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(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(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(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. 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) {