From 9a0f62efc8314133e355a190fa2cac4eb18dd2cc Mon Sep 17 00:00:00 2001 From: Roman Lebedev Date: Wed, 20 Sep 2017 13:50:01 +0000 Subject: [PATCH] Replace r313747, don't always warn on enums, rework testcases. As Aaron Ballman has pointed out, that is not really correct. So the key problem there is the invalidity of the testcase. Revert r313747, and rework testcase in such a way, so these details (platform-specific default enum sigdness) are accounted for. Also, add a C++-specific testcase. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@313756 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/SemaChecking.cpp | 12 +- .../tautological-unsigned-enum-zero-compare.c | 28 ++- ...autological-unsigned-enum-zero-compare.cpp | 176 ++++++++++++++++++ 3 files changed, 205 insertions(+), 11 deletions(-) create mode 100644 test/Sema/tautological-unsigned-enum-zero-compare.cpp diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp index 9ff8f6347e..87634ad57e 100644 --- a/lib/Sema/SemaChecking.cpp +++ b/lib/Sema/SemaChecking.cpp @@ -8592,26 +8592,22 @@ bool CheckTautologicalComparisonWithZero(Sema &S, BinaryOperator *E) { bool Match = true; - if (Op == BO_LT && IsZero(S, RHS) && - (isNonBooleanUnsignedValue(LHS) || HasEnumType(LHS))) { + if (Op == BO_LT && isNonBooleanUnsignedValue(LHS) && IsZero(S, RHS)) { S.Diag(E->getOperatorLoc(), HasEnumType(LHS) ? diag::warn_lunsigned_enum_always_true_comparison : diag::warn_lunsigned_always_true_comparison) << "< 0" << false << LHS->getSourceRange() << RHS->getSourceRange(); - } else if (Op == BO_GE && IsZero(S, RHS) && - (isNonBooleanUnsignedValue(LHS) || HasEnumType(LHS))) { + } else if (Op == BO_GE && isNonBooleanUnsignedValue(LHS) && IsZero(S, RHS)) { S.Diag(E->getOperatorLoc(), HasEnumType(LHS) ? diag::warn_lunsigned_enum_always_true_comparison : diag::warn_lunsigned_always_true_comparison) << ">= 0" << true << LHS->getSourceRange() << RHS->getSourceRange(); - } else if (Op == BO_GT && IsZero(S, LHS) && - (isNonBooleanUnsignedValue(RHS) || HasEnumType(RHS))) { + } else if (Op == BO_GT && isNonBooleanUnsignedValue(RHS) && IsZero(S, LHS)) { S.Diag(E->getOperatorLoc(), HasEnumType(RHS) ? diag::warn_runsigned_enum_always_true_comparison : diag::warn_runsigned_always_true_comparison) << "0 >" << false << LHS->getSourceRange() << RHS->getSourceRange(); - } else if (Op == BO_LE && IsZero(S, LHS) && - (isNonBooleanUnsignedValue(RHS) || HasEnumType(RHS))) { + } else if (Op == BO_LE && isNonBooleanUnsignedValue(RHS) && IsZero(S, LHS)) { S.Diag(E->getOperatorLoc(), HasEnumType(RHS) ? diag::warn_runsigned_enum_always_true_comparison : diag::warn_runsigned_always_true_comparison) diff --git a/test/Sema/tautological-unsigned-enum-zero-compare.c b/test/Sema/tautological-unsigned-enum-zero-compare.c index a0c2a30055..49982a9fd7 100644 --- a/test/Sema/tautological-unsigned-enum-zero-compare.c +++ b/test/Sema/tautological-unsigned-enum-zero-compare.c @@ -1,11 +1,16 @@ -// RUN: %clang_cc1 -fsyntax-only -DTEST -verify %s -// RUN: %clang_cc1 -fsyntax-only -Wno-tautological-unsigned-enum-zero-compare -verify %s +// RUN: %clang_cc1 -triple=x86_64-pc-linux-gnu -fsyntax-only -DALL_WARN -verify %s +// RUN: %clang_cc1 -triple=x86_64-pc-win32 -fsyntax-only -DSIGN_WARN -verify %s +// RUN: %clang_cc1 -triple=x86_64-pc-win32 -fsyntax-only -Wno-tautological-unsigned-enum-zero-compare -verify %s + +// Okay, this is where it gets complicated. +// Then default enum sigdness is target-specific. +// On windows, it is signed by default. We do not want to warn in that case. int main() { enum A { A_foo, A_bar }; enum A a; -#ifdef TEST +#ifdef ALL_WARN if (a < 0) // expected-warning {{comparison of unsigned enum expression < 0 is always false}} return 0; if (a >= 0) // expected-warning {{comparison of unsigned enum expression >= 0 is always true}} @@ -22,6 +27,23 @@ int main() { return 0; if (0U > a) // expected-warning {{comparison of 0 > unsigned enum expression is always false}} return 0; +#elif defined(SIGN_WARN) + if (a < 0) // ok + return 0; + if (a >= 0) // ok + return 0; + if (0 <= a) // ok + return 0; + if (0 > a) // ok + return 0; + if (a < 0U) // expected-warning {{comparison of unsigned enum expression < 0 is always false}} + return 0; + if (a >= 0U) // expected-warning {{comparison of unsigned enum expression >= 0 is always true}} + return 0; + if (0U <= a) // expected-warning {{comparison of 0 <= unsigned enum expression is always true}} + return 0; + if (0U > a) // expected-warning {{comparison of 0 > unsigned enum expression is always false}} + return 0; #else // expected-no-diagnostics if (a < 0) diff --git a/test/Sema/tautological-unsigned-enum-zero-compare.cpp b/test/Sema/tautological-unsigned-enum-zero-compare.cpp new file mode 100644 index 0000000000..3e78626745 --- /dev/null +++ b/test/Sema/tautological-unsigned-enum-zero-compare.cpp @@ -0,0 +1,176 @@ +// RUN: %clang_cc1 -std=c++11 -triple=x86_64-pc-linux-gnu -fsyntax-only -DALL_WARN -verify %s +// RUN: %clang_cc1 -std=c++11 -triple=x86_64-pc-win32 -fsyntax-only -DSIGN_WARN -verify %s +// RUN: %clang_cc1 -std=c++11 -triple=x86_64-pc-win32 -fsyntax-only -Wno-tautological-unsigned-enum-zero-compare -verify %s + +// Okay, this is where it gets complicated. +// Then default enum sigdness is target-specific. +// On windows, it is signed by default. We do not want to warn in that case. + +int main() { + enum A { A_foo, A_bar }; + enum A a; + + enum B : unsigned { B_foo, B_bar }; + enum B b; + + enum C : signed { c_foo, c_bar }; + enum C c; + +#ifdef ALL_WARN + if (a < 0) // expected-warning {{comparison of unsigned enum expression < 0 is always false}} + return 0; + if (a >= 0) // expected-warning {{comparison of unsigned enum expression >= 0 is always true}} + return 0; + if (0 <= a) // expected-warning {{comparison of 0 <= unsigned enum expression is always true}} + return 0; + if (0 > a) // expected-warning {{comparison of 0 > unsigned enum expression is always false}} + return 0; + if (a < 0U) // expected-warning {{comparison of unsigned enum expression < 0 is always false}} + return 0; + if (a >= 0U) // expected-warning {{comparison of unsigned enum expression >= 0 is always true}} + return 0; + if (0U <= a) // expected-warning {{comparison of 0 <= unsigned enum expression is always true}} + return 0; + if (0U > a) // expected-warning {{comparison of 0 > unsigned enum expression is always false}} + return 0; + + if (b < 0) // expected-warning {{comparison of unsigned enum expression < 0 is always false}} + return 0; + if (b >= 0) // expected-warning {{comparison of unsigned enum expression >= 0 is always true}} + return 0; + if (0 <= b) // expected-warning {{comparison of 0 <= unsigned enum expression is always true}} + return 0; + if (0 > b) // expected-warning {{comparison of 0 > unsigned enum expression is always false}} + return 0; + if (b < 0U) // expected-warning {{comparison of unsigned enum expression < 0 is always false}} + return 0; + if (b >= 0U) // expected-warning {{comparison of unsigned enum expression >= 0 is always true}} + return 0; + if (0U <= b) // expected-warning {{comparison of 0 <= unsigned enum expression is always true}} + return 0; + if (0U > b) // expected-warning {{comparison of 0 > unsigned enum expression is always false}} + return 0; + + if (c < 0) // ok + return 0; + if (c >= 0) // ok + return 0; + if (0 <= c) // ok + return 0; + if (0 > c) // ok + return 0; + if (c < 0U) // expected-warning {{comparison of unsigned enum expression < 0 is always false}} + return 0; + if (c >= 0U) // expected-warning {{comparison of unsigned enum expression >= 0 is always true}} + return 0; + if (0U <= c) // expected-warning {{comparison of 0 <= unsigned enum expression is always true}} + return 0; + if (0U > c) // expected-warning {{comparison of 0 > unsigned enum expression is always false}} + return 0; +#elif defined(SIGN_WARN) + if (a < 0) // ok + return 0; + if (a >= 0) // ok + return 0; + if (0 <= a) // ok + return 0; + if (0 > a) // ok + return 0; + if (a < 0U) // expected-warning {{comparison of unsigned enum expression < 0 is always false}} + return 0; + if (a >= 0U) // expected-warning {{comparison of unsigned enum expression >= 0 is always true}} + return 0; + if (0U <= a) // expected-warning {{comparison of 0 <= unsigned enum expression is always true}} + return 0; + if (0U > a) // expected-warning {{comparison of 0 > unsigned enum expression is always false}} + return 0; + + if (b < 0) // expected-warning {{comparison of unsigned enum expression < 0 is always false}} + return 0; + if (b >= 0) // expected-warning {{comparison of unsigned enum expression >= 0 is always true}} + return 0; + if (0 <= b) // expected-warning {{comparison of 0 <= unsigned enum expression is always true}} + return 0; + if (0 > b) // expected-warning {{comparison of 0 > unsigned enum expression is always false}} + return 0; + if (b < 0U) // expected-warning {{comparison of unsigned enum expression < 0 is always false}} + return 0; + if (b >= 0U) // expected-warning {{comparison of unsigned enum expression >= 0 is always true}} + return 0; + if (0U <= b) // expected-warning {{comparison of 0 <= unsigned enum expression is always true}} + return 0; + if (0U > b) // expected-warning {{comparison of 0 > unsigned enum expression is always false}} + return 0; + + if (c < 0) // ok + return 0; + if (c >= 0) // ok + return 0; + if (0 <= c) // ok + return 0; + if (0 > c) // ok + return 0; + if (c < 0U) // expected-warning {{comparison of unsigned enum expression < 0 is always false}} + return 0; + if (c >= 0U) // expected-warning {{comparison of unsigned enum expression >= 0 is always true}} + return 0; + if (0U <= c) // expected-warning {{comparison of 0 <= unsigned enum expression is always true}} + return 0; + if (0U > c) // expected-warning {{comparison of 0 > unsigned enum expression is always false}} + return 0; +#else + // expected-no-diagnostics + if (a < 0) + return 0; + if (a >= 0) + return 0; + if (0 <= a) + return 0; + if (0 > a) + return 0; + if (a < 0U) + return 0; + if (a >= 0U) + return 0; + if (0U <= a) + return 0; + if (0U > a) + return 0; + + if (b < 0) + return 0; + if (b >= 0) + return 0; + if (0 <= b) + return 0; + if (0 > b) + return 0; + if (b < 0U) + return 0; + if (b >= 0U) + return 0; + if (0U <= b) + return 0; + if (0U > b) + return 0; + + if (c < 0) + return 0; + if (c >= 0) + return 0; + if (0 <= c) + return 0; + if (0 > c) + return 0; + if (c < 0U) + return 0; + if (c >= 0U) + return 0; + if (0U <= c) + return 0; + if (0U > c) + return 0; +#endif + + return 1; +} -- 2.40.0