2002-10-21 Mark Mitchell * class.c (empty_base_at_nonzero_offset_p): New function. (layout_nonempty_base_or_field): Do not check for conflicts when laying out a virtual base using the GCC 3.2 ABI. (build_base_field): Correct checking for presence of empty classes at non-zero offsets when clearing CLASSTYPE_NEARLY_EMPTY_P. 2002-10-21 Mark Mitchell * g++.dg/abi/vbase13.C: New test. * g++.dg/abi/vbase14.C: Likewise. Index: cp/class.c =================================================================== RCS file: /cvs/gcc/gcc/gcc/cp/class.c,v retrieving revision 1.482 diff -c -p -r1.482 class.c *** cp/class.c 21 Oct 2002 21:47:44 -0000 1.482 --- cp/class.c 22 Oct 2002 05:01:02 -0000 *************** static bool type_requires_array_cookie P *** 209,214 **** --- 209,215 ---- static bool contains_empty_class_p (tree); static tree dfs_base_derived_from (tree, void *); static bool base_derived_from (tree, tree); + static int empty_base_at_nonzero_offset_p (tree, tree, splay_tree); /* Macros for dfs walking during vtt construction. See dfs_ctor_vtable_bases_queue_p, dfs_build_secondary_vptr_vtt_inits *************** layout_nonempty_base_or_field (record_la *** 3674,3679 **** --- 3675,3684 ---- empty class, have nonzero size, any overlap can happen only with a direct or indirect base-class -- it can't happen with a data member. */ + /* G++ 3.2 did not check for overlaps when placing a non-empty + virtual base. */ + if (!abi_version_at_least (2) && binfo && TREE_VIA_VIRTUAL (binfo)) + break; if (layout_conflict_p (type, offset, offsets, field_p)) { /* Strip off the size allocated to this field. That puts us *************** layout_nonempty_base_or_field (record_la *** 3708,3713 **** --- 3713,3728 ---- t); } + /* Returns true if TYPE is empty and OFFSET is non-zero. */ + + static int + empty_base_at_nonzero_offset_p (tree type, + tree offset, + splay_tree offsets ATTRIBUTE_UNUSED) + { + return is_empty_class (type) && !integer_zerop (offset); + } + /* 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 *************** build_base_field (record_layout_info rli *** 3816,3829 **** else { tree eoc; /* On some platforms (ARM), even empty classes will not be byte-aligned. */ eoc = round_up (rli_size_unit_so_far (rli), CLASSTYPE_ALIGN_UNIT (basetype)); ! if (layout_empty_base (binfo, eoc, offsets, t)) ! CLASSTYPE_NEARLY_EMPTY_P (t) = 0; ! /* We do not create a FIELD_DECL for empty base classes because it might overlap some other field. We want to be able to create CONSTRUCTORs for the class by iterating over the --- 3831,3867 ---- else { tree eoc; + bool atend; /* On some platforms (ARM), even empty classes will not be byte-aligned. */ eoc = round_up (rli_size_unit_so_far (rli), CLASSTYPE_ALIGN_UNIT (basetype)); ! atend = layout_empty_base (binfo, eoc, offsets, t); ! /* A nearly-empty class "has no proper base class that is empty, ! not morally virtual, and at an offset other than zero." */ ! if (!TREE_VIA_VIRTUAL (binfo) && CLASSTYPE_NEARLY_EMPTY_P (t)) ! { ! if (atend) ! CLASSTYPE_NEARLY_EMPTY_P (t) = 0; ! /* The check above (used in G++ 3.2) is insufficient because ! an empty class placed at offset zero might itself have an ! empty base at a non-zero offset. */ ! else if (walk_subobject_offsets (basetype, ! empty_base_at_nonzero_offset_p, ! size_zero_node, ! /*offsets=*/NULL, ! /*max_offset=*/NULL_TREE, ! /*vbases_p=*/true)) ! { ! if (abi_version_at_least (2)) ! CLASSTYPE_NEARLY_EMPTY_P (t) = 0; ! else if (warn_abi) ! warning ("class `%T' will be considered nearly empty in a " ! "future version of GCC", t); ! } ! } ! /* We do not create a FIELD_DECL for empty base classes because it might overlap some other field. We want to be able to create CONSTRUCTORs for the class by iterating over the Index: testsuite/g++.dg/abi/vbase13.C =================================================================== RCS file: testsuite/g++.dg/abi/vbase13.C diff -N testsuite/g++.dg/abi/vbase13.C *** /dev/null 1 Jan 1970 00:00:00 -0000 --- testsuite/g++.dg/abi/vbase13.C 22 Oct 2002 05:01:02 -0000 *************** *** 0 **** --- 1,17 ---- + // { dg-do run } + // { dg-options "-fabi-version=0 -w" } + + struct E1 {}; + struct E2 : public E1 {}; + struct E : public E1, public E2 {}; + struct N : public E { virtual void f () {} }; + + struct X : virtual public N { + }; + + int main () { + X x; + /* N should not be the primary base of X; it is not nearly empty. */ + if ((void*)&x == (void*)(N*)&x) + return 1; + } Index: testsuite/g++.dg/abi/vbase14.C =================================================================== RCS file: testsuite/g++.dg/abi/vbase14.C diff -N testsuite/g++.dg/abi/vbase14.C *** /dev/null 1 Jan 1970 00:00:00 -0000 --- testsuite/g++.dg/abi/vbase14.C 22 Oct 2002 05:01:02 -0000 *************** *** 0 **** --- 1,6 ---- + // { dg-options "-Wabi" } + + struct E1 {}; + struct E2 : public E1 {}; // { dg-warning "layout" } + struct E : public E1, public E2 {}; // { dg-warning "layout|ambiguity" } + struct N : public E { virtual void f () {} }; // { dg-warning "nearly" }