[C++] Fix 3130, 3131

Nathan Sidwell nathan@codesourcery.com
Fri Jun 15 07:48:00 GMT 2001


Jason Merrill wrote:
> 
> >>>>> "Nathan" == Nathan Sidwell <nathan@codesourcery.com> writes:
> 
> > Initially I tried to just change get_primary_binfo, to see if it could
> > find the canonical binfo, when given a choice, but that failed. The only
> > way I found to fix it was by allowing a canonical binfo to be inside
> > a non-canonical one.
> 
> Please explain to me how this makes sense.  How can a canonical binfo be
> inside a non-canonical one?

struct A { virtual ~A (); 
struct B{ virtual ~B ();};
struct C : virtual public A, virtual public B {};
class D : public virtual C {};
class E : public virtual C, public virtual D {};

this has the following binfo hierarchy for E,

E (0x401632c0) 0 nearly-empty
    vptridx=0 vptr=((&E::_ZTV1E) + 28)
  C (0x40163300) 4 nearly-empty virtual non-canonical
    A (0x40163380) 4 nearly-empty virtual non-canonical
        primary-for C (0x40163300)
    B (0x40163340) 0 nearly-empty virtual canonical
        primary-for E (0x401632c0)
        vbaseoffset=-24
  D (0x401633c0) 4 nearly-empty virtual canonical
      subvttidx=28 vptridx=4 vbaseoffset=-28 vptr=((&E::_ZTV1E) + 60)
    C (0x40163400) 4 nearly-empty virtual canonical
        primary-for D (0x401633c0)
        subvttidx=16 vptridx=8 vbaseoffset=-16
      A (0x40163480) 4 nearly-empty virtual canonical
          primary-for C (0x40163400)
          vptridx=12 vbaseoffset=-20
      B (0x40163440) 0 nearly-empty virtual non-canonical

B is chosen as E's primary as it is the first nearly-empty virtual
base that is not already a primary base in inheritance graph order.
Before the primary bases are set up, the canonical virtual bases are
those met in inheritance order (So for C, A & B we get the top
instances rather than the bottom instances). However, C is D's
primary, so we reseat C's canonical base to be the one contained inside
D. Prior to 3130, we also moved all the canonical bases which were
within the outgoing canonical base too. So now we'd have the bottom set
of C, A & B being the canonical bases. This caused problems with
3130, where the canonical binfo for E's primary base B, was not the
one met in inheritance order. So the change I made: when reseating
canonical bases, we only reseat those that are primary to the reseated
binfos (this will be A), and leave those that aren't.

that make sense?

It'd be really nice to have BINFO_UNSHARED_P, so we could determine
this unsharedness simply, rather than having to go along the
inheritance_chain looking for a virtual base and then seeing if that
was canonical. (It'd be even nicer if we didn't have unshared bases ...)

> Looking at the test for 3145, I notice an oddity whereby the primary base
> (C8) of a class (C9) has lost its own primary (C4).  This seems odd to me;
> I would have thought the primary base would have had priority, perhaps
> simply by treating the primary base as though it had been declared first.
> But, of course, it's too late to change this now.  I wish we had had more
> implementation experience before freezing the ABI...
you, me and Mark! This virtual primary base thing has an unbelievable
number of unobvious side effects.

> patch, which does away with orig_last in favor of waiting until we're done
> with all the bases before trying to look at someone else's vtable pointer.
> It also fixes the extra space in 3145 (which, as you said, does not affect
> binary compatibility).  Look reasonable?  I'm going to go ahead and check
> it in after testing.
Yes, your patch looks much simpler - all those sample cases were making me
dizzy! Thanks for looking at this.

> !       tree primary = NULL_TREE;
...
> !       if (b == rtti_binfo
> !         || (b && binfo_for_vbase (BINFO_TYPE (b),
> !                                   BINFO_TYPE (rtti_binfo))))
> !       primary = last;
Unless I'm mistaken, this is the only assignment to PRIMARY, and LAST
must be non-null here, so the next if can be subsumed.

> !       /* Otherwise, this is case 3 and we get our own.  */
> !
> !       if (primary)
> !       /* We're the primary of some binfo that we may not have
> !          met in the inheritance graph walk of RTTI_BINFO.  Just
> !          point to it.  */
> !       vtbl = primary;

nathan

-- 
Dr Nathan Sidwell   ::   http://www.codesourcery.com   ::   CodeSourcery LLC
         'But that's a lie.' - 'Yes it is. What's your point?'
nathan@codesourcery.com : http://www.cs.bris.ac.uk/~nathan/ : nathan@acm.org



More information about the Gcc-patches mailing list