Skip to content

Commit 2f6fc3d

Browse files
committed
Finish first draft
1 parent 9cab1f5 commit 2f6fc3d

File tree

1 file changed

+65
-58
lines changed

1 file changed

+65
-58
lines changed

cpp/misra/src/rules/RULE-9-5-1/LegacyForStatementsShouldBeSimple.ql

Lines changed: 65 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717

1818
import cpp
1919
import codingstandards.cpp.misra
20+
import codingstandards.cpp.Call
21+
import codingstandards.cpp.misra.BuiltInTypeRules::MisraCpp23BuiltInTypes
2022

2123
/**
2224
* A comparison expression that has the minimum qualification as being a valid termination
@@ -59,7 +61,7 @@ class LegacyForLoopCondition extends RelationalOperation {
5961
predicate exprWithVarAccessMaybeImpure(Expr expr, Variable variable) {
6062
exists(VariableAccess varAccess |
6163
expr.mayBeImpure() and
62-
expr.getAChild*() = varAccess and
64+
expr.getAChild*() = varAccess and // TODO: the `l` in the `i += l` is not mutated!
6365
variable = varAccess.getTarget()
6466
)
6567
}
@@ -267,6 +269,61 @@ private predicate variableReferenceTakenAsNonConstArgument(
267269
)
268270
}
269271

272+
predicate loopVariableAssignedToPointerOrReferenceType(
273+
ForStmt forLoop, VariableAccess loopVariableAccessInCondition
274+
) {
275+
exists(Expr assignmentRhs, DerivedType targetType |
276+
assignmentRhs.getEnclosingStmt().getParent*() = forLoop.getStmt() and
277+
(
278+
assignmentRhs.(AddressOfExpr).getOperand() =
279+
loopVariableAccessInCondition.getTarget().getAnAccess() or
280+
assignmentRhs = loopVariableAccessInCondition.getTarget().getAnAccess()
281+
) and
282+
isAssignment(assignmentRhs, targetType, _) and
283+
(
284+
targetType instanceof PointerType or
285+
targetType instanceof ReferenceType
286+
) and
287+
not targetType.getBaseType().isConst()
288+
)
289+
}
290+
291+
/*
292+
* An adapted part of `BuiltinTypeRules::MisraCpp23BuiltInTypes::isPreConversionAssignment`
293+
* that is only relevant to an argument passed to a parameter, seen as an assignment.
294+
*
295+
* This predicate adds two constraints to the target type, as compared to the original
296+
* portion of the predicate:
297+
*
298+
* 1. This predicate adds type constraint that the target type is a `ReferenceType`.
299+
* 2. This predicate adds the constraint that the target type is not `const`.
300+
*
301+
* Also, this predicate requires that the call is the body of the given for-loop.
302+
*/
303+
304+
predicate loopVariablePassedAsArgumentToReferenceParameter(
305+
ForStmt forLoop, Expr loopVariableAccessInCondition
306+
) {
307+
exists(ReferenceType targetType |
308+
exists(Call call, int i |
309+
call.getArgument(i) = loopVariableAccessInCondition and
310+
call.getEnclosingStmt().getParent*() = forLoop.getStmt() and
311+
not targetType.getBaseType().isConst()
312+
|
313+
/* A regular function call */
314+
targetType = call.getTarget().getParameter(i).getType()
315+
or
316+
/* A function call where the argument is passed as varargs */
317+
call.getTarget().getNumberOfParameters() <= i and
318+
/* The rule states that the type should match the "adjusted" type of the argument */
319+
targetType = loopVariableAccessInCondition.getFullyConverted().getType()
320+
or
321+
/* An expression call - get the function type, then the parameter type */
322+
targetType = getExprCallFunctionType(call).getParameterType(i)
323+
)
324+
)
325+
}
326+
270327
from ForStmt forLoop
271328
where
272329
not isExcluded(forLoop, StatementsPackage::legacyForStatementsShouldBeSimpleQuery()) and
@@ -332,63 +389,13 @@ where
332389
* or its address to a mutable pointer.
333390
*/
334391

335-
/* 6-1. The loop counter is taken a mutable reference or its address to a mutable pointer. */
336-
exists(VariableAccess loopCounterAccessInCondition |
337-
loopCounterAccessInCondition = forLoop.getCondition().(LegacyForLoopCondition).getLoopCounter()
392+
exists(VariableAccess loopVariableAccessInCondition |
393+
loopVariableAccessInCondition = forLoop.getCondition().(LegacyForLoopCondition).getLoopCounter() or
394+
loopVariableAccessInCondition = forLoop.getCondition().(LegacyForLoopCondition).getLoopBound() or
395+
loopVariableAccessInCondition = getLoopStepOfForStmt(forLoop)
338396
|
339-
exists(VariableAccess loopCounterAccessTakenAddressOrReference |
340-
loopCounterAccessInCondition.getTarget() =
341-
loopCounterAccessTakenAddressOrReference.getTarget()
342-
|
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)
350-
or
351-
variableReferenceTakenAsNonConstArgument(forLoop,
352-
loopCounterAccessTakenAddressOrReference.getTarget().getAnAccess(), _)
353-
)
354-
)
355-
or
356-
/* 6-2. The loop bound is taken a mutable reference or its address to a mutable pointer. */
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-
)
374-
or
375-
/* 6-3. The loop step is taken a mutable reference or its address to a mutable pointer. */
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-
)
397+
loopVariableAssignedToPointerOrReferenceType(forLoop, loopVariableAccessInCondition)
398+
or
399+
loopVariablePassedAsArgumentToReferenceParameter(forLoop, loopVariableAccessInCondition)
393400
)
394401
select forLoop, "TODO"

0 commit comments

Comments
 (0)