re PR c/58943 (wrong calculation of indirect structure member arithmetic via function...
authorJakub Jelinek <jakub@redhat.com>
Wed, 15 Jan 2014 08:03:53 +0000 (09:03 +0100)
committerJakub Jelinek <jakub@gcc.gnu.org>
Wed, 15 Jan 2014 08:03:53 +0000 (09:03 +0100)
PR c/58943
* c-typeck.c (build_modify_expr): For lhs op= rhs, if rhs has side
effects, preevaluate rhs using SAVE_EXPR first.

* c-omp.c (c_finish_omp_atomic): Set in_late_binary_op around
build_modify_expr with non-NOP_EXPR opcode.  Handle return from it
being COMPOUND_EXPR.
(c_finish_omp_for): Handle incr being COMPOUND_EXPR with first
operand a SAVE_EXPR and second MODIFY_EXPR.

* gcc.c-torture/execute/pr58943.c: New test.
* gcc.dg/tree-ssa/ssa-fre-33.c (main): Avoid using += in the test.

From-SVN: r206620

gcc/c-family/ChangeLog
gcc/c-family/c-omp.c
gcc/c/ChangeLog
gcc/c/c-typeck.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.c-torture/execute/pr58943.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-33.c

index d9b69b32c4191f2233dfa5a2c96d82a6b7cf25ff..80dd632a632407aab8f81252b5e2626fb55f303b 100644 (file)
@@ -1,3 +1,12 @@
+2014-01-15  Jakub Jelinek  <jakub@redhat.com>
+
+       PR c/58943
+       * c-omp.c (c_finish_omp_atomic): Set in_late_binary_op around
+       build_modify_expr with non-NOP_EXPR opcode.  Handle return from it
+       being COMPOUND_EXPR.
+       (c_finish_omp_for): Handle incr being COMPOUND_EXPR with first
+       operand a SAVE_EXPR and second MODIFY_EXPR.
+
 2014-01-09  Jakub Jelinek  <jakub@redhat.com>
 
        PR target/58115
index ac380ee7e1d244a16f9131aafc76762bcbfd3abf..4ce51e4a9d2fe425873f66ab00d089498e2b50b6 100644 (file)
@@ -136,7 +136,7 @@ c_finish_omp_atomic (location_t loc, enum tree_code code,
                     enum tree_code opcode, tree lhs, tree rhs,
                     tree v, tree lhs1, tree rhs1, bool swapped, bool seq_cst)
 {
-  tree x, type, addr;
+  tree x, type, addr, pre = NULL_TREE;
 
   if (lhs == error_mark_node || rhs == error_mark_node
       || v == error_mark_node || lhs1 == error_mark_node
@@ -194,9 +194,18 @@ c_finish_omp_atomic (location_t loc, enum tree_code code,
       rhs = build2_loc (loc, opcode, TREE_TYPE (lhs), rhs, lhs);
       opcode = NOP_EXPR;
     }
+  bool save = in_late_binary_op;
+  in_late_binary_op = true;
   x = build_modify_expr (loc, lhs, NULL_TREE, opcode, loc, rhs, NULL_TREE);
+  in_late_binary_op = save;
   if (x == error_mark_node)
     return error_mark_node;
+  if (TREE_CODE (x) == COMPOUND_EXPR)
+    {
+      pre = TREE_OPERAND (x, 0);
+      gcc_assert (TREE_CODE (pre) == SAVE_EXPR);
+      x = TREE_OPERAND (x, 1);
+    }
   gcc_assert (TREE_CODE (x) == MODIFY_EXPR);
   rhs = TREE_OPERAND (x, 1);
 
@@ -264,6 +273,8 @@ c_finish_omp_atomic (location_t loc, enum tree_code code,
       x = omit_one_operand_loc (loc, type, x, rhs1addr);
     }
 
+  if (pre)
+    x = omit_one_operand_loc (loc, type, x, pre);
   return x;
 }
 
@@ -555,6 +566,12 @@ c_finish_omp_for (location_t locus, enum tree_code code, tree declv,
              incr = c_omp_for_incr_canonicalize_ptr (elocus, decl, incr);
              break;
 
+           case COMPOUND_EXPR:
+             if (TREE_CODE (TREE_OPERAND (incr, 0)) != SAVE_EXPR
+                 || TREE_CODE (TREE_OPERAND (incr, 1)) != MODIFY_EXPR)
+               break;
+             incr = TREE_OPERAND (incr, 1);
+             /* FALLTHRU */
            case MODIFY_EXPR:
              if (TREE_OPERAND (incr, 0) != decl)
                break;
index d3b338a5b8ea14d2b47aeab9f1db969a4ba50fb3..4754bdf2b99cc8f9dcffb0a06833d5aaacfdbd3d 100644 (file)
@@ -1,3 +1,9 @@
+2014-01-15  Jakub Jelinek  <jakub@redhat.com>
+
+       PR c/58943
+       * c-typeck.c (build_modify_expr): For lhs op= rhs, if rhs has side
+       effects, preevaluate rhs using SAVE_EXPR first.
+
 2014-01-09  Balaji V. Iyer  <balaji.v.iyer@intel.com>
 
        PR c++/59631
index d9dc69495e3140ec1579966362facc38f6d1083d..09049e2a3ca960bc4972942df1f7987785af8530 100644 (file)
@@ -5193,6 +5193,7 @@ build_modify_expr (location_t location, tree lhs, tree lhs_origtype,
 {
   tree result;
   tree newrhs;
+  tree rhseval = NULL_TREE;
   tree rhs_semantic_type = NULL_TREE;
   tree lhstype = TREE_TYPE (lhs);
   tree olhstype = lhstype;
@@ -5254,8 +5255,17 @@ build_modify_expr (location_t location, tree lhs, tree lhs_origtype,
       /* Construct the RHS for any non-atomic compound assignemnt. */
       if (!is_atomic_op)
         {
+         /* If in LHS op= RHS the RHS has side-effects, ensure they
+            are preevaluated before the rest of the assignment expression's
+            side-effects, because RHS could contain e.g. function calls
+            that modify LHS.  */
+         if (TREE_SIDE_EFFECTS (rhs))
+           {
+             newrhs = in_late_binary_op ? save_expr (rhs) : c_save_expr (rhs);
+             rhseval = newrhs;
+           }
          newrhs = build_binary_op (location,
-                                   modifycode, lhs, rhs, 1);
+                                   modifycode, lhs, newrhs, 1);
 
          /* The original type of the right hand side is no longer
             meaningful.  */
@@ -5269,7 +5279,7 @@ build_modify_expr (location_t location, tree lhs, tree lhs_origtype,
         if so, we need to generate setter calls.  */
       result = objc_maybe_build_modify_expr (lhs, newrhs);
       if (result)
-       return result;
+       goto return_result;
 
       /* Else, do the check that we postponed for Objective-C.  */
       if (!lvalue_or_else (location, lhs, lv_assign))
@@ -5363,7 +5373,7 @@ build_modify_expr (location_t location, tree lhs, tree lhs_origtype,
       if (result)
        {
          protected_set_expr_location (result, location);
-         return result;
+         goto return_result;
        }
     }
 
@@ -5384,11 +5394,15 @@ build_modify_expr (location_t location, tree lhs, tree lhs_origtype,
      as the LHS argument.  */
 
   if (olhstype == TREE_TYPE (result))
-    return result;
+    goto return_result;
 
   result = convert_for_assignment (location, olhstype, result, rhs_origtype,
                                   ic_assign, false, NULL_TREE, NULL_TREE, 0);
   protected_set_expr_location (result, location);
+
+return_result:
+  if (rhseval)
+    result = build2 (COMPOUND_EXPR, TREE_TYPE (result), rhseval, result);
   return result;
 }
 \f
index 2f033c09ebb64ddb1f628128671e4576603cdc16..c9eba44783946e257f45907f2482a96db83065f8 100644 (file)
@@ -1,3 +1,9 @@
+2014-01-15  Jakub Jelinek  <jakub@redhat.com>
+
+       PR c/58943
+       * gcc.c-torture/execute/pr58943.c: New test.
+       * gcc.dg/tree-ssa/ssa-fre-33.c (main): Avoid using += in the test.
+
 2014-01-14  H.J. Lu  <hongjiu.lu@intel.com>
 
        PR target/59794
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr58943.c b/gcc/testsuite/gcc.c-torture/execute/pr58943.c
new file mode 100644 (file)
index 0000000..75e87ae
--- /dev/null
@@ -0,0 +1,19 @@
+/* PR c/58943 */
+
+unsigned int x[1] = { 2 };
+
+unsigned int
+foo (void)
+{
+  x[0] |= 128;
+  return 1;
+}
+
+int
+main ()
+{
+  x[0] |= foo ();
+  if (x[0] != 131)
+    __builtin_abort ();
+  return 0;
+}
index 4108188460190842cea70ed7bdaaefd0218a870b..ead6a183d0288bf65ae3c803371e8eb5540b1fd3 100644 (file)
@@ -11,8 +11,8 @@ struct {
 float x;
 int main(int argc)
 {
-  vector float res = (vector float){0.0f,0.0f,0.0f,1.0f};
-  res += (vector float){1.0f,2.0f,3.0f,4.0f};
+  vector float res;
+  res = (vector float){1.0f,2.0f,3.0f,5.0f};
   s.global_res = res;
   x = *((float*)&s.global_res + 1);
   return 0;