Commit 9a71c18b by Jason Merrill

Re-implement allocation of base class subobjects.

	* tree.c (unshare_base_binfos): New fn.
	(layout_basetypes): Use it.  Now handles offsets of both virtual and
	non-virtual bases, after layout_type.
	(layout_vbasetypes): Remove.
	(build_base_fields): Generate FIELD_DECLs for each non-virtual base.
	(build_vbase_pointer_fields): Split out from old layout_basetypes.
	* class.c (finish_base_struct): Lose offset handling code.
	Move nonvdtor warning here.  Don't mess with t_binfo anymore.
	(finish_struct_1): Don't mess with t_binfo anymore.  Use fns above.
	* cp-tree.h: Adjust.

From-SVN: r18973
parent 516c2342
Fri Apr 3 02:22:59 1998 Jason Merrill <jason@yorick.cygnus.com>
Re-implement allocation of base class subobjects.
* tree.c (unshare_base_binfos): New fn.
(layout_basetypes): Use it. Now handles offsets of both virtual and
non-virtual bases, after layout_type.
(layout_vbasetypes): Remove.
(build_base_fields): Generate FIELD_DECLs for each non-virtual base.
(build_vbase_pointer_fields): Split out from old layout_basetypes.
* class.c (finish_base_struct): Lose offset handling code.
Move nonvdtor warning here. Don't mess with t_binfo anymore.
(finish_struct_1): Don't mess with t_binfo anymore. Use fns above.
* cp-tree.h: Adjust.
Thu Apr 2 14:25:13 1998 Jason Merrill <jason@yorick.cygnus.com> Thu Apr 2 14:25:13 1998 Jason Merrill <jason@yorick.cygnus.com>
* cp-tree.h: Lose CLASSTYPE_VBASE_SIZE, some unused stuff. * cp-tree.h: Lose CLASSTYPE_VBASE_SIZE, some unused stuff.
...@@ -12,7 +26,7 @@ Wed Apr 1 18:22:25 1998 Jeffrey A Law (law@cygnus.com) ...@@ -12,7 +26,7 @@ Wed Apr 1 18:22:25 1998 Jeffrey A Law (law@cygnus.com)
* class.c, Make sure system.h is included just after config.h. * class.c, Make sure system.h is included just after config.h.
Delete lingering stdio and errno references too. Delete lingering stdio and errno references too.
* decl.c, errfn.c, parse.y, ptree.c search.c, xrefc.: Likewwise. * decl.c, errfn.c, parse.y, ptree.c search.c, xref.c: Likewise.
Wed Apr 1 15:38:36 1998 Jason Merrill <jason@yorick.cygnus.com> Wed Apr 1 15:38:36 1998 Jason Merrill <jason@yorick.cygnus.com>
......
...@@ -124,7 +124,7 @@ static void modify_all_direct_vtables PROTO((tree, int, tree, tree, ...@@ -124,7 +124,7 @@ static void modify_all_direct_vtables PROTO((tree, int, tree, tree,
static void modify_all_indirect_vtables PROTO((tree, int, int, tree, static void modify_all_indirect_vtables PROTO((tree, int, int, tree,
tree, tree)); tree, tree));
static void build_class_init_list PROTO((tree)); static void build_class_init_list PROTO((tree));
static int finish_base_struct PROTO((tree, struct base_info *, tree)); static int finish_base_struct PROTO((tree, struct base_info *));
/* Way of stacking language names. */ /* Way of stacking language names. */
tree *current_lang_base, *current_lang_stack; tree *current_lang_base, *current_lang_stack;
...@@ -1526,17 +1526,14 @@ struct base_info ...@@ -1526,17 +1526,14 @@ struct base_info
offsets include that offset in theirs. offsets include that offset in theirs.
Returns the index of the first base class to have virtual functions, Returns the index of the first base class to have virtual functions,
or -1 if no such base class. or -1 if no such base class. */
Note that at this point TYPE_BINFO (t) != t_binfo. */
static int static int
finish_base_struct (t, b, t_binfo) finish_base_struct (t, b)
tree t; tree t;
struct base_info *b; struct base_info *b;
tree t_binfo;
{ {
tree binfos = BINFO_BASETYPES (t_binfo); tree binfos = TYPE_BINFO_BASETYPES (t);
int i, n_baseclasses = binfos ? TREE_VEC_LENGTH (binfos) : 0; int i, n_baseclasses = binfos ? TREE_VEC_LENGTH (binfos) : 0;
int first_vfn_base_index = -1; int first_vfn_base_index = -1;
bzero ((char *) b, sizeof (struct base_info)); bzero ((char *) b, sizeof (struct base_info));
...@@ -1546,6 +1543,13 @@ finish_base_struct (t, b, t_binfo) ...@@ -1546,6 +1543,13 @@ finish_base_struct (t, b, t_binfo)
tree base_binfo = TREE_VEC_ELT (binfos, i); tree base_binfo = TREE_VEC_ELT (binfos, i);
tree basetype = BINFO_TYPE (base_binfo); tree basetype = BINFO_TYPE (base_binfo);
/* Effective C++ rule 14. We only need to check TYPE_VIRTUAL_P
here because the case of virtual functions but non-virtual
dtor is handled in finish_struct_1. */
if (warn_ecpp && ! TYPE_VIRTUAL_P (basetype)
&& TYPE_HAS_DESTRUCTOR (basetype))
cp_warning ("base class `%#T' has a non-virtual destructor", basetype);
/* If the type of basetype is incomplete, then /* If the type of basetype is incomplete, then
we already complained about that fact we already complained about that fact
(and we should have fixed it up as well). */ (and we should have fixed it up as well). */
...@@ -1592,36 +1596,6 @@ finish_base_struct (t, b, t_binfo) ...@@ -1592,36 +1596,6 @@ finish_base_struct (t, b, t_binfo)
TYPE_OVERLOADS_ARRAY_REF (t) |= TYPE_OVERLOADS_ARRAY_REF (basetype); TYPE_OVERLOADS_ARRAY_REF (t) |= TYPE_OVERLOADS_ARRAY_REF (basetype);
TYPE_OVERLOADS_ARROW (t) |= TYPE_OVERLOADS_ARROW (basetype); TYPE_OVERLOADS_ARROW (t) |= TYPE_OVERLOADS_ARROW (basetype);
if (! TREE_VIA_VIRTUAL (base_binfo)
&& BINFO_BASETYPES (base_binfo))
{
tree base_binfos = BINFO_BASETYPES (base_binfo);
tree chain = NULL_TREE;
int j;
/* Now unshare the structure beneath BASE_BINFO. */
for (j = TREE_VEC_LENGTH (base_binfos)-1;
j >= 0; j--)
{
tree base_base_binfo = TREE_VEC_ELT (base_binfos, j);
if (! TREE_VIA_VIRTUAL (base_base_binfo))
TREE_VEC_ELT (base_binfos, j)
= make_binfo (BINFO_OFFSET (base_base_binfo),
base_base_binfo,
BINFO_VTABLE (base_base_binfo),
BINFO_VIRTUALS (base_base_binfo),
chain);
chain = TREE_VEC_ELT (base_binfos, j);
TREE_VIA_PUBLIC (chain) = TREE_VIA_PUBLIC (base_base_binfo);
TREE_VIA_PROTECTED (chain) = TREE_VIA_PROTECTED (base_base_binfo);
BINFO_INHERITANCE_CHAIN (chain) = base_binfo;
}
/* Completely unshare potentially shared data, and
update what is ours. */
propagate_binfo_offsets (base_binfo, BINFO_OFFSET (base_binfo));
}
if (! TREE_VIA_VIRTUAL (base_binfo)) if (! TREE_VIA_VIRTUAL (base_binfo))
CLASSTYPE_N_SUPERCLASSES (t) += 1; CLASSTYPE_N_SUPERCLASSES (t) += 1;
...@@ -1644,8 +1618,8 @@ finish_base_struct (t, b, t_binfo) ...@@ -1644,8 +1618,8 @@ finish_base_struct (t, b, t_binfo)
/* Update these two, now that we know what vtable we are /* Update these two, now that we know what vtable we are
going to extend. This is so that we can add virtual going to extend. This is so that we can add virtual
functions, and override them properly. */ functions, and override them properly. */
BINFO_VTABLE (t_binfo) = TYPE_BINFO_VTABLE (basetype); TYPE_BINFO_VTABLE (t) = TYPE_BINFO_VTABLE (basetype);
BINFO_VIRTUALS (t_binfo) = TYPE_BINFO_VIRTUALS (basetype); TYPE_BINFO_VIRTUALS (t) = TYPE_BINFO_VIRTUALS (basetype);
b->has_virtual = CLASSTYPE_VSIZE (basetype); b->has_virtual = CLASSTYPE_VSIZE (basetype);
b->vfield = CLASSTYPE_VFIELD (basetype); b->vfield = CLASSTYPE_VFIELD (basetype);
b->vfields = copy_list (CLASSTYPE_VFIELDS (basetype)); b->vfields = copy_list (CLASSTYPE_VFIELDS (basetype));
...@@ -1693,8 +1667,8 @@ finish_base_struct (t, b, t_binfo) ...@@ -1693,8 +1667,8 @@ finish_base_struct (t, b, t_binfo)
/* Update these two, now that we know what vtable we are /* Update these two, now that we know what vtable we are
going to extend. This is so that we can add virtual going to extend. This is so that we can add virtual
functions, and override them properly. */ functions, and override them properly. */
BINFO_VTABLE (t_binfo) = TYPE_BINFO_VTABLE (basetype); TYPE_BINFO_VTABLE (t) = TYPE_BINFO_VTABLE (basetype);
BINFO_VIRTUALS (t_binfo) = TYPE_BINFO_VIRTUALS (basetype); TYPE_BINFO_VIRTUALS (t) = TYPE_BINFO_VIRTUALS (basetype);
b->has_virtual = CLASSTYPE_VSIZE (basetype); b->has_virtual = CLASSTYPE_VSIZE (basetype);
b->vfield = CLASSTYPE_VFIELD (basetype); b->vfield = CLASSTYPE_VFIELD (basetype);
CLASSTYPE_VFIELD (t) = b->vfield; CLASSTYPE_VFIELD (t) = b->vfield;
...@@ -1720,25 +1694,27 @@ finish_base_struct (t, b, t_binfo) ...@@ -1720,25 +1694,27 @@ finish_base_struct (t, b, t_binfo)
} }
} }
/* Must come after offsets are fixed for all bases. */ /* This comment said "Must come after offsets are fixed for all bases."
Well, now this happens before the offsets are fixed, but it seems to
work fine. Guess we'll see... */
for (i = 0; i < n_baseclasses; i++) for (i = 0; i < n_baseclasses; i++)
{ {
tree base_binfo = TREE_VEC_ELT (binfos, i); tree base_binfo = TREE_VEC_ELT (binfos, i);
tree basetype = BINFO_TYPE (base_binfo); tree basetype = BINFO_TYPE (base_binfo);
if (get_base_distance (basetype, t_binfo, 0, (tree*)0) == -2) if (get_base_distance (basetype, t, 0, (tree*)0) == -2)
{ {
cp_warning ("direct base `%T' inaccessible in `%T' due to ambiguity", cp_warning ("direct base `%T' inaccessible in `%T' due to ambiguity",
basetype, t); basetype, t);
} }
} }
{ {
tree v = get_vbase_types (t_binfo); tree v = get_vbase_types (t);
for (; v; v = TREE_CHAIN (v)) for (; v; v = TREE_CHAIN (v))
{ {
tree basetype = BINFO_TYPE (v); tree basetype = BINFO_TYPE (v);
if (get_base_distance (basetype, t_binfo, 0, (tree*)0) == -2) if (get_base_distance (basetype, t, 0, (tree*)0) == -2)
{ {
if (extra_warnings) if (extra_warnings)
cp_warning ("virtual base `%T' inaccessible in `%T' due to ambiguity", cp_warning ("virtual base `%T' inaccessible in `%T' due to ambiguity",
...@@ -3088,7 +3064,6 @@ finish_struct_1 (t, warn_anon) ...@@ -3088,7 +3064,6 @@ finish_struct_1 (t, warn_anon)
int const_sans_init = 0; int const_sans_init = 0;
int ref_sans_init = 0; int ref_sans_init = 0;
int nonprivate_method = 0; int nonprivate_method = 0;
tree t_binfo = TYPE_BINFO (t);
tree access_decls = NULL_TREE; tree access_decls = NULL_TREE;
int aggregate = 1; int aggregate = 1;
int empty = 1; int empty = 1;
...@@ -3125,13 +3100,6 @@ finish_struct_1 (t, warn_anon) ...@@ -3125,13 +3100,6 @@ finish_struct_1 (t, warn_anon)
} }
#endif #endif
#if 0
if (flag_rtti)
build_t_desc (t, 0);
#endif
TYPE_BINFO (t) = NULL_TREE;
old = suspend_momentary (); old = suspend_momentary ();
/* Install struct as DECL_FIELD_CONTEXT of each field decl. /* Install struct as DECL_FIELD_CONTEXT of each field decl.
...@@ -3141,8 +3109,8 @@ finish_struct_1 (t, warn_anon) ...@@ -3141,8 +3109,8 @@ finish_struct_1 (t, warn_anon)
Store 0 there, except for ": 0" fields (so we can find them Store 0 there, except for ": 0" fields (so we can find them
and delete them, below). */ and delete them, below). */
if (t_binfo && BINFO_BASETYPES (t_binfo)) if (TYPE_BINFO_BASETYPES (t))
n_baseclasses = TREE_VEC_LENGTH (BINFO_BASETYPES (t_binfo)); n_baseclasses = TREE_VEC_LENGTH (TYPE_BINFO_BASETYPES (t));
else else
n_baseclasses = 0; n_baseclasses = 0;
...@@ -3150,13 +3118,7 @@ finish_struct_1 (t, warn_anon) ...@@ -3150,13 +3118,7 @@ finish_struct_1 (t, warn_anon)
{ {
struct base_info base_info; struct base_info base_info;
/* If using multiple inheritance, this may cause variants of our first_vfn_base_index = finish_base_struct (t, &base_info);
basetypes to be used (instead of their canonical forms). */
tree vf = layout_basetypes (t, BINFO_BASETYPES (t_binfo));
last_x = tree_last (vf);
fields = chainon (vf, fields);
first_vfn_base_index = finish_base_struct (t, &base_info, t_binfo);
/* Remember where we got our vfield from. */ /* Remember where we got our vfield from. */
CLASSTYPE_VFIELD_PARENT (t) = first_vfn_base_index; CLASSTYPE_VFIELD_PARENT (t) = first_vfn_base_index;
has_virtual = base_info.has_virtual; has_virtual = base_info.has_virtual;
...@@ -3168,8 +3130,8 @@ finish_struct_1 (t, warn_anon) ...@@ -3168,8 +3130,8 @@ finish_struct_1 (t, warn_anon)
cant_have_default_ctor = base_info.cant_have_default_ctor; cant_have_default_ctor = base_info.cant_have_default_ctor;
cant_have_const_ctor = base_info.cant_have_const_ctor; cant_have_const_ctor = base_info.cant_have_const_ctor;
no_const_asn_ref = base_info.no_const_asn_ref; no_const_asn_ref = base_info.no_const_asn_ref;
n_baseclasses = TREE_VEC_LENGTH (BINFO_BASETYPES (t_binfo));
aggregate = 0; aggregate = 0;
empty = 0;
} }
else else
{ {
...@@ -3179,7 +3141,6 @@ finish_struct_1 (t, warn_anon) ...@@ -3179,7 +3141,6 @@ finish_struct_1 (t, warn_anon)
vfield = NULL_TREE; vfield = NULL_TREE;
vfields = NULL_TREE; vfields = NULL_TREE;
CLASSTYPE_RTTI (t) = NULL_TREE; CLASSTYPE_RTTI (t) = NULL_TREE;
last_x = NULL_TREE;
cant_have_default_ctor = 0; cant_have_default_ctor = 0;
cant_have_const_ctor = 0; cant_have_const_ctor = 0;
no_const_asn_ref = 0; no_const_asn_ref = 0;
...@@ -3198,8 +3159,6 @@ finish_struct_1 (t, warn_anon) ...@@ -3198,8 +3159,6 @@ finish_struct_1 (t, warn_anon)
/* The three of these are approximations which may later be /* The three of these are approximations which may later be
modified. Needed at this point to make add_virtual_function modified. Needed at this point to make add_virtual_function
and modify_vtable_entries work. */ and modify_vtable_entries work. */
TREE_CHAIN (t_binfo) = TYPE_BINFO (t);
TYPE_BINFO (t) = t_binfo;
CLASSTYPE_VFIELDS (t) = vfields; CLASSTYPE_VFIELDS (t) = vfields;
CLASSTYPE_VFIELD (t) = vfield; CLASSTYPE_VFIELD (t) = vfield;
...@@ -3250,7 +3209,8 @@ finish_struct_1 (t, warn_anon) ...@@ -3250,7 +3209,8 @@ finish_struct_1 (t, warn_anon)
} }
} }
for (x = TYPE_FIELDS (t); x; x = TREE_CHAIN (x)) last_x = NULL_TREE;
for (x = fields; x; x = TREE_CHAIN (x))
{ {
GNU_xref_member (current_class_name, x); GNU_xref_member (current_class_name, x);
...@@ -3797,6 +3757,9 @@ finish_struct_1 (t, warn_anon) ...@@ -3797,6 +3757,9 @@ finish_struct_1 (t, warn_anon)
} }
if (n_baseclasses)
fields = chainon (build_vbase_pointer_fields (t), fields);
if (vfield == NULL_TREE && has_virtual) if (vfield == NULL_TREE && has_virtual)
{ {
/* We build this decl with ptr_type_node, and /* We build this decl with ptr_type_node, and
...@@ -3888,21 +3851,8 @@ finish_struct_1 (t, warn_anon) ...@@ -3888,21 +3851,8 @@ finish_struct_1 (t, warn_anon)
TYPE_FIELDS (t) = fields; TYPE_FIELDS (t) = fields;
/* Pass layout information about base classes to layout_type, if any. */
if (n_baseclasses) if (n_baseclasses)
{ TYPE_FIELDS (t) = chainon (build_base_fields (t), fields);
tree pseudo_basetype = TREE_TYPE (base_layout_decl);
TREE_CHAIN (base_layout_decl) = TYPE_FIELDS (t);
TYPE_FIELDS (t) = base_layout_decl;
TYPE_SIZE (pseudo_basetype) = CLASSTYPE_SIZE (t);
TYPE_MODE (pseudo_basetype) = TYPE_MODE (t);
TYPE_ALIGN (pseudo_basetype) = CLASSTYPE_ALIGN (t);
DECL_ALIGN (base_layout_decl) = TYPE_ALIGN (pseudo_basetype);
/* Don't re-use old size. */
DECL_SIZE (base_layout_decl) = NULL_TREE;
}
else if (empty) else if (empty)
{ {
/* C++: do not let empty structures exist. */ /* C++: do not let empty structures exist. */
...@@ -3914,16 +3864,13 @@ finish_struct_1 (t, warn_anon) ...@@ -3914,16 +3864,13 @@ finish_struct_1 (t, warn_anon)
layout_type (t); layout_type (t);
/* Remember the size, mode and alignment of the class before adding /* Remember the size and alignment of the class before adding
the virtual bases. */ the virtual bases. */
CLASSTYPE_SIZE (t) = TYPE_SIZE (t); CLASSTYPE_SIZE (t) = TYPE_SIZE (t);
CLASSTYPE_ALIGN (t) = TYPE_ALIGN (t); CLASSTYPE_ALIGN (t) = TYPE_ALIGN (t);
finish_struct_anon (t); finish_struct_anon (t);
if (n_baseclasses || empty)
TYPE_FIELDS (t) = TREE_CHAIN (TYPE_FIELDS (t));
/* Set the TYPE_DECL for this type to contain the right /* Set the TYPE_DECL for this type to contain the right
value for DECL_OFFSET, so that we can use it as part value for DECL_OFFSET, so that we can use it as part
of a COMPONENT_REF for multiple inheritance. */ of a COMPONENT_REF for multiple inheritance. */
...@@ -3935,11 +3882,16 @@ finish_struct_1 (t, warn_anon) ...@@ -3935,11 +3882,16 @@ finish_struct_1 (t, warn_anon)
virtual function table. */ virtual function table. */
pending_hard_virtuals = nreverse (pending_hard_virtuals); pending_hard_virtuals = nreverse (pending_hard_virtuals);
if (n_baseclasses)
/* layout_basetypes will remove the base subobject fields. */
max_has_virtual = layout_basetypes (t, max_has_virtual);
else if (empty)
TYPE_FIELDS (t) = fields;
if (TYPE_USES_VIRTUAL_BASECLASSES (t)) if (TYPE_USES_VIRTUAL_BASECLASSES (t))
{ {
tree vbases; tree vbases;
max_has_virtual = layout_vbasetypes (t, max_has_virtual);
vbases = CLASSTYPE_VBASECLASSES (t); vbases = CLASSTYPE_VBASECLASSES (t);
CLASSTYPE_N_VBASECLASSES (t) = list_length (vbases); CLASSTYPE_N_VBASECLASSES (t) = list_length (vbases);
......
...@@ -728,13 +728,7 @@ struct lang_type ...@@ -728,13 +728,7 @@ struct lang_type
#define CLASSTYPE_MTABLE_ENTRY(NODE) (TYPE_LANG_SPECIFIC(NODE)->memoized_table_entry) #define CLASSTYPE_MTABLE_ENTRY(NODE) (TYPE_LANG_SPECIFIC(NODE)->memoized_table_entry)
/* These are the size, mode and alignment of the type without its /* 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. virtual base classes, for when we use this type as a base itself. */
CLASSTYPE_SIZE is also used during finish_struct_1 to remember the total
size of the baseclasses defined for the type. We do this because it is
desirable to layout such information before beginning to process the
class itself, and we don't want to compute it second time when actually
laying out the type for real. */
#define CLASSTYPE_SIZE(NODE) (TYPE_LANG_SPECIFIC(NODE)->size) #define CLASSTYPE_SIZE(NODE) (TYPE_LANG_SPECIFIC(NODE)->size)
#define CLASSTYPE_ALIGN(NODE) (TYPE_LANG_SPECIFIC(NODE)->align) #define CLASSTYPE_ALIGN(NODE) (TYPE_LANG_SPECIFIC(NODE)->align)
...@@ -2591,9 +2585,9 @@ extern tree break_out_calls PROTO((tree)); ...@@ -2591,9 +2585,9 @@ extern tree break_out_calls PROTO((tree));
extern tree build_cplus_method_type PROTO((tree, tree, 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_staticfn_type PROTO((tree, tree, tree));
extern tree build_cplus_array_type PROTO((tree, tree)); extern tree build_cplus_array_type PROTO((tree, tree));
extern void propagate_binfo_offsets PROTO((tree, tree)); extern int layout_basetypes PROTO((tree, int));
extern int layout_vbasetypes PROTO((tree, int)); extern tree build_vbase_pointer_fields PROTO((tree));
extern tree layout_basetypes PROTO((tree, tree)); extern tree build_base_fields PROTO((tree));
extern tree hash_tree_cons PROTO((int, int, int, tree, tree, tree)); extern tree hash_tree_cons PROTO((int, int, int, tree, tree, tree));
extern tree hash_tree_chain PROTO((tree, tree)); extern tree hash_tree_chain PROTO((tree, tree));
extern tree hash_chainon PROTO((tree, tree)); extern tree hash_chainon PROTO((tree, tree));
......
...@@ -42,6 +42,8 @@ static void list_hash_add PROTO((int, tree)); ...@@ -42,6 +42,8 @@ static void list_hash_add PROTO((int, tree));
static int list_hash PROTO((tree, tree, tree)); static int list_hash PROTO((tree, tree, tree));
static tree list_hash_lookup PROTO((int, int, int, int, tree, tree, static tree list_hash_lookup PROTO((int, int, int, int, tree, tree,
tree)); tree));
static void propagate_binfo_offsets PROTO((tree, tree));
static void unshare_base_binfos PROTO((tree));
#define CEIL(x,y) (((x) + (y) - 1) / (y)) #define CEIL(x,y) (((x) + (y) - 1) / (y))
...@@ -548,7 +550,7 @@ cp_build_type_variant (type, constp, volatilep) ...@@ -548,7 +550,7 @@ cp_build_type_variant (type, constp, volatilep)
Note that we don't have to worry about having two paths to the Note that we don't have to worry about having two paths to the
same base type, since this type owns its association list. */ same base type, since this type owns its association list. */
void static void
propagate_binfo_offsets (binfo, offset) propagate_binfo_offsets (binfo, offset)
tree binfo; tree binfo;
tree offset; tree offset;
...@@ -588,31 +590,8 @@ propagate_binfo_offsets (binfo, offset) ...@@ -588,31 +590,8 @@ propagate_binfo_offsets (binfo, offset)
#else #else
BINFO_OFFSET (base_binfo) = offset; BINFO_OFFSET (base_binfo) = offset;
#endif #endif
if (base_binfos)
{ unshare_base_binfos (base_binfo);
int k;
tree chain = NULL_TREE;
/* Now unshare the structure beneath BASE_BINFO. */
for (k = TREE_VEC_LENGTH (base_binfos)-1;
k >= 0; k--)
{
tree base_base_binfo = TREE_VEC_ELT (base_binfos, k);
if (! TREE_VIA_VIRTUAL (base_base_binfo))
TREE_VEC_ELT (base_binfos, k)
= make_binfo (BINFO_OFFSET (base_base_binfo),
base_base_binfo,
BINFO_VTABLE (base_base_binfo),
BINFO_VIRTUALS (base_base_binfo),
chain);
chain = TREE_VEC_ELT (base_binfos, k);
TREE_VIA_PUBLIC (chain) = TREE_VIA_PUBLIC (base_base_binfo);
TREE_VIA_PROTECTED (chain) = TREE_VIA_PROTECTED (base_base_binfo);
BINFO_INHERITANCE_CHAIN (chain) = base_binfo;
}
/* Now propagate the offset to the base types. */
propagate_binfo_offsets (base_binfo, offset);
}
/* Go to our next class that counts for offset propagation. */ /* Go to our next class that counts for offset propagation. */
i = j; i = j;
...@@ -622,19 +601,59 @@ propagate_binfo_offsets (binfo, offset) ...@@ -622,19 +601,59 @@ propagate_binfo_offsets (binfo, offset)
} }
} }
/* Compute the actual offsets that our virtual base classes /* Makes new binfos for the indirect bases under BASE_BINFO, and updates
will have *for this type*. This must be performed after BINFO_OFFSET for them and their bases. */
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 virtual static void
unshare_base_binfos (base_binfo)
tree base_binfo;
{
if (BINFO_BASETYPES (base_binfo))
{
tree base_binfos = BINFO_BASETYPES (base_binfo);
tree chain = NULL_TREE;
int j;
/* Now unshare the structure beneath BASE_BINFO. */
for (j = TREE_VEC_LENGTH (base_binfos)-1;
j >= 0; j--)
{
tree base_base_binfo = TREE_VEC_ELT (base_binfos, j);
if (! TREE_VIA_VIRTUAL (base_base_binfo))
TREE_VEC_ELT (base_binfos, j)
= make_binfo (BINFO_OFFSET (base_base_binfo),
base_base_binfo,
BINFO_VTABLE (base_base_binfo),
BINFO_VIRTUALS (base_base_binfo),
chain);
chain = TREE_VEC_ELT (base_binfos, j);
TREE_VIA_PUBLIC (chain) = TREE_VIA_PUBLIC (base_base_binfo);
TREE_VIA_PROTECTED (chain) = TREE_VIA_PROTECTED (base_base_binfo);
BINFO_INHERITANCE_CHAIN (chain) = base_binfo;
}
/* Completely unshare potentially shared data, and
update what is ours. */
propagate_binfo_offsets (base_binfo, BINFO_OFFSET (base_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. */ baseclasses provide. */
int int
layout_vbasetypes (rec, max) layout_basetypes (rec, max)
tree rec; tree rec;
int max; int max;
{ {
tree binfos = TYPE_BINFO_BASETYPES (rec);
int i, n_baseclasses = binfos ? TREE_VEC_LENGTH (binfos) : 0;
/* Get all the virtual base types that this type uses. /* Get all the virtual base types that this type uses.
The TREE_VALUE slot holds the virtual baseclass type. */ The TREE_VALUE slot holds the virtual baseclass type. */
tree vbase_types = get_vbase_types (rec); tree vbase_types = get_vbase_types (rec);
...@@ -672,8 +691,7 @@ layout_vbasetypes (rec, max) ...@@ -672,8 +691,7 @@ layout_vbasetypes (rec, max)
else else
{ {
/* Give each virtual base type the alignment it wants. */ /* Give each virtual base type the alignment it wants. */
const_size = CEIL (const_size, TYPE_ALIGN (basetype)) const_size = CEIL (const_size, desired_align) * desired_align;
* TYPE_ALIGN (basetype);
offset = size_int (CEIL (const_size, BITS_PER_UNIT)); offset = size_int (CEIL (const_size, BITS_PER_UNIT));
} }
...@@ -704,85 +722,106 @@ layout_vbasetypes (rec, max) ...@@ -704,85 +722,106 @@ layout_vbasetypes (rec, max)
if (const_size != nonvirtual_const_size) if (const_size != nonvirtual_const_size)
TYPE_SIZE (rec) = size_int (const_size); TYPE_SIZE (rec) = size_int (const_size);
/* Now propagate offset information throughout the lattice /* Now propagate offset information throughout the lattice. */
under the vbase type. */ for (i = 0; i < n_baseclasses; i++)
for (vbase_types = CLASSTYPE_VBASECLASSES (rec); vbase_types;
vbase_types = TREE_CHAIN (vbase_types))
{ {
tree base_binfos = BINFO_BASETYPES (vbase_types); register tree base_binfo = TREE_VEC_ELT (binfos, i);
register tree basetype = BINFO_TYPE (base_binfo);
BINFO_INHERITANCE_CHAIN (vbase_types) = TYPE_BINFO (rec); tree field = TYPE_FIELDS (rec);
if (base_binfos) if (TREE_VIA_VIRTUAL (base_binfo))
{ continue;
tree chain = NULL_TREE;
int j;
/* Now unshare the structure beneath BASE_BINFO. */
for (j = TREE_VEC_LENGTH (base_binfos)-1; my_friendly_assert (TREE_TYPE (field) == basetype, 23897);
j >= 0; j--) BINFO_OFFSET (base_binfo)
{ = size_int (CEIL (TREE_INT_CST_LOW (DECL_FIELD_BITPOS (field)),
tree base_base_binfo = TREE_VEC_ELT (base_binfos, j); BITS_PER_UNIT));
if (! TREE_VIA_VIRTUAL (base_base_binfo)) unshare_base_binfos (base_binfo);
TREE_VEC_ELT (base_binfos, j) TYPE_FIELDS (rec) = TREE_CHAIN (field);
= make_binfo (BINFO_OFFSET (base_base_binfo), }
base_base_binfo,
BINFO_VTABLE (base_base_binfo),
BINFO_VIRTUALS (base_base_binfo),
chain);
chain = TREE_VEC_ELT (base_binfos, j);
TREE_VIA_PUBLIC (chain) = TREE_VIA_PUBLIC (base_base_binfo);
TREE_VIA_PROTECTED (chain) = TREE_VIA_PROTECTED (base_base_binfo);
BINFO_INHERITANCE_CHAIN (chain) = vbase_types;
}
propagate_binfo_offsets (vbase_types, BINFO_OFFSET (vbase_types)); 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);
} }
return max; return max;
} }
/* Lay out the base types of a record type, REC. /* Returns a list of fields to stand in for the base class subobjects
Tentatively set the size and alignment of REC of REC. These fields are later removed by layout_basetypes. */
according to the base types alone.
tree
build_base_fields (rec)
tree rec;
{
/* Chain to hold all the new FIELD_DECLs which stand in for base class
subobjects. */
tree base_decls = NULL_TREE;
tree binfos = TYPE_BINFO_BASETYPES (rec);
int n_baseclasses = binfos ? TREE_VEC_LENGTH (binfos) : 0;
tree decl;
int i;
unsigned int base_align = 0;
for (i = 0; i < n_baseclasses; ++i)
{
register tree base_binfo = TREE_VEC_ELT (binfos, i);
register tree basetype = BINFO_TYPE (base_binfo);
Offsets for immediate nonvirtual baseclasses are also computed here. if (TYPE_SIZE (basetype) == 0)
/* This error is now reported in xref_tag, thus giving better
location information. */
continue;
TYPE_BINFO (REC) should be NULL_TREE on entry, and this routine if (TREE_VIA_VIRTUAL (base_binfo))
creates a list of base_binfos in TYPE_BINFO (REC) from BINFOS. continue;
Returns list of virtual base class pointers in a FIELD_DECL chain. */ decl = build_lang_field_decl (FIELD_DECL, NULL_TREE, basetype);
DECL_ARTIFICIAL (decl) = 1;
DECL_FIELD_CONTEXT (decl) = DECL_CLASS_CONTEXT (decl) = rec;
DECL_SIZE (decl) = CLASSTYPE_SIZE (basetype);
DECL_ALIGN (decl) = CLASSTYPE_ALIGN (basetype);
TREE_CHAIN (decl) = base_decls;
base_decls = decl;
/* Brain damage for backwards compatibility. For no good reason, the
old layout_basetypes made every base at least as large as the
alignment for the bases up to that point, gratuitously wasting
space. So we do the same thing here. */
base_align = MAX (base_align, DECL_ALIGN (decl));
DECL_SIZE (decl) = size_int (MAX (TREE_INT_CST_LOW (DECL_SIZE (decl)),
base_align));
}
/* Reverse the list of fields so we allocate the bases in the proper
order. */
return nreverse (base_decls);
}
/* Returns list of virtual base class pointers in a FIELD_DECL chain. */
tree tree
layout_basetypes (rec, binfos) build_vbase_pointer_fields (rec)
tree rec, binfos; tree rec;
{ {
/* Chain to hold all the new FIELD_DECLs which point at virtual /* Chain to hold all the new FIELD_DECLs which point at virtual
base classes. */ base classes. */
tree vbase_decls = NULL_TREE; tree vbase_decls = NULL_TREE;
unsigned record_align = MAX (BITS_PER_UNIT, TYPE_ALIGN (rec)); tree binfos = TYPE_BINFO_BASETYPES (rec);
int n_baseclasses = binfos ? TREE_VEC_LENGTH (binfos) : 0;
/* Record size so far is CONST_SIZE bits, where CONST_SIZE is an integer. */ tree decl;
register unsigned const_size = 0; int i;
int i, n_baseclasses = binfos ? TREE_VEC_LENGTH (binfos) : 0;
#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
/* Handle basetypes almost like fields, but record their /* Handle basetypes almost like fields, but record their
offsets differently. */ offsets differently. */
for (i = 0; i < n_baseclasses; i++) for (i = 0; i < n_baseclasses; i++)
{ {
int inc;
unsigned int desired_align;
register tree base_binfo = TREE_VEC_ELT (binfos, i); register tree base_binfo = TREE_VEC_ELT (binfos, i);
register tree basetype = BINFO_TYPE (base_binfo); register tree basetype = BINFO_TYPE (base_binfo);
tree decl, offset;
if (TYPE_SIZE (basetype) == 0) if (TYPE_SIZE (basetype) == 0)
/* This error is now reported in xref_tag, thus giving better /* This error is now reported in xref_tag, thus giving better
...@@ -811,7 +850,9 @@ layout_basetypes (rec, binfos) ...@@ -811,7 +850,9 @@ layout_basetypes (rec, binfos)
tree other_base_binfo = TREE_VEC_ELT (binfos, j); tree other_base_binfo = TREE_VEC_ELT (binfos, j);
if (! TREE_VIA_VIRTUAL (other_base_binfo) if (! TREE_VIA_VIRTUAL (other_base_binfo)
&& binfo_member (basetype, && binfo_member (basetype,
CLASSTYPE_VBASECLASSES (BINFO_TYPE (other_base_binfo)))) CLASSTYPE_VBASECLASSES (BINFO_TYPE
(other_base_binfo))
))
goto got_it; goto got_it;
} }
sprintf (name, VBASE_NAME_FORMAT, TYPE_NAME_STRING (basetype)); sprintf (name, VBASE_NAME_FORMAT, TYPE_NAME_STRING (basetype));
...@@ -835,51 +876,10 @@ layout_basetypes (rec, binfos) ...@@ -835,51 +876,10 @@ layout_basetypes (rec, binfos)
got_it: got_it:
/* The space this decl occupies has already been accounted for. */ /* The space this decl occupies has already been accounted for. */
continue; ;
}
/* Effective C++ rule 14. We only need to check TYPE_VIRTUAL_P
here because the case of virtual functions but non-virtual
dtor is handled in finish_struct_1. */
if (warn_ecpp && ! TYPE_VIRTUAL_P (basetype)
&& TYPE_HAS_DESTRUCTOR (basetype))
cp_warning ("base class `%#T' has a non-virtual destructor", basetype);
if (const_size == 0)
offset = integer_zero_node;
else
{
/* Give each base type the alignment it wants. */
const_size = CEIL (const_size, TYPE_ALIGN (basetype))
* TYPE_ALIGN (basetype);
offset = size_int ((const_size + BITS_PER_UNIT - 1) / BITS_PER_UNIT);
} }
BINFO_OFFSET (base_binfo) = offset;
if (CLASSTYPE_VSIZE (basetype))
{
BINFO_VTABLE (base_binfo) = TYPE_BINFO_VTABLE (basetype);
BINFO_VIRTUALS (base_binfo) = TYPE_BINFO_VIRTUALS (basetype);
}
TREE_CHAIN (base_binfo) = TYPE_BINFO (rec);
TYPE_BINFO (rec) = base_binfo;
/* Add only the amount of storage not present in
the virtual baseclasses. */
inc = MAX (record_align, TREE_INT_CST_LOW (CLASSTYPE_SIZE (basetype)));
/* Record must have at least as much alignment as any field. */
desired_align = TYPE_ALIGN (basetype);
record_align = MAX (record_align, desired_align);
const_size += inc;
} }
if (const_size)
CLASSTYPE_SIZE (rec) = size_int (const_size);
else
CLASSTYPE_SIZE (rec) = integer_zero_node;
CLASSTYPE_ALIGN (rec) = record_align;
return vbase_decls; return vbase_decls;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment