summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAdam Jackson <ajax@redhat.com>2015-12-04 10:44:12 -0500
committerAdam Jackson <ajax@redhat.com>2015-12-04 10:44:12 -0500
commit64695d69a2aac2ccdfcf733f7466d6b771d8781f (patch)
tree5e31bdcd9d249837a187b22f7e384e8bb34ab3b4
parent478ee5f8609926d72bc88fa506e4b7b974b7f266 (diff)
downloadllvm-64695d69a2aac2ccdfcf733f7466d6b771d8781f.zip
llvm-64695d69a2aac2ccdfcf733f7466d6b771d8781f.tar.gz
llvm-64695d69a2aac2ccdfcf733f7466d6b771d8781f.tar.xz
Resolves: rhbz#1282645 add GCC abi_tag support
-rw-r--r--0001-add-gcc-abi_tag-support.patch1232
-rw-r--r--0002-Adapt-previous-Clang-trunk-patch-to-Clang-3.7.patch24
-rw-r--r--llvm.spec11
3 files changed, 1266 insertions, 1 deletions
diff --git a/0001-add-gcc-abi_tag-support.patch b/0001-add-gcc-abi_tag-support.patch
new file mode 100644
index 0000000..89301f9
--- /dev/null
+++ b/0001-add-gcc-abi_tag-support.patch
@@ -0,0 +1,1232 @@
+From d7c20ff3406ee048dd5d0ff812f9e8b3d48bb192 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Stefan=20B=C3=BChler?= <lighttpd@stbuehler.de>
+Date: Thu, 3 Dec 2015 14:51:50 +0100
+Subject: [PATCH 1/3] add gcc abi_tag support
+
+<http://reviews.llvm.org/D12834?id=34645>
+---
+ 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 <unqualified-name> are emitted after the
++<unqualified-name>, before <template-args> or <discriminator>, and are part of
++the same <substitution> the <unqualified-name> is.
++
++They are mangled as:
++
++ <abi-tags> ::= <abi-tag>* # sort by name
++ <abi-tag> ::= B <tag source-name>
++
++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 <bare-function-type> (which
++might include the return type for template functions) are available.
++
++For <local-name>s all active tags used in the local part (<function-
++encoding>) are available, but not implicit tags which were not active!
++
++Implicit and explicit tags used in the <unqualified-name> 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<IgnoredAttributes>;
+ def err_attribute_wrong_decl_type : Error<warn_attribute_wrong_decl_type.Text>;
+ 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 <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 +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<StringRef> 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) {
+ // <mangled-name> ::= _Z <encoding>
+ // ::= <data name>
+@@ -471,14 +668,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";
+@@ -524,7 +735,7 @@ void CXXNameMangler::mangleFunctionEncoding(const FunctionDecl *FD) {
+ FD = PrimaryTemplate->getTemplatedDecl();
+ }
+
+- mangleBareFunctionType(FD->getType()->getAs<FunctionType>(),
++ mangleBareFunctionType(FD->getType()->getAs<FunctionType>(),
+ 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 <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 +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) {
+ // <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 +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;
+ // <unqualified-name> ::= <operator-name>
+ // ::= <ctor-dtor-name>
+@@ -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,
+ // <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 +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) {
+ // <nested-name>
+ // ::= N [<CV-qualifiers>] [<ref-qualifier>] <prefix> <unqualified-name> E
+ // ::= N [<CV-qualifiers>] [<ref-qualifier>] <template-prefix>
+@@ -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) {
+ // <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 +1409,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 +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<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 +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<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 +1518,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 +1555,7 @@ void CXXNameMangler::mangleLambda(const CXXRecordDecl *Lambda) {
+ if (const IdentifierInfo *Name
+ = cast<NamedDecl>(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) {
+ // ::= <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 +1687,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 +1736,7 @@ void CXXNameMangler::mangleType(TemplateName TN) {
+ // <name> ::= <nested-name>
+ mangleUnresolvedPrefix(Dependent->getQualifier());
+ mangleSourceName(Dependent->getIdentifier());
++ // writeAbiTags(Dependent);
+ break;
+ }
+
+@@ -1544,16 +1828,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 +1859,7 @@ bool CXXNameMangler::mangleUnresolvedTypeOrSimpleId(QualType Ty,
+ goto unresolvedType;
+
+ mangleSourceName(TD->getIdentifier());
++ writeAbiTags(TD);
+ break;
+ }
+
+@@ -1603,16 +1891,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 +2712,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 +2763,7 @@ void CXXNameMangler::mangleType(const DependentNameType *T) {
+ Out << 'N';
+ manglePrefix(T->getQualifier());
+ mangleSourceName(T->getIdentifier());
++ // writeAbiTags(T); // TODO(abitags)
+ Out << 'E';
+ }
+
+@@ -3863,6 +4159,74 @@ 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);
++
++ 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.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 +4328,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/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp
+index 191dbd0..225607e 100644
+--- a/tools/clang/lib/Sema/SemaDeclAttr.cpp
++++ b/tools/clang/lib/Sema/SemaDeclAttr.cpp
+@@ -4166,6 +4166,58 @@ static void handleDeclspecThreadAttr(Sema &S, Decl *D,
+ Attr.getRange(), S.Context, Attr.getAttributeSpellingListIndex()));
+ }
+
++static void handleAbiTagAttr(Sema &S, Decl *D,
++ const AttributeList &Attr) {
++ if (!checkAttributeAtLeastNumArgs(S, Attr, 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);
++ }
++ // store tags sorted and without duplicates
++ std::sort(Tags.begin(), Tags.end());
++ Tags.erase(std::unique(Tags.begin(), Tags.end()), Tags.end());
++
++ if (const auto *NS = dyn_cast<NamespaceDecl>(D)) {
++ if (!NS->isInline()) {
++ S.Diag(Attr.getLoc(), diag::err_attr_abi_tag_only_on_inline_namespace);
++ return;
++ }
++ }
++
++ 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 +5030,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:
+--
+2.4.3
+
diff --git a/0002-Adapt-previous-Clang-trunk-patch-to-Clang-3.7.patch b/0002-Adapt-previous-Clang-trunk-patch-to-Clang-3.7.patch
new file mode 100644
index 0000000..399c832
--- /dev/null
+++ b/0002-Adapt-previous-Clang-trunk-patch-to-Clang-3.7.patch
@@ -0,0 +1,24 @@
+From e746af90e6aa52af6e6bb0b88ffe20dbd97a1e4d Mon Sep 17 00:00:00 2001
+From: Stephan Bergmann <sbergman@redhat.com>
+Date: Thu, 3 Dec 2015 14:53:39 +0100
+Subject: [PATCH 2/3] Adapt previous (Clang trunk) patch to Clang 3.7
+
+---
+ lib/AST/ItaniumMangle.cpp | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/lib/AST/ItaniumMangle.cpp b/lib/AST/ItaniumMangle.cpp
+index e32b659..19a09dc 100644
+--- a/tools/clang/lib/AST/ItaniumMangle.cpp
++++ b/tools/clang/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 <set>
+
+ #define MANGLE_CHECKER 0
+
+--
+2.4.3
+
diff --git a/llvm.spec b/llvm.spec
index f10704f..b3d6627 100644
--- a/llvm.spec
+++ b/llvm.spec
@@ -35,7 +35,7 @@
Name: llvm
Version: 3.7.0
-Release: 2%{?dist}
+Release: 3%{?dist}
Summary: The Low Level Virtual Machine
Group: Development/Languages
@@ -72,6 +72,9 @@ Patch2: 0001-data-install-preserve-timestamps.patch
Patch200: lldb-python.patch
Patch202: lldb-python-module-symlink.patch
+Patch203: 0001-add-gcc-abi_tag-support.patch
+Patch204: 0002-Adapt-previous-Clang-trunk-patch-to-Clang-3.7.patch
+
BuildRequires: bison
BuildRequires: chrpath
BuildRequires: flex
@@ -332,6 +335,9 @@ sed -i s/@lib@/%{_lib}/g scripts/Python/modules/readline/Makefile
popd
%endif
+%patch203 -p1
+%patch204 -p1
+
# fix library paths
sed -i 's|/lib /usr/lib $lt_ld_extra|%{_libdir} $lt_ld_extra|' configure
sed -i 's|(PROJ_prefix)/lib|(PROJ_prefix)/%{_lib}/%{name}|g' Makefile.config.in
@@ -698,6 +704,9 @@ exit 0
%endif
%changelog
+* Thu Dec 03 2015 Stephan Bergmann <sbergman@redhat.com> 3.7.0-3
+- Resolves: rhbz#1282645 add GCC abi_tag support
+
* Thu Oct 29 2015 Adam Jackson <ajax@redhat.com> 3.7.0-2
- Drop -fno-devirtualize
- Link with -static-libstdc++ to work around bundled libstdc++ in Steam