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