re PR c++/3061 (kde2/artsd miscompilation (part 2))

PR c++/3061
        * class.c (build_secondary_vtable): Use assert, rather than an error
        message.
        (dfs_fixup_binfo_vtbls): BINFO_VTABLE might be NULL.
        (dfs_accumulate_vtbl_inits): A lost primary virtual base may
        be between ORIG_BINFO and RTTI_BINFO, but neither of them.
        Don't set BINFO_VTABLE for a primary virtual base.

Co-Authored-By: Jason Merrill <jason@redhat.com>

From-SVN: r43006
This commit is contained in:
Nathan Sidwell 2001-06-08 11:10:29 +00:00 committed by Jason Merrill
parent 6a1447333f
commit 85a9a0a28b
4 changed files with 125 additions and 58 deletions

View File

@ -1,3 +1,14 @@
2001-06-08 Nathan Sidwell <nathan@codesourcery.com>
Jason Merrill <jason_merrill@redhat.com>
PR c++/3061
* class.c (build_secondary_vtable): Use assert, rather than an error
message.
(dfs_fixup_binfo_vtbls): BINFO_VTABLE might be NULL.
(dfs_accumulate_vtbl_inits): A lost primary virtual base may
be between ORIG_BINFO and RTTI_BINFO, but neither of them.
Don't set BINFO_VTABLE for a primary virtual base.
2001-06-07 Mark Mitchell <mark@codesourcery.com> 2001-06-07 Mark Mitchell <mark@codesourcery.com>
* decl.c (duplicate_decls): Update source position information * decl.c (duplicate_decls): Update source position information

View File

@ -866,19 +866,7 @@ build_secondary_vtable (binfo, for_type)
/* Make fresh virtual list, so we can smash it later. */ /* Make fresh virtual list, so we can smash it later. */
BINFO_VIRTUALS (binfo) = copy_virtuals (binfo); BINFO_VIRTUALS (binfo) = copy_virtuals (binfo);
if (TREE_VIA_VIRTUAL (binfo)) my_friendly_assert (binfo == CANONICAL_BINFO (binfo, for_type), 20010605);
{
tree binfo1 = binfo_for_vbase (BINFO_TYPE (binfo), for_type);
/* XXX - This should never happen, if it does, the caller should
ensure that the binfo is from for_type's binfos, not from any
base type's. We can remove all this code after a while. */
if (binfo1 != binfo)
warning ("internal inconsistency: binfo offset error for rtti");
offset = BINFO_OFFSET (binfo1);
}
else
offset = BINFO_OFFSET (binfo); offset = BINFO_OFFSET (binfo);
/* In the new ABI, secondary vtables are laid out as part of the /* In the new ABI, secondary vtables are laid out as part of the
@ -6744,12 +6732,12 @@ dfs_get_primary_binfo (binfo, data)
return NULL_TREE; return NULL_TREE;
} }
/* Returns the binfo for the primary base of BINFO. Note that in a /* Returns the unshared binfo for the primary base of BINFO. Note
complex hierarchy the resulting BINFO may not actually *be* that in a complex hierarchy the resulting BINFO may not actually
primary. In particular if the resulting BINFO is a virtual base, *be* primary. In particular if the resulting BINFO is a virtual
and it occurs elsewhere in the hierarchy, then this occurrence may base, and it occurs elsewhere in the hierarchy, then this
not actually be a primary base in the complete object. Check occurrence may not actually be a primary base in the complete
BINFO_PRIMARY_P to be sure. */ object. Check BINFO_PRIMARY_P to be sure. */
tree tree
get_primary_binfo (binfo) get_primary_binfo (binfo)
@ -7397,7 +7385,8 @@ dfs_fixup_binfo_vtbls (binfo, data)
/* If we scribbled the construction vtable vptr into BINFO, clear it /* If we scribbled the construction vtable vptr into BINFO, clear it
out now. */ out now. */
if (TREE_CODE (BINFO_VTABLE (binfo)) == TREE_LIST if (BINFO_VTABLE (binfo)
&& TREE_CODE (BINFO_VTABLE (binfo)) == TREE_LIST
&& (TREE_PURPOSE (BINFO_VTABLE (binfo)) && (TREE_PURPOSE (BINFO_VTABLE (binfo))
== TREE_VALUE ((tree) data))) == TREE_VALUE ((tree) data)))
BINFO_VTABLE (binfo) = TREE_CHAIN (BINFO_VTABLE (binfo)); BINFO_VTABLE (binfo) = TREE_CHAIN (BINFO_VTABLE (binfo));
@ -7543,42 +7532,81 @@ dfs_accumulate_vtbl_inits (binfo, orig_binfo, rtti_binfo, t, l)
virtual base. If it is not the same primary in the hierarchy of T, 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 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 location in T. If it is the same primary, we still need a VTT
entry for the vtable, but that must be the base it is a entry for the vtable, but it should point to the ctor vtable for the
primary for within the sub-hierarchy of RTTI_BINFO. */ base it is a primary for within the sub-hierarchy of RTTI_BINFO.
tree parent;
tree best_primary = NULL;
tree primary_for;
my_friendly_assert (BINFO_PRIMARY_P (binfo), 20010131); There are three possible cases:
for (primary_for = BINFO_PRIMARY_BASE_OF (binfo); 1) We are in the same place.
primary_for; 2) We are a primary base within a lost primary virtual base of
primary_for = BINFO_PRIMARY_BASE_OF (primary_for)) 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))))
{ {
for (parent = primary_for; /* Case 1: We're in the same place relative to RTTI_BINFO as we
parent; were in the complete type, so we are primary either to
parent = BINFO_INHERITANCE_CHAIN (parent)) 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))
{ {
if (parent == rtti_binfo) primary = b;
{ if (b == rtti_binfo)
best_primary = primary_for;
break; break;
} }
} }
if (!parent) 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; break;
} }
if (best_primary) /* 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 (best_primary); vtbl = BINFO_VTABLE (primary);
if (TREE_CODE (vtbl) == TREE_LIST) /* If we haven't already been here for our primary derivation,
{ all bets are off. Especially for case 2 above, we need
my_friendly_assert (TREE_PURPOSE (vtbl) == rtti_binfo, the derived vtable to have been generated. */
my_friendly_assert (TREE_CODE (vtbl) == TREE_LIST
&& TREE_PURPOSE (vtbl) == rtti_binfo,
20010126); 20010126);
vtbl = TREE_VALUE (vtbl); vtbl = TREE_VALUE (vtbl);
} }
} }
}
else if (!BINFO_NEW_VTABLE_MARKED (orig_binfo, BINFO_TYPE (rtti_binfo))) else if (!BINFO_NEW_VTABLE_MARKED (orig_binfo, BINFO_TYPE (rtti_binfo)))
return inits; return inits;
@ -7610,9 +7638,10 @@ dfs_accumulate_vtbl_inits (binfo, orig_binfo, rtti_binfo, t, l)
if (!ctor_vtbl_p) if (!ctor_vtbl_p)
{ {
/* For an ordinary vtable, set BINFO_VTABLE. */ /* For an ordinary vtable, set BINFO_VTABLE. */
BINFO_VTABLE (binfo) = vtbl;
if (BINFO_PRIMARY_P (binfo) && TREE_VIA_VIRTUAL (binfo)) if (BINFO_PRIMARY_P (binfo) && TREE_VIA_VIRTUAL (binfo))
inits = NULL_TREE; inits = NULL_TREE;
else
BINFO_VTABLE (binfo) = vtbl;
} }
else else
/* For a construction vtable, we can't overwrite BINFO_VTABLE. /* For a construction vtable, we can't overwrite BINFO_VTABLE.

View File

@ -292,7 +292,7 @@ request for member `%D' is ambiguous in multiple inheritance lattice",
/* Return a thunk to FUNCTION. For a virtual thunk, DELTA is the /* Return a thunk to FUNCTION. For a virtual thunk, DELTA is the
offset to this used to locate the vptr, and VCALL_INDEX is used to offset to this used to locate the vptr, and VCALL_INDEX is used to
look up the eventual subobject location. For a non-virtual thunk, look up the eventual subobject location. For a non-virtual thunk,
DELTA is the offset to this and VCALL_INDEX is zero. */ DELTA is the offset to this and VCALL_INDEX is NULL. */
tree tree
make_thunk (function, delta, vcall_index) make_thunk (function, delta, vcall_index)

View File

@ -0,0 +1,27 @@
// Test for proper handling of extreme virtual inheritance.
// Previously we failed to recognise that in the constructor vtable
// for B_skel in C_skel, A_base was still primary to B_base, even though
// not to B_skel.
// From PR c++/3061.
struct A_base {
virtual void foo() { }
};
class A_skel : virtual public A_base { };
class B_base : virtual public A_base { };
class B_skel : virtual public B_base, virtual public A_skel { };
class C_base : virtual public B_base { };
class C_skel : virtual public C_base, virtual public B_skel { };
class D_base : virtual public C_base { };
class D_skel : virtual public D_base, virtual public C_skel { };
class D_impl : virtual public D_skel { };
int main()
{
D_impl i;
}