Add support for XScale target
[official-gcc.git] / gcc / cp / except.c
blobd3c3d169e6791c3aeef21d352e11789aa6cd3694
1 /* Handle exceptional things in C++.
2 Copyright (C) 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000
3 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.
8 This file is part of GNU CC.
10 GNU CC 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.
15 GNU CC 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.
20 You should have received a copy of the GNU General Public License
21 along with GNU CC; see the file COPYING. If not, write to
22 the Free Software Foundation, 59 Temple Place - Suite 330,
23 Boston, MA 02111-1307, USA. */
26 #include "config.h"
27 #include "system.h"
28 #include "tree.h"
29 #include "rtl.h"
30 #include "expr.h"
31 #include "cp-tree.h"
32 #include "flags.h"
33 #include "obstack.h"
34 #include "output.h"
35 #include "except.h"
36 #include "defaults.h"
37 #include "toplev.h"
38 #include "eh-common.h"
40 static void push_eh_cleanup PARAMS ((tree));
41 static tree build_eh_type_type PARAMS ((tree));
42 static tree call_eh_info PARAMS ((void));
43 static void push_eh_info PARAMS ((void));
44 static tree get_eh_info PARAMS ((void));
45 static tree get_eh_value PARAMS ((void));
46 #if 0
47 static tree get_eh_type PARAMS ((void));
48 static tree get_eh_caught PARAMS ((void));
49 static tree get_eh_handlers PARAMS ((void));
50 #endif
51 static int dtor_nothrow PARAMS ((tree));
52 static tree do_pop_exception PARAMS ((tree));
53 static tree build_eh_type_type_ref PARAMS ((tree));
54 static tree build_terminate_handler PARAMS ((void));
55 static tree alloc_eh_object PARAMS ((tree));
56 static int complete_ptr_ref_or_void_ptr_p PARAMS ((tree, tree));
57 static int can_convert_eh PARAMS ((tree, tree));
58 static void check_handlers_1 PARAMS ((tree, tree));
59 static void initialize_handler_parm PARAMS ((tree));
60 static tree expand_throw PARAMS ((tree));
61 static int decl_is_java_type PARAMS ((tree decl, int err));
63 #include "decl.h"
64 #include "insn-flags.h"
65 #include "obstack.h"
67 /* In a given translation unit we are constrained to catch only C++
68 types or only Java types. `catch_language' holds the current type,
69 and `catch_language_init' registers whether `catch_language' has
70 been set. */
72 static int catch_language_init = 0;
73 static int catch_language;
75 /* ======================================================================
76 Briefly the algorithm works like this:
78 When a constructor or start of a try block is encountered,
79 push_eh_entry (&eh_stack) is called. Push_eh_entry () creates a
80 new entry in the unwind protection stack and returns a label to
81 output to start the protection for that block.
83 When a destructor or end try block is encountered, pop_eh_entry
84 (&eh_stack) is called. Pop_eh_entry () returns the eh_entry it
85 created when push_eh_entry () was called. The eh_entry structure
86 contains three things at this point. The start protect label,
87 the end protect label, and the exception handler label. The end
88 protect label should be output before the call to the destructor
89 (if any). If it was a destructor, then its parse tree is stored
90 in the finalization variable in the eh_entry structure. Otherwise
91 the finalization variable is set to NULL to reflect the fact that
92 it is the end of a try block. Next, this modified eh_entry node
93 is enqueued in the finalizations queue by calling
94 enqueue_eh_entry (&queue,entry).
96 +---------------------------------------------------------------+
97 |XXX: Will need modification to deal with partially |
98 | constructed arrays of objects |
99 | |
100 | Basically, this consists of keeping track of how many |
101 | of the objects have been constructed already (this |
102 | should be in a register though, so that shouldn't be a |
103 | problem. |
104 +---------------------------------------------------------------+
106 When a catch block is encountered, there is a lot of work to be
107 done.
109 Since we don't want to generate the catch block inline with the
110 regular flow of the function, we need to have some way of doing
111 so. Luckily, we can use sequences to defer the catch sections.
112 When the start of a catch block is encountered, we start the
113 sequence. After the catch block is generated, we end the
114 sequence.
116 Next we must insure that when the catch block is executed, all
117 finalizations for the matching try block have been completed. If
118 any of those finalizations throw an exception, we must call
119 terminate according to the ARM (section r.15.6.1). What this
120 means is that we need to dequeue and emit finalizations for each
121 entry in the eh_queue until we get to an entry with a NULL
122 finalization field. For any of the finalization entries, if it
123 is not a call to terminate (), we must protect it by giving it
124 another start label, end label, and exception handler label,
125 setting its finalization tree to be a call to terminate (), and
126 enqueue'ing this new eh_entry to be output at an outer level.
127 Finally, after all that is done, we can get around to outputting
128 the catch block which basically wraps all the "catch (...) {...}"
129 statements in a big if/then/else construct that matches the
130 correct block to call.
132 ===================================================================== */
134 /* ====================================================================== */
136 /* sets up all the global eh stuff that needs to be initialized at the
137 start of compilation. */
139 void
140 init_exception_processing ()
142 /* void vtype () */
143 tree vtype = build_function_type (void_type_node, void_list_node);
145 if (flag_honor_std)
146 push_namespace (std_identifier);
147 terminate_node = build_cp_library_fn_ptr ("terminate", vtype);
148 TREE_THIS_VOLATILE (terminate_node) = 1;
149 TREE_NOTHROW (terminate_node) = 1;
150 if (flag_honor_std)
151 pop_namespace ();
153 set_exception_lang_code (EH_LANG_C_plus_plus);
154 set_exception_version_code (1);
156 /* If we use setjmp/longjmp EH, arrange for all cleanup actions to
157 be protected with __terminate. */
158 protect_cleanup_actions_with_terminate = 1;
161 /* Retrieve a pointer to the cp_eh_info node for the current exception. */
163 static tree
164 call_eh_info ()
166 tree fn;
168 fn = get_identifier ("__start_cp_handler");
169 if (IDENTIFIER_GLOBAL_VALUE (fn))
170 fn = IDENTIFIER_GLOBAL_VALUE (fn);
171 else
173 tree t1, t, fields[7];
175 /* Declare cp_eh_info * __start_cp_handler (void),
176 as defined in exception.cc. */
178 /* struct cp_eh_info. This must match exception.cc. Note that this
179 type is not pushed anywhere. */
180 t1= make_aggr_type (RECORD_TYPE);
181 fields[0] = build_decl (FIELD_DECL,
182 get_identifier ("handler_label"), ptr_type_node);
183 fields[1] = build_decl (FIELD_DECL,
184 get_identifier ("dynamic_handler_chain"), ptr_type_node);
185 fields[2] = build_decl (FIELD_DECL,
186 get_identifier ("info"), ptr_type_node);
187 fields[3] = build_decl (FIELD_DECL,
188 get_identifier ("table_index"), ptr_type_node);
189 /* N.B.: The fourth field LEN is expected to be
190 the number of fields - 1, not the total number of fields. */
191 finish_builtin_type (t1, "eh_context", fields, 3, ptr_type_node);
192 t1 = build_pointer_type (t1);
194 t1= make_aggr_type (RECORD_TYPE);
195 fields[0] = build_decl (FIELD_DECL,
196 get_identifier ("match_function"), ptr_type_node);
197 fields[1] = build_decl (FIELD_DECL,
198 get_identifier ("language"), short_integer_type_node);
199 fields[2] = build_decl (FIELD_DECL,
200 get_identifier ("version"), short_integer_type_node);
201 /* N.B.: The fourth field LEN is expected to be
202 the number of fields - 1, not the total number of fields. */
203 finish_builtin_type (t1, "__eh_info", fields, 2, ptr_type_node);
204 t = make_aggr_type (RECORD_TYPE);
205 fields[0] = build_decl (FIELD_DECL,
206 get_identifier ("eh_info"), t1);
207 fields[1] = build_decl (FIELD_DECL, get_identifier ("value"),
208 ptr_type_node);
209 fields[2] = build_decl (FIELD_DECL, get_identifier ("type"),
210 ptr_type_node);
211 fields[3] = build_decl
212 (FIELD_DECL, get_identifier ("cleanup"),
213 build_pointer_type (build_function_type
214 (ptr_type_node, tree_cons
215 (NULL_TREE, ptr_type_node, void_list_node))));
216 fields[4] = build_decl (FIELD_DECL, get_identifier ("caught"),
217 boolean_type_node);
218 fields[5] = build_decl (FIELD_DECL, get_identifier ("next"),
219 build_pointer_type (t));
220 fields[6] = build_decl
221 (FIELD_DECL, get_identifier ("handlers"), long_integer_type_node);
222 /* N.B.: The fourth field LEN is expected to be
223 the number of fields - 1, not the total number of fields. */
224 finish_builtin_type (t, "cp_eh_info", fields, 6, ptr_type_node);
225 t = build_pointer_type (t);
227 /* And now the function. */
228 fn = push_library_fn (fn, build_function_type (t, void_list_node));
230 return build_function_call (fn, NULL_TREE);
233 /* Retrieve a pointer to the cp_eh_info node for the current exception
234 and save it in the current binding level. */
236 static void
237 push_eh_info ()
239 tree decl, fn = call_eh_info ();
241 /* Remember the pointer to the current exception info; it won't change
242 during this catch block. */
243 decl = build_decl (VAR_DECL, get_identifier ("__exception_info"),
244 TREE_TYPE (fn));
245 DECL_ARTIFICIAL (decl) = 1;
246 DECL_INITIAL (decl) = fn;
247 decl = pushdecl (decl);
248 cp_finish_decl (decl, fn, NULL_TREE, 0);
251 /* Returns a reference to the cp_eh_info node for the current exception. */
253 static tree
254 get_eh_info ()
256 /* Look for the pointer pushed in push_eh_info. */
257 tree t = lookup_name (get_identifier ("__exception_info"), 0);
258 return build_indirect_ref (t, NULL_PTR);
261 /* Returns a reference to the current exception object. */
263 static tree
264 get_eh_value ()
266 return build_component_ref (get_eh_info (), get_identifier ("value"),
267 NULL_TREE, 0);
270 /* Returns a reference to the current exception type. */
272 #if 0
273 static tree
274 get_eh_type ()
276 return build_component_ref (get_eh_info (), get_identifier ("type"),
277 NULL_TREE, 0);
280 /* Returns a reference to whether or not the current exception
281 has been caught. */
283 static tree
284 get_eh_caught ()
286 return build_component_ref (get_eh_info (), get_identifier ("caught"),
287 NULL_TREE, 0);
290 /* Returns a reference to whether or not the current exception
291 has been caught. */
293 static tree
294 get_eh_handlers ()
296 return build_component_ref (get_eh_info (), get_identifier ("handlers"),
297 NULL_TREE, 0);
299 #endif
301 /* Build a type value for use at runtime for a type that is matched
302 against by the exception handling system. */
304 static tree
305 build_eh_type_type (type)
306 tree type;
308 if (type == error_mark_node)
309 return error_mark_node;
311 /* peel back references, so they match. */
312 if (TREE_CODE (type) == REFERENCE_TYPE)
313 type = TREE_TYPE (type);
315 /* Peel off cv qualifiers. */
316 type = TYPE_MAIN_VARIANT (type);
318 return build1 (ADDR_EXPR, ptr_type_node, get_typeid_1 (type));
321 /* Build the address of a typeinfo decl for use in the runtime
322 matching field of the new exception model */
324 static tree
325 build_eh_type_type_ref (type)
326 tree type;
328 tree exp;
330 if (type == NULL_TREE || type == error_mark_node)
331 return type;
333 /* peel back references, so they match. */
334 if (TREE_CODE (type) == REFERENCE_TYPE)
335 type = TREE_TYPE (type);
337 /* Peel off cv qualifiers. */
338 type = TYPE_MAIN_VARIANT (type);
340 exp = get_tinfo_decl (type);
341 mark_used (exp);
342 exp = build1 (ADDR_EXPR, ptr_type_node, exp);
344 return (exp);
347 /* This routine is called to mark all the symbols representing runtime
348 type functions in the exception table as having been referenced.
349 This will make sure code is emitted for them. Called from finish_file. */
351 void
352 mark_all_runtime_matches ()
354 int x,num;
355 void **ptr;
356 tree exp;
358 num = find_all_handler_type_matches (&ptr);
359 if (num == 0 || ptr == NULL)
360 return;
362 for (x=0; x <num; x++)
364 exp = (tree) ptr[x];
365 if (TREE_CODE (exp) == ADDR_EXPR)
367 exp = TREE_OPERAND (exp, 0);
368 if (TREE_CODE (exp) == FUNCTION_DECL)
369 TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (exp)) = 1;
373 free (ptr);
376 /* Returns nonzero if cleaning up an exception of type TYPE (which can be
377 NULL_TREE for a ... handler) will not throw an exception. */
379 static int
380 dtor_nothrow (type)
381 tree type;
383 tree fn;
385 if (type == NULL_TREE)
386 return 0;
388 if (! TYPE_HAS_DESTRUCTOR (type))
389 return 1;
391 fn = lookup_member (type, dtor_identifier, 0, 0);
392 fn = TREE_VALUE (fn);
393 return TREE_NOTHROW (fn);
396 /* Build up a call to __cp_pop_exception, to destroy the exception object
397 for the current catch block if no others are currently using it. */
399 static tree
400 do_pop_exception (type)
401 tree type;
403 tree fn, cleanup;
404 fn = get_identifier ("__cp_pop_exception");
405 if (IDENTIFIER_GLOBAL_VALUE (fn))
406 fn = IDENTIFIER_GLOBAL_VALUE (fn);
407 else
409 /* Declare void __cp_pop_exception (void *),
410 as defined in exception.cc. */
411 fn = push_void_library_fn
412 (fn, tree_cons (NULL_TREE, ptr_type_node, void_list_node));
413 /* This can throw if the destructor for the exception throws. */
414 TREE_NOTHROW (fn) = 0;
417 /* Arrange to do a dynamically scoped cleanup upon exit from this region. */
418 cleanup = lookup_name (get_identifier ("__exception_info"), 0);
419 cleanup = build_function_call (fn, tree_cons
420 (NULL_TREE, cleanup, NULL_TREE));
421 TREE_NOTHROW (cleanup) = dtor_nothrow (type);
422 return cleanup;
425 /* This routine creates the cleanup for the current exception. */
427 static void
428 push_eh_cleanup (type)
429 tree type;
431 finish_decl_cleanup (NULL_TREE, do_pop_exception (type));
434 /* Build up a call to terminate on the function obstack, for use as an
435 exception handler. */
437 static tree
438 build_terminate_handler ()
440 return build_function_call (terminate_node, NULL_TREE);
443 /* Return nonzero value if DECL is a Java type suitable for catch or
444 throw. */
446 static int
447 decl_is_java_type (decl, err)
448 tree decl;
449 int err;
451 int r = (TREE_CODE (decl) == POINTER_TYPE
452 && TREE_CODE (TREE_TYPE (decl)) == RECORD_TYPE
453 && TYPE_FOR_JAVA (TREE_TYPE (decl)));
455 if (err)
457 if (TREE_CODE (decl) == REFERENCE_TYPE
458 && TREE_CODE (TREE_TYPE (decl)) == RECORD_TYPE
459 && TYPE_FOR_JAVA (TREE_TYPE (decl)))
461 /* Can't throw a reference. */
462 cp_error ("type `%T' is disallowed in Java `throw' or `catch'",
463 decl);
466 if (r)
468 tree jthrow_node
469 = IDENTIFIER_GLOBAL_VALUE (get_identifier ("jthrowable"));
470 if (jthrow_node == NULL_TREE)
471 fatal ("call to Java `catch' or `throw', while `jthrowable' undefined");
472 jthrow_node = TREE_TYPE (TREE_TYPE (jthrow_node));
474 if (! DERIVED_FROM_P (jthrow_node, TREE_TYPE (decl)))
476 /* Thrown object must be a Throwable. */
477 cp_error ("type `%T' is not derived from `java::lang::Throwable'",
478 TREE_TYPE (decl));
483 return r;
486 /* Initialize the catch parameter DECL. */
488 static void
489 initialize_handler_parm (decl)
490 tree decl;
492 tree exp;
493 tree init;
494 tree init_type;
495 int lang;
497 /* Make sure we mark the catch param as used, otherwise we'll get a
498 warning about an unused ((anonymous)). */
499 TREE_USED (decl) = 1;
501 /* Figure out the type that the initializer is. */
502 init_type = TREE_TYPE (decl);
503 if (TREE_CODE (init_type) != REFERENCE_TYPE
504 && TREE_CODE (init_type) != POINTER_TYPE)
505 init_type = build_reference_type (init_type);
507 if (decl_is_java_type (init_type, 0))
509 tree fn
510 = builtin_function ("_Jv_exception_info",
511 build_function_type (ptr_type_node,
512 tree_cons (NULL_TREE,
513 void_type_node,
514 NULL_TREE)),
515 0, NOT_BUILT_IN, NULL_PTR);
517 exp = build (CALL_EXPR, ptr_type_node,
518 build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (fn)),
519 fn),
520 NULL_TREE, NULL_TREE);
521 TREE_SIDE_EFFECTS (exp) = 1;
522 lang = EH_LANG_Java;
524 set_exception_lang_code (EH_LANG_Java);
525 set_exception_version_code (1);
527 else
529 exp = get_eh_value ();
530 lang = EH_LANG_C_plus_plus;
533 if (catch_language_init)
535 if (lang != catch_language)
536 error ("mixing C++ and Java `catch'es in single translation unit");
538 else
540 catch_language_init = 1;
541 catch_language = lang;
544 /* Since pointers are passed by value, initialize a reference to
545 pointer catch parm with the address of the value slot. */
546 if (TREE_CODE (init_type) == REFERENCE_TYPE
547 && TREE_CODE (TREE_TYPE (init_type)) == POINTER_TYPE)
548 exp = build_unary_op (ADDR_EXPR, exp, 1);
550 exp = ocp_convert (init_type , exp, CONV_IMPLICIT|CONV_FORCE_TEMP, 0);
552 init = convert_from_reference (exp);
554 /* If the constructor for the catch parm exits via an exception, we
555 must call terminate. See eh23.C. */
556 if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl)))
558 /* Generate the copy constructor call directly so we can wrap it.
559 See also expand_default_init. */
560 init = ocp_convert (TREE_TYPE (decl), init,
561 CONV_IMPLICIT|CONV_FORCE_TEMP, 0);
562 init = build (TRY_CATCH_EXPR, TREE_TYPE (init), init,
563 build_terminate_handler ());
566 /* Let `cp_finish_decl' know that this initializer is ok. */
567 DECL_INITIAL (decl) = error_mark_node;
568 decl = pushdecl (decl);
570 start_decl_1 (decl);
571 cp_finish_decl (decl, init, NULL_TREE,
572 LOOKUP_ONLYCONVERTING|DIRECT_BIND);
575 /* Call this to start a catch block. DECL is the catch parameter. */
577 tree
578 expand_start_catch_block (decl)
579 tree decl;
581 tree compound_stmt_1;
582 tree compound_stmt_2;
584 if (! doing_eh (1))
585 return NULL_TREE;
587 /* Make sure this declaration is reasonable. */
588 if (decl && !complete_ptr_ref_or_void_ptr_p (TREE_TYPE (decl), NULL_TREE))
589 decl = NULL_TREE;
591 /* Create a binding level for the eh_info and the exception object
592 cleanup. */
593 compound_stmt_1 = begin_compound_stmt (/*has_no_scope=*/0);
595 if (! decl || ! decl_is_java_type (TREE_TYPE (decl), 1))
597 /* The ordinary C++ case. */
598 tree type;
600 if (decl)
601 type = TREE_TYPE (decl);
602 else
603 type = NULL_TREE;
604 begin_catch_block (build_eh_type_type_ref (type));
606 push_eh_info ();
607 push_eh_cleanup (type);
609 else
611 /* The Java case. In this case, the match_info is a pointer to
612 the Java class object. We assume that the class is a
613 compiled class. */
614 tree ref = build_java_class_ref (TREE_TYPE (TREE_TYPE (decl)));
615 begin_catch_block (build1 (ADDR_EXPR, jclass_node, ref));
618 /* Create a binding level for the parm. */
619 compound_stmt_2 = begin_compound_stmt (/*has_no_scope=*/0);
621 if (decl)
622 initialize_handler_parm (decl);
624 return build_tree_list (compound_stmt_1, compound_stmt_2);
628 /* Call this to end a catch block. Its responsible for emitting the
629 code to handle jumping back to the correct place, and for emitting
630 the label to jump to if this catch block didn't match. */
632 void
633 expand_end_catch_block (blocks)
634 tree blocks;
636 tree compound_stmt_1 = blocks ? TREE_PURPOSE (blocks): NULL_TREE;
637 tree compound_stmt_2 = blocks ? TREE_VALUE (blocks): NULL_TREE;
639 if (! doing_eh (1))
640 return;
642 /* The exception being handled is rethrown if control reaches the end of
643 a handler of the function-try-block of a constructor or destructor. */
644 if (in_function_try_handler
645 && (DECL_CONSTRUCTOR_P (current_function_decl)
646 || DECL_DESTRUCTOR_P (current_function_decl)))
647 finish_expr_stmt (build_throw (NULL_TREE));
649 /* Cleanup the EH parameter. */
650 finish_compound_stmt (/*has_no_scope=*/0, compound_stmt_2);
651 /* Cleanup the EH object. */
652 finish_compound_stmt (/*has_no_scope=*/0, compound_stmt_1);
655 /* An exception spec is implemented more or less like:
657 try {
658 function body;
659 } catch (...) {
660 void *p[] = { typeid(raises) };
661 __check_eh_spec (p, count);
664 __check_eh_spec in exception.cc handles all the details. */
666 tree
667 expand_start_eh_spec ()
669 return begin_try_block ();
672 void
673 expand_end_eh_spec (raises, try_block)
674 tree raises;
675 tree try_block;
677 tree tmp, fn, decl, types = NULL_TREE;
678 tree blocks;
679 tree handler;
680 int count = 0;
682 finish_try_block (try_block);
683 handler = begin_handler ();
684 blocks = finish_handler_parms (NULL_TREE, handler);
686 if (TREE_VALUE (raises) == NULL_TREE)
688 fn = get_identifier ("__check_null_eh_spec");
689 if (IDENTIFIER_GLOBAL_VALUE (fn))
690 fn = IDENTIFIER_GLOBAL_VALUE (fn);
691 else
693 tmp = build_function_type (void_type_node, void_list_node);
694 fn = push_throw_library_fn (fn, tmp);
695 /* Since the spec doesn't allow any exceptions, this call
696 will never throw. */
697 TREE_NOTHROW (fn) = 1;
699 tmp = NULL_TREE;
701 else
703 /* Build up an array of type_infos. */
704 for (; raises && TREE_VALUE (raises); raises = TREE_CHAIN (raises))
706 types = tree_cons
707 (NULL_TREE, build_eh_type_type (TREE_VALUE (raises)), types);
708 ++count;
711 types = build_nt (CONSTRUCTOR, NULL_TREE, types);
712 TREE_HAS_CONSTRUCTOR (types) = 1;
714 /* We can't pass the CONSTRUCTOR directly, so stick it in a variable. */
715 tmp = build_cplus_array_type (const_ptr_type_node, NULL_TREE);
716 decl = build_decl (VAR_DECL, NULL_TREE, tmp);
717 DECL_ARTIFICIAL (decl) = 1;
718 DECL_INITIAL (decl) = types;
719 DECL_CONTEXT (decl) = current_function_decl;
720 cp_finish_decl (decl, types, NULL_TREE, 0);
722 decl = decay_conversion (decl);
724 fn = get_identifier ("__check_eh_spec");
725 if (IDENTIFIER_GLOBAL_VALUE (fn))
726 fn = IDENTIFIER_GLOBAL_VALUE (fn);
727 else
729 tmp = tree_cons
730 (NULL_TREE, integer_type_node, tree_cons
731 (NULL_TREE, TREE_TYPE (decl), void_list_node));
732 tmp = build_function_type (void_type_node, tmp);
734 fn = push_throw_library_fn (fn, tmp);
737 tmp = tree_cons (NULL_TREE, build_int_2 (count, 0),
738 tree_cons (NULL_TREE, decl, NULL_TREE));
741 tmp = build_call (fn, tmp);
742 finish_expr_stmt (tmp);
744 finish_handler (blocks, handler);
745 finish_handler_sequence (try_block);
748 /* This is called to expand all the toplevel exception handling
749 finalization for a function. It should only be called once per
750 function. */
752 void
753 expand_exception_blocks ()
755 do_pending_stack_adjust ();
757 if (catch_clauses)
759 rtx funcend = gen_label_rtx ();
760 emit_jump (funcend);
762 /* We cannot protect n regions this way if we must flow into the
763 EH region through the top of the region, as we have to with
764 the setjmp/longjmp approach. */
765 if (exceptions_via_longjmp == 0)
766 expand_eh_region_start ();
768 emit_insns (catch_clauses);
769 catch_clauses = catch_clauses_last = NULL_RTX;
771 if (exceptions_via_longjmp == 0)
772 expand_eh_region_end (build_terminate_handler ());
774 emit_insns (catch_clauses);
775 catch_clauses = catch_clauses_last = NULL_RTX;
776 emit_label (funcend);
780 /* Return a pointer to a buffer for an exception object of type TYPE. */
782 static tree
783 alloc_eh_object (type)
784 tree type;
786 tree fn, exp;
788 fn = get_identifier ("__eh_alloc");
789 if (IDENTIFIER_GLOBAL_VALUE (fn))
790 fn = IDENTIFIER_GLOBAL_VALUE (fn);
791 else
793 /* Declare __eh_alloc (size_t), as defined in exception.cc. */
794 tree tmp = tree_cons (NULL_TREE, sizetype, void_list_node);
795 fn = push_library_fn (fn, build_function_type (ptr_type_node, tmp));
798 exp = build_function_call (fn, tree_cons
799 (NULL_TREE, size_in_bytes (type), NULL_TREE));
800 exp = build1 (NOP_EXPR, build_pointer_type (type), exp);
801 return exp;
804 /* Expand a throw statement. This follows the following
805 algorithm:
807 1. Allocate space to save the current PC onto the stack.
808 2. Generate and emit a label and save its address into the
809 newly allocated stack space since we can't save the pc directly.
810 3. If this is the first call to throw in this function:
811 generate a label for the throw block
812 4. jump to the throw block label. */
814 static tree
815 expand_throw (exp)
816 tree exp;
818 tree fn;
820 if (! doing_eh (1))
821 return error_mark_node;
823 if (exp
824 && decl_is_java_type (TREE_TYPE (exp), 1))
826 /* A Java `throw' statement. */
827 tree args = tree_cons (NULL_TREE, exp, NULL);
829 fn = get_identifier (exceptions_via_longjmp
830 ? "_Jv_Sjlj_Throw"
831 : "_Jv_Throw");
832 if (IDENTIFIER_GLOBAL_VALUE (fn))
833 fn = IDENTIFIER_GLOBAL_VALUE (fn);
834 else
836 /* Declare _Jv_Throw (void *), as defined in Java's
837 exception.cc. */
838 tree tmp = tree_cons (NULL_TREE, ptr_type_node, void_list_node);
839 tmp = build_function_type (ptr_type_node, tmp);
840 fn = push_library_fn (fn, tmp);
841 TREE_THIS_VOLATILE (fn) = 1;
842 TREE_NOTHROW (fn) = 0;
845 exp = build_function_call (fn, args);
847 else if (exp)
849 tree throw_type;
850 tree cleanup = NULL_TREE, e;
851 tree stmt_expr;
852 tree compound_stmt;
853 tree try_block;
855 begin_init_stmts (&stmt_expr, &compound_stmt);
857 /* throw expression */
858 /* First, decay it. */
859 exp = decay_conversion (exp);
861 /* The CLEANUP_TYPE is the internal type of a destructor. Under
862 the old ABI, destructors are two-argument functions; under
863 the new ABI they take only one argument. */
864 if (cleanup_type == NULL_TREE)
866 tree arg_types;
868 arg_types = void_list_node;
869 if (!flag_new_abi)
870 arg_types = tree_cons (NULL_TREE, integer_type_node, arg_types);
871 arg_types = tree_cons (NULL_TREE, ptr_type_node, arg_types);
872 cleanup_type = (build_pointer_type
873 (build_function_type (void_type_node, arg_types)));
876 if (TYPE_PTR_P (TREE_TYPE (exp)))
877 throw_type = build_eh_type_type (TREE_TYPE (exp));
878 else
880 tree object, ptr;
882 /* OK, this is kind of wacky. The standard says that we call
883 terminate when the exception handling mechanism, after
884 completing evaluation of the expression to be thrown but
885 before the exception is caught (_except.throw_), calls a
886 user function that exits via an uncaught exception.
888 So we have to protect the actual initialization of the
889 exception object with terminate(), but evaluate the expression
890 first. We also expand the call to __eh_alloc
891 first. Since there could be temps in the expression, we need
892 to handle that, too. */
894 my_friendly_assert (stmts_are_full_exprs_p () == 1, 19990926);
896 /* Store the throw expression into a temp. This can be less
897 efficient than storing it into the allocated space directly, but
898 oh well. To do this efficiently we would need to insinuate
899 ourselves into expand_call. */
900 if (TREE_SIDE_EFFECTS (exp))
902 tree temp = create_temporary_var (TREE_TYPE (exp));
903 DECL_INITIAL (temp) = exp;
904 cp_finish_decl (temp, exp, NULL_TREE, LOOKUP_ONLYCONVERTING);
905 exp = temp;
908 /* Allocate the space for the exception. */
909 ptr = save_expr (alloc_eh_object (TREE_TYPE (exp)));
910 finish_expr_stmt (ptr);
912 try_block = begin_try_block ();
913 object = build_indirect_ref (ptr, NULL_PTR);
914 exp = build_modify_expr (object, INIT_EXPR, exp);
916 if (exp == error_mark_node)
917 error (" in thrown expression");
919 finish_expr_stmt (exp);
920 finish_cleanup_try_block (try_block);
921 finish_cleanup (build_terminate_handler (), try_block);
923 throw_type = build_eh_type_type (TREE_TYPE (object));
925 if (TYPE_HAS_DESTRUCTOR (TREE_TYPE (object)))
927 cleanup = lookup_fnfields (TYPE_BINFO (TREE_TYPE (object)),
928 (flag_new_abi
929 ? complete_dtor_identifier
930 : dtor_identifier),
932 cleanup = TREE_VALUE (cleanup);
933 mark_used (cleanup);
934 mark_addressable (cleanup);
935 /* Pretend it's a normal function. */
936 cleanup = build1 (ADDR_EXPR, cleanup_type, cleanup);
939 exp = ptr;
942 /* Cast EXP to `void *' so that it will match the prototype for
943 __cp_push_exception. */
944 exp = convert (ptr_type_node, exp);
946 if (cleanup == NULL_TREE)
948 cleanup = build_int_2 (0, 0);
949 TREE_TYPE (cleanup) = cleanup_type;
952 fn = cp_push_exception_identifier;
953 if (IDENTIFIER_GLOBAL_VALUE (fn))
954 fn = IDENTIFIER_GLOBAL_VALUE (fn);
955 else
957 /* Declare __cp_push_exception (void*, void*, void (*)(void*, int)),
958 as defined in exception.cc. */
959 tree tmp;
960 tmp = tree_cons
961 (NULL_TREE, ptr_type_node, tree_cons
962 (NULL_TREE, ptr_type_node, tree_cons
963 (NULL_TREE, cleanup_type, void_list_node)));
964 fn = push_void_library_fn (fn, tmp);
967 e = tree_cons (NULL_TREE, exp, tree_cons
968 (NULL_TREE, throw_type, tree_cons
969 (NULL_TREE, cleanup, NULL_TREE)));
970 finish_expr_stmt (build_function_call (fn, e));
972 exp = finish_init_stmts (stmt_expr, compound_stmt);
974 else
976 /* rethrow current exception; note that it's no longer caught. */
978 tree fn = get_identifier ("__uncatch_exception");
979 if (IDENTIFIER_GLOBAL_VALUE (fn))
980 fn = IDENTIFIER_GLOBAL_VALUE (fn);
981 else
982 /* Declare void __uncatch_exception (void)
983 as defined in exception.cc. */
984 fn = push_void_library_fn (fn, void_list_node);
986 exp = build_function_call (fn, NULL_TREE);
989 return exp;
992 /* Build a throw expression. */
994 tree
995 build_throw (e)
996 tree e;
998 if (e == error_mark_node)
999 return e;
1001 if (processing_template_decl)
1002 return build_min (THROW_EXPR, void_type_node, e);
1004 if (e == null_node)
1005 cp_warning ("throwing NULL, which has integral, not pointer type");
1007 if (e != NULL_TREE)
1009 if (!complete_ptr_ref_or_void_ptr_p (TREE_TYPE (e), e))
1010 return error_mark_node;
1013 e = expand_throw (e);
1014 e = build1 (THROW_EXPR, void_type_node, e);
1015 TREE_SIDE_EFFECTS (e) = 1;
1016 TREE_USED (e) = 1;
1018 return e;
1021 /* Make sure TYPE is complete, pointer to complete, reference to
1022 complete, or pointer to cv void. Issue diagnostic on failure.
1023 Return the zero on failure and non-zero on success. FROM can be
1024 the expr or decl from whence TYPE came, if available. */
1026 static int
1027 complete_ptr_ref_or_void_ptr_p (type, from)
1028 tree type;
1029 tree from;
1031 int is_ptr;
1033 /* Check complete. */
1034 type = complete_type_or_else (type, from);
1035 if (!type)
1036 return 0;
1038 /* Or a pointer or ref to one, or cv void *. */
1039 is_ptr = TREE_CODE (type) == POINTER_TYPE;
1040 if (is_ptr || TREE_CODE (type) == REFERENCE_TYPE)
1042 tree core = TREE_TYPE (type);
1044 if (is_ptr && VOID_TYPE_P (core))
1045 /* OK */;
1046 else if (!complete_type_or_else (core, from))
1047 return 0;
1049 return 1;
1052 /* Returns nonzero if FN is a declaration of a standard C library
1053 function which is known not to throw.
1055 [lib.res.on.exception.handling]: None of the functions from the
1056 Standard C library shall report an error by throwing an
1057 exception, unless it calls a program-supplied function that
1058 throws an exception. */
1060 #include "cfns.h"
1063 nothrow_libfn_p (fn)
1064 tree fn;
1066 tree id;
1068 if (TREE_PUBLIC (fn)
1069 && DECL_EXTERNAL (fn)
1070 && DECL_EXTERN_C_P (fn))
1071 /* OK */;
1072 else
1073 /* Can't be a C library function. */
1074 return 0;
1076 id = DECL_ASSEMBLER_NAME (fn);
1077 return !!libc_name_p (IDENTIFIER_POINTER (id), IDENTIFIER_LENGTH (id));
1080 /* Returns nonzero if an exception of type FROM will be caught by a
1081 handler for type TO, as per [except.handle]. */
1083 static int
1084 can_convert_eh (to, from)
1085 tree to, from;
1087 if (TREE_CODE (to) == REFERENCE_TYPE)
1088 to = TREE_TYPE (to);
1089 if (TREE_CODE (from) == REFERENCE_TYPE)
1090 from = TREE_TYPE (from);
1092 if (TREE_CODE (to) == POINTER_TYPE && TREE_CODE (from) == POINTER_TYPE)
1094 to = TREE_TYPE (to);
1095 from = TREE_TYPE (from);
1097 if (! at_least_as_qualified_p (to, from))
1098 return 0;
1100 if (TREE_CODE (to) == VOID_TYPE)
1101 return 1;
1103 /* else fall through */
1106 if (IS_AGGR_TYPE (to) && IS_AGGR_TYPE (from)
1107 && PUBLICLY_UNIQUELY_DERIVED_P (to, from))
1108 return 1;
1110 return 0;
1113 /* Check whether any of HANDLERS are shadowed by another handler accepting
1114 TYPE. Note that the shadowing may not be complete; even if an exception
1115 of type B would be caught by a handler for A, there could be a derived
1116 class C for which A is an ambiguous base but B is not, so the handler
1117 for B would catch an exception of type C. */
1119 static void
1120 check_handlers_1 (master, handlers)
1121 tree master;
1122 tree handlers;
1124 tree type = TREE_TYPE (master);
1125 tree handler;
1127 for (handler = handlers; handler; handler = TREE_CHAIN (handler))
1128 if (TREE_TYPE (handler)
1129 && can_convert_eh (type, TREE_TYPE (handler)))
1131 lineno = STMT_LINENO (handler);
1132 cp_warning ("exception of type `%T' will be caught",
1133 TREE_TYPE (handler));
1134 lineno = STMT_LINENO (master);
1135 cp_warning (" by earlier handler for `%T'", type);
1136 break;
1140 /* Given a chain of HANDLERs, make sure that they're OK. */
1142 void
1143 check_handlers (handlers)
1144 tree handlers;
1146 tree handler;
1147 int save_line = lineno;
1148 for (handler = handlers; handler; handler = TREE_CHAIN (handler))
1150 if (TREE_CHAIN (handler) == NULL_TREE)
1151 /* No more handlers; nothing to shadow. */;
1152 else if (TREE_TYPE (handler) == NULL_TREE)
1154 lineno = STMT_LINENO (handler);
1155 cp_pedwarn
1156 ("`...' handler must be the last handler for its try block");
1158 else
1159 check_handlers_1 (handler, TREE_CHAIN (handler));
1161 lineno = save_line;