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