@@ -24,6 +24,9 @@ import codingstandards.cpp.misra
2424 * compared to a value, which is supposed to be the loop bound.
2525 */
2626class LegacyForLoopCondition extends RelationalOperation {
27+ /**
28+ * The legacy for-loop this relational operation is a condition of.
29+ */
2730 ForStmt forLoop ;
2831 VariableAccess loopCounter ;
2932 Expr loopBound ;
@@ -35,8 +38,14 @@ class LegacyForLoopCondition extends RelationalOperation {
3538 loopBound != loopCounter
3639 }
3740
41+ /**
42+ * Gets the variable access to the loop counter variable, embedded in this loop condition.
43+ */
3844 VariableAccess getLoopCounter ( ) { result = loopCounter }
3945
46+ /**
47+ * Gets the variable access to the loop bound variable, embedded in this loop condition.
48+ */
4049 Expr getLoopBound ( ) { result = loopBound }
4150}
4251
@@ -69,17 +78,16 @@ Expr getLoopStepOfForStmt(ForStmt forLoop) {
6978}
7079
7180/**
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 .
7483 */
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 ( )
7886}
7987
8088/**
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.
8391 *
8492 * e.g.1. The loop counter variable `i` in the body is taken its address in the
8593 * declaration of a pointer variable `m`.
@@ -115,22 +123,26 @@ predicate variableAddressTakenInNonConstDeclaration(
115123}
116124
117125/**
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
119127 * as an argument of a call in either the body of the for-loop or in its update
120128 * expression.
121129 *
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 `.
124132 * ``` C++
133+ * void g1(int *x);
134+ *
125135 * for (int i = 0; i < k; i += l) {
126- * g (&i);
136+ * g1 (&i);
127137 * }
128138 * ```
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 `.
131141 * ``` C++
142+ * void g1(int *x);
143+ *
132144 * for (int i = j; i < k; i += l) {
133- * g (&k);
145+ * g1 (&k);
134146 * }
135147 * ```
136148 */
@@ -140,32 +152,119 @@ private predicate variableAddressTakenAsConstArgument(
140152 exists ( AddressOfExpr addressOfExpr , int index |
141153 call .getParent + ( ) = forLoop .getAChild + ( ) and // TODO: Bad
142154 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
144159 addressOfExpr .getOperand ( ) = baseVariableAccess .getTarget ( ) .getAnAccess ( ) and
145160 baseVariableAccess .getParent + ( ) = forLoop
146161 )
147162}
148163
149164/**
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
151166 * as an argument of a complex expression in either the body of the for-loop or
152167 * in its update expression.
153168 *
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`
155179 * is taken its address in a compound expression.
156180 * ``` C++
157181 * for (int i = 0; i < k; i += l) {
158182 * *(cond ? &i : &k) += 1;
159183 * }
160184 * ```
161185 */
186+ /* TODO: Do we need to use Expr.getUnderlyingType() to ensure that the expression is non-const? */
162187predicate variableAddressTakenInExpression ( ForStmt forLoop , VariableAccess baseVariableAccess ) {
163188 exists ( AddressOfExpr addressOfExpr |
164189 baseVariableAccess .getParent + ( ) = forLoop .getAChild + ( ) and // TODO: Bad
165190 addressOfExpr .getParent + ( ) = forLoop .getAChild + ( ) and
166191 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+ )
169268}
170269
171270from ForStmt forLoop
@@ -237,34 +336,59 @@ where
237336 exists ( VariableAccess loopCounterAccessInCondition |
238337 loopCounterAccessInCondition = forLoop .getCondition ( ) .( LegacyForLoopCondition ) .getLoopCounter ( )
239338 |
240- exists ( VariableAccess loopCounterAccessTakenAddress |
241- loopCounterAccessInCondition .getTarget ( ) = loopCounterAccessTakenAddress .getTarget ( )
339+ exists ( VariableAccess loopCounterAccessTakenAddressOrReference |
340+ loopCounterAccessInCondition .getTarget ( ) =
341+ loopCounterAccessTakenAddressOrReference .getTarget ( )
242342 |
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 )
244350 or
245- variableAddressTakenInExpression ( forLoop , loopCounterAccessTakenAddress )
351+ variableReferenceTakenAsNonConstArgument ( forLoop ,
352+ loopCounterAccessTakenAddressOrReference .getTarget ( ) .getAnAccess ( ) , _)
246353 )
247354 )
248355 or
249356 /* 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+ )
251374 or
252375 /* 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+ )
254394select 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