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:
parent
0b4c7d8042
commit
956d93056d
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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. */
|
||||
|
||||
|
@ -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)}
|
||||
|
@ -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
|
||||
|
17
gcc/testsuite/g++.dg/abi/empty5.C
Normal file
17
gcc/testsuite/g++.dg/abi/empty5.C
Normal 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;
|
||||
}
|
8
gcc/testsuite/g++.dg/abi/empty6.C
Normal file
8
gcc/testsuite/g++.dg/abi/empty6.C
Normal file
@ -0,0 +1,8 @@
|
||||
// { dg-options "-Wabi" }
|
||||
|
||||
struct A {};
|
||||
|
||||
struct B {
|
||||
A a; // { dg-warning "empty" }
|
||||
virtual void f () {}
|
||||
};
|
14
gcc/testsuite/g++.dg/abi/vbase12.C
Normal file
14
gcc/testsuite/g++.dg/abi/vbase12.C
Normal 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;
|
||||
}
|
Loading…
Reference in New Issue
Block a user