This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
Re: Manipulating bit fields is behaving inconsistently
- From: Richard Biener <richard dot guenther at gmail dot com>
- To: Wink Saville <wink at saville dot com>
- Cc: Bernd Edlinger <bernd dot edlinger at hotmail dot de>, "gcc at gcc dot gnu dot org" <gcc at gcc dot gnu dot org>
- Date: Fri, 19 Feb 2016 09:37:20 +0100
- Subject: Re: Manipulating bit fields is behaving inconsistently
- Authentication-results: sourceware.org; auth=none
- References: <HE1PR07MB090588653DC1A71961F97195E4AF0 at HE1PR07MB0905 dot eurprd07 dot prod dot outlook dot com> <CAKk8isp3AuFJ=_daThz-WF2VZp2vzQSsTrC0-XGLi53u9SP5Og at mail dot gmail dot com>
On Thu, Feb 18, 2016 at 5:31 PM, Wink Saville <wink@saville.com> wrote:
> You've convinced me that this isn't a bug, but I assume you'd agree
> its weird at best. I tested it with clang and it works as I'd expect:
>
> $ make
> clang -x c -m64 -O3 -Wall -o test.o -c test.c
> objdump -d test.o > test.txt
> clang -m64 -O3 -Wall test.o -o test
> wink@wink-desktop:~/prgs/large_fields_are_odd
> $ ./test
> x.f0=0xfff
> g0=0x1ffe expect 0x1ffe
> x.f1=0xfffffffffffff
> g1=0x1ffffffffffffe expect 0x1ffffffffffffe
>
> Here is the make file:
>
> CC = clang
> CFLAGS = -m64 -O3 -Wall
>
> all: test
>
> test.o: test.c
> $(CC) -x c $(CFLAGS) -o test.o -c test.c
> objdump -d test.o > test.txt
>
> test: test.o
> $(CC) $(CFLAGS) test.o -o test
>
> clean:
> rm -f test test.o test.txt
>
>
> Do you think gcc should change?
No, clang should. GCC behaved this way since forever.
> On Thu, Feb 18, 2016 at 2:52 AM, Bernd Edlinger
> <bernd.edlinger@hotmail.de> wrote:
>> Hi,
>>
>>> struct fields {
>>> long long unsigned f0:12;
>>> long long unsigned f1:52;
>>> } __attribute__((__packed__));
>>
>> the C99 standard ISO/IEC 9899 forbids this type:
>>
>> 6.7.2.1 Structure and union specifiers
>>
>> 4 A bit-field shall have a type that is a qualified or unqualified version of _Bool, signed int,
>> unsigned int, or some other implementation-defined type.
>>
>> The C standard simply does not promote the bit-field value to any type larger than int or
>> unsigned int.
>>
>> GCC chooses to do the larger than int computations in an artificial 52-bit type, but it is a
>> non-standard extension.
>>
>> And if you compile your example with -Wall you'll see the problem:
>>
>> gcc -m32 -O3 -Wall test.c
>> test.c: In function 'main':
>> test.c:17:21: warning: format '%llx' expects argument of type 'long long unsigned int', but argument 2 has type 'int' [-Wformat=]
>> printf("x.f0=0x%llx\n", x.f0);
>> ^
>> test.c:19:21: warning: format '%llx' expects argument of type 'long long unsigned int', but argument 2 has type 'long long unsigned int:52' [-Wformat=]
>> printf("x.f1=0x%llx\n", x.f1);
>> ^
>>
>> so especially the first warning is no joke:
>>
>> ./a.out
>> x.f0=0x80497b400000fff
>> g0=0x1ffe expect 0x1ffe
>> x.f1=0xfffffffffffff
>> g1=0xffffffffffffe expect 0x1ffffffffffffe
>>
>>
>> OTOH that is perfectly OK for C++:
>>
>> gcc -x c++ -m32 -O3 -Wall test.c
>>
>> ./a.out
>> x.f0=0xfff
>> g0=0x1ffe expect 0x1ffe
>> x.f1=0xfffffffffffff
>> g1=0x1ffffffffffffe expect 0x1ffffffffffffe
>>
>>
>> Regards
>> Bernd.