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)
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. */
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));
48 static tree get_eh_type
PROTO((void));
49 static tree get_eh_caught
PROTO((void));
50 static tree get_eh_handlers
PROTO((void));
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
));
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"
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
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
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 */
92 #include "insn-flags.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 |
124 +---------------------------------------------------------------+
126 When a catch block is encountered, there is a lot of work to be
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
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. */
160 init_exception_processing ()
163 tree vtype
= build_function_type (void_type_node
, void_list_node
);
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;
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. */
188 fn
= get_identifier ("__start_cp_handler");
189 if (IDENTIFIER_GLOBAL_VALUE (fn
))
190 fn
= IDENTIFIER_GLOBAL_VALUE (fn
);
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"),
230 fields
[2] = build_lang_decl (FIELD_DECL
, get_identifier ("type"),
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"),
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
);
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. */
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"),
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. */
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. */
295 return build_component_ref (get_eh_info (), get_identifier ("value"),
299 /* Returns a reference to the current exception type. */
305 return build_component_ref (get_eh_info (), get_identifier ("type"),
309 /* Returns a reference to whether or not the current exception
315 return build_component_ref (get_eh_info (), get_identifier ("caught"),
319 /* Returns a reference to whether or not the current exception
325 return build_component_ref (get_eh_info (), get_identifier ("handlers"),
330 /* Build a type value for use at runtime for a type that is matched
331 against by the exception handling system. */
334 build_eh_type_type (type
)
337 const char *typestring
;
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
);
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 */
362 build_eh_type_type_ref (type
)
365 const char *typestring
;
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 ();
382 exp
= get_tinfo_fn (type
);
384 mark_inline_for_output (exp
);
385 exp
= build1 (ADDR_EXPR
, ptr_type_node
, exp
);
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
);
398 /* Build a type value for use at runtime for a exp that is thrown or
399 matched against by the exception handling system. */
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. */
417 mark_all_runtime_matches ()
423 num
= find_all_handler_type_matches (&ptr
);
424 if (num
== 0 || ptr
== NULL
)
427 for (x
=0; x
<num
; 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;
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. */
450 fn
= get_identifier ("__cp_pop_exception");
451 if (IDENTIFIER_GLOBAL_VALUE (fn
))
452 fn
= IDENTIFIER_GLOBAL_VALUE (fn
);
455 /* Declare void __cp_pop_exception (void *),
456 as defined in exception.cc. */
457 push_permanent_obstack ();
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
);
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
));
478 /* This routine creates the cleanup for the current exception. */
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. */
495 build_terminate_handler ()
497 int yes
= suspend_momentary ();
498 tree term
= build_function_call (terminate_node
, NULL_TREE
);
499 resume_momentary (yes
);
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) */
510 expand_start_catch_block (decl
)
513 if (building_stmt_tree ())
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
);
524 add_decl_stmt (decl
);
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. */
541 process_start_catch_block (decl
)
546 /* Create a binding level for the eh_info and the exception object
549 expand_start_bindings (0);
551 if (decl
&& !complete_ptr_ref_or_void_ptr_p (TREE_TYPE (decl
), NULL_TREE
))
555 start_catch_handler (build_eh_type_type_ref (TREE_TYPE (decl
)));
557 start_catch_handler (CATCH_ALL_TYPE
);
559 emit_line_note (input_filename
, lineno
);
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);
590 /* Create a binding level for the parm. */
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
);
613 cp_finish_decl (decl
, init
, NULL_TREE
, 0,
614 LOOKUP_ONLYCONVERTING
|DIRECT_BIND
);
620 /* Create a binding level for the parm. */
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. */
636 expand_end_catch_block ()
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
659 expand_goto (top_label_entry (&caught_return_label_stack
));
661 end_catch_handler ();
664 /* An exception spec is implemented more or less like:
669 void *p[] = { typeid(raises) };
670 __check_eh_spec (p, count);
673 __check_eh_spec in exception.cc handles all the details. */
676 expand_start_eh_spec ()
678 expand_start_try_stmts ();
682 expand_end_eh_spec (raises
)
685 tree tmp
, fn
, decl
, types
= NULL_TREE
;
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
))
695 (NULL_TREE
, build_eh_type_type (TREE_VALUE (raises
)), types
);
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
);
716 push_permanent_obstack ();
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
);
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
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 ();
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 ();
774 rtx funcend
= gen_label_rtx ();
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
);
798 static int counter
= 0;
799 int old_interface_unknown
= interface_unknown
;
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
,
816 start_function (decl_tree_cons (NULL_TREE
, get_identifier ("static"),
818 t
, NULL_TREE
, SF_DEFAULT
);
823 expand_start_bindings (0);
824 emit_line_note (input_filename
, lineno
);
826 interface_unknown
= old_interface_unknown
;
830 return current_function_decl
;
836 expand_end_bindings (getdecls (), 1, 0);
840 finish_function (lineno
, 0);
842 pop_from_top_level ();
845 /* Return a pointer to a buffer for an exception object of type TYPE. */
848 alloc_eh_object (type
)
853 fn
= get_identifier ("__eh_alloc");
854 if (IDENTIFIER_GLOBAL_VALUE (fn
))
855 fn
= IDENTIFIER_GLOBAL_VALUE (fn
);
858 /* Declare __eh_alloc (size_t), as defined in exception.cc. */
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
);
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
);
879 /* Expand a throw statement. This follows the following
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. */
894 static tree cleanup_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
915 (void_type_node
, tree_cons
916 (NULL_TREE
, ptr_type_node
, tree_cons
917 (NULL_TREE
, integer_type_node
, void_list_node
))));
921 if (TYPE_PTR_P (TREE_TYPE (exp
)))
922 throw_type
= build_eh_type (exp
);
927 /* OK, this is kind of wacky. The WP says that we call
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 ();
944 /* Unfortunately, this doesn't work. */
945 preexpand_calls (exp
);
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
);
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
)),
982 cleanup
= TREE_VALUE (cleanup
);
984 mark_addressable (cleanup
);
985 /* Pretend it's a normal function. */
986 cleanup
= build1 (ADDR_EXPR
, cleanup_type
, cleanup
);
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
);
1007 /* Declare __cp_push_exception (void*, void*, void (*)(void*, int)),
1008 as defined in exception.cc. */
1010 push_permanent_obstack ();
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
);
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);
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
);
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
,
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
);
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. */
1069 if (e
== error_mark_node
)
1072 if (processing_template_decl
)
1073 return build_min (THROW_EXPR
, void_type_node
, e
);
1076 cp_warning ("throwing NULL, which has integral, not pointer type");
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;
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. */
1097 complete_ptr_ref_or_void_ptr_p (type
, from
)
1103 /* Check complete. */
1104 type
= complete_type_or_else (type
, from
);
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
))
1116 else if (!complete_type_or_else (core
, from
))