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:
parent
6a1447333f
commit
85a9a0a28b
@ -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
|
||||||
|
115
gcc/cp/class.c
115
gcc/cp/class.c
@ -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.
|
||||||
|
@ -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)
|
||||||
|
27
gcc/testsuite/g++.old-deja/g++.abi/vtable4.C
Normal file
27
gcc/testsuite/g++.old-deja/g++.abi/vtable4.C
Normal 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;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user