re PR c++/45437 (Loses reference during update)
authorJason Merrill <jason@redhat.com>
Sat, 9 Jul 2011 03:33:54 +0000 (23:33 -0400)
committerJason Merrill <jason@gcc.gnu.org>
Sat, 9 Jul 2011 03:33:54 +0000 (23:33 -0400)
PR c++/45437
gcc/
* gimplify.c (goa_stabilize_expr): Handle RHS preevaluation in
compound assignment.
gcc/c-family/
* c-omp.c (check_omp_for_incr_expr): Handle preevaluation.
gcc/cp/
* typeck.c (cp_build_modify_expr): Preevaluate RHS.

From-SVN: r176072

gcc/ChangeLog
gcc/c-family/ChangeLog
gcc/c-family/c-omp.c
gcc/cp/ChangeLog
gcc/cp/typeck.c
gcc/gimplify.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/expr/compound-asn1.C [new file with mode: 0644]
gcc/testsuite/g++.dg/warn/sequence-pt-1.C

index c2d866da6a2fa284fdaa6cc75f79770e5121e59a..9bf29427b60588a08612516d2c0aa7d1cd4a3e8f 100644 (file)
@@ -1,5 +1,9 @@
 2011-07-08  Jason Merrill  <jason@redhat.com>
 
+       PR c++/45437
+       * gimplify.c (goa_stabilize_expr): Handle RHS preevaluation in
+       compound assignment.
+
        * cgraph.c (cgraph_add_to_same_comdat_group): New.
        * cgraph.h: Declare it.
        * ipa.c (function_and_variable_visibility): Make sure thunks
index 72a118a942fda2ded8710bd1aedc3b543d38e4dd..87930c21fcf7b811c6e95105ae210fbd0ed0d4f0 100644 (file)
@@ -1,5 +1,8 @@
 2011-07-08  Jason Merrill  <jason@redhat.com>
 
+       PR c++/45437
+       * c-omp.c (check_omp_for_incr_expr): Handle preevaluation.
+
        PR c++/49673
        * c-common.c (c_apply_type_quals_to_decl): Don't check
        TYPE_NEEDS_CONSTRUCTING.
index 1ee0bf0f8d59500177ac201caa1ca32912e9a199..d2256ffd376b578eb8f4b496522b5c23a47d5331 100644 (file)
@@ -213,6 +213,27 @@ check_omp_for_incr_expr (location_t loc, tree exp, tree decl)
         return fold_build2_loc (loc, PLUS_EXPR,
                            TREE_TYPE (exp), TREE_OPERAND (exp, 0), t);
       break;
+    case COMPOUND_EXPR:
+      {
+       /* cp_build_modify_expr forces preevaluation of the RHS to make
+          sure that it is evaluated before the lvalue-rvalue conversion
+          is applied to the LHS.  Reconstruct the original expression.  */
+       tree op0 = TREE_OPERAND (exp, 0);
+       if (TREE_CODE (op0) == TARGET_EXPR
+           && !VOID_TYPE_P (TREE_TYPE (op0)))
+         {
+           tree op1 = TREE_OPERAND (exp, 1);
+           tree temp = TARGET_EXPR_SLOT (op0);
+           if (TREE_CODE_CLASS (TREE_CODE (op1)) == tcc_binary
+               && TREE_OPERAND (op1, 1) == temp)
+             {
+               op1 = copy_node (op1);
+               TREE_OPERAND (op1, 1) = TARGET_EXPR_INITIAL (op0);
+               return check_omp_for_incr_expr (loc, op1, decl);
+             }
+         }
+       break;
+      }
     default:
       break;
     }
index 3f776b097ad84bcfadd615693049e855f0ec8695..cbdc4d83df2b5a5a7f60db58bb25b66e4e788134 100644 (file)
@@ -1,5 +1,8 @@
 2011-07-08  Jason Merrill  <jason@redhat.com>
 
+       PR c++/45437
+       * typeck.c (cp_build_modify_expr): Preevaluate RHS.
+
        * method.c (use_thunk): Use cgraph_add_to_same_comdat_group.
        * optimize.c (maybe_clone_body): Likewise.
        * semantics.c (maybe_add_lambda_conv_op): Likewise.
index 5febff5cba91f74299d8ad6212727134c9387a89..d87c107ab762ac33a1cc73ee4e8a4f74569d5d16 100644 (file)
@@ -6663,6 +6663,8 @@ cp_build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs,
        }
       else
        {
+         tree init = NULL_TREE;
+
          /* A binary op has been requested.  Combine the old LHS
             value with the RHS producing the value we should actually
             store into the LHS.  */
@@ -6670,7 +6672,17 @@ cp_build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs,
                         && MAYBE_CLASS_TYPE_P (TREE_TYPE (lhstype)))
                        || MAYBE_CLASS_TYPE_P (lhstype)));
 
+         /* Preevaluate the RHS to make sure its evaluation is complete
+            before the lvalue-to-rvalue conversion of the LHS:
+
+            [expr.ass] With respect to an indeterminately-sequenced
+            function call, the operation of a compound assignment is a
+            single evaluation. [ Note: Therefore, a function call shall
+            not intervene between the lvalue-to-rvalue conversion and the
+            side effect associated with any single compound assignment
+            operator. -- end note ]  */
          lhs = stabilize_reference (lhs);
+         rhs = stabilize_expr (rhs, &init);
          newrhs = cp_build_binary_op (input_location,
                                       modifycode, lhs, rhs,
                                       complain);
@@ -6682,6 +6694,9 @@ cp_build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs,
              return error_mark_node;
            }
 
+         if (init)
+           newrhs = build2 (COMPOUND_EXPR, TREE_TYPE (newrhs), init, newrhs);
+
          /* Now it looks like a plain assignment.  */
          modifycode = NOP_EXPR;
          if (c_dialect_objc ())
index 4ff7e933834f26b855b7317a66a14ed08d7c7892..5a928be9434fc6b33ac4e6373112a9bc7ad9311d 100644 (file)
@@ -6451,6 +6451,13 @@ goa_stabilize_expr (tree *expr_p, gimple_seq *pre_p, tree lhs_addr,
          saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 0), pre_p,
                                         lhs_addr, lhs_var);
          break;
+       case COMPOUND_EXPR:
+         /* Break out any preevaluations from cp_build_modify_expr.  */
+         for (; TREE_CODE (expr) == COMPOUND_EXPR;
+              expr = TREE_OPERAND (expr, 1))
+           gimplify_stmt (&TREE_OPERAND (expr, 0), pre_p);
+         *expr_p = expr;
+         return goa_stabilize_expr (expr_p, pre_p, lhs_addr, lhs_var);
        default:
          break;
        }
index fc6931a24d22897a7a534b45b84a6c4f1bc4184a..5b8be3309cbd0382e1e1f2cdd65c30d2495f6cae 100644 (file)
@@ -1,3 +1,9 @@
+2011-07-08  Jason Merrill  <jason@redhat.com>
+
+       PR c++/45437
+       * g++.dg/expr/compound-asn1.C: New.
+       * g++.dg/warn/sequence-pt-1.C: Change one dg-error to dg-bogus.
+
 2011-07-08  Jakub Jelinek  <jakub@redhat.com>
 
        PR target/49621
diff --git a/gcc/testsuite/g++.dg/expr/compound-asn1.C b/gcc/testsuite/g++.dg/expr/compound-asn1.C
new file mode 100644 (file)
index 0000000..194235c
--- /dev/null
@@ -0,0 +1,15 @@
+// PR c++/45437
+// { dg-options -Wsequence-point }
+// { dg-do run }
+
+bool f(bool& b) {
+  b = true;
+  return false;
+}
+
+int main() {
+  bool b = false;
+  b |= f(b);
+  if (!b)
+    return 1;
+}
index 05eee82c176025dcce7a0bb76c8ea83533457b99..6a98fd703cd50d8b9d22ef88ba6118bcad5d7635 100644 (file)
@@ -62,7 +62,7 @@ foo (int a, int b, int n, int p, int *ptr, struct s *sptr,
   (a = a++) && b; /* { dg-warning "undefined" "sequence point warning" } */
   b, (a = a++); /* { dg-warning "undefined" "sequence point warning" } */
   (a = a++), b; /* { dg-warning "undefined" "sequence point warning" } */
-  a ^= b ^= a ^= b; /* { dg-warning "undefined" "sequence point warning" } */
+  a ^= b ^= a ^= b; /* { dg-bogus "undefined" "sequence point warning" } */
 
   a = a; /* { dg-bogus "undefined" "bogus sequence point warning" } */
   a = (a++ && 4); /* { dg-bogus "undefined" "bogus sequence point warning" } */