1999-10-04 Mark Mitchell <mark@codesourcery.com>
[official-gcc.git] / gcc / cp / except.c
blob72644e63847d319ac6efab62274ab7ea50e96d52
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 call_eh_info PROTO((void));
42 static void push_eh_info PROTO((void));
43 static tree get_eh_info PROTO((void));
44 static tree get_eh_value PROTO((void));
45 #if 0
46 static tree get_eh_type PROTO((void));
47 static tree get_eh_caught PROTO((void));
48 static tree get_eh_handlers PROTO((void));
49 #endif
50 static tree do_pop_exception PROTO((void));
51 static tree build_eh_type_type_ref PROTO((tree));
52 static tree build_terminate_handler PROTO((void));
53 static tree alloc_eh_object PROTO((tree));
54 static int complete_ptr_ref_or_void_ptr_p PROTO((tree, tree));
55 static void initialize_handler_parm PROTO((tree));
56 static tree expand_throw PROTO((tree));
58 #if 0
59 /* This is the startup, and finish stuff per exception table. */
61 /* XXX - Tad: exception handling section */
62 #ifndef EXCEPT_SECTION_ASM_OP
63 #define EXCEPT_SECTION_ASM_OP "section\t.gcc_except_table,\"a\",@progbits"
64 #endif
66 #ifdef EXCEPT_SECTION_ASM_OP
68 /* on machines which support it, the exception table lives in another section,
69 but it needs a label so we can reference it... This sets up that
70 label! */
71 asm (EXCEPT_SECTION_ASM_OP);
72 exception_table __EXCEPTION_TABLE__[1] = { (void*)0, (void*)0, (void*)0 };
73 asm (TEXT_SECTION_ASM_OP);
75 #endif /* EXCEPT_SECTION_ASM_OP */
77 #ifdef EXCEPT_SECTION_ASM_OP
79 /* we need to know where the end of the exception table is... so this
80 is how we do it! */
82 asm (EXCEPT_SECTION_ASM_OP);
83 exception_table __EXCEPTION_END__[1] = { (void*)-1, (void*)-1, (void*)-1 };
84 asm (TEXT_SECTION_ASM_OP);
86 #endif /* EXCEPT_SECTION_ASM_OP */
88 #endif
90 #include "decl.h"
91 #include "insn-flags.h"
92 #include "obstack.h"
94 /* ======================================================================
95 Briefly the algorithm works like this:
97 When a constructor or start of a try block is encountered,
98 push_eh_entry (&eh_stack) is called. Push_eh_entry () creates a
99 new entry in the unwind protection stack and returns a label to
100 output to start the protection for that block.
102 When a destructor or end try block is encountered, pop_eh_entry
103 (&eh_stack) is called. Pop_eh_entry () returns the eh_entry it
104 created when push_eh_entry () was called. The eh_entry structure
105 contains three things at this point. The start protect label,
106 the end protect label, and the exception handler label. The end
107 protect label should be output before the call to the destructor
108 (if any). If it was a destructor, then its parse tree is stored
109 in the finalization variable in the eh_entry structure. Otherwise
110 the finalization variable is set to NULL to reflect the fact that
111 it is the end of a try block. Next, this modified eh_entry node
112 is enqueued in the finalizations queue by calling
113 enqueue_eh_entry (&queue,entry).
115 +---------------------------------------------------------------+
116 |XXX: Will need modification to deal with partially |
117 | constructed arrays of objects |
119 | Basically, this consists of keeping track of how many |
120 | of the objects have been constructed already (this |
121 | should be in a register though, so that shouldn't be a |
122 | problem. |
123 +---------------------------------------------------------------+
125 When a catch block is encountered, there is a lot of work to be
126 done.
128 Since we don't want to generate the catch block inline with the
129 regular flow of the function, we need to have some way of doing
130 so. Luckily, we can use sequences to defer the catch sections.
131 When the start of a catch block is encountered, we start the
132 sequence. After the catch block is generated, we end the
133 sequence.
135 Next we must insure that when the catch block is executed, all
136 finalizations for the matching try block have been completed. If
137 any of those finalizations throw an exception, we must call
138 terminate according to the ARM (section r.15.6.1). What this
139 means is that we need to dequeue and emit finalizations for each
140 entry in the eh_queue until we get to an entry with a NULL
141 finalization field. For any of the finalization entries, if it
142 is not a call to terminate (), we must protect it by giving it
143 another start label, end label, and exception handler label,
144 setting its finalization tree to be a call to terminate (), and
145 enqueue'ing this new eh_entry to be output at an outer level.
146 Finally, after all that is done, we can get around to outputting
147 the catch block which basically wraps all the "catch (...) {...}"
148 statements in a big if/then/else construct that matches the
149 correct block to call.
151 ===================================================================== */
153 /* ====================================================================== */
155 /* sets up all the global eh stuff that needs to be initialized at the
156 start of compilation. */
158 void
159 init_exception_processing ()
161 /* void vtype () */
162 tree vtype = build_function_type (void_type_node, void_list_node);
164 if (flag_honor_std)
165 push_namespace (get_identifier ("std"));
166 terminate_node = auto_function (get_identifier ("terminate"), vtype);
167 TREE_THIS_VOLATILE (terminate_node) = 1;
168 if (flag_honor_std)
169 pop_namespace ();
171 set_exception_lang_code (EH_LANG_C_plus_plus);
172 set_exception_version_code (1);
174 /* If we use setjmp/longjmp EH, arrange for all cleanup actions to
175 be protected with __terminate. */
176 protect_cleanup_actions_with_terminate = 1;
179 /* Retrieve a pointer to the cp_eh_info node for the current exception. */
181 static tree
182 call_eh_info ()
184 tree fn;
186 fn = get_identifier ("__start_cp_handler");
187 if (IDENTIFIER_GLOBAL_VALUE (fn))
188 fn = IDENTIFIER_GLOBAL_VALUE (fn);
189 else
191 tree t1, t, fields[7];
193 /* Declare cp_eh_info * __start_cp_handler (void),
194 as defined in exception.cc. */
195 push_permanent_obstack ();
197 /* struct cp_eh_info. This must match exception.cc. Note that this
198 type is not pushed anywhere. */
199 t1= make_lang_type (RECORD_TYPE);
200 fields[0] = build_lang_decl (FIELD_DECL,
201 get_identifier ("handler_label"), ptr_type_node);
202 fields[1] = build_lang_decl (FIELD_DECL,
203 get_identifier ("dynamic_handler_chain"), ptr_type_node);
204 fields[2] = build_lang_decl (FIELD_DECL,
205 get_identifier ("info"), ptr_type_node);
206 fields[3] = build_lang_decl (FIELD_DECL,
207 get_identifier ("table_index"), ptr_type_node);
208 /* N.B.: The fourth field LEN is expected to be
209 the number of fields - 1, not the total number of fields. */
210 finish_builtin_type (t1, "eh_context", fields, 3, ptr_type_node);
211 t1 = build_pointer_type (t1);
213 t1= make_lang_type (RECORD_TYPE);
214 fields[0] = build_lang_decl (FIELD_DECL,
215 get_identifier ("match_function"), ptr_type_node);
216 fields[1] = build_lang_decl (FIELD_DECL,
217 get_identifier ("language"), short_integer_type_node);
218 fields[2] = build_lang_decl (FIELD_DECL,
219 get_identifier ("version"), short_integer_type_node);
220 /* N.B.: The fourth field LEN is expected to be
221 the number of fields - 1, not the total number of fields. */
222 finish_builtin_type (t1, "__eh_info", fields, 2, ptr_type_node);
223 t = make_lang_type (RECORD_TYPE);
224 fields[0] = build_lang_decl (FIELD_DECL,
225 get_identifier ("eh_info"), t1);
226 fields[1] = build_lang_decl (FIELD_DECL, get_identifier ("value"),
227 ptr_type_node);
228 fields[2] = build_lang_decl (FIELD_DECL, get_identifier ("type"),
229 ptr_type_node);
230 fields[3] = build_lang_decl
231 (FIELD_DECL, get_identifier ("cleanup"),
232 build_pointer_type (build_function_type
233 (ptr_type_node, tree_cons
234 (NULL_TREE, ptr_type_node, void_list_node))));
235 fields[4] = build_lang_decl (FIELD_DECL, get_identifier ("caught"),
236 boolean_type_node);
237 fields[5] = build_lang_decl (FIELD_DECL, get_identifier ("next"),
238 build_pointer_type (t));
239 fields[6] = build_lang_decl
240 (FIELD_DECL, get_identifier ("handlers"), long_integer_type_node);
241 /* N.B.: The fourth field LEN is expected to be
242 the number of fields - 1, not the total number of fields. */
243 finish_builtin_type (t, "cp_eh_info", fields, 6, ptr_type_node);
244 t = build_pointer_type (t);
246 /* And now the function. */
247 fn = build_lang_decl (FUNCTION_DECL, fn,
248 build_function_type (t, void_list_node));
249 DECL_EXTERNAL (fn) = 1;
250 TREE_PUBLIC (fn) = 1;
251 DECL_ARTIFICIAL (fn) = 1;
252 pushdecl_top_level (fn);
253 make_function_rtl (fn);
254 pop_obstacks ();
256 mark_used (fn);
257 return build_function_call (fn, NULL_TREE);
260 /* Retrieve a pointer to the cp_eh_info node for the current exception
261 and save it in the current binding level. */
263 static void
264 push_eh_info ()
266 tree decl, fn = call_eh_info ();
268 /* Remember the pointer to the current exception info; it won't change
269 during this catch block. */
270 decl = build_decl (VAR_DECL, get_identifier ("__exception_info"),
271 TREE_TYPE (fn));
272 DECL_ARTIFICIAL (decl) = 1;
273 DECL_INITIAL (decl) = fn;
274 decl = pushdecl (decl);
275 cp_finish_decl (decl, fn, NULL_TREE, 0, 0);
278 /* Returns a reference to the cp_eh_info node for the current exception. */
280 static tree
281 get_eh_info ()
283 /* Look for the pointer pushed in push_eh_info. */
284 tree t = lookup_name (get_identifier ("__exception_info"), 0);
285 return build_indirect_ref (t, NULL_PTR);
288 /* Returns a reference to the current exception object. */
290 static tree
291 get_eh_value ()
293 return build_component_ref (get_eh_info (), get_identifier ("value"),
294 NULL_TREE, 0);
297 /* Returns a reference to the current exception type. */
299 #if 0
300 static tree
301 get_eh_type ()
303 return build_component_ref (get_eh_info (), get_identifier ("type"),
304 NULL_TREE, 0);
307 /* Returns a reference to whether or not the current exception
308 has been caught. */
310 static tree
311 get_eh_caught ()
313 return build_component_ref (get_eh_info (), get_identifier ("caught"),
314 NULL_TREE, 0);
317 /* Returns a reference to whether or not the current exception
318 has been caught. */
320 static tree
321 get_eh_handlers ()
323 return build_component_ref (get_eh_info (), get_identifier ("handlers"),
324 NULL_TREE, 0);
326 #endif
328 /* Build a type value for use at runtime for a type that is matched
329 against by the exception handling system. */
331 static tree
332 build_eh_type_type (type)
333 tree type;
335 if (type == error_mark_node)
336 return error_mark_node;
338 /* peel back references, so they match. */
339 if (TREE_CODE (type) == REFERENCE_TYPE)
340 type = TREE_TYPE (type);
342 /* Peel off cv qualifiers. */
343 type = TYPE_MAIN_VARIANT (type);
345 return build1 (ADDR_EXPR, ptr_type_node, get_typeid_1 (type));
348 /* Build the address of a typeinfo function for use in the runtime
349 matching field of the new exception model */
351 static tree
352 build_eh_type_type_ref (type)
353 tree type;
355 tree exp;
357 if (type == error_mark_node)
358 return error_mark_node;
360 /* peel back references, so they match. */
361 if (TREE_CODE (type) == REFERENCE_TYPE)
362 type = TREE_TYPE (type);
364 /* Peel off cv qualifiers. */
365 type = TYPE_MAIN_VARIANT (type);
367 exp = get_tinfo_fn (type);
368 exp = build1 (ADDR_EXPR, ptr_type_node, exp);
370 return (exp);
373 /* This routine is called to mark all the symbols representing runtime
374 type functions in the exception table as haveing been referenced.
375 This will make sure code is emitted for them. Called from finish_file. */
376 void
377 mark_all_runtime_matches ()
379 int x,num;
380 void **ptr;
381 tree exp;
383 num = find_all_handler_type_matches (&ptr);
384 if (num == 0 || ptr == NULL)
385 return;
387 for (x=0; x <num; x++)
389 exp = (tree) ptr[x];
390 if (TREE_CODE (exp) == ADDR_EXPR)
392 exp = TREE_OPERAND (exp, 0);
393 if (TREE_CODE (exp) == FUNCTION_DECL)
394 TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (exp)) = 1;
398 free (ptr);
401 /* Build up a call to __cp_pop_exception, to destroy the exception object
402 for the current catch block. HANDLER is either true or false, telling
403 the library whether or not it is being called from an exception handler;
404 if it is, it avoids destroying the object on rethrow. */
406 static tree
407 do_pop_exception ()
409 tree fn, cleanup;
410 fn = get_identifier ("__cp_pop_exception");
411 if (IDENTIFIER_GLOBAL_VALUE (fn))
412 fn = IDENTIFIER_GLOBAL_VALUE (fn);
413 else
415 /* Declare void __cp_pop_exception (void *),
416 as defined in exception.cc. */
417 push_permanent_obstack ();
418 fn = build_lang_decl
419 (FUNCTION_DECL, fn,
420 build_function_type (void_type_node, tree_cons
421 (NULL_TREE, ptr_type_node, void_list_node)));
422 DECL_EXTERNAL (fn) = 1;
423 TREE_PUBLIC (fn) = 1;
424 DECL_ARTIFICIAL (fn) = 1;
425 pushdecl_top_level (fn);
426 make_function_rtl (fn);
427 pop_obstacks ();
430 mark_used (fn);
431 /* Arrange to do a dynamically scoped cleanup upon exit from this region. */
432 cleanup = lookup_name (get_identifier ("__exception_info"), 0);
433 cleanup = build_function_call (fn, tree_cons
434 (NULL_TREE, cleanup, NULL_TREE));
435 return cleanup;
438 /* This routine creates the cleanup for the current exception. */
440 static void
441 push_eh_cleanup ()
443 int yes;
445 yes = suspend_momentary ();
446 /* All cleanups must last longer than normal. */
447 finish_decl_cleanup (NULL_TREE, do_pop_exception ());
448 resume_momentary (yes);
451 /* Build up a call to terminate on the function obstack, for use as an
452 exception handler. */
454 static tree
455 build_terminate_handler ()
457 int yes = suspend_momentary ();
458 tree term = build_function_call (terminate_node, NULL_TREE);
459 resume_momentary (yes);
460 return term;
463 /* Initialize the catch parameter DECL. */
465 static void
466 initialize_handler_parm (decl)
467 tree decl;
469 tree exp;
470 tree init;
471 tree init_type;
473 /* Make sure we mark the catch param as used, otherwise we'll get a
474 warning about an unused ((anonymous)). */
475 TREE_USED (decl) = 1;
477 /* Figure out the type that the initializer is. */
478 init_type = TREE_TYPE (decl);
479 if (TREE_CODE (init_type) != REFERENCE_TYPE
480 && TREE_CODE (init_type) != POINTER_TYPE)
481 init_type = build_reference_type (init_type);
483 exp = get_eh_value ();
485 /* Since pointers are passed by value, initialize a reference to
486 pointer catch parm with the address of the value slot. */
487 if (TREE_CODE (init_type) == REFERENCE_TYPE
488 && TREE_CODE (TREE_TYPE (init_type)) == POINTER_TYPE)
489 exp = build_unary_op (ADDR_EXPR, exp, 1);
491 exp = ocp_convert (init_type , exp, CONV_IMPLICIT|CONV_FORCE_TEMP, 0);
493 init = convert_from_reference (exp);
495 /* If the constructor for the catch parm exits via an exception, we
496 must call terminate. See eh23.C. */
497 if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl)))
499 /* Generate the copy constructor call directly so we can wrap it.
500 See also expand_default_init. */
501 init = ocp_convert (TREE_TYPE (decl), init,
502 CONV_IMPLICIT|CONV_FORCE_TEMP, 0);
503 init = build (TRY_CATCH_EXPR, TREE_TYPE (init), init,
504 build_terminate_handler ());
507 /* Let `cp_finish_decl' know that this initializer is ok. */
508 DECL_INITIAL (decl) = error_mark_node;
509 decl = pushdecl (decl);
511 start_decl_1 (decl);
512 cp_finish_decl (decl, init, NULL_TREE, 0,
513 LOOKUP_ONLYCONVERTING|DIRECT_BIND);
516 /* Call this to start a catch block. DECL is the catch parameter. */
518 tree
519 expand_start_catch_block (decl)
520 tree decl;
522 tree compound_stmt_1;
523 tree compound_stmt_2;
524 tree type;
526 if (! doing_eh (1))
527 return NULL_TREE;
529 /* Make sure this declaration is reasonable. */
530 if (decl && !complete_ptr_ref_or_void_ptr_p (TREE_TYPE (decl), NULL_TREE))
531 decl = NULL_TREE;
533 /* Create a binding level for the eh_info and the exception object
534 cleanup. */
535 compound_stmt_1 = begin_compound_stmt (/*has_no_scope=*/0);
537 if (decl)
538 type = build_eh_type_type_ref (TREE_TYPE (decl));
539 else
540 type = NULL_TREE;
541 begin_catch_block (type);
543 push_eh_info ();
544 push_eh_cleanup ();
546 /* Create a binding level for the parm. */
547 compound_stmt_2 = begin_compound_stmt (/*has_no_scope=*/0);
549 if (decl)
550 initialize_handler_parm (decl);
552 return build_tree_list (compound_stmt_1, compound_stmt_2);
556 /* Call this to end a catch block. Its responsible for emitting the
557 code to handle jumping back to the correct place, and for emitting
558 the label to jump to if this catch block didn't match. */
560 void
561 expand_end_catch_block (blocks)
562 tree blocks;
564 tree compound_stmt_1 = blocks ? TREE_PURPOSE (blocks): NULL_TREE;
565 tree compound_stmt_2 = blocks ? TREE_VALUE (blocks): NULL_TREE;
567 if (! doing_eh (1))
568 return;
570 /* The exception being handled is rethrown if control reaches the end of
571 a handler of the function-try-block of a constructor or destructor. */
572 if (in_function_try_handler
573 && (DECL_CONSTRUCTOR_P (current_function_decl)
574 || DECL_DESTRUCTOR_P (current_function_decl)))
575 finish_expr_stmt (build_throw (NULL_TREE));
577 /* Cleanup the EH parameter. */
578 finish_compound_stmt (/*has_no_scope=*/0, compound_stmt_1);
579 /* Cleanup the EH object. */
580 finish_compound_stmt (/*has_no_scope=*/0, compound_stmt_2);
583 /* An exception spec is implemented more or less like:
585 try {
586 function body;
587 } catch (...) {
588 void *p[] = { typeid(raises) };
589 __check_eh_spec (p, count);
592 __check_eh_spec in exception.cc handles all the details. */
594 tree
595 expand_start_eh_spec ()
597 return begin_try_block ();
600 void
601 expand_end_eh_spec (raises, try_block)
602 tree raises;
603 tree try_block;
605 tree tmp, fn, decl, types = NULL_TREE;
606 tree blocks;
607 tree handler;
608 int count = 0;
610 finish_try_block (try_block);
611 handler = begin_handler ();
612 blocks = finish_handler_parms (NULL_TREE, handler);
614 /* Build up an array of type_infos. */
615 for (; raises && TREE_VALUE (raises); raises = TREE_CHAIN (raises))
617 types = tree_cons
618 (NULL_TREE, build_eh_type_type (TREE_VALUE (raises)), types);
619 ++count;
622 types = build_nt (CONSTRUCTOR, NULL_TREE, types);
623 TREE_HAS_CONSTRUCTOR (types) = 1;
625 /* We can't pass the CONSTRUCTOR directly, so stick it in a variable. */
626 tmp = build_cplus_array_type (const_ptr_type_node, NULL_TREE);
627 decl = build_decl (VAR_DECL, NULL_TREE, tmp);
628 DECL_ARTIFICIAL (decl) = 1;
629 DECL_INITIAL (decl) = types;
630 cp_finish_decl (decl, types, NULL_TREE, 0, 0);
632 decl = decay_conversion (decl);
634 fn = get_identifier ("__check_eh_spec");
635 if (IDENTIFIER_GLOBAL_VALUE (fn))
636 fn = IDENTIFIER_GLOBAL_VALUE (fn);
637 else
639 push_permanent_obstack ();
641 tmp = tree_cons
642 (NULL_TREE, integer_type_node, tree_cons
643 (NULL_TREE, TREE_TYPE (decl), void_list_node));
644 tmp = build_function_type (void_type_node, tmp);
646 fn = build_lang_decl (FUNCTION_DECL, fn, tmp);
647 DECL_EXTERNAL (fn) = 1;
648 TREE_PUBLIC (fn) = 1;
649 DECL_ARTIFICIAL (fn) = 1;
650 TREE_THIS_VOLATILE (fn) = 1;
651 pushdecl_top_level (fn);
652 make_function_rtl (fn);
653 pop_obstacks ();
656 mark_used (fn);
657 tmp = tree_cons (NULL_TREE, build_int_2 (count, 0),
658 tree_cons (NULL_TREE, decl, NULL_TREE));
659 tmp = build_call (fn, TREE_TYPE (TREE_TYPE (fn)), tmp);
660 finish_expr_stmt (tmp);
662 finish_handler (blocks, handler);
663 finish_handler_sequence (try_block);
666 /* This is called to expand all the toplevel exception handling
667 finalization for a function. It should only be called once per
668 function. */
670 void
671 expand_exception_blocks ()
673 do_pending_stack_adjust ();
674 push_to_sequence (catch_clauses);
675 expand_leftover_cleanups ();
676 do_pending_stack_adjust ();
677 catch_clauses = get_insns ();
678 end_sequence ();
680 if (catch_clauses)
682 rtx funcend = gen_label_rtx ();
683 emit_jump (funcend);
685 /* We cannot protect n regions this way if we must flow into the
686 EH region through the top of the region, as we have to with
687 the setjmp/longjmp approach. */
688 if (exceptions_via_longjmp == 0)
689 expand_eh_region_start ();
691 emit_insns (catch_clauses);
692 catch_clauses = NULL_RTX;
694 if (exceptions_via_longjmp == 0)
695 expand_eh_region_end (build_terminate_handler ());
697 expand_leftover_cleanups ();
699 emit_label (funcend);
703 tree
704 start_anon_func ()
706 static int counter = 0;
707 int old_interface_unknown = interface_unknown;
708 char name[32];
709 tree params;
710 tree t;
712 push_to_top_level ();
714 /* No need to mangle this. */
715 push_lang_context (lang_name_c);
717 interface_unknown = 1;
719 params = void_list_node;
720 /* tcf stands for throw clean function. */
721 sprintf (name, "__tcf_%d", counter++);
722 t = make_call_declarator (get_identifier (name), params, NULL_TREE,
723 NULL_TREE);
724 start_function (decl_tree_cons (NULL_TREE, get_identifier ("static"),
725 void_list_node),
726 t, NULL_TREE, SF_DEFAULT);
727 do_pushlevel ();
729 interface_unknown = old_interface_unknown;
731 pop_lang_context ();
733 return current_function_decl;
736 void
737 end_anon_func ()
739 do_poplevel ();
741 expand_body (finish_function (lineno, 0));
743 pop_from_top_level ();
746 /* Return a pointer to a buffer for an exception object of type TYPE. */
748 static tree
749 alloc_eh_object (type)
750 tree type;
752 tree fn, exp;
754 fn = get_identifier ("__eh_alloc");
755 if (IDENTIFIER_GLOBAL_VALUE (fn))
756 fn = IDENTIFIER_GLOBAL_VALUE (fn);
757 else
759 /* Declare __eh_alloc (size_t), as defined in exception.cc. */
760 tree tmp;
761 push_permanent_obstack ();
762 tmp = tree_cons (NULL_TREE, sizetype, void_list_node);
763 fn = build_lang_decl (FUNCTION_DECL, fn,
764 build_function_type (ptr_type_node, tmp));
765 DECL_EXTERNAL (fn) = 1;
766 TREE_PUBLIC (fn) = 1;
767 DECL_ARTIFICIAL (fn) = 1;
768 pushdecl_top_level (fn);
769 make_function_rtl (fn);
770 pop_obstacks ();
773 mark_used (fn);
774 exp = build_function_call (fn, tree_cons
775 (NULL_TREE, size_in_bytes (type), NULL_TREE));
776 exp = build1 (NOP_EXPR, build_pointer_type (type), exp);
777 return exp;
780 /* Expand a throw statement. This follows the following
781 algorithm:
783 1. Allocate space to save the current PC onto the stack.
784 2. Generate and emit a label and save its address into the
785 newly allocated stack space since we can't save the pc directly.
786 3. If this is the first call to throw in this function:
787 generate a label for the throw block
788 4. jump to the throw block label. */
790 tree
791 expand_throw (exp)
792 tree exp;
794 tree fn;
796 if (! doing_eh (1))
797 return error_mark_node;
799 if (exp)
801 tree throw_type;
802 tree cleanup = NULL_TREE, e;
803 tree stmt_expr;
804 tree compound_stmt;
805 tree try_block;
807 begin_init_stmts (&stmt_expr, &compound_stmt);
809 /* throw expression */
810 /* First, decay it. */
811 exp = decay_conversion (exp);
813 /* cleanup_type is void (*)(void *, int),
814 the internal type of a destructor. */
815 if (cleanup_type == NULL_TREE)
816 cleanup_type = build_pointer_type
817 (build_function_type
818 (void_type_node, tree_cons
819 (NULL_TREE, ptr_type_node, tree_cons
820 (NULL_TREE, integer_type_node, void_list_node))));
822 if (TYPE_PTR_P (TREE_TYPE (exp)))
823 throw_type = build_eh_type_type (TREE_TYPE (exp));
824 else
826 tree object, ptr;
828 /* OK, this is kind of wacky. The WP says that we call
829 terminate
831 when the exception handling mechanism, after completing
832 evaluation of the expression to be thrown but before the
833 exception is caught (_except.throw_), calls a user function
834 that exits via an uncaught exception.
836 So we have to protect the actual initialization of the
837 exception object with terminate(), but evaluate the expression
838 first. We also expand the call to __eh_alloc
839 first. Since there could be temps in the expression, we need
840 to handle that, too. */
842 my_friendly_assert (stmts_are_full_exprs_p == 1, 19990926);
844 /* Store the throw expression into a temp. This can be less
845 efficient than storing it into the allocated space directly, but
846 oh well. To do this efficiently we would need to insinuate
847 ourselves into expand_call. */
848 if (TREE_SIDE_EFFECTS (exp))
850 tree temp = create_temporary_var (TREE_TYPE (exp));
851 DECL_INITIAL (temp) = exp;
852 cp_finish_decl (temp, exp, NULL_TREE, 0, LOOKUP_ONLYCONVERTING);
853 exp = temp;
856 /* Allocate the space for the exception. */
857 ptr = save_expr (alloc_eh_object (TREE_TYPE (exp)));
858 finish_expr_stmt (ptr);
860 try_block = begin_try_block ();
861 object = build_indirect_ref (ptr, NULL_PTR);
862 exp = build_modify_expr (object, INIT_EXPR, exp);
864 if (exp == error_mark_node)
865 error (" in thrown expression");
867 finish_expr_stmt (exp);
868 finish_cleanup_try_block (try_block);
869 finish_cleanup (build_terminate_handler (), try_block);
871 throw_type = build_eh_type_type (TREE_TYPE (object));
873 if (TYPE_HAS_DESTRUCTOR (TREE_TYPE (object)))
875 cleanup = lookup_fnfields (TYPE_BINFO (TREE_TYPE (object)),
876 dtor_identifier, 0);
877 cleanup = TREE_VALUE (cleanup);
878 mark_used (cleanup);
879 mark_addressable (cleanup);
880 /* Pretend it's a normal function. */
881 cleanup = build1 (ADDR_EXPR, cleanup_type, cleanup);
884 exp = ptr;
887 /* Cast EXP to `void *' so that it will match the prototype for
888 __cp_push_exception. */
889 exp = convert (ptr_type_node, exp);
891 if (cleanup == NULL_TREE)
893 cleanup = build_int_2 (0, 0);
894 TREE_TYPE (cleanup) = cleanup_type;
897 fn = get_identifier ("__cp_push_exception");
898 if (IDENTIFIER_GLOBAL_VALUE (fn))
899 fn = IDENTIFIER_GLOBAL_VALUE (fn);
900 else
902 /* Declare __cp_push_exception (void*, void*, void (*)(void*, int)),
903 as defined in exception.cc. */
904 tree tmp;
905 push_permanent_obstack ();
906 tmp = tree_cons
907 (NULL_TREE, ptr_type_node, tree_cons
908 (NULL_TREE, ptr_type_node, tree_cons
909 (NULL_TREE, cleanup_type, void_list_node)));
910 fn = build_lang_decl (FUNCTION_DECL, fn,
911 build_function_type (void_type_node, tmp));
912 DECL_EXTERNAL (fn) = 1;
913 TREE_PUBLIC (fn) = 1;
914 DECL_ARTIFICIAL (fn) = 1;
915 pushdecl_top_level (fn);
916 make_function_rtl (fn);
917 pop_obstacks ();
920 mark_used (fn);
921 e = tree_cons (NULL_TREE, exp, tree_cons
922 (NULL_TREE, throw_type, tree_cons
923 (NULL_TREE, cleanup, NULL_TREE)));
924 finish_expr_stmt (build_function_call (fn, e));
926 exp = finish_init_stmts (stmt_expr, compound_stmt);
928 else
930 /* rethrow current exception; note that it's no longer caught. */
932 tree fn = get_identifier ("__uncatch_exception");
933 if (IDENTIFIER_GLOBAL_VALUE (fn))
934 fn = IDENTIFIER_GLOBAL_VALUE (fn);
935 else
937 /* Declare void __uncatch_exception (void)
938 as defined in exception.cc. */
939 push_permanent_obstack ();
940 fn = build_lang_decl (FUNCTION_DECL, fn,
941 build_function_type (void_type_node,
942 void_list_node));
943 DECL_EXTERNAL (fn) = 1;
944 TREE_PUBLIC (fn) = 1;
945 DECL_ARTIFICIAL (fn) = 1;
946 pushdecl_top_level (fn);
947 make_function_rtl (fn);
948 pop_obstacks ();
951 mark_used (fn);
952 exp = build_function_call (fn, NULL_TREE);
955 return exp;
958 /* Build a throw expression. */
960 tree
961 build_throw (e)
962 tree e;
964 if (e == error_mark_node)
965 return e;
967 if (processing_template_decl)
968 return build_min (THROW_EXPR, void_type_node, e);
970 if (e == null_node)
971 cp_warning ("throwing NULL, which has integral, not pointer type");
973 if (e != NULL_TREE)
975 if (!complete_ptr_ref_or_void_ptr_p (TREE_TYPE (e), e))
976 return error_mark_node;
979 e = expand_throw (e);
980 e = build1 (THROW_EXPR, void_type_node, e);
981 TREE_SIDE_EFFECTS (e) = 1;
982 TREE_USED (e) = 1;
984 return e;
987 /* Make sure TYPE is complete, pointer to complete, reference to
988 complete, or pointer to cv void. Issue diagnostic on failure.
989 Return the zero on failure and non-zero on success. FROM can be
990 the expr or decl from whence TYPE came, if available. */
992 static int
993 complete_ptr_ref_or_void_ptr_p (type, from)
994 tree type;
995 tree from;
997 int is_ptr;
999 /* Check complete. */
1000 type = complete_type_or_else (type, from);
1001 if (!type)
1002 return 0;
1004 /* Or a pointer or ref to one, or cv void *. */
1005 is_ptr = TREE_CODE (type) == POINTER_TYPE;
1006 if (is_ptr || TREE_CODE (type) == REFERENCE_TYPE)
1008 tree core = TREE_TYPE (type);
1010 if (is_ptr && same_type_p (TYPE_MAIN_VARIANT (core), void_type_node))
1011 /* OK */;
1012 else if (!complete_type_or_else (core, from))
1013 return 0;
1015 return 1;