https://gcc.gnu.org/bugzilla/show_bug.cgi?id=67650
Jonathan Wakely <redi at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- Last reconfirmed|2018-05-03 00:00:00 |2019-2-26 --- Comment #34 from Jonathan Wakely <redi at gcc dot gnu.org> --- Honza, could you take another look at this reduced version please? __attribute__((weak)) void f() { } template <typename T> struct Base { virtual void virt() = 0; void do_virt() { virt(); } }; template <typename T> struct Derived : Base<T> { void virt() {} }; template <typename T> struct Wrap { T* p = nullptr; virtual void indirect_virt() { #ifdef FIX p->virt(); // OK #else p->do_virt(); // link error #endif } }; template <const char*> struct Template { }; constexpr char str[] = ""; struct I { I() { f(); } Wrap<Derived<Template<str>>> l; }; int main(){new I();} This is valid C++, but when compiled with -O1 -fdevirtualize it fails with: l.cc:13:8: warning: ‘void Derived<T>::virt() [with T = Template<(& str)>]’ used but never defined void virt() {} ^~~~ /usr/bin/ld: /tmp/ccYAFtTY.o: in function `Wrap<Derived<Template<&str> > >::indirect_virt()': l.cc:(.text+0x57): undefined reference to `Derived<Template<&str> >::virt()' collect2: error: ld returned 1 exit status If compiled with -DFIX it links OK. Even though the Template<(&str)> template argument is completely unused, it compiles fine if Derived<int> is used instead, or Derived<AnotherTemplate<int>>. It only fails when using a template that has a pointer for its template parameter.