aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Mitchell <mark@codesourcery.com>2002-09-25 19:07:35 +0000
committerMark Mitchell <mmitchel@gcc.gnu.org>2002-09-25 19:07:35 +0000
commit956d93056d6c4a121da5e5caf5e15e8f619845f1 (patch)
treeb79b951416ea5c7c8a8f8c353bf2390e1d2645da
parent0b4c7d8042c4045b76681b4993752f79d11a31fd (diff)
downloadgcc-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/ChangeLog4
-rw-r--r--gcc/cp/ChangeLog7
-rw-r--r--gcc/cp/class.c55
-rw-r--r--gcc/doc/invoke.texi19
-rw-r--r--gcc/testsuite/ChangeLog6
-rw-r--r--gcc/testsuite/g++.dg/abi/empty5.C17
-rw-r--r--gcc/testsuite/g++.dg/abi/empty6.C8
-rw-r--r--gcc/testsuite/g++.dg/abi/vbase12.C14
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;
+}