From: Jan Hubicka Date: Tue, 27 Jan 2015 19:39:37 +0000 (+0100) Subject: re PR ipa/60871 (internal compiler error: in possible_polymorphic_call_targets, at... X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=e23f28927f1922bd684d985901d13588a942fbd4;p=gcc.git re PR ipa/60871 (internal compiler error: in possible_polymorphic_call_targets, at ipa-devirt.c:1510) 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. From-SVN: r220185 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 03097cf2a3f..36d0045f194 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2015-01-27 Jan Hubicka + + 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 PR ipa/64282 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 + + PR ipa/60871 + PR ipa/64139 + * g++.dg/torture/pr64139.C: New testcase. + * g++.dg/torture/pr60871.C: Likewise. + 2015-01-27 Janus Weil 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;