@@ -1389,6 +1389,28 @@ find_decomp_unqualified_name (tree decl, size_t *len)
return p;
}
+/* "For the purposes of mangling, the name of an anonymous union is considered
+ to be the name of the first named data member found by a pre-order,
+ depth-first, declaration-order walk of the data members of the anonymous
+ union. If there is no such data member (i.e., if all of the data members in
+ the union are unnamed), then there is no way for a program to refer to the
+ anonymous union, and there is therefore no need to mangle its name." */
+
+static tree
+anon_aggr_naming_decl (tree type)
+{
+ tree field = next_aggregate_field (TYPE_FIELDS (type));
+ for (; field; field = next_aggregate_field (DECL_CHAIN (field)))
+ {
+ if (DECL_NAME (field))
+ return field;
+ if (ANON_AGGR_TYPE_P (TREE_TYPE (field)))
+ if (tree sub = anon_aggr_naming_decl (TREE_TYPE (field)))
+ return sub;
+ }
+ return NULL_TREE;
+}
+
/* We don't need to handle thunks, vtables, or VTTs here. Those are
mangled through special entry points.
@@ -1432,7 +1454,10 @@ write_unqualified_name (tree decl)
bool found = false;
- if (DECL_NAME (decl) == NULL_TREE)
+ if (DECL_NAME (decl) == NULL_TREE
+ && ANON_AGGR_TYPE_P (TREE_TYPE (decl)))
+ decl = anon_aggr_naming_decl (TREE_TYPE (decl));
+ else if (DECL_NAME (decl) == NULL_TREE)
{
found = true;
gcc_assert (DECL_ASSEMBLER_NAME_SET_P (decl));
new file mode 100644
@@ -0,0 +1,19 @@
+// PR c++/108566
+// { dg-do compile { target c++20 } }
+
+template<typename T>
+struct wrapper1 {
+ union {
+ union {
+ T RightName;
+ };
+ };
+};
+
+template<auto tparam> void dummy(){}
+
+void uses() {
+ dummy<wrapper1<double>{123.0}>();
+}
+
+// { dg-final { scan-assembler "_Z5dummyIXtl8wrapper1IdEtlNS1_Ut_Edi9RightNametlNS2_Ut_Edi9RightNameLd405ec00000000000EEEEEEvv" } }