https://gcc.gnu.org/g:a11b76ce4db284c4071901a3fe283be655bc74b5
commit r14-12743-ga11b76ce4db284c4071901a3fe283be655bc74b5 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 0685b21d55c3..44a4b8bf476a 100644 --- a/gcc/cp/pt.cc +++ b/gcc/cp/pt.cc @@ -15394,11 +15394,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;
