# HG changeset patch # User Tomas Lindquist Olsen # Date 1238774374 -7200 # Node ID e961851fb8be6c9305d9330eb87c7cfa0132854a # Parent 1853dcd9b9449d2ac968aad898114a9ded6b06ab Merged DMD 1.042. diff -r 1853dcd9b944 -r e961851fb8be dmd/attrib.c --- a/dmd/attrib.c Fri Apr 03 17:02:52 2009 +0200 +++ b/dmd/attrib.c Fri Apr 03 17:59:34 2009 +0200 @@ -1,6 +1,6 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2008 by Digital Mars +// Copyright (c) 1999-2009 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -322,7 +322,7 @@ sc->stc = stc; } -void StorageClassDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) +void StorageClassDeclaration::stcToCBuffer(OutBuffer *buf, int stc) { struct SCstring { @@ -350,18 +350,19 @@ // { STCtls, TOKtls }, }; - int written = 0; for (int i = 0; i < sizeof(table)/sizeof(table[0]); i++) { if (stc & table[i].stc) { - if (written) - buf->writeByte(' '); - written = 1; buf->writestring(Token::toChars(table[i].tok)); + buf->writeByte(' '); } } +} +void StorageClassDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) +{ + stcToCBuffer(buf, stc); AttribDeclaration::toCBuffer(buf, hgs); } @@ -1193,6 +1194,18 @@ name[se->len] = 0; obj_includelib(name); } +#if DMDV2 + else if (ident == Id::startaddress) + { + assert(args && args->dim == 1); + Expression *e = (Expression *)args->data[0]; + Dsymbol *sa = getDsymbol(e); + FuncDeclaration *f = sa->isFuncDeclaration(); + assert(f); + Symbol *s = f->toSymbol(); + obj_startaddress(s); + } +#endif AttribDeclaration::toObjFile(multiobj); } #endif diff -r 1853dcd9b944 -r e961851fb8be dmd/attrib.h --- a/dmd/attrib.h Fri Apr 03 17:02:52 2009 +0200 +++ b/dmd/attrib.h Fri Apr 03 17:59:34 2009 +0200 @@ -68,6 +68,8 @@ Dsymbol *syntaxCopy(Dsymbol *s); void semantic(Scope *sc); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); + + static void stcToCBuffer(OutBuffer *buf, int stc); }; struct LinkDeclaration : AttribDeclaration diff -r 1853dcd9b944 -r e961851fb8be dmd/cast.c --- a/dmd/cast.c Fri Apr 03 17:02:52 2009 +0200 +++ b/dmd/cast.c Fri Apr 03 17:59:34 2009 +0200 @@ -1,5 +1,5 @@ -// Copyright (c) 1999-2008 by Digital Mars +// Copyright (c) 1999-2009 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -228,7 +228,7 @@ case Tchar: case Tuns8: - //printf("value = %llu %llu\n", (integer_t)(unsigned char)value, value); + //printf("value = %llu %llu\n", (dinteger_t)(unsigned char)value, value); if ((unsigned char)value != value) goto Lno; goto Lyes; diff -r 1853dcd9b944 -r e961851fb8be dmd/class.c --- a/dmd/class.c Fri Apr 03 17:02:52 2009 +0200 +++ b/dmd/class.c Fri Apr 03 17:59:34 2009 +0200 @@ -562,7 +562,7 @@ // sc->offset += PTRSIZE; // room for uplevel context pointer } else - { sc->offset = 2*PTRSIZE; // allow room for vptr[] and monitor + { sc->offset = PTRSIZE * 2; // allow room for vptr[] and monitor alignsize = PTRSIZE; } structsize = sc->offset; @@ -1152,7 +1152,7 @@ sc->linkage = LINKwindows; sc->structalign = 8; structalign = sc->structalign; - sc->offset = 2*PTRSIZE; + sc->offset = PTRSIZE * 2; inuse++; for (i = 0; i < members->dim; i++) { diff -r 1853dcd9b944 -r e961851fb8be dmd/cond.c --- a/dmd/cond.c Fri Apr 03 17:02:52 2009 +0200 +++ b/dmd/cond.c Fri Apr 03 17:59:34 2009 +0200 @@ -129,7 +129,14 @@ { "DigitalMars", "X86", "X86_64", "Windows", "Win32", "Win64", - "linux", "Posix", "OSX", "FreeBSD", + "linux", +#if DMDV2 + /* Although Posix is predefined by D1, disallowing its + * redefinition breaks makefiles and older builds. + */ + "Posix", +#endif + "OSX", "FreeBSD", "LittleEndian", "BigEndian", "all", "none", diff -r 1853dcd9b944 -r e961851fb8be dmd/constfold.c --- a/dmd/constfold.c Fri Apr 03 17:02:52 2009 +0200 +++ b/dmd/constfold.c Fri Apr 03 17:59:34 2009 +0200 @@ -1,6 +1,6 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2007 by Digital Mars +// Copyright (c) 1999-2009 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -555,7 +555,7 @@ { Expression *e; Loc loc = e1->loc; unsigned count; - integer_t value; + dinteger_t value; value = e1->toInteger(); count = e2->toInteger(); @@ -604,7 +604,7 @@ { Expression *e; Loc loc = e1->loc; unsigned count; - integer_t value; + dinteger_t value; value = e1->toInteger(); count = e2->toInteger(); @@ -887,7 +887,7 @@ Expression *Cmp(enum TOK op, Type *type, Expression *e1, Expression *e2) { Expression *e; Loc loc = e1->loc; - integer_t n; + dinteger_t n; real_t r1; real_t r2; @@ -1058,7 +1058,7 @@ else if (type->isintegral()) { if (e1->type->isfloating()) - { integer_t result; + { dinteger_t result; real_t r = e1->toReal(); switch (type->toBasetype()->ty) @@ -1251,7 +1251,7 @@ if (iupr > es1->len || ilwr > iupr) e1->error("string slice [%ju .. %ju] is out of bounds", ilwr, iupr); else - { integer_t value; + { dinteger_t value; void *s; size_t len = iupr - ilwr; int sz = es1->sz; @@ -1317,7 +1317,7 @@ StringExp *es; size_t len = 1; int sz = tn->size(); - integer_t v = e->toInteger(); + dinteger_t v = e->toInteger(); s = mem.malloc((len + 1) * sz); memcpy((unsigned char *)s, &v, sz); @@ -1384,7 +1384,7 @@ Type *t; size_t len = es1->len + 1; int sz = es1->sz; - integer_t v = e2->toInteger(); + dinteger_t v = e2->toInteger(); s = mem.malloc((len + 1) * sz); memcpy(s, es1->string, es1->len * sz); @@ -1409,7 +1409,7 @@ Type *t; size_t len = 1 + es2->len; int sz = es2->sz; - integer_t v = e1->toInteger(); + dinteger_t v = e1->toInteger(); s = mem.malloc((len + 1) * sz); memcpy((unsigned char *)s, &v, sz); diff -r 1853dcd9b944 -r e961851fb8be dmd/declaration.c --- a/dmd/declaration.c Fri Apr 03 17:02:52 2009 +0200 +++ b/dmd/declaration.c Fri Apr 03 17:59:34 2009 +0200 @@ -1,1426 +1,1416 @@ - -// Compiler implementation of the D programming language -// Copyright (c) 1999-2008 by Digital Mars -// All Rights Reserved -// written by Walter Bright -// 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. - -#include -#include - -#include "init.h" -#include "declaration.h" -#include "attrib.h" -#include "mtype.h" -#include "template.h" -#include "scope.h" -#include "aggregate.h" -#include "module.h" -#include "id.h" -#include "expression.h" -#include "hdrgen.h" - -/********************************* Declaration ****************************/ - -Declaration::Declaration(Identifier *id) - : Dsymbol(id) -{ - type = NULL; - originalType = NULL; - storage_class = STCundefined; - protection = PROTundefined; - linkage = LINKdefault; -} - -void Declaration::semantic(Scope *sc) -{ -} - -const char *Declaration::kind() -{ - return "declaration"; -} - -unsigned Declaration::size(Loc loc) -{ - assert(type); - return type->size(); -} - -int Declaration::isStaticConstructor() -{ - return FALSE; -} - -int Declaration::isStaticDestructor() -{ - return FALSE; -} - -int Declaration::isDelete() -{ - return FALSE; -} - -int Declaration::isDataseg() -{ - return FALSE; -} - -int Declaration::isCodeseg() -{ - return FALSE; -} - -enum PROT Declaration::prot() -{ - return protection; -} - -/************************************* - * Check to see if declaration can be modified in this context (sc). - * Issue error if not. - */ - -#if DMDV2 -void Declaration::checkModify(Loc loc, Scope *sc, Type *t) -{ - if (sc->incontract && isParameter()) - error(loc, "cannot modify parameter '%s' in contract", toChars()); - - if (isCtorinit()) - { // It's only modifiable if inside the right constructor - Dsymbol *s = sc->func; - while (1) - { - FuncDeclaration *fd = NULL; - if (s) - fd = s->isFuncDeclaration(); - if (fd && - ((fd->isCtorDeclaration() && storage_class & STCfield) || - (fd->isStaticCtorDeclaration() && !(storage_class & STCfield))) && - fd->toParent() == toParent() - ) - { - VarDeclaration *v = isVarDeclaration(); - assert(v); - v->ctorinit = 1; - //printf("setting ctorinit\n"); - } - else - { - if (s) - { s = s->toParent2(); - continue; - } - else - { - const char *p = isStatic() ? "static " : ""; - error(loc, "can only initialize %sconst %s inside %sconstructor", - p, toChars(), p); - } - } - break; - } - } - else - { - VarDeclaration *v = isVarDeclaration(); - if (v && v->canassign == 0) - { - char *p = NULL; - if (isConst()) - p = "const"; - else if (isInvariant()) - p = "invariant"; - else if (storage_class & STCmanifest) - p = "manifest constant"; - else if (!t->isAssignable()) - p = "struct with immutable members"; - if (p) - { error(loc, "cannot modify %s", p); - halt(); - } - } - } -} -#endif - - -/********************************* TupleDeclaration ****************************/ - -TupleDeclaration::TupleDeclaration(Loc loc, Identifier *id, Objects *objects) - : Declaration(id) -{ - this->type = NULL; - this->objects = objects; - this->isexp = 0; - this->tupletype = NULL; -} - -Dsymbol *TupleDeclaration::syntaxCopy(Dsymbol *s) -{ - assert(0); - return NULL; -} - -const char *TupleDeclaration::kind() -{ - return "tuple"; -} - -Type *TupleDeclaration::getType() -{ - /* If this tuple represents a type, return that type - */ - - //printf("TupleDeclaration::getType() %s\n", toChars()); - if (isexp) - return NULL; - if (!tupletype) - { - /* It's only a type tuple if all the Object's are types - */ - for (size_t i = 0; i < objects->dim; i++) - { Object *o = (Object *)objects->data[i]; - - if (o->dyncast() != DYNCAST_TYPE) - { - //printf("\tnot[%d], %p, %d\n", i, o, o->dyncast()); - return NULL; - } - } - - /* We know it's a type tuple, so build the TypeTuple - */ - Arguments *args = new Arguments(); - args->setDim(objects->dim); - OutBuffer buf; - for (size_t i = 0; i < objects->dim; i++) - { Type *t = (Type *)objects->data[i]; - - //printf("type = %s\n", t->toChars()); -#if 0 - buf.printf("_%s_%d", ident->toChars(), i); - char *name = (char *)buf.extractData(); - Identifier *id = new Identifier(name, TOKidentifier); - Argument *arg = new Argument(STCin, t, id, NULL); -#else - Argument *arg = new Argument(STCin, t, NULL, NULL); -#endif - args->data[i] = (void *)arg; - } - - tupletype = new TypeTuple(args); - } - - return tupletype; -} - -int TupleDeclaration::needThis() -{ - //printf("TupleDeclaration::needThis(%s)\n", toChars()); - for (size_t i = 0; i < objects->dim; i++) - { Object *o = (Object *)objects->data[i]; - if (o->dyncast() == DYNCAST_EXPRESSION) - { Expression *e = (Expression *)o; - if (e->op == TOKdsymbol) - { DsymbolExp *ve = (DsymbolExp *)e; - Declaration *d = ve->s->isDeclaration(); - if (d && d->needThis()) - { - return 1; - } - } - } - } - return 0; -} - -/********************************* TypedefDeclaration ****************************/ - -TypedefDeclaration::TypedefDeclaration(Loc loc, Identifier *id, Type *basetype, Initializer *init) - : Declaration(id) -{ - this->type = new TypeTypedef(this); - this->basetype = basetype->toBasetype(); - this->init = init; -#ifdef _DH - this->htype = NULL; - this->hbasetype = NULL; -#endif - this->sem = 0; - this->inuse = 0; - this->loc = loc; -#if IN_DMD - this->sinit = NULL; -#endif -} - -Dsymbol *TypedefDeclaration::syntaxCopy(Dsymbol *s) -{ - Type *basetype = this->basetype->syntaxCopy(); - - Initializer *init = NULL; - if (this->init) - init = this->init->syntaxCopy(); - - assert(!s); - TypedefDeclaration *st; - st = new TypedefDeclaration(loc, ident, basetype, init); -#ifdef _DH - // Syntax copy for header file - if (!htype) // Don't overwrite original - { if (type) // Make copy for both old and new instances - { htype = type->syntaxCopy(); - st->htype = type->syntaxCopy(); - } - } - else // Make copy of original for new instance - st->htype = htype->syntaxCopy(); - if (!hbasetype) - { if (basetype) - { hbasetype = basetype->syntaxCopy(); - st->hbasetype = basetype->syntaxCopy(); - } - } - else - st->hbasetype = hbasetype->syntaxCopy(); -#endif - return st; -} - -void TypedefDeclaration::semantic(Scope *sc) -{ - //printf("TypedefDeclaration::semantic(%s) sem = %d\n", toChars(), sem); - if (sem == 0) - { sem = 1; - basetype = basetype->semantic(loc, sc); - sem = 2; - type = type->semantic(loc, sc); - if (sc->parent->isFuncDeclaration() && init) - semantic2(sc); - storage_class |= sc->stc & STCdeprecated; - } - else if (sem == 1) - { - error("circular definition"); - } -} - -void TypedefDeclaration::semantic2(Scope *sc) -{ - //printf("TypedefDeclaration::semantic2(%s) sem = %d\n", toChars(), sem); - if (sem == 2) - { sem = 3; - if (init) - { - init = init->semantic(sc, basetype); - - ExpInitializer *ie = init->isExpInitializer(); - if (ie) - { - if (ie->exp->type == basetype) - ie->exp->type = type; - } - } - } -} - -const char *TypedefDeclaration::kind() -{ - return "typedef"; -} - -Type *TypedefDeclaration::getType() -{ - return type; -} - -void TypedefDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) -{ - buf->writestring("typedef "); - basetype->toCBuffer(buf, ident, hgs); - if (init) - { - buf->writestring(" = "); - init->toCBuffer(buf, hgs); - } - buf->writeByte(';'); - buf->writenl(); -} - -/********************************* AliasDeclaration ****************************/ - -AliasDeclaration::AliasDeclaration(Loc loc, Identifier *id, Type *type) - : Declaration(id) -{ - //printf("AliasDeclaration(id = '%s', type = %p)\n", id->toChars(), type); - //printf("type = '%s'\n", type->toChars()); - this->loc = loc; - this->type = type; - this->aliassym = NULL; -#ifdef _DH - this->htype = NULL; - this->haliassym = NULL; -#endif - this->overnext = NULL; - this->inSemantic = 0; - assert(type); -} - -AliasDeclaration::AliasDeclaration(Loc loc, Identifier *id, Dsymbol *s) - : Declaration(id) -{ - //printf("AliasDeclaration(id = '%s', s = %p)\n", id->toChars(), s); - assert(s != this); - this->loc = loc; - this->type = NULL; - this->aliassym = s; -#ifdef _DH - this->htype = NULL; - this->haliassym = NULL; -#endif - this->overnext = NULL; - this->inSemantic = 0; - assert(s); -} - -Dsymbol *AliasDeclaration::syntaxCopy(Dsymbol *s) -{ - //printf("AliasDeclaration::syntaxCopy()\n"); - assert(!s); - AliasDeclaration *sa; - if (type) - sa = new AliasDeclaration(loc, ident, type->syntaxCopy()); - else - sa = new AliasDeclaration(loc, ident, aliassym->syntaxCopy(NULL)); -#ifdef _DH - // Syntax copy for header file - if (!htype) // Don't overwrite original - { if (type) // Make copy for both old and new instances - { htype = type->syntaxCopy(); - sa->htype = type->syntaxCopy(); - } - } - else // Make copy of original for new instance - sa->htype = htype->syntaxCopy(); - if (!haliassym) - { if (aliassym) - { haliassym = aliassym->syntaxCopy(s); - sa->haliassym = aliassym->syntaxCopy(s); - } - } - else - sa->haliassym = haliassym->syntaxCopy(s); -#endif - return sa; -} - -void AliasDeclaration::semantic(Scope *sc) -{ - //printf("AliasDeclaration::semantic() %s\n", toChars()); - if (aliassym) - { - if (aliassym->isTemplateInstance()) - aliassym->semantic(sc); - return; - } - this->inSemantic = 1; - - if (storage_class & STCconst) - error("cannot be const"); - - storage_class |= sc->stc & STCdeprecated; - - // Given: - // alias foo.bar.abc def; - // it is not knowable from the syntax whether this is an alias - // for a type or an alias for a symbol. It is up to the semantic() - // pass to distinguish. - // If it is a type, then type is set and getType() will return that - // type. If it is a symbol, then aliassym is set and type is NULL - - // toAlias() will return aliasssym. - - Dsymbol *s; - Type *t; - Expression *e; - - /* This section is needed because resolve() will: - * const x = 3; - * alias x y; - * try to alias y to 3. - */ - s = type->toDsymbol(sc); - if (s) - goto L2; // it's a symbolic alias - - //printf("alias type is %s\n", type->toChars()); - type->resolve(loc, sc, &e, &t, &s); - if (s) - { - goto L2; - } - else if (e) - { - // Try to convert Expression to Dsymbol - if (e->op == TOKvar) - { s = ((VarExp *)e)->var; - goto L2; - } - else if (e->op == TOKfunction) - { s = ((FuncExp *)e)->fd; - goto L2; - } - else - { error("cannot alias an expression %s", e->toChars()); - t = e->type; - } - } - else if (t) - type = t; - if (overnext) - ScopeDsymbol::multiplyDefined(0, this, overnext); - this->inSemantic = 0; - return; - - L2: - //printf("alias is a symbol %s %s\n", s->kind(), s->toChars()); - type = NULL; - VarDeclaration *v = s->isVarDeclaration(); - if (v && v->linkage == LINKdefault) - { - error("forward reference of %s", v->toChars()); - s = NULL; - } - else - { - FuncDeclaration *f = s->toAlias()->isFuncDeclaration(); - if (f) - { - if (overnext) - { - FuncAliasDeclaration *fa = new FuncAliasDeclaration(f); - if (!fa->overloadInsert(overnext)) - ScopeDsymbol::multiplyDefined(0, f, overnext); - overnext = NULL; - s = fa; - s->parent = sc->parent; - } - } - if (overnext) - ScopeDsymbol::multiplyDefined(0, s, overnext); - if (s == this) - { - assert(global.errors); - s = NULL; - } - } - aliassym = s; - this->inSemantic = 0; -} - -int AliasDeclaration::overloadInsert(Dsymbol *s) -{ - /* Don't know yet what the aliased symbol is, so assume it can - * be overloaded and check later for correctness. - */ - - //printf("AliasDeclaration::overloadInsert('%s')\n", s->toChars()); - if (overnext == NULL) - { overnext = s; - return TRUE; - } - else - { - return overnext->overloadInsert(s); - } -} - -const char *AliasDeclaration::kind() -{ - return "alias"; -} - -Type *AliasDeclaration::getType() -{ - return type; -} - -Dsymbol *AliasDeclaration::toAlias() -{ - //printf("AliasDeclaration::toAlias('%s', this = %p, aliassym = %p, kind = '%s')\n", toChars(), this, aliassym, aliassym ? aliassym->kind() : ""); - assert(this != aliassym); - //static int count; if (++count == 10) *(char*)0=0; - if (inSemantic) - { error("recursive alias declaration"); -// return this; - } - Dsymbol *s = aliassym ? aliassym->toAlias() : this; - return s; -} - -void AliasDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) -{ - buf->writestring("alias "); -#if 0 && _DH - if (hgs->hdrgen) - { - if (haliassym) - { - haliassym->toCBuffer(buf, hgs); - buf->writeByte(' '); - buf->writestring(ident->toChars()); - } - else - htype->toCBuffer(buf, ident, hgs); - } - else -#endif - { - if (aliassym) - { - aliassym->toCBuffer(buf, hgs); - buf->writeByte(' '); - buf->writestring(ident->toChars()); - } - else - type->toCBuffer(buf, ident, hgs); - } - buf->writeByte(';'); - buf->writenl(); -} - -/********************************* VarDeclaration ****************************/ - -VarDeclaration::VarDeclaration(Loc loc, Type *type, Identifier *id, Initializer *init) - : Declaration(id) -{ - //printf("VarDeclaration('%s')\n", id->toChars()); -#ifdef DEBUG - if (!type && !init) - { printf("VarDeclaration('%s')\n", id->toChars()); - //*(char*)0=0; - } -#endif - assert(type || init); - this->type = type; - this->init = init; -#ifdef _DH - this->htype = NULL; - this->hinit = NULL; -#endif - this->loc = loc; - offset = 0; - noauto = 0; - nestedref = 0; - inuse = 0; - ctorinit = 0; - aliassym = NULL; - onstack = 0; - canassign = 0; - value = NULL; - - // LDC - anonDecl = NULL; - offset2 = 0; - nakedUse = false; -} - -Dsymbol *VarDeclaration::syntaxCopy(Dsymbol *s) -{ - //printf("VarDeclaration::syntaxCopy(%s)\n", toChars()); - - VarDeclaration *sv; - if (s) - { sv = (VarDeclaration *)s; - } - else - { - Initializer *init = NULL; - if (this->init) - { init = this->init->syntaxCopy(); - //init->isExpInitializer()->exp->print(); - //init->isExpInitializer()->exp->dump(0); - } - - sv = new VarDeclaration(loc, type ? type->syntaxCopy() : NULL, ident, init); - sv->storage_class = storage_class; - } -#ifdef _DH - // Syntax copy for header file - if (!htype) // Don't overwrite original - { if (type) // Make copy for both old and new instances - { htype = type->syntaxCopy(); - sv->htype = type->syntaxCopy(); - } - } - else // Make copy of original for new instance - sv->htype = htype->syntaxCopy(); - if (!hinit) - { if (init) - { hinit = init->syntaxCopy(); - sv->hinit = init->syntaxCopy(); - } - } - else - sv->hinit = hinit->syntaxCopy(); -#endif - return sv; -} - -void VarDeclaration::semantic(Scope *sc) -{ - //printf("VarDeclaration::semantic('%s', parent = '%s')\n", toChars(), sc->parent->toChars()); - //printf(" type = %s\n", type ? type->toChars() : "null"); - //printf(" stc = x%x\n", sc->stc); - //printf(" storage_class = x%x\n", storage_class); - //printf("linkage = %d\n", sc->linkage); - //if (strcmp(toChars(), "mul") == 0) halt(); - - storage_class |= sc->stc; - if (storage_class & STCextern && init) - error("extern symbols cannot have initializers"); - - /* If auto type inference, do the inference - */ - int inferred = 0; - if (!type) - { inuse++; - type = init->inferType(sc); - inuse--; - inferred = 1; - - /* This is a kludge to support the existing syntax for RAII - * declarations. - */ - storage_class &= ~STCauto; - originalType = type; - } - else - { if (!originalType) - originalType = type; - type = type->semantic(loc, sc); - } - //printf(" semantic type = %s\n", type ? type->toChars() : "null"); - - type->checkDeprecated(loc, sc); - linkage = sc->linkage; - this->parent = sc->parent; - //printf("this = %p, parent = %p, '%s'\n", this, parent, parent->toChars()); - protection = sc->protection; - //printf("sc->stc = %x\n", sc->stc); - //printf("storage_class = x%x\n", storage_class); - - Dsymbol *parent = toParent(); - FuncDeclaration *fd = parent->isFuncDeclaration(); - - Type *tb = type->toBasetype(); - if (tb->ty == Tvoid && !(storage_class & STClazy)) - { error("voids have no value"); - type = Type::terror; - tb = type; - } - if (tb->ty == Tfunction) - { error("cannot be declared to be a function"); - type = Type::terror; - tb = type; - } - if (tb->ty == Tstruct) - { TypeStruct *ts = (TypeStruct *)tb; - - if (!ts->sym->members) - { - error("no definition of struct %s", ts->toChars()); - } - } - - if (tb->ty == Ttuple) - { /* Instead, declare variables for each of the tuple elements - * and add those. - */ - TypeTuple *tt = (TypeTuple *)tb; - size_t nelems = Argument::dim(tt->arguments); - Objects *exps = new Objects(); - exps->setDim(nelems); - Expression *ie = init ? init->toExpression() : NULL; - - for (size_t i = 0; i < nelems; i++) - { Argument *arg = Argument::getNth(tt->arguments, i); - - OutBuffer buf; - buf.printf("_%s_field_%zu", ident->toChars(), i); - buf.writeByte(0); - char *name = (char *)buf.extractData(); - Identifier *id = new Identifier(name, TOKidentifier); - - Expression *einit = ie; - if (ie && ie->op == TOKtuple) - { einit = (Expression *)((TupleExp *)ie)->exps->data[i]; - } - Initializer *ti = init; - if (einit) - { ti = new ExpInitializer(einit->loc, einit); - } - - VarDeclaration *v = new VarDeclaration(loc, arg->type, id, ti); - //printf("declaring field %s of type %s\n", v->toChars(), v->type->toChars()); - v->semantic(sc); - -/* -// removed for LDC since TupleDeclaration::toObj already creates the fields; -// adding them to the scope again leads to duplicates - if (sc->scopesym) - { //printf("adding %s to %s\n", v->toChars(), sc->scopesym->toChars()); - if (sc->scopesym->members) - sc->scopesym->members->push(v); - } -*/ - Expression *e = new DsymbolExp(loc, v); - exps->data[i] = e; - } - TupleDeclaration *v2 = new TupleDeclaration(loc, ident, exps); - v2->isexp = 1; - aliassym = v2; - return; - } - - if (storage_class & STCconst && !init && !fd) - // Initialize by constructor only - storage_class = (storage_class & ~STCconst) | STCctorinit; - - if (isConst()) - { - } - else if (isStatic()) - { - } - else if (isSynchronized()) - { - error("variable %s cannot be synchronized", toChars()); - } - else if (isOverride()) - { - error("override cannot be applied to variable"); - } - else if (isAbstract()) - { - error("abstract cannot be applied to variable"); - } - else if (storage_class & STCtemplateparameter) - { - } - else - { - AggregateDeclaration *aad = sc->anonAgg; - if (!aad) - aad = parent->isAggregateDeclaration(); - if (aad) - { - aad->addField(sc, this); - } - - InterfaceDeclaration *id = parent->isInterfaceDeclaration(); - if (id) - { - error("field not allowed in interface"); - } - - /* Templates cannot add fields to aggregates - */ - TemplateInstance *ti = parent->isTemplateInstance(); - if (ti) - { - // Take care of nested templates - while (1) - { - TemplateInstance *ti2 = ti->tempdecl->parent->isTemplateInstance(); - if (!ti2) - break; - ti = ti2; - } - - // If it's a member template - AggregateDeclaration *ad = ti->tempdecl->isMember(); - if (ad && storage_class != STCundefined) - { - error("cannot use template to add field to aggregate '%s'", ad->toChars()); - } - } - } - - if (type->isauto() && !noauto) - { - if (storage_class & (STCfield | STCout | STCref | STCstatic) || !fd) - { - error("globals, statics, fields, ref and out parameters cannot be auto"); - } - - if (!(storage_class & (STCauto | STCscope))) - { - if (!(storage_class & STCparameter) && ident != Id::withSym) - error("reference to scope class must be scope"); - } - } - - if (!init && !sc->inunion && !isStatic() && !isConst() && fd && - !(storage_class & (STCfield | STCin | STCforeach)) && - type->size() != 0) - { - // Provide a default initializer - //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); - e = new AssignExp(loc, e1, e); - e->type = e1->type; - init = new ExpInitializer(loc, e/*->type->defaultInit()*/); - return; - } - else if (type->ty == Ttypedef) - { TypeTypedef *td = (TypeTypedef *)type; - if (td->sym->init) - { init = td->sym->init; - ExpInitializer *ie = init->isExpInitializer(); - if (ie) - // Make copy so we can modify it - init = new ExpInitializer(ie->loc, ie->exp); - } - else - init = getExpInitializer(); - } - else - { - init = getExpInitializer(); - } - } - - if (init) - { - sc = sc->push(); - sc->stc &= ~(STCconst | STCinvariant | STCpure); - - ArrayInitializer *ai = init->isArrayInitializer(); - if (ai && tb->ty == Taarray) - { - init = ai->toAssocArrayInitializer(); - } - - StructInitializer *si = init->isStructInitializer(); - ExpInitializer *ei = init->isExpInitializer(); - - // See if we can allocate on the stack - if (ei && isScope() && ei->exp->op == TOKnew) - { NewExp *ne = (NewExp *)ei->exp; - if (!(ne->newargs && ne->newargs->dim)) - { ne->onstack = 1; - onstack = 1; - if (type->isBaseOf(ne->newtype->semantic(loc, sc), NULL)) - onstack = 2; - } - } - - // If inside function, there is no semantic3() call - if (sc->func) - { - // If local variable, use AssignExp to handle all the various - // possibilities. - if (fd && !isStatic() && !isConst() && !init->isVoidInitializer()) - { - //printf("fd = '%s', var = '%s'\n", fd->toChars(), toChars()); - if (!ei) - { - Expression *e = init->toExpression(); - if (!e) - { - init = init->semantic(sc, type); - e = init->toExpression(); - if (!e) - { error("is not a static and cannot have static initializer"); - return; - } - } - ei = new ExpInitializer(init->loc, e); - init = ei; - } - - Expression *e1 = new VarExp(loc, this); - - Type *t = type->toBasetype(); - if (t->ty == Tsarray) - { - ei->exp = ei->exp->semantic(sc); - if (!ei->exp->implicitConvTo(type)) - { - int dim = ((TypeSArray *)t)->dim->toInteger(); - // If multidimensional static array, treat as one large array - while (1) - { - t = t->nextOf()->toBasetype(); - if (t->ty != Tsarray) - break; - dim *= ((TypeSArray *)t)->dim->toInteger(); - e1->type = new TypeSArray(t->nextOf(), new IntegerExp(0, dim, Type::tindex)); - } - } - e1 = new SliceExp(loc, e1, NULL, NULL); - } - else if (t->ty == Tstruct) - { - ei->exp = ei->exp->semantic(sc); - if (!ei->exp->implicitConvTo(type)) - ei->exp = new CastExp(loc, ei->exp, type); - } - ei->exp = new AssignExp(loc, e1, ei->exp); - ei->exp->op = TOKconstruct; - canassign++; - ei->exp = ei->exp->semantic(sc); - canassign--; - ei->exp->optimize(WANTvalue); - } - else - { - init = init->semantic(sc, type); - if (fd && isConst() && !isStatic()) - { // Make it static - storage_class |= STCstatic; - } - } - } - else if (isConst() || isFinal()) - { - /* Because we may need the results of a const declaration in a - * subsequent type, such as an array dimension, before semantic2() - * gets ordinarily run, try to run semantic2() now. - * Ignore failure. - */ - - if (!global.errors && !inferred) - { - unsigned errors = global.errors; - global.gag++; - //printf("+gag\n"); - Expression *e; - Initializer *i2 = init; - inuse++; - 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--; - global.gag--; - //printf("-gag\n"); - if (errors != global.errors) // if errors happened - { - if (global.gag == 0) - global.errors = errors; // act as if nothing happened - } - else if (ei) - { - e = e->optimize(WANTvalue | WANTinterpret); - if (e->op == TOKint64 || e->op == TOKstring) - { - ei->exp = e; // no errors, keep result - } - } - else - init = i2; // no errors, keep result - } - } - sc = sc->pop(); - } -} - -ExpInitializer *VarDeclaration::getExpInitializer() -{ - ExpInitializer *ei; - - if (init) - ei = init->isExpInitializer(); - else - { - Expression *e = type->defaultInit(loc); - if (e) - ei = new ExpInitializer(loc, e); - else - ei = NULL; - } - return ei; -} - -void VarDeclaration::semantic2(Scope *sc) -{ - //printf("VarDeclaration::semantic2('%s')\n", toChars()); - if (init && !toParent()->isFuncDeclaration()) - { inuse++; -#if 0 - ExpInitializer *ei = init->isExpInitializer(); - if (ei) - { - ei->exp->dump(0); - printf("type = %p\n", ei->exp->type); - } -#endif - init = init->semantic(sc, type); - inuse--; - } -} - -const char *VarDeclaration::kind() -{ - return "variable"; -} - -Dsymbol *VarDeclaration::toAlias() -{ - //printf("VarDeclaration::toAlias('%s', this = %p, aliassym = %p)\n", toChars(), this, aliassym); - assert(this != aliassym); - Dsymbol *s = aliassym ? aliassym->toAlias() : this; - return s; -} - -void VarDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) -{ - if (storage_class & STCconst) - buf->writestring("const "); - if (storage_class & STCstatic) - buf->writestring("static "); - if (storage_class & STCauto) - buf->writestring("auto "); -#if DMDV2 - if (storage_class & STCmanifest) - buf->writestring("manifest "); - if (storage_class & STCinvariant) - buf->writestring("invariant "); - if (storage_class & STCtls) - buf->writestring("__thread "); -#endif - - if (type) - type->toCBuffer(buf, ident, hgs); - else - buf->writestring(ident->toChars()); - if (init) - { buf->writestring(" = "); - init->toCBuffer(buf, hgs); - } - buf->writeByte(';'); - buf->writenl(); -} - -int VarDeclaration::needThis() -{ - //printf("VarDeclaration::needThis(%s, x%x)\n", toChars(), storage_class); - return storage_class & STCfield; -} - -int VarDeclaration::isImportedSymbol() -{ - if (protection == PROTexport && !init && (isStatic() || isConst() || parent->isModule())) - return TRUE; - return FALSE; -} - -void VarDeclaration::checkCtorConstInit() -{ - if (ctorinit == 0 && isCtorinit() && !(storage_class & STCfield)) - error("missing initializer in static constructor for const variable"); -} - -/************************************ - * Check to see if this variable is actually in an enclosing function - * rather than the current one. - */ - -void VarDeclaration::checkNestedReference(Scope *sc, Loc loc) -{ - //printf("VarDeclaration::checkNestedReference() %s\n", toChars()); - if (parent && !isDataseg() && parent != sc->parent) - { - // The function that this variable is in - FuncDeclaration *fdv = toParent()->isFuncDeclaration(); - // The current function - FuncDeclaration *fdthis = sc->parent->isFuncDeclaration(); - - if (fdv && fdthis) - { - if (loc.filename) - fdthis->getLevel(loc, fdv); - nestedref = 1; - fdv->nestedFrameRef = 1; - fdv->nestedVars.insert(this); - //printf("var %s in function %s is nested ref\n", toChars(), fdv->toChars()); - } - } -} - -/******************************* - * Does symbol go into data segment? - * Includes extern variables. - */ - -int VarDeclaration::isDataseg() -{ -#if 0 - printf("VarDeclaration::isDataseg(%p, '%s')\n", this, toChars()); - printf("%x, %p, %p\n", storage_class & (STCstatic | STCconst), parent->isModule(), parent->isTemplateInstance()); - printf("parent = '%s'\n", parent->toChars()); -#endif - Dsymbol *parent = this->toParent(); - if (!parent && !(storage_class & (STCstatic | STCconst))) - { error("forward referenced"); - type = Type::terror; - return 0; - } - return (storage_class & (STCstatic | STCconst) || - parent->isModule() || - parent->isTemplateInstance()); -} - -int VarDeclaration::hasPointers() -{ - return (!isDataseg() && type->hasPointers()); -} - -/****************************************** - * If a variable has an auto destructor call, return call for it. - * Otherwise, return NULL. - */ - -Expression *VarDeclaration::callAutoDtor() -{ Expression *e = NULL; - - //printf("VarDeclaration::callAutoDtor() %s\n", toChars()); - if (storage_class & (STCauto | STCscope) && !noauto) - { - for (ClassDeclaration *cd = type->isClassHandle(); - cd; - cd = cd->baseClass) - { - /* We can do better if there's a way with onstack - * classes to determine if there's no way the monitor - * could be set. - */ - //if (cd->isInterfaceDeclaration()) - //error("interface %s cannot be scope", cd->toChars()); - if (1 || onstack || cd->dtors.dim) // if any destructors - { - // delete this; - Expression *ec; - - ec = new VarExp(loc, this); - e = new DeleteExp(loc, ec); - e->type = Type::tvoid; - break; - } - } - } - return e; -} - - -/********************************* ClassInfoDeclaration ****************************/ - -ClassInfoDeclaration::ClassInfoDeclaration(ClassDeclaration *cd) - : VarDeclaration(0, ClassDeclaration::classinfo->type, cd->ident, NULL) -{ - this->cd = cd; - storage_class = STCstatic; -} - -Dsymbol *ClassInfoDeclaration::syntaxCopy(Dsymbol *s) -{ - assert(0); // should never be produced by syntax - return NULL; -} - -void ClassInfoDeclaration::semantic(Scope *sc) -{ -} - -/********************************* ModuleInfoDeclaration ****************************/ - -ModuleInfoDeclaration::ModuleInfoDeclaration(Module *mod) - : VarDeclaration(0, Module::moduleinfo->type, mod->ident, NULL) -{ - this->mod = mod; - storage_class = STCstatic; -} - -Dsymbol *ModuleInfoDeclaration::syntaxCopy(Dsymbol *s) -{ - assert(0); // should never be produced by syntax - return NULL; -} - -void ModuleInfoDeclaration::semantic(Scope *sc) -{ -} - -/********************************* TypeInfoDeclaration ****************************/ - -TypeInfoDeclaration::TypeInfoDeclaration(Type *tinfo, int internal) - : VarDeclaration(0, Type::typeinfo->type, tinfo->getTypeInfoIdent(internal), NULL) -{ - this->tinfo = tinfo; - storage_class = STCstatic; - protection = PROTpublic; - linkage = LINKc; -} - -Dsymbol *TypeInfoDeclaration::syntaxCopy(Dsymbol *s) -{ - assert(0); // should never be produced by syntax - return NULL; -} - -void TypeInfoDeclaration::semantic(Scope *sc) -{ - assert(linkage == LINKc); -} - -/***************************** TypeInfoConstDeclaration **********************/ - -#if DMDV2 -TypeInfoConstDeclaration::TypeInfoConstDeclaration(Type *tinfo) - : TypeInfoDeclaration(tinfo, 0) -{ -} -#endif - -/***************************** TypeInfoInvariantDeclaration **********************/ - -#if DMDV2 -TypeInfoInvariantDeclaration::TypeInfoInvariantDeclaration(Type *tinfo) - : TypeInfoDeclaration(tinfo, 0) -{ -} -#endif - -/***************************** TypeInfoStructDeclaration **********************/ - -TypeInfoStructDeclaration::TypeInfoStructDeclaration(Type *tinfo) - : TypeInfoDeclaration(tinfo, 0) -{ -} - -/***************************** TypeInfoClassDeclaration ***********************/ - -TypeInfoClassDeclaration::TypeInfoClassDeclaration(Type *tinfo) - : TypeInfoDeclaration(tinfo, 0) -{ -} - -/***************************** TypeInfoInterfaceDeclaration *******************/ - -TypeInfoInterfaceDeclaration::TypeInfoInterfaceDeclaration(Type *tinfo) - : TypeInfoDeclaration(tinfo, 0) -{ -} - -/***************************** TypeInfoTypedefDeclaration *********************/ - -TypeInfoTypedefDeclaration::TypeInfoTypedefDeclaration(Type *tinfo) - : TypeInfoDeclaration(tinfo, 0) -{ -} - -/***************************** TypeInfoPointerDeclaration *********************/ - -TypeInfoPointerDeclaration::TypeInfoPointerDeclaration(Type *tinfo) - : TypeInfoDeclaration(tinfo, 0) -{ -} - -/***************************** TypeInfoArrayDeclaration ***********************/ - -TypeInfoArrayDeclaration::TypeInfoArrayDeclaration(Type *tinfo) - : TypeInfoDeclaration(tinfo, 0) -{ -} - -/***************************** TypeInfoStaticArrayDeclaration *****************/ - -TypeInfoStaticArrayDeclaration::TypeInfoStaticArrayDeclaration(Type *tinfo) - : TypeInfoDeclaration(tinfo, 0) -{ -} - -/***************************** TypeInfoAssociativeArrayDeclaration ************/ - -TypeInfoAssociativeArrayDeclaration::TypeInfoAssociativeArrayDeclaration(Type *tinfo) - : TypeInfoDeclaration(tinfo, 0) -{ -} - -/***************************** TypeInfoEnumDeclaration ***********************/ - -TypeInfoEnumDeclaration::TypeInfoEnumDeclaration(Type *tinfo) - : TypeInfoDeclaration(tinfo, 0) -{ -} - -/***************************** TypeInfoFunctionDeclaration ********************/ - -TypeInfoFunctionDeclaration::TypeInfoFunctionDeclaration(Type *tinfo) - : TypeInfoDeclaration(tinfo, 0) -{ -} - -/***************************** TypeInfoDelegateDeclaration ********************/ - -TypeInfoDelegateDeclaration::TypeInfoDelegateDeclaration(Type *tinfo) - : TypeInfoDeclaration(tinfo, 0) -{ -} - -/***************************** TypeInfoTupleDeclaration **********************/ - -TypeInfoTupleDeclaration::TypeInfoTupleDeclaration(Type *tinfo) - : TypeInfoDeclaration(tinfo, 0) -{ -} - -/********************************* ThisDeclaration ****************************/ - -// For the "this" parameter to member functions - -ThisDeclaration::ThisDeclaration(Type *t) - : VarDeclaration(0, t, Id::This, NULL) -{ - noauto = 1; -} - -Dsymbol *ThisDeclaration::syntaxCopy(Dsymbol *s) -{ - assert(0); // should never be produced by syntax - return NULL; -} - -/********************** StaticStructInitDeclaration ***************************/ - -StaticStructInitDeclaration::StaticStructInitDeclaration(Loc loc, StructDeclaration *dsym) - : Declaration(new Identifier("", TOKidentifier)) -{ - this->loc = loc; - this->dsym = dsym; - storage_class |= STCconst; -} - + +// Compiler implementation of the D programming language +// Copyright (c) 1999-2009 by Digital Mars +// All Rights Reserved +// written by Walter Bright +// 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. + +#include +#include + +#include "init.h" +#include "declaration.h" +#include "attrib.h" +#include "mtype.h" +#include "template.h" +#include "scope.h" +#include "aggregate.h" +#include "module.h" +#include "id.h" +#include "expression.h" +#include "hdrgen.h" + +/********************************* Declaration ****************************/ + +Declaration::Declaration(Identifier *id) + : Dsymbol(id) +{ + type = NULL; + originalType = NULL; + storage_class = STCundefined; + protection = PROTundefined; + linkage = LINKdefault; +} + +void Declaration::semantic(Scope *sc) +{ +} + +const char *Declaration::kind() +{ + return "declaration"; +} + +unsigned Declaration::size(Loc loc) +{ + assert(type); + return type->size(); +} + +int Declaration::isStaticConstructor() +{ + return FALSE; +} + +int Declaration::isStaticDestructor() +{ + return FALSE; +} + +int Declaration::isDelete() +{ + return FALSE; +} + +int Declaration::isDataseg() +{ + return FALSE; +} + +int Declaration::isCodeseg() +{ + return FALSE; +} + +enum PROT Declaration::prot() +{ + return protection; +} + +/************************************* + * Check to see if declaration can be modified in this context (sc). + * Issue error if not. + */ + +#if DMDV2 +void Declaration::checkModify(Loc loc, Scope *sc, Type *t) +{ + if (sc->incontract && isParameter()) + error(loc, "cannot modify parameter '%s' in contract", toChars()); + + if (isCtorinit()) + { // It's only modifiable if inside the right constructor + Dsymbol *s = sc->func; + while (1) + { + FuncDeclaration *fd = NULL; + if (s) + fd = s->isFuncDeclaration(); + if (fd && + ((fd->isCtorDeclaration() && storage_class & STCfield) || + (fd->isStaticCtorDeclaration() && !(storage_class & STCfield))) && + fd->toParent() == toParent() + ) + { + VarDeclaration *v = isVarDeclaration(); + assert(v); + v->ctorinit = 1; + //printf("setting ctorinit\n"); + } + else + { + if (s) + { s = s->toParent2(); + continue; + } + else + { + const char *p = isStatic() ? "static " : ""; + error(loc, "can only initialize %sconst %s inside %sconstructor", + p, toChars(), p); + } + } + break; + } + } + else + { + VarDeclaration *v = isVarDeclaration(); + if (v && v->canassign == 0) + { + char *p = NULL; + if (isConst()) + p = "const"; + else if (isInvariant()) + p = "invariant"; + else if (storage_class & STCmanifest) + p = "manifest constant"; + else if (!t->isAssignable()) + p = "struct with immutable members"; + if (p) + { error(loc, "cannot modify %s", p); + halt(); + } + } + } +} +#endif + + +/********************************* TupleDeclaration ****************************/ + +TupleDeclaration::TupleDeclaration(Loc loc, Identifier *id, Objects *objects) + : Declaration(id) +{ + this->type = NULL; + this->objects = objects; + this->isexp = 0; + this->tupletype = NULL; +} + +Dsymbol *TupleDeclaration::syntaxCopy(Dsymbol *s) +{ + assert(0); + return NULL; +} + +const char *TupleDeclaration::kind() +{ + return "tuple"; +} + +Type *TupleDeclaration::getType() +{ + /* If this tuple represents a type, return that type + */ + + //printf("TupleDeclaration::getType() %s\n", toChars()); + if (isexp) + return NULL; + if (!tupletype) + { + /* It's only a type tuple if all the Object's are types + */ + for (size_t i = 0; i < objects->dim; i++) + { Object *o = (Object *)objects->data[i]; + + if (o->dyncast() != DYNCAST_TYPE) + { + //printf("\tnot[%d], %p, %d\n", i, o, o->dyncast()); + return NULL; + } + } + + /* We know it's a type tuple, so build the TypeTuple + */ + Arguments *args = new Arguments(); + args->setDim(objects->dim); + OutBuffer buf; + for (size_t i = 0; i < objects->dim; i++) + { Type *t = (Type *)objects->data[i]; + + //printf("type = %s\n", t->toChars()); +#if 0 + buf.printf("_%s_%d", ident->toChars(), i); + char *name = (char *)buf.extractData(); + Identifier *id = new Identifier(name, TOKidentifier); + Argument *arg = new Argument(STCin, t, id, NULL); +#else + Argument *arg = new Argument(STCin, t, NULL, NULL); +#endif + args->data[i] = (void *)arg; + } + + tupletype = new TypeTuple(args); + } + + return tupletype; +} + +int TupleDeclaration::needThis() +{ + //printf("TupleDeclaration::needThis(%s)\n", toChars()); + for (size_t i = 0; i < objects->dim; i++) + { Object *o = (Object *)objects->data[i]; + if (o->dyncast() == DYNCAST_EXPRESSION) + { Expression *e = (Expression *)o; + if (e->op == TOKdsymbol) + { DsymbolExp *ve = (DsymbolExp *)e; + Declaration *d = ve->s->isDeclaration(); + if (d && d->needThis()) + { + return 1; + } + } + } + } + return 0; +} + +/********************************* TypedefDeclaration ****************************/ + +TypedefDeclaration::TypedefDeclaration(Loc loc, Identifier *id, Type *basetype, Initializer *init) + : Declaration(id) +{ + this->type = new TypeTypedef(this); + this->basetype = basetype->toBasetype(); + this->init = init; +#ifdef _DH + this->htype = NULL; + this->hbasetype = NULL; +#endif + this->sem = 0; + this->inuse = 0; + this->loc = loc; +#if IN_DMD + this->sinit = NULL; +#endif +} + +Dsymbol *TypedefDeclaration::syntaxCopy(Dsymbol *s) +{ + Type *basetype = this->basetype->syntaxCopy(); + + Initializer *init = NULL; + if (this->init) + init = this->init->syntaxCopy(); + + assert(!s); + TypedefDeclaration *st; + st = new TypedefDeclaration(loc, ident, basetype, init); +#ifdef _DH + // Syntax copy for header file + if (!htype) // Don't overwrite original + { if (type) // Make copy for both old and new instances + { htype = type->syntaxCopy(); + st->htype = type->syntaxCopy(); + } + } + else // Make copy of original for new instance + st->htype = htype->syntaxCopy(); + if (!hbasetype) + { if (basetype) + { hbasetype = basetype->syntaxCopy(); + st->hbasetype = basetype->syntaxCopy(); + } + } + else + st->hbasetype = hbasetype->syntaxCopy(); +#endif + return st; +} + +void TypedefDeclaration::semantic(Scope *sc) +{ + //printf("TypedefDeclaration::semantic(%s) sem = %d\n", toChars(), sem); + if (sem == 0) + { sem = 1; + basetype = basetype->semantic(loc, sc); + sem = 2; + type = type->semantic(loc, sc); + if (sc->parent->isFuncDeclaration() && init) + semantic2(sc); + storage_class |= sc->stc & STCdeprecated; + } + else if (sem == 1) + { + error("circular definition"); + } +} + +void TypedefDeclaration::semantic2(Scope *sc) +{ + //printf("TypedefDeclaration::semantic2(%s) sem = %d\n", toChars(), sem); + if (sem == 2) + { sem = 3; + if (init) + { + init = init->semantic(sc, basetype); + + ExpInitializer *ie = init->isExpInitializer(); + if (ie) + { + if (ie->exp->type == basetype) + ie->exp->type = type; + } + } + } +} + +const char *TypedefDeclaration::kind() +{ + return "typedef"; +} + +Type *TypedefDeclaration::getType() +{ + return type; +} + +void TypedefDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) +{ + buf->writestring("typedef "); + basetype->toCBuffer(buf, ident, hgs); + if (init) + { + buf->writestring(" = "); + init->toCBuffer(buf, hgs); + } + buf->writeByte(';'); + buf->writenl(); +} + +/********************************* AliasDeclaration ****************************/ + +AliasDeclaration::AliasDeclaration(Loc loc, Identifier *id, Type *type) + : Declaration(id) +{ + //printf("AliasDeclaration(id = '%s', type = %p)\n", id->toChars(), type); + //printf("type = '%s'\n", type->toChars()); + this->loc = loc; + this->type = type; + this->aliassym = NULL; +#ifdef _DH + this->htype = NULL; + this->haliassym = NULL; +#endif + this->overnext = NULL; + this->inSemantic = 0; + assert(type); +} + +AliasDeclaration::AliasDeclaration(Loc loc, Identifier *id, Dsymbol *s) + : Declaration(id) +{ + //printf("AliasDeclaration(id = '%s', s = %p)\n", id->toChars(), s); + assert(s != this); + this->loc = loc; + this->type = NULL; + this->aliassym = s; +#ifdef _DH + this->htype = NULL; + this->haliassym = NULL; +#endif + this->overnext = NULL; + this->inSemantic = 0; + assert(s); +} + +Dsymbol *AliasDeclaration::syntaxCopy(Dsymbol *s) +{ + //printf("AliasDeclaration::syntaxCopy()\n"); + assert(!s); + AliasDeclaration *sa; + if (type) + sa = new AliasDeclaration(loc, ident, type->syntaxCopy()); + else + sa = new AliasDeclaration(loc, ident, aliassym->syntaxCopy(NULL)); +#ifdef _DH + // Syntax copy for header file + if (!htype) // Don't overwrite original + { if (type) // Make copy for both old and new instances + { htype = type->syntaxCopy(); + sa->htype = type->syntaxCopy(); + } + } + else // Make copy of original for new instance + sa->htype = htype->syntaxCopy(); + if (!haliassym) + { if (aliassym) + { haliassym = aliassym->syntaxCopy(s); + sa->haliassym = aliassym->syntaxCopy(s); + } + } + else + sa->haliassym = haliassym->syntaxCopy(s); +#endif + return sa; +} + +void AliasDeclaration::semantic(Scope *sc) +{ + //printf("AliasDeclaration::semantic() %s\n", toChars()); + if (aliassym) + { + if (aliassym->isTemplateInstance()) + aliassym->semantic(sc); + return; + } + this->inSemantic = 1; + + if (storage_class & STCconst) + error("cannot be const"); + + storage_class |= sc->stc & STCdeprecated; + + // Given: + // alias foo.bar.abc def; + // it is not knowable from the syntax whether this is an alias + // for a type or an alias for a symbol. It is up to the semantic() + // pass to distinguish. + // If it is a type, then type is set and getType() will return that + // type. If it is a symbol, then aliassym is set and type is NULL - + // toAlias() will return aliasssym. + + Dsymbol *s; + Type *t; + Expression *e; + + /* This section is needed because resolve() will: + * const x = 3; + * alias x y; + * try to alias y to 3. + */ + s = type->toDsymbol(sc); + if (s) + goto L2; // it's a symbolic alias + + //printf("alias type is %s\n", type->toChars()); + type->resolve(loc, sc, &e, &t, &s); + if (s) + { + goto L2; + } + else if (e) + { + // Try to convert Expression to Dsymbol + if (e->op == TOKvar) + { s = ((VarExp *)e)->var; + goto L2; + } + else if (e->op == TOKfunction) + { s = ((FuncExp *)e)->fd; + goto L2; + } + else + { error("cannot alias an expression %s", e->toChars()); + t = e->type; + } + } + else if (t) + type = t; + if (overnext) + ScopeDsymbol::multiplyDefined(0, this, overnext); + this->inSemantic = 0; + return; + + L2: + //printf("alias is a symbol %s %s\n", s->kind(), s->toChars()); + type = NULL; + VarDeclaration *v = s->isVarDeclaration(); + if (v && v->linkage == LINKdefault) + { + error("forward reference of %s", v->toChars()); + s = NULL; + } + else + { + FuncDeclaration *f = s->toAlias()->isFuncDeclaration(); + if (f) + { + if (overnext) + { + FuncAliasDeclaration *fa = new FuncAliasDeclaration(f); + if (!fa->overloadInsert(overnext)) + ScopeDsymbol::multiplyDefined(0, f, overnext); + overnext = NULL; + s = fa; + s->parent = sc->parent; + } + } + if (overnext) + ScopeDsymbol::multiplyDefined(0, s, overnext); + if (s == this) + { + assert(global.errors); + s = NULL; + } + } + aliassym = s; + this->inSemantic = 0; +} + +int AliasDeclaration::overloadInsert(Dsymbol *s) +{ + /* Don't know yet what the aliased symbol is, so assume it can + * be overloaded and check later for correctness. + */ + + //printf("AliasDeclaration::overloadInsert('%s')\n", s->toChars()); + if (overnext == NULL) + { overnext = s; + return TRUE; + } + else + { + return overnext->overloadInsert(s); + } +} + +const char *AliasDeclaration::kind() +{ + return "alias"; +} + +Type *AliasDeclaration::getType() +{ + return type; +} + +Dsymbol *AliasDeclaration::toAlias() +{ + //printf("AliasDeclaration::toAlias('%s', this = %p, aliassym = %p, kind = '%s')\n", toChars(), this, aliassym, aliassym ? aliassym->kind() : ""); + assert(this != aliassym); + //static int count; if (++count == 10) *(char*)0=0; + if (inSemantic) + { error("recursive alias declaration"); +// return this; + } + Dsymbol *s = aliassym ? aliassym->toAlias() : this; + return s; +} + +void AliasDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) +{ + buf->writestring("alias "); +#if 0 && _DH + if (hgs->hdrgen) + { + if (haliassym) + { + haliassym->toCBuffer(buf, hgs); + buf->writeByte(' '); + buf->writestring(ident->toChars()); + } + else + htype->toCBuffer(buf, ident, hgs); + } + else +#endif + { + if (aliassym) + { + aliassym->toCBuffer(buf, hgs); + buf->writeByte(' '); + buf->writestring(ident->toChars()); + } + else + type->toCBuffer(buf, ident, hgs); + } + buf->writeByte(';'); + buf->writenl(); +} + +/********************************* VarDeclaration ****************************/ + +VarDeclaration::VarDeclaration(Loc loc, Type *type, Identifier *id, Initializer *init) + : Declaration(id) +{ + //printf("VarDeclaration('%s')\n", id->toChars()); +#ifdef DEBUG + if (!type && !init) + { printf("VarDeclaration('%s')\n", id->toChars()); + //*(char*)0=0; + } +#endif + assert(type || init); + this->type = type; + this->init = init; +#ifdef _DH + this->htype = NULL; + this->hinit = NULL; +#endif + this->loc = loc; + offset = 0; + noauto = 0; + nestedref = 0; + inuse = 0; + ctorinit = 0; + aliassym = NULL; + onstack = 0; + canassign = 0; + value = NULL; + + // LDC + anonDecl = NULL; + offset2 = 0; + nakedUse = false; +} + +Dsymbol *VarDeclaration::syntaxCopy(Dsymbol *s) +{ + //printf("VarDeclaration::syntaxCopy(%s)\n", toChars()); + + VarDeclaration *sv; + if (s) + { sv = (VarDeclaration *)s; + } + else + { + Initializer *init = NULL; + if (this->init) + { init = this->init->syntaxCopy(); + //init->isExpInitializer()->exp->print(); + //init->isExpInitializer()->exp->dump(0); + } + + sv = new VarDeclaration(loc, type ? type->syntaxCopy() : NULL, ident, init); + sv->storage_class = storage_class; + } +#ifdef _DH + // Syntax copy for header file + if (!htype) // Don't overwrite original + { if (type) // Make copy for both old and new instances + { htype = type->syntaxCopy(); + sv->htype = type->syntaxCopy(); + } + } + else // Make copy of original for new instance + sv->htype = htype->syntaxCopy(); + if (!hinit) + { if (init) + { hinit = init->syntaxCopy(); + sv->hinit = init->syntaxCopy(); + } + } + else + sv->hinit = hinit->syntaxCopy(); +#endif + return sv; +} + +void VarDeclaration::semantic(Scope *sc) +{ + //printf("VarDeclaration::semantic('%s', parent = '%s')\n", toChars(), sc->parent->toChars()); + //printf(" type = %s\n", type ? type->toChars() : "null"); + //printf(" stc = x%x\n", sc->stc); + //printf(" storage_class = x%x\n", storage_class); + //printf("linkage = %d\n", sc->linkage); + //if (strcmp(toChars(), "mul") == 0) halt(); + + storage_class |= sc->stc; + if (storage_class & STCextern && init) + error("extern symbols cannot have initializers"); + + /* If auto type inference, do the inference + */ + int inferred = 0; + if (!type) + { inuse++; + type = init->inferType(sc); + inuse--; + inferred = 1; + + /* This is a kludge to support the existing syntax for RAII + * declarations. + */ + storage_class &= ~STCauto; + originalType = type; + } + else + { if (!originalType) + originalType = type; + type = type->semantic(loc, sc); + } + //printf(" semantic type = %s\n", type ? type->toChars() : "null"); + + type->checkDeprecated(loc, sc); + linkage = sc->linkage; + this->parent = sc->parent; + //printf("this = %p, parent = %p, '%s'\n", this, parent, parent->toChars()); + protection = sc->protection; + //printf("sc->stc = %x\n", sc->stc); + //printf("storage_class = x%x\n", storage_class); + + Dsymbol *parent = toParent(); + FuncDeclaration *fd = parent->isFuncDeclaration(); + + Type *tb = type->toBasetype(); + if (tb->ty == Tvoid && !(storage_class & STClazy)) + { error("voids have no value"); + type = Type::terror; + tb = type; + } + if (tb->ty == Tfunction) + { error("cannot be declared to be a function"); + type = Type::terror; + tb = type; + } + if (tb->ty == Tstruct) + { TypeStruct *ts = (TypeStruct *)tb; + + if (!ts->sym->members) + { + error("no definition of struct %s", ts->toChars()); + } + } + + if (tb->ty == Ttuple) + { /* Instead, declare variables for each of the tuple elements + * and add those. + */ + TypeTuple *tt = (TypeTuple *)tb; + size_t nelems = Argument::dim(tt->arguments); + Objects *exps = new Objects(); + exps->setDim(nelems); + Expression *ie = init ? init->toExpression() : NULL; + + for (size_t i = 0; i < nelems; i++) + { Argument *arg = Argument::getNth(tt->arguments, i); + + OutBuffer buf; + buf.printf("_%s_field_%zu", ident->toChars(), i); + buf.writeByte(0); + char *name = (char *)buf.extractData(); + Identifier *id = new Identifier(name, TOKidentifier); + + Expression *einit = ie; + if (ie && ie->op == TOKtuple) + { einit = (Expression *)((TupleExp *)ie)->exps->data[i]; + } + Initializer *ti = init; + if (einit) + { ti = new ExpInitializer(einit->loc, einit); + } + + VarDeclaration *v = new VarDeclaration(loc, arg->type, id, ti); + //printf("declaring field %s of type %s\n", v->toChars(), v->type->toChars()); + v->semantic(sc); + +/* +// removed for LDC since TupleDeclaration::toObj already creates the fields; +// adding them to the scope again leads to duplicates + if (sc->scopesym) + { //printf("adding %s to %s\n", v->toChars(), sc->scopesym->toChars()); + if (sc->scopesym->members) + sc->scopesym->members->push(v); + } +*/ + Expression *e = new DsymbolExp(loc, v); + exps->data[i] = e; + } + TupleDeclaration *v2 = new TupleDeclaration(loc, ident, exps); + v2->isexp = 1; + aliassym = v2; + return; + } + + if (storage_class & STCconst && !init && !fd) + // Initialize by constructor only + storage_class = (storage_class & ~STCconst) | STCctorinit; + + if (isConst()) + { + } + else if (isStatic()) + { + } + else if (isSynchronized()) + { + error("variable %s cannot be synchronized", toChars()); + } + else if (isOverride()) + { + error("override cannot be applied to variable"); + } + else if (isAbstract()) + { + error("abstract cannot be applied to variable"); + } + else if (storage_class & STCtemplateparameter) + { + } + else + { + AggregateDeclaration *aad = sc->anonAgg; + if (!aad) + aad = parent->isAggregateDeclaration(); + if (aad) + { + aad->addField(sc, this); + } + + InterfaceDeclaration *id = parent->isInterfaceDeclaration(); + if (id) + { + error("field not allowed in interface"); + } + + /* Templates cannot add fields to aggregates + */ + TemplateInstance *ti = parent->isTemplateInstance(); + if (ti) + { + // Take care of nested templates + while (1) + { + TemplateInstance *ti2 = ti->tempdecl->parent->isTemplateInstance(); + if (!ti2) + break; + ti = ti2; + } + + // If it's a member template + AggregateDeclaration *ad = ti->tempdecl->isMember(); + if (ad && storage_class != STCundefined) + { + error("cannot use template to add field to aggregate '%s'", ad->toChars()); + } + } + } + + if (type->isauto() && !noauto) + { + if (storage_class & (STCfield | STCout | STCref | STCstatic) || !fd) + { + error("globals, statics, fields, ref and out parameters cannot be auto"); + } + + if (!(storage_class & (STCauto | STCscope))) + { + if (!(storage_class & STCparameter) && ident != Id::withSym) + error("reference to scope class must be scope"); + } + } + + if (!init && !sc->inunion && !isStatic() && !isConst() && fd && + !(storage_class & (STCfield | STCin | STCforeach)) && + type->size() != 0) + { + // Provide a default initializer + //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); + e = new AssignExp(loc, e1, e); + e->type = e1->type; + init = new ExpInitializer(loc, e/*->type->defaultInit()*/); + return; + } + else if (type->ty == Ttypedef) + { TypeTypedef *td = (TypeTypedef *)type; + if (td->sym->init) + { init = td->sym->init; + ExpInitializer *ie = init->isExpInitializer(); + if (ie) + // Make copy so we can modify it + init = new ExpInitializer(ie->loc, ie->exp); + } + else + init = getExpInitializer(); + } + else + { + init = getExpInitializer(); + } + } + + if (init) + { + sc = sc->push(); + sc->stc &= ~(STCconst | STCinvariant | STCpure); + + ArrayInitializer *ai = init->isArrayInitializer(); + if (ai && tb->ty == Taarray) + { + init = ai->toAssocArrayInitializer(); + } + + StructInitializer *si = init->isStructInitializer(); + ExpInitializer *ei = init->isExpInitializer(); + + // See if we can allocate on the stack + if (ei && isScope() && ei->exp->op == TOKnew) + { NewExp *ne = (NewExp *)ei->exp; + if (!(ne->newargs && ne->newargs->dim)) + { ne->onstack = 1; + onstack = 1; + if (type->isBaseOf(ne->newtype->semantic(loc, sc), NULL)) + onstack = 2; + } + } + + // If inside function, there is no semantic3() call + if (sc->func) + { + // If local variable, use AssignExp to handle all the various + // possibilities. + if (fd && !isStatic() && !isConst() && !init->isVoidInitializer()) + { + //printf("fd = '%s', var = '%s'\n", fd->toChars(), toChars()); + if (!ei) + { + Expression *e = init->toExpression(); + if (!e) + { + init = init->semantic(sc, type); + e = init->toExpression(); + if (!e) + { error("is not a static and cannot have static initializer"); + return; + } + } + ei = new ExpInitializer(init->loc, e); + init = ei; + } + + Expression *e1 = new VarExp(loc, this); + + Type *t = type->toBasetype(); + if (t->ty == Tsarray) + { + ei->exp = ei->exp->semantic(sc); + if (!ei->exp->implicitConvTo(type)) + { + int dim = ((TypeSArray *)t)->dim->toInteger(); + // If multidimensional static array, treat as one large array + while (1) + { + t = t->nextOf()->toBasetype(); + if (t->ty != Tsarray) + break; + dim *= ((TypeSArray *)t)->dim->toInteger(); + e1->type = new TypeSArray(t->nextOf(), new IntegerExp(0, dim, Type::tindex)); + } + } + e1 = new SliceExp(loc, e1, NULL, NULL); + } + else if (t->ty == Tstruct) + { + ei->exp = ei->exp->semantic(sc); + if (!ei->exp->implicitConvTo(type)) + ei->exp = new CastExp(loc, ei->exp, type); + } + ei->exp = new AssignExp(loc, e1, ei->exp); + ei->exp->op = TOKconstruct; + canassign++; + ei->exp = ei->exp->semantic(sc); + canassign--; + ei->exp->optimize(WANTvalue); + } + else + { + init = init->semantic(sc, type); + if (fd && isConst() && !isStatic()) + { // Make it static + storage_class |= STCstatic; + } + } + } + else if (isConst() || isFinal()) + { + /* Because we may need the results of a const declaration in a + * subsequent type, such as an array dimension, before semantic2() + * gets ordinarily run, try to run semantic2() now. + * Ignore failure. + */ + + if (!global.errors && !inferred) + { + unsigned errors = global.errors; + global.gag++; + //printf("+gag\n"); + Expression *e; + Initializer *i2 = init; + inuse++; + 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--; + global.gag--; + //printf("-gag\n"); + if (errors != global.errors) // if errors happened + { + if (global.gag == 0) + global.errors = errors; // act as if nothing happened + } + else if (ei) + { + e = e->optimize(WANTvalue | WANTinterpret); + if (e->op == TOKint64 || e->op == TOKstring) + { + ei->exp = e; // no errors, keep result + } + } + else + init = i2; // no errors, keep result + } + } + sc = sc->pop(); + } +} + +ExpInitializer *VarDeclaration::getExpInitializer() +{ + ExpInitializer *ei; + + if (init) + ei = init->isExpInitializer(); + else + { + Expression *e = type->defaultInit(loc); + if (e) + ei = new ExpInitializer(loc, e); + else + ei = NULL; + } + return ei; +} + +void VarDeclaration::semantic2(Scope *sc) +{ + //printf("VarDeclaration::semantic2('%s')\n", toChars()); + if (init && !toParent()->isFuncDeclaration()) + { inuse++; +#if 0 + ExpInitializer *ei = init->isExpInitializer(); + if (ei) + { + ei->exp->dump(0); + printf("type = %p\n", ei->exp->type); + } +#endif + init = init->semantic(sc, type); + inuse--; + } +} + +const char *VarDeclaration::kind() +{ + return "variable"; +} + +Dsymbol *VarDeclaration::toAlias() +{ + //printf("VarDeclaration::toAlias('%s', this = %p, aliassym = %p)\n", toChars(), this, aliassym); + assert(this != aliassym); + Dsymbol *s = aliassym ? aliassym->toAlias() : this; + return s; +} + +void VarDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) +{ + StorageClassDeclaration::stcToCBuffer(buf, storage_class); + + /* If changing, be sure and fix CompoundDeclarationStatement::toCBuffer() + * too. + */ + if (type) + type->toCBuffer(buf, ident, hgs); + else + buf->writestring(ident->toChars()); + if (init) + { buf->writestring(" = "); + init->toCBuffer(buf, hgs); + } + buf->writeByte(';'); + buf->writenl(); +} + +int VarDeclaration::needThis() +{ + //printf("VarDeclaration::needThis(%s, x%x)\n", toChars(), storage_class); + return storage_class & STCfield; +} + +int VarDeclaration::isImportedSymbol() +{ + if (protection == PROTexport && !init && (isStatic() || isConst() || parent->isModule())) + return TRUE; + return FALSE; +} + +void VarDeclaration::checkCtorConstInit() +{ + if (ctorinit == 0 && isCtorinit() && !(storage_class & STCfield)) + error("missing initializer in static constructor for const variable"); +} + +/************************************ + * Check to see if this variable is actually in an enclosing function + * rather than the current one. + */ + +void VarDeclaration::checkNestedReference(Scope *sc, Loc loc) +{ + //printf("VarDeclaration::checkNestedReference() %s\n", toChars()); + if (parent && !isDataseg() && parent != sc->parent) + { + // The function that this variable is in + FuncDeclaration *fdv = toParent()->isFuncDeclaration(); + // The current function + FuncDeclaration *fdthis = sc->parent->isFuncDeclaration(); + + if (fdv && fdthis) + { + if (loc.filename) + fdthis->getLevel(loc, fdv); + nestedref = 1; + fdv->nestedFrameRef = 1; + fdv->nestedVars.insert(this); + //printf("var %s in function %s is nested ref\n", toChars(), fdv->toChars()); + } + } +} + +/******************************* + * Does symbol go into data segment? + * Includes extern variables. + */ + +int VarDeclaration::isDataseg() +{ +#if 0 + printf("VarDeclaration::isDataseg(%p, '%s')\n", this, toChars()); + printf("%x, %p, %p\n", storage_class & (STCstatic | STCconst), parent->isModule(), parent->isTemplateInstance()); + printf("parent = '%s'\n", parent->toChars()); +#endif + Dsymbol *parent = this->toParent(); + if (!parent && !(storage_class & (STCstatic | STCconst))) + { error("forward referenced"); + type = Type::terror; + return 0; + } + return (storage_class & (STCstatic | STCconst) || + parent->isModule() || + parent->isTemplateInstance()); +} + +int VarDeclaration::hasPointers() +{ + return (!isDataseg() && type->hasPointers()); +} + +/****************************************** + * If a variable has an auto destructor call, return call for it. + * Otherwise, return NULL. + */ + +Expression *VarDeclaration::callAutoDtor() +{ Expression *e = NULL; + + //printf("VarDeclaration::callAutoDtor() %s\n", toChars()); + if (storage_class & (STCauto | STCscope) && !noauto) + { + for (ClassDeclaration *cd = type->isClassHandle(); + cd; + cd = cd->baseClass) + { + /* We can do better if there's a way with onstack + * classes to determine if there's no way the monitor + * could be set. + */ + //if (cd->isInterfaceDeclaration()) + //error("interface %s cannot be scope", cd->toChars()); + if (1 || onstack || cd->dtors.dim) // if any destructors + { + // delete this; + Expression *ec; + + ec = new VarExp(loc, this); + e = new DeleteExp(loc, ec); + e->type = Type::tvoid; + break; + } + } + } + return e; +} + + +/********************************* ClassInfoDeclaration ****************************/ + +ClassInfoDeclaration::ClassInfoDeclaration(ClassDeclaration *cd) + : VarDeclaration(0, ClassDeclaration::classinfo->type, cd->ident, NULL) +{ + this->cd = cd; + storage_class = STCstatic; +} + +Dsymbol *ClassInfoDeclaration::syntaxCopy(Dsymbol *s) +{ + assert(0); // should never be produced by syntax + return NULL; +} + +void ClassInfoDeclaration::semantic(Scope *sc) +{ +} + +/********************************* ModuleInfoDeclaration ****************************/ + +ModuleInfoDeclaration::ModuleInfoDeclaration(Module *mod) + : VarDeclaration(0, Module::moduleinfo->type, mod->ident, NULL) +{ + this->mod = mod; + storage_class = STCstatic; +} + +Dsymbol *ModuleInfoDeclaration::syntaxCopy(Dsymbol *s) +{ + assert(0); // should never be produced by syntax + return NULL; +} + +void ModuleInfoDeclaration::semantic(Scope *sc) +{ +} + +/********************************* TypeInfoDeclaration ****************************/ + +TypeInfoDeclaration::TypeInfoDeclaration(Type *tinfo, int internal) + : VarDeclaration(0, Type::typeinfo->type, tinfo->getTypeInfoIdent(internal), NULL) +{ + this->tinfo = tinfo; + storage_class = STCstatic; + protection = PROTpublic; + linkage = LINKc; +} + +Dsymbol *TypeInfoDeclaration::syntaxCopy(Dsymbol *s) +{ + assert(0); // should never be produced by syntax + return NULL; +} + +void TypeInfoDeclaration::semantic(Scope *sc) +{ + assert(linkage == LINKc); +} + +/***************************** TypeInfoConstDeclaration **********************/ + +#if DMDV2 +TypeInfoConstDeclaration::TypeInfoConstDeclaration(Type *tinfo) + : TypeInfoDeclaration(tinfo, 0) +{ +} +#endif + +/***************************** TypeInfoInvariantDeclaration **********************/ + +#if DMDV2 +TypeInfoInvariantDeclaration::TypeInfoInvariantDeclaration(Type *tinfo) + : TypeInfoDeclaration(tinfo, 0) +{ +} +#endif + +/***************************** TypeInfoStructDeclaration **********************/ + +TypeInfoStructDeclaration::TypeInfoStructDeclaration(Type *tinfo) + : TypeInfoDeclaration(tinfo, 0) +{ +} + +/***************************** TypeInfoClassDeclaration ***********************/ + +TypeInfoClassDeclaration::TypeInfoClassDeclaration(Type *tinfo) + : TypeInfoDeclaration(tinfo, 0) +{ +} + +/***************************** TypeInfoInterfaceDeclaration *******************/ + +TypeInfoInterfaceDeclaration::TypeInfoInterfaceDeclaration(Type *tinfo) + : TypeInfoDeclaration(tinfo, 0) +{ +} + +/***************************** TypeInfoTypedefDeclaration *********************/ + +TypeInfoTypedefDeclaration::TypeInfoTypedefDeclaration(Type *tinfo) + : TypeInfoDeclaration(tinfo, 0) +{ +} + +/***************************** TypeInfoPointerDeclaration *********************/ + +TypeInfoPointerDeclaration::TypeInfoPointerDeclaration(Type *tinfo) + : TypeInfoDeclaration(tinfo, 0) +{ +} + +/***************************** TypeInfoArrayDeclaration ***********************/ + +TypeInfoArrayDeclaration::TypeInfoArrayDeclaration(Type *tinfo) + : TypeInfoDeclaration(tinfo, 0) +{ +} + +/***************************** TypeInfoStaticArrayDeclaration *****************/ + +TypeInfoStaticArrayDeclaration::TypeInfoStaticArrayDeclaration(Type *tinfo) + : TypeInfoDeclaration(tinfo, 0) +{ +} + +/***************************** TypeInfoAssociativeArrayDeclaration ************/ + +TypeInfoAssociativeArrayDeclaration::TypeInfoAssociativeArrayDeclaration(Type *tinfo) + : TypeInfoDeclaration(tinfo, 0) +{ +} + +/***************************** TypeInfoEnumDeclaration ***********************/ + +TypeInfoEnumDeclaration::TypeInfoEnumDeclaration(Type *tinfo) + : TypeInfoDeclaration(tinfo, 0) +{ +} + +/***************************** TypeInfoFunctionDeclaration ********************/ + +TypeInfoFunctionDeclaration::TypeInfoFunctionDeclaration(Type *tinfo) + : TypeInfoDeclaration(tinfo, 0) +{ +} + +/***************************** TypeInfoDelegateDeclaration ********************/ + +TypeInfoDelegateDeclaration::TypeInfoDelegateDeclaration(Type *tinfo) + : TypeInfoDeclaration(tinfo, 0) +{ +} + +/***************************** TypeInfoTupleDeclaration **********************/ + +TypeInfoTupleDeclaration::TypeInfoTupleDeclaration(Type *tinfo) + : TypeInfoDeclaration(tinfo, 0) +{ +} + +/********************************* ThisDeclaration ****************************/ + +// For the "this" parameter to member functions + +ThisDeclaration::ThisDeclaration(Type *t) + : VarDeclaration(0, t, Id::This, NULL) +{ + noauto = 1; +} + +Dsymbol *ThisDeclaration::syntaxCopy(Dsymbol *s) +{ + assert(0); // should never be produced by syntax + return NULL; +} + +/********************** StaticStructInitDeclaration ***************************/ + +StaticStructInitDeclaration::StaticStructInitDeclaration(Loc loc, StructDeclaration *dsym) + : Declaration(new Identifier("", TOKidentifier)) +{ + this->loc = loc; + this->dsym = dsym; + storage_class |= STCconst; +} + diff -r 1853dcd9b944 -r e961851fb8be dmd/declaration.h --- a/dmd/declaration.h Fri Apr 03 17:02:52 2009 +0200 +++ b/dmd/declaration.h Fri Apr 03 17:59:34 2009 +0200 @@ -1,914 +1,914 @@ - -// Compiler implementation of the D programming language -// Copyright (c) 1999-2008 by Digital Mars -// All Rights Reserved -// written by Walter Bright -// 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. - -#ifndef DMD_DECLARATION_H -#define DMD_DECLARATION_H - -#ifdef __DMC__ -#pragma once -#endif /* __DMC__ */ - -#include -#include -#include - -#include "dsymbol.h" -#include "lexer.h" -#include "mtype.h" - -struct Expression; -struct Statement; -struct LabelDsymbol; -struct LabelStatement; -struct Initializer; -struct Module; -struct InlineScanState; -struct ForeachStatement; -struct FuncDeclaration; -struct ExpInitializer; -struct StructDeclaration; -struct TupleType; -struct InterState; -struct IRState; -struct AnonDeclaration; - -enum PROT; -enum LINK; -enum TOK; -enum MATCH; - -enum STC -{ - STCundefined = 0, - STCstatic = 1, - STCextern = 2, - STCconst = 4, - STCfinal = 8, - STCabstract = 0x10, - STCparameter = 0x20, - STCfield = 0x40, - STCoverride = 0x80, - STCauto = 0x100, - STCsynchronized = 0x200, - STCdeprecated = 0x400, - STCin = 0x800, // in parameter - STCout = 0x1000, // out parameter - STClazy = 0x2000, // lazy parameter - STCforeach = 0x4000, // variable for foreach loop - STCcomdat = 0x8000, // should go into COMDAT record - STCvariadic = 0x10000, // variadic function argument - STCctorinit = 0x20000, // can only be set inside constructor - STCtemplateparameter = 0x40000, // template parameter - STCscope = 0x80000, // template parameter - STCinvariant = 0x100000, - STCref = 0x200000, - STCinit = 0x400000, // has explicit initializer - STCmanifest = 0x800000, // manifest constant - STCnodtor = 0x1000000, // don't run destructor - STCnothrow = 0x2000000, // never throws exceptions - STCpure = 0x4000000, // pure function - STCtls = 0x8000000, // thread local - STCalias = 0x10000000, // alias parameter -}; - -struct Match -{ - int count; // number of matches found - MATCH last; // match level of lastf - FuncDeclaration *lastf; // last matching function we found - FuncDeclaration *nextf; // current matching function - FuncDeclaration *anyf; // pick a func, any func, to use for error recovery -}; - -void overloadResolveX(Match *m, FuncDeclaration *f, Expressions *arguments); -int overloadApply(FuncDeclaration *fstart, - int (*fp)(void *, FuncDeclaration *), - void *param); - -/**************************************************************/ - -struct Declaration : Dsymbol -{ - Type *type; - Type *originalType; // before semantic analysis - unsigned storage_class; - enum PROT protection; - enum LINK linkage; - - Declaration(Identifier *id); - void semantic(Scope *sc); - const char *kind(); - unsigned size(Loc loc); - void checkModify(Loc loc, Scope *sc, Type *t); - - void emitComment(Scope *sc); - void toDocBuffer(OutBuffer *buf); - - char *mangle(); - int isStatic() { return storage_class & STCstatic; } - virtual int isStaticConstructor(); - virtual int isStaticDestructor(); - virtual int isDelete(); - virtual int isDataseg(); - virtual int isCodeseg(); - int isCtorinit() { return storage_class & STCctorinit; } - int isFinal() { return storage_class & STCfinal; } - int isAbstract() { return storage_class & STCabstract; } - int isConst() { return storage_class & STCconst; } - int isInvariant() { return 0; } - int isAuto() { return storage_class & STCauto; } - int isScope() { return storage_class & (STCscope | STCauto); } - int isSynchronized() { return storage_class & STCsynchronized; } - int isParameter() { return storage_class & STCparameter; } - int isDeprecated() { return storage_class & STCdeprecated; } - int isOverride() { return storage_class & STCoverride; } - - int isIn() { return storage_class & STCin; } - int isOut() { return storage_class & STCout; } - int isRef() { return storage_class & STCref; } - - enum PROT prot(); - - Declaration *isDeclaration() { return this; } - -#if IN_LLVM - /// Codegen traversal - virtual void codegen(Ir* ir); -#endif -}; - -/**************************************************************/ - -struct TupleDeclaration : Declaration -{ - Objects *objects; - int isexp; // 1: expression tuple - - TypeTuple *tupletype; // !=NULL if this is a type tuple - - TupleDeclaration(Loc loc, Identifier *ident, Objects *objects); - Dsymbol *syntaxCopy(Dsymbol *); - const char *kind(); - Type *getType(); - int needThis(); - - TupleDeclaration *isTupleDeclaration() { return this; } - -#if IN_LLVM - /// Codegen traversal - void codegen(Ir* ir); -#endif -}; - -/**************************************************************/ - -struct TypedefDeclaration : Declaration -{ - Type *basetype; - Initializer *init; - int sem; // 0: semantic() has not been run - // 1: semantic() is in progress - // 2: semantic() has been run - // 3: semantic2() has been run - int inuse; // used to detect typedef cycles - - TypedefDeclaration(Loc loc, Identifier *ident, Type *basetype, Initializer *init); - Dsymbol *syntaxCopy(Dsymbol *); - void semantic(Scope *sc); - void semantic2(Scope *sc); - char *mangle(); - const char *kind(); - Type *getType(); - void toCBuffer(OutBuffer *buf, HdrGenState *hgs); -#ifdef _DH - Type *htype; - Type *hbasetype; -#endif - - void toDocBuffer(OutBuffer *buf); - -#if IN_DMD - void toObjFile(int multiobj); // compile to .obj file - void toDebug(); - int cvMember(unsigned char *p); -#endif - - TypedefDeclaration *isTypedefDeclaration() { return this; } - -#if IN_DMD - Symbol *sinit; - Symbol *toInitializer(); -#endif - -#if IN_LLVM - /// Codegen traversal - void codegen(Ir* ir); -#endif -}; - -/**************************************************************/ - -struct AliasDeclaration : Declaration -{ - Dsymbol *aliassym; - Dsymbol *overnext; // next in overload list - int inSemantic; - - AliasDeclaration(Loc loc, Identifier *ident, Type *type); - AliasDeclaration(Loc loc, Identifier *ident, Dsymbol *s); - Dsymbol *syntaxCopy(Dsymbol *); - void semantic(Scope *sc); - int overloadInsert(Dsymbol *s); - const char *kind(); - Type *getType(); - Dsymbol *toAlias(); - void toCBuffer(OutBuffer *buf, HdrGenState *hgs); -#ifdef _DH - Type *htype; - Dsymbol *haliassym; -#endif - - void toDocBuffer(OutBuffer *buf); - - AliasDeclaration *isAliasDeclaration() { return this; } -}; - -/**************************************************************/ - -struct VarDeclaration : Declaration -{ - Initializer *init; - unsigned offset; - int noauto; // no auto semantics - int nestedref; // referenced by a lexically nested function - int inuse; - int ctorinit; // it has been initialized in a ctor - int onstack; // 1: it has been allocated on the stack - // 2: on stack, run destructor anyway - int canassign; // it can be assigned to - Dsymbol *aliassym; // if redone as alias to another symbol - Expression *value; // when interpreting, this is the value - // (NULL if value not determinable) - - VarDeclaration(Loc loc, Type *t, Identifier *id, Initializer *init); - Dsymbol *syntaxCopy(Dsymbol *); - void semantic(Scope *sc); - void semantic2(Scope *sc); - const char *kind(); - void toCBuffer(OutBuffer *buf, HdrGenState *hgs); -#ifdef _DH - Type *htype; - Initializer *hinit; -#endif - int needThis(); - int isImportedSymbol(); - int isDataseg(); - int hasPointers(); - Expression *callAutoDtor(); - ExpInitializer *getExpInitializer(); - void checkCtorConstInit(); - void checkNestedReference(Scope *sc, Loc loc); - Dsymbol *toAlias(); - -#if IN_DMD - void toObjFile(int multiobj); // compile to .obj file - Symbol *toSymbol(); - int cvMember(unsigned char *p); -#endif - - // Eliminate need for dynamic_cast - VarDeclaration *isVarDeclaration() { return (VarDeclaration *)this; } - -#if IN_LLVM - /// Codegen traversal - virtual void codegen(Ir* ir); - - // LDC - AnonDeclaration* anonDecl; - unsigned offset2; - bool nakedUse; -#endif -}; - -/**************************************************************/ - -// LDC uses this to denote static struct initializers - -struct StaticStructInitDeclaration : Declaration -{ - StructDeclaration *dsym; - - StaticStructInitDeclaration(Loc loc, StructDeclaration *dsym); - -#if IN_DMD - Symbol *toSymbol(); -#endif - - // Eliminate need for dynamic_cast - StaticStructInitDeclaration *isStaticStructInitDeclaration() { return (StaticStructInitDeclaration *)this; } -}; - -struct ClassInfoDeclaration : VarDeclaration -{ - ClassDeclaration *cd; - - ClassInfoDeclaration(ClassDeclaration *cd); - Dsymbol *syntaxCopy(Dsymbol *); - void semantic(Scope *sc); - - void emitComment(Scope *sc); - -#if IN_DMD - Symbol *toSymbol(); -#endif - - ClassInfoDeclaration* isClassInfoDeclaration() { return this; } -}; - -struct ModuleInfoDeclaration : VarDeclaration -{ - Module *mod; - - ModuleInfoDeclaration(Module *mod); - Dsymbol *syntaxCopy(Dsymbol *); - void semantic(Scope *sc); - - void emitComment(Scope *sc); - -#if IN_DMD - Symbol *toSymbol(); -#endif -}; - -struct TypeInfoDeclaration : VarDeclaration -{ - Type *tinfo; - - TypeInfoDeclaration(Type *tinfo, int internal); - Dsymbol *syntaxCopy(Dsymbol *); - void semantic(Scope *sc); - - void emitComment(Scope *sc); - -#if IN_DMD - void toObjFile(int multiobj); // compile to .obj file - Symbol *toSymbol(); - virtual void toDt(dt_t **pdt); -#endif - - virtual TypeInfoDeclaration* isTypeInfoDeclaration() { return this; } - -#if IN_LLVM - /// Codegen traversal - void codegen(Ir* ir); - virtual void llvmDefine(); -#endif -}; - -struct TypeInfoStructDeclaration : TypeInfoDeclaration -{ - TypeInfoStructDeclaration(Type *tinfo); - -#if IN_DMD - void toDt(dt_t **pdt); -#endif - -#if IN_LLVM - void llvmDefine(); -#endif -}; - -struct TypeInfoClassDeclaration : TypeInfoDeclaration -{ - TypeInfoClassDeclaration(Type *tinfo); - -#if IN_DMD - void toDt(dt_t **pdt); -#endif - -#if IN_LLVM - void llvmDefine(); -#endif -}; - -struct TypeInfoInterfaceDeclaration : TypeInfoDeclaration -{ - TypeInfoInterfaceDeclaration(Type *tinfo); - -#if IN_DMD - void toDt(dt_t **pdt); -#endif - -#if IN_LLVM - void llvmDefine(); -#endif -}; - -struct TypeInfoTypedefDeclaration : TypeInfoDeclaration -{ - TypeInfoTypedefDeclaration(Type *tinfo); - -#if IN_DMD - void toDt(dt_t **pdt); -#endif - -#if IN_LLVM - void llvmDefine(); -#endif -}; - -struct TypeInfoPointerDeclaration : TypeInfoDeclaration -{ - TypeInfoPointerDeclaration(Type *tinfo); - -#if IN_DMD - void toDt(dt_t **pdt); -#endif - -#if IN_LLVM - void llvmDefine(); -#endif -}; - -struct TypeInfoArrayDeclaration : TypeInfoDeclaration -{ - TypeInfoArrayDeclaration(Type *tinfo); - -#if IN_DMD - void toDt(dt_t **pdt); -#endif - -#if IN_LLVM - void llvmDefine(); -#endif -}; - -struct TypeInfoStaticArrayDeclaration : TypeInfoDeclaration -{ - TypeInfoStaticArrayDeclaration(Type *tinfo); - -#if IN_DMD - void toDt(dt_t **pdt); -#endif - -#if IN_LLVM - void llvmDefine(); -#endif -}; - -struct TypeInfoAssociativeArrayDeclaration : TypeInfoDeclaration -{ - TypeInfoAssociativeArrayDeclaration(Type *tinfo); - -#if IN_DMD - void toDt(dt_t **pdt); -#endif - -#if IN_LLVM - void llvmDefine(); -#endif -}; - -struct TypeInfoEnumDeclaration : TypeInfoDeclaration -{ - TypeInfoEnumDeclaration(Type *tinfo); - -#if IN_DMD - void toDt(dt_t **pdt); -#endif - -#if IN_LLVM - void llvmDefine(); -#endif -}; - -struct TypeInfoFunctionDeclaration : TypeInfoDeclaration -{ - TypeInfoFunctionDeclaration(Type *tinfo); - -#if IN_DMD - void toDt(dt_t **pdt); -#endif - -#if IN_LLVM - void llvmDefine(); -#endif -}; - -struct TypeInfoDelegateDeclaration : TypeInfoDeclaration -{ - TypeInfoDelegateDeclaration(Type *tinfo); - -#if IN_DMD - void toDt(dt_t **pdt); -#endif - -#if IN_LLVM - void llvmDefine(); -#endif -}; - -struct TypeInfoTupleDeclaration : TypeInfoDeclaration -{ - TypeInfoTupleDeclaration(Type *tinfo); - -#if IN_DMD - void toDt(dt_t **pdt); -#endif - -#if IN_LLVM - void llvmDefine(); -#endif -}; - -#if DMDV2 -struct TypeInfoConstDeclaration : TypeInfoDeclaration -{ - TypeInfoConstDeclaration(Type *tinfo); - -#if IN_DMD - void toDt(dt_t **pdt); -#endif - -#if IN_LLVM - void llvmDefine(); -#endif -}; - -struct TypeInfoInvariantDeclaration : TypeInfoDeclaration -{ - TypeInfoInvariantDeclaration(Type *tinfo); - -#if IN_DMD - void toDt(dt_t **pdt); -#endif - -#if IN_LLVM - void llvmDefine(); -#endif -}; -#endif - -/**************************************************************/ - -struct ThisDeclaration : VarDeclaration -{ - ThisDeclaration(Type *t); - Dsymbol *syntaxCopy(Dsymbol *); -}; - -enum ILS -{ - ILSuninitialized, // not computed yet - ILSno, // cannot inline - ILSyes, // can inline -}; - -/**************************************************************/ -#if DMDV2 - -enum BUILTIN -{ - BUILTINunknown = -1, // not known if this is a builtin - BUILTINnot, // this is not a builtin - BUILTINsin, // std.math.sin - BUILTINcos, // std.math.cos - BUILTINtan, // std.math.tan - BUILTINsqrt, // std.math.sqrt - BUILTINfabs, // std.math.fabs -}; - -Expression *eval_builtin(enum BUILTIN builtin, Expressions *arguments); - -#endif - -struct FuncDeclaration : Declaration -{ - Array *fthrows; // Array of Type's of exceptions (not used) - Statement *frequire; - Statement *fensure; - Statement *fbody; - - Identifier *outId; // identifier for out statement - VarDeclaration *vresult; // variable corresponding to outId - LabelDsymbol *returnLabel; // where the return goes - - DsymbolTable *localsymtab; // used to prevent symbols in different - // scopes from having the same name - VarDeclaration *vthis; // 'this' parameter (member and nested) - VarDeclaration *v_arguments; // '_arguments' parameter -#if IN_GCC - VarDeclaration *v_argptr; // '_argptr' variable -#endif - Dsymbols *parameters; // Array of VarDeclaration's for parameters - DsymbolTable *labtab; // statement label symbol table - Declaration *overnext; // next in overload list - Loc endloc; // location of closing curly bracket - int vtblIndex; // for member functions, index into vtbl[] - int naked; // !=0 if naked - int inlineAsm; // !=0 if has inline assembler - ILS inlineStatus; - int inlineNest; // !=0 if nested inline - int cantInterpret; // !=0 if cannot interpret function - int semanticRun; // !=0 if semantic3() had been run - // this function's frame ptr - ForeachStatement *fes; // if foreach body, this is the foreach - int introducing; // !=0 if 'introducing' function - Type *tintro; // if !=NULL, then this is the type - // of the 'introducing' function - // this one is overriding - int inferRetType; // !=0 if return type is to be inferred - Scope *scope; // !=NULL means context to use - - // Things that should really go into Scope - int hasReturnExp; // 1 if there's a return exp; statement - // 2 if there's a throw statement - // 4 if there's an assert(0) - // 8 if there's inline asm - - // Support for NRVO (named return value optimization) - int nrvo_can; // !=0 means we can do it - VarDeclaration *nrvo_var; // variable to replace with shidden -#if IN_DMD - Symbol *shidden; // hidden pointer passed to function -#endif - -#if DMDV2 - enum BUILTIN builtin; // set if this is a known, builtin - // function we can evaluate at compile - // time - - int tookAddressOf; // set if someone took the address of - // this function - Dsymbols closureVars; // local variables in this function - // which are referenced by nested - // functions -#else - int nestedFrameRef; // !=0 if nested variables referenced -#endif - - FuncDeclaration(Loc loc, Loc endloc, Identifier *id, enum STC storage_class, Type *type); - Dsymbol *syntaxCopy(Dsymbol *); - void semantic(Scope *sc); - void semantic2(Scope *sc); - void semantic3(Scope *sc); - void toCBuffer(OutBuffer *buf, HdrGenState *hgs); - void bodyToCBuffer(OutBuffer *buf, HdrGenState *hgs); - int overrides(FuncDeclaration *fd); - int findVtblIndex(Array *vtbl, int dim); - int overloadInsert(Dsymbol *s); - FuncDeclaration *overloadExactMatch(Type *t); - FuncDeclaration *overloadResolve(Loc loc, Expressions *arguments); - LabelDsymbol *searchLabel(Identifier *ident); - AggregateDeclaration *isThis(); - AggregateDeclaration *isMember2(); - int getLevel(Loc loc, FuncDeclaration *fd); // lexical nesting level difference - void appendExp(Expression *e); - void appendState(Statement *s); - char *mangle(); - int isMain(); - int isWinMain(); - int isDllMain(); - int isExport(); - int isImportedSymbol(); - int isAbstract(); - int isCodeseg(); - virtual int isNested(); - int needThis(); - virtual int isVirtual(); - virtual int isFinal(); - virtual int addPreInvariant(); - virtual int addPostInvariant(); - Expression *interpret(InterState *istate, Expressions *arguments); - void inlineScan(); - int canInline(int hasthis, int hdrscan = 0); - Expression *doInline(InlineScanState *iss, Expression *ethis, Array *arguments); - const char *kind(); - void toDocBuffer(OutBuffer *buf); - -// LDC: give argument types to runtime functions - static FuncDeclaration *genCfunc(Arguments *args, Type *treturn, const char *name); - static FuncDeclaration *genCfunc(Arguments *args, Type *treturn, Identifier *id); - -#if IN_DMD - Symbol *toSymbol(); - Symbol *toThunkSymbol(int offset); // thunk version - void toObjFile(int multiobj); // compile to .obj file - int cvMember(unsigned char *p); -#endif - - FuncDeclaration *isFuncDeclaration() { return this; } - -#if IN_LLVM - // LDC stuff - - /// Codegen traversal - void codegen(Ir* ir); - - // vars declared in this function that nested funcs reference - // is this is not empty, nestedFrameRef is set and these VarDecls - // probably have nestedref set too, see VarDeclaration::checkNestedReference - std::set nestedVars; - - std::string intrinsicName; - - bool isIntrinsic(); - bool isVaIntrinsic(); - - // we keep our own table of label statements as LabelDsymbolS - // don't always carry their corresponding statement along ... - typedef std::map LabelMap; - LabelMap labmap; - - // if this is an array operation it gets a little special attention - bool isArrayOp; - - // true if overridden with the pragma(allow_inline); stmt - bool allowInlining; -#endif -}; - -struct FuncAliasDeclaration : FuncDeclaration -{ - FuncDeclaration *funcalias; - - FuncAliasDeclaration(FuncDeclaration *funcalias); - - FuncAliasDeclaration *isFuncAliasDeclaration() { return this; } - const char *kind(); -#if IN_DMD - Symbol *toSymbol(); -#endif -}; - -struct FuncLiteralDeclaration : FuncDeclaration -{ - enum TOK tok; // TOKfunction or TOKdelegate - - FuncLiteralDeclaration(Loc loc, Loc endloc, Type *type, enum TOK tok, - ForeachStatement *fes); - void toCBuffer(OutBuffer *buf, HdrGenState *hgs); - Dsymbol *syntaxCopy(Dsymbol *); - int isNested(); - int isVirtual(); - - FuncLiteralDeclaration *isFuncLiteralDeclaration() { return this; } - const char *kind(); -}; - -struct CtorDeclaration : FuncDeclaration -{ Arguments *arguments; - int varargs; - - CtorDeclaration(Loc loc, Loc endloc, Arguments *arguments, int varargs); - Dsymbol *syntaxCopy(Dsymbol *); - void semantic(Scope *sc); - void toCBuffer(OutBuffer *buf, HdrGenState *hgs); - const char *kind(); - char *toChars(); - int isVirtual(); - int addPreInvariant(); - int addPostInvariant(); - void toDocBuffer(OutBuffer *buf); - - CtorDeclaration *isCtorDeclaration() { return this; } -}; - -#if DMDV2 -struct PostBlitDeclaration : FuncDeclaration -{ - PostBlitDeclaration(Loc loc, Loc endloc); - PostBlitDeclaration(Loc loc, Loc endloc, Identifier *id); - Dsymbol *syntaxCopy(Dsymbol *); - void semantic(Scope *sc); - void toCBuffer(OutBuffer *buf, HdrGenState *hgs); - int isVirtual(); - int addPreInvariant(); - int addPostInvariant(); - int overloadInsert(Dsymbol *s); - void emitComment(Scope *sc); - - PostBlitDeclaration *isPostBlitDeclaration() { return this; } -}; -#endif - -struct DtorDeclaration : FuncDeclaration -{ - DtorDeclaration(Loc loc, Loc endloc); - DtorDeclaration(Loc loc, Loc endloc, Identifier *id); - Dsymbol *syntaxCopy(Dsymbol *); - void semantic(Scope *sc); - void toCBuffer(OutBuffer *buf, HdrGenState *hgs); - int isVirtual(); - int addPreInvariant(); - int addPostInvariant(); - int overloadInsert(Dsymbol *s); - void emitComment(Scope *sc); - - DtorDeclaration *isDtorDeclaration() { return this; } -}; - -struct StaticCtorDeclaration : FuncDeclaration -{ - StaticCtorDeclaration(Loc loc, Loc endloc); - Dsymbol *syntaxCopy(Dsymbol *); - void semantic(Scope *sc); - AggregateDeclaration *isThis(); - int isStaticConstructor(); - int isVirtual(); - int addPreInvariant(); - int addPostInvariant(); - void emitComment(Scope *sc); - void toCBuffer(OutBuffer *buf, HdrGenState *hgs); - - StaticCtorDeclaration *isStaticCtorDeclaration() { return this; } -}; - -struct StaticDtorDeclaration : FuncDeclaration -{ VarDeclaration *vgate; // 'gate' variable - - StaticDtorDeclaration(Loc loc, Loc endloc); - Dsymbol *syntaxCopy(Dsymbol *); - void semantic(Scope *sc); - AggregateDeclaration *isThis(); - int isStaticDestructor(); - int isVirtual(); - int addPreInvariant(); - int addPostInvariant(); - void emitComment(Scope *sc); - void toCBuffer(OutBuffer *buf, HdrGenState *hgs); - - StaticDtorDeclaration *isStaticDtorDeclaration() { return this; } -}; - -struct InvariantDeclaration : FuncDeclaration -{ - InvariantDeclaration(Loc loc, Loc endloc); - Dsymbol *syntaxCopy(Dsymbol *); - void semantic(Scope *sc); - int isVirtual(); - int addPreInvariant(); - int addPostInvariant(); - void emitComment(Scope *sc); - void toCBuffer(OutBuffer *buf, HdrGenState *hgs); - - InvariantDeclaration *isInvariantDeclaration() { return this; } -}; - - -struct UnitTestDeclaration : FuncDeclaration -{ - UnitTestDeclaration(Loc loc, Loc endloc); - Dsymbol *syntaxCopy(Dsymbol *); - void semantic(Scope *sc); - AggregateDeclaration *isThis(); - int isVirtual(); - int addPreInvariant(); - int addPostInvariant(); - void toCBuffer(OutBuffer *buf, HdrGenState *hgs); - - UnitTestDeclaration *isUnitTestDeclaration() { return this; } -}; - -struct NewDeclaration : FuncDeclaration -{ Arguments *arguments; - int varargs; - - NewDeclaration(Loc loc, Loc endloc, Arguments *arguments, int varargs); - Dsymbol *syntaxCopy(Dsymbol *); - void semantic(Scope *sc); - void toCBuffer(OutBuffer *buf, HdrGenState *hgs); - const char *kind(); - int isVirtual(); - int addPreInvariant(); - int addPostInvariant(); - - NewDeclaration *isNewDeclaration() { return this; } -}; - - -struct DeleteDeclaration : FuncDeclaration -{ Arguments *arguments; - - DeleteDeclaration(Loc loc, Loc endloc, Arguments *arguments); - Dsymbol *syntaxCopy(Dsymbol *); - void semantic(Scope *sc); - void toCBuffer(OutBuffer *buf, HdrGenState *hgs); - const char *kind(); - int isDelete(); - int isVirtual(); - int addPreInvariant(); - int addPostInvariant(); -#ifdef _DH - DeleteDeclaration *isDeleteDeclaration() { return this; } -#endif -}; - -#endif /* DMD_DECLARATION_H */ + +// Compiler implementation of the D programming language +// Copyright (c) 1999-2008 by Digital Mars +// All Rights Reserved +// written by Walter Bright +// 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. + +#ifndef DMD_DECLARATION_H +#define DMD_DECLARATION_H + +#ifdef __DMC__ +#pragma once +#endif /* __DMC__ */ + +#include +#include +#include + +#include "dsymbol.h" +#include "lexer.h" +#include "mtype.h" + +struct Expression; +struct Statement; +struct LabelDsymbol; +struct LabelStatement; +struct Initializer; +struct Module; +struct InlineScanState; +struct ForeachStatement; +struct FuncDeclaration; +struct ExpInitializer; +struct StructDeclaration; +struct TupleType; +struct InterState; +struct IRState; +struct AnonDeclaration; + +enum PROT; +enum LINK; +enum TOK; +enum MATCH; + +enum STC +{ + STCundefined = 0, + STCstatic = 1, + STCextern = 2, + STCconst = 4, + STCfinal = 8, + STCabstract = 0x10, + STCparameter = 0x20, + STCfield = 0x40, + STCoverride = 0x80, + STCauto = 0x100, + STCsynchronized = 0x200, + STCdeprecated = 0x400, + STCin = 0x800, // in parameter + STCout = 0x1000, // out parameter + STClazy = 0x2000, // lazy parameter + STCforeach = 0x4000, // variable for foreach loop + STCcomdat = 0x8000, // should go into COMDAT record + STCvariadic = 0x10000, // variadic function argument + STCctorinit = 0x20000, // can only be set inside constructor + STCtemplateparameter = 0x40000, // template parameter + STCscope = 0x80000, // template parameter + STCinvariant = 0x100000, + STCref = 0x200000, + STCinit = 0x400000, // has explicit initializer + STCmanifest = 0x800000, // manifest constant + STCnodtor = 0x1000000, // don't run destructor + STCnothrow = 0x2000000, // never throws exceptions + STCpure = 0x4000000, // pure function + STCtls = 0x8000000, // thread local + STCalias = 0x10000000, // alias parameter +}; + +struct Match +{ + int count; // number of matches found + MATCH last; // match level of lastf + FuncDeclaration *lastf; // last matching function we found + FuncDeclaration *nextf; // current matching function + FuncDeclaration *anyf; // pick a func, any func, to use for error recovery +}; + +void overloadResolveX(Match *m, FuncDeclaration *f, Expressions *arguments); +int overloadApply(FuncDeclaration *fstart, + int (*fp)(void *, FuncDeclaration *), + void *param); + +/**************************************************************/ + +struct Declaration : Dsymbol +{ + Type *type; + Type *originalType; // before semantic analysis + unsigned storage_class; + enum PROT protection; + enum LINK linkage; + + Declaration(Identifier *id); + void semantic(Scope *sc); + const char *kind(); + unsigned size(Loc loc); + void checkModify(Loc loc, Scope *sc, Type *t); + + void emitComment(Scope *sc); + void toDocBuffer(OutBuffer *buf); + + char *mangle(); + int isStatic() { return storage_class & STCstatic; } + virtual int isStaticConstructor(); + virtual int isStaticDestructor(); + virtual int isDelete(); + virtual int isDataseg(); + virtual int isCodeseg(); + int isCtorinit() { return storage_class & STCctorinit; } + int isFinal() { return storage_class & STCfinal; } + int isAbstract() { return storage_class & STCabstract; } + int isConst() { return storage_class & STCconst; } + int isInvariant() { return 0; } + int isAuto() { return storage_class & STCauto; } + int isScope() { return storage_class & (STCscope | STCauto); } + int isSynchronized() { return storage_class & STCsynchronized; } + int isParameter() { return storage_class & STCparameter; } + int isDeprecated() { return storage_class & STCdeprecated; } + int isOverride() { return storage_class & STCoverride; } + + int isIn() { return storage_class & STCin; } + int isOut() { return storage_class & STCout; } + int isRef() { return storage_class & STCref; } + + enum PROT prot(); + + Declaration *isDeclaration() { return this; } + +#if IN_LLVM + /// Codegen traversal + virtual void codegen(Ir* ir); +#endif +}; + +/**************************************************************/ + +struct TupleDeclaration : Declaration +{ + Objects *objects; + int isexp; // 1: expression tuple + + TypeTuple *tupletype; // !=NULL if this is a type tuple + + TupleDeclaration(Loc loc, Identifier *ident, Objects *objects); + Dsymbol *syntaxCopy(Dsymbol *); + const char *kind(); + Type *getType(); + int needThis(); + + TupleDeclaration *isTupleDeclaration() { return this; } + +#if IN_LLVM + /// Codegen traversal + void codegen(Ir* ir); +#endif +}; + +/**************************************************************/ + +struct TypedefDeclaration : Declaration +{ + Type *basetype; + Initializer *init; + int sem; // 0: semantic() has not been run + // 1: semantic() is in progress + // 2: semantic() has been run + // 3: semantic2() has been run + int inuse; // used to detect typedef cycles + + TypedefDeclaration(Loc loc, Identifier *ident, Type *basetype, Initializer *init); + Dsymbol *syntaxCopy(Dsymbol *); + void semantic(Scope *sc); + void semantic2(Scope *sc); + char *mangle(); + const char *kind(); + Type *getType(); + void toCBuffer(OutBuffer *buf, HdrGenState *hgs); +#ifdef _DH + Type *htype; + Type *hbasetype; +#endif + + void toDocBuffer(OutBuffer *buf); + +#if IN_DMD + void toObjFile(int multiobj); // compile to .obj file + void toDebug(); + int cvMember(unsigned char *p); +#endif + + TypedefDeclaration *isTypedefDeclaration() { return this; } + +#if IN_DMD + Symbol *sinit; + Symbol *toInitializer(); +#endif + +#if IN_LLVM + /// Codegen traversal + void codegen(Ir* ir); +#endif +}; + +/**************************************************************/ + +struct AliasDeclaration : Declaration +{ + Dsymbol *aliassym; + Dsymbol *overnext; // next in overload list + int inSemantic; + + AliasDeclaration(Loc loc, Identifier *ident, Type *type); + AliasDeclaration(Loc loc, Identifier *ident, Dsymbol *s); + Dsymbol *syntaxCopy(Dsymbol *); + void semantic(Scope *sc); + int overloadInsert(Dsymbol *s); + const char *kind(); + Type *getType(); + Dsymbol *toAlias(); + void toCBuffer(OutBuffer *buf, HdrGenState *hgs); +#ifdef _DH + Type *htype; + Dsymbol *haliassym; +#endif + + void toDocBuffer(OutBuffer *buf); + + AliasDeclaration *isAliasDeclaration() { return this; } +}; + +/**************************************************************/ + +struct VarDeclaration : Declaration +{ + Initializer *init; + unsigned offset; + int noauto; // no auto semantics + int nestedref; // referenced by a lexically nested function + int inuse; + int ctorinit; // it has been initialized in a ctor + int onstack; // 1: it has been allocated on the stack + // 2: on stack, run destructor anyway + int canassign; // it can be assigned to + Dsymbol *aliassym; // if redone as alias to another symbol + Expression *value; // when interpreting, this is the value + // (NULL if value not determinable) + + VarDeclaration(Loc loc, Type *t, Identifier *id, Initializer *init); + Dsymbol *syntaxCopy(Dsymbol *); + void semantic(Scope *sc); + void semantic2(Scope *sc); + const char *kind(); + void toCBuffer(OutBuffer *buf, HdrGenState *hgs); +#ifdef _DH + Type *htype; + Initializer *hinit; +#endif + int needThis(); + int isImportedSymbol(); + int isDataseg(); + int hasPointers(); + Expression *callAutoDtor(); + ExpInitializer *getExpInitializer(); + void checkCtorConstInit(); + void checkNestedReference(Scope *sc, Loc loc); + Dsymbol *toAlias(); + +#if IN_DMD + void toObjFile(int multiobj); // compile to .obj file + Symbol *toSymbol(); + int cvMember(unsigned char *p); +#endif + + // Eliminate need for dynamic_cast + VarDeclaration *isVarDeclaration() { return (VarDeclaration *)this; } + +#if IN_LLVM + /// Codegen traversal + virtual void codegen(Ir* ir); + + // LDC + AnonDeclaration* anonDecl; + unsigned offset2; + bool nakedUse; +#endif +}; + +/**************************************************************/ + +// LDC uses this to denote static struct initializers + +struct StaticStructInitDeclaration : Declaration +{ + StructDeclaration *dsym; + + StaticStructInitDeclaration(Loc loc, StructDeclaration *dsym); + +#if IN_DMD + Symbol *toSymbol(); +#endif + + // Eliminate need for dynamic_cast + StaticStructInitDeclaration *isStaticStructInitDeclaration() { return (StaticStructInitDeclaration *)this; } +}; + +struct ClassInfoDeclaration : VarDeclaration +{ + ClassDeclaration *cd; + + ClassInfoDeclaration(ClassDeclaration *cd); + Dsymbol *syntaxCopy(Dsymbol *); + void semantic(Scope *sc); + + void emitComment(Scope *sc); + +#if IN_DMD + Symbol *toSymbol(); +#endif + + ClassInfoDeclaration* isClassInfoDeclaration() { return this; } +}; + +struct ModuleInfoDeclaration : VarDeclaration +{ + Module *mod; + + ModuleInfoDeclaration(Module *mod); + Dsymbol *syntaxCopy(Dsymbol *); + void semantic(Scope *sc); + + void emitComment(Scope *sc); + +#if IN_DMD + Symbol *toSymbol(); +#endif +}; + +struct TypeInfoDeclaration : VarDeclaration +{ + Type *tinfo; + + TypeInfoDeclaration(Type *tinfo, int internal); + Dsymbol *syntaxCopy(Dsymbol *); + void semantic(Scope *sc); + + void emitComment(Scope *sc); + +#if IN_DMD + void toObjFile(int multiobj); // compile to .obj file + Symbol *toSymbol(); + virtual void toDt(dt_t **pdt); +#endif + + virtual TypeInfoDeclaration* isTypeInfoDeclaration() { return this; } + +#if IN_LLVM + /// Codegen traversal + void codegen(Ir* ir); + virtual void llvmDefine(); +#endif +}; + +struct TypeInfoStructDeclaration : TypeInfoDeclaration +{ + TypeInfoStructDeclaration(Type *tinfo); + +#if IN_DMD + void toDt(dt_t **pdt); +#endif + +#if IN_LLVM + void llvmDefine(); +#endif +}; + +struct TypeInfoClassDeclaration : TypeInfoDeclaration +{ + TypeInfoClassDeclaration(Type *tinfo); + +#if IN_DMD + void toDt(dt_t **pdt); +#endif + +#if IN_LLVM + void llvmDefine(); +#endif +}; + +struct TypeInfoInterfaceDeclaration : TypeInfoDeclaration +{ + TypeInfoInterfaceDeclaration(Type *tinfo); + +#if IN_DMD + void toDt(dt_t **pdt); +#endif + +#if IN_LLVM + void llvmDefine(); +#endif +}; + +struct TypeInfoTypedefDeclaration : TypeInfoDeclaration +{ + TypeInfoTypedefDeclaration(Type *tinfo); + +#if IN_DMD + void toDt(dt_t **pdt); +#endif + +#if IN_LLVM + void llvmDefine(); +#endif +}; + +struct TypeInfoPointerDeclaration : TypeInfoDeclaration +{ + TypeInfoPointerDeclaration(Type *tinfo); + +#if IN_DMD + void toDt(dt_t **pdt); +#endif + +#if IN_LLVM + void llvmDefine(); +#endif +}; + +struct TypeInfoArrayDeclaration : TypeInfoDeclaration +{ + TypeInfoArrayDeclaration(Type *tinfo); + +#if IN_DMD + void toDt(dt_t **pdt); +#endif + +#if IN_LLVM + void llvmDefine(); +#endif +}; + +struct TypeInfoStaticArrayDeclaration : TypeInfoDeclaration +{ + TypeInfoStaticArrayDeclaration(Type *tinfo); + +#if IN_DMD + void toDt(dt_t **pdt); +#endif + +#if IN_LLVM + void llvmDefine(); +#endif +}; + +struct TypeInfoAssociativeArrayDeclaration : TypeInfoDeclaration +{ + TypeInfoAssociativeArrayDeclaration(Type *tinfo); + +#if IN_DMD + void toDt(dt_t **pdt); +#endif + +#if IN_LLVM + void llvmDefine(); +#endif +}; + +struct TypeInfoEnumDeclaration : TypeInfoDeclaration +{ + TypeInfoEnumDeclaration(Type *tinfo); + +#if IN_DMD + void toDt(dt_t **pdt); +#endif + +#if IN_LLVM + void llvmDefine(); +#endif +}; + +struct TypeInfoFunctionDeclaration : TypeInfoDeclaration +{ + TypeInfoFunctionDeclaration(Type *tinfo); + +#if IN_DMD + void toDt(dt_t **pdt); +#endif + +#if IN_LLVM + void llvmDefine(); +#endif +}; + +struct TypeInfoDelegateDeclaration : TypeInfoDeclaration +{ + TypeInfoDelegateDeclaration(Type *tinfo); + +#if IN_DMD + void toDt(dt_t **pdt); +#endif + +#if IN_LLVM + void llvmDefine(); +#endif +}; + +struct TypeInfoTupleDeclaration : TypeInfoDeclaration +{ + TypeInfoTupleDeclaration(Type *tinfo); + +#if IN_DMD + void toDt(dt_t **pdt); +#endif + +#if IN_LLVM + void llvmDefine(); +#endif +}; + +#if DMDV2 +struct TypeInfoConstDeclaration : TypeInfoDeclaration +{ + TypeInfoConstDeclaration(Type *tinfo); + +#if IN_DMD + void toDt(dt_t **pdt); +#endif + +#if IN_LLVM + void llvmDefine(); +#endif +}; + +struct TypeInfoInvariantDeclaration : TypeInfoDeclaration +{ + TypeInfoInvariantDeclaration(Type *tinfo); + +#if IN_DMD + void toDt(dt_t **pdt); +#endif + +#if IN_LLVM + void llvmDefine(); +#endif +}; +#endif + +/**************************************************************/ + +struct ThisDeclaration : VarDeclaration +{ + ThisDeclaration(Type *t); + Dsymbol *syntaxCopy(Dsymbol *); +}; + +enum ILS +{ + ILSuninitialized, // not computed yet + ILSno, // cannot inline + ILSyes, // can inline +}; + +/**************************************************************/ +#if DMDV2 + +enum BUILTIN +{ + BUILTINunknown = -1, // not known if this is a builtin + BUILTINnot, // this is not a builtin + BUILTINsin, // std.math.sin + BUILTINcos, // std.math.cos + BUILTINtan, // std.math.tan + BUILTINsqrt, // std.math.sqrt + BUILTINfabs, // std.math.fabs +}; + +Expression *eval_builtin(enum BUILTIN builtin, Expressions *arguments); + +#endif + +struct FuncDeclaration : Declaration +{ + Array *fthrows; // Array of Type's of exceptions (not used) + Statement *frequire; + Statement *fensure; + Statement *fbody; + + Identifier *outId; // identifier for out statement + VarDeclaration *vresult; // variable corresponding to outId + LabelDsymbol *returnLabel; // where the return goes + + DsymbolTable *localsymtab; // used to prevent symbols in different + // scopes from having the same name + VarDeclaration *vthis; // 'this' parameter (member and nested) + VarDeclaration *v_arguments; // '_arguments' parameter +#if IN_GCC + VarDeclaration *v_argptr; // '_argptr' variable +#endif + Dsymbols *parameters; // Array of VarDeclaration's for parameters + DsymbolTable *labtab; // statement label symbol table + Declaration *overnext; // next in overload list + Loc endloc; // location of closing curly bracket + int vtblIndex; // for member functions, index into vtbl[] + int naked; // !=0 if naked + int inlineAsm; // !=0 if has inline assembler + ILS inlineStatus; + int inlineNest; // !=0 if nested inline + int cantInterpret; // !=0 if cannot interpret function + int semanticRun; // !=0 if semantic3() had been run + // this function's frame ptr + ForeachStatement *fes; // if foreach body, this is the foreach + int introducing; // !=0 if 'introducing' function + Type *tintro; // if !=NULL, then this is the type + // of the 'introducing' function + // this one is overriding + int inferRetType; // !=0 if return type is to be inferred + Scope *scope; // !=NULL means context to use + + // Things that should really go into Scope + int hasReturnExp; // 1 if there's a return exp; statement + // 2 if there's a throw statement + // 4 if there's an assert(0) + // 8 if there's inline asm + + // Support for NRVO (named return value optimization) + int nrvo_can; // !=0 means we can do it + VarDeclaration *nrvo_var; // variable to replace with shidden +#if IN_DMD + Symbol *shidden; // hidden pointer passed to function +#endif + +#if DMDV2 + enum BUILTIN builtin; // set if this is a known, builtin + // function we can evaluate at compile + // time + + int tookAddressOf; // set if someone took the address of + // this function + Dsymbols closureVars; // local variables in this function + // which are referenced by nested + // functions +#else + int nestedFrameRef; // !=0 if nested variables referenced +#endif + + FuncDeclaration(Loc loc, Loc endloc, Identifier *id, enum STC storage_class, Type *type); + Dsymbol *syntaxCopy(Dsymbol *); + void semantic(Scope *sc); + void semantic2(Scope *sc); + void semantic3(Scope *sc); + void toCBuffer(OutBuffer *buf, HdrGenState *hgs); + void bodyToCBuffer(OutBuffer *buf, HdrGenState *hgs); + int overrides(FuncDeclaration *fd); + int findVtblIndex(Array *vtbl, int dim); + int overloadInsert(Dsymbol *s); + FuncDeclaration *overloadExactMatch(Type *t); + FuncDeclaration *overloadResolve(Loc loc, Expressions *arguments); + LabelDsymbol *searchLabel(Identifier *ident); + AggregateDeclaration *isThis(); + AggregateDeclaration *isMember2(); + int getLevel(Loc loc, FuncDeclaration *fd); // lexical nesting level difference + void appendExp(Expression *e); + void appendState(Statement *s); + char *mangle(); + int isMain(); + int isWinMain(); + int isDllMain(); + int isExport(); + int isImportedSymbol(); + int isAbstract(); + int isCodeseg(); + virtual int isNested(); + int needThis(); + virtual int isVirtual(); + virtual int isFinal(); + virtual int addPreInvariant(); + virtual int addPostInvariant(); + Expression *interpret(InterState *istate, Expressions *arguments); + void inlineScan(); + int canInline(int hasthis, int hdrscan = 0); + Expression *doInline(InlineScanState *iss, Expression *ethis, Array *arguments); + const char *kind(); + void toDocBuffer(OutBuffer *buf); + +// LDC: give argument types to runtime functions + static FuncDeclaration *genCfunc(Arguments *args, Type *treturn, const char *name); + static FuncDeclaration *genCfunc(Arguments *args, Type *treturn, Identifier *id); + +#if IN_DMD + Symbol *toSymbol(); + Symbol *toThunkSymbol(int offset); // thunk version + void toObjFile(int multiobj); // compile to .obj file + int cvMember(unsigned char *p); +#endif + + FuncDeclaration *isFuncDeclaration() { return this; } + +#if IN_LLVM + // LDC stuff + + /// Codegen traversal + void codegen(Ir* ir); + + // vars declared in this function that nested funcs reference + // is this is not empty, nestedFrameRef is set and these VarDecls + // probably have nestedref set too, see VarDeclaration::checkNestedReference + std::set nestedVars; + + std::string intrinsicName; + + bool isIntrinsic(); + bool isVaIntrinsic(); + + // we keep our own table of label statements as LabelDsymbolS + // don't always carry their corresponding statement along ... + typedef std::map LabelMap; + LabelMap labmap; + + // if this is an array operation it gets a little special attention + bool isArrayOp; + + // true if overridden with the pragma(allow_inline); stmt + bool allowInlining; +#endif +}; + +struct FuncAliasDeclaration : FuncDeclaration +{ + FuncDeclaration *funcalias; + + FuncAliasDeclaration(FuncDeclaration *funcalias); + + FuncAliasDeclaration *isFuncAliasDeclaration() { return this; } + const char *kind(); +#if IN_DMD + Symbol *toSymbol(); +#endif +}; + +struct FuncLiteralDeclaration : FuncDeclaration +{ + enum TOK tok; // TOKfunction or TOKdelegate + + FuncLiteralDeclaration(Loc loc, Loc endloc, Type *type, enum TOK tok, + ForeachStatement *fes); + void toCBuffer(OutBuffer *buf, HdrGenState *hgs); + Dsymbol *syntaxCopy(Dsymbol *); + int isNested(); + int isVirtual(); + + FuncLiteralDeclaration *isFuncLiteralDeclaration() { return this; } + const char *kind(); +}; + +struct CtorDeclaration : FuncDeclaration +{ Arguments *arguments; + int varargs; + + CtorDeclaration(Loc loc, Loc endloc, Arguments *arguments, int varargs); + Dsymbol *syntaxCopy(Dsymbol *); + void semantic(Scope *sc); + void toCBuffer(OutBuffer *buf, HdrGenState *hgs); + const char *kind(); + char *toChars(); + int isVirtual(); + int addPreInvariant(); + int addPostInvariant(); + void toDocBuffer(OutBuffer *buf); + + CtorDeclaration *isCtorDeclaration() { return this; } +}; + +#if DMDV2 +struct PostBlitDeclaration : FuncDeclaration +{ + PostBlitDeclaration(Loc loc, Loc endloc); + PostBlitDeclaration(Loc loc, Loc endloc, Identifier *id); + Dsymbol *syntaxCopy(Dsymbol *); + void semantic(Scope *sc); + void toCBuffer(OutBuffer *buf, HdrGenState *hgs); + int isVirtual(); + int addPreInvariant(); + int addPostInvariant(); + int overloadInsert(Dsymbol *s); + void emitComment(Scope *sc); + + PostBlitDeclaration *isPostBlitDeclaration() { return this; } +}; +#endif + +struct DtorDeclaration : FuncDeclaration +{ + DtorDeclaration(Loc loc, Loc endloc); + DtorDeclaration(Loc loc, Loc endloc, Identifier *id); + Dsymbol *syntaxCopy(Dsymbol *); + void semantic(Scope *sc); + void toCBuffer(OutBuffer *buf, HdrGenState *hgs); + int isVirtual(); + int addPreInvariant(); + int addPostInvariant(); + int overloadInsert(Dsymbol *s); + void emitComment(Scope *sc); + + DtorDeclaration *isDtorDeclaration() { return this; } +}; + +struct StaticCtorDeclaration : FuncDeclaration +{ + StaticCtorDeclaration(Loc loc, Loc endloc); + Dsymbol *syntaxCopy(Dsymbol *); + void semantic(Scope *sc); + AggregateDeclaration *isThis(); + int isStaticConstructor(); + int isVirtual(); + int addPreInvariant(); + int addPostInvariant(); + void emitComment(Scope *sc); + void toCBuffer(OutBuffer *buf, HdrGenState *hgs); + + StaticCtorDeclaration *isStaticCtorDeclaration() { return this; } +}; + +struct StaticDtorDeclaration : FuncDeclaration +{ VarDeclaration *vgate; // 'gate' variable + + StaticDtorDeclaration(Loc loc, Loc endloc); + Dsymbol *syntaxCopy(Dsymbol *); + void semantic(Scope *sc); + AggregateDeclaration *isThis(); + int isStaticDestructor(); + int isVirtual(); + int addPreInvariant(); + int addPostInvariant(); + void emitComment(Scope *sc); + void toCBuffer(OutBuffer *buf, HdrGenState *hgs); + + StaticDtorDeclaration *isStaticDtorDeclaration() { return this; } +}; + +struct InvariantDeclaration : FuncDeclaration +{ + InvariantDeclaration(Loc loc, Loc endloc); + Dsymbol *syntaxCopy(Dsymbol *); + void semantic(Scope *sc); + int isVirtual(); + int addPreInvariant(); + int addPostInvariant(); + void emitComment(Scope *sc); + void toCBuffer(OutBuffer *buf, HdrGenState *hgs); + + InvariantDeclaration *isInvariantDeclaration() { return this; } +}; + + +struct UnitTestDeclaration : FuncDeclaration +{ + UnitTestDeclaration(Loc loc, Loc endloc); + Dsymbol *syntaxCopy(Dsymbol *); + void semantic(Scope *sc); + AggregateDeclaration *isThis(); + int isVirtual(); + int addPreInvariant(); + int addPostInvariant(); + void toCBuffer(OutBuffer *buf, HdrGenState *hgs); + + UnitTestDeclaration *isUnitTestDeclaration() { return this; } +}; + +struct NewDeclaration : FuncDeclaration +{ Arguments *arguments; + int varargs; + + NewDeclaration(Loc loc, Loc endloc, Arguments *arguments, int varargs); + Dsymbol *syntaxCopy(Dsymbol *); + void semantic(Scope *sc); + void toCBuffer(OutBuffer *buf, HdrGenState *hgs); + const char *kind(); + int isVirtual(); + int addPreInvariant(); + int addPostInvariant(); + + NewDeclaration *isNewDeclaration() { return this; } +}; + + +struct DeleteDeclaration : FuncDeclaration +{ Arguments *arguments; + + DeleteDeclaration(Loc loc, Loc endloc, Arguments *arguments); + Dsymbol *syntaxCopy(Dsymbol *); + void semantic(Scope *sc); + void toCBuffer(OutBuffer *buf, HdrGenState *hgs); + const char *kind(); + int isDelete(); + int isVirtual(); + int addPreInvariant(); + int addPostInvariant(); +#ifdef _DH + DeleteDeclaration *isDeleteDeclaration() { return this; } +#endif +}; + +#endif /* DMD_DECLARATION_H */ diff -r 1853dcd9b944 -r e961851fb8be dmd/enum.c --- a/dmd/enum.c Fri Apr 03 17:02:52 2009 +0200 +++ b/dmd/enum.c Fri Apr 03 17:59:34 2009 +0200 @@ -1,5 +1,5 @@ -// Copyright (c) 1999-2008 by Digital Mars +// Copyright (c) 1999-2009 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com diff -r 1853dcd9b944 -r e961851fb8be dmd/enum.h --- a/dmd/enum.h Fri Apr 03 17:02:52 2009 +0200 +++ b/dmd/enum.h Fri Apr 03 17:59:34 2009 +0200 @@ -32,9 +32,9 @@ Type *memtype; // type of the members #if DMDV1 - integer_t maxval; - integer_t minval; - integer_t defaultval; // default initializer + dinteger_t maxval; + dinteger_t minval; + dinteger_t defaultval; // default initializer #else Expression *maxval; Expression *minval; diff -r 1853dcd9b944 -r e961851fb8be dmd/expression.c --- a/dmd/expression.c Fri Apr 03 17:02:52 2009 +0200 +++ b/dmd/expression.c Fri Apr 03 17:59:34 2009 +0200 @@ -34,15 +34,6 @@ #endif #endif -#if IN_GCC -// Issues with using -include total.h (defines integer_t) and then complex.h fails... -#undef integer_t -#endif - -#ifdef __APPLE__ -#define integer_t dmd_integer_t -#endif - #include "rmem.h" //#include "port.h" @@ -700,7 +691,6 @@ arg = arg->checkToPointer(); } #endif - #if DMDV2 if (tb->ty == Tstruct && !(p->storageClass & (STCref | STCout))) { @@ -1000,7 +990,7 @@ return e1; } -integer_t Expression::toInteger() +dinteger_t Expression::toInteger() { //printf("Expression %s\n", Token::toChars(op)); error("Integer constant expression expected instead of %s", toChars()); @@ -1289,7 +1279,7 @@ /******************************** IntegerExp **************************/ -IntegerExp::IntegerExp(Loc loc, integer_t value, Type *type) +IntegerExp::IntegerExp(Loc loc, dinteger_t value, Type *type) : Expression(loc, TOKint64, sizeof(IntegerExp)) { //printf("IntegerExp(value = %lld, type = '%s')\n", value, type ? type->toChars() : ""); @@ -1303,7 +1293,7 @@ this->value = value; } -IntegerExp::IntegerExp(integer_t value) +IntegerExp::IntegerExp(dinteger_t value) : Expression(0, TOKint64, sizeof(IntegerExp)) { this->type = Type::tint32; @@ -1333,7 +1323,7 @@ #endif } -integer_t IntegerExp::toInteger() +dinteger_t IntegerExp::toInteger() { Type *t; t = type; @@ -1355,11 +1345,12 @@ case Tint64: value = (d_int64) value; break; case Tuns64: value = (d_uns64) value; break; case Tpointer: - // FIXME: Other pointer widths than 32 and 64? if (PTRSIZE == 4) value = (d_uns32) value; - else + else if (PTRSIZE == 8) value = (d_uns64) value; + else + assert(0); break; case Tenum: @@ -1423,7 +1414,7 @@ if (!type) { // Determine what the type of this number is - integer_t number = value; + dinteger_t number = value; if (number & 0x8000000000000000LL) type = Type::tuns64; @@ -1451,7 +1442,7 @@ void IntegerExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) { - integer_t v = toInteger(); + dinteger_t v = toInteger(); if (type) { Type *t = type; @@ -1520,7 +1511,7 @@ break; case Tuns64: - L4: + L4: buf->printf("%juLU", v); break; @@ -1533,11 +1524,12 @@ buf->writestring("cast("); buf->writestring(t->toChars()); buf->writeByte(')'); - // FIXME: Other pointer widths than 32 and 64? if (PTRSIZE == 4) goto L3; - else + else if (PTRSIZE == 8) goto L4; + else + assert(0); default: /* This can happen if errors, such as @@ -1592,7 +1584,7 @@ return mem.strdup(buffer); } -integer_t RealExp::toInteger() +dinteger_t RealExp::toInteger() { #ifdef IN_GCC return toReal().toInt(); @@ -1817,7 +1809,7 @@ return mem.strdup(buffer); } -integer_t ComplexExp::toInteger() +dinteger_t ComplexExp::toInteger() { #ifdef IN_GCC return (sinteger_t) toReal().toInt(); @@ -2163,9 +2155,11 @@ imp = s->isImport(); if (imp) { - ScopeExp *ie; - - ie = new ScopeExp(loc, imp->pkg); + if (!imp->pkg) + { error("forward reference of import %s", imp->toChars()); + return this; + } + ScopeExp *ie = new ScopeExp(loc, imp->pkg); return ie->semantic(sc); } pkg = s->isPackage(); @@ -3650,7 +3644,7 @@ if (cd->aggNew) { - // Prepend the size_t size argument to newargs[] + // Prepend the size argument to newargs[] Expression *e = new IntegerExp(loc, cd->size(loc), Type::tsize_t); if (!newargs) newargs = new Expressions(); @@ -4319,7 +4313,8 @@ void FuncExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) { - buf->writestring(fd->toChars()); + fd->toCBuffer(buf, hgs); + //buf->writestring(fd->toChars()); } @@ -7593,8 +7588,8 @@ e2 = e2->optimize(WANTvalue); if (e2->op == TOKint64) { - integer_t index = e2->toInteger(); - integer_t length = tsa->dim->toInteger(); + dinteger_t index = e2->toInteger(); + dinteger_t length = tsa->dim->toInteger(); if (index < 0 || index >= length) error("array index [%lld] is outside array bounds [0 .. %lld]", index, length); diff -r 1853dcd9b944 -r e961851fb8be dmd/expression.h --- a/dmd/expression.h Fri Apr 03 17:02:52 2009 +0200 +++ b/dmd/expression.h Fri Apr 03 17:59:34 2009 +0200 @@ -1,6 +1,6 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2008 by Digital Mars +// Copyright (c) 1999-2009 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -105,7 +105,7 @@ static Expression *combine(Expression *e1, Expression *e2); static Expressions *arraySyntaxCopy(Expressions *exps); - virtual integer_t toInteger(); + virtual dinteger_t toInteger(); virtual uinteger_t toUInteger(); virtual real_t toReal(); virtual real_t toImaginary(); @@ -175,16 +175,16 @@ struct IntegerExp : Expression { - integer_t value; + dinteger_t value; - IntegerExp(Loc loc, integer_t value, Type *type); - IntegerExp(integer_t value); + IntegerExp(Loc loc, dinteger_t value, Type *type); + IntegerExp(dinteger_t value); int equals(Object *o); Expression *semantic(Scope *sc); Expression *interpret(InterState *istate); char *toChars(); void dump(int indent); - integer_t toInteger(); + dinteger_t toInteger(); real_t toReal(); real_t toImaginary(); complex_t toComplex(); @@ -212,7 +212,7 @@ Expression *semantic(Scope *sc); Expression *interpret(InterState *istate); char *toChars(); - integer_t toInteger(); + dinteger_t toInteger(); uinteger_t toUInteger(); real_t toReal(); real_t toImaginary(); @@ -240,7 +240,7 @@ Expression *semantic(Scope *sc); Expression *interpret(InterState *istate); char *toChars(); - integer_t toInteger(); + dinteger_t toInteger(); uinteger_t toUInteger(); real_t toReal(); real_t toImaginary(); diff -r 1853dcd9b944 -r e961851fb8be dmd/func.c --- a/dmd/func.c Fri Apr 03 17:02:52 2009 +0200 +++ b/dmd/func.c Fri Apr 03 17:59:34 2009 +0200 @@ -1237,7 +1237,7 @@ { // Call invariant virtually ThisExp *v = new ThisExp(0); v->type = vthis->type; - Expression *se = new StringExp(0, "null this"); + Expression *se = new StringExp(0, (char *)"null this"); se = se->semantic(sc); se->type = Type::tchar->arrayOf(); e = new AssertExp(loc, v, se); @@ -2878,7 +2878,7 @@ type = type->semantic(loc, sc); assert(type->ty == Tfunction); - // Check that there is at least one argument of type uint + // Check that there is at least one argument of type size_t TypeFunction *tf = (TypeFunction *)type; if (Argument::dim(tf->parameters) < 1) { diff -r 1853dcd9b944 -r e961851fb8be dmd/identifier.c --- a/dmd/identifier.c Fri Apr 03 17:02:52 2009 +0200 +++ b/dmd/identifier.c Fri Apr 03 17:59:34 2009 +0200 @@ -45,9 +45,9 @@ return (char *)string; } -char *Identifier::toHChars2() +const char *Identifier::toHChars2() { - char *p = NULL; + const char *p = NULL; if (this == Id::ctor) p = "this"; else if (this == Id::dtor) p = "~this"; diff -r 1853dcd9b944 -r e961851fb8be dmd/identifier.h --- a/dmd/identifier.h Fri Apr 03 17:02:52 2009 +0200 +++ b/dmd/identifier.h Fri Apr 03 17:59:34 2009 +0200 @@ -37,7 +37,7 @@ #ifdef _DH char *toHChars(); #endif - char *toHChars2(); + const char *toHChars2(); int dyncast(); static Identifier *generateId(const char *prefix); diff -r 1853dcd9b944 -r e961851fb8be dmd/lexer.c --- a/dmd/lexer.c Fri Apr 03 17:02:52 2009 +0200 +++ b/dmd/lexer.c Fri Apr 03 17:59:34 2009 +0200 @@ -1,6 +1,6 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2008 by Digital Mars +// Copyright (c) 1999-2009 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -8,7 +8,7 @@ // in artistic.txt, or the GNU General Public License in gnu.txt. // See the included readme.txt for details. -#define __C99FEATURES__ 1 +#include /* Lexical Analyzer */ @@ -20,19 +20,7 @@ #include #include #include -#include - -#if _MSC_VER -#include -#else -#include -#endif - -#ifdef IN_GCC -#include -#elif __GNUC__ -#include -#endif +#include // for time() and ctime() #include "rmem.h" @@ -49,10 +37,6 @@ extern "C" char * __cdecl __locale_decpoint; #endif -#if _MSC_VER // workaround VC++ bug, labels and types should be in separate namespaces -#define Lstring Lstr -#endif - extern int HtmlNamedEntity(unsigned char *p, int length); #define LS 0x2028 // UTF line separator @@ -682,7 +666,7 @@ if (mod && id == Id::FILE) { t->ustring = (unsigned char *)(loc.filename ? loc.filename : mod->ident->toChars()); - goto Lstring; + goto Lstr; } else if (mod && id == Id::LINE) { @@ -694,22 +678,22 @@ if (id == Id::DATE) { t->ustring = (unsigned char *)date; - goto Lstring; + goto Lstr; } else if (id == Id::TIME) { t->ustring = (unsigned char *)time; - goto Lstring; + goto Lstr; } else if (id == Id::VENDOR) { t->ustring = (unsigned char *)"LDC"; - goto Lstring; + goto Lstr; } else if (id == Id::TIMESTAMP) { t->ustring = (unsigned char *)timestamp; - Lstring: + Lstr: t->value = TOKstring; Llen: t->postfix = 0; @@ -3097,4 +3081,6 @@ Token::tochars[TOKdeclaration] = "declaration"; Token::tochars[TOKdottd] = "dottd"; Token::tochars[TOKon_scope_exit] = "scope(exit)"; + Token::tochars[TOKon_scope_success] = "scope(success)"; + Token::tochars[TOKon_scope_failure] = "scope(failure)"; } diff -r 1853dcd9b944 -r e961851fb8be dmd/lexer.h --- a/dmd/lexer.h Fri Apr 03 17:02:52 2009 +0200 +++ b/dmd/lexer.h Fri Apr 03 17:59:34 2009 +0200 @@ -1,305 +1,305 @@ - -// Compiler implementation of the D programming language -// Copyright (c) 1999-2008 by Digital Mars -// All Rights Reserved -// written by Walter Bright -// 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. - -#ifndef DMD_LEXER_H -#define DMD_LEXER_H - -#ifdef __DMC__ -#pragma once -#endif /* __DMC__ */ - -#include "root.h" -#include "mars.h" - -struct StringTable; -struct Identifier; -struct Module; - -/* Tokens: - ( ) - [ ] - { } - < > <= >= == != === !== - << >> <<= >>= >>> >>>= - + - += -= - * / % *= /= %= - & | ^ &= |= ^= - = ! ~ - ++ -- - . -> : , - ? && || - */ - -enum TOK -{ - TOKreserved, - - // Other - TOKlparen, TOKrparen, - TOKlbracket, TOKrbracket, - TOKlcurly, TOKrcurly, - TOKcolon, TOKneg, - TOKsemicolon, TOKdotdotdot, - TOKeof, TOKcast, - TOKnull, TOKassert, - TOKtrue, TOKfalse, - TOKarray, TOKcall, - TOKaddress, TOKtypedot, - TOKtype, TOKthrow, - TOKnew, TOKdelete, - TOKstar, TOKsymoff, - TOKvar, TOKdotvar, - TOKdotti, TOKdotexp, - TOKdottype, TOKslice, - TOKarraylength, TOKversion, - TOKmodule, TOKdollar, - TOKtemplate, TOKdottd, - TOKdeclaration, TOKtypeof, - TOKpragma, TOKdsymbol, - TOKtypeid, TOKuadd, - TOKremove, - TOKnewanonclass, TOKcomment, - TOKarrayliteral, TOKassocarrayliteral, - TOKstructliteral, - - // Operators - TOKlt, TOKgt, - TOKle, TOKge, - TOKequal, TOKnotequal, - TOKidentity, TOKnotidentity, - TOKindex, TOKis, - TOKtobool, - -// 60 - // NCEG floating point compares - // !<>= <> <>= !> !>= !< !<= !<> - TOKunord,TOKlg,TOKleg,TOKule,TOKul,TOKuge,TOKug,TOKue, - - TOKshl, TOKshr, - TOKshlass, TOKshrass, - TOKushr, TOKushrass, - TOKcat, TOKcatass, // ~ ~= - TOKadd, TOKmin, TOKaddass, TOKminass, - TOKmul, TOKdiv, TOKmod, - TOKmulass, TOKdivass, TOKmodass, - TOKand, TOKor, TOKxor, - TOKandass, TOKorass, TOKxorass, - TOKassign, TOKnot, TOKtilde, - TOKplusplus, TOKminusminus, TOKconstruct, TOKblit, - TOKdot, TOKarrow, TOKcomma, - TOKquestion, TOKandand, TOKoror, - -// 104 - // Numeric literals - TOKint32v, TOKuns32v, - TOKint64v, TOKuns64v, - TOKfloat32v, TOKfloat64v, TOKfloat80v, - TOKimaginary32v, TOKimaginary64v, TOKimaginary80v, - - // Char constants - TOKcharv, TOKwcharv, TOKdcharv, - - // Leaf operators - TOKidentifier, TOKstring, - TOKthis, TOKsuper, - TOKhalt, TOKtuple, - - // Basic types - TOKvoid, - TOKint8, TOKuns8, - TOKint16, TOKuns16, - TOKint32, TOKuns32, - TOKint64, TOKuns64, - TOKfloat32, TOKfloat64, TOKfloat80, - TOKimaginary32, TOKimaginary64, TOKimaginary80, - TOKcomplex32, TOKcomplex64, TOKcomplex80, - TOKchar, TOKwchar, TOKdchar, TOKbit, TOKbool, - TOKcent, TOKucent, - - // Aggregates - TOKstruct, TOKclass, TOKinterface, TOKunion, TOKenum, TOKimport, - TOKtypedef, TOKalias, TOKoverride, TOKdelegate, TOKfunction, - TOKmixin, - - TOKalign, TOKextern, TOKprivate, TOKprotected, TOKpublic, TOKexport, - TOKstatic, /*TOKvirtual,*/ TOKfinal, TOKconst, TOKabstract, TOKvolatile, - TOKdebug, TOKdeprecated, TOKin, TOKout, TOKinout, TOKlazy, - TOKauto, TOKpackage, TOKmanifest, - - // Statements - TOKif, TOKelse, TOKwhile, TOKfor, TOKdo, TOKswitch, - TOKcase, TOKdefault, TOKbreak, TOKcontinue, TOKwith, - TOKsynchronized, TOKreturn, TOKgoto, TOKtry, TOKcatch, TOKfinally, - TOKasm, TOKforeach, TOKforeach_reverse, - TOKscope, - TOKon_scope_exit, TOKon_scope_failure, TOKon_scope_success, - - // Contracts - TOKbody, TOKinvariant, - - // Testing - TOKunittest, - - // Added after 1.0 - TOKref, - TOKmacro, -#if DMDV2 - TOKtraits, - TOKoverloadset, - TOKpure, - TOKnothrow, - TOKtls, - TOKline, - TOKfile, - TOKshared, -#endif - -// LDC specific -#if IN_LLVM - TOKgep, -#endif - - TOKMAX -}; - -#define CASE_BASIC_TYPES \ - case TOKwchar: case TOKdchar: \ - case TOKbit: case TOKbool: case TOKchar: \ - case TOKint8: case TOKuns8: \ - case TOKint16: case TOKuns16: \ - case TOKint32: case TOKuns32: \ - case TOKint64: case TOKuns64: \ - case TOKfloat32: case TOKfloat64: case TOKfloat80: \ - case TOKimaginary32: case TOKimaginary64: case TOKimaginary80: \ - case TOKcomplex32: case TOKcomplex64: case TOKcomplex80: \ - case TOKvoid - -#define CASE_BASIC_TYPES_X(t) \ - case TOKvoid: t = Type::tvoid; goto LabelX; \ - case TOKint8: t = Type::tint8; goto LabelX; \ - case TOKuns8: t = Type::tuns8; goto LabelX; \ - case TOKint16: t = Type::tint16; goto LabelX; \ - case TOKuns16: t = Type::tuns16; goto LabelX; \ - case TOKint32: t = Type::tint32; goto LabelX; \ - case TOKuns32: t = Type::tuns32; goto LabelX; \ - case TOKint64: t = Type::tint64; goto LabelX; \ - case TOKuns64: t = Type::tuns64; goto LabelX; \ - case TOKfloat32: t = Type::tfloat32; goto LabelX; \ - case TOKfloat64: t = Type::tfloat64; goto LabelX; \ - case TOKfloat80: t = Type::tfloat80; goto LabelX; \ - case TOKimaginary32: t = Type::timaginary32; goto LabelX; \ - case TOKimaginary64: t = Type::timaginary64; goto LabelX; \ - case TOKimaginary80: t = Type::timaginary80; goto LabelX; \ - case TOKcomplex32: t = Type::tcomplex32; goto LabelX; \ - case TOKcomplex64: t = Type::tcomplex64; goto LabelX; \ - case TOKcomplex80: t = Type::tcomplex80; goto LabelX; \ - case TOKbit: t = Type::tbit; goto LabelX; \ - case TOKbool: t = Type::tbool; goto LabelX; \ - case TOKchar: t = Type::tchar; goto LabelX; \ - case TOKwchar: t = Type::twchar; goto LabelX; \ - case TOKdchar: t = Type::tdchar; goto LabelX; \ - LabelX - -struct Token -{ - Token *next; - unsigned char *ptr; // pointer to first character of this token within buffer - enum TOK value; - unsigned char *blockComment; // doc comment string prior to this token - unsigned char *lineComment; // doc comment for previous token - union - { - // Integers - d_int64 int64value; - d_uns64 uns64value; - - // Floats -#ifdef IN_GCC - // real_t float80value; // can't use this in a union! -#else - d_float80 float80value; -#endif - - struct - { unsigned char *ustring; // UTF8 string - unsigned len; - unsigned char postfix; // 'c', 'w', 'd' - }; - - Identifier *ident; - }; -#ifdef IN_GCC - real_t float80value; // can't use this in a union! -#endif - - static const char *tochars[TOKMAX]; - static void *operator new(size_t sz); - - int isKeyword(); - void print(); - const char *toChars(); - static const char *toChars(enum TOK); -}; - -struct Lexer -{ - static StringTable stringtable; - static OutBuffer stringbuffer; - static Token *freelist; - - Loc loc; // for error messages - - unsigned char *base; // pointer to start of buffer - unsigned char *end; // past end of buffer - unsigned char *p; // current character - Token token; - Module *mod; - int doDocComment; // collect doc comment information - int anyToken; // !=0 means seen at least one token - int commentToken; // !=0 means comments are TOKcomment's - - Lexer(Module *mod, - unsigned char *base, unsigned begoffset, unsigned endoffset, - int doDocComment, int commentToken); - - static void initKeywords(); - static Identifier *idPool(const char *s); - static Identifier *uniqueId(const char *s); - static Identifier *uniqueId(const char *s, int num); - - TOK nextToken(); - TOK peekNext(); - void scan(Token *t); - Token *peek(Token *t); - Token *peekPastParen(Token *t); - unsigned escapeSequence(); - TOK wysiwygStringConstant(Token *t, int tc); - TOK hexStringConstant(Token *t); -#if DMDV2 - 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); - unsigned wchar(unsigned u); - TOK number(Token *t); - TOK inreal(Token *t); - void error(const char *format, ...); - void error(Loc loc, const char *format, ...); - void pragma(); - unsigned decodeUTF(); - void getDocComment(Token *t, unsigned lineComment); - - static int isValidIdentifier(char *p); - static unsigned char *combineComments(unsigned char *c1, unsigned char *c2); -}; - -#endif /* DMD_LEXER_H */ + +// Compiler implementation of the D programming language +// Copyright (c) 1999-2008 by Digital Mars +// All Rights Reserved +// written by Walter Bright +// 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. + +#ifndef DMD_LEXER_H +#define DMD_LEXER_H + +#ifdef __DMC__ +#pragma once +#endif /* __DMC__ */ + +#include "root.h" +#include "mars.h" + +struct StringTable; +struct Identifier; +struct Module; + +/* Tokens: + ( ) + [ ] + { } + < > <= >= == != === !== + << >> <<= >>= >>> >>>= + + - += -= + * / % *= /= %= + & | ^ &= |= ^= + = ! ~ + ++ -- + . -> : , + ? && || + */ + +enum TOK +{ + TOKreserved, + + // Other + TOKlparen, TOKrparen, + TOKlbracket, TOKrbracket, + TOKlcurly, TOKrcurly, + TOKcolon, TOKneg, + TOKsemicolon, TOKdotdotdot, + TOKeof, TOKcast, + TOKnull, TOKassert, + TOKtrue, TOKfalse, + TOKarray, TOKcall, + TOKaddress, TOKtypedot, + TOKtype, TOKthrow, + TOKnew, TOKdelete, + TOKstar, TOKsymoff, + TOKvar, TOKdotvar, + TOKdotti, TOKdotexp, + TOKdottype, TOKslice, + TOKarraylength, TOKversion, + TOKmodule, TOKdollar, + TOKtemplate, TOKdottd, + TOKdeclaration, TOKtypeof, + TOKpragma, TOKdsymbol, + TOKtypeid, TOKuadd, + TOKremove, + TOKnewanonclass, TOKcomment, + TOKarrayliteral, TOKassocarrayliteral, + TOKstructliteral, + + // Operators + TOKlt, TOKgt, + TOKle, TOKge, + TOKequal, TOKnotequal, + TOKidentity, TOKnotidentity, + TOKindex, TOKis, + TOKtobool, + +// 60 + // NCEG floating point compares + // !<>= <> <>= !> !>= !< !<= !<> + TOKunord,TOKlg,TOKleg,TOKule,TOKul,TOKuge,TOKug,TOKue, + + TOKshl, TOKshr, + TOKshlass, TOKshrass, + TOKushr, TOKushrass, + TOKcat, TOKcatass, // ~ ~= + TOKadd, TOKmin, TOKaddass, TOKminass, + TOKmul, TOKdiv, TOKmod, + TOKmulass, TOKdivass, TOKmodass, + TOKand, TOKor, TOKxor, + TOKandass, TOKorass, TOKxorass, + TOKassign, TOKnot, TOKtilde, + TOKplusplus, TOKminusminus, TOKconstruct, TOKblit, + TOKdot, TOKarrow, TOKcomma, + TOKquestion, TOKandand, TOKoror, + +// 104 + // Numeric literals + TOKint32v, TOKuns32v, + TOKint64v, TOKuns64v, + TOKfloat32v, TOKfloat64v, TOKfloat80v, + TOKimaginary32v, TOKimaginary64v, TOKimaginary80v, + + // Char constants + TOKcharv, TOKwcharv, TOKdcharv, + + // Leaf operators + TOKidentifier, TOKstring, + TOKthis, TOKsuper, + TOKhalt, TOKtuple, + + // Basic types + TOKvoid, + TOKint8, TOKuns8, + TOKint16, TOKuns16, + TOKint32, TOKuns32, + TOKint64, TOKuns64, + TOKfloat32, TOKfloat64, TOKfloat80, + TOKimaginary32, TOKimaginary64, TOKimaginary80, + TOKcomplex32, TOKcomplex64, TOKcomplex80, + TOKchar, TOKwchar, TOKdchar, TOKbit, TOKbool, + TOKcent, TOKucent, + + // Aggregates + TOKstruct, TOKclass, TOKinterface, TOKunion, TOKenum, TOKimport, + TOKtypedef, TOKalias, TOKoverride, TOKdelegate, TOKfunction, + TOKmixin, + + TOKalign, TOKextern, TOKprivate, TOKprotected, TOKpublic, TOKexport, + TOKstatic, /*TOKvirtual,*/ TOKfinal, TOKconst, TOKabstract, TOKvolatile, + TOKdebug, TOKdeprecated, TOKin, TOKout, TOKinout, TOKlazy, + TOKauto, TOKpackage, TOKmanifest, + + // Statements + TOKif, TOKelse, TOKwhile, TOKfor, TOKdo, TOKswitch, + TOKcase, TOKdefault, TOKbreak, TOKcontinue, TOKwith, + TOKsynchronized, TOKreturn, TOKgoto, TOKtry, TOKcatch, TOKfinally, + TOKasm, TOKforeach, TOKforeach_reverse, + TOKscope, + TOKon_scope_exit, TOKon_scope_failure, TOKon_scope_success, + + // Contracts + TOKbody, TOKinvariant, + + // Testing + TOKunittest, + + // Added after 1.0 + TOKref, + TOKmacro, +#if DMDV2 + TOKtraits, + TOKoverloadset, + TOKpure, + TOKnothrow, + TOKtls, + TOKline, + TOKfile, + TOKshared, +#endif + +// LDC specific +#if IN_LLVM + TOKgep, +#endif + + TOKMAX +}; + +#define CASE_BASIC_TYPES \ + case TOKwchar: case TOKdchar: \ + case TOKbit: case TOKbool: case TOKchar: \ + case TOKint8: case TOKuns8: \ + case TOKint16: case TOKuns16: \ + case TOKint32: case TOKuns32: \ + case TOKint64: case TOKuns64: \ + case TOKfloat32: case TOKfloat64: case TOKfloat80: \ + case TOKimaginary32: case TOKimaginary64: case TOKimaginary80: \ + case TOKcomplex32: case TOKcomplex64: case TOKcomplex80: \ + case TOKvoid + +#define CASE_BASIC_TYPES_X(t) \ + case TOKvoid: t = Type::tvoid; goto LabelX; \ + case TOKint8: t = Type::tint8; goto LabelX; \ + case TOKuns8: t = Type::tuns8; goto LabelX; \ + case TOKint16: t = Type::tint16; goto LabelX; \ + case TOKuns16: t = Type::tuns16; goto LabelX; \ + case TOKint32: t = Type::tint32; goto LabelX; \ + case TOKuns32: t = Type::tuns32; goto LabelX; \ + case TOKint64: t = Type::tint64; goto LabelX; \ + case TOKuns64: t = Type::tuns64; goto LabelX; \ + case TOKfloat32: t = Type::tfloat32; goto LabelX; \ + case TOKfloat64: t = Type::tfloat64; goto LabelX; \ + case TOKfloat80: t = Type::tfloat80; goto LabelX; \ + case TOKimaginary32: t = Type::timaginary32; goto LabelX; \ + case TOKimaginary64: t = Type::timaginary64; goto LabelX; \ + case TOKimaginary80: t = Type::timaginary80; goto LabelX; \ + case TOKcomplex32: t = Type::tcomplex32; goto LabelX; \ + case TOKcomplex64: t = Type::tcomplex64; goto LabelX; \ + case TOKcomplex80: t = Type::tcomplex80; goto LabelX; \ + case TOKbit: t = Type::tbit; goto LabelX; \ + case TOKbool: t = Type::tbool; goto LabelX; \ + case TOKchar: t = Type::tchar; goto LabelX; \ + case TOKwchar: t = Type::twchar; goto LabelX; \ + case TOKdchar: t = Type::tdchar; goto LabelX; \ + LabelX + +struct Token +{ + Token *next; + unsigned char *ptr; // pointer to first character of this token within buffer + enum TOK value; + unsigned char *blockComment; // doc comment string prior to this token + unsigned char *lineComment; // doc comment for previous token + union + { + // Integers + d_int64 int64value; + d_uns64 uns64value; + + // Floats +#ifdef IN_GCC + // real_t float80value; // can't use this in a union! +#else + d_float80 float80value; +#endif + + struct + { unsigned char *ustring; // UTF8 string + unsigned len; + unsigned char postfix; // 'c', 'w', 'd' + }; + + Identifier *ident; + }; +#ifdef IN_GCC + real_t float80value; // can't use this in a union! +#endif + + static const char *tochars[TOKMAX]; + static void *operator new(size_t sz); + + int isKeyword(); + void print(); + const char *toChars(); + static const char *toChars(enum TOK); +}; + +struct Lexer +{ + static StringTable stringtable; + static OutBuffer stringbuffer; + static Token *freelist; + + Loc loc; // for error messages + + unsigned char *base; // pointer to start of buffer + unsigned char *end; // past end of buffer + unsigned char *p; // current character + Token token; + Module *mod; + int doDocComment; // collect doc comment information + int anyToken; // !=0 means seen at least one token + int commentToken; // !=0 means comments are TOKcomment's + + Lexer(Module *mod, + unsigned char *base, unsigned begoffset, unsigned endoffset, + int doDocComment, int commentToken); + + static void initKeywords(); + static Identifier *idPool(const char *s); + static Identifier *uniqueId(const char *s); + static Identifier *uniqueId(const char *s, int num); + + TOK nextToken(); + TOK peekNext(); + void scan(Token *t); + Token *peek(Token *t); + Token *peekPastParen(Token *t); + unsigned escapeSequence(); + TOK wysiwygStringConstant(Token *t, int tc); + TOK hexStringConstant(Token *t); +#if DMDV2 + 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); + unsigned wchar(unsigned u); + TOK number(Token *t); + TOK inreal(Token *t); + void error(const char *format, ...); + void error(Loc loc, const char *format, ...); + void pragma(); + unsigned decodeUTF(); + void getDocComment(Token *t, unsigned lineComment); + + static int isValidIdentifier(char *p); + static unsigned char *combineComments(unsigned char *c1, unsigned char *c2); +}; + +#endif /* DMD_LEXER_H */ diff -r 1853dcd9b944 -r e961851fb8be dmd/mangle.c --- a/dmd/mangle.c Fri Apr 03 17:02:52 2009 +0200 +++ b/dmd/mangle.c Fri Apr 03 17:59:34 2009 +0200 @@ -117,7 +117,7 @@ return ident->toChars(); case LINKcpp: -#if V2 && (TARGET_LINUX || TARGET_OSX) +#if DMDV2 && (TARGET_LINUX || TARGET_OSX) return cpp_mangle(this); #else // Windows C++ mangling is done by C++ back end diff -r 1853dcd9b944 -r e961851fb8be dmd/mars.c --- a/dmd/mars.c Fri Apr 03 17:02:52 2009 +0200 +++ b/dmd/mars.c Fri Apr 03 17:59:34 2009 +0200 @@ -1,3 +1,4 @@ + // Compiler implementation of the D programming language // Copyright (c) 1999-2009 by Digital Mars // All Rights Reserved @@ -15,10 +16,6 @@ #include #include -#if __DMC__ -#include -#endif - #if POSIX #include #elif _WIN32 @@ -59,7 +56,7 @@ copyright = "Copyright (c) 1999-2009 by Digital Mars and Tomas Lindquist Olsen"; written = "written by Walter Bright and Tomas Lindquist Olsen"; - version = "v1.041"; + version = "v1.042"; ldc_version = LDC_REV; llvm_version = LLVM_REV_STR; global.structalign = 8; diff -r 1853dcd9b944 -r e961851fb8be dmd/mars.h --- a/dmd/mars.h Fri Apr 03 17:02:52 2009 +0200 +++ b/dmd/mars.h Fri Apr 03 17:59:34 2009 +0200 @@ -57,6 +57,7 @@ */ +#include #include #include #include @@ -77,7 +78,8 @@ #define DMDV2 0 // Version 2.0 features #define BREAKABI 1 // 0 if not ready to break the ABI just yet -#define STRUCTTHISREF V2 // if 'this' for struct is a reference, not a pointer +#define STRUCTTHISREF DMDV2 // if 'this' for struct is a reference, not a pointer +#define SNAN_DEFAULT_INIT DMDV2 // if floats are default initialized to signalling NaN /* Other targets are TARGET_LINUX and TARGET_OSX, which are * set on the command line via the compiler makefile. @@ -261,11 +263,6 @@ #define WINDOWS_SEH (_WIN32 && __DMC__) -#if __GNUC__ -//#define memicmp strncasecmp -//#define stricmp strcasecmp -#endif - #ifdef __DMC__ typedef _Complex long double complex_t; #else @@ -274,12 +271,13 @@ #endif #ifdef __APPLE__ //#include "complex.h"//This causes problems with include the c++ and not the C "complex.h" - #define integer_t dmd_integer_t #endif #endif -// Be careful not to care about sign when using integer_t -typedef uint64_t integer_t; +// Be careful not to care about sign when using dinteger_t +//typedef uint64_t integer_t; +typedef uint64_t dinteger_t; // use this instead of integer_t to + // avoid conflicts with system #include's // Signed and unsigned variants typedef int64_t sinteger_t; diff -r 1853dcd9b944 -r e961851fb8be dmd/module.c --- a/dmd/module.c Fri Apr 03 17:02:52 2009 +0200 +++ b/dmd/module.c Fri Apr 03 17:59:34 2009 +0200 @@ -1,6 +1,6 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2007 by Digital Mars +// Copyright (c) 1999-2009 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com diff -r 1853dcd9b944 -r e961851fb8be dmd/mtype.c --- a/dmd/mtype.c Fri Apr 03 17:02:52 2009 +0200 +++ b/dmd/mtype.c Fri Apr 03 17:59:34 2009 +0200 @@ -25,10 +25,6 @@ #include #include -#ifdef __DMC__ -#include -#endif - #if _MSC_VER #include #include @@ -37,19 +33,10 @@ #include #elif __MINGW32__ #include -#else -//#define signbit 56 #endif -#if __GNUC__ -#if !(defined (__SVR4) && defined (__sun)) -#include -#include -#endif -#endif -static double zero = 0; - #include "rmem.h" +#include "port.h" #include "dsymbol.h" #include "mtype.h" @@ -85,15 +72,18 @@ */ int PTRSIZE = 4; -#if IN_LLVM -int REALSIZE = 8; -int REALPAD = 0; -#elif TARGET_LINUX +#if TARGET_OSX +int REALSIZE = 16; +int REALPAD = 6; +int REALALIGNSIZE = 16; +#elif TARGET_LINUX || TARGET_FREEBSD int REALSIZE = 12; int REALPAD = 2; +int REALALIGNSIZE = 4; #else int REALSIZE = 10; int REALPAD = 0; +int REALALIGNSIZE = 2; #endif int Tsize_t = Tuns32; int Tptrdiff_t = Tint32; @@ -1119,24 +1109,7 @@ case Tfloat64: case Tfloat80: { -#if IN_GCC - // mode doesn't matter, will be converted in RealExp anyway - fvalue = real_t::getnan(real_t::LongDouble); -#elif __GNUC__ - // gcc nan's have the sign bit set by default, so turn it off - // Need the volatile to prevent gcc from doing incorrect - // constant folding. - volatile d_float80 foo; - foo = NAN; - if (std::signbit(foo)) // signbit sometimes, not always, set - foo = -foo; // turn off sign bit - fvalue = foo; -#elif _MSC_VER - unsigned long nan[2]= { 0xFFFFFFFF, 0x7FFFFFFF }; - fvalue = *(double*)nan; -#else - fvalue = NAN; -#endif + fvalue = Port::nan; goto Lfvalue; } } @@ -1154,15 +1127,7 @@ case Tfloat32: case Tfloat64: case Tfloat80: -#if IN_GCC - fvalue = real_t::getinfinity(); -#elif __GNUC__ - fvalue = 1 / zero; -#elif _MSC_VER - fvalue = std::numeric_limits::infinity(); -#else - fvalue = INFINITY; -#endif + fvalue = Port::infinity; goto Lfvalue; } } @@ -1378,7 +1343,7 @@ } Expression *TypeBasic::defaultInit(Loc loc) -{ integer_t value = 0; +{ dinteger_t value = 0; #if LOGDEFAULTINIT printf("TypeBasic::defaultInit() '%s'\n", toChars()); @@ -1735,7 +1700,7 @@ } d_uns64 TypeSArray::size(Loc loc) -{ integer_t sz; +{ dinteger_t sz; if (!dim) return Type::size(loc); @@ -1747,7 +1712,7 @@ sz = ((sz + 31) & ~31) / 8; // size in bytes, rounded up to 32 bit dwords } else - { integer_t n, n2; + { dinteger_t n, n2; n = next->size(); n2 = n * sz; @@ -1896,7 +1861,7 @@ Type *tbn = next->toBasetype(); if (dim) - { integer_t n, n2; + { dinteger_t n, n2; dim = semanticLength(sc, tbn, dim); @@ -1909,10 +1874,10 @@ */ return this; } - integer_t d1 = dim->toInteger(); + dinteger_t d1 = dim->toInteger(); dim = dim->castTo(sc, tsize_t); dim = dim->optimize(WANTvalue); - integer_t d2 = dim->toInteger(); + dinteger_t d2 = dim->toInteger(); if (d1 != d2) goto Loverflow; @@ -3052,7 +3017,7 @@ if (varargs == 2 && u + 1 == nparams) // if last varargs param { Type *tb = p->type->toBasetype(); TypeSArray *tsa; - integer_t sz; + dinteger_t sz; switch (tb->ty) { diff -r 1853dcd9b944 -r e961851fb8be dmd/opover.c --- a/dmd/opover.c Fri Apr 03 17:02:52 2009 +0200 +++ b/dmd/opover.c Fri Apr 03 17:59:34 2009 +0200 @@ -18,10 +18,6 @@ #include #endif -#ifdef __APPLE__ -#define integer_t dmd_integer_t -#endif - #include "rmem.h" //#include "port.h" diff -r 1853dcd9b944 -r e961851fb8be dmd/optimize.c --- a/dmd/optimize.c Fri Apr 03 17:02:52 2009 +0200 +++ b/dmd/optimize.c Fri Apr 03 17:59:34 2009 +0200 @@ -1,791 +1,791 @@ - -// Compiler implementation of the D programming language -// Copyright (c) 1999-2007 by Digital Mars -// All Rights Reserved -// written by Walter Bright -// 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. - -#include -#include -#include -#include - -#if __DMC__ -#include -#endif - -#include "lexer.h" -#include "mtype.h" -#include "expression.h" -#include "declaration.h" -#include "aggregate.h" -#include "init.h" - - -#ifdef IN_GCC -#include "d-gcc-real.h" - -/* %% fix? */ -extern "C" bool real_isnan (const real_t *); -#endif - -static real_t zero; // work around DMC bug for now - - -/************************************* - * If expression is a variable with a const initializer, - * return that initializer. - */ - -Expression *fromConstInitializer(Expression *e1) -{ - //printf("fromConstInitializer(%s)\n", e1->toChars()); - if (e1->op == TOKvar) - { VarExp *ve = (VarExp *)e1; - VarDeclaration *v = ve->var->isVarDeclaration(); - if (v && v->isConst() && v->init) - { Expression *ei = v->init->toExpression(); - if (ei && ei->type) - e1 = ei; - } - } - return e1; -} - - -Expression *Expression::optimize(int result) -{ - //printf("Expression::optimize(result = x%x) %s\n", result, toChars()); - return this; -} - -Expression *VarExp::optimize(int result) -{ - if (result & WANTinterpret) - { - return fromConstInitializer(this); - } - return this; -} - -Expression *TupleExp::optimize(int result) -{ - for (size_t i = 0; i < exps->dim; i++) - { Expression *e = (Expression *)exps->data[i]; - - e = e->optimize(WANTvalue | (result & WANTinterpret)); - exps->data[i] = (void *)e; - } - return this; -} - -Expression *ArrayLiteralExp::optimize(int result) -{ - if (elements) - { - for (size_t i = 0; i < elements->dim; i++) - { Expression *e = (Expression *)elements->data[i]; - - e = e->optimize(WANTvalue | (result & WANTinterpret)); - elements->data[i] = (void *)e; - } - } - return this; -} - -Expression *AssocArrayLiteralExp::optimize(int result) -{ - assert(keys->dim == values->dim); - for (size_t i = 0; i < keys->dim; i++) - { Expression *e = (Expression *)keys->data[i]; - - e = e->optimize(WANTvalue | (result & WANTinterpret)); - keys->data[i] = (void *)e; - - e = (Expression *)values->data[i]; - e = e->optimize(WANTvalue | (result & WANTinterpret)); - values->data[i] = (void *)e; - } - return this; -} - -Expression *StructLiteralExp::optimize(int result) -{ - if (elements) - { - for (size_t i = 0; i < elements->dim; i++) - { Expression *e = (Expression *)elements->data[i]; - if (!e) - continue; - e = e->optimize(WANTvalue | (result & WANTinterpret)); - elements->data[i] = (void *)e; - } - } - return this; -} - -Expression *TypeExp::optimize(int result) -{ - return this; -} - -Expression *UnaExp::optimize(int result) -{ - e1 = e1->optimize(result); - return this; -} - -Expression *NegExp::optimize(int result) -{ Expression *e; - - e1 = e1->optimize(result); - if (e1->isConst() == 1) - { - e = Neg(type, e1); - } - else - e = this; - return e; -} - -Expression *ComExp::optimize(int result) -{ Expression *e; - - e1 = e1->optimize(result); - if (e1->isConst() == 1) - { - e = Com(type, e1); - } - else - e = this; - return e; -} - -Expression *NotExp::optimize(int result) -{ Expression *e; - - e1 = e1->optimize(result); - if (e1->isConst() == 1) - { - e = Not(type, e1); - } - else - e = this; - return e; -} - -Expression *BoolExp::optimize(int result) -{ Expression *e; - - e1 = e1->optimize(result); - if (e1->isConst() == 1) - { - e = Bool(type, e1); - } - else - e = this; - return e; -} - -Expression *AddrExp::optimize(int result) -{ Expression *e; - - //printf("AddrExp::optimize(result = %d) %s\n", result, toChars()); - e1 = e1->optimize(result); - // Convert &*ex to ex - if (e1->op == TOKstar) - { Expression *ex; - - ex = ((PtrExp *)e1)->e1; - if (type->equals(ex->type)) - e = ex; - else - { - e = ex->copy(); - e->type = type; - } - return e; - } -#if !IN_LLVM - if (e1->op == TOKvar) - { VarExp *ve = (VarExp *)e1; - if (!ve->var->isOut() && !ve->var->isRef() && - !ve->var->isImportedSymbol()) - { - e = new SymOffExp(loc, ve->var, 0); - e->type = type; - return e; - } - } - if (e1->op == TOKindex) - { // Convert &array[n] to &array+n - IndexExp *ae = (IndexExp *)e1; - - if (ae->e2->op == TOKint64 && ae->e1->op == TOKvar) - { - integer_t index = ae->e2->toInteger(); - VarExp *ve = (VarExp *)ae->e1; - if (ve->type->ty == Tsarray && ve->type->next->ty != Tbit - && !ve->var->isImportedSymbol()) - { - TypeSArray *ts = (TypeSArray *)ve->type; - integer_t dim = ts->dim->toInteger(); - if (index < 0 || index >= dim) - error("array index %jd is out of bounds [0..%jd]", index, dim); - e = new SymOffExp(loc, ve->var, index * ts->next->size()); - e->type = type; - return e; - } - } - } -#endif - return this; -} - -Expression *PtrExp::optimize(int result) -{ - //printf("PtrExp::optimize(result = x%x) %s\n", result, toChars()); - e1 = e1->optimize(result); - // Convert *&ex to ex - if (e1->op == TOKaddress) - { Expression *e; - Expression *ex; - - ex = ((AddrExp *)e1)->e1; - if (type->equals(ex->type)) - e = ex; - else - { - e = ex->copy(); - e->type = type; - } - return e; - } - // Constant fold *(&structliteral + offset) - if (e1->op == TOKadd) - { - Expression *e; - e = Ptr(type, e1); - if (e != EXP_CANT_INTERPRET) - return e; - } - - return this; -} - -Expression *DotVarExp::optimize(int result) -{ - //printf("DotVarExp::optimize(result = x%x) %s\n", result, toChars()); - e1 = e1->optimize(result); - -#if DMDV2 - if (e1->op == TOKvar) - { VarExp *ve = (VarExp *)e1; - VarDeclaration *v = ve->var->isVarDeclaration(); - Expression *e = expandVar(result, v); - if (e && e->op == TOKstructliteral) - { StructLiteralExp *sle = (StructLiteralExp *)e; - VarDeclaration *vf = var->isVarDeclaration(); - if (vf) - { - e = sle->getField(type, vf->offset); - if (e != EXP_CANT_INTERPRET) - return e; - } - } - } - else -#endif - if (e1->op == TOKstructliteral) - { StructLiteralExp *sle = (StructLiteralExp *)e1; - VarDeclaration *vf = var->isVarDeclaration(); - if (vf) - { - Expression *e = sle->getField(type, vf->offset); - if (e != EXP_CANT_INTERPRET) - return e; - } - } - - return this; -} - -Expression *CallExp::optimize(int result) -{ Expression *e = this; - - e1 = e1->optimize(result); - if (e1->op == TOKvar && result & WANTinterpret) - { - FuncDeclaration *fd = ((VarExp *)e1)->var->isFuncDeclaration(); - if (fd) - { - Expression *eresult = fd->interpret(NULL, arguments); - if (eresult && eresult != EXP_VOID_INTERPRET) - e = eresult; - else if (result & WANTinterpret) - error("cannot evaluate %s at compile time", toChars()); - } - } - return e; -} - - -Expression *CastExp::optimize(int result) -{ - //printf("CastExp::optimize(result = %d) %s\n", result, toChars()); - //printf("from %s to %s\n", type->toChars(), to->toChars()); - //printf("from %s\n", type->toChars()); - //printf("e1->type %s\n", e1->type->toChars()); - //printf("type = %p\n", type); - assert(type); - enum TOK op1 = e1->op; - - e1 = e1->optimize(result); - if (result & WANTinterpret) - e1 = fromConstInitializer(e1); - - if ((e1->op == TOKstring || e1->op == TOKarrayliteral) && - (type->ty == Tpointer || type->ty == Tarray) && - type->next->equals(e1->type->next) - ) - { - // make a copy before adjusting type to avoid - // messing up the type of an existing initializer - e1 = e1->syntaxCopy(); - e1->type = type; - return e1; - } - /* The first test here is to prevent infinite loops - */ - if (op1 != TOKarrayliteral && e1->op == TOKarrayliteral) - return e1->castTo(NULL, to); - if (e1->op == TOKnull && - (type->ty == Tpointer || type->ty == Tclass)) - { - e1->type = type; - return e1; - } - - if (result & WANTflags && type->ty == Tclass && e1->type->ty == Tclass) - { - // See if we can remove an unnecessary cast - ClassDeclaration *cdfrom; - ClassDeclaration *cdto; - int offset; - - cdfrom = e1->type->isClassHandle(); - cdto = type->isClassHandle(); - if (cdto->isBaseOf(cdfrom, &offset) && offset == 0) - { - e1->type = type; - return e1; - } - } - - Expression *e; - - if (e1->isConst()) - { - if (e1->op == TOKsymoff) - { - if (type->size() == e1->type->size() && - type->toBasetype()->ty != Tsarray) - { - e1->type = type; - return e1; - } - return this; - } - if (to->toBasetype()->ty == Tvoid) - e = this; - else - e = Cast(type, to, e1); - } - else - e = this; - return e; -} - -Expression *BinExp::optimize(int result) -{ - //printf("BinExp::optimize(result = %d) %s\n", result, toChars()); - e1 = e1->optimize(result); - e2 = e2->optimize(result); - if (op == TOKshlass || op == TOKshrass || op == TOKushrass) - { - if (e2->isConst() == 1) - { - integer_t i2 = e2->toInteger(); - d_uns64 sz = e1->type->size() * 8; - if (i2 < 0 || i2 > sz) - { error("shift assign by %jd is outside the range 0..%zu", i2, sz); - e2 = new IntegerExp(0); - } - } - } - return this; -} - -Expression *AddExp::optimize(int result) -{ Expression *e; - - //printf("AddExp::optimize(%s)\n", toChars()); - e1 = e1->optimize(result); - e2 = e2->optimize(result); - if (e1->isConst() && e2->isConst()) - { - if (e1->op == TOKsymoff && e2->op == TOKsymoff) - return this; - e = Add(type, e1, e2); - } - else - e = this; - return e; -} - -Expression *MinExp::optimize(int result) -{ Expression *e; - - e1 = e1->optimize(result); - e2 = e2->optimize(result); - if (e1->isConst() && e2->isConst()) - { - if (e2->op == TOKsymoff) - return this; - e = Min(type, e1, e2); - } - else - e = this; - return e; -} - -Expression *MulExp::optimize(int result) -{ Expression *e; - - //printf("MulExp::optimize(result = %d) %s\n", result, toChars()); - e1 = e1->optimize(result); - e2 = e2->optimize(result); - if (e1->isConst() == 1 && e2->isConst() == 1) - { - e = Mul(type, e1, e2); - } - else - e = this; - return e; -} - -Expression *DivExp::optimize(int result) -{ Expression *e; - - //printf("DivExp::optimize(%s)\n", toChars()); - e1 = e1->optimize(result); - e2 = e2->optimize(result); - if (e1->isConst() == 1 && e2->isConst() == 1) - { - e = Div(type, e1, e2); - } - else - e = this; - return e; -} - -Expression *ModExp::optimize(int result) -{ Expression *e; - - e1 = e1->optimize(result); - e2 = e2->optimize(result); - if (e1->isConst() == 1 && e2->isConst() == 1) - { - e = Mod(type, e1, e2); - } - else - e = this; - return e; -} - -Expression *shift_optimize(int result, BinExp *e, Expression *(*shift)(Type *, Expression *, Expression *)) -{ Expression *ex = e; - - e->e1 = e->e1->optimize(result); - e->e2 = e->e2->optimize(result); - if (e->e2->isConst() == 1) - { - integer_t i2 = e->e2->toInteger(); - d_uns64 sz = e->e1->type->size() * 8; - if (i2 < 0 || i2 > sz) - { e->error("shift by %jd is outside the range 0..%zu", i2, sz); - e->e2 = new IntegerExp(0); - } - if (e->e1->isConst() == 1) - ex = (*shift)(e->type, e->e1, e->e2); - } - return ex; -} - -Expression *ShlExp::optimize(int result) -{ - //printf("ShlExp::optimize(result = %d) %s\n", result, toChars()); - return shift_optimize(result, this, Shl); -} - -Expression *ShrExp::optimize(int result) -{ - //printf("ShrExp::optimize(result = %d) %s\n", result, toChars()); - return shift_optimize(result, this, Shr); -} - -Expression *UshrExp::optimize(int result) -{ - //printf("UshrExp::optimize(result = %d) %s\n", result, toChars()); - return shift_optimize(result, this, Ushr); -} - -Expression *AndExp::optimize(int result) -{ Expression *e; - - e1 = e1->optimize(result); - e2 = e2->optimize(result); - if (e1->isConst() == 1 && e2->isConst() == 1) - e = And(type, e1, e2); - else - e = this; - return e; -} - -Expression *OrExp::optimize(int result) -{ Expression *e; - - e1 = e1->optimize(result); - e2 = e2->optimize(result); - if (e1->isConst() == 1 && e2->isConst() == 1) - e = Or(type, e1, e2); - else - e = this; - return e; -} - -Expression *XorExp::optimize(int result) -{ Expression *e; - - e1 = e1->optimize(result); - e2 = e2->optimize(result); - if (e1->isConst() == 1 && e2->isConst() == 1) - e = Xor(type, e1, e2); - else - e = this; - return e; -} - -Expression *CommaExp::optimize(int result) -{ Expression *e; - - //printf("CommaExp::optimize(result = %d) %s\n", result, toChars()); - e1 = e1->optimize(result & WANTinterpret); - e2 = e2->optimize(result); - if (!e1 || e1->op == TOKint64 || e1->op == TOKfloat64 || !e1->checkSideEffect(2)) - { - e = e2; - if (e) - e->type = type; - } - else - e = this; - //printf("-CommaExp::optimize(result = %d) %s\n", result, e->toChars()); - return e; -} - -Expression *ArrayLengthExp::optimize(int result) -{ Expression *e; - - //printf("ArrayLengthExp::optimize(result = %d) %s\n", result, toChars()); - e1 = e1->optimize(WANTvalue | (result & WANTinterpret)); - e = this; - if (e1->op == TOKstring || e1->op == TOKarrayliteral || e1->op == TOKassocarrayliteral) - { - e = ArrayLength(type, e1); - } - return e; -} - -Expression *EqualExp::optimize(int result) -{ Expression *e; - - //printf("EqualExp::optimize(result = %x) %s\n", result, toChars()); - e1 = e1->optimize(WANTvalue | (result & WANTinterpret)); - e2 = e2->optimize(WANTvalue | (result & WANTinterpret)); - e = this; - - Expression *e1 = fromConstInitializer(this->e1); - Expression *e2 = fromConstInitializer(this->e2); - - e = Equal(op, type, e1, e2); - if (e == EXP_CANT_INTERPRET) - e = this; - return e; -} - -Expression *IdentityExp::optimize(int result) -{ Expression *e; - - //printf("IdentityExp::optimize(result = %d) %s\n", result, toChars()); - e1 = e1->optimize(WANTvalue | (result & WANTinterpret)); - e2 = e2->optimize(WANTvalue | (result & WANTinterpret)); - e = this; - - if (this->e1->isConst() && this->e2->isConst()) - { - e = Identity(op, type, this->e1, this->e2); - } - return e; -} - -Expression *IndexExp::optimize(int result) -{ Expression *e; - - //printf("IndexExp::optimize(result = %d) %s\n", result, toChars()); - Expression *e1 = this->e1->optimize(WANTvalue | (result & WANTinterpret)); - if (result & WANTinterpret) - e1 = fromConstInitializer(e1); - e2 = e2->optimize(WANTvalue | (result & WANTinterpret)); - e = Index(type, e1, e2); - if (e == EXP_CANT_INTERPRET) - e = this; - return e; -} - -Expression *SliceExp::optimize(int result) -{ Expression *e; - - //printf("SliceExp::optimize(result = %d) %s\n", result, toChars()); - e = this; - e1 = e1->optimize(WANTvalue | (result & WANTinterpret)); - if (!lwr) - { if (e1->op == TOKstring) - { // Convert slice of string literal into dynamic array - Type *t = e1->type->toBasetype(); - if (t->next) - e = e1->castTo(NULL, t->next->arrayOf()); - } - return e; - } - if (result & WANTinterpret) - e1 = fromConstInitializer(e1); - lwr = lwr->optimize(WANTvalue | (result & WANTinterpret)); - upr = upr->optimize(WANTvalue | (result & WANTinterpret)); - e = Slice(type, e1, lwr, upr); - if (e == EXP_CANT_INTERPRET) - e = this; - return e; -} - -Expression *AndAndExp::optimize(int result) -{ Expression *e; - - //printf("AndAndExp::optimize(%d) %s\n", result, toChars()); - e1 = e1->optimize(WANTflags | (result & WANTinterpret)); - e = this; - if (e1->isBool(FALSE)) - { - e = new CommaExp(loc, e1, new IntegerExp(loc, 0, type)); - e->type = type; - e = e->optimize(result); - } - else - { - e2 = e2->optimize(WANTflags | (result & WANTinterpret)); - if (result && e2->type->toBasetype()->ty == Tvoid && !global.errors) - error("void has no value"); - if (e1->isConst()) - { - if (e2->isConst()) - { int n1 = e1->isBool(1); - int n2 = e2->isBool(1); - - e = new IntegerExp(loc, n1 && n2, type); - } - else if (e1->isBool(TRUE)) - e = new BoolExp(loc, e2, type); - } - } - return e; -} - -Expression *OrOrExp::optimize(int result) -{ Expression *e; - - e1 = e1->optimize(WANTflags | (result & WANTinterpret)); - e = this; - if (e1->isBool(TRUE)) - { // Replace with (e1, 1) - e = new CommaExp(loc, e1, new IntegerExp(loc, 1, type)); - e->type = type; - e = e->optimize(result); - } - else - { - e2 = e2->optimize(WANTflags | (result & WANTinterpret)); - if (result && e2->type->toBasetype()->ty == Tvoid && !global.errors) - error("void has no value"); - if (e1->isConst()) - { - if (e2->isConst()) - { int n1 = e1->isBool(1); - int n2 = e2->isBool(1); - - e = new IntegerExp(loc, n1 || n2, type); - } - else if (e1->isBool(FALSE)) - e = new BoolExp(loc, e2, type); - } - } - return e; -} - -Expression *CmpExp::optimize(int result) -{ Expression *e; - - //printf("CmpExp::optimize() %s\n", toChars()); - e1 = e1->optimize(result); - e2 = e2->optimize(result); - if (e1->isConst() == 1 && e2->isConst() == 1) - { - e = Cmp(op, type, this->e1, this->e2); - } - else - e = this; - return e; -} - -Expression *CatExp::optimize(int result) -{ Expression *e; - - //printf("CatExp::optimize(%d) %s\n", result, toChars()); - e1 = e1->optimize(result); - e2 = e2->optimize(result); - e = Cat(type, e1, e2); - if (e == EXP_CANT_INTERPRET) - e = this; - return e; -} - - -Expression *CondExp::optimize(int result) -{ Expression *e; - - econd = econd->optimize(WANTflags | (result & WANTinterpret)); - if (econd->isBool(TRUE)) - e = e1->optimize(result); - else if (econd->isBool(FALSE)) - e = e2->optimize(result); - else - { e1 = e1->optimize(result); - e2 = e2->optimize(result); - e = this; - } - return e; -} - - + +// Compiler implementation of the D programming language +// Copyright (c) 1999-2009 by Digital Mars +// All Rights Reserved +// written by Walter Bright +// 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. + +#include +#include +#include +#include + +#if __DMC__ +#include +#endif + +#include "lexer.h" +#include "mtype.h" +#include "expression.h" +#include "declaration.h" +#include "aggregate.h" +#include "init.h" + + +#ifdef IN_GCC +#include "d-gcc-real.h" + +/* %% fix? */ +extern "C" bool real_isnan (const real_t *); +#endif + +static real_t zero; // work around DMC bug for now + + +/************************************* + * If expression is a variable with a const initializer, + * return that initializer. + */ + +Expression *fromConstInitializer(Expression *e1) +{ + //printf("fromConstInitializer(%s)\n", e1->toChars()); + if (e1->op == TOKvar) + { VarExp *ve = (VarExp *)e1; + VarDeclaration *v = ve->var->isVarDeclaration(); + if (v && v->isConst() && v->init) + { Expression *ei = v->init->toExpression(); + if (ei && ei->type) + e1 = ei; + } + } + return e1; +} + + +Expression *Expression::optimize(int result) +{ + //printf("Expression::optimize(result = x%x) %s\n", result, toChars()); + return this; +} + +Expression *VarExp::optimize(int result) +{ + if (result & WANTinterpret) + { + return fromConstInitializer(this); + } + return this; +} + +Expression *TupleExp::optimize(int result) +{ + for (size_t i = 0; i < exps->dim; i++) + { Expression *e = (Expression *)exps->data[i]; + + e = e->optimize(WANTvalue | (result & WANTinterpret)); + exps->data[i] = (void *)e; + } + return this; +} + +Expression *ArrayLiteralExp::optimize(int result) +{ + if (elements) + { + for (size_t i = 0; i < elements->dim; i++) + { Expression *e = (Expression *)elements->data[i]; + + e = e->optimize(WANTvalue | (result & WANTinterpret)); + elements->data[i] = (void *)e; + } + } + return this; +} + +Expression *AssocArrayLiteralExp::optimize(int result) +{ + assert(keys->dim == values->dim); + for (size_t i = 0; i < keys->dim; i++) + { Expression *e = (Expression *)keys->data[i]; + + e = e->optimize(WANTvalue | (result & WANTinterpret)); + keys->data[i] = (void *)e; + + e = (Expression *)values->data[i]; + e = e->optimize(WANTvalue | (result & WANTinterpret)); + values->data[i] = (void *)e; + } + return this; +} + +Expression *StructLiteralExp::optimize(int result) +{ + if (elements) + { + for (size_t i = 0; i < elements->dim; i++) + { Expression *e = (Expression *)elements->data[i]; + if (!e) + continue; + e = e->optimize(WANTvalue | (result & WANTinterpret)); + elements->data[i] = (void *)e; + } + } + return this; +} + +Expression *TypeExp::optimize(int result) +{ + return this; +} + +Expression *UnaExp::optimize(int result) +{ + e1 = e1->optimize(result); + return this; +} + +Expression *NegExp::optimize(int result) +{ Expression *e; + + e1 = e1->optimize(result); + if (e1->isConst() == 1) + { + e = Neg(type, e1); + } + else + e = this; + return e; +} + +Expression *ComExp::optimize(int result) +{ Expression *e; + + e1 = e1->optimize(result); + if (e1->isConst() == 1) + { + e = Com(type, e1); + } + else + e = this; + return e; +} + +Expression *NotExp::optimize(int result) +{ Expression *e; + + e1 = e1->optimize(result); + if (e1->isConst() == 1) + { + e = Not(type, e1); + } + else + e = this; + return e; +} + +Expression *BoolExp::optimize(int result) +{ Expression *e; + + e1 = e1->optimize(result); + if (e1->isConst() == 1) + { + e = Bool(type, e1); + } + else + e = this; + return e; +} + +Expression *AddrExp::optimize(int result) +{ Expression *e; + + //printf("AddrExp::optimize(result = %d) %s\n", result, toChars()); + e1 = e1->optimize(result); + // Convert &*ex to ex + if (e1->op == TOKstar) + { Expression *ex; + + ex = ((PtrExp *)e1)->e1; + if (type->equals(ex->type)) + e = ex; + else + { + e = ex->copy(); + e->type = type; + } + return e; + } +#if !IN_LLVM + if (e1->op == TOKvar) + { VarExp *ve = (VarExp *)e1; + if (!ve->var->isOut() && !ve->var->isRef() && + !ve->var->isImportedSymbol()) + { + e = new SymOffExp(loc, ve->var, 0); + e->type = type; + return e; + } + } + if (e1->op == TOKindex) + { // Convert &array[n] to &array+n + IndexExp *ae = (IndexExp *)e1; + + if (ae->e2->op == TOKint64 && ae->e1->op == TOKvar) + { + dinteger_t index = ae->e2->toInteger(); + VarExp *ve = (VarExp *)ae->e1; + if (ve->type->ty == Tsarray && ve->type->next->ty != Tbit + && !ve->var->isImportedSymbol()) + { + TypeSArray *ts = (TypeSArray *)ve->type; + dinteger_t dim = ts->dim->toInteger(); + if (index < 0 || index >= dim) + error("array index %jd is out of bounds [0..%jd]", index, dim); + e = new SymOffExp(loc, ve->var, index * ts->next->size()); + e->type = type; + return e; + } + } + } +#endif + return this; +} + +Expression *PtrExp::optimize(int result) +{ + //printf("PtrExp::optimize(result = x%x) %s\n", result, toChars()); + e1 = e1->optimize(result); + // Convert *&ex to ex + if (e1->op == TOKaddress) + { Expression *e; + Expression *ex; + + ex = ((AddrExp *)e1)->e1; + if (type->equals(ex->type)) + e = ex; + else + { + e = ex->copy(); + e->type = type; + } + return e; + } + // Constant fold *(&structliteral + offset) + if (e1->op == TOKadd) + { + Expression *e; + e = Ptr(type, e1); + if (e != EXP_CANT_INTERPRET) + return e; + } + + return this; +} + +Expression *DotVarExp::optimize(int result) +{ + //printf("DotVarExp::optimize(result = x%x) %s\n", result, toChars()); + e1 = e1->optimize(result); + +#if DMDV2 + if (e1->op == TOKvar) + { VarExp *ve = (VarExp *)e1; + VarDeclaration *v = ve->var->isVarDeclaration(); + Expression *e = expandVar(result, v); + if (e && e->op == TOKstructliteral) + { StructLiteralExp *sle = (StructLiteralExp *)e; + VarDeclaration *vf = var->isVarDeclaration(); + if (vf) + { + e = sle->getField(type, vf->offset); + if (e != EXP_CANT_INTERPRET) + return e; + } + } + } + else +#endif + if (e1->op == TOKstructliteral) + { StructLiteralExp *sle = (StructLiteralExp *)e1; + VarDeclaration *vf = var->isVarDeclaration(); + if (vf) + { + Expression *e = sle->getField(type, vf->offset); + if (e != EXP_CANT_INTERPRET) + return e; + } + } + + return this; +} + +Expression *CallExp::optimize(int result) +{ Expression *e = this; + + e1 = e1->optimize(result); + if (e1->op == TOKvar && result & WANTinterpret) + { + FuncDeclaration *fd = ((VarExp *)e1)->var->isFuncDeclaration(); + if (fd) + { + Expression *eresult = fd->interpret(NULL, arguments); + if (eresult && eresult != EXP_VOID_INTERPRET) + e = eresult; + else if (result & WANTinterpret) + error("cannot evaluate %s at compile time", toChars()); + } + } + return e; +} + + +Expression *CastExp::optimize(int result) +{ + //printf("CastExp::optimize(result = %d) %s\n", result, toChars()); + //printf("from %s to %s\n", type->toChars(), to->toChars()); + //printf("from %s\n", type->toChars()); + //printf("e1->type %s\n", e1->type->toChars()); + //printf("type = %p\n", type); + assert(type); + enum TOK op1 = e1->op; + + e1 = e1->optimize(result); + if (result & WANTinterpret) + e1 = fromConstInitializer(e1); + + if ((e1->op == TOKstring || e1->op == TOKarrayliteral) && + (type->ty == Tpointer || type->ty == Tarray) && + type->next->equals(e1->type->next) + ) + { + // make a copy before adjusting type to avoid + // messing up the type of an existing initializer + e1 = e1->syntaxCopy(); + e1->type = type; + return e1; + } + /* The first test here is to prevent infinite loops + */ + if (op1 != TOKarrayliteral && e1->op == TOKarrayliteral) + return e1->castTo(NULL, to); + if (e1->op == TOKnull && + (type->ty == Tpointer || type->ty == Tclass)) + { + e1->type = type; + return e1; + } + + if (result & WANTflags && type->ty == Tclass && e1->type->ty == Tclass) + { + // See if we can remove an unnecessary cast + ClassDeclaration *cdfrom; + ClassDeclaration *cdto; + int offset; + + cdfrom = e1->type->isClassHandle(); + cdto = type->isClassHandle(); + if (cdto->isBaseOf(cdfrom, &offset) && offset == 0) + { + e1->type = type; + return e1; + } + } + + Expression *e; + + if (e1->isConst()) + { + if (e1->op == TOKsymoff) + { + if (type->size() == e1->type->size() && + type->toBasetype()->ty != Tsarray) + { + e1->type = type; + return e1; + } + return this; + } + if (to->toBasetype()->ty == Tvoid) + e = this; + else + e = Cast(type, to, e1); + } + else + e = this; + return e; +} + +Expression *BinExp::optimize(int result) +{ + //printf("BinExp::optimize(result = %d) %s\n", result, toChars()); + e1 = e1->optimize(result); + e2 = e2->optimize(result); + if (op == TOKshlass || op == TOKshrass || op == TOKushrass) + { + if (e2->isConst() == 1) + { + dinteger_t i2 = e2->toInteger(); + d_uns64 sz = e1->type->size() * 8; + if (i2 < 0 || i2 > sz) + { error("shift assign by %jd is outside the range 0..%zu", i2, sz); + e2 = new IntegerExp(0); + } + } + } + return this; +} + +Expression *AddExp::optimize(int result) +{ Expression *e; + + //printf("AddExp::optimize(%s)\n", toChars()); + e1 = e1->optimize(result); + e2 = e2->optimize(result); + if (e1->isConst() && e2->isConst()) + { + if (e1->op == TOKsymoff && e2->op == TOKsymoff) + return this; + e = Add(type, e1, e2); + } + else + e = this; + return e; +} + +Expression *MinExp::optimize(int result) +{ Expression *e; + + e1 = e1->optimize(result); + e2 = e2->optimize(result); + if (e1->isConst() && e2->isConst()) + { + if (e2->op == TOKsymoff) + return this; + e = Min(type, e1, e2); + } + else + e = this; + return e; +} + +Expression *MulExp::optimize(int result) +{ Expression *e; + + //printf("MulExp::optimize(result = %d) %s\n", result, toChars()); + e1 = e1->optimize(result); + e2 = e2->optimize(result); + if (e1->isConst() == 1 && e2->isConst() == 1) + { + e = Mul(type, e1, e2); + } + else + e = this; + return e; +} + +Expression *DivExp::optimize(int result) +{ Expression *e; + + //printf("DivExp::optimize(%s)\n", toChars()); + e1 = e1->optimize(result); + e2 = e2->optimize(result); + if (e1->isConst() == 1 && e2->isConst() == 1) + { + e = Div(type, e1, e2); + } + else + e = this; + return e; +} + +Expression *ModExp::optimize(int result) +{ Expression *e; + + e1 = e1->optimize(result); + e2 = e2->optimize(result); + if (e1->isConst() == 1 && e2->isConst() == 1) + { + e = Mod(type, e1, e2); + } + else + e = this; + return e; +} + +Expression *shift_optimize(int result, BinExp *e, Expression *(*shift)(Type *, Expression *, Expression *)) +{ Expression *ex = e; + + e->e1 = e->e1->optimize(result); + e->e2 = e->e2->optimize(result); + if (e->e2->isConst() == 1) + { + dinteger_t i2 = e->e2->toInteger(); + d_uns64 sz = e->e1->type->size() * 8; + if (i2 < 0 || i2 > sz) + { e->error("shift by %jd is outside the range 0..%zu", i2, sz); + e->e2 = new IntegerExp(0); + } + if (e->e1->isConst() == 1) + ex = (*shift)(e->type, e->e1, e->e2); + } + return ex; +} + +Expression *ShlExp::optimize(int result) +{ + //printf("ShlExp::optimize(result = %d) %s\n", result, toChars()); + return shift_optimize(result, this, Shl); +} + +Expression *ShrExp::optimize(int result) +{ + //printf("ShrExp::optimize(result = %d) %s\n", result, toChars()); + return shift_optimize(result, this, Shr); +} + +Expression *UshrExp::optimize(int result) +{ + //printf("UshrExp::optimize(result = %d) %s\n", result, toChars()); + return shift_optimize(result, this, Ushr); +} + +Expression *AndExp::optimize(int result) +{ Expression *e; + + e1 = e1->optimize(result); + e2 = e2->optimize(result); + if (e1->isConst() == 1 && e2->isConst() == 1) + e = And(type, e1, e2); + else + e = this; + return e; +} + +Expression *OrExp::optimize(int result) +{ Expression *e; + + e1 = e1->optimize(result); + e2 = e2->optimize(result); + if (e1->isConst() == 1 && e2->isConst() == 1) + e = Or(type, e1, e2); + else + e = this; + return e; +} + +Expression *XorExp::optimize(int result) +{ Expression *e; + + e1 = e1->optimize(result); + e2 = e2->optimize(result); + if (e1->isConst() == 1 && e2->isConst() == 1) + e = Xor(type, e1, e2); + else + e = this; + return e; +} + +Expression *CommaExp::optimize(int result) +{ Expression *e; + + //printf("CommaExp::optimize(result = %d) %s\n", result, toChars()); + e1 = e1->optimize(result & WANTinterpret); + e2 = e2->optimize(result); + if (!e1 || e1->op == TOKint64 || e1->op == TOKfloat64 || !e1->checkSideEffect(2)) + { + e = e2; + if (e) + e->type = type; + } + else + e = this; + //printf("-CommaExp::optimize(result = %d) %s\n", result, e->toChars()); + return e; +} + +Expression *ArrayLengthExp::optimize(int result) +{ Expression *e; + + //printf("ArrayLengthExp::optimize(result = %d) %s\n", result, toChars()); + e1 = e1->optimize(WANTvalue | (result & WANTinterpret)); + e = this; + if (e1->op == TOKstring || e1->op == TOKarrayliteral || e1->op == TOKassocarrayliteral) + { + e = ArrayLength(type, e1); + } + return e; +} + +Expression *EqualExp::optimize(int result) +{ Expression *e; + + //printf("EqualExp::optimize(result = %x) %s\n", result, toChars()); + e1 = e1->optimize(WANTvalue | (result & WANTinterpret)); + e2 = e2->optimize(WANTvalue | (result & WANTinterpret)); + e = this; + + Expression *e1 = fromConstInitializer(this->e1); + Expression *e2 = fromConstInitializer(this->e2); + + e = Equal(op, type, e1, e2); + if (e == EXP_CANT_INTERPRET) + e = this; + return e; +} + +Expression *IdentityExp::optimize(int result) +{ Expression *e; + + //printf("IdentityExp::optimize(result = %d) %s\n", result, toChars()); + e1 = e1->optimize(WANTvalue | (result & WANTinterpret)); + e2 = e2->optimize(WANTvalue | (result & WANTinterpret)); + e = this; + + if (this->e1->isConst() && this->e2->isConst()) + { + e = Identity(op, type, this->e1, this->e2); + } + return e; +} + +Expression *IndexExp::optimize(int result) +{ Expression *e; + + //printf("IndexExp::optimize(result = %d) %s\n", result, toChars()); + Expression *e1 = this->e1->optimize(WANTvalue | (result & WANTinterpret)); + if (result & WANTinterpret) + e1 = fromConstInitializer(e1); + e2 = e2->optimize(WANTvalue | (result & WANTinterpret)); + e = Index(type, e1, e2); + if (e == EXP_CANT_INTERPRET) + e = this; + return e; +} + +Expression *SliceExp::optimize(int result) +{ Expression *e; + + //printf("SliceExp::optimize(result = %d) %s\n", result, toChars()); + e = this; + e1 = e1->optimize(WANTvalue | (result & WANTinterpret)); + if (!lwr) + { if (e1->op == TOKstring) + { // Convert slice of string literal into dynamic array + Type *t = e1->type->toBasetype(); + if (t->next) + e = e1->castTo(NULL, t->next->arrayOf()); + } + return e; + } + if (result & WANTinterpret) + e1 = fromConstInitializer(e1); + lwr = lwr->optimize(WANTvalue | (result & WANTinterpret)); + upr = upr->optimize(WANTvalue | (result & WANTinterpret)); + e = Slice(type, e1, lwr, upr); + if (e == EXP_CANT_INTERPRET) + e = this; + return e; +} + +Expression *AndAndExp::optimize(int result) +{ Expression *e; + + //printf("AndAndExp::optimize(%d) %s\n", result, toChars()); + e1 = e1->optimize(WANTflags | (result & WANTinterpret)); + e = this; + if (e1->isBool(FALSE)) + { + e = new CommaExp(loc, e1, new IntegerExp(loc, 0, type)); + e->type = type; + e = e->optimize(result); + } + else + { + e2 = e2->optimize(WANTflags | (result & WANTinterpret)); + if (result && e2->type->toBasetype()->ty == Tvoid && !global.errors) + error("void has no value"); + if (e1->isConst()) + { + if (e2->isConst()) + { int n1 = e1->isBool(1); + int n2 = e2->isBool(1); + + e = new IntegerExp(loc, n1 && n2, type); + } + else if (e1->isBool(TRUE)) + e = new BoolExp(loc, e2, type); + } + } + return e; +} + +Expression *OrOrExp::optimize(int result) +{ Expression *e; + + e1 = e1->optimize(WANTflags | (result & WANTinterpret)); + e = this; + if (e1->isBool(TRUE)) + { // Replace with (e1, 1) + e = new CommaExp(loc, e1, new IntegerExp(loc, 1, type)); + e->type = type; + e = e->optimize(result); + } + else + { + e2 = e2->optimize(WANTflags | (result & WANTinterpret)); + if (result && e2->type->toBasetype()->ty == Tvoid && !global.errors) + error("void has no value"); + if (e1->isConst()) + { + if (e2->isConst()) + { int n1 = e1->isBool(1); + int n2 = e2->isBool(1); + + e = new IntegerExp(loc, n1 || n2, type); + } + else if (e1->isBool(FALSE)) + e = new BoolExp(loc, e2, type); + } + } + return e; +} + +Expression *CmpExp::optimize(int result) +{ Expression *e; + + //printf("CmpExp::optimize() %s\n", toChars()); + e1 = e1->optimize(result); + e2 = e2->optimize(result); + if (e1->isConst() == 1 && e2->isConst() == 1) + { + e = Cmp(op, type, this->e1, this->e2); + } + else + e = this; + return e; +} + +Expression *CatExp::optimize(int result) +{ Expression *e; + + //printf("CatExp::optimize(%d) %s\n", result, toChars()); + e1 = e1->optimize(result); + e2 = e2->optimize(result); + e = Cat(type, e1, e2); + if (e == EXP_CANT_INTERPRET) + e = this; + return e; +} + + +Expression *CondExp::optimize(int result) +{ Expression *e; + + econd = econd->optimize(WANTflags | (result & WANTinterpret)); + if (econd->isBool(TRUE)) + e = e1->optimize(result); + else if (econd->isBool(FALSE)) + e = e2->optimize(result); + else + { e1 = e1->optimize(result); + e2 = e2->optimize(result); + e = this; + } + return e; +} + + diff -r 1853dcd9b944 -r e961851fb8be dmd/parse.c --- a/dmd/parse.c Fri Apr 03 17:02:52 2009 +0200 +++ b/dmd/parse.c Fri Apr 03 17:59:34 2009 +0200 @@ -1,6 +1,6 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2008 by Digital Mars +// Copyright (c) 1999-2009 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -32,6 +32,9 @@ #include "enum.h" #include "id.h" #include "version.h" +#if DMDV2 +#include "aliasthis.h" +#endif // How multiple declarations are parsed. // If 1, treat as C. @@ -75,6 +78,25 @@ unsigned char *comment = token.blockComment; nextToken(); +#if DMDV2 + if (token.value == TOKlparen) + { + nextToken(); + if (token.value != TOKidentifier) + { error("module (system) identifier expected"); + goto Lerr; + } + Identifier *id = token.ident; + + if (id == Id::system) + safe = TRUE; + else + error("(safe) expected, not %s", id->toChars()); + nextToken(); + check(TOKrparen); + } +#endif + if (token.value != TOKidentifier) { error("Identifier expected following module"); goto Lerr; @@ -259,6 +281,13 @@ case TOKabstract: stc = STCabstract; goto Lstc; case TOKsynchronized: stc = STCsynchronized; goto Lstc; case TOKdeprecated: stc = STCdeprecated; goto Lstc; +#if DMDV2 + case TOKnothrow: stc = STCnothrow; goto Lstc; + case TOKpure: stc = STCpure; goto Lstc; + case TOKref: stc = STCref; goto Lstc; + case TOKtls: stc = STCtls; goto Lstc; + //case TOKmanifest: stc = STCmanifest; goto Lstc; +#endif Lstc: nextToken(); @@ -342,6 +371,16 @@ Lprot: nextToken(); + switch (token.value) + { + case TOKprivate: + case TOKpackage: + case TOKprotected: + case TOKpublic: + case TOKexport: + error("redundant protection attribute"); + break; + } a = parseBlock(); s = new ProtDeclaration(prot, a); break; @@ -802,7 +841,7 @@ /***************************************** * Parse an invariant definition: - * invariant { body } + * invariant() { body } * Current token is 'invariant'. */ @@ -987,7 +1026,7 @@ EnumDeclaration *Parser::parseEnum() { EnumDeclaration *e; Identifier *id; - Type *t; + Type *memtype; Loc loc = this->loc; //printf("Parser::parseEnum()\n"); @@ -1002,12 +1041,12 @@ if (token.value == TOKcolon) { nextToken(); - t = parseBasicType(); + memtype = parseBasicType(); } else - t = NULL; - - e = new EnumDeclaration(loc, id, t); + memtype = NULL; + + e = new EnumDeclaration(loc, id, memtype); if (token.value == TOKsemicolon && id) nextToken(); else if (token.value == TOKlcurly) @@ -1058,6 +1097,10 @@ return e; } +/******************************** + * Parse struct, union, interface, class. + */ + Dsymbol *Parser::parseAggregate() { AggregateDeclaration *a = NULL; int anon = 0; @@ -1160,7 +1203,7 @@ // Wrap a template around the aggregate declaration decldefs = new Array(); decldefs->push(a); - tempdecl = new TemplateDeclaration(loc, id, tpl, decldefs); + tempdecl = new TemplateDeclaration(loc, id, tpl, NULL, decldefs); return tempdecl; } @@ -1265,7 +1308,7 @@ nextToken(); } - tempdecl = new TemplateDeclaration(loc, id, tpl, decldefs); + tempdecl = new TemplateDeclaration(loc, id, tpl, NULL, decldefs); return tempdecl; Lerr: @@ -1650,6 +1693,60 @@ return NULL; } +#if DMDV2 +Type *Parser::parseType(Identifier **pident, TemplateParameters **tpl) +{ Type *t; + + /* Take care of the storage class prefixes that + * serve as type attributes: + * const shared, shared const, const, invariant, shared + */ + if (token.value == TOKconst && peekNext() == TOKshared && peekNext2() != TOKlparen || + token.value == TOKshared && peekNext() == TOKconst && peekNext2() != TOKlparen) + { + nextToken(); + nextToken(); + /* shared const type + */ + t = parseType(pident, tpl); + t = t->makeSharedConst(); + return t; + } + else if (token.value == TOKconst && peekNext() != TOKlparen) + { + nextToken(); + /* const type + */ + t = parseType(pident, tpl); + t = t->makeConst(); + return t; + } + else if ((token.value == TOKinvariant || token.value == TOKimmutable) && + peekNext() != TOKlparen) + { + nextToken(); + /* invariant type + */ + t = parseType(pident, tpl); + t = t->makeInvariant(); + return t; + } + else if (token.value == TOKshared && peekNext() != TOKlparen) + { + nextToken(); + /* shared type + */ + t = parseType(pident, tpl); + t = t->makeShared(); + return t; + } + else + t = parseBasicType(); + t = parseDeclarator(t, pident, tpl); + return t; +} +#endif + Type *Parser::parseBasicType() { Type *t; Identifier *id; @@ -1889,6 +1986,7 @@ break; } + // parse DeclaratorSuffixes while (1) { switch (token.value) @@ -1924,6 +2022,7 @@ ta = new TypeSArray(t, e); check(TOKrbracket); } + /* Insert ta into * ts -> ... -> t * so that @@ -1986,7 +2085,7 @@ Type *tfirst; Identifier *ident; Array *a; - enum TOK tok; + enum TOK tok = TOKreserved; unsigned char *comment = token.blockComment; enum LINK link = linkage; @@ -2018,6 +2117,13 @@ case TOKabstract: stc = STCabstract; goto L1; case TOKsynchronized: stc = STCsynchronized; goto L1; case TOKdeprecated: stc = STCdeprecated; goto L1; +#if DMDV2 + case TOKnothrow: stc = STCnothrow; goto L1; + case TOKpure: stc = STCpure; goto L1; + case TOKref: stc = STCref; goto L1; + case TOKtls: stc = STCtls; goto L1; + case TOKenum: stc = STCmanifest; goto L1; +#endif L1: if (storage_class & stc) error("redundant storage class '%s'", token.toChars()); @@ -2108,9 +2214,8 @@ if (tok == TOKtypedef || tok == TOKalias) { Declaration *v; - Initializer *init; - - init = NULL; + Initializer *init = NULL; + if (token.value == TOKassign) { nextToken(); @@ -2150,13 +2255,12 @@ } } else if (t->ty == Tfunction) - { FuncDeclaration *f; - Dsymbol *s; - - f = new FuncDeclaration(loc, 0, ident, storage_class, t); + { FuncDeclaration *f = + new FuncDeclaration(loc, 0, ident, storage_class, t); addComment(f, comment); parseContracts(f); addComment(f, NULL); + Dsymbol *s; if (link == linkage) { s = f; @@ -2174,23 +2278,22 @@ // Wrap a template around the aggregate declaration decldefs = new Array(); decldefs->push(s); - tempdecl = new TemplateDeclaration(loc, s->ident, tpl, decldefs); + tempdecl = new TemplateDeclaration(loc, s->ident, tpl, NULL, decldefs); s = tempdecl; } addComment(s, comment); a->push(s); } else - { VarDeclaration *v; - Initializer *init; - - init = NULL; + { + Initializer *init = NULL; if (token.value == TOKassign) { nextToken(); init = parseInitializer(); } - v = new VarDeclaration(loc, t, ident, init); + + VarDeclaration *v = new VarDeclaration(loc, t, ident, init); v->storage_class = storage_class; if (link == linkage) a->push(v); @@ -2363,6 +2466,7 @@ } /***************************************** + * Parse initializer for variable declaration. */ Initializer *Parser::parseInitializer() @@ -2620,13 +2724,14 @@ switch (token.value) { case TOKidentifier: - // Need to look ahead to see if it is a declaration, label, or expression + /* A leading identifier can be a declaration, label, or expression. + * The easiest case to check first is label: + */ t = peek(&token); if (t->value == TOKcolon) { // It's a label - Identifier *ident; - - ident = token.ident; + + Identifier *ident = token.ident; nextToken(); nextToken(); s = parseStatement(PSsemi); @@ -2718,6 +2823,10 @@ case TOKextern: case TOKfinal: case TOKinvariant: +#if DMDV2 + case TOKimmutable: + case TOKshared: +#endif // case TOKtypeof: Ldeclaration: { Array *a; @@ -2733,7 +2842,7 @@ s = new DeclarationStatement(loc, d); as->push(s); } - s = new CompoundStatement(loc, as); + s = new CompoundDeclarationStatement(loc, as); } else if (a->dim == 1) { @@ -3443,7 +3552,7 @@ nextToken(); } -void Parser::check(enum TOK value, char *string) +void Parser::check(enum TOK value, const char *string) { if (token.value != value) error("found '%s' when expecting '%s' following '%s'", @@ -3461,6 +3570,7 @@ int Parser::isDeclaration(Token *t, int needId, enum TOK endtok, Token **pt) { + //printf("isDeclaration(needId = %d)\n", needId); int haveId = 0; #if DMDV2 @@ -3551,9 +3661,11 @@ goto Lfalse; } *pt = t; + //printf("is\n"); return TRUE; Lfalse: + //printf("is not\n"); return FALSE; } @@ -3678,6 +3790,25 @@ parens = FALSE; if (!isParameters(&t)) return FALSE; +#if DMDV2 + while (1) + { + switch (t->value) + { + case TOKconst: + case TOKinvariant: + case TOKimmutable: + case TOKshared: + case TOKpure: + case TOKnothrow: + t = peek(t); + continue; + default: + break; + } + break; + } +#endif continue; // Valid tokens that follow a declaration @@ -4203,6 +4334,12 @@ token.value == TOKsuper || token.value == TOKenum || token.value == TOKinterface || +#if DMDV2 + token.value == TOKconst && peek(&token)->value == TOKrparen || + token.value == TOKinvariant && peek(&token)->value == TOKrparen || + token.value == TOKimmutable && peek(&token)->value == TOKrparen || + token.value == TOKshared && peek(&token)->value == TOKrparen || +#endif token.value == TOKfunction || token.value == TOKdelegate || token.value == TOKreturn)) diff -r 1853dcd9b944 -r e961851fb8be dmd/parse.h --- a/dmd/parse.h Fri Apr 03 17:02:52 2009 +0200 +++ b/dmd/parse.h Fri Apr 03 17:59:34 2009 +0200 @@ -1,6 +1,6 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2008 by Digital Mars +// Copyright (c) 1999-2009 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -100,7 +100,7 @@ Initializer *parseInitializer(); void check(Loc loc, enum TOK value); void check(enum TOK value); - void check(enum TOK value, char *string); + void check(enum TOK value, const char *string); int isDeclaration(Token *t, int needId, enum TOK endtok, Token **pt); int isBasicType(Token **pt); int isDeclarator(Token **pt, int *haveId, enum TOK endtok); diff -r 1853dcd9b944 -r e961851fb8be dmd/root/array.c --- a/dmd/root/array.c Fri Apr 03 17:02:52 2009 +0200 +++ b/dmd/root/array.c Fri Apr 03 17:59:34 2009 +0200 @@ -1,5 +1,5 @@ -// Copyright (c) 1999-2006 by Digital Mars +// Copyright (c) 1999-2009 by Digital Mars // All Rights Reserved // written by Walter Bright // www.digitalmars.com diff -r 1853dcd9b944 -r e961851fb8be dmd/root/async.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dmd/root/async.c Fri Apr 03 17:59:34 2009 +0200 @@ -0,0 +1,177 @@ + +#define _MT 1 + +#include +#include +#include + +#if _WIN32 + +#include +#include +#include +#include + +#include "root.h" +#include "rmem.h" + +static unsigned __stdcall startthread(void *p); + +struct FileData +{ + File *file; + int result; + HANDLE event; +}; + +struct AsyncRead +{ + static AsyncRead *create(size_t nfiles); + void addFile(File *file); + void start(); + int read(size_t i); + static void dispose(AsyncRead *); + + HANDLE hThread; + + size_t filesdim; + size_t filesmax; + FileData files[1]; +}; + + +AsyncRead *AsyncRead::create(size_t nfiles) +{ + AsyncRead *aw = (AsyncRead *)mem.calloc(1, sizeof(AsyncRead) + + (nfiles - 1) * sizeof(FileData)); + aw->filesmax = nfiles; + return aw; +} + +void AsyncRead::addFile(File *file) +{ + //printf("addFile(file = %p)\n", file); + //printf("filesdim = %d, filesmax = %d\n", filesdim, filesmax); + assert(filesdim < filesmax); + files[filesdim].file = file; + files[filesdim].event = CreateEvent(NULL, TRUE, FALSE, NULL); + ResetEvent(files[filesdim].event); + filesdim++; +} + +void AsyncRead::start() +{ + unsigned threadaddr; + hThread = (HANDLE) _beginthreadex(NULL, + 0, + &startthread, + this, + 0, + (unsigned *)&threadaddr); + + if (hThread) + { + SetThreadPriority(hThread, THREAD_PRIORITY_HIGHEST); + } + else + { + assert(0); + } +} + +int AsyncRead::read(size_t i) +{ + FileData *f = &files[i]; + WaitForSingleObject(f->event, INFINITE); + Sleep(0); // give up time slice + return f->result; +} + +void AsyncRead::dispose(AsyncRead *aw) +{ + delete aw; +} + + + +unsigned __stdcall startthread(void *p) +{ + AsyncRead *aw = (AsyncRead *)p; + + for (size_t i = 0; i < aw->filesdim; i++) + { FileData *f = &aw->files[i]; + + f->result = f->file->read(); + SetEvent(f->event); + } + _endthreadex(EXIT_SUCCESS); + return EXIT_SUCCESS; // if skidding +} + +#else + +#include +#include + +#include "root.h" +#include "rmem.h" + +struct FileData +{ + File *file; + int result; + //HANDLE event; +}; + +struct AsyncRead +{ + static AsyncRead *create(size_t nfiles); + void addFile(File *file); + void start(); + int read(size_t i); + static void dispose(AsyncRead *); + + //HANDLE hThread; + + size_t filesdim; + size_t filesmax; + FileData files[1]; +}; + + +AsyncRead *AsyncRead::create(size_t nfiles) +{ + AsyncRead *aw = (AsyncRead *)mem.calloc(1, sizeof(AsyncRead) + + (nfiles - 1) * sizeof(FileData)); + aw->filesmax = nfiles; + return aw; +} + +void AsyncRead::addFile(File *file) +{ + //printf("addFile(file = %p)\n", file); + //printf("filesdim = %d, filesmax = %d\n", filesdim, filesmax); + assert(filesdim < filesmax); + files[filesdim].file = file; + //files[filesdim].event = CreateEvent(NULL, TRUE, FALSE, NULL); + //ResetEvent(files[filesdim].event); + filesdim++; +} + +void AsyncRead::start() +{ +} + +int AsyncRead::read(size_t i) +{ + FileData *f = &files[i]; + f->result = f->file->read(); + return f->result; +} + +void AsyncRead::dispose(AsyncRead *aw) +{ + delete aw; +} + +#endif diff -r 1853dcd9b944 -r e961851fb8be dmd/root/async.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dmd/root/async.h Fri Apr 03 17:59:34 2009 +0200 @@ -0,0 +1,33 @@ + +// Copyright (c) 2009-2009 by Digital Mars +// All Rights Reserved +// written by Walter Bright +// 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. + +#ifndef ASYNC_H +#define ASYNC_H + +#if __DMC__ +#pragma once +#endif + + +/******************* + * Simple interface to read files asynchronously in another + * thread. + */ + +struct AsyncRead +{ + static AsyncRead *create(size_t nfiles); + void addFile(File *file); + void start(); + int read(size_t i); + static void dispose(AsyncRead *); +}; + + +#endif diff -r 1853dcd9b944 -r e961851fb8be dmd/root/port.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dmd/root/port.c Fri Apr 03 17:59:34 2009 +0200 @@ -0,0 +1,754 @@ + +// Copyright (c) 1999-2009 by Digital Mars +// All Rights Reserved +// written by Walter Bright +// http://www.digitalmars.com + +#include "port.h" + +#if __DMC__ +#include +#include +#include +#include +#include +#include + +double Port::nan = NAN; +double Port::infinity = INFINITY; +double Port::dbl_max = DBL_MAX; +double Port::dbl_min = DBL_MIN; + +int Port::isNan(double r) +{ + return ::isnan(r); +} + +int Port::isNan(long double r) +{ + return ::isnan(r); +} + +int Port::isSignallingNan(double r) +{ + /* A signalling NaN is a NaN with 0 as the most significant bit of + * its significand, which is bit 51 of 0..63 for 64 bit doubles. + */ + return isNan(r) && !((((unsigned char*)&r)[6]) & 8); +} + +int Port::isSignallingNan(long double r) +{ + /* A signalling NaN is a NaN with 0 as the most significant bit of + * its significand, which is bit 62 of 0..79 for 80 bit reals. + */ + return isNan(r) && !((((unsigned char*)&r)[7]) & 0x40); +} + +int Port::isFinite(double r) +{ + return ::isfinite(r); +} + +int Port::isInfinity(double r) +{ + return (::fpclassify(r) == FP_INFINITE); +} + +int Port::Signbit(double r) +{ + return ::signbit(r); +} + +double Port::floor(double d) +{ + return ::floor(d); +} + +double Port::pow(double x, double y) +{ + return ::pow(x, y); +} + +unsigned long long Port::strtoull(const char *p, char **pend, int base) +{ + return ::strtoull(p, pend, base); +} + +char *Port::ull_to_string(char *buffer, ulonglong ull) +{ + sprintf(buffer, "%llu", ull); + return buffer; +} + +wchar_t *Port::ull_to_string(wchar_t *buffer, ulonglong ull) +{ + swprintf(buffer, sizeof(ulonglong) * 3 + 1, L"%llu", ull); + return buffer; +} + +double Port::ull_to_double(ulonglong ull) +{ + return (double) ull; +} + +const char *Port::list_separator() +{ + // LOCALE_SLIST for Windows + return ","; +} + +const wchar_t *Port::wlist_separator() +{ + // LOCALE_SLIST for Windows + return L","; +} + +char *Port::strupr(char *s) +{ + return ::strupr(s); +} + +#endif + +#if _MSC_VER + +// Disable useless warnings about unreferenced functions +#pragma warning (disable : 4514) + +#include +#include +#include +#include +#include +#include +#include + +static unsigned long nanarray[2]= { 0xFFFFFFFF, 0x7FFFFFFF }; +//static unsigned long nanarray[2] = {0,0x7FF80000 }; +double Port::nan = (*(double *)nanarray); + +//static unsigned long infinityarray[2] = {0,0x7FF00000 }; +static double zero = 0; +double Port::infinity = 1 / zero; + +double Port::dbl_max = DBL_MAX; +double Port::dbl_min = DBL_MIN; + +struct PortInitializer +{ + PortInitializer(); +}; + +static PortInitializer portinitializer; + +PortInitializer::PortInitializer() +{ + Port::infinity = std::numeric_limits::infinity(); +} + +int Port::isNan(double r) +{ + return ::_isnan(r); +} + +int Port::isNan(long double r) +{ + return ::_isnan(r); +} + +int Port::isSignallingNan(double r) +{ + /* A signalling NaN is a NaN with 0 as the most significant bit of + * its significand, which is bit 51 of 0..63 for 64 bit doubles. + */ + return isNan(r) && !((((unsigned char*)&r)[6]) & 8); +} + +int Port::isSignallingNan(long double r) +{ + /* MSVC doesn't have 80 bit long doubles + */ + return isSignallingNan((double) r); +} + +int Port::isFinite(double r) +{ + return ::_finite(r); +} + +int Port::isInfinity(double r) +{ + return (::_fpclass(r) & (_FPCLASS_NINF | _FPCLASS_PINF)); +} + +int Port::Signbit(double r) +{ + return (long)(((long *)&(r))[1] & 0x80000000); +} + +double Port::floor(double d) +{ + return ::floor(d); +} + +double Port::pow(double x, double y) +{ + if (y == 0) + return 1; // even if x is NAN + return ::pow(x, y); +} + +unsigned _int64 Port::strtoull(const char *p, char **pend, int base) +{ + unsigned _int64 number = 0; + int c; + int error; + #define ULLONG_MAX ((unsigned _int64)~0I64) + + while (isspace(*p)) /* skip leading white space */ + p++; + if (*p == '+') + p++; + switch (base) + { case 0: + base = 10; /* assume decimal base */ + if (*p == '0') + { base = 8; /* could be octal */ + p++; + switch (*p) + { case 'x': + case 'X': + base = 16; /* hex */ + p++; + break; +#if BINARY + case 'b': + case 'B': + base = 2; /* binary */ + p++; + break; +#endif + } + } + break; + case 16: /* skip over '0x' and '0X' */ + if (*p == '0' && (p[1] == 'x' || p[1] == 'X')) + p += 2; + break; +#if BINARY + case 2: /* skip over '0b' and '0B' */ + if (*p == '0' && (p[1] == 'b' || p[1] == 'B')) + p += 2; + break; +#endif + } + error = 0; + for (;;) + { c = *p; + if (isdigit(c)) + c -= '0'; + else if (isalpha(c)) + c = (c & ~0x20) - ('A' - 10); + else /* unrecognized character */ + break; + if (c >= base) /* not in number base */ + break; + if ((ULLONG_MAX - c) / base < number) + error = 1; + number = number * base + c; + p++; + } + if (pend) + *pend = (char *)p; + if (error) + { number = ULLONG_MAX; + errno = ERANGE; + } + return number; +} + +char *Port::ull_to_string(char *buffer, ulonglong ull) +{ + _ui64toa(ull, buffer, 10); + return buffer; +} + +wchar_t *Port::ull_to_string(wchar_t *buffer, ulonglong ull) +{ + _ui64tow(ull, buffer, 10); + return buffer; +} + +double Port::ull_to_double(ulonglong ull) +{ double d; + + if ((__int64) ull < 0) + { + // MSVC doesn't implement the conversion + d = (double) (__int64)(ull - 0x8000000000000000i64); + d += (double)(signed __int64)(0x7FFFFFFFFFFFFFFFi64) + 1.0; + } + else + d = (double)(__int64)ull; + return d; +} + +const char *Port::list_separator() +{ + // LOCALE_SLIST for Windows + return ","; +} + +const wchar_t *Port::wlist_separator() +{ + // LOCALE_SLIST for Windows + return L","; +} + +char *Port::strupr(char *s) +{ + return ::strupr(s); +} + +#endif + +#if linux || __APPLE__ || __FreeBSD__ + +#include +#if linux +#include +#include +#endif +#include +#include +#include +#include +#include +#include + +static double zero = 0; +double Port::nan = NAN; +double Port::infinity = 1 / zero; +double Port::dbl_max = 1.7976931348623157e308; +double Port::dbl_min = 5e-324; + +struct PortInitializer +{ + PortInitializer(); +}; + +static PortInitializer portinitializer; + +PortInitializer::PortInitializer() +{ + // gcc nan's have the sign bit set by default, so turn it off + // Need the volatile to prevent gcc from doing incorrect + // constant folding. + volatile long double foo; + foo = NAN; + if (signbit(foo)) // signbit sometimes, not always, set + foo = -foo; // turn off sign bit + Port::nan = foo; +} + +#undef isnan +int Port::isNan(double r) +{ +#if __APPLE__ + return __inline_isnan(r); +#else + return ::isnan(r); +#endif +} + +int Port::isNan(long double r) +{ +#if __APPLE__ + return __inline_isnan(r); +#else + return ::isnan(r); +#endif +} + +int Port::isSignallingNan(double r) +{ + /* A signalling NaN is a NaN with 0 as the most significant bit of + * its significand, which is bit 51 of 0..63 for 64 bit doubles. + */ + return isNan(r) && !((((unsigned char*)&r)[6]) & 8); +} + +int Port::isSignallingNan(long double r) +{ + /* A signalling NaN is a NaN with 0 as the most significant bit of + * its significand, which is bit 62 of 0..79 for 80 bit reals. + */ + return isNan(r) && !((((unsigned char*)&r)[7]) & 0x40); +} + +#undef isfinite +int Port::isFinite(double r) +{ + return ::finite(r); +} + +#undef isinf +int Port::isInfinity(double r) +{ +#if __APPLE__ + return fpclassify(r) == FP_INFINITE; +#else + return ::isinf(r); +#endif +} + +#undef signbit +int Port::Signbit(double r) +{ + return (long)(((long *)&r)[1] & 0x80000000); +} + +double Port::floor(double d) +{ + return ::floor(d); +} + +double Port::pow(double x, double y) +{ + return ::pow(x, y); +} + +unsigned long long Port::strtoull(const char *p, char **pend, int base) +{ + return ::strtoull(p, pend, base); +} + +char *Port::ull_to_string(char *buffer, ulonglong ull) +{ + sprintf(buffer, "%llu", ull); + return buffer; +} + +wchar_t *Port::ull_to_string(wchar_t *buffer, ulonglong ull) +{ + swprintf(buffer, sizeof(ulonglong) * 3 + 1, L"%llu", ull); + return buffer; +} + +double Port::ull_to_double(ulonglong ull) +{ + return (double) ull; +} + +const char *Port::list_separator() +{ + return ","; +} + +const wchar_t *Port::wlist_separator() +{ + return L","; +} + +char *Port::strupr(char *s) +{ + char *t = s; + + while (*s) + { + *s = toupper(*s); + s++; + } + + return t; +} + +#endif + +#if defined (__SVR4) && defined (__sun) + +#define __C99FEATURES__ 1 // Needed on Solaris for NaN and more +#include +#include +#include +#include +#include +#include +#include + +static double zero = 0; +double Port::nan = NAN; +double Port::infinity = 1 / zero; +double Port::dbl_max = 1.7976931348623157e308; +double Port::dbl_min = 5e-324; + +struct PortInitializer +{ + PortInitializer(); +}; + +static PortInitializer portinitializer; + +PortInitializer::PortInitializer() +{ + // gcc nan's have the sign bit set by default, so turn it off + // Need the volatile to prevent gcc from doing incorrect + // constant folding. + volatile long double foo; + foo = NAN; + if (signbit(foo)) // signbit sometimes, not always, set + foo = -foo; // turn off sign bit + Port::nan = foo; +} + +#undef isnan +int Port::isNan(double r) +{ +#if __APPLE__ + return __inline_isnan(r); +#else + return ::isnan(r); +#endif +} + +int Port::isNan(long double r) +{ +#if __APPLE__ + return __inline_isnan(r); +#else + return ::isnan(r); +#endif +} + +int Port::isSignallingNan(double r) +{ + /* A signalling NaN is a NaN with 0 as the most significant bit of + * its significand, which is bit 51 of 0..63 for 64 bit doubles. + */ + return isNan(r) && !((((unsigned char*)&r)[6]) & 8); +} + +int Port::isSignallingNan(long double r) +{ + /* A signalling NaN is a NaN with 0 as the most significant bit of + * its significand, which is bit 62 of 0..79 for 80 bit reals. + */ + return isNan(r) && !((((unsigned char*)&r)[7]) & 0x40); +} + +#undef isfinite +int Port::isFinite(double r) +{ + return ::finite(r); +} + +#undef isinf +int Port::isInfinity(double r) +{ + return ::isinf(r); +} + +#undef signbit +int Port::Signbit(double r) +{ + return (long)(((long *)&r)[1] & 0x80000000); +} + +double Port::floor(double d) +{ + return ::floor(d); +} + +double Port::pow(double x, double y) +{ + return ::pow(x, y); +} + +unsigned long long Port::strtoull(const char *p, char **pend, int base) +{ + return ::strtoull(p, pend, base); +} + +char *Port::ull_to_string(char *buffer, ulonglong ull) +{ + sprintf(buffer, "%llu", ull); + return buffer; +} + +wchar_t *Port::ull_to_string(wchar_t *buffer, ulonglong ull) +{ + swprintf(buffer, sizeof(ulonglong) * 3 + 1, L"%llu", ull); + return buffer; +} + +double Port::ull_to_double(ulonglong ull) +{ + return (double) ull; +} + +const char *Port::list_separator() +{ + return ","; +} + +const wchar_t *Port::wlist_separator() +{ + return L","; +} + +char *Port::strupr(char *s) +{ + char *t = s; + + while (*s) + { + *s = toupper(*s); + s++; + } + + return t; +} + +#endif + +#if IN_GCC + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static double zero = 0; +double Port::nan = NAN; +double Port::infinity = 1 / zero; +double Port::dbl_max = 1.7976931348623157e308; +double Port::dbl_min = 5e-324; + +#include "d-gcc-real.h" +extern "C" bool real_isnan (const real_t *); + +struct PortInitializer +{ + PortInitializer(); +}; + +static PortInitializer portinitializer; + +PortInitializer::PortInitializer() +{ + Port::infinity = real_t::getinfinity(); + Port::nan = real_t::getnan(real_t::LongDouble); +} + +#undef isnan +int Port::isNan(double r) +{ +#if __APPLE__ + return __inline_isnan(r); +#else + return ::isnan(r); +#endif +} + +int Port::isNan(long double r) +{ + return real_isnan(&r); +} + +int Port::isSignallingNan(double r) +{ + /* A signalling NaN is a NaN with 0 as the most significant bit of + * its significand, which is bit 51 of 0..63 for 64 bit doubles. + */ + return isNan(r) && !((((unsigned char*)&r)[6]) & 8); +} + +int Port::isSignallingNan(long double r) +{ + /* A signalling NaN is a NaN with 0 as the most significant bit of + * its significand, which is bit 62 of 0..79 for 80 bit reals. + */ + return isNan(r) && !((((unsigned char*)&r)[7]) & 0x40); +} + +#undef isfinite +int Port::isFinite(double r) +{ + return ::finite(r); +} + +#undef isinf +int Port::isInfinity(double r) +{ + return ::isinf(r); +} + +#undef signbit +int Port::Signbit(double r) +{ + return (long)(((long *)&r)[1] & 0x80000000); +} + +double Port::floor(double d) +{ + return ::floor(d); +} + +double Port::pow(double x, double y) +{ + return ::pow(x, y); +} + +unsigned long long Port::strtoull(const char *p, char **pend, int base) +{ + return ::strtoull(p, pend, base); +} + +char *Port::ull_to_string(char *buffer, ulonglong ull) +{ + sprintf(buffer, "%llu", ull); + return buffer; +} + +wchar_t *Port::ull_to_string(wchar_t *buffer, ulonglong ull) +{ + swprintf(buffer, L"%llu", ull); + return buffer; +} + +double Port::ull_to_double(ulonglong ull) +{ + return (double) ull; +} + +const char *Port::list_separator() +{ + return ","; +} + +const wchar_t *Port::wlist_separator() +{ + return L","; +} + +char *Port::strupr(char *s) +{ + char *t = s; + + while (*s) + { + *s = toupper(*s); + s++; + } + + return t; +} + +#endif + diff -r 1853dcd9b944 -r e961851fb8be dmd/root/port.h --- a/dmd/root/port.h Fri Apr 03 17:02:52 2009 +0200 +++ b/dmd/root/port.h Fri Apr 03 17:59:34 2009 +0200 @@ -1,8 +1,8 @@ -// Copyright (c) 1999-2002 by Digital Mars +// Copyright (c) 1999-2009 by Digital Mars // All Rights Reserved // written by Walter Bright -// www.digitalmars.com +// http://www.digitalmars.com #ifndef PORT_H #define PORT_H @@ -42,6 +42,11 @@ #undef signbit #endif static int isNan(double); + static int isNan(long double); + + static int isSignallingNan(double); + static int isSignallingNan(long double); + static int isFinite(double); static int isInfinity(double); static int Signbit(double); @@ -58,8 +63,10 @@ static double ull_to_double(ulonglong ull); // Get locale-dependent list separator - static char *list_separator(); - static wchar_t *wlist_separator(); + static const char *list_separator(); + static const wchar_t *wlist_separator(); + + static char *strupr(char *); }; #endif diff -r 1853dcd9b944 -r e961851fb8be dmd/root/root.c --- a/dmd/root/root.c Fri Apr 03 17:02:52 2009 +0200 +++ b/dmd/root/root.c Fri Apr 03 17:59:34 2009 +0200 @@ -583,9 +583,17 @@ return e + 1; #if _WIN32 + case '/': case '\\': + return e + 1; case ':': - return e + 1; + /* The ':' is a drive letter only if it is the second + * character or the last character, + * otherwise it is an ADS (Alternate Data Stream) separator. + * Consider ADS separators as part of the file name. + */ + if (e == str + 1 || e == str + len - 1) + return e + 1; #endif default: if (e == str) @@ -620,7 +628,7 @@ n--; #if _WIN32 - if (n[-1] == '\\') + if (n[-1] == '\\' || n[-1] == '/') n--; #endif } @@ -822,8 +830,8 @@ if (*p) { #if _WIN32 - size_t len = strlen(p); - if (len > 2 && p[-1] == ':') + size_t len = strlen(path); + if (len > 2 && p[-1] == ':' && path + 2 == p) { mem.free(p); return; } diff -r 1853dcd9b944 -r e961851fb8be dmd/scope.h --- a/dmd/scope.h Fri Apr 03 17:02:52 2009 +0200 +++ b/dmd/scope.h Fri Apr 03 17:59:34 2009 +0200 @@ -1,114 +1,120 @@ - -// Copyright (c) 1999-2005 by Digital Mars -// All Rights Reserved -// written by Walter Bright -// 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. - -#ifndef DMD_SCOPE_H -#define DMD_SCOPE_H - -#ifdef __DMC__ -#pragma once -#endif /* __DMC__ */ - -struct Dsymbol; -struct ScopeDsymbol; -struct Array; -struct Identifier; -struct Module; -struct Statement; -struct SwitchStatement; -struct TryFinallyStatement; -struct LabelStatement; -struct ForeachStatement; -struct ClassDeclaration; -struct AggregateDeclaration; -struct AnonymousAggregateDeclaration; -struct FuncDeclaration; -struct DocComment; -struct EnclosingHandler; -struct AnonDeclaration; -enum LINK; -enum PROT; - -struct Scope -{ - Scope *enclosing; // enclosing Scope - - Module *module; // Root module - ScopeDsymbol *scopesym; // current symbol - ScopeDsymbol *sd; // if in static if, and declaring new symbols, - // sd gets the addMember() - FuncDeclaration *func; // function we are in - Dsymbol *parent; // parent to use - LabelStatement *slabel; // enclosing labelled statement - SwitchStatement *sw; // enclosing switch statement - TryFinallyStatement *enclosingFinally; // enclosing try finally statement; set inside its finally block - Statement *enclosingScopeExit; // enclosing statement that wants to do something on scope exit - TemplateInstance *tinst; // enclosing template instance - Statement *sbreak; // enclosing statement that supports "break" - Statement *scontinue; // enclosing statement that supports "continue" - ForeachStatement *fes; // if nested function for ForeachStatement, this is it - unsigned offset; // next offset to use in aggregate - int inunion; // we're processing members of a union - int incontract; // we're inside contract code - int nofree; // set if shouldn't free it - int noctor; // set if constructor calls aren't allowed - int intypeof; // in typeof(exp) - int parameterSpecialization; // if in template parameter specialization - int noaccesscheck; // don't do access checks - - unsigned callSuper; // primitive flow analysis for constructors -#define CSXthis_ctor 1 // called this() -#define CSXsuper_ctor 2 // called super() -#define CSXthis 4 // referenced this -#define CSXsuper 8 // referenced super -#define CSXlabel 0x10 // seen a label -#define CSXreturn 0x20 // seen a return statement -#define CSXany_ctor 0x40 // either this() or super() was called - - unsigned structalign; // alignment for struct members - enum LINK linkage; // linkage for external functions - - enum PROT protection; // protection for class members - int explicitProtection; // set if in an explicit protection attribute - - unsigned stc; // storage class - - unsigned flags; -#define SCOPEctor 1 // constructor type -#define SCOPEstaticif 2 // inside static if -#define SCOPEfree 4 // is on free list - - AnonymousAggregateDeclaration *anonAgg; // for temporary analysis - - DocComment *lastdc; // documentation comment for last symbol at this scope - unsigned lastoffset; // offset in docbuf of where to insert next dec - OutBuffer *docbuf; // buffer for documentation output - - static Scope *freelist; - static void *operator new(size_t sz); - static Scope *createGlobal(Module *module); - - Scope(); - Scope(Module *module); - Scope(Scope *enclosing); - - Scope *push(); - Scope *push(ScopeDsymbol *ss); - Scope *pop(); - - void mergeCallSuper(Loc loc, unsigned cs); - - Dsymbol *search(Loc loc, Identifier *ident, Dsymbol **pscopesym); - Dsymbol *insert(Dsymbol *s); - - ClassDeclaration *getClassScope(); - AggregateDeclaration *getStructClassScope(); - void setNoFree(); -}; - -#endif /* DMD_SCOPE_H */ + +// Copyright (c) 1999-2009 by Digital Mars +// All Rights Reserved +// written by Walter Bright +// 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. + +#ifndef DMD_SCOPE_H +#define DMD_SCOPE_H + +#ifdef __DMC__ +#pragma once +#endif /* __DMC__ */ + +struct Dsymbol; +struct ScopeDsymbol; +struct Array; +struct Identifier; +struct Module; +struct Statement; +struct SwitchStatement; +struct TryFinallyStatement; +struct LabelStatement; +struct ForeachStatement; +struct ClassDeclaration; +struct AggregateDeclaration; +struct AnonymousAggregateDeclaration; +struct FuncDeclaration; +struct DocComment; +struct EnclosingHandler; +struct AnonDeclaration; + +#if __GNUC__ +#include "dsymbol.h" // PROT +#include "mars.h" // LINK +#else +enum LINK; +enum PROT; +#endif + +struct Scope +{ + Scope *enclosing; // enclosing Scope + + Module *module; // Root module + ScopeDsymbol *scopesym; // current symbol + ScopeDsymbol *sd; // if in static if, and declaring new symbols, + // sd gets the addMember() + FuncDeclaration *func; // function we are in + Dsymbol *parent; // parent to use + LabelStatement *slabel; // enclosing labelled statement + SwitchStatement *sw; // enclosing switch statement + TryFinallyStatement *enclosingFinally; // enclosing try finally statement; set inside its finally block + Statement *enclosingScopeExit; // enclosing statement that wants to do something on scope exit + TemplateInstance *tinst; // enclosing template instance + Statement *sbreak; // enclosing statement that supports "break" + Statement *scontinue; // enclosing statement that supports "continue" + ForeachStatement *fes; // if nested function for ForeachStatement, this is it + unsigned offset; // next offset to use in aggregate + int inunion; // we're processing members of a union + int incontract; // we're inside contract code + int nofree; // set if shouldn't free it + int noctor; // set if constructor calls aren't allowed + int intypeof; // in typeof(exp) + int parameterSpecialization; // if in template parameter specialization + int noaccesscheck; // don't do access checks + + unsigned callSuper; // primitive flow analysis for constructors +#define CSXthis_ctor 1 // called this() +#define CSXsuper_ctor 2 // called super() +#define CSXthis 4 // referenced this +#define CSXsuper 8 // referenced super +#define CSXlabel 0x10 // seen a label +#define CSXreturn 0x20 // seen a return statement +#define CSXany_ctor 0x40 // either this() or super() was called + + unsigned structalign; // alignment for struct members + enum LINK linkage; // linkage for external functions + + enum PROT protection; // protection for class members + int explicitProtection; // set if in an explicit protection attribute + + unsigned stc; // storage class + + unsigned flags; +#define SCOPEctor 1 // constructor type +#define SCOPEstaticif 2 // inside static if +#define SCOPEfree 4 // is on free list + + AnonymousAggregateDeclaration *anonAgg; // for temporary analysis + + DocComment *lastdc; // documentation comment for last symbol at this scope + unsigned lastoffset; // offset in docbuf of where to insert next dec + OutBuffer *docbuf; // buffer for documentation output + + static Scope *freelist; + static void *operator new(size_t sz); + static Scope *createGlobal(Module *module); + + Scope(); + Scope(Module *module); + Scope(Scope *enclosing); + + Scope *push(); + Scope *push(ScopeDsymbol *ss); + Scope *pop(); + + void mergeCallSuper(Loc loc, unsigned cs); + + Dsymbol *search(Loc loc, Identifier *ident, Dsymbol **pscopesym); + Dsymbol *insert(Dsymbol *s); + + ClassDeclaration *getClassScope(); + AggregateDeclaration *getStructClassScope(); + void setNoFree(); +}; + +#endif /* DMD_SCOPE_H */ diff -r 1853dcd9b944 -r e961851fb8be dmd/statement.c --- a/dmd/statement.c Fri Apr 03 17:02:52 2009 +0200 +++ b/dmd/statement.c Fri Apr 03 17:59:34 2009 +0200 @@ -27,6 +27,7 @@ #include "hdrgen.h" #include "parse.h" #include "template.h" +#include "attrib.h" /******************************** Statement ***************************/ @@ -207,6 +208,10 @@ exp = resolveProperties(sc, exp); exp->checkSideEffect(0); exp = exp->optimize(0); + if (exp->op == TOKdeclaration && !isDeclarationStatement()) + { Statement *s = new DeclarationStatement(loc, exp); + return s; + } //exp = exp->optimize(isDeclarationStatement() ? WANTvalue : 0); } return this; @@ -576,6 +581,82 @@ } +/******************************** CompoundDeclarationStatement ***************************/ + +CompoundDeclarationStatement::CompoundDeclarationStatement(Loc loc, Statements *s) + : CompoundStatement(loc, s) +{ + statements = s; +} + +Statement *CompoundDeclarationStatement::syntaxCopy() +{ + Statements *a = new Statements(); + a->setDim(statements->dim); + for (size_t i = 0; i < statements->dim; i++) + { Statement *s = (Statement *)statements->data[i]; + if (s) + s = s->syntaxCopy(); + a->data[i] = s; + } + CompoundDeclarationStatement *cs = new CompoundDeclarationStatement(loc, a); + return cs; +} + +void CompoundDeclarationStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) +{ + int nwritten = 0; + for (int i = 0; i < statements->dim; i++) + { Statement *s = (Statement *) statements->data[i]; + if (s) + { DeclarationStatement *ds = s->isDeclarationStatement(); + assert(ds); + DeclarationExp *de = (DeclarationExp *)ds->exp; + assert(de->op == TOKdeclaration); + Declaration *d = de->declaration->isDeclaration(); + assert(d); + VarDeclaration *v = d->isVarDeclaration(); + if (v) + { + /* This essentially copies the part of VarDeclaration::toCBuffer() + * that does not print the type. + * Should refactor this. + */ + if (nwritten) + { + buf->writeByte(','); + buf->writestring(v->ident->toChars()); + } + else + { + StorageClassDeclaration::stcToCBuffer(buf, v->storage_class); + if (v->type) + v->type->toCBuffer(buf, v->ident, hgs); + else + buf->writestring(v->ident->toChars()); + } + + if (v->init) + { buf->writestring(" = "); +#if DMDV2 + ExpInitializer *ie = v->init->isExpInitializer(); + if (ie && (ie->exp->op == TOKconstruct || ie->exp->op == TOKblit)) + ((AssignExp *)ie->exp)->e2->toCBuffer(buf, hgs); + else +#endif + v->init->toCBuffer(buf, hgs); + } + } + else + d->toCBuffer(buf, hgs); + nwritten++; + } + } + buf->writeByte(';'); + if (!hgs->FLinit.init) + buf->writenl(); +} + /**************************** UnrolledLoopStatement ***************************/ UnrolledLoopStatement::UnrolledLoopStatement(Loc loc, Statements *s) @@ -889,6 +970,7 @@ return result; } + int WhileStatement::comeFrom() { if (body) @@ -974,6 +1056,7 @@ return result; } + int DoStatement::comeFrom() { if (body) @@ -1103,6 +1186,7 @@ return result; } + int ForStatement::comeFrom() { //printf("ForStatement::comeFrom()\n"); @@ -1120,11 +1204,7 @@ if (init) { hgs->FLinit.init++; - hgs->FLinit.decl = 0; init->toCBuffer(buf, hgs); - if (hgs->FLinit.decl > 0) - buf->writebyte(';'); - hgs->FLinit.decl = 0; hgs->FLinit.init--; } else @@ -1249,17 +1329,16 @@ if (arg->storageClass & (STCout | STCref | STClazy)) error("no storage class for key %s", arg->ident->toChars()); TY keyty = arg->type->ty; - if (global.params.is64bit) - { - if (keyty != Tint32 && keyty != Tuns32 && keyty != Tint64 && keyty != Tuns64) - { - error("foreach: key type must be int, uint, long or ulong, not %s", key->type->toChars()); - } - } - else if (keyty != Tint32 && keyty != Tuns32) - { - error("foreach: key type must be int or uint, not %s", key->type->toChars()); - } + if (keyty != Tint32 && keyty != Tuns32) + { + if (global.params.is64bit) + { + if (keyty != Tint64 && keyty != Tuns64) + error("foreach: key type must be int or uint, long or ulong, not %s", arg->type->toChars()); + } + else + error("foreach: key type must be int or uint, not %s", arg->type->toChars()); + } Initializer *ie = new ExpInitializer(0, new IntegerExp(k)); VarDeclaration *var = new VarDeclaration(loc, arg->type, arg->ident, ie); var->storage_class |= STCconst; @@ -1391,20 +1470,16 @@ tab->toChars(), value->type->toChars()); } - if (key) - { - if (global.params.is64bit) - { - if (key->type->ty != Tint32 && key->type->ty != Tuns32 && key->type->ty != Tint64 && key->type->ty != Tuns64) - { - error("foreach: key type must be int, uint, long or ulong, not %s", key->type->toChars()); - } - } - else if (key->type->ty != Tint32 && key->type->ty != Tuns32) - { - error("foreach: key type must be int or uint, not %s", key->type->toChars()); - } - } + if (key && key->type->ty != Tint32 && key->type->ty != Tuns32) + { + if (global.params.is64bit) + { + if (key->type->ty != Tint64 && key->type->ty != Tuns64) + error("foreach: key type must be int or uint, long or ulong, not %s", key->type->toChars()); + } + else + error("foreach: key type must be int or uint, not %s", key->type->toChars()); + } if (key && key->storage_class & (STCout | STCref)) error("foreach: key cannot be out or ref"); diff -r 1853dcd9b944 -r e961851fb8be dmd/statement.h --- a/dmd/statement.h Fri Apr 03 17:02:52 2009 +0200 +++ b/dmd/statement.h Fri Apr 03 17:59:34 2009 +0200 @@ -1,882 +1,889 @@ - -// Compiler implementation of the D programming language -// Copyright (c) 1999-2008 by Digital Mars -// All Rights Reserved -// written by Walter Bright -// 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. - -#ifndef DMD_STATEMENT_H -#define DMD_STATEMENT_H - -#ifdef __DMC__ -#pragma once -#endif /* __DMC__ */ - -#include "root.h" - -#include "arraytypes.h" -#include "dsymbol.h" -#include "lexer.h" - -struct OutBuffer; -struct Scope; -struct Expression; -struct LabelDsymbol; -struct Identifier; -struct IfStatement; -struct DeclarationStatement; -struct DefaultStatement; -struct VarDeclaration; -struct Condition; -struct Module; -struct Token; -struct InlineCostState; -struct InlineDoState; -struct InlineScanState; -struct ReturnStatement; -struct CompoundStatement; -struct Argument; -struct StaticAssert; -struct AsmStatement; -struct AsmBlockStatement; -struct GotoStatement; -struct ScopeStatement; -struct TryCatchStatement; -struct TryFinallyStatement; -struct HdrGenState; -struct InterState; -struct CaseStatement; -struct LabelStatement; -struct VolatileStatement; -struct SynchronizedStatement; - -enum TOK; - -namespace llvm -{ - class Value; - class BasicBlock; - class ConstantInt; -} - -// Back end -struct IRState; -struct Blockx; -#if IN_LLVM -struct DValue; -typedef DValue elem; -#endif - -#if IN_GCC -union tree_node; typedef union tree_node block; -//union tree_node; typedef union tree_node elem; -#else -struct block; -//struct elem; -#endif -struct code; - -/* How a statement exits; this is returned by blockExit() - */ -enum BE -{ - BEnone = 0, - BEfallthru = 1, - BEthrow = 2, - BEreturn = 4, - BEgoto = 8, - BEhalt = 0x10, - BEbreak = 0x20, - BEcontinue = 0x40, - BEany = (BEfallthru | BEthrow | BEreturn | BEgoto | BEhalt), -}; - -struct Statement : Object -{ - Loc loc; - - Statement(Loc loc); - virtual Statement *syntaxCopy(); - - void print(); - char *toChars(); - - void error(const char *format, ...); - void warning(const char *format, ...); - virtual void toCBuffer(OutBuffer *buf, HdrGenState *hgs); - virtual TryCatchStatement *isTryCatchStatement() { return NULL; } - virtual GotoStatement *isGotoStatement() { return NULL; } - virtual AsmStatement *isAsmStatement() { return NULL; } - virtual AsmBlockStatement *isAsmBlockStatement() { return NULL; } -#ifdef _DH - int incontract; -#endif - virtual ScopeStatement *isScopeStatement() { return NULL; } - virtual Statement *semantic(Scope *sc); - Statement *semanticScope(Scope *sc, Statement *sbreak, Statement *scontinue); - virtual int hasBreak(); - virtual int hasContinue(); - virtual int usesEH(); - virtual int blockExit(); - virtual int comeFrom(); - virtual void scopeCode(Statement **sentry, Statement **sexit, Statement **sfinally); - virtual Statements *flatten(Scope *sc); - virtual Expression *interpret(InterState *istate); - - virtual int inlineCost(InlineCostState *ics); - virtual Expression *doInline(InlineDoState *ids); - virtual Statement *inlineScan(InlineScanState *iss); - - // Back end - virtual void toIR(IRState *irs); - - // Avoid dynamic_cast - virtual DeclarationStatement *isDeclarationStatement() { return NULL; } - virtual CompoundStatement *isCompoundStatement() { return NULL; } - virtual ReturnStatement *isReturnStatement() { return NULL; } - virtual IfStatement *isIfStatement() { return NULL; } - virtual CaseStatement* isCaseStatement() { return NULL; } - - // LDC - virtual void toNakedIR(IRState *irs); - virtual AsmBlockStatement* endsWithAsm(); -}; - -struct ExpStatement : Statement -{ - Expression *exp; - - ExpStatement(Loc loc, Expression *exp); - Statement *syntaxCopy(); - void toCBuffer(OutBuffer *buf, HdrGenState *hgs); - Statement *semantic(Scope *sc); - Expression *interpret(InterState *istate); - int blockExit(); - - int inlineCost(InlineCostState *ics); - Expression *doInline(InlineDoState *ids); - Statement *inlineScan(InlineScanState *iss); - - void toIR(IRState *irs); - - // LDC - void toNakedIR(IRState *irs); -}; - -struct CompileStatement : Statement -{ - Expression *exp; - - CompileStatement(Loc loc, Expression *exp); - Statement *syntaxCopy(); - void toCBuffer(OutBuffer *buf, HdrGenState *hgs); - Statements *flatten(Scope *sc); - Statement *semantic(Scope *sc); -}; - -struct DeclarationStatement : ExpStatement -{ - // Doing declarations as an expression, rather than a statement, - // makes inlining functions much easier. - - DeclarationStatement(Loc loc, Dsymbol *s); - DeclarationStatement(Loc loc, Expression *exp); - Statement *syntaxCopy(); - void toCBuffer(OutBuffer *buf, HdrGenState *hgs); - void scopeCode(Statement **sentry, Statement **sexit, Statement **sfinally); - - DeclarationStatement *isDeclarationStatement() { return this; } -}; - -struct CompoundStatement : Statement -{ - Statements *statements; - - CompoundStatement(Loc loc, Statements *s); - CompoundStatement(Loc loc, Statement *s1, Statement *s2); - virtual Statement *syntaxCopy(); - void toCBuffer(OutBuffer *buf, HdrGenState *hgs); - virtual Statement *semantic(Scope *sc); - int usesEH(); - int blockExit(); - int comeFrom(); - virtual Statements *flatten(Scope *sc); - ReturnStatement *isReturnStatement(); - Expression *interpret(InterState *istate); - - int inlineCost(InlineCostState *ics); - Expression *doInline(InlineDoState *ids); - Statement *inlineScan(InlineScanState *iss); - - virtual void toIR(IRState *irs); - - // LDC - virtual void toNakedIR(IRState *irs); - virtual AsmBlockStatement* endsWithAsm(); - - virtual CompoundStatement *isCompoundStatement() { return this; } -}; - -/* The purpose of this is so that continue will go to the next - * of the statements, and break will go to the end of the statements. - */ -struct UnrolledLoopStatement : Statement -{ - Statements *statements; - - UnrolledLoopStatement(Loc loc, Statements *statements); - Statement *syntaxCopy(); - Statement *semantic(Scope *sc); - int hasBreak(); - int hasContinue(); - int usesEH(); - int blockExit(); - int comeFrom(); - Expression *interpret(InterState *istate); - void toCBuffer(OutBuffer *buf, HdrGenState *hgs); - - int inlineCost(InlineCostState *ics); - Expression *doInline(InlineDoState *ids); - Statement *inlineScan(InlineScanState *iss); - - void toIR(IRState *irs); -}; - -struct ScopeStatement : Statement -{ - Statement *statement; - - ScopeStatement(Loc loc, Statement *s); - Statement *syntaxCopy(); - void toCBuffer(OutBuffer *buf, HdrGenState *hgs); - ScopeStatement *isScopeStatement() { return this; } - Statement *semantic(Scope *sc); - int hasBreak(); - int hasContinue(); - int usesEH(); - int blockExit(); - int comeFrom(); - Expression *interpret(InterState *istate); - - Statement *inlineScan(InlineScanState *iss); - - void toIR(IRState *irs); -}; - -struct WhileStatement : Statement -{ - Expression *condition; - Statement *body; - - WhileStatement(Loc loc, Expression *c, Statement *b); - Statement *syntaxCopy(); - Statement *semantic(Scope *sc); - int hasBreak(); - int hasContinue(); - int usesEH(); - int blockExit(); - int comeFrom(); - Expression *interpret(InterState *istate); - void toCBuffer(OutBuffer *buf, HdrGenState *hgs); - - Statement *inlineScan(InlineScanState *iss); - - void toIR(IRState *irs); -}; - -struct DoStatement : Statement -{ - Statement *body; - Expression *condition; - - DoStatement(Loc loc, Statement *b, Expression *c); - Statement *syntaxCopy(); - Statement *semantic(Scope *sc); - int hasBreak(); - int hasContinue(); - int usesEH(); - int blockExit(); - int comeFrom(); - Expression *interpret(InterState *istate); - void toCBuffer(OutBuffer *buf, HdrGenState *hgs); - - Statement *inlineScan(InlineScanState *iss); - - void toIR(IRState *irs); -}; - -struct ForStatement : Statement -{ - Statement *init; - Expression *condition; - Expression *increment; - Statement *body; - - ForStatement(Loc loc, Statement *init, Expression *condition, Expression *increment, Statement *body); - Statement *syntaxCopy(); - Statement *semantic(Scope *sc); - void scopeCode(Statement **sentry, Statement **sexit, Statement **sfinally); - int hasBreak(); - int hasContinue(); - int usesEH(); - int blockExit(); - int comeFrom(); - Expression *interpret(InterState *istate); - void toCBuffer(OutBuffer *buf, HdrGenState *hgs); - - Statement *inlineScan(InlineScanState *iss); - - void toIR(IRState *irs); -}; - -struct ForeachStatement : Statement -{ - enum TOK op; // TOKforeach or TOKforeach_reverse - Arguments *arguments; // array of Argument*'s - Expression *aggr; - Statement *body; - - VarDeclaration *key; - VarDeclaration *value; - - FuncDeclaration *func; // function we're lexically in - - Array cases; // put breaks, continues, gotos and returns here - Array gotos; // forward referenced goto's go here - - ForeachStatement(Loc loc, enum TOK op, Arguments *arguments, Expression *aggr, Statement *body); - Statement *syntaxCopy(); - Statement *semantic(Scope *sc); - int hasBreak(); - int hasContinue(); - int usesEH(); - int blockExit(); - int comeFrom(); - Expression *interpret(InterState *istate); - void toCBuffer(OutBuffer *buf, HdrGenState *hgs); - - Statement *inlineScan(InlineScanState *iss); - - void toIR(IRState *irs); -}; - -#if DMDV2 -struct ForeachRangeStatement : Statement -{ - enum TOK op; // TOKforeach or TOKforeach_reverse - Argument *arg; // loop index variable - Expression *lwr; - Expression *upr; - Statement *body; - - VarDeclaration *key; - - ForeachRangeStatement(Loc loc, enum TOK op, Argument *arg, - Expression *lwr, Expression *upr, Statement *body); - Statement *syntaxCopy(); - Statement *semantic(Scope *sc); - int hasBreak(); - int hasContinue(); - int usesEH(); - int blockExit(); - int comeFrom(); - Expression *interpret(InterState *istate); - void toCBuffer(OutBuffer *buf, HdrGenState *hgs); - - Statement *inlineScan(InlineScanState *iss); - - void toIR(IRState *irs); -}; -#endif - -struct IfStatement : Statement -{ - Argument *arg; - Expression *condition; - Statement *ifbody; - Statement *elsebody; - - VarDeclaration *match; // for MatchExpression results - - IfStatement(Loc loc, Argument *arg, Expression *condition, Statement *ifbody, Statement *elsebody); - Statement *syntaxCopy(); - Statement *semantic(Scope *sc); - Expression *interpret(InterState *istate); - void toCBuffer(OutBuffer *buf, HdrGenState *hgs); - int usesEH(); - int blockExit(); - IfStatement *isIfStatement() { return this; } - - int inlineCost(InlineCostState *ics); - Expression *doInline(InlineDoState *ids); - Statement *inlineScan(InlineScanState *iss); - - void toIR(IRState *irs); -}; - -struct ConditionalStatement : Statement -{ - Condition *condition; - Statement *ifbody; - Statement *elsebody; - - ConditionalStatement(Loc loc, Condition *condition, Statement *ifbody, Statement *elsebody); - Statement *syntaxCopy(); - Statement *semantic(Scope *sc); - Statements *flatten(Scope *sc); - int usesEH(); - int blockExit(); - - void toCBuffer(OutBuffer *buf, HdrGenState *hgs); -}; - -struct PragmaStatement : Statement -{ - Identifier *ident; - Expressions *args; // array of Expression's - Statement *body; - - PragmaStatement(Loc loc, Identifier *ident, Expressions *args, Statement *body); - Statement *syntaxCopy(); - Statement *semantic(Scope *sc); - int usesEH(); - int blockExit(); - - void toCBuffer(OutBuffer *buf, HdrGenState *hgs); -}; - -struct StaticAssertStatement : Statement -{ - StaticAssert *sa; - - StaticAssertStatement(StaticAssert *sa); - Statement *syntaxCopy(); - Statement *semantic(Scope *sc); - - void toCBuffer(OutBuffer *buf, HdrGenState *hgs); -}; - -struct SwitchStatement : Statement -{ - Expression *condition; - Statement *body; - - DefaultStatement *sdefault; - - Array gotoCases; // array of unresolved GotoCaseStatement's - Array *cases; // array of CaseStatement's - int hasNoDefault; // !=0 if no default statement - - // LDC - Statement *enclosingScopeExit; - - SwitchStatement(Loc loc, Expression *c, Statement *b); - Statement *syntaxCopy(); - Statement *semantic(Scope *sc); - int hasBreak(); - int usesEH(); - int blockExit(); - Expression *interpret(InterState *istate); - void toCBuffer(OutBuffer *buf, HdrGenState *hgs); - - Statement *inlineScan(InlineScanState *iss); - - void toIR(IRState *irs); -}; - -struct CaseStatement : Statement -{ - Expression *exp; - Statement *statement; - int index; // which case it is (since we sort this) - block *cblock; // back end: label for the block - - // LDC - Statement *enclosingScopeExit; - - CaseStatement(Loc loc, Expression *exp, Statement *s); - Statement *syntaxCopy(); - Statement *semantic(Scope *sc); - int compare(Object *obj); - int usesEH(); - int blockExit(); - int comeFrom(); - Expression *interpret(InterState *istate); - void toCBuffer(OutBuffer *buf, HdrGenState *hgs); - - Statement *inlineScan(InlineScanState *iss); - - void toIR(IRState *irs); - - CaseStatement* isCaseStatement() { return this; } - - // LDC - llvm::BasicBlock* bodyBB; - llvm::ConstantInt* llvmIdx; -}; - -struct DefaultStatement : Statement -{ - Statement *statement; -#if IN_GCC - block *cblock; // back end: label for the block -#endif - - // LDC - Statement *enclosingScopeExit; - - DefaultStatement(Loc loc, Statement *s); - Statement *syntaxCopy(); - Statement *semantic(Scope *sc); - int usesEH(); - int blockExit(); - int comeFrom(); - Expression *interpret(InterState *istate); - void toCBuffer(OutBuffer *buf, HdrGenState *hgs); - - Statement *inlineScan(InlineScanState *iss); - - void toIR(IRState *irs); - - // LDC - llvm::BasicBlock* bodyBB; -}; - -struct GotoDefaultStatement : Statement -{ - SwitchStatement *sw; - - GotoDefaultStatement(Loc loc); - Statement *syntaxCopy(); - Statement *semantic(Scope *sc); - Expression *interpret(InterState *istate); - int blockExit(); - void toCBuffer(OutBuffer *buf, HdrGenState *hgs); - - void toIR(IRState *irs); -}; - -struct GotoCaseStatement : Statement -{ - Expression *exp; // NULL, or which case to goto - CaseStatement *cs; // case statement it resolves to - SwitchStatement *sw; - - GotoCaseStatement(Loc loc, Expression *exp); - Statement *syntaxCopy(); - Statement *semantic(Scope *sc); - Expression *interpret(InterState *istate); - int blockExit(); - void toCBuffer(OutBuffer *buf, HdrGenState *hgs); - - void toIR(IRState *irs); -}; - -struct SwitchErrorStatement : Statement -{ - SwitchErrorStatement(Loc loc); - int blockExit(); - void toCBuffer(OutBuffer *buf, HdrGenState *hgs); - - void toIR(IRState *irs); -}; - -struct ReturnStatement : Statement -{ - Expression *exp; - - ReturnStatement(Loc loc, Expression *exp); - Statement *syntaxCopy(); - void toCBuffer(OutBuffer *buf, HdrGenState *hgs); - Statement *semantic(Scope *sc); - int blockExit(); - Expression *interpret(InterState *istate); - - int inlineCost(InlineCostState *ics); - Expression *doInline(InlineDoState *ids); - Statement *inlineScan(InlineScanState *iss); - - void toIR(IRState *irs); - - ReturnStatement *isReturnStatement() { return this; } -}; - -struct BreakStatement : Statement -{ - Identifier *ident; - - BreakStatement(Loc loc, Identifier *ident); - Statement *syntaxCopy(); - Statement *semantic(Scope *sc); - Expression *interpret(InterState *istate); - int blockExit(); - void toCBuffer(OutBuffer *buf, HdrGenState *hgs); - - void toIR(IRState *irs); - - // LDC: only set if ident is set: label statement to jump to - LabelStatement *target; -}; - -struct ContinueStatement : Statement -{ - Identifier *ident; - - ContinueStatement(Loc loc, Identifier *ident); - Statement *syntaxCopy(); - Statement *semantic(Scope *sc); - Expression *interpret(InterState *istate); - int blockExit(); - void toCBuffer(OutBuffer *buf, HdrGenState *hgs); - - void toIR(IRState *irs); - - // LDC: only set if ident is set: label statement to jump to - LabelStatement *target; -}; - -struct SynchronizedStatement : Statement -{ - Expression *exp; - Statement *body; - - SynchronizedStatement(Loc loc, Expression *exp, Statement *body); - Statement *syntaxCopy(); - Statement *semantic(Scope *sc); - int hasBreak(); - int hasContinue(); - int usesEH(); - int blockExit(); - void toCBuffer(OutBuffer *buf, HdrGenState *hgs); - - Statement *inlineScan(InlineScanState *iss); - -// Back end - elem *esync; - SynchronizedStatement(Loc loc, elem *esync, Statement *body); - void toIR(IRState *irs); - llvm::Value* llsync; -}; - -struct WithStatement : Statement -{ - Expression *exp; - Statement *body; - VarDeclaration *wthis; - - WithStatement(Loc loc, Expression *exp, Statement *body); - Statement *syntaxCopy(); - Statement *semantic(Scope *sc); - void toCBuffer(OutBuffer *buf, HdrGenState *hgs); - int usesEH(); - int blockExit(); - - Statement *inlineScan(InlineScanState *iss); - - void toIR(IRState *irs); -}; - -struct TryCatchStatement : Statement -{ - Statement *body; - Array *catches; - - TryCatchStatement(Loc loc, Statement *body, Array *catches); - Statement *syntaxCopy(); - Statement *semantic(Scope *sc); - int hasBreak(); - int usesEH(); - int blockExit(); - - Statement *inlineScan(InlineScanState *iss); - - void toIR(IRState *irs); - void toCBuffer(OutBuffer *buf, HdrGenState *hgs); - TryCatchStatement *isTryCatchStatement() { return this; } -}; - -struct Catch : Object -{ - Loc loc; - Type *type; - Identifier *ident; - VarDeclaration *var; - Statement *handler; - - Catch(Loc loc, Type *t, Identifier *id, Statement *handler); - Catch *syntaxCopy(); - void semantic(Scope *sc); - int blockExit(); - void toCBuffer(OutBuffer *buf, HdrGenState *hgs); -}; - -struct TryFinallyStatement : Statement -{ - Statement *body; - Statement *finalbody; - - TryFinallyStatement(Loc loc, Statement *body, Statement *finalbody); - Statement *syntaxCopy(); - void toCBuffer(OutBuffer *buf, HdrGenState *hgs); - Statement *semantic(Scope *sc); - int hasBreak(); - int hasContinue(); - int usesEH(); - int blockExit(); - - Statement *inlineScan(InlineScanState *iss); - - void toIR(IRState *irs); -}; - -struct OnScopeStatement : Statement -{ - TOK tok; - Statement *statement; - - OnScopeStatement(Loc loc, TOK tok, Statement *statement); - Statement *syntaxCopy(); - int blockExit(); - void toCBuffer(OutBuffer *buf, HdrGenState *hgs); - Statement *semantic(Scope *sc); - int usesEH(); - void scopeCode(Statement **sentry, Statement **sexit, Statement **sfinally); - - void toIR(IRState *irs); -}; - -struct ThrowStatement : Statement -{ - Expression *exp; - - ThrowStatement(Loc loc, Expression *exp); - Statement *syntaxCopy(); - Statement *semantic(Scope *sc); - void toCBuffer(OutBuffer *buf, HdrGenState *hgs); - int blockExit(); - - Statement *inlineScan(InlineScanState *iss); - - void toIR(IRState *irs); -}; - -struct VolatileStatement : Statement -{ - Statement *statement; - - VolatileStatement(Loc loc, Statement *statement); - Statement *syntaxCopy(); - Statement *semantic(Scope *sc); - Statements *flatten(Scope *sc); - int blockExit(); - void toCBuffer(OutBuffer *buf, HdrGenState *hgs); - - Statement *inlineScan(InlineScanState *iss); - - void toIR(IRState *irs); -}; - -struct GotoStatement : Statement -{ - Identifier *ident; - LabelDsymbol *label; - TryFinallyStatement *enclosingFinally; - Statement* enclosingScopeExit; - - GotoStatement(Loc loc, Identifier *ident); - Statement *syntaxCopy(); - Statement *semantic(Scope *sc); - int blockExit(); - Expression *interpret(InterState *istate); - - void toIR(IRState *irs); - void toCBuffer(OutBuffer *buf, HdrGenState *hgs); - GotoStatement *isGotoStatement() { return this; } -}; - -struct LabelStatement : Statement -{ - Identifier *ident; - Statement *statement; - TryFinallyStatement *enclosingFinally; - Statement* enclosingScopeExit; - block *lblock; // back end - int isReturnLabel; - - LabelStatement(Loc loc, Identifier *ident, Statement *statement); - Statement *syntaxCopy(); - Statement *semantic(Scope *sc); - Statements *flatten(Scope *sc); - int usesEH(); - int blockExit(); - int comeFrom(); - Expression *interpret(InterState *istate); - void toCBuffer(OutBuffer *buf, HdrGenState *hgs); - - Statement *inlineScan(InlineScanState *iss); - - void toIR(IRState *irs); - - // LDC - bool asmLabel; // for labels inside inline assembler - void toNakedIR(IRState *irs); -}; - -struct LabelDsymbol : Dsymbol -{ - LabelStatement *statement; - - LabelDsymbol(Identifier *ident); - LabelDsymbol *isLabel(); -}; - -struct AsmStatement : Statement -{ - Token *tokens; - code *asmcode; - unsigned asmalign; // alignment of this statement - unsigned refparam; // !=0 if function parameter is referenced - unsigned naked; // !=0 if function is to be naked - - AsmStatement(Loc loc, Token *tokens); - Statement *syntaxCopy(); - Statement *semantic(Scope *sc); - int blockExit(); - int comeFrom(); - - void toCBuffer(OutBuffer *buf, HdrGenState *hgs); - virtual AsmStatement *isAsmStatement() { return this; } - - void toIR(IRState *irs); - - // LDC - // non-zero if this is a branch, contains the target labels identifier - Identifier* isBranchToLabel; - - void toNakedIR(IRState *irs); -}; - -struct AsmBlockStatement : CompoundStatement -{ - TryFinallyStatement* enclosingFinally; - Statement* enclosingScopeExit; - - AsmBlockStatement(Loc loc, Statements *s); - Statements *flatten(Scope *sc); - Statement *syntaxCopy(); - Statement *semantic(Scope *sc); - - CompoundStatement *isCompoundStatement() { return NULL; } - AsmBlockStatement *isAsmBlockStatement() { return this; } - - void toIR(IRState *irs); - void toNakedIR(IRState *irs); - AsmBlockStatement* endsWithAsm(); - - llvm::Value* abiret; -}; - -#endif /* DMD_STATEMENT_H */ + +// Compiler implementation of the D programming language +// Copyright (c) 1999-2008 by Digital Mars +// All Rights Reserved +// written by Walter Bright +// 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. + +#ifndef DMD_STATEMENT_H +#define DMD_STATEMENT_H + +#ifdef __DMC__ +#pragma once +#endif /* __DMC__ */ + +#include "root.h" + +#include "arraytypes.h" +#include "dsymbol.h" +#include "lexer.h" + +struct OutBuffer; +struct Scope; +struct Expression; +struct LabelDsymbol; +struct Identifier; +struct IfStatement; +struct DeclarationStatement; +struct DefaultStatement; +struct VarDeclaration; +struct Condition; +struct Module; +struct Token; +struct InlineCostState; +struct InlineDoState; +struct InlineScanState; +struct ReturnStatement; +struct CompoundStatement; +struct Argument; +struct StaticAssert; +struct AsmStatement; +struct AsmBlockStatement; +struct GotoStatement; +struct ScopeStatement; +struct TryCatchStatement; +struct TryFinallyStatement; +struct HdrGenState; +struct InterState; +struct CaseStatement; +struct LabelStatement; +struct VolatileStatement; +struct SynchronizedStatement; + +enum TOK; + +namespace llvm +{ + class Value; + class BasicBlock; + class ConstantInt; +} + +// Back end +struct IRState; +struct Blockx; +#if IN_LLVM +struct DValue; +typedef DValue elem; +#endif + +#if IN_GCC +union tree_node; typedef union tree_node block; +//union tree_node; typedef union tree_node elem; +#else +struct block; +//struct elem; +#endif +struct code; + +/* How a statement exits; this is returned by blockExit() + */ +enum BE +{ + BEnone = 0, + BEfallthru = 1, + BEthrow = 2, + BEreturn = 4, + BEgoto = 8, + BEhalt = 0x10, + BEbreak = 0x20, + BEcontinue = 0x40, + BEany = (BEfallthru | BEthrow | BEreturn | BEgoto | BEhalt), +}; + +struct Statement : Object +{ + Loc loc; + + Statement(Loc loc); + virtual Statement *syntaxCopy(); + + void print(); + char *toChars(); + + void error(const char *format, ...); + void warning(const char *format, ...); + virtual void toCBuffer(OutBuffer *buf, HdrGenState *hgs); + virtual TryCatchStatement *isTryCatchStatement() { return NULL; } + virtual GotoStatement *isGotoStatement() { return NULL; } + virtual AsmStatement *isAsmStatement() { return NULL; } + virtual AsmBlockStatement *isAsmBlockStatement() { return NULL; } +#ifdef _DH + int incontract; +#endif + virtual ScopeStatement *isScopeStatement() { return NULL; } + virtual Statement *semantic(Scope *sc); + Statement *semanticScope(Scope *sc, Statement *sbreak, Statement *scontinue); + virtual int hasBreak(); + virtual int hasContinue(); + virtual int usesEH(); + virtual int blockExit(); + virtual int comeFrom(); + virtual void scopeCode(Statement **sentry, Statement **sexit, Statement **sfinally); + virtual Statements *flatten(Scope *sc); + virtual Expression *interpret(InterState *istate); + + virtual int inlineCost(InlineCostState *ics); + virtual Expression *doInline(InlineDoState *ids); + virtual Statement *inlineScan(InlineScanState *iss); + + // Back end + virtual void toIR(IRState *irs); + + // Avoid dynamic_cast + virtual DeclarationStatement *isDeclarationStatement() { return NULL; } + virtual CompoundStatement *isCompoundStatement() { return NULL; } + virtual ReturnStatement *isReturnStatement() { return NULL; } + virtual IfStatement *isIfStatement() { return NULL; } + virtual CaseStatement* isCaseStatement() { return NULL; } + + // LDC + virtual void toNakedIR(IRState *irs); + virtual AsmBlockStatement* endsWithAsm(); +}; + +struct ExpStatement : Statement +{ + Expression *exp; + + ExpStatement(Loc loc, Expression *exp); + Statement *syntaxCopy(); + void toCBuffer(OutBuffer *buf, HdrGenState *hgs); + Statement *semantic(Scope *sc); + Expression *interpret(InterState *istate); + int blockExit(); + + int inlineCost(InlineCostState *ics); + Expression *doInline(InlineDoState *ids); + Statement *inlineScan(InlineScanState *iss); + + void toIR(IRState *irs); + + // LDC + void toNakedIR(IRState *irs); +}; + +struct CompileStatement : Statement +{ + Expression *exp; + + CompileStatement(Loc loc, Expression *exp); + Statement *syntaxCopy(); + void toCBuffer(OutBuffer *buf, HdrGenState *hgs); + Statements *flatten(Scope *sc); + Statement *semantic(Scope *sc); +}; + +struct DeclarationStatement : ExpStatement +{ + // Doing declarations as an expression, rather than a statement, + // makes inlining functions much easier. + + DeclarationStatement(Loc loc, Dsymbol *s); + DeclarationStatement(Loc loc, Expression *exp); + Statement *syntaxCopy(); + void toCBuffer(OutBuffer *buf, HdrGenState *hgs); + void scopeCode(Statement **sentry, Statement **sexit, Statement **sfinally); + + DeclarationStatement *isDeclarationStatement() { return this; } +}; + +struct CompoundStatement : Statement +{ + Statements *statements; + + CompoundStatement(Loc loc, Statements *s); + CompoundStatement(Loc loc, Statement *s1, Statement *s2); + virtual Statement *syntaxCopy(); + void toCBuffer(OutBuffer *buf, HdrGenState *hgs); + virtual Statement *semantic(Scope *sc); + int usesEH(); + int blockExit(); + int comeFrom(); + virtual Statements *flatten(Scope *sc); + ReturnStatement *isReturnStatement(); + Expression *interpret(InterState *istate); + + int inlineCost(InlineCostState *ics); + Expression *doInline(InlineDoState *ids); + Statement *inlineScan(InlineScanState *iss); + + virtual void toIR(IRState *irs); + + // LDC + virtual void toNakedIR(IRState *irs); + virtual AsmBlockStatement* endsWithAsm(); + + virtual CompoundStatement *isCompoundStatement() { return this; } +}; + +struct CompoundDeclarationStatement : CompoundStatement +{ + CompoundDeclarationStatement(Loc loc, Statements *s); + Statement *syntaxCopy(); + void toCBuffer(OutBuffer *buf, HdrGenState *hgs); +}; + +/* The purpose of this is so that continue will go to the next + * of the statements, and break will go to the end of the statements. + */ +struct UnrolledLoopStatement : Statement +{ + Statements *statements; + + UnrolledLoopStatement(Loc loc, Statements *statements); + Statement *syntaxCopy(); + Statement *semantic(Scope *sc); + int hasBreak(); + int hasContinue(); + int usesEH(); + int blockExit(); + int comeFrom(); + Expression *interpret(InterState *istate); + void toCBuffer(OutBuffer *buf, HdrGenState *hgs); + + int inlineCost(InlineCostState *ics); + Expression *doInline(InlineDoState *ids); + Statement *inlineScan(InlineScanState *iss); + + void toIR(IRState *irs); +}; + +struct ScopeStatement : Statement +{ + Statement *statement; + + ScopeStatement(Loc loc, Statement *s); + Statement *syntaxCopy(); + void toCBuffer(OutBuffer *buf, HdrGenState *hgs); + ScopeStatement *isScopeStatement() { return this; } + Statement *semantic(Scope *sc); + int hasBreak(); + int hasContinue(); + int usesEH(); + int blockExit(); + int comeFrom(); + Expression *interpret(InterState *istate); + + Statement *inlineScan(InlineScanState *iss); + + void toIR(IRState *irs); +}; + +struct WhileStatement : Statement +{ + Expression *condition; + Statement *body; + + WhileStatement(Loc loc, Expression *c, Statement *b); + Statement *syntaxCopy(); + Statement *semantic(Scope *sc); + int hasBreak(); + int hasContinue(); + int usesEH(); + int blockExit(); + int comeFrom(); + Expression *interpret(InterState *istate); + void toCBuffer(OutBuffer *buf, HdrGenState *hgs); + + Statement *inlineScan(InlineScanState *iss); + + void toIR(IRState *irs); +}; + +struct DoStatement : Statement +{ + Statement *body; + Expression *condition; + + DoStatement(Loc loc, Statement *b, Expression *c); + Statement *syntaxCopy(); + Statement *semantic(Scope *sc); + int hasBreak(); + int hasContinue(); + int usesEH(); + int blockExit(); + int comeFrom(); + Expression *interpret(InterState *istate); + void toCBuffer(OutBuffer *buf, HdrGenState *hgs); + + Statement *inlineScan(InlineScanState *iss); + + void toIR(IRState *irs); +}; + +struct ForStatement : Statement +{ + Statement *init; + Expression *condition; + Expression *increment; + Statement *body; + + ForStatement(Loc loc, Statement *init, Expression *condition, Expression *increment, Statement *body); + Statement *syntaxCopy(); + Statement *semantic(Scope *sc); + void scopeCode(Statement **sentry, Statement **sexit, Statement **sfinally); + int hasBreak(); + int hasContinue(); + int usesEH(); + int blockExit(); + int comeFrom(); + Expression *interpret(InterState *istate); + void toCBuffer(OutBuffer *buf, HdrGenState *hgs); + + Statement *inlineScan(InlineScanState *iss); + + void toIR(IRState *irs); +}; + +struct ForeachStatement : Statement +{ + enum TOK op; // TOKforeach or TOKforeach_reverse + Arguments *arguments; // array of Argument*'s + Expression *aggr; + Statement *body; + + VarDeclaration *key; + VarDeclaration *value; + + FuncDeclaration *func; // function we're lexically in + + Array cases; // put breaks, continues, gotos and returns here + Array gotos; // forward referenced goto's go here + + ForeachStatement(Loc loc, enum TOK op, Arguments *arguments, Expression *aggr, Statement *body); + Statement *syntaxCopy(); + Statement *semantic(Scope *sc); + int hasBreak(); + int hasContinue(); + int usesEH(); + int blockExit(); + int comeFrom(); + Expression *interpret(InterState *istate); + void toCBuffer(OutBuffer *buf, HdrGenState *hgs); + + Statement *inlineScan(InlineScanState *iss); + + void toIR(IRState *irs); +}; + +#if DMDV2 +struct ForeachRangeStatement : Statement +{ + enum TOK op; // TOKforeach or TOKforeach_reverse + Argument *arg; // loop index variable + Expression *lwr; + Expression *upr; + Statement *body; + + VarDeclaration *key; + + ForeachRangeStatement(Loc loc, enum TOK op, Argument *arg, + Expression *lwr, Expression *upr, Statement *body); + Statement *syntaxCopy(); + Statement *semantic(Scope *sc); + int hasBreak(); + int hasContinue(); + int usesEH(); + int blockExit(); + int comeFrom(); + Expression *interpret(InterState *istate); + void toCBuffer(OutBuffer *buf, HdrGenState *hgs); + + Statement *inlineScan(InlineScanState *iss); + + void toIR(IRState *irs); +}; +#endif + +struct IfStatement : Statement +{ + Argument *arg; + Expression *condition; + Statement *ifbody; + Statement *elsebody; + + VarDeclaration *match; // for MatchExpression results + + IfStatement(Loc loc, Argument *arg, Expression *condition, Statement *ifbody, Statement *elsebody); + Statement *syntaxCopy(); + Statement *semantic(Scope *sc); + Expression *interpret(InterState *istate); + void toCBuffer(OutBuffer *buf, HdrGenState *hgs); + int usesEH(); + int blockExit(); + IfStatement *isIfStatement() { return this; } + + int inlineCost(InlineCostState *ics); + Expression *doInline(InlineDoState *ids); + Statement *inlineScan(InlineScanState *iss); + + void toIR(IRState *irs); +}; + +struct ConditionalStatement : Statement +{ + Condition *condition; + Statement *ifbody; + Statement *elsebody; + + ConditionalStatement(Loc loc, Condition *condition, Statement *ifbody, Statement *elsebody); + Statement *syntaxCopy(); + Statement *semantic(Scope *sc); + Statements *flatten(Scope *sc); + int usesEH(); + int blockExit(); + + void toCBuffer(OutBuffer *buf, HdrGenState *hgs); +}; + +struct PragmaStatement : Statement +{ + Identifier *ident; + Expressions *args; // array of Expression's + Statement *body; + + PragmaStatement(Loc loc, Identifier *ident, Expressions *args, Statement *body); + Statement *syntaxCopy(); + Statement *semantic(Scope *sc); + int usesEH(); + int blockExit(); + + void toCBuffer(OutBuffer *buf, HdrGenState *hgs); +}; + +struct StaticAssertStatement : Statement +{ + StaticAssert *sa; + + StaticAssertStatement(StaticAssert *sa); + Statement *syntaxCopy(); + Statement *semantic(Scope *sc); + + void toCBuffer(OutBuffer *buf, HdrGenState *hgs); +}; + +struct SwitchStatement : Statement +{ + Expression *condition; + Statement *body; + + DefaultStatement *sdefault; + + Array gotoCases; // array of unresolved GotoCaseStatement's + Array *cases; // array of CaseStatement's + int hasNoDefault; // !=0 if no default statement + + // LDC + Statement *enclosingScopeExit; + + SwitchStatement(Loc loc, Expression *c, Statement *b); + Statement *syntaxCopy(); + Statement *semantic(Scope *sc); + int hasBreak(); + int usesEH(); + int blockExit(); + Expression *interpret(InterState *istate); + void toCBuffer(OutBuffer *buf, HdrGenState *hgs); + + Statement *inlineScan(InlineScanState *iss); + + void toIR(IRState *irs); +}; + +struct CaseStatement : Statement +{ + Expression *exp; + Statement *statement; + int index; // which case it is (since we sort this) + block *cblock; // back end: label for the block + + // LDC + Statement *enclosingScopeExit; + + CaseStatement(Loc loc, Expression *exp, Statement *s); + Statement *syntaxCopy(); + Statement *semantic(Scope *sc); + int compare(Object *obj); + int usesEH(); + int blockExit(); + int comeFrom(); + Expression *interpret(InterState *istate); + void toCBuffer(OutBuffer *buf, HdrGenState *hgs); + + Statement *inlineScan(InlineScanState *iss); + + void toIR(IRState *irs); + + CaseStatement* isCaseStatement() { return this; } + + // LDC + llvm::BasicBlock* bodyBB; + llvm::ConstantInt* llvmIdx; +}; + +struct DefaultStatement : Statement +{ + Statement *statement; +#if IN_GCC + block *cblock; // back end: label for the block +#endif + + // LDC + Statement *enclosingScopeExit; + + DefaultStatement(Loc loc, Statement *s); + Statement *syntaxCopy(); + Statement *semantic(Scope *sc); + int usesEH(); + int blockExit(); + int comeFrom(); + Expression *interpret(InterState *istate); + void toCBuffer(OutBuffer *buf, HdrGenState *hgs); + + Statement *inlineScan(InlineScanState *iss); + + void toIR(IRState *irs); + + // LDC + llvm::BasicBlock* bodyBB; +}; + +struct GotoDefaultStatement : Statement +{ + SwitchStatement *sw; + + GotoDefaultStatement(Loc loc); + Statement *syntaxCopy(); + Statement *semantic(Scope *sc); + Expression *interpret(InterState *istate); + int blockExit(); + void toCBuffer(OutBuffer *buf, HdrGenState *hgs); + + void toIR(IRState *irs); +}; + +struct GotoCaseStatement : Statement +{ + Expression *exp; // NULL, or which case to goto + CaseStatement *cs; // case statement it resolves to + SwitchStatement *sw; + + GotoCaseStatement(Loc loc, Expression *exp); + Statement *syntaxCopy(); + Statement *semantic(Scope *sc); + Expression *interpret(InterState *istate); + int blockExit(); + void toCBuffer(OutBuffer *buf, HdrGenState *hgs); + + void toIR(IRState *irs); +}; + +struct SwitchErrorStatement : Statement +{ + SwitchErrorStatement(Loc loc); + int blockExit(); + void toCBuffer(OutBuffer *buf, HdrGenState *hgs); + + void toIR(IRState *irs); +}; + +struct ReturnStatement : Statement +{ + Expression *exp; + + ReturnStatement(Loc loc, Expression *exp); + Statement *syntaxCopy(); + void toCBuffer(OutBuffer *buf, HdrGenState *hgs); + Statement *semantic(Scope *sc); + int blockExit(); + Expression *interpret(InterState *istate); + + int inlineCost(InlineCostState *ics); + Expression *doInline(InlineDoState *ids); + Statement *inlineScan(InlineScanState *iss); + + void toIR(IRState *irs); + + ReturnStatement *isReturnStatement() { return this; } +}; + +struct BreakStatement : Statement +{ + Identifier *ident; + + BreakStatement(Loc loc, Identifier *ident); + Statement *syntaxCopy(); + Statement *semantic(Scope *sc); + Expression *interpret(InterState *istate); + int blockExit(); + void toCBuffer(OutBuffer *buf, HdrGenState *hgs); + + void toIR(IRState *irs); + + // LDC: only set if ident is set: label statement to jump to + LabelStatement *target; +}; + +struct ContinueStatement : Statement +{ + Identifier *ident; + + ContinueStatement(Loc loc, Identifier *ident); + Statement *syntaxCopy(); + Statement *semantic(Scope *sc); + Expression *interpret(InterState *istate); + int blockExit(); + void toCBuffer(OutBuffer *buf, HdrGenState *hgs); + + void toIR(IRState *irs); + + // LDC: only set if ident is set: label statement to jump to + LabelStatement *target; +}; + +struct SynchronizedStatement : Statement +{ + Expression *exp; + Statement *body; + + SynchronizedStatement(Loc loc, Expression *exp, Statement *body); + Statement *syntaxCopy(); + Statement *semantic(Scope *sc); + int hasBreak(); + int hasContinue(); + int usesEH(); + int blockExit(); + void toCBuffer(OutBuffer *buf, HdrGenState *hgs); + + Statement *inlineScan(InlineScanState *iss); + +// Back end + elem *esync; + SynchronizedStatement(Loc loc, elem *esync, Statement *body); + void toIR(IRState *irs); + llvm::Value* llsync; +}; + +struct WithStatement : Statement +{ + Expression *exp; + Statement *body; + VarDeclaration *wthis; + + WithStatement(Loc loc, Expression *exp, Statement *body); + Statement *syntaxCopy(); + Statement *semantic(Scope *sc); + void toCBuffer(OutBuffer *buf, HdrGenState *hgs); + int usesEH(); + int blockExit(); + + Statement *inlineScan(InlineScanState *iss); + + void toIR(IRState *irs); +}; + +struct TryCatchStatement : Statement +{ + Statement *body; + Array *catches; + + TryCatchStatement(Loc loc, Statement *body, Array *catches); + Statement *syntaxCopy(); + Statement *semantic(Scope *sc); + int hasBreak(); + int usesEH(); + int blockExit(); + + Statement *inlineScan(InlineScanState *iss); + + void toIR(IRState *irs); + void toCBuffer(OutBuffer *buf, HdrGenState *hgs); + TryCatchStatement *isTryCatchStatement() { return this; } +}; + +struct Catch : Object +{ + Loc loc; + Type *type; + Identifier *ident; + VarDeclaration *var; + Statement *handler; + + Catch(Loc loc, Type *t, Identifier *id, Statement *handler); + Catch *syntaxCopy(); + void semantic(Scope *sc); + int blockExit(); + void toCBuffer(OutBuffer *buf, HdrGenState *hgs); +}; + +struct TryFinallyStatement : Statement +{ + Statement *body; + Statement *finalbody; + + TryFinallyStatement(Loc loc, Statement *body, Statement *finalbody); + Statement *syntaxCopy(); + void toCBuffer(OutBuffer *buf, HdrGenState *hgs); + Statement *semantic(Scope *sc); + int hasBreak(); + int hasContinue(); + int usesEH(); + int blockExit(); + + Statement *inlineScan(InlineScanState *iss); + + void toIR(IRState *irs); +}; + +struct OnScopeStatement : Statement +{ + TOK tok; + Statement *statement; + + OnScopeStatement(Loc loc, TOK tok, Statement *statement); + Statement *syntaxCopy(); + int blockExit(); + void toCBuffer(OutBuffer *buf, HdrGenState *hgs); + Statement *semantic(Scope *sc); + int usesEH(); + void scopeCode(Statement **sentry, Statement **sexit, Statement **sfinally); + + void toIR(IRState *irs); +}; + +struct ThrowStatement : Statement +{ + Expression *exp; + + ThrowStatement(Loc loc, Expression *exp); + Statement *syntaxCopy(); + Statement *semantic(Scope *sc); + void toCBuffer(OutBuffer *buf, HdrGenState *hgs); + int blockExit(); + + Statement *inlineScan(InlineScanState *iss); + + void toIR(IRState *irs); +}; + +struct VolatileStatement : Statement +{ + Statement *statement; + + VolatileStatement(Loc loc, Statement *statement); + Statement *syntaxCopy(); + Statement *semantic(Scope *sc); + Statements *flatten(Scope *sc); + int blockExit(); + void toCBuffer(OutBuffer *buf, HdrGenState *hgs); + + Statement *inlineScan(InlineScanState *iss); + + void toIR(IRState *irs); +}; + +struct GotoStatement : Statement +{ + Identifier *ident; + LabelDsymbol *label; + TryFinallyStatement *enclosingFinally; + Statement* enclosingScopeExit; + + GotoStatement(Loc loc, Identifier *ident); + Statement *syntaxCopy(); + Statement *semantic(Scope *sc); + int blockExit(); + Expression *interpret(InterState *istate); + + void toIR(IRState *irs); + void toCBuffer(OutBuffer *buf, HdrGenState *hgs); + GotoStatement *isGotoStatement() { return this; } +}; + +struct LabelStatement : Statement +{ + Identifier *ident; + Statement *statement; + TryFinallyStatement *enclosingFinally; + Statement* enclosingScopeExit; + block *lblock; // back end + int isReturnLabel; + + LabelStatement(Loc loc, Identifier *ident, Statement *statement); + Statement *syntaxCopy(); + Statement *semantic(Scope *sc); + Statements *flatten(Scope *sc); + int usesEH(); + int blockExit(); + int comeFrom(); + Expression *interpret(InterState *istate); + void toCBuffer(OutBuffer *buf, HdrGenState *hgs); + + Statement *inlineScan(InlineScanState *iss); + + void toIR(IRState *irs); + + // LDC + bool asmLabel; // for labels inside inline assembler + void toNakedIR(IRState *irs); +}; + +struct LabelDsymbol : Dsymbol +{ + LabelStatement *statement; + + LabelDsymbol(Identifier *ident); + LabelDsymbol *isLabel(); +}; + +struct AsmStatement : Statement +{ + Token *tokens; + code *asmcode; + unsigned asmalign; // alignment of this statement + unsigned refparam; // !=0 if function parameter is referenced + unsigned naked; // !=0 if function is to be naked + + AsmStatement(Loc loc, Token *tokens); + Statement *syntaxCopy(); + Statement *semantic(Scope *sc); + int blockExit(); + int comeFrom(); + + void toCBuffer(OutBuffer *buf, HdrGenState *hgs); + virtual AsmStatement *isAsmStatement() { return this; } + + void toIR(IRState *irs); + + // LDC + // non-zero if this is a branch, contains the target labels identifier + Identifier* isBranchToLabel; + + void toNakedIR(IRState *irs); +}; + +struct AsmBlockStatement : CompoundStatement +{ + TryFinallyStatement* enclosingFinally; + Statement* enclosingScopeExit; + + AsmBlockStatement(Loc loc, Statements *s); + Statements *flatten(Scope *sc); + Statement *syntaxCopy(); + Statement *semantic(Scope *sc); + + CompoundStatement *isCompoundStatement() { return NULL; } + AsmBlockStatement *isAsmBlockStatement() { return this; } + + void toIR(IRState *irs); + void toNakedIR(IRState *irs); + AsmBlockStatement* endsWithAsm(); + + llvm::Value* abiret; +}; + +#endif /* DMD_STATEMENT_H */ diff -r 1853dcd9b944 -r e961851fb8be dmd/struct.c --- a/dmd/struct.c Fri Apr 03 17:02:52 2009 +0200 +++ b/dmd/struct.c Fri Apr 03 17:59:34 2009 +0200 @@ -1,512 +1,512 @@ - -// Compiler implementation of the D programming language -// Copyright (c) 1999-2009 by Digital Mars -// All Rights Reserved -// written by Walter Bright -// 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. - -#include -#include - -#include "root.h" -#include "aggregate.h" -#include "scope.h" -#include "mtype.h" -#include "declaration.h" -#include "module.h" -#include "id.h" -#include "statement.h" - -/********************************* AggregateDeclaration ****************************/ - -AggregateDeclaration::AggregateDeclaration(Loc loc, Identifier *id) - : ScopeDsymbol(id) -{ - this->loc = loc; - - storage_class = 0; - protection = PROTpublic; - type = NULL; - handle = NULL; - structsize = 0; // size of struct - alignsize = 0; // size of struct for alignment purposes - structalign = 0; // struct member alignment in effect - hasUnions = 0; - sizeok = 0; // size not determined yet - isdeprecated = 0; - inv = NULL; - aggNew = NULL; - aggDelete = NULL; - -#if IN_DMD - stag = NULL; - sinit = NULL; -#endif - scope = NULL; -#if V2 - dtor = NULL; - - ctor = NULL; - defaultCtor = NULL; -#endif -} - -enum PROT AggregateDeclaration::prot() -{ - return protection; -} - -void AggregateDeclaration::semantic2(Scope *sc) -{ - //printf("AggregateDeclaration::semantic2(%s)\n", toChars()); - if (scope) - { error("has forward references"); - return; - } - if (members) - { - sc = sc->push(this); - for (size_t i = 0; i < members->dim; i++) - { - Dsymbol *s = (Dsymbol *)members->data[i]; - s->semantic2(sc); - } - sc->pop(); - } -} - -void AggregateDeclaration::semantic3(Scope *sc) -{ int i; - - //printf("AggregateDeclaration::semantic3(%s)\n", toChars()); - if (members) - { - sc = sc->push(this); - for (i = 0; i < members->dim; i++) - { - Dsymbol *s = (Dsymbol *)members->data[i]; - s->semantic3(sc); - } - sc->pop(); - } -} - -void AggregateDeclaration::inlineScan() -{ int i; - - //printf("AggregateDeclaration::inlineScan(%s)\n", toChars()); - if (members) - { - for (i = 0; i < members->dim; i++) - { - Dsymbol *s = (Dsymbol *)members->data[i]; - //printf("inline scan aggregate symbol '%s'\n", s->toChars()); - s->inlineScan(); - } - } -} - -unsigned AggregateDeclaration::size(Loc loc) -{ - //printf("AggregateDeclaration::size() = %d\n", structsize); - if (!members) - error(loc, "unknown size"); - if (sizeok != 1) - { error(loc, "no size yet for forward reference"); - //*(char*)0=0; - } - return structsize; -} - -Type *AggregateDeclaration::getType() -{ - return type; -} - -int AggregateDeclaration::isDeprecated() -{ - return isdeprecated; -} - -/**************************** - * Do byte or word alignment as necessary. - * Align sizes of 0, as we may not know array sizes yet. - */ - -void AggregateDeclaration::alignmember( - unsigned salign, // struct alignment that is in effect - unsigned size, // alignment requirement of field - unsigned *poffset) -{ - //printf("salign = %d, size = %d, offset = %d\n",salign,size,offset); - if (salign > 1) - { - assert(size != 3); - int sa = size; - if (sa == 0 || salign < sa) - sa = salign; - *poffset = (*poffset + sa - 1) & ~(sa - 1); - } - //printf("result = %d\n",offset); -} - - -void AggregateDeclaration::addField(Scope *sc, VarDeclaration *v) -{ - unsigned memsize; // size of member - unsigned memalignsize; // size of member for alignment purposes - unsigned xalign; // alignment boundaries - - //printf("AggregateDeclaration::addField('%s') %s\n", v->toChars(), toChars()); - - // Check for forward referenced types which will fail the size() call - Type *t = v->type->toBasetype(); - if (t->ty == Tstruct /*&& isStructDeclaration()*/) - { TypeStruct *ts = (TypeStruct *)t; -#if V2 - if (ts->sym == this) - { - error("cannot have field %s with same struct type", v->toChars()); - } -#endif - - if (ts->sym->sizeok != 1) - { - sizeok = 2; // cannot finish; flag as forward referenced - return; - } - } - if (t->ty == Tident) - { - sizeok = 2; // cannot finish; flag as forward referenced - return; - } - - memsize = v->type->size(loc); - memalignsize = v->type->alignsize(); - xalign = v->type->memalign(sc->structalign); - alignmember(xalign, memalignsize, &sc->offset); - v->offset = sc->offset; - sc->offset += memsize; - if (sc->offset > structsize) - structsize = sc->offset; - if (sc->structalign < memalignsize) - memalignsize = sc->structalign; - if (alignsize < memalignsize) - alignsize = memalignsize; - //printf("\talignsize = %d\n", alignsize); - - v->storage_class |= STCfield; - //printf(" addField '%s' to '%s' at offset %d, size = %d\n", v->toChars(), toChars(), v->offset, memsize); - fields.push(v); -} - - -/********************************* StructDeclaration ****************************/ - -StructDeclaration::StructDeclaration(Loc loc, Identifier *id) - : AggregateDeclaration(loc, id) -{ - zeroInit = 0; // assume false until we do semantic processing -#if V2 - hasIdentityAssign = 0; - cpctor = NULL; - postblit = NULL; -#endif - - // For forward references - type = new TypeStruct(this); -} - -Dsymbol *StructDeclaration::syntaxCopy(Dsymbol *s) -{ - StructDeclaration *sd; - - if (s) - sd = (StructDeclaration *)s; - else - sd = new StructDeclaration(loc, ident); - ScopeDsymbol::syntaxCopy(sd); - return sd; -} - -void StructDeclaration::semantic(Scope *sc) -{ int i; - Scope *sc2; - - //printf("+StructDeclaration::semantic(this=%p, '%s')\n", this, toChars()); - - //static int count; if (++count == 20) *(char*)0=0; - - assert(type); - if (!members) // if forward reference - return; - - if (symtab) - { if (!scope) - return; // semantic() already completed - } - else - symtab = new DsymbolTable(); - - Scope *scx = NULL; - if (scope) - { sc = scope; - scx = scope; // save so we don't make redundant copies - scope = NULL; - } - - parent = sc->parent; -#if STRUCTTHISREF - handle = type; -#else - handle = type->pointerTo(); -#endif - structalign = sc->structalign; - protection = sc->protection; - if (sc->stc & STCdeprecated) - isdeprecated = 1; - assert(!isAnonymous()); - if (sc->stc & STCabstract) - error("structs, unions cannot be abstract"); -#if V2 - if (storage_class & STCinvariant) - type = type->invariantOf(); - else if (storage_class & STCconst) - type = type->constOf(); -#endif - - if (sizeok == 0) // if not already done the addMember step - { - for (i = 0; i < members->dim; i++) - { - Dsymbol *s = (Dsymbol *)members->data[i]; - //printf("adding member '%s' to '%s'\n", s->toChars(), this->toChars()); - s->addMember(sc, this, 1); - } - } - - sizeok = 0; - sc2 = sc->push(this); - sc2->stc = 0; - sc2->parent = this; - if (isUnionDeclaration()) - sc2->inunion = 1; - sc2->protection = PROTpublic; - sc2->explicitProtection = 0; - - int members_dim = members->dim; - for (i = 0; i < members_dim; i++) - { - Dsymbol *s = (Dsymbol *)members->data[i]; - s->semantic(sc2); - if (isUnionDeclaration()) - sc2->offset = 0; -#if 0 - if (sizeok == 2) - { //printf("forward reference\n"); - break; - } -#endif - } - - /* The TypeInfo_Struct is expecting an opEquals and opCmp with - * a parameter that is a pointer to the struct. But if there - * isn't one, but is an opEquals or opCmp with a value, write - * another that is a shell around the value: - * int opCmp(struct *p) { return opCmp(*p); } - */ - - TypeFunction *tfeqptr; - { - Arguments *arguments = new Arguments; - Argument *arg = new Argument(STCin, handle, Id::p, NULL); - - arguments->push(arg); - tfeqptr = new TypeFunction(arguments, Type::tint32, 0, LINKd); - tfeqptr = (TypeFunction *)tfeqptr->semantic(0, sc); - } - - TypeFunction *tfeq; - { - Arguments *arguments = new Arguments; - Argument *arg = new Argument(STCin, type, NULL, NULL); - - arguments->push(arg); - tfeq = new TypeFunction(arguments, Type::tint32, 0, LINKd); - tfeq = (TypeFunction *)tfeq->semantic(0, sc); - } - - Identifier *id = Id::eq; - for (int i = 0; i < 2; i++) - { - Dsymbol *s = search_function(this, id); - FuncDeclaration *fdx = s ? s->isFuncDeclaration() : NULL; - if (fdx) - { FuncDeclaration *fd = fdx->overloadExactMatch(tfeqptr); - if (!fd) - { fd = fdx->overloadExactMatch(tfeq); - if (fd) - { // Create the thunk, fdptr - FuncDeclaration *fdptr = new FuncDeclaration(loc, loc, fdx->ident, STCundefined, tfeqptr); - Expression *e = new IdentifierExp(loc, Id::p); - e = new PtrExp(loc, e); - Expressions *args = new Expressions(); - args->push(e); - e = new IdentifierExp(loc, id); - e = new CallExp(loc, e, args); - fdptr->fbody = new ReturnStatement(loc, e); - ScopeDsymbol *s = fdx->parent->isScopeDsymbol(); - assert(s); - s->members->push(fdptr); - fdptr->addMember(sc, s, 1); - fdptr->semantic(sc2); - } - } - } - - id = Id::cmp; - } -#if V2 - dtor = buildDtor(sc2); - postblit = buildPostBlit(sc2); - cpctor = buildCpCtor(sc2); - buildOpAssign(sc2); -#endif - - sc2->pop(); - - if (sizeok == 2) - { // semantic() failed because of forward references. - // Unwind what we did, and defer it for later - fields.setDim(0); - structsize = 0; - alignsize = 0; - structalign = 0; - - scope = scx ? scx : new Scope(*sc); - scope->setNoFree(); - scope->module->addDeferredSemantic(this); - //printf("\tdeferring %s\n", toChars()); - return; - } - - // 0 sized struct's are set to 1 byte - if (structsize == 0) - { - structsize = 1; - alignsize = 1; - } - - // Round struct size up to next alignsize boundary. - // This will ensure that arrays of structs will get their internals - // aligned properly. - structsize = (structsize + alignsize - 1) & ~(alignsize - 1); - - sizeok = 1; - Module::dprogress++; - - //printf("-StructDeclaration::semantic(this=%p, '%s')\n", this, toChars()); - - // Determine if struct is all zeros or not - zeroInit = 1; - for (i = 0; i < fields.dim; i++) - { - Dsymbol *s = (Dsymbol *)fields.data[i]; - VarDeclaration *vd = s->isVarDeclaration(); - if (vd && !vd->isDataseg()) - { - if (vd->init) - { - // Should examine init to see if it is really all 0's - zeroInit = 0; - break; - } - else - { - if (!vd->type->isZeroInit()) - { - zeroInit = 0; - break; - } - } - } - } - - /* Look for special member functions. - */ -#if V2 - ctor = (CtorDeclaration *)search(0, Id::ctor, 0); -#endif - inv = (InvariantDeclaration *)search(0, Id::classInvariant, 0); - aggNew = (NewDeclaration *)search(0, Id::classNew, 0); - aggDelete = (DeleteDeclaration *)search(0, Id::classDelete, 0); - - if (sc->func) - { - semantic2(sc); - semantic3(sc); - } -} - -void StructDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) -{ int i; - - buf->printf("%s ", kind()); - if (!isAnonymous()) - buf->writestring(toChars()); - if (!members) - { - buf->writeByte(';'); - buf->writenl(); - return; - } - buf->writenl(); - buf->writeByte('{'); - buf->writenl(); - for (i = 0; i < members->dim; i++) - { - Dsymbol *s = (Dsymbol *)members->data[i]; - - buf->writestring(" "); - s->toCBuffer(buf, hgs); - } - buf->writeByte('}'); - buf->writenl(); -} - - -const char *StructDeclaration::kind() -{ - return "struct"; -} - -/********************************* UnionDeclaration ****************************/ - -UnionDeclaration::UnionDeclaration(Loc loc, Identifier *id) - : StructDeclaration(loc, id) -{ -} - -Dsymbol *UnionDeclaration::syntaxCopy(Dsymbol *s) -{ - UnionDeclaration *ud; - - if (s) - ud = (UnionDeclaration *)s; - else - ud = new UnionDeclaration(loc, ident); - StructDeclaration::syntaxCopy(ud); - return ud; -} - - -const char *UnionDeclaration::kind() -{ - return "union"; -} - - + +// Compiler implementation of the D programming language +// Copyright (c) 1999-2009 by Digital Mars +// All Rights Reserved +// written by Walter Bright +// 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. + +#include +#include + +#include "root.h" +#include "aggregate.h" +#include "scope.h" +#include "mtype.h" +#include "declaration.h" +#include "module.h" +#include "id.h" +#include "statement.h" + +/********************************* AggregateDeclaration ****************************/ + +AggregateDeclaration::AggregateDeclaration(Loc loc, Identifier *id) + : ScopeDsymbol(id) +{ + this->loc = loc; + + storage_class = 0; + protection = PROTpublic; + type = NULL; + handle = NULL; + structsize = 0; // size of struct + alignsize = 0; // size of struct for alignment purposes + structalign = 0; // struct member alignment in effect + hasUnions = 0; + sizeok = 0; // size not determined yet + isdeprecated = 0; + inv = NULL; + aggNew = NULL; + aggDelete = NULL; + +#if IN_DMD + stag = NULL; + sinit = NULL; +#endif + scope = NULL; +#if DMDV2 + dtor = NULL; + + ctor = NULL; + defaultCtor = NULL; +#endif +} + +enum PROT AggregateDeclaration::prot() +{ + return protection; +} + +void AggregateDeclaration::semantic2(Scope *sc) +{ + //printf("AggregateDeclaration::semantic2(%s)\n", toChars()); + if (scope) + { error("has forward references"); + return; + } + if (members) + { + sc = sc->push(this); + for (size_t i = 0; i < members->dim; i++) + { + Dsymbol *s = (Dsymbol *)members->data[i]; + s->semantic2(sc); + } + sc->pop(); + } +} + +void AggregateDeclaration::semantic3(Scope *sc) +{ int i; + + //printf("AggregateDeclaration::semantic3(%s)\n", toChars()); + if (members) + { + sc = sc->push(this); + for (i = 0; i < members->dim; i++) + { + Dsymbol *s = (Dsymbol *)members->data[i]; + s->semantic3(sc); + } + sc->pop(); + } +} + +void AggregateDeclaration::inlineScan() +{ int i; + + //printf("AggregateDeclaration::inlineScan(%s)\n", toChars()); + if (members) + { + for (i = 0; i < members->dim; i++) + { + Dsymbol *s = (Dsymbol *)members->data[i]; + //printf("inline scan aggregate symbol '%s'\n", s->toChars()); + s->inlineScan(); + } + } +} + +unsigned AggregateDeclaration::size(Loc loc) +{ + //printf("AggregateDeclaration::size() = %d\n", structsize); + if (!members) + error(loc, "unknown size"); + if (sizeok != 1) + { error(loc, "no size yet for forward reference"); + //*(char*)0=0; + } + return structsize; +} + +Type *AggregateDeclaration::getType() +{ + return type; +} + +int AggregateDeclaration::isDeprecated() +{ + return isdeprecated; +} + +/**************************** + * Do byte or word alignment as necessary. + * Align sizes of 0, as we may not know array sizes yet. + */ + +void AggregateDeclaration::alignmember( + unsigned salign, // struct alignment that is in effect + unsigned size, // alignment requirement of field + unsigned *poffset) +{ + //printf("salign = %d, size = %d, offset = %d\n",salign,size,offset); + if (salign > 1) + { + assert(size != 3); + int sa = size; + if (sa == 0 || salign < sa) + sa = salign; + *poffset = (*poffset + sa - 1) & ~(sa - 1); + } + //printf("result = %d\n",offset); +} + + +void AggregateDeclaration::addField(Scope *sc, VarDeclaration *v) +{ + unsigned memsize; // size of member + unsigned memalignsize; // size of member for alignment purposes + unsigned xalign; // alignment boundaries + + //printf("AggregateDeclaration::addField('%s') %s\n", v->toChars(), toChars()); + + // Check for forward referenced types which will fail the size() call + Type *t = v->type->toBasetype(); + if (t->ty == Tstruct /*&& isStructDeclaration()*/) + { TypeStruct *ts = (TypeStruct *)t; +#if DMDV2 + if (ts->sym == this) + { + error("cannot have field %s with same struct type", v->toChars()); + } +#endif + + if (ts->sym->sizeok != 1) + { + sizeok = 2; // cannot finish; flag as forward referenced + return; + } + } + if (t->ty == Tident) + { + sizeok = 2; // cannot finish; flag as forward referenced + return; + } + + memsize = v->type->size(loc); + memalignsize = v->type->alignsize(); + xalign = v->type->memalign(sc->structalign); + alignmember(xalign, memalignsize, &sc->offset); + v->offset = sc->offset; + sc->offset += memsize; + if (sc->offset > structsize) + structsize = sc->offset; + if (sc->structalign < memalignsize) + memalignsize = sc->structalign; + if (alignsize < memalignsize) + alignsize = memalignsize; + //printf("\talignsize = %d\n", alignsize); + + v->storage_class |= STCfield; + //printf(" addField '%s' to '%s' at offset %d, size = %d\n", v->toChars(), toChars(), v->offset, memsize); + fields.push(v); +} + + +/********************************* StructDeclaration ****************************/ + +StructDeclaration::StructDeclaration(Loc loc, Identifier *id) + : AggregateDeclaration(loc, id) +{ + zeroInit = 0; // assume false until we do semantic processing +#if DMDV2 + hasIdentityAssign = 0; + cpctor = NULL; + postblit = NULL; +#endif + + // For forward references + type = new TypeStruct(this); +} + +Dsymbol *StructDeclaration::syntaxCopy(Dsymbol *s) +{ + StructDeclaration *sd; + + if (s) + sd = (StructDeclaration *)s; + else + sd = new StructDeclaration(loc, ident); + ScopeDsymbol::syntaxCopy(sd); + return sd; +} + +void StructDeclaration::semantic(Scope *sc) +{ int i; + Scope *sc2; + + //printf("+StructDeclaration::semantic(this=%p, '%s')\n", this, toChars()); + + //static int count; if (++count == 20) *(char*)0=0; + + assert(type); + if (!members) // if forward reference + return; + + if (symtab) + { if (!scope) + return; // semantic() already completed + } + else + symtab = new DsymbolTable(); + + Scope *scx = NULL; + if (scope) + { sc = scope; + scx = scope; // save so we don't make redundant copies + scope = NULL; + } + + parent = sc->parent; +#if STRUCTTHISREF + handle = type; +#else + handle = type->pointerTo(); +#endif + structalign = sc->structalign; + protection = sc->protection; + if (sc->stc & STCdeprecated) + isdeprecated = 1; + assert(!isAnonymous()); + if (sc->stc & STCabstract) + error("structs, unions cannot be abstract"); +#if DMDV2 + if (storage_class & STCinvariant) + type = type->invariantOf(); + else if (storage_class & STCconst) + type = type->constOf(); +#endif + + if (sizeok == 0) // if not already done the addMember step + { + for (i = 0; i < members->dim; i++) + { + Dsymbol *s = (Dsymbol *)members->data[i]; + //printf("adding member '%s' to '%s'\n", s->toChars(), this->toChars()); + s->addMember(sc, this, 1); + } + } + + sizeok = 0; + sc2 = sc->push(this); + sc2->stc = 0; + sc2->parent = this; + if (isUnionDeclaration()) + sc2->inunion = 1; + sc2->protection = PROTpublic; + sc2->explicitProtection = 0; + + int members_dim = members->dim; + for (i = 0; i < members_dim; i++) + { + Dsymbol *s = (Dsymbol *)members->data[i]; + s->semantic(sc2); + if (isUnionDeclaration()) + sc2->offset = 0; +#if 0 + if (sizeok == 2) + { //printf("forward reference\n"); + break; + } +#endif + } + + /* The TypeInfo_Struct is expecting an opEquals and opCmp with + * a parameter that is a pointer to the struct. But if there + * isn't one, but is an opEquals or opCmp with a value, write + * another that is a shell around the value: + * int opCmp(struct *p) { return opCmp(*p); } + */ + + TypeFunction *tfeqptr; + { + Arguments *arguments = new Arguments; + Argument *arg = new Argument(STCin, handle, Id::p, NULL); + + arguments->push(arg); + tfeqptr = new TypeFunction(arguments, Type::tint32, 0, LINKd); + tfeqptr = (TypeFunction *)tfeqptr->semantic(0, sc); + } + + TypeFunction *tfeq; + { + Arguments *arguments = new Arguments; + Argument *arg = new Argument(STCin, type, NULL, NULL); + + arguments->push(arg); + tfeq = new TypeFunction(arguments, Type::tint32, 0, LINKd); + tfeq = (TypeFunction *)tfeq->semantic(0, sc); + } + + Identifier *id = Id::eq; + for (int i = 0; i < 2; i++) + { + Dsymbol *s = search_function(this, id); + FuncDeclaration *fdx = s ? s->isFuncDeclaration() : NULL; + if (fdx) + { FuncDeclaration *fd = fdx->overloadExactMatch(tfeqptr); + if (!fd) + { fd = fdx->overloadExactMatch(tfeq); + if (fd) + { // Create the thunk, fdptr + FuncDeclaration *fdptr = new FuncDeclaration(loc, loc, fdx->ident, STCundefined, tfeqptr); + Expression *e = new IdentifierExp(loc, Id::p); + e = new PtrExp(loc, e); + Expressions *args = new Expressions(); + args->push(e); + e = new IdentifierExp(loc, id); + e = new CallExp(loc, e, args); + fdptr->fbody = new ReturnStatement(loc, e); + ScopeDsymbol *s = fdx->parent->isScopeDsymbol(); + assert(s); + s->members->push(fdptr); + fdptr->addMember(sc, s, 1); + fdptr->semantic(sc2); + } + } + } + + id = Id::cmp; + } +#if DMDV2 + dtor = buildDtor(sc2); + postblit = buildPostBlit(sc2); + cpctor = buildCpCtor(sc2); + buildOpAssign(sc2); +#endif + + sc2->pop(); + + if (sizeok == 2) + { // semantic() failed because of forward references. + // Unwind what we did, and defer it for later + fields.setDim(0); + structsize = 0; + alignsize = 0; + structalign = 0; + + scope = scx ? scx : new Scope(*sc); + scope->setNoFree(); + scope->module->addDeferredSemantic(this); + //printf("\tdeferring %s\n", toChars()); + return; + } + + // 0 sized struct's are set to 1 byte + if (structsize == 0) + { + structsize = 1; + alignsize = 1; + } + + // Round struct size up to next alignsize boundary. + // This will ensure that arrays of structs will get their internals + // aligned properly. + structsize = (structsize + alignsize - 1) & ~(alignsize - 1); + + sizeok = 1; + Module::dprogress++; + + //printf("-StructDeclaration::semantic(this=%p, '%s')\n", this, toChars()); + + // Determine if struct is all zeros or not + zeroInit = 1; + for (i = 0; i < fields.dim; i++) + { + Dsymbol *s = (Dsymbol *)fields.data[i]; + VarDeclaration *vd = s->isVarDeclaration(); + if (vd && !vd->isDataseg()) + { + if (vd->init) + { + // Should examine init to see if it is really all 0's + zeroInit = 0; + break; + } + else + { + if (!vd->type->isZeroInit()) + { + zeroInit = 0; + break; + } + } + } + } + + /* Look for special member functions. + */ +#if DMDV2 + ctor = (CtorDeclaration *)search(0, Id::ctor, 0); +#endif + inv = (InvariantDeclaration *)search(0, Id::classInvariant, 0); + aggNew = (NewDeclaration *)search(0, Id::classNew, 0); + aggDelete = (DeleteDeclaration *)search(0, Id::classDelete, 0); + + if (sc->func) + { + semantic2(sc); + semantic3(sc); + } +} + +void StructDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) +{ int i; + + buf->printf("%s ", kind()); + if (!isAnonymous()) + buf->writestring(toChars()); + if (!members) + { + buf->writeByte(';'); + buf->writenl(); + return; + } + buf->writenl(); + buf->writeByte('{'); + buf->writenl(); + for (i = 0; i < members->dim; i++) + { + Dsymbol *s = (Dsymbol *)members->data[i]; + + buf->writestring(" "); + s->toCBuffer(buf, hgs); + } + buf->writeByte('}'); + buf->writenl(); +} + + +const char *StructDeclaration::kind() +{ + return "struct"; +} + +/********************************* UnionDeclaration ****************************/ + +UnionDeclaration::UnionDeclaration(Loc loc, Identifier *id) + : StructDeclaration(loc, id) +{ +} + +Dsymbol *UnionDeclaration::syntaxCopy(Dsymbol *s) +{ + UnionDeclaration *ud; + + if (s) + ud = (UnionDeclaration *)s; + else + ud = new UnionDeclaration(loc, ident); + StructDeclaration::syntaxCopy(ud); + return ud; +} + + +const char *UnionDeclaration::kind() +{ + return "union"; +} + + diff -r 1853dcd9b944 -r e961851fb8be dmd/template.c --- a/dmd/template.c Fri Apr 03 17:02:52 2009 +0200 +++ b/dmd/template.c Fri Apr 03 17:59:34 2009 +0200 @@ -14,12 +14,7 @@ #include #if !IN_LLVM -#if _WIN32 -#include -long __cdecl __ehfilter(LPEXCEPTION_POINTERS ep); #endif -#endif - #include "root.h" #include "rmem.h" #include "stringtable.h" @@ -36,6 +31,11 @@ #include "dsymbol.h" #include "hdrgen.h" +#if WINDOWS_SEH +#include +long __cdecl __ehfilter(LPEXCEPTION_POINTERS ep); +#endif + #define LOG 0 /******************************************** @@ -159,6 +159,8 @@ } } + //printf("t1 = %s\n", t1->toChars()); + //printf("t2 = %s\n", t2->toChars()); if (!t2 || !t1->equals(t2)) goto Lnomatch; } @@ -186,7 +188,7 @@ { goto Lnomatch; } -#if V2 +#if DMDV2 VarDeclaration *v1 = s1->isVarDeclaration(); VarDeclaration *v2 = s2->isVarDeclaration(); if (v1 && v2 && v1->storage_class & v2->storage_class & STCmanifest) @@ -263,7 +265,7 @@ } } -#if V2 +#if DMDV2 Object *objectSyntaxCopy(Object *o) { if (!o) @@ -281,7 +283,8 @@ /* ======================== TemplateDeclaration ============================= */ -TemplateDeclaration::TemplateDeclaration(Loc loc, Identifier *id, TemplateParameters *parameters, Array *decldefs) +TemplateDeclaration::TemplateDeclaration(Loc loc, Identifier *id, + TemplateParameters *parameters, Expression *constraint, Array *decldefs) : ScopeDsymbol(id) { #if LOG @@ -303,9 +306,7 @@ this->loc = loc; this->parameters = parameters; this->origParameters = parameters; -#if V2 this->constraint = constraint; -#endif this->members = decldefs; this->overnext = NULL; this->overroot = NULL; @@ -330,13 +331,11 @@ p->data[i] = (void *)tp->syntaxCopy(); } } -#if V2 Expression *e = NULL; if (constraint) e = constraint->syntaxCopy(); -#endif d = Dsymbol::arraySyntaxCopy(members); - td = new TemplateDeclaration(loc, ident, p, d); + td = new TemplateDeclaration(loc, ident, p, e, d); #if IN_LLVM // LDC @@ -673,11 +672,11 @@ /******************************************** * Determine partial specialization order of 'this' vs td2. * Returns: - * 1 this is at least as specialized as td2 + * match this is at least as specialized as td2 * 0 td2 is more specialized than this */ -int TemplateDeclaration::leastAsSpecialized(TemplateDeclaration *td2) +MATCH TemplateDeclaration::leastAsSpecialized(TemplateDeclaration *td2) { /* This works by taking the template parameters to this template * declaration and feeding them to td2 as if it were a template @@ -715,7 +714,8 @@ dedtypes.setDim(td2->parameters->dim); // Attempt a type deduction - if (td2->matchWithInstance(&ti, &dedtypes, 1)) + MATCH m = td2->matchWithInstance(&ti, &dedtypes, 1); + if (m) { /* A non-variadic template is more specialized than a * variadic one. @@ -724,15 +724,15 @@ goto L1; #if LOG_LEASTAS - printf(" matches, so is least as specialized\n"); + printf(" matches %d, so is least as specialized\n", m); #endif - return 1; + return m; } L1: #if LOG_LEASTAS printf(" doesn't match, so is not as specialized\n"); #endif - return 0; + return MATCHnomatch; } @@ -762,7 +762,6 @@ MATCH match = MATCHexact; FuncDeclaration *fd = onemember->toAlias()->isFuncDeclaration(); TypeFunction *fdtype; // type of fd - TemplateTupleParameter *tp; Objects dedtypes; // for T:T*, the dedargs is the T*, dedtypes is the T #if 0 @@ -786,7 +785,18 @@ paramsym->parent = scope->parent; Scope *paramscope = scope->push(paramsym); - tp = isVariadic(); + TemplateTupleParameter *tp = isVariadic(); + +#if 0 + for (i = 0; i < dedargs->dim; i++) + { + printf("\tdedarg[%d] = ", i); + Object *oarg = (Object *)dedargs->data[i]; + if (oarg) printf("%s", oarg->toChars()); + printf("\n"); + } +#endif + nargsi = 0; if (targsi) @@ -802,11 +812,11 @@ memcpy(dedargs->data, targsi->data, nargsi * sizeof(*dedargs->data)); - for (i = 0; i < nargsi; i++) + for (size_t i = 0; i < nargsi; i++) { assert(i < parameters->dim); TemplateParameter *tp = (TemplateParameter *)parameters->data[i]; MATCH m; - Declaration *sparam; + Declaration *sparam = NULL; m = tp->matchArg(paramscope, dedargs, i, parameters, &dedtypes, &sparam); //printf("\tdeduceType m = %d\n", m); @@ -820,6 +830,15 @@ goto Lnomatch; } } +#if 0 + for (i = 0; i < dedargs->dim; i++) + { + printf("\tdedarg[%d] = ", i); + Object *oarg = (Object *)dedargs->data[i]; + if (oarg) printf("%s", oarg->toChars()); + printf("\n"); + } +#endif assert(fd->type->ty == Tfunction); fdtype = (TypeFunction *)fd->type; @@ -833,7 +852,6 @@ * template Foo(T, A...) { void Foo(T t, A a); } * void main() { Foo(1,2,3); } */ - tp = isVariadic(); if (tp) // if variadic { if (nfparams == 0) // if no function parameters @@ -906,7 +924,7 @@ { MATCH m; Type *t = new TypeIdentifier(0, ttp->ident); - m = ethis->type->deduceType(scope, t, parameters, &dedtypes); + m = ethis->type->deduceType(paramscope, t, parameters, &dedtypes); if (!m) goto Lnomatch; if (m < match) @@ -946,9 +964,25 @@ printf("\tfarg->type = %s\n", farg->type->toChars()); printf("\tfparam->type = %s\n", fparam->type->toChars()); #endif + Type *argtype = farg->type; + +#if DMDV2 + /* Allow string literals which are type [] to match with [dim] + */ + if (farg->op == TOKstring) + { StringExp *se = (StringExp *)farg; + if (!se->committed && argtype->ty == Tarray && + fparam->type->toBasetype()->ty == Tsarray) + { + argtype = new TypeSArray(argtype->nextOf(), new IntegerExp(se->loc, se->len, Type::tindex)); + argtype = argtype->semantic(se->loc, NULL); + argtype = argtype->invariantOf(); + } + } +#endif MATCH m; - m = farg->type->deduceType(scope, fparam->type, parameters, &dedtypes); + m = argtype->deduceType(paramscope, fparam->type, parameters, &dedtypes); //printf("\tdeduceType m = %d\n", m); /* If no match, see if there's a conversion to a delegate @@ -960,7 +994,7 @@ if (!tf->varargs && Argument::dim(tf->parameters) == 0) { - m = farg->type->deduceType(scope, tf->next, parameters, &dedtypes); + m = farg->type->deduceType(paramscope, tf->next, parameters, &dedtypes); if (!m && tf->next->toBasetype()->ty == Tvoid) m = MATCHconvert; } @@ -988,7 +1022,7 @@ // Perhaps we can do better with this, see TypeFunction::callMatch() case Tsarray: { TypeSArray *tsa = (TypeSArray *)tb; - integer_t sz = tsa->dim->toInteger(); + dinteger_t sz = tsa->dim->toInteger(); if (sz != nfargs - i) goto Lnomatch; } @@ -1020,7 +1054,7 @@ } else { - m = arg->type->deduceType(scope, ta->next, parameters, &dedtypes); + m = arg->type->deduceType(paramscope, ta->next, parameters, &dedtypes); //m = arg->implicitConvTo(ta->next); } if (m == MATCHnomatch) @@ -1053,6 +1087,8 @@ Object *oarg = (Object *)dedargs->data[i]; Object *oded = (Object *)dedtypes.data[i]; //printf("1dedargs[%d] = %p, dedtypes[%d] = %p\n", i, oarg, i, oded); + //if (oarg) printf("oarg: %s\n", oarg->toChars()); + //if (oded) printf("oded: %s\n", oded->toChars()); if (!oarg) { if (oded) @@ -1134,6 +1170,22 @@ Dsymbol *s; + // See if tp->ident already exists with a matching definition + Dsymbol *scopesym; + s = sc->search(loc, tp->ident, &scopesym); + if (s && scopesym == sc->scopesym) + { + TupleDeclaration *td = s->isTupleDeclaration(); + if (va && td) + { Tuple tup; + tup.objects = *td->objects; + if (match(va, &tup, this, sc)) + { + return; + } + } + } + if (targ) { //printf("type %s\n", targ->toChars()); @@ -1267,8 +1319,8 @@ { // Disambiguate by picking the most specialized TemplateDeclaration - int c1 = td->leastAsSpecialized(td_best); - int c2 = td_best->leastAsSpecialized(td); + MATCH c1 = td->leastAsSpecialized(td_best); + MATCH c2 = td_best->leastAsSpecialized(td); //printf("c1 = %d, c2 = %d\n", c1, c2); if (c1 > c2) @@ -1298,7 +1350,7 @@ } if (!td_best) { - error(loc, "does not match any template declaration"); + error(loc, "does not match any function template declaration"); goto Lerror; } if (td_ambig) @@ -1319,6 +1371,9 @@ return fd; Lerror: +#if DMDV2 + if (!(flags & 1)) +#endif { HdrGenState hgs; @@ -1537,8 +1592,29 @@ Lnomatch: return MATCHnomatch; + +#if DMDV2 +Lconst: + return MATCHconst; +#endif } +#if DMDV2 +MATCH TypeDArray::deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, + Objects *dedtypes) +{ +#if 0 + printf("TypeDArray::deduceType()\n"); + printf("\tthis = %d, ", ty); print(); + printf("\ttparam = %d, ", tparam->ty); tparam->print(); +#endif + return Type::deduceType(sc, tparam, parameters, dedtypes); + + Lnomatch: + return MATCHnomatch; +} +#endif + MATCH TypeSArray::deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes) { @@ -1765,8 +1841,11 @@ Type *tparam, TemplateParameters *parameters, Objects *dedtypes) { - //printf("TypeInstance::deduceType(tparam = %s) %s\n", tparam->toChars(), toChars()); - //printf("\ttparam = %d, ", tparam->ty); tparam->print(); +#if 0 + printf("TypeInstance::deduceType()\n"); + printf("\tthis = %d, ", ty); print(); + printf("\ttparam = %d, ", tparam->ty); tparam->print(); +#endif // Extra check if (tparam && tparam->ty == Tinstance) @@ -1802,14 +1881,14 @@ TemplateAliasParameter *ta = tpx->isTemplateAliasParameter(); if (!ta) goto Lnomatch; - Dsymbol *sa = tempinst->tempdecl; + Object *sa = tempinst->tempdecl; if (!sa) goto Lnomatch; if (ta->specAlias && sa != ta->specAlias) goto Lnomatch; if (dedtypes->data[i]) { // Must match already deduced symbol - Dsymbol *s = (Dsymbol *)dedtypes->data[i]; + Object *s = (Object *)dedtypes->data[i]; if (s != sa) goto Lnomatch; @@ -1821,12 +1900,13 @@ goto Lnomatch; L2: - if (tempinst->tiargs->dim != tp->tempinst->tiargs->dim) - goto Lnomatch; for (int i = 0; i < tempinst->tiargs->dim; i++) { //printf("\ttest: tempinst->tiargs[%d]\n", i); + if (i >= tp->tempinst->tiargs->dim) + goto Lnomatch; + int j; Object *o1 = (Object *)tempinst->tiargs->data[i]; Object *o2 = (Object *)tp->tempinst->tiargs->data[i]; @@ -1853,6 +1933,43 @@ if (v2) printf("v2 = %s\n", v2->toChars()); #endif + TemplateTupleParameter *ttp; + if (t2 && + t2->ty == Tident && + i == tp->tempinst->tiargs->dim - 1 && + i == tempinst->tempdecl->parameters->dim - 1 && + (ttp = tempinst->tempdecl->isVariadic()) != NULL) + { + /* Given: + * struct A(B...) {} + * alias A!(int, float) X; + * static if (!is(X Y == A!(Z), Z)) + * deduce that Z is a tuple(int, float) + */ + + j = templateParameterLookup(t2, parameters); + if (j == -1) + goto Lnomatch; + + /* Create tuple from remaining args + */ + Tuple *vt = new Tuple(); + int vtdim = tempinst->tiargs->dim - i; + vt->objects.setDim(vtdim); + for (size_t k = 0; k < vtdim; k++) + vt->objects.data[k] = (void *)tempinst->tiargs->data[i + k]; + + Tuple *v = (Tuple *)dedtypes->data[j]; + if (v) + { + if (!match(v, vt, tempinst->tempdecl, sc)) + goto Lnomatch; + } + else + dedtypes->data[j] = vt; + break; //return MATCHexact; + } + if (t1 && t2) { if (!t1->deduceType(sc, t2, parameters, dedtypes)) @@ -3299,12 +3416,10 @@ sc2->parent = /*isnested ? sc->parent :*/ this; sc2->tinst = this; -#if !IN_LLVM -#if _WIN32 +#if WINDOWS_SEH __try { #endif -#endif for (int i = 0; i < members->dim; i++) { Dsymbol *s = (Dsymbol *)members->data[i]; @@ -3317,8 +3432,7 @@ //printf("test4: isnested = %d, s->parent = %s\n", isnested, s->parent->toChars()); sc2->module->runDeferredSemantic(); } -#if !IN_LLVM -#if _WIN32 +#if WINDOWS_SEH } __except (__ehfilter(GetExceptionInformation())) { @@ -3327,7 +3441,6 @@ fatal(); } #endif -#endif /* If any of the instantiation members didn't get semantic() run * on them due to forward references, we cannot run semantic2() @@ -3385,10 +3498,15 @@ if (semantictiargsdone) return; semantictiargsdone = 1; - semanticTiargs(loc, sc, tiargs); + semanticTiargs(loc, sc, tiargs, 0); } -void TemplateInstance::semanticTiargs(Loc loc, Scope *sc, Objects *tiargs) +/********************************** + * Input: + * flags 1: replace const variables with their initializers + */ + +void TemplateInstance::semanticTiargs(Loc loc, Scope *sc, Objects *tiargs, int flags) { // Run semantic on each argument, place results in tiargs[] //printf("+TemplateInstance::semanticTiargs() %s\n", toChars()); @@ -3636,8 +3754,8 @@ { // Disambiguate by picking the most specialized TemplateDeclaration - int c1 = td->leastAsSpecialized(td_best); - int c2 = td_best->leastAsSpecialized(td); + MATCH c1 = td->leastAsSpecialized(td_best); + MATCH c2 = td_best->leastAsSpecialized(td); //printf("c1 = %d, c2 = %d\n", c1, c2); if (c1 > c2) @@ -3667,7 +3785,11 @@ if (!td_best) { - error("%s does not match any template declaration", toChars()); + if (tempdecl && !tempdecl->overnext) + // Only one template, so we can give better error message + error("%s does not match template declaration %s", toChars(), tempdecl->toChars()); + else + error("%s does not match any template declaration", toChars()); return NULL; } if (td_ambig) @@ -3777,7 +3899,7 @@ nested |= 1; } else - error("cannot use local '%s' as template parameter", d->toChars()); + error("cannot use local '%s' as parameter to non-global template %s", d->toChars(), tempdecl->toChars()); } } else if (va) diff -r 1853dcd9b944 -r e961851fb8be dmd/template.h --- a/dmd/template.h Fri Apr 03 17:02:52 2009 +0200 +++ b/dmd/template.h Fri Apr 03 17:59:34 2009 +0200 @@ -54,9 +54,7 @@ TemplateParameters *parameters; // array of TemplateParameter's TemplateParameters *origParameters; // originals for Ddoc -#if DMDV2 Expression *constraint; -#endif Array instances; // array of TemplateInstance's TemplateDeclaration *overnext; // next overloaded TemplateDeclaration @@ -66,10 +64,7 @@ Dsymbol *onemember; // if !=NULL then one member of this template TemplateDeclaration(Loc loc, Identifier *id, TemplateParameters *parameters, -#if DMDV2 - Expression *constraint, -#endif - Array *decldefs); + Expression *constraint, Array *decldefs); Dsymbol *syntaxCopy(Dsymbol *); void semantic(Scope *sc); int overloadInsert(Dsymbol *s); @@ -81,7 +76,7 @@ // void toDocBuffer(OutBuffer *buf); MATCH matchWithInstance(TemplateInstance *ti, Objects *atypes, int flag); - int leastAsSpecialized(TemplateDeclaration *td2); + MATCH leastAsSpecialized(TemplateDeclaration *td2); MATCH deduceFunctionTemplateMatch(Loc loc, Objects *targsi, Expression *ethis, Expressions *fargs, Objects *dedargs); FuncDeclaration *deduceFunctionTemplate(Scope *sc, Loc loc, Objects *targsi, Expression *ethis, Expressions *fargs, int flags = 0); @@ -108,6 +103,8 @@ * template Foo(valType ident : specValue) * For alias-parameter: * template Foo(alias ident) + * For this-parameter: + * template Foo(this ident) */ Loc loc; @@ -216,7 +213,7 @@ struct TemplateAliasParameter : TemplateParameter { /* Syntax: - * ident : specAlias = defaultAlias + * specType ident : specAlias = defaultAlias */ Type *specAliasT; @@ -317,7 +314,7 @@ #endif // Internal - static void semanticTiargs(Loc loc, Scope *sc, Objects *tiargs); + static void semanticTiargs(Loc loc, Scope *sc, Objects *tiargs, int flags); void semanticTiargs(Scope *sc); TemplateDeclaration *findTemplateDeclaration(Scope *sc); TemplateDeclaration *findBestMatch(Scope *sc);