baloghadamsoftware updated this revision to Diff 106627.
baloghadamsoftware added a comment.
Type selection simplified, FIXME added.
https://reviews.llvm.org/D35110
Files:
lib/StaticAnalyzer/Core/RangeConstraintManager.cpp
test/Analysis/constraint_manager_negate_difference.c
test/Analysis/ptr-arith.c
Index: test/Analysis/ptr-arith.c
===================================================================
--- test/Analysis/ptr-arith.c
+++ test/Analysis/ptr-arith.c
@@ -265,49 +265,26 @@
clang_analyzer_eval((rhs - lhs) > 0); // expected-warning{{TRUE}}
}
-//-------------------------------
-// False positives
-//-------------------------------
-
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: test/Analysis/constraint_manager_negate_difference.c
===================================================================
--- /dev/null
+++ test/Analysis/constraint_manager_negate_difference.c
@@ -0,0 +1,39 @@
+// RUN: %clang_analyze_cc1 -analyzer-checker=debug.ExprInspection -verify %s
+
+void clang_analyzer_eval(int);
+
+void equal(int m, int n) {
+ if (m != n)
+ return;
+ clang_analyzer_eval(n == m); // expected-warning{{TRUE}}
+}
+
+void non_equal(int m, int n) {
+ if (m == n)
+ return;
+ clang_analyzer_eval(n != m); // expected-warning{{TRUE}}
+}
+
+void less_or_equal(int m, int n) {
+ if (m < n)
+ return;
+ clang_analyzer_eval(n <= m); // expected-warning{{TRUE}}
+}
+
+void less(int m, int n) {
+ if (m <= n)
+ return;
+ clang_analyzer_eval(n < m); // expected-warning{{TRUE}}
+}
+
+void greater_or_equal(int m, int n) {
+ if (m > n)
+ return;
+ clang_analyzer_eval(n >= m); // expected-warning{{TRUE}}
+}
+
+void greater(int m, int n) {
+ if (m >= n)
+ return;
+ clang_analyzer_eval(n > m); // expected-warning{{TRUE}}
+}
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,38 @@
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)) {
+ // FIXME: Once SValBuilder supports unary minus, we should use SValBuilder
+ // to obtain the negated symbolic expression instead of constructing
+ // the symbol manually. This will allow us to support finding ranges
+ // of not only negated SymSymExpr-type expressions, but also of
+ // other, simpler expressions which we currently do not know how to
+ // negate.
+ if (SSE->getOpcode() == BO_Sub) {
+ SymbolManager &SymMgr = State->getSymbolManager();
+ SymbolRef negSym = SymMgr.getSymSymExpr(SSE->getRHS(), BO_Sub,
+ SSE->getLHS(), T);
+ if (ConstraintRangeTy::data_type *negV =
+ State->get<ConstraintRange>(negSym)) {
+ // Unsigned range set cannot be negated, unless it is [0, 0].
+ if ((negV->getConcreteValue() &&
+ (*negV->getConcreteValue() == 0)) ||
+ T->isSignedIntegerOrEnumerationType() ||
+ T->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
[email protected]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits