danielmarjamaki updated this revision to Diff 110378.
danielmarjamaki added a comment.
Refactoring, use BasicValueFactory::evalAPSInt
Repository:
rL LLVM
https://reviews.llvm.org/D36471
Files:
include/clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h
lib/StaticAnalyzer/Core/ExprEngineC.cpp
lib/StaticAnalyzer/Core/RangeConstraintManager.cpp
test/Analysis/eval-range.c
Index: test/Analysis/eval-range.c
===================================================================
--- test/Analysis/eval-range.c
+++ test/Analysis/eval-range.c
@@ -0,0 +1,18 @@
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -verify %s
+
+void clang_analyzer_eval(int);
+
+void test1(int a) {
+ if (a >= 10 && a <= 50) {
+ int b;
+
+ b = a + 2;
+ clang_analyzer_eval(b >= 12 && b <= 52); // expected-warning{{TRUE}}
+
+ b = a - 2;
+ clang_analyzer_eval(b >= 8 && b <= 48); // expected-warning{{TRUE}}
+
+ b = a / 2;
+ clang_analyzer_eval(b >= 5 && b <= 25); // expected-warning{{TRUE}}
+ }
+}
Index: lib/StaticAnalyzer/Core/RangeConstraintManager.cpp
===================================================================
--- lib/StaticAnalyzer/Core/RangeConstraintManager.cpp
+++ lib/StaticAnalyzer/Core/RangeConstraintManager.cpp
@@ -304,6 +304,8 @@
void print(ProgramStateRef State, raw_ostream &Out, const char *nl,
const char *sep) override;
+ ProgramStateRef evalRangeOp(ProgramStateRef state, SVal V) override;
+
//===------------------------------------------------------------------===//
// Implementation for interface from RangedConstraintManager.
//===------------------------------------------------------------------===//
@@ -741,3 +743,56 @@
}
Out << nl;
}
+
+ProgramStateRef RangeConstraintManager::evalRangeOp(ProgramStateRef St,
+ SVal V) {
+ const SymExpr *SE = V.getAsSymExpr();
+ if (!SE)
+ return nullptr;
+
+ const SymIntExpr *SIE = dyn_cast<SymIntExpr>(SE);
+ if (!SIE)
+ return nullptr;
+
+ const clang::BinaryOperatorKind Opc = SIE->getOpcode();
+
+ if (Opc != BO_Add && Opc != BO_Sub && Opc != BO_Div)
+ return nullptr;
+
+ const SymExpr *LHS = SIE->getLHS();
+ const llvm::APSInt &RHS = SIE->getRHS();
+
+ ConstraintRangeTy Ranges = St->get<ConstraintRange>();
+ for (ConstraintRangeTy::iterator I = Ranges.begin(), E = Ranges.end(); I != E;
+ ++I) {
+ if (LHS == I.getKey()) {
+ const auto D = I.getData();
+ for (auto I = D.begin(); I != D.end(); ++I) {
+ if (I->From().isUnsigned() != RHS.isUnsigned())
+ // TODO: Handle sign conversions.
+ return nullptr;
+ if (I->From().getBitWidth() != RHS.getBitWidth())
+ // TODO: Promote values.
+ return nullptr;
+ if (I->From().isNegative())
+ // TODO: Handle negative range values
+ return nullptr;
+
+ BasicValueFactory &BVF = getBasicVals();
+ const llvm::APSInt *Lower = BVF.evalAPSInt(Opc, I->From(), RHS);
+ if (!Lower)
+ return nullptr;
+ const llvm::APSInt *Upper = BVF.evalAPSInt(Opc, I->To(), RHS);
+ if (!Upper)
+ return nullptr;
+
+ SymbolRef Sym = V.getAsSymbol();
+ RangeSet RS =
+ getRange(St, Sym).Intersect(getBasicVals(), F, *Lower, *Upper);
+ // TODO: This only evaluates the first range. Evaluate all ranges.
+ return RS.isEmpty() ? nullptr : St->set<ConstraintRange>(Sym, RS);
+ }
+ }
+ }
+ return nullptr;
+}
Index: lib/StaticAnalyzer/Core/ExprEngineC.cpp
===================================================================
--- lib/StaticAnalyzer/Core/ExprEngineC.cpp
+++ lib/StaticAnalyzer/Core/ExprEngineC.cpp
@@ -98,7 +98,9 @@
}
state = state->BindExpr(B, LCtx, Result);
- Bldr.generateNode(B, *it, state);
+ ProgramStateRef state2 =
+ getConstraintManager().evalRangeOp(state, Result);
+ Bldr.generateNode(B, *it, state2 ? state2 : state);
continue;
}
Index: include/clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h
===================================================================
--- include/clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h
+++ include/clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h
@@ -142,13 +142,15 @@
/// Scan all symbols referenced by the constraints. If the symbol is not
/// alive, remove it.
virtual ProgramStateRef removeDeadBindings(ProgramStateRef state,
- SymbolReaper& SymReaper) = 0;
+ SymbolReaper &SymReaper) = 0;
- virtual void print(ProgramStateRef state,
- raw_ostream &Out,
- const char* nl,
+ virtual void print(ProgramStateRef state, raw_ostream &Out, const char *nl,
const char *sep) = 0;
+ virtual ProgramStateRef evalRangeOp(ProgramStateRef state, SVal V) {
+ return nullptr;
+ }
+
virtual void EndPath(ProgramStateRef state) {}
/// Convenience method to query the state to see if a symbol is null or
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits