baloghadamsoftware updated this revision to Diff 105593.
baloghadamsoftware added a comment.

Wrong patch files was uploaded first.


https://reviews.llvm.org/D35110

Files:
  lib/StaticAnalyzer/Core/RangeConstraintManager.cpp
  test/Analysis/ptr-arith.c

Index: test/Analysis/ptr-arith.c
===================================================================
--- test/Analysis/ptr-arith.c
+++ test/Analysis/ptr-arith.c
@@ -272,42 +272,23 @@
 void zero_implies_reversed_equal(int *lhs, int *rhs) {
   clang_analyzer_eval((rhs - lhs) == 0); // expected-warning{{UNKNOWN}}
   if ((rhs - lhs) == 0) {
-#ifdef ANALYZER_CM_Z3
     clang_analyzer_eval(rhs != lhs); // expected-warning{{FALSE}}
     clang_analyzer_eval(rhs == lhs); // expected-warning{{TRUE}}
-#else
-    clang_analyzer_eval(rhs != lhs); // expected-warning{{UNKNOWN}}
-    clang_analyzer_eval(rhs == lhs); // expected-warning{{UNKNOWN}}
-#endif
     return;
   }
   clang_analyzer_eval((rhs - lhs) == 0); // expected-warning{{FALSE}}
-#ifdef ANALYZER_CM_Z3
   clang_analyzer_eval(rhs == lhs); // expected-warning{{FALSE}}
   clang_analyzer_eval(rhs != lhs); // expected-warning{{TRUE}}
-#else
-  clang_analyzer_eval(rhs == lhs); // expected-warning{{UNKNOWN}}
-  clang_analyzer_eval(rhs != lhs); // expected-warning{{UNKNOWN}}
-#endif
 }
 
 void canonical_equal(int *lhs, int *rhs) {
   clang_analyzer_eval(lhs == rhs); // expected-warning{{UNKNOWN}}
   if (lhs == rhs) {
-#ifdef ANALYZER_CM_Z3
     clang_analyzer_eval(rhs == lhs); // expected-warning{{TRUE}}
-#else
-    clang_analyzer_eval(rhs == lhs); // expected-warning{{UNKNOWN}}
-#endif
     return;
   }
   clang_analyzer_eval(lhs == rhs); // expected-warning{{FALSE}}
-
-#ifdef ANALYZER_CM_Z3
   clang_analyzer_eval(rhs == lhs); // expected-warning{{FALSE}}
-#else
-  clang_analyzer_eval(rhs == lhs); // expected-warning{{UNKNOWN}}
-#endif
 }
 
 void compare_element_region_and_base(int *p) {
Index: lib/StaticAnalyzer/Core/RangeConstraintManager.cpp
===================================================================
--- lib/StaticAnalyzer/Core/RangeConstraintManager.cpp
+++ lib/StaticAnalyzer/Core/RangeConstraintManager.cpp
@@ -256,6 +256,29 @@
     return newRanges;
   }
 
+  // Turn all [A, B] ranges to [-B, -A]. Turn minimal signed value to maximal
+  // signed value and vice versa.
+  RangeSet Negate(BasicValueFactory &BV, Factory &F) const {
+    PrimRangeSet newRanges = F.getEmptySet();
+
+    for (iterator i = begin(), e = end(); i != e; ++i) {
+      const llvm::APSInt &from = i->From(), &to = i->To();
+      const llvm::APSInt &newFrom = (to.isMinSignedValue() ?
+                                     BV.getMaxValue(to) :
+                                     (to.isMaxSignedValue() ?
+                                      BV.getMinValue(to) :
+                                      BV.getValue(- to)));
+      const llvm::APSInt &newTo = (from.isMinSignedValue() ?
+                                   BV.getMaxValue(from) :
+                                   (from.isMaxSignedValue() ?
+                                    BV.getMinValue(from) :
+                                    BV.getValue(- from)));
+      newRanges = F.add(newRanges, Range(newFrom, newTo));
+    }
+
+    return newRanges;
+  }
+
   void print(raw_ostream &os) const {
     bool isFirst = true;
     os << "{ ";
@@ -465,11 +488,36 @@
   if (ConstraintRangeTy::data_type *V = State->get<ConstraintRange>(Sym))
     return *V;
 
-  // Lazily generate a new RangeSet representing all possible values for the
-  // given symbol type.
+  // If Sym is a difference of symbols A - B, then maybe we have range set
+  // stored for B - A.
   BasicValueFactory &BV = getBasicVals();
   QualType T = Sym->getType();
 
+  if (const SymSymExpr *SSE = dyn_cast<SymSymExpr>(Sym)) {
+    if (SSE->getOpcode() == BO_Sub) {
+      SymbolManager &SymMgr = State->getSymbolManager();
+      // If the type of A - B is the same as the type of A, then use the type of
+      // B as the type of B - A. Otherwise keep the type of A - B.
+      SymbolRef negSym = SymMgr.getSymSymExpr(SSE->getRHS(), BO_Sub,
+                                              SSE->getLHS(),
+                                              (T == SSE->getLHS()->getType()) ?
+                                              SSE->getRHS()->getType() : T);
+      if (ConstraintRangeTy::data_type *negV =
+          State->get<ConstraintRange>(negSym)) {
+        // Do not negate an unsigned range set, unless it is [0, 0].
+        if((negV->getConcreteValue() &&
+            (*negV->getConcreteValue() == 0)) ||
+           SSE->getLHS()->getType()->isSignedIntegerOrEnumerationType() ||
+           SSE->getLHS()->getType()->isPointerType()) {
+          return negV->Negate(BV, F);
+        }
+      }
+    }
+  }
+
+  // Lazily generate a new RangeSet representing all possible values for the
+  // given symbol type.
+
   RangeSet Result(F, BV.getMinValue(T), BV.getMaxValue(T));
 
   // Special case: references are known to be non-zero.
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to