[gcc r13-10440] c++: Diagnose invalid type of bitfield widths in templates [PR125674]

Jakub Jelinek via Gcc-cvs <[email protected]> Sat, 1 Aug 2026 10:58:00 +0000 (GMT)
Newsgroups gmane.comp.gcc.cvs
Message-ID <[email protected]>
https://gcc.gnu.org/g:8c921513fe8d790e7c0c5f1bc6bc28601885f165

commit r13-10440-g8c921513fe8d790e7c0c5f1bc6bc28601885f165
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 f13e2faa9ac0..9159c043cdc6 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -15119,11 +15119,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;