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:
Mark Mitchell 2000-01-02 19:41:09 +00:00 committed by Mark Mitchell
parent 13799af323
commit 80fd5f4866
5 changed files with 366 additions and 248 deletions

View File

@ -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.

View File

@ -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. */

View File

@ -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));

View File

@ -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);
}

View File

@ -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'. */