diff options
author | Mark Mitchell <mark@codesourcery.com> | 2002-08-27 22:14:51 +0000 |
---|---|---|
committer | Mark Mitchell <mmitchel@gcc.gnu.org> | 2002-08-27 22:14:51 +0000 |
commit | eca7f13c6953706b97f6158dcef99f0566f1fbb5 (patch) | |
tree | ee767505882b4cd0b13a99e8d37e215ba2dcf0f5 /gcc/cp/class.c | |
parent | c350f8c1c479aabb1bd0a58f4072381d77daca77 (diff) | |
download | gcc-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.c | 38 |
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 |