On 3/12/26 10:51 AM, Jakub Jelinek wrote:
On Thu, Mar 12, 2026 at 09:50:08AM -0400, Jason Merrill wrote:
{,u8}display_string_of was printing any unnamed FIELD_DECL as
%T::<unnamed bit-field>, but anon union member is also unnamed and
is not a bit-field.
Fixed thusly, bootstrapped/regtested on x86_64-linux and i686-linux, ok for
trunk?
2026-03-07 Jakub Jelinek <[email protected]>
PR c++/124388
* reflect.cc (eval_display_string_of): Only print <unnmamed bit-field>
for DECL_UNNAMED_BIT_FIELD, otherwise print <unnamed member>.
* g++.dg/reflect/display_string_of1.C (S, NS5::S): Add
union { int a; }. Add static_assertions that the unnamed non-static
data member is printed as <unnamed member>.
How about <anonymous union>?
So like this then?
Left the <unnamed member> as fallback for now at least for anonymous structs
(for which we really need to add test coverage and tweak reflect.cc to
probably handle it like anonymous unions) or perhaps other cases.
Tested on x86_64-linux with
GXX_TESTSUITE_STDS=98,11,14,17,20,23,26 make -j32 -k check-g++
RUNTESTFLAGS="dg.exp='reflect/* expansion-stmt*'"
Ok for trunk if it passes full bootstrap/regtest?
OK.
2026-03-12 Jakub Jelinek <[email protected]>
PR c++/124388
* reflect.cc (eval_display_string_of): Only print <unnmamed bit-field>
for DECL_UNNAMED_BIT_FIELD, for anon union print <anonymous union>,
otherwise print <unnamed member>.
* g++.dg/reflect/display_string_of1.C (S, NS5::S): Add
union { int a; }. Add static_assertions that the unnamed non-static
data member is printed as <unnamed member>.
* g++.dg/reflect/u8display_string_of1.C (S, NS5::S): Add
union { int a; }. Add static_assertions that the unnamed non-static
data member is printed as <unnamed member>.
--- gcc/cp/reflect.cc.jj 2026-03-05 09:19:22.173774816 +0100
+++ gcc/cp/reflect.cc 2026-03-12 15:44:28.123749635 +0100
@@ -3604,7 +3604,14 @@ eval_display_string_of (location_t loc,
else if (DECL_P (r) && (DECL_NAME (r) || TREE_CODE (r) == NAMESPACE_DECL))
pp_printf (&pp, "%D", r);
else if (TREE_CODE (r) == FIELD_DECL)
- pp_printf (&pp, "%T::<unnamed bit-field>", DECL_CONTEXT (r));
+ {
+ if (DECL_UNNAMED_BIT_FIELD (r))
+ pp_printf (&pp, "%T::<unnamed bit-field>", DECL_CONTEXT (r));
+ else if (ANON_UNION_TYPE_P (TREE_TYPE (r)))
+ pp_printf (&pp, "%T::<anonymous union>", DECL_CONTEXT (r));
+ else
+ pp_printf (&pp, "%T::<unnamed member>", DECL_CONTEXT (r));
+ }
else if (kind == REFLECT_BASE)
{
tree d = direct_base_derived (r);
--- gcc/testsuite/g++.dg/reflect/display_string_of1.C.jj 2026-01-15
16:33:47.007097959 +0100
+++ gcc/testsuite/g++.dg/reflect/display_string_of1.C 2026-03-12
15:45:46.572128144 +0100
@@ -17,6 +17,7 @@ struct B {};
struct S : B {
int mem;
int : 0;
+ union { int a; };
};
struct T {
T () {}
@@ -106,6 +107,7 @@ foo (int a, const long b, T c, int d[4],
static_assert (display_string_of (^^S) == "S");
static_assert (display_string_of (^^S::mem) == "S::mem");
static_assert (display_string_of (members_of (^^S, ctx)[1]) == "S::<unnamed
bit-field>");
+ static_assert (display_string_of (nonstatic_data_members_of (^^S, ctx)[1]) ==
"S::<anonymous union>");
static_assert (display_string_of (^^TCls) == "template<auto <anonymous> > struct
TCls");
static_assert (display_string_of (^^TFn) == "template<auto <anonymous> > void
TFn()");
static_assert (display_string_of (^^TVar) == "template<auto <anonymous> > int
TVar<<anonymous> >");
@@ -145,6 +147,7 @@ namespace NS5 {
struct S : B {
int mem;
int : 0;
+ union { int a; };
};
struct T {
T () {}
@@ -212,6 +215,7 @@ namespace NS5 {
static_assert (display_string_of (^^S) == "NS5::S");
static_assert (display_string_of (^^S::mem) == "NS5::S::mem");
static_assert (display_string_of (members_of (^^S, ctx)[1]) == "NS5::S::<unnamed
bit-field>");
+ static_assert (display_string_of (nonstatic_data_members_of (^^S, ctx)[1]) ==
"NS5::S::<anonymous union>");
static_assert (display_string_of (^^TCls) == "template<auto <anonymous> >
struct NS5::TCls");
static_assert (display_string_of (^^TFn) == "template<auto <anonymous> > void
NS5::TFn()");
static_assert (display_string_of (^^TVar) == "template<auto <anonymous> > int
NS5::TVar<<anonymous> >");
--- gcc/testsuite/g++.dg/reflect/u8display_string_of1.C.jj 2026-01-15
16:33:47.017097789 +0100
+++ gcc/testsuite/g++.dg/reflect/u8display_string_of1.C 2026-03-12
15:46:31.895312350 +0100
@@ -17,6 +17,7 @@ struct B {};
struct S : B {
int mem;
int : 0;
+ union { int a; };
};
struct T {
T () {}
@@ -106,6 +107,7 @@ foo (int a, const long b, T c, int d[4],
static_assert (u8display_string_of (^^S) == u8"S");
static_assert (u8display_string_of (^^S::mem) == u8"S::mem");
static_assert (u8display_string_of (members_of (^^S, ctx)[1]) == u8"S::<unnamed
bit-field>");
+ static_assert (u8display_string_of (nonstatic_data_members_of (^^S, ctx)[1]) ==
u8"S::<anonymous union>");
static_assert (u8display_string_of (^^TCls) == u8"template<auto <anonymous> >
struct TCls");
static_assert (u8display_string_of (^^TFn) == u8"template<auto <anonymous> >
void TFn()");
static_assert (u8display_string_of (^^TVar) == u8"template<auto <anonymous> > int
TVar<<anonymous> >");
@@ -145,6 +147,7 @@ namespace NS5 {
struct S : B {
int mem;
int : 0;
+ union { int a; };
};
struct T {
T () {}
@@ -212,6 +215,7 @@ namespace NS5 {
static_assert (u8display_string_of (^^S) == u8"NS5::S");
static_assert (u8display_string_of (^^S::mem) == u8"NS5::S::mem");
static_assert (u8display_string_of (members_of (^^S, ctx)[1]) ==
u8"NS5::S::<unnamed bit-field>");
+ static_assert (u8display_string_of (nonstatic_data_members_of (^^S, ctx)[1]) ==
u8"NS5::S::<anonymous union>");
static_assert (u8display_string_of (^^TCls) == u8"template<auto <anonymous> >
struct NS5::TCls");
static_assert (u8display_string_of (^^TFn) == u8"template<auto <anonymous> >
void NS5::TFn()");
static_assert (u8display_string_of (^^TVar) == u8"template<auto <anonymous> > int
NS5::TVar<<anonymous> >");
Jakub