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.
commit 564dc208610fbbd53c50998dbe2748546eb8c26a Author: Jason Merrill <ja...@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: