From: Argyrios Kyrtzidis Date: Mon, 31 Jan 2011 07:05:00 +0000 (+0000) Subject: Warn if the class has virtual methods but non-virtual destructor. Addresses rdar... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=def4e2a405a15eb8381ca305725285d27a4bab65;p=clang Warn if the class has virtual methods but non-virtual destructor. Addresses rdar://8756445. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@124582 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Basic/DiagnosticGroups.td b/include/clang/Basic/DiagnosticGroups.td index 897ccf957f..a0e73639c1 100644 --- a/include/clang/Basic/DiagnosticGroups.td +++ b/include/clang/Basic/DiagnosticGroups.td @@ -80,7 +80,7 @@ def NullDereference : DiagGroup<"null-dereference">; def InitializerOverrides : DiagGroup<"initializer-overrides">; def NonNull : DiagGroup<"nonnull">; def : DiagGroup<"nonportable-cfstrings">; -def : DiagGroup<"non-virtual-dtor">; +def NonVirtualDtor : DiagGroup<"non-virtual-dtor">; def : DiagGroup<"old-style-cast">; def : DiagGroup<"old-style-definition">; def OutOfLineDeclaration : DiagGroup<"out-of-line-declaration">; diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 47174b76b0..308bf0d031 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -2756,6 +2756,9 @@ def err_bad_memptr_lhs : Error< def warn_exception_caught_by_earlier_handler : Warning< "exception of type %0 will be caught by earlier handler">; def note_previous_exception_handler : Note<"for type %0">; +def warn_non_virtual_dtor : Warning< + "%0 has virtual functions but non-virtual destructor">, + InGroup, DefaultIgnore; def err_conditional_void_nonvoid : Error< "%select{left|right}1 operand to ? is void, but %select{right|left}1 operand " diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index c9c58b3e3a..89332eae0e 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -2769,6 +2769,14 @@ void Sema::CheckCompletedCXXClass(CXXRecordDecl *Record) { } } } + + // Warn if the class has virtual methods but non-virtual destructor. + if (Record->isDynamicClass()) { + CXXDestructorDecl *dtor = Record->getDestructor(); + if (!(dtor && dtor->isVirtual())) + Diag(dtor ? dtor->getLocation() : Record->getLocation(), + diag::warn_non_virtual_dtor) << Context.getRecordType(Record); + } } void Sema::ActOnFinishCXXMemberSpecification(Scope* S, SourceLocation RLoc, diff --git a/test/SemaCXX/destructor.cpp b/test/SemaCXX/destructor.cpp index 72268bd43a..a86859c62d 100644 --- a/test/SemaCXX/destructor.cpp +++ b/test/SemaCXX/destructor.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s +// RUN: %clang_cc1 -fsyntax-only -Wnon-virtual-dtor -verify %s class A { public: ~A(); @@ -120,3 +120,31 @@ namespace test7 { b->~B(); } } + +namespace nonvirtualdtor { +struct S1 { // expected-warning {{has virtual functions but non-virtual destructor}} + virtual void m(); +}; + +struct S2 { + ~S2(); // expected-warning {{has virtual functions but non-virtual destructor}} + virtual void m(); +}; + +struct S3 : public S1 { // expected-warning {{has virtual functions but non-virtual destructor}} + virtual void m(); +}; + +struct S4 : public S2 { // expected-warning {{has virtual functions but non-virtual destructor}} + virtual void m(); +}; + +struct B { + virtual ~B(); + virtual void m(); +}; + +struct S5 : public B { + virtual void m(); +}; +}