except.c revision 110621
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
8This file is part of GNU CC.
9
10GNU CC is free software; you can redistribute it and/or modify
11it under the terms of the GNU General Public License as published by
12the Free Software Foundation; either version 2, or (at your option)
13any later version.
14
15GNU CC is distributed in the hope that it will be useful,
16but WITHOUT ANY WARRANTY; without even the implied warranty of
17MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18GNU General Public License for more details.
19
20You should have received a copy of the GNU General Public License
21along with GNU CC; see the file COPYING.  If not, write to
22the Free Software Foundation, 59 Temple Place - Suite 330,
23Boston, 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
39static void push_eh_cleanup PARAMS ((tree));
40static tree prepare_eh_type PARAMS ((tree));
41static tree build_eh_type_type PARAMS ((tree));
42static tree do_begin_catch PARAMS ((void));
43static int dtor_nothrow PARAMS ((tree));
44static tree do_end_catch PARAMS ((tree));
45static void push_eh_cleanup PARAMS ((tree));
46static bool decl_is_java_type PARAMS ((tree decl, int err));
47static void initialize_handler_parm PARAMS ((tree, tree));
48static tree do_allocate_exception PARAMS ((tree));
49static int complete_ptr_ref_or_void_ptr_p PARAMS ((tree, tree));
50static bool is_admissible_throw_operand PARAMS ((tree));
51static int can_convert_eh PARAMS ((tree, tree));
52static void check_handlers_1 PARAMS ((tree, tree));
53static 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
61void
62init_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
91static tree
92cp_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
101static tree
102prepare_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
123static tree
124build_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
143tree
144build_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
152static tree
153do_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
174static int
175dtor_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
194static tree
195do_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
219static void
220push_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
229static bool
230decl_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?  */
278void
279choose_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
333static void
334initialize_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
388tree
389expand_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
456void
457expand_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
470tree
471begin_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
478void
479finish_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
499static tree
500do_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, 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
523static tree
524do_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
545tree
546build_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
724static int
725complete_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
754static bool
755is_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
792int
793nothrow_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
814static int
815can_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
850static void
851check_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
873void
874check_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}
894