This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

[C++ PATCH] new-abi dynamic cast


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);

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]