diff --git a/clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp b/clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp --- a/clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp +++ b/clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp @@ -1519,9 +1519,6 @@ // This is an infeasible assumption. return nullptr; - if (SymbolRef SimplifiedSym = simplify(State, Sym)) - Sym = SimplifiedSym; - if (ProgramStateRef NewState = setConstraint(State, Sym, NewConstraint)) { if (auto Equality = EqualityInfo::extract(Sym, Int, Adjustment)) { // If the original assumption is not Sym + Adjustment !=/ Int, @@ -2314,6 +2311,9 @@ llvm::APSInt Point = AdjustmentType.convert(Int) - Adjustment; + if (SymbolRef SimplifiedSym = simplify(St, Sym)) + Sym = SimplifiedSym; + RangeSet New = getRange(St, Sym); New = F.deletePoint(New, Point); @@ -2331,6 +2331,10 @@ // [Int-Adjustment, Int-Adjustment] llvm::APSInt AdjInt = AdjustmentType.convert(Int) - Adjustment; + + if (SymbolRef SimplifiedSym = simplify(St, Sym)) + Sym = SimplifiedSym; + RangeSet New = getRange(St, Sym); New = F.intersect(New, AdjInt); @@ -2370,6 +2374,8 @@ RangeConstraintManager::assumeSymLT(ProgramStateRef St, SymbolRef Sym, const llvm::APSInt &Int, const llvm::APSInt &Adjustment) { + if (SymbolRef SimplifiedSym = simplify(St, Sym)) + Sym = SimplifiedSym; RangeSet New = getSymLTRange(St, Sym, Int, Adjustment); return trackNE(New, St, Sym, Int, Adjustment); } @@ -2407,6 +2413,8 @@ RangeConstraintManager::assumeSymGT(ProgramStateRef St, SymbolRef Sym, const llvm::APSInt &Int, const llvm::APSInt &Adjustment) { + if (SymbolRef SimplifiedSym = simplify(St, Sym)) + Sym = SimplifiedSym; RangeSet New = getSymGTRange(St, Sym, Int, Adjustment); return trackNE(New, St, Sym, Int, Adjustment); } diff --git a/clang/test/Analysis/solver-sym-simplification-no-crash.c b/clang/test/Analysis/solver-sym-simplification-no-crash.c new file mode 100644 --- /dev/null +++ b/clang/test/Analysis/solver-sym-simplification-no-crash.c @@ -0,0 +1,26 @@ +// RUN: %clang_analyze_cc1 %s \ +// RUN: -analyzer-checker=core \ +// RUN: -analyzer-checker=debug.ExprInspection \ +// RUN: -verify + +// Here, we test that symbol simplification in the solver does not produce any +// crashes. + +// expected-no-diagnostics + +static int a, b; +static long c; + +static void f(int i, int j) +{ + (void)(j <= 0 && i ? i : j); +} + +static void g(void) +{ + int d = a - b | (c < 0); + for (;;) + { + f(d ^ c, c); + } +} diff --git a/clang/test/Analysis/solver-sym-simplification-with-proper-range-type.c b/clang/test/Analysis/solver-sym-simplification-with-proper-range-type.c new file mode 100644 --- /dev/null +++ b/clang/test/Analysis/solver-sym-simplification-with-proper-range-type.c @@ -0,0 +1,29 @@ +// RUN: %clang_analyze_cc1 %s \ +// RUN: -analyzer-checker=core \ +// RUN: -analyzer-checker=debug.ExprInspection \ +// RUN: -verify + +// Here we test that the range based solver equivalency tracking mechanism +// assigns a properly typed range to the simplified symbol. + +void clang_analyzer_printState(); +void clang_analyzer_eval(int); + +void f(int a0, int b0, int c) +{ + int a1 = a0 - b0; + int b1 = (unsigned)a1 + c; + if (c == 0) { + + int d = 7L / b1; // ... + // At this point b1 is considered non-zero, which results in a new + // constraint for $a0 - $b0 + $c. The type of this sym is unsigned, + // however, the simplified sym is $a0 - $b0 and its type is signed. + // This is probably the result of the inherent improper handling of + // casts. Anyway, Range assignment for constraints use this type + // information. Therefore, we must make sure that first we simplify the + // symbol and only then we assign the range. + + clang_analyzer_eval(a0 - b0 != 0); // expected-warning{{TRUE}} + } +}