Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
81 changes: 41 additions & 40 deletions src/e2ir.c
Original file line number Diff line number Diff line change
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 Expand Up @@ -4581,7 +4582,7 @@ elem *toElem(Expression *e, IRState *irs)
elem *einit = resolveLengthVar(ie->lengthVar, &n1, t1);
elem *n2 = toElem(ie->e2, irs);

if (irs->arrayBoundsCheck() && !ie->skipboundscheck)
if (irs->arrayBoundsCheck() && !ie->indexIsInBounds)
{
elem *elength;

Expand Down
41 changes: 39 additions & 2 deletions src/expression.c
Original file line number Diff line number Diff line change
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 Expand Up @@ -10390,7 +10424,7 @@ IndexExp::IndexExp(Loc loc, Expression *e1, Expression *e2)
//printf("IndexExp::IndexExp('%s')\n", toChars());
lengthVar = NULL;
modifiable = false; // assume it is an rvalue
skipboundscheck = 0;
indexIsInBounds = false;
}

Expression *IndexExp::syntaxCopy()
Expand Down Expand Up @@ -10573,7 +10607,10 @@ Expression *IndexExp::semantic(Scope *sc)
e2 = e2->optimize(WANTvalue);
dinteger_t length = el->toInteger();
if (length)
skipboundscheck = IntRange(SignExtendedNumber(0), SignExtendedNumber(length-1)).contains(getIntRange(e2));
{
IntRange bounds(SignExtendedNumber(0), SignExtendedNumber(length - 1));
indexIsInBounds = bounds.contains(getIntRange(e2));
}
}
}

Expand Down
4 changes: 3 additions & 1 deletion src/expression.h
Original file line number Diff line number Diff line change
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 Expand Up @@ -1110,7 +1112,7 @@ class IndexExp : public BinExp
public:
VarDeclaration *lengthVar;
bool modifiable;
bool skipboundscheck;
bool indexIsInBounds; // true if 0 <= e2 && e2 <= e1.length - 1

IndexExp(Loc loc, Expression *e1, Expression *e2);
Expression *syntaxCopy();
Expand Down
38 changes: 38 additions & 0 deletions test/runnable/testbounds.d
Original file line number Diff line number Diff line change
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