@@ -37,13 +37,14 @@ predicate isForLoopWithFloatingPointCounters(ForStmt forLoop, Variable v) {
3737 * Holds if for loop `forLoop` contains an invalid for loop incrementation.
3838 * M6-5-2
3939 */
40- predicate isInvalidForLoopIncrementation ( ForStmt forLoop , LoopControlVariable v ) {
41- v .getAnAccess ( ) = forLoop .getCondition ( ) .getAChild * ( ) and
42- exists ( VariableAccess va |
43- va = v .getAnAccess ( ) and
44- va = forLoop .getUpdate ( ) .getAChild * ( ) and
45- not exists ( CrementOperation cop | cop .getOperand ( ) = va ) and
46- not exists ( Call c | c .getQualifier ( ) = va and c .getTarget ( ) instanceof UserCrementOperator )
40+ predicate isInvalidForLoopIncrementation ( ForStmt forLoop , Variable v , VariableAccess modification ) {
41+ v = getAnIterationVariable ( forLoop ) and
42+ modification = v .getAnAccess ( ) and
43+ modification = forLoop .getUpdate ( ) .getAChild * ( ) and
44+ modification .isModified ( ) and
45+ not exists ( CrementOperation cop | cop .getOperand ( ) = modification ) and
46+ not exists ( Call c |
47+ c .getQualifier ( ) = modification and c .getTarget ( ) instanceof UserCrementOperator
4748 ) and
4849 exists ( VariableAccess va | va = forLoop .getCondition ( ) .getAChild * ( ) and va = v .getAnAccess ( ) |
4950 exists ( EqualityOperation eop | eop .getAnOperand ( ) = va )
@@ -163,26 +164,72 @@ predicate isLoopControlVarModifiedInLoopExpr(
163164predicate isNonBoolLoopControlVar (
164165 ForStmt forLoop , LoopControlVariable loopControlVariable , VariableAccess loopControlVariableAccess
165166) {
166- // get a loop control variable that is not a loop counter
167- loopControlVariableAccess = loopControlVariable .getVariableAccessInLoop ( forLoop ) and
168- not loopControlVariable = getAnIterationVariable ( forLoop ) and
169- loopControlVariableAccess .getEnclosingStmt ( ) = forLoop .getStmt ( ) .getAChild * ( ) and
170- // filter only loop control variables that are modified
171- (
172- loopControlVariableAccess .isModified ( ) or
173- loopControlVariableAccess .isAddressOfAccess ( )
174- ) and
175- // check if the variable type is anything but bool
176- not loopControlVariable .getType ( ) instanceof BoolType
167+ exists ( Variable loopCounter , ComparisonOperation terminationCheck |
168+ loopCounter = getAnIterationVariable ( forLoop ) and
169+ forLoop .getCondition ( ) = terminationCheck .getParent * ( )
170+ |
171+ // get a loop control variable that is not a loop counter
172+ loopControlVariableAccess = loopControlVariable .getVariableAccessInLoop ( forLoop ) and
173+ not loopControlVariable = getAnIterationVariable ( forLoop ) and
174+ // filter only loop control variables that are modified
175+ (
176+ loopControlVariableAccess .isModified ( ) or
177+ loopControlVariableAccess .isAddressOfAccess ( )
178+ ) and
179+ // check if the variable type is anything but bool
180+ not loopControlVariable .getType ( ) instanceof BoolType and
181+ // check if the control variable is part of the termination check, but is not compared to the loop counter
182+ terminationCheck .getAnOperand ( ) = loopControlVariable .getAnAccess ( ) .getParent * ( ) and
183+ not terminationCheck .getAnOperand ( ) = loopCounter .getAnAccess ( ) .getParent * ( )
184+ )
177185}
178186
179- predicate isInvalidLoop ( ForStmt forLoop ) {
180- isInvalidForLoopIncrementation ( forLoop , _) or
181- isForLoopWithMulipleCounters ( forLoop ) or
182- isForLoopWithFloatingPointCounters ( forLoop , _) or
183- isLoopCounterModifiedInCondition ( forLoop , _) or
184- isLoopCounterModifiedInStatement ( forLoop , _, _) or
185- isIrregularLoopCounterModification ( forLoop , _, _) or
186- isLoopControlVarModifiedInLoopExpr ( forLoop , _, _) or
187- isNonBoolLoopControlVar ( forLoop , _, _)
187+ predicate isInvalidLoop ( ForStmt forLoop ) { isInvalidLoop ( forLoop , _, _, _) }
188+
189+ predicate isInvalidLoop ( ForStmt forLoop , string reason , Locatable reasonLocation , string reasonLabel ) {
190+ exists ( Variable loopCounter |
191+ isInvalidForLoopIncrementation ( forLoop , loopCounter , reasonLocation ) and
192+ reason =
193+ "it $@ its loop counter '" + loopCounter .getName ( ) +
194+ "' with an operation that is not an increment or decrement" and
195+ reasonLabel = "updates"
196+ )
197+ or
198+ isForLoopWithMulipleCounters ( forLoop ) and
199+ reason = "it uses multiple loop counters$@" and
200+ reasonLabel = "" and
201+ reasonLocation .getLocation ( ) instanceof UnknownExprLocation
202+ or
203+ isForLoopWithFloatingPointCounters ( forLoop , reasonLocation ) and
204+ reason = "it uses a loop counter '$@' of type floating-point" and
205+ reasonLabel = reasonLocation .( Variable ) .getName ( )
206+ or
207+ isLoopCounterModifiedInCondition ( forLoop , reasonLocation ) and
208+ reason =
209+ "it $@ the loop counter '" + reasonLocation .( VariableAccess ) .getTarget ( ) .getName ( ) +
210+ "' in the condition" and
211+ reasonLabel = "updates"
212+ or
213+ exists ( Variable loopCounter |
214+ isLoopCounterModifiedInStatement ( forLoop , loopCounter , reasonLocation ) and
215+ reason = "it $@ the loop counter '" + loopCounter .getName ( ) + "' in the body of the loop" and
216+ reasonLabel = "updates"
217+ )
218+ or
219+ exists ( Variable loopCounter |
220+ isIrregularLoopCounterModification ( forLoop , loopCounter , reasonLocation ) and
221+ reason = "it $@ the loop counter '" + loopCounter .getName ( ) + "' irregularly" and
222+ reasonLabel = "updates"
223+ )
224+ or
225+ exists ( Variable loopControlVariable |
226+ isLoopControlVarModifiedInLoopExpr ( forLoop , loopControlVariable , reasonLocation ) and
227+ reason =
228+ "it updates $@, a loop control variable other than the loop counter, in the update expression of the loop" and
229+ reasonLabel = loopControlVariable .getName ( )
230+ )
231+ or
232+ isNonBoolLoopControlVar ( forLoop , reasonLocation , _) and
233+ reason = "its $@ is not a boolean" and
234+ reasonLabel = "loop control variable"
188235}
0 commit comments