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()) + 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 ManglingNumbers; - llvm::DenseMap VarManglingNumbers; - llvm::DenseMap TagManglingNumbers; + llvm::DenseMap VarManglingNumbers; + llvm::DenseMap 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()) { + 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 DiscriminatorKeyTy; - llvm::DenseMap Discriminator; + llvm::DenseMap Discriminators; llvm::DenseMap 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(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()) - 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(ND)) { // We must have an anonymous union or struct declaration. - const RecordDecl *RD = + const RecordDecl *RD = cast(VD->getType()->getAs()->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(ND)) { + if (Tag->getName().empty() && !Tag->getTypedefNameForAnonDecl()) + return false; + } + + if (const VarDecl *VD = dyn_cast(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(ND)) { + if (const RecordType *RT = VD->getType()->getAs()) { + 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(); +} +