[clang] 4cf98f9 - [GH54588]Fix ItaniumMangler for NTTP unnamed unions w/ unnamed structs
Erich Keane via cfe-commits
cfe-commits at lists.llvm.org
Fri Apr 1 11:48:47 PDT 2022
Author: Erich Keane
Date: 2022-04-01T11:31:14-07:00
New Revision: 4cf98f973a13c5049322abff43f0dff3c214311b
URL: https://github.com/llvm/llvm-project/commit/4cf98f973a13c5049322abff43f0dff3c214311b
DIFF: https://github.com/llvm/llvm-project/commit/4cf98f973a13c5049322abff43f0dff3c214311b.diff
LOG: [GH54588]Fix ItaniumMangler for NTTP unnamed unions w/ unnamed structs
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.
Differential Revision: https://reviews.llvm.org/D122820
Added:
clang/test/CodeGenCXX/mangle-nttp-anon-union.cpp
Modified:
clang/lib/AST/ItaniumMangle.cpp
Removed:
################################################################################
diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp
index fb76fa7b896fc..50e110ec1f57e 100644
--- a/clang/lib/AST/ItaniumMangle.cpp
+++ b/clang/lib/AST/ItaniumMangle.cpp
@@ -5545,6 +5545,47 @@ static QualType getLValueType(ASTContext &Ctx, const APValue &LV) {
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 @@ void CXXNameMangler::mangleValueInTemplateArg(QualType T, const APValue &V,
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';
diff --git a/clang/test/CodeGenCXX/mangle-nttp-anon-union.cpp b/clang/test/CodeGenCXX/mangle-nttp-anon-union.cpp
new file mode 100644
index 0000000000000..fcf07615eb991
--- /dev/null
+++ b/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}}}>()()
+}
More information about the cfe-commits
mailing list