fixes #431 :: apply DMDFE 1.062; thanks SiegeLord

This commit is contained in:
Moritz Warning
2010-09-27 00:06:28 +02:00
parent b032e3d1f7
commit c4e255206a
35 changed files with 918 additions and 335 deletions

View File

@@ -84,8 +84,8 @@ enum PROT ClassDeclaration::getAccess(Dsymbol *smember)
access_ret = smember->prot();
}
for (i = 0; i < baseclasses.dim; i++)
{ BaseClass *b = (BaseClass *)baseclasses.data[i];
for (i = 0; i < baseclasses->dim; i++)
{ BaseClass *b = (BaseClass *)baseclasses->data[i];
access = b->base->getAccess(smember);
switch (access)
@@ -153,8 +153,8 @@ static int accessCheckX(
ClassDeclaration *cdthis = dthis->isClassDeclaration();
if (cdthis)
{
for (int i = 0; i < cdthis->baseclasses.dim; i++)
{ BaseClass *b = (BaseClass *)cdthis->baseclasses.data[i];
for (int i = 0; i < cdthis->baseclasses->dim; i++)
{ BaseClass *b = (BaseClass *)cdthis->baseclasses->data[i];
enum PROT access;
access = b->base->getAccess(smember);
@@ -174,8 +174,8 @@ static int accessCheckX(
ClassDeclaration *cdthis = dthis->isClassDeclaration();
if (cdthis)
{
for (int i = 0; i < cdthis->baseclasses.dim; i++)
{ BaseClass *b = (BaseClass *)cdthis->baseclasses.data[i];
for (int i = 0; i < cdthis->baseclasses->dim; i++)
{ BaseClass *b = (BaseClass *)cdthis->baseclasses->data[i];
if (accessCheckX(smember, sfunc, b->base, cdscope))
return 1;

View File

@@ -237,7 +237,7 @@ struct ClassDeclaration : AggregateDeclaration
Array vtbl; // Array of FuncDeclaration's making up the vtbl[]
Array vtblFinal; // More FuncDeclaration's that aren't in vtbl[]
BaseClasses baseclasses; // Array of BaseClass's; first is super,
BaseClasses *baseclasses; // Array of BaseClass's; first is super,
// rest are Interface's
int interfaces_dim;

View File

@@ -1,5 +1,5 @@
// Copyright (c) 1999-2009 by Digital Mars
// Copyright (c) 1999-2010 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
@@ -34,6 +34,46 @@ extern int binary(const char *p , const char **tab, int high);
StringTable arrayfuncs;
#endif
/**********************************************
* Check that there are no uses of arrays without [].
*/
bool isArrayOpValid(Expression *e)
{
if (e->op == TOKslice)
return true;
Type *tb = e->type->toBasetype();
if ( (tb->ty == Tarray) || (tb->ty == Tsarray) )
{
switch (e->op)
{
case TOKadd:
case TOKmin:
case TOKmul:
case TOKdiv:
case TOKmod:
case TOKxor:
case TOKand:
case TOKor:
#if DMDV2
case TOKpow:
#endif
return isArrayOpValid(((BinExp *)e)->e1) && isArrayOpValid(((BinExp *)e)->e2);
case TOKcall:
return false; // TODO: Decide if [] is required after arrayop calls.
case TOKneg:
case TOKtilde:
return isArrayOpValid(((UnaExp *)e)->e1);
default:
return false;
}
}
return true;
}
/***********************************
* Construct the array operation expression.
*/
@@ -48,6 +88,12 @@ Expression *BinExp::arrayOp(Scope *sc)
return new ErrorExp();
}
if (!isArrayOpValid(e2))
{
e2->error("invalid array operation %s (did you forget a [] ?)", toChars());
return new ErrorExp();
}
Expressions *arguments = new Expressions();
/* The expression to generate an array operation for is mangled

View File

@@ -1,6 +1,6 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2009 by Digital Mars
// Copyright (c) 1999-2010 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
@@ -468,7 +468,27 @@ void StorageClassDeclaration::stcToCBuffer(OutBuffer *buf, StorageClass stc)
{
if (stc & table[i].stc)
{
buf->writestring(Token::toChars(table[i].tok));
enum TOK tok = table[i].tok;
#if DMDV2
if (tok == TOKat)
{ Identifier *id;
if (stc & STCproperty)
id = Id::property;
else if (stc & STCsafe)
id = Id::safe;
else if (stc & STCtrusted)
id = Id::trusted;
else if (stc & STCdisable)
id = Id::disable;
else
assert(0);
buf->writeByte('@');
buf->writestring(id->toChars());
}
else
#endif
buf->writestring(Token::toChars(tok));
buf->writeByte(' ');
}
}
@@ -963,7 +983,7 @@ void PragmaDeclaration::semantic(Scope *sc)
fprintf(stdmsg, "%.*s", (int)se->len, (char *)se->string);
}
else
fprintf(stdmsg, e->toChars());
fprintf(stdmsg, "%s", e->toChars());
}
fprintf(stdmsg, "\n");
}

View File

@@ -1,5 +1,5 @@
// Copyright (c) 1999-2009 by Digital Mars
// Copyright (c) 1999-2010 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
@@ -84,22 +84,25 @@ printf("%p %p type: %s to: %s\n", type->deco, t->deco, type->deco, t->deco);
//printf("%p %p %p\n", type->nextOf()->arrayOf(), type, t);
fflush(stdout);
#endif
if (!t->deco)
{ /* Can happen with:
* enum E { One }
* class A
* { static void fork(EDG dg) { dg(E.One); }
* alias void delegate(E) EDG;
* }
* Should eventually make it work.
*/
error("forward reference to type %s", t->toChars());
}
else if (t->reliesOnTident())
error("forward reference to type %s", t->reliesOnTident()->toChars());
if (t->ty != Terror && type->ty != Terror)
{
if (!t->deco)
{ /* Can happen with:
* enum E { One }
* class A
* { static void fork(EDG dg) { dg(E.One); }
* alias void delegate(E) EDG;
* }
* Should eventually make it work.
*/
error("forward reference to type %s", t->toChars());
}
else if (t->reliesOnTident())
error("forward reference to type %s", t->reliesOnTident()->toChars());
error("cannot implicitly convert expression (%s) of type %s to %s",
toChars(), type->toChars(), t->toChars());
error("cannot implicitly convert expression (%s) of type %s to %s",
toChars(), type->toChars(), t->toChars());
}
return new ErrorExp();
}
@@ -828,7 +831,7 @@ Expression *StringExp::castTo(Scope *sc, Type *t)
case X(Tchar, Twchar):
for (size_t u = 0; u < len;)
{ unsigned c;
char *p = utf_decodeChar((unsigned char *)se->string, len, &u, &c);
const char *p = utf_decodeChar((unsigned char *)se->string, len, &u, &c);
if (p)
error("%s", p);
else
@@ -841,7 +844,7 @@ Expression *StringExp::castTo(Scope *sc, Type *t)
case X(Tchar, Tdchar):
for (size_t u = 0; u < len;)
{ unsigned c;
char *p = utf_decodeChar((unsigned char *)se->string, len, &u, &c);
const char *p = utf_decodeChar((unsigned char *)se->string, len, &u, &c);
if (p)
error("%s", p);
buffer.write4(c);
@@ -853,7 +856,7 @@ Expression *StringExp::castTo(Scope *sc, Type *t)
case X(Twchar,Tchar):
for (size_t u = 0; u < len;)
{ unsigned c;
char *p = utf_decodeWchar((unsigned short *)se->string, len, &u, &c);
const char *p = utf_decodeWchar((unsigned short *)se->string, len, &u, &c);
if (p)
error("%s", p);
else
@@ -866,7 +869,7 @@ Expression *StringExp::castTo(Scope *sc, Type *t)
case X(Twchar,Tdchar):
for (size_t u = 0; u < len;)
{ unsigned c;
char *p = utf_decodeWchar((unsigned short *)se->string, len, &u, &c);
const char *p = utf_decodeWchar((unsigned short *)se->string, len, &u, &c);
if (p)
error("%s", p);
buffer.write4(c);
@@ -1550,6 +1553,7 @@ Expression *BinExp::typeCombine(Scope *sc)
type = Type::terror;
e1 = new ErrorExp();
e2 = new ErrorExp();
return new ErrorExp();
}
Lret:
if (!type)

View File

@@ -1,6 +1,6 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2009 by Digital Mars
// Copyright (c) 1999-2010 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
@@ -38,7 +38,10 @@ ClassDeclaration::ClassDeclaration(Loc loc, Identifier *id, BaseClasses *basecla
static char msg[] = "only object.d can define this reserved class name";
if (baseclasses)
this->baseclasses = *baseclasses;
// Actually, this is a transfer
this->baseclasses = baseclasses;
else
this->baseclasses = new BaseClasses();
baseClass = NULL;
interfaces_dim = 0;
@@ -46,7 +49,7 @@ ClassDeclaration::ClassDeclaration(Loc loc, Identifier *id, BaseClasses *basecla
vtblInterfaces = NULL;
//printf("ClassDeclaration(%s), dim = %d\n", id->toChars(), this->baseclasses.dim);
//printf("ClassDeclaration(%s), dim = %d\n", id->toChars(), this->baseclasses->dim);
// For forward references
type = new TypeClass(this);
@@ -209,12 +212,12 @@ Dsymbol *ClassDeclaration::syntaxCopy(Dsymbol *s)
cd->storage_class |= storage_class;
cd->baseclasses.setDim(this->baseclasses.dim);
for (int i = 0; i < cd->baseclasses.dim; i++)
cd->baseclasses->setDim(this->baseclasses->dim);
for (int i = 0; i < cd->baseclasses->dim; i++)
{
BaseClass *b = (BaseClass *)this->baseclasses.data[i];
BaseClass *b = (BaseClass *)this->baseclasses->data[i];
BaseClass *b2 = new BaseClass(b->type->syntaxCopy(), b->protection);
cd->baseclasses.data[i] = b2;
cd->baseclasses->data[i] = b2;
}
ScopeDsymbol::syntaxCopy(cd);
@@ -275,20 +278,20 @@ void ClassDeclaration::semantic(Scope *sc)
}
// Expand any tuples in baseclasses[]
for (i = 0; i < baseclasses.dim; )
{ BaseClass *b = (BaseClass *)baseclasses.data[i];
for (i = 0; i < baseclasses->dim; )
{ BaseClass *b = (BaseClass *)baseclasses->data[i];
b->type = b->type->semantic(loc, sc);
Type *tb = b->type->toBasetype();
if (tb->ty == Ttuple)
{ TypeTuple *tup = (TypeTuple *)tb;
enum PROT protection = b->protection;
baseclasses.remove(i);
baseclasses->remove(i);
size_t dim = Parameter::dim(tup->arguments);
for (size_t j = 0; j < dim; j++)
{ Parameter *arg = Parameter::getNth(tup->arguments, j);
b = new BaseClass(arg->type, protection);
baseclasses.insert(i + j, b);
baseclasses->insert(i + j, b);
}
}
else
@@ -296,17 +299,17 @@ void ClassDeclaration::semantic(Scope *sc)
}
// See if there's a base class as first in baseclasses[]
if (baseclasses.dim)
if (baseclasses->dim)
{ TypeClass *tc;
BaseClass *b;
Type *tb;
b = (BaseClass *)baseclasses.data[0];
b = (BaseClass *)baseclasses->data[0];
//b->type = b->type->semantic(loc, sc);
tb = b->type->toBasetype();
if (tb->ty != Tclass)
{ error("base type must be class or interface, not %s", b->type->toChars());
baseclasses.remove(0);
baseclasses->remove(0);
}
else
{
@@ -332,7 +335,7 @@ void ClassDeclaration::semantic(Scope *sc)
if (cdb == this)
{
error("circular inheritance");
baseclasses.remove(0);
baseclasses->remove(0);
goto L7;
}
}
@@ -365,12 +368,12 @@ void ClassDeclaration::semantic(Scope *sc)
// Treat the remaining entries in baseclasses as interfaces
// Check for errors, handle forward references
for (i = (baseClass ? 1 : 0); i < baseclasses.dim; )
for (i = (baseClass ? 1 : 0); i < baseclasses->dim; )
{ TypeClass *tc;
BaseClass *b;
Type *tb;
b = (BaseClass *)baseclasses.data[i];
b = (BaseClass *)baseclasses->data[i];
b->type = b->type->semantic(loc, sc);
tb = b->type->toBasetype();
if (tb->ty == Tclass)
@@ -380,7 +383,7 @@ void ClassDeclaration::semantic(Scope *sc)
if (!tc || !tc->sym->isInterfaceDeclaration())
{
error("base type must be interface, not %s", b->type->toChars());
baseclasses.remove(i);
baseclasses->remove(i);
continue;
}
else
@@ -399,7 +402,7 @@ void ClassDeclaration::semantic(Scope *sc)
// Check for duplicate interfaces
for (size_t j = (baseClass ? 1 : 0); j < i; j++)
{
BaseClass *b2 = (BaseClass *)baseclasses.data[j];
BaseClass *b2 = (BaseClass *)baseclasses->data[j];
if (b2->base == tc->sym)
error("inherits from duplicate interface %s", b2->base->toChars());
}
@@ -444,7 +447,7 @@ void ClassDeclaration::semantic(Scope *sc)
}
bt = tbase->semantic(loc, sc)->toBasetype();
b = new BaseClass(bt, PROTpublic);
baseclasses.shift(b);
baseclasses->shift(b);
assert(b->type->ty == Tclass);
tc = (TypeClass *)(b->type);
baseClass = tc->sym;
@@ -452,8 +455,8 @@ void ClassDeclaration::semantic(Scope *sc)
b->base = baseClass;
}
interfaces_dim = baseclasses.dim;
interfaces = (BaseClass **)baseclasses.data;
interfaces_dim = baseclasses->dim;
interfaces = (BaseClass **)baseclasses->data;
if (baseClass)
@@ -665,13 +668,14 @@ void ClassDeclaration::semantic(Scope *sc)
if (!ctor && baseClass && baseClass->ctor)
{
//printf("Creating default this(){} for class %s\n", toChars());
ctor = new CtorDeclaration(loc, 0, NULL, 0);
CtorDeclaration *ctor = new CtorDeclaration(loc, 0, NULL, 0);
ctor->fbody = new CompoundStatement(0, new Statements());
members->push(ctor);
ctor->addMember(sc, this, 1);
*sc = scsave; // why? What about sc->nofree?
sc->offset = structsize;
ctor->semantic(sc);
this->ctor = ctor;
defaultCtor = ctor;
}
@@ -731,12 +735,12 @@ void ClassDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
{
buf->printf("%s ", kind());
buf->writestring(toChars());
if (baseclasses.dim)
if (baseclasses->dim)
buf->writestring(" : ");
}
for (int i = 0; i < baseclasses.dim; i++)
for (int i = 0; i < baseclasses->dim; i++)
{
BaseClass *b = (BaseClass *)baseclasses.data[i];
BaseClass *b = (BaseClass *)baseclasses->data[i];
if (i)
buf->writeByte(',');
@@ -784,8 +788,8 @@ int ClassDeclaration::isBaseOf2(ClassDeclaration *cd)
if (!cd)
return 0;
//printf("ClassDeclaration::isBaseOf2(this = '%s', cd = '%s')\n", toChars(), cd->toChars());
for (int i = 0; i < cd->baseclasses.dim; i++)
{ BaseClass *b = (BaseClass *)cd->baseclasses.data[i];
for (int i = 0; i < cd->baseclasses->dim; i++)
{ BaseClass *b = (BaseClass *)cd->baseclasses->data[i];
if (b->base == this || isBaseOf2(b->base))
return 1;
@@ -809,7 +813,7 @@ int ClassDeclaration::isBaseOf(ClassDeclaration *cd, int *poffset)
/* cd->baseClass might not be set if cd is forward referenced.
*/
if (!cd->baseClass && cd->baseclasses.dim && !cd->isInterfaceDeclaration())
if (!cd->baseClass && cd->baseclasses->dim && !cd->isInterfaceDeclaration())
{
cd->error("base class is forward referenced by %s", toChars());
}
@@ -845,9 +849,9 @@ Dsymbol *ClassDeclaration::search(Loc loc, Identifier *ident, int flags)
int i;
for (i = 0; i < baseclasses.dim; i++)
for (i = 0; i < baseclasses->dim; i++)
{
BaseClass *b = (BaseClass *)baseclasses.data[i];
BaseClass *b = (BaseClass *)baseclasses->data[i];
if (b->base)
{
@@ -1096,20 +1100,20 @@ void InterfaceDeclaration::semantic(Scope *sc)
}
// Expand any tuples in baseclasses[]
for (i = 0; i < baseclasses.dim; )
{ BaseClass *b = (BaseClass *)baseclasses.data[0];
for (i = 0; i < baseclasses->dim; )
{ BaseClass *b = (BaseClass *)baseclasses->data[0];
b->type = b->type->semantic(loc, sc);
Type *tb = b->type->toBasetype();
if (tb->ty == Ttuple)
{ TypeTuple *tup = (TypeTuple *)tb;
enum PROT protection = b->protection;
baseclasses.remove(i);
baseclasses->remove(i);
size_t dim = Parameter::dim(tup->arguments);
for (size_t j = 0; j < dim; j++)
{ Parameter *arg = Parameter::getNth(tup->arguments, j);
b = new BaseClass(arg->type, protection);
baseclasses.insert(i + j, b);
baseclasses->insert(i + j, b);
}
}
else
@@ -1117,12 +1121,12 @@ void InterfaceDeclaration::semantic(Scope *sc)
}
// Check for errors, handle forward references
for (i = 0; i < baseclasses.dim; )
for (i = 0; i < baseclasses->dim; )
{ TypeClass *tc;
BaseClass *b;
Type *tb;
b = (BaseClass *)baseclasses.data[i];
b = (BaseClass *)baseclasses->data[i];
b->type = b->type->semantic(loc, sc);
tb = b->type->toBasetype();
if (tb->ty == Tclass)
@@ -1132,7 +1136,7 @@ void InterfaceDeclaration::semantic(Scope *sc)
if (!tc || !tc->sym->isInterfaceDeclaration())
{
error("base type must be interface, not %s", b->type->toChars());
baseclasses.remove(i);
baseclasses->remove(i);
continue;
}
else
@@ -1140,7 +1144,7 @@ void InterfaceDeclaration::semantic(Scope *sc)
// Check for duplicate interfaces
for (size_t j = 0; j < i; j++)
{
BaseClass *b2 = (BaseClass *)baseclasses.data[j];
BaseClass *b2 = (BaseClass *)baseclasses->data[j];
if (b2->base == tc->sym)
error("inherits from duplicate interface %s", b2->base->toChars());
}
@@ -1149,7 +1153,7 @@ void InterfaceDeclaration::semantic(Scope *sc)
if (b->base == this || isBaseOf2(b->base))
{
error("circular inheritance of interface");
baseclasses.remove(i);
baseclasses->remove(i);
continue;
}
if (!b->base->symtab)
@@ -1171,8 +1175,8 @@ void InterfaceDeclaration::semantic(Scope *sc)
i++;
}
interfaces_dim = baseclasses.dim;
interfaces = (BaseClass **)baseclasses.data;
interfaces_dim = baseclasses->dim;
interfaces = (BaseClass **)baseclasses->data;
interfaceSemantic(sc);

View File

@@ -1,6 +1,6 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2009 by Digital Mars
// Copyright (c) 1999-2010 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
@@ -1150,8 +1150,9 @@ Expression *Cast(Type *type, Type *to, Expression *e1)
}
else
{
error(loc, "cannot cast %s to %s", e1->type->toChars(), type->toChars());
e = new IntegerExp(loc, 0, Type::tint32);
if (type != Type::terror)
error(loc, "cannot cast %s to %s", e1->type->toChars(), type->toChars());
e = new ErrorExp();
}
return e;
}

View File

@@ -1,6 +1,6 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2009 by Digital Mars
// Copyright (c) 1999-2010 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
@@ -97,7 +97,10 @@ void Declaration::checkModify(Loc loc, Scope *sc, Type *t)
if (sc->incontract && isParameter())
error(loc, "cannot modify parameter '%s' in contract", toChars());
if (isCtorinit())
if (sc->incontract && isResult())
error(loc, "cannot modify result '%s' in contract", toChars());
if (isCtorinit() && !t->isMutable())
{ // It's only modifiable if inside the right constructor
Dsymbol *s = sc->func;
while (1)
@@ -479,11 +482,11 @@ void AliasDeclaration::semantic(Scope *sc)
#if DMDV2
type = type->addStorageClass(storage_class);
if (storage_class & (STCref | STCnothrow | STCpure))
if (storage_class & (STCref | STCnothrow | STCpure | STCdisable))
{ // For 'ref' to be attached to function types, and picked
// up by Type::resolve(), it has to go into sc.
sc = sc->push();
sc->stc |= storage_class & (STCref | STCnothrow | STCpure | STCshared);
sc->stc |= storage_class & (STCref | STCnothrow | STCpure | STCshared | STCdisable);
type->resolve(loc, sc, &e, &t, &s);
sc = sc->pop();
}
@@ -552,8 +555,8 @@ void AliasDeclaration::semantic(Scope *sc)
s = NULL;
}
}
if (!aliassym)
aliassym = s;
//printf("setting aliassym %s to %s %s\n", toChars(), s->kind(), s->toChars());
aliassym = s;
this->inSemantic = 0;
}
@@ -673,7 +676,10 @@ VarDeclaration::VarDeclaration(Loc loc, Type *type, Identifier *id, Initializer
#endif
this->loc = loc;
offset = 0;
noscope = 0;
noauto = 0;
#if DMDV2
isargptr = FALSE;
#endif
#if DMDV1
nestedref = 0;
#endif
@@ -951,11 +957,11 @@ void VarDeclaration::semantic(Scope *sc)
}
#endif
if (type->isscope() && !noscope)
if (type->isscope() && !noauto)
{
if (storage_class & (STCfield | STCout | STCref | STCstatic) || !fd)
{
error("globals, statics, fields, ref and out parameters cannot be scope");
error("globals, statics, fields, ref and out parameters cannot be auto");
}
if (!(storage_class & STCscope))
@@ -1394,7 +1400,7 @@ int VarDeclaration::isCTFE()
{
//printf("VarDeclaration::isCTFE(%p, '%s')\n", this, toChars());
//printf("%llx\n", storage_class);
return (storage_class & STCctfe) || !isDataseg();
return (storage_class & STCctfe) != 0; // || !isDataseg();
}
int VarDeclaration::hasPointers()
@@ -1420,7 +1426,7 @@ Expression *VarDeclaration::callScopeDtor(Scope *sc)
{ Expression *e = NULL;
//printf("VarDeclaration::callScopeDtor() %s\n", toChars());
if (storage_class & STCscope && !noscope)
if (storage_class & STCscope && !noauto)
{
for (ClassDeclaration *cd = type->isClassHandle();
cd;
@@ -1630,7 +1636,7 @@ TypeInfoTupleDeclaration::TypeInfoTupleDeclaration(Type *tinfo)
ThisDeclaration::ThisDeclaration(Loc loc, Type *t)
: VarDeclaration(loc, t, Id::This, NULL)
{
noscope = 1;
noauto = 1;
}
Dsymbol *ThisDeclaration::syntaxCopy(Dsymbol *s)

View File

@@ -265,7 +265,7 @@ struct VarDeclaration : Declaration
{
Initializer *init;
unsigned offset;
int noscope; // no scope semantics
int noauto; // no scope semantics
#if DMDV2
FuncDeclarations nestedrefs; // referenced by these lexically nested functions
bool isargptr; // if parameter that _argptr points to

View File

@@ -856,8 +856,8 @@ void ClassDeclaration::toDocBuffer(OutBuffer *buf)
buf->printf("%s $(DDOC_PSYMBOL %s)", kind(), toChars());
}
int any = 0;
for (int i = 0; i < baseclasses.dim; i++)
{ BaseClass *bc = (BaseClass *)baseclasses.data[i];
for (int i = 0; i < baseclasses->dim; i++)
{ BaseClass *bc = (BaseClass *)baseclasses->data[i];
if (bc->protection == PROTprivate)
continue;

View File

@@ -845,7 +845,7 @@ Dsymbol *ScopeDsymbol::search(Loc loc, Identifier *ident, int flags)
{
Declaration *d = s->isDeclaration();
if (d && d->protection == PROTprivate && !d->parent->isTemplateMixin())
error("%s is private", d->toPrettyChars());
error(loc, "%s is private", d->toPrettyChars());
}
}
return s;

View File

@@ -1059,18 +1059,24 @@ char *Expression::toChars()
void Expression::error(const char *format, ...)
{
va_list ap;
va_start(ap, format);
::verror(loc, format, ap);
va_end( ap );
if (type != Type::terror)
{
va_list ap;
va_start(ap, format);
::verror(loc, format, ap);
va_end( ap );
}
}
void Expression::warning(const char *format, ...)
{
va_list ap;
va_start(ap, format);
::vwarning(loc, format, ap);
va_end( ap );
if (type != Type::terror)
{
va_list ap;
va_start(ap, format);
::vwarning(loc, format, ap);
va_end( ap );
}
}
void Expression::rvalue()
@@ -1403,7 +1409,8 @@ IntegerExp::IntegerExp(Loc loc, dinteger_t value, Type *type)
if (type && !type->isscalar())
{
//printf("%s, loc = %d\n", toChars(), loc.linnum);
error("integral constant must be scalar type, not %s", type->toChars());
if (type->ty != Terror)
error("integral constant must be scalar type, not %s", type->toChars());
type = Type::terror;
}
this->type = type;
@@ -4160,8 +4167,8 @@ void VarExp::checkEscape()
// if reference type
if (tb->ty == Tarray || tb->ty == Tsarray || tb->ty == Tclass)
{
if (v->isScope() && !v->noscope)
error("escaping reference to scope local %s", v->toChars());
if (v->isScope() && !v->noauto)
error("escaping reference to auto local %s", v->toChars());
else if (v->storage_class & STCvariadic)
error("escaping reference to variadic parameter %s", v->toChars());
}
@@ -4824,9 +4831,9 @@ Expression *IsExp::semantic(Scope *sc)
else
{ ClassDeclaration *cd = ((TypeClass *)targ)->sym;
Parameters *args = new Parameters;
args->reserve(cd->baseclasses.dim);
for (size_t i = 0; i < cd->baseclasses.dim; i++)
{ BaseClass *b = (BaseClass *)cd->baseclasses.data[i];
args->reserve(cd->baseclasses->dim);
for (size_t i = 0; i < cd->baseclasses->dim; i++)
{ BaseClass *b = (BaseClass *)cd->baseclasses->data[i];
args->push(new Parameter(STCin, b->type, NULL, NULL));
}
tded = new TypeTuple(args);
@@ -5246,9 +5253,12 @@ int BinExp::canThrow()
void BinExp::incompatibleTypes()
{
error("incompatible types for ((%s) %s (%s)): '%s' and '%s'",
e1->toChars(), Token::toChars(op), e2->toChars(),
e1->type->toChars(), e2->type->toChars());
if (e1->type->toBasetype() != Type::terror &&
e2->type->toBasetype() != Type::terror
)
error("incompatible types for ((%s) %s (%s)): '%s' and '%s'",
e1->toChars(), Token::toChars(op), e2->toChars(),
e1->type->toChars(), e2->type->toChars());
}
/************************************************************/
@@ -5550,13 +5560,13 @@ Expression *DotIdExp::semantic(Scope *sc)
if (e1->op == TOKdottd)
{
error("template %s does not have property %s", e1->toChars(), ident->toChars());
return e1;
return new ErrorExp();
}
if (!e1->type)
{
error("expression %s does not have property %s", e1->toChars(), ident->toChars());
return e1;
return new ErrorExp();
}
if (eright->op == TOKimport) // also used for template alias's
@@ -6005,7 +6015,27 @@ L1:
Dsymbol *s = ti->inst->toAlias();
Declaration *v = s->isDeclaration();
if (v)
{ e = new DotVarExp(loc, eleft, v);
{
/* Fix for Bugzilla 4003
* The problem is a class template member function v returning a reference to the same
* type as the enclosing template instantiation. This results in a nested instantiation,
* which of course gets short circuited. The return type then gets set to
* the template instance type before instantiation, rather than after.
* We can detect this by the deco not being set. If so, go ahead and retry
* the return type semantic.
* The offending code is the return type from std.typecons.Tuple.slice:
* ref Tuple!(Types[from .. to]) slice(uint from, uint to)()
* {
* return *cast(typeof(return) *) &(field[from]);
* }
* and this line from the following unittest:
* auto s = a.slice!(1, 3);
* where s's type wound up not having semantic() run on it.
*/
if (v->type && !v->type->deco)
v->type = v->type->semantic(v->loc, sc);
e = new DotVarExp(loc, eleft, v);
e = e->semantic(sc);
return e;
}
@@ -7074,6 +7104,7 @@ Expression *PtrExp::semantic(Scope *sc)
default:
error("can only * a pointer, not a '%s'", e1->type->toChars());
case Terror:
return new ErrorExp();
}
rvalue();
@@ -7479,26 +7510,7 @@ void CastExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
to->toCBuffer(buf, NULL, hgs);
else
{
switch (mod)
{ case 0:
break;
case MODconst:
buf->writestring(Token::tochars[TOKconst]);
break;
case MODimmutable:
buf->writestring(Token::tochars[TOKimmutable]);
break;
case MODshared:
buf->writestring(Token::tochars[TOKshared]);
break;
case MODshared | MODconst:
buf->writestring(Token::tochars[TOKshared]);
buf->writeByte(' ');
buf->writestring(Token::tochars[TOKconst]);
break;
default:
assert(0);
}
MODtoBuffer(buf, mod);
}
#endif
buf->writeByte(')');
@@ -7550,7 +7562,9 @@ Expression *SliceExp::semantic(Scope *sc)
if (t->ty == Tpointer)
{
if (!lwr || !upr)
error("need upper and lower bound to slice pointer");
{ error("need upper and lower bound to slice pointer");
return new ErrorExp();
}
}
else if (t->ty == Tarray)
{
@@ -7611,11 +7625,15 @@ Expression *SliceExp::semantic(Scope *sc)
{ lwr = lwr->semantic(sc);
lwr = resolveProperties(sc, lwr);
lwr = lwr->implicitCastTo(sc, Type::tsize_t);
if (lwr->type == Type::terror)
goto Lerr;
}
if (upr)
{ upr = upr->semantic(sc);
upr = resolveProperties(sc, upr);
upr = upr->implicitCastTo(sc, Type::tsize_t);
if (lwr->type == Type::terror)
goto Lerr;
}
if (t->ty == Tsarray || t->ty == Tarray || t->ty == Ttuple)
@@ -7670,7 +7688,7 @@ Expression *SliceExp::semantic(Scope *sc)
else
{
error("string slice [%ju .. %ju] is out of bounds", i1, i2);
e = new IntegerExp(0);
goto Lerr;
}
return e;
}
@@ -7684,12 +7702,15 @@ Expression *SliceExp::semantic(Scope *sc)
return e;
Lerror:
if (e1->op == TOKerror)
return e1;
char *s;
if (t->ty == Tvoid)
s = e1->toChars();
else
s = t->toChars();
error("%s cannot be sliced with []", s);
Lerr:
e = new ErrorExp();
return e;
}
@@ -7798,7 +7819,9 @@ Expression *ArrayExp::semantic(Scope *sc)
if (t1->ty != Tclass && t1->ty != Tstruct)
{ // Convert to IndexExp
if (arguments->dim != 1)
error("only one index allowed to index %s", t1->toChars());
{ error("only one index allowed to index %s", t1->toChars());
goto Lerr;
}
e = new IndexExp(loc, e1, (Expression *)arguments->data[0]);
return e->semantic(sc);
}
@@ -7809,7 +7832,11 @@ Expression *ArrayExp::semantic(Scope *sc)
e = e->semantic(sc);
if (!e->type)
error("%s has no value", e->toChars());
{ error("%s has no value", e->toChars());
goto Lerr;
}
else if (e->type == Type::terror)
goto Lerr;
arguments->data[i] = (void *)e;
}
@@ -7819,9 +7846,12 @@ Expression *ArrayExp::semantic(Scope *sc)
e = op_overload(sc);
if (!e)
{ error("no [] operator overload for type %s", e1->type->toChars());
e = e1;
goto Lerr;
}
return e;
Lerr:
return new ErrorExp();
}
#if DMDV2
@@ -7987,9 +8017,11 @@ Expression *IndexExp::semantic(Scope *sc)
if (!e2->type)
{
error("%s has no value", e2->toChars());
e2->type = Type::terror;
goto Lerr;
}
e2 = resolveProperties(sc, e2);
if (e2->type == Type::terror)
goto Lerr;
if (t1->ty == Tsarray || t1->ty == Tarray || t1->ty == Ttuple)
sc = sc->pop();
@@ -8074,10 +8106,13 @@ Expression *IndexExp::semantic(Scope *sc)
default:
error("%s must be an array or pointer type, not %s",
e1->toChars(), e1->type->toChars());
type = Type::tint32;
break;
case Terror:
goto Lerr;
}
return e;
Lerr:
return new ErrorExp();
}
#if DMDV2
@@ -8408,6 +8443,14 @@ Expression *AssignExp::checkToBoolean()
/************************************************************/
ConstructExp::ConstructExp(Loc loc, Expression *e1, Expression *e2)
: AssignExp(loc, e1, e2)
{
op = TOKconstruct;
}
/************************************************************/
AddAssignExp::AddAssignExp(Loc loc, Expression *e1, Expression *e2)
: BinExp(loc, TOKaddass, sizeof(AddAssignExp), e1, e2)
{
@@ -8588,7 +8631,9 @@ Expression *CatAssignExp::semantic(Scope *sc)
{ SliceExp *se = (SliceExp *)e1;
if (se->e1->type->toBasetype()->ty == Tsarray)
error("cannot append to static array %s", se->e1->type->toChars());
{ error("cannot append to static array %s", se->e1->type->toChars());
return new ErrorExp();
}
}
e1 = e1->modifiableLvalue(sc, e1);
@@ -8638,7 +8683,8 @@ Expression *CatAssignExp::semantic(Scope *sc)
}
else
{
error("cannot append type %s to type %s", tb2->toChars(), tb1->toChars());
if (tb1 != Type::terror && tb2 != Type::terror)
error("cannot append type %s to type %s", tb2->toChars(), tb1->toChars());
e = new ErrorExp();
}
return e;
@@ -9710,20 +9756,30 @@ Expression *InExp::semantic(Scope *sc)
//type = Type::tboolean;
Type *t2b = e2->type->toBasetype();
if (t2b->ty != Taarray)
switch (t2b->ty)
{
error("rvalue of in expression must be an associative array, not %s", e2->type->toChars());
type = Type::terror;
}
else
{
TypeAArray *ta = (TypeAArray *)t2b;
case Taarray:
{
TypeAArray *ta = (TypeAArray *)t2b;
// Convert key to type of key
e1 = e1->implicitCastTo(sc, ta->index);
#if DMDV2
// Special handling for array keys
if (!arrayTypeCompatible(e1->loc, e1->type, ta->index))
#endif
{
// Convert key to type of key
e1 = e1->implicitCastTo(sc, ta->index);
}
// Return type is pointer to value
type = ta->nextOf()->pointerTo();
// Return type is pointer to value
type = ta->nextOf()->pointerTo();
break;
}
default:
error("rvalue of in expression must be an associative array, not %s", e2->type->toChars());
case Terror:
return new ErrorExp();
}
return this;
}

View File

@@ -606,6 +606,7 @@ struct NewExp : Expression
Type *newtype, Expressions *arguments);
Expression *syntaxCopy();
Expression *semantic(Scope *sc);
Expression *interpret(InterState *istate);
Expression *optimize(int result);
#if IN_DMD
elem *toElem(IRState *irs);
@@ -1399,6 +1400,11 @@ struct AssignExp : BinExp
AssignExp* isAssignExp() { return this; }
};
struct ConstructExp : AssignExp
{
ConstructExp(Loc loc, Expression *e1, Expression *e2);
};
#if IN_DMD
#define ASSIGNEXP_TOELEM elem *toElem(IRState *irs);
#elif IN_LLVM

View File

@@ -184,6 +184,8 @@ void FuncDeclaration::semantic(Scope *sc)
foverrides.setDim(0); // reset in case semantic() is being retried for this function
if (!originalType)
originalType = type;
if (!type->deco)
{
type = type->semantic(loc, sc);
@@ -1019,7 +1021,7 @@ void FuncDeclaration::semantic3(Scope *sc)
loc = fensure->loc;
v = new VarDeclaration(loc, type->nextOf(), outId, NULL);
v->noscope = 1;
v->noauto = 1;
#if DMDV2
if (!isVirtual())
v->storage_class |= STCconst;
@@ -1264,6 +1266,7 @@ void FuncDeclaration::semantic3(Scope *sc)
assert(v->init);
ExpInitializer *ie = v->init->isExpInitializer();
assert(ie);
ie->exp->op = TOKassign; // construction occurred in parameter processing
a->push(new ExpStatement(0, ie->exp));
}
}
@@ -1294,6 +1297,8 @@ void FuncDeclaration::semantic3(Scope *sc)
offset = p->type->size();
offset = (offset + 3) & ~3; // assume stack aligns on 4
Expression *e = new SymOffExp(0, p, offset);
e->type = Type::tvoidptr;
//e = e->semantic(sc);
e = new AssignExp(0, e1, e);
e->type = t;
a->push(new ExpStatement(0, e));

View File

@@ -1374,6 +1374,7 @@ int FuncDeclaration::canInline(int hasthis, int hdrscan)
}
#if !IN_LLVM
#if !SARRAYVALUE
/* If any parameters are Tsarray's (which are passed by reference)
* or out parameters (also passed by reference), don't do inlining.
*/
@@ -1382,10 +1383,11 @@ int FuncDeclaration::canInline(int hasthis, int hdrscan)
for (int i = 0; i < parameters->dim; i++)
{
VarDeclaration *v = (VarDeclaration *)parameters->data[i];
if (v->isOut() || v->isRef() || v->type->toBasetype()->ty == Tsarray)
if (/*v->isOut() || v->isRef() ||*/ v->type->toBasetype()->ty == Tsarray)
goto Lno;
}
}
#endif
#endif
memset(&ics, 0, sizeof(ics));
@@ -1517,6 +1519,7 @@ Expression *FuncDeclaration::doInline(InlineScanState *iss, Expression *ethis, A
ve->type = arg->type;
ei->exp = new AssignExp(vto->loc, ve, arg);
ei->exp->op = TOKconstruct;
ei->exp->type = ve->type;
//ve->type->print();
//arg->type->print();
@@ -1538,7 +1541,50 @@ Expression *FuncDeclaration::doInline(InlineScanState *iss, Expression *ethis, A
//eb->type->print();
//eb->print();
//eb->dump(0);
return Expression::combine(e, eb);
e = Expression::combine(e, eb);
/* There's a problem if what the function returns is used subsequently as an
* lvalue, as in a struct return that is then used as a 'this'.
* If we take the address of the return value, we will be taking the address
* of the original, not the copy. Fix this by assigning the return value to
* a temporary, then returning the temporary. If the temporary is used as an
* lvalue, it will work.
* This only happens with struct returns.
* See Bugzilla 2127 for an example.
*/
TypeFunction *tf = (TypeFunction*)type;
if (tf->next->ty == Tstruct)
{
/* Generate a new variable to hold the result and initialize it with the
* inlined body of the function:
* tret __inlineretval = e;
*/
ExpInitializer* ei = new ExpInitializer(loc, e);
Identifier* tmp = Identifier::generateId("__inlineretval");
VarDeclaration* vd = new VarDeclaration(loc, tf->next, tmp, ei);
vd->storage_class = 0;
vd->linkage = tf->linkage;
vd->parent = iss->fd;
VarExp *ve = new VarExp(loc, vd);
ve->type = tf->next;
ei->exp = new AssignExp(loc, ve, e);
ei->exp->op = TOKconstruct;
ei->exp->type = ve->type;
DeclarationExp* de = new DeclarationExp(0, vd);
de->type = Type::tvoid;
// Chain the two together:
// ( typeof(return) __inlineretval = ( inlined body )) , __inlineretval
e = Expression::combine(de, ve);
//fprintf(stderr, "CallExp::inlineScan: e = "); e->print();
}
return e;
}

View File

@@ -55,6 +55,7 @@ Expression *interpret_values(InterState *istate, Expression *earg, FuncDeclarati
ArrayLiteralExp *createBlockDuplicatedArrayLiteral(Type *type, Expression *elem, size_t dim);
Expression * resolveReferences(Expression *e, Expression *thisval, bool *isReference = NULL);
Expression *getVarExp(Loc loc, InterState *istate, Declaration *d);
/*************************************
* Attempt to interpret a function given the arguments.
@@ -118,18 +119,6 @@ Expression *FuncDeclaration::interpret(InterState *istate, Expressions *argument
return NULL;
}
// Ensure there are no lazy parameters
if (tf->parameters)
{ size_t dim = Parameter::dim(tf->parameters);
for (size_t i = 0; i < dim; i++)
{ Parameter *arg = Parameter::getNth(tf->parameters, i);
if (arg->storageClass & STClazy)
{ cantInterpret = 1;
return NULL;
}
}
}
InterState istatex;
istatex.caller = istate;
istatex.fd = this;
@@ -143,6 +132,11 @@ Expression *FuncDeclaration::interpret(InterState *istate, Expressions *argument
error("need 'this' to access member %s", toChars());
return NULL;
}
if (thisarg && !istate)
{ // Check that 'this' aleady has a value
if (thisarg->interpret(istate) == EXP_CANT_INTERPRET)
return NULL;
}
if (arguments)
{
dim = arguments->dim;
@@ -159,7 +153,15 @@ Expression *FuncDeclaration::interpret(InterState *istate, Expressions *argument
{ Expression *earg = (Expression *)arguments->data[i];
Parameter *arg = Parameter::getNth(tf->parameters, i);
if (arg->storageClass & (STCout | STCref | STClazy))
if (arg->storageClass & (STCout | STCref))
{
if (!istate)
{
earg->error("%s cannot be passed by reference at compile time", earg->toChars());
return NULL;
}
}
else if (arg->storageClass & STClazy)
{
}
else
@@ -173,7 +175,7 @@ Expression *FuncDeclaration::interpret(InterState *istate, Expressions *argument
*/
earg = ((AddrExp *)earg)->e1;
}
earg = earg->interpret(istate ? istate : &istatex);
earg = earg->interpret(istate); // ? istate : &istatex);
if (earg == EXP_CANT_INTERPRET)
{ cantInterpret = 1;
return NULL;
@@ -1251,7 +1253,7 @@ Expression *getVarExp(Loc loc, InterState *istate, Declaration *d)
if (e && !e->type)
e->type = v->type;
}
else if (v->isCTFE() && !v->value)
else if ((v->isCTFE() || (!v->isDataseg() && istate)) && !v->value)
{
if (v->init)
{
@@ -1266,9 +1268,13 @@ Expression *getVarExp(Loc loc, InterState *istate, Declaration *d)
else
e = v->type->defaultInitLiteral(loc);
}
else if (!v->isDataseg() && !istate) {
error(loc, "variable %s cannot be read at compile time", v->toChars());
return EXP_CANT_INTERPRET;
}
else
{ e = v->value;
if (!v->isCTFE())
if (!v->isCTFE() && v->isDataseg())
{ error(loc, "static variable %s cannot be read at compile time", v->toChars());
e = EXP_CANT_INTERPRET;
}
@@ -1579,6 +1585,24 @@ Expression *StructLiteralExp::interpret(InterState *istate)
return this;
}
Expression *NewExp::interpret(InterState *istate)
{
#if LOG
printf("NewExp::interpret() %s\n", toChars());
#endif
if (newtype->ty == Tarray && arguments && arguments->dim == 1)
{
Expression *lenExpr = ((Expression *)(arguments->data[0]))->interpret(istate);
if (lenExpr == EXP_CANT_INTERPRET)
return EXP_CANT_INTERPRET;
return createBlockDuplicatedArrayLiteral(newtype,
((TypeArray *)newtype)->next->defaultInitLiteral(),
lenExpr->toInteger());
}
error("Cannot interpret %s at compile time", toChars());
return EXP_CANT_INTERPRET;
}
Expression *UnaExp::interpretCommon(InterState *istate, Expression *(*fp)(Type *, Expression *))
{ Expression *e;
Expression *e1;
@@ -1841,7 +1865,7 @@ Expression * modifyStructField(Type *type, StructLiteralExp *se, size_t offset,
* set arr[index] = newval and return the new array.
*
*/
Expression * assignArrayElement(Expression *arr, Expression *index, Expression *newval)
Expression * assignArrayElement(Loc loc, Expression *arr, Expression *index, Expression *newval)
{
ArrayLiteralExp *ae = NULL;
AssocArrayLiteralExp *aae = NULL;
@@ -1859,7 +1883,7 @@ Expression * assignArrayElement(Expression *arr, Expression *index, Expression *
int elemi = index->toInteger();
if (elemi >= ae->elements->dim)
{
error("array index %d is out of bounds %s[0..%d]", elemi,
error(loc, "array index %d is out of bounds %s[0..%d]", elemi,
arr->toChars(), ae->elements->dim);
return EXP_CANT_INTERPRET;
}
@@ -1874,6 +1898,12 @@ Expression * assignArrayElement(Expression *arr, Expression *index, Expression *
/* Create new string literal reflecting updated elem
*/
int elemi = index->toInteger();
if (elemi >= se->len)
{
error(loc, "array index %d is out of bounds %s[0..%d]", elemi,
arr->toChars(), se->len);
return EXP_CANT_INTERPRET;
}
unsigned char *s;
s = (unsigned char *)mem.calloc(se->len + 1, se->sz);
memcpy(s, se->string, se->len * se->sz);
@@ -2087,6 +2117,8 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, fp_t fp, int post)
if (e1 == EXP_CANT_INTERPRET)
return e1;
assert(istate);
// ----------------------------------------------------
// Deal with read-modify-write assignments.
// Set 'newval' to the final assignment value
@@ -2097,7 +2129,7 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, fp_t fp, int post)
if (newval == EXP_CANT_INTERPRET)
return newval;
if (fp)
if (fp || e1->op == TOKarraylength)
{
// If it isn't a simple assignment, we need the existing value
Expression * oldval = e1->interpret(istate);
@@ -2105,17 +2137,72 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, fp_t fp, int post)
return EXP_CANT_INTERPRET;
while (oldval->op == TOKvar)
{
oldval = resolveReferences(oldval, istate->localThis);
oldval = oldval->interpret(istate);
if (oldval == EXP_CANT_INTERPRET) return oldval;
oldval = resolveReferences(oldval, istate->localThis);
oldval = oldval->interpret(istate);
if (oldval == EXP_CANT_INTERPRET)
return oldval;
}
if (fp)
{
newval = (*fp)(type, oldval, newval);
if (newval == EXP_CANT_INTERPRET)
{
error("Cannot interpret %s at compile time", toChars());
return EXP_CANT_INTERPRET;
}
// Determine the return value
e = Cast(type, type, post ? oldval : newval);
if (e == EXP_CANT_INTERPRET)
return e;
}
else
e = newval;
if (e1->op == TOKarraylength)
{
size_t oldlen = oldval->toInteger();
size_t newlen = newval->toInteger();
if (oldlen == newlen) // no change required -- we're done!
return e;
// Now change the assignment from arr.length = n into arr = newval
e1 = ((ArrayLengthExp *)e1)->e1;
if (oldlen != 0)
{ // Get the old array literal.
oldval = e1->interpret(istate);
while (oldval->op == TOKvar)
{ oldval = resolveReferences(oldval, istate->localThis);
oldval = oldval->interpret(istate);
}
}
Type *t = e1->type->toBasetype();
if (t->ty == Tarray)
{
Type *elemType= NULL;
elemType = ((TypeArray *)t)->next;
assert(elemType);
Expression *defaultElem = elemType->defaultInitLiteral();
Expressions *elements = new Expressions();
elements->setDim(newlen);
size_t copylen = oldlen < newlen ? oldlen : newlen;
ArrayLiteralExp *ae = (ArrayLiteralExp *)oldval;
for (size_t i = 0; i < copylen; i++)
elements->data[i] = ae->elements->data[i];
for (size_t i = copylen; i < newlen; i++)
elements->data[i] = defaultElem;
ArrayLiteralExp *aae = new ArrayLiteralExp(0, elements);
aae->type = t;
newval = aae;
}
else
{
error("%s is not yet supported at compile time", toChars());
return EXP_CANT_INTERPRET;
}
}
newval = (*fp)(type, oldval, newval);
if (newval == EXP_CANT_INTERPRET)
return EXP_CANT_INTERPRET;
// Determine the return value
e = Cast(type, type, post ? oldval : newval);
if (e == EXP_CANT_INTERPRET)
return e;
}
else if (e1->op != TOKslice)
{ /* Look for special case of struct being initialized with 0.
@@ -2136,7 +2223,7 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, fp_t fp, int post)
// Make sure we're not trying to modify a global or static variable
// We do this by locating the ultimate parent variable which gets modified.
VarDeclaration * ultimateVar = findParentVar(e1, istate->localThis);
if (ultimateVar && !ultimateVar->isCTFE())
if (ultimateVar && ultimateVar->isDataseg() && !ultimateVar->isCTFE())
{ // Can't modify global or static data
error("%s cannot be modified at compile time", ultimateVar->toChars());
return EXP_CANT_INTERPRET;
@@ -2283,7 +2370,9 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, fp_t fp, int post)
Expression *index = ie->e2->interpret(istate);
if (index == EXP_CANT_INTERPRET)
return EXP_CANT_INTERPRET;
newval = assignArrayElement(v->value, index, newval);
newval = assignArrayElement(loc, v->value, index, newval);
if (newval == EXP_CANT_INTERPRET)
return EXP_CANT_INTERPRET;
v->value = newval;
return e;
}
@@ -2444,7 +2533,7 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, fp_t fp, int post)
if (((PtrExp *)e1)->e1->op == TOKsymoff)
{ SymOffExp *soe = (SymOffExp *)((PtrExp *)e1)->e1;
VarDeclaration *v = soe->var->isVarDeclaration();
if (!v->isCTFE())
if (v->isDataseg() && !v->isCTFE())
{
error("%s cannot be modified at compile time", v->toChars());
return EXP_CANT_INTERPRET;
@@ -2743,17 +2832,22 @@ Expression *CommaExp::interpret(InterState *istate)
#if LOG
printf("CommaExp::interpret() %s\n", toChars());
#endif
CommaExp * firstComma = this;
while (firstComma->e1->op == TOKcomma)
firstComma = (CommaExp *)firstComma->e1;
// If it creates a variable, and there's no context for
// the variable to be created in, we need to create one now.
InterState istateComma;
if (!istate && firstComma->e1->op == TOKdeclaration)
istate = &istateComma;
// If the comma returns a temporary variable, it needs to be an lvalue
// (this is particularly important for struct constructors)
if (e1->op == TOKdeclaration && e2->op == TOKvar
&& ((DeclarationExp *)e1)->declaration == ((VarExp*)e2)->var)
{
// If there's no context for the variable to be created in,
// we need to create one now.
InterState istateComma;
if (!istate)
istate = &istateComma;
VarExp* ve = (VarExp *)e2;
VarDeclaration *v = ve->var->isVarDeclaration();
if (!v->init && !v->value)
@@ -2845,7 +2939,10 @@ Expression *IndexExp::interpret(InterState *istate)
e2 = this->e2->interpret(istate);
if (e2 == EXP_CANT_INTERPRET)
goto Lcant;
return Index(type, e1, e2);
e = Index(type, e1, e2);
if (e == EXP_CANT_INTERPRET)
error("%s cannot be interpreted at compile time", toChars());
return e;
Lcant:
return EXP_CANT_INTERPRET;
@@ -2887,7 +2984,10 @@ Expression *SliceExp::interpret(InterState *istate)
if (upr == EXP_CANT_INTERPRET)
goto Lcant;
return Slice(type, e1, lwr, upr);
e = Slice(type, e1, lwr, upr);
if (e == EXP_CANT_INTERPRET)
error("%s cannot be interpreted at compile time", toChars());
return e;
Lcant:
return EXP_CANT_INTERPRET;
@@ -2910,7 +3010,10 @@ Expression *CatExp::interpret(InterState *istate)
e2 = this->e2->interpret(istate);
if (e2 == EXP_CANT_INTERPRET)
goto Lcant;
return Cat(type, e1, e2);
e = Cat(type, e1, e2);
if (e == EXP_CANT_INTERPRET)
error("%s cannot be interpreted at compile time", toChars());
return e;
Lcant:
#if LOG
@@ -2930,7 +3033,10 @@ Expression *CastExp::interpret(InterState *istate)
e1 = this->e1->interpret(istate);
if (e1 == EXP_CANT_INTERPRET)
goto Lcant;
return Cast(type, to, e1);
e = Cast(type, to, e1);
if (e == EXP_CANT_INTERPRET)
error("%s cannot be interpreted at compile time", toChars());
return e;
Lcant:
#if LOG
@@ -3071,7 +3177,7 @@ Expression *DotVarExp::interpret(InterState *istate)
}
}
else
error("%s.%s is not yet implemented at compile time", ex->toChars(), var->toChars());
error("%s.%s is not yet implemented at compile time", e1->toChars(), var->toChars());
}
#if LOG

View File

@@ -71,8 +71,9 @@ void json_generate(Array *modules)
arg = fn->toChars();
}
else if (arg[0] == '-' && arg[1] == 0)
{ // Write to stdout
fwrite(buf.data, 1, buf.offset, stdout);
{ // Write to stdout; assume it succeeds
int n = fwrite(buf.data, 1, buf.offset, stdout);
assert(n == buf.offset); // keep gcc happy about return values
return;
}
// if (!FileName::absolute(arg))

View File

@@ -1,6 +1,6 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2009 by Digital Mars
// Copyright (c) 1999-2010 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
@@ -48,6 +48,8 @@ extern int HtmlNamedEntity(unsigned char *p, int length);
#define LS 0x2028 // UTF line separator
#define PS 0x2029 // UTF paragraph separator
void unittest_lexer();
/********************************************
* Do our own char maps
*/
@@ -384,6 +386,16 @@ TOK Lexer::peekNext()
return peek(&token)->value;
}
/***********************
* Look 2 tokens ahead at value.
*/
TOK Lexer::peekNext2()
{
Token *t = peek(&token);
return peek(t)->value;
}
/*********************************
* tk is on the opening (.
* Look ahead and return token that is past the closing ).
@@ -581,8 +593,10 @@ void Lexer::scan(Token *t)
t->value = escapeStringConstant(t,0);
return;
#if ! TEXTUAL_ASSEMBLY_OUT
case '\\': // escaped string literal
{ unsigned c;
unsigned char *pstart = p;
stringbuffer.reset();
do
@@ -609,8 +623,13 @@ void Lexer::scan(Token *t)
memcpy(t->ustring, stringbuffer.data, stringbuffer.offset);
t->postfix = 0;
t->value = TOKstring;
#if DMDV2
if (!global.params.useDeprecated)
error("Escape String literal %.*s is deprecated, use double quoted string literal \"%.*s\" instead", p - pstart, pstart, p - pstart, pstart);
#endif
return;
}
#endif
case 'l':
case 'L':
@@ -1148,6 +1167,27 @@ void Lexer::scan(Token *t)
t->value = TOKtilde; // ~
return;
#if DMDV2
case '^':
p++;
if (*p == '^')
{ p++;
if (*p == '=')
{ p++;
t->value = TOKpowass; // ^^=
}
else
t->value = TOKpow; // ^^
}
else if (*p == '=')
{ p++;
t->value = TOKxorass; // ^=
}
else
t->value = TOKxor; // ^
return;
#endif
#define SINGLE(c,tok) case c: p++; t->value = tok; return;
SINGLE('(', TOKlparen)
@@ -1161,7 +1201,9 @@ void Lexer::scan(Token *t)
SINGLE(';', TOKsemicolon)
SINGLE(':', TOKcolon)
SINGLE('$', TOKdollar)
#if DMDV2
SINGLE('@', TOKat)
#endif
#undef SINGLE
#define DOUBLE(c1,tok1,c2,tok2) \
@@ -1177,8 +1219,9 @@ void Lexer::scan(Token *t)
DOUBLE('*', TOKmul, '=', TOKmulass)
DOUBLE('%', TOKmod, '=', TOKmodass)
#if DMDV1
DOUBLE('^', TOKxor, '=', TOKxorass)
#endif
#undef DOUBLE
case '#':
@@ -1219,11 +1262,14 @@ void Lexer::scan(Token *t)
*/
unsigned Lexer::escapeSequence()
{ unsigned c;
{ unsigned c = *p;
#ifdef TEXTUAL_ASSEMBLY_OUT
return c;
#endif
int n;
int ndigits;
c = *p;
switch (c)
{
case '\'':
@@ -1580,6 +1626,10 @@ TOK Lexer::delimitedStringConstant(Token *t)
else
{ delimright = c;
nest = 0;
#if DMDV2
if (isspace(c))
error("delimiter cannot be whitespace");
#endif
}
}
else
@@ -1601,7 +1651,11 @@ TOK Lexer::delimitedStringConstant(Token *t)
}
else if (c == delimright)
goto Ldone;
if (startline && isalpha(c))
if (startline && isalpha(c)
#if DMDV2
&& hereid
#endif
)
{ Token t;
unsigned char *psave = p;
p--;
@@ -1710,6 +1764,7 @@ TOK Lexer::escapeStringConstant(Token *t, int wide)
c = *p++;
switch (c)
{
#if !( TEXTUAL_ASSEMBLY_OUT )
case '\\':
switch (*p)
{
@@ -1725,7 +1780,7 @@ TOK Lexer::escapeStringConstant(Token *t, int wide)
break;
}
break;
#endif
case '\n':
loc.linnum++;
break;
@@ -1786,6 +1841,7 @@ TOK Lexer::charConstant(Token *t, int wide)
c = *p++;
switch (c)
{
#if ! TEXTUAL_ASSEMBLY_OUT
case '\\':
switch (*p)
{
@@ -1805,7 +1861,7 @@ TOK Lexer::charConstant(Token *t, int wide)
break;
}
break;
#endif
case '\n':
L1:
loc.linnum++;
@@ -2954,6 +3010,7 @@ static Keyword keywords[] =
{ "pure", TOKpure },
{ "nothrow", TOKnothrow },
{ "__thread", TOKtls },
{ "__gshared", TOKgshared },
{ "__traits", TOKtraits },
{ "__overloadset", TOKoverloadset },
{ "__FILE__", TOKfile },
@@ -3058,6 +3115,8 @@ void Lexer::initKeywords()
Token::tochars[TOKcast] = "cast";
Token::tochars[TOKplusplus] = "++";
Token::tochars[TOKminusminus] = "--";
Token::tochars[TOKpreplusplus] = "++";
Token::tochars[TOKpreminusminus] = "--";
Token::tochars[TOKtype] = "type";
Token::tochars[TOKquestion] = "?";
Token::tochars[TOKneg] = "-";
@@ -3081,6 +3140,11 @@ void Lexer::initKeywords()
Token::tochars[TOKorass] = "|=";
Token::tochars[TOKidentifier] = "identifier";
#if DMDV2
Token::tochars[TOKat] = "@";
Token::tochars[TOKpow] = "^^";
Token::tochars[TOKpowass] = "^^=";
#endif
// For debugging
Token::tochars[TOKerror] = "error";
@@ -3101,4 +3165,30 @@ void Lexer::initKeywords()
Token::tochars[TOKon_scope_exit] = "scope(exit)";
Token::tochars[TOKon_scope_success] = "scope(success)";
Token::tochars[TOKon_scope_failure] = "scope(failure)";
#if UNITTEST
unittest_lexer();
#endif
}
#if UNITTEST
void unittest_lexer()
{
//printf("unittest_lexer()\n");
/* Not much here, just trying things out.
*/
const unsigned char text[] = "int";
Lexer lex1(NULL, (unsigned char *)text, 0, sizeof(text), 0, 0);
TOK tok;
tok = lex1.nextToken();
//printf("tok == %s, %d, %d\n", Token::toChars(tok), tok, TOKint32);
assert(tok == TOKint32);
tok = lex1.nextToken();
assert(tok == TOKeof);
tok = lex1.nextToken();
assert(tok == TOKeof);
}
#endif

View File

@@ -1,6 +1,6 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2008 by Digital Mars
// Copyright (c) 1999-2010 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
@@ -31,7 +31,8 @@ struct Module;
+ - += -=
* / % *= /= %=
& | ^ &= |= ^=
= ! ~
= ! ~ @
^^ ^^=
++ --
. -> : ,
? && ||
@@ -95,8 +96,9 @@ enum TOK
TOKplusplus, TOKminusminus, TOKconstruct, TOKblit,
TOKdot, TOKarrow, TOKcomma,
TOKquestion, TOKandand, TOKoror,
TOKpreplusplus, TOKpreminusminus,
// 104
// 106
// Numeric literals
TOKint32v, TOKuns32v,
TOKint64v, TOKuns64v,
@@ -124,7 +126,7 @@ enum TOK
TOKchar, TOKwchar, TOKdchar, TOKbit, TOKbool,
TOKcent, TOKucent,
// 150
// 152
// Aggregates
TOKstruct, TOKclass, TOKinterface, TOKunion, TOKenum, TOKimport,
TOKtypedef, TOKalias, TOKoverride, TOKdelegate, TOKfunction,
@@ -133,7 +135,7 @@ enum TOK
TOKalign, TOKextern, TOKprivate, TOKprotected, TOKpublic, TOKexport,
TOKstatic, /*TOKvirtual,*/ TOKfinal, TOKconst, TOKabstract, TOKvolatile,
TOKdebug, TOKdeprecated, TOKin, TOKout, TOKinout, TOKlazy,
TOKauto, TOKpackage, TOKmanifest,
TOKauto, TOKpackage, TOKmanifest, TOKimmutable,
// Statements
TOKif, TOKelse, TOKwhile, TOKfor, TOKdo, TOKswitch,
@@ -158,9 +160,13 @@ enum TOK
TOKpure,
TOKnothrow,
TOKtls,
TOKgshared,
TOKline,
TOKfile,
TOKshared,
TOKshared,
TOKat,
TOKpow,
TOKpowass,
#endif
// LDC specific
@@ -171,6 +177,8 @@ enum TOK
TOKMAX
};
#define TOKwild TOKinout
#define BASIC_TYPES \
TOKwchar: case TOKdchar: \
case TOKbit: case TOKbool: case TOKchar: \
@@ -278,6 +286,7 @@ struct Lexer
TOK nextToken();
TOK peekNext();
TOK peekNext2();
void scan(Token *t);
Token *peek(Token *t);
Token *peekPastParen(Token *t);

View File

@@ -63,7 +63,7 @@ Global::Global()
copyright = "Copyright (c) 1999-2010 by Digital Mars and Tomas Lindquist Olsen";
written = "written by Walter Bright and Tomas Lindquist Olsen";
version = "v1.061";
version = "v1.062";
ldc_version = LDC_REV;
llvm_version = LLVM_REV_STR;
global.structalign = 8;

View File

@@ -672,9 +672,16 @@ void Module::parse()
Dsymbol *prev = dst->lookup(ident);
assert(prev);
Module *mprev = prev->isModule();
assert(mprev);
error(loc, "from file %s conflicts with another module %s from file %s",
srcname, mprev->toChars(), mprev->srcfile->toChars());
if (mprev)
error(loc, "from file %s conflicts with another module %s from file %s",
srcname, mprev->toChars(), mprev->srcfile->toChars());
else
{
Package *pkg = prev->isPackage();
assert(pkg);
error(loc, "from file %s conflicts with package name %s",
srcname, pkg->toChars());
}
}
else
{

View File

@@ -231,6 +231,7 @@ void Type::init()
mangleChar[Twchar] = 'u';
mangleChar[Tdchar] = 'w';
// '@' shouldn't appear anywhere in the deco'd names
mangleChar[Tbit] = '@';
mangleChar[Tinstance] = '@';
mangleChar[Terror] = '@';
@@ -256,7 +257,7 @@ void Type::init()
for (i = 0; i < sizeof(basetab) / sizeof(basetab[0]); i++)
basic[basetab[i]] = new TypeBasic(basetab[i]);
basic[Terror] = basic[Tint32];
basic[Terror] = new TypeError();
tvoidptr = tvoid->pointerTo();
@@ -881,6 +882,24 @@ int Type::hasPointers()
return FALSE;
}
/* ============================= TypeError =========================== */
TypeError::TypeError()
: Type(Terror, NULL)
{
}
void TypeError::toCBuffer(OutBuffer *buf, Identifier *ident, HdrGenState *hgs)
{
buf->writestring("_error_");
}
d_uns64 TypeError::size(Loc loc) { return 1; }
Expression *TypeError::getProperty(Loc loc, Identifier *ident) { return new ErrorExp(); }
Expression *TypeError::dotExp(Scope *sc, Expression *e, Identifier *ident) { return new ErrorExp(); }
Expression *TypeError::defaultInit(Loc loc) { return new ErrorExp(); }
Expression *TypeError::defaultInitLiteral(Loc loc) { return new ErrorExp(); }
/* ============================= TypeBasic =========================== */
TypeBasic::TypeBasic(TY ty)
@@ -1436,9 +1455,6 @@ Expression *TypeBasic::defaultInit(Loc loc)
#endif
switch (ty)
{
case Tvoid:
return new IntegerExp(loc, value, Type::tbool);
case Tchar:
value = 0xFF;
break;
@@ -1458,6 +1474,10 @@ Expression *TypeBasic::defaultInit(Loc loc)
case Tcomplex64:
case Tcomplex80:
return getProperty(loc, Id::nan);
case Tvoid:
error(loc, "void does not have a default initializer");
return new ErrorExp();
}
return new IntegerExp(loc, value, this);
}
@@ -1530,6 +1550,13 @@ MATCH TypeBasic::implicitConvTo(Type *to)
if (this == to)
return MATCHexact;
#if DMDV2
if (ty == to->ty)
{
return (mod == to->mod) ? MATCHexact : MATCHconst;
}
#endif
if (ty == Tvoid || to->ty == Tvoid)
return MATCHnomatch;
if (to->ty == Tbool)
@@ -1545,16 +1572,18 @@ MATCH TypeBasic::implicitConvTo(Type *to)
return MATCHnomatch;
#if DMDV2
// If converting to integral
if (0 && global.params.Dversion > 1 && tob->flags & TFLAGSintegral)
// If converting from integral to integral
if (1 && tob->flags & TFLAGSintegral)
{ d_uns64 sz = size(0);
d_uns64 tosz = tob->size(0);
/* Can't convert to smaller size or, if same size, change sign
/* Can't convert to smaller size
*/
if (sz > tosz)
return MATCHnomatch;
/* Can't change sign if same size
*/
/*if (sz == tosz && (flags ^ tob->flags) & TFLAGSunsigned)
return MATCHnomatch;*/
}
@@ -2822,7 +2851,7 @@ int Type::covariant(Type *t)
// If t1n is forward referenced:
ClassDeclaration *cd = ((TypeClass *)t1n)->sym;
if (!cd->baseClass && cd->baseclasses.dim && !cd->isInterfaceDeclaration())
if (!cd->baseClass && cd->baseclasses->dim && !cd->isInterfaceDeclaration())
{
return 3;
}
@@ -3973,6 +4002,11 @@ Type *TypeTypeof::semantic(Loc loc, Scope *sc)
{
sc->intypeof++;
exp = exp->semantic(sc);
#if DMDV2
if (exp->type && exp->type->ty == Tfunction &&
((TypeFunction *)exp->type)->isproperty)
exp = resolveProperties(sc, exp);
#endif
sc->intypeof--;
if (exp->op == TOKtype)
{
@@ -4141,7 +4175,7 @@ Expression *TypeEnum::dotExp(Scope *sc, Expression *e, Identifier *ident)
if (ident == Id::max ||
ident == Id::min ||
ident == Id::init ||
ident == Id::stringof ||
ident == Id::mangleof ||
!sym->memtype
)
{
@@ -4186,6 +4220,10 @@ Expression *TypeEnum::getProperty(Loc loc, Identifier *ident)
Scope sc;
e = e->semantic(&sc);
}
else if (ident == Id::mangleof)
{
e = Type::getProperty(loc, ident);
}
else
{
if (!sym->memtype)
@@ -5448,7 +5486,8 @@ Type *TypeSlice::semantic(Loc loc, Scope *sc)
args->push(arg);
}
return new TypeTuple(args);
Type *t = (new TypeTuple(args))->semantic(loc, sc);
return t;
}
void TypeSlice::resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps)

View File

@@ -122,8 +122,10 @@ struct Type : Object
/* pick this order of numbers so switch statements work better
*/
#define MODconst 1 // type is const
#define MODimmutable 4 // type is invariant
#define MODimmutable 4 // type is immutable
#define MODshared 2 // type is shared
#define MODwild 8 // type is wild
#define MODmutable 0x10 // type is mutable (only used in wildcard matching)
char *deco;
Type *pto; // merged pointer to this type
Type *rto; // reference to this type
@@ -288,6 +290,43 @@ struct Type : Object
#endif
};
struct TypeError : Type
{
TypeError();
void toCBuffer(OutBuffer *buf, Identifier *ident, HdrGenState *hgs);
d_uns64 size(Loc loc);
Expression *getProperty(Loc loc, Identifier *ident);
Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
Expression *defaultInit(Loc loc);
Expression *defaultInitLiteral(Loc loc);
};
#if DMDV2
struct TypeNext : Type
{
Type *next;
TypeNext(TY ty, Type *next);
void toDecoBuffer(OutBuffer *buf, int flag);
void checkDeprecated(Loc loc, Scope *sc);
Type *reliesOnTident();
int hasWild();
unsigned wildMatch(Type *targ);
Type *nextOf();
Type *makeConst();
Type *makeInvariant();
Type *makeShared();
Type *makeSharedConst();
Type *makeWild();
Type *makeSharedWild();
Type *makeMutable();
MATCH constConv(Type *to);
void transitive();
};
#endif
struct TypeBasic : Type
{
const char *dstring;

View File

@@ -2652,6 +2652,7 @@ Initializer *Parser::parseInitializer()
{ t = peek(t);
if (t->value != TOKsemicolon &&
t->value != TOKcomma &&
t->value != TOKrbracket &&
t->value != TOKrcurly)
goto Lexpression;
break;
@@ -2976,7 +2977,7 @@ Statement *Parser::parseStatement(int flags)
s = new CompoundStatement(loc, statements);
if (flags & (PSscope | PScurlyscope))
s = new ScopeStatement(loc, s);
nextToken();
check(TOKrcurly, "compound statement");
break;
}
@@ -3638,7 +3639,7 @@ void Parser::check(Loc loc, enum TOK value)
void Parser::check(enum TOK value, const char *string)
{
if (token.value != value)
error("found '%s' when expecting '%s' following '%s'",
error("found '%s' when expecting '%s' following %s",
token.toChars(), Token::toChars(value), string);
nextToken();
}

View File

@@ -1,8 +1,8 @@
// Copyright (c) 1999-2009 by Digital Mars
// Copyright (c) 1999-2010 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// www.digitalmars.com
// http://www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
@@ -48,14 +48,15 @@
Array::Array()
{
data = NULL;
data = SMALLARRAYCAP ? &smallarray[0] : NULL;
dim = 0;
allocdim = 0;
allocdim = SMALLARRAYCAP;
}
Array::~Array()
{
mem.free(data);
if (data != &smallarray[0])
mem.free(data);
}
void Array::mark()
@@ -68,11 +69,30 @@ void Array::mark()
void Array::reserve(unsigned nentries)
{
//printf("Array::reserve: size = %d, offset = %d, nbytes = %d\n", size, offset, nbytes);
//printf("Array::reserve: dim = %d, allocdim = %d, nentries = %d\n", dim, allocdim, nentries);
if (allocdim - dim < nentries)
{
allocdim = dim + nentries;
data = (void **)mem.realloc(data, allocdim * sizeof(*data));
if (allocdim == 0)
{ // Not properly initialized, someone memset it to zero
if (nentries <= SMALLARRAYCAP)
{ allocdim = SMALLARRAYCAP;
data = SMALLARRAYCAP ? &smallarray[0] : NULL;
}
else
{ allocdim = nentries;
data = (void **)mem.malloc(allocdim * sizeof(*data));
}
}
else if (allocdim == SMALLARRAYCAP)
{
allocdim = dim + nentries;
data = (void **)mem.malloc(allocdim * sizeof(*data));
memcpy(data, &smallarray[0], dim * sizeof(*data));
}
else
{ allocdim = dim + nentries;
data = (void **)mem.realloc(data, allocdim * sizeof(*data));
}
}
}
@@ -88,7 +108,17 @@ void Array::setDim(unsigned newdim)
void Array::fixDim()
{
if (dim != allocdim)
{ data = (void **)mem.realloc(data, dim * sizeof(*data));
{
if (allocdim >= SMALLARRAYCAP)
{
if (dim <= SMALLARRAYCAP)
{
memcpy(&smallarray[0], data, dim * sizeof(*data));
mem.free(data);
}
else
data = (void **)mem.realloc(data, dim * sizeof(*data));
}
allocdim = dim;
}
}

View File

@@ -427,7 +427,9 @@ int Port::isInfinity(double r)
#undef signbit
int Port::Signbit(double r)
{
return (long)(((long *)&r)[1] & 0x80000000);
union { double d; long long ll; } u;
u.d = r;
return u.ll < 0;
}
double Port::floor(double d)

View File

@@ -318,11 +318,17 @@ struct OutBuffer : Object
struct Array : Object
{
unsigned dim;
unsigned allocdim;
void **data;
private:
unsigned allocdim;
#define SMALLARRAYCAP 1
void *smallarray[SMALLARRAYCAP]; // inline storage for small arrays
public:
Array();
~Array();
//Array(const Array&);
void mark();
char *toChars();

View File

@@ -377,7 +377,10 @@ void *scope_search_fp(void *arg, const char *seed)
/* If not in the lexer's string table, it certainly isn't in the symbol table.
* Doing this first is a lot faster.
*/
StringValue *sv = Lexer::stringtable.lookup(seed, strlen(seed));
size_t len = strlen(seed);
if (!len)
return NULL;
StringValue *sv = Lexer::stringtable.lookup(seed, len);
if (!sv)
return NULL;
Identifier *id = (Identifier *)sv->ptrvalue;

View File

@@ -75,18 +75,28 @@ Statement *Statement::semantic(Scope *sc)
return this;
}
// Same as semantic(), but do create a new scope
Statement *Statement::semanticNoScope(Scope *sc)
{
//printf("Statement::semanticNoScope() %s\n", toChars());
Statement *s = this;
if (!s->isCompoundStatement() && !s->isScopeStatement())
{
s = new CompoundStatement(loc, this); // so scopeCode() gets called
}
s = s->semantic(sc);
return s;
}
// Same as semanticNoScope(), but do create a new scope
Statement *Statement::semanticScope(Scope *sc, Statement *sbreak, Statement *scontinue)
{ Scope *scd;
Statement *s;
scd = sc->push();
{
Scope *scd = sc->push();
if (sbreak)
scd->sbreak = sbreak;
if (scontinue)
scd->scontinue = scontinue;
s = semantic(scd);
Statement *s = semanticNoScope(scd);
scd->pop();
return s;
}
@@ -394,6 +404,13 @@ CompoundStatement::CompoundStatement(Loc loc, Statement *s1, Statement *s2)
statements->push(s2);
}
CompoundStatement::CompoundStatement(Loc loc, Statement *s1)
: Statement(loc)
{
statements = new Statements();
statements->push(s1);
}
Statement *CompoundStatement::syntaxCopy()
{
Statements *a = new Statements();
@@ -859,6 +876,7 @@ Statement *ScopeStatement::semantic(Scope *sc)
if (sfinally)
{
//printf("adding sfinally\n");
sfinally = sfinally->semantic(sc);
statement = new CompoundStatement(loc, statement, sfinally);
}
}
@@ -1065,7 +1083,8 @@ int DoStatement::blockExit()
else
result = BEfallthru;
if (result & BEfallthru)
{ if (condition->canThrow())
{
if (condition->canThrow())
result |= BEthrow;
if (!(result & BEbreak) && condition->isBool(TRUE))
result &= ~BEfallthru;
@@ -1148,7 +1167,7 @@ Statement *ForStatement::semantic(Scope *sc)
sc->sbreak = this;
sc->scontinue = this;
if (body)
body = body->semantic(sc);
body = body->semanticNoScope(sc);
sc->noctor--;
sc->pop();
@@ -1266,10 +1285,14 @@ ForeachStatement::ForeachStatement(Loc loc, enum TOK op, Parameters *arguments,
this->value = NULL;
this->func = NULL;
this->cases = NULL;
this->gotos = NULL;
}
Statement *ForeachStatement::syntaxCopy()
{
//printf("ForeachStatement::syntaxCopy()\n");
Parameters *args = Parameter::arraySyntaxCopy(arguments);
Expression *exp = aggr->syntaxCopy();
ForeachStatement *s = new ForeachStatement(loc, op, args, exp,
@@ -1661,28 +1684,21 @@ Statement *ForeachStatement::semantic(Scope *sc)
#endif
case Tdelegate:
Lapply:
{ FuncDeclaration *fdapply;
Parameters *args;
{
Expression *ec;
Expression *e;
FuncLiteralDeclaration *fld;
Parameter *a;
Type *t;
Expression *flde;
Identifier *id;
Type *tret;
TypeDelegate* dgty;
TypeDelegate* dgty2;
TypeDelegate* fldeTy;
tret = func->type->nextOf();
Type *tret = func->type->nextOf();
// Need a variable to hold value from any return statements in body.
if (!sc->func->vresult && tret && tret != Type::tvoid)
{ VarDeclaration *v;
v = new VarDeclaration(loc, tret, Id::result, NULL);
v->noscope = 1;
{
VarDeclaration *v = new VarDeclaration(loc, tret, Id::result, NULL);
v->noauto = 1;
v->semantic(sc);
if (!sc->insert(v))
assert(0);
@@ -1693,9 +1709,10 @@ Statement *ForeachStatement::semantic(Scope *sc)
/* Turn body into the function literal:
* int delegate(ref T arg) { body }
*/
args = new Parameters();
Parameters *args = new Parameters();
for (size_t i = 0; i < dim; i++)
{ Parameter *arg = (Parameter *)arguments->data[i];
Identifier *id;
arg->type = arg->type->semantic(loc, sc);
if (arg->storageClass & STCref)
@@ -1703,34 +1720,33 @@ Statement *ForeachStatement::semantic(Scope *sc)
else
{ // Make a copy of the ref argument so it isn't
// a reference.
VarDeclaration *v;
Initializer *ie;
id = Lexer::uniqueId("__applyArg", i);
ie = new ExpInitializer(0, new IdentifierExp(0, id));
v = new VarDeclaration(0, arg->type, arg->ident, ie);
Initializer *ie = new ExpInitializer(0, new IdentifierExp(0, id));
VarDeclaration *v = new VarDeclaration(0, arg->type, arg->ident, ie);
s = new DeclarationStatement(0, v);
body = new CompoundStatement(loc, s, body);
}
a = new Parameter(STCref, arg->type, id, NULL);
args->push(a);
}
t = new TypeFunction(args, Type::tint32, 0, LINKd);
fld = new FuncLiteralDeclaration(loc, 0, t, TOKdelegate, this);
Type *t = new TypeFunction(args, Type::tint32, 0, LINKd);
cases = new Array();
gotos = new Array();
FuncLiteralDeclaration *fld = new FuncLiteralDeclaration(loc, 0, t, TOKdelegate, this);
fld->fbody = body;
flde = new FuncExp(loc, fld);
Expression *flde = new FuncExp(loc, fld);
flde = flde->semantic(sc);
// Resolve any forward referenced goto's
for (int i = 0; i < gotos.dim; i++)
{ CompoundStatement *cs = (CompoundStatement *)gotos.data[i];
for (size_t i = 0; i < gotos->dim; i++)
{ CompoundStatement *cs = (CompoundStatement *)gotos->data[i];
GotoStatement *gs = (GotoStatement *)cs->statements->data[0];
if (!gs->label->statement)
{ // 'Promote' it to this scope, and replace with a return
cases.push(gs);
s = new ReturnStatement(0, new IntegerExp(cases.dim + 1));
cases->push(gs);
s = new ReturnStatement(0, new IntegerExp(cases->dim + 1));
cs->statements->data[0] = (void *)s;
}
}
@@ -1779,6 +1795,7 @@ Statement *ForeachStatement::semantic(Scope *sc)
args->push(new Parameter(STCin, aaApply_dg, NULL, NULL));
aaApply_fd = FuncDeclaration::genCfunc(args, Type::tindex, "_aaApply");
}
FuncDeclaration *fdapply;
if (dim == 2) {
fdapply = aaApply2_fd;
fldeTy = aaApply2_dg;
@@ -1838,6 +1855,7 @@ Statement *ForeachStatement::semantic(Scope *sc)
#endif
assert(j < sizeof(fdname));
//LDC: Build arguments.
FuncDeclaration *fdapply;
Parameters* args = new Parameters;
args->push(new Parameter(STCin, tn->arrayOf(), NULL, NULL));
if (dim == 2) {
@@ -1899,7 +1917,7 @@ Statement *ForeachStatement::semantic(Scope *sc)
error("opApply() function for %s must return an int", tab->toChars());
}
if (!cases.dim)
if (!cases->dim)
// Easy case, a clean exit from the loop
s = new ExpStatement(loc, e);
else
@@ -1913,9 +1931,9 @@ Statement *ForeachStatement::semantic(Scope *sc)
a->push(s);
// cases 2...
for (int i = 0; i < cases.dim; i++)
for (int i = 0; i < cases->dim; i++)
{
s = (Statement *)cases.data[i];
s = (Statement *)cases->data[i];
s = new CaseStatement(0, new IntegerExp(i + 2), s);
a->push(s);
}
@@ -2064,7 +2082,9 @@ Statement *ForeachRangeStatement::semantic(Scope *sc)
/* Must infer types from lwr and upr
*/
AddExp ea(loc, lwr, upr);
ea.typeCombine(sc);
Expression *e = ea.typeCombine(sc);
if (e->op == TOKerror)
return this;
arg->type = ea.type->mutableOf();
lwr = ea.e1;
upr = ea.e2;
@@ -2265,7 +2285,7 @@ Statement *IfStatement::semantic(Scope *sc)
Type *t = arg->type ? arg->type : condition->type;
match = new VarDeclaration(loc, t, arg->ident, NULL);
match->noscope = 1;
match->noauto = 1;
match->semantic(scd);
if (!scd->insert(match))
assert(0);
@@ -2280,7 +2300,7 @@ Statement *IfStatement::semantic(Scope *sc)
}
else
scd = sc->push();
ifbody = ifbody->semantic(scd);
ifbody = ifbody->semanticNoScope(scd);
scd->pop();
cs1 = sc->callSuper;
@@ -2482,21 +2502,14 @@ Statement *PragmaStatement::semantic(Scope *sc)
Expression *e = (Expression *)args->data[i];
e = e->semantic(sc);
#if 1
e = e->optimize(WANTvalue | WANTinterpret);
#else
e = e->interpret(NULL);
if (e == EXP_CANT_INTERPRET)
fprintf(stdmsg, ((Expression *)args->data[i])->toChars());
else
#endif
if (e->op == TOKstring)
{
StringExp *se = (StringExp *)e;
fprintf(stdmsg, "%.*s", (int)se->len, (char *)se->string);
}
else
fprintf(stdmsg, e->toChars());
fprintf(stdmsg, "%s", e->toChars());
}
fprintf(stdmsg, "\n");
}
@@ -3368,18 +3381,18 @@ Statement *ReturnStatement::semantic(Scope *sc)
exp->op == TOKthis || exp->op == TOKsuper || exp->op == TOKnull ||
exp->op == TOKstring)
{
sc->fes->cases.push(this);
// Construct: return cases.dim+1;
s = new ReturnStatement(0, new IntegerExp(sc->fes->cases.dim + 1));
sc->fes->cases->push(this);
// Construct: return cases->dim+1;
s = new ReturnStatement(0, new IntegerExp(sc->fes->cases->dim + 1));
}
else if (fd->type->nextOf()->toBasetype() == Type::tvoid)
{
s = new ReturnStatement(0, NULL);
sc->fes->cases.push(s);
sc->fes->cases->push(s);
// Construct: { exp; return cases.dim + 1; }
// Construct: { exp; return cases->dim + 1; }
Statement *s1 = new ExpStatement(loc, exp);
Statement *s2 = new ReturnStatement(0, new IntegerExp(sc->fes->cases.dim + 1));
Statement *s2 = new ReturnStatement(0, new IntegerExp(sc->fes->cases->dim + 1));
s = new CompoundStatement(loc, s1, s2);
}
else
@@ -3388,7 +3401,7 @@ Statement *ReturnStatement::semantic(Scope *sc)
if (!fd->vresult)
{ // Declare vresult
VarDeclaration *v = new VarDeclaration(loc, tret, Id::result, NULL);
v->noscope = 1;
v->noauto = 1;
v->semantic(scx);
if (!scx->insert(v))
assert(0);
@@ -3397,14 +3410,13 @@ Statement *ReturnStatement::semantic(Scope *sc)
}
s = new ReturnStatement(0, new VarExp(0, fd->vresult));
sc->fes->cases.push(s);
sc->fes->cases->push(s);
// Construct: { vresult = exp; return cases.dim + 1; }
exp = new AssignExp(loc, new VarExp(0, fd->vresult), exp);
exp->op = TOKconstruct;
// Construct: { vresult = exp; return cases->dim + 1; }
exp = new ConstructExp(loc, new VarExp(0, fd->vresult), exp);
exp = exp->semantic(sc);
Statement *s1 = new ExpStatement(loc, exp);
Statement *s2 = new ReturnStatement(0, new IntegerExp(sc->fes->cases.dim + 1));
Statement *s2 = new ReturnStatement(0, new IntegerExp(sc->fes->cases->dim + 1));
s = new CompoundStatement(loc, s1, s2);
}
return s;
@@ -3529,8 +3541,8 @@ Statement *BreakStatement::semantic(Scope *sc)
* and 1 is break.
*/
Statement *s;
sc->fes->cases.push(this);
s = new ReturnStatement(0, new IntegerExp(sc->fes->cases.dim + 1));
sc->fes->cases->push(this);
s = new ReturnStatement(0, new IntegerExp(sc->fes->cases->dim + 1));
return s;
}
break; // can't break to it
@@ -3632,8 +3644,8 @@ Statement *ContinueStatement::semantic(Scope *sc)
* and 1 is break.
*/
Statement *s;
sc->fes->cases.push(this);
s = new ReturnStatement(0, new IntegerExp(sc->fes->cases.dim + 1));
sc->fes->cases->push(this);
s = new ReturnStatement(0, new IntegerExp(sc->fes->cases->dim + 1));
return s;
}
break; // can't continue to it
@@ -4083,7 +4095,7 @@ void Catch::semantic(Scope *sc)
type = new TypeIdentifier(0, Id::Object);
type = type->semantic(loc, sc);
if (!type->toBasetype()->isClassHandle())
error("can only catch class objects, not '%s'", type->toChars());
error(loc, "can only catch class objects, not '%s'", type->toChars());
else if (ident)
{
var = new VarDeclaration(loc, type, ident, NULL);
@@ -4136,17 +4148,12 @@ Statement *TryFinallyStatement::syntaxCopy()
Statement *TryFinallyStatement::semantic(Scope *sc)
{
//printf("TryFinallyStatement::semantic()\n");
Statement* oldScopeExit = sc->enclosingScopeExit;
sc->enclosingScopeExit = this;
body = body->semantic(sc);
sc->enclosingScopeExit = oldScopeExit;
sc = sc->push();
sc->enclosingFinally = this;
sc->sbreak = NULL;
sc->scontinue = NULL; // no break or continue out of finally block
finalbody = finalbody->semantic(sc);
finalbody = finalbody->semanticNoScope(sc);
sc->pop();
return this;
}
@@ -4414,7 +4421,7 @@ Statement *GotoStatement::semantic(Scope *sc)
a->push(this);
s = new CompoundStatement(loc, a);
sc->fes->gotos.push(s); // 'look at this later' list
sc->fes->gotos->push(s); // 'look at this later' list
return s;
}
if (label->statement && label->statement->enclosingFinally != sc->enclosingFinally)
@@ -4476,7 +4483,7 @@ Statement *LabelStatement::semantic(Scope *sc)
sc->callSuper |= CSXlabel;
sc->slabel = this;
if (statement)
statement = statement->semantic(sc);
statement = statement->semanticNoScope(sc);
sc->pop();
// LDC put in labmap

View File

@@ -1,6 +1,6 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2008 by Digital Mars
// Copyright (c) 1999-2010 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
@@ -118,6 +118,7 @@ struct Statement : Object
virtual ScopeStatement *isScopeStatement() { return NULL; }
virtual Statement *semantic(Scope *sc);
Statement *semanticScope(Scope *sc, Statement *sbreak, Statement *scontinue);
Statement *semanticNoScope(Scope *sc);
virtual int hasBreak();
virtual int hasContinue();
virtual int usesEH();
@@ -210,6 +211,7 @@ struct CompoundStatement : Statement
Statements *statements;
CompoundStatement(Loc loc, Statements *s);
CompoundStatement(Loc loc, Statement *s1);
CompoundStatement(Loc loc, Statement *s1, Statement *s2);
virtual Statement *syntaxCopy();
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
@@ -367,8 +369,8 @@ struct ForeachStatement : Statement
FuncDeclaration *func; // function we're lexically in
Array cases; // put breaks, continues, gotos and returns here
Array gotos; // forward referenced goto's go here
Array *cases; // put breaks, continues, gotos and returns here
Array *gotos; // forward referenced goto's go here
ForeachStatement(Loc loc, enum TOK op, Parameters *arguments, Expression *aggr, Statement *body);
Statement *syntaxCopy();

View File

@@ -200,11 +200,22 @@ void AggregateDeclaration::addField(Scope *sc, VarDeclaration *v)
memsize = v->type->size(loc);
memalignsize = v->type->alignsize();
xalign = v->type->memalign(sc->structalign);
#if 0
alignmember(xalign, memalignsize, &sc->offset);
v->offset = sc->offset;
sc->offset += memsize;
if (sc->offset > structsize)
structsize = sc->offset;
#else
unsigned ofs = sc->offset;
alignmember(xalign, memalignsize, &ofs);
v->offset = ofs;
ofs += memsize;
if (ofs > structsize)
structsize = ofs;
if (!isUnionDeclaration())
sc->offset = ofs;
#endif
if (sc->structalign < memalignsize)
memalignsize = sc->structalign;
if (alignsize < memalignsize)
@@ -337,8 +348,6 @@ void StructDeclaration::semantic(Scope *sc)
{
Dsymbol *s = (Dsymbol *)members->data[i];
s->semantic(sc2);
if (isUnionDeclaration())
sc2->offset = 0;
#if 0
if (sizeok == 2)
{ //printf("forward reference\n");

View File

@@ -75,6 +75,36 @@ Tuple *isTuple(Object *o)
return (Tuple *)o;
}
/**************************************
* Is this Object an error?
*/
int isError(Object *o)
{
Type *t = isType(o);
if (t)
return (t->ty == Terror);
Expression *e = isExpression(o);
if (e)
return (e->op == TOKerror);
Tuple *v = isTuple(o);
if (v)
return arrayObjectIsError(&v->objects);
return 0;
}
/**************************************
* Are any of the Objects an error?
*/
int arrayObjectIsError(Objects *args)
{
for (size_t i = 0; i < args->dim; i++)
{
Object *o = (Object *)args->data[i];
if (isError(o))
return 1;
}
return 0;
}
/***********************
* Try to get arg as a type.
@@ -1366,8 +1396,10 @@ FuncDeclaration *TemplateDeclaration::deduceFunctionTemplate(Scope *sc, Loc loc,
}
if (td_ambig)
{
error(loc, "matches more than one function template declaration:\n %s\nand:\n %s",
td_best->toChars(), td_ambig->toChars());
error(loc, "%s matches more than one template declaration, %s(%d):%s and %s(%d):%s",
toChars(),
td_best->loc.filename, td_best->loc.linnum, td_best->toChars(),
td_ambig->loc.filename, td_ambig->loc.linnum, td_ambig->toChars());
}
/* The best match is td_best with arguments tdargs.
@@ -3892,8 +3924,10 @@ TemplateDeclaration *TemplateInstance::findBestMatch(Scope *sc)
}
if (td_ambig)
{
error("%s matches more than one template declaration, %s and %s",
toChars(), td_best->toChars(), td_ambig->toChars());
error("%s matches more than one template declaration, %s(%d):%s and %s(%d):%s",
toChars(),
td_best->loc.filename, td_best->loc.linnum, td_best->toChars(),
td_ambig->loc.filename, td_ambig->loc.linnum, td_ambig->toChars());
}
/* The best match is td_best

View File

@@ -374,6 +374,8 @@ Expression *isExpression(Object *o);
Dsymbol *isDsymbol(Object *o);
Type *isType(Object *o);
Tuple *isTuple(Object *o);
int arrayObjectIsError(Objects *args);
int isError(Object *o);
Type *getType(Object *o);
Dsymbol *getDsymbol(Object *o);

View File

@@ -1,5 +1,5 @@
// utf.c
// Copyright (c) 2003 by Digital Mars
// Copyright (c) 2003-2010 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
@@ -28,12 +28,14 @@ int utf_isValidDchar(dchar_t c)
* !=NULL error message string
*/
char *utf_decodeChar(unsigned char *s, size_t len, size_t *pidx, dchar_t *presult)
const char *utf_decodeChar(unsigned char *s, size_t len, size_t *pidx, dchar_t *presult)
{
dchar_t V;
size_t i = *pidx;
unsigned char u = s[i];
//printf("utf_decodeChar(s = %02x, %02x, %02x len = %d)\n", u, s[1], s[2], len);
assert(i >= 0 && i < len);
if (u & 0x80)
@@ -117,10 +119,10 @@ char *utf_decodeChar(unsigned char *s, size_t len, size_t *pidx, dchar_t *presul
* !=NULL error message string
*/
char *utf_validateString(unsigned char *s, size_t len)
const char *utf_validateString(unsigned char *s, size_t len)
{
size_t idx;
char *err = NULL;
const char *err = NULL;
dchar_t dc;
for (idx = 0; idx < len; )
@@ -141,9 +143,9 @@ char *utf_validateString(unsigned char *s, size_t len)
*/
char *utf_decodeWchar(unsigned short *s, size_t len, size_t *pidx, dchar_t *presult)
const char *utf_decodeWchar(unsigned short *s, size_t len, size_t *pidx, dchar_t *presult)
{
char *msg;
const char *msg;
size_t i = *pidx;
unsigned u = s[i];

View File

@@ -1,6 +1,6 @@
// Compiler implementation of the D programming language
// utf.h
// Copyright (c) 2003-2006 by Digital Mars
// Copyright (c) 2003-2010 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
@@ -16,10 +16,10 @@ typedef unsigned dchar_t;
int utf_isValidDchar(dchar_t c);
char *utf_decodeChar(unsigned char *s, size_t len, size_t *pidx, dchar_t *presult);
char *utf_decodeWchar(unsigned short *s, size_t len, size_t *pidx, dchar_t *presult);
const char *utf_decodeChar(unsigned char *s, size_t len, size_t *pidx, dchar_t *presult);
const char *utf_decodeWchar(unsigned short *s, size_t len, size_t *pidx, dchar_t *presult);
char *utf_validateString(unsigned char *s, size_t len);
const char *utf_validateString(unsigned char *s, size_t len);
extern int isUniAlpha(dchar_t);