baloghadamsoftware updated this revision to Diff 202191.
baloghadamsoftware added a comment.
Herald added a subscriber: Charusso.

Multipliers limited to less or equal to 255.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D50256/new/

https://reviews.llvm.org/D50256

Files:
  include/clang/StaticAnalyzer/Core/PathSensitive/RangedConstraintManager.h
  lib/StaticAnalyzer/Core/RangeConstraintManager.cpp
  lib/StaticAnalyzer/Core/RangedConstraintManager.cpp
  test/Analysis/multiplicative-folding.c

Index: test/Analysis/multiplicative-folding.c
===================================================================
--- /dev/null
+++ test/Analysis/multiplicative-folding.c
@@ -0,0 +1,686 @@
+// RUN: %clang_analyze_cc1 --std=c11 -analyzer-checker=core,debug.ExprInspection -verify %s
+
+void clang_analyzer_eval(int);
+void clang_analyzer_warnIfReached(void);
+
+#define UINT_MAX (~0U)
+#define INT_MAX (int)(UINT_MAX & (UINT_MAX >> 1))
+#define INT_MIN (-INT_MAX - 1)
+
+#define ULONG_LONG_MAX (~0UL)
+#define LONG_LONG_MAX (long long)(ULONG_LONG_MAX & (ULONG_LONG_MAX >> 1))
+#define LONG_LONG_MIN (-LONG_LONG_MAX - 1)
+
+extern void __assert_fail (__const char *__assertion, __const char *__file,
+    unsigned int __line, __const char *__function)
+     __attribute__ ((__noreturn__));
+#define assert(expr) \
+  ((expr)  ? (void)(0)  : __assert_fail (#expr, __FILE__, __LINE__, __func__))
+
+typedef int int32_t;
+typedef unsigned int uint32_t;
+typedef long long int64_t;
+typedef unsigned long long uint64_t;
+
+void signed_multiplication_eq(int32_t n) {
+  if (n * 2 == 3) {
+    clang_analyzer_warnIfReached(); // no-warning
+
+  } else if (n * 2 == 4) {
+    const int32_t C1 = 0x80000002, C2 = 2;
+    
+    assert(C1 * 2 == 4);
+    assert(C2 * 2 == 4);
+
+    clang_analyzer_eval(n == INT_MIN); //expected-warning{{FALSE}}
+    clang_analyzer_eval(n == C1 - 1); //expected-warning{{FALSE}}
+    clang_analyzer_eval(n == C1); //expected-warning{{FALSE}}
+                                  //expected-warning@-1{{TRUE}}
+    clang_analyzer_eval(n == C1 + 1); //expected-warning{{FALSE}}
+    clang_analyzer_eval(n == 0); //expected-warning{{FALSE}}
+    clang_analyzer_eval(n == C2 - 1); //expected-warning{{FALSE}}
+    clang_analyzer_eval(n == C2); //expected-warning{{FALSE}}
+                                  //expected-warning@-1{{TRUE}}
+    clang_analyzer_eval(n == C2 + 1); //expected-warning{{FALSE}}
+    clang_analyzer_eval(n == INT_MAX); //expected-warning{{FALSE}}
+
+  } else if (n * 3 == 4) {
+    const int32_t C1 = 0xaaaaaaac;
+
+    assert(C1 * 3 == 4);
+
+    clang_analyzer_eval(n == INT_MIN); //expected-warning{{FALSE}}
+    clang_analyzer_eval(n == C1 - 1); //expected-warning{{FALSE}}
+    clang_analyzer_eval(n == C1); //expected-warning{{TRUE}}
+    clang_analyzer_eval(n == C1 + 1); //expected-warning{{FALSE}}
+    clang_analyzer_eval(n == 0); //expected-warning{{FALSE}}
+    clang_analyzer_eval(n == INT_MAX); //expected-warning{{FALSE}}
+
+  } else if (n * 4 == -5) {
+    clang_analyzer_warnIfReached(); // no-warning
+
+  } else if (n * 4 == -8) {
+    const int32_t C1 = 0xbffffffe, C2 = 0xfffffffe,
+                  C3 = 0x3ffffffe, C4 = 0x7ffffffe;
+
+    assert(C1 * 4 == -8);
+    assert(C2 * 4 == -8);
+    assert(C3 * 4 == -8);
+    assert(C4 * 4 == -8);
+
+    clang_analyzer_eval(n == INT_MIN); //expected-warning{{FALSE}}
+    clang_analyzer_eval(n == C1 - 1); //expected-warning{{FALSE}}
+    clang_analyzer_eval(n == C1); //expected-warning{{FALSE}}
+                                  //expected-warning@-1{{TRUE}}
+    clang_analyzer_eval(n == C1 + 1); //expected-warning{{FALSE}}
+    clang_analyzer_eval(n == C2 - 1); //expected-warning{{FALSE}}
+    clang_analyzer_eval(n == C2); //expected-warning{{FALSE}}
+                                  //expected-warning@-1{{TRUE}}
+    clang_analyzer_eval(n == C2 + 1); //expected-warning{{FALSE}}
+    clang_analyzer_eval(n == 0); //expected-warning{{FALSE}}
+    clang_analyzer_eval(n == C3 - 1); //expected-warning{{FALSE}}
+    clang_analyzer_eval(n == C3); //expected-warning{{FALSE}}
+                                  //expected-warning@-1{{TRUE}}
+    clang_analyzer_eval(n == C3 + 1); //expected-warning{{FALSE}}
+    clang_analyzer_eval(n == C4 - 1); //expected-warning{{FALSE}}
+    clang_analyzer_eval(n == C4); //expected-warning{{FALSE}}
+                                  //expected-warning@-1{{TRUE}}
+    clang_analyzer_eval(n == C4 + 1); //expected-warning{{FALSE}}
+    clang_analyzer_eval(n == INT_MAX); //expected-warning{{FALSE}}
+
+  } else if (n * 6 == -7) {
+    clang_analyzer_warnIfReached(); // no-warning
+
+  } else if (n * 6 == -2) {
+    const int32_t C1 = 0xd5555555, C2 = 0x55555555;
+
+    assert(C1 * 6 == -2);
+    assert(C2 * 6 == -2);
+
+    clang_analyzer_eval(n == INT_MIN); //expected-warning{{FALSE}}
+    clang_analyzer_eval(n == C1 - 1); //expected-warning{{FALSE}}
+    clang_analyzer_eval(n == C1); //expected-warning{{FALSE}}
+                                  //expected-warning@-1{{TRUE}}
+    clang_analyzer_eval(n == C1 + 1); //expected-warning{{FALSE}}
+    clang_analyzer_eval(n == 0); //expected-warning{{FALSE}}
+    clang_analyzer_eval(n == C2 - 1); //expected-warning{{FALSE}}
+    clang_analyzer_eval(n == C2); //expected-warning{{FALSE}}
+                                  //expected-warning@-1{{TRUE}}
+    clang_analyzer_eval(n == C2 + 1); //expected-warning{{FALSE}}
+    clang_analyzer_eval(n == INT_MAX); //expected-warning{{FALSE}}
+
+  }
+}
+
+void signed_multiplication_eq64(int64_t n) {
+  if (n * 2 == 4) {
+    const int64_t C1 = 0x8000000000000002, C2 = 2;
+
+    assert(C1 * 2 == 4);
+    assert(C2 * 2 == 4);
+
+    clang_analyzer_eval(n == LONG_LONG_MIN); //expected-warning{{FALSE}}
+    clang_analyzer_eval(n == C1 - 1); //expected-warning{{FALSE}}
+    clang_analyzer_eval(n == C1); //expected-warning{{FALSE}}
+                                  //expected-warning@-1{{TRUE}}
+    clang_analyzer_eval(n == C1 + 1); //expected-warning{{FALSE}}
+    clang_analyzer_eval(n == 0); //expected-warning{{FALSE}}
+    clang_analyzer_eval(n == C2 - 1); //expected-warning{{FALSE}}
+    clang_analyzer_eval(n == C2); //expected-warning{{FALSE}}
+                                  //expected-warning@-1{{TRUE}}
+    clang_analyzer_eval(n == C2 + 1); //expected-warning{{FALSE}}
+    clang_analyzer_eval(n == LONG_LONG_MAX); //expected-warning{{FALSE}}
+
+  }
+}
+
+void signed_division_eq(int32_t n) {
+  if (n / 2 == 0) {
+    clang_analyzer_eval(n == INT_MIN); //expected-warning{{FALSE}}
+    clang_analyzer_eval(n == -1); //expected-warning{{FALSE}}
+    clang_analyzer_eval(n == 0); //expected-warning{{TRUE}}
+    clang_analyzer_eval(n == 1); //expected-warning{{FALSE}}
+    clang_analyzer_eval(n == INT_MAX); //expected-warning{{FALSE}}
+
+  } else if (n / 2 == 3) {
+    const int32_t C = 6;
+
+    assert(C / 2 == 3);
+    assert((C + 1) / 2 == 3);
+
+    clang_analyzer_eval(n == INT_MIN); //expected-warning{{FALSE}}
+    clang_analyzer_eval(n == 0); //expected-warning{{FALSE}}
+    clang_analyzer_eval(n == C - 1); //expected-warning{{FALSE}}
+    clang_analyzer_eval(n >= C); //expected-warning{{TRUE}}
+    clang_analyzer_eval(n <= C + 1); //expected-warning{{TRUE}}
+    clang_analyzer_eval(n == C + 2); //expected-warning{{FALSE}}
+    clang_analyzer_eval(n == INT_MAX); //expected-warning{{FALSE}}
+
+  } else if (n / 3 == -5) {
+    const int32_t C = -15;
+
+    assert(C / 3 == -5);
+    assert((C - 2) / 3 == -5);
+
+    clang_analyzer_eval(n == INT_MIN); //expected-warning{{FALSE}}
+    clang_analyzer_eval(n == C - 3); //expected-warning{{FALSE}}
+    clang_analyzer_eval(n >= C - 2); //expected-warning{{TRUE}}
+    clang_analyzer_eval(n <= C); //expected-warning{{TRUE}}
+    clang_analyzer_eval(n == C + 1); //expected-warning{{FALSE}}
+    clang_analyzer_eval(n == 0); //expected-warning{{FALSE}}
+    clang_analyzer_eval(n == INT_MAX); //expected-warning{{FALSE}}
+
+  } else if (n / 2 == INT_MAX / 2 + 1) {
+    clang_analyzer_warnIfReached(); // no-warning
+
+  } else if (n / 3 == INT_MIN / 3 - 1) {
+    clang_analyzer_warnIfReached(); // no-warning
+
+  } else if (n / 4 == INT_MAX) {
+    clang_analyzer_warnIfReached(); // no-warning
+
+  } else if (n / 5 == INT_MIN) {
+    clang_analyzer_warnIfReached(); // no-warning
+
+  }
+}
+
+void unsigned_multiplication_eq(uint32_t n) {
+  if (n * 2 == 3) {
+    clang_analyzer_warnIfReached(); // no-warning
+
+  } else if (n * 2 == 4) {
+    const uint32_t C1 = 2, C2 = 0x80000002;
+    
+    assert(C1 * 2 == 4);
+    assert(C2 * 2 == 4);
+
+    clang_analyzer_eval(n == 0); //expected-warning{{FALSE}}
+    clang_analyzer_eval(n == C1 - 1); //expected-warning{{FALSE}}
+    clang_analyzer_eval(n == C1); //expected-warning{{FALSE}}
+                                  //expected-warning@-1{{TRUE}}
+    clang_analyzer_eval(n == C1 + 1); //expected-warning{{FALSE}}
+    clang_analyzer_eval(n == C2 - 1); //expected-warning{{FALSE}}
+    clang_analyzer_eval(n == C2); //expected-warning{{FALSE}}
+                                  //expected-warning@-1{{TRUE}}
+    clang_analyzer_eval(n == C2 + 1); //expected-warning{{FALSE}}
+    clang_analyzer_eval(n == UINT_MAX); //expected-warning{{FALSE}}
+
+  } else if (n * 3 == 4) {
+    const uint32_t C1 = 0xaaaaaaac;
+
+    assert(C1 * 3 == 4);
+
+    clang_analyzer_eval(n == 0); //expected-warning{{FALSE}}
+    clang_analyzer_eval(n == C1 - 1); //expected-warning{{FALSE}}
+    clang_analyzer_eval(n == C1); //expected-warning{{TRUE}}
+    clang_analyzer_eval(n == C1 + 1); //expected-warning{{FALSE}}
+    clang_analyzer_eval(n == UINT_MAX); //expected-warning{{FALSE}}
+
+  }
+}
+
+void unsigned_division_eq(uint32_t n) {
+  if (n / 2 == 0) {
+    clang_analyzer_eval(n == -1); //expected-warning{{FALSE}}
+    clang_analyzer_eval(n == 0); //expected-warning{{TRUE}}
+    clang_analyzer_eval(n == 1); //expected-warning{{FALSE}}
+    clang_analyzer_eval(n == UINT_MAX); //expected-warning{{FALSE}}
+
+  } else if (n / 2 == 3) {
+    const uint32_t C = 6;
+
+    assert(C / 2 == 3);
+    assert((C + 1) / 2 == 3);
+
+    clang_analyzer_eval(n == 0); //expected-warning{{FALSE}}
+    clang_analyzer_eval(n == C - 1); //expected-warning{{FALSE}}
+    clang_analyzer_eval(n >= C); //expected-warning{{TRUE}}
+    clang_analyzer_eval(n <= C + 1); //expected-warning{{TRUE}}
+    clang_analyzer_eval(n == C + 2); //expected-warning{{FALSE}}
+    clang_analyzer_eval(n == UINT_MAX); //expected-warning{{FALSE}}
+
+  } else if (n / 2 == UINT_MAX / 2 + 1) {
+    clang_analyzer_warnIfReached(); // no-warning
+
+  } else if (n / 3 == UINT_MAX) {
+    clang_analyzer_warnIfReached(); // no-warning
+
+  }
+}
+
+void signed_multiplication_ne(int32_t n) {
+  if (n * 2 != 3) {
+    clang_analyzer_eval(n == INT_MIN); //expected-warning{{FALSE}}
+                                       //expected-warning@-1{{TRUE}}
+    clang_analyzer_eval(n == 0); //expected-warning{{FALSE}}
+                                 //expected-warning@-1{{TRUE}}
+    clang_analyzer_eval(n == 1); //expected-warning{{FALSE}}
+                                 //expected-warning@-1{{TRUE}}
+    clang_analyzer_eval(n == 2); //expected-warning{{FALSE}}
+                                 //expected-warning@-1{{TRUE}}
+    clang_analyzer_eval(n == 3); //expected-warning{{FALSE}}
+                                 //expected-warning@-1{{TRUE}}
+    clang_analyzer_eval(n == INT_MAX); //expected-warning{{FALSE}}
+                                       //expected-warning@-1{{TRUE}}
+
+    if (n * 2 != 4) {
+      const int32_t C1 = 0x80000002, C2 = 2;
+
+      assert(C1 * 2 == 4);
+      assert(C2 * 2 == 4);
+
+      clang_analyzer_eval(n == INT_MIN); //expected-warning{{FALSE}}
+                                         //expected-warning@-1{{TRUE}}
+      clang_analyzer_eval(n == C1 - 1); //expected-warning{{FALSE}}
+                                        //expected-warning@-1{{TRUE}}
+      clang_analyzer_eval(n == C1); //expected-warning{{FALSE}}
+      clang_analyzer_eval(n == C1 + 1); //expected-warning{{FALSE}}
+                                        //expected-warning@-1{{TRUE}}
+      clang_analyzer_eval(n == 0); //expected-warning{{FALSE}}
+                                   //expected-warning@-1{{TRUE}}
+      clang_analyzer_eval(n == C2 - 1); //expected-warning{{FALSE}}
+                                        //expected-warning@-1{{TRUE}}
+      clang_analyzer_eval(n == C2); //expected-warning{{FALSE}}
+      clang_analyzer_eval(n == C2 + 1); //expected-warning{{FALSE}}
+                                        //expected-warning@-1{{TRUE}}
+      clang_analyzer_eval(n == INT_MAX); //expected-warning{{FALSE}}
+                                         //expected-warning@-1{{TRUE}}
+
+      if (n * 3 != 4) {
+        const int32_t C1 = 0xaaaaaaac;
+
+        assert(C1 * 3 == 4);
+
+        clang_analyzer_eval(n == INT_MIN); //expected-warning{{FALSE}}
+                                           //expected-warning@-1{{TRUE}}
+        clang_analyzer_eval(n == C1 - 1); //expected-warning{{FALSE}}
+                                          //expected-warning@-1{{TRUE}}
+        clang_analyzer_eval(n == C1); //expected-warning{{FALSE}}
+        clang_analyzer_eval(n == C1 + 1); //expected-warning{{FALSE}}
+                                          //expected-warning@-1{{TRUE}}
+        clang_analyzer_eval(n == 0); //expected-warning{{FALSE}}
+                                     //expected-warning@-1{{TRUE}}
+        clang_analyzer_eval(n == INT_MAX); //expected-warning{{FALSE}}
+                                           //expected-warning@-1{{TRUE}}
+
+        if (n * 4 != -5) {
+          clang_analyzer_eval(n == INT_MIN); //expected-warning{{FALSE}}
+                                             //expected-warning@-1{{TRUE}}
+          clang_analyzer_eval(n == -5); //expected-warning{{FALSE}}
+                                        //expected-warning@-1{{TRUE}}
+          clang_analyzer_eval(n == -2); //expected-warning{{FALSE}}
+                                        //expected-warning@-1{{TRUE}}
+          clang_analyzer_eval(n == -1); //expected-warning{{FALSE}}
+                                        //expected-warning@-1{{TRUE}}
+          clang_analyzer_eval(n == 0); //expected-warning{{FALSE}}
+                                       //expected-warning@-1{{TRUE}}
+          clang_analyzer_eval(n == INT_MAX); //expected-warning{{FALSE}}
+                                             //expected-warning@-1{{TRUE}}
+
+          if (n * 4 != -8) {
+            const int32_t C1 = 0xbffffffe, C2 = 0xfffffffe,
+                          C3 = 0x3ffffffe, C4 = 0x7ffffffe;
+
+            assert(C1 * 4 == -8);
+            assert(C2 * 4 == -8);
+            assert(C3 * 4 == -8);
+            assert(C4 * 4 == -8);
+
+            clang_analyzer_eval(n == INT_MIN); //expected-warning{{FALSE}}
+                                               //expected-warning@-1{{TRUE}}
+            clang_analyzer_eval(n == C1 - 1); //expected-warning{{FALSE}}
+                                              //expected-warning@-1{{TRUE}}
+            clang_analyzer_eval(n == C1); //expected-warning{{FALSE}}
+            clang_analyzer_eval(n == C1 + 1); //expected-warning{{FALSE}}
+                                              //expected-warning@-1{{TRUE}}
+            clang_analyzer_eval(n == C2 - 1); //expected-warning{{FALSE}}
+                                              //expected-warning@-1{{TRUE}}
+            clang_analyzer_eval(n == C2); //expected-warning{{FALSE}}
+            clang_analyzer_eval(n == C2 + 1); //expected-warning{{FALSE}}
+                                              //expected-warning@-1{{TRUE}}
+            clang_analyzer_eval(n == 0); //expected-warning{{FALSE}}
+                                         //expected-warning@-1{{TRUE}}
+            clang_analyzer_eval(n == C3 - 1); //expected-warning{{FALSE}}
+                                              //expected-warning@-1{{TRUE}}
+            clang_analyzer_eval(n == C3); //expected-warning{{FALSE}}
+            clang_analyzer_eval(n == C3 + 1); //expected-warning{{FALSE}}
+                                              //expected-warning@-1{{TRUE}}
+            clang_analyzer_eval(n == C4 - 1); //expected-warning{{FALSE}}
+                                              //expected-warning@-1{{TRUE}}
+            clang_analyzer_eval(n == C4); //expected-warning{{FALSE}}
+            clang_analyzer_eval(n == C4 + 1); //expected-warning{{FALSE}}
+                                              //expected-warning@-1{{TRUE}}
+            clang_analyzer_eval(n == INT_MAX); //expected-warning{{FALSE}}
+                                               //expected-warning@-1{{TRUE}}
+
+            if (n * 6 != -7) {
+              clang_analyzer_eval(n == INT_MIN); //expected-warning{{FALSE}}
+                                                 //expected-warning@-1{{TRUE}}
+              clang_analyzer_eval(n == -1); //expected-warning{{FALSE}}
+                                            //expected-warning@-1{{TRUE}}
+              clang_analyzer_eval(n == 0); //expected-warning{{FALSE}}
+                                           //expected-warning@-1{{TRUE}}
+              clang_analyzer_eval(n == INT_MAX); //expected-warning{{FALSE}}
+                                                 //expected-warning@-1{{TRUE}}
+
+              if (n * 6 != -2) {
+                const int32_t C1 = 0xd5555555, C2 = 0x55555555;
+
+                assert(C1 * 6 == -2);
+                assert(C2 * 6 == -2);
+
+                clang_analyzer_eval(n == INT_MIN); //expected-warning{{FALSE}}
+                                                   //expected-warning@-1{{TRUE}}
+                clang_analyzer_eval(n == C1 - 1); //expected-warning{{FALSE}}
+                                                  //expected-warning@-1{{TRUE}}
+                clang_analyzer_eval(n == C1); //expected-warning{{FALSE}}
+                clang_analyzer_eval(n == C1 + 1); //expected-warning{{FALSE}}
+                                                  //expected-warning@-1{{TRUE}}
+                clang_analyzer_eval(n == 0); //expected-warning{{FALSE}}
+                                             //expected-warning@-1{{TRUE}}
+                clang_analyzer_eval(n == C2 - 1); //expected-warning{{FALSE}}
+                                                  //expected-warning@-1{{TRUE}}
+                clang_analyzer_eval(n == C2); //expected-warning{{FALSE}}
+                clang_analyzer_eval(n == C2 + 1); //expected-warning{{FALSE}}
+                                                  //expected-warning@-1{{TRUE}}
+                clang_analyzer_eval(n == INT_MAX); //expected-warning{{FALSE}}
+                                                   //expected-warning@-1{{TRUE}}
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+}
+
+void signed_division_ne(int32_t n) {
+  if (n / 2 != 0) {
+    clang_analyzer_eval(n == INT_MIN); //expected-warning{{FALSE}}
+                                       //expected-warning@-1{{TRUE}}
+    clang_analyzer_eval(n == -1); //expected-warning{{FALSE}}
+                                  //expected-warning@-1{{TRUE}}
+    clang_analyzer_eval(n == 0); //expected-warning{{FALSE}}
+    clang_analyzer_eval(n == 1); //expected-warning{{FALSE}}
+                                 //expected-warning@-1{{TRUE}}
+    clang_analyzer_eval(n == INT_MAX); //expected-warning{{FALSE}}
+                                       //expected-warning@-1{{TRUE}}
+
+    if (n / 2 != 3) {
+      const int32_t C = 6;
+
+      assert(C / 2 == 3);
+      assert((C + 1) / 2 == 3);
+
+      clang_analyzer_eval(n == INT_MIN); //expected-warning{{FALSE}}
+                                         //expected-warning@-1{{TRUE}}
+      clang_analyzer_eval(n == C - 1); //expected-warning{{FALSE}}
+                                       //expected-warning@-1{{TRUE}}
+      clang_analyzer_eval(n == C); //expected-warning{{FALSE}}
+      clang_analyzer_eval(n == C + 1); //expected-warning{{FALSE}}
+      clang_analyzer_eval(n == C + 2); //expected-warning{{FALSE}}
+                                       //expected-warning@-1{{TRUE}}
+      clang_analyzer_eval(n == INT_MAX); //expected-warning{{FALSE}}
+                                         //expected-warning@-1{{TRUE}}
+
+      if (n / 3 != -5) {
+        const int32_t C = -15;
+
+        assert(C / 3 == -5);
+        assert((C - 2) / 3 == -5);
+
+        clang_analyzer_eval(n == INT_MIN); //expected-warning{{FALSE}}
+                                           //expected-warning@-1{{TRUE}}
+        clang_analyzer_eval(n == C - 3); //expected-warning{{FALSE}}
+                                         //expected-warning@-1{{TRUE}}
+        clang_analyzer_eval(n == C - 2); //expected-warning{{FALSE}}
+        clang_analyzer_eval(n == C - 1); //expected-warning{{FALSE}}
+        clang_analyzer_eval(n == C); //expected-warning{{FALSE}}
+        clang_analyzer_eval(n == C + 1); //expected-warning{{FALSE}}
+                                         //expected-warning@-1{{TRUE}}
+        clang_analyzer_eval(n == INT_MAX); //expected-warning{{FALSE}}
+                                           //expected-warning@-1{{TRUE}}
+
+        if (n / 2 != INT_MAX / 2 + 1) {
+          clang_analyzer_eval(n == INT_MIN); //expected-warning{{FALSE}}
+                                             //expected-warning@-1{{TRUE}}
+          clang_analyzer_eval(n == INT_MAX / 2 + 1); //expected-warning{{FALSE}}
+                                                     //expected-warning@-1{{TRUE}}
+          clang_analyzer_eval(n == INT_MAX); //expected-warning{{FALSE}}
+                                             //expected-warning@-1{{TRUE}}
+
+          if (n / 3 != INT_MIN / 3 - 1) {
+            clang_analyzer_eval(n == INT_MIN); //expected-warning{{FALSE}}
+                                               //expected-warning@-1{{TRUE}}
+            clang_analyzer_eval(n == INT_MIN / 3 - 1); //expected-warning{{FALSE}}
+                                                       //expected-warning@-1{{TRUE}}
+            clang_analyzer_eval(n == INT_MAX); //expected-warning{{FALSE}}
+                                               //expected-warning@-1{{TRUE}}
+
+            if (n / 4 != INT_MAX) {
+              clang_analyzer_eval(n == INT_MIN); //expected-warning{{FALSE}}
+                                                 //expected-warning@-1{{TRUE}}
+              clang_analyzer_eval(n == INT_MAX); //expected-warning{{FALSE}}
+                                                 //expected-warning@-1{{TRUE}}
+
+              if (n / 5 != INT_MIN) {
+                clang_analyzer_eval(n == INT_MIN); //expected-warning{{FALSE}}
+                                                   //expected-warning@-1{{TRUE}}
+                clang_analyzer_eval(n == INT_MAX); //expected-warning{{FALSE}}
+                                                   //expected-warning@-1{{TRUE}}
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+}
+
+void unsigned_multiplication_ne(uint32_t n) {
+  if (n * 2 != 3) {
+    clang_analyzer_eval(n == 0); //expected-warning{{FALSE}}
+                                 //expected-warning@-1{{TRUE}}
+    clang_analyzer_eval(n == 1); //expected-warning{{FALSE}}
+                                 //expected-warning@-1{{TRUE}}
+    clang_analyzer_eval(n == 2); //expected-warning{{FALSE}}
+                                 //expected-warning@-1{{TRUE}}
+    clang_analyzer_eval(n == 3); //expected-warning{{FALSE}}
+                                 //expected-warning@-1{{TRUE}}
+    clang_analyzer_eval(n == UINT_MAX); //expected-warning{{FALSE}}
+                                        //expected-warning@-1{{TRUE}}
+
+    if (n * 2 != 4) {
+      const uint32_t C1 = 2, C2 = 0x80000002;
+
+      assert(C1 * 2 == 4);
+      assert(C2 * 2 == 4);
+
+      clang_analyzer_eval(n == 0); //expected-warning{{FALSE}}
+                                   //expected-warning@-1{{TRUE}}
+      clang_analyzer_eval(n == C1 - 1); //expected-warning{{FALSE}}
+                                        //expected-warning@-1{{TRUE}}
+      clang_analyzer_eval(n == C1); //expected-warning{{FALSE}}
+      clang_analyzer_eval(n == C1 + 1); //expected-warning{{FALSE}}
+                                        //expected-warning@-1{{TRUE}}
+      clang_analyzer_eval(n == C2 - 1); //expected-warning{{FALSE}}
+                                        //expected-warning@-1{{TRUE}}
+      clang_analyzer_eval(n == C2); //expected-warning{{FALSE}}
+      clang_analyzer_eval(n == C2 + 1); //expected-warning{{FALSE}}
+                                        //expected-warning@-1{{TRUE}}
+      clang_analyzer_eval(n == UINT_MAX); //expected-warning{{FALSE}}
+                                          //expected-warning@-1{{TRUE}}
+
+      if (n * 3 != 4) {
+        const uint32_t C1 = 0xaaaaaaac;
+
+        assert(C1 * 3 == 4);
+
+        clang_analyzer_eval(n == 0); //expected-warning{{FALSE}}
+                                     //expected-warning@-1{{TRUE}}
+        clang_analyzer_eval(n == C1 - 1); //expected-warning{{FALSE}}
+                                          //expected-warning@-1{{TRUE}}
+        clang_analyzer_eval(n == C1); //expected-warning{{FALSE}}
+        clang_analyzer_eval(n == C1 + 1); //expected-warning{{FALSE}}
+                                          //expected-warning@-1{{TRUE}}
+        clang_analyzer_eval(n == UINT_MAX); //expected-warning{{FALSE}}
+                                            //expected-warning@-1{{TRUE}}
+
+      }
+    }
+  }
+}
+
+void unsigned_division_ne(uint32_t n) {
+  if (n / 2 != 0) {
+    clang_analyzer_eval(n == 0); //expected-warning{{FALSE}}
+    clang_analyzer_eval(n == 1); //expected-warning{{FALSE}}
+                                 //expected-warning@-1{{TRUE}}
+    clang_analyzer_eval(n == UINT_MAX); //expected-warning{{FALSE}}
+                                        //expected-warning@-1{{TRUE}}
+
+    if (n / 2 != 3) {
+      const uint32_t C = 6;
+
+      assert(C / 2 == 3);
+      assert((C + 1) / 2 == 3);
+
+      clang_analyzer_eval(n == C - 1); //expected-warning{{FALSE}}
+                                       //expected-warning@-1{{TRUE}}
+      clang_analyzer_eval(n == C); //expected-warning{{FALSE}}
+      clang_analyzer_eval(n == C + 1); //expected-warning{{FALSE}}
+      clang_analyzer_eval(n == C + 2); //expected-warning{{FALSE}}
+                                       //expected-warning@-1{{TRUE}}
+      clang_analyzer_eval(n == UINT_MAX); //expected-warning{{FALSE}}
+                                          //expected-warning@-1{{TRUE}}
+
+      if (n / 2 != UINT_MAX / 2 + 1) {
+        clang_analyzer_eval(n == UINT_MAX / 2 + 1); //expected-warning{{FALSE}}
+                                                    //expected-warning@-1{{TRUE}}
+        clang_analyzer_eval(n == UINT_MAX); //expected-warning{{FALSE}}
+                                            //expected-warning@-1{{TRUE}}
+
+        if (n / 4 != UINT_MAX) {
+          clang_analyzer_eval(n == UINT_MAX); //expected-warning{{FALSE}}
+                                              //expected-warning@-1{{TRUE}}
+        }
+      }
+    }
+  }
+}
+
+void additive(int32_t n) {
+  if (n * 2 + 1 == 4) {
+    clang_analyzer_warnIfReached(); // no-warning
+
+  } else if (n * 4 - 1 == 15) {
+    const int32_t C1 = 0x80000004, C2 = 0xc0000004, C3 = 4, C4 = 0x40000004;
+
+    assert(C1 * 4 - 1 == 15);
+    assert(C2 * 4 - 1 == 15);
+    assert(C3 * 4 - 1 == 15);
+    assert(C4 * 4 - 1 == 15);
+
+    clang_analyzer_eval(n == INT_MIN); //expected-warning{{FALSE}}
+    clang_analyzer_eval(n == C1 - 1); //expected-warning{{FALSE}}
+    clang_analyzer_eval(n == C1); //expected-warning{{FALSE}}
+                                  //expected-warning@-1{{TRUE}}
+    clang_analyzer_eval(n == C1 + 1); //expected-warning{{FALSE}}
+    clang_analyzer_eval(n == C2 - 1); //expected-warning{{FALSE}}
+    clang_analyzer_eval(n == C2); //expected-warning{{FALSE}}
+                                  //expected-warning@-1{{TRUE}}
+    clang_analyzer_eval(n == C2 + 1); //expected-warning{{FALSE}}
+    clang_analyzer_eval(n == 0); //expected-warning{{FALSE}}
+    clang_analyzer_eval(n == C3 - 1); //expected-warning{{FALSE}}
+    clang_analyzer_eval(n == C3); //expected-warning{{FALSE}}
+                                  //expected-warning@-1{{TRUE}}
+    clang_analyzer_eval(n == C3 + 1); //expected-warning{{FALSE}}
+    clang_analyzer_eval(n == C4 - 1); //expected-warning{{FALSE}}
+    clang_analyzer_eval(n == C4); //expected-warning{{FALSE}}
+                                  //expected-warning@-1{{TRUE}}
+    clang_analyzer_eval(n == C4 + 1); //expected-warning{{FALSE}}
+    clang_analyzer_eval(n == INT_MAX); //expected-warning{{FALSE}}
+
+  } else if (n / 6 + 3 == 7) {
+    const int32_t C = 24;
+
+    assert(C / 6 + 3 == 7);
+    assert((C + 5) / 6 + 3 == 7);
+
+    clang_analyzer_eval(n == INT_MIN); //expected-warning{{FALSE}}
+    clang_analyzer_eval(n == 0); //expected-warning{{FALSE}}
+    clang_analyzer_eval(n == C - 1); //expected-warning{{FALSE}}
+    clang_analyzer_eval(n >= C); //expected-warning{{TRUE}}
+    clang_analyzer_eval(n <= C + 5); //expected-warning{{TRUE}}
+    clang_analyzer_eval(n == C + 6); //expected-warning{{FALSE}}
+    clang_analyzer_eval(n == INT_MAX); //expected-warning{{FALSE}}
+
+  } else if (n / 5 - 2 == 4) {
+    const int32_t C = 30;
+
+    assert(C / 5 - 2 == 4);
+    assert((C + 4) / 5 - 2 == 4);
+
+    clang_analyzer_eval(n == INT_MIN); //expected-warning{{FALSE}}
+    clang_analyzer_eval(n == 0); //expected-warning{{FALSE}}
+    clang_analyzer_eval(n == C - 1); //expected-warning{{FALSE}}
+    clang_analyzer_eval(n >= C); //expected-warning{{TRUE}}
+    clang_analyzer_eval(n <= C + 4); //expected-warning{{TRUE}}
+    clang_analyzer_eval(n == C + 5); //expected-warning{{FALSE}}
+    clang_analyzer_eval(n == INT_MAX); //expected-warning{{FALSE}}
+
+  } else if (n * 3 - INT_MIN == 7) {
+    const int32_t C1 = 0x2aaaaaad;
+
+    assert(C1 * 3 - INT_MIN == 7);
+
+    clang_analyzer_eval(n == INT_MIN); //expected-warning{{FALSE}}
+    clang_analyzer_eval(n == C1 - 1); //expected-warning{{FALSE}}
+    clang_analyzer_eval(n == C1); //expected-warning{{TRUE}}
+    clang_analyzer_eval(n == C1 + 1); //expected-warning{{FALSE}}
+    clang_analyzer_eval(n == 0); //expected-warning{{FALSE}}
+    clang_analyzer_eval(n == INT_MAX); //expected-warning{{FALSE}}
+
+  } else if (n / 2 + 1 == INT_MAX / 2 + 1) {
+    clang_analyzer_eval(n == INT_MIN); //expected-warning{{FALSE}}
+    clang_analyzer_eval(n == 0); //expected-warning{{FALSE}}
+    clang_analyzer_eval(n == INT_MAX - 1); //expected-warning{{FALSE}}
+                                           //expected-warning@-1{{TRUE}}
+    clang_analyzer_eval(n == INT_MAX); //expected-warning{{FALSE}}
+                                       //expected-warning@-1{{TRUE}}
+
+  }
+}
+
+void mixed_signedness(int32_t n, uint32_t m) {
+  if (n * 2U == 4) {
+    clang_analyzer_warnIfReached(); //expected-warning{{REACHABLE}}
+  } else if (n * 3 == 9U) {
+    clang_analyzer_warnIfReached(); //expected-warning{{REACHABLE}}
+  } else if (n * 5U == 25U) {
+    clang_analyzer_warnIfReached(); //expected-warning{{REACHABLE}}
+  } else if (m * 2U == 4) {
+    clang_analyzer_warnIfReached(); //expected-warning{{REACHABLE}}
+  } else if (m * 3 == 9U) {
+    clang_analyzer_warnIfReached(); //expected-warning{{REACHABLE}}
+  } else if (m * 5 == 2) {
+    clang_analyzer_warnIfReached(); //expected-warning{{REACHABLE}}
+  }
+}
+
+void mixed_size(int32_t n, int64_t m) {
+  if (n * 2L == 4) {
+    clang_analyzer_warnIfReached(); //expected-warning{{REACHABLE}}
+  } else if (n * 3 == 9L) {
+    clang_analyzer_warnIfReached(); //expected-warning{{REACHABLE}}
+  } else if (n * 5L == 25L) {
+    clang_analyzer_warnIfReached(); //expected-warning{{REACHABLE}}
+  } else if (m * 2L == 4) {
+    clang_analyzer_warnIfReached(); //expected-warning{{REACHABLE}}
+  } else if (m * 3 == 9L) {
+    clang_analyzer_warnIfReached(); //expected-warning{{REACHABLE}}
+  } else if (m * 5 == 2) {
+    clang_analyzer_warnIfReached(); //expected-warning{{REACHABLE}}
+  }
+}
Index: lib/StaticAnalyzer/Core/RangedConstraintManager.cpp
===================================================================
--- lib/StaticAnalyzer/Core/RangedConstraintManager.cpp
+++ lib/StaticAnalyzer/Core/RangedConstraintManager.cpp
@@ -110,10 +110,11 @@
 
   // Reverse the operation and add directly to state.
   const llvm::APSInt &Zero = BVF.getValue(0, T);
+  const ScalingFactor One = {BVF.getValue(1, T), false};
   if (Assumption)
-    return assumeSymNE(State, Sym, Zero, Zero);
+    return assumeSymNE(State, Sym, Zero, One, Zero);
   else
-    return assumeSymEQ(State, Sym, Zero, Zero);
+    return assumeSymEQ(State, Sym, Zero, One, Zero);
 }
 
 ProgramStateRef RangedConstraintManager::assumeSymRel(ProgramStateRef State,
@@ -138,8 +139,10 @@
   BasicValueFactory &BVF = getBasicVals();
   APSIntType WraparoundType = BVF.getAPSIntType(Sym->getType());
 
-  // We only handle simple comparisons of the form "$sym == constant"
-  // or "($sym+constant1) == constant2".
+  // We only handle simple comparisons of the form "$sym == constant",
+  // "$sym*constant0 == constant2", "$sym+constant1 == constant2" and
+  // "($sym*constant0)+constant1 == constant2".
+
   // The adjustment is "constant1" in the above expression. It's used to
   // "slide" the solution range around for modular arithmetic. For example,
   // x < 4 has the solution [0, 3]. x+2 < 4 has the solution [0-2, 3-2], which
@@ -148,24 +151,35 @@
   llvm::APSInt Adjustment = WraparoundType.getZeroValue();
   computeAdjustment(Sym, Adjustment);
 
+  // The scale is "constant0" in the above expression. It's used to
+  // "rescale" the solution range. It's up to the subclasses of
+  // SimpleConstraintManager to handle the scaling.
+
+  ScalingFactor Scale = {WraparoundType.getValue(1), false};
+  // FIXME: For now scaling only works for == and !=
+  if (Op == BO_EQ || Op == BO_NE)
+    computeScale(Sym, Scale);
+
   // Convert the right-hand side integer as necessary.
   APSIntType ComparisonType = std::max(WraparoundType, APSIntType(Int));
   llvm::APSInt ConvertedInt = ComparisonType.convert(Int);
 
   // Prefer unsigned comparisons.
   if (ComparisonType.getBitWidth() == WraparoundType.getBitWidth() &&
-      ComparisonType.isUnsigned() && !WraparoundType.isUnsigned())
+      ComparisonType.isUnsigned() && !WraparoundType.isUnsigned()) {
+    Scale.Val.setIsSigned(false);
     Adjustment.setIsSigned(false);
+  }
 
   switch (Op) {
   default:
     llvm_unreachable("invalid operation not caught by assertion above");
 
   case BO_EQ:
-    return assumeSymEQ(State, Sym, ConvertedInt, Adjustment);
+    return assumeSymEQ(State, Sym, ConvertedInt, Scale, Adjustment);
 
   case BO_NE:
-    return assumeSymNE(State, Sym, ConvertedInt, Adjustment);
+    return assumeSymNE(State, Sym, ConvertedInt, Scale, Adjustment);
 
   case BO_GT:
     return assumeSymGT(State, Sym, ConvertedInt, Adjustment);
@@ -181,6 +195,30 @@
   } // end switch
 }
 
+void RangedConstraintManager::computeScale(SymbolRef &Sym,
+                                           ScalingFactor &Scale) {
+  // Is it a "($sym*constant1)" expression?
+  if (const SymIntExpr *SE = dyn_cast<SymIntExpr>(Sym)) {
+    BinaryOperator::Opcode Op = SE->getOpcode();
+    if (Op == BO_Mul || Op == BO_Div) {
+      Sym = SE->getLHS();
+
+      // FIXME: We do not yet support multiplication/division by negative
+      if (SE->getRHS() < 0)
+        return;
+
+      // We cannot handle too big multipliers
+      if (Op == BO_Mul && SE->getRHS() > 255)
+        return;
+
+      Scale.Val = APSIntType(Scale.Val).convert(SE->getRHS());
+
+      // Don't forget to reciprocate the scale if it's being divided.
+      Scale.Reciprocal = (Op == BO_Div);
+    }
+  }
+}
+
 void RangedConstraintManager::computeAdjustment(SymbolRef &Sym,
                                                 llvm::APSInt &Adjustment) {
   // Is it a "($sym+constant1)" expression?
Index: lib/StaticAnalyzer/Core/RangeConstraintManager.cpp
===================================================================
--- lib/StaticAnalyzer/Core/RangeConstraintManager.cpp
+++ lib/StaticAnalyzer/Core/RangeConstraintManager.cpp
@@ -270,10 +270,12 @@
 
   ProgramStateRef assumeSymNE(ProgramStateRef State, SymbolRef Sym,
                               const llvm::APSInt &V,
+                              const ScalingFactor &Scale,
                               const llvm::APSInt &Adjustment) override;
 
   ProgramStateRef assumeSymEQ(ProgramStateRef State, SymbolRef Sym,
                               const llvm::APSInt &V,
+                              const ScalingFactor &Scale,
                               const llvm::APSInt &Adjustment) override;
 
   ProgramStateRef assumeSymLT(ProgramStateRef State, SymbolRef Sym,
@@ -323,6 +325,8 @@
                          const llvm::APSInt &Int,
                          const llvm::APSInt &Adjustment);
 
+  bool rescale(llvm::APSInt &Int, const ScalingFactor &Scale,
+               const llvm::APSInt &Index);
 };
 
 } // end anonymous namespace
@@ -537,6 +541,39 @@
   return nullptr;
 }
 
+bool RangeConstraintManager::rescale(llvm::APSInt &Int,
+                                     const ScalingFactor &Scale,
+                                     const llvm::APSInt &Index) {
+  if (Scale.Val == 1)
+    return true;
+
+  APSIntType ScaleType(Scale.Val);
+  APSIntType BigType(2 * ScaleType.getBitWidth(), ScaleType.isUnsigned());
+
+  if (Scale.Reciprocal) {
+    // Check whether the scaled value can show up
+    if(ScaleType.testInRange(BigType.convert(Int) * BigType.convert(Scale.Val),
+                             true) != APSIntType::RTR_Within)
+      return false;
+
+    Int = Int * Scale.Val;
+    return true;
+  } else {
+    llvm::APSInt Range = BigType.convert(ScaleType.getMaxValue()) -
+      BigType.convert(ScaleType.getMinValue()) +
+      BigType.getValue(1);
+    llvm::APSInt PeriodInt = Range / BigType.convert(Scale.Val);
+    llvm::APSInt PeriodFrac = Range % BigType.convert(Scale.Val);
+    llvm::APSInt Quotient = BigType.convert(Int) / BigType.convert(Scale.Val);
+    llvm::APSInt Remainder = BigType.convert(Int) % BigType.convert(Scale.Val);
+    llvm::APSInt Frac = Remainder + BigType.convert(Index) * PeriodFrac;
+    Int = ScaleType.convert(Quotient + BigType.convert(Index) * PeriodInt +
+                            Frac / BigType.convert(Scale.Val));
+
+    return (Frac % BigType.convert(Scale.Val)).isNullValue();
+  }
+}
+
 //===------------------------------------------------------------------------===
 // assumeSymX methods: protected interface for RangeConstraintManager.
 //===------------------------------------------------------------------------===/
@@ -552,35 +589,77 @@
 ProgramStateRef
 RangeConstraintManager::assumeSymNE(ProgramStateRef St, SymbolRef Sym,
                                     const llvm::APSInt &Int,
+                                    const ScalingFactor &Scale,
                                     const llvm::APSInt &Adjustment) {
   // Before we do any real work, see if the value can even show up.
   APSIntType AdjustmentType(Adjustment);
   if (AdjustmentType.testInRange(Int, true) != APSIntType::RTR_Within)
     return St;
 
-  llvm::APSInt Lower = AdjustmentType.convert(Int) - Adjustment;
-  llvm::APSInt Upper = Lower;
-  --Lower;
-  ++Upper;
-
-  // [Int-Adjustment+1, Int-Adjustment-1]
+  // [(Int-Adjustment)/Scale+1, (Int-Adjustment)/Scale-1]
   // Notice that the lower bound is greater than the upper bound.
-  RangeSet New = getRange(St, Sym).Intersect(getBasicVals(), F, Upper, Lower);
+  llvm::APSInt AdjInt = AdjustmentType.convert(Int) - Adjustment;
+
+  RangeSet New = getRange(St, Sym);
+  for (llvm::APSInt I = AdjustmentType.getZeroValue();
+      I < (Scale.Reciprocal ? AdjustmentType.getValue(1) : Scale.Val); ++I) {
+
+    llvm::APSInt ScInt = AdjInt;
+    if (!rescale(ScInt, Scale, I))
+      continue;
+
+    llvm::APSInt Lower = ScInt;
+    llvm::APSInt Upper = ScInt;
+    Lower--;
+    Upper++;
+
+    if (Scale.Reciprocal) {
+      if (ScInt < 0)
+        Lower -= Scale.Val - AdjustmentType.getValue(1);
+      else if (ScInt > 0)
+        Upper += Scale.Val - AdjustmentType.getValue(1);
+    }
+
+    New = New.Intersect(getBasicVals(), F, Upper, Lower);
+  }
+
   return New.isEmpty() ? nullptr : St->set<ConstraintRange>(Sym, New);
 }
 
 ProgramStateRef
 RangeConstraintManager::assumeSymEQ(ProgramStateRef St, SymbolRef Sym,
                                     const llvm::APSInt &Int,
+                                    const ScalingFactor &Scale,
                                     const llvm::APSInt &Adjustment) {
   // Before we do any real work, see if the value can even show up.
   APSIntType AdjustmentType(Adjustment);
   if (AdjustmentType.testInRange(Int, true) != APSIntType::RTR_Within)
     return nullptr;
 
-  // [Int-Adjustment, Int-Adjustment]
+  // [(Int-Adjustment)/Scale, (Int-Adjustment)/Scale]
   llvm::APSInt AdjInt = AdjustmentType.convert(Int) - Adjustment;
-  RangeSet New = getRange(St, Sym).Intersect(getBasicVals(), F, AdjInt, AdjInt);
+
+  RangeSet New = F.getEmptySet();
+  for (llvm::APSInt I = AdjustmentType.getZeroValue();
+      I < (Scale.Reciprocal ? AdjustmentType.getValue(1) : Scale.Val); ++I) {
+  
+    llvm::APSInt ScInt = AdjInt;
+    if (!rescale(ScInt, Scale, I))
+      continue;
+
+    llvm::APSInt Lower = ScInt;
+    llvm::APSInt Upper = ScInt;
+
+    if (Scale.Reciprocal) {
+      if (ScInt < 0)
+        Lower -= Scale.Val - AdjustmentType.getValue(1);
+      else if (ScInt > 0)
+        Upper += Scale.Val - AdjustmentType.getValue(1);
+    }
+
+    New = New.addRange(F, getRange(St, Sym).Intersect(getBasicVals(), F, Lower,
+                                                      Upper));
+  }
   return New.isEmpty() ? nullptr : St->set<ConstraintRange>(Sym, New);
 }
 
Index: include/clang/StaticAnalyzer/Core/PathSensitive/RangedConstraintManager.h
===================================================================
--- include/clang/StaticAnalyzer/Core/PathSensitive/RangedConstraintManager.h
+++ include/clang/StaticAnalyzer/Core/PathSensitive/RangedConstraintManager.h
@@ -158,6 +158,11 @@
                                        bool Assumption) override;
 
 protected:
+  struct ScalingFactor {
+    llvm::APSInt Val;
+    bool Reciprocal;
+  };
+
   /// Assume a constraint between a symbolic expression and a concrete integer.
   virtual ProgramStateRef assumeSymRel(ProgramStateRef State, SymbolRef Sym,
                                BinaryOperator::Opcode op,
@@ -172,10 +177,12 @@
 
   virtual ProgramStateRef assumeSymNE(ProgramStateRef State, SymbolRef Sym,
                                       const llvm::APSInt &V,
+                                      const ScalingFactor &Scale,
                                       const llvm::APSInt &Adjustment) = 0;
 
   virtual ProgramStateRef assumeSymEQ(ProgramStateRef State, SymbolRef Sym,
                                       const llvm::APSInt &V,
+                                      const ScalingFactor &Scale,
                                       const llvm::APSInt &Adjustment) = 0;
 
   virtual ProgramStateRef assumeSymLT(ProgramStateRef State, SymbolRef Sym,
@@ -207,6 +214,7 @@
   //===------------------------------------------------------------------===//
 private:
   static void computeAdjustment(SymbolRef &Sym, llvm::APSInt &Adjustment);
+  static void computeScale(SymbolRef &Sym, ScalingFactor &Scale);
 };
 
 } // end GR namespace
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to