changeset 846:bc982f1ad106

Merged DMD 1.037 frontend
author Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
date Sat, 13 Dec 2008 13:15:31 +0100
parents d128381e086e
children 356e65836fb5 ba390e5e9150
files dmd/attrib.c dmd/cast.c dmd/declaration.h dmd/expression.c dmd/func.c dmd/import.c dmd/lexer.c dmd/mars.c dmd/mtype.c dmd/parse.c dmd/root.c dmd/statement.c
diffstat 12 files changed, 508 insertions(+), 350 deletions(-) [+]
line wrap: on
line diff
--- a/dmd/attrib.c	Sat Dec 13 06:48:00 2008 +0100
+++ b/dmd/attrib.c	Sat Dec 13 13:15:31 2008 +0100
@@ -615,6 +615,7 @@
 	sc->flags = 0;
 	aad.structalign = sc->structalign;
 	aad.parent = ad;
+
 	for (unsigned i = 0; i < decl->dim; i++)
 	{
 	    Dsymbol *s = (Dsymbol *)decl->data[i];
--- a/dmd/cast.c	Sat Dec 13 06:48:00 2008 +0100
+++ b/dmd/cast.c	Sat Dec 13 13:15:31 2008 +0100
@@ -33,9 +33,10 @@
 {
     //printf("implicitCastTo(%s) => %s\n", type->toChars(), t->toChars());
     if (implicitConvTo(t))
-    {
+    {	TY tyfrom = type->toBasetype()->ty;
+	TY tyto = t->toBasetype()->ty;
 	if (global.params.warnings &&
-	    Type::impcnvWarn[type->toBasetype()->ty][t->toBasetype()->ty] &&
+	    Type::impcnvWarn[tyfrom][tyto] &&
 	    op != TOKint64)
 	{
 	    Expression *e = optimize(WANTflags | WANTvalue);
@@ -43,8 +44,24 @@
 	    if (e->op == TOKint64)
 		return e->implicitCastTo(sc, t);
 
-	    warning("%s: implicit conversion of expression (%s) of type %s to %s can cause loss of data",
-		loc.toChars(), toChars(), type->toChars(), t->toChars());
+	    if (tyfrom == Tint32 &&
+		(op == TOKadd || op == TOKmin ||
+		 op == TOKand || op == TOKor || op == TOKxor)
+	       )
+	    {
+		/* This is really only a semi-kludge fix,
+		 * we really should look at the operands of op
+		 * and see if they are narrower types.
+		 * For example, b=b|b and b=b|7 and s=b+b should be allowed,
+		 * but b=b|i should be an error.
+		 */
+		;
+	    }
+	    else
+	    {
+		warning("%s: implicit conversion of expression (%s) of type %s to %s can cause loss of data",
+		    loc.toChars(), toChars(), type->toChars(), t->toChars());
+	    }
 	}
 #if DMDV2
 	if (match == MATCHconst && t == type->constOf())
--- a/dmd/declaration.h	Sat Dec 13 06:48:00 2008 +0100
+++ b/dmd/declaration.h	Sat Dec 13 13:15:31 2008 +0100
@@ -623,6 +623,7 @@
     virtual int isNested();
     int needThis();
     virtual int isVirtual();
+    virtual int isFinal();
     virtual int addPreInvariant();
     virtual int addPostInvariant();
     Expression *interpret(InterState *istate, Expressions *arguments);
--- a/dmd/expression.c	Sat Dec 13 06:48:00 2008 +0100
+++ b/dmd/expression.c	Sat Dec 13 13:15:31 2008 +0100
@@ -5067,10 +5067,14 @@
 
     if (eright->op == TOKimport)	// also used for template alias's
     {
-	Dsymbol *s;
 	ScopeExp *ie = (ScopeExp *)eright;
 
-	s = ie->sds->search(loc, ident, 0);
+	/* Disable access to another module's private imports.
+	 * The check for 'is sds our current module' is because
+	 * the current module should have access to its own imports.
+	 */
+	Dsymbol *s = ie->sds->search(loc, ident,
+	    (ie->sds->isModule() && ie->sds != sc->module) ? 1 : 0);
 	if (s)
 	{
 	    s = s->toAlias();
--- a/dmd/func.c	Sat Dec 13 06:48:00 2008 +0100
+++ b/dmd/func.c	Sat Dec 13 13:15:31 2008 +0100
@@ -1965,6 +1965,23 @@
 	toParent()->isClassDeclaration();
 }
 
+int FuncDeclaration::isFinal()
+{
+    ClassDeclaration *cd;
+#if 0
+    printf("FuncDeclaration::isFinal(%s)\n", toChars());
+    printf("%p %d %d %d %d\n", isMember(), isStatic(), protection == PROTprivate, isCtorDeclaration(), linkage != LINKd);
+    printf("result is %d\n",
+	isMember() &&
+	!(isStatic() || protection == PROTprivate || protection == PROTpackage) &&
+	(cd = toParent()->isClassDeclaration()) != NULL &&
+	cd->storage_class & STCfinal);
+#endif
+    return isMember() &&
+	(Declaration::isFinal() ||
+	 ((cd = toParent()->isClassDeclaration()) != NULL && cd->storage_class & STCfinal));
+}
+
 int FuncDeclaration::isAbstract()
 {
     return storage_class & STCabstract;
@@ -2708,10 +2725,11 @@
 {
     if (global.params.useUnitTests)
     {
-	Type *tret;
-
 	type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd);
-	FuncDeclaration::semantic(sc);
+	Scope *sc2 = sc->push();
+	sc2->linkage = LINKd;
+	FuncDeclaration::semantic(sc2);
+	sc2->pop();
     }
 
     // We're going to need ModuleInfo even if the unit tests are not
--- a/dmd/import.c	Sat Dec 13 06:48:00 2008 +0100
+++ b/dmd/import.c	Sat Dec 13 13:15:31 2008 +0100
@@ -1,275 +1,262 @@
-
-// Compiler implementation of the D programming language
-// Copyright (c) 1999-2006 by Digital Mars
-// All Rights Reserved
-// written by Walter Bright
-// http://www.digitalmars.com
-// License for redistribution is by either the Artistic License
-// in artistic.txt, or the GNU General Public License in gnu.txt.
-// See the included readme.txt for details.
-
-#include <stdio.h>
-#include <assert.h>
-
-#include "root.h"
-#include "dsymbol.h"
-#include "import.h"
-#include "identifier.h"
-#include "module.h"
-#include "scope.h"
-#include "hdrgen.h"
-#include "mtype.h"
-#include "declaration.h"
-#include "id.h"
-
-/********************************* Import ****************************/
-
-Import::Import(Loc loc, Array *packages, Identifier *id, Identifier *aliasId,
-	int isstatic)
-    : Dsymbol(id)
-{
-    this->loc = loc;
-    this->packages = packages;
-    this->id = id;
-    this->aliasId = aliasId;
-    this->isstatic = isstatic;
-    protection = PROTundefined;
-    pkg = NULL;
-    mod = NULL;
-
-    if (aliasId)
-	this->ident = aliasId;
-    // Kludge to change Import identifier to first package
-    else if (packages && packages->dim)
-	this->ident = (Identifier *)packages->data[0];
-}
-
-void Import::addAlias(Identifier *name, Identifier *alias)
-{
-    if (isstatic)
-	error("cannot have an import bind list");
-
-    if (!aliasId)
-	this->ident = NULL;	// make it an anonymous import
-
-    names.push(name);
-    aliases.push(alias);
-}
-
-const char *Import::kind()
-{
-    return isstatic ? (char *)"static import" : (char *)"import";
-}
-
-enum PROT Import::prot()
-{
-    return protection;
-}
-
-Dsymbol *Import::syntaxCopy(Dsymbol *s)
-{
-    assert(!s);
-
-    Import *si;
-
-    si = new Import(loc, packages, id, aliasId, isstatic);
-
-    for (size_t i = 0; i < names.dim; i++)
-    {
-	si->addAlias((Identifier *)names.data[i], (Identifier *)aliases.data[i]);
-    }
-
-    return si;
-}
-
-void Import::load(Scope *sc)
-{
-    DsymbolTable *dst;
-    Dsymbol *s;
-
-    //printf("Import::load('%s')\n", toChars());
-
-    // See if existing module
-    dst = Package::resolve(packages, NULL, &pkg);
-
-    s = dst->lookup(id);
-    if (s)
-    {
-	if (s->isModule())
-	    mod = (Module *)s;
-	else
-	    error("package and module have the same name");
-    }
-
-    if (!mod)
-    {
-	// Load module
-	mod = Module::load(loc, packages, id);
-	dst->insert(id, mod);		// id may be different from mod->ident,
-					// if so then insert alias
-	if (!mod->importedFrom)
-	    mod->importedFrom = sc ? sc->module->importedFrom : Module::rootModule;
-    }
-    if (!pkg)
-	pkg = mod;
-    mod->semantic();
-
-    //printf("-Import::load('%s'), pkg = %p\n", toChars(), pkg);
-}
-
-
-void Import::semantic(Scope *sc)
-{
-    //printf("Import::semantic('%s')\n", toChars());
-
-    load(sc);
-
-    if (mod)
-    {
-#if 0
-	if (mod->loc.linnum != 0)
-	{   /* If the line number is not 0, then this is not
-	     * a 'root' module, i.e. it was not specified on the command line.
-	     */
-	    mod->importedFrom = sc->module->importedFrom;
-	    assert(mod->importedFrom);
-	}
-#endif
-
-	/* Default to private importing
-	 */
-	protection = sc->protection;
-	if (!sc->explicitProtection)
-	    protection = PROTprivate;
-
-	if (!isstatic && !aliasId && !names.dim)
-	{
-	    sc->scopesym->importScope(mod, protection);
-	}
-
-	// Modules need a list of each imported module
-	sc->module->aimports.push(mod);
-
-	if (mod->needmoduleinfo)
-	    sc->module->needmoduleinfo = 1;
-
-	sc = sc->push(mod);
-	for (size_t i = 0; i < aliasdecls.dim; i++)
-	{   AliasDeclaration *ad = (AliasDeclaration *)aliasdecls.data[i];
-
-	    //printf("\tImport alias semantic('%s')\n", s->toChars());
-	    if (!mod->search(loc, (Identifier *)names.data[i], 0))
-		error("%s not found", ((Identifier *)names.data[i])->toChars());
-
-	    ad->semantic(sc);
-	    ad->protection = protection;
-	}
-	sc = sc->pop();
-    }
-    //printf("-Import::semantic('%s'), pkg = %p\n", toChars(), pkg);
-}
-
-void Import::semantic2(Scope *sc)
-{
-    //printf("Import::semantic2('%s')\n", toChars());
-    mod->semantic2();
-    if (mod->needmoduleinfo)
-	sc->module->needmoduleinfo = 1;
-}
-
-Dsymbol *Import::toAlias()
-{
-    if (aliasId)
-	return mod;
-    return this;
-}
-
-int Import::addMember(Scope *sc, ScopeDsymbol *sd, int memnum)
-{
-    int result = 0;
-
-    if (names.dim == 0)
-	return Dsymbol::addMember(sc, sd, memnum);
-
-    if (aliasId)
-	result = Dsymbol::addMember(sc, sd, memnum);
-
-    for (size_t i = 0; i < names.dim; i++)
-    {
-	Identifier *name = (Identifier *)names.data[i];
-	Identifier *alias = (Identifier *)aliases.data[i];
-
-	if (!alias)
-	    alias = name;
-
-#if 1
-	TypeIdentifier *tname = new TypeIdentifier(loc, name);
-#else
-	TypeIdentifier *tname = new TypeIdentifier(loc, NULL);
-	if (packages)
-	{
-	    for (size_t j = 0; j < packages->dim; j++)
-	    {   Identifier *pid = (Identifier *)packages->data[j];
-
-		if (!tname->ident)
-		    tname->ident = pid;
-		else
-		    tname->addIdent(pid);
-	    }
-	}
-	if (!tname->ident)
-	    tname->ident = id;
-	else
-	    tname->addIdent(id);
-	tname->addIdent(name);
-#endif
-	AliasDeclaration *ad = new AliasDeclaration(loc, alias, tname);
-	result |= ad->addMember(sc, sd, memnum);
-
-	aliasdecls.push(ad);
-    }
-
-    return result;
-}
-
-Dsymbol *Import::search(Loc loc, Identifier *ident, int flags)
-{
-    //printf("%s.Import::search(ident = '%s', flags = x%x)\n", toChars(), ident->toChars(), flags);
-
-    if (!pkg)
-	load(NULL);
-
-    // Forward it to the package/module
-    return pkg->search(loc, ident, flags);
-}
-
-int Import::overloadInsert(Dsymbol *s)
-{
-    // Allow multiple imports of the same name
-    return s->isImport() != NULL;
-}
-
-void Import::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{
-    if (hgs->hdrgen && id == Id::object)
-	return;		// object is imported by default
-
-    if (isstatic)
-	buf->writestring("static ");
-    buf->writestring("import ");
-    if (aliasId)
-    {
-	buf->printf("%s = ", aliasId->toChars());
-    }
-    if (packages && packages->dim)
-    {
-	for (size_t i = 0; i < packages->dim; i++)
-	{   Identifier *pid = (Identifier *)packages->data[i];
-
-	    buf->printf("%s.", pid->toChars());
-	}
-    }
-    buf->printf("%s;", id->toChars());
-    buf->writenl();
-}
-
+
+// Compiler implementation of the D programming language
+// Copyright (c) 1999-2006 by Digital Mars
+// All Rights Reserved
+// written by Walter Bright
+// http://www.digitalmars.com
+// License for redistribution is by either the Artistic License
+// in artistic.txt, or the GNU General Public License in gnu.txt.
+// See the included readme.txt for details.
+
+#include <stdio.h>
+#include <assert.h>
+
+#include "root.h"
+#include "dsymbol.h"
+#include "import.h"
+#include "identifier.h"
+#include "module.h"
+#include "scope.h"
+#include "hdrgen.h"
+#include "mtype.h"
+#include "declaration.h"
+#include "id.h"
+
+/********************************* Import ****************************/
+
+Import::Import(Loc loc, Array *packages, Identifier *id, Identifier *aliasId,
+	int isstatic)
+    : Dsymbol(id)
+{
+    this->loc = loc;
+    this->packages = packages;
+    this->id = id;
+    this->aliasId = aliasId;
+    this->isstatic = isstatic;
+    protection = PROTundefined;
+    pkg = NULL;
+    mod = NULL;
+
+    if (aliasId)
+	this->ident = aliasId;
+    // Kludge to change Import identifier to first package
+    else if (packages && packages->dim)
+	this->ident = (Identifier *)packages->data[0];
+}
+
+void Import::addAlias(Identifier *name, Identifier *alias)
+{
+    if (isstatic)
+	error("cannot have an import bind list");
+
+    if (!aliasId)
+	this->ident = NULL;	// make it an anonymous import
+
+    names.push(name);
+    aliases.push(alias);
+}
+
+const char *Import::kind()
+{
+    return isstatic ? (char *)"static import" : (char *)"import";
+}
+
+enum PROT Import::prot()
+{
+    return protection;
+}
+
+Dsymbol *Import::syntaxCopy(Dsymbol *s)
+{
+    assert(!s);
+
+    Import *si;
+
+    si = new Import(loc, packages, id, aliasId, isstatic);
+
+    for (size_t i = 0; i < names.dim; i++)
+    {
+	si->addAlias((Identifier *)names.data[i], (Identifier *)aliases.data[i]);
+    }
+
+    return si;
+}
+
+void Import::load(Scope *sc)
+{
+    DsymbolTable *dst;
+    Dsymbol *s;
+
+    //printf("Import::load('%s')\n", toChars());
+
+    // See if existing module
+    dst = Package::resolve(packages, NULL, &pkg);
+
+    s = dst->lookup(id);
+    if (s)
+    {
+	if (s->isModule())
+	    mod = (Module *)s;
+	else
+	    error("package and module have the same name");
+    }
+
+    if (!mod)
+    {
+	// Load module
+	mod = Module::load(loc, packages, id);
+	dst->insert(id, mod);		// id may be different from mod->ident,
+					// if so then insert alias
+	if (!mod->importedFrom)
+	    mod->importedFrom = sc ? sc->module->importedFrom : Module::rootModule;
+    }
+    if (!pkg)
+	pkg = mod;
+    mod->semantic();
+
+    //printf("-Import::load('%s'), pkg = %p\n", toChars(), pkg);
+}
+
+
+void Import::semantic(Scope *sc)
+{
+    //printf("Import::semantic('%s')\n", toChars());
+
+    load(sc);
+
+    if (mod)
+    {
+#if 0
+	if (mod->loc.linnum != 0)
+	{   /* If the line number is not 0, then this is not
+	     * a 'root' module, i.e. it was not specified on the command line.
+	     */
+	    mod->importedFrom = sc->module->importedFrom;
+	    assert(mod->importedFrom);
+	}
+#endif
+
+	/* Default to private importing
+	 */
+	protection = sc->protection;
+	if (!sc->explicitProtection)
+	    protection = PROTprivate;
+
+	if (!isstatic && !aliasId && !names.dim)
+	{
+	    sc->scopesym->importScope(mod, protection);
+	}
+
+	// Modules need a list of each imported module
+	sc->module->aimports.push(mod);
+
+	if (mod->needmoduleinfo)
+	    sc->module->needmoduleinfo = 1;
+
+	sc = sc->push(mod);
+	for (size_t i = 0; i < aliasdecls.dim; i++)
+	{   AliasDeclaration *ad = (AliasDeclaration *)aliasdecls.data[i];
+
+	    //printf("\tImport alias semantic('%s')\n", s->toChars());
+	    if (!mod->search(loc, (Identifier *)names.data[i], 0))
+		error("%s not found", ((Identifier *)names.data[i])->toChars());
+
+	    ad->semantic(sc);
+	    ad->protection = protection;
+	}
+	sc = sc->pop();
+    }
+    //printf("-Import::semantic('%s'), pkg = %p\n", toChars(), pkg);
+}
+
+void Import::semantic2(Scope *sc)
+{
+    //printf("Import::semantic2('%s')\n", toChars());
+    mod->semantic2();
+    if (mod->needmoduleinfo)
+	sc->module->needmoduleinfo = 1;
+}
+
+Dsymbol *Import::toAlias()
+{
+    if (aliasId)
+	return mod;
+    return this;
+}
+
+/*****************************
+ * Add import to sd's symbol table.
+ */
+
+int Import::addMember(Scope *sc, ScopeDsymbol *sd, int memnum)
+{
+    int result = 0;
+
+    if (names.dim == 0)
+	return Dsymbol::addMember(sc, sd, memnum);
+
+    if (aliasId)
+	result = Dsymbol::addMember(sc, sd, memnum);
+
+    /* Instead of adding the import to sd's symbol table,
+     * add each of the alias=name pairs
+     */
+    for (size_t i = 0; i < names.dim; i++)
+    {
+	Identifier *name = (Identifier *)names.data[i];
+	Identifier *alias = (Identifier *)aliases.data[i];
+
+	if (!alias)
+	    alias = name;
+
+	TypeIdentifier *tname = new TypeIdentifier(loc, name);
+	AliasDeclaration *ad = new AliasDeclaration(loc, alias, tname);
+	result |= ad->addMember(sc, sd, memnum);
+
+	aliasdecls.push(ad);
+    }
+
+    return result;
+}
+
+Dsymbol *Import::search(Loc loc, Identifier *ident, int flags)
+{
+    //printf("%s.Import::search(ident = '%s', flags = x%x)\n", toChars(), ident->toChars(), flags);
+
+    if (!pkg)
+	load(NULL);
+
+    // Forward it to the package/module
+    return pkg->search(loc, ident, flags);
+}
+
+int Import::overloadInsert(Dsymbol *s)
+{
+    // Allow multiple imports of the same name
+    return s->isImport() != NULL;
+}
+
+void Import::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    if (hgs->hdrgen && id == Id::object)
+	return;		// object is imported by default
+
+    if (isstatic)
+	buf->writestring("static ");
+    buf->writestring("import ");
+    if (aliasId)
+    {
+	buf->printf("%s = ", aliasId->toChars());
+    }
+    if (packages && packages->dim)
+    {
+	for (size_t i = 0; i < packages->dim; i++)
+	{   Identifier *pid = (Identifier *)packages->data[i];
+
+	    buf->printf("%s.", pid->toChars());
+	}
+    }
+    buf->printf("%s;", id->toChars());
+    buf->writenl();
+}
+
--- a/dmd/lexer.c	Sat Dec 13 06:48:00 2008 +0100
+++ b/dmd/lexer.c	Sat Dec 13 13:15:31 2008 +0100
@@ -2656,10 +2656,13 @@
 
 void Lexer::getDocComment(Token *t, unsigned lineComment)
 {
-    OutBuffer buf;
+    /* ct tells us which kind of comment it is: '/', '*', or '+'
+     */
     unsigned char ct = t->ptr[2];
+
+    /* Start of comment text skips over / * *, / + +, or / / /
+     */
     unsigned char *q = t->ptr + 3;	// start of comment text
-    int linestart = 0;
 
     unsigned char *qend = p;
     if (ct == '*' || ct == '+')
@@ -2684,6 +2687,12 @@
 	}
     }
 
+    /* Comment is now [q .. qend].
+     * Canonicalize it into buf[].
+     */
+    OutBuffer buf;
+    int linestart = 0;
+
     for (; q < qend; q++)
     {
 	unsigned char c = *q;
@@ -2760,11 +2769,14 @@
 }
 
 /********************************************
- * Combine two document comments into one.
+ * Combine two document comments into one,
+ * separated by a newline.
  */
 
 unsigned char *Lexer::combineComments(unsigned char *c1, unsigned char *c2)
 {
+    //printf("Lexer::combineComments('%s', '%s')\n", c1, c2);
+
     unsigned char *c = c2;
 
     if (c1)
@@ -2775,9 +2787,12 @@
 
 	    c = (unsigned char *)mem.malloc(len1 + 1 + len2 + 1);
 	    memcpy(c, c1, len1);
-	    c[len1] = '\n';
-	    memcpy(c + len1 + 1, c2, len2);
-	    c[len1 + 1 + len2] = 0;
+	    if (len1 && c1[len1 - 1] != '\n')
+	    {	c[len1] = '\n';
+		len1++;
+	    }
+	    memcpy(c + len1, c2, len2);
+	    c[len1 + len2] = 0;
 	}
     }
     return c;
@@ -2951,6 +2966,7 @@
     {	"__FILE__",	TOKfile		},
     {	"__LINE__",	TOKline		},
     {	"shared",	TOKshared	},
+    {	"immutable",	TOKimmutable	},
 #endif
 };
 
--- a/dmd/mars.c	Sat Dec 13 06:48:00 2008 +0100
+++ b/dmd/mars.c	Sat Dec 13 13:15:31 2008 +0100
@@ -64,7 +64,7 @@
 
     copyright = "Copyright (c) 1999-2008 by Digital Mars and Tomas Lindquist Olsen";
     written = "written by Walter Bright and Tomas Lindquist Olsen";
-    version = "v1.036";
+    version = "v1.037";
     ldc_version = "0.1";
     global.structalign = 8;
 
--- a/dmd/mtype.c	Sat Dec 13 06:48:00 2008 +0100
+++ b/dmd/mtype.c	Sat Dec 13 13:15:31 2008 +0100
@@ -2485,7 +2485,7 @@
 
 int TypeAArray::isZeroInit()
 {
-    return 1;
+    return TRUE;
 }
 
 int TypeAArray::checkBoolean()
@@ -3994,6 +3994,12 @@
 	    goto Lfwd;
 	e = defaultInit(loc);
     }
+    else if (ident == Id::stringof)
+    {	char *s = toChars();
+	e = new StringExp(loc, s, strlen(s), 'c');
+	Scope sc;
+	e = e->semantic(&sc);
+    }
     else
     {
 	if (!sym->memtype)
--- a/dmd/parse.c	Sat Dec 13 06:48:00 2008 +0100
+++ b/dmd/parse.c	Sat Dec 13 13:15:31 2008 +0100
@@ -386,7 +386,7 @@
 		}
 		ident = token.ident;
 		nextToken();
-		if (token.value == TOKcomma)
+		if (token.value == TOKcomma && peekNext() != TOKrparen)
 		    args = parseArguments();	// pragma(identifier, args...)
 		else
 		    check(TOKrparen);		// pragma(identifier)
@@ -3068,7 +3068,7 @@
 	    }
 	    ident = token.ident;
 	    nextToken();
-	    if (token.value == TOKcomma)
+	    if (token.value == TOKcomma && peekNext() != TOKrparen)
 		args = parseArguments();	// pragma(identifier, args...);
 	    else
 		check(TOKrparen);		// pragma(identifier);
--- a/dmd/root.c	Sat Dec 13 06:48:00 2008 +0100
+++ b/dmd/root.c	Sat Dec 13 13:15:31 2008 +0100
@@ -16,6 +16,7 @@
 
 #if _MSC_VER ||__MINGW32__
 #include <malloc.h>
+#include <string>
 #endif
 
 #if _WIN32
@@ -47,6 +48,7 @@
 }
 #endif
 
+
 /*************************************
  * Convert wchar string to ascii string.
  */
@@ -1606,6 +1608,36 @@
     fill0(nbytes);
 }
 
+
+////////////////////////////////////////////////////////////////
+// The compiler shipped with Visual Studio 2005 (and possible
+// other versions) does not support C99 printf format specfiers
+// such as %z and %j
+#if _MSC_VER
+using std::string;
+using std::wstring;
+
+template<typename S>
+inline void 
+search_and_replace(S& str, const S& what, const S& replacement)
+{
+    assert(!what.empty());
+    size_t pos = str.find(what);
+    while (pos != S::npos) 
+    {
+        str.replace(pos, what.size(), replacement);
+        pos = str.find(what, pos + replacement.size());
+    }
+}
+#define WORKAROUND_C99_SPECIFIERS_BUG(S,tmp,f) \
+    S tmp = f;                                 \
+    search_and_replace(fmt, S("%z"), S("%l")); \
+    search_and_replace(fmt, S("%j"), S("%i")); \
+    f = tmp.c_str();
+#else
+#define WORKAROUND_C99_SPECIFIERS_BUG(S,tmp,f)
+#endif
+
 void OutBuffer::vprintf(const char *format, va_list args)
 {
     char buffer[128];
@@ -1613,10 +1645,7 @@
     unsigned psize;
     int count;
 
-    // On some platforms (i.e. x86_64) va_list is an array and thus passed by
-    // reference. Copy the input list so we can copy it back before retrying.
-    va_list orig_args;
-    va_copy(orig_args, args);
+    WORKAROUND_C99_SPECIFIERS_BUG(string, fmt, format);
 
     p = buffer;
     psize = sizeof(buffer);
@@ -1628,7 +1657,19 @@
 	    break;
 	psize *= 2;
 #elif POSIX
-	count = vsnprintf(p,psize,format,args);
+        va_list va;
+        va_copy(va, args);
+/*
+  The functions vprintf(), vfprintf(), vsprintf(), vsnprintf()
+  are equivalent to the functions printf(), fprintf(), sprintf(),
+  snprintf(), respectively, except that they are called with a
+  va_list instead of a variable number of arguments. These
+  functions do not call the va_end macro. Consequently, the value
+  of ap is undefined after the call. The application should call
+  va_end(ap) itself afterwards.
+ */
+	count = vsnprintf(p,psize,format,va);
+        va_end(va);
 	if (count == -1)
 	    psize *= 2;
 	else if (count >= psize)
@@ -1636,7 +1677,6 @@
 	else
 	    break;
 #endif
-	va_copy(args, orig_args);
 	p = (char *) alloca(psize);	// buffer too small, try again with larger size
     }
     write(p,count);
@@ -1650,6 +1690,8 @@
     unsigned psize;
     int count;
 
+    WORKAROUND_C99_SPECIFIERS_BUG(wstring, fmt, format);
+
     p = buffer;
     psize = sizeof(buffer) / sizeof(buffer[0]);
     for (;;)
@@ -1661,7 +1703,11 @@
 	psize *= 2;
 #endif
 #if POSIX
-	count = vsnwprintf(p,psize,format,args);
+        va_list va;
+        va_copy(va, args);
+	count = vsnwprintf(p,psize,format,va);
+        va_end(va); 
+
 	if (count == -1)
 	    psize *= 2;
 	else if (count >= psize)
--- a/dmd/statement.c	Sat Dec 13 06:48:00 2008 +0100
+++ b/dmd/statement.c	Sat Dec 13 13:15:31 2008 +0100
@@ -26,6 +26,7 @@
 #include "id.h"
 #include "hdrgen.h"
 #include "parse.h"
+#include "template.h"
 
 /******************************** Statement ***************************/
 
@@ -451,10 +452,7 @@
 			body = new CompoundStatement(0, a);
 			body = new ScopeStatement(0, body);
 
-			static int num;
-			char name[3 + sizeof(num) * 3 + 1];
-			sprintf(name, "__o%d", ++num);
-			Identifier *id = Lexer::idPool(name);
+			Identifier *id = Lexer::uniqueId("__o");
 
 			Statement *handler = new ThrowStatement(0, new IdentifierExp(0, id));
 			handler = new CompoundStatement(0, sexception, handler);
@@ -1107,12 +1105,17 @@
 	// Use a default value
 	condition = new IntegerExp(loc, 1, Type::tboolean);
     sc->noctor++;
-    condition = condition->semantic(sc);
-    condition = resolveProperties(sc, condition);
-    condition = condition->optimize(WANTvalue);
-    condition = condition->checkToBoolean();
+    if (condition)
+    {
+	condition = condition->semantic(sc);
+	condition = resolveProperties(sc, condition);
+	condition = condition->optimize(WANTvalue);
+	condition = condition->checkToBoolean();
+    }
     if (increment)
-	increment = increment->semantic(sc);
+    {	increment = increment->semantic(sc);
+	increment = resolveProperties(sc, increment);
+    }
 
     sc->sbreak = this;
     sc->scontinue = this;
@@ -1257,8 +1260,7 @@
     //printf("ForeachStatement::semantic() %p\n", this);
     ScopeDsymbol *sym;
     Statement *s = this;
-    int dim = arguments->dim;
-    int i;
+    size_t dim = arguments->dim;
     TypeAArray *taa = NULL;
 
     Type *tn = NULL;
@@ -1272,6 +1274,7 @@
 
     aggr = aggr->semantic(sc);
     aggr = resolveProperties(sc, aggr);
+    aggr = aggr->optimize(WANTvalue);
     if (!aggr->type)
     {
 	error("invalid foreach aggregate %s", aggr->toChars());
@@ -1387,7 +1390,7 @@
 	return s;
     }
 
-    for (i = 0; i < dim; i++)
+    for (size_t i = 0; i < dim; i++)
     {	Argument *arg = (Argument *)arguments->data[i];
 	if (!arg->type)
 	{
@@ -1419,7 +1422,7 @@
 	    if (tn->ty == Tchar || tn->ty == Twchar || tn->ty == Tdchar)
 	    {	Argument *arg;
 
-		i = (dim == 1) ? 0 : 1;	// index of value
+		int i = (dim == 1) ? 0 : 1;	// index of value
 		arg = (Argument *)arguments->data[i];
 		arg->type = arg->type->semantic(loc, sc);
 		tnv = arg->type->toBasetype();
@@ -1437,7 +1440,7 @@
 		}
 	    }
 
-	    for (i = 0; i < dim; i++)
+	    for (size_t i = 0; i < dim; i++)
 	    {	// Declare args
 		Argument *arg = (Argument *)arguments->data[i];
 		VarDeclaration *var;
@@ -1468,7 +1471,8 @@
 		if (aggr->op == TOKstring)
 		    aggr = aggr->implicitCastTo(sc, value->type->arrayOf());
 		else
-		    error("foreach: %s is not an array of %s", tab->toChars(), value->type->toChars());
+		    error("foreach: %s is not an array of %s",
+			tab->toChars(), value->type->toChars());
 	    }
 
         if (key)
@@ -1505,6 +1509,72 @@
 
 	case Tclass:
 	case Tstruct:
+#if DMDV2
+	{   /* Look for range iteration, i.e. the properties
+	     * .empty, .next, .retreat, .head and .rear
+	     *    foreach (e; range) { ... }
+	     * translates to:
+	     *    for (auto __r = range; !__r.empty; __r.next)
+	     *    {   auto e = __r.head;
+	     *        ...
+	     *    }
+	     */
+	    if (dim != 1)	// only one argument allowed with ranges
+		goto Lapply;
+	    AggregateDeclaration *ad = (tab->ty == Tclass)
+			? (AggregateDeclaration *)((TypeClass  *)tab)->sym
+			: (AggregateDeclaration *)((TypeStruct *)tab)->sym;
+	    Identifier *idhead;
+	    Identifier *idnext;
+	    if (op == TOKforeach)
+	    {	idhead = Id::Fhead;
+		idnext = Id::Fnext;
+	    }
+	    else
+	    {	idhead = Id::Frear;
+		idnext = Id::Fretreat;
+	    }
+	    Dsymbol *shead = search_function(ad, idhead);
+	    if (!shead)
+		goto Lapply;
+
+	    /* Generate a temporary __r and initialize it with the aggregate.
+	     */
+	    Identifier *id = Identifier::generateId("__r");
+	    VarDeclaration *r = new VarDeclaration(loc, NULL, id, new ExpInitializer(loc, aggr));
+	    r->semantic(sc);
+	    Statement *init = new DeclarationStatement(loc, r);
+
+	    // !__r.empty
+	    Expression *e = new VarExp(loc, r);
+	    e = new DotIdExp(loc, e, Id::Fempty);
+	    Expression *condition = new NotExp(loc, e);
+
+	    // __r.next
+	    e = new VarExp(loc, r);
+	    Expression *increment = new DotIdExp(loc, e, idnext);
+
+	    /* Declaration statement for e:
+	     *    auto e = __r.idhead;
+	     */
+	    e = new VarExp(loc, r);
+	    Expression *einit = new DotIdExp(loc, e, idhead);
+	    einit = einit->semantic(sc);
+	    Argument *arg = (Argument *)arguments->data[0];
+	    VarDeclaration *ve = new VarDeclaration(loc, arg->type, arg->ident, new ExpInitializer(loc, einit));
+	    ve->storage_class |= STCforeach;
+	    ve->storage_class |= arg->storageClass & (STCin | STCout | STCref | STCconst | STCinvariant);
+
+	    DeclarationExp *de = new DeclarationExp(loc, ve);
+
+	    Statement *body = new CompoundStatement(loc,
+		new DeclarationStatement(loc, de), this->body);
+
+	    s = new ForStatement(loc, init, condition, increment, body);
+	    s = s->semantic(sc);
+	    break;
+	}
+#endif
 	case Tdelegate:
 	Lapply:
 	{   FuncDeclaration *fdapply;
@@ -1540,7 +1610,7 @@
 	     *	int delegate(ref T arg) { body }
 	     */
 	    args = new Arguments();
-	    for (i = 0; i < dim; i++)
+	    for (size_t i = 0; i < dim; i++)
 	    {	Argument *arg = (Argument *)arguments->data[i];
 
 		arg->type = arg->type->semantic(loc, sc);
@@ -1551,10 +1621,8 @@
 		    // a reference.
 		    VarDeclaration *v;
 		    Initializer *ie;
-		    char applyArg[10 + sizeof(i)*3 + 1];
-
-		    sprintf(applyArg, "__applyArg%d", i);
-		    id = Lexer::idPool(applyArg);
+
+		    id = Lexer::uniqueId("__applyArg", i);
 
 		    ie = new ExpInitializer(0, new IdentifierExp(0, id));
 		    v = new VarDeclaration(0, arg->type, arg->ident, ie);
@@ -2145,6 +2213,11 @@
     }
     else if (ident == Id::lib)
     {
+#if 1
+	/* Should this be allowed?
+	 */
+	error("pragma(lib) not allowed as statement");
+#else
 	if (!args || args->dim != 1)
 	    error("string expected for library name");
 	else
@@ -2166,6 +2239,7 @@
 		mem.free(name);
 	    }
 	}
+#endif
     }
     else
         error("unrecognized pragma(%s)", ident->toChars());
@@ -2454,8 +2528,7 @@
     //printf("CaseStatement::semantic() %s\n", toChars());
     exp = exp->semantic(sc);
     if (sw)
-    {	int i;
-
+    {
 	exp = exp->implicitCastTo(sc, sw->condition->type);
 	exp = exp->optimize(WANTvalue | WANTinterpret);
 	if (exp->op != TOKstring && exp->op != TOKint64)
@@ -2464,7 +2537,7 @@
 	    exp = new IntegerExp(0);
 	}
 
-	for (i = 0; i < sw->cases->dim; i++)
+	for (int i = 0; i < sw->cases->dim; i++)
 	{
 	    CaseStatement *cs = (CaseStatement *)sw->cases->data[i];
 
@@ -2478,7 +2551,7 @@
 	sw->cases->push(this);
 
 	// Resolve any goto case's with no exp to this case statement
-	for (i = 0; i < sw->gotoCases.dim; i++)
+	for (size_t i = 0; i < sw->gotoCases.dim; i++)
 	{
 	    GotoCaseStatement *gcs = (GotoCaseStatement *)sw->gotoCases.data[i];
 
@@ -2875,32 +2948,25 @@
 	    exp->op == TOKstring)
 	{
 	    sc->fes->cases.push(this);
+	    // Construct: return cases.dim+1;
 	    s = new ReturnStatement(0, new IntegerExp(sc->fes->cases.dim + 1));
 	}
 	else if (fd->type->nextOf()->toBasetype() == Type::tvoid)
 	{
-	    Statement *s1;
-	    Statement *s2;
-
 	    s = new ReturnStatement(0, NULL);
 	    sc->fes->cases.push(s);
 
 	    // Construct: { exp; return cases.dim + 1; }
-	    s1 = new ExpStatement(loc, exp);
-	    s2 = new ReturnStatement(0, new IntegerExp(sc->fes->cases.dim + 1));
+	    Statement *s1 = new ExpStatement(loc, exp);
+	    Statement *s2 = new ReturnStatement(0, new IntegerExp(sc->fes->cases.dim + 1));
 	    s = new CompoundStatement(loc, s1, s2);
 	}
 	else
 	{
-	    VarExp *v;
-	    Statement *s1;
-	    Statement *s2;
-
 	    // Construct: return vresult;
 	    if (!fd->vresult)
-	    {	VarDeclaration *v;
-
-		v = new VarDeclaration(loc, tret, Id::result, NULL);
+	    {	// Declare vresult
+		VarDeclaration *v = new VarDeclaration(loc, tret, Id::result, NULL);
 		v->noauto = 1;
 		v->semantic(scx);
 		if (!scx->insert(v))
@@ -2909,16 +2975,14 @@
 		fd->vresult = v;
 	    }
 
-	    v = new VarExp(0, fd->vresult);
-	    s = new ReturnStatement(0, v);
+	    s = new ReturnStatement(0, new VarExp(0, fd->vresult));
 	    sc->fes->cases.push(s);
 
 	    // Construct: { vresult = exp; return cases.dim + 1; }
-	    v = new VarExp(0, fd->vresult);
-	    exp = new AssignExp(loc, v, exp);
+	    exp = new AssignExp(loc, new VarExp(0, fd->vresult), exp);
 	    exp = exp->semantic(sc);
-	    s1 = new ExpStatement(loc, exp);
-	    s2 = new ReturnStatement(0, new IntegerExp(sc->fes->cases.dim + 1));
+	    Statement *s1 = new ExpStatement(loc, exp);
+	    Statement *s2 = new ReturnStatement(0, new IntegerExp(sc->fes->cases.dim + 1));
 	    s = new CompoundStatement(loc, s1, s2);
 	}
 	return s;
@@ -2959,9 +3023,10 @@
 
 	gs->label = fd->returnLabel;
 	if (exp)
-	{   Statement *s;
-
-	    s = new ExpStatement(0, exp);
+	{   /* Replace: return exp;
+	     * with:    exp; goto returnLabel;
+	     */
+	    Statement *s = new ExpStatement(0, exp);
 	    return new CompoundStatement(loc, s, gs);
 	}
 	return gs;
@@ -3739,10 +3804,7 @@
 	     *	sexception:    x = 1;
 	     *	sfinally: if (!x) statement;
 	     */
-	    static int num;
-	    char name[5 + sizeof(num) * 3 + 1];
-	    sprintf(name, "__osf%d", ++num);
-	    Identifier *id = Lexer::idPool(name);
+	    Identifier *id = Lexer::uniqueId("__os");
 
 	    ExpInitializer *ie = new ExpInitializer(loc, new IntegerExp(0));
 	    VarDeclaration *v = new VarDeclaration(loc, Type::tint32, id, ie);