invoke.texi: Document -Wdelete-non-virtual-dtor.
authorJonathan Wakely <jwakely.gcc@gmail.com>
Sat, 4 Jun 2011 16:18:36 +0000 (16:18 +0000)
committerJonathan Wakely <redi@gcc.gnu.org>
Sat, 4 Jun 2011 16:18:36 +0000 (17:18 +0100)
* doc/invoke.texi: Document -Wdelete-non-virtual-dtor.

c-family:
* c.opt: Add -Wdelete-non-virtual-dtor.
* c-opts.c (c_common_handle_option): Include it in -Wall.

cp:
* init.c (build_delete): Warn when deleting type with non-virtual
destructor.

testsuite:
* testsuite/g++.dg/warn/delete-non-virtual-dtor.C: New.

From-SVN: r174643

gcc/ChangeLog
gcc/c-family/ChangeLog
gcc/c-family/c-opts.c
gcc/c-family/c.opt
gcc/cp/ChangeLog
gcc/cp/init.c
gcc/doc/invoke.texi
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/warn/delete-non-virtual-dtor.C [new file with mode: 0644]

index 926e1b8f1fd74e25c54d7eb7397b488ee4344c09..ddfb4f95a1a0e93d5a0806b3f6cd408a657a05e9 100644 (file)
@@ -1,3 +1,7 @@
+2011-06-04  Jonathan Wakely  <jwakely.gcc@gmail.com>
+
+       * doc/invoke.texi: Document -Wdelete-non-virtual-dtor.
+
 2011-06-04  Jakub Jelinek  <jakub@redhat.com>
 
        PR target/49281
index 4ddc60d9cc5ad1026d19dad5d973df04b72c1f11..38a6d5560bae4a6d3d61f63f1695e62356df93d6 100644 (file)
@@ -1,3 +1,8 @@
+2011-06-02  Jonathan Wakely  <jwakely.gcc@gmail.com>
+
+       * c.opt: Add -Wdelete-non-virtual-dtor.
+       * c-opts.c (c_common_handle_option): Include it in -Wall.
+
 2011-05-30  Nathan Froyd  <froydnj@gcc.gnu.org>
 
        PR bootstrap/49190
index 3cd3e56ff3ae9e915d8b563602ae5136b7f0302a..5cf58acd62dbf9273716599382adfc0a1f4da6c1 100644 (file)
@@ -405,6 +405,7 @@ c_common_handle_option (size_t scode, const char *arg, int value,
           warn_sign_compare = value;
          warn_reorder = value;
           warn_cxx0x_compat = value;
+          warn_delnonvdtor = value;
        }
 
       cpp_opts->warn_trigraphs = value;
index 6fc72789689d20e2a64db4b55fff8c98729462d7..c4cf4d083d266a669cb7361459b0f3e2cb0f8239 100644 (file)
@@ -331,6 +331,10 @@ Wdeclaration-after-statement
 C ObjC Var(warn_declaration_after_statement) Warning
 Warn when a declaration is found after a statement
 
+Wdelete-non-virtual-dtor
+C++ ObjC++ Var(warn_delnonvdtor) Warning
+Warn about deleting polymorphic objects with non-virtual destructors
+
 Wdeprecated
 C C++ ObjC ObjC++ Var(warn_deprecated) Init(1) Warning
 Warn if a deprecated compiler feature, class, method, or field is used
index 2e70bc6d141612406e1faea8e9f46ed094eff7de..48f39f4da21fc83e1a5e7d3f4e292f5f1bc99994 100644 (file)
@@ -1,3 +1,8 @@
+2011-06-04  Jonathan Wakely  <jwakely.gcc@gmail.com>
+
+       * init.c (build_delete): Warn when deleting type with non-virtual
+       destructor.
+
 2011-06-03  Jakub Jelinek  <jakub@redhat.com>
 
        PR c++/49276
index d92dacce888a97a42b36e3ae49da912365cff607..3b926657c5e7259759aaca29fa0bf2d2eec75151 100644 (file)
@@ -3421,6 +3421,25 @@ build_delete (tree type, tree addr, special_function_kind auto_delete,
                }
              complete_p = false;
            }
+         else if (warn_delnonvdtor && MAYBE_CLASS_TYPE_P (type)
+                  && !CLASSTYPE_FINAL (type) && TYPE_POLYMORPHIC_P (type))
+           {
+             tree dtor;
+             dtor = CLASSTYPE_DESTRUCTORS (type);
+             if (!dtor || !DECL_VINDEX (dtor))
+               {
+                 if (CLASSTYPE_PURE_VIRTUALS (type))
+                   warning (OPT_Wdelete_non_virtual_dtor,
+                            "deleting object of abstract class type %qT"
+                            " which has non-virtual destructor"
+                            " will cause undefined behaviour", type);
+                 else
+                   warning (OPT_Wdelete_non_virtual_dtor,
+                            "deleting object of polymorphic class type %qT"
+                            " which has non-virtual destructor"
+                            " might cause undefined behaviour", type);
+               }
+           }
        }
       if (VOID_TYPE_P (type) || !complete_p || !MAYBE_CLASS_TYPE_P (type))
        /* Call the builtin operator delete.  */
index 585901e29dac98ceee235c92321f41878fabe544..a0690426fd15b54f8a558a0a200b72f244ff544b 100644 (file)
@@ -2331,6 +2331,15 @@ Warn when a class seems unusable because all the constructors or
 destructors in that class are private, and it has neither friends nor
 public static member functions.
 
+@item -Wdelete-non-virtual-dtor @r{(C++ and Objective-C++ only)}
+@opindex Wdelete-non-virtual-dtor
+@opindex Wno-delete-non-virtual-dtor
+Warn when @samp{delete} is used to destroy an instance of a class which
+has virtual functions and non-virtual destructor. It is unsafe to delete
+an instance of a derived class through a pointer to a base class if the
+base class does not have a virtual destructor.  This warning is enabled
+by @option{-Wall}.
+
 @item -Wnoexcept @r{(C++ and Objective-C++ only)}
 @opindex Wnoexcept
 @opindex Wno-noexcept
index fb95911a9323e73d3493516de4408c17b4c0e3a3..30639929fb69d1bad8680f1ba3fdb235526cb8c7 100644 (file)
@@ -1,3 +1,7 @@
+2011-06-04  Jonathan Wakely  <jwakely.gcc@gmail.com>
+
+       * testsuite/g++.dg/warn/delete-non-virtual-dtor.C: New.
+
 2011-06-04  Jonathan Wakely  <jwakely.gcc@gmail.com>
 
        PR c++/33840
diff --git a/gcc/testsuite/g++.dg/warn/delete-non-virtual-dtor.C b/gcc/testsuite/g++.dg/warn/delete-non-virtual-dtor.C
new file mode 100644 (file)
index 0000000..9849b1e
--- /dev/null
@@ -0,0 +1,44 @@
+// { dg-options "-std=gnu++0x -Wdelete-non-virtual-dtor" }
+// { dg-do compile }
+
+struct polyBase { virtual void f(); };
+
+void f(polyBase* p, polyBase* arr)
+{
+  delete p;      // { dg-warning "non-virtual destructor might" }
+  delete [] arr;
+}
+
+struct polyDerived : polyBase { };
+
+void f(polyDerived* p, polyDerived* arr)
+{
+  delete p;      // { dg-warning "non-virtual destructor might" }
+  delete [] arr;
+}
+
+struct absDerived : polyBase { virtual void g() = 0; };
+
+void f(absDerived* p, absDerived* arr)
+{
+  delete p;      // { dg-warning "non-virtual destructor will" }
+  delete [] arr;
+}
+
+struct finalDerived final : polyBase { };
+
+void f(finalDerived* p, finalDerived* arr)
+{
+  delete p;      // no error for final classes
+  delete [] arr;
+}
+
+struct safeBase { virtual ~safeBase(); };
+struct safeDerived : safeBase { virtual void f(); };
+
+void f(safeDerived* p, safeDerived* arr)
+{
+  delete p;      // no error because base has virtual dtor
+  delete [] arr;
+}
+