mirror of
https://github.com/xomboverlord/ldc.git
synced 2026-01-15 04:13:14 +01:00
fixes #431 :: apply DMDFE 1.062; thanks SiegeLord
This commit is contained in:
12
dmd/access.c
12
dmd/access.c
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
26
dmd/attrib.c
26
dmd/attrib.c
@@ -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");
|
||||
}
|
||||
|
||||
44
dmd/cast.c
44
dmd/cast.c
@@ -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)
|
||||
|
||||
88
dmd/class.c
88
dmd/class.c
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
178
dmd/expression.c
178
dmd/expression.c
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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));
|
||||
|
||||
50
dmd/inline.c
50
dmd/inline.c
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
192
dmd/interpret.c
192
dmd/interpret.c
@@ -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
|
||||
|
||||
@@ -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))
|
||||
|
||||
106
dmd/lexer.c
106
dmd/lexer.c
@@ -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
|
||||
|
||||
21
dmd/lexer.h
21
dmd/lexer.h
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
13
dmd/module.c
13
dmd/module.c
@@ -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
|
||||
{
|
||||
|
||||
59
dmd/mtype.c
59
dmd/mtype.c
@@ -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)
|
||||
|
||||
41
dmd/mtype.h
41
dmd/mtype.h
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
151
dmd/statement.c
151
dmd/statement.c
@@ -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
|
||||
|
||||
@@ -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();
|
||||
|
||||
13
dmd/struct.c
13
dmd/struct.c
@@ -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");
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
14
dmd/utf.c
14
dmd/utf.c
@@ -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];
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user