Replace r313747, don't always warn on enums, rework testcases.
authorRoman Lebedev <lebedev.ri@gmail.com>
Wed, 20 Sep 2017 13:50:01 +0000 (13:50 +0000)
committerRoman Lebedev <lebedev.ri@gmail.com>
Wed, 20 Sep 2017 13:50:01 +0000 (13:50 +0000)
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.

llvm-svn: 313756

clang/lib/Sema/SemaChecking.cpp
clang/test/Sema/tautological-unsigned-enum-zero-compare.c
clang/test/Sema/tautological-unsigned-enum-zero-compare.cpp [new file with mode: 0644]

index 9ff8f63..87634ad 100644 (file)
@@ -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)
index a0c2a30..49982a9 100644 (file)
@@ -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/clang/test/Sema/tautological-unsigned-enum-zero-compare.cpp b/clang/test/Sema/tautological-unsigned-enum-zero-compare.cpp
new file mode 100644 (file)
index 0000000..3e78626
--- /dev/null
@@ -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;
+}