r316268 - [Sema] Fixes for enum handling for tautological comparison diagnostics
Roman Lebedev via cfe-commits
cfe-commits at lists.llvm.org
Tue Oct 24 14:07:29 PDT 2017
On Tue, Oct 24, 2017 at 3:00 PM, Hans Wennborg <hans at chromium.org> wrote:
> On Mon, Oct 23, 2017 at 2:02 PM, Roman Lebedev <lebedev.ri at gmail.com> wrote:
>> On Mon, Oct 23, 2017 at 2:13 PM, Hans Wennborg <hans at chromium.org> wrote:
>> Hi.
>>
>>> This seems to have had the side effect of introducing a new warning in
>>> Chromium builds:
>>>
>>> ../../third_party/expat/files/lib/xmlparse.c(2429,24): error:
>>> comparison of integers of different signs: 'enum XML_Error' and
>>> 'unsigned int' [-Werror,-Wsign-compare]
>>> if (code > 0 && code < sizeof(message)/sizeof(message[0]))
>>> ~~~~ ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>> (I guess this is on windows)
>
> Yes.
>
>>
>>> I'm not sure if this was intentional or not.
>>>
>>> The warning seems technically correct here, though not very useful in
>>> this specific case.
>> I *believe* that was caused by the fix for IntRange::forValueOfCanonicalType()
>> to use enum's underlying type for C code. That fix was absolutely intentional.
>>
>> However that new -Wsign-compare diagnostic (and i suspect there may be
>> more repercussions) was not really intentional.
>> However as you have said, and i think i agree, the diagnostic valid.
>>
>> So perhaps i simply should add a test and release notes entry?
>
> Sounds reasonable. It turns out we only got this single extra
> -Wsign-compare warning, so it didn't turn out to be a big problem for
> us.
Ok, committed in https://reviews.llvm.org/rL316500
Roman.
>>
>> Roman.
>>
>>> On Sat, Oct 21, 2017 at 6:44 PM, Roman Lebedev via cfe-commits
>>> <cfe-commits at lists.llvm.org> wrote:
>>>> Author: lebedevri
>>>> Date: Sat Oct 21 09:44:03 2017
>>>> New Revision: 316268
>>>>
>>>> URL: http://llvm.org/viewvc/llvm-project?rev=316268&view=rev
>>>> Log:
>>>> [Sema] Fixes for enum handling for tautological comparison diagnostics
>>>>
>>>> Summary:
>>>> As Mattias Eriksson has reported in PR35009, in C, for enums, the underlying type should
>>>> be used when checking for the tautological comparison, unlike C++, where the enumerator
>>>> values define the value range. So if not in CPlusPlus mode, use the enum underlying type.
>>>>
>>>> Also, i have discovered a problem (a crash) when evaluating tautological-ness of the following comparison:
>>>> ```
>>>> enum A { A_a = 0 };
>>>> if (a < 0) // expected-warning {{comparison of unsigned enum expression < 0 is always false}}
>>>> return 0;
>>>> ```
>>>> This affects both the C and C++, but after the first fix, only C++ code was affected.
>>>> That was also fixed, while preserving (i think?) the proper diagnostic output.
>>>>
>>>> And while there, attempt to enhance the test coverage.
>>>> Yes, some tests got moved around, sorry about that :)
>>>>
>>>> Fixes PR35009
>>>>
>>>> Reviewers: aaron.ballman, rsmith, rjmccall
>>>>
>>>> Reviewed By: aaron.ballman
>>>>
>>>> Subscribers: Rakete1111, efriedma, materi, cfe-commits
>>>>
>>>> Tags: #clang
>>>>
>>>> Differential Revision: https://reviews.llvm.org/D39122
>>>>
>>>> Added:
>>>> cfe/trunk/test/Sema/outof-range-enum-constant-compare.c
>>>> cfe/trunk/test/Sema/tautological-constant-enum-compare.c
>>>> Modified:
>>>> cfe/trunk/lib/Sema/SemaChecking.cpp
>>>> cfe/trunk/test/Sema/tautological-unsigned-enum-zero-compare.c
>>>> cfe/trunk/test/Sema/tautological-unsigned-enum-zero-compare.cpp
>>>>
>>>> Modified: cfe/trunk/lib/Sema/SemaChecking.cpp
>>>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaChecking.cpp?rev=316268&r1=316267&r2=316268&view=diff
>>>> ==============================================================================
>>>> --- cfe/trunk/lib/Sema/SemaChecking.cpp (original)
>>>> +++ cfe/trunk/lib/Sema/SemaChecking.cpp Sat Oct 21 09:44:03 2017
>>>> @@ -8181,8 +8181,12 @@ struct IntRange {
>>>> 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.
>>>> @@ -8584,8 +8588,10 @@ bool isNonBooleanUnsignedValue(Expr *E)
>>>> }
>>>>
>>>> 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
>>>> @@ -8608,6 +8614,10 @@ llvm::Optional<LimitType> IsTypeLimit(Se
>>>>
>>>> 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()),
>>>> @@ -8620,7 +8630,7 @@ llvm::Optional<LimitType> IsTypeLimit(Se
>>>> Value))
>>>> return LimitType::Min;
>>>>
>>>> - return llvm::Optional<LimitType>();
>>>> + return llvm::None;
>>>> }
>>>>
>>>> bool HasEnumType(Expr *E) {
>>>> @@ -8655,9 +8665,12 @@ bool CheckTautologicalComparison(Sema &S
>>>>
>>>> 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;
>>>>
>>>> Added: cfe/trunk/test/Sema/outof-range-enum-constant-compare.c
>>>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/outof-range-enum-constant-compare.c?rev=316268&view=auto
>>>> ==============================================================================
>>>> --- cfe/trunk/test/Sema/outof-range-enum-constant-compare.c (added)
>>>> +++ cfe/trunk/test/Sema/outof-range-enum-constant-compare.c Sat Oct 21 09:44:03 2017
>>>> @@ -0,0 +1,379 @@
>>>> +// 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;
>>>> +}
>>>>
>>>> Added: cfe/trunk/test/Sema/tautological-constant-enum-compare.c
>>>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/tautological-constant-enum-compare.c?rev=316268&view=auto
>>>> ==============================================================================
>>>> --- cfe/trunk/test/Sema/tautological-constant-enum-compare.c (added)
>>>> +++ cfe/trunk/test/Sema/tautological-constant-enum-compare.c Sat Oct 21 09:44:03 2017
>>>> @@ -0,0 +1,419 @@
>>>> +// 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;
>>>> +}
>>>>
>>>> Modified: cfe/trunk/test/Sema/tautological-unsigned-enum-zero-compare.c
>>>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/tautological-unsigned-enum-zero-compare.c?rev=316268&r1=316267&r2=316268&view=diff
>>>> ==============================================================================
>>>> --- cfe/trunk/test/Sema/tautological-unsigned-enum-zero-compare.c (original)
>>>> +++ cfe/trunk/test/Sema/tautological-unsigned-enum-zero-compare.c Sat Oct 21 09:44:03 2017
>>>> @@ -1,5 +1,5 @@
>>>> -// 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.
>>>> @@ -7,62 +7,254 @@
>>>> // 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;
>>>> }
>>>>
>>>> Modified: cfe/trunk/test/Sema/tautological-unsigned-enum-zero-compare.cpp
>>>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/tautological-unsigned-enum-zero-compare.cpp?rev=316268&r1=316267&r2=316268&view=diff
>>>> ==============================================================================
>>>> --- cfe/trunk/test/Sema/tautological-unsigned-enum-zero-compare.cpp (original)
>>>> +++ cfe/trunk/test/Sema/tautological-unsigned-enum-zero-compare.cpp Sat Oct 21 09:44:03 2017
>>>> @@ -1,176 +1,347 @@
>>>> -// 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
>>>>
>>>>
>>>> _______________________________________________
>>>> cfe-commits mailing list
>>>> cfe-commits at lists.llvm.org
>>>> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
More information about the cfe-commits
mailing list