Skip to content

Commit 50ba4a8

Browse files
committed
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 <jakub@redhat.com> 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 <jason@redhat.com>
1 parent fad08bd commit 50ba4a8

3 files changed

Lines changed: 45 additions & 5 deletions

File tree

gcc/cp/pt.cc

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16058,11 +16058,26 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain,
1605816058
cp_apply_type_quals_to_decl (cp_type_quals (type), r);
1605916059

1606016060
if (DECL_C_BIT_FIELD (r))
16061-
/* For bit-fields, DECL_BIT_FIELD_REPRESENTATIVE gives the
16062-
number of bits. */
16063-
DECL_BIT_FIELD_REPRESENTATIVE (r)
16064-
= tsubst_expr (DECL_BIT_FIELD_REPRESENTATIVE (t), args,
16065-
complain, in_decl);
16061+
{
16062+
/* For bit-fields, DECL_BIT_FIELD_REPRESENTATIVE gives the
16063+
number of bits. */
16064+
tree width
16065+
= tsubst_expr (DECL_BIT_FIELD_REPRESENTATIVE (t), args,
16066+
complain, in_decl);
16067+
if (width
16068+
&& width != error_mark_node
16069+
&& !type_dependent_expression_p (width)
16070+
&& !INTEGRAL_OR_UNSCOPED_ENUMERATION_TYPE_P
16071+
(TREE_TYPE (width)))
16072+
{
16073+
if (complain & tf_error)
16074+
error_at (DECL_SOURCE_LOCATION (t),
16075+
"width of bit-field %qD has non-integral "
16076+
"type %qT", r, TREE_TYPE (width));
16077+
RETURN (error_mark_node);
16078+
}
16079+
DECL_BIT_FIELD_REPRESENTATIVE (r) = width;
16080+
}
1606616081
if (DECL_INITIAL (t))
1606716082
{
1606816083
/* Set up DECL_TEMPLATE_INFO so that we can get at the
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// PR c++/125674
2+
// { dg-do compile { target c++20 } }
3+
4+
struct A { int a : 1.; }; // { dg-error "width of bit-field 'a' has non-integral type 'double'" }
5+
template <typename T>
6+
struct B { int b : 1.; }; // { dg-error "width of bit-field 'b' has non-integral type 'double'" }
7+
template <typename T>
8+
struct C { T c : 1.; }; // { dg-error "width of bit-field 'c' has non-integral type 'double'" }
9+
template <auto N>
10+
struct D { int d : N; }; // { dg-error "width of bit-field 'D<N>::d' has non-integral type 'double'" }
11+
template <typename T, auto N>
12+
struct E { T e : N; }; // { dg-error "width of bit-field 'E<T, N>::e' has non-integral type 'double'" }
13+
B <int> b;
14+
C <int> c;
15+
D <1.> d;
16+
E <int, 1.> e;
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// PR c++/125674
2+
// { dg-do compile }
3+
4+
template <typename T>
5+
struct A {
6+
int f ();
7+
int i : f; // { dg-error "width of bit-field 'A<T>::i' has non-integral type '<unresolved overloaded function type>'" }
8+
};
9+
A<int> a;

0 commit comments

Comments
 (0)