Skip to content

Commit

Permalink
Merge pull request #3485 from 9rnsr/fix12606
Browse files Browse the repository at this point in the history
Issue 12606 - Mismatch of known array length during dynamic => static array assignment should emit better diagnostics
  • Loading branch information
AndrejMitrovic committed Apr 25, 2014
2 parents 0f9ff61 + 4d9ea94 commit 3a50fa4
Show file tree
Hide file tree
Showing 5 changed files with 130 additions and 32 deletions.
6 changes: 6 additions & 0 deletions src/cast.c
Expand Up @@ -1234,6 +1234,12 @@ Type *toStaticArrayType(SliceExp *e)
return e->type->toBasetype()->nextOf()->sarrayOf(len);
}
}
else
{
Type *t1b = e->e1->type->toBasetype();
if (t1b->ty == Tsarray)
return t1b;
}
return NULL;
}

Expand Down
63 changes: 33 additions & 30 deletions src/expression.c
Expand Up @@ -11271,12 +11271,22 @@ Expression *AssignExp::semantic(Scope *sc)
}
else
{
if (e2x->op == TOKarrayliteral)
if (e2x->implicitConvTo(t1->nextOf()->arrayOf()) > MATCHnomatch)
{
ArrayLiteralExp *ale = (ArrayLiteralExp *)e2x;
uinteger_t dim1 = ((TypeSArray *)t1)->dim->toInteger();
uinteger_t dim2 = ale->elements ? ale->elements->dim : 0;
if (e2x->implicitConvTo(t1->nextOf()->sarrayOf(dim2)))
uinteger_t dim2 = dim1;
if (e2x->op == TOKarrayliteral)
{
ArrayLiteralExp *ale = (ArrayLiteralExp *)e2x;
dim2 = ale->elements ? ale->elements->dim : 0;
}
else if (e2x->op == TOKslice)
{
Type *tx = toStaticArrayType((SliceExp *)e2x);
if (tx)
dim2 = ((TypeSArray *)tx)->dim->toInteger();
}
if (dim1 != dim2)
{
error("mismatched array lengths, %d and %d", (int)dim1, (int)dim2);
return new ErrorExp();
Expand Down Expand Up @@ -11384,45 +11394,38 @@ Expression *AssignExp::semantic(Scope *sc)
t2->nextOf()->implicitConvTo(t1->nextOf()))
{
// Check element-wise assignment.
SliceExp *se1 = (SliceExp *)e1;
Type *tx1 = se1->e1->type->toBasetype();

/* If assigned elements number is known at compile time,
* check the mismatch.
*/
if (se1->lwr == NULL && tx1->ty == Tsarray)
{
Type *tx2 = t2;
if (e2->op == TOKslice && ((SliceExp *)e2)->lwr == NULL)
tx2 = ((SliceExp *)e2)->e1->type->toBasetype();
uinteger_t dim1, dim2;
if (e2->op == TOKarrayliteral)
{
dim2 = ((ArrayLiteralExp *)e2)->elements->dim;
goto Lsa;
}
if (tx2->ty == Tsarray)
{
// sa1[] = sa2[];
// sa1[] = sa2;
// sa1[] = [ ... ];
dim2 = ((TypeSArray *)tx2)->dim->toInteger();
Lsa:
dim1 = ((TypeSArray *)tx1)->dim->toInteger();
if (dim1 != dim2)
{
error("mismatched array lengths, %d and %d", (int)dim1, (int)dim2);
return new ErrorExp();
}
SliceExp *se1 = (SliceExp *)e1;
TypeSArray *tsa1 = (TypeSArray *)toStaticArrayType(se1);
TypeSArray *tsa2 = NULL;
if (e2->op == TOKarrayliteral)
tsa2 = (TypeSArray *)t2->nextOf()->sarrayOf(((ArrayLiteralExp *)e2)->elements->dim);
else if (e2->op == TOKslice)
tsa2 = (TypeSArray *)toStaticArrayType((SliceExp *)e2);
else if (t2->ty == Tsarray)
tsa2 = (TypeSArray *)t2;
if (tsa1 && tsa2)
{
uinteger_t dim1 = tsa1->dim->toInteger();
uinteger_t dim2 = tsa2->dim->toInteger();
if (dim1 != dim2)
{
error("mismatched array lengths, %d and %d", (int)dim1, (int)dim2);
return new ErrorExp();
}
}

if (op != TOKblit &&
(e2->op == TOKslice && ((UnaExp *)e2)->e1->isLvalue() ||
e2->op == TOKcast && ((UnaExp *)e2)->e1->isLvalue() ||
e2->op != TOKslice && e2->isLvalue()))
{
e1->checkPostblit(sc, t1->nextOf());
}

if (0 && global.params.warnings && !global.gag && op == TOKassign &&
e2->op != TOKslice && e2->op != TOKassign &&
e2->op != TOKarrayliteral && e2->op != TOKstring &&
Expand Down
33 changes: 32 additions & 1 deletion src/init.c
Expand Up @@ -902,7 +902,38 @@ Initializer *ExpInitializer::semantic(Scope *sc, Type *t, NeedInterpret needInte
t = tb->nextOf();
}

exp = exp->implicitCastTo(sc, t);
if (exp->implicitConvTo(t))
{
exp = exp->implicitCastTo(sc, t);
}
else
{
// Look for mismatch of compile-time known length to emit
// better diagnostic message, as same as AssignExp::semantic.
if (tb->ty == Tsarray &&
exp->implicitConvTo(tb->nextOf()->arrayOf()) > MATCHnomatch)
{
uinteger_t dim1 = ((TypeSArray *)tb)->dim->toInteger();
uinteger_t dim2 = dim1;
if (exp->op == TOKarrayliteral)
{
ArrayLiteralExp *ale = (ArrayLiteralExp *)exp;
dim2 = ale->elements ? ale->elements->dim : 0;
}
else if (exp->op == TOKslice)
{
Type *tx = toStaticArrayType((SliceExp *)exp);
if (tx)
dim2 = ((TypeSArray *)tx)->dim->toInteger();
}
if (dim1 != dim2)
{
exp->error("mismatched array lengths, %d and %d", (int)dim1, (int)dim2);
exp = new ErrorExp();
}
}
exp = exp->implicitCastTo(sc, t);
}
if (exp->op == TOKerror)
return this;
L1:
Expand Down
57 changes: 57 additions & 0 deletions test/fail_compilation/fail12604.d
Expand Up @@ -20,3 +20,60 @@ void main()
short[1] c = [65536];
short[1] d = [65536,2,3];
}

/*
TEST_OUTPUT:
---
fail_compilation/fail12604.d(39): Error: mismatched array lengths, 2 and 3
fail_compilation/fail12604.d(40): Error: mismatched array lengths, 2 and 3
fail_compilation/fail12604.d(41): Error: mismatched array lengths, 2 and 3
fail_compilation/fail12604.d(42): Error: mismatched array lengths, 2 and 3
fail_compilation/fail12604.d(43): Error: mismatched array lengths, 2 and 3
fail_compilation/fail12604.d(44): Error: mismatched array lengths, 2 and 3
fail_compilation/fail12604.d(45): Error: mismatched array lengths, 2 and 3
fail_compilation/fail12604.d(46): Error: mismatched array lengths, 2 and 3
---
*/
void test12606a() // AssignExp::semantic
{
uint[2] a1 = [1, 2, 3][];
ushort[2] a2 = [1, 2, 3][];
uint[2] a3 = [1, 2, 3][0 .. 3];
ushort[2] a4 = [1, 2, 3][0 .. 3];
a1 = [1, 2, 3][];
a2 = [1, 2, 3][];
a3 = [1, 2, 3][0 .. 3];
a4 = [1, 2, 3][0 .. 3];
}

/*
TEST_OUTPUT:
---
fail_compilation/fail12604.d(60): Error: mismatched array lengths, 2 and 3
fail_compilation/fail12604.d(61): Error: mismatched array lengths, 2 and 3
fail_compilation/fail12604.d(62): Error: mismatched array lengths, 2 and 3
fail_compilation/fail12604.d(63): Error: mismatched array lengths, 2 and 3
---
*/
void test12606b() // ExpInitializer::semantic
{
static uint[2] a1 = [1, 2, 3][];
static uint[2] a2 = [1, 2, 3][0 .. 3];
static ushort[2] a3 = [1, 2, 3][];
static ushort[2] a4 = [1, 2, 3][0 .. 3];
}

/*
TEST_OUTPUT:
---
fail_compilation/fail12604.d(77): Error: mismatched array lengths, 4 and 3
fail_compilation/fail12604.d(78): Error: mismatched array lengths, 4 and 3
---
*/
void testc()
{
int[4] sa1;
int[3] sa2;
sa1[0..4] = [1,2,3];
sa1[0..4] = sa2;
}
3 changes: 2 additions & 1 deletion test/runnable/interpret.d
Expand Up @@ -2055,7 +2055,8 @@ int badfoo6()
int badfoo7()
{
S[] b = [S(7), S(15), S(56), S(12), S(67)];
b[1..4] = [S(17), S(4)]; // slice mismatch in dynamic array
S[] c = [S(17), S(4)];
b[1..4] = c[]; // slice mismatch in dynamic array
return 1;
}

Expand Down

0 comments on commit 3a50fa4

Please sign in to comment.