|
15 | 15 |
|
16 | 16 | import cpp |
17 | 17 | import codingstandards.cpp.autosar |
18 | | - |
19 | | -/** |
20 | | - * Holds if `e` is a full expression or `AggregateLiteral` in the initializer of a |
21 | | - * `StaticStorageDurationVariable`. |
22 | | - * |
23 | | - * Although `AggregateLiteral`s are expressions according to our model, they are not considered |
24 | | - * expressions from the perspective of the standard. Therefore, we should consider components of |
25 | | - * aggregate literals within static initializers to also be full expressions. |
26 | | - */ |
27 | | -private predicate isFullExprOrAggregateInStaticInitializer(Expr e) { |
28 | | - exists(StaticStorageDurationVariable var | e = var.getInitializer().getExpr()) |
29 | | - or |
30 | | - isFullExprOrAggregateInStaticInitializer(e.getParent().(AggregateLiteral)) |
31 | | -} |
32 | | - |
33 | | -/** |
34 | | - * Holds if `e` is a non-constant full expression in a static initializer, for the given `reason` |
35 | | - * and `reasonElement`. |
36 | | - */ |
37 | | -private predicate nonConstantFullExprInStaticInitializer( |
38 | | - Expr e, Element reasonElement, string reason |
39 | | -) { |
40 | | - isFullExprOrAggregateInStaticInitializer(e) and |
41 | | - if e instanceof AggregateLiteral |
42 | | - then |
43 | | - // If this is an aggregate literal, we apply this recursively |
44 | | - nonConstantFullExprInStaticInitializer(e.getAChild(), reasonElement, reason) |
45 | | - else ( |
46 | | - // Otherwise we check this component to determine if it is constant |
47 | | - not ( |
48 | | - e.getFullyConverted().isConstant() or |
49 | | - e.(Call).getTarget().isConstexpr() or |
50 | | - e.(VariableAccess).getTarget().isConstexpr() |
51 | | - ) and |
52 | | - reason = "uses a non-constant element in the initialization" and |
53 | | - reasonElement = e |
54 | | - ) |
55 | | -} |
56 | | - |
57 | | -/** |
58 | | - * A `ConstructorCall` that does not represent a constant initializer for an object according to |
59 | | - * `[basic.start.init]`. |
60 | | - * |
61 | | - * In addition to identifying `ConstructorCall`s which are not constant initializers, this also |
62 | | - * provides an explanatory "reason" for why this constructor is not considered to be a constant |
63 | | - * initializer. |
64 | | - */ |
65 | | -predicate isNotConstantInitializer(ConstructorCall cc, Element reasonElement, string reason) { |
66 | | - // Must call a constexpr constructor |
67 | | - not cc.getTarget().isConstexpr() and |
68 | | - reason = |
69 | | - "calls the " + cc.getTarget().getName() + "(..) constructor which is not marked as constexpr" and |
70 | | - reasonElement = cc |
71 | | - or |
72 | | - // And all arguments must either be constant, or themselves call constexpr constructors |
73 | | - cc.getTarget().isConstexpr() and |
74 | | - exists(Expr arg | arg = cc.getAnArgument() | |
75 | | - isNotConstantInitializer(arg, reasonElement, reason) |
76 | | - or |
77 | | - not arg instanceof ConstructorCall and |
78 | | - not arg.getFullyConverted().isConstant() and |
79 | | - not arg.(Call).getTarget().isConstexpr() and |
80 | | - not arg.(VariableAccess).getTarget().isConstexpr() and |
81 | | - reason = "includes a non constant " + arg.getType() + " argument to a constexpr constructor" and |
82 | | - reasonElement = arg |
83 | | - ) |
84 | | -} |
85 | | - |
86 | | -/** |
87 | | - * Identifies if a `StaticStorageDurationVariable` is not constant initialized according to |
88 | | - * `[basic.start.init]`. |
89 | | - */ |
90 | | -predicate isNotConstantInitialized( |
91 | | - StaticStorageDurationVariable v, string reason, Element reasonElement |
92 | | -) { |
93 | | - if v.getInitializer().getExpr() instanceof ConstructorCall |
94 | | - then |
95 | | - // (2.2) if initialized by a constructor call, then that constructor call must be a constant |
96 | | - // initializer for the variable to be constant initialized |
97 | | - isNotConstantInitializer(v.getInitializer().getExpr(), reasonElement, reason) |
98 | | - else |
99 | | - // (2.3) If it is not initialized by a constructor call, then it must be the case that every full |
100 | | - // expr in the initializer is a constant expression or that the object was "value initialized" |
101 | | - // but without a constructor call. For value initialization, there are two non-constructor call |
102 | | - // cases to consider: |
103 | | - // |
104 | | - // 1. The object was zero initialized - in which case, the extractor does not include a |
105 | | - // constructor call - instead, it has a blank aggregate literal, or no initializer. |
106 | | - // 2. The object is an array, which will be initialized by an aggregate literal. |
107 | | - // |
108 | | - // In both cases it is sufficient for us to find a non-constant full expression in the static |
109 | | - // initializer |
110 | | - nonConstantFullExprInStaticInitializer(v.getInitializer().getExpr(), reasonElement, reason) |
111 | | -} |
| 18 | +import codingstandards.cpp.orderofevaluation.Initialization |
112 | 19 |
|
113 | 20 | from StaticStorageDurationVariable staticOrThreadLocalVar, string reason, Element reasonElement |
114 | 21 | where |
|
0 commit comments