From a88b359fdc59e46e8b784fb4f4d08dc482c5d2c9 Mon Sep 17 00:00:00 2001 From: David Majnemer Date: Wed, 18 Feb 2015 02:28:01 +0000 Subject: [PATCH] Itanium ABI: Improve our mangling of Our mangling of 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 --- clang/lib/AST/ItaniumMangle.cpp | 132 +++++++++++++++++-------- clang/test/CodeGenCXX/mangle-subst.cpp | 16 +++ clang/test/CodeGenCXX/mangle.cpp | 11 +++ 3 files changed, 117 insertions(+), 42 deletions(-) diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp index fdb256434f68..0d10bb1d9907 100644 --- a/clang/lib/AST/ItaniumMangle.cpp +++ b/clang/lib/AST/ItaniumMangle.cpp @@ -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()) { + if (const auto *TST = type->getAs()) { 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()) { - TemplateName Template - = getASTContext().getDependentTemplateName(DTST->getQualifier(), - DTST->getIdentifier()); - mangleTemplatePrefix(Template); + } else if (const auto *DTST = + type->getAs()) { + 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()) { // ::= case DeclarationName::Identifier: + mangleSourceName(name.getAsIdentifierInfo()); + break; + // ::= dn + case DeclarationName::CXXDestructorName: + Out << "dn"; + mangleDestructorName(name.getCXXNameType()); break; // ::= on 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; // ::= // ::= // ::= @@ -1219,33 +1227,19 @@ void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND, mangleCXXDtorType(Dtor_Complete); break; - case DeclarationName::CXXConversionFunctionName: - // ::= cv # (cast) - Out << "cv"; - mangleType(Name.getCXXNameType()); - break; - - case DeclarationName::CXXOperatorName: { - unsigned Arity; - if (ND) { + case DeclarationName::CXXOperatorName: + if (ND && Arity == UnknownArity) { Arity = cast(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(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(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) { + // ::= + // ::= + if (const auto *TST = DestroyedType->getAs()) { + TemplateName TN = TST->getTemplateName(); + const auto *TD = TN.getAsTemplateDecl(); + if (const auto *TTP = dyn_cast(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()) { + 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: + // ::= cv # (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); // ::= dn Out << "dn"; - // ::= - // ::= - manglePrefix(PDE->getDestroyedType()); + QualType DestroyedType = PDE->getDestroyedType(); + mangleDestructorName(DestroyedType); break; } diff --git a/clang/test/CodeGenCXX/mangle-subst.cpp b/clang/test/CodeGenCXX/mangle-subst.cpp index 30360aeae317..09326e2acf2c 100644 --- a/clang/test/CodeGenCXX/mangle-subst.cpp +++ b/clang/test/CodeGenCXX/mangle-subst.cpp @@ -80,3 +80,19 @@ void f(void (B::*)(), A, A) { } void f(void (B::*)(), A, A, void (B::*)(A), void (A::*)()) { } } + +namespace ManglePrefix { +template +struct X { + template + struct Y { + typedef int type; + typedef int type2; + }; +}; +template +typename X::template Y::type f(typename X::template Y::type2) { return 0; } + +// CHECK: @_ZN12ManglePrefix1fIiEENS_1XIT_E1YIS2_E4typeENS5_5type2E +template int f(int); +} diff --git a/clang/test/CodeGenCXX/mangle.cpp b/clang/test/CodeGenCXX/mangle.cpp index 3b4123eace50..e15d54086a64 100644 --- a/clang/test/CodeGenCXX/mangle.cpp +++ b/clang/test/CodeGenCXX/mangle.cpp @@ -1030,10 +1030,21 @@ namespace test51 { decltype(U().~S1()) fun2() {} template decltype(S1().~U()) fun3() {} + template + decltype(S1().~S1(), S1().~S1()) fun4() {}; + template + decltype(S1().~S1()) fun5(){}; + template