mirror of
https://github.com/xomboverlord/ldc.git
synced 2026-01-17 13:23:14 +01:00
Update source to eb1b004.
This brings the source beyond beta4.
This commit is contained in:
@@ -1572,17 +1572,19 @@ Lnomatch:
|
||||
*/
|
||||
storage_class &= ~(STCref | STCforeach | STCparameter);
|
||||
|
||||
Expression *e;
|
||||
Expression *e = new VarExp(loc, this);
|
||||
if (sd->zeroInit == 1)
|
||||
{
|
||||
e = new ConstructExp(loc, new VarExp(loc, this), new IntegerExp(loc, 0, Type::tint32));
|
||||
e = new ConstructExp(loc, e, new IntegerExp(loc, 0, Type::tint32));
|
||||
}
|
||||
else if (sd->isNested())
|
||||
{ e = new AssignExp(loc, new VarExp(loc, this), t->defaultInitLiteral(loc));
|
||||
{
|
||||
e = new AssignExp(loc, e, t->defaultInitLiteral(loc));
|
||||
e->op = TOKblit;
|
||||
}
|
||||
else
|
||||
{ e = new AssignExp(loc, new VarExp(loc, this), t->defaultInit(loc));
|
||||
{
|
||||
e = new AssignExp(loc, e, t->defaultInit(loc));
|
||||
e->op = TOKblit;
|
||||
}
|
||||
e->type = t;
|
||||
|
||||
@@ -414,7 +414,7 @@ Expression *resolvePropertiesX(Scope *sc, Expression *e1, Expression *e2 = NULL)
|
||||
tthis = NULL;
|
||||
goto Lfd;
|
||||
}
|
||||
else if (e1->op == TOKdotvar && e1->type->toBasetype()->ty == Tfunction)
|
||||
else if (e1->op == TOKdotvar && e1->type && e1->type->toBasetype()->ty == Tfunction)
|
||||
{
|
||||
DotVarExp *dve = (DotVarExp *)e1;
|
||||
s = dve->var->isFuncDeclaration();
|
||||
@@ -422,7 +422,7 @@ Expression *resolvePropertiesX(Scope *sc, Expression *e1, Expression *e2 = NULL)
|
||||
tthis = dve->e1->type;
|
||||
goto Lfd;
|
||||
}
|
||||
else if (e1->op == TOKvar && e1->type->toBasetype()->ty == Tfunction)
|
||||
else if (e1->op == TOKvar && e1->type && e1->type->toBasetype()->ty == Tfunction)
|
||||
{
|
||||
s = ((VarExp *)e1)->var->isFuncDeclaration();
|
||||
tiargs = NULL;
|
||||
@@ -4618,7 +4618,6 @@ StructLiteralExp::StructLiteralExp(Loc loc, StructDeclaration *sd, Expressions *
|
||||
this->soffset = 0;
|
||||
this->fillHoles = 1;
|
||||
this->ownedByCtfe = false;
|
||||
this->ctorinit = 0;
|
||||
#if IN_LLVM
|
||||
this->inProgressMemory = NULL;
|
||||
this->globalVar = NULL;
|
||||
@@ -4729,52 +4728,17 @@ Expression *StructLiteralExp::semantic(Scope *sc)
|
||||
|
||||
/* Fill out remainder of elements[] with default initializers for fields[]
|
||||
*/
|
||||
for (size_t i = elements->dim; i < nfields; i++)
|
||||
Expression *e = fill(false);
|
||||
if (e->op == TOKerror)
|
||||
{
|
||||
Expression *e;
|
||||
VarDeclaration *v = sd->fields[i];
|
||||
assert(!v->isThisDeclaration());
|
||||
|
||||
if (v->offset < offset)
|
||||
{
|
||||
e = NULL;
|
||||
sd->hasUnions = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (v->init)
|
||||
{
|
||||
if (v->init->isVoidInitializer())
|
||||
e = NULL;
|
||||
else
|
||||
e = v->getConstInitializer(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((v->storage_class & STCnodefaultctor) && !ctorinit)
|
||||
{
|
||||
error("field %s.%s must be initialized because it has no default constructor",
|
||||
sd->type->toChars(), v->toChars());
|
||||
}
|
||||
if (v->type->needsNested() && ctorinit)
|
||||
e = v->type->defaultInit(loc);
|
||||
else
|
||||
e = v->type->defaultInitLiteral(loc);
|
||||
}
|
||||
offset = v->offset + v->type->size();
|
||||
}
|
||||
if (e && e->op == TOKerror)
|
||||
{
|
||||
/* An error in the initializer needs to be recorded as an error
|
||||
* in the enclosing function or template, since the initializer
|
||||
* will be part of the stuct declaration.
|
||||
*/
|
||||
global.increaseErrorCount();
|
||||
return e;
|
||||
}
|
||||
elements->push(e);
|
||||
/* An error in the initializer needs to be recorded as an error
|
||||
* in the enclosing function or template, since the initializer
|
||||
* will be part of the stuct declaration.
|
||||
*/
|
||||
global.increaseErrorCount();
|
||||
return e;
|
||||
}
|
||||
|
||||
assert(e == this);
|
||||
type = stype ? stype : sd->type;
|
||||
|
||||
/* If struct requires a destructor, rewrite as:
|
||||
@@ -4795,6 +4759,115 @@ Expression *StructLiteralExp::semantic(Scope *sc)
|
||||
return this;
|
||||
}
|
||||
|
||||
Expression *StructLiteralExp::fill(bool ctorinit)
|
||||
{
|
||||
assert(sd && sd->sizeok == SIZEOKdone);
|
||||
size_t nfields = sd->fields.dim - sd->isNested();
|
||||
|
||||
size_t dim = elements->dim;
|
||||
elements->setDim(nfields);
|
||||
for (size_t i = dim; i < nfields; i++)
|
||||
(*elements)[i] = NULL;
|
||||
|
||||
// Fill in missing any elements with default initializers
|
||||
for (size_t i = 0; i < nfields; i++)
|
||||
{
|
||||
if ((*elements)[i])
|
||||
continue;
|
||||
VarDeclaration *vd = sd->fields[i];
|
||||
VarDeclaration *vx = vd;
|
||||
if (vd->init && vd->init->isVoidInitializer())
|
||||
vx = NULL;
|
||||
// Find overlapped fields with the hole [vd->offset .. vd->offset->size()].
|
||||
size_t fieldi = i;
|
||||
for (size_t j = 0; j < nfields; j++)
|
||||
{
|
||||
if (i == j)
|
||||
continue;
|
||||
VarDeclaration *v2 = sd->fields[j];
|
||||
if (v2->init && v2->init->isVoidInitializer())
|
||||
continue;
|
||||
|
||||
bool overlap = (vd->offset < v2->offset + v2->type->size() &&
|
||||
v2->offset < vd->offset + vd->type->size());
|
||||
if (!overlap)
|
||||
continue;
|
||||
|
||||
sd->hasUnions = 1; // note that directly unrelated...
|
||||
|
||||
if ((*elements)[j])
|
||||
{
|
||||
vx = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
#if 1
|
||||
/* Prefer first found non-void-initialized field
|
||||
* union U { int a; int b = 2; }
|
||||
* U u; // Error: overlapping initialization for field a and b
|
||||
*/
|
||||
if (!vx)
|
||||
vx = v2, fieldi = j;
|
||||
else if (v2->init)
|
||||
{
|
||||
error("overlapping initialization for field %s and %s",
|
||||
v2->toChars(), vd->toChars());
|
||||
}
|
||||
#else // fix Bugzilla 1432
|
||||
/* Prefer explicitly initialized field
|
||||
* union U { int a; int b = 2; }
|
||||
* U u; // OK (u.b == 2)
|
||||
*/
|
||||
if (!vx || !vx->init && v2->init)
|
||||
vx = v2, fieldi = j;
|
||||
else if (vx != vd &&
|
||||
!(vx->offset < v2->offset + v2->type->size() &&
|
||||
v2->offset < vx->offset + vx->type->size()))
|
||||
{
|
||||
// Both vx and v2 fills vd, but vx and v2 does not overlap
|
||||
}
|
||||
else if (vx->init && v2->init)
|
||||
{
|
||||
error("overlapping default initialization for field %s and %s",
|
||||
v2->toChars(), vd->toChars());
|
||||
}
|
||||
else
|
||||
assert(vx->init || !vx->init && !v2->init);
|
||||
#endif
|
||||
}
|
||||
if (vx)
|
||||
{
|
||||
Expression *e;
|
||||
if (vx->init)
|
||||
{
|
||||
assert(!vx->init->isVoidInitializer());
|
||||
e = vx->getConstInitializer(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((vx->storage_class & STCnodefaultctor) && !ctorinit)
|
||||
{
|
||||
error("field %s.%s must be initialized because it has no default constructor",
|
||||
sd->type->toChars(), vx->toChars());
|
||||
}
|
||||
if (vx->type->needsNested() && ctorinit)
|
||||
e = vx->type->defaultInit(loc);
|
||||
else
|
||||
e = vx->type->defaultInitLiteral(loc);
|
||||
}
|
||||
(*elements)[fieldi] = e;
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < elements->dim; i++)
|
||||
{
|
||||
Expression *e = (*elements)[i];
|
||||
if (e && e->op == TOKerror)
|
||||
return e;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**************************************
|
||||
* Gets expression at offset of type.
|
||||
* Returns NULL if not found.
|
||||
@@ -7885,7 +7958,9 @@ Expression *DotVarExp::semantic(Scope *sc)
|
||||
Identifier *id = Lexer::uniqueId("__tup");
|
||||
ExpInitializer *ei = new ExpInitializer(e1->loc, e1);
|
||||
VarDeclaration *v = new VarDeclaration(e1->loc, NULL, id, ei);
|
||||
v->storage_class |= STCctfe | STCref | STCforeach;
|
||||
v->storage_class |= STCctfe;
|
||||
if (e1->isLvalue())
|
||||
v->storage_class |= STCref | STCforeach;
|
||||
e0 = new DeclarationExp(e1->loc, v);
|
||||
ev = new VarExp(e1->loc, v);
|
||||
e0 = e0->semantic(sc);
|
||||
@@ -8732,8 +8807,8 @@ Lagain:
|
||||
|
||||
// Check for call operator overload
|
||||
if (t1)
|
||||
{ AggregateDeclaration *ad;
|
||||
|
||||
{
|
||||
AggregateDeclaration *ad;
|
||||
if (t1->ty == Tstruct)
|
||||
{
|
||||
ad = ((TypeStruct *)t1)->sym;
|
||||
@@ -8762,29 +8837,29 @@ Lagain:
|
||||
ExpInitializer *ei = NULL;
|
||||
if (t1->needsNested())
|
||||
{
|
||||
Expressions *args = new Expressions();
|
||||
StructLiteralExp *se = new StructLiteralExp(loc, (StructDeclaration *)ad, args);
|
||||
se->ctorinit = 1;
|
||||
ei = new ExpInitializer(loc, se);
|
||||
StructLiteralExp *sle = new StructLiteralExp(loc, (StructDeclaration *)ad, NULL, e1->type);
|
||||
Expression *e = sle->fill(true);
|
||||
if (e->op == TOKerror)
|
||||
return e;
|
||||
sle->type = type;
|
||||
ei = new ExpInitializer(loc, sle);
|
||||
}
|
||||
|
||||
VarDeclaration *tmp = new VarDeclaration(loc, t1, idtmp, ei);
|
||||
tmp->storage_class |= STCctfe;
|
||||
Expression *av = new DeclarationExp(loc, tmp);
|
||||
av = new CommaExp(loc, av, new VarExp(loc, tmp));
|
||||
|
||||
Expression *e;
|
||||
Expression *e = new DeclarationExp(loc, tmp);
|
||||
e = new CommaExp(loc, e, new VarExp(loc, tmp));
|
||||
if (CtorDeclaration *cf = ad->ctor->isCtorDeclaration())
|
||||
{
|
||||
e = new DotVarExp(loc, av, cf, 1);
|
||||
e = new DotVarExp(loc, e, cf, 1);
|
||||
}
|
||||
else if (TemplateDeclaration *td = ad->ctor->isTemplateDeclaration())
|
||||
{
|
||||
e = new DotTemplateExp(loc, av, td);
|
||||
e = new DotTemplateExp(loc, e, td);
|
||||
}
|
||||
else if (OverloadSet *os = ad->ctor->isOverloadSet())
|
||||
{
|
||||
e = new DotExp(loc, av, new OverExp(loc, os));
|
||||
e = new DotExp(loc, e, new OverExp(loc, os));
|
||||
}
|
||||
else
|
||||
assert(0);
|
||||
@@ -11446,7 +11521,9 @@ Ltupleassign:
|
||||
Identifier *id = Lexer::uniqueId("__tup");
|
||||
ExpInitializer *ei = new ExpInitializer(e2->loc, e2);
|
||||
VarDeclaration *v = new VarDeclaration(e2->loc, NULL, id, ei);
|
||||
v->storage_class = STCctfe | STCref | STCforeach;
|
||||
v->storage_class = STCctfe;
|
||||
if (e2->isLvalue())
|
||||
v->storage_class = STCref | STCforeach;
|
||||
Expression *e0 = new DeclarationExp(e2->loc, v);
|
||||
Expression *ev = new VarExp(e2->loc, v);
|
||||
ev->type = e2->type;
|
||||
@@ -11532,6 +11609,8 @@ Ltupleassign:
|
||||
VarDeclaration *v = new VarDeclaration(loc, ie->e1->type,
|
||||
Lexer::uniqueId("__aatmp"), new ExpInitializer(loc, ie->e1));
|
||||
v->storage_class |= STCctfe;
|
||||
if (ea->isLvalue())
|
||||
v->storage_class |= STCforeach | STCref;
|
||||
v->semantic(sc);
|
||||
e0 = combine(e0, new DeclarationExp(loc, v));
|
||||
ea = new VarExp(loc, v);
|
||||
@@ -11541,6 +11620,8 @@ Ltupleassign:
|
||||
VarDeclaration *v = new VarDeclaration(loc, ie->e2->type,
|
||||
Lexer::uniqueId("__aakey"), new ExpInitializer(loc, ie->e2));
|
||||
v->storage_class |= STCctfe;
|
||||
if (ek->isLvalue())
|
||||
v->storage_class |= STCforeach | STCref;
|
||||
v->semantic(sc);
|
||||
e0 = combine(e0, new DeclarationExp(loc, v));
|
||||
ek = new VarExp(loc, v);
|
||||
@@ -11550,6 +11631,8 @@ Ltupleassign:
|
||||
VarDeclaration *v = new VarDeclaration(loc, e2->type,
|
||||
Lexer::uniqueId("__aaval"), new ExpInitializer(loc, e2));
|
||||
v->storage_class |= STCctfe;
|
||||
if (ev->isLvalue())
|
||||
v->storage_class |= STCforeach | STCref;
|
||||
v->semantic(sc);
|
||||
e0 = combine(e0, new DeclarationExp(loc, v));
|
||||
ev = new VarExp(loc, v);
|
||||
@@ -11761,7 +11844,7 @@ Ltupleassign:
|
||||
e2 = new SliceExp(e2->loc, e2, NULL, NULL);
|
||||
e2 = e2->semantic(sc);
|
||||
}
|
||||
else if (global.params.warnings && !global.gag && op == TOKassign &&
|
||||
else if (0 && global.params.warnings && !global.gag && op == TOKassign &&
|
||||
e2->op != TOKarrayliteral && e2->op != TOKstring &&
|
||||
!e2->implicitConvTo(t1))
|
||||
{ // Disallow sa = da (Converted to sa[] = da[])
|
||||
@@ -11891,7 +11974,7 @@ Ltupleassign:
|
||||
{
|
||||
e2->checkPostblit(sc, t2->nextOf());
|
||||
}
|
||||
if (global.params.warnings && !global.gag && op == TOKassign &&
|
||||
if (0 && global.params.warnings && !global.gag && op == TOKassign &&
|
||||
e2->op != TOKslice && e2->op != TOKassign &&
|
||||
e2->op != TOKarrayliteral && e2->op != TOKstring &&
|
||||
!(e2->op == TOKadd || e2->op == TOKmin ||
|
||||
@@ -11915,7 +11998,7 @@ Ltupleassign:
|
||||
}
|
||||
else
|
||||
{
|
||||
if (global.params.warnings && !global.gag && op == TOKassign &&
|
||||
if (0 && global.params.warnings && !global.gag && op == TOKassign &&
|
||||
t1->ty == Tarray && t2->ty == Tsarray &&
|
||||
e2->op != TOKslice && //e2->op != TOKarrayliteral &&
|
||||
t2->implicitConvTo(t1))
|
||||
@@ -13976,7 +14059,8 @@ Expression *extractOpDollarSideEffect(Scope *sc, UnaExp *ue)
|
||||
Identifier *id = Lexer::uniqueId("__dop");
|
||||
ExpInitializer *ei = new ExpInitializer(ue->loc, ue->e1);
|
||||
VarDeclaration *v = new VarDeclaration(ue->loc, ue->e1->type, id, ei);
|
||||
v->storage_class |= STCctfe | STCforeach | STCref;
|
||||
v->storage_class |= STCctfe
|
||||
| (ue->e1->isLvalue() ? (STCforeach | STCref) : 0);
|
||||
e0 = new DeclarationExp(ue->loc, v);
|
||||
e0 = e0->semantic(sc);
|
||||
ue->e1 = new VarExp(ue->loc, v);
|
||||
@@ -14098,9 +14182,9 @@ Expression *BinExp::reorderSettingAAElem(Scope *sc)
|
||||
{
|
||||
Identifier *id = Lexer::uniqueId("__aatmp");
|
||||
VarDeclaration *vd = new VarDeclaration(ie->e1->loc, ie->e1->type, id, new ExpInitializer(ie->e1->loc, ie->e1));
|
||||
vd->storage_class |= STCref | STCforeach;
|
||||
Expression *de = new DeclarationExp(ie->e1->loc, vd);
|
||||
|
||||
if (ie->e1->isLvalue())
|
||||
vd->storage_class |= STCref | STCforeach;
|
||||
ec = de;
|
||||
ie->e1 = new VarExp(ie->e1->loc, vd);
|
||||
}
|
||||
@@ -14108,7 +14192,8 @@ Expression *BinExp::reorderSettingAAElem(Scope *sc)
|
||||
{
|
||||
Identifier *id = Lexer::uniqueId("__aakey");
|
||||
VarDeclaration *vd = new VarDeclaration(ie->e2->loc, ie->e2->type, id, new ExpInitializer(ie->e2->loc, ie->e2));
|
||||
vd->storage_class |= STCref | STCforeach;
|
||||
if (ie->e2->isLvalue())
|
||||
vd->storage_class |= STCref | STCforeach;
|
||||
Expression *de = new DeclarationExp(ie->e2->loc, vd);
|
||||
|
||||
ec = ec ? new CommaExp(loc, ec, de) : de;
|
||||
|
||||
@@ -604,7 +604,6 @@ public:
|
||||
size_t soffset; // offset from start of s
|
||||
int fillHoles; // fill alignment 'holes' with zero
|
||||
bool ownedByCtfe; // true = created in CTFE
|
||||
int ctorinit;
|
||||
|
||||
StructLiteralExp *origin; // pointer to the origin instance of the expression.
|
||||
// once a new expression is created, origin is set to 'this'.
|
||||
@@ -622,6 +621,7 @@ public:
|
||||
Expression *syntaxCopy();
|
||||
int apply(apply_fp_t fp, void *param);
|
||||
Expression *semantic(Scope *sc);
|
||||
Expression *fill(bool ctorinit);
|
||||
Expression *getField(Type *type, unsigned offset);
|
||||
int getFieldIndex(Type *type, unsigned offset);
|
||||
elem *toElem(IRState *irs);
|
||||
|
||||
280
dmd2/init.c
280
dmd2/init.c
@@ -189,11 +189,101 @@ Initializer *StructInitializer::semantic(Scope *sc, Type *t, NeedInterpret needI
|
||||
sd->kind(), sd->toChars(), sd->toChars());
|
||||
return new ErrorInitializer();
|
||||
}
|
||||
sd->size(loc);
|
||||
if (sd->sizeok != SIZEOKdone)
|
||||
return new ErrorInitializer();
|
||||
size_t nfields = sd->fields.dim - sd->isNested();
|
||||
|
||||
Expression *e = fill(sc, t, needInterpret);
|
||||
//expandTuples for non-identity arguments?
|
||||
|
||||
Expressions *elements = new Expressions();
|
||||
elements->setDim(nfields);
|
||||
for (size_t i = 0; i < elements->dim; i++)
|
||||
(*elements)[i] = NULL;
|
||||
|
||||
// Run semantic for explicitly given initializers
|
||||
// TODO: this part is slightly different from StructLiteralExp::semantic.
|
||||
bool errors = false;
|
||||
for (size_t fieldi = 0, i = 0; i < field.dim; i++)
|
||||
{
|
||||
if (Identifier *id = field[i])
|
||||
{
|
||||
Dsymbol *s = sd->search(loc, id, 0);
|
||||
if (!s)
|
||||
{
|
||||
s = sd->search_correct(id);
|
||||
if (s)
|
||||
error(loc, "'%s' is not a member of '%s', did you mean '%s %s'?",
|
||||
id->toChars(), sd->toChars(), s->kind(), s->toChars());
|
||||
else
|
||||
error(loc, "'%s' is not a member of '%s'", id->toChars(), sd->toChars());
|
||||
return new ErrorInitializer();
|
||||
}
|
||||
s = s->toAlias();
|
||||
|
||||
// Find out which field index it is
|
||||
for (fieldi = 0; 1; fieldi++)
|
||||
{
|
||||
if (fieldi >= nfields)
|
||||
{
|
||||
error(loc, "%s.%s is not a per-instance initializable field",
|
||||
sd->toChars(), s->toChars());
|
||||
return new ErrorInitializer();
|
||||
}
|
||||
if (s == sd->fields[fieldi])
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (fieldi >= nfields)
|
||||
{
|
||||
error(loc, "too many initializers for %s", sd->toChars());
|
||||
return new ErrorInitializer();
|
||||
}
|
||||
|
||||
VarDeclaration *vd = sd->fields[fieldi];
|
||||
if ((*elements)[fieldi])
|
||||
{
|
||||
error(loc, "duplicate initializer for field '%s'", vd->toChars());
|
||||
errors = true;
|
||||
continue;
|
||||
}
|
||||
for (size_t j = 0; j < nfields; j++)
|
||||
{
|
||||
VarDeclaration *v2 = sd->fields[j];
|
||||
bool overlap = (vd->offset < v2->offset + v2->type->size() &&
|
||||
v2->offset < vd->offset + vd->type->size());
|
||||
if (overlap && (*elements)[j])
|
||||
{
|
||||
error(loc, "overlapping initialization for field %s and %s",
|
||||
v2->toChars(), vd->toChars());
|
||||
errors = true;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
assert(sc);
|
||||
Initializer *iz = value[i];
|
||||
iz = iz->semantic(sc, vd->type->addMod(t->mod), needInterpret);
|
||||
Expression *ex = iz->toExpression();
|
||||
if (ex->op == TOKerror)
|
||||
{
|
||||
errors = true;
|
||||
continue;
|
||||
}
|
||||
value[i] = iz;
|
||||
(*elements)[fieldi] = ex;
|
||||
++fieldi;
|
||||
}
|
||||
if (errors)
|
||||
return new ErrorInitializer();
|
||||
|
||||
StructLiteralExp *sle = new StructLiteralExp(loc, sd, elements, t);
|
||||
Expression *e = sle->fill(false);
|
||||
if (e->op == TOKerror)
|
||||
return new ErrorInitializer();
|
||||
|
||||
e->type = t;
|
||||
|
||||
ExpInitializer *ie = new ExpInitializer(loc, e);
|
||||
return ie->semantic(sc, t, needInterpret);
|
||||
}
|
||||
@@ -226,194 +316,6 @@ Expression *StructInitializer::toExpression(Type *t)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Expression *StructInitializer::fill(Scope *sc, Type *t, NeedInterpret needInterpret)
|
||||
{
|
||||
//printf("StructInitializer::fill(sc = %p, '%s')\n", sc, toChars());
|
||||
assert(t->ty == Tstruct);
|
||||
StructDeclaration *sd = ((TypeStruct *)t)->sym;
|
||||
sd->size(loc);
|
||||
if (sd->sizeok != SIZEOKdone)
|
||||
return new ErrorExp();
|
||||
size_t nfields = sd->fields.dim - sd->isNested();
|
||||
|
||||
Expressions *elements = new Expressions();
|
||||
elements->setDim(nfields);
|
||||
for (size_t i = 0; i < elements->dim; i++)
|
||||
(*elements)[i] = NULL;
|
||||
|
||||
// Run semantic for explicitly given initializers
|
||||
bool errors = false;
|
||||
for (size_t fieldi = 0, i = 0; i < field.dim; i++)
|
||||
{
|
||||
if (Identifier *id = field[i])
|
||||
{
|
||||
Dsymbol *s = sd->search(loc, id, 0);
|
||||
if (!s)
|
||||
{
|
||||
s = sd->search_correct(id);
|
||||
if (s)
|
||||
error(loc, "'%s' is not a member of '%s', did you mean '%s %s'?",
|
||||
id->toChars(), sd->toChars(), s->kind(), s->toChars());
|
||||
else
|
||||
error(loc, "'%s' is not a member of '%s'", id->toChars(), sd->toChars());
|
||||
return new ErrorExp();
|
||||
}
|
||||
s = s->toAlias();
|
||||
|
||||
// Find out which field index it is
|
||||
for (fieldi = 0; 1; fieldi++)
|
||||
{
|
||||
if (fieldi >= nfields)
|
||||
{
|
||||
error(loc, "%s.%s is not a per-instance initializable field",
|
||||
sd->toChars(), s->toChars());
|
||||
return new ErrorExp();
|
||||
}
|
||||
if (s == sd->fields[fieldi])
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (fieldi >= nfields)
|
||||
{
|
||||
error(loc, "too many initializers for %s", sd->toChars());
|
||||
return new ErrorExp();
|
||||
}
|
||||
|
||||
VarDeclaration *vd = sd->fields[fieldi];
|
||||
if ((*elements)[fieldi])
|
||||
{
|
||||
error(loc, "duplicate initializer for field '%s'", vd->toChars());
|
||||
errors = true;
|
||||
continue;
|
||||
}
|
||||
for (size_t j = 0; j < nfields; j++)
|
||||
{
|
||||
VarDeclaration *v2 = sd->fields[j];
|
||||
bool overlap = (vd->offset < v2->offset + v2->type->size() &&
|
||||
v2->offset < vd->offset + vd->type->size());
|
||||
if (overlap && (*elements)[j])
|
||||
{
|
||||
error(loc, "overlapping initialization for field %s and %s",
|
||||
v2->toChars(), vd->toChars());
|
||||
errors = true;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
assert(sc);
|
||||
Initializer *iz = value[i];
|
||||
iz = iz->semantic(sc, vd->type->addMod(t->mod), needInterpret);
|
||||
Expression *ex = iz->toExpression();
|
||||
if (ex->op == TOKerror)
|
||||
{
|
||||
errors = true;
|
||||
continue;
|
||||
}
|
||||
value[i] = iz;
|
||||
(*elements)[fieldi] = ex;
|
||||
++fieldi;
|
||||
}
|
||||
if (errors)
|
||||
return new ErrorExp();
|
||||
|
||||
// Fill in missing any elements with default initializers
|
||||
for (size_t i = 0; i < elements->dim; i++)
|
||||
{
|
||||
if ((*elements)[i])
|
||||
continue;
|
||||
VarDeclaration *vd = sd->fields[i];
|
||||
VarDeclaration *vx = vd;
|
||||
if (vd->init && vd->init->isVoidInitializer())
|
||||
vx = NULL;
|
||||
// Find overlapped fields with the hole [vd->offset .. vd->offset->size()].
|
||||
size_t fieldi = i;
|
||||
for (size_t j = 0; j < nfields; j++)
|
||||
{
|
||||
if (i == j)
|
||||
continue;
|
||||
VarDeclaration *v2 = sd->fields[j];
|
||||
if (v2->init && v2->init->isVoidInitializer())
|
||||
continue;
|
||||
|
||||
bool overlap = (vd->offset < v2->offset + v2->type->size() &&
|
||||
v2->offset < vd->offset + vd->type->size());
|
||||
if (!overlap)
|
||||
continue;
|
||||
|
||||
if ((*elements)[j])
|
||||
{
|
||||
vx = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
#if 1
|
||||
/* Prefer first found non-void-initialized field
|
||||
* union U { int a; int b = 2; }
|
||||
* U u; // Error: overlapping initialization for field a and b
|
||||
*/
|
||||
if (!vx)
|
||||
vx = v2, fieldi = j;
|
||||
else if (v2->init)
|
||||
{
|
||||
error(loc, "overlapping initialization for field %s and %s",
|
||||
v2->toChars(), vd->toChars());
|
||||
}
|
||||
#else // fix Bugzilla 1432
|
||||
/* Prefer explicitly initialized field
|
||||
* union U { int a; int b = 2; }
|
||||
* U u; // OK (u.b == 2)
|
||||
*/
|
||||
if (!vx || !vx->init && v2->init)
|
||||
vx = v2, fieldi = j;
|
||||
else if (vx->init && v2->init)
|
||||
{
|
||||
error(loc, "overlapping default initialization for field %s and %s",
|
||||
v2->toChars(), vd->toChars());
|
||||
}
|
||||
else
|
||||
assert(vx->init || !vx->init && !v2->init);
|
||||
#endif
|
||||
}
|
||||
if (vx)
|
||||
{
|
||||
if (vx->init)
|
||||
{
|
||||
assert(!vx->init->isVoidInitializer());
|
||||
if (vx->scope)
|
||||
{
|
||||
// Do deferred semantic analysis
|
||||
Initializer *i2 = vx->init->syntaxCopy();
|
||||
i2 = i2->semantic(vx->scope, vx->type, INITinterpret);
|
||||
(*elements)[fieldi] = i2->toExpression();
|
||||
if (!global.gag)
|
||||
{
|
||||
vx->scope = NULL;
|
||||
vx->init = i2; // save result
|
||||
}
|
||||
}
|
||||
else
|
||||
(*elements)[fieldi] = vx->init->toExpression();
|
||||
}
|
||||
else
|
||||
(*elements)[fieldi] = vx->type->defaultInit();
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < elements->dim; i++)
|
||||
{
|
||||
Expression *e = (*elements)[i];
|
||||
if (e && e->op == TOKerror)
|
||||
return e;
|
||||
}
|
||||
|
||||
Expression *e = new StructLiteralExp(loc, sd, elements, t);
|
||||
if (sc)
|
||||
e = e->semantic(sc);
|
||||
else
|
||||
e->type = sd->type; // from glue layer
|
||||
return e;
|
||||
}
|
||||
|
||||
void StructInitializer::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||
{
|
||||
//printf("StructInitializer::toCBuffer()\n");
|
||||
|
||||
@@ -105,7 +105,6 @@ public:
|
||||
void addInit(Identifier *field, Initializer *value);
|
||||
Initializer *semantic(Scope *sc, Type *t, NeedInterpret needInterpret);
|
||||
Expression *toExpression(Type *t = NULL);
|
||||
Expression *fill(Scope *sc, Type *t, NeedInterpret needInterpret);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
|
||||
#if IN_DMD
|
||||
|
||||
15
dmd2/mars.c
15
dmd2/mars.c
@@ -368,6 +368,7 @@ Usage:\n\
|
||||
\n\
|
||||
files.d D source files\n\
|
||||
@cmdfile read arguments from cmdfile\n\
|
||||
-allinst generate code for all template instantiations\n\
|
||||
-c do not link\n\
|
||||
-cov do code coverage analysis\n\
|
||||
-cov=nnn require at least nnn%% code coverage\n\
|
||||
@@ -634,7 +635,9 @@ int tryMain(size_t argc, char *argv[])
|
||||
p = argv[i];
|
||||
if (*p == '-')
|
||||
{
|
||||
if (strcmp(p + 1, "de") == 0)
|
||||
if (strcmp(p + 1, "allinst") == 0)
|
||||
global.params.allInst = true;
|
||||
else if (strcmp(p + 1, "de") == 0)
|
||||
global.params.useDeprecated = 0;
|
||||
else if (strcmp(p + 1, "d") == 0)
|
||||
global.params.useDeprecated = 1;
|
||||
@@ -1713,12 +1716,7 @@ Language changes listed by -transition=id:\n\
|
||||
fprintf(global.stdmsg, "code %s\n", m->toChars());
|
||||
m->genobjfile(0);
|
||||
if (entrypoint && m == entrypoint->importedFrom)
|
||||
{
|
||||
char v = global.params.verbose;
|
||||
global.params.verbose = 0;
|
||||
entrypoint->genobjfile(0);
|
||||
global.params.verbose = v;
|
||||
}
|
||||
if (!global.errors && global.params.doDocComments)
|
||||
m->gendocfile();
|
||||
}
|
||||
@@ -1739,12 +1737,7 @@ Language changes listed by -transition=id:\n\
|
||||
obj_start(m->srcfile->toChars());
|
||||
m->genobjfile(global.params.multiobj);
|
||||
if (entrypoint && m == entrypoint->importedFrom)
|
||||
{
|
||||
char v = global.params.verbose;
|
||||
global.params.verbose = 0;
|
||||
entrypoint->genobjfile(global.params.multiobj);
|
||||
global.params.verbose = v;
|
||||
}
|
||||
obj_end(library, m->objfile);
|
||||
obj_write_deferred(library);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
// Compiler implementation of the D programming language
|
||||
// Copyright (c) 1999-2012 by Digital Mars
|
||||
// Copyright (c) 1999-2013 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
@@ -218,6 +218,7 @@ struct Param
|
||||
bool ignoreUnsupportedPragmas; // rather than error on them
|
||||
bool enforcePropertySyntax;
|
||||
bool addMain; // LDC_FIXME: Implement.
|
||||
bool allInst; // LDC_FIXME: Implement.
|
||||
#else
|
||||
bool pic; // generate position-independent-code for shared libs
|
||||
bool cov; // generate code coverage data
|
||||
@@ -227,6 +228,7 @@ struct Param
|
||||
char enforcePropertySyntax;
|
||||
char betterC; // be a "better C" compiler; no dependency on D runtime
|
||||
bool addMain; // add a default main() function
|
||||
bool allInst; // generate code for all template instantiations
|
||||
#endif
|
||||
|
||||
char *argv0; // program name
|
||||
|
||||
@@ -1274,8 +1274,12 @@ const char *lookForSourceFile(const char *filename)
|
||||
{
|
||||
/* The filename exists and it's a directory.
|
||||
* Therefore, the result should be: filename/package.d
|
||||
* iff filename/package.d is a file
|
||||
*/
|
||||
return FileName::combine(filename, "package.d");
|
||||
const char *n = FileName::combine(filename, "package.d");
|
||||
if (FileName::exists(n) == 1)
|
||||
return n;
|
||||
FileName::free(n);
|
||||
}
|
||||
|
||||
if (FileName::absolute(filename))
|
||||
@@ -1302,7 +1306,12 @@ const char *lookForSourceFile(const char *filename)
|
||||
n = FileName::combine(p, b);
|
||||
FileName::free(b);
|
||||
if (FileName::exists(n) == 2)
|
||||
return FileName::combine(n, "package.d");
|
||||
{
|
||||
const char *n2 = FileName::combine(n, "package.d");
|
||||
if (FileName::exists(n2) == 1)
|
||||
return n2;
|
||||
FileName::free(n2);
|
||||
}
|
||||
FileName::free(n);
|
||||
}
|
||||
return NULL;
|
||||
|
||||
Reference in New Issue
Block a user