/* This test script is part of GDB, the GNU debugger.

   Copyright 1993-2013 Free Software Foundation, Inc.

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 3 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program.  If not, see <http://www.gnu.org/licenses/>.
   */

// Pls try the following program on virtual functions and try to do print on
//  most of the code in main().  Almost none of them works !

//
// The inheritance structure is:
//
// V : VA VB
// A : (V)
// B : A
// D : AD (V)
// C : (V)
// E : B (V) D C
//

class VA 
{
public:
    int va;
};

class VB
{
public:
    int vb;
    int fvb();
    virtual int vvb();
};

class V : public VA, public VB
{
public:
    int f();
    virtual int vv();
    int w;
};

class A : virtual public V
{
public:
    virtual int f();
private:
    int a;
};

class B : public A
{
public:
    int f();
private:
    int b;
};

class C : public virtual V
{
public:
    int c;
};

class AD
{
public:
    virtual int vg() = 0;
};

class D : public AD, virtual public V
{
public:
    static void s();
    virtual int vg();
    virtual int vd();
    int fd();
    int d;
};

class E : public B, virtual public V, public D, public C
{
public:
    int f();
    int vg();
    int vv();
    int e;
};

D   dd;
D*  ppd = &dd;
AD* pAd = &dd;

A   a;
B   b;
C   c;
D   d;
E   e;
V   v;
VB  vb;
VA  va;


A* 	pAa	= 	&a;
A*	pAe	=	&e;

B*	pBe	=	&e;

D*	pDd	=	&d;
D*	pDe	=	&e;

V*	pVa	=	&a;
V*	pVv	=	&v;
V*	pVe	=	&e;
V*     pVd	=	&d;

AD*	pADe	=	&e;

E*	pEe	=	&e;

VB*     pVB	=	&vb;

void init()
{
	a.vb = 1;
	b.vb = 2;
	c.vb = 3;
	d.vb = 4;
	e.vb = 5;
	v.vb = 6;
	vb.vb = 7;

	d.d	= 1;
	e.d	=  2;
}

extern "C" int printf(const char *, ...);

int all_count = 0;
int failed_count = 0;

#define TEST(EXPR, EXPECTED) \
   ret = EXPR; \
   if (ret != EXPECTED) {\
      printf("Failed %s is %d, should be %d!\n", #EXPR, ret, EXPECTED); \
      failed_count++; } \
   all_count++;

int ret;

void test_calls()
{
	TEST(pAe->f(), 20);
	TEST(pAa->f(), 1);

	TEST(pDe->vg(), 202);
	TEST(pADe->vg(), 202);
	TEST(pDd->vg(), 101);

	TEST(pEe->vvb(), 411);

	TEST(pVB->vvb(), 407);

	TEST(pBe->vvb(), 411);
	TEST(pDe->vvb(), 411);

        TEST(pEe->vd(), 282);
        TEST(pEe->fvb(), 311);
    
        TEST(pEe->D::vg(), 102);
	printf("Did %d tests, of which %d failed.\n", all_count, failed_count);
}

int main()
{
    init();

    e.w = 7;
    e.vb = 11;

    test_calls();
    return 0;
    
}

int A::f() {return 1;}
int B::f() {return 2;}
void D::s() {}
int E::f() {return 20;}
int D::vg() {return 100+d;}
int E::vg() {return 200+d;}
int V::f() {return 600+w;}
int V::vv() {return 400+w;}
int E::vv() {return 450+w;}
int D::fd() {return 250+d;}
int D::vd() {return 280+d;}
int VB::fvb() {return 300+vb;}
int VB::vvb() {return 400+vb;}
