From 8443188a8f9cbd27612b7058cdcfc53356f024a3 Mon Sep 17 00:00:00 2001 From: Eli Friedman Date: Tue, 2 Jul 2013 17:52:28 +0000 Subject: [PATCH] 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. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@185450 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/AST/ItaniumMangle.cpp | 121 +++++++++++------- .../expr.prim.lambda/blocks-irgen.mm | 2 +- test/CodeGenCXX/captured-statements.cpp | 4 +- test/CodeGenCXX/mangle-lambdas.cpp | 6 +- test/CodeGenObjCXX/mangle-blocks.mm | 14 +- 5 files changed, 90 insertions(+), 57 deletions(-) diff --git a/lib/AST/ItaniumMangle.cpp b/lib/AST/ItaniumMangle.cpp index 7948ef7de0..419cb32e45 100644 --- a/lib/AST/ItaniumMangle.cpp +++ b/lib/AST/ItaniumMangle.cpp @@ -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(DC)) + return getEffectiveDeclContext(CD); + + return DC; } static const DeclContext *getEffectiveParentContext(const DeclContext *DC) { return getEffectiveDeclContext(cast(DC)); } - + +static bool isLocalContainerContext(const DeclContext *DC) { + return isa(DC) || isa(DC) || isa(DC); +} + static const CXXRecordDecl *GetLocalClassDecl(const Decl *D) { const DeclContext *DC = getEffectiveDeclContext(D); while (!DC->isNamespace() && !DC->isTranslationUnit()) { - if (isa(DC) || isa(DC) || isa(DC)) + if (isLocalContainerContext(DC)) return dyn_cast(D); D = cast(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(DC) || isa(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(DC) || isa(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) { // := Z E [] // := Z E s [] // := Z E d [ ] // _ // := _ - const CXXRecordDecl *RD = GetLocalClassDecl(ND); - const DeclContext *DC = getEffectiveDeclContext(RD ? RD : ND); + assert(isa(D) || isa(D)); + const CXXRecordDecl *RD = GetLocalClassDecl(D); + const DeclContext *DC = getEffectiveDeclContext(RD ? RD : D); Out << 'Z'; if (const ObjCMethodDecl *MD = dyn_cast(DC)) mangleObjCMethodName(MD); else if (const BlockDecl *BD = dyn_cast(DC)) - manglePrefix(BD); // FIXME: This isn't right. + mangleBlockForPrefix(BD); else mangleFunctionEncoding(cast(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(D)) { + manglePrefix(getEffectiveDeclContext(BD), true /*NoFunction*/); + mangleUnqualifiedBlock(BD); + } else { + const NamedDecl *ND = cast(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(D)) + mangleUnqualifiedBlock(BD); + else + mangleUnqualifiedName(cast(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(Context) || isa(Context)) && + Context->getDeclContext()->isRecord()) { + if (const IdentifierInfo *Name + = cast(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(DC)) { - // Reflect the lambda mangling rules, except that we don't have an - // actual function declaration. - if (NoFunction) - return; - - 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(DC)) { - // Skip CapturedDecl context. - manglePrefix(getEffectiveParentContext(DC), NoFunction); + if (NoFunction && isLocalContainerContext(DC)) return; - } - + + assert(!isLocalContainerContext(DC)); + const NamedDecl *ND = cast(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(ND) || isa(ND))) - return; - else if (const ObjCMethodDecl *Method = dyn_cast(ND)) - mangleObjCMethodName(Method); - else { + } else { manglePrefix(getEffectiveDeclContext(ND), NoFunction); mangleUnqualifiedName(ND); } diff --git a/test/CXX/expr/expr.prim/expr.prim.lambda/blocks-irgen.mm b/test/CXX/expr/expr.prim/expr.prim.lambda/blocks-irgen.mm index a86770d24f..24ce2cd6c1 100644 --- a/test/CXX/expr/expr.prim/expr.prim.lambda/blocks-irgen.mm +++ b/test/CXX/expr/expr.prim/expr.prim.lambda/blocks-irgen.mm @@ -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 { diff --git a/test/CodeGenCXX/captured-statements.cpp b/test/CodeGenCXX/captured-statements.cpp index 65f5abb9a4..a428a3e622 100644 --- a/test/CodeGenCXX/captured-statements.cpp +++ b/test/CodeGenCXX/captured-statements.cpp @@ -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 { diff --git a/test/CodeGenCXX/mangle-lambdas.cpp b/test/CodeGenCXX/mangle-lambdas.cpp index 76839e1c9d..d618782c3c 100644 --- a/test/CodeGenCXX/mangle-lambdas.cpp +++ b/test/CodeGenCXX/mangle-lambdas.cpp @@ -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(); } @@ -205,8 +205,8 @@ namespace PR12808 { void f() { b(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_ diff --git a/test/CodeGenObjCXX/mangle-blocks.mm b/test/CodeGenObjCXX/mangle-blocks.mm index 6493135050..9630c475bd 100644 --- a/test/CodeGenObjCXX/mangle-blocks.mm +++ b/test/CodeGenObjCXX/mangle-blocks.mm @@ -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]; }; -- 2.40.0