diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -1583,8 +1583,8 @@ "emitted in every translation unit">, InGroup>, DefaultIgnore; def warn_weak_template_vtable : Warning< - "explicit template instantiation %0 will emit a vtable in every " - "translation unit">, + "there is no explicit instantiation declaration for %0; its vtable will be " + "emitted in every translation unit">, InGroup>, DefaultIgnore; def ext_using_undefined_std : ExtWarn< diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -17359,15 +17359,24 @@ // no key function or the key function is inlined. Don't warn in C++ ABIs // that lack key functions, since the user won't be able to make one. if (Context.getTargetInfo().getCXXABI().hasKeyFunctions() && - Class->isExternallyVisible() && ClassTSK != TSK_ImplicitInstantiation) { + Class->isExternallyVisible() && + ClassTSK != TSK_ExplicitInstantiationDefinition) { const FunctionDecl *KeyFunctionDef = nullptr; if (!KeyFunction || (KeyFunction->hasBody(KeyFunctionDef) && KeyFunctionDef->isInlined())) { - Diag(Class->getLocation(), - ClassTSK == TSK_ExplicitInstantiationDefinition - ? diag::warn_weak_template_vtable - : diag::warn_weak_vtable) - << Class; + if (ClassTSK == TSK_ImplicitInstantiation) { + Diag(Class->getLocation(), diag::warn_weak_template_vtable) << Class; + + SourceLocation InstLoc; + if (const auto *CTSD = + dyn_cast(Class)) + InstLoc = CTSD->getPointOfInstantiation(); + else + InstLoc = + Class->getMemberSpecializationInfo()->getPointOfInstantiation(); + Diag(InstLoc, diag::note_instantiation_required_here) << false; + } else + Diag(Class->getLocation(), diag::warn_weak_vtable) << Class; } } } diff --git a/clang/test/SemaCXX/warn-weak-vtables.cpp b/clang/test/SemaCXX/warn-weak-vtables.cpp --- a/clang/test/SemaCXX/warn-weak-vtables.cpp +++ b/clang/test/SemaCXX/warn-weak-vtables.cpp @@ -8,7 +8,7 @@ virtual void f() { } }; -template struct B { +template struct B { // expected-warning {{there is no explicit instantiation declaration for 'B'; its vtable will be emitted in every translation unit}} virtual void f() { } }; @@ -29,7 +29,8 @@ // Use the vtables void uses_abc() { A a; - B b; + B b; // expected-note{{implicit instantiation first required here}} + B b_internal; C c; } @@ -63,7 +64,7 @@ virtual void f(); }; -template class TemplVirt; // expected-warning{{explicit template instantiation 'TemplVirt' will emit a vtable in every translation unit}} +template class TemplVirt; template<> struct TemplVirt { virtual void f();