]> gcc.gnu.org Git - gcc.git/blame - gcc/cp/except.c
mips.md (movdicc): Make conditional on TARGET_64BIT.
[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);
c93586fa 351 if (! TYPE_PTR_P (init_type)
52a11cbf 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. */
c93586fa
RS
360 if (TREE_CODE (init_type) == REFERENCE_TYPE
361 && TYPE_PTR_P (TREE_TYPE (init_type)))
b35d4555
MM
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{
52a11cbf
RH
394 tree exp = NULL_TREE;
395 tree type;
396 bool is_java;
5816cb14 397
b35d4555
MM
398 if (! doing_eh (1))
399 return NULL_TREE;
5816cb14 400
b35d4555 401 /* Make sure this declaration is reasonable. */
3c5c0849
MM
402 if (decl && !complete_ptr_ref_or_void_ptr_p (TREE_TYPE (decl), NULL_TREE))
403 decl = NULL_TREE;
5816cb14 404
52a11cbf
RH
405 if (decl)
406 type = prepare_eh_type (TREE_TYPE (decl));
407 else
408 type = NULL_TREE;
52a11cbf
RH
409
410 is_java = false;
411 if (decl)
e97f22c9 412 {
52a11cbf 413 tree init;
5816cb14 414
52a11cbf
RH
415 if (decl_is_java_type (type, 1))
416 {
417 /* Java only passes object via pointer and doesn't require
418 adjusting. The java object is immediately before the
419 generic exception header. */
420 init = build_exc_ptr ();
421 init = build1 (NOP_EXPR, build_pointer_type (type), init);
422 init = build (MINUS_EXPR, TREE_TYPE (init), init,
423 TYPE_SIZE_UNIT (TREE_TYPE (init)));
3e411c3f 424 init = build_indirect_ref (init, NULL);
52a11cbf
RH
425 is_java = true;
426 }
e97f22c9 427 else
52a11cbf
RH
428 {
429 /* C++ requires that we call __cxa_begin_catch to get the
430 pointer to the actual object. */
431 init = do_begin_catch ();
432 }
433
434 exp = create_temporary_var (ptr_type_node);
435 DECL_REGISTER (exp) = 1;
436 cp_finish_decl (exp, init, NULL_TREE, LOOKUP_ONLYCONVERTING);
437 finish_expr_stmt (build_modify_expr (exp, INIT_EXPR, init));
e97f22c9
TT
438 }
439 else
52a11cbf
RH
440 finish_expr_stmt (do_begin_catch ());
441
442 /* C++ requires that we call __cxa_end_catch at the end of
443 processing the exception. */
444 if (! is_java)
445 push_eh_cleanup (type);
5816cb14 446
b35d4555 447 if (decl)
52a11cbf 448 initialize_handler_parm (decl, exp);
5816cb14 449
1a6025b4 450 return type;
5816cb14
AM
451}
452
f30432d7 453
8d2733ca
MS
454/* Call this to end a catch block. Its responsible for emitting the
455 code to handle jumping back to the correct place, and for emitting
456 the label to jump to if this catch block didn't match. */
6467930b 457
824b9a4c 458void
1a6025b4 459expand_end_catch_block ()
8d08fdba 460{
f30432d7
MS
461 if (! doing_eh (1))
462 return;
8d2733ca 463
0dde4175
JM
464 /* The exception being handled is rethrown if control reaches the end of
465 a handler of the function-try-block of a constructor or destructor. */
466 if (in_function_try_handler
467 && (DECL_CONSTRUCTOR_P (current_function_decl)
468 || DECL_DESTRUCTOR_P (current_function_decl)))
b35d4555 469 finish_expr_stmt (build_throw (NULL_TREE));
8d2733ca 470}
8d08fdba 471
b35d4555 472tree
52a11cbf 473begin_eh_spec_block ()
f30432d7 474{
52a11cbf
RH
475 tree r = build_stmt (EH_SPEC_BLOCK, NULL_TREE, NULL_TREE);
476 add_stmt (r);
477 return r;
f30432d7
MS
478}
479
b35d4555 480void
52a11cbf
RH
481finish_eh_spec_block (raw_raises, eh_spec_block)
482 tree raw_raises;
483 tree eh_spec_block;
f30432d7 484{
52a11cbf 485 tree raises;
0c11ada6 486
52a11cbf 487 RECHAIN_STMTS (eh_spec_block, EH_SPEC_STMTS (eh_spec_block));
6c20b7e9 488
52a11cbf
RH
489 /* Strip cv quals, etc, from the specification types. */
490 for (raises = NULL_TREE;
491 raw_raises && TREE_VALUE (raw_raises);
492 raw_raises = TREE_CHAIN (raw_raises))
493 raises = tree_cons (NULL_TREE, prepare_eh_type (TREE_VALUE (raw_raises)),
494 raises);
6c20b7e9 495
52a11cbf 496 EH_SPEC_RAISES (eh_spec_block) = raises;
f30432d7
MS
497}
498
52a11cbf 499/* Return a pointer to a buffer for an exception object of type TYPE. */
6467930b 500
52a11cbf
RH
501static tree
502do_allocate_exception (type)
503 tree type;
8d08fdba 504{
52a11cbf 505 tree fn;
eb448459 506
52a11cbf
RH
507 fn = get_identifier ("__cxa_allocate_exception");
508 if (IDENTIFIER_GLOBAL_VALUE (fn))
509 fn = IDENTIFIER_GLOBAL_VALUE (fn);
510 else
f30432d7 511 {
52a11cbf
RH
512 /* Declare void *__cxa_allocate_exception(size_t). */
513 tree tmp = tree_cons (NULL_TREE, c_size_type_node, void_list_node);
514 fn = push_library_fn (fn, build_function_type (ptr_type_node, tmp));
e00737d2 515 }
52a11cbf
RH
516
517 return build_function_call (fn, tree_cons (NULL_TREE, size_in_bytes (type),
518 NULL_TREE));
8d08fdba
MS
519}
520
2ac8a0f9
JM
521#if 0
522/* Call __cxa_free_exception from a cleanup. This is never invoked
523 directly. */
f4a23343 524
c6160f8f 525static tree
52a11cbf
RH
526do_free_exception (ptr)
527 tree ptr;
f4a23343 528{
52a11cbf 529 tree fn;
f4a23343 530
52a11cbf 531 fn = get_identifier ("__cxa_free_exception");
f4a23343
JM
532 if (IDENTIFIER_GLOBAL_VALUE (fn))
533 fn = IDENTIFIER_GLOBAL_VALUE (fn);
534 else
535 {
52a11cbf
RH
536 /* Declare void __cxa_free_exception (void *). */
537 fn = push_void_library_fn (fn, tree_cons (NULL_TREE, ptr_type_node,
538 void_list_node));
f4a23343
JM
539 }
540
52a11cbf 541 return build_function_call (fn, tree_cons (NULL_TREE, ptr, NULL_TREE));
f4a23343 542}
2ac8a0f9 543#endif
f4a23343 544
52a11cbf 545/* Build a throw expression. */
6467930b 546
52a11cbf
RH
547tree
548build_throw (exp)
8d2733ca 549 tree exp;
8d08fdba 550{
6874c264 551 tree fn;
8d08fdba 552
52a11cbf
RH
553 if (exp == error_mark_node)
554 return exp;
555
556 if (processing_template_decl)
557 return build_min (THROW_EXPR, void_type_node, exp);
558
559 if (exp == null_node)
560 cp_warning ("throwing NULL, which has integral, not pointer type");
561
562 if (exp != NULL_TREE)
563 {
564 if (!is_admissible_throw_operand (exp))
565 return error_mark_node;
566 }
567
8d2733ca 568 if (! doing_eh (1))
59ccf49d 569 return error_mark_node;
8d08fdba 570
52a11cbf 571 if (exp && decl_is_java_type (TREE_TYPE (exp), 1))
e97f22c9 572 {
52a11cbf 573 tree fn = get_identifier ("_Jv_Throw");
e97f22c9
TT
574 if (IDENTIFIER_GLOBAL_VALUE (fn))
575 fn = IDENTIFIER_GLOBAL_VALUE (fn);
576 else
577 {
52a11cbf 578 /* Declare void _Jv_Throw (void *). */
0c11ada6
JM
579 tree tmp = tree_cons (NULL_TREE, ptr_type_node, void_list_node);
580 tmp = build_function_type (ptr_type_node, tmp);
c00996a3 581 fn = push_throw_library_fn (fn, tmp);
e97f22c9
TT
582 }
583
52a11cbf 584 exp = build_function_call (fn, tree_cons (NULL_TREE, exp, NULL_TREE));
e97f22c9
TT
585 }
586 else if (exp)
8d2733ca 587 {
faae18ab 588 tree throw_type;
52a11cbf 589 tree cleanup;
59ccf49d
MM
590 tree stmt_expr;
591 tree compound_stmt;
52a11cbf
RH
592 tree object, ptr;
593 tree tmp;
594
595 fn = get_identifier ("__cxa_throw");
596 if (IDENTIFIER_GLOBAL_VALUE (fn))
597 fn = IDENTIFIER_GLOBAL_VALUE (fn);
598 else
599 {
600 /* The CLEANUP_TYPE is the internal type of a destructor. */
601 if (cleanup_type == NULL_TREE)
602 {
603 tmp = void_list_node;
604 tmp = tree_cons (NULL_TREE, ptr_type_node, tmp);
605 tmp = build_function_type (void_type_node, tmp);
606 cleanup_type = build_pointer_type (tmp);
607 }
608
609 /* Declare void __cxa_throw (void*, void*, void (*)(void*)). */
610 /* ??? Second argument is supposed to be "std::type_info*". */
611 tmp = void_list_node;
612 tmp = tree_cons (NULL_TREE, cleanup_type, tmp);
613 tmp = tree_cons (NULL_TREE, ptr_type_node, tmp);
614 tmp = tree_cons (NULL_TREE, ptr_type_node, tmp);
615 tmp = build_function_type (void_type_node, tmp);
616 fn = push_throw_library_fn (fn, tmp);
617 }
59ccf49d
MM
618
619 begin_init_stmts (&stmt_expr, &compound_stmt);
faae18ab 620
a3b49ccd 621 /* throw expression */
e92cc029 622 /* First, decay it. */
f30432d7 623 exp = decay_conversion (exp);
a3b49ccd 624
52a11cbf
RH
625 /* OK, this is kind of wacky. The standard says that we call
626 terminate when the exception handling mechanism, after
627 completing evaluation of the expression to be thrown but
628 before the exception is caught (_except.throw_), calls a
629 user function that exits via an uncaught exception.
630
631 So we have to protect the actual initialization of the
632 exception object with terminate(), but evaluate the
633 expression first. Since there could be temps in the
634 expression, we need to handle that, too. We also expand
635 the call to __cxa_allocate_exception first (which doesn't
636 matter, since it can't throw). */
637
638 my_friendly_assert (stmts_are_full_exprs_p () == 1, 19990926);
639
640 /* Store the throw expression into a temp. This can be less
641 efficient than storing it into the allocated space directly, but
642 if we allocated the space first we would have to deal with
643 cleaning it up if evaluating this expression throws. */
644 if (TREE_SIDE_EFFECTS (exp))
298d6f60 645 {
52a11cbf
RH
646 tmp = create_temporary_var (TREE_TYPE (exp));
647 DECL_INITIAL (tmp) = exp;
648 cp_finish_decl (tmp, exp, NULL_TREE, LOOKUP_ONLYCONVERTING);
649 exp = tmp;
298d6f60 650 }
6874c264 651
52a11cbf
RH
652 /* Allocate the space for the exception. */
653 ptr = create_temporary_var (ptr_type_node);
654 DECL_REGISTER (ptr) = 1;
655 cp_finish_decl (ptr, NULL_TREE, NULL_TREE, LOOKUP_ONLYCONVERTING);
656 tmp = do_allocate_exception (TREE_TYPE (exp));
657 tmp = build_modify_expr (ptr, INIT_EXPR, tmp);
658 finish_expr_stmt (tmp);
f4a23343 659
52a11cbf 660 object = build1 (NOP_EXPR, build_pointer_type (TREE_TYPE (exp)), ptr);
3e411c3f 661 object = build_indirect_ref (object, NULL);
faae18ab 662
52a11cbf
RH
663 exp = build_modify_expr (object, INIT_EXPR, exp);
664 if (exp == error_mark_node)
665 error (" in thrown expression");
f4a23343 666
2ac8a0f9 667 exp = build1 (MUST_NOT_THROW_EXPR, TREE_TYPE (exp), exp);
52a11cbf 668 finish_expr_stmt (exp);
72b7eeff 669
52a11cbf 670 throw_type = build_eh_type_type (prepare_eh_type (TREE_TYPE (object)));
f4a23343 671
52a11cbf
RH
672 if (TYPE_HAS_DESTRUCTOR (TREE_TYPE (object)))
673 {
674 cleanup = lookup_fnfields (TYPE_BINFO (TREE_TYPE (object)),
675 complete_dtor_identifier, 0);
676 cleanup = TREE_VALUE (cleanup);
677 mark_used (cleanup);
678 mark_addressable (cleanup);
679 /* Pretend it's a normal function. */
680 cleanup = build1 (ADDR_EXPR, cleanup_type, cleanup);
f30432d7 681 }
52a11cbf 682 else
6874c264
JM
683 {
684 cleanup = build_int_2 (0, 0);
685 TREE_TYPE (cleanup) = cleanup_type;
686 }
72b7eeff 687
52a11cbf
RH
688 tmp = tree_cons (NULL_TREE, cleanup, NULL_TREE);
689 tmp = tree_cons (NULL_TREE, throw_type, tmp);
690 tmp = tree_cons (NULL_TREE, ptr, tmp);
691 tmp = build_function_call (fn, tmp);
692
693 /* ??? Indicate that this function call throws throw_type. */
72b7eeff 694
52a11cbf 695 finish_expr_stmt (tmp);
59ccf49d
MM
696
697 exp = finish_init_stmts (stmt_expr, compound_stmt);
8d2733ca
MS
698 }
699 else
a3b49ccd 700 {
52a11cbf 701 /* Rethrow current exception. */
6874c264 702
52a11cbf 703 tree fn = get_identifier ("__cxa_rethrow");
6874c264
JM
704 if (IDENTIFIER_GLOBAL_VALUE (fn))
705 fn = IDENTIFIER_GLOBAL_VALUE (fn);
706 else
52a11cbf
RH
707 {
708 /* Declare void __cxa_rethrow (void). */
709 fn = push_throw_library_fn
710 (fn, build_function_type (void_type_node, void_list_node));
711 }
6874c264
JM
712
713 exp = build_function_call (fn, NULL_TREE);
a3b49ccd 714 }
8d2733ca 715
52a11cbf 716 exp = build1 (THROW_EXPR, void_type_node, exp);
02020185 717
52a11cbf 718 return exp;
8d08fdba 719}
4cfbc546
NS
720
721/* Make sure TYPE is complete, pointer to complete, reference to
722 complete, or pointer to cv void. Issue diagnostic on failure.
723 Return the zero on failure and non-zero on success. FROM can be
724 the expr or decl from whence TYPE came, if available. */
725
726static int
727complete_ptr_ref_or_void_ptr_p (type, from)
728 tree type;
729 tree from;
730{
731 int is_ptr;
732
733 /* Check complete. */
734 type = complete_type_or_else (type, from);
735 if (!type)
736 return 0;
737
738 /* Or a pointer or ref to one, or cv void *. */
739 is_ptr = TREE_CODE (type) == POINTER_TYPE;
740 if (is_ptr || TREE_CODE (type) == REFERENCE_TYPE)
741 {
742 tree core = TREE_TYPE (type);
743
b72801e2 744 if (is_ptr && VOID_TYPE_P (core))
4cfbc546
NS
745 /* OK */;
746 else if (!complete_type_or_else (core, from))
747 return 0;
748 }
749 return 1;
750}
751
d064d75a
GDR
752/* Return truth-value if EXPRESSION is admissible in throw-expression,
753 i.e. if it is not of incomplete type or a pointer/reference to such
754 a type or of an abstract class type. */
755
756static bool
757is_admissible_throw_operand (expr)
758 tree expr;
759{
760 tree type = TREE_TYPE (expr);
761
762 /* 15.1/4 [...] The type of the throw-expression shall not be an
763 incomplete type, or a pointer or a reference to an incomplete
764 type, other than void*, const void*, volatile void*, or
765 const volatile void*. Except for these restriction and the
766 restrictions on type matching mentioned in 15.3, the operand
767 of throw is treated exactly as a function argument in a call
768 (5.2.2) or the operand of a return statement. */
769 if (!complete_ptr_ref_or_void_ptr_p (type, expr))
770 return false;
771
772 /* 10.4/3 An abstract class shall not be used as a parameter type,
773 as a function return type or as type of an explicit
774 conversion. */
775 else if (CLASS_TYPE_P (type) && CLASSTYPE_PURE_VIRTUALS (type))
776 {
777 cp_error ("Expression '%E' of abstract class type '%T' cannot be used in throw-expression", expr, type);
778 return false;
779 }
780
781 return true;
782}
783
1660cb3a
JM
784/* Returns nonzero if FN is a declaration of a standard C library
785 function which is known not to throw.
786
787 [lib.res.on.exception.handling]: None of the functions from the
788 Standard C library shall report an error by throwing an
789 exception, unless it calls a program-supplied function that
790 throws an exception. */
791
792#include "cfns.h"
793
794int
795nothrow_libfn_p (fn)
796 tree fn;
797{
798 tree id;
799
800 if (TREE_PUBLIC (fn)
801 && DECL_EXTERNAL (fn)
92643fea 802 && DECL_NAMESPACE_SCOPE_P (fn)
eb68cb58 803 && DECL_EXTERN_C_P (fn))
1660cb3a
JM
804 /* OK */;
805 else
806 /* Can't be a C library function. */
807 return 0;
808
809 id = DECL_ASSEMBLER_NAME (fn);
810 return !!libc_name_p (IDENTIFIER_POINTER (id), IDENTIFIER_LENGTH (id));
811}
2bc9f1d1
JM
812
813/* Returns nonzero if an exception of type FROM will be caught by a
814 handler for type TO, as per [except.handle]. */
815
816static int
817can_convert_eh (to, from)
818 tree to, from;
819{
820 if (TREE_CODE (to) == REFERENCE_TYPE)
821 to = TREE_TYPE (to);
822 if (TREE_CODE (from) == REFERENCE_TYPE)
823 from = TREE_TYPE (from);
824
825 if (TREE_CODE (to) == POINTER_TYPE && TREE_CODE (from) == POINTER_TYPE)
826 {
827 to = TREE_TYPE (to);
828 from = TREE_TYPE (from);
829
830 if (! at_least_as_qualified_p (to, from))
831 return 0;
832
833 if (TREE_CODE (to) == VOID_TYPE)
834 return 1;
835
836 /* else fall through */
837 }
838
2d46ec83 839 if (CLASS_TYPE_P (to) && CLASS_TYPE_P (from)
2bc9f1d1
JM
840 && PUBLICLY_UNIQUELY_DERIVED_P (to, from))
841 return 1;
842
843 return 0;
844}
845
846/* Check whether any of HANDLERS are shadowed by another handler accepting
847 TYPE. Note that the shadowing may not be complete; even if an exception
848 of type B would be caught by a handler for A, there could be a derived
849 class C for which A is an ambiguous base but B is not, so the handler
850 for B would catch an exception of type C. */
851
852static void
853check_handlers_1 (master, handlers)
854 tree master;
855 tree handlers;
856{
857 tree type = TREE_TYPE (master);
858 tree handler;
859
860 for (handler = handlers; handler; handler = TREE_CHAIN (handler))
861 if (TREE_TYPE (handler)
862 && can_convert_eh (type, TREE_TYPE (handler)))
863 {
864 lineno = STMT_LINENO (handler);
865 cp_warning ("exception of type `%T' will be caught",
866 TREE_TYPE (handler));
867 lineno = STMT_LINENO (master);
868 cp_warning (" by earlier handler for `%T'", type);
869 break;
870 }
871}
872
873/* Given a chain of HANDLERs, make sure that they're OK. */
874
875void
876check_handlers (handlers)
877 tree handlers;
878{
879 tree handler;
880 int save_line = lineno;
881 for (handler = handlers; handler; handler = TREE_CHAIN (handler))
882 {
883 if (TREE_CHAIN (handler) == NULL_TREE)
884 /* No more handlers; nothing to shadow. */;
885 else if (TREE_TYPE (handler) == NULL_TREE)
886 {
887 lineno = STMT_LINENO (handler);
888 cp_pedwarn
889 ("`...' handler must be the last handler for its try block");
890 }
891 else
892 check_handlers_1 (handler, TREE_CHAIN (handler));
893 }
894 lineno = save_line;
895}
This page took 0.987982 seconds and 5 git commands to generate.