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