expr.c (expand_expr, [...]): Make TARGET_EXPRs redoable for UNSAVE_EXPR.
authorMike Stump <mrs@gcc.gnu.org>
Fri, 17 May 1996 21:48:14 +0000 (21:48 +0000)
committerMike Stump <mrs@gcc.gnu.org>
Fri, 17 May 1996 21:48:14 +0000 (21:48 +0000)
* 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

gcc/expr.c
gcc/stmt.c
gcc/tree.c
gcc/tree.def

index c10ff7b90e939ef6a5359abf57af04ba3954f5fd..9dc6ccfe5c937236642e50cf0bbbd146ea7fd4ca 100644 (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;
 
index 6a2e670d95ef4a65ee26f246e9f0fd40282aa918..d9551f6a8ac91662facc9bc3d853c29b4d92d219 100644 (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.  */
index fc4c983568a147f2968b2e959a663866ca3a04d6..0e31d5322fb63babea5311062bcf2aec93d0df92 100644 (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:
index 61f06a94a68f69e963a67b9d0c286f14f9186221..2b7088351f2dda250edeb63ec1959c67b0c7f1e4 100644 (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).