118334Speter/* Handle exceptional things in C++.
290289Sobrien   Copyright (C) 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
3169699Skan   2000, 2001, 2002, 2003, 2004, 2005  Free Software Foundation, Inc.
418334Speter   Contributed by Michael Tiemann <tiemann@cygnus.com>
518334Speter   Rewritten by Mike Stump <mrs@cygnus.com>, based upon an
618334Speter   initial re-implementation courtesy Tad Hunt.
718334Speter
8132727SkanThis file is part of GCC.
918334Speter
10132727SkanGCC is free software; you can redistribute it and/or modify
1118334Speterit under the terms of the GNU General Public License as published by
1218334Speterthe Free Software Foundation; either version 2, or (at your option)
1318334Speterany later version.
1418334Speter
15132727SkanGCC is distributed in the hope that it will be useful,
1618334Speterbut WITHOUT ANY WARRANTY; without even the implied warranty of
1718334SpeterMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1818334SpeterGNU General Public License for more details.
1918334Speter
2018334SpeterYou should have received a copy of the GNU General Public License
21132727Skanalong with GCC; see the file COPYING.  If not, write to
22169699Skanthe Free Software Foundation, 51 Franklin Street, Fifth Floor,
23169699SkanBoston, MA 02110-1301, USA.  */
2418334Speter
2518334Speter
2618334Speter#include "config.h"
2750643Sobrien#include "system.h"
28132727Skan#include "coretypes.h"
29132727Skan#include "tm.h"
3018334Speter#include "tree.h"
3118334Speter#include "rtl.h"
3290289Sobrien#include "expr.h"
3390289Sobrien#include "libfuncs.h"
3418334Speter#include "cp-tree.h"
3518334Speter#include "flags.h"
3650643Sobrien#include "output.h"
3750643Sobrien#include "except.h"
3850643Sobrien#include "toplev.h"
39117404Skan#include "tree-inline.h"
40169699Skan#include "tree-iterator.h"
41169699Skan#include "target.h"
4218334Speter
43132727Skanstatic void push_eh_cleanup (tree);
44132727Skanstatic tree prepare_eh_type (tree);
45132727Skanstatic tree build_eh_type_type (tree);
46132727Skanstatic tree do_begin_catch (void);
47132727Skanstatic int dtor_nothrow (tree);
48132727Skanstatic tree do_end_catch (tree);
49132727Skanstatic bool decl_is_java_type (tree decl, int err);
50132727Skanstatic void initialize_handler_parm (tree, tree);
51132727Skanstatic tree do_allocate_exception (tree);
52132727Skanstatic tree wrap_cleanups_r (tree *, int *, void *);
53132727Skanstatic int complete_ptr_ref_or_void_ptr_p (tree, tree);
54132727Skanstatic bool is_admissible_throw_operand (tree);
55132727Skanstatic int can_convert_eh (tree, tree);
56132727Skanstatic tree cp_protect_cleanup_actions (void);
5718334Speter
5890289Sobrien/* Sets up all the global eh stuff that needs to be initialized at the
5990289Sobrien   start of compilation.  */
6018334Speter
6118334Spetervoid
62132727Skaninit_exception_processing (void)
6318334Speter{
6490289Sobrien  tree tmp;
6518334Speter
6690289Sobrien  /* void std::terminate (); */
6790289Sobrien  push_namespace (std_identifier);
6890289Sobrien  tmp = build_function_type (void_type_node, void_list_node);
6990289Sobrien  terminate_node = build_cp_library_fn_ptr ("terminate", tmp);
7090289Sobrien  TREE_THIS_VOLATILE (terminate_node) = 1;
7190289Sobrien  TREE_NOTHROW (terminate_node) = 1;
7290289Sobrien  pop_namespace ();
7318334Speter
7490289Sobrien  /* void __cxa_call_unexpected(void *); */
7590289Sobrien  tmp = tree_cons (NULL_TREE, ptr_type_node, void_list_node);
7690289Sobrien  tmp = build_function_type (void_type_node, tmp);
7790289Sobrien  call_unexpected_node
7890289Sobrien    = push_throw_library_fn (get_identifier ("__cxa_call_unexpected"), tmp);
7918334Speter
8090289Sobrien  eh_personality_libfunc = init_one_libfunc (USING_SJLJ_EXCEPTIONS
8190289Sobrien					     ? "__gxx_personality_sj0"
8290289Sobrien					     : "__gxx_personality_v0");
83169699Skan  if (targetm.arm_eabi_unwinder)
84169699Skan    unwind_resume_libfunc = init_one_libfunc ("__cxa_end_cleanup");
85169699Skan  else
86169699Skan    default_init_unwind_resume_libfunc ();
8718334Speter
8890289Sobrien  lang_eh_runtime_type = build_eh_type_type;
8990289Sobrien  lang_protect_cleanup_actions = &cp_protect_cleanup_actions;
9018334Speter}
9118334Speter
9290289Sobrien/* Returns an expression to be executed if an unhandled exception is
9390289Sobrien   propagated out of a cleanup region.  */
9418334Speter
9550643Sobrienstatic tree
96132727Skancp_protect_cleanup_actions (void)
9718334Speter{
9890289Sobrien  /* [except.terminate]
9918334Speter
10090289Sobrien     When the destruction of an object during stack unwinding exits
10190289Sobrien     using an exception ... void terminate(); is called.  */
10290289Sobrien  return build_call (terminate_node, NULL_TREE);
103169699Skan}
10418334Speter
10550643Sobrienstatic tree
106132727Skanprepare_eh_type (tree type)
10718334Speter{
10890289Sobrien  if (type == NULL_TREE)
10990289Sobrien    return type;
11050643Sobrien  if (type == error_mark_node)
11150643Sobrien    return error_mark_node;
11218334Speter
11350643Sobrien  /* peel back references, so they match.  */
114132727Skan  type = non_reference (type);
11518334Speter
11650643Sobrien  /* Peel off cv qualifiers.  */
11750643Sobrien  type = TYPE_MAIN_VARIANT (type);
11818334Speter
11990289Sobrien  return type;
12018334Speter}
12118334Speter
122132727Skan/* Return the type info for TYPE as used by EH machinery.  */
123132727Skantree
124132727Skaneh_type_info (tree type)
12518334Speter{
12618334Speter  tree exp;
12718334Speter
12890289Sobrien  if (type == NULL_TREE || type == error_mark_node)
12990289Sobrien    return type;
13018334Speter
13190289Sobrien  if (decl_is_java_type (type, 0))
13290289Sobrien    exp = build_java_class_ref (TREE_TYPE (type));
13390289Sobrien  else
13490289Sobrien    exp = get_tinfo_decl (type);
13518334Speter
136132727Skan  return exp;
137132727Skan}
138132727Skan
139132727Skan/* Build the address of a typeinfo decl for use in the runtime
140132727Skan   matching field of the exception model.  */
141132727Skan
142132727Skanstatic tree
143132727Skanbuild_eh_type_type (tree type)
144132727Skan{
145132727Skan  tree exp = eh_type_info (type);
146132727Skan
147132727Skan  if (!exp)
148132727Skan    return NULL;
149132727Skan
15090289Sobrien  mark_used (exp);
15118334Speter
152169699Skan  return convert (ptr_type_node, build_address (exp));
15390289Sobrien}
15450643Sobrien
15590289Sobrientree
156132727Skanbuild_exc_ptr (void)
15790289Sobrien{
158169699Skan  return build0 (EXC_PTR_EXPR, ptr_type_node);
15918334Speter}
16018334Speter
161169699Skan/* Build up a call to __cxa_get_exception_ptr so that we can build a
162169699Skan   copy constructor for the thrown object.  */
163169699Skan
164169699Skanstatic tree
165169699Skando_get_exception_ptr (void)
166169699Skan{
167169699Skan  tree fn;
168169699Skan
169169699Skan  fn = get_identifier ("__cxa_get_exception_ptr");
170169699Skan  if (!get_global_value_if_present (fn, &fn))
171169699Skan    {
172169699Skan      /* Declare void* __cxa_get_exception_ptr (void *).  */
173169699Skan      tree tmp = tree_cons (NULL_TREE, ptr_type_node, void_list_node);
174169699Skan      fn = push_library_fn (fn, build_function_type (ptr_type_node, tmp));
175169699Skan    }
176169699Skan
177169699Skan  return build_function_call (fn, tree_cons (NULL_TREE, build_exc_ptr (),
178169699Skan					     NULL_TREE));
179169699Skan}
180169699Skan
18190289Sobrien/* Build up a call to __cxa_begin_catch, to tell the runtime that the
18290289Sobrien   exception has been handled.  */
18350643Sobrien
18418334Speterstatic tree
185132727Skando_begin_catch (void)
18618334Speter{
18790289Sobrien  tree fn;
18890289Sobrien
18990289Sobrien  fn = get_identifier ("__cxa_begin_catch");
190132727Skan  if (!get_global_value_if_present (fn, &fn))
19118334Speter    {
19290289Sobrien      /* Declare void* __cxa_begin_catch (void *).  */
19390289Sobrien      tree tmp = tree_cons (NULL_TREE, ptr_type_node, void_list_node);
19490289Sobrien      fn = push_library_fn (fn, build_function_type (ptr_type_node, tmp));
19518334Speter    }
19690289Sobrien
19790289Sobrien  return build_function_call (fn, tree_cons (NULL_TREE, build_exc_ptr (),
19890289Sobrien					     NULL_TREE));
19918334Speter}
20018334Speter
20190289Sobrien/* Returns nonzero if cleaning up an exception of type TYPE (which can be
20290289Sobrien   NULL_TREE for a ... handler) will not throw an exception.  */
20390289Sobrien
20490289Sobrienstatic int
205132727Skandtor_nothrow (tree type)
20650643Sobrien{
20790289Sobrien  if (type == NULL_TREE)
20890289Sobrien    return 0;
20990289Sobrien
210169699Skan  if (!CLASS_TYPE_P (type))
21190289Sobrien    return 1;
21290289Sobrien
213169699Skan  if (CLASSTYPE_LAZY_DESTRUCTOR (type))
214169699Skan    lazily_declare_fn (sfk_destructor, type);
215169699Skan
216117404Skan  return TREE_NOTHROW (CLASSTYPE_DESTRUCTORS (type));
21750643Sobrien}
21850643Sobrien
21990289Sobrien/* Build up a call to __cxa_end_catch, to destroy the exception object
22090289Sobrien   for the current catch block if no others are currently using it.  */
22150643Sobrien
22250643Sobrienstatic tree
223132727Skando_end_catch (tree type)
22450643Sobrien{
22550643Sobrien  tree fn, cleanup;
22690289Sobrien
22790289Sobrien  fn = get_identifier ("__cxa_end_catch");
228132727Skan  if (!get_global_value_if_present (fn, &fn))
22950643Sobrien    {
23090289Sobrien      /* Declare void __cxa_end_catch ().  */
23190289Sobrien      fn = push_void_library_fn (fn, void_list_node);
23290289Sobrien      /* This can throw if the destructor for the exception throws.  */
23390289Sobrien      TREE_NOTHROW (fn) = 0;
23450643Sobrien    }
23550643Sobrien
23690289Sobrien  cleanup = build_function_call (fn, NULL_TREE);
23790289Sobrien  TREE_NOTHROW (cleanup) = dtor_nothrow (type);
23890289Sobrien
23950643Sobrien  return cleanup;
24050643Sobrien}
24150643Sobrien
24250643Sobrien/* This routine creates the cleanup for the current exception.  */
24350643Sobrien
24450643Sobrienstatic void
245132727Skanpush_eh_cleanup (tree type)
24650643Sobrien{
24790289Sobrien  finish_decl_cleanup (NULL_TREE, do_end_catch (type));
24850643Sobrien}
24950643Sobrien
25090289Sobrien/* Return nonzero value if DECL is a Java type suitable for catch or
25190289Sobrien   throw.  */
25250643Sobrien
25390289Sobrienstatic bool
254132727Skandecl_is_java_type (tree decl, int err)
25550643Sobrien{
25690289Sobrien  bool r = (TREE_CODE (decl) == POINTER_TYPE
25790289Sobrien	    && TREE_CODE (TREE_TYPE (decl)) == RECORD_TYPE
25890289Sobrien	    && TYPE_FOR_JAVA (TREE_TYPE (decl)));
25990289Sobrien
26090289Sobrien  if (err)
26190289Sobrien    {
26290289Sobrien      if (TREE_CODE (decl) == REFERENCE_TYPE
26390289Sobrien	  && TREE_CODE (TREE_TYPE (decl)) == RECORD_TYPE
26490289Sobrien	  && TYPE_FOR_JAVA (TREE_TYPE (decl)))
26590289Sobrien	{
26690289Sobrien	  /* Can't throw a reference.  */
267169699Skan	  error ("type %qT is disallowed in Java %<throw%> or %<catch%>",
268169699Skan		 decl);
26990289Sobrien	}
27090289Sobrien
27190289Sobrien      if (r)
27290289Sobrien	{
27390289Sobrien	  tree jthrow_node
27490289Sobrien	    = IDENTIFIER_GLOBAL_VALUE (get_identifier ("jthrowable"));
27590289Sobrien
27690289Sobrien	  if (jthrow_node == NULL_TREE)
27790289Sobrien	    fatal_error
278169699Skan	      ("call to Java %<catch%> or %<throw%> with %<jthrowable%> undefined");
27990289Sobrien
28090289Sobrien	  jthrow_node = TREE_TYPE (TREE_TYPE (jthrow_node));
28190289Sobrien
28290289Sobrien	  if (! DERIVED_FROM_P (jthrow_node, TREE_TYPE (decl)))
28390289Sobrien	    {
28490289Sobrien	      /* Thrown object must be a Throwable.  */
285169699Skan	      error ("type %qT is not derived from %<java::lang::Throwable%>",
286169699Skan		     TREE_TYPE (decl));
28790289Sobrien	    }
28890289Sobrien	}
28990289Sobrien    }
29090289Sobrien
29190289Sobrien  return r;
29250643Sobrien}
29350643Sobrien
29490289Sobrien/* Select the personality routine to be used for exception handling,
29590289Sobrien   or issue an error if we need two different ones in the same
29690289Sobrien   translation unit.
29790289Sobrien   ??? At present eh_personality_libfunc is set to
29890289Sobrien   __gxx_personality_(sj|v)0 in init_exception_processing - should it
29990289Sobrien   be done here instead?  */
30018334Spetervoid
301132727Skanchoose_personality_routine (enum languages lang)
30218334Speter{
30390289Sobrien  static enum {
30490289Sobrien    chose_none,
30590289Sobrien    chose_cpp,
30690289Sobrien    chose_java,
30790289Sobrien    gave_error
30890289Sobrien  } state;
30950643Sobrien
31090289Sobrien  switch (state)
31150643Sobrien    {
31290289Sobrien    case gave_error:
31350643Sobrien      return;
31490289Sobrien
31590289Sobrien    case chose_cpp:
31690289Sobrien      if (lang != lang_cplusplus)
31790289Sobrien	goto give_error;
31890289Sobrien      return;
31990289Sobrien
32090289Sobrien    case chose_java:
32190289Sobrien      if (lang != lang_java)
32290289Sobrien	goto give_error;
32390289Sobrien      return;
32490289Sobrien
32590289Sobrien    case chose_none:
326132727Skan      ; /* Proceed to language selection.  */
32750643Sobrien    }
32850643Sobrien
32990289Sobrien  switch (lang)
33090289Sobrien    {
33190289Sobrien    case lang_cplusplus:
33290289Sobrien      state = chose_cpp;
33390289Sobrien      break;
33450643Sobrien
33590289Sobrien    case lang_java:
33690289Sobrien      state = chose_java;
33790289Sobrien      eh_personality_libfunc = init_one_libfunc (USING_SJLJ_EXCEPTIONS
33890289Sobrien						 ? "__gcj_personality_sj0"
33990289Sobrien						 : "__gcj_personality_v0");
34090289Sobrien      break;
34190289Sobrien
34290289Sobrien    default:
343169699Skan      gcc_unreachable ();
34490289Sobrien    }
34590289Sobrien  return;
34690289Sobrien
34790289Sobrien give_error:
34890289Sobrien  error ("mixing C++ and Java catches in a single translation unit");
34990289Sobrien  state = gave_error;
35050643Sobrien}
35150643Sobrien
35290289Sobrien/* Initialize the catch parameter DECL.  */
35350643Sobrien
354169699Skanstatic void
355132727Skaninitialize_handler_parm (tree decl, tree exp)
35618334Speter{
35750643Sobrien  tree init;
35890289Sobrien  tree init_type;
35918334Speter
36090289Sobrien  /* Make sure we mark the catch param as used, otherwise we'll get a
36190289Sobrien     warning about an unused ((anonymous)).  */
36290289Sobrien  TREE_USED (decl) = 1;
36318334Speter
36490289Sobrien  /* Figure out the type that the initializer is.  Pointers are returned
365169699Skan     adjusted by value from __cxa_begin_catch.  Others are returned by
36690289Sobrien     reference.  */
36790289Sobrien  init_type = TREE_TYPE (decl);
368169699Skan  if (!POINTER_TYPE_P (init_type))
36990289Sobrien    init_type = build_reference_type (init_type);
37018334Speter
37190289Sobrien  choose_personality_routine (decl_is_java_type (init_type, 0)
37290289Sobrien			      ? lang_java : lang_cplusplus);
37318334Speter
37490289Sobrien  /* Since pointers are passed by value, initialize a reference to
37590289Sobrien     pointer catch parm with the address of the temporary.  */
37690289Sobrien  if (TREE_CODE (init_type) == REFERENCE_TYPE
37790289Sobrien      && TYPE_PTR_P (TREE_TYPE (init_type)))
37890289Sobrien    exp = build_unary_op (ADDR_EXPR, exp, 1);
37918334Speter
38090289Sobrien  exp = ocp_convert (init_type, exp, CONV_IMPLICIT|CONV_FORCE_TEMP, 0);
38118334Speter
38290289Sobrien  init = convert_from_reference (exp);
38318334Speter
38490289Sobrien  /* If the constructor for the catch parm exits via an exception, we
38590289Sobrien     must call terminate.  See eh23.C.  */
38690289Sobrien  if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl)))
38750643Sobrien    {
38890289Sobrien      /* Generate the copy constructor call directly so we can wrap it.
38990289Sobrien	 See also expand_default_init.  */
39090289Sobrien      init = ocp_convert (TREE_TYPE (decl), init,
39190289Sobrien			  CONV_IMPLICIT|CONV_FORCE_TEMP, 0);
39290289Sobrien      init = build1 (MUST_NOT_THROW_EXPR, TREE_TYPE (init), init);
39390289Sobrien    }
39418334Speter
39590289Sobrien  decl = pushdecl (decl);
39618334Speter
397169699Skan  start_decl_1 (decl, true);
398169699Skan  cp_finish_decl (decl, init, /*init_const_expr_p=*/false, NULL_TREE,
39990289Sobrien		  LOOKUP_ONLYCONVERTING|DIRECT_BIND);
40090289Sobrien}
40118334Speter
40290289Sobrien/* Call this to start a catch block.  DECL is the catch parameter.  */
40318334Speter
40490289Sobrientree
405132727Skanexpand_start_catch_block (tree decl)
40690289Sobrien{
407169699Skan  tree exp;
40890289Sobrien  tree type;
40918334Speter
41090289Sobrien  if (! doing_eh (1))
41190289Sobrien    return NULL_TREE;
41218334Speter
41390289Sobrien  /* Make sure this declaration is reasonable.  */
41490289Sobrien  if (decl && !complete_ptr_ref_or_void_ptr_p (TREE_TYPE (decl), NULL_TREE))
415169699Skan    decl = error_mark_node;
41618334Speter
41790289Sobrien  if (decl)
41890289Sobrien    type = prepare_eh_type (TREE_TYPE (decl));
41990289Sobrien  else
42090289Sobrien    type = NULL_TREE;
42118334Speter
422169699Skan  if (decl && decl_is_java_type (type, 1))
42390289Sobrien    {
424169699Skan      /* Java only passes object via pointer and doesn't require
425169699Skan	 adjusting.  The java object is immediately before the
426169699Skan	 generic exception header.  */
427169699Skan      exp = build_exc_ptr ();
428169699Skan      exp = build1 (NOP_EXPR, build_pointer_type (type), exp);
429169699Skan      exp = build2 (MINUS_EXPR, TREE_TYPE (exp), exp,
430169699Skan		    TYPE_SIZE_UNIT (TREE_TYPE (exp)));
431169699Skan      exp = build_indirect_ref (exp, NULL);
432169699Skan      initialize_handler_parm (decl, exp);
433169699Skan      return type;
434169699Skan    }
43518334Speter
436169699Skan  /* Call __cxa_end_catch at the end of processing the exception.  */
437169699Skan  push_eh_cleanup (type);
438169699Skan
439169699Skan  /* If there's no decl at all, then all we need to do is make sure
440169699Skan     to tell the runtime that we've begun handling the exception.  */
441169699Skan  if (decl == NULL || decl == error_mark_node)
442169699Skan    finish_expr_stmt (do_begin_catch ());
443169699Skan
444169699Skan  /* If the C++ object needs constructing, we need to do that before
445169699Skan     calling __cxa_begin_catch, so that std::uncaught_exception gets
446169699Skan     the right value during the copy constructor.  */
447169699Skan  else if (flag_use_cxa_get_exception_ptr
448169699Skan	   && TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl)))
449169699Skan    {
450169699Skan      exp = do_get_exception_ptr ();
451169699Skan      initialize_handler_parm (decl, exp);
452169699Skan      finish_expr_stmt (do_begin_catch ());
45350643Sobrien    }
454169699Skan
455169699Skan  /* Otherwise the type uses a bitwise copy, and we don't have to worry
456169699Skan     about the value of std::uncaught_exception and therefore can do the
457169699Skan     copy with the return value of __cxa_end_catch instead.  */
45850643Sobrien  else
459169699Skan    {
460169699Skan      tree init = do_begin_catch ();
461169699Skan      tree init_type = type;
46218334Speter
463169699Skan      /* Pointers are passed by values, everything else by reference.  */
464169699Skan      if (!TYPE_PTR_P (type))
465169699Skan	init_type = build_pointer_type (type);
466169699Skan      if (init_type != TREE_TYPE (init))
467169699Skan	init = build1 (NOP_EXPR, init_type, init);
468169699Skan      exp = create_temporary_var (init_type);
469169699Skan      DECL_REGISTER (exp) = 1;
470169699Skan      cp_finish_decl (exp, init, /*init_const_expr=*/false,
471169699Skan		      NULL_TREE, LOOKUP_ONLYCONVERTING);
472169699Skan      initialize_handler_parm (decl, exp);
473169699Skan    }
47418334Speter
47590289Sobrien  return type;
47618334Speter}
47718334Speter
47818334Speter
47950643Sobrien/* Call this to end a catch block.  Its responsible for emitting the
48050643Sobrien   code to handle jumping back to the correct place, and for emitting
48150643Sobrien   the label to jump to if this catch block didn't match.  */
48218334Speter
48318334Spetervoid
484132727Skanexpand_end_catch_block (void)
48518334Speter{
48650643Sobrien  if (! doing_eh (1))
48718334Speter    return;
48818334Speter
48990289Sobrien  /* The exception being handled is rethrown if control reaches the end of
49090289Sobrien     a handler of the function-try-block of a constructor or destructor.  */
49190289Sobrien  if (in_function_try_handler
49290289Sobrien      && (DECL_CONSTRUCTOR_P (current_function_decl)
49390289Sobrien	  || DECL_DESTRUCTOR_P (current_function_decl)))
49490289Sobrien    finish_expr_stmt (build_throw (NULL_TREE));
49590289Sobrien}
49618334Speter
49790289Sobrientree
498132727Skanbegin_eh_spec_block (void)
49990289Sobrien{
50090289Sobrien  tree r = build_stmt (EH_SPEC_BLOCK, NULL_TREE, NULL_TREE);
50190289Sobrien  add_stmt (r);
502169699Skan  EH_SPEC_STMTS (r) = push_stmt_list ();
50390289Sobrien  return r;
50450643Sobrien}
50518334Speter
50690289Sobrienvoid
507132727Skanfinish_eh_spec_block (tree raw_raises, tree eh_spec_block)
50890289Sobrien{
50990289Sobrien  tree raises;
51018334Speter
511169699Skan  EH_SPEC_STMTS (eh_spec_block) = pop_stmt_list (EH_SPEC_STMTS (eh_spec_block));
51218334Speter
51390289Sobrien  /* Strip cv quals, etc, from the specification types.  */
51490289Sobrien  for (raises = NULL_TREE;
51590289Sobrien       raw_raises && TREE_VALUE (raw_raises);
51690289Sobrien       raw_raises = TREE_CHAIN (raw_raises))
517132727Skan    {
518132727Skan      tree type = prepare_eh_type (TREE_VALUE (raw_raises));
519132727Skan      tree tinfo = eh_type_info (type);
52018334Speter
521132727Skan      mark_used (tinfo);
522132727Skan      raises = tree_cons (NULL_TREE, type, raises);
523132727Skan    }
524132727Skan
52590289Sobrien  EH_SPEC_RAISES (eh_spec_block) = raises;
52618334Speter}
52718334Speter
52890289Sobrien/* Return a pointer to a buffer for an exception object of type TYPE.  */
52990289Sobrien
53090289Sobrienstatic tree
531132727Skando_allocate_exception (tree type)
53218334Speter{
53390289Sobrien  tree fn;
53418334Speter
53590289Sobrien  fn = get_identifier ("__cxa_allocate_exception");
536132727Skan  if (!get_global_value_if_present (fn, &fn))
53750643Sobrien    {
53890289Sobrien      /* Declare void *__cxa_allocate_exception(size_t).  */
539110621Skan      tree tmp = tree_cons (NULL_TREE, size_type_node, void_list_node);
54090289Sobrien      fn = push_library_fn (fn, build_function_type (ptr_type_node, tmp));
54150643Sobrien    }
542169699Skan
54390289Sobrien  return build_function_call (fn, tree_cons (NULL_TREE, size_in_bytes (type),
54490289Sobrien					     NULL_TREE));
54590289Sobrien}
54618334Speter
54790289Sobrien/* Call __cxa_free_exception from a cleanup.  This is never invoked
548117404Skan   directly, but see the comment for stabilize_throw_expr.  */
54950643Sobrien
55090289Sobrienstatic tree
551132727Skando_free_exception (tree ptr)
55290289Sobrien{
55390289Sobrien  tree fn;
55450643Sobrien
55590289Sobrien  fn = get_identifier ("__cxa_free_exception");
556132727Skan  if (!get_global_value_if_present (fn, &fn))
55718334Speter    {
55890289Sobrien      /* Declare void __cxa_free_exception (void *).  */
55990289Sobrien      fn = push_void_library_fn (fn, tree_cons (NULL_TREE, ptr_type_node,
56090289Sobrien						void_list_node));
56150643Sobrien    }
56218334Speter
56390289Sobrien  return build_function_call (fn, tree_cons (NULL_TREE, ptr, NULL_TREE));
56418334Speter}
56518334Speter
566117404Skan/* Wrap all cleanups for TARGET_EXPRs in MUST_NOT_THROW_EXPR.
567117404Skan   Called from build_throw via walk_tree_without_duplicates.  */
568117404Skan
569117404Skanstatic tree
570132727Skanwrap_cleanups_r (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED,
571169699Skan		 void *data ATTRIBUTE_UNUSED)
572117404Skan{
573117404Skan  tree exp = *tp;
574117404Skan  tree cleanup;
575117404Skan
576117404Skan  /* Don't walk into types.  */
577117404Skan  if (TYPE_P (exp))
578117404Skan    {
579117404Skan      *walk_subtrees = 0;
580117404Skan      return NULL_TREE;
581117404Skan    }
582117404Skan  if (TREE_CODE (exp) != TARGET_EXPR)
583117404Skan    return NULL_TREE;
584117404Skan
585117404Skan  cleanup = TARGET_EXPR_CLEANUP (exp);
586117404Skan  if (cleanup)
587117404Skan    {
588132727Skan      cleanup = build1 (MUST_NOT_THROW_EXPR, void_type_node, cleanup);
589117404Skan      TARGET_EXPR_CLEANUP (exp) = cleanup;
590117404Skan    }
591117404Skan
592117404Skan  /* Keep iterating.  */
593117404Skan  return NULL_TREE;
594117404Skan}
595117404Skan
59690289Sobrien/* Build a throw expression.  */
59750643Sobrien
59890289Sobrientree
599132727Skanbuild_throw (tree exp)
60018334Speter{
60190289Sobrien  tree fn;
60218334Speter
60390289Sobrien  if (exp == error_mark_node)
60490289Sobrien    return exp;
60590289Sobrien
60690289Sobrien  if (processing_template_decl)
607132727Skan    {
608169699Skan      if (cfun)
609169699Skan	current_function_returns_abnormally = 1;
610132727Skan      return build_min (THROW_EXPR, void_type_node, exp);
611132727Skan    }
61290289Sobrien
61390289Sobrien  if (exp == null_node)
614169699Skan    warning (0, "throwing NULL, which has integral, not pointer type");
615169699Skan
61690289Sobrien  if (exp != NULL_TREE)
61750643Sobrien    {
61890289Sobrien      if (!is_admissible_throw_operand (exp))
619169699Skan	return error_mark_node;
62050643Sobrien    }
62118334Speter
62290289Sobrien  if (! doing_eh (1))
62390289Sobrien    return error_mark_node;
62490289Sobrien
62590289Sobrien  if (exp && decl_is_java_type (TREE_TYPE (exp), 1))
62650643Sobrien    {
62790289Sobrien      tree fn = get_identifier ("_Jv_Throw");
628132727Skan      if (!get_global_value_if_present (fn, &fn))
62990289Sobrien	{
63090289Sobrien	  /* Declare void _Jv_Throw (void *).  */
63190289Sobrien	  tree tmp = tree_cons (NULL_TREE, ptr_type_node, void_list_node);
63290289Sobrien	  tmp = build_function_type (ptr_type_node, tmp);
63390289Sobrien	  fn = push_throw_library_fn (fn, tmp);
63490289Sobrien	}
635132727Skan      else if (really_overloaded_fn (fn))
636146906Skan	{
637169699Skan	  error ("%qD should never be overloaded", fn);
638146906Skan	  return error_mark_node;
639132727Skan	}
640132727Skan      fn = OVL_CURRENT (fn);
64190289Sobrien      exp = build_function_call (fn, tree_cons (NULL_TREE, exp, NULL_TREE));
64290289Sobrien    }
64390289Sobrien  else if (exp)
64490289Sobrien    {
64590289Sobrien      tree throw_type;
646169699Skan      tree temp_type;
64790289Sobrien      tree cleanup;
64890289Sobrien      tree object, ptr;
64990289Sobrien      tree tmp;
650117404Skan      tree temp_expr, allocate_expr;
651132727Skan      bool elided;
65218334Speter
653146906Skan      /* The CLEANUP_TYPE is the internal type of a destructor.  */
654146906Skan      if (!cleanup_type)
655146906Skan	{
656146906Skan	  tmp = void_list_node;
657146906Skan	  tmp = tree_cons (NULL_TREE, ptr_type_node, tmp);
658146906Skan	  tmp = build_function_type (void_type_node, tmp);
659146906Skan	  cleanup_type = build_pointer_type (tmp);
660146906Skan	}
661169699Skan
66290289Sobrien      fn = get_identifier ("__cxa_throw");
663132727Skan      if (!get_global_value_if_present (fn, &fn))
66490289Sobrien	{
66590289Sobrien	  /* Declare void __cxa_throw (void*, void*, void (*)(void*)).  */
66690289Sobrien	  /* ??? Second argument is supposed to be "std::type_info*".  */
66790289Sobrien	  tmp = void_list_node;
66890289Sobrien	  tmp = tree_cons (NULL_TREE, cleanup_type, tmp);
66990289Sobrien	  tmp = tree_cons (NULL_TREE, ptr_type_node, tmp);
67090289Sobrien	  tmp = tree_cons (NULL_TREE, ptr_type_node, tmp);
67190289Sobrien	  tmp = build_function_type (void_type_node, tmp);
67290289Sobrien	  fn = push_throw_library_fn (fn, tmp);
67390289Sobrien	}
67418334Speter
675169699Skan      /* [except.throw]
676169699Skan
677169699Skan	 A throw-expression initializes a temporary object, the type
678169699Skan	 of which is determined by removing any top-level
679169699Skan	 cv-qualifiers from the static type of the operand of throw
680169699Skan	 and adjusting the type from "array of T" or "function return
681169699Skan	 T" to "pointer to T" or "pointer to function returning T"
682169699Skan	 respectively.  */
683169699Skan      temp_type = is_bitfield_expr_with_lowered_type (exp);
684169699Skan      if (!temp_type)
685169699Skan	temp_type = type_decays_to (TYPE_MAIN_VARIANT (TREE_TYPE (exp)));
686169699Skan
68790289Sobrien      /* OK, this is kind of wacky.  The standard says that we call
68890289Sobrien	 terminate when the exception handling mechanism, after
68990289Sobrien	 completing evaluation of the expression to be thrown but
69090289Sobrien	 before the exception is caught (_except.throw_), calls a
69190289Sobrien	 user function that exits via an uncaught exception.
69218334Speter
69390289Sobrien	 So we have to protect the actual initialization of the
69490289Sobrien	 exception object with terminate(), but evaluate the
69590289Sobrien	 expression first.  Since there could be temps in the
69690289Sobrien	 expression, we need to handle that, too.  We also expand
69790289Sobrien	 the call to __cxa_allocate_exception first (which doesn't
69890289Sobrien	 matter, since it can't throw).  */
69918334Speter
70090289Sobrien      /* Allocate the space for the exception.  */
701169699Skan      allocate_expr = do_allocate_exception (temp_type);
702117404Skan      allocate_expr = get_target_expr (allocate_expr);
703117404Skan      ptr = TARGET_EXPR_SLOT (allocate_expr);
704169699Skan      object = build_nop (build_pointer_type (temp_type), ptr);
70590289Sobrien      object = build_indirect_ref (object, NULL);
70618334Speter
707132727Skan      elided = (TREE_CODE (exp) == TARGET_EXPR);
708132727Skan
709117404Skan      /* And initialize the exception object.  */
710169699Skan      if (CLASS_TYPE_P (temp_type))
711117404Skan	{
712169699Skan	  /* Call the copy constructor.  */
713169699Skan	  exp = (build_special_member_call
714169699Skan		 (object, complete_ctor_identifier,
715169699Skan		  build_tree_list (NULL_TREE, exp),
716169699Skan		  TREE_TYPE (object),
717259660Spfg		  LOOKUP_NORMAL | LOOKUP_ONLYCONVERTING));
718169699Skan	  if (exp == error_mark_node)
719169699Skan	    {
720169699Skan	      error ("  in thrown expression");
721169699Skan	      return error_mark_node;
722169699Skan	    }
723117404Skan	}
724169699Skan      else
725169699Skan	exp = build2 (INIT_EXPR, temp_type, object,
726169699Skan		      decay_conversion (exp));
72718334Speter
728132727Skan      /* Pre-evaluate the thrown expression first, since if we allocated
729132727Skan	 the space first we would have to deal with cleaning it up if
730132727Skan	 evaluating this expression throws.
731132727Skan
732169699Skan	 The case where EXP the initializer is a cast or a function
733169699Skan	 returning a class is a bit of a grey area in the standard; it's
734169699Skan	 unclear whether or not it should be allowed to throw.  We used to
735169699Skan	 say no, as that allowed us to optimize this case without worrying
736169699Skan	 about deallocating the exception object if it does.  But that
737169699Skan	 conflicted with expectations (PR 13944) and the EDG compiler; now
738169699Skan	 we wrap the initialization in a TRY_CATCH_EXPR to call
739169699Skan	 do_free_exception rather than in a MUST_NOT_THROW_EXPR, for this
740169699Skan	 case only.
741132727Skan
742169699Skan	 BUT: Issue 475 may do away with this inconsistency by removing the
743169699Skan	 terminate() in this situation.
744169699Skan
745169699Skan	 Note that we don't check the return value from stabilize_init
746169699Skan	 because it will only return false in cases where elided is true,
747169699Skan	 and therefore we don't need to work around the failure to
748169699Skan	 preevaluate.  */
749132727Skan      temp_expr = NULL_TREE;
750132727Skan      stabilize_init (exp, &temp_expr);
751132727Skan
752169699Skan      /* Wrap the initialization in a CLEANUP_POINT_EXPR so that cleanups
753169699Skan	 for temporaries within the initialization are run before the one
754169699Skan	 for the exception object, preserving LIFO order.  */
755169699Skan      exp = build1 (CLEANUP_POINT_EXPR, void_type_node, exp);
756169699Skan
757132727Skan      if (elided)
758169699Skan	exp = build2 (TRY_CATCH_EXPR, void_type_node, exp,
759169699Skan		      do_free_exception (ptr));
760132727Skan      else
761132727Skan	exp = build1 (MUST_NOT_THROW_EXPR, void_type_node, exp);
762132727Skan
763117404Skan      /* Prepend the allocation.  */
764169699Skan      exp = build2 (COMPOUND_EXPR, TREE_TYPE (exp), allocate_expr, exp);
765132727Skan      if (temp_expr)
766117404Skan	{
767117404Skan	  /* Prepend the calculation of the throw expression.  Also, force
768117404Skan	     any cleanups from the expression to be evaluated here so that
769117404Skan	     we don't have to do them during unwinding.  But first wrap
770117404Skan	     them in MUST_NOT_THROW_EXPR, since they are run after the
771117404Skan	     exception object is initialized.  */
772117404Skan	  walk_tree_without_duplicates (&temp_expr, wrap_cleanups_r, 0);
773169699Skan	  exp = build2 (COMPOUND_EXPR, TREE_TYPE (exp), temp_expr, exp);
774117404Skan	  exp = build1 (CLEANUP_POINT_EXPR, TREE_TYPE (exp), exp);
775117404Skan	}
77618334Speter
77790289Sobrien      throw_type = build_eh_type_type (prepare_eh_type (TREE_TYPE (object)));
77818334Speter
779169699Skan      if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (object)))
78090289Sobrien	{
78190289Sobrien	  cleanup = lookup_fnfields (TYPE_BINFO (TREE_TYPE (object)),
78290289Sobrien				     complete_dtor_identifier, 0);
783117404Skan	  cleanup = BASELINK_FUNCTIONS (cleanup);
78490289Sobrien	  mark_used (cleanup);
785117404Skan	  cxx_mark_addressable (cleanup);
78690289Sobrien	  /* Pretend it's a normal function.  */
78790289Sobrien	  cleanup = build1 (ADDR_EXPR, cleanup_type, cleanup);
78890289Sobrien	}
78990289Sobrien      else
790169699Skan	cleanup = build_int_cst (cleanup_type, 0);
79150643Sobrien
79290289Sobrien      tmp = tree_cons (NULL_TREE, cleanup, NULL_TREE);
79390289Sobrien      tmp = tree_cons (NULL_TREE, throw_type, tmp);
79490289Sobrien      tmp = tree_cons (NULL_TREE, ptr, tmp);
795117404Skan      /* ??? Indicate that this function call throws throw_type.  */
79690289Sobrien      tmp = build_function_call (fn, tmp);
79718334Speter
798117404Skan      /* Tack on the initialization stuff.  */
799169699Skan      exp = build2 (COMPOUND_EXPR, TREE_TYPE (tmp), exp, tmp);
80090289Sobrien    }
80150643Sobrien  else
80250643Sobrien    {
80390289Sobrien      /* Rethrow current exception.  */
80490289Sobrien
80590289Sobrien      tree fn = get_identifier ("__cxa_rethrow");
806132727Skan      if (!get_global_value_if_present (fn, &fn))
80790289Sobrien	{
80890289Sobrien	  /* Declare void __cxa_rethrow (void).  */
80990289Sobrien	  fn = push_throw_library_fn
81090289Sobrien	    (fn, build_function_type (void_type_node, void_list_node));
81190289Sobrien	}
81290289Sobrien
813117404Skan      /* ??? Indicate that this function call allows exceptions of the type
814169699Skan	 of the enclosing catch block (if known).  */
81590289Sobrien      exp = build_function_call (fn, NULL_TREE);
81650643Sobrien    }
81750643Sobrien
81890289Sobrien  exp = build1 (THROW_EXPR, void_type_node, exp);
81990289Sobrien
82050643Sobrien  return exp;
82150643Sobrien}
82250643Sobrien
82390289Sobrien/* Make sure TYPE is complete, pointer to complete, reference to
82490289Sobrien   complete, or pointer to cv void. Issue diagnostic on failure.
825117404Skan   Return the zero on failure and nonzero on success. FROM can be
82690289Sobrien   the expr or decl from whence TYPE came, if available.  */
82718334Speter
82890289Sobrienstatic int
829132727Skancomplete_ptr_ref_or_void_ptr_p (tree type, tree from)
83090289Sobrien{
83190289Sobrien  int is_ptr;
832169699Skan
83390289Sobrien  /* Check complete.  */
83490289Sobrien  type = complete_type_or_else (type, from);
83590289Sobrien  if (!type)
83690289Sobrien    return 0;
837169699Skan
83890289Sobrien  /* Or a pointer or ref to one, or cv void *.  */
83990289Sobrien  is_ptr = TREE_CODE (type) == POINTER_TYPE;
84090289Sobrien  if (is_ptr || TREE_CODE (type) == REFERENCE_TYPE)
84190289Sobrien    {
84290289Sobrien      tree core = TREE_TYPE (type);
843169699Skan
84490289Sobrien      if (is_ptr && VOID_TYPE_P (core))
845169699Skan	/* OK */;
84690289Sobrien      else if (!complete_type_or_else (core, from))
847169699Skan	return 0;
84890289Sobrien    }
84990289Sobrien  return 1;
85090289Sobrien}
85150643Sobrien
85290289Sobrien/* Return truth-value if EXPRESSION is admissible in throw-expression,
85390289Sobrien   i.e. if it is not of incomplete type or a pointer/reference to such
85490289Sobrien   a type or of an abstract class type.  */
85590289Sobrien
85690289Sobrienstatic bool
857132727Skanis_admissible_throw_operand (tree expr)
85818334Speter{
85990289Sobrien  tree type = TREE_TYPE (expr);
86018334Speter
86190289Sobrien  /* 15.1/4 [...] The type of the throw-expression shall not be an
862169699Skan	    incomplete type, or a pointer or a reference to an incomplete
863169699Skan	    type, other than void*, const void*, volatile void*, or
864169699Skan	    const volatile void*.  Except for these restriction and the
865169699Skan	    restrictions on type matching mentioned in 15.3, the operand
866169699Skan	    of throw is treated exactly as a function argument in a call
867169699Skan	    (5.2.2) or the operand of a return statement.  */
86890289Sobrien  if (!complete_ptr_ref_or_void_ptr_p (type, expr))
86990289Sobrien    return false;
87018334Speter
87190289Sobrien  /* 10.4/3 An abstract class shall not be used as a parameter type,
872169699Skan	    as a function return type or as type of an explicit
873169699Skan	    conversion.  */
87490289Sobrien  else if (CLASS_TYPE_P (type) && CLASSTYPE_PURE_VIRTUALS (type))
87518334Speter    {
876169699Skan      error ("expression %qE of abstract class type %qT cannot "
877169699Skan	     "be used in throw-expression", expr, type);
87890289Sobrien      return false;
87990289Sobrien    }
88018334Speter
88190289Sobrien  return true;
88290289Sobrien}
88318334Speter
88490289Sobrien/* Returns nonzero if FN is a declaration of a standard C library
88590289Sobrien   function which is known not to throw.
88650643Sobrien
88790289Sobrien   [lib.res.on.exception.handling]: None of the functions from the
88890289Sobrien   Standard C library shall report an error by throwing an
88990289Sobrien   exception, unless it calls a program-supplied function that
89090289Sobrien   throws an exception.  */
89118334Speter
89290289Sobrien#include "cfns.h"
89318334Speter
89490289Sobrienint
895132727Skannothrow_libfn_p (tree fn)
89690289Sobrien{
89790289Sobrien  tree id;
89818334Speter
89990289Sobrien  if (TREE_PUBLIC (fn)
90090289Sobrien      && DECL_EXTERNAL (fn)
90190289Sobrien      && DECL_NAMESPACE_SCOPE_P (fn)
90290289Sobrien      && DECL_EXTERN_C_P (fn))
90390289Sobrien    /* OK */;
90490289Sobrien  else
90590289Sobrien    /* Can't be a C library function.  */
90690289Sobrien    return 0;
90718334Speter
908169699Skan  /* Being a C library function, DECL_ASSEMBLER_NAME == DECL_NAME
909169699Skan     unless the system headers are playing rename tricks, and if
910169699Skan     they are, we don't want to be confused by them.  */
911169699Skan  id = DECL_NAME (fn);
91290289Sobrien  return !!libc_name_p (IDENTIFIER_POINTER (id), IDENTIFIER_LENGTH (id));
91390289Sobrien}
91418334Speter
91590289Sobrien/* Returns nonzero if an exception of type FROM will be caught by a
91690289Sobrien   handler for type TO, as per [except.handle].  */
91718334Speter
91890289Sobrienstatic int
919132727Skancan_convert_eh (tree to, tree from)
92090289Sobrien{
921132727Skan  to = non_reference (to);
922132727Skan  from = non_reference (from);
92318334Speter
92490289Sobrien  if (TREE_CODE (to) == POINTER_TYPE && TREE_CODE (from) == POINTER_TYPE)
92590289Sobrien    {
92690289Sobrien      to = TREE_TYPE (to);
92790289Sobrien      from = TREE_TYPE (from);
92818334Speter
92990289Sobrien      if (! at_least_as_qualified_p (to, from))
93090289Sobrien	return 0;
93118334Speter
93290289Sobrien      if (TREE_CODE (to) == VOID_TYPE)
93390289Sobrien	return 1;
93418334Speter
935132727Skan      /* Else fall through.  */
93690289Sobrien    }
93718334Speter
93890289Sobrien  if (CLASS_TYPE_P (to) && CLASS_TYPE_P (from)
93990289Sobrien      && PUBLICLY_UNIQUELY_DERIVED_P (to, from))
94090289Sobrien    return 1;
94118334Speter
94290289Sobrien  return 0;
94390289Sobrien}
94418334Speter
945169699Skan/* Check whether any of the handlers in I are shadowed by another handler
946169699Skan   accepting TYPE.  Note that the shadowing may not be complete; even if
947169699Skan   an exception of type B would be caught by a handler for A, there could
948169699Skan   be a derived class C for which A is an ambiguous base but B is not, so
949169699Skan   the handler for B would catch an exception of type C.  */
95018334Speter
95190289Sobrienstatic void
952169699Skancheck_handlers_1 (tree master, tree_stmt_iterator i)
95390289Sobrien{
95490289Sobrien  tree type = TREE_TYPE (master);
95552291Sobrien
956169699Skan  for (; !tsi_end_p (i); tsi_next (&i))
957169699Skan    {
958169699Skan      tree handler = tsi_stmt (i);
959169699Skan      if (TREE_TYPE (handler) && can_convert_eh (type, TREE_TYPE (handler)))
960169699Skan	{
961169699Skan	  warning (0, "%Hexception of type %qT will be caught",
962169699Skan		   EXPR_LOCUS (handler), TREE_TYPE (handler));
963169699Skan	  warning (0, "%H   by earlier handler for %qT",
964169699Skan		   EXPR_LOCUS (master), type);
965169699Skan	  break;
966169699Skan	}
967169699Skan    }
96890289Sobrien}
96918334Speter
970169699Skan/* Given a STATEMENT_LIST of HANDLERs, make sure that they're OK.  */
97118659Sjdp
97290289Sobrienvoid
973132727Skancheck_handlers (tree handlers)
97490289Sobrien{
975169699Skan  tree_stmt_iterator i;
976169699Skan
977169699Skan  /* If we don't have a STATEMENT_LIST, then we've just got one
978169699Skan     handler, and thus nothing to warn about.  */
979169699Skan  if (TREE_CODE (handlers) != STATEMENT_LIST)
980169699Skan    return;
981169699Skan
982169699Skan  i = tsi_start (handlers);
983169699Skan  if (!tsi_end_p (i))
984169699Skan    while (1)
985169699Skan      {
986169699Skan	tree handler = tsi_stmt (i);
987169699Skan	tsi_next (&i);
988169699Skan
989169699Skan	/* No more handlers; nothing to shadow.  */
990169699Skan	if (tsi_end_p (i))
991169699Skan	  break;
992169699Skan	if (TREE_TYPE (handler) == NULL_TREE)
993169699Skan	  pedwarn ("%H%<...%> handler must be the last handler for"
994169699Skan		   " its try block", EXPR_LOCUS (handler));
995169699Skan	else
996169699Skan	  check_handlers_1 (handler, i);
997169699Skan      }
99818334Speter}
999