erichkeane updated this revision to Diff 419748.
erichkeane added a comment.

Update to 'diag' instead of crash, as implied/requested by @rjmccall


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D122820/new/

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,113 @@
+// 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<typename T>
+struct wrapper6 {
+  union {
+    union{
+    int : 5;
+    T RightName;
+    };
+  };
+};
+
+
+
+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<wrapper6<int>{}>();
+  // CHECK: call void @_Z5dummyIXtl8wrapper6IiEEEEvv
+  // DEMANGLED: call void @void dummy<wrapper6<int>{}>()()
+
+  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}}}>()()
+  dummy<wrapper6<double>{1}>();
+  // CHECK: call void @_Z5dummyIXtl8wrapper6IdEtlNS1_Ut_Edi9RightNametlNS2_Ut_Edi9RightNameLd3ff0000000000000EEEEEEvv
+  // DEMANGELD: call void @void dummy<wrapper6<double>{wrapper6<double>::'unnamed'{.RightName = wrapper6<double>::'unnamed'::'unnamed'{.RightName = 0x1p+0}}}>()()   
+}
Index: clang/lib/AST/ItaniumMangle.cpp
===================================================================
--- clang/lib/AST/ItaniumMangle.cpp
+++ clang/lib/AST/ItaniumMangle.cpp
@@ -5545,6 +5545,47 @@
   return T;
 }
 
+static IdentifierInfo *getUnionInitName(SourceLocation UnionLoc,
+                                        DiagnosticsEngine &Diags,
+                                        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 or if it is an unnamed bitfield.
+  // There is no type to descend into in the case of a bitfield, so we can just
+  // return nullptr in that case.
+  if (FD->isBitField())
+    return nullptr;
+  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(UnionLoc, Diags, RDField))
+      return II;
+  }
+
+  // According to the Itanium ABI: 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. However, we should diagnose this anyway.
+  unsigned DiagID = Diags.getCustomDiagID(
+      DiagnosticsEngine::Error, "cannot mangle this unnamed union NTTP yet");
+  Diags.Report(UnionLoc, DiagID);
+
+  return nullptr;
+}
+
 void CXXNameMangler::mangleValueInTemplateArg(QualType T, const APValue &V,
                                               bool TopLevel,
                                               bool NeedExactType) {
@@ -5628,7 +5669,10 @@
     mangleType(T);
     if (!isZeroInitialized(T, V)) {
       Out << "di";
-      mangleSourceName(FD->getIdentifier());
+      IdentifierInfo *II = (getUnionInitName(
+          T->getAsCXXRecordDecl()->getLocation(), Context.getDiags(), FD));
+      if (II)
+        mangleSourceName(II);
       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