aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJan Hubicka <jh@suse.cz>2014-01-10 22:34:37 +0100
committerJan Hubicka <hubicka@gcc.gnu.org>2014-01-10 21:34:37 +0000
commitb270b096a14b869e59e10ca879b5cffa65ea3fd5 (patch)
treea257114435a40ca9a3037d56f5138b40d8c8afa7
parent0d6d7b9a20f3ed4370214a03f1ee26bdda4ad4e9 (diff)
downloadgcc-b270b096a14b869e59e10ca879b5cffa65ea3fd5.zip
gcc-b270b096a14b869e59e10ca879b5cffa65ea3fd5.tar.gz
gcc-b270b096a14b869e59e10ca879b5cffa65ea3fd5.tar.bz2
re PR middle-end/58585 (ICE in ipa with virtual inheritance)
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
-rw-r--r--gcc/ChangeLog6
-rw-r--r--gcc/ipa-devirt.c33
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/g++.dg/torture/pr58585.C20
4 files changed, 61 insertions, 3 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 89f60a2..54d6260 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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
diff --git a/gcc/ipa-devirt.c b/gcc/ipa-devirt.c
index b0bedac..fb03dd2 100644
--- a/gcc/ipa-devirt.c
+++ b/gcc/ipa-devirt.c
@@ -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);
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 8ccfe65..4373d0f 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
index 0000000..69fcf04
--- /dev/null
+++ b/gcc/testsuite/g++.dg/torture/pr58585.C
@@ -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(); }