@@ -9,22 +9,48 @@ private import semmle.code.cpp.ir.ValueNumbering
99private import semmle.code.cpp.ir.implementation.raw.internal.TranslatedExpr
1010private import semmle.code.cpp.ir.implementation.raw.internal.InstructionTag
1111
12+ /**
13+ * Variant of valueNumber that accounts for conversions.
14+ * Note: this predicate is defined in IRGuards to take advantage of
15+ * IRGuards definition of int_value.
16+ */
17+ ValueNumber valueNumberWithConversions ( Instruction instr ) {
18+ exists ( ValueNumber vn | vn = valueNumber ( instr ) |
19+ // GVN using valueNumber directly
20+ result = vn
21+ or
22+ // GVN for the ConvertInstruction conversion
23+ result = valueNumberWithConversions ( vn .getAnInstruction ( ) .( ConvertInstruction ) .getUnary ( ) )
24+ or
25+ // GVN for the CompareNEInstruction conversion for a comparison with 0 (conversion of value to boolean in c)
26+ exists ( CompareNEInstruction cmp | cmp = vn .getAnInstruction ( ) |
27+ result = valueNumberWithConversions ( cmp .getLeft ( ) ) and
28+ int_value ( cmp .getRight ( ) ) = 0
29+ )
30+ )
31+ }
32+
1233/**
1334 * Returns `instr` or any instruction used to define `instr`.
1435 */
36+ pragma [ inline]
1537private Instruction getDerivedInstruction ( Instruction instr ) {
16- // The instruction itself
1738 result = instr
1839 or
19- // or the GVN definition for the current instruction
2040 result = valueNumber ( instr ) .getAnInstruction ( ) .( StoreInstruction ) .getSourceValue ( )
2141 or
22- // Special handling for conversions
23- result =
24- getDerivedInstruction ( valueNumber ( instr ) .getAnInstruction ( ) .( CompareNEInstruction ) .getLeft ( ) )
42+ result = derivedThroughConversion ( valueNumber ( instr ) )
43+ }
44+
45+ private Instruction derivedThroughConversion ( ValueNumber vn ) {
46+ // GVN for the ConvertInstruction conversion
47+ result = getDerivedInstruction ( vn .getAnInstruction ( ) .( ConvertInstruction ) .getUnary ( ) )
2548 or
26- result =
27- getDerivedInstruction ( valueNumber ( instr ) .getAnInstruction ( ) .( ConvertInstruction ) .getUnary ( ) )
49+ // GVN for the CompareNEInstruction conversion for a comparison with 0 (conversion of value to boolean in c)
50+ exists ( CompareNEInstruction comp | comp = vn .getAnInstruction ( ) |
51+ result = getDerivedInstruction ( comp .getLeft ( ) ) and
52+ int_value ( comp .getRight ( ) ) = 0
53+ )
2854}
2955
3056/**
@@ -832,7 +858,7 @@ private predicate unary_compares_eq(
832858 exists ( Instruction derived | derived = getDerivedInstruction ( test ) |
833859 /* The simple case where the test *is* the comparison so areEqual = testIsTrue xor eq. */
834860 exists ( AbstractValue v |
835- unary_simple_comparison_eq ( derived , k , inNonZeroCase , v ) and op .getDef ( ) = test
861+ unary_simple_comparison_eq ( derived , k , inNonZeroCase , v ) and op .getDef ( ) = derived
836862 |
837863 areEqual = true and value = v
838864 or
@@ -897,6 +923,18 @@ private predicate unary_simple_comparison_eq(
897923 inNonZeroCase = false
898924 )
899925 or
926+ (
927+ exists ( BinaryLogicalOperation e | e .getAnOperand ( ) = test .getUnconvertedResultExpression ( ) )
928+ or
929+ exists ( UnaryLogicalOperation e | e .getAnOperand ( ) = test .getUnconvertedResultExpression ( ) )
930+ or
931+ exists ( IfStmt i | i .getCondition ( ) = test .getUnconvertedResultExpression ( ) )
932+ or
933+ exists ( Loop i | i .getCondition ( ) = test .getUnconvertedResultExpression ( ) )
934+ or
935+ exists ( ConditionalExpr c | c .getCondition ( ) = test .getUnconvertedResultExpression ( ) )
936+ // Todo recursive conditionalExpr in guard
937+ ) and
900938 // Any instruction with an integral type could potentially be part of a
901939 // check for nullness when used in a guard. So we include all integral
902940 // typed instructions here. However, since some of these instructions are
@@ -941,6 +979,8 @@ private predicate unary_simple_comparison_eq(
941979 value .( BooleanValue ) .getValue ( ) = false and
942980 inNonZeroCase = false
943981 )
982+ // Has to be in a boolean operator (operanad of OR or AND)
983+ // has to be a 'guard' (loop, if, switch, ternary)
944984}
945985
946986/** A call to the builtin operation `__builtin_expect`. */
0 commit comments