First merge of 2.064 beta.

This corresponds to DMD commit a913ce4bc59a94a022a27e390fc841f4aededffb.

Doesn't build Phobos yet.
This commit is contained in:
David Nadlinger
2013-10-19 23:21:53 +02:00
committed by Kai Nacke
parent c400d180d2
commit cb341586e3
130 changed files with 13566 additions and 9190 deletions

View File

@@ -135,13 +135,10 @@ int StructDeclaration::needOpAssign()
assert(v && v->isField());
if (v->storage_class & STCref)
continue;
Type *tv = v->type->toBasetype();
while (tv->ty == Tsarray)
{ TypeSArray *ta = (TypeSArray *)tv;
tv = tv->nextOf()->toBasetype();
}
Type *tv = v->type->baseElemOf();
if (tv->ty == Tstruct)
{ TypeStruct *ts = (TypeStruct *)tv;
{
TypeStruct *ts = (TypeStruct *)tv;
StructDeclaration *sd = ts->sym;
if (sd->needOpAssign())
goto Lneed;
@@ -164,7 +161,7 @@ Lneed:
* Note that s will be constructed onto the stack, and probably
* copy-constructed in caller site.
*
* If S has copy copy construction and/or destructor,
* If S has copy copy construction and/or destructor,
* the body will make bit-wise object swap:
* S __tmp = this; // bit copy
* this = s; // bit copy
@@ -192,19 +189,46 @@ FuncDeclaration *StructDeclaration::buildOpAssign(Scope *sc)
return NULL;
//printf("StructDeclaration::buildOpAssign() %s\n", toChars());
StorageClass stc = STCundefined;
StorageClass stc = STCsafe | STCnothrow | STCpure;
Loc declLoc = this->loc;
Loc loc = Loc(); // internal code should have no loc to prevent coverage
if (dtor || postblit)
{
if (dtor)
stc = mergeFuncAttrs(stc, dtor->storage_class);
}
else
{
for (size_t i = 0; i < fields.dim; i++)
{
Dsymbol *s = fields[i];
VarDeclaration *v = s->isVarDeclaration();
assert(v && v->isField());
if (v->storage_class & STCref)
continue;
Type *tv = v->type->baseElemOf();
if (tv->ty == Tstruct)
{
TypeStruct *ts = (TypeStruct *)tv;
StructDeclaration *sd = ts->sym;
if (FuncDeclaration *f = sd->hasIdentityOpAssign(sc))
stc = mergeFuncAttrs(stc, f->storage_class);
}
}
}
Parameters *fparams = new Parameters;
fparams->push(new Parameter(STCnodtor, type, Id::p, NULL));
Type *ftype = new TypeFunction(fparams, handle, FALSE, LINKd);
((TypeFunction *)ftype)->isref = 1;
Type *tf = new TypeFunction(fparams, handle, 0, LINKd, stc | STCref);
FuncDeclaration *fop = new FuncDeclaration(declLoc, Loc(), Id::assign, stc, ftype);
FuncDeclaration *fop = new FuncDeclaration(declLoc, Loc(), Id::assign, stc, tf);
Expression *e = NULL;
if (dtor || postblit)
if (stc & STCdisable)
{
}
else if (dtor || postblit)
{
/* Do swap this and rhs
* tmp = this; this = s; tmp.dtor();
@@ -258,15 +282,18 @@ FuncDeclaration *StructDeclaration::buildOpAssign(Scope *sc)
e = Expression::combine(e, ec);
}
}
Statement *s1 = new ExpStatement(loc, e);
if (e)
{
Statement *s1 = new ExpStatement(loc, e);
/* Add:
* return this;
*/
e = new ThisExp(loc);
Statement *s2 = new ReturnStatement(loc, e);
/* Add:
* return this;
*/
e = new ThisExp(loc);
Statement *s2 = new ReturnStatement(loc, e);
fop->fbody = new CompoundStatement(loc, s1, s2);
fop->fbody = new CompoundStatement(loc, s1, s2);
}
Dsymbol *s = fop;
#if 1 // workaround until fixing issue 1528
@@ -347,12 +374,10 @@ int StructDeclaration::needOpEquals()
goto Lneed;
if (tv->ty == Tclass)
goto Lneed;
while (tv->ty == Tsarray)
{ TypeSArray *ta = (TypeSArray *)tv;
tv = tv->nextOf()->toBasetype();
}
tv = tv->baseElemOf();
if (tv->ty == Tstruct)
{ TypeStruct *ts = (TypeStruct *)tv;
{
TypeStruct *ts = (TypeStruct *)tv;
StructDeclaration *sd = ts->sym;
if (sd->needOpEquals())
goto Lneed;
@@ -384,7 +409,7 @@ FuncDeclaration *AggregateDeclaration::hasIdentityOpEquals(Scope *sc)
Type *tthis;
if (i == 0) tthis = type;
if (i == 1) tthis = type->constOf();
if (i == 2) tthis = type->invariantOf();
if (i == 2) tthis = type->immutableOf();
if (i == 3) tthis = type->sharedOf();
if (i == 4) tthis = type->sharedConstOf();
if (i == 5) break;
@@ -449,9 +474,48 @@ FuncDeclaration *StructDeclaration::buildOpEquals(Scope *sc)
FuncDeclaration *StructDeclaration::buildXopEquals(Scope *sc)
{
if (!needOpEquals())
return NULL;
return NULL; // bitwise comparison would work
//printf("StructDeclaration::buildXopEquals() %s\n", toChars());
if (Dsymbol *eq = search_function(this, Id::eq))
{
if (FuncDeclaration *fd = eq->isFuncDeclaration())
{
TypeFunction *tfeqptr;
{
Scope sc;
/* const bool opEquals(ref const S s);
*/
Parameters *parameters = new Parameters;
parameters->push(new Parameter(STCref | STCconst, type, NULL, NULL));
tfeqptr = new TypeFunction(parameters, Type::tbool, 0, LINKd);
tfeqptr->mod = MODconst;
tfeqptr = (TypeFunction *)tfeqptr->semantic(Loc(), &sc);
}
fd = fd->overloadExactMatch(tfeqptr);
if (fd)
return fd;
}
}
if (!xerreq)
{
Identifier *id = Lexer::idPool("_xopEquals");
Expression *e = new IdentifierExp(loc, Id::empty);
e = new DotIdExp(loc, e, Id::object);
e = new DotIdExp(loc, e, id);
e = e->semantic(sc);
Dsymbol *s = getDsymbol(e);
if (!s)
{
::error(Loc(), "ICE: %s not found in object module. You must update druntime", id->toChars());
fatal();
}
assert(s);
xerreq = s->isFuncDeclaration();
}
Loc declLoc = Loc(); // loc is unnecessary so __xopEquals is never called directly
Loc loc = Loc(); // loc is unnecessary so errors are gagged
@@ -470,42 +534,143 @@ FuncDeclaration *StructDeclaration::buildXopEquals(Scope *sc)
fop->fbody = new ReturnStatement(loc, e);
size_t index = members->dim;
members->push(fop);
unsigned errors = global.startGagging(); // Do not report errors, even if the
unsigned oldspec = global.speculativeGag; // template opAssign fbody makes it.
global.speculativeGag = global.gag;
unsigned errors = global.startGagging(); // Do not report errors
Scope *sc2 = sc->push();
sc2->stc = 0;
sc2->linkage = LINKd;
sc2->speculative = true;
fop->semantic(sc2);
fop->semantic2(sc2);
fop->semantic3(sc2);
sc2->pop();
global.speculativeGag = oldspec;
if (global.endGagging(errors)) // if errors happened
{
members->remove(index);
if (!xerreq)
{
Expression *e = new IdentifierExp(loc, Id::empty);
e = new DotIdExp(loc, e, Id::object);
e = new DotIdExp(loc, e, Lexer::idPool("_xopEquals"));
e = e->semantic(sc);
Dsymbol *s = getDsymbol(e);
FuncDeclaration *fd = s->isFuncDeclaration();
xerreq = fd;
}
fop = xerreq;
return fop;
}
/******************************************
* Build __xopCmp for TypeInfo_Struct
* static bool __xopCmp(ref const S p, ref const S q)
* {
* return p.opCmp(q);
* }
*
* This is called by TypeInfo.compare(p1, p2). If the struct does not support
* const objects comparison, it will throw "not implemented" Error in runtime.
*/
FuncDeclaration *StructDeclaration::buildXopCmp(Scope *sc)
{
//printf("StructDeclaration::buildXopCmp() %s\n", toChars());
if (Dsymbol *cmp = search_function(this, Id::cmp))
{
if (FuncDeclaration *fd = cmp->isFuncDeclaration())
{
TypeFunction *tfcmpptr;
{
Scope sc;
/* const int opCmp(ref const S s);
*/
Parameters *parameters = new Parameters;
parameters->push(new Parameter(STCref | STCconst, type, NULL, NULL));
tfcmpptr = new TypeFunction(parameters, Type::tint32, 0, LINKd);
tfcmpptr->mod = MODconst;
tfcmpptr = (TypeFunction *)tfcmpptr->semantic(Loc(), &sc);
}
fd = fd->overloadExactMatch(tfcmpptr);
if (fd)
return fd;
}
}
else
fop->addMember(sc, this, 1);
{
#if 0 // FIXME: doesn't work for recursive alias this
/* Check opCmp member exists.
* Consider 'alias this', but except opDispatch.
*/
Expression *e = new DsymbolExp(loc, this);
e = new DotIdExp(loc, e, Id::cmp);
Scope *sc2 = sc->push();
e = e->trySemantic(sc2);
sc2->pop();
if (e)
{
Dsymbol *s = NULL;
switch (e->op)
{
case TOKoverloadset: s = ((OverExp *)e)->vars; break;
case TOKimport: s = ((ScopeExp *)e)->sds; break;
case TOKvar: s = ((VarExp *)e)->var; break;
default: break;
}
if (!s || s->ident != Id::cmp)
e = NULL; // there's no valid member 'opCmp'
}
if (!e)
return NULL; // bitwise comparison would work
/* Essentially, a struct which does not define opCmp is not comparable.
* At this time, typeid(S).compare might be correct that throwing "not implement" Error.
* But implementing it would break existing code, such as:
*
* struct S { int value; } // no opCmp
* int[S] aa; // Currently AA key uses bitwise comparison
* // (It's default behavior of TypeInfo_Strust.compare).
*
* Not sure we should fix this inconsistency, so just keep current behavior.
*/
#else
return NULL;
#endif
}
if (!xerrcmp)
{
Identifier *id = Lexer::idPool("_xopCmp");
Expression *e = new IdentifierExp(loc, Id::empty);
e = new DotIdExp(loc, e, Id::object);
e = new DotIdExp(loc, e, id);
e = e->semantic(sc);
Dsymbol *s = getDsymbol(e);
if (!s)
{
::error(Loc(), "ICE: %s not found in object module. You must update druntime", id->toChars());
fatal();
}
assert(s);
xerrcmp = s->isFuncDeclaration();
}
Loc declLoc = Loc(); // loc is unnecessary so __xopCmp is never called directly
Loc loc = Loc(); // loc is unnecessary so errors are gagged
Parameters *parameters = new Parameters;
parameters->push(new Parameter(STCref | STCconst, type, Id::p, NULL));
parameters->push(new Parameter(STCref | STCconst, type, Id::q, NULL));
TypeFunction *tf = new TypeFunction(parameters, Type::tint32, 0, LINKd);
tf = (TypeFunction *)tf->semantic(loc, sc);
Identifier *id = Lexer::idPool("__xopCmp");
FuncDeclaration *fop = new FuncDeclaration(declLoc, Loc(), id, STCstatic, tf);
Expression *e1 = new IdentifierExp(loc, Id::p);
Expression *e2 = new IdentifierExp(loc, Id::q);
Expression *e = new CallExp(loc, new DotIdExp(loc, e1, Id::cmp), e2);
fop->fbody = new ReturnStatement(loc, e);
unsigned errors = global.startGagging(); // Do not report errors
Scope *sc2 = sc->push();
sc2->stc = 0;
sc2->linkage = LINKd;
fop->semantic(sc2);
fop->semantic2(sc2);
sc2->pop();
if (global.endGagging(errors)) // if errors happened
fop = xerrcmp;
return fop;
}
@@ -542,14 +707,14 @@ FuncDeclaration *StructDeclaration::buildCpCtor(Scope *sc)
stc = mergeFuncAttrs(stc, postblit->storage_class);
if (stc & STCsafe) // change to @trusted for unsafe casts
stc = stc & ~STCsafe | STCtrusted;
stc = (stc & ~STCsafe) | STCtrusted;
Parameters *fparams = new Parameters;
fparams->push(new Parameter(STCref, type->constOf(), Id::p, NULL));
Type *ftype = new TypeFunction(fparams, Type::tvoid, 0, LINKd, stc);
ftype->mod = MODconst;
Type *tf = new TypeFunction(fparams, Type::tvoid, 0, LINKd, stc);
tf->mod = MODconst;
FuncDeclaration *fcp = new FuncDeclaration(declLoc, Loc(), Id::cpctor, stc, ftype);
FuncDeclaration *fcp = new FuncDeclaration(declLoc, Loc(), Id::cpctor, stc, tf);
if (!(stc & STCdisable))
{
@@ -612,12 +777,14 @@ FuncDeclaration *StructDeclaration::buildPostBlit(Scope *sc)
Type *tv = v->type->toBasetype();
dinteger_t dim = 1;
while (tv->ty == Tsarray)
{ TypeSArray *ta = (TypeSArray *)tv;
dim *= ((TypeSArray *)tv)->dim->toInteger();
tv = tv->nextOf()->toBasetype();
{
TypeSArray *tsa = (TypeSArray *)tv;
dim *= tsa->dim->toInteger();
tv = tsa->next->toBasetype();
}
if (tv->ty == Tstruct)
{ TypeStruct *ts = (TypeStruct *)tv;
{
TypeStruct *ts = (TypeStruct *)tv;
StructDeclaration *sd = ts->sym;
if (sd->postblit && dim)
{
@@ -726,12 +893,14 @@ FuncDeclaration *AggregateDeclaration::buildDtor(Scope *sc)
Type *tv = v->type->toBasetype();
dinteger_t dim = 1;
while (tv->ty == Tsarray)
{ TypeSArray *ta = (TypeSArray *)tv;
dim *= ((TypeSArray *)tv)->dim->toInteger();
tv = tv->nextOf()->toBasetype();
{
TypeSArray *tsa = (TypeSArray *)tv;
dim *= tsa->dim->toInteger();
tv = tsa->next->toBasetype();
}
if (tv->ty == Tstruct)
{ TypeStruct *ts = (TypeStruct *)tv;
{
TypeStruct *ts = (TypeStruct *)tv;
StructDeclaration *sd = ts->sym;
if (sd->dtor && dim)
{