d: RHS value lost when a target_expr modifies LHS in a cond_expr

To prevent the RHS of an assignment modifying the LHS before the
assignment proper, a target_expr is forced so that function calls that
return with slot optimization modify the temporary instead.  This did
not work for conditional expressions however, to give one example.  So
now the RHS is always forced to a temporary.

	PR d/101282

gcc/d/ChangeLog:

	* d-codegen.cc (build_assign): Force target_expr on RHS for non-POD
	assignment expressions.

gcc/testsuite/ChangeLog:

	* gdc.dg/torture/pr101282.d: New test.
This commit is contained in:
Iain Buclaw 2021-07-03 00:13:29 +02:00
parent 6feb628a70
commit c77230856e
2 changed files with 30 additions and 0 deletions

View File

@ -1344,6 +1344,13 @@ build_assign (tree_code code, tree lhs, tree rhs)
d_mark_addressable (lhs);
CALL_EXPR_RETURN_SLOT_OPT (rhs) = true;
}
/* If modifying an LHS whose type is marked TREE_ADDRESSABLE. */
else if (code == MODIFY_EXPR && TREE_ADDRESSABLE (TREE_TYPE (lhs))
&& TREE_SIDE_EFFECTS (rhs) && TREE_CODE (rhs) != TARGET_EXPR)
{
/* LHS may be referenced by the RHS expression, so force a temporary. */
rhs = force_target_expr (rhs);
}
/* The LHS assignment replaces the temporary in TARGET_EXPR_SLOT. */
if (TREE_CODE (rhs) == TARGET_EXPR)

View File

@ -0,0 +1,23 @@
// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101282
// { dg-do run }
void main()
{
struct S101282
{
int impl;
S101282 opUnary(string op : "-")()
{
return S101282(-impl);
}
int opCmp(int i)
{
return (impl < i) ? -1 : (impl > i) ? 1 : 0;
}
}
auto a = S101282(120);
a = -a;
assert(a.impl == -120);
a = a >= 0 ? a : -a;
assert(a.impl == 120);
}