Itanium ABI: Properly qualify the destructor-name

We didn't have enough qualificaiton before the scope specifier and we
had too much qualification in the destructor name itself.

llvm-svn: 229809
This commit is contained in:
David Majnemer 2015-02-19 02:16:16 +00:00
parent 0a52cd7937
commit b8014dd7c0
2 changed files with 185 additions and 208 deletions

View File

@ -327,10 +327,8 @@ private:
void addSubstitution(uintptr_t Ptr);
void mangleUnresolvedPrefix(NestedNameSpecifier *qualifier,
NamedDecl *firstQualifierLookup,
bool recursive = false);
void mangleUnresolvedName(NestedNameSpecifier *qualifier,
NamedDecl *firstQualifierLookup,
DeclarationName name,
unsigned KnownArity = UnknownArity);
@ -360,7 +358,8 @@ private:
void manglePrefix(QualType type);
void mangleTemplatePrefix(const TemplateDecl *ND, bool NoFunction=false);
void mangleTemplatePrefix(TemplateName Template);
void mangleDestructorName(QualType DestroyedType);
bool mangleUnresolvedTypeOrSimpleId(QualType DestroyedType,
StringRef Prefix = "");
void mangleOperatorName(DeclarationName Name, unsigned Arity);
void mangleOperatorName(OverloadedOperatorKind OO, unsigned Arity);
void mangleQualifiers(Qualifiers Quals);
@ -799,7 +798,6 @@ void CXXNameMangler::manglePrefix(QualType type) {
/// \param recursive - true if this is being called recursively,
/// i.e. if there is more prefix "to the right".
void CXXNameMangler::mangleUnresolvedPrefix(NestedNameSpecifier *qualifier,
NamedDecl *firstQualifierLookup,
bool recursive) {
// x, ::x
@ -832,7 +830,7 @@ void CXXNameMangler::mangleUnresolvedPrefix(NestedNameSpecifier *qualifier,
case NestedNameSpecifier::Namespace:
if (qualifier->getPrefix())
mangleUnresolvedPrefix(qualifier->getPrefix(), firstQualifierLookup,
mangleUnresolvedPrefix(qualifier->getPrefix(),
/*recursive*/ true);
else
Out << "sr";
@ -840,7 +838,7 @@ void CXXNameMangler::mangleUnresolvedPrefix(NestedNameSpecifier *qualifier,
break;
case NestedNameSpecifier::NamespaceAlias:
if (qualifier->getPrefix())
mangleUnresolvedPrefix(qualifier->getPrefix(), firstQualifierLookup,
mangleUnresolvedPrefix(qualifier->getPrefix(),
/*recursive*/ true);
else
Out << "sr";
@ -857,193 +855,26 @@ void CXXNameMangler::mangleUnresolvedPrefix(NestedNameSpecifier *qualifier,
// - a template template parameter with arguments
// In all of these cases, we should have no prefix.
if (qualifier->getPrefix()) {
mangleUnresolvedPrefix(qualifier->getPrefix(), firstQualifierLookup,
mangleUnresolvedPrefix(qualifier->getPrefix(),
/*recursive*/ true);
} else {
// Otherwise, all the cases want this.
Out << "sr";
}
// Only certain other types are valid as prefixes; enumerate them.
switch (type->getTypeClass()) {
case Type::Builtin:
case Type::Complex:
case Type::Adjusted:
case Type::Decayed:
case Type::Pointer:
case Type::BlockPointer:
case Type::LValueReference:
case Type::RValueReference:
case Type::MemberPointer:
case Type::ConstantArray:
case Type::IncompleteArray:
case Type::VariableArray:
case Type::DependentSizedArray:
case Type::DependentSizedExtVector:
case Type::Vector:
case Type::ExtVector:
case Type::FunctionProto:
case Type::FunctionNoProto:
case Type::Enum:
case Type::Paren:
case Type::Elaborated:
case Type::Attributed:
case Type::Auto:
case Type::PackExpansion:
case Type::ObjCObject:
case Type::ObjCInterface:
case Type::ObjCObjectPointer:
case Type::Atomic:
llvm_unreachable("type is illegal as a nested name specifier");
case Type::SubstTemplateTypeParmPack:
// FIXME: not clear how to mangle this!
// template <class T...> class A {
// template <class U...> void foo(decltype(T::foo(U())) x...);
// };
Out << "_SUBSTPACK_";
break;
// <unresolved-type> ::= <template-param>
// ::= <decltype>
// ::= <template-template-param> <template-args>
// (this last is not official yet)
case Type::TypeOfExpr:
case Type::TypeOf:
case Type::Decltype:
case Type::TemplateTypeParm:
case Type::UnaryTransform:
case Type::SubstTemplateTypeParm:
unresolvedType:
assert(!qualifier->getPrefix());
// We only get here recursively if we're followed by identifiers.
if (recursive) Out << 'N';
// This seems to do everything we want. It's not really
// sanctioned for a substituted template parameter, though.
mangleType(QualType(type, 0));
// We never want to print 'E' directly after an unresolved-type,
// so we return directly.
if (mangleUnresolvedTypeOrSimpleId(QualType(type, 0), recursive ? "N" : ""))
return;
case Type::Typedef:
mangleSourceName(cast<TypedefType>(type)->getDecl()->getIdentifier());
break;
case Type::UnresolvedUsing:
mangleSourceName(cast<UnresolvedUsingType>(type)->getDecl()
->getIdentifier());
break;
case Type::Record:
mangleSourceName(cast<RecordType>(type)->getDecl()->getIdentifier());
break;
case Type::TemplateSpecialization: {
const TemplateSpecializationType *tst
= cast<TemplateSpecializationType>(type);
TemplateName name = tst->getTemplateName();
switch (name.getKind()) {
case TemplateName::Template:
case TemplateName::QualifiedTemplate: {
TemplateDecl *temp = name.getAsTemplateDecl();
// If the base is a template template parameter, this is an
// unresolved type.
assert(temp && "no template for template specialization type");
if (isa<TemplateTemplateParmDecl>(temp)) goto unresolvedType;
mangleSourceName(temp->getIdentifier());
break;
}
case TemplateName::OverloadedTemplate:
case TemplateName::DependentTemplate:
llvm_unreachable("invalid base for a template specialization type");
case TemplateName::SubstTemplateTemplateParm: {
SubstTemplateTemplateParmStorage *subst
= name.getAsSubstTemplateTemplateParm();
mangleExistingSubstitution(subst->getReplacement());
break;
}
case TemplateName::SubstTemplateTemplateParmPack: {
// FIXME: not clear how to mangle this!
// template <template <class U> class T...> class A {
// template <class U...> void foo(decltype(T<U>::foo) x...);
// };
Out << "_SUBSTPACK_";
break;
}
}
mangleTemplateArgs(tst->getArgs(), tst->getNumArgs());
break;
}
case Type::InjectedClassName:
mangleSourceName(cast<InjectedClassNameType>(type)->getDecl()
->getIdentifier());
break;
case Type::DependentName:
mangleSourceName(cast<DependentNameType>(type)->getIdentifier());
break;
case Type::DependentTemplateSpecialization: {
const DependentTemplateSpecializationType *tst
= cast<DependentTemplateSpecializationType>(type);
mangleSourceName(tst->getIdentifier());
mangleTemplateArgs(tst->getArgs(), tst->getNumArgs());
break;
}
}
break;
}
case NestedNameSpecifier::Identifier:
// Member expressions can have these without prefixes.
if (qualifier->getPrefix()) {
mangleUnresolvedPrefix(qualifier->getPrefix(), firstQualifierLookup,
if (qualifier->getPrefix())
mangleUnresolvedPrefix(qualifier->getPrefix(),
/*recursive*/ true);
} else if (firstQualifierLookup) {
// Try to make a proper qualifier out of the lookup result, and
// then just recurse on that.
NestedNameSpecifier *newQualifier;
if (TypeDecl *typeDecl = dyn_cast<TypeDecl>(firstQualifierLookup)) {
QualType type = getASTContext().getTypeDeclType(typeDecl);
// Pretend we had a different nested name specifier.
newQualifier = NestedNameSpecifier::Create(getASTContext(),
/*prefix*/ nullptr,
/*template*/ false,
type.getTypePtr());
} else if (NamespaceDecl *nspace =
dyn_cast<NamespaceDecl>(firstQualifierLookup)) {
newQualifier = NestedNameSpecifier::Create(getASTContext(),
/*prefix*/ nullptr,
nspace);
} else if (NamespaceAliasDecl *alias =
dyn_cast<NamespaceAliasDecl>(firstQualifierLookup)) {
newQualifier = NestedNameSpecifier::Create(getASTContext(),
/*prefix*/ nullptr,
alias);
} else {
// No sensible mangling to do here.
newQualifier = nullptr;
}
if (newQualifier)
return mangleUnresolvedPrefix(newQualifier, /*lookup*/ nullptr,
recursive);
} else {
else
Out << "sr";
}
mangleSourceName(qualifier->getAsIdentifier());
break;
@ -1058,10 +889,9 @@ void CXXNameMangler::mangleUnresolvedPrefix(NestedNameSpecifier *qualifier,
/// Mangle an unresolved-name, which is generally used for names which
/// weren't resolved to specific entities.
void CXXNameMangler::mangleUnresolvedName(NestedNameSpecifier *qualifier,
NamedDecl *firstQualifierLookup,
DeclarationName name,
unsigned knownArity) {
if (qualifier) mangleUnresolvedPrefix(qualifier, firstQualifierLookup);
if (qualifier) mangleUnresolvedPrefix(qualifier);
switch (name.getNameKind()) {
// <base-unresolved-name> ::= <simple-id>
case DeclarationName::Identifier:
@ -1070,7 +900,7 @@ void CXXNameMangler::mangleUnresolvedName(NestedNameSpecifier *qualifier,
// <base-unresolved-name> ::= dn <destructor-name>
case DeclarationName::CXXDestructorName:
Out << "dn";
mangleDestructorName(name.getCXXNameType());
mangleUnresolvedTypeOrSimpleId(name.getCXXNameType());
break;
// <base-unresolved-name> ::= on <operator-name>
case DeclarationName::CXXConversionFunctionName:
@ -1648,29 +1478,149 @@ 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>()) {
bool CXXNameMangler::mangleUnresolvedTypeOrSimpleId(QualType Ty,
StringRef Prefix) {
// Only certain other types are valid as prefixes; enumerate them.
switch (Ty->getTypeClass()) {
case Type::Builtin:
case Type::Complex:
case Type::Adjusted:
case Type::Decayed:
case Type::Pointer:
case Type::BlockPointer:
case Type::LValueReference:
case Type::RValueReference:
case Type::MemberPointer:
case Type::ConstantArray:
case Type::IncompleteArray:
case Type::VariableArray:
case Type::DependentSizedArray:
case Type::DependentSizedExtVector:
case Type::Vector:
case Type::ExtVector:
case Type::FunctionProto:
case Type::FunctionNoProto:
case Type::Paren:
case Type::Attributed:
case Type::Auto:
case Type::PackExpansion:
case Type::ObjCObject:
case Type::ObjCInterface:
case Type::ObjCObjectPointer:
case Type::Atomic:
llvm_unreachable("type is illegal as a nested name specifier");
case Type::SubstTemplateTypeParmPack:
// FIXME: not clear how to mangle this!
// template <class T...> class A {
// template <class U...> void foo(decltype(T::foo(U())) x...);
// };
Out << "_SUBSTPACK_";
break;
// <unresolved-type> ::= <template-param>
// ::= <decltype>
// ::= <template-template-param> <template-args>
// (this last is not official yet)
case Type::TypeOfExpr:
case Type::TypeOf:
case Type::Decltype:
case Type::TemplateTypeParm:
case Type::UnaryTransform:
case Type::SubstTemplateTypeParm:
unresolvedType:
// Some callers want a prefix before the mangled type.
Out << Prefix;
// This seems to do everything we want. It's not really
// sanctioned for a substituted template parameter, though.
mangleType(Ty);
// We never want to print 'E' directly after an unresolved-type,
// so we return directly.
return true;
case Type::Typedef:
mangleSourceName(cast<TypedefType>(Ty)->getDecl()->getIdentifier());
break;
case Type::UnresolvedUsing:
mangleSourceName(
cast<UnresolvedUsingType>(Ty)->getDecl()->getIdentifier());
break;
case Type::Enum:
case Type::Record:
mangleSourceName(cast<TagType>(Ty)->getDecl()->getIdentifier());
break;
case Type::TemplateSpecialization: {
const TemplateSpecializationType *TST =
cast<TemplateSpecializationType>(Ty);
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());
switch (TN.getKind()) {
case TemplateName::Template:
case TemplateName::QualifiedTemplate: {
TemplateDecl *TD = TN.getAsTemplateDecl();
// If the base is a template template parameter, this is an
// unresolved type.
assert(TD && "no template for template specialization type");
if (isa<TemplateTemplateParmDecl>(TD))
goto unresolvedType;
mangleSourceName(TD->getIdentifier());
break;
}
case TemplateName::OverloadedTemplate:
case TemplateName::DependentTemplate:
llvm_unreachable("invalid base for a template specialization type");
case TemplateName::SubstTemplateTemplateParm: {
SubstTemplateTemplateParmStorage *subst =
TN.getAsSubstTemplateTemplateParm();
mangleExistingSubstitution(subst->getReplacement());
break;
}
case TemplateName::SubstTemplateTemplateParmPack: {
// FIXME: not clear how to mangle this!
// template <template <class U> class T...> class A {
// template <class U...> void foo(decltype(T<U>::foo) x...);
// };
Out << "_SUBSTPACK_";
break;
}
}
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);
break;
}
case Type::InjectedClassName:
mangleSourceName(
cast<InjectedClassNameType>(Ty)->getDecl()->getIdentifier());
break;
case Type::DependentName:
mangleSourceName(cast<DependentNameType>(Ty)->getIdentifier());
break;
case Type::DependentTemplateSpecialization: {
const DependentTemplateSpecializationType *DTST =
cast<DependentTemplateSpecializationType>(Ty);
mangleSourceName(DTST->getIdentifier());
mangleTemplateArgs(DTST->getArgs(), DTST->getNumArgs());
break;
}
case Type::Elaborated:
return mangleUnresolvedTypeOrSimpleId(
cast<ElaboratedType>(Ty)->getNamedType(), Prefix);
}
return false;
}
void CXXNameMangler::mangleOperatorName(DeclarationName Name, unsigned Arity) {
@ -2636,7 +2586,7 @@ void CXXNameMangler::mangleMemberExpr(const Expr *base,
// ::= pt <expression> <unresolved-name>
if (base)
mangleMemberExprBase(base, isArrow);
mangleUnresolvedName(qualifier, firstQualifierLookup, member, arity);
mangleUnresolvedName(qualifier, member, arity);
}
/// Look at the callee of the given call expression and determine if
@ -2894,12 +2844,26 @@ recurse:
const auto *PDE = cast<CXXPseudoDestructorExpr>(E);
if (const Expr *Base = PDE->getBase())
mangleMemberExprBase(Base, PDE->isArrow());
if (NestedNameSpecifier *Qualifier = PDE->getQualifier())
mangleUnresolvedPrefix(Qualifier, /*FirstQualifierLookup=*/nullptr);
NestedNameSpecifier *Qualifier = PDE->getQualifier();
QualType ScopeType;
if (TypeSourceInfo *ScopeInfo = PDE->getScopeTypeInfo()) {
if (Qualifier) {
mangleUnresolvedPrefix(Qualifier,
/*Recursive=*/true);
mangleUnresolvedTypeOrSimpleId(ScopeInfo->getType());
Out << 'E';
} else {
Out << "sr";
if (!mangleUnresolvedTypeOrSimpleId(ScopeInfo->getType()))
Out << 'E';
}
} else if (Qualifier) {
mangleUnresolvedPrefix(Qualifier);
}
// <base-unresolved-name> ::= dn <destructor-name>
Out << "dn";
QualType DestroyedType = PDE->getDestroyedType();
mangleDestructorName(DestroyedType);
mangleUnresolvedTypeOrSimpleId(DestroyedType);
break;
}
@ -2934,7 +2898,7 @@ recurse:
case Expr::UnresolvedLookupExprClass: {
const UnresolvedLookupExpr *ULE = cast<UnresolvedLookupExpr>(E);
mangleUnresolvedName(ULE->getQualifier(), nullptr, ULE->getName(), Arity);
mangleUnresolvedName(ULE->getQualifier(), ULE->getName(), Arity);
// All the <unresolved-name> productions end in a
// base-unresolved-name, where <template-args> are just tacked
@ -3248,8 +3212,7 @@ recurse:
case Expr::DependentScopeDeclRefExprClass: {
const DependentScopeDeclRefExpr *DRE = cast<DependentScopeDeclRefExpr>(E);
mangleUnresolvedName(DRE->getQualifier(), nullptr, DRE->getDeclName(),
Arity);
mangleUnresolvedName(DRE->getQualifier(), DRE->getDeclName(), Arity);
// All the <unresolved-name> productions end in a
// base-unresolved-name, where <template-args> are just tacked

View File

@ -1024,6 +1024,12 @@ namespace test51 {
template void fun<S1<int> >();
// CHECK-LABEL: @_ZN6test513funI2S1IiEEEDTcldtcvT__EdnS3_EEv
enum E {};
template <typename T>
struct X {
struct Y {};
};
template <typename T>
decltype(S1<T>().~S1<T>()) fun1() {};
template <typename U, typename T>
@ -1036,6 +1042,10 @@ namespace test51 {
decltype(S1<int>().~S1<T>()) fun5(){};
template <template <typename T> class U>
decltype(S1<int>().~U<int>()) fun6(){};
template <typename T>
decltype(E().E::~T()) fun7() {}
template <template <typename> class U>
decltype(X<int>::Y().U<int>::Y::~Y()) fun8() {}
template void fun1<int>();
// CHECK-LABEL: @_ZN6test514fun1IiEEDTcldtcv2S1IT_E_Edn2S1IS2_EEEv
template void fun2<S1<int>, int>();
@ -1045,6 +1055,10 @@ namespace test51 {
template void fun4<int>();
// CHECK-LABEL: @_ZN6test514fun4IiEEDTcmcldtcv2S1IT_E_Edn2S1IS2_EEcldtcvS3__Edn2S1IS2_EEEv
template void fun5<int>();
// CHECK-LABEL: @_ZN6test514fun6I2S1EEDTcldtcvS1_IiE_EdnT_IiEEEv
// CHECK-LABEL: @_ZN6test514fun5IiEEDTcldtcv2S1IiE_Edn2S1IT_EEEv
template void fun6<S1>();
// CHECK-LABEL: @_ZN6test514fun6I2S1EEDTcldtcvS1_IiE_EdnT_IiEEEv
template void fun7<E>();
// CHECK-LABEL: @_ZN6test514fun7INS_1EEEEDTcldtcvS1__Esr1EEdnT_EEv
template void fun8<X>();
}