]> gcc.gnu.org Git - gcc.git/blame - gcc/cp/except.c
except.c (sjlj_emit_function_enter): Call assemble_external_libcall for eh_personalit...
[gcc.git] / gcc / cp / except.c
CommitLineData
8d08fdba 1/* Handle exceptional things in C++.
c913b6f1
KG
2 Copyright (C) 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
3 2000, 2001 Free Software Foundation, Inc.
8d2733ca
MS
4 Contributed by Michael Tiemann <tiemann@cygnus.com>
5 Rewritten by Mike Stump <mrs@cygnus.com>, based upon an
6 initial re-implementation courtesy Tad Hunt.
8d08fdba
MS
7
8This file is part of GNU CC.
9
10GNU CC is free software; you can redistribute it and/or modify
11it under the terms of the GNU General Public License as published by
12the Free Software Foundation; either version 2, or (at your option)
13any later version.
14
15GNU CC is distributed in the hope that it will be useful,
16but WITHOUT ANY WARRANTY; without even the implied warranty of
17MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18GNU General Public License for more details.
19
20You should have received a copy of the GNU General Public License
21along with GNU CC; see the file COPYING. If not, write to
e9fa0c7c
RK
22the Free Software Foundation, 59 Temple Place - Suite 330,
23Boston, MA 02111-1307, USA. */
8d08fdba
MS
24
25
8d08fdba 26#include "config.h"
8d052bc7 27#include "system.h"
8d08fdba
MS
28#include "tree.h"
29#include "rtl.h"
8f17b5c5 30#include "expr.h"
8d08fdba
MS
31#include "cp-tree.h"
32#include "flags.h"
8d2733ca 33#include "obstack.h"
21451173 34#include "output.h"
6467930b 35#include "except.h"
54f92bfb 36#include "toplev.h"
8d08fdba 37
93ca4ba7 38static void push_eh_cleanup PARAMS ((tree));
52a11cbf 39static tree prepare_eh_type PARAMS ((tree));
158991b7 40static tree build_eh_type_type PARAMS ((tree));
52a11cbf 41static tree do_begin_catch PARAMS ((void));
93ca4ba7 42static int dtor_nothrow PARAMS ((tree));
52a11cbf
RH
43static tree do_end_catch PARAMS ((tree));
44static void push_eh_cleanup PARAMS ((tree));
45static bool decl_is_java_type PARAMS ((tree decl, int err));
52a11cbf
RH
46static void initialize_handler_parm PARAMS ((tree, tree));
47static tree do_allocate_exception PARAMS ((tree));
158991b7 48static int complete_ptr_ref_or_void_ptr_p PARAMS ((tree, tree));
d064d75a 49static bool is_admissible_throw_operand PARAMS ((tree));
fbd40359
ZW
50static int can_convert_eh PARAMS ((tree, tree));
51static void check_handlers_1 PARAMS ((tree, tree));
8d2733ca 52
8d2733ca 53#include "decl.h"
8d2733ca 54#include "obstack.h"
8d2733ca 55
52a11cbf 56/* Sets up all the global eh stuff that needs to be initialized at the
bbd0d54a 57 start of compilation. */
8d08fdba 58
8d08fdba 59void
8d2733ca 60init_exception_processing ()
8d08fdba 61{
52a11cbf
RH
62 tree tmp;
63
2c73f9f5 64 if (flag_honor_std)
6bcedb4e 65 push_namespace (std_identifier);
52a11cbf
RH
66
67 /* void std::terminate (); */
68 tmp = build_function_type (void_type_node, void_list_node);
69 terminate_node = build_cp_library_fn_ptr ("terminate", tmp);
9cd64686 70 TREE_THIS_VOLATILE (terminate_node) = 1;
0c11ada6 71 TREE_NOTHROW (terminate_node) = 1;
2c73f9f5
ML
72 if (flag_honor_std)
73 pop_namespace ();
8ccc31eb 74
52a11cbf 75 protect_cleanup_actions = build_call (terminate_node, NULL_TREE);
6874c264 76
52a11cbf
RH
77 /* void __cxa_call_unexpected(void *); */
78 tmp = tree_cons (NULL_TREE, ptr_type_node, void_list_node);
79 tmp = build_function_type (void_type_node, tmp);
80 call_unexpected_node
81 = push_throw_library_fn (get_identifier ("__cxa_call_unexpected"), tmp);
6874c264 82
52a11cbf
RH
83 eh_personality_libfunc = init_one_libfunc (USING_SJLJ_EXCEPTIONS
84 ? "__gxx_personality_sj0"
85 : "__gxx_personality_v0");
6874c264 86
52a11cbf 87 lang_eh_runtime_type = build_eh_type_type;
6874c264
JM
88}
89
6874c264 90static tree
52a11cbf 91prepare_eh_type (type)
f30432d7 92 tree type;
8d08fdba 93{
52a11cbf
RH
94 if (type == NULL_TREE)
95 return type;
f30432d7
MS
96 if (type == error_mark_node)
97 return error_mark_node;
8d2733ca 98
e92cc029 99 /* peel back references, so they match. */
f30432d7
MS
100 if (TREE_CODE (type) == REFERENCE_TYPE)
101 type = TREE_TYPE (type);
8d08fdba 102
e92cc029 103 /* Peel off cv qualifiers. */
f30432d7 104 type = TYPE_MAIN_VARIANT (type);
8d2733ca 105
52a11cbf 106 return type;
8d08fdba 107}
8d08fdba 108
e5f614d7 109/* Build the address of a typeinfo decl for use in the runtime
52a11cbf 110 matching field of the exception model. */
5816cb14
AM
111
112static tree
52a11cbf 113build_eh_type_type (type)
5816cb14
AM
114 tree type;
115{
5816cb14 116 tree exp;
5816cb14 117
93ca4ba7
JM
118 if (type == NULL_TREE || type == error_mark_node)
119 return type;
5816cb14 120
52a11cbf
RH
121 if (decl_is_java_type (type, 0))
122 exp = build_java_class_ref (TREE_TYPE (type));
123 else
124 exp = get_tinfo_decl (type);
5816cb14 125
e5f614d7 126 mark_used (exp);
db48b831 127 exp = build1 (ADDR_EXPR, ptr_type_node, exp);
5816cb14 128
52a11cbf 129 return exp;
5816cb14
AM
130}
131
52a11cbf
RH
132tree
133build_exc_ptr ()
134{
135 return build (EXC_PTR_EXPR, ptr_type_node);
136}
137
138/* Build up a call to __cxa_begin_catch, to tell the runtime that the
139 exception has been handled. */
93ca4ba7 140
52a11cbf
RH
141static tree
142do_begin_catch ()
9c606f69 143{
52a11cbf
RH
144 tree fn;
145
146 fn = get_identifier ("__cxa_begin_catch");
147 if (IDENTIFIER_GLOBAL_VALUE (fn))
148 fn = IDENTIFIER_GLOBAL_VALUE (fn);
149 else
9c606f69 150 {
52a11cbf
RH
151 /* Declare void* __cxa_begin_catch (void *). */
152 tree tmp = tree_cons (NULL_TREE, ptr_type_node, void_list_node);
153 fn = push_library_fn (fn, build_function_type (ptr_type_node, tmp));
9c606f69 154 }
52a11cbf
RH
155
156 return build_function_call (fn, tree_cons (NULL_TREE, build_exc_ptr (),
157 NULL_TREE));
9c606f69
AM
158}
159
93ca4ba7
JM
160/* Returns nonzero if cleaning up an exception of type TYPE (which can be
161 NULL_TREE for a ... handler) will not throw an exception. */
162
163static int
164dtor_nothrow (type)
165 tree type;
166{
167 tree fn;
168
169 if (type == NULL_TREE)
170 return 0;
171
172 if (! TYPE_HAS_DESTRUCTOR (type))
173 return 1;
174
175 fn = lookup_member (type, dtor_identifier, 0, 0);
176 fn = TREE_VALUE (fn);
177 return TREE_NOTHROW (fn);
178}
179
52a11cbf 180/* Build up a call to __cxa_end_catch, to destroy the exception object
93ca4ba7 181 for the current catch block if no others are currently using it. */
6467930b 182
c7ae64f2 183static tree
52a11cbf 184do_end_catch (type)
93ca4ba7 185 tree type;
72b7eeff 186{
6874c264 187 tree fn, cleanup;
52a11cbf
RH
188
189 fn = get_identifier ("__cxa_end_catch");
6874c264
JM
190 if (IDENTIFIER_GLOBAL_VALUE (fn))
191 fn = IDENTIFIER_GLOBAL_VALUE (fn);
192 else
193 {
52a11cbf
RH
194 /* Declare void __cxa_end_catch (). */
195 fn = push_void_library_fn (fn, void_list_node);
0c11ada6
JM
196 /* This can throw if the destructor for the exception throws. */
197 TREE_NOTHROW (fn) = 0;
6874c264 198 }
72b7eeff 199
52a11cbf 200 cleanup = build_function_call (fn, NULL_TREE);
93ca4ba7 201 TREE_NOTHROW (cleanup) = dtor_nothrow (type);
52a11cbf 202
c0700ea5 203 return cleanup;
c7ae64f2
JM
204}
205
206/* This routine creates the cleanup for the current exception. */
72b7eeff 207
c7ae64f2 208static void
93ca4ba7
JM
209push_eh_cleanup (type)
210 tree type;
c7ae64f2 211{
52a11cbf 212 finish_decl_cleanup (NULL_TREE, do_end_catch (type));
f4a23343
JM
213}
214
e97f22c9
TT
215/* Return nonzero value if DECL is a Java type suitable for catch or
216 throw. */
217
52a11cbf 218static bool
e97f22c9
TT
219decl_is_java_type (decl, err)
220 tree decl;
221 int err;
222{
52a11cbf
RH
223 bool r = (TREE_CODE (decl) == POINTER_TYPE
224 && TREE_CODE (TREE_TYPE (decl)) == RECORD_TYPE
225 && TYPE_FOR_JAVA (TREE_TYPE (decl)));
e97f22c9
TT
226
227 if (err)
228 {
229 if (TREE_CODE (decl) == REFERENCE_TYPE
230 && TREE_CODE (TREE_TYPE (decl)) == RECORD_TYPE
231 && TYPE_FOR_JAVA (TREE_TYPE (decl)))
232 {
233 /* Can't throw a reference. */
234 cp_error ("type `%T' is disallowed in Java `throw' or `catch'",
235 decl);
236 }
237
238 if (r)
239 {
240 tree jthrow_node
241 = IDENTIFIER_GLOBAL_VALUE (get_identifier ("jthrowable"));
400500c4 242
e97f22c9 243 if (jthrow_node == NULL_TREE)
400500c4
RK
244 fatal_error
245 ("call to Java `catch' or `throw' with `jthrowable' undefined");
246
e97f22c9
TT
247 jthrow_node = TREE_TYPE (TREE_TYPE (jthrow_node));
248
249 if (! DERIVED_FROM_P (jthrow_node, TREE_TYPE (decl)))
250 {
251 /* Thrown object must be a Throwable. */
252 cp_error ("type `%T' is not derived from `java::lang::Throwable'",
253 TREE_TYPE (decl));
254 }
255 }
256 }
257
258 return r;
259}
260
1f730ff7
ZW
261/* Select the personality routine to be used for exception handling,
262 or issue an error if we need two different ones in the same
263 translation unit.
264 ??? At present eh_personality_libfunc is set to
265 __gxx_personality_(sj|v)0 in init_exception_processing - should it
266 be done here instead? */
267void
268choose_personality_routine (lang)
269 enum languages lang;
52a11cbf
RH
270{
271 static enum {
272 chose_none,
273 chose_cpp,
274 chose_java,
275 gave_error
276 } state;
277
278 switch (state)
279 {
1f730ff7
ZW
280 case gave_error:
281 return;
52a11cbf
RH
282
283 case chose_cpp:
1f730ff7
ZW
284 if (lang != lang_cplusplus)
285 goto give_error;
286 return;
287
52a11cbf 288 case chose_java:
1f730ff7
ZW
289 if (lang != lang_java)
290 goto give_error;
291 return;
292
293 case chose_none:
294 ; /* proceed to language selection */
295 }
296
297 switch (lang)
298 {
299 case lang_cplusplus:
300 state = chose_cpp;
52a11cbf
RH
301 break;
302
1f730ff7
ZW
303 case lang_java:
304 state = chose_java;
305 eh_personality_libfunc = init_one_libfunc (USING_SJLJ_EXCEPTIONS
306 ? "__gcj_personality_sj0"
307 : "__gcj_personality_v0");
52a11cbf 308 break;
1f730ff7
ZW
309
310 default:
311 abort ();
52a11cbf 312 }
1f730ff7
ZW
313 return;
314
315 give_error:
316 error ("mixing C++ and Java catches in a single translation unit");
317 state = gave_error;
52a11cbf
RH
318}
319
b35d4555 320/* Initialize the catch parameter DECL. */
6467930b 321
b35d4555 322static void
52a11cbf 323initialize_handler_parm (decl, exp)
3c5c0849 324 tree decl;
52a11cbf 325 tree exp;
8d08fdba 326{
b35d4555
MM
327 tree init;
328 tree init_type;
329
330 /* Make sure we mark the catch param as used, otherwise we'll get a
331 warning about an unused ((anonymous)). */
332 TREE_USED (decl) = 1;
333
52a11cbf
RH
334 /* Figure out the type that the initializer is. Pointers are returned
335 adjusted by value from __cxa_begin_catch. Others are returned by
336 reference. */
b35d4555 337 init_type = TREE_TYPE (decl);
52a11cbf
RH
338 if (TREE_CODE (init_type) != POINTER_TYPE
339 && TREE_CODE (init_type) != REFERENCE_TYPE)
b35d4555
MM
340 init_type = build_reference_type (init_type);
341
1f730ff7
ZW
342 choose_personality_routine (decl_is_java_type (init_type, 0)
343 ? lang_java : lang_cplusplus);
b35d4555
MM
344
345 /* Since pointers are passed by value, initialize a reference to
52a11cbf 346 pointer catch parm with the address of the temporary. */
b35d4555
MM
347 if (TREE_CODE (init_type) == REFERENCE_TYPE
348 && TREE_CODE (TREE_TYPE (init_type)) == POINTER_TYPE)
349 exp = build_unary_op (ADDR_EXPR, exp, 1);
350
52a11cbf 351 exp = ocp_convert (init_type, exp, CONV_IMPLICIT|CONV_FORCE_TEMP, 0);
b35d4555
MM
352
353 init = convert_from_reference (exp);
354
355 /* If the constructor for the catch parm exits via an exception, we
356 must call terminate. See eh23.C. */
357 if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl)))
faf5394a 358 {
b35d4555
MM
359 /* Generate the copy constructor call directly so we can wrap it.
360 See also expand_default_init. */
361 init = ocp_convert (TREE_TYPE (decl), init,
362 CONV_IMPLICIT|CONV_FORCE_TEMP, 0);
52a11cbf 363 init = build1 (MUST_NOT_THROW_EXPR, TREE_TYPE (init), init);
faf5394a
MS
364 }
365
b35d4555
MM
366 /* Let `cp_finish_decl' know that this initializer is ok. */
367 DECL_INITIAL (decl) = error_mark_node;
368 decl = pushdecl (decl);
8d2733ca 369
b35d4555 370 start_decl_1 (decl);
cd9f6678 371 cp_finish_decl (decl, init, NULL_TREE,
b35d4555 372 LOOKUP_ONLYCONVERTING|DIRECT_BIND);
5816cb14
AM
373}
374
b35d4555 375/* Call this to start a catch block. DECL is the catch parameter. */
5816cb14 376
b35d4555
MM
377tree
378expand_start_catch_block (decl)
3c5c0849 379 tree decl;
5816cb14 380{
b35d4555
MM
381 tree compound_stmt_1;
382 tree compound_stmt_2;
52a11cbf
RH
383 tree exp = NULL_TREE;
384 tree type;
385 bool is_java;
5816cb14 386
b35d4555
MM
387 if (! doing_eh (1))
388 return NULL_TREE;
5816cb14 389
b35d4555 390 /* Make sure this declaration is reasonable. */
3c5c0849
MM
391 if (decl && !complete_ptr_ref_or_void_ptr_p (TREE_TYPE (decl), NULL_TREE))
392 decl = NULL_TREE;
5816cb14 393
b35d4555
MM
394 /* Create a binding level for the eh_info and the exception object
395 cleanup. */
396 compound_stmt_1 = begin_compound_stmt (/*has_no_scope=*/0);
826840d9 397 note_level_for_catch ();
b35d4555 398
52a11cbf
RH
399 if (decl)
400 type = prepare_eh_type (TREE_TYPE (decl));
401 else
402 type = NULL_TREE;
403 begin_catch_block (type);
404
405 is_java = false;
406 if (decl)
e97f22c9 407 {
52a11cbf 408 tree init;
5816cb14 409
52a11cbf
RH
410 if (decl_is_java_type (type, 1))
411 {
412 /* Java only passes object via pointer and doesn't require
413 adjusting. The java object is immediately before the
414 generic exception header. */
415 init = build_exc_ptr ();
416 init = build1 (NOP_EXPR, build_pointer_type (type), init);
417 init = build (MINUS_EXPR, TREE_TYPE (init), init,
418 TYPE_SIZE_UNIT (TREE_TYPE (init)));
3e411c3f 419 init = build_indirect_ref (init, NULL);
52a11cbf
RH
420 is_java = true;
421 }
e97f22c9 422 else
52a11cbf
RH
423 {
424 /* C++ requires that we call __cxa_begin_catch to get the
425 pointer to the actual object. */
426 init = do_begin_catch ();
427 }
428
429 exp = create_temporary_var (ptr_type_node);
430 DECL_REGISTER (exp) = 1;
431 cp_finish_decl (exp, init, NULL_TREE, LOOKUP_ONLYCONVERTING);
432 finish_expr_stmt (build_modify_expr (exp, INIT_EXPR, init));
e97f22c9
TT
433 }
434 else
52a11cbf
RH
435 finish_expr_stmt (do_begin_catch ());
436
437 /* C++ requires that we call __cxa_end_catch at the end of
438 processing the exception. */
439 if (! is_java)
440 push_eh_cleanup (type);
5816cb14 441
b35d4555
MM
442 /* Create a binding level for the parm. */
443 compound_stmt_2 = begin_compound_stmt (/*has_no_scope=*/0);
5816cb14 444
b35d4555 445 if (decl)
52a11cbf 446 initialize_handler_parm (decl, exp);
5816cb14 447
b35d4555 448 return build_tree_list (compound_stmt_1, compound_stmt_2);
5816cb14
AM
449}
450
f30432d7 451
8d2733ca
MS
452/* Call this to end a catch block. Its responsible for emitting the
453 code to handle jumping back to the correct place, and for emitting
454 the label to jump to if this catch block didn't match. */
6467930b 455
824b9a4c 456void
b35d4555
MM
457expand_end_catch_block (blocks)
458 tree blocks;
8d08fdba 459{
b35d4555
MM
460 tree compound_stmt_1 = blocks ? TREE_PURPOSE (blocks): NULL_TREE;
461 tree compound_stmt_2 = blocks ? TREE_VALUE (blocks): NULL_TREE;
462
f30432d7
MS
463 if (! doing_eh (1))
464 return;
8d2733ca 465
0dde4175
JM
466 /* The exception being handled is rethrown if control reaches the end of
467 a handler of the function-try-block of a constructor or destructor. */
468 if (in_function_try_handler
469 && (DECL_CONSTRUCTOR_P (current_function_decl)
470 || DECL_DESTRUCTOR_P (current_function_decl)))
b35d4555 471 finish_expr_stmt (build_throw (NULL_TREE));
0dde4175 472
c7ae64f2 473 /* Cleanup the EH parameter. */
b35d4555 474 finish_compound_stmt (/*has_no_scope=*/0, compound_stmt_2);
46e8c075 475 /* Cleanup the EH object. */
4a6ef811 476 finish_compound_stmt (/*has_no_scope=*/0, compound_stmt_1);
8d2733ca 477}
8d08fdba 478
b35d4555 479tree
52a11cbf 480begin_eh_spec_block ()
f30432d7 481{
52a11cbf
RH
482 tree r = build_stmt (EH_SPEC_BLOCK, NULL_TREE, NULL_TREE);
483 add_stmt (r);
484 return r;
f30432d7
MS
485}
486
b35d4555 487void
52a11cbf
RH
488finish_eh_spec_block (raw_raises, eh_spec_block)
489 tree raw_raises;
490 tree eh_spec_block;
f30432d7 491{
52a11cbf 492 tree raises;
0c11ada6 493
52a11cbf 494 RECHAIN_STMTS (eh_spec_block, EH_SPEC_STMTS (eh_spec_block));
6c20b7e9 495
52a11cbf
RH
496 /* Strip cv quals, etc, from the specification types. */
497 for (raises = NULL_TREE;
498 raw_raises && TREE_VALUE (raw_raises);
499 raw_raises = TREE_CHAIN (raw_raises))
500 raises = tree_cons (NULL_TREE, prepare_eh_type (TREE_VALUE (raw_raises)),
501 raises);
6c20b7e9 502
52a11cbf 503 EH_SPEC_RAISES (eh_spec_block) = raises;
f30432d7
MS
504}
505
52a11cbf 506/* Return a pointer to a buffer for an exception object of type TYPE. */
6467930b 507
52a11cbf
RH
508static tree
509do_allocate_exception (type)
510 tree type;
8d08fdba 511{
52a11cbf 512 tree fn;
eb448459 513
52a11cbf
RH
514 fn = get_identifier ("__cxa_allocate_exception");
515 if (IDENTIFIER_GLOBAL_VALUE (fn))
516 fn = IDENTIFIER_GLOBAL_VALUE (fn);
517 else
f30432d7 518 {
52a11cbf
RH
519 /* Declare void *__cxa_allocate_exception(size_t). */
520 tree tmp = tree_cons (NULL_TREE, c_size_type_node, void_list_node);
521 fn = push_library_fn (fn, build_function_type (ptr_type_node, tmp));
e00737d2 522 }
52a11cbf
RH
523
524 return build_function_call (fn, tree_cons (NULL_TREE, size_in_bytes (type),
525 NULL_TREE));
8d08fdba
MS
526}
527
2ac8a0f9
JM
528#if 0
529/* Call __cxa_free_exception from a cleanup. This is never invoked
530 directly. */
f4a23343 531
c6160f8f 532static tree
52a11cbf
RH
533do_free_exception (ptr)
534 tree ptr;
f4a23343 535{
52a11cbf 536 tree fn;
f4a23343 537
52a11cbf 538 fn = get_identifier ("__cxa_free_exception");
f4a23343
JM
539 if (IDENTIFIER_GLOBAL_VALUE (fn))
540 fn = IDENTIFIER_GLOBAL_VALUE (fn);
541 else
542 {
52a11cbf
RH
543 /* Declare void __cxa_free_exception (void *). */
544 fn = push_void_library_fn (fn, tree_cons (NULL_TREE, ptr_type_node,
545 void_list_node));
f4a23343
JM
546 }
547
52a11cbf 548 return build_function_call (fn, tree_cons (NULL_TREE, ptr, NULL_TREE));
f4a23343 549}
2ac8a0f9 550#endif
f4a23343 551
52a11cbf 552/* Build a throw expression. */
6467930b 553
52a11cbf
RH
554tree
555build_throw (exp)
8d2733ca 556 tree exp;
8d08fdba 557{
6874c264 558 tree fn;
8d08fdba 559
52a11cbf
RH
560 if (exp == error_mark_node)
561 return exp;
562
563 if (processing_template_decl)
564 return build_min (THROW_EXPR, void_type_node, exp);
565
566 if (exp == null_node)
567 cp_warning ("throwing NULL, which has integral, not pointer type");
568
569 if (exp != NULL_TREE)
570 {
571 if (!is_admissible_throw_operand (exp))
572 return error_mark_node;
573 }
574
8d2733ca 575 if (! doing_eh (1))
59ccf49d 576 return error_mark_node;
8d08fdba 577
52a11cbf 578 if (exp && decl_is_java_type (TREE_TYPE (exp), 1))
e97f22c9 579 {
52a11cbf 580 tree fn = get_identifier ("_Jv_Throw");
e97f22c9
TT
581 if (IDENTIFIER_GLOBAL_VALUE (fn))
582 fn = IDENTIFIER_GLOBAL_VALUE (fn);
583 else
584 {
52a11cbf 585 /* Declare void _Jv_Throw (void *). */
0c11ada6
JM
586 tree tmp = tree_cons (NULL_TREE, ptr_type_node, void_list_node);
587 tmp = build_function_type (ptr_type_node, tmp);
c00996a3 588 fn = push_throw_library_fn (fn, tmp);
e97f22c9
TT
589 }
590
52a11cbf 591 exp = build_function_call (fn, tree_cons (NULL_TREE, exp, NULL_TREE));
e97f22c9
TT
592 }
593 else if (exp)
8d2733ca 594 {
faae18ab 595 tree throw_type;
52a11cbf 596 tree cleanup;
59ccf49d
MM
597 tree stmt_expr;
598 tree compound_stmt;
52a11cbf
RH
599 tree object, ptr;
600 tree tmp;
601
602 fn = get_identifier ("__cxa_throw");
603 if (IDENTIFIER_GLOBAL_VALUE (fn))
604 fn = IDENTIFIER_GLOBAL_VALUE (fn);
605 else
606 {
607 /* The CLEANUP_TYPE is the internal type of a destructor. */
608 if (cleanup_type == NULL_TREE)
609 {
610 tmp = void_list_node;
611 tmp = tree_cons (NULL_TREE, ptr_type_node, tmp);
612 tmp = build_function_type (void_type_node, tmp);
613 cleanup_type = build_pointer_type (tmp);
614 }
615
616 /* Declare void __cxa_throw (void*, void*, void (*)(void*)). */
617 /* ??? Second argument is supposed to be "std::type_info*". */
618 tmp = void_list_node;
619 tmp = tree_cons (NULL_TREE, cleanup_type, tmp);
620 tmp = tree_cons (NULL_TREE, ptr_type_node, tmp);
621 tmp = tree_cons (NULL_TREE, ptr_type_node, tmp);
622 tmp = build_function_type (void_type_node, tmp);
623 fn = push_throw_library_fn (fn, tmp);
624 }
59ccf49d
MM
625
626 begin_init_stmts (&stmt_expr, &compound_stmt);
faae18ab 627
a3b49ccd 628 /* throw expression */
e92cc029 629 /* First, decay it. */
f30432d7 630 exp = decay_conversion (exp);
a3b49ccd 631
52a11cbf
RH
632 /* OK, this is kind of wacky. The standard says that we call
633 terminate when the exception handling mechanism, after
634 completing evaluation of the expression to be thrown but
635 before the exception is caught (_except.throw_), calls a
636 user function that exits via an uncaught exception.
637
638 So we have to protect the actual initialization of the
639 exception object with terminate(), but evaluate the
640 expression first. Since there could be temps in the
641 expression, we need to handle that, too. We also expand
642 the call to __cxa_allocate_exception first (which doesn't
643 matter, since it can't throw). */
644
645 my_friendly_assert (stmts_are_full_exprs_p () == 1, 19990926);
646
647 /* Store the throw expression into a temp. This can be less
648 efficient than storing it into the allocated space directly, but
649 if we allocated the space first we would have to deal with
650 cleaning it up if evaluating this expression throws. */
651 if (TREE_SIDE_EFFECTS (exp))
298d6f60 652 {
52a11cbf
RH
653 tmp = create_temporary_var (TREE_TYPE (exp));
654 DECL_INITIAL (tmp) = exp;
655 cp_finish_decl (tmp, exp, NULL_TREE, LOOKUP_ONLYCONVERTING);
656 exp = tmp;
298d6f60 657 }
6874c264 658
52a11cbf
RH
659 /* Allocate the space for the exception. */
660 ptr = create_temporary_var (ptr_type_node);
661 DECL_REGISTER (ptr) = 1;
662 cp_finish_decl (ptr, NULL_TREE, NULL_TREE, LOOKUP_ONLYCONVERTING);
663 tmp = do_allocate_exception (TREE_TYPE (exp));
664 tmp = build_modify_expr (ptr, INIT_EXPR, tmp);
665 finish_expr_stmt (tmp);
f4a23343 666
52a11cbf 667 object = build1 (NOP_EXPR, build_pointer_type (TREE_TYPE (exp)), ptr);
3e411c3f 668 object = build_indirect_ref (object, NULL);
faae18ab 669
52a11cbf
RH
670 exp = build_modify_expr (object, INIT_EXPR, exp);
671 if (exp == error_mark_node)
672 error (" in thrown expression");
f4a23343 673
2ac8a0f9 674 exp = build1 (MUST_NOT_THROW_EXPR, TREE_TYPE (exp), exp);
52a11cbf 675 finish_expr_stmt (exp);
72b7eeff 676
52a11cbf 677 throw_type = build_eh_type_type (prepare_eh_type (TREE_TYPE (object)));
f4a23343 678
52a11cbf
RH
679 if (TYPE_HAS_DESTRUCTOR (TREE_TYPE (object)))
680 {
681 cleanup = lookup_fnfields (TYPE_BINFO (TREE_TYPE (object)),
682 complete_dtor_identifier, 0);
683 cleanup = TREE_VALUE (cleanup);
684 mark_used (cleanup);
685 mark_addressable (cleanup);
686 /* Pretend it's a normal function. */
687 cleanup = build1 (ADDR_EXPR, cleanup_type, cleanup);
f30432d7 688 }
52a11cbf 689 else
6874c264
JM
690 {
691 cleanup = build_int_2 (0, 0);
692 TREE_TYPE (cleanup) = cleanup_type;
693 }
72b7eeff 694
52a11cbf
RH
695 tmp = tree_cons (NULL_TREE, cleanup, NULL_TREE);
696 tmp = tree_cons (NULL_TREE, throw_type, tmp);
697 tmp = tree_cons (NULL_TREE, ptr, tmp);
698 tmp = build_function_call (fn, tmp);
699
700 /* ??? Indicate that this function call throws throw_type. */
72b7eeff 701
52a11cbf 702 finish_expr_stmt (tmp);
59ccf49d
MM
703
704 exp = finish_init_stmts (stmt_expr, compound_stmt);
8d2733ca
MS
705 }
706 else
a3b49ccd 707 {
52a11cbf 708 /* Rethrow current exception. */
6874c264 709
52a11cbf 710 tree fn = get_identifier ("__cxa_rethrow");
6874c264
JM
711 if (IDENTIFIER_GLOBAL_VALUE (fn))
712 fn = IDENTIFIER_GLOBAL_VALUE (fn);
713 else
52a11cbf
RH
714 {
715 /* Declare void __cxa_rethrow (void). */
716 fn = push_throw_library_fn
717 (fn, build_function_type (void_type_node, void_list_node));
718 }
6874c264
JM
719
720 exp = build_function_call (fn, NULL_TREE);
a3b49ccd 721 }
8d2733ca 722
52a11cbf 723 exp = build1 (THROW_EXPR, void_type_node, exp);
02020185 724
52a11cbf 725 return exp;
8d08fdba 726}
4cfbc546
NS
727
728/* Make sure TYPE is complete, pointer to complete, reference to
729 complete, or pointer to cv void. Issue diagnostic on failure.
730 Return the zero on failure and non-zero on success. FROM can be
731 the expr or decl from whence TYPE came, if available. */
732
733static int
734complete_ptr_ref_or_void_ptr_p (type, from)
735 tree type;
736 tree from;
737{
738 int is_ptr;
739
740 /* Check complete. */
741 type = complete_type_or_else (type, from);
742 if (!type)
743 return 0;
744
745 /* Or a pointer or ref to one, or cv void *. */
746 is_ptr = TREE_CODE (type) == POINTER_TYPE;
747 if (is_ptr || TREE_CODE (type) == REFERENCE_TYPE)
748 {
749 tree core = TREE_TYPE (type);
750
b72801e2 751 if (is_ptr && VOID_TYPE_P (core))
4cfbc546
NS
752 /* OK */;
753 else if (!complete_type_or_else (core, from))
754 return 0;
755 }
756 return 1;
757}
758
d064d75a
GDR
759/* Return truth-value if EXPRESSION is admissible in throw-expression,
760 i.e. if it is not of incomplete type or a pointer/reference to such
761 a type or of an abstract class type. */
762
763static bool
764is_admissible_throw_operand (expr)
765 tree expr;
766{
767 tree type = TREE_TYPE (expr);
768
769 /* 15.1/4 [...] The type of the throw-expression shall not be an
770 incomplete type, or a pointer or a reference to an incomplete
771 type, other than void*, const void*, volatile void*, or
772 const volatile void*. Except for these restriction and the
773 restrictions on type matching mentioned in 15.3, the operand
774 of throw is treated exactly as a function argument in a call
775 (5.2.2) or the operand of a return statement. */
776 if (!complete_ptr_ref_or_void_ptr_p (type, expr))
777 return false;
778
779 /* 10.4/3 An abstract class shall not be used as a parameter type,
780 as a function return type or as type of an explicit
781 conversion. */
782 else if (CLASS_TYPE_P (type) && CLASSTYPE_PURE_VIRTUALS (type))
783 {
784 cp_error ("Expression '%E' of abstract class type '%T' cannot be used in throw-expression", expr, type);
785 return false;
786 }
787
788 return true;
789}
790
1660cb3a
JM
791/* Returns nonzero if FN is a declaration of a standard C library
792 function which is known not to throw.
793
794 [lib.res.on.exception.handling]: None of the functions from the
795 Standard C library shall report an error by throwing an
796 exception, unless it calls a program-supplied function that
797 throws an exception. */
798
799#include "cfns.h"
800
801int
802nothrow_libfn_p (fn)
803 tree fn;
804{
805 tree id;
806
807 if (TREE_PUBLIC (fn)
808 && DECL_EXTERNAL (fn)
92643fea 809 && DECL_NAMESPACE_SCOPE_P (fn)
eb68cb58 810 && DECL_EXTERN_C_P (fn))
1660cb3a
JM
811 /* OK */;
812 else
813 /* Can't be a C library function. */
814 return 0;
815
816 id = DECL_ASSEMBLER_NAME (fn);
817 return !!libc_name_p (IDENTIFIER_POINTER (id), IDENTIFIER_LENGTH (id));
818}
2bc9f1d1
JM
819
820/* Returns nonzero if an exception of type FROM will be caught by a
821 handler for type TO, as per [except.handle]. */
822
823static int
824can_convert_eh (to, from)
825 tree to, from;
826{
827 if (TREE_CODE (to) == REFERENCE_TYPE)
828 to = TREE_TYPE (to);
829 if (TREE_CODE (from) == REFERENCE_TYPE)
830 from = TREE_TYPE (from);
831
832 if (TREE_CODE (to) == POINTER_TYPE && TREE_CODE (from) == POINTER_TYPE)
833 {
834 to = TREE_TYPE (to);
835 from = TREE_TYPE (from);
836
837 if (! at_least_as_qualified_p (to, from))
838 return 0;
839
840 if (TREE_CODE (to) == VOID_TYPE)
841 return 1;
842
843 /* else fall through */
844 }
845
2d46ec83 846 if (CLASS_TYPE_P (to) && CLASS_TYPE_P (from)
2bc9f1d1
JM
847 && PUBLICLY_UNIQUELY_DERIVED_P (to, from))
848 return 1;
849
850 return 0;
851}
852
853/* Check whether any of HANDLERS are shadowed by another handler accepting
854 TYPE. Note that the shadowing may not be complete; even if an exception
855 of type B would be caught by a handler for A, there could be a derived
856 class C for which A is an ambiguous base but B is not, so the handler
857 for B would catch an exception of type C. */
858
859static void
860check_handlers_1 (master, handlers)
861 tree master;
862 tree handlers;
863{
864 tree type = TREE_TYPE (master);
865 tree handler;
866
867 for (handler = handlers; handler; handler = TREE_CHAIN (handler))
868 if (TREE_TYPE (handler)
869 && can_convert_eh (type, TREE_TYPE (handler)))
870 {
871 lineno = STMT_LINENO (handler);
872 cp_warning ("exception of type `%T' will be caught",
873 TREE_TYPE (handler));
874 lineno = STMT_LINENO (master);
875 cp_warning (" by earlier handler for `%T'", type);
876 break;
877 }
878}
879
880/* Given a chain of HANDLERs, make sure that they're OK. */
881
882void
883check_handlers (handlers)
884 tree handlers;
885{
886 tree handler;
887 int save_line = lineno;
888 for (handler = handlers; handler; handler = TREE_CHAIN (handler))
889 {
890 if (TREE_CHAIN (handler) == NULL_TREE)
891 /* No more handlers; nothing to shadow. */;
892 else if (TREE_TYPE (handler) == NULL_TREE)
893 {
894 lineno = STMT_LINENO (handler);
895 cp_pedwarn
896 ("`...' handler must be the last handler for its try block");
897 }
898 else
899 check_handlers_1 (handler, TREE_CHAIN (handler));
900 }
901 lineno = save_line;
902}
This page took 0.814674 seconds and 5 git commands to generate.