erichkeane created this revision.
erichkeane added reviewers: rjmccall, aaron.ballman, tahonermann.
Herald added a project: All.
erichkeane requested review of this revision.

As reported in https://github.com/llvm/llvm-project/issues/54588
and discussed in https://github.com/itanium-cxx-abi/cxx-abi/issues/139

We are supposed to do a DFS, pre-order, decl-order search for a name for
the union in this case. Prevoiusly we crashed because the IdentiferInfo
pointer was nullptr, so this makes sure we have a name in the cases
described by the ABI.

I added an llvm-unreachable to cover an unexpected case at the end of
the new function with information/reference to the ABI in case we come
up with some way to get back to here.


https://reviews.llvm.org/D122820

Files:
  clang/lib/AST/ItaniumMangle.cpp
  clang/test/CodeGenCXX/mangle-nttp-anon-union.cpp

Index: clang/test/CodeGenCXX/mangle-nttp-anon-union.cpp
===================================================================
--- /dev/null
+++ clang/test/CodeGenCXX/mangle-nttp-anon-union.cpp
@@ -0,0 +1,99 @@
+// RUN: %clang_cc1 -std=c++20 -emit-llvm %s -o - -triple=x86_64-linux-gnu | FileCheck %s
+// RUN: %clang_cc1 -std=c++20 -emit-llvm %s -o - -triple=x86_64-linux-gnu | llvm-cxxfilt | FileCheck %s --check-prefix DEMANGLED
+
+template<typename T>
+struct wrapper1 {
+  union {
+    struct {
+      T RightName;
+    };
+  };
+};
+
+template<typename T>
+struct wrapper2 {
+  union {
+    struct {
+      T RightName;
+    };
+    T WrongName;
+  };
+};
+
+struct Base {
+  int WrongName;
+};
+
+template <typename T>
+struct wrapper3 {
+  union {
+    struct : Base {
+      T RightName;
+    };
+    T WrongName;
+  };
+};
+
+template <typename T>
+struct wrapper4 {
+  union {
+    int RightName;
+    struct {
+      T WrongName;
+    };
+    T AlsoWrongName;
+  };
+};
+
+template <typename T>
+struct wrapper5 {
+  union {
+    struct {
+      struct {
+        T RightName;
+      };
+      T WrongName;
+    };
+  };
+};
+
+
+
+template<auto tparam> void dummy(){}
+
+
+void uses() {
+  // Zero init'ed cases.
+  dummy<wrapper1<int>{}>();
+  // CHECK: call void @_Z5dummyIXtl8wrapper1IiEEEEvv
+  // DEMANGLED: call void @void dummy<wrapper1<int>{}>()()
+  dummy<wrapper2<float>{}>();
+  // CHECK: call void @_Z5dummyIXtl8wrapper2IfEEEEvv
+  // DEMANGLED: call void @void dummy<wrapper2<float>{}>()()
+  dummy<wrapper3<short>{}>();
+  // CHECK: call void @_Z5dummyIXtl8wrapper3IsEEEEvv
+  // DEMANGLED: call void @void dummy<wrapper3<short>{}>()()
+  dummy<wrapper4<double>{}>();
+  // CHECK: call void @_Z5dummyIXtl8wrapper4IdEEEEvv
+  // DEMANGLED: call void @void dummy<wrapper4<double>{}>()()
+  dummy<wrapper5<long long>{}>();
+  // CHECK: call void @_Z5dummyIXtl8wrapper5IxEEEEvv
+  // DEMANGLED: call void @void dummy<wrapper5<long long>{}>()()
+
+
+  dummy<wrapper1<double>{123.0}>();
+  // CHECK: call void @_Z5dummyIXtl8wrapper1IdEtlNS1_Ut_Edi9RightNametlNS2_Ut_ELd405ec00000000000EEEEEEvv
+  // DEMANGLED: call void @void dummy<wrapper1<double>{wrapper1<double>::'unnamed'{.RightName = wrapper1<double>::'unnamed'::'unnamed'{0x1.ecp+6}}}>()()
+  dummy<wrapper2<double>{123.0}>();
+  // CHECK: call void @_Z5dummyIXtl8wrapper2IdEtlNS1_Ut_Edi9RightNametlNS2_Ut_ELd405ec00000000000EEEEEEvv
+  // DEMANGLED: call void @void dummy<wrapper2<double>{wrapper2<double>::'unnamed'{.RightName = wrapper2<double>::'unnamed'::'unnamed'{0x1.ecp+6}}}>()()
+  dummy<wrapper3<double>{123, 456}>();
+  // CHECK: call void @_Z5dummyIXtl8wrapper3IdEtlNS1_Ut_Edi9RightNametlNS2_Ut_Etl4BaseLi123EELd407c800000000000EEEEEEvv
+  // DEMANGLED: call void @void dummy<wrapper3<double>{wrapper3<double>::'unnamed'{.RightName = wrapper3<double>::'unnamed'::'unnamed'{Base{123}, 0x1.c8p+8}}}>()()
+  dummy<wrapper4<double>{123}>();
+  // CHECK: call void @_Z5dummyIXtl8wrapper4IdEtlNS1_Ut_Edi9RightNameLi123EEEEEvv
+  // DEMANGLED: call void @void dummy<wrapper4<double>{wrapper4<double>::'unnamed'{.RightName = 123}}>()()
+  dummy<wrapper5<double>{123.0, 456.0}>();
+  // CHECK: call void @_Z5dummyIXtl8wrapper5IdEtlNS1_Ut_Edi9RightNametlNS2_Ut_EtlNS3_Ut_ELd405ec00000000000EELd407c800000000000EEEEEEvv
+  // DEMANGLED: call void @void dummy<wrapper5<double>{wrapper5<double>::'unnamed'{.RightName = wrapper5<double>::'unnamed'::'unnamed'{wrapper5<double>::'unnamed'::'unnamed'::'unnamed'{0x1.ecp+6}, 0x1.c8p+8}}}>()()
+}
Index: clang/lib/AST/ItaniumMangle.cpp
===================================================================
--- clang/lib/AST/ItaniumMangle.cpp
+++ clang/lib/AST/ItaniumMangle.cpp
@@ -5545,6 +5545,37 @@
   return T;
 }
 
+static IdentifierInfo *getUnionInitName(const FieldDecl *FD) {
+  // According to:
+  // http://itanium-cxx-abi.github.io/cxx-abi/abi.html#mangling.anonymous
+  // 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 (FD->getIdentifier())
+    return FD->getIdentifier();
+
+  // The only cases where the identifer of a FieldDecl would be blank is if the
+  // field represents an anonymous record type.
+  const CXXRecordDecl *RD = FD->getType()->getAsCXXRecordDecl();
+
+  // Consider only the fields in declaration order, searched depth-first.  We
+  // don't care about the active member of the union, as all we are doing is
+  // looking for a valid name. We also don't check bases, due to guidance from
+  // the Itanium ABI folks.
+  for (const FieldDecl *RDField : RD->fields()) {
+      if (IdentifierInfo *II = getUnionInitName(RDField))
+        return II;
+  }
+
+  llvm_unreachable(
+      "Itanium ABI claims: ' 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. '");
+}
+
 void CXXNameMangler::mangleValueInTemplateArg(QualType T, const APValue &V,
                                               bool TopLevel,
                                               bool NeedExactType) {
@@ -5628,7 +5659,7 @@
     mangleType(T);
     if (!isZeroInitialized(T, V)) {
       Out << "di";
-      mangleSourceName(FD->getIdentifier());
+      mangleSourceName(getUnionInitName(FD));
       mangleValueInTemplateArg(FD->getType(), V.getUnionValue(), false);
     }
     Out << 'E';
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to