diff options
-rw-r--r-- | include/clang/Basic/DiagnosticSemaKinds.td | 4 | ||||
-rw-r--r-- | lib/Sema/SemaDeclCXX.cpp | 5 | ||||
-rw-r--r-- | test/SemaCXX/warn-weak-vtables.cpp | 22 |
3 files changed, 29 insertions, 2 deletions
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 2031d068a3..15824849e7 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -701,6 +701,10 @@ def warn_weak_vtable : Warning< "%0 has no out-of-line virtual method definitions; its vtable will be " "emitted in every translation unit">, InGroup<DiagGroup<"weak-vtables">>, DefaultIgnore; +def warn_weak_template_vtable : Warning< + "explicit template instantiation %0 will emit a vtable in every " + "translation unit">, + InGroup<DiagGroup<"weak-template-vtables">>, DefaultIgnore; def ext_using_undefined_std : ExtWarn< "using directive refers to implicitly-defined namespace 'std'">; diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 59c5e7894f..50e07553a1 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -10617,7 +10617,10 @@ bool Sema::DefineUsedVTables() { if (!KeyFunction || (KeyFunction->hasBody(KeyFunctionDef) && KeyFunctionDef->isInlined())) - Diag(Class->getLocation(), diag::warn_weak_vtable) << Class; + Diag(Class->getLocation(), Class->getTemplateSpecializationKind() == + TSK_ExplicitInstantiationDefinition + ? diag::warn_weak_template_vtable : diag::warn_weak_vtable) + << Class; } } VTableUses.clear(); diff --git a/test/SemaCXX/warn-weak-vtables.cpp b/test/SemaCXX/warn-weak-vtables.cpp index 912622f5a7..135e034259 100644 --- a/test/SemaCXX/warn-weak-vtables.cpp +++ b/test/SemaCXX/warn-weak-vtables.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 %s -fsyntax-only -verify -Wweak-vtables +// RUN: %clang_cc1 %s -fsyntax-only -verify -Wweak-vtables -Wweak-template-vtables struct A { // expected-warning {{'A' has no out-of-line virtual method definitions; its vtable will be emitted in every translation unit}} virtual void f() { } @@ -56,3 +56,23 @@ void uses(Parent &p, Derived &d, VeryDerived &vd) { d.getFoo(); vd.getFoo(); } + +template<typename T> struct TemplVirt { + virtual void f(); +}; + +template class TemplVirt<float>; // expected-warning{{explicit template instantiation 'TemplVirt<float>' will emit a vtable in every translation unit}} + +template<> struct TemplVirt<bool> { + virtual void f(); +}; + +template<> struct TemplVirt<long> { // expected-warning{{'TemplVirt<long>' has no out-of-line virtual method definitions; its vtable will be emitted in every translation unit}} + virtual void f() {} +}; + +void uses(TemplVirt<float>& f, TemplVirt<bool>& b, TemplVirt<long>& l) { + f.f(); + b.f(); + l.f(); +} |