compnerd created this revision.
compnerd added a project: clang.

When generating the decorated name for a static variable inside a BlockDecl, 
construct a scope for the block invocation function that homes the parameter.  
This allows for arbitrary nesting of the blocks even if the variables are 
shadowed.  Furthermore, using this for the name allows for undname to properly 
undecorated the name for us.  It shows up as the synthetic __block_invocation 
function that the compiler emitted in the local scope.


Repository:
  rL LLVM

https://reviews.llvm.org/D34523

Files:
  lib/AST/MicrosoftMangle.cpp
  test/CodeGenCXX/msabi-blocks.cpp


Index: test/CodeGenCXX/msabi-blocks.cpp
===================================================================
--- /dev/null
+++ test/CodeGenCXX/msabi-blocks.cpp
@@ -0,0 +1,42 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-windows-msvc -std=c++11 -fblocks -S 
-emit-llvm -o - %s | FileCheck %s
+
+auto b = ^() {
+  static int i = 0;
+  return ++i;
+};
+
+
+void f() {
+  auto l = ^() {
+    static int i = 0;
+    return ++i;
+  };
+  auto m = ^() {
+    static int i = 0;
+    return ++i;
+  };
+  auto n = ^() {
+    auto o = ^() {
+      static int i = 0;
+      return ++i;
+    };
+  };
+}
+
+template <typename T>
+void g() {
+  auto p = ^() {
+    static int i = 0;
+    return ++i;
+  };
+}
+
+template void g<char>();
+template void g<int>();
+
+// CHECK: @"\01?i@?1??_block_invoke@@YAXPAU__block_literal@@@Z@4HA" = internal
+// CHECK: 
@"\01?i@?1??_block_invoke_1@@YAXPAU__block_literal_1@@@Z?1??f@@YAXXZ@4HA" = 
internal
+// CHECK: 
@"\01?i@?1??_block_invoke_2@@YAXPAU__block_literal_2@@@Z?1??f@@YAXXZ@4HA" = 
internal
+// CHECK: 
@"\01?i@?1??_block_invoke_3@@YAXPAU__block_literal_3@@@Z?1??_block_invoke_4@@YAXPAU__block_literal_4@@@Z?1??f@@YAXXZ@4HA"
 = internal
+// CHECK: 
@"\01?i@?2??_block_invoke_5@@YAXPAU__block_literal_5@@@Z?2???$g@D@@YAXXZ@4HA" = 
linkonce_odr
+// CHECK: 
@"\01?i@?2??_block_invoke_6@@YAXPAU__block_literal_6@@@Z?2???$g@H@@YAXXZ@4HA" = 
linkonce_odr
Index: lib/AST/MicrosoftMangle.cpp
===================================================================
--- lib/AST/MicrosoftMangle.cpp
+++ lib/AST/MicrosoftMangle.cpp
@@ -966,16 +966,14 @@
     }

     if (const BlockDecl *BD = dyn_cast<BlockDecl>(DC)) {
-      DiagnosticsEngine &Diags = Context.getDiags();
-      unsigned DiagID =
-          Diags.getCustomDiagID(DiagnosticsEngine::Error,
-                                "cannot mangle a local inside this block yet");
-      Diags.Report(BD->getLocation(), DiagID);
-
-      // FIXME: This is completely, utterly, wrong; see ItaniumMangle
-      // for how this should be done.
-      Out << "__block_invoke" << Context.getBlockId(BD, false);
-      Out << '@';
+      auto Discriminator = Context.getBlockId(BD, false);
+      Out << "?_block_invoke";
+      if (Discriminator)
+        Out << '_' << Discriminator;
+      Out << "@@YAXPAU__block_literal";
+      if (Discriminator)
+        Out << '_' << Discriminator;
+      Out << "@@@Z";
     } else if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(DC)) {
       mangleObjCMethodName(Method);
     } else if (isa<NamedDecl>(DC)) {


Index: test/CodeGenCXX/msabi-blocks.cpp
===================================================================
--- /dev/null
+++ test/CodeGenCXX/msabi-blocks.cpp
@@ -0,0 +1,42 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-windows-msvc -std=c++11 -fblocks -S -emit-llvm -o - %s | FileCheck %s
+
+auto b = ^() {
+  static int i = 0;
+  return ++i;
+};
+
+
+void f() {
+  auto l = ^() {
+    static int i = 0;
+    return ++i;
+  };
+  auto m = ^() {
+    static int i = 0;
+    return ++i;
+  };
+  auto n = ^() {
+    auto o = ^() {
+      static int i = 0;
+      return ++i;
+    };
+  };
+}
+
+template <typename T>
+void g() {
+  auto p = ^() {
+    static int i = 0;
+    return ++i;
+  };
+}
+
+template void g<char>();
+template void g<int>();
+
+// CHECK: @"\01?i@?1??_block_invoke@@YAXPAU__block_literal@@@Z@4HA" = internal
+// CHECK: @"\01?i@?1??_block_invoke_1@@YAXPAU__block_literal_1@@@Z?1??f@@YAXXZ@4HA" = internal
+// CHECK: @"\01?i@?1??_block_invoke_2@@YAXPAU__block_literal_2@@@Z?1??f@@YAXXZ@4HA" = internal
+// CHECK: @"\01?i@?1??_block_invoke_3@@YAXPAU__block_literal_3@@@Z?1??_block_invoke_4@@YAXPAU__block_literal_4@@@Z?1??f@@YAXXZ@4HA" = internal
+// CHECK: @"\01?i@?2??_block_invoke_5@@YAXPAU__block_literal_5@@@Z?2???$g@D@@YAXXZ@4HA" = linkonce_odr
+// CHECK: @"\01?i@?2??_block_invoke_6@@YAXPAU__block_literal_6@@@Z?2???$g@H@@YAXXZ@4HA" = linkonce_odr
Index: lib/AST/MicrosoftMangle.cpp
===================================================================
--- lib/AST/MicrosoftMangle.cpp
+++ lib/AST/MicrosoftMangle.cpp
@@ -966,16 +966,14 @@
     }

     if (const BlockDecl *BD = dyn_cast<BlockDecl>(DC)) {
-      DiagnosticsEngine &Diags = Context.getDiags();
-      unsigned DiagID =
-          Diags.getCustomDiagID(DiagnosticsEngine::Error,
-                                "cannot mangle a local inside this block yet");
-      Diags.Report(BD->getLocation(), DiagID);
-
-      // FIXME: This is completely, utterly, wrong; see ItaniumMangle
-      // for how this should be done.
-      Out << "__block_invoke" << Context.getBlockId(BD, false);
-      Out << '@';
+      auto Discriminator = Context.getBlockId(BD, false);
+      Out << "?_block_invoke";
+      if (Discriminator)
+        Out << '_' << Discriminator;
+      Out << "@@YAXPAU__block_literal";
+      if (Discriminator)
+        Out << '_' << Discriminator;
+      Out << "@@@Z";
     } else if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(DC)) {
       mangleObjCMethodName(Method);
     } else if (isa<NamedDecl>(DC)) {
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to