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)
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. */
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));
47 static tree get_eh_type PARAMS ((void));
48 static tree get_eh_caught PARAMS ((void));
49 static tree get_eh_handlers PARAMS ((void));
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));
64 #include "insn-flags.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
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 |
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 |
104 +---------------------------------------------------------------+
106 When a catch block is encountered, there is a lot of work to be
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
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. */
140 init_exception_processing ()
143 tree vtype = build_function_type (void_type_node, void_list_node);
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;
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. */
168 fn = get_identifier ("__start_cp_handler");
169 if (IDENTIFIER_GLOBAL_VALUE (fn))
170 fn = IDENTIFIER_GLOBAL_VALUE (fn);
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"),
209 fields[2] = build_decl (FIELD_DECL, get_identifier ("type"),
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"),
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. */
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"),
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. */
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. */
266 return build_component_ref (get_eh_info (), get_identifier ("value"),
270 /* Returns a reference to the current exception type. */
276 return build_component_ref (get_eh_info (), get_identifier ("type"),
280 /* Returns a reference to whether or not the current exception
286 return build_component_ref (get_eh_info (), get_identifier ("caught"),
290 /* Returns a reference to whether or not the current exception
296 return build_component_ref (get_eh_info (), get_identifier ("handlers"),
301 /* Build a type value for use at runtime for a type that is matched
302 against by the exception handling system. */
305 build_eh_type_type (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 */
325 build_eh_type_type_ref (type)
330 if (type == NULL_TREE || type == error_mark_node)
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);
342 exp = build1 (ADDR_EXPR, ptr_type_node, 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. */
352 mark_all_runtime_matches ()
358 num = find_all_handler_type_matches (&ptr);
359 if (num == 0 || ptr == NULL)
362 for (x=0; x <num; 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;
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. */
385 if (type == NULL_TREE)
388 if (! TYPE_HAS_DESTRUCTOR (type))
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. */
400 do_pop_exception (type)
404 fn = get_identifier ("__cp_pop_exception");
405 if (IDENTIFIER_GLOBAL_VALUE (fn))
406 fn = IDENTIFIER_GLOBAL_VALUE (fn);
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);
425 /* This routine creates the cleanup for the current exception. */
428 push_eh_cleanup (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. */
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
447 decl_is_java_type (decl, err)
451 int r = (TREE_CODE (decl) == POINTER_TYPE
452 && TREE_CODE (TREE_TYPE (decl)) == RECORD_TYPE
453 && TYPE_FOR_JAVA (TREE_TYPE (decl)));
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'",
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'",
486 /* Initialize the catch parameter DECL. */
489 initialize_handler_parm (decl)
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))
510 = builtin_function ("_Jv_exception_info",
511 build_function_type (ptr_type_node,
512 tree_cons (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)),
520 NULL_TREE, NULL_TREE);
521 TREE_SIDE_EFFECTS (exp) = 1;
524 set_exception_lang_code (EH_LANG_Java);
525 set_exception_version_code (1);
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");
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);
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. */
578 expand_start_catch_block (decl)
581 tree compound_stmt_1;
582 tree compound_stmt_2;
587 /* Make sure this declaration is reasonable. */
588 if (decl && !complete_ptr_ref_or_void_ptr_p (TREE_TYPE (decl), NULL_TREE))
591 /* Create a binding level for the eh_info and the exception object
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. */
601 type = TREE_TYPE (decl);
604 begin_catch_block (build_eh_type_type_ref (type));
607 push_eh_cleanup (type);
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
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);
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. */
633 expand_end_catch_block (blocks)
636 tree compound_stmt_1 = blocks ? TREE_PURPOSE (blocks): NULL_TREE;
637 tree compound_stmt_2 = blocks ? TREE_VALUE (blocks): NULL_TREE;
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:
660 void *p[] = { typeid(raises) };
661 __check_eh_spec (p, count);
664 __check_eh_spec in exception.cc handles all the details. */
667 expand_start_eh_spec ()
669 return begin_try_block ();
673 expand_end_eh_spec (raises, try_block)
677 tree tmp, fn, decl, types = NULL_TREE;
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);
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 will
696 never throw. We use push_throw_library_fn because we do want
697 TREE_THIS_VOLATILE to be set. */
698 TREE_NOTHROW (fn) = 1;
704 /* Build up an array of type_infos. */
705 for (; raises && TREE_VALUE (raises); raises = TREE_CHAIN (raises))
708 (NULL_TREE, build_eh_type_type (TREE_VALUE (raises)), types);
712 types = build_nt (CONSTRUCTOR, NULL_TREE, types);
713 TREE_HAS_CONSTRUCTOR (types) = 1;
715 /* We can't pass the CONSTRUCTOR directly, so stick it in a variable. */
716 tmp = build_cplus_array_type (const_ptr_type_node, NULL_TREE);
717 decl = build_decl (VAR_DECL, NULL_TREE, tmp);
718 DECL_ARTIFICIAL (decl) = 1;
719 DECL_INITIAL (decl) = types;
720 DECL_CONTEXT (decl) = current_function_decl;
721 cp_finish_decl (decl, types, NULL_TREE, 0);
723 decl = decay_conversion (decl);
725 fn = get_identifier ("__check_eh_spec");
726 if (IDENTIFIER_GLOBAL_VALUE (fn))
727 fn = IDENTIFIER_GLOBAL_VALUE (fn);
731 (NULL_TREE, integer_type_node, tree_cons
732 (NULL_TREE, TREE_TYPE (decl), void_list_node));
733 tmp = build_function_type (void_type_node, tmp);
735 fn = push_throw_library_fn (fn, tmp);
738 tmp = tree_cons (NULL_TREE, build_int_2 (count, 0),
739 tree_cons (NULL_TREE, decl, NULL_TREE));
742 tmp = build_call (fn, tmp);
743 finish_expr_stmt (tmp);
745 finish_handler (blocks, handler);
746 finish_handler_sequence (try_block);
749 /* This is called to expand all the toplevel exception handling
750 finalization for a function. It should only be called once per
754 expand_exception_blocks ()
756 do_pending_stack_adjust ();
760 rtx funcend = gen_label_rtx ();
763 /* We cannot protect n regions this way if we must flow into the
764 EH region through the top of the region, as we have to with
765 the setjmp/longjmp approach. */
766 if (exceptions_via_longjmp == 0)
767 expand_eh_region_start ();
769 emit_insns (catch_clauses);
770 catch_clauses = catch_clauses_last = NULL_RTX;
772 if (exceptions_via_longjmp == 0)
773 expand_eh_region_end (build_terminate_handler ());
775 emit_insns (catch_clauses);
776 catch_clauses = catch_clauses_last = NULL_RTX;
777 emit_label (funcend);
781 /* Return a pointer to a buffer for an exception object of type TYPE. */
784 alloc_eh_object (type)
789 fn = get_identifier ("__eh_alloc");
790 if (IDENTIFIER_GLOBAL_VALUE (fn))
791 fn = IDENTIFIER_GLOBAL_VALUE (fn);
794 /* Declare __eh_alloc (size_t), as defined in exception.cc. */
795 tree tmp = tree_cons (NULL_TREE, sizetype, void_list_node);
796 fn = push_library_fn (fn, build_function_type (ptr_type_node, tmp));
799 exp = build_function_call (fn, tree_cons
800 (NULL_TREE, size_in_bytes (type), NULL_TREE));
801 exp = build1 (NOP_EXPR, build_pointer_type (type), exp);
805 /* Expand a throw statement. This follows the following
808 1. Allocate space to save the current PC onto the stack.
809 2. Generate and emit a label and save its address into the
810 newly allocated stack space since we can't save the pc directly.
811 3. If this is the first call to throw in this function:
812 generate a label for the throw block
813 4. jump to the throw block label. */
822 return error_mark_node;
825 && decl_is_java_type (TREE_TYPE (exp), 1))
827 /* A Java `throw' statement. */
828 tree args = tree_cons (NULL_TREE, exp, NULL);
830 fn = get_identifier (exceptions_via_longjmp
833 if (IDENTIFIER_GLOBAL_VALUE (fn))
834 fn = IDENTIFIER_GLOBAL_VALUE (fn);
837 /* Declare _Jv_Throw (void *), as defined in Java's
839 tree tmp = tree_cons (NULL_TREE, ptr_type_node, void_list_node);
840 tmp = build_function_type (ptr_type_node, tmp);
841 fn = push_throw_library_fn (fn, tmp);
844 exp = build_function_call (fn, args);
849 tree cleanup = NULL_TREE, e;
854 begin_init_stmts (&stmt_expr, &compound_stmt);
856 /* throw expression */
857 /* First, decay it. */
858 exp = decay_conversion (exp);
860 /* The CLEANUP_TYPE is the internal type of a destructor. Under
861 the old ABI, destructors are two-argument functions; under
862 the new ABI they take only one argument. */
863 if (cleanup_type == NULL_TREE)
867 arg_types = void_list_node;
869 arg_types = tree_cons (NULL_TREE, integer_type_node, arg_types);
870 arg_types = tree_cons (NULL_TREE, ptr_type_node, arg_types);
871 cleanup_type = (build_pointer_type
872 (build_function_type (void_type_node, arg_types)));
875 if (TYPE_PTR_P (TREE_TYPE (exp)))
876 throw_type = build_eh_type_type (TREE_TYPE (exp));
881 /* OK, this is kind of wacky. The standard says that we call
882 terminate when the exception handling mechanism, after
883 completing evaluation of the expression to be thrown but
884 before the exception is caught (_except.throw_), calls a
885 user function that exits via an uncaught exception.
887 So we have to protect the actual initialization of the
888 exception object with terminate(), but evaluate the
889 expression first. Since there could be temps in the
890 expression, we need to handle that, too. We also expand
891 the call to __eh_alloc first (which doesn't matter, since
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 if we allocated the space first we would have to deal with
899 cleaning it up if evaluating this expression throws. */
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);
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)),
929 ? complete_dtor_identifier
932 cleanup = TREE_VALUE (cleanup);
934 mark_addressable (cleanup);
935 /* Pretend it's a normal function. */
936 cleanup = build1 (ADDR_EXPR, cleanup_type, cleanup);
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);
957 /* Declare __cp_push_exception (void*, void*, void (*)(void*, int)),
958 as defined in exception.cc. */
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);
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);
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);
992 /* Build a throw expression. */
998 if (e == error_mark_node)
1001 if (processing_template_decl)
1002 return build_min (THROW_EXPR, void_type_node, e);
1005 cp_warning ("throwing NULL, which has integral, not pointer type");
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;
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. */
1027 complete_ptr_ref_or_void_ptr_p (type, from)
1033 /* Check complete. */
1034 type = complete_type_or_else (type, from);
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))
1046 else if (!complete_type_or_else (core, from))
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. */
1063 nothrow_libfn_p (fn)
1068 if (TREE_PUBLIC (fn)
1069 && DECL_EXTERNAL (fn)
1070 && DECL_EXTERN_C_P (fn))
1073 /* Can't be a C library function. */
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]. */
1084 can_convert_eh (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))
1100 if (TREE_CODE (to) == VOID_TYPE)
1103 /* else fall through */
1106 if (IS_AGGR_TYPE (to) && IS_AGGR_TYPE (from)
1107 && PUBLICLY_UNIQUELY_DERIVED_P (to, from))
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. */
1120 check_handlers_1 (master, handlers)
1124 tree type = TREE_TYPE (master);
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);
1140 /* Given a chain of HANDLERs, make sure that they're OK. */
1143 check_handlers (handlers)
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);
1156 ("`...' handler must be the last handler for its try block");
1159 check_handlers_1 (handler, TREE_CHAIN (handler));