@@ -24,6 +24,9 @@ import codingstandards.cpp.misra
24
24
* compared to a value, which is supposed to be the loop bound.
25
25
*/
26
26
class LegacyForLoopCondition extends RelationalOperation {
27
+ /**
28
+ * The legacy for-loop this relational operation is a condition of.
29
+ */
27
30
ForStmt forLoop ;
28
31
VariableAccess loopCounter ;
29
32
Expr loopBound ;
@@ -35,8 +38,14 @@ class LegacyForLoopCondition extends RelationalOperation {
35
38
loopBound != loopCounter
36
39
}
37
40
41
+ /**
42
+ * Gets the variable access to the loop counter variable, embedded in this loop condition.
43
+ */
38
44
VariableAccess getLoopCounter ( ) { result = loopCounter }
39
45
46
+ /**
47
+ * Gets the variable access to the loop bound variable, embedded in this loop condition.
48
+ */
40
49
Expr getLoopBound ( ) { result = loopBound }
41
50
}
42
51
@@ -69,17 +78,16 @@ Expr getLoopStepOfForStmt(ForStmt forLoop) {
69
78
}
70
79
71
80
/**
72
- * Holds if the given function has as parameter at a given index a pointer to a
73
- * constant value or a reference of a constant value .
81
+ * Holds if the given function has as parameter a pointer to a constant
82
+ * value, at a given index .
74
83
*/
75
- private predicate functionHasConstPointerOrReferenceParameter ( Function function , int index ) {
76
- function .getParameter ( index ) .getType ( ) .( PointerType ) .getBaseType ( ) .isConst ( ) or
77
- function .getParameter ( index ) .getType ( ) .( ReferenceType ) .getBaseType ( ) .isConst ( )
84
+ private predicate functionHasConstPointerParameter ( Function function , int index ) {
85
+ function .getParameter ( index ) .getType ( ) .( PointerType ) .getBaseType ( ) .isConst ( )
78
86
}
79
87
80
88
/**
81
- * Holds if the the variable behind a given variable access is taken its address
82
- * in a non-const variable declaration, in the body of the for-loop.
89
+ * Holds if the variable behind a given variable access is taken its address in
90
+ * a non-const variable declaration, in the body of the for-loop.
83
91
*
84
92
* e.g.1. The loop counter variable `i` in the body is taken its address in the
85
93
* declaration of a pointer variable `m`.
@@ -115,22 +123,26 @@ predicate variableAddressTakenInNonConstDeclaration(
115
123
}
116
124
117
125
/**
118
- * Holds if the the variable behind a given variable access is taken its address
126
+ * Holds if the variable behind a given variable access is taken its address
119
127
* as an argument of a call in either the body of the for-loop or in its update
120
128
* expression.
121
129
*
122
- * e.g.1. The loop counter variable `i` in the body is taken its address in the
123
- * declaration of a pointer variable `m `.
130
+ * e.g.1. The address of the loop counter variable `i` is passed as argument
131
+ * to the call to `g `.
124
132
* ``` C++
133
+ * void g1(int *x);
134
+ *
125
135
* for (int i = 0; i < k; i += l) {
126
- * g (&i);
136
+ * g1 (&i);
127
137
* }
128
138
* ```
129
- * e.g.2. The loop bound variable `k` in the body is taken its address in the
130
- * declaration of a pointer variable `m `.
139
+ * e.g.2. The address of the loop counter variable `k` is passed as argument
140
+ * to the call to `g `.
131
141
* ``` C++
142
+ * void g1(int *x);
143
+ *
132
144
* for (int i = j; i < k; i += l) {
133
- * g (&k);
145
+ * g1 (&k);
134
146
* }
135
147
* ```
136
148
*/
@@ -140,32 +152,119 @@ private predicate variableAddressTakenAsConstArgument(
140
152
exists ( AddressOfExpr addressOfExpr , int index |
141
153
call .getParent + ( ) = forLoop .getAChild + ( ) and // TODO: Bad
142
154
call .getArgument ( index ) .getAChild * ( ) = addressOfExpr and
143
- functionHasConstPointerOrReferenceParameter ( call .getTarget ( ) , index ) and
155
+ exists ( PointerType parameterType |
156
+ parameterType = call .getTarget ( ) .getParameter ( index ) .getType ( ) and
157
+ not parameterType .getBaseType ( ) .isConst ( )
158
+ ) and
144
159
addressOfExpr .getOperand ( ) = baseVariableAccess .getTarget ( ) .getAnAccess ( ) and
145
160
baseVariableAccess .getParent + ( ) = forLoop
146
161
)
147
162
}
148
163
149
164
/**
150
- * Holds if the the variable behind a given variable access is taken its address
165
+ * Holds if the variable behind a given variable access is taken its address
151
166
* as an argument of a complex expression in either the body of the for-loop or
152
167
* in its update expression.
153
168
*
154
- * e.g. The loop counter variable `i` in the body and the loop bound variable `k`
169
+ * e.g.1. The loop counter variable `i` in the body and the loop bound variable `k`
170
+ * is taken its address in a call.
171
+ * ``` C++
172
+ * void g1(int *x);
173
+ *
174
+ * for (int i = j; i < k; i += l) {
175
+ * g1(&i);
176
+ * }
177
+ * ```
178
+ * e.g.2. The loop counter variable `i` in the body and the loop bound variable `k`
155
179
* is taken its address in a compound expression.
156
180
* ``` C++
157
181
* for (int i = 0; i < k; i += l) {
158
182
* *(cond ? &i : &k) += 1;
159
183
* }
160
184
* ```
161
185
*/
186
+ /* TODO: Do we need to use Expr.getUnderlyingType() to ensure that the expression is non-const? */
162
187
predicate variableAddressTakenInExpression ( ForStmt forLoop , VariableAccess baseVariableAccess ) {
163
188
exists ( AddressOfExpr addressOfExpr |
164
189
baseVariableAccess .getParent + ( ) = forLoop .getAChild + ( ) and // TODO: Bad
165
190
addressOfExpr .getParent + ( ) = forLoop .getAChild + ( ) and
166
191
addressOfExpr .getOperand ( ) = baseVariableAccess .getTarget ( ) .getAnAccess ( )
167
- ) and
168
- not variableAddressTakenAsConstArgument ( forLoop , baseVariableAccess .getTarget ( ) .getAnAccess ( ) , _)
192
+ )
193
+ }
194
+
195
+ /**
196
+ * Holds if the variable behind a given variable access is taken its reference
197
+ * in a non-const variable declaration, in the body of the for-loop.
198
+ *
199
+ * e.g.1. The loop counter variable `i` in the body is taken its reference in
200
+ * the declaration of a variable `m`.
201
+ * ``` C++
202
+ * for (int i = j; i < k; i += l) {
203
+ * int &m = i;
204
+ * }
205
+ * ```
206
+ * e.g.2. The loop bound variable `k` in the body is taken its reference in the
207
+ * declaration of a variable `m`.
208
+ * ``` C++
209
+ * for (int i = j; i < k; i += l) {
210
+ * int &m = k;
211
+ * }
212
+ * ```
213
+ */
214
+ predicate variableReferenceTakenInNonConstDeclaration (
215
+ ForStmt forLoop , VariableAccess baseVariableAccess
216
+ ) {
217
+ exists ( DeclStmt decl , Variable definedVariable , ReferenceType definedVariableType |
218
+ decl .getParentStmt + ( ) = forLoop and
219
+ not decl = forLoop .getInitialization ( ) and // Exclude the for-loop counter initialization.
220
+ definedVariable = decl .getADeclarationEntry ( ) .( VariableDeclarationEntry ) .getVariable ( ) and
221
+ definedVariable .getInitializer ( ) .getExpr ( ) = baseVariableAccess and
222
+ definedVariableType = definedVariable .getType ( ) and
223
+ not definedVariableType .getBaseType ( ) .isConst ( )
224
+ )
225
+ }
226
+
227
+ /**
228
+ * Holds if the variable behind a given variable access is taken its reference
229
+ * as an argument of a call in either the body of the for-loop or in its update
230
+ * expression.
231
+ *
232
+ * e.g.1. The loop counter variable `i` in the body is passed by reference to the
233
+ * call to `f1`.
234
+ * ``` C++
235
+ * void f1(int &x);
236
+ *
237
+ * for (int i = j; i < k; i += l) {
238
+ * f1(i);
239
+ * }
240
+ * ```
241
+ * e.g.2. The loop bound variable `k` in the body is passed by reference to the
242
+ * call to `f1`.
243
+ * ``` C++
244
+ * void f1(int &x);
245
+ *
246
+ * for (int i = j; i < k; i += l) {
247
+ * f1(k);
248
+ * }
249
+ * ```
250
+ */
251
+ private predicate variableReferenceTakenAsNonConstArgument (
252
+ ForStmt forLoop , VariableAccess baseVariableAccess , Call call
253
+ ) {
254
+ exists ( int index |
255
+ call .getParent + ( ) = forLoop .getAChild + ( ) and
256
+ call .getArgument ( index ) .getAChild * ( ) = baseVariableAccess .getTarget ( ) .getAnAccess ( ) and
257
+ /*
258
+ * The given function has as parameter a reference of a constant
259
+ * value, at a given index.
260
+ */
261
+
262
+ exists ( ReferenceType parameterType |
263
+ parameterType = call .getTarget ( ) .getParameter ( index ) .getType ( ) and
264
+ not parameterType .getBaseType ( ) .isConst ( )
265
+ ) and
266
+ baseVariableAccess .getParent + ( ) = forLoop
267
+ )
169
268
}
170
269
171
270
from ForStmt forLoop
@@ -237,34 +336,59 @@ where
237
336
exists ( VariableAccess loopCounterAccessInCondition |
238
337
loopCounterAccessInCondition = forLoop .getCondition ( ) .( LegacyForLoopCondition ) .getLoopCounter ( )
239
338
|
240
- exists ( VariableAccess loopCounterAccessTakenAddress |
241
- loopCounterAccessInCondition .getTarget ( ) = loopCounterAccessTakenAddress .getTarget ( )
339
+ exists ( VariableAccess loopCounterAccessTakenAddressOrReference |
340
+ loopCounterAccessInCondition .getTarget ( ) =
341
+ loopCounterAccessTakenAddressOrReference .getTarget ( )
242
342
|
243
- variableAddressTakenInNonConstDeclaration ( forLoop , loopCounterAccessTakenAddress )
343
+ variableAddressTakenInNonConstDeclaration ( forLoop , loopCounterAccessTakenAddressOrReference )
344
+ or
345
+ variableAddressTakenInExpression ( forLoop , loopCounterAccessTakenAddressOrReference ) and
346
+ not variableAddressTakenAsConstArgument ( forLoop ,
347
+ loopCounterAccessTakenAddressOrReference .getTarget ( ) .getAnAccess ( ) , _)
348
+ or
349
+ variableReferenceTakenInNonConstDeclaration ( forLoop , loopCounterAccessTakenAddressOrReference )
244
350
or
245
- variableAddressTakenInExpression ( forLoop , loopCounterAccessTakenAddress )
351
+ variableReferenceTakenAsNonConstArgument ( forLoop ,
352
+ loopCounterAccessTakenAddressOrReference .getTarget ( ) .getAnAccess ( ) , _)
246
353
)
247
354
)
248
355
or
249
356
/* 6-2. The loop bound is taken a mutable reference or its address to a mutable pointer. */
250
- none ( )
357
+ exists ( VariableAccess loopBoundAccessInCondition |
358
+ loopBoundAccessInCondition = forLoop .getCondition ( ) .( LegacyForLoopCondition ) .getLoopBound ( )
359
+ |
360
+ exists ( VariableAccess loopBoundAccessTakenAddressOrReference |
361
+ loopBoundAccessInCondition .getTarget ( ) = loopBoundAccessTakenAddressOrReference .getTarget ( )
362
+ |
363
+ variableAddressTakenInNonConstDeclaration ( forLoop , loopBoundAccessTakenAddressOrReference )
364
+ or
365
+ variableAddressTakenInExpression ( forLoop , loopBoundAccessTakenAddressOrReference ) and
366
+ not variableAddressTakenAsConstArgument ( forLoop ,
367
+ loopBoundAccessTakenAddressOrReference .getTarget ( ) .getAnAccess ( ) , _)
368
+ or
369
+ variableReferenceTakenInNonConstDeclaration ( forLoop , loopBoundAccessTakenAddressOrReference )
370
+ or
371
+ variableReferenceTakenAsNonConstArgument ( forLoop , loopBoundAccessTakenAddressOrReference , _)
372
+ )
373
+ )
251
374
or
252
375
/* 6-3. The loop step is taken a mutable reference or its address to a mutable pointer. */
253
- none ( )
376
+ exists ( VariableAccess loopStepAccessInCondition |
377
+ loopStepAccessInCondition = getLoopStepOfForStmt ( forLoop )
378
+ |
379
+ exists ( VariableAccess loopStepAccessTakenAddressOrReference |
380
+ loopStepAccessInCondition .getTarget ( ) = loopStepAccessTakenAddressOrReference .getTarget ( )
381
+ |
382
+ variableAddressTakenInNonConstDeclaration ( forLoop , loopStepAccessTakenAddressOrReference )
383
+ or
384
+ variableAddressTakenInExpression ( forLoop , loopStepAccessTakenAddressOrReference ) and
385
+ not variableAddressTakenAsConstArgument ( forLoop ,
386
+ loopStepAccessTakenAddressOrReference .getTarget ( ) .getAnAccess ( ) , _)
387
+ or
388
+ variableReferenceTakenInNonConstDeclaration ( forLoop , loopStepAccessTakenAddressOrReference )
389
+ or
390
+ variableReferenceTakenAsNonConstArgument ( forLoop ,
391
+ loopStepAccessTakenAddressOrReference .getTarget ( ) .getAnAccess ( ) , _)
392
+ )
393
+ )
254
394
select forLoop , "TODO"
255
-
256
- private module Notebook {
257
- private predicate test ( Function function ) {
258
- function .getParameter ( _) .getType ( ) .( PointerType ) .getBaseType ( ) .isConst ( ) or
259
- function .getParameter ( _) .getType ( ) .( ReferenceType ) .getBaseType ( ) .isConst ( )
260
- }
261
-
262
- private predicate test2 ( Expr expr , string qlClasses ) {
263
- expr .getType ( ) .isConst ( ) and
264
- qlClasses = expr .getPrimaryQlClasses ( )
265
- }
266
-
267
- private predicate test3 ( Function function , string qlClasses ) {
268
- qlClasses = function .getParameter ( _) .getType ( ) .getAQlClass ( )
269
- }
270
- }
0 commit comments