diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -13804,6 +13804,16 @@ if (InRange && IsEnumConstOrFromMacro(S, Constant)) return false; + // Don't warn if the comparison involves integral or floating-point types with + // the same canonical types. + QualType LHSCanonical = Constant->getType().getCanonicalType(); + QualType RHSCanonical = Other->getType().getCanonicalType(); + if ((LHSCanonical->isIntegralOrEnumerationType() || + LHSCanonical->isFloatingType()) && + S.Context.hasSameType(LHSCanonical, RHSCanonical)) { + return false; + } + // A comparison of an unsigned bit-field against 0 is really a type problem, // even though at the type level the bit-field might promote to 'signed int'. if (Other->refersToBitField() && InRange && Value == 0 && diff --git a/clang/test/Sema/atomic-compare.c b/clang/test/Sema/atomic-compare.c --- a/clang/test/Sema/atomic-compare.c +++ b/clang/test/Sema/atomic-compare.c @@ -14,10 +14,10 @@ if (a > 2) {} // no warning if (!a > 0) {} // no warning - if (!a > 1) {} // expected-warning {{comparison of constant 1 with boolean expression is always false}} - if (!a > 2) {} // expected-warning {{comparison of constant 2 with boolean expression is always false}} + if (!a > 1) {} + if (!a > 2) {} if (!a > b) {} // no warning - if (!a > -1) {} // expected-warning {{comparison of constant -1 with boolean expression is always true}} + if (!a > -1) {} } typedef _Atomic(int) Ty; diff --git a/clang/test/Sema/tautological-objc-bool-compare.m b/clang/test/Sema/tautological-objc-bool-compare.m --- a/clang/test/Sema/tautological-objc-bool-compare.m +++ b/clang/test/Sema/tautological-objc-bool-compare.m @@ -15,10 +15,10 @@ r = B >= 0; // expected-warning {{result of comparison of constant 0 with expression of type 'BOOL' is always true, as the only well defined values for 'BOOL' are YES and NO}} r = B <= 0; - r = B > YES; // expected-warning {{result of comparison of constant YES with expression of type 'BOOL' is always false, as the only well defined values for 'BOOL' are YES and NO}} + r = B > YES; r = B > NO; - r = B < NO; // expected-warning {{result of comparison of constant NO with expression of type 'BOOL' is always false, as the only well defined values for 'BOOL' are YES and NO}} + r = B < NO; r = B < YES; - r = B >= NO; // expected-warning {{result of comparison of constant NO with expression of type 'BOOL' is always true, as the only well defined values for 'BOOL' are YES and NO}} + r = B >= NO; r = B <= NO; } diff --git a/clang/test/Sema/type-limit-compare.cpp b/clang/test/Sema/type-limit-compare.cpp new file mode 100644 --- /dev/null +++ b/clang/test/Sema/type-limit-compare.cpp @@ -0,0 +1,20 @@ +// RUN: %clang_cc1 %s -fsyntax-only -Wtautological-type-limit-compare -verify + +// expected-no-diagnostics +#if defined(_WIN32) +typedef unsigned long long uint64_t; +#else +typedef unsigned long uint64_t; +#endif + +namespace std { +using size_t = decltype(sizeof(0)); +} // namespace std + +bool func(uint64_t Size) { + if (sizeof(std::size_t) < sizeof(uint64_t) && + Size > (uint64_t)(__SIZE_MAX__)) + return false; + return true; +} + diff --git a/clang/test/SemaCXX/bool-compare.cpp b/clang/test/SemaCXX/bool-compare.cpp --- a/clang/test/SemaCXX/bool-compare.cpp +++ b/clang/test/SemaCXX/bool-compare.cpp @@ -5,16 +5,16 @@ bool a,b; - if(b > true) {} // expected-warning {{comparison of true with expression of type 'bool' is always false}} + if(b > true) {} if(b < true) {} // no warning if(b >= true) {} // no warning - if(b <= true) {} // expected-warning {{comparison of true with expression of type 'bool' is always true}} + if(b <= true) {} if(b == true) {} // no warning if(b != true) {} // no warning if(b > false) {} // no warning - if(b < false) {} // expected-warning {{comparison of false with expression of type 'bool' is always false}} - if(b >= false) {} // expected-warning {{comparison of false with expression of type 'bool' is always true}} + if(b < false) {} + if(b >= false) {} if(b <= false) {} // no warning if(b == false) {} // no warning if(b != false) {} // no warning