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