D issues are now tracked on GitHub. This Bugzilla instance remains as a read-only archive.
Issue 3716 - Regression (2.037) with multi dimensional array literals
Summary: Regression (2.037) with multi dimensional array literals
Status: RESOLVED FIXED
Alias: None
Product: D
Classification: Unclassified
Component: dmd (show other issues)
Version: D2
Hardware: Other All
: P2 regression
Assignee: No Owner
URL:
Keywords: patch, rejects-valid
Depends on:
Blocks:
 
Reported: 2010-01-17 11:30 UTC by Marcin Kuszczak
Modified: 2010-06-27 18:35 UTC (History)
3 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this issue.
Description Marcin Kuszczak 2010-01-17 11:30:37 UTC
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 Don 2010-01-22 13:39:10 UTC
This also worked in DMD2.035. Haven't checked intermediate versions. The regression was probably introduced in 2.037.
Comment 2 Ellery Newcomer 2010-02-25 20:45:10 UTC
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 Ellery Newcomer 2010-02-26 08:15:39 UTC
Oop. Never mind. I was looking at bug 3854 and assumed they were the same. They aren't.
Comment 4 Don 2010-06-24 00:00:18 UTC
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 Walter Bright 2010-06-27 18:35:14 UTC
http://www.dsource.org/projects/dmd/changeset/562