aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp/class.c
diff options
context:
space:
mode:
authorMark Mitchell <mark@codesourcery.com>2002-08-27 22:14:51 +0000
committerMark Mitchell <mmitchel@gcc.gnu.org>2002-08-27 22:14:51 +0000
commiteca7f13c6953706b97f6158dcef99f0566f1fbb5 (patch)
treeee767505882b4cd0b13a99e8d37e215ba2dcf0f5 /gcc/cp/class.c
parentc350f8c1c479aabb1bd0a58f4072381d77daca77 (diff)
downloadgcc-eca7f13c6953706b97f6158dcef99f0566f1fbb5.zip
gcc-eca7f13c6953706b97f6158dcef99f0566f1fbb5.tar.gz
gcc-eca7f13c6953706b97f6158dcef99f0566f1fbb5.tar.bz2
c-common.c (warn_abi): New variable.
* c-common.c (warn_abi): New variable. * c-common.h (warn_abi): Likewise. * c-opts.c (COMMAND_LINE_OPTIONS): Add -Wabi. (c_common_decode_option): Handle it. * doc/invoke.texi:P Document -Wabi. * class.c (layout_virtual_bases): Warn about bugs in G++ that result in incorrect object layouts. (layout_class_type): Likewise. * testsuite/g++.dg/abi/bitfield5.C: New test. * testsuite/g++.dg/abi/vbase10.C: Likewise. From-SVN: r56618
Diffstat (limited to 'gcc/cp/class.c')
-rw-r--r--gcc/cp/class.c38
1 files changed, 37 insertions, 1 deletions
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index db8cfa7..7cdfdaf 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -4562,6 +4562,7 @@ layout_virtual_bases (t, offsets)
{
tree vbases, dsize;
unsigned HOST_WIDE_INT eoc;
+ bool first_vbase = true;
if (CLASSTYPE_N_BASECLASSES (t) == 0)
return;
@@ -4589,6 +4590,7 @@ layout_virtual_bases (t, offsets)
if (!TREE_VIA_VIRTUAL (vbases))
continue;
+
vbase = binfo_for_vbase (BINFO_TYPE (vbases), t);
if (!BINFO_PRIMARY_P (vbase))
@@ -4606,7 +4608,6 @@ layout_virtual_bases (t, offsets)
/* Add padding so that we can put the virtual base class at an
appropriately aligned offset. */
dsize = round_up (dsize, desired_align);
-
usize = size_binop (CEIL_DIV_EXPR, dsize, bitsize_unit_node);
/* We try to squish empty virtual bases in just like
@@ -4634,11 +4635,30 @@ layout_virtual_bases (t, offsets)
CLASSTYPE_SIZE (basetype)));
}
+ /* If the first virtual base might have been placed at a
+ lower address, had we started from CLASSTYPE_SIZE, rather
+ than TYPE_SIZE, issue a warning. There can be both false
+ positives and false negatives from this warning in rare
+ cases; to deal with all the possibilities would probably
+ require performing both layout algorithms and comparing
+ the results which is not particularly tractable. */
+ if (warn_abi
+ && first_vbase
+ && tree_int_cst_lt (size_binop (CEIL_DIV_EXPR,
+ round_up (CLASSTYPE_SIZE (t),
+ desired_align),
+ bitsize_unit_node),
+ BINFO_OFFSET (vbase)))
+ warning ("offset of virtual base `%T' is not ABI-compliant and may change in a future version of GCC",
+ basetype);
+
/* Keep track of the offsets assigned to this virtual base. */
record_subobject_offsets (BINFO_TYPE (vbase),
BINFO_OFFSET (vbase),
offsets,
/*vbases_p=*/0);
+
+ first_vbase = false;
}
}
@@ -4776,6 +4796,8 @@ layout_class_type (t, empty_p, vfuns_p, virtuals_p)
/* Maps offsets (represented as INTEGER_CSTs) to a TREE_LIST of
types that appear at that offset. */
splay_tree empty_base_offsets;
+ /* True if the last field layed out was a bit-field. */
+ bool last_field_was_bitfield = false;
/* Keep track of the first non-static data member. */
non_static_data_members = TYPE_FIELDS (t);
@@ -4865,6 +4887,18 @@ layout_class_type (t, empty_p, vfuns_p, virtuals_p)
layout_nonempty_base_or_field (rli, field, NULL_TREE,
empty_base_offsets, t);
+ /* If a bit-field does not immediately follow another bit-field,
+ and yet it starts in the middle of a byte, we have failed to
+ comply with the ABI. */
+ if (warn_abi
+ && DECL_C_BIT_FIELD (field)
+ && !last_field_was_bitfield
+ && !integer_zerop (size_binop (TRUNC_MOD_EXPR,
+ DECL_FIELD_BIT_OFFSET (field),
+ bitsize_unit_node)))
+ cp_warning_at ("offset of `%D' is not ABI-compliant and may change in a future version of GCC",
+ field);
+
/* If we needed additional padding after this field, add it
now. */
if (padding)
@@ -4882,6 +4916,8 @@ layout_class_type (t, empty_p, vfuns_p, virtuals_p)
NULL_TREE,
empty_base_offsets, t);
}
+
+ last_field_was_bitfield = DECL_C_BIT_FIELD (field);
}
/* It might be the case that we grew the class to allocate a