Commit 19331b53 by Nathan Sidwell Committed by Nathan Sidwell

Update new-abi dynamic cast algorithm.

	* tinfo.cc (__class_type_info::__dyncast_result): Add
	whole_details. Adjust constructor.
	(__vmi_class_type_info::__do_dyncast): Adjust for vmi_flags.
	Avoid unnecessary searching.
	(__dynamic_cast): Adjust for __dyncast_result::whole_details.

From-SVN: r34401
parent 80661759
2000-06-05 Nathan Sidwell <nathan@codesourcery.com>
Update new-abi dynamic cast algorithm.
* tinfo.cc (__class_type_info::__dyncast_result): Add
whole_details. Adjust constructor.
(__vmi_class_type_info::__do_dyncast): Adjust for vmi_flags.
Avoid unnecessary searching.
(__dynamic_cast): Adjust for __dyncast_result::whole_details.
Mon Jun 5 06:48:55 2000 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
* decl.c (init_decl_processing): Don't call record_component_aliases.
......
......@@ -685,11 +685,13 @@ struct __class_type_info::__dyncast_result
__sub_kind whole2dst; // path from most derived object to target
__sub_kind whole2src; // path from most derived object to sub object
__sub_kind dst2src; // path from target to sub object
int whole_details; // details of the whole class heirarchy
public:
__dyncast_result ()
__dyncast_result (int details_ = __vmi_class_type_info::__flags_unknown_mask)
:dst_ptr (NULL), whole2dst (__unknown),
whole2src (__unknown), dst2src (__unknown)
whole2src (__unknown), dst2src (__unknown),
whole_details (details_)
{}
};
......@@ -869,6 +871,9 @@ __do_dyncast (ptrdiff_t src2dst,
const void *src_ptr,
__dyncast_result &__restrict result) const
{
if (result.whole_details & __flags_unknown_mask)
result.whole_details = vmi_flags;
if (obj_ptr == src_ptr && *this == *src_type)
{
// The src object we started from. Indicate how we are accessible from
......@@ -887,10 +892,11 @@ __do_dyncast (ptrdiff_t src2dst,
result.dst2src = __not_contained;
return false;
}
bool result_ambig = false;
for (size_t i = vmi_base_count; i--;)
{
__dyncast_result result2;
__dyncast_result result2 (result.whole_details);
void const *base = obj_ptr;
__sub_kind base_access = access_path;
ptrdiff_t offset = vmi_bases[i].__offset ();
......@@ -901,7 +907,17 @@ __do_dyncast (ptrdiff_t src2dst,
base = convert_to_base (base, is_virtual, offset);
if (!vmi_bases[i].__is_public_p ())
base_access = __sub_kind (base_access & ~__contained_public_mask);
{
if (src2dst == -2 &&
!(result.whole_details
& (non_diamond_repeat_mask | diamond_shaped_mask)))
// The hierarchy has no duplicate bases (which might ambiguate
// things) and where we started is not a public base of what we
// want (so it cannot be a downcast). There is nothing of interest
// hiding in a non-public base.
continue;
base_access = __sub_kind (base_access & ~__contained_public_mask);
}
bool result2_ambig
= vmi_bases[i].base->__do_dyncast (src2dst, base_access,
......@@ -925,6 +941,10 @@ __do_dyncast (ptrdiff_t src2dst,
result.dst_ptr = result2.dst_ptr;
result.whole2dst = result2.whole2dst;
result_ambig = result2_ambig;
if (result.dst_ptr && result.whole2src != __unknown
&& !(vmi_flags & non_diamond_repeat_mask))
// Found dst and src and we don't have repeated bases.
return result_ambig;
}
else if (result.dst_ptr && result.dst_ptr == result2.dst_ptr)
{
......@@ -933,9 +953,8 @@ __do_dyncast (ptrdiff_t src2dst,
result.whole2dst =
__sub_kind (result.whole2dst | result2.whole2dst);
}
else if ((result.dst_ptr && result2.dst_ptr)
|| (result_ambig && result2.dst_ptr)
|| (result2_ambig && result.dst_ptr))
else if ((result.dst_ptr != 0 | result_ambig)
&& (result2.dst_ptr != 0 | result2_ambig))
{
// Found two different DST_TYPE bases, or a valid one and a set of
// ambiguous ones, must disambiguate. See whether SRC_PTR is
......@@ -948,11 +967,14 @@ __do_dyncast (ptrdiff_t src2dst,
__sub_kind new_sub_kind = result2.dst2src;
__sub_kind old_sub_kind = result.dst2src;
if (contained_nonvirtual_p (result.whole2src))
if (contained_p (result.whole2src)
&& (!virtual_p (result.whole2src)
|| !(result.whole_details & diamond_shaped_mask)))
{
// We already found SRC_PTR as a non-virtual base of most
// derived. Therefore if it is in either choice, it can only be
// in one of them, and we will already know.
// We already found SRC_PTR as a base of most derived, and
// either it was non-virtual, or the whole heirarchy is
// not-diamond shaped. Therefore if it is in either choice, it
// can only be in one of them, and we will already know.
if (old_sub_kind == __unknown)
old_sub_kind = __not_contained;
if (new_sub_kind == __unknown)
......@@ -962,9 +984,11 @@ __do_dyncast (ptrdiff_t src2dst,
{
if (old_sub_kind >= __not_contained)
;// already calculated
else if (contained_nonvirtual_p (new_sub_kind))
// Already found non-virtually inside the other choice,
// cannot be in this.
else if (contained_p (new_sub_kind)
&& (!virtual_p (new_sub_kind)
|| !(vmi_flags & diamond_shaped_mask)))
// Already found inside the other choice, and it was
// non-virtual or we are not diamond shaped.
old_sub_kind = __not_contained;
else
old_sub_kind = dst_type->__find_public_src
......@@ -972,9 +996,11 @@ __do_dyncast (ptrdiff_t src2dst,
if (new_sub_kind >= __not_contained)
;// already calculated
else if (contained_nonvirtual_p (old_sub_kind))
// Already found non-virtually inside the other choice,
// cannot be in this.
else if (contained_p (old_sub_kind)
&& (!virtual_p (old_sub_kind)
|| !(vmi_flags & diamond_shaped_mask)))
// Already found inside the other choice, and it was
// non-virtual or we are not diamond shaped.
new_sub_kind = __not_contained;
else
new_sub_kind = dst_type->__find_public_src
......@@ -1159,18 +1185,17 @@ __dynamic_cast (const void *src_ptr, // object started from
if (!result.dst_ptr)
return NULL;
if (contained_public_p (result.dst2src))
// Src is known to be a public base of dst.
return const_cast <void *> (result.dst_ptr);
if (contained_public_p (__class_type_info::__sub_kind (result.whole2src & result.whole2dst)))
// Found a valid cross cast
// Both src and dst are known to be public bases of whole. Found a valid
// cross cast.
return const_cast <void *> (result.dst_ptr);
if (contained_nonvirtual_p (result.whole2src))
// Found an invalid cross cast, which cannot also be a down cast
// Src is known to be a non-public nonvirtual base of whole, and not a
// base of dst. Found an invalid cross cast, which cannot also be a down
// cast
return NULL;
#if 0 // FIXME: we need to discover this lazily
if (!(whole_type->details & __class_type_info::private_base_mask))
// whole type has no private bases
return const_cast <void *> (result.dst_ptr);
#endif
if (result.dst2src == __class_type_info::__unknown)
result.dst2src = dst_type->__find_public_src (src2dst, result.dst_ptr,
src_type, src_ptr);
......
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