]> granicus.if.org Git - clang/commitdiff
Warn if the class has virtual methods but non-virtual destructor. Addresses rdar...
authorArgyrios Kyrtzidis <akyrtzi@gmail.com>
Mon, 31 Jan 2011 07:05:00 +0000 (07:05 +0000)
committerArgyrios Kyrtzidis <akyrtzi@gmail.com>
Mon, 31 Jan 2011 07:05:00 +0000 (07:05 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@124582 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/DiagnosticGroups.td
include/clang/Basic/DiagnosticSemaKinds.td
lib/Sema/SemaDeclCXX.cpp
test/SemaCXX/destructor.cpp

index 897ccf957f144a5ba50a5789a96a294bc8554efb..a0e73639c10009ce15924c2a442a903599ef30c6 100644 (file)
@@ -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">;
index 47174b76b04a5b137bd21ac6592c813ca95370fc..308bf0d0311fd8238522dcc81d0d86d4755f4516 100644 (file)
@@ -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 "
index c9c58b3e3a48d754ab95237933e64d4b94da5332..89332eae0e0ed28af6164f3cae232aec9b08336f 100644 (file)
@@ -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,
index 72268bd43ac2f924611f2e3bbecbe0959f62785d..a86859c62d92192115e0ccffa4760d4077a4a170 100644 (file)
@@ -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();
+};
+}