Commit 57e20f74 by Jakub Jelinek Committed by Jakub Jelinek

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
parent b2595987
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> 2018-03-21 Nathan Sidwell <nathan@acm.org>
PR c++/85008 PR c++/85008
......
...@@ -7145,6 +7145,7 @@ extern tree cp_build_addressof (location_t, tree, ...@@ -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_addr_expr (tree, tsubst_flags_t);
extern tree cp_build_unary_op (enum tree_code, tree, bool, extern tree cp_build_unary_op (enum tree_code, tree, bool,
tsubst_flags_t); tsubst_flags_t);
extern tree genericize_compound_lvalue (tree);
extern tree unary_complex_lvalue (enum tree_code, tree); extern tree unary_complex_lvalue (enum tree_code, tree);
extern tree build_x_conditional_expr (location_t, tree, tree, tree, extern tree build_x_conditional_expr (location_t, tree, tree, tree,
tsubst_flags_t); tsubst_flags_t);
......
...@@ -1512,6 +1512,21 @@ finish_asm_stmt (int volatile_p, tree string, tree output_operands, ...@@ -1512,6 +1512,21 @@ finish_asm_stmt (int volatile_p, tree string, tree output_operands,
&& C_TYPE_FIELDS_READONLY (TREE_TYPE (operand))))) && C_TYPE_FIELDS_READONLY (TREE_TYPE (operand)))))
cxx_readonly_error (operand, lv_asm); 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))); constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (t)));
oconstraints[i] = constraint; oconstraints[i] = constraint;
...@@ -1520,7 +1535,7 @@ finish_asm_stmt (int volatile_p, tree string, tree output_operands, ...@@ -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, /* If the operand is going to end up in memory,
mark it addressable. */ mark it addressable. */
if (!allows_reg && !cxx_mark_addressable (operand)) if (!allows_reg && !cxx_mark_addressable (*op))
operand = error_mark_node; operand = error_mark_node;
} }
else else
...@@ -1562,7 +1577,23 @@ finish_asm_stmt (int volatile_p, tree string, tree output_operands, ...@@ -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 /* Strip the nops as we allow this case. FIXME, this really
should be rejected or made deprecated. */ should be rejected or made deprecated. */
STRIP_NOPS (operand); 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; operand = error_mark_node;
} }
else if (!allows_reg && !allows_mem) else if (!allows_reg && !allows_mem)
......
...@@ -6357,6 +6357,25 @@ build_unary_op (location_t /*location*/, ...@@ -6357,6 +6357,25 @@ build_unary_op (location_t /*location*/,
return cp_build_unary_op (code, xarg, noconvert, tf_warning_or_error); 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 /* Apply unary lvalue-demanding operator CODE to the expression ARG
for certain kinds of expressions which are not really lvalues for certain kinds of expressions which are not really lvalues
but which we can accept as lvalues. but which we can accept as lvalues.
...@@ -6391,17 +6410,7 @@ unary_complex_lvalue (enum tree_code code, tree arg) ...@@ -6391,17 +6410,7 @@ unary_complex_lvalue (enum tree_code code, tree arg)
if (TREE_CODE (arg) == MODIFY_EXPR if (TREE_CODE (arg) == MODIFY_EXPR
|| TREE_CODE (arg) == PREINCREMENT_EXPR || TREE_CODE (arg) == PREINCREMENT_EXPR
|| TREE_CODE (arg) == PREDECREMENT_EXPR) || TREE_CODE (arg) == PREDECREMENT_EXPR)
{ return unary_complex_lvalue (code, genericize_compound_lvalue (arg));
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));
}
if (code != ADDR_EXPR) if (code != ADDR_EXPR)
return NULL_TREE; return NULL_TREE;
...@@ -7887,11 +7896,7 @@ cp_build_modify_expr (location_t loc, tree lhs, enum tree_code modifycode, ...@@ -7887,11 +7896,7 @@ cp_build_modify_expr (location_t loc, tree lhs, enum tree_code modifycode,
case PREINCREMENT_EXPR: case PREINCREMENT_EXPR:
if (compound_side_effects_p) if (compound_side_effects_p)
newrhs = rhs = stabilize_expr (rhs, &preeval); newrhs = rhs = stabilize_expr (rhs, &preeval);
if (TREE_SIDE_EFFECTS (TREE_OPERAND (lhs, 0))) lhs = genericize_compound_lvalue (lhs);
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));
maybe_add_compound: maybe_add_compound:
/* If we had (bar, --foo) = 5; or (bar, (baz, --foo)) = 5; /* If we had (bar, --foo) = 5; or (bar, (baz, --foo)) = 5;
and looked through the COMPOUND_EXPRs, readd them now around 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, ...@@ -7914,11 +7919,7 @@ cp_build_modify_expr (location_t loc, tree lhs, enum tree_code modifycode,
case MODIFY_EXPR: case MODIFY_EXPR:
if (compound_side_effects_p) if (compound_side_effects_p)
newrhs = rhs = stabilize_expr (rhs, &preeval); newrhs = rhs = stabilize_expr (rhs, &preeval);
if (TREE_SIDE_EFFECTS (TREE_OPERAND (lhs, 0))) lhs = genericize_compound_lvalue (lhs);
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));
goto maybe_add_compound; goto maybe_add_compound;
case MIN_EXPR: case MIN_EXPR:
......
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> 2018-03-21 Nathan Sidwell <nathan@acm.org>
PR c++/85008 PR c++/85008
......
...@@ -6,8 +6,8 @@ void ...@@ -6,8 +6,8 @@ void
foo (char *x) 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" } */ 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" } */ asm ("" : : "m" (--x)); /* { dg-error "is not directly addressable" "" { target c } } */
asm ("" : : "m" (x + 1)); /* { dg-error "is not directly addressable" } */ asm ("" : : "m" (x + 1)); /* { dg-error "is not directly addressable" } */
} }
// 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));
}
// 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));
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment