diff -uNr dmd-1.025/dmd/src/dmd/declaration.c dmd-1.026/dmd/src/dmd/declaration.c --- dmd-1.025/dmd/src/dmd/declaration.c 2007-11-01 22:17:24.000000000 +0100 +++ dmd-1.026/dmd/src/dmd/declaration.c 2008-01-20 00:35:24.000000000 +0100 @@ -1094,6 +1094,7 @@ Expression *VarDeclaration::callAutoDtor() { Expression *e = NULL; + //printf("VarDeclaration::callAutoDtor() %s\n", toChars()); if (storage_class & (STCauto | STCscope) && !noauto) { for (ClassDeclaration *cd = type->isClassHandle(); @@ -1104,6 +1105,8 @@ * classes to determine if there's no way the monitor * could be set. */ + if (cd->isInterfaceDeclaration()) + error("interface %s cannot be scope", cd->toChars()); if (1 || onstack || cd->dtors.dim) // if any destructors { // delete this; diff -uNr dmd-1.025/dmd/src/dmd/expression.c dmd-1.026/dmd/src/dmd/expression.c --- dmd-1.025/dmd/src/dmd/expression.c 2007-12-21 02:44:52.000000000 +0100 +++ dmd-1.026/dmd/src/dmd/expression.c 2008-01-17 14:36:20.000000000 +0100 @@ -518,7 +518,7 @@ { // BUG: should check that argument to ref is type 'invariant' // BUG: assignments to ref should also be type 'invariant' - arg = arg->modifiableLvalue(sc, NULL); + arg = arg->modifiableLvalue(sc, arg); //if (arg->op == TOKslice) //arg->error("cannot modify slice %s", arg->toChars()); @@ -4351,7 +4351,7 @@ if (e) return e; - e1 = e1->modifiableLvalue(sc, NULL); + e1 = e1->modifiableLvalue(sc, e1); e1->checkScalar(); type = e1->type; if (type->toBasetype()->ty == Tbool) @@ -4382,7 +4382,7 @@ if (e) return e; - e1 = e1->modifiableLvalue(sc, NULL); + e1 = e1->modifiableLvalue(sc, e1); e1->checkScalar(); type = e1->type; if (type->toBasetype()->ty == Tbool) @@ -6863,7 +6863,7 @@ return e; e = this; - e1 = e1->modifiableLvalue(sc, NULL); + e1 = e1->modifiableLvalue(sc, e1); e1->checkScalar(); e1->checkNoBool(); if (e1->type->ty == Tpointer) @@ -7049,7 +7049,7 @@ // e1 is not an lvalue, but we let code generator handle it ArrayLengthExp *ale = (ArrayLengthExp *)e1; - ale->e1 = ale->e1->modifiableLvalue(sc, NULL); + ale->e1 = ale->e1->modifiableLvalue(sc, e1); } else if (e1->op == TOKslice) ; @@ -7111,7 +7111,7 @@ if (e) return e; - e1 = e1->modifiableLvalue(sc, NULL); + e1 = e1->modifiableLvalue(sc, e1); Type *tb1 = e1->type->toBasetype(); Type *tb2 = e2->type->toBasetype(); @@ -7211,7 +7211,7 @@ if (e) return e; - e1 = e1->modifiableLvalue(sc, NULL); + e1 = e1->modifiableLvalue(sc, e1); e1->checkScalar(); e1->checkNoBool(); if (e1->type->ty == Tpointer && e2->type->isintegral()) @@ -7256,7 +7256,7 @@ error("cannot append to static array %s", se->e1->type->toChars()); } - e1 = e1->modifiableLvalue(sc, NULL); + e1 = e1->modifiableLvalue(sc, e1); Type *tb1 = e1->type->toBasetype(); Type *tb2 = e2->type->toBasetype(); @@ -7305,7 +7305,7 @@ if (e) return e; - e1 = e1->modifiableLvalue(sc, NULL); + e1 = e1->modifiableLvalue(sc, e1); e1->checkScalar(); e1->checkNoBool(); type = e1->type; @@ -7361,7 +7361,7 @@ if (e) return e; - e1 = e1->modifiableLvalue(sc, NULL); + e1 = e1->modifiableLvalue(sc, e1); e1->checkScalar(); e1->checkNoBool(); type = e1->type; @@ -7432,7 +7432,7 @@ if (e) return e; - e1 = e1->modifiableLvalue(sc, NULL); + e1 = e1->modifiableLvalue(sc, e1); e1->checkScalar(); e1->checkNoBool(); type = e1->type; @@ -7460,7 +7460,7 @@ if (e) return e; - e1 = e1->modifiableLvalue(sc, NULL); + e1 = e1->modifiableLvalue(sc, e1); e1->checkScalar(); e1->checkNoBool(); type = e1->type; @@ -7488,7 +7488,7 @@ if (e) return e; - e1 = e1->modifiableLvalue(sc, NULL); + e1 = e1->modifiableLvalue(sc, e1); e1->checkScalar(); e1->checkNoBool(); type = e1->type; diff -uNr dmd-1.025/dmd/src/dmd/lexer.c dmd-1.026/dmd/src/dmd/lexer.c --- dmd-1.025/dmd/src/dmd/lexer.c 2007-08-21 16:44:26.000000000 +0200 +++ dmd-1.026/dmd/src/dmd/lexer.c 2008-01-20 01:29:46.000000000 +0100 @@ -2160,7 +2160,7 @@ break; if (d >= r) break; - if (n * r + d < n) + if (n && n * r + d <= n) { error ("integer overflow"); break; diff -uNr dmd-1.025/dmd/src/dmd/mangle.c dmd-1.026/dmd/src/dmd/mangle.c --- dmd-1.025/dmd/src/dmd/mangle.c 2007-04-11 21:40:44.000000000 +0200 +++ dmd-1.026/dmd/src/dmd/mangle.c 2008-01-07 18:12:40.000000000 +0100 @@ -141,6 +141,9 @@ if (isMain()) return "_Dmain"; + if (isWinMain() || isDllMain()) + return ident->toChars(); + assert(this); return Declaration::mangle(); } diff -uNr dmd-1.025/dmd/src/dmd/mars.c dmd-1.026/dmd/src/dmd/mars.c --- dmd-1.025/dmd/src/dmd/mars.c 2007-12-03 14:21:34.000000000 +0100 +++ dmd-1.026/dmd/src/dmd/mars.c 2008-01-20 11:51:34.000000000 +0100 @@ -1,6 +1,6 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2007 by Digital Mars +// Copyright (c) 1999-2008 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -58,9 +58,9 @@ #error "fix this" #endif - copyright = "Copyright (c) 1999-2007 by Digital Mars"; + copyright = "Copyright (c) 1999-2008 by Digital Mars"; written = "written by Walter Bright"; - version = "v1.025"; + version = "v1.026"; global.structalign = 8; memset(¶ms, 0, sizeof(Param)); diff -uNr dmd-1.025/dmd/src/dmd/mtype.c dmd-1.026/dmd/src/dmd/mtype.c --- dmd-1.025/dmd/src/dmd/mtype.c 2007-11-01 22:27:36.000000000 +0100 +++ dmd-1.026/dmd/src/dmd/mtype.c 2008-01-15 02:04:24.000000000 +0100 @@ -3951,6 +3951,15 @@ return sym->basetype->dotExp(sc, e, ident); } +Expression *TypeTypedef::getProperty(Loc loc, Identifier *ident) +{ + if (ident == Id::init) + { + return Type::getProperty(loc, ident); + } + return sym->basetype->getProperty(loc, ident); +} + int TypeTypedef::isbit() { return sym->basetype->isbit(); @@ -4254,6 +4263,18 @@ return e; } + TemplateInstance *ti = s->isTemplateInstance(); + if (ti) + { if (!ti->semanticdone) + ti->semantic(sc); + s = ti->inst->toAlias(); + if (!s->isTemplateInstance()) + goto L1; + Expression *de = new DotExp(e->loc, e, new ScopeExp(e->loc, ti)); + de->type = e->type; + return de; + } + d = s->isDeclaration(); #ifdef DEBUG if (!d) @@ -4579,6 +4600,18 @@ return e; } + TemplateInstance *ti = s->isTemplateInstance(); + if (ti) + { if (!ti->semanticdone) + ti->semantic(sc); + s = ti->inst->toAlias(); + if (!s->isTemplateInstance()) + goto L1; + Expression *de = new DotExp(e->loc, e, new ScopeExp(e->loc, ti)); + de->type = e->type; + return de; + } + d = s->isDeclaration(); if (!d) { diff -uNr dmd-1.025/dmd/src/dmd/mtype.h dmd-1.026/dmd/src/dmd/mtype.h --- dmd-1.025/dmd/src/dmd/mtype.h 2007-10-21 11:17:04.000000000 +0200 +++ dmd-1.026/dmd/src/dmd/mtype.h 2008-01-03 02:17:28.000000000 +0100 @@ -572,6 +572,7 @@ void toTypeInfoBuffer(OutBuffer *buf); void toCBuffer2(OutBuffer *buf, Identifier *ident, HdrGenState *hgs); Expression *dotExp(Scope *sc, Expression *e, Identifier *ident); + Expression *getProperty(Loc loc, Identifier *ident); int isbit(); int isintegral(); int isfloating(); diff -uNr dmd-1.025/dmd/src/dmd/parse.c dmd-1.026/dmd/src/dmd/parse.c --- dmd-1.025/dmd/src/dmd/parse.c 2007-10-24 18:53:24.000000000 +0200 +++ dmd-1.026/dmd/src/dmd/parse.c 2008-01-19 01:14:20.000000000 +0100 @@ -1219,13 +1219,12 @@ TemplateParameters *Parser::parseTemplateParameterList() { - TemplateParameters *tpl; + TemplateParameters *tpl = new TemplateParameters(); if (token.value != TOKlparen) { error("parenthesized TemplateParameterList expected following TemplateIdentifier"); goto Lerr; } - tpl = new TemplateParameters(); nextToken(); // Get array of TemplateParameters @@ -1309,7 +1308,7 @@ if (!tp_ident) { error("no identifier for template value parameter"); - goto Lerr; + tp_ident = new Identifier("error", TOKidentifier); } if (token.value == TOKcolon) // : CondExpression { @@ -1330,10 +1329,8 @@ } } check(TOKrparen); - return tpl; - Lerr: - return NULL; + return tpl; } /****************************************** diff -uNr dmd-1.025/dmd/src/dmd/statement.c dmd-1.026/dmd/src/dmd/statement.c --- dmd-1.025/dmd/src/dmd/statement.c 2007-10-20 01:05:20.000000000 +0200 +++ dmd-1.026/dmd/src/dmd/statement.c 2008-01-19 23:36:04.000000000 +0100 @@ -1982,6 +1982,7 @@ { condition = condition->integralPromotions(sc); condition->checkIntegral(); } + condition = condition->optimize(WANTvalue); sc = sc->push(); sc->sbreak = this; diff -uNr dmd-1.025/dmd/src/dmd/template.c dmd-1.026/dmd/src/dmd/template.c --- dmd-1.025/dmd/src/dmd/template.c 2007-11-14 11:41:34.000000000 +0100 +++ dmd-1.026/dmd/src/dmd/template.c 2008-01-19 23:17:26.000000000 +0100 @@ -1,6 +1,6 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2007 by Digital Mars +// Copyright (c) 1999-2008 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -1540,6 +1540,9 @@ else if (tempinst->tempdecl != tp->tempinst->tempdecl) goto Lnomatch; + if (tempinst->tiargs->dim != tp->tempinst->tiargs->dim) + goto Lnomatch; + for (int i = 0; i < tempinst->tiargs->dim; i++) { //printf("test: [%d]\n", i); @@ -3008,6 +3011,8 @@ ea = ea->semantic(sc); ea = ea->optimize(WANTvalue | WANTinterpret); tiargs->data[j] = ea; + if (ea->op == TOKtype) + tiargs->data[j] = ea->type; } else if (sa) { @@ -3292,6 +3297,9 @@ Lsa: Declaration *d = sa->isDeclaration(); if (d && !d->isDataseg() && +#if V2 + !(d->storage_class & STCmanifest) && +#endif (!d->isFuncDeclaration() || d->isFuncDeclaration()->isNested()) && !isTemplateMixin()) { diff -uNr dmd-1.025/dmd/src/dmd/toir.c dmd-1.026/dmd/src/dmd/toir.c --- dmd-1.025/dmd/src/dmd/toir.c 2007-07-12 08:02:08.000000000 +0200 +++ dmd-1.026/dmd/src/dmd/toir.c 2008-01-18 10:15:28.000000000 +0100 @@ -1,6 +1,6 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2007 by Digital Mars +// Copyright (c) 1999-2008 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -102,6 +102,11 @@ { /* Going down one nesting level, i.e. we're calling * a nested function from its enclosing function. */ +#if V2 + if (irs->sclosure) + ethis = el_var(irs->sclosure); + else +#endif if (irs->sthis) { // We have a 'this' pointer for the current function ethis = el_var(irs->sthis); @@ -111,7 +116,11 @@ * adding this frame into the linked list of stack * frames. */ +#if V2 + if (thisfd->closureVars.dim) +#else if (thisfd->nestedFrameRef) +#endif { /* Local variables are referenced, can't skip. * Address of 'this' gives the 'this' for the nested * function @@ -124,7 +133,11 @@ * use NULL if no references to the current function's frame */ ethis = el_long(TYnptr, 0); +#if V2 + if (thisfd->closureVars.dim) +#else if (thisfd->nestedFrameRef) +#endif { /* OPframeptr is an operator that gets the frame pointer * for the current function, i.e. for the x86 it gets * the value of EBP @@ -160,7 +173,11 @@ if (thisfd->isNested()) { FuncDeclaration *p = s->toParent2()->isFuncDeclaration(); +#if V2 + if (!p || p->closureVars.dim) +#else if (!p || p->nestedFrameRef) +#endif ethis = el_una(OPind, TYnptr, ethis); } else if (thisfd->vthis) @@ -174,13 +191,15 @@ * function must be a member function of that class. */ ClassDeclaration *cd = s->isClassDeclaration(); - assert(cd); + if (!cd) + goto Lnoframe; if (//cd->baseClass == fd || fd->isClassDeclaration() && fd->isClassDeclaration()->isBaseOf(cd, NULL)) break; if (!cd->isNested() || !cd->vthis) { + Lnoframe: irs->getFunc()->error(loc, "cannot get frame pointer to %s", fd->toChars()); return el_long(TYnptr, 0); // error recovery } @@ -194,7 +213,11 @@ * nested references are skipped in the linked list * of frames. */ +#if V2 + if (s->toParent2()->isFuncDeclaration()->closureVars.dim) +#else if (s->toParent2()->isFuncDeclaration()->nestedFrameRef) +#endif ethis = el_una(OPind, TYnptr, ethis); break; } @@ -204,7 +227,11 @@ * nested references are skipped in the linked list * of frames. */ +#if V2 + if (s->toParent2()->isFuncDeclaration()->closureVars.dim) +#else if (s->toParent2()->isFuncDeclaration()->nestedFrameRef) +#endif ethis = el_una(OPind, TYnptr, ethis); } } @@ -351,4 +378,110 @@ return einit; } +/************************************* + * Closures are implemented by taking the local variables that + * need to survive the scope of the function, and copying them + * into a gc allocated chuck of memory. That chunk, called the + * closure here, is inserted into the linked list of stack + * frames instead of the usual stack frame. + * + * buildClosure() inserts code just after the function prolog + * is complete. It allocates memory for the closure, allocates + * a local variable (sclosure) to point to it, inserts into it + * the link to the enclosing frame, and copies into it the parameters + * that are referred to in nested functions. + * In VarExp::toElem and SymOffExp::toElem, when referring to a + * variable that is in a closure, takes the offset from sclosure rather + * than from the frame pointer. + * + * getEthis() and NewExp::toElem need to use sclosure, if set, rather + * than the current frame pointer. + */ + +#if V2 + +void FuncDeclaration::buildClosure(IRState *irs) +{ + if (needsClosure()) + { // Generate closure on the heap + // BUG: doesn't capture variadic arguments passed to this function + + Symbol *sclosure; + sclosure = symbol_name("__closptr",SCauto,Type::tvoidptr->toCtype()); + sclosure->Sflags |= SFLtrue | SFLfree; + symbol_add(sclosure); + irs->sclosure = sclosure; + + unsigned offset = PTRSIZE; // leave room for previous sthis + for (int i = 0; i < closureVars.dim; i++) + { VarDeclaration *v = (VarDeclaration *)closureVars.data[i]; + assert(v->isVarDeclaration()); + + /* Align and allocate space for v in the closure + * just like AggregateDeclaration::addField() does. + */ + unsigned memsize = v->type->size(); + unsigned memalignsize = v->type->alignsize(); + unsigned xalign = v->type->memalign(global.structalign); + AggregateDeclaration::alignmember(xalign, memalignsize, &offset); + v->offset = offset; + offset += memsize; + + /* Can't do nrvo if the variable is put in a closure, since + * what the shidden points to may no longer exist. + */ + if (nrvo_can && nrvo_var == v) + { + nrvo_can = 0; + } + } + // offset is now the size of the closure + + // Allocate memory for the closure + elem *e; + e = el_long(TYint, offset); + e = el_bin(OPcall, TYnptr, el_var(rtlsym[RTLSYM_ALLOCMEMORY]), e); + + // Assign block of memory to sclosure + // sclosure = allocmemory(sz); + e = el_bin(OPeq, TYvoid, el_var(sclosure), e); + + // Set the first element to sthis + // *(sclosure + 0) = sthis; + elem *ethis; + if (irs->sthis) + ethis = el_var(irs->sthis); + else + ethis = el_long(TYnptr, 0); + elem *ex = el_una(OPind, TYnptr, el_var(sclosure)); + ex = el_bin(OPeq, TYnptr, ex, ethis); + e = el_combine(e, ex); + + // Copy function parameters into closure + for (int i = 0; i < closureVars.dim; i++) + { VarDeclaration *v = (VarDeclaration *)closureVars.data[i]; + + if (!v->isParameter()) + continue; + tym_t tym = v->type->totym(); + if (v->type->toBasetype()->ty == Tsarray || v->isOut() || v->isRef()) + tym = TYnptr; // reference parameters are just pointers + ex = el_bin(OPadd, TYnptr, el_var(sclosure), el_long(TYint, v->offset)); + ex = el_una(OPind, tym, ex); + if (ex->Ety == TYstruct) + { ex->Enumbytes = v->type->size(); + ex = el_bin(OPstreq, tym, ex, el_var(v->toSymbol())); + ex->Enumbytes = v->type->size(); + } + else + ex = el_bin(OPeq, tym, ex, el_var(v->toSymbol())); + + e = el_combine(e, ex); + } + + block_appendexp(irs->blx->curblock, e); + } +} + +#endif diff -uNr dmd-1.025/dmd/src/phobos/std/stream.d dmd-1.026/dmd/src/phobos/std/stream.d --- dmd-1.025/dmd/src/phobos/std/stream.d 2008-01-01 00:49:12.000000000 +0100 +++ dmd-1.026/dmd/src/phobos/std/stream.d 2008-01-20 11:41:10.000000000 +0100 @@ -2109,7 +2109,7 @@ } /// creates file in requested mode - void create(char[] filename, FileMode mode = FileMode.Out) { + void create(char[] filename, FileMode mode = FileMode.OutNew) { File sf = cast(File)s; sf.create(filename,mode); resetSource();