Skip to content

Commit 00ff2bb

Browse files
Merge pull request #1554 from jbj/ir-ErrorExpr
C++ IR: support for translating ErrorExpr
2 parents 23001d5 + 70f81ba commit 00ff2bb

File tree

9 files changed

+138
-2
lines changed

9 files changed

+138
-2
lines changed

cpp/ql/src/semmle/code/cpp/ir/implementation/Opcode.qll

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
private newtype TOpcode =
22
TNoOp() or
33
TUninitialized() or
4+
TError() or
45
TInitializeParameter() or
56
TInitializeThis() or
67
TEnterFunction() or
@@ -147,6 +148,7 @@ abstract class BufferAccessOpcode extends MemoryAccessOpcode {}
147148
module Opcode {
148149
class NoOp extends Opcode, TNoOp { override final string toString() { result = "NoOp" } }
149150
class Uninitialized extends MemoryAccessOpcode, TUninitialized { override final string toString() { result = "Uninitialized" } }
151+
class Error extends Opcode, TError { override final string toString() { result = "Error" } }
150152
class InitializeParameter extends MemoryAccessOpcode, TInitializeParameter { override final string toString() { result = "InitializeParameter" } }
151153
class InitializeThis extends Opcode, TInitializeThis { override final string toString() { result = "InitializeThis" } }
152154
class EnterFunction extends Opcode, TEnterFunction { override final string toString() { result = "EnterFunction" } }

cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -702,6 +702,22 @@ class FieldAddressInstruction extends FieldInstruction {
702702
}
703703
}
704704

705+
/**
706+
* An instruction that produces a well-defined but unknown result and has
707+
* unknown side effects, including side effects that are not conservatively
708+
* modeled in the SSA graph.
709+
*
710+
* This type of instruction appears when there is an `ErrorExpr` in the AST,
711+
* meaning that the extractor could not understand the expression and therefore
712+
* produced a partial AST. Queries that give alerts when some action is _not_
713+
* taken may want to ignore any function that contains an `ErrorInstruction`.
714+
*/
715+
class ErrorInstruction extends Instruction {
716+
ErrorInstruction() {
717+
getOpcode() instanceof Opcode::Error
718+
}
719+
}
720+
705721
class UninitializedInstruction extends VariableInstruction {
706722
UninitializedInstruction() {
707723
getOpcode() instanceof Opcode::Uninitialized

cpp/ql/src/semmle/code/cpp/ir/implementation/raw/Instruction.qll

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -702,6 +702,22 @@ class FieldAddressInstruction extends FieldInstruction {
702702
}
703703
}
704704

705+
/**
706+
* An instruction that produces a well-defined but unknown result and has
707+
* unknown side effects, including side effects that are not conservatively
708+
* modeled in the SSA graph.
709+
*
710+
* This type of instruction appears when there is an `ErrorExpr` in the AST,
711+
* meaning that the extractor could not understand the expression and therefore
712+
* produced a partial AST. Queries that give alerts when some action is _not_
713+
* taken may want to ignore any function that contains an `ErrorInstruction`.
714+
*/
715+
class ErrorInstruction extends Instruction {
716+
ErrorInstruction() {
717+
getOpcode() instanceof Opcode::Error
718+
}
719+
}
720+
705721
class UninitializedInstruction extends VariableInstruction {
706722
UninitializedInstruction() {
707723
getOpcode() instanceof Opcode::Uninitialized

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

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,13 @@ private predicate ignoreExprOnly(Expr expr) {
8484
// Ignore the allocator call, because we always synthesize it. Don't ignore
8585
// its arguments, though, because we use them as part of the synthesis.
8686
newExpr.getAllocatorCall() = expr
87-
) or
87+
)
88+
or
89+
// The extractor deliberately emits an `ErrorExpr` as the first argument to
90+
// the allocator call, if any, of a `NewOrNewArrayExpr`. That `ErrorExpr`
91+
// should not be translated.
92+
exists(NewOrNewArrayExpr new | expr = new.getAllocatorCall().getArgument(0))
93+
or
8894
not translateFunction(expr.getEnclosingFunction())
8995
or
9096
// We do not yet translate destructors properly, so for now we ignore the

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

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2862,3 +2862,29 @@ class TranslatedStmtExpr extends TranslatedNonConstantExpr {
28622862
result = getTranslatedStmt(expr.getStmt())
28632863
}
28642864
}
2865+
2866+
class TranslatedErrorExpr extends TranslatedSingleInstructionExpr {
2867+
override ErrorExpr expr;
2868+
2869+
override final Instruction getFirstInstruction() {
2870+
result = getInstruction(OnlyInstructionTag())
2871+
}
2872+
2873+
override final TranslatedElement getChild(int id) { none() }
2874+
2875+
override final Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
2876+
tag = OnlyInstructionTag() and
2877+
result = getParent().getChildSuccessor(this) and
2878+
kind instanceof GotoEdge
2879+
}
2880+
2881+
override final Instruction getChildSuccessor(TranslatedElement child) { none() }
2882+
2883+
override final Instruction getInstructionOperand(InstructionTag tag, OperandTag operandTag) {
2884+
none()
2885+
}
2886+
2887+
override final Opcode getOpcode() {
2888+
result instanceof Opcode::Error
2889+
}
2890+
}

cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -702,6 +702,22 @@ class FieldAddressInstruction extends FieldInstruction {
702702
}
703703
}
704704

705+
/**
706+
* An instruction that produces a well-defined but unknown result and has
707+
* unknown side effects, including side effects that are not conservatively
708+
* modeled in the SSA graph.
709+
*
710+
* This type of instruction appears when there is an `ErrorExpr` in the AST,
711+
* meaning that the extractor could not understand the expression and therefore
712+
* produced a partial AST. Queries that give alerts when some action is _not_
713+
* taken may want to ignore any function that contains an `ErrorInstruction`.
714+
*/
715+
class ErrorInstruction extends Instruction {
716+
ErrorInstruction() {
717+
getOpcode() instanceof Opcode::Error
718+
}
719+
}
720+
705721
class UninitializedInstruction extends VariableInstruction {
706722
UninitializedInstruction() {
707723
getOpcode() instanceof Opcode::Uninitialized

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

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,34 @@ bad_asts.cpp:
190190
# 27| Type = const Point &
191191
# 27| ValueCategory = prvalue(load)
192192
# 28| 1: return ...
193+
# 30| void Bad::errorExpr()
194+
# 30| params:
195+
# 30| body: { ... }
196+
# 31| 0: declaration
197+
# 31| 0: definition of intref
198+
# 31| Type = int &
199+
# 31| init: initializer for intref
200+
# 31| expr: <error expr>
201+
# 31| Type = error
202+
# 31| ValueCategory = prvalue
203+
# 32| 1: declaration
204+
# 32| 0: definition of x
205+
# 32| Type = int
206+
# 32| init: initializer for x
207+
# 32| expr: <error expr>
208+
# 32| Type = error
209+
# 32| ValueCategory = prvalue
210+
# 33| 2: ExprStmt
211+
# 33| 0: ... = ...
212+
# 33| Type = int
213+
# 33| ValueCategory = lvalue
214+
# 33| 0: x
215+
# 33| Type = int
216+
# 33| ValueCategory = lvalue
217+
#-----| 1: <error expr>
218+
#-----| Type = error
219+
#-----| ValueCategory = prvalue(load)
220+
# 34| 3: return ...
193221
clang.cpp:
194222
# 5| int* globalIntAddress()
195223
# 5| params:

cpp/ql/test/library-tests/ir/ir/bad_asts.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// semmle-extractor-options: -std=c++17
1+
// semmle-extractor-options: -std=c++17 --expect_errors
22

33
// Test cases that illustrate known bad ASTs that we have to work around in IR generation.
44
namespace Bad {
@@ -26,4 +26,10 @@ namespace Bad {
2626
void CallCopyConstructor(const Point& a) {
2727
Point b = a; // Copy constructor contains literal expressions with no values.
2828
}
29+
30+
void errorExpr() {
31+
int &intref = 0;
32+
int x = 0[0];
33+
x = 1[1];
34+
}
2935
}

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

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,26 @@ bad_asts.cpp:
4848
# 26| v0_13(void) = UnmodeledUse : mu*
4949
# 26| v0_14(void) = ExitFunction :
5050

51+
# 30| void Bad::errorExpr()
52+
# 30| Block 0
53+
# 30| v0_0(void) = EnterFunction :
54+
# 30| mu0_1(unknown) = AliasedDefinition :
55+
# 30| mu0_2(unknown) = UnmodeledDefinition :
56+
# 31| r0_3(glval<int &>) = VariableAddress[intref] :
57+
# 31| r0_4(error) = Error :
58+
# 31| mu0_5(int &) = Store : &:r0_3, r0_4
59+
# 32| r0_6(glval<int>) = VariableAddress[x] :
60+
# 32| r0_7(error) = Error :
61+
# 32| mu0_8(int) = Store : &:r0_6, r0_7
62+
#-----| r0_9(glval<error>) = Error :
63+
#-----| r0_10(error) = Load : &:r0_9, ~mu0_2
64+
# 33| r0_11(glval<int>) = VariableAddress[x] :
65+
# 33| mu0_12(int) = Store : &:r0_11, r0_10
66+
# 34| v0_13(void) = NoOp :
67+
# 30| v0_14(void) = ReturnVoid :
68+
# 30| v0_15(void) = UnmodeledUse : mu*
69+
# 30| v0_16(void) = ExitFunction :
70+
5171
clang.cpp:
5272
# 5| int* globalIntAddress()
5373
# 5| Block 0

0 commit comments

Comments
 (0)