@@ -6,6 +6,7 @@ private import semmle.code.cpp.ir.internal.IRUtilities
66private import InstructionTag
77private import TranslatedElement
88private import TranslatedExpr
9+ private import TranslatedFunction
910private import TranslatedInitialization
1011
1112/**
@@ -66,17 +67,172 @@ abstract class TranslatedLocalVariableDeclaration extends TranslatedVariableInit
6667}
6768
6869/**
69- * Represents the IR translation of a local variable declaration within a declaration statement.
70+ * The IR translation of a local variable declaration within a declaration statement.
7071 */
71- class TranslatedVariableDeclarationEntry extends TranslatedLocalVariableDeclaration ,
72+ class TranslatedAutoVariableDeclarationEntry extends TranslatedLocalVariableDeclaration ,
7273 TranslatedDeclarationEntry {
73- LocalVariable var ;
74+ StackVariable var ;
7475
75- TranslatedVariableDeclarationEntry ( ) { var = entry .getDeclaration ( ) }
76+ TranslatedAutoVariableDeclarationEntry ( ) { var = entry .getDeclaration ( ) }
7677
7778 override LocalVariable getVariable ( ) { result = var }
7879}
7980
81+ /**
82+ * The IR translation of the declaration of a static local variable.
83+ * This element generates the logic that determines whether or not the variable has already been
84+ * initialized, and if not, invokes the initializer and sets the dynamic initialization flag for the
85+ * variable. The actual initialization code is handled in
86+ * `TranslatedStaticLocalVariableInitialization`, which is a child of this element.
87+ *
88+ * The generated code to do the initialization only once is:
89+ * ```
90+ * Block 1
91+ * r1225_1(glval<bool>) = VariableAddress[c#init] :
92+ * r1225_2(bool) = Load : &:r1225_1, ~mu1222_4
93+ * v1225_3(void) = ConditionalBranch : r1225_2
94+ * False -> Block 2
95+ * True -> Block 3
96+ *
97+ * Block 2
98+ * r1225_4(glval<int>) = VariableAddress[c] :
99+ * <actual initialization of `c`>
100+ * r1225_8(bool) = Constant[1] :
101+ * mu1225_9(bool) = Store : &:r1225_1, r1225_8
102+ * Goto -> Block 3
103+ *
104+ * Block 3
105+ * ```
106+ *
107+ * Note that the flag variable, `c#init`, is assumed to be zero-initialized at program startup, just
108+ * like any other variable with static storage duration.
109+ */
110+ class TranslatedStaticLocalVariableDeclarationEntry extends TranslatedDeclarationEntry {
111+ StaticLocalVariable var ;
112+
113+ TranslatedStaticLocalVariableDeclarationEntry ( ) { var = entry .getDeclaration ( ) }
114+
115+ final override TranslatedElement getChild ( int id ) { id = 0 and result = getInitialization ( ) }
116+
117+ final override predicate hasInstruction ( Opcode opcode , InstructionTag tag , CppType type ) {
118+ tag = DynamicInitializationFlagAddressTag ( ) and
119+ opcode instanceof Opcode:: VariableAddress and
120+ type = getBoolGLValueType ( )
121+ or
122+ tag = DynamicInitializationFlagLoadTag ( ) and
123+ opcode instanceof Opcode:: Load and
124+ type = getBoolType ( )
125+ or
126+ tag = DynamicInitializationConditionalBranchTag ( ) and
127+ opcode instanceof Opcode:: ConditionalBranch and
128+ type = getVoidType ( )
129+ or
130+ tag = DynamicInitializationFlagConstantTag ( ) and
131+ opcode instanceof Opcode:: Constant and
132+ type = getBoolType ( )
133+ or
134+ tag = DynamicInitializationFlagStoreTag ( ) and
135+ opcode instanceof Opcode:: Store and
136+ type = getBoolType ( )
137+ }
138+
139+ final override Instruction getFirstInstruction ( ) {
140+ result = getInstruction ( DynamicInitializationFlagAddressTag ( ) )
141+ }
142+
143+ final override Instruction getInstructionSuccessor ( InstructionTag tag , EdgeKind kind ) {
144+ tag = DynamicInitializationFlagAddressTag ( ) and
145+ kind instanceof GotoEdge and
146+ result = getInstruction ( DynamicInitializationFlagLoadTag ( ) )
147+ or
148+ tag = DynamicInitializationFlagLoadTag ( ) and
149+ kind instanceof GotoEdge and
150+ result = getInstruction ( DynamicInitializationConditionalBranchTag ( ) )
151+ or
152+ tag = DynamicInitializationConditionalBranchTag ( ) and
153+ (
154+ kind instanceof TrueEdge and
155+ result = getParent ( ) .getChildSuccessor ( this )
156+ or
157+ kind instanceof FalseEdge and
158+ result = getInitialization ( ) .getFirstInstruction ( )
159+ )
160+ or
161+ tag = DynamicInitializationFlagConstantTag ( ) and
162+ kind instanceof GotoEdge and
163+ result = getInstruction ( DynamicInitializationFlagStoreTag ( ) )
164+ or
165+ tag = DynamicInitializationFlagStoreTag ( ) and
166+ kind instanceof GotoEdge and
167+ result = getParent ( ) .getChildSuccessor ( this )
168+ }
169+
170+ final override Instruction getChildSuccessor ( TranslatedElement child ) {
171+ child = getInitialization ( ) and
172+ result = getInstruction ( DynamicInitializationFlagConstantTag ( ) )
173+ }
174+
175+ final override IRDynamicInitializationFlag getInstructionVariable ( InstructionTag tag ) {
176+ tag = DynamicInitializationFlagAddressTag ( ) and
177+ result .getVariable ( ) = var
178+ }
179+
180+ final override string getInstructionConstantValue ( InstructionTag tag ) {
181+ tag = DynamicInitializationFlagConstantTag ( ) and result = "1"
182+ }
183+
184+ final override Instruction getInstructionOperand ( InstructionTag tag , OperandTag operandTag ) {
185+ tag = DynamicInitializationFlagLoadTag ( ) and
186+ (
187+ operandTag instanceof AddressOperandTag and
188+ result = getInstruction ( DynamicInitializationFlagAddressTag ( ) )
189+ or
190+ operandTag instanceof LoadOperandTag and
191+ result = getTranslatedFunction ( var .getFunction ( ) ) .getUnmodeledDefinitionInstruction ( )
192+ )
193+ or
194+ tag = DynamicInitializationConditionalBranchTag ( ) and
195+ operandTag instanceof ConditionOperandTag and
196+ result = getInstruction ( DynamicInitializationFlagLoadTag ( ) )
197+ or
198+ tag = DynamicInitializationFlagStoreTag ( ) and
199+ (
200+ operandTag instanceof AddressOperandTag and
201+ result = getInstruction ( DynamicInitializationFlagAddressTag ( ) )
202+ or
203+ operandTag instanceof StoreValueOperandTag and
204+ result = getInstruction ( DynamicInitializationFlagConstantTag ( ) )
205+ )
206+ }
207+
208+ private TranslatedStaticLocalVariableInitialization getInitialization ( ) {
209+ result .getVariable ( ) = var
210+ }
211+ }
212+
213+ /**
214+ * The initialization of a static local variable. This element will only exist for a static variable
215+ * with a dynamic initializer.
216+ */
217+ class TranslatedStaticLocalVariableInitialization extends TranslatedElement ,
218+ TranslatedLocalVariableDeclaration , TTranslatedStaticLocalVariableInitialization {
219+ VariableDeclarationEntry entry ;
220+ StaticLocalVariable var ;
221+
222+ TranslatedStaticLocalVariableInitialization ( ) {
223+ this = TTranslatedStaticLocalVariableInitialization ( entry ) and
224+ var = entry .getDeclaration ( )
225+ }
226+
227+ final override string toString ( ) { result = "init: " + entry .toString ( ) }
228+
229+ final override Locatable getAST ( ) { result = entry }
230+
231+ final override LocalVariable getVariable ( ) { result = var }
232+
233+ final override Function getFunction ( ) { result = var .getFunction ( ) }
234+ }
235+
80236/**
81237 * Gets the `TranslatedRangeBasedForVariableDeclaration` that represents the declaration of
82238 * `var`.
0 commit comments