This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
C++ PATCH for lto/53808 (devirtualization of defaulted virtual dtor)
- From: Jason Merrill <jason at redhat dot com>
- To: gcc-patches List <gcc-patches at gcc dot gnu dot org>, Jan Hubicka <hubicka at ucw dot cz>
- Date: Tue, 25 Feb 2014 13:53:21 -0500
- Subject: C++ PATCH for lto/53808 (devirtualization of defaulted virtual dtor)
- Authentication-results: sourceware.org; auth=none
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 <jason@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;
+}