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();
}
}}}

Reply via email to