explorerframe: Mark internal symbols with hidden visibility.
[wine] / dlls / msvcp90 / 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 "msvcp90.h"
24
25 #include "windef.h"
26 #include "winbase.h"
27 #include "wine/debug.h"
28 WINE_DEFAULT_DEBUG_CHANNEL(msvcp90);
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
65 #ifdef _WIN64
66
67 #define __ASM_VTABLE(name,funcs) \
68     __asm__(".data\n" \
69             "\t.align 8\n" \
70             "\t.quad " __ASM_NAME(#name "_rtti") "\n" \
71             "\t.globl " __ASM_NAME("MSVCP_" #name "_vtable") "\n" \
72             __ASM_NAME("MSVCP_" #name "_vtable") ":\n" \
73             "\t.quad " THISCALL_NAME(MSVCP_ ## name ## _vector_dtor) "\n" \
74             funcs "\n\t.text");
75
76 #define __ASM_EXCEPTION_VTABLE(name) \
77     __ASM_VTABLE(name, "\t.quad " THISCALL_NAME(MSVCP_what_exception) )
78
79 #define __ASM_EXCEPTION_STRING_VTABLE(name) \
80     __ASM_VTABLE(name, "\t.quad " THISCALL_NAME(MSVCP_logic_error_what) )
81
82 #else
83
84 #define __ASM_VTABLE(name,funcs) \
85     __asm__(".data\n" \
86             "\t.align 4\n" \
87             "\t.long " __ASM_NAME(#name "_rtti") "\n" \
88             "\t.globl " __ASM_NAME("MSVCP_" #name "_vtable") "\n" \
89             __ASM_NAME("MSVCP_" #name "_vtable") ":\n" \
90             "\t.long " THISCALL_NAME(MSVCP_ ## name ## _vector_dtor) "\n" \
91             funcs "\n\t.text");
92
93 #define __ASM_EXCEPTION_VTABLE(name) \
94     __ASM_VTABLE(name, "\t.long " THISCALL_NAME(MSVCP_what_exception) )
95
96 #define __ASM_EXCEPTION_STRING_VTABLE(name) \
97     __ASM_VTABLE(name, "\t.long " THISCALL_NAME(MSVCP_logic_error_what) )
98
99 #endif /* _WIN64 */
100
101 extern const vtable_ptr MSVCP_bad_alloc_vtable;
102 extern const vtable_ptr MSVCP_logic_error_vtable;
103 extern const vtable_ptr MSVCP_length_error_vtable;
104 extern const vtable_ptr MSVCP_out_of_range_vtable;
105 extern const vtable_ptr MSVCP_invalid_argument_vtable;
106
107 /* exception class data */
108 static type_info exception_type_info = {
109     NULL, /* set by set_exception_vtable */
110     NULL,
111     ".?AVexception@std@@"
112 };
113
114 DEFINE_THISCALL_WRAPPER(MSVCP_exception_ctor, 8)
115 exception* __thiscall MSVCP_exception_ctor(exception *this, const char **name)
116 {
117     TRACE("(%p %s)\n", this, *name);
118
119     this->vtable = exception_type_info.vtable;
120     if(*name) {
121         unsigned int name_len = strlen(*name) + 1;
122         this->name = malloc(name_len);
123         memcpy(this->name, *name, name_len);
124         this->do_free = TRUE;
125     } else {
126         this->name = NULL;
127         this->do_free = FALSE;
128     }
129     return this;
130 }
131
132 DEFINE_THISCALL_WRAPPER(MSVCP_exception_copy_ctor,8)
133 exception* __thiscall MSVCP_exception_copy_ctor(exception *this, const exception *rhs)
134 {
135     TRACE("(%p,%p)\n", this, rhs);
136
137     if(!rhs->do_free) {
138         this->vtable = exception_type_info.vtable;
139         this->name = rhs->name;
140         this->do_free = FALSE;
141     } else
142         MSVCP_exception_ctor(this, (const char**)&rhs->name);
143     TRACE("name = %s\n", this->name);
144     return this;
145 }
146
147 DEFINE_THISCALL_WRAPPER(MSVCP_exception_dtor,4)
148 void __thiscall MSVCP_exception_dtor(exception *this)
149 {
150     TRACE("(%p)\n", this);
151     this->vtable = exception_type_info.vtable;
152     if(this->do_free)
153         free(this->name);
154 }
155
156 static const rtti_base_descriptor exception_rtti_base_descriptor = {
157     &exception_type_info,
158     0,
159     { 0, -1, 0 },
160     0
161 };
162
163 static const cxx_type_info exception_cxx_type_info = {
164     0,
165     &exception_type_info,
166     { 0, -1, 0 },
167     sizeof(exception),
168     (cxx_copy_ctor)THISCALL(MSVCP_exception_dtor)
169 };
170
171 static const cxx_type_info_table exception_cxx_type_table = {
172     1,
173     {
174         &exception_cxx_type_info,
175         NULL,
176         NULL
177     }
178 };
179
180 static const cxx_exception_type exception_cxx_type = {
181     0,
182     (cxx_copy_ctor)THISCALL(MSVCP_exception_copy_ctor),
183     NULL,
184     &exception_cxx_type_table
185 };
186
187 void set_exception_vtable(void)
188 {
189     HMODULE hmod = GetModuleHandleA("msvcrt.dll");
190     exception_type_info.vtable = (void*)GetProcAddress(hmod, "??_7exception@@6B@");
191 }
192
193 /* bad_alloc class data */
194 typedef exception bad_alloc;
195
196 DEFINE_THISCALL_WRAPPER(MSVCP_bad_alloc_ctor, 8)
197 bad_alloc* __thiscall MSVCP_bad_alloc_ctor(bad_alloc *this, const char **name)
198 {
199     TRACE("%p %s\n", this, *name);
200     MSVCP_exception_ctor(this, name);
201     this->vtable = &MSVCP_bad_alloc_vtable;
202     return this;
203 }
204
205 DEFINE_THISCALL_WRAPPER(MSVCP_bad_alloc_copy_ctor, 8)
206 bad_alloc* __thiscall MSVCP_bad_alloc_copy_ctor(bad_alloc *this, const bad_alloc *rhs)
207 {
208     TRACE("%p %p\n", this, rhs);
209     MSVCP_exception_copy_ctor(this, rhs);
210     this->vtable = &MSVCP_bad_alloc_vtable;
211     return this;
212 }
213
214 DEFINE_THISCALL_WRAPPER(MSVCP_bad_alloc_dtor, 4)
215 void __thiscall MSVCP_bad_alloc_dtor(bad_alloc *this)
216 {
217     TRACE("%p\n", this);
218     MSVCP_exception_dtor(this);
219 }
220
221 DEFINE_THISCALL_WRAPPER(MSVCP_bad_alloc_vector_dtor, 8)
222 void * __thiscall MSVCP_bad_alloc_vector_dtor(bad_alloc *this, unsigned int flags)
223 {
224     TRACE("%p %x\n", this, flags);
225     if(flags & 2) {
226         /* we have an array, with the number of elements stored before the first object */
227         int i, *ptr = (int *)this-1;
228
229         for(i=*ptr-1; i>=0; i--)
230             MSVCP_bad_alloc_dtor(this+i);
231         MSVCRT_operator_delete(ptr);
232     } else {
233         MSVCP_bad_alloc_dtor(this);
234         if(flags & 1)
235             MSVCRT_operator_delete(this);
236     }
237
238     return this;
239 }
240
241 DEFINE_THISCALL_WRAPPER(MSVCP_what_exception,4)
242 const char* __thiscall MSVCP_what_exception(exception * this)
243 {
244     TRACE("(%p) returning %s\n", this, this->name);
245     return this->name ? this->name : "Unknown exception";
246 }
247
248 static const type_info bad_alloc_type_info = {
249     &MSVCP_bad_alloc_vtable,
250     NULL,
251     ".?AVbad_alloc@std@@"
252 };
253
254 static const rtti_base_descriptor bad_alloc_rtti_base_descriptor = {
255     &bad_alloc_type_info,
256     1,
257     { 0, -1, 0 },
258     64
259 };
260
261 static const rtti_base_array bad_alloc_rtti_base_array = {
262     {
263         &bad_alloc_rtti_base_descriptor,
264         &exception_rtti_base_descriptor,
265         NULL
266     }
267 };
268
269 static const rtti_object_hierarchy bad_alloc_type_hierarchy = {
270     0,
271     0,
272     2,
273     &bad_alloc_rtti_base_array
274 };
275
276 const rtti_object_locator bad_alloc_rtti = {
277     0,
278     0,
279     0,
280     &bad_alloc_type_info,
281     &bad_alloc_type_hierarchy
282 };
283
284 static const cxx_type_info bad_alloc_cxx_type_info = {
285     0,
286     &bad_alloc_type_info,
287     { 0, -1, 0 },
288     sizeof(bad_alloc),
289     (cxx_copy_ctor)THISCALL(MSVCP_bad_alloc_copy_ctor)
290 };
291
292 static const cxx_type_info_table bad_alloc_cxx_type_table = {
293     2,
294     {
295         &bad_alloc_cxx_type_info,
296         &exception_cxx_type_info,
297         NULL
298     }
299 };
300
301 static const cxx_exception_type bad_alloc_cxx_type = {
302     0,
303     (cxx_copy_ctor)THISCALL(MSVCP_bad_alloc_dtor),
304     NULL,
305     &bad_alloc_cxx_type_table
306 };
307
308 /* logic_error class data */
309 typedef struct _logic_error {
310     exception e;
311     basic_string_char str;
312 } logic_error;
313
314 DEFINE_THISCALL_WRAPPER(MSVCP_logic_error_ctor, 8)
315 logic_error* __thiscall MSVCP_logic_error_ctor(
316         logic_error *this, const char **name)
317 {
318     TRACE("%p %s\n", this, *name);
319     this->e.vtable = &MSVCP_logic_error_vtable;
320     this->e.name = NULL;
321     this->e.do_free = FALSE;
322     MSVCP_basic_string_char_ctor_cstr(&this->str, *name);
323     return this;
324 }
325
326 DEFINE_THISCALL_WRAPPER(MSVCP_logic_error_copy_ctor, 8)
327 logic_error* __thiscall MSVCP_logic_error_copy_ctor(
328         logic_error *this, logic_error *rhs)
329 {
330     TRACE("%p %p\n", this, rhs);
331     MSVCP_exception_copy_ctor(&this->e, &rhs->e);
332     MSVCP_basic_string_char_copy_ctor(&this->str, &rhs->str);
333     this->e.vtable = &MSVCP_logic_error_vtable;
334     return this;
335 }
336
337 DEFINE_THISCALL_WRAPPER(MSVCP_logic_error_dtor, 4)
338 void __thiscall MSVCP_logic_error_dtor(logic_error *this)
339 {
340     TRACE("%p\n", this);
341     MSVCP_exception_dtor(&this->e);
342     MSVCP_basic_string_char_dtor(&this->str);
343 }
344
345 DEFINE_THISCALL_WRAPPER(MSVCP_logic_error_vector_dtor, 8)
346 void* __thiscall MSVCP_logic_error_vector_dtor(
347         logic_error *this, unsigned int flags)
348 {
349     TRACE("%p %x\n", this, flags);
350     if(flags & 2) {
351         /* we have an array, with the number of elements stored before the first object */
352         int i, *ptr = (int *)this-1;
353
354         for(i=*ptr-1; i>=0; i--)
355             MSVCP_logic_error_dtor(this+i);
356         MSVCRT_operator_delete(ptr);
357     } else {
358         MSVCP_logic_error_dtor(this);
359         if(flags & 1)
360             MSVCRT_operator_delete(this);
361     }
362
363     return this;
364 }
365
366 DEFINE_THISCALL_WRAPPER(MSVCP_logic_error_what, 4)
367 const char* __thiscall MSVCP_logic_error_what(logic_error *this)
368 {
369     TRACE("%p\n", this);
370     return MSVCP_basic_string_char_c_str(&this->str);
371 }
372
373 static const type_info logic_error_type_info = {
374     &MSVCP_logic_error_vtable,
375     NULL,
376     ".?AVlogic_error@std@@"
377 };
378
379 static const rtti_base_descriptor logic_error_rtti_base_descriptor = {
380     &logic_error_type_info,
381     1,
382     { 0, -1, 0 },
383     64
384 };
385
386 static const rtti_base_array logic_error_rtti_base_array = {
387     {
388         &logic_error_rtti_base_descriptor,
389         &exception_rtti_base_descriptor,
390         NULL
391     }
392 };
393
394 static const rtti_object_hierarchy logic_error_type_hierarchy = {
395     0,
396     0,
397     2,
398     &logic_error_rtti_base_array
399 };
400
401 const rtti_object_locator logic_error_rtti = {
402     0,
403     0,
404     0,
405     &logic_error_type_info,
406     &logic_error_type_hierarchy
407 };
408
409 static const cxx_type_info logic_error_cxx_type_info = {
410     0,
411     &logic_error_type_info,
412     { 0, -1, 0 },
413     sizeof(logic_error),
414     (cxx_copy_ctor)THISCALL(MSVCP_logic_error_copy_ctor)
415 };
416
417 static const cxx_type_info_table logic_error_cxx_type_table = {
418     2,
419     {
420         &logic_error_cxx_type_info,
421         &exception_cxx_type_info,
422         NULL
423     }
424 };
425
426 static const cxx_exception_type logic_error_cxx_type = {
427     0,
428     (cxx_copy_ctor)THISCALL(MSVCP_logic_error_dtor),
429     NULL,
430     &logic_error_cxx_type_table
431 };
432
433 /* length_error class data */
434 typedef logic_error length_error;
435
436 DEFINE_THISCALL_WRAPPER(MSVCP_length_error_ctor, 8)
437 length_error* __thiscall MSVCP_length_error_ctor(
438         length_error *this, const char **name)
439 {
440     TRACE("%p %s\n", this, *name);
441     MSVCP_logic_error_ctor(this, name);
442     this->e.vtable = &MSVCP_length_error_vtable;
443     return this;
444 }
445
446 DEFINE_THISCALL_WRAPPER(MSVCP_length_error_copy_ctor, 8)
447 length_error* __thiscall MSVCP_length_error_copy_ctor(
448         length_error *this, length_error *rhs)
449 {
450     TRACE("%p %p\n", this, rhs);
451     MSVCP_logic_error_copy_ctor(this, rhs);
452     this->e.vtable = &MSVCP_length_error_vtable;
453     return this;
454 }
455
456 DEFINE_THISCALL_WRAPPER(MSVCP_length_error_vector_dtor, 8)
457 void* __thiscall MSVCP_length_error_vector_dtor(
458         length_error *this, unsigned int flags)
459 {
460     TRACE("%p %x\n", this, flags);
461     return MSVCP_logic_error_vector_dtor(this, flags);
462 }
463
464 static const type_info length_error_type_info = {
465     &MSVCP_length_error_vtable,
466     NULL,
467     ".?AVlength_error@std@@"
468 };
469
470 static const rtti_base_descriptor length_error_rtti_base_descriptor = {
471     &length_error_type_info,
472     2,
473     { 0, -1, 0 },
474     64
475 };
476
477 static const rtti_base_array length_error_rtti_base_array = {
478     {
479         &length_error_rtti_base_descriptor,
480         &logic_error_rtti_base_descriptor,
481         &exception_rtti_base_descriptor
482     }
483 };
484
485 static const rtti_object_hierarchy length_error_type_hierarchy = {
486     0,
487     0,
488     3,
489     &length_error_rtti_base_array
490 };
491
492 const rtti_object_locator length_error_rtti = {
493     0,
494     0,
495     0,
496     &length_error_type_info,
497     &length_error_type_hierarchy
498 };
499
500 static const cxx_type_info length_error_cxx_type_info = {
501     0,
502     &length_error_type_info,
503     { 0, -1, 0 },
504     sizeof(length_error),
505     (cxx_copy_ctor)THISCALL(MSVCP_length_error_copy_ctor)
506 };
507
508 static const cxx_type_info_table length_error_cxx_type_table = {
509     3,
510     {
511         &length_error_cxx_type_info,
512         &logic_error_cxx_type_info,
513         &exception_cxx_type_info
514     }
515 };
516
517 static const cxx_exception_type length_error_cxx_type = {
518     0,
519     (cxx_copy_ctor)THISCALL(MSVCP_logic_error_dtor),
520     NULL,
521     &length_error_cxx_type_table
522 };
523
524 /* out_of_range class data */
525 typedef logic_error out_of_range;
526
527 DEFINE_THISCALL_WRAPPER(MSVCP_out_of_range_ctor, 8)
528 out_of_range* __thiscall MSVCP_out_of_range_ctor(
529         out_of_range *this, const char **name)
530 {
531     TRACE("%p %s\n", this, *name);
532     MSVCP_logic_error_ctor(this, name);
533     this->e.vtable = &MSVCP_out_of_range_vtable;
534     return this;
535 }
536
537 DEFINE_THISCALL_WRAPPER(MSVCP_out_of_range_copy_ctor, 8)
538 out_of_range* __thiscall MSVCP_out_of_range_copy_ctor(
539         out_of_range *this, out_of_range *rhs)
540 {
541     TRACE("%p %p\n", this, rhs);
542     MSVCP_logic_error_copy_ctor(this, rhs);
543     this->e.vtable = &MSVCP_out_of_range_vtable;
544     return this;
545 }
546
547 DEFINE_THISCALL_WRAPPER(MSVCP_out_of_range_vector_dtor, 8)
548 void* __thiscall MSVCP_out_of_range_vector_dtor(
549         out_of_range *this, unsigned int flags)
550 {
551     TRACE("%p %x\n", this, flags);
552     return MSVCP_logic_error_vector_dtor(this, flags);
553 }
554
555 static const type_info out_of_range_type_info = {
556     &MSVCP_out_of_range_vtable,
557     NULL,
558     ".?AVout_of_range@std@@"
559 };
560
561 static const rtti_base_descriptor out_of_range_rtti_base_descriptor = {
562     &out_of_range_type_info,
563     2,
564     { 0, -1, 0 },
565     64
566 };
567
568 static const rtti_base_array out_of_range_rtti_base_array = {
569     {
570         &out_of_range_rtti_base_descriptor,
571         &logic_error_rtti_base_descriptor,
572         &exception_rtti_base_descriptor
573     }
574 };
575
576 static const rtti_object_hierarchy out_of_range_type_hierarchy = {
577     0,
578     0,
579     3,
580     &out_of_range_rtti_base_array
581 };
582
583 const rtti_object_locator out_of_range_rtti = {
584     0,
585     0,
586     0,
587     &out_of_range_type_info,
588     &out_of_range_type_hierarchy
589 };
590
591 static const cxx_type_info out_of_range_cxx_type_info = {
592     0,
593     &out_of_range_type_info,
594     { 0, -1, 0 },
595     sizeof(out_of_range),
596     (cxx_copy_ctor)THISCALL(MSVCP_out_of_range_copy_ctor)
597 };
598
599 static const cxx_type_info_table out_of_range_cxx_type_table = {
600     3,
601     {
602         &out_of_range_cxx_type_info,
603         &logic_error_cxx_type_info,
604         &exception_cxx_type_info
605     }
606 };
607
608 static const cxx_exception_type out_of_range_cxx_type = {
609     0,
610     (cxx_copy_ctor)THISCALL(MSVCP_logic_error_dtor),
611     NULL,
612     &out_of_range_cxx_type_table
613 };
614
615 /* invalid_argument class data */
616 typedef logic_error invalid_argument;
617
618 DEFINE_THISCALL_WRAPPER(MSVCP_invalid_argument_ctor, 8)
619 invalid_argument* __thiscall MSVCP_invalid_argument_ctor(
620         invalid_argument *this, const char **name)
621 {
622     TRACE("%p %s\n", this, *name);
623     MSVCP_logic_error_ctor(this, name);
624     this->e.vtable = &MSVCP_invalid_argument_vtable;
625     return this;
626 }
627
628 DEFINE_THISCALL_WRAPPER(MSVCP_invalid_argument_copy_ctor, 8)
629 invalid_argument* __thiscall MSVCP_invalid_argument_copy_ctor(
630         invalid_argument *this, invalid_argument *rhs)
631 {
632     TRACE("%p %p\n", this, rhs);
633     MSVCP_logic_error_copy_ctor(this, rhs);
634     this->e.vtable = &MSVCP_invalid_argument_vtable;
635     return this;
636 }
637
638 DEFINE_THISCALL_WRAPPER(MSVCP_invalid_argument_vector_dtor, 8)
639 void* __thiscall MSVCP_invalid_argument_vector_dtor(
640         invalid_argument *this, unsigned int flags)
641 {
642     TRACE("%p %x\n", this, flags);
643     return MSVCP_logic_error_vector_dtor(this, flags);
644 }
645
646 static const type_info invalid_argument_type_info = {
647     &MSVCP_invalid_argument_vtable,
648     NULL,
649     ".?AVinvalid_argument@std@@"
650 };
651
652 static const rtti_base_descriptor invalid_argument_rtti_base_descriptor = {
653     &invalid_argument_type_info,
654     2,
655     { 0, -1, 0 },
656     64
657 };
658
659 static const rtti_base_array invalid_argument_rtti_base_array = {
660     {
661         &invalid_argument_rtti_base_descriptor,
662         &logic_error_rtti_base_descriptor,
663         &exception_rtti_base_descriptor
664     }
665 };
666
667 static const rtti_object_hierarchy invalid_argument_type_hierarchy = {
668     0,
669     0,
670     3,
671     &invalid_argument_rtti_base_array
672 };
673
674 const rtti_object_locator invalid_argument_rtti = {
675     0,
676     0,
677     0,
678     &invalid_argument_type_info,
679     &invalid_argument_type_hierarchy
680 };
681
682 static const cxx_type_info invalid_argument_cxx_type_info = {
683     0,
684     &invalid_argument_type_info,
685     { 0, -1, 0 },
686     sizeof(invalid_argument),
687     (cxx_copy_ctor)THISCALL(MSVCP_invalid_argument_copy_ctor)
688 };
689
690 static const cxx_type_info_table invalid_argument_cxx_type_table = {
691     3,
692     {
693         &invalid_argument_cxx_type_info,
694         &logic_error_cxx_type_info,
695         &exception_cxx_type_info
696     }
697 };
698
699 static const cxx_exception_type invalid_argument_cxx_type = {
700     0,
701     (cxx_copy_ctor)THISCALL(MSVCP_logic_error_dtor),
702     NULL,
703     &invalid_argument_cxx_type_table
704 };
705
706 #ifndef __GNUC__
707 void __asm_dummy_vtables(void) {
708 #endif
709     __ASM_EXCEPTION_VTABLE(bad_alloc)
710     __ASM_EXCEPTION_STRING_VTABLE(logic_error)
711     __ASM_EXCEPTION_STRING_VTABLE(length_error)
712     __ASM_EXCEPTION_STRING_VTABLE(out_of_range)
713     __ASM_EXCEPTION_STRING_VTABLE(invalid_argument)
714 #ifndef __GNUC__
715 }
716 #endif
717
718 /* Internal: throws selected exception */
719 void throw_exception(exception_type et, const char *str)
720 {
721     const char *addr = str;
722
723     switch(et) {
724     case EXCEPTION: {
725         exception e;
726         MSVCP_exception_ctor(&e, &addr);
727         _CxxThrowException(&e, &exception_cxx_type);
728         return;
729     }
730     case EXCEPTION_BAD_ALLOC: {
731         bad_alloc e;
732         MSVCP_bad_alloc_ctor(&e, &addr);
733         _CxxThrowException(&e, &bad_alloc_cxx_type);
734         return;
735     }
736     case EXCEPTION_LOGIC_ERROR: {
737         logic_error e;
738         MSVCP_logic_error_ctor(&e, &addr);
739         _CxxThrowException((exception*)&e, &logic_error_cxx_type);
740         return;
741     }
742     case EXCEPTION_LENGTH_ERROR: {
743         length_error e;
744         MSVCP_length_error_ctor(&e, &addr);
745         _CxxThrowException((exception*)&e, &length_error_cxx_type);
746         return;
747     }
748     case EXCEPTION_OUT_OF_RANGE: {
749         out_of_range e;
750         MSVCP_out_of_range_ctor(&e, &addr);
751         _CxxThrowException((exception*)&e, &out_of_range_cxx_type);
752     }
753     case EXCEPTION_INVALID_ARGUMENT: {
754         invalid_argument e;
755         MSVCP_invalid_argument_ctor(&e, &addr);
756         _CxxThrowException((exception*)&e, &invalid_argument_cxx_type);
757     }
758     }
759 }