<html>
<head>
<base href="http://llvm.org/bugs/" />
</head>
<body><table border="1" cellspacing="0" cellpadding="8">
<tr>
<th>Bug ID</th>
<td><a class="bz_bug_link
bz_status_NEW "
title="NEW --- - 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"
href="http://llvm.org/bugs/show_bug.cgi?id=20538">20538</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>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
</td>
</tr>
<tr>
<th>Product</th>
<td>clang
</td>
</tr>
<tr>
<th>Version</th>
<td>trunk
</td>
</tr>
<tr>
<th>Hardware</th>
<td>PC
</td>
</tr>
<tr>
<th>OS</th>
<td>Linux
</td>
</tr>
<tr>
<th>Status</th>
<td>NEW
</td>
</tr>
<tr>
<th>Severity</th>
<td>normal
</td>
</tr>
<tr>
<th>Priority</th>
<td>P
</td>
</tr>
<tr>
<th>Component</th>
<td>Frontend
</td>
</tr>
<tr>
<th>Assignee</th>
<td>unassignedclangbugs@nondot.org
</td>
</tr>
<tr>
<th>Reporter</th>
<td>thonermann@coverity.com
</td>
</tr>
<tr>
<th>CC</th>
<td>llvmbugs@cs.uiuc.edu
</td>
</tr>
<tr>
<th>Classification</th>
<td>Unclassified
</td>
</tr></table>
<p>
<div>
<pre>The following program exhibits failure of name correspondence for static
objects declared within Block expressions in inline functions when the code is
emitted to a .ast file and then loaded for compilation, rather than being
compiled directly.
$ cat t.h
inline int* f() {
return ^int* {
static int i = 1;
return &i;
}();
}
$ cat t1.cpp
#include "t.h"
int* f1() {
return f();
}
$ cat t2.cpp
int i = ^int { return 1; }();
#include "t.h"
int* f2() {
return f();
}
$ cat main.cpp
extern "C" void abort();
#define assert(x) ((x) ? (void)0 : abort())
extern int* f1();
extern int* f2();
int main() {
assert(f1() == f2());
}
Compiling directly from source, with optimizations, results in a program that
runs as expected.
$ clang -O2 -fblocks t1.cpp t2.cpp main.cpp -o t -lBlocksRuntime
<no error>
$ ./t
<no error>
Emitting to .ast files and then compiling those results in a program that does
not run as expected.
$ clang -O2 -emit-ast -fblocks t1.cpp t2.cpp main.cpp
<no error>
$ clang -O2 -fblocks t1.ast t2.ast main.ast -o t -lBlocksRuntime
<no error>
$ ./t
Aborted (core dumped)
I believe the issue is that serialization via the ASTReader and ASTWriter
classes fails to preserve the BlockDecl class members 'ManglingNumber' and
'ManglingContextDecl'. These variables are referenced (by member functions
getBlockManglingNumber() and getBlockManglingContextDecl()) by various
functions in lib/AST/ItaniumMangle.cpp, but in particular by
CXXNameMangler::mangleUnqualifiedBlock() which contains this code:
1393 void CXXNameMangler::mangleUnqualifiedBlock(const BlockDecl *Block) {
....
1405 // If we have a block mangling number, use it.
1406 unsigned Number = Block->getBlockManglingNumber();
1407 // Otherwise, just make up a number. It doesn't matter what it is
because
1408 // the symbol in question isn't externally visible.
1409 if (!Number)
1410 Number = Context.getBlockId(Block, false);
1411 Out << "Ub";
1412 if (Number > 0)
1413 Out << Number - 1;
1414 Out << '_';
1415 }
These members get their values via calls to the BlockDecl setBlockMangling()
member function which is called by Sema::ActOnBlockStart() when the target ABI
requires name mangling correspondence for an entity across translation units.
Sema::ActOnBlockStart() is called prior to emitting a .ast file (and is not
called again when loading a .ast file). However,
CXXNameMangler::mangleUnqualifiedBlock() and other mangling functions are
called after loading a .ast file. Since serialization fails to preserve the
BlockDecl members mentioned above, mangled names are generated using mangling
numbers and contexts other than what was intended.</pre>
</div>
</p>
<hr>
<span>You are receiving this mail because:</span>
<ul>
<li>You are on the CC list for the bug.</li>
</ul>
</body>
</html>