# HG changeset patch # User Robert Clipsham # Date 1246929971 -3600 # Node ID 54b3c1394d620a6a8f464e430897a8169f1c6c1a # Parent d28cd7c45267f8efb6efd0dffd49619f122861dc Merged dmdfe 2.031. diff -r d28cd7c45267 -r 54b3c1394d62 dmd2/arrayop.c --- a/dmd2/arrayop.c Mon Jul 06 23:57:27 2009 +0100 +++ b/dmd2/arrayop.c Tue Jul 07 02:26:11 2009 +0100 @@ -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 @@ -435,6 +435,12 @@ /* Evaluate assign expressions right to left */ Expression *ex2 = e2->buildArrayLoop(fparams); + /* Need the cast because: + * b = c + p[i]; + * where b is a byte fails because (c + p[i]) is an int + * which cannot be implicitly cast to byte. + */ + ex2 = new CastExp(0, ex2, e1->type->nextOf()); Expression *ex1 = e1->buildArrayLoop(fparams); Argument *param = (Argument *)fparams->data[0]; param->storageClass = 0; diff -r d28cd7c45267 -r 54b3c1394d62 dmd2/attrib.c --- a/dmd2/attrib.c Mon Jul 06 23:57:27 2009 +0100 +++ b/dmd2/attrib.c Tue Jul 07 02:26:11 2009 +0100 @@ -26,6 +26,9 @@ #include "module.h" #include "parse.h" #include "template.h" +#if TARGET_NET + #include "frontend.net/pragma.h" +#endif #if IN_LLVM #include "../gen/enums.h" @@ -74,6 +77,41 @@ return m; } +void AttribDeclaration::semanticNewSc(Scope *sc, + unsigned stc, enum LINK linkage, enum PROT protection, int explicitProtection, + unsigned structalign) +{ + if (decl) + { + Scope *newsc = sc; + if (stc != sc->stc || + linkage != sc->linkage || + protection != sc->protection || + explicitProtection != sc->explicitProtection || + structalign != sc->structalign) + { + // create new one for changes + newsc = new Scope(*sc); + newsc->flags &= ~SCOPEfree; + newsc->stc = stc; + newsc->linkage = linkage; + newsc->protection = protection; + newsc->explicitProtection = explicitProtection; + newsc->structalign = structalign; + } + for (unsigned i = 0; i < decl->dim; i++) + { Dsymbol *s = (Dsymbol *)decl->data[i]; + + s->semantic(newsc); + } + if (newsc != sc) + { + sc->offset = newsc->offset; + newsc->pop(); + } + } +} + void AttribDeclaration::semantic(Scope *sc) { Array *d = include(sc, NULL); @@ -305,10 +343,38 @@ void StorageClassDeclaration::semantic(Scope *sc) { if (decl) - { unsigned stc_save = sc->stc; + { +#if 1 + unsigned scstc = sc->stc; - if (stc & (STCauto | STCscope | STCstatic | STCextern)) - sc->stc &= ~(STCauto | STCscope | STCstatic | STCextern); + /* These sets of storage classes are mutually exclusive, + * so choose the innermost or most recent one. + */ + if (stc & (STCauto | STCscope | STCstatic | STCextern | STCmanifest)) + scstc &= ~(STCauto | STCscope | STCstatic | STCextern | STCmanifest); + if (stc & (STCauto | STCscope | STCstatic | STCtls | STCmanifest | STCgshared)) + scstc &= ~(STCauto | STCscope | STCstatic | STCtls | STCmanifest | STCgshared); + if (stc & (STCconst | STCimmutable | STCmanifest)) + scstc &= ~(STCconst | STCimmutable | STCmanifest); + if (stc & (STCgshared | STCshared | STCtls)) + scstc &= ~(STCgshared | STCshared | STCtls); + scstc |= stc; + + semanticNewSc(sc, scstc, sc->linkage, sc->protection, sc->explicitProtection, sc->structalign); +#else + unsigned stc_save = sc->stc; + + /* These sets of storage classes are mutually exclusive, + * so choose the innermost or most recent one. + */ + if (stc & (STCauto | STCscope | STCstatic | STCextern | STCmanifest)) + sc->stc &= ~(STCauto | STCscope | STCstatic | STCextern | STCmanifest); + if (stc & (STCauto | STCscope | STCstatic | STCtls | STCmanifest | STCgshared)) + sc->stc &= ~(STCauto | STCscope | STCstatic | STCtls | STCmanifest | STCgshared); + if (stc & (STCconst | STCimmutable | STCmanifest)) + sc->stc &= ~(STCconst | STCimmutable | STCmanifest); + if (stc & (STCgshared | STCshared | STCtls)) + sc->stc &= ~(STCgshared | STCshared | STCtls); sc->stc |= stc; for (unsigned i = 0; i < decl->dim; i++) { @@ -317,9 +383,8 @@ s->semantic(sc); } sc->stc = stc_save; +#endif } - else - sc->stc = stc; } void StorageClassDeclaration::stcToCBuffer(OutBuffer *buf, int stc) @@ -393,7 +458,11 @@ { //printf("LinkDeclaration::semantic(linkage = %d, decl = %p)\n", linkage, decl); if (decl) - { enum LINK linkage_save = sc->linkage; + { +#if 1 + semanticNewSc(sc, sc->stc, linkage, sc->protection, sc->explicitProtection, sc->structalign); +#else + enum LINK linkage_save = sc->linkage; sc->linkage = linkage; for (unsigned i = 0; i < decl->dim; i++) @@ -403,10 +472,7 @@ s->semantic(sc); } sc->linkage = linkage_save; - } - else - { - sc->linkage = linkage; +#endif } } @@ -481,7 +547,11 @@ void ProtDeclaration::semantic(Scope *sc) { if (decl) - { enum PROT protection_save = sc->protection; + { +#if 1 + semanticNewSc(sc, sc->stc, sc->linkage, protection, 1, sc->structalign); +#else + enum PROT protection_save = sc->protection; int explicitProtection_save = sc->explicitProtection; sc->protection = protection; @@ -494,15 +564,13 @@ } sc->protection = protection_save; sc->explicitProtection = explicitProtection_save; - } - else - { sc->protection = protection; - sc->explicitProtection = 1; +#endif } } -void ProtDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) -{ const char *p; +void ProtDeclaration::protectionToCBuffer(OutBuffer *buf, enum PROT protection) +{ + const char *p; switch (protection) { @@ -516,6 +584,12 @@ break; } buf->writestring(p); + buf->writeByte(' '); +} + +void ProtDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) +{ + protectionToCBuffer(buf, protection); AttribDeclaration::toCBuffer(buf, hgs); } @@ -545,7 +619,12 @@ //printf("\tAlignDeclaration::semantic '%s'\n",toChars()); if (decl) - { unsigned salign_save = sc->structalign; + { +#if 1 + semanticNewSc(sc, sc->stc, sc->linkage, sc->protection, sc->explicitProtection, salign); +#else + unsigned salign_save = sc->structalign; + #if IN_DMD sc->structalign = salign; #endif @@ -553,6 +632,7 @@ { Dsymbol *s = (Dsymbol *)decl->data[i]; +#if IN_LLVM if (s->isStructDeclaration() && salign == 1) { sc->structalign = salign; @@ -561,10 +641,14 @@ } else { +#endif s->semantic(sc); +#if IN_LLVM } +#endif } sc->structalign = salign_save; +#endif } else assert(0 && "what kind of align use triggers this?"); @@ -584,7 +668,6 @@ { this->loc = loc; this->isunion = isunion; - this->scope = NULL; this->sem = 0; } @@ -895,7 +978,27 @@ } goto Lnodecl; } - +#if TARGET_NET + else if (ident == Lexer::idPool("assembly")) + { + if (!args || args->dim != 1) + error("pragma has invalid number of arguments"); + else + { + Expression *e = (Expression *)args->data[0]; + e = e->semantic(sc); + e = e->optimize(WANTvalue | WANTinterpret); + args->data[0] = (void *)e; + if (e->op != TOKstring) + { + error("string expected, not '%s'", e->toChars()); + } + PragmaScope* pragma = new PragmaScope(this, sc->parent, static_cast(e)); + decl = new Array; + decl->push(pragma); + } + } +#endif // TARGET_NET // LDC #if IN_LLVM diff -r d28cd7c45267 -r 54b3c1394d62 dmd2/attrib.h --- a/dmd2/attrib.h Mon Jul 06 23:57:27 2009 +0100 +++ b/dmd2/attrib.h Tue Jul 07 02:26:11 2009 +0100 @@ -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 @@ -36,6 +36,9 @@ AttribDeclaration(Array *decl); virtual Array *include(Scope *sc, ScopeDsymbol *s); int addMember(Scope *sc, ScopeDsymbol *s, int memnum); + void semanticNewSc(Scope *sc, + unsigned newstc, enum LINK linkage, enum PROT protection, int explictProtection, + unsigned structalign); void semantic(Scope *sc); void semantic2(Scope *sc); void semantic3(Scope *sc); @@ -92,6 +95,8 @@ Dsymbol *syntaxCopy(Dsymbol *s); void semantic(Scope *sc); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); + + static void protectionToCBuffer(OutBuffer *buf, enum PROT protection); }; struct AlignDeclaration : AttribDeclaration @@ -107,7 +112,6 @@ struct AnonDeclaration : AttribDeclaration { int isunion; - Scope *scope; // !=NULL means context to use int sem; // 1 if successful semantic() AnonDeclaration(Loc loc, int isunion, Array *decl); diff -r d28cd7c45267 -r 54b3c1394d62 dmd2/cast.c --- a/dmd2/cast.c Mon Jul 06 23:57:27 2009 +0100 +++ b/dmd2/cast.c Tue Jul 07 02:26:11 2009 +0100 @@ -33,6 +33,7 @@ if (match) { TY tyfrom = type->toBasetype()->ty; TY tyto = t->toBasetype()->ty; +#if DMDV1 if (global.params.warnings && Type::impcnvWarn[tyfrom][tyto] && op != TOKint64) @@ -41,7 +42,6 @@ if (e->op == TOKint64) return e->implicitCastTo(sc, t); - if (tyfrom == Tint32 && (op == TOKadd || op == TOKmin || op == TOKand || op == TOKor || op == TOKxor) @@ -61,6 +61,7 @@ toChars(), type->toChars(), t->toChars()); } } +#endif #if DMDV2 if (match == MATCHconst && t == type->constOf()) { @@ -144,6 +145,16 @@ MATCH match = type->implicitConvTo(t); if (match != MATCHnomatch) return match; + + /* See if we can do integral narrowing conversions + */ + if (type->isintegral() && t->isintegral() && + type->isTypeBasic() && t->isTypeBasic()) + { IntRange ir = getIntRange(); + if (ir.imax <= t->sizemask()) + return MATCHconvert; + } + #if 0 Type *tb = t->toBasetype(); if (tb->ty == Tdelegate) @@ -676,18 +687,72 @@ return result; } +MATCH OrExp::implicitConvTo(Type *t) +{ + MATCH result = Expression::implicitConvTo(t); + + if (result == MATCHnomatch) + { + MATCH m1 = e1->implicitConvTo(t); + MATCH m2 = e2->implicitConvTo(t); + + // Pick the worst match + result = (m1 < m2) ? m1 : m2; + } + return result; +} + +MATCH XorExp::implicitConvTo(Type *t) +{ + MATCH result = Expression::implicitConvTo(t); + + if (result == MATCHnomatch) + { + MATCH m1 = e1->implicitConvTo(t); + MATCH m2 = e2->implicitConvTo(t); + + // Pick the worst match + result = (m1 < m2) ? m1 : m2; + } + return result; +} + MATCH CondExp::implicitConvTo(Type *t) { - MATCH m1; - MATCH m2; - - m1 = e1->implicitConvTo(t); - m2 = e2->implicitConvTo(t); + MATCH m1 = e1->implicitConvTo(t); + MATCH m2 = e2->implicitConvTo(t); + //printf("CondExp: m1 %d m2 %d\n", m1, m2); // Pick the worst match return (m1 < m2) ? m1 : m2; } +MATCH CommaExp::implicitConvTo(Type *t) +{ + return e2->implicitConvTo(t); +} + +MATCH CastExp::implicitConvTo(Type *t) +{ +#if 0 + printf("CastExp::implicitConvTo(this=%s, type=%s, t=%s)\n", + toChars(), type->toChars(), t->toChars()); +#endif + MATCH result; + + result = type->implicitConvTo(t); + + if (result == MATCHnomatch) + { + if (t->isintegral() && + e1->type->isintegral() && + e1->implicitConvTo(t) != MATCHnomatch) + result = MATCHconvert; + else + result = Expression::implicitConvTo(t); + } + return result; +} /* ==================== castTo ====================== */ @@ -1258,22 +1323,35 @@ f = f->overloadExactMatch(tb->nextOf(), m); if (f) { - if (tb->ty == Tdelegate && f->needThis() && hasThis(sc)) + if (tb->ty == Tdelegate) { - e = new DelegateExp(loc, new ThisExp(loc), f); - e = e->semantic(sc); - } - else if (tb->ty == Tdelegate && f->isNested()) - { - e = new DelegateExp(loc, new IntegerExp(0), f); - e = e->semantic(sc); + if (f->needThis() && hasThis(sc)) + { + e = new DelegateExp(loc, new ThisExp(loc), f); + e = e->semantic(sc); + } + else if (f->isNested()) + { + e = new DelegateExp(loc, new IntegerExp(0), f); + e = e->semantic(sc); + } + else if (f->needThis()) + { error("no 'this' to create delegate for %s", f->toChars()); + e = new ErrorExp(); + } + else + { error("cannot cast from function pointer to delegate"); + e = new ErrorExp(); + } } else { e = new SymOffExp(loc, f, 0); e->type = t; } +#if DMDV2 f->tookAddressOf++; +#endif return e; } } @@ -1353,6 +1431,23 @@ return e; } +Expression *CommaExp::castTo(Scope *sc, Type *t) +{ + Expression *e2c = e2->castTo(sc, t); + Expression *e; + + if (e2c != e2) + { + e = new CommaExp(loc, e1, e2c); + e->type = e2c->type; + } + else + { e = this; + e->type = e2->type; + } + return e; +} + /* ==================== ====================== */ /**************************************** @@ -1777,3 +1872,226 @@ } return 0; } + +/******************************************************************/ + +/* Determine the integral ranges of an expression. + * This is used to determine if implicit narrowing conversions will + * be allowed. + */ + +uinteger_t getMask(uinteger_t v) +{ + uinteger_t u = 0; + if (v >= 0x80) + u = 0xFF; + while (u < v) + u = (u << 1) | 1; + return u; +} + +IntRange Expression::getIntRange() +{ + IntRange ir; + ir.imin = 0; + ir.imax = type->sizemask(); + return ir; +} + +IntRange IntegerExp::getIntRange() +{ + IntRange ir; + ir.imin = value & type->sizemask(); + ir.imax = ir.imin; + return ir; +} + +IntRange CastExp::getIntRange() +{ + IntRange ir; + ir = e1->getIntRange(); + // Do sign extension + switch (e1->type->toBasetype()->ty) + { + case Tint8: + if (ir.imax & 0x80) + ir.imax |= 0xFFFFFFFFFFFFFF00ULL; + break; + case Tint16: + if (ir.imax & 0x8000) + ir.imax |= 0xFFFFFFFFFFFF0000ULL; + break; + case Tint32: + if (ir.imax & 0x80000000) + ir.imax |= 0xFFFFFFFF00000000ULL; + break; + } + ir.imin &= type->sizemask(); + ir.imax &= type->sizemask(); +//printf("CastExp: imin = x%llx, imax = x%llx\n", ir.imin, ir.imax); + return ir; +} + +IntRange DivExp::getIntRange() +{ + if (!e1->type->isunsigned() && !e2->type->isunsigned()) + return Expression::getIntRange(); + + IntRange ir; + IntRange ir1 = e1->getIntRange(); + IntRange ir2 = e2->getIntRange(); + + ir.imin = ir1.imin / ir2.imax; + ir.imax = ir1.imax / ir2.imin; + + ir.imin &= type->sizemask(); + ir.imax &= type->sizemask(); + +//printf("DivExp: imin = x%llx, imax = x%llx\n", ir.imin, ir.imax); +//e1->dump(0); + + return ir; +} + +IntRange AndExp::getIntRange() +{ + IntRange ir; + IntRange ir1 = e1->getIntRange(); + IntRange ir2 = e2->getIntRange(); + + ir.imin = ir1.imin; + if (ir2.imin < ir.imin) + ir.imin = ir2.imin; + + ir.imax = ir1.imax; + if (ir2.imax > ir.imax) + ir.imax = ir2.imax; + + uinteger_t u; + + u = getMask(ir1.imax); + ir.imin &= u; + ir.imax &= u; + + u = getMask(ir2.imax); + ir.imin &= u; + ir.imax &= u; + + ir.imin &= type->sizemask(); + ir.imax &= type->sizemask(); + +//printf("AndExp: imin = x%llx, imax = x%llx\n", ir.imin, ir.imax); +//e1->dump(0); + + return ir; +} + +IntRange OrExp::getIntRange() +{ + IntRange ir; + IntRange ir1 = e1->getIntRange(); + IntRange ir2 = e2->getIntRange(); + + ir.imin = ir1.imin; + if (ir2.imin < ir.imin) + ir.imin = ir2.imin; + + ir.imax = ir1.imax; + if (ir2.imax > ir.imax) + ir.imax = ir2.imax; + + ir.imin &= type->sizemask(); + ir.imax &= type->sizemask(); + +//printf("OrExp: imin = x%llx, imax = x%llx\n", ir.imin, ir.imax); +//e1->dump(0); + + return ir; +} + +IntRange XorExp::getIntRange() +{ + IntRange ir; + IntRange ir1 = e1->getIntRange(); + IntRange ir2 = e2->getIntRange(); + + ir.imin = ir1.imin; + if (ir2.imin < ir.imin) + ir.imin = ir2.imin; + + ir.imax = ir1.imax; + if (ir2.imax > ir.imax) + ir.imax = ir2.imax; + + ir.imin &= type->sizemask(); + ir.imax &= type->sizemask(); + +//printf("XorExp: imin = x%llx, imax = x%llx\n", ir.imin, ir.imax); +//e1->dump(0); + + return ir; +} + +IntRange ShlExp::getIntRange() +{ + IntRange ir; + IntRange ir1 = e1->getIntRange(); + IntRange ir2 = e2->getIntRange(); + + ir.imin = getMask(ir1.imin) << ir2.imin; + ir.imax = getMask(ir1.imax) << ir2.imax; + + ir.imin &= type->sizemask(); + ir.imax &= type->sizemask(); + +//printf("ShlExp: imin = x%llx, imax = x%llx\n", ir.imin, ir.imax); +//e1->dump(0); + + return ir; +} + +IntRange ShrExp::getIntRange() +{ + if (!e1->type->isunsigned()) + return Expression::getIntRange(); + + IntRange ir; + IntRange ir1 = e1->getIntRange(); + IntRange ir2 = e2->getIntRange(); + + ir.imin = ir1.imin >> ir2.imax; + ir.imax = ir1.imax >> ir2.imin; + + ir.imin &= type->sizemask(); + ir.imax &= type->sizemask(); + +//printf("ShrExp: imin = x%llx, imax = x%llx\n", ir.imin, ir.imax); +//e1->dump(0); + + return ir; +} + +IntRange UshrExp::getIntRange() +{ + IntRange ir; + IntRange ir1 = e1->getIntRange(); + IntRange ir2 = e2->getIntRange(); + + ir.imin = ir1.imin >> ir2.imax; + ir.imax = ir1.imax >> ir2.imin; + + ir.imin &= type->sizemask(); + ir.imax &= type->sizemask(); + +//printf("UshrExp: imin = x%llx, imax = x%llx\n", ir.imin, ir.imax); +//e1->dump(0); + + return ir; +} + +IntRange CommaExp::getIntRange() +{ + return e2->getIntRange(); +} + + diff -r d28cd7c45267 -r 54b3c1394d62 dmd2/class.c --- a/dmd2/class.c Mon Jul 06 23:57:27 2009 +0100 +++ b/dmd2/class.c Tue Jul 07 02:26:11 2009 +0100 @@ -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 @@ -233,14 +233,14 @@ ident = Identifier::generateId(id); } - if (!scope) - { - if (!parent && sc->parent && !sc->parent->isModule()) - parent = sc->parent; + if (!sc) + sc = scope; + if (!parent && sc->parent && !sc->parent->isModule()) + parent = sc->parent; - type = type->semantic(loc, sc); - handle = handle->semantic(loc, sc); - } + type = type->semantic(loc, sc); + handle = type; + if (!members) // if forward reference { //printf("\tclass '%s' is forward referenced\n", toChars()); return; @@ -275,7 +275,9 @@ // Expand any tuples in baseclasses[] for (i = 0; i < baseclasses.dim; ) { BaseClass *b = (BaseClass *)baseclasses.data[i]; +//printf("test1 %s %s\n", toChars(), b->type->toChars()); b->type = b->type->semantic(loc, sc); +//printf("test2\n"); Type *tb = b->type->toBasetype(); if (tb->ty == Ttuple) @@ -334,8 +336,14 @@ goto L7; } } + if (!tc->sym->symtab || tc->sym->sizeok == 0) + { // Try to resolve forward reference + if (sc->mustsemantic && tc->sym->scope) + tc->sym->semantic(NULL); + } if (!tc->sym->symtab || tc->sym->scope || tc->sym->sizeok == 0) { + //printf("%s: forward reference of base class %s\n", toChars(), tc->sym->toChars()); //error("forward reference of base class %s", baseClass->toChars()); // Forward reference of base class, try again later //printf("\ttry later, forward reference of base class %s\n", tc->sym->toChars()); @@ -793,10 +801,15 @@ //printf("%s.ClassDeclaration::search('%s')\n", toChars(), ident->toChars()); if (scope) - semantic(scope); + { Scope *sc = scope; + sc->mustsemantic++; + semantic(sc); + sc->mustsemantic--; + } if (!members || !symtab || scope) - { error("is forward referenced when looking for '%s'", ident->toChars()); + { + error("is forward referenced when looking for '%s'", ident->toChars()); //*(char*)0=0; return NULL; } @@ -1037,10 +1050,15 @@ //printf("InterfaceDeclaration::semantic(%s), type = %p\n", toChars(), type); if (inuse) return; - if (!scope) - { type = type->semantic(loc, sc); - handle = handle->semantic(loc, sc); - } + + if (!sc) + sc = scope; + if (!parent && sc->parent && !sc->parent->isModule()) + parent = sc->parent; + + type = type->semantic(loc, sc); + handle = type; + if (!members) // if forward reference { //printf("\tinterface '%s' is forward referenced\n", toChars()); return; diff -r d28cd7c45267 -r 54b3c1394d62 dmd2/cond.c --- a/dmd2/cond.c Mon Jul 06 23:57:27 2009 +0100 +++ b/dmd2/cond.c Tue Jul 07 02:26:11 2009 +0100 @@ -143,10 +143,11 @@ "all", "none", - // LDC +#if IN_LLVM "LLVM", "LDC", "LLVM64", "PPC", "PPC64", "darwin","solaris","freebsd" +#endif }; for (unsigned i = 0; i < sizeof(reserved) / sizeof(reserved[0]); i++) diff -r d28cd7c45267 -r 54b3c1394d62 dmd2/constfold.c --- a/dmd2/constfold.c Mon Jul 06 23:57:27 2009 +0100 +++ b/dmd2/constfold.c Tue Jul 07 02:26:11 2009 +0100 @@ -853,9 +853,13 @@ Loc loc = e1->loc; int cmp; - if (e1->op == TOKnull && e2->op == TOKnull) + if (e1->op == TOKnull) { - cmp = 1; + cmp = (e2->op == TOKnull); + } + else if (e2->op == TOKnull) + { + cmp = 0; } else if (e1->op == TOKsymoff && e2->op == TOKsymoff) { diff -r d28cd7c45267 -r 54b3c1394d62 dmd2/declaration.c --- a/dmd2/declaration.c Mon Jul 06 23:57:27 2009 +0100 +++ b/dmd2/declaration.c Tue Jul 07 02:26:11 2009 +0100 @@ -463,6 +463,7 @@ if (s && ((s->getType() && type->equals(s->getType())) || s->isEnumMember())) goto L2; // it's a symbolic alias +#if DMDV2 if (storage_class & STCref) { // For 'ref' to be attached to function types, and picked // up by Type::resolve(), it has to go into sc. @@ -472,6 +473,7 @@ sc = sc->pop(); } else +#endif type->resolve(loc, sc, &e, &t, &s); if (s) { @@ -488,7 +490,9 @@ t = e->type; } else if (t) + { type = t; + } if (overnext) ScopeDsymbol::multiplyDefined(0, this, overnext); this->inSemantic = 0; @@ -511,7 +515,9 @@ if (overnext) { FuncAliasDeclaration *fa = new FuncAliasDeclaration(f); +#if IN_LLVM fa->importprot = importprot; +#endif if (!fa->overloadInsert(overnext)) ScopeDsymbol::multiplyDefined(0, f, overnext); overnext = NULL; @@ -527,6 +533,7 @@ s = NULL; } } + //printf("setting aliassym %p to %p\n", this, s); aliassym = s; this->inSemantic = 0; } @@ -624,12 +631,14 @@ this->loc = loc; offset = 0; noauto = 0; +#if DMDV1 + nestedref = 0; +#endif ctorinit = 0; aliassym = NULL; onstack = 0; canassign = 0; value = NULL; - scope = NULL; #if IN_LLVM aggrIndex = 0; @@ -730,10 +739,12 @@ //printf("sc->stc = %x\n", sc->stc); //printf("storage_class = x%x\n", storage_class); +#if DMDV2 if (storage_class & STCgshared && global.params.safe && !sc->module->safe) { error("__gshared not allowed in safe mode; use shared"); } +#endif Dsymbol *parent = toParent(); FuncDeclaration *fd = parent->isFuncDeclaration(); @@ -851,7 +862,9 @@ if (!aad) aad = parent->isAggregateDeclaration(); if (aad) - { assert(!(storage_class & (STCextern | STCstatic | STCtls | STCgshared))); + { +#if DMDV2 + assert(!(storage_class & (STCextern | STCstatic | STCtls | STCgshared))); if (storage_class & (STCconst | STCimmutable) && init) { @@ -859,6 +872,7 @@ storage_class |= STCstatic; } else +#endif aad->addField(sc, this); } @@ -891,11 +905,13 @@ } } +#if DMDV2 if ((storage_class & (STCref | STCparameter | STCforeach)) == STCref && ident != Id::This) { error("only parameters or foreach declarations can be ref"); } +#endif if (type->isauto() && !noauto) { @@ -940,7 +956,9 @@ Expression *e1; e1 = new VarExp(loc, this); e = new AssignExp(loc, e1, e); +#if DMDV2 e->op = TOKconstruct; +#endif e->type = e1->type; // don't type check this, it would fail init = new ExpInitializer(loc, e); return; @@ -961,8 +979,10 @@ { init = getExpInitializer(); } +#if DMDV2 // Default initializer is always a blit op = TOKblit; +#endif } if (init) @@ -1040,7 +1060,7 @@ else if (t->ty == Tstruct) { ei->exp = ei->exp->semantic(sc); - +#if DMDV2 /* Look to see if initializer is a call to the constructor */ StructDeclaration *sd = ((TypeStruct *)t)->sym; @@ -1078,7 +1098,7 @@ } } } - +#endif if (!ei->exp->implicitConvTo(type)) { Type *ti = ei->exp->type->toBasetype(); // Don't cast away invariant or mutability in initializer @@ -1132,11 +1152,12 @@ { if (global.gag == 0) global.errors = errors; // act as if nothing happened - +#if DMDV2 /* Save scope for later use, to try again */ scope = new Scope(*sc); scope->setNoFree(); +#endif } else if (ei) { @@ -1150,6 +1171,7 @@ { ei->exp = e; // no errors, keep result } +#if DMDV2 else { /* Save scope for later use, to try again @@ -1157,6 +1179,7 @@ scope = new Scope(*sc); scope->setNoFree(); } +#endif } else init = i2; // no errors, keep result @@ -1220,10 +1243,12 @@ buf->writestring(ident->toChars()); if (init) { buf->writestring(" = "); +#if DMDV2 ExpInitializer *ie = init->isExpInitializer(); if (ie && (ie->exp->op == TOKconstruct || ie->exp->op == TOKblit)) ((AssignExp *)ie->exp)->e2->toCBuffer(buf, hgs); else +#endif init->toCBuffer(buf, hgs); } buf->writeByte(';'); @@ -1588,9 +1613,10 @@ void TypeInfoDeclaration::semantic(Scope *sc) { assert(linkage == LINKc); - // LDC +#if IN_LLVM if (!global.params.useAvailableExternally) availableExternally = false; +#endif } /***************************** TypeInfoConstDeclaration **********************/ diff -r d28cd7c45267 -r 54b3c1394d62 dmd2/declaration.h --- a/dmd2/declaration.h Mon Jul 06 23:57:27 2009 +0100 +++ b/dmd2/declaration.h Tue Jul 07 02:26:11 2009 +0100 @@ -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 @@ -269,7 +269,6 @@ Dsymbol *aliassym; // if redone as alias to another symbol Expression *value; // when interpreting, this is the value // (NULL if value not determinable) - Scope *scope; // !=NULL means context to use VarDeclaration(Loc loc, Type *t, Identifier *id, Initializer *init); Dsymbol *syntaxCopy(Dsymbol *); @@ -668,7 +667,6 @@ // 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 diff -r d28cd7c45267 -r 54b3c1394d62 dmd2/dsymbol.c --- a/dmd2/dsymbol.c Mon Jul 06 23:57:27 2009 +0100 +++ b/dmd2/dsymbol.c Tue Jul 07 02:26:11 2009 +0100 @@ -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 @@ -48,6 +48,7 @@ #endif this->loc = 0; this->comment = NULL; + this->scope = NULL; #if IN_LLVM this->llvmInternal = LLVMnone; @@ -67,6 +68,7 @@ #endif this->loc = 0; this->comment = NULL; + this->scope = NULL; #if IN_LLVM this->llvmInternal = LLVMnone; @@ -193,6 +195,16 @@ if (q == s) break; q--; +#if TARGET_NET + if (AggregateDeclaration* ad = p->isAggregateDeclaration()) + { + if (ad->isNested() && p->parent && p->parent->isAggregateDeclaration()) + { + *q = '/'; + continue; + } + } +#endif *q = '.'; } return s; @@ -269,24 +281,53 @@ return ident ? 0 : 1; } +/************************************* + * Set scope for future semantic analysis so we can + * deal better with forward references. + */ + +void Dsymbol::setScope(Scope *sc) +{ + //printf("Dsymbol::setScope() %p %s\n", this, toChars()); + if (!sc->nofree) + sc->setNoFree(); // may need it even after semantic() finishes + scope = sc; +} + +/************************************* + * Does semantic analysis on the public face of declarations. + */ + void Dsymbol::semantic(Scope *sc) { error("%p has no semantic routine", this); } +/************************************* + * Does semantic analysis on initializers and members of aggregates. + */ + void Dsymbol::semantic2(Scope *sc) { // Most Dsymbols have no further semantic analysis needed } +/************************************* + * Does semantic analysis on function bodies. + */ + void Dsymbol::semantic3(Scope *sc) { // Most Dsymbols have no further semantic analysis needed } +/************************************* + * Look for function inlining possibilities. + */ + void Dsymbol::inlineScan() { - // Most Dsymbols have no further semantic analysis needed + // Most Dsymbols aren't functions } /********************************************* @@ -344,7 +385,7 @@ return NULL; } ti->tempdecl = td; - if (!ti->semanticdone) + if (!ti->semanticRun) ti->semantic(sc); sm = ti->toAlias(); break; diff -r d28cd7c45267 -r 54b3c1394d62 dmd2/dsymbol.h --- a/dmd2/dsymbol.h Mon Jul 06 23:57:27 2009 +0100 +++ b/dmd2/dsymbol.h Tue Jul 07 02:26:11 2009 +0100 @@ -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 @@ -74,15 +74,14 @@ struct DeleteDeclaration; struct HdrGenState; struct OverloadSet; +#if TARGET_NET +struct PragmaScope; +#endif #if IN_LLVM struct TypeInfoDeclaration; struct ClassInfoDeclaration; #endif -#if IN_DMD -struct Symbol; -#endif - #if IN_GCC union tree_node; typedef union tree_node TYPE; @@ -126,6 +125,7 @@ #endif unsigned char *comment; // documentation comment for this Dsymbol Loc loc; // where defined + Scope *scope; // !=NULL means context to use for semantic() Dsymbol(); Dsymbol(Identifier *); @@ -151,6 +151,7 @@ virtual const char *kind(); virtual Dsymbol *toAlias(); // resolve real symbol virtual int addMember(Scope *sc, ScopeDsymbol *s, int memnum); + virtual void setScope(Scope *sc); virtual void semantic(Scope *sc); virtual void semantic2(Scope *sc); virtual void semantic3(Scope *sc); @@ -245,7 +246,9 @@ virtual OverloadSet *isOverloadSet() { return NULL; } virtual TypeInfoDeclaration* isTypeInfoDeclaration() { return NULL; } virtual ClassInfoDeclaration* isClassInfoDeclaration() { return NULL; } - +#if TARGET_NET + virtual PragmaScope* isPragmaScope() { return NULL; } +#endif #if IN_LLVM /// Codegen traversal virtual void codegen(Ir* ir); diff -r d28cd7c45267 -r 54b3c1394d62 dmd2/enum.c --- a/dmd2/enum.c Mon Jul 06 23:57:27 2009 +0100 +++ b/dmd2/enum.c Tue Jul 07 02:26:11 2009 +0100 @@ -33,7 +33,6 @@ #if IN_DMD sinit = NULL; #endif - scope = NULL; isdeprecated = 0; } diff -r d28cd7c45267 -r 54b3c1394d62 dmd2/enum.h --- a/dmd2/enum.h Mon Jul 06 23:57:27 2009 +0100 +++ b/dmd2/enum.h Tue Jul 07 02:26:11 2009 +0100 @@ -40,8 +40,6 @@ Expression *maxval; Expression *minval; Expression *defaultval; // default initializer - - Scope *scope; // !=NULL means context to use #endif int isdeprecated; diff -r d28cd7c45267 -r 54b3c1394d62 dmd2/expression.c --- a/dmd2/expression.c Mon Jul 06 23:57:27 2009 +0100 +++ b/dmd2/expression.c Tue Jul 07 02:26:11 2009 +0100 @@ -380,6 +380,11 @@ } } + else if (e->op == TOKdottd) + { + e = new CallExp(e->loc, e); + e = e->semantic(sc); + } return e; } @@ -1002,7 +1007,7 @@ dump(0); halt(); #endif - type = Type::tint32; + type = Type::terror; } } @@ -1064,6 +1069,9 @@ void Expression::toMangleBuffer(OutBuffer *buf) { error("expression %s is not a valid template value argument", toChars()); +#ifdef DEBUG +dump(0); +#endif } /*************************************** @@ -1116,6 +1124,7 @@ { if (!type->isscalar()) error("'%s' is not a scalar, it is a %s", toChars(), type->toChars()); + rvalue(); } void Expression::checkNoBool() @@ -1130,6 +1139,7 @@ { error("'%s' is not of integral type, it is a %s", toChars(), type->toChars()); return new ErrorExp(); } + rvalue(); return this; } @@ -1139,6 +1149,7 @@ { error("'%s' is not of arithmetic type, it is a %s", toChars(), type->toChars()); return new ErrorExp(); } + rvalue(); return this; } @@ -1996,6 +2007,28 @@ withsym = scopesym->isWithScopeSymbol(); if (withsym) { +#if DMDV2 + /* Disallow shadowing + */ + // First find the scope of the with + Scope *scwith = sc; + while (scwith->scopesym != scopesym) + { scwith = scwith->enclosing; + assert(scwith); + } + // Look at enclosing scopes for symbols with the same name, + // in the same function + for (Scope *scx = scwith; scx && scx->func == scwith->func; scx = scx->enclosing) + { Dsymbol *s2; + + if (scx->scopesym && scx->scopesym->symtab && + (s2 = scx->scopesym->symtab->lookup(s->ident)) != NULL && + s != s2) + { + error("with symbol %s is shadowing local symbol %s", s->toPrettyChars(), s2->toPrettyChars()); + } + } +#endif s = s->toAlias(); // Same as wthis.ident @@ -2160,7 +2193,7 @@ if (!type) { type = v->type; if (!v->type) - { error("forward reference of %s", v->toChars()); + { error("forward reference of %s %s", v->kind(), v->toChars()); type = Type::terror; } } @@ -2178,6 +2211,11 @@ f = s->isFuncDeclaration(); if (f) { //printf("'%s' is a function\n", f->toChars()); + + if (!f->type->deco) + { + error("forward reference to %s", toChars()); + } return new VarExp(loc, f, hasOverloads); } o = s->isOverloadSet(); @@ -2237,7 +2275,7 @@ TemplateInstance *ti = s->isTemplateInstance(); if (ti && !global.errors) - { if (!ti->semanticdone) + { if (!ti->semanticRun) ti->semantic(sc); s = ti->inst->toAlias(); if (!s->isTemplateInstance()) @@ -2926,6 +2964,7 @@ for (int i = 0; i < elements->dim; i++) { e = (Expression *)elements->data[i]; e = e->semantic(sc); + assert(e->type); elements->data[i] = (void *)e; } expandTuples(elements); @@ -3405,6 +3444,11 @@ return this; } +void TypeExp::rvalue() +{ + error("type %s has no value", toChars()); +} + void TypeExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) { type->toCBuffer(buf, NULL, hgs); @@ -3440,7 +3484,7 @@ ti = sds->isTemplateInstance(); if (ti && !global.errors) { Dsymbol *s; - if (!ti->semanticdone) + if (!ti->semanticRun) ti->semantic(sc); s = ti->inst->toAlias(); sds2 = s->isScopeDsymbol(); @@ -3655,7 +3699,26 @@ } #endif } - else if (fdn) // Possible problems here, no obvious solution when merging +#if 1 + else if (thisexp) + error("e.new is only for allocating nested classes"); + else if (fdn) + { + // make sure the parent context fdn of cd is reachable from sc + for (Dsymbol *sp = sc->parent; 1; sp = sp->parent) + { + if (fdn == sp) + break; + FuncDeclaration *fsp = sp ? sp->isFuncDeclaration() : NULL; + if (!sp || (fsp && fsp->isStatic())) + { + error("outer function context of %s is needed to 'new' nested class %s", fdn->toPrettyChars(), cd->toPrettyChars()); + break; + } + } + } +#else + else if (fdn) { /* The nested class cd is nested inside a function, * we'll let getEthis() look for errors. */ @@ -3664,6 +3727,7 @@ // Because thisexp cannot be a function frame pointer error("e.new is only for allocating nested classes"); } +#endif else assert(0); } @@ -4028,6 +4092,7 @@ } #endif } + /* Fix for 1161 doesn't work because it causes protection * problems when instantiating imported templates passing private * variables as alias template parameters. @@ -4109,6 +4174,7 @@ return e; } #endif + return this; } @@ -4295,6 +4361,7 @@ return (Expression *)exps->data[0]; } type = new TypeTuple(exps); + type = type->semantic(loc, sc); //printf("-TupleExp::semantic(%s)\n", toChars()); return this; } @@ -6159,7 +6226,7 @@ if (e1->op == TOKimport && !e1->type) { ScopeExp *se = (ScopeExp *)e1; TemplateInstance *ti = se->sds->isTemplateInstance(); - if (ti && !ti->semanticdone) + if (ti && !ti->semanticRun) { /* Attempt to instantiate ti. If that works, go with it. * If not, go with partial explicit specialization. @@ -6187,7 +6254,7 @@ if (e1->op == TOKdotti && !e1->type) { DotTemplateInstanceExp *se = (DotTemplateInstanceExp *)e1; TemplateInstance *ti = se->ti; - if (!ti->semanticdone) + if (!ti->semanticRun) { /* Attempt to instantiate ti. If that works, go with it. * If not, go with partial explicit specialization. @@ -6795,7 +6862,9 @@ AddrExp::AddrExp(Loc loc, Expression *e) : UnaExp(loc, TOKaddress, sizeof(AddrExp), e) { +#if IN_LLVM m = NULL; +#endif } Expression *AddrExp::semantic(Scope *sc) @@ -6805,15 +6874,30 @@ #endif if (!type) { +#if IN_LLVM m = sc->module; +#endif UnaExp::semantic(sc); e1 = e1->toLvalue(sc, NULL); if (!e1->type) { error("cannot take address of %s", e1->toChars()); - type = Type::tint32; - return this; - } + return new ErrorExp(); + } + if (!e1->type->deco) + { + /* No deco means semantic() was not run on the type. + * We have to run semantic() on the symbol to get the right type: + * auto x = &bar; + * pure: int bar() { return 1;} + * otherwise the 'pure' is missing from the type assigned to x. + */ + + error("forward reference to %s", e1->toChars()); + return new ErrorExp(); + } + +//printf("test3 deco = %p\n", e1->type->deco); type = e1->type->pointerTo(); // See if this should really be a delegate @@ -6878,8 +6962,8 @@ PtrExp::PtrExp(Loc loc, Expression *e) : UnaExp(loc, TOKstar, sizeof(PtrExp), e) { - if (e->type) - type = ((TypePointer *)e->type)->next; +// if (e->type) +// type = ((TypePointer *)e->type)->next; } PtrExp::PtrExp(Loc loc, Expression *e, Type *t) @@ -6889,8 +6973,7 @@ } Expression *PtrExp::semantic(Scope *sc) -{ Type *tb; - +{ #if LOGSEMANTIC printf("PtrExp::semantic('%s')\n", toChars()); #endif @@ -6903,7 +6986,7 @@ Expression *e = op_overload(sc); if (e) return e; - tb = e1->type->toBasetype(); + Type *tb = e1->type->toBasetype(); switch (tb->ty) { case Tpointer: @@ -6918,8 +7001,7 @@ default: error("can only * a pointer, not a '%s'", e1->type->toChars()); - type = Type::tint32; - break; + return new ErrorExp(); } rvalue(); } @@ -9744,8 +9826,11 @@ } #endif else + { e1->rvalue(); + e2->rvalue(); e = this; - //printf("CmpExp: %s\n", e->toChars()); + } + //printf("CmpExp: %s, type = %s\n", e->toChars(), e->type->toChars()); return e; } diff -r d28cd7c45267 -r 54b3c1394d62 dmd2/expression.h --- a/dmd2/expression.h Mon Jul 06 23:57:27 2009 +0100 +++ b/dmd2/expression.h Tue Jul 07 02:26:11 2009 +0100 @@ -85,6 +85,11 @@ Expression *fromConstInitializer(int result, Expression *e); int arrayExpressionCanThrow(Expressions *exps); +struct IntRange +{ uinteger_t imin; + uinteger_t imax; +}; + struct Expression : Object { Loc loc; // file location @@ -122,6 +127,7 @@ virtual Expression *modifiableLvalue(Scope *sc, Expression *e); virtual Expression *implicitCastTo(Scope *sc, Type *t); virtual MATCH implicitConvTo(Type *t); + virtual IntRange getIntRange(); virtual Expression *castTo(Scope *sc, Type *t); virtual void checkEscape(); void checkScalar(); @@ -191,6 +197,7 @@ Expression *interpret(InterState *istate); char *toChars(); void dump(int indent); + IntRange getIntRange(); dinteger_t toInteger(); real_t toReal(); real_t toImaginary(); @@ -558,6 +565,7 @@ TypeExp(Loc loc, Type *type); Expression *syntaxCopy(); Expression *semantic(Scope *sc); + void rvalue(); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); Expression *optimize(int result); #if IN_DMD @@ -1230,6 +1238,8 @@ CastExp(Loc loc, Expression *e, unsigned mod); Expression *syntaxCopy(); Expression *semantic(Scope *sc); + MATCH implicitConvTo(Type *t); + IntRange getIntRange(); Expression *optimize(int result); Expression *interpret(InterState *istate); int checkSideEffect(int flag); @@ -1334,11 +1344,14 @@ CommaExp(Loc loc, Expression *e1, Expression *e2); Expression *semantic(Scope *sc); void checkEscape(); + IntRange getIntRange(); int isLvalue(); Expression *toLvalue(Scope *sc, Expression *e); Expression *modifiableLvalue(Scope *sc, Expression *e); int isBool(int result); int checkSideEffect(int flag); + MATCH implicitConvTo(Type *t); + Expression *castTo(Scope *sc, Type *t); Expression *optimize(int result); Expression *interpret(InterState *istate); #if IN_DMD @@ -1552,6 +1565,7 @@ Expression *interpret(InterState *istate); void buildArrayIdent(OutBuffer *buf, Expressions *arguments); Expression *buildArrayLoop(Arguments *fparams); + IntRange getIntRange(); // For operator overloading Identifier *opId(); @@ -1594,6 +1608,7 @@ Expression *semantic(Scope *sc); Expression *optimize(int result); Expression *interpret(InterState *istate); + IntRange getIntRange(); // For operator overloading Identifier *opId(); @@ -1614,6 +1629,7 @@ Expression *semantic(Scope *sc); Expression *optimize(int result); Expression *interpret(InterState *istate); + IntRange getIntRange(); // For operator overloading Identifier *opId(); @@ -1634,6 +1650,7 @@ Expression *semantic(Scope *sc); Expression *optimize(int result); Expression *interpret(InterState *istate); + IntRange getIntRange(); // For operator overloading Identifier *opId(); @@ -1656,6 +1673,7 @@ Expression *interpret(InterState *istate); void buildArrayIdent(OutBuffer *buf, Expressions *arguments); Expression *buildArrayLoop(Arguments *fparams); + IntRange getIntRange(); // For operator overloading int isCommutative(); @@ -1679,6 +1697,8 @@ Expression *interpret(InterState *istate); void buildArrayIdent(OutBuffer *buf, Expressions *arguments); Expression *buildArrayLoop(Arguments *fparams); + MATCH implicitConvTo(Type *t); + IntRange getIntRange(); // For operator overloading int isCommutative(); @@ -1702,6 +1722,8 @@ Expression *interpret(InterState *istate); void buildArrayIdent(OutBuffer *buf, Expressions *arguments); Expression *buildArrayLoop(Arguments *fparams); + MATCH implicitConvTo(Type *t); + IntRange getIntRange(); // For operator overloading int isCommutative(); diff -r d28cd7c45267 -r 54b3c1394d62 dmd2/func.c --- a/dmd2/func.c Mon Jul 06 23:57:27 2009 +0100 +++ b/dmd2/func.c Tue Jul 07 02:26:11 2009 +0100 @@ -1,5 +1,5 @@ // 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 @@ -64,6 +64,9 @@ inlineAsm = 0; cantInterpret = 0; semanticRun = 0; +#if DMDV1 + nestedFrameRef = 0; +#endif fes = NULL; introducing = 0; tintro = NULL; @@ -71,17 +74,16 @@ * NULL for the return type. */ inferRetType = (type && type->nextOf() == NULL); - scope = NULL; hasReturnExp = 0; nrvo_can = 1; nrvo_var = NULL; #if IN_DMD shidden = NULL; #endif - +#if DMDV2 builtin = BUILTINunknown; tookAddressOf = 0; - +#endif #if IN_LLVM // LDC isArrayOp = false; @@ -125,8 +127,9 @@ f->fbody = fbody ? fbody->syntaxCopy() : NULL; assert(!fthrows); // deprecated - // LDC +#if IN_LLVM f->intrinsicName = intrinsicName; +#endif return f; } @@ -166,7 +169,7 @@ if (!originalType) originalType = type; - if (!type->deco && type->nextOf()) + if (!type->deco) { /* Apply const and invariant storage class * to the function type @@ -304,7 +307,9 @@ storage_class |= STCabstract; if (isCtorDeclaration() || +#if DMDV2 isPostBlitDeclaration() || +#endif isDtorDeclaration() || isInvariantDeclaration() || isUnitTestDeclaration() || isNewDeclaration() || isDelete()) @@ -878,6 +883,7 @@ for (size_t i = 0; i < f->parameters->dim; i++) { Argument *arg = (Argument *)f->parameters->data[i]; + //printf("[%d] arg->type->ty = %d %s\n", i, arg->type->ty, arg->type->toChars()); if (arg->type->ty == Ttuple) { TypeTuple *t = (TypeTuple *)arg->type; size_t dim = Argument::dim(t->arguments); @@ -1008,6 +1014,12 @@ v = new VarDeclaration(loc, type->nextOf(), outId, NULL); v->noauto = 1; +#if DMDV2 + if (f->isref) + { + v->storage_class |= STCref | STCforeach; + } +#endif sc2->incontract--; v->semantic(sc2); sc2->incontract++; @@ -1108,6 +1120,8 @@ nrvo_can = 0; fbody = fbody->semantic(sc2); + if (!fbody) + fbody = new CompoundStatement(0, new Statements()); if (inferRetType) { // If no return type inferred yet, then infer a void @@ -1185,7 +1199,7 @@ error("expected to return a value of type %s", type->nextOf()->toChars()); else if (!inlineAsm) { - int blockexit = fbody ? fbody->blockExit() : 0; + int blockexit = fbody ? fbody->blockExit() : BEfallthru; if (f->isnothrow && blockexit & BEthrow) error("'%s' is nothrow yet may throw", toChars()); @@ -1204,7 +1218,8 @@ if (offend) { Expression *e; - warning(loc, "no return at end of function"); + //warning(loc, "no return exp; or assert(0); at end of function"); + error("no return exp; or assert(0); at end of function"); if (global.params.useAssert && !global.params.useInline) @@ -2169,16 +2184,22 @@ } void FuncDeclaration::appendState(Statement *s) -{ CompoundStatement *cs; - +{ if (!fbody) - { Statements *a; - - a = new Statements(); - fbody = new CompoundStatement(0, a); + fbody = s; + else + { + CompoundStatement *cs = fbody->isCompoundStatement(); + if (cs) + { + if (!cs->statements) + fbody = s; + else + cs->statements->push(s); + } + else + fbody = new CompoundStatement(0, fbody, s); } - cs = fbody->isCompoundStatement(); - cs->statements->push(s); } @@ -2635,6 +2656,7 @@ /********************************* PostBlitDeclaration ****************************/ +#if DMDV2 PostBlitDeclaration::PostBlitDeclaration(Loc loc, Loc endloc) : FuncDeclaration(loc, endloc, Id::_postblit, STCundefined, NULL) { @@ -2704,6 +2726,7 @@ buf->writestring("=this()"); bodyToCBuffer(buf, hgs); } +#endif /********************************* DtorDeclaration ****************************/ diff -r d28cd7c45267 -r 54b3c1394d62 dmd2/import.c --- a/dmd2/import.c Mon Jul 06 23:57:27 2009 +0100 +++ b/dmd2/import.c Tue Jul 07 02:26:11 2009 +0100 @@ -21,6 +21,7 @@ #include "mtype.h" #include "declaration.h" #include "id.h" +#include "attrib.h" /********************************* Import ****************************/ @@ -100,10 +101,14 @@ s = dst->lookup(id); if (s) { +#if TARGET_NET + mod = (Module *)s; +#else if (s->isModule()) mod = (Module *)s; else error("package and module have the same name"); +#endif } if (!mod) @@ -121,27 +126,25 @@ //printf("-Import::load('%s'), pkg = %p\n", toChars(), pkg); } -#if IN_LLVM -char* escapePath(char* fname, char* buffer, int bufLen) { - char* res = buffer; - bufLen -= 2; // for \0 and an occasional escape char - int dst = 0; - for (; dst < bufLen && *fname; ++dst, ++fname) { - switch (*fname) { +void escapePath(OutBuffer *buf, const char *fname) +{ + while (1) + { + switch (*fname) + { + case 0: + return; case '(': case ')': case '\\': - buffer[dst++] = '\\'; - // fall through - + buf->writebyte('\\'); default: - buffer[dst] = *fname; + buf->writebyte(*fname); + break; } + fname++; } - buffer[dst] = '\0'; - return buffer; } -#endif void Import::semantic(Scope *sc) { @@ -165,8 +168,6 @@ //printf("%s imports %s\n", sc->module->toChars(), mod->toChars()); sc->module->aimports.push(mod); - mod->semantic(); - if (!isstatic && !aliasId && !names.dim) { /* Default to private importing @@ -177,6 +178,8 @@ sc->scopesym->importScope(mod, prot); } + mod->semantic(); + if (mod->needmoduleinfo) sc->module->needmoduleinfo = 1; @@ -193,69 +196,77 @@ } sc = sc->pop(); } - //printf("-Import::semantic('%s'), pkg = %p\n", toChars(), pkg); - - if (global.params.moduleDeps != NULL) { - char fnameBuf[262]; // MAX_PATH+2 - - OutBuffer *const ob = global.params.moduleDeps; - ob->printf("%s (%s) : ", - sc->module->toPrettyChars(), - escapePath(sc->module->srcfile->toChars(), fnameBuf, sizeof(fnameBuf) / sizeof(*fnameBuf)) - ); + if (global.params.moduleDeps != NULL) + { + /* The grammar of the file is: + * ImportDeclaration + * ::= BasicImportDeclaration [ " : " ImportBindList ] [ " -> " + * ModuleAliasIdentifier ] "\n" + * + * BasicImportDeclaration + * ::= ModuleFullyQualifiedName " (" FilePath ") : " Protection + * " [ " static" ] : " ModuleFullyQualifiedName " (" FilePath ")" + * + * FilePath + * - any string with '(', ')' and '\' escaped with the '\' character + */ - char* protStr = ""; - switch (sc->protection) { - case PROTpublic: protStr = "public"; break; - case PROTprivate: protStr = "private"; break; - case PROTpackage: protStr = "package"; break; - default: break; - } - ob->writestring(protStr); - if (isstatic) { - ob->writestring(" static"); - } - ob->writestring(" : "); + OutBuffer *ob = global.params.moduleDeps; + + ob->writestring(sc->module->toPrettyChars()); + ob->writestring(" ("); + escapePath(ob, sc->module->srcfile->toChars()); + ob->writestring(") : "); - if (this->packages) { - for (size_t i = 0; i < this->packages->dim; i++) { - Identifier *pid = (Identifier *)this->packages->data[i]; + ProtDeclaration::protectionToCBuffer(ob, sc->protection); + if (isstatic) + StorageClassDeclaration::stcToCBuffer(ob, STCstatic); + ob->writestring(": "); + + if (packages) + { + for (size_t i = 0; i < packages->dim; i++) + { + Identifier *pid = (Identifier *)packages->data[i]; ob->printf("%s.", pid->toChars()); } } - ob->printf("%s (%s)", - this->id->toChars(), - mod ? escapePath(mod->srcfile->toChars(), fnameBuf, sizeof(fnameBuf) / sizeof(*fnameBuf)) : "???" - ); + ob->writestring(id->toChars()); + ob->writestring(" ("); + if (mod) + escapePath(ob, mod->srcfile->toChars()); + else + ob->writestring("???"); + ob->writebyte(')'); + + for (size_t i = 0; i < names.dim; i++) + { + if (i == 0) + ob->writebyte(':'); + else + ob->writebyte(','); - if (aliasId) { - ob->printf(" -> %s", aliasId->toChars()); - } else { - if (names.dim > 0) { - ob->writestring(" : "); - for (size_t i = 0; i < names.dim; i++) - { - if (i > 0) { - ob->writebyte(','); - } + Identifier *name = (Identifier *)names.data[i]; + Identifier *alias = (Identifier *)aliases.data[i]; - Identifier *name = (Identifier *)names.data[i]; - Identifier *alias = (Identifier *)aliases.data[i]; + if (!alias) + { + ob->printf("%s", name->toChars()); + alias = name; + } + else + ob->printf("%s=%s", alias->toChars(), name->toChars()); + } - if (!alias) { - ob->printf("%s", name->toChars()); - alias = name; - } else { - ob->printf("%s=%s", alias->toChars(), name->toChars()); - } - } - } - } + if (aliasId) + ob->printf(" -> %s", aliasId->toChars()); ob->writenl(); } + + //printf("-Import::semantic('%s'), pkg = %p\n", toChars(), pkg); } void Import::semantic2(Scope *sc) @@ -347,27 +358,7 @@ buf->printf("%s.", pid->toChars()); } } - buf->printf("%s", id->toChars()); - if (names.dim > 0) { - buf->writebyte(':'); - for (size_t i = 0; i < names.dim; i++) - { - if (i > 0) { - buf->writebyte(','); - } - - Identifier *name = (Identifier *)names.data[i]; - Identifier *alias = (Identifier *)aliases.data[i]; - - if (!alias) { - buf->printf("%s", name->toChars()); - alias = name; - } else { - buf->printf("%s=%s", alias->toChars(), name->toChars()); - } - } - } - buf->writebyte(';'); + buf->printf("%s;", id->toChars()); buf->writenl(); } diff -r d28cd7c45267 -r 54b3c1394d62 dmd2/import.h --- a/dmd2/import.h Mon Jul 06 23:57:27 2009 +0100 +++ b/dmd2/import.h Tue Jul 07 02:26:11 2009 +0100 @@ -34,7 +34,9 @@ Identifier *id; // module Identifier Identifier *aliasId; int isstatic; // !=0 if static import +#if IN_LLVM enum PROT protection; +#endif // Pairs of alias=name to bind into current namespace Array names; @@ -50,7 +52,9 @@ void addAlias(Identifier *name, Identifier *alias); const char *kind(); +#if IN_LLVM enum PROT prot(); +#endif Dsymbol *syntaxCopy(Dsymbol *s); // copy only syntax trees void load(Scope *sc); void semantic(Scope *sc); diff -r d28cd7c45267 -r 54b3c1394d62 dmd2/inifile.c --- a/dmd2/inifile.c Mon Jul 06 23:57:27 2009 +0100 +++ b/dmd2/inifile.c Tue Jul 07 02:26:11 2009 +0100 @@ -15,6 +15,10 @@ #include #include +#if _WIN32 +#include +#endif + #if __APPLE__ #include #endif @@ -91,6 +95,15 @@ filename = FileName::combine(getenv("HOME"), inifile); if (!FileName::exists(filename)) { +#if _WIN32 // This fix by Tim Matthews + char resolved_name[MAX_PATH + 1]; + if(GetModuleFileName(NULL, resolved_name, MAX_PATH + 1) && FileName::exists(resolved_name)) + { + filename = (char *)FileName::replaceName(resolved_name, inifile); + if(FileName::exists(filename)) + goto Ldone; + } +#endif filename = (char *)FileName::replaceName(argv0, inifile); if (!FileName::exists(filename)) { diff -r d28cd7c45267 -r 54b3c1394d62 dmd2/init.c --- a/dmd2/init.c Mon Jul 06 23:57:27 2009 +0100 +++ b/dmd2/init.c Tue Jul 07 02:26:11 2009 +0100 @@ -396,24 +396,70 @@ { Expressions *elements; Expression *e; - //printf("ArrayInitializer::toExpression()\n"); + //printf("ArrayInitializer::toExpression(), dim = %d\n", dim); //static int i; if (++i == 2) halt(); + + size_t edim; + Type *t = NULL; + if (type) + { + t = type->toBasetype(); + switch (t->ty) + { + case Tsarray: + edim = ((TypeSArray *)t)->dim->toInteger(); + break; + + case Tpointer: + case Tarray: + edim = dim; + break; + + default: + assert(0); + } + } + else + edim = value.dim; + elements = new Expressions(); - for (size_t i = 0; i < value.dim; i++) + elements->setDim(edim); + for (size_t i = 0, j = 0; i < value.dim; i++, j++) { if (index.data[i]) - goto Lno; + j = ((Expression *)index.data[i])->toInteger(); + assert(j < edim); Initializer *iz = (Initializer *)value.data[i]; if (!iz) goto Lno; Expression *ex = iz->toExpression(); if (!ex) + { goto Lno; - elements->push(ex); + } + elements->data[j] = ex; } - e = new ArrayLiteralExp(loc, elements); + + /* Fill in any missing elements with the default initializer + */ + { + Expression *init = NULL; + for (size_t i = 0; i < edim; i++) + { + if (!elements->data[i]) + { + if (!type) + goto Lno; + if (!init) + init = ((TypeNext *)t)->next->defaultInit(); + elements->data[i] = init; + } + } + + Expression *e = new ArrayLiteralExp(loc, elements); e->type = type; return e; + } Lno: delete elements; @@ -466,21 +512,26 @@ Type *ArrayInitializer::inferType(Scope *sc) { + //printf("ArrayInitializer::inferType() %s\n", toChars()); + type = Type::terror; for (size_t i = 0; i < value.dim; i++) { if (index.data[i]) goto Lno; } - if (value.dim) + for (size_t i = 0; i < value.dim; i++) { - Initializer *iz = (Initializer *)value.data[0]; + Initializer *iz = (Initializer *)value.data[i]; if (iz) { Type *t = iz->inferType(sc); - t = new TypeSArray(t, new IntegerExp(value.dim)); - t = t->semantic(loc, sc); - return t; + if (i == 0) + { t = new TypeSArray(t, new IntegerExp(value.dim)); + t = t->semantic(loc, sc); + type = t; + } } } + return type; Lno: error(loc, "cannot infer type from this array initializer"); diff -r d28cd7c45267 -r 54b3c1394d62 dmd2/interpret.c --- a/dmd2/interpret.c Mon Jul 06 23:57:27 2009 +0100 +++ b/dmd2/interpret.c Tue Jul 07 02:26:11 2009 +0100 @@ -2293,6 +2293,8 @@ return NULL; AssocArrayLiteralExp *aae = (AssocArrayLiteralExp *)earg; Expression *e = new ArrayLiteralExp(aae->loc, aae->keys); + Type *elemType = ((TypeAArray *)aae->type)->index; + e->type = new TypeSArray(elemType, new IntegerExp(arguments ? arguments->dim : 0)); return e; } @@ -2309,6 +2311,8 @@ return NULL; AssocArrayLiteralExp *aae = (AssocArrayLiteralExp *)earg; Expression *e = new ArrayLiteralExp(aae->loc, aae->values); + Type *elemType = ((TypeAArray *)aae->type)->next; + e->type = new TypeSArray(elemType, new IntegerExp(arguments ? arguments->dim : 0)); //printf("result is %s\n", e->toChars()); return e; } diff -r d28cd7c45267 -r 54b3c1394d62 dmd2/lexer.c --- a/dmd2/lexer.c Mon Jul 06 23:57:27 2009 +0100 +++ b/dmd2/lexer.c Tue Jul 07 02:26:11 2009 +0100 @@ -1278,7 +1278,9 @@ } } if (ndigits != 2 && !utf_isValidDchar(v)) - error("invalid UTF character \\U%08x", v); + { error("invalid UTF character \\U%08x", v); + v = '?'; // recover with valid UTF character + } c = v; } else diff -r d28cd7c45267 -r 54b3c1394d62 dmd2/mangle.c --- a/dmd2/mangle.c Mon Jul 06 23:57:27 2009 +0100 +++ b/dmd2/mangle.c Tue Jul 07 02:26:11 2009 +0100 @@ -113,9 +113,9 @@ case LINKd: break; - // LDC +#if IN_LLVM case LINKintrinsic: - +#endif case LINKc: case LINKwindows: case LINKpascal: diff -r d28cd7c45267 -r 54b3c1394d62 dmd2/mars.c --- a/dmd2/mars.c Mon Jul 06 23:57:27 2009 +0100 +++ b/dmd2/mars.c Tue Jul 07 02:26:11 2009 +0100 @@ -98,7 +98,7 @@ "\nMSIL back-end (alpha release) by Cristian L. Vlasceanu and associates."; #endif ; - version = "v2.030"; + version = "v2.031"; #if IN_LLVM ldc_version = LDC_REV; llvm_version = LLVM_REV_STR; diff -r d28cd7c45267 -r 54b3c1394d62 dmd2/mars.h --- a/dmd2/mars.h Mon Jul 06 23:57:27 2009 +0100 +++ b/dmd2/mars.h Tue Jul 07 02:26:11 2009 +0100 @@ -209,10 +209,10 @@ Array *debuglibnames; // default libraries for debug builds const char *xmlname; // filename for XML output - - OutBuffer *moduleDeps; // buffer and filename for emitting module deps - char *moduleDepsFile; - + + char *moduleDepsFile; // filename for deps output + OutBuffer *moduleDeps; // contents to be written to deps file + // Hidden debug switches bool debuga; bool debugb; @@ -443,7 +443,7 @@ #if IN_GCC || IN_LLVM #define stdmsg stderr #else -#define stdmsg stdout +#define stdmsg stderr #endif #if !IN_LLVM diff -r d28cd7c45267 -r 54b3c1394d62 dmd2/module.c --- a/dmd2/module.c Mon Jul 06 23:57:27 2009 +0100 +++ b/dmd2/module.c Tue Jul 07 02:26:11 2009 +0100 @@ -99,7 +99,7 @@ searchCacheSymbol = NULL; searchCacheFlags = 0; semanticstarted = 0; - semanticdone = 0; + semanticRun = 0; decldefs = NULL; vmoduleinfo = NULL; #if IN_DMD @@ -770,25 +770,32 @@ // Add all symbols into module's symbol table symtab = new DsymbolTable(); for (i = 0; i < members->dim; i++) - { Dsymbol *s; + { Dsymbol *s = (Dsymbol *)members->data[i]; + s->addMember(NULL, sc->scopesym, 1); + } - s = (Dsymbol *)members->data[i]; - s->addMember(NULL, sc->scopesym, 1); + /* Set scope for the symbols so that if we forward reference + * a symbol, it can possibly be resolved on the spot. + * If this works out well, it can be extended to all modules + * before any semantic() on any of them. + */ + for (i = 0; i < members->dim; i++) + { Dsymbol *s = (Dsymbol *)members->data[i]; + s->setScope(sc); } // Pass 1 semantic routines: do public side of the definition for (i = 0; i < members->dim; i++) - { Dsymbol *s; + { Dsymbol *s = (Dsymbol *)members->data[i]; - s = (Dsymbol *)members->data[i]; //printf("\tModule('%s'): '%s'.semantic()\n", toChars(), s->toChars()); s->semantic(sc); runDeferredSemantic(); } sc = sc->pop(); - sc->pop(); - semanticdone = semanticstarted; + sc->pop(); // 2 pops because Scope::createGlobal() created 2 + semanticRun = semanticstarted; //printf("-Module::semantic(this = %p, '%s'): parent = %p\n", this, toChars(), parent); } @@ -827,7 +834,7 @@ sc = sc->pop(); sc->pop(); - semanticdone = semanticstarted; + semanticRun = semanticstarted; //printf("-Module::semantic2('%s'): parent = %p\n", toChars(), parent); } @@ -857,7 +864,7 @@ sc = sc->pop(); sc->pop(); - semanticdone = semanticstarted; + semanticRun = semanticstarted; } void Module::inlineScan() @@ -882,7 +889,7 @@ s->inlineScan(); } - semanticdone = semanticstarted; + semanticRun = semanticstarted; } /**************************************************** @@ -1143,11 +1150,14 @@ else { assert(p->isPackage()); +#if TARGET_NET //dot net needs modules and packages with same name +#else if (p->isModule()) { p->error("module and package have the same name"); fatal(); break; } +#endif } parent = p; dst = ((Package *)p)->symtab; diff -r d28cd7c45267 -r 54b3c1394d62 dmd2/module.h --- a/dmd2/module.h Mon Jul 06 23:57:27 2009 +0100 +++ b/dmd2/module.h Tue Jul 07 02:26:11 2009 +0100 @@ -91,7 +91,7 @@ int searchCacheFlags; // cached flags int semanticstarted; // has semantic() been started? - int semanticdone; // has semantic() been done? + int semanticRun; // has semantic() been done? int root; // != 0 if this is a 'root' module, // i.e. a module that will be taken all the // way to an object file diff -r d28cd7c45267 -r 54b3c1394d62 dmd2/mtype.c --- a/dmd2/mtype.c Mon Jul 06 23:57:27 2009 +0100 +++ b/dmd2/mtype.c Tue Jul 07 02:26:11 2009 +0100 @@ -1171,6 +1171,10 @@ sv = stringtable.update((char *)buf.data, buf.offset); if (sv->ptrvalue) { t = (Type *) sv->ptrvalue; +#ifdef DEBUG + if (!t->deco) + printf("t = %s\n", t->toChars()); +#endif assert(t->deco); //printf("old value, deco = '%s' %p\n", t->deco, t->deco); } @@ -1324,14 +1328,14 @@ * Determine if 'this' can be implicitly converted * to type 'to'. * Returns: - * 0 can't convert - * 1 can convert using implicit conversions - * 2 this and to are the same type + * MATCHnomatch, MATCHconvert, MATCHconst, MATCHexact */ MATCH Type::implicitConvTo(Type *to) { //printf("Type::implicitConvTo(this=%p, to=%p)\n", this, to); + //printf("from: %s\n", toChars()); + //printf("to : %s\n", to->toChars()); if (this == to) return MATCHexact; return MATCHnomatch; @@ -1591,6 +1595,33 @@ return NULL; } +/**************************************** + * Return the mask that an integral type will + * fit into. + */ +uinteger_t Type::sizemask() +{ uinteger_t m; + + switch (toBasetype()->ty) + { + case Tbool: m = 1; break; + case Tchar: + case Tint8: + case Tuns8: m = 0xFF; break; + case Twchar: + case Tint16: + case Tuns16: m = 0xFFFFUL; break; + case Tdchar: + case Tint32: + case Tuns32: m = 0xFFFFFFFFUL; break; + case Tint64: + case Tuns64: m = 0xFFFFFFFFFFFFFFFFULL; break; + default: + assert(0); + } + return m; +} + /* ============================= TypeNext =========================== */ TypeNext::TypeNext(TY ty, Type *next) @@ -1610,7 +1641,8 @@ void TypeNext::checkDeprecated(Loc loc, Scope *sc) { Type::checkDeprecated(loc, sc); - next->checkDeprecated(loc, sc); + if (next) // next can be NULL if TypeFunction and auto return type + next->checkDeprecated(loc, sc); } @@ -1632,7 +1664,8 @@ return cto; } TypeNext *t = (TypeNext *)Type::makeConst(); - if (ty != Tfunction && ty != Tdelegate && next->deco && + if (ty != Tfunction && ty != Tdelegate && + (next->deco || next->ty == Tfunction) && !next->isInvariant() && !next->isConst()) { if (next->isShared()) t->next = next->sharedConstOf(); @@ -1651,7 +1684,8 @@ return ito; } TypeNext *t = (TypeNext *)Type::makeInvariant(); - if (ty != Tfunction && ty != Tdelegate && next->deco && + if (ty != Tfunction && ty != Tdelegate && + (next->deco || next->ty == Tfunction) && !next->isInvariant()) { t->next = next->invariantOf(); } @@ -1666,7 +1700,8 @@ return sto; } TypeNext *t = (TypeNext *)Type::makeShared(); - if (ty != Tfunction && ty != Tdelegate && next->deco && + if (ty != Tfunction && ty != Tdelegate && + (next->deco || next->ty == Tfunction) && !next->isInvariant() && !next->isShared()) { if (next->isConst()) @@ -1686,7 +1721,8 @@ return scto; } TypeNext *t = (TypeNext *)Type::makeSharedConst(); - if (ty != Tfunction && ty != Tdelegate && next->deco && + if (ty != Tfunction && ty != Tdelegate && + (next->deco || next->ty == Tfunction) && !next->isInvariant() && !next->isSharedConst()) { t->next = next->sharedConstOf(); @@ -2361,23 +2397,17 @@ if (this == to) return MATCHexact; +#if DMDV2 if (ty == to->ty) { return (mod == to->mod) ? MATCHexact : MATCHconst; } +#endif if (ty == Tvoid || to->ty == Tvoid) return MATCHnomatch; - if (1 || global.params.Dversion == 1) - { - if (to->ty == Tbool) - return MATCHnomatch; - } - else - { - if (ty == Tbool || to->ty == Tbool) - return MATCHnomatch; - } + if (to->ty == Tbool) + return MATCHnomatch; if (!to->isTypeBasic()) return MATCHnomatch; @@ -2388,19 +2418,23 @@ if (tob->flags & (TFLAGSimaginary | TFLAGScomplex)) return MATCHnomatch; - // If converting to integral - if (0 && global.params.Dversion > 1 && tob->flags & TFLAGSintegral) +#if DMDV2 + // If converting from integral to integral + if (1 && tob->flags & TFLAGSintegral) { d_uns64 sz = size(0); d_uns64 tosz = tob->size(0); - /* Can't convert to smaller size or, if same size, change sign + /* Can't convert to smaller size */ if (sz > tosz) return MATCHnomatch; + /* Can't change sign if same size + */ /*if (sz == tosz && (flags ^ tob->flags) & TFLAGSunsigned) return MATCHnomatch;*/ } +#endif } else if (flags & TFLAGSfloating) { @@ -3552,6 +3586,8 @@ Type *TypePointer::semantic(Loc loc, Scope *sc) { //printf("TypePointer::semantic()\n"); + if (deco) + return this; Type *n = next->semantic(loc, sc); switch (n->toBasetype()->ty) { @@ -3561,7 +3597,9 @@ break; } if (n != next) + { deco = NULL; + } next = n; transitive(); return merge(); @@ -3801,7 +3839,13 @@ Argument *arg2 = Argument::getNth(t2->parameters, i); if (!arg1->type->equals(arg2->type)) - goto Ldistinct; + { +#if 0 // turn on this for contravariant argument types, see bugzilla 3075 + // We can add const, but not subtract it + if (arg2->type->implicitConvTo(arg1->type) < MATCHconst) +#endif + goto Ldistinct; + } if ((arg1->storageClass & ~STCscope) != (arg2->storageClass & ~STCscope)) inoutmismatch = 1; // We can add scope, but not subtract it @@ -4057,7 +4101,7 @@ if (mod & MODconst) buf->writestring(" const"); if (mod & MODinvariant) - buf->writestring(" invariant"); + buf->writestring(" immutable"); if (mod & MODshared) buf->writestring(" shared"); } @@ -4081,6 +4125,10 @@ //printf("TypeFunction::semantic() this = %p\n", this); //printf("TypeFunction::semantic() %s, sc->stc = %x\n", toChars(), sc->stc); + /* Copy in order to not mess up original. + * This can produce redundant copies if inferring return type, + * as semantic() will get called again on this. + */ TypeFunction *tf = (TypeFunction *)mem.malloc(sizeof(TypeFunction)); memcpy(tf, this, sizeof(TypeFunction)); if (parameters) @@ -4101,26 +4149,24 @@ tf->isref = TRUE; tf->linkage = sc->linkage; - if (!tf->next) - { - assert(global.errors); - tf->next = tvoid; - } - tf->next = tf->next->semantic(loc,sc); - if (tf->next->toBasetype()->ty == Tsarray) - { error(loc, "functions cannot return static array %s", tf->next->toChars()); - tf->next = Type::terror; - } - if (tf->next->toBasetype()->ty == Tfunction) - { error(loc, "functions cannot return a function"); - tf->next = Type::terror; - } - if (tf->next->toBasetype()->ty == Ttuple) - { error(loc, "functions cannot return a tuple"); - tf->next = Type::terror; - } - if (tf->next->isauto() && !(sc->flags & SCOPEctor)) - error(loc, "functions cannot return scope %s", tf->next->toChars()); + if (tf->next) + { + tf->next = tf->next->semantic(loc,sc); + if (tf->next->toBasetype()->ty == Tsarray) + { error(loc, "functions cannot return static array %s", tf->next->toChars()); + tf->next = Type::terror; + } + if (tf->next->toBasetype()->ty == Tfunction) + { error(loc, "functions cannot return a function"); + tf->next = Type::terror; + } + if (tf->next->toBasetype()->ty == Ttuple) + { error(loc, "functions cannot return a tuple"); + tf->next = Type::terror; + } + if (tf->next->isauto() && !(sc->flags & SCOPEctor)) + error(loc, "functions cannot return scope %s", tf->next->toChars()); + } if (tf->parameters) { size_t dim = Argument::dim(tf->parameters); @@ -4168,7 +4214,8 @@ } } } - tf->deco = tf->merge()->deco; + if (tf->next) + tf->deco = tf->merge()->deco; if (tf->inuse) { error(loc, "recursive type"); @@ -4770,11 +4817,11 @@ */ void TypeIdentifier::resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps) -{ Dsymbol *s; +{ Dsymbol *scopesym; //printf("TypeIdentifier::resolve(sc = %p, idents = '%s')\n", sc, toChars()); - s = sc->search(loc, ident, &scopesym); + Dsymbol *s = sc->search(loc, ident, &scopesym); resolveHelper(loc, sc, s, scopesym, pe, pt, ps); if (*pt) (*pt) = (*pt)->addMod(mod); @@ -5241,7 +5288,7 @@ Type *TypeEnum::semantic(Loc loc, Scope *sc) { //printf("TypeEnum::semantic() %s\n", toChars()); - sym->semantic(sc); + //sym->semantic(sc); return merge(); } @@ -5895,7 +5942,7 @@ TemplateInstance *ti = s->isTemplateInstance(); if (ti) - { if (!ti->semanticdone) + { if (!ti->semanticRun) ti->semantic(sc); s = ti->inst->toAlias(); if (!s->isTemplateInstance()) @@ -6134,8 +6181,9 @@ Type *TypeClass::semantic(Loc loc, Scope *sc) { //printf("TypeClass::semantic(%s)\n", sym->toChars()); - if (sym->scope) - sym->semantic(sym->scope); + if (deco) + return this; + //printf("\t%s\n", merge()->deco); return merge(); } @@ -6426,7 +6474,7 @@ TemplateInstance *ti = s->isTemplateInstance(); if (ti) - { if (!ti->semanticdone) + { if (!ti->semanticRun) ti->semantic(sc); s = ti->inst->toAlias(); if (!s->isTemplateInstance()) diff -r d28cd7c45267 -r 54b3c1394d62 dmd2/mtype.h --- a/dmd2/mtype.h Mon Jul 06 23:57:27 2009 +0100 +++ b/dmd2/mtype.h Tue Jul 07 02:26:11 2009 +0100 @@ -306,6 +306,8 @@ virtual int hasPointers(); //Type *next; virtual Type *nextOf(); + uinteger_t sizemask(); + static void error(Loc loc, const char *format, ...) IS_PRINTF(2); static void warning(Loc loc, const char *format, ...) IS_PRINTF(2); @@ -714,10 +716,10 @@ EnumDeclaration *sym; TypeEnum(EnumDeclaration *sym); + Type *syntaxCopy(); d_uns64 size(Loc loc); unsigned alignsize(); char *toChars(); - Type *syntaxCopy(); Type *semantic(Loc loc, Scope *sc); Dsymbol *toDsymbol(Scope *sc); void toDecoBuffer(OutBuffer *buf, int flag, bool mangle); diff -r d28cd7c45267 -r 54b3c1394d62 dmd2/opover.c --- a/dmd2/opover.c Mon Jul 06 23:57:27 2009 +0100 +++ b/dmd2/opover.c Tue Jul 07 02:26:11 2009 +0100 @@ -198,6 +198,7 @@ } } +#if DMDV2 // Didn't find it. Forward to aliasthis if (ad->aliasthis) { @@ -210,6 +211,7 @@ e = e->semantic(sc); return e; } +#endif } return NULL; } @@ -441,6 +443,7 @@ } } +#if DMDV2 // Try alias this on first operand if (ad1 && ad1->aliasthis) { @@ -466,7 +469,7 @@ e = e->semantic(sc); return e; } - +#endif return NULL; } diff -r d28cd7c45267 -r 54b3c1394d62 dmd2/optimize.c --- a/dmd2/optimize.c Mon Jul 06 23:57:27 2009 +0100 +++ b/dmd2/optimize.c Tue Jul 07 02:26:11 2009 +0100 @@ -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 @@ -805,6 +805,16 @@ //printf("IndexExp::optimize(result = %d) %s\n", result, toChars()); Expression *e1 = this->e1->optimize(WANTvalue | (result & WANTinterpret)); e1 = fromConstInitializer(result, e1); + if (this->e1->op == TOKvar) + { VarExp *ve = (VarExp *)this->e1; + if (ve->var->storage_class & STCmanifest) + { /* We generally don't want to have more than one copy of an + * array literal, but if it's an enum we have to because the + * enum isn't stored elsewhere. See Bugzilla 2559 + */ + this->e1 = e1; + } + } e2 = e2->optimize(WANTvalue | (result & WANTinterpret)); e = Index(type, e1, e2); if (e == EXP_CANT_INTERPRET) diff -r d28cd7c45267 -r 54b3c1394d62 dmd2/parse.c --- a/dmd2/parse.c Mon Jul 06 23:57:27 2009 +0100 +++ b/dmd2/parse.c Tue Jul 07 02:26:11 2009 +0100 @@ -3144,6 +3144,7 @@ Condition *condition; Statement *ifbody; Statement *elsebody; + bool isfinal; Loc loc = this->loc; //printf("parseStatement()\n"); @@ -3245,13 +3246,21 @@ goto Ldeclaration; } + case TOKfinal: + if (peekNext() == TOKswitch) + { + nextToken(); + isfinal = TRUE; + goto Lswitch; + } + goto Ldeclaration; + CASE_BASIC_TYPES: case TOKtypedef: case TOKalias: case TOKconst: case TOKauto: case TOKextern: - case TOKfinal: case TOKinvariant: #if DMDV2 case TOKimmutable: @@ -3651,15 +3660,17 @@ } case TOKswitch: - { Expression *condition; - Statement *body; - + isfinal = FALSE; + goto Lswitch; + + Lswitch: + { nextToken(); check(TOKlparen); - condition = parseExpression(); + Expression *condition = parseExpression(); check(TOKrparen); - body = parseStatement(PSscope); - s = new SwitchStatement(loc, condition, body); + Statement *body = parseStatement(PSscope); + s = new SwitchStatement(loc, condition, body, isfinal); break; } @@ -3667,6 +3678,7 @@ { Expression *exp; Statements *statements; Array cases; // array of Expression's + Expression *last = NULL; while (1) { @@ -3678,6 +3690,20 @@ } check(TOKcolon); +#if DMDV2 + /* case exp: .. case last: + */ + if (token.value == TOKslice) + { + if (cases.dim > 1) + error("only one case allowed for start of case range"); + nextToken(); + check(TOKcase); + last = parseAssignExp(); + check(TOKcolon); + } +#endif + statements = new Statements(); while (token.value != TOKcase && token.value != TOKdefault && @@ -3688,11 +3714,20 @@ s = new CompoundStatement(loc, statements); s = new ScopeStatement(loc, s); - // Keep cases in order by building the case statements backwards - for (int i = cases.dim; i; i--) +#if DMDV2 + if (last) { - exp = (Expression *)cases.data[i - 1]; - s = new CaseStatement(loc, exp, s); + s = new CaseRangeStatement(loc, exp, last, s); + } + else +#endif + { + // Keep cases in order by building the case statements backwards + for (int i = cases.dim; i; i--) + { + exp = (Expression *)cases.data[i - 1]; + s = new CaseStatement(loc, exp, s); + } } break; } @@ -4024,6 +4059,8 @@ * needId 0 no identifier * 1 identifier optional * 2 must have identifier + * Output: + * if *pt is not NULL, it is set to the ending token, which would be endtok */ int Parser::isDeclaration(Token *t, int needId, enum TOK endtok, Token **pt) @@ -4062,7 +4099,7 @@ goto Lisnot; Lis: - //printf("\tis declaration\n"); + //printf("\tis declaration, t = %s\n", t->toChars()); return TRUE; Lisnot: @@ -4357,7 +4394,6 @@ int Parser::isParameters(Token **pt) { // This code parallels parseParameters() Token *t = *pt; - int tmp; //printf("isParameters()\n"); if (t->value != TOKlparen) @@ -4366,6 +4402,7 @@ t = peek(t); for (;1; t = peek(t)) { + L1: switch (t->value) { case TOKrparen: @@ -4380,12 +4417,23 @@ case TOKinout: case TOKref: case TOKlazy: + case TOKfinal: + continue; + case TOKconst: case TOKinvariant: case TOKimmutable: case TOKshared: - case TOKfinal: - continue; + t = peek(t); + if (t->value == TOKlparen) + { + t = peek(t); + if (!isDeclaration(t, 0, TOKrparen, &t)) + return FALSE; + t = peek(t); // skip past closing ')' + goto L2; + } + goto L1; #if 0 case TOKstatic: @@ -4404,9 +4452,10 @@ #endif default: - if (!isBasicType(&t)) + { if (!isBasicType(&t)) return FALSE; - tmp = FALSE; + L2: + int tmp = FALSE; if (t->value != TOKdotdotdot && !isDeclarator(&t, &tmp, TOKreserved)) return FALSE; @@ -4420,6 +4469,7 @@ t = peek(t); break; } + } L3: if (t->value == TOKcomma) { diff -r d28cd7c45267 -r 54b3c1394d62 dmd2/root/async.c --- a/dmd2/root/async.c Mon Jul 06 23:57:27 2009 +0100 +++ b/dmd2/root/async.c Tue Jul 07 02:26:11 2009 +0100 @@ -61,21 +61,25 @@ void AsyncRead::start() { - unsigned threadaddr; - hThread = (HANDLE) _beginthreadex(NULL, - 0, - &startthread, - this, - 0, - (unsigned *)&threadaddr); + //printf("aw->filesdim = %p %d\n", this, filesdim); + if (filesdim) + { + unsigned threadaddr; + hThread = (HANDLE) _beginthreadex(NULL, + 0, + &startthread, + this, + 0, + (unsigned *)&threadaddr); - if (hThread) - { - SetThreadPriority(hThread, THREAD_PRIORITY_HIGHEST); - } - else - { - assert(0); + if (hThread) + { + SetThreadPriority(hThread, THREAD_PRIORITY_HIGHEST); + } + else + { + assert(0); + } } } @@ -98,6 +102,7 @@ { AsyncRead *aw = (AsyncRead *)p; + //printf("aw->filesdim = %p %d\n", aw, aw->filesdim); for (size_t i = 0; i < aw->filesdim; i++) { FileData *f = &aw->files[i]; diff -r d28cd7c45267 -r 54b3c1394d62 dmd2/scope.c --- a/dmd2/scope.c Mon Jul 06 23:57:27 2009 +0100 +++ b/dmd2/scope.c Tue Jul 07 02:26:11 2009 +0100 @@ -71,6 +71,7 @@ this->nofree = 0; this->noctor = 0; this->noaccesscheck = 0; + this->mustsemantic = 0; this->intypeof = 0; this->parameterSpecialization = 0; this->callSuper = 0; @@ -119,6 +120,7 @@ this->nofree = 0; this->noctor = enclosing->noctor; this->noaccesscheck = enclosing->noaccesscheck; + this->mustsemantic = enclosing->mustsemantic; this->intypeof = enclosing->intypeof; this->parameterSpecialization = enclosing->parameterSpecialization; this->callSuper = enclosing->callSuper; diff -r d28cd7c45267 -r 54b3c1394d62 dmd2/scope.h --- a/dmd2/scope.h Mon Jul 06 23:57:27 2009 +0100 +++ b/dmd2/scope.h Tue Jul 07 02:26:11 2009 +0100 @@ -71,6 +71,7 @@ int intypeof; // in typeof(exp) int parameterSpecialization; // if in template parameter specialization int noaccesscheck; // don't do access checks + int mustsemantic; // cannot defer semantic() unsigned callSuper; // primitive flow analysis for constructors #define CSXthis_ctor 1 // called this() diff -r d28cd7c45267 -r 54b3c1394d62 dmd2/statement.c --- a/dmd2/statement.c Mon Jul 06 23:57:27 2009 +0100 +++ b/dmd2/statement.c Tue Jul 07 02:26:11 2009 +0100 @@ -144,6 +144,13 @@ return FALSE; } +// Return TRUE if statement has no code in it +int Statement::isEmpty() +{ + //printf("Statement::isEmpty()\n"); + return FALSE; +} + /**************************************** * If this statement has code that needs to run in a finally clause * at the end of the current scope, return that code in the form of @@ -580,6 +587,16 @@ return comefrom; } +int CompoundStatement::isEmpty() +{ + for (int i = 0; i < statements->dim; i++) + { Statement *s = (Statement *) statements->data[i]; + if (s && !s->isEmpty()) + return FALSE; + } + return TRUE; +} + /******************************** CompoundDeclarationStatement ***************************/ @@ -856,6 +873,12 @@ return statement ? statement->comeFrom() : FALSE; } +int ScopeStatement::isEmpty() +{ + //printf("ScopeStatement::isEmpty() %d\n", statement ? statement->isEmpty() : TRUE); + return statement ? statement->isEmpty() : TRUE; +} + void ScopeStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) { buf->writeByte('{'); @@ -1536,7 +1559,6 @@ /* Generate a temporary __r and initialize it with the aggregate. */ Identifier *id = Identifier::generateId("__r"); - aggr = aggr->semantic(sc); Expression *rinit = new SliceExp(loc, aggr, NULL, NULL); rinit = rinit->trySemantic(sc); if (!rinit) // if application of [] failed @@ -1870,7 +1892,7 @@ } s = new CompoundStatement(loc, a); - s = new SwitchStatement(loc, e, s); + s = new SwitchStatement(loc, e, s, FALSE); s = s->semantic(sc); } break; @@ -2546,23 +2568,25 @@ /******************************** SwitchStatement ***************************/ -SwitchStatement::SwitchStatement(Loc loc, Expression *c, Statement *b) +SwitchStatement::SwitchStatement(Loc loc, Expression *c, Statement *b, bool isFinal) : Statement(loc) { - condition = c; - body = b; + this->condition = c; + this->body = b; + this->isFinal = isFinal; sdefault = NULL; cases = NULL; hasNoDefault = 0; hasVars = 0; - // LDC +#if IN_LLVM enclosingScopeExit = NULL; +#endif } Statement *SwitchStatement::syntaxCopy() { SwitchStatement *s = new SwitchStatement(loc, - condition->syntaxCopy(), body->syntaxCopy()); + condition->syntaxCopy(), body->syntaxCopy(), isFinal); return s; } @@ -2571,8 +2595,9 @@ //printf("SwitchStatement::semantic(%p)\n", this); assert(!cases); // ensure semantic() is only run once - // LDC +#if IN_LLVM enclosingScopeExit = sc->enclosingScopeExit; +#endif condition = condition->semantic(sc); condition = resolveProperties(sc, condition); @@ -2663,6 +2688,37 @@ body = cs; } +#if DMDV2 + if (isFinal) + { Type *t = condition->type; + while (t->ty == Ttypedef) + { // Don't use toBasetype() because that will skip past enums + t = ((TypeTypedef *)t)->sym->basetype; + } + if (condition->type->ty == Tenum) + { TypeEnum *te = (TypeEnum *)condition->type; + EnumDeclaration *ed = te->toDsymbol(sc)->isEnumDeclaration(); + assert(ed); + size_t dim = ed->members->dim; + for (size_t i = 0; i < dim; i++) + { + EnumMember *em = ((Dsymbol *)ed->members->data[i])->isEnumMember(); + if (em) + { + for (size_t j = 0; j < cases->dim; j++) + { CaseStatement *cs = (CaseStatement *)cases->data[j]; + if (cs->exp->equals(em->value)) + goto L1; + } + error("enum member %s not represented in final switch", em->toChars()); + } + L1: + ; + } + } + } +#endif + sc->pop(); return this; } @@ -2746,13 +2802,13 @@ exp = exp->semantic(sc); if (sw) { - // LDC +#if IN_LLVM enclosingScopeExit = sc->enclosingScopeExit; if (enclosingScopeExit != sw->enclosingScopeExit) { error("case must be inside the same try, synchronized or volatile level as switch"); } - +#endif exp = exp->implicitCastTo(sc, sw->condition->type); exp = exp->optimize(WANTvalue | WANTinterpret); @@ -2767,6 +2823,8 @@ * for this, i.e. generate a sequence of if-then-else */ sw->hasVars = 1; + if (sw->isFinal) + error("case variables not allowed in final switch statements"); goto L1; } } @@ -2846,6 +2904,85 @@ statement->toCBuffer(buf, hgs); } +/******************************** CaseRangeStatement ***************************/ + +#if DMDV2 + +CaseRangeStatement::CaseRangeStatement(Loc loc, Expression *first, + Expression *last, Statement *s) + : Statement(loc) +{ + this->first = first; + this->last = last; + this->statement = s; +} + +Statement *CaseRangeStatement::syntaxCopy() +{ + CaseRangeStatement *s = new CaseRangeStatement(loc, + first->syntaxCopy(), last->syntaxCopy(), statement->syntaxCopy()); + return s; +} + +Statement *CaseRangeStatement::semantic(Scope *sc) +{ SwitchStatement *sw = sc->sw; + + //printf("CaseRangeStatement::semantic() %s\n", toChars()); + if (sw->isFinal) + error("case ranges not allowed in final switch"); + + first = first->semantic(sc); + first = first->implicitCastTo(sc, sw->condition->type); + first = first->optimize(WANTvalue | WANTinterpret); + dinteger_t fval = first->toInteger(); + + last = last->semantic(sc); + last = last->implicitCastTo(sc, sw->condition->type); + last = last->optimize(WANTvalue | WANTinterpret); + dinteger_t lval = last->toInteger(); + + if (lval - fval > 256) + { error("more than 256 cases in case range"); + lval = fval + 256; + } + + /* This works by replacing the CaseRange with an array of Case's. + * + * case a: .. case b: s; + * => + * case a: + * [...] + * case b: + * s; + */ + + Statements *statements = new Statements(); + for (dinteger_t i = fval; i <= lval; i++) + { + Statement *s = statement; + if (i != lval) + s = new ExpStatement(loc, NULL); + Expression *e = new IntegerExp(loc, i, first->type); + Statement *cs = new CaseStatement(loc, e, s); + statements->push(cs); + } + Statement *s = new CompoundStatement(loc, statements); + s = s->semantic(sc); + return s; +} + +void CaseRangeStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) +{ + buf->writestring("case "); + first->toCBuffer(buf, hgs); + buf->writestring(": .. case "); + last->toCBuffer(buf, hgs); + buf->writenl(); + statement->toCBuffer(buf, hgs); +} + +#endif + /******************************** DefaultStatement ***************************/ DefaultStatement::DefaultStatement(Loc loc, Statement *s) @@ -2877,12 +3014,18 @@ } sc->sw->sdefault = this; - // LDC +#if IN_LLVM enclosingScopeExit = sc->enclosingScopeExit; if (enclosingScopeExit != sc->sw->enclosingScopeExit) { error("default must be inside the same try, synchronized or volatile level as switch"); } + + if (sc->sw->isFinal) + { + error("default statement not allowed in final switch statement"); + } +#endif } else error("default not in switch statement"); @@ -3217,6 +3360,7 @@ // Construct: { vresult = exp; return cases.dim + 1; } exp = new AssignExp(loc, new VarExp(0, fd->vresult), exp); + exp->op = TOKconstruct; exp = exp->semantic(sc); Statement *s1 = new ExpStatement(loc, exp); Statement *s2 = new ReturnStatement(0, new IntegerExp(sc->fes->cases.dim + 1)); @@ -3233,6 +3377,7 @@ VarExp *v = new VarExp(0, fd->vresult); exp = new AssignExp(loc, v, exp); + exp->op = TOKconstruct; exp = exp->semantic(sc); } @@ -3757,9 +3902,10 @@ } } - if (!body) + if (!body || body->isEmpty()) + { return NULL; - + } return this; } diff -r d28cd7c45267 -r 54b3c1394d62 dmd2/statement.h --- a/dmd2/statement.h Mon Jul 06 23:57:27 2009 +0100 +++ b/dmd2/statement.h Tue Jul 07 02:26:11 2009 +0100 @@ -128,6 +128,7 @@ virtual int usesEH(); virtual int blockExit(); virtual int comeFrom(); + virtual int isEmpty(); virtual void scopeCode(Scope *sc, Statement **sentry, Statement **sexit, Statement **sfinally); virtual Statements *flatten(Scope *sc); virtual Expression *interpret(InterState *istate); @@ -146,9 +147,10 @@ virtual IfStatement *isIfStatement() { return NULL; } virtual CaseStatement* isCaseStatement() { return NULL; } - // LDC +#if IN_LLVM virtual void toNakedIR(IRState *irs); virtual AsmBlockStatement* endsWithAsm(); +#endif }; struct ExpStatement : Statement @@ -168,8 +170,9 @@ void toIR(IRState *irs); - // LDC +#if IN_LLVM void toNakedIR(IRState *irs); +#endif }; struct CompileStatement : Statement @@ -209,6 +212,7 @@ int usesEH(); int blockExit(); int comeFrom(); + int isEmpty(); virtual Statements *flatten(Scope *sc); ReturnStatement *isReturnStatement(); Expression *interpret(InterState *istate); @@ -219,9 +223,10 @@ virtual void toIR(IRState *irs); - // LDC +#if IN_LLVM virtual void toNakedIR(IRState *irs); virtual AsmBlockStatement* endsWithAsm(); +#endif virtual CompoundStatement *isCompoundStatement() { return this; } }; @@ -272,6 +277,7 @@ int usesEH(); int blockExit(); int comeFrom(); + int isEmpty(); Expression *interpret(InterState *istate); Statement *inlineScan(InlineScanState *iss); @@ -479,6 +485,7 @@ { Expression *condition; Statement *body; + bool isFinal; DefaultStatement *sdefault; @@ -487,10 +494,11 @@ int hasNoDefault; // !=0 if no default statement int hasVars; // !=0 if has variable case values - // LDC +#if IN_LLVM Statement *enclosingScopeExit; +#endif - SwitchStatement(Loc loc, Expression *c, Statement *b); + SwitchStatement(Loc loc, Expression *c, Statement *b, bool isFinal); Statement *syntaxCopy(); Statement *semantic(Scope *sc); int hasBreak(); @@ -508,11 +516,13 @@ { Expression *exp; Statement *statement; + int index; // which case it is (since we sort this) block *cblock; // back end: label for the block - // LDC +#if IN_LLVM Statement *enclosingScopeExit; +#endif CaseStatement(Loc loc, Expression *exp, Statement *s); Statement *syntaxCopy(); @@ -530,11 +540,28 @@ CaseStatement* isCaseStatement() { return this; } - // LDC +#if IN_LLVM llvm::BasicBlock* bodyBB; llvm::ConstantInt* llvmIdx; +#endif }; +#if DMDV2 + +struct CaseRangeStatement : Statement +{ + Expression *first; + Expression *last; + Statement *statement; + + CaseRangeStatement(Loc loc, Expression *first, Expression *last, Statement *s); + Statement *syntaxCopy(); + Statement *semantic(Scope *sc); + void toCBuffer(OutBuffer *buf, HdrGenState *hgs); +}; + +#endif + struct DefaultStatement : Statement { Statement *statement; @@ -542,8 +569,9 @@ block *cblock; // back end: label for the block #endif - // LDC +#if IN_LLVM Statement *enclosingScopeExit; +#endif DefaultStatement(Loc loc, Statement *s); Statement *syntaxCopy(); @@ -558,8 +586,9 @@ void toIR(IRState *irs); - // LDC +#if IN_LLVM llvm::BasicBlock* bodyBB; +#endif }; struct GotoDefaultStatement : Statement @@ -634,8 +663,10 @@ void toIR(IRState *irs); +#if IN_LLVM // LDC: only set if ident is set: label statement to jump to LabelStatement *target; +#endif }; struct ContinueStatement : Statement @@ -651,8 +682,10 @@ void toIR(IRState *irs); +#if IN_LLVM // LDC: only set if ident is set: label statement to jump to LabelStatement *target; +#endif }; struct SynchronizedStatement : Statement @@ -675,7 +708,9 @@ elem *esync; SynchronizedStatement(Loc loc, elem *esync, Statement *body); void toIR(IRState *irs); +#if IN_LLVM llvm::Value* llsync; +#endif }; struct WithStatement : Statement @@ -837,9 +872,10 @@ void toIR(IRState *irs); - // LDC +#if IN_LLVM bool asmLabel; // for labels inside inline assembler void toNakedIR(IRState *irs); +#endif }; struct LabelDsymbol : Dsymbol @@ -873,11 +909,12 @@ void toIR(IRState *irs); - // LDC +#if IN_LLVM // non-zero if this is a branch, contains the target labels identifier Identifier* isBranchToLabel; void toNakedIR(IRState *irs); +#endif }; struct AsmBlockStatement : CompoundStatement diff -r d28cd7c45267 -r 54b3c1394d62 dmd2/struct.c --- a/dmd2/struct.c Mon Jul 06 23:57:27 2009 +0100 +++ b/dmd2/struct.c Tue Jul 07 02:26:11 2009 +0100 @@ -46,7 +46,6 @@ stag = NULL; sinit = NULL; #endif - scope = NULL; isnested = 0; vthis = NULL; @@ -70,7 +69,7 @@ void AggregateDeclaration::semantic2(Scope *sc) { //printf("AggregateDeclaration::semantic2(%s)\n", toChars()); - if (scope) + if (scope && members) { error("has forward references"); return; } @@ -89,9 +88,10 @@ void AggregateDeclaration::semantic3(Scope *sc) { int i; - // LDC +#if IN_LLVM if (!global.params.useAvailableExternally) availableExternally = false; +#endif //printf("AggregateDeclaration::semantic3(%s)\n", toChars()); if (members) @@ -288,6 +288,7 @@ } parent = sc->parent; + type = type->semantic(loc, sc); #if STRUCTTHISREF handle = type; #else diff -r d28cd7c45267 -r 54b3c1394d62 dmd2/template.c --- a/dmd2/template.c Mon Jul 06 23:57:27 2009 +0100 +++ b/dmd2/template.c Tue Jul 07 02:26:11 2009 +0100 @@ -308,7 +308,7 @@ this->members = decldefs; this->overnext = NULL; this->overroot = NULL; - this->scope = NULL; + this->semanticRun = 0; this->onemember = NULL; this->literal = 0; } @@ -337,7 +337,6 @@ td = new TemplateDeclaration(loc, ident, p, e, d); #if IN_LLVM - // LDC td->intrinsicName = intrinsicName; #endif @@ -349,8 +348,9 @@ #if LOG printf("TemplateDeclaration::semantic(this = %p, id = '%s')\n", this, ident->toChars()); #endif - if (scope) + if (semanticRun) return; // semantic() already run + semanticRun = 1; if (sc->func) { @@ -878,8 +878,8 @@ fvarargs = fctor->varargs; } - nfparams = Argument::dim(fparameters); // number of function parameters - nfargs = fargs->dim; // number of function arguments + nfparams = Argument::dim(fparameters); // number of function parameters + nfargs = fargs ? fargs->dim : 0; // number of function arguments /* Check for match of function arguments with variadic template * parameter, such as: @@ -1329,7 +1329,7 @@ for (TemplateDeclaration *td = this; td; td = td->overnext) { - if (!td->scope) + if (!td->semanticRun) { error("forward reference to template %s", td->toChars()); goto Lerror; @@ -3215,7 +3215,7 @@ this->tinst = NULL; this->argsym = NULL; this->aliasdecl = NULL; - this->semanticdone = 0; + this->semanticRun = 0; this->semantictiargsdone = 0; this->withsym = NULL; this->nest = 0; @@ -3249,7 +3249,7 @@ this->tinst = NULL; this->argsym = NULL; this->aliasdecl = NULL; - this->semanticdone = 0; + this->semanticRun = 0; this->semantictiargsdone = 1; this->withsym = NULL; this->nest = 0; @@ -3324,13 +3324,13 @@ // get the enclosing template instance from the scope tinst tinst = sc->tinst; - if (semanticdone != 0) + if (semanticRun != 0) { error(loc, "recursive template expansion"); // inst = this; return; } - semanticdone = 1; + semanticRun = 1; #if IN_LLVM // get the enclosing template instance from the scope tinst tinst = sc->tinst; @@ -3474,7 +3474,7 @@ { Module *m = sc->module->importedFrom; //printf("\t2: adding to module %s instead of module %s\n", m->toChars(), sc->module->toChars()); a = m->members; - if (m->semanticdone >= 3) + if (m->semanticRun >= 3) dosemantic3 = 1; } for (int i = 0; 1; i++) @@ -3495,9 +3495,9 @@ // Create our own scope for the template parameters Scope *scope = tempdecl->scope; - if (!scope) + if (!tempdecl->semanticRun) { - error("forward reference to template declaration %s\n", tempdecl->toChars()); + error("template instantiation %s forward references template declaration %s\n", toChars(), tempdecl->toChars()); return; } @@ -3717,6 +3717,7 @@ } else if (ta) { + Ltype: if (ta->ty == Ttuple) { // Expand tuple TypeTuple *tt = (TypeTuple *)ta; @@ -3752,12 +3753,26 @@ ea = ea->optimize(WANTvalue | WANTinterpret); tiargs->data[j] = ea; if (ea->op == TOKtype) - tiargs->data[j] = ea->type; + { ta = ea->type; + goto Ltype; + } + if (ea->op == TOKtuple) + { // Expand tuple + TupleExp *te = (TupleExp *)ea; + size_t dim = te->exps->dim; + tiargs->remove(j); + if (dim) + { tiargs->reserve(dim); + for (size_t i = 0; i < dim; i++) + tiargs->insert(j + i, te->exps->data[i]); + } + j--; + } } else if (sa) { TemplateDeclaration *td = sa->isTemplateDeclaration(); - if (td && !td->scope && td->literal) + if (td && !td->semanticRun && td->literal) td->semantic(sc); } else @@ -3898,6 +3913,23 @@ #if LOG printf("TemplateInstance::findBestMatch()\n"); #endif + // First look for forward references + for (TemplateDeclaration *td = tempdecl; td; td = td->overnext) + { + if (!td->semanticRun) + { + if (td->scope) + { // Try to fix forward reference + td->semantic(td->scope); + } + if (!td->semanticRun) + { + error("%s forward references template declaration %s\n", toChars(), td->toChars()); + return NULL; + } + } + } + for (TemplateDeclaration *td = tempdecl; td; td = td->overnext) { MATCH m; @@ -3914,11 +3946,7 @@ dedtypes.setDim(td->parameters->dim); dedtypes.zero(); - if (!td->scope) - { - error("forward reference to template declaration %s", td->toChars()); - return NULL; - } + assert(td->semanticRun); m = td->matchWithInstance(this, &dedtypes, 0); //printf("matchWithInstance = %d\n", m); if (!m) // no match at all @@ -4212,7 +4240,7 @@ * template instance arguments. */ -void TemplateInstance::declareParameters(Scope *scope) +void TemplateInstance::declareParameters(Scope *sc) { //printf("TemplateInstance::declareParameters()\n"); for (int i = 0; i < tdtypes.dim; i++) @@ -4222,7 +4250,7 @@ Object *o = (Object *)tdtypes.data[i]; // initializer for tp //printf("\ttdtypes[%d] = %p\n", i, o); - tempdecl->declareParameter(scope, tp, o); + tempdecl->declareParameter(sc, tp, o); } } @@ -4230,9 +4258,9 @@ void TemplateInstance::semantic2(Scope *sc) { int i; - if (semanticdone >= 2) + if (semanticRun >= 2) return; - semanticdone = 2; + semanticRun = 2; #if LOG printf("+TemplateInstance::semantic2('%s')\n", toChars()); #endif @@ -4262,12 +4290,12 @@ void TemplateInstance::semantic3(Scope *sc) { #if LOG - printf("TemplateInstance::semantic3('%s'), semanticdone = %d\n", toChars(), semanticdone); + printf("TemplateInstance::semantic3('%s'), semanticRun = %d\n", toChars(), semanticRun); #endif //if (toChars()[0] == 'D') *(char*)0=0; - if (semanticdone >= 3) + if (semanticRun >= 3) return; - semanticdone = 3; + semanticRun = 3; if (!errors && members) { sc = tempdecl->scope; @@ -4457,7 +4485,6 @@ this->tqual = tqual; this->idents = idents; this->tiargs = tiargs ? tiargs : new Objects(); - this->scope = NULL; } Dsymbol *TemplateMixin::syntaxCopy(Dsymbol *s) @@ -4491,7 +4518,7 @@ printf("+TemplateMixin::semantic('%s', this=%p)\n", toChars(), this); fflush(stdout); #endif - if (semanticdone && + if (semanticRun && // This for when a class/struct contains mixin members, and // is done over because of forward references (!parent || !toParent()->isAggregateDeclaration())) @@ -4501,8 +4528,8 @@ #endif return; } - if (!semanticdone) - semanticdone = 1; + if (!semanticRun) + semanticRun = 1; #if LOG printf("\tdo semantic\n"); #endif @@ -4577,7 +4604,7 @@ assert(tempdecl); for (TemplateDeclaration *td = tempdecl; td; td = td->overnext) { - if (!td->scope) + if (!td->semanticRun) { /* Cannot handle forward references if mixin is a struct member, * because addField must happen during struct's semantic, not @@ -4585,7 +4612,7 @@ * runDeferred will re-run mixin's semantic outside of the struct's * semantic. */ - semanticdone = 0; + semanticRun = 0; AggregateDeclaration *ad = toParent()->isAggregateDeclaration(); if (ad) ad->sizeok = 2; @@ -4691,19 +4718,19 @@ argsym = new ScopeDsymbol(); argsym->parent = scy->parent; - Scope *scope = scy->push(argsym); + Scope *argscope = scy->push(argsym); unsigned errorsave = global.errors; // Declare each template parameter as an alias for the argument type - declareParameters(scope); + declareParameters(argscope); // Add members to enclosing scope, as well as this scope for (unsigned i = 0; i < members->dim; i++) { Dsymbol *s; s = (Dsymbol *)members->data[i]; - s->addMember(scope, this, i); + s->addMember(argscope, this, i); //sc->insert(s); //printf("sc->parent = %p, sc->scopesym = %p\n", sc->parent, sc->scopesym); //printf("s->parent = %s\n", s->parent->toChars()); @@ -4714,7 +4741,7 @@ printf("\tdo semantic() on template instance members '%s'\n", toChars()); #endif Scope *sc2; - sc2 = scope->push(this); + sc2 = argscope->push(this); sc2->offset = sc->offset; static int nest; @@ -4757,7 +4784,7 @@ sc2->pop(); - scope->pop(); + argscope->pop(); // if (!isAnonymous()) { @@ -4771,9 +4798,9 @@ void TemplateMixin::semantic2(Scope *sc) { int i; - if (semanticdone >= 2) + if (semanticRun >= 2) return; - semanticdone = 2; + semanticRun = 2; #if LOG printf("+TemplateMixin::semantic2('%s')\n", toChars()); #endif @@ -4801,9 +4828,9 @@ void TemplateMixin::semantic3(Scope *sc) { int i; - if (semanticdone >= 3) + if (semanticRun >= 3) return; - semanticdone = 3; + semanticRun = 3; #if LOG printf("TemplateMixin::semantic3('%s')\n", toChars()); #endif diff -r d28cd7c45267 -r 54b3c1394d62 dmd2/template.h --- a/dmd2/template.h Mon Jul 06 23:57:27 2009 +0100 +++ b/dmd2/template.h Tue Jul 07 02:26:11 2009 +0100 @@ -61,7 +61,8 @@ TemplateDeclaration *overnext; // next overloaded TemplateDeclaration TemplateDeclaration *overroot; // first in overnext list - Scope *scope; + int semanticRun; // 1 semantic() run + Dsymbol *onemember; // if !=NULL then one member of this template int literal; // this template declaration is a literal @@ -284,7 +285,7 @@ AliasDeclaration *aliasdecl; // !=NULL if instance is an alias for its // sole member WithScopeSymbol *withsym; // if a member of a with statement - int semanticdone; // has semantic() been done? + int semanticRun; // has semantic() been done? int semantictiargsdone; // has semanticTiargs() been done? int nest; // for recursion detection int havetempdecl; // 1 if used second constructor @@ -343,8 +344,6 @@ Array *idents; Type *tqual; - Scope *scope; // for forward referencing - TemplateMixin(Loc loc, Identifier *ident, Type *tqual, Array *idents, Objects *tiargs); Dsymbol *syntaxCopy(Dsymbol *s); void semantic(Scope *sc);