forked from OSchip/llvm-project
More fixes for block mangling.
Make sure we properly treat names defined inside a block as local names. There are basically three fixes here. One, correctly treat blocks as a context where we need to use local-name mangling using the new isLocalContainerContext helper. Two, make CXXNameMangler::manglePrefix handle local names in a consistent way. Three, extend CXXNameMangler::mangleLocalName so it can mangle a block correctly. llvm-svn: 185450
This commit is contained in:
parent
43bbdd29de
commit
95f501284a
|
@ -57,17 +57,25 @@ static const DeclContext *getEffectiveDeclContext(const Decl *D) {
|
|||
return ContextParam->getDeclContext();
|
||||
}
|
||||
|
||||
return D->getDeclContext();
|
||||
const DeclContext *DC = D->getDeclContext();
|
||||
if (const CapturedDecl *CD = dyn_cast<CapturedDecl>(DC))
|
||||
return getEffectiveDeclContext(CD);
|
||||
|
||||
return DC;
|
||||
}
|
||||
|
||||
static const DeclContext *getEffectiveParentContext(const DeclContext *DC) {
|
||||
return getEffectiveDeclContext(cast<Decl>(DC));
|
||||
}
|
||||
|
||||
|
||||
static bool isLocalContainerContext(const DeclContext *DC) {
|
||||
return isa<FunctionDecl>(DC) || isa<ObjCMethodDecl>(DC) || isa<BlockDecl>(DC);
|
||||
}
|
||||
|
||||
static const CXXRecordDecl *GetLocalClassDecl(const Decl *D) {
|
||||
const DeclContext *DC = getEffectiveDeclContext(D);
|
||||
while (!DC->isNamespace() && !DC->isTranslationUnit()) {
|
||||
if (isa<FunctionDecl>(DC) || isa<ObjCMethodDecl>(DC) || isa<BlockDecl>(DC))
|
||||
if (isLocalContainerContext(DC))
|
||||
return dyn_cast<CXXRecordDecl>(D);
|
||||
D = cast<Decl>(DC);
|
||||
DC = getEffectiveDeclContext(D);
|
||||
|
@ -306,7 +314,9 @@ private:
|
|||
void mangleUnscopedTemplateName(const TemplateDecl *ND);
|
||||
void mangleUnscopedTemplateName(TemplateName);
|
||||
void mangleSourceName(const IdentifierInfo *II);
|
||||
void mangleLocalName(const NamedDecl *ND);
|
||||
void mangleLocalName(const Decl *D);
|
||||
void mangleBlockForPrefix(const BlockDecl *Block);
|
||||
void mangleUnqualifiedBlock(const BlockDecl *Block);
|
||||
void mangleLambda(const CXXRecordDecl *Lambda);
|
||||
void mangleNestedName(const NamedDecl *ND, const DeclContext *DC,
|
||||
bool NoFunction=false);
|
||||
|
@ -551,8 +561,7 @@ void CXXNameMangler::mangleName(const NamedDecl *ND) {
|
|||
// is that of the containing namespace, or the translation unit.
|
||||
// FIXME: This is a hack; extern variables declared locally should have
|
||||
// a proper semantic declaration context!
|
||||
if ((isa<FunctionDecl>(DC) || isa<ObjCMethodDecl>(DC)) &&
|
||||
ND->hasLinkage() && !isLambda(ND))
|
||||
if (isLocalContainerContext(DC) && ND->hasLinkage() && !isLambda(ND))
|
||||
while (!DC->isNamespace() && !DC->isTranslationUnit())
|
||||
DC = getEffectiveParentContext(DC);
|
||||
else if (GetLocalClassDecl(ND)) {
|
||||
|
@ -575,7 +584,7 @@ void CXXNameMangler::mangleName(const NamedDecl *ND) {
|
|||
return;
|
||||
}
|
||||
|
||||
if (isa<FunctionDecl>(DC) || isa<ObjCMethodDecl>(DC)) {
|
||||
if (isLocalContainerContext(DC)) {
|
||||
mangleLocalName(ND);
|
||||
return;
|
||||
}
|
||||
|
@ -1264,21 +1273,22 @@ void CXXNameMangler::mangleNestedName(const TemplateDecl *TD,
|
|||
Out << 'E';
|
||||
}
|
||||
|
||||
void CXXNameMangler::mangleLocalName(const NamedDecl *ND) {
|
||||
void CXXNameMangler::mangleLocalName(const Decl *D) {
|
||||
// <local-name> := Z <function encoding> E <entity name> [<discriminator>]
|
||||
// := Z <function encoding> E s [<discriminator>]
|
||||
// <local-name> := Z <function encoding> E d [ <parameter number> ]
|
||||
// _ <entity name>
|
||||
// <discriminator> := _ <non-negative number>
|
||||
const CXXRecordDecl *RD = GetLocalClassDecl(ND);
|
||||
const DeclContext *DC = getEffectiveDeclContext(RD ? RD : ND);
|
||||
assert(isa<NamedDecl>(D) || isa<BlockDecl>(D));
|
||||
const CXXRecordDecl *RD = GetLocalClassDecl(D);
|
||||
const DeclContext *DC = getEffectiveDeclContext(RD ? RD : D);
|
||||
|
||||
Out << 'Z';
|
||||
|
||||
if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(DC))
|
||||
mangleObjCMethodName(MD);
|
||||
else if (const BlockDecl *BD = dyn_cast<BlockDecl>(DC))
|
||||
manglePrefix(BD); // FIXME: This isn't right.
|
||||
mangleBlockForPrefix(BD);
|
||||
else
|
||||
mangleFunctionEncoding(cast<FunctionDecl>(DC));
|
||||
|
||||
|
@ -1307,10 +1317,16 @@ void CXXNameMangler::mangleLocalName(const NamedDecl *ND) {
|
|||
}
|
||||
|
||||
// Mangle the name relative to the closest enclosing function.
|
||||
if (ND == RD) // equality ok because RD derived from ND above
|
||||
mangleUnqualifiedName(ND);
|
||||
else
|
||||
// equality ok because RD derived from ND above
|
||||
if (D == RD) {
|
||||
mangleUnqualifiedName(RD);
|
||||
} else if (const BlockDecl *BD = dyn_cast<BlockDecl>(D)) {
|
||||
manglePrefix(getEffectiveDeclContext(BD), true /*NoFunction*/);
|
||||
mangleUnqualifiedBlock(BD);
|
||||
} else {
|
||||
const NamedDecl *ND = cast<NamedDecl>(D);
|
||||
mangleNestedName(ND, getEffectiveDeclContext(ND), true /*NoFunction*/);
|
||||
}
|
||||
|
||||
if (!SkipDiscriminator) {
|
||||
unsigned disc;
|
||||
|
@ -1325,7 +1341,48 @@ void CXXNameMangler::mangleLocalName(const NamedDecl *ND) {
|
|||
return;
|
||||
}
|
||||
|
||||
mangleUnqualifiedName(ND);
|
||||
if (const BlockDecl *BD = dyn_cast<BlockDecl>(D))
|
||||
mangleUnqualifiedBlock(BD);
|
||||
else
|
||||
mangleUnqualifiedName(cast<NamedDecl>(D));
|
||||
}
|
||||
|
||||
void CXXNameMangler::mangleBlockForPrefix(const BlockDecl *Block) {
|
||||
if (GetLocalClassDecl(Block)) {
|
||||
mangleLocalName(Block);
|
||||
return;
|
||||
}
|
||||
const DeclContext *DC = getEffectiveDeclContext(Block);
|
||||
if (isLocalContainerContext(DC)) {
|
||||
mangleLocalName(Block);
|
||||
return;
|
||||
}
|
||||
manglePrefix(getEffectiveDeclContext(Block));
|
||||
mangleUnqualifiedBlock(Block);
|
||||
}
|
||||
|
||||
void CXXNameMangler::mangleUnqualifiedBlock(const BlockDecl *Block) {
|
||||
if (Decl *Context = Block->getBlockManglingContextDecl()) {
|
||||
if ((isa<VarDecl>(Context) || isa<FieldDecl>(Context)) &&
|
||||
Context->getDeclContext()->isRecord()) {
|
||||
if (const IdentifierInfo *Name
|
||||
= cast<NamedDecl>(Context)->getIdentifier()) {
|
||||
mangleSourceName(Name);
|
||||
Out << 'M';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If we have a block mangling number, use it.
|
||||
unsigned Number = Block->getBlockManglingNumber();
|
||||
// Otherwise, just make up a number. It doesn't matter what it is because
|
||||
// the symbol in question isn't externally visible.
|
||||
if (!Number)
|
||||
Number = Context.getBlockId(Block, false);
|
||||
Out << "Ub";
|
||||
if (Number > 1)
|
||||
Out << Number - 2;
|
||||
Out << '_';
|
||||
}
|
||||
|
||||
void CXXNameMangler::mangleLambda(const CXXRecordDecl *Lambda) {
|
||||
|
@ -1411,30 +1468,11 @@ void CXXNameMangler::manglePrefix(const DeclContext *DC, bool NoFunction) {
|
|||
if (DC->isTranslationUnit())
|
||||
return;
|
||||
|
||||
if (const BlockDecl *Block = dyn_cast<BlockDecl>(DC)) {
|
||||
// Reflect the lambda mangling rules, except that we don't have an
|
||||
// actual function declaration.
|
||||
if (NoFunction)
|
||||
return;
|
||||
if (NoFunction && isLocalContainerContext(DC))
|
||||
return;
|
||||
|
||||
assert(!isLocalContainerContext(DC));
|
||||
|
||||
manglePrefix(getEffectiveParentContext(DC), NoFunction);
|
||||
// If we have a block mangling number, use it.
|
||||
unsigned Number = Block->getBlockManglingNumber();
|
||||
// Otherwise, just make up a number. It doesn't matter what it is because
|
||||
// the symbol in question isn't externally visible.
|
||||
if (!Number)
|
||||
Number = Context.getBlockId(Block, false);
|
||||
Out << "Ub";
|
||||
if (Number > 1)
|
||||
Out << Number - 2;
|
||||
Out << '_';
|
||||
return;
|
||||
} else if (isa<CapturedDecl>(DC)) {
|
||||
// Skip CapturedDecl context.
|
||||
manglePrefix(getEffectiveParentContext(DC), NoFunction);
|
||||
return;
|
||||
}
|
||||
|
||||
const NamedDecl *ND = cast<NamedDecl>(DC);
|
||||
if (mangleSubstitution(ND))
|
||||
return;
|
||||
|
@ -1444,12 +1482,7 @@ void CXXNameMangler::manglePrefix(const DeclContext *DC, bool NoFunction) {
|
|||
if (const TemplateDecl *TD = isTemplate(ND, TemplateArgs)) {
|
||||
mangleTemplatePrefix(TD);
|
||||
mangleTemplateArgs(*TemplateArgs);
|
||||
}
|
||||
else if(NoFunction && (isa<FunctionDecl>(ND) || isa<ObjCMethodDecl>(ND)))
|
||||
return;
|
||||
else if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND))
|
||||
mangleObjCMethodName(Method);
|
||||
else {
|
||||
} else {
|
||||
manglePrefix(getEffectiveDeclContext(ND), NoFunction);
|
||||
mangleUnqualifiedName(ND);
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@ namespace PR12746 {
|
|||
}
|
||||
|
||||
// CHECK: define internal zeroext i1 @___ZN7PR127462f1EPi_block_invoke
|
||||
// CHECK: call zeroext i1 @"_ZZ7PR127462f1Ub_ENK3$_0clEv"
|
||||
// CHECK: call zeroext i1 @"_ZZZN7PR127462f1EPiEUb_ENK3$_0clEv"
|
||||
|
||||
bool f2(int *x) {
|
||||
auto outer = [&]() -> bool {
|
||||
|
|
|
@ -165,7 +165,7 @@ void template_capture_lambda() {
|
|||
}
|
||||
|
||||
void test_capture_lambda() {
|
||||
// CHECK-6: define {{.*}} void @_ZZ23template_capture_lambdaIiEvvENKS_IiEUlvE_clEv
|
||||
// CHECK-6: define {{.*}} void @_ZZ23template_capture_lambdaIiEvvENKUlvE_clEv
|
||||
// CHECK-6-NOT: }
|
||||
// CHECK-6: store i32*
|
||||
// CHECK-6: store i32*
|
||||
|
@ -175,7 +175,7 @@ void test_capture_lambda() {
|
|||
}
|
||||
|
||||
inline int test_captured_linkage() {
|
||||
// CHECK-7: @_ZN21test_captured_linkage1iE = linkonce_odr global i32 0
|
||||
// CHECK-7: @_ZZ21test_captured_linkagevE1i = linkonce_odr global i32 0
|
||||
int j;
|
||||
#pragma clang __debug captured
|
||||
{
|
||||
|
|
|
@ -160,7 +160,7 @@ void func_template(T = []{ return T(); }());
|
|||
|
||||
// CHECK: define void @_Z17use_func_templatev()
|
||||
void use_func_template() {
|
||||
// CHECK: call i32 @"_ZZ13func_templateIiEvT_ENKS_IiE3$_3clEv"
|
||||
// CHECK: call i32 @"_ZZ13func_templateIiEvT_ENK3$_3clEv"
|
||||
func_template<int>();
|
||||
}
|
||||
|
||||
|
@ -205,8 +205,8 @@ namespace PR12808 {
|
|||
void f() {
|
||||
b<int>(1);
|
||||
}
|
||||
// CHECK: define linkonce_odr void @_ZZN7PR128081bIiEEviENKS0_IiEUlvE_clEv
|
||||
// CHECK: define linkonce_odr i32 @_ZZZN7PR128081bIiEEviENKS0_IiEUlvE_clEvENKUlvE_clEv
|
||||
// CHECK: define linkonce_odr void @_ZZN7PR128081bIiEEviENKUlvE_clEv
|
||||
// CHECK: define linkonce_odr i32 @_ZZZN7PR128081bIiEEviENKUlvE_clEvENKUlvE_clEv
|
||||
}
|
||||
|
||||
// CHECK: define linkonce_odr void @_Z1fIZZNK23TestNestedInstantiationclEvENKUlvE_clEvEUlvE_EvT_
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
// RUN: %clang_cc1 -emit-llvm -fblocks -o - -triple x86_64-apple-darwin10 -fobjc-runtime=macosx-fragile-10.5 %s | FileCheck %s
|
||||
|
||||
// CHECK: @_ZGVN3fooUb_5valueE = internal global i64 0
|
||||
// CHECK: @_ZN26externally_visible_statics1SUb_1jE = linkonce_odr global i32 0
|
||||
// CHECK: @_ZN26externally_visible_statics10inlinefuncUb_1iE = linkonce_odr global i32 0
|
||||
// CHECK: @_ZGVZZ3foovEUb_E5value = internal global i64 0
|
||||
// CHECK: @_ZZ26externally_visible_statics1S1xMUb_E1j = linkonce_odr global i32 0
|
||||
// CHECK: @_ZZZN26externally_visible_statics10inlinefuncEvEUb_E1i = linkonce_odr global i32 0
|
||||
|
||||
int f();
|
||||
|
||||
void foo() {
|
||||
// CHECK: define internal i32 @___Z3foov_block_invoke
|
||||
// CHECK: call i32 @__cxa_guard_acquire(i64* @_ZGVN3fooUb_5valueE
|
||||
// CHECK: call i32 @__cxa_guard_acquire(i64* @_ZGVZZ3foovEUb_E5value
|
||||
(void)^(int x) {
|
||||
static int value = f();
|
||||
return x + value;
|
||||
|
@ -26,7 +26,7 @@ int i = ^(int x) { return x;}(i);
|
|||
- (void)method {
|
||||
// CHECK: define internal signext i8 @"__11-[A method]_block_invoke"
|
||||
(void)^(int x) {
|
||||
// CHECK: @"_ZN11-[A method]Ub0_4nameE"
|
||||
// CHECK: @"_ZZZ11-[A method]EUb0_E4name"
|
||||
static const char *name = "hello";
|
||||
return name[x];
|
||||
};
|
||||
|
@ -44,7 +44,7 @@ namespace N {
|
|||
// CHECK: define internal signext i8 @___Z3fooi_block_invoke
|
||||
void bar() {
|
||||
(void)^(int x) {
|
||||
// CHECK: @_ZN1N3barUb2_4nameE
|
||||
// CHECK: @_ZZZN1N3barEvEUb2_E4name
|
||||
static const char *name = "hello";
|
||||
return name[x];
|
||||
};
|
||||
|
@ -56,7 +56,7 @@ class C {
|
|||
};
|
||||
C::C() {
|
||||
(void)^(int x) {
|
||||
// CHECK: @_ZN1CC1Ub3_5namebE
|
||||
// CHECK: @_ZZZN1CC1EvEUb3_E5nameb
|
||||
static const char *nameb = "hello";
|
||||
return nameb[x];
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue