Index: cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/RangedConstraintManager.h =================================================================== --- cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/RangedConstraintManager.h +++ cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/RangedConstraintManager.h @@ -113,7 +113,8 @@ public: RangeSet Intersect(BasicValueFactory &BV, Factory &F, llvm::APSInt Lower, llvm::APSInt Upper) const; - + RangeSet Intersect(BasicValueFactory &BV, Factory &F, + const RangeSet &Other) const; RangeSet Negate(BasicValueFactory &BV, Factory &F) const; void print(raw_ostream &os) const; Index: cfe/trunk/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp =================================================================== --- cfe/trunk/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp +++ cfe/trunk/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp @@ -173,6 +173,22 @@ return newRanges; } +// Returns a set containing the values in the receiving set, intersected with +// the range set passed as parameter. +RangeSet RangeSet::Intersect(BasicValueFactory &BV, Factory &F, + const RangeSet &Other) const { + PrimRangeSet newRanges = F.getEmptySet(); + + for (iterator i = Other.begin(), e = Other.end(); i != e; ++i) { + RangeSet newPiece = Intersect(BV, F, i->From(), i->To()); + for (iterator j = newPiece.begin(), ee = newPiece.end(); j != ee; ++j) { + newRanges = F.add(newRanges, *j); + } + } + + return newRanges; +} + // Turn all [A, B] ranges to [-B, -A]. Ranges [MIN, B] are turned to range set // [MIN, MIN] U [-B, MAX], when MIN and MAX are the minimal and the maximal // signed values of the type. @@ -461,14 +477,21 @@ RangeSet RangeConstraintManager::getRange(ProgramStateRef State, SymbolRef Sym) { - if (ConstraintRangeTy::data_type *V = State->get(Sym)) - return *V; - - BasicValueFactory &BV = getBasicVals(); + ConstraintRangeTy::data_type *V = State->get(Sym); // If Sym is a difference of symbols A - B, then maybe we have range set // stored for B - A. - if (const RangeSet *R = getRangeForMinusSymbol(State, Sym)) + BasicValueFactory &BV = getBasicVals(); + const RangeSet *R = getRangeForMinusSymbol(State, Sym); + + // If we have range set stored for both A - B and B - A then calculate the + // effective range set by intersecting the range set for A - B and the + // negated range set of B - A. + if (V && R) + return V->Intersect(BV, F, R->Negate(BV, F)); + if (V) + return *V; + if (R) return R->Negate(BV, F); // Lazily generate a new RangeSet representing all possible values for the Index: cfe/trunk/test/Analysis/constraint_manager_negate_difference.c =================================================================== --- cfe/trunk/test/Analysis/constraint_manager_negate_difference.c +++ cfe/trunk/test/Analysis/constraint_manager_negate_difference.c @@ -96,3 +96,17 @@ return; clang_analyzer_eval(n - m <= 0); // expected-warning{{TRUE}} } + +void effective_range(int m, int n) { + assert(m - n >= 0); + assert(n - m >= 0); + clang_analyzer_eval(m - n == 0); // expected-warning{{TRUE}} + clang_analyzer_eval(n - m == 0); // expected-warning{{TRUE}} +} + +void effective_range_2(int m, int n) { + assert(m - n <= 0); + assert(n - m <= 0); + clang_analyzer_eval(m - n == 0); // expected-warning{{TRUE}} expected-warning{{FALSE}} + clang_analyzer_eval(n - m == 0); // expected-warning{{TRUE}} expected-warning{{FALSE}} +}