changeset 1526:54b3c1394d62

Merged dmdfe 2.031.
author Robert Clipsham <robert@octarineparrot.com>
date Tue, 07 Jul 2009 02:26:11 +0100
parents d28cd7c45267
children f19adff18813
files dmd2/arrayop.c dmd2/attrib.c dmd2/attrib.h dmd2/cast.c dmd2/class.c dmd2/cond.c dmd2/constfold.c dmd2/declaration.c dmd2/declaration.h dmd2/dsymbol.c dmd2/dsymbol.h dmd2/enum.c dmd2/enum.h dmd2/expression.c dmd2/expression.h dmd2/func.c dmd2/import.c dmd2/import.h dmd2/inifile.c dmd2/init.c dmd2/interpret.c dmd2/lexer.c dmd2/mangle.c dmd2/mars.c dmd2/mars.h dmd2/module.c dmd2/module.h dmd2/mtype.c dmd2/mtype.h dmd2/opover.c dmd2/optimize.c dmd2/parse.c dmd2/root/async.c dmd2/scope.c dmd2/scope.h dmd2/statement.c dmd2/statement.h dmd2/struct.c dmd2/template.c dmd2/template.h
diffstat 40 files changed, 1436 insertions(+), 381 deletions(-) [+]
line wrap: on
line diff
--- 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;
--- 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<StringExp*>(e));
+            decl = new Array;
+            decl->push(pragma);
+        }
+    }
+#endif // TARGET_NET
 // LDC
 #if IN_LLVM
 
--- 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);
--- 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();
+}
+
+
--- 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;
--- 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++)
--- 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)
     {
--- 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 **********************/
--- 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
--- 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;
--- 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);
--- 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;
 }
 
--- 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;
 
--- 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;
 }
 
--- 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();
--- 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 ****************************/
 
--- 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)
+    {
+	/* 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
+	 */
 
-    if (global.params.moduleDeps != NULL) {
-	char fnameBuf[262];		// MAX_PATH+2
+	OutBuffer *ob = global.params.moduleDeps;
 
-	OutBuffer *const ob = global.params.moduleDeps;
-	ob->printf("%s (%s) : ",
-	    sc->module->toPrettyChars(),
-	    escapePath(sc->module->srcfile->toChars(), fnameBuf, sizeof(fnameBuf) / sizeof(*fnameBuf))
-	);
+	ob->writestring(sc->module->toPrettyChars());
+	ob->writestring(" (");
+	escapePath(ob, sc->module->srcfile->toChars());
+	ob->writestring(") : ");
 
-	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(" : ");
+	ProtDeclaration::protectionToCBuffer(ob, sc->protection);
+	if (isstatic)
+	    StorageClassDeclaration::stcToCBuffer(ob, STCstatic);
+	ob->writestring(": ");
 
-	if (this->packages) {
-	    for (size_t i = 0; i < this->packages->dim; i++) {
-		Identifier *pid = (Identifier *)this->packages->data[i];
+	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(')');
 
-	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(',');
-		    }
+	for (size_t i = 0; i < names.dim; i++)
+	{
+	    if (i == 0)
+		ob->writebyte(':');
+	    else
+		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();
 }
 
--- 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);
--- 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	<stdlib.h>
 #include	<ctype.h>
 
+#if _WIN32
+#include <windows.h>
+#endif
+
 #if __APPLE__
 #include	<sys/syslimits.h>
 #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))
 		{
--- 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");
--- 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;
 }
--- 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
--- 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:
--- 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;
--- 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
--- 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;
--- 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
--- 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())
--- 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);
--- 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;
 }
 
--- 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)
--- 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)
 		{
--- 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];
 
--- 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;
--- 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()
--- 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;
 }
 
--- 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
--- 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
--- 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
--- 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);