Itanium ABI: Improve our mangling of <destructor-name>

Our mangling of <destructor-name> wasn't quite right: we'd introduce
mangling substitutions where one shouldn't be possible.  We also didn't
correctly handle the case where the destroyed type was not dependent but
still a TemplateSpecializationType.

N.B. There isn't a mangling for a template-template parameter showing up
as the destroyed type.  We do the 'obvious' thing and mangle the index
of the parameter.

llvm-svn: 229615
This commit is contained in:
David Majnemer 2015-02-18 02:28:01 +00:00
parent 0ba644b66b
commit a88b359fdc
3 changed files with 117 additions and 42 deletions

View File

@ -352,6 +352,8 @@ private:
void manglePrefix(QualType type);
void mangleTemplatePrefix(const TemplateDecl *ND, bool NoFunction=false);
void mangleTemplatePrefix(TemplateName Template);
void mangleDestructorName(QualType DestroyedType);
void mangleOperatorName(DeclarationName Name, unsigned Arity);
void mangleOperatorName(OverloadedOperatorKind OO, unsigned Arity);
void mangleQualifiers(Qualifiers Quals);
void mangleRefQualifier(RefQualifierKind RefQualifier);
@ -752,8 +754,7 @@ void CXXNameMangler::mangleCallOffset(int64_t NonVirtual, int64_t Virtual) {
}
void CXXNameMangler::manglePrefix(QualType type) {
if (const TemplateSpecializationType *TST =
type->getAs<TemplateSpecializationType>()) {
if (const auto *TST = type->getAs<TemplateSpecializationType>()) {
if (!mangleSubstitution(QualType(TST, 0))) {
mangleTemplatePrefix(TST->getTemplateName());
@ -763,17 +764,19 @@ void CXXNameMangler::manglePrefix(QualType type) {
mangleTemplateArgs(TST->getArgs(), TST->getNumArgs());
addSubstitution(QualType(TST, 0));
}
} else if (const DependentTemplateSpecializationType *DTST
= type->getAs<DependentTemplateSpecializationType>()) {
TemplateName Template
= getASTContext().getDependentTemplateName(DTST->getQualifier(),
DTST->getIdentifier());
mangleTemplatePrefix(Template);
} else if (const auto *DTST =
type->getAs<DependentTemplateSpecializationType>()) {
if (!mangleSubstitution(QualType(DTST, 0))) {
TemplateName Template = getASTContext().getDependentTemplateName(
DTST->getQualifier(), DTST->getIdentifier());
mangleTemplatePrefix(Template);
// FIXME: GCC does not appear to mangle the template arguments when
// the template in question is a dependent template name. Should we
// emulate that badness?
mangleTemplateArgs(DTST->getArgs(), DTST->getNumArgs());
// FIXME: GCC does not appear to mangle the template arguments when
// the template in question is a dependent template name. Should we
// emulate that badness?
mangleTemplateArgs(DTST->getArgs(), DTST->getNumArgs());
addSubstitution(QualType(DTST, 0));
}
} else {
// We use the QualType mangle type variant here because it handles
// substitutions.
@ -1054,15 +1057,20 @@ void CXXNameMangler::mangleUnresolvedName(NestedNameSpecifier *qualifier,
switch (name.getNameKind()) {
// <base-unresolved-name> ::= <simple-id>
case DeclarationName::Identifier:
mangleSourceName(name.getAsIdentifierInfo());
break;
// <base-unresolved-name> ::= dn <destructor-name>
case DeclarationName::CXXDestructorName:
Out << "dn";
mangleDestructorName(name.getCXXNameType());
break;
// <base-unresolved-name> ::= on <operator-name>
case DeclarationName::CXXConversionFunctionName:
case DeclarationName::CXXLiteralOperatorName:
case DeclarationName::CXXOperatorName:
Out << "on";
mangleOperatorName(name, knownArity);
break;
case DeclarationName::CXXDestructorName:
llvm_unreachable("Can't mangle a constructor name!");
case DeclarationName::CXXConstructorName:
llvm_unreachable("Can't mangle a constructor name!");
case DeclarationName::CXXUsingDirective:
@ -1072,12 +1080,12 @@ void CXXNameMangler::mangleUnresolvedName(NestedNameSpecifier *qualifier,
case DeclarationName::ObjCZeroArgSelector:
llvm_unreachable("Can't mangle Objective-C selector names here!");
}
mangleUnqualifiedName(nullptr, name, knownArity);
}
void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND,
DeclarationName Name,
unsigned KnownArity) {
unsigned Arity = KnownArity;
// <unqualified-name> ::= <operator-name>
// ::= <ctor-dtor-name>
// ::= <source-name>
@ -1219,33 +1227,19 @@ void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND,
mangleCXXDtorType(Dtor_Complete);
break;
case DeclarationName::CXXConversionFunctionName:
// <operator-name> ::= cv <type> # (cast)
Out << "cv";
mangleType(Name.getCXXNameType());
break;
case DeclarationName::CXXOperatorName: {
unsigned Arity;
if (ND) {
case DeclarationName::CXXOperatorName:
if (ND && Arity == UnknownArity) {
Arity = cast<FunctionDecl>(ND)->getNumParams();
// If we have a C++ member function, we need to include the 'this' pointer.
// FIXME: This does not make sense for operators that are static, but their
// names stay the same regardless of the arity (operator new for instance).
if (isa<CXXMethodDecl>(ND))
Arity++;
} else
Arity = KnownArity;
mangleOperatorName(Name.getCXXOverloadedOperator(), Arity);
break;
}
// If we have a member function, we need to include the 'this' pointer.
if (const auto *MD = dyn_cast<CXXMethodDecl>(ND))
if (!MD->isStatic())
Arity++;
}
// FALLTHROUGH
case DeclarationName::CXXConversionFunctionName:
case DeclarationName::CXXLiteralOperatorName:
// FIXME: This mangling is not yet official.
Out << "li";
mangleSourceName(Name.getCXXLiteralIdentifier());
mangleOperatorName(Name, Arity);
break;
case DeclarationName::CXXUsingDirective:
@ -1646,6 +1640,61 @@ void CXXNameMangler::mangleType(TemplateName TN) {
addSubstitution(TN);
}
void CXXNameMangler::mangleDestructorName(QualType DestroyedType) {
// <destructor-name> ::= <unresolved-type>
// ::= <simple-id>
if (const auto *TST = DestroyedType->getAs<TemplateSpecializationType>()) {
TemplateName TN = TST->getTemplateName();
const auto *TD = TN.getAsTemplateDecl();
if (const auto *TTP = dyn_cast<TemplateTemplateParmDecl>(TD)) {
// Proposed to cxx-abi-dev on 2015-02-17.
mangleTemplateParameter(TTP->getIndex());
} else {
mangleUnscopedName(TD->getTemplatedDecl());
}
mangleTemplateArgs(TST->getArgs(), TST->getNumArgs());
} else if (const auto *DTST =
DestroyedType->getAs<DependentTemplateSpecializationType>()) {
const IdentifierInfo *II = DTST->getIdentifier();
mangleSourceName(II);
mangleTemplateArgs(DTST->getArgs(), DTST->getNumArgs());
} else {
// We use the QualType mangle type variant here because it handles
// substitutions.
mangleType(DestroyedType);
}
}
void CXXNameMangler::mangleOperatorName(DeclarationName Name, unsigned Arity) {
switch (Name.getNameKind()) {
case DeclarationName::CXXConstructorName:
case DeclarationName::CXXDestructorName:
case DeclarationName::CXXUsingDirective:
case DeclarationName::Identifier:
case DeclarationName::ObjCMultiArgSelector:
case DeclarationName::ObjCOneArgSelector:
case DeclarationName::ObjCZeroArgSelector:
llvm_unreachable("Not an operator name");
case DeclarationName::CXXConversionFunctionName:
// <operator-name> ::= cv <type> # (cast)
Out << "cv";
mangleType(Name.getCXXNameType());
break;
case DeclarationName::CXXLiteralOperatorName:
Out << "li";
mangleSourceName(Name.getCXXLiteralIdentifier());
return;
case DeclarationName::CXXOperatorName:
mangleOperatorName(Name.getCXXOverloadedOperator(), Arity);
break;
}
}
void
CXXNameMangler::mangleOperatorName(OverloadedOperatorKind OO, unsigned Arity) {
switch (OO) {
@ -2841,9 +2890,8 @@ recurse:
mangleUnresolvedPrefix(Qualifier, /*FirstQualifierLookup=*/nullptr);
// <base-unresolved-name> ::= dn <destructor-name>
Out << "dn";
// <destructor-name> ::= <unresolved-type>
// ::= <simple-id>
manglePrefix(PDE->getDestroyedType());
QualType DestroyedType = PDE->getDestroyedType();
mangleDestructorName(DestroyedType);
break;
}

View File

@ -80,3 +80,19 @@ void f(void (B::*)(), A, A) { }
void f(void (B::*)(), A, A, void (B::*)(A), void (A::*)()) { }
}
namespace ManglePrefix {
template <typename>
struct X {
template <typename>
struct Y {
typedef int type;
typedef int type2;
};
};
template <typename T>
typename X<T>::template Y<T>::type f(typename X<T>::template Y<T>::type2) { return 0; }
// CHECK: @_ZN12ManglePrefix1fIiEENS_1XIT_E1YIS2_E4typeENS5_5type2E
template int f<int>(int);
}

View File

@ -1030,10 +1030,21 @@ namespace test51 {
decltype(U().~S1<T>()) fun2() {}
template <typename U, typename T>
decltype(S1<T>().~U()) fun3() {}
template <typename T>
decltype(S1<T>().~S1<T>(), S1<T>().~S1<T>()) fun4() {};
template <typename T>
decltype(S1<int>().~S1<T>()) fun5(){};
template <template <typename T> class U>
decltype(S1<int>().~U<int>()) fun6(){};
template void fun1<int>();
// CHECK-LABEL: @_ZN6test514fun1IiEEDTcldtcv2S1IT_E_Edn2S1IS2_EEEv
template void fun2<S1<int>, int>();
// CHECK-LABEL: @_ZN6test514fun2I2S1IiEiEEDTcldtcvT__Edn2S1IT0_EEEv
template void fun3<S1<int>, int>();
// CHECK-LABEL: @_ZN6test514fun3I2S1IiEiEEDTcldtcvS1_IT0_E_EdnT_EEv
template void fun4<int>();
// CHECK-LABEL: @_ZN6test514fun4IiEEDTcmcldtcv2S1IT_E_Edn2S1IS2_EEcldtcvS3__Edn2S1IS2_EEEv
template void fun5<int>();
// CHECK-LABEL: @_ZN6test514fun6I2S1EEDTcldtcvS1_IiE_EdnT_IiEEEv
template void fun6<S1>();
}