mirror of https://github.com/microsoft/clang.git
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. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@229615 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
cb59dc9022
commit
d2ec4c03b3
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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>();
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue