xref: /dflybsd-src/contrib/gcc-4.7/gcc/cp/except.c (revision 0a8dc9fc45f4d0b236341a473fac4a486375f60c)
1e4b17023SJohn Marino /* Handle exceptional things in C++.
2e4b17023SJohn Marino    Copyright (C) 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
3e4b17023SJohn Marino    2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010
4e4b17023SJohn Marino    Free Software Foundation, Inc.
5e4b17023SJohn Marino    Contributed by Michael Tiemann <tiemann@cygnus.com>
6e4b17023SJohn Marino    Rewritten by Mike Stump <mrs@cygnus.com>, based upon an
7e4b17023SJohn Marino    initial re-implementation courtesy Tad Hunt.
8e4b17023SJohn Marino 
9e4b17023SJohn Marino This file is part of GCC.
10e4b17023SJohn Marino 
11e4b17023SJohn Marino GCC is free software; you can redistribute it and/or modify
12e4b17023SJohn Marino it under the terms of the GNU General Public License as published by
13e4b17023SJohn Marino the Free Software Foundation; either version 3, or (at your option)
14e4b17023SJohn Marino any later version.
15e4b17023SJohn Marino 
16e4b17023SJohn Marino GCC is distributed in the hope that it will be useful,
17e4b17023SJohn Marino but WITHOUT ANY WARRANTY; without even the implied warranty of
18e4b17023SJohn Marino MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19e4b17023SJohn Marino GNU General Public License for more details.
20e4b17023SJohn Marino 
21e4b17023SJohn Marino You should have received a copy of the GNU General Public License
22e4b17023SJohn Marino along with GCC; see the file COPYING3.  If not see
23e4b17023SJohn Marino <http://www.gnu.org/licenses/>.  */
24e4b17023SJohn Marino 
25e4b17023SJohn Marino 
26e4b17023SJohn Marino #include "config.h"
27e4b17023SJohn Marino #include "system.h"
28e4b17023SJohn Marino #include "coretypes.h"
29e4b17023SJohn Marino #include "tm.h"
30e4b17023SJohn Marino #include "tree.h"
31e4b17023SJohn Marino #include "cp-tree.h"
32e4b17023SJohn Marino #include "flags.h"
33e4b17023SJohn Marino #include "output.h"
34e4b17023SJohn Marino #include "tree-inline.h"
35e4b17023SJohn Marino #include "tree-iterator.h"
36e4b17023SJohn Marino #include "target.h"
37e4b17023SJohn Marino #include "gimple.h"
38e4b17023SJohn Marino 
39e4b17023SJohn Marino static void push_eh_cleanup (tree);
40e4b17023SJohn Marino static tree prepare_eh_type (tree);
41e4b17023SJohn Marino static tree do_begin_catch (void);
42e4b17023SJohn Marino static int dtor_nothrow (tree);
43e4b17023SJohn Marino static tree do_end_catch (tree);
44e4b17023SJohn Marino static bool decl_is_java_type (tree decl, int err);
45e4b17023SJohn Marino static void initialize_handler_parm (tree, tree);
46e4b17023SJohn Marino static tree do_allocate_exception (tree);
47e4b17023SJohn Marino static tree wrap_cleanups_r (tree *, int *, void *);
48e4b17023SJohn Marino static int complete_ptr_ref_or_void_ptr_p (tree, tree);
49e4b17023SJohn Marino static bool is_admissible_throw_operand (tree);
50e4b17023SJohn Marino static int can_convert_eh (tree, tree);
51e4b17023SJohn Marino 
52e4b17023SJohn Marino /* Sets up all the global eh stuff that needs to be initialized at the
53e4b17023SJohn Marino    start of compilation.  */
54e4b17023SJohn Marino 
55e4b17023SJohn Marino void
init_exception_processing(void)56e4b17023SJohn Marino init_exception_processing (void)
57e4b17023SJohn Marino {
58e4b17023SJohn Marino   tree tmp;
59e4b17023SJohn Marino 
60e4b17023SJohn Marino   /* void std::terminate (); */
61e4b17023SJohn Marino   push_namespace (std_identifier);
62e4b17023SJohn Marino   tmp = build_function_type_list (void_type_node, NULL_TREE);
63e4b17023SJohn Marino   terminate_node = build_cp_library_fn_ptr ("terminate", tmp);
64e4b17023SJohn Marino   TREE_THIS_VOLATILE (terminate_node) = 1;
65e4b17023SJohn Marino   TREE_NOTHROW (terminate_node) = 1;
66e4b17023SJohn Marino   pop_namespace ();
67e4b17023SJohn Marino 
68e4b17023SJohn Marino   /* void __cxa_call_unexpected(void *); */
69e4b17023SJohn Marino   tmp = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE);
70e4b17023SJohn Marino   call_unexpected_node
71e4b17023SJohn Marino     = push_throw_library_fn (get_identifier ("__cxa_call_unexpected"), tmp);
72e4b17023SJohn Marino }
73e4b17023SJohn Marino 
74e4b17023SJohn Marino /* Returns an expression to be executed if an unhandled exception is
75e4b17023SJohn Marino    propagated out of a cleanup region.  */
76e4b17023SJohn Marino 
77e4b17023SJohn Marino tree
cp_protect_cleanup_actions(void)78e4b17023SJohn Marino cp_protect_cleanup_actions (void)
79e4b17023SJohn Marino {
80e4b17023SJohn Marino   /* [except.terminate]
81e4b17023SJohn Marino 
82e4b17023SJohn Marino      When the destruction of an object during stack unwinding exits
83e4b17023SJohn Marino      using an exception ... void terminate(); is called.  */
84e4b17023SJohn Marino   return terminate_node;
85e4b17023SJohn Marino }
86e4b17023SJohn Marino 
87e4b17023SJohn Marino static tree
prepare_eh_type(tree type)88e4b17023SJohn Marino prepare_eh_type (tree type)
89e4b17023SJohn Marino {
90e4b17023SJohn Marino   if (type == NULL_TREE)
91e4b17023SJohn Marino     return type;
92e4b17023SJohn Marino   if (type == error_mark_node)
93e4b17023SJohn Marino     return error_mark_node;
94e4b17023SJohn Marino 
95e4b17023SJohn Marino   /* peel back references, so they match.  */
96e4b17023SJohn Marino   type = non_reference (type);
97e4b17023SJohn Marino 
98e4b17023SJohn Marino   /* Peel off cv qualifiers.  */
99e4b17023SJohn Marino   type = TYPE_MAIN_VARIANT (type);
100e4b17023SJohn Marino 
101e4b17023SJohn Marino   /* Functions and arrays decay to pointers.  */
102e4b17023SJohn Marino   type = type_decays_to (type);
103e4b17023SJohn Marino 
104e4b17023SJohn Marino   return type;
105e4b17023SJohn Marino }
106e4b17023SJohn Marino 
107e4b17023SJohn Marino /* Return the type info for TYPE as used by EH machinery.  */
108e4b17023SJohn Marino tree
eh_type_info(tree type)109e4b17023SJohn Marino eh_type_info (tree type)
110e4b17023SJohn Marino {
111e4b17023SJohn Marino   tree exp;
112e4b17023SJohn Marino 
113e4b17023SJohn Marino   if (type == NULL_TREE || type == error_mark_node)
114e4b17023SJohn Marino     return type;
115e4b17023SJohn Marino 
116e4b17023SJohn Marino   if (decl_is_java_type (type, 0))
117e4b17023SJohn Marino     exp = build_java_class_ref (TREE_TYPE (type));
118e4b17023SJohn Marino   else
119e4b17023SJohn Marino     exp = get_tinfo_decl (type);
120e4b17023SJohn Marino 
121e4b17023SJohn Marino   return exp;
122e4b17023SJohn Marino }
123e4b17023SJohn Marino 
124e4b17023SJohn Marino /* Build the address of a typeinfo decl for use in the runtime
125e4b17023SJohn Marino    matching field of the exception model.  */
126e4b17023SJohn Marino 
127e4b17023SJohn Marino tree
build_eh_type_type(tree type)128e4b17023SJohn Marino build_eh_type_type (tree type)
129e4b17023SJohn Marino {
130e4b17023SJohn Marino   tree exp = eh_type_info (type);
131e4b17023SJohn Marino 
132e4b17023SJohn Marino   if (!exp)
133e4b17023SJohn Marino     return NULL;
134e4b17023SJohn Marino 
135e4b17023SJohn Marino   mark_used (exp);
136e4b17023SJohn Marino 
137e4b17023SJohn Marino   return convert (ptr_type_node, build_address (exp));
138e4b17023SJohn Marino }
139e4b17023SJohn Marino 
140e4b17023SJohn Marino tree
build_exc_ptr(void)141e4b17023SJohn Marino build_exc_ptr (void)
142e4b17023SJohn Marino {
143e4b17023SJohn Marino   return build_call_n (builtin_decl_explicit (BUILT_IN_EH_POINTER),
144e4b17023SJohn Marino 		       1, integer_zero_node);
145e4b17023SJohn Marino }
146e4b17023SJohn Marino 
147e4b17023SJohn Marino /* Declare a function NAME, returning RETURN_TYPE, taking a single
148e4b17023SJohn Marino    parameter PARM_TYPE, with an empty exception specification.
149e4b17023SJohn Marino 
150e4b17023SJohn Marino    Note that the C++ ABI document does not have a throw-specifier on
151e4b17023SJohn Marino    the routines declared below via this function.  The declarations
152e4b17023SJohn Marino    are consistent with the actual implementations in libsupc++.  */
153e4b17023SJohn Marino 
154e4b17023SJohn Marino static tree
declare_nothrow_library_fn(tree name,tree return_type,tree parm_type)155e4b17023SJohn Marino declare_nothrow_library_fn (tree name, tree return_type, tree parm_type)
156e4b17023SJohn Marino {
157e4b17023SJohn Marino   return push_library_fn (name, build_function_type_list (return_type,
158e4b17023SJohn Marino 							  parm_type,
159e4b17023SJohn Marino 							  NULL_TREE),
160e4b17023SJohn Marino 			  empty_except_spec);
161e4b17023SJohn Marino }
162e4b17023SJohn Marino 
163e4b17023SJohn Marino /* Build up a call to __cxa_get_exception_ptr so that we can build a
164e4b17023SJohn Marino    copy constructor for the thrown object.  */
165e4b17023SJohn Marino 
166e4b17023SJohn Marino static tree
do_get_exception_ptr(void)167e4b17023SJohn Marino do_get_exception_ptr (void)
168e4b17023SJohn Marino {
169e4b17023SJohn Marino   tree fn;
170e4b17023SJohn Marino 
171e4b17023SJohn Marino   fn = get_identifier ("__cxa_get_exception_ptr");
172e4b17023SJohn Marino   if (!get_global_value_if_present (fn, &fn))
173e4b17023SJohn Marino     {
174e4b17023SJohn Marino       /* Declare void* __cxa_get_exception_ptr (void *) throw().  */
175e4b17023SJohn Marino       fn = declare_nothrow_library_fn (fn, ptr_type_node, ptr_type_node);
176e4b17023SJohn Marino 
177e4b17023SJohn Marino       if (flag_tm)
178e4b17023SJohn Marino 	apply_tm_attr (fn, get_identifier ("transaction_pure"));
179e4b17023SJohn Marino     }
180e4b17023SJohn Marino 
181e4b17023SJohn Marino   return cp_build_function_call_nary (fn, tf_warning_or_error,
182e4b17023SJohn Marino 				      build_exc_ptr (), NULL_TREE);
183e4b17023SJohn Marino }
184e4b17023SJohn Marino 
185e4b17023SJohn Marino /* Build up a call to __cxa_begin_catch, to tell the runtime that the
186e4b17023SJohn Marino    exception has been handled.  */
187e4b17023SJohn Marino 
188e4b17023SJohn Marino static tree
do_begin_catch(void)189e4b17023SJohn Marino do_begin_catch (void)
190e4b17023SJohn Marino {
191e4b17023SJohn Marino   tree fn;
192e4b17023SJohn Marino 
193e4b17023SJohn Marino   fn = get_identifier ("__cxa_begin_catch");
194e4b17023SJohn Marino   if (!get_global_value_if_present (fn, &fn))
195e4b17023SJohn Marino     {
196e4b17023SJohn Marino       /* Declare void* __cxa_begin_catch (void *) throw().  */
197e4b17023SJohn Marino       fn = declare_nothrow_library_fn (fn, ptr_type_node, ptr_type_node);
198e4b17023SJohn Marino 
199e4b17023SJohn Marino       /* Create its transactional-memory equivalent.  */
200e4b17023SJohn Marino       if (flag_tm)
201e4b17023SJohn Marino 	{
202e4b17023SJohn Marino 	  tree fn2 = get_identifier ("_ITM_cxa_begin_catch");
203e4b17023SJohn Marino 	  if (!get_global_value_if_present (fn2, &fn2))
204e4b17023SJohn Marino 	    fn2 = declare_nothrow_library_fn (fn2, ptr_type_node,
205e4b17023SJohn Marino 					      ptr_type_node);
206e4b17023SJohn Marino 	  apply_tm_attr (fn2, get_identifier ("transaction_pure"));
207e4b17023SJohn Marino 	  record_tm_replacement (fn, fn2);
208e4b17023SJohn Marino 	}
209e4b17023SJohn Marino     }
210e4b17023SJohn Marino 
211e4b17023SJohn Marino   return cp_build_function_call_nary (fn, tf_warning_or_error,
212e4b17023SJohn Marino 				      build_exc_ptr (), NULL_TREE);
213e4b17023SJohn Marino }
214e4b17023SJohn Marino 
215e4b17023SJohn Marino /* Returns nonzero if cleaning up an exception of type TYPE (which can be
216e4b17023SJohn Marino    NULL_TREE for a ... handler) will not throw an exception.  */
217e4b17023SJohn Marino 
218e4b17023SJohn Marino static int
dtor_nothrow(tree type)219e4b17023SJohn Marino dtor_nothrow (tree type)
220e4b17023SJohn Marino {
221e4b17023SJohn Marino   if (type == NULL_TREE || type == error_mark_node)
222e4b17023SJohn Marino     return 0;
223e4b17023SJohn Marino 
224e4b17023SJohn Marino   if (TYPE_HAS_TRIVIAL_DESTRUCTOR (type))
225e4b17023SJohn Marino     return 1;
226e4b17023SJohn Marino 
227e4b17023SJohn Marino   if (CLASSTYPE_LAZY_DESTRUCTOR (type))
228e4b17023SJohn Marino     lazily_declare_fn (sfk_destructor, type);
229e4b17023SJohn Marino 
230e4b17023SJohn Marino   return TREE_NOTHROW (CLASSTYPE_DESTRUCTORS (type));
231e4b17023SJohn Marino }
232e4b17023SJohn Marino 
233e4b17023SJohn Marino /* Build up a call to __cxa_end_catch, to destroy the exception object
234e4b17023SJohn Marino    for the current catch block if no others are currently using it.  */
235e4b17023SJohn Marino 
236e4b17023SJohn Marino static tree
do_end_catch(tree type)237e4b17023SJohn Marino do_end_catch (tree type)
238e4b17023SJohn Marino {
239e4b17023SJohn Marino   tree fn, cleanup;
240e4b17023SJohn Marino 
241e4b17023SJohn Marino   fn = get_identifier ("__cxa_end_catch");
242e4b17023SJohn Marino   if (!get_global_value_if_present (fn, &fn))
243e4b17023SJohn Marino     {
244e4b17023SJohn Marino       /* Declare void __cxa_end_catch ().  */
245e4b17023SJohn Marino       fn = push_void_library_fn (fn, void_list_node);
246e4b17023SJohn Marino       /* This can throw if the destructor for the exception throws.  */
247e4b17023SJohn Marino       TREE_NOTHROW (fn) = 0;
248e4b17023SJohn Marino 
249e4b17023SJohn Marino       /* Create its transactional-memory equivalent.  */
250e4b17023SJohn Marino       if (flag_tm)
251e4b17023SJohn Marino 	{
252e4b17023SJohn Marino 	  tree fn2 = get_identifier ("_ITM_cxa_end_catch");
253e4b17023SJohn Marino 	  if (!get_global_value_if_present (fn2, &fn2))
254e4b17023SJohn Marino 	    {
255e4b17023SJohn Marino 	      fn2 = push_void_library_fn (fn2, void_list_node);
256e4b17023SJohn Marino 	      TREE_NOTHROW (fn2) = 0;
257e4b17023SJohn Marino 	    }
258e4b17023SJohn Marino 	  apply_tm_attr (fn2, get_identifier ("transaction_pure"));
259e4b17023SJohn Marino 	  record_tm_replacement (fn, fn2);
260e4b17023SJohn Marino 	}
261e4b17023SJohn Marino     }
262e4b17023SJohn Marino 
263e4b17023SJohn Marino   cleanup = cp_build_function_call_vec (fn, NULL, tf_warning_or_error);
264e4b17023SJohn Marino   TREE_NOTHROW (cleanup) = dtor_nothrow (type);
265e4b17023SJohn Marino 
266e4b17023SJohn Marino   return cleanup;
267e4b17023SJohn Marino }
268e4b17023SJohn Marino 
269e4b17023SJohn Marino /* This routine creates the cleanup for the current exception.  */
270e4b17023SJohn Marino 
271e4b17023SJohn Marino static void
push_eh_cleanup(tree type)272e4b17023SJohn Marino push_eh_cleanup (tree type)
273e4b17023SJohn Marino {
274e4b17023SJohn Marino   finish_decl_cleanup (NULL_TREE, do_end_catch (type));
275e4b17023SJohn Marino }
276e4b17023SJohn Marino 
277e4b17023SJohn Marino /* Return nonzero value if DECL is a Java type suitable for catch or
278e4b17023SJohn Marino    throw.  */
279e4b17023SJohn Marino 
280e4b17023SJohn Marino static bool
decl_is_java_type(tree decl,int err)281e4b17023SJohn Marino decl_is_java_type (tree decl, int err)
282e4b17023SJohn Marino {
283e4b17023SJohn Marino   bool r = (TREE_CODE (decl) == POINTER_TYPE
284e4b17023SJohn Marino 	    && TREE_CODE (TREE_TYPE (decl)) == RECORD_TYPE
285e4b17023SJohn Marino 	    && TYPE_FOR_JAVA (TREE_TYPE (decl)));
286e4b17023SJohn Marino 
287e4b17023SJohn Marino   if (err)
288e4b17023SJohn Marino     {
289e4b17023SJohn Marino       if (TREE_CODE (decl) == REFERENCE_TYPE
290e4b17023SJohn Marino 	  && TREE_CODE (TREE_TYPE (decl)) == RECORD_TYPE
291e4b17023SJohn Marino 	  && TYPE_FOR_JAVA (TREE_TYPE (decl)))
292e4b17023SJohn Marino 	{
293e4b17023SJohn Marino 	  /* Can't throw a reference.  */
294e4b17023SJohn Marino 	  error ("type %qT is disallowed in Java %<throw%> or %<catch%>",
295e4b17023SJohn Marino 		 decl);
296e4b17023SJohn Marino 	}
297e4b17023SJohn Marino 
298e4b17023SJohn Marino       if (r)
299e4b17023SJohn Marino 	{
300e4b17023SJohn Marino 	  tree jthrow_node
301e4b17023SJohn Marino 	    = IDENTIFIER_GLOBAL_VALUE (get_identifier ("jthrowable"));
302e4b17023SJohn Marino 
303e4b17023SJohn Marino 	  if (jthrow_node == NULL_TREE)
304e4b17023SJohn Marino 	    fatal_error
305e4b17023SJohn Marino 	      ("call to Java %<catch%> or %<throw%> with %<jthrowable%> undefined");
306e4b17023SJohn Marino 
307e4b17023SJohn Marino 	  jthrow_node = TREE_TYPE (TREE_TYPE (jthrow_node));
308e4b17023SJohn Marino 
309e4b17023SJohn Marino 	  if (! DERIVED_FROM_P (jthrow_node, TREE_TYPE (decl)))
310e4b17023SJohn Marino 	    {
311e4b17023SJohn Marino 	      /* Thrown object must be a Throwable.  */
312e4b17023SJohn Marino 	      error ("type %qT is not derived from %<java::lang::Throwable%>",
313e4b17023SJohn Marino 		     TREE_TYPE (decl));
314e4b17023SJohn Marino 	    }
315e4b17023SJohn Marino 	}
316e4b17023SJohn Marino     }
317e4b17023SJohn Marino 
318e4b17023SJohn Marino   return r;
319e4b17023SJohn Marino }
320e4b17023SJohn Marino 
321e4b17023SJohn Marino /* Select the personality routine to be used for exception handling,
322e4b17023SJohn Marino    or issue an error if we need two different ones in the same
323e4b17023SJohn Marino    translation unit.
324e4b17023SJohn Marino    ??? At present DECL_FUNCTION_PERSONALITY is set via
325e4b17023SJohn Marino    LANG_HOOKS_EH_PERSONALITY.  Should it be done here instead?  */
326e4b17023SJohn Marino void
choose_personality_routine(enum languages lang)327e4b17023SJohn Marino choose_personality_routine (enum languages lang)
328e4b17023SJohn Marino {
329e4b17023SJohn Marino   static enum {
330e4b17023SJohn Marino     chose_none,
331e4b17023SJohn Marino     chose_cpp,
332e4b17023SJohn Marino     chose_java,
333e4b17023SJohn Marino     gave_error
334e4b17023SJohn Marino   } state;
335e4b17023SJohn Marino 
336e4b17023SJohn Marino   switch (state)
337e4b17023SJohn Marino     {
338e4b17023SJohn Marino     case gave_error:
339e4b17023SJohn Marino       return;
340e4b17023SJohn Marino 
341e4b17023SJohn Marino     case chose_cpp:
342e4b17023SJohn Marino       if (lang != lang_cplusplus)
343e4b17023SJohn Marino 	goto give_error;
344e4b17023SJohn Marino       return;
345e4b17023SJohn Marino 
346e4b17023SJohn Marino     case chose_java:
347e4b17023SJohn Marino       if (lang != lang_java)
348e4b17023SJohn Marino 	goto give_error;
349e4b17023SJohn Marino       return;
350e4b17023SJohn Marino 
351e4b17023SJohn Marino     case chose_none:
352e4b17023SJohn Marino       ; /* Proceed to language selection.  */
353e4b17023SJohn Marino     }
354e4b17023SJohn Marino 
355e4b17023SJohn Marino   switch (lang)
356e4b17023SJohn Marino     {
357e4b17023SJohn Marino     case lang_cplusplus:
358e4b17023SJohn Marino       state = chose_cpp;
359e4b17023SJohn Marino       break;
360e4b17023SJohn Marino 
361e4b17023SJohn Marino     case lang_java:
362e4b17023SJohn Marino       state = chose_java;
363e4b17023SJohn Marino       terminate_node = builtin_decl_explicit (BUILT_IN_ABORT);
364e4b17023SJohn Marino       pragma_java_exceptions = true;
365e4b17023SJohn Marino       break;
366e4b17023SJohn Marino 
367e4b17023SJohn Marino     default:
368e4b17023SJohn Marino       gcc_unreachable ();
369e4b17023SJohn Marino     }
370e4b17023SJohn Marino   return;
371e4b17023SJohn Marino 
372e4b17023SJohn Marino  give_error:
373e4b17023SJohn Marino   error ("mixing C++ and Java catches in a single translation unit");
374e4b17023SJohn Marino   state = gave_error;
375e4b17023SJohn Marino }
376e4b17023SJohn Marino 
377e4b17023SJohn Marino /* Wrap EXPR in a MUST_NOT_THROW_EXPR expressing that EXPR must
378e4b17023SJohn Marino    not throw any exceptions if COND is true.  A condition of
379e4b17023SJohn Marino    NULL_TREE is treated as 'true'.  */
380e4b17023SJohn Marino 
381e4b17023SJohn Marino tree
build_must_not_throw_expr(tree body,tree cond)382e4b17023SJohn Marino build_must_not_throw_expr (tree body, tree cond)
383e4b17023SJohn Marino {
384e4b17023SJohn Marino   tree type = body ? TREE_TYPE (body) : void_type_node;
385e4b17023SJohn Marino 
386*95d28233SJohn Marino   if (!flag_exceptions)
387*95d28233SJohn Marino     return body;
388*95d28233SJohn Marino 
389e4b17023SJohn Marino   if (cond && !value_dependent_expression_p (cond))
390e4b17023SJohn Marino     {
391e4b17023SJohn Marino       cond = cxx_constant_value (cond);
392e4b17023SJohn Marino       if (integer_zerop (cond))
393e4b17023SJohn Marino 	return body;
394e4b17023SJohn Marino       else if (integer_onep (cond))
395e4b17023SJohn Marino 	cond = NULL_TREE;
396e4b17023SJohn Marino     }
397e4b17023SJohn Marino 
398e4b17023SJohn Marino   return build2 (MUST_NOT_THROW_EXPR, type, body, cond);
399e4b17023SJohn Marino }
400e4b17023SJohn Marino 
401e4b17023SJohn Marino 
402e4b17023SJohn Marino /* Initialize the catch parameter DECL.  */
403e4b17023SJohn Marino 
404e4b17023SJohn Marino static void
initialize_handler_parm(tree decl,tree exp)405e4b17023SJohn Marino initialize_handler_parm (tree decl, tree exp)
406e4b17023SJohn Marino {
407e4b17023SJohn Marino   tree init;
408e4b17023SJohn Marino   tree init_type;
409e4b17023SJohn Marino 
410e4b17023SJohn Marino   /* Make sure we mark the catch param as used, otherwise we'll get a
411e4b17023SJohn Marino      warning about an unused ((anonymous)).  */
412e4b17023SJohn Marino   TREE_USED (decl) = 1;
413e4b17023SJohn Marino   DECL_READ_P (decl) = 1;
414e4b17023SJohn Marino 
415e4b17023SJohn Marino   /* Figure out the type that the initializer is.  Pointers are returned
416e4b17023SJohn Marino      adjusted by value from __cxa_begin_catch.  Others are returned by
417e4b17023SJohn Marino      reference.  */
418e4b17023SJohn Marino   init_type = TREE_TYPE (decl);
419e4b17023SJohn Marino   if (!POINTER_TYPE_P (init_type))
420e4b17023SJohn Marino     init_type = build_reference_type (init_type);
421e4b17023SJohn Marino 
422e4b17023SJohn Marino   choose_personality_routine (decl_is_java_type (init_type, 0)
423e4b17023SJohn Marino 			      ? lang_java : lang_cplusplus);
424e4b17023SJohn Marino 
425e4b17023SJohn Marino   /* Since pointers are passed by value, initialize a reference to
426e4b17023SJohn Marino      pointer catch parm with the address of the temporary.  */
427e4b17023SJohn Marino   if (TREE_CODE (init_type) == REFERENCE_TYPE
428e4b17023SJohn Marino       && TYPE_PTR_P (TREE_TYPE (init_type)))
429e4b17023SJohn Marino     exp = cp_build_addr_expr (exp, tf_warning_or_error);
430e4b17023SJohn Marino 
431e4b17023SJohn Marino   exp = ocp_convert (init_type, exp, CONV_IMPLICIT|CONV_FORCE_TEMP, 0);
432e4b17023SJohn Marino 
433e4b17023SJohn Marino   init = convert_from_reference (exp);
434e4b17023SJohn Marino 
435e4b17023SJohn Marino   /* If the constructor for the catch parm exits via an exception, we
436e4b17023SJohn Marino      must call terminate.  See eh23.C.  */
437e4b17023SJohn Marino   if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl)))
438e4b17023SJohn Marino     {
439e4b17023SJohn Marino       /* Generate the copy constructor call directly so we can wrap it.
440e4b17023SJohn Marino 	 See also expand_default_init.  */
441e4b17023SJohn Marino       init = ocp_convert (TREE_TYPE (decl), init,
442e4b17023SJohn Marino 			  CONV_IMPLICIT|CONV_FORCE_TEMP, 0);
443e4b17023SJohn Marino       /* Force cleanups now to avoid nesting problems with the
444e4b17023SJohn Marino 	 MUST_NOT_THROW_EXPR.  */
445e4b17023SJohn Marino       init = fold_build_cleanup_point_expr (TREE_TYPE (init), init);
446e4b17023SJohn Marino       init = build_must_not_throw_expr (init, NULL_TREE);
447e4b17023SJohn Marino     }
448e4b17023SJohn Marino 
449e4b17023SJohn Marino   decl = pushdecl (decl);
450e4b17023SJohn Marino 
451e4b17023SJohn Marino   start_decl_1 (decl, true);
452e4b17023SJohn Marino   cp_finish_decl (decl, init, /*init_const_expr_p=*/false, NULL_TREE,
453e4b17023SJohn Marino 		  LOOKUP_ONLYCONVERTING|DIRECT_BIND);
454e4b17023SJohn Marino }
455e4b17023SJohn Marino 
456e4b17023SJohn Marino 
457e4b17023SJohn Marino /* Routine to see if exception handling is turned on.
458e4b17023SJohn Marino    DO_WARN is nonzero if we want to inform the user that exception
459e4b17023SJohn Marino    handling is turned off.
460e4b17023SJohn Marino 
461e4b17023SJohn Marino    This is used to ensure that -fexceptions has been specified if the
462e4b17023SJohn Marino    compiler tries to use any exception-specific functions.  */
463e4b17023SJohn Marino 
464e4b17023SJohn Marino static inline int
doing_eh(void)465e4b17023SJohn Marino doing_eh (void)
466e4b17023SJohn Marino {
467e4b17023SJohn Marino   if (! flag_exceptions)
468e4b17023SJohn Marino     {
469e4b17023SJohn Marino       static int warned = 0;
470e4b17023SJohn Marino       if (! warned)
471e4b17023SJohn Marino 	{
472e4b17023SJohn Marino 	  error ("exception handling disabled, use -fexceptions to enable");
473e4b17023SJohn Marino 	  warned = 1;
474e4b17023SJohn Marino 	}
475e4b17023SJohn Marino       return 0;
476e4b17023SJohn Marino     }
477e4b17023SJohn Marino   return 1;
478e4b17023SJohn Marino }
479e4b17023SJohn Marino 
480e4b17023SJohn Marino /* Call this to start a catch block.  DECL is the catch parameter.  */
481e4b17023SJohn Marino 
482e4b17023SJohn Marino tree
expand_start_catch_block(tree decl)483e4b17023SJohn Marino expand_start_catch_block (tree decl)
484e4b17023SJohn Marino {
485e4b17023SJohn Marino   tree exp;
486e4b17023SJohn Marino   tree type, init;
487e4b17023SJohn Marino 
488e4b17023SJohn Marino   if (! doing_eh ())
489e4b17023SJohn Marino     return NULL_TREE;
490e4b17023SJohn Marino 
491e4b17023SJohn Marino   /* Make sure this declaration is reasonable.  */
492e4b17023SJohn Marino   if (decl && !complete_ptr_ref_or_void_ptr_p (TREE_TYPE (decl), NULL_TREE))
493e4b17023SJohn Marino     decl = error_mark_node;
494e4b17023SJohn Marino 
495e4b17023SJohn Marino   if (decl)
496e4b17023SJohn Marino     type = prepare_eh_type (TREE_TYPE (decl));
497e4b17023SJohn Marino   else
498e4b17023SJohn Marino     type = NULL_TREE;
499e4b17023SJohn Marino 
500e4b17023SJohn Marino   if (decl && decl_is_java_type (type, 1))
501e4b17023SJohn Marino     {
502e4b17023SJohn Marino       /* Java only passes object via pointer and doesn't require
503e4b17023SJohn Marino 	 adjusting.  The java object is immediately before the
504e4b17023SJohn Marino 	 generic exception header.  */
505e4b17023SJohn Marino       exp = build_exc_ptr ();
506e4b17023SJohn Marino       exp = build1 (NOP_EXPR, build_pointer_type (type), exp);
507e4b17023SJohn Marino       exp = fold_build_pointer_plus (exp,
508e4b17023SJohn Marino 		    fold_build1_loc (input_location,
509e4b17023SJohn Marino 				     NEGATE_EXPR, sizetype,
510e4b17023SJohn Marino 				     TYPE_SIZE_UNIT (TREE_TYPE (exp))));
511e4b17023SJohn Marino       exp = cp_build_indirect_ref (exp, RO_NULL, tf_warning_or_error);
512e4b17023SJohn Marino       initialize_handler_parm (decl, exp);
513e4b17023SJohn Marino       return type;
514e4b17023SJohn Marino     }
515e4b17023SJohn Marino 
516e4b17023SJohn Marino   /* Call __cxa_end_catch at the end of processing the exception.  */
517e4b17023SJohn Marino   push_eh_cleanup (type);
518e4b17023SJohn Marino 
519e4b17023SJohn Marino   init = do_begin_catch ();
520e4b17023SJohn Marino 
521e4b17023SJohn Marino   /* If there's no decl at all, then all we need to do is make sure
522e4b17023SJohn Marino      to tell the runtime that we've begun handling the exception.  */
523e4b17023SJohn Marino   if (decl == NULL || decl == error_mark_node || init == error_mark_node)
524e4b17023SJohn Marino     finish_expr_stmt (init);
525e4b17023SJohn Marino 
526e4b17023SJohn Marino   /* If the C++ object needs constructing, we need to do that before
527e4b17023SJohn Marino      calling __cxa_begin_catch, so that std::uncaught_exception gets
528e4b17023SJohn Marino      the right value during the copy constructor.  */
529e4b17023SJohn Marino   else if (flag_use_cxa_get_exception_ptr
530e4b17023SJohn Marino 	   && TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl)))
531e4b17023SJohn Marino     {
532e4b17023SJohn Marino       exp = do_get_exception_ptr ();
533e4b17023SJohn Marino       initialize_handler_parm (decl, exp);
534e4b17023SJohn Marino       finish_expr_stmt (init);
535e4b17023SJohn Marino     }
536e4b17023SJohn Marino 
537e4b17023SJohn Marino   /* Otherwise the type uses a bitwise copy, and we don't have to worry
538e4b17023SJohn Marino      about the value of std::uncaught_exception and therefore can do the
539e4b17023SJohn Marino      copy with the return value of __cxa_end_catch instead.  */
540e4b17023SJohn Marino   else
541e4b17023SJohn Marino     {
542e4b17023SJohn Marino       tree init_type = type;
543e4b17023SJohn Marino 
544e4b17023SJohn Marino       /* Pointers are passed by values, everything else by reference.  */
545e4b17023SJohn Marino       if (!TYPE_PTR_P (type))
546e4b17023SJohn Marino 	init_type = build_pointer_type (type);
547e4b17023SJohn Marino       if (init_type != TREE_TYPE (init))
548e4b17023SJohn Marino 	init = build1 (NOP_EXPR, init_type, init);
549e4b17023SJohn Marino       exp = create_temporary_var (init_type);
550e4b17023SJohn Marino       DECL_REGISTER (exp) = 1;
551e4b17023SJohn Marino       cp_finish_decl (exp, init, /*init_const_expr=*/false,
552e4b17023SJohn Marino 		      NULL_TREE, LOOKUP_ONLYCONVERTING);
553e4b17023SJohn Marino       initialize_handler_parm (decl, exp);
554e4b17023SJohn Marino     }
555e4b17023SJohn Marino 
556e4b17023SJohn Marino   return type;
557e4b17023SJohn Marino }
558e4b17023SJohn Marino 
559e4b17023SJohn Marino 
560e4b17023SJohn Marino /* Call this to end a catch block.  Its responsible for emitting the
561e4b17023SJohn Marino    code to handle jumping back to the correct place, and for emitting
562e4b17023SJohn Marino    the label to jump to if this catch block didn't match.  */
563e4b17023SJohn Marino 
564e4b17023SJohn Marino void
expand_end_catch_block(void)565e4b17023SJohn Marino expand_end_catch_block (void)
566e4b17023SJohn Marino {
567e4b17023SJohn Marino   if (! doing_eh ())
568e4b17023SJohn Marino     return;
569e4b17023SJohn Marino 
570e4b17023SJohn Marino   /* The exception being handled is rethrown if control reaches the end of
571e4b17023SJohn Marino      a handler of the function-try-block of a constructor or destructor.  */
572e4b17023SJohn Marino   if (in_function_try_handler
573e4b17023SJohn Marino       && (DECL_CONSTRUCTOR_P (current_function_decl)
574e4b17023SJohn Marino 	  || DECL_DESTRUCTOR_P (current_function_decl)))
575e4b17023SJohn Marino     finish_expr_stmt (build_throw (NULL_TREE));
576e4b17023SJohn Marino }
577e4b17023SJohn Marino 
578e4b17023SJohn Marino tree
begin_eh_spec_block(void)579e4b17023SJohn Marino begin_eh_spec_block (void)
580e4b17023SJohn Marino {
581e4b17023SJohn Marino   tree r;
582e4b17023SJohn Marino   location_t spec_location = DECL_SOURCE_LOCATION (current_function_decl);
583e4b17023SJohn Marino 
584e4b17023SJohn Marino   /* A noexcept specification (or throw() with -fnothrow-opt) is a
585e4b17023SJohn Marino      MUST_NOT_THROW_EXPR.  */
586e4b17023SJohn Marino   if (TYPE_NOEXCEPT_P (TREE_TYPE (current_function_decl)))
587e4b17023SJohn Marino     {
588e4b17023SJohn Marino       r = build_stmt (spec_location, MUST_NOT_THROW_EXPR,
589e4b17023SJohn Marino 		      NULL_TREE, NULL_TREE);
590e4b17023SJohn Marino       TREE_SIDE_EFFECTS (r) = 1;
591e4b17023SJohn Marino     }
592e4b17023SJohn Marino   else
593e4b17023SJohn Marino     r = build_stmt (spec_location, EH_SPEC_BLOCK, NULL_TREE, NULL_TREE);
594e4b17023SJohn Marino   add_stmt (r);
595e4b17023SJohn Marino   TREE_OPERAND (r, 0) = push_stmt_list ();
596e4b17023SJohn Marino   return r;
597e4b17023SJohn Marino }
598e4b17023SJohn Marino 
599e4b17023SJohn Marino void
finish_eh_spec_block(tree raw_raises,tree eh_spec_block)600e4b17023SJohn Marino finish_eh_spec_block (tree raw_raises, tree eh_spec_block)
601e4b17023SJohn Marino {
602e4b17023SJohn Marino   tree raises;
603e4b17023SJohn Marino 
604e4b17023SJohn Marino   TREE_OPERAND (eh_spec_block, 0)
605e4b17023SJohn Marino     = pop_stmt_list (TREE_OPERAND (eh_spec_block, 0));
606e4b17023SJohn Marino 
607e4b17023SJohn Marino   if (TREE_CODE (eh_spec_block) == MUST_NOT_THROW_EXPR)
608e4b17023SJohn Marino     return;
609e4b17023SJohn Marino 
610e4b17023SJohn Marino   /* Strip cv quals, etc, from the specification types.  */
611e4b17023SJohn Marino   for (raises = NULL_TREE;
612e4b17023SJohn Marino        raw_raises && TREE_VALUE (raw_raises);
613e4b17023SJohn Marino        raw_raises = TREE_CHAIN (raw_raises))
614e4b17023SJohn Marino     {
615e4b17023SJohn Marino       tree type = prepare_eh_type (TREE_VALUE (raw_raises));
616e4b17023SJohn Marino       tree tinfo = eh_type_info (type);
617e4b17023SJohn Marino 
618e4b17023SJohn Marino       mark_used (tinfo);
619e4b17023SJohn Marino       raises = tree_cons (NULL_TREE, type, raises);
620e4b17023SJohn Marino     }
621e4b17023SJohn Marino 
622e4b17023SJohn Marino   EH_SPEC_RAISES (eh_spec_block) = raises;
623e4b17023SJohn Marino }
624e4b17023SJohn Marino 
625e4b17023SJohn Marino /* Return a pointer to a buffer for an exception object of type TYPE.  */
626e4b17023SJohn Marino 
627e4b17023SJohn Marino static tree
do_allocate_exception(tree type)628e4b17023SJohn Marino do_allocate_exception (tree type)
629e4b17023SJohn Marino {
630e4b17023SJohn Marino   tree fn;
631e4b17023SJohn Marino 
632e4b17023SJohn Marino   fn = get_identifier ("__cxa_allocate_exception");
633e4b17023SJohn Marino   if (!get_global_value_if_present (fn, &fn))
634e4b17023SJohn Marino     {
635e4b17023SJohn Marino       /* Declare void *__cxa_allocate_exception(size_t) throw().  */
636e4b17023SJohn Marino       fn = declare_nothrow_library_fn (fn, ptr_type_node, size_type_node);
637e4b17023SJohn Marino 
638e4b17023SJohn Marino       if (flag_tm)
639e4b17023SJohn Marino 	{
640e4b17023SJohn Marino 	  tree fn2 = get_identifier ("_ITM_cxa_allocate_exception");
641e4b17023SJohn Marino 	  if (!get_global_value_if_present (fn2, &fn2))
642e4b17023SJohn Marino 	    fn2 = declare_nothrow_library_fn (fn2, ptr_type_node,
643e4b17023SJohn Marino 					      size_type_node);
644e4b17023SJohn Marino 	  apply_tm_attr (fn2, get_identifier ("transaction_pure"));
645e4b17023SJohn Marino 	  record_tm_replacement (fn, fn2);
646e4b17023SJohn Marino 	}
647e4b17023SJohn Marino     }
648e4b17023SJohn Marino 
649e4b17023SJohn Marino   return cp_build_function_call_nary (fn, tf_warning_or_error,
650e4b17023SJohn Marino 				      size_in_bytes (type), NULL_TREE);
651e4b17023SJohn Marino }
652e4b17023SJohn Marino 
653e4b17023SJohn Marino /* Call __cxa_free_exception from a cleanup.  This is never invoked
654e4b17023SJohn Marino    directly, but see the comment for stabilize_throw_expr.  */
655e4b17023SJohn Marino 
656e4b17023SJohn Marino static tree
do_free_exception(tree ptr)657e4b17023SJohn Marino do_free_exception (tree ptr)
658e4b17023SJohn Marino {
659e4b17023SJohn Marino   tree fn;
660e4b17023SJohn Marino 
661e4b17023SJohn Marino   fn = get_identifier ("__cxa_free_exception");
662e4b17023SJohn Marino   if (!get_global_value_if_present (fn, &fn))
663e4b17023SJohn Marino     {
664e4b17023SJohn Marino       /* Declare void __cxa_free_exception (void *) throw().  */
665e4b17023SJohn Marino       fn = declare_nothrow_library_fn (fn, void_type_node, ptr_type_node);
666e4b17023SJohn Marino     }
667e4b17023SJohn Marino 
668e4b17023SJohn Marino   return cp_build_function_call_nary (fn, tf_warning_or_error, ptr, NULL_TREE);
669e4b17023SJohn Marino }
670e4b17023SJohn Marino 
671e4b17023SJohn Marino /* Wrap all cleanups for TARGET_EXPRs in MUST_NOT_THROW_EXPR.
672e4b17023SJohn Marino    Called from build_throw via walk_tree_without_duplicates.  */
673e4b17023SJohn Marino 
674e4b17023SJohn Marino static tree
wrap_cleanups_r(tree * tp,int * walk_subtrees ATTRIBUTE_UNUSED,void * data ATTRIBUTE_UNUSED)675e4b17023SJohn Marino wrap_cleanups_r (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED,
676e4b17023SJohn Marino 		 void *data ATTRIBUTE_UNUSED)
677e4b17023SJohn Marino {
678e4b17023SJohn Marino   tree exp = *tp;
679e4b17023SJohn Marino   tree cleanup;
680e4b17023SJohn Marino 
681e4b17023SJohn Marino   /* Don't walk into types.  */
682e4b17023SJohn Marino   if (TYPE_P (exp))
683e4b17023SJohn Marino     {
684e4b17023SJohn Marino       *walk_subtrees = 0;
685e4b17023SJohn Marino       return NULL_TREE;
686e4b17023SJohn Marino     }
687e4b17023SJohn Marino   if (TREE_CODE (exp) != TARGET_EXPR)
688e4b17023SJohn Marino     return NULL_TREE;
689e4b17023SJohn Marino 
690e4b17023SJohn Marino   cleanup = TARGET_EXPR_CLEANUP (exp);
691e4b17023SJohn Marino   if (cleanup)
692e4b17023SJohn Marino     {
693e4b17023SJohn Marino       cleanup = build2 (MUST_NOT_THROW_EXPR, void_type_node, cleanup,
694e4b17023SJohn Marino 			NULL_TREE);
695e4b17023SJohn Marino       TARGET_EXPR_CLEANUP (exp) = cleanup;
696e4b17023SJohn Marino     }
697e4b17023SJohn Marino 
698e4b17023SJohn Marino   /* Keep iterating.  */
699e4b17023SJohn Marino   return NULL_TREE;
700e4b17023SJohn Marino }
701e4b17023SJohn Marino 
702e4b17023SJohn Marino /* Build a throw expression.  */
703e4b17023SJohn Marino 
704e4b17023SJohn Marino tree
build_throw(tree exp)705e4b17023SJohn Marino build_throw (tree exp)
706e4b17023SJohn Marino {
707e4b17023SJohn Marino   tree fn;
708e4b17023SJohn Marino 
709e4b17023SJohn Marino   if (exp == error_mark_node)
710e4b17023SJohn Marino     return exp;
711e4b17023SJohn Marino 
712e4b17023SJohn Marino   if (processing_template_decl)
713e4b17023SJohn Marino     {
714e4b17023SJohn Marino       if (cfun)
715e4b17023SJohn Marino 	current_function_returns_abnormally = 1;
716e4b17023SJohn Marino       exp = build_min (THROW_EXPR, void_type_node, exp);
717e4b17023SJohn Marino       SET_EXPR_LOCATION (exp, input_location);
718e4b17023SJohn Marino       return exp;
719e4b17023SJohn Marino     }
720e4b17023SJohn Marino 
721e4b17023SJohn Marino   if (exp == null_node)
722e4b17023SJohn Marino     warning (0, "throwing NULL, which has integral, not pointer type");
723e4b17023SJohn Marino 
724e4b17023SJohn Marino   if (exp != NULL_TREE)
725e4b17023SJohn Marino     {
726e4b17023SJohn Marino       if (!is_admissible_throw_operand (exp))
727e4b17023SJohn Marino 	return error_mark_node;
728e4b17023SJohn Marino     }
729e4b17023SJohn Marino 
730e4b17023SJohn Marino   if (! doing_eh ())
731e4b17023SJohn Marino     return error_mark_node;
732e4b17023SJohn Marino 
733e4b17023SJohn Marino   if (exp && decl_is_java_type (TREE_TYPE (exp), 1))
734e4b17023SJohn Marino     {
735e4b17023SJohn Marino       tree fn = get_identifier ("_Jv_Throw");
736e4b17023SJohn Marino       if (!get_global_value_if_present (fn, &fn))
737e4b17023SJohn Marino 	{
738e4b17023SJohn Marino 	  /* Declare void _Jv_Throw (void *).  */
739e4b17023SJohn Marino 	  tree tmp;
740e4b17023SJohn Marino 	  tmp = build_function_type_list (ptr_type_node,
741e4b17023SJohn Marino 					  ptr_type_node, NULL_TREE);
742e4b17023SJohn Marino 	  fn = push_throw_library_fn (fn, tmp);
743e4b17023SJohn Marino 	}
744e4b17023SJohn Marino       else if (really_overloaded_fn (fn))
745e4b17023SJohn Marino 	{
746e4b17023SJohn Marino 	  error ("%qD should never be overloaded", fn);
747e4b17023SJohn Marino 	  return error_mark_node;
748e4b17023SJohn Marino 	}
749e4b17023SJohn Marino       fn = OVL_CURRENT (fn);
750e4b17023SJohn Marino       exp = cp_build_function_call_nary (fn, tf_warning_or_error,
751e4b17023SJohn Marino 					 exp, NULL_TREE);
752e4b17023SJohn Marino     }
753e4b17023SJohn Marino   else if (exp)
754e4b17023SJohn Marino     {
755e4b17023SJohn Marino       tree throw_type;
756e4b17023SJohn Marino       tree temp_type;
757e4b17023SJohn Marino       tree cleanup;
758e4b17023SJohn Marino       tree object, ptr;
759e4b17023SJohn Marino       tree tmp;
760e4b17023SJohn Marino       tree allocate_expr;
761e4b17023SJohn Marino 
762e4b17023SJohn Marino       /* The CLEANUP_TYPE is the internal type of a destructor.  */
763e4b17023SJohn Marino       if (!cleanup_type)
764e4b17023SJohn Marino 	{
765e4b17023SJohn Marino 	  tmp = build_function_type_list (void_type_node,
766e4b17023SJohn Marino 					  ptr_type_node, NULL_TREE);
767e4b17023SJohn Marino 	  cleanup_type = build_pointer_type (tmp);
768e4b17023SJohn Marino 	}
769e4b17023SJohn Marino 
770e4b17023SJohn Marino       fn = get_identifier ("__cxa_throw");
771e4b17023SJohn Marino       if (!get_global_value_if_present (fn, &fn))
772e4b17023SJohn Marino 	{
773e4b17023SJohn Marino 	  /* Declare void __cxa_throw (void*, void*, void (*)(void*)).  */
774e4b17023SJohn Marino 	  /* ??? Second argument is supposed to be "std::type_info*".  */
775e4b17023SJohn Marino 	  tmp = build_function_type_list (void_type_node,
776e4b17023SJohn Marino 					  ptr_type_node, ptr_type_node,
777e4b17023SJohn Marino 					  cleanup_type, NULL_TREE);
778e4b17023SJohn Marino 	  fn = push_throw_library_fn (fn, tmp);
779e4b17023SJohn Marino 
780e4b17023SJohn Marino 	  if (flag_tm)
781e4b17023SJohn Marino 	    {
782e4b17023SJohn Marino 	      tree fn2 = get_identifier ("_ITM_cxa_throw");
783e4b17023SJohn Marino 	      if (!get_global_value_if_present (fn2, &fn2))
784e4b17023SJohn Marino 		fn2 = push_throw_library_fn (fn2, tmp);
785e4b17023SJohn Marino 	      apply_tm_attr (fn2, get_identifier ("transaction_pure"));
786e4b17023SJohn Marino 	      record_tm_replacement (fn, fn2);
787e4b17023SJohn Marino 	    }
788e4b17023SJohn Marino 	}
789e4b17023SJohn Marino 
790e4b17023SJohn Marino       /* [except.throw]
791e4b17023SJohn Marino 
792e4b17023SJohn Marino 	 A throw-expression initializes a temporary object, the type
793e4b17023SJohn Marino 	 of which is determined by removing any top-level
794e4b17023SJohn Marino 	 cv-qualifiers from the static type of the operand of throw
795e4b17023SJohn Marino 	 and adjusting the type from "array of T" or "function return
796e4b17023SJohn Marino 	 T" to "pointer to T" or "pointer to function returning T"
797e4b17023SJohn Marino 	 respectively.  */
798e4b17023SJohn Marino       temp_type = is_bitfield_expr_with_lowered_type (exp);
799e4b17023SJohn Marino       if (!temp_type)
800e4b17023SJohn Marino 	temp_type = cv_unqualified (type_decays_to (TREE_TYPE (exp)));
801e4b17023SJohn Marino 
802e4b17023SJohn Marino       /* OK, this is kind of wacky.  The standard says that we call
803e4b17023SJohn Marino 	 terminate when the exception handling mechanism, after
804e4b17023SJohn Marino 	 completing evaluation of the expression to be thrown but
805e4b17023SJohn Marino 	 before the exception is caught (_except.throw_), calls a
806e4b17023SJohn Marino 	 user function that exits via an uncaught exception.
807e4b17023SJohn Marino 
808e4b17023SJohn Marino 	 So we have to protect the actual initialization of the
809e4b17023SJohn Marino 	 exception object with terminate(), but evaluate the
810e4b17023SJohn Marino 	 expression first.  Since there could be temps in the
811e4b17023SJohn Marino 	 expression, we need to handle that, too.  We also expand
812e4b17023SJohn Marino 	 the call to __cxa_allocate_exception first (which doesn't
813e4b17023SJohn Marino 	 matter, since it can't throw).  */
814e4b17023SJohn Marino 
815e4b17023SJohn Marino       /* Allocate the space for the exception.  */
816e4b17023SJohn Marino       allocate_expr = do_allocate_exception (temp_type);
817e4b17023SJohn Marino       allocate_expr = get_target_expr (allocate_expr);
818e4b17023SJohn Marino       ptr = TARGET_EXPR_SLOT (allocate_expr);
819e4b17023SJohn Marino       TARGET_EXPR_CLEANUP (allocate_expr) = do_free_exception (ptr);
820e4b17023SJohn Marino       CLEANUP_EH_ONLY (allocate_expr) = 1;
821e4b17023SJohn Marino 
822e4b17023SJohn Marino       object = build_nop (build_pointer_type (temp_type), ptr);
823e4b17023SJohn Marino       object = cp_build_indirect_ref (object, RO_NULL, tf_warning_or_error);
824e4b17023SJohn Marino 
825e4b17023SJohn Marino       /* And initialize the exception object.  */
826e4b17023SJohn Marino       if (CLASS_TYPE_P (temp_type))
827e4b17023SJohn Marino 	{
828e4b17023SJohn Marino 	  int flags = LOOKUP_NORMAL | LOOKUP_ONLYCONVERTING;
829e4b17023SJohn Marino 	  VEC(tree,gc) *exp_vec;
830e4b17023SJohn Marino 
831e4b17023SJohn Marino 	  /* Under C++0x [12.8/16 class.copy], a thrown lvalue is sometimes
832e4b17023SJohn Marino 	     treated as an rvalue for the purposes of overload resolution
833e4b17023SJohn Marino 	     to favor move constructors over copy constructors.  */
834e4b17023SJohn Marino 	  if (/* Must be a local, automatic variable.  */
835e4b17023SJohn Marino 	      TREE_CODE (exp) == VAR_DECL
836e4b17023SJohn Marino 	      && DECL_CONTEXT (exp) == current_function_decl
837e4b17023SJohn Marino 	      && ! TREE_STATIC (exp)
838e4b17023SJohn Marino 	      /* The variable must not have the `volatile' qualifier.  */
839e4b17023SJohn Marino 	      && !(cp_type_quals (TREE_TYPE (exp)) & TYPE_QUAL_VOLATILE))
840e4b17023SJohn Marino 	    flags = flags | LOOKUP_PREFER_RVALUE;
841e4b17023SJohn Marino 
842e4b17023SJohn Marino 	  /* Call the copy constructor.  */
843e4b17023SJohn Marino 	  exp_vec = make_tree_vector_single (exp);
844e4b17023SJohn Marino 	  exp = (build_special_member_call
845e4b17023SJohn Marino 		 (object, complete_ctor_identifier, &exp_vec,
846e4b17023SJohn Marino 		  TREE_TYPE (object), flags, tf_warning_or_error));
847e4b17023SJohn Marino 	  release_tree_vector (exp_vec);
848e4b17023SJohn Marino 	  if (exp == error_mark_node)
849e4b17023SJohn Marino 	    {
850e4b17023SJohn Marino 	      error ("  in thrown expression");
851e4b17023SJohn Marino 	      return error_mark_node;
852e4b17023SJohn Marino 	    }
853e4b17023SJohn Marino 	}
854e4b17023SJohn Marino       else
855e4b17023SJohn Marino 	{
856e4b17023SJohn Marino 	  tmp = decay_conversion (exp);
857e4b17023SJohn Marino 	  if (tmp == error_mark_node)
858e4b17023SJohn Marino 	    return error_mark_node;
859e4b17023SJohn Marino 	  exp = build2 (INIT_EXPR, temp_type, object, tmp);
860e4b17023SJohn Marino 	}
861e4b17023SJohn Marino 
862e4b17023SJohn Marino       /* Mark any cleanups from the initialization as MUST_NOT_THROW, since
863e4b17023SJohn Marino 	 they are run after the exception object is initialized.  */
864e4b17023SJohn Marino       cp_walk_tree_without_duplicates (&exp, wrap_cleanups_r, 0);
865e4b17023SJohn Marino 
866e4b17023SJohn Marino       /* Prepend the allocation.  */
867e4b17023SJohn Marino       exp = build2 (COMPOUND_EXPR, TREE_TYPE (exp), allocate_expr, exp);
868e4b17023SJohn Marino 
869e4b17023SJohn Marino       /* Force all the cleanups to be evaluated here so that we don't have
870e4b17023SJohn Marino 	 to do them during unwinding.  */
871e4b17023SJohn Marino       exp = build1 (CLEANUP_POINT_EXPR, void_type_node, exp);
872e4b17023SJohn Marino 
873e4b17023SJohn Marino       throw_type = build_eh_type_type (prepare_eh_type (TREE_TYPE (object)));
874e4b17023SJohn Marino 
875e4b17023SJohn Marino       if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (object)))
876e4b17023SJohn Marino 	{
877e4b17023SJohn Marino 	  cleanup = lookup_fnfields (TYPE_BINFO (TREE_TYPE (object)),
878e4b17023SJohn Marino 				     complete_dtor_identifier, 0);
879e4b17023SJohn Marino 	  cleanup = BASELINK_FUNCTIONS (cleanup);
880e4b17023SJohn Marino 	  mark_used (cleanup);
881e4b17023SJohn Marino 	  cxx_mark_addressable (cleanup);
882e4b17023SJohn Marino 	  /* Pretend it's a normal function.  */
883e4b17023SJohn Marino 	  cleanup = build1 (ADDR_EXPR, cleanup_type, cleanup);
884e4b17023SJohn Marino 	}
885e4b17023SJohn Marino       else
886e4b17023SJohn Marino 	cleanup = build_int_cst (cleanup_type, 0);
887e4b17023SJohn Marino 
888e4b17023SJohn Marino       /* ??? Indicate that this function call throws throw_type.  */
889e4b17023SJohn Marino       tmp = cp_build_function_call_nary (fn, tf_warning_or_error,
890e4b17023SJohn Marino 					 ptr, throw_type, cleanup, NULL_TREE);
891e4b17023SJohn Marino 
892e4b17023SJohn Marino       /* Tack on the initialization stuff.  */
893e4b17023SJohn Marino       exp = build2 (COMPOUND_EXPR, TREE_TYPE (tmp), exp, tmp);
894e4b17023SJohn Marino     }
895e4b17023SJohn Marino   else
896e4b17023SJohn Marino     {
897e4b17023SJohn Marino       /* Rethrow current exception.  */
898e4b17023SJohn Marino 
899e4b17023SJohn Marino       tree fn = get_identifier ("__cxa_rethrow");
900e4b17023SJohn Marino       if (!get_global_value_if_present (fn, &fn))
901e4b17023SJohn Marino 	{
902e4b17023SJohn Marino 	  /* Declare void __cxa_rethrow (void).  */
903e4b17023SJohn Marino 	  fn = push_throw_library_fn
904e4b17023SJohn Marino 	    (fn, build_function_type_list (void_type_node, NULL_TREE));
905e4b17023SJohn Marino 	}
906e4b17023SJohn Marino 
907e4b17023SJohn Marino       if (flag_tm)
908e4b17023SJohn Marino 	apply_tm_attr (fn, get_identifier ("transaction_pure"));
909e4b17023SJohn Marino 
910e4b17023SJohn Marino       /* ??? Indicate that this function call allows exceptions of the type
911e4b17023SJohn Marino 	 of the enclosing catch block (if known).  */
912e4b17023SJohn Marino       exp = cp_build_function_call_vec (fn, NULL, tf_warning_or_error);
913e4b17023SJohn Marino     }
914e4b17023SJohn Marino 
915e4b17023SJohn Marino   exp = build1 (THROW_EXPR, void_type_node, exp);
916e4b17023SJohn Marino   SET_EXPR_LOCATION (exp, input_location);
917e4b17023SJohn Marino 
918e4b17023SJohn Marino   return exp;
919e4b17023SJohn Marino }
920e4b17023SJohn Marino 
921e4b17023SJohn Marino /* Make sure TYPE is complete, pointer to complete, reference to
922e4b17023SJohn Marino    complete, or pointer to cv void. Issue diagnostic on failure.
923e4b17023SJohn Marino    Return the zero on failure and nonzero on success. FROM can be
924e4b17023SJohn Marino    the expr or decl from whence TYPE came, if available.  */
925e4b17023SJohn Marino 
926e4b17023SJohn Marino static int
complete_ptr_ref_or_void_ptr_p(tree type,tree from)927e4b17023SJohn Marino complete_ptr_ref_or_void_ptr_p (tree type, tree from)
928e4b17023SJohn Marino {
929e4b17023SJohn Marino   int is_ptr;
930e4b17023SJohn Marino 
931e4b17023SJohn Marino   /* Check complete.  */
932e4b17023SJohn Marino   type = complete_type_or_else (type, from);
933e4b17023SJohn Marino   if (!type)
934e4b17023SJohn Marino     return 0;
935e4b17023SJohn Marino 
936e4b17023SJohn Marino   /* Or a pointer or ref to one, or cv void *.  */
937e4b17023SJohn Marino   is_ptr = TREE_CODE (type) == POINTER_TYPE;
938e4b17023SJohn Marino   if (is_ptr || TREE_CODE (type) == REFERENCE_TYPE)
939e4b17023SJohn Marino     {
940e4b17023SJohn Marino       tree core = TREE_TYPE (type);
941e4b17023SJohn Marino 
942e4b17023SJohn Marino       if (is_ptr && VOID_TYPE_P (core))
943e4b17023SJohn Marino 	/* OK */;
944e4b17023SJohn Marino       else if (!complete_type_or_else (core, from))
945e4b17023SJohn Marino 	return 0;
946e4b17023SJohn Marino     }
947e4b17023SJohn Marino   return 1;
948e4b17023SJohn Marino }
949e4b17023SJohn Marino 
950e4b17023SJohn Marino /* Return truth-value if EXPRESSION is admissible in throw-expression,
951e4b17023SJohn Marino    i.e. if it is not of incomplete type or a pointer/reference to such
952e4b17023SJohn Marino    a type or of an abstract class type.  */
953e4b17023SJohn Marino 
954e4b17023SJohn Marino static bool
is_admissible_throw_operand(tree expr)955e4b17023SJohn Marino is_admissible_throw_operand (tree expr)
956e4b17023SJohn Marino {
957e4b17023SJohn Marino   tree type = TREE_TYPE (expr);
958e4b17023SJohn Marino 
959e4b17023SJohn Marino   /* 15.1/4 [...] The type of the throw-expression shall not be an
960e4b17023SJohn Marino 	    incomplete type, or a pointer or a reference to an incomplete
961e4b17023SJohn Marino 	    type, other than void*, const void*, volatile void*, or
962e4b17023SJohn Marino 	    const volatile void*.  Except for these restriction and the
963e4b17023SJohn Marino 	    restrictions on type matching mentioned in 15.3, the operand
964e4b17023SJohn Marino 	    of throw is treated exactly as a function argument in a call
965e4b17023SJohn Marino 	    (5.2.2) or the operand of a return statement.  */
966e4b17023SJohn Marino   if (!complete_ptr_ref_or_void_ptr_p (type, expr))
967e4b17023SJohn Marino     return false;
968e4b17023SJohn Marino 
969e4b17023SJohn Marino   /* 10.4/3 An abstract class shall not be used as a parameter type,
970e4b17023SJohn Marino 	    as a function return type or as type of an explicit
971e4b17023SJohn Marino 	    conversion.  */
972e4b17023SJohn Marino   else if (CLASS_TYPE_P (type) && CLASSTYPE_PURE_VIRTUALS (type))
973e4b17023SJohn Marino     {
974e4b17023SJohn Marino       error ("expression %qE of abstract class type %qT cannot "
975e4b17023SJohn Marino 	     "be used in throw-expression", expr, type);
976e4b17023SJohn Marino       return false;
977e4b17023SJohn Marino     }
978e4b17023SJohn Marino 
979e4b17023SJohn Marino   return true;
980e4b17023SJohn Marino }
981e4b17023SJohn Marino 
982e4b17023SJohn Marino /* Returns nonzero if FN is a declaration of a standard C library
983e4b17023SJohn Marino    function which is known not to throw.
984e4b17023SJohn Marino 
985e4b17023SJohn Marino    [lib.res.on.exception.handling]: None of the functions from the
986e4b17023SJohn Marino    Standard C library shall report an error by throwing an
987e4b17023SJohn Marino    exception, unless it calls a program-supplied function that
988e4b17023SJohn Marino    throws an exception.  */
989e4b17023SJohn Marino 
990e4b17023SJohn Marino #include "cfns.h"
991e4b17023SJohn Marino 
992e4b17023SJohn Marino int
nothrow_libfn_p(const_tree fn)993e4b17023SJohn Marino nothrow_libfn_p (const_tree fn)
994e4b17023SJohn Marino {
995e4b17023SJohn Marino   tree id;
996e4b17023SJohn Marino 
997e4b17023SJohn Marino   if (TREE_PUBLIC (fn)
998e4b17023SJohn Marino       && DECL_EXTERNAL (fn)
999e4b17023SJohn Marino       && DECL_NAMESPACE_SCOPE_P (fn)
1000e4b17023SJohn Marino       && DECL_EXTERN_C_P (fn))
1001e4b17023SJohn Marino     /* OK */;
1002e4b17023SJohn Marino   else
1003e4b17023SJohn Marino     /* Can't be a C library function.  */
1004e4b17023SJohn Marino     return 0;
1005e4b17023SJohn Marino 
1006e4b17023SJohn Marino   /* Being a C library function, DECL_ASSEMBLER_NAME == DECL_NAME
1007e4b17023SJohn Marino      unless the system headers are playing rename tricks, and if
1008e4b17023SJohn Marino      they are, we don't want to be confused by them.  */
1009e4b17023SJohn Marino   id = DECL_NAME (fn);
1010e4b17023SJohn Marino   return !!libc_name_p (IDENTIFIER_POINTER (id), IDENTIFIER_LENGTH (id));
1011e4b17023SJohn Marino }
1012e4b17023SJohn Marino 
1013e4b17023SJohn Marino /* Returns nonzero if an exception of type FROM will be caught by a
1014e4b17023SJohn Marino    handler for type TO, as per [except.handle].  */
1015e4b17023SJohn Marino 
1016e4b17023SJohn Marino static int
can_convert_eh(tree to,tree from)1017e4b17023SJohn Marino can_convert_eh (tree to, tree from)
1018e4b17023SJohn Marino {
1019e4b17023SJohn Marino   to = non_reference (to);
1020e4b17023SJohn Marino   from = non_reference (from);
1021e4b17023SJohn Marino 
1022e4b17023SJohn Marino   if (TREE_CODE (to) == POINTER_TYPE && TREE_CODE (from) == POINTER_TYPE)
1023e4b17023SJohn Marino     {
1024e4b17023SJohn Marino       to = TREE_TYPE (to);
1025e4b17023SJohn Marino       from = TREE_TYPE (from);
1026e4b17023SJohn Marino 
1027e4b17023SJohn Marino       if (! at_least_as_qualified_p (to, from))
1028e4b17023SJohn Marino 	return 0;
1029e4b17023SJohn Marino 
1030e4b17023SJohn Marino       if (TREE_CODE (to) == VOID_TYPE)
1031e4b17023SJohn Marino 	return 1;
1032e4b17023SJohn Marino 
1033e4b17023SJohn Marino       /* Else fall through.  */
1034e4b17023SJohn Marino     }
1035e4b17023SJohn Marino 
1036e4b17023SJohn Marino   if (CLASS_TYPE_P (to) && CLASS_TYPE_P (from)
1037e4b17023SJohn Marino       && PUBLICLY_UNIQUELY_DERIVED_P (to, from))
1038e4b17023SJohn Marino     return 1;
1039e4b17023SJohn Marino 
1040e4b17023SJohn Marino   return 0;
1041e4b17023SJohn Marino }
1042e4b17023SJohn Marino 
1043e4b17023SJohn Marino /* Check whether any of the handlers in I are shadowed by another handler
1044e4b17023SJohn Marino    accepting TYPE.  Note that the shadowing may not be complete; even if
1045e4b17023SJohn Marino    an exception of type B would be caught by a handler for A, there could
1046e4b17023SJohn Marino    be a derived class C for which A is an ambiguous base but B is not, so
1047e4b17023SJohn Marino    the handler for B would catch an exception of type C.  */
1048e4b17023SJohn Marino 
1049e4b17023SJohn Marino static void
check_handlers_1(tree master,tree_stmt_iterator i)1050e4b17023SJohn Marino check_handlers_1 (tree master, tree_stmt_iterator i)
1051e4b17023SJohn Marino {
1052e4b17023SJohn Marino   tree type = TREE_TYPE (master);
1053e4b17023SJohn Marino 
1054e4b17023SJohn Marino   for (; !tsi_end_p (i); tsi_next (&i))
1055e4b17023SJohn Marino     {
1056e4b17023SJohn Marino       tree handler = tsi_stmt (i);
1057e4b17023SJohn Marino       if (TREE_TYPE (handler) && can_convert_eh (type, TREE_TYPE (handler)))
1058e4b17023SJohn Marino 	{
1059e4b17023SJohn Marino 	  warning_at (EXPR_LOCATION (handler), 0,
1060e4b17023SJohn Marino 		      "exception of type %qT will be caught",
1061e4b17023SJohn Marino 		      TREE_TYPE (handler));
1062e4b17023SJohn Marino 	  warning_at (EXPR_LOCATION (master), 0,
1063e4b17023SJohn Marino 		      "   by earlier handler for %qT", type);
1064e4b17023SJohn Marino 	  break;
1065e4b17023SJohn Marino 	}
1066e4b17023SJohn Marino     }
1067e4b17023SJohn Marino }
1068e4b17023SJohn Marino 
1069e4b17023SJohn Marino /* Given a STATEMENT_LIST of HANDLERs, make sure that they're OK.  */
1070e4b17023SJohn Marino 
1071e4b17023SJohn Marino void
check_handlers(tree handlers)1072e4b17023SJohn Marino check_handlers (tree handlers)
1073e4b17023SJohn Marino {
1074e4b17023SJohn Marino   tree_stmt_iterator i;
1075e4b17023SJohn Marino 
1076e4b17023SJohn Marino   /* If we don't have a STATEMENT_LIST, then we've just got one
1077e4b17023SJohn Marino      handler, and thus nothing to warn about.  */
1078e4b17023SJohn Marino   if (TREE_CODE (handlers) != STATEMENT_LIST)
1079e4b17023SJohn Marino     return;
1080e4b17023SJohn Marino 
1081e4b17023SJohn Marino   i = tsi_start (handlers);
1082e4b17023SJohn Marino   if (!tsi_end_p (i))
1083e4b17023SJohn Marino     while (1)
1084e4b17023SJohn Marino       {
1085e4b17023SJohn Marino 	tree handler = tsi_stmt (i);
1086e4b17023SJohn Marino 	tsi_next (&i);
1087e4b17023SJohn Marino 
1088e4b17023SJohn Marino 	/* No more handlers; nothing to shadow.  */
1089e4b17023SJohn Marino 	if (tsi_end_p (i))
1090e4b17023SJohn Marino 	  break;
1091e4b17023SJohn Marino 	if (TREE_TYPE (handler) == NULL_TREE)
1092e4b17023SJohn Marino 	  permerror (EXPR_LOCATION (handler), "%<...%>"
1093e4b17023SJohn Marino 		     " handler must be the last handler for its try block");
1094e4b17023SJohn Marino 	else
1095e4b17023SJohn Marino 	  check_handlers_1 (handler, i);
1096e4b17023SJohn Marino       }
1097e4b17023SJohn Marino }
1098e4b17023SJohn Marino 
1099e4b17023SJohn Marino /* walk_tree helper for finish_noexcept_expr.  Returns non-null if the
1100e4b17023SJohn Marino    expression *TP causes the noexcept operator to evaluate to false.
1101e4b17023SJohn Marino 
1102e4b17023SJohn Marino    5.3.7 [expr.noexcept]: The result of the noexcept operator is false if
1103e4b17023SJohn Marino    in a potentially-evaluated context the expression would contain
1104e4b17023SJohn Marino    * a potentially evaluated call to a function, member function,
1105e4b17023SJohn Marino      function pointer, or member function pointer that does not have a
1106e4b17023SJohn Marino      non-throwing exception-specification (15.4),
1107e4b17023SJohn Marino    * a potentially evaluated throw-expression (15.1),
1108e4b17023SJohn Marino    * a potentially evaluated dynamic_cast expression dynamic_cast<T>(v),
1109e4b17023SJohn Marino      where T is a reference type, that requires a run-time check (5.2.7), or
1110e4b17023SJohn Marino    * a potentially evaluated typeid expression (5.2.8) applied to a glvalue
1111e4b17023SJohn Marino      expression whose type is a polymorphic class type (10.3).  */
1112e4b17023SJohn Marino 
1113e4b17023SJohn Marino static tree
check_noexcept_r(tree * tp,int * walk_subtrees ATTRIBUTE_UNUSED,void * data ATTRIBUTE_UNUSED)1114e4b17023SJohn Marino check_noexcept_r (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED,
1115e4b17023SJohn Marino 		  void *data ATTRIBUTE_UNUSED)
1116e4b17023SJohn Marino {
1117e4b17023SJohn Marino   tree t = *tp;
1118e4b17023SJohn Marino   enum tree_code code = TREE_CODE (t);
1119e4b17023SJohn Marino   if (code == CALL_EXPR
1120e4b17023SJohn Marino       || code == AGGR_INIT_EXPR)
1121e4b17023SJohn Marino     {
1122e4b17023SJohn Marino       /* We can only use the exception specification of the called function
1123e4b17023SJohn Marino 	 for determining the value of a noexcept expression; we can't use
1124e4b17023SJohn Marino 	 TREE_NOTHROW, as it might have a different value in another
1125e4b17023SJohn Marino 	 translation unit, creating ODR problems.
1126e4b17023SJohn Marino 
1127e4b17023SJohn Marino          We could use TREE_NOTHROW (t) for !TREE_PUBLIC fns, though... */
1128e4b17023SJohn Marino       tree fn = (code == AGGR_INIT_EXPR
1129e4b17023SJohn Marino 		 ? AGGR_INIT_EXPR_FN (t) : CALL_EXPR_FN (t));
1130e4b17023SJohn Marino       tree type = TREE_TYPE (TREE_TYPE (fn));
1131e4b17023SJohn Marino 
1132e4b17023SJohn Marino       STRIP_NOPS (fn);
1133e4b17023SJohn Marino       if (TREE_CODE (fn) == ADDR_EXPR)
1134e4b17023SJohn Marino 	fn = TREE_OPERAND (fn, 0);
1135e4b17023SJohn Marino       if (TREE_CODE (fn) == FUNCTION_DECL)
1136e4b17023SJohn Marino 	{
1137e4b17023SJohn Marino 	  /* We do use TREE_NOTHROW for ABI internals like __dynamic_cast,
1138e4b17023SJohn Marino 	     and for C library functions known not to throw.  */
1139e4b17023SJohn Marino 	  if (DECL_EXTERN_C_P (fn)
1140e4b17023SJohn Marino 	      && (DECL_ARTIFICIAL (fn)
1141e4b17023SJohn Marino 		  || nothrow_libfn_p (fn)))
1142e4b17023SJohn Marino 	    return TREE_NOTHROW (fn) ? NULL_TREE : fn;
1143e4b17023SJohn Marino 	  /* A call to a constexpr function is noexcept if the call
1144e4b17023SJohn Marino 	     is a constant expression.  */
1145e4b17023SJohn Marino 	  if (DECL_DECLARED_CONSTEXPR_P (fn)
1146e4b17023SJohn Marino 	      && is_sub_constant_expr (t))
1147e4b17023SJohn Marino 	    return NULL_TREE;
1148e4b17023SJohn Marino 	}
1149e4b17023SJohn Marino       if (!TYPE_NOTHROW_P (type))
1150e4b17023SJohn Marino 	return fn;
1151e4b17023SJohn Marino     }
1152e4b17023SJohn Marino 
1153e4b17023SJohn Marino   return NULL_TREE;
1154e4b17023SJohn Marino }
1155e4b17023SJohn Marino 
1156e4b17023SJohn Marino /* If a function that causes a noexcept-expression to be false isn't
1157e4b17023SJohn Marino    defined yet, remember it and check it for TREE_NOTHROW again at EOF.  */
1158e4b17023SJohn Marino 
1159e4b17023SJohn Marino typedef struct GTY(()) pending_noexcept {
1160e4b17023SJohn Marino   tree fn;
1161e4b17023SJohn Marino   location_t loc;
1162e4b17023SJohn Marino } pending_noexcept;
1163e4b17023SJohn Marino DEF_VEC_O(pending_noexcept);
1164e4b17023SJohn Marino DEF_VEC_ALLOC_O(pending_noexcept,gc);
1165e4b17023SJohn Marino static GTY(()) VEC(pending_noexcept,gc) *pending_noexcept_checks;
1166e4b17023SJohn Marino 
1167e4b17023SJohn Marino /* FN is a FUNCTION_DECL that caused a noexcept-expr to be false.  Warn if
1168e4b17023SJohn Marino    it can't throw.  */
1169e4b17023SJohn Marino 
1170e4b17023SJohn Marino static void
maybe_noexcept_warning(tree fn)1171e4b17023SJohn Marino maybe_noexcept_warning (tree fn)
1172e4b17023SJohn Marino {
1173e4b17023SJohn Marino   if (TREE_NOTHROW (fn))
1174e4b17023SJohn Marino     {
1175e4b17023SJohn Marino       warning (OPT_Wnoexcept, "noexcept-expression evaluates to %<false%> "
1176e4b17023SJohn Marino 	       "because of a call to %qD", fn);
1177e4b17023SJohn Marino       warning (OPT_Wnoexcept, "but %q+D does not throw; perhaps "
1178e4b17023SJohn Marino 	       "it should be declared %<noexcept%>", fn);
1179e4b17023SJohn Marino     }
1180e4b17023SJohn Marino }
1181e4b17023SJohn Marino 
1182e4b17023SJohn Marino /* Check any functions that weren't defined earlier when they caused a
1183e4b17023SJohn Marino    noexcept expression to evaluate to false.  */
1184e4b17023SJohn Marino 
1185e4b17023SJohn Marino void
perform_deferred_noexcept_checks(void)1186e4b17023SJohn Marino perform_deferred_noexcept_checks (void)
1187e4b17023SJohn Marino {
1188e4b17023SJohn Marino   int i;
1189e4b17023SJohn Marino   pending_noexcept *p;
1190e4b17023SJohn Marino   location_t saved_loc = input_location;
1191e4b17023SJohn Marino   FOR_EACH_VEC_ELT (pending_noexcept, pending_noexcept_checks, i, p)
1192e4b17023SJohn Marino     {
1193e4b17023SJohn Marino       input_location = p->loc;
1194e4b17023SJohn Marino       maybe_noexcept_warning (p->fn);
1195e4b17023SJohn Marino     }
1196e4b17023SJohn Marino   input_location = saved_loc;
1197e4b17023SJohn Marino }
1198e4b17023SJohn Marino 
1199e4b17023SJohn Marino /* Evaluate noexcept ( EXPR ).  */
1200e4b17023SJohn Marino 
1201e4b17023SJohn Marino tree
finish_noexcept_expr(tree expr,tsubst_flags_t complain)1202e4b17023SJohn Marino finish_noexcept_expr (tree expr, tsubst_flags_t complain)
1203e4b17023SJohn Marino {
1204e4b17023SJohn Marino   if (expr == error_mark_node)
1205e4b17023SJohn Marino     return error_mark_node;
1206e4b17023SJohn Marino 
1207e4b17023SJohn Marino   if (processing_template_decl)
1208e4b17023SJohn Marino     return build_min (NOEXCEPT_EXPR, boolean_type_node, expr);
1209e4b17023SJohn Marino 
1210e4b17023SJohn Marino   return (expr_noexcept_p (expr, complain)
1211e4b17023SJohn Marino 	  ? boolean_true_node : boolean_false_node);
1212e4b17023SJohn Marino }
1213e4b17023SJohn Marino 
1214e4b17023SJohn Marino /* Returns whether EXPR is noexcept, possibly warning if allowed by
1215e4b17023SJohn Marino    COMPLAIN.  */
1216e4b17023SJohn Marino 
1217e4b17023SJohn Marino bool
expr_noexcept_p(tree expr,tsubst_flags_t complain)1218e4b17023SJohn Marino expr_noexcept_p (tree expr, tsubst_flags_t complain)
1219e4b17023SJohn Marino {
1220e4b17023SJohn Marino   tree fn;
1221e4b17023SJohn Marino 
1222e4b17023SJohn Marino   if (expr == error_mark_node)
1223e4b17023SJohn Marino     return false;
1224e4b17023SJohn Marino 
1225e4b17023SJohn Marino   fn = cp_walk_tree_without_duplicates (&expr, check_noexcept_r, 0);
1226e4b17023SJohn Marino   if (fn)
1227e4b17023SJohn Marino     {
1228e4b17023SJohn Marino       if ((complain & tf_warning) && warn_noexcept
1229e4b17023SJohn Marino 	  && TREE_CODE (fn) == FUNCTION_DECL)
1230e4b17023SJohn Marino 	{
1231e4b17023SJohn Marino 	  if (!DECL_INITIAL (fn))
1232e4b17023SJohn Marino 	    {
1233e4b17023SJohn Marino 	      /* Not defined yet; check again at EOF.  */
1234e4b17023SJohn Marino 	      pending_noexcept *p
1235e4b17023SJohn Marino 		= VEC_safe_push (pending_noexcept, gc,
1236e4b17023SJohn Marino 				 pending_noexcept_checks, NULL);
1237e4b17023SJohn Marino 	      p->fn = fn;
1238e4b17023SJohn Marino 	      p->loc = input_location;
1239e4b17023SJohn Marino 	    }
1240e4b17023SJohn Marino 	  else
1241e4b17023SJohn Marino 	    maybe_noexcept_warning (fn);
1242e4b17023SJohn Marino 	}
1243e4b17023SJohn Marino       return false;
1244e4b17023SJohn Marino     }
1245e4b17023SJohn Marino   else
1246e4b17023SJohn Marino     return true;
1247e4b17023SJohn Marino }
1248e4b17023SJohn Marino 
1249e4b17023SJohn Marino /* Return true iff SPEC is throw() or noexcept(true).  */
1250e4b17023SJohn Marino 
1251e4b17023SJohn Marino bool
nothrow_spec_p(const_tree spec)1252e4b17023SJohn Marino nothrow_spec_p (const_tree spec)
1253e4b17023SJohn Marino {
1254e4b17023SJohn Marino   gcc_assert (!DEFERRED_NOEXCEPT_SPEC_P (spec));
1255e4b17023SJohn Marino   if (spec == NULL_TREE
1256e4b17023SJohn Marino       || TREE_VALUE (spec) != NULL_TREE
1257e4b17023SJohn Marino       || spec == noexcept_false_spec)
1258e4b17023SJohn Marino     return false;
1259e4b17023SJohn Marino   if (TREE_PURPOSE (spec) == NULL_TREE
1260e4b17023SJohn Marino       || spec == noexcept_true_spec)
1261e4b17023SJohn Marino     return true;
1262e4b17023SJohn Marino   gcc_assert (processing_template_decl
1263e4b17023SJohn Marino 	      || TREE_PURPOSE (spec) == error_mark_node);
1264e4b17023SJohn Marino   return false;
1265e4b17023SJohn Marino }
1266e4b17023SJohn Marino 
1267e4b17023SJohn Marino /* For FUNCTION_TYPE or METHOD_TYPE, true if NODE is noexcept.  This is the
1268e4b17023SJohn Marino    case for things declared noexcept(true) and, with -fnothrow-opt, for
1269e4b17023SJohn Marino    throw() functions.  */
1270e4b17023SJohn Marino 
1271e4b17023SJohn Marino bool
type_noexcept_p(const_tree type)1272e4b17023SJohn Marino type_noexcept_p (const_tree type)
1273e4b17023SJohn Marino {
1274e4b17023SJohn Marino   tree spec = TYPE_RAISES_EXCEPTIONS (type);
1275e4b17023SJohn Marino   gcc_assert (!DEFERRED_NOEXCEPT_SPEC_P (spec));
1276e4b17023SJohn Marino   if (flag_nothrow_opt)
1277e4b17023SJohn Marino     return nothrow_spec_p (spec);
1278e4b17023SJohn Marino   else
1279e4b17023SJohn Marino     return spec == noexcept_true_spec;
1280e4b17023SJohn Marino }
1281e4b17023SJohn Marino 
1282e4b17023SJohn Marino /* For FUNCTION_TYPE or METHOD_TYPE, true if NODE can throw any type,
1283e4b17023SJohn Marino    i.e. no exception-specification or noexcept(false).  */
1284e4b17023SJohn Marino 
1285e4b17023SJohn Marino bool
type_throw_all_p(const_tree type)1286e4b17023SJohn Marino type_throw_all_p (const_tree type)
1287e4b17023SJohn Marino {
1288e4b17023SJohn Marino   tree spec = TYPE_RAISES_EXCEPTIONS (type);
1289e4b17023SJohn Marino   gcc_assert (!DEFERRED_NOEXCEPT_SPEC_P (spec));
1290e4b17023SJohn Marino   return spec == NULL_TREE || spec == noexcept_false_spec;
1291e4b17023SJohn Marino }
1292e4b17023SJohn Marino 
1293e4b17023SJohn Marino /* Create a representation of the noexcept-specification with
1294e4b17023SJohn Marino    constant-expression of EXPR.  COMPLAIN is as for tsubst.  */
1295e4b17023SJohn Marino 
1296e4b17023SJohn Marino tree
build_noexcept_spec(tree expr,int complain)1297e4b17023SJohn Marino build_noexcept_spec (tree expr, int complain)
1298e4b17023SJohn Marino {
1299e4b17023SJohn Marino   /* This isn't part of the signature, so don't bother trying to evaluate
1300e4b17023SJohn Marino      it until instantiation.  */
1301e4b17023SJohn Marino   if (!processing_template_decl && TREE_CODE (expr) != DEFERRED_NOEXCEPT)
1302e4b17023SJohn Marino     {
1303e4b17023SJohn Marino       expr = perform_implicit_conversion_flags (boolean_type_node, expr,
1304e4b17023SJohn Marino 						complain,
1305e4b17023SJohn Marino 						LOOKUP_NORMAL);
1306e4b17023SJohn Marino       expr = cxx_constant_value (expr);
1307e4b17023SJohn Marino     }
13085ce9237cSJohn Marino   if (TREE_CODE (expr) == INTEGER_CST)
13095ce9237cSJohn Marino     {
13105ce9237cSJohn Marino       if (operand_equal_p (expr, boolean_true_node, 0))
1311e4b17023SJohn Marino 	return noexcept_true_spec;
13125ce9237cSJohn Marino       else
13135ce9237cSJohn Marino 	{
13145ce9237cSJohn Marino 	  gcc_checking_assert (operand_equal_p (expr, boolean_false_node, 0));
1315e4b17023SJohn Marino 	  return noexcept_false_spec;
13165ce9237cSJohn Marino 	}
13175ce9237cSJohn Marino     }
1318e4b17023SJohn Marino   else if (expr == error_mark_node)
1319e4b17023SJohn Marino     return error_mark_node;
1320e4b17023SJohn Marino   else
1321e4b17023SJohn Marino     {
13225ce9237cSJohn Marino       gcc_assert (processing_template_decl
1323e4b17023SJohn Marino 		  || TREE_CODE (expr) == DEFERRED_NOEXCEPT);
1324e4b17023SJohn Marino       return build_tree_list (expr, NULL_TREE);
1325e4b17023SJohn Marino     }
1326e4b17023SJohn Marino }
1327e4b17023SJohn Marino 
1328e4b17023SJohn Marino #include "gt-cp-except.h"
1329