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 @@ -1454,8 +1454,7 @@ QualType T = Sym->getType(); // Do not negate unsigned ranges - if (!T->isUnsignedIntegerOrEnumerationType() && - !T->isSignedIntegerOrEnumerationType()) + if (T->isUnsignedIntegerOrEnumerationType()) return llvm::None; SymbolManager &SymMgr = State->getSymbolManager(); diff --git a/clang/test/Analysis/constraint_manager_negate_difference.c b/clang/test/Analysis/constraint_manager_negate_difference.c --- a/clang/test/Analysis/constraint_manager_negate_difference.c +++ b/clang/test/Analysis/constraint_manager_negate_difference.c @@ -122,31 +122,37 @@ } } +_Static_assert(12u - 1u != 1u - 12u, "Good modulo arithmetic"); void negate_unsigned_mid(unsigned m, unsigned n) { if (m - n == UINT_MID) { - clang_analyzer_eval(n - m == UINT_MID); // expected-warning{{TRUE}} - clang_analyzer_eval(n - m != UINT_MID); // expected-warning{{FALSE}} + clang_analyzer_eval(n - m == UINT_MID); // expected-warning{{TRUE}} expected-warning{{FALSE}} + clang_analyzer_eval(n - m != UINT_MID); // expected-warning{{FALSE}} expected-warning{{TRUE}} } } void negate_unsigned_mid2(unsigned m, unsigned n) { if (m - n < UINT_MID && m - n > UINT_MIN) { - clang_analyzer_eval(n - m > UINT_MID); // expected-warning{{TRUE}} - clang_analyzer_eval(n - m < UINT_MID); // expected-warning{{FALSE}} + clang_analyzer_eval(n - m > UINT_MID); // expected-warning{{TRUE}} expected-warning{{FALSE}} + clang_analyzer_eval(n - m < UINT_MID); // expected-warning{{FALSE}} expected-warning{{TRUE}} } } + +_Static_assert(1u - 2u == UINT_MAX, "Good modulo arithmetic"); +_Static_assert(2u - 1u == 1, "Good modulo arithmetic"); void negate_unsigned_max(unsigned m, unsigned n) { if (m - n == UINT_MAX) { - clang_analyzer_eval(n - m == 1); // expected-warning{{TRUE}} - clang_analyzer_eval(n - m != 1); // expected-warning{{FALSE}} + // FIXME only the TRUE case should appear. But it is better to be + // conservative than faulty. + clang_analyzer_eval(n - m == 1); // expected-warning{{TRUE}} expected-warning{{FALSE}} + clang_analyzer_eval(n - m != 1); // expected-warning{{FALSE}} expected-warning{{TRUE}} } } - void negate_unsigned_one(unsigned m, unsigned n) { if (m - n == 1) { - clang_analyzer_eval(n - m == UINT_MAX); // expected-warning{{TRUE}} - clang_analyzer_eval(n - m < UINT_MAX); // expected-warning{{FALSE}} + // FIXME only the TRUE case should appear. + clang_analyzer_eval(n - m == UINT_MAX); // expected-warning{{TRUE}} expected-warning{{FALSE}} + clang_analyzer_eval(n - m < UINT_MAX); // expected-warning{{FALSE}} expected-warning{{TRUE}} } }