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

Reply via email to