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