@@ -12,7 +12,95 @@ private import semmle.code.cpp.ir.ValueNumbering
1212module SemanticExprConfig {
1313 class Location = Cpp:: Location ;
1414
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+ }
16104
17105 SemBasicBlock getExprBasicBlock ( Expr e ) { result = getSemanticBasicBlock ( e .getBlock ( ) ) }
18106
0 commit comments