From: Jason Merrill Date: Fri, 3 Apr 1998 03:41:20 +0000 (-0500) Subject: Re-implement allocation of base class subobjects. X-Git-Tag: prereleases/egcs-1.1-prerelease~1838 X-Git-Url: https://gcc.gnu.org/git/?a=commitdiff_plain;h=9a71c18b28efc85365b4a221558d748ec6582794;p=gcc.git 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 --- diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 3de389d3c4e6..76101855e08e 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,17 @@ +Fri Apr 3 02:22:59 1998 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. + Thu Apr 2 14:25:13 1998 Jason Merrill * 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) * class.c, Make sure system.h is included just after config.h. 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 diff --git a/gcc/cp/class.c b/gcc/cp/class.c index 3559c04221eb..c39caac5b119 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -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, tree, 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. */ tree *current_lang_base, *current_lang_stack; @@ -1526,17 +1526,14 @@ struct base_info offsets include that offset in theirs. Returns the index of the first base class to have virtual functions, - or -1 if no such base class. - - Note that at this point TYPE_BINFO (t) != t_binfo. */ + or -1 if no such base class. */ static int -finish_base_struct (t, b, t_binfo) +finish_base_struct (t, b) tree t; 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 first_vfn_base_index = -1; bzero ((char *) b, sizeof (struct base_info)); @@ -1546,6 +1543,13 @@ finish_base_struct (t, b, t_binfo) tree base_binfo = TREE_VEC_ELT (binfos, i); 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 we already complained about that fact (and we should have fixed it up as well). */ @@ -1592,36 +1596,6 @@ finish_base_struct (t, b, t_binfo) TYPE_OVERLOADS_ARRAY_REF (t) |= TYPE_OVERLOADS_ARRAY_REF (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)) CLASSTYPE_N_SUPERCLASSES (t) += 1; @@ -1644,8 +1618,8 @@ finish_base_struct (t, b, t_binfo) /* Update these two, now that we know what vtable we are going to extend. This is so that we can add virtual functions, and override them properly. */ - BINFO_VTABLE (t_binfo) = TYPE_BINFO_VTABLE (basetype); - BINFO_VIRTUALS (t_binfo) = TYPE_BINFO_VIRTUALS (basetype); + TYPE_BINFO_VTABLE (t) = TYPE_BINFO_VTABLE (basetype); + TYPE_BINFO_VIRTUALS (t) = TYPE_BINFO_VIRTUALS (basetype); b->has_virtual = CLASSTYPE_VSIZE (basetype); b->vfield = CLASSTYPE_VFIELD (basetype); b->vfields = copy_list (CLASSTYPE_VFIELDS (basetype)); @@ -1693,8 +1667,8 @@ finish_base_struct (t, b, t_binfo) /* Update these two, now that we know what vtable we are going to extend. This is so that we can add virtual functions, and override them properly. */ - BINFO_VTABLE (t_binfo) = TYPE_BINFO_VTABLE (basetype); - BINFO_VIRTUALS (t_binfo) = TYPE_BINFO_VIRTUALS (basetype); + TYPE_BINFO_VTABLE (t) = TYPE_BINFO_VTABLE (basetype); + TYPE_BINFO_VIRTUALS (t) = TYPE_BINFO_VIRTUALS (basetype); b->has_virtual = CLASSTYPE_VSIZE (basetype); b->vfield = CLASSTYPE_VFIELD (basetype); CLASSTYPE_VFIELD (t) = b->vfield; @@ -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++) { tree base_binfo = TREE_VEC_ELT (binfos, i); 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", basetype, t); } } { - tree v = get_vbase_types (t_binfo); + tree v = get_vbase_types (t); for (; v; v = TREE_CHAIN (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) cp_warning ("virtual base `%T' inaccessible in `%T' due to ambiguity", @@ -3088,7 +3064,6 @@ finish_struct_1 (t, warn_anon) int const_sans_init = 0; int ref_sans_init = 0; int nonprivate_method = 0; - tree t_binfo = TYPE_BINFO (t); tree access_decls = NULL_TREE; int aggregate = 1; int empty = 1; @@ -3125,13 +3100,6 @@ finish_struct_1 (t, warn_anon) } #endif -#if 0 - if (flag_rtti) - build_t_desc (t, 0); -#endif - - TYPE_BINFO (t) = NULL_TREE; - old = suspend_momentary (); /* Install struct as DECL_FIELD_CONTEXT of each field decl. @@ -3141,8 +3109,8 @@ finish_struct_1 (t, warn_anon) Store 0 there, except for ": 0" fields (so we can find them and delete them, below). */ - if (t_binfo && BINFO_BASETYPES (t_binfo)) - n_baseclasses = TREE_VEC_LENGTH (BINFO_BASETYPES (t_binfo)); + if (TYPE_BINFO_BASETYPES (t)) + n_baseclasses = TREE_VEC_LENGTH (TYPE_BINFO_BASETYPES (t)); else n_baseclasses = 0; @@ -3150,13 +3118,7 @@ finish_struct_1 (t, warn_anon) { struct base_info base_info; - /* If using multiple inheritance, this may cause variants of our - 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); + first_vfn_base_index = finish_base_struct (t, &base_info); /* Remember where we got our vfield from. */ CLASSTYPE_VFIELD_PARENT (t) = first_vfn_base_index; has_virtual = base_info.has_virtual; @@ -3168,8 +3130,8 @@ finish_struct_1 (t, warn_anon) cant_have_default_ctor = base_info.cant_have_default_ctor; cant_have_const_ctor = base_info.cant_have_const_ctor; no_const_asn_ref = base_info.no_const_asn_ref; - n_baseclasses = TREE_VEC_LENGTH (BINFO_BASETYPES (t_binfo)); aggregate = 0; + empty = 0; } else { @@ -3179,7 +3141,6 @@ finish_struct_1 (t, warn_anon) vfield = NULL_TREE; vfields = NULL_TREE; CLASSTYPE_RTTI (t) = NULL_TREE; - last_x = NULL_TREE; cant_have_default_ctor = 0; cant_have_const_ctor = 0; no_const_asn_ref = 0; @@ -3198,8 +3159,6 @@ finish_struct_1 (t, warn_anon) /* The three of these are approximations which may later be modified. Needed at this point to make add_virtual_function and modify_vtable_entries work. */ - TREE_CHAIN (t_binfo) = TYPE_BINFO (t); - TYPE_BINFO (t) = t_binfo; CLASSTYPE_VFIELDS (t) = vfields; CLASSTYPE_VFIELD (t) = vfield; @@ -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); @@ -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) { /* We build this decl with ptr_type_node, and @@ -3888,21 +3851,8 @@ finish_struct_1 (t, warn_anon) TYPE_FIELDS (t) = fields; - /* Pass layout information about base classes to layout_type, if any. */ if (n_baseclasses) - { - 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; - } + TYPE_FIELDS (t) = chainon (build_base_fields (t), fields); else if (empty) { /* C++: do not let empty structures exist. */ @@ -3914,16 +3864,13 @@ finish_struct_1 (t, warn_anon) 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. */ CLASSTYPE_SIZE (t) = TYPE_SIZE (t); CLASSTYPE_ALIGN (t) = TYPE_ALIGN (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 value for DECL_OFFSET, so that we can use it as part of a COMPONENT_REF for multiple inheritance. */ @@ -3935,11 +3882,16 @@ finish_struct_1 (t, warn_anon) virtual function table. */ 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)) { tree vbases; - max_has_virtual = layout_vbasetypes (t, max_has_virtual); vbases = CLASSTYPE_VBASECLASSES (t); CLASSTYPE_N_VBASECLASSES (t) = list_length (vbases); diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 25749d3625f1..c62fe082a97b 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -728,13 +728,7 @@ struct lang_type #define CLASSTYPE_MTABLE_ENTRY(NODE) (TYPE_LANG_SPECIFIC(NODE)->memoized_table_entry) /* 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. - - 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. */ + virtual base classes, for when we use this type as a base itself. */ #define CLASSTYPE_SIZE(NODE) (TYPE_LANG_SPECIFIC(NODE)->size) #define CLASSTYPE_ALIGN(NODE) (TYPE_LANG_SPECIFIC(NODE)->align) @@ -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_staticfn_type PROTO((tree, tree, tree)); extern tree build_cplus_array_type PROTO((tree, tree)); -extern void propagate_binfo_offsets PROTO((tree, tree)); -extern int layout_vbasetypes PROTO((tree, int)); -extern tree layout_basetypes PROTO((tree, tree)); +extern int layout_basetypes PROTO((tree, int)); +extern tree build_vbase_pointer_fields PROTO((tree)); +extern tree build_base_fields PROTO((tree)); extern tree hash_tree_cons PROTO((int, int, int, tree, tree, tree)); extern tree hash_tree_chain PROTO((tree, tree)); extern tree hash_chainon PROTO((tree, tree)); diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index 2f6dbe623bcb..8f4d02d70ffa 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -42,6 +42,8 @@ static void list_hash_add PROTO((int, tree)); static int list_hash PROTO((tree, tree, tree)); static tree list_hash_lookup PROTO((int, int, int, int, 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)) @@ -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 same base type, since this type owns its association list. */ -void +static void propagate_binfo_offsets (binfo, offset) tree binfo; tree offset; @@ -588,31 +590,8 @@ propagate_binfo_offsets (binfo, offset) #else BINFO_OFFSET (base_binfo) = offset; #endif - if (base_binfos) - { - 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); - } + + unshare_base_binfos (base_binfo); /* Go to our next class that counts for offset propagation. */ i = j; @@ -622,19 +601,59 @@ propagate_binfo_offsets (binfo, offset) } } -/* Compute the actual offsets that our virtual base classes - will have *for this type*. This must be performed after - the fields are laid out, since virtual baseclasses must - lay down at the end of the record. +/* Makes new binfos for the indirect bases under BASE_BINFO, and updates + BINFO_OFFSET for them and their bases. */ - 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. */ int -layout_vbasetypes (rec, max) +layout_basetypes (rec, max) tree rec; 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. The TREE_VALUE slot holds the virtual baseclass type. */ tree vbase_types = get_vbase_types (rec); @@ -672,8 +691,7 @@ layout_vbasetypes (rec, max) else { /* Give each virtual base type the alignment it wants. */ - const_size = CEIL (const_size, TYPE_ALIGN (basetype)) - * TYPE_ALIGN (basetype); + const_size = CEIL (const_size, desired_align) * desired_align; offset = size_int (CEIL (const_size, BITS_PER_UNIT)); } @@ -704,85 +722,106 @@ layout_vbasetypes (rec, max) if (const_size != nonvirtual_const_size) TYPE_SIZE (rec) = size_int (const_size); - /* Now propagate offset information throughout the lattice - under the vbase type. */ - for (vbase_types = CLASSTYPE_VBASECLASSES (rec); vbase_types; - vbase_types = TREE_CHAIN (vbase_types)) + /* Now propagate offset information throughout the lattice. */ + for (i = 0; i < n_baseclasses; i++) { - tree base_binfos = BINFO_BASETYPES (vbase_types); - - BINFO_INHERITANCE_CHAIN (vbase_types) = TYPE_BINFO (rec); + register tree base_binfo = TREE_VEC_ELT (binfos, i); + register tree basetype = BINFO_TYPE (base_binfo); + tree field = TYPE_FIELDS (rec); - if (base_binfos) - { - tree chain = NULL_TREE; - int j; - /* Now unshare the structure beneath BASE_BINFO. */ + if (TREE_VIA_VIRTUAL (base_binfo)) + continue; - 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) = vbase_types; - } + my_friendly_assert (TREE_TYPE (field) == basetype, 23897); + BINFO_OFFSET (base_binfo) + = size_int (CEIL (TREE_INT_CST_LOW (DECL_FIELD_BITPOS (field)), + BITS_PER_UNIT)); + unshare_base_binfos (base_binfo); + TYPE_FIELDS (rec) = TREE_CHAIN (field); + } - 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; } -/* Lay out the base types of a record type, REC. - Tentatively set the size and alignment of REC - according to the base types alone. +/* Returns a list of fields to stand in for the base class subobjects + of REC. These fields are later removed by layout_basetypes. */ + +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 - creates a list of base_binfos in TYPE_BINFO (REC) from BINFOS. + if (TREE_VIA_VIRTUAL (base_binfo)) + 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 -layout_basetypes (rec, binfos) - tree rec, binfos; +build_vbase_pointer_fields (rec) + tree rec; { /* Chain to hold all the new FIELD_DECLs which point at virtual base classes. */ tree vbase_decls = NULL_TREE; - unsigned record_align = MAX (BITS_PER_UNIT, TYPE_ALIGN (rec)); - - /* Record size so far is CONST_SIZE bits, where CONST_SIZE is an integer. */ - register unsigned const_size = 0; - 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 + tree binfos = TYPE_BINFO_BASETYPES (rec); + int n_baseclasses = binfos ? TREE_VEC_LENGTH (binfos) : 0; + tree decl; + int i; /* Handle basetypes almost like fields, but record their offsets differently. */ for (i = 0; i < n_baseclasses; i++) { - int inc; - unsigned int desired_align; register tree base_binfo = TREE_VEC_ELT (binfos, i); register tree basetype = BINFO_TYPE (base_binfo); - tree decl, offset; if (TYPE_SIZE (basetype) == 0) /* This error is now reported in xref_tag, thus giving better @@ -811,7 +850,9 @@ layout_basetypes (rec, binfos) tree other_base_binfo = TREE_VEC_ELT (binfos, j); if (! TREE_VIA_VIRTUAL (other_base_binfo) && binfo_member (basetype, - CLASSTYPE_VBASECLASSES (BINFO_TYPE (other_base_binfo)))) + CLASSTYPE_VBASECLASSES (BINFO_TYPE + (other_base_binfo)) + )) goto got_it; } sprintf (name, VBASE_NAME_FORMAT, TYPE_NAME_STRING (basetype)); @@ -835,51 +876,10 @@ layout_basetypes (rec, binfos) got_it: /* 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; }