summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>2000-01-02 19:41:09 +0000
committermmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>2000-01-02 19:41:09 +0000
commita22f582f57ba118336b8526353065d9984e627ff (patch)
tree3fa1f12ab897f718878ac55b7d173dcf94ba10c5
parentb4898254b2bd83a2a6eff6deef709ef983eb0044 (diff)
downloadgcc-a22f582f57ba118336b8526353065d9984e627ff.tar.gz
* 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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@31168 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/cp/ChangeLog19
-rw-r--r--gcc/cp/class.c319
-rw-r--r--gcc/cp/cp-tree.h2
-rw-r--r--gcc/cp/search.c29
-rw-r--r--gcc/cp/tree.c245
5 files changed, 366 insertions, 248 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index d1762d63c9e..c023f90f754 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -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.
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index fe5d29685dd..7d22db8f463 100644
--- a/gcc/cp/class.c
+++ b/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. */
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index db9a5e4a361..a83dc15a2c0 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -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));
diff --git a/gcc/cp/search.c b/gcc/cp/search.c
index c22391db6a3..079a653130a 100644
--- a/gcc/cp/search.c
+++ b/gcc/cp/search.c
@@ -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);
}
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index f5e24740200..a951b5f7197 100644
--- a/gcc/cp/tree.c
+++ b/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'. */