Added tests for div_t and ldiv_t.
[wine] / dlls / msvcrt / tests / cpp.c
1 /* Unit test suite for msvcrt C++ objects
2  *
3  * Copyright 2003 Jon Griffiths
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18  *
19  * NOTES
20  * This tests is only valid for ix86 platforms, on others it's a no-op.
21  * Some tests cannot be checked with ok(), for example the dtors. We simply
22  * call them to ensure we don't crash ;-)
23  *
24  * If we build this test with VC++ in debug mode, we will fail in _chkstk()
25  * or at program exit malloc() checking if these methods haven't been
26  * implemented correctly (they have).
27  *
28  * Tested with a range of native msvcrt's from v4 -> v7.
29  */
30 #include "wine/test.h"
31 #include "winbase.h"
32 #include "winnt.h"
33
34 #ifndef __i386__
35 /* Skip these tests for non x86 platforms */
36 START_TEST(cpp)
37 {
38 }
39 #else
40
41 typedef struct __exception
42 {
43   void *vtable;
44   char *name;
45   int   do_free;
46 } exception;
47
48 typedef struct __type_info
49 {
50   void *vtable;
51   char *name;
52   char  mangled[16];
53 } type_info;
54
55 /* Function pointers. We need to use these to call these funcs as __thiscall */
56 static HMODULE hMsvcrt;
57
58 static void* (*poperator_new)(unsigned int);
59 static void  (*poperator_delete)(void*);
60 static void* (*pmalloc)(unsigned int);
61 static void  (*pfree)(void*);
62
63 /* exception */
64 static void (WINAPI *pexception_ctor)(exception*,LPCSTR*);
65 static void (WINAPI *pexception_copy_ctor)(exception*,exception*);
66 static void (WINAPI *pexception_default_ctor)(exception*);
67 static void (WINAPI *pexception_dtor)(exception*);
68 static exception* (WINAPI *pexception_opequals)(exception*,exception*);
69 static char* (WINAPI *pexception_what)(exception*);
70 static void* (WINAPI *pexception_vtable)(exception*);
71 static void (WINAPI *pexception_vector_dtor)(exception*,unsigned int);
72 static void (WINAPI *pexception_scalar_dtor)(exception*,unsigned int);
73
74 /* bad_typeid */
75 static void (WINAPI *pbad_typeid_ctor)(exception*,LPCSTR);
76 static void (WINAPI *pbad_typeid_ctor_closure)(exception*);
77 static void (WINAPI *pbad_typeid_copy_ctor)(exception*,exception*);
78 static void (WINAPI *pbad_typeid_dtor)(exception*);
79 static exception* (WINAPI *pbad_typeid_opequals)(exception*,exception*);
80 static char* (WINAPI *pbad_typeid_what)(exception*);
81 static void* (WINAPI *pbad_typeid_vtable)(exception*);
82 static void (WINAPI *pbad_typeid_vector_dtor)(exception*,unsigned int);
83 static void (WINAPI *pbad_typeid_scalar_dtor)(exception*,unsigned int);
84
85 /* bad_cast */
86 static void (WINAPI *pbad_cast_ctor)(exception*,LPCSTR*);
87 static void (WINAPI *pbad_cast_ctor2)(exception*,LPCSTR);
88 static void (WINAPI *pbad_cast_ctor_closure)(exception*);
89 static void (WINAPI *pbad_cast_copy_ctor)(exception*,exception*);
90 static void (WINAPI *pbad_cast_dtor)(exception*);
91 static exception* (WINAPI *pbad_cast_opequals)(exception*,exception*);
92 static char* (WINAPI *pbad_cast_what)(exception*);
93 static void* (WINAPI *pbad_cast_vtable)(exception*);
94 static void (WINAPI *pbad_cast_vector_dtor)(exception*,unsigned int);
95 static void (WINAPI *pbad_cast_scalar_dtor)(exception*,unsigned int);
96
97 /* __non_rtti_object */
98 static void (WINAPI *p__non_rtti_object_ctor)(exception*,LPCSTR);
99 static void (WINAPI *p__non_rtti_object_copy_ctor)(exception*,exception*);
100 static void (WINAPI *p__non_rtti_object_dtor)(exception*);
101 static exception* (WINAPI *p__non_rtti_object_opequals)(exception*,exception*);
102 static char* (WINAPI *p__non_rtti_object_what)(exception*);
103 static void* (WINAPI *p__non_rtti_object_vtable)(exception*);
104 static void (WINAPI *p__non_rtti_object_vector_dtor)(exception*,unsigned int);
105 static void (WINAPI *p__non_rtti_object_scalar_dtor)(exception*,unsigned int);
106
107 /* type_info */
108 static void  (WINAPI *ptype_info_dtor)(type_info*);
109 static char* (WINAPI *ptype_info_raw_name)(type_info*);
110 static char* (WINAPI *ptype_info_name)(type_info*);
111 static int   (WINAPI *ptype_info_before)(type_info*,type_info*);
112 static int   (WINAPI *ptype_info_opequals_equals)(type_info*,type_info*);
113 static int   (WINAPI *ptype_info_opnot_equals)(type_info*,type_info*);
114
115 /* RTTI */
116 static type_info* (*p__RTtypeid)(void*);
117 static void* (*p__RTCastToVoid)(void*);
118 static void* (*p__RTDynamicCast)(void*,int,void*,void*,int);
119
120 /* _very_ early native versions have serious RTTI bugs, so we check */
121 static void* bAncientVersion;
122
123 /* Emulate a __thiscall */
124 #ifdef _MSC_VER
125 inline static void* do_call_func1(void *func, void *_this)
126 {
127   volatile void* retval = 0;
128   __asm
129   {
130     push ecx
131     mov ecx, _this
132     call func
133     mov retval, eax
134     pop ecx
135   }
136   return (void*)retval;
137 }
138
139 inline static void* do_call_func2(void *func, void *_this, void* arg)
140 {
141   volatile void* retval = 0;
142   __asm
143   {
144     push ecx
145     push arg
146     mov ecx, _this
147     call func
148     mov retval, eax
149     pop ecx
150   }
151   return (void*)retval;
152 }
153 #else
154 static void* do_call_func1(void *func, void *_this)
155 {
156   void* ret;
157   __asm__ __volatile__ ("pushl %%ecx;\n\tmovl %2, %%ecx;\n\tcall *%1;\n\tpopl %%ecx;"
158                         : "=a" (ret)
159                         : "g" (func), "m" (_this)
160                         : "memory" );
161   return ret;
162 }
163 static void* do_call_func2(void *func, void *_this, void* arg)
164 {
165   void* ret;
166   __asm__ __volatile__ ("pushl %%ecx;\n\tpushl %2;\n\t"
167                         "movl %3, %%ecx;\n\tcall *%1;\n\tpopl %%ecx;"
168                         : "=a" (ret)
169                         : "g" (func), "m" (arg), "m" (_this)
170                         : "memory" );
171   return ret;
172 }
173 #endif
174
175 #define call_func1(x,y)   do_call_func1((void*)x,(void*)y)
176 #define call_func2(x,y,z) do_call_func2((void*)x,(void*)y,(void*)z)
177
178 /* Some exports are only available in later versions */
179 #define SETNOFAIL(x,y) x = (void*)GetProcAddress(hMsvcrt,y)
180 #define SET(x,y) SETNOFAIL(x,y); ok(x != NULL, "Export '%s' not found\n", y)
181
182 static void InitFunctionPtrs()
183 {
184   hMsvcrt = LoadLibraryA("msvcrt.dll");
185   ok(hMsvcrt != 0, "LoadLibraryA failed\n");
186   if (hMsvcrt)
187   {
188     SETNOFAIL(poperator_new, "??_U@YAPAXI@Z");
189     SETNOFAIL(poperator_delete, "??_V@YAXPAX@Z");
190     SET(pmalloc, "malloc");
191     SET(pfree, "free");
192
193     if (!poperator_new)
194       poperator_new = pmalloc;
195     if (!poperator_delete)
196       poperator_delete = pfree;
197
198     SET(pexception_ctor, "??0exception@@QAE@ABQBD@Z");
199     SET(pexception_copy_ctor, "??0exception@@QAE@ABV0@@Z");
200     SET(pexception_default_ctor, "??0exception@@QAE@XZ");
201     SET(pexception_dtor, "??1exception@@UAE@XZ");
202     SET(pexception_opequals, "??4exception@@QAEAAV0@ABV0@@Z");
203     SET(pexception_what, "?what@exception@@UBEPBDXZ");
204     SET(pexception_vtable, "??_7exception@@6B@");
205     SET(pexception_vector_dtor, "??_Eexception@@UAEPAXI@Z");
206     SET(pexception_scalar_dtor, "??_Gexception@@UAEPAXI@Z");
207
208     SET(pbad_typeid_ctor, "??0bad_typeid@@QAE@PBD@Z");
209     SETNOFAIL(pbad_typeid_ctor_closure, "??_Fbad_typeid@@QAEXXZ");
210     SET(pbad_typeid_copy_ctor, "??0bad_typeid@@QAE@ABV0@@Z");
211     SET(pbad_typeid_dtor, "??1bad_typeid@@UAE@XZ");
212     SET(pbad_typeid_opequals, "??4bad_typeid@@QAEAAV0@ABV0@@Z");
213     SET(pbad_typeid_what, "?what@exception@@UBEPBDXZ");
214     SET(pbad_typeid_vtable, "??_7bad_typeid@@6B@");
215     SET(pbad_typeid_vector_dtor, "??_Ebad_typeid@@UAEPAXI@Z");
216     SET(pbad_typeid_scalar_dtor, "??_Gbad_typeid@@UAEPAXI@Z");
217
218     SETNOFAIL(pbad_cast_ctor, "??0bad_cast@@QAE@ABQBD@Z");
219     if (!pbad_cast_ctor)
220       SET(pbad_cast_ctor, "??0bad_cast@@AAE@PBQBD@Z");
221     SETNOFAIL(pbad_cast_ctor2, "??0bad_cast@@QAE@PBD@Z");
222     SETNOFAIL(pbad_cast_ctor_closure, "??_Fbad_cast@@QAEXXZ");
223     SET(pbad_cast_copy_ctor, "??0bad_cast@@QAE@ABV0@@Z");
224     SET(pbad_cast_dtor, "??1bad_cast@@UAE@XZ");
225     SET(pbad_cast_opequals, "??4bad_cast@@QAEAAV0@ABV0@@Z");
226     SET(pbad_cast_what, "?what@exception@@UBEPBDXZ");
227     SET(pbad_cast_vtable, "??_7bad_cast@@6B@");
228     SET(pbad_cast_vector_dtor, "??_Ebad_cast@@UAEPAXI@Z");
229     SET(pbad_cast_scalar_dtor, "??_Gbad_cast@@UAEPAXI@Z");
230
231     SET(p__non_rtti_object_ctor, "??0__non_rtti_object@@QAE@PBD@Z");
232     SET(p__non_rtti_object_copy_ctor, "??0__non_rtti_object@@QAE@ABV0@@Z");
233     SET(p__non_rtti_object_dtor, "??1__non_rtti_object@@UAE@XZ");
234     SET(p__non_rtti_object_opequals, "??4__non_rtti_object@@QAEAAV0@ABV0@@Z");
235     SET(p__non_rtti_object_what, "?what@exception@@UBEPBDXZ");
236     SET(p__non_rtti_object_vtable, "??_7__non_rtti_object@@6B@");
237     SET(p__non_rtti_object_vector_dtor, "??_E__non_rtti_object@@UAEPAXI@Z");
238     SET(p__non_rtti_object_scalar_dtor, "??_G__non_rtti_object@@UAEPAXI@Z");
239
240     SET(ptype_info_dtor, "??1type_info@@UAE@XZ");
241     SET(ptype_info_raw_name, "?raw_name@type_info@@QBEPBDXZ");
242     SET(ptype_info_name, "?name@type_info@@QBEPBDXZ");
243     SET(ptype_info_before, "?before@type_info@@QBEHABV1@@Z");
244     SET(ptype_info_opequals_equals, "??8type_info@@QBEHABV0@@Z");
245     SET(ptype_info_opnot_equals, "??9type_info@@QBEHABV0@@Z");
246
247     SET(p__RTtypeid, "__RTtypeid");
248     SET(p__RTCastToVoid, "__RTCastToVoid");
249     SET(p__RTDynamicCast, "__RTDynamicCast");
250
251     /* Extremely early versions export logic_error, and crash in RTTI */
252     SETNOFAIL(bAncientVersion, "??0logic_error@@QAE@ABQBD@Z");
253   }
254 }
255
256 static void test_exception(void)
257 {
258   static const char* e_name = "An exception name";
259   char* name;
260   exception e, e2, e3, *pe;
261
262   if (!poperator_new || !poperator_delete ||
263       !pexception_ctor || !pexception_copy_ctor || !pexception_default_ctor ||
264       !pexception_dtor || !pexception_opequals || !pexception_what ||
265       !pexception_vtable || !pexception_vector_dtor || !pexception_scalar_dtor)
266     return;
267
268   /* 'const char*&' ctor */
269   memset(&e, 0, sizeof(e));
270   call_func2(pexception_ctor, &e, &e_name);
271   ok(e.vtable != NULL, "Null exception vtable for e\n");
272   ok(e.name && e.name != e_name && !strcmp(e.name, "An exception name"), "Bad name '%s' for e\n", e.name);
273   ok(e.do_free == 1, "do_free set to %d for e\n", e.do_free);
274
275   /* Copy ctor */
276   memset(&e2, 0, sizeof(e2));
277   call_func2(pexception_copy_ctor, &e2, &e);
278   ok(e2.vtable != NULL, "Null exception vtable for e2\n");
279   ok(e2.name && e2.name != e.name && !strcmp(e2.name, "An exception name"), "Bad exception name for e2\n");
280   ok(e2.do_free == 1, "do_free set to %d for e2\n", e2.do_free);
281
282   /* Default ctor */
283   memset(&e3, 1, sizeof(e3));
284   call_func1(pexception_default_ctor, &e3);
285   ok(e3.vtable != NULL, "Null exception vtable for e3\n");
286   ok(e3.name == NULL, "Bad exception name for e3\n");
287   ok(e3.do_free == 0, "do_free set to %d for e3\n", e3.do_free);
288
289   ok(e.vtable == e2.vtable && e.vtable == e3.vtable, "exception vtables differ!\n");
290
291   /* Test calling the dtors */
292   call_func1(pexception_dtor, &e2);
293   call_func1(pexception_dtor, &e3);
294
295   /* Operator equals */
296   memset(&e2, 0, sizeof(e2));
297   pe = call_func2(pexception_opequals, &e2, &e);
298   ok(e2.vtable != NULL, "Null exception vtable for e2\n");
299   ok(e2.name && e2.name != e.name && !strcmp(e2.name, "An exception name"), "Bad exception name for e2\n");
300   ok(e2.do_free == 1, "do_free set to %d for e2\n", e2.do_free);
301   ok(pe == &e2, "opequals didn't return e2\n");
302
303   /* what() */
304   name = call_func1(pexception_what, &e2);
305   ok(e2.name == name, "Bad exception name from e2::what()\n");
306
307   /* vtable ptr */
308   ok(e2.vtable == pexception_vtable, "Bad vtable for e2\n");
309   call_func1(pexception_dtor, &e2);
310
311   /* new() */
312   pe = poperator_new(sizeof(exception));
313   ok(pe != NULL, "new() failed\n");
314   if (pe)
315   {
316     call_func2(pexception_ctor, pe, &e_name);
317     /* scalar dtor */
318     call_func2(pexception_scalar_dtor, pe, 0); /* Shouldn't delete pe */
319     pe->name = NULL;
320     pe->do_free = 0;
321     call_func2(pexception_scalar_dtor, pe, 1); /* Should delete pe */
322   }
323
324   pe = poperator_new(sizeof(exception));
325   ok(pe != NULL, "new() failed\n");
326   if (pe)
327   {
328     /* vector dtor, single element */
329     call_func2(pexception_ctor, pe, &e_name);
330     call_func2(pexception_vector_dtor, pe, 1); /* Should delete pe as single element*/
331   }
332
333   pe = poperator_new(sizeof(exception) * 4 + sizeof(int));
334   ok(pe != NULL, "new() failed\n");
335   if (pe)
336   {
337     /* vector dtor, multiple elements */
338     char name[] = "a constant";
339     *((int*)pe) = 3;
340     pe = (exception*)((int*)pe + 1);
341     call_func2(pexception_ctor, &pe[0], &e_name);
342     call_func2(pexception_ctor, &pe[1], &e_name);
343     call_func2(pexception_ctor, &pe[2], &e_name);
344     pe[3].name = name;
345     pe[3].do_free = 1; /* Crash if we try to free this */
346     call_func2(pexception_vector_dtor, pe, 3); /* Should delete all 3 and then pe block */
347   }
348
349   /* test our exported vtable is kosher */
350   pe = (void*)pexception_vtable; /* Use the exception struct to get vtable ptrs */
351   pexception_vector_dtor = (void*)pe->vtable;
352   pexception_what = (void*)pe->name;
353
354   name = call_func1(pexception_what, &e);
355   ok(e.name == name, "Bad exception name from vtable e::what()\n");
356
357   if (p__RTtypeid && !bAncientVersion)
358   {
359     /* Check the rtti */
360     type_info *ti = p__RTtypeid(&e);
361     ok (ti && ti->mangled &&
362         !strcmp(ti->mangled, ".?AVexception@@"), "bad rtti for e\n");
363
364     if (ti)
365     {
366       /* Check the returned type_info has rtti too */
367       type_info *ti2 = p__RTtypeid(ti);
368       ok (ti2 != NULL && !strcmp(ti2->mangled, ".?AVtype_info@@"), "bad rtti for e's type_info\n");
369     }
370   }
371
372   call_func2(pexception_vector_dtor, &e, 0); /* Should delete e.name, but not e */
373 }
374
375 /* This test is basically a cut 'n' paste of the exception test. but it verifies that
376  * bad_typeid works the exact same way... */
377 static void test_bad_typeid(void)
378 {
379   static const char* e_name = "A bad_typeid name";
380   char* name;
381   exception e, e2, e3, *pe;
382
383   if (!poperator_new || !poperator_delete ||
384       !pbad_typeid_ctor || !pbad_typeid_copy_ctor ||
385       !pbad_typeid_dtor || !pbad_typeid_opequals || !pbad_typeid_what ||
386       !pbad_typeid_vtable || !pbad_typeid_vector_dtor || !pbad_typeid_scalar_dtor)
387     return;
388
389   /* 'const char*' ctor */
390   memset(&e, 0, sizeof(e));
391   call_func2(pbad_typeid_ctor, &e, e_name);
392   ok(e.vtable != NULL, "Null bad_typeid vtable for e\n");
393   ok(e.name && e.name != e_name && !strcmp(e.name, "A bad_typeid name"), "Bad name '%s' for e\n", e.name);
394   ok(e.do_free == 1, "do_free set to %d for e\n", e.do_free);
395
396   /* Copy ctor */
397   memset(&e2, 0, sizeof(e2));
398   call_func2(pbad_typeid_copy_ctor, &e2, &e);
399   ok(e2.vtable != NULL, "Null bad_typeid vtable for e2\n");
400   ok(e2.name && e2.name != e.name && !strcmp(e2.name, "A bad_typeid name"), "Bad name '%s' for e2\n", e2.name);
401   ok(e2.do_free == 1, "do_free set to %d for e2\n", e2.do_free);
402
403   /* Ctor closure */
404   if (pbad_typeid_ctor_closure)
405   {
406     memset(&e3, 1, sizeof(e3));
407     call_func1(pbad_typeid_ctor_closure, &e3);
408     ok(e3.vtable != NULL, "Null bad_typeid vtable for e3\n");
409     ok(e3.name && !strcmp(e3.name, "bad typeid"), "Bad bad_typeid name for e3\n");
410     ok(e3.do_free == 1, "do_free set to %d for e3\n", e3.do_free);
411     ok(e.vtable == e3.vtable, "bad_typeid closure vtables differ!\n");
412     call_func1(pbad_typeid_dtor, &e3);
413   }
414   ok(e.vtable == e2.vtable, "bad_typeid vtables differ!\n");
415
416   /* Test calling the dtors */
417   call_func1(pbad_typeid_dtor, &e2);
418
419   /* Operator equals */
420   memset(&e2, 1, sizeof(e2));
421   pe = call_func2(pbad_typeid_opequals, &e2, &e);
422   ok(e2.vtable != NULL, "Null bad_typeid vtable for e2\n");
423   ok(e2.name && e2.name != e.name && !strcmp(e2.name, "A bad_typeid name"), "Bad bad_typeid name for e2\n");
424   ok(e2.do_free == 1, "do_free set to %d for e2\n", e2.do_free);
425   ok(pe == &e2, "opequals didn't return e2\n");
426
427   /* what() */
428   name = call_func1(pbad_typeid_what, &e2);
429   ok(e2.name == name, "Bad bad_typeid name from e2::what()\n");
430
431   /* vtable ptr */
432   ok(e2.vtable == pexception_vtable, "Bad vtable for e2\n");
433   call_func1(pbad_typeid_dtor, &e2);
434
435   /* new() */
436   pe = poperator_new(sizeof(exception));
437   ok(pe != NULL, "new() failed\n");
438   if (pe)
439   {
440     call_func2(pbad_typeid_ctor, pe, e_name);
441     /* scalar dtor */
442     call_func2(pbad_typeid_scalar_dtor, pe, 0); /* Shouldn't delete pe */
443     pe->name = NULL;
444     pe->do_free = 0;
445     call_func2(pbad_typeid_scalar_dtor, pe, 1); /* Should delete pe */
446   }
447
448   pe = poperator_new(sizeof(exception));
449   ok(pe != NULL, "new() failed\n");
450   if (pe)
451   {
452     /* vector dtor, single element */
453     call_func2(pbad_typeid_ctor, pe, e_name);
454     call_func2(pbad_typeid_vector_dtor, pe, 1); /* Should delete pe as single element*/
455   }
456
457   pe = poperator_new(sizeof(exception) * 4 + sizeof(int));
458   ok(pe != NULL, "new() failed\n");
459   if (pe)
460   {
461     /* vector dtor, multiple elements */
462     *((int*)pe) = 3;
463     pe = (exception*)((int*)pe + 1);
464     call_func2(pbad_typeid_ctor, &pe[0], e_name);
465     call_func2(pbad_typeid_ctor, &pe[1], e_name);
466     call_func2(pbad_typeid_ctor, &pe[2], e_name);
467     pe[3].name = 0;
468     pe[3].do_free = 1; /* Crash if we try to free this element */
469     call_func2(pbad_typeid_vector_dtor, pe, 3); /* Should delete all 3 and then pe block */
470   }
471
472   /* test our exported vtable is kosher */
473   pe = (void*)pbad_typeid_vtable; /* Use the exception struct to get vtable ptrs */
474   pbad_typeid_vector_dtor = (void*)pe->vtable;
475   pbad_typeid_what = (void*)pe->name;
476
477   name = call_func1(pbad_typeid_what, &e);
478   ok(e.name == name, "Bad bad_typeid name from vtable e::what()\n");
479
480   if (p__RTtypeid && !bAncientVersion)
481   {
482     /* Check the rtti */
483     type_info *ti = p__RTtypeid(&e);
484     ok (ti != NULL && !strcmp(ti->mangled, ".?AVbad_typeid@@"), "bad rtti for e (%s)\n",
485         !ti ? "null" : ti->mangled);
486   }
487
488   call_func2(pbad_typeid_vector_dtor, &e, 0); /* Should delete e.name, but not e */
489 }
490
491
492 /* Ditto for this test... */
493 static void test_bad_cast(void)
494 {
495   static const char* e_name = "A bad_cast name";
496   char* name;
497   exception e, e2, e3, *pe;
498
499   if (!poperator_new || !poperator_delete ||
500       !pbad_cast_ctor || !pbad_cast_copy_ctor ||
501       !pbad_cast_dtor || !pbad_cast_opequals || !pbad_cast_what ||
502       !pbad_cast_vtable || !pbad_cast_vector_dtor || !pbad_cast_scalar_dtor)
503     return;
504
505   if (pbad_cast_ctor2)
506   {
507     /* 'const char*' ctor */
508     memset(&e, 0, sizeof(e));
509     call_func2(pbad_cast_ctor2, &e, e_name);
510     ok(e.vtable != NULL, "Null bad_cast vtable for e\n");
511     ok(e.name && e.name != e_name && !strcmp(e.name, "A bad_cast name"), "Bad name '%s' for e\n", e.name);
512     ok(e.do_free == 1, "do_free set to %d for e\n", e.do_free);
513     call_func1(pbad_cast_dtor, &e);
514   }
515
516   /* 'const char*&' ctor */
517   memset(&e, 0, sizeof(e));
518   call_func2(pbad_cast_ctor, &e, &e_name);
519   ok(e.vtable != NULL, "Null bad_cast vtable for e\n");
520   ok(e.name && e.name != e_name && !strcmp(e.name, "A bad_cast name"), "Bad name '%s' for e\n", e.name);
521   ok(e.do_free == 1, "do_free set to %d for e\n", e.do_free);
522
523   /* Copy ctor */
524   memset(&e2, 0, sizeof(e2));
525   call_func2(pbad_cast_copy_ctor, &e2, &e);
526   ok(e2.vtable != NULL, "Null bad_cast vtable for e2\n");
527   ok(e2.name && e2.name != e.name && !strcmp(e2.name, "A bad_cast name"), "Bad name '%s' for e2\n", e2.name);
528   ok(e2.do_free == 1, "do_free set to %d for e2\n", e2.do_free);
529
530   /* Ctor closure */
531   if (pbad_cast_ctor_closure)
532   {
533     memset(&e3, 1, sizeof(e3));
534     call_func1(pbad_cast_ctor_closure, &e3);
535     ok(e3.vtable != NULL, "Null bad_cast vtable for e3\n");
536     ok(e3.name && !strcmp(e3.name, "bad cast"), "Bad bad_cast name for e3\n");
537     ok(e3.do_free == 1, "do_free set to %d for e3\n", e3.do_free);
538     ok(e.vtable == e3.vtable, "bad_cast closure vtables differ!\n");
539     call_func1(pbad_cast_dtor, &e3);
540   }
541   ok(e.vtable == e2.vtable, "bad_cast vtables differ!\n");
542
543   /* Test calling the dtors */
544   call_func1(pbad_cast_dtor, &e2);
545
546   /* Operator equals */
547   memset(&e2, 1, sizeof(e2));
548   pe = call_func2(pbad_cast_opequals, &e2, &e);
549   ok(e2.vtable != NULL, "Null bad_cast vtable for e2\n");
550   ok(e2.name && e2.name != e.name && !strcmp(e2.name, "A bad_cast name"), "Bad bad_cast name for e2\n");
551   ok(e2.do_free == 1, "do_free set to %d for e2\n", e2.do_free);
552   ok(pe == &e2, "opequals didn't return e2\n");
553
554   /* what() */
555   name = call_func1(pbad_cast_what, &e2);
556   ok(e2.name == name, "Bad bad_cast name from e2::what()\n");
557
558   /* vtable ptr */
559   ok(e2.vtable == pexception_vtable, "Bad vtable for e2\n");
560   call_func1(pbad_cast_dtor, &e2);
561
562   /* new() */
563   pe = poperator_new(sizeof(exception));
564   ok(pe != NULL, "new() failed\n");
565   if (pe)
566   {
567     call_func2(pbad_cast_ctor, pe, &e_name);
568     /* scalar dtor */
569     call_func2(pbad_cast_scalar_dtor, pe, 0); /* Shouldn't delete pe */
570     pe->name = NULL;
571     pe->do_free = 0;
572     call_func2(pbad_cast_scalar_dtor, pe, 1); /* Should delete pe */
573   }
574
575   pe = poperator_new(sizeof(exception));
576   ok(pe != NULL, "new() failed\n");
577   if (pe)
578   {
579     /* vector dtor, single element */
580     call_func2(pbad_cast_ctor, pe, &e_name);
581     call_func2(pbad_cast_vector_dtor, pe, 1); /* Should delete pe as single element*/
582   }
583
584   pe = poperator_new(sizeof(exception) * 4 + sizeof(int));
585   ok(pe != NULL, "new() failed\n");
586   if (pe)
587   {
588     /* vector dtor, multiple elements */
589     *((int*)pe) = 3;
590     pe = (exception*)((int*)pe + 1);
591     call_func2(pbad_cast_ctor, &pe[0], &e_name);
592     call_func2(pbad_cast_ctor, &pe[1], &e_name);
593     call_func2(pbad_cast_ctor, &pe[2], &e_name);
594     pe[3].name = 0;
595     pe[3].do_free = 1; /* Crash if we try to free this element */
596     call_func2(pbad_cast_vector_dtor, pe, 3); /* Should delete all 3 and then pe block */
597   }
598
599   /* test our exported vtable is kosher */
600   pe = (void*)pbad_cast_vtable; /* Use the exception struct to get vtable ptrs */
601   pbad_cast_vector_dtor = (void*)pe->vtable;
602   pbad_cast_what = (void*)pe->name;
603
604   name = call_func1(pbad_cast_what, &e);
605   ok(e.name == name, "Bad bad_cast name from vtable e::what()\n");
606
607   if (p__RTtypeid && !bAncientVersion)
608   {
609     /* Check the rtti */
610     type_info *ti = p__RTtypeid(&e);
611     ok (ti != NULL && !strcmp(ti->mangled, ".?AVbad_cast@@"), "bad rtti for e\n");
612   }
613   call_func2(pbad_cast_vector_dtor, &e, 0); /* Should delete e.name, but not e */
614 }
615
616 /* ... and this one */
617 static void test___non_rtti_object(void)
618 {
619   static const char* e_name = "A __non_rtti_object name";
620   char* name;
621   exception e, e2, *pe;
622
623   if (!poperator_new || !poperator_delete ||
624       !p__non_rtti_object_ctor || !p__non_rtti_object_copy_ctor ||
625       !p__non_rtti_object_dtor || !p__non_rtti_object_opequals || !p__non_rtti_object_what ||
626       !p__non_rtti_object_vtable || !p__non_rtti_object_vector_dtor || !p__non_rtti_object_scalar_dtor)
627     return;
628
629   /* 'const char*' ctor */
630   memset(&e, 0, sizeof(e));
631   call_func2(p__non_rtti_object_ctor, &e, e_name);
632   ok(e.vtable != NULL, "Null __non_rtti_object vtable for e\n");
633   ok(e.name && e.name != e_name && !strcmp(e.name, "A __non_rtti_object name"), "Bad name '%s' for e\n", e.name);
634   ok(e.do_free == 1, "do_free set to %d for e\n", e.do_free);
635
636   /* Copy ctor */
637   memset(&e2, 0, sizeof(e2));
638   call_func2(p__non_rtti_object_copy_ctor, &e2, &e);
639   ok(e2.vtable != NULL, "Null __non_rtti_object vtable for e2\n");
640   ok(e2.name && e2.name != e.name && !strcmp(e2.name, "A __non_rtti_object name"), "Bad name '%s' for e2\n", e2.name);
641   ok(e2.do_free == 1, "do_free set to %d for e2\n", e2.do_free);
642   ok(e.vtable == e2.vtable, "__non_rtti_object vtables differ!\n");
643
644   /* Test calling the dtors */
645   call_func1(p__non_rtti_object_dtor, &e2);
646
647   /* Operator equals */
648   memset(&e2, 1, sizeof(e2));
649   pe = call_func2(p__non_rtti_object_opequals, &e2, &e);
650   ok(e2.vtable != NULL, "Null __non_rtti_object vtable for e2\n");
651   ok(e2.name && e2.name != e.name && !strcmp(e2.name, "A __non_rtti_object name"), "Bad __non_rtti_object name for e2\n");
652   ok(e2.do_free == 1, "do_free set to %d for e2\n", e2.do_free);
653   ok(pe == &e2, "opequals didn't return e2\n");
654
655   /* what() */
656   name = call_func1(p__non_rtti_object_what, &e2);
657   ok(e2.name == name, "Bad __non_rtti_object name from e2::what()\n");
658
659   /* vtable ptr */
660   ok(e2.vtable == pexception_vtable, "Bad vtable for e2\n");
661   call_func1(p__non_rtti_object_dtor, &e2);
662
663   /* new() */
664   pe = poperator_new(sizeof(exception));
665   ok(pe != NULL, "new() failed\n");
666   if (pe)
667   {
668     call_func2(p__non_rtti_object_ctor, pe, e_name);
669     /* scalar dtor */
670     call_func2(p__non_rtti_object_scalar_dtor, pe, 0); /* Shouldn't delete pe */
671     pe->name = NULL;
672     pe->do_free = 0;
673     call_func2(p__non_rtti_object_scalar_dtor, pe, 1); /* Should delete pe */
674   }
675
676   pe = poperator_new(sizeof(exception));
677   ok(pe != NULL, "new() failed\n");
678   if (pe)
679   {
680     /* vector dtor, single element */
681     call_func2(p__non_rtti_object_ctor, pe, e_name);
682     call_func2(p__non_rtti_object_vector_dtor, pe, 1); /* Should delete pe as single element*/
683   }
684
685   pe = poperator_new(sizeof(exception) * 4 + sizeof(int));
686   ok(pe != NULL, "new() failed\n");
687   if (pe)
688   {
689     /* vector dtor, multiple elements */
690     *((int*)pe) = 3;
691     pe = (exception*)((int*)pe + 1);
692     call_func2(p__non_rtti_object_ctor, &pe[0], e_name);
693     call_func2(p__non_rtti_object_ctor, &pe[1], e_name);
694     call_func2(p__non_rtti_object_ctor, &pe[2], e_name);
695     pe[3].name = 0;
696     pe[3].do_free = 1; /* Crash if we try to free this element */
697     call_func2(p__non_rtti_object_vector_dtor, pe, 3); /* Should delete all 3 and then pe block */
698   }
699
700   /* test our exported vtable is kosher */
701   pe = (void*)p__non_rtti_object_vtable; /* Use the exception struct to get vtable ptrs */
702   p__non_rtti_object_vector_dtor = (void*)pe->vtable;
703   p__non_rtti_object_what = (void*)pe->name;
704
705   name = call_func1(p__non_rtti_object_what, &e);
706   ok(e.name == name, "Bad __non_rtti_object name from vtable e::what()\n");
707
708   if (p__RTtypeid && !bAncientVersion)
709   {
710     /* Check the rtti */
711     type_info *ti = p__RTtypeid(&e);
712     ok (ti != NULL && !strcmp(ti->mangled, ".?AV__non_rtti_object@@"), "bad rtti for e\n");
713   }
714   call_func2(p__non_rtti_object_vector_dtor, &e, 0); /* Should delete e.name, but not e */
715 }
716
717
718 static void test_type_info(void)
719 {
720   static type_info t1 = { NULL, NULL,{'.','?','A','V','t','e','s','t','1','@','@',0,0,0,0,0 } };
721   static type_info t1_1 = { NULL, NULL,{'?','?','A','V','t','e','s','t','1','@','@',0,0,0,0,0 } };
722   static type_info t2 = { NULL, NULL, {'.','?','A','V','t','e','s','t','2','@','@',0,0,0,0,0 } };
723   char* name;
724   int res;
725
726   if (!pmalloc || !pfree || !ptype_info_dtor || !ptype_info_raw_name ||
727       !ptype_info_name || !ptype_info_before ||
728       !ptype_info_opequals_equals || !ptype_info_opnot_equals)
729     return;
730
731   /* Test calling the dtors */
732   call_func1(ptype_info_dtor, &t1); /* No effect, since name is NULL */
733   t1.name = pmalloc(64);
734   strcpy(t1.name, "foo");
735   call_func1(ptype_info_dtor, &t1); /* Frees t1.name using 'free' */
736
737   /* raw_name */
738   t1.name = NULL;
739   name = call_func1(ptype_info_raw_name, &t1);
740
741   /* FIXME: This fails on native; it shouldn't though - native bug?
742    * ok(name && !strcmp(name, t1.mangled), "bad raw_name '%s' for t1 (expected '%s')\n", name, t1.mangled);
743    */
744   ok(t1.name == NULL, "raw_name() set name for t1\n");
745
746   /* name */
747   t1.name = NULL;
748   name = call_func1(ptype_info_name, &t1);
749   ok(name && t1.name && !strcmp(name, t1.name), "bad name '%s' for t1\n", name);
750
751   todo_wine
752   {
753     /* Demangling doesn't work yet, since __unDName() is a stub */
754     ok(t1.name && !strcmp(t1.name, "class test1"), "demangled to '%s' for t1\n", t1.name);
755   }
756   call_func1(ptype_info_dtor, &t1);
757
758   /* before */
759   t1.name = NULL;
760   res = (int)call_func2(ptype_info_before, &t1, &t1);
761   ok(res == 0, "expected 0, got %d\n", res);
762   res = (int)call_func2(ptype_info_before, &t2, &t1);
763   ok(res == 0, "expected 0, got %d\n", res);
764   res = (int)call_func2(ptype_info_before, &t1, &t2);
765   ok(res == 1, "expected 1, got %d\n", res);
766   /* Doesn't check first char */
767   res = (int)call_func2(ptype_info_before, &t1, &t1_1);
768   ok(res == 0, "expected 0, got %d\n", res);
769
770   /* opequals_equals */
771   t1.name = NULL;
772   res = (int)call_func2(ptype_info_opequals_equals, &t1, &t1);
773   ok(res == 1, "expected 1, got %d\n", res);
774   res = (int)call_func2(ptype_info_opequals_equals, &t1, &t2);
775   ok(res == 0, "expected 0, got %d\n", res);
776   res = (int)call_func2(ptype_info_opequals_equals, &t2, &t1);
777   ok(res == 0, "expected 0, got %d\n", res);
778
779   /* opnot_equals */
780   t1.name = NULL;
781   res = (int)call_func2(ptype_info_opnot_equals, &t1, &t1);
782   ok(res == 0, "expected 0, got %d\n", res);
783   res = (int)call_func2(ptype_info_opnot_equals, &t1, &t2);
784   ok(res == 1, "expected 1, got %d\n", res);
785   res = (int)call_func2(ptype_info_opnot_equals, &t2, &t1);
786   ok(res == 1, "expected 1, got %d\n", res);
787 }
788
789 /* Test RTTI functions */
790 static void test_rtti(void)
791 {
792   static const char* e_name = "name";
793   type_info *ti,*bti;
794   exception e,b;
795   void *casted;
796
797   if (bAncientVersion ||
798       !p__RTCastToVoid || !p__RTtypeid || !pexception_ctor || !pbad_typeid_ctor || !p__RTDynamicCast)
799     return;
800
801   call_func2(pexception_ctor, &e, &e_name);
802   call_func2(pbad_typeid_ctor, &b, e_name);
803
804   /* dynamic_cast to void* */
805   casted = p__RTCastToVoid(&e);
806   ok (casted == (void*)&e, "failed cast to void\n");
807
808   /* dynamic_cast up */
809   ti = p__RTtypeid(&e);
810   bti = p__RTtypeid(&b);
811
812   casted = p__RTDynamicCast(&b, 0, NULL, ti, 0);
813   ok (casted == (void*)&b, "failed cast from bad_cast to exception\n");
814
815   /* dynamic_cast down */
816   casted = p__RTDynamicCast(&e, 0, NULL, bti, 0);
817   ok (casted == NULL, "Cast succeeded\n");
818 }
819
820 START_TEST(cpp)
821 {
822   InitFunctionPtrs();
823
824   test_exception();
825   test_bad_typeid();
826   test_bad_cast();
827   test___non_rtti_object();
828   test_type_info();
829   test_rtti();
830
831   if (hMsvcrt)
832     FreeLibrary(hMsvcrt);
833 }
834 #endif /* __i386__ */