$ 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

Reply via email to