OSDN Git Service

.:
[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,
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
38 static void push_eh_cleanup PARAMS ((tree));
39 static tree prepare_eh_type PARAMS ((tree));
40 static tree build_eh_type_type PARAMS ((tree));
41 static tree do_begin_catch PARAMS ((void));
42 static int dtor_nothrow PARAMS ((tree));
43 static tree do_end_catch PARAMS ((tree));
44 static void push_eh_cleanup PARAMS ((tree));
45 static bool decl_is_java_type PARAMS ((tree decl, int err));
46 static void initialize_handler_parm PARAMS ((tree, tree));
47 static tree do_allocate_exception PARAMS ((tree));
48 static int complete_ptr_ref_or_void_ptr_p PARAMS ((tree, tree));
49 static bool is_admissible_throw_operand PARAMS ((tree));
50 static int can_convert_eh PARAMS ((tree, tree));
51 static void check_handlers_1 PARAMS ((tree, tree));
52 static tree cp_protect_cleanup_actions PARAMS ((void));
53
54 #include "decl.h"
55 #include "obstack.h"
56
57 /* Sets up all the global eh stuff that needs to be initialized at the
58    start of compilation.  */
59
60 void
61 init_exception_processing ()
62 {
63   tree tmp;
64
65   /* void std::terminate (); */
66   push_namespace (std_identifier);
67   tmp = build_function_type (void_type_node, void_list_node);
68   terminate_node = build_cp_library_fn_ptr ("terminate", tmp);
69   TREE_THIS_VOLATILE (terminate_node) = 1;
70   TREE_NOTHROW (terminate_node) = 1;
71   pop_namespace ();
72
73   /* void __cxa_call_unexpected(void *); */
74   tmp = tree_cons (NULL_TREE, ptr_type_node, void_list_node);
75   tmp = build_function_type (void_type_node, tmp);
76   call_unexpected_node
77     = push_throw_library_fn (get_identifier ("__cxa_call_unexpected"), tmp);
78
79   eh_personality_libfunc = init_one_libfunc (USING_SJLJ_EXCEPTIONS
80                                              ? "__gxx_personality_sj0"
81                                              : "__gxx_personality_v0");
82
83   lang_eh_runtime_type = build_eh_type_type;
84   lang_protect_cleanup_actions = &cp_protect_cleanup_actions;
85 }
86
87 /* Returns an expression to be executed if an unhandled exception is
88    propogated out of a cleanup region.  */
89
90 static tree
91 cp_protect_cleanup_actions ()
92 {
93   /* [except.terminate]
94
95      When the destruction of an object during stack unwinding exits
96      using an exception ... void terminate(); is called.  */
97   return build_call (terminate_node, NULL_TREE);
98 }     
99
100 static tree
101 prepare_eh_type (type)
102      tree type;
103 {
104   if (type == NULL_TREE)
105     return type;
106   if (type == error_mark_node)
107     return error_mark_node;
108
109   /* peel back references, so they match.  */
110   if (TREE_CODE (type) == REFERENCE_TYPE)
111     type = TREE_TYPE (type);
112
113   /* Peel off cv qualifiers.  */
114   type = TYPE_MAIN_VARIANT (type);
115
116   return type;
117 }
118
119 /* Build the address of a typeinfo decl for use in the runtime
120    matching field of the exception model.   */
121
122 static tree
123 build_eh_type_type (type)
124      tree type;
125 {
126   tree exp;
127
128   if (type == NULL_TREE || type == error_mark_node)
129     return type;
130
131   if (decl_is_java_type (type, 0))
132     exp = build_java_class_ref (TREE_TYPE (type));
133   else
134     exp = get_tinfo_decl (type);
135
136   mark_used (exp);
137   exp = build1 (ADDR_EXPR, ptr_type_node, exp);
138
139   return exp;
140 }
141
142 tree
143 build_exc_ptr ()
144 {
145   return build (EXC_PTR_EXPR, ptr_type_node);
146 }
147
148 /* Build up a call to __cxa_begin_catch, to tell the runtime that the
149    exception has been handled.  */
150
151 static tree
152 do_begin_catch ()
153 {
154   tree fn;
155
156   fn = get_identifier ("__cxa_begin_catch");
157   if (IDENTIFIER_GLOBAL_VALUE (fn))
158     fn = IDENTIFIER_GLOBAL_VALUE (fn);
159   else
160     {
161       /* Declare void* __cxa_begin_catch (void *).  */
162       tree tmp = tree_cons (NULL_TREE, ptr_type_node, void_list_node);
163       fn = push_library_fn (fn, build_function_type (ptr_type_node, tmp));
164     }
165
166   return build_function_call (fn, tree_cons (NULL_TREE, build_exc_ptr (),
167                                              NULL_TREE));
168 }
169
170 /* Returns nonzero if cleaning up an exception of type TYPE (which can be
171    NULL_TREE for a ... handler) will not throw an exception.  */
172
173 static int
174 dtor_nothrow (type)
175      tree type;
176 {
177   tree fn;
178
179   if (type == NULL_TREE)
180     return 0;
181
182   if (! TYPE_HAS_DESTRUCTOR (type))
183     return 1;
184
185   fn = lookup_member (type, dtor_identifier, 0, 0);
186   fn = TREE_VALUE (fn);
187   return TREE_NOTHROW (fn);
188 }
189
190 /* Build up a call to __cxa_end_catch, to destroy the exception object
191    for the current catch block if no others are currently using it.  */
192
193 static tree
194 do_end_catch (type)
195      tree type;
196 {
197   tree fn, cleanup;
198
199   fn = get_identifier ("__cxa_end_catch");
200   if (IDENTIFIER_GLOBAL_VALUE (fn))
201     fn = IDENTIFIER_GLOBAL_VALUE (fn);
202   else
203     {
204       /* Declare void __cxa_end_catch ().  */
205       fn = push_void_library_fn (fn, void_list_node);
206       /* This can throw if the destructor for the exception throws.  */
207       TREE_NOTHROW (fn) = 0;
208     }
209
210   cleanup = build_function_call (fn, NULL_TREE);
211   TREE_NOTHROW (cleanup) = dtor_nothrow (type);
212
213   return cleanup;
214 }
215
216 /* This routine creates the cleanup for the current exception.  */
217
218 static void
219 push_eh_cleanup (type)
220      tree type;
221 {
222   finish_decl_cleanup (NULL_TREE, do_end_catch (type));
223 }
224
225 /* Return nonzero value if DECL is a Java type suitable for catch or
226    throw.  */
227
228 static bool
229 decl_is_java_type (decl, err)
230      tree decl;
231      int err;
232 {
233   bool r = (TREE_CODE (decl) == POINTER_TYPE
234             && TREE_CODE (TREE_TYPE (decl)) == RECORD_TYPE
235             && TYPE_FOR_JAVA (TREE_TYPE (decl)));
236
237   if (err)
238     {
239       if (TREE_CODE (decl) == REFERENCE_TYPE
240           && TREE_CODE (TREE_TYPE (decl)) == RECORD_TYPE
241           && TYPE_FOR_JAVA (TREE_TYPE (decl)))
242         {
243           /* Can't throw a reference.  */
244           cp_error ("type `%T' is disallowed in Java `throw' or `catch'",
245                     decl);
246         }
247
248       if (r)
249         {
250           tree jthrow_node
251             = IDENTIFIER_GLOBAL_VALUE (get_identifier ("jthrowable"));
252
253           if (jthrow_node == NULL_TREE)
254             fatal_error
255               ("call to Java `catch' or `throw' with `jthrowable' undefined");
256
257           jthrow_node = TREE_TYPE (TREE_TYPE (jthrow_node));
258
259           if (! DERIVED_FROM_P (jthrow_node, TREE_TYPE (decl)))
260             {
261               /* Thrown object must be a Throwable.  */
262               cp_error ("type `%T' is not derived from `java::lang::Throwable'",
263                         TREE_TYPE (decl));
264             }
265         }
266     }
267
268   return r;
269 }
270
271 /* Select the personality routine to be used for exception handling,
272    or issue an error if we need two different ones in the same
273    translation unit.
274    ??? At present eh_personality_libfunc is set to
275    __gxx_personality_(sj|v)0 in init_exception_processing - should it
276    be done here instead?  */
277 void
278 choose_personality_routine (lang)
279      enum languages lang;
280 {
281   static enum {
282     chose_none,
283     chose_cpp,
284     chose_java,
285     gave_error
286   } state;
287
288   switch (state)
289     {
290     case gave_error:
291       return;
292
293     case chose_cpp:
294       if (lang != lang_cplusplus)
295         goto give_error;
296       return;
297
298     case chose_java:
299       if (lang != lang_java)
300         goto give_error;
301       return;
302
303     case chose_none:
304       ; /* proceed to language selection */
305     }
306
307   switch (lang)
308     {
309     case lang_cplusplus:
310       state = chose_cpp;
311       break;
312
313     case lang_java:
314       state = chose_java;
315       eh_personality_libfunc = init_one_libfunc (USING_SJLJ_EXCEPTIONS
316                                                  ? "__gcj_personality_sj0"
317                                                  : "__gcj_personality_v0");
318       break;
319
320     default:
321       abort ();
322     }
323   return;
324
325  give_error:
326   error ("mixing C++ and Java catches in a single translation unit");
327   state = gave_error;
328 }
329
330 /* Initialize the catch parameter DECL.  */
331
332 static void 
333 initialize_handler_parm (decl, exp)
334      tree decl;
335      tree exp;
336 {
337   tree init;
338   tree init_type;
339
340   /* Make sure we mark the catch param as used, otherwise we'll get a
341      warning about an unused ((anonymous)).  */
342   TREE_USED (decl) = 1;
343
344   /* Figure out the type that the initializer is.  Pointers are returned
345      adjusted by value from __cxa_begin_catch.  Others are returned by 
346      reference.  */
347   init_type = TREE_TYPE (decl);
348   if (! TYPE_PTR_P (init_type)
349       && TREE_CODE (init_type) != REFERENCE_TYPE)
350     init_type = build_reference_type (init_type);
351
352   choose_personality_routine (decl_is_java_type (init_type, 0)
353                               ? lang_java : lang_cplusplus);
354
355   /* Since pointers are passed by value, initialize a reference to
356      pointer catch parm with the address of the temporary.  */
357   if (TREE_CODE (init_type) == REFERENCE_TYPE
358       && TYPE_PTR_P (TREE_TYPE (init_type)))
359     exp = build_unary_op (ADDR_EXPR, exp, 1);
360
361   exp = ocp_convert (init_type, exp, CONV_IMPLICIT|CONV_FORCE_TEMP, 0);
362
363   init = convert_from_reference (exp);
364
365   /* If the constructor for the catch parm exits via an exception, we
366      must call terminate.  See eh23.C.  */
367   if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl)))
368     {
369       /* Generate the copy constructor call directly so we can wrap it.
370          See also expand_default_init.  */
371       init = ocp_convert (TREE_TYPE (decl), init,
372                           CONV_IMPLICIT|CONV_FORCE_TEMP, 0);
373       init = build1 (MUST_NOT_THROW_EXPR, TREE_TYPE (init), init);
374     }
375
376   /* Let `cp_finish_decl' know that this initializer is ok.  */
377   DECL_INITIAL (decl) = error_mark_node;
378   decl = pushdecl (decl);
379
380   start_decl_1 (decl);
381   cp_finish_decl (decl, init, NULL_TREE,
382                   LOOKUP_ONLYCONVERTING|DIRECT_BIND);
383 }
384
385 /* Call this to start a catch block.  DECL is the catch parameter.  */
386
387 tree
388 expand_start_catch_block (decl)
389      tree decl;
390 {
391   tree exp = NULL_TREE;
392   tree type;
393   bool is_java;
394
395   if (! doing_eh (1))
396     return NULL_TREE;
397
398   /* Make sure this declaration is reasonable.  */
399   if (decl && !complete_ptr_ref_or_void_ptr_p (TREE_TYPE (decl), NULL_TREE))
400     decl = NULL_TREE;
401
402   if (decl)
403     type = prepare_eh_type (TREE_TYPE (decl));
404   else
405     type = NULL_TREE;
406
407   is_java = false;
408   if (decl)
409     {
410       tree init;
411
412       if (decl_is_java_type (type, 1))
413         {
414           /* Java only passes object via pointer and doesn't require
415              adjusting.  The java object is immediately before the
416              generic exception header.  */
417           init = build_exc_ptr ();
418           init = build1 (NOP_EXPR, build_pointer_type (type), init);
419           init = build (MINUS_EXPR, TREE_TYPE (init), init,
420                         TYPE_SIZE_UNIT (TREE_TYPE (init)));
421           init = build_indirect_ref (init, NULL);
422           is_java = true;
423         }
424       else
425         {
426           /* C++ requires that we call __cxa_begin_catch to get the
427              pointer to the actual object.  */
428           init = do_begin_catch ();
429         }
430           
431       exp = create_temporary_var (ptr_type_node);
432       DECL_REGISTER (exp) = 1;
433       cp_finish_decl (exp, init, NULL_TREE, LOOKUP_ONLYCONVERTING);
434       finish_expr_stmt (build_modify_expr (exp, INIT_EXPR, init));
435     }
436   else
437     finish_expr_stmt (do_begin_catch ());
438
439   /* C++ requires that we call __cxa_end_catch at the end of
440      processing the exception.  */
441   if (! is_java)
442     push_eh_cleanup (type);
443
444   if (decl)
445     initialize_handler_parm (decl, exp);
446
447   return type;
448 }
449
450
451 /* Call this to end a catch block.  Its responsible for emitting the
452    code to handle jumping back to the correct place, and for emitting
453    the label to jump to if this catch block didn't match.  */
454
455 void
456 expand_end_catch_block ()
457 {
458   if (! doing_eh (1))
459     return;
460
461   /* The exception being handled is rethrown if control reaches the end of
462      a handler of the function-try-block of a constructor or destructor.  */
463   if (in_function_try_handler
464       && (DECL_CONSTRUCTOR_P (current_function_decl)
465           || DECL_DESTRUCTOR_P (current_function_decl)))
466     finish_expr_stmt (build_throw (NULL_TREE));
467 }
468
469 tree
470 begin_eh_spec_block ()
471 {
472   tree r = build_stmt (EH_SPEC_BLOCK, NULL_TREE, NULL_TREE);
473   add_stmt (r);
474   return r;
475 }
476
477 void
478 finish_eh_spec_block (raw_raises, eh_spec_block)
479      tree raw_raises;
480      tree eh_spec_block;
481 {
482   tree raises;
483
484   RECHAIN_STMTS (eh_spec_block, EH_SPEC_STMTS (eh_spec_block));
485
486   /* Strip cv quals, etc, from the specification types.  */
487   for (raises = NULL_TREE;
488        raw_raises && TREE_VALUE (raw_raises);
489        raw_raises = TREE_CHAIN (raw_raises))
490     raises = tree_cons (NULL_TREE, prepare_eh_type (TREE_VALUE (raw_raises)),
491                         raises);
492
493   EH_SPEC_RAISES (eh_spec_block) = raises;
494 }
495
496 /* Return a pointer to a buffer for an exception object of type TYPE.  */
497
498 static tree
499 do_allocate_exception (type)
500      tree type;
501 {
502   tree fn;
503
504   fn = get_identifier ("__cxa_allocate_exception");
505   if (IDENTIFIER_GLOBAL_VALUE (fn))
506     fn = IDENTIFIER_GLOBAL_VALUE (fn);
507   else
508     {
509       /* Declare void *__cxa_allocate_exception(size_t).  */
510       tree tmp = tree_cons (NULL_TREE, c_size_type_node, void_list_node);
511       fn = push_library_fn (fn, build_function_type (ptr_type_node, tmp));
512     }
513   
514   return build_function_call (fn, tree_cons (NULL_TREE, size_in_bytes (type),
515                                              NULL_TREE));
516 }
517
518 #if 0
519 /* Call __cxa_free_exception from a cleanup.  This is never invoked
520    directly.  */
521
522 static tree
523 do_free_exception (ptr)
524      tree ptr;
525 {
526   tree fn;
527
528   fn = get_identifier ("__cxa_free_exception");
529   if (IDENTIFIER_GLOBAL_VALUE (fn))
530     fn = IDENTIFIER_GLOBAL_VALUE (fn);
531   else
532     {
533       /* Declare void __cxa_free_exception (void *).  */
534       fn = push_void_library_fn (fn, tree_cons (NULL_TREE, ptr_type_node,
535                                                 void_list_node));
536     }
537
538   return build_function_call (fn, tree_cons (NULL_TREE, ptr, NULL_TREE));
539 }
540 #endif
541
542 /* Build a throw expression.  */
543
544 tree
545 build_throw (exp)
546      tree exp;
547 {
548   tree fn;
549
550   if (exp == error_mark_node)
551     return exp;
552
553   if (processing_template_decl)
554     return build_min (THROW_EXPR, void_type_node, exp);
555
556   if (exp == null_node)
557     cp_warning ("throwing NULL, which has integral, not pointer type");
558   
559   if (exp != NULL_TREE)
560     {
561       if (!is_admissible_throw_operand (exp))
562         return error_mark_node;
563     }
564
565   if (! doing_eh (1))
566     return error_mark_node;
567
568   if (exp && decl_is_java_type (TREE_TYPE (exp), 1))
569     {
570       tree fn = get_identifier ("_Jv_Throw");
571       if (IDENTIFIER_GLOBAL_VALUE (fn))
572         fn = IDENTIFIER_GLOBAL_VALUE (fn);
573       else
574         {
575           /* Declare void _Jv_Throw (void *).  */
576           tree tmp = tree_cons (NULL_TREE, ptr_type_node, void_list_node);
577           tmp = build_function_type (ptr_type_node, tmp);
578           fn = push_throw_library_fn (fn, tmp);
579         }
580
581       exp = build_function_call (fn, tree_cons (NULL_TREE, exp, NULL_TREE));
582     }
583   else if (exp)
584     {
585       tree throw_type;
586       tree cleanup;
587       tree stmt_expr;
588       tree compound_stmt;
589       tree object, ptr;
590       tree tmp;
591
592       fn = get_identifier ("__cxa_throw");
593       if (IDENTIFIER_GLOBAL_VALUE (fn))
594         fn = IDENTIFIER_GLOBAL_VALUE (fn);
595       else
596         {
597           /* The CLEANUP_TYPE is the internal type of a destructor.  */
598           if (cleanup_type == NULL_TREE)
599             {
600               tmp = void_list_node;
601               tmp = tree_cons (NULL_TREE, ptr_type_node, tmp);
602               tmp = build_function_type (void_type_node, tmp);
603               cleanup_type = build_pointer_type (tmp);
604             }
605
606           /* Declare void __cxa_throw (void*, void*, void (*)(void*)).  */
607           /* ??? Second argument is supposed to be "std::type_info*".  */
608           tmp = void_list_node;
609           tmp = tree_cons (NULL_TREE, cleanup_type, tmp);
610           tmp = tree_cons (NULL_TREE, ptr_type_node, tmp);
611           tmp = tree_cons (NULL_TREE, ptr_type_node, tmp);
612           tmp = build_function_type (void_type_node, tmp);
613           fn = push_throw_library_fn (fn, tmp);
614         }
615
616       begin_init_stmts (&stmt_expr, &compound_stmt);
617
618       /* throw expression */
619       /* First, decay it.  */
620       exp = decay_conversion (exp);
621
622       /* OK, this is kind of wacky.  The standard says that we call
623          terminate when the exception handling mechanism, after
624          completing evaluation of the expression to be thrown but
625          before the exception is caught (_except.throw_), calls a
626          user function that exits via an uncaught exception.
627
628          So we have to protect the actual initialization of the
629          exception object with terminate(), but evaluate the
630          expression first.  Since there could be temps in the
631          expression, we need to handle that, too.  We also expand
632          the call to __cxa_allocate_exception first (which doesn't
633          matter, since it can't throw).  */
634
635       my_friendly_assert (stmts_are_full_exprs_p () == 1, 19990926);
636
637       /* Store the throw expression into a temp.  This can be less
638          efficient than storing it into the allocated space directly, but
639          if we allocated the space first we would have to deal with
640          cleaning it up if evaluating this expression throws.  */
641       if (TREE_SIDE_EFFECTS (exp))
642         {
643           tmp = create_temporary_var (TREE_TYPE (exp));
644           DECL_INITIAL (tmp) = exp;
645           cp_finish_decl (tmp, exp, NULL_TREE, LOOKUP_ONLYCONVERTING);
646           exp = tmp;
647         }
648
649       /* Allocate the space for the exception.  */
650       ptr = create_temporary_var (ptr_type_node);
651       DECL_REGISTER (ptr) = 1;
652       cp_finish_decl (ptr, NULL_TREE, NULL_TREE, LOOKUP_ONLYCONVERTING);
653       tmp = do_allocate_exception (TREE_TYPE (exp));
654       tmp = build_modify_expr (ptr, INIT_EXPR, tmp);
655       finish_expr_stmt (tmp);
656
657       object = build1 (NOP_EXPR, build_pointer_type (TREE_TYPE (exp)), ptr);
658       object = build_indirect_ref (object, NULL);
659
660       exp = build_modify_expr (object, INIT_EXPR, exp);
661       if (exp == error_mark_node)
662         error ("  in thrown expression");
663
664       exp = build1 (MUST_NOT_THROW_EXPR, TREE_TYPE (exp), exp);
665       finish_expr_stmt (exp);
666
667       throw_type = build_eh_type_type (prepare_eh_type (TREE_TYPE (object)));
668
669       if (TYPE_HAS_DESTRUCTOR (TREE_TYPE (object)))
670         {
671           cleanup = lookup_fnfields (TYPE_BINFO (TREE_TYPE (object)),
672                                      complete_dtor_identifier, 0);
673           cleanup = TREE_VALUE (cleanup);
674           mark_used (cleanup);
675           mark_addressable (cleanup);
676           /* Pretend it's a normal function.  */
677           cleanup = build1 (ADDR_EXPR, cleanup_type, cleanup);
678         }
679       else
680         {
681           cleanup = build_int_2 (0, 0);
682           TREE_TYPE (cleanup) = cleanup_type;
683         }
684
685       tmp = tree_cons (NULL_TREE, cleanup, NULL_TREE);
686       tmp = tree_cons (NULL_TREE, throw_type, tmp);
687       tmp = tree_cons (NULL_TREE, ptr, tmp);
688       tmp = build_function_call (fn, tmp);
689
690       /* ??? Indicate that this function call throws throw_type.  */
691
692       finish_expr_stmt (tmp);
693
694       exp = finish_init_stmts (stmt_expr, compound_stmt);
695     }
696   else
697     {
698       /* Rethrow current exception.  */
699
700       tree fn = get_identifier ("__cxa_rethrow");
701       if (IDENTIFIER_GLOBAL_VALUE (fn))
702         fn = IDENTIFIER_GLOBAL_VALUE (fn);
703       else
704         {
705           /* Declare void __cxa_rethrow (void).  */
706           fn = push_throw_library_fn
707             (fn, build_function_type (void_type_node, void_list_node));
708         }
709
710       exp = build_function_call (fn, NULL_TREE);
711     }
712
713   exp = build1 (THROW_EXPR, void_type_node, exp);
714
715   return exp;
716 }
717
718 /* Make sure TYPE is complete, pointer to complete, reference to
719    complete, or pointer to cv void. Issue diagnostic on failure.
720    Return the zero on failure and non-zero on success. FROM can be
721    the expr or decl from whence TYPE came, if available.  */
722
723 static int
724 complete_ptr_ref_or_void_ptr_p (type, from)
725      tree type;
726      tree from;
727 {
728   int is_ptr;
729   
730   /* Check complete.  */
731   type = complete_type_or_else (type, from);
732   if (!type)
733     return 0;
734   
735   /* Or a pointer or ref to one, or cv void *.  */
736   is_ptr = TREE_CODE (type) == POINTER_TYPE;
737   if (is_ptr || TREE_CODE (type) == REFERENCE_TYPE)
738     {
739       tree core = TREE_TYPE (type);
740   
741       if (is_ptr && VOID_TYPE_P (core))
742         /* OK */;
743       else if (!complete_type_or_else (core, from))
744         return 0;
745     }
746   return 1;
747 }
748
749 /* Return truth-value if EXPRESSION is admissible in throw-expression,
750    i.e. if it is not of incomplete type or a pointer/reference to such
751    a type or of an abstract class type.  */
752
753 static bool
754 is_admissible_throw_operand (expr)
755      tree expr;
756 {
757   tree type = TREE_TYPE (expr);
758
759   /* 15.1/4 [...] The type of the throw-expression shall not be an
760             incomplete type, or a pointer or a reference to an incomplete
761             type, other than void*, const void*, volatile void*, or
762             const volatile void*.  Except for these restriction and the
763             restrictions on type matching mentioned in 15.3, the operand
764             of throw is treated exactly as a function argument in a call
765             (5.2.2) or the operand of a return statement.  */
766   if (!complete_ptr_ref_or_void_ptr_p (type, expr))
767     return false;
768
769   /* 10.4/3 An abstract class shall not be used as a parameter type,
770             as a function return type or as type of an explicit
771             conversion.  */
772   else if (CLASS_TYPE_P (type) && CLASSTYPE_PURE_VIRTUALS (type))
773     {
774       cp_error ("Expression '%E' of abstract class type '%T' cannot be used in throw-expression", expr, type);
775       return false;
776     }
777
778   return true;
779 }
780
781 /* Returns nonzero if FN is a declaration of a standard C library
782    function which is known not to throw.
783
784    [lib.res.on.exception.handling]: None of the functions from the
785    Standard C library shall report an error by throwing an
786    exception, unless it calls a program-supplied function that
787    throws an exception.  */
788
789 #include "cfns.h"
790
791 int
792 nothrow_libfn_p (fn)
793      tree fn;
794 {
795   tree id;
796
797   if (TREE_PUBLIC (fn)
798       && DECL_EXTERNAL (fn)
799       && DECL_NAMESPACE_SCOPE_P (fn)
800       && DECL_EXTERN_C_P (fn))
801     /* OK */;
802   else
803     /* Can't be a C library function.  */
804     return 0;
805
806   id = DECL_ASSEMBLER_NAME (fn);
807   return !!libc_name_p (IDENTIFIER_POINTER (id), IDENTIFIER_LENGTH (id));
808 }
809
810 /* Returns nonzero if an exception of type FROM will be caught by a
811    handler for type TO, as per [except.handle].  */
812
813 static int
814 can_convert_eh (to, from)
815      tree to, from;
816 {
817   if (TREE_CODE (to) == REFERENCE_TYPE)
818     to = TREE_TYPE (to);
819   if (TREE_CODE (from) == REFERENCE_TYPE)
820     from = TREE_TYPE (from);
821
822   if (TREE_CODE (to) == POINTER_TYPE && TREE_CODE (from) == POINTER_TYPE)
823     {
824       to = TREE_TYPE (to);
825       from = TREE_TYPE (from);
826
827       if (! at_least_as_qualified_p (to, from))
828         return 0;
829
830       if (TREE_CODE (to) == VOID_TYPE)
831         return 1;
832
833       /* else fall through */
834     }
835
836   if (CLASS_TYPE_P (to) && CLASS_TYPE_P (from)
837       && PUBLICLY_UNIQUELY_DERIVED_P (to, from))
838     return 1;
839
840   return 0;
841 }
842
843 /* Check whether any of HANDLERS are shadowed by another handler accepting
844    TYPE.  Note that the shadowing may not be complete; even if an exception
845    of type B would be caught by a handler for A, there could be a derived
846    class C for which A is an ambiguous base but B is not, so the handler
847    for B would catch an exception of type C.  */
848
849 static void
850 check_handlers_1 (master, handlers)
851      tree master;
852      tree handlers;
853 {
854   tree type = TREE_TYPE (master);
855   tree handler;
856
857   for (handler = handlers; handler; handler = TREE_CHAIN (handler))
858     if (TREE_TYPE (handler)
859         && can_convert_eh (type, TREE_TYPE (handler)))
860       {
861         lineno = STMT_LINENO (handler);
862         cp_warning ("exception of type `%T' will be caught",
863                     TREE_TYPE (handler));
864         lineno = STMT_LINENO (master);
865         cp_warning ("   by earlier handler for `%T'", type);
866         break;
867       }
868 }
869
870 /* Given a chain of HANDLERs, make sure that they're OK.  */
871
872 void
873 check_handlers (handlers)
874      tree handlers;
875 {
876   tree handler;
877   int save_line = lineno;
878   for (handler = handlers; handler; handler = TREE_CHAIN (handler))
879     {
880       if (TREE_CHAIN (handler) == NULL_TREE)
881         /* No more handlers; nothing to shadow.  */;
882       else if (TREE_TYPE (handler) == NULL_TREE)
883         {
884           lineno = STMT_LINENO (handler);
885           cp_pedwarn
886             ("`...' handler must be the last handler for its try block");
887         }
888       else
889         check_handlers_1 (handler, TREE_CHAIN (handler));
890     }
891   lineno = save_line;
892 }