Daily bump.
[official-gcc.git] / gcc / cp / except.c
blob821223f07d6c26b9f069b496c23620f3d5183dc0
1 /* Handle exceptional things in C++.
2 Copyright (C) 1989, 92-97, 1998, 1999 Free Software Foundation, Inc.
3 Contributed by Michael Tiemann <tiemann@cygnus.com>
4 Rewritten by Mike Stump <mrs@cygnus.com>, based upon an
5 initial re-implementation courtesy Tad Hunt.
7 This file is part of GNU CC.
9 GNU CC is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2, or (at your option)
12 any later version.
14 GNU CC is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with GNU CC; see the file COPYING. If not, write to
21 the Free Software Foundation, 59 Temple Place - Suite 330,
22 Boston, MA 02111-1307, USA. */
25 #include "config.h"
26 #include "system.h"
27 #include "tree.h"
28 #include "rtl.h"
29 #include "cp-tree.h"
30 #include "flags.h"
31 #include "obstack.h"
32 #include "expr.h"
33 #include "output.h"
34 #include "except.h"
35 #include "defaults.h"
36 #include "toplev.h"
37 #include "eh-common.h"
39 static void push_eh_cleanup PROTO((void));
40 static tree build_eh_type_type PROTO((tree));
41 static tree build_eh_type PROTO((tree));
42 static void expand_end_eh_spec PROTO((tree));
43 static tree call_eh_info PROTO((void));
44 static void push_eh_info PROTO((void));
45 static tree get_eh_info PROTO((void));
46 static tree get_eh_value PROTO((void));
47 #if 0
48 static tree get_eh_type PROTO((void));
49 static tree get_eh_caught PROTO((void));
50 static tree get_eh_handlers PROTO((void));
51 #endif
52 static tree do_pop_exception PROTO((void));
53 static void process_start_catch_block PROTO((tree));
54 static tree build_eh_type_type_ref PROTO((tree));
55 static tree build_terminate_handler PROTO((void));
56 static tree alloc_eh_object PROTO((tree));
57 static int complete_ptr_ref_or_void_ptr_p PROTO((tree, tree));
59 #if 0
60 /* This is the startup, and finish stuff per exception table. */
62 /* XXX - Tad: exception handling section */
63 #ifndef EXCEPT_SECTION_ASM_OP
64 #define EXCEPT_SECTION_ASM_OP "section\t.gcc_except_table,\"a\",@progbits"
65 #endif
67 #ifdef EXCEPT_SECTION_ASM_OP
69 /* on machines which support it, the exception table lives in another section,
70 but it needs a label so we can reference it... This sets up that
71 label! */
72 asm (EXCEPT_SECTION_ASM_OP);
73 exception_table __EXCEPTION_TABLE__[1] = { (void*)0, (void*)0, (void*)0 };
74 asm (TEXT_SECTION_ASM_OP);
76 #endif /* EXCEPT_SECTION_ASM_OP */
78 #ifdef EXCEPT_SECTION_ASM_OP
80 /* we need to know where the end of the exception table is... so this
81 is how we do it! */
83 asm (EXCEPT_SECTION_ASM_OP);
84 exception_table __EXCEPTION_END__[1] = { (void*)-1, (void*)-1, (void*)-1 };
85 asm (TEXT_SECTION_ASM_OP);
87 #endif /* EXCEPT_SECTION_ASM_OP */
89 #endif
91 #include "decl.h"
92 #include "insn-flags.h"
93 #include "obstack.h"
95 /* ======================================================================
96 Briefly the algorithm works like this:
98 When a constructor or start of a try block is encountered,
99 push_eh_entry (&eh_stack) is called. Push_eh_entry () creates a
100 new entry in the unwind protection stack and returns a label to
101 output to start the protection for that block.
103 When a destructor or end try block is encountered, pop_eh_entry
104 (&eh_stack) is called. Pop_eh_entry () returns the eh_entry it
105 created when push_eh_entry () was called. The eh_entry structure
106 contains three things at this point. The start protect label,
107 the end protect label, and the exception handler label. The end
108 protect label should be output before the call to the destructor
109 (if any). If it was a destructor, then its parse tree is stored
110 in the finalization variable in the eh_entry structure. Otherwise
111 the finalization variable is set to NULL to reflect the fact that
112 it is the end of a try block. Next, this modified eh_entry node
113 is enqueued in the finalizations queue by calling
114 enqueue_eh_entry (&queue,entry).
116 +---------------------------------------------------------------+
117 |XXX: Will need modification to deal with partially |
118 | constructed arrays of objects |
120 | Basically, this consists of keeping track of how many |
121 | of the objects have been constructed already (this |
122 | should be in a register though, so that shouldn't be a |
123 | problem. |
124 +---------------------------------------------------------------+
126 When a catch block is encountered, there is a lot of work to be
127 done.
129 Since we don't want to generate the catch block inline with the
130 regular flow of the function, we need to have some way of doing
131 so. Luckily, we can use sequences to defer the catch sections.
132 When the start of a catch block is encountered, we start the
133 sequence. After the catch block is generated, we end the
134 sequence.
136 Next we must insure that when the catch block is executed, all
137 finalizations for the matching try block have been completed. If
138 any of those finalizations throw an exception, we must call
139 terminate according to the ARM (section r.15.6.1). What this
140 means is that we need to dequeue and emit finalizations for each
141 entry in the eh_queue until we get to an entry with a NULL
142 finalization field. For any of the finalization entries, if it
143 is not a call to terminate (), we must protect it by giving it
144 another start label, end label, and exception handler label,
145 setting its finalization tree to be a call to terminate (), and
146 enqueue'ing this new eh_entry to be output at an outer level.
147 Finally, after all that is done, we can get around to outputting
148 the catch block which basically wraps all the "catch (...) {...}"
149 statements in a big if/then/else construct that matches the
150 correct block to call.
152 ===================================================================== */
154 /* ====================================================================== */
156 /* sets up all the global eh stuff that needs to be initialized at the
157 start of compilation. */
159 void
160 init_exception_processing ()
162 /* void vtype () */
163 tree vtype = build_function_type (void_type_node, void_list_node);
165 if (flag_honor_std)
166 push_namespace (get_identifier ("std"));
167 terminate_node = auto_function (get_identifier ("terminate"),
168 vtype, NOT_BUILT_IN);
169 TREE_THIS_VOLATILE (terminate_node) = 1;
170 if (flag_honor_std)
171 pop_namespace ();
173 set_exception_lang_code (EH_LANG_C_plus_plus);
174 set_exception_version_code (1);
176 /* If we use setjmp/longjmp EH, arrange for all cleanup actions to
177 be protected with __terminate. */
178 protect_cleanup_actions_with_terminate = 1;
181 /* Retrieve a pointer to the cp_eh_info node for the current exception. */
183 static tree
184 call_eh_info ()
186 tree fn;
188 fn = get_identifier ("__start_cp_handler");
189 if (IDENTIFIER_GLOBAL_VALUE (fn))
190 fn = IDENTIFIER_GLOBAL_VALUE (fn);
191 else
193 tree t1, t, fields[7];
195 /* Declare cp_eh_info * __start_cp_handler (void),
196 as defined in exception.cc. */
197 push_permanent_obstack ();
199 /* struct cp_eh_info. This must match exception.cc. Note that this
200 type is not pushed anywhere. */
201 t1= make_lang_type (RECORD_TYPE);
202 fields[0] = build_lang_decl (FIELD_DECL,
203 get_identifier ("handler_label"), ptr_type_node);
204 fields[1] = build_lang_decl (FIELD_DECL,
205 get_identifier ("dynamic_handler_chain"), ptr_type_node);
206 fields[2] = build_lang_decl (FIELD_DECL,
207 get_identifier ("info"), ptr_type_node);
208 fields[3] = build_lang_decl (FIELD_DECL,
209 get_identifier ("table_index"), ptr_type_node);
210 /* N.B.: The fourth field LEN is expected to be
211 the number of fields - 1, not the total number of fields. */
212 finish_builtin_type (t1, "eh_context", fields, 3, ptr_type_node);
213 t1 = build_pointer_type (t1);
215 t1= make_lang_type (RECORD_TYPE);
216 fields[0] = build_lang_decl (FIELD_DECL,
217 get_identifier ("match_function"), ptr_type_node);
218 fields[1] = build_lang_decl (FIELD_DECL,
219 get_identifier ("language"), short_integer_type_node);
220 fields[2] = build_lang_decl (FIELD_DECL,
221 get_identifier ("version"), short_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 (t1, "__eh_info", fields, 2, ptr_type_node);
225 t = make_lang_type (RECORD_TYPE);
226 fields[0] = build_lang_decl (FIELD_DECL,
227 get_identifier ("eh_info"), t1);
228 fields[1] = build_lang_decl (FIELD_DECL, get_identifier ("value"),
229 ptr_type_node);
230 fields[2] = build_lang_decl (FIELD_DECL, get_identifier ("type"),
231 ptr_type_node);
232 fields[3] = build_lang_decl
233 (FIELD_DECL, get_identifier ("cleanup"),
234 build_pointer_type (build_function_type
235 (ptr_type_node, tree_cons
236 (NULL_TREE, ptr_type_node, void_list_node))));
237 fields[4] = build_lang_decl (FIELD_DECL, get_identifier ("caught"),
238 boolean_type_node);
239 fields[5] = build_lang_decl (FIELD_DECL, get_identifier ("next"),
240 build_pointer_type (t));
241 fields[6] = build_lang_decl
242 (FIELD_DECL, get_identifier ("handlers"), long_integer_type_node);
243 /* N.B.: The fourth field LEN is expected to be
244 the number of fields - 1, not the total number of fields. */
245 finish_builtin_type (t, "cp_eh_info", fields, 6, ptr_type_node);
246 t = build_pointer_type (t);
248 /* And now the function. */
249 fn = build_lang_decl (FUNCTION_DECL, fn,
250 build_function_type (t, void_list_node));
251 DECL_EXTERNAL (fn) = 1;
252 TREE_PUBLIC (fn) = 1;
253 DECL_ARTIFICIAL (fn) = 1;
254 pushdecl_top_level (fn);
255 make_function_rtl (fn);
256 pop_obstacks ();
258 mark_used (fn);
259 return build_function_call (fn, NULL_TREE);
262 /* Retrieve a pointer to the cp_eh_info node for the current exception
263 and save it in the current binding level. */
265 static void
266 push_eh_info ()
268 tree decl, fn = call_eh_info ();
270 /* Remember the pointer to the current exception info; it won't change
271 during this catch block. */
272 decl = build_decl (VAR_DECL, get_identifier ("__exception_info"),
273 TREE_TYPE (fn));
274 DECL_ARTIFICIAL (decl) = 1;
275 DECL_INITIAL (decl) = fn;
276 decl = pushdecl (decl);
277 cp_finish_decl (decl, fn, NULL_TREE, 0, 0);
280 /* Returns a reference to the cp_eh_info node for the current exception. */
282 static tree
283 get_eh_info ()
285 /* Look for the pointer pushed in push_eh_info. */
286 tree t = lookup_name (get_identifier ("__exception_info"), 0);
287 return build_indirect_ref (t, NULL_PTR);
290 /* Returns a reference to the current exception object. */
292 static tree
293 get_eh_value ()
295 return build_component_ref (get_eh_info (), get_identifier ("value"),
296 NULL_TREE, 0);
299 /* Returns a reference to the current exception type. */
301 #if 0
302 static tree
303 get_eh_type ()
305 return build_component_ref (get_eh_info (), get_identifier ("type"),
306 NULL_TREE, 0);
309 /* Returns a reference to whether or not the current exception
310 has been caught. */
312 static tree
313 get_eh_caught ()
315 return build_component_ref (get_eh_info (), get_identifier ("caught"),
316 NULL_TREE, 0);
319 /* Returns a reference to whether or not the current exception
320 has been caught. */
322 static tree
323 get_eh_handlers ()
325 return build_component_ref (get_eh_info (), get_identifier ("handlers"),
326 NULL_TREE, 0);
328 #endif
330 /* Build a type value for use at runtime for a type that is matched
331 against by the exception handling system. */
333 static tree
334 build_eh_type_type (type)
335 tree type;
337 const char *typestring;
338 tree exp;
340 if (type == error_mark_node)
341 return error_mark_node;
343 /* peel back references, so they match. */
344 if (TREE_CODE (type) == REFERENCE_TYPE)
345 type = TREE_TYPE (type);
347 /* Peel off cv qualifiers. */
348 type = TYPE_MAIN_VARIANT (type);
350 if (flag_rtti)
351 return build1 (ADDR_EXPR, ptr_type_node, get_typeid_1 (type));
353 typestring = build_overload_name (type, 1, 1);
354 exp = combine_strings (build_string (strlen (typestring)+1, typestring));
355 return build1 (ADDR_EXPR, ptr_type_node, exp);
358 /* Build the address of a runtime type for use in the runtime matching
359 field of the new exception model */
361 static tree
362 build_eh_type_type_ref (type)
363 tree type;
365 const char *typestring;
366 tree exp;
368 if (type == error_mark_node)
369 return error_mark_node;
371 /* peel back references, so they match. */
372 if (TREE_CODE (type) == REFERENCE_TYPE)
373 type = TREE_TYPE (type);
375 /* Peel off cv qualifiers. */
376 type = TYPE_MAIN_VARIANT (type);
378 push_permanent_obstack ();
380 if (flag_rtti)
382 exp = get_tinfo_fn (type);
383 TREE_USED (exp) = 1;
384 mark_inline_for_output (exp);
385 exp = build1 (ADDR_EXPR, ptr_type_node, exp);
387 else
389 typestring = build_overload_name (type, 1, 1);
390 exp = combine_strings (build_string (strlen (typestring)+1, typestring));
391 exp = build1 (ADDR_EXPR, ptr_type_node, exp);
393 pop_obstacks ();
394 return (exp);
398 /* Build a type value for use at runtime for a exp that is thrown or
399 matched against by the exception handling system. */
401 static tree
402 build_eh_type (exp)
403 tree exp;
405 if (flag_rtti)
407 exp = build_typeid (exp);
408 return build1 (ADDR_EXPR, ptr_type_node, exp);
410 return build_eh_type_type (TREE_TYPE (exp));
413 /* This routine is called to mark all the symbols representing runtime
414 type functions in the exception table as haveing been referenced.
415 This will make sure code is emitted for them. Called from finish_file. */
416 void
417 mark_all_runtime_matches ()
419 int x,num;
420 void **ptr;
421 tree exp;
423 num = find_all_handler_type_matches (&ptr);
424 if (num == 0 || ptr == NULL)
425 return;
427 for (x=0; x <num; x++)
429 exp = (tree) ptr[x];
430 if (TREE_CODE (exp) == ADDR_EXPR)
432 exp = TREE_OPERAND (exp, 0);
433 if (TREE_CODE (exp) == FUNCTION_DECL)
434 TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (exp)) = 1;
438 free (ptr);
441 /* Build up a call to __cp_pop_exception, to destroy the exception object
442 for the current catch block. HANDLER is either true or false, telling
443 the library whether or not it is being called from an exception handler;
444 if it is, it avoids destroying the object on rethrow. */
446 static tree
447 do_pop_exception ()
449 tree fn, cleanup;
450 fn = get_identifier ("__cp_pop_exception");
451 if (IDENTIFIER_GLOBAL_VALUE (fn))
452 fn = IDENTIFIER_GLOBAL_VALUE (fn);
453 else
455 /* Declare void __cp_pop_exception (void *),
456 as defined in exception.cc. */
457 push_permanent_obstack ();
458 fn = build_lang_decl
459 (FUNCTION_DECL, fn,
460 build_function_type (void_type_node, tree_cons
461 (NULL_TREE, ptr_type_node, void_list_node)));
462 DECL_EXTERNAL (fn) = 1;
463 TREE_PUBLIC (fn) = 1;
464 DECL_ARTIFICIAL (fn) = 1;
465 pushdecl_top_level (fn);
466 make_function_rtl (fn);
467 pop_obstacks ();
470 mark_used (fn);
471 /* Arrange to do a dynamically scoped cleanup upon exit from this region. */
472 cleanup = lookup_name (get_identifier ("__exception_info"), 0);
473 cleanup = build_function_call (fn, tree_cons
474 (NULL_TREE, cleanup, NULL_TREE));
475 return cleanup;
478 /* This routine creates the cleanup for the current exception. */
480 static void
481 push_eh_cleanup ()
483 int yes;
485 yes = suspend_momentary ();
486 /* All cleanups must last longer than normal. */
487 expand_decl_cleanup (NULL_TREE, do_pop_exception ());
488 resume_momentary (yes);
491 /* Build up a call to terminate on the function obstack, for use as an
492 exception handler. */
494 static tree
495 build_terminate_handler ()
497 int yes = suspend_momentary ();
498 tree term = build_function_call (terminate_node, NULL_TREE);
499 resume_momentary (yes);
500 return term;
503 /* Call this to start a catch block. Typename is the typename, and identifier
504 is the variable to place the object in or NULL if the variable doesn't
505 matter. If typename is NULL, that means its a "catch (...)" or catch
506 everything. In that case we don't need to do any type checking.
507 (ie: it ends up as the "else" clause rather than an "else if" clause) */
509 void
510 expand_start_catch_block (decl)
511 tree decl;
513 if (building_stmt_tree ())
515 if (decl)
517 /* We must ensure that DECL_CONTEXT is set up before we call
518 push_template_decl; that code depends on DECL_CONTEXT
519 being set correctly. */
520 DECL_CONTEXT (decl) = current_function_decl;
521 if (processing_template_decl)
522 decl = push_template_decl (decl);
523 pushdecl (decl);
524 add_decl_stmt (decl);
526 return;
529 if (! doing_eh (1))
530 return;
532 process_start_catch_block (decl);
535 /* This function performs the expand_start_catch_block functionality for
536 exceptions implemented in the new style. __throw determines whether
537 a handler needs to be called or not, so the handler itself has to do
538 nothing additional. */
540 static void
541 process_start_catch_block (decl)
542 tree decl;
544 tree init;
546 /* Create a binding level for the eh_info and the exception object
547 cleanup. */
548 pushlevel (0);
549 expand_start_bindings (0);
551 if (decl && !complete_ptr_ref_or_void_ptr_p (TREE_TYPE (decl), NULL_TREE))
552 decl = NULL_TREE;
554 if (decl)
555 start_catch_handler (build_eh_type_type_ref (TREE_TYPE (decl)));
556 else
557 start_catch_handler (CATCH_ALL_TYPE);
559 emit_line_note (input_filename, lineno);
561 push_eh_info ();
563 if (decl)
565 tree exp;
566 tree init_type;
568 /* Make sure we mark the catch param as used, otherwise we'll get
569 a warning about an unused ((anonymous)). */
570 TREE_USED (decl) = 1;
572 /* Figure out the type that the initializer is. */
573 init_type = TREE_TYPE (decl);
574 if (TREE_CODE (init_type) != REFERENCE_TYPE
575 && TREE_CODE (init_type) != POINTER_TYPE)
576 init_type = build_reference_type (init_type);
578 exp = get_eh_value ();
580 /* Since pointers are passed by value, initialize a reference to
581 pointer catch parm with the address of the value slot. */
582 if (TREE_CODE (init_type) == REFERENCE_TYPE
583 && TREE_CODE (TREE_TYPE (init_type)) == POINTER_TYPE)
584 exp = build_unary_op (ADDR_EXPR, exp, 1);
586 exp = ocp_convert (init_type , exp, CONV_IMPLICIT|CONV_FORCE_TEMP, 0);
588 push_eh_cleanup ();
590 /* Create a binding level for the parm. */
591 pushlevel (0);
592 expand_start_bindings (0);
594 init = convert_from_reference (exp);
596 /* If the constructor for the catch parm exits via an exception, we
597 must call terminate. See eh23.C. */
598 if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl)))
600 /* Generate the copy constructor call directly so we can wrap it.
601 See also expand_default_init. */
602 init = ocp_convert (TREE_TYPE (decl), init,
603 CONV_IMPLICIT|CONV_FORCE_TEMP, 0);
604 init = build (TRY_CATCH_EXPR, TREE_TYPE (init), init,
605 build_terminate_handler ());
608 /* Let `cp_finish_decl' know that this initializer is ok. */
609 DECL_INITIAL (decl) = init;
610 decl = pushdecl (decl);
612 start_decl_1 (decl);
613 cp_finish_decl (decl, init, NULL_TREE, 0,
614 LOOKUP_ONLYCONVERTING|DIRECT_BIND);
616 else
618 push_eh_cleanup ();
620 /* Create a binding level for the parm. */
621 pushlevel (0);
622 expand_start_bindings (0);
624 /* Fall into the catch all section. */
627 emit_line_note (input_filename, lineno);
631 /* Call this to end a catch block. Its responsible for emitting the
632 code to handle jumping back to the correct place, and for emitting
633 the label to jump to if this catch block didn't match. */
635 void
636 expand_end_catch_block ()
638 if (! doing_eh (1))
639 return;
641 /* The exception being handled is rethrown if control reaches the end of
642 a handler of the function-try-block of a constructor or destructor. */
643 if (in_function_try_handler
644 && (DECL_CONSTRUCTOR_P (current_function_decl)
645 || DECL_DESTRUCTOR_P (current_function_decl)))
646 expand_throw (NULL_TREE);
648 /* Cleanup the EH parameter. */
649 expand_end_bindings (getdecls (), kept_level_p (), 0);
650 poplevel (kept_level_p (), 1, 0);
652 /* Cleanup the EH object. */
653 expand_end_bindings (getdecls (), kept_level_p (), 0);
654 poplevel (kept_level_p (), 1, 0);
656 /* Fall to outside the try statement when done executing handler and
657 we fall off end of handler. This is jump Lresume in the
658 documentation. */
659 expand_goto (top_label_entry (&caught_return_label_stack));
661 end_catch_handler ();
664 /* An exception spec is implemented more or less like:
666 try {
667 function body;
668 } catch (...) {
669 void *p[] = { typeid(raises) };
670 __check_eh_spec (p, count);
673 __check_eh_spec in exception.cc handles all the details. */
675 void
676 expand_start_eh_spec ()
678 expand_start_try_stmts ();
681 static void
682 expand_end_eh_spec (raises)
683 tree raises;
685 tree tmp, fn, decl, types = NULL_TREE;
686 int count = 0;
688 expand_start_all_catch ();
689 expand_start_catch_block (NULL_TREE);
691 /* Build up an array of type_infos. */
692 for (; raises && TREE_VALUE (raises); raises = TREE_CHAIN (raises))
694 types = tree_cons
695 (NULL_TREE, build_eh_type_type (TREE_VALUE (raises)), types);
696 ++count;
699 types = build_nt (CONSTRUCTOR, NULL_TREE, types);
700 TREE_HAS_CONSTRUCTOR (types) = 1;
702 /* We can't pass the CONSTRUCTOR directly, so stick it in a variable. */
703 tmp = build_cplus_array_type (const_ptr_type_node, NULL_TREE);
704 decl = build_decl (VAR_DECL, NULL_TREE, tmp);
705 DECL_ARTIFICIAL (decl) = 1;
706 DECL_INITIAL (decl) = types;
707 cp_finish_decl (decl, types, NULL_TREE, 0, 0);
709 decl = decay_conversion (decl);
711 fn = get_identifier ("__check_eh_spec");
712 if (IDENTIFIER_GLOBAL_VALUE (fn))
713 fn = IDENTIFIER_GLOBAL_VALUE (fn);
714 else
716 push_permanent_obstack ();
718 tmp = tree_cons
719 (NULL_TREE, integer_type_node, tree_cons
720 (NULL_TREE, TREE_TYPE (decl), void_list_node));
721 tmp = build_function_type (void_type_node, tmp);
723 fn = build_lang_decl (FUNCTION_DECL, fn, tmp);
724 DECL_EXTERNAL (fn) = 1;
725 TREE_PUBLIC (fn) = 1;
726 DECL_ARTIFICIAL (fn) = 1;
727 TREE_THIS_VOLATILE (fn) = 1;
728 pushdecl_top_level (fn);
729 make_function_rtl (fn);
730 pop_obstacks ();
733 mark_used (fn);
734 tmp = tree_cons (NULL_TREE, build_int_2 (count, 0),
735 tree_cons (NULL_TREE, decl, NULL_TREE));
736 tmp = build_call (fn, TREE_TYPE (TREE_TYPE (fn)), tmp);
737 expand_expr (tmp, const0_rtx, VOIDmode, EXPAND_NORMAL);
739 expand_end_catch_block ();
740 expand_end_all_catch ();
743 /* This is called to expand all the toplevel exception handling
744 finalization for a function. It should only be called once per
745 function. */
747 void
748 expand_exception_blocks ()
750 do_pending_stack_adjust ();
751 push_to_sequence (catch_clauses);
752 expand_leftover_cleanups ();
753 do_pending_stack_adjust ();
754 catch_clauses = get_insns ();
755 end_sequence ();
757 /* Do this after we expand leftover cleanups, so that the
758 expand_eh_region_end that expand_end_eh_spec does will match the
759 right expand_eh_region_start, and make sure it comes out before
760 the terminate protected region. */
761 if (TYPE_RAISES_EXCEPTIONS (TREE_TYPE (current_function_decl)))
763 expand_end_eh_spec (TYPE_RAISES_EXCEPTIONS (TREE_TYPE (current_function_decl)));
764 do_pending_stack_adjust ();
765 push_to_sequence (catch_clauses);
766 expand_leftover_cleanups ();
767 do_pending_stack_adjust ();
768 catch_clauses = get_insns ();
769 end_sequence ();
772 if (catch_clauses)
774 rtx funcend = gen_label_rtx ();
775 emit_jump (funcend);
777 /* We cannot protect n regions this way if we must flow into the
778 EH region through the top of the region, as we have to with
779 the setjmp/longjmp approach. */
780 if (exceptions_via_longjmp == 0)
781 expand_eh_region_start ();
783 emit_insns (catch_clauses);
784 catch_clauses = NULL_RTX;
786 if (exceptions_via_longjmp == 0)
787 expand_eh_region_end (build_terminate_handler ());
789 expand_leftover_cleanups ();
791 emit_label (funcend);
795 tree
796 start_anon_func ()
798 static int counter = 0;
799 int old_interface_unknown = interface_unknown;
800 char name[32];
801 tree params;
802 tree t;
804 push_to_top_level ();
806 /* No need to mangle this. */
807 push_lang_context (lang_name_c);
809 interface_unknown = 1;
811 params = void_list_node;
812 /* tcf stands for throw clean function. */
813 sprintf (name, "__tcf_%d", counter++);
814 t = make_call_declarator (get_identifier (name), params, NULL_TREE,
815 NULL_TREE);
816 start_function (decl_tree_cons (NULL_TREE, get_identifier ("static"),
817 void_list_node),
818 t, NULL_TREE, SF_DEFAULT);
819 store_parm_decls ();
820 pushlevel (0);
821 clear_last_expr ();
822 push_momentary ();
823 expand_start_bindings (0);
824 emit_line_note (input_filename, lineno);
826 interface_unknown = old_interface_unknown;
828 pop_lang_context ();
830 return current_function_decl;
833 void
834 end_anon_func ()
836 expand_end_bindings (getdecls (), 1, 0);
837 poplevel (1, 0, 0);
838 pop_momentary ();
840 finish_function (lineno, 0);
842 pop_from_top_level ();
845 /* Return a pointer to a buffer for an exception object of type TYPE. */
847 static tree
848 alloc_eh_object (type)
849 tree type;
851 tree fn, exp;
853 fn = get_identifier ("__eh_alloc");
854 if (IDENTIFIER_GLOBAL_VALUE (fn))
855 fn = IDENTIFIER_GLOBAL_VALUE (fn);
856 else
858 /* Declare __eh_alloc (size_t), as defined in exception.cc. */
859 tree tmp;
860 push_permanent_obstack ();
861 tmp = tree_cons (NULL_TREE, sizetype, void_list_node);
862 fn = build_lang_decl (FUNCTION_DECL, fn,
863 build_function_type (ptr_type_node, tmp));
864 DECL_EXTERNAL (fn) = 1;
865 TREE_PUBLIC (fn) = 1;
866 DECL_ARTIFICIAL (fn) = 1;
867 pushdecl_top_level (fn);
868 make_function_rtl (fn);
869 pop_obstacks ();
872 mark_used (fn);
873 exp = build_function_call (fn, tree_cons
874 (NULL_TREE, size_in_bytes (type), NULL_TREE));
875 exp = build1 (NOP_EXPR, build_pointer_type (type), exp);
876 return exp;
879 /* Expand a throw statement. This follows the following
880 algorithm:
882 1. Allocate space to save the current PC onto the stack.
883 2. Generate and emit a label and save its address into the
884 newly allocated stack space since we can't save the pc directly.
885 3. If this is the first call to throw in this function:
886 generate a label for the throw block
887 4. jump to the throw block label. */
889 void
890 expand_throw (exp)
891 tree exp;
893 tree fn;
894 static tree cleanup_type;
896 if (! doing_eh (1))
897 return;
899 if (exp)
901 tree throw_type;
902 tree cleanup = NULL_TREE, e;
904 /* throw expression */
905 /* First, decay it. */
906 exp = decay_conversion (exp);
908 /* cleanup_type is void (*)(void *, int),
909 the internal type of a destructor. */
910 if (cleanup_type == NULL_TREE)
912 push_permanent_obstack ();
913 cleanup_type = build_pointer_type
914 (build_function_type
915 (void_type_node, tree_cons
916 (NULL_TREE, ptr_type_node, tree_cons
917 (NULL_TREE, integer_type_node, void_list_node))));
918 pop_obstacks ();
921 if (TYPE_PTR_P (TREE_TYPE (exp)))
922 throw_type = build_eh_type (exp);
923 else
925 tree object, ptr;
927 /* OK, this is kind of wacky. The WP says that we call
928 terminate
930 when the exception handling mechanism, after completing
931 evaluation of the expression to be thrown but before the
932 exception is caught (_except.throw_), calls a user function
933 that exits via an uncaught exception.
935 So we have to protect the actual initialization of the
936 exception object with terminate(), but evaluate the expression
937 first. We also expand the call to __eh_alloc
938 first. Since there could be temps in the expression, we need
939 to handle that, too. */
941 expand_start_target_temps ();
943 #if 0
944 /* Unfortunately, this doesn't work. */
945 preexpand_calls (exp);
946 #else
947 /* Store the throw expression into a temp. This can be less
948 efficient than storing it into the allocated space directly, but
949 oh well. To do this efficiently we would need to insinuate
950 ourselves into expand_call. */
951 if (TREE_SIDE_EFFECTS (exp))
953 tree temp = create_temporary_var (TREE_TYPE (exp));
954 DECL_INITIAL (temp) = exp;
955 cp_finish_decl (temp, exp, NULL_TREE, 0, LOOKUP_ONLYCONVERTING);
956 exp = temp;
958 #endif
960 /* Allocate the space for the exception. */
961 ptr = save_expr (alloc_eh_object (TREE_TYPE (exp)));
962 expand_expr (ptr, const0_rtx, VOIDmode, 0);
964 expand_eh_region_start ();
966 object = build_indirect_ref (ptr, NULL_PTR);
967 exp = build_modify_expr (object, INIT_EXPR, exp);
969 if (exp == error_mark_node)
970 error (" in thrown expression");
972 expand_expr (exp, const0_rtx, VOIDmode, 0);
973 expand_eh_region_end (build_terminate_handler ());
974 expand_end_target_temps ();
976 throw_type = build_eh_type (object);
978 if (TYPE_HAS_DESTRUCTOR (TREE_TYPE (object)))
980 cleanup = lookup_fnfields (TYPE_BINFO (TREE_TYPE (object)),
981 dtor_identifier, 0);
982 cleanup = TREE_VALUE (cleanup);
983 mark_used (cleanup);
984 mark_addressable (cleanup);
985 /* Pretend it's a normal function. */
986 cleanup = build1 (ADDR_EXPR, cleanup_type, cleanup);
989 exp = ptr;
992 /* Cast EXP to `void *' so that it will match the prototype for
993 __cp_push_exception. */
994 exp = convert (ptr_type_node, exp);
996 if (cleanup == NULL_TREE)
998 cleanup = build_int_2 (0, 0);
999 TREE_TYPE (cleanup) = cleanup_type;
1002 fn = get_identifier ("__cp_push_exception");
1003 if (IDENTIFIER_GLOBAL_VALUE (fn))
1004 fn = IDENTIFIER_GLOBAL_VALUE (fn);
1005 else
1007 /* Declare __cp_push_exception (void*, void*, void (*)(void*, int)),
1008 as defined in exception.cc. */
1009 tree tmp;
1010 push_permanent_obstack ();
1011 tmp = tree_cons
1012 (NULL_TREE, ptr_type_node, tree_cons
1013 (NULL_TREE, ptr_type_node, tree_cons
1014 (NULL_TREE, cleanup_type, void_list_node)));
1015 fn = build_lang_decl (FUNCTION_DECL, fn,
1016 build_function_type (void_type_node, tmp));
1017 DECL_EXTERNAL (fn) = 1;
1018 TREE_PUBLIC (fn) = 1;
1019 DECL_ARTIFICIAL (fn) = 1;
1020 pushdecl_top_level (fn);
1021 make_function_rtl (fn);
1022 pop_obstacks ();
1025 mark_used (fn);
1026 e = tree_cons (NULL_TREE, exp, tree_cons
1027 (NULL_TREE, throw_type, tree_cons
1028 (NULL_TREE, cleanup, NULL_TREE)));
1029 e = build_function_call (fn, e);
1030 expand_expr (e, const0_rtx, VOIDmode, 0);
1032 else
1034 /* rethrow current exception; note that it's no longer caught. */
1036 tree fn = get_identifier ("__uncatch_exception");
1037 if (IDENTIFIER_GLOBAL_VALUE (fn))
1038 fn = IDENTIFIER_GLOBAL_VALUE (fn);
1039 else
1041 /* Declare void __uncatch_exception (void)
1042 as defined in exception.cc. */
1043 push_permanent_obstack ();
1044 fn = build_lang_decl (FUNCTION_DECL, fn,
1045 build_function_type (void_type_node,
1046 void_list_node));
1047 DECL_EXTERNAL (fn) = 1;
1048 TREE_PUBLIC (fn) = 1;
1049 DECL_ARTIFICIAL (fn) = 1;
1050 pushdecl_top_level (fn);
1051 make_function_rtl (fn);
1052 pop_obstacks ();
1055 mark_used (fn);
1056 exp = build_function_call (fn, NULL_TREE);
1057 expand_expr (exp, const0_rtx, VOIDmode, EXPAND_NORMAL);
1060 expand_internal_throw ();
1063 /* Build a throw expression. */
1065 tree
1066 build_throw (e)
1067 tree e;
1069 if (e == error_mark_node)
1070 return e;
1072 if (processing_template_decl)
1073 return build_min (THROW_EXPR, void_type_node, e);
1075 if (e == null_node)
1076 cp_warning ("throwing NULL, which has integral, not pointer type");
1078 if (e != NULL_TREE)
1080 if (!complete_ptr_ref_or_void_ptr_p (TREE_TYPE (e), e))
1081 return error_mark_node;
1084 e = build1 (THROW_EXPR, void_type_node, e);
1085 TREE_SIDE_EFFECTS (e) = 1;
1086 TREE_USED (e) = 1;
1088 return e;
1091 /* Make sure TYPE is complete, pointer to complete, reference to
1092 complete, or pointer to cv void. Issue diagnostic on failure.
1093 Return the zero on failure and non-zero on success. FROM can be
1094 the expr or decl from whence TYPE came, if available. */
1096 static int
1097 complete_ptr_ref_or_void_ptr_p (type, from)
1098 tree type;
1099 tree from;
1101 int is_ptr;
1103 /* Check complete. */
1104 type = complete_type_or_else (type, from);
1105 if (!type)
1106 return 0;
1108 /* Or a pointer or ref to one, or cv void *. */
1109 is_ptr = TREE_CODE (type) == POINTER_TYPE;
1110 if (is_ptr || TREE_CODE (type) == REFERENCE_TYPE)
1112 tree core = TREE_TYPE (type);
1114 if (is_ptr && same_type_p (TYPE_MAIN_VARIANT (core), void_type_node))
1115 /* OK */;
1116 else if (!complete_type_or_else (core, from))
1117 return 0;
1119 return 1;