diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/RangedConstraintManager.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/RangedConstraintManager.h --- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/RangedConstraintManager.h +++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/RangedConstraintManager.h @@ -342,7 +342,6 @@ ProgramStateRef assumeSymUnsupported(ProgramStateRef State, SymbolRef Sym, bool Assumption) override; -protected: /// Assume a constraint between a symbolic expression and a concrete integer. virtual ProgramStateRef assumeSymRel(ProgramStateRef State, SymbolRef Sym, BinaryOperator::Opcode op, 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 @@ -1620,7 +1620,7 @@ Builder.getBasicValueFactory().getValue(0, Sym->getType()); // a % b != 0 implies that a != 0. if (!Constraint.containsZero()) { - State = RCM.assumeSymNE(State, LHS, Zero, Zero); + State = RCM.assumeSymRel(State, LHS, BO_NE, Zero); if (!State) return false; } diff --git a/clang/test/Analysis/constraint-assignor.c b/clang/test/Analysis/constraint-assignor.c --- a/clang/test/Analysis/constraint-assignor.c +++ b/clang/test/Analysis/constraint-assignor.c @@ -3,9 +3,8 @@ // RUN: -analyzer-checker=debug.ExprInspection \ // RUN: -verify -// expected-no-diagnostics - void clang_analyzer_warnIfReached(); +void clang_analyzer_eval(); void rem_constant_rhs_ne_zero(int x, int y) { if (x % 3 == 0) // x % 3 != 0 -> x != 0 @@ -67,3 +66,11 @@ if (d % 2 != 0) return; } + +void remainder_with_adjustment(int x, int y) { + if ((x + 1) % 3 == 0) // (x + 1) % 3 != 0 -> x + 1 != 0 -> x != -1 + return; + clang_analyzer_eval(x + 1 != 0); // expected-warning{{TRUE}} + clang_analyzer_eval(x != -1); // expected-warning{{TRUE}} + (void)x; // keep the constraints alive. +}