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.)