Updated patch according to comments

http://reviews.llvm.org/D6295

Files:
  include/clang/AST/Decl.h
  lib/AST/Decl.cpp
  lib/AST/ItaniumCXXABI.cpp
  lib/AST/ItaniumMangle.cpp
  test/CodeGenCXX/mangle-local-anonymous-unions.cpp
Index: include/clang/AST/Decl.h
===================================================================
--- include/clang/AST/Decl.h
+++ include/clang/AST/Decl.h
@@ -3274,6 +3274,10 @@
   /// intra-object-overflow bugs.
   bool mayInsertExtraPadding(bool EmitRemark = false) const;
 
+  /// Finds the first data member which has a name.
+  /// nullptr is returned if no named data member exists.
+  const FieldDecl *findFirstNamedDataMember() const;
+
 private:
   /// \brief Deserialize just the fields.
   void LoadFieldsFromExternalStorage() const;
Index: lib/AST/Decl.cpp
===================================================================
--- lib/AST/Decl.cpp
+++ lib/AST/Decl.cpp
@@ -3667,6 +3667,22 @@
   return ReasonToReject < 0;
 }
 
+const FieldDecl *RecordDecl::findFirstNamedDataMember() const {
+  for (const auto *I : fields()) {
+    if (I->getIdentifier())
+      return I;
+
+    if (const RecordType *RT = I->getType()->getAs<RecordType>())
+      if (const FieldDecl *NamedDataMember =
+          RT->getDecl()->findFirstNamedDataMember())
+        return NamedDataMember;
+  }
+
+  // We didn't find a named data member.
+  return nullptr;
+}
+
+
 //===----------------------------------------------------------------------===//
 // BlockDecl Implementation
 //===----------------------------------------------------------------------===//
Index: lib/AST/ItaniumCXXABI.cpp
===================================================================
--- lib/AST/ItaniumCXXABI.cpp
+++ lib/AST/ItaniumCXXABI.cpp
@@ -33,8 +33,8 @@
 /// literals within a particular context.
 class ItaniumNumberingContext : public MangleNumberingContext {
   llvm::DenseMap<const Type *, unsigned> ManglingNumbers;
-  llvm::DenseMap<IdentifierInfo *, unsigned> VarManglingNumbers;
-  llvm::DenseMap<IdentifierInfo *, unsigned> TagManglingNumbers;
+  llvm::DenseMap<const IdentifierInfo *, unsigned> VarManglingNumbers;
+  llvm::DenseMap<const IdentifierInfo *, unsigned> TagManglingNumbers;
 
 public:
   unsigned getManglingNumber(const CXXMethodDecl *CallOperator) override {
@@ -60,7 +60,18 @@
 
   /// Variable decls are numbered by identifier.
   unsigned getManglingNumber(const VarDecl *VD, unsigned) override {
-    return ++VarManglingNumbers[VD->getIdentifier()];
+    const IdentifierInfo *Identifier = VD->getIdentifier();
+    if (!Identifier) {
+      if (const RecordType *RT = VD->getType()->getAs<RecordType>()) {
+        const RecordDecl *RD = RT->getDecl();
+        if (RD->isUnion()) {
+          if (const FieldDecl *FD = RD->findFirstNamedDataMember()) {
+            Identifier = FD->getIdentifier();
+          }
+        }
+      }
+    }
+    return ++VarManglingNumbers[Identifier];
   }
 
   unsigned getManglingNumber(const TagDecl *TD, unsigned) override {
Index: lib/AST/ItaniumMangle.cpp
===================================================================
--- lib/AST/ItaniumMangle.cpp
+++ lib/AST/ItaniumMangle.cpp
@@ -115,9 +115,11 @@
 
 class ItaniumMangleContextImpl : public ItaniumMangleContext {
   typedef std::pair<const DeclContext*, IdentifierInfo*> DiscriminatorKeyTy;
-  llvm::DenseMap<DiscriminatorKeyTy, unsigned> Discriminator;
+  llvm::DenseMap<DiscriminatorKeyTy, unsigned> Discriminators;
   llvm::DenseMap<const NamedDecl*, unsigned> Uniquifier;
-  
+private:
+  unsigned uniquifyNamedDecl(const NamedDecl *ND);
+
 public:
   explicit ItaniumMangleContextImpl(ASTContext &Context,
                                     DiagnosticsEngine &Diags)
@@ -162,37 +164,7 @@
 
   void mangleStringLiteral(const StringLiteral *, raw_ostream &) override;
 
-  bool getNextDiscriminator(const NamedDecl *ND, unsigned &disc) {
-    // Lambda closure types are already numbered.
-    if (isLambda(ND))
-      return false;
-
-    // Anonymous tags are already numbered.
-    if (const TagDecl *Tag = dyn_cast<TagDecl>(ND)) {
-      if (Tag->getName().empty() && !Tag->getTypedefNameForAnonDecl())
-        return false;
-    }
-
-    // Use the canonical number for externally visible decls.
-    if (ND->isExternallyVisible()) {
-      unsigned discriminator = getASTContext().getManglingNumber(ND);
-      if (discriminator == 1)
-        return false;
-      disc = discriminator - 2;
-      return true;
-    }
-
-    // Make up a reasonable number for internal decls.
-    unsigned &discriminator = Uniquifier[ND];
-    if (!discriminator) {
-      const DeclContext *DC = getEffectiveDeclContext(ND);
-      discriminator = ++Discriminator[std::make_pair(DC, ND->getIdentifier())];
-    }
-    if (discriminator == 1)
-      return false;
-    disc = discriminator-2;
-    return true;
-  }
+  bool getNextDiscriminator(const NamedDecl *ND, unsigned &disc);
   /// @}
 };
 
@@ -1050,24 +1022,6 @@
   mangleUnqualifiedName(nullptr, name, knownArity);
 }
 
-static const FieldDecl *FindFirstNamedDataMember(const RecordDecl *RD) {
-  assert(RD->isAnonymousStructOrUnion() &&
-         "Expected anonymous struct or union!");
-  
-  for (const auto *I : RD->fields()) {
-    if (I->getIdentifier())
-      return I;
-    
-    if (const RecordType *RT = I->getType()->getAs<RecordType>())
-      if (const FieldDecl *NamedDataMember = 
-          FindFirstNamedDataMember(RT->getDecl()))
-        return NamedDataMember;
-  }
-
-  // We didn't find a named data member.
-  return nullptr;
-}
-
 void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND,
                                            DeclarationName Name,
                                            unsigned KnownArity) {
@@ -1104,9 +1058,9 @@
 
     if (const VarDecl *VD = dyn_cast<VarDecl>(ND)) {
       // We must have an anonymous union or struct declaration.
-      const RecordDecl *RD = 
+      const RecordDecl *RD =
         cast<RecordDecl>(VD->getType()->getAs<RecordType>()->getDecl());
-      
+
       // Itanium C++ ABI 5.1.2:
       //
       //   For the purposes of mangling, the name of an anonymous union is
@@ -1116,14 +1070,16 @@
       //   the data members in the union are unnamed), then there is no way for
       //   a program to refer to the anonymous union, and there is therefore no
       //   need to mangle its name.
-      const FieldDecl *FD = FindFirstNamedDataMember(RD);
+      assert(RD->isAnonymousStructOrUnion()
+             && "Expected anonymous struct or union!");
+      const FieldDecl *FD = RD->findFirstNamedDataMember();
 
       // It's actually possible for various reasons for us to get here
       // with an empty anonymous struct / union.  Fortunately, it
       // doesn't really matter what name we generate.
       if (!FD) break;
       assert(FD->getIdentifier() && "Data member name isn't an identifier!");
-      
+
       mangleSourceName(FD->getIdentifier());
       break;
     }
@@ -3745,7 +3701,7 @@
                                  "Mangling declaration");
 
   CXXNameMangler Mangler(*this, Out, D);
-  return Mangler.mangle(D);
+  Mangler.mangle(D);
 }
 
 void ItaniumMangleContextImpl::mangleCXXCtor(const CXXConstructorDecl *D,
@@ -3934,3 +3890,64 @@
 ItaniumMangleContext::create(ASTContext &Context, DiagnosticsEngine &Diags) {
   return new ItaniumMangleContextImpl(Context, Diags);
 }
+
+static bool isDiscriminatorNeeded(const NamedDecl *ND) {
+  // Lambda closure types are already numbered.
+  if (isLambda(ND))
+    return false;
+
+  // Anonymous tags are already numbered.
+  if (const TagDecl *Tag = dyn_cast<TagDecl>(ND)) {
+    if (Tag->getName().empty() && !Tag->getTypedefNameForAnonDecl())
+      return false;
+  }
+
+  if (const VarDecl *VD = dyn_cast<VarDecl>(ND)) {
+      return VD->isStaticLocal() || VD->isExternallyVisible();
+  }
+
+  return true;
+}
+
+unsigned ItaniumMangleContextImpl::uniquifyNamedDecl(const NamedDecl *ND) {
+  IdentifierInfo *Identifier = ND->getIdentifier();
+  if (!Identifier) {
+    if (const VarDecl *VD = dyn_cast<VarDecl>(ND)) {
+      if (const RecordType *RT = VD->getType()->getAs<RecordType>()) {
+        const RecordDecl *RD = RT->getDecl();
+        if (RD->isUnion()) {
+          if (const FieldDecl *FD = RD->findFirstNamedDataMember()) {
+            Identifier = FD->getIdentifier();
+          }
+        }
+      }
+    }
+  }
+  unsigned &Discriminator = Uniquifier[ND];
+  assert(!Discriminator && "NameDecl has already been uniquified.");
+  const DeclContext *DC = getEffectiveDeclContext(ND);
+  Discriminator = ++Discriminators[std::make_pair(DC, Identifier)];
+  return Discriminator;
+}
+
+bool ItaniumMangleContextImpl::getNextDiscriminator(const NamedDecl *ND,
+                                                unsigned &disc) {
+  if (!isDiscriminatorNeeded(ND))
+    return false;
+
+  unsigned Discriminator = 0;
+  // Use the canonical number for externally visible decls.
+  if (ND->isExternallyVisible()) {
+    Discriminator = getASTContext().getManglingNumber(ND);
+  } else {
+    Discriminator = Uniquifier[ND];
+    if (!Discriminator) {
+      Discriminator = uniquifyNamedDecl(ND);
+    }
+  }
+  if (Discriminator <= 1)
+    return false;
+  disc = Discriminator-2;
+  return true;
+}
+
Index: test/CodeGenCXX/mangle-local-anonymous-unions.cpp
===================================================================
--- test/CodeGenCXX/mangle-local-anonymous-unions.cpp
+++ test/CodeGenCXX/mangle-local-anonymous-unions.cpp
@@ -0,0 +1,51 @@
+// RUN: %clang_cc1 %s -emit-llvm -triple %itanium_abi_triple -o - | FileCheck %s
+
+// CHECK-DAG: @_ZZ2f0vE1a
+// CHECK-DAG: @_ZZ2f0vE1c
+// CHECK-DAG: @_ZZ2f0vE1e_0
+inline int f0() {
+  static union {
+    int a;
+    long int b;
+  };
+
+  static union {
+    int c;
+    double d;
+  };
+
+  if (0) {
+    static union {
+      int e;
+      int f;
+    };
+  }
+  static union {
+    int e;
+    int f;
+  };
+
+  return a+c;
+}
+
+// CHECK-DAG: @_ZZ2f1vE1a
+// CHECK-DAG: @_ZZ2f1vE1c
+// CHECK-DAG: @_ZZ2f1vE1c_0
+// CHECK-DAG: @_ZZ2f1vE1c_1
+int f1 () {
+  static union {
+    int a;
+    long int b;
+  };
+
+  static union {
+    int c;
+    double d;
+  };
+
+  { static int c; }
+  { static int c; }
+
+  return a+c+f0();
+}
+
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to