This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
bug 3089
- To: gcc-patches at gcc dot gnu dot org
- Subject: bug 3089
- From: Nathan Sidwell <nathan at codesourcery dot com>
- Date: Mon, 11 Jun 2001 16:25:37 +0100
- CC: mark at codesourcery dot com, jason at redhat dot com
- Organization: Codesourcery LLC
Hi,
this fixes bug 3089. It builds and tests ok on i686-pc-linux-gnu,
I'm running a bootstrap now.
The problem is when generating the E-in-F ctor vtable in the following
heirarchy.
F (0x40164980) 0 nearly-empty
vptridx=0 vptr=((&F::_ZTV1F) + 32)
E (0x401649c0) 0 nearly-empty virtual canonical
primary-for F (0x40164980)
subvttidx=24 vptridx=4 vbaseoffset=-32
C (0x40164a80) 0 nearly-empty virtual canonical
primary-for E (0x401649c0)
subvttidx=44 vptridx=8 vbaseoffset=-24
B (0x40164b00) 0 nearly-empty virtual canonical
primary-for C (0x40164a80)
vptridx=12 vbaseoffset=-16
A (0x40164ac0) 4 nearly-empty virtual non-canonical
vptr=((&C::_ZTV1C) + 40)
D (0x40164a00) 4 nearly-empty virtual canonical
subvttidx=56 vptridx=16 vbaseoffset=-28 vptr=((&F::_ZTV1F) + 56)
A (0x40164a40) 4 nearly-empty virtual canonical
primary-for D (0x40164a00)
vptridx=20 vbaseoffset=-20
We do an inheritance graph walk of E's virtual bases which gives us
C, B, A, D. The problem is A. A is the primary base of D, and we
find D's binfo when looking back up the hierarchy. However, as we've not
yet walked D for the ctor-vtable, it's vtable indicates D's vtable pointer
in the complete object F. Hence the ICE. What we want is the D-in-E's
vtable during E's construction.
We can detect this case during the ctor primary base walk, and track
the equivalent ORIG_BINFO (the D-in-complete-E binfo). For this case
we then recursively call dfs_accumulate_vtbl_inits to generate that
vtable. During the inheritance walk when we do the D-in-E case, we
discover we've already generated the vtable.
The equivalent problem does not exist in the complete E case, even though
the hierarchy is identical, because all the BINFO_PRIMARY_BASE_OF
stuff is correct then.
ok?
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
// Copyright (C) 2001 Free Software Foundation, Inc.
// Contributed by Nathan Sidwell 9 Jun 2001 <nathan@codesourcery.com>
// Bug 3089. We ICE'd in construction vtables.
int failed;
void fail (int val)
{
if (!failed)
failed = val;
}
struct A
{
virtual ~A();
A ();
virtual void check (void *whole, void *base);
};
A::A ()
{
check (this, this);
}
A::~A ()
{
check (this, this);
}
void A::check (void *whole, void *base)
{
if (dynamic_cast <void *> (this) != whole)
fail (1);
else if (this != base)
fail (2);
}
struct B
{
virtual ~B ();
B ();
virtual void check (void *whole, void *base);
};
B::B ()
{
check (this, this);
}
B::~B ()
{
check (this, this);
}
void B::check (void *whole, void *base)
{
if (dynamic_cast <void *> (this) != whole)
fail (3);
else if (this != base)
fail (4);
}
struct C : virtual public B, virtual public A
{
virtual ~C ();
C ();
virtual void check (void *whole, void *base);
};
C::C ()
{
check (this, this);
}
C::~C ()
{
check (this, this);
}
void C::check (void *whole, void *base)
{
if (dynamic_cast <void *> (this) != whole)
fail (5);
else if (this != base)
fail (6);
A::check (whole, static_cast <A *> (this));
B::check (whole, static_cast <B *> (this));
}
struct D : virtual public A
{
virtual ~D ();
D ();
virtual void check (void *whole, void *base);
};
D::D ()
{
check (this, this);
}
D::~D ()
{
check (this, this);
}
void D::check (void *whole, void *base)
{
if (dynamic_cast <void *> (this) != whole)
fail (5);
else if (this != base)
fail (6);
A::check (whole, static_cast <A *> (this));
}
struct E : virtual public C, virtual public D
{
virtual ~E ();
E ();
virtual void check (void *whole, void *base);
};
E::E ()
{
check (this, this);
}
E::~E ()
{
check (this, this);
}
void E::check (void *whole, void *base)
{
if (dynamic_cast <void *> (this) != whole)
fail (5);
else if (this != base)
fail (6);
C::check (whole, static_cast <C *> (this));
D::check (whole, static_cast <D *> (this));
}
struct F : virtual public E
{
virtual ~F ();
F ();
virtual void check (void *whole, void *base);
};
F::F ()
{
check (this, this);
}
F::~F ()
{
check (this, this);
}
void F::check (void *whole, void *base)
{
if (dynamic_cast <void *> (this) != whole)
fail (5);
else if (this != base)
fail (6);
E::check (whole, static_cast <F *> (this));
}
int main ()
{
A a;
B b;
C c;
D d;
E e;
F f;
return failed;
}
2001-06-11 Nathan Sidwell <nathan@codesourcery.com>
PR c++/3089
* class.c (dfs_accumulate_vtbl_inits): Always walk down the
hierarchy looking for primary bases for a ctor
vtable. Recursively call oneself, if we meet our primary via
this route and haven't met it yet via inheritance graph order.
Index: cp/class.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/class.c,v
retrieving revision 1.358.2.22
diff -c -3 -p -r1.358.2.22 class.c
*** class.c 2001/06/08 11:09:01 1.358.2.22
--- class.c 2001/06/11 14:46:41
*************** build_ctor_vtbl_group (binfo, t)
*** 7425,7431 ****
tree id;
tree vbase;
! /* See if we've already create this construction vtable group. */
id = mangle_ctor_vtbl_for_type (t, binfo);
if (IDENTIFIER_GLOBAL_VALUE (id))
return;
--- 7425,7431 ----
tree id;
tree vbase;
! /* See if we've already created this construction vtable group. */
id = mangle_ctor_vtbl_for_type (t, binfo);
if (IDENTIFIER_GLOBAL_VALUE (id))
return;
*************** dfs_accumulate_vtbl_inits (binfo, orig_b
*** 7541,7631 ****
tree vtbl = NULL_TREE;
int ctor_vtbl_p = !same_type_p (BINFO_TYPE (rtti_binfo), t);
! if (ctor_vtbl_p
! && TREE_VIA_VIRTUAL (orig_binfo) && BINFO_PRIMARY_P (orig_binfo))
{
! /* In the hierarchy of BINFO_TYPE (RTTI_BINFO), this is a primary
! virtual base. If it is not the same primary in the hierarchy of T,
! we'll need to generate a ctor vtable for it, to place at its
! location in T. If it is the same primary, we still need a VTT
! entry for the vtable, but it should point to the ctor vtable for the
! base it is a primary for within the sub-hierarchy of RTTI_BINFO.
!
! There are three possible cases:
!
! 1) We are in the same place.
! 2) We are a primary base within a lost primary virtual base of
! RTTI_BINFO.
! 3) We are not primary to anything else in RTTI_BINFO. */
!
! tree primary = NULL_TREE;
! if (tree_int_cst_equal (BINFO_OFFSET (orig_binfo),
! size_diffop (BINFO_OFFSET (binfo),
! BINFO_OFFSET (rtti_binfo))))
{
! /* Case 1: We're in the same place relative to RTTI_BINFO as we
! were in the complete type, so we are primary either to
! RTTI_BINFO or one of its secondary bases. */
!
! tree b = BINFO_PRIMARY_BASE_OF (binfo);
!
! /* Walk down our until we either find the last primary base or
! rtti_binfo. */
! for (; b; b = BINFO_PRIMARY_BASE_OF (b))
{
! primary = b;
! if (b == rtti_binfo)
! break;
}
! }
! else
! {
! /* Case 2 or 3: We're not in the same place. We might still be
! primary to something within a lost primary virtual base of
! RTTI_BINFO. */
!
! tree b = BINFO_PRIMARY_BASE_OF (binfo);
! tree last;
!
! /* First, look through the bases we are primary to for a virtual
! base. */
! for (; b; b = BINFO_PRIMARY_BASE_OF (b))
{
! last = b;
! if (TREE_VIA_VIRTUAL (b))
! break;
}
- /* If we run out of primary links, keep looking down our
- inheritance chain; we might be an indirect primary of a
- virtual base. */
- if (b == NULL_TREE)
- for (b = last; b; b = BINFO_INHERITANCE_CHAIN (b))
- if (TREE_VIA_VIRTUAL (b))
- break;
-
- /* If we found a virtual base B and it is a base of RTTI_BINFO, we
- share our vtable with LAST, i.e. the derived-most base within
- B of which we are a primary. Otherwise, we get our own. */
- if (b && binfo_for_vbase (BINFO_TYPE (b),
- BINFO_TYPE (rtti_binfo)))
- primary = last;
}
!
! if (primary)
{
- vtbl = BINFO_VTABLE (primary);
- /* If we haven't already been here for our primary derivation,
- all bets are off. Especially for case 2 above, we need
- the derived vtable to have been generated. */
- my_friendly_assert (TREE_CODE (vtbl) == TREE_LIST
- && TREE_PURPOSE (vtbl) == rtti_binfo,
- 20010126);
vtbl = TREE_VALUE (vtbl);
}
}
else if (!BINFO_NEW_VTABLE_MARKED (orig_binfo, BINFO_TYPE (rtti_binfo)))
return inits;
!
if (!vtbl)
{
tree index;
--- 7541,7658 ----
tree vtbl = NULL_TREE;
int ctor_vtbl_p = !same_type_p (BINFO_TYPE (rtti_binfo), t);
! if (ctor_vtbl_p)
{
! tree primary = binfo;
! tree orig_primary = orig_binfo;
!
! if (TREE_VIA_VIRTUAL (orig_binfo) && BINFO_PRIMARY_P (orig_binfo))
{
! /* In the hierarchy of BINFO_TYPE (RTTI_BINFO), this is a
! primary virtual base. If it is not the same primary in
! the hierarchy of T, we'll need to generate a ctor vtable
! for it, to place at its location in T. If it is the same
! primary, we still need a VTT entry for the vtable, but it
! should point to the ctor vtable for the base it is a
! primary for within the sub-hierarchy of RTTI_BINFO.
!
! There are three possible cases:
!
! 1) We are in the same place.
! 2) We are a primary base within a lost primary virtual base of
! RTTI_BINFO.
! 3) We are not primary to anything else in RTTI_BINFO. */
!
! if (tree_int_cst_equal (BINFO_OFFSET (orig_binfo),
! size_diffop (BINFO_OFFSET (binfo),
! BINFO_OFFSET (rtti_binfo))))
{
! /* Case 1: We're in the same place relative to
! RTTI_BINFO as we were in the complete type, so we are
! primary either to RTTI_BINFO or one of its secondary
! bases. */
!
! /* Walk down our until we either find the last
! primary base or rtti_binfo. */
! tree b = BINFO_PRIMARY_BASE_OF (binfo);
!
! for (; b; b = BINFO_PRIMARY_BASE_OF (b))
! {
! primary = b;
! orig_primary = BINFO_PRIMARY_BASE_OF (orig_primary);
! if (b == rtti_binfo)
! break;
! }
}
! else
{
! /* Case 2 or 3: We're not in the same place. We might
! still be primary to something within a lost primary
! virtual base of RTTI_BINFO. */
! tree b;
! tree last, orig_last;
!
! /* First, look through the bases we are primary to for a
! virtual base. */
! for (b = BINFO_PRIMARY_BASE_OF (binfo), orig_last = orig_binfo;
! b;
! b = BINFO_PRIMARY_BASE_OF (b))
! {
! last = b;
! if (orig_last)
! orig_last = BINFO_PRIMARY_BASE_OF (orig_last);
! if (TREE_VIA_VIRTUAL (b))
! break;
! }
! /* If we run out of primary links, keep looking down our
! inheritance chain; we might be an indirect primary of
! a virtual base. */
! if (b == NULL_TREE)
! for (b = last; b; b = BINFO_INHERITANCE_CHAIN (b))
! if (TREE_VIA_VIRTUAL (b))
! break;
!
! /* If we found a virtual base B and it is a base of
! RTTI_BINFO, we share our vtable with LAST, i.e. the
! derived-most base within B of which we are a primary.
! Otherwise, we get our own. */
! if (b && binfo_for_vbase (BINFO_TYPE (b),
! BINFO_TYPE (rtti_binfo)))
! {
! my_friendly_assert (orig_last, 20010611);
! primary = last;
! orig_primary = orig_last;
! }
}
}
!
! vtbl = BINFO_VTABLE (primary);
! if (vtbl && TREE_CODE (vtbl) == TREE_LIST
! && TREE_PURPOSE (vtbl) == rtti_binfo)
{
vtbl = TREE_VALUE (vtbl);
+ if (primary == binfo)
+ /* We created this vtable because we met its primary base
+ earlier in the inheritance graph walk of
+ RTTI_BINFO. */
+ return inits;
}
+ else if (primary != binfo)
+ {
+ /* We're the primary of some binfo that we've not yet
+ met in the inheritance graph walk of RTTI_BINFO. We
+ must create that vtable now. */
+ inits = dfs_accumulate_vtbl_inits (primary, orig_primary,
+ rtti_binfo, t, l);
+ vtbl = BINFO_VTABLE (primary);
+ vtbl = TREE_VALUE (vtbl);
+ }
+ else
+ vtbl = NULL;
}
else if (!BINFO_NEW_VTABLE_MARKED (orig_binfo, BINFO_TYPE (rtti_binfo)))
return inits;
!
if (!vtbl)
{
tree index;
*************** dfs_accumulate_vtbl_inits (binfo, orig_b
*** 7650,7668 ****
TREE_CONSTANT (vtbl) = 1;
}
! if (!ctor_vtbl_p)
! {
! /* For an ordinary vtable, set BINFO_VTABLE. */
! if (BINFO_PRIMARY_P (binfo) && TREE_VIA_VIRTUAL (binfo))
! inits = NULL_TREE;
! else
! BINFO_VTABLE (binfo) = vtbl;
! }
! else
/* For a construction vtable, we can't overwrite BINFO_VTABLE.
So, we make a TREE_LIST. Later, dfs_fixup_binfo_vtbls will
straighten this out. */
BINFO_VTABLE (binfo) = tree_cons (rtti_binfo, vtbl, BINFO_VTABLE (binfo));
return inits;
}
--- 7677,7692 ----
TREE_CONSTANT (vtbl) = 1;
}
! if (ctor_vtbl_p)
/* For a construction vtable, we can't overwrite BINFO_VTABLE.
So, we make a TREE_LIST. Later, dfs_fixup_binfo_vtbls will
straighten this out. */
BINFO_VTABLE (binfo) = tree_cons (rtti_binfo, vtbl, BINFO_VTABLE (binfo));
+ else if (BINFO_PRIMARY_P (binfo) && TREE_VIA_VIRTUAL (binfo))
+ inits = NULL_TREE;
+ else
+ /* For an ordinary vtable, set BINFO_VTABLE. */
+ BINFO_VTABLE (binfo) = vtbl;
return inits;
}