forked from OSchip/llvm-project
Reapply"[GH54588]Fix ItaniumMangler for NTTP unnamed unions w/ unnamed structs"
AND the followups that fixed builds.
I attempted to get 'cute' and use llvm-cxxfilt to make the test look
nicer, but apparently some of the bots have a version of llvm-cxxfilt
that is not the in-tree one, so it fails to properly demangle the stuff.
I've disabled this "RUN" line.
This reverts commit 50186b63d1
.
This commit is contained in:
parent
980c3e6dd2
commit
d1205bb37d
|
@ -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';
|
||||
|
|
|
@ -0,0 +1,117 @@
|
|||
// RUN: %clang_cc1 -std=c++20 -emit-llvm %s -o - -triple=x86_64-linux-gnu | FileCheck %s
|
||||
|
||||
// FIXME: In the future we could possibly do this to get nicer looking output
|
||||
// for this, but it seems that some of the bots don't have a recent enough
|
||||
// version of llvm-cxxfilt to demangle these.
|
||||
// %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.ec{{.*}}p+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.ec{{.*}}p+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.c8{{.*}}p+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.ec{{.*}}p+6}, 0x1.c8{{.*}}p+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 = 0x1{{.*}}p+0}}}>()()
|
||||
}
|
Loading…
Reference in New Issue