compnerd updated this revision to Diff 103887.
compnerd added a comment.

Some more comments, add test case.


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,78 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-windows-msvc -std=c++11 -fblocks -S -o - -emit-llvm %s | FileCheck %s
+
+extern int e(void);
+
+void (^b)() = ^{
+  static int i = 0;
+};
+
+// CHECK-DAG: @"\01?i@?1??_block_invoke@@YAXPAU__block_literal@@@Z@4HA" ={{.*}} global i32 0
+
+void f(void) {
+  static int i = 0;
+  ^{ static int i = e(); }();
+
+// CHECK-DAG: @"\01?i@?1??_block_invoke_1@@YAXPAU__block_literal_1@@@Z?1??f@@YAXXZ@4HA" ={{.*}} global i32 0
+
+  ^{ static int i = e(); }();
+
+// CHECK-DAG: @"\01?i@?1??_block_invoke_2@@YAXPAU__block_literal_2@@@Z?1??f@@YAXXZ@4HA" ={{.*}} global i32 0
+
+  ^{ ^{ static int i = e(); }(); }();
+
+// CHECK-DAG: @"\01?i@?1??_block_invoke_3@@YAXPAU__block_literal_3@@@Z?1??_block_invoke_4@@YAXPAU__block_literal_4@@@Z?1??f@@YAXXZ@4HA" ={{.*}} global i32 0
+}
+
+
+template <typename>
+void g(void) {
+  ^{ static int i = e(); }();
+}
+
+template void g<char>(void);
+
+// CHECK-DAG: @"\01?i@?2??_block_invoke_1@@YAXPAU__block_literal_1@@@Z?2???$g@D@@YAXXZ@4HA" ={{.*}} global i32 0
+
+template void g<int>(void);
+
+// CHECK-DAG: @"\01?i@?2??_block_invoke_1@@YAXPAU__block_literal_1@@@Z?2???$g@H@@YAXXZ@4HA" ={{.*}} global i32 0
+
+inline void h(void) {
+  ^{ static int i = e(); }();
+}
+
+// CHECK-DAG: @"\01?i@?2??_block_invoke_1@@YAXPAU__block_literal_1@@@Z?2??h@@YAXXZ@4HA" ={{.*}} global i32 0
+
+struct s {
+  int i = ^{ static int i = e(); return ++i; }();
+
+// CHECK-DAG: @"\01?i@?0??_block_invoke_1@s@@YAXPAU__block_literal_1@@@Z0@4HA" ={{.*}} global i32 0
+
+  int j = ^{ static int i = e(); return ++i; }();
+
+// CHECK-DAG: @"\01?i@?0??_block_invoke_1@s@@YAXPAU__block_literal_1@@@Zj@@4HA" ={{.*}} global i32 0
+
+  void m(int i = ^{ static int i = e(); return ++i; }(),
+         int j = ^{ static int i = e(); return ++i; }()) {}
+
+// CHECK-DAG: @"\01?i@?0??_block_invoke_1@@YAXPAU__block_literal_1@@@Zj@?0??m@s@@QEAAXHH@Z@4HA" ={{.*}} global i32 0
+// CHECK-DAG: @"\01?i@?0??_block_invoke_1@@YAXPAU__block_literal_1@@@Z0?0??m@s@@QEAAXHH@Z@4HA" ={{.*}} global i32 0
+
+};
+
+struct t {
+  struct u {
+    int i = ^{ static int i = e(); return ++i; }();
+
+// CHECK-DAG: @"\01?i@?0??_block_invoke_1@u@t@@YAXPAU__block_literal_1@@@Z0@4HA" ={{.*}} global i32 0
+
+  };
+};
+
+void j(void) {
+  h();
+  struct s s;
+  s.m();
+  struct t::u t;
+}
+
Index: lib/AST/MicrosoftMangle.cpp
===================================================================
--- lib/AST/MicrosoftMangle.cpp
+++ lib/AST/MicrosoftMangle.cpp
@@ -966,16 +966,48 @@
     }
 
     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 Discriminate = [](StringRef Name,
+                             const unsigned Discriminator) -> std::string {
+        std::string Buffer;
+        llvm::raw_string_ostream Stream(Buffer);
+        Stream << Name;
+        if (Discriminator)
+          Stream << '_' << Discriminator;
+        return Stream.str();
+      };
+
+      unsigned Discriminator = BD->getBlockManglingNumber();
+      if (!Discriminator)
+        Discriminator = Context.getBlockId(BD, /*Local=*/false);
+
+      DC = getEffectiveDeclContext(BD);
+
+      Out << '?';
+      mangleSourceName(Discriminate("_block_invoke", Discriminator));
+      if (const auto *RD = dyn_cast<RecordDecl>(DC))
+        mangleName(RD);
+      else
+        Out << '@';
+      // void __cdecl
+      Out << "YAX";
+      // struct __block_literal *
+      Out << "PA";
+      mangleArtificalTagType(TTK_Struct,
+                             Discriminate("__block_literal", Discriminator));
+      Out << "@Z";
+
+      // If we have a block mangling context, encode that now.  Although the
+      // mangling is not perfect, it allows us to discriminate between multiple
+      // instances in the same scope.
+      if (const auto *MC = BD->getBlockManglingContextDecl())
+        if (const auto *ND = dyn_cast<NamedDecl>(MC))
+          mangleUnqualifiedName(ND);
+
+      // If the effective context was a Record, we have fully mangled the
+      // qualified name and do not need to continue.
+      if (isa<RecordDecl>(DC))
+        break;
+      continue;
     } 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