diff --git a/clang/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp b/clang/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp --- a/clang/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp +++ b/clang/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp @@ -372,6 +372,15 @@ NonLoc InputLHS = lhs; NonLoc InputRHS = rhs; + // Constraints may have changed since the creation of a bound SVal. Check if + // the values can be simplified based on those new constraints. + SVal simplifiedLhs = simplifySVal(state, lhs); + SVal simplifiedRhs = simplifySVal(state, rhs); + if (auto simplifiedLhsAsNonLoc = simplifiedLhs.getAs()) + lhs = *simplifiedLhsAsNonLoc; + if (auto simplifiedRhsAsNonLoc = simplifiedRhs.getAs()) + rhs = *simplifiedRhsAsNonLoc; + // Handle trivial case where left-side and right-side are the same. if (lhs == rhs) switch (op) { @@ -619,16 +628,6 @@ } } - // Does the symbolic expression simplify to a constant? - // If so, "fold" the constant by setting 'lhs' to a ConcreteInt - // and try again. - SVal simplifiedLhs = simplifySVal(state, lhs); - if (simplifiedLhs != lhs) - if (auto simplifiedLhsAsNonLoc = simplifiedLhs.getAs()) { - lhs = *simplifiedLhsAsNonLoc; - continue; - } - // Is the RHS a constant? if (const llvm::APSInt *RHSValue = getKnownValue(state, rhs)) return MakeSymIntVal(Sym, op, *RHSValue, resultTy); diff --git a/clang/test/Analysis/svalbuilder-simplify-in-evalbinop.cpp b/clang/test/Analysis/svalbuilder-simplify-in-evalbinop.cpp new file mode 100644 --- /dev/null +++ b/clang/test/Analysis/svalbuilder-simplify-in-evalbinop.cpp @@ -0,0 +1,30 @@ +// RUN: %clang_analyze_cc1 %s \ +// RUN: -analyzer-checker=core \ +// RUN: -analyzer-checker=debug.ExprInspection \ +// RUN: -analyzer-config eagerly-assume=false \ +// RUN: -verify + +// Here we test whether the SValBuilder is capable to simplify existing +// SVals based on a newly added constraints when evaluating a BinOp. + +void clang_analyzer_eval(bool); + +void test_evalBinOp_simplifies_lhs(int y) { + int x = y / 77; + if (y != 77) + return; + + // Below `x` is the LHS being simplified. + clang_analyzer_eval(x == 1); // expected-warning{{TRUE}} + (void)(x * y); +} + +void test_evalBinOp_simplifies_rhs(int y) { + int x = y / 77; + if (y != 77) + return; + + // Below `x` is the RHS being simplified. + clang_analyzer_eval(1 == x); // expected-warning{{TRUE}} + (void)(x * y); +}