Deleted Added
full compact
34d33
< #include "obstack.h"
37a37
> #include "tree-inline.h"
48a49,50
> static tree stabilize_throw_expr PARAMS ((tree, tree *));
> static tree wrap_cleanups_r PARAMS ((tree *, int *, void *));
55,57d56
< #include "decl.h"
< #include "obstack.h"
<
121c120
< matching field of the exception model. */
---
> matching field of the exception model. */
178,179d176
< tree fn;
<
186,188c183
< fn = lookup_member (type, dtor_identifier, 0, 0);
< fn = TREE_VALUE (fn);
< return TREE_NOTHROW (fn);
---
> return TREE_NOTHROW (CLASSTYPE_DESTRUCTORS (type));
521c516
< directly. */
---
> directly, but see the comment for stabilize_throw_expr. */
542a538,623
> /* Wrap all cleanups for TARGET_EXPRs in MUST_NOT_THROW_EXPR.
> Called from build_throw via walk_tree_without_duplicates. */
>
> static tree
> wrap_cleanups_r (tp, walk_subtrees, data)
> tree *tp;
> int *walk_subtrees ATTRIBUTE_UNUSED;
> void *data ATTRIBUTE_UNUSED;
> {
> tree exp = *tp;
> tree cleanup;
>
> /* Don't walk into types. */
> if (TYPE_P (exp))
> {
> *walk_subtrees = 0;
> return NULL_TREE;
> }
> if (TREE_CODE (exp) != TARGET_EXPR)
> return NULL_TREE;
>
> cleanup = TARGET_EXPR_CLEANUP (exp);
> if (cleanup)
> {
> cleanup = build1 (MUST_NOT_THROW_EXPR, TREE_TYPE (cleanup), cleanup);
> TARGET_EXPR_CLEANUP (exp) = cleanup;
> }
>
> /* Keep iterating. */
> return NULL_TREE;
> }
>
> /* Like stabilize_expr, but specifically for a thrown expression. When
> throwing a temporary class object, we want to construct it directly into
> the thrown exception, so we look past the TARGET_EXPR and stabilize the
> arguments of the call instead.
>
> The case where EXP is a call to a function returning a class is a bit of
> a grey area in the standard; it's unclear whether or not it should be
> allowed to throw. I'm going to say no, as that allows us to optimize
> this case without worrying about deallocating the exception object if it
> does. The alternatives would be either not optimizing this case, or
> wrapping the initialization in a TRY_CATCH_EXPR to call do_free_exception
> rather than in a MUST_NOT_THROW_EXPR, for this case only. */
>
> static tree
> stabilize_throw_expr (exp, initp)
> tree exp;
> tree *initp;
> {
> tree init_expr;
>
> if (TREE_CODE (exp) == TARGET_EXPR
> && TREE_CODE (TARGET_EXPR_INITIAL (exp)) == AGGR_INIT_EXPR
> && flag_elide_constructors)
> {
> tree aggr_init = AGGR_INIT_EXPR_CHECK (TARGET_EXPR_INITIAL (exp));
> tree args = TREE_OPERAND (aggr_init, 1);
> tree newargs = NULL_TREE;
> tree *p = &newargs;
>
> init_expr = void_zero_node;
> for (; args; args = TREE_CHAIN (args))
> {
> tree arg = TREE_VALUE (args);
> tree arg_init_expr;
>
> arg = stabilize_expr (arg, &arg_init_expr);
>
> if (TREE_SIDE_EFFECTS (arg_init_expr))
> init_expr = build (COMPOUND_EXPR, void_type_node, init_expr,
> arg_init_expr);
> *p = tree_cons (NULL_TREE, arg, NULL_TREE);
> p = &TREE_CHAIN (*p);
> }
> TREE_OPERAND (aggr_init, 1) = newargs;
> }
> else
> {
> exp = stabilize_expr (exp, &init_expr);
> }
>
> *initp = init_expr;
> return exp;
> }
>
588,589d668
< tree stmt_expr;
< tree compound_stmt;
591a671
> tree temp_expr, allocate_expr;
617,618d696
< begin_init_stmts (&stmt_expr, &compound_stmt);
<
636c714,717
< my_friendly_assert (stmts_are_full_exprs_p () == 1, 19990926);
---
> /* Pre-evaluate the thrown expression first, since if we allocated
> the space first we would have to deal with cleaning it up if
> evaluating this expression throws. */
> exp = stabilize_throw_expr (exp, &temp_expr);
638,649d718
< /* Store the throw expression into a temp. This can be less
< efficient than storing it into the allocated space directly, but
< if we allocated the space first we would have to deal with
< cleaning it up if evaluating this expression throws. */
< if (TREE_SIDE_EFFECTS (exp))
< {
< tmp = create_temporary_var (TREE_TYPE (exp));
< DECL_INITIAL (tmp) = exp;
< cp_finish_decl (tmp, exp, NULL_TREE, LOOKUP_ONLYCONVERTING);
< exp = tmp;
< }
<
651,657c720,722
< ptr = create_temporary_var (ptr_type_node);
< DECL_REGISTER (ptr) = 1;
< cp_finish_decl (ptr, NULL_TREE, NULL_TREE, LOOKUP_ONLYCONVERTING);
< tmp = do_allocate_exception (TREE_TYPE (exp));
< tmp = build_modify_expr (ptr, INIT_EXPR, tmp);
< finish_expr_stmt (tmp);
<
---
> allocate_expr = do_allocate_exception (TREE_TYPE (exp));
> allocate_expr = get_target_expr (allocate_expr);
> ptr = TARGET_EXPR_SLOT (allocate_expr);
661c726,727
< exp = build_modify_expr (object, INIT_EXPR, exp);
---
> /* And initialize the exception object. */
> exp = build_init (object, exp, LOOKUP_ONLYCONVERTING);
663c729,732
< error (" in thrown expression");
---
> {
> error (" in thrown expression");
> return error_mark_node;
> }
666c735,747
< finish_expr_stmt (exp);
---
> /* Prepend the allocation. */
> exp = build (COMPOUND_EXPR, TREE_TYPE (exp), allocate_expr, exp);
> if (temp_expr != void_zero_node)
> {
> /* Prepend the calculation of the throw expression. Also, force
> any cleanups from the expression to be evaluated here so that
> we don't have to do them during unwinding. But first wrap
> them in MUST_NOT_THROW_EXPR, since they are run after the
> exception object is initialized. */
> walk_tree_without_duplicates (&temp_expr, wrap_cleanups_r, 0);
> exp = build (COMPOUND_EXPR, TREE_TYPE (exp), temp_expr, exp);
> exp = build1 (CLEANUP_POINT_EXPR, TREE_TYPE (exp), exp);
> }
674c755
< cleanup = TREE_VALUE (cleanup);
---
> cleanup = BASELINK_FUNCTIONS (cleanup);
676c757
< mark_addressable (cleanup);
---
> cxx_mark_addressable (cleanup);
688a770
> /* ??? Indicate that this function call throws throw_type. */
691,695c773,774
< /* ??? Indicate that this function call throws throw_type. */
<
< finish_expr_stmt (tmp);
<
< exp = finish_init_stmts (stmt_expr, compound_stmt);
---
> /* Tack on the initialization stuff. */
> exp = build (COMPOUND_EXPR, TREE_TYPE (tmp), exp, tmp);
710a790,791
> /* ??? Indicate that this function call allows exceptions of the type
> of the enclosing catch block (if known). */
721c802
< Return the zero on failure and non-zero on success. FROM can be
---
> Return the zero on failure and nonzero on success. FROM can be