rspec/rules/S1987/rule.adoc
Arseniy Zaostrovnykh 7ca29f686f Force linebreaks
2021-02-02 15:02:10 +01:00

94 lines
3.4 KiB
Plaintext

A sequence point is the still point of calm between evaluations; all the side effects of the previous operation have been calculated, and the next operation has not yet started.
There is no sequence point between the arguments to a function call, so function calls with multiple arguments that produce side effects result in undefined behavior. I.E. it's up to the compiler to pick an order in which to execute the statements, potentially resulting in unexpected runtime results.
Specifically, the use of increment and decrement operators in function calls can result in undefined behavior because there is no sequence point in the operation. Even if there were, such code would still be difficult to understand.
Similarly, passing function calls as arguments to function calls can also result in undefined behavior.
This is also true for expression where one variable is present more than once and is modified by a postfix, or prefix operator ``{plus}{plus},--``.
== Noncompliant Code Example
----
int counter;
void f(int i) {
a[i++] = i; // Noncompliant; the value that will be assigned is unspecified
int c = i + a[++i]; // Noncompliant; 'i' is evaluated more than once.
g(i++, i); // Noncompliant. What value(s) will be passed to g?
g(counterSet(), counter++); // Noncompliant; same var modified twice but order undefined
g(counterSet(); counterInc()); // Noncompliant; both fcns modify same var. Evaluation order undefined
}
void g(int i, int j) {
//...
}
void counterSet() {
counter = 0;
}
void counterInc() {
counter ++;
}
----
== Compliant Solution
----
void f(int i) {
int tmp = i+1;
int c = i + a[tmp];
a[tmp] = i;
g(tmp, i);
counterSet();
int count1 = counter;
counterInc();
int count2 = counter;
g(count1, count2);
}
void g(int i, int j) {
//...
}
void counterSet() {
counter = 0;
}
void counterInc() {
counter ++;
}
----
== See
* MISRA C:2004, 12.1 - Limited dependence should be placed on C's operator precedence rules in expressions.
* MISRA C:2004, 12.2 - The value of an expression shall be the same under any order of evaluation that the standard permits.
* MISRA {cpp}:2008, 5-0-1 - The value of an expression shall be the same under any order of evaluation that the standard permits.
* MISRA {cpp}:2008, 5-2-10 - The increment ({plus}{plus}) and decrement (--) operator should not be mixed with other operators in an expression.
* MISRA C:2012, 12.1 - The precedence of operators within expressions should be made explicit
* MISRA C:2012, 13.2 - The value of an expression and its persistent side effects shall be the same under all permitted evaluation orders
* MISRA C:2012, 13.3 - A full expression containing an increment ({plus}{plus}) or decrement (--) operator should have no other potential side effects other than that cause by the increment or decrement operator
* https://wiki.sei.cmu.edu/confluence/x/StYxBQ[CERT, EXP30-C.] - Do not depend on the order of evaluation for side effects
* https://wiki.sei.cmu.edu/confluence/x/IXw-BQ[CERT, EXP50-CPP.] - Do not depend on the order of evaluation for side effects
* https://wiki.sei.cmu.edu/confluence/x/NDdGBQ[CERT, EXP05-J.] - Do not follow a write by a subsequent write or read of the same object within an expression
* https://wiki.sei.cmu.edu/confluence/x/T9YxBQ[CERT, EXP10-C.] - Do not depend on the order of evaluation of subexpressions or the order in which side effects take place