How to use _Generic with bit-fields

Martin Sebor msebor@gmail.com
Wed Feb 24 19:26:00 GMT 2016


>> $ cat z.c && /home/msebor/build/gcc-trunk-svn/gcc/xgcc
>> -B/home/msebor/build/gcc-trunk-svn/gcc -Wall -Wextra -Wpedantic -xc z.c
>> struct S { unsigned i: 31; } s;
>> int i = _Generic (s.i, unsigned: 1);
>> z.c:2:19: error: ‘_Generic’ selector of type ‘unsigned int:31’ is not
>> compatible with any association
>>   int i = _Generic (s.i, unsigned: 1);
>>                     ^
>
> That can be avoided simply by using unary + in the controlling expression
> of _Generic (just as using unary + will avoid an error from sizeof, if you
> want to be able to apply that to expressions that might be bit-fields) -
> or any of the other techniques for achieving promotions of selected types.

Unfortunately, the + n trick is far too limited to be generally
usable.  Since GCC allows bit-fields of other integers types
besides those described by the standard (e.g., long long), the
plus expression would have to be converted to the widest possible
type (e.g., by (x + 0LL)) which would defeat the purpose of
_Generic.  The trick of course work at all for type-generic
macro intended to also accept non- scalar arguments.

>
> You can't use bit-fields with sizeof, or with unary &, or in GNU C with
> typeof.  I think extending this constraint to _Generic - meaning you need
> to use a trick such as unary + when a bit-field might occur there - is
> consistent with the peculiar position of bit-fields in C as not quite
> normal objects or types (and consistent with how _Generic is intended for
> certain limited kinds of overloading such as <tgmath.h>,

GCC's handling of bit-fields in __typeof__  is also a problem
and causes bugs in <tgmath.h>.  For example, the following is
rejected by GCC (with not just one but 42 errors) as a result:

   struct S { unsigned b: 31; } s;
   carg (s.b);

even though this is accepted:

   _Complex double cd = s.b;

> not for
> arbitrarily expressive logic on types, cf. the rejection of overloading on
> qualifiers).  If someone uses e.g. unsigned int:8 as the controlling
> expression of _Generic, it's hardly clear whether a selection for unsigned
> char (a type with the same set of values), unsigned int (the declared type
> ignoring width) or int (the type resulting from the integer promotions)
> would be the most useful selection.

If it isn't clear it should be brought up in WG14 and clarified.
It's clear enough in C++ for bit-fields to be used as arguments
to overloaded functions or function templates.  I can't imagine
a good reason for not nailing it down in C.  Especially since
existing practice shows that it can be made to work in
unsurprising ways (all 5 GCC-compatible compilers that I've
tested accept bit-fields in __typeof__ and, those that support
it, also in _Generic).

Martin



More information about the Gcc mailing list