cp-tree.h (dfs_mark_primary_bases_queue_p): New function.
* cp-tree.h (dfs_mark_primary_bases_queue_p): New function. (layout_basetypes): Remove. * class.c (propagate_binfo_offsets): Moved here from tree.c. Update to handle primary virtual bases. (remove_base_fields): New function, split out from layout_basetypes. (dfs_mark_primary_bases_and_set_vbase_offsets): New function. (layout_virtual_bases): New function, split out from layout_basetypes. Update to handle primary virtual bases. (layout_basetypes): Moved here from tree.c. Use remove_base_fields and layout_virtual_bases. * search.c (dfs_mark_primary_bases_queue_p): New function. (mark_primary_bases): Use it. * tree.c (CEIL): Remove. (propagate_binfo_offsets): Remove. (layout_basetypes): Remove. From-SVN: r31168
This commit is contained in:
parent
13799af323
commit
80fd5f4866
@ -1,3 +1,22 @@
|
||||
2000-01-02 Mark Mitchell <mark@codesourcery.com>
|
||||
|
||||
* cp-tree.h (dfs_mark_primary_bases_queue_p): New function.
|
||||
(layout_basetypes): Remove.
|
||||
* class.c (propagate_binfo_offsets): Moved here from tree.c.
|
||||
Update to handle primary virtual bases.
|
||||
(remove_base_fields): New function, split out from
|
||||
layout_basetypes.
|
||||
(dfs_mark_primary_bases_and_set_vbase_offsets): New function.
|
||||
(layout_virtual_bases): New function, split out from
|
||||
layout_basetypes. Update to handle primary virtual bases.
|
||||
(layout_basetypes): Moved here from tree.c. Use
|
||||
remove_base_fields and layout_virtual_bases.
|
||||
* search.c (dfs_mark_primary_bases_queue_p): New function.
|
||||
(mark_primary_bases): Use it.
|
||||
* tree.c (CEIL): Remove.
|
||||
(propagate_binfo_offsets): Remove.
|
||||
(layout_basetypes): Remove.
|
||||
|
||||
2000-01-01 Mark Mitchell <mark@codesourcery.com>
|
||||
|
||||
* cp-tree.h (skip_rtti_stuff): Adjust prototype.
|
||||
|
319
gcc/cp/class.c
319
gcc/cp/class.c
@ -138,6 +138,11 @@ static void layout_class_type PROTO((tree, int *, int *, int *, tree *, tree *))
|
||||
static void fixup_pending_inline PROTO((struct pending_inline *));
|
||||
static void fixup_inline_methods PROTO((tree));
|
||||
static void set_primary_base PROTO((tree, int, int *));
|
||||
static void propagate_binfo_offsets PROTO((tree, tree));
|
||||
static int layout_basetypes PROTO((tree, int));
|
||||
static tree dfs_mark_primary_bases_and_set_vbase_offsets PROTO((tree, void *));
|
||||
static int layout_virtual_bases PROTO((tree, int));
|
||||
static void remove_base_fields PROTO((tree));
|
||||
|
||||
/* Variables shared between class.c and call.c. */
|
||||
|
||||
@ -4143,6 +4148,320 @@ fixup_inline_methods (type)
|
||||
CLASSTYPE_INLINE_FRIENDS (type) = NULL_TREE;
|
||||
}
|
||||
|
||||
/* Add OFFSET to all base types of T.
|
||||
|
||||
OFFSET, which is a type offset, is number of bytes.
|
||||
|
||||
Note that we don't have to worry about having two paths to the
|
||||
same base type, since this type owns its association list. */
|
||||
|
||||
static void
|
||||
propagate_binfo_offsets (binfo, offset)
|
||||
tree binfo;
|
||||
tree offset;
|
||||
{
|
||||
tree binfos = BINFO_BASETYPES (binfo);
|
||||
int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
|
||||
|
||||
if (flag_new_abi)
|
||||
{
|
||||
for (i = 0; i < n_baselinks; ++i)
|
||||
{
|
||||
tree base_binfo;
|
||||
|
||||
/* Figure out which base we're looking at. */
|
||||
base_binfo = TREE_VEC_ELT (binfos, i);
|
||||
|
||||
/* Skip non-primary 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)
|
||||
&& i != CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (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);
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Remove the FIELD_DECLs created for T's base classes in
|
||||
build_base_fields. Simultaneously, update BINFO_OFFSET for all the
|
||||
bases, except for non-primary virtual baseclasses. */
|
||||
|
||||
static void
|
||||
remove_base_fields (t)
|
||||
tree t;
|
||||
{
|
||||
int i;
|
||||
tree *field;
|
||||
|
||||
/* Now propagate offset information throughout the lattice.
|
||||
Simultaneously, remove the temporary FIELD_DECLS we created in
|
||||
build_base_fields to refer to base types. */
|
||||
field = &TYPE_FIELDS (t);
|
||||
if (TYPE_VFIELD (t) == *field)
|
||||
{
|
||||
/* If this class did not have a primary base, we create a
|
||||
virtual function table pointer. It will be the first thing
|
||||
in the class, under the new ABI. Skip it; the base fields
|
||||
will follow it. */
|
||||
my_friendly_assert (flag_new_abi
|
||||
&& !CLASSTYPE_HAS_PRIMARY_BASE_P (t),
|
||||
19991218);
|
||||
field = &TREE_CHAIN (*field);
|
||||
}
|
||||
|
||||
for (i = 0; i < CLASSTYPE_N_BASECLASSES (t); i++)
|
||||
{
|
||||
register tree base_binfo = BINFO_BASETYPE (TYPE_BINFO (t), i);
|
||||
register tree basetype = BINFO_TYPE (base_binfo);
|
||||
|
||||
/* We treat a primary virtual base class just like an ordinary
|
||||
base class. But, non-primary virtual bases are laid out
|
||||
later. */
|
||||
if (TREE_VIA_VIRTUAL (base_binfo) && i != CLASSTYPE_VFIELD_PARENT (t))
|
||||
continue;
|
||||
|
||||
my_friendly_assert (TREE_TYPE (*field) == basetype, 23897);
|
||||
|
||||
if (get_base_distance (basetype, t, 0, (tree*)0) == -2)
|
||||
cp_warning ("direct base `%T' inaccessible in `%T' due to ambiguity",
|
||||
basetype, t);
|
||||
|
||||
BINFO_OFFSET (base_binfo)
|
||||
= size_int (CEIL (TREE_INT_CST_LOW (DECL_FIELD_BITPOS (*field)),
|
||||
BITS_PER_UNIT));
|
||||
propagate_binfo_offsets (base_binfo, BINFO_OFFSET (base_binfo));
|
||||
|
||||
/* Remove this field. */
|
||||
*field = TREE_CHAIN (*field);
|
||||
}
|
||||
}
|
||||
|
||||
/* Called via dfs_walk from layout_virtual_bases. */
|
||||
|
||||
static tree
|
||||
dfs_mark_primary_bases_and_set_vbase_offsets (binfo, data)
|
||||
tree binfo;
|
||||
void *data;
|
||||
{
|
||||
if (CLASSTYPE_HAS_PRIMARY_BASE_P (BINFO_TYPE (binfo)))
|
||||
{
|
||||
int i;
|
||||
tree base_binfo;
|
||||
|
||||
i = CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (binfo));
|
||||
base_binfo = BINFO_BASETYPE (binfo, i);
|
||||
|
||||
/* If this is a virtual base class, and we've just now
|
||||
discovered it to be a primary base, then reuse this copy as
|
||||
the virtual base class for the complete object. */
|
||||
if (TREE_VIA_VIRTUAL (base_binfo)
|
||||
&& !BINFO_PRIMARY_MARKED_P (base_binfo))
|
||||
{
|
||||
tree vbase;
|
||||
|
||||
vbase = BINFO_FOR_VBASE (BINFO_TYPE (base_binfo), (tree) data);
|
||||
BINFO_OFFSET (vbase) = BINFO_OFFSET (base_binfo);
|
||||
}
|
||||
|
||||
SET_BINFO_PRIMARY_MARKED_P (BINFO_BASETYPE (binfo, i));
|
||||
}
|
||||
|
||||
SET_BINFO_MARKED (binfo);
|
||||
|
||||
return NULL_TREE;
|
||||
}
|
||||
|
||||
/* Set BINFO_OFFSET for all of the virtual bases for T. Update
|
||||
TYPE_ALIGN and TYPE_SIZE for T. Return the maximum of MAX and the
|
||||
largest CLASSTYPE_VSIZE for any of the virtual bases. */
|
||||
|
||||
static int
|
||||
layout_virtual_bases (t, max)
|
||||
tree t;
|
||||
int max;
|
||||
{
|
||||
tree vbase;
|
||||
int dsize;
|
||||
|
||||
/* Mark the primary base classes. Only virtual bases that are not
|
||||
also primary base classes need to be laid out (since otherwise we
|
||||
can just reuse one of the places in the hierarchy where the
|
||||
virtual base already occurs.) */
|
||||
dfs_walk (TYPE_BINFO (t),
|
||||
dfs_mark_primary_bases_and_set_vbase_offsets,
|
||||
dfs_mark_primary_bases_queue_p,
|
||||
t);
|
||||
|
||||
/* DSIZE is the size of the class without the virtual bases. */
|
||||
dsize = TREE_INT_CST_LOW (TYPE_SIZE (t));
|
||||
/* Make every class have alignment of at least one. */
|
||||
TYPE_ALIGN (t) = MAX (TYPE_ALIGN (t), BITS_PER_UNIT);
|
||||
|
||||
for (vbase = CLASSTYPE_VBASECLASSES (t);
|
||||
vbase;
|
||||
vbase = TREE_CHAIN (vbase))
|
||||
if (!BINFO_PRIMARY_MARKED_P (vbase))
|
||||
{
|
||||
/* This virtual base is not a primary base of any class in the
|
||||
hierarchy, so we have to add space for it. */
|
||||
tree basetype;
|
||||
unsigned int desired_align;
|
||||
|
||||
basetype = BINFO_TYPE (vbase);
|
||||
desired_align = TYPE_ALIGN (basetype);
|
||||
TYPE_ALIGN (t) = MAX (TYPE_ALIGN (t), desired_align);
|
||||
|
||||
/* Add padding so that we can put the virtual base class at an
|
||||
appropriately aligned offset. */
|
||||
dsize = CEIL (dsize, desired_align) * desired_align;
|
||||
/* And compute the offset of the virtual base. */
|
||||
BINFO_OFFSET (vbase) = size_int (CEIL (dsize, BITS_PER_UNIT));
|
||||
/* Every virtual baseclass takes a least a UNIT, so that we can
|
||||
take it's address and get something different for each base. */
|
||||
dsize += MAX (BITS_PER_UNIT,
|
||||
TREE_INT_CST_LOW (CLASSTYPE_SIZE (basetype)));
|
||||
|
||||
/* Now that we've laid out this virtual base class, some of
|
||||
the remaining virtual bases might have been implicitly laid
|
||||
out as well -- they could be primary base classes of
|
||||
classes in BASETYPE. */
|
||||
dfs_walk (vbase,
|
||||
dfs_mark_primary_bases_and_set_vbase_offsets,
|
||||
dfs_mark_primary_bases_queue_p,
|
||||
t);
|
||||
|
||||
/* While we're here, see if this new virtual base class has
|
||||
more virtual functions than we expected. */
|
||||
max = MAX (CLASSTYPE_VSIZE (basetype), max);
|
||||
}
|
||||
|
||||
/* We're done with the various marks, now, so clear them. */
|
||||
unmark_primary_bases (t);
|
||||
dfs_walk (TYPE_BINFO (t), dfs_unmark, markedp, 0);
|
||||
|
||||
/* Now, make sure that the total size of the type is a multiple of
|
||||
its alignment. */
|
||||
dsize = CEIL (dsize, TYPE_ALIGN (t)) * TYPE_ALIGN (t);
|
||||
TYPE_SIZE (t) = size_int (dsize);
|
||||
TYPE_SIZE_UNIT (t) = size_binop (FLOOR_DIV_EXPR, TYPE_SIZE (t),
|
||||
size_int (BITS_PER_UNIT));
|
||||
|
||||
return max;
|
||||
}
|
||||
|
||||
/* Finish the work of layout_record, now taking virtual bases into account.
|
||||
Also compute the actual offsets that our base classes will have.
|
||||
This must be performed after the fields are laid out, since virtual
|
||||
baseclasses must lay down at the end of the record.
|
||||
|
||||
Returns the maximum number of virtual functions any of the
|
||||
baseclasses provide. */
|
||||
|
||||
static int
|
||||
layout_basetypes (rec, max)
|
||||
tree rec;
|
||||
int max;
|
||||
{
|
||||
tree vbase_types;
|
||||
|
||||
#ifdef STRUCTURE_SIZE_BOUNDARY
|
||||
/* Packed structures don't need to have minimum size. */
|
||||
if (! TYPE_PACKED (rec))
|
||||
TYPE_ALIGN (rec) = MAX (TYPE_ALIGN (rec), STRUCTURE_SIZE_BOUNDARY);
|
||||
#endif
|
||||
|
||||
/* Remove the FIELD_DECLs we created for baseclasses in
|
||||
build_base_fields. Simultaneously, update the BINFO_OFFSETs for
|
||||
everything in the hierarcy except non-primary virtual bases. */
|
||||
remove_base_fields (rec);
|
||||
|
||||
/* Allocate the virtual base classes. */
|
||||
max = layout_virtual_bases (rec, max);
|
||||
|
||||
/* Get all the virtual base types that this type uses. The
|
||||
TREE_VALUE slot holds the virtual baseclass type. Note that
|
||||
get_vbase_types makes copies of the virtual base BINFOs, so that
|
||||
the vbase_types are unshared. */
|
||||
for (vbase_types = CLASSTYPE_VBASECLASSES (rec); vbase_types;
|
||||
vbase_types = TREE_CHAIN (vbase_types))
|
||||
{
|
||||
BINFO_INHERITANCE_CHAIN (vbase_types) = TYPE_BINFO (rec);
|
||||
unshare_base_binfos (vbase_types);
|
||||
propagate_binfo_offsets (vbase_types, BINFO_OFFSET (vbase_types));
|
||||
|
||||
if (extra_warnings)
|
||||
{
|
||||
tree basetype = BINFO_TYPE (vbase_types);
|
||||
if (get_base_distance (basetype, rec, 0, (tree*)0) == -2)
|
||||
cp_warning ("virtual base `%T' inaccessible in `%T' due to ambiguity",
|
||||
basetype, rec);
|
||||
}
|
||||
}
|
||||
|
||||
return max;
|
||||
}
|
||||
|
||||
/* Calculate the TYPE_SIZE, TYPE_ALIGN, etc for T. Calculate
|
||||
BINFO_OFFSETs for all of the base-classes. Position the vtable
|
||||
pointer. */
|
||||
|
@ -3909,6 +3909,7 @@ extern tree dfs_walk PROTO((tree,
|
||||
void *));
|
||||
extern tree dfs_unmark PROTO((tree, void *));
|
||||
extern tree markedp PROTO((tree, void *));
|
||||
extern tree dfs_mark_primary_bases_queue_p PROTO((tree, void *));
|
||||
extern void mark_primary_bases PROTO((tree));
|
||||
extern void unmark_primary_bases PROTO((tree));
|
||||
|
||||
@ -4028,7 +4029,6 @@ extern tree break_out_calls PROTO((tree));
|
||||
extern tree build_cplus_method_type PROTO((tree, tree, tree));
|
||||
extern tree build_cplus_staticfn_type PROTO((tree, tree, tree));
|
||||
extern tree build_cplus_array_type PROTO((tree, tree));
|
||||
extern int layout_basetypes PROTO((tree, int));
|
||||
extern tree hash_tree_cons PROTO((tree, tree, tree));
|
||||
extern tree hash_tree_chain PROTO((tree, tree));
|
||||
extern tree hash_chainon PROTO((tree, tree));
|
||||
|
@ -2104,7 +2104,7 @@ get_matching_virtual (binfo, fndecl, dtorp)
|
||||
}
|
||||
}
|
||||
|
||||
/* Called via dfs_walk from mark_nonprimary_bases. */
|
||||
/* Called via dfs_walk from mark_primary_bases. */
|
||||
|
||||
static tree
|
||||
dfs_mark_primary_bases (binfo, data)
|
||||
@ -2124,6 +2124,31 @@ dfs_mark_primary_bases (binfo, data)
|
||||
return NULL_TREE;
|
||||
}
|
||||
|
||||
/* Called via dfs_walk from mark_primary_bases. */
|
||||
|
||||
tree
|
||||
dfs_mark_primary_bases_queue_p (binfo, data)
|
||||
tree binfo;
|
||||
void *data ATTRIBUTE_UNUSED;
|
||||
{
|
||||
/* Don't walk into virtual baseclasses that are not primary
|
||||
bases. */
|
||||
if (TREE_VIA_VIRTUAL (binfo))
|
||||
{
|
||||
tree derived_class;
|
||||
tree primary_base;
|
||||
|
||||
derived_class = BINFO_TYPE (BINFO_INHERITANCE_CHAIN (binfo));
|
||||
primary_base = CLASSTYPE_PRIMARY_BINFO (derived_class);
|
||||
if (!primary_base || !same_type_p (BINFO_TYPE (primary_base),
|
||||
BINFO_TYPE (binfo)))
|
||||
return NULL_TREE;
|
||||
}
|
||||
|
||||
/* But do walk into everything else. */
|
||||
return binfo;
|
||||
}
|
||||
|
||||
/* Set BINFO_PRIMARY_MARKED_P for all binfos in the hierarchy
|
||||
dominated by TYPE that are primary bases. (In addition,
|
||||
BINFO_MARKED is set for all classes in the hierarchy; callers
|
||||
@ -2135,7 +2160,7 @@ mark_primary_bases (type)
|
||||
{
|
||||
dfs_walk (TYPE_BINFO (type),
|
||||
dfs_mark_primary_bases,
|
||||
unmarkedp,
|
||||
dfs_mark_primary_bases_queue_p,
|
||||
NULL);
|
||||
}
|
||||
|
||||
|
245
gcc/cp/tree.c
245
gcc/cp/tree.c
@ -37,7 +37,6 @@ static tree build_cplus_array_type_1 PROTO((tree, tree));
|
||||
static void list_hash_add PROTO((int, tree));
|
||||
static int list_hash PROTO((tree, tree, tree));
|
||||
static tree list_hash_lookup PROTO((int, tree, tree, tree));
|
||||
static void propagate_binfo_offsets PROTO((tree, tree));
|
||||
static cp_lvalue_kind lvalue_p_1 PROTO((tree, int));
|
||||
static tree no_linkage_helper PROTO((tree *, int *, void *));
|
||||
static tree build_srcloc PROTO((char *, int));
|
||||
@ -48,8 +47,6 @@ static tree cp_unsave_r PROTO ((tree *, int *, void *));
|
||||
static void cp_unsave PROTO((tree *));
|
||||
static tree build_target_expr PROTO((tree, tree));
|
||||
|
||||
#define CEIL(x,y) (((x) + (y) - 1) / (y))
|
||||
|
||||
/* If REF is an lvalue, returns the kind of lvalue that REF is.
|
||||
Otherwise, returns clk_none. If TREAT_CLASS_RVALUES_AS_LVALUES is
|
||||
non-zero, rvalues of class type are considered lvalues. */
|
||||
@ -656,100 +653,6 @@ canonical_type_variant (t)
|
||||
return cp_build_qualified_type (TYPE_MAIN_VARIANT (t), CP_TYPE_QUALS (t));
|
||||
}
|
||||
|
||||
/* Add OFFSET to all base types of T.
|
||||
|
||||
OFFSET, which is a type offset, is number of bytes.
|
||||
|
||||
Note that we don't have to worry about having two paths to the
|
||||
same base type, since this type owns its association list. */
|
||||
|
||||
static void
|
||||
propagate_binfo_offsets (binfo, offset)
|
||||
tree binfo;
|
||||
tree offset;
|
||||
{
|
||||
tree binfos = BINFO_BASETYPES (binfo);
|
||||
int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
|
||||
|
||||
if (flag_new_abi)
|
||||
{
|
||||
for (i = 0; i < n_baselinks; ++i)
|
||||
{
|
||||
tree base_binfo;
|
||||
|
||||
/* Figure out which base we're looking at. */
|
||||
base_binfo = TREE_VEC_ELT (binfos, i);
|
||||
|
||||
/* 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);
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Makes new binfos for the indirect bases under BINFO, and updates
|
||||
BINFO_OFFSET for them and their bases. */
|
||||
|
||||
@ -782,154 +685,6 @@ unshare_base_binfos (binfo)
|
||||
}
|
||||
}
|
||||
|
||||
/* Finish the work of layout_record, now taking virtual bases into account.
|
||||
Also compute the actual offsets that our base classes will have.
|
||||
This must be performed after the fields are laid out, since virtual
|
||||
baseclasses must lay down at the end of the record.
|
||||
|
||||
Returns the maximum number of virtual functions any of the
|
||||
baseclasses provide. */
|
||||
|
||||
int
|
||||
layout_basetypes (rec, max)
|
||||
tree rec;
|
||||
int max;
|
||||
{
|
||||
tree binfos = TYPE_BINFO_BASETYPES (rec);
|
||||
int i, n_baseclasses = CLASSTYPE_N_BASECLASSES (rec);
|
||||
tree vbase_types;
|
||||
tree *field;
|
||||
|
||||
unsigned int record_align = MAX (BITS_PER_UNIT, TYPE_ALIGN (rec));
|
||||
unsigned int desired_align;
|
||||
|
||||
/* Record size so far is CONST_SIZE bits, where CONST_SIZE is an integer. */
|
||||
register unsigned int const_size = 0;
|
||||
unsigned int nonvirtual_const_size;
|
||||
|
||||
#ifdef STRUCTURE_SIZE_BOUNDARY
|
||||
/* Packed structures don't need to have minimum size. */
|
||||
if (! TYPE_PACKED (rec))
|
||||
record_align = MAX (record_align, STRUCTURE_SIZE_BOUNDARY);
|
||||
#endif
|
||||
|
||||
/* Get all the virtual base types that this type uses. The
|
||||
TREE_VALUE slot holds the virtual baseclass type. Note that
|
||||
get_vbase_types makes copies of the virtual base BINFOs, so that
|
||||
the vbase_types are unshared. */
|
||||
vbase_types = CLASSTYPE_VBASECLASSES (rec);
|
||||
|
||||
my_friendly_assert (TREE_CODE (TYPE_SIZE (rec)) == INTEGER_CST, 19970302);
|
||||
const_size = TREE_INT_CST_LOW (TYPE_SIZE (rec));
|
||||
|
||||
nonvirtual_const_size = const_size;
|
||||
|
||||
while (vbase_types)
|
||||
{
|
||||
tree basetype = BINFO_TYPE (vbase_types);
|
||||
tree offset;
|
||||
|
||||
desired_align = TYPE_ALIGN (basetype);
|
||||
record_align = MAX (record_align, desired_align);
|
||||
|
||||
if (const_size == 0)
|
||||
offset = integer_zero_node;
|
||||
else
|
||||
{
|
||||
/* Give each virtual base type the alignment it wants. */
|
||||
const_size = CEIL (const_size, desired_align) * desired_align;
|
||||
offset = size_int (CEIL (const_size, BITS_PER_UNIT));
|
||||
}
|
||||
|
||||
if (CLASSTYPE_VSIZE (basetype) > max)
|
||||
max = CLASSTYPE_VSIZE (basetype);
|
||||
BINFO_OFFSET (vbase_types) = offset;
|
||||
|
||||
/* Every virtual baseclass takes a least a UNIT, so that we can
|
||||
take it's address and get something different for each base. */
|
||||
const_size += MAX (BITS_PER_UNIT,
|
||||
TREE_INT_CST_LOW (CLASSTYPE_SIZE (basetype)));
|
||||
|
||||
vbase_types = TREE_CHAIN (vbase_types);
|
||||
}
|
||||
|
||||
if (const_size)
|
||||
{
|
||||
/* Because a virtual base might take a single byte above,
|
||||
we have to re-adjust the total size to make sure it is
|
||||
a multiple of the alignment. */
|
||||
/* Give the whole object the alignment it wants. */
|
||||
const_size = CEIL (const_size, record_align) * record_align;
|
||||
}
|
||||
|
||||
/* Set the alignment in the complete type. We don't set CLASSTYPE_ALIGN
|
||||
here, as that is for this class, without any virtual base classes. */
|
||||
TYPE_ALIGN (rec) = record_align;
|
||||
if (const_size != nonvirtual_const_size)
|
||||
{
|
||||
TYPE_SIZE (rec) = size_int (const_size);
|
||||
TYPE_SIZE_UNIT (rec) = size_binop (FLOOR_DIV_EXPR, TYPE_SIZE (rec),
|
||||
size_int (BITS_PER_UNIT));
|
||||
}
|
||||
|
||||
/* Now propagate offset information throughout the lattice.
|
||||
Simultaneously, remove the temporary FIELD_DECLS we created in
|
||||
build_base_fields to refer to base types. */
|
||||
field = &TYPE_FIELDS (rec);
|
||||
if (TYPE_VFIELD (rec) == *field)
|
||||
{
|
||||
/* If this class did not have a primary base, we create a
|
||||
virtual function table pointer. It will be the first thing
|
||||
in the class, under the new ABI. Skip it; the base fields
|
||||
will follow it. */
|
||||
my_friendly_assert (flag_new_abi
|
||||
&& !CLASSTYPE_HAS_PRIMARY_BASE_P (rec),
|
||||
19991218);
|
||||
field = &TREE_CHAIN (*field);
|
||||
}
|
||||
|
||||
for (i = 0; i < n_baseclasses; i++)
|
||||
{
|
||||
register tree base_binfo = TREE_VEC_ELT (binfos, i);
|
||||
register tree basetype = BINFO_TYPE (base_binfo);
|
||||
|
||||
if (TREE_VIA_VIRTUAL (base_binfo))
|
||||
continue;
|
||||
|
||||
my_friendly_assert (TREE_TYPE (*field) == basetype, 23897);
|
||||
|
||||
if (get_base_distance (basetype, rec, 0, (tree*)0) == -2)
|
||||
cp_warning ("direct base `%T' inaccessible in `%T' due to ambiguity",
|
||||
basetype, rec);
|
||||
|
||||
BINFO_OFFSET (base_binfo)
|
||||
= size_int (CEIL (TREE_INT_CST_LOW (DECL_FIELD_BITPOS (*field)),
|
||||
BITS_PER_UNIT));
|
||||
propagate_binfo_offsets (base_binfo, BINFO_OFFSET (base_binfo));
|
||||
|
||||
/* Remove this field. */
|
||||
*field = TREE_CHAIN (*field);
|
||||
}
|
||||
|
||||
for (vbase_types = CLASSTYPE_VBASECLASSES (rec); vbase_types;
|
||||
vbase_types = TREE_CHAIN (vbase_types))
|
||||
{
|
||||
BINFO_INHERITANCE_CHAIN (vbase_types) = TYPE_BINFO (rec);
|
||||
unshare_base_binfos (vbase_types);
|
||||
propagate_binfo_offsets (vbase_types, BINFO_OFFSET (vbase_types));
|
||||
|
||||
if (extra_warnings)
|
||||
{
|
||||
tree basetype = BINFO_TYPE (vbase_types);
|
||||
if (get_base_distance (basetype, rec, 0, (tree*)0) == -2)
|
||||
cp_warning ("virtual base `%T' inaccessible in `%T' due to ambiguity",
|
||||
basetype, rec);
|
||||
}
|
||||
}
|
||||
|
||||
return max;
|
||||
}
|
||||
|
||||
|
||||
/* Hashing of lists so that we don't make duplicates.
|
||||
The entry point is `list_hash_canon'. */
|
||||
|
Loading…
Reference in New Issue
Block a user