propsys: Implement prop variant integer conversions with tests.
[wine] / dlls / msvcp100 / exception.c
1 /*
2  * Copyright 2010 Piotr Caban for CodeWeavers
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17  */
18
19 #include "config.h"
20
21 #include <stdarg.h>
22
23 #include "msvcp.h"
24
25 #include "windef.h"
26 #include "winbase.h"
27 #include "wine/debug.h"
28 WINE_DEFAULT_DEBUG_CHANNEL(msvcp);
29
30 /* dlls/msvcrt/cppexcept.h */
31 typedef void (*cxx_copy_ctor)(void);
32
33 /* complete information about a C++ type */
34 typedef struct __cxx_type_info
35 {
36     UINT             flags;        /* flags (see CLASS_* flags below) */
37     const type_info *type_info;    /* C++ type info */
38     this_ptr_offsets offsets;      /* offsets for computing the this pointer */
39     unsigned int     size;         /* object size */
40     cxx_copy_ctor    copy_ctor;    /* copy constructor */
41 } cxx_type_info;
42 #define CLASS_IS_SIMPLE_TYPE          1
43 #define CLASS_HAS_VIRTUAL_BASE_CLASS  4
44
45 /* table of C++ types that apply for a given object */
46 typedef struct __cxx_type_info_table
47 {
48     UINT                 count;     /* number of types */
49     const cxx_type_info *info[3];   /* variable length, we declare it large enough for static RTTI */
50 } cxx_type_info_table;
51
52 /* type information for an exception object */
53 typedef struct __cxx_exception_type
54 {
55     UINT                       flags;            /* TYPE_FLAG flags */
56     void                     (*destructor)(void);/* exception object destructor */
57     void* /*cxx_exc_custom_handler*/ custom_handler;   /* custom handler for this exception */
58     const cxx_type_info_table *type_info_table;  /* list of types for this exception object */
59 } cxx_exception_type;
60
61 void WINAPI _CxxThrowException(exception*,const cxx_exception_type*);
62
63 /* vtables */
64 extern const vtable_ptr MSVCP_exception_vtable;
65 extern const vtable_ptr MSVCP_bad_alloc_vtable;
66 extern const vtable_ptr MSVCP_logic_error_vtable;
67 extern const vtable_ptr MSVCP_length_error_vtable;
68 extern const vtable_ptr MSVCP_out_of_range_vtable;
69 extern const vtable_ptr MSVCP_invalid_argument_vtable;
70 extern const vtable_ptr MSVCP_runtime_error_vtable;
71 extern const vtable_ptr MSVCP_failure_vtable;
72
73 static void MSVCP_type_info_dtor(type_info * _this)
74 {
75     free(_this->name);
76 }
77
78 /* Unexported */
79 DEFINE_THISCALL_WRAPPER(MSVCP_type_info_vector_dtor,8)
80 void * __thiscall MSVCP_type_info_vector_dtor(type_info * _this, unsigned int flags)
81 {
82     TRACE("(%p %x)\n", _this, flags);
83     if (flags & 2)
84     {
85         /* we have an array, with the number of elements stored before the first object */
86         INT_PTR i, *ptr = (INT_PTR *)_this - 1;
87
88         for (i = *ptr - 1; i >= 0; i--) MSVCP_type_info_dtor(_this + i);
89         MSVCRT_operator_delete(ptr);
90     }
91     else
92     {
93         MSVCP_type_info_dtor(_this);
94         if (flags & 1) MSVCRT_operator_delete(_this);
95     }
96     return _this;
97 }
98
99 DEFINE_RTTI_DATA0( type_info, 0, ".?AVtype_info@@" );
100
101 DEFINE_THISCALL_WRAPPER(MSVCP_exception_ctor, 8)
102 exception* __thiscall MSVCP_exception_ctor(exception *this, const char **name)
103 {
104     TRACE("(%p %s)\n", this, *name);
105
106     this->vtable = &MSVCP_exception_vtable;
107     if(*name) {
108         unsigned int name_len = strlen(*name) + 1;
109         this->name = malloc(name_len);
110         memcpy(this->name, *name, name_len);
111         this->do_free = TRUE;
112     } else {
113         this->name = NULL;
114         this->do_free = FALSE;
115     }
116     return this;
117 }
118
119 DEFINE_THISCALL_WRAPPER(MSVCP_exception_copy_ctor,8)
120 exception* __thiscall MSVCP_exception_copy_ctor(exception *this, const exception *rhs)
121 {
122     TRACE("(%p,%p)\n", this, rhs);
123
124     if(!rhs->do_free) {
125         this->vtable = &MSVCP_exception_vtable;
126         this->name = rhs->name;
127         this->do_free = FALSE;
128     } else
129         MSVCP_exception_ctor(this, (const char**)&rhs->name);
130     TRACE("name = %s\n", this->name);
131     return this;
132 }
133
134 DEFINE_THISCALL_WRAPPER(MSVCP_exception_dtor,4)
135 void __thiscall MSVCP_exception_dtor(exception *this)
136 {
137     TRACE("(%p)\n", this);
138     this->vtable = &MSVCP_exception_vtable;
139     if(this->do_free)
140         free(this->name);
141 }
142
143 DEFINE_THISCALL_WRAPPER(MSVCP_exception_vector_dtor, 8)
144 void * __thiscall MSVCP_exception_vector_dtor(exception *this, unsigned int flags)
145 {
146     TRACE("%p %x\n", this, flags);
147     if(flags & 2) {
148         /* we have an array, with the number of elements stored before the first object */
149         INT_PTR i, *ptr = (INT_PTR *)this-1;
150
151         for(i=*ptr-1; i>=0; i--)
152             MSVCP_exception_dtor(this+i);
153         MSVCRT_operator_delete(ptr);
154     } else {
155         MSVCP_exception_dtor(this);
156         if(flags & 1)
157             MSVCRT_operator_delete(this);
158     }
159
160     return this;
161 }
162
163 DEFINE_RTTI_DATA0(exception, 0, ".?AVexception@std@@");
164
165 static const cxx_type_info exception_cxx_type_info = {
166     0,
167     &exception_type_info,
168     { 0, -1, 0 },
169     sizeof(exception),
170     (cxx_copy_ctor)THISCALL(MSVCP_exception_dtor)
171 };
172
173 static const cxx_type_info_table exception_cxx_type_table = {
174     1,
175     {
176         &exception_cxx_type_info,
177         NULL,
178         NULL
179     }
180 };
181
182 static const cxx_exception_type exception_cxx_type = {
183     0,
184     (cxx_copy_ctor)THISCALL(MSVCP_exception_copy_ctor),
185     NULL,
186     &exception_cxx_type_table
187 };
188
189 /* bad_alloc class data */
190 typedef exception bad_alloc;
191
192 DEFINE_THISCALL_WRAPPER(MSVCP_bad_alloc_ctor, 8)
193 bad_alloc* __thiscall MSVCP_bad_alloc_ctor(bad_alloc *this, const char **name)
194 {
195     TRACE("%p %s\n", this, *name);
196     MSVCP_exception_ctor(this, name);
197     this->vtable = &MSVCP_bad_alloc_vtable;
198     return this;
199 }
200
201 DEFINE_THISCALL_WRAPPER(MSVCP_bad_alloc_copy_ctor, 8)
202 bad_alloc* __thiscall MSVCP_bad_alloc_copy_ctor(bad_alloc *this, const bad_alloc *rhs)
203 {
204     TRACE("%p %p\n", this, rhs);
205     MSVCP_exception_copy_ctor(this, rhs);
206     this->vtable = &MSVCP_bad_alloc_vtable;
207     return this;
208 }
209
210 DEFINE_THISCALL_WRAPPER(MSVCP_bad_alloc_dtor, 4)
211 void __thiscall MSVCP_bad_alloc_dtor(bad_alloc *this)
212 {
213     TRACE("%p\n", this);
214     MSVCP_exception_dtor(this);
215 }
216
217 DEFINE_THISCALL_WRAPPER(MSVCP_bad_alloc_vector_dtor, 8)
218 void * __thiscall MSVCP_bad_alloc_vector_dtor(bad_alloc *this, unsigned int flags)
219 {
220     TRACE("%p %x\n", this, flags);
221     if(flags & 2) {
222         /* we have an array, with the number of elements stored before the first object */
223         INT_PTR i, *ptr = (INT_PTR *)this-1;
224
225         for(i=*ptr-1; i>=0; i--)
226             MSVCP_bad_alloc_dtor(this+i);
227         MSVCRT_operator_delete(ptr);
228     } else {
229         MSVCP_bad_alloc_dtor(this);
230         if(flags & 1)
231             MSVCRT_operator_delete(this);
232     }
233
234     return this;
235 }
236
237 DEFINE_THISCALL_WRAPPER(MSVCP_what_exception,4)
238 const char* __thiscall MSVCP_what_exception(exception * this)
239 {
240     TRACE("(%p) returning %s\n", this, this->name);
241     return this->name ? this->name : "Unknown exception";
242 }
243
244 DEFINE_RTTI_DATA1(bad_alloc, 0, &exception_rtti_base_descriptor, ".?AVbad_alloc@std@@");
245
246 static const cxx_type_info bad_alloc_cxx_type_info = {
247     0,
248     &bad_alloc_type_info,
249     { 0, -1, 0 },
250     sizeof(bad_alloc),
251     (cxx_copy_ctor)THISCALL(MSVCP_bad_alloc_copy_ctor)
252 };
253
254 static const cxx_type_info_table bad_alloc_cxx_type_table = {
255     2,
256     {
257         &bad_alloc_cxx_type_info,
258         &exception_cxx_type_info,
259         NULL
260     }
261 };
262
263 static const cxx_exception_type bad_alloc_cxx_type = {
264     0,
265     (cxx_copy_ctor)THISCALL(MSVCP_bad_alloc_dtor),
266     NULL,
267     &bad_alloc_cxx_type_table
268 };
269
270 /* logic_error class data */
271 typedef struct _logic_error {
272     exception e;
273     basic_string_char str;
274 } logic_error;
275
276 DEFINE_THISCALL_WRAPPER(MSVCP_logic_error_ctor, 8)
277 logic_error* __thiscall MSVCP_logic_error_ctor(
278         logic_error *this, const char **name)
279 {
280     TRACE("%p %s\n", this, *name);
281     this->e.vtable = &MSVCP_logic_error_vtable;
282     this->e.name = NULL;
283     this->e.do_free = FALSE;
284     MSVCP_basic_string_char_ctor_cstr(&this->str, *name);
285     return this;
286 }
287
288 DEFINE_THISCALL_WRAPPER(MSVCP_logic_error_copy_ctor, 8)
289 logic_error* __thiscall MSVCP_logic_error_copy_ctor(
290         logic_error *this, logic_error *rhs)
291 {
292     TRACE("%p %p\n", this, rhs);
293     MSVCP_exception_copy_ctor(&this->e, &rhs->e);
294     MSVCP_basic_string_char_copy_ctor(&this->str, &rhs->str);
295     this->e.vtable = &MSVCP_logic_error_vtable;
296     return this;
297 }
298
299 DEFINE_THISCALL_WRAPPER(MSVCP_logic_error_dtor, 4)
300 void __thiscall MSVCP_logic_error_dtor(logic_error *this)
301 {
302     TRACE("%p\n", this);
303     MSVCP_exception_dtor(&this->e);
304     MSVCP_basic_string_char_dtor(&this->str);
305 }
306
307 DEFINE_THISCALL_WRAPPER(MSVCP_logic_error_vector_dtor, 8)
308 void* __thiscall MSVCP_logic_error_vector_dtor(
309         logic_error *this, unsigned int flags)
310 {
311     TRACE("%p %x\n", this, flags);
312     if(flags & 2) {
313         /* we have an array, with the number of elements stored before the first object */
314         INT_PTR i, *ptr = (INT_PTR *)this-1;
315
316         for(i=*ptr-1; i>=0; i--)
317             MSVCP_logic_error_dtor(this+i);
318         MSVCRT_operator_delete(ptr);
319     } else {
320         MSVCP_logic_error_dtor(this);
321         if(flags & 1)
322             MSVCRT_operator_delete(this);
323     }
324
325     return this;
326 }
327
328 DEFINE_THISCALL_WRAPPER(MSVCP_logic_error_what, 4)
329 const char* __thiscall MSVCP_logic_error_what(logic_error *this)
330 {
331     TRACE("%p\n", this);
332     return MSVCP_basic_string_char_c_str(&this->str);
333 }
334
335 DEFINE_RTTI_DATA1(logic_error, 0, &exception_rtti_base_descriptor, ".?AVlogic_error@std@@");
336
337 static const cxx_type_info logic_error_cxx_type_info = {
338     0,
339     &logic_error_type_info,
340     { 0, -1, 0 },
341     sizeof(logic_error),
342     (cxx_copy_ctor)THISCALL(MSVCP_logic_error_copy_ctor)
343 };
344
345 static const cxx_type_info_table logic_error_cxx_type_table = {
346     2,
347     {
348         &logic_error_cxx_type_info,
349         &exception_cxx_type_info,
350         NULL
351     }
352 };
353
354 static const cxx_exception_type logic_error_cxx_type = {
355     0,
356     (cxx_copy_ctor)THISCALL(MSVCP_logic_error_dtor),
357     NULL,
358     &logic_error_cxx_type_table
359 };
360
361 /* length_error class data */
362 typedef logic_error length_error;
363
364 DEFINE_THISCALL_WRAPPER(MSVCP_length_error_ctor, 8)
365 length_error* __thiscall MSVCP_length_error_ctor(
366         length_error *this, const char **name)
367 {
368     TRACE("%p %s\n", this, *name);
369     MSVCP_logic_error_ctor(this, name);
370     this->e.vtable = &MSVCP_length_error_vtable;
371     return this;
372 }
373
374 DEFINE_THISCALL_WRAPPER(MSVCP_length_error_copy_ctor, 8)
375 length_error* __thiscall MSVCP_length_error_copy_ctor(
376         length_error *this, length_error *rhs)
377 {
378     TRACE("%p %p\n", this, rhs);
379     MSVCP_logic_error_copy_ctor(this, rhs);
380     this->e.vtable = &MSVCP_length_error_vtable;
381     return this;
382 }
383
384 DEFINE_RTTI_DATA2(length_error, 0, &logic_error_rtti_base_descriptor, &exception_rtti_base_descriptor, ".?AVlength_error@std@@");
385
386 static const cxx_type_info length_error_cxx_type_info = {
387     0,
388     &length_error_type_info,
389     { 0, -1, 0 },
390     sizeof(length_error),
391     (cxx_copy_ctor)THISCALL(MSVCP_length_error_copy_ctor)
392 };
393
394 static const cxx_type_info_table length_error_cxx_type_table = {
395     3,
396     {
397         &length_error_cxx_type_info,
398         &logic_error_cxx_type_info,
399         &exception_cxx_type_info
400     }
401 };
402
403 static const cxx_exception_type length_error_cxx_type = {
404     0,
405     (cxx_copy_ctor)THISCALL(MSVCP_logic_error_dtor),
406     NULL,
407     &length_error_cxx_type_table
408 };
409
410 /* out_of_range class data */
411 typedef logic_error out_of_range;
412
413 DEFINE_THISCALL_WRAPPER(MSVCP_out_of_range_ctor, 8)
414 out_of_range* __thiscall MSVCP_out_of_range_ctor(
415         out_of_range *this, const char **name)
416 {
417     TRACE("%p %s\n", this, *name);
418     MSVCP_logic_error_ctor(this, name);
419     this->e.vtable = &MSVCP_out_of_range_vtable;
420     return this;
421 }
422
423 DEFINE_THISCALL_WRAPPER(MSVCP_out_of_range_copy_ctor, 8)
424 out_of_range* __thiscall MSVCP_out_of_range_copy_ctor(
425         out_of_range *this, out_of_range *rhs)
426 {
427     TRACE("%p %p\n", this, rhs);
428     MSVCP_logic_error_copy_ctor(this, rhs);
429     this->e.vtable = &MSVCP_out_of_range_vtable;
430     return this;
431 }
432
433 DEFINE_RTTI_DATA2(out_of_range, 0, &logic_error_rtti_base_descriptor, &exception_rtti_base_descriptor, ".?AVout_of_range@std@@");
434
435 static const cxx_type_info out_of_range_cxx_type_info = {
436     0,
437     &out_of_range_type_info,
438     { 0, -1, 0 },
439     sizeof(out_of_range),
440     (cxx_copy_ctor)THISCALL(MSVCP_out_of_range_copy_ctor)
441 };
442
443 static const cxx_type_info_table out_of_range_cxx_type_table = {
444     3,
445     {
446         &out_of_range_cxx_type_info,
447         &logic_error_cxx_type_info,
448         &exception_cxx_type_info
449     }
450 };
451
452 static const cxx_exception_type out_of_range_cxx_type = {
453     0,
454     (cxx_copy_ctor)THISCALL(MSVCP_logic_error_dtor),
455     NULL,
456     &out_of_range_cxx_type_table
457 };
458
459 /* invalid_argument class data */
460 typedef logic_error invalid_argument;
461
462 DEFINE_THISCALL_WRAPPER(MSVCP_invalid_argument_ctor, 8)
463 invalid_argument* __thiscall MSVCP_invalid_argument_ctor(
464         invalid_argument *this, const char **name)
465 {
466     TRACE("%p %s\n", this, *name);
467     MSVCP_logic_error_ctor(this, name);
468     this->e.vtable = &MSVCP_invalid_argument_vtable;
469     return this;
470 }
471
472 DEFINE_THISCALL_WRAPPER(MSVCP_invalid_argument_copy_ctor, 8)
473 invalid_argument* __thiscall MSVCP_invalid_argument_copy_ctor(
474         invalid_argument *this, invalid_argument *rhs)
475 {
476     TRACE("%p %p\n", this, rhs);
477     MSVCP_logic_error_copy_ctor(this, rhs);
478     this->e.vtable = &MSVCP_invalid_argument_vtable;
479     return this;
480 }
481
482 DEFINE_RTTI_DATA2(invalid_argument, 0, &logic_error_rtti_base_descriptor, &exception_rtti_base_descriptor, ".?AVinvalid_argument@std@@");
483
484 static const cxx_type_info invalid_argument_cxx_type_info = {
485     0,
486     &invalid_argument_type_info,
487     { 0, -1, 0 },
488     sizeof(invalid_argument),
489     (cxx_copy_ctor)THISCALL(MSVCP_invalid_argument_copy_ctor)
490 };
491
492 static const cxx_type_info_table invalid_argument_cxx_type_table = {
493     3,
494     {
495         &invalid_argument_cxx_type_info,
496         &logic_error_cxx_type_info,
497         &exception_cxx_type_info
498     }
499 };
500
501 static const cxx_exception_type invalid_argument_cxx_type = {
502     0,
503     (cxx_copy_ctor)THISCALL(MSVCP_logic_error_dtor),
504     NULL,
505     &invalid_argument_cxx_type_table
506 };
507
508 /* runtime_error class data */
509 typedef struct {
510     exception e;
511     basic_string_char str;
512 } runtime_error;
513
514 DEFINE_THISCALL_WRAPPER(MSVCP_runtime_error_ctor, 8)
515 runtime_error* __thiscall MSVCP_runtime_error_ctor(
516         runtime_error *this, const char **name)
517 {
518     TRACE("%p %s\n", this, *name);
519     this->e.vtable = &MSVCP_runtime_error_vtable;
520     this->e.name = NULL;
521     this->e.do_free = FALSE;
522     MSVCP_basic_string_char_ctor_cstr(&this->str, *name);
523     return this;
524 }
525
526 DEFINE_THISCALL_WRAPPER(MSVCP_runtime_error_copy_ctor, 8)
527 runtime_error* __thiscall MSVCP_runtime_error_copy_ctor(
528         runtime_error *this, runtime_error *rhs)
529 {
530     TRACE("%p %p\n", this, rhs);
531     MSVCP_exception_copy_ctor(&this->e, &rhs->e);
532     MSVCP_basic_string_char_copy_ctor(&this->str, &rhs->str);
533     this->e.vtable = &MSVCP_runtime_error_vtable;
534     return this;
535 }
536
537 DEFINE_THISCALL_WRAPPER(MSVCP_runtime_error_dtor, 4)
538 void __thiscall MSVCP_runtime_error_dtor(runtime_error *this)
539 {
540     TRACE("%p\n", this);
541     MSVCP_exception_dtor(&this->e);
542     MSVCP_basic_string_char_dtor(&this->str);
543 }
544
545 DEFINE_THISCALL_WRAPPER(MSVCP_runtime_error_vector_dtor, 8)
546 void* __thiscall MSVCP_runtime_error_vector_dtor(
547         runtime_error *this, unsigned int flags)
548 {
549     TRACE("%p %x\n", this, flags);
550     if(flags & 2) {
551         /* we have an array, with the number of elements stored before the first object */
552         INT_PTR i, *ptr = (INT_PTR *)this-1;
553
554         for(i=*ptr-1; i>=0; i--)
555             MSVCP_runtime_error_dtor(this+i);
556         MSVCRT_operator_delete(ptr);
557     } else {
558         MSVCP_runtime_error_dtor(this);
559         if(flags & 1)
560             MSVCRT_operator_delete(this);
561     }
562
563     return this;
564 }
565
566 DEFINE_THISCALL_WRAPPER(MSVCP_runtime_error_what, 4)
567 const char* __thiscall MSVCP_runtime_error_what(runtime_error *this)
568 {
569     TRACE("%p\n", this);
570     return MSVCP_basic_string_char_c_str(&this->str);
571 }
572
573 DEFINE_RTTI_DATA1(runtime_error, 0, &exception_rtti_base_descriptor, ".?AVruntime_error@std@@");
574
575 static const cxx_type_info runtime_error_cxx_type_info = {
576     0,
577     &runtime_error_type_info,
578     { 0, -1, 0 },
579     sizeof(runtime_error),
580     (cxx_copy_ctor)THISCALL(MSVCP_runtime_error_copy_ctor)
581 };
582
583 static const cxx_type_info_table runtime_error_cxx_type_table = {
584     2,
585     {
586         &runtime_error_cxx_type_info,
587         &exception_cxx_type_info,
588         NULL
589     }
590 };
591
592 static const cxx_exception_type runtime_error_cxx_type = {
593     0,
594     (cxx_copy_ctor)THISCALL(MSVCP_runtime_error_dtor),
595     NULL,
596     &runtime_error_cxx_type_table
597 };
598
599 /* failure class data */
600 typedef runtime_error failure;
601
602 DEFINE_THISCALL_WRAPPER(MSVCP_failure_ctor, 8)
603 failure* __thiscall MSVCP_failure_ctor(
604         failure *this, const char **name)
605 {
606     TRACE("%p %s\n", this, *name);
607     MSVCP_runtime_error_ctor(this, name);
608     this->e.vtable = &MSVCP_failure_vtable;
609     return this;
610 }
611
612 DEFINE_THISCALL_WRAPPER(MSVCP_failure_copy_ctor, 8)
613 failure* __thiscall MSVCP_failure_copy_ctor(
614         failure *this, failure *rhs)
615 {
616     TRACE("%p %p\n", this, rhs);
617     MSVCP_runtime_error_copy_ctor(this, rhs);
618     this->e.vtable = &MSVCP_failure_vtable;
619     return this;
620 }
621
622 DEFINE_THISCALL_WRAPPER(MSVCP_failure_dtor, 4)
623 void __thiscall MSVCP_failure_dtor(failure *this)
624 {
625     TRACE("%p\n", this);
626     MSVCP_runtime_error_dtor(this);
627 }
628
629 DEFINE_THISCALL_WRAPPER(MSVCP_failure_vector_dtor, 8)
630 void* __thiscall MSVCP_failure_vector_dtor(
631         failure *this, unsigned int flags)
632 {
633     TRACE("%p %x\n", this, flags);
634     return MSVCP_runtime_error_vector_dtor(this, flags);
635 }
636
637 DEFINE_THISCALL_WRAPPER(MSVCP_failure_what, 4)
638 const char* __thiscall MSVCP_failure_what(failure *this)
639 {
640     TRACE("%p\n", this);
641     return MSVCP_runtime_error_what(this);
642 }
643
644 DEFINE_RTTI_DATA2(failure, 0, &runtime_error_rtti_base_descriptor, &exception_rtti_base_descriptor, ".?AVfailure@std@@");
645
646 static const cxx_type_info failure_cxx_type_info = {
647     0,
648     &failure_type_info,
649     { 0, -1, 0 },
650     sizeof(failure),
651     (cxx_copy_ctor)THISCALL(MSVCP_failure_copy_ctor)
652 };
653
654 static const cxx_type_info_table failure_cxx_type_table = {
655     3,
656     {
657         &failure_cxx_type_info,
658         &runtime_error_cxx_type_info,
659         &exception_cxx_type_info
660     }
661 };
662
663 static const cxx_exception_type failure_cxx_type = {
664     0,
665     (cxx_copy_ctor)THISCALL(MSVCP_failure_dtor),
666     NULL,
667     &failure_cxx_type_table
668 };
669
670 #ifndef __GNUC__
671 void __asm_dummy_vtables(void) {
672 #endif
673     __ASM_VTABLE(type_info,
674             VTABLE_ADD_FUNC(MSVCP_type_info_vector_dtor));
675     __ASM_VTABLE(exception,
676             VTABLE_ADD_FUNC(MSVCP_exception_vector_dtor)
677             VTABLE_ADD_FUNC(MSVCP_what_exception));
678     __ASM_VTABLE(bad_alloc,
679             VTABLE_ADD_FUNC(MSVCP_bad_alloc_vector_dtor)
680             VTABLE_ADD_FUNC(MSVCP_what_exception));
681     __ASM_VTABLE(logic_error,
682             VTABLE_ADD_FUNC(MSVCP_logic_error_vector_dtor)
683             VTABLE_ADD_FUNC(MSVCP_logic_error_what));
684     __ASM_VTABLE(length_error,
685             VTABLE_ADD_FUNC(MSVCP_logic_error_vector_dtor)
686             VTABLE_ADD_FUNC(MSVCP_logic_error_what));
687     __ASM_VTABLE(out_of_range,
688             VTABLE_ADD_FUNC(MSVCP_logic_error_vector_dtor)
689             VTABLE_ADD_FUNC(MSVCP_logic_error_what));
690     __ASM_VTABLE(invalid_argument,
691             VTABLE_ADD_FUNC(MSVCP_logic_error_vector_dtor)
692             VTABLE_ADD_FUNC(MSVCP_logic_error_what));
693     __ASM_VTABLE(runtime_error,
694             VTABLE_ADD_FUNC(MSVCP_runtime_error_vector_dtor)
695             VTABLE_ADD_FUNC(MSVCP_runtime_error_what));
696     __ASM_VTABLE(failure,
697             VTABLE_ADD_FUNC(MSVCP_failure_vector_dtor)
698             VTABLE_ADD_FUNC(MSVCP_failure_what));
699 #ifndef __GNUC__
700 }
701 #endif
702
703 /* Internal: throws selected exception */
704 void throw_exception(exception_type et, const char *str)
705 {
706     const char *addr = str;
707
708     switch(et) {
709     case EXCEPTION_RERAISE:
710         _CxxThrowException(NULL, NULL);
711     case EXCEPTION: {
712         exception e;
713         MSVCP_exception_ctor(&e, &addr);
714         _CxxThrowException(&e, &exception_cxx_type);
715     }
716     case EXCEPTION_BAD_ALLOC: {
717         bad_alloc e;
718         MSVCP_bad_alloc_ctor(&e, &addr);
719         _CxxThrowException(&e, &bad_alloc_cxx_type);
720     }
721     case EXCEPTION_LOGIC_ERROR: {
722         logic_error e;
723         MSVCP_logic_error_ctor(&e, &addr);
724         _CxxThrowException((exception*)&e, &logic_error_cxx_type);
725     }
726     case EXCEPTION_LENGTH_ERROR: {
727         length_error e;
728         MSVCP_length_error_ctor(&e, &addr);
729         _CxxThrowException((exception*)&e, &length_error_cxx_type);
730     }
731     case EXCEPTION_OUT_OF_RANGE: {
732         out_of_range e;
733         MSVCP_out_of_range_ctor(&e, &addr);
734         _CxxThrowException((exception*)&e, &out_of_range_cxx_type);
735     }
736     case EXCEPTION_INVALID_ARGUMENT: {
737         invalid_argument e;
738         MSVCP_invalid_argument_ctor(&e, &addr);
739         _CxxThrowException((exception*)&e, &invalid_argument_cxx_type);
740     }
741     case EXCEPTION_RUNTIME_ERROR: {
742         runtime_error e;
743         MSVCP_runtime_error_ctor(&e, &addr);
744         _CxxThrowException((exception*)&e, &runtime_error_cxx_type);
745     }
746     case EXCEPTION_FAILURE: {
747         failure e;
748         MSVCP_failure_ctor(&e, &addr);
749         _CxxThrowException((exception*)&e, &failure_cxx_type);
750     }
751     }
752 }
753
754 void init_exception(void *base)
755 {
756 #ifdef __x86_64__
757     init_type_info_rtti(base);
758     init_exception_rtti(base);
759     init_bad_alloc_rtti(base);
760     init_logic_error_rtti(base);
761     init_length_error_rtti(base);
762     init_out_of_range_rtti(base);
763     init_invalid_argument_rtti(base);
764     init_runtime_error_rtti(base);
765     init_failure_rtti(base);
766 #endif
767 }