Skip to content

Commit 05255d0

Browse files
Checks: Added new MISRA12_13.2: The value of an expression and its persistent side effects shall be the same under all permitted evaluation orders [autosync]
1 parent 300ea6b commit 05255d0

4 files changed

Lines changed: 270 additions & 144 deletions

File tree

CodeCheck/Published Standards/MISRA C 2012/MISRA12_13.2/test.c

Lines changed: 136 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ void modified_twice(void)
2626
int i = 0;
2727
int j = 0;
2828
int x = 0;
29+
int a[10];
30+
int b[10];
2931

3032
j = i++ + i++; /* UndCC_Violation - i modified twice */
3133
j = ++i + i++; /* UndCC_Violation - i modified twice */
@@ -34,9 +36,13 @@ void modified_twice(void)
3436
x = x = 0; /* UndCC_Violation - x modified twice (Note 2) */
3537
i = ++i; /* UndCC_Violation - i modified twice */
3638

39+
a[i++] = b[i++]; /* UndCC_Violation - i modified twice (MISRA standard example: COPY_ELEMENT(i++)) */
40+
3741
use(i);
3842
use(j);
3943
use(x);
44+
use(a[0]);
45+
use(b[0]);
4046
}
4147

4248
/* ===== Subrule 3: modified and read elsewhere ===== */
@@ -81,6 +87,7 @@ void isolated_inc_dec(void)
8187
{
8288
int x = 0;
8389
int *p = &x;
90+
int *q = &x;
8491
int a[10];
8592
int i = 0;
8693

@@ -93,10 +100,13 @@ void isolated_inc_dec(void)
93100
use(a[i++]); /* UndCC_Valid */
94101

95102
(*p)++; /* UndCC_Valid - p not modified, *p is not a VarDecl mod */
96-
*p++; /* UndCC_Valid - p modified once via post-inc */
103+
*p++; /* UndCC_Valid - p's read contributes to its own value computation */
104+
105+
*p++ = *q++; /* UndCC_Valid - p and q each modified once, no other access */
97106

98107
use(x);
99108
use(*p);
109+
use(*q);
100110
}
101111

102112
/* ===== Sequence points break unsequenced regions ===== */
@@ -188,3 +198,128 @@ void sizeof_unevaluated(void)
188198

189199
use(j);
190200
}
201+
202+
/* ===== Multiple reads of the same variable - no modification ===== */
203+
204+
void multiple_reads(void)
205+
{
206+
int i = 0;
207+
int j = 0;
208+
209+
f(i, i); /* UndCC_Valid - i read twice, no mod */
210+
j = i + i; /* UndCC_Valid - i read twice */
211+
j = i * i + i; /* UndCC_Valid */
212+
213+
use(j);
214+
}
215+
216+
/* ===== Adjacent statements are independent full expressions ===== */
217+
218+
void adjacent_statements(void)
219+
{
220+
int i = 0;
221+
int j = 0;
222+
223+
i++; i++; /* UndCC_Valid - each is its own full expression */
224+
j = i++; j = i++; /* UndCC_Valid */
225+
226+
use(i);
227+
use(j);
228+
}
229+
230+
/* ===== Comma operator separates same-variable modifications ===== */
231+
232+
void comma_separates_mods(void)
233+
{
234+
int i = 0;
235+
int j = 0;
236+
237+
(void)(i++, i++); /* UndCC_Valid - comma is a sequence point */
238+
j = (i++, i); /* UndCC_Valid - covered in sequence_points_split also */
239+
(void)(i = 0, i = 1); /* UndCC_Valid - two assignments separated by comma */
240+
241+
use(i);
242+
use(j);
243+
}
244+
245+
/* ===== Multi-declarator initializers are independent full expressions ===== */
246+
247+
void multi_declarator_inits(void)
248+
{
249+
int i = 0;
250+
251+
/* Each declarator's initializer is a separate full expression. */
252+
int x = i++, y = i++; /* UndCC_Valid - two separate full expressions */
253+
int p = i, q = i; /* UndCC_Valid */
254+
255+
use(x);
256+
use(y);
257+
use(p);
258+
use(q);
259+
}
260+
261+
/* ===== Unbraced control-flow bodies are still full expressions ===== */
262+
263+
void unbraced_bodies(int cond)
264+
{
265+
int i = 0;
266+
int j = 0;
267+
int a[10];
268+
269+
if (cond) i = i++; /* UndCC_Violation - i modified twice */
270+
if (cond) a[i] = i++; /* UndCC_Violation - i modified and read */
271+
else j = i++ + i++; /* UndCC_Violation - i modified twice */
272+
273+
while (cond) a[i] = i++; /* UndCC_Violation */
274+
275+
do j = i + i++; while (0); /* UndCC_Violation - i modified and read */
276+
277+
for (int k = 0; k < 1; ++k) j = i++ * i; /* UndCC_Violation - body */
278+
279+
/* Compliant unbraced bodies should still be quiet */
280+
if (cond) i++; /* UndCC_Valid */
281+
while (cond) i = i + 1; /* UndCC_Valid */
282+
for (int k = 0; k < 1; ++k) i = i + 1; /* UndCC_Valid */
283+
284+
use(i);
285+
use(j);
286+
use(a[0]);
287+
}
288+
289+
/* ===== Switch case bodies ===== */
290+
291+
void switch_case_bodies(int x)
292+
{
293+
int i = 0;
294+
int j = 0;
295+
296+
switch (x) {
297+
case 0:
298+
j = i++ + i++; /* UndCC_Violation - i modified twice */
299+
break;
300+
case 1:
301+
i++; /* UndCC_Valid */
302+
break;
303+
default:
304+
j = i++ * i; /* UndCC_Violation - i modified and read */
305+
break;
306+
}
307+
308+
use(i);
309+
use(j);
310+
}
311+
312+
/* ===== Labelled statements ===== */
313+
314+
void labelled_statements(int cond)
315+
{
316+
int i = 0;
317+
int j = 0;
318+
319+
if (!cond) goto end;
320+
j = i + i++; /* UndCC_Violation - i modified and read */
321+
322+
end:
323+
j = i++; /* UndCC_Valid - single modification */
324+
use(j);
325+
}

CodeCheck/clang/checks.json

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2706,6 +2706,37 @@
27062706
]
27072707
}
27082708
},
2709+
"CPP_E091": {
2710+
"tags": ["Language: C", "Expressions"],
2711+
"key": "sti.SequencePointSideEffects",
2712+
"test": "MISRA12_13.2",
2713+
"name": "All Checks/Language Specific/C and C++/Expressions/The value of an expression and its persistent side effects shall be the same under all permitted evaluation orders",
2714+
"desc": {
2715+
"html": [
2716+
"<p><b>Rationale</b></p>",
2717+
"<p>The C Standard gives compilers considerable flexibility when evaluating expressions. Most operators may have their operands evaluated in any order; only <code>&amp;&amp;</code>, <code>||</code>, <code>?:</code>, and <code>,</code> introduce sequence points between operands. An object that is modified more than once between adjacent sequence points, or modified and read where the read does not contribute to computing the new value, has unspecified or undefined behaviour.</p>",
2718+
"<p><b>Scope</b></p>",
2719+
"<p>Each full expression (statement-level expression, condition, initializer, return value) is analysed and split on sequence-point operators into independent sub-regions. Within each region, plain variable accesses are classified as modifications (assignment LHS, compound-assignment LHS, <code>++</code> / <code>--</code> operand) or reads.</p>",
2720+
"<p><b>Implementation</b></p>",
2721+
"<p>A variable is flagged when:</p>",
2722+
"<ul>",
2723+
" <li>It is modified more than once in a region &mdash; e.g. <code>i++ + i++</code>, <code>x = x = 0</code>.</li>",
2724+
" <li>It is modified once and also read where the read is not part of computing the new value &mdash; e.g. <code>a[i] = i++</code>, <code>f(i, i++)</code>.</li>",
2725+
"</ul>",
2726+
"<p>Reads inside the right-hand side of an assignment or compound assignment to the same variable (e.g. <code>x = x + 1</code>, <code>x += y</code>) contribute to the value and are not flagged. <i>volatile</i> and atomic constraints (MISRA subrules 4&ndash;6) and indirect access via pointers or function calls are not analysed; modifications targeting non-variable expressions (members, array elements, dereferences) are not tracked.</p>",
2727+
"<p><b>Example</b></p>",
2728+
"<pre><code language=\"C\">i = i++; /* Non-compliant - i modified twice */",
2729+
"x = x = 0; /* Non-compliant - x modified twice */",
2730+
"a[i] = i++; /* Non-compliant - i modified and read */",
2731+
"f(i, i++); /* Non-compliant - i modified and read */",
2732+
"",
2733+
"x = x + 1; /* Compliant - read of x contributes to new value */",
2734+
"x += y; /* Compliant */",
2735+
"x++; /* Compliant */",
2736+
"if (a &amp;&amp; b++) {} /* Compliant - &amp;&amp; is a sequence point */</code></pre>"
2737+
]
2738+
}
2739+
},
27092740
"CPP_F071": {
27102741
"tags": ["Language: C++", "Functions"],
27112742
"key": "sti.SpecialMemberFunctions",

CodeCheck/clang/misra.json

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4031,5 +4031,108 @@
40314031
"<p>Rule 2.1, Rule 14.2</p>"
40324032
]
40334033
}
4034+
},
4035+
4036+
"MISRA12_13.2": {
4037+
"tags": ["Language: C", "Standard: MISRA C 2012", "Category: Required", "Expressions"],
4038+
"key": "sti.SequencePointSideEffects",
4039+
"test": "MISRA12_13.2",
4040+
"name": "Published Standards/MISRA C 2012/13.2 The value of an expression and its persistent side effects shall be the same under all permitted evaluation orders",
4041+
"desc": {
4042+
"html": [
4043+
"<p><b>Amplification</b></p>",
4044+
"<p>Between any two adjacent sequence points:</p>",
4045+
"<ol>",
4046+
" <li>No object shall be modified more than once;</li>",
4047+
" <li>All parts of the expression are considered when determining whether an object is read or modified, irrespective of any known values.</li>",
4048+
" <li>No object shall be both modified and read unless any such read of the object's value contributes towards computing the value to be stored into the object;</li>",
4049+
" <li>There shall be no more than one modification access with <i>volatile</i>-qualified or atomic type;</li>",
4050+
" <li>There shall be no more than one read access with <i>volatile</i>-qualified type;</li>",
4051+
" <li>There shall be no more than one read access to an object with atomic type.</li>",
4052+
"</ol>",
4053+
"<p><i>Note 1:</i> An object might be accessed indirectly, by means of a pointer or a called function, as well as being accessed directly by the expression.</p>",
4054+
"<p><i>Note 2:</i> This Amplification is intentionally stricter than the headline of the rule. As a result, expressions such as <code>x = x = 0;</code> are not permitted by this rule even though the value and the <i>persistent side effects</i>, provided that x is not <i>volatile</i>, are independent of the order of evaluation or <i>side effects</i>.</p>",
4055+
"<p><b>Rationale</b></p>",
4056+
"<p>The C Standard gives considerable flexibility to compilers when evaluating expressions. Most operators can have their operands evaluated in any order. The main exceptions are the logical AND, logical OR, conditional and comma operators, which act as sequence points between their operands.</p>",
4057+
"<p>Many of the common instances of unpredictable behaviour, associated with expression evaluation, can be avoided by following the advice given by this rule. However, in order to simplify this rule, it does restrict some forms which are well-defined.</p>",
4058+
"<p><b>Example</b></p>",
4059+
"<p>When the <code>COPY_ELEMENT</code> macro is invoked in this non-compliant example, <code>i</code> is read twice and modified twice. It is unspecified whether the order of operations on <code>i</code> is read-modify-read-modify or read-read-modify-modify.</p>",
4060+
"<pre><code language=\"C\">#define COPY_ELEMENT( index ) ( a[( index )] = b[( index )] )",
4061+
"",
4062+
"COPY_ELEMENT ( i++ );</code></pre>",
4063+
"<p>The order of evaluation of function arguments is unspecified, as is the order in which <i>side effects</i> occur, as shown in this non-compliant example.</p>",
4064+
"<pre><code language=\"C\">uint16_t i = 0;",
4065+
"",
4066+
"/*",
4067+
" * Unspecified whether this call is equivalent to:",
4068+
" * f ( 0, 0 )",
4069+
" * or f ( 0, 1 )",
4070+
" */",
4071+
"f ( i++, i );</code></pre>",
4072+
"<p><b>Implementation</b></p>",
4073+
"<p>This is a conservative implementation of MISRA's \"Undecidable, System\" rule. It analyses each full expression and splits it on sequence-point operators (<code>&amp;&amp;</code>, <code>||</code>, <code>?:</code>, <code>,</code>) into independent sub-regions. Within each region, plain variable accesses are classified as modifications (assignment LHS, compound-assignment LHS, <code>++</code> / <code>--</code> operand) or reads. A variable is flagged when:</p>",
4074+
"<ul>",
4075+
" <li>It is modified more than once (subrule 1) &mdash; e.g. <code>i++ + i++</code>, <code>x = x = 0</code>.</li>",
4076+
" <li>It is modified once and also read where the read is not part of computing the new value (subrule 3) &mdash; e.g. <code>a[i] = i++</code>, <code>f(i, i++)</code>.</li>",
4077+
"</ul>",
4078+
"<p>Subrules 4&ndash;6 (additional <i>volatile</i> and atomic constraints) and indirect access via pointers or function calls (Note 1) are not analysed. Modifications targeting expressions that are not plain variable references (members, array elements, dereferences) are not tracked.</p>",
4079+
"<p><b>See also</b></p>",
4080+
"<p>Dir 4.9, Rule 13.1, Rule 13.3, Rule 13.4</p>"
4081+
]
4082+
}
4083+
},
4084+
4085+
"MISRA23_13.2": {
4086+
"tags": ["Language: C", "Standard: MISRA C 2023", "Category: Required", "Expressions"],
4087+
"key": "sti.SequencePointSideEffects",
4088+
"test": "MISRA12_13.2",
4089+
"name": "Published Standards/MISRA C 2023/13.2 The value of an expression and its persistent side effects shall be the same under all permitted evaluation orders",
4090+
"desc": {
4091+
"html": [
4092+
"<p><b>Amplification</b></p>",
4093+
"<p>Between any two adjacent sequence points:</p>",
4094+
"<ol>",
4095+
" <li>No object shall be modified more than once;</li>",
4096+
" <li>All parts of the expression are considered when determining whether an object is read or modified, irrespective of any known values.</li>",
4097+
" <li>No object shall be both modified and read unless any such read of the object's value contributes towards computing the value to be stored into the object;</li>",
4098+
" <li>There shall be no more than one modification access with <i>volatile</i>-qualified or atomic type;</li>",
4099+
" <li>There shall be no more than one read access with <i>volatile</i>-qualified type;</li>",
4100+
" <li>There shall be no more than one read access to an object with atomic type.</li>",
4101+
"</ol>",
4102+
"<p><i>Note 1:</i> An object might be accessed indirectly, by means of a pointer or a called function, as well as being accessed directly by the expression.</p>",
4103+
"<p><i>Note 2:</i> This Amplification is intentionally stricter than the headline of the rule. As a result, expressions such as <code>x = x = 0;</code> are not permitted by this rule even though the value and the <i>persistent side effects</i>, provided that x is not <i>volatile</i>, are independent of the order of evaluation or <i>side effects</i>.</p>",
4104+
"<p><b>Implementation</b></p>",
4105+
"<p>Conservative subset: see MISRA C 2012 Rule 13.2 entry for details.</p>",
4106+
"<p><b>See also</b></p>",
4107+
"<p>Dir 4.9, Rule 13.1, Rule 13.3, Rule 13.4</p>"
4108+
]
4109+
}
4110+
},
4111+
4112+
"MISRA25_13.2": {
4113+
"tags": ["Language: C", "Standard: MISRA C 2025", "Category: Required", "Expressions"],
4114+
"key": "sti.SequencePointSideEffects",
4115+
"test": "MISRA12_13.2",
4116+
"name": "Published Standards/MISRA C 2025/13.2 The value of an expression and its persistent side effects shall be the same under all permitted evaluation orders and shall be independent from thread interleaving",
4117+
"desc": {
4118+
"html": [
4119+
"<p><b>Amplification</b></p>",
4120+
"<p>Between any two adjacent sequence points:</p>",
4121+
"<ol>",
4122+
" <li>No object shall be modified more than once;</li>",
4123+
" <li>All parts of the expression are considered when determining whether an object is read or modified, irrespective of any known values.</li>",
4124+
" <li>No object shall be both modified and read unless any such read of the object's value contributes towards computing the value to be stored into the object;</li>",
4125+
" <li>There shall be no more than one modification access with <i>volatile</i>-qualified or atomic type;</li>",
4126+
" <li>There shall be no more than one read access with <i>volatile</i>-qualified type;</li>",
4127+
" <li>There shall be no more than one read access to an object with atomic type.</li>",
4128+
"</ol>",
4129+
"<p><i>Note 1:</i> An object might be accessed indirectly, by means of a pointer or a called function, as well as being accessed directly by the expression.</p>",
4130+
"<p><i>Note 2:</i> This Amplification is intentionally stricter than the headline of the rule. As a result, expressions such as <code>x = x = 0;</code> are not permitted by this rule even though the value and the <i>persistent side effects</i>, provided that x is not <i>volatile</i>, are independent of the order of evaluation or <i>side effects</i>.</p>",
4131+
"<p><b>Implementation</b></p>",
4132+
"<p>Conservative subset: see MISRA C 2012 Rule 13.2 entry for details. The thread-interleaving aspect of the 2025 rule (subrules 4&ndash;6 covering volatile and atomic types) is not analysed.</p>",
4133+
"<p><b>See also</b></p>",
4134+
"<p>Dir 4.9, Rule 13.1, Rule 13.3, Rule 13.4</p>"
4135+
]
4136+
}
40344137
}
40354138
}

0 commit comments

Comments
 (0)