diff options
author | Mark Mitchell <mark@codesourcery.com> | 2002-09-25 19:07:35 +0000 |
---|---|---|
committer | Mark Mitchell <mmitchel@gcc.gnu.org> | 2002-09-25 19:07:35 +0000 |
commit | 956d93056d6c4a121da5e5caf5e15e8f619845f1 (patch) | |
tree | b79b951416ea5c7c8a8f8c353bf2390e1d2645da | |
parent | 0b4c7d8042c4045b76681b4993752f79d11a31fd (diff) | |
download | gcc-956d93056d6c4a121da5e5caf5e15e8f619845f1.zip gcc-956d93056d6c4a121da5e5caf5e15e8f619845f1.tar.gz gcc-956d93056d6c4a121da5e5caf5e15e8f619845f1.tar.bz2 |
class.c (contains_empty_class_p): New method.
* cp/class.c (contains_empty_class_p): New method.
(walk_subobject_offsets): Correct computation of field offset.
(layout_empty_base): Correct placement of emtpy base classes.
(layout_class_type): Warn about ABI changes.
* doc/invoke.texi: Add more -Wabi examples.
* gcc/testsuite/g++.dg/abi/empty5.C: New test.
* gcc/testsuite/g++.dg/abi/empty6.C: New test.
* gcc/testsuite/g++.dg/abi/vbase12.C: New test.
From-SVN: r57508
-rw-r--r-- | gcc/ChangeLog | 4 | ||||
-rw-r--r-- | gcc/cp/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/cp/class.c | 55 | ||||
-rw-r--r-- | gcc/doc/invoke.texi | 19 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/abi/empty5.C | 17 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/abi/empty6.C | 8 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/abi/vbase12.C | 14 |
8 files changed, 128 insertions, 2 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 41e393b..4d85a2f 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,7 @@ +2002-09-25 Mark Mitchell <mark@codesourcery.com> + + * doc/invoke.texi: Add more -Wabi examples. + 2002-09-25 Richard Sandiford <rsandifo@redhat.com> * config/mips/mips.h (TARGET_MIPS4100): Add missing bracket. diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index a25c6aa..c9f7523 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,10 @@ +2002-09-25 Mark Mitchell <mark@codesourcery.com> + + * cp/class.c (contains_empty_class_p): New method. + (walk_subobject_offsets): Correct computation of field offset. + (layout_empty_base): Correct placement of emtpy base classes. + (layout_class_type): Warn about ABI changes. + 2002-09-23 Mark Mitchell <mark@codesourcery.com> * cp/class.c (layout_virtual_bases): Do not round the size of the diff --git a/gcc/cp/class.c b/gcc/cp/class.c index 316bc63..7532c5d 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -210,6 +210,7 @@ static int splay_tree_compare_integer_csts PARAMS ((splay_tree_key k1, splay_tree_key k2)); static void warn_about_ambiguous_direct_bases PARAMS ((tree)); static bool type_requires_array_cookie PARAMS ((tree)); +static bool contains_empty_class_p (tree); /* Macros for dfs walking during vtt construction. See dfs_ctor_vtable_bases_queue_p, dfs_build_secondary_vptr_vtt_inits @@ -3544,11 +3545,19 @@ walk_subobject_offsets (type, f, offset, offsets, max_offset, vbases_p) for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field)) if (TREE_CODE (field) == FIELD_DECL) { + tree field_offset; + + if (abi_version_at_least (2)) + field_offset = byte_position (field); + else + /* In G++ 3.2, DECL_FIELD_OFFSET was used. */ + field_offset = DECL_FIELD_OFFSET (field); + r = walk_subobject_offsets (TREE_TYPE (field), f, size_binop (PLUS_EXPR, offset, - DECL_FIELD_OFFSET (field)), + field_offset), offsets, max_offset, /*vbases_p=*/1); @@ -3720,10 +3729,17 @@ layout_empty_base (binfo, eoc, offsets, t) 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); alignment = ssize_int (CLASSTYPE_ALIGN_UNIT (basetype)); + + if (abi_version_at_least (2)) + BINFO_OFFSET (binfo) = size_zero_node; + if (warn_abi && !integer_zerop (BINFO_OFFSET (binfo))) + warning ("offset of empty base `%T' may not be ABI-compliant and may" + "change in a future version of GCC", + BINFO_TYPE (binfo)); /* This is an empty base class. We first try to put it at offset zero. */ @@ -4915,6 +4931,17 @@ layout_class_type (t, empty_p, vfuns_p, virtuals_p) cp_warning_at ("offset of `%D' is not ABI-compliant and may change in a future version of GCC", field); + /* G++ used to use DECL_FIELD_OFFSET as if it were the byte + offset of the field. */ + if (warn_abi + && !tree_int_cst_equal (DECL_FIELD_OFFSET (field), + byte_position (field)) + && contains_empty_class_p (TREE_TYPE (field))) + cp_warning_at ("`%D' contains empty classes which may cause base " + "classes to be placed at different locations in a " + "future version of GCC", + field); + /* If we needed additional padding after this field, add it now. */ if (padding) @@ -6371,6 +6398,30 @@ is_empty_class (type) return integer_zerop (CLASSTYPE_SIZE (type)); } +/* Returns true if TYPE contains an empty class. */ + +static bool +contains_empty_class_p (tree type) +{ + if (is_empty_class (type)) + return true; + if (CLASS_TYPE_P (type)) + { + tree field; + int i; + + for (i = 0; i < CLASSTYPE_N_BASECLASSES (type); ++i) + if (contains_empty_class_p (TYPE_BINFO_BASETYPE (type, i))) + return true; + for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field)) + if (contains_empty_class_p (TREE_TYPE (field))) + return true; + } + else if (TREE_CODE (type) == ARRAY_TYPE) + return contains_empty_class_p (TREE_TYPE (type)); + return false; +} + /* Find the enclosing class of the given NODE. NODE can be a *_DECL or a *_TYPE node. NODE can also be a local class. */ diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 386c174..9a8fa2a 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -1546,6 +1546,25 @@ union U @{ int i : 4096; @}; Assuming that an @code{int} does not have 4096 bits, G++ will make the union too small by the number of bits in an @code{int}. +@item +Empty classes can be placed at incorrect offsets. For example: + +@smallexample +struct A @{@}; + +struct B @{ + A a; + virtual void f (); +@}; + +struct C : public B, public A @{@}; +@end smallexample + +@noindent +G++ will place the @code{A} base class of @code{C} at a non-zero offset; +it should be placed at offset zero. G++ mistakenly believes that the +@code{A} data member of @code{B} is already at offset zero. + @end itemize @item -Wctor-dtor-privacy @r{(C++ only)} diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index b4021bc..c7b67c6 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2002-09-25 Mark Mitchell <mark@codesourcery.com> + + * gcc/testsuite/g++.dg/abi/empty5.C: New test. + * gcc/testsuite/g++.dg/abi/empty6.C: New test. + * gcc/testsuite/g++.dg/abi/vbase12.C: New test. + 2002-09-25 Richard Henderson <rth@redhat.com> * gcc.c-torture/execute/ieee/20010226-1.c: Early exit for diff --git a/gcc/testsuite/g++.dg/abi/empty5.C b/gcc/testsuite/g++.dg/abi/empty5.C new file mode 100644 index 0000000..c371772 --- /dev/null +++ b/gcc/testsuite/g++.dg/abi/empty5.C @@ -0,0 +1,17 @@ +// { dg-options "-fabi-version=0" } + +struct A {}; + +struct B { + A a; + virtual void f () {} +}; + +struct C : public B, public A {}; + +C c; + +int main () { + if ((void*) (A*) &c != &c) + return 1; +} diff --git a/gcc/testsuite/g++.dg/abi/empty6.C b/gcc/testsuite/g++.dg/abi/empty6.C new file mode 100644 index 0000000..aa27273 --- /dev/null +++ b/gcc/testsuite/g++.dg/abi/empty6.C @@ -0,0 +1,8 @@ +// { dg-options "-Wabi" } + +struct A {}; + +struct B { + A a; // { dg-warning "empty" } + virtual void f () {} +}; diff --git a/gcc/testsuite/g++.dg/abi/vbase12.C b/gcc/testsuite/g++.dg/abi/vbase12.C new file mode 100644 index 0000000..98b9054 --- /dev/null +++ b/gcc/testsuite/g++.dg/abi/vbase12.C @@ -0,0 +1,14 @@ +// { dg-do run } +// { dg-options "-fabi-version=0" } + +struct A {}; +struct B { A a; virtual void f () {} }; +struct C : public B, virtual public A {}; +struct D : public C, virtual public A {}; + +D d; + +int main () { + if (((char*)(A*)&d - (char*)&d) != 0) + return 1; +} |