From 58731fd132e25cb603d1e1feaaace2cb91250c12 Mon Sep 17 00:00:00 2001 From: Mark Mitchell Date: Tue, 15 Oct 2002 18:07:24 +0000 Subject: [PATCH] class.c (check_field_decls): Remove empty_p parameter. * class.c (check_field_decls): Remove empty_p parameter. Instead, clear CLASSTYPE_EMPTY_P. (build_base_field): Likewise. (build_base_fields): Likewise. (check_bases_and_members): Likewise. (create_vtbl_ptr): Likewise. (layout_class_type): Likewise. Ensure that empty classes have size zero when used as base classes in the 3.2 ABI. (finish_struct_1): Initialize CLASSTYPE_EMPTY_P and CLASSTYPE_NEARLY_EMPTY_P. Adjust calls to avoid passing empty_p parameter. (is_empty_class): Correct definition when using post-3.2 ABI. * cp-tree.h (lang_type_class): Add empty_p. (CLASSTYPE_EMPTY_P): New macro. From-SVN: r58170 --- gcc/cp/ChangeLog | 17 +++++ gcc/cp/class.c | 119 ++++++++++++++++-------------- gcc/cp/cp-tree.h | 7 +- gcc/testsuite/ChangeLog | 4 + gcc/testsuite/g++.dg/abi/empty8.C | 14 ++++ 5 files changed, 104 insertions(+), 57 deletions(-) create mode 100644 gcc/testsuite/g++.dg/abi/empty8.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index cce0b8e7c46..9087df7fe42 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,20 @@ +2002-10-14 Mark Mitchell + + * class.c (check_field_decls): Remove empty_p parameter. Instead, + clear CLASSTYPE_EMPTY_P. + (build_base_field): Likewise. + (build_base_fields): Likewise. + (check_bases_and_members): Likewise. + (create_vtbl_ptr): Likewise. + (layout_class_type): Likewise. Ensure that empty classes have + size zero when used as base classes in the 3.2 ABI. + (finish_struct_1): Initialize CLASSTYPE_EMPTY_P and + CLASSTYPE_NEARLY_EMPTY_P. Adjust calls to avoid passing empty_p + parameter. + (is_empty_class): Correct definition when using post-3.2 ABI. + * cp-tree.h (lang_type_class): Add empty_p. + (CLASSTYPE_EMPTY_P): New macro. + 2002-10-12 Nathan Sidwell * init.c (build_delete): Do not apply save_expr for arrays. diff --git a/gcc/cp/class.c b/gcc/cp/class.c index 5b5332579b1..59f5ce37fc1 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -134,20 +134,17 @@ static tree build_vtbl_initializer PARAMS ((tree, tree, tree, tree, int *)); static int count_fields PARAMS ((tree)); static int add_fields_to_vec PARAMS ((tree, tree, int)); static void check_bitfield_decl PARAMS ((tree)); -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 tree *build_base_field PARAMS ((record_layout_info, tree, int *, - splay_tree, tree *)); -static void build_base_fields PARAMS ((record_layout_info, int *, - splay_tree, tree *)); +static void check_field_decl (tree, tree, int *, int *, int *, int *); +static void check_field_decls (tree, tree *, int *, int *, int *); +static tree *build_base_field (record_layout_info, tree, splay_tree, tree *); +static void build_base_fields (record_layout_info, splay_tree, tree *); 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 *, tree *)); +static void check_bases_and_members (tree); +static tree create_vtable_ptr (tree, tree *); static void include_empty_classes (record_layout_info); -static void layout_class_type PARAMS ((tree, int *, int *, tree *)); +static void layout_class_type (tree, int *, tree *); static void fixup_pending_inline PARAMS ((tree)); static void fixup_inline_methods PARAMS ((tree)); static void set_primary_base PARAMS ((tree, tree, int *)); @@ -3201,15 +3198,10 @@ check_field_decl (field, t, cant_have_const_ctor, fields can be added by adding to this chain. */ static void -check_field_decls (t, access_decls, empty_p, - cant_have_default_ctor_p, cant_have_const_ctor_p, - no_const_asn_ref_p) - tree t; - tree *access_decls; - int *empty_p; - int *cant_have_default_ctor_p; - int *cant_have_const_ctor_p; - int *no_const_asn_ref_p; +check_field_decls (tree t, tree *access_decls, + int *cant_have_default_ctor_p, + int *cant_have_const_ctor_p, + int *no_const_asn_ref_p) { tree *field; tree *next; @@ -3245,7 +3237,7 @@ check_field_decls (t, access_decls, empty_p, else { /* The class is non-empty. */ - *empty_p = 0; + CLASSTYPE_EMPTY_P (t) = 0; /* The class is not even nearly empty. */ CLASSTYPE_NEARLY_EMPTY_P (t) = 0; } @@ -3821,8 +3813,7 @@ layout_empty_base (binfo, eoc, offsets, t) } /* Layout the the base given by BINFO in the class indicated by RLI. - If the new object is non-empty, and EMPTY_P is non-NULL, clear - *EMPTY_P. *BASE_ALIGN is a running maximum of the alignments of + *BASE_ALIGN is a running maximum of the alignments of any base class. OFFSETS gives the location of empty base subobjects. T is the most derived type. Return nonzero if the new object cannot be nearly-empty. A new FIELD_DECL is inserted at @@ -3831,7 +3822,7 @@ layout_empty_base (binfo, eoc, offsets, t) Returns the location at which the next field should be inserted. */ static tree * -build_base_field (record_layout_info rli, tree binfo, int *empty_p, +build_base_field (record_layout_info rli, tree binfo, splay_tree offsets, tree *next_field) { tree t = rli->t; @@ -3849,8 +3840,7 @@ build_base_field (record_layout_info rli, tree binfo, int *empty_p, /* The containing class is non-empty because it has a non-empty base class. */ - if (empty_p) - *empty_p = 0; + CLASSTYPE_EMPTY_P (t) = 0; /* Create the FIELD_DECL. */ decl = build_decl (FIELD_DECL, NULL_TREE, CLASSTYPE_AS_BASE (basetype)); @@ -3888,6 +3878,11 @@ build_base_field (record_layout_info rli, tree binfo, int *empty_p, create CONSTRUCTORs for the class by iterating over the FIELD_DECLs, and the back end does not handle overlapping FIELD_DECLs. */ + + /* An empty virtual base causes a class to be non-empty + -- but in that case we do not need to clear CLASSTYPE_EMPTY_P + here because that was already done when the virtual table + pointer was created. */ } /* Record the offsets of BINFO and its base subobjects. */ @@ -3906,7 +3901,7 @@ build_base_field (record_layout_info rli, tree binfo, int *empty_p, *NEXT_FIELD. */ static void -build_base_fields (record_layout_info rli, int *empty_p, +build_base_fields (record_layout_info rli, splay_tree offsets, tree *next_field) { /* Chain to hold all the new FIELD_DECLs which stand in for base class @@ -3918,7 +3913,7 @@ build_base_fields (record_layout_info rli, int *empty_p, /* The primary base class is always allocated first. */ if (CLASSTYPE_HAS_PRIMARY_BASE_P (t)) next_field = build_base_field (rli, CLASSTYPE_PRIMARY_BINFO (t), - empty_p, offsets, next_field); + offsets, next_field); /* Now allocate the rest of the bases. */ for (i = 0; i < n_baseclasses; ++i) @@ -3939,7 +3934,7 @@ build_base_fields (record_layout_info rli, int *empty_p, && !BINFO_PRIMARY_P (base_binfo)) continue; - next_field = build_base_field (rli, base_binfo, empty_p, + next_field = build_base_field (rli, base_binfo, offsets, next_field); } } @@ -4330,9 +4325,7 @@ type_requires_array_cookie (type) level: i.e., independently of the ABI in use. */ static void -check_bases_and_members (t, empty_p) - tree t; - int *empty_p; +check_bases_and_members (tree t) { /* Nonzero if we are not allowed to generate a default constructor for this case. */ @@ -4351,16 +4344,12 @@ check_bases_and_members (t, empty_p) cant_have_const_ctor = 0; no_const_asn_ref = 0; - /* Assume that the class is nearly empty; we'll clear this flag if - it turns out not to be nearly empty. */ - CLASSTYPE_NEARLY_EMPTY_P (t) = 1; - /* Check all the base-classes. */ check_bases (t, &cant_have_default_ctor, &cant_have_const_ctor, &no_const_asn_ref); /* Check all the data member declarations. */ - check_field_decls (t, &access_decls, empty_p, + check_field_decls (t, &access_decls, &cant_have_default_ctor, &cant_have_const_ctor, &no_const_asn_ref); @@ -4423,9 +4412,8 @@ check_bases_and_members (t, empty_p) on VIRTUALS_P. */ static tree -create_vtable_ptr (t, empty_p, virtuals_p) +create_vtable_ptr (t, virtuals_p) tree t; - int *empty_p; tree *virtuals_p; { tree fn; @@ -4483,7 +4471,7 @@ create_vtable_ptr (t, empty_p, virtuals_p) TYPE_VFIELD (t) = field; /* This class is non-empty. */ - *empty_p = 0; + CLASSTYPE_EMPTY_P (t) = 0; if (CLASSTYPE_N_BASECLASSES (t)) /* If there were any baseclasses, they can't possibly be at @@ -4688,7 +4676,7 @@ layout_virtual_bases (record_layout_info rli, splay_tree offsets) /* This virtual base is not a primary base of any class in the hierarchy, so we have to add space for it. */ - next_field = build_base_field (rli, vbase, /*empty_p=*/NULL, + next_field = build_base_field (rli, vbase, offsets, next_field); /* If the first virtual base might have been placed at a @@ -4843,11 +4831,7 @@ include_empty_classes (record_layout_info rli) pointer. Accumulate declared virtual functions on VIRTUALS_P. */ static void -layout_class_type (t, empty_p, vfuns_p, virtuals_p) - tree t; - int *empty_p; - int *vfuns_p; - tree *virtuals_p; +layout_class_type (tree t, int *vfuns_p, tree *virtuals_p) { tree non_static_data_members; tree field; @@ -4874,7 +4858,7 @@ layout_class_type (t, empty_p, vfuns_p, virtuals_p) determine_primary_base (t, vfuns_p); /* Create a pointer to our virtual function table. */ - vptr = create_vtable_ptr (t, empty_p, virtuals_p); + vptr = create_vtable_ptr (t, virtuals_p); /* The vptr is always the first thing in the class. */ if (vptr) @@ -4890,7 +4874,7 @@ layout_class_type (t, empty_p, vfuns_p, virtuals_p) /* Build FIELD_DECLs for all of the non-virtual base-types. */ empty_base_offsets = splay_tree_new (splay_tree_compare_integer_csts, NULL, NULL); - build_base_fields (rli, empty_p, empty_base_offsets, next_field); + build_base_fields (rli, empty_base_offsets, next_field); /* Layout the non-static data members. */ for (field = non_static_data_members; field; field = TREE_CHAIN (field)) @@ -5028,13 +5012,27 @@ layout_class_type (t, empty_p, vfuns_p, virtuals_p) /* Create the version of T used for virtual bases. We do not use make_aggr_type for this version; this is an artificial type. For a POD type, we just reuse T. */ - if (CLASSTYPE_NON_POD_P (t) || *empty_p) + if (CLASSTYPE_NON_POD_P (t) || CLASSTYPE_EMPTY_P (t)) { base_t = make_node (TREE_CODE (t)); - /* Set the size and alignment for the new type. */ - TYPE_SIZE (base_t) = rli_size_so_far (rli); - TYPE_SIZE_UNIT (base_t) = rli_size_unit_so_far (rli); + /* Set the size and alignment for the new type. In G++ 3.2, all + empty classes were considered to have size zero when used as + base classes. */ + if (!abi_version_at_least (2) && CLASSTYPE_EMPTY_P (t)) + { + TYPE_SIZE (base_t) = bitsize_zero_node; + TYPE_SIZE_UNIT (base_t) = size_zero_node; + if (warn_abi && !integer_zerop (rli_size_unit_so_far (rli))) + warning ("layout of classes derived from empty class `%T' " + "may change in a future version of GCC", + t); + } + else + { + TYPE_SIZE (base_t) = rli_size_so_far (rli); + TYPE_SIZE_UNIT (base_t) = rli_size_unit_so_far (rli); + } TYPE_ALIGN (base_t) = rli->record_align; TYPE_USER_ALIGN (base_t) = TYPE_USER_ALIGN (t); @@ -5075,7 +5073,7 @@ layout_class_type (t, empty_p, vfuns_p, virtuals_p) include_empty_classes(rli); /* Make sure not to create any structures with zero size. */ - if (integer_zerop (rli_size_unit_so_far (rli)) && *empty_p) + if (integer_zerop (rli_size_unit_so_far (rli)) && CLASSTYPE_EMPTY_P (t)) place_field (rli, build_decl (FIELD_DECL, NULL_TREE, char_type_node)); @@ -5126,7 +5124,6 @@ finish_struct_1 (t) tree virtuals = NULL_TREE; int n_fields = 0; tree vfield; - int empty = 1; if (COMPLETE_TYPE_P (t)) { @@ -5148,12 +5145,17 @@ finish_struct_1 (t) fixup_inline_methods (t); + /* Assume that the class is both empty and nearly empty; we'll clear + these flag if necessary. */ + CLASSTYPE_EMPTY_P (t) = 1; + CLASSTYPE_NEARLY_EMPTY_P (t) = 1; + /* Do end-of-class semantic processing: checking the validity of the bases and members and add implicitly generated methods. */ - check_bases_and_members (t, &empty); + check_bases_and_members (t); /* Layout the class itself. */ - layout_class_type (t, &empty, &vfuns, &virtuals); + layout_class_type (t, &vfuns, &virtuals); /* Make sure that we get our own copy of the vfield FIELD_DECL. */ vfield = TYPE_VFIELD (t); @@ -6437,7 +6439,12 @@ is_empty_class (type) if (! IS_AGGR_TYPE (type)) return 0; - return integer_zerop (CLASSTYPE_SIZE (type)); + /* In G++ 3.2, whether or not a class was empty was determined by + looking at its size. */ + if (abi_version_at_least (2)) + return CLASSTYPE_EMPTY_P (type); + else + return integer_zerop (CLASSTYPE_SIZE (type)); } /* Returns true if TYPE contains an empty class. */ diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index d3d064a0dad..c8344406162 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -1134,6 +1134,7 @@ struct lang_type_class GTY(()) unsigned anon_aggr : 1; unsigned non_zero_init : 1; + unsigned empty_p : 1; /* When adding a flag here, consider whether or not it ought to apply to a template instance if it applies to the template. If @@ -1142,7 +1143,7 @@ struct lang_type_class GTY(()) /* There are some bits left to fill out a 32-bit word. Keep track of this by updating the size of this bitfield whenever you add or remove a flag. */ - unsigned dummy : 6; + unsigned dummy : 5; int vsize; @@ -1447,6 +1448,10 @@ struct lang_type GTY(()) #define CLASSTYPE_NON_ZERO_INIT_P(NODE) \ (LANG_TYPE_CLASS_CHECK (NODE)->non_zero_init) +/* Nonzero if this class is "empty" in the sense of the C++ ABI. */ +#define CLASSTYPE_EMPTY_P(NODE) \ + (LANG_TYPE_CLASS_CHECK (NODE)->empty_p) + /* Nonzero if this class is "nearly empty", i.e., contains only a virtual function table pointer. */ #define CLASSTYPE_NEARLY_EMPTY_P(NODE) \ diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 5b77af5325e..20de7631d65 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2002-10-14 Mark Mitchell + + * g++.dg/abi/empty8.C: New test. + 2002-10-15 Nathan Sidwell * g++.dg/init/ctor1.C: New test. diff --git a/gcc/testsuite/g++.dg/abi/empty8.C b/gcc/testsuite/g++.dg/abi/empty8.C new file mode 100644 index 00000000000..a5287b15fa0 --- /dev/null +++ b/gcc/testsuite/g++.dg/abi/empty8.C @@ -0,0 +1,14 @@ +// { dg-do run } +// { dg-options "-fabi-version=0" } + +struct E1 {}; +struct E2 : public E1 {}; +struct S1 { int i; }; +struct S2 : public S1, E2 {}; + +S2 s2; + +int main () { + if ((char *)(E2*) &s2 != (char *)&s2) + return 1; +}