Deleted Added
full compact
except.c (110621) except.c (117404)
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"
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 "obstack.h"
35#include "output.h"
36#include "except.h"
37#include "toplev.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));
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 *));
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
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
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

--- 47 unchanged lines hidden (view full) ---

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
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
121 matching field of the exception model. */
120 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)

--- 40 unchanged lines hidden (view full) ---

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{
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{
178 tree fn;
179
180 if (type == NULL_TREE)
181 return 0;
182
183 if (! TYPE_HAS_DESTRUCTOR (type))
184 return 1;
185
177 if (type == NULL_TREE)
178 return 0;
179
180 if (! TYPE_HAS_DESTRUCTOR (type))
181 return 1;
182
186 fn = lookup_member (type, dtor_identifier, 0, 0);
187 fn = TREE_VALUE (fn);
188 return TREE_NOTHROW (fn);
183 return TREE_NOTHROW (CLASSTYPE_DESTRUCTORS (type));
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;

--- 316 unchanged lines hidden (view full) ---

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
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
521 directly. */
516 directly, but see the comment for stabilize_throw_expr. */
522
523static tree
524do_free_exception (ptr)
525 tree ptr;
526{
527 tree fn;
528
529 fn = get_identifier ("__cxa_free_exception");

--- 5 unchanged lines hidden (view full) ---

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
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
543/* Build a throw expression. */
544
545tree
546build_throw (exp)
547 tree exp;
548{
549 tree fn;
550

--- 29 unchanged lines hidden (view full) ---

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;
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;
588 tree stmt_expr;
589 tree compound_stmt;
590 tree object, ptr;
591 tree tmp;
669 tree object, ptr;
670 tree tmp;
671 tree temp_expr, allocate_expr;
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)

--- 9 unchanged lines hidden (view full) ---

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
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
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
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
636 my_friendly_assert (stmts_are_full_exprs_p () == 1, 19990926);
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);
637
718
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. */
719 /* 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
720 allocate_expr = do_allocate_exception (TREE_TYPE (exp));
721 allocate_expr = get_target_expr (allocate_expr);
722 ptr = TARGET_EXPR_SLOT (allocate_expr);
658 object = build1 (NOP_EXPR, build_pointer_type (TREE_TYPE (exp)), ptr);
659 object = build_indirect_ref (object, NULL);
660
723 object = build1 (NOP_EXPR, build_pointer_type (TREE_TYPE (exp)), ptr);
724 object = build_indirect_ref (object, NULL);
725
661 exp = build_modify_expr (object, INIT_EXPR, exp);
726 /* And initialize the exception object. */
727 exp = build_init (object, exp, LOOKUP_ONLYCONVERTING);
662 if (exp == error_mark_node)
728 if (exp == error_mark_node)
663 error (" in thrown expression");
729 {
730 error (" in thrown expression");
731 return error_mark_node;
732 }
664
665 exp = build1 (MUST_NOT_THROW_EXPR, TREE_TYPE (exp), exp);
733
734 exp = build1 (MUST_NOT_THROW_EXPR, TREE_TYPE (exp), exp);
666 finish_expr_stmt (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 }
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);
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);
674 cleanup = TREE_VALUE (cleanup);
755 cleanup = BASELINK_FUNCTIONS (cleanup);
675 mark_used (cleanup);
756 mark_used (cleanup);
676 mark_addressable (cleanup);
757 cxx_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);
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. */
689 tmp = build_function_call (fn, tmp);
690
771 tmp = build_function_call (fn, tmp);
772
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);
773 /* Tack on the initialization stuff. */
774 exp = build (COMPOUND_EXPR, TREE_TYPE (tmp), exp, tmp);
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
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). */
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.
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.
721 Return the zero on failure and non-zero on success. FROM can be
802 Return the zero on failure and nonzero 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;

--- 164 unchanged lines hidden ---
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 ---