From: John McCall Date: Wed, 4 May 2011 01:45:19 +0000 (+0000) Subject: Type prefixes of unresolved-names should only be mangled as unresolved-types X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=4f4e413f282609d4a488b44fc8669c28636a7aba;p=clang Type prefixes of unresolved-names should only be mangled as unresolved-types if they match that production, i.e. if they're template type parameters or decltypes (or, as an obvious case not yet described in the ABI document, if they're template template parameters applied to template arguments). git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@130824 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/AST/ItaniumMangle.cpp b/lib/AST/ItaniumMangle.cpp index c460929c46..e368c8927f 100644 --- a/lib/AST/ItaniumMangle.cpp +++ b/lib/AST/ItaniumMangle.cpp @@ -255,7 +255,8 @@ private: DeclarationName name, unsigned KnownArity = UnknownArity); - void mangleUnresolvedType(QualType type); + static bool isUnresolvedType(const Type *type); + void mangleUnresolvedType(const Type *type); void mangleName(const TemplateDecl *TD, const TemplateArgument *TemplateArgs, @@ -277,6 +278,7 @@ private: unsigned NumTemplateArgs); void manglePrefix(NestedNameSpecifier *qualifier); void manglePrefix(const DeclContext *DC, bool NoFunction=false); + void manglePrefix(QualType type); void mangleTemplatePrefix(const TemplateDecl *ND); void mangleTemplatePrefix(TemplateName Template); void mangleOperatorName(OverloadedOperatorKind OO, unsigned Arity); @@ -317,6 +319,8 @@ private: void mangleTemplateArgs(const TemplateParameterList &PL, const TemplateArgumentList &AL); void mangleTemplateArg(const NamedDecl *P, const TemplateArgument &A); + void mangleUnresolvedTemplateArgs(const TemplateArgument *args, + unsigned numArgs); void mangleTemplateParameter(unsigned Index); @@ -667,7 +671,7 @@ void CXXNameMangler::mangleCallOffset(int64_t NonVirtual, int64_t Virtual) { Out << '_'; } -void CXXNameMangler::mangleUnresolvedType(QualType type) { +void CXXNameMangler::manglePrefix(QualType type) { if (const TemplateSpecializationType *TST = type->getAs()) { if (!mangleSubstitution(QualType(TST, 0))) { @@ -698,6 +702,31 @@ void CXXNameMangler::mangleUnresolvedType(QualType type) { } } +/// Returns true if the given type, appearing within an +/// unresolved-name, should be mangled as an unresolved-type. +bool CXXNameMangler::isUnresolvedType(const Type *type) { + // ::= + // ::= + // ::= + // (this last is not official yet) + + if (isa(type)) return true; + if (isa(type)) return true; + // typeof? + if (const TemplateSpecializationType *tst = + dyn_cast(type)) { + TemplateDecl *temp = tst->getTemplateName().getAsTemplateDecl(); + if (temp && isa(temp)) + return true; + } + return false; +} + +void CXXNameMangler::mangleUnresolvedType(const Type *type) { + // This seems to be do everything we want. + mangleType(QualType(type, 0)); +} + /// Mangle everything prior to the base-unresolved-name in an unresolved-name. /// /// \param firstQualifierLookup - the entity found by unqualified lookup @@ -752,17 +781,60 @@ void CXXNameMangler::mangleUnresolvedPrefix(NestedNameSpecifier *qualifier, case NestedNameSpecifier::TypeSpec: case NestedNameSpecifier::TypeSpecWithTemplate: { - // Both cases want this. - Out << "sr"; + const Type *type = qualifier->getAsType(); + + // We only want to use an unresolved-type encoding if this is one of: + // - a decltype + // - a template type parameter + // - a template template parameter with arguments + // In all of these cases, we should have no prefix. + if (qualifier->getPrefix()) { + mangleUnresolvedPrefix(qualifier->getPrefix(), firstQualifierLookup, + /*recursive*/ true); + } else { + // Otherwise, all the cases want this. + Out << "sr"; - // We only get here recursively if we're followed by identifiers. - if (recursive) Out << 'N'; + if (isUnresolvedType(type)) { + // We only get here recursively if we're followed by identifiers. + if (recursive) Out << 'N'; + mangleUnresolvedType(type); - mangleUnresolvedType(QualType(qualifier->getAsType(), 0)); + // We never want to print 'E' directly after an unresolved-type, + // so we return directly. + return; + } + } - // We never want to print 'E' directly after an unresolved-type, - // so we return directly. - return; + assert(!isUnresolvedType(type)); + + // Only certain other types are valid as prefixes; enumerate them. + // FIXME: can we get ElaboratedTypes here? + // FIXME: SubstTemplateTypeParmType? + if (const TagType *t = dyn_cast(type)) { + mangleSourceName(t->getDecl()->getIdentifier()); + } else if (const TypedefType *t = dyn_cast(type)) { + mangleSourceName(t->getDecl()->getIdentifier()); + } else if (const UnresolvedUsingType *t + = dyn_cast(type)) { + mangleSourceName(t->getDecl()->getIdentifier()); + } else if (const DependentNameType *t + = dyn_cast(type)) { + mangleSourceName(t->getIdentifier()); + } else if (const TemplateSpecializationType *tst + = dyn_cast(type)) { + TemplateDecl *temp = tst->getTemplateName().getAsTemplateDecl(); + assert(temp && "no template for template specialization type"); + mangleSourceName(temp->getIdentifier()); + mangleUnresolvedTemplateArgs(tst->getArgs(), tst->getNumArgs()); + } else if (const DependentTemplateSpecializationType *tst + = dyn_cast(type)) { + mangleSourceName(tst->getIdentifier()); + mangleUnresolvedTemplateArgs(tst->getArgs(), tst->getNumArgs()); + } else { + llvm_unreachable("unexpected type in nested name specifier!"); + } + break; } case NestedNameSpecifier::Identifier: @@ -1097,7 +1169,7 @@ void CXXNameMangler::manglePrefix(NestedNameSpecifier *qualifier) { case NestedNameSpecifier::TypeSpec: case NestedNameSpecifier::TypeSpecWithTemplate: - mangleUnresolvedType(QualType(qualifier->getAsType(), 0)); + manglePrefix(QualType(qualifier->getAsType(), 0)); return; case NestedNameSpecifier::Identifier: @@ -2552,8 +2624,8 @@ void CXXNameMangler::mangleTemplateArgs( const ExplicitTemplateArgumentList &TemplateArgs) { // ::= I + E Out << 'I'; - for (unsigned I = 0, E = TemplateArgs.NumTemplateArgs; I != E; ++I) - mangleTemplateArg(0, TemplateArgs.getTemplateArgs()[I].getArgument()); + for (unsigned i = 0, e = TemplateArgs.NumTemplateArgs; i != e; ++i) + mangleTemplateArg(0, TemplateArgs.getTemplateArgs()[i].getArgument()); Out << 'E'; } @@ -2564,10 +2636,15 @@ void CXXNameMangler::mangleTemplateArgs(TemplateName Template, return mangleTemplateArgs(*TD->getTemplateParameters(), TemplateArgs, NumTemplateArgs); + mangleUnresolvedTemplateArgs(TemplateArgs, NumTemplateArgs); +} + +void CXXNameMangler::mangleUnresolvedTemplateArgs(const TemplateArgument *args, + unsigned numArgs) { // ::= I + E Out << 'I'; - for (unsigned i = 0; i != NumTemplateArgs; ++i) - mangleTemplateArg(0, TemplateArgs[i]); + for (unsigned i = 0; i != numArgs; ++i) + mangleTemplateArg(0, args[i]); Out << 'E'; } diff --git a/test/CodeGenCXX/mangle.cpp b/test/CodeGenCXX/mangle.cpp index 27777a51c4..01dcf8b230 100644 --- a/test/CodeGenCXX/mangle.cpp +++ b/test/CodeGenCXX/mangle.cpp @@ -397,16 +397,16 @@ namespace test3 { struct Path2 : AmbiguousBase { double p; }; struct Derived : Path1, Path2 { }; - // CHECK: define linkonce_odr i32 @_ZN5test38get_ab_1INS_7DerivedEEEDtptcvPT_Li0EsrNS_5Path1E2abERS2_( + // CHECK: define linkonce_odr i32 @_ZN5test38get_ab_1INS_7DerivedEEEDtptcvPT_Li0Esr5Path1E2abERS2_( template decltype(((T*) 0)->Path1::ab) get_ab_1(T &ref) { return ref.Path1::ab; } - // CHECK: define linkonce_odr i32 @_ZN5test38get_ab_2INS_7DerivedEEEDtptcvPT_Li0EsrNS_5Path2E2abERS2_( + // CHECK: define linkonce_odr i32 @_ZN5test38get_ab_2INS_7DerivedEEEDtptcvPT_Li0Esr5Path2E2abERS2_( template decltype(((T*) 0)->Path2::ab) get_ab_2(T &ref) { return ref.Path2::ab; } - // CHECK: define linkonce_odr float @_ZN5test37get_p_1INS_7DerivedEEEDtptcvPT_Li0EsrNS_5Path1E1pERS2_( + // CHECK: define linkonce_odr float @_ZN5test37get_p_1INS_7DerivedEEEDtptcvPT_Li0Esr5Path1E1pERS2_( template decltype(((T*) 0)->Path1::p) get_p_1(T &ref) { return ref.Path1::p; } - // CHECK: define linkonce_odr double @_ZN5test37get_p_2INS_7DerivedEEEDtptcvPT_Li0EsrNS_5Path2E1pERS2_( + // CHECK: define linkonce_odr double @_ZN5test37get_p_2INS_7DerivedEEEDtptcvPT_Li0Esr5Path2E1pERS2_( template decltype(((T*) 0)->Path2::p) get_p_2(T &ref) { return ref.Path2::p; } Derived obj; @@ -676,3 +676,38 @@ namespace test25 { A::call(); } } + +namespace test26 { + template