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:
Mike Stump 1996-05-17 21:48:14 +00:00
parent 3cd456066e
commit 4847c9386b
4 changed files with 14 additions and 11 deletions

View File

@ -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;

View File

@ -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. */

View File

@ -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:

View File

@ -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).