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