aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorMark Mitchell <mark@codesourcery.com>2002-11-29 21:17:05 +0000
committerMark Mitchell <mmitchel@gcc.gnu.org>2002-11-29 21:17:05 +0000
commitff944b4986e98b09d1c300ad3f41ed89313aa915 (patch)
tree5e087c8befd91a9e9973b1c4373f15a13ed820b4 /gcc
parent8ef34c0df0f3f3ede1c25d172168a5b3bd1f6572 (diff)
downloadgcc-ff944b4986e98b09d1c300ad3f41ed89313aa915.zip
gcc-ff944b4986e98b09d1c300ad3f41ed89313aa915.tar.gz
gcc-ff944b4986e98b09d1c300ad3f41ed89313aa915.tar.bz2
class.c (walk_subobject_offsets): Recur on binfos as well as on types.
* 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. From-SVN: r59643
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog9
-rw-r--r--gcc/cp/class.c136
2 files changed, 91 insertions, 54 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 677a6bb..d22e538 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,12 @@
+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.
+
2002-11-27 Mark Mitchell <mark@codesourcery.com>
* class.c (build_base_field): Make sure we get the canonical base
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index 0d93334..e3ea2db 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -3410,12 +3410,20 @@ walk_subobject_offsets (type, f, offset, offsets, max_offset, vbases_p)
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;
@@ -3432,9 +3440,13 @@ walk_subobject_offsets (type, f, offset, offsets, max_offset, vbases_p)
return r;
/* Iterate through the direct base classes of TYPE. */
- for (i = 0; i < CLASSTYPE_N_BASECLASSES (type); ++i)
+ if (!type_binfo)
+ type_binfo = TYPE_BINFO (type);
+ for (i = 0; i < BINFO_N_BASETYPES (type_binfo); ++i)
{
- binfo = BINFO_BASETYPE (TYPE_BINFO (type), i);
+ tree binfo_offset;
+
+ binfo = BINFO_BASETYPE (type_binfo, i);
if (abi_version_at_least (2)
&& TREE_VIA_VIRTUAL (binfo))
@@ -3445,11 +3457,25 @@ walk_subobject_offsets (type, f, offset, offsets, max_offset, vbases_p)
&& !BINFO_PRIMARY_P (binfo))
continue;
- r = walk_subobject_offsets (BINFO_TYPE (binfo),
+ 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,
- size_binop (PLUS_EXPR,
- offset,
- BINFO_OFFSET (binfo)),
+ binfo_offset,
offsets,
max_offset,
(abi_version_at_least (2)
@@ -3458,30 +3484,55 @@ walk_subobject_offsets (type, f, offset, offsets, max_offset, vbases_p)
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)
+ if (abi_version_at_least (2))
{
tree vbase;
- for (vbase = CLASSTYPE_VBASECLASSES (type);
- vbase;
- vbase = TREE_CHAIN (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
{
- 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;
+ /* 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;
+ }
+ }
}
}
@@ -3652,7 +3703,8 @@ layout_nonempty_base_or_field (record_layout_info rli,
virtual base. */
if (!abi_version_at_least (2) && binfo && TREE_VIA_VIRTUAL (binfo))
break;
- if (layout_conflict_p (type, offset, offsets, field_p))
+ 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
@@ -3726,7 +3778,7 @@ layout_empty_base (binfo, eoc, offsets, t)
/* This is an empty base class. We first try to put it at offset
zero. */
- if (layout_conflict_p (BINFO_TYPE (binfo),
+ if (layout_conflict_p (binfo,
BINFO_OFFSET (binfo),
offsets,
/*vbases_p=*/0))
@@ -3737,7 +3789,7 @@ layout_empty_base (binfo, eoc, offsets, t)
propagate_binfo_offsets (binfo, convert (ssizetype, eoc), t);
while (1)
{
- if (!layout_conflict_p (BINFO_TYPE (binfo),
+ if (!layout_conflict_p (binfo,
BINFO_OFFSET (binfo),
offsets,
/*vbases_p=*/0))
@@ -3848,35 +3900,11 @@ build_base_field (record_layout_info rli, tree binfo,
}
/* Record the offsets of BINFO and its base subobjects. */
- record_subobject_offsets (BINFO_TYPE (binfo),
+ record_subobject_offsets (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;
}