From 1610b8198e31eb6d77d4d6904d6af88ef5cc6d3b Mon Sep 17 00:00:00 2001 From: Anders Carlsson Date: Sat, 6 Feb 2010 02:27:10 +0000 Subject: [PATCH] Implement a warning diagnostic for weak vtables. Fixes PR6116. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@95472 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/DiagnosticSemaKinds.td | 5 +++++ lib/Sema/SemaDecl.cpp | 11 +++++++++-- test/SemaCXX/warn-weak-vtables.cpp | 21 +++++++++++++++++++++ 3 files changed, 35 insertions(+), 2 deletions(-) create mode 100644 test/SemaCXX/warn-weak-vtables.cpp diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index cecd757a65..d31dbd531a 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -390,6 +390,11 @@ def err_deleted_non_function : Error< def err_deleted_decl_not_first : Error< "deleted definition must be first declaration">; +def warn_weak_vtable : Warning< + "%0 has no out-of-line virtual method definitions; its vtable will be " + "emitted in every translation unit">, + InGroup>, DefaultIgnore; + // C++ exception specifications def err_exception_spec_in_typedef : Error< "exception specifications are not allowed in typedefs">; diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 52fc9b74e0..659969334e 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -5002,9 +5002,16 @@ RecordDynamicClassesWithNoKeyFunction(Sema &S, CXXRecordDecl *Record, if (Record->isDependentContext() || !Record->isDefinition()) return; - if (Record->isDynamicClass() && !S.Context.getKeyFunction(Record)) - S.ClassesWithUnmarkedVirtualMembers.push_back(std::make_pair(Record, Loc)); + if (Record->isDynamicClass()) { + const CXXMethodDecl *KeyFunction = S.Context.getKeyFunction(Record); + if (!KeyFunction) + S.ClassesWithUnmarkedVirtualMembers.push_back(std::make_pair(Record, Loc)); + + if ((!KeyFunction || KeyFunction->getBody() && KeyFunction->isInlined()) && + Record->getLinkage() == ExternalLinkage) + S.Diag(Record->getLocation(), diag::warn_weak_vtable) << Record; + } for (DeclContext::decl_iterator D = Record->decls_begin(), DEnd = Record->decls_end(); D != DEnd; ++D) { diff --git a/test/SemaCXX/warn-weak-vtables.cpp b/test/SemaCXX/warn-weak-vtables.cpp new file mode 100644 index 0000000000..1ea88a548e --- /dev/null +++ b/test/SemaCXX/warn-weak-vtables.cpp @@ -0,0 +1,21 @@ +// RUN: %clang_cc1 %s -fsyntax-only -verify -Wweak-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() { } +}; + +template struct B { + virtual void f() { } +}; + +namespace { + struct C { + virtual void f() { } + }; +} + +void f() { + struct A { + virtual void f() { } + }; +} \ No newline at end of file -- 2.40.0