From d7c20ff3406ee048dd5d0ff812f9e8b3d48bb192 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20B=C3=BChler?= Date: Thu, 3 Dec 2015 14:51:50 +0100 Subject: [PATCH 1/3] add gcc abi_tag support --- docs/ItaniumMangleAbiTags.rst | 90 +++++ include/clang/Basic/Attr.td | 8 + include/clang/Basic/DiagnosticSemaKinds.td | 10 +- include/clang/Sema/AttributeList.h | 3 +- lib/AST/ItaniumMangle.cpp | 525 ++++++++++++++++++++++++----- lib/Sema/SemaDeclAttr.cpp | 55 +++ 6 files changed, 609 insertions(+), 82 deletions(-) create mode 100644 docs/ItaniumMangleAbiTags.rst diff --git a/docs/ItaniumMangleAbiTags.rst b/docs/ItaniumMangleAbiTags.rst new file mode 100644 index 0000000..d390162 --- /dev/null +++ b/tools/clang/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. diff --git a/include/clang/Basic/Attr.td b/include/clang/Basic/Attr.td index 6187bcb..c54ab34 100644 --- a/tools/clang/include/clang/Basic/Attr.td +++ b/tools/clang/include/clang/Basic/Attr.td @@ -338,6 +338,14 @@ class IgnoredAttr : Attr { // 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">]; diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 82f5121..973456e 100644 --- a/tools/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/tools/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -2323,7 +2323,8 @@ def warn_attribute_wrong_decl_type : Warning< "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< @@ -3997,6 +3998,13 @@ def err_definition_of_explicitly_defaulted_member : Error< 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_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'">; diff --git a/include/clang/Sema/AttributeList.h b/include/clang/Sema/AttributeList.h index 4d18633..b3a9333 100644 --- a/tools/clang/include/clang/Sema/AttributeList.h +++ b/tools/clang/include/clang/Sema/AttributeList.h @@ -854,7 +854,8 @@ enum AttributeDeclKind { ExpectedStructOrUnionOrTypedef, ExpectedStructOrTypedef, ExpectedObjectiveCInterfaceOrProtocol, - ExpectedKernelFunction + ExpectedKernelFunction, + ExpectedStructClassVariableFunctionMethodOrInlineNamespace }; } // end namespace clang diff --git a/lib/AST/ItaniumMangle.cpp b/lib/AST/ItaniumMangle.cpp index dac803e..e32b659 100644 --- a/tools/clang/lib/AST/ItaniumMangle.cpp +++ b/tools/clang/lib/AST/ItaniumMangle.cpp @@ -214,6 +214,8 @@ public: 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,6 +265,167 @@ class CXXNameMangler { } 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(); } @@ -285,6 +448,10 @@ public: : 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,18 +465,21 @@ public: #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); @@ -336,31 +506,49 @@ private: 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 = ""); @@ -406,6 +594,10 @@ private: 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); }; } @@ -456,6 +648,11 @@ bool ItaniumMangleContextImpl::shouldMangleCXXName(const NamedDecl *D) { 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 // ::= @@ -471,14 +668,28 @@ void CXXNameMangler::mangle(const NamedDecl *D) { 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"; @@ -524,7 +735,7 @@ void CXXNameMangler::mangleFunctionEncoding(const FunctionDecl *FD) { FD = PrimaryTemplate->getTemplatedDecl(); } - mangleBareFunctionType(FD->getType()->getAs(), + mangleBareFunctionType(FD->getType()->getAs(), MangleReturnType); } @@ -582,7 +793,21 @@ isTemplate(const NamedDecl *ND, const TemplateArgumentList *&TemplateArgs) { 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) { // ::= // ::= // ::= @@ -598,7 +823,7 @@ void CXXNameMangler::mangleName(const NamedDecl *ND) { while (!DC->isNamespace() && !DC->isTranslationUnit()) DC = getEffectiveParentContext(DC); else if (GetLocalClassDecl(ND)) { - mangleLocalName(ND); + mangleLocalName(ND, AdditionalAbiTags, ExcludeUnqualifiedName); return; } @@ -608,76 +833,88 @@ void CXXNameMangler::mangleName(const NamedDecl *ND) { // 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); } @@ -837,6 +1074,7 @@ void CXXNameMangler::mangleUnresolvedPrefix(NestedNameSpecifier *qualifier, else Out << "sr"; mangleSourceName(qualifier->getAsNamespace()->getIdentifier()); + writeAbiTags(qualifier->getAsNamespace()); break; case NestedNameSpecifier::NamespaceAlias: if (qualifier->getPrefix()) @@ -845,6 +1083,7 @@ void CXXNameMangler::mangleUnresolvedPrefix(NestedNameSpecifier *qualifier, else Out << "sr"; mangleSourceName(qualifier->getAsNamespaceAlias()->getIdentifier()); + writeAbiTags(qualifier->getAsNamespaceAlias()); break; case NestedNameSpecifier::TypeSpec: @@ -879,6 +1118,7 @@ void CXXNameMangler::mangleUnresolvedPrefix(NestedNameSpecifier *qualifier, Out << "sr"; mangleSourceName(qualifier->getAsIdentifier()); + writeAbiTags(qualifier->getAsNamespaceAlias()); break; } @@ -924,7 +1164,8 @@ void CXXNameMangler::mangleUnresolvedName(NestedNameSpecifier *qualifier, void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND, DeclarationName Name, - unsigned KnownArity) { + unsigned KnownArity, + const AbiTagList *AdditionalAbiTags) { unsigned Arity = KnownArity; // ::= // ::= @@ -943,6 +1184,7 @@ void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND, Out << 'L'; mangleSourceName(II); + writeAbiTags(ND, AdditionalAbiTags); break; } @@ -982,6 +1224,7 @@ void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND, assert(FD->getIdentifier() && "Data member name isn't an identifier!"); mangleSourceName(FD->getIdentifier()); + // TODO(abitags): not emitting abi tags: internal name anyway break; } @@ -1002,6 +1245,9 @@ void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND, 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; } @@ -1011,6 +1257,7 @@ void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND, // ::= + # 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; } @@ -1022,6 +1269,7 @@ void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND, if (UnnamedMangle > 1) Out << llvm::utostr(UnnamedMangle - 2); Out << '_'; + writeAbiTags(TD, AdditionalAbiTags); break; } @@ -1054,6 +1302,7 @@ void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND, // 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: @@ -1065,6 +1314,7 @@ void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND, // 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: @@ -1080,6 +1330,7 @@ void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND, case DeclarationName::CXXConversionFunctionName: case DeclarationName::CXXLiteralOperatorName: mangleOperatorName(Name, Arity); + writeAbiTags(ND, AdditionalAbiTags); break; case DeclarationName::CXXUsingDirective: @@ -1096,7 +1347,9 @@ void CXXNameMangler::mangleSourceName(const IdentifierInfo *II) { void CXXNameMangler::mangleNestedName(const NamedDecl *ND, const DeclContext *DC, - bool NoFunction) { + const AbiTagList *AdditionalAbiTags, + bool NoFunction, + bool ExcludeUnqualifiedName) { // // ::= N [] [] E // ::= N [] [] @@ -1116,30 +1369,35 @@ void CXXNameMangler::mangleNestedName(const NamedDecl *ND, // 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 [ ] @@ -1151,15 +1409,25 @@ void CXXNameMangler::mangleLocalName(const Decl *D) { 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 @@ -1184,13 +1452,17 @@ void CXXNameMangler::mangleLocalName(const Decl *D) { // 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 @@ -1207,30 +1479,35 @@ void CXXNameMangler::mangleLocalName(const Decl *D) { } } - 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)); @@ -1241,10 +1518,11 @@ void CXXNameMangler::mangleUnqualifiedBlock(const BlockDecl *Block) { 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'; } } } @@ -1277,7 +1555,7 @@ void CXXNameMangler::mangleLambda(const CXXRecordDecl *Lambda) { if (const IdentifierInfo *Name = cast(Context)->getIdentifier()) { mangleSourceName(Name); - Out << 'M'; + Out << 'M'; } } } @@ -1359,11 +1637,11 @@ void CXXNameMangler::manglePrefix(const DeclContext *DC, bool NoFunction) { // 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); @@ -1374,27 +1652,30 @@ void CXXNameMangler::mangleTemplatePrefix(TemplateName Template) { // ::= // ::= 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) { // ::=