Skip to content

Commit

Permalink
Merge pull request #2672 from 9rnsr/fix10684
Browse files Browse the repository at this point in the history
[REG2.063][enh] Issue 10684 - Refused array op with array literal
  • Loading branch information
WalterBright committed Oct 18, 2013
2 parents e7022d8 + f78a770 commit f39979f
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 0 deletions.
33 changes: 33 additions & 0 deletions src/arrayop.c
Expand Up @@ -309,6 +309,13 @@ bool isArrayOpValid(Expression *e)
{
if (e->op == TOKslice)
return true;
if (e->op == TOKarrayliteral)
{
Type *t = e->type->toBasetype();
while (t->ty == Tarray || t->ty == Tsarray)
t = t->nextOf()->toBasetype();
return (t->ty != Tvoid);
}
Type *tb = e->type->toBasetype();

if ( (tb->ty == Tarray) || (tb->ty == Tsarray) )
Expand Down Expand Up @@ -451,6 +458,12 @@ void CastExp::buildArrayIdent(OutBuffer *buf, Expressions *arguments)
Expression::buildArrayIdent(buf, arguments);
}

void ArrayLiteralExp::buildArrayIdent(OutBuffer *buf, Expressions *arguments)
{
buf->writestring("Slice");
arguments->shift(this);
}

void SliceExp::buildArrayIdent(OutBuffer *buf, Expressions *arguments)
{
buf->writestring("Slice");
Expand Down Expand Up @@ -558,6 +571,19 @@ Expression *CastExp::buildArrayLoop(Parameters *fparams)
return Expression::buildArrayLoop(fparams);
}

Expression *ArrayLiteralExp::buildArrayLoop(Parameters *fparams)
{
Identifier *id = Identifier::generateId("p", fparams->dim);
Parameter *param = new Parameter(STCconst, type, id, NULL);
fparams->shift(param);
Expression *e = new IdentifierExp(Loc(), id);
Expressions *arguments = new Expressions();
Expression *index = new IdentifierExp(Loc(), Id::p);
arguments->push(index);
e = new ArrayExp(Loc(), e, arguments);
return e;
}

Expression *SliceExp::buildArrayLoop(Parameters *fparams)
{
Identifier *id = Identifier::generateId("p", fparams->dim);
Expand Down Expand Up @@ -671,6 +697,13 @@ int Expression::isArrayOperand()
//printf("Expression::isArrayOperand() %s\n", toChars());
if (op == TOKslice)
return 1;
if (op == TOKarrayliteral)
{
Type *t = type->toBasetype();
while (t->ty == Tarray || t->ty == Tsarray)
t = t->nextOf()->toBasetype();
return (t->ty != Tvoid);
}
if (type->toBasetype()->ty == Tarray)
{
switch (op)
Expand Down
3 changes: 3 additions & 0 deletions src/expression.h
Expand Up @@ -486,6 +486,9 @@ class ArrayLiteralExp : public Expression
Expression *inferType(Type *t, int flag = 0, Scope *sc = NULL, TemplateParameters *tparams = NULL);
dt_t **toDt(dt_t **pdt);

void buildArrayIdent(OutBuffer *buf, Expressions *arguments);
Expression *buildArrayLoop(Parameters *fparams);

Expression *doInline(InlineDoState *ids);
Expression *inlineScan(InlineScanState *iss);
};
Expand Down
34 changes: 34 additions & 0 deletions test/runnable/arrayop.d
Expand Up @@ -664,6 +664,38 @@ void test10433()
foo(v, v);
}

/************************************************************************/
// 10684

void test10684a()
{
int[] a = [0, 0];
a[] += [10, 20][];
}

void test10684b()
{
int[] a = [1, 2, 3];
int[] b = [4, 5, 6];

// Allow array literal as the operand of array oeration
a[] += [1, 2, 3];
assert(a == [2, 4, 6]);

a[] *= b[] + [1, 1, 1];
assert(a == [2*(4+1), 4*(5+1), 6*(6+1)]);

a[] = [9, 8, 7] - [1, 2, 3];
assert(a == [8, 6, 4]);

a[] = [2, 4, 6] / 2;
assert(a == [1,2,3]);

// Disallow: [1,2,3] is not an lvalue
static assert(!__traits(compiles, { [1,2,3] = a[] * 2; }));
static assert(!__traits(compiles, { [1,2,3] += a[] * b[]; }));
}

/************************************************************************/

int main()
Expand All @@ -678,6 +710,8 @@ int main()
test8651();
test9656();
test10433();
test10684a();
test10684b();

printf("Success\n");
return 0;
Expand Down

0 comments on commit f39979f

Please sign in to comment.