Index: docs/ItaniumMangleAbiTags.rst =================================================================== --- /dev/null +++ docs/ItaniumMangleAbiTags.rst @@ -0,0 +1,90 @@ +======== +Abi Tags +======== + +Introduction +============ + +This text tries to describe gcc semantic for mangling "abi_tag" attributes +described in https://gcc.gnu.org/onlinedocs/gcc/C_002b_002b-Attributes.html + +There is no guarantee the following rules are correct, complete or make sense +in any way as they were determined empirically by experiments with gcc5. + +Declaration +=========== + +Abi tags are declared in an abi_tag attribute and can be applied to a +function, variable, class or inline namespace declaration. The attribute takes +one or more strings (called tags); the order does not matter. + +See https://gcc.gnu.org/onlinedocs/gcc/C_002b_002b-Attributes.html for +details. + +Tags on an inline namespace are called "implicit tags", all other tags are +"explicit tags". + +Mangling +======== + +All tags that are "active" on a are emitted after the +, before or , and are part of +the same the is. + +They are mangled as: + + ::= * # sort by name + ::= B + +Example: + + __attribute__((abi_tag("test"))) + void Func(); + + gets mangled as: _Z4FuncB4testv (prettified as `Func[abi:test]()`) + +Active tags +=========== + +A namespace has never any active tags; for types (class / struct / union / +enum) the explicit tags are the active tags. + +For variables and functions the active tags are the explicit tags plus any +"required tags" which are not in the "available tags" set: + + derived-tags := (required-tags - available-tags) + active-tags := explicit-tags + derived-tags + +Required tags for a function +============================ + +If a function is used as a local scope for another name, and is part of +another function as local scope, it doesn't have any required tags. + +If a function is used as a local scope for a guard variable name, it doesn't +have any required tags. + +Otherwise the function requires any implicit or explicit tag used in the name +for the return type. + +Required tags for a variable +============================ + +A variable requires any implicit or explicit tag used in its type. + +Available tags +============== + +All tags used in the prefix and in the template arguments for a name are +available; for functions also all tags from the (which +might include the return type for template functions) are available. + +For s all active tags used in the local part () are available, but not implicit tags which were not active! + +Implicit and explicit tags used in the for a function (as +in the type of a cast operator) are NOT available. + +Example: a cast operator to std::string (which is +std::__cxx11::basic_string<...>) will use 'cxx11' as active tag, as it is +required from the return type `std::string` but not available. Index: include/clang/Basic/Attr.td =================================================================== --- include/clang/Basic/Attr.td +++ include/clang/Basic/Attr.td @@ -349,6 +349,14 @@ // Attributes begin here // +def AbiTag : Attr { + let Spellings = [GCC<"abi_tag">]; + let Args = [VariadicStringArgument<"Tags">]; + let Subjects = SubjectList<[Struct, Var, Function, Namespace], ErrorDiag, + "ExpectedStructClassVariableFunctionMethodOrInlineNamespace">; + let Documentation = [Undocumented]; +} + def AddressSpace : TypeAttr { let Spellings = [GNU<"address_space">]; let Args = [IntArgument<"AddressSpace">]; Index: include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- include/clang/Basic/DiagnosticSemaKinds.td +++ include/clang/Basic/DiagnosticSemaKinds.td @@ -2434,7 +2434,8 @@ "Objective-C instance methods|init methods of interface or class extension declarations|" "variables, functions and classes|Objective-C protocols|" "functions and global variables|structs, unions, and typedefs|structs and typedefs|" - "interface or protocol declarations|kernel functions}1">, + "interface or protocol declarations|kernel functions|" + "structs, classes, variables, functions, methods and inline namespaces}1">, InGroup; def err_attribute_wrong_decl_type : Error; def warn_type_attribute_wrong_type : Warning< @@ -4144,6 +4145,15 @@ def err_redefinition_extern_inline : Error< "redefinition of a 'extern inline' function %0 is not supported in " "%select{C99 mode|C++}1">; +def err_attr_abi_tag_only_on_inline_namespace : + Error<"abi_tag attribute only allowed on inline namespaces">; +def err_attr_abi_tag_only_on_named_namespace : + Error<"abi_tag attribute only allowed on named namespaces">; +def err_abi_tag_on_redeclaration : + Error<"cannot add abi_tag attribute in redeclaration">; +def err_new_abi_tag_on_redeclaration : + Error<"abi_tag %0 missing in original declaration">; + def note_deleted_dtor_no_operator_delete : Note< "virtual destructor requires an unambiguous, accessible 'operator delete'">; Index: include/clang/Sema/AttributeList.h =================================================================== --- include/clang/Sema/AttributeList.h +++ include/clang/Sema/AttributeList.h @@ -855,7 +855,8 @@ ExpectedStructOrUnionOrTypedef, ExpectedStructOrTypedef, ExpectedObjectiveCInterfaceOrProtocol, - ExpectedKernelFunction + ExpectedKernelFunction, + ExpectedStructClassVariableFunctionMethodOrInlineNamespace }; } // end namespace clang Index: lib/AST/ItaniumMangle.cpp =================================================================== --- lib/AST/ItaniumMangle.cpp +++ lib/AST/ItaniumMangle.cpp @@ -31,6 +31,7 @@ #include "llvm/ADT/StringExtras.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" +#include #define MANGLE_CHECKER 0 @@ -212,6 +212,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 @@ -261,6 +263,167 @@ } FunctionTypeDepth; + // abi_tag is a gcc attribute, taking one or more strings called "tags". + // + // the goal is to annotage 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. + // + // TODO(abitags): how to handle substituted names? they should add the tags used in + // the substitution to the list of available tags. + class AbiTagState final { + public: + //! 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}; + + 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); + } + + protected: + template + void writeSortedUniqueAbiTags(raw_ostream &Out, TagList const& AbiTags) { + for (const auto& Tag: AbiTags) { + EmittedAbiTags.insert(Tag); + Out << "B"; + Out << Tag.size(); + Out << Tag; + } + } + } *AbiTags = nullptr; + AbiTagState AbiTagsRoot{AbiTags}; + + struct TemporaryDisableDerivedAbiTags { + bool& StateRef; + bool OldState; + + TemporaryDisableDerivedAbiTags(bool& State, bool Disable = true) + : StateRef(State) { + OldState = StateRef; + StateRef = Disable; + } + TemporaryDisableDerivedAbiTags(TemporaryDisableDerivedAbiTags const&) = delete; + ~TemporaryDisableDerivedAbiTags() { + StateRef = OldState; + } + }; + llvm::DenseMap Substitutions; ASTContext &getASTContext() const { return Context.getASTContext(); } @@ -283,6 +446,10 @@ : 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') @@ -296,18 +463,21 @@ #endif raw_ostream &getStream() { return Out; } + void disableDerivedAbiTags() { DisableDerivedAbiTags = true; } + 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); private: + void writeAbiTags(const NamedDecl *ND, const AbiTagList *AdditionalAbiTags = nullptr); bool mangleSubstitution(const NamedDecl *ND); bool mangleSubstitution(QualType T); @@ -334,31 +504,49 @@ DeclarationName name, unsigned KnownArity = UnknownArity); - void mangleName(const TemplateDecl *TD, + 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) { - mangleUnqualifiedName(ND, ND->getDeclName(), UnknownArity); + 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 = ""); @@ -405,6 +593,10 @@ void mangleTemplateParameter(unsigned Index); void mangleFunctionParam(const ParmVarDecl *parm); + + std::set getTagsFromPrefixAndTemplateArguments(const NamedDecl *ND); + AbiTagList makeAdditionalTagsForFunction(const FunctionDecl *FD); + AbiTagList makeAdditionalTagsForVariable(const VarDecl *VD); }; } @@ -455,6 +647,11 @@ 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 // ::= @@ -470,14 +667,28 @@ 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"; @@ -581,7 +792,21 @@ 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) { // ::= // ::= // ::= @@ -597,7 +822,7 @@ while (!DC->isNamespace() && !DC->isTranslationUnit()) DC = getEffectiveParentContext(DC); else if (GetLocalClassDecl(ND)) { - mangleLocalName(ND); + mangleLocalName(ND, AdditionalAbiTags, ExcludeUnqualifiedName); return; } @@ -607,76 +832,88 @@ // 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"); // TODO(abitags) 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"); // TODO(abitags) + 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); } @@ -835,14 +1072,16 @@ else Out << "sr"; mangleSourceName(qualifier->getAsNamespace()->getIdentifier()); + writeAbiTags(qualifier->getAsNamespace()); break; case NestedNameSpecifier::NamespaceAlias: if (qualifier->getPrefix()) mangleUnresolvedPrefix(qualifier->getPrefix(), /*recursive*/ true); else Out << "sr"; mangleSourceName(qualifier->getAsNamespaceAlias()->getIdentifier()); + writeAbiTags(qualifier->getAsNamespaceAlias()); break; case NestedNameSpecifier::TypeSpec: @@ -877,6 +1116,7 @@ Out << "sr"; mangleSourceName(qualifier->getAsIdentifier()); + // an Identifier has no type information, so we can't emit abi tags for it break; } @@ -922,7 +1162,8 @@ void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND, DeclarationName Name, - unsigned KnownArity) { + unsigned KnownArity, + const AbiTagList *AdditionalAbiTags) { unsigned Arity = KnownArity; // ::= // ::= @@ -941,6 +1182,7 @@ Out << 'L'; mangleSourceName(II); + writeAbiTags(ND, AdditionalAbiTags); break; } @@ -980,6 +1222,7 @@ assert(FD->getIdentifier() && "Data member name isn't an identifier!"); mangleSourceName(FD->getIdentifier()); + // TODO(abitags): not emitting abi tags: internal name anyway break; } @@ -1000,6 +1243,9 @@ 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; } @@ -1009,6 +1255,7 @@ // ::= + # 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; } @@ -1020,6 +1267,7 @@ if (UnnamedMangle > 1) Out << UnnamedMangle - 2; Out << '_'; + writeAbiTags(TD, AdditionalAbiTags); break; } @@ -1052,6 +1300,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: @@ -1063,6 +1312,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: @@ -1078,6 +1328,7 @@ case DeclarationName::CXXConversionFunctionName: case DeclarationName::CXXLiteralOperatorName: mangleOperatorName(Name, Arity); + writeAbiTags(ND, AdditionalAbiTags); break; case DeclarationName::CXXUsingDirective: @@ -1094,7 +1345,9 @@ void CXXNameMangler::mangleNestedName(const NamedDecl *ND, const DeclContext *DC, - bool NoFunction) { + const AbiTagList *AdditionalAbiTags, + bool NoFunction, + bool ExcludeUnqualifiedName) { // // ::= N [] [] E // ::= N [] [] @@ -1114,30 +1367,35 @@ // 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 [ ] @@ -1149,15 +1407,25 @@ 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.UsedAbiTags = localAbiTags.EmittedAbiTags; + } Out << 'E'; + TemporaryDisableDerivedAbiTags TemporyDisable(DisableDerivedAbiTags, getStructor(dyn_cast(D)) != Structor); + 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 @@ -1182,13 +1450,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 @@ -1205,30 +1477,35 @@ } } - 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)); @@ -1239,10 +1516,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'; } } } @@ -1275,7 +1553,7 @@ if (const IdentifierInfo *Name = cast(Context)->getIdentifier()) { mangleSourceName(Name); - Out << 'M'; + Out << 'M'; } } } @@ -1358,11 +1636,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); @@ -1373,27 +1651,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) { // ::=