This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
patch:dynamic_cast and nonprivate inheritance
- To: egcs-patches at egcs dot cygnus dot com
- Subject: patch:dynamic_cast and nonprivate inheritance
- From: Alfred Minarik <a8601248 at unet dot univie dot ac dot at>
- Date: Fri, 11 Jun 1999 21:10:00 +0200
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 */;