[cfe-dev] Linkage of static local variables in available_externally definitions

David Blaikie via cfe-dev cfe-dev at lists.llvm.org
Fri Jan 27 14:10:17 PST 2017


Ah - yep!

Sent out https://reviews.llvm.org/D29233 - turned out
 linkonce_odr/linkonce_odr is needed for the static local variables to meet
the Itanium ABI (well, technically while linkonce_odr must be used in the
use - there would be no harm in putting weak_odr in the definition, but no
benefit either since the ABI doesn't guarantee it, so it cannot be depended
on)

Richard & I also talked about the ramifications of this for Modular Codegen
as well - we came to the conclusion that for now the same behavior
can/should be used, but once modular codegen is implemented using a_e/weak
could be experimented with and would be a valid implementation based on
current ideas around where the ABI and contracts would be between objects
in modular codegen scenarios. (essentially the idea was: modular objects
will need to be ABI compatible with existing code (eg: maybe some of the
code is built with Clang and moduels, some of the code is built with GCC) -
but could provide extra ABI surface for objects generated by a compiler
using those modules (eg: objects built by the compiler that built the
modules used for modular codegen could depend on extra ABI surface, like
weak_odr static locals)... that may've been a bit rambly, sorry - might be
able to explain that better another time)

Thanks, Richard, for walking through all this with me.

On Thu, Jan 26, 2017 at 5:43 PM Mehdi Amini <mehdi.amini at apple.com> wrote:


> On Jan 26, 2017, at 2:51 PM, David Blaikie via cfe-dev <
cfe-dev at lists.llvm.org> wrote:
>
> In implementing modular codegen, specifically verifying the behavior for
static local variables in inline functions in modular headers, I came
across a piece of logic in Clang's linkage calculation that seems off.
>
> To demonstrate a real-world example:
>
> template<typename T>
> inline void f() { static int i; }
> extern template void f<int>();
> ...
> template void f<int>();
>
> In the TU with the extern template declaration, an available_externally
definition of f<int> and f<int>::i are provided (when optimizations are
enabled).
>
> In the TU with the extern template definition, a weak_odr definition of
f<int> is provided but a linkonce_odr definition of f<int>::i is provided.
>
> This surprises me and doesn't seem correct. What if the TU with the
weak_odr definition is optimized to the point of removing the f<int>::i
definition - but the available_externally TU is not - it inlines f<int> but
leaves a use of f<int>::i available?
>
> What's the deal here - am I missing something that makes this
safe/correct?

Seems buggy to me, either it should be (decl / def ): available_externally
/ weak_odr or: linkonce_odr / linkonce_odr.

Indeed based on your example, here are two source files and a header that
fail to link on macOS when optimizations are enabled.




—
Mehdi
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20170127/e124e002/attachment.html>


More information about the cfe-dev mailing list