diff options
author | Mike Stump <mrs@gcc.gnu.org> | 1996-05-17 21:48:14 +0000 |
---|---|---|
committer | Mike Stump <mrs@gcc.gnu.org> | 1996-05-17 21:48:14 +0000 |
commit | 4847c9386bfbaf333a36d7086c74a4b29f3b1461 (patch) | |
tree | d45ed9209ff2030610011f8365b79f5db25beac6 | |
parent | 3cd456066e16f812b16ea0095bc392adbb94fa8f (diff) | |
download | gcc-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.c | 2 | ||||
-rw-r--r-- | gcc/stmt.c | 11 | ||||
-rw-r--r-- | gcc/tree.c | 8 | ||||
-rw-r--r-- | gcc/tree.def | 4 |
4 files changed, 14 insertions, 11 deletions
@@ -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; @@ -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: 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). |