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() {}