From: Eli Friedman Date: Wed, 10 Jul 2013 00:30:46 +0000 (+0000) Subject: More local mangling fixes. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=5e867c8a07d82da0d3b0a43402ee4f1c6ba416e9;p=clang More local mangling fixes. Compute mangling numbers for externally visible local variables and tags. Change the mangler to consistently use discriminators where necessary. Tweak the scheme we use to number decls which are not externally visible to avoid unnecessary discriminators in common cases now that we request them more consistently. Fixes . git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@185986 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index 7c2cea25cc..f0b0e41bd0 100644 --- a/include/clang/AST/ASTContext.h +++ b/include/clang/AST/ASTContext.h @@ -344,8 +344,9 @@ class ASTContext : public RefCountedBase { llvm::DenseMap MangleNumberingContexts; - llvm::DenseMap UnnamedMangleContexts; - llvm::DenseMap UnnamedMangleNumbers; + /// \brief Side-table of mangling numbers for declarations which rarely + /// need them (like static local vars). + llvm::DenseMap MangleNumbers; /// \brief Mapping that stores parameterIndex values for ParmVarDecls when /// that value exceeds the bitfield size of ParmVarDeclBits.ParameterIndex. @@ -2086,12 +2087,12 @@ public: /// it is not used. bool DeclMustBeEmitted(const Decl *D); - void addUnnamedTag(const TagDecl *Tag); - int getUnnamedTagManglingNumber(const TagDecl *Tag) const; + void setManglingNumber(const NamedDecl *ND, unsigned Number); + unsigned getManglingNumber(const NamedDecl *ND) const; /// \brief Retrieve the context for computing mangling numbers in the given /// DeclContext. - MangleNumberingContext &getManglingNumberContext(DeclContext *DC); + MangleNumberingContext &getManglingNumberContext(const DeclContext *DC); /// \brief Used by ParmVarDecl to store on the side the /// index of the parameter when it exceeds the size of the normal bitfield. diff --git a/include/clang/AST/MangleNumberingContext.h b/include/clang/AST/MangleNumberingContext.h index 35c2abd9d8..4f81e0c554 100644 --- a/include/clang/AST/MangleNumberingContext.h +++ b/include/clang/AST/MangleNumberingContext.h @@ -23,22 +23,35 @@ namespace clang { class BlockDecl; class CXXMethodDecl; +class IdentifierInfo; +class TagDecl; class Type; +class VarDecl; /// \brief Keeps track of the mangled names of lambda expressions and block /// literals within a particular context. class MangleNumberingContext : public RefCountedBase { llvm::DenseMap ManglingNumbers; - + llvm::DenseMap VarManglingNumbers; + llvm::DenseMap TagManglingNumbers; + public: /// \brief Retrieve the mangling number of a new lambda expression with the /// given call operator within this context. - unsigned getManglingNumber(CXXMethodDecl *CallOperator); + unsigned getManglingNumber(const CXXMethodDecl *CallOperator); /// \brief Retrieve the mangling number of a new block literal within this /// context. - unsigned getManglingNumber(BlockDecl *BD); + unsigned getManglingNumber(const BlockDecl *BD); + + /// \brief Retrieve the mangling number of a static local variable within + /// this context. + unsigned getManglingNumber(const VarDecl *VD); + + /// \brief Retrieve the mangling number of a static local variable within + /// this context. + unsigned getManglingNumber(const TagDecl *TD); }; } // end namespace clang diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index 1d780def42..6345989f16 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -716,7 +716,7 @@ public: /// \param[out] ManglingContextDecl - Returns the ManglingContextDecl /// associated with the context, if relevant. MangleNumberingContext *getCurrentMangleNumberContext( - DeclContext *DC, + const DeclContext *DC, Decl *&ManglingContextDecl); diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index 7f02f59c68..933e5e057e 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -7990,24 +7990,19 @@ size_t ASTContext::getSideTableAllocatedMemory() const { + llvm::capacity_in_bytes(ClassScopeSpecializationPattern); } -void ASTContext::addUnnamedTag(const TagDecl *Tag) { - // FIXME: This mangling should be applied to function local classes too - if (!Tag->getName().empty() || Tag->getTypedefNameForAnonDecl() || - !isa(Tag->getParent())) - return; - - std::pair::iterator, bool> P = - UnnamedMangleContexts.insert(std::make_pair(Tag->getParent(), 0)); - UnnamedMangleNumbers.insert(std::make_pair(Tag, P.first->second++)); +void ASTContext::setManglingNumber(const NamedDecl *ND, unsigned Number) { + if (Number > 1) + MangleNumbers[ND] = Number; } -int ASTContext::getUnnamedTagManglingNumber(const TagDecl *Tag) const { - llvm::DenseMap::const_iterator I = - UnnamedMangleNumbers.find(Tag); - return I != UnnamedMangleNumbers.end() ? I->second : -1; +unsigned ASTContext::getManglingNumber(const NamedDecl *ND) const { + llvm::DenseMap::const_iterator I = + MangleNumbers.find(ND); + return I != MangleNumbers.end() ? I->second : 1; } -MangleNumberingContext &ASTContext::getManglingNumberContext(DeclContext *DC) { +MangleNumberingContext & +ASTContext::getManglingNumberContext(const DeclContext *DC) { return MangleNumberingContexts[DC]; } diff --git a/lib/AST/ItaniumMangle.cpp b/lib/AST/ItaniumMangle.cpp index 79219825aa..2dc44eb355 100644 --- a/lib/AST/ItaniumMangle.cpp +++ b/lib/AST/ItaniumMangle.cpp @@ -99,7 +99,8 @@ static const unsigned UnknownArity = ~0U; class ItaniumMangleContext : public MangleContext { llvm::DenseMap AnonStructIds; - unsigned Discriminator; + typedef std::pair DiscriminatorKeyTy; + llvm::DenseMap Discriminator; llvm::DenseMap Uniquifier; public: @@ -114,11 +115,6 @@ public: return Result.first->second; } - void startNewFunction() { - MangleContext::startNewFunction(); - mangleInitDiscriminator(); - } - /// @name Mangler Entry Points /// @{ @@ -153,21 +149,33 @@ public: void mangleItaniumThreadLocalInit(const VarDecl *D, raw_ostream &); void mangleItaniumThreadLocalWrapper(const VarDecl *D, raw_ostream &); - void mangleInitDiscriminator() { - Discriminator = 0; - } - bool getNextDiscriminator(const NamedDecl *ND, unsigned &disc) { - // Lambda closure types with external linkage (indicated by a - // non-zero lambda mangling number) have their own numbering scheme, so - // they do not need a discriminator. + // Lambda closure types are already numbered. if (const CXXRecordDecl *RD = dyn_cast(ND)) - if (RD->isLambda() && RD->getLambdaManglingNumber() > 0) + if (RD->isLambda()) 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) - discriminator = ++Discriminator; + if (!discriminator) { + const DeclContext *DC = getEffectiveDeclContext(ND); + discriminator = ++Discriminator[std::make_pair(DC, ND->getIdentifier())]; + } if (discriminator == 1) return false; disc = discriminator-2; @@ -1141,11 +1149,11 @@ void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND, } } - int UnnamedMangle = Context.getASTContext().getUnnamedTagManglingNumber(TD); - if (UnnamedMangle != -1) { + if (TD->isExternallyVisible()) { + unsigned UnnamedMangle = getASTContext().getManglingNumber(TD); Out << "Ut"; - if (UnnamedMangle != 0) - Out << llvm::utostr(UnnamedMangle - 1); + if (UnnamedMangle > 1) + Out << llvm::utostr(UnnamedMangle - 2); Out << '_'; break; } @@ -1300,7 +1308,6 @@ void CXXNameMangler::mangleLocalName(const Decl *D) { // will of course contain a : Its // numbering will be local to the particular argument in which it appears // -- other default arguments do not affect its encoding. - bool SkipDiscriminator = false; const CXXRecordDecl *CXXRD = dyn_cast(RD); if (CXXRD->isLambda()) { if (const ParmVarDecl *Parm @@ -1312,7 +1319,6 @@ void CXXNameMangler::mangleLocalName(const Decl *D) { if (Num > 1) mangleNumber(Num - 2); Out << '_'; - SkipDiscriminator = true; } } } @@ -1328,24 +1334,21 @@ void CXXNameMangler::mangleLocalName(const Decl *D) { const NamedDecl *ND = cast(D); mangleNestedName(ND, getEffectiveDeclContext(ND), true /*NoFunction*/); } - - if (!SkipDiscriminator) { - unsigned disc; - if (Context.getNextDiscriminator(RD, disc)) { - if (disc < 10) - Out << '_' << disc; - else - Out << "__" << disc << '_'; - } + } else { + if (const BlockDecl *BD = dyn_cast(D)) + mangleUnqualifiedBlock(BD); + else + mangleUnqualifiedName(cast(D)); + } + if (const NamedDecl *ND = dyn_cast(RD ? RD : D)) { + unsigned disc; + if (Context.getNextDiscriminator(ND, disc)) { + if (disc < 10) + Out << '_' << disc; + else + Out << "__" << disc << '_'; } - - return; } - - if (const BlockDecl *BD = dyn_cast(D)) - mangleUnqualifiedBlock(BD); - else - mangleUnqualifiedName(cast(D)); } void CXXNameMangler::mangleBlockForPrefix(const BlockDecl *Block) { diff --git a/lib/AST/MangleNumberingContext.cpp b/lib/AST/MangleNumberingContext.cpp index a4c8a27da5..4e9006ec24 100644 --- a/lib/AST/MangleNumberingContext.cpp +++ b/lib/AST/MangleNumberingContext.cpp @@ -19,7 +19,7 @@ using namespace clang; unsigned -MangleNumberingContext::getManglingNumber(CXXMethodDecl *CallOperator) { +MangleNumberingContext::getManglingNumber(const CXXMethodDecl *CallOperator) { const FunctionProtoType *Proto = CallOperator->getType()->getAs(); ASTContext &Context = CallOperator->getASTContext(); @@ -31,8 +31,18 @@ MangleNumberingContext::getManglingNumber(CXXMethodDecl *CallOperator) { } unsigned -MangleNumberingContext::getManglingNumber(BlockDecl *BD) { +MangleNumberingContext::getManglingNumber(const BlockDecl *BD) { // FIXME: Compute a BlockPointerType? Not obvious how. const Type *Ty = 0; return ++ManglingNumbers[Ty]; } + +unsigned +MangleNumberingContext::getManglingNumber(const VarDecl *VD) { + return ++VarManglingNumbers[VD->getIdentifier()]; +} + +unsigned +MangleNumberingContext::getManglingNumber(const TagDecl *TD) { + return ++TagManglingNumbers[TD->getIdentifier()]; +} diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 3f85de5d2c..5e535da19a 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -3043,6 +3043,27 @@ Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, return ParsedFreeStandingDeclSpec(S, AS, DS, MultiTemplateParamsArg()); } +static void HandleTagNumbering(Sema &S, const TagDecl *Tag) { + if (isa(Tag->getParent())) { + // If this tag is the direct child of a class, number it if + // it is anonymous. + if (!Tag->getName().empty() || Tag->getTypedefNameForAnonDecl()) + return; + MangleNumberingContext &MCtx = + S.Context.getManglingNumberContext(Tag->getParent()); + S.Context.setManglingNumber(Tag, MCtx.getManglingNumber(Tag)); + return; + } + + // If this tag isn't a direct child of a class, number it if it is local. + Decl *ManglingContextDecl; + if (MangleNumberingContext *MCtx = + S.getCurrentMangleNumberContext(Tag->getDeclContext(), + ManglingContextDecl)) { + S.Context.setManglingNumber(Tag, MCtx->getManglingNumber(Tag)); + } +} + /// ParsedFreeStandingDeclSpec - This method is invoked when a declspec with /// no declarator (e.g. "struct foo;") is parsed. It also accepts template /// parameters to cope with template friend declarations. @@ -3072,7 +3093,7 @@ Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, } if (Tag) { - getASTContext().addUnnamedTag(Tag); + HandleTagNumbering(*this, Tag); Tag->setFreeStanding(); if (Tag->isInvalidDecl()) return Tag; @@ -5120,6 +5141,15 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC, isIncompleteDeclExternC(*this, NewVD)) RegisterLocallyScopedExternCDecl(NewVD, S); + if (NewVD->isStaticLocal()) { + Decl *ManglingContextDecl; + if (MangleNumberingContext *MCtx = + getCurrentMangleNumberContext(NewVD->getDeclContext(), + ManglingContextDecl)) { + Context.setManglingNumber(NewVD, MCtx->getManglingNumber(NewVD)); + } + } + return NewVD; } @@ -8374,9 +8404,10 @@ Sema::DeclGroupPtrTy Sema::FinalizeDeclaratorGroup(Scope *S, const DeclSpec &DS, if (Decl *D = Group[i]) Decls.push_back(D); - if (DeclSpec::isDeclRep(DS.getTypeSpecType())) + if (DeclSpec::isDeclRep(DS.getTypeSpecType())) { if (const TagDecl *Tag = dyn_cast_or_null(DS.getRepAsDecl())) - getASTContext().addUnnamedTag(Tag); + HandleTagNumbering(*this, Tag); + } return BuildDeclaratorGroup(Decls, DS.containsPlaceholderType()); } diff --git a/lib/Sema/SemaLambda.cpp b/lib/Sema/SemaLambda.cpp index 1e6ef9baf7..8351ff2786 100644 --- a/lib/Sema/SemaLambda.cpp +++ b/lib/Sema/SemaLambda.cpp @@ -53,7 +53,7 @@ static bool isInInlineFunction(const DeclContext *DC) { } MangleNumberingContext * -Sema::getCurrentMangleNumberContext(DeclContext *DC, +Sema::getCurrentMangleNumberContext(const DeclContext *DC, Decl *&ManglingContextDecl) { // Compute the context for allocating mangling numbers in the current // expression, if the ABI requires them. diff --git a/test/CodeGenCXX/linkage.cpp b/test/CodeGenCXX/linkage.cpp index 4aba1b3282..cc4e0909c2 100644 --- a/test/CodeGenCXX/linkage.cpp +++ b/test/CodeGenCXX/linkage.cpp @@ -12,7 +12,7 @@ namespace test1 { } namespace test2 { - // CHECK-DAG: define internal void @_ZN5test21fIZNS_L1gEvE1S_0EEvT_( + // CHECK-DAG: define internal void @_ZN5test21fIZNS_L1gEvE1SEEvT_( template void f(T) {} static inline void *g() { struct S { @@ -46,7 +46,7 @@ namespace test4 { } namespace test5 { - // CHECK-DAG: define linkonce_odr void @_ZN5test51fIZNS_1gILi1EEEPvvE1S_1EEvT_( + // CHECK-DAG: define linkonce_odr void @_ZN5test51fIZNS_1gILi1EEEPvvE1SEEvT_( template void f(T) {} template inline void *g() { struct S { @@ -58,7 +58,7 @@ namespace test5 { } namespace test6 { - // CHECK-DAG: define linkonce_odr void @_ZN5test61fIZZNS_1gEvEN1S1hE_2vE1T_3EEvv( + // CHECK-DAG: define linkonce_odr void @_ZN5test61fIZZNS_1gEvEN1S1hEvE1TEEvv( template void f() {} inline void *g() { @@ -76,7 +76,7 @@ namespace test6 { } namespace test7 { - // CHECK-DAG: define internal void @_ZN5test71fIZZNS_1gEvEN1S1hEvE1T_4EEvv( + // CHECK-DAG: define internal void @_ZN5test71fIZZNS_1gEvEN1S1hEvE1TEEvv( template void f() {} void *g() { @@ -105,7 +105,7 @@ namespace test8 { } namespace test9 { - // CHECK-DAG: define linkonce_odr void @_ZN5test91fIPZNS_1gEvE1S_5EEvT_( + // CHECK-DAG: define linkonce_odr void @_ZN5test91fIPZNS_1gEvE1SEEvT_( template void f(T) {} inline void *g() { struct S { @@ -116,7 +116,7 @@ namespace test9 { } namespace test10 { - // CHECK-DAG: define linkonce_odr void @_ZN6test101fIPFZNS_1gEvE1S_6vEEEvT_( + // CHECK-DAG: define linkonce_odr void @_ZN6test101fIPFZNS_1gEvE1SvEEEvT_( template void f(T) {} inline void *g() { struct S { @@ -128,7 +128,7 @@ namespace test10 { } namespace test11 { - // CHECK-DAG: define internal void @_ZN6test111fIPFZNS_1gEvE1S_7PNS_12_GLOBAL__N_11IEEEEvT_( + // CHECK-DAG: define internal void @_ZN6test111fIPFZNS_1gEvE1SPNS_12_GLOBAL__N_11IEEEEvT_( namespace { struct I { }; @@ -172,7 +172,7 @@ namespace test13 { } namespace test14 { - // CHECK-DAG: define linkonce_odr void @_ZN6test143fooIZNS_1fEvE1S_8E3barILPS1_0EEEvv( + // CHECK-DAG: define linkonce_odr void @_ZN6test143fooIZNS_1fEvE1SE3barILPS1_0EEEvv( template struct foo { template static void bar() {} static void *g() { return (void *)bar; } @@ -186,7 +186,7 @@ namespace test14 { } namespace test15 { - // CHECK-DAG: define linkonce_odr void @_ZN6test153zedIZNS_3fooIiEEPvvE3bar_9EEvv( + // CHECK-DAG: define linkonce_odr void @_ZN6test153zedIZNS_3fooIiEEPvvE3barEEvv( template void zed() {} template void *foo() { class bar { @@ -197,7 +197,7 @@ namespace test15 { } namespace test16 { - // CHECK-DAG: define linkonce_odr void @_ZN6test163zedIZNS_3fooIiE3barEvE1S__10_EEvv( + // CHECK-DAG: define linkonce_odr void @_ZN6test163zedIZNS_3fooIiE3barEvE1SEEvv( template void zed() {} template struct foo { static void *bar(); diff --git a/test/CodeGenCXX/mangle-local-class-names.cpp b/test/CodeGenCXX/mangle-local-class-names.cpp index c3ea31a54c..186d76a225 100644 --- a/test/CodeGenCXX/mangle-local-class-names.cpp +++ b/test/CodeGenCXX/mangle-local-class-names.cpp @@ -55,6 +55,26 @@ void GORF (float IVAR1) } } +// CHECK: @_ZZ12OmittingCodefEN4SSSSC1E_0RKf +inline void OmittingCode(float x) { + if (0) { + struct SSSS { + float bv; + SSSS(const float& from): bv(from) { } + }; + + SSSS VAR1(x); + } + + struct SSSS { + float bv; + SSSS(const float& from): bv(from) { } + }; + + SSSS VAR2(x); +} +void CallOmittingCode() { OmittingCode(1); } + // CHECK: @_ZZ25LocalTemplateFunctionTestdEN5Local3fooIdEET_S1_ int LocalTemplateFunctionTest(double d) { struct Local { @@ -64,3 +84,14 @@ int LocalTemplateFunctionTest(double d) { }; return Local().foo(d); } + +// CHECK: @_ZZ15LocalAnonStructvENUt0_1gEv +inline void LocalAnonStruct() { + if (0) { + struct { void f() {} } x; + x.f(); + } + struct { void g() {} } y; + y.g(); +} +void CallLocalAnonStruct() { LocalAnonStruct(); } diff --git a/test/CodeGenCXX/mangle.cpp b/test/CodeGenCXX/mangle.cpp index 5f31e5480d..4b601229d3 100644 --- a/test/CodeGenCXX/mangle.cpp +++ b/test/CodeGenCXX/mangle.cpp @@ -888,7 +888,7 @@ namespace test38 { } namespace test39 { - // CHECK: define internal void @"_ZN6test394funcINS_3$_0Ut_EEEvT_" + // CHECK: define internal void @"_ZN6test394funcINS_3$_03$_1EEEvT_" typedef struct { struct {} a; } *foo; @@ -897,3 +897,16 @@ namespace test39 { func(x->a); } } + +namespace test40 { + // CHECK: i32* @_ZZN6test401fEvE1a_0 + void h(int&); + inline void f() { + if (0) { + static int a; + } + static int a; + h(a); + }; + void g() { f(); } +}