diff mbox

C++ PATCH for order of evaluation with compound LHS

Message ID CADzB+2kHPyuqtoOJOndncFw_bz=5SrPcBfioNokX3u5HoCHG5A@mail.gmail.com
State New
Headers show

Commit Message

Jason Merrill June 24, 2016, 9:56 p.m. UTC
This patch stops breaking up

(side-effect, lval) = rval;

into

side-effect;
lval = rval;

because now the RHS is required to be sequenced before the LHS. And
other complex LHS that were broken out similarly are now turned into
COMPOUND_EXPR.

This revealed a bug in verify_tree's handling of COMPOUND_EXPR, which
led to (b++, b) being considered by -Wsequence-point to conflict with
itself when used on the LHS of an assignment.  Fixed thus.  Of course,
-Wsequence-point is no longer correct given the new rules, but I'm
inclined to leave it alone for now, to encourage people not to rely on
rules that are not portable to earlier C++ standards or to C.

Tested x86_64-pc-linux-gnu, applying to trunk.
diff mbox

Patch

commit 564dc208610fbbd53c50998dbe2748546eb8c26a
Author: Jason Merrill <jason@redhat.com>
Date:   Thu Jun 16 14:23:04 2016 -0400

    	P0145R2: Refining Expression Order for C++ (complex LHS of =).
    
    gcc/c-common/
    	* c-common.c (verify_tree) [COMPOUND_EXPR]: Fix handling on LHS of
    	MODIFY_EXPR.
    gcc/cp/
    	* typeck.c (cp_build_modify_expr): Leave COMPOUND_EXPR on LHS.

diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index 4988f06..3301c31 100644
--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c
@@ -2980,13 +2980,15 @@  verify_tree (tree x, struct tlist **pbefore_sp, struct tlist **pno_sp,
     case COMPOUND_EXPR:
     case TRUTH_ANDIF_EXPR:
     case TRUTH_ORIF_EXPR:
-      tmp_before = tmp_nosp = tmp_list3 = 0;
+      tmp_before = tmp_nosp = tmp_list2 = tmp_list3 = 0;
       verify_tree (TREE_OPERAND (x, 0), &tmp_before, &tmp_nosp, NULL_TREE);
       warn_for_collisions (tmp_nosp);
       merge_tlist (pbefore_sp, tmp_before, 0);
       merge_tlist (pbefore_sp, tmp_nosp, 0);
-      verify_tree (TREE_OPERAND (x, 1), &tmp_list3, pno_sp, NULL_TREE);
+      verify_tree (TREE_OPERAND (x, 1), &tmp_list3, &tmp_list2, NULL_TREE);
+      warn_for_collisions (tmp_list2);
       merge_tlist (pbefore_sp, tmp_list3, 0);
+      merge_tlist (pno_sp, tmp_list2, 0);
       return;
 
     case COND_EXPR:
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 3704b88..fb6a16e 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -7515,7 +7515,8 @@  cp_build_modify_expr (location_t loc, tree lhs, enum tree_code modifycode,
   if (error_operand_p (lhs) || error_operand_p (rhs))
     return error_mark_node;
 
-  /* Handle control structure constructs used as "lvalues".  */
+  /* Handle control structure constructs used as "lvalues".  Note that we
+     leave COMPOUND_EXPR on the LHS because it is sequenced after the RHS.  */
   switch (TREE_CODE (lhs))
     {
       /* Handle --foo = 5; as these are valid constructs in C++.  */
@@ -7525,31 +7526,16 @@  cp_build_modify_expr (location_t loc, tree lhs, enum tree_code modifycode,
 	lhs = build2 (TREE_CODE (lhs), TREE_TYPE (lhs),
 		      cp_stabilize_reference (TREE_OPERAND (lhs, 0)),
 		      TREE_OPERAND (lhs, 1));
-      newrhs = cp_build_modify_expr (loc, TREE_OPERAND (lhs, 0),
-				     modifycode, rhs, complain);
-      if (newrhs == error_mark_node)
-	return error_mark_node;
-      return build2 (COMPOUND_EXPR, lhstype, lhs, newrhs);
-
-      /* Handle (a, b) used as an "lvalue".  */
-    case COMPOUND_EXPR:
-      newrhs = cp_build_modify_expr (loc, TREE_OPERAND (lhs, 1),
-				     modifycode, rhs, complain);
-      if (newrhs == error_mark_node)
-	return error_mark_node;
-      return build2 (COMPOUND_EXPR, lhstype,
-		     TREE_OPERAND (lhs, 0), newrhs);
+      lhs = build2 (COMPOUND_EXPR, lhstype, lhs, TREE_OPERAND (lhs, 0));
+      break;
 
     case MODIFY_EXPR:
       if (TREE_SIDE_EFFECTS (TREE_OPERAND (lhs, 0)))
 	lhs = build2 (TREE_CODE (lhs), TREE_TYPE (lhs),
 		      cp_stabilize_reference (TREE_OPERAND (lhs, 0)),
 		      TREE_OPERAND (lhs, 1));
-      newrhs = cp_build_modify_expr (loc, TREE_OPERAND (lhs, 0), modifycode,
-				     rhs, complain);
-      if (newrhs == error_mark_node)
-	return error_mark_node;
-      return build2 (COMPOUND_EXPR, lhstype, lhs, newrhs);
+      lhs = build2 (COMPOUND_EXPR, lhstype, lhs, TREE_OPERAND (lhs, 0));
+      break;
 
     case MIN_EXPR:
     case MAX_EXPR: