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

Reply via email to