[clang] a8297ed - [Analyzer][solver] Handle adjustments in constraint assignor remainder

Gabor Marton via cfe-commits cfe-commits at lists.llvm.org
Wed Oct 27 08:14:53 PDT 2021


Author: Gabor Marton
Date: 2021-10-27T17:14:34+02:00
New Revision: a8297ed994301dbf34f259690e9f5fa8fce96ea2

URL: https://github.com/llvm/llvm-project/commit/a8297ed994301dbf34f259690e9f5fa8fce96ea2
DIFF: https://github.com/llvm/llvm-project/commit/a8297ed994301dbf34f259690e9f5fa8fce96ea2.diff

LOG: [Analyzer][solver] Handle adjustments in constraint assignor remainder

We can reuse the "adjustment" handling logic in the higher level
of the solver by calling `State->assume`.

Differential Revision: https://reviews.llvm.org/D112296

Added: 
    

Modified: 
    clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp
    clang/lib/StaticAnalyzer/Core/RangedConstraintManager.cpp
    clang/test/Analysis/constraint-assignor.c

Removed: 
    


################################################################################
diff  --git a/clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp b/clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp
index 77f97da4322b3..6e4ee6e337ce5 100644
--- a/clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp
+++ b/clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp
@@ -1614,14 +1614,14 @@ class ConstraintAssignor : public ConstraintAssignorBase<ConstraintAssignor> {
   bool handleRemainderOp(const SymT *Sym, RangeSet Constraint) {
     if (Sym->getOpcode() != BO_Rem)
       return true;
-    const SymbolRef LHS = Sym->getLHS();
-    const llvm::APSInt &Zero =
-        Builder.getBasicValueFactory().getValue(0, Sym->getType());
     // a % b != 0 implies that a != 0.
     if (!Constraint.containsZero()) {
-      State = RCM.assumeSymNE(State, LHS, Zero, Zero);
-      if (!State)
-        return false;
+      SVal SymSVal = Builder.makeSymbolVal(Sym->getLHS());
+      if (auto NonLocSymSVal = SymSVal.getAs<nonloc::SymbolVal>()) {
+        State = State->assume(*NonLocSymSVal, true);
+        if (!State)
+          return false;
+      }
     }
     return true;
   }

diff  --git a/clang/lib/StaticAnalyzer/Core/RangedConstraintManager.cpp b/clang/lib/StaticAnalyzer/Core/RangedConstraintManager.cpp
index 80f3054a5a37f..892d64ea4e4e2 100644
--- a/clang/lib/StaticAnalyzer/Core/RangedConstraintManager.cpp
+++ b/clang/lib/StaticAnalyzer/Core/RangedConstraintManager.cpp
@@ -41,7 +41,12 @@ ProgramStateRef RangedConstraintManager::assumeSym(ProgramStateRef State,
       return assumeSymRel(State, SIE->getLHS(), op, SIE->getRHS());
     }
 
-  } else if (const SymSymExpr *SSE = dyn_cast<SymSymExpr>(Sym)) {
+    // Handle adjustment with non-comparison ops.
+    const llvm::APSInt &Zero = getBasicVals().getValue(0, SIE->getType());
+    return assumeSymRel(State, SIE, (Assumption ? BO_NE : BO_EQ), Zero);
+  }
+
+  if (const auto *SSE = dyn_cast<SymSymExpr>(Sym)) {
     BinaryOperator::Opcode Op = SSE->getOpcode();
     assert(BinaryOperator::isComparisonOp(Op));
 

diff  --git a/clang/test/Analysis/constraint-assignor.c b/clang/test/Analysis/constraint-assignor.c
index 1c041e3e0ce45..1b9e40e6bf649 100644
--- a/clang/test/Analysis/constraint-assignor.c
+++ b/clang/test/Analysis/constraint-assignor.c
@@ -3,9 +3,8 @@
 // RUN:   -analyzer-checker=debug.ExprInspection \
 // RUN:   -verify
 
-// expected-no-diagnostics
-
 void clang_analyzer_warnIfReached();
+void clang_analyzer_eval(int);
 
 void rem_constant_rhs_ne_zero(int x, int y) {
   if (x % 3 == 0) // x % 3 != 0 -> x != 0
@@ -67,3 +66,19 @@ void internal_unsigned_signed_mismatch(unsigned a) {
   if (d % 2 != 0)
     return;
 }
+
+void remainder_with_adjustment(int x) {
+  if ((x + 1) % 3 == 0) // (x + 1) % 3 != 0 -> x + 1 != 0 -> x != -1
+    return;
+  clang_analyzer_eval(x + 1 != 0); // expected-warning{{TRUE}}
+  clang_analyzer_eval(x != -1);    // expected-warning{{TRUE}}
+  (void)x; // keep the constraints alive.
+}
+
+void remainder_with_adjustment_of_composit_lhs(int x, int y) {
+  if ((x + y + 1) % 3 == 0) // (x + 1) % 3 != 0 -> x + 1 != 0 -> x != -1
+    return;
+  clang_analyzer_eval(x + y + 1 != 0); // expected-warning{{TRUE}}
+  clang_analyzer_eval(x + y != -1);    // expected-warning{{TRUE}}
+  (void)(x * y); // keep the constraints alive.
+}


        


More information about the cfe-commits mailing list