Skip to content

Commit d544f47

Browse files
committed
C++: Simplify the definition of 'SemExpr' by instead making non-overflowing conversions copy value expressions.
1 parent 4e214e1 commit d544f47

File tree

3 files changed

+27
-90
lines changed

3 files changed

+27
-90
lines changed

cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/SimpleRangeAnalysis.qll

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ predicate exprMightOverflowNegatively(Expr expr) {
100100
lowerBound(expr) < exprMinVal(expr)
101101
or
102102
exists(SemanticExprConfig::Expr semExpr |
103-
semExpr.getUnconverted().getAst() = expr and
103+
semExpr.getAst() = expr and
104104
ConstantStage::potentiallyOverflowingExpr(false, semExpr) and
105105
not ConstantStage::initialBounded(semExpr, _, _, false, _, _, _)
106106
)
@@ -126,7 +126,7 @@ predicate exprMightOverflowPositively(Expr expr) {
126126
upperBound(expr) > exprMaxVal(expr)
127127
or
128128
exists(SemanticExprConfig::Expr semExpr |
129-
semExpr.getUnconverted().getAst() = expr and
129+
semExpr.getAst() = expr and
130130
ConstantStage::potentiallyOverflowingExpr(true, semExpr) and
131131
not ConstantStage::initialBounded(semExpr, _, _, true, _, _, _)
132132
)

cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/internal/semantic/SemanticExpr.qll

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
private import Semantic
66
private import SemanticExprSpecific::SemanticExprConfig as Specific
7+
private import SemanticType
78

89
/**
910
* An language-neutral expression.
@@ -241,8 +242,21 @@ class SemConvertExpr extends SemUnaryExpr {
241242
SemConvertExpr() { opcode instanceof Opcode::Convert }
242243
}
243244

245+
private import semmle.code.cpp.ir.IR as IR
246+
247+
/** A conversion instruction which is guaranteed to not overflow. */
248+
private class SafeConversion extends IR::ConvertInstruction {
249+
SafeConversion() {
250+
exists(SemType tFrom, SemType tTo |
251+
tFrom = getSemanticType(super.getUnary().getResultIRType()) and
252+
tTo = getSemanticType(super.getResultIRType()) and
253+
conversionCannotOverflow(tFrom, tTo)
254+
)
255+
}
256+
}
257+
244258
class SemCopyValueExpr extends SemUnaryExpr {
245-
SemCopyValueExpr() { opcode instanceof Opcode::CopyValue }
259+
SemCopyValueExpr() { opcode instanceof Opcode::CopyValue or this instanceof SafeConversion }
246260
}
247261

248262
class SemNegateExpr extends SemUnaryExpr {

cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/internal/semantic/SemanticExprSpecific.qll

Lines changed: 10 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -12,87 +12,10 @@ private import semmle.code.cpp.ir.ValueNumbering
1212
module SemanticExprConfig {
1313
class Location = Cpp::Location;
1414

15-
/** A `ConvertInstruction` or a `CopyValueInstruction`. */
16-
private class Conversion extends IR::UnaryInstruction {
17-
Conversion() {
18-
this instanceof IR::CopyValueInstruction
19-
or
20-
this instanceof IR::ConvertInstruction
21-
}
22-
23-
/** Holds if this instruction converts a value of type `tFrom` to a value of type `tTo`. */
24-
predicate converts(SemType tFrom, SemType tTo) {
25-
tFrom = getSemanticType(this.getUnary().getResultIRType()) and
26-
tTo = getSemanticType(this.getResultIRType())
27-
}
28-
}
29-
30-
/**
31-
* Gets a conversion-like instruction that consumes `op`, and
32-
* which is guaranteed to not overflow.
33-
*/
34-
private IR::Instruction safeConversion(IR::Operand op) {
35-
exists(Conversion conv, SemType tFrom, SemType tTo |
36-
conv.converts(tFrom, tTo) and
37-
conversionCannotOverflow(tFrom, tTo) and
38-
conv.getUnaryOperand() = op and
39-
result = conv
40-
)
41-
}
42-
43-
/** Holds if `i1 = i2` or if `i2` is a safe conversion that consumes `i1`. */
44-
private predicate idOrSafeConversion(IR::Instruction i1, IR::Instruction i2) {
45-
not i1.getResultIRType() instanceof IR::IRVoidType and
46-
(
47-
i1 = i2
48-
or
49-
i2 = safeConversion(i1.getAUse()) and
50-
i1.getBlock() = i2.getBlock()
51-
)
52-
}
53-
54-
module Equiv = QlBuiltins::EquivalenceRelation<IR::Instruction, idOrSafeConversion/2>;
55-
5615
/**
5716
* The expressions on which we perform range analysis.
5817
*/
59-
class Expr extends Equiv::EquivalenceClass {
60-
/** Gets the n'th instruction in this equivalence class. */
61-
private IR::Instruction getInstruction(int n) {
62-
result =
63-
rank[n + 1](IR::Instruction instr, int i, IR::IRBlock block |
64-
this = Equiv::getEquivalenceClass(instr) and block.getInstruction(i) = instr
65-
|
66-
instr order by i
67-
)
68-
}
69-
70-
/** Gets a textual representation of this element. */
71-
string toString() { result = this.getUnconverted().toString() }
72-
73-
/** Gets the basic block of this expression. */
74-
IR::IRBlock getBlock() { result = this.getUnconverted().getBlock() }
75-
76-
/** Gets the unconverted instruction associated with this expression. */
77-
IR::Instruction getUnconverted() { result = this.getInstruction(0) }
78-
79-
/**
80-
* Gets the final instruction associated with this expression. This
81-
* represents the result after applying all the safe conversions.
82-
*/
83-
IR::Instruction getConverted() {
84-
exists(int n |
85-
result = this.getInstruction(n) and
86-
not exists(this.getInstruction(n + 1))
87-
)
88-
}
89-
90-
/** Gets the type of the result produced by this instruction. */
91-
IR::IRType getResultIRType() { result = this.getConverted().getResultIRType() }
92-
93-
/** Gets the location of the source code for this expression. */
94-
Location getLocation() { result = this.getUnconverted().getLocation() }
95-
}
18+
class Expr = IR::Instruction;
9619

9720
SemBasicBlock getExprBasicBlock(Expr e) { result = getSemanticBasicBlock(e.getBlock()) }
9821

@@ -139,12 +62,12 @@ module SemanticExprConfig {
13962

14063
predicate stringLiteral(Expr expr, SemType type, string value) {
14164
anyConstantExpr(expr, type, value) and
142-
expr.getUnconverted() instanceof IR::StringConstantInstruction
65+
expr instanceof IR::StringConstantInstruction
14366
}
14467

14568
predicate binaryExpr(Expr expr, Opcode opcode, SemType type, Expr leftOperand, Expr rightOperand) {
14669
exists(IR::BinaryInstruction instr |
147-
instr = expr.getUnconverted() and
70+
instr = expr and
14871
type = getSemanticType(instr.getResultIRType()) and
14972
leftOperand = getSemanticExpr(instr.getLeft()) and
15073
rightOperand = getSemanticExpr(instr.getRight()) and
@@ -154,14 +77,14 @@ module SemanticExprConfig {
15477
}
15578

15679
predicate unaryExpr(Expr expr, Opcode opcode, SemType type, Expr operand) {
157-
exists(IR::UnaryInstruction instr | instr = expr.getUnconverted() |
80+
exists(IR::UnaryInstruction instr | instr = expr |
15881
type = getSemanticType(instr.getResultIRType()) and
15982
operand = getSemanticExpr(instr.getUnary()) and
16083
// REVIEW: Merge the two operand types.
16184
opcode.toString() = instr.getOpcode().toString()
16285
)
16386
or
164-
exists(IR::StoreInstruction instr | instr = expr.getUnconverted() |
87+
exists(IR::StoreInstruction instr | instr = expr |
16588
type = getSemanticType(instr.getResultIRType()) and
16689
operand = getSemanticExpr(instr.getSourceValue()) and
16790
opcode instanceof Opcode::Store
@@ -170,13 +93,13 @@ module SemanticExprConfig {
17093

17194
predicate nullaryExpr(Expr expr, Opcode opcode, SemType type) {
17295
exists(IR::LoadInstruction load |
173-
load = expr.getUnconverted() and
96+
load = expr and
17497
type = getSemanticType(load.getResultIRType()) and
17598
opcode instanceof Opcode::Load
17699
)
177100
or
178101
exists(IR::InitializeParameterInstruction init |
179-
init = expr.getUnconverted() and
102+
init = expr and
180103
type = getSemanticType(init.getResultIRType()) and
181104
opcode instanceof Opcode::InitializeParameter
182105
)
@@ -290,9 +213,9 @@ module SemanticExprConfig {
290213
}
291214

292215
Expr getAUse(SsaVariable v) {
293-
result.getUnconverted().(IR::LoadInstruction).getSourceValue() = v.asInstruction()
216+
result.(IR::LoadInstruction).getSourceValue() = v.asInstruction()
294217
or
295-
result.getUnconverted() = v.asPointerArithGuard().getAnInstruction()
218+
result = v.asPointerArithGuard().getAnInstruction()
296219
}
297220

298221
SemType getSsaVariableType(SsaVariable v) {
@@ -433,7 +356,7 @@ module SemanticExprConfig {
433356
}
434357

435358
/** Gets the expression associated with `instr`. */
436-
SemExpr getSemanticExpr(IR::Instruction instr) { result = Equiv::getEquivalenceClass(instr) }
359+
SemExpr getSemanticExpr(IR::Instruction instr) { result = instr }
437360
}
438361

439362
predicate getSemanticExpr = SemanticExprConfig::getSemanticExpr/1;

0 commit comments

Comments
 (0)