Commit ff944b49 by Mark Mitchell Committed by Mark Mitchell

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
parent 8ef34c0d
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> 2002-11-27 Mark Mitchell <mark@codesourcery.com>
* class.c (build_base_field): Make sure we get the canonical base * class.c (build_base_field): Make sure we get the canonical base
......
...@@ -3410,12 +3410,20 @@ walk_subobject_offsets (type, f, offset, offsets, max_offset, vbases_p) ...@@ -3410,12 +3410,20 @@ walk_subobject_offsets (type, f, offset, offsets, max_offset, vbases_p)
int vbases_p; int vbases_p;
{ {
int r = 0; int r = 0;
tree type_binfo = NULL_TREE;
/* If this OFFSET is bigger than the MAX_OFFSET, then we should /* If this OFFSET is bigger than the MAX_OFFSET, then we should
stop. */ stop. */
if (max_offset && INT_CST_LT (max_offset, offset)) if (max_offset && INT_CST_LT (max_offset, offset))
return 0; return 0;
if (!TYPE_P (type))
{
if (abi_version_at_least (2))
type_binfo = type;
type = BINFO_TYPE (type);
}
if (CLASS_TYPE_P (type)) if (CLASS_TYPE_P (type))
{ {
tree field; tree field;
...@@ -3432,9 +3440,13 @@ walk_subobject_offsets (type, f, offset, offsets, max_offset, vbases_p) ...@@ -3432,9 +3440,13 @@ walk_subobject_offsets (type, f, offset, offsets, max_offset, vbases_p)
return r; return r;
/* Iterate through the direct base classes of TYPE. */ /* 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) if (abi_version_at_least (2)
&& TREE_VIA_VIRTUAL (binfo)) && TREE_VIA_VIRTUAL (binfo))
...@@ -3445,11 +3457,25 @@ walk_subobject_offsets (type, f, offset, offsets, max_offset, vbases_p) ...@@ -3445,11 +3457,25 @@ walk_subobject_offsets (type, f, offset, offsets, max_offset, vbases_p)
&& !BINFO_PRIMARY_P (binfo)) && !BINFO_PRIMARY_P (binfo))
continue; 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, f,
size_binop (PLUS_EXPR, binfo_offset,
offset,
BINFO_OFFSET (binfo)),
offsets, offsets,
max_offset, max_offset,
(abi_version_at_least (2) (abi_version_at_least (2)
...@@ -3458,30 +3484,55 @@ walk_subobject_offsets (type, f, offset, offsets, max_offset, vbases_p) ...@@ -3458,30 +3484,55 @@ walk_subobject_offsets (type, f, offset, offsets, max_offset, vbases_p)
return r; return r;
} }
/* Iterate through the virtual base classes of TYPE. In G++ if (abi_version_at_least (2))
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; tree vbase;
for (vbase = CLASSTYPE_VBASECLASSES (type); /* Iterate through the virtual base classes of TYPE. In G++
vbase; 3.2, we included virtual bases in the direct base class
vbase = TREE_CHAIN (vbase)) 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); /* We still have to walk the primary base, if it is
r = walk_subobject_offsets (BINFO_TYPE (binfo), virtual. (If it is non-virtual, then it was walked
f, above.) */
size_binop (PLUS_EXPR, vbase = get_primary_binfo (type_binfo);
offset, if (vbase && TREE_VIA_VIRTUAL (vbase))
BINFO_OFFSET (binfo)), {
offsets, tree derived = type_binfo;
max_offset, while (BINFO_INHERITANCE_CHAIN (derived))
/*vbases_p=*/0); derived = BINFO_INHERITANCE_CHAIN (derived);
if (r) derived = TREE_TYPE (derived);
return r; 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, ...@@ -3652,7 +3703,8 @@ layout_nonempty_base_or_field (record_layout_info rli,
virtual base. */ virtual base. */
if (!abi_version_at_least (2) && binfo && TREE_VIA_VIRTUAL (binfo)) if (!abi_version_at_least (2) && binfo && TREE_VIA_VIRTUAL (binfo))
break; 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 /* Strip off the size allocated to this field. That puts us
at the first place we could have put the field with at the first place we could have put the field with
...@@ -3726,7 +3778,7 @@ layout_empty_base (binfo, eoc, offsets, t) ...@@ -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 /* This is an empty base class. We first try to put it at offset
zero. */ zero. */
if (layout_conflict_p (BINFO_TYPE (binfo), if (layout_conflict_p (binfo,
BINFO_OFFSET (binfo), BINFO_OFFSET (binfo),
offsets, offsets,
/*vbases_p=*/0)) /*vbases_p=*/0))
...@@ -3737,7 +3789,7 @@ layout_empty_base (binfo, eoc, offsets, t) ...@@ -3737,7 +3789,7 @@ layout_empty_base (binfo, eoc, offsets, t)
propagate_binfo_offsets (binfo, convert (ssizetype, eoc), t); propagate_binfo_offsets (binfo, convert (ssizetype, eoc), t);
while (1) while (1)
{ {
if (!layout_conflict_p (BINFO_TYPE (binfo), if (!layout_conflict_p (binfo,
BINFO_OFFSET (binfo), BINFO_OFFSET (binfo),
offsets, offsets,
/*vbases_p=*/0)) /*vbases_p=*/0))
...@@ -3848,35 +3900,11 @@ build_base_field (record_layout_info rli, tree binfo, ...@@ -3848,35 +3900,11 @@ build_base_field (record_layout_info rli, tree binfo,
} }
/* Record the offsets of BINFO and its base subobjects. */ /* Record the offsets of BINFO and its base subobjects. */
record_subobject_offsets (BINFO_TYPE (binfo), record_subobject_offsets (binfo,
BINFO_OFFSET (binfo), BINFO_OFFSET (binfo),
offsets, offsets,
/*vbases_p=*/0); /*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; return next_field;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment