re PR middle-end/58585 (ICE in ipa with virtual inheritance)
authorJan Hubicka <jh@suse.cz>
Fri, 10 Jan 2014 21:34:37 +0000 (22:34 +0100)
committerJan Hubicka <hubicka@gcc.gnu.org>
Fri, 10 Jan 2014 21:34:37 +0000 (21:34 +0000)
PR ipa/58585
* ipa-devirt.c (build_type_inheritance_graph): Also add types of vtables
into the type inheritance graph.

* g++.dg/torture/pr58585.C: New testcase.

From-SVN: r206543

gcc/ChangeLog
gcc/ipa-devirt.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/torture/pr58585.C [new file with mode: 0644]

index 89f60a2ea1f7af820c841f39297209dc6c528071..54d62608a9439612506a8a91cd8bc335c8c67955 100644 (file)
@@ -1,3 +1,9 @@
+2014-01-10  Jan Hubicka  <jh@suse.cz>
+
+       PR ipa/58585
+       * ipa-devirt.c (build_type_inheritance_graph): Also add types of vtables
+       into the type inheritance graph.
+
 2014-01-10  Jakub Jelinek  <jakub@redhat.com>
 
        PR rtl-optimization/59754
index b0bedacd60924da21b350058a5db6ca204b5eb2d..fb03dd2618d15f9d7bcc1fecebdfb3d275c31444 100644 (file)
@@ -542,7 +542,7 @@ method_class_type (tree t)
 void
 build_type_inheritance_graph (void)
 {
-  struct cgraph_node *n;
+  struct symtab_node *n;
   FILE *inheritance_dump_file;
   int flags;
 
@@ -554,10 +554,37 @@ build_type_inheritance_graph (void)
 
   /* We reconstruct the graph starting of types of all methods seen in the
      the unit.  */
-  FOR_EACH_FUNCTION (n)
-    if (DECL_VIRTUAL_P (n->decl)
+  FOR_EACH_SYMBOL (n)
+    if (is_a <cgraph_node> (n)
+       && DECL_VIRTUAL_P (n->decl)
        && symtab_real_symbol_p (n))
       get_odr_type (method_class_type (TREE_TYPE (n->decl)), true);
+
+    /* Look also for virtual tables of types that do not define any methods.
+       We need it in a case where class B has virtual base of class A
+       re-defining its virtual method and there is class C with no virtual
+       methods with B as virtual base.
+
+       Here we output B's virtual method in two variant - for non-virtual
+       and virtual inheritance.  B's virtual table has non-virtual version,
+       while C's has virtual.
+
+       For this reason we need to know about C in order to include both
+       variants of B.  More correctly, record_target_from_binfo should
+       add both variants of the method when walking B, but we have no
+       link in between them.
+
+       We rely on fact that either the method is exported and thus we
+       assume it is called externally or C is in anonymous namespace and
+       thus we will see the vtable.  */
+
+    else if (is_a <varpool_node> (n)
+            && DECL_VIRTUAL_P (n->decl)
+            && TREE_CODE (DECL_CONTEXT (n->decl)) == RECORD_TYPE
+            && TYPE_BINFO (DECL_CONTEXT (n->decl))
+            && polymorphic_type_binfo_p (TYPE_BINFO (DECL_CONTEXT (n->decl))))
+      get_odr_type (DECL_CONTEXT (n->decl), true);
   if (inheritance_dump_file)
     {
       dump_type_inheritance_graph (inheritance_dump_file);
index 8ccfe652a8ea1e32a62af5f08739dc3fc0a2db0f..4373d0ffcc29010a2dc01f51a1ffa374e5c7e8ed 100644 (file)
@@ -1,3 +1,8 @@
+2014-01-10  Jan Hubicka  <jh@suse.cz>
+
+       PR ipa/58585
+       * g++.dg/torture/pr58585.C: New testcase.
+
 2014-01-10  Hans-Peter Nilsson  <hp@axis.com>
 
        * gcc.dg/pr46309.c: Disable for cris*-*-*.
diff --git a/gcc/testsuite/g++.dg/torture/pr58585.C b/gcc/testsuite/g++.dg/torture/pr58585.C
new file mode 100644 (file)
index 0000000..69fcf04
--- /dev/null
@@ -0,0 +1,20 @@
+// { dg-do compile }
+// { dg-options "-fpic" { target fpic } }
+struct A
+{
+  virtual void foo() {}
+  void bar();
+};
+void A::bar() { foo(); }
+
+struct B : virtual A
+{
+  virtual void foo() {}
+  char c;
+};
+
+struct C : virtual B
+{
+  C();
+};
+C::C() { bar(); }