Index: lib/AST/MicrosoftMangle.cpp =================================================================== --- lib/AST/MicrosoftMangle.cpp +++ lib/AST/MicrosoftMangle.cpp @@ -966,16 +966,48 @@ } 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); - 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(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(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(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,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 +void g(void) { + ^{ static int i = e(); }(); +} + +template void g(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(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; +} +