1 /* Handle exceptional things in C++. 2 Copyright (C) 1989-2020 Free Software Foundation, Inc. 3 Contributed by Michael Tiemann <tiemann@cygnus.com> 4 Rewritten by Mike Stump <mrs@cygnus.com>, based upon an 5 initial re-implementation courtesy Tad Hunt. 6 7 This file is part of GCC. 8 9 GCC is free software; you can redistribute it and/or modify 10 it under the terms of the GNU General Public License as published by 11 the Free Software Foundation; either version 3, or (at your option) 12 any later version. 13 14 GCC is distributed in the hope that it will be useful, 15 but WITHOUT ANY WARRANTY; without even the implied warranty of 16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 GNU General Public License for more details. 18 19 You should have received a copy of the GNU General Public License 20 along with GCC; see the file COPYING3. If not see 21 <http://www.gnu.org/licenses/>. */ 22 23 24 #include "config.h" 25 #include "system.h" 26 #include "coretypes.h" 27 #include "cp-tree.h" 28 #include "stringpool.h" 29 #include "trans-mem.h" 30 #include "attribs.h" 31 #include "tree-iterator.h" 32 #include "target.h" 33 34 static void push_eh_cleanup (tree); 35 static tree prepare_eh_type (tree); 36 static tree do_begin_catch (void); 37 static int dtor_nothrow (tree); 38 static tree do_end_catch (tree); 39 static void initialize_handler_parm (tree, tree); 40 static tree do_allocate_exception (tree); 41 static tree wrap_cleanups_r (tree *, int *, void *); 42 static int complete_ptr_ref_or_void_ptr_p (tree, tree); 43 static bool is_admissible_throw_operand_or_catch_parameter (tree, bool); 44 static int can_convert_eh (tree, tree); 45 46 /* Sets up all the global eh stuff that needs to be initialized at the 47 start of compilation. */ 48 49 void 50 init_exception_processing (void) 51 { 52 tree tmp; 53 54 /* void std::terminate (); */ 55 push_nested_namespace (std_node); 56 tmp = build_function_type_list (void_type_node, NULL_TREE); 57 terminate_fn = build_cp_library_fn_ptr ("terminate", tmp, 58 ECF_NOTHROW | ECF_NORETURN 59 | ECF_COLD); 60 gcc_checking_assert (TREE_THIS_VOLATILE (terminate_fn) 61 && TREE_NOTHROW (terminate_fn)); 62 pop_nested_namespace (std_node); 63 64 /* void __cxa_call_unexpected(void *); */ 65 tmp = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE); 66 call_unexpected_fn 67 = push_throw_library_fn (get_identifier ("__cxa_call_unexpected"), tmp); 68 } 69 70 /* Returns an expression to be executed if an unhandled exception is 71 propagated out of a cleanup region. */ 72 73 tree 74 cp_protect_cleanup_actions (void) 75 { 76 /* [except.terminate] 77 78 When the destruction of an object during stack unwinding exits 79 using an exception ... void terminate(); is called. */ 80 return terminate_fn; 81 } 82 83 static tree 84 prepare_eh_type (tree type) 85 { 86 if (type == NULL_TREE) 87 return type; 88 if (type == error_mark_node) 89 return error_mark_node; 90 91 /* peel back references, so they match. */ 92 type = non_reference (type); 93 94 /* Peel off cv qualifiers. */ 95 type = TYPE_MAIN_VARIANT (type); 96 97 /* Functions and arrays decay to pointers. */ 98 type = type_decays_to (type); 99 100 return type; 101 } 102 103 /* Return the type info for TYPE as used by EH machinery. */ 104 tree 105 eh_type_info (tree type) 106 { 107 if (type == NULL_TREE || type == error_mark_node) 108 return type; 109 110 return get_tinfo_decl (type); 111 } 112 113 /* Build the address of a typeinfo decl for use in the runtime 114 matching field of the exception model. */ 115 116 tree 117 build_eh_type_type (tree type) 118 { 119 tree exp = eh_type_info (type); 120 121 if (!exp) 122 return NULL; 123 124 mark_used (exp); 125 126 return convert (ptr_type_node, build_address (exp)); 127 } 128 129 tree 130 build_exc_ptr (void) 131 { 132 return build_call_n (builtin_decl_explicit (BUILT_IN_EH_POINTER), 133 1, integer_zero_node); 134 } 135 136 /* Check that user declared function FN is a function and has return 137 type RTYPE and argument types ARG{1,2,3}TYPE. */ 138 139 static bool 140 verify_library_fn (tree fn, const char *name, tree rtype, 141 tree arg1type, tree arg2type, tree arg3type) 142 { 143 if (TREE_CODE (fn) != FUNCTION_DECL 144 || TREE_CODE (TREE_TYPE (fn)) != FUNCTION_TYPE) 145 { 146 bad: 147 error_at (DECL_SOURCE_LOCATION (fn), "%qs declared incorrectly", name); 148 return false; 149 } 150 tree fntype = TREE_TYPE (fn); 151 if (!same_type_p (TREE_TYPE (fntype), rtype)) 152 goto bad; 153 tree targs = TYPE_ARG_TYPES (fntype); 154 tree args[3] = { arg1type, arg2type, arg3type }; 155 for (int i = 0; i < 3 && args[i]; i++) 156 { 157 if (targs == NULL_TREE) 158 goto bad; 159 if (!same_type_p (TREE_VALUE (targs), args[i])) 160 { 161 if (i == 0) 162 goto bad; 163 /* Be less strict for second and following arguments, __cxa_throw 164 needs to be more permissive. */ 165 if (TYPE_PTROBV_P (TREE_VALUE (targs)) && TYPE_PTROBV_P (args[i])) 166 /* Both object pointers. */; 167 else if (TYPE_PTRFN_P (TREE_VALUE (targs)) && TYPE_PTRFN_P (args[i])) 168 /* Both function pointers. */; 169 else 170 goto bad; 171 } 172 targs = TREE_CHAIN (targs); 173 } 174 if (targs != void_list_node) 175 goto bad; 176 return true; 177 } 178 179 /* Find or declare a function NAME, returning RTYPE, taking a single 180 parameter PTYPE, with an empty exception specification. ECF are the 181 library fn flags. If TM_ECF is non-zero, also find or create a 182 transaction variant and record it as a replacement, when flag_tm is 183 in effect. 184 185 Note that the C++ ABI document does not have a throw-specifier on 186 the routines declared below via this function. The declarations 187 are consistent with the actual implementations in libsupc++. */ 188 189 static tree 190 declare_library_fn (const char *name, tree rtype, tree ptype, 191 int ecf, int tm_ecf) 192 { 193 tree ident = get_identifier (name); 194 tree res = get_global_binding (ident); 195 tree fntype = NULL_TREE; 196 tree except = NULL_TREE; 197 if (!res) 198 { 199 fntype = build_function_type_list (rtype, ptype, NULL_TREE); 200 if (ecf & ECF_NOTHROW) 201 except = empty_except_spec; 202 res = push_library_fn (ident, fntype, except, ecf); 203 } 204 else if (!verify_library_fn (res, name, rtype, ptype, NULL_TREE, NULL_TREE)) 205 return error_mark_node; 206 207 if (tm_ecf && flag_tm) 208 { 209 char *tm_name = concat ("_ITM_", name + 2, NULL_TREE); 210 tree tm_ident = get_identifier (tm_name); 211 tree tm_fn = get_global_binding (tm_ident); 212 if (!tm_fn) 213 { 214 if (!fntype) 215 { 216 fntype = build_function_type_list (rtype, ptype, NULL_TREE); 217 if (ecf & ECF_NOTHROW) 218 except = empty_except_spec; 219 } 220 tm_fn = push_library_fn (tm_ident, fntype, except, ecf | tm_ecf); 221 } 222 else if (!verify_library_fn (tm_fn, tm_name, rtype, ptype, 223 NULL_TREE, NULL_TREE)) 224 tm_fn = error_mark_node; 225 free (tm_name); 226 if (tm_fn != error_mark_node) 227 record_tm_replacement (res, tm_fn); 228 } 229 return res; 230 } 231 232 /* Build up a call to __cxa_get_exception_ptr so that we can build a 233 copy constructor for the thrown object. */ 234 235 static tree 236 do_get_exception_ptr (void) 237 { 238 if (!get_exception_ptr_fn) 239 /* Declare void* __cxa_get_exception_ptr (void *) throw(). */ 240 get_exception_ptr_fn 241 = declare_library_fn ("__cxa_get_exception_ptr", 242 ptr_type_node, ptr_type_node, 243 ECF_NOTHROW | ECF_PURE | ECF_LEAF | ECF_TM_PURE, 244 0); 245 246 return cp_build_function_call_nary (get_exception_ptr_fn, 247 tf_warning_or_error, 248 build_exc_ptr (), NULL_TREE); 249 } 250 251 /* Build up a call to __cxa_begin_catch, to tell the runtime that the 252 exception has been handled. */ 253 254 static tree 255 do_begin_catch (void) 256 { 257 if (!begin_catch_fn) 258 /* Declare void* __cxa_begin_catch (void *) throw(). */ 259 begin_catch_fn 260 = declare_library_fn ("__cxa_begin_catch", 261 ptr_type_node, ptr_type_node, ECF_NOTHROW, 262 ECF_TM_PURE); 263 264 return cp_build_function_call_nary (begin_catch_fn, tf_warning_or_error, 265 build_exc_ptr (), NULL_TREE); 266 } 267 268 /* Returns nonzero if cleaning up an exception of type TYPE (which can be 269 NULL_TREE for a ... handler) will not throw an exception. */ 270 271 static int 272 dtor_nothrow (tree type) 273 { 274 if (type == NULL_TREE || type == error_mark_node) 275 return 0; 276 277 if (TYPE_HAS_TRIVIAL_DESTRUCTOR (type)) 278 return 1; 279 280 if (CLASSTYPE_LAZY_DESTRUCTOR (type)) 281 lazily_declare_fn (sfk_destructor, type); 282 283 return TREE_NOTHROW (CLASSTYPE_DESTRUCTOR (type)); 284 } 285 286 /* Build up a call to __cxa_end_catch, to destroy the exception object 287 for the current catch block if no others are currently using it. */ 288 289 static tree 290 do_end_catch (tree type) 291 { 292 if (!end_catch_fn) 293 /* Declare void __cxa_end_catch (). 294 This can throw if the destructor for the exception throws. */ 295 end_catch_fn 296 = declare_library_fn ("__cxa_end_catch", void_type_node, 297 NULL_TREE, 0, ECF_TM_PURE); 298 299 tree cleanup = cp_build_function_call_vec (end_catch_fn, 300 NULL, tf_warning_or_error); 301 if (cleanup != error_mark_node) 302 TREE_NOTHROW (cleanup) = dtor_nothrow (type); 303 304 return cleanup; 305 } 306 307 /* This routine creates the cleanup for the current exception. */ 308 309 static void 310 push_eh_cleanup (tree type) 311 { 312 finish_decl_cleanup (NULL_TREE, do_end_catch (type)); 313 } 314 315 /* Wrap EXPR in a MUST_NOT_THROW_EXPR expressing that EXPR must 316 not throw any exceptions if COND is true. A condition of 317 NULL_TREE is treated as 'true'. */ 318 319 tree 320 build_must_not_throw_expr (tree body, tree cond) 321 { 322 tree type = body ? TREE_TYPE (body) : void_type_node; 323 324 if (!flag_exceptions) 325 return body; 326 327 if (!cond) 328 /* OK, unconditional. */; 329 else 330 { 331 tree conv = NULL_TREE; 332 if (!type_dependent_expression_p (cond)) 333 conv = perform_implicit_conversion_flags (boolean_type_node, cond, 334 tf_warning_or_error, 335 LOOKUP_NORMAL); 336 if (tree inst = instantiate_non_dependent_or_null (conv)) 337 cond = cxx_constant_value (inst); 338 else 339 require_constant_expression (cond); 340 if (integer_zerop (cond)) 341 return body; 342 else if (integer_onep (cond)) 343 cond = NULL_TREE; 344 } 345 346 return build2 (MUST_NOT_THROW_EXPR, type, body, cond); 347 } 348 349 350 /* Initialize the catch parameter DECL. */ 351 352 static void 353 initialize_handler_parm (tree decl, tree exp) 354 { 355 tree init; 356 tree init_type; 357 358 /* Make sure we mark the catch param as used, otherwise we'll get a 359 warning about an unused ((anonymous)). */ 360 TREE_USED (decl) = 1; 361 DECL_READ_P (decl) = 1; 362 363 /* Figure out the type that the initializer is. Pointers are returned 364 adjusted by value from __cxa_begin_catch. Others are returned by 365 reference. */ 366 init_type = TREE_TYPE (decl); 367 if (!INDIRECT_TYPE_P (init_type)) 368 init_type = build_reference_type (init_type); 369 370 /* Since pointers are passed by value, initialize a reference to 371 pointer catch parm with the address of the temporary. */ 372 if (TYPE_REF_P (init_type) 373 && TYPE_PTR_P (TREE_TYPE (init_type))) 374 exp = cp_build_addr_expr (exp, tf_warning_or_error); 375 376 exp = ocp_convert (init_type, exp, CONV_IMPLICIT|CONV_FORCE_TEMP, 0, 377 tf_warning_or_error); 378 379 init = convert_from_reference (exp); 380 381 /* If the constructor for the catch parm exits via an exception, we 382 must call terminate. See eh23.C. */ 383 if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl))) 384 { 385 /* Generate the copy constructor call directly so we can wrap it. 386 See also expand_default_init. */ 387 init = ocp_convert (TREE_TYPE (decl), init, 388 CONV_IMPLICIT|CONV_FORCE_TEMP, 0, 389 tf_warning_or_error); 390 /* Force cleanups now to avoid nesting problems with the 391 MUST_NOT_THROW_EXPR. */ 392 init = fold_build_cleanup_point_expr (TREE_TYPE (init), init); 393 init = build_must_not_throw_expr (init, NULL_TREE); 394 } 395 396 decl = pushdecl (decl); 397 398 start_decl_1 (decl, true); 399 cp_finish_decl (decl, init, /*init_const_expr_p=*/false, NULL_TREE, 400 LOOKUP_ONLYCONVERTING|DIRECT_BIND); 401 } 402 403 404 /* Routine to see if exception handling is turned on. 405 DO_WARN is nonzero if we want to inform the user that exception 406 handling is turned off. 407 408 This is used to ensure that -fexceptions has been specified if the 409 compiler tries to use any exception-specific functions. */ 410 411 static inline int 412 doing_eh (void) 413 { 414 if (! flag_exceptions) 415 { 416 static int warned = 0; 417 if (! warned) 418 { 419 error ("exception handling disabled, use %<-fexceptions%> to enable"); 420 warned = 1; 421 } 422 return 0; 423 } 424 return 1; 425 } 426 427 /* Call this to start a catch block. DECL is the catch parameter. */ 428 429 tree 430 expand_start_catch_block (tree decl) 431 { 432 tree exp; 433 tree type, init; 434 435 if (! doing_eh ()) 436 return NULL_TREE; 437 438 if (decl) 439 { 440 if (!is_admissible_throw_operand_or_catch_parameter (decl, false)) 441 decl = error_mark_node; 442 443 type = prepare_eh_type (TREE_TYPE (decl)); 444 mark_used (eh_type_info (type)); 445 } 446 else 447 type = NULL_TREE; 448 449 /* Call __cxa_end_catch at the end of processing the exception. */ 450 push_eh_cleanup (type); 451 452 init = do_begin_catch (); 453 454 /* If there's no decl at all, then all we need to do is make sure 455 to tell the runtime that we've begun handling the exception. */ 456 if (decl == NULL || decl == error_mark_node || init == error_mark_node) 457 finish_expr_stmt (init); 458 459 /* If the C++ object needs constructing, we need to do that before 460 calling __cxa_begin_catch, so that std::uncaught_exception gets 461 the right value during the copy constructor. */ 462 else if (flag_use_cxa_get_exception_ptr 463 && TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl))) 464 { 465 exp = do_get_exception_ptr (); 466 if (exp != error_mark_node) 467 initialize_handler_parm (decl, exp); 468 finish_expr_stmt (init); 469 } 470 471 /* Otherwise the type uses a bitwise copy, and we don't have to worry 472 about the value of std::uncaught_exception and therefore can do the 473 copy with the return value of __cxa_end_catch instead. */ 474 else 475 { 476 tree init_type = type; 477 478 /* Pointers are passed by values, everything else by reference. */ 479 if (!TYPE_PTR_P (type)) 480 init_type = build_pointer_type (type); 481 if (init_type != TREE_TYPE (init)) 482 init = build1 (NOP_EXPR, init_type, init); 483 exp = create_temporary_var (init_type); 484 cp_finish_decl (exp, init, /*init_const_expr=*/false, 485 NULL_TREE, LOOKUP_ONLYCONVERTING); 486 DECL_REGISTER (exp) = 1; 487 initialize_handler_parm (decl, exp); 488 } 489 490 return type; 491 } 492 493 494 /* Call this to end a catch block. Its responsible for emitting the 495 code to handle jumping back to the correct place, and for emitting 496 the label to jump to if this catch block didn't match. */ 497 498 void 499 expand_end_catch_block (void) 500 { 501 if (! doing_eh ()) 502 return; 503 504 /* The exception being handled is rethrown if control reaches the end of 505 a handler of the function-try-block of a constructor or destructor. */ 506 if (in_function_try_handler 507 && (DECL_CONSTRUCTOR_P (current_function_decl) 508 || DECL_DESTRUCTOR_P (current_function_decl))) 509 { 510 tree rethrow = build_throw (input_location, NULL_TREE); 511 TREE_NO_WARNING (rethrow) = true; 512 finish_expr_stmt (rethrow); 513 } 514 } 515 516 tree 517 begin_eh_spec_block (void) 518 { 519 tree r; 520 location_t spec_location = DECL_SOURCE_LOCATION (current_function_decl); 521 522 /* A noexcept specification (or throw() with -fnothrow-opt) is a 523 MUST_NOT_THROW_EXPR. */ 524 if (TYPE_NOEXCEPT_P (TREE_TYPE (current_function_decl))) 525 { 526 r = build_stmt (spec_location, MUST_NOT_THROW_EXPR, 527 NULL_TREE, NULL_TREE); 528 TREE_SIDE_EFFECTS (r) = 1; 529 } 530 else 531 r = build_stmt (spec_location, EH_SPEC_BLOCK, NULL_TREE, NULL_TREE); 532 add_stmt (r); 533 TREE_OPERAND (r, 0) = push_stmt_list (); 534 return r; 535 } 536 537 void 538 finish_eh_spec_block (tree raw_raises, tree eh_spec_block) 539 { 540 tree raises; 541 542 TREE_OPERAND (eh_spec_block, 0) 543 = pop_stmt_list (TREE_OPERAND (eh_spec_block, 0)); 544 545 if (TREE_CODE (eh_spec_block) == MUST_NOT_THROW_EXPR) 546 return; 547 548 /* Strip cv quals, etc, from the specification types. */ 549 for (raises = NULL_TREE; 550 raw_raises && TREE_VALUE (raw_raises); 551 raw_raises = TREE_CHAIN (raw_raises)) 552 { 553 tree type = prepare_eh_type (TREE_VALUE (raw_raises)); 554 tree tinfo = eh_type_info (type); 555 556 mark_used (tinfo); 557 raises = tree_cons (NULL_TREE, type, raises); 558 } 559 560 EH_SPEC_RAISES (eh_spec_block) = raises; 561 } 562 563 /* Return a pointer to a buffer for an exception object of type TYPE. */ 564 565 static tree 566 do_allocate_exception (tree type) 567 { 568 if (!allocate_exception_fn) 569 /* Declare void *__cxa_allocate_exception(size_t) throw(). */ 570 allocate_exception_fn 571 = declare_library_fn ("__cxa_allocate_exception", 572 ptr_type_node, size_type_node, 573 ECF_NOTHROW | ECF_MALLOC | ECF_COLD, ECF_TM_PURE); 574 575 return cp_build_function_call_nary (allocate_exception_fn, 576 tf_warning_or_error, 577 size_in_bytes (type), NULL_TREE); 578 } 579 580 /* Call __cxa_free_exception from a cleanup. This is never invoked 581 directly, but see the comment for stabilize_throw_expr. */ 582 583 static tree 584 do_free_exception (tree ptr) 585 { 586 if (!free_exception_fn) 587 /* Declare void __cxa_free_exception (void *) throw(). */ 588 free_exception_fn 589 = declare_library_fn ("__cxa_free_exception", 590 void_type_node, ptr_type_node, 591 ECF_NOTHROW | ECF_LEAF, ECF_TM_PURE); 592 593 return cp_build_function_call_nary (free_exception_fn, 594 tf_warning_or_error, ptr, NULL_TREE); 595 } 596 597 /* Wrap all cleanups for TARGET_EXPRs in MUST_NOT_THROW_EXPR. 598 Called from build_throw via walk_tree_without_duplicates. */ 599 600 static tree 601 wrap_cleanups_r (tree *tp, int *walk_subtrees, void * /*data*/) 602 { 603 tree exp = *tp; 604 tree cleanup; 605 606 /* Don't walk into types. */ 607 if (TYPE_P (exp)) 608 { 609 *walk_subtrees = 0; 610 return NULL_TREE; 611 } 612 if (TREE_CODE (exp) != TARGET_EXPR) 613 return NULL_TREE; 614 615 cleanup = TARGET_EXPR_CLEANUP (exp); 616 if (cleanup) 617 { 618 cleanup = build2 (MUST_NOT_THROW_EXPR, void_type_node, cleanup, 619 NULL_TREE); 620 TARGET_EXPR_CLEANUP (exp) = cleanup; 621 } 622 623 /* Keep iterating. */ 624 return NULL_TREE; 625 } 626 627 /* Build a throw expression. */ 628 629 tree 630 build_throw (location_t loc, tree exp) 631 { 632 if (exp == error_mark_node) 633 return exp; 634 635 if (processing_template_decl) 636 { 637 if (cfun) 638 current_function_returns_abnormally = 1; 639 exp = build_min (THROW_EXPR, void_type_node, exp); 640 SET_EXPR_LOCATION (exp, loc); 641 return exp; 642 } 643 644 if (exp && null_node_p (exp)) 645 warning_at (loc, 0, 646 "throwing NULL, which has integral, not pointer type"); 647 648 if (exp != NULL_TREE) 649 { 650 if (!is_admissible_throw_operand_or_catch_parameter (exp, true)) 651 return error_mark_node; 652 } 653 654 if (! doing_eh ()) 655 return error_mark_node; 656 657 if (exp) 658 { 659 tree throw_type; 660 tree temp_type; 661 tree cleanup; 662 tree object, ptr; 663 tree tmp; 664 tree allocate_expr; 665 666 /* The CLEANUP_TYPE is the internal type of a destructor. */ 667 if (!cleanup_type) 668 { 669 tmp = build_function_type_list (void_type_node, 670 ptr_type_node, NULL_TREE); 671 cleanup_type = build_pointer_type (tmp); 672 } 673 674 if (!throw_fn) 675 { 676 const char *name = "__cxa_throw"; 677 tree ident = get_identifier (name); 678 tree fntype = NULL_TREE; 679 throw_fn = get_global_binding (ident); 680 if (!throw_fn) 681 { 682 /* Declare void __cxa_throw (void*, void*, void (*)(void*)). */ 683 /* ??? Second argument is supposed to be "std::type_info*". */ 684 fntype = build_function_type_list (void_type_node, 685 ptr_type_node, ptr_type_node, 686 cleanup_type, NULL_TREE); 687 throw_fn = push_throw_library_fn (ident, fntype); 688 } 689 else if (!verify_library_fn (throw_fn, name, void_type_node, 690 ptr_type_node, ptr_type_node, 691 cleanup_type)) 692 throw_fn = error_mark_node; 693 694 if (flag_tm && throw_fn != error_mark_node) 695 { 696 const char *itm_name = "_ITM_cxa_throw"; 697 tree itm_ident = get_identifier (itm_name); 698 tree itm_fn = get_global_binding (itm_ident); 699 if (!itm_fn) 700 { 701 if (!fntype) 702 fntype 703 = build_function_type_list (void_type_node, 704 ptr_type_node, ptr_type_node, 705 cleanup_type, NULL_TREE); 706 itm_fn = push_throw_library_fn (itm_ident, fntype); 707 } 708 else if (!verify_library_fn (itm_fn, itm_name, void_type_node, 709 ptr_type_node, ptr_type_node, 710 cleanup_type)) 711 itm_fn = error_mark_node; 712 if (itm_fn != error_mark_node) 713 { 714 apply_tm_attr (itm_fn, get_identifier ("transaction_pure")); 715 record_tm_replacement (throw_fn, itm_fn); 716 } 717 } 718 } 719 720 /* [except.throw] 721 722 A throw-expression initializes a temporary object, the type 723 of which is determined by removing any top-level 724 cv-qualifiers from the static type of the operand of throw 725 and adjusting the type from "array of T" or "function return 726 T" to "pointer to T" or "pointer to function returning T" 727 respectively. */ 728 temp_type = is_bitfield_expr_with_lowered_type (exp); 729 if (!temp_type) 730 temp_type = cv_unqualified (type_decays_to (TREE_TYPE (exp))); 731 732 /* OK, this is kind of wacky. The standard says that we call 733 terminate when the exception handling mechanism, after 734 completing evaluation of the expression to be thrown but 735 before the exception is caught (_except.throw_), calls a 736 user function that exits via an uncaught exception. 737 738 So we have to protect the actual initialization of the 739 exception object with terminate(), but evaluate the 740 expression first. Since there could be temps in the 741 expression, we need to handle that, too. We also expand 742 the call to __cxa_allocate_exception first (which doesn't 743 matter, since it can't throw). */ 744 745 /* Allocate the space for the exception. */ 746 allocate_expr = do_allocate_exception (temp_type); 747 if (allocate_expr == error_mark_node) 748 return error_mark_node; 749 allocate_expr = get_target_expr (allocate_expr); 750 ptr = TARGET_EXPR_SLOT (allocate_expr); 751 TARGET_EXPR_CLEANUP (allocate_expr) = do_free_exception (ptr); 752 CLEANUP_EH_ONLY (allocate_expr) = 1; 753 754 object = build_nop (build_pointer_type (temp_type), ptr); 755 object = cp_build_fold_indirect_ref (object); 756 757 /* And initialize the exception object. */ 758 if (CLASS_TYPE_P (temp_type)) 759 { 760 int flags = LOOKUP_NORMAL | LOOKUP_ONLYCONVERTING; 761 bool converted = false; 762 location_t exp_loc = cp_expr_loc_or_loc (exp, loc); 763 764 /* Under C++0x [12.8/16 class.copy], a thrown lvalue is sometimes 765 treated as an rvalue for the purposes of overload resolution 766 to favor move constructors over copy constructors. */ 767 if (treat_lvalue_as_rvalue_p (exp, /*parm_ok*/false) 768 /* The variable must not have the `volatile' qualifier. */ 769 && !CP_TYPE_VOLATILE_P (TREE_TYPE (exp))) 770 { 771 tree moved = move (exp); 772 releasing_vec exp_vec (make_tree_vector_single (moved)); 773 moved = (build_special_member_call 774 (object, complete_ctor_identifier, &exp_vec, 775 TREE_TYPE (object), flags|LOOKUP_PREFER_RVALUE, 776 tf_none)); 777 if (moved != error_mark_node) 778 { 779 exp = moved; 780 converted = true; 781 } 782 } 783 784 /* Call the copy constructor. */ 785 if (!converted) 786 { 787 releasing_vec exp_vec (make_tree_vector_single (exp)); 788 exp = (build_special_member_call 789 (object, complete_ctor_identifier, &exp_vec, 790 TREE_TYPE (object), flags, tf_warning_or_error)); 791 } 792 793 if (exp == error_mark_node) 794 { 795 inform (exp_loc, " in thrown expression"); 796 return error_mark_node; 797 } 798 } 799 else 800 { 801 tmp = decay_conversion (exp, tf_warning_or_error); 802 if (tmp == error_mark_node) 803 return error_mark_node; 804 exp = build2 (INIT_EXPR, temp_type, object, tmp); 805 } 806 807 /* Mark any cleanups from the initialization as MUST_NOT_THROW, since 808 they are run after the exception object is initialized. */ 809 cp_walk_tree_without_duplicates (&exp, wrap_cleanups_r, 0); 810 811 /* Prepend the allocation. */ 812 exp = build2 (COMPOUND_EXPR, TREE_TYPE (exp), allocate_expr, exp); 813 814 /* Force all the cleanups to be evaluated here so that we don't have 815 to do them during unwinding. */ 816 exp = build1 (CLEANUP_POINT_EXPR, void_type_node, exp); 817 818 throw_type = build_eh_type_type (prepare_eh_type (TREE_TYPE (object))); 819 820 cleanup = NULL_TREE; 821 if (type_build_dtor_call (TREE_TYPE (object))) 822 { 823 tree dtor_fn = lookup_fnfields (TYPE_BINFO (TREE_TYPE (object)), 824 complete_dtor_identifier, 0); 825 dtor_fn = BASELINK_FUNCTIONS (dtor_fn); 826 mark_used (dtor_fn); 827 if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (object))) 828 { 829 cxx_mark_addressable (dtor_fn); 830 /* Pretend it's a normal function. */ 831 cleanup = build1 (ADDR_EXPR, cleanup_type, dtor_fn); 832 } 833 } 834 if (cleanup == NULL_TREE) 835 cleanup = build_int_cst (cleanup_type, 0); 836 837 /* ??? Indicate that this function call throws throw_type. */ 838 tmp = cp_build_function_call_nary (throw_fn, tf_warning_or_error, 839 ptr, throw_type, cleanup, NULL_TREE); 840 841 /* Tack on the initialization stuff. */ 842 exp = build2 (COMPOUND_EXPR, TREE_TYPE (tmp), exp, tmp); 843 } 844 else 845 { 846 /* Rethrow current exception. */ 847 if (!rethrow_fn) 848 { 849 const char *name = "__cxa_rethrow"; 850 tree ident = get_identifier (name); 851 rethrow_fn = get_global_binding (ident); 852 if (!rethrow_fn) 853 { 854 /* Declare void __cxa_rethrow (void). */ 855 tree fntype 856 = build_function_type_list (void_type_node, NULL_TREE); 857 rethrow_fn = push_throw_library_fn (ident, fntype); 858 } 859 else if (!verify_library_fn (rethrow_fn, name, void_type_node, 860 NULL_TREE, NULL_TREE, NULL_TREE)) 861 rethrow_fn = error_mark_node; 862 863 if (flag_tm && rethrow_fn != error_mark_node) 864 apply_tm_attr (rethrow_fn, get_identifier ("transaction_pure")); 865 } 866 867 /* ??? Indicate that this function call allows exceptions of the type 868 of the enclosing catch block (if known). */ 869 exp = cp_build_function_call_vec (rethrow_fn, NULL, tf_warning_or_error); 870 } 871 872 exp = build1_loc (loc, THROW_EXPR, void_type_node, exp); 873 874 return exp; 875 } 876 877 /* Make sure TYPE is complete, pointer to complete, reference to 878 complete, or pointer to cv void. Issue diagnostic on failure. 879 Return the zero on failure and nonzero on success. FROM can be 880 the expr or decl from whence TYPE came, if available. */ 881 882 static int 883 complete_ptr_ref_or_void_ptr_p (tree type, tree from) 884 { 885 int is_ptr; 886 887 /* Check complete. */ 888 type = complete_type_or_else (type, from); 889 if (!type) 890 return 0; 891 892 /* Or a pointer or ref to one, or cv void *. */ 893 is_ptr = TYPE_PTR_P (type); 894 if (is_ptr || TYPE_REF_P (type)) 895 { 896 tree core = TREE_TYPE (type); 897 898 if (is_ptr && VOID_TYPE_P (core)) 899 /* OK */; 900 else if (!complete_type_or_else (core, from)) 901 return 0; 902 } 903 return 1; 904 } 905 906 /* If IS_THROW is true return truth-value if T is an expression admissible 907 in throw-expression, i.e. if it is not of incomplete type or a pointer/ 908 reference to such a type or of an abstract class type. 909 If IS_THROW is false, likewise for a catch parameter, same requirements 910 for its type plus rvalue reference type is also not admissible. */ 911 912 static bool 913 is_admissible_throw_operand_or_catch_parameter (tree t, bool is_throw) 914 { 915 tree expr = is_throw ? t : NULL_TREE; 916 tree type = TREE_TYPE (t); 917 918 /* C++11 [except.handle] The exception-declaration shall not denote 919 an incomplete type, an abstract class type, or an rvalue reference 920 type. */ 921 922 /* 15.1/4 [...] The type of the throw-expression shall not be an 923 incomplete type, or a pointer or a reference to an incomplete 924 type, other than void*, const void*, volatile void*, or 925 const volatile void*. Except for these restriction and the 926 restrictions on type matching mentioned in 15.3, the operand 927 of throw is treated exactly as a function argument in a call 928 (5.2.2) or the operand of a return statement. */ 929 if (!complete_ptr_ref_or_void_ptr_p (type, expr)) 930 return false; 931 932 tree nonref_type = non_reference (type); 933 if (!verify_type_context (input_location, TCTX_EXCEPTIONS, nonref_type)) 934 return false; 935 936 /* 10.4/3 An abstract class shall not be used as a parameter type, 937 as a function return type or as type of an explicit 938 conversion. */ 939 else if (abstract_virtuals_error (is_throw ? ACU_THROW : ACU_CATCH, type)) 940 return false; 941 else if (!is_throw 942 && TYPE_REF_P (type) 943 && TYPE_REF_IS_RVALUE (type)) 944 { 945 error ("cannot declare %<catch%> parameter to be of rvalue " 946 "reference type %qT", type); 947 return false; 948 } 949 else if (variably_modified_type_p (type, NULL_TREE)) 950 { 951 if (is_throw) 952 error_at (cp_expr_loc_or_input_loc (expr), 953 "cannot throw expression of type %qT because it involves " 954 "types of variable size", type); 955 else 956 error ("cannot catch type %qT because it involves types of " 957 "variable size", type); 958 return false; 959 } 960 961 return true; 962 } 963 964 /* Returns nonzero if FN is a declaration of a standard C library 965 function which is known not to throw. 966 967 [lib.res.on.exception.handling]: None of the functions from the 968 Standard C library shall report an error by throwing an 969 exception, unless it calls a program-supplied function that 970 throws an exception. */ 971 972 #include "cfns.h" 973 974 int 975 nothrow_libfn_p (const_tree fn) 976 { 977 tree id; 978 979 if (TREE_PUBLIC (fn) 980 && DECL_EXTERNAL (fn) 981 && DECL_NAMESPACE_SCOPE_P (fn) 982 && DECL_EXTERN_C_P (fn)) 983 /* OK */; 984 else 985 /* Can't be a C library function. */ 986 return 0; 987 988 /* Being a C library function, DECL_ASSEMBLER_NAME == DECL_NAME 989 unless the system headers are playing rename tricks, and if 990 they are, we don't want to be confused by them. */ 991 id = DECL_NAME (fn); 992 const struct libc_name_struct *s 993 = libc_name::libc_name_p (IDENTIFIER_POINTER (id), IDENTIFIER_LENGTH (id)); 994 if (s == NULL) 995 return 0; 996 switch (s->c_ver) 997 { 998 case 89: return 1; 999 case 99: return !flag_iso || flag_isoc99; 1000 case 11: return !flag_iso || flag_isoc11; 1001 default: gcc_unreachable (); 1002 } 1003 } 1004 1005 /* Returns nonzero if an exception of type FROM will be caught by a 1006 handler for type TO, as per [except.handle]. */ 1007 1008 static int 1009 can_convert_eh (tree to, tree from) 1010 { 1011 to = non_reference (to); 1012 from = non_reference (from); 1013 1014 if (TYPE_PTR_P (to) && TYPE_PTR_P (from)) 1015 { 1016 to = TREE_TYPE (to); 1017 from = TREE_TYPE (from); 1018 1019 if (! at_least_as_qualified_p (to, from)) 1020 return 0; 1021 1022 if (VOID_TYPE_P (to)) 1023 return 1; 1024 1025 /* Else fall through. */ 1026 } 1027 1028 if (CLASS_TYPE_P (to) && CLASS_TYPE_P (from) 1029 && publicly_uniquely_derived_p (to, from)) 1030 return 1; 1031 1032 return 0; 1033 } 1034 1035 /* Check whether any of the handlers in I are shadowed by another handler 1036 accepting TYPE. Note that the shadowing may not be complete; even if 1037 an exception of type B would be caught by a handler for A, there could 1038 be a derived class C for which A is an ambiguous base but B is not, so 1039 the handler for B would catch an exception of type C. */ 1040 1041 static void 1042 check_handlers_1 (tree master, tree_stmt_iterator i) 1043 { 1044 tree type = TREE_TYPE (master); 1045 1046 for (; !tsi_end_p (i); tsi_next (&i)) 1047 { 1048 tree handler = tsi_stmt (i); 1049 if (TREE_TYPE (handler) && can_convert_eh (type, TREE_TYPE (handler))) 1050 { 1051 warning_at (EXPR_LOCATION (handler), 0, 1052 "exception of type %qT will be caught", 1053 TREE_TYPE (handler)); 1054 warning_at (EXPR_LOCATION (master), 0, 1055 " by earlier handler for %qT", type); 1056 break; 1057 } 1058 } 1059 } 1060 1061 /* Given a STATEMENT_LIST of HANDLERs, make sure that they're OK. */ 1062 1063 void 1064 check_handlers (tree handlers) 1065 { 1066 tree_stmt_iterator i; 1067 1068 /* If we don't have a STATEMENT_LIST, then we've just got one 1069 handler, and thus nothing to warn about. */ 1070 if (TREE_CODE (handlers) != STATEMENT_LIST) 1071 return; 1072 1073 i = tsi_start (handlers); 1074 if (!tsi_end_p (i)) 1075 while (1) 1076 { 1077 tree handler = tsi_stmt (i); 1078 tsi_next (&i); 1079 1080 /* No more handlers; nothing to shadow. */ 1081 if (tsi_end_p (i)) 1082 break; 1083 if (TREE_TYPE (handler) == NULL_TREE) 1084 permerror (EXPR_LOCATION (handler), "%<...%>" 1085 " handler must be the last handler for its try block"); 1086 else 1087 check_handlers_1 (handler, i); 1088 } 1089 } 1090 1091 /* walk_tree helper for finish_noexcept_expr. Returns non-null if the 1092 expression *TP causes the noexcept operator to evaluate to false. 1093 1094 5.3.7 [expr.noexcept]: The result of the noexcept operator is false if 1095 in a potentially-evaluated context the expression would contain 1096 * a potentially evaluated call to a function, member function, 1097 function pointer, or member function pointer that does not have a 1098 non-throwing exception-specification (15.4), 1099 * a potentially evaluated throw-expression (15.1), 1100 * a potentially evaluated dynamic_cast expression dynamic_cast<T>(v), 1101 where T is a reference type, that requires a run-time check (5.2.7), or 1102 * a potentially evaluated typeid expression (5.2.8) applied to a glvalue 1103 expression whose type is a polymorphic class type (10.3). */ 1104 1105 static tree 1106 check_noexcept_r (tree *tp, int *walk_subtrees, void *) 1107 { 1108 tree t = *tp; 1109 enum tree_code code = TREE_CODE (t); 1110 1111 if (unevaluated_p (code)) 1112 *walk_subtrees = false; 1113 else if ((code == CALL_EXPR && CALL_EXPR_FN (t)) 1114 || code == AGGR_INIT_EXPR) 1115 { 1116 /* We can only use the exception specification of the called function 1117 for determining the value of a noexcept expression; we can't use 1118 TREE_NOTHROW, as it might have a different value in another 1119 translation unit, creating ODR problems. 1120 1121 We could use TREE_NOTHROW (t) for !TREE_PUBLIC fns, though... */ 1122 tree fn = cp_get_callee (t); 1123 if (concept_check_p (fn)) 1124 return NULL_TREE; 1125 tree type = TREE_TYPE (fn); 1126 gcc_assert (INDIRECT_TYPE_P (type)); 1127 type = TREE_TYPE (type); 1128 1129 STRIP_NOPS (fn); 1130 if (TREE_CODE (fn) == ADDR_EXPR) 1131 fn = TREE_OPERAND (fn, 0); 1132 if (TREE_CODE (fn) == FUNCTION_DECL) 1133 { 1134 /* We do use TREE_NOTHROW for ABI internals like __dynamic_cast, 1135 and for C library functions known not to throw. */ 1136 if (DECL_EXTERN_C_P (fn) 1137 && (DECL_ARTIFICIAL (fn) 1138 || nothrow_libfn_p (fn))) 1139 return TREE_NOTHROW (fn) ? NULL_TREE : fn; 1140 /* We used to treat a call to a constexpr function as noexcept if 1141 the call was a constant expression (CWG 1129). This has changed 1142 in P0003 whereby noexcept has no special rule for constant 1143 expressions anymore. Since the current behavior is important for 1144 certain library functionality, we treat this as a DR, therefore 1145 adjusting the behavior for C++11 and C++14. Previously, we had 1146 to evaluate the noexcept-specifier's operand here, but that could 1147 cause instantiations that would fail. */ 1148 } 1149 if (!TYPE_NOTHROW_P (type)) 1150 return fn; 1151 } 1152 1153 return NULL_TREE; 1154 } 1155 1156 /* If a function that causes a noexcept-expression to be false isn't 1157 defined yet, remember it and check it for TREE_NOTHROW again at EOF. */ 1158 1159 struct GTY(()) pending_noexcept { 1160 tree fn; 1161 location_t loc; 1162 }; 1163 static GTY(()) vec<pending_noexcept, va_gc> *pending_noexcept_checks; 1164 1165 /* FN is a FUNCTION_DECL that caused a noexcept-expr to be false. Warn if 1166 it can't throw. 1167 1168 TODO: Consider extending -Wnoexcept to do something like walk_subtrees in the 1169 case of a defaulted function that obtained a noexcept(false) spec. */ 1170 1171 static void 1172 maybe_noexcept_warning (tree fn) 1173 { 1174 if (TREE_NOTHROW (fn) 1175 && (!DECL_IN_SYSTEM_HEADER (fn) 1176 || global_dc->dc_warn_system_headers)) 1177 { 1178 temp_override<bool> s (global_dc->dc_warn_system_headers, true); 1179 auto_diagnostic_group d; 1180 if (warning (OPT_Wnoexcept, "noexcept-expression evaluates to %<false%> " 1181 "because of a call to %qD", fn)) 1182 inform (DECL_SOURCE_LOCATION (fn), 1183 "but %qD does not throw; perhaps " 1184 "it should be declared %<noexcept%>", fn); 1185 } 1186 } 1187 1188 /* Check any functions that weren't defined earlier when they caused a 1189 noexcept expression to evaluate to false. */ 1190 1191 void 1192 perform_deferred_noexcept_checks (void) 1193 { 1194 int i; 1195 pending_noexcept *p; 1196 location_t saved_loc = input_location; 1197 FOR_EACH_VEC_SAFE_ELT (pending_noexcept_checks, i, p) 1198 { 1199 input_location = p->loc; 1200 maybe_noexcept_warning (p->fn); 1201 } 1202 input_location = saved_loc; 1203 } 1204 1205 /* Evaluate noexcept ( EXPR ). */ 1206 1207 tree 1208 finish_noexcept_expr (tree expr, tsubst_flags_t complain) 1209 { 1210 if (expr == error_mark_node) 1211 return error_mark_node; 1212 1213 if (processing_template_decl) 1214 return build_min (NOEXCEPT_EXPR, boolean_type_node, expr); 1215 1216 return (expr_noexcept_p (expr, complain) 1217 ? boolean_true_node : boolean_false_node); 1218 } 1219 1220 /* Returns whether EXPR is noexcept, possibly warning if allowed by 1221 COMPLAIN. */ 1222 1223 bool 1224 expr_noexcept_p (tree expr, tsubst_flags_t complain) 1225 { 1226 tree fn; 1227 1228 if (expr == error_mark_node) 1229 return false; 1230 1231 fn = cp_walk_tree_without_duplicates (&expr, check_noexcept_r, 0); 1232 if (fn) 1233 { 1234 if ((complain & tf_warning) && warn_noexcept 1235 && TREE_CODE (fn) == FUNCTION_DECL) 1236 { 1237 if (!DECL_INITIAL (fn)) 1238 { 1239 /* Not defined yet; check again at EOF. */ 1240 pending_noexcept p = {fn, input_location}; 1241 vec_safe_push (pending_noexcept_checks, p); 1242 } 1243 else 1244 maybe_noexcept_warning (fn); 1245 } 1246 return false; 1247 } 1248 else 1249 return true; 1250 } 1251 1252 /* Return true iff SPEC is throw() or noexcept(true). */ 1253 1254 bool 1255 nothrow_spec_p (const_tree spec) 1256 { 1257 gcc_assert (!DEFERRED_NOEXCEPT_SPEC_P (spec)); 1258 1259 if (spec == empty_except_spec 1260 || spec == noexcept_true_spec) 1261 return true; 1262 1263 gcc_assert (!spec 1264 || TREE_VALUE (spec) 1265 || spec == noexcept_false_spec 1266 || TREE_PURPOSE (spec) == error_mark_node 1267 || UNPARSED_NOEXCEPT_SPEC_P (spec) 1268 || processing_template_decl); 1269 1270 return false; 1271 } 1272 1273 /* For FUNCTION_TYPE or METHOD_TYPE, true if NODE is noexcept. This is the 1274 case for things declared noexcept(true) and, with -fnothrow-opt, for 1275 throw() functions. */ 1276 1277 bool 1278 type_noexcept_p (const_tree type) 1279 { 1280 tree spec = TYPE_RAISES_EXCEPTIONS (type); 1281 gcc_assert (!DEFERRED_NOEXCEPT_SPEC_P (spec)); 1282 if (flag_nothrow_opt) 1283 return nothrow_spec_p (spec); 1284 else 1285 return spec == noexcept_true_spec; 1286 } 1287 1288 /* For FUNCTION_TYPE or METHOD_TYPE, true if NODE can throw any type, 1289 i.e. no exception-specification or noexcept(false). */ 1290 1291 bool 1292 type_throw_all_p (const_tree type) 1293 { 1294 tree spec = TYPE_RAISES_EXCEPTIONS (type); 1295 gcc_assert (!DEFERRED_NOEXCEPT_SPEC_P (spec)); 1296 return spec == NULL_TREE || spec == noexcept_false_spec; 1297 } 1298 1299 /* Create a representation of the noexcept-specification with 1300 constant-expression of EXPR. COMPLAIN is as for tsubst. */ 1301 1302 tree 1303 build_noexcept_spec (tree expr, tsubst_flags_t complain) 1304 { 1305 if (TREE_CODE (expr) != DEFERRED_NOEXCEPT 1306 && !value_dependent_expression_p (expr)) 1307 { 1308 expr = build_converted_constant_bool_expr (expr, complain); 1309 expr = instantiate_non_dependent_expr_sfinae (expr, complain); 1310 expr = cxx_constant_value (expr); 1311 } 1312 if (TREE_CODE (expr) == INTEGER_CST) 1313 { 1314 if (operand_equal_p (expr, boolean_true_node, 0)) 1315 return noexcept_true_spec; 1316 else 1317 { 1318 gcc_checking_assert (operand_equal_p (expr, boolean_false_node, 0)); 1319 return noexcept_false_spec; 1320 } 1321 } 1322 else if (expr == error_mark_node) 1323 return error_mark_node; 1324 else 1325 { 1326 gcc_assert (processing_template_decl 1327 || TREE_CODE (expr) == DEFERRED_NOEXCEPT); 1328 if (TREE_CODE (expr) != DEFERRED_NOEXCEPT) 1329 /* Avoid problems with a function type built with a dependent typedef 1330 being reused in another scope (c++/84045). */ 1331 expr = strip_typedefs_expr (expr); 1332 return build_tree_list (expr, NULL_TREE); 1333 } 1334 } 1335 1336 /* If the current function has a cleanup that might throw, and the return value 1337 has a non-trivial destructor, return a MODIFY_EXPR to set 1338 current_retval_sentinel so that we know that the return value needs to be 1339 destroyed on throw. Otherwise, returns NULL_TREE. */ 1340 1341 tree 1342 maybe_set_retval_sentinel () 1343 { 1344 if (processing_template_decl) 1345 return NULL_TREE; 1346 tree retval = DECL_RESULT (current_function_decl); 1347 if (!TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (retval))) 1348 return NULL_TREE; 1349 if (!cp_function_chain->throwing_cleanup) 1350 return NULL_TREE; 1351 1352 if (!current_retval_sentinel) 1353 { 1354 /* Just create the temporary now, maybe_splice_retval_cleanup 1355 will do the rest. */ 1356 current_retval_sentinel = create_temporary_var (boolean_type_node); 1357 DECL_INITIAL (current_retval_sentinel) = boolean_false_node; 1358 pushdecl_outermost_localscope (current_retval_sentinel); 1359 } 1360 1361 return build2 (MODIFY_EXPR, boolean_type_node, 1362 current_retval_sentinel, boolean_true_node); 1363 } 1364 1365 /* COMPOUND_STMT is the STATEMENT_LIST for the current function body. If 1366 current_retval_sentinel was set in this function, wrap the body in a 1367 CLEANUP_STMT to destroy the return value on throw. */ 1368 1369 void 1370 maybe_splice_retval_cleanup (tree compound_stmt) 1371 { 1372 /* If need_retval_cleanup set current_retval_sentinel, wrap the function body 1373 in a CLEANUP_STMT to handle destroying the return value. */ 1374 if (!DECL_CONSTRUCTOR_P (current_function_decl) 1375 && !DECL_DESTRUCTOR_P (current_function_decl) 1376 && current_retval_sentinel) 1377 { 1378 location_t loc = DECL_SOURCE_LOCATION (current_function_decl); 1379 1380 /* Add a DECL_EXPR for current_retval_sentinel. */ 1381 tree_stmt_iterator iter = tsi_start (compound_stmt); 1382 tree retval = DECL_RESULT (current_function_decl); 1383 tree decl_expr = build_stmt (loc, DECL_EXPR, current_retval_sentinel); 1384 tsi_link_before (&iter, decl_expr, TSI_SAME_STMT); 1385 1386 /* Skip past other decls, they can't contain a return. */ 1387 while (TREE_CODE (tsi_stmt (iter)) == DECL_EXPR) 1388 tsi_next (&iter); 1389 gcc_assert (!tsi_end_p (iter)); 1390 1391 /* Wrap the rest of the STATEMENT_LIST in a CLEANUP_STMT. */ 1392 tree stmts = NULL_TREE; 1393 while (!tsi_end_p (iter)) 1394 { 1395 append_to_statement_list_force (tsi_stmt (iter), &stmts); 1396 tsi_delink (&iter); 1397 } 1398 tree dtor = build_cleanup (retval); 1399 tree cond = build3 (COND_EXPR, void_type_node, current_retval_sentinel, 1400 dtor, void_node); 1401 tree cleanup = build_stmt (loc, CLEANUP_STMT, 1402 stmts, cond, retval); 1403 CLEANUP_EH_ONLY (cleanup) = true; 1404 append_to_statement_list_force (cleanup, &compound_stmt); 1405 } 1406 } 1407 1408 #include "gt-cp-except.h" 1409