diff --git a/clang/lib/AST/Mangle.cpp b/clang/lib/AST/Mangle.cpp --- a/clang/lib/AST/Mangle.cpp +++ b/clang/lib/AST/Mangle.cpp @@ -36,11 +36,10 @@ StringRef Outer, const BlockDecl *BD, raw_ostream &Out) { - unsigned discriminator = Context.getBlockId(BD, true); - if (discriminator == 0) - Out << "__" << Outer << "_block_invoke"; - else - Out << "__" << Outer << "_block_invoke_" << discriminator+1; + Out << "__" << Outer << "_block_invoke"; + for (ParmVarDecl *PVD : BD->parameters()) { + Context.mangleTypeName(PVD->getType(), Out); + } } void MangleContext::anchor() { } @@ -235,7 +234,6 @@ void MangleContext::mangleGlobalBlock(const BlockDecl *BD, const NamedDecl *ID, raw_ostream &Out) { - unsigned discriminator = getBlockId(BD, false); if (ID) { if (shouldMangleDeclName(ID)) mangleName(ID, Out); @@ -243,10 +241,11 @@ Out << ID->getIdentifier()->getName(); } } - if (discriminator == 0) - Out << "_block_invoke"; - else - Out << "_block_invoke_" << discriminator+1; + + Out << "_block_invoke"; + for (ParmVarDecl *PVD : BD->parameters()) { + mangleTypeName(PVD->getType(), Out); + } } void MangleContext::mangleCtorBlock(const CXXConstructorDecl *CD, diff --git a/clang/test/CodeGen/block-with-perdefinedexpr.c b/clang/test/CodeGen/block-with-perdefinedexpr.c --- a/clang/test/CodeGen/block-with-perdefinedexpr.c +++ b/clang/test/CodeGen/block-with-perdefinedexpr.c @@ -10,6 +10,6 @@ { handler( ^(){ syslog("%s", __FUNCTION__); } ); }; -// CHECK: @__FUNCTION__.spd_block_invoke_2 = private unnamed_addr constant [19 x i8] c"spd_block_invoke_2\00" -// CHECK: define internal void @spd_block_invoke_2 -// CHECK: @__FUNCTION__.spd_block_invoke_2 +// CHECK: @__FUNCTION__.spd_block_invoke.1 = private unnamed_addr constant [19 x i8] c"spd_block_invoke.1\00" +// CHECK: define internal void @spd_block_invoke +// CHECK: @__FUNCTION__.spd_block_invoke diff --git a/clang/test/CodeGen/block-with-perdefinedexpr.cpp b/clang/test/CodeGen/block-with-perdefinedexpr.cpp --- a/clang/test/CodeGen/block-with-perdefinedexpr.cpp +++ b/clang/test/CodeGen/block-with-perdefinedexpr.cpp @@ -5,7 +5,7 @@ const char * (^block1)() = ^() { return __FUNCTION__; }; - // CHECK-DAG: @__FUNCTION__.___Z3barv_block_invoke_2 = private unnamed_addr constant [19 x i8] c"bar_block_invoke_2\00", align 1 + // CHECK-DAG: @__FUNCTION__.___Z3barv_block_invoke.1 = private unnamed_addr constant [19 x i8] c"bar_block_invoke_2\00", align 1 const char * (^block2)() = ^() { return __FUNCTION__; }; @@ -16,7 +16,7 @@ const char * (^block1)() = ^() { return __PRETTY_FUNCTION__; }; - // CHECK-DAG: @__PRETTY_FUNCTION__.___Z3bazv_block_invoke_2 = private unnamed_addr constant [26 x i8] c"void baz()_block_invoke_2\00", align 1 + // CHECK-DAG: @__PRETTY_FUNCTION__.___Z3bazv_block_invoke.6 = private unnamed_addr constant [26 x i8] c"void baz()_block_invoke_2\00", align 1 const char * (^block2)() = ^() { return __PRETTY_FUNCTION__; }; diff --git a/clang/test/CodeGen/blockwithlocalstatic.c b/clang/test/CodeGen/blockwithlocalstatic.c --- a/clang/test/CodeGen/blockwithlocalstatic.c +++ b/clang/test/CodeGen/blockwithlocalstatic.c @@ -6,14 +6,18 @@ static int test=0; return test; }; -// CHECK: @block1_block_invoke_2.test = internal global i32 +// CHECK: @block1_block_invoke.test = internal global i32 void (^block1)(void) = ^ { static int test = 2; return; }; -// CHECK: @block2_block_invoke_3.test = internal global i32 +// CHECK: @block2_block_invoke.test = internal global i32 int (^block2)(void) = ^ { static int test = 5; return test; }; - +// CHECK: @block3_block_invoke_ZTSi_ZTSj.test = internal global i32 +int (^block3)(int, unsigned) = ^(int, unsigned) { + static int test = 5; + return test; +}; diff --git a/libcxxabi/src/demangle/ItaniumDemangle.h b/libcxxabi/src/demangle/ItaniumDemangle.h --- a/libcxxabi/src/demangle/ItaniumDemangle.h +++ b/libcxxabi/src/demangle/ItaniumDemangle.h @@ -5503,8 +5503,7 @@ // ::= _Z // ::= // extension ::= ___Z _block_invoke -// extension ::= ___Z _block_invoke+ -// extension ::= ___Z _block_invoke_+ +// extension ::= ___Z _block_invoke+ template Node *AbstractManglingParser::parse() { if (consumeIf("_Z") || consumeIf("__Z")) { @@ -5524,14 +5523,38 @@ Node *Encoding = getDerived().parseEncoding(); if (Encoding == nullptr || !consumeIf("_block_invoke")) return nullptr; - bool RequireNumber = consumeIf('_'); - if (parseNumber().empty() && RequireNumber) - return nullptr; + + OutputStream ParamOS; + if (!initializeOutputStream(nullptr, nullptr, ParamOS, 1024)) { + std::terminate(); + } + + ParamOS += "("; + while (consumeIf("_ZTS")) { + Node *paramType = getDerived().parseType(); + if (ParamOS.back() != '(') + ParamOS += ", "; + + paramType->print(ParamOS); + } + ParamOS += ")"; + if (look() == '.') First = Last; if (numLeft() != 0) return nullptr; - return make("invocation function for block in ", Encoding); + + OutputStream DescOS; + if (!initializeOutputStream(nullptr, nullptr, DescOS, 1024)) { + std::terminate(); + } + DescOS << "invocation function for block with params '"; + DescOS << ParamOS.getBuffer(); + DescOS << "' in "; + DescOS << '\0'; + std::free(ParamOS.getBuffer()); + + return make(DescOS.getBuffer(), Encoding); } Node *Ty = getDerived().parseType(); @@ -5540,6 +5563,12 @@ return Ty; } + Node *Ty = getDerived().parseType(); + if (numLeft() != 0) + return nullptr; + return Ty; +} + template struct ManglingParser : AbstractManglingParser, Alloc> { using AbstractManglingParser, diff --git a/llvm/include/llvm/Demangle/ItaniumDemangle.h b/llvm/include/llvm/Demangle/ItaniumDemangle.h --- a/llvm/include/llvm/Demangle/ItaniumDemangle.h +++ b/llvm/include/llvm/Demangle/ItaniumDemangle.h @@ -27,6 +27,8 @@ #include #include #include +#include +#include #include #define FOR_EACH_NODE_KIND(X) \ @@ -5503,8 +5505,7 @@ // ::= _Z // ::= // extension ::= ___Z _block_invoke -// extension ::= ___Z _block_invoke+ -// extension ::= ___Z _block_invoke_+ +// extension ::= ___Z _block_invoke+ template Node *AbstractManglingParser::parse() { if (consumeIf("_Z") || consumeIf("__Z")) { @@ -5524,14 +5525,39 @@ Node *Encoding = getDerived().parseEncoding(); if (Encoding == nullptr || !consumeIf("_block_invoke")) return nullptr; - bool RequireNumber = consumeIf('_'); - if (parseNumber().empty() && RequireNumber) - return nullptr; + + OutputStream ParamOS; + if (!initializeOutputStream(nullptr, nullptr, ParamOS, 1024)) { + std::terminate(); + } + + ParamOS += "("; + while (consumeIf("_ZTS")) { + Node *paramType = getDerived().parseType(); + if (ParamOS.back() != '(') + ParamOS += ", "; + + paramType->print(ParamOS); + } + ParamOS += ")"; + ParamOS += '\0'; + if (look() == '.') First = Last; if (numLeft() != 0) return nullptr; - return make("invocation function for block in ", Encoding); + + OutputStream DescOS; + if (!initializeOutputStream(nullptr, nullptr, DescOS, 1024)) { + std::terminate(); + } + DescOS << "invocation function for block with params '"; + DescOS << ParamOS.getBuffer(); + DescOS << "' in "; + DescOS << '\0'; + std::free(ParamOS.getBuffer()); + + return make(DescOS.getBuffer(), Encoding); } Node *Ty = getDerived().parseType(); diff --git a/llvm/test/tools/llvm-cxxfilt/invalid.test b/llvm/test/tools/llvm-cxxfilt/invalid.test --- a/llvm/test/tools/llvm-cxxfilt/invalid.test +++ b/llvm/test/tools/llvm-cxxfilt/invalid.test @@ -1,6 +1,7 @@ -RUN: llvm-cxxfilt -n _Z1fi __Z1fi f ___ZSt1ff_block_invoke | FileCheck %s +RUN: llvm-cxxfilt -n _Z1fi __Z1fi f ___ZSt1ff_block_invoke ___Z7my_mainv_block_invoke_ZTSi_ZTSj_ZTSPVK3sss | FileCheck %s CHECK: f(int) CHECK-NEXT: __Z1fi CHECK-NEXT: f -CHECK-NEXT: invocation function for block in std::f(float) +CHECK-NEXT: invocation function for block with params '()' in std::f(float) +CHECK-NEXT: invocation function for block with params '(int, unsigned int, sss const volatile*)' in my_main() diff --git a/llvm/unittests/Demangle/DemangleTest.cpp b/llvm/unittests/Demangle/DemangleTest.cpp --- a/llvm/unittests/Demangle/DemangleTest.cpp +++ b/llvm/unittests/Demangle/DemangleTest.cpp @@ -16,9 +16,11 @@ EXPECT_EQ(demangle("_Z3fooi"), "foo(int)"); EXPECT_EQ(demangle("__Z3fooi"), "foo(int)"); EXPECT_EQ(demangle("___Z3fooi_block_invoke"), - "invocation function for block in foo(int)"); + "invocation function for block with params '()' in foo(int)"); EXPECT_EQ(demangle("____Z3fooi_block_invoke"), - "invocation function for block in foo(int)"); + "invocation function for block with params '()' in foo(int)"); + EXPECT_EQ(demangle("____Z7my_mainv_block_invoke_ZTSi_ZTSj_ZTSPVK3sss"), + "invocation function for block with params '(int, unsigned int, sss const volatile*)' in my_main()"); EXPECT_EQ(demangle("?foo@@YAXH@Z"), "void __cdecl foo(int)"); EXPECT_EQ(demangle("foo"), "foo"); }