1 // Copyright (C) 2000 Free Software Foundation, Inc.
2 // Contributed by Nathan Sidwell 4 February 2001 <nathan@codesourcery.com>
3 
4 // Check constructor vtables work. This is included from numerous test
5 // files, which set the #defines necessary to specify the hierarchy.
6 
7 #include <typeinfo>
8 #include <stdio.h>
9 
10 int fail;
11 struct A;
12 
13 template <typename BASE, typename DERIVED>
Test(DERIVED * d,int expect)14 int Test (DERIVED *d, int expect)
15 {
16   BASE *b = static_cast <BASE *> (d);
17   void *full_b = dynamic_cast <void *> (b);
18   void *full_d = dynamic_cast <void *> (d);
19   A *ap = static_cast <A *> (b);
20 
21   if (full_b != full_d)
22     {
23       fail++;
24       fprintf (stderr, "base %s and derived %s have different full objects\n",
25               typeid (BASE).name (), typeid (DERIVED).name ());
26       return 1;
27     }
28 
29   DERIVED *dynamic_d = dynamic_cast <DERIVED *> (b);
30 
31   if (dynamic_d != d)
32     {
33       fail++;
34       fprintf (stderr, "dynamic_cast from %s to %s failed\n",
35               typeid (BASE).name (), typeid (DERIVED).name ());
36       return 1;
37     }
38 
39   b->Baz (static_cast <void *> (ap));
40 
41   int res = b->Foo (static_cast <void *> (d));
42 
43   if (res != expect)
44     {
45       fail++;
46       fprintf (stderr, "%s::Foo returned %d, expected %d\n",
47               typeid (BASE).name (), res, expect);
48       return 1;
49     }
50 
51   return 0;
52 }
53 
54 template <typename T>
Test(T * self,void * expected,int result)55 int Test (T *self, void *expected, int result)
56 {
57   if (self != expected)
58     {
59       fail++;
60       fprintf (stderr, "%s::Foo wrong this pointer\n", typeid (T).name ());
61     }
62   return result;
63 }
64 
65 struct A {
66 #ifndef A_EMPTY
67   int a_m;
68 #endif
FooA69   virtual int Foo (void *p) {return Test (this, p, 1);}
BazA70   virtual int Baz (void *p) {return Test (this, p, 1);}
71   A ();
72   ~A ();
73 };
74 
75 struct B1: virtual A {
76 #ifndef B1_EMPTY
77   int b1_m;
78 #endif
FooB179   virtual int Foo (void *p) {return Test (this, p, 2);}
80   B1();
81   ~B1();
82 };
83 
84 struct B2: virtual A {
85 #ifndef B2_EMPTY
86   int b2_m;
87 #endif
FooB288   virtual int Foo (void *p) {return Test (this, p, 3);}
89   B2();
90   ~B2();
91 };
92 
93 struct Empty {};
94 
95 struct C : C_PARENTS {
96 #ifndef C_EMPTY
97   int c_m;
98 #endif
FooC99   virtual int Foo (void *p) {return Test (this, p, 4);}
100   C();
101   ~C();
102 };
103 
A()104 A::A ()
105 {
106   fprintf (stderr, "%s\n", __PRETTY_FUNCTION__);
107   Test <A> (this, 1);
108 }
~A()109 A::~A ()
110 {
111   fprintf (stderr, "%s\n", __PRETTY_FUNCTION__);
112   Test <A> (this, 1);
113 }
114 
B1()115 B1::B1()
116 {
117   fprintf (stderr, "%s\n", __PRETTY_FUNCTION__);
118   Test <A> (this, 2);
119   Test <B1> (this, 2);
120 }
~B1()121 B1::~B1()
122 {
123   fprintf (stderr, "%s\n", __PRETTY_FUNCTION__);
124   Test <A> (this, 2);
125   Test <B1> (this, 2);
126 }
B2()127 B2::B2()
128 {
129   fprintf (stderr, "%s\n", __PRETTY_FUNCTION__);
130   Test <A> (this, 3);
131   Test <B2> (this, 3);
132 }
~B2()133 B2::~B2()
134 {
135   fprintf (stderr, "%s\n", __PRETTY_FUNCTION__);
136   Test <A> (this, 3);
137   Test <B2> (this, 3);
138 }
C()139 C::C()
140 {
141   fprintf (stderr, "%s\n", __PRETTY_FUNCTION__);
142   Test <A> (this, 4);
143   Test <C> (this, 4);
144 }
~C()145 C::~C()
146 {
147   fprintf (stderr, "%s\n", __PRETTY_FUNCTION__);
148   Test <A> (this, 4);
149   Test <C> (this, 4);
150 }
151 
152 struct D : C {};
153 struct D1 : virtual C {};
154 struct D2 : virtual A, virtual C {};
155 
main()156 int main()
157 {
158   {
159     fprintf (stderr, "C\n");
160     C c;
161   }
162   {
163     fprintf (stderr, "D\n");
164     D d;
165   }
166   {
167     fprintf (stderr, "D1\n");
168     D1 d1;
169   }
170   {
171     fprintf (stderr, "D2\n");
172     D2 d2;
173   }
174   if (fail)
175     fprintf (stderr, "There are %d failings\n", fail);
176   else
177     fprintf (stderr, "Passed\n");
178   return fail ? 1 : 0;
179 }
180