aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Stump <mrs@gcc.gnu.org>1996-05-17 21:48:14 +0000
committerMike Stump <mrs@gcc.gnu.org>1996-05-17 21:48:14 +0000
commit4847c9386bfbaf333a36d7086c74a4b29f3b1461 (patch)
treed45ed9209ff2030610011f8365b79f5db25beac6
parent3cd456066e16f812b16ea0095bc392adbb94fa8f (diff)
downloadgcc-4847c9386bfbaf333a36d7086c74a4b29f3b1461.zip
gcc-4847c9386bfbaf333a36d7086c74a4b29f3b1461.tar.gz
gcc-4847c9386bfbaf333a36d7086c74a4b29f3b1461.tar.bz2
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
-rw-r--r--gcc/expr.c2
-rw-r--r--gcc/stmt.c11
-rw-r--r--gcc/tree.c8
-rw-r--r--gcc/tree.def4
4 files changed, 14 insertions, 11 deletions
diff --git a/gcc/expr.c b/gcc/expr.c
index c10ff7b..9dc6ccf 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -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;
diff --git a/gcc/stmt.c b/gcc/stmt.c
index 6a2e670..d9551f6 100644
--- a/gcc/stmt.c
+++ b/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. */
diff --git a/gcc/tree.c b/gcc/tree.c
index fc4c983..0e31d53 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -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:
diff --git a/gcc/tree.def b/gcc/tree.def
index 61f06a9..2b70883 100644
--- a/gcc/tree.def
+++ b/gcc/tree.def
@@ -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).