-
-
Notifications
You must be signed in to change notification settings - Fork 699
Set length variable for slice and index expressions during semantic #7682
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -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 | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Apparently this caching doesn't work.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You mean coverage wise? That's probably because semantic only calls it once. Doesn't make the safeguards any less correct. |
||
| 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()); | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -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 ($ <= $ ) | ||
|
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. These two can be improved in a latter PR by using the check for |
||
| { 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 | ||
| } | ||
|
|
||
| /******************************************/ | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like this doesn't work.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Control flow has likely moved this to the other function. Should still be kept around though, as it's a utility function.