aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArgyrios Kyrtzidis <akyrtzi@gmail.com>2011-01-31 07:05:00 +0000
committerArgyrios Kyrtzidis <akyrtzi@gmail.com>2011-01-31 07:05:00 +0000
commitdef4e2a405a15eb8381ca305725285d27a4bab65 (patch)
tree55dde82193fcb662f66b337e7befdd1a8355b1ef
parent36eb5e43bcdbe291da4df696755009ffd6a35ac2 (diff)
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
-rw-r--r--include/clang/Basic/DiagnosticGroups.td2
-rw-r--r--include/clang/Basic/DiagnosticSemaKinds.td3
-rw-r--r--lib/Sema/SemaDeclCXX.cpp8
-rw-r--r--test/SemaCXX/destructor.cpp30
4 files changed, 41 insertions, 2 deletions
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<NonVirtualDtor>, 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();
+};
+}