Hi, the two testcases show somewhat crazy layout of C++ object that goes in order base1,base2,virtual_base_of_base1 this confuses the walk in get_binfo_at_offset while looking for virtual_base_of_base1 to look into base2 instead of base1.
It seems that in the case of virtual inheritance we simply want to do fully recursive search for the given binfo - it is not that expensiv ebecause bases are not many. Bootstrapped/regtested x86_64-linux. Will commit it today after rebuilding firefox. 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. Index: tree.c =================================================================== --- tree.c (revision 220142) +++ tree.c (working copy) @@ -11990,6 +11990,23 @@ type_in_anonymous_namespace_p (const_tre 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_WI represented in the binfo for the derived class. */ else if (offset != 0) { - tree base_binfo, binfo2 = binfo; - - /* 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; - } - } + tree found_binfo = NULL, base_binfo; + int offset = (tree_to_shwi (BINFO_OFFSET (binfo)) + pos + / BITS_PER_UNIT); + + 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; Index: testsuite/g++.dg/torture/pr64139.C =================================================================== --- testsuite/g++.dg/torture/pr64139.C (revision 0) +++ testsuite/g++.dg/torture/pr64139.C (revision 0) @@ -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); +} + Index: testsuite/g++.dg/torture/pr60871.C =================================================================== --- testsuite/g++.dg/torture/pr60871.C (revision 0) +++ testsuite/g++.dg/torture/pr60871.C (revision 0) @@ -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 (); }