summaryrefslogtreecommitdiff
path: root/gcc/d/dmd/optimize.d
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/d/dmd/optimize.d')
-rw-r--r--gcc/d/dmd/optimize.d49
1 files changed, 39 insertions, 10 deletions
diff --git a/gcc/d/dmd/optimize.d b/gcc/d/dmd/optimize.d
index 3745a15da42..3cc36b49e01 100644
--- a/gcc/d/dmd/optimize.d
+++ b/gcc/d/dmd/optimize.d
@@ -271,7 +271,7 @@ package void setLengthVarIfKnown(VarDeclaration lengthVar, Type type)
*/
Expression Expression_optimize(Expression e, int result, bool keepLvalue)
{
- //printf("Expression_optimize() %s\n", e.toChars());
+ //printf("Expression_optimize() e: %s result: %d keepLvalue %d\n", e.toChars(), result, keepLvalue);
Expression ret = e;
void error()
@@ -426,7 +426,7 @@ Expression Expression_optimize(Expression e, int result, bool keepLvalue)
void visitAddr(AddrExp e)
{
- //printf("AddrExp::optimize(result = %d) %s\n", result, e.toChars());
+ //printf("AddrExp::optimize(result = %d, keepLvalue = %d) %s\n", result, keepLvalue, e.toChars());
/* Rewrite &(a,b) as (a,&b)
*/
if (auto ce = e.e1.isCommaExp())
@@ -438,7 +438,8 @@ Expression Expression_optimize(Expression e, int result, bool keepLvalue)
}
// Keep lvalue-ness
if (expOptimize(e.e1, result, true))
- return;
+ return; // error return
+
// Convert &*ex to ex
if (auto pe = e.e1.isPtrExp())
{
@@ -515,6 +516,23 @@ Expression Expression_optimize(Expression e, int result, bool keepLvalue)
}
}
}
+ else if (auto ei = e.isIndexExp())
+ {
+ if (auto ve = ei.e1.isVarExp())
+ {
+ if (!ve.var.isReference() &&
+ !ve.var.isImportedSymbol() &&
+ ve.var.isDataseg() &&
+ ve.var.isCsymbol())
+ {
+ if (auto ie = ei.e2.isIntegerExp())
+ {
+ var = ve.var.isVarDeclaration();
+ offset += ie.toInteger() * ve.type.toBasetype().nextOf().size();
+ }
+ }
+ }
+ }
return false;
}
@@ -538,7 +556,7 @@ Expression Expression_optimize(Expression e, int result, bool keepLvalue)
return;
}
}
- if (auto ae = e.e1.isIndexExp())
+ else if (auto ae = e.e1.isIndexExp())
{
// Convert &array[n] to &array+n
if (ae.e2.isIntegerExp() && ae.e1.isVarExp())
@@ -551,9 +569,10 @@ Expression Expression_optimize(Expression e, int result, bool keepLvalue)
sinteger_t dim = ts.dim.toInteger();
if (index < 0 || index >= dim)
{
- /* 0 for C static arrays means size is unknown, no need to check
+ /* 0 for C static arrays means size is unknown, no need to check,
+ * and address one past the end is OK, too
*/
- if (!(dim == 0 && ve.var.isCsymbol()))
+ if (!((dim == 0 || dim == index) && ve.var.isCsymbol()))
{
e.error("array index %lld is out of bounds `[0..%lld]`", index, dim);
return error();
@@ -574,7 +593,7 @@ Expression Expression_optimize(Expression e, int result, bool keepLvalue)
return;
}
}
- // Convert &((a.b)[n]) to (&a.b)+n
+ // Convert &((a.b)[index]) to (&a.b)+index*elementsize
else if (ae.e2.isIntegerExp() && ae.e1.isDotVarExp())
{
sinteger_t index = ae.e2.toInteger();
@@ -585,18 +604,28 @@ Expression Expression_optimize(Expression e, int result, bool keepLvalue)
sinteger_t dim = ts.dim.toInteger();
if (index < 0 || index >= dim)
{
- /* 0 for C static arrays means size is unknown, no need to check
+ /* 0 for C static arrays means size is unknown, no need to check,
+ * and address one past the end is OK, too
*/
- if (!(dim == 0 && ve.var.isCsymbol()))
+ if (!((dim == 0 || dim == index) && ve.var.isCsymbol()))
{
e.error("array index %lld is out of bounds `[0..%lld]`", index, dim);
return error();
}
}
+ import core.checkedint : mulu;
+ bool overflow;
+ const offset = mulu(index, ts.nextOf().size(e.loc), overflow); // index*elementsize
+ if (overflow)
+ {
+ e.error("array offset overflow");
+ return error();
+ }
+
auto pe = new AddrExp(e.loc, ve);
pe.type = e.type;
- ret = new AddExp(e.loc, pe, ae.e2);
+ ret = new AddExp(e.loc, pe, new IntegerExp(e.loc, offset, Type.tsize_t));
ret.type = e.type;
return;
}