From 64ab4de44339d84e8ecf578e260b68aeb142187b Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Tue, 14 Oct 2014 17:20:14 +0000 Subject: [PATCH] CodeGen: correct mangling for blocks This addresses a regression introduced with SVN r219393. A block may be contained within another block. In such a scenario, we would end up within a BlockDecl, which is not a NamedDecl (as the names are synthesised). The cast to a NamedDecl of the DeclContext would then assert as the types are unrelated. Restore the mangling behaviour to that prior to SVN r219393. If the current block is contained within a BlockDecl, walk up to the parent DeclContext, recursively, until we have a non-BlockDecl. This is expected to be a NamedDecl. Add in a couple of asserts to ensure that the assumption that we only encounter a block within a NamedDecl or a BlockDecl. llvm-svn: 219696 --- clang/lib/AST/Mangle.cpp | 6 ++++++ clang/test/CodeGen/mangle-blocks.c | 20 ++++++++++++++++++++ 2 files changed, 26 insertions(+) create mode 100644 clang/test/CodeGen/mangle-blocks.c diff --git a/clang/lib/AST/Mangle.cpp b/clang/lib/AST/Mangle.cpp index fdc00e389350..fba835451e29 100644 --- a/clang/lib/AST/Mangle.cpp +++ b/clang/lib/AST/Mangle.cpp @@ -215,6 +215,12 @@ void MangleContext::mangleBlock(const DeclContext *DC, const BlockDecl *BD, if (const ObjCMethodDecl *Method = dyn_cast(DC)) { mangleObjCMethodName(Method, Stream); } else { + assert((isa(DC) || isa(DC)) && + "expected a NamedDecl or BlockDecl"); + if (isa(DC)) + for (; DC && isa(DC); DC = DC->getParent()) + (void) getBlockId(cast(DC), true); + assert(isa(DC) && "expected a NamedDecl"); const NamedDecl *ND = cast(DC); if (!shouldMangleDeclName(ND) && ND->getIdentifier()) Stream << ND->getIdentifier()->getName(); diff --git a/clang/test/CodeGen/mangle-blocks.c b/clang/test/CodeGen/mangle-blocks.c new file mode 100644 index 000000000000..90328425c95e --- /dev/null +++ b/clang/test/CodeGen/mangle-blocks.c @@ -0,0 +1,20 @@ +// RUN: %clang_cc1 -triple i386-apple-ios -fblocks -emit-llvm -o - %s | FileCheck %s + +void __assert_rtn(const char *, const char *, int, const char *) + __attribute__ (( noreturn )); +void invoke(void (^)(void)); + +void mangle(void) { + invoke(^{ invoke(^{ __assert_rtn(__func__, __FILE__, __LINE__, "mangle"); }); }); +} + +// CHECK: @__func__.__mangle_block_invoke_2 = private unnamed_addr constant [24 x i8] c"__mangle_block_invoke_2\00", align 1 +// CHECK: @.str = private unnamed_addr constant {{.*}}, align 1 +// CHECK: @.str1 = private unnamed_addr constant [7 x i8] c"mangle\00", align 1 + +// CHECK: define internal void @__mangle_block_invoke(i8* %.block_descriptor) + +// CHECK: define internal void @__mangle_block_invoke_2(i8* %.block_descriptor){{.*}}{ +// CHECK: call void @__assert_rtn(i8* getelementptr inbounds ([24 x i8]* @__func__.__mangle_block_invoke_2, i32 0, i32 0), i8* getelementptr inbounds {{.*}}, i32 8, i8* getelementptr inbounds ([7 x i8]* @.str1, i32 0, i32 0)) +// CHECK: } +