Skip to content

Commit 24247d2

Browse files
committed
Refactor A7-1-2 to extract constant expression logic
1 parent 30aa044 commit 24247d2

File tree

2 files changed

+82
-73
lines changed

2 files changed

+82
-73
lines changed

cpp/autosar/src/rules/A7-1-2/VariableMissingConstexpr.ql

Lines changed: 2 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import codingstandards.cpp.autosar
1818
import codingstandards.cpp.TrivialType
1919
import codingstandards.cpp.SideEffect
2020
import semmle.code.cpp.controlflow.SSA
21+
import codingstandards.cpp.Expr
2122

2223
predicate isZeroInitializable(Variable v) {
2324
not exists(v.getInitializer().getExpr()) and
@@ -34,78 +35,6 @@ predicate isTypeZeroInitializable(Type t) {
3435
t.getUnderlyingType() instanceof ArrayType
3536
}
3637

37-
/**
38-
* An optimized set of expressions used to determine the flow through constexpr variables.
39-
*/
40-
class VariableAccessOrCallOrLiteral extends Expr {
41-
VariableAccessOrCallOrLiteral() {
42-
this instanceof VariableAccess or
43-
this instanceof Call or
44-
this instanceof Literal
45-
}
46-
}
47-
48-
/**
49-
* Holds if the value of source flows through compile time evaluated variables to target.
50-
*/
51-
predicate flowsThroughConstExprVariables(
52-
VariableAccessOrCallOrLiteral source, VariableAccessOrCallOrLiteral target
53-
) {
54-
(
55-
source = target
56-
or
57-
source != target and
58-
exists(SsaDefinition intermediateDef, StackVariable intermediate |
59-
intermediateDef.getAVariable().getFunction() = source.getEnclosingFunction() and
60-
intermediateDef.getAVariable().getFunction() = target.getEnclosingFunction() and
61-
intermediateDef.getAVariable() = intermediate and
62-
intermediate.isConstexpr()
63-
|
64-
DataFlow::localExprFlow(source, intermediateDef.getDefiningValue(intermediate)) and
65-
flowsThroughConstExprVariables(intermediateDef.getAUse(intermediate), target)
66-
)
67-
)
68-
}
69-
70-
/*
71-
* Returns true if the given call may be evaluated at compile time and is compile time evaluated because
72-
* all its arguments are compile time evaluated and its default values are compile time evaluated.
73-
*/
74-
75-
predicate isCompileTimeEvaluated(Call call) {
76-
// 1. The call may be evaluated at compile time, because it is constexpr, and
77-
call.getTarget().isConstexpr() and
78-
// 2. all its arguments are compile time evaluated, and
79-
forall(DataFlow::Node ultimateArgSource, DataFlow::Node argSource |
80-
argSource = DataFlow::exprNode(call.getAnArgument()) and
81-
DataFlow::localFlow(ultimateArgSource, argSource) and
82-
not DataFlow::localFlowStep(_, ultimateArgSource)
83-
|
84-
(
85-
ultimateArgSource.asExpr() instanceof Literal
86-
or
87-
any(Call c | isCompileTimeEvaluated(c)) = ultimateArgSource.asExpr()
88-
) and
89-
// If the ultimate argument source is not the same as the argument source, then it must flow through
90-
// constexpr variables.
91-
(
92-
ultimateArgSource != argSource
93-
implies
94-
flowsThroughConstExprVariables(ultimateArgSource.asExpr(), argSource.asExpr())
95-
)
96-
) and
97-
// 3. all the default values used are compile time evaluated.
98-
forall(Expr defaultValue, Parameter parameterUsingDefaultValue, int idx |
99-
parameterUsingDefaultValue = call.getTarget().getParameter(idx) and
100-
not exists(call.getArgument(idx)) and
101-
parameterUsingDefaultValue.getAnAssignedValue() = defaultValue
102-
|
103-
defaultValue instanceof Literal
104-
or
105-
any(Call c | isCompileTimeEvaluated(c)) = defaultValue
106-
)
107-
}
108-
10938
from Variable v
11039
where
11140
not isExcluded(v, ConstPackage::variableMissingConstexprQuery()) and
@@ -119,7 +48,7 @@ where
11948
(
12049
v.getInitializer().getExpr().isConstant()
12150
or
122-
any(Call call | isCompileTimeEvaluated(call)) = v.getInitializer().getExpr()
51+
any(Call call | isCompileTimeEvaluatedCall(call)) = v.getInitializer().getExpr()
12352
or
12453
isZeroInitializable(v)
12554
or

cpp/common/src/codingstandards/cpp/Expr.qll

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,3 +189,83 @@ module MisraExpr {
189189
CValue() { isCValue(this) }
190190
}
191191
}
192+
193+
/**
194+
* An optimized set of expressions used to determine the flow through constexpr variables.
195+
*/
196+
class VariableAccessOrCallOrLiteral extends Expr {
197+
VariableAccessOrCallOrLiteral() {
198+
this instanceof VariableAccess and this.(VariableAccess).getTarget().isConstexpr()
199+
or
200+
this instanceof Call
201+
or
202+
this instanceof Literal
203+
}
204+
}
205+
206+
/**
207+
* Holds if the value of source flows through compile time evaluated variables to target.
208+
*/
209+
predicate flowsThroughConstExprVariables(
210+
VariableAccessOrCallOrLiteral source, VariableAccessOrCallOrLiteral target
211+
) {
212+
(
213+
source = target
214+
or
215+
source != target and
216+
exists(SsaDefinition intermediateDef, StackVariable intermediate |
217+
intermediateDef.getAVariable().getFunction() = source.getEnclosingFunction() and
218+
intermediateDef.getAVariable().getFunction() = target.getEnclosingFunction() and
219+
intermediateDef.getAVariable() = intermediate and
220+
intermediate.isConstexpr()
221+
|
222+
DataFlow::localExprFlow(source, intermediateDef.getDefiningValue(intermediate)) and
223+
flowsThroughConstExprVariables(intermediateDef.getAUse(intermediate), target)
224+
)
225+
)
226+
}
227+
228+
predicate isCompileTimeEvaluatedExpression(Expr expression) {
229+
forall(DataFlow::Node ultimateSource, DataFlow::Node source |
230+
source = DataFlow::exprNode(expression) and
231+
DataFlow::localFlow(ultimateSource, source) and
232+
not DataFlow::localFlowStep(_, ultimateSource)
233+
|
234+
isDirectCompileTimeEvaluatedExpression(ultimateSource.asExpr()) and
235+
// If the ultimate source is not the same as the source, then it must flow through
236+
// constexpr variables.
237+
(
238+
ultimateSource != source
239+
implies
240+
flowsThroughConstExprVariables(ultimateSource.asExpr(), source.asExpr())
241+
)
242+
)
243+
}
244+
245+
predicate isDirectCompileTimeEvaluatedExpression(Expr expression) {
246+
expression instanceof Literal
247+
or
248+
any(Call c | isCompileTimeEvaluatedCall(c)) = expression
249+
}
250+
251+
/*
252+
* Returns true if the given call may be evaluated at compile time and is compile time evaluated because
253+
* all its arguments are compile time evaluated and its default values are compile time evaluated.
254+
*/
255+
256+
predicate isCompileTimeEvaluatedCall(Call call) {
257+
// 1. The call may be evaluated at compile time, because it is constexpr, and
258+
call.getTarget().isConstexpr() and
259+
// 2. all its arguments are compile time evaluated, and
260+
forall(Expr argSource | argSource = call.getAnArgument() |
261+
isCompileTimeEvaluatedExpression(argSource)
262+
) and
263+
// 3. all the default values used are compile time evaluated.
264+
forall(Expr defaultValue, Parameter parameterUsingDefaultValue, int idx |
265+
parameterUsingDefaultValue = call.getTarget().getParameter(idx) and
266+
not exists(call.getArgument(idx)) and
267+
parameterUsingDefaultValue.getAnAssignedValue() = defaultValue
268+
|
269+
isDirectCompileTimeEvaluatedExpression(defaultValue)
270+
)
271+
}

0 commit comments

Comments
 (0)