Index: lib/AST/MicrosoftMangle.cpp =================================================================== --- lib/AST/MicrosoftMangle.cpp +++ lib/AST/MicrosoftMangle.cpp @@ -966,16 +966,23 @@ } if (const BlockDecl *BD = dyn_cast(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); + DC = getEffectiveDeclContext(BD); + unsigned Discriminator = Context.getBlockId(BD, /*Local=*/false); + Out << "?_block_invoke"; + if (Discriminator) + Out<< '_' << Discriminator; Out << '@'; + if (const auto *RD = dyn_cast(DC)) + mangleName(RD); + else + Out << '@'; + Out << "YAXPAU__block_literal"; + if (Discriminator) + Out<< '_' << Discriminator; + Out << "@@@Z"; + if (isa(DC)) + break; + continue; } else if (const ObjCMethodDecl *Method = dyn_cast(DC)) { mangleObjCMethodName(Method); } else if (isa(DC)) { Index: test/CodeGenCXX/msabi-blocks.cpp =================================================================== --- /dev/null +++ test/CodeGenCXX/msabi-blocks.cpp @@ -0,0 +1,68 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-windows-msvc -std=c++11 -fblocks -S -o - -emit-llvm %s | FileCheck %s + +void (^b)() = ^{ + static int i = 0; +}; + +// CHECK-DAG: @"\01?i@?1??_block_invoke@@YAXPAU__block_literal@@@Z@4HA" ={{.*}} global i32 0 + +extern int e(void); + +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 +void g(void) { + ^{ static int i = e(); }(); +} + +template void g(void); + +// CHECK-DAG: @"\01?i@?2??_block_invoke_5@@YAXPAU__block_literal_5@@@Z?2???$g@D@@YAXXZ@4HA" ={{.*}} global i32 0 + +template void g(void); + +// CHECK-DAG: @"\01?i@?2??_block_invoke_6@@YAXPAU__block_literal_6@@@Z?2???$g@H@@YAXXZ@4HA" ={{.*}} global i32 0 + +inline void h(void) { + ^{ static int i = e(); }(); +} + +// CHECK-DAG: @"\01?i@?2??_block_invoke_9@@YAXPAU__block_literal_9@@@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_10@s@@YAXPAU__block_literal_10@@@Z@4HA" ={{.*}} global i32 0 + + int j = ^{ static int i = e(); return ++i; }(); + +// CHECK-DAG: @"\01?i@?0??_block_invoke_11@s@@YAXPAU__block_literal_11@@@Z@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_7@@YAXPAU__block_literal_7@@@Z?0??m@s@@QEAAXHH@Z@4HA" ={{.*}} global i32 0 +// CHECK-DAG: @"\01?i@?0??_block_invoke_8@@YAXPAU__block_literal_8@@@Z?0??m@s@@QEAAXHH@Z@4HA" ={{.*}} global i32 0 +}; + + +void j(void) { + h(); + struct s s; + s.m(); +} +