The integral promotion behavior of long bit-fields has changed with g++ 4.4.0 on x86_64-linux, and appears broken. Consider:
#include <stdio.h> #define T unsigned long int main() { struct { T f : 33; } s = { 1UL << 32 }; printf("%lx %lx %lx\n", (T)s.f, (T)(s.f << 1), (T)((s.f << 1) >> 1)); struct { T f : 16; } t = { 1UL << 15 }; printf("%lx %lx %lx\n", (T)t.f, (T)(t.f << 17), (T)((t.f << 17) >> 17)); return 0; } In C++, the expected output is (rationale below): 100000000 200000000 100000000 8000 100000000 8000 The actual output is: $ g++44 -Wall -pedantic x.c; ./a.out 100000000 200000000 100000000 8000 0 0 Note that 4.1.2 matches the expected output (more recent releases may also match, but I don't have one handy): $ g++ -Wall -pedantic x.c; ./a.out 100000000 200000000 100000000 8000 100000000 8000 $ g++44 -v Using built-in specs. Target: x86_64-redhat-linux6E Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=http://bugzilla.redhat.com/bugzilla --enable-bootstrap --enable-shared --enable-threads=posix --enable-checking=release --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-languages=c,c++,fortran --disable-libgcj --with-mpfr=/builddir/build/BUILD/gcc-4.4.0-20090514/obj-x86_64-redhat-linux6E/mpfr-install/ --with-ppl=/builddir/build/BUILD/gcc-4.4.0-20090514/obj-x86_64-redhat-linux6E/ppl-install --with-cloog=/builddir/build/BUILD/gcc-4.4.0-20090514/obj-x86_64-redhat-linux6E/cloog-install --with-tune=generic --with-arch_32=i586 --build=x86_64-redhat-linux6E Thread model: posix gcc version 4.4.0 20090514 (Red Hat 4.4.0-6) (GCC) $ g++ -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 20080704 (Red Hat 4.1.2-46) Rationale for expected output: In C++ the number of bits in bit-field is not part of its type [1][2]; so in the given example, the bit-field expressions s.f and t.f are of type long. Since long is larger than int and unsigned int, no integral promotions apply [3], so the expected output is: 100000000 200000000 100000000 8000 100000000 8000 [1] ISO/IEC 14882-1998 [class.bit] The bit-field attribute is not part of the type of the class member. [2] http://www.open-std.org/JTC1/SC22/WG21/docs/cwg_closed.html#303 [3] ISO/IEC 14882-1998 [conv.prom] An rvalue for an integral bit-field can be converted to an rvalue of type int if int can represent all the values of the bit-field; otherwise, it can be converted to unsigned int if unsigned int can represent all the values of the bit-field. If the bit-field is larger yet, no integral promotion applies to it. If the bit-field has an enumerated type, it is treated as any other value of that type for promotion purposes. -- Summary: integral promotion of long bit-fields broken in g++ 4.4.0 Product: gcc Version: 4.4.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ AssignedTo: unassigned at gcc dot gnu dot org ReportedBy: vsoni at tilera dot com http://gcc.gnu.org/bugzilla/show_bug.cgi?id=43393