<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/xhtml; charset=utf-8">
</head>
<body>
<div style="font-family:sans-serif"><div style="white-space:normal">
<p dir="auto">On 21 May 2020, at 5:54, John Edwards via cfe-dev wrote:</p>
</div>
<div style="white-space:normal"><blockquote style="border-left:2px solid #777; color:#777; margin:0 0 5px; padding-left:5px"><p dir="auto">Hi all, wanted to share some behavior I'm seeing that seems unintentional,<br>
and I'm wondering if there's a simple fix.<br>
<br>
As the title suggests, not all versions of an __attribute__((used)) tagged<br>
constructor get emitted when compiling with -mconstructor-aliases (which is<br>
the default when using the "clang" driver). Same with destructors. I mostly<br>
tested with the triple "x86_64-unknown-linux-gnu", but WebAssembly, at<br>
least, appears to behave the same way. Ctor_Base (the one using C2 in the<br>
mangled name), always get emitted, but C1 does not. There's a test at<br>
llvm/clang/test/CodeGenCXX/attr-used.cpp that specifically checks to make<br>
sure C1 gets emitted, but it doesn't use the -mconstructor-aliases flag<br>
(and, in fact, fails if you try). I did most of my testing on the master<br>
branch, but it appeared the same on several versions I sampled back to 5.0.<br>
<br>
I traced compilation on the following minimal test case:<br>
<br>
class X0 {<br>
public:<br>
__attribute__((used)) X0() {}<br>
};<br>
<br>
When CodeGenModule::EmitTopLevelDecl() was called for X0(), it called<br>
ItaniumCXXABI::EmitCXXConstructors(), which called<br>
CodeGenModule::EmitGlobal() for first Ctor_Base and then Ctor_Complete.<br>
Normally, EmitGlobal() would try to defer emitting the inline functions<br>
until they were used somewhere else, but ASTContext::DeclMustBeEmitted()<br>
checks for __attribute__((used)) and forces<br>
CodeGenModule::EmitGlobalDefinition() to be called for both of them. So far<br>
so good, but then EmitGlobalDefinition() calls into<br>
ItaniumCXXABI::emitCXXStructor(), and this is where things start to go<br>
wrong. If you compile without the -mconstructor-aliases flag,<br>
emitCXXStructor() checks getCodegenToUse(), which immediately returns Emit,<br>
both ctor versions get emitted, and you pass your tests. With the<br>
-mconstructor-aliases flag, however, getCodegenToUse() wends its way down<br>
to eventually calling GlobalValue::isDiscardableIfUnused(), which returns<br>
true, and getCodegenToUse() ends up returning RAUW (Replace All Uses With).<br>
Ctor_Base gets emitted to comdat, but Ctor_Complete gets<br>
CodeGenModule::addReplacement'd with Ctor_Base, and doesn't make it to the<br>
object file.<br>
<br>
Intuitively, a function tagged as __attribute__((used)) seems like it<br>
shouldn't be isDiscardableIfUnused, though I can also imagine that argued<br>
the other way, but RAUW is even harder to justify. Adding a check for<br>
hasAttr<UsedAttr>() on the line that checks for hasAttr<DLLExportAttr>() in<br>
ASTContext::adjustGVALinkageForAttributes() results in RAUW becoming<br>
COMDAT, and C1 being emitted as an alias for C2 (along with a simple C5<br>
comdat), which seems like the right outcome, though I'm less sure if it's<br>
the right way of getting there. I'm a novice to the Clang internals, but<br>
I'm up for looking into this deeper with some guidance.</p>
</blockquote></div>
<div style="white-space:normal">
<p dir="auto">Well, <code style="background-color:#F7F7F7; border-radius:3px; margin:0; padding:0 0.4em" bgcolor="#F7F7F7">isDiscardableIfUnused</code> is just a query about IR linkages and<br>
can’t consider the source declaration holistically.</p>
<p dir="auto">I think (1) we should be skipping the RAUW if the declaration is used<br>
and (2) adding the alias to the used list, and probably neither of those<br>
is happening.</p>
</div>
<div style="white-space:normal"><blockquote style="border-left:2px solid #777; color:#777; margin:0 0 5px; padding-left:5px"><p dir="auto">In the meantime, is there a way to suppress clang frontend flags via the<br>
clang driver?</p>
</blockquote></div>
<div style="white-space:normal">
<p dir="auto">I don’t think so, no.</p>
<p dir="auto">John.</p>
</div>
</div>
</body>
</html>