@@ -12,7 +12,95 @@ private import semmle.code.cpp.ir.ValueNumbering
12
12
module SemanticExprConfig {
13
13
class Location = Cpp:: Location ;
14
14
15
- class Expr = IR:: Instruction ;
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
+ exists ( IR:: ConvertInstruction convert |
26
+ this = convert and
27
+ tFrom = getSemanticType ( convert .getUnary ( ) .getResultIRType ( ) ) and
28
+ tTo = getSemanticType ( convert .getResultIRType ( ) )
29
+ )
30
+ or
31
+ exists ( IR:: CopyValueInstruction copy |
32
+ this = copy and
33
+ tFrom = getSemanticType ( copy .getUnary ( ) .getResultIRType ( ) ) and
34
+ tTo = getSemanticType ( copy .getResultIRType ( ) )
35
+ )
36
+ }
37
+ }
38
+
39
+ /**
40
+ * Gets a conversion-like instruction that consumes `op`, and
41
+ * which is guaranteed to not overflow.
42
+ */
43
+ private IR:: Instruction safeConversion ( IR:: Operand op ) {
44
+ exists ( Conversion conv , SemType tFrom , SemType tTo |
45
+ conv .converts ( tFrom , tTo ) and
46
+ conversionCannotOverflow ( tFrom , tTo ) and
47
+ conv .getUnaryOperand ( ) = op and
48
+ result = conv
49
+ )
50
+ }
51
+
52
+ /** Holds if `i1 = i2` or if `i2` is a safe conversion that consumes `i1`. */
53
+ private predicate idOrSafeConversion ( IR:: Instruction i1 , IR:: Instruction i2 ) {
54
+ not i1 .getResultIRType ( ) instanceof IR:: IRVoidType and
55
+ (
56
+ i1 = i2
57
+ or
58
+ i2 = safeConversion ( i1 .getAUse ( ) )
59
+ )
60
+ }
61
+
62
+ module Equiv = QlBuiltins:: EquivalenceRelation< IR:: Instruction , idOrSafeConversion / 2 > ;
63
+
64
+ /**
65
+ * The expressions on which we perform range analysis.
66
+ */
67
+ class Expr extends Equiv:: EquivalenceClass {
68
+ /** Gets the n'th instruction in this equivalence class. */
69
+ private IR:: Instruction getInstruction ( int n ) {
70
+ result =
71
+ rank [ n + 1 ] ( IR:: Instruction instr , int i , IR:: IRBlock block |
72
+ this = Equiv:: getEquivalenceClass ( instr ) and block .getInstruction ( i ) = instr
73
+ |
74
+ instr order by i
75
+ )
76
+ }
77
+
78
+ /** Gets a textual representation of this element. */
79
+ string toString ( ) { result = this .getUnconverted ( ) .toString ( ) }
80
+
81
+ /** Gets the basic block of this expression. */
82
+ IR:: IRBlock getBlock ( ) { result = getInstruction ( 0 ) .getBlock ( ) }
83
+
84
+ /** Gets the unconverted instruction associated with this expression. */
85
+ IR:: Instruction getUnconverted ( ) { result = this .getInstruction ( 0 ) }
86
+
87
+ /**
88
+ * Gets the final instruction associated with this expression. This
89
+ * represents the result after applying all the safe conversions.
90
+ */
91
+ IR:: Instruction getConverted ( ) {
92
+ exists ( int n |
93
+ result = this .getInstruction ( n ) and
94
+ not exists ( this .getInstruction ( n + 1 ) )
95
+ )
96
+ }
97
+
98
+ /** Gets the type of the result produced by this instruction. */
99
+ IR:: IRType getResultIRType ( ) { result = this .getConverted ( ) .getResultIRType ( ) }
100
+
101
+ /** Gets the location of the source code for this expression. */
102
+ Location getLocation ( ) { result = this .getUnconverted ( ) .getLocation ( ) }
103
+ }
16
104
17
105
SemBasicBlock getExprBasicBlock ( Expr e ) { result = getSemanticBasicBlock ( e .getBlock ( ) ) }
18
106
0 commit comments