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