Skip to content

Commit 3715215

Browse files
C++: Add IR support for ConditionalDeclExpr
Also fixes several places in the library that weren't handling `ConditionalDeclExpr` correctly.
1 parent 07f9fe6 commit 3715215

File tree

11 files changed

+670
-2
lines changed

11 files changed

+670
-2
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: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,3 +186,39 @@ class TranslatedVariableDeclarationEntry extends TranslatedVariableDeclaration,
186186
result = var
187187
}
188188
}
189+
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)
207+
}
208+
209+
override string toString() {
210+
result = "decl: " + conditionDeclExpr.toString()
211+
}
212+
213+
override Locatable getAST() {
214+
result = conditionDeclExpr
215+
}
216+
217+
override Function getFunction() {
218+
result = conditionDeclExpr.getEnclosingFunction()
219+
}
220+
221+
override LocalVariable getVariable() {
222+
result = conditionDeclExpr.getVariable()
223+
}
224+
}

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+
}

cpp/ql/test/library-tests/ir/ir/PrintAST.expected

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6335,3 +6335,119 @@ ir.cpp:
63356335
# 963| Type = int
63366336
# 963| Value = 900
63376337
# 963| ValueCategory = prvalue
6338+
# 966| IfStmtWithDeclaration(int, int) -> void
6339+
# 966| params:
6340+
# 966| 0: x
6341+
# 966| Type = int
6342+
# 966| 1: y
6343+
# 966| Type = int
6344+
# 966| body: { ... }
6345+
# 967| 0: if (...) ...
6346+
# 967| 0: (condition decl)
6347+
# 967| Type = bool
6348+
# 967| ValueCategory = prvalue
6349+
# 967| 0: b
6350+
# 967| Type = bool
6351+
# 967| ValueCategory = prvalue(load)
6352+
# 967| 1: { ... }
6353+
# 968| 0: ExprStmt
6354+
# 968| 0: ... = ...
6355+
# 968| Type = int
6356+
# 968| ValueCategory = lvalue
6357+
# 968| 0: x
6358+
# 968| Type = int
6359+
# 968| ValueCategory = lvalue
6360+
# 968| 1: 5
6361+
# 968| Type = int
6362+
# 968| Value = 5
6363+
# 968| ValueCategory = prvalue
6364+
# 970| 2: if (...) ...
6365+
# 970| 0: (condition decl)
6366+
# 970| Type = bool
6367+
# 970| ValueCategory = prvalue
6368+
# 970| 0: (bool)...
6369+
# 970| Conversion = conversion to bool
6370+
# 970| Type = bool
6371+
# 970| ValueCategory = prvalue
6372+
# 970| expr: z
6373+
# 970| Type = int
6374+
# 970| ValueCategory = prvalue(load)
6375+
# 970| 1: { ... }
6376+
# 971| 0: ExprStmt
6377+
# 971| 0: ... = ...
6378+
# 971| Type = int
6379+
# 971| ValueCategory = lvalue
6380+
# 971| 0: y
6381+
# 971| Type = int
6382+
# 971| ValueCategory = lvalue
6383+
# 971| 1: 7
6384+
# 971| Type = int
6385+
# 971| Value = 7
6386+
# 971| ValueCategory = prvalue
6387+
# 973| 2: if (...) ...
6388+
# 973| 0: (condition decl)
6389+
# 973| Type = bool
6390+
# 973| ValueCategory = prvalue
6391+
# 973| 0: (bool)...
6392+
# 973| Conversion = conversion to bool
6393+
# 973| Type = bool
6394+
# 973| ValueCategory = prvalue
6395+
# 973| expr: p
6396+
# 973| Type = int *
6397+
# 973| ValueCategory = prvalue(load)
6398+
# 973| 1: { ... }
6399+
# 974| 0: ExprStmt
6400+
# 974| 0: ... = ...
6401+
# 974| Type = int
6402+
# 974| ValueCategory = lvalue
6403+
# 974| 0: * ...
6404+
# 974| Type = int
6405+
# 974| ValueCategory = lvalue
6406+
# 974| 0: p
6407+
# 974| Type = int *
6408+
# 974| ValueCategory = prvalue(load)
6409+
# 974| 1: 2
6410+
# 974| Type = int
6411+
# 974| Value = 2
6412+
# 974| ValueCategory = prvalue
6413+
# 976| 1: return ...
6414+
# 978| WhileStmtWithDeclaration(int, int) -> void
6415+
# 978| params:
6416+
# 978| 0: x
6417+
# 978| Type = int
6418+
# 978| 1: y
6419+
# 978| Type = int
6420+
# 978| body: { ... }
6421+
# 979| 0: while (...) ...
6422+
# 979| 0: (condition decl)
6423+
# 979| Type = bool
6424+
# 979| ValueCategory = prvalue
6425+
# 979| 0: b
6426+
# 979| Type = bool
6427+
# 979| ValueCategory = prvalue(load)
6428+
# 979| 1: { ... }
6429+
# 981| 1: while (...) ...
6430+
# 981| 0: (condition decl)
6431+
# 981| Type = bool
6432+
# 981| ValueCategory = prvalue
6433+
# 981| 0: (bool)...
6434+
# 981| Conversion = conversion to bool
6435+
# 981| Type = bool
6436+
# 981| ValueCategory = prvalue
6437+
# 981| expr: z
6438+
# 981| Type = int
6439+
# 981| ValueCategory = prvalue(load)
6440+
# 981| 1: { ... }
6441+
# 983| 2: while (...) ...
6442+
# 983| 0: (condition decl)
6443+
# 983| Type = bool
6444+
# 983| ValueCategory = prvalue
6445+
# 983| 0: (bool)...
6446+
# 983| Conversion = conversion to bool
6447+
# 983| Type = bool
6448+
# 983| ValueCategory = prvalue
6449+
# 983| expr: p
6450+
# 983| Type = int *
6451+
# 983| ValueCategory = prvalue(load)
6452+
# 983| 1: { ... }
6453+
# 985| 3: return ...

0 commit comments

Comments
 (0)