On 6/10/26 2:25 AM, Jakub Jelinek wrote:
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?
As usual I'd be inclined to factor out the error instead of duplicating
it between template and non-template, but I suppose this small and
stable enough not to need that; OK either way.
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