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]

Re: C++ PATCH: throw (T *)NULL and dynamic_cast


Nathan Sidwell wrote:
>I'm not attaching Alfred's test case, but recommend that it is made suitable
>for testsuite inclusion.
>

And here they are ...

But I have to tell a sad story: Sidwells patch still does not work
completely.
While cleaning and completing the testcases it came up.
It is Nr. 24 in first testsuite file.
maybe your solution is irritated by the public B base from CC.
The B from which the cast starts is not a public base
of the most derived object, so the cast should fail.
       A
       |
from-> B
       |
   (private)      A
       \         /
        C       B
         \     /
          D  CC  <-to should not be reachable
           \ /
            E  
=======================================
A sidenote on my last patch submission (just in case someone 
has looked at it). Well it also has
a small leak but with other cases.
replace:
      void* tmp2 = _to.dcast(_sub, require_public, tmp, &_sub, subptr);
!     if(tmp2) 
        return tmp;
by:
      void* tmp2 = _to.dcast(_sub, require_public, tmp, &_sub, subptr);
!     if(tmp2 && (tmp2==subptr) ) 
        return tmp;
But you will prefer Sidwells solution.
========================================

But now for the testsuit

----------------------dynamic_cast_nonpublic_1.C
// test of dynamic_cast
// runtime detecting of nonpublic
// inheritance within a cast
// and therefor failing with result 0.

extern "C" void abort();
//extern "C" void printf(const char*, ...);

void error(int i)
{
//  printf("Error %i\n",i);
  abort();
}

// 1. downcast

// 1.1. single inheritance case

struct A {virtual ~A(){}};
struct B : A {};
class C : B {};
struct D : C {};

struct CC : B {};
class DD : CC {};

class CCC : protected B {};
class DDD : protected CCC {};

void 
test01 ()
{
  D d;
  if(dynamic_cast<D*> ((A*)&d)) error(1);
  if(dynamic_cast<D*> ((B*)&d)) error(2);
  if(&d != dynamic_cast<D*> ((C*)&d)) error(3); //counter example
  if(dynamic_cast<C*> ((B*)&d)) error(4);
	
  DD dd;
  if(dynamic_cast<DD*> ((A*)&dd)) error(5);
  if(dynamic_cast<DD*> ((B*)&dd)) error(6);

  DDD ddd;
  if(dynamic_cast<DDD*> ((A*)&ddd)) error(7);
  if(dynamic_cast<DDD*> ((B*)&ddd)) error(8);
  if(dynamic_cast<CCC*> ((B*)&ddd)) error(9);
}		

// 1.2. multiple inheritance case
// 1.2.1. all bases are public
 
struct E : D, CC {};
struct EE : CC, D {}; //Will search in reverse order.

void 
test02 ()
{
  E e;
  if(dynamic_cast<E*> ((A*)(D*)&e)) error(10);
  if(dynamic_cast<E*> ((B*)(D*)&e)) error(11);
  if(&e != dynamic_cast<E*> ((C*)(D*)&e)) error(12); //counter example
  if(&e != dynamic_cast<E*> ((B*)(CC*)&e)) error(13); //counter example
  if((CC*)&e != dynamic_cast<CC*> ((B*)(CC*)&e)) error(14); //counter
example
  
  EE ee;
  if(dynamic_cast<EE*> ((A*)(D*)&ee)) error(15);
  if(dynamic_cast<EE*> ((B*)(D*)&ee)) error(16);
  if(&ee != dynamic_cast<EE*> ((C*)(D*)&ee)) error(17); //counter
example
  if(&ee != dynamic_cast<EE*> ((B*)(CC*)&ee)) error(18); //counter
example
  if((CC*)&ee != dynamic_cast<CC*> ((B*)(CC*)&ee)) error(19); //counter
example
}		

// 1.2.2 one or more branches are nonpublic

struct X : private B, E {};
struct Y : A, private B {};

class XX : B, E {};

void 
test03 ()
{
  X x;
  if(&x != dynamic_cast<X*>((B*)(CC*)(E*)&x)) error(20); //counter
example
  XX xx;
  if(dynamic_cast<XX*>((B*)(CC*)(E*)&xx)) error(21);	
  Y y;
  if(dynamic_cast<Y*>((B*)&y)) error (22);
  if(dynamic_cast<Y*>((A*)(B*)&y)) error (23);
}

// 2. crosscast

struct J {virtual ~J(){};};
struct K : CC, private J {}; 
class KK : J, CC{};
		
void 
test04 ()
{
  E e;
  if(dynamic_cast<CC*> ((B*)(D*)&e)) error(24);
  if((CC*)&e != dynamic_cast<CC*> ((C*)(D*)&e)) error(25); //counter
example
  K k;
  if(dynamic_cast<J*> ((B*)&k)) error(26);
  KK kk;
  if(dynamic_cast<J*> ((CC*)&kk)) error(27);
}

int 
main ()
{
  test01();
  test02();
  test03();
  test04();
}

----------------------end of dynamic_cast_nonpublic_1.C

----------------------dynamic_cast_nonpublic_2.C
// test of dynamic_cast
// runtime detecting of valid 
// downcasts within nonpublic 
// baseclasses.

extern "C" void abort();
//extern "C" void printf(const char*, ...);

void error(int i)
{
//  printf("Error %i\n",i);
  abort();
}

// 1. downcast
// 1.1 single inheritance case

struct A {virtual ~A(){};int i;};
struct B : A {int i;};
struct C : B {int i;};
class D : C {int i;};

struct E : D {int i;};
class F : E {int i;};

void 
test01 ()
{
  D d;
  if((C*)&d != dynamic_cast<C*> ((A*)&d)) error(1);
  if((C*)&d != dynamic_cast<C*> ((B*)&d)) error(2);
  if((B*)&d != dynamic_cast<B*> ((A*)&d)) error(3);

  E e;
  if((C*)&e != dynamic_cast<C*> ((A*)&e)) error(4);

  F f;
  if((C*)&f != dynamic_cast<C*> ((B*)&f)) error(5);
  if((B*)&f != dynamic_cast<B*> ((A*)&f)) error(6);
  if((E*)&f != dynamic_cast<E*> ((D*)&f)) error(7);
  if(dynamic_cast<E*> ((C*)&f)) error(8); //counter example
}		

// 1.2 multiple inheritance case

struct G : C, F{};
		
void 
test02 ()
{
  G g;
  if((B*)(F*)&g != dynamic_cast<B*> ((A*)(F*)&g)) error(9);
  if(dynamic_cast<D*> ((A*)(F*)&g)) error(10);
  if(dynamic_cast<G*> ((B*)(F*)&g)) error(11);
}

// 2. crosscast (always fail)

struct I : C{};
struct J : F{};
struct K : I, J{};
class L : K{};
		
void 
test03 ()
{
  L l;
  if(dynamic_cast<J*> ((I*)&l)) error(12);
  if(dynamic_cast<J*> ((E*)&l)) error(13);
  if(dynamic_cast<I*> ((J*)&l)) error(14);
}

int 
main ()
{
  test01();
  test02();
  test03();
}

----------------------end of dynamic_cast_nonpublic_2.C


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