<div dir="ltr"><div class="gmail_quote"><div dir="ltr">On Tue, 21 Aug 2018 at 14:44, Louis Dionne via cfe-dev <<a href="mailto:cfe-dev@lists.llvm.org">cfe-dev@lists.llvm.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Hi,<br>
<br>
This message is related to solving the issue explained at [1], and indirectly, the usage of __always_inline__ in libc++ as explained at [2].<br>
<br>
I've been looking to add an attribute (tentatively called no_extern_template) which would prevent member functions in a template from getting available_externally linkage even when there is a matching extern template declaration. In other words, given the following code:<br>
<br>
    template <class T><br>
    struct Foo { void func() { } };<br>
    extern template struct Foo<int>;<br>
<br>
    void use() {<br>
      Foo<int> f;<br>
      f.func();<br>
    }<br>
<br>
it is possible for Clang to emit a call to the extern function `Foo<int>::func()`, because the extern template declaration promises that it exists somewhere else in the program. Clang could also decide to inline the function and generate no extern call, but it does not _have_ to. What I want is an attribute that inhibits generating an external call, i.e. that makes sure `Foo<int>::func()` is either emitted in this TU despite the extern template declaration, or inlined (in which case a definition is obviously not needed). If the function is emitted, it should be emitted with proper linkage, in this case linkonce_odr (IIUC). The attribute would be applied to the member function that should be opted-out of the extern template declaration, like so:<br>
<br>
    template <class T><br>
    struct Foo { __attribute__((no_extern_template)) void func() { } };<br>
    extern template struct Foo<int>;<br>
<br>
I'd like to have some feedback on this idea, specifically:<br></blockquote><div><br></div><div>I think I'm following what you're asking for: the idea is that an explicit instantiation declaration for the class would not be treated as an explicit instantiation declaration for the members of the class that have the attribute, right? So the desired behavior for:</div><div><br></div><div><div>template <class T> struct Foo { // non-polymorphic class</div><div>  void foo() { }</div><div>  __attribute__((no_extern_template)) void bar() { }<br></div><div>  void baz() { }<br></div><div>};</div><div>extern template struct Foo<int>;</div></div><div><br></div><div>would be exactly the same as the standard behavior of:</div><div><br></div><div><div><div>template <class T> struct Foo {</div><div>  void foo() { }</div><div>  void bar() { }<br></div><div>  void baz() { }<br></div><div>};</div><div>extern void Foo<int>::foo();</div></div></div><div>extern void Foo<int>::baz();<br></div><div><br></div><div>except that this is an opt-out mechanism whereas the standard mechanism is opt-in. (For polymorphic class types, there's more differences, as explicit instantiations can also affect where vtables are emitted.)</div><div><br></div><div>Given that (I'm guessing) the idea is to more precisely control which functions are part of the libc++ DSO's ABI, have you considered explicitly listing those functions (that is, following the opt-in strategy) rather than adding an opt-out mechanism? That seems to give more direct control over the ABI surface, albeit at the cost of presumably making the header larger. Is there a reason that approach won't work or is undesirable?</div><div><br class="gmail-Apple-interchange-newline"></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
- What entities does it make sense to apply this attribute to? Currently, I'm thinking only static and non-static member functions of templates, for lack of imagination and other use cases. Does it make sense to apply it to static data members? To the vtable and RTTI somehow?<br>
<br>
- What other attributes would be mutually exclusive with this one? Right now I can only think of `internal_linkage`, but is there anything else?<br>
<br>
Finally, I'd also welcome any guidance on how to best achieve this in Clang. So far, I've achieved something that "works" by forcing declarations with `GVA_AvailableExternally` linkage to have `GVA_DiscardableODR` linkage (in `adjustGVALinkageForAttributes`). I think this is probably the wrong approach but I’m a Clang beginner, so I’m looking for advice if somebody has some. I'll soon publish an early code review on Phabricator to ease the process of getting feedback on the code itself.<br>
<br>
Thanks,<br>
Louis<br>
<br>
[1]: <a href="http://lists.llvm.org/pipermail/cfe-dev/2018-July/058460.html" rel="noreferrer" target="_blank">http://lists.llvm.org/pipermail/cfe-dev/2018-July/058460.html</a><br>
[2]: <a href="http://lists.llvm.org/pipermail/cfe-dev/2018-July/058419.html" rel="noreferrer" target="_blank">http://lists.llvm.org/pipermail/cfe-dev/2018-July/058419.html</a><br>
<br>
_______________________________________________<br>
cfe-dev mailing list<br>
<a href="mailto:cfe-dev@lists.llvm.org" target="_blank">cfe-dev@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev</a><br>
</blockquote></div></div>