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 <rdar://problem/14204721>.
llvm-svn: 185986
diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h
index 7c2cea2..f0b0e41 100644
--- a/clang/include/clang/AST/ASTContext.h
+++ b/clang/include/clang/AST/ASTContext.h
@@ -344,8 +344,9 @@
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 @@
/// 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 35c2abd..4f81e0c 100644
--- a/clang/include/clang/AST/MangleNumberingContext.h
+++ b/clang/include/clang/AST/MangleNumberingContext.h
@@ -23,22 +23,35 @@
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 1d780de..6345989 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -716,7 +716,7 @@
/// \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 7f02f59..933e5e0 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -7990,24 +7990,19 @@
+ 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 7921982..2dc44eb 100644
--- a/clang/lib/AST/ItaniumMangle.cpp
+++ b/clang/lib/AST/ItaniumMangle.cpp
@@ -99,7 +99,8 @@
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 @@
return Result.first->second;
}
- void startNewFunction() {
- MangleContext::startNewFunction();
- mangleInitDiscriminator();
- }
-
/// @name Mangler Entry Points
/// @{
@@ -153,21 +149,33 @@
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 @@
}
}
- 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 @@
// <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 @@
if (Num > 1)
mangleNumber(Num - 2);
Out << '_';
- SkipDiscriminator = true;
}
}
}
@@ -1328,24 +1334,21 @@
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 << '_';
- }
- }
-
- return;
+ } else {
+ if (const BlockDecl *BD = dyn_cast<BlockDecl>(D))
+ mangleUnqualifiedBlock(BD);
+ else
+ mangleUnqualifiedName(cast<NamedDecl>(D));
}
-
- 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 << '_';
+ }
+ }
}
void CXXNameMangler::mangleBlockForPrefix(const BlockDecl *Block) {
diff --git a/clang/lib/AST/MangleNumberingContext.cpp b/clang/lib/AST/MangleNumberingContext.cpp
index a4c8a27..4e9006e 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 @@
}
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 3f85de5..5e535da 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -3043,6 +3043,27 @@
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 @@
}
if (Tag) {
- getASTContext().addUnnamedTag(Tag);
+ HandleTagNumbering(*this, Tag);
Tag->setFreeStanding();
if (Tag->isInvalidDecl())
return Tag;
@@ -5120,6 +5141,15 @@
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 @@
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 1e6ef9b..8351ff2 100644
--- a/clang/lib/Sema/SemaLambda.cpp
+++ b/clang/lib/Sema/SemaLambda.cpp
@@ -53,7 +53,7 @@
}
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 4aba1b3..cc4e090 100644
--- a/clang/test/CodeGenCXX/linkage.cpp
+++ b/clang/test/CodeGenCXX/linkage.cpp
@@ -12,7 +12,7 @@
}
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 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 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 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 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 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 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 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 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 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 c3ea31a..186d76a 100644
--- a/clang/test/CodeGenCXX/mangle-local-class-names.cpp
+++ b/clang/test/CodeGenCXX/mangle-local-class-names.cpp
@@ -55,6 +55,26 @@
}
}
+// 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 @@
};
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 5f31e54..4b60122 100644
--- a/clang/test/CodeGenCXX/mangle.cpp
+++ b/clang/test/CodeGenCXX/mangle.cpp
@@ -888,7 +888,7 @@
}
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 @@
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(); }
+}