This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[C++ PATCH] new-abi dynamic cast
- To: gcc-patches at gcc dot gnu dot org
- Subject: [C++ PATCH] new-abi dynamic cast
- From: Nathan Sidwell <nathan at codesourcery dot com>
- Date: Mon, 05 Jun 2000 13:19:05 +0100
- Organization: CodeSourcery, LLC
Hi,
I've installed the attached patch which updates the new-abi's dynamic
cast algorithm. No change in old abi, which continues to boot and test
on i686-pc-linux-gnu
nathan
--
Dr Nathan Sidwell :: http://www.codesourcery.com :: CodeSourcery LLC
'But that's a lie.' - 'Yes it is. What's your point?'
nathan@codesourcery.com : http://www.cs.bris.ac.uk/~nathan/ : nathan@acm.org
2000-06-04 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.
Index: cp/tinfo.cc
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/tinfo.cc,v
retrieving revision 1.32
diff -c -3 -p -r1.32 tinfo.cc
*** tinfo.cc 2000/05/25 11:13:17 1.32
--- tinfo.cc 2000/06/04 17:09:58
*************** struct __class_type_info::__dyncast_resu
*** 685,695 ****
__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
public:
! __dyncast_result ()
:dst_ptr (NULL), whole2dst (__unknown),
! whole2src (__unknown), dst2src (__unknown)
{}
};
--- 685,697 ----
__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 (int details_ = __vmi_class_type_info::__flags_unknown_mask)
:dst_ptr (NULL), whole2dst (__unknown),
! whole2src (__unknown), dst2src (__unknown),
! whole_details (details_)
{}
};
*************** __do_dyncast (ptrdiff_t src2dst,
*** 869,874 ****
--- 874,882 ----
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
*************** __do_dyncast (ptrdiff_t src2dst,
*** 887,896 ****
result.dst2src = __not_contained;
return false;
}
bool result_ambig = false;
for (size_t i = vmi_base_count; i--;)
{
! __dyncast_result result2;
void const *base = obj_ptr;
__sub_kind base_access = access_path;
ptrdiff_t offset = vmi_bases[i].__offset ();
--- 895,905 ----
result.dst2src = __not_contained;
return false;
}
+
bool result_ambig = false;
for (size_t i = vmi_base_count; i--;)
{
! __dyncast_result result2 (result.whole_details);
void const *base = obj_ptr;
__sub_kind base_access = access_path;
ptrdiff_t offset = vmi_bases[i].__offset ();
*************** __do_dyncast (ptrdiff_t src2dst,
*** 901,907 ****
base = convert_to_base (base, is_virtual, offset);
if (!vmi_bases[i].__is_public_p ())
! base_access = __sub_kind (base_access & ~__contained_public_mask);
bool result2_ambig
= vmi_bases[i].base->__do_dyncast (src2dst, base_access,
--- 910,926 ----
base = convert_to_base (base, is_virtual, offset);
if (!vmi_bases[i].__is_public_p ())
! {
! 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,
*************** __do_dyncast (ptrdiff_t src2dst,
*** 925,930 ****
--- 944,953 ----
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)
{
*************** __do_dyncast (ptrdiff_t src2dst,
*** 933,941 ****
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))
{
// Found two different DST_TYPE bases, or a valid one and a set of
// ambiguous ones, must disambiguate. See whether SRC_PTR is
--- 956,963 ----
result.whole2dst =
__sub_kind (result.whole2dst | result2.whole2dst);
}
! 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
*************** __do_dyncast (ptrdiff_t src2dst,
*** 948,958 ****
__sub_kind new_sub_kind = result2.dst2src;
__sub_kind old_sub_kind = result.dst2src;
! if (contained_nonvirtual_p (result.whole2src))
{
! // 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.
if (old_sub_kind == __unknown)
old_sub_kind = __not_contained;
if (new_sub_kind == __unknown)
--- 970,983 ----
__sub_kind new_sub_kind = result2.dst2src;
__sub_kind old_sub_kind = result.dst2src;
! if (contained_p (result.whole2src)
! && (!virtual_p (result.whole2src)
! || !(result.whole_details & diamond_shaped_mask)))
{
! // 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)
*************** __do_dyncast (ptrdiff_t src2dst,
*** 962,970 ****
{
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.
old_sub_kind = __not_contained;
else
old_sub_kind = dst_type->__find_public_src
--- 987,997 ----
{
if (old_sub_kind >= __not_contained)
;// already calculated
! 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
*************** __do_dyncast (ptrdiff_t src2dst,
*** 972,980 ****
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.
new_sub_kind = __not_contained;
else
new_sub_kind = dst_type->__find_public_src
--- 999,1009 ----
if (new_sub_kind >= __not_contained)
;// already calculated
! 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
*************** __dynamic_cast (const void *src_ptr,
*** 1159,1176 ****
if (!result.dst_ptr)
return NULL;
if (contained_public_p (result.dst2src))
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
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
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);
--- 1189,1205 ----
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)))
! // 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))
! // 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 (result.dst2src == __class_type_info::__unknown)
result.dst2src = dst_type->__find_public_src (src2dst, result.dst_ptr,
src_type, src_ptr);