Bug 3716 – Regression (2.037) with multi dimensional array literals

Status
RESOLVED
Resolution
FIXED
Severity
regression
Priority
P2
Component
dmd
Product
D
Version
D2
Platform
Other
OS
All
Creation time
2010-01-17T11:30:00Z
Last change time
2010-06-27T18:35:14Z
Keywords
patch, rejects-valid
Assigned to
nobody
Creator
aarti

Comments

Comment #0 by aarti — 2010-01-17T11:30:37Z
void main(char[][] args) { int[][][] input_int1; //input_int1 = [[[2,3],[4,5],[6,7]], [[]], [[0,-5],[-8,1]]]; //Error //input_int1 = [[[2,3],[4,5],[6,7]], [[1]], [[0,-5],[-8,1]]]; //Error input_int1 = [[[2,3],[4,5],[6,7]], [[1,1]], [[0,-5],[-8,1]]]; //Ok int[] input_int2 = [1, 2, 3, 4]; assert(input_int2 == [1, 2, 3, 4]); //Ok int[][] input_int3 = [[1,2], [3,4]]; //assert(input_int3 == [[1,2], [3,4]]); //Error } Above code used to work with DMD 1 compiler.
Comment #1 by clugdbug — 2010-01-22T13:39:10Z
This also worked in DMD2.035. Haven't checked intermediate versions. The regression was probably introduced in 2.037.
Comment #2 by ellery-newcomer — 2010-02-25T20:45:10Z
looks like it parses an expression rather than an initializer. this should fix it: --- parse.c (revision 400) +++ parse.c (working copy) @@ -3248,6 +3248,7 @@ { t = peek(t); if (t->value != TOKsemicolon && t->value != TOKcomma && + t->value != TOKrbracket && t->value != TOKrcurly) goto Lexpression; break;
Comment #3 by ellery-newcomer — 2010-02-26T08:15:39Z
Oop. Never mind. I was looking at bug 3854 and assumed they were the same. They aren't.
Comment #4 by clugdbug — 2010-06-24T00:00:18Z
This was caused by the change in 2.037: "The type inferred from an ArrayLiteral is now a dynamic array, not a static one." typeMerge() in cast.c, needed to be modified in response, since [[]] is now of type void[][] instead of void[][0] I've patched this with a more general test for void array literals. I'm not terribly happy with the patch, the dimensionality check seems unnecessarily complicated. // TEST CASES void bug3716() { auto k1 = true ? [1,2] : []; // OK auto k2 = true ? [[1,2]] : [[]]; auto k3 = true ? [] : [[1,2]]; auto k4 = true ? [[[]]] : [[[1,2]]]; auto k5 = true ? [[[1,2]]] : [[[]]]; auto k6 = true ? [] : [[[]]]; static assert(!is(typeof(true ? [[[]]] : [[1,2]]))); // Must fail } ---------- Index: cast.c =================================================================== --- cast.c (revision 557) +++ cast.c (working copy) @@ -1499,6 +1499,30 @@ } /************************************** + * Return true if e is an empty array literal with dimensionality + * equal to or less than type of other array. + * [], [[]], [[[]]], etc. + */ +bool isVoidArrayLiteral(Expression *e, Type *other) +{ + while (e->op == TOKarrayliteral && e->type->ty == Tarray + && (((ArrayLiteralExp *)e)->elements->dim == 1)) + { + e = (Expression *)((ArrayLiteralExp *)e)->elements->data[0]; + if (other->ty == Tsarray || other->ty == Tarray) + other = other->nextOf(); + else + return false; + } + if (other->ty != Tsarray && other->ty != Tarray) + return false; + Type *t = e->type; + return (e->op == TOKarrayliteral && t->ty == Tarray && + t->nextOf()->ty == Tvoid && + ((ArrayLiteralExp *)e)->elements->dim == 0); +} + +/************************************** * Combine types. * Output: * *pt merged type, if *pt is not NULL @@ -1616,7 +1640,7 @@ else if ((t1->ty == Tsarray || t1->ty == Tarray) && (e2->op == TOKnull && t2->ty == Tpointer && t2->nextOf()->ty == Tvoid || e2->op == TOKarrayliteral && t2->ty == Tsarray && t2->nextOf()->ty == Tvoid && ((TypeSArray *)t2)->dim->toInteger() == 0 || - e2->op == TOKarrayliteral && t2->ty == Tarray && t2->nextOf()->ty == Tvoid && ((ArrayLiteralExp *)e2)->elements->dim == 0) + isVoidArrayLiteral(e2, t1)) ) { /* (T[n] op void*) => T[] * (T[] op void*) => T[] @@ -1630,7 +1654,7 @@ else if ((t2->ty == Tsarray || t2->ty == Tarray) && (e1->op == TOKnull && t1->ty == Tpointer && t1->nextOf()->ty == Tvoid || e1->op == TOKarrayliteral && t1->ty == Tsarray && t1->nextOf()->ty == Tvoid && ((TypeSArray *)t1)->dim->toInteger() == 0 || - e1->op == TOKarrayliteral && t1->ty == Tarray && t1->nextOf()->ty == Tvoid && ((ArrayLiteralExp *)e1)->elements->dim == 0) + isVoidArrayLiteral(e1, t2)) ) { /* (void* op T[n]) => T[] * (void* op T[]) => T[]
Comment #5 by bugzilla — 2010-06-27T18:35:14Z