Name manging issue with Apple Blocks at global scope

It appears that BlockDecl instances at global scope are not being given unique names for mangling purposes. The following test aborts when compiled with Clang trunk (r214613)

$ cat block-mangling.cpp
extern "C" void abort();
#define assert(x) ((x) ? (void)0 : abort())

template<typename T>
int tf() {
     return T::value;
}

int i1 = ^int {
     struct S { enum { value = 1 };};
     return tf<S>();
}();
int i2 = ^int(int p1) {
     struct S { enum { value = 2 };};
     return tf<S>() + p1;
}(1);

int main() {
     assert(i1 == 1);
     assert(i2 == 3);
}

$ clang -fblocks -std=c++11 block-mangling.cpp -o block-mangling -lBlocksRuntime

$ ./block-mangling
Aborted (core dumped)

$ nm block-mangling
...
0000000000400590 t _Z2tfIZUb_E1SEiv
...

Note that only one specialization of template function tf() is present in the executable produced. There should have been two, one for each block literal in the test program.

The analogous test using C++11 lambda expressions runs as expected.

$ cat lambda-mangling.cpp
extern "C" void abort();
#define assert(x) ((x) ? (void)0 : abort())

template<typename T>
int tf() {
     return T::value;
}

int i1 = [] {
     struct S { enum { value = 1 };};
     return tf<S>();
}();
int i2 = [](int p1) {
     struct S { enum { value = 2 };};
     return tf<S>() + p1;
}(1);

int main() {
     assert(i1 == 1);
     assert(i2 == 3);
}

$ clang -std=c++11 lambda-mangling.cpp -o lambda-mangling

$ ./lambda-mangling
$ echo $?
0

$ nm lambda-mangling
...
0000000000400600 t _Z2tfIZNK3$_0clEvE1SEiv
00000000004005f0 t _Z2tfIZNK3$_1clEiE1SEiv
...

Note that two specializations of template function tf() are present in the lambda case.

Tom.

Thanks for the bug report.

This has been fixed in r214699. In the future, please files bugs here: http://llvm.org/bugs/

Thank you for the quick fix!

The update to the test case (cfe/test/CodeGenObjCXX/mangle-blocks.mm) revealed something that I wasn't aware of - that mangled names generated for local block expressions aren't always assigned numeric discriminators local to the declaration context. In particular, they are only assigned local discriminators when required by the target ABI for correspondence between entities in multiple translation units.

However, I found that local discriminators are not used when they should be when code is first emitted to a .ast file and then compiled. Investigation revealed that the problem stems from ASTReader and ASTWriter failing to preserve the ManglingNumber and ManglingContextDecl members of BlockDecl.

I filed a bug report for this:
Bug 20538 - "Mangled names generated for local types and static objects of Block expressions that must correspond across translation units fail to do so when .AST files are emitted and loaded"
http://llvm.org/bugs/show_bug.cgi?id=20538

Tom.