Go to:
Gentoo Home
Documentation
Forums
Lists
Bugs
Planet
Store
Wiki
Get Gentoo!
Gentoo's Bugzilla – Attachment 423550 Details for
Bug 571600
sys-devel/clang, sys-devel/llvm - ABI incompatibilty with libstdc++ from sys-devel/gcc-5* due to missing abi-tag support
Home
|
New
–
[Ex]
|
Browse
|
Search
|
Privacy Policy
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
patch that adds abi_tag support (experimental)
0001-Add-abi-tag-support-1.patch (text/plain), 44.14 KB, created by
Matthias Maier
on 2016-01-21 19:34:46 UTC
(
hide
)
Description:
patch that adds abi_tag support (experimental)
Filename:
MIME Type:
Creator:
Matthias Maier
Created:
2016-01-21 19:34:46 UTC
Size:
44.14 KB
patch
obsolete
>diff --git a/tools/clang/include/clang/Basic/Attr.td b/tools/clang/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/tools/clang/include/clang/Basic/DiagnosticSemaKinds.td b/tools/clang/include/clang/Basic/DiagnosticSemaKinds.td >index 82f5121..3acc5c4 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<IgnoredAttributes>; > def err_attribute_wrong_decl_type : Error<warn_attribute_wrong_decl_type.Text>; > def warn_type_attribute_wrong_type : Warning< >@@ -3997,6 +3998,15 @@ 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_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'">; >diff --git a/tools/clang/include/clang/Sema/AttributeList.h b/tools/clang/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/tools/clang/lib/AST/ItaniumMangle.cpp b/tools/clang/lib/AST/ItaniumMangle.cpp >index dac803e..8782015 100644 >--- a/tools/clang/lib/AST/ItaniumMangle.cpp >+++ b/tools/clang/lib/AST/ItaniumMangle.cpp >@@ -32,6 +32,8 @@ > #include "llvm/Support/ErrorHandling.h" > #include "llvm/Support/raw_ostream.h" > >+#include <set> >+ > #define MANGLE_CHECKER 0 > > #if MANGLE_CHECKER >@@ -214,6 +216,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 +267,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 <bare-function-type> (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 >+ // <abitag> ::= B <"tag" source-name> >+ >+ typedef SmallVector<StringRef, 4> 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<StringRef> UsedAbiTags; >+ //! all explicit abi tags (i.e. not from namespace) >+ std::set<StringRef> 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<NamedDecl>(ND->getCanonicalDecl()); >+ >+ if (dyn_cast<FunctionDecl>(ND) || dyn_cast<VarDecl>(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<NamespaceDecl>(ND)) { >+ if (const auto* AbiTag = NS->getAttr<AbiTagAttr>()) { >+ 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<AbiTagAttr>()) { >+ 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<typename TagList> >+ 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<uintptr_t, unsigned> Substitutions; > > ASTContext &getASTContext() const { return Context.getASTContext(); } >@@ -285,6 +450,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 +467,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 +508,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 +596,10 @@ private: > void mangleTemplateParameter(unsigned Index); > > void mangleFunctionParam(const ParmVarDecl *parm); >+ >+ std::set<StringRef> getTagsFromPrefixAndTemplateArguments(const NamedDecl *ND); >+ AbiTagList makeAdditionalTagsForFunction(const FunctionDecl *FD); >+ AbiTagList makeAdditionalTagsForVariable(const VarDecl *VD); > }; > > } >@@ -456,6 +650,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) { > // <mangled-name> ::= _Z <encoding> > // ::= <data name> >@@ -471,14 +670,28 @@ void CXXNameMangler::mangle(const NamedDecl *D) { > mangleName(cast<FieldDecl>(D)); > } > >-void CXXNameMangler::mangleFunctionEncoding(const FunctionDecl *FD) { >- // <encoding> ::= <function name> <bare-function-type> >- 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; >+ } >+ >+ // <encoding> ::= <function name> <bare-function-type> >+ >+ 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<EnableIfAttr>()) { > FunctionTypeDepthState Saved = FunctionTypeDepth.push(); > Out << "Ua9enable_ifI"; >@@ -582,7 +795,21 @@ isTemplate(const NamedDecl *ND, const TemplateArgumentList *&TemplateArgs) { > return nullptr; > } > >-void CXXNameMangler::mangleName(const NamedDecl *ND) { >+// must not be run from mangleLocalName for the <entity name> as it would loop otherwise. >+void CXXNameMangler::mangleName(const NamedDecl *ND, bool ExcludeUnqualifiedName) { >+ if (!ExcludeUnqualifiedName) { >+ if (const VarDecl *VD = dyn_cast<VarDecl>(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) { > // <name> ::= <nested-name> > // ::= <unscoped-name> > // ::= <unscoped-template-name> <template-args> >@@ -598,7 +825,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 +835,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) { > // <unscoped-name> ::= <unqualified-name> > // ::= St <unqualified-name> # ::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) { > // <unscoped-template-name> ::= <unscoped-name> > // ::= <substitution> > if (mangleSubstitution(ND)) > return; > > // <template-template-param> ::= <template-param> >- if (const auto *TTP = dyn_cast<TemplateTemplateParmDecl>(ND)) >+ if (const auto *TTP = dyn_cast<TemplateTemplateParmDecl>(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) { > // <unscoped-template-name> ::= <unscoped-name> > // ::= <substitution> > 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 +1076,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 +1085,7 @@ void CXXNameMangler::mangleUnresolvedPrefix(NestedNameSpecifier *qualifier, > else > Out << "sr"; > mangleSourceName(qualifier->getAsNamespaceAlias()->getIdentifier()); >+ writeAbiTags(qualifier->getAsNamespaceAlias()); > break; > > case NestedNameSpecifier::TypeSpec: >@@ -879,6 +1120,7 @@ void CXXNameMangler::mangleUnresolvedPrefix(NestedNameSpecifier *qualifier, > Out << "sr"; > > mangleSourceName(qualifier->getAsIdentifier()); >+ // an Identifier has no type information, so we can't emit abi tags for it > break; > } > >@@ -924,7 +1166,8 @@ void CXXNameMangler::mangleUnresolvedName(NestedNameSpecifier *qualifier, > > void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND, > DeclarationName Name, >- unsigned KnownArity) { >+ unsigned KnownArity, >+ const AbiTagList *AdditionalAbiTags) { > unsigned Arity = KnownArity; > // <unqualified-name> ::= <operator-name> > // ::= <ctor-dtor-name> >@@ -943,6 +1186,7 @@ void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND, > Out << 'L'; > > mangleSourceName(II); >+ writeAbiTags(ND, AdditionalAbiTags); > break; > } > >@@ -982,6 +1226,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 +1247,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 +1259,7 @@ void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND, > // <lambda-sig> ::= <parameter-type>+ # Parameter types or 'v' for 'void'. > if (const CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(TD)) { > if (Record->isLambda() && Record->getLambdaManglingNumber()) { >+ assert(!AdditionalAbiTags && "Lambda type cannot have additional abi tags"); > mangleLambda(Record); > break; > } >@@ -1022,6 +1271,7 @@ void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND, > if (UnnamedMangle > 1) > Out << llvm::utostr(UnnamedMangle - 2); > Out << '_'; >+ writeAbiTags(TD, AdditionalAbiTags); > break; > } > >@@ -1054,6 +1304,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 +1316,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 +1332,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 +1349,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) { > // <nested-name> > // ::= N [<CV-qualifiers>] [<ref-qualifier>] <prefix> <unqualified-name> E > // ::= N [<CV-qualifiers>] [<ref-qualifier>] <template-prefix> >@@ -1116,30 +1371,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) { > // <nested-name> ::= N [<CV-qualifiers>] <template-prefix> <template-args> 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) { > // <local-name> := Z <function encoding> E <entity name> [<discriminator>] > // := Z <function encoding> E s [<discriminator>] > // <local-name> := Z <function encoding> E d [ <parameter number> ] >@@ -1151,15 +1411,25 @@ void CXXNameMangler::mangleLocalName(const Decl *D) { > > Out << 'Z'; > >- if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(DC)) >- mangleObjCMethodName(MD); >- else if (const BlockDecl *BD = dyn_cast<BlockDecl>(DC)) >- mangleBlockForPrefix(BD); >- else >- mangleFunctionEncoding(cast<FunctionDecl>(DC)); >+ { >+ AbiTagState localAbiTags(AbiTags); >+ >+ if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(DC)) >+ mangleObjCMethodName(MD); >+ else if (const BlockDecl *BD = dyn_cast<BlockDecl>(DC)) >+ mangleBlockForPrefix(BD); >+ else >+ mangleFunctionEncoding(cast<FunctionDecl>(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<NamedDecl>(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 +1454,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<BlockDecl>(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<NamedDecl>(D); >- mangleNestedName(ND, getEffectiveDeclContext(ND), true /*NoFunction*/); >+ mangleNestedName(ND, getEffectiveDeclContext(ND), >+ AdditionalAbiTags, true /*NoFunction*/, ExcludeUnqualifiedName); > } > } else if (const BlockDecl *BD = dyn_cast<BlockDecl>(D)) { > // Mangle a block in a default parameter; see above explanation for >@@ -1207,30 +1481,35 @@ void CXXNameMangler::mangleLocalName(const Decl *D) { > } > } > >- mangleUnqualifiedBlock(BD); >+ assert(!AdditionalAbiTags && "Block cannot have additional abi tags"); >+ if (!ExcludeUnqualifiedName) >+ mangleUnqualifiedBlock(BD); > } else { >- mangleUnqualifiedName(cast<NamedDecl>(D)); >- } >- >- if (const NamedDecl *ND = dyn_cast<NamedDecl>(RD ? RD : D)) { >- unsigned disc; >- if (Context.getNextDiscriminator(ND, disc)) { >- if (disc < 10) >- Out << '_' << disc; >- else >- Out << "__" << disc << '_'; >+ if (!ExcludeUnqualifiedName) >+ mangleUnqualifiedName(cast<NamedDecl>(D), AdditionalAbiTags); >+ } >+ >+ if (!ExcludeUnqualifiedName) { >+ if (const NamedDecl *ND = dyn_cast<NamedDecl>(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 +1520,11 @@ void CXXNameMangler::mangleUnqualifiedBlock(const BlockDecl *Block) { > if (Decl *Context = Block->getBlockManglingContextDecl()) { > if ((isa<VarDecl>(Context) || isa<FieldDecl>(Context)) && > Context->getDeclContext()->isRecord()) { >- if (const IdentifierInfo *Name >- = cast<NamedDecl>(Context)->getIdentifier()) { >+ const auto *ND = cast<NamedDecl>(Context); >+ if (const IdentifierInfo *Name = ND->getIdentifier()) { > mangleSourceName(Name); >- Out << 'M'; >+ writeAbiTags(ND, /* AdditionalAbiTags */ nullptr); >+ Out << 'M'; > } > } > } >@@ -1277,7 +1557,7 @@ void CXXNameMangler::mangleLambda(const CXXRecordDecl *Lambda) { > if (const IdentifierInfo *Name > = cast<NamedDecl>(Context)->getIdentifier()) { > mangleSourceName(Name); >- Out << 'M'; >+ Out << 'M'; > } > } > } >@@ -1359,11 +1639,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 +1654,30 @@ void CXXNameMangler::mangleTemplatePrefix(TemplateName Template) { > // ::= <template-param> > // ::= <substitution> > 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) { > // <template-prefix> ::= <prefix> <template unqualified-name> > // ::= <template-param> > // ::= <substitution> >@@ -1406,10 +1689,12 @@ void CXXNameMangler::mangleTemplatePrefix(const TemplateDecl *ND, > > // <template-template-param> ::= <template-param> > if (const auto *TTP = dyn_cast<TemplateTemplateParmDecl>(ND)) { >+ // TODO(abitags): ??? > mangleTemplateParameter(TTP->getIndex()); > } else { > manglePrefix(getEffectiveDeclContext(ND), NoFunction); >- mangleUnqualifiedName(ND->getTemplatedDecl()); >+ if (!ExcludeUnqualifiedName) >+ mangleUnqualifiedName(ND->getTemplatedDecl(), AdditionalAbiTags); > } > > addSubstitution(ND); >@@ -1453,6 +1738,7 @@ void CXXNameMangler::mangleType(TemplateName TN) { > // <name> ::= <nested-name> > mangleUnresolvedPrefix(Dependent->getQualifier()); > mangleSourceName(Dependent->getIdentifier()); >+ // writeAbiTags(Dependent); > break; > } > >@@ -1544,16 +1830,19 @@ bool CXXNameMangler::mangleUnresolvedTypeOrSimpleId(QualType Ty, > > case Type::Typedef: > mangleSourceName(cast<TypedefType>(Ty)->getDecl()->getIdentifier()); >+ writeAbiTags(cast<TypedefType>(Ty)->getDecl()); > break; > > case Type::UnresolvedUsing: > mangleSourceName( > cast<UnresolvedUsingType>(Ty)->getDecl()->getIdentifier()); >+ writeAbiTags(cast<UnresolvedUsingType>(Ty)->getDecl()); > break; > > case Type::Enum: > case Type::Record: > mangleSourceName(cast<TagType>(Ty)->getDecl()->getIdentifier()); >+ writeAbiTags(cast<TagType>(Ty)->getDecl()); > break; > > case Type::TemplateSpecialization: { >@@ -1572,6 +1861,7 @@ bool CXXNameMangler::mangleUnresolvedTypeOrSimpleId(QualType Ty, > goto unresolvedType; > > mangleSourceName(TD->getIdentifier()); >+ writeAbiTags(TD); > break; > } > >@@ -1603,16 +1893,19 @@ bool CXXNameMangler::mangleUnresolvedTypeOrSimpleId(QualType Ty, > case Type::InjectedClassName: > mangleSourceName( > cast<InjectedClassNameType>(Ty)->getDecl()->getIdentifier()); >+ writeAbiTags(cast<InjectedClassNameType>(Ty)->getDecl()); > break; > > case Type::DependentName: > mangleSourceName(cast<DependentNameType>(Ty)->getIdentifier()); >+ // writeAbiTags(cast<DependentNameType>(Ty)); > break; > > case Type::DependentTemplateSpecialization: { > const DependentTemplateSpecializationType *DTST = > cast<DependentTemplateSpecializationType>(Ty); > mangleSourceName(DTST->getIdentifier()); >+ // writeAbiTags(DTST); > mangleTemplateArgs(DTST->getArgs(), DTST->getNumArgs()); > break; > } >@@ -2421,7 +2714,11 @@ void CXXNameMangler::mangleType(const InjectedClassNameType *T) { > > void CXXNameMangler::mangleType(const TemplateSpecializationType *T) { > if (TemplateDecl *TD = T->getTemplateName().getAsTemplateDecl()) { >- mangleName(TD, T->getArgs(), T->getNumArgs()); >+ // types only have explicit abi tags, no addition tags >+ mangleTemplateName(TD, >+ /* AdditionalAbiTags */ nullptr, >+ /* ExcludeUnqualifiedName */ false, >+ T->getArgs(), T->getNumArgs()); > } else { > if (mangleSubstitution(QualType(T, 0))) > return; >@@ -2468,6 +2765,7 @@ void CXXNameMangler::mangleType(const DependentNameType *T) { > Out << 'N'; > manglePrefix(T->getQualifier()); > mangleSourceName(T->getIdentifier()); >+ // writeAbiTags(T); // TODO(abitags) > Out << 'E'; > } > >@@ -3863,6 +4161,76 @@ void CXXNameMangler::addSubstitution(uintptr_t Ptr) { > Substitutions[Ptr] = SeqID++; > } > >+std::set<StringRef> CXXNameMangler::getTagsFromPrefixAndTemplateArguments(const NamedDecl *ND) { >+ llvm::raw_null_ostream NullOutStream; >+ CXXNameMangler TrackPrefixAndTemplateArguments(*this, NullOutStream); >+ >+ if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)) { >+ TrackPrefixAndTemplateArguments.mangleFunctionEncoding(FD, /* ExcludeUnqualifiedName */ true); >+ } else { >+ TrackPrefixAndTemplateArguments.mangleName(ND, /* ExcludeUnqualifiedName */ true); >+ } >+ >+ return std::move(TrackPrefixAndTemplateArguments.AbiTagsRoot.UsedAbiTags); >+} >+ >+CXXNameMangler::AbiTagList CXXNameMangler::makeAdditionalTagsForFunction(const FunctionDecl *FD) { >+ // when derived abi tags are disabled there is no need to make any list >+ if (DisableDerivedAbiTags) return AbiTagList(); >+ >+ std::set<StringRef> ImplicitlyAvailableTags = getTagsFromPrefixAndTemplateArguments(FD); >+ std::set<StringRef> ReturnTypeTags; >+ >+ { >+ llvm::raw_null_ostream NullOutStream; >+ CXXNameMangler TrackReturnTypeTags(*this, NullOutStream); >+ TrackReturnTypeTags.disableDerivedAbiTags(); >+ >+ const FunctionProtoType *Proto = cast<FunctionProtoType>(FD->getType()->getAs<FunctionType>()); >+ TrackReturnTypeTags.FunctionTypeDepth.enterResultType(); >+ TrackReturnTypeTags.mangleType(Proto->getReturnType()); >+ TrackReturnTypeTags.FunctionTypeDepth.leaveResultType(); >+ >+ ReturnTypeTags = std::move(TrackReturnTypeTags.AbiTagsRoot.UsedAbiTags); >+ } >+ >+ AbiTagList AdditionalAbiTags; >+ >+ for (const auto& Tag: ReturnTypeTags) { >+ if (ImplicitlyAvailableTags.count(Tag) == 0) >+ AdditionalAbiTags.push_back(Tag); >+ } >+ >+ return AdditionalAbiTags; >+} >+ >+CXXNameMangler::AbiTagList CXXNameMangler::makeAdditionalTagsForVariable(const VarDecl *VD) { >+ // when derived abi tags are disabled there is no need to make any list >+ if (DisableDerivedAbiTags) return AbiTagList(); >+ >+ std::set<StringRef> ImplicitlyAvailableTags = getTagsFromPrefixAndTemplateArguments(VD); >+ std::set<StringRef> VariableTypeTags; >+ >+ { >+ llvm::raw_null_ostream NullOutStream; >+ CXXNameMangler TrackVariableType(*this, NullOutStream); >+ TrackVariableType.disableDerivedAbiTags(); >+ >+ TrackVariableType.mangleType(VD->getType()); >+ >+ VariableTypeTags = std::move(TrackVariableType.AbiTagsRoot.UsedAbiTags); >+ } >+ >+ AbiTagList AdditionalAbiTags; >+ >+ for (const auto& Tag: VariableTypeTags) { >+ if (ImplicitlyAvailableTags.count(Tag) == 0) >+ AdditionalAbiTags.push_back(Tag); >+ } >+ >+ return AdditionalAbiTags; >+} >+ > // > > /// Mangles the name of the declaration D and emits that name to the given >@@ -3964,6 +4332,7 @@ void ItaniumMangleContextImpl::mangleStaticGuardVariable(const VarDecl *D, > // <special-name> ::= GV <object name> # Guard variable for one-time > // # initialization > CXXNameMangler Mangler(*this, Out); >+ Mangler.disableDerivedAbiTags(); // GCC: doesn't emit derived abi tags for guard variables > Mangler.getStream() << "_ZGV"; > Mangler.mangleName(D); > } >diff --git a/tools/clang/lib/Sema/SemaDeclAttr.cpp b/tools/clang/lib/Sema/SemaDeclAttr.cpp >index 191dbd0..04e67f2 100644 >--- a/tools/clang/lib/Sema/SemaDeclAttr.cpp >+++ b/tools/clang/lib/Sema/SemaDeclAttr.cpp >@@ -4166,6 +4166,66 @@ static void handleDeclspecThreadAttr(Sema &S, Decl *D, > Attr.getRange(), S.Context, Attr.getAttributeSpellingListIndex())); > } > >+static void handleAbiTagAttr(Sema &S, Decl *D, >+ const AttributeList &Attr) { >+ const auto *NS = dyn_cast<NamespaceDecl>(D); >+ >+ if (!checkAttributeAtLeastNumArgs(S, Attr, NS ? 0 : 1)) >+ return; >+ >+ SmallVector<std::string, 4> Tags; >+ >+ for (unsigned I = 0, E = Attr.getNumArgs(); I != E; ++I) { >+ StringRef Tag; >+ >+ if (!S.checkStringLiteralArgumentAttr(Attr, I, Tag)) >+ return; >+ >+ Tags.push_back(Tag); >+ } >+ >+ if (NS && !NS->isInline()) { >+ S.Diag(Attr.getLoc(), diag::err_attr_abi_tag_only_on_inline_namespace); >+ return; >+ } >+ if (NS && NS->isAnonymousNamespace()) { >+ S.Diag(Attr.getLoc(), diag::err_attr_abi_tag_only_on_named_namespace); >+ return; >+ } >+ if (NS && Attr.getNumArgs() == 0) { >+ Tags.push_back(NS->getName()); >+ } >+ >+ // store tags sorted and without duplicates >+ std::sort(Tags.begin(), Tags.end()); >+ Tags.erase(std::unique(Tags.begin(), Tags.end()), Tags.end()); >+ >+ const auto *CD = D->getCanonicalDecl(); >+ if (CD != D) { >+ // redeclarations must not add new abi tags, or abi tags in the first place >+ const auto *OldAbiTagAttr = D->getAttr<AbiTagAttr>(); >+ if (nullptr == OldAbiTagAttr) { >+ S.Diag(Attr.getLoc(), diag::err_abi_tag_on_redeclaration); >+ S.Diag(CD->getLocation(), diag::note_previous_definition); >+ return; >+ } >+ for (const auto& NewTag: Tags) { >+ if (std::find(OldAbiTagAttr->tags_begin(), >+ OldAbiTagAttr->tags_end(), >+ NewTag) == OldAbiTagAttr->tags_end()) { >+ S.Diag(Attr.getLoc(), diag::err_new_abi_tag_on_redeclaration) << NewTag; >+ S.Diag(OldAbiTagAttr->getLocation(), diag::note_previous_definition); >+ return; >+ } >+ } >+ return; >+ } >+ >+ D->addAttr(::new (S.Context) AbiTagAttr(Attr.getRange(), S.Context, >+ Tags.data(), Tags.size(), >+ Attr.getAttributeSpellingListIndex())); >+} >+ > static void handleARMInterruptAttr(Sema &S, Decl *D, > const AttributeList &Attr) { > // Check the attribute arguments. >@@ -4978,6 +5038,9 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, > case AttributeList::AT_Thread: > handleDeclspecThreadAttr(S, D, Attr); > break; >+ case AttributeList::AT_AbiTag: >+ handleAbiTagAttr(S, D, Attr); >+ break; > > // Thread safety attributes: > case AttributeList::AT_AssertExclusiveLock:
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 571600
:
423550
|
440340
|
440342