Bug 5996 – ICE(expression.c) CTFE of erroneous auto return function
Status
RESOLVED
Resolution
FIXED
Severity
normal
Priority
P2
Component
dmd
Product
D
Version
D2
Platform
x86
OS
Windows
Creation time
2011-05-13T13:10:00Z
Last change time
2012-11-07T12:52:21Z
Keywords
CTFE, ice
Assigned to
nobody
Creator
bearophile_hugs
Comments
Comment #0 by bearophile_hugs — 2011-05-13T13:10:26Z
This is wrong D2 code, because min() is not defined:
auto foo(int n) {
uint two = 2, three = 3, five = 5;
auto h = new typeof(two)[n];
h[0] = 1;
auto x2 = two, x3 = three, x5 = five;
int i, j, k;
for (int w = 1; w < n; w++) {
auto el = h[w] = min(x2, x3, x5);
if (x2 == el) x2 = two * h[++i];
if (x3 == el) x3 = three * h[++j];
if (x5 == el) x5 = five * h[++k];
}
return h[$ - 1];
}
enum uint h = foo(1691);
static assert(h == 2123366400);
void main() {}
DMD 2.053beta prints:
Assertion failure: '0' on line 1601 in file 'expression.c'
---------------------
If I have remove the three if() lines:
auto foo(int n) {
uint two = 2, three = 3, five = 5;
auto h = new typeof(two)[n];
h[0] = 1;
auto x2 = two, x3 = three, x5 = five;
int i, j, k;
for (int w = 1; w < n; w++) {
auto el = h[w] = min(x2, x3, x5);
}
return h[$ - 1];
}
enum uint h = foo(1691);
static assert(h == 2123366400);
void main() {}
Now the error messages are:
Error: array index 4294967295 is out of bounds [][0 .. 0]
test2.d(10): Error: h[__dollar - 1u] cannot be interpreted at compile time
test2.d(12): Error: cannot evaluate foo(1691) at compile time
test2.d(12): Error: cannot evaluate foo(1691) at compile time
test2.d(13): Error: static assert (foo(1691) == 2123366400u) is not evaluatable at compile time
Note an error message without line number too.
DMD 2.052 instead prints:
test2.d(4): Error: array index 0 is out of bounds [][0..0]
test2.d(12): Error: cannot evaluate foo(1691) at compile time
test2.d(12): Error: cannot evaluate foo(1691) at compile time
test2.d(12): Error: cannot evaluate foo(1691) at compile time
test2.d(13): Error: static assert (foo(1691) == 2123366400u) is not evaluatable at compile time
---------------------
If I remove "auto" as return type and put a "uint":
uint foo(int n) {
uint two = 2, three = 3, five = 5;
auto h = new typeof(two)[n];
h[0] = 1;
auto x2 = two, x3 = three, x5 = five;
int i, j, k;
for (int w = 1; w < n; w++) {
auto el = h[w] = min(x2, x3, x5);
}
return h[$ - 1];
}
enum uint h = foo(1691);
static assert(h == 2123366400);
void main() {}
Finally the error messages are correct:
test3.d(8): Error: undefined identifier min, did you mean function main?
test3.d(12): Error: cannot evaluate foo(1691) at compile time
--------------------------
Now adding the missing min() fixes the problem, and it works with auto return type too:
T min(T)(T a, T b, T c) {
return (a > b) ? ((b > c) ? c : b) : ((a > c) ? c : a);
}
auto foo(int n) {
uint two = 2, three = 3, five = 5;
auto h = new typeof(two)[n];
h[0] = 1;
auto x2 = two, x3 = three, x5 = five;
int i, j, k;
for (int w = 1; w < n; w++) {
auto el = h[w] = min(x2, x3, x5);
if (x2 == el) x2 = two * h[++i];
if (x3 == el) x3 = three * h[++j];
if (x5 == el) x5 = five * h[++k];
}
return h[$ - 1];
}
enum uint h = foo(1691);
static assert(h == 2125764000);
void main() {}
Comment #1 by clugdbug — 2011-07-05T17:12:13Z
Reduced test case:
---------
auto bug5996() {
if (anyOldGarbage) {}
return 2;
}
enum uint h5996 = bug5996();
static assert(h5996 == 2);
Comment #2 by bearophile_hugs — 2011-07-06T03:20:22Z
(In reply to comment #1)
> Reduced test case:
My second example shows an error message with missing line number:
Error: array index 4294967295 is out of bounds [][0 .. 0]
I have reduced it to this, I think it's better to fix this before fixing your reduced test case:
auto foo(int n) {
auto h = new typeof(something)[n];
return h[$];
}
enum uint f = foo(1);
void main() {}
Comment #3 by clugdbug — 2011-07-06T04:21:21Z
(In reply to comment #2)
> (In reply to comment #1)
> > Reduced test case:
>
> My second example shows an error message with missing line number:
> Error: array index 4294967295 is out of bounds [][0 .. 0]
>
> I have reduced it to this, I think it's better to fix this before fixing your
> reduced test case:
>
> auto foo(int n) {
> auto h = new typeof(something)[n];
> return h[$];
> }
> enum uint f = foo(1);
> void main() {}
It's a problem with the gagging system. It actually shouldn't get as far as CTFE, so the out-of-bounds error shouldn't happen.
Comment #4 by github-bugzilla — 2012-11-07T12:46:18Z