]> granicus.if.org Git - clang/commitdiff
Re-fix r136172 so it isn't an error; apparently, some people are fond of their undefi...
authorEli Friedman <eli.friedman@gmail.com>
Tue, 26 Jul 2011 23:27:24 +0000 (23:27 +0000)
committerEli Friedman <eli.friedman@gmail.com>
Tue, 26 Jul 2011 23:27:24 +0000 (23:27 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@136183 91177308-0d34-0410-b5e6-96231b3b80d8

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

index 41aaebaa607ea5e3ceb9752c6aaffe6dcc209268..7ee93568e33577ef57970722073592f889b81645 100644 (file)
@@ -3421,8 +3421,9 @@ 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_delete_abstract_non_virtual_dtor : Warning<
+  "delete called on %0 that is abstract but has non-virtual destructor">,
+  InGroup<DeleteNonVirtualDtor>;
 def warn_overloaded_virtual : Warning<
   "%q0 hides overloaded virtual %select{function|functions}1">,
   InGroup<OverloadedVirtual>, DefaultIgnore;
index 86a4ecc1fc52b02a62b8b354eebdd466fc8cff0f..94a5bafa7c7d6102d14d7d09d8c57580c09063e0 100644 (file)
@@ -1913,18 +1913,6 @@ 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
@@ -1933,11 +1921,20 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal,
       //   behavior is undefined.
       //
       // Note: a final class cannot be derived from, no issue there
-      if (!ArrayForm && PointeeRD->isPolymorphic() &&
-          !PointeeRD->hasAttr<FinalAttr>()) {
+      if (PointeeRD->isPolymorphic() && !PointeeRD->hasAttr<FinalAttr>()) {
         CXXDestructorDecl *dtor = PointeeRD->getDestructor();
-        if (dtor && !dtor->isVirtual())
-          Diag(StartLoc, diag::warn_delete_non_virtual_dtor) << PointeeElem;
+        if (dtor && !dtor->isVirtual()) {
+          if (PointeeRD->isAbstract()) {
+            // If the class is abstract, we warn by default, because we're
+            // sure the code has undefined behavior.
+            Diag(StartLoc, diag::warn_delete_abstract_non_virtual_dtor)
+                << PointeeElem;
+          } else if (!ArrayForm) {
+            // Otherwise, if this is not an array delete, it's a bit suspect,
+            // but not necessarily wrong.
+            Diag(StartLoc, diag::warn_delete_non_virtual_dtor) << PointeeElem;
+          }
+        }
       }
 
     } else if (getLangOptions().ObjCAutoRefCount &&
index 7545b7c136d1248e0e5464cb0e77e9f8b996ef72..748ce77700976043449f2334d449c3877ba27986 100644 (file)
@@ -414,5 +414,5 @@ 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}}
+  void f(A *x) { delete x; } // expected-warning {{delete called on 'PR10504::A' that is abstract but has non-virtual destructor}}
 }