From: Douglas Gregor Date: Wed, 28 Apr 2010 05:58:56 +0000 (+0000) Subject: Improve name mangling for dependent template names (e.g., typename X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=1e9268e29798155b9edb5b20ac7490d8539ef6aa;p=clang Improve name mangling for dependent template names (e.g., typename T::template apply), handling a few cases where we previously failed and performing substitutions on such dependent names. Fixes a crash in Boost.PropertyTree. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@102490 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/CodeGen/Mangle.cpp b/lib/CodeGen/Mangle.cpp index cb32570bd4..8658cfb028 100644 --- a/lib/CodeGen/Mangle.cpp +++ b/lib/CodeGen/Mangle.cpp @@ -111,6 +111,7 @@ public: private: bool mangleSubstitution(const NamedDecl *ND); bool mangleSubstitution(QualType T); + bool mangleSubstitution(TemplateName Template); bool mangleSubstitution(uintptr_t Ptr); bool mangleStandardSubstitution(const NamedDecl *ND); @@ -121,6 +122,7 @@ private: addSubstitution(reinterpret_cast(ND)); } void addSubstitution(QualType T); + void addSubstitution(TemplateName Template); void addSubstitution(uintptr_t Ptr); void mangleUnresolvedScope(NestedNameSpecifier *Qualifier); @@ -138,6 +140,7 @@ private: unsigned KnownArity); void mangleUnscopedName(const NamedDecl *ND); void mangleUnscopedTemplateName(const TemplateDecl *ND); + void mangleUnscopedTemplateName(TemplateName); void mangleSourceName(const IdentifierInfo *II); void mangleLocalName(const NamedDecl *ND); void mangleNestedName(const NamedDecl *ND, const DeclContext *DC, @@ -431,6 +434,31 @@ void CXXNameMangler::mangleUnscopedTemplateName(const TemplateDecl *ND) { addSubstitution(ND); } +void CXXNameMangler::mangleUnscopedTemplateName(TemplateName Template) { + // ::= + // ::= + if (TemplateDecl *TD = Template.getAsTemplateDecl()) + return mangleUnscopedTemplateName(TD); + + if (mangleSubstitution(Template)) + return; + + // FIXME: How to cope with operators here? + DependentTemplateName *Dependent = Template.getAsDependentTemplateName(); + assert(Dependent && "Not a dependent template name?"); + if (!Dependent->isIdentifier()) { + // FIXME: We can't possibly know the arity of the operator here! + Diagnostic &Diags = Context.getDiags(); + unsigned DiagID = Diags.getCustomDiagID(Diagnostic::Error, + "cannot mangle dependent operator name"); + Diags.Report(FullSourceLoc(), DiagID); + return; + } + + mangleSourceName(Dependent->getIdentifier()); + addSubstitution(Template); +} + void CXXNameMangler::mangleNumber(int64_t Number) { // ::= [n] if (Number < 0) { @@ -764,15 +792,7 @@ void CXXNameMangler::mangleTemplatePrefix(TemplateName Template) { DependentTemplateName *Dependent = Template.getAsDependentTemplateName(); assert(Dependent && "Unknown template name kind?"); mangleUnresolvedScope(Dependent->getQualifier()); - if (Dependent->isIdentifier()) - mangleSourceName(Dependent->getIdentifier()); - else { - // FIXME: We can't possibly know the arity of the operator here! - Diagnostic &Diags = Context.getDiags(); - unsigned DiagID = Diags.getCustomDiagID(Diagnostic::Error, - "cannot mangle dependent operator name"); - Diags.Report(FullSourceLoc(), DiagID); - } + mangleUnscopedTemplateName(Template); } void CXXNameMangler::mangleTemplatePrefix(const TemplateDecl *ND) { @@ -1199,17 +1219,42 @@ void CXXNameMangler::mangleType(const InjectedClassNameType *T) { } void CXXNameMangler::mangleType(const TemplateSpecializationType *T) { - TemplateDecl *TD = T->getTemplateName().getAsTemplateDecl(); - assert(TD && "FIXME: Support dependent template names!"); - - mangleName(TD, T->getArgs(), T->getNumArgs()); + if (TemplateDecl *TD = T->getTemplateName().getAsTemplateDecl()) { + mangleName(TD, T->getArgs(), T->getNumArgs()); + } else { + if (mangleSubstitution(QualType(T, 0))) + return; + + mangleTemplatePrefix(T->getTemplateName()); + + // 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(T->getTemplateName(), T->getArgs(), T->getNumArgs()); + addSubstitution(QualType(T, 0)); + } } void CXXNameMangler::mangleType(const DependentNameType *T) { // Typename types are always nested Out << 'N'; - mangleUnresolvedScope(T->getQualifier()); - mangleSourceName(T->getIdentifier()); + if (T->getIdentifier()) { + mangleUnresolvedScope(T->getQualifier()); + mangleSourceName(T->getIdentifier()); + } else { + const TemplateSpecializationType *TST = T->getTemplateId(); + if (!mangleSubstitution(QualType(TST, 0))) { + mangleTemplatePrefix(TST->getTemplateName()); + + // 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(TST->getTemplateName(), TST->getArgs(), + TST->getNumArgs()); + addSubstitution(QualType(TST, 0)); + } + } + Out << 'E'; } @@ -1743,6 +1788,15 @@ bool CXXNameMangler::mangleSubstitution(QualType T) { return mangleSubstitution(TypePtr); } +bool CXXNameMangler::mangleSubstitution(TemplateName Template) { + if (TemplateDecl *TD = Template.getAsTemplateDecl()) + return mangleSubstitution(TD); + + Template = Context.getASTContext().getCanonicalTemplateName(Template); + return mangleSubstitution( + reinterpret_cast(Template.getAsVoidPointer())); +} + bool CXXNameMangler::mangleSubstitution(uintptr_t Ptr) { llvm::DenseMap::iterator I = Substitutions.find(Ptr); if (I == Substitutions.end()) @@ -1921,6 +1975,14 @@ void CXXNameMangler::addSubstitution(QualType T) { addSubstitution(TypePtr); } +void CXXNameMangler::addSubstitution(TemplateName Template) { + if (TemplateDecl *TD = Template.getAsTemplateDecl()) + return addSubstitution(TD); + + Template = Context.getASTContext().getCanonicalTemplateName(Template); + addSubstitution(reinterpret_cast(Template.getAsVoidPointer())); +} + void CXXNameMangler::addSubstitution(uintptr_t Ptr) { unsigned SeqID = Substitutions.size(); diff --git a/test/CodeGenCXX/mangle-template.cpp b/test/CodeGenCXX/mangle-template.cpp index 8b097ff69f..6a29944071 100644 --- a/test/CodeGenCXX/mangle-template.cpp +++ b/test/CodeGenCXX/mangle-template.cpp @@ -127,3 +127,20 @@ namespace test9 { f(); } } + +namespace test10 { + template + struct X { + template + struct definition { + }; + }; + + // CHECK: _ZN6test101fIidEENS_1XIT_E10definitionIT0_EES2_S5_ + template + typename X::template definition f(T, U) { } + + void g(int i, double d) { + f(i, d); + } +}