Hi!

As the first testcase shows, outside of templates or when
the bitfield width is not type dependent, we diagnose it
in grokbitfield:
  if (width != error_mark_node)
    {
      /* The width must be an integer type.  */
      if (!type_dependent_expression_p (width)
          && !INTEGRAL_OR_UNSCOPED_ENUMERATION_TYPE_P (TREE_TYPE (width)))
        error ("width of bit-field %qD has non-integral type %qT", value,
               TREE_TYPE (width));
      else if (!check_for_bare_parameter_packs (width))
        {
          /* Temporarily stash the width in DECL_BIT_FIELD_REPRESENTATIVE.
             check_bitfield_decl picks it from there later and sets DECL_SIZE
             accordingly.  */
          DECL_BIT_FIELD_REPRESENTATIVE (value) = width;
          SET_DECL_C_BIT_FIELD (value);
        }
    }
Later on in check_bitfield_decl we verify it is a constant expression,
folded into INTEGER_CST, non-negative etc.
But during instantiation, we don't repeat that check, so only call
check_bitfield_decl later on which can sometimes emit different diagnostics
(so e.g.
bit-field ‘D<1.0e+0>::d’ width not an integer constant
instead of
width of bit-field ‘D<N>::d’ has non-integral type ‘double’
) but what the second testcase shows, we can ICE during cxx_constant_value
even before that if the type is even more problematic.

The following patch fixes that by repeating the test from grokbitfield
during tsubst_decl.

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

2026-06-09  Jakub Jelinek  <[email protected]>

        PR c++/125674
        * pt.cc (tsubst_decl): Diagnose bit-field widths
        with invalid type.

        * g++.dg/template/bitfield5.C: New test.
        * g++.dg/template/bitfield6.C: New test.

--- gcc/cp/pt.cc.jj     2026-06-05 20:39:09.000000000 +0200
+++ gcc/cp/pt.cc        2026-06-09 15:23:48.297250118 +0200
@@ -16075,11 +16075,26 @@ tsubst_decl (tree t, tree args, tsubst_f
            cp_apply_type_quals_to_decl (cp_type_quals (type), r);
 
            if (DECL_C_BIT_FIELD (r))
-             /* For bit-fields, DECL_BIT_FIELD_REPRESENTATIVE gives the
-                number of bits.  */
-             DECL_BIT_FIELD_REPRESENTATIVE (r)
-               = tsubst_expr (DECL_BIT_FIELD_REPRESENTATIVE (t), args,
-                              complain, in_decl);
+             {
+               /* For bit-fields, DECL_BIT_FIELD_REPRESENTATIVE gives the
+                  number of bits.  */
+               tree width
+                 = tsubst_expr (DECL_BIT_FIELD_REPRESENTATIVE (t), args,
+                                complain, in_decl);
+               if (width
+                   && width != error_mark_node
+                   && !type_dependent_expression_p (width)
+                   && !INTEGRAL_OR_UNSCOPED_ENUMERATION_TYPE_P
+                        (TREE_TYPE (width)))
+                 {
+                   if (complain & tf_error)
+                     error_at (DECL_SOURCE_LOCATION (t),
+                               "width of bit-field %qD has non-integral "
+                               "type %qT", r, TREE_TYPE (width));
+                   RETURN (error_mark_node);
+                 }
+               DECL_BIT_FIELD_REPRESENTATIVE (r) = width;
+             }
            if (DECL_INITIAL (t))
              {
                /* Set up DECL_TEMPLATE_INFO so that we can get at the
--- gcc/testsuite/g++.dg/template/bitfield5.C.jj        2026-06-09 
15:30:47.317846301 +0200
+++ gcc/testsuite/g++.dg/template/bitfield5.C   2026-06-09 15:35:45.269007812 
+0200
@@ -0,0 +1,16 @@
+// PR c++/125674
+// { dg-do compile { target c++20 } }
+
+struct A { int a : 1.; };      // { dg-error "width of bit-field 'a' has 
non-integral type 'double'" }
+template <typename T>
+struct B { int b : 1.; };      // { dg-error "width of bit-field 'b' has 
non-integral type 'double'" }
+template <typename T>
+struct C { T c : 1.; };                // { dg-error "width of bit-field 'c' 
has non-integral type 'double'" }
+template <auto N>
+struct D { int d : N; };       // { dg-error "width of bit-field 'D<N>::d' has 
non-integral type 'double'" }
+template <typename T, auto N>
+struct E { T e : N; };         // { dg-error "width of bit-field 'E<T, N>::e' 
has non-integral type 'double'" }
+B <int> b;
+C <int> c;
+D <1.> d;
+E <int, 1.> e;
--- gcc/testsuite/g++.dg/template/bitfield6.C.jj        2026-06-09 
15:32:25.109586455 +0200
+++ gcc/testsuite/g++.dg/template/bitfield6.C   2026-06-09 15:32:15.977704100 
+0200
@@ -0,0 +1,9 @@
+// PR c++/125674
+// { dg-do compile }
+
+template <typename T>
+struct A {
+  int f ();
+  int i : f;   // { dg-error "width of bit-field 'A<T>::i' has non-integral 
type '<unresolved overloaded function type>'" }
+};
+A<int> a;

        Jakub

Reply via email to