OSDN Git Service

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