Patchwork [PR,60600] Handle inconsistent devirtualizations gracefully

login
register
mail settings
Submitter Martin Jambor
Date March 25, 2014, 6:16 p.m.
Message ID <20140325181625.GS19304@virgil.suse>
Download mbox | patch
Permalink /patch/333645/
State New
Headers show

Comments

Martin Jambor - March 25, 2014, 6:16 p.m.
Hi,

the following patch converting an assert to a test fixes PR 60600.  If
we determine that a devirtualization cannot happen, we can now convert
the call to builtin_unreachable.

Bootstrapped and tested on x86_64-linux.  I have also sucessfully LTO
built Firefox with the change.  Pre-approved by Honza in bugzilla and
thus I will commit it shortly.

Thanks,

Martin


2014-03-25  Martin Jambor  <mjambor@suse.cz>

	PR ipa/60600
	* ipa-cp.c (ipa_get_indirect_edge_target_1): Redirect type
	inconsistent devirtualizations to __builtin_unreachable.

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

Patch

diff --git a/gcc/ipa-cp.c b/gcc/ipa-cp.c
index b71048a..74042ad 100644
--- a/gcc/ipa-cp.c
+++ b/gcc/ipa-cp.c
@@ -1639,11 +1639,18 @@  ipa_get_indirect_edge_target_1 (struct cgraph_edge *ie,
 	return NULL_TREE;
       target = gimple_get_virt_method_for_binfo (token, binfo);
     }
-#ifdef ENABLE_CHECKING
-  if (target)
-    gcc_assert (possible_polymorphic_call_target_p
-		 (ie, cgraph_get_node (target)));
-#endif
+
+  if (target && !possible_polymorphic_call_target_p (ie,
+						     cgraph_get_node (target)))
+    {
+      if (dump_file)
+	fprintf (dump_file,
+		 "Type inconsident devirtualization: %s/%i->%s\n",
+		 ie->caller->name (), ie->caller->order,
+		 IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (target)));
+      target = builtin_decl_implicit (BUILT_IN_UNREACHABLE);
+      cgraph_get_create_node (target);
+    }
 
   return target;
 }
diff --git a/gcc/testsuite/g++.dg/ipa/pr60600.C b/gcc/testsuite/g++.dg/ipa/pr60600.C
new file mode 100644
index 0000000..00c368e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ipa/pr60600.C
@@ -0,0 +1,34 @@ 
+/* { dg-do compile } */
+/* { dg-options "-O3 -fdump-ipa-cp" } */
+
+struct data {
+    data(int);
+};
+
+struct top {
+    virtual int topf();
+};
+
+struct intermediate: top {
+    int topf() /* override */ { return 0; }
+};
+
+struct child1: top {
+    void childf()
+    {
+        data d(topf());
+    }
+};
+
+struct child2: intermediate {};
+
+void test(top& t)
+{
+    child1& c = static_cast<child1&>(t);
+    c.childf();
+    child2 d;
+    test(d);
+}
+
+/* { dg-final { scan-ipa-dump "Type inconsident devirtualization" "cp" } } */
+/* { dg-final { cleanup-ipa-dump "cp" } } */