Commit 956d9305 by Mark Mitchell Committed by Mark Mitchell

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
parent 0b4c7d80
2002-09-25 Mark Mitchell <mark@codesourcery.com>
* doc/invoke.texi: Add more -Wabi examples.
2002-09-25 Richard Sandiford <rsandifo@redhat.com> 2002-09-25 Richard Sandiford <rsandifo@redhat.com>
* config/mips/mips.h (TARGET_MIPS4100): Add missing bracket. * config/mips/mips.h (TARGET_MIPS4100): Add missing bracket.
......
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> 2002-09-23 Mark Mitchell <mark@codesourcery.com>
* cp/class.c (layout_virtual_bases): Do not round the size of the * cp/class.c (layout_virtual_bases): Do not round the size of the
......
...@@ -210,6 +210,7 @@ static int splay_tree_compare_integer_csts PARAMS ((splay_tree_key k1, ...@@ -210,6 +210,7 @@ static int splay_tree_compare_integer_csts PARAMS ((splay_tree_key k1,
splay_tree_key k2)); splay_tree_key k2));
static void warn_about_ambiguous_direct_bases PARAMS ((tree)); static void warn_about_ambiguous_direct_bases PARAMS ((tree));
static bool type_requires_array_cookie 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 /* Macros for dfs walking during vtt construction. See
dfs_ctor_vtable_bases_queue_p, dfs_build_secondary_vptr_vtt_inits 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) ...@@ -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)) for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
if (TREE_CODE (field) == FIELD_DECL) 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), r = walk_subobject_offsets (TREE_TYPE (field),
f, f,
size_binop (PLUS_EXPR, size_binop (PLUS_EXPR,
offset, offset,
DECL_FIELD_OFFSET (field)), field_offset),
offsets, offsets,
max_offset, max_offset,
/*vbases_p=*/1); /*vbases_p=*/1);
...@@ -3720,10 +3729,17 @@ layout_empty_base (binfo, eoc, offsets, t) ...@@ -3720,10 +3729,17 @@ layout_empty_base (binfo, eoc, offsets, t)
tree alignment; tree alignment;
tree basetype = BINFO_TYPE (binfo); tree basetype = BINFO_TYPE (binfo);
bool atend = false; bool atend = false;
/* This routine should only be used for empty classes. */ /* This routine should only be used for empty classes. */
my_friendly_assert (is_empty_class (basetype), 20000321); my_friendly_assert (is_empty_class (basetype), 20000321);
alignment = ssize_int (CLASSTYPE_ALIGN_UNIT (basetype)); 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 /* This is an empty base class. We first try to put it at offset
zero. */ zero. */
...@@ -4915,6 +4931,17 @@ layout_class_type (t, empty_p, vfuns_p, virtuals_p) ...@@ -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", cp_warning_at ("offset of `%D' is not ABI-compliant and may change in a future version of GCC",
field); 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 /* If we needed additional padding after this field, add it
now. */ now. */
if (padding) if (padding)
...@@ -6371,6 +6398,30 @@ is_empty_class (type) ...@@ -6371,6 +6398,30 @@ is_empty_class (type)
return integer_zerop (CLASSTYPE_SIZE (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 /* Find the enclosing class of the given NODE. NODE can be a *_DECL or
a *_TYPE node. NODE can also be a local class. */ a *_TYPE node. NODE can also be a local class. */
......
...@@ -1546,6 +1546,25 @@ union U @{ int i : 4096; @}; ...@@ -1546,6 +1546,25 @@ union U @{ int i : 4096; @};
Assuming that an @code{int} does not have 4096 bits, G++ will make the 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}. 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 @end itemize
@item -Wctor-dtor-privacy @r{(C++ only)} @item -Wctor-dtor-privacy @r{(C++ only)}
......
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> 2002-09-25 Richard Henderson <rth@redhat.com>
* gcc.c-torture/execute/ieee/20010226-1.c: Early exit for * gcc.c-torture/execute/ieee/20010226-1.c: Early exit for
......
// { 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;
}
// { dg-options "-Wabi" }
struct A {};
struct B {
A a; // { dg-warning "empty" }
virtual void f () {}
};
// { 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;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment