Hi Abdulmalek,
I need to be humble because this is a complex area that has been debated
for decades, but I'll try to answer.
On 24/09/2026 03:21, Abdulmalek Almkainzi wrote:
Hello.
gcc treats bit-field expressions as having different type from its
declared integer type.
for example:
```
struct S { unsigned i : 1; };
struct S s;
int i = _Generic(s.i, unsigned: 1, default: 2);
```
It would be problematic if "unsigned: 1" were a type name, wouldn't it?
Unfortunately, that would also be the most natural way of writing such a
type, analogous to how one could write 'int (double)' to name the type
of a function that has a parameter of type double and a return value of
type int.
`i` is 2 in gcc, but 1 in clang and msvc.
I think clang/msvc follow the standard more correctly here:
6.7.3.2 paragraph 5
> A bit-field shall have a type that is a qualified or unqualified
bool, signed int, unsigned int, a
> bit-precise integer type, or other implementation-defined type. It is
implementation-defined whether
> atomic types are permitted.
My understanding is that GCC uses the "other implementation-defined
type" escape hatch to justify its behaviour.
I did a simple fix in c_parser_generic_selection where I convert the
type of a bit-field expression to its declared integer type.
This does make a different test fail (c23-auto-1.c), specifically this
part:
```
struct b { int a : 2; unsigned b : 3; } bv = { };
auto bfa = bv.a;
auto bfb = bv.b;
static_assert (_Generic (bv.a, typeof (bfa) : 1, default : 2) == 1);
static_assert (_Generic (bv.b, typeof (bfb) : 1, default : 2) == 1);
```
if the rhs of a auto type inference assignment is a bit-field, the
variable will have a bit-field type. and that type matches a controlling
operand of a bit-field expression.
Yes; GCC's interpretation of the C standard implies the existence of a
vast number of integer types. At first glance, there seems to be no way
of naming such bit-field types outside the specific context of a member
declaration.
One might therefore expect _Generic to be useless for matching with such
unnamable types, except in contrived tautological (and
near-tautological) cases like these:
int main(int argc, char *argv[])
{
struct bf {
unsigned int i:31;
} b = {};
auto z = b.i;
_Static_assert(_Generic(z, typeof(z):1, default: 0), "");
_Static_assert(_Generic(b.i, typeof(z):1, default: 0), "");
return z;
}
See https://godbolt.org/z/aM71x14TT
Surprisingly, one can work around this apparent inability to name
specific-width integer types by using compound literals:
#include <stdio.h>
#define BF_TYPE(N) typeof(0, (struct {int j:(N);}){}.j)
#define NAME(T) \
_Generic((T), BF_TYPE(1):1, default: 0) ? "one" : \
_Generic((T), BF_TYPE(2):1, default: 0) ? "two" : \
_Generic((T), BF_TYPE(3):1, default: 0) ? "three" : \
_Generic((T), BF_TYPE(4):1, default: 0) ? "four" : \
"many"
int main(void)
{
struct bf {
int i:3, j:4, k:1, l:2;
} b;
printf("%s %s %s %s", NAME(b.i), NAME(b.j), NAME(b.k), NAME(b.l));
return 0;
}
See https://godbolt.org/z/z64Gz56x5
So, the extra integer types supported by GCC can actually be named --
just not without use of typeof.
The comma operator is used to work around what appears to be an
arbitrary constraint. Without the comma operator, both Clang and GCC
report a variant of "error: 'typeof' applied to a bit-field"; with it,
the program compiled by GCC prints "three four one two" (as expected),
whereas the program compiled by Clang prints "one one one one".
Interestingly, I cannot find any prohibition in C23 against using an
assignment expression of bitfield type in a declaration that does type
inference using 'auto'. Nevertheless, Clang (but not GCC) reports
"error: cannot pass bit-field as __auto_type initializer in C". This
appears to be a bug in Clang -- especially given that it can seemingly
be bypassed by using the comma operator just as I did when specifying an
expression of bitfield type as the operand of typeof.
int main(int argc, char *argv[])
{
struct bf {
int i:3, j:4, k:1, l:2;
} b = {};
auto x = (argc++, b.i); // no error
auto y = b.i; // error only from Clang
return 0;
}
See https://godbolt.org/z/7GfMK7P5G
HTH,
--
Christopher Bazley
Staff Software Engineer, GNU Tools Team.
Arm Ltd, 110 Fulbourn Road, Cambridge, CB1 9NJ, UK.
http://www.arm.com/