Skip to content

Commit 07f9fe6

Browse files
C++: Add Uninitialized instruction for list-initialized variables
This commit inserts an `Uninitialized` instruction to "initialize" a local variable when that variable is initialized with an initializer list. This ensures that there is always a definition of the whole variable before any read or write to part of that variable. This change appears in a different form in @rdmarsh2's Chi node PR, but I needed to refactor the initialization code anyway to handle ConditionDeclExpr.
1 parent b21b066 commit 07f9fe6

File tree

4 files changed

+633
-624
lines changed

4 files changed

+633
-624
lines changed

cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedDeclarationEntry.qll

Lines changed: 55 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,7 @@ private import TranslatedInitialization
1010
* Gets the `TranslatedDeclarationEntry` that represents the declaration
1111
* `entry`.
1212
*/
13-
TranslatedDeclarationEntry getTranslatedDeclarationEntry(
14-
DeclarationEntry entry) {
13+
TranslatedDeclarationEntry getTranslatedDeclarationEntry(DeclarationEntry entry) {
1514
result.getAST() = entry
1615
}
1716

@@ -21,8 +20,7 @@ TranslatedDeclarationEntry getTranslatedDeclarationEntry(
2120
* it can also be the declaration of a static local variable, an extern
2221
* variable, or an extern function.
2322
*/
24-
abstract class TranslatedDeclarationEntry extends TranslatedElement,
25-
TTranslatedDeclarationEntry {
23+
abstract class TranslatedDeclarationEntry extends TranslatedElement, TTranslatedDeclarationEntry {
2624
DeclarationEntry entry;
2725

2826
TranslatedDeclarationEntry() {
@@ -50,14 +48,13 @@ abstract class TranslatedDeclarationEntry extends TranslatedElement,
5048
* for declarations other than local variables. Since these have no semantic
5149
* effect, they are translated as `NoOp`.
5250
*/
53-
class TranslatedNonVariableDeclaration extends
54-
TranslatedDeclarationEntry {
55-
TranslatedNonVariableDeclaration() {
51+
class TranslatedNonVariableDeclarationEntry extends TranslatedDeclarationEntry {
52+
TranslatedNonVariableDeclarationEntry() {
5653
not entry.getDeclaration() instanceof LocalVariable
5754
}
5855

5956
override predicate hasInstruction(Opcode opcode, InstructionTag tag,
60-
Type resultType, boolean isGLValue) {
57+
Type resultType, boolean isGLValue) {
6158
opcode instanceof Opcode::NoOp and
6259
tag = OnlyInstructionTag() and
6360
resultType instanceof VoidType and
@@ -88,140 +85,104 @@ class TranslatedNonVariableDeclaration extends
8885
* Represents the IR translation of the declaration of a local variable,
8986
* including its initialization, if any.
9087
*/
91-
abstract class TranslatedVariableDeclaration extends
92-
TranslatedDeclarationEntry {
93-
LocalVariable var;
94-
95-
TranslatedVariableDeclaration() {
96-
entry.getDeclaration() = var
97-
}
98-
}
99-
100-
/**
101-
* Represents the IR translation of a local variable with no initializer. The
102-
* generated IR stores into the variable using an `Uninitialized` instruction,
103-
* rather than a `Store`.
104-
*/
105-
class TranslatedUninitializedVariable extends
106-
TranslatedVariableDeclaration {
107-
TranslatedUninitializedVariable() {
108-
not exists(Initializer init |
109-
init.getDeclaration() = var
110-
)
111-
}
88+
abstract class TranslatedVariableDeclaration extends TranslatedElement, InitializationContext {
89+
/**
90+
* Gets the local variable being declared.
91+
*/
92+
abstract LocalVariable getVariable();
11293

11394
override TranslatedElement getChild(int id) {
114-
none()
95+
id = 0 and result = getInitialization()
11596
}
11697

11798
override Instruction getFirstInstruction() {
11899
result = getInstruction(InitializerVariableAddressTag())
119100
}
120101

121102
override predicate hasInstruction(Opcode opcode, InstructionTag tag,
122-
Type resultType, boolean isGLValue) {
103+
Type resultType, boolean isGLValue) {
123104
(
124105
tag = InitializerVariableAddressTag() and
125106
opcode instanceof Opcode::VariableAddress and
126-
resultType = var.getType().getUnspecifiedType() and
107+
resultType = getVariable().getType().getUnspecifiedType() and
127108
isGLValue = true
128109
) or
129-
(
110+
(
111+
hasUninitializedInstruction() and
130112
tag = InitializerStoreTag() and
131113
opcode instanceof Opcode::Uninitialized and
132-
resultType = var.getType().getUnspecifiedType() and
114+
resultType = getVariable().getType().getUnspecifiedType() and
133115
isGLValue = false
134116
)
135117
}
136118

137119
override Instruction getInstructionSuccessor(InstructionTag tag,
138-
EdgeKind kind) {
139-
kind instanceof GotoEdge and
120+
EdgeKind kind) {
140121
(
141-
(
142-
tag = InitializerVariableAddressTag() and
122+
tag = InitializerVariableAddressTag() and
123+
kind instanceof GotoEdge and
124+
if hasUninitializedInstruction() then
143125
result = getInstruction(InitializerStoreTag())
144-
) or
126+
else
127+
result = getInitialization().getFirstInstruction()
128+
) or
129+
(
130+
hasUninitializedInstruction() and
131+
kind instanceof GotoEdge and
132+
tag = InitializerStoreTag() and
145133
(
146-
tag = InitializerStoreTag() and
147-
result = getParent().getChildSuccessor(this)
134+
result = getInitialization().getFirstInstruction() or
135+
not exists(getInitialization()) and result = getParent().getChildSuccessor(this)
148136
)
149137
)
150138
}
151139

152140
override Instruction getChildSuccessor(TranslatedElement child) {
153-
none()
154-
}
155-
156-
override Instruction getInstructionOperand(InstructionTag tag,
157-
OperandTag operandTag) {
158-
tag = InitializerStoreTag() and
159-
(
160-
(
161-
operandTag instanceof AddressOperandTag and
162-
result = getInstruction(InitializerVariableAddressTag())
163-
)
164-
)
141+
child = getInitialization() and result = getParent().getChildSuccessor(this)
165142
}
166143

167144
override IRVariable getInstructionVariable(InstructionTag tag) {
168145
tag = InitializerVariableAddressTag() and
169-
result = getIRUserVariable(var.getFunction(), var)
146+
result = getIRUserVariable(getFunction(), getVariable())
170147
}
171-
}
172148

173-
/**
174-
* Represents the IR translation of a local variable with an initializer.
175-
*/
176-
class TranslatedInitializedVariable extends
177-
TranslatedVariableDeclaration, InitializationContext {
178-
Initializer init;
179-
180-
TranslatedInitializedVariable() {
181-
init.getDeclaration() = var
182-
}
183-
184-
override TranslatedElement getChild(int id) {
185-
id = 0 and result = getInitialization()
186-
}
187-
188-
override Instruction getFirstInstruction() {
149+
override Instruction getInstructionOperand(InstructionTag tag, OperandTag operandTag) {
150+
hasUninitializedInstruction() and
151+
tag = InitializerStoreTag() and
152+
operandTag instanceof AddressOperandTag and
189153
result = getInstruction(InitializerVariableAddressTag())
190154
}
191155

192-
override predicate hasInstruction(Opcode opcode, InstructionTag tag,
193-
Type resultType, boolean isGLValue) {
194-
tag = InitializerVariableAddressTag() and
195-
opcode instanceof Opcode::VariableAddress and
196-
resultType = var.getType().getUnspecifiedType() and
197-
isGLValue = true
156+
override Instruction getTargetAddress() {
157+
result = getInstruction(InitializerVariableAddressTag())
198158
}
199159

200-
override Instruction getInstructionSuccessor(InstructionTag tag,
201-
EdgeKind kind) {
202-
tag = InitializerVariableAddressTag() and
203-
result = getInitialization().getFirstInstruction() and
204-
kind instanceof GotoEdge
160+
override Type getTargetType() {
161+
result = getVariable().getType().getUnspecifiedType()
205162
}
206163

207-
override Instruction getChildSuccessor(TranslatedElement child) {
208-
child = getInitialization() and result = getParent().getChildSuccessor(this)
164+
private TranslatedInitialization getInitialization() {
165+
result = getTranslatedInitialization(getVariable().getInitializer().getExpr().getFullyConverted())
209166
}
210167

211-
override IRVariable getInstructionVariable(InstructionTag tag) {
212-
tag = InitializerVariableAddressTag() and
213-
result = getIRUserVariable(var.getFunction(), var)
168+
private predicate hasUninitializedInstruction() {
169+
not exists(getInitialization()) or
170+
getInitialization() instanceof TranslatedListInitialization
214171
}
172+
}
215173

216-
override Instruction getTargetAddress() {
217-
result = getInstruction(InitializerVariableAddressTag())
218-
}
174+
/**
175+
* Represents the IR translation of a local variable declaration within a declaration statement.
176+
*/
177+
class TranslatedVariableDeclarationEntry extends TranslatedVariableDeclaration,
178+
TranslatedDeclarationEntry {
179+
LocalVariable var;
219180

220-
override Type getTargetType() {
221-
result = var.getType().getUnspecifiedType()
181+
TranslatedVariableDeclarationEntry() {
182+
var = entry.getDeclaration()
222183
}
223184

224-
private TranslatedInitialization getInitialization() {
225-
result = getTranslatedInitialization(init.getExpr().getFullyConverted())
185+
override LocalVariable getVariable() {
186+
result = var
226187
}
227188
}

0 commit comments

Comments
 (0)