DmitryPolukhin updated this revision to Diff 61350.
DmitryPolukhin added a comment.

This patch set contains serious refactoring to make it closer to what Richard 
suggested. Unfortunately there is no way to fully implement Richard's idea 
because we have to mangle twice name of functions and variables. But this patch 
reuse mangled bare function type generated during tags calculation.

NOTE for people who use this patch for local testing: this patch set was not 
tested extensively on real world apps so it might have be worse than previous 
one. If you can, please test it in your environment and report any issues. For 
now "stable" version of this patch is previous patch set from May 23.

Richard, please take a look and let me know if it looks better for you. IMHO, 
it becomes smaller and simpler and reuse mangling for function prototype.


http://reviews.llvm.org/D18035

Files:
  lib/AST/ItaniumMangle.cpp
  lib/Sema/SemaDeclAttr.cpp
  test/CodeGenCXX/mangle-abi-tag.cpp
  test/PCH/attrs.c
  test/SemaCXX/attr-abi-tag-syntax.cpp

Index: test/SemaCXX/attr-abi-tag-syntax.cpp
===================================================================
--- test/SemaCXX/attr-abi-tag-syntax.cpp
+++ test/SemaCXX/attr-abi-tag-syntax.cpp
@@ -16,28 +16,18 @@
 // expected-warning@-1 {{'abi_tag' attribute on anonymous namespace ignored}}
 
 inline namespace N __attribute__((__abi_tag__)) {}
-// FIXME: remove this warning as soon as attribute fully supported.
-// expected-warning@-2 {{'__abi_tag__' attribute ignored}}
 
 } // namespcace N2
 
 __attribute__((abi_tag("B", "A"))) extern int a1;
-// FIXME: remove this warning as soon as attribute fully supported.
-// expected-warning@-2 {{'abi_tag' attribute ignored}}
 
 __attribute__((abi_tag("A", "B"))) extern int a1;
 // expected-note@-1 {{previous declaration is here}}
-// FIXME: remove this warning as soon as attribute fully supported.
-// expected-warning@-3 {{'abi_tag' attribute ignored}}
 
 __attribute__((abi_tag("A", "C"))) extern int a1;
 // expected-error@-1 {{'abi_tag' C missing in original declaration}}
-// FIXME: remove this warning as soon as attribute fully supported.
-// expected-warning@-3 {{'abi_tag' attribute ignored}}
 
 extern int a2;
 // expected-note@-1 {{previous declaration is here}}
 __attribute__((abi_tag("A")))extern int a2;
 // expected-error@-1 {{cannot add 'abi_tag' attribute in a redeclaration}}
-// FIXME: remove this warning as soon as attribute fully supported.
-// expected-warning@-3 {{'abi_tag' attribute ignored}}
Index: test/PCH/attrs.c
===================================================================
--- test/PCH/attrs.c
+++ test/PCH/attrs.c
@@ -9,7 +9,7 @@
 #define HEADER
 
 int f(int) __attribute__((visibility("default"), overloadable));
-int g(int) __attribute__((abi_tag("foo", "bar", "baz"), no_sanitize("address", "memory"))); // expected-warning {{ignored}}
+int g(int) __attribute__((abi_tag("foo", "bar", "baz"), no_sanitize("address", "memory")));
 
 #else
 
Index: test/CodeGenCXX/mangle-abi-tag.cpp
===================================================================
--- /dev/null
+++ test/CodeGenCXX/mangle-abi-tag.cpp
@@ -0,0 +1,182 @@
+// RUN: %clang_cc1 %s -emit-llvm -triple %itanium_abi_triple -std=c++11 -o - | FileCheck %s
+// RUN: %clang_cc1 %s -emit-llvm -triple i686-linux-gnu -std=c++11 -o - | FileCheck %s
+// RUN: %clang_cc1 %s -emit-llvm -triple x86_64-linux-gnu -std=c++11 -o - | FileCheck %s
+
+struct __attribute__((abi_tag("A", "B"))) A { };
+
+struct B: A { };
+
+template<class T>
+
+struct C {
+};
+
+struct D { A* p; };
+
+template<class T>
+struct __attribute__((abi_tag("C", "D"))) E {
+};
+
+struct __attribute__((abi_tag("A", "B"))) F { };
+
+A a1;
+// CHECK-DAG: @_Z2a1B1AB1B =
+
+__attribute__((abi_tag("C", "D")))
+A a2;
+// CHECK-DAG: @_Z2a2B1AB1BB1CB1D =
+
+B a3;
+// CHECK-DAG: @a3 =
+
+C<A> a4;
+// CHECK-DAG: @_Z2a4B1AB1B =
+
+D a5;
+// CHECK-DAG: @a5 =
+
+E<int> a6;
+// CHECK-DAG: @_Z2a6B1CB1D =
+
+E<A> a7;
+// CHECK-DAG: @_Z2a7B1AB1BB1CB1D =
+
+template<>
+struct E<float> {
+  static float a8;
+};
+float E<float>::a8;
+// CHECK-DAG: @_ZN1EB1CB1DIfE2a8E =
+
+template<>
+struct E<F> {
+  static bool a9;
+};
+bool E<F>::a9;
+// CHECK-DAG: @_ZN1EB1CB1DI1FB1AB1BE2a9E =
+
+struct __attribute__((abi_tag("A", "B"))) A10 {
+  virtual ~A10() {}
+} a10;
+// vtable
+// CHECK-DAG: @_ZTV3A10B1AB1B =
+// typeinfo
+// CHECK-DAG: @_ZTI3A10B1AB1B =
+
+struct __attribute__((abi_tag("A"))) B11 {
+  static A10 b;
+};
+A10 B11::b;
+// B11[abi:A]::b[abi:B]
+// CHECK-DAG: @_ZN3B11B1A1bB1BE =
+
+__attribute__ ((abi_tag("C", "D")))
+void* f1() {
+  return 0;
+}
+// CHECK-DAG: define {{.*}} @_Z2f1B1CB1Dv(
+
+__attribute__ ((abi_tag("C", "D")))
+A* f2() {
+  return 0;
+}
+// CHECK-DAG: define {{.*}} @_Z2f2B1AB1BB1CB1Dv(
+
+B* f3() {
+  return 0;
+}
+// CHECK-DAG: define {{.*}} @_Z2f3v(
+
+C<A>* f4() {
+  return 0;
+}
+// CHECK-DAG: define {{.*}} @_Z2f4B1AB1Bv(
+
+D* f5() {
+  return 0;
+}
+// CHECK-DAG: define {{.*}} @_Z2f5v(
+
+E<char>* f6() {
+  return 0;
+}
+// CHECK-DAG: define {{.*}} @_Z2f6B1CB1Dv(
+
+E<A>* f7() {
+  return 0;
+}
+// CHECK-DAG: define {{.*}} @_Z2f7B1AB1BB1CB1Dv(
+
+void f8(E<A>*) {
+}
+// CHECK-DAG: define {{.*}} @_Z2f8P1EB1CB1DI1AB1AB1BE(
+
+inline namespace Names1 __attribute__((__abi_tag__)) {
+    class C1 {};
+}
+C1 f9() { return C1(); }
+// CHECK-DAG: @_Z2f9B6Names1v(
+
+inline namespace Names2 __attribute__((__abi_tag__("Tag1", "Tag2"))) {
+    class C2 {};
+}
+C2 f10() { return C2(); }
+// CHECK-DAG: @_Z3f10B4Tag1B4Tag2v(
+
+void __attribute__((abi_tag("A"))) f11(A) {}
+// f11[abi:A](A[abi:A][abi:B])
+// CHECK-DAG: define {{.*}} @_Z3f11B1A1AB1AB1B(
+
+A f12(A) { return A(); }
+// f12(A[abi:A][abi:B])
+// CHECK-DAG: define {{.*}} @_Z3f121AB1AB1B(
+
+inline void f13() {
+  struct L {
+    static E<int>* foo() {
+      static A10 a;
+      return 0;
+    }
+  };
+  L::foo();
+}
+void f13_test() {
+  f13();
+}
+// f13()::L::foo[abi:C][abi:D]()
+// CHECK-DAG: define linkonce_odr %struct.E* @_ZZ3f13vEN1L3fooB1CB1DEv(
+
+// f13()::L::foo[abi:C][abi:D]()::a[abi:A][abi:B]
+// CHECK-DAG: @_ZZZ3f13vEN1L3fooB1CB1DEvE1aB1AB1B =
+
+// guard variable for f13()::L::foo[abi:C][abi:D]()::a[abi:A][abi:B]
+// CHECK-DAG: @_ZGVZZ3f13vEN1L3fooB1CB1DEvE1aB1AB1B =
+
+struct __attribute__((abi_tag("TAG"))) A14 {
+  A14 f14();
+};
+A14 A14::f14() {
+  return A14();
+}
+// A14[abi:TAG]::f14()
+// CHECK-DAG: define void @_ZN3A14B3TAG3f14Ev(
+
+template<class T>
+T f15() {
+  return T();
+}
+void f15_test() {
+  f15<A14>();
+}
+// A14[abi:TAG] f15<A14[abi:TAG]>()
+// CHECK-DAG: define linkonce_odr void @_Z3f15I3A14B3TAGET_v(
+
+template<class T>
+A14 f16() {
+  return A14();
+}
+void f16_test() {
+  f16<int>();
+}
+// A14[abi:TAG] f16<int>()
+// CHECK-DAG: define linkonce_odr void @_Z3f16IiE3A14B3TAGv(
Index: lib/Sema/SemaDeclAttr.cpp
===================================================================
--- lib/Sema/SemaDeclAttr.cpp
+++ lib/Sema/SemaDeclAttr.cpp
@@ -4713,10 +4713,6 @@
   D->addAttr(::new (S.Context)
              AbiTagAttr(Attr.getRange(), S.Context, Tags.data(), Tags.size(),
                         Attr.getAttributeSpellingListIndex()));
-
-  // FIXME: remove this warning as soon as mangled part is ready.
-  S.Diag(Attr.getRange().getBegin(), diag::warn_attribute_ignored)
-        << Attr.getName();
 }
 
 static void handleARMInterruptAttr(Sema &S, Decl *D,
Index: lib/AST/ItaniumMangle.cpp
===================================================================
--- lib/AST/ItaniumMangle.cpp
+++ lib/AST/ItaniumMangle.cpp
@@ -214,6 +214,12 @@
 class CXXNameMangler {
   ItaniumMangleContextImpl &Context;
   raw_ostream &Out;
+  bool NullOut = false;
+  /// In the "DisableDerivedAbiTags" mode derived ABI tags are not calculated.
+  /// This mode is used when mangler creates another mangler recursively to
+  /// calculate ABI tags for the function return value or the variable type.
+  /// Also it is required to avoid infinite recursion in some cases.
+  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,27 +269,153 @@
 
   } FunctionTypeDepth;
 
+  // abi_tag is a gcc attribute, taking one or more strings called "tags".
+  // The goal is to annotate against which version of a library an object was
+  // built and to be able to provide backwards compatibility ("dual abi").
+  // For more information see docs/ItaniumMangleAbiTags.rst.
+  typedef SmallVector<StringRef, 4> AbiTagList;
+  typedef llvm::SmallSetVector<StringRef, 4> AbiTagSet;
+
+  // 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.
+  class AbiTagState final {
+    //! All abi tags used implicitly or explicitly
+    AbiTagSet UsedAbiTags;
+    //! All explicit abi tags (i.e. not from namespace)
+    AbiTagSet EmittedAbiTags;
+
+    AbiTagState *&LinkHead;
+    AbiTagState *Parent = nullptr;
+
+    bool LinkActive = false;
+
+  public:
+    explicit AbiTagState(AbiTagState *&Head) : LinkHead(Head) {
+      Parent = LinkHead;
+      LinkHead = this;
+      LinkActive = true;
+    }
+
+    // no copy, no move
+    AbiTagState(const AbiTagState &) = delete;
+    AbiTagState &operator=(const AbiTagState &) = 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 (!isa<FunctionDecl>(ND) && !isa<VarDecl>(ND)) {
+        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);
+    }
+
+    const AbiTagSet &getUsedAbiTags() const { return UsedAbiTags; }
+    void setUsedAbiTags(const AbiTagSet &AbiTags) {
+      UsedAbiTags = AbiTags;
+    }
+
+    const AbiTagSet &getEmittedAbiTags() const {
+      return EmittedAbiTags;
+    }
+
+  private:
+    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;
+      }
+    }
+  };
+
+  AbiTagState *AbiTags = nullptr;
+  AbiTagState AbiTagsRoot;
+
   llvm::DenseMap<uintptr_t, unsigned> Substitutions;
 
   ASTContext &getASTContext() const { return Context.getASTContext(); }
 
 public:
   CXXNameMangler(ItaniumMangleContextImpl &C, raw_ostream &Out_,
-                 const NamedDecl *D = nullptr)
-    : Context(C), Out(Out_), Structor(getStructor(D)), StructorType(0),
-      SeqID(0) {
+                 const NamedDecl *D = nullptr, bool NullOut_ = false)
+    : Context(C), Out(Out_), NullOut(NullOut_),  Structor(getStructor(D)),
+      StructorType(0), SeqID(0), AbiTagsRoot(AbiTags) {
     // These can't be mangled without a ctor type or dtor type.
     assert(!D || (!isa<CXXDestructorDecl>(D) &&
                   !isa<CXXConstructorDecl>(D)));
   }
   CXXNameMangler(ItaniumMangleContextImpl &C, raw_ostream &Out_,
                  const CXXConstructorDecl *D, CXXCtorType Type)
     : Context(C), Out(Out_), Structor(getStructor(D)), StructorType(Type),
-      SeqID(0) { }
+      SeqID(0), AbiTagsRoot(AbiTags) { }
   CXXNameMangler(ItaniumMangleContextImpl &C, raw_ostream &Out_,
                  const CXXDestructorDecl *D, CXXDtorType Type)
     : Context(C), Out(Out_), Structor(getStructor(D)), StructorType(Type),
-      SeqID(0) { }
+      SeqID(0), AbiTagsRoot(AbiTags) { }
+
+  CXXNameMangler(CXXNameMangler &Outer, raw_ostream &Out_)
+      : Context(Outer.Context), Out(Out_), NullOut(false),
+        Structor(Outer.Structor), StructorType(Outer.StructorType),
+        SeqID(Outer.SeqID), AbiTagsRoot(AbiTags) {}
+
+  CXXNameMangler(CXXNameMangler &Outer, llvm::raw_null_ostream &Out_)
+      : Context(Outer.Context), Out(Out_), NullOut(true),
+        Structor(Outer.Structor), StructorType(Outer.StructorType),
+        SeqID(Outer.SeqID), AbiTagsRoot(AbiTags) {}
 
 #if MANGLE_CHECKER
   ~CXXNameMangler() {
@@ -298,6 +430,9 @@
 #endif
   raw_ostream &getStream() { return Out; }
 
+  void disableDerivedAbiTags() { DisableDerivedAbiTags = true; }
+  static bool shouldHaveAbiTags(ItaniumMangleContextImpl &C, const VarDecl *VD);
+
   void mangle(const NamedDecl *D);
   void mangleCallOffset(int64_t NonVirtual, int64_t Virtual);
   void mangleNumber(const llvm::APSInt &I);
@@ -336,23 +471,37 @@
                             DeclarationName name,
                             unsigned KnownArity = UnknownArity);
 
-  void mangleName(const TemplateDecl *TD,
-                  const TemplateArgument *TemplateArgs,
-                  unsigned NumTemplateArgs);
-  void mangleUnqualifiedName(const NamedDecl *ND) {
-    mangleUnqualifiedName(ND, ND->getDeclName(), UnknownArity);
+  void mangleFunctionEncodingBareType(const FunctionDecl *FD);
+
+  void mangleNameWithAbiTags(const NamedDecl *ND,
+                             const AbiTagList *AdditionalAbiTags);
+  void mangleTemplateName(const TemplateDecl *TD,
+                          const TemplateArgument *TemplateArgs,
+                          unsigned NumTemplateArgs);
+  void mangleUnqualifiedName(const NamedDecl *ND,
+                             const AbiTagList *AdditionalAbiTags) {
+    mangleUnqualifiedName(ND, ND->getDeclName(), UnknownArity,
+                          AdditionalAbiTags);
   }
   void mangleUnqualifiedName(const NamedDecl *ND, DeclarationName Name,
-                             unsigned KnownArity);
-  void mangleUnscopedName(const NamedDecl *ND);
-  void mangleUnscopedTemplateName(const TemplateDecl *ND);
-  void mangleUnscopedTemplateName(TemplateName);
+                             unsigned KnownArity,
+                             const AbiTagList *AdditionalAbiTags);
+  void mangleUnscopedName(const NamedDecl *ND,
+                          const AbiTagList *AdditionalAbiTags);
+  void mangleUnscopedTemplateName(const TemplateDecl *ND,
+                                  const AbiTagList *AdditionalAbiTags);
+  void mangleUnscopedTemplateName(TemplateName,
+                                  const AbiTagList *AdditionalAbiTags);
   void mangleSourceName(const IdentifierInfo *II);
-  void mangleLocalName(const Decl *D);
+  void mangleSourceNameWithAbiTags(
+      const NamedDecl *ND, const AbiTagList *AdditionalAbiTags = nullptr);
+  void mangleLocalName(const Decl *D,
+                       const AbiTagList *AdditionalAbiTags);
   void mangleBlockForPrefix(const BlockDecl *Block);
   void mangleUnqualifiedBlock(const BlockDecl *Block);
   void mangleLambda(const CXXRecordDecl *Lambda);
   void mangleNestedName(const NamedDecl *ND, const DeclContext *DC,
+                        const AbiTagList *AdditionalAbiTags,
                         bool NoFunction=false);
   void mangleNestedName(const TemplateDecl *TD,
                         const TemplateArgument *TemplateArgs,
@@ -411,6 +560,12 @@
   void mangleTemplateParameter(unsigned Index);
 
   void mangleFunctionParam(const ParmVarDecl *parm);
+
+  void writeAbiTags(const NamedDecl *ND,
+                    const AbiTagList *AdditionalAbiTags);
+
+  AbiTagSet makeFunctionReturnTypeTags(const FunctionDecl *FD);
+  AbiTagSet makeVariableTypeTags(const VarDecl *VD);
 };
 
 }
@@ -454,13 +609,26 @@
       while (!DC->isNamespace() && !DC->isTranslationUnit())
         DC = getEffectiveParentContext(DC);
     if (DC->isTranslationUnit() && D->getFormalLinkage() != InternalLinkage &&
+        !CXXNameMangler::shouldHaveAbiTags(*this, VD) &&
         !isa<VarTemplateSpecializationDecl>(D))
       return false;
   }
 
   return true;
 }
 
+void CXXNameMangler::writeAbiTags(const NamedDecl *ND,
+                                  const AbiTagList *AdditionalAbiTags) {
+  assert(AbiTags && "require AbiTagState");
+  AbiTags->write(Out, ND, DisableDerivedAbiTags ? nullptr : AdditionalAbiTags);
+}
+
+void CXXNameMangler::mangleSourceNameWithAbiTags(
+    const NamedDecl *ND, const AbiTagList *AdditionalAbiTags) {
+  mangleSourceName(ND->getIdentifier());
+  writeAbiTags(ND, AdditionalAbiTags);
+}
+
 void CXXNameMangler::mangle(const NamedDecl *D) {
   // <mangled-name> ::= _Z <encoding>
   //            ::= <data name>
@@ -478,12 +646,47 @@
 
 void CXXNameMangler::mangleFunctionEncoding(const FunctionDecl *FD) {
   // <encoding> ::= <function name> <bare-function-type>
-  mangleName(FD);
 
   // Don't mangle in the type if this isn't a decl we should typically mangle.
-  if (!Context.shouldMangleDeclName(FD))
+  if (!Context.shouldMangleDeclName(FD)) {
+    mangleName(FD);
     return;
+  }
+
+  AbiTagSet ReturnTypeAbiTags = makeFunctionReturnTypeTags(FD);
+  if (ReturnTypeAbiTags.empty()) {
+    // There are no tags for return type, the simplest case.
+    mangleName(FD);
+    mangleFunctionEncodingBareType(FD);
+    return;
+  }
+
+  // Mangle function encoding to temporary buffer.
+  SmallString<256> FunctionEncodingBuf;
+  llvm::raw_svector_ostream FunctionEncodingStream(FunctionEncodingBuf);
+  CXXNameMangler FunctionEncodingMangler(*this, FunctionEncodingStream);
+  FunctionEncodingMangler.mangleFunctionEncodingBareType(FD);
+
+  // Mangle function name to null stream to collect tags.
+  llvm::raw_null_ostream NullOutStream;
+  CXXNameMangler FunctionNameMangler(*this, NullOutStream);
+  FunctionNameMangler.disableDerivedAbiTags();
+  FunctionNameMangler.mangleNameWithAbiTags(FD, nullptr);
+
+  // Get tags from return type that are not present in function name or encoding
+  AbiTagList AdditionalAbiTags;
+  for (const auto &Tag : ReturnTypeAbiTags) {
+    if (!FunctionEncodingMangler.AbiTagsRoot.getUsedAbiTags().count(Tag) &&
+        !FunctionNameMangler.AbiTagsRoot.getUsedAbiTags().count(Tag))
+      AdditionalAbiTags.push_back(Tag);
+  }
+
+  // Output name with implicit tags and function encoding from temporary buffer.
+  mangleNameWithAbiTags(FD, &AdditionalAbiTags);
+  Out << FunctionEncodingStream.str();
+}
 
+void CXXNameMangler::mangleFunctionEncodingBareType(const FunctionDecl *FD) {
   if (FD->hasAttr<EnableIfAttr>()) {
     FunctionTypeDepthState Saved = FunctionTypeDepth.push();
     Out << "Ua9enable_ifI";
@@ -588,6 +791,37 @@
 }
 
 void CXXNameMangler::mangleName(const NamedDecl *ND) {
+  if (const VarDecl *VD = dyn_cast<VarDecl>(ND)) {
+    // Variables should have implicit tags from its type.
+    AbiTagSet VariableTypeAbiTags = makeVariableTypeTags(VD);
+    if (VariableTypeAbiTags.empty()) {
+      // Simple case no variable type tags.
+      mangleNameWithAbiTags(VD, nullptr);
+      return;
+    }
+
+    // Mangle variable name to null stream to collect tags.
+    llvm::raw_null_ostream NullOutStream;
+    CXXNameMangler VariableNameMangler(*this, NullOutStream);
+    VariableNameMangler.disableDerivedAbiTags();
+    VariableNameMangler.mangleNameWithAbiTags(VD, nullptr);
+
+    // Get tags from variable type that are not present in its name.
+    AbiTagList AdditionalAbiTags;
+    for (const auto &Tag : VariableTypeAbiTags) {
+     if (!VariableNameMangler.AbiTagsRoot.getUsedAbiTags().count(Tag))
+        AdditionalAbiTags.push_back(Tag);
+    }
+
+    // Output name with implicit tags.
+    mangleNameWithAbiTags(VD, &AdditionalAbiTags);
+  } else {
+    mangleNameWithAbiTags(ND, nullptr);
+  }
+}
+
+void CXXNameMangler::mangleNameWithAbiTags(const NamedDecl *ND,
+                                           const AbiTagList *AdditionalAbiTags) {
   //  <name> ::= <nested-name>
   //         ::= <unscoped-name>
   //         ::= <unscoped-template-name> <template-args>
@@ -603,7 +837,7 @@
     while (!DC->isNamespace() && !DC->isTranslationUnit())
       DC = getEffectiveParentContext(DC);
   else if (GetLocalClassDecl(ND)) {
-    mangleLocalName(ND);
+    mangleLocalName(ND, AdditionalAbiTags);
     return;
   }
 
@@ -613,76 +847,88 @@
     // Check if we have a template.
     const TemplateArgumentList *TemplateArgs = nullptr;
     if (const TemplateDecl *TD = isTemplate(ND, TemplateArgs)) {
-      mangleUnscopedTemplateName(TD);
+      mangleUnscopedTemplateName(TD, AdditionalAbiTags);
       mangleTemplateArgs(*TemplateArgs);
       return;
     }
 
-    mangleUnscopedName(ND);
+    mangleUnscopedName(ND, AdditionalAbiTags);
     return;
   }
 
   if (isLocalContainerContext(DC)) {
-    mangleLocalName(ND);
+    mangleLocalName(ND, AdditionalAbiTags);
     return;
   }
 
-  mangleNestedName(ND, DC);
+  mangleNestedName(ND, DC, AdditionalAbiTags);
 }
-void CXXNameMangler::mangleName(const TemplateDecl *TD,
-                                const TemplateArgument *TemplateArgs,
-                                unsigned NumTemplateArgs) {
+
+void CXXNameMangler::mangleTemplateName(const TemplateDecl *TD,
+                                        const TemplateArgument *TemplateArgs,
+                                        unsigned NumTemplateArgs) {
   const DeclContext *DC = IgnoreLinkageSpecDecls(getEffectiveDeclContext(TD));
 
   if (DC->isTranslationUnit() || isStdNamespace(DC)) {
-    mangleUnscopedTemplateName(TD);
+    mangleUnscopedTemplateName(TD, nullptr);
     mangleTemplateArgs(TemplateArgs, NumTemplateArgs);
   } else {
     mangleNestedName(TD, 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) {
+  assert(!AdditionalAbiTags || AdditionalAbiTags->empty());
   //     <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");
     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) {
+  assert(!AdditionalAbiTags || AdditionalAbiTags->empty());
   //     <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");
+
   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);
 }
 
@@ -840,15 +1086,15 @@
                              /*recursive*/ true);
     else
       Out << "sr";
-    mangleSourceName(qualifier->getAsNamespace()->getIdentifier());
+    mangleSourceNameWithAbiTags(qualifier->getAsNamespace());
     break;
   case NestedNameSpecifier::NamespaceAlias:
     if (qualifier->getPrefix())
       mangleUnresolvedPrefix(qualifier->getPrefix(),
                              /*recursive*/ true);
     else
       Out << "sr";
-    mangleSourceName(qualifier->getAsNamespaceAlias()->getIdentifier());
+    mangleSourceNameWithAbiTags(qualifier->getAsNamespaceAlias());
     break;
 
   case NestedNameSpecifier::TypeSpec:
@@ -883,6 +1129,7 @@
       Out << "sr";
 
     mangleSourceName(qualifier->getAsIdentifier());
+    // an Identifier has no type information, so we can't emit abi tags for it
     break;
   }
 
@@ -928,7 +1175,8 @@
 
 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>
@@ -947,6 +1195,7 @@
         Out << 'L';
 
       mangleSourceName(II);
+      writeAbiTags(ND, AdditionalAbiTags);
       break;
     }
 
@@ -986,6 +1235,7 @@
       assert(FD->getIdentifier() && "Data member name isn't an identifier!");
 
       mangleSourceName(FD->getIdentifier());
+      // Not emitting abi tags: internal name anyway
       break;
     }
 
@@ -1006,6 +1256,10 @@
       assert(D->getDeclName().getAsIdentifierInfo() &&
              "Typedef was not named!");
       mangleSourceName(D->getDeclName().getAsIdentifierInfo());
+      assert(!AdditionalAbiTags && "Type cannot have additional abi tags");
+      // explicit abi tags are still possible; take from underlying type, not
+      // from typedef.
+      writeAbiTags(TD, nullptr);
       break;
     }
 
@@ -1015,6 +1269,8 @@
     // <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;
       }
@@ -1026,11 +1282,13 @@
       if (UnnamedMangle > 1)
         Out << UnnamedMangle - 2;
       Out << '_';
+      writeAbiTags(TD, AdditionalAbiTags);
       break;
     }
 
-    // Get a unique id for the anonymous struct.
-    unsigned AnonStructId = Context.getAnonymousStructId(TD);
+    // Get a unique id for the anonymous struct. If it is not a real output
+    // ID doesn't matter so use fake one.
+    unsigned AnonStructId = NullOut ? 0 : Context.getAnonymousStructId(TD);
 
     // Mangle it as a source name in the form
     // [n] $_<id>
@@ -1058,6 +1316,7 @@
       // Otherwise, use the complete constructor name. This is relevant if a
       // class with a constructor is declared within a constructor.
       mangleCXXCtorType(Ctor_Complete);
+    writeAbiTags(ND, AdditionalAbiTags);
     break;
 
   case DeclarationName::CXXDestructorName:
@@ -1069,6 +1328,7 @@
       // Otherwise, use the complete destructor name. This is relevant if a
       // class with a destructor is declared within a destructor.
       mangleCXXDtorType(Dtor_Complete);
+    writeAbiTags(ND, AdditionalAbiTags);
     break;
 
   case DeclarationName::CXXOperatorName:
@@ -1084,6 +1344,7 @@
   case DeclarationName::CXXConversionFunctionName:
   case DeclarationName::CXXLiteralOperatorName:
     mangleOperatorName(Name, Arity);
+    writeAbiTags(ND, AdditionalAbiTags);
     break;
 
   case DeclarationName::CXXUsingDirective:
@@ -1100,6 +1361,7 @@
 
 void CXXNameMangler::mangleNestedName(const NamedDecl *ND,
                                       const DeclContext *DC,
+                                      const AbiTagList *AdditionalAbiTags,
                                       bool NoFunction) {
   // <nested-name> 
   //   ::= N [<CV-qualifiers>] [<ref-qualifier>] <prefix> <unqualified-name> E
@@ -1125,7 +1387,7 @@
   }
   else {
     manglePrefix(DC, NoFunction);
-    mangleUnqualifiedName(ND);
+    mangleUnqualifiedName(ND, AdditionalAbiTags);
   }
 
   Out << 'E';
@@ -1143,7 +1405,8 @@
   Out << 'E';
 }
 
-void CXXNameMangler::mangleLocalName(const Decl *D) {
+void CXXNameMangler::mangleLocalName(const Decl *D,
+                                     const AbiTagList *AdditionalAbiTags) {
   // <local-name> := Z <function encoding> E <entity name> [<discriminator>]
   //              := Z <function encoding> E s [<discriminator>]
   // <local-name> := Z <function encoding> E d [ <parameter number> ] 
@@ -1155,15 +1418,26 @@
 
   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.setUsedAbiTags(LocalAbiTags.getEmittedAbiTags());
+  }
 
   Out << 'E';
 
+  // GCC 5.3.0 doesn't emit derived ABI tags for local names but that seems to
+  // be a bug that is fixed in trunk.
+
   if (RD) {
     // The parameter number is omitted for the last parameter, 0 for the 
     // second-to-last parameter, 1 for the third-to-last parameter, etc. The 
@@ -1188,13 +1462,15 @@
     // Mangle the name relative to the closest enclosing function.
     // equality ok because RD derived from ND above
     if (D == RD)  {
-      mangleUnqualifiedName(RD);
+      mangleUnqualifiedName(RD, AdditionalAbiTags);
     } else if (const BlockDecl *BD = dyn_cast<BlockDecl>(D)) {
       manglePrefix(getEffectiveDeclContext(BD), true /*NoFunction*/);
+      assert(!AdditionalAbiTags && "Block cannot have additional abi tags");
       mangleUnqualifiedBlock(BD);
     } else {
       const NamedDecl *ND = cast<NamedDecl>(D);
-      mangleNestedName(ND, getEffectiveDeclContext(ND), true /*NoFunction*/);
+      mangleNestedName(ND, getEffectiveDeclContext(ND), AdditionalAbiTags,
+                       true /*NoFunction*/);
     }
   } else if (const BlockDecl *BD = dyn_cast<BlockDecl>(D)) {
     // Mangle a block in a default parameter; see above explanation for
@@ -1211,9 +1487,10 @@
       }
     }
 
+    assert(!AdditionalAbiTags && "Block cannot have additional abi tags");
     mangleUnqualifiedBlock(BD);
   } else {
-    mangleUnqualifiedName(cast<NamedDecl>(D));
+    mangleUnqualifiedName(cast<NamedDecl>(D), AdditionalAbiTags);
   }
 
   if (const NamedDecl *ND = dyn_cast<NamedDecl>(RD ? RD : D)) {
@@ -1229,12 +1506,12 @@
 
 void CXXNameMangler::mangleBlockForPrefix(const BlockDecl *Block) {
   if (GetLocalClassDecl(Block)) {
-    mangleLocalName(Block);
+    mangleLocalName(Block, /* AdditionalAbiTags */ nullptr);
     return;
   }
   const DeclContext *DC = getEffectiveDeclContext(Block);
   if (isLocalContainerContext(DC)) {
-    mangleLocalName(Block);
+    mangleLocalName(Block, /* AdditionalAbiTags */ nullptr);
     return;
   }
   manglePrefix(getEffectiveDeclContext(Block));
@@ -1245,10 +1522,10 @@
   if (Decl *Context = Block->getBlockManglingContextDecl()) {
     if ((isa<VarDecl>(Context) || isa<FieldDecl>(Context)) &&
         Context->getDeclContext()->isRecord()) {
-      if (const IdentifierInfo *Name
-            = cast<NamedDecl>(Context)->getIdentifier()) {
-        mangleSourceName(Name);
-        Out << 'M';            
+      const auto *ND = cast<NamedDecl>(Context);
+      if (ND->getIdentifier()) {
+        mangleSourceNameWithAbiTags(ND);
+        Out << 'M';
       }
     }
   }
@@ -1281,7 +1558,7 @@
       if (const IdentifierInfo *Name
             = cast<NamedDecl>(Context)->getIdentifier()) {
         mangleSourceName(Name);
-        Out << 'M';            
+        Out << 'M';
       }
     }
   }
@@ -1368,7 +1645,7 @@
     mangleTemplateArgs(*TemplateArgs);
   } else {
     manglePrefix(getEffectiveDeclContext(ND), NoFunction);
-    mangleUnqualifiedName(ND);
+    mangleUnqualifiedName(ND, nullptr);
   }
 
   addSubstitution(ND);
@@ -1383,19 +1660,19 @@
 
   if (QualifiedTemplateName *Qualified = Template.getAsQualifiedTemplateName())
     manglePrefix(Qualified->getQualifier());
-  
+
   if (OverloadedTemplateStorage *Overloaded
                                       = Template.getAsOverloadedTemplate()) {
     mangleUnqualifiedName(nullptr, (*Overloaded->begin())->getDeclName(),
-                          UnknownArity);
+                          UnknownArity, 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,
@@ -1414,7 +1691,7 @@
     mangleTemplateParameter(TTP->getIndex());
   } else {
     manglePrefix(getEffectiveDeclContext(ND), NoFunction);
-    mangleUnqualifiedName(ND->getTemplatedDecl());
+    mangleUnqualifiedName(ND->getTemplatedDecl(), nullptr);
   }
 
   addSubstitution(ND);
@@ -1549,17 +1826,17 @@
     return true;
 
   case Type::Typedef:
-    mangleSourceName(cast<TypedefType>(Ty)->getDecl()->getIdentifier());
+    mangleSourceNameWithAbiTags(cast<TypedefType>(Ty)->getDecl());
     break;
 
   case Type::UnresolvedUsing:
-    mangleSourceName(
-        cast<UnresolvedUsingType>(Ty)->getDecl()->getIdentifier());
+    mangleSourceNameWithAbiTags(
+        cast<UnresolvedUsingType>(Ty)->getDecl());
     break;
 
   case Type::Enum:
   case Type::Record:
-    mangleSourceName(cast<TagType>(Ty)->getDecl()->getIdentifier());
+    mangleSourceNameWithAbiTags(cast<TagType>(Ty)->getDecl());
     break;
 
   case Type::TemplateSpecialization: {
@@ -1577,7 +1854,7 @@
       if (isa<TemplateTemplateParmDecl>(TD))
         goto unresolvedType;
 
-      mangleSourceName(TD->getIdentifier());
+      mangleSourceNameWithAbiTags(TD);
       break;
     }
 
@@ -1607,8 +1884,8 @@
   }
 
   case Type::InjectedClassName:
-    mangleSourceName(
-        cast<InjectedClassNameType>(Ty)->getDecl()->getIdentifier());
+    mangleSourceNameWithAbiTags(
+        cast<InjectedClassNameType>(Ty)->getDecl());
     break;
 
   case Type::DependentName:
@@ -1659,8 +1936,6 @@
   }
 }
 
-
-
 void
 CXXNameMangler::mangleOperatorName(OverloadedOperatorKind OO, unsigned Arity) {
   switch (OO) {
@@ -2088,7 +2363,9 @@
   case BuiltinType::Id:
 #include "clang/AST/BuiltinTypes.def"
   case BuiltinType::Dependent:
-    llvm_unreachable("mangling a placeholder type");
+    if (!NullOut)
+      llvm_unreachable("mangling a placeholder type");
+    break;
   case BuiltinType::ObjCId:
     Out << "11objc_object";
     break;
@@ -2620,7 +2897,7 @@
 
 void CXXNameMangler::mangleType(const TemplateSpecializationType *T) {
   if (TemplateDecl *TD = T->getTemplateName().getAsTemplateDecl()) {
-    mangleName(TD, T->getArgs(), T->getNumArgs());
+    mangleTemplateName(TD, T->getArgs(), T->getNumArgs());
   } else {
     if (mangleSubstitution(QualType(T, 0)))
       return;
@@ -2946,12 +3223,14 @@
   case Expr::PseudoObjectExprClass:
   case Expr::AtomicExprClass:
   {
-    // As bad as this diagnostic is, it's better than crashing.
-    DiagnosticsEngine &Diags = Context.getDiags();
-    unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
-                                     "cannot yet mangle expression type %0");
-    Diags.Report(E->getExprLoc(), DiagID)
-      << E->getStmtClassName() << E->getSourceRange();
+    if (!NullOut) {
+      // As bad as this diagnostic is, it's better than crashing.
+      DiagnosticsEngine &Diags = Context.getDiags();
+      unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
+                                       "cannot yet mangle expression type %0");
+      Diags.Report(E->getExprLoc(), DiagID)
+        << E->getStmtClassName() << E->getSourceRange();
+    }
     break;
   }
 
@@ -4094,6 +4373,48 @@
   Substitutions[Ptr] = SeqID++;
 }
 
+CXXNameMangler::AbiTagSet
+CXXNameMangler::makeFunctionReturnTypeTags(const FunctionDecl *FD) {
+  // When derived abi tags are disabled there is no need to make any list.
+  if (DisableDerivedAbiTags)
+    return AbiTagSet();
+
+  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();
+
+  return TrackReturnTypeTags.AbiTagsRoot.getUsedAbiTags();
+}
+
+CXXNameMangler::AbiTagSet
+CXXNameMangler::makeVariableTypeTags(const VarDecl *VD) {
+  // When derived abi tags are disabled there is no need to make any list.
+  if (DisableDerivedAbiTags)
+    return AbiTagSet();
+
+  llvm::raw_null_ostream NullOutStream;
+  CXXNameMangler TrackVariableType(*this, NullOutStream);
+  TrackVariableType.disableDerivedAbiTags();
+
+  TrackVariableType.mangleType(VD->getType());
+
+  return TrackVariableType.AbiTagsRoot.getUsedAbiTags();
+}
+
+bool CXXNameMangler::shouldHaveAbiTags(ItaniumMangleContextImpl &C,
+                                       const VarDecl *VD) {
+  llvm::raw_null_ostream NullOutStream;
+  CXXNameMangler TrackAbiTags(C, NullOutStream, nullptr, true);
+  TrackAbiTags.mangle(VD);
+  return TrackAbiTags.AbiTagsRoot.getUsedAbiTags().size();
+}
+
 //
 
 /// Mangles the name of the declaration D and emits that name to the given
@@ -4195,6 +4516,8 @@
   //  <special-name> ::= GV <object name>       # Guard variable for one-time
   //                                            # initialization
   CXXNameMangler Mangler(*this, Out);
+  // GCC 5.3.0 doesn't emit derived ABI tags for local names but that seems to
+  // be a bug that is fixed in trunk.
   Mangler.getStream() << "_ZGV";
   Mangler.mangleName(D);
 }
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to