diff --git a/src/dmd/expressionsem.d b/src/dmd/expressionsem.d index 331f5ed4d1c0..b9ba50c1f3b5 100644 --- a/src/dmd/expressionsem.d +++ b/src/dmd/expressionsem.d @@ -5706,6 +5706,9 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor if (exp.type.equals(t1b)) exp.type = exp.e1.type; + // We might know $ now + setLengthVarIfKnown(exp.lengthVar, t1b); + if (exp.lwr && exp.upr) { exp.lwr = exp.lwr.optimize(WANTvalue); @@ -5735,7 +5738,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor exp.lowerIsLessThanUpper = (lwrRange.imax <= uprRange.imin); - //printf("upperIsInBounds = %d lowerIsLessThanUpper = %d\n", upperIsInBounds, lowerIsLessThanUpper); + //printf("upperIsInBounds = %d lowerIsLessThanUpper = %d\n", exp.upperIsInBounds, exp.lowerIsLessThanUpper); } result = exp; @@ -6115,6 +6118,9 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor return setError(); } + // We might know $ now + setLengthVarIfKnown(exp.lengthVar, t1b); + if (t1b.ty == Tsarray || t1b.ty == Tarray) { Expression el = new ArrayLengthExp(exp.loc, exp.e1); diff --git a/src/dmd/optimize.d b/src/dmd/optimize.d index 129b624feb85..1e21f39642d3 100644 --- a/src/dmd/optimize.d +++ b/src/dmd/optimize.d @@ -206,6 +206,52 @@ private Expression fromConstInitializer(int result, Expression e1) return e; } +/* It is possible for constant folding to change an array expression of + * unknown length, into one where the length is known. + * If the expression 'arr' is a literal, set lengthVar to be its length. + */ +package void setLengthVarIfKnown(VarDeclaration lengthVar, Expression arr) +{ + if (!lengthVar) + return; + if (lengthVar._init && !lengthVar._init.isVoidInitializer()) + return; // we have previously calculated the length + size_t len; + if (arr.op == TOK.string_) + len = (cast(StringExp)arr).len; + else if (arr.op == TOK.arrayLiteral) + len = (cast(ArrayLiteralExp)arr).elements.dim; + else + { + Type t = arr.type.toBasetype(); + if (t.ty == Tsarray) + len = cast(size_t)(cast(TypeSArray)t).dim.toInteger(); + else + return; // we don't know the length yet + } + Expression dollar = new IntegerExp(Loc.initial, len, Type.tsize_t); + lengthVar._init = new ExpInitializer(Loc.initial, dollar); + lengthVar.storage_class |= STC.static_ | STC.const_; +} + +/* Same as above, but determines the length from 'type'. */ +package void setLengthVarIfKnown(VarDeclaration lengthVar, Type type) +{ + if (!lengthVar) + return; + if (lengthVar._init && !lengthVar._init.isVoidInitializer()) + return; // we have previously calculated the length + size_t len; + Type t = type.toBasetype(); + if (t.ty == Tsarray) + len = cast(size_t)(cast(TypeSArray)t).dim.toInteger(); + else + return; // we don't know the length yet + Expression dollar = new IntegerExp(Loc.initial, len, Type.tsize_t); + lengthVar._init = new ExpInitializer(Loc.initial, dollar); + lengthVar.storage_class |= STC.static_ | STC.const_; +} + /********************************* * Constant fold an Expression. * Params: @@ -1001,34 +1047,6 @@ extern (C++) Expression Expression_optimize(Expression e, int result, bool keepL } } - /* It is possible for constant folding to change an array expression of - * unknown length, into one where the length is known. - * If the expression 'arr' is a literal, set lengthVar to be its length. - */ - static void setLengthVarIfKnown(VarDeclaration lengthVar, Expression arr) - { - if (!lengthVar) - return; - if (lengthVar._init && !lengthVar._init.isVoidInitializer()) - return; // we have previously calculated the length - size_t len; - if (arr.op == TOK.string_) - len = (cast(StringExp)arr).len; - else if (arr.op == TOK.arrayLiteral) - len = (cast(ArrayLiteralExp)arr).elements.dim; - else - { - Type t = arr.type.toBasetype(); - if (t.ty == Tsarray) - len = cast(size_t)(cast(TypeSArray)t).dim.toInteger(); - else - return; // we don't know the length yet - } - Expression dollar = new IntegerExp(Loc.initial, len, Type.tsize_t); - lengthVar._init = new ExpInitializer(Loc.initial, dollar); - lengthVar.storage_class |= STC.static_ | STC.const_; - } - override void visit(IndexExp e) { //printf("IndexExp::optimize(result = %d) %s\n", result, e.toChars()); diff --git a/test/runnable/testbounds.d b/test/runnable/testbounds.d index b23c88f29b6c..2deb8902793a 100644 --- a/test/runnable/testbounds.d +++ b/test/runnable/testbounds.d @@ -185,34 +185,53 @@ 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 + enum size_t two = 2; + enum size_t five = 5; + size_t lb = 0; // upperInRange + size_t ub = 9; // | lowerLessThan + // | | check code + { auto s = da[lb .. ub]; } // 0 0 (ub <= $ && lb <= ub ) + { auto s = da[1 .. ub]; } // 0 0 (ub <= $ && 1 <= ub ) + { auto s = da[lb .. 10]; } // 0 0 (10 <= $ && lb <= 10 ) + { auto s = da[1 .. ub%5]; } // 0 0 (ub%5 <= $ && 1 <= ub%5) + + { auto s = da[lb .. ub]; } // 0 0 (ub <= $ && lb <= ub ) + { auto s = da[0 .. ub]; } // 0 1 (ub <= $ ) + { auto s = da[lb .. 10]; } // 0 0 (10 <= $ && lb <= 10 ) + { auto s = da[0 .. ub%5]; } // 0 1 (ub%5 <= $ ) + + { auto s = da[0 .. 0]; } // 0 1 (0 <= $ ) + { auto s = da[0 .. $]; } // 0 1 ($ <= $ ) + { auto s = da[1 .. $]; } // 0 0 ($ <= $ && 1 <= $ ) + { auto s = da[$ .. $]; } // 0 0 ($ <= $ && $ <= $ ) + { auto s = da[0 .. $/two]; } // 0 1 ($/2 <= $ ) + { auto s = da[$/two .. $]; } // 0 0 ($ <= $ && $/2 <= $ ) + { auto s = da[$/five .. $/two]; } // 0 0 ($/2 <= $ && $/5 <= $/2) + + { auto s = sa[lb .. ub]; } // 0 0 (ub <= 10 && lb <= ub ) + { auto s = sa[1 .. ub]; } // 0 0 (ub <= 10 && 1 <= ub ) + { auto s = sa[lb .. 10]; } // 1 0 ( lb <= 10 ) + { auto s = sa[1 .. ub%5]; } // 1 0 ( 1 <= ub%5) + + { auto s = sa[lb .. ub]; } // 0 0 (ub <= 10 && lb <= ub ) + { auto s = sa[0 .. ub]; } // 0 1 (ub <= 10 ) + { auto s = sa[lb .. 10]; } // 1 0 ( lb <= 10 ) + { auto s = sa[0 .. ub%5]; } // 1 1 NULL + + { auto s = sa[0 .. 0]; } // 1 1 NULL + { auto s = sa[0 .. $]; } // 1 1 NULL + { auto s = sa[1 .. $]; } // 1 1 NULL + { auto s = sa[$ .. $]; } // 1 1 NULL + { auto s = sa[0 .. $/two]; } // 1 1 NULL + { auto s = sa[$/two .. $]; } // 1 1 NULL + { auto s = sa[$/five .. $/two]; } // 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) + { auto s = p[0 .. ub]; } // 1 1 NULL + { auto s = p[lb .. ub]; } // 1 0 (lb <= ub ) + { auto s = p[0 .. ub%5]; } // 1 1 NULL + { auto s = p[1 .. ub%5]; } // 1 0 (1 <= ub%5) + { auto s = p[0 .. 0]; } // 1 1 NULL } /******************************************/