ASDenysPetrov created this revision.
ASDenysPetrov added reviewers: martong, steakhal, NoQ.
ASDenysPetrov added a project: clang.
Herald added subscribers: manas, dkrupp, donat.nagy, Szelethus, 
mikhail.ramalho, a.sidorin, rnkovacs, szepet, baloghadamsoftware, xazax.hun.
Herald added a project: All.
ASDenysPetrov requested review of this revision.
Herald added a subscriber: cfe-commits.

Infer range using associated unequal symbols from DisequalityMap.
Example:

  if(x == 42)
    if(x != y)
      y; // [-2147483648, 41]U[43, 2147483647]

NOTE: Currently, this revision causes test failure due to assertion in related 
to `IteratorModeling.cpp` in `relateSymbols` on line
`assert(isa<SymIntExpr>(CompSym) && "Symbol comparison must be a 
`SymIntExpr`");`. It needs to be fixed in some way before loading. The revision 
is exposed to show the motivation for D130372 
<https://reviews.llvm.org/D130372>.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D131006

Files:
  clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp
  clang/test/Analysis/range-inferring-from-disequality-map.cpp

Index: clang/test/Analysis/range-inferring-from-disequality-map.cpp
===================================================================
--- /dev/null
+++ clang/test/Analysis/range-inferring-from-disequality-map.cpp
@@ -0,0 +1,57 @@
+// RUN: %clang_analyze_cc1 -analyzer-checker=debug.ExprInspection -verify %s
+
+template<typename T>
+void clang_analyzer_value(T x);
+
+void test1(int x, int tmp) {
+  if(tmp != 0)
+    if(x != tmp)
+     clang_analyzer_value(x); // expected-warning {{32s:{ [0, 0] }}}
+  // TODO:  TODO: Keep x range correct even if associated disequalities are
+  // already dead.
+  (void)tmp; // Keep alive.
+}
+
+void test2(int x, int tmp) {
+  if(x != tmp)
+    if(tmp < 0)
+      clang_analyzer_value(x); // expected-warning {{32s:{ [0, 2147483647] }}}
+  // TODO:  TODO: Keep x range correct even if associated disequalities are
+  // already dead.
+  (void)tmp; // Keep alive.
+}
+
+void test3(int x, int tmp) {
+  if(x != tmp)
+    if(tmp > 42 && tmp < 87)
+      clang_analyzer_value(x); // expected-warning {{32s:{ [-2147483648, 42], [87, 2147483647] }}}
+  // TODO:  TODO: Keep x range correct even if associated disequalities are
+  // already dead.
+  (void)tmp; // Keep alive.
+}
+
+void test4(int x, int tmp1, int tmp2) {
+  if(x != tmp1) {
+    if (tmp1 < 0 && tmp2 > 0) {
+      clang_analyzer_value(x); // expected-warning {{32s:{ [0, 2147483647] }}}
+      if(x != tmp2)
+        clang_analyzer_value(x); // expected-warning {{32s:{ [0, 0] }}}
+    }
+  }
+  // TODO:  TODO: Keep x range correct even if associated disequalities are
+  // already dead.
+  (void)tmp1; // Keep alive.
+  (void)tmp2; // Keep alive.
+}
+
+void test5(int x, int tmp1, int tmp2) {
+  if (tmp1 < 42 && tmp2 >= 42) 
+    if(x != tmp1 && x != tmp2)
+      // TODO: This condition should be infeasible.
+      //       Thus, the branch should be unreachable.
+      clang_analyzer_value(x); // expected-warning {{{ empty }}}
+  // TODO:  TODO: Keep x range correct even if associated disequalities are
+  // already dead.
+  (void)tmp1; // Keep alive.
+  (void)tmp2; // Keep alive.
+}
Index: clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp
+++ clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp
@@ -1327,6 +1327,8 @@
                      // Of course, we should take the constraint directly
                      // associated with this symbol into consideration.
                      getConstraint(State, Sym),
+                     // Use inverted ranges from DisequalityMap.
+                     getInvertedRangeFromDisequalityMap(State, Sym),
                      // Apart from the Sym itself, we can infer quite a lot if
                      // we look into subexpressions of Sym.
                      Visit(Sym));
@@ -1490,6 +1492,39 @@
     return RangeFactory.deletePoint(Domain, IntType.getZeroValue());
   }
 
+  Optional<RangeSet> getInvertedRangeFromDisequalityMap(ProgramStateRef State,
+                                                        SymbolRef Sym) {
+    QualType T = Sym->getType();
+    // We only support integral types.
+    if (!T->isIntegralOrEnumerationType())
+      return llvm::None;
+
+    EquivalenceClass EC = EquivalenceClass::find(State, Sym);
+    const ClassSet *CS = State->get<DisequalityMap>(EC);
+
+    if (!CS)
+      return llvm::None;
+
+    bool IsFirst = true;
+    RangeSet RS = RangeFactory.getEmptySet();
+    for (EquivalenceClass EC : *CS) {
+      if (const RangeSet *RSPtr = getConstraint(State, EC)) {
+        if (IsFirst) {
+          IsFirst = false;
+          RS = *RSPtr;
+        } else
+          RS = RangeFactory.unite(RS, *RSPtr);
+      }
+    }
+
+    if (IsFirst)
+      return llvm::None;
+
+    RS = RangeFactory.castTo(RS, T);
+    RS = RangeFactory.invert(RS);
+    return RS;
+  }
+
   template <typename ProduceNegatedSymFunc>
   Optional<RangeSet> getRangeForNegatedExpr(ProduceNegatedSymFunc F,
                                             QualType T) {
@@ -3217,8 +3252,12 @@
 void RangeConstraintManager::printValue(raw_ostream &Out, ProgramStateRef State,
                                         SymbolRef Sym) {
   const RangeSet RS = getRange(State, Sym);
-  Out << RS.getBitWidth() << (RS.isUnsigned() ? "u:" : "s:");
-  RS.dump(Out);
+  if (RS.isEmpty())
+    Out << "{ empty }";
+  else {
+    Out << RS.getBitWidth() << (RS.isUnsigned() ? "u:" : "s:");
+    RS.dump(Out);
+  }
 }
 
 static std::string toString(const SymbolRef &Sym) {
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to