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