The primary bug under discussion in 53808 has been fixed separately, but it also pointed out that once devirtualization resolves the delete to use the bar destructor, we ought to be able to inline that destructor. So if we're devirtualizing, always add a virtual defaulted dtor to the list of functions to be synthesized.

Tested x86_64-pc-linux-gnu, applying to trunk.
commit 9f9f907732429f413e490be0fa969b72153fdd88
Author: Jason Merrill <ja...@redhat.com>
Date:   Fri Mar 22 20:24:49 2013 -0400

    	PR c++/53808
    	* class.c (clone_function_decl): Call note_vague_linkage_fn for
    	defaulted virtual dtor.

diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index 97a1cc2..e861e4d 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -4582,6 +4582,10 @@ clone_function_decl (tree fn, int update_method_vec_p)
 	 destructor.  */
       if (DECL_VIRTUAL_P (fn))
 	{
+	  if (DECL_DEFAULTED_FN (fn) && flag_devirtualize)
+	    /* Make sure the destructor gets synthesized so that it can be
+	       inlined after devirtualization.  */
+	    note_vague_linkage_fn (fn);
 	  clone = build_clone (fn, deleting_dtor_identifier);
 	  if (update_method_vec_p)
 	    add_method (DECL_CONTEXT (clone), clone, NULL_TREE);
diff --git a/gcc/testsuite/g++.dg/opt/devirt4.C b/gcc/testsuite/g++.dg/opt/devirt4.C
new file mode 100644
index 0000000..26e8ee6
--- /dev/null
+++ b/gcc/testsuite/g++.dg/opt/devirt4.C
@@ -0,0 +1,16 @@
+// PR c++/53808
+// Devirtualization + inlining should produce a non-virtual
+// call to ~foo.
+// { dg-options "-O -fdevirtualize" }
+// { dg-final { scan-assembler "_ZN3fooD2Ev" } }
+
+struct foo {
+ virtual ~foo();
+};
+struct bar : public foo {
+ virtual void zed();
+};
+void f() {
+ foo *x(new bar);
+ delete x;
+}

Reply via email to