http://gcc.gnu.org/bugzilla/show_bug.cgi?id=58559
Bug ID: 58559 Summary: Underlying type of enum is hybrid of int and unsigned Product: gcc Version: 4.7.3 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: cyp561 at gmail dot com An enum with no values outside the range 0..INT_MAX seems to be treated as an int in all cases, with the exception that casting to long or long long does not sign extend. As far as I understand, the compiler is free to decide to use either int or unsigned to represent an enum, but not some hybrid. Assuming e is an enum represented by an int, I think the comparison "((long long)e < 0" should not be always false. If e is an enum represented by an unsigned, the warning would be valid, but "e < 0" should then also be always false. Compiling as plain C or adding a value larger than INT_MAX, enums seem to be consistently unsigned. Adding a negative value, enums seem to be consistently signed. The same thing happens in all versions: 3.4.6 4.1.2 4.2.4 4.3.6 4.4.7 4.5.4 4.6.4 4.7.3 {{{ /* { dg-do run } */ /* { dg-options "-fno-strict-enums -Wtype-limits" } */ extern "C" void abort(); enum E {A, B}; long long f(int x) { return x; } long long f(unsigned x) { return x; } int main() { E e = (E)-1; if (sizeof(e) >= sizeof(long long)) // First check that test makes sense. return 0; if (((long long)e < 0) != (e < 0)) /* { dg-bogus "comparison is always false" } */ abort(); if (((long long)e < 0) != (f(e) < 0)) /* { dg-bogus "comparison is always false" } */ abort(); } }}}