diff options
Diffstat (limited to 'clang')
-rw-r--r-- | clang/include/clang/AST/ASTContext.h | 11 | ||||
-rw-r--r-- | clang/include/clang/AST/MangleNumberingContext.h | 19 | ||||
-rw-r--r-- | clang/include/clang/Sema/Sema.h | 2 | ||||
-rw-r--r-- | clang/lib/AST/ASTContext.cpp | 23 | ||||
-rw-r--r-- | clang/lib/AST/ItaniumMangle.cpp | 81 | ||||
-rw-r--r-- | clang/lib/AST/MangleNumberingContext.cpp | 14 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 37 | ||||
-rw-r--r-- | clang/lib/Sema/SemaLambda.cpp | 2 | ||||
-rw-r--r-- | clang/test/CodeGenCXX/linkage.cpp | 20 | ||||
-rw-r--r-- | clang/test/CodeGenCXX/mangle-local-class-names.cpp | 31 | ||||
-rw-r--r-- | clang/test/CodeGenCXX/mangle.cpp | 15 |
11 files changed, 176 insertions, 79 deletions
diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h index 7c2cea25cce..f0b0e41bd0f 100644 --- a/clang/include/clang/AST/ASTContext.h +++ b/clang/include/clang/AST/ASTContext.h @@ -344,8 +344,9 @@ class ASTContext : public RefCountedBase<ASTContext> { llvm::DenseMap<const DeclContext *, MangleNumberingContext> MangleNumberingContexts; - llvm::DenseMap<const DeclContext *, unsigned> UnnamedMangleContexts; - llvm::DenseMap<const TagDecl *, unsigned> UnnamedMangleNumbers; + /// \brief Side-table of mangling numbers for declarations which rarely + /// need them (like static local vars). + llvm::DenseMap<const NamedDecl *, unsigned> 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/clang/include/clang/AST/MangleNumberingContext.h b/clang/include/clang/AST/MangleNumberingContext.h index 35c2abd9d84..4f81e0c5548 100644 --- a/clang/include/clang/AST/MangleNumberingContext.h +++ b/clang/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<MangleNumberingContext> { llvm::DenseMap<const Type *, unsigned> ManglingNumbers; - + llvm::DenseMap<IdentifierInfo*, unsigned> VarManglingNumbers; + llvm::DenseMap<IdentifierInfo*, unsigned> 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/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 1d780def42d..6345989f160 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/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/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 7f02f59c683..933e5e057ee 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/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<CXXRecordDecl>(Tag->getParent())) - return; - - std::pair<llvm::DenseMap<const DeclContext *, unsigned>::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 TagDecl *, unsigned>::const_iterator I = - UnnamedMangleNumbers.find(Tag); - return I != UnnamedMangleNumbers.end() ? I->second : -1; +unsigned ASTContext::getManglingNumber(const NamedDecl *ND) const { + llvm::DenseMap<const NamedDecl *, unsigned>::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/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp index 79219825aae..2dc44eb3555 100644 --- a/clang/lib/AST/ItaniumMangle.cpp +++ b/clang/lib/AST/ItaniumMangle.cpp @@ -99,7 +99,8 @@ static const unsigned UnknownArity = ~0U; class ItaniumMangleContext : public MangleContext { llvm::DenseMap<const TagDecl *, uint64_t> AnonStructIds; - unsigned Discriminator; + typedef std::pair<const DeclContext*, IdentifierInfo*> DiscriminatorKeyTy; + llvm::DenseMap<DiscriminatorKeyTy, unsigned> Discriminator; llvm::DenseMap<const NamedDecl*, unsigned> 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<CXXRecordDecl>(ND)) - if (RD->isLambda() && RD->getLambdaManglingNumber() > 0) + if (RD->isLambda()) 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) - 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) { // <entity name> will of course contain a <closure-type-name>: 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<CXXRecordDecl>(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<NamedDecl>(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<BlockDecl>(D)) + mangleUnqualifiedBlock(BD); + else + mangleUnqualifiedName(cast<NamedDecl>(D)); + } + if (const NamedDecl *ND = dyn_cast<NamedDecl>(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<BlockDecl>(D)) - mangleUnqualifiedBlock(BD); - else - mangleUnqualifiedName(cast<NamedDecl>(D)); } void CXXNameMangler::mangleBlockForPrefix(const BlockDecl *Block) { diff --git a/clang/lib/AST/MangleNumberingContext.cpp b/clang/lib/AST/MangleNumberingContext.cpp index a4c8a27da5c..4e9006ec24a 100644 --- a/clang/lib/AST/MangleNumberingContext.cpp +++ b/clang/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<FunctionProtoType>(); 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/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 3f85de5d2c1..5e535da19a1 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/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<CXXRecordDecl>(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<TagDecl>(DS.getRepAsDecl())) - getASTContext().addUnnamedTag(Tag); + HandleTagNumbering(*this, Tag); + } return BuildDeclaratorGroup(Decls, DS.containsPlaceholderType()); } diff --git a/clang/lib/Sema/SemaLambda.cpp b/clang/lib/Sema/SemaLambda.cpp index 1e6ef9baf70..8351ff27869 100644 --- a/clang/lib/Sema/SemaLambda.cpp +++ b/clang/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/clang/test/CodeGenCXX/linkage.cpp b/clang/test/CodeGenCXX/linkage.cpp index 4aba1b32822..cc4e0909c21 100644 --- a/clang/test/CodeGenCXX/linkage.cpp +++ b/clang/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 <typename T> 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 <typename T> void f(T) {} template <int N> 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 <typename T> 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 <typename T> 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 <typename T> 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 <typename T> 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 <typename T> struct foo { template <T *P> static void bar() {} static void *g() { return (void *)bar<nullptr>; } @@ -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 <class T> void zed() {} template <class T> 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 <class T> void zed() {} template <class T> struct foo { static void *bar(); diff --git a/clang/test/CodeGenCXX/mangle-local-class-names.cpp b/clang/test/CodeGenCXX/mangle-local-class-names.cpp index c3ea31a54ca..186d76a225a 100644 --- a/clang/test/CodeGenCXX/mangle-local-class-names.cpp +++ b/clang/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/clang/test/CodeGenCXX/mangle.cpp b/clang/test/CodeGenCXX/mangle.cpp index 5f31e5480d2..4b601229d34 100644 --- a/clang/test/CodeGenCXX/mangle.cpp +++ b/clang/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(); } +} |