On Wed, May 27, 2026 at 08:47:50PM +0000, Joseph Myers wrote:
> On Wed, 27 May 2026, Jakub Jelinek wrote:
>
> > On Wed, May 27, 2026 at 08:29:51PM +0000, Joseph Myers wrote:
> > > I think there should be a testcase that bit-fields of bit-precise enum
> > > type get promoted to their declared type by the integer promotions, like
> > > _BitInt bit-fields do. (And then from the enum type to the underlying
> > > bit-precise type - conversion to the underlying type is what GCC does
> > > with
> > > enums in the integer promotions and is the expressed preference of WG14
> > > in
> > > C23 issue 1021 for what should be done with enums in integer promotions
> > > in
> > > general.)
> >
> > I even started adding those when writing the patch, but then gave up because
> > _Generic on the bit-fields themselves gives unpromoted types.
> > So, for testing this, shall I test using _Generic (object.bit_field + 0wb,
> > ...) or something similar (or _Generic (+object.bit_field, ...))?
>
> Yes, something like that. I think bitint-17.c has the corresponding tests
> for bit-fields declared with _BitInt.
Ah, ok.
So then something like the following incremental patch?
Will incorporate into the full patch when testing succeeds.
Note, haven't tweaked the handling of non-_BitInt enums for issue 1021,
I think such a change shouldn't be in mostly unrelated patch. Note the
issue 1021 proposed resolution doesn't take into account the N3705 changes
to the same spot.
--- gcc/c/c-typeck.cc.jj 2026-05-25 09:46:35.000000000 +0200
+++ gcc/c/c-typeck.cc 2026-05-28 13:31:01.852472787 +0200
@@ -2826,9 +2826,14 @@ perform_integral_promotions (tree exp)
if (TREE_CODE (exp) == COMPONENT_REF
&& DECL_C_BIT_FIELD (TREE_OPERAND (exp, 1)))
{
- if (TREE_CODE (DECL_BIT_FIELD_TYPE (TREE_OPERAND (exp, 1)))
- == BITINT_TYPE)
- return convert (DECL_BIT_FIELD_TYPE (TREE_OPERAND (exp, 1)), exp);
+ if (BITINT_TYPE_P (DECL_BIT_FIELD_TYPE (TREE_OPERAND (exp, 1))))
+ {
+ tree btype = DECL_BIT_FIELD_TYPE (TREE_OPERAND (exp, 1));
+ if (TREE_CODE (btype) == BITINT_TYPE)
+ return convert (btype, exp);
+ else
+ return convert (ENUM_UNDERLYING_TYPE (btype), exp);
+ }
/* If it's thinner than an int, promote it like a
c_promoting_integer_type_p, otherwise leave it alone. */
if (compare_tree_int (DECL_SIZE (TREE_OPERAND (exp, 1)),
--- gcc/testsuite/gcc.dg/bitint-133.c.jj 2026-05-28 12:54:32.989818266
+0200
+++ gcc/testsuite/gcc.dg/bitint-133.c 2026-05-28 13:02:46.634302551 +0200
@@ -1,7 +1,9 @@
/* C2Y N3705: bit-precise enum. */
-/* { dg-do run { target bitint } } */
+/* { dg-do compile { target bitint } } */
/* { dg-options "-std=c2y" } */
+#define expr_has_type(e, t) _Generic (e, default : 0, t : 1)
+
#if __BITINT_MAXWIDTH__ >= 129
enum A : unsigned _BitInt(3) { A0 = 0, A1 = 7 };
enum B : unsigned _BitInt(67) { B0 = 0, B1 = 255 };
@@ -14,28 +16,30 @@ int
main ()
{
#if __BITINT_MAXWIDTH__ >= 129
- int i = 0;
enum A a = A0;
- _Generic (a, enum A: ++i);
- _Generic (+a, unsigned _BitInt(3): ++i);
- _Generic (a + a, unsigned _BitInt(3): ++i);
+ static_assert (expr_has_type (a, enum A));
+ static_assert (expr_has_type (+a, unsigned _BitInt(3)));
+ static_assert (expr_has_type (a + 0wb, unsigned _BitInt(3)));
+ static_assert (expr_has_type (a + a, unsigned _BitInt(3)));
enum B b = B0;
- _Generic (b, enum B: ++i);
- _Generic (+b, unsigned _BitInt(67): ++i);
- _Generic (b + b, unsigned _BitInt(67): ++i);
+ static_assert (expr_has_type (b, enum B));
+ static_assert (expr_has_type (+b, unsigned _BitInt(67)));
+ static_assert (expr_has_type (b + 0wb, unsigned _BitInt(67)));
+ static_assert (expr_has_type (b + b, unsigned _BitInt(67)));
enum C c = C0;
- _Generic (c, enum C: ++i);
- _Generic (+c, _BitInt(4): ++i);
- _Generic (c + c, _BitInt(4): ++i);
+ static_assert (expr_has_type (c, enum C));
+ static_assert (expr_has_type (+c, _BitInt(4)));
+ static_assert (expr_has_type (c + 0wb, _BitInt(4)));
+ static_assert (expr_has_type (c + c, _BitInt(4)));
enum D d = D0;
- _Generic (d, enum D: ++i);
- _Generic (+d, signed _BitInt(129): ++i);
- _Generic (d + d, signed _BitInt(129): ++i);
+ static_assert (expr_has_type (d, enum D));
+ static_assert (expr_has_type (+d, signed _BitInt(129)));
+ static_assert (expr_has_type (d + 0wb, signed _BitInt(129)));
+ static_assert (expr_has_type (d + d, signed _BitInt(129)));
enum E e = E0;
- _Generic (e, enum E: ++i);
- _Generic (+e, signed _BitInt(__BITINT_MAXWIDTH__): ++i);
- _Generic (e + e, signed _BitInt(__BITINT_MAXWIDTH__): ++i);
- if (i != 15)
- __builtin_abort ();
+ static_assert (expr_has_type (e, enum E));
+ static_assert (expr_has_type (+e, signed _BitInt(__BITINT_MAXWIDTH__)));
+ static_assert (expr_has_type (e + 0wb, signed _BitInt(__BITINT_MAXWIDTH__)));
+ static_assert (expr_has_type (e + e, signed _BitInt(__BITINT_MAXWIDTH__)));
#endif
}
--- gcc/testsuite/gcc.dg/bitint-136.c.jj 2026-05-28 12:57:21.456489212
+0200
+++ gcc/testsuite/gcc.dg/bitint-136.c 2026-05-28 13:20:15.304217771 +0200
@@ -0,0 +1,36 @@
+/* C2Y N3705: bit-precise enum. */
+/* { dg-do compile { target bitint } } */
+/* { dg-options "-std=c2y" } */
+
+#define expr_has_type(e, t) _Generic (e, default : 0, t : 1)
+
+#if __BITINT_MAXWIDTH__ >= 257
+enum A : unsigned _BitInt(7) { A0 = 0, A1 = 7 };
+enum B : unsigned _BitInt(79) { B0 = 0, B1 = 255 };
+enum C : _BitInt(25) { C0 = -8, C1 = 7 };
+enum D : signed _BitInt(182) { D0 = -61822874253726891040447382843909510144wb,
D1 = 333265406300494622897688995893630121068wb };
+enum E : _BitInt(__BITINT_MAXWIDTH__) { E0 = -1, E1 = 1 };
+struct F { enum A a : 3; enum B b : 67; enum C c : 4; enum D d : 129; enum E e
: 257; } f;
+#endif
+
+int
+main ()
+{
+#if __BITINT_MAXWIDTH__ >= 257
+ static_assert (expr_has_type (+f.a, unsigned _BitInt(7)));
+ static_assert (expr_has_type (f.a + 0wb, unsigned _BitInt(7)));
+ static_assert (expr_has_type (f.a + f.a, unsigned _BitInt(7)));
+ static_assert (expr_has_type (+f.b, unsigned _BitInt(79)));
+ static_assert (expr_has_type (f.b + 0wb, unsigned _BitInt(79)));
+ static_assert (expr_has_type (f.b + f.b, unsigned _BitInt(79)));
+ static_assert (expr_has_type (+f.c, _BitInt(25)));
+ static_assert (expr_has_type (f.c + 0wb, _BitInt(25)));
+ static_assert (expr_has_type (f.c + f.c, _BitInt(25)));
+ static_assert (expr_has_type (+f.d, signed _BitInt(182)));
+ static_assert (expr_has_type (f.d + 0wb, signed _BitInt(182)));
+ static_assert (expr_has_type (f.d + f.d, signed _BitInt(182)));
+ static_assert (expr_has_type (+f.e, signed _BitInt(__BITINT_MAXWIDTH__)));
+ static_assert (expr_has_type (f.e + 0wb, signed
_BitInt(__BITINT_MAXWIDTH__)));
+ static_assert (expr_has_type (f.e + f.e, signed
_BitInt(__BITINT_MAXWIDTH__)));
+#endif
+}
Jakub