]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
c++: class NTTP and nested anon union [PR108566]
authorJason Merrill <jason@redhat.com>
Fri, 10 Mar 2023 04:33:43 +0000 (23:33 -0500)
committerJason Merrill <jason@redhat.com>
Tue, 18 Apr 2023 20:44:26 +0000 (16:44 -0400)
We were failing to come up with the name for the anonymous union.  It seems
like unfortunate redundancy, but the ABI does say that the name of an
anonymous union is its first named member.

PR c++/108566

gcc/cp/ChangeLog:

* mangle.cc (anon_aggr_naming_decl): New.
(write_unqualified_name): Use it.

gcc/testsuite/ChangeLog:

* g++.dg/abi/anon6.C: New test.

gcc/cp/mangle.cc
gcc/testsuite/g++.dg/abi/anon6.C [new file with mode: 0644]

index eb53e0ebeb435f011e5d53177908e852212f601f..4660514dc628b12a29948904fab15bf70d7dc1ef 100644 (file)
@@ -1371,6 +1371,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_initializable_field (TYPE_FIELDS (type));
+  for (; field; field = next_initializable_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.
 
@@ -1414,7 +1436,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));
diff --git a/gcc/testsuite/g++.dg/abi/anon6.C b/gcc/testsuite/g++.dg/abi/anon6.C
new file mode 100644 (file)
index 0000000..7be0b0b
--- /dev/null
@@ -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" } }