]> granicus.if.org Git - clang/commitdiff
Diagnose trying to delete a pointer to an abstract class with a non-virtual destructo...
authorEli Friedman <eli.friedman@gmail.com>
Tue, 26 Jul 2011 22:50:18 +0000 (22:50 +0000)
committerEli Friedman <eli.friedman@gmail.com>
Tue, 26 Jul 2011 22:50:18 +0000 (22:50 +0000)
I'm not completely sure the standard allows us to reject this, but if it doesn't, it should. :)

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@136172 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/DiagnosticSemaKinds.td
lib/Sema/SemaExprCXX.cpp
test/SemaCXX/new-delete.cpp

index 20332dc286ee4e9e15edff2538153a7ed2da4a0a..264f7a9d10dab4d403a657942de3a8dbc0a5cea0 100644 (file)
@@ -3406,6 +3406,8 @@ def warn_non_virtual_dtor : Warning<
 def warn_delete_non_virtual_dtor : Warning<
   "delete called on %0 that has virtual functions but non-virtual destructor">,
   InGroup<DeleteNonVirtualDtor>, DefaultIgnore;
+def err_delete_abstract_non_virtual_dtor : Error<
+  "cannot delete %0, which is abstract and does not have a virtual destructor">;
 def warn_overloaded_virtual : Warning<
   "%q0 hides overloaded virtual %select{function|functions}1">,
   InGroup<OverloadedVirtual>, DefaultIgnore;
index a3e3c11c6ad69bc67a35012649e84a20c8e6afe0..86a4ecc1fc52b02a62b8b354eebdd466fc8cff0f 100644 (file)
@@ -1913,6 +1913,18 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal,
           DiagnoseUseOfDecl(Dtor, StartLoc);
         }
 
+      // Deleting an abstract class with a non-virtual destructor is always
+      // undefined per [expr.delete]p3, and leads to strange-looking
+      // linker errors.
+      if (PointeeRD->isAbstract()) {
+        CXXDestructorDecl *dtor = PointeeRD->getDestructor();
+        if (dtor && !dtor->isVirtual()) {
+          Diag(StartLoc, diag::err_delete_abstract_non_virtual_dtor)
+              << PointeeElem;
+          return ExprError();
+        }
+      }
+
       // C++ [expr.delete]p3:
       //   In the first alternative (delete object), if the static type of the
       //   object to be deleted is different from its dynamic type, the static
@@ -1924,7 +1936,7 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal,
       if (!ArrayForm && PointeeRD->isPolymorphic() &&
           !PointeeRD->hasAttr<FinalAttr>()) {
         CXXDestructorDecl *dtor = PointeeRD->getDestructor();
-        if (!dtor || !dtor->isVirtual())
+        if (dtor && !dtor->isVirtual())
           Diag(StartLoc, diag::warn_delete_non_virtual_dtor) << PointeeElem;
       }
 
index 850229c32005b1bcdfb837bdbc653009437a2464..7545b7c136d1248e0e5464cb0e77e9f8b996ef72 100644 (file)
@@ -409,3 +409,10 @@ namespace DeleteIncompleteClassPointerError {
   void f(A *x) { 1+delete x; } // expected-warning {{deleting pointer to incomplete type}} \
                                // expected-error {{invalid operands to binary expression}}
 }
+
+namespace PR10504 {
+  struct A {
+    virtual void foo() = 0;
+  };
+  void f(A *x) { delete x; } // expected-error {{cannot delete 'PR10504::A', which is abstract and does not have a virtual destructor}}
+}