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]

patch:dynamic_cast and nonprivate inheritance


Sorry I sent you not the final patch
here comes the right one with an
additional security gard.

Alfred
*** egcs-19990602.orig/gcc/cp/tinfo.cc	Fri Jun  4 13:20:53 1999
--- egcs-19990602/gcc/cp/tinfo.cc	Fri Jun 11 20:50:51 1999
***************
*** 65,81 ****
  // dynamic_cast helper methods.
  // Returns a pointer to the desired sub-object or 0.
  
  void * __user_type_info::
! dcast (const type_info& to, int, void *addr, const type_info *, void *) const
! { return (*this == to) ? addr : 0; }
  
  void * __si_type_info::
! dcast (const type_info& to, int require_public, void *addr,
         const type_info *sub, void *subptr) const
  {
!   if (*this == to)
!     return addr;
!   return base.dcast (to, require_public, addr, sub, subptr);
  }
  
  void* __class_type_info::
--- 65,112 ----
  // dynamic_cast helper methods.
  // Returns a pointer to the desired sub-object or 0.
  
+ namespace {
+   void * 
+   __test_if_downcast(const type_info& desired, int is_public, void *objptr,
+ 	 const type_info *sub, void *subptr)
+   {
+     if (!sub) 
+       return objptr;
+     if (*sub == desired) 
+       return (subptr != objptr) ? 0 : objptr;
+     // Try as downcast (test if there are nonpublic bases on way from sub)
+     // Do not enter special privat handling by using -1 as secound argument
+     // (if is_public == 1 or -1)
+     int abs_public = (is_public==-1) ? 1 : is_public;
+     void *pp = static_cast <const __user_type_info &> (desired).dcast
+       (*sub,-abs_public,objptr,sub,subptr); 
+     if (pp == subptr)
+       return objptr;
+     // Distinguish between unreachabel downcast and crosscast
+     pp = static_cast <const __user_type_info &> (desired).dcast
+       (*sub,0,objptr,sub,subptr);
+     return (pp == subptr) ? 0 : objptr;
+   }
+ }
+ 
  void * __user_type_info::
! dcast (const type_info& to, int, void *addr, const type_info *sub, void *subptr) const
! {
!   if (*this == to)
!   {
!     if (sub && *sub == to && subptr != addr) return 0;
!     return addr;
!   }
!   return 0;
! }
  
  void * __si_type_info::
! dcast (const type_info& desired, int is_public, void *objptr,
         const type_info *sub, void *subptr) const
  {
!   if (*this == desired) 
!     return __test_if_downcast(desired,is_public,objptr,sub,subptr);
!   return base.dcast (desired, is_public, objptr, sub, subptr);
  }
  
  void* __class_type_info::
***************
*** 83,102 ****
         const type_info *sub, void *subptr) const
  {
    if (*this == desired)
!     return objptr;
  
    void *match_found = 0;
    for (size_t i = 0; i < n_bases; i++)
      {
-       if (is_public && base_list[i].access != PUBLIC)
- 	continue;
- 
        void *p = (char *)objptr + base_list[i].offset;
        if (base_list[i].is_virtual)
  	p = *(void **)p;
        p = base_list[i].base->dcast (desired, is_public, p, sub, subptr);
        if (p)
  	{
  	  if (match_found == 0)
  	    match_found = p;
  	  else if (match_found != p)
--- 114,156 ----
         const type_info *sub, void *subptr) const
  {
    if (*this == desired)
!     return __test_if_downcast(desired,is_public,objptr,sub,subptr);
  
    void *match_found = 0;
    for (size_t i = 0; i < n_bases; i++)
      {
        void *p = (char *)objptr + base_list[i].offset;
        if (base_list[i].is_virtual)
  	p = *(void **)p;
+ 	
+       //There can by a valid downcast within a nonpublic baseclass
+       //Skippd at internal public downcast tests indicated with is_public== -1
+       if ((is_public==-1) && base_list[i].access != PUBLIC) 
+         continue;
+       if (is_public && base_list[i].access != PUBLIC)
+       {
+         if (sub)
+         {
+           void *tmp = base_list[i].base->dcast (desired, 0, p, sub, subptr);
+ 	  if(tmp)
+ 	  {
+ 	    void *pp = static_cast <const __user_type_info &> (desired).dcast 
+ 	      (*sub,-1,tmp,sub,subptr);
+ 	    if(pp)
+ 	      return tmp;
+ 	    else 
+ 	      continue;
+ 	  }
+ 	  else
+ 	    continue;
+ 	}
+ 	else 
+ 	  continue;
+       }
        p = base_list[i].base->dcast (desired, is_public, p, sub, subptr);
        if (p)
  	{
+ 	  if (p == subptr) return p; //shortcut
  	  if (match_found == 0)
  	    match_found = p;
  	  else if (match_found != p)
***************
*** 108,116 ****
  
  		  const __user_type_info &d =
  		    static_cast <const __user_type_info &> (desired);
! 
! 		  void *os = d.dcast (*sub, 1, match_found);
! 		  void *ns = d.dcast (*sub, 1, p);
  
  		  if (os == ns)
  		    /* ambiguous -- subptr is a virtual base */;
--- 162,171 ----
  
  		  const __user_type_info &d =
  		    static_cast <const __user_type_info &> (desired);
! 			
! 		  int abs_public = (is_public==-1) ? 1 : is_public;
! 		  void *os = d.dcast (*sub, -abs_public, match_found, sub, subptr);
! 		  void *ns = d.dcast (*sub, -abs_public, p, sub, subptr);
  
  		  if (os == ns)
  		    /* ambiguous -- subptr is a virtual base */;


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