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