Skip to content

Commit

Permalink
fix Issue 13976 - Value range propagation to disable some slice bound…
Browse files Browse the repository at this point in the history
… tests
  • Loading branch information
9rnsr committed Jan 14, 2015
1 parent b87f342 commit d80902b
Show file tree
Hide file tree
Showing 4 changed files with 114 additions and 39 deletions.
79 changes: 40 additions & 39 deletions src/e2ir.c
Expand Up @@ -4412,71 +4412,72 @@ elem *toElem(Expression *e, IRState *irs)
if (se->lwr)
{
elem *einit = resolveLengthVar(se->lengthVar, &e, t1);

unsigned sz = t1->nextOf()->size();

elem *elwr = toElem(se->lwr, irs);
elem *eupr = toElem(se->upr, irs);

elem *elwr2 = el_same(&elwr);
elem *eupr2 = eupr;

//printf("upperIsInBounds = %d lowerIsLessThanUpper = %d\n", se->upperIsInBounds, se->lowerIsLessThanUpper);
if (irs->arrayBoundsCheck())
{
// Checks (unsigned compares):
// upr <= array.length
// lwr <= upr

elem *c1;
elem *c2;
elem *eupr2;

if (t1->ty == Tpointer)
elem *c1 = NULL;
if (!se->upperIsInBounds)
{
// Just do lwr <= upr check

eupr2 = el_same(&eupr);
eupr2->Ety = TYsize_t; // make sure unsigned comparison
c1 = el_bin(OPle, TYint, elwr2, eupr2);
c1 = el_combine(eupr, c1);
}
else
{
elem *elength;
eupr2->Ety = TYsize_t; // make sure unsigned comparison

elem *elen;
if (t1->ty == Tsarray)
{
TypeSArray *tsa = (TypeSArray *)t1;
dinteger_t length = tsa->dim->toInteger();

elength = el_long(TYsize_t, length);
elen = el_long(TYsize_t, tsa->dim->toInteger());
}
else if (t1->ty == Tarray)
{
if (se->lengthVar && !(se->lengthVar->storage_class & STCconst))
elength = el_var(toSymbol(se->lengthVar));
elen = el_var(toSymbol(se->lengthVar));
else
{
elength = e;
e = el_same(&elength);
elength = el_una(I64 ? OP128_64 : OP64_32, TYsize_t, elength);
elen = e;
e = el_same(&elen);
elen = el_una(I64 ? OP128_64 : OP64_32, TYsize_t, elen);
}
}

c1 = el_bin(OPle, TYint, eupr, elen);

if (!se->lowerIsLessThanUpper)
{
c1 = el_bin(OPandand, TYint,
c1, el_bin(OPle, TYint, elwr2, eupr2));
elwr2 = el_copytree(elwr2);
eupr2 = el_copytree(eupr2);
}
}
else if (!se->lowerIsLessThanUpper)
{
eupr2 = el_same(&eupr);
c1 = el_bin(OPle, TYint, eupr, elength);
eupr2->Ety = TYsize_t; // make sure unsigned comparison
c2 = el_bin(OPle, TYint, elwr2, eupr2);
c1 = el_bin(OPandand, TYint, c1, c2); // (c1 && c2)
eupr2->Ety = TYsize_t; // make sure unsigned comparison

c1 = el_bin(OPle, TYint, elwr2, eupr);
elwr2 = el_copytree(elwr2);
}

// Construct: (c1 || ModuleArray(line))
Symbol *sassert = irs->blx->module->toModuleArray();
elem *ea = el_bin(OPcall, TYvoid, el_var(sassert), el_long(TYint, se->loc.linnum));
elem *eb = el_bin(OPoror, TYvoid, c1, ea);
elwr = el_combine(elwr, eb);
if (c1)
{
// Construct: (c1 || ModuleArray(line))
Symbol *sassert = irs->blx->module->toModuleArray();
elem *ea = el_bin(OPcall, TYvoid, el_var(sassert), el_long(TYint, se->loc.linnum));
elem *eb = el_bin(OPoror, TYvoid, c1, ea);

elwr2 = el_copytree(elwr2);
eupr = el_copytree(eupr2);
elwr = el_combine(elwr, eb);
}
}

// Create an array reference where:
Expand All @@ -4486,18 +4487,18 @@ elem *toElem(Expression *e, IRState *irs)

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

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

if (tb->ty == Tarray)
{
elem *elength = el_bin(OPmin, TYsize_t, eupr, el_copytree(elwr2));
e = el_combine(e, el_pair(TYdarray, elength, eptr));
elem *elen = el_bin(OPmin, TYsize_t, eupr2, el_copytree(elwr2));
e = el_combine(e, el_pair(TYdarray, elen, eptr));
}
else
{
assert(tb->ty == Tsarray);
e = el_una(OPind, totym(se->type), eptr);
e = el_una(OPind, totym(se->type), el_combine(e, eptr));
if (tybasic(e->Ety) == TYstruct)
e->ET = Type_toCtype(se->type);
}
Expand Down
34 changes: 34 additions & 0 deletions src/expression.c
Expand Up @@ -9737,6 +9737,8 @@ SliceExp::SliceExp(Loc loc, Expression *e1, Expression *lwr, Expression *upr)
this->upr = upr;
this->lwr = lwr;
lengthVar = NULL;
upperIsInBounds = false;
lowerIsLessThanUpper = false;
}

Expression *SliceExp::syntaxCopy()
Expand Down Expand Up @@ -9977,6 +9979,38 @@ Expression *SliceExp::semantic(Scope *sc)
if (type->equals(t1b))
type = e1->type;

if (lwr && upr)
{
lwr = lwr->optimize(WANTvalue);
upr = upr->optimize(WANTvalue);

IntRange lwrRange = getIntRange(lwr);
IntRange uprRange = getIntRange(upr);

if (t1b->ty == Tsarray || t1b->ty == Tarray)
{
Expression *el = new ArrayLengthExp(loc, e1);
el = el->semantic(sc);
el = el->optimize(WANTvalue);
if (el->op == TOKint64)
{
dinteger_t length = el->toInteger();
IntRange bounds(SignExtendedNumber(0), SignExtendedNumber(length));
this->upperIsInBounds = bounds.contains(uprRange);
}
}
else if (t1b->ty == Tpointer)
{
this->upperIsInBounds = true;
}
else
assert(0);

this->lowerIsLessThanUpper = (lwrRange.imax <= uprRange.imin);

//printf("upperIsInBounds = %d lowerIsLessThanUpper = %d\n", upperIsInBounds, lowerIsLessThanUpper);
}

return this;
}

Expand Down
2 changes: 2 additions & 0 deletions src/expression.h
Expand Up @@ -1008,6 +1008,8 @@ class SliceExp : public UnaExp
Expression *upr; // NULL if implicit 0
Expression *lwr; // NULL if implicit [length - 1]
VarDeclaration *lengthVar;
bool upperIsInBounds; // true if upr <= e1.length
bool lowerIsLessThanUpper; // true if lwr <= upr

SliceExp(Loc loc, Expression *e1, Expression *lwr, Expression *upr);
Expression *syntaxCopy();
Expand Down
38 changes: 38 additions & 0 deletions test/runnable/testbounds.d
Expand Up @@ -176,11 +176,49 @@ void test1()
assert(r[0] == foop[1]);
}

/******************************************/
// 13976

void test13976()
{
int[] da = new int[](10);
int[10] sa;
size_t l = 0; // upperInRange
size_t u = 9; // | lowerLessThan
// | | check code
{ auto s = da[l .. u]; } // 0 0 (u <= 10 && l <= u )
{ auto s = da[1 .. u]; } // 0 0 (u <= 10 && l <= u )
{ auto s = da[l .. 10]; } // 0 0 (u <= 10 && l <= u )
{ auto s = da[1 .. u%5]; } // 0 0 (u <= 10 && l <= u%5)

{ auto s = da[l .. u]; } // 0 0 (u <= 10 && l <= u)
{ auto s = da[0 .. u]; } // 0 1 (u <= 10 )
{ auto s = da[l .. 10]; } // 0 0 (u <= 10 && l <= u)
{ auto s = da[0 .. u%5]; } // 0 1 (u%5 <= 10 )

{ auto s = sa[l .. u]; } // 0 0 (u <= 10 && l <= u )
{ auto s = sa[1 .. u]; } // 0 0 (u <= 10 && l <= u )
{ auto s = sa[l .. 10]; } // 1 0 ( l <= u )
{ auto s = sa[1 .. u%5]; } // 1 0 ( l <= u%5)

{ auto s = sa[l .. u]; } // 0 0 (u <= 10 && l <= u )
{ auto s = sa[0 .. u]; } // 0 1 (u <= 10 )
{ auto s = sa[l .. 10]; } // 1 0 ( l <= 10)
{ auto s = sa[0 .. u%5]; } // 1 1 NULL

int* p = new int[](10).ptr;
{ auto s = p[0 .. u]; } // 1 1 NULL
{ auto s = p[l .. u]; } // 1 0 (l <= u)
{ auto s = p[0 .. u%5]; } // 1 1 NULL
{ auto s = p[1 .. u%5]; } // 1 0 (l <= u%5)
}

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

int main()
{
test1();
test13976();

printf("Success\n");
return 0;
Expand Down

0 comments on commit d80902b

Please sign in to comment.