This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
-fabi-version=0 layout tweak
- From: Mark Mitchell <mark at codesourcery dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Fri, 29 Nov 2002 13:12:25 -0800
- Subject: -fabi-version=0 layout tweak
- Reply-to: mark at codesourcery dot com
I'm pulling my hair out trying to make sure this empty base layout
code is correct, and this version gives me more confidence. I'm
afraid the last version could cause us to get burned due to the fact
that BINFO_OFFSET contains an incorrect value for a while. (No, that
is not a good thing, but not something we can fix too easily.)
Applied to mainline, tested on i686-pc-linux-gnu.
--
Mark Mitchell mark@codesourcery.com
CodeSourcery, LLC http://www.codesourcery.com
2002-11-29 Mark Mitchell <mark@codesourcery.com>
* class.c (walk_subobject_offsets): Recur on binfos as well as on
types.
(layout_nonempty_base_or_field): Pass it a binfo when processing a
base class.
(layout_empty_base): Likewise.
(build_base_field): Likewise.
Index: class.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/class.c,v
retrieving revision 1.497
diff -c -p -r1.497 class.c
*** class.c 27 Nov 2002 20:44:16 -0000 1.497
--- class.c 29 Nov 2002 21:13:03 -0000
*************** walk_subobject_offsets (type, f, offset,
*** 3410,3421 ****
--- 3410,3429 ----
int vbases_p;
{
int r = 0;
+ tree type_binfo = NULL_TREE;
/* If this OFFSET is bigger than the MAX_OFFSET, then we should
stop. */
if (max_offset && INT_CST_LT (max_offset, offset))
return 0;
+ if (!TYPE_P (type))
+ {
+ if (abi_version_at_least (2))
+ type_binfo = type;
+ type = BINFO_TYPE (type);
+ }
+
if (CLASS_TYPE_P (type))
{
tree field;
*************** walk_subobject_offsets (type, f, offset,
*** 3432,3440 ****
return r;
/* Iterate through the direct base classes of TYPE. */
! for (i = 0; i < CLASSTYPE_N_BASECLASSES (type); ++i)
{
! binfo = BINFO_BASETYPE (TYPE_BINFO (type), i);
if (abi_version_at_least (2)
&& TREE_VIA_VIRTUAL (binfo))
--- 3440,3452 ----
return r;
/* Iterate through the direct base classes of TYPE. */
! if (!type_binfo)
! type_binfo = TYPE_BINFO (type);
! for (i = 0; i < BINFO_N_BASETYPES (type_binfo); ++i)
{
! tree binfo_offset;
!
! binfo = BINFO_BASETYPE (type_binfo, i);
if (abi_version_at_least (2)
&& TREE_VIA_VIRTUAL (binfo))
*************** walk_subobject_offsets (type, f, offset,
*** 3445,3455 ****
&& !BINFO_PRIMARY_P (binfo))
continue;
! r = walk_subobject_offsets (BINFO_TYPE (binfo),
f,
! size_binop (PLUS_EXPR,
! offset,
! BINFO_OFFSET (binfo)),
offsets,
max_offset,
(abi_version_at_least (2)
--- 3457,3481 ----
&& !BINFO_PRIMARY_P (binfo))
continue;
! if (!abi_version_at_least (2))
! binfo_offset = size_binop (PLUS_EXPR,
! offset,
! BINFO_OFFSET (binfo));
! else
! {
! tree orig_binfo;
! /* We cannot rely on BINFO_OFFSET being set for the base
! class yet, but the offsets for direct non-virtual
! bases can be calculated by going back to the TYPE. */
! orig_binfo = BINFO_BASETYPE (TYPE_BINFO (type), i);
! binfo_offset = size_binop (PLUS_EXPR,
! offset,
! BINFO_OFFSET (orig_binfo));
! }
!
! r = walk_subobject_offsets (binfo,
f,
! binfo_offset,
offsets,
max_offset,
(abi_version_at_least (2)
*************** walk_subobject_offsets (type, f, offset,
*** 3458,3487 ****
return r;
}
! /* Iterate through the virtual base classes of TYPE. In G++
! 3.2, we included virtual bases in the direct base class loop
! above, which results in incorrect results; the correct
! offsets for virtual bases are only known when working with
! the most derived type. */
! if (abi_version_at_least (2) && vbases_p)
{
tree vbase;
! for (vbase = CLASSTYPE_VBASECLASSES (type);
! vbase;
! vbase = TREE_CHAIN (vbase))
{
! binfo = TREE_VALUE (vbase);
! r = walk_subobject_offsets (BINFO_TYPE (binfo),
! f,
! size_binop (PLUS_EXPR,
! offset,
! BINFO_OFFSET (binfo)),
! offsets,
! max_offset,
! /*vbases_p=*/0);
! if (r)
! return r;
}
}
--- 3484,3538 ----
return r;
}
! if (abi_version_at_least (2))
{
tree vbase;
! /* Iterate through the virtual base classes of TYPE. In G++
! 3.2, we included virtual bases in the direct base class
! loop above, which results in incorrect results; the
! correct offsets for virtual bases are only known when
! working with the most derived type. */
! if (vbases_p)
! for (vbase = CLASSTYPE_VBASECLASSES (type);
! vbase;
! vbase = TREE_CHAIN (vbase))
! {
! binfo = TREE_VALUE (vbase);
! r = walk_subobject_offsets (binfo,
! f,
! size_binop (PLUS_EXPR,
! offset,
! BINFO_OFFSET (binfo)),
! offsets,
! max_offset,
! /*vbases_p=*/0);
! if (r)
! return r;
! }
! else
{
! /* We still have to walk the primary base, if it is
! virtual. (If it is non-virtual, then it was walked
! above.) */
! vbase = get_primary_binfo (type_binfo);
! if (vbase && TREE_VIA_VIRTUAL (vbase))
! {
! tree derived = type_binfo;
! while (BINFO_INHERITANCE_CHAIN (derived))
! derived = BINFO_INHERITANCE_CHAIN (derived);
! derived = TREE_TYPE (derived);
! vbase = binfo_for_vbase (TREE_TYPE (vbase), derived);
!
! if (BINFO_PRIMARY_BASE_OF (vbase) == type_binfo)
! {
! r = (walk_subobject_offsets
! (vbase, f, offset,
! offsets, max_offset, /*vbases_p=*/0));
! if (r)
! return r;
! }
! }
}
}
*************** layout_nonempty_base_or_field (record_la
*** 3652,3658 ****
virtual base. */
if (!abi_version_at_least (2) && binfo && TREE_VIA_VIRTUAL (binfo))
break;
! if (layout_conflict_p (type, offset, offsets, field_p))
{
/* Strip off the size allocated to this field. That puts us
at the first place we could have put the field with
--- 3703,3710 ----
virtual base. */
if (!abi_version_at_least (2) && binfo && TREE_VIA_VIRTUAL (binfo))
break;
! if (layout_conflict_p (field_p ? type : binfo, offset,
! offsets, field_p))
{
/* Strip off the size allocated to this field. That puts us
at the first place we could have put the field with
*************** layout_empty_base (binfo, eoc, offsets,
*** 3726,3732 ****
/* This is an empty base class. We first try to put it at offset
zero. */
! if (layout_conflict_p (BINFO_TYPE (binfo),
BINFO_OFFSET (binfo),
offsets,
/*vbases_p=*/0))
--- 3778,3784 ----
/* This is an empty base class. We first try to put it at offset
zero. */
! if (layout_conflict_p (binfo,
BINFO_OFFSET (binfo),
offsets,
/*vbases_p=*/0))
*************** layout_empty_base (binfo, eoc, offsets,
*** 3737,3743 ****
propagate_binfo_offsets (binfo, convert (ssizetype, eoc), t);
while (1)
{
! if (!layout_conflict_p (BINFO_TYPE (binfo),
BINFO_OFFSET (binfo),
offsets,
/*vbases_p=*/0))
--- 3789,3795 ----
propagate_binfo_offsets (binfo, convert (ssizetype, eoc), t);
while (1)
{
! if (!layout_conflict_p (binfo,
BINFO_OFFSET (binfo),
offsets,
/*vbases_p=*/0))
*************** build_base_field (record_layout_info rli
*** 3848,3881 ****
}
/* Record the offsets of BINFO and its base subobjects. */
! record_subobject_offsets (BINFO_TYPE (binfo),
BINFO_OFFSET (binfo),
offsets,
/*vbases_p=*/0);
-
- if (abi_version_at_least (2))
- {
- /* If BINFO has a primary virtual base that is really going to
- be located at the same offset as binfo, it will have been
- skipped -- but we should record empty bases from there too. */
- while (true)
- {
- tree b;
-
- b = get_primary_binfo (binfo);
- if (!b)
- break;
- b = CANONICAL_BINFO (b, rli->t);
- if (BINFO_PRIMARY_BASE_OF (b) != binfo)
- break;
- if (TREE_VIA_VIRTUAL (b))
- record_subobject_offsets (BINFO_TYPE (b),
- BINFO_OFFSET (b),
- offsets,
- /*vbases_p=*/0);
- binfo = b;
- }
- }
return next_field;
}
--- 3900,3909 ----
}
/* Record the offsets of BINFO and its base subobjects. */
! record_subobject_offsets (binfo,
BINFO_OFFSET (binfo),
offsets,
/*vbases_p=*/0);
return next_field;
}