OSDN Git Service

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