Index: include/clang/Basic/AttrDocs.td =================================================================== --- include/clang/Basic/AttrDocs.td +++ include/clang/Basic/AttrDocs.td @@ -2160,6 +2160,9 @@ } def AbiTagsDocs : Documentation { + // It it not function only attribute but creating special creating special + // category for this abi_tag attribute only seems overkill, eh. + let Category = DocCatFunction; let Content = [{ The ``abi_tag`` attribute can be applied to a function, variable, class or inline namespace declaration to modify the mangled name of the entity. It gives Index: lib/AST/ItaniumMangle.cpp =================================================================== --- lib/AST/ItaniumMangle.cpp +++ lib/AST/ItaniumMangle.cpp @@ -214,6 +214,8 @@ class CXXNameMangler { ItaniumMangleContextImpl &Context; raw_ostream &Out; + bool NullOut = false; + bool DisableDerivedAbiTags = false; /// The "structor" is the top-level declaration being mangled, if /// that's not a template specialization; otherwise it's the pattern @@ -263,15 +265,176 @@ } FunctionTypeDepth; + // abi_tag is a gcc attribute, taking one or more strings called "tags". + // + // The goal is to annotate against which version of a library an object was + // build and to be able to provide backwards compatibility ("dual abi"). + // + // For this the emitted mangled names have to be different, while you don't + // want the user to have to use different names in the source. + // + // The abi_tag can be present on Struct, Var and Function declarations as + // "explicit" tag, and on inline Namespace as "implicit" tag. Explicit tags + // are always emitted after the unqualified name, and (implicit) tags on + // namespace are not. + // + // For functions and variables there is a set of "implicitly available" + // tags. These tags are: all tags from the namespace/structs the name is + // embedded in, all tags from any template arguments of the name, and, for + // functions, alls tags used anywhere in the (i.e. + // parameters and sometimes the return type). + // + // For functions this is basically the list of all tags from the signature + // without the unqualified name and usually without the return type of the + // function. In `operator Type()` Type is NOT part of that list, as it is + // part of the unqualified name! + // + // Now all tags from the function return type/variable type which are not + // "implicitly available" must be added to the explicit list of tags, and + // are emitted after the unqualified name. + // + // Example: + // namespace std { + // inline namespace __cxx11 __attribute__((__abi_tag__("cxx11"))) { } + // inline namespace __cxx11 { + // struct string { }; + // } + // } + // + // std::string foo(); // needs abi tag "cxx11" on foo + // std::string foo(std::string); // does NOT need abi tag "cxx11" on foo + // __attribute__((__abi_tag__("cxx11"))) + // std::string foo2(std::string); // emit abi tag "cxx11" on foo anyway + // + // The tags are sorted by name before emitting, and are serialized as + // ::= B <"tag" source-name> + + typedef SmallVector AbiTagList; + + // State to gather all implicit and explicit tags used in a mangled name. + // Must always have an instance of this while emitting any name to keep + // track. + // + // FIXME: how to handle substituted names? They should add the tags used in + // the substitution to the list of available tags. + class AbiTagState final { + //! All abi tags used implicitly or explicitly + std::set UsedAbiTags; + //! All explicit abi tags (i.e. not from namespace) + std::set EmittedAbiTags; + + AbiTagState *&LinkHead; + AbiTagState *Parent{ nullptr }; + + bool LinkActive{ false }; + + public: + explicit AbiTagState(AbiTagState *&linkHead) : LinkHead(linkHead) { + Parent = LinkHead; + LinkHead = this; + LinkActive = true; + } + + // no copy, no move + AbiTagState(AbiTagState const &) = delete; + AbiTagState &operator=(AbiTagState const &) = delete; + + ~AbiTagState() { pop(); } + + void pop() { + if (!LinkActive) + return; + + assert(LinkHead == this && + "abi tag link head must point to us on destruction"); + LinkActive = false; + if (Parent) { + Parent->UsedAbiTags.insert(UsedAbiTags.begin(), UsedAbiTags.end()); + Parent->EmittedAbiTags.insert(EmittedAbiTags.begin(), + EmittedAbiTags.end()); + } + LinkHead = Parent; + } + + void write(raw_ostream &Out, const NamedDecl *ND, + const AbiTagList *AdditionalAbiTags) { + ND = cast(ND->getCanonicalDecl()); + + if (dyn_cast(ND) || dyn_cast(ND)) { + // assert(AdditionalAbiTags && "function and variables need a list of + // additional abi tags"); + } else { + assert( + !AdditionalAbiTags && + "only function and variables need a list of additional abi tags"); + if (const auto *NS = dyn_cast(ND)) { + if (const auto *AbiTag = NS->getAttr()) { + for (const auto &Tag : AbiTag->tags()) { + UsedAbiTags.insert(Tag); + } + } + // don't emit abi tags for namespaces + return; + } + } + + AbiTagList TagList; + if (const auto *AbiTag = ND->getAttr()) { + for (const auto &Tag : AbiTag->tags()) { + UsedAbiTags.insert(Tag); + // AbiTag->tags() is sorted and has no duplicates + TagList.push_back(Tag); + } + } + + if (AdditionalAbiTags) { + for (const auto &Tag : *AdditionalAbiTags) { + UsedAbiTags.insert(Tag); + if (std::find(TagList.begin(), TagList.end(), Tag) == TagList.end()) { + // don't insert duplicates + TagList.push_back(Tag); + } + } + // AbiTag->tags() are already sorted; only add if we had additional tags + std::sort(TagList.begin(), TagList.end()); + } + + writeSortedUniqueAbiTags(Out, TagList); + } + + const std::set &getUsedAbiTags() const { return UsedAbiTags; } + void setUsedAbiTags(const std::set &AbiTags) { + UsedAbiTags = AbiTags; + } + + const std::set &getEmittedAbiTags() const { + return EmittedAbiTags; + } + + private: + template + void writeSortedUniqueAbiTags(raw_ostream &Out, TagList const &AbiTags) { + for (const auto &Tag : AbiTags) { + EmittedAbiTags.insert(Tag); + Out << "B"; + Out << Tag.size(); + Out << Tag; + } + } + }; + + AbiTagState *AbiTags = nullptr; + AbiTagState AbiTagsRoot{ AbiTags }; + llvm::DenseMap Substitutions; ASTContext &getASTContext() const { return Context.getASTContext(); } public: CXXNameMangler(ItaniumMangleContextImpl &C, raw_ostream &Out_, - const NamedDecl *D = nullptr) - : Context(C), Out(Out_), Structor(getStructor(D)), StructorType(0), - SeqID(0) { + const NamedDecl *D = nullptr, bool NullOut_ = false) + : Context(C), Out(Out_), NullOut(NullOut_), Structor(getStructor(D)), + StructorType(0), SeqID(0) { // These can't be mangled without a ctor type or dtor type. assert(!D || (!isa(D) && !isa(D))); @@ -285,6 +448,11 @@ : Context(C), Out(Out_), Structor(getStructor(D)), StructorType(Type), SeqID(0) { } + CXXNameMangler(CXXNameMangler &Outer, llvm::raw_null_ostream &Out_) + : Context(Outer.Context), Out(Out_), NullOut(true), + Structor(Outer.Structor), StructorType(Outer.StructorType), + SeqID(Outer.SeqID) {} + #if MANGLE_CHECKER ~CXXNameMangler() { if (Out.str()[0] == '\01') @@ -298,14 +466,18 @@ #endif raw_ostream &getStream() { return Out; } + void disableDerivedAbiTags() { DisableDerivedAbiTags = true; } + static bool shouldHaveAbiTags(ItaniumMangleContextImpl &C, const VarDecl *VD); + void mangle(const NamedDecl *D); void mangleCallOffset(int64_t NonVirtual, int64_t Virtual); void mangleNumber(const llvm::APSInt &I); void mangleNumber(int64_t Number); void mangleFloat(const llvm::APFloat &F); - void mangleFunctionEncoding(const FunctionDecl *FD); + void mangleFunctionEncoding(const FunctionDecl *FD, + bool ExcludeUnqualifiedName = false); void mangleSeqID(unsigned SeqID); - void mangleName(const NamedDecl *ND); + void mangleName(const NamedDecl *ND, bool ExcludeUnqualifiedName = false); void mangleType(QualType T); void mangleNameOrStandardSubstitution(const NamedDecl *ND); @@ -336,31 +508,53 @@ DeclarationName name, unsigned KnownArity = UnknownArity); - void mangleName(const TemplateDecl *TD, - const TemplateArgument *TemplateArgs, - unsigned NumTemplateArgs); - void mangleUnqualifiedName(const NamedDecl *ND) { - mangleUnqualifiedName(ND, ND->getDeclName(), UnknownArity); + void mangleFunctionEncodingBareType(const FunctionDecl *FD); + + void mangleNameWithAbiTags(const NamedDecl *ND, + const AbiTagList *AdditionalAbiTags, + bool ExcludeUnqualifiedName); + void mangleTemplateName(const TemplateDecl *TD, + const AbiTagList *AdditionalAbiTags, + bool ExcludeUnqualifiedName, + const TemplateArgument *TemplateArgs, + unsigned NumTemplateArgs); + void mangleUnqualifiedName(const NamedDecl *ND, + const AbiTagList *AdditionalAbiTags) { + mangleUnqualifiedName(ND, ND->getDeclName(), UnknownArity, + AdditionalAbiTags); } void mangleUnqualifiedName(const NamedDecl *ND, DeclarationName Name, - unsigned KnownArity); - void mangleUnscopedName(const NamedDecl *ND); - void mangleUnscopedTemplateName(const TemplateDecl *ND); - void mangleUnscopedTemplateName(TemplateName); + unsigned KnownArity, + const AbiTagList *AdditionalAbiTags); + void mangleUnscopedName(const NamedDecl *ND, + const AbiTagList *AdditionalAbiTags); + void mangleUnscopedTemplateName(const TemplateDecl *ND, + const AbiTagList *AdditionalAbiTags); + void mangleUnscopedTemplateName(TemplateName, + const AbiTagList *AdditionalAbiTags); void mangleSourceName(const IdentifierInfo *II); - void mangleLocalName(const Decl *D); + void mangleLocalName(const Decl *D, + const AbiTagList *AdditionalAbiTags, + bool ExcludeUnqualifiedName); void mangleBlockForPrefix(const BlockDecl *Block); void mangleUnqualifiedBlock(const BlockDecl *Block); void mangleLambda(const CXXRecordDecl *Lambda); void mangleNestedName(const NamedDecl *ND, const DeclContext *DC, - bool NoFunction=false); + const AbiTagList *AdditionalAbiTags, + bool NoFunction, + bool ExcludeUnqualifiedName); void mangleNestedName(const TemplateDecl *TD, + const AbiTagList *AdditionalAbiTags, + bool ExcludeUnqualifiedName, const TemplateArgument *TemplateArgs, unsigned NumTemplateArgs); void manglePrefix(NestedNameSpecifier *qualifier); void manglePrefix(const DeclContext *DC, bool NoFunction=false); void manglePrefix(QualType type); - void mangleTemplatePrefix(const TemplateDecl *ND, bool NoFunction=false); + void mangleTemplatePrefix(const TemplateDecl *ND, + const AbiTagList *AdditionalAbiTags, + bool NoFunction = false, + bool ExcludeUnqualifiedName = false); void mangleTemplatePrefix(TemplateName Template); bool mangleUnresolvedTypeOrSimpleId(QualType DestroyedType, StringRef Prefix = ""); @@ -411,6 +605,15 @@ void mangleTemplateParameter(unsigned Index); void mangleFunctionParam(const ParmVarDecl *parm); + + void writeAbiTags(const NamedDecl *ND, + const AbiTagList *AdditionalAbiTags = nullptr); + + std::set + getTagsFromPrefixAndTemplateArguments(const NamedDecl *ND); + + AbiTagList makeAdditionalTagsForFunction(const FunctionDecl *FD); + AbiTagList makeAdditionalTagsForVariable(const VarDecl *VD); }; } @@ -454,6 +657,7 @@ while (!DC->isNamespace() && !DC->isTranslationUnit()) DC = getEffectiveParentContext(DC); if (DC->isTranslationUnit() && D->getFormalLinkage() != InternalLinkage && + !CXXNameMangler::shouldHaveAbiTags(*this, VD) && !isa(D)) return false; } @@ -461,6 +665,14 @@ return true; } +void CXXNameMangler::writeAbiTags(const NamedDecl *ND, + const AbiTagList *AdditionalAbiTags) { + assert(AbiTags && "require AbiTagState"); + if (AbiTags) + AbiTags->write(Out, ND, + DisableDerivedAbiTags ? nullptr : AdditionalAbiTags); +} + void CXXNameMangler::mangle(const NamedDecl *D) { // ::= _Z // ::= @@ -476,14 +688,31 @@ mangleName(cast(D)); } -void CXXNameMangler::mangleFunctionEncoding(const FunctionDecl *FD) { - // ::= - mangleName(FD); - +void CXXNameMangler::mangleFunctionEncoding(const FunctionDecl *FD, + bool ExcludeUnqualifiedName) { // Don't mangle in the type if this isn't a decl we should typically mangle. - if (!Context.shouldMangleDeclName(FD)) + if (!Context.shouldMangleDeclName(FD)) { + mangleNameWithAbiTags(FD, /* AdditionalAbiTags */ nullptr, + ExcludeUnqualifiedName); return; + } + + // ::= + if (ExcludeUnqualifiedName) { + // running makeAdditionalTagsForFunction would loop, don't need it here + // anyway + mangleNameWithAbiTags(FD, /* AdditionalAbiTags */ nullptr, + ExcludeUnqualifiedName); + } else { + AbiTagList AdditionalAbiTags = makeAdditionalTagsForFunction(FD); + mangleNameWithAbiTags(FD, &AdditionalAbiTags, ExcludeUnqualifiedName); + } + + mangleFunctionEncodingBareType(FD); +} + +void CXXNameMangler::mangleFunctionEncodingBareType(const FunctionDecl *FD) { if (FD->hasAttr()) { FunctionTypeDepthState Saved = FunctionTypeDepth.push(); Out << "Ua9enable_ifI"; @@ -587,7 +816,24 @@ return nullptr; } -void CXXNameMangler::mangleName(const NamedDecl *ND) { +// Must not be run from mangleLocalName for the as it would loop +// otherwise. +void CXXNameMangler::mangleName(const NamedDecl *ND, + bool ExcludeUnqualifiedName) { + if (!ExcludeUnqualifiedName) { + if (const VarDecl *VD = dyn_cast(ND)) { + AbiTagList VariableAdditionalAbiTags = makeAdditionalTagsForVariable(VD); + mangleNameWithAbiTags(VD, &VariableAdditionalAbiTags, + ExcludeUnqualifiedName); + return; + } + } + mangleNameWithAbiTags(ND, nullptr, ExcludeUnqualifiedName); +} + +void CXXNameMangler::mangleNameWithAbiTags(const NamedDecl *ND, + const AbiTagList *AdditionalAbiTags, + bool ExcludeUnqualifiedName) { // ::= // ::= // ::= @@ -603,7 +849,7 @@ while (!DC->isNamespace() && !DC->isTranslationUnit()) DC = getEffectiveParentContext(DC); else if (GetLocalClassDecl(ND)) { - mangleLocalName(ND); + mangleLocalName(ND, AdditionalAbiTags, ExcludeUnqualifiedName); return; } @@ -613,76 +859,93 @@ // Check if we have a template. const TemplateArgumentList *TemplateArgs = nullptr; if (const TemplateDecl *TD = isTemplate(ND, TemplateArgs)) { - mangleUnscopedTemplateName(TD); + if (!ExcludeUnqualifiedName) + mangleUnscopedTemplateName(TD, AdditionalAbiTags); mangleTemplateArgs(*TemplateArgs); return; } - mangleUnscopedName(ND); + if (!ExcludeUnqualifiedName) + mangleUnscopedName(ND, AdditionalAbiTags); return; } if (isLocalContainerContext(DC)) { - mangleLocalName(ND); + mangleLocalName(ND, AdditionalAbiTags, ExcludeUnqualifiedName); return; } - mangleNestedName(ND, DC); + mangleNestedName(ND, DC, AdditionalAbiTags, /* NoFunction */ false, + ExcludeUnqualifiedName); } -void CXXNameMangler::mangleName(const TemplateDecl *TD, - const TemplateArgument *TemplateArgs, - unsigned NumTemplateArgs) { + +void CXXNameMangler::mangleTemplateName(const TemplateDecl *TD, + const AbiTagList *AdditionalAbiTags, + bool ExcludeUnqualifiedName, + const TemplateArgument *TemplateArgs, + unsigned NumTemplateArgs) { const DeclContext *DC = IgnoreLinkageSpecDecls(getEffectiveDeclContext(TD)); if (DC->isTranslationUnit() || isStdNamespace(DC)) { - mangleUnscopedTemplateName(TD); + if (!ExcludeUnqualifiedName) + mangleUnscopedTemplateName(TD, AdditionalAbiTags); mangleTemplateArgs(TemplateArgs, NumTemplateArgs); } else { - mangleNestedName(TD, TemplateArgs, NumTemplateArgs); + mangleNestedName(TD, AdditionalAbiTags, ExcludeUnqualifiedName, + TemplateArgs, NumTemplateArgs); } } -void CXXNameMangler::mangleUnscopedName(const NamedDecl *ND) { +void CXXNameMangler::mangleUnscopedName(const NamedDecl *ND, + const AbiTagList *AdditionalAbiTags) { // ::= // ::= St # ::std:: if (isStdNamespace(IgnoreLinkageSpecDecls(getEffectiveDeclContext(ND)))) Out << "St"; - mangleUnqualifiedName(ND); + mangleUnqualifiedName(ND, AdditionalAbiTags); } -void CXXNameMangler::mangleUnscopedTemplateName(const TemplateDecl *ND) { +void CXXNameMangler::mangleUnscopedTemplateName( + const TemplateDecl *ND, const AbiTagList *AdditionalAbiTags) { // ::= // ::= if (mangleSubstitution(ND)) return; // ::= - if (const auto *TTP = dyn_cast(ND)) + if (const auto *TTP = dyn_cast(ND)) { + assert(!AdditionalAbiTags && + "template template param cannot have abi tags"); mangleTemplateParameter(TTP->getIndex()); - else - mangleUnscopedName(ND->getTemplatedDecl()); + } else { + mangleUnscopedName(ND->getTemplatedDecl(), AdditionalAbiTags); + } addSubstitution(ND); } -void CXXNameMangler::mangleUnscopedTemplateName(TemplateName Template) { +void CXXNameMangler::mangleUnscopedTemplateName( + TemplateName Template, const AbiTagList *AdditionalAbiTags) { // ::= // ::= if (TemplateDecl *TD = Template.getAsTemplateDecl()) - return mangleUnscopedTemplateName(TD); + return mangleUnscopedTemplateName(TD, AdditionalAbiTags); if (mangleSubstitution(Template)) return; + assert(!AdditionalAbiTags && + "dependent template name cannot have abi tags"); + DependentTemplateName *Dependent = Template.getAsDependentTemplateName(); assert(Dependent && "Not a dependent template name?"); if (const IdentifierInfo *Id = Dependent->getIdentifier()) mangleSourceName(Id); else mangleOperatorName(Dependent->getOperator(), UnknownArity); - + addSubstitution(Template); } @@ -841,6 +1104,7 @@ else Out << "sr"; mangleSourceName(qualifier->getAsNamespace()->getIdentifier()); + writeAbiTags(qualifier->getAsNamespace()); break; case NestedNameSpecifier::NamespaceAlias: if (qualifier->getPrefix()) @@ -849,6 +1113,7 @@ else Out << "sr"; mangleSourceName(qualifier->getAsNamespaceAlias()->getIdentifier()); + writeAbiTags(qualifier->getAsNamespaceAlias()); break; case NestedNameSpecifier::TypeSpec: @@ -883,6 +1148,7 @@ Out << "sr"; mangleSourceName(qualifier->getAsIdentifier()); + // an Identifier has no type information, so we can't emit abi tags for it break; } @@ -928,7 +1194,8 @@ void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND, DeclarationName Name, - unsigned KnownArity) { + unsigned KnownArity, + const AbiTagList *AdditionalAbiTags) { unsigned Arity = KnownArity; // ::= // ::= @@ -947,6 +1214,7 @@ Out << 'L'; mangleSourceName(II); + writeAbiTags(ND, AdditionalAbiTags); break; } @@ -986,6 +1254,7 @@ assert(FD->getIdentifier() && "Data member name isn't an identifier!"); mangleSourceName(FD->getIdentifier()); + // Not emitting abi tags: internal name anyway break; } @@ -1006,6 +1275,10 @@ assert(D->getDeclName().getAsIdentifierInfo() && "Typedef was not named!"); mangleSourceName(D->getDeclName().getAsIdentifierInfo()); + assert(!AdditionalAbiTags && "Type cannot have additional abi tags"); + // explicit abi tags are still possible; take from underlying type, not + // from typedef. + writeAbiTags(TD, nullptr); break; } @@ -1015,6 +1288,8 @@ // ::= + # Parameter types or 'v' for 'void'. if (const CXXRecordDecl *Record = dyn_cast(TD)) { if (Record->isLambda() && Record->getLambdaManglingNumber()) { + assert(!AdditionalAbiTags && + "Lambda type cannot have additional abi tags"); mangleLambda(Record); break; } @@ -1026,11 +1301,13 @@ if (UnnamedMangle > 1) Out << UnnamedMangle - 2; Out << '_'; + writeAbiTags(TD, AdditionalAbiTags); break; } - // Get a unique id for the anonymous struct. - unsigned AnonStructId = Context.getAnonymousStructId(TD); + // Get a unique id for the anonymous struct. If it is not a real output + // ID doesn't matter so use fake one. + unsigned AnonStructId = NullOut ? 0 : Context.getAnonymousStructId(TD); // Mangle it as a source name in the form // [n] $_ @@ -1058,6 +1335,7 @@ // Otherwise, use the complete constructor name. This is relevant if a // class with a constructor is declared within a constructor. mangleCXXCtorType(Ctor_Complete); + writeAbiTags(ND, AdditionalAbiTags); break; case DeclarationName::CXXDestructorName: @@ -1069,6 +1347,7 @@ // Otherwise, use the complete destructor name. This is relevant if a // class with a destructor is declared within a destructor. mangleCXXDtorType(Dtor_Complete); + writeAbiTags(ND, AdditionalAbiTags); break; case DeclarationName::CXXOperatorName: @@ -1084,6 +1363,7 @@ case DeclarationName::CXXConversionFunctionName: case DeclarationName::CXXLiteralOperatorName: mangleOperatorName(Name, Arity); + writeAbiTags(ND, AdditionalAbiTags); break; case DeclarationName::CXXUsingDirective: @@ -1100,7 +1380,9 @@ void CXXNameMangler::mangleNestedName(const NamedDecl *ND, const DeclContext *DC, - bool NoFunction) { + const AbiTagList *AdditionalAbiTags, + bool NoFunction, + bool ExcludeUnqualifiedName) { // // ::= N [] [] E // ::= N [] [] @@ -1120,30 +1402,36 @@ // Check if we have a template. const TemplateArgumentList *TemplateArgs = nullptr; if (const TemplateDecl *TD = isTemplate(ND, TemplateArgs)) { - mangleTemplatePrefix(TD, NoFunction); + mangleTemplatePrefix(TD, AdditionalAbiTags, NoFunction, + ExcludeUnqualifiedName); mangleTemplateArgs(*TemplateArgs); } else { manglePrefix(DC, NoFunction); - mangleUnqualifiedName(ND); + if (!ExcludeUnqualifiedName) + mangleUnqualifiedName(ND, AdditionalAbiTags); } Out << 'E'; } void CXXNameMangler::mangleNestedName(const TemplateDecl *TD, + const AbiTagList *AdditionalAbiTags, + bool ExcludeUnqualifiedName, const TemplateArgument *TemplateArgs, unsigned NumTemplateArgs) { // ::= N [] E Out << 'N'; - mangleTemplatePrefix(TD); + mangleTemplatePrefix(TD, AdditionalAbiTags, ExcludeUnqualifiedName); mangleTemplateArgs(TemplateArgs, NumTemplateArgs); Out << 'E'; } -void CXXNameMangler::mangleLocalName(const Decl *D) { +void CXXNameMangler::mangleLocalName(const Decl *D, + const AbiTagList *AdditionalAbiTags, + bool ExcludeUnqualifiedName) { // := Z E [] // := Z E s [] // := Z E d [ ] @@ -1155,15 +1443,26 @@ Out << 'Z'; - if (const ObjCMethodDecl *MD = dyn_cast(DC)) - mangleObjCMethodName(MD); - else if (const BlockDecl *BD = dyn_cast(DC)) - mangleBlockForPrefix(BD); - else - mangleFunctionEncoding(cast(DC)); + { + AbiTagState localAbiTags(AbiTags); + + if (const ObjCMethodDecl *MD = dyn_cast(DC)) + mangleObjCMethodName(MD); + else if (const BlockDecl *BD = dyn_cast(DC)) + mangleBlockForPrefix(BD); + else + mangleFunctionEncoding(cast(DC)); + + // Implicit ABI tags (from namespace) are not available in the following + // entity; reset to actually emitted tags, which are available. + localAbiTags.setUsedAbiTags(localAbiTags.getEmittedAbiTags()); + } Out << 'E'; + // GCC 5.3.0 doesn't emit derived abi tags for but that seems to be a bug + // that is fixed in trunk. + if (RD) { // The parameter number is omitted for the last parameter, 0 for the // second-to-last parameter, 1 for the third-to-last parameter, etc. The @@ -1188,13 +1487,17 @@ // Mangle the name relative to the closest enclosing function. // equality ok because RD derived from ND above if (D == RD) { - mangleUnqualifiedName(RD); + if (!ExcludeUnqualifiedName) + mangleUnqualifiedName(RD, AdditionalAbiTags); } else if (const BlockDecl *BD = dyn_cast(D)) { manglePrefix(getEffectiveDeclContext(BD), true /*NoFunction*/); - mangleUnqualifiedBlock(BD); + assert(!AdditionalAbiTags && "Block cannot have additional abi tags"); + if (!ExcludeUnqualifiedName) + mangleUnqualifiedBlock(BD); } else { const NamedDecl *ND = cast(D); - mangleNestedName(ND, getEffectiveDeclContext(ND), true /*NoFunction*/); + mangleNestedName(ND, getEffectiveDeclContext(ND), AdditionalAbiTags, + true /*NoFunction*/, ExcludeUnqualifiedName); } } else if (const BlockDecl *BD = dyn_cast(D)) { // Mangle a block in a default parameter; see above explanation for @@ -1211,30 +1514,37 @@ } } - mangleUnqualifiedBlock(BD); + assert(!AdditionalAbiTags && "Block cannot have additional abi tags"); + if (!ExcludeUnqualifiedName) + mangleUnqualifiedBlock(BD); } else { - mangleUnqualifiedName(cast(D)); - } - - if (const NamedDecl *ND = dyn_cast(RD ? RD : D)) { - unsigned disc; - if (Context.getNextDiscriminator(ND, disc)) { - if (disc < 10) - Out << '_' << disc; - else - Out << "__" << disc << '_'; + if (!ExcludeUnqualifiedName) + mangleUnqualifiedName(cast(D), AdditionalAbiTags); + } + + if (!ExcludeUnqualifiedName) { + if (const NamedDecl *ND = dyn_cast(RD ? RD : D)) { + unsigned disc; + if (Context.getNextDiscriminator(ND, disc)) { + if (disc < 10) + Out << '_' << disc; + else + Out << "__" << disc << '_'; + } } } } void CXXNameMangler::mangleBlockForPrefix(const BlockDecl *Block) { if (GetLocalClassDecl(Block)) { - mangleLocalName(Block); + mangleLocalName(Block, /* AdditionalAbiTags */ nullptr, + /* ExcludeUnqualifiedName */ false); return; } const DeclContext *DC = getEffectiveDeclContext(Block); if (isLocalContainerContext(DC)) { - mangleLocalName(Block); + mangleLocalName(Block, /* AdditionalAbiTags */ nullptr, + /* ExcludeUnqualifiedName */ false); return; } manglePrefix(getEffectiveDeclContext(Block)); @@ -1245,10 +1555,11 @@ if (Decl *Context = Block->getBlockManglingContextDecl()) { if ((isa(Context) || isa(Context)) && Context->getDeclContext()->isRecord()) { - if (const IdentifierInfo *Name - = cast(Context)->getIdentifier()) { + const auto *ND = cast(Context); + if (const IdentifierInfo *Name = ND->getIdentifier()) { mangleSourceName(Name); - Out << 'M'; + writeAbiTags(ND, /* AdditionalAbiTags */ nullptr); + Out << 'M'; } } } @@ -1281,7 +1592,7 @@ if (const IdentifierInfo *Name = cast(Context)->getIdentifier()) { mangleSourceName(Name); - Out << 'M'; + Out << 'M'; } } } @@ -1364,11 +1675,11 @@ // Check if we have a template. const TemplateArgumentList *TemplateArgs = nullptr; if (const TemplateDecl *TD = isTemplate(ND, TemplateArgs)) { - mangleTemplatePrefix(TD); + mangleTemplatePrefix(TD, /* AdditionalAbiTags */ nullptr); mangleTemplateArgs(*TemplateArgs); } else { manglePrefix(getEffectiveDeclContext(ND), NoFunction); - mangleUnqualifiedName(ND); + mangleUnqualifiedName(ND, /* AdditionalAbiTags */ nullptr); } addSubstitution(ND); @@ -1379,27 +1690,30 @@ // ::= // ::= if (TemplateDecl *TD = Template.getAsTemplateDecl()) - return mangleTemplatePrefix(TD); + return mangleTemplatePrefix(TD, /* AdditionalAbiTags */ nullptr); if (QualifiedTemplateName *Qualified = Template.getAsQualifiedTemplateName()) manglePrefix(Qualified->getQualifier()); - + if (OverloadedTemplateStorage *Overloaded = Template.getAsOverloadedTemplate()) { mangleUnqualifiedName(nullptr, (*Overloaded->begin())->getDeclName(), - UnknownArity); + UnknownArity, + /* AdditionalAbiTags */ nullptr); return; } - + DependentTemplateName *Dependent = Template.getAsDependentTemplateName(); assert(Dependent && "Unknown template name kind?"); if (NestedNameSpecifier *Qualifier = Dependent->getQualifier()) manglePrefix(Qualifier); - mangleUnscopedTemplateName(Template); + mangleUnscopedTemplateName(Template, /* AdditionalAbiTags */ nullptr); } void CXXNameMangler::mangleTemplatePrefix(const TemplateDecl *ND, - bool NoFunction) { + const AbiTagList *AdditionalAbiTags, + bool NoFunction, + bool ExcludeUnqualifiedName) { // ::=