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

   Copyright 1993-2021 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;}
