1 /* Handle exceptional things in C++.
2 Copyright (C) 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000
3 Free Software Foundation, Inc.
4 Contributed by Michael Tiemann <tiemann@cygnus.com>
5 Rewritten by Mike Stump <mrs@cygnus.com>, based upon an
6 initial re-implementation courtesy Tad Hunt.
8 This file is part of GNU CC.
10 GNU CC is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2, or (at your option)
15 GNU CC is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with GNU CC; see the file COPYING. If not, write to
22 the Free Software Foundation, 59 Temple Place - Suite 330,
23 Boston, MA 02111-1307, USA. */
38 #include "eh-common.h"
40 static void push_eh_cleanup
PARAMS ((void));
41 static tree build_eh_type_type
PARAMS ((tree
));
42 static tree call_eh_info
PARAMS ((void));
43 static void push_eh_info
PARAMS ((void));
44 static tree get_eh_info
PARAMS ((void));
45 static tree get_eh_value
PARAMS ((void));
47 static tree get_eh_type
PARAMS ((void));
48 static tree get_eh_caught
PARAMS ((void));
49 static tree get_eh_handlers
PARAMS ((void));
51 static tree do_pop_exception
PARAMS ((void));
52 static tree build_eh_type_type_ref
PARAMS ((tree
));
53 static tree build_terminate_handler
PARAMS ((void));
54 static tree alloc_eh_object
PARAMS ((tree
));
55 static int complete_ptr_ref_or_void_ptr_p
PARAMS ((tree
, tree
));
56 static void initialize_handler_parm
PARAMS ((tree
));
57 static tree expand_throw
PARAMS ((tree
));
58 static int decl_is_java_type
PARAMS ((tree decl
, int err
));
61 /* This is the startup, and finish stuff per exception table. */
63 /* XXX - Tad: exception handling section */
64 #ifndef EXCEPT_SECTION_ASM_OP
65 #define EXCEPT_SECTION_ASM_OP "section\t.gcc_except_table,\"a\",@progbits"
68 #ifdef EXCEPT_SECTION_ASM_OP
70 /* on machines which support it, the exception table lives in another section,
71 but it needs a label so we can reference it... This sets up that
73 asm (EXCEPT_SECTION_ASM_OP
);
74 exception_table __EXCEPTION_TABLE__
[1] = { (void*)0, (void*)0, (void*)0 };
75 asm (TEXT_SECTION_ASM_OP
);
77 #endif /* EXCEPT_SECTION_ASM_OP */
79 #ifdef EXCEPT_SECTION_ASM_OP
81 /* we need to know where the end of the exception table is... so this
84 asm (EXCEPT_SECTION_ASM_OP
);
85 exception_table __EXCEPTION_END__
[1] = { (void*)-1, (void*)-1, (void*)-1 };
86 asm (TEXT_SECTION_ASM_OP
);
88 #endif /* EXCEPT_SECTION_ASM_OP */
93 #include "insn-flags.h"
96 /* In a given translation unit we are constrained to catch only C++
97 types or only Java types. `catch_language' holds the current type,
98 and `catch_language_init' registers whether `catch_language' has
101 static int catch_language_init
= 0;
102 static int catch_language
;
104 /* ======================================================================
105 Briefly the algorithm works like this:
107 When a constructor or start of a try block is encountered,
108 push_eh_entry (&eh_stack) is called. Push_eh_entry () creates a
109 new entry in the unwind protection stack and returns a label to
110 output to start the protection for that block.
112 When a destructor or end try block is encountered, pop_eh_entry
113 (&eh_stack) is called. Pop_eh_entry () returns the eh_entry it
114 created when push_eh_entry () was called. The eh_entry structure
115 contains three things at this point. The start protect label,
116 the end protect label, and the exception handler label. The end
117 protect label should be output before the call to the destructor
118 (if any). If it was a destructor, then its parse tree is stored
119 in the finalization variable in the eh_entry structure. Otherwise
120 the finalization variable is set to NULL to reflect the fact that
121 it is the end of a try block. Next, this modified eh_entry node
122 is enqueued in the finalizations queue by calling
123 enqueue_eh_entry (&queue,entry).
125 +---------------------------------------------------------------+
126 |XXX: Will need modification to deal with partially |
127 | constructed arrays of objects |
129 | Basically, this consists of keeping track of how many |
130 | of the objects have been constructed already (this |
131 | should be in a register though, so that shouldn't be a |
133 +---------------------------------------------------------------+
135 When a catch block is encountered, there is a lot of work to be
138 Since we don't want to generate the catch block inline with the
139 regular flow of the function, we need to have some way of doing
140 so. Luckily, we can use sequences to defer the catch sections.
141 When the start of a catch block is encountered, we start the
142 sequence. After the catch block is generated, we end the
145 Next we must insure that when the catch block is executed, all
146 finalizations for the matching try block have been completed. If
147 any of those finalizations throw an exception, we must call
148 terminate according to the ARM (section r.15.6.1). What this
149 means is that we need to dequeue and emit finalizations for each
150 entry in the eh_queue until we get to an entry with a NULL
151 finalization field. For any of the finalization entries, if it
152 is not a call to terminate (), we must protect it by giving it
153 another start label, end label, and exception handler label,
154 setting its finalization tree to be a call to terminate (), and
155 enqueue'ing this new eh_entry to be output at an outer level.
156 Finally, after all that is done, we can get around to outputting
157 the catch block which basically wraps all the "catch (...) {...}"
158 statements in a big if/then/else construct that matches the
159 correct block to call.
161 ===================================================================== */
163 /* ====================================================================== */
165 /* sets up all the global eh stuff that needs to be initialized at the
166 start of compilation. */
169 init_exception_processing ()
172 tree vtype
= build_function_type (void_type_node
, void_list_node
);
175 push_namespace (get_identifier ("std"));
176 terminate_node
= build_cp_library_fn_ptr ("terminate", vtype
);
177 TREE_THIS_VOLATILE (terminate_node
) = 1;
178 TREE_NOTHROW (terminate_node
) = 1;
182 set_exception_lang_code (EH_LANG_C_plus_plus
);
183 set_exception_version_code (1);
185 /* If we use setjmp/longjmp EH, arrange for all cleanup actions to
186 be protected with __terminate. */
187 protect_cleanup_actions_with_terminate
= 1;
190 /* Retrieve a pointer to the cp_eh_info node for the current exception. */
197 fn
= get_identifier ("__start_cp_handler");
198 if (IDENTIFIER_GLOBAL_VALUE (fn
))
199 fn
= IDENTIFIER_GLOBAL_VALUE (fn
);
202 tree t1
, t
, fields
[7];
204 /* Declare cp_eh_info * __start_cp_handler (void),
205 as defined in exception.cc. */
207 /* struct cp_eh_info. This must match exception.cc. Note that this
208 type is not pushed anywhere. */
209 t1
= make_aggr_type (RECORD_TYPE
);
210 fields
[0] = build_lang_decl (FIELD_DECL
,
211 get_identifier ("handler_label"), ptr_type_node
);
212 fields
[1] = build_lang_decl (FIELD_DECL
,
213 get_identifier ("dynamic_handler_chain"), ptr_type_node
);
214 fields
[2] = build_lang_decl (FIELD_DECL
,
215 get_identifier ("info"), ptr_type_node
);
216 fields
[3] = build_lang_decl (FIELD_DECL
,
217 get_identifier ("table_index"), ptr_type_node
);
218 /* N.B.: The fourth field LEN is expected to be
219 the number of fields - 1, not the total number of fields. */
220 finish_builtin_type (t1
, "eh_context", fields
, 3, ptr_type_node
);
221 t1
= build_pointer_type (t1
);
223 t1
= make_aggr_type (RECORD_TYPE
);
224 fields
[0] = build_lang_decl (FIELD_DECL
,
225 get_identifier ("match_function"), ptr_type_node
);
226 fields
[1] = build_lang_decl (FIELD_DECL
,
227 get_identifier ("language"), short_integer_type_node
);
228 fields
[2] = build_lang_decl (FIELD_DECL
,
229 get_identifier ("version"), short_integer_type_node
);
230 /* N.B.: The fourth field LEN is expected to be
231 the number of fields - 1, not the total number of fields. */
232 finish_builtin_type (t1
, "__eh_info", fields
, 2, ptr_type_node
);
233 t
= make_aggr_type (RECORD_TYPE
);
234 fields
[0] = build_lang_decl (FIELD_DECL
,
235 get_identifier ("eh_info"), t1
);
236 fields
[1] = build_lang_decl (FIELD_DECL
, get_identifier ("value"),
238 fields
[2] = build_lang_decl (FIELD_DECL
, get_identifier ("type"),
240 fields
[3] = build_lang_decl
241 (FIELD_DECL
, get_identifier ("cleanup"),
242 build_pointer_type (build_function_type
243 (ptr_type_node
, tree_cons
244 (NULL_TREE
, ptr_type_node
, void_list_node
))));
245 fields
[4] = build_lang_decl (FIELD_DECL
, get_identifier ("caught"),
247 fields
[5] = build_lang_decl (FIELD_DECL
, get_identifier ("next"),
248 build_pointer_type (t
));
249 fields
[6] = build_lang_decl
250 (FIELD_DECL
, get_identifier ("handlers"), long_integer_type_node
);
251 /* N.B.: The fourth field LEN is expected to be
252 the number of fields - 1, not the total number of fields. */
253 finish_builtin_type (t
, "cp_eh_info", fields
, 6, ptr_type_node
);
254 t
= build_pointer_type (t
);
256 /* And now the function. */
257 fn
= push_library_fn (fn
, build_function_type (t
, void_list_node
));
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);
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 if (type
== error_mark_node
)
338 return error_mark_node
;
340 /* peel back references, so they match. */
341 if (TREE_CODE (type
) == REFERENCE_TYPE
)
342 type
= TREE_TYPE (type
);
344 /* Peel off cv qualifiers. */
345 type
= TYPE_MAIN_VARIANT (type
);
347 return build1 (ADDR_EXPR
, ptr_type_node
, get_typeid_1 (type
));
350 /* Build the address of a typeinfo decl for use in the runtime
351 matching field of the new exception model */
354 build_eh_type_type_ref (type
)
359 if (type
== error_mark_node
)
360 return error_mark_node
;
362 /* peel back references, so they match. */
363 if (TREE_CODE (type
) == REFERENCE_TYPE
)
364 type
= TREE_TYPE (type
);
366 /* Peel off cv qualifiers. */
367 type
= TYPE_MAIN_VARIANT (type
);
369 exp
= get_tinfo_decl (type
);
371 exp
= build1 (ADDR_EXPR
, ptr_type_node
, exp
);
376 /* This routine is called to mark all the symbols representing runtime
377 type functions in the exception table as having been referenced.
378 This will make sure code is emitted for them. Called from finish_file. */
380 mark_all_runtime_matches ()
386 num
= find_all_handler_type_matches (&ptr
);
387 if (num
== 0 || ptr
== NULL
)
390 for (x
=0; x
<num
; x
++)
393 if (TREE_CODE (exp
) == ADDR_EXPR
)
395 exp
= TREE_OPERAND (exp
, 0);
396 if (TREE_CODE (exp
) == FUNCTION_DECL
)
397 TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (exp
)) = 1;
404 /* Build up a call to __cp_pop_exception, to destroy the exception object
405 for the current catch block. HANDLER is either true or false, telling
406 the library whether or not it is being called from an exception handler;
407 if it is, it avoids destroying the object on rethrow. */
413 fn
= get_identifier ("__cp_pop_exception");
414 if (IDENTIFIER_GLOBAL_VALUE (fn
))
415 fn
= IDENTIFIER_GLOBAL_VALUE (fn
);
418 /* Declare void __cp_pop_exception (void *),
419 as defined in exception.cc. */
420 fn
= push_void_library_fn
421 (fn
, tree_cons (NULL_TREE
, ptr_type_node
, void_list_node
));
422 /* This can throw if the destructor for the exception throws. */
423 TREE_NOTHROW (fn
) = 0;
426 /* Arrange to do a dynamically scoped cleanup upon exit from this region. */
427 cleanup
= lookup_name (get_identifier ("__exception_info"), 0);
428 cleanup
= build_function_call (fn
, tree_cons
429 (NULL_TREE
, cleanup
, NULL_TREE
));
433 /* This routine creates the cleanup for the current exception. */
438 finish_decl_cleanup (NULL_TREE
, do_pop_exception ());
441 /* Build up a call to terminate on the function obstack, for use as an
442 exception handler. */
445 build_terminate_handler ()
447 return build_function_call (terminate_node
, NULL_TREE
);
450 /* Return nonzero value if DECL is a Java type suitable for catch or
454 decl_is_java_type (decl
, err
)
458 int r
= (TREE_CODE (decl
) == POINTER_TYPE
459 && TREE_CODE (TREE_TYPE (decl
)) == RECORD_TYPE
460 && TYPE_FOR_JAVA (TREE_TYPE (decl
)));
464 if (TREE_CODE (decl
) == REFERENCE_TYPE
465 && TREE_CODE (TREE_TYPE (decl
)) == RECORD_TYPE
466 && TYPE_FOR_JAVA (TREE_TYPE (decl
)))
468 /* Can't throw a reference. */
469 cp_error ("type `%T' is disallowed in Java `throw' or `catch'",
476 = IDENTIFIER_GLOBAL_VALUE (get_identifier ("jthrowable"));
477 if (jthrow_node
== NULL_TREE
)
478 fatal ("call to Java `catch' or `throw', while `jthrowable' undefined");
479 jthrow_node
= TREE_TYPE (TREE_TYPE (jthrow_node
));
481 if (! DERIVED_FROM_P (jthrow_node
, TREE_TYPE (decl
)))
483 /* Thrown object must be a Throwable. */
484 cp_error ("type `%T' is not derived from `java::lang::Throwable'",
493 /* Initialize the catch parameter DECL. */
496 initialize_handler_parm (decl
)
504 /* Make sure we mark the catch param as used, otherwise we'll get a
505 warning about an unused ((anonymous)). */
506 TREE_USED (decl
) = 1;
508 /* Figure out the type that the initializer is. */
509 init_type
= TREE_TYPE (decl
);
510 if (TREE_CODE (init_type
) != REFERENCE_TYPE
511 && TREE_CODE (init_type
) != POINTER_TYPE
)
512 init_type
= build_reference_type (init_type
);
514 if (decl_is_java_type (init_type
, 0))
517 = builtin_function ("_Jv_exception_info",
518 build_function_type (ptr_type_node
,
519 tree_cons (NULL_TREE
,
522 0, NOT_BUILT_IN
, NULL_PTR
);
524 exp
= build (CALL_EXPR
, ptr_type_node
,
525 build1 (ADDR_EXPR
, build_pointer_type (TREE_TYPE (fn
)),
527 NULL_TREE
, NULL_TREE
);
528 TREE_SIDE_EFFECTS (exp
) = 1;
531 set_exception_lang_code (EH_LANG_Java
);
532 set_exception_version_code (1);
536 exp
= get_eh_value ();
537 lang
= EH_LANG_C_plus_plus
;
540 if (catch_language_init
)
542 if (lang
!= catch_language
)
543 error ("mixing C++ and Java `catch'es in single translation unit");
547 catch_language_init
= 1;
548 catch_language
= lang
;
551 /* Since pointers are passed by value, initialize a reference to
552 pointer catch parm with the address of the value slot. */
553 if (TREE_CODE (init_type
) == REFERENCE_TYPE
554 && TREE_CODE (TREE_TYPE (init_type
)) == POINTER_TYPE
)
555 exp
= build_unary_op (ADDR_EXPR
, exp
, 1);
557 exp
= ocp_convert (init_type
, exp
, CONV_IMPLICIT
|CONV_FORCE_TEMP
, 0);
559 init
= convert_from_reference (exp
);
561 /* If the constructor for the catch parm exits via an exception, we
562 must call terminate. See eh23.C. */
563 if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl
)))
565 /* Generate the copy constructor call directly so we can wrap it.
566 See also expand_default_init. */
567 init
= ocp_convert (TREE_TYPE (decl
), init
,
568 CONV_IMPLICIT
|CONV_FORCE_TEMP
, 0);
569 init
= build (TRY_CATCH_EXPR
, TREE_TYPE (init
), init
,
570 build_terminate_handler ());
573 /* Let `cp_finish_decl' know that this initializer is ok. */
574 DECL_INITIAL (decl
) = error_mark_node
;
575 decl
= pushdecl (decl
);
578 cp_finish_decl (decl
, init
, NULL_TREE
,
579 LOOKUP_ONLYCONVERTING
|DIRECT_BIND
);
582 /* Call this to start a catch block. DECL is the catch parameter. */
585 expand_start_catch_block (decl
)
588 tree compound_stmt_1
;
589 tree compound_stmt_2
;
595 /* Make sure this declaration is reasonable. */
596 if (decl
&& !complete_ptr_ref_or_void_ptr_p (TREE_TYPE (decl
), NULL_TREE
))
599 /* Create a binding level for the eh_info and the exception object
601 compound_stmt_1
= begin_compound_stmt (/*has_no_scope=*/0);
603 if (! decl
|| ! decl_is_java_type (TREE_TYPE (decl
), 1))
605 /* The ordinary C++ case. */
608 type
= build_eh_type_type_ref (TREE_TYPE (decl
));
611 begin_catch_block (type
);
618 /* The Java case. In this case, the match_info is a pointer to
619 the Java class object. We assume that the class is a
621 tree ref
= build_java_class_ref (TREE_TYPE (TREE_TYPE (decl
)));
622 begin_catch_block (build1 (ADDR_EXPR
, jclass_node
, ref
));
625 /* Create a binding level for the parm. */
626 compound_stmt_2
= begin_compound_stmt (/*has_no_scope=*/0);
629 initialize_handler_parm (decl
);
631 return build_tree_list (compound_stmt_1
, compound_stmt_2
);
635 /* Call this to end a catch block. Its responsible for emitting the
636 code to handle jumping back to the correct place, and for emitting
637 the label to jump to if this catch block didn't match. */
640 expand_end_catch_block (blocks
)
643 tree compound_stmt_1
= blocks
? TREE_PURPOSE (blocks
): NULL_TREE
;
644 tree compound_stmt_2
= blocks
? TREE_VALUE (blocks
): NULL_TREE
;
649 /* The exception being handled is rethrown if control reaches the end of
650 a handler of the function-try-block of a constructor or destructor. */
651 if (in_function_try_handler
652 && (DECL_CONSTRUCTOR_P (current_function_decl
)
653 || DECL_DESTRUCTOR_P (current_function_decl
)))
654 finish_expr_stmt (build_throw (NULL_TREE
));
656 /* Cleanup the EH parameter. */
657 finish_compound_stmt (/*has_no_scope=*/0, compound_stmt_2
);
658 /* Cleanup the EH object. */
659 finish_compound_stmt (/*has_no_scope=*/0, compound_stmt_1
);
662 /* An exception spec is implemented more or less like:
667 void *p[] = { typeid(raises) };
668 __check_eh_spec (p, count);
671 __check_eh_spec in exception.cc handles all the details. */
674 expand_start_eh_spec ()
676 return begin_try_block ();
680 expand_end_eh_spec (raises
, try_block
)
684 tree tmp
, fn
, decl
, types
= NULL_TREE
;
689 finish_try_block (try_block
);
690 handler
= begin_handler ();
691 blocks
= finish_handler_parms (NULL_TREE
, handler
);
693 /* Build up an array of type_infos. */
694 for (; raises
&& TREE_VALUE (raises
); raises
= TREE_CHAIN (raises
))
697 (NULL_TREE
, build_eh_type_type (TREE_VALUE (raises
)), types
);
701 types
= build_nt (CONSTRUCTOR
, NULL_TREE
, types
);
702 TREE_HAS_CONSTRUCTOR (types
) = 1;
704 /* We can't pass the CONSTRUCTOR directly, so stick it in a variable. */
705 tmp
= build_cplus_array_type (const_ptr_type_node
, NULL_TREE
);
706 decl
= build_decl (VAR_DECL
, NULL_TREE
, tmp
);
707 DECL_ARTIFICIAL (decl
) = 1;
708 DECL_INITIAL (decl
) = types
;
709 DECL_CONTEXT (decl
) = current_function_decl
;
710 cp_finish_decl (decl
, types
, NULL_TREE
, 0);
712 decl
= decay_conversion (decl
);
714 fn
= get_identifier ("__check_eh_spec");
715 if (IDENTIFIER_GLOBAL_VALUE (fn
))
716 fn
= IDENTIFIER_GLOBAL_VALUE (fn
);
720 (NULL_TREE
, integer_type_node
, tree_cons
721 (NULL_TREE
, TREE_TYPE (decl
), void_list_node
));
723 fn
= push_throw_library_fn (fn
, tmp
);
726 tmp
= tree_cons (NULL_TREE
, build_int_2 (count
, 0),
727 tree_cons (NULL_TREE
, decl
, NULL_TREE
));
728 tmp
= build_call (fn
, tmp
);
729 finish_expr_stmt (tmp
);
731 finish_handler (blocks
, handler
);
732 finish_handler_sequence (try_block
);
735 /* This is called to expand all the toplevel exception handling
736 finalization for a function. It should only be called once per
740 expand_exception_blocks ()
742 do_pending_stack_adjust ();
746 rtx funcend
= gen_label_rtx ();
749 /* We cannot protect n regions this way if we must flow into the
750 EH region through the top of the region, as we have to with
751 the setjmp/longjmp approach. */
752 if (exceptions_via_longjmp
== 0)
753 expand_eh_region_start ();
755 emit_insns (catch_clauses
);
756 catch_clauses
= NULL_RTX
;
758 if (exceptions_via_longjmp
== 0)
759 expand_eh_region_end (build_terminate_handler ());
761 emit_insns (catch_clauses
);
762 catch_clauses
= NULL_RTX
;
763 emit_label (funcend
);
767 /* Return a pointer to a buffer for an exception object of type TYPE. */
770 alloc_eh_object (type
)
775 fn
= get_identifier ("__eh_alloc");
776 if (IDENTIFIER_GLOBAL_VALUE (fn
))
777 fn
= IDENTIFIER_GLOBAL_VALUE (fn
);
780 /* Declare __eh_alloc (size_t), as defined in exception.cc. */
781 tree tmp
= tree_cons (NULL_TREE
, sizetype
, void_list_node
);
782 fn
= push_library_fn (fn
, build_function_type (ptr_type_node
, tmp
));
785 exp
= build_function_call (fn
, tree_cons
786 (NULL_TREE
, size_in_bytes (type
), NULL_TREE
));
787 exp
= build1 (NOP_EXPR
, build_pointer_type (type
), exp
);
791 /* Expand a throw statement. This follows the following
794 1. Allocate space to save the current PC onto the stack.
795 2. Generate and emit a label and save its address into the
796 newly allocated stack space since we can't save the pc directly.
797 3. If this is the first call to throw in this function:
798 generate a label for the throw block
799 4. jump to the throw block label. */
808 return error_mark_node
;
811 && decl_is_java_type (TREE_TYPE (exp
), 1))
813 /* A Java `throw' statement. */
814 tree args
= tree_cons (NULL_TREE
, exp
, NULL
);
816 fn
= get_identifier (exceptions_via_longjmp
819 if (IDENTIFIER_GLOBAL_VALUE (fn
))
820 fn
= IDENTIFIER_GLOBAL_VALUE (fn
);
823 /* Declare _Jv_Throw (void *), as defined in Java's
825 tree tmp
= tree_cons (NULL_TREE
, ptr_type_node
, void_list_node
);
826 tmp
= build_function_type (ptr_type_node
, tmp
);
827 fn
= push_library_fn (fn
, tmp
);
828 TREE_THIS_VOLATILE (fn
) = 1;
829 TREE_NOTHROW (fn
) = 0;
832 exp
= build_function_call (fn
, args
);
837 tree cleanup
= NULL_TREE
, e
;
842 begin_init_stmts (&stmt_expr
, &compound_stmt
);
844 /* throw expression */
845 /* First, decay it. */
846 exp
= decay_conversion (exp
);
848 /* cleanup_type is void (*)(void *, int),
849 the internal type of a destructor. */
850 if (cleanup_type
== NULL_TREE
)
851 cleanup_type
= build_pointer_type
853 (void_type_node
, tree_cons
854 (NULL_TREE
, ptr_type_node
, tree_cons
855 (NULL_TREE
, integer_type_node
, void_list_node
))));
857 if (TYPE_PTR_P (TREE_TYPE (exp
)))
858 throw_type
= build_eh_type_type (TREE_TYPE (exp
));
863 /* OK, this is kind of wacky. The standard says that we call
864 terminate when the exception handling mechanism, after
865 completing evaluation of the expression to be thrown but
866 before the exception is caught (_except.throw_), calls a
867 user function that exits via an uncaught exception.
869 So we have to protect the actual initialization of the
870 exception object with terminate(), but evaluate the expression
871 first. We also expand the call to __eh_alloc
872 first. Since there could be temps in the expression, we need
873 to handle that, too. */
875 my_friendly_assert (stmts_are_full_exprs_p
== 1, 19990926);
877 /* Store the throw expression into a temp. This can be less
878 efficient than storing it into the allocated space directly, but
879 oh well. To do this efficiently we would need to insinuate
880 ourselves into expand_call. */
881 if (TREE_SIDE_EFFECTS (exp
))
883 tree temp
= create_temporary_var (TREE_TYPE (exp
));
884 DECL_INITIAL (temp
) = exp
;
885 cp_finish_decl (temp
, exp
, NULL_TREE
, LOOKUP_ONLYCONVERTING
);
889 /* Allocate the space for the exception. */
890 ptr
= save_expr (alloc_eh_object (TREE_TYPE (exp
)));
891 finish_expr_stmt (ptr
);
893 try_block
= begin_try_block ();
894 object
= build_indirect_ref (ptr
, NULL_PTR
);
895 exp
= build_modify_expr (object
, INIT_EXPR
, exp
);
897 if (exp
== error_mark_node
)
898 error (" in thrown expression");
900 finish_expr_stmt (exp
);
901 finish_cleanup_try_block (try_block
);
902 finish_cleanup (build_terminate_handler (), try_block
);
904 throw_type
= build_eh_type_type (TREE_TYPE (object
));
906 if (TYPE_HAS_DESTRUCTOR (TREE_TYPE (object
)))
908 cleanup
= lookup_fnfields (TYPE_BINFO (TREE_TYPE (object
)),
910 cleanup
= TREE_VALUE (cleanup
);
912 mark_addressable (cleanup
);
913 /* Pretend it's a normal function. */
914 cleanup
= build1 (ADDR_EXPR
, cleanup_type
, cleanup
);
920 /* Cast EXP to `void *' so that it will match the prototype for
921 __cp_push_exception. */
922 exp
= convert (ptr_type_node
, exp
);
924 if (cleanup
== NULL_TREE
)
926 cleanup
= build_int_2 (0, 0);
927 TREE_TYPE (cleanup
) = cleanup_type
;
930 fn
= get_identifier ("__cp_push_exception");
931 if (IDENTIFIER_GLOBAL_VALUE (fn
))
932 fn
= IDENTIFIER_GLOBAL_VALUE (fn
);
935 /* Declare __cp_push_exception (void*, void*, void (*)(void*, int)),
936 as defined in exception.cc. */
939 (NULL_TREE
, ptr_type_node
, tree_cons
940 (NULL_TREE
, ptr_type_node
, tree_cons
941 (NULL_TREE
, cleanup_type
, void_list_node
)));
942 fn
= push_void_library_fn (fn
, tmp
);
945 e
= tree_cons (NULL_TREE
, exp
, tree_cons
946 (NULL_TREE
, throw_type
, tree_cons
947 (NULL_TREE
, cleanup
, NULL_TREE
)));
948 finish_expr_stmt (build_function_call (fn
, e
));
950 exp
= finish_init_stmts (stmt_expr
, compound_stmt
);
954 /* rethrow current exception; note that it's no longer caught. */
956 tree fn
= get_identifier ("__uncatch_exception");
957 if (IDENTIFIER_GLOBAL_VALUE (fn
))
958 fn
= IDENTIFIER_GLOBAL_VALUE (fn
);
960 /* Declare void __uncatch_exception (void)
961 as defined in exception.cc. */
962 fn
= push_void_library_fn (fn
, void_list_node
);
964 exp
= build_function_call (fn
, NULL_TREE
);
970 /* Build a throw expression. */
976 if (e
== error_mark_node
)
979 if (processing_template_decl
)
980 return build_min (THROW_EXPR
, void_type_node
, e
);
983 cp_warning ("throwing NULL, which has integral, not pointer type");
987 if (!complete_ptr_ref_or_void_ptr_p (TREE_TYPE (e
), e
))
988 return error_mark_node
;
991 e
= expand_throw (e
);
992 e
= build1 (THROW_EXPR
, void_type_node
, e
);
993 TREE_SIDE_EFFECTS (e
) = 1;
999 /* Make sure TYPE is complete, pointer to complete, reference to
1000 complete, or pointer to cv void. Issue diagnostic on failure.
1001 Return the zero on failure and non-zero on success. FROM can be
1002 the expr or decl from whence TYPE came, if available. */
1005 complete_ptr_ref_or_void_ptr_p (type
, from
)
1011 /* Check complete. */
1012 type
= complete_type_or_else (type
, from
);
1016 /* Or a pointer or ref to one, or cv void *. */
1017 is_ptr
= TREE_CODE (type
) == POINTER_TYPE
;
1018 if (is_ptr
|| TREE_CODE (type
) == REFERENCE_TYPE
)
1020 tree core
= TREE_TYPE (type
);
1022 if (is_ptr
&& same_type_p (TYPE_MAIN_VARIANT (core
), void_type_node
))
1024 else if (!complete_type_or_else (core
, from
))