[svn r23] * Updated to DMD 1.021

This commit is contained in:
Tomas Lindquist Olsen
2007-10-04 03:42:56 +02:00
parent 8004219a69
commit 1cb583cbca
24 changed files with 638 additions and 179 deletions

View File

@@ -192,6 +192,28 @@ void AttribDeclaration::toObjFile()
}
}
int AttribDeclaration::cvMember(unsigned char *p)
{
unsigned i;
int nwritten = 0;
int n;
Array *d = include(NULL, NULL);
if (d)
{
for (i = 0; i < d->dim; i++)
{ Dsymbol *s;
s = (Dsymbol *)d->data[i];
n = s->cvMember(p);
if (p)
p += n;
nwritten += n;
}
}
return nwritten;
}
int AttribDeclaration::hasPointers()
{
Array *d = include(NULL, NULL);

View File

@@ -51,6 +51,7 @@ struct AttribDeclaration : Dsymbol
AttribDeclaration *isAttribDeclaration() { return this; }
void toObjFile(); // compile to .obj file
int cvMember(unsigned char *p);
};
struct StorageClassDeclaration: AttribDeclaration

View File

@@ -658,77 +658,85 @@ Expression *NullExp::castTo(Scope *sc, Type *t)
Expression *StringExp::castTo(Scope *sc, Type *t)
{
/* This follows copy-on-write; any changes to 'this'
* will result in a copy.
* The this->string member is considered immutable.
*/
StringExp *se;
Type *tb;
int unique;
int copied = 0;
//printf("StringExp::castTo(t = %s), '%s' committed = %d\n", t->toChars(), toChars(), committed);
if (!committed && t->ty == Tpointer && t->next->ty == Tvoid)
if (!committed && t->ty == Tpointer && t->nextOf()->ty == Tvoid)
{
error("cannot convert string literal to void*");
}
se = this;
if (!committed)
{ se = (StringExp *)copy();
se->committed = 1;
copied = 1;
}
if (type == t)
{
return se;
}
tb = t->toBasetype();
//printf("\ttype = %s\n", type->toChars());
if (tb->ty == Tdelegate && type->toBasetype()->ty != Tdelegate)
return Expression::castTo(sc, t);
se = this;
unique = 0;
if (!committed)
Type *typeb = type->toBasetype();
if (typeb == tb)
{
// Copy when committing the type
void *s;
s = (unsigned char *)mem.malloc((len + 1) * sz);
memcpy(s, string, (len + 1) * sz);
se = new StringExp(loc, s, len);
se->type = type;
se->sz = sz;
se->committed = 0;
unique = 1; // this is the only instance
}
se->type = type->toBasetype();
if (tb == se->type)
{ se->type = t;
se->committed = 1;
if (!copied)
{ se = (StringExp *)copy();
copied = 1;
}
se->type = t;
return se;
}
if (tb->ty != Tsarray && tb->ty != Tarray && tb->ty != Tpointer)
{ se->committed = 1;
{ if (!copied)
{ se = (StringExp *)copy();
copied = 1;
}
goto Lcast;
}
if (se->type->ty != Tsarray && se->type->ty != Tarray && se->type->ty != Tpointer)
{ se->committed = 1;
goto Lcast;
}
if (se->committed == 1)
{
if (se->type->next->size() == tb->next->size())
{ se->type = t;
return se;
if (typeb->ty != Tsarray && typeb->ty != Tarray && typeb->ty != Tpointer)
{ if (!copied)
{ se = (StringExp *)copy();
copied = 1;
}
goto Lcast;
}
se->committed = 1;
if (typeb->nextOf()->size() == tb->nextOf()->size())
{
if (!copied)
{ se = (StringExp *)copy();
copied = 1;
}
if (tb->ty == Tsarray)
goto L2; // handle possible change in static array dimension
se->type = t;
return se;
}
int tfty;
int ttty;
char *p;
size_t u;
unsigned c;
size_t newlen;
if (committed)
goto Lcast;
#define X(tf,tt) ((tf) * 256 + (tt))
{
OutBuffer buffer;
newlen = 0;
tfty = se->type->next->toBasetype()->ty;
ttty = tb->next->toBasetype()->ty;
size_t newlen = 0;
int tfty = typeb->nextOf()->toBasetype()->ty;
int ttty = tb->nextOf()->toBasetype()->ty;
switch (X(tfty, ttty))
{
case X(Tchar, Tchar):
@@ -737,9 +745,9 @@ Expression *StringExp::castTo(Scope *sc, Type *t)
break;
case X(Tchar, Twchar):
for (u = 0; u < len;)
{
p = utf_decodeChar((unsigned char *)se->string, len, &u, &c);
for (size_t u = 0; u < len;)
{ unsigned c;
char *p = utf_decodeChar((unsigned char *)se->string, len, &u, &c);
if (p)
error("%s", p);
else
@@ -750,9 +758,9 @@ Expression *StringExp::castTo(Scope *sc, Type *t)
goto L1;
case X(Tchar, Tdchar):
for (u = 0; u < len;)
{
p = utf_decodeChar((unsigned char *)se->string, len, &u, &c);
for (size_t u = 0; u < len;)
{ unsigned c;
char *p = utf_decodeChar((unsigned char *)se->string, len, &u, &c);
if (p)
error("%s", p);
buffer.write4(c);
@@ -762,9 +770,9 @@ Expression *StringExp::castTo(Scope *sc, Type *t)
goto L1;
case X(Twchar,Tchar):
for (u = 0; u < len;)
{
p = utf_decodeWchar((unsigned short *)se->string, len, &u, &c);
for (size_t u = 0; u < len;)
{ unsigned c;
char *p = utf_decodeWchar((unsigned short *)se->string, len, &u, &c);
if (p)
error("%s", p);
else
@@ -775,9 +783,9 @@ Expression *StringExp::castTo(Scope *sc, Type *t)
goto L1;
case X(Twchar,Tdchar):
for (u = 0; u < len;)
{
p = utf_decodeWchar((unsigned short *)se->string, len, &u, &c);
for (size_t u = 0; u < len;)
{ unsigned c;
char *p = utf_decodeWchar((unsigned short *)se->string, len, &u, &c);
if (p)
error("%s", p);
buffer.write4(c);
@@ -787,9 +795,9 @@ Expression *StringExp::castTo(Scope *sc, Type *t)
goto L1;
case X(Tdchar,Tchar):
for (u = 0; u < len; u++)
for (size_t u = 0; u < len; u++)
{
c = ((unsigned *)se->string)[u];
unsigned c = ((unsigned *)se->string)[u];
if (!utf_isValidDchar(c))
error("invalid UCS-32 char \\U%08x", c);
else
@@ -801,9 +809,9 @@ Expression *StringExp::castTo(Scope *sc, Type *t)
goto L1;
case X(Tdchar,Twchar):
for (u = 0; u < len; u++)
for (size_t u = 0; u < len; u++)
{
c = ((unsigned *)se->string)[u];
unsigned c = ((unsigned *)se->string)[u];
if (!utf_isValidDchar(c))
error("invalid UCS-32 char \\U%08x", c);
else
@@ -815,22 +823,23 @@ Expression *StringExp::castTo(Scope *sc, Type *t)
goto L1;
L1:
if (!unique)
se = new StringExp(loc, NULL, 0);
if (!copied)
{ se = (StringExp *)copy();
copied = 1;
}
se->string = buffer.extractData();
se->len = newlen;
se->sz = tb->next->size();
se->sz = tb->nextOf()->size();
break;
default:
if (se->type->next->size() == tb->next->size())
{ se->type = t;
return se;
}
assert(typeb->nextOf()->size() != tb->nextOf()->size());
goto Lcast;
}
}
#undef X
L2:
assert(copied);
// See if need to truncate or extend the literal
if (tb->ty == Tsarray)
@@ -842,28 +851,18 @@ Expression *StringExp::castTo(Scope *sc, Type *t)
// Changing dimensions
if (dim2 != se->len)
{
// Copy when changing the string literal
unsigned newsz = se->sz;
void *s;
int d;
if (unique && dim2 < se->len)
{ se->len = dim2;
// Add terminating 0
memset((unsigned char *)se->string + dim2 * newsz, 0, newsz);
}
else
{
// Copy when changing the string literal
void *s;
int d;
d = (dim2 < se->len) ? dim2 : se->len;
s = (unsigned char *)mem.malloc((dim2 + 1) * newsz);
memcpy(s, se->string, d * newsz);
// Extend with 0, add terminating 0
memset((char *)s + d * newsz, 0, (dim2 + 1 - d) * newsz);
se = new StringExp(loc, s, dim2);
se->committed = 1; // it now has a firm type
se->sz = newsz;
}
d = (dim2 < se->len) ? dim2 : se->len;
s = (unsigned char *)mem.malloc((dim2 + 1) * newsz);
memcpy(s, se->string, d * newsz);
// Extend with 0, add terminating 0
memset((char *)s + d * newsz, 0, (dim2 + 1 - d) * newsz);
se->string = s;
se->len = dim2;
}
}
se->type = t;
@@ -871,7 +870,7 @@ Expression *StringExp::castTo(Scope *sc, Type *t)
Lcast:
Expression *e = new CastExp(loc, se, t);
e->type = t;
e->type = t; // so semantic() won't be run on e
return e;
}

View File

@@ -668,7 +668,35 @@ Expression *Equal(enum TOK op, Type *type, Expression *e1, Expression *e2)
assert(op == TOKequal || op == TOKnotequal);
if (e1->op == TOKstring && e2->op == TOKstring)
if (e1->op == TOKnull)
{
if (e2->op == TOKnull)
cmp = 1;
else if (e2->op == TOKstring)
{ StringExp *es2 = (StringExp *)e2;
cmp = (0 == es2->len);
}
else if (e2->op == TOKarrayliteral)
{ ArrayLiteralExp *es2 = (ArrayLiteralExp *)e2;
cmp = !es2->elements || (0 == es2->elements->dim);
}
else
return EXP_CANT_INTERPRET;
}
else if (e2->op == TOKnull)
{
if (e1->op == TOKstring)
{ StringExp *es1 = (StringExp *)e1;
cmp = (0 == es1->len);
}
else if (e1->op == TOKarrayliteral)
{ ArrayLiteralExp *es1 = (ArrayLiteralExp *)e1;
cmp = !es1->elements || (0 == es1->elements->dim);
}
else
return EXP_CANT_INTERPRET;
}
else if (e1->op == TOKstring && e2->op == TOKstring)
{ StringExp *es1 = (StringExp *)e1;
StringExp *es2 = (StringExp *)e2;
@@ -792,7 +820,11 @@ Expression *Identity(enum TOK op, Type *type, Expression *e1, Expression *e2)
Loc loc = e1->loc;
int cmp;
if (e1->op == TOKsymoff && e2->op == TOKsymoff)
if (e1->op == TOKnull && e2->op == TOKnull)
{
cmp = 1;
}
else if (e1->op == TOKsymoff && e2->op == TOKsymoff)
{
SymOffExp *es1 = (SymOffExp *)e1;
SymOffExp *es2 = (SymOffExp *)e2;
@@ -1051,7 +1083,7 @@ Expression *Cast(Type *type, Type *to, Expression *e1)
}
else
{
error("cannot cast %s to %s", e1->type->toChars(), type->toChars());
error(loc, "cannot cast %s to %s", e1->type->toChars(), type->toChars());
e = new IntegerExp(loc, 0, type);
}
return e;
@@ -1245,11 +1277,11 @@ Expression *Cat(Type *type, Expression *e1, Expression *e2)
//printf("Cat(e1 = %s, e2 = %s)\n", e1->toChars(), e2->toChars());
if (e1->op == TOKnull && e2->op == TOKint64)
if (e1->op == TOKnull && (e2->op == TOKint64 || e2->op == TOKstructliteral))
{ e = e2;
goto L2;
}
else if (e1->op == TOKint64 && e2->op == TOKnull)
else if ((e1->op == TOKint64 || e1->op == TOKstructliteral) && e2->op == TOKnull)
{ e = e1;
L2:
Type *tn = e->type->toBasetype();
@@ -1381,7 +1413,7 @@ Expression *Cat(Type *type, Expression *e1, Expression *e2)
e->type = type;
}
else if (e1->op == TOKarrayliteral &&
e1->type->toBasetype()->next->equals(e2->type))
e1->type->toBasetype()->nextOf()->equals(e2->type))
{
ArrayLiteralExp *es1 = (ArrayLiteralExp *)e1;
@@ -1398,7 +1430,7 @@ Expression *Cat(Type *type, Expression *e1, Expression *e2)
e->type = type;
}
else if (e2->op == TOKarrayliteral &&
e2->type->toBasetype()->next->equals(e1->type))
e2->type->toBasetype()->nextOf()->equals(e1->type))
{
ArrayLiteralExp *es2 = (ArrayLiteralExp *)e2;
@@ -1425,7 +1457,7 @@ Expression *Cat(Type *type, Expression *e1, Expression *e2)
t = e2->type;
L1:
Type *tb = t->toBasetype();
if (tb->ty == Tarray && tb->next->equals(e->type))
if (tb->ty == Tarray && tb->nextOf()->equals(e->type))
{ Expressions *expressions = new Expressions();
expressions->push(e);
e = new ArrayLiteralExp(loc, expressions);

View File

@@ -771,7 +771,12 @@ void VarDeclaration::semantic(Scope *sc)
//printf("Providing default initializer for '%s'\n", toChars());
if (type->ty == Tstruct &&
((TypeStruct *)type)->sym->zeroInit == 1)
{
{ /* If a struct is all zeros, as a special case
* set it's initializer to the integer 0.
* In AssignExp::toElem(), we check for this and issue
* a memset() to initialize the struct.
* Must do same check in interpreter.
*/
Expression *e = new IntegerExp(loc, 0, Type::tint32);
Expression *e1;
e1 = new VarExp(loc, this);
@@ -801,11 +806,12 @@ void VarDeclaration::semantic(Scope *sc)
if (init)
{
ArrayInitializer *ai = init->isArrayInitializer();
if (ai && type->toBasetype()->ty == Taarray)
if (ai && tb->ty == Taarray)
{
init = ai->toAssocArrayInitializer();
}
StructInitializer *si = init->isStructInitializer();
ExpInitializer *ei = init->isExpInitializer();
// See if we can allocate on the stack
@@ -898,16 +904,25 @@ void VarDeclaration::semantic(Scope *sc)
* Ignore failure.
*/
if (ei && !global.errors && !inferred)
if (!global.errors && !inferred)
{
unsigned errors = global.errors;
global.gag++;
//printf("+gag\n");
Expression *e = ei->exp->syntaxCopy();
Expression *e;
Initializer *i2 = init;
inuse++;
e = e->semantic(sc);
if (ei)
{
e = ei->exp->syntaxCopy();
e = e->semantic(sc);
e = e->implicitCastTo(sc, type);
}
else if (si || ai)
{ i2 = init->syntaxCopy();
i2 = i2->semantic(sc, type);
}
inuse--;
e = e->implicitCastTo(sc, type);
global.gag--;
//printf("-gag\n");
if (errors != global.errors) // if errors happened
@@ -915,7 +930,7 @@ void VarDeclaration::semantic(Scope *sc)
if (global.gag == 0)
global.errors = errors; // act as if nothing happened
}
else
else if (ei)
{
e = e->optimize(WANTvalue | WANTinterpret);
if (e->op == TOKint64 || e->op == TOKstring)
@@ -923,6 +938,8 @@ void VarDeclaration::semantic(Scope *sc)
ei->exp = e; // no errors, keep result
}
}
else
init = i2; // no errors, keep result
}
}
}

View File

@@ -775,6 +775,43 @@ char *ScopeDsymbol::kind()
}
/*******************************************
* Look for member of the form:
* const(MemberInfo)[] getMembers(string);
* Returns NULL if not found
*/
#if V2
FuncDeclaration *ScopeDsymbol::findGetMembers()
{
Dsymbol *s = search_function(this, Id::getmembers);
FuncDeclaration *fdx = s ? s->isFuncDeclaration() : NULL;
#if 0 // Finish
static TypeFunction *tfgetmembers;
if (!tfgetmembers)
{
Scope sc;
Arguments *arguments = new Arguments;
Arguments *arg = new Argument(STCin, Type::tchar->constOf()->arrayOf(), NULL, NULL);
arguments->push(arg);
Type *tret = NULL;
tfgetmembers = new TypeFunction(arguments, tret, 0, LINKd);
tfgetmembers = (TypeFunction *)tfgetmembers->semantic(0, &sc);
}
if (fdx)
fdx = fdx->overloadExactMatch(tfgetmembers);
#endif
if (fdx && fdx->isVirtual())
fdx = NULL;
return fdx;
}
#endif
/****************************** WithScopeSymbol ******************************/
WithScopeSymbol::WithScopeSymbol(WithStatement *withstate)

View File

@@ -619,9 +619,11 @@ void argsToCBuffer(OutBuffer *buf, Expressions *arguments, HdrGenState *hgs)
for (size_t i = 0; i < arguments->dim; i++)
{ Expression *arg = (Expression *)arguments->data[i];
if (i)
buf->writeByte(',');
expToCBuffer(buf, hgs, arg, PREC_assign);
if (arg)
{ if (i)
buf->writeByte(',');
expToCBuffer(buf, hgs, arg, PREC_assign);
}
}
}
}
@@ -3979,9 +3981,9 @@ void HaltExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
/************************************************************/
IftypeExp::IftypeExp(Loc loc, Type *targ, Identifier *id, enum TOK tok,
IsExp::IsExp(Loc loc, Type *targ, Identifier *id, enum TOK tok,
Type *tspec, enum TOK tok2)
: Expression(loc, TOKis, sizeof(IftypeExp))
: Expression(loc, TOKis, sizeof(IsExp))
{
this->targ = targ;
this->id = id;
@@ -3990,9 +3992,9 @@ IftypeExp::IftypeExp(Loc loc, Type *targ, Identifier *id, enum TOK tok,
this->tok2 = tok2;
}
Expression *IftypeExp::syntaxCopy()
Expression *IsExp::syntaxCopy()
{
return new IftypeExp(loc,
return new IsExp(loc,
targ->syntaxCopy(),
id,
tok,
@@ -4000,10 +4002,10 @@ Expression *IftypeExp::syntaxCopy()
tok2);
}
Expression *IftypeExp::semantic(Scope *sc)
Expression *IsExp::semantic(Scope *sc)
{ Type *tded;
//printf("IftypeExp::semantic()\n");
//printf("IsExp::semantic()\n");
if (id && !(sc->flags & SCOPEstaticif))
error("can only declare type aliases within static if conditionals");
@@ -4201,11 +4203,15 @@ Lno:
return new IntegerExp(0);
}
void IftypeExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
void IsExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
{
buf->writestring("is(");
targ->toCBuffer(buf, id, hgs);
if (tspec)
if (tok2 != TOKreserved)
{
buf->printf(" %s %s", Token::toChars(tok), Token::toChars(tok2));
}
else if (tspec)
{
if (tok == TOKcolon)
buf->writestring(" : ");
@@ -4213,6 +4219,17 @@ void IftypeExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
buf->writestring(" == ");
tspec->toCBuffer(buf, NULL, hgs);
}
#if V2
if (parameters)
{ // First parameter is already output, so start with second
for (int i = 1; i < parameters->dim; i++)
{
buf->writeByte(',');
TemplateParameter *tp = (TemplateParameter *)parameters->data[i];
tp->toCBuffer(buf, hgs);
}
}
#endif
buf->writeByte(')');
}
@@ -5308,7 +5325,7 @@ Expression *CallExp::semantic(Scope *sc)
int istemp;
#if LOGSEMANTIC
printf("CallExp::semantic('%s')\n", toChars());
printf("CallExp::semantic() %s\n", toChars());
#endif
if (type)
return this; // semantic() already run
@@ -5443,6 +5460,9 @@ Lagain:
ad = ((TypeStruct *)t1)->sym;
if (search_function(ad, Id::call))
goto L1; // overload of opCall, therefore it's a call
if (e1->op != TOKtype)
error("%s %s does not overload ()", ad->kind(), ad->toChars());
/* It's a struct literal
*/
Expression *e = new StructLiteralExp(loc, (StructDeclaration *)ad, arguments);

View File

@@ -70,6 +70,8 @@ void inferApplyArgTypes(enum TOK op, Arguments *arguments, Expression *aggr);
void argExpTypesToCBuffer(OutBuffer *buf, Expressions *arguments, HdrGenState *hgs);
void argsToCBuffer(OutBuffer *buf, Expressions *arguments, HdrGenState *hgs);
void expandTuples(Expressions *exps);
FuncDeclaration *hasThis(Scope *sc);
Expression *fromConstInitializer(int result, Expression *e);
struct Expression : Object
{
@@ -622,7 +624,7 @@ struct HaltExp : Expression
elem *toElem(IRState *irs);
};
struct IftypeExp : Expression
struct IsExp : Expression
{
/* is(targ id tok tspec)
* is(targ id == tok2)
@@ -633,7 +635,7 @@ struct IftypeExp : Expression
Type *tspec; // can be NULL
enum TOK tok2; // 'struct', 'union', 'typedef', etc.
IftypeExp(Loc loc, Type *targ, Identifier *id, enum TOK tok, Type *tspec, enum TOK tok2);
IsExp(Loc loc, Type *targ, Identifier *id, enum TOK tok, Type *tspec, enum TOK tok2);
Expression *syntaxCopy();
Expression *semantic(Scope *sc);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);

View File

@@ -255,7 +255,7 @@ void FuncDeclaration::semantic(Scope *sc)
if (!isVirtual())
{
//printf("\tnot virtual\n");
return;
goto Ldone;
}
// Find index of existing function in vtbl[] to override
@@ -405,8 +405,8 @@ void FuncDeclaration::semantic(Scope *sc)
#if 0
if (offset)
ti = fdv->type;
else if (type->next->ty == Tclass)
{ ClassDeclaration *cdn = ((TypeClass *)type->next)->sym;
else if (type->nextOf()->ty == Tclass)
{ ClassDeclaration *cdn = ((TypeClass *)type->nextOf())->sym;
if (cdn && cdn->sizeok != 1)
ti = fdv->type;
}
@@ -480,8 +480,8 @@ void FuncDeclaration::semantic(Scope *sc)
{
Argument *arg0 = Argument::getNth(f->parameters, 0);
if (arg0->type->ty != Tarray ||
arg0->type->next->ty != Tarray ||
arg0->type->next->next->ty != Tchar ||
arg0->type->nextOf()->ty != Tarray ||
arg0->type->nextOf()->nextOf()->ty != Tchar ||
arg0->storageClass & (STCout | STCref | STClazy))
goto Lmainerr;
break;
@@ -526,6 +526,7 @@ void FuncDeclaration::semantic(Scope *sc)
}
}
Ldone:
/* Save scope for possible later use (if we need the
* function internals)
*/
@@ -2185,7 +2186,8 @@ void DtorDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
/********************************* StaticCtorDeclaration ****************************/
StaticCtorDeclaration::StaticCtorDeclaration(Loc loc, Loc endloc)
: FuncDeclaration(loc, endloc, Id::staticCtor, STCstatic, NULL)
: FuncDeclaration(loc, endloc,
Identifier::generateId("_staticCtor"), STCstatic, NULL)
{
}
@@ -2257,7 +2259,8 @@ void StaticCtorDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
/********************************* StaticDtorDeclaration ****************************/
StaticDtorDeclaration::StaticDtorDeclaration(Loc loc, Loc endloc)
: FuncDeclaration(loc, endloc, Id::staticDtor, STCstatic, NULL)
: FuncDeclaration(loc, endloc,
Identifier::generateId("_staticDtor"), STCstatic, NULL)
{
}

View File

@@ -12,8 +12,6 @@ Identifier *Id::ctor;
Identifier *Id::dtor;
Identifier *Id::classInvariant;
Identifier *Id::unitTest;
Identifier *Id::staticCtor;
Identifier *Id::staticDtor;
Identifier *Id::init;
Identifier *Id::size;
Identifier *Id::__sizeof;
@@ -187,8 +185,6 @@ void Id::initialize()
dtor = Lexer::idPool("_dtor");
classInvariant = Lexer::idPool("__invariant");
unitTest = Lexer::idPool("_unitTest");
staticCtor = Lexer::idPool("_staticCtor");
staticDtor = Lexer::idPool("_staticDtor");
init = Lexer::idPool("init");
size = Lexer::idPool("size");
__sizeof = Lexer::idPool("sizeof");

View File

@@ -14,8 +14,6 @@ struct Id
static Identifier *dtor;
static Identifier *classInvariant;
static Identifier *unitTest;
static Identifier *staticCtor;
static Identifier *staticDtor;
static Identifier *init;
static Identifier *size;
static Identifier *__sizeof;

View File

@@ -53,14 +53,20 @@ char *Identifier::toHChars2()
else if (this == Id::dtor) p = "~this";
else if (this == Id::classInvariant) p = "invariant";
else if (this == Id::unitTest) p = "unittest";
else if (this == Id::staticCtor) p = "static this";
else if (this == Id::staticDtor) p = "static ~this";
else if (this == Id::dollar) p = "$";
else if (this == Id::withSym) p = "with";
else if (this == Id::result) p = "result";
else if (this == Id::returnLabel) p = "return";
else
p = toChars();
{ p = toChars();
if (*p == '_')
{
if (memcmp(p, "_staticCtor", 11) == 0)
p = "static this";
else if (memcmp(p, "_staticDtor", 11) == 0)
p = "static ~this";
}
}
return p;
}

View File

@@ -38,8 +38,6 @@ Msgtable msgtable[] =
{ "dtor", "_dtor" },
{ "classInvariant", "__invariant" },
{ "unitTest", "_unitTest" },
{ "staticCtor", "_staticCtor" },
{ "staticDtor", "_staticDtor" },
{ "init" },
{ "size" },
{ "__sizeof", "sizeof" },

View File

@@ -235,9 +235,43 @@ Initializer *StructInitializer::semantic(Scope *sc, Type *t)
}
/***************************************
* This works by transforming a struct initializer into
* a struct literal. In the future, the two should be the
* same thing.
*/
Expression *StructInitializer::toExpression()
{
return NULL; // cannot do it
{ Expression *e;
//printf("StructInitializer::toExpression() %s\n", toChars());
if (!ad) // if fwd referenced
{
return NULL;
}
StructDeclaration *sd = ad->isStructDeclaration();
if (!sd)
return NULL;
Expressions *elements = new Expressions();
for (size_t i = 0; i < value.dim; i++)
{
if (field.data[i])
goto Lno;
Initializer *iz = (Initializer *)value.data[i];
if (!iz)
goto Lno;
Expression *ex = iz->toExpression();
if (!ex)
goto Lno;
elements->push(ex);
}
e = new StructLiteralExp(loc, sd, elements);
e->type = sd->type;
return e;
Lno:
delete elements;
//error(loc, "struct initializers as expressions are not allowed");
return NULL;
}

View File

@@ -23,6 +23,7 @@ struct Type;
struct dt_t;
struct AggregateDeclaration;
struct VoidInitializer;
struct StructInitializer;
struct ArrayInitializer;
struct ExpInitializer;
struct StructInitializer;
@@ -47,9 +48,9 @@ struct Initializer : Object
virtual dt_t *toDt();
virtual VoidInitializer *isVoidInitializer() { return NULL; }
virtual StructInitializer *isStructInitializer() { return NULL; }
virtual ArrayInitializer *isArrayInitializer() { return NULL; }
virtual ExpInitializer *isExpInitializer() { return NULL; }
virtual StructInitializer *isStructInitializer() { return NULL; }
};
struct VoidInitializer : Initializer
@@ -84,7 +85,7 @@ struct StructInitializer : Initializer
dt_t *toDt();
virtual StructInitializer *isStructInitializer() { return this; }
StructInitializer *isStructInitializer() { return this; }
};
struct ArrayInitializer : Initializer

View File

@@ -77,6 +77,7 @@ Expression *FuncDeclaration::interpret(InterState *istate, Expressions *argument
return NULL;
}
//printf("test2 %d, %p\n", semanticRun, scope);
if (semanticRun == 0 && scope)
{
semantic3(scope);
@@ -276,7 +277,7 @@ Expression *ExpStatement::interpret(InterState *istate)
Expression *e = exp->interpret(istate);
if (e == EXP_CANT_INTERPRET)
{
//printf("cannot interpret %s\n", exp->toChars());
//printf("-ExpStatement::interpret(): %p\n", e);
return EXP_CANT_INTERPRET;
}
}
@@ -364,20 +365,13 @@ Expression *IfStatement::interpret(InterState *istate)
//if (e == EXP_CANT_INTERPRET) printf("cannot interpret\n");
if (e != EXP_CANT_INTERPRET)
{
if (!e->isConst())
{
e = EXP_CANT_INTERPRET;
}
if (e->isBool(TRUE))
e = ifbody ? ifbody->interpret(istate) : NULL;
else if (e->isBool(FALSE))
e = elsebody ? elsebody->interpret(istate) : NULL;
else
{
if (e->isBool(TRUE))
e = ifbody ? ifbody->interpret(istate) : NULL;
else if (e->isBool(FALSE))
e = elsebody ? elsebody->interpret(istate) : NULL;
else
{
e = EXP_CANT_INTERPRET;
}
e = EXP_CANT_INTERPRET;
}
}
return e;
@@ -957,7 +951,7 @@ Expression *getVarExp(Loc loc, InterState *istate, Declaration *d)
{
if (v->isConst() && v->init)
{ e = v->init->toExpression();
if (!e->type)
if (e && !e->type)
e->type = v->type;
}
else
@@ -994,7 +988,7 @@ Expression *DeclarationExp::interpret(InterState *istate)
#if LOG
printf("DeclarationExp::interpret() %s\n", toChars());
#endif
Expression *e = EXP_CANT_INTERPRET;
Expression *e;
VarDeclaration *v = declaration->isVarDeclaration();
if (v)
{
@@ -1015,6 +1009,19 @@ Expression *DeclarationExp::interpret(InterState *istate)
e->type = v->type;
}
}
else if (declaration->isAttribDeclaration() ||
declaration->isTemplateMixin() ||
declaration->isTupleDeclaration())
{ // These can be made to work, too lazy now
e = EXP_CANT_INTERPRET;
}
else
{ // Others should not contain executable code, so are trivial to evaluate
e = NULL;
}
#if LOG
printf("-DeclarationExp::interpret(): %p\n", e);
#endif
return e;
}
@@ -1084,7 +1091,7 @@ Expression *ArrayLiteralExp::interpret(InterState *istate)
if (!expsx)
{ expsx = new Expressions();
expsx->setDim(elements->dim);
for (size_t j = 0; j < i; j++)
for (size_t j = 0; j < elements->dim; j++)
{
expsx->data[j] = elements->data[j];
}
@@ -1342,6 +1349,7 @@ Expression *BinExp::interpretCommon2(InterState *istate, fp2_t fp)
if (e1 == EXP_CANT_INTERPRET)
goto Lcant;
if (e1->isConst() != 1 &&
e1->op != TOKnull &&
e1->op != TOKstring &&
e1->op != TOKarrayliteral &&
e1->op != TOKstructliteral)
@@ -1351,6 +1359,7 @@ Expression *BinExp::interpretCommon2(InterState *istate, fp2_t fp)
if (e2 == EXP_CANT_INTERPRET)
goto Lcant;
if (e2->isConst() != 1 &&
e2->op != TOKnull &&
e2->op != TOKstring &&
e2->op != TOKarrayliteral &&
e2->op != TOKstructliteral)
@@ -1420,7 +1429,14 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, fp_t fp, int post)
if (fp)
e2 = (*fp)(v->type, ev, e2);
else
{ /* Look for special case of struct being initialized with 0.
*/
if (v->type->toBasetype()->ty == Tstruct && e2->op == TOKint64)
{
e2 = v->type->defaultInit();
}
e2 = Cast(v->type, v->type, e2);
}
if (e2 != EXP_CANT_INTERPRET)
{
if (!v->isParameter())
@@ -1453,9 +1469,15 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, fp_t fp, int post)
{ error("variable %s is used before initialization", v->toChars());
return e;
}
if (v->value->op != TOKstructliteral)
Expression *vie = v->value;
if (vie->op == TOKvar)
{
Declaration *d = ((VarExp *)vie)->var;
vie = getVarExp(e1->loc, istate, d);
}
if (vie->op != TOKstructliteral)
return EXP_CANT_INTERPRET;
StructLiteralExp *se = (StructLiteralExp *)v->value;
StructLiteralExp *se = (StructLiteralExp *)vie;
int fieldi = se->getFieldIndex(type, soe->offset);
if (fieldi == -1)
return EXP_CANT_INTERPRET;
@@ -1843,6 +1865,10 @@ Expression *ArrayLengthExp::interpret(InterState *istate)
{
e = ArrayLength(type, e1);
}
else if (e1->op == TOKnull)
{
e = new IntegerExp(loc, 0, type);
}
else
goto Lcant;
return e;

View File

@@ -459,7 +459,7 @@ int Lexer::isValidIdentifier(char *p)
if (!p || !*p)
goto Linvalid;
if (isdigit(*p))
if (*p >= '0' && *p <= '9') // beware of isdigit() on signed chars
goto Linvalid;
len = strlen(p);
@@ -568,6 +568,23 @@ void Lexer::scan(Token *t)
t->value = hexStringConstant(t);
return;
#if V2
case 'q':
if (p[1] == '"')
{
p++;
t->value = delimitedStringConstant(t);
return;
}
else if (p[1] == '{')
{
p++;
t->value = tokenStringConstant(t);
return;
}
else
goto case_ident;
#endif
case '"':
t->value = escapeStringConstant(t,0);
@@ -598,7 +615,11 @@ void Lexer::scan(Token *t)
case 'a': case 'b': case 'c': case 'd': case 'e':
case 'f': case 'g': case 'h': case 'i': case 'j':
case 'k': case 'm': case 'n': case 'o':
#if V2
case 'p': /*case 'q': case 'r':*/ case 's': case 't':
#else
case 'p': case 'q': /*case 'r':*/ case 's': case 't':
#endif
case 'u': case 'v': case 'w': /*case 'x':*/ case 'y':
case 'z':
case 'A': case 'B': case 'C': case 'D': case 'E':
@@ -1431,6 +1452,223 @@ TOK Lexer::hexStringConstant(Token *t)
}
}
#if V2
/**************************************
* Lex delimited strings:
* q"(foo(xxx))" // "foo(xxx)"
* q"[foo(]" // "foo("
* q"/foo]/" // "foo]"
* q"HERE
* foo
* HERE" // "foo\n"
* Input:
* p is on the "
*/
TOK Lexer::delimitedStringConstant(Token *t)
{ unsigned c;
Loc start = loc;
unsigned delimleft = 0;
unsigned delimright = 0;
unsigned nest = 1;
unsigned nestcount;
Identifier *hereid = NULL;
unsigned blankrol = 0;
unsigned startline = 0;
p++;
stringbuffer.reset();
while (1)
{
c = *p++;
//printf("c = '%c'\n", c);
switch (c)
{
case '\n':
Lnextline:
printf("Lnextline\n");
loc.linnum++;
startline = 1;
if (blankrol)
{ blankrol = 0;
continue;
}
if (hereid)
{
stringbuffer.writeUTF8(c);
continue;
}
break;
case '\r':
if (*p == '\n')
continue; // ignore
c = '\n'; // treat EndOfLine as \n character
goto Lnextline;
case 0:
case 0x1A:
goto Lerror;
default:
if (c & 0x80)
{ p--;
c = decodeUTF();
p++;
if (c == PS || c == LS)
goto Lnextline;
}
break;
}
if (delimleft == 0)
{ delimleft = c;
nest = 1;
nestcount = 1;
if (c == '(')
delimright = ')';
else if (c == '{')
delimright = '}';
else if (c == '[')
delimright = ']';
else if (c == '<')
delimright = '>';
else if (isalpha(c) || c == '_' || (c >= 0x80 && isUniAlpha(c)))
{ // Start of identifier; must be a heredoc
Token t;
p--;
scan(&t); // read in heredoc identifier
if (t.value != TOKidentifier)
{ error("identifier expected for heredoc, not %s", t.toChars());
delimright = c;
}
else
{ hereid = t.ident;
printf("hereid = '%s'\n", hereid->toChars());
blankrol = 1;
}
nest = 0;
}
else
{ delimright = c;
nest = 0;
}
}
else
{
if (blankrol)
{ error("heredoc rest of line should be blank");
blankrol = 0;
continue;
}
if (nest == 1)
{
if (c == delimleft)
nestcount++;
else if (c == delimright)
{ nestcount--;
if (nestcount == 0)
goto Ldone;
}
}
else if (c == delimright)
goto Ldone;
if (startline && isalpha(c))
{ Token t;
unsigned char *psave = p;
p--;
scan(&t); // read in possible heredoc identifier
printf("endid = '%s'\n", t.ident->toChars());
if (t.value == TOKidentifier && t.ident->equals(hereid))
{ /* should check that rest of line is blank
*/
printf("done\n");
goto Ldone;
}
p = psave;
}
stringbuffer.writeUTF8(c);
startline = 0;
}
}
Ldone:
if (*p == '"')
p++;
else
error("delimited string must end in %c\"", delimright);
t->len = stringbuffer.offset;
stringbuffer.writeByte(0);
t->ustring = (unsigned char *)mem.malloc(stringbuffer.offset);
memcpy(t->ustring, stringbuffer.data, stringbuffer.offset);
stringPostfix(t);
return TOKstring;
Lerror:
error("unterminated string constant starting at %s", start.toChars());
t->ustring = (unsigned char *)"";
t->len = 0;
t->postfix = 0;
return TOKstring;
}
/**************************************
* Lex delimited strings:
* q{ foo(xxx) } // " foo(xxx) "
* q{foo(} // "foo("
* q{{foo}"}"} // "{foo}"}""
* Input:
* p is on the q
*/
TOK Lexer::tokenStringConstant(Token *t)
{
unsigned nest = 1;
Loc start = loc;
unsigned char *pstart = ++p;
while (1)
{ Token tok;
scan(&tok);
switch (tok.value)
{
case TOKlcurly:
nest++;
continue;
case TOKrcurly:
if (--nest == 0)
goto Ldone;
continue;
case TOKeof:
goto Lerror;
default:
continue;
}
}
Ldone:
t->len = p - 1 - pstart;
t->ustring = (unsigned char *)mem.malloc(t->len + 1);
memcpy(t->ustring, pstart, t->len);
t->ustring[t->len] = 0;
stringPostfix(t);
return TOKstring;
Lerror:
error("unterminated token string constant starting at %s", start.toChars());
t->ustring = (unsigned char *)"";
t->len = 0;
t->postfix = 0;
return TOKstring;
}
#endif
/**************************************
*/
@@ -2641,6 +2879,9 @@ static Keyword keywords[] =
// Added after 1.0
{ "ref", TOKref },
{ "macro", TOKmacro },
#if V2
{ "__traits", TOKtraits },
#endif
};
int Token::isKeyword()

View File

@@ -150,6 +150,9 @@ enum TOK
// Added after 1.0
TOKref,
TOKmacro,
#if V2
TOKtraits,
#endif
TOKMAX
};
@@ -266,6 +269,10 @@ struct Lexer
unsigned escapeSequence();
TOK wysiwygStringConstant(Token *t, int tc);
TOK hexStringConstant(Token *t);
#if V2
TOK delimitedStringConstant(Token *t);
TOK tokenStringConstant(Token *t);
#endif
TOK escapeStringConstant(Token *t, int wide);
TOK charConstant(Token *t, int wide);
void stringPostfix(Token *t);

View File

@@ -68,7 +68,7 @@ Global::Global()
copyright = "Copyright (c) 1999-2007 by Digital Mars and Tomas Lindquist Olsen";
written = "written by Walter Bright and Tomas Lindquist Olsen";
llvmdc_version = "0.0.1";
version = "v1.020";
version = "v1.021";
global.structalign = 8;
memset(&params, 0, sizeof(Param));
@@ -282,6 +282,9 @@ int main(int argc, char *argv[])
global.params.optimizeLevel = 2;
global.params.runtimeImppath = 0;
global.params.defaultlibname = "phobos";
global.params.debuglibname = global.params.defaultlibname;
// Predefine version identifiers
#if IN_LLVM
VersionCondition::addPredefinedGlobalIdent("LLVM");
@@ -474,7 +477,7 @@ int main(int argc, char *argv[])
{
global.params.runtimeImppath = p+2;
}
else if (memcmp(p + 1, "debug", 5) == 0)
else if (memcmp(p + 1, "debug", 5) == 0 && p[6] != 'l')
{
// Parse:
// -debug
@@ -545,6 +548,14 @@ int main(int argc, char *argv[])
{
global.params.linkswitches->push(p + 2);
}
else if (memcmp(p + 1, "defaultlib=", 11) == 0)
{
global.params.defaultlibname = p + 1 + 11;
}
else if (memcmp(p + 1, "debuglib=", 9) == 0)
{
global.params.debuglibname = p + 1 + 9;
}
else if (strcmp(p + 1, "run") == 0)
{ global.params.run = 1;
global.params.runargs_length = ((i >= argcstart) ? argc : argcstart) - i - 1;

View File

@@ -94,6 +94,11 @@ struct Param
bool dump_source;
char *defaultlibname; // default library for non-debug builds
char *debuglibname; // default library for debug builds
char *xmlname; // filename for XML output
// Hidden debug switches
char debuga;
char debugb;

View File

@@ -3940,7 +3940,7 @@ Expression *Parser::parsePrimaryExp()
{ error("(type identifier : specialization) expected following is");
goto Lerr;
}
e = new IftypeExp(loc, targ, ident, tok, tspec, tok2);
e = new IsExp(loc, targ, ident, tok, tspec, tok2);
break;
}

View File

@@ -894,6 +894,7 @@ Statement *DoStatement::semantic(Scope *sc)
sc->noctor--;
condition = condition->semantic(sc);
condition = resolveProperties(sc, condition);
condition = condition->optimize(WANTvalue);
condition = condition->checkToBoolean();
@@ -979,6 +980,7 @@ Statement *ForStatement::semantic(Scope *sc)
sc->noctor++;
condition = condition->semantic(sc);
condition = resolveProperties(sc, condition);
condition = condition->optimize(WANTvalue);
condition = condition->checkToBoolean();
if (increment)
increment = increment->semantic(sc);
@@ -1090,7 +1092,8 @@ Statement *ForeachStatement::syntaxCopy()
{
Arguments *args = Argument::arraySyntaxCopy(arguments);
Expression *exp = aggr->syntaxCopy();
ForeachStatement *s = new ForeachStatement(loc, op, args, exp, body->syntaxCopy());
ForeachStatement *s = new ForeachStatement(loc, op, args, exp,
body ? body->syntaxCopy() : NULL);
return s;
}
@@ -1255,7 +1258,7 @@ Statement *ForeachStatement::semantic(Scope *sc)
/* Look for special case of parsing char types out of char type
* array.
*/
tn = tab->next->toBasetype();
tn = tab->nextOf()->toBasetype();
if (tn->ty == Tchar || tn->ty == Twchar || tn->ty == Tdchar)
{ Argument *arg;
@@ -1311,9 +1314,6 @@ Statement *ForeachStatement::semantic(Scope *sc)
error("foreach: %s is not an array of %s", tab->toChars(), value->type->toChars());
}
if (value->storage_class & STCout && value->type->toBasetype()->ty == Tbit)
error("foreach: value cannot be out and type bit");
if (key &&
((key->type->ty != Tint32 && key->type->ty != Tuns32) ||
(global.params.is64bit &&
@@ -1356,7 +1356,7 @@ Statement *ForeachStatement::semantic(Scope *sc)
Identifier *id;
Type *tret;
tret = func->type->next;
tret = func->type->nextOf();
// Need a variable to hold value from any return statements in body.
if (!sc->func->vresult && tret && tret != Type::tvoid)
@@ -1430,8 +1430,8 @@ Statement *ForeachStatement::semantic(Scope *sc)
error("foreach: index must be type %s, not %s", taa->index->toChars(), arg->type->toChars());
arg = (Argument *)arguments->data[1];
}
if (!arg->type->equals(taa->next))
error("foreach: value must be type %s, not %s", taa->next->toChars(), arg->type->toChars());
if (!arg->type->equals(taa->nextOf()))
error("foreach: value must be type %s, not %s", taa->nextOf()->toChars(), arg->type->toChars());
/* Call:
* _aaApply(aggr, keysize, flde)
@@ -1982,7 +1982,7 @@ Statement *SwitchStatement::semantic(Scope *sc)
// If it's not an array, cast it to one
if (condition->type->ty != Tarray)
{
condition = condition->implicitCastTo(sc, condition->type->next->arrayOf());
condition = condition->implicitCastTo(sc, condition->type->nextOf()->arrayOf());
}
}
else
@@ -2122,6 +2122,7 @@ Statement *CaseStatement::syntaxCopy()
Statement *CaseStatement::semantic(Scope *sc)
{ SwitchStatement *sw = sc->sw;
//printf("CaseStatement::semantic() %s\n", toChars());
exp = exp->semantic(sc);
if (sw)
{ int i;
@@ -2390,9 +2391,9 @@ Statement *ReturnStatement::semantic(Scope *sc)
}
}
Type *tret = fd->type->next;
Type *tret = fd->type->nextOf();
if (fd->tintro)
tret = fd->tintro->next;
tret = fd->tintro->nextOf();
Type *tbret = NULL;
if (tret)
@@ -2452,18 +2453,18 @@ Statement *ReturnStatement::semantic(Scope *sc)
}
else if (fd->inferRetType)
{
if (fd->type->next)
if (fd->type->nextOf())
{
if (!exp->type->equals(fd->type->next))
if (!exp->type->equals(fd->type->nextOf()))
error("mismatched function return type inference of %s and %s",
exp->type->toChars(), fd->type->next->toChars());
exp->type->toChars(), fd->type->nextOf()->toChars());
}
else
{
fd->type->next = exp->type;
fd->type = fd->type->semantic(loc, sc);
if (!fd->tintro)
{ tret = fd->type->next;
{ tret = fd->type->nextOf();
tbret = tret->toBasetype();
}
}
@@ -2475,11 +2476,11 @@ Statement *ReturnStatement::semantic(Scope *sc)
}
else if (fd->inferRetType)
{
if (fd->type->next)
if (fd->type->nextOf())
{
if (fd->type->next->ty != Tvoid)
if (fd->type->nextOf()->ty != Tvoid)
error("mismatched function return type inference of void and %s",
fd->type->next->toChars());
fd->type->nextOf()->toChars());
}
else
{
@@ -2510,7 +2511,7 @@ Statement *ReturnStatement::semantic(Scope *sc)
sc->fes->cases.push(this);
s = new ReturnStatement(0, new IntegerExp(sc->fes->cases.dim + 1));
}
else if (fd->type->next->toBasetype() == Type::tvoid)
else if (fd->type->nextOf()->toBasetype() == Type::tvoid)
{
Statement *s1;
Statement *s2;

View File

@@ -49,6 +49,7 @@ void StaticAssert::semantic2(Scope *sc)
{
Expression *e;
//printf("StaticAssert::semantic2() %s\n", toChars());
e = exp->semantic(sc);
e = e->optimize(WANTvalue | WANTinterpret);
if (e->isBool(FALSE))

View File

@@ -1232,7 +1232,7 @@ MATCH Type::deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters,
return (MATCH) implicitConvTo(at);
}
else if (ty == Tsarray && at->ty == Tarray &&
next->equals(at->nextOf()))
nextOf()->equals(at->nextOf()))
{
goto Lexact;
}
@@ -3278,7 +3278,6 @@ Identifier *TemplateInstance::genIdent()
else if (ea)
{ sinteger_t v;
real_t r;
unsigned char *p;
if (ea->op == TOKvar)
{
@@ -3298,6 +3297,8 @@ Identifier *TemplateInstance::genIdent()
continue;
}
#if 1
/* Use deco that matches what it would be for a function parameter
*/
buf.writestring(ea->type->deco);
#else
// Use type of parameter, not type of argument