OSDN Git Service

Add - before rms to be more portable.
[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 (std_identifier);
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 will
696              never throw.  We use push_throw_library_fn because we do want
697              TREE_THIS_VOLATILE to be set.  */
698           TREE_NOTHROW (fn) = 1;
699         }
700       tmp = NULL_TREE;
701     }
702   else
703     {
704       /* Build up an array of type_infos.  */
705       for (; raises && TREE_VALUE (raises); raises = TREE_CHAIN (raises))
706         {
707           types = tree_cons
708             (NULL_TREE, build_eh_type_type (TREE_VALUE (raises)), types);
709           ++count;
710         }
711
712       types = build_nt (CONSTRUCTOR, NULL_TREE, types);
713       TREE_HAS_CONSTRUCTOR (types) = 1;
714
715       /* We can't pass the CONSTRUCTOR directly, so stick it in a variable.  */
716       tmp = build_cplus_array_type (const_ptr_type_node, NULL_TREE);
717       decl = build_decl (VAR_DECL, NULL_TREE, tmp);
718       DECL_ARTIFICIAL (decl) = 1;
719       DECL_INITIAL (decl) = types;
720       DECL_CONTEXT (decl) = current_function_decl;
721       cp_finish_decl (decl, types, NULL_TREE, 0);
722
723       decl = decay_conversion (decl);
724
725       fn = get_identifier ("__check_eh_spec");
726       if (IDENTIFIER_GLOBAL_VALUE (fn))
727         fn = IDENTIFIER_GLOBAL_VALUE (fn);
728       else
729         {
730           tmp = tree_cons
731             (NULL_TREE, integer_type_node, tree_cons
732              (NULL_TREE, TREE_TYPE (decl), void_list_node));
733           tmp = build_function_type (void_type_node, tmp);
734
735           fn = push_throw_library_fn (fn, tmp);
736         }
737
738       tmp = tree_cons (NULL_TREE, build_int_2 (count, 0), 
739                        tree_cons (NULL_TREE, decl, NULL_TREE));
740     }
741
742   tmp = build_call (fn, tmp);
743   finish_expr_stmt (tmp);
744
745   finish_handler (blocks, handler);
746   finish_handler_sequence (try_block);
747 }
748
749 /* This is called to expand all the toplevel exception handling
750    finalization for a function.  It should only be called once per
751    function.  */
752
753 void
754 expand_exception_blocks ()
755 {
756   do_pending_stack_adjust ();
757
758   if (catch_clauses)
759     {
760       rtx funcend = gen_label_rtx ();
761       emit_jump (funcend);
762
763       /* We cannot protect n regions this way if we must flow into the
764          EH region through the top of the region, as we have to with
765          the setjmp/longjmp approach.  */
766       if (exceptions_via_longjmp == 0)
767         expand_eh_region_start ();
768
769       emit_insns (catch_clauses);
770       catch_clauses = catch_clauses_last = NULL_RTX;
771
772       if (exceptions_via_longjmp == 0)
773         expand_eh_region_end (build_terminate_handler ());
774
775       emit_insns (catch_clauses);
776       catch_clauses = catch_clauses_last = NULL_RTX;
777       emit_label (funcend);
778     }
779 }
780
781 /* Return a pointer to a buffer for an exception object of type TYPE.  */
782
783 static tree
784 alloc_eh_object (type)
785      tree type;
786 {
787   tree fn, exp;
788
789   fn = get_identifier ("__eh_alloc");
790   if (IDENTIFIER_GLOBAL_VALUE (fn))
791     fn = IDENTIFIER_GLOBAL_VALUE (fn);
792   else
793     {
794       /* Declare __eh_alloc (size_t), as defined in exception.cc.  */
795       tree tmp = tree_cons (NULL_TREE, sizetype, void_list_node);
796       fn = push_library_fn (fn, build_function_type (ptr_type_node, tmp));
797     }
798
799   exp = build_function_call (fn, tree_cons
800                              (NULL_TREE, size_in_bytes (type), NULL_TREE));
801   exp = build1 (NOP_EXPR, build_pointer_type (type), exp);
802   return exp;
803 }
804
805 /* Expand a throw statement.  This follows the following
806    algorithm:
807
808         1. Allocate space to save the current PC onto the stack.
809         2. Generate and emit a label and save its address into the
810                 newly allocated stack space since we can't save the pc directly.
811         3. If this is the first call to throw in this function:
812                 generate a label for the throw block
813         4. jump to the throw block label.  */
814
815 static tree
816 expand_throw (exp)
817      tree exp;
818 {
819   tree fn;
820
821   if (! doing_eh (1))
822     return error_mark_node;
823
824   if (exp
825       && decl_is_java_type (TREE_TYPE (exp), 1))
826     {
827       /* A Java `throw' statement.  */
828       tree args = tree_cons (NULL_TREE, exp, NULL);
829
830       fn = get_identifier (exceptions_via_longjmp
831                            ? "_Jv_Sjlj_Throw"
832                            : "_Jv_Throw");
833       if (IDENTIFIER_GLOBAL_VALUE (fn))
834         fn = IDENTIFIER_GLOBAL_VALUE (fn);
835       else
836         {
837           /* Declare _Jv_Throw (void *), as defined in Java's
838              exception.cc.  */
839           tree tmp = tree_cons (NULL_TREE, ptr_type_node, void_list_node);
840           tmp = build_function_type (ptr_type_node, tmp);
841           fn = push_throw_library_fn (fn, tmp);
842         }
843
844       exp = build_function_call (fn, args);
845     }
846   else if (exp)
847     {
848       tree throw_type;
849       tree cleanup = NULL_TREE, e;
850       tree stmt_expr;
851       tree compound_stmt;
852       tree try_block;
853
854       begin_init_stmts (&stmt_expr, &compound_stmt);
855
856       /* throw expression */
857       /* First, decay it.  */
858       exp = decay_conversion (exp);
859
860       /* The CLEANUP_TYPE is the internal type of a destructor.  Under
861          the old ABI, destructors are two-argument functions; under
862          the new ABI they take only one argument.  */
863       if (cleanup_type == NULL_TREE)
864         {
865           tree arg_types;
866           
867           arg_types = void_list_node;
868           if (!flag_new_abi)
869             arg_types = tree_cons (NULL_TREE, integer_type_node, arg_types);
870           arg_types = tree_cons (NULL_TREE, ptr_type_node, arg_types);
871           cleanup_type = (build_pointer_type 
872                           (build_function_type (void_type_node, arg_types)));
873         }
874
875       if (TYPE_PTR_P (TREE_TYPE (exp)))
876         throw_type = build_eh_type_type (TREE_TYPE (exp));
877       else
878         {
879           tree object, ptr;
880
881           /* OK, this is kind of wacky.  The standard says that we call
882              terminate when the exception handling mechanism, after
883              completing evaluation of the expression to be thrown but
884              before the exception is caught (_except.throw_), calls a
885              user function that exits via an uncaught exception.
886
887              So we have to protect the actual initialization of the
888              exception object with terminate(), but evaluate the
889              expression first.  Since there could be temps in the
890              expression, we need to handle that, too.  We also expand
891              the call to __eh_alloc first (which doesn't matter, since
892              it can't throw).  */
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              if we allocated the space first we would have to deal with
899              cleaning it up if evaluating this expression throws.  */
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 }