This is the mail archive of the
gcc-help@gcc.gnu.org
mailing list for the GCC project.
Re: 64-bit enums and left shift operator - invalid code or GCC bug?
- From: Andrew Haley <aph at redhat dot com>
- To: jens dot kilian at verigy dot com
- Cc: gcc-help at gcc dot gnu dot org
- Date: Fri, 27 Jun 2008 13:16:45 +0100
- Subject: Re: 64-bit enums and left shift operator - invalid code or GCC bug?
- References: <20080627115346.GB29062@socle119.verigy.net>
Jens Kilian wrote:
> Consider the following test program:
> --8<------------------------------------------------8<---
> #include <stdint.h>
> #include <stdio.h>
>
> typedef enum {
> FOO = 1LL << 0,
> BAR = 1LL << 1,
> BAZ = 1LL << 63
> } Foo;
>
> int
> main(void)
> {
> uint64_t zip = (FOO << 32) | BAR;
> uint64_t qux = ((Foo)FOO << 32) | BAR;
> printf("%llx %llx\n", zip, qux);
> return 0;
> }
> --8<------------------------------------------------8<---
>
> This causes different behavior in GCC 3.2.3 (i386) vs. 4.1.2 (x86_64):
>
> ~ % gcc -v
> Reading specs from /usr/lib/gcc-lib/i386-redhat-linux/3.2.3/specs
> Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --enable-shared --enable-threads=posix --disable-checking --with-system-zlib --enable-__cxa_atexit --host=i386-redhat-linux
> Thread model: posix
> gcc version 3.2.3 20030502 (Red Hat Linux 3.2.3-54)
> ~ % gcc -o foo foo.c
> ~ % ./foo
> 100000002 100000002
>
> ~ % gcc -v
> Using built-in specs.
> Target: x86_64-redhat-linux
> Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --enable-shared --enable-threads=posix --enable-checking=release --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-libgcj-multifile --enable-languages=c,c++,objc,obj-c++,java,fortran,ada --enable-java-awt=gtk --disable-dssi --enable-plugin --with-java-home=/usr/lib/jvm/java-1.4.2-gcj-1.4.2.0/jre --with-cpu=generic --host=x86_64-redhat-linux
> Thread model: posix
> gcc version 4.1.2 20070626 (Red Hat 4.1.2-14)
> ~ % gcc -o foo foo.c
> foo.c: In function 'main':
> foo.c:13: warning: left shift count >= width of type
> ~ % ./foo
> 2 100000002
>
> Apparently GCC 4.1.2 converts the value of FOO to 32 bits before doing the
> shift; the bizarre thing is that casting to Foo (which should be unnecessary)
> avoids this.
>
> Is this a GCC bug, or does the standard really require this conversion?
It's a bug. C99 says an enumerated type shall be large enough to
represent all its members, and that when promoting the rank of the
enumerated type shall equal the rank of the compatible integer type.
Andrew.