summaryrefslogtreecommitdiff
path: root/gcc/cp
diff options
context:
space:
mode:
authormmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>2002-09-25 19:07:35 +0000
committermmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>2002-09-25 19:07:35 +0000
commitd99a5b29ac7bb4222edbfb1581578ca4e5d37519 (patch)
treeb79b951416ea5c7c8a8f8c353bf2390e1d2645da /gcc/cp
parent6e4c9ed0673a95d639a469d6c3d004420020eea3 (diff)
downloadgcc-d99a5b29ac7bb4222edbfb1581578ca4e5d37519.tar.gz
* 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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@57508 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/cp')
-rw-r--r--gcc/cp/ChangeLog7
-rw-r--r--gcc/cp/class.c55
2 files changed, 60 insertions, 2 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index a25c6aa8b3f..c9f7523d1c7 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 316bc63f99d..7532c5d8e21 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. */