Skip to content

Commit

Permalink
Merge pull request #10577 from SSoulaimane/irlvalue
Browse files Browse the repository at this point in the history
Fix issue 20401 - The glue shouldn't copy side effects by value where the lvalue is wanted
merged-on-behalf-of: Nicholas Wilson <thewilsonator@users.noreply.github.com>
  • Loading branch information
dlang-bot committed Nov 23, 2019
2 parents c37827a + 4cfff1c commit b0cdc91
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 3 deletions.
25 changes: 22 additions & 3 deletions src/dmd/e2ir.d
Expand Up @@ -683,6 +683,26 @@ elem *addressElem(elem *e, Type t, bool alwaysCopy = false)
return e;
}

/***************************************
* Return `true` if elem is a an lvalue.
* Lvalue elems are OPvar and OPind.
*/

bool elemIsLvalue(elem* e)
{
while (e.Eoper == OPcomma || e.Eoper == OPinfo)
e = e.EV.E2;

// For conditional operator, both branches need to be lvalues.
if (e.Eoper == OPcond)
{
elem* ec = e.EV.E2;
return elemIsLvalue(ec.EV.E1) && elemIsLvalue(ec.EV.E2);
}

return e.Eoper == OPvar || e.Eoper == OPind;
}

/*****************************************
* Convert array to a pointer to the data.
* Params:
Expand Down Expand Up @@ -5890,10 +5910,9 @@ private elem *appendDtors(IRState *irs, elem *er, size_t starti, size_t endi)
{
*pe = el_combine(edtors, erx);
}
else if ((tybasic(erx.Ety) == TYstruct || tybasic(erx.Ety) == TYarray) &&
!(erx.ET && type_size(erx.ET) <= 16))
else if (elemIsLvalue(erx))
{
/* Expensive to copy, to take a pointer to it instead
/* Lvalue, take a pointer to it
*/
elem *ep = el_una(OPaddr, TYnptr, erx);
elem *e = el_same(&ep);
Expand Down
20 changes: 20 additions & 0 deletions test/runnable/test20401.d
@@ -0,0 +1,20 @@
// https://issues.dlang.org/show_bug.cgi?id=20401

void main()
{
int i;
assert(&passthrough(i) == &i);
}

ref int passthrough(return ref int i)
{
return get().flag ? i : i;
}

S get() { return S(); }

struct S
{
bool flag;
~this(){}
}

0 comments on commit b0cdc91

Please sign in to comment.