re PR c/5354 (function call with two statement expressions yields incorrect result)
authorEric Botcazou <ebotcazou@multimania.com>
Thu, 21 Mar 2002 09:39:18 +0000 (09:39 +0000)
committerRichard Henderson <rth@gcc.gnu.org>
Thu, 21 Mar 2002 09:39:18 +0000 (01:39 -0800)
        PR c/5354
        * c-common.c (c_expand_expr): Preserve result of a statement
        expression if needed.

Co-Authored-By: Richard Henderson <rth@redhat.com>
From-SVN: r51121

gcc/ChangeLog
gcc/c-common.c
gcc/testsuite/gcc.c-torture/execute/20020320-1.c [new file with mode: 0644]

index 0a06dbd1b20953d5e087098e1110fa6b3e13ed8e..56349e57fadb52899d5d7b15f47a6524b1767633 100644 (file)
@@ -1,3 +1,10 @@
+2002-03-21  Eric Botcazou <ebotcazou@multimania.com>
+           Richard Henderson  <rth@redhat.com>
+
+       PR c/5354
+       * c-common.c (c_expand_expr): Preserve result of a statement
+       expression if needed.
+
 2002-03-21  Jakub Jelinek  <jakub@redhat.com>
 
        PR bootstrap/4195
index 91f2a20476b1812dda720f9a0806698a18725c9a..28920599deae902a7b2de49c4b8c5de73497fc02 100644 (file)
@@ -3574,6 +3574,7 @@ c_expand_expr (exp, target, tmode, modifier)
       {
        tree rtl_expr;
        rtx result;
+       bool preserve_result = false;
 
        /* Since expand_expr_stmt calls free_temp_slots after every
           expression statement, we must call push_temp_slots here.
@@ -3600,12 +3601,24 @@ c_expand_expr (exp, target, tmode, modifier)
 
            if (TREE_CODE (last) == SCOPE_STMT
                && TREE_CODE (expr) == EXPR_STMT)
-             TREE_ADDRESSABLE (expr) = 1;
+             {
+               TREE_ADDRESSABLE (expr) = 1;
+               preserve_result = true;
+             }
          }
 
        expand_stmt (STMT_EXPR_STMT (exp));
        expand_end_stmt_expr (rtl_expr);
+
        result = expand_expr (rtl_expr, target, tmode, modifier);
+       if (preserve_result && GET_CODE (result) == MEM)
+         {
+           if (GET_MODE (result) != BLKmode)
+             result = copy_to_reg (result);
+           else
+             preserve_temp_slots (result);
+         }
+
        pop_temp_slots ();
        return result;
       }
diff --git a/gcc/testsuite/gcc.c-torture/execute/20020320-1.c b/gcc/testsuite/gcc.c-torture/execute/20020320-1.c
new file mode 100644 (file)
index 0000000..05f72c6
--- /dev/null
@@ -0,0 +1,23 @@
+/* PR c/5354 */
+/* Verify that GCC preserves relevant stack slots.  */
+
+extern void abort(void);
+extern void exit(int);
+
+struct large { int x, y[9]; };
+
+int main()
+{
+  int fixed;
+
+  fixed = ({ int temp1 = 2; temp1; }) - ({ int temp2 = 1; temp2; });
+  if (fixed != 1)
+    abort();
+
+  fixed = ({ struct large temp3; temp3.x = 2; temp3; }).x
+         - ({ struct large temp4; temp4.x = 1; temp4; }).x;
+  if (fixed != 1)
+    abort();
+
+  exit(0);
+}