[PATCH] D51789: [clang] Add the no_extern_template attribute

Richard Smith - zygoloid via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Fri Sep 14 10:26:12 PDT 2018


rsmith added a comment.

In https://reviews.llvm.org/D51789#1235100, @ldionne wrote:

> In https://reviews.llvm.org/D51789#1235096, @rsmith wrote:
>
> > OK, so the semantics of this attribute are "explicit instantiation declarations or definitions applied to the enclosing class do not apply to this member", right? So it opts the member out of both `extern template` and (non-`extern`) `template`, but only when applied to an enclosing class.
>
>
> Yes, but it also (obviously) opts the member out when applied to the member itself, not only to an enclosing class.


Assuming I'm understanding you correctly, I don't think the current implementation does that (nor does the documentation change say that), and I think that's a feature not a bug. For example, given:

  template<typename T> struct A {
    [[clang::no_extern_template]] void f() {}
    void g() {}
  };
  template struct A<int>; // instantiates A<int> and definition of A<int>::g(), does not instantiate definition of A<int>::f()
  template void A<int>::f(); // instantiates definition of A<int>::f() despite attribute

... the attribute affects the first explicit instantiation but not the second (I think you're saying it should affect both, and make the second explicit instantiation have no effect). I think the current behavior in this patch is appropriate: making the attribute also affect the second case makes it strictly less useful. If you didn't want to actually explictly instantiate `A<int>::f()`, you can just leave out that explicit instantiation. But the current implementation gives you extra capabilities:

  // A<float>::g() is instantiated somewhere else, A<float>::f() still needs to be implicitly instantiated when used
  extern template struct A<float>;
  
  // A<int>::f() and A<int>::g() are both instantiated somewhere else
  extern template struct A<int>;
  extern template void A<int>::f();

You can't do that if an explicit instantiation of a member with the attribute has no effect.


Repository:
  rC Clang

https://reviews.llvm.org/D51789





More information about the cfe-commits mailing list