This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
C++ PATCH: New ABI class layout
- To: gcc-patches at gcc dot gnu dot org
- Subject: C++ PATCH: New ABI class layout
- From: Mark Mitchell <mark at codesourcery dot com>
- Date: Tue, 14 Mar 2000 16:26:29 -0800
- Reply-to: mark at codesourcery dot com
This patch should be the last major class-layout bit for the new ABI.
There's one little bit regarding bit-fields remaining. However, for
the most part, this should be it, modulo bugs. We'll be writing
test-cases over the next couple of days to check some of the details
of the ABI layout -- this code is still largely untested and so
probably doesn't yet work correctly. The infrastructure is now in
place.
Using the new stor-layout.c APIs allows this code to be simpler: we no
longer have to stuff in FIELD_DECLs we don't want and then rip them
out later, for example.
--
Mark Mitchell mark@codesourcery.com
CodeSourcery, LLC http://www.codesourcery.com
2000-03-14 Mark Mitchell <mark@codesourcery.com>
* cp-tree.h: Tweak documentation.
* class.c (build_vbase_pointer_fields): Layout the fields, too.
(avoid_overlap): Remove.
(get_binfo_offset_as_int): New function.
(dfs_serach_base_offsets): Likewise.
(layout_nonempty_base_or_field): Likewise.
(build_base_field): Layout fields here. Avoid placing two objects
of the same type at the same address, under the new ABI.
(build_base_fields): Adjust accordingly.
(create_vtable_ptr): Return the new field, but don't attach it to
TYPE_FIELDS.
(remove_base_field): Remove.
(remove_base_fields): Remove.
(layout_basetypes): Adjust accordingly.
(layout_class_type): Call layout_field for each field, rather than
just making a wholesale call to layout_type.
Index: class.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/class.c,v
retrieving revision 1.268
diff -c -p -r1.268 class.c
*** class.c 2000/03/07 11:41:21 1.268
--- class.c 2000/03/15 00:14:31
*************** static void check_bitfield_decl PARAMS (
*** 116,132 ****
static void check_field_decl PARAMS ((tree, tree, int *, int *, int *, int *));
static void check_field_decls PARAMS ((tree, tree *, int *, int *, int *,
int *));
! static int avoid_overlap PARAMS ((tree, tree, int *));
! static tree build_base_field PARAMS ((tree, tree, int *, int *, unsigned int *));
! static tree build_base_fields PARAMS ((tree, int *));
! static tree build_vbase_pointer_fields PARAMS ((tree, int *));
static tree build_vtbl_or_vbase_field PARAMS ((tree, tree, tree, tree, tree,
int *));
static void check_methods PARAMS ((tree));
static void remove_zero_width_bit_fields PARAMS ((tree));
static void check_bases PARAMS ((tree, int *, int *, int *));
static void check_bases_and_members PARAMS ((tree, int *));
! static void create_vtable_ptr PARAMS ((tree, int *, int *, tree *, tree *));
static void layout_class_type PARAMS ((tree, int *, int *, tree *, tree *));
static void fixup_pending_inline PARAMS ((struct pending_inline *));
static void fixup_inline_methods PARAMS ((tree));
--- 116,132 ----
static void check_field_decl PARAMS ((tree, tree, int *, int *, int *, int *));
static void check_field_decls PARAMS ((tree, tree *, int *, int *, int *,
int *));
! static void build_base_field PARAMS ((record_layout_info, tree, int *,
! unsigned int *, varray_type *));
! static varray_type build_base_fields PARAMS ((record_layout_info, int *));
! static tree build_vbase_pointer_fields PARAMS ((record_layout_info, int *));
static tree build_vtbl_or_vbase_field PARAMS ((tree, tree, tree, tree, tree,
int *));
static void check_methods PARAMS ((tree));
static void remove_zero_width_bit_fields PARAMS ((tree));
static void check_bases PARAMS ((tree, int *, int *, int *));
static void check_bases_and_members PARAMS ((tree, int *));
! static tree create_vtable_ptr PARAMS ((tree, int *, int *, tree *, tree *));
static void layout_class_type PARAMS ((tree, int *, int *, tree *, tree *));
static void fixup_pending_inline PARAMS ((struct pending_inline *));
static void fixup_inline_methods PARAMS ((tree));
*************** static tree dfs_propagate_binfo_offsets
*** 135,142 ****
static void propagate_binfo_offsets PARAMS ((tree, tree));
static void layout_basetypes PARAMS ((tree));
static void layout_virtual_bases PARAMS ((tree));
- static void remove_base_field PARAMS ((tree, tree, tree *));
- static void remove_base_fields PARAMS ((tree));
static tree dfs_set_offset_for_shared_vbases PARAMS ((tree, void *));
static tree dfs_set_offset_for_unshared_vbases PARAMS ((tree, void *));
static tree dfs_build_vbase_offset_vtbl_entries PARAMS ((tree, void *));
--- 135,140 ----
*************** static int make_new_vtable PARAMS ((tree
*** 155,160 ****
--- 153,161 ----
extern void dump_class_hierarchy PARAMS ((tree, int));
static tree build_vtable PARAMS ((tree, tree, tree));
static void initialize_vtable PARAMS ((tree, tree));
+ static void layout_nonempty_base_or_field PARAMS ((record_layout_info,
+ tree, tree,
+ varray_type));
/* Variables shared between class.c and call.c. */
*************** int n_inner_fields_searched = 0;
*** 175,186 ****
FIELD_DECLS. */
static tree
! build_vbase_pointer_fields (rec, empty_p)
! tree rec;
int *empty_p;
{
/* Chain to hold all the new FIELD_DECLs which point at virtual
base classes. */
tree vbase_decls = NULL_TREE;
tree binfos = TYPE_BINFO_BASETYPES (rec);
int n_baseclasses = CLASSTYPE_N_BASECLASSES (rec);
--- 176,188 ----
FIELD_DECLS. */
static tree
! build_vbase_pointer_fields (rli, empty_p)
! record_layout_info rli;
int *empty_p;
{
/* Chain to hold all the new FIELD_DECLs which point at virtual
base classes. */
+ tree rec = rli->t;
tree vbase_decls = NULL_TREE;
tree binfos = TYPE_BINFO_BASETYPES (rec);
int n_baseclasses = CLASSTYPE_N_BASECLASSES (rec);
*************** build_vbase_pointer_fields (rec, empty_p
*** 235,240 ****
--- 237,243 ----
empty_p);
BINFO_VPTR_FIELD (base_binfo) = decl;
TREE_CHAIN (decl) = vbase_decls;
+ layout_field (rli, decl);
vbase_decls = decl;
*empty_p = 0;
*************** build_vtbl_or_vbase_field (name, assembl
*** 4091,4136 ****
return field;
}
! /* If the empty base field in DECL overlaps with a base of the same type in
! NEWDECL, which is either another base field or the first data field of
! the class, pad the base just before NEWDECL and return 1. Otherwise,
! return 0. */
! static int
! avoid_overlap (decl, newdecl, empty_p)
! tree decl, newdecl;
! int *empty_p;
{
! tree field;
! if (newdecl == NULL_TREE
! || ! types_overlap_p (TREE_TYPE (decl), TREE_TYPE (newdecl)))
! return 0;
! for (field = decl; TREE_CHAIN (field) && TREE_CHAIN (field) != newdecl;
! field = TREE_CHAIN (field))
! ;
! DECL_SIZE (field) = bitsize_int (1);
! DECL_SIZE_UNIT (field) = 0;
! /* The containing class cannot be empty; this field takes up space. */
! *empty_p = 0;
! return 1;
}
! /* Build a FIELD_DECL for the base given by BINFO in T. If the new
! object is non-empty, clear *EMPTY_P. Otherwise, set *SAW_EMPTY_P.
! *BASE_ALIGN is a running maximum of the alignments of any base
! class. */
static tree
! build_base_field (t, binfo, empty_p, saw_empty_p, base_align)
! tree t;
tree binfo;
int *empty_p;
- int *saw_empty_p;
unsigned int *base_align;
{
tree basetype = BINFO_TYPE (binfo);
tree decl;
--- 4094,4248 ----
return field;
}
! /* Return the BINFO_OFFSET for BINFO as a native integer, not an
! INTEGER_CST. */
! static unsigned HOST_WIDE_INT
! get_binfo_offset_as_int (binfo)
! tree binfo;
{
! tree offset;
! offset = BINFO_OFFSET (binfo);
! my_friendly_assert (TREE_CODE (offset) == INTEGER_CST, 20000313);
! my_friendly_assert (TREE_INT_CST_HIGH (offset) == 0, 20000313);
! return (unsigned HOST_WIDE_INT) TREE_INT_CST_LOW (offset);
! }
! /* Record the type of BINFO in the slot in DATA (which is really a
! `varray_type *') corresponding to the BINFO_OFFSET. */
! static tree
! dfs_record_base_offsets (binfo, data)
! tree binfo;
! void *data;
! {
! varray_type *v;
! unsigned HOST_WIDE_INT offset = get_binfo_offset_as_int (binfo);
!
! v = (varray_type *) data;
! while (VARRAY_SIZE (*v) <= offset)
! VARRAY_GROW (*v, 2 * VARRAY_SIZE (*v));
! VARRAY_TREE (*v, offset) = tree_cons (NULL_TREE,
! BINFO_TYPE (binfo),
! VARRAY_TREE (*v, offset));
!
! return NULL_TREE;
}
! /* Returns non-NULL if there is already an entry in DATA (which is
! really a `varray_type') indicating that an object with the same
! type of BINFO is already at the BINFO_OFFSET for BINFO. */
static tree
! dfs_search_base_offsets (binfo, data)
tree binfo;
+ void *data;
+ {
+ if (is_empty_class (BINFO_TYPE (binfo)))
+ {
+ varray_type v = (varray_type) data;
+ unsigned HOST_WIDE_INT offset;
+ tree t;
+
+ /* Find the offset for this BINFO. */
+ offset = get_binfo_offset_as_int (binfo);
+ /* If we haven't yet encountered any objects at offsets that
+ big, then there's no conflict. */
+ if (VARRAY_SIZE (v) <= offset)
+ return NULL_TREE;
+ /* Otherwise, go through the objects already allocated at this
+ offset. */
+ for (t = VARRAY_TREE (v, offset); t; t = TREE_CHAIN (t))
+ if (same_type_p (TREE_VALUE (t), BINFO_TYPE (binfo)))
+ return binfo;
+ }
+
+ return NULL_TREE;
+ }
+
+ /* DECL is a FIELD_DECL corresponding either to a base subobject of a
+ non-static data member of the type indicated by RLI. BINFO is the
+ binfo corresponding to the base subobject, or, if this is a
+ non-static data-member, a dummy BINFO for the type of the data
+ member. V maps offsets to types already located at those offsets.
+ This function determines the position of the DECL. */
+
+ static void
+ layout_nonempty_base_or_field (rli, decl, binfo, v)
+ record_layout_info rli;
+ tree decl;
+ tree binfo;
+ varray_type v;
+ {
+ /* Try to place the field. It may take more than one try if we have
+ a hard time placing the field without putting two objects of the
+ same type at the same address. */
+ while (1)
+ {
+ tree offset;
+
+ /* Layout this field. */
+ layout_field (rli, decl);
+
+ /* Now that we know where it wil be placed, update its
+ BINFO_OFFSET. */
+ offset = size_int (CEIL (TREE_INT_CST_LOW (DECL_FIELD_BITPOS (decl)),
+ BITS_PER_UNIT));
+ propagate_binfo_offsets (binfo, offset);
+
+ /* We have to check to see whether or not there is already
+ something of the same type at the offset we're about to use.
+ For example:
+
+ struct S {};
+ struct T : public S { int i; };
+ struct U : public S, public T {};
+
+ Here, we put S at offset zero in U. Then, we can't put T at
+ offset zero -- its S component would be at the same address
+ as the S we already allocated. So, we have to skip ahead.
+ Since all data members, including those whose type is an
+ empty class, have non-zero size, any overlap can happen only
+ with a direct or indirect base-class -- it can't happen with
+ a data member. */
+ if (flag_new_abi && dfs_walk (binfo,
+ dfs_search_base_offsets,
+ dfs_skip_vbases,
+ v))
+ {
+ /* Undo the propogate_binfo_offsets call. */
+ offset = convert (sizetype,
+ size_diffop (size_zero_node, offset));
+ propagate_binfo_offsets (binfo, offset);
+
+ /* Strip off the size allocated to this field. That puts us
+ at the first place we could have put the field with
+ proper alignment. */
+ rli->const_size -= TREE_INT_CST_LOW (DECL_SIZE (decl));
+ /* Bump up by th alignment required for the type, without
+ virtual base classes. */
+ rli->const_size += CLASSTYPE_ALIGN (BINFO_TYPE (binfo));
+ }
+ else
+ /* There was no conflict. We're done laying out this field. */
+ break;
+ }
+ }
+
+ /* Build a FIELD_DECL for the base given by BINFO in the class
+ *indicated by RLI. If the new object is non-empty, clear *EMPTY_P.
+ *BASE_ALIGN is a running maximum of the alignments of any base
+ *class. */
+
+ static void
+ build_base_field (rli, binfo, empty_p, base_align, v)
+ record_layout_info rli;
+ tree binfo;
int *empty_p;
unsigned int *base_align;
+ varray_type *v;
{
tree basetype = BINFO_TYPE (binfo);
tree decl;
*************** build_base_field (t, binfo, empty_p, saw
*** 4138,4162 ****
if (TYPE_SIZE (basetype) == 0)
/* This error is now reported in xref_tag, thus giving better
location information. */
! return NULL_TREE;
decl = build_lang_decl (FIELD_DECL, NULL_TREE, basetype);
DECL_ARTIFICIAL (decl) = 1;
! DECL_FIELD_CONTEXT (decl) = t;
DECL_SIZE (decl) = CLASSTYPE_SIZE (basetype);
DECL_SIZE_UNIT (decl) = CLASSTYPE_SIZE_UNIT (basetype);
DECL_ALIGN (decl) = CLASSTYPE_ALIGN (basetype);
- if (flag_new_abi && integer_zerop (DECL_SIZE (decl)))
- {
- *saw_empty_p = 1;
- return decl;
- }
-
- /* The containing class is non-empty because it has a non-empty base
- class. */
- *empty_p = 0;
-
if (! flag_new_abi)
{
/* Brain damage for backwards compatibility. For no good
--- 4250,4264 ----
if (TYPE_SIZE (basetype) == 0)
/* This error is now reported in xref_tag, thus giving better
location information. */
! return;
decl = build_lang_decl (FIELD_DECL, NULL_TREE, basetype);
DECL_ARTIFICIAL (decl) = 1;
! DECL_FIELD_CONTEXT (decl) = rli->t;
DECL_SIZE (decl) = CLASSTYPE_SIZE (basetype);
DECL_SIZE_UNIT (decl) = CLASSTYPE_SIZE_UNIT (basetype);
DECL_ALIGN (decl) = CLASSTYPE_ALIGN (basetype);
if (! flag_new_abi)
{
/* Brain damage for backwards compatibility. For no good
*************** build_base_field (t, binfo, empty_p, saw
*** 4174,4213 ****
(int) *base_align / BITS_PER_UNIT));
}
! return decl;
}
! /* Returns a list of fields to stand in for the base class subobjects
! of REC. These fields are later removed by layout_basetypes. */
! static tree
! build_base_fields (rec, empty_p)
! tree rec;
int *empty_p;
{
/* Chain to hold all the new FIELD_DECLs which stand in for base class
subobjects. */
! tree base_decls = NULL_TREE;
int n_baseclasses = CLASSTYPE_N_BASECLASSES (rec);
! tree decl, nextdecl;
! int i, saw_empty = 0;
unsigned int base_align = 0;
/* Under the new ABI, the primary base class is always allocated
first. */
if (flag_new_abi && CLASSTYPE_HAS_PRIMARY_BASE_P (rec))
! {
! tree primary_base;
- primary_base = CLASSTYPE_PRIMARY_BINFO (rec);
- base_decls = chainon (build_base_field (rec,
- primary_base,
- empty_p,
- &saw_empty,
- &base_align),
- base_decls);
- }
-
/* Now allocate the rest of the bases. */
for (i = 0; i < n_baseclasses; ++i)
{
--- 4276,4360 ----
(int) *base_align / BITS_PER_UNIT));
}
! if (!integer_zerop (DECL_SIZE (decl)))
! {
! /* The containing class is non-empty because it has a non-empty
! base class. */
! *empty_p = 0;
!
! /* Try to place the field. It may take more than one try if we
! have a hard time placing the field without putting two
! objects of the same type at the same address. */
! layout_nonempty_base_or_field (rli, decl, binfo, *v);
! }
! else
! {
! /* This code assumes that zero-sized classes have one-byte
! alignment. There might someday be a system where that's not
! true. */
! my_friendly_assert (DECL_ALIGN (basetype) == BITS_PER_UNIT,
! 20000314);
!
! /* This is an empty base class. We first try to put it at
! offset zero. */
! if (dfs_walk (binfo, dfs_search_base_offsets, dfs_skip_vbases, *v))
! {
! /* That didn't work. Now, we move forward from the next
! available spot in the class. */
! propagate_binfo_offsets (binfo, size_int (rli->const_size));
! while (1)
! {
! if (!dfs_walk (binfo, dfs_search_base_offsets,
! dfs_skip_vbases, *v))
! /* We finally found a spot where there's no overlap. */
! break;
!
! /* There's overlap here, too. Bump along to the next
! spot. */
! propagate_binfo_offsets (binfo, size_one_node);
! }
! }
! }
!
! /* Check for inaccessible base classes. If the same base class
! appears more than once in the hierarchy, but isn't virtual, then
! it's ambiguous. */
! if (get_base_distance (basetype, rli->t, 0, NULL) == -2)
! cp_warning ("direct base `%T' inaccessible in `%T' due to ambiguity",
! basetype, rli->t);
!
! /* Record the offsets of BINFO and its base subobjects. */
! dfs_walk (binfo,
! dfs_record_base_offsets,
! dfs_skip_vbases,
! v);
}
! /* Layout all of the non-virtual base classes. Returns a map from
! offsets to types present at those offsets. */
! static varray_type
! build_base_fields (rli, empty_p)
! record_layout_info rli;
int *empty_p;
{
/* Chain to hold all the new FIELD_DECLs which stand in for base class
subobjects. */
! tree rec = rli->t;
int n_baseclasses = CLASSTYPE_N_BASECLASSES (rec);
! int i;
! varray_type v;
unsigned int base_align = 0;
+ /* Create the table mapping offsets to empty base classes. */
+ VARRAY_TREE_INIT (v, 32, "v");
+
/* Under the new ABI, the primary base class is always allocated
first. */
if (flag_new_abi && CLASSTYPE_HAS_PRIMARY_BASE_P (rec))
! build_base_field (rli, CLASSTYPE_PRIMARY_BINFO (rec),
! empty_p, &base_align, &v);
/* Now allocate the rest of the bases. */
for (i = 0; i < n_baseclasses; ++i)
{
*************** build_base_fields (rec, empty_p)
*** 4227,4270 ****
&& !BINFO_PRIMARY_MARKED_P (base_binfo))
continue;
! base_decls = chainon (build_base_field (rec, base_binfo,
! empty_p,
! &saw_empty,
! &base_align),
! base_decls);
}
! /* Reverse the list of fields so we allocate the bases in the proper
! order. */
! base_decls = nreverse (base_decls);
!
! /* In the presence of empty base classes, we run the risk of allocating
! two objects of the same class on top of one another. Avoid that. */
! if (flag_new_abi && saw_empty)
! for (decl = base_decls; decl; decl = TREE_CHAIN (decl))
! {
! if (integer_zerop (DECL_SIZE (decl)))
! {
! /* First step through the following bases until we find
! an overlap or a non-empty base. */
! for (nextdecl = TREE_CHAIN (decl); nextdecl;
! nextdecl = TREE_CHAIN (nextdecl))
! if (avoid_overlap (decl, nextdecl, empty_p)
! || ! integer_zerop (DECL_SIZE (nextdecl)))
! goto nextbase;
!
! /* If we're still looking, also check against the first
! field. */
! for (nextdecl = TYPE_FIELDS (rec);
! nextdecl && TREE_CODE (nextdecl) != FIELD_DECL;
! nextdecl = TREE_CHAIN (nextdecl))
! /* keep looking */;
! avoid_overlap (decl, nextdecl, empty_p);
! }
! nextbase:;
! }
!
! return base_decls;
}
/* Go through the TYPE_METHODS of T issuing any appropriate
--- 4374,4383 ----
&& !BINFO_PRIMARY_MARKED_P (base_binfo))
continue;
! build_base_field (rli, base_binfo, empty_p, &base_align, &v);
}
! return v;
}
/* Go through the TYPE_METHODS of T issuing any appropriate
*************** check_bases_and_members (t, empty_p)
*** 4438,4447 ****
}
/* If T needs a pointer to its virtual function table, set TYPE_VFIELD
! accordingly, and, if necessary, add the TYPE_VFIELD to the
! TYPE_FIELDS list. */
! static void
create_vtable_ptr (t, empty_p, has_virtual_p,
new_virtuals_p, overridden_virtuals_p)
tree t;
--- 4551,4562 ----
}
/* If T needs a pointer to its virtual function table, set TYPE_VFIELD
! accordingly. If a new vfield was created (because T doesn't have a
! primary base class), then the newly created field is returned. It
! is not added to the TYPE_FIELDS list; it is the callers
! responsibility to do that. */
! static tree
create_vtable_ptr (t, empty_p, has_virtual_p,
new_virtuals_p, overridden_virtuals_p)
tree t;
*************** create_vtable_ptr (t, empty_p, has_virtu
*** 4496,4524 ****
t,
empty_p);
! /* Add the new field to the list of fields in this class. */
! 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
! modify_all_vtables function depends on this not being done.
! So, it is done later, in finish_struct_1. */
}
}
/* Fixup the inline function given by INFO now that the class is
--- 4611,4627 ----
t,
empty_p);
! if (flag_new_abi && CLASSTYPE_N_BASECLASSES (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. */
! TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (t) = 1;
! return TYPE_VFIELD (t);
}
+
+ return NULL_TREE;
}
/* Fixup the inline function given by INFO now that the class is
*************** propagate_binfo_offsets (binfo, offset)
*** 4613,4697 ****
NULL);
}
- /* Remove *FIELD (which corresponds to the base given by BINFO) from
- the field list for T. */
-
- static void
- remove_base_field (t, binfo, field)
- tree t;
- tree binfo;
- tree *field;
- {
- tree basetype = BINFO_TYPE (binfo);
- tree offset;
-
- 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);
-
- offset
- = size_int (CEIL (TREE_INT_CST_LOW (DECL_FIELD_BITPOS (*field)),
- BITS_PER_UNIT));
- propagate_binfo_offsets (binfo, offset);
-
- /* Remove this field. */
- *field = TREE_CHAIN (*field);
- }
-
- /* 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);
- }
-
- /* Under the new ABI, the primary base is always allocated first. */
- if (flag_new_abi && CLASSTYPE_HAS_PRIMARY_BASE_P (t))
- remove_base_field (t, CLASSTYPE_PRIMARY_BINFO (t), field);
-
- /* Now remove the rest of the bases. */
- for (i = 0; i < CLASSTYPE_N_BASECLASSES (t); i++)
- {
- tree binfo;
-
- /* Under the new ABI, we've already removed the primary base
- above. */
- if (flag_new_abi && i == CLASSTYPE_VFIELD_PARENT (t))
- continue;
-
- binfo = BINFO_BASETYPE (TYPE_BINFO (t), i);
-
- /* 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 (binfo) && !BINFO_PRIMARY_MARKED_P (binfo))
- continue;
-
- remove_base_field (t, binfo, field);
- }
- }
-
/* Called via dfs_walk from layout_virtual bases. */
static tree
--- 4716,4721 ----
*************** layout_basetypes (rec)
*** 4819,4835 ****
{
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. */
layout_virtual_bases (rec);
--- 4843,4857 ----
{
tree vbase_types;
+ if (CLASSTYPE_N_BASECLASSES (rec) == 0)
+ return;
+
#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
/* Allocate the virtual base classes. */
layout_virtual_bases (rec);
*************** layout_class_type (t, empty_p, has_virtu
*** 4861,4924 ****
tree *new_virtuals_p;
tree *overridden_virtuals_p;
{
! tree padding = NULL_TREE;
/* If possible, we reuse the virtual function table pointer from one
of our base classes. */
determine_primary_base (t, has_virtual_p);
/* Add pointers to all of our virtual base-classes. */
! TYPE_FIELDS (t) = chainon (build_vbase_pointer_fields (t, empty_p),
TYPE_FIELDS (t));
/* Build FIELD_DECLs for all of the non-virtual base-types. */
! TYPE_FIELDS (t) = chainon (build_base_fields (t, empty_p),
! TYPE_FIELDS (t));
!
! /* Create a pointer to our virtual function table. */
! create_vtable_ptr (t, empty_p, has_virtual_p,
! new_virtuals_p, overridden_virtuals_p);
/* CLASSTYPE_INLINE_FRIENDS is really TYPE_NONCOPIED_PARTS. Thus,
we have to save this before we start modifying
TYPE_NONCOPIED_PARTS. */
fixup_inline_methods (t);
/* We make all structures have at least one element, so that they
! have non-zero size. The field that we add here is fake, in the
! sense that, for example, we don't want people to be able to
! initialize it later. So, we add it just long enough to let the
! back-end lay out the type, and then remove it. In the new ABI,
! the class may be empty even if it has basetypes. Therefore, we
! add the fake field at the end of the fields list; if there are
! already FIELD_DECLs on the list, their offsets will not be
! disturbed. */
if (*empty_p)
{
padding = build_lang_decl (FIELD_DECL, NULL_TREE, char_type_node);
! TYPE_FIELDS (t) = chainon (TYPE_FIELDS (t), padding);
TYPE_NONCOPIED_PARTS (t)
= tree_cons (NULL_TREE, padding, TYPE_NONCOPIED_PARTS (t));
TREE_STATIC (TYPE_NONCOPIED_PARTS (t)) = 1;
}
/* Let the back-end lay out the type. Note that at this point we
have only included non-virtual base-classes; we will lay out the
virtual base classes later. So, the TYPE_SIZE/TYPE_ALIGN after
this call are not necessarily correct; they are just the size and
alignment when no virtual base clases are used. */
! layout_type (t);
!
! /* If we added an extra field to make this class non-empty, remove
! it now. */
! if (*empty_p)
! {
! tree *declp;
!
! declp = &TYPE_FIELDS (t);
! while (*declp != padding)
! declp = &TREE_CHAIN (*declp);
! *declp = TREE_CHAIN (*declp);
! }
/* Delete all zero-width bit-fields from the list of fields. Now
that the type is laid out they are no longer important. */
--- 4883,4999 ----
tree *new_virtuals_p;
tree *overridden_virtuals_p;
{
! tree non_static_data_members;
! tree field;
! tree vptr;
! record_layout_info rli;
! varray_type v;
! int i;
!
! /* Keep track of the first non-static data member. */
! non_static_data_members = TYPE_FIELDS (t);
+ /* Initialize the layout information. */
+ rli = new_record_layout_info (t);
+
/* If possible, we reuse the virtual function table pointer from one
of our base classes. */
determine_primary_base (t, has_virtual_p);
+ /* Create a pointer to our virtual function table. */
+ vptr = create_vtable_ptr (t, empty_p, has_virtual_p,
+ new_virtuals_p, overridden_virtuals_p);
+
+ /* Under the new ABI, the vptr is always the first thing in the
+ class. */
+ if (flag_new_abi && vptr)
+ {
+ TYPE_FIELDS (t) = chainon (vptr, TYPE_FIELDS (t));
+ layout_field (rli, vptr);
+ }
+
/* Add pointers to all of our virtual base-classes. */
! TYPE_FIELDS (t) = chainon (build_vbase_pointer_fields (rli, empty_p),
TYPE_FIELDS (t));
/* Build FIELD_DECLs for all of the non-virtual base-types. */
! v = build_base_fields (rli, empty_p);
/* CLASSTYPE_INLINE_FRIENDS is really TYPE_NONCOPIED_PARTS. Thus,
we have to save this before we start modifying
TYPE_NONCOPIED_PARTS. */
fixup_inline_methods (t);
+ /* Layout the non-static data members. */
+ for (field = non_static_data_members;
+ field;
+ field = TREE_CHAIN (field))
+ {
+ tree binfo;
+
+ /* We still pass things that aren't non-static data members to
+ the back-end, in case it wants to do something with them. */
+ if (TREE_CODE (field) != FIELD_DECL)
+ {
+ layout_field (rli, field);
+ continue;
+ }
+
+ /* Create a dummy BINFO corresponding to this field. */
+ binfo = make_binfo (size_zero_node, TREE_TYPE (field),
+ NULL_TREE, NULL_TREE);
+ unshare_base_binfos (binfo);
+ layout_nonempty_base_or_field (rli, field, binfo, v);
+ }
+
+ /* Clean up. */
+ VARRAY_FREE (v);
+
+ /* It might be the case that we grew the class to allocate a
+ zero-sized base class. That won't be reflected in RLI, yet,
+ because we are willing to overlay multiple bases at the same
+ offset. However, now we need to make sure that RLI is big enough
+ to reflect the entire class. */
+ for (i = 0; i < CLASSTYPE_N_BASECLASSES (t); ++i)
+ {
+ tree base_binfo;
+ unsigned HOST_WIDE_INT offset;
+
+ base_binfo = BINFO_BASETYPE (TYPE_BINFO (t), i);
+ offset = get_binfo_offset_as_int (base_binfo);
+ if (offset * BITS_PER_UNIT > rli->const_size)
+ rli->const_size = (offset + 1) * BITS_PER_UNIT;
+ }
+
/* We make all structures have at least one element, so that they
! have non-zero size. In the new ABI, the class may be empty even
! if it has basetypes. Therefore, we add the fake field after all
! the other fields; if there are already FIELD_DECLs on the list,
! their offsets will not be disturbed. */
if (*empty_p)
{
+ tree padding;
+
padding = build_lang_decl (FIELD_DECL, NULL_TREE, char_type_node);
! layout_field (rli, padding);
TYPE_NONCOPIED_PARTS (t)
= tree_cons (NULL_TREE, padding, TYPE_NONCOPIED_PARTS (t));
TREE_STATIC (TYPE_NONCOPIED_PARTS (t)) = 1;
}
+ /* Under the old ABI, the vptr comes at the very end of the
+ class. */
+ if (!flag_new_abi && vptr)
+ {
+ layout_field (rli, vptr);
+ TYPE_FIELDS (t) = chainon (TYPE_FIELDS (t), vptr);
+ }
+
/* Let the back-end lay out the type. Note that at this point we
have only included non-virtual base-classes; we will lay out the
virtual base classes later. So, the TYPE_SIZE/TYPE_ALIGN after
this call are not necessarily correct; they are just the size and
alignment when no virtual base clases are used. */
! finish_record_layout (rli);
/* Delete all zero-width bit-fields from the list of fields. Now
that the type is laid out they are no longer important. */
*************** layout_class_type (t, empty_p, has_virtu
*** 4952,4961 ****
/* Now fix up any virtual base class types that we left lying
around. We must get these done before we try to lay out the
! virtual function table. */
! if (CLASSTYPE_N_BASECLASSES (t))
! /* layout_basetypes will remove the base subobject fields. */
! layout_basetypes (t);
}
/* Create a RECORD_TYPE or UNION_TYPE node for a C struct or union declaration
--- 5027,5035 ----
/* Now fix up any virtual base class types that we left lying
around. We must get these done before we try to lay out the
! virtual function table. As a side-effect, this will remove the
! base subobject fields. */
! layout_basetypes (t);
}
/* Create a RECORD_TYPE or UNION_TYPE node for a C struct or union declaration
Index: cp-tree.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/cp-tree.h,v
retrieving revision 1.417
diff -c -p -r1.417 cp-tree.h
*** cp-tree.h 2000/03/13 04:54:39 1.417
--- cp-tree.h 2000/03/15 00:14:35
*************** struct lang_type
*** 1578,1585 ****
which uses this must define what exactly this slot is used for. */
#define CLASSTYPE_SEARCH_SLOT(NODE) (TYPE_LANG_SPECIFIC(NODE)->search_slot)
! /* These are the size, mode and alignment of the type without its
! virtual base classes, for when we use this type as a base itself. */
#define CLASSTYPE_SIZE(NODE) (TYPE_LANG_SPECIFIC(NODE)->size)
#define CLASSTYPE_SIZE_UNIT(NODE) (TYPE_LANG_SPECIFIC(NODE)->size_unit)
#define CLASSTYPE_ALIGN(NODE) (TYPE_LANG_SPECIFIC(NODE)->align)
--- 1578,1585 ----
which uses this must define what exactly this slot is used for. */
#define CLASSTYPE_SEARCH_SLOT(NODE) (TYPE_LANG_SPECIFIC(NODE)->search_slot)
! /* These are the size and alignment of the type without its virtual
! base classes, for when we use this type as a base itself. */
#define CLASSTYPE_SIZE(NODE) (TYPE_LANG_SPECIFIC(NODE)->size)
#define CLASSTYPE_SIZE_UNIT(NODE) (TYPE_LANG_SPECIFIC(NODE)->size_unit)
#define CLASSTYPE_ALIGN(NODE) (TYPE_LANG_SPECIFIC(NODE)->align)