diff options
Diffstat (limited to 'gcc/d/dmd/optimize.d')
-rw-r--r-- | gcc/d/dmd/optimize.d | 49 |
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; } |