The failure with -flto is due to make_decl_local clearing DECL_COMDAT, so the check in ipa_devirt allows devirtualization to an implicitly declared destructor. It's not clear to me why make_decl_local needs to clear DECL_COMDAT, but it's simpler to just remove that check from ipa_devirt.

Tested x86_64-pc-linux-gnu.  OK for trunk and 4.9?
commit f88473ffec00cd8b537f7d92102f99fbd855b685
Author: Jason Merrill <ja...@redhat.com>
Date:   Fri Aug 29 12:44:54 2014 -0400

    	PR c++/58678
    	* ipa-devirt.c (ipa_devirt): Don't check DECL_COMDAT.

diff --git a/gcc/ipa-devirt.c b/gcc/ipa-devirt.c
index f98a18e..948ae23 100644
--- a/gcc/ipa-devirt.c
+++ b/gcc/ipa-devirt.c
@@ -3952,8 +3952,7 @@ ipa_devirt (void)
 	    /* Don't use an implicitly-declared destructor (c++/58678).  */
 	    struct cgraph_node *non_thunk_target
 	      = likely_target->function_symbol ();
-	    if (DECL_ARTIFICIAL (non_thunk_target->decl)
-		&& DECL_COMDAT (non_thunk_target->decl))
+	    if (DECL_ARTIFICIAL (non_thunk_target->decl))
 	      {
 		if (dump_file)
 		  fprintf (dump_file, "Target is artificial\n\n");
diff --git a/gcc/testsuite/g++.dg/ipa/devirt-28a.C b/gcc/testsuite/g++.dg/ipa/devirt-28a.C
new file mode 100644
index 0000000..bdd1682
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ipa/devirt-28a.C
@@ -0,0 +1,15 @@
+// PR c++/58678
+// { dg-options "-O3 -flto -shared -fPIC -Wl,--no-undefined" }
+// { dg-do link { target { gld && fpic } } }
+
+struct A {
+  virtual ~A();
+};
+struct B : A {
+  virtual int m_fn1();
+};
+void fn1(B* b) {
+  delete b;
+}
+
+int main() {}

Reply via email to