OSDN Git Service

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