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

Jakub Jelinek via Gcc-cvs <[email protected]>
Newsgroups gmane.comp.gcc.cvs
Message-ID <[email protected]>
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;
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.