https://gcc.gnu.org/g:57c193084178997a1e65b865b2a2b93915436c86

commit r15-11375-g57c193084178997a1e65b865b2a2b93915436c86
Author: Jakub Jelinek <[email protected]>
Date:   Fri Jun 12 22:43:06 2026 +0200

    c++: Diagnose invalid type of bitfield widths in templates [PR125674]
    
    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.
    
    2026-06-12  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.
    
    Reviewed-by: Jason Merrill <[email protected]>
    (cherry picked from commit 50ba4a8ca7a51a72514aae55d9fb81732ef7a3bd)

Diff:
---
 gcc/cp/pt.cc                              | 25 ++++++++++++++++++++-----
 gcc/testsuite/g++.dg/template/bitfield5.C | 16 ++++++++++++++++
 gcc/testsuite/g++.dg/template/bitfield6.C |  9 +++++++++
 3 files changed, 45 insertions(+), 5 deletions(-)

diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 0f96c842f9de..df9e479c9fc5 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -15634,11 +15634,26 @@ tsubst_decl (tree t, tree args, tsubst_flags_t 
complain,
            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
diff --git a/gcc/testsuite/g++.dg/template/bitfield5.C 
b/gcc/testsuite/g++.dg/template/bitfield5.C
new file mode 100644
index 000000000000..ba2d42ef38e5
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/bitfield5.C
@@ -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;
diff --git a/gcc/testsuite/g++.dg/template/bitfield6.C 
b/gcc/testsuite/g++.dg/template/bitfield6.C
new file mode 100644
index 000000000000..48763f04f477
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/bitfield6.C
@@ -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;

Reply via email to