Showing with 66 additions and 7 deletions.
  1. +16 −0 src/backend/el.c
  2. +1 −0 src/backend/el.h
  3. +19 −7 src/e2ir.c
  4. +30 −0 test/runnable/evalorder.d
16 changes: 16 additions & 0 deletions src/backend/el.c
Original file line number Diff line number Diff line change
Expand Up @@ -623,6 +623,22 @@ elem * el_same(elem **pe)
return el_copytree(e);
}

/*************************
* Thin wrapper of exp2_copytotemp. Different from el_same,
* always makes a temporary.
*/
elem *el_copytotmp(elem **pe)
{
//printf("copytotemp()\n");
elem *e = *pe;
if (e)
{
*pe = exp2_copytotemp(e);
e = (*pe)->E2;
}
return el_copytree(e);
}

/**************************
* Replace symbol s1 with s2 in tree.
*/
Expand Down
1 change: 1 addition & 0 deletions src/backend/el.h
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@ int el_signx32(elem_p);
targ_ldouble el_toldouble(elem_p);
void el_toconst(elem_p);
elem_p el_same(elem_p *);
elem_p el_copytotmp(elem_p *);
int el_match(elem_p ,elem_p);
int el_match2(elem_p ,elem_p);
int el_match3(elem_p ,elem_p);
Expand Down
26 changes: 19 additions & 7 deletions src/e2ir.c
Original file line number Diff line number Diff line change
Expand Up @@ -4573,12 +4573,23 @@ elem *toElem(Expression *e, IRState *irs)
elem *e = toElem(se->e1, irs);
if (se->lwr)
{
elem *einit = resolveLengthVar(se->lengthVar, &e, t1);
unsigned sz = t1->nextOf()->size();

elem *einit = resolveLengthVar(se->lengthVar, &e, t1);
if (t1->ty == Tsarray)
e = array_toPtr(se->e1->type, e);
if (!einit)
{
einit = e;
e = el_same(&einit);
}
// e is a temporary, typed:
// TYdarray if t->ty == Tarray
// TYptr if t->ty == Tsarray or Tpointer

elem *elwr = toElem(se->lwr, irs);
elem *eupr = toElem(se->upr, irs);
elem *elwr2 = el_same(&elwr);
elem *elwr2 = el_sideeffect(eupr) ? el_copytotmp(&elwr) : el_same(&elwr);
elem *eupr2 = eupr;

//printf("upperIsInBounds = %d lowerIsLessThanUpper = %d\n", se->upperIsInBounds, se->lowerIsLessThanUpper);
Expand Down Expand Up @@ -4641,31 +4652,32 @@ elem *toElem(Expression *e, IRState *irs)
elwr = el_combine(elwr, eb);
}
}
if (t1->ty != Tsarray)
e = array_toPtr(se->e1->type, e);

// Create an array reference where:
// length is (upr - lwr)
// pointer is (ptr + lwr*sz)
// Combine as (length pair ptr)

e = array_toPtr(se->e1->type, e);

elem *eofs = el_bin(OPmul, TYsize_t, elwr2, el_long(TYsize_t, sz));
elem *eptr = el_bin(OPadd, TYnptr, el_same(&e), eofs);
elem *eptr = el_bin(OPadd, TYnptr, e, eofs);

if (tb->ty == Tarray)
{
elem *elen = el_bin(OPmin, TYsize_t, eupr2, el_copytree(elwr2));
e = el_combine(e, el_pair(TYdarray, elen, eptr));
e = el_pair(TYdarray, elen, eptr);
}
else
{
assert(tb->ty == Tsarray);
e = el_una(OPind, totym(se->type), el_combine(e, eptr));
e = el_una(OPind, totym(se->type), eptr);
if (tybasic(e->Ety) == TYstruct)
e->ET = Type_toCtype(se->type);
}
e = el_combine(elwr, e);
e = el_combine(einit, e);
//elem_print(e);
}
else if (t1->ty == Tsarray && tb->ty == Tarray)
{
Expand Down
30 changes: 30 additions & 0 deletions test/runnable/evalorder.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
extern(C) int printf(const char*, ...);

void test14040()
{
uint[] values = [0, 1, 2, 3, 4, 5, 6, 7];
uint offset = 0;

auto a1 = values[offset .. offset += 2];
if (a1 != [0, 1] || offset != 2)
assert(0);

uint[] fun()
{
offset += 2;
return values;
}
auto a2 = fun()[offset .. offset += 2];
if (a2 != [4, 5] || offset != 6)
assert(0);
}

/******************************************/

int main()
{
test14040();

printf("Success\n");
return 0;
}