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. --- 17 unchanged lines hidden (view full) --- 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 "output.h" 35#include "except.h" 36#include "toplev.h" |
37#include "tree-inline.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 tree stabilize_throw_expr PARAMS ((tree, tree *)); 50static tree wrap_cleanups_r PARAMS ((tree *, int *, void *)); |
51static int complete_ptr_ref_or_void_ptr_p PARAMS ((tree, tree)); 52static bool is_admissible_throw_operand PARAMS ((tree)); 53static int can_convert_eh PARAMS ((tree, tree)); 54static void check_handlers_1 PARAMS ((tree, tree)); 55static tree cp_protect_cleanup_actions PARAMS ((void)); 56 |
57/* Sets up all the global eh stuff that needs to be initialized at the 58 start of compilation. */ 59 60void 61init_exception_processing () 62{ 63 tree tmp; 64 --- 47 unchanged lines hidden (view full) --- 112 113 /* Peel off cv qualifiers. */ 114 type = TYPE_MAIN_VARIANT (type); 115 116 return type; 117} 118 119/* Build the address of a typeinfo decl for use in the runtime |
120 matching field of the exception model. */ |
121 122static tree 123build_eh_type_type (type) 124 tree type; 125{ 126 tree exp; 127 128 if (type == NULL_TREE || type == error_mark_node) --- 40 unchanged lines hidden (view full) --- 169 170/* Returns nonzero if cleaning up an exception of type TYPE (which can be 171 NULL_TREE for a ... handler) will not throw an exception. */ 172 173static int 174dtor_nothrow (type) 175 tree type; 176{ |
177 if (type == NULL_TREE) 178 return 0; 179 180 if (! TYPE_HAS_DESTRUCTOR (type)) 181 return 1; 182 |
183 return TREE_NOTHROW (CLASSTYPE_DESTRUCTORS (type)); |
184} 185 186/* Build up a call to __cxa_end_catch, to destroy the exception object 187 for the current catch block if no others are currently using it. */ 188 189static tree 190do_end_catch (type) 191 tree type; --- 316 unchanged lines hidden (view full) --- 508 } 509 510 return build_function_call (fn, tree_cons (NULL_TREE, size_in_bytes (type), 511 NULL_TREE)); 512} 513 514#if 0 515/* Call __cxa_free_exception from a cleanup. This is never invoked |
516 directly, but see the comment for stabilize_throw_expr. */ |
517 518static tree 519do_free_exception (ptr) 520 tree ptr; 521{ 522 tree fn; 523 524 fn = get_identifier ("__cxa_free_exception"); --- 5 unchanged lines hidden (view full) --- 530 fn = push_void_library_fn (fn, tree_cons (NULL_TREE, ptr_type_node, 531 void_list_node)); 532 } 533 534 return build_function_call (fn, tree_cons (NULL_TREE, ptr, NULL_TREE)); 535} 536#endif 537 |
538/* Wrap all cleanups for TARGET_EXPRs in MUST_NOT_THROW_EXPR. 539 Called from build_throw via walk_tree_without_duplicates. */ 540 541static tree 542wrap_cleanups_r (tp, walk_subtrees, data) 543 tree *tp; 544 int *walk_subtrees ATTRIBUTE_UNUSED; 545 void *data ATTRIBUTE_UNUSED; 546{ 547 tree exp = *tp; 548 tree cleanup; 549 550 /* Don't walk into types. */ 551 if (TYPE_P (exp)) 552 { 553 *walk_subtrees = 0; 554 return NULL_TREE; 555 } 556 if (TREE_CODE (exp) != TARGET_EXPR) 557 return NULL_TREE; 558 559 cleanup = TARGET_EXPR_CLEANUP (exp); 560 if (cleanup) 561 { 562 cleanup = build1 (MUST_NOT_THROW_EXPR, TREE_TYPE (cleanup), cleanup); 563 TARGET_EXPR_CLEANUP (exp) = cleanup; 564 } 565 566 /* Keep iterating. */ 567 return NULL_TREE; 568} 569 570/* Like stabilize_expr, but specifically for a thrown expression. When 571 throwing a temporary class object, we want to construct it directly into 572 the thrown exception, so we look past the TARGET_EXPR and stabilize the 573 arguments of the call instead. 574 575 The case where EXP is a call to a function returning a class is a bit of 576 a grey area in the standard; it's unclear whether or not it should be 577 allowed to throw. I'm going to say no, as that allows us to optimize 578 this case without worrying about deallocating the exception object if it 579 does. The alternatives would be either not optimizing this case, or 580 wrapping the initialization in a TRY_CATCH_EXPR to call do_free_exception 581 rather than in a MUST_NOT_THROW_EXPR, for this case only. */ 582 583static tree 584stabilize_throw_expr (exp, initp) 585 tree exp; 586 tree *initp; 587{ 588 tree init_expr; 589 590 if (TREE_CODE (exp) == TARGET_EXPR 591 && TREE_CODE (TARGET_EXPR_INITIAL (exp)) == AGGR_INIT_EXPR 592 && flag_elide_constructors) 593 { 594 tree aggr_init = AGGR_INIT_EXPR_CHECK (TARGET_EXPR_INITIAL (exp)); 595 tree args = TREE_OPERAND (aggr_init, 1); 596 tree newargs = NULL_TREE; 597 tree *p = &newargs; 598 599 init_expr = void_zero_node; 600 for (; args; args = TREE_CHAIN (args)) 601 { 602 tree arg = TREE_VALUE (args); 603 tree arg_init_expr; 604 605 arg = stabilize_expr (arg, &arg_init_expr); 606 607 if (TREE_SIDE_EFFECTS (arg_init_expr)) 608 init_expr = build (COMPOUND_EXPR, void_type_node, init_expr, 609 arg_init_expr); 610 *p = tree_cons (NULL_TREE, arg, NULL_TREE); 611 p = &TREE_CHAIN (*p); 612 } 613 TREE_OPERAND (aggr_init, 1) = newargs; 614 } 615 else 616 { 617 exp = stabilize_expr (exp, &init_expr); 618 } 619 620 *initp = init_expr; 621 return exp; 622} 623 |
624/* Build a throw expression. */ 625 626tree 627build_throw (exp) 628 tree exp; 629{ 630 tree fn; 631 --- 29 unchanged lines hidden (view full) --- 661 } 662 663 exp = build_function_call (fn, tree_cons (NULL_TREE, exp, NULL_TREE)); 664 } 665 else if (exp) 666 { 667 tree throw_type; 668 tree cleanup; |
669 tree object, ptr; 670 tree tmp; |
671 tree temp_expr, allocate_expr; |
672 673 fn = get_identifier ("__cxa_throw"); 674 if (IDENTIFIER_GLOBAL_VALUE (fn)) 675 fn = IDENTIFIER_GLOBAL_VALUE (fn); 676 else 677 { 678 /* The CLEANUP_TYPE is the internal type of a destructor. */ 679 if (cleanup_type == NULL_TREE) --- 9 unchanged lines hidden (view full) --- 689 tmp = void_list_node; 690 tmp = tree_cons (NULL_TREE, cleanup_type, tmp); 691 tmp = tree_cons (NULL_TREE, ptr_type_node, tmp); 692 tmp = tree_cons (NULL_TREE, ptr_type_node, tmp); 693 tmp = build_function_type (void_type_node, tmp); 694 fn = push_throw_library_fn (fn, tmp); 695 } 696 |
697 /* throw expression */ 698 /* First, decay it. */ 699 exp = decay_conversion (exp); 700 701 /* OK, this is kind of wacky. The standard says that we call 702 terminate when the exception handling mechanism, after 703 completing evaluation of the expression to be thrown but 704 before the exception is caught (_except.throw_), calls a 705 user function that exits via an uncaught exception. 706 707 So we have to protect the actual initialization of the 708 exception object with terminate(), but evaluate the 709 expression first. Since there could be temps in the 710 expression, we need to handle that, too. We also expand 711 the call to __cxa_allocate_exception first (which doesn't 712 matter, since it can't throw). */ 713 |
714 /* Pre-evaluate the thrown expression first, since if we allocated 715 the space first we would have to deal with cleaning it up if 716 evaluating this expression throws. */ 717 exp = stabilize_throw_expr (exp, &temp_expr); |
718 |
719 /* Allocate the space for the exception. */ |
720 allocate_expr = do_allocate_exception (TREE_TYPE (exp)); 721 allocate_expr = get_target_expr (allocate_expr); 722 ptr = TARGET_EXPR_SLOT (allocate_expr); |
723 object = build1 (NOP_EXPR, build_pointer_type (TREE_TYPE (exp)), ptr); 724 object = build_indirect_ref (object, NULL); 725 |
726 /* And initialize the exception object. */ 727 exp = build_init (object, exp, LOOKUP_ONLYCONVERTING); |
728 if (exp == error_mark_node) |
729 { 730 error (" in thrown expression"); 731 return error_mark_node; 732 } |
733 734 exp = build1 (MUST_NOT_THROW_EXPR, TREE_TYPE (exp), exp); |
735 /* Prepend the allocation. */ 736 exp = build (COMPOUND_EXPR, TREE_TYPE (exp), allocate_expr, exp); 737 if (temp_expr != void_zero_node) 738 { 739 /* Prepend the calculation of the throw expression. Also, force 740 any cleanups from the expression to be evaluated here so that 741 we don't have to do them during unwinding. But first wrap 742 them in MUST_NOT_THROW_EXPR, since they are run after the 743 exception object is initialized. */ 744 walk_tree_without_duplicates (&temp_expr, wrap_cleanups_r, 0); 745 exp = build (COMPOUND_EXPR, TREE_TYPE (exp), temp_expr, exp); 746 exp = build1 (CLEANUP_POINT_EXPR, TREE_TYPE (exp), exp); 747 } |
748 749 throw_type = build_eh_type_type (prepare_eh_type (TREE_TYPE (object))); 750 751 if (TYPE_HAS_DESTRUCTOR (TREE_TYPE (object))) 752 { 753 cleanup = lookup_fnfields (TYPE_BINFO (TREE_TYPE (object)), 754 complete_dtor_identifier, 0); |
755 cleanup = BASELINK_FUNCTIONS (cleanup); |
756 mark_used (cleanup); |
757 cxx_mark_addressable (cleanup); |
758 /* Pretend it's a normal function. */ 759 cleanup = build1 (ADDR_EXPR, cleanup_type, cleanup); 760 } 761 else 762 { 763 cleanup = build_int_2 (0, 0); 764 TREE_TYPE (cleanup) = cleanup_type; 765 } 766 767 tmp = tree_cons (NULL_TREE, cleanup, NULL_TREE); 768 tmp = tree_cons (NULL_TREE, throw_type, tmp); 769 tmp = tree_cons (NULL_TREE, ptr, tmp); |
770 /* ??? Indicate that this function call throws throw_type. */ |
771 tmp = build_function_call (fn, tmp); 772 |
773 /* Tack on the initialization stuff. */ 774 exp = build (COMPOUND_EXPR, TREE_TYPE (tmp), exp, tmp); |
775 } 776 else 777 { 778 /* Rethrow current exception. */ 779 780 tree fn = get_identifier ("__cxa_rethrow"); 781 if (IDENTIFIER_GLOBAL_VALUE (fn)) 782 fn = IDENTIFIER_GLOBAL_VALUE (fn); 783 else 784 { 785 /* Declare void __cxa_rethrow (void). */ 786 fn = push_throw_library_fn 787 (fn, build_function_type (void_type_node, void_list_node)); 788 } 789 |
790 /* ??? Indicate that this function call allows exceptions of the type 791 of the enclosing catch block (if known). */ |
792 exp = build_function_call (fn, NULL_TREE); 793 } 794 795 exp = build1 (THROW_EXPR, void_type_node, exp); 796 797 return exp; 798} 799 800/* Make sure TYPE is complete, pointer to complete, reference to 801 complete, or pointer to cv void. Issue diagnostic on failure. |
802 Return the zero on failure and nonzero on success. FROM can be |
803 the expr or decl from whence TYPE came, if available. */ 804 805static int 806complete_ptr_ref_or_void_ptr_p (type, from) 807 tree type; 808 tree from; 809{ 810 int is_ptr; --- 164 unchanged lines hidden --- |