* long bit-fields with g++ 4.4.1
@ 2010-03-11 20:31 Vineet Soni
2010-03-12 13:49 ` Cedric Roux
2010-03-16 14:56 ` Ian Lance Taylor
0 siblings, 2 replies; 5+ messages in thread
From: Vineet Soni @ 2010-03-11 20:31 UTC (permalink / raw)
To: gcc-help
The integral promotion behavior of long bit-fields has changed with g++ 4.4.1 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;
}
Based on my interpretation of the C++ standard, the expected output is:
100000000 200000000 100000000
8000 100000000 8000
The actual output is:
$ g++-4.4.1 -Wall -pedantic x.c; ./a.out
100000000 200000000 100000000
8000 0 0
Is this a bug?
Note that 4.0.2 matches the expected output:
$ g++-4.0.2 -Wall -pedantic x.c; ./a.out
100000000 200000000 100000000
8000 100000000 8000
GCC versions used:
$ gcc-4.0.2 -v
Using built-in specs.
Target: x86_64-unknown-linux-gnu
Configured with: ../../src/gcc-4.0.2/configure
--prefix=/home/global/Linux-x86_64-rhel3/encap/gcc-4.0.2 --disable-libgcj
--enable-languages=c,c++
Thread model: posix
gcc version 4.0.2
$ gcc-4.4.1 -v
Using built-in specs.
Target: x86_64-unknown-linux-gnu
Configured with: ./configure
--prefix=/home/global/Linux-x86_64-rhel5/encap/gcc-4.4.1 --disable-libgcj
--enable-languages=c,c++
--with-mpfr=/home/global/Linux-x86_64-rhel5/encap/mpfr-2.4.1
Thread model: posix
gcc version 4.4.1 (GCC)
-- Vineet
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: long bit-fields with g++ 4.4.1
2010-03-11 20:31 long bit-fields with g++ 4.4.1 Vineet Soni
@ 2010-03-12 13:49 ` Cedric Roux
2010-03-12 16:17 ` Vineet Soni
2010-03-16 14:56 ` Ian Lance Taylor
1 sibling, 1 reply; 5+ messages in thread
From: Cedric Roux @ 2010-03-12 13:49 UTC (permalink / raw)
To: Vineet Soni; +Cc: gcc-help
Vineet Soni wrote:
> The integral promotion behavior of long bit-fields has changed with g++ 4.4.1 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;
> }
>
> Based on my interpretation of the C++ standard, the expected output is:
>
> 100000000 200000000 100000000
> 8000 100000000 8000
>
> The actual output is:
>
> $ g++-4.4.1 -Wall -pedantic x.c; ./a.out
> 100000000 200000000 100000000
> 8000 0 0
>
> Is this a bug?
>
> Note that 4.0.2 matches the expected output:
>
> $ g++-4.0.2 -Wall -pedantic x.c; ./a.out
> 100000000 200000000 100000000
> 8000 100000000 8000
If that is what you refer to:
3 An rvalue for an integral bit-field (_class.bit_) 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.
(found on the internet, I don't have the standard)
we can understand that "t" may be promoted to "int" (which is 32b) because
it occupies 16 bits. And the << arithmetic operator asks for the
promotion.
Maybe that's why you have 0.
Maybe that's the way it has to be and gcc 4.0.2 was wrong.
Note that doing:
printf("%lx %lx %lx\n", (T)t.f, (T)((unsigned long)t.f << 17), (T)(((unsigned long)t.f << 17) >> 17));
prints what you wait (not 0)
(with a g++ 4.3.2, not even 4.4.1)
(Note that I am not involved in g++ or gcc development nor
C++ standardization, so all what I say may be totally wrong.)
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: long bit-fields with g++ 4.4.1
2010-03-12 13:49 ` Cedric Roux
@ 2010-03-12 16:17 ` Vineet Soni
0 siblings, 0 replies; 5+ messages in thread
From: Vineet Soni @ 2010-03-12 16:17 UTC (permalink / raw)
To: Cedric Roux; +Cc: gcc-help
Cedric Roux wrote:
>
> If that is what you refer to:
> 3 An rvalue for an integral bit-field (_class.bit_) 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.
> (found on the internet, I don't have the standard)
>
> we can understand that "t" may be promoted to "int" (which is 32b) because
> it occupies 16 bits. And the << arithmetic operator asks for the
> promotion.
>
> Maybe that's why you have 0.
> Maybe that's the way it has to be and gcc 4.0.2 was wrong.
Your citation applies, but my interpretation differs:
In C++ a bit-field has the declared type; the number of bits is not part of its
type [1][2]. The C++ integer promotion rules apply [your citation above]; in
particular the clause: "If the bit-field is larger yet, no integral promotion
applies to it". A bit-field expression of declared type long is unchanged by
integer promotions, since (the number of bits in the bit-field being irrelevant)
long is larger than int and unsigned int. 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] C++ Standard Core Language Issue #303
(http://www.open-std.org/JTC1/SC22/WG21/docs/cwg_closed.html#303)
>
> Note that doing:
> printf("%lx %lx %lx\n", (T)t.f, (T)((unsigned long)t.f << 17),
> (T)(((unsigned long)t.f << 17) >> 17));
> prints what you wait (not 0)
> (with a g++ 4.3.2, not even 4.4.1)
Yes, we can cast, but the question is what is the correct behavior in the absence of
a cast. I don't want to find all the places in existing code where a cast might
be necessary, if 4.4.1 behavior is a bug.
-- Vineet
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: long bit-fields with g++ 4.4.1
2010-03-11 20:31 long bit-fields with g++ 4.4.1 Vineet Soni
2010-03-12 13:49 ` Cedric Roux
@ 2010-03-16 14:56 ` Ian Lance Taylor
2010-03-16 18:17 ` Vineet Soni
1 sibling, 1 reply; 5+ messages in thread
From: Ian Lance Taylor @ 2010-03-16 14:56 UTC (permalink / raw)
To: Vineet Soni; +Cc: gcc-help
Vineet Soni <vsoni@tilera.com> writes:
> The integral promotion behavior of long bit-fields has changed with g++ 4.4.1 on
> x86_64-linux, and appears broken.
That looks broken to me too. Please file a bug report following the
directions at http://gcc.gnu.org/bugs/ . Thanks.
Ian
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: long bit-fields with g++ 4.4.1
2010-03-16 14:56 ` Ian Lance Taylor
@ 2010-03-16 18:17 ` Vineet Soni
0 siblings, 0 replies; 5+ messages in thread
From: Vineet Soni @ 2010-03-16 18:17 UTC (permalink / raw)
To: Ian Lance Taylor; +Cc: gcc-help
Ian Lance Taylor wrote:
> That looks broken to me too. Please file a bug report following the
> directions at http://gcc.gnu.org/bugs/ . Thanks.
Filed as:
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=43393
Thanks.
Vineet
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2010-03-16 17:59 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-03-11 20:31 long bit-fields with g++ 4.4.1 Vineet Soni
2010-03-12 13:49 ` Cedric Roux
2010-03-12 16:17 ` Vineet Soni
2010-03-16 14:56 ` Ian Lance Taylor
2010-03-16 18:17 ` Vineet Soni
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).