<html><head><meta http-equiv="Content-Type" content="text/html charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><br class=""><div><blockquote type="cite" class=""><div class="">On Oct 20, 2016, at 11:51 AM, John McCall <<a href="mailto:rjmccall@apple.com" class="">rjmccall@apple.com</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><div style="" class=""><blockquote type="cite" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px;" class="">On Oct 20, 2016, at 11:39 AM, Mehdi Amini <<a href="mailto:mehdi.amini@apple.com" class="">mehdi.amini@apple.com</a>> wrote:<br class=""><blockquote type="cite" class="">On Oct 20, 2016, at 10:35 AM, John McCall <<a href="mailto:rjmccall@apple.com" class="">rjmccall@apple.com</a>> wrote:<br class=""><br class=""><blockquote type="cite" class="">On Oct 13, 2016, at 10:46 PM, Mehdi Amini via cfe-dev <<a href="mailto:cfe-dev@lists.llvm.org" class="">cfe-dev@lists.llvm.org</a>> wrote:<br class="">Hi,<br class=""><br class="">This fairly simple (and valid) code does not link (on MacOS):<br class=""><br class=""><br class="">#include <iostream><br class="">#include <string><br class="">namespace {<br class=""><span class="Apple-tab-span" style="white-space: pre;">  </span>struct VA {<br class=""><span class="Apple-tab-span" style="white-space: pre;">  </span>};<br class=""><span class="Apple-tab-span" style="white-space: pre;">   </span>struct A : virtual public VA {<br class=""><span class="Apple-tab-span" style="white-space: pre;">       </span><span class="Apple-tab-span" style="white-space: pre;">  </span>A() {<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span><span class="Apple-tab-span" style="white-space: pre;">  </span><span class="Apple-tab-span" style="white-space: pre;">  </span>static bool b = false;<br class=""><span class="Apple-tab-span" style="white-space: pre;">       </span><span class="Apple-tab-span" style="white-space: pre;">  </span><span class="Apple-tab-span" style="white-space: pre;">  </span>std::string str;<br class=""><span class="Apple-tab-span" style="white-space: pre;">     </span><span class="Apple-tab-span" style="white-space: pre;">  </span>}<br class=""><span class="Apple-tab-span" style="white-space: pre;">    </span>};<br class="">}<br class="">int main(int argc, char* argv[]) {<br class=""><span class="Apple-tab-span" style="white-space: pre;">      </span>A::A a;<br class="">}<br class=""><br class=""><br class=""><br class="">The issue is that clang emits two constructors (the complete one and the base one) for struct A because it has a virtual base class.<br class=""><br class="">Because struct A is declared in an anonymous namespace, these constructors are internal linkage. Only one of them is actually called, the other is unreachable.<br class=""><br class="">The “always-inliner” does not visit unreachable internal function. However this constructor is calling into a function from libc++ that are marked “available_externally” and “always inline”: the basic_string constructor.<br class=""><br class="">The problem is that the linkage “available_externally" is a “lie”: there is an external template instantiation in the header, but it is marked “visibility hidden”. So the function cannot be linked to in the libc++ dylib. (I think it’d work with a static libc++).<br class=""></blockquote><br class="">Is it actually hidden in the library, or is it in practice exported?  That is, is the link failure specifically because the external definition is not defined within the current linkage unit (and thus we emit a code sequence that cannot be used to call an external symbol), or is because the symbol isn't available at all?<br class=""><br class="">Assuming the latter, then maybe the right answer is that libc++ should only be declaring an external instantiation of the members it actually exports.  That would be the most explicit thing, because arguably what libc++ is currently doing is a lie.  Trying to work around that problem in the compiler by recognizing certain members as not "really" being externally available seems doomed to failure.<br class=""></blockquote><br class=""><br class="">Right: that’s why I suggested going through a base class that would be externally instantiated, and a derived one for the specific member intended to be hidden.<br class="">That seems like the most “clear” (and maintainable) way to achieve it, but there might be drawbacks (or alternative) that I missed.<br class=""></blockquote><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">Well, I don't know about "maintainable".  The set of members that are guaranteed to be explicitly instantiated is fixed</span>.  If a future version of the standard adds members to basic_string, those members will not be explicitly instantiated in existing versions of the library, and that's something the compiler needs to know about.  If you want to expand the set of explicit instantiations, you'll need to gate those explicit instantiation declarations on the target deployment version.</div></div></blockquote><blockquote type="cite" class=""><div class=""><div style="" class=""><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">Enumerating all the methods that are instantiated is probably *obnoxious*, but it's the most correct thing to do.</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""></div></div></blockquote><div><br class=""></div><div>OK I see, makes sense.</div><div>I was finding the base-class trick a little less syntax-heavy, but as you mention this is a “fixed” list anyway.</div><div><br class=""></div><div>— </div><div>Mehdi</div><div><br class=""></div><div><br class=""></div><br class=""><blockquote type="cite" class=""><div class=""><div style="" class=""><blockquote type="cite" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px;" class=""><blockquote type="cite" class=""><br class=""><blockquote type="cite" class=""><br class="">I see multiple ways to address such cases, possibly many of them can be implemented:<br class=""><br class="">- Don’t emit unreferenced internal_linkage function. (We should try to do this anyway right?)<br class="">- Have the CGSCC run on the unreachable part of the call-graph.<br class="">- Run global-DCE at O0 (might be a good idea anyway if it speeds-up the build)<br class="">- We should have the “available_externally” compatible with “hidden visibility”. Maybe we need a way to have to mark some method excluded from one  `external template` instantiation so that it would be ODR.<br class="">- We could make the basic_string constructor and other method in the same situation internal linkage instead.<br class=""><br class=""><br class="">Thoughts?<br class=""><br class="">—<span class="Apple-converted-space"> </span><br class="">Mehdi<br class="">_______________________________________________<br class="">cfe-dev mailing list<br class=""><a href="mailto:cfe-dev@lists.llvm.org" class="">cfe-dev@lists.llvm.org</a><br class="">http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev</blockquote></blockquote></blockquote></div></div></blockquote></div><br class=""></body></html>