From: Jakub Jelinek Date: Wed, 21 Mar 2018 20:19:33 +0000 (+0100) Subject: re PR c++/84961 (ICE error: SSA_NAME_DEF_STMT is wrong) X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=57e20f74e011f190a29ec0b414c0ee74e62ebdc9;p=gcc.git re PR c++/84961 (ICE error: SSA_NAME_DEF_STMT is wrong) PR c++/84961 * cp-tree.h (genericize_compound_lvalue): Declare. * typeck.c (genericize_compound_lvalue): New function. (unary_complex_lvalue, cp_build_modify_expr): Use it. * semantics.c (finish_asm_stmt): Replace MODIFY_EXPR, PREINCREMENT_EXPR and PREDECREMENT_EXPR in output and "m" constrained input operands with COMPOUND_EXPR. Call cxx_mark_addressable on the rightmost COMPOUND_EXPR operand. * c-c++-common/pr43690.c: Don't expect errors on "m" (--x) and "m" (++x) in C++. * g++.dg/torture/pr84961-1.C: New test. * g++.dg/torture/pr84961-2.C: New test. From-SVN: r258741 --- diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index e97f99d0d3f..fd2f371e836 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,14 @@ +2018-03-21 Jakub Jelinek + + PR c++/84961 + * cp-tree.h (genericize_compound_lvalue): Declare. + * typeck.c (genericize_compound_lvalue): New function. + (unary_complex_lvalue, cp_build_modify_expr): Use it. + * semantics.c (finish_asm_stmt): Replace MODIFY_EXPR, PREINCREMENT_EXPR + and PREDECREMENT_EXPR in output and "m" constrained input operands with + COMPOUND_EXPR. Call cxx_mark_addressable on the rightmost + COMPOUND_EXPR operand. + 2018-03-21 Nathan Sidwell PR c++/85008 diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index d5382c2604f..c07aaa5781a 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -7145,6 +7145,7 @@ extern tree cp_build_addressof (location_t, tree, extern tree cp_build_addr_expr (tree, tsubst_flags_t); extern tree cp_build_unary_op (enum tree_code, tree, bool, tsubst_flags_t); +extern tree genericize_compound_lvalue (tree); extern tree unary_complex_lvalue (enum tree_code, tree); extern tree build_x_conditional_expr (location_t, tree, tree, tree, tsubst_flags_t); diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index fdf37bea770..4b9fc277436 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -1512,6 +1512,21 @@ finish_asm_stmt (int volatile_p, tree string, tree output_operands, && C_TYPE_FIELDS_READONLY (TREE_TYPE (operand))))) cxx_readonly_error (operand, lv_asm); + tree *op = &operand; + while (TREE_CODE (*op) == COMPOUND_EXPR) + op = &TREE_OPERAND (*op, 1); + switch (TREE_CODE (*op)) + { + case PREINCREMENT_EXPR: + case PREDECREMENT_EXPR: + case MODIFY_EXPR: + *op = genericize_compound_lvalue (*op); + op = &TREE_OPERAND (*op, 1); + break; + default: + break; + } + constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (t))); oconstraints[i] = constraint; @@ -1520,7 +1535,7 @@ finish_asm_stmt (int volatile_p, tree string, tree output_operands, { /* If the operand is going to end up in memory, mark it addressable. */ - if (!allows_reg && !cxx_mark_addressable (operand)) + if (!allows_reg && !cxx_mark_addressable (*op)) operand = error_mark_node; } else @@ -1562,7 +1577,23 @@ finish_asm_stmt (int volatile_p, tree string, tree output_operands, /* Strip the nops as we allow this case. FIXME, this really should be rejected or made deprecated. */ STRIP_NOPS (operand); - if (!cxx_mark_addressable (operand)) + + tree *op = &operand; + while (TREE_CODE (*op) == COMPOUND_EXPR) + op = &TREE_OPERAND (*op, 1); + switch (TREE_CODE (*op)) + { + case PREINCREMENT_EXPR: + case PREDECREMENT_EXPR: + case MODIFY_EXPR: + *op = genericize_compound_lvalue (*op); + op = &TREE_OPERAND (*op, 1); + break; + default: + break; + } + + if (!cxx_mark_addressable (*op)) operand = error_mark_node; } else if (!allows_reg && !allows_mem) diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index 0c2ebd1b3e4..d3183b5321d 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -6357,6 +6357,25 @@ build_unary_op (location_t /*location*/, return cp_build_unary_op (code, xarg, noconvert, tf_warning_or_error); } +/* Adjust LVALUE, an MODIFY_EXPR, PREINCREMENT_EXPR or PREDECREMENT_EXPR, + so that it is a valid lvalue even for GENERIC by replacing + (lhs = rhs) with ((lhs = rhs), lhs) + (--lhs) with ((--lhs), lhs) + (++lhs) with ((++lhs), lhs) + and if lhs has side-effects, calling cp_stabilize_reference on it, so + that it can be evaluated multiple times. */ + +tree +genericize_compound_lvalue (tree lvalue) +{ + if (TREE_SIDE_EFFECTS (TREE_OPERAND (lvalue, 0))) + lvalue = build2 (TREE_CODE (lvalue), TREE_TYPE (lvalue), + cp_stabilize_reference (TREE_OPERAND (lvalue, 0)), + TREE_OPERAND (lvalue, 1)); + return build2 (COMPOUND_EXPR, TREE_TYPE (TREE_OPERAND (lvalue, 0)), + lvalue, TREE_OPERAND (lvalue, 0)); +} + /* Apply unary lvalue-demanding operator CODE to the expression ARG for certain kinds of expressions which are not really lvalues but which we can accept as lvalues. @@ -6391,17 +6410,7 @@ unary_complex_lvalue (enum tree_code code, tree arg) if (TREE_CODE (arg) == MODIFY_EXPR || TREE_CODE (arg) == PREINCREMENT_EXPR || TREE_CODE (arg) == PREDECREMENT_EXPR) - { - tree lvalue = TREE_OPERAND (arg, 0); - if (TREE_SIDE_EFFECTS (lvalue)) - { - lvalue = cp_stabilize_reference (lvalue); - arg = build2 (TREE_CODE (arg), TREE_TYPE (arg), - lvalue, TREE_OPERAND (arg, 1)); - } - return unary_complex_lvalue - (code, build2 (COMPOUND_EXPR, TREE_TYPE (lvalue), arg, lvalue)); - } + return unary_complex_lvalue (code, genericize_compound_lvalue (arg)); if (code != ADDR_EXPR) return NULL_TREE; @@ -7887,11 +7896,7 @@ cp_build_modify_expr (location_t loc, tree lhs, enum tree_code modifycode, case PREINCREMENT_EXPR: if (compound_side_effects_p) newrhs = rhs = stabilize_expr (rhs, &preeval); - 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)); - lhs = build2 (COMPOUND_EXPR, lhstype, lhs, TREE_OPERAND (lhs, 0)); + lhs = genericize_compound_lvalue (lhs); maybe_add_compound: /* If we had (bar, --foo) = 5; or (bar, (baz, --foo)) = 5; and looked through the COMPOUND_EXPRs, readd them now around @@ -7914,11 +7919,7 @@ cp_build_modify_expr (location_t loc, tree lhs, enum tree_code modifycode, case MODIFY_EXPR: if (compound_side_effects_p) newrhs = rhs = stabilize_expr (rhs, &preeval); - 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)); - lhs = build2 (COMPOUND_EXPR, lhstype, lhs, TREE_OPERAND (lhs, 0)); + lhs = genericize_compound_lvalue (lhs); goto maybe_add_compound; case MIN_EXPR: diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 6ecd1f502e1..4e787c5f8fb 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,11 @@ +2018-03-21 Jakub Jelinek + + PR c++/84961 + * c-c++-common/pr43690.c: Don't expect errors on "m" (--x) and + "m" (++x) in C++. + * g++.dg/torture/pr84961-1.C: New test. + * g++.dg/torture/pr84961-2.C: New test. + 2018-03-21 Nathan Sidwell PR c++/85008 diff --git a/gcc/testsuite/c-c++-common/pr43690.c b/gcc/testsuite/c-c++-common/pr43690.c index 67c6cb0f88c..8d10744903f 100644 --- a/gcc/testsuite/c-c++-common/pr43690.c +++ b/gcc/testsuite/c-c++-common/pr43690.c @@ -6,8 +6,8 @@ void foo (char *x) { asm ("" : : "m" (x++)); /* { dg-error "is not directly addressable" } */ - asm ("" : : "m" (++x)); /* { dg-error "is not directly addressable" } */ + asm ("" : : "m" (++x)); /* { dg-error "is not directly addressable" "" { target c } } */ asm ("" : : "m" (x--)); /* { dg-error "is not directly addressable" } */ - asm ("" : : "m" (--x)); /* { dg-error "is not directly addressable" } */ + asm ("" : : "m" (--x)); /* { dg-error "is not directly addressable" "" { target c } } */ asm ("" : : "m" (x + 1)); /* { dg-error "is not directly addressable" } */ } diff --git a/gcc/testsuite/g++.dg/torture/pr84961-1.C b/gcc/testsuite/g++.dg/torture/pr84961-1.C new file mode 100644 index 00000000000..6a72ad5134f --- /dev/null +++ b/gcc/testsuite/g++.dg/torture/pr84961-1.C @@ -0,0 +1,24 @@ +// PR c++/84961 +// { dg-do compile } + +short a; +volatile int b; +int c, d; + +void +foo () +{ + asm volatile ("" : "=r" (b = a)); +} + +void +bar () +{ + asm volatile ("" : "=r" (++c, ++d, b = a)); +} + +void +baz () +{ + asm volatile ("" : "=r" (--b)); +} diff --git a/gcc/testsuite/g++.dg/torture/pr84961-2.C b/gcc/testsuite/g++.dg/torture/pr84961-2.C new file mode 100644 index 00000000000..0909eedb7f9 --- /dev/null +++ b/gcc/testsuite/g++.dg/torture/pr84961-2.C @@ -0,0 +1,24 @@ +// PR c++/84961 +// { dg-do compile } + +short a; +volatile int b; +int c, d; + +void +foo () +{ + asm volatile ("" : : "m" (b = a)); +} + +void +bar () +{ + asm volatile ("" : : "m" (++c, ++d, b = a)); +} + +void +baz () +{ + asm volatile ("" : : "m" (--b)); +}