===================================================================
@@ -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
===================================================================
@@ -405,6 +405,7 @@ c_common_handle_option (size_t scode, co
warn_sign_compare = value;
warn_reorder = value;
warn_cxx0x_compat = value;
+ warn_delnonvdtor = value;
}
cpp_opts->warn_trigraphs = value;
===================================================================
@@ -3421,6 +3421,31 @@ build_delete (tree type, tree addr, spec
}
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))
+ {
+ tree x;
+ bool abstract = false;
+ for (x = TYPE_METHODS (type); x; x = DECL_CHAIN (x))
+ if (DECL_PURE_VIRTUAL_P (x))
+ {
+ abstract = true;
+ break;
+ }
+ if (abstract)
+ 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 may cause undefined behaviour", type);
+ }
+ }
}
if (VOID_TYPE_P (type) || !complete_p || !MAYBE_CLASS_TYPE_P (type))
/* Call the builtin operator delete. */
===================================================================
@@ -2331,6 +2331,15 @@ Warn when a class seems unusable because
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
===================================================================
@@ -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 may" }
+ delete [] arr;
+}
+
+struct polyDerived : polyBase { };
+
+void f(polyDerived* p, polyDerived* arr)
+{
+ delete p; // { dg-warning "non-virtual destructor may" }
+ 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;
+}
+