The integral promotion behavior of long bit-fields has changed with g++ 4.4.0
on x86_64-linux, and appears broken. Consider:
#include
#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):
1 2 1
8000 1 8000
The actual output is:
$ g++44 -Wall -pedantic x.c; ./a.out
1 2 1
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
1 2 1
8000 1 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:
1 2 1
8000 1 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