expr.c (expand_expr, [...]): Make TARGET_EXPRs redoable for UNSAVE_EXPR.
* expr.c (expand_expr, cond TARGET_EXPR): Make TARGET_EXPRs redoable for UNSAVE_EXPR. * stmt.c (expand_decl_cleanup): Wrap the cleanup in an UNSAVE_EXPR to that we can redo it. * tree.c (unsave_expr_now): Handle TARGET_EXPRs fully now. * tree.def (TARGET_EXPR): Add a third field so that TARGET_EXPRs are redoable. From-SVN: r12018
This commit is contained in:
parent
3cd456066e
commit
4847c9386b
|
@ -6705,7 +6705,7 @@ expand_expr (exp, target, tmode, modifier)
|
|||
DECL_RTL (slot) = target;
|
||||
}
|
||||
|
||||
exp1 = TREE_OPERAND (exp, 1);
|
||||
exp1 = TREE_OPERAND (exp, 3) = TREE_OPERAND (exp, 1);
|
||||
/* Mark it as expanded. */
|
||||
TREE_OPERAND (exp, 1) = NULL_TREE;
|
||||
|
||||
|
|
11
gcc/stmt.c
11
gcc/stmt.c
|
@ -3687,12 +3687,9 @@ bc_expand_decl_init (decl)
|
|||
/* CLEANUP is an expression to be executed at exit from this binding contour;
|
||||
for example, in C++, it might call the destructor for this variable.
|
||||
|
||||
If CLEANUP contains any SAVE_EXPRs, then you must preevaluate them
|
||||
either before or after calling `expand_decl_cleanup' but before compiling
|
||||
any subsequent expressions. This is because CLEANUP may be expanded
|
||||
more than once, on different branches of execution.
|
||||
For the same reason, CLEANUP may not contain a CALL_EXPR
|
||||
except as its topmost node--else `preexpand_calls' would get confused.
|
||||
We wrap CLEANUP in an UNSAVE_EXPR node, so that we can expand the
|
||||
CLEANUP multiple times, and have the correct semantics. This
|
||||
happens in exception handling, and for non-local gotos.
|
||||
|
||||
If CLEANUP is nonzero and DECL is zero, we record a cleanup
|
||||
that is not associated with any particular variable. */
|
||||
|
@ -3711,6 +3708,8 @@ expand_decl_cleanup (decl, cleanup)
|
|||
|
||||
if (cleanup != 0)
|
||||
{
|
||||
cleanup = unsave_expr (cleanup);
|
||||
|
||||
thisblock->data.block.cleanups
|
||||
= temp_tree_cons (decl, cleanup, thisblock->data.block.cleanups);
|
||||
/* If this block has a cleanup, it belongs in stack_block_stack. */
|
||||
|
|
|
@ -2195,12 +2195,14 @@ unsave_expr_now (expr)
|
|||
break;
|
||||
|
||||
case TARGET_EXPR:
|
||||
sorry ("TARGET_EXPR reused inside UNSAVE_EXPR");
|
||||
TREE_OPERAND (expr, 1) = TREE_OPERAND (expr, 3);
|
||||
TREE_OPERAND (expr, 3) = NULL_TREE;
|
||||
break;
|
||||
|
||||
case RTL_EXPR:
|
||||
warning ("RTL_EXPR reused inside UNSAVE_EXPR");
|
||||
RTL_EXPR_SEQUENCE (expr) = NULL_RTX;
|
||||
/* I don't yet know how to emit a sequence multiple times. */
|
||||
if (RTL_EXPR_SEQUENCE (expr) != NULL_RTX)
|
||||
abort ();
|
||||
break;
|
||||
|
||||
case CALL_EXPR:
|
||||
|
|
|
@ -406,7 +406,9 @@ DEFTREECODE (INIT_EXPR, "init_expr", "e", 2)
|
|||
|
||||
/* For TARGET_EXPR, operand 0 is the target of an initialization,
|
||||
operand 1 is the initializer for the target,
|
||||
and operand 2 is the cleanup for this node, if any. */
|
||||
and operand 2 is the cleanup for this node, if any.
|
||||
and operand 3 is the saved initializer after this node has been
|
||||
expanded once, this is so we can re-expand the tree later. */
|
||||
DEFTREECODE (TARGET_EXPR, "target_expr", "e", 3)
|
||||
|
||||
/* Conditional expression ( ... ? ... : ... in C).
|
||||
|
|
Loading…
Reference in New Issue