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