Skip to content

Commit b586e45

Browse files
authored
Merge pull request #425 from github/lcartey/m6-5-5-loop-modification
`M6-5-5`: Improve detection of modification by reference
2 parents 5e6a5b8 + d135c26 commit b586e45

File tree

4 files changed

+46
-2
lines changed

4 files changed

+46
-2
lines changed
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
- `M6-5-5`:
2+
- Reduce false positives by no longer considering the taking of a const reference as a modification.
3+
- Improve detection of non-local modification of loop iteration variables to reduce false positives.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
| test.cpp:24:8:24:15 | testFlag | Loop control variable testFlag is modified in the loop update expression. |
2+
| test.cpp:47:12:47:12 | y | Loop control variable y is modified in the loop update expression. |

cpp/autosar/test/rules/M6-5-5/test.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,3 +24,27 @@ void test_loop_control_variable_modified_in_expression() {
2424
testFlag = updateFlagWithIncrement(++x)) { // NON_COMPLIANT
2525
}
2626
}
27+
28+
#include <vector>
29+
30+
void test_const_refs(std::vector<int> v) {
31+
std::vector<int>::iterator first = v.begin();
32+
std::vector<int>::iterator last = v.end();
33+
// call to operator!= passes a const reference to first
34+
for (; first != last; first++) { // COMPLIANT
35+
}
36+
}
37+
38+
void update(std::vector<int>::iterator &f, const int &x, int &y) {}
39+
40+
void test_const_refs_update(std::vector<int> v) {
41+
std::vector<int>::iterator last = v.end();
42+
int x = 0;
43+
int y = 0;
44+
// call to operator!= passes a const reference to first
45+
for (std::vector<int>::iterator first = v.begin(); first != last; update(
46+
first, x, // COMPLIANT - first is a loop counter, so can be modified
47+
y)) { // NON_COMPLIANT - y is modified and is not a loop counter
48+
first + 1;
49+
}
50+
}

cpp/common/src/codingstandards/cpp/Loops.qll

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,13 @@ class MemberAssignmentOperation extends FunctionCall {
7070
*/
7171
pragma[noopt]
7272
Variable getALoopCounter(ForStmt fs) {
73+
// ------------------------------------------------------------------------------------------------
74+
// NOTE: This is an updated version of ForStmt.getAnIterationVariable(), handling additional cases.
75+
// The use of pragma[noopt] is retained from the original code, as we haven't determined
76+
// whether it's still necessary across a broad range of databases. As a noopt predicate, it
77+
// includes a degree of duplication as the join order is defined based on the order of the
78+
// conditions.
79+
// ------------------------------------------------------------------------------------------------
7380
// check that it is assigned to, incremented or decremented in the update
7481
exists(Expr updateOpRoot, Expr updateOp |
7582
updateOpRoot = fs.getUpdate() and
@@ -106,6 +113,15 @@ Variable getALoopCounter(ForStmt fs) {
106113
)
107114
or
108115
updateOp = result.getAnAssignedValue()
116+
or
117+
// updateOp is an access whose address is taken in a non-const way
118+
exists(FunctionCall fc, VariableAccess va |
119+
fc = updateOp and
120+
fc instanceof FunctionCall and
121+
fc.getAnArgument() = va and
122+
va = result.getAnAccess() and
123+
va.isAddressOfAccessNonConst()
124+
)
109125
) and
110126
result instanceof Variable and
111127
// checked or used in the condition
@@ -260,7 +276,7 @@ predicate isLoopControlVarModifiedInLoopCondition(
260276
loopControlVariableAccess = forLoop.getCondition().getAChild+() and
261277
(
262278
loopControlVariableAccess.isModified() or
263-
loopControlVariableAccess.isAddressOfAccess()
279+
loopControlVariableAccess.isAddressOfAccessNonConst()
264280
)
265281
}
266282

@@ -277,7 +293,7 @@ predicate isLoopControlVarModifiedInLoopExpr(
277293
loopControlVariableAccess = forLoop.getUpdate().getAChild() and
278294
(
279295
loopControlVariableAccess.isModified() or
280-
loopControlVariableAccess.isAddressOfAccess()
296+
loopControlVariableAccess.isAddressOfAccessNonConst()
281297
)
282298
}
283299

0 commit comments

Comments
 (0)