From 06d9f09f53cd3d0c1164986a9c5ff3a37e59dec4 Mon Sep 17 00:00:00 2001 From: Nathan Sidwell Date: Fri, 20 Apr 2001 15:29:09 +0000 Subject: [PATCH] class.c (dfs_unshared_virtual_bases): Add ATTRIBUTE_UNUSED. cp: * class.c (dfs_unshared_virtual_bases): Add ATTRIBUTE_UNUSED. (layout_empty_base): Return at end flag. (build_base_field): Likewise. (build_base_fields): Likewise. (layout_virtual_bases): Don't add 1 to eoc value. (end_of_class): Use full size for empty bases. (layout_class_type): Clear CLASSNEARLY_EMPTY_P if we appended empty bases. Don't add 1 to eoc value. Only add trailing padding if we're an empty class with no empty bases. (dump_class_hierarchy): Dump size and alignment. testsuite: * g++.old-deja/g++.abi/empty2.C: New test. * g++.old-deja/g++.abi/empty3.C: New test. From-SVN: r41460 --- gcc/cp/ChangeLog | 13 ++ gcc/cp/class.c | 65 +++++++--- gcc/testsuite/ChangeLog | 5 + gcc/testsuite/g++.old-deja/g++.abi/empty2.C | 136 ++++++++++++++++++++ gcc/testsuite/g++.old-deja/g++.abi/empty3.C | 24 ++++ 5 files changed, 222 insertions(+), 21 deletions(-) create mode 100644 gcc/testsuite/g++.old-deja/g++.abi/empty2.C create mode 100644 gcc/testsuite/g++.old-deja/g++.abi/empty3.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 16a03dcf18c..eaee2bb24a3 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,16 @@ +2001-04-20 Nathan Sidwell + + * class.c (dfs_unshared_virtual_bases): Add ATTRIBUTE_UNUSED. + (layout_empty_base): Return at end flag. + (build_base_field): Likewise. + (build_base_fields): Likewise. + (layout_virtual_bases): Don't add 1 to eoc value. + (end_of_class): Use full size for empty bases. + (layout_class_type): Clear CLASSNEARLY_EMPTY_P if we appended + empty bases. Don't add 1 to eoc value. Only add trailing padding + if we're an empty class with no empty bases. + (dump_class_hierarchy): Dump size and alignment. + 2001-04-20 Jakub Jelinek * call.c (maybe_handle_ref_bind): Copy ICS_USER_FLAG and diff --git a/gcc/cp/class.c b/gcc/cp/class.c index 290dc214da4..9c713c0c047 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -144,10 +144,10 @@ 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 void build_base_field PARAMS ((record_layout_info, tree, int *, +static bool build_base_field PARAMS ((record_layout_info, tree, int *, + splay_tree)); +static bool build_base_fields PARAMS ((record_layout_info, int *, splay_tree)); -static void build_base_fields PARAMS ((record_layout_info, int *, - splay_tree)); 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 *)); @@ -180,7 +180,7 @@ static void layout_nonempty_base_or_field PARAMS ((record_layout_info, tree, tree, splay_tree)); static unsigned HOST_WIDE_INT end_of_class PARAMS ((tree, int)); -static void layout_empty_base PARAMS ((tree, tree, splay_tree)); +static bool layout_empty_base PARAMS ((tree, tree, splay_tree)); static void accumulate_vtbl_inits PARAMS ((tree, tree, tree, tree, tree)); static tree dfs_accumulate_vtbl_inits PARAMS ((tree, tree, tree, tree, tree)); @@ -1825,7 +1825,7 @@ mark_primary_virtual_base (binfo, base_binfo, type) static tree dfs_unshared_virtual_bases (binfo, data) tree binfo; - void *data; + void *data ATTRIBUTE_UNUSED; { if (TREE_VIA_VIRTUAL (binfo) && !BINFO_MARKED (binfo) && CLASSTYPE_HAS_PRIMARY_BASE_P (BINFO_TYPE (binfo))) @@ -4015,9 +4015,10 @@ layout_nonempty_base_or_field (rli, decl, binfo, offsets) /* Layout the empty base BINFO. EOC indicates the byte currently just past the end of the class, and should be correctly aligned for a class of the type indicated by BINFO; OFFSETS gives the offsets of - the empty bases allocated so far. */ + the empty bases allocated so far. Return non-zero iff we added it + at the end. */ -static void +static bool layout_empty_base (binfo, eoc, offsets) tree binfo; tree eoc; @@ -4025,6 +4026,7 @@ layout_empty_base (binfo, eoc, offsets) { tree alignment; tree basetype = BINFO_TYPE (binfo); + bool atend = false; /* This routine should only be used for empty classes. */ my_friendly_assert (is_empty_class (basetype), 20000321); @@ -4039,6 +4041,7 @@ layout_empty_base (binfo, eoc, offsets) { /* That didn't work. Now, we move forward from the next available spot in the class. */ + atend = true; propagate_binfo_offsets (binfo, convert (ssizetype, eoc)); while (1) { @@ -4053,14 +4056,16 @@ layout_empty_base (binfo, eoc, offsets) propagate_binfo_offsets (binfo, alignment); } } + return atend; } /* 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. OFFSETS gives the location of empty base subobjects. */ + class. OFFSETS gives the location of empty base subobjects. Return + non-zero if the new object cannot be nearly-empty. */ -static void +static bool build_base_field (rli, binfo, empty_p, offsets) record_layout_info rli; tree binfo; @@ -4069,11 +4074,12 @@ build_base_field (rli, binfo, empty_p, offsets) { tree basetype = BINFO_TYPE (binfo); tree decl; + bool atend = false; if (!COMPLETE_TYPE_P (basetype)) /* This error is now reported in xref_tag, thus giving better location information. */ - return; + return atend; decl = build_decl (FIELD_DECL, NULL_TREE, basetype); DECL_ARTIFICIAL (decl) = 1; @@ -4102,7 +4108,7 @@ build_base_field (rli, binfo, empty_p, offsets) byte-aligned. */ eoc = tree_low_cst (rli_size_unit_so_far (rli), 0); eoc = CEIL (eoc, DECL_ALIGN_UNIT (decl)) * DECL_ALIGN_UNIT (decl); - layout_empty_base (binfo, size_int (eoc), offsets); + atend |= layout_empty_base (binfo, size_int (eoc), offsets); } /* Record the offsets of BINFO and its base subobjects. */ @@ -4110,12 +4116,14 @@ build_base_field (rli, binfo, empty_p, offsets) BINFO_OFFSET (binfo), offsets, /*vbases_p=*/0); + return atend; } /* Layout all of the non-virtual base classes. Record empty - subobjects in OFFSETS. */ + subobjects in OFFSETS. Return non-zero if the type cannot be nearly + empty. */ -static void +static bool build_base_fields (rli, empty_p, offsets) record_layout_info rli; int *empty_p; @@ -4126,6 +4134,7 @@ build_base_fields (rli, empty_p, offsets) tree rec = rli->t; int n_baseclasses = CLASSTYPE_N_BASECLASSES (rec); int i; + bool atend = 0; /* Under the new ABI, the primary base class is always allocated first. */ @@ -4152,8 +4161,9 @@ build_base_fields (rli, empty_p, offsets) && !BINFO_PRIMARY_P (base_binfo)) continue; - build_base_field (rli, base_binfo, empty_p, offsets); + atend |= build_base_field (rli, base_binfo, empty_p, offsets); } + return atend; } /* Go through the TYPE_METHODS of T issuing any appropriate @@ -4828,7 +4838,7 @@ layout_virtual_bases (t, offsets) multiple such bases at the same location. */ eoc = end_of_class (t, /*include_virtuals_p=*/1); if (eoc * BITS_PER_UNIT > dsize) - dsize = (eoc + 1) * BITS_PER_UNIT; + dsize = eoc * BITS_PER_UNIT; /* Now, make sure that the total size of the type is a multiple of its alignment. */ @@ -4867,6 +4877,7 @@ end_of_class (t, include_virtuals_p) { tree base_binfo; tree offset; + tree size; unsigned HOST_WIDE_INT end_of_base; base_binfo = BINFO_BASETYPE (TYPE_BINFO (t), i); @@ -4876,9 +4887,16 @@ end_of_class (t, include_virtuals_p) && !BINFO_PRIMARY_P (base_binfo)) continue; + if (is_empty_class (BINFO_TYPE (base_binfo))) + /* An empty class has zero CLASSTYPE_SIZE_UNIT, but we need to + allocate some space for it. It cannot have virtual bases, + so TYPE_SIZE_UNIT is fine. */ + size = TYPE_SIZE_UNIT (BINFO_TYPE (base_binfo)); + else + size = CLASSTYPE_SIZE_UNIT (BINFO_TYPE (base_binfo)); offset = size_binop (PLUS_EXPR, BINFO_OFFSET (base_binfo), - CLASSTYPE_SIZE_UNIT (BINFO_TYPE (base_binfo))); + size); end_of_base = tree_low_cst (offset, /*pos=*/1); if (end_of_base > result) result = end_of_base; @@ -4970,7 +4988,9 @@ layout_class_type (t, empty_p, vfuns_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); + if (build_base_fields (rli, empty_p, empty_base_offsets)) + CLASSTYPE_NEARLY_EMPTY_P (t) = 0; + /* Add pointers to all of our virtual base-classes. */ TYPE_FIELDS (t) = chainon (build_vbase_pointer_fields (rli, empty_p), TYPE_FIELDS (t)); @@ -5060,7 +5080,7 @@ layout_class_type (t, empty_p, vfuns_p, if (TREE_CODE (rli_size_unit_so_far (rli)) == INTEGER_CST && compare_tree_int (rli_size_unit_so_far (rli), eoc) < 0) { - rli->offset = size_binop (MAX_EXPR, rli->offset, size_int (eoc + 1)); + rli->offset = size_binop (MAX_EXPR, rli->offset, size_int (eoc)); rli->bitpos = bitsize_zero_node; } @@ -5069,7 +5089,7 @@ layout_class_type (t, empty_p, vfuns_p, 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) + if (!eoc && *empty_p) { tree padding; @@ -6758,8 +6778,11 @@ dump_class_hierarchy (name, t) error ("could not open dump file `%s'", name); return; } - fprintf (stream, "%s\n", - type_as_string (t, TFF_PLAIN_IDENTIFIER)); + fprintf (stream, "%s size=", type_as_string (t, TFF_PLAIN_IDENTIFIER)); + fprintf (stream, HOST_WIDE_INT_PRINT_DEC, + tree_low_cst (TYPE_SIZE (t), 0) / BITS_PER_UNIT); + fprintf (stream, " align=%lu\n", + (unsigned long)(TYPE_ALIGN (t) / BITS_PER_UNIT)); dump_class_hierarchy_r (stream, t, TYPE_BINFO (t), 0); fprintf (stream, "\n"); if (name) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 8ba71f84b8e..157bbed491c 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2001-04-20 Nathan Sidwell + + * g++.old-deja/g++.abi/empty2.C: New test. + * g++.old-deja/g++.abi/empty3.C: New test. + 2001-04-20 Jakub Jelinek * g++.old-deja/g++.other/comdat2.C: New test. diff --git a/gcc/testsuite/g++.old-deja/g++.abi/empty2.C b/gcc/testsuite/g++.old-deja/g++.abi/empty2.C new file mode 100644 index 00000000000..411651701e3 --- /dev/null +++ b/gcc/testsuite/g++.old-deja/g++.abi/empty2.C @@ -0,0 +1,136 @@ +// Build don't link: + +// Copyright (C) 2001 Free Software Foundation, Inc. +// Contributed by Nathan Sidwell 12 Apr 2001 + +// Check we deal with trailing empty base classes properly + +struct A {}; +struct B1 : A {}; +struct B2 : A {}; +struct B3 : A {}; +struct B4 : A {}; +struct B5 : A {}; +struct B6 : A {}; +struct B7 : A {}; +struct B8 : A {}; + +struct C1 : B1 +{ + virtual void Foo () {}; +}; +struct C2 : B1, B2 +{ + virtual void Foo () {}; +}; +struct C3 : B1, B2, B3 +{ + virtual void Foo () {}; +}; +struct C4 : B1, B2, B3, B4 +{ + virtual void Foo () {}; +}; +struct C5 : B1, B2, B3, B4, B5 +{ + virtual void Foo () {}; +}; +struct C6 : B1, B2, B3, B4, B5, B6 +{ + virtual void Foo () {}; +}; +struct C7 : B1, B2, B3, B4, B5, B6, B7 +{ + virtual void Foo () {}; +}; +struct C8 : B1, B2, B3, B4, B5, B6, B7, B8 +{ + virtual void Foo () {}; +}; + +struct D1 : virtual C1 {}; +struct D2 : virtual C2 {}; +struct D3 : virtual C3 {}; +struct D4 : virtual C4 {}; +struct D5 : virtual C5 {}; +struct D6 : virtual C6 {}; +struct D7 : virtual C7 {}; +struct D8 : virtual C8 {}; + +unsigned const nearly_empty_size = sizeof (D1); + +template int Check (Dn const &ref) +{ + if ((sizeof (Cn) <= nearly_empty_size) + != (static_cast (&ref) + == static_cast (&ref))) + return 1; + return 0; +} + +template int Check () +{ + Cn c[2]; + + if (static_cast (static_cast (&c[1])) + == static_cast (static_cast (&c[0]))) + return 1; + return 0; +} + + +int main () +{ +#if defined (__GXX_ABI_VERSION) && __GXX_ABI_VERSION >= 100 + if (Check ()) + return 1; + if (Check ()) + return 2; + if (Check ()) + return 3; + if (Check ()) + return 4; + if (Check ()) + return 5; + if (Check ()) + return 6; + if (Check ()) + return 7; + if (Check ()) + return 8; + + if (Check (D1 ())) + return 11; + if (Check (D2 ())) + return 12; + if (Check (D3 ())) + return 13; + if (Check (D4 ())) + return 14; + if (Check (D5 ())) + return 15; + if (Check (D6 ())) + return 16; + if (Check (D7 ())) + return 17; + if (Check (D8 ())) + return 18; + + if (sizeof (C2) == nearly_empty_size) + return 22; + if (sizeof (C3) == nearly_empty_size) + return 23; + if (sizeof (C4) == nearly_empty_size) + return 24; + if (sizeof (C5) == nearly_empty_size) + return 25; + if (sizeof (C6) == nearly_empty_size) + return 26; + if (sizeof (C7) == nearly_empty_size) + return 27; + if (sizeof (C8) == nearly_empty_size) + return 28; +#endif + return 0; + +} diff --git a/gcc/testsuite/g++.old-deja/g++.abi/empty3.C b/gcc/testsuite/g++.old-deja/g++.abi/empty3.C new file mode 100644 index 00000000000..93e9d9ffdf9 --- /dev/null +++ b/gcc/testsuite/g++.old-deja/g++.abi/empty3.C @@ -0,0 +1,24 @@ +// Build don't link: + +// Copyright (C) 2001 Free Software Foundation, Inc. +// Contributed by Nathan Sidwell 12 Apr 2001 + +// Check we deal with aligning virtual bases after a trailing empty +// base class properly + +struct A {}; +struct B1 : A {}; +struct B2 : A {}; +struct B3 : A {}; + +struct C : B1, B2, virtual B3 {}; + +int main () +{ +#if defined (__GXX_ABI_VERSION) && __GXX_ABI_VERSION >= 100 + C c; + if (((char *)static_cast (&c) - (char *)&c) % __alignof__ (C)) + return 1; +#endif + return 0; +} -- 2.30.2