aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2018-03-21 21:19:33 +0100
committerJakub Jelinek <jakub@gcc.gnu.org>2018-03-21 21:19:33 +0100
commit57e20f74e011f190a29ec0b414c0ee74e62ebdc9 (patch)
treef41cf51616f80f3c15202210cfdc0de3ca0b3ac7 /gcc
parentb2595987bd320849de932cd2bcf83d2faf5f3ee8 (diff)
downloadgcc-57e20f74e011f190a29ec0b414c0ee74e62ebdc9.zip
gcc-57e20f74e011f190a29ec0b414c0ee74e62ebdc9.tar.gz
gcc-57e20f74e011f190a29ec0b414c0ee74e62ebdc9.tar.bz2
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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog11
-rw-r--r--gcc/cp/cp-tree.h1
-rw-r--r--gcc/cp/semantics.c35
-rw-r--r--gcc/cp/typeck.c43
-rw-r--r--gcc/testsuite/ChangeLog8
-rw-r--r--gcc/testsuite/c-c++-common/pr43690.c4
-rw-r--r--gcc/testsuite/g++.dg/torture/pr84961-1.C24
-rw-r--r--gcc/testsuite/g++.dg/torture/pr84961-2.C24
8 files changed, 125 insertions, 25 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index e97f99d..fd2f371 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,14 @@
+2018-03-21 Jakub Jelinek <jakub@redhat.com>
+
+ 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 <nathan@acm.org>
PR c++/85008
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index d5382c2..c07aaa5 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 fdf37be..4b9fc27 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 0c2ebd1..d3183b5 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 6ecd1f5..4e787c5 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,11 @@
+2018-03-21 Jakub Jelinek <jakub@redhat.com>
+
+ 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 <nathan@acm.org>
PR c++/85008
diff --git a/gcc/testsuite/c-c++-common/pr43690.c b/gcc/testsuite/c-c++-common/pr43690.c
index 67c6cb0..8d10744 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 0000000..6a72ad5
--- /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 0000000..0909eed
--- /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));
+}