]> granicus.if.org Git - clang/commitdiff
CodeGen: correct mangling for blocks
authorSaleem Abdulrasool <compnerd@compnerd.org>
Tue, 14 Oct 2014 17:20:14 +0000 (17:20 +0000)
committerSaleem Abdulrasool <compnerd@compnerd.org>
Tue, 14 Oct 2014 17:20:14 +0000 (17:20 +0000)
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.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@219696 91177308-0d34-0410-b5e6-96231b3b80d8

lib/AST/Mangle.cpp
test/CodeGen/mangle-blocks.c [new file with mode: 0644]

index fdc00e389350f4c0d4e8abf66b7a2e0b89f53d10..fba835451e291fc62756eae14c7b96ba480bd052 100644 (file)
@@ -215,6 +215,12 @@ void MangleContext::mangleBlock(const DeclContext *DC, const BlockDecl *BD,
   if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(DC)) {
     mangleObjCMethodName(Method, Stream);
   } else {
+    assert((isa<NamedDecl>(DC) || isa<BlockDecl>(DC)) &&
+           "expected a NamedDecl or BlockDecl");
+    if (isa<BlockDecl>(DC))
+      for (; DC && isa<BlockDecl>(DC); DC = DC->getParent())
+        (void) getBlockId(cast<BlockDecl>(DC), true);
+    assert(isa<NamedDecl>(DC) && "expected a NamedDecl");
     const NamedDecl *ND = cast<NamedDecl>(DC);
     if (!shouldMangleDeclName(ND) && ND->getIdentifier())
       Stream << ND->getIdentifier()->getName();
diff --git a/test/CodeGen/mangle-blocks.c b/test/CodeGen/mangle-blocks.c
new file mode 100644 (file)
index 0000000..9032842
--- /dev/null
@@ -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: }
+