xref: /openbsd-src/gnu/gcc/gcc/cp/except.c (revision 404b540a9034ac75a6199ad1a32d1bbc7a0d4210)
1*404b540aSrobert /* Handle exceptional things in C++.
2*404b540aSrobert    Copyright (C) 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
3*404b540aSrobert    2000, 2001, 2002, 2003, 2004, 2005  Free Software Foundation, Inc.
4*404b540aSrobert    Contributed by Michael Tiemann <tiemann@cygnus.com>
5*404b540aSrobert    Rewritten by Mike Stump <mrs@cygnus.com>, based upon an
6*404b540aSrobert    initial re-implementation courtesy Tad Hunt.
7*404b540aSrobert 
8*404b540aSrobert This file is part of GCC.
9*404b540aSrobert 
10*404b540aSrobert GCC is free software; you can redistribute it and/or modify
11*404b540aSrobert it under the terms of the GNU General Public License as published by
12*404b540aSrobert the Free Software Foundation; either version 2, or (at your option)
13*404b540aSrobert any later version.
14*404b540aSrobert 
15*404b540aSrobert GCC is distributed in the hope that it will be useful,
16*404b540aSrobert but WITHOUT ANY WARRANTY; without even the implied warranty of
17*404b540aSrobert MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18*404b540aSrobert GNU General Public License for more details.
19*404b540aSrobert 
20*404b540aSrobert You should have received a copy of the GNU General Public License
21*404b540aSrobert along with GCC; see the file COPYING.  If not, write to
22*404b540aSrobert the Free Software Foundation, 51 Franklin Street, Fifth Floor,
23*404b540aSrobert Boston, MA 02110-1301, USA.  */
24*404b540aSrobert 
25*404b540aSrobert 
26*404b540aSrobert #include "config.h"
27*404b540aSrobert #include "system.h"
28*404b540aSrobert #include "coretypes.h"
29*404b540aSrobert #include "tm.h"
30*404b540aSrobert #include "tree.h"
31*404b540aSrobert #include "rtl.h"
32*404b540aSrobert #include "expr.h"
33*404b540aSrobert #include "libfuncs.h"
34*404b540aSrobert #include "cp-tree.h"
35*404b540aSrobert #include "flags.h"
36*404b540aSrobert #include "output.h"
37*404b540aSrobert #include "except.h"
38*404b540aSrobert #include "toplev.h"
39*404b540aSrobert #include "tree-inline.h"
40*404b540aSrobert #include "tree-iterator.h"
41*404b540aSrobert #include "target.h"
42*404b540aSrobert 
43*404b540aSrobert static void push_eh_cleanup (tree);
44*404b540aSrobert static tree prepare_eh_type (tree);
45*404b540aSrobert static tree build_eh_type_type (tree);
46*404b540aSrobert static tree do_begin_catch (void);
47*404b540aSrobert static int dtor_nothrow (tree);
48*404b540aSrobert static tree do_end_catch (tree);
49*404b540aSrobert static bool decl_is_java_type (tree decl, int err);
50*404b540aSrobert static void initialize_handler_parm (tree, tree);
51*404b540aSrobert static tree do_allocate_exception (tree);
52*404b540aSrobert static tree wrap_cleanups_r (tree *, int *, void *);
53*404b540aSrobert static int complete_ptr_ref_or_void_ptr_p (tree, tree);
54*404b540aSrobert static bool is_admissible_throw_operand (tree);
55*404b540aSrobert static int can_convert_eh (tree, tree);
56*404b540aSrobert static tree cp_protect_cleanup_actions (void);
57*404b540aSrobert 
58*404b540aSrobert /* Sets up all the global eh stuff that needs to be initialized at the
59*404b540aSrobert    start of compilation.  */
60*404b540aSrobert 
61*404b540aSrobert void
init_exception_processing(void)62*404b540aSrobert init_exception_processing (void)
63*404b540aSrobert {
64*404b540aSrobert   tree tmp;
65*404b540aSrobert 
66*404b540aSrobert   /* void std::terminate (); */
67*404b540aSrobert   push_namespace (std_identifier);
68*404b540aSrobert   tmp = build_function_type (void_type_node, void_list_node);
69*404b540aSrobert   terminate_node = build_cp_library_fn_ptr ("terminate", tmp);
70*404b540aSrobert   TREE_THIS_VOLATILE (terminate_node) = 1;
71*404b540aSrobert   TREE_NOTHROW (terminate_node) = 1;
72*404b540aSrobert   pop_namespace ();
73*404b540aSrobert 
74*404b540aSrobert   /* void __cxa_call_unexpected(void *); */
75*404b540aSrobert   tmp = tree_cons (NULL_TREE, ptr_type_node, void_list_node);
76*404b540aSrobert   tmp = build_function_type (void_type_node, tmp);
77*404b540aSrobert   call_unexpected_node
78*404b540aSrobert     = push_throw_library_fn (get_identifier ("__cxa_call_unexpected"), tmp);
79*404b540aSrobert 
80*404b540aSrobert   eh_personality_libfunc = init_one_libfunc (USING_SJLJ_EXCEPTIONS
81*404b540aSrobert 					     ? "__gxx_personality_sj0"
82*404b540aSrobert 					     : "__gxx_personality_v0");
83*404b540aSrobert   if (targetm.arm_eabi_unwinder)
84*404b540aSrobert     unwind_resume_libfunc = init_one_libfunc ("__cxa_end_cleanup");
85*404b540aSrobert   else
86*404b540aSrobert     default_init_unwind_resume_libfunc ();
87*404b540aSrobert 
88*404b540aSrobert   lang_eh_runtime_type = build_eh_type_type;
89*404b540aSrobert   lang_protect_cleanup_actions = &cp_protect_cleanup_actions;
90*404b540aSrobert }
91*404b540aSrobert 
92*404b540aSrobert /* Returns an expression to be executed if an unhandled exception is
93*404b540aSrobert    propagated out of a cleanup region.  */
94*404b540aSrobert 
95*404b540aSrobert static tree
cp_protect_cleanup_actions(void)96*404b540aSrobert cp_protect_cleanup_actions (void)
97*404b540aSrobert {
98*404b540aSrobert   /* [except.terminate]
99*404b540aSrobert 
100*404b540aSrobert      When the destruction of an object during stack unwinding exits
101*404b540aSrobert      using an exception ... void terminate(); is called.  */
102*404b540aSrobert   return build_call (terminate_node, NULL_TREE);
103*404b540aSrobert }
104*404b540aSrobert 
105*404b540aSrobert static tree
prepare_eh_type(tree type)106*404b540aSrobert prepare_eh_type (tree type)
107*404b540aSrobert {
108*404b540aSrobert   if (type == NULL_TREE)
109*404b540aSrobert     return type;
110*404b540aSrobert   if (type == error_mark_node)
111*404b540aSrobert     return error_mark_node;
112*404b540aSrobert 
113*404b540aSrobert   /* peel back references, so they match.  */
114*404b540aSrobert   type = non_reference (type);
115*404b540aSrobert 
116*404b540aSrobert   /* Peel off cv qualifiers.  */
117*404b540aSrobert   type = TYPE_MAIN_VARIANT (type);
118*404b540aSrobert 
119*404b540aSrobert   return type;
120*404b540aSrobert }
121*404b540aSrobert 
122*404b540aSrobert /* Return the type info for TYPE as used by EH machinery.  */
123*404b540aSrobert tree
eh_type_info(tree type)124*404b540aSrobert eh_type_info (tree type)
125*404b540aSrobert {
126*404b540aSrobert   tree exp;
127*404b540aSrobert 
128*404b540aSrobert   if (type == NULL_TREE || type == error_mark_node)
129*404b540aSrobert     return type;
130*404b540aSrobert 
131*404b540aSrobert   if (decl_is_java_type (type, 0))
132*404b540aSrobert     exp = build_java_class_ref (TREE_TYPE (type));
133*404b540aSrobert   else
134*404b540aSrobert     exp = get_tinfo_decl (type);
135*404b540aSrobert 
136*404b540aSrobert   return exp;
137*404b540aSrobert }
138*404b540aSrobert 
139*404b540aSrobert /* Build the address of a typeinfo decl for use in the runtime
140*404b540aSrobert    matching field of the exception model.  */
141*404b540aSrobert 
142*404b540aSrobert static tree
build_eh_type_type(tree type)143*404b540aSrobert build_eh_type_type (tree type)
144*404b540aSrobert {
145*404b540aSrobert   tree exp = eh_type_info (type);
146*404b540aSrobert 
147*404b540aSrobert   if (!exp)
148*404b540aSrobert     return NULL;
149*404b540aSrobert 
150*404b540aSrobert   mark_used (exp);
151*404b540aSrobert 
152*404b540aSrobert   return convert (ptr_type_node, build_address (exp));
153*404b540aSrobert }
154*404b540aSrobert 
155*404b540aSrobert tree
build_exc_ptr(void)156*404b540aSrobert build_exc_ptr (void)
157*404b540aSrobert {
158*404b540aSrobert   return build0 (EXC_PTR_EXPR, ptr_type_node);
159*404b540aSrobert }
160*404b540aSrobert 
161*404b540aSrobert /* Build up a call to __cxa_get_exception_ptr so that we can build a
162*404b540aSrobert    copy constructor for the thrown object.  */
163*404b540aSrobert 
164*404b540aSrobert static tree
do_get_exception_ptr(void)165*404b540aSrobert do_get_exception_ptr (void)
166*404b540aSrobert {
167*404b540aSrobert   tree fn;
168*404b540aSrobert 
169*404b540aSrobert   fn = get_identifier ("__cxa_get_exception_ptr");
170*404b540aSrobert   if (!get_global_value_if_present (fn, &fn))
171*404b540aSrobert     {
172*404b540aSrobert       /* Declare void* __cxa_get_exception_ptr (void *).  */
173*404b540aSrobert       tree tmp = tree_cons (NULL_TREE, ptr_type_node, void_list_node);
174*404b540aSrobert       fn = push_library_fn (fn, build_function_type (ptr_type_node, tmp));
175*404b540aSrobert     }
176*404b540aSrobert 
177*404b540aSrobert   return build_function_call (fn, tree_cons (NULL_TREE, build_exc_ptr (),
178*404b540aSrobert 					     NULL_TREE));
179*404b540aSrobert }
180*404b540aSrobert 
181*404b540aSrobert /* Build up a call to __cxa_begin_catch, to tell the runtime that the
182*404b540aSrobert    exception has been handled.  */
183*404b540aSrobert 
184*404b540aSrobert static tree
do_begin_catch(void)185*404b540aSrobert do_begin_catch (void)
186*404b540aSrobert {
187*404b540aSrobert   tree fn;
188*404b540aSrobert 
189*404b540aSrobert   fn = get_identifier ("__cxa_begin_catch");
190*404b540aSrobert   if (!get_global_value_if_present (fn, &fn))
191*404b540aSrobert     {
192*404b540aSrobert       /* Declare void* __cxa_begin_catch (void *).  */
193*404b540aSrobert       tree tmp = tree_cons (NULL_TREE, ptr_type_node, void_list_node);
194*404b540aSrobert       fn = push_library_fn (fn, build_function_type (ptr_type_node, tmp));
195*404b540aSrobert     }
196*404b540aSrobert 
197*404b540aSrobert   return build_function_call (fn, tree_cons (NULL_TREE, build_exc_ptr (),
198*404b540aSrobert 					     NULL_TREE));
199*404b540aSrobert }
200*404b540aSrobert 
201*404b540aSrobert /* Returns nonzero if cleaning up an exception of type TYPE (which can be
202*404b540aSrobert    NULL_TREE for a ... handler) will not throw an exception.  */
203*404b540aSrobert 
204*404b540aSrobert static int
dtor_nothrow(tree type)205*404b540aSrobert dtor_nothrow (tree type)
206*404b540aSrobert {
207*404b540aSrobert   if (type == NULL_TREE)
208*404b540aSrobert     return 0;
209*404b540aSrobert 
210*404b540aSrobert   if (!CLASS_TYPE_P (type))
211*404b540aSrobert     return 1;
212*404b540aSrobert 
213*404b540aSrobert   if (CLASSTYPE_LAZY_DESTRUCTOR (type))
214*404b540aSrobert     lazily_declare_fn (sfk_destructor, type);
215*404b540aSrobert 
216*404b540aSrobert   return TREE_NOTHROW (CLASSTYPE_DESTRUCTORS (type));
217*404b540aSrobert }
218*404b540aSrobert 
219*404b540aSrobert /* Build up a call to __cxa_end_catch, to destroy the exception object
220*404b540aSrobert    for the current catch block if no others are currently using it.  */
221*404b540aSrobert 
222*404b540aSrobert static tree
do_end_catch(tree type)223*404b540aSrobert do_end_catch (tree type)
224*404b540aSrobert {
225*404b540aSrobert   tree fn, cleanup;
226*404b540aSrobert 
227*404b540aSrobert   fn = get_identifier ("__cxa_end_catch");
228*404b540aSrobert   if (!get_global_value_if_present (fn, &fn))
229*404b540aSrobert     {
230*404b540aSrobert       /* Declare void __cxa_end_catch ().  */
231*404b540aSrobert       fn = push_void_library_fn (fn, void_list_node);
232*404b540aSrobert       /* This can throw if the destructor for the exception throws.  */
233*404b540aSrobert       TREE_NOTHROW (fn) = 0;
234*404b540aSrobert     }
235*404b540aSrobert 
236*404b540aSrobert   cleanup = build_function_call (fn, NULL_TREE);
237*404b540aSrobert   TREE_NOTHROW (cleanup) = dtor_nothrow (type);
238*404b540aSrobert 
239*404b540aSrobert   return cleanup;
240*404b540aSrobert }
241*404b540aSrobert 
242*404b540aSrobert /* This routine creates the cleanup for the current exception.  */
243*404b540aSrobert 
244*404b540aSrobert static void
push_eh_cleanup(tree type)245*404b540aSrobert push_eh_cleanup (tree type)
246*404b540aSrobert {
247*404b540aSrobert   finish_decl_cleanup (NULL_TREE, do_end_catch (type));
248*404b540aSrobert }
249*404b540aSrobert 
250*404b540aSrobert /* Return nonzero value if DECL is a Java type suitable for catch or
251*404b540aSrobert    throw.  */
252*404b540aSrobert 
253*404b540aSrobert static bool
decl_is_java_type(tree decl,int err)254*404b540aSrobert decl_is_java_type (tree decl, int err)
255*404b540aSrobert {
256*404b540aSrobert   bool r = (TREE_CODE (decl) == POINTER_TYPE
257*404b540aSrobert 	    && TREE_CODE (TREE_TYPE (decl)) == RECORD_TYPE
258*404b540aSrobert 	    && TYPE_FOR_JAVA (TREE_TYPE (decl)));
259*404b540aSrobert 
260*404b540aSrobert   if (err)
261*404b540aSrobert     {
262*404b540aSrobert       if (TREE_CODE (decl) == REFERENCE_TYPE
263*404b540aSrobert 	  && TREE_CODE (TREE_TYPE (decl)) == RECORD_TYPE
264*404b540aSrobert 	  && TYPE_FOR_JAVA (TREE_TYPE (decl)))
265*404b540aSrobert 	{
266*404b540aSrobert 	  /* Can't throw a reference.  */
267*404b540aSrobert 	  error ("type %qT is disallowed in Java %<throw%> or %<catch%>",
268*404b540aSrobert 		 decl);
269*404b540aSrobert 	}
270*404b540aSrobert 
271*404b540aSrobert       if (r)
272*404b540aSrobert 	{
273*404b540aSrobert 	  tree jthrow_node
274*404b540aSrobert 	    = IDENTIFIER_GLOBAL_VALUE (get_identifier ("jthrowable"));
275*404b540aSrobert 
276*404b540aSrobert 	  if (jthrow_node == NULL_TREE)
277*404b540aSrobert 	    fatal_error
278*404b540aSrobert 	      ("call to Java %<catch%> or %<throw%> with %<jthrowable%> undefined");
279*404b540aSrobert 
280*404b540aSrobert 	  jthrow_node = TREE_TYPE (TREE_TYPE (jthrow_node));
281*404b540aSrobert 
282*404b540aSrobert 	  if (! DERIVED_FROM_P (jthrow_node, TREE_TYPE (decl)))
283*404b540aSrobert 	    {
284*404b540aSrobert 	      /* Thrown object must be a Throwable.  */
285*404b540aSrobert 	      error ("type %qT is not derived from %<java::lang::Throwable%>",
286*404b540aSrobert 		     TREE_TYPE (decl));
287*404b540aSrobert 	    }
288*404b540aSrobert 	}
289*404b540aSrobert     }
290*404b540aSrobert 
291*404b540aSrobert   return r;
292*404b540aSrobert }
293*404b540aSrobert 
294*404b540aSrobert /* Select the personality routine to be used for exception handling,
295*404b540aSrobert    or issue an error if we need two different ones in the same
296*404b540aSrobert    translation unit.
297*404b540aSrobert    ??? At present eh_personality_libfunc is set to
298*404b540aSrobert    __gxx_personality_(sj|v)0 in init_exception_processing - should it
299*404b540aSrobert    be done here instead?  */
300*404b540aSrobert void
choose_personality_routine(enum languages lang)301*404b540aSrobert choose_personality_routine (enum languages lang)
302*404b540aSrobert {
303*404b540aSrobert   static enum {
304*404b540aSrobert     chose_none,
305*404b540aSrobert     chose_cpp,
306*404b540aSrobert     chose_java,
307*404b540aSrobert     gave_error
308*404b540aSrobert   } state;
309*404b540aSrobert 
310*404b540aSrobert   switch (state)
311*404b540aSrobert     {
312*404b540aSrobert     case gave_error:
313*404b540aSrobert       return;
314*404b540aSrobert 
315*404b540aSrobert     case chose_cpp:
316*404b540aSrobert       if (lang != lang_cplusplus)
317*404b540aSrobert 	goto give_error;
318*404b540aSrobert       return;
319*404b540aSrobert 
320*404b540aSrobert     case chose_java:
321*404b540aSrobert       if (lang != lang_java)
322*404b540aSrobert 	goto give_error;
323*404b540aSrobert       return;
324*404b540aSrobert 
325*404b540aSrobert     case chose_none:
326*404b540aSrobert       ; /* Proceed to language selection.  */
327*404b540aSrobert     }
328*404b540aSrobert 
329*404b540aSrobert   switch (lang)
330*404b540aSrobert     {
331*404b540aSrobert     case lang_cplusplus:
332*404b540aSrobert       state = chose_cpp;
333*404b540aSrobert       break;
334*404b540aSrobert 
335*404b540aSrobert     case lang_java:
336*404b540aSrobert       state = chose_java;
337*404b540aSrobert       eh_personality_libfunc = init_one_libfunc (USING_SJLJ_EXCEPTIONS
338*404b540aSrobert 						 ? "__gcj_personality_sj0"
339*404b540aSrobert 						 : "__gcj_personality_v0");
340*404b540aSrobert       break;
341*404b540aSrobert 
342*404b540aSrobert     default:
343*404b540aSrobert       gcc_unreachable ();
344*404b540aSrobert     }
345*404b540aSrobert   return;
346*404b540aSrobert 
347*404b540aSrobert  give_error:
348*404b540aSrobert   error ("mixing C++ and Java catches in a single translation unit");
349*404b540aSrobert   state = gave_error;
350*404b540aSrobert }
351*404b540aSrobert 
352*404b540aSrobert /* Initialize the catch parameter DECL.  */
353*404b540aSrobert 
354*404b540aSrobert static void
initialize_handler_parm(tree decl,tree exp)355*404b540aSrobert initialize_handler_parm (tree decl, tree exp)
356*404b540aSrobert {
357*404b540aSrobert   tree init;
358*404b540aSrobert   tree init_type;
359*404b540aSrobert 
360*404b540aSrobert   /* Make sure we mark the catch param as used, otherwise we'll get a
361*404b540aSrobert      warning about an unused ((anonymous)).  */
362*404b540aSrobert   TREE_USED (decl) = 1;
363*404b540aSrobert 
364*404b540aSrobert   /* Figure out the type that the initializer is.  Pointers are returned
365*404b540aSrobert      adjusted by value from __cxa_begin_catch.  Others are returned by
366*404b540aSrobert      reference.  */
367*404b540aSrobert   init_type = TREE_TYPE (decl);
368*404b540aSrobert   if (!POINTER_TYPE_P (init_type))
369*404b540aSrobert     init_type = build_reference_type (init_type);
370*404b540aSrobert 
371*404b540aSrobert   choose_personality_routine (decl_is_java_type (init_type, 0)
372*404b540aSrobert 			      ? lang_java : lang_cplusplus);
373*404b540aSrobert 
374*404b540aSrobert   /* Since pointers are passed by value, initialize a reference to
375*404b540aSrobert      pointer catch parm with the address of the temporary.  */
376*404b540aSrobert   if (TREE_CODE (init_type) == REFERENCE_TYPE
377*404b540aSrobert       && TYPE_PTR_P (TREE_TYPE (init_type)))
378*404b540aSrobert     exp = build_unary_op (ADDR_EXPR, exp, 1);
379*404b540aSrobert 
380*404b540aSrobert   exp = ocp_convert (init_type, exp, CONV_IMPLICIT|CONV_FORCE_TEMP, 0);
381*404b540aSrobert 
382*404b540aSrobert   init = convert_from_reference (exp);
383*404b540aSrobert 
384*404b540aSrobert   /* If the constructor for the catch parm exits via an exception, we
385*404b540aSrobert      must call terminate.  See eh23.C.  */
386*404b540aSrobert   if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl)))
387*404b540aSrobert     {
388*404b540aSrobert       /* Generate the copy constructor call directly so we can wrap it.
389*404b540aSrobert 	 See also expand_default_init.  */
390*404b540aSrobert       init = ocp_convert (TREE_TYPE (decl), init,
391*404b540aSrobert 			  CONV_IMPLICIT|CONV_FORCE_TEMP, 0);
392*404b540aSrobert       init = build1 (MUST_NOT_THROW_EXPR, TREE_TYPE (init), init);
393*404b540aSrobert     }
394*404b540aSrobert 
395*404b540aSrobert   decl = pushdecl (decl);
396*404b540aSrobert 
397*404b540aSrobert   start_decl_1 (decl, true);
398*404b540aSrobert   cp_finish_decl (decl, init, /*init_const_expr_p=*/false, NULL_TREE,
399*404b540aSrobert 		  LOOKUP_ONLYCONVERTING|DIRECT_BIND);
400*404b540aSrobert }
401*404b540aSrobert 
402*404b540aSrobert /* Call this to start a catch block.  DECL is the catch parameter.  */
403*404b540aSrobert 
404*404b540aSrobert tree
expand_start_catch_block(tree decl)405*404b540aSrobert expand_start_catch_block (tree decl)
406*404b540aSrobert {
407*404b540aSrobert   tree exp;
408*404b540aSrobert   tree type;
409*404b540aSrobert 
410*404b540aSrobert   if (! doing_eh (1))
411*404b540aSrobert     return NULL_TREE;
412*404b540aSrobert 
413*404b540aSrobert   /* Make sure this declaration is reasonable.  */
414*404b540aSrobert   if (decl && !complete_ptr_ref_or_void_ptr_p (TREE_TYPE (decl), NULL_TREE))
415*404b540aSrobert     decl = error_mark_node;
416*404b540aSrobert 
417*404b540aSrobert   if (decl)
418*404b540aSrobert     type = prepare_eh_type (TREE_TYPE (decl));
419*404b540aSrobert   else
420*404b540aSrobert     type = NULL_TREE;
421*404b540aSrobert 
422*404b540aSrobert   if (decl && decl_is_java_type (type, 1))
423*404b540aSrobert     {
424*404b540aSrobert       /* Java only passes object via pointer and doesn't require
425*404b540aSrobert 	 adjusting.  The java object is immediately before the
426*404b540aSrobert 	 generic exception header.  */
427*404b540aSrobert       exp = build_exc_ptr ();
428*404b540aSrobert       exp = build1 (NOP_EXPR, build_pointer_type (type), exp);
429*404b540aSrobert       exp = build2 (MINUS_EXPR, TREE_TYPE (exp), exp,
430*404b540aSrobert 		    TYPE_SIZE_UNIT (TREE_TYPE (exp)));
431*404b540aSrobert       exp = build_indirect_ref (exp, NULL);
432*404b540aSrobert       initialize_handler_parm (decl, exp);
433*404b540aSrobert       return type;
434*404b540aSrobert     }
435*404b540aSrobert 
436*404b540aSrobert   /* Call __cxa_end_catch at the end of processing the exception.  */
437*404b540aSrobert   push_eh_cleanup (type);
438*404b540aSrobert 
439*404b540aSrobert   /* If there's no decl at all, then all we need to do is make sure
440*404b540aSrobert      to tell the runtime that we've begun handling the exception.  */
441*404b540aSrobert   if (decl == NULL || decl == error_mark_node)
442*404b540aSrobert     finish_expr_stmt (do_begin_catch ());
443*404b540aSrobert 
444*404b540aSrobert   /* If the C++ object needs constructing, we need to do that before
445*404b540aSrobert      calling __cxa_begin_catch, so that std::uncaught_exception gets
446*404b540aSrobert      the right value during the copy constructor.  */
447*404b540aSrobert   else if (flag_use_cxa_get_exception_ptr
448*404b540aSrobert 	   && TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl)))
449*404b540aSrobert     {
450*404b540aSrobert       exp = do_get_exception_ptr ();
451*404b540aSrobert       initialize_handler_parm (decl, exp);
452*404b540aSrobert       finish_expr_stmt (do_begin_catch ());
453*404b540aSrobert     }
454*404b540aSrobert 
455*404b540aSrobert   /* Otherwise the type uses a bitwise copy, and we don't have to worry
456*404b540aSrobert      about the value of std::uncaught_exception and therefore can do the
457*404b540aSrobert      copy with the return value of __cxa_end_catch instead.  */
458*404b540aSrobert   else
459*404b540aSrobert     {
460*404b540aSrobert       tree init = do_begin_catch ();
461*404b540aSrobert       tree init_type = type;
462*404b540aSrobert 
463*404b540aSrobert       /* Pointers are passed by values, everything else by reference.  */
464*404b540aSrobert       if (!TYPE_PTR_P (type))
465*404b540aSrobert 	init_type = build_pointer_type (type);
466*404b540aSrobert       if (init_type != TREE_TYPE (init))
467*404b540aSrobert 	init = build1 (NOP_EXPR, init_type, init);
468*404b540aSrobert       exp = create_temporary_var (init_type);
469*404b540aSrobert       DECL_REGISTER (exp) = 1;
470*404b540aSrobert       cp_finish_decl (exp, init, /*init_const_expr=*/false,
471*404b540aSrobert 		      NULL_TREE, LOOKUP_ONLYCONVERTING);
472*404b540aSrobert       initialize_handler_parm (decl, exp);
473*404b540aSrobert     }
474*404b540aSrobert 
475*404b540aSrobert   return type;
476*404b540aSrobert }
477*404b540aSrobert 
478*404b540aSrobert 
479*404b540aSrobert /* Call this to end a catch block.  Its responsible for emitting the
480*404b540aSrobert    code to handle jumping back to the correct place, and for emitting
481*404b540aSrobert    the label to jump to if this catch block didn't match.  */
482*404b540aSrobert 
483*404b540aSrobert void
expand_end_catch_block(void)484*404b540aSrobert expand_end_catch_block (void)
485*404b540aSrobert {
486*404b540aSrobert   if (! doing_eh (1))
487*404b540aSrobert     return;
488*404b540aSrobert 
489*404b540aSrobert   /* The exception being handled is rethrown if control reaches the end of
490*404b540aSrobert      a handler of the function-try-block of a constructor or destructor.  */
491*404b540aSrobert   if (in_function_try_handler
492*404b540aSrobert       && (DECL_CONSTRUCTOR_P (current_function_decl)
493*404b540aSrobert 	  || DECL_DESTRUCTOR_P (current_function_decl)))
494*404b540aSrobert     finish_expr_stmt (build_throw (NULL_TREE));
495*404b540aSrobert }
496*404b540aSrobert 
497*404b540aSrobert tree
begin_eh_spec_block(void)498*404b540aSrobert begin_eh_spec_block (void)
499*404b540aSrobert {
500*404b540aSrobert   tree r = build_stmt (EH_SPEC_BLOCK, NULL_TREE, NULL_TREE);
501*404b540aSrobert   add_stmt (r);
502*404b540aSrobert   EH_SPEC_STMTS (r) = push_stmt_list ();
503*404b540aSrobert   return r;
504*404b540aSrobert }
505*404b540aSrobert 
506*404b540aSrobert void
finish_eh_spec_block(tree raw_raises,tree eh_spec_block)507*404b540aSrobert finish_eh_spec_block (tree raw_raises, tree eh_spec_block)
508*404b540aSrobert {
509*404b540aSrobert   tree raises;
510*404b540aSrobert 
511*404b540aSrobert   EH_SPEC_STMTS (eh_spec_block) = pop_stmt_list (EH_SPEC_STMTS (eh_spec_block));
512*404b540aSrobert 
513*404b540aSrobert   /* Strip cv quals, etc, from the specification types.  */
514*404b540aSrobert   for (raises = NULL_TREE;
515*404b540aSrobert        raw_raises && TREE_VALUE (raw_raises);
516*404b540aSrobert        raw_raises = TREE_CHAIN (raw_raises))
517*404b540aSrobert     {
518*404b540aSrobert       tree type = prepare_eh_type (TREE_VALUE (raw_raises));
519*404b540aSrobert       tree tinfo = eh_type_info (type);
520*404b540aSrobert 
521*404b540aSrobert       mark_used (tinfo);
522*404b540aSrobert       raises = tree_cons (NULL_TREE, type, raises);
523*404b540aSrobert     }
524*404b540aSrobert 
525*404b540aSrobert   EH_SPEC_RAISES (eh_spec_block) = raises;
526*404b540aSrobert }
527*404b540aSrobert 
528*404b540aSrobert /* Return a pointer to a buffer for an exception object of type TYPE.  */
529*404b540aSrobert 
530*404b540aSrobert static tree
do_allocate_exception(tree type)531*404b540aSrobert do_allocate_exception (tree type)
532*404b540aSrobert {
533*404b540aSrobert   tree fn;
534*404b540aSrobert 
535*404b540aSrobert   fn = get_identifier ("__cxa_allocate_exception");
536*404b540aSrobert   if (!get_global_value_if_present (fn, &fn))
537*404b540aSrobert     {
538*404b540aSrobert       /* Declare void *__cxa_allocate_exception(size_t).  */
539*404b540aSrobert       tree tmp = tree_cons (NULL_TREE, size_type_node, void_list_node);
540*404b540aSrobert       fn = push_library_fn (fn, build_function_type (ptr_type_node, tmp));
541*404b540aSrobert     }
542*404b540aSrobert 
543*404b540aSrobert   return build_function_call (fn, tree_cons (NULL_TREE, size_in_bytes (type),
544*404b540aSrobert 					     NULL_TREE));
545*404b540aSrobert }
546*404b540aSrobert 
547*404b540aSrobert /* Call __cxa_free_exception from a cleanup.  This is never invoked
548*404b540aSrobert    directly, but see the comment for stabilize_throw_expr.  */
549*404b540aSrobert 
550*404b540aSrobert static tree
do_free_exception(tree ptr)551*404b540aSrobert do_free_exception (tree ptr)
552*404b540aSrobert {
553*404b540aSrobert   tree fn;
554*404b540aSrobert 
555*404b540aSrobert   fn = get_identifier ("__cxa_free_exception");
556*404b540aSrobert   if (!get_global_value_if_present (fn, &fn))
557*404b540aSrobert     {
558*404b540aSrobert       /* Declare void __cxa_free_exception (void *).  */
559*404b540aSrobert       fn = push_void_library_fn (fn, tree_cons (NULL_TREE, ptr_type_node,
560*404b540aSrobert 						void_list_node));
561*404b540aSrobert     }
562*404b540aSrobert 
563*404b540aSrobert   return build_function_call (fn, tree_cons (NULL_TREE, ptr, NULL_TREE));
564*404b540aSrobert }
565*404b540aSrobert 
566*404b540aSrobert /* Wrap all cleanups for TARGET_EXPRs in MUST_NOT_THROW_EXPR.
567*404b540aSrobert    Called from build_throw via walk_tree_without_duplicates.  */
568*404b540aSrobert 
569*404b540aSrobert static tree
wrap_cleanups_r(tree * tp,int * walk_subtrees ATTRIBUTE_UNUSED,void * data ATTRIBUTE_UNUSED)570*404b540aSrobert wrap_cleanups_r (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED,
571*404b540aSrobert 		 void *data ATTRIBUTE_UNUSED)
572*404b540aSrobert {
573*404b540aSrobert   tree exp = *tp;
574*404b540aSrobert   tree cleanup;
575*404b540aSrobert 
576*404b540aSrobert   /* Don't walk into types.  */
577*404b540aSrobert   if (TYPE_P (exp))
578*404b540aSrobert     {
579*404b540aSrobert       *walk_subtrees = 0;
580*404b540aSrobert       return NULL_TREE;
581*404b540aSrobert     }
582*404b540aSrobert   if (TREE_CODE (exp) != TARGET_EXPR)
583*404b540aSrobert     return NULL_TREE;
584*404b540aSrobert 
585*404b540aSrobert   cleanup = TARGET_EXPR_CLEANUP (exp);
586*404b540aSrobert   if (cleanup)
587*404b540aSrobert     {
588*404b540aSrobert       cleanup = build1 (MUST_NOT_THROW_EXPR, void_type_node, cleanup);
589*404b540aSrobert       TARGET_EXPR_CLEANUP (exp) = cleanup;
590*404b540aSrobert     }
591*404b540aSrobert 
592*404b540aSrobert   /* Keep iterating.  */
593*404b540aSrobert   return NULL_TREE;
594*404b540aSrobert }
595*404b540aSrobert 
596*404b540aSrobert /* Build a throw expression.  */
597*404b540aSrobert 
598*404b540aSrobert tree
build_throw(tree exp)599*404b540aSrobert build_throw (tree exp)
600*404b540aSrobert {
601*404b540aSrobert   tree fn;
602*404b540aSrobert 
603*404b540aSrobert   if (exp == error_mark_node)
604*404b540aSrobert     return exp;
605*404b540aSrobert 
606*404b540aSrobert   if (processing_template_decl)
607*404b540aSrobert     {
608*404b540aSrobert       if (cfun)
609*404b540aSrobert 	current_function_returns_abnormally = 1;
610*404b540aSrobert       return build_min (THROW_EXPR, void_type_node, exp);
611*404b540aSrobert     }
612*404b540aSrobert 
613*404b540aSrobert   if (exp == null_node)
614*404b540aSrobert     warning (0, "throwing NULL, which has integral, not pointer type");
615*404b540aSrobert 
616*404b540aSrobert   if (exp != NULL_TREE)
617*404b540aSrobert     {
618*404b540aSrobert       if (!is_admissible_throw_operand (exp))
619*404b540aSrobert 	return error_mark_node;
620*404b540aSrobert     }
621*404b540aSrobert 
622*404b540aSrobert   if (! doing_eh (1))
623*404b540aSrobert     return error_mark_node;
624*404b540aSrobert 
625*404b540aSrobert   if (exp && decl_is_java_type (TREE_TYPE (exp), 1))
626*404b540aSrobert     {
627*404b540aSrobert       tree fn = get_identifier ("_Jv_Throw");
628*404b540aSrobert       if (!get_global_value_if_present (fn, &fn))
629*404b540aSrobert 	{
630*404b540aSrobert 	  /* Declare void _Jv_Throw (void *).  */
631*404b540aSrobert 	  tree tmp = tree_cons (NULL_TREE, ptr_type_node, void_list_node);
632*404b540aSrobert 	  tmp = build_function_type (ptr_type_node, tmp);
633*404b540aSrobert 	  fn = push_throw_library_fn (fn, tmp);
634*404b540aSrobert 	}
635*404b540aSrobert       else if (really_overloaded_fn (fn))
636*404b540aSrobert 	{
637*404b540aSrobert 	  error ("%qD should never be overloaded", fn);
638*404b540aSrobert 	  return error_mark_node;
639*404b540aSrobert 	}
640*404b540aSrobert       fn = OVL_CURRENT (fn);
641*404b540aSrobert       exp = build_function_call (fn, tree_cons (NULL_TREE, exp, NULL_TREE));
642*404b540aSrobert     }
643*404b540aSrobert   else if (exp)
644*404b540aSrobert     {
645*404b540aSrobert       tree throw_type;
646*404b540aSrobert       tree temp_type;
647*404b540aSrobert       tree cleanup;
648*404b540aSrobert       tree object, ptr;
649*404b540aSrobert       tree tmp;
650*404b540aSrobert       tree temp_expr, allocate_expr;
651*404b540aSrobert       bool elided;
652*404b540aSrobert 
653*404b540aSrobert       /* The CLEANUP_TYPE is the internal type of a destructor.  */
654*404b540aSrobert       if (!cleanup_type)
655*404b540aSrobert 	{
656*404b540aSrobert 	  tmp = void_list_node;
657*404b540aSrobert 	  tmp = tree_cons (NULL_TREE, ptr_type_node, tmp);
658*404b540aSrobert 	  tmp = build_function_type (void_type_node, tmp);
659*404b540aSrobert 	  cleanup_type = build_pointer_type (tmp);
660*404b540aSrobert 	}
661*404b540aSrobert 
662*404b540aSrobert       fn = get_identifier ("__cxa_throw");
663*404b540aSrobert       if (!get_global_value_if_present (fn, &fn))
664*404b540aSrobert 	{
665*404b540aSrobert 	  /* Declare void __cxa_throw (void*, void*, void (*)(void*)).  */
666*404b540aSrobert 	  /* ??? Second argument is supposed to be "std::type_info*".  */
667*404b540aSrobert 	  tmp = void_list_node;
668*404b540aSrobert 	  tmp = tree_cons (NULL_TREE, cleanup_type, tmp);
669*404b540aSrobert 	  tmp = tree_cons (NULL_TREE, ptr_type_node, tmp);
670*404b540aSrobert 	  tmp = tree_cons (NULL_TREE, ptr_type_node, tmp);
671*404b540aSrobert 	  tmp = build_function_type (void_type_node, tmp);
672*404b540aSrobert 	  fn = push_throw_library_fn (fn, tmp);
673*404b540aSrobert 	}
674*404b540aSrobert 
675*404b540aSrobert       /* [except.throw]
676*404b540aSrobert 
677*404b540aSrobert 	 A throw-expression initializes a temporary object, the type
678*404b540aSrobert 	 of which is determined by removing any top-level
679*404b540aSrobert 	 cv-qualifiers from the static type of the operand of throw
680*404b540aSrobert 	 and adjusting the type from "array of T" or "function return
681*404b540aSrobert 	 T" to "pointer to T" or "pointer to function returning T"
682*404b540aSrobert 	 respectively.  */
683*404b540aSrobert       temp_type = is_bitfield_expr_with_lowered_type (exp);
684*404b540aSrobert       if (!temp_type)
685*404b540aSrobert 	temp_type = type_decays_to (TYPE_MAIN_VARIANT (TREE_TYPE (exp)));
686*404b540aSrobert 
687*404b540aSrobert       /* OK, this is kind of wacky.  The standard says that we call
688*404b540aSrobert 	 terminate when the exception handling mechanism, after
689*404b540aSrobert 	 completing evaluation of the expression to be thrown but
690*404b540aSrobert 	 before the exception is caught (_except.throw_), calls a
691*404b540aSrobert 	 user function that exits via an uncaught exception.
692*404b540aSrobert 
693*404b540aSrobert 	 So we have to protect the actual initialization of the
694*404b540aSrobert 	 exception object with terminate(), but evaluate the
695*404b540aSrobert 	 expression first.  Since there could be temps in the
696*404b540aSrobert 	 expression, we need to handle that, too.  We also expand
697*404b540aSrobert 	 the call to __cxa_allocate_exception first (which doesn't
698*404b540aSrobert 	 matter, since it can't throw).  */
699*404b540aSrobert 
700*404b540aSrobert       /* Allocate the space for the exception.  */
701*404b540aSrobert       allocate_expr = do_allocate_exception (temp_type);
702*404b540aSrobert       allocate_expr = get_target_expr (allocate_expr);
703*404b540aSrobert       ptr = TARGET_EXPR_SLOT (allocate_expr);
704*404b540aSrobert       object = build_nop (build_pointer_type (temp_type), ptr);
705*404b540aSrobert       object = build_indirect_ref (object, NULL);
706*404b540aSrobert 
707*404b540aSrobert       elided = (TREE_CODE (exp) == TARGET_EXPR);
708*404b540aSrobert 
709*404b540aSrobert       /* And initialize the exception object.  */
710*404b540aSrobert       if (CLASS_TYPE_P (temp_type))
711*404b540aSrobert 	{
712*404b540aSrobert 	  /* Call the copy constructor.  */
713*404b540aSrobert 	  exp = (build_special_member_call
714*404b540aSrobert 		 (object, complete_ctor_identifier,
715*404b540aSrobert 		  build_tree_list (NULL_TREE, exp),
716*404b540aSrobert 		  TREE_TYPE (object),
717*404b540aSrobert 		  LOOKUP_NORMAL | LOOKUP_ONLYCONVERTING));
718*404b540aSrobert 	  if (exp == error_mark_node)
719*404b540aSrobert 	    {
720*404b540aSrobert 	      error ("  in thrown expression");
721*404b540aSrobert 	      return error_mark_node;
722*404b540aSrobert 	    }
723*404b540aSrobert 	}
724*404b540aSrobert       else
725*404b540aSrobert 	exp = build2 (INIT_EXPR, temp_type, object,
726*404b540aSrobert 		      decay_conversion (exp));
727*404b540aSrobert 
728*404b540aSrobert       /* Pre-evaluate the thrown expression first, since if we allocated
729*404b540aSrobert 	 the space first we would have to deal with cleaning it up if
730*404b540aSrobert 	 evaluating this expression throws.
731*404b540aSrobert 
732*404b540aSrobert 	 The case where EXP the initializer is a cast or a function
733*404b540aSrobert 	 returning a class is a bit of a grey area in the standard; it's
734*404b540aSrobert 	 unclear whether or not it should be allowed to throw.  We used to
735*404b540aSrobert 	 say no, as that allowed us to optimize this case without worrying
736*404b540aSrobert 	 about deallocating the exception object if it does.  But that
737*404b540aSrobert 	 conflicted with expectations (PR 13944) and the EDG compiler; now
738*404b540aSrobert 	 we wrap the initialization in a TRY_CATCH_EXPR to call
739*404b540aSrobert 	 do_free_exception rather than in a MUST_NOT_THROW_EXPR, for this
740*404b540aSrobert 	 case only.
741*404b540aSrobert 
742*404b540aSrobert 	 BUT: Issue 475 may do away with this inconsistency by removing the
743*404b540aSrobert 	 terminate() in this situation.
744*404b540aSrobert 
745*404b540aSrobert 	 Note that we don't check the return value from stabilize_init
746*404b540aSrobert 	 because it will only return false in cases where elided is true,
747*404b540aSrobert 	 and therefore we don't need to work around the failure to
748*404b540aSrobert 	 preevaluate.  */
749*404b540aSrobert       temp_expr = NULL_TREE;
750*404b540aSrobert       stabilize_init (exp, &temp_expr);
751*404b540aSrobert 
752*404b540aSrobert       /* Wrap the initialization in a CLEANUP_POINT_EXPR so that cleanups
753*404b540aSrobert 	 for temporaries within the initialization are run before the one
754*404b540aSrobert 	 for the exception object, preserving LIFO order.  */
755*404b540aSrobert       exp = build1 (CLEANUP_POINT_EXPR, void_type_node, exp);
756*404b540aSrobert 
757*404b540aSrobert       if (elided)
758*404b540aSrobert 	exp = build2 (TRY_CATCH_EXPR, void_type_node, exp,
759*404b540aSrobert 		      do_free_exception (ptr));
760*404b540aSrobert       else
761*404b540aSrobert 	exp = build1 (MUST_NOT_THROW_EXPR, void_type_node, exp);
762*404b540aSrobert 
763*404b540aSrobert       /* Prepend the allocation.  */
764*404b540aSrobert       exp = build2 (COMPOUND_EXPR, TREE_TYPE (exp), allocate_expr, exp);
765*404b540aSrobert       if (temp_expr)
766*404b540aSrobert 	{
767*404b540aSrobert 	  /* Prepend the calculation of the throw expression.  Also, force
768*404b540aSrobert 	     any cleanups from the expression to be evaluated here so that
769*404b540aSrobert 	     we don't have to do them during unwinding.  But first wrap
770*404b540aSrobert 	     them in MUST_NOT_THROW_EXPR, since they are run after the
771*404b540aSrobert 	     exception object is initialized.  */
772*404b540aSrobert 	  walk_tree_without_duplicates (&temp_expr, wrap_cleanups_r, 0);
773*404b540aSrobert 	  exp = build2 (COMPOUND_EXPR, TREE_TYPE (exp), temp_expr, exp);
774*404b540aSrobert 	  exp = build1 (CLEANUP_POINT_EXPR, TREE_TYPE (exp), exp);
775*404b540aSrobert 	}
776*404b540aSrobert 
777*404b540aSrobert       throw_type = build_eh_type_type (prepare_eh_type (TREE_TYPE (object)));
778*404b540aSrobert 
779*404b540aSrobert       if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (object)))
780*404b540aSrobert 	{
781*404b540aSrobert 	  cleanup = lookup_fnfields (TYPE_BINFO (TREE_TYPE (object)),
782*404b540aSrobert 				     complete_dtor_identifier, 0);
783*404b540aSrobert 	  cleanup = BASELINK_FUNCTIONS (cleanup);
784*404b540aSrobert 	  mark_used (cleanup);
785*404b540aSrobert 	  cxx_mark_addressable (cleanup);
786*404b540aSrobert 	  /* Pretend it's a normal function.  */
787*404b540aSrobert 	  cleanup = build1 (ADDR_EXPR, cleanup_type, cleanup);
788*404b540aSrobert 	}
789*404b540aSrobert       else
790*404b540aSrobert 	cleanup = build_int_cst (cleanup_type, 0);
791*404b540aSrobert 
792*404b540aSrobert       tmp = tree_cons (NULL_TREE, cleanup, NULL_TREE);
793*404b540aSrobert       tmp = tree_cons (NULL_TREE, throw_type, tmp);
794*404b540aSrobert       tmp = tree_cons (NULL_TREE, ptr, tmp);
795*404b540aSrobert       /* ??? Indicate that this function call throws throw_type.  */
796*404b540aSrobert       tmp = build_function_call (fn, tmp);
797*404b540aSrobert 
798*404b540aSrobert       /* Tack on the initialization stuff.  */
799*404b540aSrobert       exp = build2 (COMPOUND_EXPR, TREE_TYPE (tmp), exp, tmp);
800*404b540aSrobert     }
801*404b540aSrobert   else
802*404b540aSrobert     {
803*404b540aSrobert       /* Rethrow current exception.  */
804*404b540aSrobert 
805*404b540aSrobert       tree fn = get_identifier ("__cxa_rethrow");
806*404b540aSrobert       if (!get_global_value_if_present (fn, &fn))
807*404b540aSrobert 	{
808*404b540aSrobert 	  /* Declare void __cxa_rethrow (void).  */
809*404b540aSrobert 	  fn = push_throw_library_fn
810*404b540aSrobert 	    (fn, build_function_type (void_type_node, void_list_node));
811*404b540aSrobert 	}
812*404b540aSrobert 
813*404b540aSrobert       /* ??? Indicate that this function call allows exceptions of the type
814*404b540aSrobert 	 of the enclosing catch block (if known).  */
815*404b540aSrobert       exp = build_function_call (fn, NULL_TREE);
816*404b540aSrobert     }
817*404b540aSrobert 
818*404b540aSrobert   exp = build1 (THROW_EXPR, void_type_node, exp);
819*404b540aSrobert 
820*404b540aSrobert   return exp;
821*404b540aSrobert }
822*404b540aSrobert 
823*404b540aSrobert /* Make sure TYPE is complete, pointer to complete, reference to
824*404b540aSrobert    complete, or pointer to cv void. Issue diagnostic on failure.
825*404b540aSrobert    Return the zero on failure and nonzero on success. FROM can be
826*404b540aSrobert    the expr or decl from whence TYPE came, if available.  */
827*404b540aSrobert 
828*404b540aSrobert static int
complete_ptr_ref_or_void_ptr_p(tree type,tree from)829*404b540aSrobert complete_ptr_ref_or_void_ptr_p (tree type, tree from)
830*404b540aSrobert {
831*404b540aSrobert   int is_ptr;
832*404b540aSrobert 
833*404b540aSrobert   /* Check complete.  */
834*404b540aSrobert   type = complete_type_or_else (type, from);
835*404b540aSrobert   if (!type)
836*404b540aSrobert     return 0;
837*404b540aSrobert 
838*404b540aSrobert   /* Or a pointer or ref to one, or cv void *.  */
839*404b540aSrobert   is_ptr = TREE_CODE (type) == POINTER_TYPE;
840*404b540aSrobert   if (is_ptr || TREE_CODE (type) == REFERENCE_TYPE)
841*404b540aSrobert     {
842*404b540aSrobert       tree core = TREE_TYPE (type);
843*404b540aSrobert 
844*404b540aSrobert       if (is_ptr && VOID_TYPE_P (core))
845*404b540aSrobert 	/* OK */;
846*404b540aSrobert       else if (!complete_type_or_else (core, from))
847*404b540aSrobert 	return 0;
848*404b540aSrobert     }
849*404b540aSrobert   return 1;
850*404b540aSrobert }
851*404b540aSrobert 
852*404b540aSrobert /* Return truth-value if EXPRESSION is admissible in throw-expression,
853*404b540aSrobert    i.e. if it is not of incomplete type or a pointer/reference to such
854*404b540aSrobert    a type or of an abstract class type.  */
855*404b540aSrobert 
856*404b540aSrobert static bool
is_admissible_throw_operand(tree expr)857*404b540aSrobert is_admissible_throw_operand (tree expr)
858*404b540aSrobert {
859*404b540aSrobert   tree type = TREE_TYPE (expr);
860*404b540aSrobert 
861*404b540aSrobert   /* 15.1/4 [...] The type of the throw-expression shall not be an
862*404b540aSrobert 	    incomplete type, or a pointer or a reference to an incomplete
863*404b540aSrobert 	    type, other than void*, const void*, volatile void*, or
864*404b540aSrobert 	    const volatile void*.  Except for these restriction and the
865*404b540aSrobert 	    restrictions on type matching mentioned in 15.3, the operand
866*404b540aSrobert 	    of throw is treated exactly as a function argument in a call
867*404b540aSrobert 	    (5.2.2) or the operand of a return statement.  */
868*404b540aSrobert   if (!complete_ptr_ref_or_void_ptr_p (type, expr))
869*404b540aSrobert     return false;
870*404b540aSrobert 
871*404b540aSrobert   /* 10.4/3 An abstract class shall not be used as a parameter type,
872*404b540aSrobert 	    as a function return type or as type of an explicit
873*404b540aSrobert 	    conversion.  */
874*404b540aSrobert   else if (CLASS_TYPE_P (type) && CLASSTYPE_PURE_VIRTUALS (type))
875*404b540aSrobert     {
876*404b540aSrobert       error ("expression %qE of abstract class type %qT cannot "
877*404b540aSrobert 	     "be used in throw-expression", expr, type);
878*404b540aSrobert       return false;
879*404b540aSrobert     }
880*404b540aSrobert 
881*404b540aSrobert   return true;
882*404b540aSrobert }
883*404b540aSrobert 
884*404b540aSrobert /* Returns nonzero if FN is a declaration of a standard C library
885*404b540aSrobert    function which is known not to throw.
886*404b540aSrobert 
887*404b540aSrobert    [lib.res.on.exception.handling]: None of the functions from the
888*404b540aSrobert    Standard C library shall report an error by throwing an
889*404b540aSrobert    exception, unless it calls a program-supplied function that
890*404b540aSrobert    throws an exception.  */
891*404b540aSrobert 
892*404b540aSrobert #include "cfns.h"
893*404b540aSrobert 
894*404b540aSrobert int
nothrow_libfn_p(tree fn)895*404b540aSrobert nothrow_libfn_p (tree fn)
896*404b540aSrobert {
897*404b540aSrobert   tree id;
898*404b540aSrobert 
899*404b540aSrobert   if (TREE_PUBLIC (fn)
900*404b540aSrobert       && DECL_EXTERNAL (fn)
901*404b540aSrobert       && DECL_NAMESPACE_SCOPE_P (fn)
902*404b540aSrobert       && DECL_EXTERN_C_P (fn))
903*404b540aSrobert     /* OK */;
904*404b540aSrobert   else
905*404b540aSrobert     /* Can't be a C library function.  */
906*404b540aSrobert     return 0;
907*404b540aSrobert 
908*404b540aSrobert   /* Being a C library function, DECL_ASSEMBLER_NAME == DECL_NAME
909*404b540aSrobert      unless the system headers are playing rename tricks, and if
910*404b540aSrobert      they are, we don't want to be confused by them.  */
911*404b540aSrobert   id = DECL_NAME (fn);
912*404b540aSrobert   return !!libc_name_p (IDENTIFIER_POINTER (id), IDENTIFIER_LENGTH (id));
913*404b540aSrobert }
914*404b540aSrobert 
915*404b540aSrobert /* Returns nonzero if an exception of type FROM will be caught by a
916*404b540aSrobert    handler for type TO, as per [except.handle].  */
917*404b540aSrobert 
918*404b540aSrobert static int
can_convert_eh(tree to,tree from)919*404b540aSrobert can_convert_eh (tree to, tree from)
920*404b540aSrobert {
921*404b540aSrobert   to = non_reference (to);
922*404b540aSrobert   from = non_reference (from);
923*404b540aSrobert 
924*404b540aSrobert   if (TREE_CODE (to) == POINTER_TYPE && TREE_CODE (from) == POINTER_TYPE)
925*404b540aSrobert     {
926*404b540aSrobert       to = TREE_TYPE (to);
927*404b540aSrobert       from = TREE_TYPE (from);
928*404b540aSrobert 
929*404b540aSrobert       if (! at_least_as_qualified_p (to, from))
930*404b540aSrobert 	return 0;
931*404b540aSrobert 
932*404b540aSrobert       if (TREE_CODE (to) == VOID_TYPE)
933*404b540aSrobert 	return 1;
934*404b540aSrobert 
935*404b540aSrobert       /* Else fall through.  */
936*404b540aSrobert     }
937*404b540aSrobert 
938*404b540aSrobert   if (CLASS_TYPE_P (to) && CLASS_TYPE_P (from)
939*404b540aSrobert       && PUBLICLY_UNIQUELY_DERIVED_P (to, from))
940*404b540aSrobert     return 1;
941*404b540aSrobert 
942*404b540aSrobert   return 0;
943*404b540aSrobert }
944*404b540aSrobert 
945*404b540aSrobert /* Check whether any of the handlers in I are shadowed by another handler
946*404b540aSrobert    accepting TYPE.  Note that the shadowing may not be complete; even if
947*404b540aSrobert    an exception of type B would be caught by a handler for A, there could
948*404b540aSrobert    be a derived class C for which A is an ambiguous base but B is not, so
949*404b540aSrobert    the handler for B would catch an exception of type C.  */
950*404b540aSrobert 
951*404b540aSrobert static void
check_handlers_1(tree master,tree_stmt_iterator i)952*404b540aSrobert check_handlers_1 (tree master, tree_stmt_iterator i)
953*404b540aSrobert {
954*404b540aSrobert   tree type = TREE_TYPE (master);
955*404b540aSrobert 
956*404b540aSrobert   for (; !tsi_end_p (i); tsi_next (&i))
957*404b540aSrobert     {
958*404b540aSrobert       tree handler = tsi_stmt (i);
959*404b540aSrobert       if (TREE_TYPE (handler) && can_convert_eh (type, TREE_TYPE (handler)))
960*404b540aSrobert 	{
961*404b540aSrobert 	  warning (0, "%Hexception of type %qT will be caught",
962*404b540aSrobert 		   EXPR_LOCUS (handler), TREE_TYPE (handler));
963*404b540aSrobert 	  warning (0, "%H   by earlier handler for %qT",
964*404b540aSrobert 		   EXPR_LOCUS (master), type);
965*404b540aSrobert 	  break;
966*404b540aSrobert 	}
967*404b540aSrobert     }
968*404b540aSrobert }
969*404b540aSrobert 
970*404b540aSrobert /* Given a STATEMENT_LIST of HANDLERs, make sure that they're OK.  */
971*404b540aSrobert 
972*404b540aSrobert void
check_handlers(tree handlers)973*404b540aSrobert check_handlers (tree handlers)
974*404b540aSrobert {
975*404b540aSrobert   tree_stmt_iterator i;
976*404b540aSrobert 
977*404b540aSrobert   /* If we don't have a STATEMENT_LIST, then we've just got one
978*404b540aSrobert      handler, and thus nothing to warn about.  */
979*404b540aSrobert   if (TREE_CODE (handlers) != STATEMENT_LIST)
980*404b540aSrobert     return;
981*404b540aSrobert 
982*404b540aSrobert   i = tsi_start (handlers);
983*404b540aSrobert   if (!tsi_end_p (i))
984*404b540aSrobert     while (1)
985*404b540aSrobert       {
986*404b540aSrobert 	tree handler = tsi_stmt (i);
987*404b540aSrobert 	tsi_next (&i);
988*404b540aSrobert 
989*404b540aSrobert 	/* No more handlers; nothing to shadow.  */
990*404b540aSrobert 	if (tsi_end_p (i))
991*404b540aSrobert 	  break;
992*404b540aSrobert 	if (TREE_TYPE (handler) == NULL_TREE)
993*404b540aSrobert 	  pedwarn ("%H%<...%> handler must be the last handler for"
994*404b540aSrobert 		   " its try block", EXPR_LOCUS (handler));
995*404b540aSrobert 	else
996*404b540aSrobert 	  check_handlers_1 (handler, i);
997*404b540aSrobert       }
998*404b540aSrobert }
999