Hi,

PR 61085 revealed that I forgot to put a type_preserved check to an
important spot, namely to update_indirect_edges_after_inlining, which
leads to wrong devirtualization because the function does not ignore
jump functions it should.

Fixed thusly, bootstrapped and tested on x86_64-linux on both trunk
and the 4.9 branch.  OK for both?

Thanks,

Martin


2014-05-15  Martin Jambor  <mjam...@suse.cz>

        PR ipa/61085
        * ipa-prop.c (update_indirect_edges_after_inlining): Check
        type_preserved flag when the indirect edge is polymorphic.

testsuite/
        * g++.dg/ipa/pr61085.C: New test.

diff --git a/gcc/ipa-prop.c b/gcc/ipa-prop.c
index da6ffe8..4f983a6 100644
--- a/gcc/ipa-prop.c
+++ b/gcc/ipa-prop.c
@@ -2877,16 +2877,20 @@ update_indirect_edges_after_inlining (struct 
cgraph_edge *cs,
       else if (jfunc->type == IPA_JF_PASS_THROUGH
               && ipa_get_jf_pass_through_operation (jfunc) == NOP_EXPR)
        {
-         if (ici->agg_contents
-             && !ipa_get_jf_pass_through_agg_preserved (jfunc))
+         if ((ici->agg_contents
+              && !ipa_get_jf_pass_through_agg_preserved (jfunc))
+             || (ici->polymorphic
+                 && !ipa_get_jf_pass_through_type_preserved (jfunc)))
            ici->param_index = -1;
          else
            ici->param_index = ipa_get_jf_pass_through_formal_id (jfunc);
        }
       else if (jfunc->type == IPA_JF_ANCESTOR)
        {
-         if (ici->agg_contents
-             && !ipa_get_jf_ancestor_agg_preserved (jfunc))
+         if ((ici->agg_contents
+              && !ipa_get_jf_ancestor_agg_preserved (jfunc))
+             || (ici->polymorphic
+                 && !ipa_get_jf_ancestor_type_preserved (jfunc)))
            ici->param_index = -1;
          else
            {
diff --git a/gcc/testsuite/g++.dg/ipa/pr61085.C 
b/gcc/testsuite/g++.dg/ipa/pr61085.C
new file mode 100644
index 0000000..531f59d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ipa/pr61085.C
@@ -0,0 +1,33 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fno-early-inlining" } */
+
+struct A {};
+struct B : virtual A {
+  unsigned m_i;
+  B() : m_i () {}
+  virtual A *m_virt ()
+  {
+    return 0;
+  }
+  ~B ()
+  {
+    m_foo ();
+    while (m_i)
+      ;
+  }
+  void m_foo ()
+  {
+    m_virt ();
+  }
+};
+
+class C : B {
+  A *m_virt () {
+    __builtin_abort ();
+  }
+};
+
+int main ()
+{
+  C c;
+}

Reply via email to