<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class=""><br class=""><div><blockquote type="cite" class=""><div class="">On Jul 10, 2018, at 16:46, Eric Fiselier <<a href="mailto:eric@efcs.ca" class="">eric@efcs.ca</a>> wrote:</div><div class=""><br style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none;" class=""><div class="gmail_quote" style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none;">On Tue, Jul 10, 2018 at 1:13 PM, Louis Dionne<span class="Apple-converted-space"> </span><span dir="ltr" class=""><<a href="mailto:ldionne@apple.com" target="_blank" class="">ldionne@apple.com</a>></span><span class="Apple-converted-space"> </span>wrote:<br class=""><blockquote class="gmail_quote" style="margin: 0px 0px 0px 0.8ex; border-left-width: 1px; border-left-style: solid; border-left-color: rgb(204, 204, 204); padding-left: 1ex;"><div style="word-wrap: break-word;" class=""><div dir="auto" style="word-wrap: break-word;" class=""><br class=""><div class=""><span class="gmail-"><blockquote type="cite" class=""><div class="">On Jul 10, 2018, at 10:07, Eric Fiselier <<a href="mailto:eric@efcs.ca" target="_blank" class="">eric@efcs.ca</a>> wrote:</div><br class="gmail-m_-1744977764213608698Apple-interchange-newline"><div class=""><div dir="ltr" class="">I like the idea of `_LIBCPP_HIDE_FROM_ABI`, and I think the first step you proposed sounds reasonable.<div class="gmail_extra"><br class=""><div class="gmail_quote">On Mon, Jul 9, 2018 at 10:33 AM, Louis Dionne via cfe-dev<span class="Apple-converted-space"> </span><span dir="ltr" class=""><<a href="mailto:cfe-dev@lists.llvm.org" target="_blank" class="">cfe-dev@lists.llvm.org</a>></span><span class="Apple-converted-space"> </span>wrote:</div><div class="gmail_quote"><blockquote class="gmail_quote" style="margin: 0px 0px 0px 0.8ex; border-left-width: 1px; border-left-style: solid; border-left-color: rgb(204, 204, 204); padding-left: 1ex;">1. Everything that is ABI stable is marked with a visibility macro like today (no change here).<br class="">2. Everything that is marked with `_LIBCPP_INLINE_VISIBILITY` today is marked with a new `_LIBCPP_HIDE_FROM_ABI` macro instead. This macro can be defined to `__attribute__((__visibility__<wbr class="">("hidden")))` or to `__attribute__((__visibility__<wbr class="">("hidden"),internal_linkage))` depending on whether we want to support only use case (1), or both use cases (1) and (2), respectively.</blockquote><div class=""><br class=""></div><div class="">By ABI stable do you mean exported from the libc++ dylib, or all non-reserved names provided by the library? (2) suggests the former, since entities like std::sort are marked with _LIBCPP_INLINE_VISIBILITY.</div><div class="">Any entity which a user can reasonably expect to externally instantiate cannot be part of the “hidden ABI”, since marking it with internal linkage will cause linkage failures.</div></div></div></div></div></blockquote><blockquote type="cite" class=""><br class=""></blockquote><blockquote type="cite" class=""><div dir="ltr" class=""><div class="gmail_extra"><div class="gmail_quote"><div class="">I think we'll be limited to applying `_LIBCPP_HIDE_FROM_ABI` to names which are (A) reserved and (B) cannot be externally instantiated as a member of a class.</div></div></div></div></blockquote><div class=""><br class=""></div></span><div class="">I mean exported from the libc++ dylib.</div><div class=""><br class=""></div><div class="">For other readers:</div><div class="">Regarding linkage failures, Eric and I talked privately and he explained that what he was worried about was a situation such as this one, where a symbol with internal linkage is included in an extern template declaration:</div><div class=""><br class=""></div><div class="">```</div><div class=""><div class="">// RUN: %cxx -c %s -o %t.first.o %flags %compile_flags</div><div class="">// RUN: %cxx -c %s -o %t.second.o -DWITH_MAIN %flags %compile_flags</div><div class="">// RUN: %cxx -o %t.exe %t.first.o %t.second.o %flags %link_flags</div><div class="">// RUN: %run</div><div class=""><br class=""></div><div class="">template <class T></div><div class="">class Foo {</div><div class="">public:</div><div class="">   __attribute__((internal_<wbr class="">linkage)) void bar();</div><div class="">};</div><div class=""><br class=""></div><div class="">template <class T></div><div class="">void Foo<T>::bar() {}</div><div class=""><br class=""></div><div class="">extern template class Foo<int>;</div><div class=""><br class=""></div><div class="">#ifdef WITH_MAIN</div><div class="">int main() {</div><div class=""> <span class="Apple-converted-space"> </span>Foo<int> f;</div><div class=""> <span class="Apple-converted-space"> </span>f.bar();</div><div class="">}</div><div class="">#else</div><div class="">template class Foo<int>;</div><div class="">#endif</div></div><div class="">```</div><div class=""><br class=""></div><div class="">This indeed fails to link because the extern template declaration promises that an instantiation will be available in `t.first.o`, but that instantiation ends up having internal linkage and hence not being visible to `t.second.o`. However, if `bar` is marked inline instead, the example compiles because the C++ Standard requires the instantiation to still happen in `t.second.o` even though an extern instantiation is promised, per <a href="http://eel.is/c++draft/temp.explicit#12" target="_blank" class="">http://eel.is/c++draft/<wbr class="">temp.explicit#12</a>. I don’t think it is ever the case that we use `_LIBCPP_INLINE_VISIBILITY` on a function that is not marked inline in libc++, which is why my proposed solution works in practice. Indeed, if I remove the inline from a function marked as `_LIBCPP_INLINE_VISIBILITY` in a class that is externally instantiated, I do get a linker error when running libc++’s tests.</div><div class=""><br class=""></div><div class="">So the gist of it is that Eric and I think Eric’s concern is not an issue for libc++, but by not much at all.</div><span class="gmail-"><div class=""><br class=""></div><blockquote type="cite" class=""><div dir="ltr" class=""><div class="gmail_extra"><div class="gmail_quote"><div class=""> </div><blockquote class="gmail_quote" style="margin: 0px 0px 0px 0.8ex; border-left-width: 1px; border-left-style: solid; border-left-color: rgb(204, 204, 204); padding-left: 1ex;">This would look something like:<br class=""><br class="">   <span class="Apple-converted-space"> </span>#ifdef _LIBCPP_NO_INTERNAL_LINKAGE_FO<wbr class="">R_ABI_UNSTABLE_SYMBOLS<br class="">   <span class="Apple-converted-space"> </span>#   define _LIBCPP_HIDE_FROM_ABI __attribute__((__visibility__(<wbr class="">"hidden")))<br class="">   <span class="Apple-converted-space"> </span>#else<br class="">   <span class="Apple-converted-space"> </span>#   define _LIBCPP_HIDE_FROM_ABI __attribute__((__visibility__(<wbr class="">"hidden"),internal_linkage))<br class="">   <span class="Apple-converted-space"> </span>#endif<br class=""><br class="">In the future, we can decide which default behavior we want, but for now, I suggest we stick to what we have right now, which is support for both (1) and (2). It would be fine to change this in the future if we make that decision.<br class=""><br class=""></blockquote><div class=""><br class=""></div><div class="">When we don’t have internal linkage, I suspect we'll want to keep `__always_inline__` as to prevent static libraries from providing each other with incompatible function definitions (I think this could occur?).</div></div></div></div></blockquote><div class=""><br class=""></div></span></div>The idea here is that some people don’t care about interoperability of static libraries (or, equivalently, object files) built with different libc++ headers. And since they don’t care about this, they’d rather not pay the cost of inlining or internal linkage, which is code bloat.</div></div></blockquote><div class=""><br class=""></div><div class="">The `__always_inline__` is always needed, at least when mixing ABI stable and ABI hidden symbols in a explicitly instantiated template. Here's a reproducer that should fail to link on GCC and Clang:</div><div class=""><a href="https://godbolt.org/g/LLZGjG" class="">https://godbolt.org/g/LLZGjG</a></div></div></div></blockquote><br class=""></div><div>I don’t believe this example is conforming. Per <a href="http://eel.is/c++draft/temp.explicit#12" class="">http://eel.is/c++draft/<wbr class="">temp.explicit#12</a>, `__init` should still be instantiated in `main.o`, because `__init` is marked inline. I must be wrong because otherwise both GCC and Clang are compiling this wrong.</div><div class=""><br class=""></div>Louis<br class=""><div class=""><br class=""></div></body></html>