Skip to content

Commit 70e9d11

Browse files
authored
Merge pull request #509 from dave-bartolomeo/dave/ConditionDeclExpr
C++: IR support for ConditionDeclExpr
2 parents 62db19b + 3715215 commit 70e9d11

File tree

11 files changed

+1298
-621
lines changed

11 files changed

+1298
-621
lines changed

cpp/ql/src/semmle/code/cpp/Variable.qll

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -291,7 +291,8 @@ class LocalVariable extends LocalScopeVariable, @localvariable {
291291
override Type getType() { localvariables(underlyingElement(this),unresolveElement(result),_) }
292292

293293
override Function getFunction() {
294-
exists(DeclStmt s | s.getADeclaration() = this and s.getEnclosingFunction() = result)
294+
exists(DeclStmt s | s.getADeclaration() = this and s.getEnclosingFunction() = result) or
295+
exists(ConditionDeclExpr e | e.getVariable() = this and e.getEnclosingFunction() = result)
295296
}
296297
}
297298

cpp/ql/src/semmle/code/cpp/exprs/Expr.qll

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,8 @@ class Expr extends StmtParent, @expr {
2828
result = this.getParent().(Expr).getEnclosingStmt() or
2929
result = this.getParent().(Stmt) or
3030
exists(Expr other | result = other.getEnclosingStmt() and other.getConversion() = this) or
31-
exists(DeclStmt d, LocalVariable v | d.getADeclaration() = v and v.getInitializer().getExpr() = this and result = d)
31+
exists(DeclStmt d, LocalVariable v | d.getADeclaration() = v and v.getInitializer().getExpr() = this and result = d) or
32+
exists(ConditionDeclExpr cde, LocalVariable v | cde.getVariable() = v and v.getInitializer().getExpr() = this and result = cde.getEnclosingStmt())
3233
}
3334

3435
/** Gets the enclosing variable of this expression, if any. */

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

Lines changed: 86 additions & 89 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,140 @@ 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;
149+
override Instruction getInstructionOperand(InstructionTag tag, OperandTag operandTag) {
150+
hasUninitializedInstruction() and
151+
tag = InitializerStoreTag() and
152+
operandTag instanceof AddressOperandTag and
153+
result = getInstruction(InitializerVariableAddressTag())
154+
}
179155

180-
TranslatedInitializedVariable() {
181-
init.getDeclaration() = var
156+
override Instruction getTargetAddress() {
157+
result = getInstruction(InitializerVariableAddressTag())
182158
}
183159

184-
override TranslatedElement getChild(int id) {
185-
id = 0 and result = getInitialization()
160+
override Type getTargetType() {
161+
result = getVariable().getType().getUnspecifiedType()
186162
}
187163

188-
override Instruction getFirstInstruction() {
189-
result = getInstruction(InitializerVariableAddressTag())
164+
private TranslatedInitialization getInitialization() {
165+
result = getTranslatedInitialization(getVariable().getInitializer().getExpr().getFullyConverted())
190166
}
191167

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
168+
private predicate hasUninitializedInstruction() {
169+
not exists(getInitialization()) or
170+
getInitialization() instanceof TranslatedListInitialization
198171
}
172+
}
199173

200-
override Instruction getInstructionSuccessor(InstructionTag tag,
201-
EdgeKind kind) {
202-
tag = InitializerVariableAddressTag() and
203-
result = getInitialization().getFirstInstruction() and
204-
kind instanceof GotoEdge
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;
180+
181+
TranslatedVariableDeclarationEntry() {
182+
var = entry.getDeclaration()
205183
}
206184

207-
override Instruction getChildSuccessor(TranslatedElement child) {
208-
child = getInitialization() and result = getParent().getChildSuccessor(this)
185+
override LocalVariable getVariable() {
186+
result = var
209187
}
188+
}
210189

211-
override IRVariable getInstructionVariable(InstructionTag tag) {
212-
tag = InitializerVariableAddressTag() and
213-
result = getIRUserVariable(var.getFunction(), var)
190+
TranslatedConditionDecl getTranslatedConditionDecl(ConditionDeclExpr expr) {
191+
result.getAST() = expr
192+
}
193+
194+
/**
195+
* Represents the IR translation of the declaration portion of a `ConditionDeclExpr`, which
196+
* represents the variable declared in code such as:
197+
* ```
198+
* if (int* p = &x) {
199+
* }
200+
* ```
201+
*/
202+
class TranslatedConditionDecl extends TranslatedVariableDeclaration, TTranslatedConditionDecl {
203+
ConditionDeclExpr conditionDeclExpr;
204+
205+
TranslatedConditionDecl() {
206+
this = TTranslatedConditionDecl(conditionDeclExpr)
214207
}
215208

216-
override Instruction getTargetAddress() {
217-
result = getInstruction(InitializerVariableAddressTag())
209+
override string toString() {
210+
result = "decl: " + conditionDeclExpr.toString()
218211
}
219212

220-
override Type getTargetType() {
221-
result = var.getType().getUnspecifiedType()
213+
override Locatable getAST() {
214+
result = conditionDeclExpr
222215
}
223216

224-
private TranslatedInitialization getInitialization() {
225-
result = getTranslatedInitialization(init.getExpr().getFullyConverted())
217+
override Function getFunction() {
218+
result = conditionDeclExpr.getEnclosingFunction()
219+
}
220+
221+
override LocalVariable getVariable() {
222+
result = conditionDeclExpr.getVariable()
226223
}
227224
}

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -319,6 +319,10 @@ newtype TTranslatedElement =
319319
// An allocation size for a `new` or `new[]` expression
320320
TTranslatedAllocationSize(NewOrNewArrayExpr newExpr) {
321321
not ignoreExpr(newExpr)
322+
} or
323+
// The declaration/initialization part of a `ConditionDeclExpr`
324+
TTranslatedConditionDecl(ConditionDeclExpr expr) {
325+
not ignoreExpr(expr)
322326
}
323327

324328
/**

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

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ private import semmle.code.cpp.ir.internal.OperandTag
44
private import semmle.code.cpp.ir.internal.TempVariableTag
55
private import InstructionTag
66
private import TranslatedCondition
7+
private import TranslatedDeclarationEntry
78
private import TranslatedElement
89
private import TranslatedFunction
910
private import TranslatedInitialization
@@ -2914,3 +2915,57 @@ class TranslatedNewArrayExpr extends TranslatedNewOrNewArrayExpr {
29142915
none()
29152916
}
29162917
}
2918+
2919+
/**
2920+
* The IR translation of a `ConditionDeclExpr`, which represents the value of the declared variable
2921+
* after conversion to `bool` in code such as:
2922+
* ```
2923+
* if (int* p = &x) {
2924+
* }
2925+
* ```
2926+
*/
2927+
class TranslatedConditionDeclExpr extends TranslatedNonConstantExpr {
2928+
ConditionDeclExpr condDeclExpr;
2929+
2930+
TranslatedConditionDeclExpr() {
2931+
condDeclExpr = expr
2932+
}
2933+
2934+
override final Instruction getFirstInstruction() {
2935+
result = getDecl().getFirstInstruction()
2936+
}
2937+
2938+
override final TranslatedElement getChild(int id) {
2939+
id = 0 and result = getDecl() or
2940+
id = 1 and result = getConditionExpr()
2941+
}
2942+
2943+
override Instruction getResult() {
2944+
result = getConditionExpr().getResult()
2945+
}
2946+
2947+
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
2948+
none()
2949+
}
2950+
2951+
override Instruction getChildSuccessor(TranslatedElement child) {
2952+
(
2953+
child = getDecl() and
2954+
result = getConditionExpr().getFirstInstruction()
2955+
) or
2956+
child = getConditionExpr() and result = getParent().getChildSuccessor(this)
2957+
}
2958+
2959+
override predicate hasInstruction(Opcode opcode, InstructionTag tag, Type resultType,
2960+
boolean isGLValue) {
2961+
none()
2962+
}
2963+
2964+
private TranslatedConditionDecl getDecl() {
2965+
result = getTranslatedConditionDecl(condDeclExpr)
2966+
}
2967+
2968+
private TranslatedExpr getConditionExpr() {
2969+
result = getTranslatedExpr(condDeclExpr.getExpr().getFullyConverted())
2970+
}
2971+
}

0 commit comments

Comments
 (0)