if (const AtomicType *AT = dyn_cast<AtomicType>(T))
T = AT->getValueType().getTypePtr();
- // For enum types, use the known bit width of the enumerators.
- if (const EnumType *ET = dyn_cast<EnumType>(T)) {
+ if (!C.getLangOpts().CPlusPlus) {
+ // For enum types in C code, use the underlying datatype.
+ if (const EnumType *ET = dyn_cast<EnumType>(T))
+ T = ET->getDecl()->getIntegerType().getDesugaredType(C).getTypePtr();
+ } else if (const EnumType *ET = dyn_cast<EnumType>(T)) {
+ // For enum types in C++, use the known bit width of the enumerators.
EnumDecl *Enum = ET->getDecl();
// In C++11, enums without definitions can have an explicitly specified
// underlying type. Use this type to compute the range.
}
enum class LimitType {
- Max, // e.g. 32767 for short
- Min // e.g. -32768 for short
+ Max = 1U << 0U, // e.g. 32767 for short
+ Min = 1U << 1U, // e.g. -32768 for short
+ Both = Max | Min // When the value is both the Min and the Max limit at the
+ // same time; e.g. in C++, A::a in enum A { a = 0 };
};
/// Checks whether Expr 'Constant' may be the
IntRange OtherRange = IntRange::forValueOfType(S.Context, OtherT);
+ // Special-case for C++ for enum with one enumerator with value of 0.
+ if (OtherRange.Width == 0)
+ return Value == 0 ? LimitType::Both : llvm::Optional<LimitType>();
+
if (llvm::APSInt::isSameValue(
llvm::APSInt::getMaxValue(OtherRange.Width,
OtherT->isUnsignedIntegerType()),
Value))
return LimitType::Min;
- return llvm::Optional<LimitType>();
+ return llvm::None;
}
bool HasEnumType(Expr *E) {
bool ConstIsLowerBound = (Op == BO_LT || Op == BO_LE) ^ RhsConstant;
bool ResultWhenConstEqualsOther = (Op == BO_LE || Op == BO_GE);
- bool ResultWhenConstNeOther =
- ConstIsLowerBound ^ (ValueType == LimitType::Max);
- if (ResultWhenConstEqualsOther != ResultWhenConstNeOther)
+ if (ValueType != LimitType::Both) {
+ bool ResultWhenConstNeOther =
+ ConstIsLowerBound ^ (ValueType == LimitType::Max);
+ if (ResultWhenConstEqualsOther != ResultWhenConstNeOther)
+ return false; // The comparison is not tautological.
+ } else if (ResultWhenConstEqualsOther == ConstIsLowerBound)
return false; // The comparison is not tautological.
const bool Result = ResultWhenConstEqualsOther;
--- /dev/null
+// RUN: %clang_cc1 -triple=x86_64-pc-linux-gnu -fsyntax-only -DUNSIGNED -verify %s
+// RUN: %clang_cc1 -triple=x86_64-pc-win32 -fsyntax-only -DSIGNED -verify %s
+// RUN: %clang_cc1 -triple=x86_64-pc-linux-gnu -fsyntax-only -DUNSIGNED -DSILENCE -Wno-tautological-constant-out-of-range-compare -verify %s
+// RUN: %clang_cc1 -triple=x86_64-pc-win32 -fsyntax-only -DSIGNED -DSILENCE -Wno-tautological-constant-out-of-range-compare -verify %s
+
+int main() {
+ enum A { A_a = 2 };
+ enum A a;
+
+#ifdef SILENCE
+ // expected-no-diagnostics
+#endif
+
+#ifdef UNSIGNED
+#ifndef SILENCE
+ if (a < 4294967296) // expected-warning {{comparison of constant 4294967296 with expression of type 'enum A' is always true}}
+ return 0;
+ if (4294967296 >= a) // expected-warning {{comparison of constant 4294967296 with expression of type 'enum A' is always true}}
+ return 0;
+ if (a > 4294967296) // expected-warning {{comparison of constant 4294967296 with expression of type 'enum A' is always false}}
+ return 0;
+ if (4294967296 <= a) // expected-warning {{comparison of constant 4294967296 with expression of type 'enum A' is always false}}
+ return 0;
+ if (a <= 4294967296) // expected-warning {{comparison of constant 4294967296 with expression of type 'enum A' is always true}}
+ return 0;
+ if (4294967296 > a) // expected-warning {{comparison of constant 4294967296 with expression of type 'enum A' is always true}}
+ return 0;
+ if (a >= 4294967296) // expected-warning {{comparison of constant 4294967296 with expression of type 'enum A' is always false}}
+ return 0;
+ if (4294967296 < a) // expected-warning {{comparison of constant 4294967296 with expression of type 'enum A' is always false}}
+ return 0;
+ if (a == 4294967296) // expected-warning {{comparison of constant 4294967296 with expression of type 'enum A' is always false}}
+ return 0;
+ if (4294967296 != a) // expected-warning {{comparison of constant 4294967296 with expression of type 'enum A' is always true}}
+ return 0;
+ if (a != 4294967296) // expected-warning {{comparison of constant 4294967296 with expression of type 'enum A' is always true}}
+ return 0;
+ if (4294967296 == a) // expected-warning {{comparison of constant 4294967296 with expression of type 'enum A' is always false}}
+ return 0;
+
+ if (a < 4294967296U) // expected-warning {{comparison of constant 4294967296 with expression of type 'enum A' is always true}}
+ return 0;
+ if (4294967296U >= a) // expected-warning {{comparison of constant 4294967296 with expression of type 'enum A' is always true}}
+ return 0;
+ if (a > 4294967296U) // expected-warning {{comparison of constant 4294967296 with expression of type 'enum A' is always false}}
+ return 0;
+ if (4294967296U <= a) // expected-warning {{comparison of constant 4294967296 with expression of type 'enum A' is always false}}
+ return 0;
+ if (a <= 4294967296U) // expected-warning {{comparison of constant 4294967296 with expression of type 'enum A' is always true}}
+ return 0;
+ if (4294967296U > a) // expected-warning {{comparison of constant 4294967296 with expression of type 'enum A' is always true}}
+ return 0;
+ if (a >= 4294967296U) // expected-warning {{comparison of constant 4294967296 with expression of type 'enum A' is always false}}
+ return 0;
+ if (4294967296U < a) // expected-warning {{comparison of constant 4294967296 with expression of type 'enum A' is always false}}
+ return 0;
+ if (a == 4294967296U) // expected-warning {{comparison of constant 4294967296 with expression of type 'enum A' is always false}}
+ return 0;
+ if (4294967296U != a) // expected-warning {{comparison of constant 4294967296 with expression of type 'enum A' is always true}}
+ return 0;
+ if (a != 4294967296U) // expected-warning {{comparison of constant 4294967296 with expression of type 'enum A' is always true}}
+ return 0;
+ if (4294967296U == a) // expected-warning {{comparison of constant 4294967296 with expression of type 'enum A' is always false}}
+ return 0;
+#else // SILENCE
+ if (a < 4294967296)
+ return 0;
+ if (4294967296 >= a)
+ return 0;
+ if (a > 4294967296)
+ return 0;
+ if (4294967296 <= a)
+ return 0;
+ if (a <= 4294967296)
+ return 0;
+ if (4294967296 > a)
+ return 0;
+ if (a >= 4294967296)
+ return 0;
+ if (4294967296 < a)
+ return 0;
+ if (a == 4294967296)
+ return 0;
+ if (4294967296 != a)
+ return 0;
+ if (a != 4294967296)
+ return 0;
+ if (4294967296 == a)
+ return 0;
+
+ if (a < 4294967296U)
+ return 0;
+ if (4294967296U >= a)
+ return 0;
+ if (a > 4294967296U)
+ return 0;
+ if (4294967296U <= a)
+ return 0;
+ if (a <= 4294967296U)
+ return 0;
+ if (4294967296U > a)
+ return 0;
+ if (a >= 4294967296U)
+ return 0;
+ if (4294967296U < a)
+ return 0;
+ if (a == 4294967296U)
+ return 0;
+ if (4294967296U != a)
+ return 0;
+ if (a != 4294967296U)
+ return 0;
+ if (4294967296U == a)
+ return 0;
+#endif
+#elif defined(SIGNED)
+#ifndef SILENCE
+ if (a < -2147483649) // expected-warning {{comparison of constant -2147483649 with expression of type 'enum A' is always false}}
+ return 0;
+ if (-2147483649 >= a) // expected-warning {{comparison of constant -2147483649 with expression of type 'enum A' is always false}}
+ return 0;
+ if (a > -2147483649) // expected-warning {{comparison of constant -2147483649 with expression of type 'enum A' is always true}}
+ return 0;
+ if (-2147483649 <= a) // expected-warning {{comparison of constant -2147483649 with expression of type 'enum A' is always true}}
+ return 0;
+ if (a <= -2147483649) // expected-warning {{comparison of constant -2147483649 with expression of type 'enum A' is always false}}
+ return 0;
+ if (-2147483649 > a) // expected-warning {{comparison of constant -2147483649 with expression of type 'enum A' is always false}}
+ return 0;
+ if (a >= -2147483649) // expected-warning {{comparison of constant -2147483649 with expression of type 'enum A' is always true}}
+ return 0;
+ if (-2147483649 < a) // expected-warning {{comparison of constant -2147483649 with expression of type 'enum A' is always true}}
+ return 0;
+ if (a == -2147483649) // expected-warning {{comparison of constant -2147483649 with expression of type 'enum A' is always false}}
+ return 0;
+ if (-2147483649 != a) // expected-warning {{comparison of constant -2147483649 with expression of type 'enum A' is always true}}
+ return 0;
+ if (a != -2147483649) // expected-warning {{comparison of constant -2147483649 with expression of type 'enum A' is always true}}
+ return 0;
+ if (-2147483649 == a) // expected-warning {{comparison of constant -2147483649 with expression of type 'enum A' is always false}}
+ return 0;
+
+ if (a < 2147483648) // expected-warning {{comparison of constant 2147483648 with expression of type 'enum A' is always true}}
+ return 0;
+ if (2147483648 >= a) // expected-warning {{comparison of constant 2147483648 with expression of type 'enum A' is always true}}
+ return 0;
+ if (a > 2147483648) // expected-warning {{comparison of constant 2147483648 with expression of type 'enum A' is always false}}
+ return 0;
+ if (2147483648 <= a) // expected-warning {{comparison of constant 2147483648 with expression of type 'enum A' is always false}}
+ return 0;
+ if (a <= 2147483648) // expected-warning {{comparison of constant 2147483648 with expression of type 'enum A' is always true}}
+ return 0;
+ if (2147483648 > a) // expected-warning {{comparison of constant 2147483648 with expression of type 'enum A' is always true}}
+ return 0;
+ if (a >= 2147483648) // expected-warning {{comparison of constant 2147483648 with expression of type 'enum A' is always false}}
+ return 0;
+ if (2147483648 < a) // expected-warning {{comparison of constant 2147483648 with expression of type 'enum A' is always false}}
+ return 0;
+ if (a == 2147483648) // expected-warning {{comparison of constant 2147483648 with expression of type 'enum A' is always false}}
+ return 0;
+ if (2147483648 != a) // expected-warning {{comparison of constant 2147483648 with expression of type 'enum A' is always true}}
+ return 0;
+ if (a != 2147483648) // expected-warning {{comparison of constant 2147483648 with expression of type 'enum A' is always true}}
+ return 0;
+ if (2147483648 == a) // expected-warning {{comparison of constant 2147483648 with expression of type 'enum A' is always false}}
+ return 0;
+#else // SILENCE
+ if (a < -2147483649)
+ return 0;
+ if (-2147483649 >= a)
+ return 0;
+ if (a > -2147483649)
+ return 0;
+ if (-2147483649 <= a)
+ return 0;
+ if (a <= -2147483649)
+ return 0;
+ if (-2147483649 > a)
+ return 0;
+ if (a >= -2147483649)
+ return 0;
+ if (-2147483649 < a)
+ return 0;
+ if (a == -2147483649)
+ return 0;
+ if (-2147483649 != a)
+ return 0;
+ if (a != -2147483649)
+ return 0;
+ if (-2147483649 == a)
+ return 0;
+
+ if (a < 2147483648)
+ return 0;
+ if (2147483648 >= a)
+ return 0;
+ if (a > 2147483648)
+ return 0;
+ if (2147483648 <= a)
+ return 0;
+ if (a <= 2147483648)
+ return 0;
+ if (2147483648 > a)
+ return 0;
+ if (a >= 2147483648)
+ return 0;
+ if (2147483648 < a)
+ return 0;
+ if (a == 2147483648)
+ return 0;
+ if (2147483648 != a)
+ return 0;
+ if (a != 2147483648)
+ return 0;
+ if (2147483648 == a)
+ return 0;
+#endif
+#endif
+}
+
+// https://bugs.llvm.org/show_bug.cgi?id=35009
+int PR35009() {
+ enum A { A_a = 2 };
+ enum A a;
+
+ // in C, this should not warn.
+
+ if (a < 1)
+ return 0;
+ if (1 >= a)
+ return 0;
+ if (a > 1)
+ return 0;
+ if (1 <= a)
+ return 0;
+ if (a <= 1)
+ return 0;
+ if (1 > a)
+ return 0;
+ if (a >= 1)
+ return 0;
+ if (1 < a)
+ return 0;
+ if (a == 1)
+ return 0;
+ if (1 != a)
+ return 0;
+ if (a != 1)
+ return 0;
+ if (1 == a)
+ return 0;
+
+ if (a < 1U)
+ return 0;
+ if (1U >= a)
+ return 0;
+ if (a > 1U)
+ return 0;
+ if (1U <= a)
+ return 0;
+ if (a <= 1U)
+ return 0;
+ if (1U > a)
+ return 0;
+ if (a >= 1U)
+ return 0;
+ if (1U < a)
+ return 0;
+ if (a == 1U)
+ return 0;
+ if (1U != a)
+ return 0;
+ if (a != 1U)
+ return 0;
+ if (1U == a)
+ return 0;
+
+ if (a < 2)
+ return 0;
+ if (2 >= a)
+ return 0;
+ if (a > 2)
+ return 0;
+ if (2 <= a)
+ return 0;
+ if (a <= 2)
+ return 0;
+ if (2 > a)
+ return 0;
+ if (a >= 2)
+ return 0;
+ if (2 < a)
+ return 0;
+ if (a == 2)
+ return 0;
+ if (2 != a)
+ return 0;
+ if (a != 2)
+ return 0;
+ if (2 == a)
+ return 0;
+
+ if (a < 2U)
+ return 0;
+ if (2U >= a)
+ return 0;
+ if (a > 2U)
+ return 0;
+ if (2U <= a)
+ return 0;
+ if (a <= 2U)
+ return 0;
+ if (2U > a)
+ return 0;
+ if (a >= 2U)
+ return 0;
+ if (2U < a)
+ return 0;
+ if (a == 2U)
+ return 0;
+ if (2U != a)
+ return 0;
+ if (a != 2U)
+ return 0;
+ if (2U == a)
+ return 0;
+
+ if (a < 3)
+ return 0;
+ if (3 >= a)
+ return 0;
+ if (a > 3)
+ return 0;
+ if (3 <= a)
+ return 0;
+ if (a <= 3)
+ return 0;
+ if (3 > a)
+ return 0;
+ if (a >= 3)
+ return 0;
+ if (3 < a)
+ return 0;
+ if (a == 3)
+ return 0;
+ if (3 != a)
+ return 0;
+ if (a != 3)
+ return 0;
+ if (3 == a)
+ return 0;
+
+ if (a < 3U)
+ return 0;
+ if (3U >= a)
+ return 0;
+ if (a > 3U)
+ return 0;
+ if (3U <= a)
+ return 0;
+ if (a <= 3U)
+ return 0;
+ if (3U > a)
+ return 0;
+ if (a >= 3U)
+ return 0;
+ if (3U < a)
+ return 0;
+ if (a == 3U)
+ return 0;
+ if (3U != a)
+ return 0;
+ if (a != 3U)
+ return 0;
+ if (3U == a)
+ return 0;
+
+ return 1;
+}
--- /dev/null
+// RUN: %clang_cc1 -triple=x86_64-pc-linux-gnu -fsyntax-only -DUNSIGNED -verify %s
+// RUN: %clang_cc1 -triple=x86_64-pc-win32 -fsyntax-only -DSIGNED -verify %s
+// RUN: %clang_cc1 -triple=x86_64-pc-linux-gnu -fsyntax-only -DUNSIGNED -DSILENCE -Wno-tautological-constant-compare -verify %s
+// RUN: %clang_cc1 -triple=x86_64-pc-win32 -fsyntax-only -DSIGNED -DSILENCE -Wno-tautological-constant-compare -verify %s
+
+int main() {
+ enum A { A_a = 2 };
+ enum A a;
+
+#ifdef SILENCE
+ // expected-no-diagnostics
+#endif
+
+#ifdef UNSIGNED
+#ifndef SILENCE
+ if (a < 0) // expected-warning {{comparison of unsigned enum expression < 0 is always false}}
+ return 0;
+ if (0 >= a)
+ return 0;
+ if (a > 0)
+ return 0;
+ if (0 <= a) // expected-warning {{comparison of 0 <= unsigned enum expression is always true}}
+ return 0;
+ if (a <= 0)
+ return 0;
+ if (0 > a) // expected-warning {{comparison of 0 > unsigned enum expression is always false}}
+ return 0;
+ if (a >= 0) // expected-warning {{comparison of unsigned enum expression >= 0 is always true}}
+ return 0;
+ if (0 < a)
+ return 0;
+
+ if (a < 0U) // expected-warning {{comparison of unsigned enum expression < 0 is always false}}
+ return 0;
+ if (0U >= a)
+ return 0;
+ if (a > 0U)
+ return 0;
+ if (0U <= a) // expected-warning {{comparison of 0 <= unsigned enum expression is always true}}
+ return 0;
+ if (a <= 0U)
+ return 0;
+ if (0U > 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 true}}
+ return 0;
+ if (0U < a)
+ return 0;
+
+ if (a < 4294967295)
+ return 0;
+ if (4294967295 >= a) // expected-warning {{comparison 4294967295 >= 'enum A' is always true}}
+ return 0;
+ if (a > 4294967295) // expected-warning {{comparison 'enum A' > 4294967295 is always false}}
+ return 0;
+ if (4294967295 <= a)
+ return 0;
+ if (a <= 4294967295) // expected-warning {{comparison 'enum A' <= 4294967295 is always true}}
+ return 0;
+ if (4294967295 > a)
+ return 0;
+ if (a >= 4294967295)
+ return 0;
+ if (4294967295 < a) // expected-warning {{comparison 4294967295 < 'enum A' is always false}}
+ return 0;
+
+ if (a < 4294967295U)
+ return 0;
+ if (4294967295U >= a) // expected-warning {{comparison 4294967295 >= 'enum A' is always true}}
+ return 0;
+ if (a > 4294967295U) // expected-warning {{comparison 'enum A' > 4294967295 is always false}}
+ return 0;
+ if (4294967295U <= a)
+ return 0;
+ if (a <= 4294967295U) // expected-warning {{comparison 'enum A' <= 4294967295 is always true}}
+ return 0;
+ if (4294967295U > a)
+ return 0;
+ if (a >= 4294967295U)
+ return 0;
+ if (4294967295U < a) // expected-warning {{comparison 4294967295 < 'enum A' is always false}}
+ return 0;
+#else // SILENCE
+ if (a < 0)
+ return 0;
+ if (0 >= a)
+ return 0;
+ if (a > 0)
+ return 0;
+ if (0 <= a)
+ return 0;
+ if (a <= 0)
+ return 0;
+ if (0 > a)
+ return 0;
+ if (a >= 0)
+ return 0;
+ if (0 < a)
+ return 0;
+
+ if (a < 0U)
+ return 0;
+ if (0U >= a)
+ return 0;
+ if (a > 0U)
+ return 0;
+ if (0U <= a)
+ return 0;
+ if (a <= 0U)
+ return 0;
+ if (0U > a)
+ return 0;
+ if (a >= 0U)
+ return 0;
+ if (0U < a)
+ return 0;
+
+ if (a < 4294967295)
+ return 0;
+ if (4294967295 >= a)
+ return 0;
+ if (a > 4294967295)
+ return 0;
+ if (4294967295 <= a)
+ return 0;
+ if (a <= 4294967295)
+ return 0;
+ if (4294967295 > a)
+ return 0;
+ if (a >= 4294967295)
+ return 0;
+ if (4294967295 < a)
+ return 0;
+
+ if (a < 4294967295U)
+ return 0;
+ if (4294967295U >= a)
+ return 0;
+ if (a > 4294967295U)
+ return 0;
+ if (4294967295U <= a)
+ return 0;
+ if (a <= 4294967295U)
+ return 0;
+ if (4294967295U > a)
+ return 0;
+ if (a >= 4294967295U)
+ return 0;
+ if (4294967295U < a)
+ return 0;
+#endif
+#elif defined(SIGNED)
+#ifndef SILENCE
+ if (a < -2147483648) // expected-warning {{comparison 'enum A' < -2147483648 is always false}}
+ return 0;
+ if (-2147483648 >= a)
+ return 0;
+ if (a > -2147483648)
+ return 0;
+ if (-2147483648 <= a) // expected-warning {{comparison -2147483648 <= 'enum A' is always true}}
+ return 0;
+ if (a <= -2147483648)
+ return 0;
+ if (-2147483648 > a) // expected-warning {{comparison -2147483648 > 'enum A' is always false}}
+ return 0;
+ if (a >= -2147483648) // expected-warning {{comparison 'enum A' >= -2147483648 is always true}}
+ return 0;
+ if (-2147483648 < a)
+ return 0;
+
+ if (a < 2147483647)
+ return 0;
+ if (2147483647 >= a) // expected-warning {{comparison 2147483647 >= 'enum A' is always true}}
+ return 0;
+ if (a > 2147483647) // expected-warning {{comparison 'enum A' > 2147483647 is always false}}
+ return 0;
+ if (2147483647 <= a)
+ return 0;
+ if (a <= 2147483647) // expected-warning {{comparison 'enum A' <= 2147483647 is always true}}
+ return 0;
+ if (2147483647 > a)
+ return 0;
+ if (a >= 2147483647)
+ return 0;
+ if (2147483647 < a) // expected-warning {{comparison 2147483647 < 'enum A' is always false}}
+ return 0;
+
+ if (a < 2147483647U)
+ return 0;
+ if (2147483647U >= a) // expected-warning {{comparison 2147483647 >= 'enum A' is always true}}
+ return 0;
+ if (a > 2147483647U) // expected-warning {{comparison 'enum A' > 2147483647 is always false}}
+ return 0;
+ if (2147483647U <= a)
+ return 0;
+ if (a <= 2147483647U) // expected-warning {{comparison 'enum A' <= 2147483647 is always true}}
+ return 0;
+ if (2147483647U > a)
+ return 0;
+ if (a >= 2147483647U)
+ return 0;
+ if (2147483647U < a) // expected-warning {{comparison 2147483647 < 'enum A' is always false}}
+ return 0;
+#else // SILENCE
+ if (a < -2147483648)
+ return 0;
+ if (-2147483648 >= a)
+ return 0;
+ if (a > -2147483648)
+ return 0;
+ if (-2147483648 <= a)
+ return 0;
+ if (a <= -2147483648)
+ return 0;
+ if (-2147483648 > a)
+ return 0;
+ if (a >= -2147483648)
+ return 0;
+ if (-2147483648 < a)
+ return 0;
+
+ if (a < 2147483647)
+ return 0;
+ if (2147483647 >= a)
+ return 0;
+ if (a > 2147483647)
+ return 0;
+ if (2147483647 <= a)
+ return 0;
+ if (a <= 2147483647)
+ return 0;
+ if (2147483647 > a)
+ return 0;
+ if (a >= 2147483647)
+ return 0;
+ if (2147483647 < a)
+ return 0;
+
+ if (a < 2147483647U)
+ return 0;
+ if (2147483647U >= a)
+ return 0;
+ if (a > 2147483647U)
+ return 0;
+ if (2147483647U <= a)
+ return 0;
+ if (a <= 2147483647U)
+ return 0;
+ if (2147483647U > a)
+ return 0;
+ if (a >= 2147483647U)
+ return 0;
+ if (2147483647U < a)
+ return 0;
+#endif
+#endif
+
+ return 1;
+}
+
+// https://bugs.llvm.org/show_bug.cgi?id=35009
+int PR35009() {
+ enum A { A_a = 2 };
+ enum A a;
+
+ // in C, this should not warn.
+
+ if (a < 1)
+ return 0;
+ if (1 >= a)
+ return 0;
+ if (a > 1)
+ return 0;
+ if (1 <= a)
+ return 0;
+ if (a <= 1)
+ return 0;
+ if (1 > a)
+ return 0;
+ if (a >= 1)
+ return 0;
+ if (1 < a)
+ return 0;
+ if (a == 1)
+ return 0;
+ if (1 != a)
+ return 0;
+ if (a != 1)
+ return 0;
+ if (1 == a)
+ return 0;
+
+ if (a < 1U)
+ return 0;
+ if (1U >= a)
+ return 0;
+ if (a > 1U)
+ return 0;
+ if (1U <= a)
+ return 0;
+ if (a <= 1U)
+ return 0;
+ if (1U > a)
+ return 0;
+ if (a >= 1U)
+ return 0;
+ if (1U < a)
+ return 0;
+ if (a == 1U)
+ return 0;
+ if (1U != a)
+ return 0;
+ if (a != 1U)
+ return 0;
+ if (1U == a)
+ return 0;
+
+ if (a < 2)
+ return 0;
+ if (2 >= a)
+ return 0;
+ if (a > 2)
+ return 0;
+ if (2 <= a)
+ return 0;
+ if (a <= 2)
+ return 0;
+ if (2 > a)
+ return 0;
+ if (a >= 2)
+ return 0;
+ if (2 < a)
+ return 0;
+ if (a == 2)
+ return 0;
+ if (2 != a)
+ return 0;
+ if (a != 2)
+ return 0;
+ if (2 == a)
+ return 0;
+
+ if (a < 2U)
+ return 0;
+ if (2U >= a)
+ return 0;
+ if (a > 2U)
+ return 0;
+ if (2U <= a)
+ return 0;
+ if (a <= 2U)
+ return 0;
+ if (2U > a)
+ return 0;
+ if (a >= 2U)
+ return 0;
+ if (2U < a)
+ return 0;
+ if (a == 2U)
+ return 0;
+ if (2U != a)
+ return 0;
+ if (a != 2U)
+ return 0;
+ if (2U == a)
+ return 0;
+
+ if (a < 3)
+ return 0;
+ if (3 >= a)
+ return 0;
+ if (a > 3)
+ return 0;
+ if (3 <= a)
+ return 0;
+ if (a <= 3)
+ return 0;
+ if (3 > a)
+ return 0;
+ if (a >= 3)
+ return 0;
+ if (3 < a)
+ return 0;
+ if (a == 3)
+ return 0;
+ if (3 != a)
+ return 0;
+ if (a != 3)
+ return 0;
+ if (3 == a)
+ return 0;
+
+ if (a < 3U)
+ return 0;
+ if (3U >= a)
+ return 0;
+ if (a > 3U)
+ return 0;
+ if (3U <= a)
+ return 0;
+ if (a <= 3U)
+ return 0;
+ if (3U > a)
+ return 0;
+ if (a >= 3U)
+ return 0;
+ if (3U < a)
+ return 0;
+ if (a == 3U)
+ return 0;
+ if (3U != a)
+ return 0;
+ if (a != 3U)
+ return 0;
+ if (3U == a)
+ return 0;
+
+ return 1;
+}
-// 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-linux-gnu -fsyntax-only -DUNSIGNED -verify %s
+// RUN: %clang_cc1 -triple=x86_64-pc-win32 -fsyntax-only -DSIGNED -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.
// 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_a = 0 };
enum A a;
+ enum B { B_a = -1 };
+ enum B b;
-#ifdef ALL_WARN
+#ifdef UNSIGNED
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}}
+ if (0 >= a)
+ return 0;
+ if (a > 0)
return 0;
if (0 <= a) // expected-warning {{comparison of 0 <= unsigned enum expression is always true}}
return 0;
+ if (a <= 0)
+ return 0;
if (0 > a) // expected-warning {{comparison of 0 > unsigned enum expression is always false}}
return 0;
+ if (a >= 0) // expected-warning {{comparison of unsigned enum expression >= 0 is always true}}
+ return 0;
+ if (0 < a)
+ 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}}
+ if (0U >= a)
+ return 0;
+ if (a > 0U)
return 0;
if (0U <= a) // expected-warning {{comparison of 0 <= unsigned enum expression is always true}}
return 0;
+ if (a <= 0U)
+ 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
+ if (a >= 0U) // expected-warning {{comparison of unsigned enum expression >= 0 is always true}}
+ return 0;
+ if (0U < a)
+ return 0;
+
+ if (b < 0)
+ return 0;
+ if (0 >= b)
+ return 0;
+ if (b > 0)
+ return 0;
+ if (0 <= b)
+ return 0;
+ if (b <= 0)
+ return 0;
+ if (0 > b)
+ return 0;
+ if (b >= 0)
+ return 0;
+ if (0 < b)
+ return 0;
+
+ if (b < 0U) // expected-warning {{comparison of unsigned enum expression < 0 is always false}}
+ return 0;
+ if (0U >= b)
+ return 0;
+ if (b > 0U)
+ return 0;
+ if (0U <= b) // expected-warning {{comparison of 0 <= unsigned enum expression is always true}}
+ return 0;
+ if (b <= 0U)
+ return 0;
+ if (0U > 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 true}}
return 0;
- if (a >= 0) // ok
+ if (0U < b)
return 0;
- if (0 <= a) // ok
+#elif defined(SIGNED)
+ if (a < 0)
+ return 0;
+ if (0 >= a)
+ return 0;
+ if (a > 0)
+ return 0;
+ if (0 <= a)
+ return 0;
+ if (a <= 0)
return 0;
- if (0 > a) // ok
+ if (0 > a)
return 0;
+ if (a >= 0)
+ return 0;
+ if (0 < a)
+ 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}}
+ if (0U >= a)
+ return 0;
+ if (a > 0U)
return 0;
if (0U <= a) // expected-warning {{comparison of 0 <= unsigned enum expression is always true}}
return 0;
+ if (a <= 0U)
+ return 0;
if (0U > 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 true}}
+ return 0;
+ if (0U < a)
+ return 0;
+
+ if (b < 0)
+ return 0;
+ if (0 >= b)
+ return 0;
+ if (b > 0)
+ return 0;
+ if (0 <= b)
+ return 0;
+ if (b <= 0)
+ return 0;
+ if (0 > b)
+ return 0;
+ if (b >= 0)
+ return 0;
+ if (0 < b)
+ return 0;
+
+ if (b < 0U) // expected-warning {{comparison of unsigned enum expression < 0 is always false}}
+ return 0;
+ if (0U >= b)
+ return 0;
+ if (b > 0U)
+ return 0;
+ if (0U <= b) // expected-warning {{comparison of 0 <= unsigned enum expression is always true}}
+ return 0;
+ if (b <= 0U)
+ return 0;
+ if (0U > 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 true}}
+ return 0;
+ if (0U < b)
+ return 0;
#else
// expected-no-diagnostics
+
if (a < 0)
return 0;
- if (a >= 0)
+ if (0 >= a)
+ return 0;
+ if (a > 0)
return 0;
if (0 <= a)
return 0;
+ if (a <= 0)
+ return 0;
if (0 > a)
return 0;
+ if (a >= 0)
+ return 0;
+ if (0 < a)
+ return 0;
+
if (a < 0U)
return 0;
- if (a >= 0U)
+ if (0U >= a)
+ return 0;
+ if (a > 0U)
return 0;
if (0U <= a)
return 0;
+ if (a <= 0U)
+ return 0;
if (0U > a)
return 0;
+ if (a >= 0U)
+ return 0;
+ if (0U < a)
+ return 0;
+
+ if (b < 0)
+ return 0;
+ if (0 >= b)
+ return 0;
+ if (b > 0)
+ return 0;
+ if (0 <= b)
+ return 0;
+ if (b <= 0)
+ return 0;
+ if (0 > b)
+ return 0;
+ if (b >= 0)
+ return 0;
+ if (0 < b)
+ return 0;
+
+ if (b < 0U)
+ return 0;
+ if (0U >= b)
+ return 0;
+ if (b > 0U)
+ return 0;
+ if (0U <= b)
+ return 0;
+ if (b <= 0U)
+ return 0;
+ if (0U > b)
+ return 0;
+ if (b >= 0U)
+ return 0;
+ if (0U < b)
+ return 0;
#endif
+ if (a == 0)
+ return 0;
+ if (0 != a)
+ return 0;
+ if (a != 0)
+ return 0;
+ if (0 == a)
+ return 0;
+
+ if (a == 0U)
+ return 0;
+ if (0U != a)
+ return 0;
+ if (a != 0U)
+ return 0;
+ if (0U == a)
+ return 0;
+
+ if (b == 0)
+ return 0;
+ if (0 != b)
+ return 0;
+ if (b != 0)
+ return 0;
+ if (0 == b)
+ return 0;
+
+ if (b == 0U)
+ return 0;
+ if (0U != b)
+ return 0;
+ if (b != 0U)
+ return 0;
+ if (0U == b)
+ return 0;
+
return 1;
}
-// 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
+// RUN: %clang_cc1 -std=c++11 -triple=x86_64-pc-linux-gnu -fsyntax-only -DUNSIGNED -verify %s
+// RUN: %clang_cc1 -std=c++11 -triple=x86_64-pc-win32 -fsyntax-only -DSIGNED -verify %s
+// RUN: %clang_cc1 -std=c++11 -triple=x86_64-pc-win32 -fsyntax-only -DSILENCE -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_foo = 0, A_bar, };
enum A a;
- enum B : unsigned { B_foo, B_bar };
+ enum B : unsigned { B_foo = 0, B_bar, };
enum B b;
- enum C : signed { c_foo, c_bar };
+ enum C : signed { C_foo = 0, C_bar, };
enum C c;
-#ifdef ALL_WARN
+#ifdef UNSIGNED
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}}
+ if (0 >= a)
+ return 0;
+ if (a > 0)
return 0;
if (0 <= a) // expected-warning {{comparison of 0 <= unsigned enum expression is always true}}
return 0;
+ if (a <= 0)
+ return 0;
if (0 > a) // expected-warning {{comparison of 0 > unsigned enum expression is always false}}
return 0;
+ if (a >= 0) // expected-warning {{comparison of unsigned enum expression >= 0 is always true}}
+ return 0;
+ if (0 < a)
+ 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}}
+ if (0U >= a)
+ return 0;
+ if (a > 0U)
return 0;
if (0U <= a) // expected-warning {{comparison of 0 <= unsigned enum expression is always true}}
return 0;
+ if (a <= 0U)
+ return 0;
if (0U > 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 true}}
+ return 0;
+ if (0U < a)
+ 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}}
+ if (0 >= b)
+ return 0;
+ if (b > 0)
return 0;
if (0 <= b) // expected-warning {{comparison of 0 <= unsigned enum expression is always true}}
return 0;
+ if (b <= 0)
+ return 0;
if (0 > b) // 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 true}}
+ return 0;
+ if (0 < b)
+ 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}}
+ if (0U >= b)
+ return 0;
+ if (b > 0U)
return 0;
if (0U <= b) // expected-warning {{comparison of 0 <= unsigned enum expression is always true}}
return 0;
+ if (b <= 0U)
+ return 0;
if (0U > 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 true}}
+ return 0;
+ if (0U < b)
+ return 0;
- if (c < 0) // ok
+ if (c < 0)
+ return 0;
+ if (0 >= c) // expected-warning {{comparison 0 >= 'enum C' is always true}}
+ return 0;
+ if (c > 0) // expected-warning {{comparison 'enum C' > 0 is always false}}
+ return 0;
+ if (0 <= c)
+ return 0;
+ if (c <= 0) // expected-warning {{comparison 'enum C' <= 0 is always true}}
return 0;
- if (c >= 0) // ok
+ if (0 > c)
return 0;
- if (0 <= c) // ok
+ if (c >= 0)
return 0;
- if (0 > c) // ok
+ if (0 < c) // expected-warning {{0 < 'enum C' is always false}}
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}}
+ if (0U >= c)
+ return 0;
+ if (c > 0U)
return 0;
if (0U <= c) // expected-warning {{comparison of 0 <= unsigned enum expression is always true}}
return 0;
+ if (c <= 0U)
+ 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
+ if (c >= 0U) // expected-warning {{comparison of unsigned enum expression >= 0 is always true}}
return 0;
- if (a >= 0) // ok
+ if (0U < c)
return 0;
- if (0 <= a) // ok
+#elif defined(SIGNED)
+ if (a < 0)
+ return 0;
+ if (0 >= a) // expected-warning {{comparison 0 >= 'enum A' is always true}}
return 0;
- if (0 > a) // ok
+ if (a > 0) // expected-warning {{comparison 'enum A' > 0 is always false}}
+ return 0;
+ if (0 <= a)
return 0;
+ if (a <= 0) // expected-warning {{comparison 'enum A' <= 0 is always true}}
+ return 0;
+ if (0 > a)
+ return 0;
+ if (a >= 0)
+ return 0;
+ if (0 < a) // expected-warning {{comparison 0 < 'enum A' 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}}
+ if (0U >= a)
+ return 0;
+ if (a > 0U)
return 0;
if (0U <= a) // expected-warning {{comparison of 0 <= unsigned enum expression is always true}}
return 0;
+ if (a <= 0U)
+ return 0;
if (0U > 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 true}}
+ return 0;
+ if (0U < a)
+ 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}}
+ if (0 >= b)
+ return 0;
+ if (b > 0)
return 0;
if (0 <= b) // expected-warning {{comparison of 0 <= unsigned enum expression is always true}}
return 0;
+ if (b <= 0)
+ return 0;
if (0 > b) // 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 true}}
+ return 0;
+ if (0 < b)
+ 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}}
+ if (0U >= b)
+ return 0;
+ if (b > 0U)
return 0;
if (0U <= b) // expected-warning {{comparison of 0 <= unsigned enum expression is always true}}
return 0;
+ if (b <= 0U)
+ return 0;
if (0U > 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 true}}
+ return 0;
+ if (0U < b)
+ return 0;
- if (c < 0) // ok
+ if (c < 0)
return 0;
- if (c >= 0) // ok
+ if (0 >= c) // expected-warning {{comparison 0 >= 'enum C' is always true}}
return 0;
- if (0 <= c) // ok
+ if (c > 0) // expected-warning {{comparison 'enum C' > 0 is always false}}
+ return 0;
+ if (0 <= c)
return 0;
- if (0 > c) // ok
+ if (c <= 0) // expected-warning {{comparison 'enum C' <= 0 is always true}}
+ return 0;
+ if (0 > c)
+ return 0;
+ if (c >= 0)
return 0;
+ if (0 < c) // expected-warning {{0 < 'enum C' is always false}}
+ 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}}
+ if (0U >= c)
+ return 0;
+ if (c > 0U)
return 0;
if (0U <= c) // expected-warning {{comparison of 0 <= unsigned enum expression is always true}}
return 0;
+ if (c <= 0U)
+ return 0;
if (0U > c) // expected-warning {{comparison of 0 > unsigned enum expression is always false}}
return 0;
+ if (c >= 0U) // expected-warning {{comparison of unsigned enum expression >= 0 is always true}}
+ return 0;
+ if (0U < c)
+ return 0;
#else
- // expected-no-diagnostics
if (a < 0)
return 0;
- if (a >= 0)
+ if (0 >= a) // expected-warning {{comparison 0 >= 'enum A' is always true}}
+ return 0;
+ if (a > 0) // expected-warning {{comparison 'enum A' > 0 is always false}}
return 0;
if (0 <= a)
return 0;
+ if (a <= 0) // expected-warning {{comparison 'enum A' <= 0 is always true}}
+ return 0;
if (0 > a)
return 0;
+ if (a >= 0)
+ return 0;
+ if (0 < a) // expected-warning {{comparison 0 < 'enum A' is always false}}
+ return 0;
+
if (a < 0U)
return 0;
- if (a >= 0U)
+ if (0U >= a)
+ return 0;
+ if (a > 0U)
return 0;
if (0U <= a)
return 0;
+ if (a <= 0U)
+ return 0;
if (0U > a)
return 0;
+ if (a >= 0U)
+ return 0;
+ if (0U < a)
+ return 0;
if (b < 0)
return 0;
- if (b >= 0)
+ if (0 >= b)
+ return 0;
+ if (b > 0)
return 0;
if (0 <= b)
return 0;
+ if (b <= 0)
+ return 0;
if (0 > b)
return 0;
+ if (b >= 0)
+ return 0;
+ if (0 < b)
+ return 0;
+
if (b < 0U)
return 0;
- if (b >= 0U)
+ if (0U >= b)
+ return 0;
+ if (b > 0U)
return 0;
if (0U <= b)
return 0;
+ if (b <= 0U)
+ return 0;
if (0U > b)
return 0;
+ if (b >= 0U)
+ return 0;
+ if (0U < b)
+ return 0;
if (c < 0)
return 0;
- if (c >= 0)
+ if (0 >= c) // expected-warning {{comparison 0 >= 'enum C' is always true}}
+ return 0;
+ if (c > 0) // expected-warning {{comparison 'enum C' > 0 is always false}}
return 0;
if (0 <= c)
return 0;
+ if (c <= 0) // expected-warning {{comparison 'enum C' <= 0 is always true}}
+ return 0;
if (0 > c)
return 0;
+ if (c >= 0)
+ return 0;
+ if (0 < c) // expected-warning {{0 < 'enum C' is always false}}
+ return 0;
+
if (c < 0U)
return 0;
- if (c >= 0U)
+ if (0U >= c)
+ return 0;
+ if (c > 0U)
return 0;
if (0U <= c)
return 0;
+ if (c <= 0U)
+ return 0;
if (0U > c)
return 0;
+ if (c >= 0U)
+ return 0;
+ if (0U < c)
+ return 0;
+#endif
+
+ return 1;
+}
+
+namespace crash_enum_zero_width {
+int test() {
+ enum A : unsigned {
+ A_foo = 0
+ };
+ enum A a;
+
+ // used to crash in llvm::APSInt::getMaxValue()
+#ifndef SILENCE
+ if (a < 0) // expected-warning {{comparison of unsigned enum expression < 0 is always false}}
+#else
+ if (a > 0)
#endif
+ return 0;
return 1;
}
+} // namespace crash_enum_zero_width