summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>2015-01-27 19:39:37 +0000
committerhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>2015-01-27 19:39:37 +0000
commit2fdf87a83ddf6330b73f9d12b3962923ed82cb74 (patch)
tree6f53950bc7b11bf868f62ef87364acf75ca6c161
parentb80c64ae1ea0a100115e08fd471a4f3463701fc8 (diff)
downloadgcc-2fdf87a83ddf6330b73f9d12b3962923ed82cb74.tar.gz
PR ipa/60871
PR ipa/64139 * tree.c (lookup_binfo_at_offset): New function. (get_binfo_at_offset): Use it. * g++.dg/torture/pr64139.C: New testcase. * g++.dg/torture/pr60871.C: Likewise. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@220185 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/ChangeLog7
-rw-r--r--gcc/testsuite/ChangeLog7
-rw-r--r--gcc/testsuite/g++.dg/torture/pr60871.C33
-rw-r--r--gcc/testsuite/g++.dg/torture/pr64139.C34
-rw-r--r--gcc/tree.c67
5 files changed, 113 insertions, 35 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 03097cf2a3f..36d0045f194 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,12 @@
2015-01-27 Jan Hubicka <hubicka@ucw.cz>
+ PR ipa/60871
+ PR ipa/64139
+ * tree.c (lookup_binfo_at_offset): New function.
+ (get_binfo_at_offset): Use it.
+
+2015-01-27 Jan Hubicka <hubicka@ucw.cz>
+
PR ipa/64282
* gimple-fold.c (gimple_get_virt_method_for_vtable): Remove assert
on vtable being vtable.
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 8b1e05085ff..8d50aacf55d 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,10 @@
+2015-01-27 Jan Hubicka <hubicka@ucw.cz>
+
+ PR ipa/60871
+ PR ipa/64139
+ * g++.dg/torture/pr64139.C: New testcase.
+ * g++.dg/torture/pr60871.C: Likewise.
+
2015-01-27 Janus Weil <janus@gcc.gnu.org>
PR fortran/64230
diff --git a/gcc/testsuite/g++.dg/torture/pr60871.C b/gcc/testsuite/g++.dg/torture/pr60871.C
new file mode 100644
index 00000000000..902b9ee69d0
--- /dev/null
+++ b/gcc/testsuite/g++.dg/torture/pr60871.C
@@ -0,0 +1,33 @@
+/* { dg-do compile } */
+struct A
+{
+ virtual void m_fn1 ();
+ int m_local;
+};
+class C : virtual public A
+{
+};
+struct B
+{
+ A *m_g;
+
+ B (A *p1) : m_g (p1) { m_g->m_fn1 (); }
+};
+struct C7
+{
+ virtual ~C7 ();
+};
+class D : public C, C7
+{
+};
+struct F : D
+{
+ F (int);
+
+ static void m_fn2 ()
+ {
+ F a (0);
+ B b (&a);
+ }
+};
+void fn1 () { F::m_fn2 (); }
diff --git a/gcc/testsuite/g++.dg/torture/pr64139.C b/gcc/testsuite/g++.dg/torture/pr64139.C
new file mode 100644
index 00000000000..932a676d6a0
--- /dev/null
+++ b/gcc/testsuite/g++.dg/torture/pr64139.C
@@ -0,0 +1,34 @@
+// { dg-do compile }
+class IObject {
+public:
+ virtual ~IObject();
+};
+class A {
+ virtual int m_fn1();
+};
+class B {
+public:
+ virtual int m_fn2(B) const;
+};
+class D : IObject, public virtual B {};
+class G : public D, A {
+public:
+ G(A);
+};
+class F : B {
+ friend class C;
+};
+class C {
+ void m_fn3(const IObject &, int &);
+ void m_fn4(const B &, int &);
+};
+A a;
+void C::m_fn3(const IObject &, int &p2) {
+ G r(a);
+ m_fn4(r, p2);
+}
+void C::m_fn4(const B &p1, int &) {
+ F b;
+ p1.m_fn2(b);
+}
+
diff --git a/gcc/tree.c b/gcc/tree.c
index e1d069d8dc0..6fe1d5a0d55 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -11990,6 +11990,23 @@ type_in_anonymous_namespace_p (const_tree t)
return (TYPE_STUB_DECL (t) && !TREE_PUBLIC (TYPE_STUB_DECL (t)));
}
+/* Lookup sub-BINFO of BINFO of TYPE at offset POS. */
+
+tree
+lookup_binfo_at_offset (tree binfo, tree type, HOST_WIDE_INT pos)
+{
+ unsigned int i;
+ tree base_binfo, b;
+
+ for (i = 0; BINFO_BASE_ITERATE (binfo, i, base_binfo); i++)
+ if (pos == tree_to_shwi (BINFO_OFFSET (base_binfo))
+ && types_same_for_odr (TREE_TYPE (base_binfo), type))
+ return base_binfo;
+ else if ((b = lookup_binfo_at_offset (base_binfo, type, pos)) != NULL)
+ return b;
+ return NULL;
+}
+
/* Try to find a base info of BINFO that would have its field decl at offset
OFFSET within the BINFO type and which is of EXPECTED_TYPE. If it can be
found, return, otherwise return NULL_TREE. */
@@ -12027,42 +12044,22 @@ get_binfo_at_offset (tree binfo, HOST_WIDE_INT offset, tree expected_type)
represented in the binfo for the derived class. */
else if (offset != 0)
{
- tree base_binfo, binfo2 = binfo;
+ tree found_binfo = NULL, base_binfo;
+ int offset = (tree_to_shwi (BINFO_OFFSET (binfo)) + pos
+ / BITS_PER_UNIT);
- /* Find BINFO corresponding to FLD. This is bit harder
- by a fact that in virtual inheritance we may need to walk down
- the non-virtual inheritance chain. */
- while (true)
- {
- tree containing_binfo = NULL, found_binfo = NULL;
- for (i = 0; BINFO_BASE_ITERATE (binfo2, i, base_binfo); i++)
- if (types_same_for_odr (TREE_TYPE (base_binfo), TREE_TYPE (fld)))
- {
- found_binfo = base_binfo;
- break;
- }
- else
- if ((tree_to_shwi (BINFO_OFFSET (base_binfo))
- - tree_to_shwi (BINFO_OFFSET (binfo)))
- * BITS_PER_UNIT < pos
- /* Rule out types with no virtual methods or we can get confused
- here by zero sized bases. */
- && TYPE_BINFO (BINFO_TYPE (base_binfo))
- && BINFO_VTABLE (TYPE_BINFO (BINFO_TYPE (base_binfo)))
- && (!containing_binfo
- || (tree_to_shwi (BINFO_OFFSET (containing_binfo))
- < tree_to_shwi (BINFO_OFFSET (base_binfo)))))
- containing_binfo = base_binfo;
- if (found_binfo)
- {
- binfo = found_binfo;
- break;
- }
- if (!containing_binfo)
- return NULL_TREE;
- binfo2 = containing_binfo;
- }
- }
+ for (i = 0; BINFO_BASE_ITERATE (binfo, i, base_binfo); i++)
+ if (tree_to_shwi (BINFO_OFFSET (base_binfo)) == offset
+ && types_same_for_odr (TREE_TYPE (base_binfo), TREE_TYPE (fld)))
+ {
+ found_binfo = base_binfo;
+ break;
+ }
+ if (found_binfo)
+ binfo = found_binfo;
+ else
+ binfo = lookup_binfo_at_offset (binfo, TREE_TYPE (fld), offset);
+ }
type = TREE_TYPE (fld);
offset -= pos;