]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/cp/except.c
Make -fsjlj-exceptions a configure option.
[thirdparty/gcc.git] / gcc / cp / except.c
1 /* Handle exceptional things in C++.
2 Copyright (C) 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
3 2000, 2001 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.
7
8 This file is part of GNU CC.
9
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)
13 any later version.
14
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.
19
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. */
24
25
26 #include "config.h"
27 #include "system.h"
28 #include "tree.h"
29 #include "rtl.h"
30 #include "expr.h"
31 #include "cp-tree.h"
32 #include "flags.h"
33 #include "obstack.h"
34 #include "output.h"
35 #include "except.h"
36 #include "toplev.h"
37 #include "eh-common.h"
38
39 static void push_eh_cleanup PARAMS ((tree));
40 static tree build_eh_type_type PARAMS ((tree));
41 static tree call_eh_info PARAMS ((void));
42 static void push_eh_info PARAMS ((void));
43 static tree get_eh_info PARAMS ((void));
44 static tree get_eh_value PARAMS ((void));
45 #if 0
46 static tree get_eh_type PARAMS ((void));
47 static tree get_eh_caught PARAMS ((void));
48 static tree get_eh_handlers PARAMS ((void));
49 #endif
50 static int dtor_nothrow PARAMS ((tree));
51 static tree do_pop_exception PARAMS ((tree));
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 bool is_admissible_throw_operand PARAMS ((tree));
57 static int can_convert_eh PARAMS ((tree, tree));
58 static void check_handlers_1 PARAMS ((tree, tree));
59 static void initialize_handler_parm PARAMS ((tree));
60 static tree expand_throw PARAMS ((tree));
61 static int decl_is_java_type PARAMS ((tree decl, int err));
62
63 #include "decl.h"
64 #include "obstack.h"
65
66 /* In a given translation unit we are constrained to catch only C++
67 types or only Java types. `catch_language' holds the current type,
68 and `catch_language_init' registers whether `catch_language' has
69 been set. */
70
71 static int catch_language_init = 0;
72 static int catch_language;
73
74 /* ======================================================================
75 Briefly the algorithm works like this:
76
77 When a constructor or start of a try block is encountered,
78 push_eh_entry (&eh_stack) is called. Push_eh_entry () creates a
79 new entry in the unwind protection stack and returns a label to
80 output to start the protection for that block.
81
82 When a destructor or end try block is encountered, pop_eh_entry
83 (&eh_stack) is called. Pop_eh_entry () returns the eh_entry it
84 created when push_eh_entry () was called. The eh_entry structure
85 contains three things at this point. The start protect label,
86 the end protect label, and the exception handler label. The end
87 protect label should be output before the call to the destructor
88 (if any). If it was a destructor, then its parse tree is stored
89 in the finalization variable in the eh_entry structure. Otherwise
90 the finalization variable is set to NULL to reflect the fact that
91 it is the end of a try block. Next, this modified eh_entry node
92 is enqueued in the finalizations queue by calling
93 enqueue_eh_entry (&queue,entry).
94
95 +---------------------------------------------------------------+
96 |XXX: Will need modification to deal with partially |
97 | constructed arrays of objects |
98 | |
99 | Basically, this consists of keeping track of how many |
100 | of the objects have been constructed already (this |
101 | should be in a register though, so that shouldn't be a |
102 | problem. |
103 +---------------------------------------------------------------+
104
105 When a catch block is encountered, there is a lot of work to be
106 done.
107
108 Since we don't want to generate the catch block inline with the
109 regular flow of the function, we need to have some way of doing
110 so. Luckily, we can use sequences to defer the catch sections.
111 When the start of a catch block is encountered, we start the
112 sequence. After the catch block is generated, we end the
113 sequence.
114
115 Next we must insure that when the catch block is executed, all
116 finalizations for the matching try block have been completed. If
117 any of those finalizations throw an exception, we must call
118 terminate according to the ARM (section r.15.6.1). What this
119 means is that we need to dequeue and emit finalizations for each
120 entry in the eh_queue until we get to an entry with a NULL
121 finalization field. For any of the finalization entries, if it
122 is not a call to terminate (), we must protect it by giving it
123 another start label, end label, and exception handler label,
124 setting its finalization tree to be a call to terminate (), and
125 enqueue'ing this new eh_entry to be output at an outer level.
126 Finally, after all that is done, we can get around to outputting
127 the catch block which basically wraps all the "catch (...) {...}"
128 statements in a big if/then/else construct that matches the
129 correct block to call.
130
131 ===================================================================== */
132
133 /* ====================================================================== */
134
135 /* sets up all the global eh stuff that needs to be initialized at the
136 start of compilation. */
137
138 void
139 init_exception_processing ()
140 {
141 /* void vtype () */
142 tree vtype = build_function_type (void_type_node, void_list_node);
143
144 if (flag_honor_std)
145 push_namespace (std_identifier);
146 terminate_node = build_cp_library_fn_ptr ("terminate", vtype);
147 TREE_THIS_VOLATILE (terminate_node) = 1;
148 TREE_NOTHROW (terminate_node) = 1;
149 if (flag_honor_std)
150 pop_namespace ();
151
152 set_exception_lang_code (EH_LANG_C_plus_plus);
153 set_exception_version_code (1);
154
155 /* If we use setjmp/longjmp EH, arrange for all cleanup actions to
156 be protected with __terminate. */
157 protect_cleanup_actions_with_terminate = 1;
158 }
159
160 /* Retrieve a pointer to the cp_eh_info node for the current exception. */
161
162 static tree
163 call_eh_info ()
164 {
165 tree fn;
166
167 fn = get_identifier ("__start_cp_handler");
168 if (IDENTIFIER_GLOBAL_VALUE (fn))
169 fn = IDENTIFIER_GLOBAL_VALUE (fn);
170 else
171 {
172 tree eh_info_type;
173 tree cleanup_fn_type;
174 tree matcher_fn_type;
175 tree cp_eh_info_type;
176 tree exception_desc_type;
177 tree fields[8];
178
179 eh_info_type = make_aggr_type (RECORD_TYPE);
180 exception_desc_type = make_aggr_type (RECORD_TYPE);
181
182 /* void * (*) (__eh_info *, void *, exception_descriptor *); */
183 matcher_fn_type = tree_cons
184 (NULL_TREE, build_pointer_type (eh_info_type), tree_cons
185 (NULL_TREE, ptr_type_node, tree_cons
186 (NULL_TREE, build_pointer_type (exception_desc_type),
187 void_list_node)));
188 matcher_fn_type = build_function_type (ptr_type_node, matcher_fn_type);
189 matcher_fn_type = build_pointer_type (matcher_fn_type);
190
191 /* void (*) (void *); */
192 cleanup_fn_type = tree_cons
193 (NULL_TREE, ptr_type_node, void_list_node);
194 cleanup_fn_type = build_function_type (void_type_node, cleanup_fn_type);
195 cleanup_fn_type = build_pointer_type (cleanup_fn_type);
196
197 /* eh-common.h
198 struct __eh_info
199 {
200 __eh_matcher match_function;
201 short language;
202 short version;
203 }; */
204 fields[0] = build_decl (FIELD_DECL,
205 get_identifier ("match_function"), ptr_type_node);
206 fields[1] = build_decl (FIELD_DECL,
207 get_identifier ("language"), short_integer_type_node);
208 fields[2] = build_decl (FIELD_DECL,
209 get_identifier ("version"), short_integer_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 (eh_info_type, "__eh_info", fields, 2, ptr_type_node);
213
214 /* exception_support.h
215 struct cp_eh_info
216 {
217 __eh_info eh_info;
218 void *value;
219 void *type;
220 cleanup_fn cleanup;
221 bool caught;
222 cp_eh_info *next;
223 long handlers;
224 void *original_value;
225 }; */
226 cp_eh_info_type = make_aggr_type (RECORD_TYPE);
227 fields[0] = build_decl (FIELD_DECL, get_identifier ("eh_info"),
228 eh_info_type);
229 fields[1] = build_decl (FIELD_DECL, get_identifier ("value"),
230 ptr_type_node);
231 fields[2] = build_decl (FIELD_DECL, get_identifier ("type"),
232 ptr_type_node);
233 fields[3] = build_decl (FIELD_DECL, get_identifier ("cleanup"),
234 cleanup_fn_type);
235 fields[4] = build_decl (FIELD_DECL, get_identifier ("caught"),
236 boolean_type_node);
237 fields[5] = build_decl (FIELD_DECL, get_identifier ("next"),
238 build_pointer_type (cp_eh_info_type));
239 fields[6] = build_decl (FIELD_DECL, get_identifier ("handlers"),
240 long_integer_type_node);
241 fields[7] = build_decl (FIELD_DECL, get_identifier ("original_value"),
242 ptr_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 (cp_eh_info_type, "cp_eh_info", fields, 7, ptr_type_node);
246
247 /* And now the function. */
248 fn = push_library_fn (fn,
249 build_function_type (build_pointer_type (cp_eh_info_type),
250 void_list_node));
251 }
252 return build_function_call (fn, NULL_TREE);
253 }
254
255 /* Retrieve a pointer to the cp_eh_info node for the current exception
256 and save it in the current binding level. */
257
258 static void
259 push_eh_info ()
260 {
261 tree decl, fn = call_eh_info ();
262
263 /* Remember the pointer to the current exception info; it won't change
264 during this catch block. */
265 decl = build_decl (VAR_DECL, get_identifier ("__exception_info"),
266 TREE_TYPE (fn));
267 DECL_ARTIFICIAL (decl) = 1;
268 DECL_INITIAL (decl) = fn;
269 decl = pushdecl (decl);
270 cp_finish_decl (decl, fn, NULL_TREE, 0);
271 }
272
273 /* Returns a reference to the cp_eh_info node for the current exception. */
274
275 static tree
276 get_eh_info ()
277 {
278 /* Look for the pointer pushed in push_eh_info. */
279 tree t = lookup_name (get_identifier ("__exception_info"), 0);
280 return build_indirect_ref (t, NULL_PTR);
281 }
282
283 /* Returns a reference to the current exception object. */
284
285 static tree
286 get_eh_value ()
287 {
288 return build_component_ref (get_eh_info (), get_identifier ("value"),
289 NULL_TREE, 0);
290 }
291
292 /* Returns a reference to the current exception type. */
293
294 #if 0
295 static tree
296 get_eh_type ()
297 {
298 return build_component_ref (get_eh_info (), get_identifier ("type"),
299 NULL_TREE, 0);
300 }
301
302 /* Returns a reference to whether or not the current exception
303 has been caught. */
304
305 static tree
306 get_eh_caught ()
307 {
308 return build_component_ref (get_eh_info (), get_identifier ("caught"),
309 NULL_TREE, 0);
310 }
311
312 /* Returns a reference to whether or not the current exception
313 has been caught. */
314
315 static tree
316 get_eh_handlers ()
317 {
318 return build_component_ref (get_eh_info (), get_identifier ("handlers"),
319 NULL_TREE, 0);
320 }
321 #endif
322
323 /* Build a type value for use at runtime for a type that is matched
324 against by the exception handling system. */
325
326 static tree
327 build_eh_type_type (type)
328 tree type;
329 {
330 if (type == error_mark_node)
331 return error_mark_node;
332
333 /* peel back references, so they match. */
334 if (TREE_CODE (type) == REFERENCE_TYPE)
335 type = TREE_TYPE (type);
336
337 /* Peel off cv qualifiers. */
338 type = TYPE_MAIN_VARIANT (type);
339
340 return build1 (ADDR_EXPR, ptr_type_node, get_typeid_1 (type));
341 }
342
343 /* Build the address of a typeinfo decl for use in the runtime
344 matching field of the new exception model */
345
346 static tree
347 build_eh_type_type_ref (type)
348 tree type;
349 {
350 tree exp;
351
352 if (type == NULL_TREE || type == error_mark_node)
353 return type;
354
355 /* peel back references, so they match. */
356 if (TREE_CODE (type) == REFERENCE_TYPE)
357 type = TREE_TYPE (type);
358
359 /* Peel off cv qualifiers. */
360 type = TYPE_MAIN_VARIANT (type);
361
362 exp = get_tinfo_decl (type);
363 mark_used (exp);
364 exp = build1 (ADDR_EXPR, ptr_type_node, exp);
365
366 return (exp);
367 }
368
369 /* This routine is called to mark all the symbols representing runtime
370 type functions in the exception table as having been referenced.
371 This will make sure code is emitted for them. Called from finish_file. */
372
373 void
374 mark_all_runtime_matches ()
375 {
376 int x,num;
377 void **ptr;
378 tree exp;
379
380 num = find_all_handler_type_matches (&ptr);
381 if (num == 0 || ptr == NULL)
382 return;
383
384 for (x=0; x <num; x++)
385 {
386 exp = (tree) ptr[x];
387 if (TREE_CODE (exp) == ADDR_EXPR)
388 {
389 exp = TREE_OPERAND (exp, 0);
390 if (TREE_CODE (exp) == FUNCTION_DECL)
391 TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (exp)) = 1;
392 }
393 }
394
395 free (ptr);
396 }
397
398 /* Returns nonzero if cleaning up an exception of type TYPE (which can be
399 NULL_TREE for a ... handler) will not throw an exception. */
400
401 static int
402 dtor_nothrow (type)
403 tree type;
404 {
405 tree fn;
406
407 if (type == NULL_TREE)
408 return 0;
409
410 if (! TYPE_HAS_DESTRUCTOR (type))
411 return 1;
412
413 fn = lookup_member (type, dtor_identifier, 0, 0);
414 fn = TREE_VALUE (fn);
415 return TREE_NOTHROW (fn);
416 }
417
418 /* Build up a call to __cp_pop_exception, to destroy the exception object
419 for the current catch block if no others are currently using it. */
420
421 static tree
422 do_pop_exception (type)
423 tree type;
424 {
425 tree fn, cleanup;
426 fn = get_identifier ("__cp_pop_exception");
427 if (IDENTIFIER_GLOBAL_VALUE (fn))
428 fn = IDENTIFIER_GLOBAL_VALUE (fn);
429 else
430 {
431 /* Declare void __cp_pop_exception (void *),
432 as defined in exception.cc. */
433 fn = push_void_library_fn
434 (fn, tree_cons (NULL_TREE, ptr_type_node, void_list_node));
435 /* This can throw if the destructor for the exception throws. */
436 TREE_NOTHROW (fn) = 0;
437 }
438
439 /* Arrange to do a dynamically scoped cleanup upon exit from this region. */
440 cleanup = lookup_name (get_identifier ("__exception_info"), 0);
441 cleanup = build_function_call (fn, tree_cons
442 (NULL_TREE, cleanup, NULL_TREE));
443 TREE_NOTHROW (cleanup) = dtor_nothrow (type);
444 return cleanup;
445 }
446
447 /* This routine creates the cleanup for the current exception. */
448
449 static void
450 push_eh_cleanup (type)
451 tree type;
452 {
453 finish_decl_cleanup (NULL_TREE, do_pop_exception (type));
454 }
455
456 /* Build up a call to terminate on the function obstack, for use as an
457 exception handler. */
458
459 static tree
460 build_terminate_handler ()
461 {
462 return build_function_call (terminate_node, NULL_TREE);
463 }
464
465 /* Return nonzero value if DECL is a Java type suitable for catch or
466 throw. */
467
468 static int
469 decl_is_java_type (decl, err)
470 tree decl;
471 int err;
472 {
473 int r = (TREE_CODE (decl) == POINTER_TYPE
474 && TREE_CODE (TREE_TYPE (decl)) == RECORD_TYPE
475 && TYPE_FOR_JAVA (TREE_TYPE (decl)));
476
477 if (err)
478 {
479 if (TREE_CODE (decl) == REFERENCE_TYPE
480 && TREE_CODE (TREE_TYPE (decl)) == RECORD_TYPE
481 && TYPE_FOR_JAVA (TREE_TYPE (decl)))
482 {
483 /* Can't throw a reference. */
484 cp_error ("type `%T' is disallowed in Java `throw' or `catch'",
485 decl);
486 }
487
488 if (r)
489 {
490 tree jthrow_node
491 = IDENTIFIER_GLOBAL_VALUE (get_identifier ("jthrowable"));
492
493 if (jthrow_node == NULL_TREE)
494 fatal_error
495 ("call to Java `catch' or `throw' with `jthrowable' undefined");
496
497 jthrow_node = TREE_TYPE (TREE_TYPE (jthrow_node));
498
499 if (! DERIVED_FROM_P (jthrow_node, TREE_TYPE (decl)))
500 {
501 /* Thrown object must be a Throwable. */
502 cp_error ("type `%T' is not derived from `java::lang::Throwable'",
503 TREE_TYPE (decl));
504 }
505 }
506 }
507
508 return r;
509 }
510
511 /* Initialize the catch parameter DECL. */
512
513 static void
514 initialize_handler_parm (decl)
515 tree decl;
516 {
517 tree exp;
518 tree init;
519 tree init_type;
520 int lang;
521
522 /* Make sure we mark the catch param as used, otherwise we'll get a
523 warning about an unused ((anonymous)). */
524 TREE_USED (decl) = 1;
525
526 /* Figure out the type that the initializer is. */
527 init_type = TREE_TYPE (decl);
528 if (TREE_CODE (init_type) != REFERENCE_TYPE
529 && TREE_CODE (init_type) != POINTER_TYPE)
530 init_type = build_reference_type (init_type);
531
532 if (decl_is_java_type (init_type, 0))
533 {
534 tree fn
535 = builtin_function ("_Jv_exception_info",
536 build_function_type (ptr_type_node,
537 tree_cons (NULL_TREE,
538 void_type_node,
539 NULL_TREE)),
540 0, NOT_BUILT_IN, NULL_PTR);
541
542 exp = build (CALL_EXPR, ptr_type_node,
543 build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (fn)),
544 fn),
545 NULL_TREE, NULL_TREE);
546 TREE_SIDE_EFFECTS (exp) = 1;
547 lang = EH_LANG_Java;
548
549 set_exception_lang_code (EH_LANG_Java);
550 set_exception_version_code (1);
551 }
552 else
553 {
554 exp = get_eh_value ();
555 lang = EH_LANG_C_plus_plus;
556 }
557
558 if (catch_language_init)
559 {
560 if (lang != catch_language)
561 error ("mixing C++ and Java `catch'es in single translation unit");
562 }
563 else
564 {
565 catch_language_init = 1;
566 catch_language = lang;
567 }
568
569 /* Since pointers are passed by value, initialize a reference to
570 pointer catch parm with the address of the value slot. */
571 if (TREE_CODE (init_type) == REFERENCE_TYPE
572 && TREE_CODE (TREE_TYPE (init_type)) == POINTER_TYPE)
573 exp = build_unary_op (ADDR_EXPR, exp, 1);
574
575 exp = ocp_convert (init_type , exp, CONV_IMPLICIT|CONV_FORCE_TEMP, 0);
576
577 init = convert_from_reference (exp);
578
579 /* If the constructor for the catch parm exits via an exception, we
580 must call terminate. See eh23.C. */
581 if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl)))
582 {
583 /* Generate the copy constructor call directly so we can wrap it.
584 See also expand_default_init. */
585 init = ocp_convert (TREE_TYPE (decl), init,
586 CONV_IMPLICIT|CONV_FORCE_TEMP, 0);
587 init = build (TRY_CATCH_EXPR, TREE_TYPE (init), init,
588 build_terminate_handler ());
589 }
590
591 /* Let `cp_finish_decl' know that this initializer is ok. */
592 DECL_INITIAL (decl) = error_mark_node;
593 decl = pushdecl (decl);
594
595 start_decl_1 (decl);
596 cp_finish_decl (decl, init, NULL_TREE,
597 LOOKUP_ONLYCONVERTING|DIRECT_BIND);
598 }
599
600 /* Call this to start a catch block. DECL is the catch parameter. */
601
602 tree
603 expand_start_catch_block (decl)
604 tree decl;
605 {
606 tree compound_stmt_1;
607 tree compound_stmt_2;
608
609 if (! doing_eh (1))
610 return NULL_TREE;
611
612 /* Make sure this declaration is reasonable. */
613 if (decl && !complete_ptr_ref_or_void_ptr_p (TREE_TYPE (decl), NULL_TREE))
614 decl = NULL_TREE;
615
616 /* Create a binding level for the eh_info and the exception object
617 cleanup. */
618 compound_stmt_1 = begin_compound_stmt (/*has_no_scope=*/0);
619
620 if (! decl || ! decl_is_java_type (TREE_TYPE (decl), 1))
621 {
622 /* The ordinary C++ case. */
623 tree type;
624
625 if (decl)
626 type = TREE_TYPE (decl);
627 else
628 type = NULL_TREE;
629 begin_catch_block (build_eh_type_type_ref (type));
630
631 push_eh_info ();
632 push_eh_cleanup (type);
633 }
634 else
635 {
636 /* The Java case. In this case, the match_info is a pointer to
637 the Java class object. We assume that the class is a
638 compiled class. */
639 tree ref = build_java_class_ref (TREE_TYPE (TREE_TYPE (decl)));
640 begin_catch_block (build1 (ADDR_EXPR, jclass_node, ref));
641 }
642
643 /* Create a binding level for the parm. */
644 compound_stmt_2 = begin_compound_stmt (/*has_no_scope=*/0);
645
646 if (decl)
647 initialize_handler_parm (decl);
648
649 return build_tree_list (compound_stmt_1, compound_stmt_2);
650 }
651
652
653 /* Call this to end a catch block. Its responsible for emitting the
654 code to handle jumping back to the correct place, and for emitting
655 the label to jump to if this catch block didn't match. */
656
657 void
658 expand_end_catch_block (blocks)
659 tree blocks;
660 {
661 tree compound_stmt_1 = blocks ? TREE_PURPOSE (blocks): NULL_TREE;
662 tree compound_stmt_2 = blocks ? TREE_VALUE (blocks): NULL_TREE;
663
664 if (! doing_eh (1))
665 return;
666
667 /* The exception being handled is rethrown if control reaches the end of
668 a handler of the function-try-block of a constructor or destructor. */
669 if (in_function_try_handler
670 && (DECL_CONSTRUCTOR_P (current_function_decl)
671 || DECL_DESTRUCTOR_P (current_function_decl)))
672 finish_expr_stmt (build_throw (NULL_TREE));
673
674 /* Cleanup the EH parameter. */
675 finish_compound_stmt (/*has_no_scope=*/0, compound_stmt_2);
676 /* Cleanup the EH object. */
677 finish_compound_stmt (/*has_no_scope=*/0, compound_stmt_1);
678 }
679
680 /* An exception spec is implemented more or less like:
681
682 try {
683 function body;
684 } catch (...) {
685 void *p[] = { typeid(raises) };
686 __check_eh_spec (p, count);
687 }
688
689 __check_eh_spec in exception.cc handles all the details. */
690
691 tree
692 expand_start_eh_spec ()
693 {
694 return begin_try_block ();
695 }
696
697 void
698 expand_end_eh_spec (raises, try_block)
699 tree raises;
700 tree try_block;
701 {
702 tree tmp, fn, decl, types = NULL_TREE;
703 tree blocks;
704 tree handler;
705 int count = 0;
706
707 finish_try_block (try_block);
708 handler = begin_handler ();
709 blocks = finish_handler_parms (NULL_TREE, handler);
710
711 if (TREE_VALUE (raises) == NULL_TREE)
712 {
713 fn = get_identifier ("__check_null_eh_spec");
714 if (IDENTIFIER_GLOBAL_VALUE (fn))
715 fn = IDENTIFIER_GLOBAL_VALUE (fn);
716 else
717 {
718 tmp = build_function_type (void_type_node, void_list_node);
719 fn = push_throw_library_fn (fn, tmp);
720 /* Since the spec doesn't allow any exceptions, this call will
721 never throw. We use push_throw_library_fn because we do want
722 TREE_THIS_VOLATILE to be set. */
723 TREE_NOTHROW (fn) = 1;
724 }
725 tmp = NULL_TREE;
726 }
727 else
728 {
729 /* Build up an array of type_infos. */
730 for (; raises && TREE_VALUE (raises); raises = TREE_CHAIN (raises))
731 {
732 types = tree_cons
733 (NULL_TREE, build_eh_type_type (TREE_VALUE (raises)), types);
734 ++count;
735 }
736
737 types = build_nt (CONSTRUCTOR, NULL_TREE, types);
738 TREE_HAS_CONSTRUCTOR (types) = 1;
739
740 /* We can't pass the CONSTRUCTOR directly, so stick it in a variable. */
741 tmp = build_cplus_array_type (const_ptr_type_node, NULL_TREE);
742 decl = build_decl (VAR_DECL, NULL_TREE, tmp);
743 DECL_ARTIFICIAL (decl) = 1;
744 DECL_INITIAL (decl) = types;
745 DECL_CONTEXT (decl) = current_function_decl;
746 cp_finish_decl (decl, types, NULL_TREE, 0);
747
748 decl = decay_conversion (decl);
749
750 fn = get_identifier ("__check_eh_spec");
751 if (IDENTIFIER_GLOBAL_VALUE (fn))
752 fn = IDENTIFIER_GLOBAL_VALUE (fn);
753 else
754 {
755 tmp = tree_cons
756 (NULL_TREE, integer_type_node, tree_cons
757 (NULL_TREE, TREE_TYPE (decl), void_list_node));
758 tmp = build_function_type (void_type_node, tmp);
759
760 fn = push_throw_library_fn (fn, tmp);
761 }
762
763 tmp = tree_cons (NULL_TREE, build_int_2 (count, 0),
764 tree_cons (NULL_TREE, decl, NULL_TREE));
765 }
766
767 tmp = build_call (fn, tmp);
768 finish_expr_stmt (tmp);
769
770 finish_handler (blocks, handler);
771 finish_handler_sequence (try_block);
772 }
773
774 /* This is called to expand all the toplevel exception handling
775 finalization for a function. It should only be called once per
776 function. */
777
778 void
779 expand_exception_blocks ()
780 {
781 do_pending_stack_adjust ();
782
783 if (catch_clauses)
784 {
785 rtx funcend = gen_label_rtx ();
786 emit_jump (funcend);
787
788 /* We cannot protect n regions this way if we must flow into the
789 EH region through the top of the region, as we have to with
790 the setjmp/longjmp approach. */
791 if (USING_SJLJ_EXCEPTIONS == 0)
792 expand_eh_region_start ();
793
794 emit_insns (catch_clauses);
795 catch_clauses = catch_clauses_last = NULL_RTX;
796
797 if (USING_SJLJ_EXCEPTIONS == 0)
798 expand_eh_region_end (build_terminate_handler ());
799
800 emit_insns (catch_clauses);
801 catch_clauses = catch_clauses_last = NULL_RTX;
802 emit_label (funcend);
803 }
804 }
805
806 /* Return a pointer to a buffer for an exception object of type TYPE. */
807
808 static tree
809 alloc_eh_object (type)
810 tree type;
811 {
812 tree fn, exp;
813
814 fn = get_identifier ("__eh_alloc");
815 if (IDENTIFIER_GLOBAL_VALUE (fn))
816 fn = IDENTIFIER_GLOBAL_VALUE (fn);
817 else
818 {
819 /* Declare __eh_alloc (size_t), as defined in exception.cc. */
820 tree tmp = tree_cons (NULL_TREE, sizetype, void_list_node);
821 fn = push_library_fn (fn, build_function_type (ptr_type_node, tmp));
822 }
823
824 exp = build_function_call (fn, tree_cons
825 (NULL_TREE, size_in_bytes (type), NULL_TREE));
826 exp = build1 (NOP_EXPR, build_pointer_type (type), exp);
827 return exp;
828 }
829
830 /* Expand a throw statement. This follows the following
831 algorithm:
832
833 1. Allocate space to save the current PC onto the stack.
834 2. Generate and emit a label and save its address into the
835 newly allocated stack space since we can't save the pc directly.
836 3. If this is the first call to throw in this function:
837 generate a label for the throw block
838 4. jump to the throw block label. */
839
840 static tree
841 expand_throw (exp)
842 tree exp;
843 {
844 tree fn;
845
846 if (! doing_eh (1))
847 return error_mark_node;
848
849 if (exp
850 && decl_is_java_type (TREE_TYPE (exp), 1))
851 {
852 /* A Java `throw' statement. */
853 tree args = tree_cons (NULL_TREE, exp, NULL);
854
855 fn = get_identifier (USING_SJLJ_EXCEPTIONS
856 ? "_Jv_Sjlj_Throw"
857 : "_Jv_Throw");
858 if (IDENTIFIER_GLOBAL_VALUE (fn))
859 fn = IDENTIFIER_GLOBAL_VALUE (fn);
860 else
861 {
862 /* Declare _Jv_Throw (void *), as defined in Java's
863 exception.cc. */
864 tree tmp = tree_cons (NULL_TREE, ptr_type_node, void_list_node);
865 tmp = build_function_type (ptr_type_node, tmp);
866 fn = push_throw_library_fn (fn, tmp);
867 }
868
869 exp = build_function_call (fn, args);
870 }
871 else if (exp)
872 {
873 tree throw_type;
874 tree cleanup = NULL_TREE, e;
875 tree stmt_expr;
876 tree compound_stmt;
877 tree try_block;
878
879 begin_init_stmts (&stmt_expr, &compound_stmt);
880
881 /* throw expression */
882 /* First, decay it. */
883 exp = decay_conversion (exp);
884
885 /* The CLEANUP_TYPE is the internal type of a destructor. Under
886 the old ABI, destructors are two-argument functions; under
887 the new ABI they take only one argument. */
888 if (cleanup_type == NULL_TREE)
889 {
890 tree arg_types;
891
892 arg_types = void_list_node;
893 arg_types = tree_cons (NULL_TREE, ptr_type_node, arg_types);
894 cleanup_type = (build_pointer_type
895 (build_function_type (void_type_node, arg_types)));
896 }
897
898 if (TYPE_PTR_P (TREE_TYPE (exp)))
899 throw_type = build_eh_type_type (TREE_TYPE (exp));
900 else
901 {
902 tree object, ptr;
903
904 /* OK, this is kind of wacky. The standard says that we call
905 terminate when the exception handling mechanism, after
906 completing evaluation of the expression to be thrown but
907 before the exception is caught (_except.throw_), calls a
908 user function that exits via an uncaught exception.
909
910 So we have to protect the actual initialization of the
911 exception object with terminate(), but evaluate the
912 expression first. Since there could be temps in the
913 expression, we need to handle that, too. We also expand
914 the call to __eh_alloc first (which doesn't matter, since
915 it can't throw). */
916
917 my_friendly_assert (stmts_are_full_exprs_p () == 1, 19990926);
918
919 /* Store the throw expression into a temp. This can be less
920 efficient than storing it into the allocated space directly, but
921 if we allocated the space first we would have to deal with
922 cleaning it up if evaluating this expression throws. */
923 if (TREE_SIDE_EFFECTS (exp))
924 {
925 tree temp = create_temporary_var (TREE_TYPE (exp));
926 DECL_INITIAL (temp) = exp;
927 cp_finish_decl (temp, exp, NULL_TREE, LOOKUP_ONLYCONVERTING);
928 exp = temp;
929 }
930
931 /* Allocate the space for the exception. */
932 ptr = save_expr (alloc_eh_object (TREE_TYPE (exp)));
933 finish_expr_stmt (ptr);
934
935 try_block = begin_try_block ();
936 object = build_indirect_ref (ptr, NULL_PTR);
937 exp = build_modify_expr (object, INIT_EXPR, exp);
938
939 if (exp == error_mark_node)
940 error (" in thrown expression");
941
942 finish_expr_stmt (exp);
943 finish_cleanup_try_block (try_block);
944 finish_cleanup (build_terminate_handler (), try_block);
945
946 throw_type = build_eh_type_type (TREE_TYPE (object));
947
948 if (TYPE_HAS_DESTRUCTOR (TREE_TYPE (object)))
949 {
950 cleanup = lookup_fnfields (TYPE_BINFO (TREE_TYPE (object)),
951 complete_dtor_identifier,
952 0);
953 cleanup = TREE_VALUE (cleanup);
954 mark_used (cleanup);
955 mark_addressable (cleanup);
956 /* Pretend it's a normal function. */
957 cleanup = build1 (ADDR_EXPR, cleanup_type, cleanup);
958 }
959
960 exp = ptr;
961 }
962
963 /* Cast EXP to `void *' so that it will match the prototype for
964 __cp_push_exception. */
965 exp = convert (ptr_type_node, exp);
966
967 if (cleanup == NULL_TREE)
968 {
969 cleanup = build_int_2 (0, 0);
970 TREE_TYPE (cleanup) = cleanup_type;
971 }
972
973 fn = cp_push_exception_identifier;
974 if (IDENTIFIER_GLOBAL_VALUE (fn))
975 fn = IDENTIFIER_GLOBAL_VALUE (fn);
976 else
977 {
978 /* Declare __cp_push_exception (void*, void*, void (*)(void*, int)),
979 as defined in exception.cc. */
980 tree tmp;
981 tmp = tree_cons
982 (NULL_TREE, ptr_type_node, tree_cons
983 (NULL_TREE, ptr_type_node, tree_cons
984 (NULL_TREE, cleanup_type, void_list_node)));
985 fn = push_void_library_fn (fn, tmp);
986 }
987
988 e = tree_cons (NULL_TREE, exp, tree_cons
989 (NULL_TREE, throw_type, tree_cons
990 (NULL_TREE, cleanup, NULL_TREE)));
991 finish_expr_stmt (build_function_call (fn, e));
992
993 exp = finish_init_stmts (stmt_expr, compound_stmt);
994 }
995 else
996 {
997 /* rethrow current exception; note that it's no longer caught. */
998
999 tree fn = get_identifier ("__uncatch_exception");
1000 if (IDENTIFIER_GLOBAL_VALUE (fn))
1001 fn = IDENTIFIER_GLOBAL_VALUE (fn);
1002 else
1003 /* Declare void __uncatch_exception (void)
1004 as defined in exception.cc. */
1005 fn = push_void_library_fn (fn, void_list_node);
1006
1007 exp = build_function_call (fn, NULL_TREE);
1008 }
1009
1010 return exp;
1011 }
1012
1013 /* Build a throw expression. */
1014
1015 tree
1016 build_throw (e)
1017 tree e;
1018 {
1019 if (e == error_mark_node)
1020 return e;
1021
1022 if (processing_template_decl)
1023 return build_min (THROW_EXPR, void_type_node, e);
1024
1025 if (e == null_node)
1026 cp_warning ("throwing NULL, which has integral, not pointer type");
1027
1028 if (e != NULL_TREE)
1029 {
1030 if (!is_admissible_throw_operand (e))
1031 return error_mark_node;
1032 }
1033
1034 e = expand_throw (e);
1035 e = build1 (THROW_EXPR, void_type_node, e);
1036 TREE_SIDE_EFFECTS (e) = 1;
1037 TREE_USED (e) = 1;
1038
1039 return e;
1040 }
1041
1042 /* Make sure TYPE is complete, pointer to complete, reference to
1043 complete, or pointer to cv void. Issue diagnostic on failure.
1044 Return the zero on failure and non-zero on success. FROM can be
1045 the expr or decl from whence TYPE came, if available. */
1046
1047 static int
1048 complete_ptr_ref_or_void_ptr_p (type, from)
1049 tree type;
1050 tree from;
1051 {
1052 int is_ptr;
1053
1054 /* Check complete. */
1055 type = complete_type_or_else (type, from);
1056 if (!type)
1057 return 0;
1058
1059 /* Or a pointer or ref to one, or cv void *. */
1060 is_ptr = TREE_CODE (type) == POINTER_TYPE;
1061 if (is_ptr || TREE_CODE (type) == REFERENCE_TYPE)
1062 {
1063 tree core = TREE_TYPE (type);
1064
1065 if (is_ptr && VOID_TYPE_P (core))
1066 /* OK */;
1067 else if (!complete_type_or_else (core, from))
1068 return 0;
1069 }
1070 return 1;
1071 }
1072
1073 /* Return truth-value if EXPRESSION is admissible in throw-expression,
1074 i.e. if it is not of incomplete type or a pointer/reference to such
1075 a type or of an abstract class type. */
1076
1077 static bool
1078 is_admissible_throw_operand (expr)
1079 tree expr;
1080 {
1081 tree type = TREE_TYPE (expr);
1082
1083 /* 15.1/4 [...] The type of the throw-expression shall not be an
1084 incomplete type, or a pointer or a reference to an incomplete
1085 type, other than void*, const void*, volatile void*, or
1086 const volatile void*. Except for these restriction and the
1087 restrictions on type matching mentioned in 15.3, the operand
1088 of throw is treated exactly as a function argument in a call
1089 (5.2.2) or the operand of a return statement. */
1090 if (!complete_ptr_ref_or_void_ptr_p (type, expr))
1091 return false;
1092
1093 /* 10.4/3 An abstract class shall not be used as a parameter type,
1094 as a function return type or as type of an explicit
1095 conversion. */
1096 else if (CLASS_TYPE_P (type) && CLASSTYPE_PURE_VIRTUALS (type))
1097 {
1098 cp_error ("Expression '%E' of abstract class type '%T' cannot be used in throw-expression", expr, type);
1099 return false;
1100 }
1101
1102 return true;
1103 }
1104
1105 /* Returns nonzero if FN is a declaration of a standard C library
1106 function which is known not to throw.
1107
1108 [lib.res.on.exception.handling]: None of the functions from the
1109 Standard C library shall report an error by throwing an
1110 exception, unless it calls a program-supplied function that
1111 throws an exception. */
1112
1113 #include "cfns.h"
1114
1115 int
1116 nothrow_libfn_p (fn)
1117 tree fn;
1118 {
1119 tree id;
1120
1121 if (TREE_PUBLIC (fn)
1122 && DECL_EXTERNAL (fn)
1123 && DECL_NAMESPACE_SCOPE_P (fn)
1124 && DECL_EXTERN_C_P (fn))
1125 /* OK */;
1126 else
1127 /* Can't be a C library function. */
1128 return 0;
1129
1130 id = DECL_ASSEMBLER_NAME (fn);
1131 return !!libc_name_p (IDENTIFIER_POINTER (id), IDENTIFIER_LENGTH (id));
1132 }
1133
1134 /* Returns nonzero if an exception of type FROM will be caught by a
1135 handler for type TO, as per [except.handle]. */
1136
1137 static int
1138 can_convert_eh (to, from)
1139 tree to, from;
1140 {
1141 if (TREE_CODE (to) == REFERENCE_TYPE)
1142 to = TREE_TYPE (to);
1143 if (TREE_CODE (from) == REFERENCE_TYPE)
1144 from = TREE_TYPE (from);
1145
1146 if (TREE_CODE (to) == POINTER_TYPE && TREE_CODE (from) == POINTER_TYPE)
1147 {
1148 to = TREE_TYPE (to);
1149 from = TREE_TYPE (from);
1150
1151 if (! at_least_as_qualified_p (to, from))
1152 return 0;
1153
1154 if (TREE_CODE (to) == VOID_TYPE)
1155 return 1;
1156
1157 /* else fall through */
1158 }
1159
1160 if (IS_AGGR_TYPE (to) && IS_AGGR_TYPE (from)
1161 && PUBLICLY_UNIQUELY_DERIVED_P (to, from))
1162 return 1;
1163
1164 return 0;
1165 }
1166
1167 /* Check whether any of HANDLERS are shadowed by another handler accepting
1168 TYPE. Note that the shadowing may not be complete; even if an exception
1169 of type B would be caught by a handler for A, there could be a derived
1170 class C for which A is an ambiguous base but B is not, so the handler
1171 for B would catch an exception of type C. */
1172
1173 static void
1174 check_handlers_1 (master, handlers)
1175 tree master;
1176 tree handlers;
1177 {
1178 tree type = TREE_TYPE (master);
1179 tree handler;
1180
1181 for (handler = handlers; handler; handler = TREE_CHAIN (handler))
1182 if (TREE_TYPE (handler)
1183 && can_convert_eh (type, TREE_TYPE (handler)))
1184 {
1185 lineno = STMT_LINENO (handler);
1186 cp_warning ("exception of type `%T' will be caught",
1187 TREE_TYPE (handler));
1188 lineno = STMT_LINENO (master);
1189 cp_warning (" by earlier handler for `%T'", type);
1190 break;
1191 }
1192 }
1193
1194 /* Given a chain of HANDLERs, make sure that they're OK. */
1195
1196 void
1197 check_handlers (handlers)
1198 tree handlers;
1199 {
1200 tree handler;
1201 int save_line = lineno;
1202 for (handler = handlers; handler; handler = TREE_CHAIN (handler))
1203 {
1204 if (TREE_CHAIN (handler) == NULL_TREE)
1205 /* No more handlers; nothing to shadow. */;
1206 else if (TREE_TYPE (handler) == NULL_TREE)
1207 {
1208 lineno = STMT_LINENO (handler);
1209 cp_pedwarn
1210 ("`...' handler must be the last handler for its try block");
1211 }
1212 else
1213 check_handlers_1 (handler, TREE_CHAIN (handler));
1214 }
1215 lineno = save_line;
1216 }