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
This commit is contained in:
Mark Mitchell 2002-09-25 19:07:35 +00:00 committed by Mark Mitchell
parent 0b4c7d8042
commit 956d93056d
8 changed files with 128 additions and 2 deletions

View File

@ -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.

View File

@ -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

View File

@ -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. */

View File

@ -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)}

View File

@ -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

View File

@ -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;
}

View File

@ -0,0 +1,8 @@
// { dg-options "-Wabi" }
struct A {};
struct B {
A a; // { dg-warning "empty" }
virtual void f () {}
};

View File

@ -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;
}