Skip to content

Commit

Permalink
Merge pull request #4579 from tramker/cherrypick
Browse files Browse the repository at this point in the history
Cherry-picking commits from master to stable branch (for 2.067.1)
  • Loading branch information
MartinNowak committed Apr 17, 2015
2 parents f63d1e9 + 56c8b67 commit aa96f70
Show file tree
Hide file tree
Showing 8 changed files with 257 additions and 89 deletions.
15 changes: 7 additions & 8 deletions src/ctfeexpr.c
Expand Up @@ -529,24 +529,23 @@ ArrayLiteralExp *createBlockDuplicatedArrayLiteral(Loc loc, Type *type,
{
Expressions *elements = new Expressions();
elements->setDim(dim);
bool mustCopy = needToCopyLiteral(elem);
if (type->ty == Tsarray && type->nextOf()->ty == Tsarray &&
elem->type->ty != Tsarray)
{
// If it is a multidimensional array literal, do it recursively
elem = createBlockDuplicatedArrayLiteral(loc, type->nextOf(), elem,
(size_t)((TypeSArray *)type->nextOf())->dim->toInteger());
mustCopy = true;
}
bool mustCopy = needToCopyLiteral(elem);
for (size_t i = 0; i < dim; i++)
{
if (mustCopy)
elem = copyLiteral(elem).copy();
(*elements)[i] = elem;
(*elements)[i] = mustCopy ? copyLiteral(elem).copy() : elem;
}
ArrayLiteralExp *ae = new ArrayLiteralExp(loc, elements);
ae->type = type;
ae->ownedByCtfe = 1;
return ae;
ArrayLiteralExp *ale = new ArrayLiteralExp(loc, elements);
ale->type = type;
ale->ownedByCtfe = 1;
return ale;
}

/******************************
Expand Down
159 changes: 84 additions & 75 deletions src/expression.c
Expand Up @@ -1531,18 +1531,14 @@ bool functionParameters(Loc loc, Scope *sc, TypeFunction *tf,
a = a->implicitCastTo(sc, tbn);
(*elements)[u] = a;
}
ArrayLiteralExp *ale = new ArrayLiteralExp(loc, elements);
ale->type = tsa;

Identifier *id = Identifier::generateId("__arrayArg");
VarDeclaration *v = new VarDeclaration(loc, tsa, id, new ExpInitializer(loc, ale));
v->storage_class |= STCtemp | STCctfe;
v->semantic(sc);
v->parent = sc->parent;

Expression *de = new DeclarationExp(loc, v);
Expression *ve = new VarExp(loc, v);
arg = Expression::combine(de, ve);
// Bugzilla 14395: Convert to a static array literal, or its slice.
arg = new ArrayLiteralExp(loc, elements);
arg->type = tsa;
if (tb->ty == Tarray)
{
arg = new SliceExp(loc, arg, NULL, NULL);
arg->type = p->type;
}
break;
}
case Tclass:
Expand Down Expand Up @@ -6945,6 +6941,12 @@ Expression *AssertExp::semantic(Scope *sc)
FuncDeclaration *fd = sc->parent->isFuncDeclaration();
if (fd)
fd->hasReturnExp |= 4;
sc->callSuper |= CSXhalt;
if (sc->fieldinit)
{
for (size_t i = 0; i < sc->fieldinit_dim; i++)
sc->fieldinit[i] |= CSXhalt;
}

if (!global.params.useAssert)
{
Expand Down Expand Up @@ -8545,39 +8547,36 @@ Expression *CallExp::semantic(Scope *sc)
error("super class constructor call must be in a constructor");
return new ErrorExp();
}
else
if (!cd->baseClass->ctor)
{
if (!cd->baseClass->ctor)
{ error("no super class constructor for %s", cd->baseClass->toChars());
return new ErrorExp();
}
else
{
if (!sc->intypeof)
{
if (sc->noctor || sc->callSuper & CSXlabel)
error("constructor calls not allowed in loops or after labels");
if (sc->callSuper & (CSXsuper_ctor | CSXthis_ctor))
error("multiple constructor calls");
if ((sc->callSuper & CSXreturn) && !(sc->callSuper & CSXany_ctor))
error("an earlier return statement skips constructor");
sc->callSuper |= CSXany_ctor | CSXsuper_ctor;
}
error("no super class constructor for %s", cd->baseClass->toChars());
return new ErrorExp();
}

tthis = cd->type->addMod(sc->func->type->mod);
f = resolveFuncCall(loc, sc, cd->baseClass->ctor, NULL, tthis, arguments, 0);
if (!f || f->errors)
return new ErrorExp();
accessCheck(loc, sc, NULL, f);
checkDeprecated(sc, f);
checkPurity(sc, f);
checkSafety(sc, f);
checkNogc(sc, f);
e1 = new DotVarExp(e1->loc, e1, f);
e1 = e1->semantic(sc);
t1 = e1->type;
}
if (!sc->intypeof && !(sc->callSuper & CSXhalt))
{
if (sc->noctor || sc->callSuper & CSXlabel)
error("constructor calls not allowed in loops or after labels");
if (sc->callSuper & (CSXsuper_ctor | CSXthis_ctor))
error("multiple constructor calls");
if ((sc->callSuper & CSXreturn) && !(sc->callSuper & CSXany_ctor))
error("an earlier return statement skips constructor");
sc->callSuper |= CSXany_ctor | CSXsuper_ctor;
}

tthis = cd->type->addMod(sc->func->type->mod);
f = resolveFuncCall(loc, sc, cd->baseClass->ctor, NULL, tthis, arguments, 0);
if (!f || f->errors)
return new ErrorExp();
checkDeprecated(sc, f);
checkPurity(sc, f);
checkSafety(sc, f);
checkNogc(sc, f);
accessCheck(loc, sc, NULL, f);

e1 = new DotVarExp(e1->loc, e1, f);
e1 = e1->semantic(sc);
t1 = e1->type;
}
else if (e1->op == TOKthis)
{
Expand All @@ -8591,38 +8590,38 @@ Expression *CallExp::semantic(Scope *sc)
error("constructor call must be in a constructor");
return new ErrorExp();
}
else

if (!sc->intypeof && !(sc->callSuper & CSXhalt))
{
if (!sc->intypeof)
{
if (sc->noctor || sc->callSuper & CSXlabel)
error("constructor calls not allowed in loops or after labels");
if (sc->callSuper & (CSXsuper_ctor | CSXthis_ctor))
error("multiple constructor calls");
if ((sc->callSuper & CSXreturn) && !(sc->callSuper & CSXany_ctor))
error("an earlier return statement skips constructor");
sc->callSuper |= CSXany_ctor | CSXthis_ctor;
}
if (sc->noctor || sc->callSuper & CSXlabel)
error("constructor calls not allowed in loops or after labels");
if (sc->callSuper & (CSXsuper_ctor | CSXthis_ctor))
error("multiple constructor calls");
if ((sc->callSuper & CSXreturn) && !(sc->callSuper & CSXany_ctor))
error("an earlier return statement skips constructor");
sc->callSuper |= CSXany_ctor | CSXthis_ctor;
}

tthis = cd->type->addMod(sc->func->type->mod);
f = resolveFuncCall(loc, sc, cd->ctor, NULL, tthis, arguments, 0);
if (!f || f->errors)
return new ErrorExp();
checkDeprecated(sc, f);
checkPurity(sc, f);
checkSafety(sc, f);
checkNogc(sc, f);
e1 = new DotVarExp(e1->loc, e1, f);
e1 = e1->semantic(sc);
t1 = e1->type;
tthis = cd->type->addMod(sc->func->type->mod);
f = resolveFuncCall(loc, sc, cd->ctor, NULL, tthis, arguments, 0);
if (!f || f->errors)
return new ErrorExp();
checkDeprecated(sc, f);
checkPurity(sc, f);
checkSafety(sc, f);
checkNogc(sc, f);
//accessCheck(loc, sc, NULL, f); // necessary?

// BUG: this should really be done by checking the static
// call graph
if (f == sc->func)
{
error("cyclic constructor call");
return new ErrorExp();
}
e1 = new DotVarExp(e1->loc, e1, f);
e1 = e1->semantic(sc);
t1 = e1->type;

// BUG: this should really be done by checking the static
// call graph
if (f == sc->func)
{
error("cyclic constructor call");
return new ErrorExp();
}
}
else if (e1->op == TOKoverloadset)
Expand Down Expand Up @@ -8652,7 +8651,8 @@ Expression *CallExp::semantic(Scope *sc)
}
}
if (!f)
{ /* No overload matches
{
/* No overload matches
*/
error("no overload matches for %s", s->toChars());
return new ErrorExp();
Expand Down Expand Up @@ -11288,9 +11288,18 @@ Expression *AssignExp::semantic(Scope *sc)
}
else // Bugzilla 11355
{
Expression *e = op_overload(sc);
if (e)
return e;
AggregateDeclaration *ad2 = isAggregate(e2x->type);
if (ad2 && ad2->aliasthis && !(att2 && e2x->type == att2))
{
if (!att2 && e2->type->checkAliasThisRec())
att2 = e2->type;

/* Rewrite (e1 op e2) as:
* (e1 op e2.aliasthis)
*/
e2 = new DotIdExp(e2->loc, e2, ad2->aliasthis->ident);
return semantic(sc);
}
}
}
else if (op == TOKassign)
Expand Down
39 changes: 33 additions & 6 deletions src/scope.c
Expand Up @@ -254,23 +254,31 @@ void Scope::mergeCallSuper(Loc loc, unsigned cs)
bool aRet = (cs & CSXreturn) != 0;
bool bRet = (callSuper & CSXreturn) != 0;

// Have any branches halted?
bool aHalt = (cs & CSXhalt) != 0;
bool bHalt = (callSuper & CSXhalt) != 0;

bool ok = true;

if ( (aRet && !aAny && bAny) ||
(bRet && !bAny && aAny))
if (aHalt && bHalt)
{
callSuper = CSXhalt;
}
else if ((!aHalt && aRet && !aAny && bAny) ||
(!bHalt && bRet && !bAny && aAny))
{
// If one has returned without a constructor call, there must be never
// have been ctor calls in the other.
ok = false;
}
else if (aRet && aAll)
else if (aHalt || aRet && aAll)
{
// If one branch has called a ctor and then exited, anything the
// other branch has done is OK (except returning without a
// ctor call, but we already checked that).
callSuper |= cs & (CSXany_ctor | CSXlabel);
}
else if (bRet && bAll)
else if (bHalt || bRet && bAll)
{
callSuper = cs | (callSuper & (CSXany_ctor | CSXlabel));
}
Expand Down Expand Up @@ -310,16 +318,35 @@ bool mergeFieldInit(Loc loc, unsigned &fieldInit, unsigned fi, bool mustInit)
bool aRet = (fi & CSXreturn) != 0;
bool bRet = (fieldInit & CSXreturn) != 0;

// Have any branches halted?
bool aHalt = (fi & CSXhalt) != 0;
bool bHalt = (fieldInit & CSXhalt) != 0;

bool ok;

if (aRet)
if (aHalt && bHalt)
{
ok = true;
fieldInit = CSXhalt;
}
else if (!aHalt && aRet)
{
ok = !mustInit || (fi & CSXthis_ctor);
fieldInit = fieldInit;
}
else if (bRet)
else if (!bHalt && bRet)
{
ok = !mustInit || (fieldInit & CSXthis_ctor);
fieldInit = fi;
}
else if (aHalt)
{
ok = !mustInit || (fieldInit & CSXthis_ctor);
fieldInit = fieldInit;
}
else if (bHalt)
{
ok = !mustInit || (fi & CSXthis_ctor);
fieldInit = fi;
}
else
Expand Down
1 change: 1 addition & 0 deletions src/scope.h
Expand Up @@ -49,6 +49,7 @@ enum LINK;
#define CSXlabel 0x10 // seen a label
#define CSXreturn 0x20 // seen a return statement
#define CSXany_ctor 0x40 // either this() or super() was called
#define CSXhalt 0x80 // assert(0)

// Flags that would not be inherited beyond scope nesting
#define SCOPEctor 0x0001 // constructor type
Expand Down
41 changes: 41 additions & 0 deletions test/compilable/interpret3.d
Expand Up @@ -4695,6 +4695,47 @@ int bug10198()
}
static assert(bug10198());

/**************************************************
14440 Multidimensional block initialization should create distinct arrays for each elements
**************************************************/

struct Matrix14440(E, size_t row, size_t col)
{
E[col][row] array2D;

@safe pure nothrow
this(E[row * col] numbers...)
{
foreach (r; 0 .. row)
{
foreach (c; 0 .. col)
{
array2D[r][c] = numbers[r * col + c];
}
}
}
}

void test14440()
{
// Replace 'enum' with 'auto' here and it will work fine.
enum matrix = Matrix14440!(int, 3, 3)(
1, 2, 3,
4, 5, 6,
7, 8, 9
);

static assert(matrix.array2D[0][0] == 1);
static assert(matrix.array2D[0][1] == 2);
static assert(matrix.array2D[0][2] == 3);
static assert(matrix.array2D[1][0] == 4);
static assert(matrix.array2D[1][1] == 5);
static assert(matrix.array2D[1][2] == 6);
static assert(matrix.array2D[2][0] == 7);
static assert(matrix.array2D[2][1] == 8);
static assert(matrix.array2D[2][2] == 9);
}

/****************************************************
* Exception chaining tests from xtest46.d
****************************************************/
Expand Down

0 comments on commit aa96f70

Please sign in to comment.