Skip to content

Commit

Permalink
Merge pull request #3488 from 9rnsr/fix9245
Browse files Browse the repository at this point in the history
Issue 9245 - [CTFE] postblit not called on static array initialization
  • Loading branch information
WalterBright committed Apr 24, 2014
2 parents 90abd4c + 3910d5c commit 6de3bd5
Show file tree
Hide file tree
Showing 3 changed files with 128 additions and 1 deletion.
2 changes: 2 additions & 0 deletions src/ctfeexpr.c
Expand Up @@ -1752,6 +1752,8 @@ void assignInPlace(Expression *dest, Expression *src)
assert(dest->op == src->op);
oldelems = ((StructLiteralExp *)dest)->elements;
newelems = ((StructLiteralExp *)src)->elements;
if (((StructLiteralExp *)dest)->sd->isNested() && oldelems->dim == newelems->dim - 1)
oldelems->push(NULL);
}
else if (dest->op == TOKarrayliteral && src->op==TOKarrayliteral)
{
Expand Down
61 changes: 60 additions & 1 deletion src/interpret.c
Expand Up @@ -259,6 +259,7 @@ void printCtfePerformanceStats()
VarDeclaration *findParentVar(Expression *e);
Expression *evaluateIfBuiltin(InterState *istate, Loc loc,
FuncDeclaration *fd, Expressions *arguments, Expression *pthis);
Expression *evaluatePostblits(InterState *istate, ArrayLiteralExp *ale, size_t lwr, size_t upr);
Expression *scrubReturnValue(Loc loc, Expression *e);


Expand Down Expand Up @@ -3467,7 +3468,7 @@ class Interpreter : public Visitor
wantRef = false;
}
}
if (isBlockAssignment && (e->e2->type->toBasetype()->ty == Tarray || e->e2->type->toBasetype()->ty == Tsarray))
if (isBlockAssignment && (e->e2->type->toBasetype()->ty == Tarray))
{
wantRef = true;
}
Expand Down Expand Up @@ -3968,6 +3969,13 @@ class Interpreter : public Visitor
else
{
TY tyE1 = e1->type->toBasetype()->ty;
if (tyE1 == Tsarray && newval->op == TOKslice)
{
// Newly set value is non-ref static array,
// so making new ArrayLiteralExp is legitimate.
newval = resolveSlice(newval);
((ArrayLiteralExp *)newval)->ownedByCtfe = true;
}
if (tyE1 == Tarray || tyE1 == Taarray)
{
// arr op= arr
Expand All @@ -3976,6 +3984,16 @@ class Interpreter : public Visitor
else
{
setValue(v, newval);
if (tyE1 == Tsarray && e->e2->isLvalue())
{
assert(newval->op == TOKarrayliteral);
ArrayLiteralExp *ale = (ArrayLiteralExp *)newval;
if (Expression *x = evaluatePostblits(istate, ale, 0, ale->elements->dim))
{
result = x;
return;
}
}
}
}
}
Expand Down Expand Up @@ -4509,6 +4527,12 @@ class Interpreter : public Visitor
{
(*oldelems)[(size_t)(j + firstIndex)] = paintTypeOntoLiteral(elemtype, (*newelems)[j]);
}
if (originalExp->e2->isLvalue())
{
Expression *x = evaluatePostblits(istate, existingAE, 0, oldelems->dim);
if (exceptionOrCantInterpret(x))
return x;
}
return newval;
}
else if (newval->op == TOKstring && existingSE)
Expand Down Expand Up @@ -4587,6 +4611,12 @@ class Interpreter : public Visitor
assignInPlace((*existingAE->elements)[(size_t)(j+firstIndex)], newval);
}
}
if (!wantRef && !cow && originalExp->e2->isLvalue())
{
Expression *x = evaluatePostblits(istate, existingAE, firstIndex, firstIndex+upperbound-lowerbound);
if (exceptionOrCantInterpret(x))
return x;
}
if (goal == ctfeNeedNothing)
return NULL; // avoid creating an unused literal
SliceExp *retslice = new SliceExp(loc, existingAE,
Expand Down Expand Up @@ -7034,6 +7064,35 @@ Expression *evaluateIfBuiltin(InterState *istate, Loc loc,
return e;
}

Expression *evaluatePostblits(InterState *istate, ArrayLiteralExp *ale, size_t lwr, size_t upr)
{
Type *telem = ale->type->nextOf()->baseElemOf();
if (telem->ty != Tstruct)
return NULL;
StructDeclaration *sd = ((TypeStruct *)telem)->sym;
if (sd->postblit)
{
for (size_t i = lwr; i < upr; i++)
{
Expression *e = (*ale->elements)[i];
if (e->op == TOKarrayliteral)
{
ArrayLiteralExp *alex = (ArrayLiteralExp *)e;
e = evaluatePostblits(istate, alex, 0, alex->elements->dim);
}
else
{
// e.__postblit()
assert(e->op == TOKstructliteral);
e = interpret(sd->postblit, istate, NULL, e);
}
if (exceptionOrCantInterpret(e))
return e;
}
}
return NULL;
}

/*************************** CTFE Sanity Checks ***************************/

/* Setter functions for CTFE variable values.
Expand Down
66 changes: 66 additions & 0 deletions test/compilable/interpret3.d
Expand Up @@ -5989,6 +5989,72 @@ bool test10929()
};
static assert(test10929());

/**************************************************
9245 - support postblit call on array assignments
**************************************************/

bool test9245()
{
int postblits = 0;
struct S
{
this(this)
{
++postblits;
}
}

S s;
S[2] a;
assert(postblits == 0);

{
S[2] arr = s;
assert(postblits == 2);
arr[] = s;
assert(postblits == 4);
postblits = 0;

S[2] arr2 = arr;
assert(postblits == 2);
arr2 = arr;
assert(postblits == 4);
postblits = 0;

const S[2] constArr = s;
assert(postblits == 2);
postblits = 0;

const S[2] constArr2 = arr;
assert(postblits == 2);
postblits = 0;
}
{
S[2][2] arr = s;
assert(postblits == 4);
arr[] = a;
assert(postblits == 8);
postblits = 0;

S[2][2] arr2 = arr;
assert(postblits == 4);
arr2 = arr;
assert(postblits == 8);
postblits = 0;

const S[2][2] constArr = s;
assert(postblits == 4);
postblits = 0;

const S[2][2] constArr2 = arr;
assert(postblits == 4);
postblits = 0;
}

return true;
}
static assert(test9245());

/**************************************************
11510 support overlapped field access in CTFE
**************************************************/
Expand Down

0 comments on commit 6de3bd5

Please sign in to comment.