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

Richard Smith - zygoloid via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Fri Sep 21 17:05:26 PDT 2018


rsmith added inline comments.


================
Comment at: clang/include/clang/Basic/DiagnosticSemaKinds.td:4683-4686
+  "Member '%0' marked with 'exclude_from_explicit_instantiation' attribute is "
+  "not defined but an explicit template instantiation declaration exists. "
+  "Reliance on this member being defined by an explicit template instantiation "
+  "will lead to link errors.">;
----------------
ldionne wrote:
> rsmith wrote:
> > Diagnostics should start with a lowercase letter and not end with a period.
> > 
> > That said, I'm not sure I see why this diagnostic is correct / useful. If the entity is never used, then there's no link error. And if it is ever used, then you should get an implicit instantiation like normal, and we already have a diagnostic for the case where an entity is implicitly instantiated and no definition is available.
> > Diagnostics should start with a lowercase letter and not end with a period.
> 
> Done.
> 
> > That said, I'm not sure I see why this diagnostic is correct / useful. If the entity is never used, then there's no link error. And if it is ever used, then you should get an implicit instantiation like normal, and we already have a diagnostic for the case where an entity is implicitly instantiated and no definition is available.
> 
> This is not what happens right now. If you don't provide a definition but you try to call the function, an extern call will be produced (and that will result in a link error because any potential explicit instantiation won't provide the function). For example:
> 
> ```
> cat <<EOF | ./install/bin/clang++ -cc1 -stdlib=libc++ -xc++ -emit-llvm -o - -
> template <class T>
> struct Foo {
>   __attribute__((exclude_from_explicit_instantiation)) static void static_member_function();
> };
> 
> extern template struct Foo<int>;
> 
> int main() {
>   Foo<int>::static_member_function();
> }
> EOF
> ```
> 
> Results in the following LLVM IR:
> 
> ```
> ; Function Attrs: noinline norecurse nounwind optnone
> define i32 @main() #0 {
> entry:
>   call void @_ZN3FooIiE22static_member_functionEv()
>   ret i32 0
> }
> 
> declare void @_ZN3FooIiE22static_member_functionEv() #1
> ```
> 
> I guess we should be getting a warning or an error on the point of implicit instantiation instead, or is this behavior acceptable?
> 
I don't think your example is fundamentally any different from:

```
template <class T>
struct Foo {
  static void static_member_function();
};

int main() {
  Foo<int>::static_member_function();
}
```

which likewise produces a declaration of `_ZN3FooIiE22static_member_functionEv`. That case produces a `-Wundefined-func-template` warning; your example should do the same.


Repository:
  rC Clang

https://reviews.llvm.org/D51789





More information about the cfe-commits mailing list