Showing with 84 additions and 60 deletions.
  1. +73 −60 src/dinterpret.d
  2. +11 −0 test/compilable/interpret3.d
133 changes: 73 additions & 60 deletions src/dinterpret.d
Original file line number Diff line number Diff line change
Expand Up @@ -2518,13 +2518,15 @@ public:
}
if (exceptionOrCant(interpret(e.e0, istate, ctfeNeedNothing)))
return;
Expressions* expsx = null;
for (size_t i = 0; i < e.exps.dim; i++)

auto expsx = e.exps;
for (size_t i = 0; i < expsx.dim; i++)
{
Expression exp = (*e.exps)[i];
Expression exp = (*expsx)[i];
Expression ex = interpret(exp, istate);
if (exceptionOrCant(ex))
return;

// A tuple of assignments can contain void (Bug 5676).
if (goal == ctfeNeedNothing)
continue;
Expand All @@ -2533,33 +2535,29 @@ public:
e.error("CTFE internal error: void element %s in tuple", exp.toChars());
assert(0);
}

/* If any changes, do Copy On Write
*/
if (ex != exp)
if (ex !is exp)
{
if (!expsx)
if (expsx is e.exps)
{
expsx = new Expressions();
expsx = e.exps.copy();
++CtfeStatus.numArrayAllocs;
expsx.setDim(e.exps.dim);
for (size_t j = 0; j < i; j++)
{
(*expsx)[j] = (*e.exps)[j];
}
}
(*expsx)[i] = ex;
}
}
if (expsx)

if (expsx !is e.exps)
{
expandTuples(expsx);
auto te = new TupleExp(e.loc, expsx);
expandTuples(te.exps);
te.type = new TypeTuple(te.exps);
result = te;
return;
}
result = e;
return;
else
result = e;
}

override void visit(ArrayLiteralExp e)
Expand Down Expand Up @@ -2654,8 +2652,6 @@ public:

override void visit(AssocArrayLiteralExp e)
{
Expressions* keysx = e.keys;
Expressions* valuesx = e.values;
static if (LOG)
{
printf("%s AssocArrayLiteralExp::interpret() %s\n", e.loc.toChars(), e.toChars());
Expand All @@ -2665,76 +2661,93 @@ public:
result = e;
return;
}
for (size_t i = 0; i < e.keys.dim; i++)

auto keysx = e.keys;
auto valuesx = e.values;
for (size_t i = 0; i < keysx.dim; i++)
{
Expression ekey = (*e.keys)[i];
Expression evalue = (*e.values)[i];
Expression ex = interpret(ekey, istate);
if (exceptionOrCant(ex))
auto ekey = (*keysx)[i];
auto evalue = (*valuesx)[i];

auto ek = interpret(ekey, istate);
if (exceptionOrCant(ek))
return;
/* If any changes, do Copy On Write
*/
if (ex != ekey)
{
if (keysx == e.keys)
keysx = cast(Expressions*)e.keys.copy();
(*keysx)[i] = ex;
}
ex = interpret(evalue, istate);
if (exceptionOrCant(ex))
auto ev = interpret(evalue, istate);
if (exceptionOrCant(ev))
return;

/* If any changes, do Copy On Write
*/
if (ex != evalue)
if (ek !is ekey ||
ev !is evalue)
{
if (valuesx == e.values)
valuesx = cast(Expressions*)e.values.copy();
(*valuesx)[i] = ex;
if (keysx is e.keys)
{
keysx = e.keys.copy();
++CtfeStatus.numArrayAllocs;
}
if (valuesx is e.values)
{
valuesx = e.values.copy();
++CtfeStatus.numArrayAllocs;
}
(*keysx)[i] = ek;
(*valuesx)[i] = ev;
}
}
if (keysx != e.keys)
if (keysx !is e.keys)
expandTuples(keysx);
if (valuesx != e.values)
if (valuesx !is e.values)
expandTuples(valuesx);
if (keysx.dim != valuesx.dim)
{
e.error("CTFE internal error: invalid AA");
result = CTFEExp.cantexp;
return;
}

/* Remove duplicate keys
*/
for (size_t i = 1; i < keysx.dim; i++)
{
Expression ekey = (*keysx)[i - 1];
auto ekey = (*keysx)[i - 1];
for (size_t j = i; j < keysx.dim; j++)
{
Expression ekey2 = (*keysx)[j];
int eq = ctfeEqual(e.loc, TOKequal, ekey, ekey2);
if (eq) // if a match
auto ekey2 = (*keysx)[j];
if (!ctfeEqual(e.loc, TOKequal, ekey, ekey2))
continue;

// Remove ekey
if (keysx is e.keys)
{
// Remove ekey
if (keysx == e.keys)
keysx = cast(Expressions*)e.keys.copy();
if (valuesx == e.values)
valuesx = cast(Expressions*)e.values.copy();
keysx.remove(i - 1);
valuesx.remove(i - 1);
i -= 1; // redo the i'th iteration
break;
keysx = e.keys.copy();
++CtfeStatus.numArrayAllocs;
}
if (valuesx is e.values)
{
valuesx = e.values.copy();
++CtfeStatus.numArrayAllocs;
}
keysx.remove(i - 1);
valuesx.remove(i - 1);

i -= 1; // redo the i'th iteration
break;
}
}
if (keysx != e.keys || valuesx != e.values)

if (keysx !is e.keys ||
valuesx !is e.values)
{
AssocArrayLiteralExp ae;
ae = new AssocArrayLiteralExp(e.loc, keysx, valuesx);
ae.type = e.type;
ae.ownedByCtfe = OWNEDctfe;
result = ae;
return;
assert(keysx !is e.keys &&
valuesx !is e.values);
auto aae = new AssocArrayLiteralExp(e.loc, keysx, valuesx);
aae.type = e.type;
aae.ownedByCtfe = OWNEDctfe;
result = aae;
}
result = copyLiteral(e).copy();
else
result = copyLiteral(e).copy();
}

override void visit(StructLiteralExp e)
Expand Down
11 changes: 11 additions & 0 deletions test/compilable/interpret3.d
Original file line number Diff line number Diff line change
Expand Up @@ -7653,3 +7653,14 @@ auto structInCaseScope()
}

static assert(!structInCaseScope());

/**************************************************
15233 - ICE in TupleExp, Copy On Write bug
**************************************************/

alias TT15233(stuff ...) = stuff;

struct Tok15233 {}
enum tup15233 = TT15233!(Tok15233(), "foo");
static assert(tup15233[0] == Tok15233());
static assert(tup15233[1] == "foo");