mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-01-28 00:24:38 +08:00
class.c (create_vtable_ptr): Put the vtable at the beginning of the class, not the end, in the new ABI.
* class.c (create_vtable_ptr): Put the vtable at the beginning of the class, not the end, in the new ABI. * tree.c (propagate_binfo_offsets): Do the right thing for the new ABI. From-SVN: r31120
This commit is contained in:
parent
71e33c0d12
commit
80ec27c8f4
@ -1,3 +1,10 @@
|
||||
1999-12-29 Mark Mitchell <mark@codesourcery.com>
|
||||
|
||||
* class.c (create_vtable_ptr): Put the vtable at the beginning of
|
||||
the class, not the end, in the new ABI.
|
||||
* tree.c (propagate_binfo_offsets): Do the right thing for the new
|
||||
ABI.
|
||||
|
||||
1999-12-29 Mark Mitchell <mark@codesourcery.com>
|
||||
|
||||
* cp-tree.h (lang_type): Add nearly_empty_p. Adjust dummy.
|
||||
|
@ -4136,7 +4136,22 @@ create_vtable_ptr (t, empty_p, has_virtual_p, max_has_virtual_p,
|
||||
empty_p);
|
||||
|
||||
/* Add the new field to the list of fields in this class. */
|
||||
TYPE_FIELDS (t) = chainon (TYPE_FIELDS (t), TYPE_VFIELD (t));
|
||||
if (!flag_new_abi)
|
||||
/* In the old ABI, the vtable pointer goes at the end of the
|
||||
class. */
|
||||
TYPE_FIELDS (t) = chainon (TYPE_FIELDS (t), TYPE_VFIELD (t));
|
||||
else
|
||||
{
|
||||
/* But in the new ABI, the vtable pointer is the first thing
|
||||
in the class. */
|
||||
TYPE_FIELDS (t) = chainon (TYPE_VFIELD (t), TYPE_FIELDS (t));
|
||||
/* If there were any baseclasses, they can't possibly be at
|
||||
offset zero any more, because that's where the vtable
|
||||
pointer is. So, converting to a base class is going to
|
||||
take work. */
|
||||
if (CLASSTYPE_N_BASECLASSES (t))
|
||||
TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (t) = 1;
|
||||
}
|
||||
|
||||
/* We can't yet add this new field to the list of all virtual
|
||||
function table pointers in this class. The
|
||||
|
@ -671,36 +671,81 @@ propagate_binfo_offsets (binfo, offset)
|
||||
tree binfos = BINFO_BASETYPES (binfo);
|
||||
int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
|
||||
|
||||
for (i = 0; i < n_baselinks; /* note increment is done in the loop. */)
|
||||
if (flag_new_abi)
|
||||
{
|
||||
tree base_binfo = TREE_VEC_ELT (binfos, i);
|
||||
|
||||
if (TREE_VIA_VIRTUAL (base_binfo))
|
||||
i += 1;
|
||||
else
|
||||
for (i = 0; i < n_baselinks; ++i)
|
||||
{
|
||||
int j;
|
||||
tree delta = NULL_TREE;
|
||||
tree base_binfo;
|
||||
|
||||
for (j = i+1; j < n_baselinks; j++)
|
||||
if (! TREE_VIA_VIRTUAL (TREE_VEC_ELT (binfos, j)))
|
||||
{
|
||||
/* The next basetype offset must take into account the space
|
||||
between the classes, not just the size of each class. */
|
||||
delta = size_binop (MINUS_EXPR,
|
||||
BINFO_OFFSET (TREE_VEC_ELT (binfos, j)),
|
||||
BINFO_OFFSET (base_binfo));
|
||||
break;
|
||||
}
|
||||
/* Figure out which base we're looking at. */
|
||||
base_binfo = TREE_VEC_ELT (binfos, i);
|
||||
|
||||
BINFO_OFFSET (base_binfo) = offset;
|
||||
/* Skip virtual bases. Their BINFO_OFFSET doesn't matter
|
||||
since they are always reached by using offsets looked up
|
||||
at run-time. */
|
||||
if (TREE_VIA_VIRTUAL (base_binfo))
|
||||
continue;
|
||||
|
||||
/* Whatever offset this class used to have in its immediate
|
||||
derived class, it is now at OFFSET more bytes in its
|
||||
final derived class, since the immediate derived class is
|
||||
already at the indicated OFFSET. */
|
||||
BINFO_OFFSET (base_binfo)
|
||||
= size_binop (PLUS_EXPR, BINFO_OFFSET (base_binfo), offset);
|
||||
|
||||
propagate_binfo_offsets (base_binfo, offset);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* This algorithm, used for the old ABI, is neither simple, nor
|
||||
general. For example, it mishandles the case of:
|
||||
|
||||
struct A;
|
||||
struct B : public A;
|
||||
struct C : public B;
|
||||
|
||||
if B is at offset zero in C, but A is not in offset zero in
|
||||
B. In that case, it sets the BINFO_OFFSET for A to zero.
|
||||
(This sitution arises in the new ABI if B has virtual
|
||||
functions, but A does not.) Rather than change this
|
||||
algorithm, and risking breaking the old ABI, it is preserved
|
||||
here. */
|
||||
for (i = 0; i < n_baselinks; /* note increment is done in the
|
||||
loop. */)
|
||||
{
|
||||
tree base_binfo = TREE_VEC_ELT (binfos, i);
|
||||
|
||||
/* Go to our next class that counts for offset propagation. */
|
||||
i = j;
|
||||
if (i < n_baselinks)
|
||||
offset = size_binop (PLUS_EXPR, offset, delta);
|
||||
if (TREE_VIA_VIRTUAL (base_binfo))
|
||||
i += 1;
|
||||
else
|
||||
{
|
||||
int j;
|
||||
tree delta = NULL_TREE;
|
||||
|
||||
for (j = i+1; j < n_baselinks; j++)
|
||||
if (! TREE_VIA_VIRTUAL (TREE_VEC_ELT (binfos, j)))
|
||||
{
|
||||
/* The next basetype offset must take into account
|
||||
the space between the classes, not just the
|
||||
size of each class. */
|
||||
delta = size_binop (MINUS_EXPR,
|
||||
BINFO_OFFSET (TREE_VEC_ELT (binfos,
|
||||
j)),
|
||||
BINFO_OFFSET (base_binfo));
|
||||
break;
|
||||
}
|
||||
|
||||
BINFO_OFFSET (base_binfo) = offset;
|
||||
|
||||
propagate_binfo_offsets (base_binfo, offset);
|
||||
|
||||
/* Go to our next class that counts for offset
|
||||
propagation. */
|
||||
i = j;
|
||||
if (i < n_baselinks)
|
||||
offset = size_binop (PLUS_EXPR, offset, delta);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user