On Wed, 24 Feb 2016, Martin Sebor wrote: > > 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.
There are lots of variants of the trick (including the conditional expression one), depending on which types you care about distinguishing and which are valid arguments to the macro. If you want, you can even distinguish each bit-field width wider than int individually using typeof, via writing expressions with typeof to determine the width of the type. I suspect many attempts to use _Generic with non-arithmetic types would run into usability problems in practice because every expression in the generic association list must still pass the Constraints whatever the type of the controlling expression - so you can select a function name based on that type, but putting more complicated expressions directly inside _Generic would be problematic in many cases if a wide range of types is to be allowed. There is a basic question: is _Generic supposed to be arbitrarily expressive, or is it meant to cover cases like <tgmath.h>? The answer in the context of questions about qualifiers and array-to-pointer decay was that it is meant to cover cases like <tgmath.h>, not to be arbitrarily expressive for hypothetical cases. Maximal expressiveness would allow distinguishing all bit-field widths, but that would fall down on usability. Integer types narrower than int are effectively second-class entities in C; you can't write constants of those types, for example, and they get promoted before used in arithmetic or being passed in variable arguments; while you *can* select on them with _Generic, the utility of doing so may be limited. Bit-fields are effectively third-class entities, and bit-fields with implementation-defined declared types other than int or signed int or unsigned int are fourth-class (not required by the standard at all, and have their own problems of specification - and the final choice for DR#315 was to leave pretty much everything about such bit-fields implementation-defined - see the minutes for Portland 2006, London 2007, Kona 2007). > 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); That should be reported as an ordinary bug in <tgmath.h>, that can easily be addressed by using unary + so that typeof isn't applied to a bit-field (<tgmath.h> treats all integer types the same and non-arithmetic types are irrelevant to it, so unary + is absoletely fine there). > 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 C++ has long diverged from C regarding bit-fields (allowing other declared types, allowing widths wider than the width of the underlying type, now requiring plain int bit-fields to be signed, ...). Whereas C has its line of textual history going back to various C90 DRs and showing that: (a) whether a bit-field width counts of part of the type doesn't generally matter within the standard except for integer promotions, so can safely be left unspecified with just special wording for promotions (modulo the new _Generic issue); (b) everything about such matters for bit-fields of nonstandard types can be left implementation-defined; (c) nothing defines semantics of conversion of out-of-range values to bit-fields other than treating the width as part of the type (or in the case of _Bool bit-fields, having the special wording to make it explicit that those have the semantics of _Bool not the semantics of an ordinary unsigned integer type with the specified number of bits). -- Joseph S. Myers jos...@codesourcery.com