changeset 1587:def7a1d494fd

Merge DMD 1.051
author Christian Kamm <kamm incasoftware de>
date Fri, 06 Nov 2009 23:58:01 +0100
parents 7f728c52e63c
children 71ad691baeb2
files dmd/aggregate.h dmd/arrayop.c dmd/attrib.c dmd/attrib.h dmd/cast.c dmd/class.c dmd/constfold.c dmd/declaration.c dmd/declaration.h dmd/doc.c dmd/dsymbol.c dmd/dsymbol.h dmd/enum.h dmd/expression.c dmd/expression.h dmd/func.c dmd/idgen.c dmd/import.c dmd/import.h dmd/init.c dmd/inline.c dmd/interpret.c dmd/lexer.c dmd/lexer.h dmd/mangle.c dmd/mars.c dmd/mars.h dmd/module.c dmd/module.h dmd/mtype.c dmd/mtype.h dmd/opover.c dmd/optimize.c dmd/parse.c dmd/root/async.c dmd/root/man.c dmd/root/root.c dmd/scope.c dmd/scope.h dmd/statement.c dmd/statement.h dmd/struct.c dmd/template.c dmd/template.h gen/classes.cpp gen/main.cpp
diffstat 46 files changed, 19573 insertions(+), 16605 deletions(-) [+]
line wrap: on
line diff
--- a/dmd/aggregate.h	Fri Nov 06 21:51:41 2009 +0100
+++ b/dmd/aggregate.h	Fri Nov 06 23:58:01 2009 +0100
@@ -62,13 +62,19 @@
 				// 1: size is correct
 				// 2: cannot determine size; fwd referenced
     int isdeprecated;		// !=0 if deprecated
-    Scope *scope;		// !=NULL means context to use
 
     // Special member functions
     InvariantDeclaration *inv;		// invariant
     NewDeclaration *aggNew;		// allocator
     DeleteDeclaration *aggDelete;	// deallocator
 
+#if DMDV2
+    //CtorDeclaration *ctor;
+    Dsymbol *ctor;			// CtorDeclaration or TemplateDeclaration
+    CtorDeclaration *defaultCtor;	// default constructor
+    Dsymbol *aliasthis;			// forward unresolved lookups to aliasthis
+#endif
+
     FuncDeclarations dtors;	// Array of destructors
     FuncDeclaration *dtor;	// aggregate destructor
 
@@ -88,6 +94,7 @@
     FuncDeclaration *buildDtor(Scope *sc);
 
     void emitComment(Scope *sc);
+    void toJsonBuffer(OutBuffer *buf);
     void toDocBuffer(OutBuffer *buf);
 
     // For access checking
--- a/dmd/arrayop.c	Fri Nov 06 21:51:41 2009 +0100
+++ b/dmd/arrayop.c	Fri Nov 06 23:58:01 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
@@ -31,6 +31,14 @@
 
 Expression *BinExp::arrayOp(Scope *sc)
 {
+    //printf("BinExp::arrayOp() %s\n", toChars());
+
+    if (type->toBasetype()->nextOf()->toBasetype()->ty == Tvoid)
+    {
+        error("Cannot perform array operations on void[] arrays");
+        return new ErrorExp();
+    }
+
     Expressions *arguments = new Expressions();
 
     /* The expression to generate an array operation for is mangled
@@ -288,6 +296,8 @@
         sc->stc = 0;
         sc->linkage = LINKd;
         fd->semantic(sc);
+	    fd->semantic2(sc);
+	    fd->semantic3(sc);
         sc->pop();
 //     }
 //     else
@@ -318,6 +328,17 @@
     arguments->shift(this);
 }
 
+void CastExp::buildArrayIdent(OutBuffer *buf, Expressions *arguments)
+{
+    Type *tb = type->toBasetype();
+    if (tb->ty == Tarray || tb->ty == Tsarray)
+    {
+	e1->buildArrayIdent(buf, arguments);
+    }
+    else
+	Expression::buildArrayIdent(buf, arguments);
+}
+
 void SliceExp::buildArrayIdent(OutBuffer *buf, Expressions *arguments)
 {
     buf->writestring("Slice");
@@ -402,6 +423,17 @@
     return e;
 }
 
+Expression *CastExp::buildArrayLoop(Arguments *fparams)
+{
+    Type *tb = type->toBasetype();
+    if (tb->ty == Tarray || tb->ty == Tsarray)
+    {
+	return e1->buildArrayLoop(fparams);
+    }
+    else
+	return Expression::buildArrayLoop(fparams);
+}
+
 Expression *SliceExp::buildArrayLoop(Arguments *fparams)
 {
     Identifier *id = Identifier::generateId("p", fparams->dim);
@@ -420,6 +452,14 @@
     /* Evaluate assign expressions right to left
      */
     Expression *ex2 = e2->buildArrayLoop(fparams);
+#if DMDV2
+    /* 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());
+#endif
     Expression *ex1 = e1->buildArrayLoop(fparams);
     Argument *param = (Argument *)fparams->data[0];
     param->storageClass = 0;
@@ -488,3 +528,34 @@
 #undef X
 
 
+/***********************************************
+ * Test if operand is a valid array op operand.
+ */
+
+int Expression::isArrayOperand()
+{
+    //printf("Expression::isArrayOperand() %s\n", toChars());
+    if (op == TOKslice)
+	return 1;
+    if (type->toBasetype()->ty == Tarray)
+    {
+	switch (op)
+	{
+	    case TOKadd:
+	    case TOKmin:
+	    case TOKmul:
+	    case TOKdiv:
+	    case TOKmod:
+	    case TOKxor:
+	    case TOKand:
+	    case TOKor:
+	    case TOKneg:
+	    case TOKtilde:
+		return 1;
+
+	    default:
+		break;
+	}
+    }
+    return 0;
+}
--- a/dmd/attrib.c	Fri Nov 06 21:51:41 2009 +0100
+++ b/dmd/attrib.c	Fri Nov 06 23:58:01 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,76 @@
     return m;
 }
 
+void AttribDeclaration::setScopeNewSc(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->setScope(newsc);	// yes, the only difference from semanticNewSc()
+	}
+	if (newsc != sc)
+	{
+	    sc->offset = newsc->offset;
+	    newsc->pop();
+	}
+    }
+}
+
+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);
@@ -302,24 +375,50 @@
     return scd;
 }
 
+void StorageClassDeclaration::setScope(Scope *sc)
+{
+    if (decl)
+    {
+	unsigned scstc = 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))
+	    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;
+
+	setScopeNewSc(sc, scstc, sc->linkage, sc->protection, sc->explicitProtection, sc->structalign);
+    }
+}
+
 void StorageClassDeclaration::semantic(Scope *sc)
 {
     if (decl)
-    {	unsigned stc_save = sc->stc;
+    {
+	unsigned scstc = sc->stc;
 
-	if (stc & (STCauto | STCscope | STCstatic | STCextern))
-	    sc->stc &= ~(STCauto | STCscope | STCstatic | STCextern);
-	sc->stc |= stc;
-	for (unsigned i = 0; i < decl->dim; i++)
-	{
-	    Dsymbol *s = (Dsymbol *)decl->data[i];
+	/* 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;
 
-	    s->semantic(sc);
-	}
-	sc->stc = stc_save;
+	semanticNewSc(sc, scstc, sc->linkage, sc->protection, sc->explicitProtection, sc->structalign);
     }
-    else
-	sc->stc = stc;
 }
 
 void StorageClassDeclaration::stcToCBuffer(OutBuffer *buf, int stc)
@@ -337,17 +436,11 @@
 	{ STCstatic,       TOKstatic },
 	{ STCextern,       TOKextern },
 	{ STCconst,        TOKconst },
-//	{ STCinvariant,    TOKimmutable },
-//	{ STCshared,       TOKshared },
 	{ STCfinal,        TOKfinal },
 	{ STCabstract,     TOKabstract },
 	{ STCsynchronized, TOKsynchronized },
 	{ STCdeprecated,   TOKdeprecated },
 	{ STCoverride,     TOKoverride },
-//	{ STCnothrow,      TOKnothrow },
-//	{ STCpure,         TOKpure },
-//	{ STCref,          TOKref },
-//	{ STCtls,          TOKtls },
     };
 
     for (int i = 0; i < sizeof(table)/sizeof(table[0]); i++)
@@ -384,24 +477,21 @@
     return ld;
 }
 
+void LinkDeclaration::setScope(Scope *sc)
+{
+    //printf("LinkDeclaration::setScope(linkage = %d, decl = %p)\n", linkage, decl);
+    if (decl)
+    {
+	setScopeNewSc(sc, sc->stc, linkage, sc->protection, sc->explicitProtection, sc->structalign);
+    }
+}
+
 void LinkDeclaration::semantic(Scope *sc)
 {
     //printf("LinkDeclaration::semantic(linkage = %d, decl = %p)\n", linkage, decl);
     if (decl)
-    {	enum LINK linkage_save = sc->linkage;
-
-	sc->linkage = linkage;
-	for (unsigned i = 0; i < decl->dim; i++)
-	{
-	    Dsymbol *s = (Dsymbol *)decl->data[i];
-
-	    s->semantic(sc);
-	}
-	sc->linkage = linkage_save;
-    }
-    else
     {
-	sc->linkage = linkage;
+	semanticNewSc(sc, sc->stc, linkage, sc->protection, sc->explicitProtection, sc->structalign);
     }
 }
 
@@ -473,31 +563,48 @@
     return pd;
 }
 
+void ProtDeclaration::setScope(Scope *sc)
+{
+    if (decl)
+    {
+	setScopeNewSc(sc, sc->stc, sc->linkage, protection, 1, sc->structalign);
+    }
+}
+
+void ProtDeclaration::importAll(Scope *sc)
+{
+    Scope *newsc = sc;
+    if (sc->protection != protection ||
+       sc->explicitProtection != 1)
+    {
+       // create new one for changes
+       newsc = new Scope(*sc);
+       newsc->flags &= ~SCOPEfree;
+       newsc->protection = protection;
+       newsc->explicitProtection = 1;
+    }
+
+    for (int i = 0; i < decl->dim; i++)
+    {
+       Dsymbol *s = (Dsymbol *)decl->data[i];
+       s->importAll(newsc);
+    }
+
+    if (newsc != sc)
+       newsc->pop();
+}
+
 void ProtDeclaration::semantic(Scope *sc)
 {
     if (decl)
-    {	enum PROT protection_save = sc->protection;
-	int explicitProtection_save = sc->explicitProtection;
-
-	sc->protection = protection;
-	sc->explicitProtection = 1;
-	for (unsigned i = 0; i < decl->dim; i++)
-	{
-	    Dsymbol *s = (Dsymbol *)decl->data[i];
-
-	    s->semantic(sc);
-	}
-	sc->protection = protection_save;
-	sc->explicitProtection = explicitProtection_save;
-    }
-    else
-    {	sc->protection = protection;
-	sc->explicitProtection = 1;
+    {
+	semanticNewSc(sc, sc->stc, sc->linkage, protection, 1, sc->structalign);
     }
 }
 
-void ProtDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{   const char *p;
+void ProtDeclaration::protectionToCBuffer(OutBuffer *buf, enum PROT protection)
+{
+    const char *p;
 
     switch (protection)
     {
@@ -511,6 +618,12 @@
 	    break;
     }
     buf->writestring(p);
+    buf->writeByte(' ');
+}
+
+void ProtDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    protectionToCBuffer(buf, protection);
     AttribDeclaration::toCBuffer(buf, hgs);
 }
 
@@ -532,35 +645,23 @@
     return ad;
 }
 
+void AlignDeclaration::setScope(Scope *sc)
+{
+    //printf("\tAlignDeclaration::setScope '%s'\n",toChars());
+    if (decl)
+    {
+	setScopeNewSc(sc, sc->stc, sc->linkage, sc->protection, sc->explicitProtection, salign);
+    }
+}
+
 void AlignDeclaration::semantic(Scope *sc)
 {
 // LDC
 // we only support packed structs, as from the spec: align(1) struct Packed { ... }
 // other alignments are simply ignored. my tests show this is what llvm-gcc does too ...
-
-    //printf("\tAlignDeclaration::semantic '%s'\n",toChars());
-    if (decl)
-    {	unsigned salign_save = sc->structalign;
-
-	for (unsigned i = 0; i < decl->dim; i++)
-	{
-	    Dsymbol *s = (Dsymbol *)decl->data[i];
-
-        if (s->isStructDeclaration() && salign == 1)
-        {
-            sc->structalign = salign;
-            s->semantic(sc);
-            sc->structalign = salign_save;
-        }
-        else
-        {
-            s->semantic(sc);
-        }
-	}
-	sc->structalign = salign_save;
+    {
+	semanticNewSc(sc, sc->stc, sc->linkage, sc->protection, sc->explicitProtection, salign);
     }
-    else
-    assert(0 && "what kind of align use triggers this?");
 }
 
 
@@ -577,7 +678,6 @@
 {
     this->loc = loc;
     this->isunion = isunion;
-    this->scope = NULL;
     this->sem = 0;
 }
 
@@ -780,6 +880,39 @@
     return pd;
 }
 
+void PragmaDeclaration::setScope(Scope *sc)
+{
+#if TARGET_NET
+    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));
+
+            assert(sc);
+            pragma->setScope(sc);
+
+            //add to module members
+            assert(sc->module);
+            assert(sc->module->members);
+            sc->module->members->push(pragma);
+        }
+    }
+#endif // TARGET_NET
+}
+
 void PragmaDeclaration::semantic(Scope *sc)
 {   // Should be merged with PragmaStatement
 
@@ -803,10 +936,10 @@
 		if (e->op == TOKstring)
 		{
 		    StringExp *se = (StringExp *)e;
-		    fprintf(stdmsg, "%.*s", (int)se->len, (char*)se->string);
+		    fprintf(stdmsg, "%.*s", (int)se->len, (char *)se->string);
 		}
 		else
-		    error("string expected for message, not '%s'", e->toChars());
+		    fprintf(stdmsg, e->toChars());
 	    }
 	    fprintf(stdmsg, "\n");
 	}
@@ -873,6 +1006,27 @@
 	goto Lnodecl;
     }
 #endif
+#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
@@ -1001,6 +1155,7 @@
 
 #endif // LDC
 
+
     else if (ignoreUnsupportedPragmas)
     {
 	if (global.params.verbose)
@@ -1298,6 +1453,37 @@
     return condition->include(sc, sd) ? decl : elsedecl;
 }
 
+void ConditionalDeclaration::setScope(Scope *sc)
+{
+    Array *d = include(sc, NULL);
+
+    //printf("\tConditionalDeclaration::setScope '%s', d = %p\n",toChars(), d);
+    if (d)
+    {
+       for (unsigned i = 0; i < d->dim; i++)
+       {
+           Dsymbol *s = (Dsymbol *)d->data[i];
+
+           s->setScope(sc);
+       }
+    }
+}
+
+void ConditionalDeclaration::importAll(Scope *sc)
+{
+    Array *d = include(sc, NULL);
+
+    //printf("\tConditionalDeclaration::importAll '%s', d = %p\n",toChars(), d);
+    if (d)
+    {
+       for (unsigned i = 0; i < d->dim; i++)
+       {
+           Dsymbol *s = (Dsymbol *)d->data[i];
+
+           s->importAll(sc);
+       }
+    }
+}
 
 void ConditionalDeclaration::addComment(unsigned char *comment)
 {
@@ -1418,6 +1604,16 @@
 }
 
 
+void StaticIfDeclaration::importAll(Scope *sc)
+{
+    // do not evaluate condition before semantic pass
+}
+
+void StaticIfDeclaration::setScope(Scope *sc)
+{
+    // do not evaluate condition before semantic pass
+}
+
 void StaticIfDeclaration::semantic(Scope *sc)
 {
     Array *d = include(sc, sd);
--- a/dmd/attrib.h	Fri Nov 06 21:51:41 2009 +0100
+++ b/dmd/attrib.h	Fri Nov 06 23:58:01 2009 +0100
@@ -1,183 +1,202 @@
-
-// Compiler implementation of the D programming language
-// Copyright (c) 1999-2007 by Digital Mars
-// All Rights Reserved
-// written by Walter Bright
-// http://www.digitalmars.com
-// License for redistribution is by either the Artistic License
-// in artistic.txt, or the GNU General Public License in gnu.txt.
-// See the included readme.txt for details.
-
-#ifndef DMD_ATTRIB_H
-#define DMD_ATTRIB_H
-
-#ifdef __DMC__
-#pragma once
-#endif /* __DMC__ */
-
-#include "dsymbol.h"
-
-struct Expression;
-struct Statement;
-struct LabelDsymbol;
-struct Initializer;
-struct Module;
-struct Condition;
-#ifdef _DH
-struct HdrGenState;
-#endif
-
-/**************************************************************/
-
-struct AttribDeclaration : Dsymbol
-{
-    Array *decl;	// array of Dsymbol's
-
-    AttribDeclaration(Array *decl);
-    virtual Array *include(Scope *sc, ScopeDsymbol *s);
-    int addMember(Scope *sc, ScopeDsymbol *s, int memnum);
-    void semantic(Scope *sc);
-    void semantic2(Scope *sc);
-    void semantic3(Scope *sc);
-    void inlineScan();
-    void addComment(unsigned char *comment);
-    void emitComment(Scope *sc);
-    const char *kind();
-    int oneMember(Dsymbol **ps);
-    int hasPointers();
-    void checkCtorConstInit();
-    void addLocalClass(ClassDeclarations *);
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-    AttribDeclaration *isAttribDeclaration() { return this; }
-
-#if IN_DMD
-    virtual void toObjFile(int multiobj);			// compile to .obj file
-    int cvMember(unsigned char *p);
-#endif
-
-#if IN_LLVM
-    virtual void codegen(Ir*);
-#endif
-};
-
-struct StorageClassDeclaration: AttribDeclaration
-{
-    unsigned stc;
-
-    StorageClassDeclaration(unsigned stc, Array *decl);
-    Dsymbol *syntaxCopy(Dsymbol *s);
-    void semantic(Scope *sc);
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-
-    static void stcToCBuffer(OutBuffer *buf, int stc);
-};
-
-struct LinkDeclaration : AttribDeclaration
-{
-    enum LINK linkage;
-
-    LinkDeclaration(enum LINK p, Array *decl);
-    Dsymbol *syntaxCopy(Dsymbol *s);
-    void semantic(Scope *sc);
-    void semantic3(Scope *sc);
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-    char *toChars();
-};
-
-struct ProtDeclaration : AttribDeclaration
-{
-    enum PROT protection;
-
-    ProtDeclaration(enum PROT p, Array *decl);
-    Dsymbol *syntaxCopy(Dsymbol *s);
-    void semantic(Scope *sc);
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-};
-
-struct AlignDeclaration : AttribDeclaration
-{
-    unsigned salign;
-
-    AlignDeclaration(Loc loc, unsigned sa, Array *decl);
-    Dsymbol *syntaxCopy(Dsymbol *s);
-    void semantic(Scope *sc);
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-};
-
-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);
-    Dsymbol *syntaxCopy(Dsymbol *s);
-    void semantic(Scope *sc);
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-    const char *kind();
-};
-
-struct PragmaDeclaration : AttribDeclaration
-{
-    Expressions *args;		// array of Expression's
-
-    PragmaDeclaration(Loc loc, Identifier *ident, Expressions *args, Array *decl);
-    Dsymbol *syntaxCopy(Dsymbol *s);
-    void semantic(Scope *sc);
-    int oneMember(Dsymbol **ps);
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-    const char *kind();
-
-#if IN_DMD
-    void toObjFile(int multiobj);			// compile to .obj file
-#endif
-
-#if IN_LLVM
-    void codegen(Ir*);
-#endif
-};
-
-struct ConditionalDeclaration : AttribDeclaration
-{
-    Condition *condition;
-    Array *elsedecl;	// array of Dsymbol's for else block
-
-    ConditionalDeclaration(Condition *condition, Array *decl, Array *elsedecl);
-    Dsymbol *syntaxCopy(Dsymbol *s);
-    int oneMember(Dsymbol **ps);
-    void emitComment(Scope *sc);
-    Array *include(Scope *sc, ScopeDsymbol *s);
-    void addComment(unsigned char *comment);
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-};
-
-struct StaticIfDeclaration : ConditionalDeclaration
-{
-    ScopeDsymbol *sd;
-    int addisdone;
-
-    StaticIfDeclaration(Condition *condition, Array *decl, Array *elsedecl);
-    Dsymbol *syntaxCopy(Dsymbol *s);
-    int addMember(Scope *sc, ScopeDsymbol *s, int memnum);
-    void semantic(Scope *sc);
-    const char *kind();
-};
-
-// Mixin declarations
-
-struct CompileDeclaration : AttribDeclaration
-{
-    Expression *exp;
-
-    ScopeDsymbol *sd;
-    int compiled;
-
-    CompileDeclaration(Loc loc, Expression *exp);
-    Dsymbol *syntaxCopy(Dsymbol *s);
-    int addMember(Scope *sc, ScopeDsymbol *sd, int memnum);
-    void compileIt(Scope *sc);
-    void semantic(Scope *sc);
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-};
-
-#endif /* DMD_ATTRIB_H */
+
+// Compiler implementation of the D programming language
+// Copyright (c) 1999-2009 by Digital Mars
+// All Rights Reserved
+// written by Walter Bright
+// http://www.digitalmars.com
+// License for redistribution is by either the Artistic License
+// in artistic.txt, or the GNU General Public License in gnu.txt.
+// See the included readme.txt for details.
+
+#ifndef DMD_ATTRIB_H
+#define DMD_ATTRIB_H
+
+#ifdef __DMC__
+#pragma once
+#endif /* __DMC__ */
+
+#include "dsymbol.h"
+
+struct Expression;
+struct Statement;
+struct LabelDsymbol;
+struct Initializer;
+struct Module;
+struct Condition;
+#ifdef _DH
+struct HdrGenState;
+#endif
+
+/**************************************************************/
+
+struct AttribDeclaration : Dsymbol
+{
+    Array *decl;	// array of Dsymbol's
+
+    AttribDeclaration(Array *decl);
+    virtual Array *include(Scope *sc, ScopeDsymbol *s);
+    int addMember(Scope *sc, ScopeDsymbol *s, int memnum);
+    void setScopeNewSc(Scope *sc,
+	unsigned newstc, enum LINK linkage, enum PROT protection, int explictProtection,
+	unsigned structalign);
+    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);
+    void inlineScan();
+    void addComment(unsigned char *comment);
+    void emitComment(Scope *sc);
+    const char *kind();
+    int oneMember(Dsymbol **ps);
+    int hasPointers();
+    void checkCtorConstInit();
+    void addLocalClass(ClassDeclarations *);
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+    void toJsonBuffer(OutBuffer *buf);
+    AttribDeclaration *isAttribDeclaration() { return this; }
+
+#if IN_DMD
+    virtual void toObjFile(int multiobj);			// compile to .obj file
+    int cvMember(unsigned char *p);
+#endif
+
+#if IN_LLVM
+    virtual void codegen(Ir*);
+#endif
+};
+
+struct StorageClassDeclaration: AttribDeclaration
+{
+    unsigned stc;
+
+    StorageClassDeclaration(unsigned stc, Array *decl);
+    Dsymbol *syntaxCopy(Dsymbol *s);
+    void setScope(Scope *sc);
+    void semantic(Scope *sc);
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+
+    static void stcToCBuffer(OutBuffer *buf, int stc);
+};
+
+struct LinkDeclaration : AttribDeclaration
+{
+    enum LINK linkage;
+
+    LinkDeclaration(enum LINK p, Array *decl);
+    Dsymbol *syntaxCopy(Dsymbol *s);
+    void setScope(Scope *sc);
+    void semantic(Scope *sc);
+    void semantic3(Scope *sc);
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+    char *toChars();
+};
+
+struct ProtDeclaration : AttribDeclaration
+{
+    enum PROT protection;
+
+    ProtDeclaration(enum PROT p, Array *decl);
+    Dsymbol *syntaxCopy(Dsymbol *s);
+    void importAll(Scope *sc);
+    void setScope(Scope *sc);
+    void semantic(Scope *sc);
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+
+    static void protectionToCBuffer(OutBuffer *buf, enum PROT protection);
+};
+
+struct AlignDeclaration : AttribDeclaration
+{
+    unsigned salign;
+
+    AlignDeclaration(Loc loc, unsigned sa, Array *decl);
+    Dsymbol *syntaxCopy(Dsymbol *s);
+    void setScope(Scope *sc);
+    void semantic(Scope *sc);
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+};
+
+struct AnonDeclaration : AttribDeclaration
+{
+    int isunion;
+    int sem;			// 1 if successful semantic()
+
+    AnonDeclaration(Loc loc, int isunion, Array *decl);
+    Dsymbol *syntaxCopy(Dsymbol *s);
+    void semantic(Scope *sc);
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+    const char *kind();
+};
+
+struct PragmaDeclaration : AttribDeclaration
+{
+    Expressions *args;		// array of Expression's
+
+    PragmaDeclaration(Loc loc, Identifier *ident, Expressions *args, Array *decl);
+    Dsymbol *syntaxCopy(Dsymbol *s);
+    void semantic(Scope *sc);
+    void setScope(Scope *sc);
+    int oneMember(Dsymbol **ps);
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+    const char *kind();
+
+#if IN_DMD
+    void toObjFile(int multiobj);			// compile to .obj file
+#endif
+
+#if IN_LLVM
+    void codegen(Ir*);
+#endif
+};
+
+struct ConditionalDeclaration : AttribDeclaration
+{
+    Condition *condition;
+    Array *elsedecl;	// array of Dsymbol's for else block
+
+    ConditionalDeclaration(Condition *condition, Array *decl, Array *elsedecl);
+    Dsymbol *syntaxCopy(Dsymbol *s);
+    int oneMember(Dsymbol **ps);
+    void emitComment(Scope *sc);
+    Array *include(Scope *sc, ScopeDsymbol *s);
+    void addComment(unsigned char *comment);
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+    void toJsonBuffer(OutBuffer *buf);
+    void importAll(Scope *sc);
+    void setScope(Scope *sc);
+};
+
+struct StaticIfDeclaration : ConditionalDeclaration
+{
+    ScopeDsymbol *sd;
+    int addisdone;
+
+    StaticIfDeclaration(Condition *condition, Array *decl, Array *elsedecl);
+    Dsymbol *syntaxCopy(Dsymbol *s);
+    int addMember(Scope *sc, ScopeDsymbol *s, int memnum);
+    void semantic(Scope *sc);
+    void importAll(Scope *sc);
+    void setScope(Scope *sc);
+    const char *kind();
+};
+
+// Mixin declarations
+
+struct CompileDeclaration : AttribDeclaration
+{
+    Expression *exp;
+
+    ScopeDsymbol *sd;
+    int compiled;
+
+    CompileDeclaration(Loc loc, Expression *exp);
+    Dsymbol *syntaxCopy(Dsymbol *s);
+    int addMember(Scope *sc, ScopeDsymbol *sd, int memnum);
+    void compileIt(Scope *sc);
+    void semantic(Scope *sc);
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+};
+
+#endif /* DMD_ATTRIB_H */
--- a/dmd/cast.c	Fri Nov 06 21:51:41 2009 +0100
+++ b/dmd/cast.c	Fri Nov 06 23:58:01 2009 +0100
@@ -1078,22 +1078,20 @@
 
 Expression *SymOffExp::castTo(Scope *sc, Type *t)
 {
-    Type *tb;
-
 #if 0
     printf("SymOffExp::castTo(this=%s, type=%s, t=%s)\n",
 	toChars(), type->toChars(), t->toChars());
 #endif
     Expression *e = this;
 
-    tb = t->toBasetype();
-    type = type->toBasetype();
-    if (tb != type)
+    Type *tb = t->toBasetype();
+    Type *typeb = type->toBasetype();
+    if (tb != typeb)
     {
 	// Look for pointers to functions where the functions are overloaded.
 	FuncDeclaration *f;
 
-	if (type->ty == Tpointer && type->next->ty == Tfunction &&
+	if (typeb->ty == Tpointer && typeb->next->ty == Tfunction &&
 	    tb->ty == Tpointer && tb->next->ty == Tfunction)
 	{
 	    f = var->isFuncDeclaration();
@@ -1102,15 +1100,47 @@
 		f = f->overloadExactMatch(tb->next, m);
 		if (f)
 		{
-		    e = new SymOffExp(loc, f, 0);
-		    e->type = t;
+#if DMDV2
+		    if (tb->ty == Tdelegate)
+		    {
+			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
+#endif
+		    {
+			e = new SymOffExp(loc, f, 0);
+			e->type = t;
+		    }
+#if DMDV2
+		    f->tookAddressOf++;
+#endif
 		    return e;
 		}
 	    }
 	}
 	e = Expression::castTo(sc, t);
     }
-    e->type = t;
+    else
+    {
+	e->type = t;
+    }
     return e;
 }
 
@@ -1484,13 +1514,13 @@
     {
 	assert(0);
     }
-    else if (e1->op == TOKslice && t1->ty == Tarray &&
+    else if (e1->isArrayOperand() && t1->ty == Tarray &&
 	     e2->implicitConvTo(t1->nextOf()))
     {	// T[] op T
 	e2 = e2->castTo(sc, t1->nextOf());
 	t = t1->nextOf()->arrayOf();
     }
-    else if (e2->op == TOKslice && t2->ty == Tarray &&
+    else if (e2->isArrayOperand() && t2->ty == Tarray &&
 	     e1->implicitConvTo(t2->nextOf()))
     {	// T op T[]
 	e1 = e1->castTo(sc, t2->nextOf());
--- a/dmd/class.c	Fri Nov 06 21:51:41 2009 +0100
+++ b/dmd/class.c	Fri Nov 06 23:58:01 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
@@ -161,6 +161,12 @@
 		    Type::typeinfoinvariant->error("%s", msg);
 		Type::typeinfoinvariant = this;
 	    }
+
+	    if (id == Id::TypeInfo_Shared)
+	    {	if (Type::typeinfoshared)
+		    Type::typeinfoshared->error("%s", msg);
+		Type::typeinfoshared = this;
+	    }
 #endif
 	}
 
@@ -226,19 +232,19 @@
     //{ static int n;  if (++n == 20) *(char*)0=0; }
 
     if (!ident)		// if anonymous class
-    {	char *id = "__anonclass";
+    {	const char *id = "__anonclass";
 
 	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;
@@ -329,13 +335,21 @@
 			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());
 		    scope = scx ? scx : new Scope(*sc);
 		    scope->setNoFree();
+		    if (tc->sym->scope)
+		        tc->sym->scope->module->addDeferredSemantic(tc->sym);
 		    scope->module->addDeferredSemantic(this);
 		    return;
 		}
@@ -389,6 +403,12 @@
 		    error("inherits from duplicate interface %s", b2->base->toChars());
 	    }
 
+	    if (!tc->sym->symtab)
+	    {   // Try to resolve forward reference
+		if (sc->mustsemantic && tc->sym->scope)
+		    tc->sym->semantic(NULL);
+	    }
+
 	    b->base = tc->sym;
 	    if (!b->base->symtab || b->base->scope)
 	    {
@@ -397,6 +417,8 @@
 		//printf("\ttry later, forward reference of base %s\n", baseClass->toChars());
 		scope = scx ? scx : new Scope(*sc);
 		scope->setNoFree();
+		if (tc->sym->scope)
+		    tc->sym->scope->module->addDeferredSemantic(tc->sym);
 		scope->module->addDeferredSemantic(this);
 		return;
 	    }
@@ -500,15 +522,15 @@
 	{   Dsymbol *s = toParent2();
 	    if (s)
 	    {
-		ClassDeclaration *cd = s->isClassDeclaration();
+		AggregateDeclaration *ad = s->isClassDeclaration();
 		FuncDeclaration *fd = s->isFuncDeclaration();
 
 
-		if (cd || fd)
+		if (ad || fd)
 		{   isnested = 1;
 		    Type *t;
-		    if (cd)
-			t = cd->type;
+		    if (ad)
+			t = ad->handle;
 		    else if (fd)
 		    {	AggregateDeclaration *ad = fd->isMember2();
 			if (ad)
@@ -564,7 +586,7 @@
 //	    sc->offset += PTRSIZE;	// room for uplevel context pointer
     }
     else
-    {	sc->offset = PTRSIZE * 2;	// allow room for vptr[] and monitor
+    {	sc->offset = PTRSIZE * 2;	// allow room for __vptr and __monitor
 	alignsize = PTRSIZE;
     }
     structsize = sc->offset;
@@ -703,17 +725,22 @@
 	//buf->writestring(b->base->ident->toChars());
 	b->type->toCBuffer(buf, NULL, hgs);
     }
-    buf->writenl();
-    buf->writeByte('{');
-    buf->writenl();
-    for (int i = 0; i < members->dim; i++)
+    if (members)
     {
-	Dsymbol *s = (Dsymbol *)members->data[i];
+	buf->writenl();
+	buf->writeByte('{');
+	buf->writenl();
+	for (int i = 0; i < members->dim; i++)
+	{
+	    Dsymbol *s = (Dsymbol *)members->data[i];
 
-	buf->writestring("    ");
-	s->toCBuffer(buf, hgs);
+	    buf->writestring("    ");
+	    s->toCBuffer(buf, hgs);
+	}
+	buf->writestring("}");
     }
-    buf->writestring("}");
+    else
+	buf->writeByte(';');
     buf->writenl();
 }
 
@@ -777,13 +804,18 @@
 Dsymbol *ClassDeclaration::search(Loc loc, Identifier *ident, int flags)
 {
     Dsymbol *s;
+    //printf("%s.ClassDeclaration::search('%s')\n", toChars(), ident->toChars());
 
-    //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;
     }
@@ -831,7 +863,7 @@
 
 int ClassDeclaration::isFuncHidden(FuncDeclaration *fd)
 {
-    //printf("ClassDeclaration::isFuncHidden(%s)\n", fd->toChars());
+    //printf("ClassDeclaration::isFuncHidden(class = %s, fd = %s)\n", toChars(), fd->toChars());
     Dsymbol *s = search(0, fd->ident, 4|2);
     if (!s)
     {	//printf("not found\n");
@@ -916,6 +948,13 @@
     return 0;
 }
 
+#if DMDV2
+int ClassDeclaration::isCPPinterface()
+{
+    return 0;
+}
+#endif
+
 
 /****************************************
  */
@@ -1006,10 +1045,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;
@@ -1090,6 +1134,11 @@
 		baseclasses.remove(i);
 		continue;
 	    }
+	    if (!b->base->symtab)
+	    {   // Try to resolve forward reference
+		if (sc->mustsemantic && b->base->scope)
+		    b->base->semantic(NULL);
+	    }
 	    if (!b->base->symtab || b->base->scope || b->base->inuse)
 	    {
 		//error("forward reference of base class %s", baseClass->toChars());
@@ -1262,6 +1311,13 @@
     return com;
 }
 
+#if DMDV2
+int InterfaceDeclaration::isCPPinterface()
+{
+    return cpp;
+}
+#endif
+
 /*******************************************
  */
 
--- a/dmd/constfold.c	Fri Nov 06 21:51:41 2009 +0100
+++ b/dmd/constfold.c	Fri Nov 06 23:58:01 2009 +0100
@@ -74,6 +74,11 @@
     return 1;
 }
 
+int NullExp::isConst()
+{
+    return 1;
+}
+
 int SymOffExp::isConst()
 {
     return 2;
@@ -845,7 +850,7 @@
     {
 	cmp = e1->toComplex() == e2->toComplex();
     }
-    else if (e1->type->isintegral())
+    else if (e1->type->isintegral() || e1->type->toBasetype()->ty == Tpointer)
     {
 	cmp = (e1->toInteger() == e2->toInteger());
     }
@@ -862,9 +867,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)
     {
@@ -1046,11 +1055,12 @@
 	return e1;
 
     Type *tb = to->toBasetype();
-    Type *typeb = type->toBasetype();
 
-    // LDC: ported from D2 to allow char[] ~ char[n] arguments in CTFE
+    /* Allow casting from one string type to another
+     */
     if (e1->op == TOKstring)
     {
+	Type *typeb = type->toBasetype();
 	if (tb->ty == Tarray && typeb->ty == Tarray &&
 	    tb->nextOf()->size() == typeb->nextOf()->size())
 	{
@@ -1069,7 +1079,7 @@
 	{   dinteger_t result;
 	    real_t r = e1->toReal();
 
-	    switch (typeb->ty)
+	    switch (type->toBasetype()->ty)
 	    {
 		case Tint8:	result = (d_int8)r;	break;
 		case Tchar:
--- a/dmd/declaration.c	Fri Nov 06 21:51:41 2009 +0100
+++ b/dmd/declaration.c	Fri Nov 06 23:58:01 2009 +0100
@@ -1,1453 +1,1616 @@
-
-// Compiler implementation of the D programming language
-// Copyright (c) 1999-2009 by Digital Mars
-// All Rights Reserved
-// written by Walter Bright
-// http://www.digitalmars.com
-// License for redistribution is by either the Artistic License
-// in artistic.txt, or the GNU General Public License in gnu.txt.
-// See the included readme.txt for details.
-
-#include <stdio.h>
-#include <assert.h>
-
-#include "init.h"
-#include "declaration.h"
-#include "attrib.h"
-#include "mtype.h"
-#include "template.h"
-#include "scope.h"
-#include "aggregate.h"
-#include "module.h"
-#include "id.h"
-#include "expression.h"
-#include "hdrgen.h"
-
-/********************************* Declaration ****************************/
-
-Declaration::Declaration(Identifier *id)
-    : Dsymbol(id)
-{
-    type = NULL;
-    originalType = NULL;
-    storage_class = STCundefined;
-    protection = PROTundefined;
-    linkage = LINKdefault;
-    inuse = 0;
-}
-
-void Declaration::semantic(Scope *sc)
-{
-}
-
-const char *Declaration::kind()
-{
-    return "declaration";
-}
-
-unsigned Declaration::size(Loc loc)
-{
-    assert(type);
-    return type->size();
-}
-
-int Declaration::isStaticConstructor()
-{
-    return FALSE;
-}
-
-int Declaration::isStaticDestructor()
-{
-    return FALSE;
-}
-
-int Declaration::isDelete()
-{
-    return FALSE;
-}
-
-int Declaration::isDataseg()
-{
-    return FALSE;
-}
-
-int Declaration::isCodeseg()
-{
-    return FALSE;
-}
-
-enum PROT Declaration::prot()
-{
-    return protection;
-}
-
-/*************************************
- * Check to see if declaration can be modified in this context (sc).
- * Issue error if not.
- */
-
-#if DMDV2
-void Declaration::checkModify(Loc loc, Scope *sc, Type *t)
-{
-    if (sc->incontract && isParameter())
-	error(loc, "cannot modify parameter '%s' in contract", toChars());
-
-    if (isCtorinit())
-    {	// It's only modifiable if inside the right constructor
-	Dsymbol *s = sc->func;
-	while (1)
-	{
-	    FuncDeclaration *fd = NULL;
-	    if (s)
-		fd = s->isFuncDeclaration();
-	    if (fd &&
-		((fd->isCtorDeclaration() && storage_class & STCfield) ||
-		 (fd->isStaticCtorDeclaration() && !(storage_class & STCfield))) &&
-		fd->toParent() == toParent()
-	       )
-	    {
-		VarDeclaration *v = isVarDeclaration();
-		assert(v);
-		v->ctorinit = 1;
-		//printf("setting ctorinit\n");
-	    }
-	    else
-	    {
-		if (s)
-		{   s = s->toParent2();
-		    continue;
-		}
-		else
-		{
-		    const char *p = isStatic() ? "static " : "";
-		    error(loc, "can only initialize %sconst %s inside %sconstructor",
-			p, toChars(), p);
-		}
-	    }
-	    break;
-	}
-    }
-    else
-    {
-	VarDeclaration *v = isVarDeclaration();
-	if (v && v->canassign == 0)
-	{
-	    char *p = NULL;
-	    if (isConst())
-		p = "const";
-	    else if (isInvariant())
-		p = "invariant";
-	    else if (storage_class & STCmanifest)
-		p = "manifest constant";
-	    else if (!t->isAssignable())
-		p = "struct with immutable members";
-	    if (p)
-	    {	error(loc, "cannot modify %s", p);
-		halt();
-	    }
-	}
-    }
-}
-#endif
-
-
-/********************************* TupleDeclaration ****************************/
-
-TupleDeclaration::TupleDeclaration(Loc loc, Identifier *id, Objects *objects)
-    : Declaration(id)
-{
-    this->type = NULL;
-    this->objects = objects;
-    this->isexp = 0;
-    this->tupletype = NULL;
-}
-
-Dsymbol *TupleDeclaration::syntaxCopy(Dsymbol *s)
-{
-    assert(0);
-    return NULL;
-}
-
-const char *TupleDeclaration::kind()
-{
-    return "tuple";
-}
-
-Type *TupleDeclaration::getType()
-{
-    /* If this tuple represents a type, return that type
-     */
-
-    //printf("TupleDeclaration::getType() %s\n", toChars());
-    if (isexp)
-	return NULL;
-    if (!tupletype)
-    {
-	/* It's only a type tuple if all the Object's are types
-	 */
-	for (size_t i = 0; i < objects->dim; i++)
-	{   Object *o = (Object *)objects->data[i];
-
-	    if (o->dyncast() != DYNCAST_TYPE)
-	    {
-		//printf("\tnot[%d], %p, %d\n", i, o, o->dyncast());
-		return NULL;
-	    }
-	}
-
-	/* We know it's a type tuple, so build the TypeTuple
-	 */
-	Arguments *args = new Arguments();
-	args->setDim(objects->dim);
-	OutBuffer buf;
-	for (size_t i = 0; i < objects->dim; i++)
-	{   Type *t = (Type *)objects->data[i];
-
-	    //printf("type = %s\n", t->toChars());
-#if 0
-	    buf.printf("_%s_%d", ident->toChars(), i);
-	    char *name = (char *)buf.extractData();
-	    Identifier *id = new Identifier(name, TOKidentifier);
-	    Argument *arg = new Argument(STCin, t, id, NULL);
-#else
-	    Argument *arg = new Argument(STCin, t, NULL, NULL);
-#endif
-	    args->data[i] = (void *)arg;
-	}
-
-	tupletype = new TypeTuple(args);
-    }
-
-    return tupletype;
-}
-
-int TupleDeclaration::needThis()
-{
-    //printf("TupleDeclaration::needThis(%s)\n", toChars());
-    for (size_t i = 0; i < objects->dim; i++)
-    {   Object *o = (Object *)objects->data[i];
-	if (o->dyncast() == DYNCAST_EXPRESSION)
-	{   Expression *e = (Expression *)o;
-	    if (e->op == TOKdsymbol)
-	    {	DsymbolExp *ve = (DsymbolExp *)e;
-		Declaration *d = ve->s->isDeclaration();
-		if (d && d->needThis())
-		{
-		    return 1;
-		}
-	    }
-	}
-    }
-    return 0;
-}
-
-/********************************* TypedefDeclaration ****************************/
-
-TypedefDeclaration::TypedefDeclaration(Loc loc, Identifier *id, Type *basetype, Initializer *init)
-    : Declaration(id)
-{
-    this->type = new TypeTypedef(this);
-    this->basetype = basetype->toBasetype();
-    this->init = init;
-#ifdef _DH
-    this->htype = NULL;
-    this->hbasetype = NULL;
-#endif
-    this->sem = 0;
-    this->loc = loc;
-#if IN_DMD
-    this->sinit = NULL;
-#endif
-}
-
-Dsymbol *TypedefDeclaration::syntaxCopy(Dsymbol *s)
-{
-    Type *basetype = this->basetype->syntaxCopy();
-
-    Initializer *init = NULL;
-    if (this->init)
-	init = this->init->syntaxCopy();
-
-    assert(!s);
-    TypedefDeclaration *st;
-    st = new TypedefDeclaration(loc, ident, basetype, init);
-#ifdef _DH
-    // Syntax copy for header file
-    if (!htype)      // Don't overwrite original
-    {	if (type)    // Make copy for both old and new instances
-	{   htype = type->syntaxCopy();
-	    st->htype = type->syntaxCopy();
-	}
-    }
-    else            // Make copy of original for new instance
-        st->htype = htype->syntaxCopy();
-    if (!hbasetype)
-    {	if (basetype)
-	{   hbasetype = basetype->syntaxCopy();
-	    st->hbasetype = basetype->syntaxCopy();
-	}
-    }
-    else
-        st->hbasetype = hbasetype->syntaxCopy();
-#endif
-    return st;
-}
-
-void TypedefDeclaration::semantic(Scope *sc)
-{
-    //printf("TypedefDeclaration::semantic(%s) sem = %d\n", toChars(), sem);
-    if (sem == 0)
-    {	sem = 1;
-	basetype = basetype->semantic(loc, sc);
-	sem = 2;
-	type = type->semantic(loc, sc);
-	if (sc->parent->isFuncDeclaration() && init)
-	    semantic2(sc);
-	storage_class |= sc->stc & STCdeprecated;
-    }
-    else if (sem == 1)
-    {
-	error("circular definition");
-    }
-}
-
-void TypedefDeclaration::semantic2(Scope *sc)
-{
-    //printf("TypedefDeclaration::semantic2(%s) sem = %d\n", toChars(), sem);
-    if (sem == 2)
-    {	sem = 3;
-	if (init)
-	{
-	    init = init->semantic(sc, basetype);
-
-	    ExpInitializer *ie = init->isExpInitializer();
-	    if (ie)
-	    {
-		if (ie->exp->type == basetype)
-		    ie->exp->type = type;
-	    }
-	}
-    }
-}
-
-const char *TypedefDeclaration::kind()
-{
-    return "typedef";
-}
-
-Type *TypedefDeclaration::getType()
-{
-    return type;
-}
-
-void TypedefDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{
-    buf->writestring("typedef ");
-    basetype->toCBuffer(buf, ident, hgs);
-    if (init)
-    {
-	buf->writestring(" = ");
-	init->toCBuffer(buf, hgs);
-    }
-    buf->writeByte(';');
-    buf->writenl();
-}
-
-/********************************* AliasDeclaration ****************************/
-
-AliasDeclaration::AliasDeclaration(Loc loc, Identifier *id, Type *type)
-    : Declaration(id)
-{
-    //printf("AliasDeclaration(id = '%s', type = %p)\n", id->toChars(), type);
-    //printf("type = '%s'\n", type->toChars());
-    this->loc = loc;
-    this->type = type;
-    this->aliassym = NULL;
-#ifdef _DH
-    this->htype = NULL;
-    this->haliassym = NULL;
-#endif
-    this->overnext = NULL;
-    this->inSemantic = 0;
-    this->importprot = PROTundefined;
-    assert(type);
-}
-
-AliasDeclaration::AliasDeclaration(Loc loc, Identifier *id, Dsymbol *s)
-    : Declaration(id)
-{
-    //printf("AliasDeclaration(id = '%s', s = %p)\n", id->toChars(), s);
-    assert(s != this);
-    this->loc = loc;
-    this->type = NULL;
-    this->aliassym = s;
-#ifdef _DH
-    this->htype = NULL;
-    this->haliassym = NULL;
-#endif
-    this->overnext = NULL;
-    this->inSemantic = 0;
-    assert(s);
-}
-
-Dsymbol *AliasDeclaration::syntaxCopy(Dsymbol *s)
-{
-    //printf("AliasDeclaration::syntaxCopy()\n");
-    assert(!s);
-    AliasDeclaration *sa;
-    if (type)
-	sa = new AliasDeclaration(loc, ident, type->syntaxCopy());
-    else
-	sa = new AliasDeclaration(loc, ident, aliassym->syntaxCopy(NULL));
-#ifdef _DH
-    // Syntax copy for header file
-    if (!htype)	    // Don't overwrite original
-    {	if (type)	// Make copy for both old and new instances
-	{   htype = type->syntaxCopy();
-	    sa->htype = type->syntaxCopy();
-	}
-    }
-    else			// Make copy of original for new instance
-	sa->htype = htype->syntaxCopy();
-    if (!haliassym)
-    {	if (aliassym)
-	{   haliassym = aliassym->syntaxCopy(s);
-	    sa->haliassym = aliassym->syntaxCopy(s);
-	}
-    }
-    else
-	sa->haliassym = haliassym->syntaxCopy(s);
-#endif
-    return sa;
-}
-
-void AliasDeclaration::semantic(Scope *sc)
-{
-    //printf("AliasDeclaration::semantic() %s\n", toChars());
-    if (aliassym)
-    {
-	if (aliassym->isTemplateInstance())
-	    aliassym->semantic(sc);
-	return;
-    }
-    this->inSemantic = 1;
-
-    if (storage_class & STCconst)
-	error("cannot be const");
-
-    storage_class |= sc->stc & STCdeprecated;
-
-    // Given:
-    //	alias foo.bar.abc def;
-    // it is not knowable from the syntax whether this is an alias
-    // for a type or an alias for a symbol. It is up to the semantic()
-    // pass to distinguish.
-    // If it is a type, then type is set and getType() will return that
-    // type. If it is a symbol, then aliassym is set and type is NULL -
-    // toAlias() will return aliasssym.
-
-    Dsymbol *s;
-    Type *t;
-    Expression *e;
-
-    /* This section is needed because resolve() will:
-     *   const x = 3;
-     *   alias x y;
-     * try to alias y to 3.
-     */
-    s = type->toDsymbol(sc);
-    if (s)
-	goto L2;			// it's a symbolic alias
-
-    //printf("alias type is %s\n", type->toChars());
-    type->resolve(loc, sc, &e, &t, &s);
-    if (s)
-    {
-	goto L2;
-    }
-    else if (e)
-    {
-	// Try to convert Expression to Dsymbol
-        if (e->op == TOKvar)
-	{   s = ((VarExp *)e)->var;
-	    goto L2;
-	}
-        else if (e->op == TOKfunction)
-	{   s = ((FuncExp *)e)->fd;
-	    goto L2;
-	}
-        else
-	{   error("cannot alias an expression %s", e->toChars());
-	    t = e->type;
-	}
-    }
-    else if (t)
-    {
-	type = t;
-    }
-    if (overnext)
-	ScopeDsymbol::multiplyDefined(0, this, overnext);
-    this->inSemantic = 0;
-    return;
-
-  L2:
-    //printf("alias is a symbol %s %s\n", s->kind(), s->toChars());
-    type = NULL;
-    VarDeclaration *v = s->isVarDeclaration();
-    if (v && v->linkage == LINKdefault)
-    {
-	error("forward reference of %s", v->toChars());
-	s = NULL;
-    }
-    else
-    {
-	FuncDeclaration *f = s->toAlias()->isFuncDeclaration();
-	if (f)
-	{
-	    if (overnext)
-	    {
-		FuncAliasDeclaration *fa = new FuncAliasDeclaration(f);
-		fa->importprot = importprot;
-		if (!fa->overloadInsert(overnext))
-		    ScopeDsymbol::multiplyDefined(0, f, overnext);
-		overnext = NULL;
-		s = fa;
-		s->parent = sc->parent;
-	    }
-	}
-	if (overnext)
-	    ScopeDsymbol::multiplyDefined(0, s, overnext);
-	if (s == this)
-	{
-	    assert(global.errors);
-	    s = NULL;
-	}
-    }
-    aliassym = s;
-    this->inSemantic = 0;
-}
-
-int AliasDeclaration::overloadInsert(Dsymbol *s)
-{
-    /* Don't know yet what the aliased symbol is, so assume it can
-     * be overloaded and check later for correctness.
-     */
-
-    //printf("AliasDeclaration::overloadInsert('%s')\n", s->toChars());
-    if (overnext == NULL)
-    {	overnext = s;
-	return TRUE;
-    }
-    else
-    {
-	return overnext->overloadInsert(s);
-    }
-}
-
-const char *AliasDeclaration::kind()
-{
-    return "alias";
-}
-
-Type *AliasDeclaration::getType()
-{
-    return type;
-}
-
-Dsymbol *AliasDeclaration::toAlias()
-{
-    //printf("AliasDeclaration::toAlias('%s', this = %p, aliassym = %p, kind = '%s')\n", toChars(), this, aliassym, aliassym ? aliassym->kind() : "");
-    assert(this != aliassym);
-    //static int count; if (++count == 10) *(char*)0=0;
-    if (inSemantic)
-    {	error("recursive alias declaration");
-	aliassym = new TypedefDeclaration(loc, ident, Type::terror, NULL);
-    }
-    Dsymbol *s = aliassym ? aliassym->toAlias() : this;
-    return s;
-}
-
-void AliasDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{
-    buf->writestring("alias ");
-#if 0 && _DH
-    if (hgs->hdrgen)
-    {
-	if (haliassym)
-	{
-	    buf->writestring(haliassym->toChars());
-	    buf->writeByte(' ');
-	    buf->writestring(ident->toChars());
-	}
-	else
-	    htype->toCBuffer(buf, ident, hgs);
-    }
-    else
-#endif
-    {
-	if (aliassym)
-	{
-	    buf->writestring(aliassym->toChars());
-	    buf->writeByte(' ');
-	    buf->writestring(ident->toChars());
-	}
-	else
-	    type->toCBuffer(buf, ident, hgs);
-    }
-    buf->writeByte(';');
-    buf->writenl();
-}
-
-/********************************* VarDeclaration ****************************/
-
-VarDeclaration::VarDeclaration(Loc loc, Type *type, Identifier *id, Initializer *init)
-    : Declaration(id)
-{
-    //printf("VarDeclaration('%s')\n", id->toChars());
-#ifdef DEBUG
-    if (!type && !init)
-    {	printf("VarDeclaration('%s')\n", id->toChars());
-	//*(char*)0=0;
-    }
-#endif
-    assert(type || init);
-    this->type = type;
-    this->init = init;
-#ifdef _DH
-    this->htype = NULL;
-    this->hinit = NULL;
-#endif
-    this->loc = loc;
-    offset = 0;
-    noscope = 0;
-    nestedref = 0;
-    ctorinit = 0;
-    aliassym = NULL;
-    onstack = 0;
-    canassign = 0;
-    value = NULL;
-
-#if IN_LLVM
-    aggrIndex = 0;
-
-    // LDC
-    anonDecl = NULL;
-    offset2 = 0;
-
-    nakedUse = false;
-
-    availableExternally = true; // assume this unless proven otherwise
-#endif
-}
-
-Dsymbol *VarDeclaration::syntaxCopy(Dsymbol *s)
-{
-    //printf("VarDeclaration::syntaxCopy(%s)\n", toChars());
-
-    VarDeclaration *sv;
-    if (s)
-    {	sv = (VarDeclaration *)s;
-    }
-    else
-    {
-	Initializer *init = NULL;
-	if (this->init)
-	{   init = this->init->syntaxCopy();
-	    //init->isExpInitializer()->exp->print();
-	    //init->isExpInitializer()->exp->dump(0);
-	}
-
-	sv = new VarDeclaration(loc, type ? type->syntaxCopy() : NULL, ident, init);
-	sv->storage_class = storage_class;
-    }
-#ifdef _DH
-    // Syntax copy for header file
-    if (!htype)      // Don't overwrite original
-    {	if (type)    // Make copy for both old and new instances
-	{   htype = type->syntaxCopy();
-	    sv->htype = type->syntaxCopy();
-	}
-    }
-    else            // Make copy of original for new instance
-        sv->htype = htype->syntaxCopy();
-    if (!hinit)
-    {	if (init)
-	{   hinit = init->syntaxCopy();
-	    sv->hinit = init->syntaxCopy();
-	}
-    }
-    else
-        sv->hinit = hinit->syntaxCopy();
-#endif
-    return sv;
-}
-
-void VarDeclaration::semantic(Scope *sc)
-{
-    //printf("VarDeclaration::semantic('%s', parent = '%s')\n", toChars(), sc->parent->toChars());
-    //printf(" type = %s\n", type ? type->toChars() : "null");
-    //printf(" stc = x%x\n", sc->stc);
-    //printf(" storage_class = x%x\n", storage_class);
-    //printf("linkage = %d\n", sc->linkage);
-    //if (strcmp(toChars(), "mul") == 0) halt();
-
-    storage_class |= sc->stc;
-    if (storage_class & STCextern && init)
-	error("extern symbols cannot have initializers");
-
-    /* If auto type inference, do the inference
-     */
-    int inferred = 0;
-    if (!type)
-    {	inuse++;
-	type = init->inferType(sc);
-	inuse--;
-	inferred = 1;
-
-	/* This is a kludge to support the existing syntax for RAII
-	 * declarations.
-	 */
-	storage_class &= ~STCauto;
-	originalType = type;
-    }
-    else
-    {	if (!originalType)
-	    originalType = type;
-	type = type->semantic(loc, sc);
-    }
-    //printf(" semantic type = %s\n", type ? type->toChars() : "null");
-
-    type->checkDeprecated(loc, sc);
-    linkage = sc->linkage;
-    this->parent = sc->parent;
-    //printf("this = %p, parent = %p, '%s'\n", this, parent, parent->toChars());
-    protection = sc->protection;
-    //printf("sc->stc = %x\n", sc->stc);
-    //printf("storage_class = x%x\n", storage_class);
-
-    Dsymbol *parent = toParent();
-    FuncDeclaration *fd = parent->isFuncDeclaration();
-
-    Type *tb = type->toBasetype();
-    if (tb->ty == Tvoid && !(storage_class & STClazy))
-    {	error("voids have no value");
-	type = Type::terror;
-	tb = type;
-    }
-    if (tb->ty == Tfunction)
-    {	error("cannot be declared to be a function");
-	type = Type::terror;
-	tb = type;
-    }
-    if (tb->ty == Tstruct)
-    {	TypeStruct *ts = (TypeStruct *)tb;
-
-	if (!ts->sym->members)
-	{
-	    error("no definition of struct %s", ts->toChars());
-	}
-    }
-    if ((storage_class & STCauto) && !inferred)
-	error("both auto and explicit type given");
-
-    if (tb->ty == Ttuple)
-    {   /* Instead, declare variables for each of the tuple elements
-	 * and add those.
-	 */
-	TypeTuple *tt = (TypeTuple *)tb;
-	size_t nelems = Argument::dim(tt->arguments);
-	Objects *exps = new Objects();
-	exps->setDim(nelems);
-	Expression *ie = init ? init->toExpression() : NULL;
-
-	for (size_t i = 0; i < nelems; i++)
-	{   Argument *arg = Argument::getNth(tt->arguments, i);
-
-	    OutBuffer buf;
-	    buf.printf("_%s_field_%zu", ident->toChars(), i);
-	    buf.writeByte(0);
-	    char *name = (char *)buf.extractData();
-	    Identifier *id = new Identifier(name, TOKidentifier);
-
-	    Expression *einit = ie;
-	    if (ie && ie->op == TOKtuple)
-	    {	einit = (Expression *)((TupleExp *)ie)->exps->data[i];
-	    }
-	    Initializer *ti = init;
-	    if (einit)
-	    {	ti = new ExpInitializer(einit->loc, einit);
-	    }
-
-	    VarDeclaration *v = new VarDeclaration(loc, arg->type, id, ti);
-	    //printf("declaring field %s of type %s\n", v->toChars(), v->type->toChars());
-	    v->semantic(sc);
-            
-/*
-// removed for LDC since TupleDeclaration::toObj already creates the fields;
-// adding them to the scope again leads to duplicates
-	    if (sc->scopesym)
-	    {	//printf("adding %s to %s\n", v->toChars(), sc->scopesym->toChars());
-		if (sc->scopesym->members)
-		    sc->scopesym->members->push(v);
-	    }
-*/
-	    Expression *e = new DsymbolExp(loc, v);
-	    exps->data[i] = e;
-	}
-	TupleDeclaration *v2 = new TupleDeclaration(loc, ident, exps);
-	v2->isexp = 1;
-	aliassym = v2;
-	return;
-    }
-
-    if (storage_class & STCconst && !init && !fd)
-	// Initialize by constructor only
-	storage_class = (storage_class & ~STCconst) | STCctorinit;
-
-    if (isConst())
-    {
-    }
-    else if (isStatic())
-    {
-    }
-    else if (isSynchronized())
-    {
-	error("variable %s cannot be synchronized", toChars());
-    }
-    else if (isOverride())
-    {
-	error("override cannot be applied to variable");
-    }
-    else if (isAbstract())
-    {
-	error("abstract cannot be applied to variable");
-    }
-    else if (storage_class & STCtemplateparameter)
-    {
-    }
-    else
-    {
-	AggregateDeclaration *aad = sc->anonAgg;
-	if (!aad)
-	    aad = parent->isAggregateDeclaration();
-	if (aad)
-	{
-	    aad->addField(sc, this);
-	}
-
-	InterfaceDeclaration *id = parent->isInterfaceDeclaration();
-	if (id)
-	{
-	    error("field not allowed in interface");
-	}
-
-	/* Templates cannot add fields to aggregates
-	 */
-	TemplateInstance *ti = parent->isTemplateInstance();
-	if (ti)
-	{
-	    // Take care of nested templates
-	    while (1)
-	    {
-		TemplateInstance *ti2 = ti->tempdecl->parent->isTemplateInstance();
-		if (!ti2)
-		    break;
-		ti = ti2;
-	    }
-
-	    // If it's a member template
-	    AggregateDeclaration *ad = ti->tempdecl->isMember();
-	    if (ad && storage_class != STCundefined)
-	    {
-		error("cannot use template to add field to aggregate '%s'", ad->toChars());
-	    }
-	}
-    }
-
-    if (type->isscope() && !noscope)
-    {
-	if (storage_class & (STCfield | STCout | STCref | STCstatic) || !fd)
-	{
-	    error("globals, statics, fields, ref and out parameters cannot be scope");
-	}
-
-	if (!(storage_class & STCscope))
-	{
-	    if (!(storage_class & STCparameter) && ident != Id::withSym)
-		error("reference to scope class must be scope");
-	}
-    }
-
-    if (!init && !sc->inunion && !isStatic() && !isConst() && fd &&
-	!(storage_class & (STCfield | STCin | STCforeach)) &&
-	type->size() != 0)
-    {
-	// Provide a default initializer
-	//printf("Providing default initializer for '%s'\n", toChars());
-	if (type->ty == Tstruct &&
-	    ((TypeStruct *)type)->sym->zeroInit == 1)
-	{   /* If a struct is all zeros, as a special case
-	     * set it's initializer to the integer 0.
-	     * In AssignExp::toElem(), we check for this and issue
-	     * a memset() to initialize the struct.
-	     * Must do same check in interpreter.
-	     */
-	    Expression *e = new IntegerExp(loc, 0, Type::tint32);
-	    Expression *e1;
-	    e1 = new VarExp(loc, this);
-	    e = new AssignExp(loc, e1, e);
-	    e->type = e1->type;
-	    init = new ExpInitializer(loc, e/*->type->defaultInit()*/);
-	    return;
-	}
-	else if (type->ty == Ttypedef)
-	{   TypeTypedef *td = (TypeTypedef *)type;
-	    if (td->sym->init)
-	    {	init = td->sym->init;
-		ExpInitializer *ie = init->isExpInitializer();
-		if (ie)
-		    // Make copy so we can modify it
-		    init = new ExpInitializer(ie->loc, ie->exp);
-	    }
-	    else
-		init = getExpInitializer();
-	}
-	else
-	{
-	    init = getExpInitializer();
-	}
-    }
-
-    if (init)
-    {
-	sc = sc->push();
-	sc->stc &= ~(STCconst | STCinvariant | STCpure);
-
-	ArrayInitializer *ai = init->isArrayInitializer();
-	if (ai && tb->ty == Taarray)
-	{
-	    init = ai->toAssocArrayInitializer();
-	}
-
-	StructInitializer *si = init->isStructInitializer();
-	ExpInitializer *ei = init->isExpInitializer();
-
-	// See if we can allocate on the stack
-	if (ei && isScope() && ei->exp->op == TOKnew)
-	{   NewExp *ne = (NewExp *)ei->exp;
-	    if (!(ne->newargs && ne->newargs->dim))
-	    {	ne->onstack = 1;
-		onstack = 1;
-		if (type->isBaseOf(ne->newtype->semantic(loc, sc), NULL))
-		    onstack = 2;
-	    }
-	}
-
-	// If inside function, there is no semantic3() call
-	if (sc->func)
-	{
-	    // If local variable, use AssignExp to handle all the various
-	    // possibilities.
-	    if (fd && !isStatic() && !isConst() && !init->isVoidInitializer())
-	    {
-		//printf("fd = '%s', var = '%s'\n", fd->toChars(), toChars());
-		if (!ei)
-		{
-		    Expression *e = init->toExpression();
-		    if (!e)
-		    {
-			init = init->semantic(sc, type);
-			e = init->toExpression();
-			if (!e)
-			{   error("is not a static and cannot have static initializer");
-			    return;
-			}
-		    }
-		    ei = new ExpInitializer(init->loc, e);
-		    init = ei;
-		}
-
-		Expression *e1 = new VarExp(loc, this);
-
-		Type *t = type->toBasetype();
-		if (t->ty == Tsarray)
-		{
-		    ei->exp = ei->exp->semantic(sc);
-		    if (!ei->exp->implicitConvTo(type))
-		    {
-			int dim = ((TypeSArray *)t)->dim->toInteger();
-			// If multidimensional static array, treat as one large array
-			while (1)
-			{
-			    t = t->nextOf()->toBasetype();
-			    if (t->ty != Tsarray)
-				break;
-			    dim *= ((TypeSArray *)t)->dim->toInteger();
-			    e1->type = new TypeSArray(t->nextOf(), new IntegerExp(0, dim, Type::tindex));
-			}
-		    }
-		    e1 = new SliceExp(loc, e1, NULL, NULL);
-		}
-		else if (t->ty == Tstruct)
-		{
-		    ei->exp = ei->exp->semantic(sc);
-		    if (!ei->exp->implicitConvTo(type))
-			ei->exp = new CastExp(loc, ei->exp, type);
-		}
-		ei->exp = new AssignExp(loc, e1, ei->exp);
-		ei->exp->op = TOKconstruct;
-		canassign++;
-		ei->exp = ei->exp->semantic(sc);
-		canassign--;
-		ei->exp->optimize(WANTvalue);
-	    }
-	    else
-	    {
-		init = init->semantic(sc, type);
-		if (fd && isConst() && !isStatic())
-		{   // Make it static
-		    storage_class |= STCstatic;
-		}
-	    }
-	}
-	else if (isConst() || isFinal())
-	{
-	    /* Because we may need the results of a const declaration in a
-	     * subsequent type, such as an array dimension, before semantic2()
-	     * gets ordinarily run, try to run semantic2() now.
-	     * Ignore failure.
-	     */
-
-	    if (!global.errors && !inferred)
-	    {
-		unsigned errors = global.errors;
-		global.gag++;
-		//printf("+gag\n");
-		Expression *e;
-		Initializer *i2 = init;
-		inuse++;
-		if (ei)
-		{
-		    e = ei->exp->syntaxCopy();
-		    e = e->semantic(sc);
-		    e = e->implicitCastTo(sc, type);
-		}
-		else if (si || ai)
-		{   i2 = init->syntaxCopy();
-		    i2 = i2->semantic(sc, type);
-		}
-		inuse--;
-		global.gag--;
-		//printf("-gag\n");
-		if (errors != global.errors)	// if errors happened
-		{
-		    if (global.gag == 0)
-			global.errors = errors;	// act as if nothing happened
-		}
-		else if (ei)
-		{
-		    e = e->optimize(WANTvalue | WANTinterpret);
-		    if (e->op == TOKint64 || e->op == TOKstring)
-		    {
-			ei->exp = e;		// no errors, keep result
-		    }
-		}
-		else
-		    init = i2;		// no errors, keep result
-	    }
-	}
-	sc = sc->pop();
-    }
-}
-
-ExpInitializer *VarDeclaration::getExpInitializer()
-{
-    ExpInitializer *ei;
-
-    if (init)
-	ei = init->isExpInitializer();
-    else
-    {
-	Expression *e = type->defaultInit(loc);
-	if (e)
-	    ei = new ExpInitializer(loc, e);
-	else
-	    ei = NULL;
-    }
-    return ei;
-}
-
-void VarDeclaration::semantic2(Scope *sc)
-{
-    //printf("VarDeclaration::semantic2('%s')\n", toChars());
-    if (init && !toParent()->isFuncDeclaration())
-    {	inuse++;
-#if 0
-	ExpInitializer *ei = init->isExpInitializer();
-	if (ei)
-	{
-	    ei->exp->dump(0);
-	    printf("type = %p\n", ei->exp->type);
-	}
-#endif
-	init = init->semantic(sc, type);
-	inuse--;
-    }
-}
-
-void VarDeclaration::semantic3(Scope *sc)
-{
-    // LDC
-    if (!global.params.useAvailableExternally)
-        availableExternally = false;
-
-    // Preserve call chain
-    Declaration::semantic3(sc);
-}
-
-const char *VarDeclaration::kind()
-{
-    return "variable";
-}
-
-Dsymbol *VarDeclaration::toAlias()
-{
-    //printf("VarDeclaration::toAlias('%s', this = %p, aliassym = %p)\n", toChars(), this, aliassym);
-    assert(this != aliassym);
-    Dsymbol *s = aliassym ? aliassym->toAlias() : this;
-    return s;
-}
-
-void VarDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{
-    StorageClassDeclaration::stcToCBuffer(buf, storage_class);
-
-    /* If changing, be sure and fix CompoundDeclarationStatement::toCBuffer()
-     * too.
-     */
-    if (type)
-	type->toCBuffer(buf, ident, hgs);
-    else
-	buf->writestring(ident->toChars());
-    if (init)
-    {	buf->writestring(" = ");
-	init->toCBuffer(buf, hgs);
-    }
-    buf->writeByte(';');
-    buf->writenl();
-}
-
-int VarDeclaration::needThis()
-{
-    //printf("VarDeclaration::needThis(%s, x%x)\n", toChars(), storage_class);
-    return storage_class & STCfield;
-}
-
-int VarDeclaration::isImportedSymbol()
-{
-    if (protection == PROTexport && !init && (isStatic() || isConst() || parent->isModule()))
-	return TRUE;
-    return FALSE;
-}
-
-void VarDeclaration::checkCtorConstInit()
-{
-    if (ctorinit == 0 && isCtorinit() && !(storage_class & STCfield))
-	error("missing initializer in static constructor for const variable");
-}
-
-/************************************
- * Check to see if this variable is actually in an enclosing function
- * rather than the current one.
- */
-
-void VarDeclaration::checkNestedReference(Scope *sc, Loc loc)
-{
-    //printf("VarDeclaration::checkNestedReference() %s\n", toChars());
-    if (parent && !isDataseg() && parent != sc->parent)
-    {
-	// The function that this variable is in
-	FuncDeclaration *fdv = toParent()->isFuncDeclaration();
-	// The current function
-	FuncDeclaration *fdthis = sc->parent->isFuncDeclaration();
-
-	if (fdv && fdthis)
-	{
-	    if (loc.filename)
-		fdthis->getLevel(loc, fdv);
-	    nestedref = 1;
-	    fdv->nestedFrameRef = 1;
-#if IN_LLVM
-#if DMDV1
-        fdv->nestedVars.insert(this);
-#endif
-#endif
-	    //printf("var %s in function %s is nested ref\n", toChars(), fdv->toChars());
-	}
-    }
-}
-
-/*******************************
- * Does symbol go into data segment?
- * Includes extern variables.
- */
-
-int VarDeclaration::isDataseg()
-{
-#if 0
-    printf("VarDeclaration::isDataseg(%p, '%s')\n", this, toChars());
-    printf("%x, %p, %p\n", storage_class & (STCstatic | STCconst), parent->isModule(), parent->isTemplateInstance());
-    printf("parent = '%s'\n", parent->toChars());
-#endif
-    Dsymbol *parent = this->toParent();
-    if (!parent && !(storage_class & (STCstatic | STCconst)))
-    {	error("forward referenced");
-	type = Type::terror;
-	return 0;
-    }
-    return (storage_class & (STCstatic | STCconst) ||
-	   parent->isModule() ||
-	   parent->isTemplateInstance());
-}
-
-int VarDeclaration::hasPointers()
-{
-    return (!isDataseg() && type->hasPointers());
-}
-
-int VarDeclaration::isSameAsInitializer()
-{
-    if (init && init->isExpInitializer() && 
-        init->isExpInitializer()->exp->op == TOKstructliteral)
-        return 0;
-    return isConst();
-}
-
-/******************************************
- * If a variable has an scope destructor call, return call for it.
- * Otherwise, return NULL.
- */
-
-Expression *VarDeclaration::callScopeDtor()
-{   Expression *e = NULL;
-
-    //printf("VarDeclaration::callScopeDtor() %s\n", toChars());
-    if (storage_class & STCscope && !noscope)
-    {
-	for (ClassDeclaration *cd = type->isClassHandle();
-	     cd;
-	     cd = cd->baseClass)
-	{
-	    /* We can do better if there's a way with onstack
-	     * classes to determine if there's no way the monitor
-	     * could be set.
-	     */
-	    //if (cd->isInterfaceDeclaration())
-		//error("interface %s cannot be scope", cd->toChars());
-	    if (1 || onstack || cd->dtors.dim)	// if any destructors
-	    {
-		// delete this;
-		Expression *ec;
-
-		ec = new VarExp(loc, this);
-		e = new DeleteExp(loc, ec);
-		e->type = Type::tvoid;
-		break;
-	    }
-	}
-    }
-    return e;
-}
-
-
-/********************************* ClassInfoDeclaration ****************************/
-
-ClassInfoDeclaration::ClassInfoDeclaration(ClassDeclaration *cd)
-    : VarDeclaration(0, ClassDeclaration::classinfo->type, cd->ident, NULL)
-{
-    this->cd = cd;
-    storage_class = STCstatic;
-}
-
-Dsymbol *ClassInfoDeclaration::syntaxCopy(Dsymbol *s)
-{
-    assert(0);		// should never be produced by syntax
-    return NULL;
-}
-
-void ClassInfoDeclaration::semantic(Scope *sc)
-{
-}
-
-/********************************* ModuleInfoDeclaration ****************************/
-
-ModuleInfoDeclaration::ModuleInfoDeclaration(Module *mod)
-    : VarDeclaration(0, Module::moduleinfo->type, mod->ident, NULL)
-{
-    this->mod = mod;
-    storage_class = STCstatic;
-}
-
-Dsymbol *ModuleInfoDeclaration::syntaxCopy(Dsymbol *s)
-{
-    assert(0);		// should never be produced by syntax
-    return NULL;
-}
-
-void ModuleInfoDeclaration::semantic(Scope *sc)
-{
-}
-
-/********************************* TypeInfoDeclaration ****************************/
-
-TypeInfoDeclaration::TypeInfoDeclaration(Type *tinfo, int internal)
-    : VarDeclaration(0, Type::typeinfo->type, tinfo->getTypeInfoIdent(internal), NULL)
-{
-    this->tinfo = tinfo;
-    storage_class = STCstatic;
-    protection = PROTpublic;
-    linkage = LINKc;
-}
-
-Dsymbol *TypeInfoDeclaration::syntaxCopy(Dsymbol *s)
-{
-    assert(0);		// should never be produced by syntax
-    return NULL;
-}
-
-void TypeInfoDeclaration::semantic(Scope *sc)
-{
-    assert(linkage == LINKc);
-    // LDC
-    if (!global.params.useAvailableExternally)
-        availableExternally = false;
-}
-
-/***************************** TypeInfoConstDeclaration **********************/
-
-#if DMDV2
-TypeInfoConstDeclaration::TypeInfoConstDeclaration(Type *tinfo)
-    : TypeInfoDeclaration(tinfo, 0)
-{
-}
-#endif
-
-/***************************** TypeInfoInvariantDeclaration **********************/
-
-#if DMDV2
-TypeInfoInvariantDeclaration::TypeInfoInvariantDeclaration(Type *tinfo)
-    : TypeInfoDeclaration(tinfo, 0)
-{
-}
-#endif
-
-/***************************** TypeInfoStructDeclaration **********************/
-
-TypeInfoStructDeclaration::TypeInfoStructDeclaration(Type *tinfo)
-    : TypeInfoDeclaration(tinfo, 0)
-{
-}
-
-/***************************** TypeInfoClassDeclaration ***********************/
-
-TypeInfoClassDeclaration::TypeInfoClassDeclaration(Type *tinfo)
-    : TypeInfoDeclaration(tinfo, 0)
-{
-}
-
-/***************************** TypeInfoInterfaceDeclaration *******************/
-
-TypeInfoInterfaceDeclaration::TypeInfoInterfaceDeclaration(Type *tinfo)
-    : TypeInfoDeclaration(tinfo, 0)
-{
-}
-
-/***************************** TypeInfoTypedefDeclaration *********************/
-
-TypeInfoTypedefDeclaration::TypeInfoTypedefDeclaration(Type *tinfo)
-    : TypeInfoDeclaration(tinfo, 0)
-{
-}
-
-/***************************** TypeInfoPointerDeclaration *********************/
-
-TypeInfoPointerDeclaration::TypeInfoPointerDeclaration(Type *tinfo)
-    : TypeInfoDeclaration(tinfo, 0)
-{
-}
-
-/***************************** TypeInfoArrayDeclaration ***********************/
-
-TypeInfoArrayDeclaration::TypeInfoArrayDeclaration(Type *tinfo)
-    : TypeInfoDeclaration(tinfo, 0)
-{
-}
-
-/***************************** TypeInfoStaticArrayDeclaration *****************/
-
-TypeInfoStaticArrayDeclaration::TypeInfoStaticArrayDeclaration(Type *tinfo)
-    : TypeInfoDeclaration(tinfo, 0)
-{
-}
-
-/***************************** TypeInfoAssociativeArrayDeclaration ************/
-
-TypeInfoAssociativeArrayDeclaration::TypeInfoAssociativeArrayDeclaration(Type *tinfo)
-    : TypeInfoDeclaration(tinfo, 0)
-{
-}
-
-/***************************** TypeInfoEnumDeclaration ***********************/
-
-TypeInfoEnumDeclaration::TypeInfoEnumDeclaration(Type *tinfo)
-    : TypeInfoDeclaration(tinfo, 0)
-{
-}
-
-/***************************** TypeInfoFunctionDeclaration ********************/
-
-TypeInfoFunctionDeclaration::TypeInfoFunctionDeclaration(Type *tinfo)
-    : TypeInfoDeclaration(tinfo, 0)
-{
-}
-
-/***************************** TypeInfoDelegateDeclaration ********************/
-
-TypeInfoDelegateDeclaration::TypeInfoDelegateDeclaration(Type *tinfo)
-    : TypeInfoDeclaration(tinfo, 0)
-{
-}
-
-/***************************** TypeInfoTupleDeclaration **********************/
-
-TypeInfoTupleDeclaration::TypeInfoTupleDeclaration(Type *tinfo)
-    : TypeInfoDeclaration(tinfo, 0)
-{
-}
-
-/********************************* ThisDeclaration ****************************/
-
-// For the "this" parameter to member functions
-
-ThisDeclaration::ThisDeclaration(Loc loc, Type *t)
-   : VarDeclaration(loc, t, Id::This, NULL)
-{
-    noscope = 1;
-}
-
-Dsymbol *ThisDeclaration::syntaxCopy(Dsymbol *s)
-{
-    assert(0);		// should never be produced by syntax
-    return NULL;
-}
-
-/********************** StaticStructInitDeclaration ***************************/
-
-StaticStructInitDeclaration::StaticStructInitDeclaration(Loc loc, StructDeclaration *dsym)
-    : Declaration(new Identifier("", TOKidentifier))
-{
-    this->loc = loc;
-    this->dsym = dsym;
-    storage_class |= STCconst;
-}
-
+
+// Compiler implementation of the D programming language
+// Copyright (c) 1999-2009 by Digital Mars
+// All Rights Reserved
+// written by Walter Bright
+// http://www.digitalmars.com
+// License for redistribution is by either the Artistic License
+// in artistic.txt, or the GNU General Public License in gnu.txt.
+// See the included readme.txt for details.
+
+#include <stdio.h>
+#include <assert.h>
+
+#include "init.h"
+#include "declaration.h"
+#include "attrib.h"
+#include "mtype.h"
+#include "template.h"
+#include "scope.h"
+#include "aggregate.h"
+#include "module.h"
+#include "id.h"
+#include "expression.h"
+#include "hdrgen.h"
+
+/********************************* Declaration ****************************/
+
+Declaration::Declaration(Identifier *id)
+    : Dsymbol(id)
+{
+    type = NULL;
+    originalType = NULL;
+    storage_class = STCundefined;
+    protection = PROTundefined;
+    linkage = LINKdefault;
+    inuse = 0;
+}
+
+void Declaration::semantic(Scope *sc)
+{
+}
+
+const char *Declaration::kind()
+{
+    return "declaration";
+}
+
+unsigned Declaration::size(Loc loc)
+{
+    assert(type);
+    return type->size();
+}
+
+int Declaration::isStaticConstructor()
+{
+    return FALSE;
+}
+
+int Declaration::isStaticDestructor()
+{
+    return FALSE;
+}
+
+int Declaration::isDelete()
+{
+    return FALSE;
+}
+
+int Declaration::isDataseg()
+{
+    return FALSE;
+}
+
+int Declaration::isThreadlocal()
+{
+    return FALSE;
+}
+
+int Declaration::isCodeseg()
+{
+    return FALSE;
+}
+
+enum PROT Declaration::prot()
+{
+    return protection;
+}
+
+/*************************************
+ * Check to see if declaration can be modified in this context (sc).
+ * Issue error if not.
+ */
+
+#if DMDV2
+void Declaration::checkModify(Loc loc, Scope *sc, Type *t)
+{
+    if (sc->incontract && isParameter())
+	error(loc, "cannot modify parameter '%s' in contract", toChars());
+
+    if (isCtorinit())
+    {	// It's only modifiable if inside the right constructor
+	Dsymbol *s = sc->func;
+	while (1)
+	{
+	    FuncDeclaration *fd = NULL;
+	    if (s)
+		fd = s->isFuncDeclaration();
+	    if (fd &&
+		((fd->isCtorDeclaration() && storage_class & STCfield) ||
+		 (fd->isStaticCtorDeclaration() && !(storage_class & STCfield))) &&
+		fd->toParent() == toParent()
+	       )
+	    {
+		VarDeclaration *v = isVarDeclaration();
+		assert(v);
+		v->ctorinit = 1;
+		//printf("setting ctorinit\n");
+	    }
+	    else
+	    {
+		if (s)
+		{   s = s->toParent2();
+		    continue;
+		}
+		else
+		{
+		    const char *p = isStatic() ? "static " : "";
+		    error(loc, "can only initialize %sconst %s inside %sconstructor",
+			p, toChars(), p);
+		}
+	    }
+	    break;
+	}
+    }
+    else
+    {
+	VarDeclaration *v = isVarDeclaration();
+	if (v && v->canassign == 0)
+	{
+	    const char *p = NULL;
+	    if (isConst())
+		p = "const";
+	    else if (isInvariant())
+		p = "immutable";
+	    else if (storage_class & STCmanifest)
+		p = "enum";
+	    else if (!t->isAssignable())
+		p = "struct with immutable members";
+	    if (p)
+	    {	error(loc, "cannot modify %s", p);
+	    }
+	}
+    }
+}
+#endif
+
+
+/********************************* TupleDeclaration ****************************/
+
+TupleDeclaration::TupleDeclaration(Loc loc, Identifier *id, Objects *objects)
+    : Declaration(id)
+{
+    this->type = NULL;
+    this->objects = objects;
+    this->isexp = 0;
+    this->tupletype = NULL;
+}
+
+Dsymbol *TupleDeclaration::syntaxCopy(Dsymbol *s)
+{
+    assert(0);
+    return NULL;
+}
+
+const char *TupleDeclaration::kind()
+{
+    return "tuple";
+}
+
+Type *TupleDeclaration::getType()
+{
+    /* If this tuple represents a type, return that type
+     */
+
+    //printf("TupleDeclaration::getType() %s\n", toChars());
+    if (isexp)
+	return NULL;
+    if (!tupletype)
+    {
+	/* It's only a type tuple if all the Object's are types
+	 */
+	for (size_t i = 0; i < objects->dim; i++)
+	{   Object *o = (Object *)objects->data[i];
+
+	    if (o->dyncast() != DYNCAST_TYPE)
+	    {
+		//printf("\tnot[%d], %p, %d\n", i, o, o->dyncast());
+		return NULL;
+	    }
+	}
+
+	/* We know it's a type tuple, so build the TypeTuple
+	 */
+	Arguments *args = new Arguments();
+	args->setDim(objects->dim);
+	OutBuffer buf;
+	int hasdeco = 1;
+	for (size_t i = 0; i < objects->dim; i++)
+	{   Type *t = (Type *)objects->data[i];
+
+	    //printf("type = %s\n", t->toChars());
+#if 0
+	    buf.printf("_%s_%d", ident->toChars(), i);
+	    char *name = (char *)buf.extractData();
+	    Identifier *id = new Identifier(name, TOKidentifier);
+	    Argument *arg = new Argument(STCin, t, id, NULL);
+#else
+	    Argument *arg = new Argument(STCin, t, NULL, NULL);
+#endif
+	    args->data[i] = (void *)arg;
+	    if (!t->deco)
+		hasdeco = 0;
+	}
+
+	tupletype = new TypeTuple(args);
+	if (hasdeco)
+	    return tupletype->semantic(0, NULL);
+    }
+
+    return tupletype;
+}
+
+int TupleDeclaration::needThis()
+{
+    //printf("TupleDeclaration::needThis(%s)\n", toChars());
+    for (size_t i = 0; i < objects->dim; i++)
+    {   Object *o = (Object *)objects->data[i];
+	if (o->dyncast() == DYNCAST_EXPRESSION)
+	{   Expression *e = (Expression *)o;
+	    if (e->op == TOKdsymbol)
+	    {	DsymbolExp *ve = (DsymbolExp *)e;
+		Declaration *d = ve->s->isDeclaration();
+		if (d && d->needThis())
+		{
+		    return 1;
+		}
+	    }
+	}
+    }
+    return 0;
+}
+
+/********************************* TypedefDeclaration ****************************/
+
+TypedefDeclaration::TypedefDeclaration(Loc loc, Identifier *id, Type *basetype, Initializer *init)
+    : Declaration(id)
+{
+    this->type = new TypeTypedef(this);
+    this->basetype = basetype->toBasetype();
+    this->init = init;
+#ifdef _DH
+    this->htype = NULL;
+    this->hbasetype = NULL;
+#endif
+    this->sem = 0;
+    this->loc = loc;
+#if IN_DMD
+    this->sinit = NULL;
+#endif
+}
+
+Dsymbol *TypedefDeclaration::syntaxCopy(Dsymbol *s)
+{
+    Type *basetype = this->basetype->syntaxCopy();
+
+    Initializer *init = NULL;
+    if (this->init)
+	init = this->init->syntaxCopy();
+
+    assert(!s);
+    TypedefDeclaration *st;
+    st = new TypedefDeclaration(loc, ident, basetype, init);
+#ifdef _DH
+    // Syntax copy for header file
+    if (!htype)      // Don't overwrite original
+    {	if (type)    // Make copy for both old and new instances
+	{   htype = type->syntaxCopy();
+	    st->htype = type->syntaxCopy();
+	}
+    }
+    else            // Make copy of original for new instance
+        st->htype = htype->syntaxCopy();
+    if (!hbasetype)
+    {	if (basetype)
+	{   hbasetype = basetype->syntaxCopy();
+	    st->hbasetype = basetype->syntaxCopy();
+	}
+    }
+    else
+        st->hbasetype = hbasetype->syntaxCopy();
+#endif
+    return st;
+}
+
+void TypedefDeclaration::semantic(Scope *sc)
+{
+    //printf("TypedefDeclaration::semantic(%s) sem = %d\n", toChars(), sem);
+    if (sem == 0)
+    {	sem = 1;
+	basetype = basetype->semantic(loc, sc);
+	sem = 2;
+	type = type->semantic(loc, sc);
+	if (sc->parent->isFuncDeclaration() && init)
+	    semantic2(sc);
+	storage_class |= sc->stc & STCdeprecated;
+    }
+    else if (sem == 1)
+    {
+	error("circular definition");
+    }
+}
+
+void TypedefDeclaration::semantic2(Scope *sc)
+{
+    //printf("TypedefDeclaration::semantic2(%s) sem = %d\n", toChars(), sem);
+    if (sem == 2)
+    {	sem = 3;
+	if (init)
+	{
+	    init = init->semantic(sc, basetype);
+
+	    ExpInitializer *ie = init->isExpInitializer();
+	    if (ie)
+	    {
+		if (ie->exp->type == basetype)
+		    ie->exp->type = type;
+	    }
+	}
+    }
+}
+
+const char *TypedefDeclaration::kind()
+{
+    return "typedef";
+}
+
+Type *TypedefDeclaration::getType()
+{
+    return type;
+}
+
+void TypedefDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    buf->writestring("typedef ");
+    basetype->toCBuffer(buf, ident, hgs);
+    if (init)
+    {
+	buf->writestring(" = ");
+	init->toCBuffer(buf, hgs);
+    }
+    buf->writeByte(';');
+    buf->writenl();
+}
+
+/********************************* AliasDeclaration ****************************/
+
+AliasDeclaration::AliasDeclaration(Loc loc, Identifier *id, Type *type)
+    : Declaration(id)
+{
+    //printf("AliasDeclaration(id = '%s', type = %p)\n", id->toChars(), type);
+    //printf("type = '%s'\n", type->toChars());
+    this->loc = loc;
+    this->type = type;
+    this->aliassym = NULL;
+#ifdef _DH
+    this->htype = NULL;
+    this->haliassym = NULL;
+#endif
+    this->overnext = NULL;
+    this->inSemantic = 0;
+    this->importprot = PROTundefined;
+    assert(type);
+}
+
+AliasDeclaration::AliasDeclaration(Loc loc, Identifier *id, Dsymbol *s)
+    : Declaration(id)
+{
+    //printf("AliasDeclaration(id = '%s', s = %p)\n", id->toChars(), s);
+    assert(s != this);
+    this->loc = loc;
+    this->type = NULL;
+    this->aliassym = s;
+#ifdef _DH
+    this->htype = NULL;
+    this->haliassym = NULL;
+#endif
+    this->overnext = NULL;
+    this->inSemantic = 0;
+    assert(s);
+}
+
+Dsymbol *AliasDeclaration::syntaxCopy(Dsymbol *s)
+{
+    //printf("AliasDeclaration::syntaxCopy()\n");
+    assert(!s);
+    AliasDeclaration *sa;
+    if (type)
+	sa = new AliasDeclaration(loc, ident, type->syntaxCopy());
+    else
+	sa = new AliasDeclaration(loc, ident, aliassym->syntaxCopy(NULL));
+#ifdef _DH
+    // Syntax copy for header file
+    if (!htype)	    // Don't overwrite original
+    {	if (type)	// Make copy for both old and new instances
+	{   htype = type->syntaxCopy();
+	    sa->htype = type->syntaxCopy();
+	}
+    }
+    else			// Make copy of original for new instance
+	sa->htype = htype->syntaxCopy();
+    if (!haliassym)
+    {	if (aliassym)
+	{   haliassym = aliassym->syntaxCopy(s);
+	    sa->haliassym = aliassym->syntaxCopy(s);
+	}
+    }
+    else
+	sa->haliassym = haliassym->syntaxCopy(s);
+#endif
+    return sa;
+}
+
+void AliasDeclaration::semantic(Scope *sc)
+{
+    //printf("AliasDeclaration::semantic() %s\n", toChars());
+    if (aliassym)
+    {
+	if (aliassym->isTemplateInstance())
+	    aliassym->semantic(sc);
+	return;
+    }
+    this->inSemantic = 1;
+
+    if (storage_class & STCconst)
+	error("cannot be const");
+
+    storage_class |= sc->stc & STCdeprecated;
+
+    // Given:
+    //	alias foo.bar.abc def;
+    // it is not knowable from the syntax whether this is an alias
+    // for a type or an alias for a symbol. It is up to the semantic()
+    // pass to distinguish.
+    // If it is a type, then type is set and getType() will return that
+    // type. If it is a symbol, then aliassym is set and type is NULL -
+    // toAlias() will return aliasssym.
+
+    Dsymbol *s;
+    Type *t;
+    Expression *e;
+
+    /* This section is needed because resolve() will:
+     *   const x = 3;
+     *   alias x y;
+     * try to alias y to 3.
+     */
+    s = type->toDsymbol(sc);
+    if (s
+#if DMDV2
+`	&& ((s->getType() && type->equals(s->getType())) || s->isEnumMember())
+#endif
+	)
+	goto L2;			// it's a symbolic alias
+
+#if DMDV2
+    if (storage_class & (STCref | STCnothrow | STCpure))
+    {	// For 'ref' to be attached to function types, and picked
+	// up by Type::resolve(), it has to go into sc.
+	sc = sc->push();
+	sc->stc |= storage_class & (STCref | STCnothrow | STCpure);
+	type->resolve(loc, sc, &e, &t, &s);
+	sc = sc->pop();
+    }
+    else
+#endif
+	type->resolve(loc, sc, &e, &t, &s);
+    if (s)
+    {
+	goto L2;
+    }
+    else if (e)
+    {
+	// Try to convert Expression to Dsymbol
+        if (e->op == TOKvar)
+	{   s = ((VarExp *)e)->var;
+	    goto L2;
+	}
+        else if (e->op == TOKfunction)
+	{   s = ((FuncExp *)e)->fd;
+	    goto L2;
+	}
+        else
+	{   error("cannot alias an expression %s", e->toChars());
+	    t = e->type;
+	}
+    }
+    else if (t)
+    {
+	type = t;
+    }
+    if (overnext)
+	ScopeDsymbol::multiplyDefined(0, this, overnext);
+    this->inSemantic = 0;
+    return;
+
+  L2:
+    //printf("alias is a symbol %s %s\n", s->kind(), s->toChars());
+    type = NULL;
+    VarDeclaration *v = s->isVarDeclaration();
+    if (v && v->linkage == LINKdefault)
+    {
+	error("forward reference of %s", v->toChars());
+	s = NULL;
+    }
+    else
+    {
+	FuncDeclaration *f = s->toAlias()->isFuncDeclaration();
+	if (f)
+	{
+	    if (overnext)
+	    {
+		FuncAliasDeclaration *fa = new FuncAliasDeclaration(f);
+		fa->importprot = importprot;
+		if (!fa->overloadInsert(overnext))
+		    ScopeDsymbol::multiplyDefined(0, f, overnext);
+		overnext = NULL;
+		s = fa;
+		s->parent = sc->parent;
+	    }
+	}
+	if (overnext)
+	    ScopeDsymbol::multiplyDefined(0, s, overnext);
+	if (s == this)
+	{
+	    assert(global.errors);
+	    s = NULL;
+	}
+    }
+    if (!aliassym)
+	aliassym = s;
+    this->inSemantic = 0;
+}
+
+int AliasDeclaration::overloadInsert(Dsymbol *s)
+{
+    /* Don't know yet what the aliased symbol is, so assume it can
+     * be overloaded and check later for correctness.
+     */
+
+    //printf("AliasDeclaration::overloadInsert('%s')\n", s->toChars());
+    if (overnext == NULL)
+    {
+	if (s == this)
+	{
+	    return TRUE;
+	}
+	overnext = s;
+	return TRUE;
+    }
+    else
+    {
+	return overnext->overloadInsert(s);
+    }
+}
+
+const char *AliasDeclaration::kind()
+{
+    return "alias";
+}
+
+Type *AliasDeclaration::getType()
+{
+    //printf("AliasDeclaration::getType() %s\n", type->toChars());
+#if 0
+    if (!type->deco && scope)
+	semantic(scope);
+    if (type && !type->deco)
+	error("forward reference to alias %s\n", toChars());
+#endif
+    return type;
+}
+
+Dsymbol *AliasDeclaration::toAlias()
+{
+    //printf("AliasDeclaration::toAlias('%s', this = %p, aliassym = %p, kind = '%s')\n", toChars(), this, aliassym, aliassym ? aliassym->kind() : "");
+    assert(this != aliassym);
+    //static int count; if (++count == 75) exit(0); //*(char*)0=0;
+    if (inSemantic)
+    {	error("recursive alias declaration");
+	aliassym = new TypedefDeclaration(loc, ident, Type::terror, NULL);
+    }
+    Dsymbol *s = aliassym ? aliassym->toAlias() : this;
+    return s;
+}
+
+void AliasDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    buf->writestring("alias ");
+#if 0 && _DH
+    if (hgs->hdrgen)
+    {
+	if (haliassym)
+	{
+	    buf->writestring(haliassym->toChars());
+	    buf->writeByte(' ');
+	    buf->writestring(ident->toChars());
+	}
+	else
+	    htype->toCBuffer(buf, ident, hgs);
+    }
+    else
+#endif
+    {
+	if (aliassym)
+	{
+	    buf->writestring(aliassym->toChars());
+	    buf->writeByte(' ');
+	    buf->writestring(ident->toChars());
+	}
+	else
+	    type->toCBuffer(buf, ident, hgs);
+    }
+    buf->writeByte(';');
+    buf->writenl();
+}
+
+/********************************* VarDeclaration ****************************/
+
+VarDeclaration::VarDeclaration(Loc loc, Type *type, Identifier *id, Initializer *init)
+    : Declaration(id)
+{
+    //printf("VarDeclaration('%s')\n", id->toChars());
+#ifdef DEBUG
+    if (!type && !init)
+    {	printf("VarDeclaration('%s')\n", id->toChars());
+	//*(char*)0=0;
+    }
+#endif
+    assert(type || init);
+    this->type = type;
+    this->init = init;
+#ifdef _DH
+    this->htype = NULL;
+    this->hinit = NULL;
+#endif
+    this->loc = loc;
+    offset = 0;
+    noscope = 0;
+#if DMDV1
+    nestedref = 0;
+#endif
+    ctorinit = 0;
+    aliassym = NULL;
+    onstack = 0;
+    canassign = 0;
+    value = NULL;
+
+#if IN_LLVM
+    aggrIndex = 0;
+
+    // LDC
+    anonDecl = NULL;
+    offset2 = 0;
+
+    nakedUse = false;
+
+    availableExternally = true; // assume this unless proven otherwise
+#endif
+}
+
+Dsymbol *VarDeclaration::syntaxCopy(Dsymbol *s)
+{
+    //printf("VarDeclaration::syntaxCopy(%s)\n", toChars());
+
+    VarDeclaration *sv;
+    if (s)
+    {	sv = (VarDeclaration *)s;
+    }
+    else
+    {
+	Initializer *init = NULL;
+	if (this->init)
+	{   init = this->init->syntaxCopy();
+	    //init->isExpInitializer()->exp->print();
+	    //init->isExpInitializer()->exp->dump(0);
+	}
+
+	sv = new VarDeclaration(loc, type ? type->syntaxCopy() : NULL, ident, init);
+	sv->storage_class = storage_class;
+    }
+#ifdef _DH
+    // Syntax copy for header file
+    if (!htype)      // Don't overwrite original
+    {	if (type)    // Make copy for both old and new instances
+	{   htype = type->syntaxCopy();
+	    sv->htype = type->syntaxCopy();
+	}
+    }
+    else            // Make copy of original for new instance
+        sv->htype = htype->syntaxCopy();
+    if (!hinit)
+    {	if (init)
+	{   hinit = init->syntaxCopy();
+	    sv->hinit = init->syntaxCopy();
+	}
+    }
+    else
+        sv->hinit = hinit->syntaxCopy();
+#endif
+    return sv;
+}
+
+void VarDeclaration::semantic(Scope *sc)
+{
+#if 0
+    printf("VarDeclaration::semantic('%s', parent = '%s')\n", toChars(), sc->parent->toChars());
+    printf(" type = %s\n", type ? type->toChars() : "null");
+    printf(" stc = x%x\n", sc->stc);
+    printf(" storage_class = x%x\n", storage_class);
+    printf("linkage = %d\n", sc->linkage);
+    //if (strcmp(toChars(), "mul") == 0) halt();
+#endif
+
+    storage_class |= sc->stc;
+    if (storage_class & STCextern && init)
+	error("extern symbols cannot have initializers");
+
+    /* If auto type inference, do the inference
+     */
+    int inferred = 0;
+    if (!type)
+    {	inuse++;
+	type = init->inferType(sc);
+	inuse--;
+	inferred = 1;
+
+	/* This is a kludge to support the existing syntax for RAII
+	 * declarations.
+	 */
+	storage_class &= ~STCauto;
+	originalType = type;
+    }
+    else
+    {	if (!originalType)
+	    originalType = type;
+	type = type->semantic(loc, sc);
+    }
+    //printf(" semantic type = %s\n", type ? type->toChars() : "null");
+
+    type->checkDeprecated(loc, sc);
+    linkage = sc->linkage;
+    this->parent = sc->parent;
+    //printf("this = %p, parent = %p, '%s'\n", this, parent, parent->toChars());
+    protection = sc->protection;
+    //printf("sc->stc = %x\n", sc->stc);
+    //printf("storage_class = x%x\n", storage_class);
+
+#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();
+
+    Type *tb = type->toBasetype();
+    if (tb->ty == Tvoid && !(storage_class & STClazy))
+    {	error("voids have no value");
+	type = Type::terror;
+	tb = type;
+    }
+    if (tb->ty == Tfunction)
+    {	error("cannot be declared to be a function");
+	type = Type::terror;
+	tb = type;
+    }
+    if (tb->ty == Tstruct)
+    {	TypeStruct *ts = (TypeStruct *)tb;
+
+	if (!ts->sym->members)
+	{
+	    error("no definition of struct %s", ts->toChars());
+	}
+    }
+    if ((storage_class & STCauto) && !inferred)
+	error("both auto and explicit type given");
+
+    if (tb->ty == Ttuple)
+    {   /* Instead, declare variables for each of the tuple elements
+	 * and add those.
+	 */
+	TypeTuple *tt = (TypeTuple *)tb;
+	size_t nelems = Argument::dim(tt->arguments);
+	Objects *exps = new Objects();
+	exps->setDim(nelems);
+	Expression *ie = init ? init->toExpression() : NULL;
+
+	for (size_t i = 0; i < nelems; i++)
+	{   Argument *arg = Argument::getNth(tt->arguments, i);
+
+	    OutBuffer buf;
+	    buf.printf("_%s_field_%zu", ident->toChars(), i);
+	    buf.writeByte(0);
+	    char *name = (char *)buf.extractData();
+	    Identifier *id = new Identifier(name, TOKidentifier);
+
+	    Expression *einit = ie;
+	    if (ie && ie->op == TOKtuple)
+	    {	einit = (Expression *)((TupleExp *)ie)->exps->data[i];
+	    }
+	    Initializer *ti = init;
+	    if (einit)
+	    {	ti = new ExpInitializer(einit->loc, einit);
+	    }
+
+	    VarDeclaration *v = new VarDeclaration(loc, arg->type, id, ti);
+	    //printf("declaring field %s of type %s\n", v->toChars(), v->type->toChars());
+	    v->semantic(sc);
+            
+/*
+// removed for LDC since TupleDeclaration::toObj already creates the fields;
+// adding them to the scope again leads to duplicates
+	    if (sc->scopesym)
+	    {	//printf("adding %s to %s\n", v->toChars(), sc->scopesym->toChars());
+		if (sc->scopesym->members)
+		    sc->scopesym->members->push(v);
+	    }
+*/
+	    Expression *e = new DsymbolExp(loc, v);
+	    exps->data[i] = e;
+	}
+	TupleDeclaration *v2 = new TupleDeclaration(loc, ident, exps);
+	v2->isexp = 1;
+	aliassym = v2;
+	return;
+    }
+
+    if (storage_class & STCconst && !init && !fd)
+	// Initialize by constructor only
+	storage_class = (storage_class & ~STCconst) | STCctorinit;
+
+    if (isConst())
+    {
+    }
+    else if (isStatic())
+    {
+    }
+    else if (isSynchronized())
+    {
+	error("variable %s cannot be synchronized", toChars());
+    }
+    else if (isOverride())
+    {
+	error("override cannot be applied to variable");
+    }
+    else if (isAbstract())
+    {
+	error("abstract cannot be applied to variable");
+    }
+    else if (storage_class & STCtemplateparameter)
+    {
+    }
+    else
+    {
+	AggregateDeclaration *aad = sc->anonAgg;
+	if (!aad)
+	    aad = parent->isAggregateDeclaration();
+	if (aad)
+	{
+#if DMDV2
+	    assert(!(storage_class & (STCextern | STCstatic | STCtls | STCgshared)));
+
+	    if (storage_class & (STCconst | STCimmutable) && init)
+	    {
+		if (!type->toBasetype()->isTypeBasic())
+		    storage_class |= STCstatic;
+	    }
+	    else
+#endif
+		aad->addField(sc, this);
+	}
+
+	InterfaceDeclaration *id = parent->isInterfaceDeclaration();
+	if (id)
+	{
+	    error("field not allowed in interface");
+	}
+
+	/* Templates cannot add fields to aggregates
+	 */
+	TemplateInstance *ti = parent->isTemplateInstance();
+	if (ti)
+	{
+	    // Take care of nested templates
+	    while (1)
+	    {
+		TemplateInstance *ti2 = ti->tempdecl->parent->isTemplateInstance();
+		if (!ti2)
+		    break;
+		ti = ti2;
+	    }
+
+	    // If it's a member template
+	    AggregateDeclaration *ad = ti->tempdecl->isMember();
+	    if (ad && storage_class != STCundefined)
+	    {
+		error("cannot use template to add field to aggregate '%s'", ad->toChars());
+	    }
+	}
+    }
+
+#if DMDV2
+    if ((storage_class & (STCref | STCparameter | STCforeach)) == STCref &&
+	ident != Id::This)
+    {
+	error("only parameters or foreach declarations can be ref");
+    }
+#endif
+
+    if (type->isscope() && !noscope)
+    {
+	if (storage_class & (STCfield | STCout | STCref | STCstatic) || !fd)
+	{
+	    error("globals, statics, fields, ref and out parameters cannot be scope");
+	}
+
+	if (!(storage_class & STCscope))
+	{
+	    if (!(storage_class & STCparameter) && ident != Id::withSym)
+		error("reference to scope class must be scope");
+	}
+    }
+
+    enum TOK op = TOKconstruct;
+    if (!init && !sc->inunion && !isStatic() && !isConst() && fd &&
+	!(storage_class & (STCfield | STCin | STCforeach)) &&
+	type->size() != 0)
+    {
+	// Provide a default initializer
+	//printf("Providing default initializer for '%s'\n", toChars());
+	if (type->ty == Tstruct &&
+	    ((TypeStruct *)type)->sym->zeroInit == 1)
+	{   /* If a struct is all zeros, as a special case
+	     * set it's initializer to the integer 0.
+	     * In AssignExp::toElem(), we check for this and issue
+	     * a memset() to initialize the struct.
+	     * Must do same check in interpreter.
+	     */
+	    Expression *e = new IntegerExp(loc, 0, Type::tint32);
+	    Expression *e1;
+	    e1 = new VarExp(loc, this);
+	    e = new AssignExp(loc, e1, e);
+	    e->op = TOKconstruct;
+	    e->type = e1->type;		// don't type check this, it would fail
+	    init = new ExpInitializer(loc, e);
+	    return;
+	}
+	else if (type->ty == Ttypedef)
+	{   TypeTypedef *td = (TypeTypedef *)type;
+	    if (td->sym->init)
+	    {	init = td->sym->init;
+		ExpInitializer *ie = init->isExpInitializer();
+		if (ie)
+		    // Make copy so we can modify it
+		    init = new ExpInitializer(ie->loc, ie->exp);
+	    }
+	    else
+		init = getExpInitializer();
+	}
+	else
+	{
+	    init = getExpInitializer();
+	}
+	// Default initializer is always a blit
+	op = TOKblit;
+    }
+
+    if (init)
+    {
+	sc = sc->push();
+	sc->stc &= ~(STC_TYPECTOR | STCpure | STCnothrow | STCref);
+
+	ArrayInitializer *ai = init->isArrayInitializer();
+	if (ai && tb->ty == Taarray)
+	{
+	    init = ai->toAssocArrayInitializer();
+	}
+
+	StructInitializer *si = init->isStructInitializer();
+	ExpInitializer *ei = init->isExpInitializer();
+
+	// See if initializer is a NewExp that can be allocated on the stack
+	if (ei && isScope() && ei->exp->op == TOKnew)
+	{   NewExp *ne = (NewExp *)ei->exp;
+	    if (!(ne->newargs && ne->newargs->dim))
+	    {	ne->onstack = 1;
+		onstack = 1;
+		if (type->isBaseOf(ne->newtype->semantic(loc, sc), NULL))
+		    onstack = 2;
+	    }
+	}
+
+	// If inside function, there is no semantic3() call
+	if (sc->func)
+	{
+	    // If local variable, use AssignExp to handle all the various
+	    // possibilities.
+	    if (fd && !isStatic() && !isConst() && !init->isVoidInitializer())
+	    {
+		//printf("fd = '%s', var = '%s'\n", fd->toChars(), toChars());
+		if (!ei)
+		{
+		    Expression *e = init->toExpression();
+		    if (!e)
+		    {
+			init = init->semantic(sc, type);
+			e = init->toExpression();
+			if (!e)
+			{   error("is not a static and cannot have static initializer");
+			    return;
+			}
+		    }
+		    ei = new ExpInitializer(init->loc, e);
+		    init = ei;
+		}
+
+		Expression *e1 = new VarExp(loc, this);
+
+		Type *t = type->toBasetype();
+		if (t->ty == Tsarray && !(storage_class & (STCref | STCout)))
+		{
+		    ei->exp = ei->exp->semantic(sc);
+		    if (!ei->exp->implicitConvTo(type))
+		    {
+			int dim = ((TypeSArray *)t)->dim->toInteger();
+			// If multidimensional static array, treat as one large array
+			while (1)
+			{
+			    t = t->nextOf()->toBasetype();
+			    if (t->ty != Tsarray)
+				break;
+			    dim *= ((TypeSArray *)t)->dim->toInteger();
+			    e1->type = new TypeSArray(t->nextOf(), new IntegerExp(0, dim, Type::tindex));
+			}
+		    }
+		    e1 = new SliceExp(loc, e1, NULL, NULL);
+		}
+		else if (t->ty == Tstruct)
+		{
+		    ei->exp = ei->exp->semantic(sc);
+		    ei->exp = resolveProperties(sc, ei->exp);
+		    StructDeclaration *sd = ((TypeStruct *)t)->sym;
+#if DMDV2
+		    /* Look to see if initializer is a call to the constructor
+		     */
+		    if (sd->ctor &&		// there are constructors
+			ei->exp->type->ty == Tstruct &&	// rvalue is the same struct
+			((TypeStruct *)ei->exp->type)->sym == sd &&
+			ei->exp->op == TOKstar)
+		    {
+			/* Look for form of constructor call which is:
+			 *    *__ctmp.ctor(arguments...)
+			 */
+			PtrExp *pe = (PtrExp *)ei->exp;
+			if (pe->e1->op == TOKcall)
+			{   CallExp *ce = (CallExp *)pe->e1;
+			    if (ce->e1->op == TOKdotvar)
+			    {	DotVarExp *dve = (DotVarExp *)ce->e1;
+				if (dve->var->isCtorDeclaration())
+				{   /* It's a constructor call, currently constructing
+				     * a temporary __ctmp.
+				     */
+				    /* Before calling the constructor, initialize
+				     * variable with a bit copy of the default
+				     * initializer
+				     */
+				    Expression *e = new AssignExp(loc, new VarExp(loc, this), t->defaultInit(loc));
+				    e->op = TOKblit;
+				    e->type = t;
+				    ei->exp = new CommaExp(loc, e, ei->exp);
+
+				    /* Replace __ctmp being constructed with e1
+				     */
+				    dve->e1 = e1;
+				    return;
+				}
+			    }
+			}
+		    }
+#endif
+		    if (!ei->exp->implicitConvTo(type))
+		    {
+			/* Look for opCall
+			 * See bugzilla 2702 for more discussion
+			 */
+			Type *ti = ei->exp->type->toBasetype();
+			// Don't cast away invariant or mutability in initializer
+			if (search_function(sd, Id::call) &&
+			    /* Initializing with the same type is done differently
+			     */
+			    !(ti->ty == Tstruct && t->toDsymbol(sc) == ti->toDsymbol(sc)))
+			{   // Rewrite as e1.call(arguments)
+			    Expression * eCall = new DotIdExp(loc, e1, Id::call);
+			    ei->exp = new CallExp(loc, eCall, ei->exp);
+			}
+		    }
+		}
+		ei->exp = new AssignExp(loc, e1, ei->exp);
+		ei->exp->op = TOKconstruct;
+		canassign++;
+		ei->exp = ei->exp->semantic(sc);
+		canassign--;
+		ei->exp->optimize(WANTvalue);
+	    }
+	    else
+	    {
+		init = init->semantic(sc, type);
+		if (fd && isConst() && !isStatic())
+		{   // Make it static
+		    storage_class |= STCstatic;
+		}
+	    }
+	}
+	else if (isConst() || isFinal() ||
+		 parent->isAggregateDeclaration())
+	{
+	    /* Because we may need the results of a const declaration in a
+	     * subsequent type, such as an array dimension, before semantic2()
+	     * gets ordinarily run, try to run semantic2() now.
+	     * Ignore failure.
+	     */
+
+	    if (!global.errors && !inferred)
+	    {
+		unsigned errors = global.errors;
+		global.gag++;
+		//printf("+gag\n");
+		Expression *e;
+		Initializer *i2 = init;
+		inuse++;
+		if (ei)
+		{
+		    e = ei->exp->syntaxCopy();
+		    e = e->semantic(sc);
+		    e = e->implicitCastTo(sc, type);
+		}
+		else if (si || ai)
+		{   i2 = init->syntaxCopy();
+		    i2 = i2->semantic(sc, type);
+		}
+		inuse--;
+		global.gag--;
+		//printf("-gag\n");
+		if (errors != global.errors)	// if errors happened
+		{
+		    if (global.gag == 0)
+			global.errors = errors;	// act as if nothing happened
+#if DMDV2
+		    /* Save scope for later use, to try again
+		     */
+		    scope = new Scope(*sc);
+		    scope->setNoFree();
+#endif
+		}
+		else if (ei)
+		{
+		    e = e->optimize(WANTvalue | WANTinterpret);
+		    if (e->op == TOKint64 || e->op == TOKstring || e->op == TOKfloat64)
+		    {
+			ei->exp = e;		// no errors, keep result
+		    }
+#if DMDV2
+		    else
+		    {
+			/* Save scope for later use, to try again
+			 */
+			scope = new Scope(*sc);
+			scope->setNoFree();
+		    }
+#endif
+		}
+		else
+		    init = i2;		// no errors, keep result
+	    }
+	}
+	sc = sc->pop();
+    }
+}
+
+ExpInitializer *VarDeclaration::getExpInitializer()
+{
+    ExpInitializer *ei;
+
+    if (init)
+	ei = init->isExpInitializer();
+    else
+    {
+	Expression *e = type->defaultInit(loc);
+	if (e)
+	    ei = new ExpInitializer(loc, e);
+	else
+	    ei = NULL;
+    }
+    return ei;
+}
+
+void VarDeclaration::semantic2(Scope *sc)
+{
+    //printf("VarDeclaration::semantic2('%s')\n", toChars());
+    if (init && !toParent()->isFuncDeclaration())
+    {	inuse++;
+#if 0
+	ExpInitializer *ei = init->isExpInitializer();
+	if (ei)
+	{
+	    ei->exp->dump(0);
+	    printf("type = %p\n", ei->exp->type);
+	}
+#endif
+	init = init->semantic(sc, type);
+	inuse--;
+    }
+}
+
+void VarDeclaration::semantic3(Scope *sc)
+{
+    // LDC
+    if (!global.params.useAvailableExternally)
+        availableExternally = false;
+
+    // Preserve call chain
+    Declaration::semantic3(sc);
+}
+
+const char *VarDeclaration::kind()
+{
+    return "variable";
+}
+
+Dsymbol *VarDeclaration::toAlias()
+{
+    //printf("VarDeclaration::toAlias('%s', this = %p, aliassym = %p)\n", toChars(), this, aliassym);
+    assert(this != aliassym);
+    Dsymbol *s = aliassym ? aliassym->toAlias() : this;
+    return s;
+}
+
+void VarDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    StorageClassDeclaration::stcToCBuffer(buf, storage_class);
+
+    /* If changing, be sure and fix CompoundDeclarationStatement::toCBuffer()
+     * too.
+     */
+    if (type)
+	type->toCBuffer(buf, ident, hgs);
+    else
+	buf->writestring(ident->toChars());
+    if (init)
+    {	buf->writestring(" = ");
+#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(';');
+    buf->writenl();
+}
+
+int VarDeclaration::needThis()
+{
+    //printf("VarDeclaration::needThis(%s, x%x)\n", toChars(), storage_class);
+    return storage_class & STCfield;
+}
+
+int VarDeclaration::isImportedSymbol()
+{
+    if (protection == PROTexport && !init && (isStatic() || isConst() || parent->isModule()))
+	return TRUE;
+    return FALSE;
+}
+
+void VarDeclaration::checkCtorConstInit()
+{
+    if (ctorinit == 0 && isCtorinit() && !(storage_class & STCfield))
+	error("missing initializer in static constructor for const variable");
+}
+
+/************************************
+ * Check to see if this variable is actually in an enclosing function
+ * rather than the current one.
+ */
+
+void VarDeclaration::checkNestedReference(Scope *sc, Loc loc)
+{
+    //printf("VarDeclaration::checkNestedReference() %s\n", toChars());
+    if (parent && !isDataseg() && parent != sc->parent)
+    {
+	// The function that this variable is in
+	FuncDeclaration *fdv = toParent()->isFuncDeclaration();
+	// The current function
+	FuncDeclaration *fdthis = sc->parent->isFuncDeclaration();
+
+	if (fdv && fdthis)
+	{
+	    if (loc.filename)
+		fdthis->getLevel(loc, fdv);
+	    nestedref = 1;
+	    fdv->nestedFrameRef = 1;
+#if IN_LLVM
+#if DMDV1
+        fdv->nestedVars.insert(this);
+#endif
+#endif
+	    //printf("var %s in function %s is nested ref\n", toChars(), fdv->toChars());
+	}
+    }
+}
+
+/*******************************
+ * Does symbol go into data segment?
+ * Includes extern variables.
+ */
+
+int VarDeclaration::isDataseg()
+{
+#if 0
+    printf("VarDeclaration::isDataseg(%p, '%s')\n", this, toChars());
+    printf("%x, %p, %p\n", storage_class & (STCstatic | STCconst), parent->isModule(), parent->isTemplateInstance());
+    printf("parent = '%s'\n", parent->toChars());
+#endif
+    Dsymbol *parent = this->toParent();
+    if (!parent && !(storage_class & (STCstatic | STCconst)))
+    {	error("forward referenced");
+	type = Type::terror;
+	return 0;
+    }
+    return (storage_class & (STCstatic | STCconst) ||
+	   parent->isModule() ||
+	   parent->isTemplateInstance());
+}
+
+/************************************
+ * Does symbol go into thread local storage?
+ */
+
+int VarDeclaration::isThreadlocal()
+{
+    return 0;
+}
+
+int VarDeclaration::hasPointers()
+{
+    //printf("VarDeclaration::hasPointers() %s, ty = %d\n", toChars(), type->ty);
+    return (!isDataseg() && type->hasPointers());
+}
+
+int VarDeclaration::isSameAsInitializer()
+{
+    if (init && init->isExpInitializer() && 
+        init->isExpInitializer()->exp->op == TOKstructliteral)
+        return 0;
+    return isConst();
+}
+
+/******************************************
+ * If a variable has an scope destructor call, return call for it.
+ * Otherwise, return NULL.
+ */
+
+Expression *VarDeclaration::callScopeDtor(Scope *sc)
+{   Expression *e = NULL;
+
+    //printf("VarDeclaration::callScopeDtor() %s\n", toChars());
+    if (storage_class & STCscope && !noscope)
+    {
+	for (ClassDeclaration *cd = type->isClassHandle();
+	     cd;
+	     cd = cd->baseClass)
+	{
+	    /* We can do better if there's a way with onstack
+	     * classes to determine if there's no way the monitor
+	     * could be set.
+	     */
+	    //if (cd->isInterfaceDeclaration())
+		//error("interface %s cannot be scope", cd->toChars());
+	    if (1 || onstack || cd->dtors.dim)	// if any destructors
+	    {
+		// delete this;
+		Expression *ec;
+
+		ec = new VarExp(loc, this);
+		e = new DeleteExp(loc, ec);
+		e->type = Type::tvoid;
+		break;
+	    }
+	}
+    }
+    return e;
+}
+
+
+/********************************* ClassInfoDeclaration ****************************/
+
+ClassInfoDeclaration::ClassInfoDeclaration(ClassDeclaration *cd)
+    : VarDeclaration(0, ClassDeclaration::classinfo->type, cd->ident, NULL)
+{
+    this->cd = cd;
+    storage_class = STCstatic;
+}
+
+Dsymbol *ClassInfoDeclaration::syntaxCopy(Dsymbol *s)
+{
+    assert(0);		// should never be produced by syntax
+    return NULL;
+}
+
+void ClassInfoDeclaration::semantic(Scope *sc)
+{
+}
+
+/********************************* ModuleInfoDeclaration ****************************/
+
+ModuleInfoDeclaration::ModuleInfoDeclaration(Module *mod)
+    : VarDeclaration(0, Module::moduleinfo->type, mod->ident, NULL)
+{
+    this->mod = mod;
+    storage_class = STCstatic;
+}
+
+Dsymbol *ModuleInfoDeclaration::syntaxCopy(Dsymbol *s)
+{
+    assert(0);		// should never be produced by syntax
+    return NULL;
+}
+
+void ModuleInfoDeclaration::semantic(Scope *sc)
+{
+}
+
+/********************************* TypeInfoDeclaration ****************************/
+
+TypeInfoDeclaration::TypeInfoDeclaration(Type *tinfo, int internal)
+    : VarDeclaration(0, Type::typeinfo->type, tinfo->getTypeInfoIdent(internal), NULL)
+{
+    this->tinfo = tinfo;
+    storage_class = STCstatic;
+    protection = PROTpublic;
+    linkage = LINKc;
+}
+
+Dsymbol *TypeInfoDeclaration::syntaxCopy(Dsymbol *s)
+{
+    assert(0);		// should never be produced by syntax
+    return NULL;
+}
+
+void TypeInfoDeclaration::semantic(Scope *sc)
+{
+    assert(linkage == LINKc);
+    // LDC
+    if (!global.params.useAvailableExternally)
+        availableExternally = false;
+}
+
+/***************************** TypeInfoConstDeclaration **********************/
+
+#if DMDV2
+TypeInfoConstDeclaration::TypeInfoConstDeclaration(Type *tinfo)
+    : TypeInfoDeclaration(tinfo, 0)
+{
+}
+#endif
+
+/***************************** TypeInfoInvariantDeclaration **********************/
+
+#if DMDV2
+TypeInfoInvariantDeclaration::TypeInfoInvariantDeclaration(Type *tinfo)
+    : TypeInfoDeclaration(tinfo, 0)
+{
+}
+#endif
+
+/***************************** TypeInfoSharedDeclaration **********************/
+
+#if DMDV2
+TypeInfoSharedDeclaration::TypeInfoSharedDeclaration(Type *tinfo)
+    : TypeInfoDeclaration(tinfo, 0)
+{
+}
+#endif
+
+/***************************** TypeInfoStructDeclaration **********************/
+
+TypeInfoStructDeclaration::TypeInfoStructDeclaration(Type *tinfo)
+    : TypeInfoDeclaration(tinfo, 0)
+{
+}
+
+/***************************** TypeInfoClassDeclaration ***********************/
+
+TypeInfoClassDeclaration::TypeInfoClassDeclaration(Type *tinfo)
+    : TypeInfoDeclaration(tinfo, 0)
+{
+}
+
+/***************************** TypeInfoInterfaceDeclaration *******************/
+
+TypeInfoInterfaceDeclaration::TypeInfoInterfaceDeclaration(Type *tinfo)
+    : TypeInfoDeclaration(tinfo, 0)
+{
+}
+
+/***************************** TypeInfoTypedefDeclaration *********************/
+
+TypeInfoTypedefDeclaration::TypeInfoTypedefDeclaration(Type *tinfo)
+    : TypeInfoDeclaration(tinfo, 0)
+{
+}
+
+/***************************** TypeInfoPointerDeclaration *********************/
+
+TypeInfoPointerDeclaration::TypeInfoPointerDeclaration(Type *tinfo)
+    : TypeInfoDeclaration(tinfo, 0)
+{
+}
+
+/***************************** TypeInfoArrayDeclaration ***********************/
+
+TypeInfoArrayDeclaration::TypeInfoArrayDeclaration(Type *tinfo)
+    : TypeInfoDeclaration(tinfo, 0)
+{
+}
+
+/***************************** TypeInfoStaticArrayDeclaration *****************/
+
+TypeInfoStaticArrayDeclaration::TypeInfoStaticArrayDeclaration(Type *tinfo)
+    : TypeInfoDeclaration(tinfo, 0)
+{
+}
+
+/***************************** TypeInfoAssociativeArrayDeclaration ************/
+
+TypeInfoAssociativeArrayDeclaration::TypeInfoAssociativeArrayDeclaration(Type *tinfo)
+    : TypeInfoDeclaration(tinfo, 0)
+{
+}
+
+/***************************** TypeInfoEnumDeclaration ***********************/
+
+TypeInfoEnumDeclaration::TypeInfoEnumDeclaration(Type *tinfo)
+    : TypeInfoDeclaration(tinfo, 0)
+{
+}
+
+/***************************** TypeInfoFunctionDeclaration ********************/
+
+TypeInfoFunctionDeclaration::TypeInfoFunctionDeclaration(Type *tinfo)
+    : TypeInfoDeclaration(tinfo, 0)
+{
+}
+
+/***************************** TypeInfoDelegateDeclaration ********************/
+
+TypeInfoDelegateDeclaration::TypeInfoDelegateDeclaration(Type *tinfo)
+    : TypeInfoDeclaration(tinfo, 0)
+{
+}
+
+/***************************** TypeInfoTupleDeclaration **********************/
+
+TypeInfoTupleDeclaration::TypeInfoTupleDeclaration(Type *tinfo)
+    : TypeInfoDeclaration(tinfo, 0)
+{
+}
+
+/********************************* ThisDeclaration ****************************/
+
+// For the "this" parameter to member functions
+
+ThisDeclaration::ThisDeclaration(Loc loc, Type *t)
+   : VarDeclaration(loc, t, Id::This, NULL)
+{
+    noscope = 1;
+}
+
+Dsymbol *ThisDeclaration::syntaxCopy(Dsymbol *s)
+{
+    assert(0);		// should never be produced by syntax
+    return NULL;
+}
+
+/********************** StaticStructInitDeclaration ***************************/
+
+StaticStructInitDeclaration::StaticStructInitDeclaration(Loc loc, StructDeclaration *dsym)
+    : Declaration(new Identifier("", TOKidentifier))
+{
+    this->loc = loc;
+    this->dsym = dsym;
+    storage_class |= STCconst;
+}
--- a/dmd/declaration.h	Fri Nov 06 21:51:41 2009 +0100
+++ b/dmd/declaration.h	Fri Nov 06 23:58:01 2009 +0100
@@ -1,951 +1,1004 @@
-
-// Compiler implementation of the D programming language
-// Copyright (c) 1999-2008 by Digital Mars
-// All Rights Reserved
-// written by Walter Bright
-// http://www.digitalmars.com
-// License for redistribution is by either the Artistic License
-// in artistic.txt, or the GNU General Public License in gnu.txt.
-// See the included readme.txt for details.
-
-#ifndef DMD_DECLARATION_H
-#define DMD_DECLARATION_H
-
-#ifdef __DMC__
-#pragma once
-#endif /* __DMC__ */
-
-#include <set>
-#include <map>
-#include <string>
-
-#include "dsymbol.h"
-#include "lexer.h"
-#include "mtype.h"
-
-struct Expression;
-struct Statement;
-struct LabelDsymbol;
-struct LabelStatement;
-struct Initializer;
-struct Module;
-struct InlineScanState;
-struct ForeachStatement;
-struct FuncDeclaration;
-struct ExpInitializer;
-struct StructDeclaration;
-struct TupleType;
-struct InterState;
-struct IRState;
-struct AnonDeclaration;
-
-enum PROT;
-enum LINK;
-enum TOK;
-enum MATCH;
-
-enum STC
-{
-    STCundefined    = 0,
-    STCstatic	    = 1,
-    STCextern	    = 2,
-    STCconst	    = 4,
-    STCfinal	    = 8,
-    STCabstract     = 0x10,
-    STCparameter    = 0x20,
-    STCfield	    = 0x40,
-    STCoverride	    = 0x80,
-    STCauto         = 0x100,
-    STCsynchronized = 0x200,
-    STCdeprecated   = 0x400,
-    STCin           = 0x800,		// in parameter
-    STCout          = 0x1000,		// out parameter
-    STClazy	    = 0x2000,		// lazy parameter
-    STCforeach      = 0x4000,		// variable for foreach loop
-    STCcomdat       = 0x8000,		// should go into COMDAT record
-    STCvariadic     = 0x10000,		// variadic function argument
-    STCctorinit     = 0x20000,		// can only be set inside constructor
-    STCtemplateparameter = 0x40000,	// template parameter
-    STCscope	    = 0x80000,		// template parameter
-    STCinvariant    = 0x100000,
-    STCimmutable    = 0x100000,
-    STCref	    = 0x200000,
-    STCinit	    = 0x400000,		// has explicit initializer
-    STCmanifest	    = 0x800000,		// manifest constant
-    STCnodtor	    = 0x1000000,	// don't run destructor
-    STCnothrow	    = 0x2000000,	// never throws exceptions
-    STCpure	    = 0x4000000,	// pure function
-    STCtls	    = 0x8000000,	// thread local
-    STCalias	    = 0x10000000,	// alias parameter
-    STCshared       = 0x20000000,	// accessible from multiple threads
-    STCgshared      = 0x40000000,	// accessible from multiple threads
-					// but not typed as "shared"
-    STC_TYPECTOR    = (STCconst | STCimmutable | STCshared),
-};
-
-struct Match
-{
-    int count;			// number of matches found
-    MATCH last;			// match level of lastf
-    FuncDeclaration *lastf;	// last matching function we found
-    FuncDeclaration *nextf;	// current matching function
-    FuncDeclaration *anyf;	// pick a func, any func, to use for error recovery
-};
-
-void overloadResolveX(Match *m, FuncDeclaration *f, Expressions *arguments, Module* from);
-int overloadApply(Module* from, FuncDeclaration *fstart,
-	int (*fp)(void *, FuncDeclaration *),
-	void *param);
-
-/**************************************************************/
-
-struct Declaration : Dsymbol
-{
-    Type *type;
-    Type *originalType;		// before semantic analysis
-    unsigned storage_class;
-    enum PROT protection;
-    enum LINK linkage;
-    int inuse;			// used to detect cycles
-
-    Declaration(Identifier *id);
-    void semantic(Scope *sc);
-    const char *kind();
-    unsigned size(Loc loc);
-    void checkModify(Loc loc, Scope *sc, Type *t);
-
-    void emitComment(Scope *sc);
-    void toDocBuffer(OutBuffer *buf);
-
-    char *mangle();
-    int isStatic() { return storage_class & STCstatic; }
-    virtual int isStaticConstructor();
-    virtual int isStaticDestructor();
-    virtual int isDelete();
-    virtual int isDataseg();
-    virtual int isCodeseg();
-    int isCtorinit()     { return storage_class & STCctorinit; }
-    int isFinal()        { return storage_class & STCfinal; }
-    int isAbstract()     { return storage_class & STCabstract; }
-    int isConst()        { return storage_class & STCconst; }
-    int isInvariant()    { return 0; }
-    int isAuto()         { return storage_class & STCauto; }
-    int isScope()        { return storage_class & STCscope; }
-    int isSynchronized() { return storage_class & STCsynchronized; }
-    int isParameter()    { return storage_class & STCparameter; }
-    int isDeprecated()   { return storage_class & STCdeprecated; }
-    int isOverride()     { return storage_class & STCoverride; }
-    
-    virtual int isSameAsInitializer() { return isConst(); };
-
-    int isIn()    { return storage_class & STCin; }
-    int isOut()   { return storage_class & STCout; }
-    int isRef()   { return storage_class & STCref; }
-
-    enum PROT prot();
-
-    Declaration *isDeclaration() { return this; }
-
-#if IN_LLVM
-    /// Codegen traversal
-    virtual void codegen(Ir* ir);
-#endif
-};
-
-/**************************************************************/
-
-struct TupleDeclaration : Declaration
-{
-    Objects *objects;
-    int isexp;			// 1: expression tuple
-
-    TypeTuple *tupletype;	// !=NULL if this is a type tuple
-
-    TupleDeclaration(Loc loc, Identifier *ident, Objects *objects);
-    Dsymbol *syntaxCopy(Dsymbol *);
-    const char *kind();
-    Type *getType();
-    int needThis();
-
-    TupleDeclaration *isTupleDeclaration() { return this; }
-
-#if IN_LLVM
-    /// Codegen traversal
-    void codegen(Ir* ir);
-#endif
-};
-
-/**************************************************************/
-
-struct TypedefDeclaration : Declaration
-{
-    Type *basetype;
-    Initializer *init;
-    int sem;			// 0: semantic() has not been run
-				// 1: semantic() is in progress
-				// 2: semantic() has been run
-				// 3: semantic2() has been run
-
-    TypedefDeclaration(Loc loc, Identifier *ident, Type *basetype, Initializer *init);
-    Dsymbol *syntaxCopy(Dsymbol *);
-    void semantic(Scope *sc);
-    void semantic2(Scope *sc);
-    char *mangle();
-    const char *kind();
-    Type *getType();
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-#ifdef _DH
-    Type *htype;
-    Type *hbasetype;
-#endif
-
-    void toDocBuffer(OutBuffer *buf);
-
-#if IN_DMD
-    void toObjFile(int multiobj);			// compile to .obj file
-    void toDebug();
-    int cvMember(unsigned char *p);
-#endif
-
-    TypedefDeclaration *isTypedefDeclaration() { return this; }
-
-#if IN_DMD
-    Symbol *sinit;
-    Symbol *toInitializer();
-#endif
-
-#if IN_LLVM
-    /// Codegen traversal
-    void codegen(Ir* ir);
-#endif
-};
-
-/**************************************************************/
-
-struct AliasDeclaration : Declaration
-{
-    Dsymbol *aliassym;
-    Dsymbol *overnext;		// next in overload list
-    int inSemantic;
-    PROT importprot;	// if generated by import, store its protection
-
-    AliasDeclaration(Loc loc, Identifier *ident, Type *type);
-    AliasDeclaration(Loc loc, Identifier *ident, Dsymbol *s);
-    Dsymbol *syntaxCopy(Dsymbol *);
-    void semantic(Scope *sc);
-    int overloadInsert(Dsymbol *s);
-    const char *kind();
-    Type *getType();
-    Dsymbol *toAlias();
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-#ifdef _DH
-    Type *htype;
-    Dsymbol *haliassym;
-#endif
-
-    void toDocBuffer(OutBuffer *buf);
-
-    AliasDeclaration *isAliasDeclaration() { return this; }
-};
-
-/**************************************************************/
-
-struct VarDeclaration : Declaration
-{
-    Initializer *init;
-    unsigned offset;
-    int noscope;		// no scope semantics
-    int nestedref;		// referenced by a lexically nested function
-    int ctorinit;		// it has been initialized in a ctor
-    int onstack;		// 1: it has been allocated on the stack
-				// 2: on stack, run destructor anyway
-    int canassign;		// it can be assigned to
-    Dsymbol *aliassym;		// if redone as alias to another symbol
-    Expression *value;		// when interpreting, this is the value
-				// (NULL if value not determinable)
-    Scope *scope;		// !=NULL means context to use
-
-    VarDeclaration(Loc loc, Type *t, Identifier *id, Initializer *init);
-    Dsymbol *syntaxCopy(Dsymbol *);
-    void semantic(Scope *sc);
-    void semantic2(Scope *sc);
-    const char *kind();
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-#ifdef _DH
-    Type *htype;
-    Initializer *hinit;
-#endif
-    int needThis();
-    int isImportedSymbol();
-    int isDataseg();
-    int hasPointers();
-    Expression *callScopeDtor();
-    ExpInitializer *getExpInitializer();
-    void checkCtorConstInit();
-    void checkNestedReference(Scope *sc, Loc loc);
-    Dsymbol *toAlias();
-    
-    virtual int isSameAsInitializer();
-
-#if IN_DMD
-    void toObjFile(int multiobj);			// compile to .obj file
-    Symbol *toSymbol();
-    int cvMember(unsigned char *p);
-#endif
-
-    // Eliminate need for dynamic_cast
-    VarDeclaration *isVarDeclaration() { return (VarDeclaration *)this; }
-
-#if IN_LLVM
-    /// Codegen traversal
-    virtual void codegen(Ir* ir);
-
-    /// Index into parent aggregate.
-    /// Set during type generation.
-    unsigned aggrIndex;
-
-    /// Variables that wouldn't have gotten semantic3'ed if we weren't inlining set this flag.
-    bool availableExternally;
-    /// Override added to set above flag.
-    void semantic3(Scope *sc);
-
-    // FIXME: we're not using these anymore!
-    AnonDeclaration* anonDecl;
-    unsigned offset2;
-
-    /// This var is used by a naked function.
-    bool nakedUse;
-#endif
-};
-
-/**************************************************************/
-
-// LDC uses this to denote static struct initializers
-
-struct StaticStructInitDeclaration : Declaration
-{
-    StructDeclaration *dsym;
-
-    StaticStructInitDeclaration(Loc loc, StructDeclaration *dsym);
-
-#if IN_DMD
-    Symbol *toSymbol();
-#endif
-
-    // Eliminate need for dynamic_cast
-    StaticStructInitDeclaration *isStaticStructInitDeclaration() { return (StaticStructInitDeclaration *)this; }
-};
-
-struct ClassInfoDeclaration : VarDeclaration
-{
-    ClassDeclaration *cd;
-
-    ClassInfoDeclaration(ClassDeclaration *cd);
-    Dsymbol *syntaxCopy(Dsymbol *);
-    void semantic(Scope *sc);
-
-    void emitComment(Scope *sc);
-
-#if IN_DMD
-    Symbol *toSymbol();
-#endif
-
-    ClassInfoDeclaration* isClassInfoDeclaration() { return this; }
-};
-
-struct ModuleInfoDeclaration : VarDeclaration
-{
-    Module *mod;
-
-    ModuleInfoDeclaration(Module *mod);
-    Dsymbol *syntaxCopy(Dsymbol *);
-    void semantic(Scope *sc);
-
-    void emitComment(Scope *sc);
-
-#if IN_DMD
-    Symbol *toSymbol();
-#endif
-};
-
-struct TypeInfoDeclaration : VarDeclaration
-{
-    Type *tinfo;
-
-    TypeInfoDeclaration(Type *tinfo, int internal);
-    Dsymbol *syntaxCopy(Dsymbol *);
-    void semantic(Scope *sc);
-
-    void emitComment(Scope *sc);
-
-#if IN_DMD
-    void toObjFile(int multiobj);			// compile to .obj file
-    Symbol *toSymbol();
-    virtual void toDt(dt_t **pdt);
-#endif
-
-    virtual TypeInfoDeclaration* isTypeInfoDeclaration() { return this; }
-
-#if IN_LLVM
-    /// Codegen traversal
-    void codegen(Ir* ir);
-    virtual void llvmDefine();
-#endif
-};
-
-struct TypeInfoStructDeclaration : TypeInfoDeclaration
-{
-    TypeInfoStructDeclaration(Type *tinfo);
-
-#if IN_DMD
-    void toDt(dt_t **pdt);
-#endif
-
-#if IN_LLVM
-    void llvmDefine();
-#endif
-};
-
-struct TypeInfoClassDeclaration : TypeInfoDeclaration
-{
-    TypeInfoClassDeclaration(Type *tinfo);
-
-#if IN_DMD
-    void toDt(dt_t **pdt);
-#endif
-
-#if IN_LLVM
-    void llvmDefine();
-#endif
-};
-
-struct TypeInfoInterfaceDeclaration : TypeInfoDeclaration
-{
-    TypeInfoInterfaceDeclaration(Type *tinfo);
-
-#if IN_DMD
-    void toDt(dt_t **pdt);
-#endif
-
-#if IN_LLVM
-    void llvmDefine();
-#endif
-};
-
-struct TypeInfoTypedefDeclaration : TypeInfoDeclaration
-{
-    TypeInfoTypedefDeclaration(Type *tinfo);
-
-#if IN_DMD
-    void toDt(dt_t **pdt);
-#endif
-
-#if IN_LLVM
-    void llvmDefine();
-#endif
-};
-
-struct TypeInfoPointerDeclaration : TypeInfoDeclaration
-{
-    TypeInfoPointerDeclaration(Type *tinfo);
-
-#if IN_DMD
-    void toDt(dt_t **pdt);
-#endif
-
-#if IN_LLVM
-    void llvmDefine();
-#endif
-};
-
-struct TypeInfoArrayDeclaration : TypeInfoDeclaration
-{
-    TypeInfoArrayDeclaration(Type *tinfo);
-
-#if IN_DMD
-    void toDt(dt_t **pdt);
-#endif
-
-#if IN_LLVM
-    void llvmDefine();
-#endif
-};
-
-struct TypeInfoStaticArrayDeclaration : TypeInfoDeclaration
-{
-    TypeInfoStaticArrayDeclaration(Type *tinfo);
-
-#if IN_DMD
-    void toDt(dt_t **pdt);
-#endif
-
-#if IN_LLVM
-    void llvmDefine();
-#endif
-};
-
-struct TypeInfoAssociativeArrayDeclaration : TypeInfoDeclaration
-{
-    TypeInfoAssociativeArrayDeclaration(Type *tinfo);
-
-#if IN_DMD
-    void toDt(dt_t **pdt);
-#endif
-
-#if IN_LLVM
-    void llvmDefine();
-#endif
-};
-
-struct TypeInfoEnumDeclaration : TypeInfoDeclaration
-{
-    TypeInfoEnumDeclaration(Type *tinfo);
-
-#if IN_DMD
-    void toDt(dt_t **pdt);
-#endif
-
-#if IN_LLVM
-    void llvmDefine();
-#endif
-};
-
-struct TypeInfoFunctionDeclaration : TypeInfoDeclaration
-{
-    TypeInfoFunctionDeclaration(Type *tinfo);
-
-#if IN_DMD
-    void toDt(dt_t **pdt);
-#endif
-
-#if IN_LLVM
-    void llvmDefine();
-#endif
-};
-
-struct TypeInfoDelegateDeclaration : TypeInfoDeclaration
-{
-    TypeInfoDelegateDeclaration(Type *tinfo);
-
-#if IN_DMD
-    void toDt(dt_t **pdt);
-#endif
-
-#if IN_LLVM
-    void llvmDefine();
-#endif
-};
-
-struct TypeInfoTupleDeclaration : TypeInfoDeclaration
-{
-    TypeInfoTupleDeclaration(Type *tinfo);
-
-#if IN_DMD
-    void toDt(dt_t **pdt);
-#endif
-
-#if IN_LLVM
-    void llvmDefine();
-#endif
-};
-
-#if DMDV2
-struct TypeInfoConstDeclaration : TypeInfoDeclaration
-{
-    TypeInfoConstDeclaration(Type *tinfo);
-
-#if IN_DMD
-    void toDt(dt_t **pdt);
-#endif
-
-#if IN_LLVM
-    void llvmDefine();
-#endif
-};
-
-struct TypeInfoInvariantDeclaration : TypeInfoDeclaration
-{
-    TypeInfoInvariantDeclaration(Type *tinfo);
-
-#if IN_DMD
-    void toDt(dt_t **pdt);
-#endif
-
-#if IN_LLVM
-    void llvmDefine();
-#endif
-};
-
-struct TypeInfoSharedDeclaration : TypeInfoDeclaration
-{
-    TypeInfoSharedDeclaration(Type *tinfo);
-
-    void toDt(dt_t **pdt);
-};
-#endif
-
-/**************************************************************/
-
-struct ThisDeclaration : VarDeclaration
-{
-    ThisDeclaration(Loc loc, Type *t);
-    Dsymbol *syntaxCopy(Dsymbol *);
-    ThisDeclaration *isThisDeclaration() { return this; }
-};
-
-enum ILS
-{
-    ILSuninitialized,	// not computed yet
-    ILSno,		// cannot inline
-    ILSyes,		// can inline
-};
-
-/**************************************************************/
-#if DMDV2
-
-enum BUILTIN
-{
-    BUILTINunknown = -1,	// not known if this is a builtin
-    BUILTINnot,			// this is not a builtin
-    BUILTINsin,			// std.math.sin
-    BUILTINcos,			// std.math.cos
-    BUILTINtan,			// std.math.tan
-    BUILTINsqrt,		// std.math.sqrt
-    BUILTINfabs,		// std.math.fabs
-};
-
-Expression *eval_builtin(enum BUILTIN builtin, Expressions *arguments);
-
-#endif
-
-struct FuncDeclaration : Declaration
-{
-    Array *fthrows;			// Array of Type's of exceptions (not used)
-    Statement *frequire;
-    Statement *fensure;
-    Statement *fbody;
-
-    Identifier *outId;			// identifier for out statement
-    VarDeclaration *vresult;		// variable corresponding to outId
-    LabelDsymbol *returnLabel;		// where the return goes
-
-    DsymbolTable *localsymtab;		// used to prevent symbols in different
-					// scopes from having the same name
-    VarDeclaration *vthis;		// 'this' parameter (member and nested)
-    VarDeclaration *v_arguments;	// '_arguments' parameter
-#if IN_GCC
-    VarDeclaration *v_argptr;	        // '_argptr' variable
-#endif
-    Dsymbols *parameters;		// Array of VarDeclaration's for parameters
-    DsymbolTable *labtab;		// statement label symbol table
-    Declaration *overnext;		// next in overload list
-    Loc endloc;				// location of closing curly bracket
-    int vtblIndex;			// for member functions, index into vtbl[]
-    int naked;				// !=0 if naked
-    int inlineAsm;			// !=0 if has inline assembler
-    ILS inlineStatus;
-    int inlineNest;			// !=0 if nested inline
-    int cantInterpret;			// !=0 if cannot interpret function
-    int semanticRun;			// 1 semantic() run
-					// 2 semantic2() run
-					// 3 semantic3() started
-					// 4 semantic3() done
-					// 5 toObjFile() run
-					// this function's frame ptr
-    ForeachStatement *fes;		// if foreach body, this is the foreach
-    int introducing;			// !=0 if 'introducing' function
-    Type *tintro;			// if !=NULL, then this is the type
-					// of the 'introducing' function
-					// this one is overriding
-    int inferRetType;			// !=0 if return type is to be inferred
-    Scope *scope;			// !=NULL means context to use
-
-    // Things that should really go into Scope
-    int hasReturnExp;			// 1 if there's a return exp; statement
-					// 2 if there's a throw statement
-					// 4 if there's an assert(0)
-					// 8 if there's inline asm
-
-    // Support for NRVO (named return value optimization)
-    int nrvo_can;			// !=0 means we can do it
-    VarDeclaration *nrvo_var;		// variable to replace with shidden
-#if IN_DMD
-    Symbol *shidden;			// hidden pointer passed to function
-#endif
-
-#if DMDV2
-    enum BUILTIN builtin;		// set if this is a known, builtin
-					// function we can evaluate at compile
-					// time
-
-    int tookAddressOf;			// set if someone took the address of
-					// this function
-    Dsymbols closureVars;		// local variables in this function
-					// which are referenced by nested
-					// functions
-#else
-    int nestedFrameRef;			// !=0 if nested variables referenced
-#endif
-
-    FuncDeclaration(Loc loc, Loc endloc, Identifier *id, enum STC storage_class, Type *type);
-    Dsymbol *syntaxCopy(Dsymbol *);
-    void semantic(Scope *sc);
-    void semantic2(Scope *sc);
-    void semantic3(Scope *sc);
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-    void bodyToCBuffer(OutBuffer *buf, HdrGenState *hgs);
-    int overrides(FuncDeclaration *fd);
-    int findVtblIndex(Array *vtbl, int dim);
-    int overloadInsert(Dsymbol *s);
-    FuncDeclaration *overloadExactMatch(Type *t, Module* from);
-    FuncDeclaration *overloadResolve(Loc loc, Expressions *arguments, Module* from);
-    LabelDsymbol *searchLabel(Identifier *ident);
-    AggregateDeclaration *isThis();
-    AggregateDeclaration *isMember2();
-    int getLevel(Loc loc, FuncDeclaration *fd);	// lexical nesting level difference
-    void appendExp(Expression *e);
-    void appendState(Statement *s);
-    char *mangle();
-    int isMain();
-    int isWinMain();
-    int isDllMain();
-    int isExport();
-    int isImportedSymbol();
-    int isAbstract();
-    int isCodeseg();
-    virtual int isNested();
-    int needThis();
-    virtual int isVirtual();
-    virtual int isFinal();
-    virtual int addPreInvariant();
-    virtual int addPostInvariant();
-    Expression *interpret(InterState *istate, Expressions *arguments);
-    void inlineScan();
-    int canInline(int hasthis, int hdrscan = 0);
-    Expression *doInline(InlineScanState *iss, Expression *ethis, Array *arguments);
-    const char *kind();
-    void toDocBuffer(OutBuffer *buf);
-
-// LDC: give argument types to runtime functions
-    static FuncDeclaration *genCfunc(Arguments *args, Type *treturn, const char *name);
-    static FuncDeclaration *genCfunc(Arguments *args, Type *treturn, Identifier *id);
-
-#if IN_DMD
-    Symbol *toSymbol();
-    Symbol *toThunkSymbol(int offset);	// thunk version
-    void toObjFile(int multiobj);			// compile to .obj file
-    int cvMember(unsigned char *p);
-#endif
-
-    FuncDeclaration *isFuncDeclaration() { return this; }
-
-#if IN_LLVM
-    // LDC stuff
-
-    /// Codegen traversal
-    void codegen(Ir* ir);
-
-    // vars declared in this function that nested funcs reference
-    // is this is not empty, nestedFrameRef is set and these VarDecls
-    // probably have nestedref set too, see VarDeclaration::checkNestedReference
-    std::set<VarDeclaration*> nestedVars;
-
-    std::string intrinsicName;
-
-    bool isIntrinsic();
-    bool isVaIntrinsic();
-
-    // we keep our own table of label statements as LabelDsymbolS
-    // don't always carry their corresponding statement along ...
-    typedef std::map<const char*, LabelStatement*> LabelMap;
-    LabelMap labmap;
-
-    // if this is an array operation it gets a little special attention
-    bool isArrayOp;
-
-    // Functions that wouldn't have gotten semantic3'ed if we weren't inlining set this flag.
-    bool availableExternally;
-
-    // true if overridden with the pragma(allow_inline); stmt
-    bool allowInlining;
-#endif
-};
-
-struct FuncAliasDeclaration : FuncDeclaration
-{
-    FuncDeclaration *funcalias;
-    PROT importprot;	// if generated by import, store its protection
-    
-    FuncAliasDeclaration(FuncDeclaration *funcalias);
-
-    FuncAliasDeclaration *isFuncAliasDeclaration() { return this; }
-    const char *kind();
-#if IN_DMD
-    Symbol *toSymbol();
-#endif
-};
-
-struct FuncLiteralDeclaration : FuncDeclaration
-{
-    enum TOK tok;			// TOKfunction or TOKdelegate
-
-    FuncLiteralDeclaration(Loc loc, Loc endloc, Type *type, enum TOK tok,
-	ForeachStatement *fes);
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-    Dsymbol *syntaxCopy(Dsymbol *);
-    int isNested();
-    int isVirtual();
-
-    FuncLiteralDeclaration *isFuncLiteralDeclaration() { return this; }
-    const char *kind();
-};
-
-struct CtorDeclaration : FuncDeclaration
-{   Arguments *arguments;
-    int varargs;
-
-    CtorDeclaration(Loc loc, Loc endloc, Arguments *arguments, int varargs);
-    Dsymbol *syntaxCopy(Dsymbol *);
-    void semantic(Scope *sc);
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-    const char *kind();
-    char *toChars();
-    int isVirtual();
-    int addPreInvariant();
-    int addPostInvariant();
-    void toDocBuffer(OutBuffer *buf);
-
-    CtorDeclaration *isCtorDeclaration() { return this; }
-};
-
-#if DMDV2
-struct PostBlitDeclaration : FuncDeclaration
-{
-    PostBlitDeclaration(Loc loc, Loc endloc);
-    PostBlitDeclaration(Loc loc, Loc endloc, Identifier *id);
-    Dsymbol *syntaxCopy(Dsymbol *);
-    void semantic(Scope *sc);
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-    int isVirtual();
-    int addPreInvariant();
-    int addPostInvariant();
-    int overloadInsert(Dsymbol *s);
-    void emitComment(Scope *sc);
-
-    PostBlitDeclaration *isPostBlitDeclaration() { return this; }
-};
-#endif
-
-struct DtorDeclaration : FuncDeclaration
-{
-    DtorDeclaration(Loc loc, Loc endloc);
-    DtorDeclaration(Loc loc, Loc endloc, Identifier *id);
-    Dsymbol *syntaxCopy(Dsymbol *);
-    void semantic(Scope *sc);
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-    int isVirtual();
-    int addPreInvariant();
-    int addPostInvariant();
-    int overloadInsert(Dsymbol *s);
-    void emitComment(Scope *sc);
-
-    DtorDeclaration *isDtorDeclaration() { return this; }
-};
-
-struct StaticCtorDeclaration : FuncDeclaration
-{
-    StaticCtorDeclaration(Loc loc, Loc endloc);
-    Dsymbol *syntaxCopy(Dsymbol *);
-    void semantic(Scope *sc);
-    AggregateDeclaration *isThis();
-    int isStaticConstructor();
-    int isVirtual();
-    int addPreInvariant();
-    int addPostInvariant();
-    void emitComment(Scope *sc);
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-
-    StaticCtorDeclaration *isStaticCtorDeclaration() { return this; }
-};
-
-struct StaticDtorDeclaration : FuncDeclaration
-{   VarDeclaration *vgate;	// 'gate' variable
-
-    StaticDtorDeclaration(Loc loc, Loc endloc);
-    Dsymbol *syntaxCopy(Dsymbol *);
-    void semantic(Scope *sc);
-    AggregateDeclaration *isThis();
-    int isStaticDestructor();
-    int isVirtual();
-    int addPreInvariant();
-    int addPostInvariant();
-    void emitComment(Scope *sc);
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-
-    StaticDtorDeclaration *isStaticDtorDeclaration() { return this; }
-};
-
-struct InvariantDeclaration : FuncDeclaration
-{
-    InvariantDeclaration(Loc loc, Loc endloc);
-    Dsymbol *syntaxCopy(Dsymbol *);
-    void semantic(Scope *sc);
-    int isVirtual();
-    int addPreInvariant();
-    int addPostInvariant();
-    void emitComment(Scope *sc);
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-
-    InvariantDeclaration *isInvariantDeclaration() { return this; }
-};
-
-
-struct UnitTestDeclaration : FuncDeclaration
-{
-    UnitTestDeclaration(Loc loc, Loc endloc);
-    Dsymbol *syntaxCopy(Dsymbol *);
-    void semantic(Scope *sc);
-    AggregateDeclaration *isThis();
-    int isVirtual();
-    int addPreInvariant();
-    int addPostInvariant();
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-
-    UnitTestDeclaration *isUnitTestDeclaration() { return this; }
-};
-
-struct NewDeclaration : FuncDeclaration
-{   Arguments *arguments;
-    int varargs;
-
-    NewDeclaration(Loc loc, Loc endloc, Arguments *arguments, int varargs);
-    Dsymbol *syntaxCopy(Dsymbol *);
-    void semantic(Scope *sc);
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-    const char *kind();
-    int isVirtual();
-    int addPreInvariant();
-    int addPostInvariant();
-
-    NewDeclaration *isNewDeclaration() { return this; }
-};
-
-
-struct DeleteDeclaration : FuncDeclaration
-{   Arguments *arguments;
-
-    DeleteDeclaration(Loc loc, Loc endloc, Arguments *arguments);
-    Dsymbol *syntaxCopy(Dsymbol *);
-    void semantic(Scope *sc);
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-    const char *kind();
-    int isDelete();
-    int isVirtual();
-    int addPreInvariant();
-    int addPostInvariant();
-#ifdef _DH
-    DeleteDeclaration *isDeleteDeclaration() { return this; }
-#endif
-};
-
-#endif /* DMD_DECLARATION_H */
+
+// Compiler implementation of the D programming language
+// Copyright (c) 1999-2009 by Digital Mars
+// All Rights Reserved
+// written by Walter Bright
+// http://www.digitalmars.com
+// License for redistribution is by either the Artistic License
+// in artistic.txt, or the GNU General Public License in gnu.txt.
+// See the included readme.txt for details.
+
+#ifndef DMD_DECLARATION_H
+#define DMD_DECLARATION_H
+
+#ifdef __DMC__
+#pragma once
+#endif /* __DMC__ */
+
+#include <set>
+#include <map>
+#include <string>
+
+#include "dsymbol.h"
+#include "lexer.h"
+#include "mtype.h"
+
+struct Expression;
+struct Statement;
+struct LabelDsymbol;
+struct LabelStatement;
+struct Initializer;
+struct Module;
+struct InlineScanState;
+struct ForeachStatement;
+struct FuncDeclaration;
+struct ExpInitializer;
+struct StructDeclaration;
+struct TupleType;
+struct InterState;
+struct IRState;
+struct AnonDeclaration;
+
+enum PROT;
+enum LINK;
+enum TOK;
+enum MATCH;
+
+enum STC
+{
+    STCundefined    = 0,
+    STCstatic	    = 1,
+    STCextern	    = 2,
+    STCconst	    = 4,
+    STCfinal	    = 8,
+    STCabstract     = 0x10,
+    STCparameter    = 0x20,
+    STCfield	    = 0x40,
+    STCoverride	    = 0x80,
+    STCauto         = 0x100,
+    STCsynchronized = 0x200,
+    STCdeprecated   = 0x400,
+    STCin           = 0x800,		// in parameter
+    STCout          = 0x1000,		// out parameter
+    STClazy	    = 0x2000,		// lazy parameter
+    STCforeach      = 0x4000,		// variable for foreach loop
+    STCcomdat       = 0x8000,		// should go into COMDAT record
+    STCvariadic     = 0x10000,		// variadic function argument
+    STCctorinit     = 0x20000,		// can only be set inside constructor
+    STCtemplateparameter = 0x40000,	// template parameter
+    STCscope	    = 0x80000,		// template parameter
+    STCinvariant    = 0x100000,
+    STCimmutable    = 0x100000,
+    STCref	    = 0x200000,
+    STCinit	    = 0x400000,		// has explicit initializer
+    STCmanifest	    = 0x800000,		// manifest constant
+    STCnodtor	    = 0x1000000,	// don't run destructor
+    STCnothrow	    = 0x2000000,	// never throws exceptions
+    STCpure	    = 0x4000000,	// pure function
+    STCtls	    = 0x8000000,	// thread local
+    STCalias	    = 0x10000000,	// alias parameter
+    STCshared       = 0x20000000,	// accessible from multiple threads
+    STCgshared      = 0x40000000,	// accessible from multiple threads
+					// but not typed as "shared"
+    STC_TYPECTOR    = (STCconst | STCimmutable | STCshared),
+};
+
+struct Match
+{
+    int count;			// number of matches found
+    MATCH last;			// match level of lastf
+    FuncDeclaration *lastf;	// last matching function we found
+    FuncDeclaration *nextf;	// current matching function
+    FuncDeclaration *anyf;	// pick a func, any func, to use for error recovery
+};
+
+void overloadResolveX(Match *m, FuncDeclaration *f,
+	Expression *ethis, Expressions *arguments, Module *from);
+int overloadApply(Module* from, FuncDeclaration *fstart,
+	int (*fp)(void *, FuncDeclaration *),
+	void *param);
+
+/**************************************************************/
+
+struct Declaration : Dsymbol
+{
+    Type *type;
+    Type *originalType;		// before semantic analysis
+    unsigned storage_class;
+    enum PROT protection;
+    enum LINK linkage;
+    int inuse;			// used to detect cycles
+
+    Declaration(Identifier *id);
+    void semantic(Scope *sc);
+    const char *kind();
+    unsigned size(Loc loc);
+    void checkModify(Loc loc, Scope *sc, Type *t);
+
+    void emitComment(Scope *sc);
+    void toJsonBuffer(OutBuffer *buf);
+    void toDocBuffer(OutBuffer *buf);
+
+    char *mangle();
+    int isStatic() { return storage_class & STCstatic; }
+    virtual int isStaticConstructor();
+    virtual int isStaticDestructor();
+    virtual int isDelete();
+    virtual int isDataseg();
+    virtual int isThreadlocal();
+    virtual int isCodeseg();
+    int isCtorinit()     { return storage_class & STCctorinit; }
+    int isFinal()        { return storage_class & STCfinal; }
+    int isAbstract()     { return storage_class & STCabstract; }
+    int isConst()        { return storage_class & STCconst; }
+    int isInvariant()    { return storage_class & STCinvariant; }
+    int isAuto()         { return storage_class & STCauto; }
+    int isScope()        { return storage_class & STCscope; }
+    int isSynchronized() { return storage_class & STCsynchronized; }
+    int isParameter()    { return storage_class & STCparameter; }
+    int isDeprecated()   { return storage_class & STCdeprecated; }
+    int isOverride()     { return storage_class & STCoverride; }
+    
+    virtual int isSameAsInitializer() { return isConst(); };
+
+    int isIn()    { return storage_class & STCin; }
+    int isOut()   { return storage_class & STCout; }
+    int isRef()   { return storage_class & STCref; }
+
+    enum PROT prot();
+
+    Declaration *isDeclaration() { return this; }
+
+#if IN_LLVM
+    /// Codegen traversal
+    virtual void codegen(Ir* ir);
+#endif
+};
+
+/**************************************************************/
+
+struct TupleDeclaration : Declaration
+{
+    Objects *objects;
+    int isexp;			// 1: expression tuple
+
+    TypeTuple *tupletype;	// !=NULL if this is a type tuple
+
+    TupleDeclaration(Loc loc, Identifier *ident, Objects *objects);
+    Dsymbol *syntaxCopy(Dsymbol *);
+    const char *kind();
+    Type *getType();
+    int needThis();
+
+    TupleDeclaration *isTupleDeclaration() { return this; }
+
+#if IN_LLVM
+    /// Codegen traversal
+    void codegen(Ir* ir);
+#endif
+};
+
+/**************************************************************/
+
+struct TypedefDeclaration : Declaration
+{
+    Type *basetype;
+    Initializer *init;
+    int sem;			// 0: semantic() has not been run
+				// 1: semantic() is in progress
+				// 2: semantic() has been run
+				// 3: semantic2() has been run
+
+    TypedefDeclaration(Loc loc, Identifier *ident, Type *basetype, Initializer *init);
+    Dsymbol *syntaxCopy(Dsymbol *);
+    void semantic(Scope *sc);
+    void semantic2(Scope *sc);
+    char *mangle();
+    const char *kind();
+    Type *getType();
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+#ifdef _DH
+    Type *htype;
+    Type *hbasetype;
+#endif
+
+    void toDocBuffer(OutBuffer *buf);
+
+#if IN_DMD
+    void toObjFile(int multiobj);			// compile to .obj file
+    void toDebug();
+    int cvMember(unsigned char *p);
+#endif
+
+    TypedefDeclaration *isTypedefDeclaration() { return this; }
+
+#if IN_DMD
+    Symbol *sinit;
+    Symbol *toInitializer();
+#endif
+
+#if IN_LLVM
+    /// Codegen traversal
+    void codegen(Ir* ir);
+#endif
+};
+
+/**************************************************************/
+
+struct AliasDeclaration : Declaration
+{
+    Dsymbol *aliassym;
+    Dsymbol *overnext;		// next in overload list
+    int inSemantic;
+    PROT importprot;	// if generated by import, store its protection
+
+    AliasDeclaration(Loc loc, Identifier *ident, Type *type);
+    AliasDeclaration(Loc loc, Identifier *ident, Dsymbol *s);
+    Dsymbol *syntaxCopy(Dsymbol *);
+    void semantic(Scope *sc);
+    int overloadInsert(Dsymbol *s);
+    const char *kind();
+    Type *getType();
+    Dsymbol *toAlias();
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+#ifdef _DH
+    Type *htype;
+    Dsymbol *haliassym;
+#endif
+
+    void toDocBuffer(OutBuffer *buf);
+
+    AliasDeclaration *isAliasDeclaration() { return this; }
+};
+
+/**************************************************************/
+
+struct VarDeclaration : Declaration
+{
+    Initializer *init;
+    unsigned offset;
+    int noscope;		// no scope semantics
+#if DMDV2
+    FuncDeclarations nestedrefs; // referenced by these lexically nested functions
+#else
+    int nestedref;		// referenced by a lexically nested function
+#endif
+    int ctorinit;		// it has been initialized in a ctor
+    int onstack;		// 1: it has been allocated on the stack
+				// 2: on stack, run destructor anyway
+    int canassign;		// it can be assigned to
+    Dsymbol *aliassym;		// if redone as alias to another symbol
+    Expression *value;		// when interpreting, this is the value
+				// (NULL if value not determinable)
+#if DMDV2
+    VarDeclaration *rundtor;	// if !NULL, rundtor is tested at runtime to see
+				// if the destructor should be run. Used to prevent
+				// dtor calls on postblitted vars
+#endif
+
+    VarDeclaration(Loc loc, Type *t, Identifier *id, Initializer *init);
+    Dsymbol *syntaxCopy(Dsymbol *);
+    void semantic(Scope *sc);
+    void semantic2(Scope *sc);
+    const char *kind();
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+#ifdef _DH
+    Type *htype;
+    Initializer *hinit;
+#endif
+    int needThis();
+    int isImportedSymbol();
+    int isDataseg();
+    int isThreadlocal();
+    int hasPointers();
+#if DMDV2
+    int canTakeAddressOf();
+    int needsAutoDtor();
+#endif
+    Expression *callScopeDtor(Scope *sc);
+    ExpInitializer *getExpInitializer();
+    Expression *getConstInitializer();
+    void checkCtorConstInit();
+    void checkNestedReference(Scope *sc, Loc loc);
+    Dsymbol *toAlias();
+    
+    virtual int isSameAsInitializer();
+
+#if IN_DMD
+    void toObjFile(int multiobj);			// compile to .obj file
+    Symbol *toSymbol();
+    int cvMember(unsigned char *p);
+#endif
+
+    // Eliminate need for dynamic_cast
+    VarDeclaration *isVarDeclaration() { return (VarDeclaration *)this; }
+
+#if IN_LLVM
+    /// Codegen traversal
+    virtual void codegen(Ir* ir);
+
+    /// Index into parent aggregate.
+    /// Set during type generation.
+    unsigned aggrIndex;
+
+    /// Variables that wouldn't have gotten semantic3'ed if we weren't inlining set this flag.
+    bool availableExternally;
+    /// Override added to set above flag.
+    void semantic3(Scope *sc);
+
+    // FIXME: we're not using these anymore!
+    AnonDeclaration* anonDecl;
+    unsigned offset2;
+
+    /// This var is used by a naked function.
+    bool nakedUse;
+#endif
+};
+
+/**************************************************************/
+
+// LDC uses this to denote static struct initializers
+
+struct StaticStructInitDeclaration : Declaration
+{
+    StructDeclaration *dsym;
+
+    StaticStructInitDeclaration(Loc loc, StructDeclaration *dsym);
+
+#if IN_DMD
+    Symbol *toSymbol();
+#endif
+
+    // Eliminate need for dynamic_cast
+    StaticStructInitDeclaration *isStaticStructInitDeclaration() { return (StaticStructInitDeclaration *)this; }
+};
+
+struct ClassInfoDeclaration : VarDeclaration
+{
+    ClassDeclaration *cd;
+
+    ClassInfoDeclaration(ClassDeclaration *cd);
+    Dsymbol *syntaxCopy(Dsymbol *);
+    void semantic(Scope *sc);
+
+    void emitComment(Scope *sc);
+    void toJsonBuffer(OutBuffer *buf);
+
+#if IN_DMD
+    Symbol *toSymbol();
+#endif
+
+    ClassInfoDeclaration* isClassInfoDeclaration() { return this; }
+};
+
+struct ModuleInfoDeclaration : VarDeclaration
+{
+    Module *mod;
+
+    ModuleInfoDeclaration(Module *mod);
+    Dsymbol *syntaxCopy(Dsymbol *);
+    void semantic(Scope *sc);
+
+    void emitComment(Scope *sc);
+    void toJsonBuffer(OutBuffer *buf);
+
+#if IN_DMD
+    Symbol *toSymbol();
+#endif
+};
+
+struct TypeInfoDeclaration : VarDeclaration
+{
+    Type *tinfo;
+
+    TypeInfoDeclaration(Type *tinfo, int internal);
+    Dsymbol *syntaxCopy(Dsymbol *);
+    void semantic(Scope *sc);
+
+    void emitComment(Scope *sc);
+    void toJsonBuffer(OutBuffer *buf);
+
+#if IN_DMD
+    void toObjFile(int multiobj);			// compile to .obj file
+    Symbol *toSymbol();
+    virtual void toDt(dt_t **pdt);
+#endif
+
+    virtual TypeInfoDeclaration* isTypeInfoDeclaration() { return this; }
+
+#if IN_LLVM
+    /// Codegen traversal
+    void codegen(Ir* ir);
+    virtual void llvmDefine();
+#endif
+};
+
+struct TypeInfoStructDeclaration : TypeInfoDeclaration
+{
+    TypeInfoStructDeclaration(Type *tinfo);
+
+#if IN_DMD
+    void toDt(dt_t **pdt);
+#endif
+
+#if IN_LLVM
+    void llvmDefine();
+#endif
+};
+
+struct TypeInfoClassDeclaration : TypeInfoDeclaration
+{
+    TypeInfoClassDeclaration(Type *tinfo);
+
+#if IN_DMD
+    void toDt(dt_t **pdt);
+#endif
+
+#if IN_LLVM
+    void llvmDefine();
+#endif
+};
+
+struct TypeInfoInterfaceDeclaration : TypeInfoDeclaration
+{
+    TypeInfoInterfaceDeclaration(Type *tinfo);
+
+#if IN_DMD
+    void toDt(dt_t **pdt);
+#endif
+
+#if IN_LLVM
+    void llvmDefine();
+#endif
+};
+
+struct TypeInfoTypedefDeclaration : TypeInfoDeclaration
+{
+    TypeInfoTypedefDeclaration(Type *tinfo);
+
+#if IN_DMD
+    void toDt(dt_t **pdt);
+#endif
+
+#if IN_LLVM
+    void llvmDefine();
+#endif
+};
+
+struct TypeInfoPointerDeclaration : TypeInfoDeclaration
+{
+    TypeInfoPointerDeclaration(Type *tinfo);
+
+#if IN_DMD
+    void toDt(dt_t **pdt);
+#endif
+
+#if IN_LLVM
+    void llvmDefine();
+#endif
+};
+
+struct TypeInfoArrayDeclaration : TypeInfoDeclaration
+{
+    TypeInfoArrayDeclaration(Type *tinfo);
+
+#if IN_DMD
+    void toDt(dt_t **pdt);
+#endif
+
+#if IN_LLVM
+    void llvmDefine();
+#endif
+};
+
+struct TypeInfoStaticArrayDeclaration : TypeInfoDeclaration
+{
+    TypeInfoStaticArrayDeclaration(Type *tinfo);
+
+#if IN_DMD
+    void toDt(dt_t **pdt);
+#endif
+
+#if IN_LLVM
+    void llvmDefine();
+#endif
+};
+
+struct TypeInfoAssociativeArrayDeclaration : TypeInfoDeclaration
+{
+    TypeInfoAssociativeArrayDeclaration(Type *tinfo);
+
+#if IN_DMD
+    void toDt(dt_t **pdt);
+#endif
+
+#if IN_LLVM
+    void llvmDefine();
+#endif
+};
+
+struct TypeInfoEnumDeclaration : TypeInfoDeclaration
+{
+    TypeInfoEnumDeclaration(Type *tinfo);
+
+#if IN_DMD
+    void toDt(dt_t **pdt);
+#endif
+
+#if IN_LLVM
+    void llvmDefine();
+#endif
+};
+
+struct TypeInfoFunctionDeclaration : TypeInfoDeclaration
+{
+    TypeInfoFunctionDeclaration(Type *tinfo);
+
+#if IN_DMD
+    void toDt(dt_t **pdt);
+#endif
+
+#if IN_LLVM
+    void llvmDefine();
+#endif
+};
+
+struct TypeInfoDelegateDeclaration : TypeInfoDeclaration
+{
+    TypeInfoDelegateDeclaration(Type *tinfo);
+
+#if IN_DMD
+    void toDt(dt_t **pdt);
+#endif
+
+#if IN_LLVM
+    void llvmDefine();
+#endif
+};
+
+struct TypeInfoTupleDeclaration : TypeInfoDeclaration
+{
+    TypeInfoTupleDeclaration(Type *tinfo);
+
+#if IN_DMD
+    void toDt(dt_t **pdt);
+#endif
+
+#if IN_LLVM
+    void llvmDefine();
+#endif
+};
+
+#if DMDV2
+struct TypeInfoConstDeclaration : TypeInfoDeclaration
+{
+    TypeInfoConstDeclaration(Type *tinfo);
+
+#if IN_DMD
+    void toDt(dt_t **pdt);
+#endif
+
+#if IN_LLVM
+    void llvmDefine();
+#endif
+};
+
+struct TypeInfoInvariantDeclaration : TypeInfoDeclaration
+{
+    TypeInfoInvariantDeclaration(Type *tinfo);
+
+#if IN_DMD
+    void toDt(dt_t **pdt);
+#endif
+
+#if IN_LLVM
+    void llvmDefine();
+#endif
+};
+
+struct TypeInfoSharedDeclaration : TypeInfoDeclaration
+{
+    TypeInfoSharedDeclaration(Type *tinfo);
+
+    void toDt(dt_t **pdt);
+};
+#endif
+
+/**************************************************************/
+
+struct ThisDeclaration : VarDeclaration
+{
+    ThisDeclaration(Loc loc, Type *t);
+    Dsymbol *syntaxCopy(Dsymbol *);
+    ThisDeclaration *isThisDeclaration() { return this; }
+};
+
+enum ILS
+{
+    ILSuninitialized,	// not computed yet
+    ILSno,		// cannot inline
+    ILSyes,		// can inline
+};
+
+/**************************************************************/
+#if DMDV2
+
+enum BUILTIN
+{
+    BUILTINunknown = -1,	// not known if this is a builtin
+    BUILTINnot,			// this is not a builtin
+    BUILTINsin,			// std.math.sin
+    BUILTINcos,			// std.math.cos
+    BUILTINtan,			// std.math.tan
+    BUILTINsqrt,		// std.math.sqrt
+    BUILTINfabs,		// std.math.fabs
+};
+
+Expression *eval_builtin(enum BUILTIN builtin, Expressions *arguments);
+
+#else
+enum BUILTIN { };
+#endif
+
+struct FuncDeclaration : Declaration
+{
+    Array *fthrows;			// Array of Type's of exceptions (not used)
+    Statement *frequire;
+    Statement *fensure;
+    Statement *fbody;
+
+    FuncDeclarations foverrides;	// functions this function overrides
+    FuncDeclaration *fdrequire;		// function that does the in contract
+    FuncDeclaration *fdensure;		// function that does the out contract
+
+    Identifier *outId;			// identifier for out statement
+    VarDeclaration *vresult;		// variable corresponding to outId
+    LabelDsymbol *returnLabel;		// where the return goes
+
+    DsymbolTable *localsymtab;		// used to prevent symbols in different
+					// scopes from having the same name
+    VarDeclaration *vthis;		// 'this' parameter (member and nested)
+    VarDeclaration *v_arguments;	// '_arguments' parameter
+#if IN_GCC
+    VarDeclaration *v_argptr;	        // '_argptr' variable
+#endif
+    Dsymbols *parameters;		// Array of VarDeclaration's for parameters
+    DsymbolTable *labtab;		// statement label symbol table
+    Declaration *overnext;		// next in overload list
+    Loc endloc;				// location of closing curly bracket
+    int vtblIndex;			// for member functions, index into vtbl[]
+    int naked;				// !=0 if naked
+    int inlineAsm;			// !=0 if has inline assembler
+    ILS inlineStatus;
+    int inlineNest;			// !=0 if nested inline
+    int cantInterpret;			// !=0 if cannot interpret function
+    int semanticRun;			// 1 semantic() run
+					// 2 semantic2() run
+					// 3 semantic3() started
+					// 4 semantic3() done
+					// 5 toObjFile() run
+					// this function's frame ptr
+    ForeachStatement *fes;		// if foreach body, this is the foreach
+    int introducing;			// !=0 if 'introducing' function
+    Type *tintro;			// if !=NULL, then this is the type
+					// of the 'introducing' function
+					// this one is overriding
+    int inferRetType;			// !=0 if return type is to be inferred
+
+    // Things that should really go into Scope
+    int hasReturnExp;			// 1 if there's a return exp; statement
+					// 2 if there's a throw statement
+					// 4 if there's an assert(0)
+					// 8 if there's inline asm
+
+    // Support for NRVO (named return value optimization)
+    int nrvo_can;			// !=0 means we can do it
+    VarDeclaration *nrvo_var;		// variable to replace with shidden
+#if IN_DMD
+    Symbol *shidden;			// hidden pointer passed to function
+#endif
+
+#if DMDV2
+    enum BUILTIN builtin;		// set if this is a known, builtin
+					// function we can evaluate at compile
+					// time
+
+    int tookAddressOf;			// set if someone took the address of
+					// this function
+    Dsymbols closureVars;		// local variables in this function
+					// which are referenced by nested
+					// functions
+#else
+    int nestedFrameRef;			// !=0 if nested variables referenced
+#endif
+
+    FuncDeclaration(Loc loc, Loc endloc, Identifier *id, enum STC storage_class, Type *type);
+    Dsymbol *syntaxCopy(Dsymbol *);
+    void semantic(Scope *sc);
+    void semantic2(Scope *sc);
+    void semantic3(Scope *sc);
+    // called from semantic3
+    void varArgs(Scope *sc, TypeFunction*, VarDeclaration *&, VarDeclaration *&);
+
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+    void bodyToCBuffer(OutBuffer *buf, HdrGenState *hgs);
+    int overrides(FuncDeclaration *fd);
+    int findVtblIndex(Array *vtbl, int dim);
+    int overloadInsert(Dsymbol *s);
+    FuncDeclaration *overloadExactMatch(Type *t, Module* from);
+    FuncDeclaration *overloadResolve(Loc loc, Expression *ethis, Expressions *arguments, Module *from, int flags = 0);
+    MATCH leastAsSpecialized(FuncDeclaration *g);
+    LabelDsymbol *searchLabel(Identifier *ident);
+    AggregateDeclaration *isThis();
+    AggregateDeclaration *isMember2();
+    int getLevel(Loc loc, FuncDeclaration *fd);	// lexical nesting level difference
+    void appendExp(Expression *e);
+    void appendState(Statement *s);
+    char *mangle();
+    const char *toPrettyChars();
+    int isMain();
+    int isWinMain();
+    int isDllMain();
+    enum BUILTIN isBuiltin();
+    int isExport();
+    int isImportedSymbol();
+    int isAbstract();
+    int isCodeseg();
+    int isOverloadable();
+    int isPure();
+    virtual int isNested();
+    int needThis();
+    virtual int isVirtual();
+    virtual int isFinal();
+    virtual int addPreInvariant();
+    virtual int addPostInvariant();
+    Expression *interpret(InterState *istate, Expressions *arguments, Expression *thisexp = NULL);
+    void inlineScan();
+    int canInline(int hasthis, int hdrscan = 0);
+    Expression *doInline(InlineScanState *iss, Expression *ethis, Array *arguments);
+    const char *kind();
+    void toDocBuffer(OutBuffer *buf);
+    FuncDeclaration *isUnique();
+    int needsClosure();
+    Statement *mergeFrequire(Statement *);
+    Statement *mergeFensure(Statement *);
+
+// LDC: give argument types to runtime functions
+    static FuncDeclaration *genCfunc(Arguments *args, Type *treturn, const char *name);
+    static FuncDeclaration *genCfunc(Arguments *args, Type *treturn, Identifier *id);
+
+#if IN_DMD
+    Symbol *toSymbol();
+    Symbol *toThunkSymbol(int offset);	// thunk version
+    void toObjFile(int multiobj);			// compile to .obj file
+    int cvMember(unsigned char *p);
+    void buildClosure(IRState *irs);
+#endif
+
+    FuncDeclaration *isFuncDeclaration() { return this; }
+
+#if IN_LLVM
+    // LDC stuff
+
+    /// Codegen traversal
+    void codegen(Ir* ir);
+
+    // vars declared in this function that nested funcs reference
+    // is this is not empty, nestedFrameRef is set and these VarDecls
+    // probably have nestedref set too, see VarDeclaration::checkNestedReference
+    std::set<VarDeclaration*> nestedVars;
+
+    std::string intrinsicName;
+
+    bool isIntrinsic();
+    bool isVaIntrinsic();
+
+    // we keep our own table of label statements as LabelDsymbolS
+    // don't always carry their corresponding statement along ...
+    typedef std::map<const char*, LabelStatement*> LabelMap;
+    LabelMap labmap;
+
+    // if this is an array operation it gets a little special attention
+    bool isArrayOp;
+
+    // Functions that wouldn't have gotten semantic3'ed if we weren't inlining set this flag.
+    bool availableExternally;
+
+    // true if overridden with the pragma(allow_inline); stmt
+    bool allowInlining;
+#endif
+};
+
+#if DMDV2
+FuncDeclaration *resolveFuncCall(Scope *sc, Loc loc, Dsymbol *s,
+	Objects *tiargs,
+	Expression *ethis,
+	Expressions *arguments,
+	int flags);
+#endif
+
+struct FuncAliasDeclaration : FuncDeclaration
+{
+    FuncDeclaration *funcalias;
+    PROT importprot;	// if generated by import, store its protection
+    
+    FuncAliasDeclaration(FuncDeclaration *funcalias);
+
+    FuncAliasDeclaration *isFuncAliasDeclaration() { return this; }
+    const char *kind();
+#if IN_DMD
+    Symbol *toSymbol();
+#endif
+};
+
+struct FuncLiteralDeclaration : FuncDeclaration
+{
+    enum TOK tok;			// TOKfunction or TOKdelegate
+
+    FuncLiteralDeclaration(Loc loc, Loc endloc, Type *type, enum TOK tok,
+	ForeachStatement *fes);
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+    Dsymbol *syntaxCopy(Dsymbol *);
+    int isNested();
+    int isVirtual();
+
+    FuncLiteralDeclaration *isFuncLiteralDeclaration() { return this; }
+    const char *kind();
+};
+
+struct CtorDeclaration : FuncDeclaration
+{   Arguments *arguments;
+    int varargs;
+
+    CtorDeclaration(Loc loc, Loc endloc, Arguments *arguments, int varargs);
+    Dsymbol *syntaxCopy(Dsymbol *);
+    void semantic(Scope *sc);
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+    const char *kind();
+    char *toChars();
+    int isVirtual();
+    int addPreInvariant();
+    int addPostInvariant();
+    void toDocBuffer(OutBuffer *buf);
+
+    CtorDeclaration *isCtorDeclaration() { return this; }
+};
+
+#if DMDV2
+struct PostBlitDeclaration : FuncDeclaration
+{
+    PostBlitDeclaration(Loc loc, Loc endloc);
+    PostBlitDeclaration(Loc loc, Loc endloc, Identifier *id);
+    Dsymbol *syntaxCopy(Dsymbol *);
+    void semantic(Scope *sc);
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+    int isVirtual();
+    int addPreInvariant();
+    int addPostInvariant();
+    int overloadInsert(Dsymbol *s);
+    void emitComment(Scope *sc);
+    void toJsonBuffer(OutBuffer *buf);
+
+    PostBlitDeclaration *isPostBlitDeclaration() { return this; }
+};
+#endif
+
+struct DtorDeclaration : FuncDeclaration
+{
+    DtorDeclaration(Loc loc, Loc endloc);
+    DtorDeclaration(Loc loc, Loc endloc, Identifier *id);
+    Dsymbol *syntaxCopy(Dsymbol *);
+    void semantic(Scope *sc);
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+    const char *kind();
+    char *toChars();
+    int isVirtual();
+    int addPreInvariant();
+    int addPostInvariant();
+    int overloadInsert(Dsymbol *s);
+    void emitComment(Scope *sc);
+    void toJsonBuffer(OutBuffer *buf);
+
+    DtorDeclaration *isDtorDeclaration() { return this; }
+};
+
+struct StaticCtorDeclaration : FuncDeclaration
+{
+    StaticCtorDeclaration(Loc loc, Loc endloc);
+    Dsymbol *syntaxCopy(Dsymbol *);
+    void semantic(Scope *sc);
+    AggregateDeclaration *isThis();
+    int isStaticConstructor();
+    int isVirtual();
+    int addPreInvariant();
+    int addPostInvariant();
+    void emitComment(Scope *sc);
+    void toJsonBuffer(OutBuffer *buf);
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+
+    StaticCtorDeclaration *isStaticCtorDeclaration() { return this; }
+};
+
+struct StaticDtorDeclaration : FuncDeclaration
+{   VarDeclaration *vgate;	// 'gate' variable
+
+    StaticDtorDeclaration(Loc loc, Loc endloc);
+    Dsymbol *syntaxCopy(Dsymbol *);
+    void semantic(Scope *sc);
+    AggregateDeclaration *isThis();
+    int isStaticDestructor();
+    int isVirtual();
+    int addPreInvariant();
+    int addPostInvariant();
+    void emitComment(Scope *sc);
+    void toJsonBuffer(OutBuffer *buf);
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+
+    StaticDtorDeclaration *isStaticDtorDeclaration() { return this; }
+};
+
+struct InvariantDeclaration : FuncDeclaration
+{
+    InvariantDeclaration(Loc loc, Loc endloc);
+    Dsymbol *syntaxCopy(Dsymbol *);
+    void semantic(Scope *sc);
+    int isVirtual();
+    int addPreInvariant();
+    int addPostInvariant();
+    void emitComment(Scope *sc);
+    void toJsonBuffer(OutBuffer *buf);
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+
+    InvariantDeclaration *isInvariantDeclaration() { return this; }
+};
+
+
+struct UnitTestDeclaration : FuncDeclaration
+{
+    UnitTestDeclaration(Loc loc, Loc endloc);
+    Dsymbol *syntaxCopy(Dsymbol *);
+    void semantic(Scope *sc);
+    AggregateDeclaration *isThis();
+    int isVirtual();
+    int addPreInvariant();
+    int addPostInvariant();
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+
+    UnitTestDeclaration *isUnitTestDeclaration() { return this; }
+};
+
+struct NewDeclaration : FuncDeclaration
+{   Arguments *arguments;
+    int varargs;
+
+    NewDeclaration(Loc loc, Loc endloc, Arguments *arguments, int varargs);
+    Dsymbol *syntaxCopy(Dsymbol *);
+    void semantic(Scope *sc);
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+    const char *kind();
+    int isVirtual();
+    int addPreInvariant();
+    int addPostInvariant();
+
+    NewDeclaration *isNewDeclaration() { return this; }
+};
+
+
+struct DeleteDeclaration : FuncDeclaration
+{   Arguments *arguments;
+
+    DeleteDeclaration(Loc loc, Loc endloc, Arguments *arguments);
+    Dsymbol *syntaxCopy(Dsymbol *);
+    void semantic(Scope *sc);
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+    const char *kind();
+    int isDelete();
+    int isVirtual();
+    int addPreInvariant();
+    int addPostInvariant();
+#ifdef _DH
+    DeleteDeclaration *isDeleteDeclaration() { return this; }
+#endif
+};
+
+#endif /* DMD_DECLARATION_H */
--- a/dmd/doc.c	Fri Nov 06 21:51:41 2009 +0100
+++ b/dmd/doc.c	Fri Nov 06 23:58:01 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
@@ -33,6 +33,7 @@
 #include "hdrgen.h"
 #include "doc.h"
 #include "mtype.h"
+#include "utf.h"
 
 struct Escape
 {
@@ -89,14 +90,18 @@
 int icmp(const char *stringz, void *s, size_t slen);
 int isDitto(unsigned char *comment);
 unsigned char *skipwhitespace(unsigned char *p);
-unsigned skiptoident(OutBuffer *buf, unsigned i);
-unsigned skippastident(OutBuffer *buf, unsigned i);
-unsigned skippastURL(OutBuffer *buf, unsigned i);
+unsigned skiptoident(OutBuffer *buf, size_t i);
+unsigned skippastident(OutBuffer *buf, size_t i);
+unsigned skippastURL(OutBuffer *buf, size_t i);
 void highlightText(Scope *sc, Dsymbol *s, OutBuffer *buf, unsigned offset);
 void highlightCode(Scope *sc, Dsymbol *s, OutBuffer *buf, unsigned offset);
 void highlightCode2(Scope *sc, Dsymbol *s, OutBuffer *buf, unsigned offset);
 Argument *isFunctionParameter(Dsymbol *s, unsigned char *p, unsigned len);
 
+int isIdStart(unsigned char *p);
+int isIdTail(unsigned char *p);
+int utfStride(unsigned char *p);
+
 static unsigned char ddoc_default[] = "\
 DDOC =	<html><head>\n\
 	<META http-equiv=\"content-type\" content=\"text/html; charset=utf-8\">\n\
@@ -238,7 +243,7 @@
     // Generate predefined macros
 
     // Set the title to be the name of the module
-    {	char *p = toPrettyChars();
+    {	const char *p = toPrettyChars();
 	Macro::define(&macrotable, (unsigned char *)"TITLE", 5, (unsigned char *)p, strlen(p));
     }
 
@@ -674,7 +679,7 @@
 	    buf->writestring("const ");
 #if DMDV2
 	if (d->isInvariant())
-	    buf->writestring("invariant ");
+	    buf->writestring("immutable ");
 #endif
 	if (d->isFinal())
 	    buf->writestring("final ");
@@ -948,7 +953,6 @@
 {   unsigned char *p;
     unsigned char *pstart;
     unsigned char *pend;
-    unsigned char *q;
     unsigned char *idstart;
     unsigned idlen;
 
@@ -963,17 +967,32 @@
 	pstart = p;
 
 	/* Find end of section, which is ended by one of:
-	 *	'identifier:'
+	 *	'identifier:' (but not inside a code section)
 	 *	'\0'
 	 */
 	idlen = 0;
+	int inCode = 0;
 	while (1)
 	{
-	    if (isalpha(*p) || *p == '_')
+	    // Check for start/end of a code section
+	    if (*p == '-')
 	    {
-		q = p + 1;
-		while (isalnum(*q) || *q == '_')
-		    q++;
+		int numdash = 0;
+		while (*p == '-')
+		{
+		    ++numdash;
+		    p++;
+		}
+		// BUG: handle UTF PS and LS too
+		if (!*p || *p == '\r' || *p == '\n' && numdash >= 3)
+		    inCode ^= 1;
+	    }
+
+	    if (!inCode && isIdStart(p))
+	    {
+		unsigned char *q = p + utfStride(p);
+		while (isIdTail(q))
+		    q += utfStride(q);
 		if (*q == ':')	// identifier: ends it
 		{   idlen = q - p;
 		    idstart = p;
@@ -1141,12 +1160,13 @@
     while (p < pend)
     {
 	// Skip to start of macro
-	for (; 1; p++)
+	while (1)
 	{
 	    switch (*p)
 	    {
 		case ' ':
 		case '\t':
+		    p++;
 		    continue;
 
 		case '\n':
@@ -1154,20 +1174,18 @@
 		    goto Lcont;
 
 		default:
-		    if (!(isalpha(*p) || *p == '_'))
-		    {
-			if (namelen)
-			    goto Ltext;		// continuation of prev macro
-			goto Lskipline;
-		    }
-		    break;
+		    if (isIdStart(p))
+			break;
+		    if (namelen)
+			goto Ltext;		// continuation of prev macro
+		    goto Lskipline;
 	    }
 	    break;
 	}
 	tempstart = p;
 
-	while (isalnum(*p) || *p == '_')
-	    p++;
+	while (isIdTail(p))
+	    p += utfStride(p);
 	templen = p - tempstart;
 
 	while (*p == ' ' || *p == '\t')
@@ -1269,7 +1287,7 @@
     while (p < pend)
     {
 	// Skip to start of macro
-	for (; 1; p++)
+	while (1)
 	{
 	    if (p >= pend)
 		goto Ldone;
@@ -1277,6 +1295,7 @@
 	    {
 		case ' ':
 		case '\t':
+		    p++;
 		    continue;
 
 		case '\n':
@@ -1284,13 +1303,11 @@
 		    goto Lcont;
 
 		default:
-		    if (!(isalpha(*p) || *p == '_'))
-		    {
-			if (namelen)
-			    goto Ltext;		// continuation of prev macro
-			goto Lskipline;
-		    }
-		    break;
+		    if (isIdStart(p))
+			break;
+		    if (namelen)
+			goto Ltext;		// continuation of prev macro
+		    goto Lskipline;
 	    }
 	    break;
 	}
@@ -1300,9 +1317,9 @@
 	{
 	    if (p >= pend)
 		goto Ldone;
-	    if (!(isalnum(*p) || *p == '_'))
+	    if (!isIdTail(p))
 		break;
-	    p++;
+	    p += utfStride(p);
 	}
 	templen = p - tempstart;
 
@@ -1486,16 +1503,25 @@
  *	end of buf
  */
 
-unsigned skiptoident(OutBuffer *buf, unsigned i)
+unsigned skiptoident(OutBuffer *buf, size_t i)
 {
-    for (; i < buf->offset; i++)
-    {
-	// BUG: handle unicode alpha's
-	unsigned char c = buf->data[i];
-	if (isalpha(c) || c == '_')
+    while (i < buf->offset)
+    {	dchar_t c;
+
+	size_t oi = i;
+	if (utf_decodeChar((unsigned char *)buf->data, buf->offset, &i, &c))
+	    /* Ignore UTF errors, but still consume input
+	     */
 	    break;
-	if (c == '\n')
-	    break;
+	if (c >= 0x80)
+	{
+	    if (!isUniAlpha(c))
+		continue;
+	}
+	else if (!(isalpha(c) || c == '_' || c == '\n'))
+	    continue;
+	i = oi;
+	break;
     }
     return i;
 }
@@ -1504,14 +1530,25 @@
  * Scan forward past end of identifier.
  */
 
-unsigned skippastident(OutBuffer *buf, unsigned i)
+unsigned skippastident(OutBuffer *buf, size_t i)
 {
-    for (; i < buf->offset; i++)
-    {
-	// BUG: handle unicode alpha's
-	unsigned char c = buf->data[i];
-	if (!(isalnum(c) || c == '_'))
+    while (i < buf->offset)
+    {	dchar_t c;
+
+	size_t oi = i;
+	if (utf_decodeChar((unsigned char *)buf->data, buf->offset, &i, &c))
+	    /* Ignore UTF errors, but still consume input
+	     */
 	    break;
+	if (c >= 0x80)
+	{
+	    if (isUniAlpha(c))
+		continue;
+	}
+	else if (isalnum(c) || c == '_')
+	    continue;
+	i = oi;
+	break;
     }
     return i;
 }
@@ -1525,7 +1562,7 @@
  *	index just past it if it is a URL
  */
 
-unsigned skippastURL(OutBuffer *buf, unsigned i)
+unsigned skippastURL(OutBuffer *buf, size_t i)
 {   unsigned length = buf->offset - i;
     unsigned char *p = &buf->data[i];
     unsigned j;
@@ -1810,7 +1847,7 @@
 
 	    default:
 		leadingBlank = 0;
-		if (sc && !inCode && (isalpha(c) || c == '_'))
+		if (sc && !inCode && isIdStart(&buf->data[i]))
 		{   unsigned j;
 
 		    j = skippastident(buf, i);
@@ -1881,7 +1918,7 @@
 	    i = buf->insert(i, se, len);
 	    i--;		// point to ';'
 	}
-	else if (isalpha(c) || c == '_')
+	else if (isIdStart(&buf->data[i]))
 	{   unsigned j;
 
 	    j = skippastident(buf, i);
@@ -2017,3 +2054,54 @@
     return s;
 }
 
+/****************************************
+ * Determine if p points to the start of an identifier.
+ */
+
+int isIdStart(unsigned char *p)
+{
+    unsigned c = *p;
+    if (isalpha(c) || c == '_')
+	return 1;
+    if (c >= 0x80)
+    {	size_t i = 0;
+	if (utf_decodeChar(p, 4, &i, &c))
+	    return 0;	// ignore errors
+	if (isUniAlpha(c))
+	    return 1;
+    }
+    return 0;
+}
+
+/****************************************
+ * Determine if p points to the rest of an identifier.
+ */
+
+int isIdTail(unsigned char *p)
+{
+    unsigned c = *p;
+    if (isalnum(c) || c == '_')
+	return 1;
+    if (c >= 0x80)
+    {	size_t i = 0;
+	if (utf_decodeChar(p, 4, &i, &c))
+	    return 0;	// ignore errors
+	if (isUniAlpha(c))
+	    return 1;
+    }
+    return 0;
+}
+
+/*****************************************
+ * Return number of bytes in UTF character.
+ */
+
+int utfStride(unsigned char *p)
+{
+    unsigned c = *p;
+    if (c < 0x80)
+	return 1;
+    size_t i = 0;
+    utf_decodeChar(p, 4, &i, &c);	// ignore errors, but still consume input
+    return i;
+}
--- a/dmd/dsymbol.c	Fri Nov 06 21:51:41 2009 +0100
+++ b/dmd/dsymbol.c	Fri Nov 06 23:58:01 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
@@ -28,7 +28,7 @@
 #include "init.h"
 #include "import.h"
 #include "template.h"
-
+#include "attrib.h"
 #include "../gen/enums.h"
 
 /****************************** Dsymbol ******************************/
@@ -45,7 +45,7 @@
 #endif
     this->loc = 0;
     this->comment = NULL;
-
+    this->scope = NULL;
 #if IN_LLVM
     this->llvmInternal = LLVMnone;
     this->irsym = NULL;
@@ -64,7 +64,7 @@
 #endif
     this->loc = 0;
     this->comment = NULL;
-
+    this->scope = NULL;
 #if IN_LLVM
     this->llvmInternal = LLVMnone;
     this->irsym = NULL;
@@ -164,7 +164,7 @@
     return ident ? ident->toChars() : (char *)"__anonymous";
 }
 
-char *Dsymbol::toPrettyChars()
+const char *Dsymbol::toPrettyChars()
 {   Dsymbol *p;
     char *s;
     char *q;
@@ -190,6 +190,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;
@@ -266,24 +276,57 @@
     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;
+}
+
+void Dsymbol::importAll(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
 }
 
 /*********************************************
@@ -341,7 +384,7 @@
 		return NULL;
 	    }
 	    ti->tempdecl = td;
-	    if (!ti->semanticdone)
+	    if (!ti->semanticRun)
 		ti->semantic(sc);
 	    sm = ti->toAlias();
 	    break;
@@ -408,6 +451,13 @@
     return FALSE;
 }
 
+#if DMDV2
+int Dsymbol::isOverloadable()
+{
+    return 0;
+}
+#endif
+
 LabelDsymbol *Dsymbol::isLabel()		// is this a LabelDsymbol()?
 {
     return NULL;
@@ -439,7 +489,7 @@
     parent = sd;
     if (!isAnonymous())		// no name, so can't add it to symbol table
     {
-	if (!sd->symtab->insert(this))	// if name is already defined
+	if (!sd->symtabInsert(this))	// if name is already defined
 	{
 	    Dsymbol *s2;
 
@@ -631,8 +681,8 @@
 
 void Dsymbol::addComment(unsigned char *comment)
 {
-//    if (comment)
-//	printf("adding comment '%s' to symbol %p '%s'\n", comment, this, toChars());
+    //if (comment)
+	//printf("adding comment '%s' to symbol %p '%s'\n", comment, this, toChars());
 
     if (!this->comment)
 	this->comment = comment;
@@ -644,6 +694,25 @@
 #endif
 }
 
+/********************************* OverloadSet ****************************/
+
+#if DMDV2
+OverloadSet::OverloadSet()
+    : Dsymbol()
+{
+}
+
+void OverloadSet::push(Dsymbol *s)
+{
+    a.push(s);
+}
+
+const char *OverloadSet::kind()
+{
+    return "overloadset";
+}
+#endif
+
 
 /********************************* ScopeDsymbol ****************************/
 
@@ -681,6 +750,7 @@
 Dsymbol *ScopeDsymbol::search(Loc loc, Identifier *ident, int flags)
 {
     //printf("%s->ScopeDsymbol::search(ident='%s', flags=x%x)\n", toChars(), ident->toChars(), flags);
+    //if (strcmp(ident->toChars(),"c") == 0) *(char*)0=0;
 
     // Look in symbols declared in this module
     Dsymbol *s = symtab ? symtab->lookup(ident) : NULL;
@@ -771,7 +841,7 @@
 	    {   ScopeDsymbol *ss;
 
 		ss = (ScopeDsymbol *) imports->data[i];
-		if (ss == s)
+		if (ss == s)			// if already imported
 		{
 		    if (protection > prots[i])
 			prots[i] = protection;	// upgrade access
@@ -849,6 +919,73 @@
     return "ScopeDsymbol";
 }
 
+Dsymbol *ScopeDsymbol::symtabInsert(Dsymbol *s)
+{
+    return symtab->insert(s);
+}
+
+/***************************************
+ * Determine number of Dsymbols, folding in AttribDeclaration members.
+ */
+
+#if DMDV2
+size_t ScopeDsymbol::dim(Array *members)
+{
+    size_t n = 0;
+    if (members)
+    {
+	for (size_t i = 0; i < members->dim; i++)
+	{   Dsymbol *s = (Dsymbol *)members->data[i];
+	    AttribDeclaration *a = s->isAttribDeclaration();
+
+	    if (a)
+	    {
+		n += dim(a->decl);
+	    }
+	    else
+		n++;
+	}
+    }
+    return n;
+}
+#endif
+
+/***************************************
+ * Get nth Dsymbol, folding in AttribDeclaration members.
+ * Returns:
+ *	Dsymbol*	nth Dsymbol
+ *	NULL		not found, *pn gets incremented by the number
+ *			of Dsymbols
+ */
+
+#if DMDV2
+Dsymbol *ScopeDsymbol::getNth(Array *members, size_t nth, size_t *pn)
+{
+    if (!members)
+	return NULL;
+
+    size_t n = 0;
+    for (size_t i = 0; i < members->dim; i++)
+    {   Dsymbol *s = (Dsymbol *)members->data[i];
+	AttribDeclaration *a = s->isAttribDeclaration();
+
+	if (a)
+	{
+	    s = getNth(a->decl, nth - n, &n);
+	    if (s)
+		return s;
+	}
+	else if (n == nth)
+	    return s;
+	else
+	    n++;
+    }
+
+    if (pn)
+	*pn += n;
+    return NULL;
+}
+#endif
 
 /*******************************************
  * Look for member of the form:
@@ -938,7 +1075,8 @@
     L1:
 
 	if (td)
- 	{
+ 	{   /* $ gives the number of elements in the tuple
+	     */
 	    VarDeclaration *v = new VarDeclaration(loc, Type::tsize_t, Id::dollar, NULL);
 	    Expression *e = new IntegerExp(0, td->objects->dim, Type::tsize_t);
 	    v->init = new ExpInitializer(0, e);
@@ -947,7 +1085,8 @@
 	}
 
 	if (type)
- 	{
+ 	{   /* $ gives the number of type entries in the type tuple
+	     */
 	    VarDeclaration *v = new VarDeclaration(loc, Type::tsize_t, Id::dollar, NULL);
 	    Expression *e = new IntegerExp(0, type->arguments->dim, Type::tsize_t);
 	    v->init = new ExpInitializer(0, e);
@@ -956,22 +1095,30 @@
 	}
 
 	if (exp->op == TOKindex)
-	{
+	{   /* array[index] where index is some function of $
+	     */
 	    IndexExp *ie = (IndexExp *)exp;
 
 	    pvar = &ie->lengthVar;
 	    ce = ie->e1;
 	}
 	else if (exp->op == TOKslice)
-	{
+	{   /* array[lwr .. upr] where lwr or upr is some function of $
+	     */
 	    SliceExp *se = (SliceExp *)exp;
 
 	    pvar = &se->lengthVar;
 	    ce = se->e1;
 	}
 	else
+	    /* Didn't find $, look in enclosing scope(s).
+	     */
 	    return NULL;
 
+	/* If we are indexing into an array that is really a type
+	 * tuple, rewrite this as an index into a type tuple and
+	 * try again.
+	 */
 	if (ce->op == TOKtype)
 	{
 	    Type *t = ((TypeExp *)ce)->type;
@@ -981,8 +1128,13 @@
 	    }
 	}
 
-	if (!*pvar)
-	{
+	/* *pvar is lazily initialized, so if we refer to $
+	 * multiple times, it gets set only once.
+	 */
+	if (!*pvar)		// if not already initialized
+	{   /* Create variable v and set it to the value of $,
+	     * which will be a constant.
+	     */
 	    VarDeclaration *v = new VarDeclaration(loc, Type::tsize_t, Id::dollar, NULL);
 
 	    if (ce->op == TOKstring)
@@ -1030,13 +1182,12 @@
 }
 
 Dsymbol *DsymbolTable::lookup(Identifier *ident)
-{   StringValue *sv;
-
+{
 #ifdef DEBUG
     assert(ident);
     assert(tab);
 #endif
-    sv = tab->lookup((char*)ident->string, ident->len);
+    StringValue *sv = tab->lookup((char*)ident->string, ident->len);
     return (Dsymbol *)(sv ? sv->ptrvalue : NULL);
 }
 
--- a/dmd/dsymbol.h	Fri Nov 06 21:51:41 2009 +0100
+++ b/dmd/dsymbol.h	Fri Nov 06 23:58:01 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
@@ -28,6 +28,7 @@
 struct Scope;
 struct DsymbolTable;
 struct Declaration;
+struct ThisDeclaration;
 struct TupleDeclaration;
 struct TypedefDeclaration;
 struct AliasDeclaration;
@@ -41,6 +42,7 @@
 struct FuncAliasDeclaration;
 struct FuncLiteralDeclaration;
 struct CtorDeclaration;
+struct PostBlitDeclaration;
 struct DtorDeclaration;
 struct StaticCtorDeclaration;
 struct StaticDtorDeclaration;
@@ -70,11 +72,13 @@
 struct HdrGenState;
 struct TypeInfoDeclaration;
 struct ClassInfoDeclaration;
-
+struct OverloadSet;
+#if TARGET_NET
+struct PragmaScope;
+#endif
 #if IN_DMD
 struct Symbol;
 #endif
-
 #if IN_GCC
 union tree_node;
 typedef union tree_node TYPE;
@@ -82,6 +86,9 @@
 struct TYPE;
 #endif
 
+// Back end
+struct Classsym;
+
 #if IN_LLVM
 class Ir;
 class IrSymbol;
@@ -114,11 +121,11 @@
 #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 *);
     char *toChars();
-    char *toPrettyChars();
     char *locToChars();
     int equals(Object *o);
     int isAnonymous();
@@ -136,9 +143,12 @@
 
     static Array *arraySyntaxCopy(Array *a);
 
+    virtual const char *toPrettyChars();
     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 importAll(Scope *sc);
     virtual void semantic(Scope *sc);
     virtual void semantic2(Scope *sc);
     virtual void semantic3(Scope *sc);
@@ -152,6 +162,7 @@
 #endif
     virtual void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
     virtual void toDocBuffer(OutBuffer *buf);
+    virtual void toJsonBuffer(OutBuffer *buf);
     virtual unsigned size(Loc loc);
     virtual int isforwardRef();
     virtual void defineRef(Dsymbol *s);
@@ -160,6 +171,9 @@
     virtual int isExport();			// is Dsymbol exported?
     virtual int isImportedSymbol();		// is Dsymbol imported?
     virtual int isDeprecated();			// is Dsymbol deprecated?
+#if DMDV2
+    virtual int isOverloadable();
+#endif
     virtual LabelDsymbol *isLabel();		// is this a LabelDsymbol?
     virtual AggregateDeclaration *isMember();	// is this symbol a member of an AggregateDeclaration?
     virtual Type *getType();			// is this a type?
@@ -198,6 +212,7 @@
     virtual TemplateInstance *isTemplateInstance() { return NULL; }
     virtual TemplateMixin *isTemplateMixin() { return NULL; }
     virtual Declaration *isDeclaration() { return NULL; }
+    virtual ThisDeclaration *isThisDeclaration() { return NULL; }
     virtual TupleDeclaration *isTupleDeclaration() { return NULL; }
     virtual TypedefDeclaration *isTypedefDeclaration() { return NULL; }
     virtual AliasDeclaration *isAliasDeclaration() { return NULL; }
@@ -206,6 +221,7 @@
     virtual FuncAliasDeclaration *isFuncAliasDeclaration() { return NULL; }
     virtual FuncLiteralDeclaration *isFuncLiteralDeclaration() { return NULL; }
     virtual CtorDeclaration *isCtorDeclaration() { return NULL; }
+    virtual PostBlitDeclaration *isPostBlitDeclaration() { return NULL; }
     virtual DtorDeclaration *isDtorDeclaration() { return NULL; }
     virtual StaticCtorDeclaration *isStaticCtorDeclaration() { return NULL; }
     virtual StaticDtorDeclaration *isStaticDtorDeclaration() { return NULL; }
@@ -230,6 +246,11 @@
     virtual TypeInfoDeclaration* isTypeInfoDeclaration() { return NULL; }
     virtual ClassInfoDeclaration* isClassInfoDeclaration() { return NULL; }
 
+    virtual OverloadSet *isOverloadSet() { return NULL; }
+#if TARGET_NET
+    virtual PragmaScope* isPragmaScope() { return NULL; }
+#endif
+
 #if IN_LLVM
     /// Codegen traversal
     virtual void codegen(Ir* ir);
@@ -250,7 +271,7 @@
     DsymbolTable *symtab;	// members[] sorted into table
 
     Array *imports;		// imported ScopeDsymbol's
-    unsigned char *prots;	// PROT for each import
+    unsigned char *prots;	// array of PROT, one for each import
 
     ScopeDsymbol();
     ScopeDsymbol(Identifier *id);
@@ -262,9 +283,14 @@
     static void multiplyDefined(Loc loc, Dsymbol *s1, Dsymbol *s2);
     Dsymbol *nameCollision(Dsymbol *s);
     const char *kind();
+    FuncDeclaration *findGetMembers();
+    virtual Dsymbol *symtabInsert(Dsymbol *s);
 
     void emitMemberComments(Scope *sc);
 
+    static size_t dim(Array *members);
+    static Dsymbol *getNth(Array *members, size_t nth, size_t *pn = NULL);
+
     ScopeDsymbol *isScopeDsymbol() { return this; }
 };
 
@@ -287,6 +313,7 @@
     Expression *exp;	// IndexExp or SliceExp
     TypeTuple *type;	// for tuple[length]
     TupleDeclaration *td;	// for tuples of objects
+    Scope *sc;
 
     ArrayScopeSymbol(Expression *e);
     ArrayScopeSymbol(TypeTuple *t);
@@ -296,6 +323,20 @@
     ArrayScopeSymbol *isArrayScopeSymbol() { return this; }
 };
 
+// Overload Sets
+
+#if DMDV2
+struct OverloadSet : Dsymbol
+{
+    Dsymbols a;		// array of Dsymbols
+
+    OverloadSet();
+    void push(Dsymbol *s);
+    OverloadSet *isOverloadSet() { return this; }
+    const char *kind();
+};
+#endif
+
 // Table of Dsymbol's
 
 struct DsymbolTable : Object
--- a/dmd/enum.h	Fri Nov 06 21:51:41 2009 +0100
+++ b/dmd/enum.h	Fri Nov 06 23:58:01 2009 +0100
@@ -1,94 +1,95 @@
-
-// Compiler implementation of the D programming language
-// Copyright (c) 1999-2008 by Digital Mars
-// All Rights Reserved
-// written by Walter Bright
-// http://www.digitalmars.com
-// License for redistribution is by either the Artistic License
-// in artistic.txt, or the GNU General Public License in gnu.txt.
-// See the included readme.txt for details.
-
-#ifndef DMD_ENUM_H
-#define DMD_ENUM_H
-
-#ifdef __DMC__
-#pragma once
-#endif /* __DMC__ */
-
-#include "root.h"
-#include "dsymbol.h"
-
-struct Identifier;
-struct Type;
-struct Expression;
-#ifdef _DH
-struct HdrGenState;
-#endif
-
-
-struct EnumDeclaration : ScopeDsymbol
-{
-    Type *type;			// the TypeEnum
-    Type *memtype;		// type of the members
-
-#if DMDV1
-    dinteger_t maxval;
-    dinteger_t minval;
-    dinteger_t defaultval;	// default initializer
-#else
-    Expression *maxval;
-    Expression *minval;
-    Expression *defaultval;	// default initializer
-
-    Scope *scope;		// !=NULL means context to use
-#endif
-    int isdeprecated;
-
-    EnumDeclaration(Loc loc, Identifier *id, Type *memtype);
-    Dsymbol *syntaxCopy(Dsymbol *s);
-    void semantic(Scope *sc);
-    int oneMember(Dsymbol **ps);
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-    Type *getType();
-    const char *kind();
-#if DMDV2
-    Dsymbol *search(Loc, Identifier *ident, int flags);
-#endif
-    int isDeprecated();			// is Dsymbol deprecated?
-
-    void emitComment(Scope *sc);
-    void toDocBuffer(OutBuffer *buf);
-
-    EnumDeclaration *isEnumDeclaration() { return this; }
-
-#if IN_DMD
-    void toObjFile(int multiobj);			// compile to .obj file
-    void toDebug();
-    int cvMember(unsigned char *p);
-
-    Symbol *sinit;
-    Symbol *toInitializer();
-#endif
-
-#if IN_LLVM
-    void codegen(Ir*);
-#endif
-};
-
-
-struct EnumMember : Dsymbol
-{
-    Expression *value;
-
-    EnumMember(Loc loc, Identifier *id, Expression *value);
-    Dsymbol *syntaxCopy(Dsymbol *s);
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-    const char *kind();
-
-    void emitComment(Scope *sc);
-    void toDocBuffer(OutBuffer *buf);
-
-    EnumMember *isEnumMember() { return this; }
-};
-
-#endif /* DMD_ENUM_H */
+
+// Compiler implementation of the D programming language
+// Copyright (c) 1999-2008 by Digital Mars
+// All Rights Reserved
+// written by Walter Bright
+// http://www.digitalmars.com
+// License for redistribution is by either the Artistic License
+// in artistic.txt, or the GNU General Public License in gnu.txt.
+// See the included readme.txt for details.
+
+#ifndef DMD_ENUM_H
+#define DMD_ENUM_H
+
+#ifdef __DMC__
+#pragma once
+#endif /* __DMC__ */
+
+#include "root.h"
+#include "dsymbol.h"
+
+struct Identifier;
+struct Type;
+struct Expression;
+#ifdef _DH
+struct HdrGenState;
+#endif
+
+
+struct EnumDeclaration : ScopeDsymbol
+{   /* enum ident : memtype { ... }
+     */
+    Type *type;			// the TypeEnum
+    Type *memtype;		// type of the members
+
+#if DMDV1
+    dinteger_t maxval;
+    dinteger_t minval;
+    dinteger_t defaultval;	// default initializer
+#else
+    Expression *maxval;
+    Expression *minval;
+    Expression *defaultval;	// default initializer
+#endif
+    int isdeprecated;
+
+    EnumDeclaration(Loc loc, Identifier *id, Type *memtype);
+    Dsymbol *syntaxCopy(Dsymbol *s);
+    void semantic(Scope *sc);
+    int oneMember(Dsymbol **ps);
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+    Type *getType();
+    const char *kind();
+#if DMDV2
+    Dsymbol *search(Loc, Identifier *ident, int flags);
+#endif
+    int isDeprecated();			// is Dsymbol deprecated?
+
+    void emitComment(Scope *sc);
+    void toJsonBuffer(OutBuffer *buf);
+    void toDocBuffer(OutBuffer *buf);
+
+    EnumDeclaration *isEnumDeclaration() { return this; }
+
+#if IN_DMD
+    void toObjFile(int multiobj);			// compile to .obj file
+    void toDebug();
+    int cvMember(unsigned char *p);
+
+    Symbol *sinit;
+    Symbol *toInitializer();
+#endif
+
+#if IN_LLVM
+    void codegen(Ir*);
+#endif
+};
+
+
+struct EnumMember : Dsymbol
+{
+    Expression *value;
+
+    EnumMember(Loc loc, Identifier *id, Expression *value);
+    Dsymbol *syntaxCopy(Dsymbol *s);
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+    const char *kind();
+
+    void emitComment(Scope *sc);
+    void toJsonBuffer(OutBuffer *buf);
+    void toDocBuffer(OutBuffer *buf);
+
+    EnumMember *isEnumMember() { return this; }
+};
+
+#endif /* DMD_ENUM_H */
--- a/dmd/expression.c	Fri Nov 06 21:51:41 2009 +0100
+++ b/dmd/expression.c	Fri Nov 06 23:58:01 2009 +0100
@@ -35,8 +35,8 @@
 #endif
 
 #include "rmem.h"
-
-//#include "port.h"
+#include "port.h"
+
 #include "mtype.h"
 #include "init.h"
 #include "expression.h"
@@ -373,6 +373,11 @@
 	}
 
     }
+    else if (e->op == TOKdottd)
+    {
+	e = new CallExp(e->loc, e);
+	e = e->semantic(sc);
+    }
     return e;
 }
 
@@ -543,7 +548,7 @@
     size_t nparams = Argument::dim(tf->parameters);
 
     if (nargs > nparams && tf->varargs == 0)
-	error(loc, "expected %zu arguments, not %zu", nparams, nargs);
+	error(loc, "expected %zu arguments, not %zu for non-variadic function type %s", nparams, nargs, tf->toChars());
 
     n = (nargs > nparams) ? nargs : nparams;	// n = max(nargs, nparams)
 
@@ -568,7 +573,7 @@
 		{
 		    if (tf->varargs == 2 && i + 1 == nparams)
 			goto L2;
-		    error(loc, "expected %zu arguments, not %zu", nparams, nargs);
+		    error(loc, "expected %zu function arguments, not %zu", nparams, nargs);
 		    break;
 		}
 		arg = p->defaultArg;
@@ -590,7 +595,7 @@
 		if (arg->implicitConvTo(p->type))
 		{
 		    if (nargs != nparams)
-		        error(loc, "expected %zu arguments, not %zu", nparams, nargs);
+		        error(loc, "expected %zu function arguments, not %zu", nparams, nargs);
 		    goto L1;
 		}
 	     L2:
@@ -669,7 +674,16 @@
 
 	L1:
 	    if (!(p->storageClass & STClazy && p->type->ty == Tvoid))
-		arg = arg->implicitCastTo(sc, p->type);
+	    {
+		if (p->type != arg->type)
+		{
+		    //printf("arg->type = %s, p->type = %s\n", arg->type->toChars(), p->type->toChars());
+		    if (arg->op == TOKtype)
+			arg->error("cannot pass type %s as function argument", arg->toChars());
+		    arg = arg->implicitCastTo(sc, p->type);
+		    arg = arg->optimize(WANTvalue);
+		}
+	    }
 	    if (p->storageClass & (STCout | STCref))
 	    {
 		// BUG: should check that argument to ref is type 'invariant'
@@ -773,11 +787,15 @@
 	    {
 		arg = callCpCtor(loc, sc, arg);
 	    }
+#endif
 
 	    // Give error for overloaded function addresses
+#if DMDV2
 	    if (arg->op == TOKsymoff)
 	    {	SymOffExp *se = (SymOffExp *)arg;
-		if (se->hasOverloads && !se->var->isFuncDeclaration()->isUnique())
+		if (
+		    se->hasOverloads &&
+		    !se->var->isFuncDeclaration()->isUnique())
 		    arg->error("function %s is overloaded", arg->toChars());
 	    }
 #endif
@@ -1214,10 +1232,10 @@
 Expression *Expression::deref()
 {
     //printf("Expression::deref()\n");
-    if (type->ty == Treference)
-    {	Expression *e;
-
-	e = new PtrExp(loc, this);
+    // type could be null if forward referencing an 'auto' variable
+    if (type && type->ty == Treference)
+    {
+	Expression *e = new PtrExp(loc, this);
 	e->type = ((TypeReference *)type)->next;
 	return e;
     }
@@ -2155,6 +2173,10 @@
     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);
     }
     cd = s->isClassDeclaration();
@@ -2209,7 +2231,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())
@@ -3166,7 +3188,16 @@
 	    if (v->init)
 	    {   e = v->init->toExpression();
 		if (!e)
-		    error("cannot make expression out of initializer for %s", v->toChars());
+		{   error("cannot make expression out of initializer for %s", v->toChars());
+		    e = new ErrorExp();
+		}
+		else if (v->scope)
+		{   // Do deferred semantic anaylsis
+		    Initializer *i2 = v->init->syntaxCopy();
+		    i2 = i2->semantic(v->scope, v->type);
+		    e = i2->toExpression();
+		    v->scope = NULL;
+		}
 	    }
 	    else
 	    {	e = v->type->defaultInit();
@@ -3200,8 +3231,26 @@
 	e = (Expression *)elements->data[i];
 	if (e)
 	{
-	    e = e->copy();
-	    e->type = type;
+	    //printf("e = %s, e->type = %s\n", e->toChars(), e->type->toChars());
+
+	    /* If type is a static array, and e is an initializer for that array,
+	     * then the field initializer should be an array literal of e.
+	     */
+	    if (e->type != type && type->ty == Tsarray)
+	    {   TypeSArray *tsa = (TypeSArray *)type;
+		uinteger_t length = tsa->dim->toInteger();
+		Expressions *z = new Expressions;
+		z->setDim(length);
+		for (int q = 0; q < length; ++q)
+		    z->data[q] = e->copy();
+		e = new ArrayLiteralExp(loc, z);
+		e->type = type;
+	    }
+	    else
+	    {
+		e = e->copy();
+		e->type = type;
+	    }
 	}
     }
     return e;
@@ -3216,20 +3265,23 @@
 {
     /* Find which field offset is by looking at the field offsets
      */
-    for (size_t i = 0; i < sd->fields.dim; i++)
-    {
-	Dsymbol *s = (Dsymbol *)sd->fields.data[i];
-	VarDeclaration *v = s->isVarDeclaration();
-	assert(v);
-
-	if (offset == v->offset &&
-	    type->size() == v->type->size())
-	{   Expression *e = (Expression *)elements->data[i];
-	    if (e)
-	    {
-		return i;
-	    }
-	    break;
+    if (elements->dim)
+    {
+	for (size_t i = 0; i < sd->fields.dim; i++)
+	{
+	    Dsymbol *s = (Dsymbol *)sd->fields.data[i];
+	    VarDeclaration *v = s->isVarDeclaration();
+	    assert(v);
+
+	    if (offset == v->offset &&
+		type->size() == v->type->size())
+	    {   Expression *e = (Expression *)elements->data[i];
+		if (e)
+		{
+		    return i;
+		}
+		break;
+	    }
 	}
     }
     return -1;
@@ -3365,7 +3417,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();
@@ -3583,7 +3635,7 @@
 	    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)
 		{
@@ -3606,7 +3658,7 @@
 	if (f)
 	{
 	    assert(f);
-	    f = f->overloadResolve(loc, arguments, sc->module);
+	    f = f->overloadResolve(loc, NULL, arguments, sc->module);
 	    checkDeprecated(sc, f);
 	    member = f->isCtorDeclaration();
 	    assert(member);
@@ -3634,7 +3686,7 @@
 		newargs = new Expressions();
 	    newargs->shift(e);
 
-	    f = cd->aggNew->overloadResolve(loc, newargs, sc->module);
+	    f = cd->aggNew->overloadResolve(loc, NULL, newargs, sc->module);
 	    allocator = f->isNewDeclaration();
 	    assert(allocator);
 
@@ -3667,7 +3719,7 @@
 		newargs = new Expressions();
 	    newargs->shift(e);
 
-	    f = f->overloadResolve(loc, newargs, sc->module);
+	    f = f->overloadResolve(loc, NULL, newargs, sc->module);
 	    allocator = f->isNewDeclaration();
 	    assert(allocator);
 
@@ -4200,6 +4252,7 @@
 	return (Expression *)exps->data[0];
     }
     type = new TypeTuple(exps);
+    type = type->semantic(loc, sc);
     //printf("-TupleExp::semantic(%s)\n", toChars());
     return this;
 }
@@ -4263,13 +4316,13 @@
 	fd->parent = sc->parent;
 	if (global.errors)
 	{
-	    if (!fd->type->next)
-		fd->type->next = Type::terror;
 	}
 	else
 	{
 	    fd->semantic2(sc);
-	    if (!global.errors)
+	    if (!global.errors ||
+		// need to infer return type
+		(fd->type && fd->type->ty == Tfunction && !fd->type->nextOf()))
 	    {
 		fd->semantic3(sc);
 
@@ -4278,6 +4331,10 @@
 	    }
 	}
 
+	// need to infer return type
+	if (global.errors && fd->type && fd->type->ty == Tfunction && !fd->type->nextOf())
+	    ((TypeFunction *)fd->type)->next = Type::terror;
+
 	// Type is a "delegate to" or "pointer to" the function literal
 	if (fd->isNested())
 	{
@@ -4377,7 +4434,13 @@
     }
     if (!s->isVarDeclaration())
     {
-	declaration->semantic(sc);
+	Scope *sc2 = sc;
+	if (sc2->stc & (STCpure | STCnothrow))
+	    sc2 = sc->push();
+	sc2->stc &= ~(STCpure | STCnothrow);
+	declaration->semantic(sc2);
+	if (sc2 != sc)
+	    sc2->pop();
 	s->parent = sc->parent;
     }
     if (!global.errors)
@@ -4920,7 +4983,7 @@
 
 	if (op == TOKmodass && e2->type->iscomplex())
 	{   error("cannot perform modulo complex arithmetic");
-	    return new IntegerExp(0);
+	    return new ErrorExp();
 	}
     }
     return this;
@@ -4985,6 +5048,46 @@
     return Expression::checkSideEffect(flag);
 }
 
+// generate an error if this is a nonsensical *=,/=, or %=, eg real *= imaginary
+void BinExp::checkComplexMulAssign()
+{
+    // Any multiplication by an imaginary or complex number yields a complex result.
+    // r *= c, i*=c, r*=i, i*=i are all forbidden operations.
+    const char *opstr = Token::toChars(op);
+    if ( e1->type->isreal() && e2->type->iscomplex())
+    {
+        error("%s %s %s is undefined. Did you mean %s %s %s.re ?",
+            e1->type->toChars(), opstr, e2->type->toChars(), 
+            e1->type->toChars(), opstr, e2->type->toChars());
+    }
+    else if (e1->type->isimaginary() && e2->type->iscomplex())
+    {
+        error("%s %s %s is undefined. Did you mean %s %s %s.im ?",
+            e1->type->toChars(), opstr, e2->type->toChars(),
+            e1->type->toChars(), opstr, e2->type->toChars());
+    }
+    else if ((e1->type->isreal() || e1->type->isimaginary()) &&
+	e2->type->isimaginary())
+    {
+        error("%s %s %s is an undefined operation", e1->type->toChars(),
+		opstr, e2->type->toChars());
+    }
+}
+
+// generate an error if this is a nonsensical += or -=, eg real += imaginary
+void BinExp::checkComplexAddAssign()
+{
+    // Addition or subtraction of a real and an imaginary is a complex result.
+    // Thus, r+=i, r+=c, i+=r, i+=c are all forbidden operations.
+    if ( (e1->type->isreal() && (e2->type->isimaginary() || e2->type->iscomplex())) ||
+         (e1->type->isimaginary() && (e2->type->isreal() || e2->type->iscomplex()))        
+        )
+    {
+        error("%s %s %s is undefined (result is complex)",
+	    e1->type->toChars(), Token::toChars(op), e2->type->toChars());
+    }
+}
+
 void BinExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
 {
     expToCBuffer(buf, hgs, e1, precedence[op]);
@@ -5094,7 +5197,7 @@
     }
 
     if (global.params.verbose)
-	printf("file      %s\t(%s)\n", (char*)se->string, name);
+	printf("file      %s\t(%s)\n", (char *)se->string, name);
 
     {	File f(name);
 	if (f.read())
@@ -5177,7 +5280,10 @@
 #if DMDV2
 int AssertExp::canThrow()
 {
-    return (global.params.useAssert != 0);
+    /* assert()s are non-recoverable errors, so functions that
+     * use them can be considered "nothrow"
+     */
+    return 0; //(global.params.useAssert != 0);
 }
 #endif
 
@@ -5479,7 +5585,11 @@
 	     ident != Id::init && ident != Id::__sizeof &&
 	     ident != Id::alignof && ident != Id::offsetof &&
 	     ident != Id::mangleof && ident != Id::stringof)
-    {
+    {	/* Rewrite:
+         *   p.ident
+         * as:
+         *   (*p).ident
+         */
 	e = new PtrExp(loc, e1);
 	e->type = ((TypePointer *)e1->type)->next;
 	return e->type->dotExp(sc, e, ident);
@@ -5598,7 +5708,7 @@
 	type = var->type;
 	if (!type && global.errors)
 	{   // var is goofed up, just return 0
-	    return new IntegerExp(0);
+	    return new ErrorExp();
 	}
 	assert(type);
 
@@ -5935,9 +6045,10 @@
 	: UnaExp(loc, TOKcall, sizeof(CallExp), e)
 {
     Expressions *arguments = new Expressions();
-    arguments->setDim(1);
-    arguments->data[0] = (void *)earg1;
-
+    if (earg1)
+    {	arguments->setDim(1);
+	arguments->data[0] = (void *)earg1;
+    }
     this->arguments = arguments;
 }
 
@@ -6040,7 +6151,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.
@@ -6067,7 +6178,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.
@@ -6163,6 +6274,36 @@
 	if (t1->ty == Tstruct)
 	{
 	    ad = ((TypeStruct *)t1)->sym;
+#if DMDV2
+	    // First look for constructor
+	    if (ad->ctor && arguments && arguments->dim)
+	    {
+		// Create variable that will get constructed
+		Identifier *idtmp = Lexer::uniqueId("__ctmp");
+		VarDeclaration *tmp = new VarDeclaration(loc, t1, idtmp, NULL);
+		Expression *av = new DeclarationExp(loc, tmp);
+		av = new CommaExp(loc, av, new VarExp(loc, tmp));
+
+		Expression *e;
+		CtorDeclaration *cf = ad->ctor->isCtorDeclaration();
+		if (cf)
+		    e = new DotVarExp(loc, av, cf, 1);
+		else
+		{   TemplateDeclaration *td = ad->ctor->isTemplateDeclaration();
+		    assert(td);
+		    e = new DotTemplateExp(loc, av, td);
+		}
+		e = new CallExp(loc, e, arguments);
+#if !STRUCTTHISREF
+		/* Constructors return a pointer to the instance
+		 */
+		e = new PtrExp(loc, e);
+#endif
+		e = e->semantic(sc);
+		return e;
+	    }
+#endif
+	    // No constructor, look for overload of opCall
 	    if (search_function(ad, Id::call))
 		goto L1;	// overload of opCall, therefore it's a call
 
@@ -6205,7 +6346,7 @@
 
 	    f = dve->var->isFuncDeclaration();
 	    assert(f);
-	    f = f->overloadResolve(loc, arguments, sc->module);
+	    f = f->overloadResolve(loc, NULL, arguments, sc->module);
 
 	    ad = f->toParent()->isAggregateDeclaration();
 	}
@@ -6306,7 +6447,7 @@
 		    sc->callSuper |= CSXany_ctor | CSXsuper_ctor;
 		}
 
-		f = f->overloadResolve(loc, arguments, sc->module);
+		f = f->overloadResolve(loc, NULL, arguments, sc->module);
 		checkDeprecated(sc, f);
 #if DMDV2
 		checkPurity(sc, f);
@@ -6346,7 +6487,7 @@
 	    }
 
 	    f = cd->ctor;
-	    f = f->overloadResolve(loc, arguments, sc->module);
+	    f = f->overloadResolve(loc, NULL, arguments, sc->module);
 	    checkDeprecated(sc, f);
 #if DMDV2
 	    checkPurity(sc, f);
@@ -6440,7 +6581,7 @@
 	    }
 	}
 
-	f = f->overloadResolve(loc, arguments, sc->module);
+	f = f->overloadResolve(loc, NULL, arguments, sc->module);
 	checkDeprecated(sc, f);
 #if DMDV2
 	checkPurity(sc, f);
@@ -6523,6 +6664,7 @@
 #if DMDV2
 int CallExp::canThrow()
 {
+    //printf("CallExp::canThrow() %s\n", toChars());
     if (e1->canThrow())
 	return 1;
 
@@ -6531,10 +6673,13 @@
     for (size_t i = 0; i < arguments->dim; i++)
     {   Expression *e = (Expression *)arguments->data[i];
 
-	if (e->canThrow())
+	if (e && e->canThrow())
 	    return 1;
     }
 
+    if (global.errors && !e1->type)
+	return 0;			// error recovery
+
     /* If calling a function or delegate that is typed as nothrow,
      * then this expression cannot throw.
      * Note that pure functions can throw.
@@ -6552,8 +6697,8 @@
 #if DMDV2
 int CallExp::isLvalue()
 {
-    if (type->toBasetype()->ty == Tstruct)
-	return 1;
+//    if (type->toBasetype()->ty == Tstruct)
+//	return 1;
     Type *tb = e1->type->toBasetype();
     if (tb->ty == Tfunction && ((TypeFunction *)tb)->isref)
 	return 1;		// function returns a reference
@@ -6563,12 +6708,28 @@
 
 Expression *CallExp::toLvalue(Scope *sc, Expression *e)
 {
+#if 1
     if (type->toBasetype()->ty == Tstruct)
 	return this;
     else
+#endif
 	return Expression::toLvalue(sc, e);
 }
 
+Expression *CallExp::modifiableLvalue(Scope *sc, Expression *e)
+{
+#if 1
+    return Expression::modifiableLvalue(sc, e);
+#else
+    /* Although function return values being usable as "ref" parameters is
+     * unsound, disabling it breaks existing code.
+     * Bugzilla 3167
+     */
+    error("cannot assign to function call");
+    return toLvalue(sc, e);
+#endif
+}
+
 void CallExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
 {   int i;
 
@@ -6600,8 +6761,19 @@
 	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();
 	}
 	type = e1->type->pointerTo();
 
@@ -6653,8 +6825,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)
@@ -6664,43 +6836,35 @@
 }
 
 Expression *PtrExp::semantic(Scope *sc)
-{   Type *tb;
-
+{
 #if LOGSEMANTIC
     printf("PtrExp::semantic('%s')\n", toChars());
 #endif
-    UnaExp::semantic(sc);
-    e1 = resolveProperties(sc, e1);
-    if (type)
-	return this;
-    if (!e1->type)
-	printf("PtrExp::semantic('%s')\n", toChars());
-    tb = e1->type->toBasetype();
-    switch (tb->ty)
-    {
-	case Tpointer:
-	    type = tb->next;
-	    if (type->isbit())
-	    {	Expression *e;
-
-		// Rewrite *p as p[0]
-		e = new IndexExp(loc, e1, new IntegerExp(0));
-		return e->semantic(sc);
-	    }
-	    break;
-
-	case Tsarray:
-	case Tarray:
-	    type = tb->next;
-	    e1 = e1->castTo(sc, type->pointerTo());
-	    break;
-
-	default:
-	    error("can only * a pointer, not a '%s'", e1->type->toChars());
-	    type = Type::tint32;
-	    break;
-    }
-    rvalue();
+    if (!type)
+    {
+	UnaExp::semantic(sc);
+	e1 = resolveProperties(sc, e1);
+	if (!e1->type)
+	    printf("PtrExp::semantic('%s')\n", toChars());
+	Type *tb = e1->type->toBasetype();
+	switch (tb->ty)
+	{
+	    case Tpointer:
+		type = tb->next;
+		break;
+
+	    case Tsarray:
+	    case Tarray:
+		type = tb->next;
+		e1 = e1->castTo(sc, type->pointerTo());
+		break;
+
+	    default:
+		error("can only * a pointer, not a '%s'", e1->type->toChars());
+		return new ErrorExp();
+	}
+	rvalue();
+    }
     return this;
 }
 
@@ -6766,7 +6930,7 @@
 	    return e;
 
 	e1->checkNoBool();
-	if (e1->op != TOKslice)
+	if (!e1->isArrayOperand())
 	    e1->checkArithmetic();
 	type = e1->type;
     }
@@ -6816,7 +6980,7 @@
 	    return e;
 
 	e1->checkNoBool();
-	if (e1->op != TOKslice)
+	if (!e1->isArrayOperand())
 	    e1 = e1->checkIntegral();
 	type = e1->type;
     }
@@ -7012,9 +7176,16 @@
 	    return e->implicitCastTo(sc, to);
 	}
 
+	if (e1->op == TOKtemplate)
+	{
+	    error("cannot cast template %s to type %s", e1->toChars(), to->toChars());
+	    return new ErrorExp();
+	}
+
+	Type *t1b = e1->type->toBasetype();
 	Type *tob = to->toBasetype();
 	if (tob->ty == Tstruct &&
-	    !tob->equals(e1->type->toBasetype()) &&
+	    !tob->equals(t1b) &&
 	    ((TypeStruct *)to)->sym->search(0, Id::call, 0)
 	   )
 	{
@@ -7031,6 +7202,18 @@
 	    e = e->semantic(sc);
 	    return e;
 	}
+
+	// Struct casts are possible only when the sizes match
+	if (tob->ty == Tstruct || t1b->ty == Tstruct)
+	{
+	    size_t fromsize = t1b->size(loc);
+	    size_t tosize = tob->size(loc);
+	    if (fromsize != tosize)
+	    {
+		error("cannot cast from %s to %s", e1->type->toChars(), to->toChars());
+		return new ErrorExp();
+	    }
+	}
     }
     e = e1->castTo(sc, to);
     return e;
@@ -7737,7 +7920,7 @@
 
 /************************************************************/
 
-/* Can be TOKconstruct too */
+/* op can be TOKassign, TOKconstruct, or TOKblit */
 
 AssignExp::AssignExp(Loc loc, Expression *e1, Expression *e2)
 	: BinExp(loc, TOKassign, sizeof(AssignExp), e1, e2)
@@ -7746,26 +7929,39 @@
 }
 
 Expression *AssignExp::semantic(Scope *sc)
-{   Type *t1;
+{
     Expression *e1old = e1;
 
 #if LOGSEMANTIC
     printf("AssignExp::semantic('%s')\n", toChars());
 #endif
     //printf("e1->op = %d, '%s'\n", e1->op, Token::toChars(e1->op));
+    //printf("e2->op = %d, '%s'\n", e2->op, Token::toChars(e2->op));
+
+    if (type)
+	return this;
+
+    if (e2->op == TOKcomma)
+    {	/* Rewrite to get rid of the comma from rvalue
+	 */
+	AssignExp *ea = new AssignExp(loc, e1, ((CommaExp *)e2)->e2);
+	ea->op = op;
+	Expression *e = new CommaExp(loc, ((CommaExp *)e2)->e1, ea);
+	return e->semantic(sc);
+    }
 
     /* Look for operator overloading of a[i]=value.
      * Do it before semantic() otherwise the a[i] will have been
      * converted to a.opIndex() already.
      */
     if (e1->op == TOKarray)
-    {	Type *t1;
+    {
 	ArrayExp *ae = (ArrayExp *)e1;
 	AggregateDeclaration *ad;
 	Identifier *id = Id::index;
 
 	ae->e1 = ae->e1->semantic(sc);
-	t1 = ae->e1->type->toBasetype();
+	Type *t1 = ae->e1->type->toBasetype();
 	if (t1->ty == Tstruct)
 	{
 	    ad = ((TypeStruct *)t1)->sym;
@@ -7880,13 +8076,20 @@
 	}
     }
 
-    t1 = e1->type->toBasetype();
+    // Determine if this is an initialization of a reference
+    int refinit = 0;
+    if (op == TOKconstruct && e1->op == TOKvar)
+    {	VarExp *ve = (VarExp *)e1;
+	VarDeclaration *v = ve->var->isVarDeclaration();
+	if (v->storage_class & (STCout | STCref))
+	    refinit = 1;
+    }
+
+    Type *t1 = e1->type->toBasetype();
 
     if (t1->ty == Tfunction)
     {	// Rewrite f=value to f(value)
-	Expression *e;
-
-	e = new CallExp(loc, e1, e2);
+	Expression *e = new CallExp(loc, e1, e2);
 	e = e->semantic(sc);
 	return e;
     }
@@ -7918,7 +8121,8 @@
     else
     {	// Try to do a decent error message with the expression
 	// before it got constant folded
-	e1 = e1->modifiableLvalue(sc, e1old);
+	if (op != TOKconstruct)
+	    e1 = e1->modifiableLvalue(sc, e1old);
     }
 
     if (e1->op == TOKslice &&
@@ -7930,7 +8134,7 @@
 	ismemset = 1;	// make it easy for back end to tell what this is
 	e2 = e2->implicitCastTo(sc, t1->next);
     }
-    else if (t1->ty == Tsarray)
+    else if (t1->ty == Tsarray && !refinit)
     {
 	error("cannot assign to static array %s", e1->toChars());
     }
@@ -8061,6 +8265,7 @@
 	    typeCombine(sc);
 	    e1->checkArithmetic();
 	    e2->checkArithmetic();
+	    checkComplexAddAssign();
 	    if (type->isreal() || type->isimaginary())
 	    {
 		assert(global.errors || e2->type->isfloating());
@@ -8111,6 +8316,7 @@
     {
 	e1 = e1->checkArithmetic();
 	e2 = e2->checkArithmetic();
+	checkComplexAddAssign();
 	type = e1->type;
 	typeCombine(sc);
 	if (type->isreal() || type->isimaginary())
@@ -8215,6 +8421,7 @@
     typeCombine(sc);
     e1->checkArithmetic();
     e2->checkArithmetic();
+    checkComplexMulAssign();
     if (e2->type->isfloating())
     {	Type *t1;
 	Type *t2;
@@ -8281,6 +8488,7 @@
     typeCombine(sc);
     e1->checkArithmetic();
     e2->checkArithmetic();
+    checkComplexMulAssign();
     if (e2->type->isimaginary())
     {	Type *t1;
 	Type *t2;
@@ -8328,6 +8536,8 @@
 
 Expression *ModAssignExp::semantic(Scope *sc)
 {
+    BinExp::semantic(sc);
+    checkComplexMulAssign();
     return commonSemanticAssign(sc);
 }
 
@@ -8736,10 +8946,10 @@
 	return e;
 
     typeCombine(sc);
-    if (e1->op != TOKslice && e2->op != TOKslice)
-    {	e1->checkArithmetic();
+    if (!e1->isArrayOperand())
+	e1->checkArithmetic();
+    if (!e2->isArrayOperand())
 	e2->checkArithmetic();
-    }
     if (type->isfloating())
     {	Type *t1 = e1->type;
 	Type *t2 = e2->type;
@@ -8802,10 +9012,10 @@
 	return e;
 
     typeCombine(sc);
-    if (e1->op != TOKslice && e2->op != TOKslice)
-    {	e1->checkArithmetic();
+    if (!e1->isArrayOperand())
+	e1->checkArithmetic();
+    if (!e2->isArrayOperand())
 	e2->checkArithmetic();
-    }
     if (type->isfloating())
     {	Type *t1 = e1->type;
 	Type *t2 = e2->type;
@@ -8869,10 +9079,10 @@
 	return e;
 
     typeCombine(sc);
-    if (e1->op != TOKslice && e2->op != TOKslice)
-    {	e1->checkArithmetic();
+    if (!e1->isArrayOperand())
+	e1->checkArithmetic();
+    if (!e2->isArrayOperand())
 	e2->checkArithmetic();
-    }
     if (type->isfloating())
     {	type = e1->type;
 	if (e2->type->iscomplex())
@@ -8983,10 +9193,10 @@
 	else
 	{
 	    typeCombine(sc);
-	    if (e1->op != TOKslice && e2->op != TOKslice)
-	    {   e1->checkIntegral();
+	    if (!e1->isArrayOperand())
+		e1->checkIntegral();
+	    if (!e2->isArrayOperand())
 		e2->checkIntegral();
-	    }
 	}
     }
     return this;
@@ -9016,10 +9226,10 @@
 	else
 	{
 	    typeCombine(sc);
-	    if (e1->op != TOKslice && e2->op != TOKslice)
-	    {   e1->checkIntegral();
+	    if (!e1->isArrayOperand())
+		e1->checkIntegral();
+	    if (!e2->isArrayOperand())
 		e2->checkIntegral();
-	    }
 	}
     }
     return this;
@@ -9049,10 +9259,10 @@
 	else
 	{
 	    typeCombine(sc);
-	    if (e1->op != TOKslice && e2->op != TOKslice)
-	    {   e1->checkIntegral();
+	    if (!e1->isArrayOperand())
+		e1->checkIntegral();
+	    if (!e2->isArrayOperand())
 		e2->checkIntegral();
-	    }
 	}
     }
     return this;
@@ -9254,8 +9464,6 @@
 
 Expression *CmpExp::semantic(Scope *sc)
 {   Expression *e;
-    Type *t1;
-    Type *t2;
 
 #if LOGSEMANTIC
     printf("CmpExp::semantic('%s')\n", toChars());
@@ -9265,8 +9473,10 @@
 
     BinExp::semanticp(sc);
 
-    if (e1->type->toBasetype()->ty == Tclass && e2->op == TOKnull ||
-	e2->type->toBasetype()->ty == Tclass && e1->op == TOKnull)
+    Type *t1 = e1->type->toBasetype();
+    Type *t2 = e2->type->toBasetype();
+    if (t1->ty == Tclass && e2->op == TOKnull ||
+	t2->ty == Tclass && e1->op == TOKnull)
     {
 	error("do not use null when comparing class types");
     }
@@ -9286,6 +9496,15 @@
 	return e;
     }
 
+    /* Disallow comparing T[]==T and T==T[]
+     */
+    if (e1->op == TOKslice && t1->ty == Tarray && e2->implicitConvTo(t1->nextOf()) ||
+	e2->op == TOKslice && t2->ty == Tarray && e1->implicitConvTo(t2->nextOf()))
+    {
+	incompatibleTypes();
+	return new ErrorExp();
+    }
+
     typeCombine(sc);
     type = Type::tboolean;
 
@@ -9337,8 +9556,6 @@
 
 Expression *EqualExp::semantic(Scope *sc)
 {   Expression *e;
-    Type *t1;
-    Type *t2;
 
     //printf("EqualExp::semantic('%s')\n", toChars());
     if (type)
@@ -9367,8 +9584,10 @@
 	}
     }
 
-    if (e1->type->toBasetype()->ty == Tclass && e2->op == TOKnull ||
-	e2->type->toBasetype()->ty == Tclass && e1->op == TOKnull)
+    Type *t1 = e1->type->toBasetype();
+    Type *t2 = e2->type->toBasetype();
+    if (t1->ty == Tclass && e2->op == TOKnull ||
+	t2->ty == Tclass && e1->op == TOKnull)
     {
 	error("use '%s' instead of '%s' when comparing with null",
 		Token::toChars(op == TOKequal ? TOKidentity : TOKnotidentity),
@@ -9389,6 +9608,15 @@
 	}
     }
 
+    /* Disallow comparing T[]==T and T==T[]
+     */
+    if (e1->op == TOKslice && t1->ty == Tarray && e2->implicitConvTo(t1->nextOf()) ||
+	e2->op == TOKslice && t2->ty == Tarray && e1->implicitConvTo(t2->nextOf()))
+    {
+	incompatibleTypes();
+	return new ErrorExp();
+    }
+
     e = typeCombine(sc);
     type = Type::tboolean;
 
--- a/dmd/expression.h	Fri Nov 06 21:51:41 2009 +0100
+++ b/dmd/expression.h	Fri Nov 06 23:58:01 2009 +0100
@@ -81,6 +81,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
@@ -157,6 +162,7 @@
     // For array ops
     virtual void buildArrayIdent(OutBuffer *buf, Expressions *arguments);
     virtual Expression *buildArrayLoop(Arguments *fparams);
+    int isArrayOperand();
 
 #if IN_DMD
     // Back end
@@ -291,6 +297,7 @@
 struct DsymbolExp : Expression
 {
     Dsymbol *s;
+    int hasOverloads;
 
     DsymbolExp(Loc loc, Dsymbol *s);
     Expression *semantic(Scope *sc);
@@ -306,6 +313,7 @@
 
     ThisExp(Loc loc);
     Expression *semantic(Scope *sc);
+    Expression *interpret(InterState *istate);
     int isBool(int result);
     void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
     Expression *toLvalue(Scope *sc, Expression *e);
@@ -343,6 +351,7 @@
     NullExp(Loc loc);
     Expression *semantic(Scope *sc);
     int isBool(int result);
+    int isConst();
     void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
     void toMangleBuffer(OutBuffer *buf);
     MATCH implicitConvTo(Type *t);
@@ -591,6 +600,7 @@
 	Type *newtype, Expressions *arguments);
     Expression *syntaxCopy();
     Expression *semantic(Scope *sc);
+    Expression *optimize(int result);
 #if IN_DMD
     elem *toElem(IRState *irs);
 #endif
@@ -842,6 +852,8 @@
     Expression *commonSemanticAssign(Scope *sc);
     Expression *commonSemanticAssignIntegral(Scope *sc);
     int checkSideEffect(int flag);
+    void checkComplexMulAssign();
+    void checkComplexAddAssign();
     void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
     Expression *scaleFactor(Scope *sc);
     Expression *typeCombine(Scope *sc);
@@ -1022,6 +1034,7 @@
 #endif
     void scanForNestedRef(Scope *sc);
     Expression *toLvalue(Scope *sc, Expression *e);
+    Expression *modifiableLvalue(Scope *sc, Expression *e);
 
     int inlineCost(InlineCostState *ics);
     Expression *doInline(InlineDoState *ids);
@@ -1182,6 +1195,8 @@
     int checkSideEffect(int flag);
     void checkEscape();
     void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+    void buildArrayIdent(OutBuffer *buf, Expressions *arguments);
+    Expression *buildArrayLoop(Arguments *fparams);
 #if IN_DMD
     elem *toElem(IRState *irs);
 #endif
--- a/dmd/func.c	Fri Nov 06 21:51:41 2009 +0100
+++ b/dmd/func.c	Fri Nov 06 23:58:01 2009 +0100
@@ -1,3081 +1,3451 @@
-// Compiler implementation of the D programming language
-// Copyright (c) 1999-2008 by Digital Mars
-// All Rights Reserved
-// written by Walter Bright
-// http://www.digitalmars.com
-// License for redistribution is by either the Artistic License
-// in artistic.txt, or the GNU General Public License in gnu.txt.
-// See the included readme.txt for details.
-
-#include <stdio.h>
-#include <assert.h>
-
-#include "mars.h"
-#include "init.h"
-#include "declaration.h"
-#include "attrib.h"
-#include "expression.h"
-#include "scope.h"
-#include "mtype.h"
-#include "aggregate.h"
-#include "identifier.h"
-#include "id.h"
-#include "module.h"
-#include "statement.h"
-#include "template.h"
-#include "hdrgen.h"
-
-#ifdef IN_GCC
-#include "d-dmd-gcc.h"
-#endif
-
-/********************************* FuncDeclaration ****************************/
-
-FuncDeclaration::FuncDeclaration(Loc loc, Loc endloc, Identifier *id, enum STC storage_class, Type *type)
-    : Declaration(id)
-{
-    //printf("FuncDeclaration(id = '%s', type = %p)\n", id->toChars(), type);
-    this->storage_class = storage_class;
-    this->type = type;
-    this->loc = loc;
-    this->endloc = endloc;
-    fthrows = NULL;
-    frequire = NULL;
-    outId = NULL;
-    vresult = NULL;
-    returnLabel = NULL;
-    fensure = NULL;
-    fbody = NULL;
-    localsymtab = NULL;
-    vthis = NULL;
-    v_arguments = NULL;
-#if IN_GCC
-    v_argptr = NULL;
-#endif
-    parameters = NULL;
-    labtab = NULL;
-    overnext = NULL;
-    vtblIndex = -1;
-    hasReturnExp = 0;
-    naked = 0;
-    inlineStatus = ILSuninitialized;
-    inlineNest = 0;
-    inlineAsm = 0;
-    cantInterpret = 0;
-    semanticRun = 0;
-    nestedFrameRef = 0;
-    fes = NULL;
-    introducing = 0;
-    tintro = NULL;
-    /* The type given for "infer the return type" is a TypeFunction with
-     * 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 IN_LLVM
-    // LDC
-    isArrayOp = false;
-    allowInlining = false;
-
-    availableExternally = true; // assume this unless proven otherwise
-
-    // function types in ldc don't merge if the context parameter differs
-    // so we actually don't care about the function declaration, but only
-    // what kind of context parameter it has.
-    // however, this constructor is usually called from the parser, which
-    // unfortunately doesn't provide the information needed to get to the
-    // aggregate type. So we have to stick with the FuncDeclaration and
-    // just be sure we don't actually rely on the symbol it points to,
-    // but rather just the type of its context parameter.
-    // this means some function might have a function type pointing to
-    // another function declaration
-
-    if (type)
-    {
-        assert(type->ty == Tfunction && "invalid function type");
-        TypeFunction* tf = (TypeFunction*)type;
-        if (tf->funcdecl == NULL)
-            tf->funcdecl = this;
-    }
-#endif
-}
-
-Dsymbol *FuncDeclaration::syntaxCopy(Dsymbol *s)
-{
-    FuncDeclaration *f;
-
-    //printf("FuncDeclaration::syntaxCopy('%s')\n", toChars());
-    if (s)
-	f = (FuncDeclaration *)s;
-    else
-	f = new FuncDeclaration(loc, endloc, ident, (enum STC) storage_class, type->syntaxCopy());
-    f->outId = outId;
-    f->frequire = frequire ? frequire->syntaxCopy() : NULL;
-    f->fensure  = fensure  ? fensure->syntaxCopy()  : NULL;
-    f->fbody    = fbody    ? fbody->syntaxCopy()    : NULL;
-    assert(!fthrows); // deprecated
-
-    // LDC
-    f->intrinsicName = intrinsicName;
-
-    return f;
-}
-
-
-// Do the semantic analysis on the external interface to the function.
-
-void FuncDeclaration::semantic(Scope *sc)
-{   TypeFunction *f;
-    StructDeclaration *sd;
-    ClassDeclaration *cd;
-    InterfaceDeclaration *id;
-    Dsymbol *pd;
-
-#if 0
-    printf("FuncDeclaration::semantic(sc = %p, this = %p, '%s', linkage = %d)\n", sc, this, toPrettyChars(), sc->linkage);
-    if (isFuncLiteralDeclaration())
-	printf("\tFuncLiteralDeclaration()\n");
-    printf("sc->parent = %s\n", sc->parent->toChars());
-    printf("type: %p, %s\n", type, type->toChars());
-#endif
-
-    if (semanticRun && isFuncLiteralDeclaration())
-    {
-	/* Member functions that have return types that are
-	 * forward references can have semantic() run more than
-	 * once on them.
-	 * See test\interface2.d, test20
-	 */
-	return;
-    }
-    assert(semanticRun <= 1);
-    semanticRun = 1;
-
-    if (type->nextOf())
-	type = type->semantic(loc, sc);
-    //type->print();
-    if (type->ty != Tfunction)
-    {
-	error("%s must be a function", toChars());
-	return;
-    }
-    f = (TypeFunction *)(type);
-    size_t nparams = Argument::dim(f->parameters);
-
-    linkage = sc->linkage;
-//    if (!parent)
-    {
-	//parent = sc->scopesym;
-	parent = sc->parent;
-    }
-    protection = sc->protection;
-    storage_class |= sc->stc;
-    //printf("function storage_class = x%x\n", storage_class);
-    Dsymbol *parent = toParent();
-
-    if (ident == Id::ctor && !isCtorDeclaration())
-	error("_ctor is reserved for constructors");
-
-    if (isConst() || isAuto() || isScope())
-	error("functions cannot be const, auto or scope");
-
-    if (isAbstract() && !isVirtual())
-	error("non-virtual functions cannot be abstract");
-
-    if (isAbstract() && isFinal())
-	error("cannot be both final and abstract");
-#if 0
-    if (isAbstract() && fbody)
-	error("abstract functions cannot have bodies");
-#endif
-
-#if 0
-    if (isStaticConstructor() || isStaticDestructor())
-    {
-	if (!isStatic() || type->nextOf()->ty != Tvoid)
-	    error("static constructors / destructors must be static void");
-	if (f->arguments && f->arguments->dim)
-	    error("static constructors / destructors must have empty parameter list");
-	// BUG: check for invalid storage classes
-    }
-#endif
-
-#ifdef IN_GCC
-    AggregateDeclaration *ad;
-
-    ad = parent->isAggregateDeclaration();
-    if (ad)
-	ad->methods.push(this);
-#endif
-    sd = parent->isStructDeclaration();
-    if (sd)
-    {
-	// Verify no constructors, destructors, etc.
-	if (isCtorDeclaration() ||
-	    isDtorDeclaration()
-	    //|| isInvariantDeclaration()
-	    //|| isUnitTestDeclaration()
-	   )
-	{
-	    error("special member functions not allowed for %ss", sd->kind());
-	}
-
-#if 0
-	if (!sd->inv)
-	    sd->inv = isInvariantDeclaration();
-
-	if (!sd->aggNew)
-	    sd->aggNew = isNewDeclaration();
-
-	if (isDelete())
-	{
-	    if (sd->aggDelete)
-		error("multiple delete's for struct %s", sd->toChars());
-	    sd->aggDelete = (DeleteDeclaration *)(this);
-	}
-#endif
-    }
-
-    id = parent->isInterfaceDeclaration();
-    if (id)
-    {
-	storage_class |= STCabstract;
-
-	if (isCtorDeclaration() ||
-	    isDtorDeclaration() ||
-	    isInvariantDeclaration() ||
-	    isUnitTestDeclaration() || isNewDeclaration() || isDelete())
-	    error("special function not allowed in interface %s", id->toChars());
-	if (fbody)
-	    error("function body is not abstract in interface %s", id->toChars());
-    }
-
-    /* Template member functions aren't virtual:
-     *   interface TestInterface { void tpl(T)(); }
-     * and so won't work in interfaces
-     */
-    if ((pd = toParent()) != NULL &&
-	pd->isTemplateInstance() &&
-	(pd = toParent2()) != NULL &&
-	(id = pd->isInterfaceDeclaration()) != NULL)
-    {
-	error("template member function not allowed in interface %s", id->toChars());
-    }
-
-    cd = parent->isClassDeclaration();
-    if (cd)
-    {	int vi;
-	CtorDeclaration *ctor;
-	DtorDeclaration *dtor;
-	InvariantDeclaration *inv;
-
-	if (isCtorDeclaration())
-	{
-//	    ctor = (CtorDeclaration *)this;
-//	    if (!cd->ctor)
-//		cd->ctor = ctor;
-	    return;
-	}
-
-#if 0
-	dtor = isDtorDeclaration();
-	if (dtor)
-	{
-	    if (cd->dtor)
-		error("multiple destructors for class %s", cd->toChars());
-	    cd->dtor = dtor;
-	}
-
-	inv = isInvariantDeclaration();
-	if (inv)
-	{
-	    cd->inv = inv;
-	}
-
-	if (isNewDeclaration())
-	{
-	    if (!cd->aggNew)
-		cd->aggNew = (NewDeclaration *)(this);
-	}
-
-	if (isDelete())
-	{
-	    if (cd->aggDelete)
-		error("multiple delete's for class %s", cd->toChars());
-	    cd->aggDelete = (DeleteDeclaration *)(this);
-	}
-#endif
-
-	if (storage_class & STCabstract)
-	    cd->isabstract = 1;
-
-	// if static function, do not put in vtbl[]
-	if (!isVirtual())
-	{
-	    //printf("\tnot virtual\n");
-	    goto Ldone;
-	}
-
-	// Find index of existing function in vtbl[] to override
-	vi = findVtblIndex(&cd->vtbl, cd->baseClass ? cd->baseClass->vtbl.dim : 0);
-	switch (vi)
-	{
-	    case -1:
-		/* Didn't find one, so
-		 * This is an 'introducing' function which gets a new
-		 * slot in the vtbl[].
-		 */
-
-		// Verify this doesn't override previous final function
-		if (cd->baseClass)
-		{   Dsymbol *s = cd->baseClass->search(loc, ident, 0);
-		    if (s)
-		    {
-			FuncDeclaration *f = s->isFuncDeclaration();
-			f = f->overloadExactMatch(type, getModule());
-			if (f && f->isFinal() && f->prot() != PROTprivate)
-			    error("cannot override final function %s", f->toPrettyChars());
-		    }
-		}
-
-		if (isFinal())
-		{
-		    if (isOverride())
-			error("does not override any function");
-		    cd->vtblFinal.push(this);
-		}
-		else
-		{
-		    // Append to end of vtbl[]
-		    //printf("\tintroducing function\n");
-		    introducing = 1;
-		    vi = cd->vtbl.dim;
-		    cd->vtbl.push(this);
-		    vtblIndex = vi;
-		}
-		break;
-
-	    case -2:	// can't determine because of fwd refs
-		cd->sizeok = 2;	// can't finish due to forward reference
-		return;
-
-	    default:
-	    {   FuncDeclaration *fdv = (FuncDeclaration *)cd->vtbl.data[vi];
-		// This function is covariant with fdv
-		if (fdv->isFinal())
-		    error("cannot override final function %s", fdv->toPrettyChars());
-
-#if DMDV2
-		if (!isOverride())
-		    warning(loc, "overrides base class function %s, but is not marked with 'override'", fdv->toPrettyChars());
-#endif
-
-		if (fdv->toParent() == parent)
-		{
-		    // If both are mixins, then error.
-		    // If either is not, the one that is not overrides
-		    // the other.
-		    if (fdv->parent->isClassDeclaration())
-			break;
-		    if (!this->parent->isClassDeclaration()
-#if !BREAKABI
-			&& !isDtorDeclaration()
-#endif
-#if DMDV2
-			&& !isPostBlitDeclaration()
-#endif
-			)
-			error("multiple overrides of same function");
-		}
-		cd->vtbl.data[vi] = (void *)this;
-		vtblIndex = vi;
-
-		/* This works by whenever this function is called,
-		 * it actually returns tintro, which gets dynamically
-		 * cast to type. But we know that tintro is a base
-		 * of type, so we could optimize it by not doing a
-		 * dynamic cast, but just subtracting the isBaseOf()
-		 * offset if the value is != null.
-		 */
-
-		if (fdv->tintro)
-		    tintro = fdv->tintro;
-		else if (!type->equals(fdv->type))
-		{
-		    /* Only need to have a tintro if the vptr
-		     * offsets differ
-		     */
-		    int offset;
-		    if (fdv->type->nextOf()->isBaseOf(type->nextOf(), &offset))
-		    {
-			tintro = fdv->type;
-		    }
-		}
-		break;
-	    }
-	}
-
-	/* Go through all the interface bases.
-	 * If this function is covariant with any members of those interface
-	 * functions, set the tintro.
-	 */
-	for (int i = 0; i < cd->interfaces_dim; i++)
-	{
-#if 1
-	    BaseClass *b = cd->interfaces[i];
-	    vi = findVtblIndex(&b->base->vtbl, b->base->vtbl.dim);
-	    switch (vi)
-	    {
-		case -1:
-		    break;
-
-		case -2:
-		    cd->sizeok = 2;	// can't finish due to forward reference
-		    return;
-
-		default:
-		{   FuncDeclaration *fdv = (FuncDeclaration *)b->base->vtbl.data[vi];
-		    Type *ti = NULL;
-
-		    if (fdv->tintro)
-			ti = fdv->tintro;
-		    else if (!type->equals(fdv->type))
-		    {
-			/* Only need to have a tintro if the vptr
-			 * offsets differ
-			 */
-			int offset;
-			if (fdv->type->nextOf()->isBaseOf(type->nextOf(), &offset))
-			{
-			    ti = fdv->type;
-#if 0
-			    if (offset)
-				ti = fdv->type;
-			    else if (type->nextOf()->ty == Tclass)
-			    {   ClassDeclaration *cdn = ((TypeClass *)type->nextOf())->sym;
-				if (cdn && cdn->sizeok != 1)
-				    ti = fdv->type;
-			    }
-#endif
-			}
-		    }
-		    if (ti)
-		    {
-			if (tintro && !tintro->equals(ti))
-			{
-			    error("incompatible covariant types %s and %s", tintro->toChars(), ti->toChars());
-			}
-			tintro = ti;
-		    }
-		    goto L2;
-		}
-	    }
-#else
-	    BaseClass *b = cd->interfaces[i];
-	    for (vi = 0; vi < b->base->vtbl.dim; vi++)
-	    {
-		Dsymbol *s = (Dsymbol *)b->base->vtbl.data[vi];
-		//printf("interface %d vtbl[%d] %p %s\n", i, vi, s, s->toChars());
-		FuncDeclaration *fdv = s->isFuncDeclaration();
-		if (fdv && fdv->ident == ident)
-		{
-		    int cov = type->covariant(fdv->type);
-		    //printf("\tcov = %d\n", cov);
-		    if (cov == 2)
-		    {
-			//type->print();
-			//fdv->type->print();
-			//printf("%s %s\n", type->deco, fdv->type->deco);
-			error("of type %s overrides but is not covariant with %s of type %s",
-			    type->toChars(), fdv->toPrettyChars(), fdv->type->toChars());
-		    }
-		    if (cov == 1)
-		    {	Type *ti = NULL;
-
-			if (fdv->tintro)
-			    ti = fdv->tintro;
-			else if (!type->equals(fdv->type))
-			{
-			    /* Only need to have a tintro if the vptr
-			     * offsets differ
-			     */
-			    int offset;
-			    if (fdv->type->nextOf()->isBaseOf(type->nextOf(), &offset))
-			    {
-				ti = fdv->type;
-#if 0
-				if (offset)
-				    ti = fdv->type;
-				else if (type->nextOf()->ty == Tclass)
-				{   ClassDeclaration *cdn = ((TypeClass *)type->nextOf())->sym;
-				    if (cdn && cdn->sizeok != 1)
-					ti = fdv->type;
-				}
-#endif
-			    }
-			}
-			if (ti)
-			{
-			    if (tintro && !tintro->equals(ti))
-			    {
-				error("incompatible covariant types %s and %s", tintro->toChars(), ti->toChars());
-			    }
-			    tintro = ti;
-			}
-			goto L2;
-		    }
-		    if (cov == 3)
-		    {
-			cd->sizeok = 2;	// can't finish due to forward reference
-			return;
-		    }
-		}
-	    }
-#endif
-	}
-
-	if (introducing && isOverride())
-	{
-	    error("does not override any function");
-	}
-
-    L2: ;
-    }
-    else if (isOverride() && !parent->isTemplateInstance())
-	error("override only applies to class member functions");
-
-    /* Do not allow template instances to add virtual functions
-     * to a class.
-     */
-    if (isVirtual())
-    {
-	TemplateInstance *ti = parent->isTemplateInstance();
-	if (ti)
-	{
-	    // Take care of nested templates
-	    while (1)
-	    {
-		TemplateInstance *ti2 = ti->tempdecl->parent->isTemplateInstance();
-		if (!ti2)
-		    break;
-		ti = ti2;
-	    }
-
-	    // If it's a member template
-	    ClassDeclaration *cd = ti->tempdecl->isClassMember();
-	    if (cd)
-	    {
-		error("cannot use template to add virtual function to class '%s'", cd->toChars());
-	    }
-	}
-    }
-
-    if (isMain())
-    {
-	// Check parameters to see if they are either () or (char[][] args)
-	switch (nparams)
-	{
-	    case 0:
-		break;
-
-	    case 1:
-	    {
-		Argument *arg0 = Argument::getNth(f->parameters, 0);
-		if (arg0->type->ty != Tarray ||
-		    arg0->type->nextOf()->ty != Tarray ||
-		    arg0->type->nextOf()->nextOf()->ty != Tchar ||
-		    arg0->storageClass & (STCout | STCref | STClazy))
-		    goto Lmainerr;
-		break;
-	    }
-
-	    default:
-		goto Lmainerr;
-	}
-
-	if (f->nextOf()->ty != Tint32 && f->nextOf()->ty != Tvoid)
-	    error("must return int or void, not %s", f->nextOf()->toChars());
-	if (f->varargs)
-	{
-	Lmainerr:
-	    error("parameters must be main() or main(char[][] args)");
-	}
-    }
-
-    if (ident == Id::assign && (sd || cd))
-    {	// Disallow identity assignment operator.
-
-	// opAssign(...)
-	if (nparams == 0)
-	{   if (f->varargs == 1)
-		goto Lassignerr;
-	}
-	else
-	{
-	    Argument *arg0 = Argument::getNth(f->parameters, 0);
-	    Type *t0 = arg0->type->toBasetype();
-	    Type *tb = sd ? sd->type : cd->type;
-	    if (arg0->type->implicitConvTo(tb) ||
-		(sd && t0->ty == Tpointer && t0->nextOf()->implicitConvTo(tb))
-	       )
-	    {
-		if (nparams == 1)
-		    goto Lassignerr;
-		Argument *arg1 = Argument::getNth(f->parameters, 1);
-		if (arg1->defaultArg)
-		    goto Lassignerr;
-	    }
-	}
-    }
-
-Ldone:
-    /* Save scope for possible later use (if we need the
-     * function internals)
-     */
-    scope = new Scope(*sc);
-    scope->setNoFree();
-    return;
-
-Lassignerr:
-    error("identity assignment operator overload is illegal");
-}
-
-void FuncDeclaration::semantic2(Scope *sc)
-{
-}
-
-// Do the semantic analysis on the internals of the function.
-
-void FuncDeclaration::semantic3(Scope *sc)
-{   TypeFunction *f;
-    AggregateDeclaration *ad;
-    VarDeclaration *argptr = NULL;
-    VarDeclaration *_arguments = NULL;
-
-    if (!parent)
-    {
-	if (global.errors)
-	    return;
-	//printf("FuncDeclaration::semantic3(%s '%s', sc = %p)\n", kind(), toChars(), sc);
-	assert(0);
-    }
-    //printf("FuncDeclaration::semantic3('%s.%s', sc = %p, loc = %s)\n", parent->toChars(), toChars(), sc, loc.toChars());
-    //fflush(stdout);
-    //{ static int x; if (++x == 2) *(char*)0=0; }
-    //printf("\tlinkage = %d\n", sc->linkage);
-
-    //printf(" sc->incontract = %d\n", sc->incontract);
-    if (semanticRun >= 3)
-	return;
-    semanticRun = 3;
-
-    // LDC
-    if (!global.params.useAvailableExternally)
-        availableExternally = false;
-
-    if (!type || type->ty != Tfunction)
-	return;
-    f = (TypeFunction *)(type);
-    size_t nparams = Argument::dim(f->parameters);
-
-    // Check the 'throws' clause
-    if (fthrows)
-    {
-	for (int i = 0; i < fthrows->dim; i++)
-	{
-	    Type *t = (Type *)fthrows->data[i];
-
-	    t = t->semantic(loc, sc);
-	    if (!t->isClassHandle())
-		error("can only throw classes, not %s", t->toChars());
-	}
-    }
-
-    if (fbody || frequire)
-    {
-	/* Symbol table into which we place parameters and nested functions,
-	 * solely to diagnose name collisions.
-	 */
-	localsymtab = new DsymbolTable();
-
-	// Establish function scope
-	ScopeDsymbol *ss = new ScopeDsymbol();
-	ss->parent = sc->scopesym;
-	Scope *sc2 = sc->push(ss);
-	sc2->func = this;
-	sc2->parent = this;
-	sc2->callSuper = 0;
-	sc2->sbreak = NULL;
-	sc2->scontinue = NULL;
-	sc2->sw = NULL;
-	sc2->fes = fes;
-	sc2->linkage = LINKd;
-	sc2->stc &= ~(STCauto | STCscope | STCstatic | STCabstract | STCdeprecated | STCfinal);
-	sc2->protection = PROTpublic;
-	sc2->explicitProtection = 0;
-	sc2->structalign = 8;
-	sc2->incontract = 0;
-	sc2->enclosingFinally = NULL;
-	sc2->enclosingScopeExit = NULL;
-	sc2->noctor = 0;
-
-	// Declare 'this'
-	ad = isThis();
-	if (ad)
-	{   VarDeclaration *v;
-
-	    if (isFuncLiteralDeclaration() && isNested())
-	    {
-		error("literals cannot be class members");
-		return;
-	    }
-	    else
-	    {
-		assert(!isNested());	// can't be both member and nested
-		assert(ad->handle);
-		v = new ThisDeclaration(loc, ad->handle);
-		v->storage_class |= STCparameter | STCin;
-		v->semantic(sc2);
-		if (!sc2->insert(v))
-		    assert(0);
-		v->parent = this;
-		vthis = v;
-	    }
-	}
-	else if (isNested())
-	{
-	    /* The 'this' for a nested function is the link to the
-	     * enclosing function's stack frame.
-	     * Note that nested functions and member functions are disjoint.
-	     */
-	    VarDeclaration *v = new ThisDeclaration(loc, Type::tvoid->pointerTo());
-	    v->storage_class |= STCparameter | STCin;
-	    v->semantic(sc2);
-	    if (!sc2->insert(v))
-		assert(0);
-	    v->parent = this;
-	    vthis = v;
-	}
-
-	// Declare hidden variable _arguments[] and _argptr
-	if (f->varargs == 1)
-	{   Type *t;
-
-	    if (f->linkage == LINKd)
-	    {	// Declare _arguments[]
-#if BREAKABI
-		v_arguments = new VarDeclaration(0, Type::typeinfotypelist->type, Id::_arguments_typeinfo, NULL);
-		v_arguments->storage_class = STCparameter | STCin;
-		v_arguments->semantic(sc2);
-		sc2->insert(v_arguments);
-		v_arguments->parent = this;
-
-		t = Type::typeinfo->type->arrayOf();
-		_arguments = new VarDeclaration(0, t, Id::_arguments, NULL);
-		_arguments->semantic(sc2);
-		sc2->insert(_arguments);
-		_arguments->parent = this;
-#else
-		t = Type::typeinfo->type->arrayOf();
-		v_arguments = new VarDeclaration(0, t, Id::_arguments, NULL);
-		v_arguments->storage_class = STCparameter | STCin;
-		v_arguments->semantic(sc2);
-		sc2->insert(v_arguments);
-		v_arguments->parent = this;
-#endif
-	    }
-	    if (f->linkage == LINKd || (parameters && parameters->dim))
-	    {	// Declare _argptr
-#if IN_GCC
-		t = d_gcc_builtin_va_list_d_type;
-#else
-		t = Type::tvoid->pointerTo();
-#endif
-		argptr = new VarDeclaration(0, t, Id::_argptr, NULL);
-		argptr->semantic(sc2);
-		sc2->insert(argptr);
-		argptr->parent = this;
-	    }
-	}
-
-#if IN_LLVM
-        // LDC make sure argument type is semanticed.
-        // Turns TypeTuple!(int, int) into two int parameters, for instance.
-        if (f->parameters)
-        {
-            for (size_t i = 0; i < Argument::dim(f->parameters); i++)
-	    {	Argument *arg = (Argument *)Argument::getNth(f->parameters, i);
-                Type* nw = arg->type->semantic(0, sc);
-                if (arg->type != nw) {
-                    arg->type = nw;
-                    // Examine this index again.
-                    // This is important if it turned into a tuple.
-                    // In particular, the empty tuple should be handled or the
-                    // next parameter will be skipped.
-                    // FIXME: Maybe we only need to do this for tuples,
-                    //        and can add tuple.length after decrement?
-                    i--;
-                }
-            }
-            // update nparams to include expanded tuples
-            nparams = Argument::dim(f->parameters);
-        }
-#endif
-
-	// Propagate storage class from tuple parameters to their element-parameters.
-	if (f->parameters)
-	{
-	    for (size_t i = 0; i < f->parameters->dim; i++)
-	    {	Argument *arg = (Argument *)f->parameters->data[i];
-
-		if (arg->type->ty == Ttuple)
-		{   TypeTuple *t = (TypeTuple *)arg->type;
-		    size_t dim = Argument::dim(t->arguments);
-		    for (size_t j = 0; j < dim; j++)
-		    {	Argument *narg = Argument::getNth(t->arguments, j);
-			narg->storageClass = arg->storageClass;
-		    }
-		}
-	    }
-	}
-
-	// Declare all the function parameters as variables
-	if (nparams)
-	{   /* parameters[] has all the tuples removed, as the back end
-	     * doesn't know about tuples
-	     */
-	    parameters = new Dsymbols();
-	    parameters->reserve(nparams);
-	    for (size_t i = 0; i < nparams; i++)
-	    {
-		Argument *arg = Argument::getNth(f->parameters, i);
-		Identifier *id = arg->ident;
-		if (!id)
-		{
-		    /* Generate identifier for un-named parameter,
-		     * because we need it later on.
-		     */
-		    arg->ident = id = Identifier::generateId("_param_", i);
-		}
-		VarDeclaration *v = new VarDeclaration(loc, arg->type, id, NULL);
-		//printf("declaring parameter %s of type %s\n", v->toChars(), v->type->toChars());
-		v->storage_class |= STCparameter;
-		if (f->varargs == 2 && i + 1 == nparams)
-		    v->storage_class |= STCvariadic;
-		v->storage_class |= arg->storageClass & (STCin | STCout | STCref | STClazy);
-		if (v->storage_class & STClazy)
-		    v->storage_class |= STCin;
-		v->semantic(sc2);
-		if (!sc2->insert(v))
-		    error("parameter %s.%s is already defined", toChars(), v->toChars());
-		else
-		    parameters->push(v);
-		localsymtab->insert(v);
-		v->parent = this;
-	    }
-	}
-
-	// Declare the tuple symbols and put them in the symbol table,
-	// but not in parameters[].
-	if (f->parameters)
-	{
-	    for (size_t i = 0; i < f->parameters->dim; i++)
-	    {	Argument *arg = (Argument *)f->parameters->data[i];
-
-		if (!arg->ident)
-		    continue;			// never used, so ignore
-		if (arg->type->ty == Ttuple)
-		{   TypeTuple *t = (TypeTuple *)arg->type;
-		    size_t dim = Argument::dim(t->arguments);
-		    Objects *exps = new Objects();
-		    exps->setDim(dim);
-		    for (size_t j = 0; j < dim; j++)
-		    {	Argument *narg = Argument::getNth(t->arguments, j);
-			assert(narg->ident);
-			VarDeclaration *v = sc2->search(0, narg->ident, NULL)->isVarDeclaration();
-			assert(v);
-			Expression *e = new VarExp(v->loc, v);
-			exps->data[j] = (void *)e;
-		    }
-		    assert(arg->ident);
-		    TupleDeclaration *v = new TupleDeclaration(loc, arg->ident, exps);
-		    //printf("declaring tuple %s\n", v->toChars());
-		    v->isexp = 1;
-		    if (!sc2->insert(v))
-			error("parameter %s.%s is already defined", toChars(), v->toChars());
-		    localsymtab->insert(v);
-		    v->parent = this;
-		}
-	    }
-	}
-
-	/* Do the semantic analysis on the [in] preconditions and
-	 * [out] postconditions.
-	 */
-	sc2->incontract++;
-
-	if (frequire)
-	{   /* frequire is composed of the [in] contracts
-	     */
-	    // BUG: need to error if accessing out parameters
-	    // BUG: need to treat parameters as const
-	    // BUG: need to disallow returns and throws
-	    // BUG: verify that all in and ref parameters are read
-	    frequire = frequire->semantic(sc2);
-	    labtab = NULL;		// so body can't refer to labels
-	}
-
-	if (fensure || addPostInvariant())
-	{   /* fensure is composed of the [out] contracts
-	     */
-	    ScopeDsymbol *sym = new ScopeDsymbol();
-	    sym->parent = sc2->scopesym;
-	    sc2 = sc2->push(sym);
-
-	    assert(type->nextOf());
-	    if (type->nextOf()->ty == Tvoid)
-	    {
-		if (outId)
-		    error("void functions have no result");
-	    }
-	    else
-	    {
-		if (!outId)
-		    outId = Id::result;		// provide a default
-	    }
-
-	    if (outId)
-	    {	// Declare result variable
-		VarDeclaration *v;
-		Loc loc = this->loc;
-
-		if (fensure)
-		    loc = fensure->loc;
-
-		v = new VarDeclaration(loc, type->nextOf(), outId, NULL);
-		v->noscope = 1;
-		sc2->incontract--;
-		v->semantic(sc2);
-		sc2->incontract++;
-		if (!sc2->insert(v))
-		    error("out result %s is already defined", v->toChars());
-		v->parent = this;
-		vresult = v;
-
-		// vresult gets initialized with the function return value
-		// in ReturnStatement::semantic()
-	    }
-
-	    // BUG: need to treat parameters as const
-	    // BUG: need to disallow returns and throws
-	    if (fensure)
-	    {	fensure = fensure->semantic(sc2);
-		labtab = NULL;		// so body can't refer to labels
-	    }
-
-	    if (!global.params.useOut)
-	    {	fensure = NULL;		// discard
-		vresult = NULL;
-	    }
-
-	    // Postcondition invariant
-	    if (addPostInvariant())
-	    {
-		Expression *e = NULL;
-		if (isCtorDeclaration())
-		{
-		    // Call invariant directly only if it exists
-		    InvariantDeclaration *inv = ad->inv;
-		    ClassDeclaration *cd = ad->isClassDeclaration();
-
-		    while (!inv && cd)
-		    {
-			cd = cd->baseClass;
-			if (!cd)
-			    break;
-			inv = cd->inv;
-		    }
-		    if (inv)
-		    {
-			e = new DsymbolExp(0, inv);
-			e = new CallExp(0, e);
-			e = e->semantic(sc2);
-		    }
-		}
-		else
-		{   // Call invariant virtually
-		    ThisExp *v = new ThisExp(0);
-		    v->type = vthis->type;
-		    e = new AssertExp(0, v);
-		}
-		if (e)
-		{
-		    ExpStatement *s = new ExpStatement(0, e);
-		    if (fensure)
-			fensure = new CompoundStatement(0, s, fensure);
-		    else
-			fensure = s;
-		}
-	    }
-
-	    if (fensure)
-	    {	returnLabel = new LabelDsymbol(Id::returnLabel);
-		LabelStatement *ls = new LabelStatement(0, Id::returnLabel, fensure);
-		ls->isReturnLabel = 1;
-		returnLabel->statement = ls;
-	    }
-	    sc2 = sc2->pop();
-	}
-
-	sc2->incontract--;
-
-	if (fbody)
-	{   ClassDeclaration *cd = isClassMember();
-
-	    /* If this is a class constructor
-	     */
-	    if (isCtorDeclaration() && cd)
-	    {
-		for (int i = 0; i < cd->fields.dim; i++)
-		{   VarDeclaration *v = (VarDeclaration *)cd->fields.data[i];
-
-		    v->ctorinit = 0;
-		}
-	    }
-
-	    if (inferRetType || f->retStyle() != RETstack)
-		nrvo_can = 0;
-
-	    fbody = fbody->semantic(sc2);
-
-	    if (inferRetType)
-	    {	// If no return type inferred yet, then infer a void
-		if (!type->nextOf())
-		{
-		    ((TypeFunction *)type)->next = Type::tvoid;
-		    type = type->semantic(loc, sc);
-		}
-		f = (TypeFunction *)type;
-	    }
-
-	    int offend = fbody ? fbody->blockExit() & BEfallthru : TRUE;
-
-	    if (isStaticCtorDeclaration())
-	    {	/* It's a static constructor. Ensure that all
-		 * ctor consts were initialized.
-		 */
-
-		Dsymbol *p = toParent();
-		ScopeDsymbol *ad = p->isScopeDsymbol();
-		if (!ad)
-		{
-		    error("static constructor can only be member of struct/class/module, not %s %s", p->kind(), p->toChars());
-		}
-		else
-		{
-		    for (int i = 0; i < ad->members->dim; i++)
-		    {   Dsymbol *s = (Dsymbol *)ad->members->data[i];
-
-			s->checkCtorConstInit();
-		    }
-		}
-	    }
-
-	    if (isCtorDeclaration() && cd)
-	    {
-		//printf("callSuper = x%x\n", sc2->callSuper);
-
-		// Verify that all the ctorinit fields got initialized
-		if (!(sc2->callSuper & CSXthis_ctor))
-		{
-		    for (int i = 0; i < cd->fields.dim; i++)
-		    {   VarDeclaration *v = (VarDeclaration *)cd->fields.data[i];
-
-			if (v->ctorinit == 0 && v->isCtorinit())
-			    error("missing initializer for const field %s", v->toChars());
-		    }
-		}
-
-		if (!(sc2->callSuper & CSXany_ctor) &&
-		    cd->baseClass && cd->baseClass->ctor)
-		{
-		    sc2->callSuper = 0;
-
-		    // Insert implicit super() at start of fbody
-		    Expression *e1 = new SuperExp(0);
-		    Expression *e = new CallExp(0, e1);
-
-		    unsigned errors = global.errors;
-		    global.gag++;
-		    e = e->semantic(sc2);
-		    global.gag--;
-		    if (errors != global.errors)
-			error("no match for implicit super() call in constructor");
-
-		    Statement *s = new ExpStatement(0, e);
-		    fbody = new CompoundStatement(0, s, fbody);
-		}
-	    }
-	    else if (fes)
-	    {	// For foreach(){} body, append a return 0;
-		Expression *e = new IntegerExp(0);
-		Statement *s = new ReturnStatement(0, e);
-		fbody = new CompoundStatement(0, fbody, s);
-		assert(!returnLabel);
-	    }
-	    else if (!hasReturnExp && type->nextOf()->ty != Tvoid)
-		error("expected to return a value of type %s", type->nextOf()->toChars());
-	    else if (!inlineAsm)
-	    {
-		if (type->nextOf()->ty == Tvoid)
-		{
-		    if (offend && isMain())
-		    {	// Add a return 0; statement
-			Statement *s = new ReturnStatement(0, new IntegerExp(0));
-			fbody = new CompoundStatement(0, fbody, s);
-		    }
-		}
-		else
-		{
-		    if (offend)
-		    {   Expression *e;
-
-			warning(loc, "no return at end of function");
-
-			if (global.params.useAssert &&
-			    !global.params.useInline)
-			{   /* Add an assert(0, msg); where the missing return
-			     * should be.
-			     */
-			    e = new AssertExp(
-				  endloc,
-				  new IntegerExp(0),
-				  new StringExp(loc, (char *)"missing return expression")
-				);
-			}
-			else
-			    e = new HaltExp(endloc);
-			e = new CommaExp(0, e, type->nextOf()->defaultInit());
-			e = e->semantic(sc2);
-			Statement *s = new ExpStatement(0, e);
-			fbody = new CompoundStatement(0, fbody, s);
-		    }
-		}
-	    }
-	}
-
-	{
-	    Statements *a = new Statements();
-
-	    // Merge in initialization of 'out' parameters
-	    if (parameters)
-	    {	for (size_t i = 0; i < parameters->dim; i++)
-		{
-		    VarDeclaration *v = (VarDeclaration *)parameters->data[i];
-		    if (v->storage_class & STCout)
-		    {
-			assert(v->init);
-			ExpInitializer *ie = v->init->isExpInitializer();
-			assert(ie);
-			a->push(new ExpStatement(0, ie->exp));
-		    }
-		}
-	    }
-
-// we'll handle variadics ourselves
-#if !IN_LLVM
-	    if (argptr)
-	    {	// Initialize _argptr to point past non-variadic arg
-#if IN_GCC
-		// Handled in FuncDeclaration::toObjFile
-		v_argptr = argptr;
-		v_argptr->init = new VoidInitializer(loc);
-#else
-		Expression *e1;
-		Expression *e;
-		Type *t = argptr->type;
-		VarDeclaration *p;
-		unsigned offset;
-
-		e1 = new VarExp(0, argptr);
-		if (parameters && parameters->dim)
-		    p = (VarDeclaration *)parameters->data[parameters->dim - 1];
-		else
-		    p = v_arguments;		// last parameter is _arguments[]
-		offset = p->type->size();
-		offset = (offset + 3) & ~3;	// assume stack aligns on 4
-		e = new SymOffExp(0, p, offset);
-		e = new AssignExp(0, e1, e);
-		e->type = t;
-		a->push(new ExpStatement(0, e));
-#endif // IN_GCC
-	    }
-
-	    if (_arguments)
-	    {
-		/* Advance to elements[] member of TypeInfo_Tuple with:
-		 *  _arguments = v_arguments.elements;
-		 */
-		Expression *e = new VarExp(0, v_arguments);
-		e = new DotIdExp(0, e, Id::elements);
-		Expression *e1 = new VarExp(0, _arguments);
-		e = new AssignExp(0, e1, e);
-		e = e->semantic(sc);
-		a->push(new ExpStatement(0, e));
-	    }
-
-#endif // !IN_LLVM
-
-	    // Merge contracts together with body into one compound statement
-
-#ifdef _DH
-	    if (frequire && global.params.useIn)
-	    {	frequire->incontract = 1;
-		a->push(frequire);
-	    }
-#else
-	    if (frequire && global.params.useIn)
-		a->push(frequire);
-#endif
-
-	    // Precondition invariant
-	    if (addPreInvariant())
-	    {
-		Expression *e = NULL;
-                Expression *ee = NULL;
-		if (isDtorDeclaration())
-		{
-		    // Call invariant directly only if it exists
-		    InvariantDeclaration *inv = ad->inv;
-		    ClassDeclaration *cd = ad->isClassDeclaration();
-
-		    while (!inv && cd)
-		    {
-			cd = cd->baseClass;
-			if (!cd)
-			    break;
-			inv = cd->inv;
-		    }
-		    if (inv)
-		    {
-			e = new DsymbolExp(0, inv);
-			e = new CallExp(0, e);
-			e = e->semantic(sc2);
-		    }
-		}
-		else
-		{   // Call invariant virtually
-                    // LDC: unless this is a struct without invariant
-                    StructDeclaration* sd = ad->isStructDeclaration();
-                    if (!sd || sd->inv)
-                    {
-                        ThisExp *v = new ThisExp(0);
-                        v->type = vthis->type;
-                        e = new AssertExp(loc, v, NULL);
-                    }
-
-                    // LDC: check for null this
-                    ThisExp* v = new ThisExp(0);
-                    v->type = vthis->type;
-                    v->var = vthis;
-
-                    NullExp *nv = new NullExp(0);
-                    nv->type = v->type;
-
-                    IdentityExp *ie = new IdentityExp(TOKnotidentity, 0, v, nv);
-                    ie->type = Type::tbool;
-
-		    Expression *se = new StringExp(0, (char *)"null this");
-		    se = se->semantic(sc);
-		    se->type = Type::tchar->arrayOf();
-
-		    ee = new AssertExp(loc, ie, se);
-		}
-                if (ee)
-                {
-                    ExpStatement *s = new ExpStatement(0, ee);
-                    a->push(s);
-                }
-		if (e)
-		{
-		    ExpStatement *s = new ExpStatement(0, e);
-		    a->push(s);
-		}
-	    }
-
-	    if (fbody)
-		a->push(fbody);
-
-	    if (fensure)
-	    {
-		a->push(returnLabel->statement);
-
-		if (type->nextOf()->ty != Tvoid)
-		{
-		    // Create: return vresult;
-		    assert(vresult);
-		    Expression *e = new VarExp(0, vresult);
-		    if (tintro)
-		    {	e = e->implicitCastTo(sc, tintro->nextOf());
-			e = e->semantic(sc);
-		    }
-		    ReturnStatement *s = new ReturnStatement(0, e);
-		    a->push(s);
-		}
-	    }
-
-	    fbody = new CompoundStatement(0, a);
-
-	    // wrap body of synchronized functions in a synchronized statement
-	    if (isSynchronized())
-	    {
-		ClassDeclaration *cd = parent->isClassDeclaration();
-		if (!cd)
-		    error("synchronized function %s must be a member of a class", toChars());
-		    
-		Expression *sync;
-		if (isStatic())
-		{
-		    // static member functions synchronize on classinfo 
-		    sync = cd->type->dotExp(sc2, new TypeExp(loc, cd->type), Id::classinfo);
-		}
-		else
-		{
-		    // non-static member functions synchronize on this
-		    sync = new VarExp(loc, vthis);
-		}
-                
-		// we do not want to rerun semantics on the whole function, so we
-		// manually adjust all labels in the function that currently don't
-		// have an enclosingScopeExit to use the new SynchronizedStatement
-		SynchronizedStatement* s = new SynchronizedStatement(loc, sync, NULL);
-		s->semantic(sc2);
-		s->body = fbody;
-		
-		// LDC
-		LabelMap::iterator it, end = labmap.end();
-		for (it = labmap.begin(); it != end; ++it)
-		    if (it->second->enclosingScopeExit == NULL)
-			it->second->enclosingScopeExit = s;
-		
-		a = new Statements;
-		a->push(s);
-		fbody = new CompoundStatement(0, a);
-	    }
-	}
-
-	sc2->callSuper = 0;
-	sc2->pop();
-    }
-    semanticRun = 4;
-}
-
-void FuncDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{
-    //printf("FuncDeclaration::toCBuffer() '%s'\n", toChars());
-
-    type->toCBuffer(buf, ident, hgs);
-    bodyToCBuffer(buf, hgs);
-}
-
-
-void FuncDeclaration::bodyToCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{
-    if (fbody &&
-	(!hgs->hdrgen || hgs->tpltMember || canInline(1,1))
-       )
-    {	buf->writenl();
-
-	// in{}
-	if (frequire)
-	{   buf->writestring("in");
-	    buf->writenl();
-	    frequire->toCBuffer(buf, hgs);
-	}
-
-	// out{}
-	if (fensure)
-	{   buf->writestring("out");
-	    if (outId)
-	    {   buf->writebyte('(');
-		buf->writestring(outId->toChars());
-		buf->writebyte(')');
-	    }
-	    buf->writenl();
-	    fensure->toCBuffer(buf, hgs);
-	}
-
-        if (frequire || fensure)
-	{   buf->writestring("body");
-	    buf->writenl();
-	}
-
-	buf->writebyte('{');
-	buf->writenl();
-	fbody->toCBuffer(buf, hgs);
-	buf->writebyte('}');
-	buf->writenl();
-    }
-    else
-    {	buf->writeByte(';');
-	buf->writenl();
-    }
-}
-
-/****************************************************
- * Determine if 'this' overrides fd.
- * Return !=0 if it does.
- */
-
-int FuncDeclaration::overrides(FuncDeclaration *fd)
-{   int result = 0;
-
-    if (fd->ident == ident)
-    {
-	int cov = type->covariant(fd->type);
-	if (cov)
-	{   ClassDeclaration *cd1 = toParent()->isClassDeclaration();
-	    ClassDeclaration *cd2 = fd->toParent()->isClassDeclaration();
-
-	    if (cd1 && cd2 && cd2->isBaseOf(cd1, NULL))
-		result = 1;
-	}
-    }
-    return result;
-}
-
-/*************************************************
- * Find index of function in vtbl[0..dim] that
- * this function overrides.
- * Returns:
- *	-1	didn't find one
- *	-2	can't determine because of forward references
- */
-
-int FuncDeclaration::findVtblIndex(Array *vtbl, int dim)
-{
-    for (int vi = 0; vi < dim; vi++)
-    {
-	FuncDeclaration *fdv = ((Dsymbol *)vtbl->data[vi])->isFuncDeclaration();
-	if (fdv && fdv->ident == ident)
-	{
-	    int cov = type->covariant(fdv->type);
-	    //printf("\tbaseclass cov = %d\n", cov);
-	    switch (cov)
-	    {
-		case 0:		// types are distinct
-		    break;
-
-		case 1:
-		    return vi;
-
-		case 2:
-		    //type->print();
-		    //fdv->type->print();
-		    //printf("%s %s\n", type->deco, fdv->type->deco);
-		    error("of type %s overrides but is not covariant with %s of type %s",
-			type->toChars(), fdv->toPrettyChars(), fdv->type->toChars());
-		    break;
-
-		case 3:
-		    return -2;	// forward references
-
-		default:
-		    assert(0);
-	    }
-	}
-    }
-    return -1;
-}
-
-/****************************************************
- * Overload this FuncDeclaration with the new one f.
- * Return !=0 if successful; i.e. no conflict.
- */
-
-int FuncDeclaration::overloadInsert(Dsymbol *s)
-{
-    FuncDeclaration *f;
-    AliasDeclaration *a;
-
-    //printf("FuncDeclaration::overloadInsert(%s)\n", s->toChars());
-    a = s->isAliasDeclaration();
-    if (a)
-    {
-	if (overnext)
-	    return overnext->overloadInsert(a);
-	if (!a->aliassym && a->type->ty != Tident && a->type->ty != Tinstance)
-	{
-	    //printf("\ta = '%s'\n", a->type->toChars());
-	    return FALSE;
-	}
-	overnext = a;
-	//printf("\ttrue: no conflict\n");
-	return TRUE;
-    }
-    f = s->isFuncDeclaration();
-    if (!f)
-	return FALSE;
-
-    if (type && f->type &&	// can be NULL for overloaded constructors
-	f->type->covariant(type) &&
-	!isFuncAliasDeclaration())
-    {
-	//printf("\tfalse: conflict %s\n", kind());
-	return FALSE;
-    }
-
-    if (overnext)
-	return overnext->overloadInsert(f);
-    overnext = f;
-    //printf("\ttrue: no conflict\n");
-    return TRUE;
-}
-
-/********************************************
- * Find function in overload list that exactly matches t.
- */
-
-/***************************************************
- * Visit each overloaded function in turn, and call
- * (*fp)(param, f) on it.
- * Exit when no more, or (*fp)(param, f) returns 1.
- * Returns:
- *	0	continue
- *	1	done
- */
-
-int overloadApply(Module* from, FuncDeclaration *fstart,
-	int (*fp)(void *, FuncDeclaration *),
-	void *param)
-{
-    FuncDeclaration *f;
-    Declaration *d;
-    Declaration *next;
-
-    for (d = fstart; d; d = next)
-    {	FuncAliasDeclaration *fa = d->isFuncAliasDeclaration();
-
-	if (fa)
-	{
-	    if (fa->getModule() == from || fa->importprot != PROTprivate)
-		if (overloadApply(from, fa->funcalias, fp, param))
-		    return 1;
-	    next = fa->overnext;
-	}
-	else
-	{
-	    AliasDeclaration *a = d->isAliasDeclaration();
-
-	    if (a)
-	    {
-		Dsymbol *s = a->toAlias();
-		next = s->isDeclaration();
-		if (next == a)
-		    break;
-		if (next == fstart)
-		    break;
-		if (a->importprot == PROTprivate && a->getModule() != from)
-		    if (FuncDeclaration* fd = next->isFuncDeclaration())
-			next = fd->overnext;
-	    }
-	    else
-	    {
-		f = d->isFuncDeclaration();
-		if (!f)
-		{   d->error("is aliased to a function");
-		    break;		// BUG: should print error message?
-		}
-		if ((*fp)(param, f))
-		    return 1;
-
-		next = f->overnext;
-	    }
-	}
-    }
-    return 0;
-}
-
-/********************************************
- * Find function in overload list that exactly matches t.
- */
-
-struct Param1
-{
-    Type *t;		// type to match
-    FuncDeclaration *f;	// return value
-};
-
-int fp1(void *param, FuncDeclaration *f)
-{   Param1 *p = (Param1 *)param;
-    Type *t = p->t;
-
-    if (t->equals(f->type))
-    {	p->f = f;
-	return 1;
-    }
-
-#if DMDV2
-    /* Allow covariant matches, if it's just a const conversion
-     * of the return type
-     */
-    if (t->ty == Tfunction)
-    {   TypeFunction *tf = (TypeFunction *)f->type;
-	if (tf->covariant(t) == 1 &&
-	    tf->nextOf()->implicitConvTo(t->nextOf()) >= MATCHconst)
-	{
-	    p->f = f;
-	    return 1;
-	}
-    }
-#endif
-    return 0;
-}
-
-FuncDeclaration *FuncDeclaration::overloadExactMatch(Type *t, Module* from)
-{
-    Param1 p;
-    p.t = t;
-    p.f = NULL;
-    overloadApply(from, this, &fp1, &p);
-    return p.f;
-}
-
-#if 0
-FuncDeclaration *FuncDeclaration::overloadExactMatch(Type *t)
-{
-    FuncDeclaration *f;
-    Declaration *d;
-    Declaration *next;
-
-    for (d = this; d; d = next)
-    {	FuncAliasDeclaration *fa = d->isFuncAliasDeclaration();
-
-	if (fa)
-	{
-	    FuncDeclaration *f2 = fa->funcalias->overloadExactMatch(t);
-	    if (f2)
-		return f2;
-	    next = fa->overnext;
-	}
-	else
-	{
-	    AliasDeclaration *a = d->isAliasDeclaration();
-
-	    if (a)
-	    {
-		Dsymbol *s = a->toAlias();
-		next = s->isDeclaration();
-		if (next == a)
-		    break;
-	    }
-	    else
-	    {
-		f = d->isFuncDeclaration();
-		if (!f)
-		    break;		// BUG: should print error message?
-		if (t->equals(d->type))
-		    return f;
-		next = f->overnext;
-	    }
-	}
-    }
-    return NULL;
-}
-#endif
-
-/********************************************
- * Decide which function matches the arguments best.
- */
-
-struct Param2
-{
-    Match *m;
-    Expressions *arguments;
-};
-
-int fp2(void *param, FuncDeclaration *f)
-{   Param2 *p = (Param2 *)param;
-    Match *m = p->m;
-    Expressions *arguments = p->arguments;
-    MATCH match;
-
-    if (f != m->lastf)		// skip duplicates
-    {
-	m->anyf = f;
-	TypeFunction *tf = (TypeFunction *)f->type;
-	match = (MATCH) tf->callMatch(arguments);
-	//printf("1match = %d\n", match);
-	if (match != MATCHnomatch)
-	{
-	    if (match > m->last)
-		goto LfIsBetter;
-
-	    if (match < m->last)
-		goto LlastIsBetter;
-
-	    /* See if one of the matches overrides the other.
-	     */
-	    if (m->lastf->overrides(f))
-		goto LlastIsBetter;
-	    else if (f->overrides(m->lastf))
-		goto LfIsBetter;
-
-	Lambiguous:
-	    m->nextf = f;
-	    m->count++;
-	    return 0;
-
-	LfIsBetter:
-	    m->last = match;
-	    m->lastf = f;
-	    m->count = 1;
-	    return 0;
-
-	LlastIsBetter:
-	    return 0;
-	}
-    }
-    return 0;
-}
-
-
-void overloadResolveX(Match *m, FuncDeclaration *fstart, Expressions *arguments, Module* from)
-{
-    Param2 p;
-    p.m = m;
-    p.arguments = arguments;
-    overloadApply(from, fstart, &fp2, &p);
-}
-
-#if 0
-// Recursive helper function
-
-void overloadResolveX(Match *m, FuncDeclaration *fstart, Expressions *arguments)
-{
-    MATCH match;
-    Declaration *d;
-    Declaration *next;
-
-    for (d = fstart; d; d = next)
-    {
-	FuncDeclaration *f;
-	FuncAliasDeclaration *fa;
-	AliasDeclaration *a;
-
-	fa = d->isFuncAliasDeclaration();
-	if (fa)
-	{
-	    overloadResolveX(m, fa->funcalias, arguments);
-	    next = fa->overnext;
-	}
-	else if ((f = d->isFuncDeclaration()) != NULL)
-	{
-	    next = f->overnext;
-	    if (f == m->lastf)
-		continue;			// skip duplicates
-	    else
-	    {
-		TypeFunction *tf;
-
-		m->anyf = f;
-		tf = (TypeFunction *)f->type;
-		match = (MATCH) tf->callMatch(arguments);
-		//printf("2match = %d\n", match);
-		if (match != MATCHnomatch)
-		{
-		    if (match > m->last)
-			goto LfIsBetter;
-
-		    if (match < m->last)
-			goto LlastIsBetter;
-
-		    /* See if one of the matches overrides the other.
-		     */
-		    if (m->lastf->overrides(f))
-			goto LlastIsBetter;
-		    else if (f->overrides(m->lastf))
-			goto LfIsBetter;
-
-		Lambiguous:
-		    m->nextf = f;
-		    m->count++;
-		    continue;
-
-		LfIsBetter:
-		    m->last = match;
-		    m->lastf = f;
-		    m->count = 1;
-		    continue;
-
-		LlastIsBetter:
-		    continue;
-		}
-	    }
-	}
-	else if ((a = d->isAliasDeclaration()) != NULL)
-	{
-	    Dsymbol *s = a->toAlias();
-	    next = s->isDeclaration();
-	    if (next == a)
-		break;
-	    if (next == fstart)
-		break;
-	}
-	else
-	{   d->error("is aliased to a function");
-	    break;
-	}
-    }
-}
-#endif
-
-FuncDeclaration *FuncDeclaration::overloadResolve(Loc loc, Expressions *arguments, Module* from)
-{
-    TypeFunction *tf;
-    Match m;
-
-#if 0
-printf("FuncDeclaration::overloadResolve('%s')\n", toChars());
-if (arguments)
-{   int i;
-
-    for (i = 0; i < arguments->dim; i++)
-    {   Expression *arg;
-
-	arg = (Expression *)arguments->data[i];
-	assert(arg->type);
-	printf("\t%s: ", arg->toChars());
-	arg->type->print();
-    }
-}
-#endif
-
-    memset(&m, 0, sizeof(m));
-    m.last = MATCHnomatch;
-    overloadResolveX(&m, this, arguments, from);
-
-    if (m.count == 1)		// exactly one match
-    {
-	return m.lastf;
-    }
-    else
-    {
-	OutBuffer buf;
-
-	if (arguments)
-	{
-	    HdrGenState hgs;
-
-	    argExpTypesToCBuffer(&buf, arguments, &hgs);
-	}
-
-	if (m.last == MATCHnomatch)
-	{
-	    tf = (TypeFunction *)type;
-
-	    //printf("tf = %s, args = %s\n", tf->deco, ((Expression *)arguments->data[0])->type->deco);
-	    error(loc, "%s does not match parameter types (%s)",
-		Argument::argsTypesToChars(tf->parameters, tf->varargs),
-		buf.toChars());
-	    return m.anyf;		// as long as it's not a FuncAliasDeclaration
-	}
-	else
-	{
-#if 1
-	    TypeFunction *t1 = (TypeFunction *)m.lastf->type;
-	    TypeFunction *t2 = (TypeFunction *)m.nextf->type;
-
-	    error(loc, "called with argument types:\n\t(%s)\nmatches both:\n\t%s%s\nand:\n\t%s%s",
-		    buf.toChars(),
-		    m.lastf->toPrettyChars(), Argument::argsTypesToChars(t1->parameters, t1->varargs),
-		    m.nextf->toPrettyChars(), Argument::argsTypesToChars(t2->parameters, t2->varargs));
-#else
-	    error(loc, "overloads %s and %s both match argument list for %s",
-		    m.lastf->type->toChars(),
-		    m.nextf->type->toChars(),
-		    m.lastf->toChars());
-#endif
-	    return m.lastf;
-	}
-    }
-}
-
-/********************************
- * Labels are in a separate scope, one per function.
- */
-
-LabelDsymbol *FuncDeclaration::searchLabel(Identifier *ident)
-{   Dsymbol *s;
-
-    if (!labtab)
-	labtab = new DsymbolTable();	// guess we need one
-
-    s = labtab->lookup(ident);
-    if (!s)
-    {
-	s = new LabelDsymbol(ident);
-	labtab->insert(s);
-    }
-    return (LabelDsymbol *)s;
-}
-
-/****************************************
- * If non-static member function that has a 'this' pointer,
- * return the aggregate it is a member of.
- * Otherwise, return NULL.
- */
-
-AggregateDeclaration *FuncDeclaration::isThis()
-{   AggregateDeclaration *ad;
-
-    //printf("+FuncDeclaration::isThis() '%s'\n", toChars());
-    ad = NULL;
-    if ((storage_class & STCstatic) == 0)
-    {
-	ad = isMember2();
-    }
-    //printf("-FuncDeclaration::isThis() %p\n", ad);
-    return ad;
-}
-
-AggregateDeclaration *FuncDeclaration::isMember2()
-{   AggregateDeclaration *ad;
-
-    //printf("+FuncDeclaration::isMember2() '%s'\n", toChars());
-    ad = NULL;
-    for (Dsymbol *s = this; s; s = s->parent)
-    {
-//printf("\ts = '%s', parent = '%s', kind = %s\n", s->toChars(), s->parent->toChars(), s->parent->kind());
-	ad = s->isMember();
-	if (ad)
-{   //printf("test4\n");
-	    break;
-}
-	if (!s->parent ||
-	    (!s->parent->isTemplateInstance()))
-{   //printf("test5\n");
-	    break;
-}
-    }
-    //printf("-FuncDeclaration::isMember2() %p\n", ad);
-    return ad;
-}
-
-/*****************************************
- * Determine lexical level difference from 'this' to nested function 'fd'.
- * Error if this cannot call fd.
- * Returns:
- *	0	same level
- *	-1	increase nesting by 1 (fd is nested within 'this')
- *	>0	decrease nesting by number
- */
-
-int FuncDeclaration::getLevel(Loc loc, FuncDeclaration *fd)
-{   int level;
-    Dsymbol *s;
-    Dsymbol *fdparent;
-
-    //printf("FuncDeclaration::getLevel(fd = '%s')\n", fd->toChars());
-    fdparent = fd->toParent2();
-    if (fdparent == this)
-	return -1;
-    s = this;
-    level = 0;
-    while (fd != s && fdparent != s->toParent2())
-    {
-	//printf("\ts = '%s'\n", s->toChars());
-	FuncDeclaration *thisfd = s->isFuncDeclaration();
-	if (thisfd)
-	{   if (!thisfd->isNested() && !thisfd->vthis)
-		goto Lerr;
-	}
-	else
-	{
-	    ClassDeclaration *thiscd = s->isClassDeclaration();
-	    if (thiscd)
-	    {	if (!thiscd->isNested())
-		    goto Lerr;
-	    }
-	    else
-		goto Lerr;
-	}
-
-	s = s->toParent2();
-	assert(s);
-	level++;
-    }
-    return level;
-
-Lerr:
-    error(loc, "cannot access frame of function %s", fd->toChars());
-    return 1;
-}
-
-void FuncDeclaration::appendExp(Expression *e)
-{   Statement *s;
-
-    s = new ExpStatement(0, e);
-    appendState(s);
-}
-
-void FuncDeclaration::appendState(Statement *s)
-{   CompoundStatement *cs;
-
-    if (!fbody)
-    {	Statements *a;
-
-	a = new Statements();
-	fbody = new CompoundStatement(0, a);
-    }
-    cs = fbody->isCompoundStatement();
-    cs->statements->push(s);
-}
-
-
-int FuncDeclaration::isMain()
-{
-    return ident == Id::main &&
-	linkage != LINKc && !isMember() && !isNested();
-}
-
-int FuncDeclaration::isWinMain()
-{
-    //printf("FuncDeclaration::isWinMain() %s\n", toChars());
-#if 0
-    int x = ident == Id::WinMain &&
-	linkage != LINKc && !isMember();
-    printf("%s\n", x ? "yes" : "no");
-    return x;
-#else
-    return ident == Id::WinMain &&
-	linkage != LINKc && !isMember();
-#endif
-}
-
-int FuncDeclaration::isDllMain()
-{
-    return ident == Id::DllMain &&
-	linkage != LINKc && !isMember();
-}
-
-int FuncDeclaration::isExport()
-{
-    return protection == PROTexport;
-}
-
-int FuncDeclaration::isImportedSymbol()
-{
-    //printf("isImportedSymbol()\n");
-    //printf("protection = %d\n", protection);
-    return (protection == PROTexport) && !fbody;
-}
-
-// Determine if function goes into virtual function pointer table
-
-int FuncDeclaration::isVirtual()
-{
-#if 0
-    printf("FuncDeclaration::isVirtual(%s)\n", toChars());
-    printf("%p %d %d %d %d\n", isMember(), isStatic(), protection == PROTprivate, isCtorDeclaration(), linkage != LINKd);
-    printf("result is %d\n",
-	isMember() &&
-	!(isStatic() || protection == PROTprivate || protection == PROTpackage) &&
-	toParent()->isClassDeclaration());
-#endif
-    return isMember() &&
-	!(isStatic() || protection == PROTprivate || protection == PROTpackage) &&
-	toParent()->isClassDeclaration();
-}
-
-int FuncDeclaration::isFinal()
-{
-    ClassDeclaration *cd;
-#if 0
-    printf("FuncDeclaration::isFinal(%s)\n", toChars());
-    printf("%p %d %d %d %d\n", isMember(), isStatic(), protection == PROTprivate, isCtorDeclaration(), linkage != LINKd);
-    printf("result is %d\n",
-	isMember() &&
-	!(isStatic() || protection == PROTprivate || protection == PROTpackage) &&
-	(cd = toParent()->isClassDeclaration()) != NULL &&
-	cd->storage_class & STCfinal);
-#endif
-    return isMember() &&
-	(Declaration::isFinal() ||
-	 ((cd = toParent()->isClassDeclaration()) != NULL && cd->storage_class & STCfinal));
-}
-
-int FuncDeclaration::isAbstract()
-{
-    return storage_class & STCabstract;
-}
-
-int FuncDeclaration::isCodeseg()
-{
-    return TRUE;		// functions are always in the code segment
-}
-
-// Determine if function needs
-// a static frame pointer to its lexically enclosing function
-
-int FuncDeclaration::isNested()
-{
-    //if (!toParent())
-	//printf("FuncDeclaration::isNested('%s') parent=%p\n", toChars(), parent);
-    //printf("\ttoParent() = '%s'\n", toParent()->toChars());
-    return ((storage_class & STCstatic) == 0) && toParent2() &&
-	   (toParent2()->isFuncDeclaration() != NULL);
-}
-
-int FuncDeclaration::needThis()
-{
-    //printf("FuncDeclaration::needThis() '%s'\n", toChars());
-    int i = isThis() != NULL;
-    //printf("\t%d\n", i);
-    if (!i && isFuncAliasDeclaration())
-	i = ((FuncAliasDeclaration *)this)->funcalias->needThis();
-    return i;
-}
-
-int FuncDeclaration::addPreInvariant()
-{
-    AggregateDeclaration *ad = isThis();
-    return (ad &&
-	    //ad->isClassDeclaration() &&
-	    global.params.useInvariants &&
-	    (protection == PROTpublic || protection == PROTexport) &&
-	    !naked);
-}
-
-int FuncDeclaration::addPostInvariant()
-{
-    AggregateDeclaration *ad = isThis();
-    return (ad &&
-	    ad->inv &&
-	    //ad->isClassDeclaration() &&
-	    global.params.useInvariants &&
-	    (protection == PROTpublic || protection == PROTexport) &&
-	    !naked);
-}
-
-/**********************************
- * Generate a FuncDeclaration for a runtime library function.
- */
-
-//
-// LDC: Adjusted to give argument info to the runtime function decl.
-//
-
-FuncDeclaration *FuncDeclaration::genCfunc(Arguments *args, Type *treturn, const char *name)
-{
-    return genCfunc(args, treturn, Lexer::idPool(name));
-}
-
-FuncDeclaration *FuncDeclaration::genCfunc(Arguments *args, Type *treturn, Identifier *id)
-{
-    FuncDeclaration *fd;
-    TypeFunction *tf;
-    Dsymbol *s;
-    static DsymbolTable *st = NULL;
-
-    //printf("genCfunc(name = '%s')\n", id->toChars());
-    //printf("treturn\n\t"); treturn->print();
-
-    // See if already in table
-    if (!st)
-	st = new DsymbolTable();
-    s = st->lookup(id);
-    if (s)
-    {
-	fd = s->isFuncDeclaration();
-	assert(fd);
-	assert(fd->type->nextOf()->equals(treturn));
-    }
-    else
-    {
-	tf = new TypeFunction(args, treturn, 0, LINKc);
-	fd = new FuncDeclaration(0, 0, id, STCstatic, tf);
-	fd->protection = PROTpublic;
-	fd->linkage = LINKc;
-
-	st->insert(fd);
-    }
-    return fd;
-}
-
-const char *FuncDeclaration::kind()
-{
-    return "function";
-}
-
-/*******************************
- * Look at all the variables in this function that are referenced
- * by nested functions, and determine if a closure needs to be
- * created for them.
- */
-
-#if DMDV2
-int FuncDeclaration::needsClosure()
-{
-    /* Need a closure for all the closureVars[] if any of the
-     * closureVars[] are accessed by a
-     * function that escapes the scope of this function.
-     * We take the conservative approach and decide that any function that:
-     * 1) is a virtual function
-     * 2) has its address taken
-     * 3) has a parent that escapes
-     *
-     * Note that since a non-virtual function can be called by
-     * a virtual one, if that non-virtual function accesses a closure
-     * var, the closure still has to be taken. Hence, we check for isThis()
-     * instead of isVirtual(). (thanks to David Friedman)
-     */
-
-    //printf("FuncDeclaration::needsClosure() %s\n", toChars());
-    for (int i = 0; i < closureVars.dim; i++)
-    {	VarDeclaration *v = (VarDeclaration *)closureVars.data[i];
-	assert(v->isVarDeclaration());
-	//printf("\tv = %s\n", v->toChars());
-
-	for (int j = 0; j < v->nestedrefs.dim; j++)
-	{   FuncDeclaration *f = (FuncDeclaration *)v->nestedrefs.data[j];
-	    assert(f != this);
-
-	    //printf("\t\tf = %s, %d, %d\n", f->toChars(), f->isVirtual(), f->tookAddressOf);
-	    if (f->isThis() || f->tookAddressOf)
-		goto Lyes;	// assume f escapes this function's scope
-
-	    // Look to see if any parents of f that are below this escape
-	    for (Dsymbol *s = f->parent; s && s != this; s = s->parent)
-	    {
-		f = s->isFuncDeclaration();
-		if (f && (f->isThis() || f->tookAddressOf))
-		    goto Lyes;
-	    }
-	}
-    }
-    return 0;
-
-Lyes:
-    //printf("\tneeds closure\n");
-    return 1;
-}
-#endif
-
-/****************************** FuncAliasDeclaration ************************/
-
-// Used as a way to import a set of functions from another scope into this one.
-
-FuncAliasDeclaration::FuncAliasDeclaration(FuncDeclaration *funcalias)
-    : FuncDeclaration(funcalias->loc, funcalias->endloc, funcalias->ident,
-	(enum STC)funcalias->storage_class, funcalias->type)
-{
-    assert(funcalias != this);
-    this->funcalias = funcalias;
-    importprot = PROTundefined;
-}
-
-const char *FuncAliasDeclaration::kind()
-{
-    return "function alias";
-}
-
-
-/****************************** FuncLiteralDeclaration ************************/
-
-FuncLiteralDeclaration::FuncLiteralDeclaration(Loc loc, Loc endloc, Type *type,
-	enum TOK tok, ForeachStatement *fes)
-    : FuncDeclaration(loc, endloc, NULL, STCundefined, type)
-{
-    const char *id;
-
-    if (fes)
-	id = "__foreachbody";
-    else if (tok == TOKdelegate)
-	id = "__dgliteral";
-    else
-	id = "__funcliteral";
-    this->ident = Identifier::generateId(id);
-    this->tok = tok;
-    this->fes = fes;
-    //printf("FuncLiteralDeclaration() id = '%s', type = '%s'\n", this->ident->toChars(), type->toChars());
-}
-
-Dsymbol *FuncLiteralDeclaration::syntaxCopy(Dsymbol *s)
-{
-    FuncLiteralDeclaration *f;
-
-    //printf("FuncLiteralDeclaration::syntaxCopy('%s')\n", toChars());
-    if (s)
-	f = (FuncLiteralDeclaration *)s;
-    else
-	f = new FuncLiteralDeclaration(loc, endloc, type->syntaxCopy(), tok, fes);
-    FuncDeclaration::syntaxCopy(f);
-    return f;
-}
-
-int FuncLiteralDeclaration::isNested()
-{
-    //printf("FuncLiteralDeclaration::isNested() '%s'\n", toChars());
-    return (tok == TOKdelegate);
-}
-
-int FuncLiteralDeclaration::isVirtual()
-{
-    return FALSE;
-}
-
-const char *FuncLiteralDeclaration::kind()
-{
-    // GCC requires the (char*) casts
-    return (tok == TOKdelegate) ? (char*)"delegate" : (char*)"function";
-}
-
-void FuncLiteralDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{
-    static Identifier *idfunc;
-    static Identifier *iddel;
-
-    if (!idfunc)
-	idfunc = new Identifier("function", 0);
-    if (!iddel)
-	iddel = new Identifier("delegate", 0);
-
-    type->toCBuffer(buf, ((tok == TOKdelegate) ? iddel : idfunc), hgs);
-    bodyToCBuffer(buf, hgs);
-}
-
-
-/********************************* CtorDeclaration ****************************/
-
-CtorDeclaration::CtorDeclaration(Loc loc, Loc endloc, Arguments *arguments, int varargs)
-    : FuncDeclaration(loc, endloc, Id::ctor, STCundefined, NULL)
-{
-    this->arguments = arguments;
-    this->varargs = varargs;
-    //printf("CtorDeclaration(loc = %s) %s\n", loc.toChars(), toChars());
-}
-
-Dsymbol *CtorDeclaration::syntaxCopy(Dsymbol *s)
-{
-    CtorDeclaration *f;
-
-    f = new CtorDeclaration(loc, endloc, NULL, varargs);
-
-    f->outId = outId;
-    f->frequire = frequire ? frequire->syntaxCopy() : NULL;
-    f->fensure  = fensure  ? fensure->syntaxCopy()  : NULL;
-    f->fbody    = fbody    ? fbody->syntaxCopy()    : NULL;
-    assert(!fthrows); // deprecated
-
-    f->arguments = Argument::arraySyntaxCopy(arguments);
-    return f;
-}
-
-
-void CtorDeclaration::semantic(Scope *sc)
-{
-    ClassDeclaration *cd;
-    Type *tret;
-
-    //printf("CtorDeclaration::semantic()\n");
-    if (type)
-	return;
-
-    sc = sc->push();
-    sc->stc &= ~STCstatic;		// not a static constructor
-
-    parent = sc->parent;
-    Dsymbol *parent = toParent();
-    cd = parent->isClassDeclaration();
-    if (!cd)
-    {
-	error("constructors are only for class definitions");
-	fatal();
-	tret = Type::tvoid;
-    }
-    else
-	tret = cd->type; //->referenceTo();
-    type = new TypeFunction(arguments, tret, varargs, LINKd);
-    if (!originalType)
-	originalType = type;
-
-    sc->flags |= SCOPEctor;
-    type = type->semantic(loc, sc);
-    sc->flags &= ~SCOPEctor;
-
-    // Append:
-    //	return this;
-    // to the function body
-    if (fbody)
-    {	Expression *e;
-	Statement *s;
-
-	e = new ThisExp(0);
-	s = new ReturnStatement(0, e);
-	fbody = new CompoundStatement(0, fbody, s);
-    }
-
-    FuncDeclaration::semantic(sc);
-
-    sc->pop();
-
-    // See if it's the default constructor
-    if (cd && varargs == 0 && Argument::dim(arguments) == 0)
-	cd->defaultCtor = this;
-}
-
-const char *CtorDeclaration::kind()
-{
-    return "constructor";
-}
-
-char *CtorDeclaration::toChars()
-{
-    return (char *)"this";
-}
-
-int CtorDeclaration::isVirtual()
-{
-    return FALSE;
-}
-
-int CtorDeclaration::addPreInvariant()
-{
-    return FALSE;
-}
-
-int CtorDeclaration::addPostInvariant()
-{
-    return (isThis() && vthis && global.params.useInvariants);
-}
-
-
-void CtorDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{
-    buf->writestring("this");
-    Argument::argsToCBuffer(buf, hgs, arguments, varargs);
-    bodyToCBuffer(buf, hgs);
-}
-
-/********************************* DtorDeclaration ****************************/
-
-DtorDeclaration::DtorDeclaration(Loc loc, Loc endloc)
-    : FuncDeclaration(loc, endloc, Id::dtor, STCundefined, NULL)
-{
-}
-
-DtorDeclaration::DtorDeclaration(Loc loc, Loc endloc, Identifier *id)
-    : FuncDeclaration(loc, endloc, id, STCundefined, NULL)
-{
-}
-
-Dsymbol *DtorDeclaration::syntaxCopy(Dsymbol *s)
-{
-    assert(!s);
-    DtorDeclaration *dd = new DtorDeclaration(loc, endloc, ident);
-    return FuncDeclaration::syntaxCopy(dd);
-}
-
-
-void DtorDeclaration::semantic(Scope *sc)
-{
-    ClassDeclaration *cd;
-
-    parent = sc->parent;
-    Dsymbol *parent = toParent();
-    cd = parent->isClassDeclaration();
-    if (!cd)
-    {
-	error("destructors only are for class definitions");
-	fatal();
-    }
-    else
-	cd->dtors.push(this);
-    type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd);
-
-    sc = sc->push();
-    sc->stc &= ~STCstatic;		// not a static destructor
-    sc->linkage = LINKd;
-
-    FuncDeclaration::semantic(sc);
-
-    sc->pop();
-}
-
-int DtorDeclaration::overloadInsert(Dsymbol *s)
-{
-    return FALSE;	// cannot overload destructors
-}
-
-int DtorDeclaration::addPreInvariant()
-{
-    return (isThis() && vthis && global.params.useInvariants);
-}
-
-int DtorDeclaration::addPostInvariant()
-{
-    return FALSE;
-}
-
-int DtorDeclaration::isVirtual()
-{
-    /* This should be FALSE so that dtor's don't get put into the vtbl[],
-     * but doing so will require recompiling everything.
-     */
-#if BREAKABI
-    return FALSE;
-#else
-    return FuncDeclaration::isVirtual();
-#endif
-}
-
-void DtorDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{
-    if (hgs->hdrgen)
-	return;
-    buf->writestring("~this()");
-    bodyToCBuffer(buf, hgs);
-}
-
-/********************************* StaticCtorDeclaration ****************************/
-
-StaticCtorDeclaration::StaticCtorDeclaration(Loc loc, Loc endloc)
-    : FuncDeclaration(loc, endloc,
-      Identifier::generateId("_staticCtor"), STCstatic, NULL)
-{
-}
-
-Dsymbol *StaticCtorDeclaration::syntaxCopy(Dsymbol *s)
-{
-    StaticCtorDeclaration *scd;
-
-    assert(!s);
-    scd = new StaticCtorDeclaration(loc, endloc);
-    return FuncDeclaration::syntaxCopy(scd);
-}
-
-
-void StaticCtorDeclaration::semantic(Scope *sc)
-{
-    //printf("StaticCtorDeclaration::semantic()\n");
-
-    type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd);
-
-    /* If the static ctor appears within a template instantiation,
-     * it could get called multiple times by the module constructors
-     * for different modules. Thus, protect it with a gate.
-     */
-    if (inTemplateInstance())
-    {
-	/* Add this prefix to the function:
-	 *	static int gate;
-	 *	if (++gate != 1) return;
-	 * Note that this is not thread safe; should not have threads
-	 * during static construction.
-	 */
-	Identifier *id = Lexer::idPool("__gate");
-	VarDeclaration *v = new VarDeclaration(0, Type::tint32, id, NULL);
-	v->storage_class = STCstatic;
-	Statements *sa = new Statements();
-	Statement *s = new DeclarationStatement(0, v);
-	sa->push(s);
-	Expression *e = new IdentifierExp(0, id);
-	e = new AddAssignExp(0, e, new IntegerExp(1));
-	e = new EqualExp(TOKnotequal, 0, e, new IntegerExp(1));
-	s = new IfStatement(0, NULL, e, new ReturnStatement(0, NULL), NULL);
-	sa->push(s);
-	if (fbody)
-	    sa->push(fbody);
-	fbody = new CompoundStatement(0, sa);
-    }
-
-    FuncDeclaration::semantic(sc);
-
-    // We're going to need ModuleInfo
-    Module *m = getModule();
-    if (!m)
-	m = sc->module;
-    if (m)
-    {	m->needmoduleinfo = 1;
-#ifdef IN_GCC
-	m->strictlyneedmoduleinfo = 1;
-#endif
-    }
-}
-
-AggregateDeclaration *StaticCtorDeclaration::isThis()
-{
-    return NULL;
-}
-
-int StaticCtorDeclaration::isStaticConstructor()
-{
-    return TRUE;
-}
-
-int StaticCtorDeclaration::isVirtual()
-{
-    return FALSE;
-}
-
-int StaticCtorDeclaration::addPreInvariant()
-{
-    return FALSE;
-}
-
-int StaticCtorDeclaration::addPostInvariant()
-{
-    return FALSE;
-}
-
-void StaticCtorDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{
-    if (hgs->hdrgen)
-    {	buf->writestring("static this();\n");
-	return;
-    }
-    buf->writestring("static this()");
-    bodyToCBuffer(buf, hgs);
-}
-
-/********************************* StaticDtorDeclaration ****************************/
-
-StaticDtorDeclaration::StaticDtorDeclaration(Loc loc, Loc endloc)
-    : FuncDeclaration(loc, endloc,
-      Identifier::generateId("_staticDtor"), STCstatic, NULL)
-{
-    vgate = NULL;
-}
-
-Dsymbol *StaticDtorDeclaration::syntaxCopy(Dsymbol *s)
-{
-    StaticDtorDeclaration *sdd;
-
-    assert(!s);
-    sdd = new StaticDtorDeclaration(loc, endloc);
-    return FuncDeclaration::syntaxCopy(sdd);
-}
-
-
-void StaticDtorDeclaration::semantic(Scope *sc)
-{
-    ClassDeclaration *cd;
-    Type *tret;
-
-    cd = sc->scopesym->isClassDeclaration();
-    if (!cd)
-    {
-    }
-    type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd);
-
-    /* If the static ctor appears within a template instantiation,
-     * it could get called multiple times by the module constructors
-     * for different modules. Thus, protect it with a gate.
-     */
-    if (inTemplateInstance())
-    {
-	/* Add this prefix to the function:
-	 *	static int gate;
-	 *	if (--gate != 0) return;
-	 * Increment gate during constructor execution.
-	 * Note that this is not thread safe; should not have threads
-	 * during static destruction.
-	 */
-	Identifier *id = Lexer::idPool("__gate");
-	VarDeclaration *v = new VarDeclaration(0, Type::tint32, id, NULL);
-	v->storage_class = STCstatic;
-	Statements *sa = new Statements();
-	Statement *s = new DeclarationStatement(0, v);
-	sa->push(s);
-	Expression *e = new IdentifierExp(0, id);
-	e = new AddAssignExp(0, e, new IntegerExp((uint64_t)-1));
-	e = new EqualExp(TOKnotequal, 0, e, new IntegerExp(0));
-	s = new IfStatement(0, NULL, e, new ReturnStatement(0, NULL), NULL);
-	sa->push(s);
-	if (fbody)
-	    sa->push(fbody);
-	fbody = new CompoundStatement(0, sa);
-	vgate = v;
-    }
-
-    FuncDeclaration::semantic(sc);
-
-    // We're going to need ModuleInfo
-    Module *m = getModule();
-    if (!m)
-	m = sc->module;
-    if (m)
-    {	m->needmoduleinfo = 1;
-#ifdef IN_GCC
-	m->strictlyneedmoduleinfo = 1;
-#endif
-    }
-}
-
-AggregateDeclaration *StaticDtorDeclaration::isThis()
-{
-    return NULL;
-}
-
-int StaticDtorDeclaration::isStaticDestructor()
-{
-    return TRUE;
-}
-
-int StaticDtorDeclaration::isVirtual()
-{
-    return FALSE;
-}
-
-int StaticDtorDeclaration::addPreInvariant()
-{
-    return FALSE;
-}
-
-int StaticDtorDeclaration::addPostInvariant()
-{
-    return FALSE;
-}
-
-void StaticDtorDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{
-    if (hgs->hdrgen)
-	return;
-    buf->writestring("static ~this()");
-    bodyToCBuffer(buf, hgs);
-}
-
-/********************************* InvariantDeclaration ****************************/
-
-InvariantDeclaration::InvariantDeclaration(Loc loc, Loc endloc)
-    : FuncDeclaration(loc, endloc, Id::classInvariant, STCundefined, NULL)
-{
-}
-
-Dsymbol *InvariantDeclaration::syntaxCopy(Dsymbol *s)
-{
-    InvariantDeclaration *id;
-
-    assert(!s);
-    id = new InvariantDeclaration(loc, endloc);
-    FuncDeclaration::syntaxCopy(id);
-    return id;
-}
-
-
-void InvariantDeclaration::semantic(Scope *sc)
-{
-    AggregateDeclaration *ad;
-    Type *tret;
-
-    parent = sc->parent;
-    Dsymbol *parent = toParent();
-    ad = parent->isAggregateDeclaration();
-    if (!ad)
-    {
-	error("invariants are only for struct/union/class definitions");
-	return;
-    }
-    else if (ad->inv && ad->inv != this)
-    {
-	error("more than one invariant for %s", ad->toChars());
-    }
-    ad->inv = this;
-    type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd);
-
-    sc = sc->push();
-    sc->stc &= ~STCstatic;		// not a static invariant
-    sc->incontract++;
-    sc->linkage = LINKd;
-
-    FuncDeclaration::semantic(sc);
-
-    sc->pop();
-}
-
-int InvariantDeclaration::isVirtual()
-{
-    return FALSE;
-}
-
-int InvariantDeclaration::addPreInvariant()
-{
-    return FALSE;
-}
-
-int InvariantDeclaration::addPostInvariant()
-{
-    return FALSE;
-}
-
-void InvariantDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{
-    if (hgs->hdrgen)
-	return;
-    buf->writestring("invariant");
-    bodyToCBuffer(buf, hgs);
-}
-
-
-/********************************* UnitTestDeclaration ****************************/
-
-/*******************************
- * Generate unique unittest function Id so we can have multiple
- * instances per module.
- */
-
-static Identifier *unitTestId()
-{
-    return Lexer::uniqueId("__unittest");
-}
-
-UnitTestDeclaration::UnitTestDeclaration(Loc loc, Loc endloc)
-    : FuncDeclaration(loc, endloc, unitTestId(), STCundefined, NULL)
-{
-}
-
-Dsymbol *UnitTestDeclaration::syntaxCopy(Dsymbol *s)
-{
-    UnitTestDeclaration *utd;
-
-    assert(!s);
-    utd = new UnitTestDeclaration(loc, endloc);
-    return FuncDeclaration::syntaxCopy(utd);
-}
-
-
-void UnitTestDeclaration::semantic(Scope *sc)
-{
-    if (global.params.useUnitTests)
-    {
-	type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd);
-	Scope *sc2 = sc->push();
-	sc2->linkage = LINKd;
-	FuncDeclaration::semantic(sc2);
-	sc2->pop();
-    }
-
-    // We're going to need ModuleInfo even if the unit tests are not
-    // compiled in, because other modules may import this module and refer
-    // to this ModuleInfo.
-    Module *m = getModule();
-    if (!m)
-	m = sc->module;
-    if (m)
-	m->needmoduleinfo = 1;
-}
-
-AggregateDeclaration *UnitTestDeclaration::isThis()
-{
-    return NULL;
-}
-
-int UnitTestDeclaration::isVirtual()
-{
-    return FALSE;
-}
-
-int UnitTestDeclaration::addPreInvariant()
-{
-    return FALSE;
-}
-
-int UnitTestDeclaration::addPostInvariant()
-{
-    return FALSE;
-}
-
-void UnitTestDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{
-    if (hgs->hdrgen)
-	return;
-    buf->writestring("unittest");
-    bodyToCBuffer(buf, hgs);
-}
-
-/********************************* NewDeclaration ****************************/
-
-NewDeclaration::NewDeclaration(Loc loc, Loc endloc, Arguments *arguments, int varargs)
-    : FuncDeclaration(loc, endloc, Id::classNew, STCstatic, NULL)
-{
-    this->arguments = arguments;
-    this->varargs = varargs;
-}
-
-Dsymbol *NewDeclaration::syntaxCopy(Dsymbol *s)
-{
-    NewDeclaration *f;
-
-    f = new NewDeclaration(loc, endloc, NULL, varargs);
-
-    FuncDeclaration::syntaxCopy(f);
-
-    f->arguments = Argument::arraySyntaxCopy(arguments);
-
-    return f;
-}
-
-
-void NewDeclaration::semantic(Scope *sc)
-{
-    ClassDeclaration *cd;
-    Type *tret;
-
-    //printf("NewDeclaration::semantic()\n");
-
-    parent = sc->parent;
-    Dsymbol *parent = toParent();
-    cd = parent->isClassDeclaration();
-    if (!cd && !parent->isStructDeclaration())
-    {
-	error("new allocators only are for class or struct definitions");
-    }
-    tret = Type::tvoid->pointerTo();
-    type = new TypeFunction(arguments, tret, varargs, LINKd);
-
-    type = type->semantic(loc, sc);
-    assert(type->ty == Tfunction);
-
-    // Check that there is at least one argument of type size_t
-    TypeFunction *tf = (TypeFunction *)type;
-    if (Argument::dim(tf->parameters) < 1)
-    {
-	error("at least one argument of type size_t expected");
-    }
-    else
-    {
-	Argument *a = Argument::getNth(tf->parameters, 0);
-	if (!a->type->equals(Type::tsize_t))
-	    error("first argument must be type size_t, not %s", a->type->toChars());
-    }
-
-    FuncDeclaration::semantic(sc);
-}
-
-const char *NewDeclaration::kind()
-{
-    return "allocator";
-}
-
-int NewDeclaration::isVirtual()
-{
-    return FALSE;
-}
-
-int NewDeclaration::addPreInvariant()
-{
-    return FALSE;
-}
-
-int NewDeclaration::addPostInvariant()
-{
-    return FALSE;
-}
-
-void NewDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{
-    buf->writestring("new");
-    Argument::argsToCBuffer(buf, hgs, arguments, varargs);
-    bodyToCBuffer(buf, hgs);
-}
-
-
-/********************************* DeleteDeclaration ****************************/
-
-DeleteDeclaration::DeleteDeclaration(Loc loc, Loc endloc, Arguments *arguments)
-    : FuncDeclaration(loc, endloc, Id::classDelete, STCstatic, NULL)
-{
-    this->arguments = arguments;
-}
-
-Dsymbol *DeleteDeclaration::syntaxCopy(Dsymbol *s)
-{
-    DeleteDeclaration *f;
-
-    f = new DeleteDeclaration(loc, endloc, NULL);
-
-    FuncDeclaration::syntaxCopy(f);
-
-    f->arguments = Argument::arraySyntaxCopy(arguments);
-
-    return f;
-}
-
-
-void DeleteDeclaration::semantic(Scope *sc)
-{
-    ClassDeclaration *cd;
-
-    //printf("DeleteDeclaration::semantic()\n");
-
-    parent = sc->parent;
-    Dsymbol *parent = toParent();
-    cd = parent->isClassDeclaration();
-    if (!cd && !parent->isStructDeclaration())
-    {
-	error("new allocators only are for class or struct definitions");
-    }
-    type = new TypeFunction(arguments, Type::tvoid, 0, LINKd);
-
-    type = type->semantic(loc, sc);
-    assert(type->ty == Tfunction);
-
-    // Check that there is only one argument of type void*
-    TypeFunction *tf = (TypeFunction *)type;
-    if (Argument::dim(tf->parameters) != 1)
-    {
-	error("one argument of type void* expected");
-    }
-    else
-    {
-	Argument *a = Argument::getNth(tf->parameters, 0);
-	if (!a->type->equals(Type::tvoid->pointerTo()))
-	    error("one argument of type void* expected, not %s", a->type->toChars());
-    }
-
-    FuncDeclaration::semantic(sc);
-}
-
-const char *DeleteDeclaration::kind()
-{
-    return "deallocator";
-}
-
-int DeleteDeclaration::isDelete()
-{
-    return TRUE;
-}
-
-int DeleteDeclaration::isVirtual()
-{
-    return FALSE;
-}
-
-int DeleteDeclaration::addPreInvariant()
-{
-    return FALSE;
-}
-
-int DeleteDeclaration::addPostInvariant()
-{
-    return FALSE;
-}
-
-void DeleteDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{
-    buf->writestring("delete");
-    Argument::argsToCBuffer(buf, hgs, arguments, 0);
-    bodyToCBuffer(buf, hgs);
-}
-
-
-
-
+// Compiler implementation of the D programming language
+// Copyright (c) 1999-2009 by Digital Mars
+// All Rights Reserved
+// written by Walter Bright
+// http://www.digitalmars.com
+// License for redistribution is by either the Artistic License
+// in artistic.txt, or the GNU General Public License in gnu.txt.
+// See the included readme.txt for details.
+
+#include <stdio.h>
+#include <assert.h>
+
+#include "mars.h"
+#include "init.h"
+#include "declaration.h"
+#include "attrib.h"
+#include "expression.h"
+#include "scope.h"
+#include "mtype.h"
+#include "aggregate.h"
+#include "identifier.h"
+#include "id.h"
+#include "module.h"
+#include "statement.h"
+#include "template.h"
+#include "hdrgen.h"
+
+#ifdef IN_GCC
+#include "d-dmd-gcc.h"
+#endif
+
+/********************************* FuncDeclaration ****************************/
+
+FuncDeclaration::FuncDeclaration(Loc loc, Loc endloc, Identifier *id, enum STC storage_class, Type *type)
+    : Declaration(id)
+{
+    //printf("FuncDeclaration(id = '%s', type = %p)\n", id->toChars(), type);
+    //printf("storage_class = x%x\n", storage_class);
+    this->storage_class = storage_class;
+    this->type = type;
+    this->loc = loc;
+    this->endloc = endloc;
+    fthrows = NULL;
+    frequire = NULL;
+    fdrequire = NULL;
+    fdensure = NULL;
+    outId = NULL;
+    vresult = NULL;
+    returnLabel = NULL;
+    fensure = NULL;
+    fbody = NULL;
+    localsymtab = NULL;
+    vthis = NULL;
+    v_arguments = NULL;
+#if IN_GCC
+    v_argptr = NULL;
+#endif
+    parameters = NULL;
+    labtab = NULL;
+    overnext = NULL;
+    vtblIndex = -1;
+    hasReturnExp = 0;
+    naked = 0;
+    inlineStatus = ILSuninitialized;
+    inlineNest = 0;
+    inlineAsm = 0;
+    cantInterpret = 0;
+    semanticRun = 0;
+#if DMDV1
+    nestedFrameRef = 0;
+#endif
+    fes = NULL;
+    introducing = 0;
+    tintro = NULL;
+    /* The type given for "infer the return type" is a TypeFunction with
+     * NULL for the return type.
+     */
+    inferRetType = (type && type->nextOf() == 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;
+    allowInlining = false;
+
+    availableExternally = true; // assume this unless proven otherwise
+
+    // function types in ldc don't merge if the context parameter differs
+    // so we actually don't care about the function declaration, but only
+    // what kind of context parameter it has.
+    // however, this constructor is usually called from the parser, which
+    // unfortunately doesn't provide the information needed to get to the
+    // aggregate type. So we have to stick with the FuncDeclaration and
+    // just be sure we don't actually rely on the symbol it points to,
+    // but rather just the type of its context parameter.
+    // this means some function might have a function type pointing to
+    // another function declaration
+
+    if (type)
+    {
+        assert(type->ty == Tfunction && "invalid function type");
+        TypeFunction* tf = (TypeFunction*)type;
+        if (tf->funcdecl == NULL)
+            tf->funcdecl = this;
+    }
+#endif
+}
+
+Dsymbol *FuncDeclaration::syntaxCopy(Dsymbol *s)
+{
+    FuncDeclaration *f;
+
+    //printf("FuncDeclaration::syntaxCopy('%s')\n", toChars());
+    if (s)
+	f = (FuncDeclaration *)s;
+    else
+	f = new FuncDeclaration(loc, endloc, ident, (enum STC) storage_class, type->syntaxCopy());
+    f->outId = outId;
+    f->frequire = frequire ? frequire->syntaxCopy() : NULL;
+    f->fensure  = fensure  ? fensure->syntaxCopy()  : NULL;
+    f->fbody    = fbody    ? fbody->syntaxCopy()    : NULL;
+    assert(!fthrows); // deprecated
+
+    // LDC
+    f->intrinsicName = intrinsicName;
+
+    return f;
+}
+
+
+// Do the semantic analysis on the external interface to the function.
+
+void FuncDeclaration::semantic(Scope *sc)
+{   TypeFunction *f;
+    StructDeclaration *sd;
+    ClassDeclaration *cd;
+    InterfaceDeclaration *id;
+    Dsymbol *pd;
+
+#if 0
+    printf("FuncDeclaration::semantic(sc = %p, this = %p, '%s', linkage = %d)\n", sc, this, toPrettyChars(), sc->linkage);
+    if (isFuncLiteralDeclaration())
+	printf("\tFuncLiteralDeclaration()\n");
+    printf("sc->parent = %s, parent = %s\n", sc->parent->toChars(), parent ? parent->toChars() : "");
+    printf("type: %p, %s\n", type, type->toChars());
+#endif
+
+    if (semanticRun && isFuncLiteralDeclaration())
+    {
+	/* Member functions that have return types that are
+	 * forward references can have semantic() run more than
+	 * once on them.
+	 * See test\interface2.d, test20
+	 */
+	return;
+    }
+    assert(semanticRun <= 1);
+    semanticRun = 1;
+
+    if (!type->deco)
+    {
+	type = type->semantic(loc, sc);
+    }
+    //type->print();
+    if (type->ty != Tfunction)
+    {
+	error("%s must be a function", toChars());
+	return;
+    }
+    f = (TypeFunction *)(type);
+    size_t nparams = Argument::dim(f->parameters);
+
+    linkage = sc->linkage;
+//    if (!parent)
+    {
+	//parent = sc->scopesym;
+	parent = sc->parent;
+    }
+    protection = sc->protection;
+    storage_class |= sc->stc;
+    //printf("function storage_class = x%x\n", storage_class);
+    Dsymbol *parent = toParent();
+
+    if (ident == Id::ctor && !isCtorDeclaration())
+	error("_ctor is reserved for constructors");
+
+    if (isConst() || isAuto() || isScope())
+	error("functions cannot be const, auto or scope");
+
+    if (isAbstract() && !isVirtual())
+	error("non-virtual functions cannot be abstract");
+
+    if (isAbstract() && isFinal())
+	error("cannot be both final and abstract");
+#if 0
+    if (isAbstract() && fbody)
+	error("abstract functions cannot have bodies");
+#endif
+
+#if 0
+    if (isStaticConstructor() || isStaticDestructor())
+    {
+	if (!isStatic() || type->nextOf()->ty != Tvoid)
+	    error("static constructors / destructors must be static void");
+	if (f->arguments && f->arguments->dim)
+	    error("static constructors / destructors must have empty parameter list");
+	// BUG: check for invalid storage classes
+    }
+#endif
+
+#ifdef IN_GCC
+    AggregateDeclaration *ad;
+
+    ad = parent->isAggregateDeclaration();
+    if (ad)
+	ad->methods.push(this);
+#endif
+    sd = parent->isStructDeclaration();
+    if (sd)
+    {
+	// Verify no constructors, destructors, etc.
+	if (isCtorDeclaration() ||
+	    isDtorDeclaration()
+	    //|| isInvariantDeclaration()
+	    //|| isUnitTestDeclaration()
+	   )
+	{
+	    error("special member functions not allowed for %ss", sd->kind());
+	}
+
+#if 0
+	if (!sd->inv)
+	    sd->inv = isInvariantDeclaration();
+
+	if (!sd->aggNew)
+	    sd->aggNew = isNewDeclaration();
+
+	if (isDelete())
+	{
+	    if (sd->aggDelete)
+		error("multiple delete's for struct %s", sd->toChars());
+	    sd->aggDelete = (DeleteDeclaration *)(this);
+	}
+#endif
+    }
+
+    id = parent->isInterfaceDeclaration();
+    if (id)
+    {
+	storage_class |= STCabstract;
+
+	if (isCtorDeclaration() ||
+#if DMDV2
+	    isPostBlitDeclaration() ||
+#endif
+	    isDtorDeclaration() ||
+	    isInvariantDeclaration() ||
+	    isUnitTestDeclaration() || isNewDeclaration() || isDelete())
+	    error("special function not allowed in interface %s", id->toChars());
+	if (fbody)
+	    error("function body is not abstract in interface %s", id->toChars());
+    }
+
+    /* Template member functions aren't virtual:
+     *   interface TestInterface { void tpl(T)(); }
+     * and so won't work in interfaces
+     */
+    if ((pd = toParent()) != NULL &&
+	pd->isTemplateInstance() &&
+	(pd = toParent2()) != NULL &&
+	(id = pd->isInterfaceDeclaration()) != NULL)
+    {
+	error("template member function not allowed in interface %s", id->toChars());
+    }
+
+    cd = parent->isClassDeclaration();
+    if (cd)
+    {	int vi;
+	CtorDeclaration *ctor;
+	DtorDeclaration *dtor;
+	InvariantDeclaration *inv;
+
+	if (isCtorDeclaration())
+	{
+//	    ctor = (CtorDeclaration *)this;
+//	    if (!cd->ctor)
+//		cd->ctor = ctor;
+	    return;
+	}
+
+#if 0
+	dtor = isDtorDeclaration();
+	if (dtor)
+	{
+	    if (cd->dtor)
+		error("multiple destructors for class %s", cd->toChars());
+	    cd->dtor = dtor;
+	}
+
+	inv = isInvariantDeclaration();
+	if (inv)
+	{
+	    cd->inv = inv;
+	}
+
+	if (isNewDeclaration())
+	{
+	    if (!cd->aggNew)
+		cd->aggNew = (NewDeclaration *)(this);
+	}
+
+	if (isDelete())
+	{
+	    if (cd->aggDelete)
+		error("multiple delete's for class %s", cd->toChars());
+	    cd->aggDelete = (DeleteDeclaration *)(this);
+	}
+#endif
+
+	if (storage_class & STCabstract)
+	    cd->isabstract = 1;
+
+	// if static function, do not put in vtbl[]
+	if (!isVirtual())
+	{
+	    //printf("\tnot virtual\n");
+	    goto Ldone;
+	}
+
+	// Find index of existing function in vtbl[] to override
+	vi = findVtblIndex(&cd->vtbl, cd->baseClass ? cd->baseClass->vtbl.dim : 0);
+	switch (vi)
+	{
+	    case -1:
+		/* Didn't find one, so
+		 * This is an 'introducing' function which gets a new
+		 * slot in the vtbl[].
+		 */
+
+		// Verify this doesn't override previous final function
+		if (cd->baseClass)
+		{   Dsymbol *s = cd->baseClass->search(loc, ident, 0);
+		    if (s)
+		    {
+			FuncDeclaration *f = s->isFuncDeclaration();
+			f = f->overloadExactMatch(type, getModule());
+			if (f && f->isFinal() && f->prot() != PROTprivate)
+			    error("cannot override final function %s", f->toPrettyChars());
+		    }
+		}
+
+		if (isFinal())
+		{
+		    if (isOverride())
+			error("does not override any function");
+		    cd->vtblFinal.push(this);
+		}
+		else
+		{
+		    // Append to end of vtbl[]
+		    //printf("\tintroducing function\n");
+		    introducing = 1;
+		    vi = cd->vtbl.dim;
+		    cd->vtbl.push(this);
+		    vtblIndex = vi;
+		}
+		break;
+
+	    case -2:	// can't determine because of fwd refs
+		cd->sizeok = 2;	// can't finish due to forward reference
+		return;
+
+	    default:
+	    {   FuncDeclaration *fdv = (FuncDeclaration *)cd->vtbl.data[vi];
+		// This function is covariant with fdv
+		if (fdv->isFinal())
+		    error("cannot override final function %s", fdv->toPrettyChars());
+
+#if DMDV2
+		if (!isOverride())
+		    warning(loc, "overrides base class function %s, but is not marked with 'override'", fdv->toPrettyChars());
+#endif
+
+		if (fdv->toParent() == parent)
+		{
+		    // If both are mixins, then error.
+		    // If either is not, the one that is not overrides
+		    // the other.
+		    if (fdv->parent->isClassDeclaration())
+			break;
+		    if (!this->parent->isClassDeclaration()
+#if !BREAKABI
+			&& !isDtorDeclaration()
+#endif
+#if DMDV2
+			&& !isPostBlitDeclaration()
+#endif
+			)
+			error("multiple overrides of same function");
+		}
+		cd->vtbl.data[vi] = (void *)this;
+		vtblIndex = vi;
+
+		/* Remember which functions this overrides
+		 */
+		foverrides.push(fdv);
+
+		/* This works by whenever this function is called,
+		 * it actually returns tintro, which gets dynamically
+		 * cast to type. But we know that tintro is a base
+		 * of type, so we could optimize it by not doing a
+		 * dynamic cast, but just subtracting the isBaseOf()
+		 * offset if the value is != null.
+		 */
+
+		if (fdv->tintro)
+		    tintro = fdv->tintro;
+		else if (!type->equals(fdv->type))
+		{
+		    /* Only need to have a tintro if the vptr
+		     * offsets differ
+		     */
+		    int offset;
+		    if (fdv->type->nextOf()->isBaseOf(type->nextOf(), &offset))
+		    {
+			tintro = fdv->type;
+		    }
+		}
+		break;
+	    }
+	}
+
+	/* Go through all the interface bases.
+	 * If this function is covariant with any members of those interface
+	 * functions, set the tintro.
+	 */
+	for (int i = 0; i < cd->interfaces_dim; i++)
+	{
+#if 1
+	    BaseClass *b = cd->interfaces[i];
+	    vi = findVtblIndex(&b->base->vtbl, b->base->vtbl.dim);
+	    switch (vi)
+	    {
+		case -1:
+		    break;
+
+		case -2:
+		    cd->sizeok = 2;	// can't finish due to forward reference
+		    return;
+
+		default:
+		{   FuncDeclaration *fdv = (FuncDeclaration *)b->base->vtbl.data[vi];
+		    Type *ti = NULL;
+
+		    /* Remember which functions this overrides
+		     */
+		    foverrides.push(fdv);
+
+		    if (fdv->tintro)
+			ti = fdv->tintro;
+		    else if (!type->equals(fdv->type))
+		    {
+			/* Only need to have a tintro if the vptr
+			 * offsets differ
+			 */
+			int offset;
+			if (fdv->type->nextOf()->isBaseOf(type->nextOf(), &offset))
+			{
+			    ti = fdv->type;
+#if 0
+			    if (offset)
+				ti = fdv->type;
+			    else if (type->nextOf()->ty == Tclass)
+			    {   ClassDeclaration *cdn = ((TypeClass *)type->nextOf())->sym;
+				if (cdn && cdn->sizeok != 1)
+				    ti = fdv->type;
+			    }
+#endif
+			}
+		    }
+		    if (ti)
+		    {
+			if (tintro && !tintro->equals(ti))
+			{
+			    error("incompatible covariant types %s and %s", tintro->toChars(), ti->toChars());
+			}
+			tintro = ti;
+		    }
+		    goto L2;
+		}
+	    }
+#else
+	    BaseClass *b = cd->interfaces[i];
+	    for (vi = 0; vi < b->base->vtbl.dim; vi++)
+	    {
+		Dsymbol *s = (Dsymbol *)b->base->vtbl.data[vi];
+		//printf("interface %d vtbl[%d] %p %s\n", i, vi, s, s->toChars());
+		FuncDeclaration *fdv = s->isFuncDeclaration();
+		if (fdv && fdv->ident == ident)
+		{
+		    int cov = type->covariant(fdv->type);
+		    //printf("\tcov = %d\n", cov);
+		    if (cov == 2)
+		    {
+			//type->print();
+			//fdv->type->print();
+			//printf("%s %s\n", type->deco, fdv->type->deco);
+			error("of type %s overrides but is not covariant with %s of type %s",
+			    type->toChars(), fdv->toPrettyChars(), fdv->type->toChars());
+		    }
+		    if (cov == 1)
+		    {	Type *ti = NULL;
+
+			if (fdv->tintro)
+			    ti = fdv->tintro;
+			else if (!type->equals(fdv->type))
+			{
+			    /* Only need to have a tintro if the vptr
+			     * offsets differ
+			     */
+			    int offset;
+			    if (fdv->type->nextOf()->isBaseOf(type->nextOf(), &offset))
+			    {
+				ti = fdv->type;
+#if 0
+				if (offset)
+				    ti = fdv->type;
+				else if (type->nextOf()->ty == Tclass)
+				{   ClassDeclaration *cdn = ((TypeClass *)type->nextOf())->sym;
+				    if (cdn && cdn->sizeok != 1)
+					ti = fdv->type;
+				}
+#endif
+			    }
+			}
+			if (ti)
+			{
+			    if (tintro && !tintro->equals(ti))
+			    {
+				error("incompatible covariant types %s and %s", tintro->toChars(), ti->toChars());
+			    }
+			    tintro = ti;
+			}
+			goto L2;
+		    }
+		    if (cov == 3)
+		    {
+			cd->sizeok = 2;	// can't finish due to forward reference
+			return;
+		    }
+		}
+	    }
+#endif
+	}
+
+	if (introducing && isOverride())
+	{
+	    error("does not override any function");
+	}
+
+    L2: ;
+    }
+    else if (isOverride() && !parent->isTemplateInstance())
+	error("override only applies to class member functions");
+
+    /* Do not allow template instances to add virtual functions
+     * to a class.
+     */
+    if (isVirtual())
+    {
+	TemplateInstance *ti = parent->isTemplateInstance();
+	if (ti)
+	{
+	    // Take care of nested templates
+	    while (1)
+	    {
+		TemplateInstance *ti2 = ti->tempdecl->parent->isTemplateInstance();
+		if (!ti2)
+		    break;
+		ti = ti2;
+	    }
+
+	    // If it's a member template
+	    ClassDeclaration *cd = ti->tempdecl->isClassMember();
+	    if (cd)
+	    {
+		error("cannot use template to add virtual function to class '%s'", cd->toChars());
+	    }
+	}
+    }
+
+    if (isMain())
+    {
+	// Check parameters to see if they are either () or (char[][] args)
+	switch (nparams)
+	{
+	    case 0:
+		break;
+
+	    case 1:
+	    {
+		Argument *arg0 = Argument::getNth(f->parameters, 0);
+		if (arg0->type->ty != Tarray ||
+		    arg0->type->nextOf()->ty != Tarray ||
+		    arg0->type->nextOf()->nextOf()->ty != Tchar ||
+		    arg0->storageClass & (STCout | STCref | STClazy))
+		    goto Lmainerr;
+		break;
+	    }
+
+	    default:
+		goto Lmainerr;
+	}
+
+	if (!f->nextOf())
+	    error("must return int or void");
+	else if (f->nextOf()->ty != Tint32 && f->nextOf()->ty != Tvoid)
+	    error("must return int or void, not %s", f->nextOf()->toChars());
+	if (f->varargs)
+	{
+	Lmainerr:
+	    error("parameters must be main() or main(char[][] args)");
+	}
+    }
+
+    if (ident == Id::assign && (sd || cd))
+    {	// Disallow identity assignment operator.
+
+	// opAssign(...)
+	if (nparams == 0)
+	{   if (f->varargs == 1)
+		goto Lassignerr;
+	}
+	else
+	{
+	    Argument *arg0 = Argument::getNth(f->parameters, 0);
+	    Type *t0 = arg0->type->toBasetype();
+	    Type *tb = sd ? sd->type : cd->type;
+	    if (arg0->type->implicitConvTo(tb) ||
+		(sd && t0->ty == Tpointer && t0->nextOf()->implicitConvTo(tb))
+	       )
+	    {
+		if (nparams == 1)
+		    goto Lassignerr;
+		Argument *arg1 = Argument::getNth(f->parameters, 1);
+		if (arg1->defaultArg)
+		    goto Lassignerr;
+	    }
+	}
+    }
+
+    if (isVirtual())
+    {
+	/* Rewrite contracts as nested functions, then call them.
+	 * Doing it as nested functions means that overriding functions
+	 * can call them.
+	 */
+	if (frequire)
+	{   /*   in { ... }
+	     * becomes:
+	     *   void __require() { ... }
+	     *   __require();
+	     */
+	    Loc loc = frequire->loc;
+	    TypeFunction *tf = new TypeFunction(NULL, Type::tvoid, 0, LINKd);
+	    FuncDeclaration *fd = new FuncDeclaration(loc, loc,
+		Id::require, STCundefined, tf);
+	    fd->fbody = frequire;
+	    Statement *s1 = new DeclarationStatement(loc, fd);
+	    Expression *e = new CallExp(loc, new VarExp(loc, fd), (Expressions *)NULL);
+	    Statement *s2 = new ExpStatement(loc, e);
+	    frequire = new CompoundStatement(loc, s1, s2);
+	    fdrequire = fd;
+	}
+
+	if (fensure)
+	{   /*   out (result) { ... }
+	     * becomes:
+	     *   tret __ensure(ref tret result) { ... }
+	     *   __ensure(result);
+	     */
+	    if (!outId && f->nextOf()->toBasetype()->ty != Tvoid)
+		outId = Id::result;	// provide a default
+
+	    Loc loc = fensure->loc;
+	    Arguments *arguments = new Arguments();
+	    Argument *a = NULL;
+	    if (outId)
+	    {	a = new Argument(STCref, f->nextOf(), outId, NULL);
+		arguments->push(a);
+	    }
+	    TypeFunction *tf = new TypeFunction(arguments, Type::tvoid, 0, LINKd);
+	    FuncDeclaration *fd = new FuncDeclaration(loc, loc,
+		Id::ensure, STCundefined, tf);
+	    fd->fbody = fensure;
+	    Statement *s1 = new DeclarationStatement(loc, fd);
+	    Expression *eresult = NULL;
+	    if (outId)
+		eresult = new IdentifierExp(loc, outId);
+	    Expression *e = new CallExp(loc, new VarExp(loc, fd), eresult);
+	    Statement *s2 = new ExpStatement(loc, e);
+	    fensure = new CompoundStatement(loc, s1, s2);
+	    fdensure = fd;
+	}
+    }
+
+Ldone:
+    /* Save scope for possible later use (if we need the
+     * function internals)
+     */
+    scope = new Scope(*sc);
+    scope->setNoFree();
+    return;
+
+Lassignerr:
+    error("identity assignment operator overload is illegal");
+}
+
+void FuncDeclaration::semantic2(Scope *sc)
+{
+}
+
+// Do the semantic analysis on the internals of the function.
+
+void FuncDeclaration::semantic3(Scope *sc)
+{   TypeFunction *f;
+    VarDeclaration *argptr = NULL;
+    VarDeclaration *_arguments = NULL;
+
+    if (!parent)
+    {
+	if (global.errors)
+	    return;
+	//printf("FuncDeclaration::semantic3(%s '%s', sc = %p)\n", kind(), toChars(), sc);
+	assert(0);
+    }
+    //printf("FuncDeclaration::semantic3('%s.%s', sc = %p, loc = %s)\n", parent->toChars(), toChars(), sc, loc.toChars());
+    //fflush(stdout);
+    //printf("storage class = x%x %x\n", sc->stc, storage_class);
+    //{ static int x; if (++x == 2) *(char*)0=0; }
+    //printf("\tlinkage = %d\n", sc->linkage);
+
+    //printf(" sc->incontract = %d\n", sc->incontract);
+    if (semanticRun >= 3)
+	return;
+    semanticRun = 3;
+
+    // LDC
+    if (!global.params.useAvailableExternally)
+        availableExternally = false;
+
+    if (!type || type->ty != Tfunction)
+	return;
+    f = (TypeFunction *)(type);
+
+    // Check the 'throws' clause
+    if (fthrows)
+    {
+	for (int i = 0; i < fthrows->dim; i++)
+	{
+	    Type *t = (Type *)fthrows->data[i];
+
+	    t = t->semantic(loc, sc);
+	    if (!t->isClassHandle())
+		error("can only throw classes, not %s", t->toChars());
+	}
+    }
+
+    frequire = mergeFrequire(frequire);
+    fensure = mergeFensure(fensure);
+
+    if (fbody || frequire)
+    {
+	/* Symbol table into which we place parameters and nested functions,
+	 * solely to diagnose name collisions.
+	 */
+	localsymtab = new DsymbolTable();
+
+	// Establish function scope
+	ScopeDsymbol *ss = new ScopeDsymbol();
+	ss->parent = sc->scopesym;
+	Scope *sc2 = sc->push(ss);
+	sc2->func = this;
+	sc2->parent = this;
+	sc2->callSuper = 0;
+	sc2->sbreak = NULL;
+	sc2->scontinue = NULL;
+	sc2->sw = NULL;
+	sc2->fes = fes;
+	sc2->linkage = LINKd;
+	sc2->stc &= ~(STCauto | STCscope | STCstatic | STCabstract | STCdeprecated | STCfinal);
+	sc2->protection = PROTpublic;
+	sc2->explicitProtection = 0;
+	sc2->structalign = 8;
+	sc2->incontract = 0;
+	sc2->enclosingFinally = NULL;
+	sc2->enclosingScopeExit = NULL;
+	sc2->noctor = 0;
+
+	// Declare 'this'
+	AggregateDeclaration *ad = isThis();
+	if (ad)
+	{   VarDeclaration *v;
+
+	    if (isFuncLiteralDeclaration() && isNested())
+	    {
+		error("literals cannot be class members");
+		return;
+	    }
+	    else
+	    {
+		assert(!isNested());	// can't be both member and nested
+		assert(ad->handle);
+		v = new ThisDeclaration(loc, ad->handle);
+		v->storage_class |= STCparameter | STCin;
+		v->semantic(sc2);
+		if (!sc2->insert(v))
+		    assert(0);
+		v->parent = this;
+		vthis = v;
+	    }
+	}
+	else if (isNested())
+	{
+	    /* The 'this' for a nested function is the link to the
+	     * enclosing function's stack frame.
+	     * Note that nested functions and member functions are disjoint.
+	     */
+	    VarDeclaration *v = new ThisDeclaration(loc, Type::tvoid->pointerTo());
+	    v->storage_class |= STCparameter | STCin;
+	    v->semantic(sc2);
+	    if (!sc2->insert(v))
+		assert(0);
+	    v->parent = this;
+	    vthis = v;
+	}
+
+	// Declare hidden variable _arguments[] and _argptr
+	if (f->varargs == 1)
+	{
+#if TARGET_NET
+        varArgs(sc2, f, argptr, _arguments);
+#else
+        Type *t;
+
+	    if (f->linkage == LINKd)
+	    {	// Declare _arguments[]
+#if BREAKABI
+		v_arguments = new VarDeclaration(0, Type::typeinfotypelist->type, Id::_arguments_typeinfo, NULL);
+		v_arguments->storage_class = STCparameter | STCin;
+		v_arguments->semantic(sc2);
+		sc2->insert(v_arguments);
+		v_arguments->parent = this;
+
+		t = Type::typeinfo->type->arrayOf();
+		_arguments = new VarDeclaration(0, t, Id::_arguments, NULL);
+		_arguments->semantic(sc2);
+		sc2->insert(_arguments);
+		_arguments->parent = this;
+#else
+		t = Type::typeinfo->type->arrayOf();
+		v_arguments = new VarDeclaration(0, t, Id::_arguments, NULL);
+		v_arguments->storage_class = STCparameter | STCin;
+		v_arguments->semantic(sc2);
+		sc2->insert(v_arguments);
+		v_arguments->parent = this;
+#endif
+	    }
+	    if (f->linkage == LINKd || (parameters && parameters->dim))
+	    {	// Declare _argptr
+#if IN_GCC
+		t = d_gcc_builtin_va_list_d_type;
+#else
+		t = Type::tvoid->pointerTo();
+#endif
+		argptr = new VarDeclaration(0, t, Id::_argptr, NULL);
+		argptr->semantic(sc2);
+		sc2->insert(argptr);
+		argptr->parent = this;
+	    }
+#endif
+	}
+
+#if IN_LLVM
+        // LDC make sure argument type is semanticed.
+        // Turns TypeTuple!(int, int) into two int parameters, for instance.
+        if (f->parameters)
+        {
+            for (size_t i = 0; i < Argument::dim(f->parameters); i++)
+	    {	Argument *arg = (Argument *)Argument::getNth(f->parameters, i);
+                Type* nw = arg->type->semantic(0, sc);
+                if (arg->type != nw) {
+                    arg->type = nw;
+                    // Examine this index again.
+                    // This is important if it turned into a tuple.
+                    // In particular, the empty tuple should be handled or the
+                    // next parameter will be skipped.
+                    // FIXME: Maybe we only need to do this for tuples,
+                    //        and can add tuple.length after decrement?
+                    i--;
+                }
+            }
+        }
+#endif
+
+	// Propagate storage class from tuple parameters to their element-parameters.
+	if (f->parameters)
+	{
+	    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);
+		    for (size_t j = 0; j < dim; j++)
+		    {	Argument *narg = Argument::getNth(t->arguments, j);
+			narg->storageClass = arg->storageClass;
+		    }
+		}
+	    }
+	}
+
+	/* Declare all the function parameters as variables
+	 * and install them in parameters[]
+	 */
+	size_t nparams = Argument::dim(f->parameters);
+	if (nparams)
+	{   /* parameters[] has all the tuples removed, as the back end
+	     * doesn't know about tuples
+	     */
+	    parameters = new Dsymbols();
+	    parameters->reserve(nparams);
+	    for (size_t i = 0; i < nparams; i++)
+	    {
+		Argument *arg = Argument::getNth(f->parameters, i);
+		Identifier *id = arg->ident;
+		if (!id)
+		{
+		    /* Generate identifier for un-named parameter,
+		     * because we need it later on.
+		     */
+		    arg->ident = id = Identifier::generateId("_param_", i);
+		}
+		Type *vtype = arg->type;
+		VarDeclaration *v = new VarDeclaration(loc, vtype, id, NULL);
+		//printf("declaring parameter %s of type %s\n", v->toChars(), v->type->toChars());
+		v->storage_class |= STCparameter;
+		if (f->varargs == 2 && i + 1 == nparams)
+		    v->storage_class |= STCvariadic;
+		v->storage_class |= arg->storageClass & (STCin | STCout | STCref | STClazy);
+		if (v->storage_class & STClazy)
+		    v->storage_class |= STCin;
+		v->semantic(sc2);
+		if (!sc2->insert(v))
+		    error("parameter %s.%s is already defined", toChars(), v->toChars());
+		else
+		    parameters->push(v);
+		localsymtab->insert(v);
+		v->parent = this;
+	    }
+	}
+
+	// Declare the tuple symbols and put them in the symbol table,
+	// but not in parameters[].
+	if (f->parameters)
+	{
+	    for (size_t i = 0; i < f->parameters->dim; i++)
+	    {	Argument *arg = (Argument *)f->parameters->data[i];
+
+		if (!arg->ident)
+		    continue;			// never used, so ignore
+		if (arg->type->ty == Ttuple)
+		{   TypeTuple *t = (TypeTuple *)arg->type;
+		    size_t dim = Argument::dim(t->arguments);
+		    Objects *exps = new Objects();
+		    exps->setDim(dim);
+		    for (size_t j = 0; j < dim; j++)
+		    {	Argument *narg = Argument::getNth(t->arguments, j);
+			assert(narg->ident);
+			VarDeclaration *v = sc2->search(0, narg->ident, NULL)->isVarDeclaration();
+			assert(v);
+			Expression *e = new VarExp(v->loc, v);
+			exps->data[j] = (void *)e;
+		    }
+		    assert(arg->ident);
+		    TupleDeclaration *v = new TupleDeclaration(loc, arg->ident, exps);
+		    //printf("declaring tuple %s\n", v->toChars());
+		    v->isexp = 1;
+		    if (!sc2->insert(v))
+			error("parameter %s.%s is already defined", toChars(), v->toChars());
+		    localsymtab->insert(v);
+		    v->parent = this;
+		}
+	    }
+	}
+
+	/* Do the semantic analysis on the [in] preconditions and
+	 * [out] postconditions.
+	 */
+	sc2->incontract++;
+
+	if (frequire)
+	{   /* frequire is composed of the [in] contracts
+	     */
+	    // BUG: need to error if accessing out parameters
+	    // BUG: need to treat parameters as const
+	    // BUG: need to disallow returns and throws
+	    // BUG: verify that all in and ref parameters are read
+	    frequire = frequire->semantic(sc2);
+	    labtab = NULL;		// so body can't refer to labels
+	}
+
+	if (fensure || addPostInvariant())
+	{   /* fensure is composed of the [out] contracts
+	     */
+	    if (!type->nextOf())
+	    {	// Have to do semantic() on fbody first
+		error("post conditions are not supported if the return type is inferred");
+		return;
+	    }
+
+	    ScopeDsymbol *sym = new ScopeDsymbol();
+	    sym->parent = sc2->scopesym;
+	    sc2 = sc2->push(sym);
+
+	    assert(type->nextOf());
+	    if (type->nextOf()->ty == Tvoid)
+	    {
+		if (outId)
+		    error("void functions have no result");
+	    }
+	    else
+	    {
+		if (!outId)
+		    outId = Id::result;		// provide a default
+	    }
+
+	    if (outId)
+	    {	// Declare result variable
+		VarDeclaration *v;
+		Loc loc = this->loc;
+
+		if (fensure)
+		    loc = fensure->loc;
+
+		v = new VarDeclaration(loc, type->nextOf(), outId, NULL);
+		v->noscope = 1;
+#if DMDV2
+		if (f->isref)
+		{
+		    v->storage_class |= STCref | STCforeach;
+		}
+#endif
+		sc2->incontract--;
+		v->semantic(sc2);
+		sc2->incontract++;
+		if (!sc2->insert(v))
+		    error("out result %s is already defined", v->toChars());
+		v->parent = this;
+		vresult = v;
+
+		// vresult gets initialized with the function return value
+		// in ReturnStatement::semantic()
+	    }
+
+	    // BUG: need to treat parameters as const
+	    // BUG: need to disallow returns and throws
+	    if (fensure)
+	    {	fensure = fensure->semantic(sc2);
+		labtab = NULL;		// so body can't refer to labels
+	    }
+
+	    if (!global.params.useOut)
+	    {	fensure = NULL;		// discard
+		vresult = NULL;
+	    }
+
+	    // Postcondition invariant
+	    if (addPostInvariant())
+	    {
+		Expression *e = NULL;
+		if (isCtorDeclaration())
+		{
+		    // Call invariant directly only if it exists
+		    InvariantDeclaration *inv = ad->inv;
+		    ClassDeclaration *cd = ad->isClassDeclaration();
+
+		    while (!inv && cd)
+		    {
+			cd = cd->baseClass;
+			if (!cd)
+			    break;
+			inv = cd->inv;
+		    }
+		    if (inv)
+		    {
+			e = new DsymbolExp(0, inv);
+			e = new CallExp(0, e);
+			e = e->semantic(sc2);
+		    }
+		}
+		else
+		{   // Call invariant virtually
+		    Expression *v = new ThisExp(0);
+		    v->type = vthis->type;
+#if STRUCTTHISREF
+		    if (ad->isStructDeclaration())
+			v = v->addressOf(sc);
+#endif
+		    e = new AssertExp(0, v);
+		}
+		if (e)
+		{
+		    ExpStatement *s = new ExpStatement(0, e);
+		    if (fensure)
+			fensure = new CompoundStatement(0, s, fensure);
+		    else
+			fensure = s;
+		}
+	    }
+
+	    if (fensure)
+	    {	returnLabel = new LabelDsymbol(Id::returnLabel);
+		LabelStatement *ls = new LabelStatement(0, Id::returnLabel, fensure);
+		ls->isReturnLabel = 1;
+		returnLabel->statement = ls;
+	    }
+	    sc2 = sc2->pop();
+	}
+
+	sc2->incontract--;
+
+	if (fbody)
+	{   ClassDeclaration *cd = isClassMember();
+
+	    /* If this is a class constructor
+	     */
+	    if (isCtorDeclaration() && cd)
+	    {
+		for (int i = 0; i < cd->fields.dim; i++)
+		{   VarDeclaration *v = (VarDeclaration *)cd->fields.data[i];
+
+		    v->ctorinit = 0;
+		}
+	    }
+
+	    if (inferRetType || f->retStyle() != RETstack)
+		nrvo_can = 0;
+
+	    fbody = fbody->semantic(sc2);
+
+	    if (inferRetType)
+	    {	// If no return type inferred yet, then infer a void
+		if (!type->nextOf())
+		{
+		    ((TypeFunction *)type)->next = Type::tvoid;
+		    type = type->semantic(loc, sc);
+		}
+		f = (TypeFunction *)type;
+	    }
+
+	    int offend = fbody ? fbody->blockExit() & BEfallthru : TRUE;
+
+	    if (isStaticCtorDeclaration())
+	    {	/* It's a static constructor. Ensure that all
+		 * ctor consts were initialized.
+		 */
+
+		Dsymbol *p = toParent();
+		ScopeDsymbol *ad = p->isScopeDsymbol();
+		if (!ad)
+		{
+		    error("static constructor can only be member of struct/class/module, not %s %s", p->kind(), p->toChars());
+		}
+		else
+		{
+		    for (int i = 0; i < ad->members->dim; i++)
+		    {   Dsymbol *s = (Dsymbol *)ad->members->data[i];
+
+			s->checkCtorConstInit();
+		    }
+		}
+	    }
+
+	    if (isCtorDeclaration() && cd)
+	    {
+		//printf("callSuper = x%x\n", sc2->callSuper);
+
+		// Verify that all the ctorinit fields got initialized
+		if (!(sc2->callSuper & CSXthis_ctor))
+		{
+		    for (int i = 0; i < cd->fields.dim; i++)
+		    {   VarDeclaration *v = (VarDeclaration *)cd->fields.data[i];
+
+			if (v->ctorinit == 0 && v->isCtorinit())
+			    error("missing initializer for const field %s", v->toChars());
+		    }
+		}
+
+		if (!(sc2->callSuper & CSXany_ctor) &&
+		    cd->baseClass && cd->baseClass->ctor)
+		{
+		    sc2->callSuper = 0;
+
+		    // Insert implicit super() at start of fbody
+		    Expression *e1 = new SuperExp(0);
+		    Expression *e = new CallExp(0, e1);
+
+		    unsigned errors = global.errors;
+		    global.gag++;
+		    e = e->semantic(sc2);
+		    global.gag--;
+		    if (errors != global.errors)
+			error("no match for implicit super() call in constructor");
+
+		    Statement *s = new ExpStatement(0, e);
+		    fbody = new CompoundStatement(0, s, fbody);
+		}
+	    }
+	    else if (fes)
+	    {	// For foreach(){} body, append a return 0;
+		Expression *e = new IntegerExp(0);
+		Statement *s = new ReturnStatement(0, e);
+		fbody = new CompoundStatement(0, fbody, s);
+		assert(!returnLabel);
+	    }
+	    else if (!hasReturnExp && type->nextOf()->ty != Tvoid)
+		error("expected to return a value of type %s", type->nextOf()->toChars());
+	    else if (!inlineAsm)
+	    {
+#if DMDV2
+		int blockexit = fbody ? fbody->blockExit() : BEfallthru;
+		if (f->isnothrow && blockexit & BEthrow)
+		    error("'%s' is nothrow yet may throw", toChars());
+
+		int offend = blockexit & BEfallthru;
+#endif
+		if (type->nextOf()->ty == Tvoid)
+		{
+		    if (offend && isMain())
+		    {	// Add a return 0; statement
+			Statement *s = new ReturnStatement(0, new IntegerExp(0));
+			fbody = new CompoundStatement(0, fbody, s);
+		    }
+		}
+		else
+		{
+		    if (offend)
+		    {   Expression *e;
+#if DMDV1
+			warning(loc, "no return exp; or assert(0); at end of function");
+#else
+			error("no return exp; or assert(0); at end of function");
+#endif
+			if (global.params.useAssert &&
+			    !global.params.useInline)
+			{   /* Add an assert(0, msg); where the missing return
+			     * should be.
+			     */
+			    e = new AssertExp(
+				  endloc,
+				  new IntegerExp(0),
+				  new StringExp(loc, (char *)"missing return expression")
+				);
+			}
+			else
+			    e = new HaltExp(endloc);
+			e = new CommaExp(0, e, type->nextOf()->defaultInit());
+			e = e->semantic(sc2);
+			Statement *s = new ExpStatement(0, e);
+			fbody = new CompoundStatement(0, fbody, s);
+		    }
+		}
+	    }
+	}
+
+	{
+	    Statements *a = new Statements();
+
+	    // Merge in initialization of 'out' parameters
+	    if (parameters)
+	    {	for (size_t i = 0; i < parameters->dim; i++)
+		{
+		    VarDeclaration *v = (VarDeclaration *)parameters->data[i];
+		    if (v->storage_class & STCout)
+		    {
+			assert(v->init);
+			ExpInitializer *ie = v->init->isExpInitializer();
+			assert(ie);
+			a->push(new ExpStatement(0, ie->exp));
+		    }
+		}
+	    }
+
+// we'll handle variadics ourselves
+#if !IN_LLVM
+	    if (argptr)
+	    {	// Initialize _argptr to point past non-variadic arg
+#if IN_GCC
+		// Handled in FuncDeclaration::toObjFile
+		v_argptr = argptr;
+		v_argptr->init = new VoidInitializer(loc);
+#else
+		Expression *e1;
+		Expression *e;
+		Type *t = argptr->type;
+		VarDeclaration *p;
+		unsigned offset;
+
+		e1 = new VarExp(0, argptr);
+		if (parameters && parameters->dim)
+		    p = (VarDeclaration *)parameters->data[parameters->dim - 1];
+		else
+		    p = v_arguments;		// last parameter is _arguments[]
+		if (p->storage_class & STClazy)
+		    // If the last parameter is lazy, it's the size of a delegate
+		    offset = PTRSIZE * 2;
+		else
+		    offset = p->type->size();
+		offset = (offset + 3) & ~3;	// assume stack aligns on 4
+		e = new SymOffExp(0, p, offset);
+		e = new AssignExp(0, e1, e);
+		e->type = t;
+		a->push(new ExpStatement(0, e));
+#endif // IN_GCC
+	    }
+
+	    if (_arguments)
+	    {
+		/* Advance to elements[] member of TypeInfo_Tuple with:
+		 *  _arguments = v_arguments.elements;
+		 */
+		Expression *e = new VarExp(0, v_arguments);
+		e = new DotIdExp(0, e, Id::elements);
+		Expression *e1 = new VarExp(0, _arguments);
+		e = new AssignExp(0, e1, e);
+		e->op = TOKconstruct;
+		e = e->semantic(sc2);
+		a->push(new ExpStatement(0, e));
+	    }
+
+#endif // !IN_LLVM
+
+	    // Merge contracts together with body into one compound statement
+
+#ifdef _DH
+	    if (frequire && global.params.useIn)
+	    {	frequire->incontract = 1;
+		a->push(frequire);
+	    }
+#else
+	    if (frequire && global.params.useIn)
+		a->push(frequire);
+#endif
+
+	    // Precondition invariant
+	    if (addPreInvariant())
+	    {
+		Expression *e = NULL;
+                Expression *ee = NULL;
+		if (isDtorDeclaration())
+		{
+		    // Call invariant directly only if it exists
+		    InvariantDeclaration *inv = ad->inv;
+		    ClassDeclaration *cd = ad->isClassDeclaration();
+
+		    while (!inv && cd)
+		    {
+			cd = cd->baseClass;
+			if (!cd)
+			    break;
+			inv = cd->inv;
+		    }
+		    if (inv)
+		    {
+			e = new DsymbolExp(0, inv);
+			e = new CallExp(0, e);
+			e = e->semantic(sc2);
+		    }
+		}
+		else
+		{   // Call invariant virtually
+                    // LDC: unless this is a struct without invariant
+                    StructDeclaration* sd = ad->isStructDeclaration();
+                    if (!sd || sd->inv)
+                    {
+                        ThisExp *v = new ThisExp(0);
+                        v->type = vthis->type;
+                        e = new AssertExp(loc, v, NULL);
+                    }
+
+                    // LDC: check for null this
+                    ThisExp* v = new ThisExp(0);
+                    v->type = vthis->type;
+#if STRUCTTHISREF
+		    if (ad->isStructDeclaration())
+			v = v->addressOf(sc);
+#endif                    
+                    v->var = vthis;
+
+                    NullExp *nv = new NullExp(0);
+                    nv->type = v->type;
+
+                    IdentityExp *ie = new IdentityExp(TOKnotidentity, 0, v, nv);
+                    ie->type = Type::tbool;
+
+		    Expression *se = new StringExp(0, (char *)"null this");
+		    se = se->semantic(sc);
+		    se->type = Type::tchar->arrayOf();
+
+		    ee = new AssertExp(loc, ie, se);
+		}
+                if (ee)
+                {
+                    ExpStatement *s = new ExpStatement(0, ee);
+                    a->push(s);
+                }
+		if (e)
+		{
+		    ExpStatement *s = new ExpStatement(0, e);
+		    a->push(s);
+		}
+	    }
+
+	    if (fbody)
+		a->push(fbody);
+
+	    if (fensure)
+	    {
+		a->push(returnLabel->statement);
+
+		if (type->nextOf()->ty != Tvoid)
+		{
+		    // Create: return vresult;
+		    assert(vresult);
+		    Expression *e = new VarExp(0, vresult);
+		    if (tintro)
+		    {	e = e->implicitCastTo(sc, tintro->nextOf());
+			e = e->semantic(sc);
+		    }
+		    ReturnStatement *s = new ReturnStatement(0, e);
+		    a->push(s);
+		}
+	    }
+
+	    fbody = new CompoundStatement(0, a);
+#if DMDV2
+	    /* Append destructor calls for parameters as finally blocks.
+	     */
+	    if (parameters)
+	    {	for (size_t i = 0; i < parameters->dim; i++)
+		{
+		    VarDeclaration *v = (VarDeclaration *)parameters->data[i];
+
+		    if (v->storage_class & (STCref | STCout))
+			continue;
+
+		    /* Don't do this for static arrays, since static
+		     * arrays are called by reference. Remove this
+		     * when we change them to call by value.
+		     */
+		    if (v->type->toBasetype()->ty == Tsarray)
+			continue;
+
+		    Expression *e = v->callAutoDtor(sc);
+		    if (e)
+		    {	Statement *s = new ExpStatement(0, e);
+			s = s->semantic(sc);
+			if (fbody->blockExit() == BEfallthru)
+			    fbody = new CompoundStatement(0, fbody, s);
+			else
+			    fbody = new TryFinallyStatement(0, fbody, s);
+		    }
+		}
+	    }
+#endif
+
+	    // wrap body of synchronized functions in a synchronized statement
+	    if (isSynchronized())
+	    {
+		ClassDeclaration *cd = parent->isClassDeclaration();
+		if (!cd)
+		    error("synchronized function %s must be a member of a class", toChars());
+		    
+		Expression *sync;
+		if (isStatic())
+		{
+		    // static member functions synchronize on classinfo 
+		    sync = cd->type->dotExp(sc2, new TypeExp(loc, cd->type), Id::classinfo);
+		}
+		else
+		{
+		    // non-static member functions synchronize on this
+		    sync = new VarExp(loc, vthis);
+		}
+                
+		// we do not want to rerun semantics on the whole function, so we
+		// manually adjust all labels in the function that currently don't
+		// have an enclosingScopeExit to use the new SynchronizedStatement
+		SynchronizedStatement* s = new SynchronizedStatement(loc, sync, NULL);
+		s->semantic(sc2);
+		s->body = fbody;
+		
+		// LDC
+		LabelMap::iterator it, end = labmap.end();
+		for (it = labmap.begin(); it != end; ++it)
+		    if (it->second->enclosingScopeExit == NULL)
+			it->second->enclosingScopeExit = s;
+		
+		a = new Statements;
+		a->push(s);
+		fbody = new CompoundStatement(0, a);
+	    }
+	}
+
+	sc2->callSuper = 0;
+	sc2->pop();
+    }
+    semanticRun = 4;
+}
+
+void FuncDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    //printf("FuncDeclaration::toCBuffer() '%s'\n", toChars());
+
+    type->toCBuffer(buf, ident, hgs);
+    bodyToCBuffer(buf, hgs);
+}
+
+
+void FuncDeclaration::bodyToCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    if (fbody &&
+	(!hgs->hdrgen || hgs->tpltMember || canInline(1,1))
+       )
+    {	buf->writenl();
+
+	// in{}
+	if (frequire)
+	{   buf->writestring("in");
+	    buf->writenl();
+	    frequire->toCBuffer(buf, hgs);
+	}
+
+	// out{}
+	if (fensure)
+	{   buf->writestring("out");
+	    if (outId)
+	    {   buf->writebyte('(');
+		buf->writestring(outId->toChars());
+		buf->writebyte(')');
+	    }
+	    buf->writenl();
+	    fensure->toCBuffer(buf, hgs);
+	}
+
+        if (frequire || fensure)
+	{   buf->writestring("body");
+	    buf->writenl();
+	}
+
+	buf->writebyte('{');
+	buf->writenl();
+	fbody->toCBuffer(buf, hgs);
+	buf->writebyte('}');
+	buf->writenl();
+    }
+    else
+    {	buf->writeByte(';');
+	buf->writenl();
+    }
+}
+
+/****************************************************
+ * Merge into this function the 'in' contracts of all it overrides.
+ * 'in's are OR'd together, i.e. only one of them needs to pass.
+ */
+
+Statement *FuncDeclaration::mergeFrequire(Statement *sf)
+{
+    /* Implementing this is done by having the overriding function call
+     * nested functions (the fdrequire functions) nested inside the overridden
+     * function. This requires that the stack layout of the calling function's
+     * parameters and 'this' pointer be in the same place (as the nested
+     * function refers to them).
+     * This is easy for the parameters, as they are all on the stack in the same
+     * place by definition, since it's an overriding function. The problem is
+     * getting the 'this' pointer in the same place, since it is a local variable.
+     * We did some hacks in the code generator to make this happen:
+     *	1. always generate exception handler frame, or at least leave space for it
+     *     in the frame (Windows 32 SEH only)
+     *	2. always generate an EBP style frame
+     *  3. since 'this' is passed in a register that is subsequently copied into
+     *     a stack local, allocate that local immediately following the exception
+     *     handler block, so it is always at the same offset from EBP.
+     */
+    for (int i = 0; i < foverrides.dim; i++)
+    {
+	FuncDeclaration *fdv = (FuncDeclaration *)foverrides.data[i];
+	sf = fdv->mergeFrequire(sf);
+	if (fdv->fdrequire)
+	{
+	    //printf("fdv->frequire: %s\n", fdv->frequire->toChars());
+	    /* Make the call:
+	     *   try { __require(); }
+	     *   catch { frequire; }
+	     */
+	    Expression *eresult = NULL;
+	    Expression *e = new CallExp(loc, new VarExp(loc, fdv->fdrequire), eresult);
+	    Statement *s2 = new ExpStatement(loc, e);
+
+	    if (sf)
+	    {	Catch *c = new Catch(loc, NULL, NULL, sf);
+		Array *catches = new Array();
+		catches->push(c);
+		sf = new TryCatchStatement(loc, s2, catches);
+	    }
+	    else
+		sf = s2;
+	}
+    }
+    return sf;
+}
+
+/****************************************************
+ * Merge into this function the 'out' contracts of all it overrides.
+ * 'out's are AND'd together, i.e. all of them need to pass.
+ */
+
+Statement *FuncDeclaration::mergeFensure(Statement *sf)
+{
+    /* Same comments as for mergeFrequire(), except that we take care
+     * of generating a consistent reference to the 'result' local by
+     * explicitly passing 'result' to the nested function as a reference
+     * argument.
+     * This won't work for the 'this' parameter as it would require changing
+     * the semantic code for the nested function so that it looks on the parameter
+     * list for the 'this' pointer, something that would need an unknown amount
+     * of tweaking of various parts of the compiler that I'd rather leave alone.
+     */
+    for (int i = 0; i < foverrides.dim; i++)
+    {
+	FuncDeclaration *fdv = (FuncDeclaration *)foverrides.data[i];
+	sf = fdv->mergeFensure(sf);
+	if (fdv->fdensure)
+	{
+	    //printf("fdv->fensure: %s\n", fdv->fensure->toChars());
+	    // Make the call: __ensure(result)
+	    Expression *eresult = NULL;
+	    if (outId)
+		eresult = new IdentifierExp(loc, outId);
+	    Expression *e = new CallExp(loc, new VarExp(loc, fdv->fdensure), eresult);
+	    Statement *s2 = new ExpStatement(loc, e);
+
+	    if (sf)
+	    {
+		sf = new CompoundStatement(fensure->loc, s2, sf);
+	    }
+	    else
+		sf = s2;
+	}
+    }
+    return sf;
+}
+
+/****************************************************
+ * Determine if 'this' overrides fd.
+ * Return !=0 if it does.
+ */
+
+int FuncDeclaration::overrides(FuncDeclaration *fd)
+{   int result = 0;
+
+    if (fd->ident == ident)
+    {
+	int cov = type->covariant(fd->type);
+	if (cov)
+	{   ClassDeclaration *cd1 = toParent()->isClassDeclaration();
+	    ClassDeclaration *cd2 = fd->toParent()->isClassDeclaration();
+
+	    if (cd1 && cd2 && cd2->isBaseOf(cd1, NULL))
+		result = 1;
+	}
+    }
+    return result;
+}
+
+/*************************************************
+ * Find index of function in vtbl[0..dim] that
+ * this function overrides.
+ * Returns:
+ *	-1	didn't find one
+ *	-2	can't determine because of forward references
+ */
+
+int FuncDeclaration::findVtblIndex(Array *vtbl, int dim)
+{
+    for (int vi = 0; vi < dim; vi++)
+    {
+	FuncDeclaration *fdv = ((Dsymbol *)vtbl->data[vi])->isFuncDeclaration();
+	if (fdv && fdv->ident == ident)
+	{
+	    int cov = type->covariant(fdv->type);
+	    //printf("\tbaseclass cov = %d\n", cov);
+	    switch (cov)
+	    {
+		case 0:		// types are distinct
+		    break;
+
+		case 1:
+		    return vi;
+
+		case 2:
+		    //type->print();
+		    //fdv->type->print();
+		    //printf("%s %s\n", type->deco, fdv->type->deco);
+		    error("of type %s overrides but is not covariant with %s of type %s",
+			type->toChars(), fdv->toPrettyChars(), fdv->type->toChars());
+		    break;
+
+		case 3:
+		    return -2;	// forward references
+
+		default:
+		    assert(0);
+	    }
+	}
+    }
+    return -1;
+}
+
+/****************************************************
+ * Overload this FuncDeclaration with the new one f.
+ * Return !=0 if successful; i.e. no conflict.
+ */
+
+int FuncDeclaration::overloadInsert(Dsymbol *s)
+{
+    FuncDeclaration *f;
+    AliasDeclaration *a;
+
+    //printf("FuncDeclaration::overloadInsert(%s)\n", s->toChars());
+    a = s->isAliasDeclaration();
+    if (a)
+    {
+	if (overnext)
+	    return overnext->overloadInsert(a);
+	if (!a->aliassym && a->type->ty != Tident && a->type->ty != Tinstance)
+	{
+	    //printf("\ta = '%s'\n", a->type->toChars());
+	    return FALSE;
+	}
+	overnext = a;
+	//printf("\ttrue: no conflict\n");
+	return TRUE;
+    }
+    f = s->isFuncDeclaration();
+    if (!f)
+	return FALSE;
+
+    if (type && f->type &&	// can be NULL for overloaded constructors
+	f->type->covariant(type) &&
+	!isFuncAliasDeclaration())
+    {
+	//printf("\tfalse: conflict %s\n", kind());
+	return FALSE;
+    }
+
+    if (overnext)
+	return overnext->overloadInsert(f);
+    overnext = f;
+    //printf("\ttrue: no conflict\n");
+    return TRUE;
+}
+
+/********************************************
+ * Find function in overload list that exactly matches t.
+ */
+
+/***************************************************
+ * Visit each overloaded function in turn, and call
+ * (*fp)(param, f) on it.
+ * Exit when no more, or (*fp)(param, f) returns 1.
+ * Returns:
+ *	0	continue
+ *	1	done
+ */
+
+int overloadApply(Module* from, FuncDeclaration *fstart,
+	int (*fp)(void *, FuncDeclaration *),
+	void *param)
+{
+    FuncDeclaration *f;
+    Declaration *d;
+    Declaration *next;
+
+    for (d = fstart; d; d = next)
+    {	FuncAliasDeclaration *fa = d->isFuncAliasDeclaration();
+
+	if (fa)
+	{
+	    if (fa->getModule() == from || fa->importprot != PROTprivate)
+		if (overloadApply(from, fa->funcalias, fp, param))
+		    return 1;
+	    next = fa->overnext;
+	}
+	else
+	{
+	    AliasDeclaration *a = d->isAliasDeclaration();
+
+	    if (a)
+	    {
+		Dsymbol *s = a->toAlias();
+		next = s->isDeclaration();
+		if (next == a)
+		    break;
+		if (next == fstart)
+		    break;
+		if (a->importprot == PROTprivate && a->getModule() != from)
+		    if (FuncDeclaration* fd = next->isFuncDeclaration())
+			next = fd->overnext;
+	    }
+	    else
+	    {
+		f = d->isFuncDeclaration();
+		if (!f)
+		{   d->error("is aliased to a function");
+		    break;		// BUG: should print error message?
+		}
+		if ((*fp)(param, f))
+		    return 1;
+
+		next = f->overnext;
+	    }
+	}
+    }
+    return 0;
+}
+
+/********************************************
+ * If there are no overloads of function f, return that function,
+ * otherwise return NULL.
+ */
+
+static int fpunique(void *param, FuncDeclaration *f)
+{   FuncDeclaration **pf = (FuncDeclaration **)param;
+
+    if (*pf)
+    {	*pf = NULL;
+	return 1;		// ambiguous, done
+    }
+    else
+    {	*pf = f;
+	return 0;
+    }
+}
+
+FuncDeclaration *FuncDeclaration::isUnique()
+{   FuncDeclaration *result = NULL;
+
+    overloadApply(getModule(), this, &fpunique, &result);
+    return result;
+}
+
+/********************************************
+ * Find function in overload list that exactly matches t.
+ */
+
+struct Param1
+{
+    Type *t;		// type to match
+    FuncDeclaration *f;	// return value
+};
+
+int fp1(void *param, FuncDeclaration *f)
+{   Param1 *p = (Param1 *)param;
+    Type *t = p->t;
+
+    if (t->equals(f->type))
+    {	p->f = f;
+	return 1;
+    }
+
+#if DMDV2
+    /* Allow covariant matches, if it's just a const conversion
+     * of the return type
+     */
+    if (t->ty == Tfunction)
+    {   TypeFunction *tf = (TypeFunction *)f->type;
+	if (tf->covariant(t) == 1 &&
+	    tf->nextOf()->implicitConvTo(t->nextOf()) >= MATCHconst)
+	{
+	    p->f = f;
+	    return 1;
+	}
+    }
+#endif
+    return 0;
+}
+
+FuncDeclaration *FuncDeclaration::overloadExactMatch(Type *t, Module* from)
+{
+    Param1 p;
+    p.t = t;
+    p.f = NULL;
+    overloadApply(from, this, &fp1, &p);
+    return p.f;
+}
+
+#if 0
+FuncDeclaration *FuncDeclaration::overloadExactMatch(Type *t)
+{
+    FuncDeclaration *f;
+    Declaration *d;
+    Declaration *next;
+
+    for (d = this; d; d = next)
+    {	FuncAliasDeclaration *fa = d->isFuncAliasDeclaration();
+
+	if (fa)
+	{
+	    FuncDeclaration *f2 = fa->funcalias->overloadExactMatch(t);
+	    if (f2)
+		return f2;
+	    next = fa->overnext;
+	}
+	else
+	{
+	    AliasDeclaration *a = d->isAliasDeclaration();
+
+	    if (a)
+	    {
+		Dsymbol *s = a->toAlias();
+		next = s->isDeclaration();
+		if (next == a)
+		    break;
+	    }
+	    else
+	    {
+		f = d->isFuncDeclaration();
+		if (!f)
+		    break;		// BUG: should print error message?
+		if (t->equals(d->type))
+		    return f;
+		next = f->overnext;
+	    }
+	}
+    }
+    return NULL;
+}
+#endif
+
+/********************************************
+ * Decide which function matches the arguments best.
+ */
+
+struct Param2
+{
+    Match *m;
+    Expressions *arguments;
+};
+
+int fp2(void *param, FuncDeclaration *f)
+{   Param2 *p = (Param2 *)param;
+    Match *m = p->m;
+    Expressions *arguments = p->arguments;
+    MATCH match;
+
+    if (f != m->lastf)		// skip duplicates
+    {
+	m->anyf = f;
+	TypeFunction *tf = (TypeFunction *)f->type;
+	match = (MATCH) tf->callMatch(arguments);
+	//printf("1match = %d\n", match);
+	if (match != MATCHnomatch)
+	{
+	    if (match > m->last)
+		goto LfIsBetter;
+
+	    if (match < m->last)
+		goto LlastIsBetter;
+
+	    /* See if one of the matches overrides the other.
+	     */
+	    if (m->lastf->overrides(f))
+		goto LlastIsBetter;
+	    else if (f->overrides(m->lastf))
+		goto LfIsBetter;
+
+	Lambiguous:
+	    m->nextf = f;
+	    m->count++;
+	    return 0;
+
+	LfIsBetter:
+	    m->last = match;
+	    m->lastf = f;
+	    m->count = 1;
+	    return 0;
+
+	LlastIsBetter:
+	    return 0;
+	}
+    }
+    return 0;
+}
+
+
+void overloadResolveX(Match *m, FuncDeclaration *fstart,
+	Expression *ethis, Expressions *arguments, Module *from)
+{
+    Param2 p;
+    p.m = m;
+    p.arguments = arguments;
+    overloadApply(from, fstart, &fp2, &p);
+}
+
+#if 0
+// Recursive helper function
+
+void overloadResolveX(Match *m, FuncDeclaration *fstart, Expressions *arguments)
+{
+    MATCH match;
+    Declaration *d;
+    Declaration *next;
+
+    for (d = fstart; d; d = next)
+    {
+	FuncDeclaration *f;
+	FuncAliasDeclaration *fa;
+	AliasDeclaration *a;
+
+	fa = d->isFuncAliasDeclaration();
+	if (fa)
+	{
+	    overloadResolveX(m, fa->funcalias, NULL, arguments);
+	    next = fa->overnext;
+	}
+	else if ((f = d->isFuncDeclaration()) != NULL)
+	{
+	    next = f->overnext;
+	    if (f == m->lastf)
+		continue;			// skip duplicates
+	    else
+	    {
+		TypeFunction *tf;
+
+		m->anyf = f;
+		tf = (TypeFunction *)f->type;
+		match = (MATCH) tf->callMatch(arguments);
+		//printf("2match = %d\n", match);
+		if (match != MATCHnomatch)
+		{
+		    if (match > m->last)
+			goto LfIsBetter;
+
+		    if (match < m->last)
+			goto LlastIsBetter;
+
+		    /* See if one of the matches overrides the other.
+		     */
+		    if (m->lastf->overrides(f))
+			goto LlastIsBetter;
+		    else if (f->overrides(m->lastf))
+			goto LfIsBetter;
+
+		Lambiguous:
+		    m->nextf = f;
+		    m->count++;
+		    continue;
+
+		LfIsBetter:
+		    m->last = match;
+		    m->lastf = f;
+		    m->count = 1;
+		    continue;
+
+		LlastIsBetter:
+		    continue;
+		}
+	    }
+	}
+	else if ((a = d->isAliasDeclaration()) != NULL)
+	{
+	    Dsymbol *s = a->toAlias();
+	    next = s->isDeclaration();
+	    if (next == a)
+		break;
+	    if (next == fstart)
+		break;
+	}
+	else
+	{   d->error("is aliased to a function");
+	    break;
+	}
+    }
+}
+#endif
+
+FuncDeclaration *FuncDeclaration::overloadResolve(Loc loc, Expression *ethis, Expressions *arguments, Module *from, int flags)
+{
+    TypeFunction *tf;
+    Match m;
+
+#if 0
+printf("FuncDeclaration::overloadResolve('%s')\n", toChars());
+if (arguments)
+{   int i;
+
+    for (i = 0; i < arguments->dim; i++)
+    {   Expression *arg;
+
+	arg = (Expression *)arguments->data[i];
+	assert(arg->type);
+	printf("\t%s: ", arg->toChars());
+	arg->type->print();
+    }
+}
+#endif
+
+    memset(&m, 0, sizeof(m));
+    m.last = MATCHnomatch;
+    overloadResolveX(&m, this, NULL, arguments, from);
+
+    if (m.count == 1)		// exactly one match
+    {
+	return m.lastf;
+    }
+    else
+    {
+	OutBuffer buf;
+
+	if (arguments)
+	{
+	    HdrGenState hgs;
+
+	    argExpTypesToCBuffer(&buf, arguments, &hgs);
+	}
+
+	if (m.last == MATCHnomatch)
+	{
+	    tf = (TypeFunction *)type;
+
+	    //printf("tf = %s, args = %s\n", tf->deco, ((Expression *)arguments->data[0])->type->deco);
+	    error(loc, "%s does not match parameter types (%s)",
+		Argument::argsTypesToChars(tf->parameters, tf->varargs),
+		buf.toChars());
+	    return m.anyf;		// as long as it's not a FuncAliasDeclaration
+	}
+	else
+	{
+#if 1
+	    TypeFunction *t1 = (TypeFunction *)m.lastf->type;
+	    TypeFunction *t2 = (TypeFunction *)m.nextf->type;
+
+	    error(loc, "called with argument types:\n\t(%s)\nmatches both:\n\t%s%s\nand:\n\t%s%s",
+		    buf.toChars(),
+		    m.lastf->toPrettyChars(), Argument::argsTypesToChars(t1->parameters, t1->varargs),
+		    m.nextf->toPrettyChars(), Argument::argsTypesToChars(t2->parameters, t2->varargs));
+#else
+	    error(loc, "overloads %s and %s both match argument list for %s",
+		    m.lastf->type->toChars(),
+		    m.nextf->type->toChars(),
+		    m.lastf->toChars());
+#endif
+	    return m.lastf;
+	}
+    }
+}
+
+/********************************
+ * Labels are in a separate scope, one per function.
+ */
+
+LabelDsymbol *FuncDeclaration::searchLabel(Identifier *ident)
+{   Dsymbol *s;
+
+    if (!labtab)
+	labtab = new DsymbolTable();	// guess we need one
+
+    s = labtab->lookup(ident);
+    if (!s)
+    {
+	s = new LabelDsymbol(ident);
+	labtab->insert(s);
+    }
+    return (LabelDsymbol *)s;
+}
+
+/****************************************
+ * If non-static member function that has a 'this' pointer,
+ * return the aggregate it is a member of.
+ * Otherwise, return NULL.
+ */
+
+AggregateDeclaration *FuncDeclaration::isThis()
+{   AggregateDeclaration *ad;
+
+    //printf("+FuncDeclaration::isThis() '%s'\n", toChars());
+    ad = NULL;
+    if ((storage_class & STCstatic) == 0)
+    {
+	ad = isMember2();
+    }
+    //printf("-FuncDeclaration::isThis() %p\n", ad);
+    return ad;
+}
+
+AggregateDeclaration *FuncDeclaration::isMember2()
+{   AggregateDeclaration *ad;
+
+    //printf("+FuncDeclaration::isMember2() '%s'\n", toChars());
+    ad = NULL;
+    for (Dsymbol *s = this; s; s = s->parent)
+    {
+//printf("\ts = '%s', parent = '%s', kind = %s\n", s->toChars(), s->parent->toChars(), s->parent->kind());
+	ad = s->isMember();
+	if (ad)
+{   //printf("test4\n");
+	    break;
+}
+	if (!s->parent ||
+	    (!s->parent->isTemplateInstance()))
+{   //printf("test5\n");
+	    break;
+}
+    }
+    //printf("-FuncDeclaration::isMember2() %p\n", ad);
+    return ad;
+}
+
+/*****************************************
+ * Determine lexical level difference from 'this' to nested function 'fd'.
+ * Error if this cannot call fd.
+ * Returns:
+ *	0	same level
+ *	-1	increase nesting by 1 (fd is nested within 'this')
+ *	>0	decrease nesting by number
+ */
+
+int FuncDeclaration::getLevel(Loc loc, FuncDeclaration *fd)
+{   int level;
+    Dsymbol *s;
+    Dsymbol *fdparent;
+
+    //printf("FuncDeclaration::getLevel(fd = '%s')\n", fd->toChars());
+    fdparent = fd->toParent2();
+    if (fdparent == this)
+	return -1;
+    s = this;
+    level = 0;
+    while (fd != s && fdparent != s->toParent2())
+    {
+	//printf("\ts = '%s'\n", s->toChars());
+	FuncDeclaration *thisfd = s->isFuncDeclaration();
+	if (thisfd)
+	{   if (!thisfd->isNested() && !thisfd->vthis)
+		goto Lerr;
+	}
+	else
+	{
+	    ClassDeclaration *thiscd = s->isClassDeclaration();
+	    if (thiscd)
+	    {	if (!thiscd->isNested())
+		    goto Lerr;
+	    }
+	    else
+		goto Lerr;
+	}
+
+	s = s->toParent2();
+	assert(s);
+	level++;
+    }
+    return level;
+
+Lerr:
+    error(loc, "cannot access frame of function %s", fd->toChars());
+    return 1;
+}
+
+void FuncDeclaration::appendExp(Expression *e)
+{   Statement *s;
+
+    s = new ExpStatement(0, e);
+    appendState(s);
+}
+
+void FuncDeclaration::appendState(Statement *s)
+{   CompoundStatement *cs;
+
+    if (!fbody)
+    {	Statements *a;
+
+	a = new Statements();
+	fbody = new CompoundStatement(0, a);
+    }
+    cs = fbody->isCompoundStatement();
+    cs->statements->push(s);
+}
+
+const char *FuncDeclaration::toPrettyChars()
+{
+    if (isMain())
+	return "D main";
+    else
+	return Dsymbol::toPrettyChars();
+}
+
+int FuncDeclaration::isMain()
+{
+    return ident == Id::main &&
+	linkage != LINKc && !isMember() && !isNested();
+}
+
+int FuncDeclaration::isWinMain()
+{
+    //printf("FuncDeclaration::isWinMain() %s\n", toChars());
+#if 0
+    int x = ident == Id::WinMain &&
+	linkage != LINKc && !isMember();
+    printf("%s\n", x ? "yes" : "no");
+    return x;
+#else
+    return ident == Id::WinMain &&
+	linkage != LINKc && !isMember();
+#endif
+}
+
+int FuncDeclaration::isDllMain()
+{
+    return ident == Id::DllMain &&
+	linkage != LINKc && !isMember();
+}
+
+int FuncDeclaration::isExport()
+{
+    return protection == PROTexport;
+}
+
+int FuncDeclaration::isImportedSymbol()
+{
+    //printf("isImportedSymbol()\n");
+    //printf("protection = %d\n", protection);
+    return (protection == PROTexport) && !fbody;
+}
+
+// Determine if function goes into virtual function pointer table
+
+int FuncDeclaration::isVirtual()
+{
+#if 0
+    printf("FuncDeclaration::isVirtual(%s)\n", toChars());
+    printf("%p %d %d %d %d\n", isMember(), isStatic(), protection == PROTprivate, isCtorDeclaration(), linkage != LINKd);
+    printf("result is %d\n",
+	isMember() &&
+	!(isStatic() || protection == PROTprivate || protection == PROTpackage) &&
+	toParent()->isClassDeclaration());
+#endif
+    return isMember() &&
+	!(isStatic() || protection == PROTprivate || protection == PROTpackage) &&
+	toParent()->isClassDeclaration();
+}
+
+int FuncDeclaration::isFinal()
+{
+    ClassDeclaration *cd;
+#if 0
+    printf("FuncDeclaration::isFinal(%s)\n", toChars());
+    printf("%p %d %d %d %d\n", isMember(), isStatic(), protection == PROTprivate, isCtorDeclaration(), linkage != LINKd);
+    printf("result is %d\n",
+	isMember() &&
+	!(isStatic() || protection == PROTprivate || protection == PROTpackage) &&
+	(cd = toParent()->isClassDeclaration()) != NULL &&
+	cd->storage_class & STCfinal);
+#endif
+    return isMember() &&
+	(Declaration::isFinal() ||
+	 ((cd = toParent()->isClassDeclaration()) != NULL && cd->storage_class & STCfinal));
+}
+
+int FuncDeclaration::isAbstract()
+{
+    return storage_class & STCabstract;
+}
+
+int FuncDeclaration::isCodeseg()
+{
+    return TRUE;		// functions are always in the code segment
+}
+
+// Determine if function needs
+// a static frame pointer to its lexically enclosing function
+
+int FuncDeclaration::isNested()
+{
+    //if (!toParent())
+	//printf("FuncDeclaration::isNested('%s') parent=%p\n", toChars(), parent);
+    //printf("\ttoParent() = '%s'\n", toParent()->toChars());
+    return ((storage_class & STCstatic) == 0) && toParent2() &&
+	   (toParent2()->isFuncDeclaration() != NULL);
+}
+
+int FuncDeclaration::needThis()
+{
+    //printf("FuncDeclaration::needThis() '%s'\n", toChars());
+    int i = isThis() != NULL;
+    //printf("\t%d\n", i);
+    if (!i && isFuncAliasDeclaration())
+	i = ((FuncAliasDeclaration *)this)->funcalias->needThis();
+    return i;
+}
+
+int FuncDeclaration::addPreInvariant()
+{
+    AggregateDeclaration *ad = isThis();
+    return (ad &&
+	    //ad->isClassDeclaration() &&
+	    global.params.useInvariants &&
+	    (protection == PROTpublic || protection == PROTexport) &&
+	    !naked);
+}
+
+int FuncDeclaration::addPostInvariant()
+{
+    AggregateDeclaration *ad = isThis();
+    return (ad &&
+	    ad->inv &&
+	    //ad->isClassDeclaration() &&
+	    global.params.useInvariants &&
+	    (protection == PROTpublic || protection == PROTexport) &&
+	    !naked);
+}
+
+/**********************************
+ * Generate a FuncDeclaration for a runtime library function.
+ */
+
+//
+// LDC: Adjusted to give argument info to the runtime function decl.
+//
+
+FuncDeclaration *FuncDeclaration::genCfunc(Arguments *args, Type *treturn, const char *name)
+{
+    return genCfunc(args, treturn, Lexer::idPool(name));
+}
+
+FuncDeclaration *FuncDeclaration::genCfunc(Arguments *args, Type *treturn, Identifier *id)
+{
+    FuncDeclaration *fd;
+    TypeFunction *tf;
+    Dsymbol *s;
+    static DsymbolTable *st = NULL;
+
+    //printf("genCfunc(name = '%s')\n", id->toChars());
+    //printf("treturn\n\t"); treturn->print();
+
+    // See if already in table
+    if (!st)
+	st = new DsymbolTable();
+    s = st->lookup(id);
+    if (s)
+    {
+	fd = s->isFuncDeclaration();
+	assert(fd);
+	assert(fd->type->nextOf()->equals(treturn));
+    }
+    else
+    {
+	tf = new TypeFunction(args, treturn, 0, LINKc);
+	fd = new FuncDeclaration(0, 0, id, STCstatic, tf);
+	fd->protection = PROTpublic;
+	fd->linkage = LINKc;
+
+	st->insert(fd);
+    }
+    return fd;
+}
+
+const char *FuncDeclaration::kind()
+{
+    return "function";
+}
+
+/*******************************
+ * Look at all the variables in this function that are referenced
+ * by nested functions, and determine if a closure needs to be
+ * created for them.
+ */
+
+#if DMDV2
+int FuncDeclaration::needsClosure()
+{
+    /* Need a closure for all the closureVars[] if any of the
+     * closureVars[] are accessed by a
+     * function that escapes the scope of this function.
+     * We take the conservative approach and decide that any function that:
+     * 1) is a virtual function
+     * 2) has its address taken
+     * 3) has a parent that escapes
+     *
+     * Note that since a non-virtual function can be called by
+     * a virtual one, if that non-virtual function accesses a closure
+     * var, the closure still has to be taken. Hence, we check for isThis()
+     * instead of isVirtual(). (thanks to David Friedman)
+     */
+
+    //printf("FuncDeclaration::needsClosure() %s\n", toChars());
+    for (int i = 0; i < closureVars.dim; i++)
+    {	VarDeclaration *v = (VarDeclaration *)closureVars.data[i];
+	assert(v->isVarDeclaration());
+	//printf("\tv = %s\n", v->toChars());
+
+	for (int j = 0; j < v->nestedrefs.dim; j++)
+	{   FuncDeclaration *f = (FuncDeclaration *)v->nestedrefs.data[j];
+	    assert(f != this);
+
+	    //printf("\t\tf = %s, %d, %d\n", f->toChars(), f->isVirtual(), f->tookAddressOf);
+	    if (f->isThis() || f->tookAddressOf)
+		goto Lyes;	// assume f escapes this function's scope
+
+	    // Look to see if any parents of f that are below this escape
+	    for (Dsymbol *s = f->parent; s && s != this; s = s->parent)
+	    {
+		f = s->isFuncDeclaration();
+		if (f && (f->isThis() || f->tookAddressOf))
+		    goto Lyes;
+	    }
+	}
+    }
+    return 0;
+
+Lyes:
+    //printf("\tneeds closure\n");
+    return 1;
+}
+#endif
+
+/****************************** FuncAliasDeclaration ************************/
+
+// Used as a way to import a set of functions from another scope into this one.
+
+FuncAliasDeclaration::FuncAliasDeclaration(FuncDeclaration *funcalias)
+    : FuncDeclaration(funcalias->loc, funcalias->endloc, funcalias->ident,
+	(enum STC)funcalias->storage_class, funcalias->type)
+{
+    assert(funcalias != this);
+    this->funcalias = funcalias;
+    importprot = PROTundefined;
+}
+
+const char *FuncAliasDeclaration::kind()
+{
+    return "function alias";
+}
+
+
+/****************************** FuncLiteralDeclaration ************************/
+
+FuncLiteralDeclaration::FuncLiteralDeclaration(Loc loc, Loc endloc, Type *type,
+	enum TOK tok, ForeachStatement *fes)
+    : FuncDeclaration(loc, endloc, NULL, STCundefined, type)
+{
+    const char *id;
+
+    if (fes)
+	id = "__foreachbody";
+    else if (tok == TOKdelegate)
+	id = "__dgliteral";
+    else
+	id = "__funcliteral";
+    this->ident = Identifier::generateId(id);
+    this->tok = tok;
+    this->fes = fes;
+    //printf("FuncLiteralDeclaration() id = '%s', type = '%s'\n", this->ident->toChars(), type->toChars());
+}
+
+Dsymbol *FuncLiteralDeclaration::syntaxCopy(Dsymbol *s)
+{
+    FuncLiteralDeclaration *f;
+
+    //printf("FuncLiteralDeclaration::syntaxCopy('%s')\n", toChars());
+    if (s)
+	f = (FuncLiteralDeclaration *)s;
+    else
+	f = new FuncLiteralDeclaration(loc, endloc, type->syntaxCopy(), tok, fes);
+    FuncDeclaration::syntaxCopy(f);
+    return f;
+}
+
+int FuncLiteralDeclaration::isNested()
+{
+    //printf("FuncLiteralDeclaration::isNested() '%s'\n", toChars());
+    return (tok == TOKdelegate);
+}
+
+int FuncLiteralDeclaration::isVirtual()
+{
+    return FALSE;
+}
+
+const char *FuncLiteralDeclaration::kind()
+{
+    // GCC requires the (char*) casts
+    return (tok == TOKdelegate) ? (char*)"delegate" : (char*)"function";
+}
+
+void FuncLiteralDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    static Identifier *idfunc;
+    static Identifier *iddel;
+
+    if (!idfunc)
+	idfunc = new Identifier("function", 0);
+    if (!iddel)
+	iddel = new Identifier("delegate", 0);
+
+    type->toCBuffer(buf, ((tok == TOKdelegate) ? iddel : idfunc), hgs);
+    bodyToCBuffer(buf, hgs);
+}
+
+
+/********************************* CtorDeclaration ****************************/
+
+CtorDeclaration::CtorDeclaration(Loc loc, Loc endloc, Arguments *arguments, int varargs)
+    : FuncDeclaration(loc, endloc, Id::ctor, STCundefined, NULL)
+{
+    this->arguments = arguments;
+    this->varargs = varargs;
+    //printf("CtorDeclaration(loc = %s) %s\n", loc.toChars(), toChars());
+}
+
+Dsymbol *CtorDeclaration::syntaxCopy(Dsymbol *s)
+{
+    CtorDeclaration *f;
+
+    f = new CtorDeclaration(loc, endloc, NULL, varargs);
+
+    f->outId = outId;
+    f->frequire = frequire ? frequire->syntaxCopy() : NULL;
+    f->fensure  = fensure  ? fensure->syntaxCopy()  : NULL;
+    f->fbody    = fbody    ? fbody->syntaxCopy()    : NULL;
+    assert(!fthrows); // deprecated
+
+    f->arguments = Argument::arraySyntaxCopy(arguments);
+    return f;
+}
+
+
+void CtorDeclaration::semantic(Scope *sc)
+{
+    ClassDeclaration *cd;
+    Type *tret;
+
+    //printf("CtorDeclaration::semantic()\n");
+    if (type)
+	return;
+
+    sc = sc->push();
+    sc->stc &= ~STCstatic;		// not a static constructor
+
+    parent = sc->parent;
+    Dsymbol *parent = toParent();
+    cd = parent->isClassDeclaration();
+    if (!cd)
+    {
+	error("constructors are only for class definitions");
+	fatal();
+	tret = Type::tvoid;
+    }
+    else
+	tret = cd->type; //->referenceTo();
+    type = new TypeFunction(arguments, tret, varargs, LINKd);
+#if STRUCTTHISREF
+    if (ad && ad->isStructDeclaration())
+	((TypeFunction *)type)->isref = 1;
+#endif
+    if (!originalType)
+	originalType = type;
+
+    sc->flags |= SCOPEctor;
+    type = type->semantic(loc, sc);
+    sc->flags &= ~SCOPEctor;
+
+    // Append:
+    //	return this;
+    // to the function body
+    if (fbody)
+    {
+	Expression *e = new ThisExp(loc);
+	Statement *s = new ReturnStatement(loc, e);
+	fbody = new CompoundStatement(loc, fbody, s);
+    }
+
+    FuncDeclaration::semantic(sc);
+
+    sc->pop();
+
+    // See if it's the default constructor
+    if (cd && varargs == 0 && Argument::dim(arguments) == 0)
+	cd->defaultCtor = this;
+}
+
+const char *CtorDeclaration::kind()
+{
+    return "constructor";
+}
+
+char *CtorDeclaration::toChars()
+{
+    return (char *)"this";
+}
+
+int CtorDeclaration::isVirtual()
+{
+    return FALSE;
+}
+
+int CtorDeclaration::addPreInvariant()
+{
+    return FALSE;
+}
+
+int CtorDeclaration::addPostInvariant()
+{
+    return (isThis() && vthis && global.params.useInvariants);
+}
+
+
+void CtorDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    buf->writestring("this");
+    Argument::argsToCBuffer(buf, hgs, arguments, varargs);
+    bodyToCBuffer(buf, hgs);
+}
+
+/********************************* PostBlitDeclaration ****************************/
+
+#if DMDV2
+PostBlitDeclaration::PostBlitDeclaration(Loc loc, Loc endloc)
+    : FuncDeclaration(loc, endloc, Id::_postblit, STCundefined, NULL)
+{
+}
+
+PostBlitDeclaration::PostBlitDeclaration(Loc loc, Loc endloc, Identifier *id)
+    : FuncDeclaration(loc, endloc, id, STCundefined, NULL)
+{
+}
+
+Dsymbol *PostBlitDeclaration::syntaxCopy(Dsymbol *s)
+{
+    assert(!s);
+    PostBlitDeclaration *dd = new PostBlitDeclaration(loc, endloc, ident);
+    return FuncDeclaration::syntaxCopy(dd);
+}
+
+
+void PostBlitDeclaration::semantic(Scope *sc)
+{
+    //printf("PostBlitDeclaration::semantic() %s\n", toChars());
+    //printf("ident: %s, %s, %p, %p\n", ident->toChars(), Id::dtor->toChars(), ident, Id::dtor);
+    parent = sc->parent;
+    Dsymbol *parent = toParent();
+    StructDeclaration *ad = parent->isStructDeclaration();
+    if (!ad)
+    {
+	error("post blits are only for struct/union definitions, not %s %s", parent->kind(), parent->toChars());
+    }
+    else if (ident == Id::_postblit)
+	ad->postblits.push(this);
+    type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd);
+
+    sc = sc->push();
+    sc->stc &= ~STCstatic;		// not static
+    sc->linkage = LINKd;
+
+    FuncDeclaration::semantic(sc);
+
+    sc->pop();
+}
+
+int PostBlitDeclaration::overloadInsert(Dsymbol *s)
+{
+    return FALSE;	// cannot overload postblits
+}
+
+int PostBlitDeclaration::addPreInvariant()
+{
+    return FALSE;
+}
+
+int PostBlitDeclaration::addPostInvariant()
+{
+    return (isThis() && vthis && global.params.useInvariants);
+}
+
+int PostBlitDeclaration::isVirtual()
+{
+    return FALSE;
+}
+
+void PostBlitDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    if (hgs->hdrgen)
+	return;
+    buf->writestring("=this()");
+    bodyToCBuffer(buf, hgs);
+}
+#endif
+
+/********************************* DtorDeclaration ****************************/
+
+DtorDeclaration::DtorDeclaration(Loc loc, Loc endloc)
+    : FuncDeclaration(loc, endloc, Id::dtor, STCundefined, NULL)
+{
+}
+
+DtorDeclaration::DtorDeclaration(Loc loc, Loc endloc, Identifier *id)
+    : FuncDeclaration(loc, endloc, id, STCundefined, NULL)
+{
+}
+
+Dsymbol *DtorDeclaration::syntaxCopy(Dsymbol *s)
+{
+    assert(!s);
+    DtorDeclaration *dd = new DtorDeclaration(loc, endloc, ident);
+    return FuncDeclaration::syntaxCopy(dd);
+}
+
+
+void DtorDeclaration::semantic(Scope *sc)
+{
+    //printf("DtorDeclaration::semantic() %s\n", toChars());
+    //printf("ident: %s, %s, %p, %p\n", ident->toChars(), Id::dtor->toChars(), ident, Id::dtor);
+    parent = sc->parent;
+    Dsymbol *parent = toParent();
+    ClassDeclaration *cd = parent->isClassDeclaration();
+    if (!cd)
+    {
+	error("destructors are only for class/struct/union definitions, not %s %s", parent->kind(), parent->toChars());
+	fatal();
+    }
+    else
+	cd->dtors.push(this);
+    type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd);
+
+    sc = sc->push();
+    sc->stc &= ~STCstatic;		// not a static destructor
+    sc->linkage = LINKd;
+
+    FuncDeclaration::semantic(sc);
+
+    sc->pop();
+}
+
+int DtorDeclaration::overloadInsert(Dsymbol *s)
+{
+    return FALSE;	// cannot overload destructors
+}
+
+int DtorDeclaration::addPreInvariant()
+{
+    return (isThis() && vthis && global.params.useInvariants);
+}
+
+int DtorDeclaration::addPostInvariant()
+{
+    return FALSE;
+}
+
+const char *DtorDeclaration::kind()
+{	
+    return "destructor";
+}
+
+char *DtorDeclaration::toChars()
+{
+    return (char *)"~this";
+}
+
+int DtorDeclaration::isVirtual()
+{
+    /* This should be FALSE so that dtor's don't get put into the vtbl[],
+     * but doing so will require recompiling everything.
+     */
+#if BREAKABI
+    return FALSE;
+#else
+    return FuncDeclaration::isVirtual();
+#endif
+}
+
+void DtorDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    if (hgs->hdrgen)
+	return;
+    buf->writestring("~this()");
+    bodyToCBuffer(buf, hgs);
+}
+
+/********************************* StaticCtorDeclaration ****************************/
+
+StaticCtorDeclaration::StaticCtorDeclaration(Loc loc, Loc endloc)
+    : FuncDeclaration(loc, endloc,
+      Identifier::generateId("_staticCtor"), STCstatic, NULL)
+{
+}
+
+Dsymbol *StaticCtorDeclaration::syntaxCopy(Dsymbol *s)
+{
+    StaticCtorDeclaration *scd;
+
+    assert(!s);
+    scd = new StaticCtorDeclaration(loc, endloc);
+    return FuncDeclaration::syntaxCopy(scd);
+}
+
+
+void StaticCtorDeclaration::semantic(Scope *sc)
+{
+    //printf("StaticCtorDeclaration::semantic()\n");
+
+    type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd);
+
+    /* If the static ctor appears within a template instantiation,
+     * it could get called multiple times by the module constructors
+     * for different modules. Thus, protect it with a gate.
+     */
+    if (inTemplateInstance())
+    {
+	/* Add this prefix to the function:
+	 *	static int gate;
+	 *	if (++gate != 1) return;
+	 * Note that this is not thread safe; should not have threads
+	 * during static construction.
+	 */
+	Identifier *id = Lexer::idPool("__gate");
+	VarDeclaration *v = new VarDeclaration(0, Type::tint32, id, NULL);
+	v->storage_class = STCstatic;
+	Statements *sa = new Statements();
+	Statement *s = new DeclarationStatement(0, v);
+	sa->push(s);
+	Expression *e = new IdentifierExp(0, id);
+	e = new AddAssignExp(0, e, new IntegerExp(1));
+	e = new EqualExp(TOKnotequal, 0, e, new IntegerExp(1));
+	s = new IfStatement(0, NULL, e, new ReturnStatement(0, NULL), NULL);
+	sa->push(s);
+	if (fbody)
+	    sa->push(fbody);
+	fbody = new CompoundStatement(0, sa);
+    }
+
+    FuncDeclaration::semantic(sc);
+
+    // We're going to need ModuleInfo
+    Module *m = getModule();
+    if (!m)
+	m = sc->module;
+    if (m)
+    {	m->needmoduleinfo = 1;
+#ifdef IN_GCC
+	m->strictlyneedmoduleinfo = 1;
+#endif
+    }
+}
+
+AggregateDeclaration *StaticCtorDeclaration::isThis()
+{
+    return NULL;
+}
+
+int StaticCtorDeclaration::isStaticConstructor()
+{
+    return TRUE;
+}
+
+int StaticCtorDeclaration::isVirtual()
+{
+    return FALSE;
+}
+
+int StaticCtorDeclaration::addPreInvariant()
+{
+    return FALSE;
+}
+
+int StaticCtorDeclaration::addPostInvariant()
+{
+    return FALSE;
+}
+
+void StaticCtorDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    if (hgs->hdrgen)
+    {	buf->writestring("static this();\n");
+	return;
+    }
+    buf->writestring("static this()");
+    bodyToCBuffer(buf, hgs);
+}
+
+/********************************* StaticDtorDeclaration ****************************/
+
+StaticDtorDeclaration::StaticDtorDeclaration(Loc loc, Loc endloc)
+    : FuncDeclaration(loc, endloc,
+      Identifier::generateId("_staticDtor"), STCstatic, NULL)
+{
+    vgate = NULL;
+}
+
+Dsymbol *StaticDtorDeclaration::syntaxCopy(Dsymbol *s)
+{
+    StaticDtorDeclaration *sdd;
+
+    assert(!s);
+    sdd = new StaticDtorDeclaration(loc, endloc);
+    return FuncDeclaration::syntaxCopy(sdd);
+}
+
+
+void StaticDtorDeclaration::semantic(Scope *sc)
+{
+    ClassDeclaration *cd;
+    Type *tret;
+
+    cd = sc->scopesym->isClassDeclaration();
+    if (!cd)
+    {
+    }
+    type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd);
+
+    /* If the static ctor appears within a template instantiation,
+     * it could get called multiple times by the module constructors
+     * for different modules. Thus, protect it with a gate.
+     */
+    if (inTemplateInstance())
+    {
+	/* Add this prefix to the function:
+	 *	static int gate;
+	 *	if (--gate != 0) return;
+	 * Increment gate during constructor execution.
+	 * Note that this is not thread safe; should not have threads
+	 * during static destruction.
+	 */
+	Identifier *id = Lexer::idPool("__gate");
+	VarDeclaration *v = new VarDeclaration(0, Type::tint32, id, NULL);
+	v->storage_class = STCstatic;
+	Statements *sa = new Statements();
+	Statement *s = new DeclarationStatement(0, v);
+	sa->push(s);
+	Expression *e = new IdentifierExp(0, id);
+	e = new AddAssignExp(0, e, new IntegerExp((uint64_t)-1));
+	e = new EqualExp(TOKnotequal, 0, e, new IntegerExp(0));
+	s = new IfStatement(0, NULL, e, new ReturnStatement(0, NULL), NULL);
+	sa->push(s);
+	if (fbody)
+	    sa->push(fbody);
+	fbody = new CompoundStatement(0, sa);
+	vgate = v;
+    }
+
+    FuncDeclaration::semantic(sc);
+
+    // We're going to need ModuleInfo
+    Module *m = getModule();
+    if (!m)
+	m = sc->module;
+    if (m)
+    {	m->needmoduleinfo = 1;
+#ifdef IN_GCC
+	m->strictlyneedmoduleinfo = 1;
+#endif
+    }
+}
+
+AggregateDeclaration *StaticDtorDeclaration::isThis()
+{
+    return NULL;
+}
+
+int StaticDtorDeclaration::isStaticDestructor()
+{
+    return TRUE;
+}
+
+int StaticDtorDeclaration::isVirtual()
+{
+    return FALSE;
+}
+
+int StaticDtorDeclaration::addPreInvariant()
+{
+    return FALSE;
+}
+
+int StaticDtorDeclaration::addPostInvariant()
+{
+    return FALSE;
+}
+
+void StaticDtorDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    if (hgs->hdrgen)
+	return;
+    buf->writestring("static ~this()");
+    bodyToCBuffer(buf, hgs);
+}
+
+/********************************* InvariantDeclaration ****************************/
+
+InvariantDeclaration::InvariantDeclaration(Loc loc, Loc endloc)
+    : FuncDeclaration(loc, endloc, Id::classInvariant, STCundefined, NULL)
+{
+}
+
+Dsymbol *InvariantDeclaration::syntaxCopy(Dsymbol *s)
+{
+    InvariantDeclaration *id;
+
+    assert(!s);
+    id = new InvariantDeclaration(loc, endloc);
+    FuncDeclaration::syntaxCopy(id);
+    return id;
+}
+
+
+void InvariantDeclaration::semantic(Scope *sc)
+{
+    AggregateDeclaration *ad;
+    Type *tret;
+
+    parent = sc->parent;
+    Dsymbol *parent = toParent();
+    ad = parent->isAggregateDeclaration();
+    if (!ad)
+    {
+	error("invariants are only for struct/union/class definitions");
+	return;
+    }
+    else if (ad->inv && ad->inv != this)
+    {
+	error("more than one invariant for %s", ad->toChars());
+    }
+    ad->inv = this;
+    type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd);
+
+    sc = sc->push();
+    sc->stc &= ~STCstatic;		// not a static invariant
+    sc->incontract++;
+    sc->linkage = LINKd;
+
+    FuncDeclaration::semantic(sc);
+
+    sc->pop();
+}
+
+int InvariantDeclaration::isVirtual()
+{
+    return FALSE;
+}
+
+int InvariantDeclaration::addPreInvariant()
+{
+    return FALSE;
+}
+
+int InvariantDeclaration::addPostInvariant()
+{
+    return FALSE;
+}
+
+void InvariantDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    if (hgs->hdrgen)
+	return;
+    buf->writestring("invariant");
+    bodyToCBuffer(buf, hgs);
+}
+
+
+/********************************* UnitTestDeclaration ****************************/
+
+/*******************************
+ * Generate unique unittest function Id so we can have multiple
+ * instances per module.
+ */
+
+static Identifier *unitTestId()
+{
+    return Lexer::uniqueId("__unittest");
+}
+
+UnitTestDeclaration::UnitTestDeclaration(Loc loc, Loc endloc)
+    : FuncDeclaration(loc, endloc, unitTestId(), STCundefined, NULL)
+{
+}
+
+Dsymbol *UnitTestDeclaration::syntaxCopy(Dsymbol *s)
+{
+    UnitTestDeclaration *utd;
+
+    assert(!s);
+    utd = new UnitTestDeclaration(loc, endloc);
+    return FuncDeclaration::syntaxCopy(utd);
+}
+
+
+void UnitTestDeclaration::semantic(Scope *sc)
+{
+    if (global.params.useUnitTests)
+    {
+	type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd);
+	Scope *sc2 = sc->push();
+	sc2->linkage = LINKd;
+	FuncDeclaration::semantic(sc2);
+	sc2->pop();
+    }
+
+#if 0
+    // We're going to need ModuleInfo even if the unit tests are not
+    // compiled in, because other modules may import this module and refer
+    // to this ModuleInfo.
+    // (This doesn't make sense to me?)
+    Module *m = getModule();
+    if (!m)
+	m = sc->module;
+    if (m)
+    {
+	//printf("module3 %s needs moduleinfo\n", m->toChars());
+	m->needmoduleinfo = 1;
+    }
+#endif
+}
+
+AggregateDeclaration *UnitTestDeclaration::isThis()
+{
+    return NULL;
+}
+
+int UnitTestDeclaration::isVirtual()
+{
+    return FALSE;
+}
+
+int UnitTestDeclaration::addPreInvariant()
+{
+    return FALSE;
+}
+
+int UnitTestDeclaration::addPostInvariant()
+{
+    return FALSE;
+}
+
+void UnitTestDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    if (hgs->hdrgen)
+	return;
+    buf->writestring("unittest");
+    bodyToCBuffer(buf, hgs);
+}
+
+/********************************* NewDeclaration ****************************/
+
+NewDeclaration::NewDeclaration(Loc loc, Loc endloc, Arguments *arguments, int varargs)
+    : FuncDeclaration(loc, endloc, Id::classNew, STCstatic, NULL)
+{
+    this->arguments = arguments;
+    this->varargs = varargs;
+}
+
+Dsymbol *NewDeclaration::syntaxCopy(Dsymbol *s)
+{
+    NewDeclaration *f;
+
+    f = new NewDeclaration(loc, endloc, NULL, varargs);
+
+    FuncDeclaration::syntaxCopy(f);
+
+    f->arguments = Argument::arraySyntaxCopy(arguments);
+
+    return f;
+}
+
+
+void NewDeclaration::semantic(Scope *sc)
+{
+    ClassDeclaration *cd;
+    Type *tret;
+
+    //printf("NewDeclaration::semantic()\n");
+
+    parent = sc->parent;
+    Dsymbol *parent = toParent();
+    cd = parent->isClassDeclaration();
+    if (!cd && !parent->isStructDeclaration())
+    {
+	error("new allocators only are for class or struct definitions");
+    }
+    tret = Type::tvoid->pointerTo();
+    type = new TypeFunction(arguments, tret, varargs, LINKd);
+
+    type = type->semantic(loc, sc);
+    assert(type->ty == Tfunction);
+
+    // Check that there is at least one argument of type size_t
+    TypeFunction *tf = (TypeFunction *)type;
+    if (Argument::dim(tf->parameters) < 1)
+    {
+	error("at least one argument of type size_t expected");
+    }
+    else
+    {
+	Argument *a = Argument::getNth(tf->parameters, 0);
+	if (!a->type->equals(Type::tsize_t))
+	    error("first argument must be type size_t, not %s", a->type->toChars());
+    }
+
+    FuncDeclaration::semantic(sc);
+}
+
+const char *NewDeclaration::kind()
+{
+    return "allocator";
+}
+
+int NewDeclaration::isVirtual()
+{
+    return FALSE;
+}
+
+int NewDeclaration::addPreInvariant()
+{
+    return FALSE;
+}
+
+int NewDeclaration::addPostInvariant()
+{
+    return FALSE;
+}
+
+void NewDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    buf->writestring("new");
+    Argument::argsToCBuffer(buf, hgs, arguments, varargs);
+    bodyToCBuffer(buf, hgs);
+}
+
+
+/********************************* DeleteDeclaration ****************************/
+
+DeleteDeclaration::DeleteDeclaration(Loc loc, Loc endloc, Arguments *arguments)
+    : FuncDeclaration(loc, endloc, Id::classDelete, STCstatic, NULL)
+{
+    this->arguments = arguments;
+}
+
+Dsymbol *DeleteDeclaration::syntaxCopy(Dsymbol *s)
+{
+    DeleteDeclaration *f;
+
+    f = new DeleteDeclaration(loc, endloc, NULL);
+
+    FuncDeclaration::syntaxCopy(f);
+
+    f->arguments = Argument::arraySyntaxCopy(arguments);
+
+    return f;
+}
+
+
+void DeleteDeclaration::semantic(Scope *sc)
+{
+    ClassDeclaration *cd;
+
+    //printf("DeleteDeclaration::semantic()\n");
+
+    parent = sc->parent;
+    Dsymbol *parent = toParent();
+    cd = parent->isClassDeclaration();
+    if (!cd && !parent->isStructDeclaration())
+    {
+	error("new allocators only are for class or struct definitions");
+    }
+    type = new TypeFunction(arguments, Type::tvoid, 0, LINKd);
+
+    type = type->semantic(loc, sc);
+    assert(type->ty == Tfunction);
+
+    // Check that there is only one argument of type void*
+    TypeFunction *tf = (TypeFunction *)type;
+    if (Argument::dim(tf->parameters) != 1)
+    {
+	error("one argument of type void* expected");
+    }
+    else
+    {
+	Argument *a = Argument::getNth(tf->parameters, 0);
+	if (!a->type->equals(Type::tvoid->pointerTo()))
+	    error("one argument of type void* expected, not %s", a->type->toChars());
+    }
+
+    FuncDeclaration::semantic(sc);
+}
+
+const char *DeleteDeclaration::kind()
+{
+    return "deallocator";
+}
+
+int DeleteDeclaration::isDelete()
+{
+    return TRUE;
+}
+
+int DeleteDeclaration::isVirtual()
+{
+    return FALSE;
+}
+
+int DeleteDeclaration::addPreInvariant()
+{
+    return FALSE;
+}
+
+int DeleteDeclaration::addPostInvariant()
+{
+    return FALSE;
+}
+
+void DeleteDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    buf->writestring("delete");
+    Argument::argsToCBuffer(buf, hgs, arguments, 0);
+    bodyToCBuffer(buf, hgs);
+}
+
+
+
+
--- a/dmd/idgen.c	Fri Nov 06 21:51:41 2009 +0100
+++ b/dmd/idgen.c	Fri Nov 06 23:58:01 2009 +0100
@@ -38,6 +38,8 @@
     { "dtor", "_dtor" },
     { "classInvariant", "__invariant" },
     { "unitTest", "_unitTest" },
+    { "require", "__require" },
+    { "ensure", "__ensure" },
     { "init" },
     { "size" },
     { "__sizeof", "sizeof" },
@@ -207,6 +209,10 @@
     { "aaKeys", "_aaKeys" },
     { "aaValues", "_aaValues" },
     { "aaRehash", "_aaRehash" },
+    { "monitorenter", "_d_monitorenter" },
+    { "monitorexit", "_d_monitorexit" },
+    { "criticalenter", "_d_criticalenter" },
+    { "criticalexit", "_d_criticalexit" },
 
     // For pragma's
     { "GNU_asm" },
--- a/dmd/import.c	Fri Nov 06 21:51:41 2009 +0100
+++ b/dmd/import.c	Fri Nov 06 23:58:01 2009 +0100
@@ -1,6 +1,6 @@
 
 // Compiler implementation of the D programming language
-// Copyright (c) 1999-2006 by Digital Mars
+// Copyright (c) 1999-2009 by Digital Mars
 // All Rights Reserved
 // written by Walter Bright
 // http://www.digitalmars.com
@@ -21,6 +21,7 @@
 #include "mtype.h"
 #include "declaration.h"
 #include "id.h"
+#include "attrib.h"
 
 /********************************* Import ****************************/
 
@@ -28,6 +29,7 @@
 	int isstatic)
     : Dsymbol(id)
 {
+    assert(id);
     this->loc = loc;
     this->packages = packages;
     this->id = id;
@@ -84,21 +86,22 @@
 
 void Import::load(Scope *sc)
 {
-    DsymbolTable *dst;
-    Dsymbol *s;
-
     //printf("Import::load('%s')\n", toChars());
 
     // See if existing module
-    dst = Package::resolve(packages, NULL, &pkg);
+    DsymbolTable *dst = Package::resolve(packages, NULL, &pkg);
 
-    s = dst->lookup(id);
+    Dsymbol *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)
@@ -116,31 +119,54 @@
     //printf("-Import::load('%s'), pkg = %p\n", toChars(), pkg);
 }
 
-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;
+}
+
+void Import::importAll(Scope *sc)
+{
+    if (!mod)
+    {
+       load(sc);
+       mod->importAll(0);
+
+       if (!isstatic && !aliasId && !names.dim)
+       {
+           /* Default to private importing
+            */
+           enum PROT prot = sc->protection;
+           if (!sc->explicitProtection)
+               prot = PROTprivate;
+           sc->scopesym->importScope(mod, prot);
+       }
+    }
 }
 
 void Import::semantic(Scope *sc)
 {
     //printf("Import::semantic('%s')\n", toChars());
 
-    load(sc);
+    // Load if not already done so
+    if (!mod)
+    {	load(sc);
+	mod->importAll(0);
+    }
 
     if (mod)
     {
@@ -158,8 +184,6 @@
 	//printf("%s imports %s\n", sc->module->toChars(), mod->toChars());
 	sc->module->aimports.push(mod);
 
-	mod->semantic();
-
 	/* Default to private importing
 	 */
 	protection = sc->protection;
@@ -171,6 +195,8 @@
 	    sc->scopesym->importScope(mod, protection);
 	}
 
+	mod->semantic();
+
 	if (mod->needmoduleinfo)
 	    sc->module->needmoduleinfo = 1;
 
@@ -189,67 +215,76 @@
     }
     //printf("-Import::semantic('%s'), pkg = %p\n", toChars(), pkg);
 
-
-    if (global.params.moduleDeps != NULL) {
-	char fnameBuf[262];		// MAX_PATH+2
-
-	OutBuffer *const ob = global.params.moduleDeps;
-	ob->printf("%s (%s) : ",
-	    sc->module->toPrettyChars(),
-	    escapePath(sc->module->srcfile->toChars(), fnameBuf, sizeof(fnameBuf) / sizeof(*fnameBuf))
-	);
+    if (global.params.moduleDeps != NULL)
+    {
+	/* The grammar of the file is:
+	 *	ImportDeclaration
+	 *	    ::= BasicImportDeclaration [ " : " ImportBindList ] [ " -> "
+	 *	ModuleAliasIdentifier ] "\n"
+	 *
+	 *	BasicImportDeclaration
+	 *	    ::= ModuleFullyQualifiedName " (" FilePath ") : " Protection
+	 *		" [ " static" ] : " ModuleFullyQualifiedName " (" FilePath ")"
+	 *
+	 *	FilePath
+	 *	    - any string with '(', ')' and '\' escaped with the '\' character
+	 */
 
-	char* protStr = "";
-	switch (sc->protection) {
-	    case PROTpublic: protStr = "public"; break;
-	    case PROTprivate: protStr = "private"; break;
-	    case PROTpackage: protStr = "package"; break;
-	    default: break;
-	}
-	ob->writestring(protStr);
-	if (isstatic) {
-	    ob->writestring(" static");
-	}
-	ob->writestring(" : ");
+	OutBuffer *ob = global.params.moduleDeps;
+
+	ob->writestring(sc->module->toPrettyChars());
+	ob->writestring(" (");
+	escapePath(ob, sc->module->srcfile->toChars());
+	ob->writestring(") : ");
 
-	if (this->packages) {
-	    for (size_t i = 0; i < this->packages->dim; i++) {
-		Identifier *pid = (Identifier *)this->packages->data[i];
+	ProtDeclaration::protectionToCBuffer(ob, sc->protection);
+	if (isstatic)
+	    StorageClassDeclaration::stcToCBuffer(ob, STCstatic);
+	ob->writestring(": ");
+
+	if (packages)
+	{
+	    for (size_t i = 0; i < packages->dim; i++)
+	    {
+		Identifier *pid = (Identifier *)packages->data[i];
 		ob->printf("%s.", pid->toChars());
 	    }
 	}
 
-	ob->printf("%s (%s)",
-	    this->id->toChars(),
-	    mod ? escapePath(mod->srcfile->toChars(), fnameBuf, sizeof(fnameBuf) / sizeof(*fnameBuf)) : "???"
-	);
+	ob->writestring(id->toChars());
+	ob->writestring(" (");
+	if (mod)
+	    escapePath(ob, mod->srcfile->toChars());
+	else
+	    ob->writestring("???");
+	ob->writebyte(')');
+
+	for (size_t i = 0; i < names.dim; i++)
+	{
+	    if (i == 0)
+		ob->writebyte(':');
+	    else
+		ob->writebyte(',');
 
-	if (aliasId) {
-	    ob->printf(" -> %s", aliasId->toChars());
-	} else {
-	    if (names.dim > 0) {
-		ob->writestring(" : ");
-		for (size_t i = 0; i < names.dim; i++)
-		{
-		    if (i > 0) {
-			ob->writebyte(',');
-		    }
+	    Identifier *name = (Identifier *)names.data[i];
+	    Identifier *alias = (Identifier *)aliases.data[i];
 
-		    Identifier *name = (Identifier *)names.data[i];
-		    Identifier *alias = (Identifier *)aliases.data[i];
+	    if (!alias)
+	    {
+		ob->printf("%s", name->toChars());
+		alias = name;
+	    }
+	    else
+		ob->printf("%s=%s", alias->toChars(), name->toChars());
+	}
 
-		    if (!alias) {
-			ob->printf("%s", name->toChars());
-			alias = name;
-		    } else {
-			ob->printf("%s=%s", alias->toChars(), name->toChars());
-		    }
-		}
-	    }
-	}
+	if (aliasId)
+		ob->printf(" -> %s", aliasId->toChars());
 
 	ob->writenl();
     }
+
+    //printf("-Import::semantic('%s'), pkg = %p\n", toChars(), pkg);
 }
 
 void Import::semantic2(Scope *sc)
--- a/dmd/import.h	Fri Nov 06 21:51:41 2009 +0100
+++ b/dmd/import.h	Fri Nov 06 23:58:01 2009 +0100
@@ -1,67 +1,68 @@
-
-// Compiler implementation of the D programming language
-// Copyright (c) 1999-2007 by Digital Mars
-// All Rights Reserved
-// written by Walter Bright
-// http://www.digitalmars.com
-// License for redistribution is by either the Artistic License
-// in artistic.txt, or the GNU General Public License in gnu.txt.
-// See the included readme.txt for details.
-
-#ifndef DMD_IMPORT_H
-#define DMD_IMPORT_H
-
-#ifdef __DMC__
-#pragma once
-#endif /* __DMC__ */
-
-#include "dsymbol.h"
-
-
-struct Identifier;
-struct Scope;
-struct OutBuffer;
-struct Module;
-struct Package;
-struct AliasDeclaration;
-#ifdef _DH
-struct HdrGenState;
-#endif
-
-struct Import : Dsymbol
-{
-    Array *packages;		// array of Identifier's representing packages
-    Identifier *id;		// module Identifier
-    Identifier *aliasId;
-    int isstatic;		// !=0 if static import
-    enum PROT protection;
-
-    // Pairs of alias=name to bind into current namespace
-    Array names;
-    Array aliases;
-
-    Array aliasdecls;		// AliasDeclarations for names/aliases
-
-    Module *mod;
-    Package *pkg;		// leftmost package/module
-
-    Import(Loc loc, Array *packages, Identifier *id, Identifier *aliasId,
-	int isstatic);
-    void addAlias(Identifier *name, Identifier *alias);
-
-    const char *kind();
-    enum PROT prot();
-    Dsymbol *syntaxCopy(Dsymbol *s);	// copy only syntax trees
-    void load(Scope *sc);
-    void semantic(Scope *sc);
-    void semantic2(Scope *sc);
-    Dsymbol *toAlias();
-    int addMember(Scope *sc, ScopeDsymbol *s, int memnum);
-    Dsymbol *search(Loc loc, Identifier *ident, int flags);
-    int overloadInsert(Dsymbol *s);
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-
-    Import *isImport() { return this; }
-};
-
-#endif /* DMD_IMPORT_H */
+
+// Compiler implementation of the D programming language
+// Copyright (c) 1999-2007 by Digital Mars
+// All Rights Reserved
+// written by Walter Bright
+// http://www.digitalmars.com
+// License for redistribution is by either the Artistic License
+// in artistic.txt, or the GNU General Public License in gnu.txt.
+// See the included readme.txt for details.
+
+#ifndef DMD_IMPORT_H
+#define DMD_IMPORT_H
+
+#ifdef __DMC__
+#pragma once
+#endif /* __DMC__ */
+
+#include "dsymbol.h"
+
+
+struct Identifier;
+struct Scope;
+struct OutBuffer;
+struct Module;
+struct Package;
+struct AliasDeclaration;
+#ifdef _DH
+struct HdrGenState;
+#endif
+
+struct Import : Dsymbol
+{
+    Array *packages;		// array of Identifier's representing packages
+    Identifier *id;		// module Identifier
+    Identifier *aliasId;
+    int isstatic;		// !=0 if static import
+    enum PROT protection;
+
+    // Pairs of alias=name to bind into current namespace
+    Array names;
+    Array aliases;
+
+    Array aliasdecls;		// AliasDeclarations for names/aliases
+
+    Module *mod;
+    Package *pkg;		// leftmost package/module
+
+    Import(Loc loc, Array *packages, Identifier *id, Identifier *aliasId,
+	int isstatic);
+    void addAlias(Identifier *name, Identifier *alias);
+
+    const char *kind();
+    enum PROT prot();
+    Dsymbol *syntaxCopy(Dsymbol *s);	// copy only syntax trees
+    void load(Scope *sc);
+    void importAll(Scope *sc);
+    void semantic(Scope *sc);
+    void semantic2(Scope *sc);
+    Dsymbol *toAlias();
+    int addMember(Scope *sc, ScopeDsymbol *s, int memnum);
+    Dsymbol *search(Loc loc, Identifier *ident, int flags);
+    int overloadInsert(Dsymbol *s);
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+
+    Import *isImport() { return this; }
+};
+
+#endif /* DMD_IMPORT_H */
--- a/dmd/init.c	Fri Nov 06 21:51:41 2009 +0100
+++ b/dmd/init.c	Fri Nov 06 23:58:01 2009 +0100
@@ -396,32 +396,89 @@
 {   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)
+    {
+	if (type == Type::terror)
+	    return new ErrorExp();
+
+	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;
+	for (size_t i = 0, j = 0; i < value.dim; i++, j++)
+	{
+	    if (index.data[i])
+		j = ((Expression *)index.data[i])->toInteger();
+	    if (j >= edim)
+		edim = j + 1;
+	}
+    }
+
     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 = t->next->defaultInit();
+	    elements->data[i] = init;
+	}
+    }
+
+    Expression *e = new ArrayLiteralExp(loc, elements);
     e->type = type;
     return e;
+    }
 
 Lno:
     delete elements;
     error(loc, "array initializers as expressions are not allowed");
-    return NULL;
+    return new ErrorExp();
 }
 
-
 /********************************
  * If possible, convert array initializer to associative array initializer.
  */
@@ -469,7 +526,7 @@
     for (size_t i = 0; i < value.dim; i++)
     {
 	if (index.data[i])
-	    goto Lno;
+	    goto Laa;
     }
     if (value.dim)
     {
@@ -482,9 +539,21 @@
 	}
     }
 
-Lno:
-    error(loc, "cannot infer type from this array initializer");
-    return Type::terror;
+Laa:
+    /* It's possibly an associative array initializer
+     */
+    Initializer *iz = (Initializer *)value.data[0];
+    Expression *indexinit = (Expression *)index.data[0];
+    if (iz && indexinit)
+    {   Type *t = iz->inferType(sc);
+	indexinit = indexinit->semantic(sc);
+	Type *indext = indexinit->type;
+	t = new TypeAArray(t, indext);
+	type = t->semantic(loc, sc);
+    }
+    else
+	error(loc, "cannot infer type from this array initializer");
+    return type;
 }
 
 
@@ -569,14 +638,27 @@
     exp = exp->semantic(sc);
     exp = resolveProperties(sc, exp);
 
-#if DMDV2
     // Give error for overloaded function addresses
     if (exp->op == TOKsymoff)
     {   SymOffExp *se = (SymOffExp *)exp;
-	if (se->hasOverloads && !se->var->isFuncDeclaration()->isUnique())
+	if (
+#if DMDV2
+	    se->hasOverloads &&
+#else
+	    se->var->isFuncDeclaration() &&
+#endif
+	    !se->var->isFuncDeclaration()->isUnique())
 	    exp->error("cannot infer type from overloaded function symbol %s", exp->toChars());
     }
-#endif
+
+    // Give error for overloaded function addresses
+    if (exp->op == TOKdelegate)
+    {   DelegateExp *se = (DelegateExp *)exp;
+	if (
+	    se->func->isFuncDeclaration() &&
+	    !se->func->isFuncDeclaration()->isUnique())
+	    exp->error("cannot infer type from overloaded function symbol %s", exp->toChars());
+    }
 
     Type *t = exp->type;
     if (!t)
--- a/dmd/inline.c	Fri Nov 06 21:51:41 2009 +0100
+++ b/dmd/inline.c	Fri Nov 06 23:58:01 2009 +0100
@@ -1,1487 +1,1535 @@
-
-// Copyright (c) 1999-2008 by Digital Mars
-// All Rights Reserved
-// written by Walter Bright
-// http://www.digitalmars.com
-// License for redistribution is by either the Artistic License
-// in artistic.txt, or the GNU General Public License in gnu.txt.
-// See the included readme.txt for details.
-
-// Routines to perform function inlining
-
-#define LOG 0
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <assert.h>
-
-#include "id.h"
-#include "init.h"
-#include "declaration.h"
-#include "aggregate.h"
-#include "expression.h"
-#include "statement.h"
-#include "mtype.h"
-
-/* ========== Compute cost of inlining =============== */
-
-/* Walk trees to determine if inlining can be done, and if so,
- * if it is too complex to be worth inlining or not.
- */
-
-struct InlineCostState
-{
-    int nested;
-    int hasthis;
-    int hdrscan;    // !=0 if inline scan for 'header' content
-    FuncDeclaration *fd;
-};
-
-const int COST_MAX = 250;
-
-int Statement::inlineCost(InlineCostState *ics)
-{
-    return COST_MAX;		// default is we can't inline it
-}
-
-int ExpStatement::inlineCost(InlineCostState *ics)
-{
-    return exp ? exp->inlineCost(ics) : 0;
-}
-
-int CompoundStatement::inlineCost(InlineCostState *ics)
-{   int cost = 0;
-
-    for (size_t i = 0; i < statements->dim; i++)
-    {	Statement *s = (Statement *) statements->data[i];
-	if (s)
-	{
-	    cost += s->inlineCost(ics);
-	    if (cost >= COST_MAX)
-		break;
-	}
-    }
-    return cost;
-}
-
-int UnrolledLoopStatement::inlineCost(InlineCostState *ics)
-{   int cost = 0;
-
-    for (size_t i = 0; i < statements->dim; i++)
-    {	Statement *s = (Statement *) statements->data[i];
-	if (s)
-	{
-	    cost += s->inlineCost(ics);
-	    if (cost >= COST_MAX)
-		break;
-	}
-    }
-    return cost;
-}
-
-int IfStatement::inlineCost(InlineCostState *ics)
-{
-    int cost;
-
-#if !IN_LLVM
-    /* Can't declare variables inside ?: expressions, so
-     * we cannot inline if a variable is declared.
-     */
-    if (arg)
-	return COST_MAX;
-#endif
-
-    cost = condition->inlineCost(ics);
-
-#if !IN_LLVM
-    /* Specifically allow:
-     *	if (condition)
-     *	    return exp1;
-     *	else
-     *	    return exp2;
-     * Otherwise, we can't handle return statements nested in if's.
-     */
-
-    if (elsebody && ifbody &&
-	ifbody->isReturnStatement() &&
-	elsebody->isReturnStatement())
-    {
-	cost += ifbody->inlineCost(ics);
-	cost += elsebody->inlineCost(ics);
-	//printf("cost = %d\n", cost);
-    }
-    else
-#endif
-    {
-	ics->nested += 1;
-	if (ifbody)
-	    cost += ifbody->inlineCost(ics);
-	if (elsebody)
-	    cost += elsebody->inlineCost(ics);
-	ics->nested -= 1;
-    }
-    return cost;
-}
-
-int ReturnStatement::inlineCost(InlineCostState *ics)
-{
-#if !IN_LLVM
-    // Can't handle return statements nested in if's
-    if (ics->nested)
-	return COST_MAX;
-#endif
-    return exp ? exp->inlineCost(ics) : 0;
-}
-
-/* -------------------------- */
-
-int arrayInlineCost(InlineCostState *ics, Array *arguments)
-{   int cost = 0;
-
-    if (arguments)
-    {
-	for (int i = 0; i < arguments->dim; i++)
-	{   Expression *e = (Expression *)arguments->data[i];
-
-	    if (e)
-		cost += e->inlineCost(ics);
-	}
-    }
-    return cost;
-}
-
-int Expression::inlineCost(InlineCostState *ics)
-{
-    return 1;
-}
-
-int VarExp::inlineCost(InlineCostState *ics)
-{
-    //printf("VarExp::inlineCost() %s\n", toChars());
-    return 1;
-}
-
-int ThisExp::inlineCost(InlineCostState *ics)
-{
-#if !IN_LLVM
-    FuncDeclaration *fd = ics->fd;
-    if (!ics->hdrscan)
-	if (fd->isNested() || !ics->hasthis)
-	    return COST_MAX;
-#endif
-    return 1;
-}
-
-int SuperExp::inlineCost(InlineCostState *ics)
-{
-#if !IN_LLVM
-    FuncDeclaration *fd = ics->fd;
-    if (!ics->hdrscan)
-	if (fd->isNested() || !ics->hasthis)
-	    return COST_MAX;
-#endif
-    return 1;
-}
-
-int TupleExp::inlineCost(InlineCostState *ics)
-{
-    return 1 + arrayInlineCost(ics, exps);
-}
-
-int ArrayLiteralExp::inlineCost(InlineCostState *ics)
-{
-    return 1 + arrayInlineCost(ics, elements);
-}
-
-int AssocArrayLiteralExp::inlineCost(InlineCostState *ics)
-{
-    return 1 + arrayInlineCost(ics, keys) + arrayInlineCost(ics, values);
-}
-
-int StructLiteralExp::inlineCost(InlineCostState *ics)
-{
-    return 1 + arrayInlineCost(ics, elements);
-}
-
-int FuncExp::inlineCost(InlineCostState *ics)
-{
-    // This breaks on LDC too, since nested functions have internal linkage
-    // and thus can't be referenced from other objects.
-    // Right now, this makes the function be output to the .obj file twice.
-    return COST_MAX;
-}
-
-int DelegateExp::inlineCost(InlineCostState *ics)
-{
-    // This breaks on LDC too, since nested functions have internal linkage
-    // and thus can't be referenced from other objects.
-    return COST_MAX;
-}
-
-int DeclarationExp::inlineCost(InlineCostState *ics)
-{   int cost = 0;
-    VarDeclaration *vd;
-
-    //printf("DeclarationExp::inlineCost()\n");
-    vd = declaration->isVarDeclaration();
-    if (vd)
-    {
-	TupleDeclaration *td = vd->toAlias()->isTupleDeclaration();
-	if (td)
-	{
-#if 1
-	    return COST_MAX;	// finish DeclarationExp::doInline
-#else
-	    for (size_t i = 0; i < td->objects->dim; i++)
-	    {   Object *o = (Object *)td->objects->data[i];
-		if (o->dyncast() != DYNCAST_EXPRESSION)
-		    return COST_MAX;
-		Expression *eo = (Expression *)o;
-		if (eo->op != TOKdsymbol)
-		    return COST_MAX;
-	    }
-	    return td->objects->dim;
-#endif
-	}
-        // This breaks on LDC too, since nested static variables have internal
-        // linkage and thus can't be referenced from other objects.
-	if (!ics->hdrscan && vd->isDataseg())
-	    return COST_MAX;
-	cost += 1;
-
-	// Scan initializer (vd->init)
-	if (vd->init)
-	{
-	    ExpInitializer *ie = vd->init->isExpInitializer();
-
-	    if (ie)
-	    {
-		cost += ie->exp->inlineCost(ics);
-	    }
-	}
-    }
-
-    // These can contain functions, which when copied, get output twice.
-    // These break on LDC too, since nested static variables and functions have
-    // internal linkage and thus can't be referenced from other objects.
-    if (declaration->isStructDeclaration() ||
-	declaration->isClassDeclaration() ||
-	declaration->isFuncDeclaration() ||
-	declaration->isTypedefDeclaration() ||
-	declaration->isTemplateMixin())
-	return COST_MAX;
-
-    //printf("DeclarationExp::inlineCost('%s')\n", toChars());
-    return cost;
-}
-
-int UnaExp::inlineCost(InlineCostState *ics)
-{
-    return 1 + e1->inlineCost(ics);
-}
-
-int AssertExp::inlineCost(InlineCostState *ics)
-{
-    return 1 + e1->inlineCost(ics) + (msg ? msg->inlineCost(ics) : 0);
-}
-
-int BinExp::inlineCost(InlineCostState *ics)
-{
-    return 1 + e1->inlineCost(ics) + e2->inlineCost(ics);
-}
-
-int CallExp::inlineCost(InlineCostState *ics)
-{
-    return 1 + e1->inlineCost(ics) + arrayInlineCost(ics, arguments);
-}
-
-int SliceExp::inlineCost(InlineCostState *ics)
-{   int cost;
-
-    cost = 1 + e1->inlineCost(ics);
-    if (lwr)
-	cost += lwr->inlineCost(ics);
-    if (upr)
-	cost += upr->inlineCost(ics);
-    return cost;
-}
-
-int ArrayExp::inlineCost(InlineCostState *ics)
-{
-    return 1 + e1->inlineCost(ics) + arrayInlineCost(ics, arguments);
-}
-
-
-int CondExp::inlineCost(InlineCostState *ics)
-{
-    return 1 +
-	 e1->inlineCost(ics) +
-	 e2->inlineCost(ics) +
-	 econd->inlineCost(ics);
-}
-
-
-/* ======================== Perform the inlining ============================== */
-
-/* Inlining is done by:
- * o	Converting to an Expression
- * o	Copying the trees of the function to be inlined
- * o	Renaming the variables
- */
-
-struct InlineDoState
-{
-    VarDeclaration *vthis;
-    Array from;		// old Dsymbols
-    Array to;		// parallel array of new Dsymbols
-    Dsymbol *parent;	// new parent
-};
-
-Expression *Statement::doInline(InlineDoState *ids)
-{
-    assert(0);
-    return NULL;		// default is we can't inline it
-}
-
-Expression *ExpStatement::doInline(InlineDoState *ids)
-{
-#if LOG
-    if (exp) printf("ExpStatement::doInline() '%s'\n", exp->toChars());
-#endif
-    return exp ? exp->doInline(ids) : NULL;
-}
-
-Expression *CompoundStatement::doInline(InlineDoState *ids)
-{
-    Expression *e = NULL;
-
-    //printf("CompoundStatement::doInline() %d\n", statements->dim);
-    for (size_t i = 0; i < statements->dim; i++)
-    {	Statement *s = (Statement *) statements->data[i];
-	if (s)
-	{
-	    Expression *e2 = s->doInline(ids);
-	    e = Expression::combine(e, e2);
-	    if (s->isReturnStatement())
-		break;
-
-	    /* Check for:
-	     *	if (condition)
-	     *	    return exp1;
-	     *	else
-	     *	    return exp2;
-	     */
-	    IfStatement *ifs = s->isIfStatement();
-	    if (ifs && ifs->elsebody && ifs->ifbody &&
-		ifs->ifbody->isReturnStatement() &&
-		ifs->elsebody->isReturnStatement()
-	       )
-		break;
-
-	}
-    }
-    return e;
-}
-
-Expression *UnrolledLoopStatement::doInline(InlineDoState *ids)
-{
-    Expression *e = NULL;
-
-    //printf("UnrolledLoopStatement::doInline() %d\n", statements->dim);
-    for (size_t i = 0; i < statements->dim; i++)
-    {	Statement *s = (Statement *) statements->data[i];
-	if (s)
-	{
-	    Expression *e2 = s->doInline(ids);
-	    e = Expression::combine(e, e2);
-	    if (s->isReturnStatement())
-		break;
-	}
-    }
-    return e;
-}
-
-Expression *IfStatement::doInline(InlineDoState *ids)
-{
-    Expression *econd;
-    Expression *e1;
-    Expression *e2;
-    Expression *e;
-
-    assert(!arg);
-    econd = condition->doInline(ids);
-    assert(econd);
-    if (ifbody)
-	e1 = ifbody->doInline(ids);
-    else
-	e1 = NULL;
-    if (elsebody)
-	e2 = elsebody->doInline(ids);
-    else
-	e2 = NULL;
-    if (e1 && e2)
-    {
-	e = new CondExp(econd->loc, econd, e1, e2);
-	e->type = e1->type;
-    }
-    else if (e1)
-    {
-	e = new AndAndExp(econd->loc, econd, e1);
-	e->type = Type::tvoid;
-    }
-    else if (e2)
-    {
-	e = new OrOrExp(econd->loc, econd, e2);
-	e->type = Type::tvoid;
-    }
-    else
-    {
-	e = econd;
-    }
-    return e;
-}
-
-Expression *ReturnStatement::doInline(InlineDoState *ids)
-{
-    //printf("ReturnStatement::doInline() '%s'\n", exp ? exp->toChars() : "");
-    return exp ? exp->doInline(ids) : 0;
-}
-
-/* --------------------------------------------------------------- */
-
-/******************************
- * Perform doInline() on an array of Expressions.
- */
-
-Expressions *arrayExpressiondoInline(Expressions *a, InlineDoState *ids)
-{   Expressions *newa = NULL;
-
-    if (a)
-    {
-	newa = new Expressions();
-	newa->setDim(a->dim);
-
-	for (int i = 0; i < a->dim; i++)
-	{   Expression *e = (Expression *)a->data[i];
-
-	    if (e)
-	    {
-		e = e->doInline(ids);
-		newa->data[i] = (void *)e;
-	    }
-	}
-    }
-    return newa;
-}
-
-Expression *Expression::doInline(InlineDoState *ids)
-{
-    //printf("Expression::doInline(%s): %s\n", Token::toChars(op), toChars());
-    return copy();
-}
-
-Expression *SymOffExp::doInline(InlineDoState *ids)
-{
-    int i;
-
-    //printf("SymOffExp::doInline(%s)\n", toChars());
-    for (i = 0; i < ids->from.dim; i++)
-    {
-	if (var == (Declaration *)ids->from.data[i])
-	{
-	    SymOffExp *se = (SymOffExp *)copy();
-
-	    se->var = (Declaration *)ids->to.data[i];
-	    return se;
-	}
-    }
-    return this;
-}
-
-Expression *VarExp::doInline(InlineDoState *ids)
-{
-    int i;
-
-    //printf("VarExp::doInline(%s)\n", toChars());
-    for (i = 0; i < ids->from.dim; i++)
-    {
-	if (var == (Declaration *)ids->from.data[i])
-	{
-	    VarExp *ve = (VarExp *)copy();
-
-	    ve->var = (Declaration *)ids->to.data[i];
-	    return ve;
-	}
-    }
-    return this;
-}
-
-Expression *ThisExp::doInline(InlineDoState *ids)
-{
-    //if (!ids->vthis)
-	//error("no 'this' when inlining %s", ids->parent->toChars());
-    if (!ids->vthis)
-    {
-	return this;
-    }
-
-    VarExp *ve = new VarExp(loc, ids->vthis);
-    ve->type = type;
-    return ve;
-}
-
-Expression *SuperExp::doInline(InlineDoState *ids)
-{
-    assert(ids->vthis);
-
-    VarExp *ve = new VarExp(loc, ids->vthis);
-    ve->type = type;
-    return ve;
-}
-
-Expression *DeclarationExp::doInline(InlineDoState *ids)
-{   DeclarationExp *de = (DeclarationExp *)copy();
-    VarDeclaration *vd;
-
-    //printf("DeclarationExp::doInline(%s)\n", toChars());
-    vd = declaration->isVarDeclaration();
-    if (vd)
-    {
-#if 0
-	// Need to figure this out before inlining can work for tuples
-	TupleDeclaration *td = vd->toAlias()->isTupleDeclaration();
-	if (td)
-	{
-	    for (size_t i = 0; i < td->objects->dim; i++)
-	    {   DsymbolExp *se = (DsymbolExp *)td->objects->data[i];
-		assert(se->op == TOKdsymbol);
-		se->s;
-	    }
-	    return st->objects->dim;
-	}
-#endif
-	if (vd->isStatic() || vd->isConst())
-	    ;
-	else
-	{
-	    VarDeclaration *vto;
-
-	    vto = new VarDeclaration(vd->loc, vd->type, vd->ident, vd->init);
-	    *vto = *vd;
-	    vto->parent = ids->parent;
-#if IN_DMD
-	    vto->csym = NULL;
-	    vto->isym = NULL;
-#endif
-
-	    ids->from.push(vd);
-	    ids->to.push(vto);
-
-	    if (vd->init)
-	    {
-		if (vd->init->isVoidInitializer())
-		{
-		    vto->init = new VoidInitializer(vd->init->loc);
-		}
-		else
-		{
-		    ExpInitializer *ie = vd->init->isExpInitializer();
-		    assert(ie);
-		    vto->init = new ExpInitializer(ie->loc, ie->exp->doInline(ids));
-		}
-	    }
-	    de->declaration = (Dsymbol *) (void *)vto;
-	}
-    }
-    /* This needs work, like DeclarationExp::toElem(), if we are
-     * to handle TemplateMixin's. For now, we just don't inline them.
-     */
-    return de;
-}
-
-Expression *NewExp::doInline(InlineDoState *ids)
-{
-    //printf("NewExp::doInline(): %s\n", toChars());
-    NewExp *ne = (NewExp *)copy();
-
-    if (thisexp)
-	ne->thisexp = thisexp->doInline(ids);
-    ne->newargs = arrayExpressiondoInline(ne->newargs, ids);
-    ne->arguments = arrayExpressiondoInline(ne->arguments, ids);
-    return ne;
-}
-
-Expression *UnaExp::doInline(InlineDoState *ids)
-{
-    UnaExp *ue = (UnaExp *)copy();
-
-    ue->e1 = e1->doInline(ids);
-    return ue;
-}
-
-Expression *AssertExp::doInline(InlineDoState *ids)
-{
-    AssertExp *ae = (AssertExp *)copy();
-
-    ae->e1 = e1->doInline(ids);
-    if (msg)
-	ae->msg = msg->doInline(ids);
-    return ae;
-}
-
-Expression *BinExp::doInline(InlineDoState *ids)
-{
-    BinExp *be = (BinExp *)copy();
-
-    be->e1 = e1->doInline(ids);
-    be->e2 = e2->doInline(ids);
-    return be;
-}
-
-Expression *CallExp::doInline(InlineDoState *ids)
-{
-    CallExp *ce;
-
-    ce = (CallExp *)copy();
-    ce->e1 = e1->doInline(ids);
-    ce->arguments = arrayExpressiondoInline(arguments, ids);
-    return ce;
-}
-
-
-Expression *IndexExp::doInline(InlineDoState *ids)
-{
-    IndexExp *are = (IndexExp *)copy();
-
-    are->e1 = e1->doInline(ids);
-
-    if (lengthVar)
-    {	//printf("lengthVar\n");
-	VarDeclaration *vd = lengthVar;
-	ExpInitializer *ie;
-	ExpInitializer *ieto;
-	VarDeclaration *vto;
-
-	vto = new VarDeclaration(vd->loc, vd->type, vd->ident, vd->init);
-	*vto = *vd;
-	vto->parent = ids->parent;
-#if IN_DMD
-	vto->csym = NULL;
-	vto->isym = NULL;
-#endif
-
-	ids->from.push(vd);
-	ids->to.push(vto);
-
-	if (vd->init)
-	{
-	    ie = vd->init->isExpInitializer();
-	    assert(ie);
-	    ieto = new ExpInitializer(ie->loc, ie->exp->doInline(ids));
-	    vto->init = ieto;
-	}
-
-	are->lengthVar = (VarDeclaration *) (void *)vto;
-    }
-    are->e2 = e2->doInline(ids);
-    return are;
-}
-
-
-Expression *SliceExp::doInline(InlineDoState *ids)
-{
-    SliceExp *are = (SliceExp *)copy();
-
-    are->e1 = e1->doInline(ids);
-
-    if (lengthVar)
-    {	//printf("lengthVar\n");
-	VarDeclaration *vd = lengthVar;
-	ExpInitializer *ie;
-	ExpInitializer *ieto;
-	VarDeclaration *vto;
-
-	vto = new VarDeclaration(vd->loc, vd->type, vd->ident, vd->init);
-	*vto = *vd;
-	vto->parent = ids->parent;
-#if IN_DMD
-	vto->csym = NULL;
-	vto->isym = NULL;
-#endif
-
-	ids->from.push(vd);
-	ids->to.push(vto);
-
-	if (vd->init)
-	{
-	    ie = vd->init->isExpInitializer();
-	    assert(ie);
-	    ieto = new ExpInitializer(ie->loc, ie->exp->doInline(ids));
-	    vto->init = ieto;
-	}
-
-	are->lengthVar = (VarDeclaration *) (void *)vto;
-    }
-    if (lwr)
-	are->lwr = lwr->doInline(ids);
-    if (upr)
-	are->upr = upr->doInline(ids);
-    return are;
-}
-
-
-Expression *TupleExp::doInline(InlineDoState *ids)
-{
-    TupleExp *ce;
-
-    ce = (TupleExp *)copy();
-    ce->exps = arrayExpressiondoInline(exps, ids);
-    return ce;
-}
-
-
-Expression *ArrayLiteralExp::doInline(InlineDoState *ids)
-{
-    ArrayLiteralExp *ce;
-
-    ce = (ArrayLiteralExp *)copy();
-    ce->elements = arrayExpressiondoInline(elements, ids);
-    return ce;
-}
-
-
-Expression *AssocArrayLiteralExp::doInline(InlineDoState *ids)
-{
-    AssocArrayLiteralExp *ce;
-
-    ce = (AssocArrayLiteralExp *)copy();
-    ce->keys = arrayExpressiondoInline(keys, ids);
-    ce->values = arrayExpressiondoInline(values, ids);
-    return ce;
-}
-
-
-Expression *StructLiteralExp::doInline(InlineDoState *ids)
-{
-    StructLiteralExp *ce;
-
-    ce = (StructLiteralExp *)copy();
-    ce->elements = arrayExpressiondoInline(elements, ids);
-    return ce;
-}
-
-
-Expression *ArrayExp::doInline(InlineDoState *ids)
-{
-    ArrayExp *ce;
-
-    ce = (ArrayExp *)copy();
-    ce->e1 = e1->doInline(ids);
-    ce->arguments = arrayExpressiondoInline(arguments, ids);
-    return ce;
-}
-
-
-Expression *CondExp::doInline(InlineDoState *ids)
-{
-    CondExp *ce = (CondExp *)copy();
-
-    ce->econd = econd->doInline(ids);
-    ce->e1 = e1->doInline(ids);
-    ce->e2 = e2->doInline(ids);
-    return ce;
-}
-
-
-/* ========== Walk the parse trees, and inline expand functions ============= */
-
-/* Walk the trees, looking for functions to inline.
- * Inline any that can be.
- */
-
-struct InlineScanState
-{
-    FuncDeclaration *fd;	// function being scanned
-};
-
-Statement *Statement::inlineScan(InlineScanState *iss)
-{
-    return this;
-}
-
-Statement *ExpStatement::inlineScan(InlineScanState *iss)
-{
-#if LOG
-    printf("ExpStatement::inlineScan(%s)\n", toChars());
-#endif
-    if (exp)
-	exp = exp->inlineScan(iss);
-    return this;
-}
-
-Statement *CompoundStatement::inlineScan(InlineScanState *iss)
-{
-    for (size_t i = 0; i < statements->dim; i++)
-    {	Statement *s = (Statement *) statements->data[i];
-	if (s)
-	    statements->data[i] = (void *)s->inlineScan(iss);
-    }
-    return this;
-}
-
-Statement *UnrolledLoopStatement::inlineScan(InlineScanState *iss)
-{
-    for (size_t i = 0; i < statements->dim; i++)
-    {	Statement *s = (Statement *) statements->data[i];
-	if (s)
-	    statements->data[i] = (void *)s->inlineScan(iss);
-    }
-    return this;
-}
-
-Statement *ScopeStatement::inlineScan(InlineScanState *iss)
-{
-    if (statement)
-	statement = statement->inlineScan(iss);
-    return this;
-}
-
-Statement *WhileStatement::inlineScan(InlineScanState *iss)
-{
-    condition = condition->inlineScan(iss);
-    body = body ? body->inlineScan(iss) : NULL;
-    return this;
-}
-
-
-Statement *DoStatement::inlineScan(InlineScanState *iss)
-{
-    body = body ? body->inlineScan(iss) : NULL;
-    condition = condition->inlineScan(iss);
-    return this;
-}
-
-
-Statement *ForStatement::inlineScan(InlineScanState *iss)
-{
-    if (init)
-	init = init->inlineScan(iss);
-    if (condition)
-	condition = condition->inlineScan(iss);
-    if (increment)
-	increment = increment->inlineScan(iss);
-    body = body->inlineScan(iss);
-    return this;
-}
-
-
-Statement *ForeachStatement::inlineScan(InlineScanState *iss)
-{
-    aggr = aggr->inlineScan(iss);
-    if (body)
-	body = body->inlineScan(iss);
-    return this;
-}
-
-
-#if DMDV2
-Statement *ForeachRangeStatement::inlineScan(InlineScanState *iss)
-{
-    lwr = lwr->inlineScan(iss);
-    upr = upr->inlineScan(iss);
-    if (body)
-	body = body->inlineScan(iss);
-    return this;
-}
-#endif
-
-
-Statement *IfStatement::inlineScan(InlineScanState *iss)
-{
-    condition = condition->inlineScan(iss);
-    if (ifbody)
-	ifbody = ifbody->inlineScan(iss);
-    if (elsebody)
-	elsebody = elsebody->inlineScan(iss);
-    return this;
-}
-
-
-Statement *SwitchStatement::inlineScan(InlineScanState *iss)
-{
-    //printf("SwitchStatement::inlineScan()\n");
-    condition = condition->inlineScan(iss);
-    body = body ? body->inlineScan(iss) : NULL;
-    if (sdefault)
-	sdefault = (DefaultStatement *)sdefault->inlineScan(iss);
-    if (cases)
-    {
-	for (int i = 0; i < cases->dim; i++)
-	{   Statement *s;
-
-	    s = (Statement *) cases->data[i];
-	    cases->data[i] = (void *)s->inlineScan(iss);
-	}
-    }
-    return this;
-}
-
-
-Statement *CaseStatement::inlineScan(InlineScanState *iss)
-{
-    //printf("CaseStatement::inlineScan()\n");
-    exp = exp->inlineScan(iss);
-    if (statement)
-	statement = statement->inlineScan(iss);
-    return this;
-}
-
-
-Statement *DefaultStatement::inlineScan(InlineScanState *iss)
-{
-    if (statement)
-	statement = statement->inlineScan(iss);
-    return this;
-}
-
-
-Statement *ReturnStatement::inlineScan(InlineScanState *iss)
-{
-    //printf("ReturnStatement::inlineScan()\n");
-    if (exp)
-    {
-	exp = exp->inlineScan(iss);
-    }
-    return this;
-}
-
-
-Statement *SynchronizedStatement::inlineScan(InlineScanState *iss)
-{
-    if (exp)
-	exp = exp->inlineScan(iss);
-    if (body)
-	body = body->inlineScan(iss);
-    return this;
-}
-
-
-Statement *WithStatement::inlineScan(InlineScanState *iss)
-{
-    if (exp)
-	exp = exp->inlineScan(iss);
-    if (body)
-	body = body->inlineScan(iss);
-    return this;
-}
-
-
-Statement *TryCatchStatement::inlineScan(InlineScanState *iss)
-{
-    if (body)
-	body = body->inlineScan(iss);
-    if (catches)
-    {
-	for (int i = 0; i < catches->dim; i++)
-	{   Catch *c = (Catch *)catches->data[i];
-
-	    if (c->handler)
-		c->handler = c->handler->inlineScan(iss);
-	}
-    }
-    return this;
-}
-
-
-Statement *TryFinallyStatement::inlineScan(InlineScanState *iss)
-{
-    if (body)
-	body = body->inlineScan(iss);
-    if (finalbody)
-	finalbody = finalbody->inlineScan(iss);
-    return this;
-}
-
-
-Statement *ThrowStatement::inlineScan(InlineScanState *iss)
-{
-    if (exp)
-	exp = exp->inlineScan(iss);
-    return this;
-}
-
-
-Statement *VolatileStatement::inlineScan(InlineScanState *iss)
-{
-    if (statement)
-	statement = statement->inlineScan(iss);
-    return this;
-}
-
-
-Statement *LabelStatement::inlineScan(InlineScanState *iss)
-{
-    if (statement)
-	statement = statement->inlineScan(iss);
-    return this;
-}
-
-/* -------------------------- */
-
-void arrayInlineScan(InlineScanState *iss, Array *arguments)
-{
-    if (arguments)
-    {
-	for (int i = 0; i < arguments->dim; i++)
-	{   Expression *e = (Expression *)arguments->data[i];
-
-	    if (e)
-	    {
-		e = e->inlineScan(iss);
-		arguments->data[i] = (void *)e;
-	    }
-	}
-    }
-}
-
-Expression *Expression::inlineScan(InlineScanState *iss)
-{
-    return this;
-}
-
-void scanVar(Dsymbol *s, InlineScanState *iss)
-{
-    VarDeclaration *vd = s->isVarDeclaration();
-    if (vd)
-    {
-	TupleDeclaration *td = vd->toAlias()->isTupleDeclaration();
-	if (td)
-	{
-	    for (size_t i = 0; i < td->objects->dim; i++)
-	    {   DsymbolExp *se = (DsymbolExp *)td->objects->data[i];
-		assert(se->op == TOKdsymbol);
-		scanVar(se->s, iss);
-	    }
-	}
-	else
-	{
-	    // Scan initializer (vd->init)
-	    if (vd->init)
-	    {
-		ExpInitializer *ie = vd->init->isExpInitializer();
-
-		if (ie)
-		{
-		    ie->exp = ie->exp->inlineScan(iss);
-		}
-	    }
-	}
-    }
-}
-
-Expression *DeclarationExp::inlineScan(InlineScanState *iss)
-{
-    //printf("DeclarationExp::inlineScan()\n");
-    scanVar(declaration, iss);
-    return this;
-}
-
-Expression *UnaExp::inlineScan(InlineScanState *iss)
-{
-    e1 = e1->inlineScan(iss);
-    return this;
-}
-
-Expression *AssertExp::inlineScan(InlineScanState *iss)
-{
-    e1 = e1->inlineScan(iss);
-    if (msg)
-	msg = msg->inlineScan(iss);
-    return this;
-}
-
-Expression *BinExp::inlineScan(InlineScanState *iss)
-{
-    e1 = e1->inlineScan(iss);
-    e2 = e2->inlineScan(iss);
-    return this;
-}
-
-
-Expression *CallExp::inlineScan(InlineScanState *iss)
-{   Expression *e = this;
-
-    //printf("CallExp::inlineScan()\n");
-    e1 = e1->inlineScan(iss);
-    arrayInlineScan(iss, arguments);
-
-    if (e1->op == TOKvar)
-    {
-	VarExp *ve = (VarExp *)e1;
-	FuncDeclaration *fd = ve->var->isFuncDeclaration();
-
-	if (fd && fd != iss->fd && fd->canInline(0))
-	{
-	    e = fd->doInline(iss, NULL, arguments);
-	}
-    }
-    else if (e1->op == TOKdotvar)
-    {
-	DotVarExp *dve = (DotVarExp *)e1;
-	FuncDeclaration *fd = dve->var->isFuncDeclaration();
-
-	if (fd && fd != iss->fd && fd->canInline(1))
-	{
-	    if (dve->e1->op == TOKcall &&
-		dve->e1->type->toBasetype()->ty == Tstruct)
-	    {
-		/* To create ethis, we'll need to take the address
-		 * of dve->e1, but this won't work if dve->e1 is
-		 * a function call.
-		 */
-		;
-	    }
-	    else
-		e = fd->doInline(iss, dve->e1, arguments);
-	}
-    }
-
-    return e;
-}
-
-
-Expression *SliceExp::inlineScan(InlineScanState *iss)
-{
-    e1 = e1->inlineScan(iss);
-    if (lwr)
-	lwr = lwr->inlineScan(iss);
-    if (upr)
-	upr = upr->inlineScan(iss);
-    return this;
-}
-
-
-Expression *TupleExp::inlineScan(InlineScanState *iss)
-{   Expression *e = this;
-
-    //printf("TupleExp::inlineScan()\n");
-    arrayInlineScan(iss, exps);
-
-    return e;
-}
-
-
-Expression *ArrayLiteralExp::inlineScan(InlineScanState *iss)
-{   Expression *e = this;
-
-    //printf("ArrayLiteralExp::inlineScan()\n");
-    arrayInlineScan(iss, elements);
-
-    return e;
-}
-
-
-Expression *AssocArrayLiteralExp::inlineScan(InlineScanState *iss)
-{   Expression *e = this;
-
-    //printf("AssocArrayLiteralExp::inlineScan()\n");
-    arrayInlineScan(iss, keys);
-    arrayInlineScan(iss, values);
-
-    return e;
-}
-
-
-Expression *StructLiteralExp::inlineScan(InlineScanState *iss)
-{   Expression *e = this;
-
-    //printf("StructLiteralExp::inlineScan()\n");
-    arrayInlineScan(iss, elements);
-
-    return e;
-}
-
-
-Expression *ArrayExp::inlineScan(InlineScanState *iss)
-{   Expression *e = this;
-
-    //printf("ArrayExp::inlineScan()\n");
-    e1 = e1->inlineScan(iss);
-    arrayInlineScan(iss, arguments);
-
-    return e;
-}
-
-
-Expression *CondExp::inlineScan(InlineScanState *iss)
-{
-    econd = econd->inlineScan(iss);
-    e1 = e1->inlineScan(iss);
-    e2 = e2->inlineScan(iss);
-    return this;
-}
-
-
-/* ==========  =============== */
-
-void FuncDeclaration::inlineScan()
-{
-    InlineScanState iss;
-
-#if LOG
-    printf("FuncDeclaration::inlineScan('%s')\n", toChars());
-#endif
-    memset(&iss, 0, sizeof(iss));
-    iss.fd = this;
-    if (fbody)
-    {
-	inlineNest++;
-	fbody = fbody->inlineScan(&iss);
-	inlineNest--;
-    }
-}
-
-int FuncDeclaration::canInline(int hasthis, int hdrscan)
-{
-    InlineCostState ics;
-    int cost;
-
-#define CANINLINE_LOG 0
-
-#if CANINLINE_LOG
-    printf("FuncDeclaration::canInline(hasthis = %d, '%s')\n", hasthis, toChars());
-#endif
-
-    if (needThis() && !hasthis)
-	return 0;
-
-    if (inlineNest || (semanticRun < 3 && !hdrscan))
-    {
-#if CANINLINE_LOG
-	printf("\t1: no, inlineNest = %d, semanticRun = %d\n", inlineNest, semanticRun);
-#endif
-	return 0;
-    }
-
-    switch (inlineStatus)
-    {
-	case ILSyes:
-#if CANINLINE_LOG
-	    printf("\t1: yes %s\n", toChars());
-#endif
-	    return 1;
-
-	case ILSno:
-#if CANINLINE_LOG
-	    printf("\t1: no %s\n", toChars());
-#endif
-	    return 0;
-
-	case ILSuninitialized:
-	    break;
-
-	default:
-	    assert(0);
-    }
-
-    if (type)
-    {	assert(type->ty == Tfunction);
-	TypeFunction *tf = (TypeFunction *)(type);
-#if IN_LLVM
-        // LDC: Only extern(C) varargs count.
-        if (tf->linkage != LINKd)
-#endif
-	if (tf->varargs == 1)	// no variadic parameter lists
-	    goto Lno;
-
-	/* Don't inline a function that returns non-void, but has
-	 * no return expression.
-	 */
-	if (tf->next && tf->next->ty != Tvoid &&
-	    !(hasReturnExp & 1) &&
-	    !hdrscan)
-	    goto Lno;
-    }
-#if !IN_LLVM
-    // LDC: Only extern(C) varargs count, and ctors use extern(D).
-    else
-    {	CtorDeclaration *ctor = isCtorDeclaration();
-
-	if (ctor && ctor->varargs == 1)
-	    goto Lno;
-    }
-#endif
-
-    if (
-	!fbody ||
-	!hdrscan &&
-	(
-#if 0
-	isCtorDeclaration() ||	// cannot because need to convert:
-				//	return;
-				// to:
-				//	return this;
-#endif
-	isSynchronized() ||
-	isImportedSymbol() ||
-#if !IN_LLVM
-#if DMDV2
-	closureVars.dim ||	// no nested references to this frame
-#else
-	nestedFrameRef ||	// no nested references to this frame
-#endif
-#endif // !IN_LLVM
-	(isVirtual() && !isFinal())
-       ))
-    {
-	goto Lno;
-    }
-
-#if !IN_LLVM
-    /* If any parameters are Tsarray's (which are passed by reference)
-     * or out parameters (also passed by reference), don't do inlining.
-     */
-    if (parameters)
-    {
-	for (int i = 0; i < parameters->dim; i++)
-	{
-	    VarDeclaration *v = (VarDeclaration *)parameters->data[i];
-	    if (v->isOut() || v->isRef() || v->type->toBasetype()->ty == Tsarray)
-		goto Lno;
-	}
-    }
-#endif
-
-    memset(&ics, 0, sizeof(ics));
-    ics.hasthis = hasthis;
-    ics.fd = this;
-    ics.hdrscan = hdrscan;
-    cost = fbody->inlineCost(&ics);
-#if CANINLINE_LOG
-    printf("cost = %d\n", cost);
-#endif
-    if (cost >= COST_MAX)
-	goto Lno;
-
-#if !IN_LLVM
-    if (!hdrscan)    // Don't scan recursively for header content scan
-	inlineScan();
-#endif
-
-Lyes:
-    if (!hdrscan)    // Don't modify inlineStatus for header content scan
-	inlineStatus = ILSyes;
-#if CANINLINE_LOG
-    printf("\t2: yes %s\n", toChars());
-#endif
-    return 1;
-
-Lno:
-    if (!hdrscan)    // Don't modify inlineStatus for header content scan
-	inlineStatus = ILSno;
-#if CANINLINE_LOG
-    printf("\t2: no %s\n", toChars());
-#endif
-    return 0;
-}
-
-Expression *FuncDeclaration::doInline(InlineScanState *iss, Expression *ethis, Array *arguments)
-{
-    InlineDoState ids;
-    DeclarationExp *de;
-    Expression *e = NULL;
-
-#if LOG
-    printf("FuncDeclaration::doInline('%s')\n", toChars());
-#endif
-
-    memset(&ids, 0, sizeof(ids));
-    ids.parent = iss->fd;
-
-    // Set up vthis
-    if (ethis)
-    {
-	VarDeclaration *vthis;
-	ExpInitializer *ei;
-	VarExp *ve;
-
-	if (ethis->type->ty != Tclass && ethis->type->ty != Tpointer)
-	{
-	    ethis = ethis->addressOf(NULL);
-	}
-
-	ei = new ExpInitializer(ethis->loc, ethis);
-
-	vthis = new VarDeclaration(ethis->loc, ethis->type, Id::This, ei);
-	vthis->storage_class = STCin;
-	vthis->linkage = LINKd;
-	vthis->parent = iss->fd;
-
-	ve = new VarExp(vthis->loc, vthis);
-	ve->type = vthis->type;
-
-	ei->exp = new AssignExp(vthis->loc, ve, ethis);
-	ei->exp->type = ve->type;
-
-	ids.vthis = vthis;
-    }
-
-    // Set up parameters
-    if (ethis)
-    {
-	e = new DeclarationExp(0, ids.vthis);
-	e->type = Type::tvoid;
-    }
-
-    if (arguments && arguments->dim)
-    {
-	assert(parameters->dim == arguments->dim);
-
-	for (int i = 0; i < arguments->dim; i++)
-	{
-	    VarDeclaration *vfrom = (VarDeclaration *)parameters->data[i];
-	    VarDeclaration *vto;
-	    Expression *arg = (Expression *)arguments->data[i];
-	    ExpInitializer *ei;
-	    VarExp *ve;
-
-	    ei = new ExpInitializer(arg->loc, arg);
-
-	    vto = new VarDeclaration(vfrom->loc, vfrom->type, vfrom->ident, ei);
-	    vto->storage_class |= vfrom->storage_class & (STCin | STCout | STClazy | STCref);
-	    vto->linkage = vfrom->linkage;
-	    vto->parent = iss->fd;
-	    //printf("vto = '%s', vto->storage_class = x%x\n", vto->toChars(), vto->storage_class);
-	    //printf("vto->parent = '%s'\n", iss->fd->toChars());
-
-	    ve = new VarExp(vto->loc, vto);
-	    //ve->type = vto->type;
-	    ve->type = arg->type;
-
-	    ei->exp = new AssignExp(vto->loc, ve, arg);
-	    ei->exp->type = ve->type;
-//ve->type->print();
-//arg->type->print();
-//ei->exp->print();
-
-	    ids.from.push(vfrom);
-	    ids.to.push(vto);
-
-	    de = new DeclarationExp(0, vto);
-	    de->type = Type::tvoid;
-
-	    e = Expression::combine(e, de);
-	}
-    }
-
-    inlineNest++;
-    Expression *eb = fbody->doInline(&ids);
-    inlineNest--;
-//eb->type->print();
-//eb->print();
-//eb->dump(0);
-    return Expression::combine(e, eb);
-}
-
-
-
+
+// Copyright (c) 1999-2009 by Digital Mars
+// All Rights Reserved
+// written by Walter Bright
+// http://www.digitalmars.com
+// License for redistribution is by either the Artistic License
+// in artistic.txt, or the GNU General Public License in gnu.txt.
+// See the included readme.txt for details.
+
+// Routines to perform function inlining
+
+#define LOG 0
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+
+#include "id.h"
+#include "init.h"
+#include "declaration.h"
+#include "aggregate.h"
+#include "expression.h"
+#include "statement.h"
+#include "mtype.h"
+
+/* ========== Compute cost of inlining =============== */
+
+/* Walk trees to determine if inlining can be done, and if so,
+ * if it is too complex to be worth inlining or not.
+ */
+
+struct InlineCostState
+{
+    int nested;
+    int hasthis;
+    int hdrscan;    // !=0 if inline scan for 'header' content
+    FuncDeclaration *fd;
+};
+
+const int COST_MAX = 250;
+
+int Statement::inlineCost(InlineCostState *ics)
+{
+    return COST_MAX;		// default is we can't inline it
+}
+
+int ExpStatement::inlineCost(InlineCostState *ics)
+{
+    return exp ? exp->inlineCost(ics) : 0;
+}
+
+int CompoundStatement::inlineCost(InlineCostState *ics)
+{   int cost = 0;
+
+    for (size_t i = 0; i < statements->dim; i++)
+    {	Statement *s = (Statement *) statements->data[i];
+	if (s)
+	{
+	    cost += s->inlineCost(ics);
+	    if (cost >= COST_MAX)
+		break;
+	}
+    }
+    return cost;
+}
+
+int UnrolledLoopStatement::inlineCost(InlineCostState *ics)
+{   int cost = 0;
+
+    for (size_t i = 0; i < statements->dim; i++)
+    {	Statement *s = (Statement *) statements->data[i];
+	if (s)
+	{
+	    cost += s->inlineCost(ics);
+	    if (cost >= COST_MAX)
+		break;
+	}
+    }
+    return cost;
+}
+
+int IfStatement::inlineCost(InlineCostState *ics)
+{
+    int cost;
+
+#if !IN_LLVM
+    /* Can't declare variables inside ?: expressions, so
+     * we cannot inline if a variable is declared.
+     */
+    if (arg)
+	return COST_MAX;
+#endif
+
+    cost = condition->inlineCost(ics);
+
+#if !IN_LLVM
+    /* Specifically allow:
+     *	if (condition)
+     *	    return exp1;
+     *	else
+     *	    return exp2;
+     * Otherwise, we can't handle return statements nested in if's.
+     */
+
+    if (elsebody && ifbody &&
+	ifbody->isReturnStatement() &&
+	elsebody->isReturnStatement())
+    {
+	cost += ifbody->inlineCost(ics);
+	cost += elsebody->inlineCost(ics);
+	//printf("cost = %d\n", cost);
+    }
+    else
+#endif
+    {
+	ics->nested += 1;
+	if (ifbody)
+	    cost += ifbody->inlineCost(ics);
+	if (elsebody)
+	    cost += elsebody->inlineCost(ics);
+	ics->nested -= 1;
+    }
+    return cost;
+}
+
+int ReturnStatement::inlineCost(InlineCostState *ics)
+{
+#if !IN_LLVM
+    // Can't handle return statements nested in if's
+    if (ics->nested)
+	return COST_MAX;
+#endif
+    return exp ? exp->inlineCost(ics) : 0;
+}
+
+/* -------------------------- */
+
+int arrayInlineCost(InlineCostState *ics, Array *arguments)
+{   int cost = 0;
+
+    if (arguments)
+    {
+	for (int i = 0; i < arguments->dim; i++)
+	{   Expression *e = (Expression *)arguments->data[i];
+
+	    if (e)
+		cost += e->inlineCost(ics);
+	}
+    }
+    return cost;
+}
+
+int Expression::inlineCost(InlineCostState *ics)
+{
+    return 1;
+}
+
+int VarExp::inlineCost(InlineCostState *ics)
+{
+    //printf("VarExp::inlineCost() %s\n", toChars());
+    return 1;
+}
+
+int ThisExp::inlineCost(InlineCostState *ics)
+{
+#if !IN_LLVM
+    FuncDeclaration *fd = ics->fd;
+    if (!ics->hdrscan)
+	if (fd->isNested() || !ics->hasthis)
+	    return COST_MAX;
+#endif
+    return 1;
+}
+
+int SuperExp::inlineCost(InlineCostState *ics)
+{
+#if !IN_LLVM
+    FuncDeclaration *fd = ics->fd;
+    if (!ics->hdrscan)
+	if (fd->isNested() || !ics->hasthis)
+	    return COST_MAX;
+#endif
+    return 1;
+}
+
+int TupleExp::inlineCost(InlineCostState *ics)
+{
+    return 1 + arrayInlineCost(ics, exps);
+}
+
+int ArrayLiteralExp::inlineCost(InlineCostState *ics)
+{
+    return 1 + arrayInlineCost(ics, elements);
+}
+
+int AssocArrayLiteralExp::inlineCost(InlineCostState *ics)
+{
+    return 1 + arrayInlineCost(ics, keys) + arrayInlineCost(ics, values);
+}
+
+int StructLiteralExp::inlineCost(InlineCostState *ics)
+{
+    return 1 + arrayInlineCost(ics, elements);
+}
+
+int FuncExp::inlineCost(InlineCostState *ics)
+{
+    // This breaks on LDC too, since nested functions have internal linkage
+    // and thus can't be referenced from other objects.
+    // Right now, this makes the function be output to the .obj file twice.
+    return COST_MAX;
+}
+
+int DelegateExp::inlineCost(InlineCostState *ics)
+{
+    // This breaks on LDC too, since nested functions have internal linkage
+    // and thus can't be referenced from other objects.
+    return COST_MAX;
+}
+
+int DeclarationExp::inlineCost(InlineCostState *ics)
+{   int cost = 0;
+    VarDeclaration *vd;
+
+    //printf("DeclarationExp::inlineCost()\n");
+    vd = declaration->isVarDeclaration();
+    if (vd)
+    {
+	TupleDeclaration *td = vd->toAlias()->isTupleDeclaration();
+	if (td)
+	{
+#if 1
+	    return COST_MAX;	// finish DeclarationExp::doInline
+#else
+	    for (size_t i = 0; i < td->objects->dim; i++)
+	    {   Object *o = (Object *)td->objects->data[i];
+		if (o->dyncast() != DYNCAST_EXPRESSION)
+		    return COST_MAX;
+		Expression *eo = (Expression *)o;
+		if (eo->op != TOKdsymbol)
+		    return COST_MAX;
+	    }
+	    return td->objects->dim;
+#endif
+	}
+        // This breaks on LDC too, since nested static variables have internal
+        // linkage and thus can't be referenced from other objects.
+	if (!ics->hdrscan && vd->isDataseg())
+	    return COST_MAX;
+	cost += 1;
+
+	// Scan initializer (vd->init)
+	if (vd->init)
+	{
+	    ExpInitializer *ie = vd->init->isExpInitializer();
+
+	    if (ie)
+	    {
+		cost += ie->exp->inlineCost(ics);
+	    }
+	}
+    }
+
+    // These can contain functions, which when copied, get output twice.
+    // These break on LDC too, since nested static variables and functions have
+    // internal linkage and thus can't be referenced from other objects.
+    if (declaration->isStructDeclaration() ||
+	declaration->isClassDeclaration() ||
+	declaration->isFuncDeclaration() ||
+	declaration->isTypedefDeclaration() ||
+	declaration->isTemplateMixin())
+	return COST_MAX;
+
+    //printf("DeclarationExp::inlineCost('%s')\n", toChars());
+    return cost;
+}
+
+int UnaExp::inlineCost(InlineCostState *ics)
+{
+    return 1 + e1->inlineCost(ics);
+}
+
+int AssertExp::inlineCost(InlineCostState *ics)
+{
+    return 1 + e1->inlineCost(ics) + (msg ? msg->inlineCost(ics) : 0);
+}
+
+int BinExp::inlineCost(InlineCostState *ics)
+{
+    return 1 + e1->inlineCost(ics) + e2->inlineCost(ics);
+}
+
+int CallExp::inlineCost(InlineCostState *ics)
+{
+    return 1 + e1->inlineCost(ics) + arrayInlineCost(ics, arguments);
+}
+
+int SliceExp::inlineCost(InlineCostState *ics)
+{   int cost;
+
+    cost = 1 + e1->inlineCost(ics);
+    if (lwr)
+	cost += lwr->inlineCost(ics);
+    if (upr)
+	cost += upr->inlineCost(ics);
+    return cost;
+}
+
+int ArrayExp::inlineCost(InlineCostState *ics)
+{
+    return 1 + e1->inlineCost(ics) + arrayInlineCost(ics, arguments);
+}
+
+
+int CondExp::inlineCost(InlineCostState *ics)
+{
+    return 1 +
+	 e1->inlineCost(ics) +
+	 e2->inlineCost(ics) +
+	 econd->inlineCost(ics);
+}
+
+
+/* ======================== Perform the inlining ============================== */
+
+/* Inlining is done by:
+ * o	Converting to an Expression
+ * o	Copying the trees of the function to be inlined
+ * o	Renaming the variables
+ */
+
+struct InlineDoState
+{
+    VarDeclaration *vthis;
+    Array from;		// old Dsymbols
+    Array to;		// parallel array of new Dsymbols
+    Dsymbol *parent;	// new parent
+};
+
+Expression *Statement::doInline(InlineDoState *ids)
+{
+    assert(0);
+    return NULL;		// default is we can't inline it
+}
+
+Expression *ExpStatement::doInline(InlineDoState *ids)
+{
+#if LOG
+    if (exp) printf("ExpStatement::doInline() '%s'\n", exp->toChars());
+#endif
+    return exp ? exp->doInline(ids) : NULL;
+}
+
+Expression *CompoundStatement::doInline(InlineDoState *ids)
+{
+    Expression *e = NULL;
+
+    //printf("CompoundStatement::doInline() %d\n", statements->dim);
+    for (size_t i = 0; i < statements->dim; i++)
+    {	Statement *s = (Statement *) statements->data[i];
+	if (s)
+	{
+	    Expression *e2 = s->doInline(ids);
+	    e = Expression::combine(e, e2);
+	    if (s->isReturnStatement())
+		break;
+
+	    /* Check for:
+	     *	if (condition)
+	     *	    return exp1;
+	     *	else
+	     *	    return exp2;
+	     */
+	    IfStatement *ifs = s->isIfStatement();
+	    if (ifs && ifs->elsebody && ifs->ifbody &&
+		ifs->ifbody->isReturnStatement() &&
+		ifs->elsebody->isReturnStatement()
+	       )
+		break;
+
+	}
+    }
+    return e;
+}
+
+Expression *UnrolledLoopStatement::doInline(InlineDoState *ids)
+{
+    Expression *e = NULL;
+
+    //printf("UnrolledLoopStatement::doInline() %d\n", statements->dim);
+    for (size_t i = 0; i < statements->dim; i++)
+    {	Statement *s = (Statement *) statements->data[i];
+	if (s)
+	{
+	    Expression *e2 = s->doInline(ids);
+	    e = Expression::combine(e, e2);
+	    if (s->isReturnStatement())
+		break;
+	}
+    }
+    return e;
+}
+
+Expression *IfStatement::doInline(InlineDoState *ids)
+{
+    Expression *econd;
+    Expression *e1;
+    Expression *e2;
+    Expression *e;
+
+    assert(!arg);
+    econd = condition->doInline(ids);
+    assert(econd);
+    if (ifbody)
+	e1 = ifbody->doInline(ids);
+    else
+	e1 = NULL;
+    if (elsebody)
+	e2 = elsebody->doInline(ids);
+    else
+	e2 = NULL;
+    if (e1 && e2)
+    {
+	e = new CondExp(econd->loc, econd, e1, e2);
+	e->type = e1->type;
+    }
+    else if (e1)
+    {
+	e = new AndAndExp(econd->loc, econd, e1);
+	e->type = Type::tvoid;
+    }
+    else if (e2)
+    {
+	e = new OrOrExp(econd->loc, econd, e2);
+	e->type = Type::tvoid;
+    }
+    else
+    {
+	e = econd;
+    }
+    return e;
+}
+
+Expression *ReturnStatement::doInline(InlineDoState *ids)
+{
+    //printf("ReturnStatement::doInline() '%s'\n", exp ? exp->toChars() : "");
+    return exp ? exp->doInline(ids) : 0;
+}
+
+/* --------------------------------------------------------------- */
+
+/******************************
+ * Perform doInline() on an array of Expressions.
+ */
+
+Expressions *arrayExpressiondoInline(Expressions *a, InlineDoState *ids)
+{   Expressions *newa = NULL;
+
+    if (a)
+    {
+	newa = new Expressions();
+	newa->setDim(a->dim);
+
+	for (int i = 0; i < a->dim; i++)
+	{   Expression *e = (Expression *)a->data[i];
+
+	    if (e)
+	    {
+		e = e->doInline(ids);
+		newa->data[i] = (void *)e;
+	    }
+	}
+    }
+    return newa;
+}
+
+Expression *Expression::doInline(InlineDoState *ids)
+{
+    //printf("Expression::doInline(%s): %s\n", Token::toChars(op), toChars());
+    return copy();
+}
+
+Expression *SymOffExp::doInline(InlineDoState *ids)
+{
+    int i;
+
+    //printf("SymOffExp::doInline(%s)\n", toChars());
+    for (i = 0; i < ids->from.dim; i++)
+    {
+	if (var == (Declaration *)ids->from.data[i])
+	{
+	    SymOffExp *se = (SymOffExp *)copy();
+
+	    se->var = (Declaration *)ids->to.data[i];
+	    return se;
+	}
+    }
+    return this;
+}
+
+Expression *VarExp::doInline(InlineDoState *ids)
+{
+    int i;
+
+    //printf("VarExp::doInline(%s)\n", toChars());
+    for (i = 0; i < ids->from.dim; i++)
+    {
+	if (var == (Declaration *)ids->from.data[i])
+	{
+	    VarExp *ve = (VarExp *)copy();
+
+	    ve->var = (Declaration *)ids->to.data[i];
+	    return ve;
+	}
+    }
+    return this;
+}
+
+Expression *ThisExp::doInline(InlineDoState *ids)
+{
+    //if (!ids->vthis)
+	//error("no 'this' when inlining %s", ids->parent->toChars());
+    if (!ids->vthis)
+    {
+	return this;
+    }
+
+    VarExp *ve = new VarExp(loc, ids->vthis);
+    ve->type = type;
+    return ve;
+}
+
+Expression *SuperExp::doInline(InlineDoState *ids)
+{
+    assert(ids->vthis);
+
+    VarExp *ve = new VarExp(loc, ids->vthis);
+    ve->type = type;
+    return ve;
+}
+
+Expression *DeclarationExp::doInline(InlineDoState *ids)
+{   DeclarationExp *de = (DeclarationExp *)copy();
+    VarDeclaration *vd;
+
+    //printf("DeclarationExp::doInline(%s)\n", toChars());
+    vd = declaration->isVarDeclaration();
+    if (vd)
+    {
+#if 0
+	// Need to figure this out before inlining can work for tuples
+	TupleDeclaration *td = vd->toAlias()->isTupleDeclaration();
+	if (td)
+	{
+	    for (size_t i = 0; i < td->objects->dim; i++)
+	    {   DsymbolExp *se = (DsymbolExp *)td->objects->data[i];
+		assert(se->op == TOKdsymbol);
+		se->s;
+	    }
+	    return st->objects->dim;
+	}
+#endif
+	if (vd->isStatic() || vd->isConst())
+	    ;
+	else
+	{
+	    VarDeclaration *vto;
+
+	    vto = new VarDeclaration(vd->loc, vd->type, vd->ident, vd->init);
+	    *vto = *vd;
+	    vto->parent = ids->parent;
+#if IN_DMD
+	    vto->csym = NULL;
+	    vto->isym = NULL;
+#endif
+
+	    ids->from.push(vd);
+	    ids->to.push(vto);
+
+	    if (vd->init)
+	    {
+		if (vd->init->isVoidInitializer())
+		{
+		    vto->init = new VoidInitializer(vd->init->loc);
+		}
+		else
+		{
+		    ExpInitializer *ie = vd->init->isExpInitializer();
+		    assert(ie);
+		    vto->init = new ExpInitializer(ie->loc, ie->exp->doInline(ids));
+		}
+	    }
+	    de->declaration = (Dsymbol *) (void *)vto;
+	}
+    }
+    /* This needs work, like DeclarationExp::toElem(), if we are
+     * to handle TemplateMixin's. For now, we just don't inline them.
+     */
+    return de;
+}
+
+Expression *NewExp::doInline(InlineDoState *ids)
+{
+    //printf("NewExp::doInline(): %s\n", toChars());
+    NewExp *ne = (NewExp *)copy();
+
+    if (thisexp)
+	ne->thisexp = thisexp->doInline(ids);
+    ne->newargs = arrayExpressiondoInline(ne->newargs, ids);
+    ne->arguments = arrayExpressiondoInline(ne->arguments, ids);
+    return ne;
+}
+
+Expression *UnaExp::doInline(InlineDoState *ids)
+{
+    UnaExp *ue = (UnaExp *)copy();
+
+    ue->e1 = e1->doInline(ids);
+    return ue;
+}
+
+Expression *AssertExp::doInline(InlineDoState *ids)
+{
+    AssertExp *ae = (AssertExp *)copy();
+
+    ae->e1 = e1->doInline(ids);
+    if (msg)
+	ae->msg = msg->doInline(ids);
+    return ae;
+}
+
+Expression *BinExp::doInline(InlineDoState *ids)
+{
+    BinExp *be = (BinExp *)copy();
+
+    be->e1 = e1->doInline(ids);
+    be->e2 = e2->doInline(ids);
+    return be;
+}
+
+Expression *CallExp::doInline(InlineDoState *ids)
+{
+    CallExp *ce;
+
+    ce = (CallExp *)copy();
+    ce->e1 = e1->doInline(ids);
+    ce->arguments = arrayExpressiondoInline(arguments, ids);
+    return ce;
+}
+
+
+Expression *IndexExp::doInline(InlineDoState *ids)
+{
+    IndexExp *are = (IndexExp *)copy();
+
+    are->e1 = e1->doInline(ids);
+
+    if (lengthVar)
+    {	//printf("lengthVar\n");
+	VarDeclaration *vd = lengthVar;
+	ExpInitializer *ie;
+	ExpInitializer *ieto;
+	VarDeclaration *vto;
+
+	vto = new VarDeclaration(vd->loc, vd->type, vd->ident, vd->init);
+	*vto = *vd;
+	vto->parent = ids->parent;
+#if IN_DMD
+	vto->csym = NULL;
+	vto->isym = NULL;
+#endif
+
+	ids->from.push(vd);
+	ids->to.push(vto);
+
+	if (vd->init)
+	{
+	    ie = vd->init->isExpInitializer();
+	    assert(ie);
+	    ieto = new ExpInitializer(ie->loc, ie->exp->doInline(ids));
+	    vto->init = ieto;
+	}
+
+	are->lengthVar = (VarDeclaration *) (void *)vto;
+    }
+    are->e2 = e2->doInline(ids);
+    return are;
+}
+
+
+Expression *SliceExp::doInline(InlineDoState *ids)
+{
+    SliceExp *are = (SliceExp *)copy();
+
+    are->e1 = e1->doInline(ids);
+
+    if (lengthVar)
+    {	//printf("lengthVar\n");
+	VarDeclaration *vd = lengthVar;
+	ExpInitializer *ie;
+	ExpInitializer *ieto;
+	VarDeclaration *vto;
+
+	vto = new VarDeclaration(vd->loc, vd->type, vd->ident, vd->init);
+	*vto = *vd;
+	vto->parent = ids->parent;
+#if IN_DMD
+	vto->csym = NULL;
+	vto->isym = NULL;
+#endif
+
+	ids->from.push(vd);
+	ids->to.push(vto);
+
+	if (vd->init)
+	{
+	    ie = vd->init->isExpInitializer();
+	    assert(ie);
+	    ieto = new ExpInitializer(ie->loc, ie->exp->doInline(ids));
+	    vto->init = ieto;
+	}
+
+	are->lengthVar = (VarDeclaration *) (void *)vto;
+    }
+    if (lwr)
+	are->lwr = lwr->doInline(ids);
+    if (upr)
+	are->upr = upr->doInline(ids);
+    return are;
+}
+
+
+Expression *TupleExp::doInline(InlineDoState *ids)
+{
+    TupleExp *ce;
+
+    ce = (TupleExp *)copy();
+    ce->exps = arrayExpressiondoInline(exps, ids);
+    return ce;
+}
+
+
+Expression *ArrayLiteralExp::doInline(InlineDoState *ids)
+{
+    ArrayLiteralExp *ce;
+
+    ce = (ArrayLiteralExp *)copy();
+    ce->elements = arrayExpressiondoInline(elements, ids);
+    return ce;
+}
+
+
+Expression *AssocArrayLiteralExp::doInline(InlineDoState *ids)
+{
+    AssocArrayLiteralExp *ce;
+
+    ce = (AssocArrayLiteralExp *)copy();
+    ce->keys = arrayExpressiondoInline(keys, ids);
+    ce->values = arrayExpressiondoInline(values, ids);
+    return ce;
+}
+
+
+Expression *StructLiteralExp::doInline(InlineDoState *ids)
+{
+    StructLiteralExp *ce;
+
+    ce = (StructLiteralExp *)copy();
+    ce->elements = arrayExpressiondoInline(elements, ids);
+    return ce;
+}
+
+
+Expression *ArrayExp::doInline(InlineDoState *ids)
+{
+    ArrayExp *ce;
+
+    ce = (ArrayExp *)copy();
+    ce->e1 = e1->doInline(ids);
+    ce->arguments = arrayExpressiondoInline(arguments, ids);
+    return ce;
+}
+
+
+Expression *CondExp::doInline(InlineDoState *ids)
+{
+    CondExp *ce = (CondExp *)copy();
+
+    ce->econd = econd->doInline(ids);
+    ce->e1 = e1->doInline(ids);
+    ce->e2 = e2->doInline(ids);
+    return ce;
+}
+
+
+/* ========== Walk the parse trees, and inline expand functions ============= */
+
+/* Walk the trees, looking for functions to inline.
+ * Inline any that can be.
+ */
+
+struct InlineScanState
+{
+    FuncDeclaration *fd;	// function being scanned
+};
+
+Statement *Statement::inlineScan(InlineScanState *iss)
+{
+    return this;
+}
+
+Statement *ExpStatement::inlineScan(InlineScanState *iss)
+{
+#if LOG
+    printf("ExpStatement::inlineScan(%s)\n", toChars());
+#endif
+    if (exp)
+	exp = exp->inlineScan(iss);
+    return this;
+}
+
+Statement *CompoundStatement::inlineScan(InlineScanState *iss)
+{
+    for (size_t i = 0; i < statements->dim; i++)
+    {	Statement *s = (Statement *) statements->data[i];
+	if (s)
+	    statements->data[i] = (void *)s->inlineScan(iss);
+    }
+    return this;
+}
+
+Statement *UnrolledLoopStatement::inlineScan(InlineScanState *iss)
+{
+    for (size_t i = 0; i < statements->dim; i++)
+    {	Statement *s = (Statement *) statements->data[i];
+	if (s)
+	    statements->data[i] = (void *)s->inlineScan(iss);
+    }
+    return this;
+}
+
+Statement *ScopeStatement::inlineScan(InlineScanState *iss)
+{
+    if (statement)
+	statement = statement->inlineScan(iss);
+    return this;
+}
+
+Statement *WhileStatement::inlineScan(InlineScanState *iss)
+{
+    condition = condition->inlineScan(iss);
+    body = body ? body->inlineScan(iss) : NULL;
+    return this;
+}
+
+
+Statement *DoStatement::inlineScan(InlineScanState *iss)
+{
+    body = body ? body->inlineScan(iss) : NULL;
+    condition = condition->inlineScan(iss);
+    return this;
+}
+
+
+Statement *ForStatement::inlineScan(InlineScanState *iss)
+{
+    if (init)
+	init = init->inlineScan(iss);
+    if (condition)
+	condition = condition->inlineScan(iss);
+    if (increment)
+	increment = increment->inlineScan(iss);
+    if (body)
+	body = body->inlineScan(iss);
+    return this;
+}
+
+
+Statement *ForeachStatement::inlineScan(InlineScanState *iss)
+{
+    aggr = aggr->inlineScan(iss);
+    if (body)
+	body = body->inlineScan(iss);
+    return this;
+}
+
+
+#if DMDV2
+Statement *ForeachRangeStatement::inlineScan(InlineScanState *iss)
+{
+    lwr = lwr->inlineScan(iss);
+    upr = upr->inlineScan(iss);
+    if (body)
+	body = body->inlineScan(iss);
+    return this;
+}
+#endif
+
+
+Statement *IfStatement::inlineScan(InlineScanState *iss)
+{
+    condition = condition->inlineScan(iss);
+    if (ifbody)
+	ifbody = ifbody->inlineScan(iss);
+    if (elsebody)
+	elsebody = elsebody->inlineScan(iss);
+    return this;
+}
+
+
+Statement *SwitchStatement::inlineScan(InlineScanState *iss)
+{
+    //printf("SwitchStatement::inlineScan()\n");
+    condition = condition->inlineScan(iss);
+    body = body ? body->inlineScan(iss) : NULL;
+    if (sdefault)
+	sdefault = (DefaultStatement *)sdefault->inlineScan(iss);
+    if (cases)
+    {
+	for (int i = 0; i < cases->dim; i++)
+	{   Statement *s;
+
+	    s = (Statement *) cases->data[i];
+	    cases->data[i] = (void *)s->inlineScan(iss);
+	}
+    }
+    return this;
+}
+
+
+Statement *CaseStatement::inlineScan(InlineScanState *iss)
+{
+    //printf("CaseStatement::inlineScan()\n");
+    exp = exp->inlineScan(iss);
+    if (statement)
+	statement = statement->inlineScan(iss);
+    return this;
+}
+
+
+Statement *DefaultStatement::inlineScan(InlineScanState *iss)
+{
+    if (statement)
+	statement = statement->inlineScan(iss);
+    return this;
+}
+
+
+Statement *ReturnStatement::inlineScan(InlineScanState *iss)
+{
+    //printf("ReturnStatement::inlineScan()\n");
+    if (exp)
+    {
+	exp = exp->inlineScan(iss);
+    }
+    return this;
+}
+
+
+Statement *SynchronizedStatement::inlineScan(InlineScanState *iss)
+{
+    if (exp)
+	exp = exp->inlineScan(iss);
+    if (body)
+	body = body->inlineScan(iss);
+    return this;
+}
+
+
+Statement *WithStatement::inlineScan(InlineScanState *iss)
+{
+    if (exp)
+	exp = exp->inlineScan(iss);
+    if (body)
+	body = body->inlineScan(iss);
+    return this;
+}
+
+
+Statement *TryCatchStatement::inlineScan(InlineScanState *iss)
+{
+    if (body)
+	body = body->inlineScan(iss);
+    if (catches)
+    {
+	for (int i = 0; i < catches->dim; i++)
+	{   Catch *c = (Catch *)catches->data[i];
+
+	    if (c->handler)
+		c->handler = c->handler->inlineScan(iss);
+	}
+    }
+    return this;
+}
+
+
+Statement *TryFinallyStatement::inlineScan(InlineScanState *iss)
+{
+    if (body)
+	body = body->inlineScan(iss);
+    if (finalbody)
+	finalbody = finalbody->inlineScan(iss);
+    return this;
+}
+
+
+Statement *ThrowStatement::inlineScan(InlineScanState *iss)
+{
+    if (exp)
+	exp = exp->inlineScan(iss);
+    return this;
+}
+
+
+Statement *VolatileStatement::inlineScan(InlineScanState *iss)
+{
+    if (statement)
+	statement = statement->inlineScan(iss);
+    return this;
+}
+
+
+Statement *LabelStatement::inlineScan(InlineScanState *iss)
+{
+    if (statement)
+	statement = statement->inlineScan(iss);
+    return this;
+}
+
+/* -------------------------- */
+
+void arrayInlineScan(InlineScanState *iss, Array *arguments)
+{
+    if (arguments)
+    {
+	for (int i = 0; i < arguments->dim; i++)
+	{   Expression *e = (Expression *)arguments->data[i];
+
+	    if (e)
+	    {
+		e = e->inlineScan(iss);
+		arguments->data[i] = (void *)e;
+	    }
+	}
+    }
+}
+
+Expression *Expression::inlineScan(InlineScanState *iss)
+{
+    return this;
+}
+
+void scanVar(Dsymbol *s, InlineScanState *iss)
+{
+    VarDeclaration *vd = s->isVarDeclaration();
+    if (vd)
+    {
+	TupleDeclaration *td = vd->toAlias()->isTupleDeclaration();
+	if (td)
+	{
+	    for (size_t i = 0; i < td->objects->dim; i++)
+	    {   DsymbolExp *se = (DsymbolExp *)td->objects->data[i];
+		assert(se->op == TOKdsymbol);
+		scanVar(se->s, iss);
+	    }
+	}
+	else
+	{
+	    // Scan initializer (vd->init)
+	    if (vd->init)
+	    {
+		ExpInitializer *ie = vd->init->isExpInitializer();
+
+		if (ie)
+		{
+#if DMDV2
+		    if (vd->type)
+		    {	Type *tb = vd->type->toBasetype();
+			if (tb->ty == Tstruct)
+			{   StructDeclaration *sd = ((TypeStruct *)tb)->sym;
+			    if (sd->cpctor)
+			    {   /* The problem here is that if the initializer is a
+				 * function call that returns a struct S with a cpctor:
+				 *   S s = foo();
+				 * the postblit is done by the return statement in foo()
+				 * in s2ir.c, the intermediate code generator.
+				 * But, if foo() is inlined and now the code looks like:
+				 *   S s = x;
+				 * the postblit is not there, because such assignments
+				 * are rewritten as s.cpctor(&x) by the front end.
+				 * So, the inlining won't get the postblit called.
+				 * Work around by not inlining these cases.
+				 * A proper fix would be to move all the postblit
+				 * additions to the front end.
+				 */
+				return;
+			    }
+			}
+		    }
+#endif
+		    ie->exp = ie->exp->inlineScan(iss);
+		}
+	    }
+	}
+    }
+}
+
+Expression *DeclarationExp::inlineScan(InlineScanState *iss)
+{
+    //printf("DeclarationExp::inlineScan()\n");
+    scanVar(declaration, iss);
+    return this;
+}
+
+Expression *UnaExp::inlineScan(InlineScanState *iss)
+{
+    e1 = e1->inlineScan(iss);
+    return this;
+}
+
+Expression *AssertExp::inlineScan(InlineScanState *iss)
+{
+    e1 = e1->inlineScan(iss);
+    if (msg)
+	msg = msg->inlineScan(iss);
+    return this;
+}
+
+Expression *BinExp::inlineScan(InlineScanState *iss)
+{
+    e1 = e1->inlineScan(iss);
+    e2 = e2->inlineScan(iss);
+    return this;
+}
+
+
+Expression *CallExp::inlineScan(InlineScanState *iss)
+{   Expression *e = this;
+
+    //printf("CallExp::inlineScan()\n");
+    e1 = e1->inlineScan(iss);
+    arrayInlineScan(iss, arguments);
+
+    if (e1->op == TOKvar)
+    {
+	VarExp *ve = (VarExp *)e1;
+	FuncDeclaration *fd = ve->var->isFuncDeclaration();
+
+	if (fd && fd != iss->fd && fd->canInline(0))
+	{
+	    e = fd->doInline(iss, NULL, arguments);
+	}
+    }
+    else if (e1->op == TOKdotvar)
+    {
+	DotVarExp *dve = (DotVarExp *)e1;
+	FuncDeclaration *fd = dve->var->isFuncDeclaration();
+
+	if (fd && fd != iss->fd && fd->canInline(1))
+	{
+	    if (dve->e1->op == TOKcall &&
+		dve->e1->type->toBasetype()->ty == Tstruct)
+	    {
+		/* To create ethis, we'll need to take the address
+		 * of dve->e1, but this won't work if dve->e1 is
+		 * a function call.
+		 */
+		;
+	    }
+	    else
+		e = fd->doInline(iss, dve->e1, arguments);
+	}
+    }
+
+    return e;
+}
+
+
+Expression *SliceExp::inlineScan(InlineScanState *iss)
+{
+    e1 = e1->inlineScan(iss);
+    if (lwr)
+	lwr = lwr->inlineScan(iss);
+    if (upr)
+	upr = upr->inlineScan(iss);
+    return this;
+}
+
+
+Expression *TupleExp::inlineScan(InlineScanState *iss)
+{   Expression *e = this;
+
+    //printf("TupleExp::inlineScan()\n");
+    arrayInlineScan(iss, exps);
+
+    return e;
+}
+
+
+Expression *ArrayLiteralExp::inlineScan(InlineScanState *iss)
+{   Expression *e = this;
+
+    //printf("ArrayLiteralExp::inlineScan()\n");
+    arrayInlineScan(iss, elements);
+
+    return e;
+}
+
+
+Expression *AssocArrayLiteralExp::inlineScan(InlineScanState *iss)
+{   Expression *e = this;
+
+    //printf("AssocArrayLiteralExp::inlineScan()\n");
+    arrayInlineScan(iss, keys);
+    arrayInlineScan(iss, values);
+
+    return e;
+}
+
+
+Expression *StructLiteralExp::inlineScan(InlineScanState *iss)
+{   Expression *e = this;
+
+    //printf("StructLiteralExp::inlineScan()\n");
+    arrayInlineScan(iss, elements);
+
+    return e;
+}
+
+
+Expression *ArrayExp::inlineScan(InlineScanState *iss)
+{   Expression *e = this;
+
+    //printf("ArrayExp::inlineScan()\n");
+    e1 = e1->inlineScan(iss);
+    arrayInlineScan(iss, arguments);
+
+    return e;
+}
+
+
+Expression *CondExp::inlineScan(InlineScanState *iss)
+{
+    econd = econd->inlineScan(iss);
+    e1 = e1->inlineScan(iss);
+    e2 = e2->inlineScan(iss);
+    return this;
+}
+
+
+/* ==========  =============== */
+
+void FuncDeclaration::inlineScan()
+{
+    InlineScanState iss;
+
+#if LOG
+    printf("FuncDeclaration::inlineScan('%s')\n", toChars());
+#endif
+    memset(&iss, 0, sizeof(iss));
+    iss.fd = this;
+    if (fbody)
+    {
+	inlineNest++;
+	fbody = fbody->inlineScan(&iss);
+	inlineNest--;
+    }
+}
+
+int FuncDeclaration::canInline(int hasthis, int hdrscan)
+{
+    InlineCostState ics;
+    int cost;
+
+#define CANINLINE_LOG 0
+
+#if CANINLINE_LOG
+    printf("FuncDeclaration::canInline(hasthis = %d, '%s')\n", hasthis, toChars());
+#endif
+
+    if (needThis() && !hasthis)
+	return 0;
+
+    if (inlineNest || (semanticRun < 3 && !hdrscan))
+    {
+#if CANINLINE_LOG
+	printf("\t1: no, inlineNest = %d, semanticRun = %d\n", inlineNest, semanticRun);
+#endif
+	return 0;
+    }
+
+    switch (inlineStatus)
+    {
+	case ILSyes:
+#if CANINLINE_LOG
+	    printf("\t1: yes %s\n", toChars());
+#endif
+	    return 1;
+
+	case ILSno:
+#if CANINLINE_LOG
+	    printf("\t1: no %s\n", toChars());
+#endif
+	    return 0;
+
+	case ILSuninitialized:
+	    break;
+
+	default:
+	    assert(0);
+    }
+
+    if (type)
+    {	assert(type->ty == Tfunction);
+	TypeFunction *tf = (TypeFunction *)(type);
+#if IN_LLVM
+        // LDC: Only extern(C) varargs count.
+        if (tf->linkage != LINKd)
+#endif
+	if (tf->varargs == 1)	// no variadic parameter lists
+	    goto Lno;
+
+	/* Don't inline a function that returns non-void, but has
+	 * no return expression.
+	 */
+	if (tf->next && tf->next->ty != Tvoid &&
+	    !(hasReturnExp & 1) &&
+	    !hdrscan)
+	    goto Lno;
+    }
+#if !IN_LLVM
+    // LDC: Only extern(C) varargs count, and ctors use extern(D).
+    else
+    {	CtorDeclaration *ctor = isCtorDeclaration();
+
+	if (ctor && ctor->varargs == 1)
+	    goto Lno;
+    }
+#endif
+
+    if (
+	!fbody ||
+	!hdrscan &&
+	(
+#if 0
+	isCtorDeclaration() ||	// cannot because need to convert:
+				//	return;
+				// to:
+				//	return this;
+#endif
+	isSynchronized() ||
+	isImportedSymbol() ||
+#if !IN_LLVM
+#if DMDV2
+	closureVars.dim ||	// no nested references to this frame
+#else
+	nestedFrameRef ||	// no nested references to this frame
+#endif
+#endif // !IN_LLVM
+	(isVirtual() && !isFinal())
+       ))
+    {
+	goto Lno;
+    }
+
+#if !IN_LLVM
+    /* If any parameters are Tsarray's (which are passed by reference)
+     * or out parameters (also passed by reference), don't do inlining.
+     */
+    if (parameters)
+    {
+	for (int i = 0; i < parameters->dim; i++)
+	{
+	    VarDeclaration *v = (VarDeclaration *)parameters->data[i];
+	    if (v->isOut() || v->isRef() || v->type->toBasetype()->ty == Tsarray)
+		goto Lno;
+	}
+    }
+#endif
+
+    memset(&ics, 0, sizeof(ics));
+    ics.hasthis = hasthis;
+    ics.fd = this;
+    ics.hdrscan = hdrscan;
+    cost = fbody->inlineCost(&ics);
+#if CANINLINE_LOG
+    printf("cost = %d\n", cost);
+#endif
+    if (cost >= COST_MAX)
+	goto Lno;
+
+#if !IN_LLVM
+    if (!hdrscan)    // Don't scan recursively for header content scan
+	inlineScan();
+#endif
+
+Lyes:
+    if (!hdrscan)    // Don't modify inlineStatus for header content scan
+	inlineStatus = ILSyes;
+#if CANINLINE_LOG
+    printf("\t2: yes %s\n", toChars());
+#endif
+    return 1;
+
+Lno:
+    if (!hdrscan)    // Don't modify inlineStatus for header content scan
+	inlineStatus = ILSno;
+#if CANINLINE_LOG
+    printf("\t2: no %s\n", toChars());
+#endif
+    return 0;
+}
+
+Expression *FuncDeclaration::doInline(InlineScanState *iss, Expression *ethis, Array *arguments)
+{
+    InlineDoState ids;
+    DeclarationExp *de;
+    Expression *e = NULL;
+
+#if LOG
+    printf("FuncDeclaration::doInline('%s')\n", toChars());
+#endif
+
+    memset(&ids, 0, sizeof(ids));
+    ids.parent = iss->fd;
+
+    // Set up vthis
+    if (ethis)
+    {
+	VarDeclaration *vthis;
+	ExpInitializer *ei;
+	VarExp *ve;
+
+#if STRUCTTHISREF
+	if (ethis->type->ty == Tpointer)
+	{   Type *t = ethis->type->nextOf();
+	    ethis = new PtrExp(ethis->loc, ethis);
+	    ethis->type = t;
+	}
+	ei = new ExpInitializer(ethis->loc, ethis);
+
+	vthis = new VarDeclaration(ethis->loc, ethis->type, Id::This, ei);
+	if (ethis->type->ty != Tclass)
+	    vthis->storage_class = STCref;
+	else
+	    vthis->storage_class = STCin;
+#else
+	if (ethis->type->ty != Tclass && ethis->type->ty != Tpointer)
+	{
+	    ethis = ethis->addressOf(NULL);
+	}
+
+	ei = new ExpInitializer(ethis->loc, ethis);
+
+	vthis = new VarDeclaration(ethis->loc, ethis->type, Id::This, ei);
+	vthis->storage_class = STCin;
+#endif
+	vthis->linkage = LINKd;
+	vthis->parent = iss->fd;
+
+	ve = new VarExp(vthis->loc, vthis);
+	ve->type = vthis->type;
+
+	ei->exp = new AssignExp(vthis->loc, ve, ethis);
+	ei->exp->type = ve->type;
+#if STRUCTTHISREF
+	if (ethis->type->ty != Tclass)
+	{   /* This is a reference initialization, not a simple assignment.
+	     */
+	    ei->exp->op = TOKconstruct;
+	}
+#endif
+
+	ids.vthis = vthis;
+    }
+
+    // Set up parameters
+    if (ethis)
+    {
+	e = new DeclarationExp(0, ids.vthis);
+	e->type = Type::tvoid;
+    }
+
+    if (arguments && arguments->dim)
+    {
+	assert(parameters->dim == arguments->dim);
+
+	for (int i = 0; i < arguments->dim; i++)
+	{
+	    VarDeclaration *vfrom = (VarDeclaration *)parameters->data[i];
+	    VarDeclaration *vto;
+	    Expression *arg = (Expression *)arguments->data[i];
+	    ExpInitializer *ei;
+	    VarExp *ve;
+
+	    ei = new ExpInitializer(arg->loc, arg);
+
+	    vto = new VarDeclaration(vfrom->loc, vfrom->type, vfrom->ident, ei);
+	    vto->storage_class |= vfrom->storage_class & (STCin | STCout | STClazy | STCref);
+	    vto->linkage = vfrom->linkage;
+	    vto->parent = iss->fd;
+	    //printf("vto = '%s', vto->storage_class = x%x\n", vto->toChars(), vto->storage_class);
+	    //printf("vto->parent = '%s'\n", iss->fd->toChars());
+
+	    ve = new VarExp(vto->loc, vto);
+	    //ve->type = vto->type;
+	    ve->type = arg->type;
+
+	    ei->exp = new AssignExp(vto->loc, ve, arg);
+	    ei->exp->type = ve->type;
+//ve->type->print();
+//arg->type->print();
+//ei->exp->print();
+
+	    ids.from.push(vfrom);
+	    ids.to.push(vto);
+
+	    de = new DeclarationExp(0, vto);
+	    de->type = Type::tvoid;
+
+	    e = Expression::combine(e, de);
+	}
+    }
+
+    inlineNest++;
+    Expression *eb = fbody->doInline(&ids);
+    inlineNest--;
+//eb->type->print();
+//eb->print();
+//eb->dump(0);
+    return Expression::combine(e, eb);
+}
+
+
+
--- a/dmd/interpret.c	Fri Nov 06 21:51:41 2009 +0100
+++ b/dmd/interpret.c	Fri Nov 06 23:58:01 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
@@ -34,6 +34,7 @@
     Dsymbols vars;		// variables used in this function
     Statement *start;		// if !=NULL, start execution at this statement
     Statement *gotoTarget;	// target of EXP_GOTO_INTERPRET result
+    Expression *localThis;	// value of 'this', or NULL if none
 
     InterState();
 };
@@ -50,11 +51,14 @@
 /*************************************
  * Attempt to interpret a function given the arguments.
  * Input:
- *	istate	state for calling function (NULL if none)
+ *	istate     state for calling function (NULL if none)
+ *      arguments  function arguments
+ *      thisarg    'this', if a needThis() function, NULL if not.	
+ *
  * Return result expression if successful, NULL if not.
  */
 
-Expression *FuncDeclaration::interpret(InterState *istate, Expressions *arguments)
+Expression *FuncDeclaration::interpret(InterState *istate, Expressions *arguments, Expression *thisarg)
 {
 #if LOG
     printf("\n********\nFuncDeclaration::interpret(istate = %p) %s\n", istate, toChars());
@@ -72,7 +76,7 @@
     if (cantInterpret || semanticRun == 3)
 	return NULL;
 
-    if (needThis() || isNested() || !fbody)
+    if (!fbody)
     {	cantInterpret = 1;
 	return NULL;
     }
@@ -90,11 +94,13 @@
     assert(tb->ty == Tfunction);
     TypeFunction *tf = (TypeFunction *)tb;
     Type *tret = tf->next->toBasetype();
-    if (tf->varargs /*|| tret->ty == Tvoid*/)
+    if (tf->varargs)
     {	cantInterpret = 1;
+	error("Variadic functions are not yet implemented in CTFE");
 	return NULL;
     }
-
+    
+    // Ensure there are no lazy parameters
     if (tf->parameters)
     {	size_t dim = Argument::dim(tf->parameters);
 	for (size_t i = 0; i < dim; i++)
@@ -109,13 +115,20 @@
     InterState istatex;
     istatex.caller = istate;
     istatex.fd = this;
+    istatex.localThis = thisarg;
 
     Expressions vsave;		// place to save previous parameter values
     size_t dim = 0;
+    if (needThis() && !thisarg)
+    {	cantInterpret = 1;
+	// error, no this. Prevent segfault.
+	error("need 'this' to access member %s", toChars());
+	return NULL;
+    }
     if (arguments)
     {
 	dim = arguments->dim;
-	assert(!dim || parameters->dim == dim);
+	assert(!dim || (parameters && (parameters->dim == dim)));
 	vsave.setDim(dim);
 
 	/* Evaluate all the arguments to the function,
@@ -144,7 +157,9 @@
 		}
 		earg = earg->interpret(istate ? istate : &istatex);
 		if (earg == EXP_CANT_INTERPRET)
+		{   cantInterpret = 1;
 		    return NULL;
+		}
 	    }
 	    eargs.data[i] = earg;
 	}
@@ -157,23 +172,39 @@
 #if LOG
 	    printf("arg[%d] = %s\n", i, earg->toChars());
 #endif
-	    if (arg->storageClass & (STCout | STCref))
+	    if (arg->storageClass & (STCout | STCref) && earg->op==TOKvar)
 	    {
 		/* Bind out or ref parameter to the corresponding
 		 * variable v2
 		 */
-		if (!istate || earg->op != TOKvar)
+		if (!istate)
+		{   cantInterpret = 1;
+		    error("%s cannot be by passed by reference at compile time", earg->toChars());
 		    return NULL;	// can't bind to non-interpreted vars
-
+		}		
+		// We need to chase down all of the the passed parameters until
+		// we find something that isn't a TOKvar, then create a variable
+		// containg that expression.
 		VarDeclaration *v2;
 		while (1)
 		{
 		    VarExp *ve = (VarExp *)earg;
 		    v2 = ve->var->isVarDeclaration();
 		    if (!v2)
+		    {   cantInterpret = 1;
 			return NULL;
+		    }
 		    if (!v2->value || v2->value->op != TOKvar)
 			break;
+//TODO
+#ifdef IN_DMD
+		    if (((VarExp *)v2->value)->var->isSymbolDeclaration())
+		    {	// This can happen if v is a struct initialized to
+			// 0 using an __initZ SymbolDeclaration from
+			// TypeStruct::defaultInit()
+			break; // eg default-initialized variable
+		    }
+#endif
 		    earg = v2->value;
 		}
 
@@ -191,8 +222,7 @@
 		}
 	    }
 	    else
-	    {	/* Value parameters
-		 */
+	    {	// Value parameters and non-trivial references
 		v->value = earg;
 	    }
 #if LOG
@@ -200,11 +230,22 @@
 #endif
 	}
     }
+    // Don't restore the value of 'this' upon function return
+    if (needThis() && thisarg->op==TOKvar) {
+	VarDeclaration *thisvar = ((VarExp *)(thisarg))->var->isVarDeclaration();
+    	for (size_t i = 0; i < istate->vars.dim; i++)
+	{   VarDeclaration *v = (VarDeclaration *)istate->vars.data[i];
+	    if (v == thisvar)
+	    {	istate->vars.data[i] = NULL;
+		break;
+	    }
+	}
+    }
 
     /* Save the values of the local variables used
      */
     Expressions valueSaves;
-    if (istate)
+    if (istate && !isNested())
     {
 	//printf("saving local variables...\n");
 	valueSaves.setDim(istate->vars.dim);
@@ -220,7 +261,6 @@
     }
 
     Expression *e = NULL;
-
     while (1)
     {
 	e = fbody->interpret(&istatex);
@@ -246,7 +286,6 @@
 	else
 	    break;
     }
-
     /* Restore the parameter values
      */
     for (size_t i = 0; i < dim; i++)
@@ -255,7 +294,7 @@
 	v->value = (Expression *)vsave.data[i];
     }
 
-    if (istate)
+    if (istate && !isNested())
     {
 	/* Restore the variable values
 	 */
@@ -268,7 +307,6 @@
 	    }
 	}
     }
-
     return e;
 }
 
@@ -478,7 +516,7 @@
 	    return e;
 	if (e == EXP_BREAK_INTERPRET)
 	    return NULL;
-	if (e != EXP_CONTINUE_INTERPRET)
+	if (e && e != EXP_CONTINUE_INTERPRET)
 	    return e;
     }
 
@@ -758,7 +796,7 @@
 
 	while (1)
 	{
-	    e = Cmp(TOKlt, key->value->type, key->value, upr);
+	    e = Cmp(TOKlt, key->value->type, key->value, eupr);
 	    if (e == EXP_CANT_INTERPRET)
 		break;
 	    if (e->isBool(TRUE) == FALSE)
@@ -773,19 +811,23 @@
 	    {   e = NULL;
 		break;
 	    }
-	    e = Add(key->value->type, key->value, new IntegerExp(loc, 1, key->value->type));
-	    if (e == EXP_CANT_INTERPRET)
+	    if (e == NULL || e == EXP_CONTINUE_INTERPRET)
+	    {	e = Add(key->value->type, key->value, new IntegerExp(loc, 1, key->value->type));
+		if (e == EXP_CANT_INTERPRET)
+		    break;
+		key->value = e;
+	    }
+	    else
 		break;
-	    key->value = e;
 	}
     }
     else // TOKforeach_reverse
     {
 	key->value = eupr;
 
-	while (1)
+	do
 	{
-	    e = Cmp(TOKgt, key->value->type, key->value, lwr);
+	    e = Cmp(TOKgt, key->value->type, key->value, elwr);
 	    if (e == EXP_CANT_INTERPRET)
 		break;
 	    if (e->isBool(TRUE) == FALSE)
@@ -805,7 +847,7 @@
 	    {   e = NULL;
 		break;
 	    }
-	}
+	} while (e == NULL || e == EXP_CONTINUE_INTERPRET);
     }
     key->value = keysave;
     return e;
@@ -946,6 +988,14 @@
     printf("type = %s\n", type->toChars());
     dump(0);
 #endif
+    error("Cannot interpret %s at compile time", toChars());
+    return EXP_CANT_INTERPRET;
+}
+
+Expression *ThisExp::interpret(InterState *istate)
+{
+    if (istate->localThis)
+        return istate->localThis->interpret(istate);
     return EXP_CANT_INTERPRET;
 }
 
@@ -991,7 +1041,7 @@
     if (v)
     {
 #if DMDV2
-	if ((v->isConst() || v->isInvariant()) && v->init && !v->value)
+	if ((v->isConst() || v->isInvariant() || v->storage_class & STCmanifest) && v->init && !v->value)
 #else
 	if (v->isConst() && v->init)
 #endif
@@ -1001,7 +1051,11 @@
 	}
 	else
 	{   e = v->value;
-	    if (!e)
+	    if (v->isDataseg())
+	    {	error(loc, "static variable %s cannot be read at compile time", v->toChars());
+		e = EXP_CANT_INTERPRET;
+	    }
+	    else if (!e)
 		error(loc, "variable %s is used before initialization", v->toChars());
 	    else if (e != EXP_CANT_INTERPRET)
 		e = e->interpret(istate);
@@ -1060,6 +1114,8 @@
 	     declaration->isTemplateMixin() ||
 	     declaration->isTupleDeclaration())
     {	// These can be made to work, too lazy now
+    error("Declaration %s is not yet implemented in CTFE", toChars());
+
 	e = EXP_CANT_INTERPRET;
     }
     else
@@ -1067,7 +1123,7 @@
 	e = NULL;
     }
 #if LOG
-    printf("-DeclarationExp::interpret(): %p\n", e);
+    printf("-DeclarationExp::interpret(%s): %p\n", toChars(), e);
 #endif
     return e;
 }
@@ -1257,7 +1313,9 @@
     /* We don't know how to deal with overlapping fields
      */
     if (sd->hasUnions)
-	return EXP_CANT_INTERPRET;
+	{   error("Unions with overlapping fields are not yet supported in CTFE");
+		return EXP_CANT_INTERPRET;
+    }
 
     if (elements)
     {
@@ -1429,6 +1487,98 @@
 BIN_INTERPRET2(Identity)
 BIN_INTERPRET2(Cmp)
 
+/* Helper functions for BinExp::interpretAssignCommon
+ */
+
+/***************************************
+ * Duplicate the elements array, then set field 'indexToChange' = newelem.
+ */
+Expressions *changeOneElement(Expressions *oldelems, size_t indexToChange, void *newelem)
+{
+    Expressions *expsx = new Expressions();
+    expsx->setDim(oldelems->dim);
+    for (size_t j = 0; j < expsx->dim; j++)
+    {
+	if (j == indexToChange)
+	    expsx->data[j] = newelem;
+	else
+	    expsx->data[j] = oldelems->data[j];
+    }
+    return expsx;
+}
+
+/***************************************
+ * Returns oldelems[0..insertpoint] ~ newelems ~ oldelems[insertpoint..$]
+ */
+Expressions *spliceElements(Expressions *oldelems,
+	Expressions *newelems, size_t insertpoint)
+{
+    Expressions *expsx = new Expressions();
+    expsx->setDim(oldelems->dim);
+    for (size_t j = 0; j < expsx->dim; j++)
+    {
+	if (j >= insertpoint && j < insertpoint + newelems->dim)
+	    expsx->data[j] = newelems->data[j - insertpoint];
+	else
+	    expsx->data[j] = oldelems->data[j];
+    }
+    return expsx;
+}
+
+/******************************
+ * Create an array literal consisting of 'elem' duplicated 'dim' times.
+ */
+ArrayLiteralExp *createBlockDuplicatedArrayLiteral(Type *type,
+	Expression *elem, size_t dim)
+{
+    Expressions *elements = new Expressions();
+    elements->setDim(dim);
+    for (size_t i = 0; i < dim; i++)
+	 elements->data[i] = elem;	
+    ArrayLiteralExp *ae = new ArrayLiteralExp(0, elements);
+    ae->type = type;
+    return ae;
+}
+
+
+/********************************
+ * Necessary because defaultInit() for a struct is a VarExp, not a StructLiteralExp.
+ */
+StructLiteralExp *createDefaultInitStructLiteral(Loc loc, StructDeclaration *sym)
+{
+    Expressions *structelems = new Expressions();
+    structelems->setDim(sym->fields.dim);
+    for (size_t j = 0; j < structelems->dim; j++)
+    {
+	structelems->data[j] = ((VarDeclaration *)(sym->fields.data[j]))->type->defaultInit();
+    }
+    StructLiteralExp *structinit = new StructLiteralExp(loc, sym, structelems);
+    // Why doesn't the StructLiteralExp constructor do this, when
+    // sym->type != NULL ?
+    structinit->type = sym->type;
+    return structinit;
+}
+
+/********************************
+ *  Add v to the istate list, unless it already exists there.
+ */
+void addVarToInterstate(InterState *istate, VarDeclaration *v)
+{
+    if (!v->isParameter())
+    {
+	for (size_t i = 0; 1; i++)
+	{
+	    if (i == istate->vars.dim)
+	    {   istate->vars.push(v);
+		//printf("\tadding %s to istate\n", v->toChars());
+		break;
+	    }
+	    if (v == (VarDeclaration *)istate->vars.data[i])
+		break;
+	}
+    }
+}
+
 Expression *BinExp::interpretAssignCommon(InterState *istate, fp_t fp, int post)
 {
 #if LOG
@@ -1449,7 +1599,43 @@
     Expression *e2 = this->e2->interpret(istate);
     if (e2 == EXP_CANT_INTERPRET)
 	return e2;
+	
+    // Chase down rebinding of out and ref.
+    if (e1->op == TOKvar)
+    {
+	VarExp *ve = (VarExp *)e1;
+	VarDeclaration *v = ve->var->isVarDeclaration();
+	if (v && v->value && v->value->op == TOKvar)
+	{
+	    VarExp *ve2 = (VarExp *)v->value;
+//TODO
+#ifdef IN_DMD
+	    if (ve2->var->isSymbolDeclaration())
+	    {	// This can happen if v is a struct initialized to
+		// 0 using an __initZ SymbolDeclaration from
+		// TypeStruct::defaultInit()
+	    }
+	    else
+#endif
+		e1 = v->value;
+	}
+	else if (v && v->value && (v->value->op==TOKindex || v->value->op == TOKdotvar))
+	{
+            // It is no longer be a TOKvar, eg when a[4] is passed by ref.
+	    e1 = v->value;	    
+	}
+    }
 
+    // To reduce code complexity of handling dotvar expressions,
+    // extract the aggregate now.
+    Expression *aggregate;
+    if (e1->op == TOKdotvar) {
+        aggregate = ((DotVarExp *)e1)->e1;
+	// Get rid of 'this'.
+        if (aggregate->op == TOKthis && istate->localThis)
+            aggregate = istate->localThis;	
+    }
+    
     /* Assignment to variable of the form:
      *	v = e2
      */
@@ -1457,25 +1643,14 @@
     {
 	VarExp *ve = (VarExp *)e1;
 	VarDeclaration *v = ve->var->isVarDeclaration();
+	assert(v);
+   	if (v && v->isDataseg())
+	{   // Can't modify global or static data
+	    error("%s cannot be modified at compile time", v->toChars());
+	    return EXP_CANT_INTERPRET;
+	}
 	if (v && !v->isDataseg())
 	{
-	    /* Chase down rebinding of out and ref
-	     */
-	    if (v->value && v->value->op == TOKvar)
-	    {
-		VarExp *ve2 = (VarExp *)v->value;
-		if (ve2->var->isStaticStructInitDeclaration())
-		{
-		    /* This can happen if v is a struct initialized to
-		     * 0 using an StaticStructInitDeclaration from
-		     * TypeStruct::defaultInit()
-		     */
-		}
-		else
-		    v = ve2->var->isVarDeclaration();
-		assert(v);
-	    }
-
 	    Expression *ev = v->value;
 	    if (fp && !ev)
 	    {	error("variable %s is used before initialization", v->toChars());
@@ -1492,35 +1667,46 @@
 		}
 		e2 = Cast(v->type, v->type, e2);
 	    }
-	    if (e2 != EXP_CANT_INTERPRET)
-	    {
-		if (!v->isParameter())
-		{
-		    for (size_t i = 0; 1; i++)
-		    {
-			if (i == istate->vars.dim)
-			{   istate->vars.push(v);
-			    //printf("\tadding %s to istate\n", v->toChars());
-			    break;
-			}
-			if (v == (VarDeclaration *)istate->vars.data[i])
-			    break;
-		    }
-		}
-		v->value = e2;
-		e = Cast(type, type, post ? ev : e2);
-	    }
+	    if (e2 == EXP_CANT_INTERPRET)
+		return e2;
+
+	    addVarToInterstate(istate, v);
+	    v->value = e2;
+	    e = Cast(type, type, post ? ev : e2);
 	}
     }
+    else if (e1->op == TOKdotvar && aggregate->op == TOKdotvar)
+    {	// eg  v.u.var = e2,  v[3].u.var = e2, etc.
+	error("Nested struct assignment %s is not yet supported in CTFE", toChars());
+    }
     /* Assignment to struct member of the form:
      *   v.var = e2
      */
-    else if (e1->op == TOKdotvar && ((DotVarExp *)e1)->e1->op == TOKvar)
-    {	VarExp *ve = (VarExp *)((DotVarExp *)e1)->e1;
-	VarDeclaration *v = ve->var->isVarDeclaration();
+    else if (e1->op == TOKdotvar && aggregate->op == TOKvar)
+    {	VarDeclaration *v = ((VarExp *)aggregate)->var->isVarDeclaration();
 
 	if (v->isDataseg())
+	{   // Can't modify global or static data
+	    error("%s cannot be modified at compile time", v->toChars());
 	    return EXP_CANT_INTERPRET;
+	} else {
+	    // Chase down rebinding of out and ref
+	    if (v->value && v->value->op == TOKvar)
+	    {
+		VarExp *ve2 = (VarExp *)v->value;
+//TODO
+#ifdef IN_DMD
+		if (ve2->var->isSymbolDeclaration())
+		{	// This can happen if v is a struct initialized to
+			// 0 using an __initZ SymbolDeclaration from
+			// TypeStruct::defaultInit()
+		}
+		else
+#endif
+		    v = ve2->var->isVarDeclaration();
+		assert(v);
+	    }
+	}
 	if (fp && !v->value)
 	{   error("variable %s is used before initialization", v->toChars());
 	    return e;
@@ -1557,30 +1743,11 @@
 	if (e2 == EXP_CANT_INTERPRET)
 	    return e2;
 
-	if (!v->isParameter())
-	{
-	    for (size_t i = 0; 1; i++)
-	    {
-		if (i == istate->vars.dim)
-		{   istate->vars.push(v);
-		    break;
-		}
-		if (v == (VarDeclaration *)istate->vars.data[i])
-		    break;
-	    }
-	}
+	addVarToInterstate(istate, v);
 
 	/* Create new struct literal reflecting updated fieldi
 	 */
-	Expressions *expsx = new Expressions();
-	expsx->setDim(se->elements->dim);
-	for (size_t j = 0; j < expsx->dim; j++)
-	{
-	    if (j == fieldi)
-		expsx->data[j] = (void *)e2;
-	    else
-		expsx->data[j] = se->elements->data[j];
-	}
+	Expressions *expsx = changeOneElement(se->elements, fieldi, e2);
 	v->value = new StructLiteralExp(se->loc, se->sd, expsx);
 	v->value->type = se->type;
 
@@ -1594,7 +1761,10 @@
 	VarDeclaration *v = soe->var->isVarDeclaration();
 
 	if (v->isDataseg())
+	{
+	    error("%s cannot be modified at compile time", v->toChars());
 	    return EXP_CANT_INTERPRET;
+	}
 	if (fp && !v->value)
 	{   error("variable %s is used before initialization", v->toChars());
 	    return e;
@@ -1619,30 +1789,11 @@
 	if (e2 == EXP_CANT_INTERPRET)
 	    return e2;
 
-	if (!v->isParameter())
-	{
-	    for (size_t i = 0; 1; i++)
-	    {
-		if (i == istate->vars.dim)
-		{   istate->vars.push(v);
-		    break;
-		}
-		if (v == (VarDeclaration *)istate->vars.data[i])
-		    break;
-	    }
-	}
+   	addVarToInterstate(istate, v);
 
 	/* Create new struct literal reflecting updated fieldi
 	 */
-	Expressions *expsx = new Expressions();
-	expsx->setDim(se->elements->dim);
-	for (size_t j = 0; j < expsx->dim; j++)
-	{
-	    if (j == fieldi)
-		expsx->data[j] = (void *)e2;
-	    else
-		expsx->data[j] = se->elements->data[j];
-	}
+	Expressions *expsx = changeOneElement(se->elements, fieldi, e2);
 	v->value = new StructLiteralExp(se->loc, se->sd, expsx);
 	v->value->type = se->type;
 
@@ -1655,9 +1806,26 @@
     {	IndexExp *ie = (IndexExp *)e1;
 	VarExp *ve = (VarExp *)ie->e1;
 	VarDeclaration *v = ve->var->isVarDeclaration();
-
 	if (!v || v->isDataseg())
+	{
+	    error("%s cannot be modified at compile time", v ? v->toChars(): "void");
 	    return EXP_CANT_INTERPRET;
+	}
+	    if (v->value && v->value->op == TOKvar)
+	    {
+		VarExp *ve2 = (VarExp *)v->value;
+// TODO
+#ifdef IN_DMD
+		if (ve2->var->isSymbolDeclaration())
+		{	// This can happen if v is a struct initialized to
+			// 0 using an __initZ SymbolDeclaration from
+			// TypeStruct::defaultInit()
+		}
+		else
+#endif
+		    v = ve2->var->isVarDeclaration();
+		assert(v);
+	    }
 	if (!v->value)
 	{
 	    if (fp)
@@ -1675,15 +1843,10 @@
 		 * But we're too lazy at the moment to do it, as that
 		 * involves redoing Index() and whoever calls it.
 		 */
-		Expression *ev = v->type->defaultInit();
+
 		size_t dim = ((TypeSArray *)t)->dim->toInteger();
-		Expressions *elements = new Expressions();
-		elements->setDim(dim);
-		for (size_t i = 0; i < dim; i++)
-		    elements->data[i] = (void *)ev;
-		ArrayLiteralExp *ae = new ArrayLiteralExp(0, elements);
-		ae->type = v->type;
-		v->value = ae;
+	        v->value = createBlockDuplicatedArrayLiteral(v->type,
+			v->type->defaultInit(), dim);
 	    }
 	    else
 		return EXP_CANT_INTERPRET;
@@ -1698,9 +1861,20 @@
 	    aae = (AssocArrayLiteralExp *)v->value;
 	else if (v->value->op == TOKstring)
 	    se = (StringExp *)v->value;
+	else if (v->value->op == TOKnull)
+	{
+	    // This would be a runtime segfault
+	    error("Cannot index null array %s", v->toChars());
+	    return EXP_CANT_INTERPRET;
+	}
 	else
 	    return EXP_CANT_INTERPRET;
 
+	/* Set the $ variable
+	 */
+	Expression *ee = ArrayLength(Type::tsize_t, v->value);
+	if (ee != EXP_CANT_INTERPRET && ie->lengthVar)
+	    ie->lengthVar->value = ee;
 	Expression *index = ie->e2->interpret(istate);
 	if (index == EXP_CANT_INTERPRET)
 	    return EXP_CANT_INTERPRET;
@@ -1718,34 +1892,14 @@
 	    e2 = Cast(type, type, e2);
 	if (e2 == EXP_CANT_INTERPRET)
 	    return e2;
-
-	if (!v->isParameter())
-	{
-	    for (size_t i = 0; 1; i++)
-	    {
-		if (i == istate->vars.dim)
-		{   istate->vars.push(v);
-		    break;
-		}
-		if (v == (VarDeclaration *)istate->vars.data[i])
-		    break;
-	    }
-	}
-
+	
+	addVarToInterstate(istate, v);
 	if (ae)
 	{
 	    /* Create new array literal reflecting updated elem
 	     */
 	    int elemi = index->toInteger();
-	    Expressions *expsx = new Expressions();
-	    expsx->setDim(ae->elements->dim);
-	    for (size_t j = 0; j < expsx->dim; j++)
-	    {
-		if (j == elemi)
-		    expsx->data[j] = (void *)e2;
-		else
-		    expsx->data[j] = ae->elements->data[j];
-	    }
+	    Expressions *expsx = changeOneElement(ae->elements, elemi, e2);
 	    v->value = new ArrayLiteralExp(ae->loc, expsx);
 	    v->value->type = ae->type;
 	}
@@ -1808,8 +1962,248 @@
 
 	e = Cast(type, type, post ? ev : e2);
     }
+    
+    /* Assignment to struct element in array, of the form:
+     *  a[i].var = e2
+     */
+    else if (e1->op == TOKdotvar && aggregate->op == TOKindex &&
+	     ((IndexExp *)aggregate)->e1->op == TOKvar)
+    {
+        IndexExp * ie = (IndexExp *)aggregate;
+	VarExp *ve = (VarExp *)(ie->e1);
+	VarDeclaration *v = ve->var->isVarDeclaration();
+	if (!v || v->isDataseg())
+	{
+	    error("%s cannot be modified at compile time", v ? v->toChars(): "void");
+	    return EXP_CANT_INTERPRET;
+	}
+	Type *t = ve->type->toBasetype();
+	ArrayLiteralExp *ae = (ArrayLiteralExp *)v->value;
+	if (!ae)
+	{
+	    // assignment to one element in an uninitialized (static) array.
+	    // This is quite difficult, because defaultInit() for a struct is a VarExp,
+	    // not a StructLiteralExp.
+	    Type *t = v->type->toBasetype();
+	    if (t->ty != Tsarray)
+	    {
+		error("Cannot index an uninitialized variable");
+		return EXP_CANT_INTERPRET;
+	    }
+
+	    Type *telem = ((TypeSArray *)t)->nextOf()->toBasetype();
+	    if (telem->ty != Tstruct) { return EXP_CANT_INTERPRET; }
+
+	    // Create a default struct literal...
+	    StructDeclaration *sym = ((TypeStruct *)telem)->sym;
+	    StructLiteralExp *structinit = createDefaultInitStructLiteral(v->loc, sym);
+
+	    // ... and use to create a blank array literal
+	    size_t dim = ((TypeSArray *)t)->dim->toInteger();
+	    ae = createBlockDuplicatedArrayLiteral(v->type, structinit, dim);
+	    v->value = ae;
+	}
+	if ((Expression *)(ae->elements) == EXP_CANT_INTERPRET)
+	{
+	    // Note that this would be a runtime segfault
+	    error("Cannot index null array %s", v->toChars());
+	    return EXP_CANT_INTERPRET;
+	}
+	// Set the $ variable
+	Expression *ee = ArrayLength(Type::tsize_t, v->value);
+	if (ee != EXP_CANT_INTERPRET && ie->lengthVar)
+	    ie->lengthVar->value = ee;
+	// Determine the index, and check that it's OK.
+	Expression *index = ie->e2->interpret(istate);
+	if (index == EXP_CANT_INTERPRET)
+	    return EXP_CANT_INTERPRET;
+
+	int elemi = index->toInteger();
+	if (elemi >= ae->elements->dim)
+	{
+	    error("array index %d is out of bounds %s[0..%d]", elemi,
+		v->toChars(), ae->elements->dim);
+	    return EXP_CANT_INTERPRET;
+	}
+	// Get old element
+	Expression *vie = (Expression *)(ae->elements->data[elemi]);
+	if (vie->op != TOKstructliteral)
+	    return EXP_CANT_INTERPRET;
+
+	// Work out which field needs to be changed
+	StructLiteralExp *se = (StructLiteralExp *)vie;
+	VarDeclaration *vf = ((DotVarExp *)e1)->var->isVarDeclaration();
+	if (!vf)
+	    return EXP_CANT_INTERPRET;
+
+	int fieldi = se->getFieldIndex(type, vf->offset);
+	if (fieldi == -1)
+	    return EXP_CANT_INTERPRET;
+		
+	Expression *ev = se->getField(type, vf->offset);
+	if (fp)
+	    e2 = (*fp)(type, ev, e2);
+	else
+	    e2 = Cast(type, type, e2);
+	if (e2 == EXP_CANT_INTERPRET)
+	    return e2;
+
+	// Create new struct literal reflecting updated field
+	Expressions *expsx = changeOneElement(se->elements, fieldi, e2);
+	Expression * newstruct = new StructLiteralExp(se->loc, se->sd, expsx);
+
+	// Create new array literal reflecting updated struct elem
+	ae->elements = changeOneElement(ae->elements, elemi, newstruct);
+	return ae;
+    }
+    /* Slice assignment, initialization of static arrays
+     *   a[] = e
+     */
+    else if (e1->op == TOKslice && ((SliceExp *)e1)->e1->op==TOKvar)
+    {
+        SliceExp * sexp = (SliceExp *)e1;
+	VarExp *ve = (VarExp *)(sexp->e1);
+	VarDeclaration *v = ve->var->isVarDeclaration();
+	if (!v || v->isDataseg())
+	{
+	    error("%s cannot be modified at compile time", v->toChars());
+	    return EXP_CANT_INTERPRET;
+	}
+	    // Chase down rebinding of out and ref
+	    if (v->value && v->value->op == TOKvar)
+	    {
+		VarExp *ve2 = (VarExp *)v->value;
+// TODO
+#ifdef IN_DMD
+		if (ve2->var->isSymbolDeclaration())
+		{	// This can happen if v is a struct initialized to
+			// 0 using an __initZ SymbolDeclaration from
+			// TypeStruct::defaultInit()
+		}
+		else
+#endif
+		    v = ve2->var->isVarDeclaration();
+		assert(v);
+	    }
+	/* Set the $ variable
+	 */
+	Expression *ee = v->value ? ArrayLength(Type::tsize_t, v->value)
+				  : EXP_CANT_INTERPRET;
+	if (ee != EXP_CANT_INTERPRET && sexp->lengthVar)
+	    sexp->lengthVar->value = ee;
+	Expression *upper = NULL;
+	Expression *lower = NULL;
+	if (sexp->upr)
+	{
+	    upper = sexp->upr->interpret(istate);
+	    if (upper == EXP_CANT_INTERPRET)
+		return EXP_CANT_INTERPRET;
+	}
+	if (sexp->lwr)
+	{
+	    lower = sexp->lwr->interpret(istate);
+	    if (lower == EXP_CANT_INTERPRET)
+		return EXP_CANT_INTERPRET;
+	}
+	Type *t = v->type->toBasetype();
+	size_t dim;
+	if (t->ty == Tsarray)			
+	    dim = ((TypeSArray *)t)->dim->toInteger();
+	else if (t->ty == Tarray)
+	{
+	    if (!v->value || v->value->op == TOKnull)
+	    {
+		error("cannot assign to null array %s", v->toChars());
+		return EXP_CANT_INTERPRET;
+	    }
+	    if (v->value->op == TOKarrayliteral)
+		dim = ((ArrayLiteralExp *)v->value)->elements->dim;
+	    else if (v->value->op ==TOKstring)
+	    {
+		error("String slice assignment is not yet supported in CTFE");
+		return EXP_CANT_INTERPRET;
+	    }
+	}
+	else
+	{
+	    error("%s cannot be evaluated at compile time", toChars());
+	    return EXP_CANT_INTERPRET;
+	}
+	int upperbound = upper ? upper->toInteger() : dim;
+	int lowerbound = lower ? lower->toInteger() : 0;
+
+	ArrayLiteralExp *existing;
+	if (((int)lowerbound < 0) || (upperbound > dim))
+	{
+	    error("Array bounds [0..%d] exceeded in slice [%d..%d]", dim, lowerbound, upperbound);
+	    return EXP_CANT_INTERPRET;
+	}
+	if (upperbound-lowerbound != dim)
+	{
+	    // Only modifying part of the array. Must create a new array literal.
+	    // If the existing array is uninitialized (this can only happen
+	    // with static arrays), create it.
+	    if (v->value && v->value->op == TOKarrayliteral)
+		    existing = (ArrayLiteralExp *)v->value;
+	    else
+	    {
+		// this can only happen with static arrays
+		existing = createBlockDuplicatedArrayLiteral(v->type, v->type->defaultInit(), dim);
+	    }
+	}
+
+	if (e2->op == TOKarrayliteral)
+	{
+	    // Static array assignment from literal
+	    ArrayLiteralExp *ae = (ArrayLiteralExp *)e2;				
+	    if (ae->elements->dim != (upperbound - lowerbound))
+	    {
+		error("Array length mismatch assigning [0..%d] to [%d..%d]", ae->elements->dim, lowerbound, upperbound);
+		return e;
+	    }
+	    if (upperbound - lowerbound == dim)
+		v->value = ae;
+	    else
+	    {
+		// value[] = value[0..lower] ~ ae ~ value[upper..$]
+		existing->elements = spliceElements(existing->elements, ae->elements, lowerbound);
+		v->value = existing;
+	    }
+	    return e2;
+	}
+	else if (t->nextOf()->ty == e2->type->ty)
+	{
+	     // Static array block assignment
+	    if (upperbound-lowerbound ==dim)
+		v->value = createBlockDuplicatedArrayLiteral(v->type, e2, dim);
+	    else
+	    {
+		// value[] = value[0..lower] ~ ae ~ value[upper..$]
+		existing->elements = spliceElements(existing->elements, createBlockDuplicatedArrayLiteral(v->type, e2, upperbound-lowerbound)->elements, lowerbound);
+		v->value = existing;
+	    }				
+	    return e2;
+	}
+	else if (e2->op == TOKstring)
+	{
+	    StringExp *se = (StringExp *)e2;
+	    // This is problematic. char[8] should be storing
+	    // values as a string literal, not
+	    // as an array literal. Then, for static arrays, we
+	    // could do modifications
+	    // in-place, with a dramatic memory and speed improvement.
+	    error("String slice assignment is not yet supported in CTFE");
+	    return e2;
+	}
+	else
+	{
+	    error("Slice operation %s cannot be evaluated at compile time", toChars());
+	    return e;
+	}
+    }
     else
     {
+	error("%s cannot be evaluated at compile time", toChars());
 #ifdef DEBUG
 	dump(0);
 #endif
@@ -1923,6 +2317,27 @@
 #if LOG
     printf("CallExp::interpret() %s\n", toChars());
 #endif
+    if (e1->op == TOKdotvar)
+    {
+        Expression * pthis = ((DotVarExp*)e1)->e1;
+	FuncDeclaration *fd = ((DotVarExp*)e1)->var->isFuncDeclaration();
+	TypeFunction *tf = fd ? (TypeFunction *)(fd->type) : NULL;
+	if (tf)
+	{   // Member function call
+	    if(pthis->op == TOKthis)
+		pthis = istate->localThis;	    
+	    Expression *eresult = fd->interpret(istate, arguments, pthis);
+	    if (eresult)
+		e = eresult;
+	    else if (fd->type->toBasetype()->nextOf()->ty == Tvoid && !global.errors)
+		e = EXP_VOID_INTERPRET;
+	    else
+		error("cannot evaluate %s at compile time", toChars());
+	    return e;
+	} 
+	error("cannot evaluate %s at compile time", toChars());
+        return EXP_CANT_INTERPRET;
+    }
     if (e1->op == TOKvar)
     {
 	FuncDeclaration *fd = ((VarExp *)e1)->var->isFuncDeclaration();
@@ -2155,6 +2570,17 @@
 #if LOG
     printf("AssertExp::interpret() %s\n", toChars());
 #endif
+    if( this->e1->op == TOKaddress)
+    {   // Special case: deal with compiler-inserted assert(&this, "null this") 
+	AddrExp *ade = (AddrExp *)this->e1;
+	if(ade->e1->op == TOKthis && istate->localThis)   	
+	return istate->localThis->interpret(istate);
+    }
+if (this->e1->op == TOKthis)
+{
+	if(istate->localThis)   	
+	return istate->localThis->interpret(istate);
+}    
     e1 = this->e1->interpret(istate);
     if (e1 == EXP_CANT_INTERPRET)
 	goto Lcant;
@@ -2223,6 +2649,14 @@
 	    }
 	}
     }
+#if DMDV2
+#else // this is required for D1, where structs return *this instead of 'this'.    
+    else if (e1->op == TOKthis)
+    {
+    	if(istate->localThis)   	
+	    return istate->localThis->interpret(istate);
+    }
+#endif    
 #if LOG
     if (e == EXP_CANT_INTERPRET)
 	printf("PtrExp::interpret() %s = EXP_CANT_INTERPRET\n", toChars());
@@ -2249,7 +2683,7 @@
 		    e = EXP_CANT_INTERPRET;
 		return e;
 	    }
-	}
+	} else error("%s.%s is not yet implemented at compile time", ex->toChars(), var->toChars());
     }
 
 #if LOG
@@ -2278,7 +2712,9 @@
 
 Expression *interpret_aaKeys(InterState *istate, Expressions *arguments)
 {
-    //printf("interpret_aaKeys()\n");
+#if LOG
+    printf("interpret_aaKeys()\n");
+#endif
     if (!arguments || arguments->dim != 2)
 	return NULL;
     Expression *earg = (Expression *)arguments->data[0];
@@ -2289,6 +2725,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;
 }
 
@@ -2305,6 +2743,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/dmd/lexer.c	Fri Nov 06 21:51:41 2009 +0100
+++ b/dmd/lexer.c	Fri Nov 06 23:58:01 2009 +0100
@@ -1266,7 +1266,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
@@ -3071,6 +3073,7 @@
     Token::tochars[TOKidentifier]	= "identifier";
 
      // For debugging
+    Token::tochars[TOKerror]		= "error";
     Token::tochars[TOKdotexp]		= "dotexp";
     Token::tochars[TOKdotti]		= "dotti";
     Token::tochars[TOKdotvar]		= "dotvar";
--- a/dmd/lexer.h	Fri Nov 06 21:51:41 2009 +0100
+++ b/dmd/lexer.h	Fri Nov 06 23:58:01 2009 +0100
@@ -1,305 +1,307 @@
-
-// Compiler implementation of the D programming language
-// Copyright (c) 1999-2008 by Digital Mars
-// All Rights Reserved
-// written by Walter Bright
-// http://www.digitalmars.com
-// License for redistribution is by either the Artistic License
-// in artistic.txt, or the GNU General Public License in gnu.txt.
-// See the included readme.txt for details.
-
-#ifndef DMD_LEXER_H
-#define DMD_LEXER_H
-
-#ifdef __DMC__
-#pragma once
-#endif /* __DMC__ */
-
-#include "root.h"
-#include "mars.h"
-
-struct StringTable;
-struct Identifier;
-struct Module;
-
-/* Tokens:
-	(	)
-	[	]
-	{	}
-	<	>	<=	>=	==	!=	===	!==
-	<<	>>	<<=	>>=	>>>	>>>=
-	+	-	+=	-=
-	*	/	%	*=	/=	%=
-	&	| 	^	&=	|=	^=
-	=	!	~
-	++	--
-	.	->	:	,
-	?	&&	||
- */
-
-enum TOK
-{
-	TOKreserved,
-
-	// Other
-	TOKlparen,	TOKrparen,
-	TOKlbracket,	TOKrbracket,
-	TOKlcurly,	TOKrcurly,
-	TOKcolon,	TOKneg,
-	TOKsemicolon,	TOKdotdotdot,
-	TOKeof,		TOKcast,
-	TOKnull,	TOKassert,
-	TOKtrue,	TOKfalse,
-	TOKarray,	TOKcall,
-	TOKaddress,
-	TOKtype,	TOKthrow,
-	TOKnew,		TOKdelete,
-	TOKstar,	TOKsymoff,
-	TOKvar,		TOKdotvar,
-	TOKdotti,	TOKdotexp,
-	TOKdottype,	TOKslice,
-	TOKarraylength,	TOKversion,
-	TOKmodule,	TOKdollar,
-	TOKtemplate,	TOKdottd,
-	TOKdeclaration,	TOKtypeof,
-	TOKpragma,	TOKdsymbol,
-	TOKtypeid,	TOKuadd,
-	TOKremove,
-	TOKnewanonclass, TOKcomment,
-	TOKarrayliteral, TOKassocarrayliteral,
-	TOKstructliteral,
-
-	// Operators
-	TOKlt,		TOKgt,
-	TOKle,		TOKge,
-	TOKequal,	TOKnotequal,
-	TOKidentity,	TOKnotidentity,
-	TOKindex,	TOKis,
-	TOKtobool,
-
-// 60
-	// NCEG floating point compares
-	// !<>=     <>    <>=    !>     !>=   !<     !<=   !<>
-	TOKunord,TOKlg,TOKleg,TOKule,TOKul,TOKuge,TOKug,TOKue,
-
-	TOKshl,		TOKshr,
-	TOKshlass,	TOKshrass,
-	TOKushr,	TOKushrass,
-	TOKcat,		TOKcatass,	// ~ ~=
-	TOKadd,		TOKmin,		TOKaddass,	TOKminass,
-	TOKmul,		TOKdiv,		TOKmod,
-	TOKmulass,	TOKdivass,	TOKmodass,
-	TOKand,		TOKor,		TOKxor,
-	TOKandass,	TOKorass,	TOKxorass,
-	TOKassign,	TOKnot,		TOKtilde,
-	TOKplusplus,	TOKminusminus,	TOKconstruct,	TOKblit,
-	TOKdot,		TOKarrow,	TOKcomma,
-	TOKquestion,	TOKandand,	TOKoror,
-
-// 104
-	// Numeric literals
-	TOKint32v, TOKuns32v,
-	TOKint64v, TOKuns64v,
-	TOKfloat32v, TOKfloat64v, TOKfloat80v,
-	TOKimaginary32v, TOKimaginary64v, TOKimaginary80v,
-
-	// Char constants
-	TOKcharv, TOKwcharv, TOKdcharv,
-
-	// Leaf operators
-	TOKidentifier,	TOKstring,
-	TOKthis,	TOKsuper,
-	TOKhalt,	TOKtuple,
-
-	// Basic types
-	TOKvoid,
-	TOKint8, TOKuns8,
-	TOKint16, TOKuns16,
-	TOKint32, TOKuns32,
-	TOKint64, TOKuns64,
-	TOKfloat32, TOKfloat64, TOKfloat80,
-	TOKimaginary32, TOKimaginary64, TOKimaginary80,
-	TOKcomplex32, TOKcomplex64, TOKcomplex80,
-	TOKchar, TOKwchar, TOKdchar, TOKbit, TOKbool,
-	TOKcent, TOKucent,
-
-	// Aggregates
-	TOKstruct, TOKclass, TOKinterface, TOKunion, TOKenum, TOKimport,
-	TOKtypedef, TOKalias, TOKoverride, TOKdelegate, TOKfunction,
-	TOKmixin,
-
-	TOKalign, TOKextern, TOKprivate, TOKprotected, TOKpublic, TOKexport,
-	TOKstatic, /*TOKvirtual,*/ TOKfinal, TOKconst, TOKabstract, TOKvolatile,
-	TOKdebug, TOKdeprecated, TOKin, TOKout, TOKinout, TOKlazy,
-	TOKauto, TOKpackage, TOKmanifest,
-
-	// Statements
-	TOKif, TOKelse, TOKwhile, TOKfor, TOKdo, TOKswitch,
-	TOKcase, TOKdefault, TOKbreak, TOKcontinue, TOKwith,
-	TOKsynchronized, TOKreturn, TOKgoto, TOKtry, TOKcatch, TOKfinally,
-	TOKasm, TOKforeach, TOKforeach_reverse,
-	TOKscope,
-	TOKon_scope_exit, TOKon_scope_failure, TOKon_scope_success,
-
-	// Contracts
-	TOKbody, TOKinvariant,
-
-	// Testing
-	TOKunittest,
-
-	// Added after 1.0
-	TOKref,
-	TOKmacro,
-#if DMDV2
-	TOKtraits,
-	TOKoverloadset,
-	TOKpure,
-	TOKnothrow,
-	TOKtls,
-	TOKline,
-	TOKfile,
-    TOKshared,
-#endif
-
-// LDC specific
-#if IN_LLVM
-    TOKgep,
-#endif
-
-	TOKMAX
-};
-
-#define CASE_BASIC_TYPES			\
-	case TOKwchar: case TOKdchar:		\
-	case TOKbit: case TOKbool: case TOKchar:	\
-	case TOKint8: case TOKuns8:		\
-	case TOKint16: case TOKuns16:		\
-	case TOKint32: case TOKuns32:		\
-	case TOKint64: case TOKuns64:		\
-	case TOKfloat32: case TOKfloat64: case TOKfloat80:		\
-	case TOKimaginary32: case TOKimaginary64: case TOKimaginary80:	\
-	case TOKcomplex32: case TOKcomplex64: case TOKcomplex80:	\
-	case TOKvoid
-
-#define CASE_BASIC_TYPES_X(t)					\
-	case TOKvoid:	 t = Type::tvoid;  goto LabelX;		\
-	case TOKint8:	 t = Type::tint8;  goto LabelX;		\
-	case TOKuns8:	 t = Type::tuns8;  goto LabelX;		\
-	case TOKint16:	 t = Type::tint16; goto LabelX;		\
-	case TOKuns16:	 t = Type::tuns16; goto LabelX;		\
-	case TOKint32:	 t = Type::tint32; goto LabelX;		\
-	case TOKuns32:	 t = Type::tuns32; goto LabelX;		\
-	case TOKint64:	 t = Type::tint64; goto LabelX;		\
-	case TOKuns64:	 t = Type::tuns64; goto LabelX;		\
-	case TOKfloat32: t = Type::tfloat32; goto LabelX;	\
-	case TOKfloat64: t = Type::tfloat64; goto LabelX;	\
-	case TOKfloat80: t = Type::tfloat80; goto LabelX;	\
-	case TOKimaginary32: t = Type::timaginary32; goto LabelX;	\
-	case TOKimaginary64: t = Type::timaginary64; goto LabelX;	\
-	case TOKimaginary80: t = Type::timaginary80; goto LabelX;	\
-	case TOKcomplex32: t = Type::tcomplex32; goto LabelX;	\
-	case TOKcomplex64: t = Type::tcomplex64; goto LabelX;	\
-	case TOKcomplex80: t = Type::tcomplex80; goto LabelX;	\
-	case TOKbit:	 t = Type::tbit;     goto LabelX;	\
-	case TOKbool:	 t = Type::tbool;    goto LabelX;	\
-	case TOKchar:	 t = Type::tchar;    goto LabelX;	\
-	case TOKwchar:	 t = Type::twchar; goto LabelX;	\
-	case TOKdchar:	 t = Type::tdchar; goto LabelX;	\
-	LabelX
-
-struct Token
-{
-    Token *next;
-    unsigned char *ptr;		// pointer to first character of this token within buffer
-    enum TOK value;
-    unsigned char *blockComment; // doc comment string prior to this token
-    unsigned char *lineComment;	 // doc comment for previous token
-    union
-    {
-	// Integers
-	d_int64	int64value;
-	d_uns64	uns64value;
-
-	// Floats
-#ifdef IN_GCC
-	// real_t float80value; // can't use this in a union!
-#else
-	d_float80 float80value;
-#endif
-
-	struct
-	{   unsigned char *ustring;	// UTF8 string
-	    unsigned len;
-	    unsigned char postfix;	// 'c', 'w', 'd'
-	};
-
-	Identifier *ident;
-    };
-#ifdef IN_GCC
-    real_t float80value; // can't use this in a union!
-#endif
-
-    static const char *tochars[TOKMAX];
-    static void *operator new(size_t sz);
-
-    int isKeyword();
-    void print();
-    const char *toChars();
-    static const char *toChars(enum TOK);
-};
-
-struct Lexer
-{
-    static StringTable stringtable;
-    static OutBuffer stringbuffer;
-    static Token *freelist;
-
-    Loc loc;			// for error messages
-
-    unsigned char *base;	// pointer to start of buffer
-    unsigned char *end;		// past end of buffer
-    unsigned char *p;		// current character
-    Token token;
-    Module *mod;
-    int doDocComment;		// collect doc comment information
-    int anyToken;		// !=0 means seen at least one token
-    int commentToken;		// !=0 means comments are TOKcomment's
-
-    Lexer(Module *mod,
-	unsigned char *base, unsigned begoffset, unsigned endoffset,
-	int doDocComment, int commentToken);
-
-    static void initKeywords();
-    static Identifier *idPool(const char *s);
-    static Identifier *uniqueId(const char *s);
-    static Identifier *uniqueId(const char *s, int num);
-
-    TOK nextToken();
-    TOK peekNext();
-    void scan(Token *t);
-    Token *peek(Token *t);
-    Token *peekPastParen(Token *t);
-    unsigned escapeSequence();
-    TOK wysiwygStringConstant(Token *t, int tc);
-    TOK hexStringConstant(Token *t);
-#if DMDV2
-    TOK delimitedStringConstant(Token *t);
-    TOK tokenStringConstant(Token *t);
-#endif
-    TOK escapeStringConstant(Token *t, int wide);
-    TOK charConstant(Token *t, int wide);
-    void stringPostfix(Token *t);
-    unsigned wchar(unsigned u);
-    TOK number(Token *t);
-    TOK inreal(Token *t);
-    void error(const char *format, ...) IS_PRINTF(2);
-    void error(Loc loc, const char *format, ...) IS_PRINTF(3);
-    void pragma();
-    unsigned decodeUTF();
-    void getDocComment(Token *t, unsigned lineComment);
-
-    static int isValidIdentifier(char *p);
-    static unsigned char *combineComments(unsigned char *c1, unsigned char *c2);
-};
-
-#endif /* DMD_LEXER_H */
+
+// Compiler implementation of the D programming language
+// Copyright (c) 1999-2008 by Digital Mars
+// All Rights Reserved
+// written by Walter Bright
+// http://www.digitalmars.com
+// License for redistribution is by either the Artistic License
+// in artistic.txt, or the GNU General Public License in gnu.txt.
+// See the included readme.txt for details.
+
+#ifndef DMD_LEXER_H
+#define DMD_LEXER_H
+
+#ifdef __DMC__
+#pragma once
+#endif /* __DMC__ */
+
+#include "root.h"
+#include "mars.h"
+
+struct StringTable;
+struct Identifier;
+struct Module;
+
+/* Tokens:
+	(	)
+	[	]
+	{	}
+	<	>	<=	>=	==	!=	===	!==
+	<<	>>	<<=	>>=	>>>	>>>=
+	+	-	+=	-=
+	*	/	%	*=	/=	%=
+	&	| 	^	&=	|=	^=
+	=	!	~
+	++	--
+	.	->	:	,
+	?	&&	||
+ */
+
+enum TOK
+{
+	TOKreserved,
+
+	// Other
+	TOKlparen,	TOKrparen,
+	TOKlbracket,	TOKrbracket,
+	TOKlcurly,	TOKrcurly,
+	TOKcolon,	TOKneg,
+	TOKsemicolon,	TOKdotdotdot,
+	TOKeof,		TOKcast,
+	TOKnull,	TOKassert,
+	TOKtrue,	TOKfalse,
+	TOKarray,	TOKcall,
+	TOKaddress,
+	TOKtype,	TOKthrow,
+	TOKnew,		TOKdelete,
+	TOKstar,	TOKsymoff,
+	TOKvar,		TOKdotvar,
+	TOKdotti,	TOKdotexp,
+	TOKdottype,	TOKslice,
+	TOKarraylength,	TOKversion,
+	TOKmodule,	TOKdollar,
+	TOKtemplate,	TOKdottd,
+	TOKdeclaration,	TOKtypeof,
+	TOKpragma,	TOKdsymbol,
+	TOKtypeid,	TOKuadd,
+	TOKremove,
+	TOKnewanonclass, TOKcomment,
+	TOKarrayliteral, TOKassocarrayliteral,
+	TOKstructliteral,
+
+	// Operators
+	TOKlt,		TOKgt,
+	TOKle,		TOKge,
+	TOKequal,	TOKnotequal,
+	TOKidentity,	TOKnotidentity,
+	TOKindex,	TOKis,
+	TOKtobool,
+
+// 60
+	// NCEG floating point compares
+	// !<>=     <>    <>=    !>     !>=   !<     !<=   !<>
+	TOKunord,TOKlg,TOKleg,TOKule,TOKul,TOKuge,TOKug,TOKue,
+
+	TOKshl,		TOKshr,
+	TOKshlass,	TOKshrass,
+	TOKushr,	TOKushrass,
+	TOKcat,		TOKcatass,	// ~ ~=
+	TOKadd,		TOKmin,		TOKaddass,	TOKminass,
+	TOKmul,		TOKdiv,		TOKmod,
+	TOKmulass,	TOKdivass,	TOKmodass,
+	TOKand,		TOKor,		TOKxor,
+	TOKandass,	TOKorass,	TOKxorass,
+	TOKassign,	TOKnot,		TOKtilde,
+	TOKplusplus,	TOKminusminus,	TOKconstruct,	TOKblit,
+	TOKdot,		TOKarrow,	TOKcomma,
+	TOKquestion,	TOKandand,	TOKoror,
+
+// 104
+	// Numeric literals
+	TOKint32v, TOKuns32v,
+	TOKint64v, TOKuns64v,
+	TOKfloat32v, TOKfloat64v, TOKfloat80v,
+	TOKimaginary32v, TOKimaginary64v, TOKimaginary80v,
+
+	// Char constants
+	TOKcharv, TOKwcharv, TOKdcharv,
+
+	// Leaf operators
+	TOKidentifier,	TOKstring,
+	TOKthis,	TOKsuper,
+	TOKhalt,	TOKtuple,
+	TOKerror,
+
+	// Basic types
+	TOKvoid,
+	TOKint8, TOKuns8,
+	TOKint16, TOKuns16,
+	TOKint32, TOKuns32,
+	TOKint64, TOKuns64,
+	TOKfloat32, TOKfloat64, TOKfloat80,
+	TOKimaginary32, TOKimaginary64, TOKimaginary80,
+	TOKcomplex32, TOKcomplex64, TOKcomplex80,
+	TOKchar, TOKwchar, TOKdchar, TOKbit, TOKbool,
+	TOKcent, TOKucent,
+
+// 150
+	// Aggregates
+	TOKstruct, TOKclass, TOKinterface, TOKunion, TOKenum, TOKimport,
+	TOKtypedef, TOKalias, TOKoverride, TOKdelegate, TOKfunction,
+	TOKmixin,
+
+	TOKalign, TOKextern, TOKprivate, TOKprotected, TOKpublic, TOKexport,
+	TOKstatic, /*TOKvirtual,*/ TOKfinal, TOKconst, TOKabstract, TOKvolatile,
+	TOKdebug, TOKdeprecated, TOKin, TOKout, TOKinout, TOKlazy,
+	TOKauto, TOKpackage, TOKmanifest,
+
+	// Statements
+	TOKif, TOKelse, TOKwhile, TOKfor, TOKdo, TOKswitch,
+	TOKcase, TOKdefault, TOKbreak, TOKcontinue, TOKwith,
+	TOKsynchronized, TOKreturn, TOKgoto, TOKtry, TOKcatch, TOKfinally,
+	TOKasm, TOKforeach, TOKforeach_reverse,
+	TOKscope,
+	TOKon_scope_exit, TOKon_scope_failure, TOKon_scope_success,
+
+	// Contracts
+	TOKbody, TOKinvariant,
+
+	// Testing
+	TOKunittest,
+
+	// Added after 1.0
+	TOKref,
+	TOKmacro,
+#if DMDV2
+	TOKtraits,
+	TOKoverloadset,
+	TOKpure,
+	TOKnothrow,
+	TOKtls,
+	TOKline,
+	TOKfile,
+    TOKshared,
+#endif
+
+// LDC specific
+#if IN_LLVM
+    TOKgep,
+#endif
+
+	TOKMAX
+};
+
+#define CASE_BASIC_TYPES			\
+	case TOKwchar: case TOKdchar:		\
+	case TOKbit: case TOKbool: case TOKchar:	\
+	case TOKint8: case TOKuns8:		\
+	case TOKint16: case TOKuns16:		\
+	case TOKint32: case TOKuns32:		\
+	case TOKint64: case TOKuns64:		\
+	case TOKfloat32: case TOKfloat64: case TOKfloat80:		\
+	case TOKimaginary32: case TOKimaginary64: case TOKimaginary80:	\
+	case TOKcomplex32: case TOKcomplex64: case TOKcomplex80:	\
+	case TOKvoid
+
+#define CASE_BASIC_TYPES_X(t)					\
+	case TOKvoid:	 t = Type::tvoid;  goto LabelX;		\
+	case TOKint8:	 t = Type::tint8;  goto LabelX;		\
+	case TOKuns8:	 t = Type::tuns8;  goto LabelX;		\
+	case TOKint16:	 t = Type::tint16; goto LabelX;		\
+	case TOKuns16:	 t = Type::tuns16; goto LabelX;		\
+	case TOKint32:	 t = Type::tint32; goto LabelX;		\
+	case TOKuns32:	 t = Type::tuns32; goto LabelX;		\
+	case TOKint64:	 t = Type::tint64; goto LabelX;		\
+	case TOKuns64:	 t = Type::tuns64; goto LabelX;		\
+	case TOKfloat32: t = Type::tfloat32; goto LabelX;	\
+	case TOKfloat64: t = Type::tfloat64; goto LabelX;	\
+	case TOKfloat80: t = Type::tfloat80; goto LabelX;	\
+	case TOKimaginary32: t = Type::timaginary32; goto LabelX;	\
+	case TOKimaginary64: t = Type::timaginary64; goto LabelX;	\
+	case TOKimaginary80: t = Type::timaginary80; goto LabelX;	\
+	case TOKcomplex32: t = Type::tcomplex32; goto LabelX;	\
+	case TOKcomplex64: t = Type::tcomplex64; goto LabelX;	\
+	case TOKcomplex80: t = Type::tcomplex80; goto LabelX;	\
+	case TOKbit:	 t = Type::tbit;     goto LabelX;	\
+	case TOKbool:	 t = Type::tbool;    goto LabelX;	\
+	case TOKchar:	 t = Type::tchar;    goto LabelX;	\
+	case TOKwchar:	 t = Type::twchar; goto LabelX;	\
+	case TOKdchar:	 t = Type::tdchar; goto LabelX;	\
+	LabelX
+
+struct Token
+{
+    Token *next;
+    unsigned char *ptr;		// pointer to first character of this token within buffer
+    enum TOK value;
+    unsigned char *blockComment; // doc comment string prior to this token
+    unsigned char *lineComment;	 // doc comment for previous token
+    union
+    {
+	// Integers
+	d_int64	int64value;
+	d_uns64	uns64value;
+
+	// Floats
+#ifdef IN_GCC
+	// real_t float80value; // can't use this in a union!
+#else
+	d_float80 float80value;
+#endif
+
+	struct
+	{   unsigned char *ustring;	// UTF8 string
+	    unsigned len;
+	    unsigned char postfix;	// 'c', 'w', 'd'
+	};
+
+	Identifier *ident;
+    };
+#ifdef IN_GCC
+    real_t float80value; // can't use this in a union!
+#endif
+
+    static const char *tochars[TOKMAX];
+    static void *operator new(size_t sz);
+
+    int isKeyword();
+    void print();
+    const char *toChars();
+    static const char *toChars(enum TOK);
+};
+
+struct Lexer
+{
+    static StringTable stringtable;
+    static OutBuffer stringbuffer;
+    static Token *freelist;
+
+    Loc loc;			// for error messages
+
+    unsigned char *base;	// pointer to start of buffer
+    unsigned char *end;		// past end of buffer
+    unsigned char *p;		// current character
+    Token token;
+    Module *mod;
+    int doDocComment;		// collect doc comment information
+    int anyToken;		// !=0 means seen at least one token
+    int commentToken;		// !=0 means comments are TOKcomment's
+
+    Lexer(Module *mod,
+	unsigned char *base, unsigned begoffset, unsigned endoffset,
+	int doDocComment, int commentToken);
+
+    static void initKeywords();
+    static Identifier *idPool(const char *s);
+    static Identifier *uniqueId(const char *s);
+    static Identifier *uniqueId(const char *s, int num);
+
+    TOK nextToken();
+    TOK peekNext();
+    void scan(Token *t);
+    Token *peek(Token *t);
+    Token *peekPastParen(Token *t);
+    unsigned escapeSequence();
+    TOK wysiwygStringConstant(Token *t, int tc);
+    TOK hexStringConstant(Token *t);
+#if DMDV2
+    TOK delimitedStringConstant(Token *t);
+    TOK tokenStringConstant(Token *t);
+#endif
+    TOK escapeStringConstant(Token *t, int wide);
+    TOK charConstant(Token *t, int wide);
+    void stringPostfix(Token *t);
+    unsigned wchar(unsigned u);
+    TOK number(Token *t);
+    TOK inreal(Token *t);
+    void error(const char *format, ...) IS_PRINTF(2);
+    void error(Loc loc, const char *format, ...) IS_PRINTF(3);
+    void pragma();
+    unsigned decodeUTF();
+    void getDocComment(Token *t, unsigned lineComment);
+
+    static int isValidIdentifier(char *p);
+    static unsigned char *combineComments(unsigned char *c1, unsigned char *c2);
+};
+
+#endif /* DMD_LEXER_H */
--- a/dmd/mangle.c	Fri Nov 06 21:51:41 2009 +0100
+++ b/dmd/mangle.c	Fri Nov 06 23:58:01 2009 +0100
@@ -1,292 +1,297 @@
-
-// Compiler implementation of the D programming language
-// Copyright (c) 1999-2009 by Digital Mars
-// All Rights Reserved
-// written by Walter Bright
-// http://www.digitalmars.com
-// License for redistribution is by either the Artistic License
-// in artistic.txt, or the GNU General Public License in gnu.txt.
-// See the included readme.txt for details.
-
-#include <stdio.h>
-#include <string.h>
-#include <ctype.h>
-#include <assert.h>
-
-#include "root.h"
-
-#include "init.h"
-#include "declaration.h"
-#include "aggregate.h"
-#include "mtype.h"
-#include "attrib.h"
-#include "template.h"
-#include "id.h"
-#include "module.h"
-
-#if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_SOLARIS
-char *cpp_mangle(Dsymbol *s);
-#endif
-
-char *mangle(Declaration *sthis)
-{
-    OutBuffer buf;
-    char *id;
-    Dsymbol *s;
-
-    //printf("::mangle(%s)\n", sthis->toChars());
-    s = sthis;
-    do
-    {
-	//printf("mangle: s = %p, '%s', parent = %p\n", s, s->toChars(), s->parent);
-	if (s->ident)
-	{
-	    FuncDeclaration *fd = s->isFuncDeclaration();
-	    if (s != sthis && fd)
-	    {
-		id = mangle(fd);
-		buf.prependstring(id);
-		goto L1;
-	    }
-	    else
-	    {
-		id = s->ident->toChars();
-		int len = strlen(id);
-		char tmp[sizeof(len) * 3 + 1];
-		buf.prependstring(id);
-		sprintf(tmp, "%d", len);
-		buf.prependstring(tmp);
-	    }
-	}
-	else
-	    buf.prependstring("0");
-	s = s->parent;
-    } while (s);
-
-//    buf.prependstring("_D");
-L1:
-    //printf("deco = '%s'\n", sthis->type->deco ? sthis->type->deco : "null");
-    //printf("sthis->type = %s\n", sthis->type->toChars());
-    FuncDeclaration *fd = sthis->isFuncDeclaration();
-    if (fd && (fd->needThis() || fd->isNested()))
-	buf.writeByte(Type::needThisPrefix());
-    if (sthis->type->deco)
-	buf.writestring(sthis->type->deco);
-    else
-    {	assert(fd->inferRetType);
-    }
-
-    id = buf.toChars();
-    buf.data = NULL;
-    return id;
-}
-
-char *Declaration::mangle()
-#if __DMC__
-    __out(result)
-    {
-	int len = strlen(result);
-
-	assert(len > 0);
-	//printf("mangle: '%s' => '%s'\n", toChars(), result);
-	for (int i = 0; i < len; i++)
-	{
-	    assert(result[i] == '_' ||
-		   result[i] == '@' ||
-		   isalnum(result[i]) || result[i] & 0x80);
-	}
-    }
-    __body
-#endif
-    {
-	//printf("Declaration::mangle(this = %p, '%s', parent = '%s', linkage = %d)\n", this, toChars(), parent ? parent->toChars() : "null", linkage);
-	if (!parent || parent->isModule())	// if at global scope
-	{
-	    // If it's not a D declaration, no mangling
-	    switch (linkage)
-	    {
-		case LINKd:
-		    break;
-
-        // LDC
-        case LINKintrinsic:
-
-		case LINKc:
-		case LINKwindows:
-		case LINKpascal:
-		    return ident->toChars();
-
-		case LINKcpp:
-#if DMDV2 && (TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_SOLARIS)
-		    return cpp_mangle(this);
-#else
-		    // Windows C++ mangling is done by C++ back end
-		    return ident->toChars();
-#endif
-
-		case LINKdefault:
-		    error("forward declaration");
-		    return ident->toChars();
-
-		default:
-		    fprintf(stdmsg, "'%s', linkage = %d\n", toChars(), linkage);
-		    assert(0);
-	    }
-	}
-	char *p = ::mangle(this);
-	OutBuffer buf;
-	buf.writestring("_D");
-	buf.writestring(p);
-	p = buf.toChars();
-	buf.data = NULL;
-	//printf("Declaration::mangle(this = %p, '%s', parent = '%s', linkage = %d) = %s\n", this, toChars(), parent ? parent->toChars() : "null", linkage, p);
-	return p;
-    }
-
-char *FuncDeclaration::mangle()
-#if __DMC__
-    __out(result)
-    {
-	assert(strlen(result) > 0);
-    }
-    __body
-#endif
-    {
-	if (isMain())
-	    return (char *)"_Dmain";
-
-	if (isWinMain() || isDllMain())
-	    return ident->toChars();
-
-	assert(this);
-	return Declaration::mangle();
-    }
-
-char *StructDeclaration::mangle()
-{
-    //printf("StructDeclaration::mangle() '%s'\n", toChars());
-    return Dsymbol::mangle();
-}
-
-
-char *TypedefDeclaration::mangle()
-{
-    //printf("TypedefDeclaration::mangle() '%s'\n", toChars());
-    return Dsymbol::mangle();
-}
-
-
-char *ClassDeclaration::mangle()
-{
-    Dsymbol *parentsave = parent;
-
-    //printf("ClassDeclaration::mangle() %s.%s\n", parent->toChars(), toChars());
-
-    /* These are reserved to the compiler, so keep simple
-     * names for them.
-     */
-    if (ident == Id::Exception)
-    {	if (parent->ident == Id::object)
-	    parent = NULL;
-    }
-    else if (ident == Id::TypeInfo   ||
-//	ident == Id::Exception ||
-	ident == Id::TypeInfo_Struct   ||
-	ident == Id::TypeInfo_Class    ||
-	ident == Id::TypeInfo_Typedef  ||
-	ident == Id::TypeInfo_Tuple ||
-	this == object     ||
-	this == classinfo  ||
-	this == Module::moduleinfo ||
-	memcmp(ident->toChars(), "TypeInfo_", 9) == 0
-       )
-	parent = NULL;
-
-    char *id = Dsymbol::mangle();
-    parent = parentsave;
-    return id;
-}
-
-
-char *TemplateInstance::mangle()
-{
-    OutBuffer buf;
-    char *id;
-
-#if 0
-    printf("TemplateInstance::mangle() %s", toChars());
-    if (parent)
-	printf("  parent = %s %s", parent->kind(), parent->toChars());
-    printf("\n");
-#endif
-    id = ident ? ident->toChars() : toChars();
-    if (!tempdecl)
-	error("is not defined");
-    else if (tempdecl->parent)
-    {
-	char *p = tempdecl->parent->mangle();
-	if (p[0] == '_' && p[1] == 'D')
-	    p += 2;
-	buf.writestring(p);
-    }
-    buf.printf("%zu%s", strlen(id), id);
-    id = buf.toChars();
-    buf.data = NULL;
-    //printf("TemplateInstance::mangle() %s = %s\n", toChars(), id);
-    return id;
-}
-
-
-char *TemplateMixin::mangle()
-{
-    OutBuffer buf;
-    char *id;
-
-#if 0
-    printf("TemplateMixin::mangle() %s", toChars());
-    if (parent)
-        printf("  parent = %s %s", parent->kind(), parent->toChars());
-    printf("\n");
-#endif
-    id = ident ? ident->toChars() : toChars();
-    if (parent)
-    {
-	char *p = parent->mangle();
-	if (p[0] == '_' && p[1] == 'D')
-	    p += 2;
-	buf.writestring(p);
-    }
-    buf.printf("%zu%s", strlen(id), id);
-    id = buf.toChars();
-    buf.data = NULL;
-    //printf("TemplateMixin::mangle() %s = %s\n", toChars(), id);
-    return id;
-}
-
-char *Dsymbol::mangle()
-{
-    OutBuffer buf;
-    char *id;
-
-#if 0
-    printf("Dsymbol::mangle() '%s'", toChars());
-    if (parent)
-	printf("  parent = %s %s", parent->kind(), parent->toChars());
-    printf("\n");
-#endif
-    id = ident ? ident->toChars() : toChars();
-    if (parent)
-    {
-	char *p = parent->mangle();
-	if (p[0] == '_' && p[1] == 'D')
-	    p += 2;
-	buf.writestring(p);
-    }
-    buf.printf("%zu%s", strlen(id), id);
-    id = buf.toChars();
-    buf.data = NULL;
-    //printf("Dsymbol::mangle() %s = %s\n", toChars(), id);
-    return id;
-}
-
-
+
+// Compiler implementation of the D programming language
+// Copyright (c) 1999-2009 by Digital Mars
+// All Rights Reserved
+// written by Walter Bright
+// http://www.digitalmars.com
+// License for redistribution is by either the Artistic License
+// in artistic.txt, or the GNU General Public License in gnu.txt.
+// See the included readme.txt for details.
+
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <assert.h>
+
+#include "root.h"
+
+#include "init.h"
+#include "declaration.h"
+#include "aggregate.h"
+#include "mtype.h"
+#include "attrib.h"
+#include "template.h"
+#include "id.h"
+#include "module.h"
+
+#if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_SOLARIS
+char *cpp_mangle(Dsymbol *s);
+#endif
+
+char *mangle(Declaration *sthis)
+{
+    OutBuffer buf;
+    char *id;
+    Dsymbol *s;
+
+    //printf("::mangle(%s)\n", sthis->toChars());
+    s = sthis;
+    do
+    {
+	//printf("mangle: s = %p, '%s', parent = %p\n", s, s->toChars(), s->parent);
+	if (s->ident)
+	{
+	    FuncDeclaration *fd = s->isFuncDeclaration();
+	    if (s != sthis && fd)
+	    {
+		id = mangle(fd);
+		buf.prependstring(id);
+		goto L1;
+	    }
+	    else
+	    {
+		id = s->ident->toChars();
+		int len = strlen(id);
+		char tmp[sizeof(len) * 3 + 1];
+		buf.prependstring(id);
+		sprintf(tmp, "%d", len);
+		buf.prependstring(tmp);
+	    }
+	}
+	else
+	    buf.prependstring("0");
+	s = s->parent;
+    } while (s);
+
+//    buf.prependstring("_D");
+L1:
+    //printf("deco = '%s'\n", sthis->type->deco ? sthis->type->deco : "null");
+    //printf("sthis->type = %s\n", sthis->type->toChars());
+    FuncDeclaration *fd = sthis->isFuncDeclaration();
+    if (fd && (fd->needThis() || fd->isNested()))
+	buf.writeByte(Type::needThisPrefix());
+    if (sthis->type->deco)
+	buf.writestring(sthis->type->deco);
+    else
+    {
+#ifdef DEBUG
+	if (!fd->inferRetType)
+	    printf("%s\n", fd->toChars());
+#endif
+	assert(fd && fd->inferRetType);
+    }
+
+    id = buf.toChars();
+    buf.data = NULL;
+    return id;
+}
+
+char *Declaration::mangle()
+#if __DMC__
+    __out(result)
+    {
+	int len = strlen(result);
+
+	assert(len > 0);
+	//printf("mangle: '%s' => '%s'\n", toChars(), result);
+	for (int i = 0; i < len; i++)
+	{
+	    assert(result[i] == '_' ||
+		   result[i] == '@' ||
+		   isalnum(result[i]) || result[i] & 0x80);
+	}
+    }
+    __body
+#endif
+    {
+	//printf("Declaration::mangle(this = %p, '%s', parent = '%s', linkage = %d)\n", this, toChars(), parent ? parent->toChars() : "null", linkage);
+	if (!parent || parent->isModule())	// if at global scope
+	{
+	    // If it's not a D declaration, no mangling
+	    switch (linkage)
+	    {
+		case LINKd:
+		    break;
+
+        // LDC
+        case LINKintrinsic:
+
+		case LINKc:
+		case LINKwindows:
+		case LINKpascal:
+		    return ident->toChars();
+
+		case LINKcpp:
+#if DMDV2 && (TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_SOLARIS)
+		    return cpp_mangle(this);
+#else
+		    // Windows C++ mangling is done by C++ back end
+		    return ident->toChars();
+#endif
+
+		case LINKdefault:
+		    error("forward declaration");
+		    return ident->toChars();
+
+		default:
+		    fprintf(stdmsg, "'%s', linkage = %d\n", toChars(), linkage);
+		    assert(0);
+	    }
+	}
+	char *p = ::mangle(this);
+	OutBuffer buf;
+	buf.writestring("_D");
+	buf.writestring(p);
+	p = buf.toChars();
+	buf.data = NULL;
+	//printf("Declaration::mangle(this = %p, '%s', parent = '%s', linkage = %d) = %s\n", this, toChars(), parent ? parent->toChars() : "null", linkage, p);
+	return p;
+    }
+
+char *FuncDeclaration::mangle()
+#if __DMC__
+    __out(result)
+    {
+	assert(strlen(result) > 0);
+    }
+    __body
+#endif
+    {
+	if (isMain())
+	    return (char *)"_Dmain";
+
+	if (isWinMain() || isDllMain())
+	    return ident->toChars();
+
+	assert(this);
+	return Declaration::mangle();
+    }
+
+char *StructDeclaration::mangle()
+{
+    //printf("StructDeclaration::mangle() '%s'\n", toChars());
+    return Dsymbol::mangle();
+}
+
+
+char *TypedefDeclaration::mangle()
+{
+    //printf("TypedefDeclaration::mangle() '%s'\n", toChars());
+    return Dsymbol::mangle();
+}
+
+
+char *ClassDeclaration::mangle()
+{
+    Dsymbol *parentsave = parent;
+
+    //printf("ClassDeclaration::mangle() %s.%s\n", parent->toChars(), toChars());
+
+    /* These are reserved to the compiler, so keep simple
+     * names for them.
+     */
+    if (ident == Id::Exception)
+    {	if (parent->ident == Id::object)
+	    parent = NULL;
+    }
+    else if (ident == Id::TypeInfo   ||
+//	ident == Id::Exception ||
+	ident == Id::TypeInfo_Struct   ||
+	ident == Id::TypeInfo_Class    ||
+	ident == Id::TypeInfo_Typedef  ||
+	ident == Id::TypeInfo_Tuple ||
+	this == object     ||
+	this == classinfo  ||
+	this == Module::moduleinfo ||
+	memcmp(ident->toChars(), "TypeInfo_", 9) == 0
+       )
+	parent = NULL;
+
+    char *id = Dsymbol::mangle();
+    parent = parentsave;
+    return id;
+}
+
+
+char *TemplateInstance::mangle()
+{
+    OutBuffer buf;
+    char *id;
+
+#if 0
+    printf("TemplateInstance::mangle() %s", toChars());
+    if (parent)
+	printf("  parent = %s %s", parent->kind(), parent->toChars());
+    printf("\n");
+#endif
+    id = ident ? ident->toChars() : toChars();
+    if (!tempdecl)
+	error("is not defined");
+    else if (tempdecl->parent)
+    {
+	char *p = tempdecl->parent->mangle();
+	if (p[0] == '_' && p[1] == 'D')
+	    p += 2;
+	buf.writestring(p);
+    }
+    buf.printf("%zu%s", strlen(id), id);
+    id = buf.toChars();
+    buf.data = NULL;
+    //printf("TemplateInstance::mangle() %s = %s\n", toChars(), id);
+    return id;
+}
+
+
+char *TemplateMixin::mangle()
+{
+    OutBuffer buf;
+    char *id;
+
+#if 0
+    printf("TemplateMixin::mangle() %s", toChars());
+    if (parent)
+        printf("  parent = %s %s", parent->kind(), parent->toChars());
+    printf("\n");
+#endif
+    id = ident ? ident->toChars() : toChars();
+    if (parent)
+    {
+	char *p = parent->mangle();
+	if (p[0] == '_' && p[1] == 'D')
+	    p += 2;
+	buf.writestring(p);
+    }
+    buf.printf("%zu%s", strlen(id), id);
+    id = buf.toChars();
+    buf.data = NULL;
+    //printf("TemplateMixin::mangle() %s = %s\n", toChars(), id);
+    return id;
+}
+
+char *Dsymbol::mangle()
+{
+    OutBuffer buf;
+    char *id;
+
+#if 0
+    printf("Dsymbol::mangle() '%s'", toChars());
+    if (parent)
+	printf("  parent = %s %s", parent->kind(), parent->toChars());
+    printf("\n");
+#endif
+    id = ident ? ident->toChars() : toChars();
+    if (parent)
+    {
+	char *p = parent->mangle();
+	if (p[0] == '_' && p[1] == 'D')
+	    p += 2;
+	buf.writestring(p);
+    }
+    buf.printf("%zu%s", strlen(id), id);
+    id = buf.toChars();
+    buf.data = NULL;
+    //printf("Dsymbol::mangle() %s = %s\n", toChars(), id);
+    return id;
+}
+
+
--- a/dmd/mars.c	Fri Nov 06 21:51:41 2009 +0100
+++ b/dmd/mars.c	Fri Nov 06 23:58:01 2009 +0100
@@ -32,6 +32,7 @@
 #include "cond.h"
 #include "expression.h"
 #include "lexer.h"
+#include "json.h"
 
 #include "gen/revisions.h"
 
@@ -44,6 +45,7 @@
     hdr_ext  = "di";
     doc_ext  = "html";
     ddoc_ext = "ddoc";
+    json_ext = "json";
 
 // LDC
     ll_ext  = "ll";
@@ -56,7 +58,7 @@
 
     copyright = "Copyright (c) 1999-2009 by Digital Mars and Tomas Lindquist Olsen";
     written = "written by Walter Bright and Tomas Lindquist Olsen";
-    version = "v1.045";
+    version = "v1.051";
     ldc_version = LDC_REV;
     llvm_version = LLVM_REV_STR;
     global.structalign = 8;
@@ -90,6 +92,11 @@
     this->filename = mod ? mod->srcfile->toChars() : NULL;
 }
 
+bool Loc::equals(const Loc& loc)
+{
+    return linnum == loc.linnum && FileName::equals(filename, loc.filename);
+}
+
 /**************************************
  * Print error message and exit.
  */
@@ -180,25 +187,20 @@
 
 void getenv_setargv(const char *envvar, int *pargc, char** *pargv)
 {
-    char *env;
     char *p;
-    Array *argv;
-    int argc;
 
-    int wildcard;		// do wildcard expansion
     int instring;
     int slash;
     char c;
-    int j;
 
-    env = getenv(envvar);
+    char *env = getenv(envvar);
     if (!env)
 	return;
 
     env = mem.strdup(env);	// create our own writable copy
 
-    argc = *pargc;
-    argv = new Array();
+    int argc = *pargc;
+    Array *argv = new Array();
     argv->setDim(argc);
 
     int argc_left = 0;
@@ -220,10 +222,10 @@
     argv->push((char*)"");
     argc++;
 
-    j = 1;			// leave argv[0] alone
+    int j = 1;			// leave argv[0] alone
     while (1)
     {
-	wildcard = 1;
+	int wildcard = 1;	// do wildcard expansion
 	switch (*env)
 	{
 	    case ' ':
--- a/dmd/mars.h	Fri Nov 06 21:51:41 2009 +0100
+++ b/dmd/mars.h	Fri Nov 06 23:58:01 2009 +0100
@@ -48,6 +48,7 @@
 	TARGET_OSX	Covers 32 and 64 bit Mac OSX
 	TARGET_FREEBSD	Covers 32 and 64 bit FreeBSD
 	TARGET_SOLARIS	Covers 32 and 64 bit Solaris
+	TARGET_NET	Covers .Net
 
     It is expected that the compiler for each platform will be able
     to generate 32 and 64 bit code from the same compiler binary.
@@ -161,6 +162,7 @@
     bool optimize;      // run optimizer
     char optimizeLevel; // optimization level
 #endif
+    char vtls;		// identify thread local variables
     ARCH cpu;		// target CPU
     OS   os;		// target OS
     bool is64bit;       // generate 64 bit code
@@ -193,6 +195,9 @@
     char *hdrdir;		// write 'header' file to docdir directory
     char *hdrname;		// write 'header' file to docname
 
+    char doXGeneration;		// write JSON file
+    char *xfilename;		// write JSON file to xfilename
+
     unsigned debuglevel;	// debug level
     Array *debugids;		// debug identifiers
 
@@ -204,11 +209,9 @@
     Array *defaultlibnames;	// default libraries for non-debug builds
     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;
@@ -260,6 +263,7 @@
     const char *doc_ext;	// for Ddoc generated files
     const char *ddoc_ext;	// for Ddoc macro include files
     const char *hdr_ext;	// for D 'header' import files
+    const char *json_ext;	// for JSON files
     const char *copyright;
     const char *written;
     Array *path;	// Array of char*'s which form the import lookup path
@@ -344,7 +348,7 @@
 //typedef unsigned Loc;		// file location
 struct Loc
 {
-    char *filename;
+    const char *filename;
     unsigned linnum;
 
     Loc()
@@ -362,6 +366,7 @@
     Loc(Module *mod, unsigned linnum);
 
     char *toChars() const;
+    bool equals(const Loc& loc);
 };
 
 #ifndef GCC_SAFE_DMD
@@ -426,7 +431,7 @@
 #if IN_GCC || IN_LLVM
 #define stdmsg stderr
 #else
-#define stdmsg stdout
+#define stdmsg stderr
 #endif
 
 #endif /* DMD_MARS_H */
--- a/dmd/module.c	Fri Nov 06 21:51:41 2009 +0100
+++ b/dmd/module.c	Fri Nov 06 23:58:01 2009 +0100
@@ -95,7 +95,7 @@
     searchCacheSymbol = NULL;
     searchCacheFlags = 0;
     semanticstarted = 0;
-    semanticdone = 0;
+    semanticRun = 0;
     decldefs = NULL;
     vmoduleinfo = NULL;
 #if IN_DMD
@@ -123,6 +123,7 @@
 
     macrotable = NULL;
     escapetable = NULL;
+    safe = FALSE;
 #if IN_DMD
     doppelganger = 0;
     cov = NULL;
@@ -661,9 +662,65 @@
     }
 }
 
-void Module::semantic(Scope* unused_sc)
-{   int i;
+void Module::importAll(Scope *prevsc)
+{
+    //printf("+Module::importAll(this = %p, '%s'): parent = %p\n", this, toChars(), parent);
+
+    if (scope)
+	return;			// already done
+
+    /* Note that modules get their own scope, from scratch.
+     * This is so regardless of where in the syntax a module
+     * gets imported, it is unaffected by context.
+     * Ignore prevsc.
+     */
+    Scope *sc = Scope::createGlobal(this);	// create root scope
+
+    // Add import of "object" if this module isn't "object"
+    if (ident != Id::object)
+    {
+	if (members->dim == 0 || ((Dsymbol *)members->data[0])->ident != Id::object)
+	{
+	    Import *im = new Import(0, NULL, Id::object, NULL, 0);
+	    members->shift(im);
+	}
+    }
 
+    if (!symtab)
+    {
+	// Add all symbols into module's symbol table
+	symtab = new DsymbolTable();
+	for (int i = 0; i < members->dim; i++)
+	{
+	    Dsymbol *s = (Dsymbol *)members->data[i];
+	    s->addMember(NULL, sc->scopesym, 1);
+	}
+    }
+    // anything else should be run after addMember, so version/debug symbols are defined
+
+    /* 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.
+     */
+    setScope(sc);		// remember module scope for semantic
+    for (int i = 0; i < members->dim; i++)
+    {	Dsymbol *s = (Dsymbol *)members->data[i];
+	s->setScope(sc);
+    }
+
+    for (int i = 0; i < members->dim; i++)
+    {
+	Dsymbol *s = (Dsymbol *)members->data[i];
+	s->importAll(sc);
+    }
+
+    sc = sc->pop();
+    sc->pop();		// 2 pops because Scope::createGlobal() created 2
+}
+
+void Module::semantic(Scope *unused_sc)
+{
     if (semanticstarted)
 	return;
 
@@ -673,10 +730,15 @@
     // Note that modules get their own scope, from scratch.
     // This is so regardless of where in the syntax a module
     // gets imported, it is unaffected by context.
-    Scope *sc = Scope::createGlobal(this);	// create root scope
+    Scope *sc = scope;			// see if already got one from importAll()
+    if (!sc)
+    {	printf("test2\n");
+	Scope::createGlobal(this);	// create root scope
+    }
 
     //printf("Module = %p, linkage = %d\n", sc->scopesym, sc->linkage);
 
+#if 0
     // Add import of "object" if this module isn't "object"
     if (ident != Id::object)
     {
@@ -686,26 +748,36 @@
 
     // Add all symbols into module's symbol table
     symtab = new DsymbolTable();
-    for (i = 0; i < members->dim; i++)
-    {	Dsymbol *s;
-
-	s = (Dsymbol *)members->data[i];
+    for (int i = 0; i < members->dim; i++)
+    {	Dsymbol *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 (int i = 0; i < members->dim; i++)
+    {	Dsymbol *s = (Dsymbol *)members->data[i];
+	s->setScope(sc);
+    }
+#endif
+
     // Pass 1 semantic routines: do public side of the definition
-    for (i = 0; i < members->dim; i++)
-    {	Dsymbol *s;
+    for (int i = 0; i < members->dim; i++)
+    {	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;
+    if (!scope)
+    {	sc = sc->pop();
+	sc->pop();		// 2 pops because Scope::createGlobal() created 2
+    }
+    semanticRun = semanticstarted;
     //printf("-Module::semantic(this = %p, '%s'): parent = %p\n", this, toChars(), parent);
 }
 
@@ -744,7 +816,7 @@
 
     sc = sc->pop();
     sc->pop();
-    semanticdone = semanticstarted;
+    semanticRun = semanticstarted;
     //printf("-Module::semantic2('%s'): parent = %p\n", toChars(), parent);
 }
 
@@ -774,12 +846,11 @@
 
     sc = sc->pop();
     sc->pop();
-    semanticdone = semanticstarted;
+    semanticRun = semanticstarted;
 }
 
 void Module::inlineScan()
-{   int i;
-
+{
     if (semanticstarted >= 4)
 	return;
     assert(semanticstarted == 3);
@@ -790,16 +861,14 @@
     // gets imported, it is unaffected by context.
     //printf("Module = %p\n", sc.scopesym);
 
-    for (i = 0; i < members->dim; i++)
-    {	Dsymbol *s;
-
-	s = (Dsymbol *)members->data[i];
+    for (int i = 0; i < members->dim; i++)
+    {	Dsymbol *s = (Dsymbol *)members->data[i];
 	//if (global.params.verbose)
 	    //printf("inline scan symbol %s\n", s->toChars());
 
 	s->inlineScan();
     }
-    semanticdone = semanticstarted;
+    semanticRun = semanticstarted;
 }
 
 /****************************************************
@@ -844,6 +913,7 @@
 {
     /* Since modules can be circularly referenced,
      * need to stop infinite recursive searches.
+     * This is done with the cache.
      */
 
     //printf("%s Module::search('%s', flags = %d) insearch = %d\n", toChars(), ident->toChars(), flags, insearch);
@@ -851,7 +921,10 @@
     if (insearch)
 	s = NULL;
     else if (searchCacheIdent == ident && searchCacheFlags == flags)
+    {
 	s = searchCacheSymbol;
+	//printf("%s Module::search('%s', flags = %d) insearch = %d searchCacheSymbol = %s\n", toChars(), ident->toChars(), flags, insearch, searchCacheSymbol ? searchCacheSymbol->toChars() : "null");
+    }
     else
     {
 	insearch = 1;
@@ -865,6 +938,13 @@
     return s;
 }
 
+Dsymbol *Module::symtabInsert(Dsymbol *s)
+{
+    searchCacheIdent = 0;	// symbol is inserted, so invalidate cache
+    return Package::symtabInsert(s);
+}
+
+
 /*******************************************
  * Can't run semantic on s now, try again later.
  */
@@ -1059,11 +1139,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/dmd/module.h	Fri Nov 06 21:51:41 2009 +0100
+++ b/dmd/module.h	Fri Nov 06 23:58:01 2009 +0100
@@ -94,7 +94,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
@@ -119,8 +119,10 @@
     Macro *macrotable;		// document comment macros
     struct Escape *escapetable;	// document comment escapes
 
-    int doDocComment;		// enable generating doc comments for this module
-    int doHdrGen;		// enable generating header file for this module
+    int doDocComment;          // enable generating doc comments for this module
+    int doHdrGen;              // enable generating header file for this module
+
+    bool safe;			// TRUE if module is marked as 'safe'
 
     Module(char *arg, Identifier *ident, int doDocComment, int doHdrGen);
     ~Module();
@@ -128,6 +130,7 @@
     static Module *load(Loc loc, Array *packages, Identifier *ident);
 
     void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+    void toJsonBuffer(OutBuffer *buf);
     const char *kind();
     void read(Loc loc);	// read file
 #if IN_GCC
@@ -135,6 +138,7 @@
 #else
     void parse();	// syntactic parse
 #endif
+    void importAll(Scope *sc);
     void semantic(Scope* unused_sc = NULL);	// semantic analysis
     void semantic2(Scope* unused_sc = NULL);	// pass 2 semantic analysis
     void semantic3(Scope* unused_sc = NULL);	// pass 3 semantic analysis
@@ -146,6 +150,7 @@
     void gendocfile();
     int needModuleInfo();
     Dsymbol *search(Loc loc, Identifier *ident, int flags);
+    Dsymbol *symtabInsert(Dsymbol *s);
     void deleteObjFile();
     void addDeferredSemantic(Dsymbol *s);
     void runDeferredSemantic();
@@ -198,6 +203,7 @@
 {
     Identifier *id;
     Array *packages;		// array of Identifier's representing packages
+    bool safe;
 
     ModuleDeclaration(Array *packages, Identifier *id);
 
--- a/dmd/mtype.c	Fri Nov 06 21:51:41 2009 +0100
+++ b/dmd/mtype.c	Fri Nov 06 23:58:01 2009 +0100
@@ -1514,16 +1514,8 @@
 
     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;
 
@@ -1534,6 +1526,7 @@
 	if (tob->flags & (TFLAGSimaginary | TFLAGScomplex))
 	    return MATCHnomatch;
 
+#if DMDV2
 	// If converting to integral
 	if (0 && global.params.Dversion > 1 && tob->flags & TFLAGSintegral)
 	{   d_uns64 sz = size(0);
@@ -1547,6 +1540,7 @@
 	    /*if (sz == tosz && (flags ^ tob->flags) & TFLAGSunsigned)
 		return MATCHnomatch;*/
 	}
+#endif
     }
     else if (flags & TFLAGSfloating)
     {
@@ -2347,6 +2341,7 @@
 	case Tfunction:
 	case Tvoid:
 	case Tnone:
+	case Ttuple:
 	    error(loc, "can't have associative array key of %s", key->toChars());
 	    break;
     }
@@ -2557,6 +2552,9 @@
 
 Type *TypePointer::semantic(Loc loc, Scope *sc)
 {
+    if (deco)
+	return this;
+
     //printf("TypePointer::semantic()\n");
     Type *n = next->semantic(loc, sc);
     switch (n->toBasetype()->ty)
@@ -2792,6 +2790,9 @@
     Type *t1n = t1->next;
     Type *t2n = t2->next;
 
+    if (!t1n || !t2n)		// happens with return type inference
+	goto Lnotcovariant;
+
     if (t1n->equals(t2n))
 	goto Lcovariant;
     if (t1n->ty != Tclass || t2n->ty != Tclass)
@@ -2936,10 +2937,10 @@
 	switch (linkage)
 	{
 	    case LINKd:		p = NULL;	break;
-	    case LINKc:		p = "C ";	break;
-	    case LINKwindows:	p = "Windows ";	break;
-	    case LINKpascal:	p = "Pascal ";	break;
-	    case LINKcpp:	p = "C++ ";	break;
+	    case LINKc:		p = " C";	break;
+	    case LINKwindows:	p = " Windows";	break;
+	    case LINKpascal:	p = " Pascal";	break;
+	    case LINKcpp:	p = " C++";	break;
 
         // LDC
         case LINKintrinsic: p = "Intrinsic"; break;
@@ -2978,36 +2979,39 @@
     }
 
     tf->linkage = sc->linkage;
-    if (!tf->next)
+    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->isscope() && !(sc->flags & SCOPEctor))
-	error(loc, "functions cannot return scope %s", tf->next->toChars());
+	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->isscope() && !(sc->flags & SCOPEctor))
+	    error(loc, "functions cannot return scope %s", tf->next->toChars());
+    }
 
     if (tf->parameters)
-    {	size_t dim = Argument::dim(tf->parameters);
-
+    {
+	/* Create a scope for evaluating the default arguments for the parameters
+	 */
+	Scope *argsc = sc->push();
+	argsc->stc = 0;			// don't inherit storage class
+	argsc->protection = PROTpublic;
+
+	size_t dim = Argument::dim(tf->parameters);
 	for (size_t i = 0; i < dim; i++)
 	{   Argument *arg = Argument::getNth(tf->parameters, i);
-	    Type *t;
 
 	    tf->inuse++;
-	    arg->type = arg->type->semantic(loc,sc);
+	    arg->type = arg->type->semantic(loc, argsc);
 	    if (tf->inuse == 1) tf->inuse--;
 
 	    // each function needs its own copy of a tuple arg, since
@@ -3019,7 +3023,7 @@
 		if (tf->inuse == 1) tf->inuse--;
 	    }
 
-	    t = arg->type->toBasetype();
+	    Type *t = arg->type->toBasetype();
 
 	    if (arg->storageClass & (STCout | STCref | STClazy))
 	    {
@@ -3031,9 +3035,9 @@
 
 	    if (arg->defaultArg)
 	    {
-		arg->defaultArg = arg->defaultArg->semantic(sc);
-		arg->defaultArg = resolveProperties(sc, arg->defaultArg);
-		arg->defaultArg = arg->defaultArg->implicitCastTo(sc, arg->type);
+		arg->defaultArg = arg->defaultArg->semantic(argsc);
+		arg->defaultArg = resolveProperties(argsc, arg->defaultArg);
+		arg->defaultArg = arg->defaultArg->implicitCastTo(argsc, arg->type);
 	    }
 
 	    /* If arg turns out to be a tuple, the number of parameters may
@@ -3044,8 +3048,10 @@
 		i--;
 	    }
 	}
-    }
-    tf->deco = tf->merge()->deco;
+	argsc->pop();
+    }
+    if (tf->next)
+	tf->deco = tf->merge()->deco;
 
     if (tf->inuse)
     {	error(loc, "recursive type");
@@ -3419,6 +3425,19 @@
 			goto Lerror;
 		    goto L3;
 		}
+		else if (v && id == Id::stringof)
+		{
+		    e = new DsymbolExp(loc, s);
+		    do
+		    {
+			id = (Identifier *)idents.data[i];
+			e = new DotIdExp(loc, e, id);
+		    } while (++i < idents.dim);
+		    e = e->semantic(sc);
+		    *pe = e;
+		    return;
+		}
+
 		t = s->getType();
 		if (!t && s->isDeclaration())
 		    t = s->isDeclaration()->type;
@@ -3515,23 +3534,33 @@
 	{
 	    if (t->reliesOnTident())
 	    {
-		Scope *scx;
-
-		for (scx = sc; 1; scx = scx->enclosing)
+		if (s->scope)
+		    t = t->semantic(loc, s->scope);
+		else
 		{
-		    if (!scx)
-		    {   error(loc, "forward reference to '%s'", t->toChars());
-			return;
+		    /* Attempt to find correct scope in which to evaluate t.
+		     * Not sure if this is right or not, or if we should just
+		     * give forward reference error if s->scope is not set.
+		     */
+		    for (Scope *scx = sc; 1; scx = scx->enclosing)
+		    {
+			if (!scx)
+			{   error(loc, "forward reference to '%s'", t->toChars());
+			    return;
+			}
+			if (scx->scopesym == scopesym)
+			{
+			    t = t->semantic(loc, scx);
+			    break;
+			}
 		    }
-		    if (scx->scopesym == scopesym)
-			break;
 		}
-		t = t->semantic(loc, scx);
-		//((TypeIdentifier *)t)->resolve(loc, scx, pe, &t, ps);
 	    }
 	}
 	if (t->ty == Ttuple)
 	    *pt = t;
+	else if (t->ty == Ttypeof)
+	    *pt = t->semantic(loc, sc);
 	else
 	    *pt = t->merge();
     }
@@ -3762,7 +3791,8 @@
     if (!t)
     {
 #ifdef DEBUG
-	printf("2: ");
+	if (s) printf("s = %s\n", s->kind());
+	printf("2: e:%p s:%p ", e, s);
 #endif
 	error(loc, "%s is used as a type", toChars());
 	t = tvoid;
@@ -3839,6 +3869,11 @@
     toCBuffer2Helper(buf, hgs);
 }
 
+void TypeTypeof::toDecoBuffer(OutBuffer *buf, bool mangle)
+{
+    assert(0);
+}
+
 Type *TypeTypeof::semantic(Loc loc, Scope *sc)
 {   Expression *e;
     Type *t;
@@ -3970,7 +4005,7 @@
 
 Type *TypeEnum::semantic(Loc loc, Scope *sc)
 {
-    sym->semantic(sc);
+    //sym->semantic(sc);
     return merge();
 }
 
@@ -4562,7 +4597,7 @@
 
     TemplateInstance *ti = s->isTemplateInstance();
     if (ti)
-    {	if (!ti->semanticdone)
+    {	if (!ti->semanticRun)
 	    ti->semantic(sc);
 	s = ti->inst->toAlias();
 	if (!s->isTemplateInstance())
@@ -4695,7 +4730,7 @@
 
 char *TypeClass::toChars()
 {
-    return sym->toPrettyChars();
+    return (char *)sym->toPrettyChars();
 }
 
 Type *TypeClass::syntaxCopy()
@@ -4706,8 +4741,8 @@
 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;
     return merge();
 }
 
@@ -4975,7 +5010,7 @@
 
     TemplateInstance *ti = s->isTemplateInstance();
     if (ti)
-    {	if (!ti->semanticdone)
+    {	if (!ti->semanticRun)
 	    ti->semantic(sc);
 	s = ti->inst->toAlias();
 	if (!s->isTemplateInstance())
@@ -4994,9 +5029,16 @@
 
     if (e->op == TOKtype)
     {
-	VarExp *ve;
-
-	if (d->needThis() && (hasThis(sc) || !d->isFuncDeclaration()))
+	/* It's:
+	 *    Class.d
+	 */
+	if (d->isTupleDeclaration())
+	{
+	    e = new TupleExp(e->loc, d->isTupleDeclaration());
+	    e = e->semantic(sc);
+	    return e;
+	}
+	else if (d->needThis() && (hasThis(sc) || !(sc->intypeof || d->isFuncDeclaration())))
 	{
 	    if (sc->func)
 	    {
@@ -5025,15 +5067,11 @@
 	    e = de->semantic(sc);
 	    return e;
 	}
-	else if (d->isTupleDeclaration())
+	else
 	{
-	    e = new TupleExp(e->loc, d->isTupleDeclaration());
-	    e = e->semantic(sc);
-	    return e;
+	    VarExp *ve = new VarExp(e->loc, d);
+	    return ve;
 	}
-	else
-	    ve = new VarExp(e->loc, d);
-	return ve;
     }
 
     if (d->isDataseg())
--- a/dmd/mtype.h	Fri Nov 06 21:51:41 2009 +0100
+++ b/dmd/mtype.h	Fri Nov 06 23:58:01 2009 +0100
@@ -561,6 +561,7 @@
     Type *syntaxCopy();
     Dsymbol *toDsymbol(Scope *sc);
     void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
+    void toDecoBuffer(OutBuffer *buf, bool mangle);
     Type *semantic(Loc loc, Scope *sc);
     d_uns64 size(Loc loc);
 };
--- a/dmd/opover.c	Fri Nov 06 21:51:41 2009 +0100
+++ b/dmd/opover.c	Fri Nov 06 23:58:01 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
@@ -33,7 +33,7 @@
 static Expression *build_overload(Loc loc, Scope *sc, Expression *ethis, Expression *earg, Identifier *id);
 static void inferApplyArgTypesX(Module* from, FuncDeclaration *fstart, Arguments *arguments);
 static int inferApplyArgTypesY(TypeFunction *tf, Arguments *arguments);
-static void templateResolve(Match *m, TemplateDeclaration *td, Scope *sc, Loc loc, Objects *targsi, Expressions *arguments);
+static void templateResolve(Match *m, TemplateDeclaration *td, Scope *sc, Loc loc, Objects *targsi, Expression *ethis, Expressions *arguments);
 
 /******************************** Expression **************************/
 
@@ -158,6 +158,7 @@
 
 Expression *UnaExp::op_overload(Scope *sc)
 {
+    //printf("UnaExp::op_overload() (%s)\n", toChars());
     AggregateDeclaration *ad;
     Dsymbol *fd;
     Type *t1 = e1->type->toBasetype();
@@ -177,10 +178,11 @@
 	{
 	    if (op == TOKarray)
 	    {
-		Expression *e;
+		/* Rewrite op e1[arguments] as:
+		 *    e1.fd(arguments)
+		 */
+		Expression *e = new DotIdExp(loc, e1, fd->ident);
 		ArrayExp *ae = (ArrayExp *)this;
-
-		e = new DotIdExp(loc, e1, fd->ident);
 		e = new CallExp(loc, e, ae->arguments);
 		e = e->semantic(sc);
 		return e;
@@ -191,6 +193,21 @@
 		return build_overload(loc, sc, e1, NULL, fd->ident);
 	    }
 	}
+
+#if DMDV2
+	// Didn't find it. Forward to aliasthis
+	if (ad->aliasthis)
+	{
+	    /* Rewrite op(e1) as:
+	     *	op(e1.aliasthis)
+	     */
+	    Expression *e1 = new DotIdExp(loc, this->e1, ad->aliasthis->ident);
+	    Expression *e = copy();
+	    ((UnaExp *)e)->e1 = e1;
+	    e = e->semantic(sc);
+	    return e;
+	}
+#endif
     }
     return NULL;
 }
@@ -264,11 +281,11 @@
 	    fd = s->isFuncDeclaration();
 	    if (fd)
 	    {
-		overloadResolveX(&m, fd, &args2, sc->module);
+		overloadResolveX(&m, fd, NULL, &args2, sc->module);
 	    }
 	    else
 	    {   td = s->isTemplateDeclaration();
-		templateResolve(&m, td, sc, loc, NULL, &args2);
+		templateResolve(&m, td, sc, loc, NULL, NULL, &args2);
 	    }
 	}
 	
@@ -279,11 +296,11 @@
 	    fd = s_r->isFuncDeclaration();
 	    if (fd)
 	    {
-		overloadResolveX(&m, fd, &args1, sc->module);
+		overloadResolveX(&m, fd, NULL, &args1, sc->module);
 	    }
 	    else
 	    {   td = s_r->isTemplateDeclaration();
-		templateResolve(&m, td, sc, loc, NULL, &args1);
+		templateResolve(&m, td, sc, loc, NULL, NULL, &args1);
 	    }
 	}
 
@@ -335,7 +352,6 @@
 	     *	b.opfunc(a)
 	     * and see which is better.
 	     */
-	    Expression *e;
 	    FuncDeclaration *lastf;
 
 	    if (!argsset)
@@ -353,11 +369,11 @@
 		fd = s_r->isFuncDeclaration();
 		if (fd)
 		{
-		    overloadResolveX(&m, fd, &args2, sc->module);
+		    overloadResolveX(&m, fd, NULL, &args2, sc->module);
 		}
 		else
 		{   td = s_r->isTemplateDeclaration();
-		    templateResolve(&m, td, sc, loc, NULL, &args2);
+		    templateResolve(&m, td, sc, loc, NULL, NULL, &args2);
 		}
 	    }
 	    lastf = m.lastf;
@@ -367,11 +383,11 @@
 		fd = s->isFuncDeclaration();
 		if (fd)
 		{
-		    overloadResolveX(&m, fd, &args1, sc->module);
+		    overloadResolveX(&m, fd, NULL, &args1, sc->module);
 		}
 		else
 		{   td = s->isTemplateDeclaration();
-		    templateResolve(&m, td, sc, loc, NULL, &args1);
+		    templateResolve(&m, td, sc, loc, NULL, NULL, &args1);
 		}
 	    }
 
@@ -388,6 +404,7 @@
 		m.lastf = m.anyf;
 	    }
 
+	    Expression *e;
 	    if (lastf && m.lastf == lastf ||
 		id_r && m.last == MATCHnomatch)
 		// Rewrite (e1 op e2) as e1.opfunc_r(e2)
@@ -423,6 +440,33 @@
 	}
     }
 
+#if DMDV2
+    // Try alias this on first operand
+    if (ad1 && ad1->aliasthis)
+    {
+	/* Rewrite (e1 op e2) as:
+	 *	(e1.aliasthis op e2)
+	 */
+	Expression *e1 = new DotIdExp(loc, this->e1, ad1->aliasthis->ident);
+	Expression *e = copy();
+	((BinExp *)e)->e1 = e1;
+	e = e->semantic(sc);
+	return e;
+    }
+
+    // Try alias this on second operand
+    if (ad2 && ad2->aliasthis)
+    {
+	/* Rewrite (e1 op e2) as:
+	 *	(e1 op e2.aliasthis)
+	 */
+	Expression *e2 = new DotIdExp(loc, this->e2, ad2->aliasthis->ident);
+	Expression *e = copy();
+	((BinExp *)e)->e2 = e2;
+	e = e->semantic(sc);
+	return e;
+    }
+#endif
     return NULL;
 }
 
@@ -430,7 +474,7 @@
  * Utility to build a function call out of this reference and argument.
  */
 
-static Expression *build_overload(Loc loc, Scope *sc, Expression *ethis, Expression *earg, Identifier *id)
+Expression *build_overload(Loc loc, Scope *sc, Expression *ethis, Expression *earg, Identifier *id)
 {
     Expression *e;
 
@@ -499,7 +543,6 @@
     }
 
     AggregateDeclaration *ad;
-    FuncDeclaration *fd;
 
     Argument *arg = (Argument *)arguments->data[0];
     Type *taggr = aggr->type;
@@ -570,7 +613,7 @@
 						   : Id::apply);
 	    if (s)
 	    {
-		fd = s->isFuncDeclaration();
+		FuncDeclaration *fd = s->isFuncDeclaration();
 		if (fd) 
 		    inferApplyArgTypesX(from, fd, arguments);
 	    }
@@ -582,7 +625,7 @@
 	    if (0 && aggr->op == TOKdelegate)
 	    {	DelegateExp *de = (DelegateExp *)aggr;
 
-		fd = de->func->isFuncDeclaration();
+		FuncDeclaration *fd = de->func->isFuncDeclaration();
 		if (fd)
 		    inferApplyArgTypesX(from, fd, arguments);
 	    }
@@ -719,7 +762,7 @@
 /**************************************
  */
 
-static void templateResolve(Match *m, TemplateDeclaration *td, Scope *sc, Loc loc, Objects *targsi, Expressions *arguments)
+static void templateResolve(Match *m, TemplateDeclaration *td, Scope *sc, Loc loc, Objects *targsi, Expression *ethis, Expressions *arguments)
 {
     FuncDeclaration *fd;
 
--- a/dmd/optimize.c	Fri Nov 06 21:51:41 2009 +0100
+++ b/dmd/optimize.c	Fri Nov 06 23:58:01 2009 +0100
@@ -1,793 +1,834 @@
-
-// Compiler implementation of the D programming language
-// Copyright (c) 1999-2009 by Digital Mars
-// All Rights Reserved
-// written by Walter Bright
-// http://www.digitalmars.com
-// License for redistribution is by either the Artistic License
-// in artistic.txt, or the GNU General Public License in gnu.txt.
-// See the included readme.txt for details.
-
-#include <stdio.h>
-#include <ctype.h>
-#include <assert.h>
-#include <math.h>
-
-#if __DMC__
-#include <complex.h>
-#endif
-
-#include "lexer.h"
-#include "mtype.h"
-#include "expression.h"
-#include "declaration.h"
-#include "aggregate.h"
-#include "init.h"
-
-
-#ifdef IN_GCC
-#include "d-gcc-real.h"
-
-/* %% fix? */
-extern "C" bool real_isnan (const real_t *);
-#endif
-
-static real_t zero;	// work around DMC bug for now
-
-
-/*************************************
- * If expression is a variable with a const initializer,
- * return that initializer.
- */
-
-Expression *fromConstInitializer(Expression *e1)
-{
-    //printf("fromConstInitializer(%s)\n", e1->toChars());
-    if (e1->op == TOKvar)
-    {	VarExp *ve = (VarExp *)e1;
-	VarDeclaration *v = ve->var->isVarDeclaration();
-	if (v && v->isConst() && v->init)
-	{   Expression *ei = v->init->toExpression();
-	    if (ei && ei->type)
-		e1 = ei;
-	}
-    }
-    return e1;
-}
-
-
-Expression *Expression::optimize(int result)
-{
-    //printf("Expression::optimize(result = x%x) %s\n", result, toChars());
-    return this;
-}
-
-Expression *VarExp::optimize(int result)
-{
-    if (result & WANTinterpret)
-    {
-	return fromConstInitializer(this);
-    }
-    return this;
-}
-
-Expression *TupleExp::optimize(int result)
-{
-    for (size_t i = 0; i < exps->dim; i++)
-    {   Expression *e = (Expression *)exps->data[i];
-
-	e = e->optimize(WANTvalue | (result & WANTinterpret));
-	exps->data[i] = (void *)e;
-    }
-    return this;
-}
-
-Expression *ArrayLiteralExp::optimize(int result)
-{
-    if (elements)
-    {
-	for (size_t i = 0; i < elements->dim; i++)
-	{   Expression *e = (Expression *)elements->data[i];
-
-	    e = e->optimize(WANTvalue | (result & WANTinterpret));
-	    elements->data[i] = (void *)e;
-	}
-    }
-    return this;
-}
-
-Expression *AssocArrayLiteralExp::optimize(int result)
-{
-    assert(keys->dim == values->dim);
-    for (size_t i = 0; i < keys->dim; i++)
-    {   Expression *e = (Expression *)keys->data[i];
-
-	e = e->optimize(WANTvalue | (result & WANTinterpret));
-	keys->data[i] = (void *)e;
-
-	e = (Expression *)values->data[i];
-	e = e->optimize(WANTvalue | (result & WANTinterpret));
-	values->data[i] = (void *)e;
-    }
-    return this;
-}
-
-Expression *StructLiteralExp::optimize(int result)
-{
-    if (elements)
-    {
-	for (size_t i = 0; i < elements->dim; i++)
-	{   Expression *e = (Expression *)elements->data[i];
-	    if (!e)
-		continue;
-	    e = e->optimize(WANTvalue | (result & WANTinterpret));
-	    elements->data[i] = (void *)e;
-	}
-    }
-    return this;
-}
-
-Expression *TypeExp::optimize(int result)
-{
-    return this;
-}
-
-Expression *UnaExp::optimize(int result)
-{
-    e1 = e1->optimize(result);
-    return this;
-}
-
-Expression *NegExp::optimize(int result)
-{   Expression *e;
-
-    e1 = e1->optimize(result);
-    if (e1->isConst() == 1)
-    {
-	e = Neg(type, e1);
-    }
-    else
-	e = this;
-    return e;
-}
-
-Expression *ComExp::optimize(int result)
-{   Expression *e;
-
-    e1 = e1->optimize(result);
-    if (e1->isConst() == 1)
-    {
-	e = Com(type, e1);
-    }
-    else
-	e = this;
-    return e;
-}
-
-Expression *NotExp::optimize(int result)
-{   Expression *e;
-
-    e1 = e1->optimize(result);
-    if (e1->isConst() == 1)
-    {
-	e = Not(type, e1);
-    }
-    else
-	e = this;
-    return e;
-}
-
-Expression *BoolExp::optimize(int result)
-{   Expression *e;
-
-    e1 = e1->optimize(result);
-    if (e1->isConst() == 1)
-    {
-	e = Bool(type, e1);
-    }
-    else
-	e = this;
-    return e;
-}
-
-Expression *AddrExp::optimize(int result)
-{   Expression *e;
-
-    //printf("AddrExp::optimize(result = %d) %s\n", result, toChars());
-    // never try to interpret: it could change the semantics by turning
-    // const p = &s; into an something like const p = &(Struct());
-    e1 = e1->optimize(result & ~WANTinterpret);
-    // Convert &*ex to ex
-    if (e1->op == TOKstar)
-    {	Expression *ex;
-
-	ex = ((PtrExp *)e1)->e1;
-	if (type->equals(ex->type))
-	    e = ex;
-	else
-	{
-	    e = ex->copy();
-	    e->type = type;
-	}
-	return e;
-    }
-#if !IN_LLVM
-    if (e1->op == TOKvar)
-    {	VarExp *ve = (VarExp *)e1;
-	if (!ve->var->isOut() && !ve->var->isRef() &&
-	    !ve->var->isImportedSymbol())
-	{
-	    e = new SymOffExp(loc, ve->var, 0);
-	    e->type = type;
-	    return e;
-	}
-    }
-    if (e1->op == TOKindex)
-    {	// Convert &array[n] to &array+n
-	IndexExp *ae = (IndexExp *)e1;
-
-	if (ae->e2->op == TOKint64 && ae->e1->op == TOKvar)
-	{
-	    dinteger_t index = ae->e2->toInteger();
-	    VarExp *ve = (VarExp *)ae->e1;
-	    if (ve->type->ty == Tsarray && ve->type->next->ty != Tbit
-		&& !ve->var->isImportedSymbol())
-	    {
-		TypeSArray *ts = (TypeSArray *)ve->type;
-		dinteger_t dim = ts->dim->toInteger();
-		if (index < 0 || index >= dim)
-		    error("array index %jd is out of bounds [0..%jd]", index, dim);
-		e = new SymOffExp(loc, ve->var, index * ts->next->size());
-		e->type = type;
-		return e;
-	    }
-	}
-    }
-#endif
-    return this;
-}
-
-Expression *PtrExp::optimize(int result)
-{
-    //printf("PtrExp::optimize(result = x%x) %s\n", result, toChars());
-    e1 = e1->optimize(result);
-    // Convert *&ex to ex
-    if (e1->op == TOKaddress)
-    {	Expression *e;
-	Expression *ex;
-
-	ex = ((AddrExp *)e1)->e1;
-	if (type->equals(ex->type))
-	    e = ex;
-	else
-	{
-	    e = ex->copy();
-	    e->type = type;
-	}
-	return e;
-    }
-    // Constant fold *(&structliteral + offset)
-    if (e1->op == TOKadd)
-    {
-	Expression *e;
-	e = Ptr(type, e1);
-	if (e != EXP_CANT_INTERPRET)
-	    return e;
-    }
-
-    return this;
-}
-
-Expression *DotVarExp::optimize(int result)
-{
-    //printf("DotVarExp::optimize(result = x%x) %s\n", result, toChars());
-    e1 = e1->optimize(result);
-
-#if DMDV2
-    if (e1->op == TOKvar)
-    {	VarExp *ve = (VarExp *)e1;
-	VarDeclaration *v = ve->var->isVarDeclaration();
-	Expression *e = expandVar(result, v);
-	if (e && e->op == TOKstructliteral)
-	{   StructLiteralExp *sle = (StructLiteralExp *)e;
-	    VarDeclaration *vf = var->isVarDeclaration();
-	    if (vf)
-	    {
-		e = sle->getField(type, vf->offset);
-		if (e && e != EXP_CANT_INTERPRET)
-		    return e;
-	    }
-	}
-    }
-    else
-#endif
-    if (e1->op == TOKstructliteral)
-    {   StructLiteralExp *sle = (StructLiteralExp *)e1;
-	VarDeclaration *vf = var->isVarDeclaration();
-	if (vf)
-	{
-	    Expression *e = sle->getField(type, vf->offset);
-	    if (e && e != EXP_CANT_INTERPRET)
-		return e;
-	}
-    }
-
-    return this;
-}
-
-Expression *CallExp::optimize(int result)
-{   Expression *e = this;
-
-    e1 = e1->optimize(result);
-    if (e1->op == TOKvar && result & WANTinterpret)
-    {
-	FuncDeclaration *fd = ((VarExp *)e1)->var->isFuncDeclaration();
-	if (fd)
-	{
-	    Expression *eresult = fd->interpret(NULL, arguments);
-	    if (eresult && eresult != EXP_VOID_INTERPRET)
-		e = eresult;
-	    else if (result & WANTinterpret)
-		error("cannot evaluate %s at compile time", toChars());
-	}
-    }
-    return e;
-}
-
-
-Expression *CastExp::optimize(int result)
-{
-    //printf("CastExp::optimize(result = %d) %s\n", result, toChars());
-    //printf("from %s to %s\n", type->toChars(), to->toChars());
-    //printf("from %s\n", type->toChars());
-    //printf("e1->type %s\n", e1->type->toChars());
-    //printf("type = %p\n", type);
-    assert(type);
-    enum TOK op1 = e1->op;
-
-    e1 = e1->optimize(result);
-    if (result & WANTinterpret)
-	e1 = fromConstInitializer(e1);
-
-    if ((e1->op == TOKstring || e1->op == TOKarrayliteral) &&
-	(type->ty == Tpointer || type->ty == Tarray) &&
-	type->next->equals(e1->type->next)
-       )
-    {
-	// make a copy before adjusting type to avoid
-	// messing up the type of an existing initializer
-	e1 = e1->syntaxCopy();
-	e1->type = type;
-	return e1;
-    }
-    /* The first test here is to prevent infinite loops
-     */
-    if (op1 != TOKarrayliteral && e1->op == TOKarrayliteral)
-	return e1->castTo(NULL, to);
-    if (e1->op == TOKnull &&
-	(type->ty == Tpointer || type->ty == Tclass))
-    {
-	e1->type = type;
-	return e1;
-    }
-
-    if (result & WANTflags && type->ty == Tclass && e1->type->ty == Tclass)
-    {
-	// See if we can remove an unnecessary cast
-	ClassDeclaration *cdfrom;
-	ClassDeclaration *cdto;
-	int offset;
-
-	cdfrom = e1->type->isClassHandle();
-	cdto   = type->isClassHandle();
-	if (cdto->isBaseOf(cdfrom, &offset) && offset == 0)
-	{
-	    e1->type = type;
-	    return e1;
-	}
-    }
-
-    Expression *e;
-
-    if (e1->isConst())
-    {
-	if (e1->op == TOKsymoff)
-	{
-	    if (type->size() == e1->type->size() &&
-		type->toBasetype()->ty != Tsarray)
-	    {
-		e1->type = type;
-		return e1;
-	    }
-	    return this;
-	}
-	if (to->toBasetype()->ty == Tvoid)
-	    e = this;
-	else
-	    e = Cast(type, to, e1);
-    }
-    else
-	e = this;
-    return e;
-}
-
-Expression *BinExp::optimize(int result)
-{
-    //printf("BinExp::optimize(result = %d) %s\n", result, toChars());
-    e1 = e1->optimize(result);
-    e2 = e2->optimize(result);
-    if (op == TOKshlass || op == TOKshrass || op == TOKushrass)
-    {
-	if (e2->isConst() == 1)
-	{
-	    dinteger_t i2 = e2->toInteger();
-	    d_uns64 sz = e1->type->size() * 8;
-	    if (i2 < 0 || i2 > sz)
-	    {   error("shift assign by %jd is outside the range 0..%zu", i2, sz);
-		e2 = new IntegerExp(0);
-	    }
-	}
-    }
-    return this;
-}
-
-Expression *AddExp::optimize(int result)
-{   Expression *e;
-
-    //printf("AddExp::optimize(%s)\n", toChars());
-    e1 = e1->optimize(result);
-    e2 = e2->optimize(result);
-    if (e1->isConst() && e2->isConst())
-    {
-	if (e1->op == TOKsymoff && e2->op == TOKsymoff)
-	    return this;
-	e = Add(type, e1, e2);
-    }
-    else
-	e = this;
-    return e;
-}
-
-Expression *MinExp::optimize(int result)
-{   Expression *e;
-
-    e1 = e1->optimize(result);
-    e2 = e2->optimize(result);
-    if (e1->isConst() && e2->isConst())
-    {
-	if (e2->op == TOKsymoff)
-	    return this;
-	e = Min(type, e1, e2);
-    }
-    else
-	e = this;
-    return e;
-}
-
-Expression *MulExp::optimize(int result)
-{   Expression *e;
-
-    //printf("MulExp::optimize(result = %d) %s\n", result, toChars());
-    e1 = e1->optimize(result);
-    e2 = e2->optimize(result);
-    if (e1->isConst() == 1 && e2->isConst() == 1)
-    {
-	e = Mul(type, e1, e2);
-    }
-    else
-	e = this;
-    return e;
-}
-
-Expression *DivExp::optimize(int result)
-{   Expression *e;
-
-    //printf("DivExp::optimize(%s)\n", toChars());
-    e1 = e1->optimize(result);
-    e2 = e2->optimize(result);
-    if (e1->isConst() == 1 && e2->isConst() == 1)
-    {
-	e = Div(type, e1, e2);
-    }
-    else
-	e = this;
-    return e;
-}
-
-Expression *ModExp::optimize(int result)
-{   Expression *e;
-
-    e1 = e1->optimize(result);
-    e2 = e2->optimize(result);
-    if (e1->isConst() == 1 && e2->isConst() == 1)
-    {
-	e = Mod(type, e1, e2);
-    }
-    else
-	e = this;
-    return e;
-}
-
-Expression *shift_optimize(int result, BinExp *e, Expression *(*shift)(Type *, Expression *, Expression *))
-{   Expression *ex = e;
-
-    e->e1 = e->e1->optimize(result);
-    e->e2 = e->e2->optimize(result);
-    if (e->e2->isConst() == 1)
-    {
-	dinteger_t i2 = e->e2->toInteger();
-	d_uns64 sz = e->e1->type->size() * 8;
-	if (i2 < 0 || i2 > sz)
-	{   e->error("shift by %jd is outside the range 0..%zu", i2, sz);
-	    e->e2 = new IntegerExp(0);
-	}
-	if (e->e1->isConst() == 1)
-	    ex = (*shift)(e->type, e->e1, e->e2);
-    }
-    return ex;
-}
-
-Expression *ShlExp::optimize(int result)
-{
-    //printf("ShlExp::optimize(result = %d) %s\n", result, toChars());
-    return shift_optimize(result, this, Shl);
-}
-
-Expression *ShrExp::optimize(int result)
-{
-    //printf("ShrExp::optimize(result = %d) %s\n", result, toChars());
-    return shift_optimize(result, this, Shr);
-}
-
-Expression *UshrExp::optimize(int result)
-{
-    //printf("UshrExp::optimize(result = %d) %s\n", result, toChars());
-    return shift_optimize(result, this, Ushr);
-}
-
-Expression *AndExp::optimize(int result)
-{   Expression *e;
-
-    e1 = e1->optimize(result);
-    e2 = e2->optimize(result);
-    if (e1->isConst() == 1 && e2->isConst() == 1)
-	e = And(type, e1, e2);
-    else
-	e = this;
-    return e;
-}
-
-Expression *OrExp::optimize(int result)
-{   Expression *e;
-
-    e1 = e1->optimize(result);
-    e2 = e2->optimize(result);
-    if (e1->isConst() == 1 && e2->isConst() == 1)
-	e = Or(type, e1, e2);
-    else
-	e = this;
-    return e;
-}
-
-Expression *XorExp::optimize(int result)
-{   Expression *e;
-
-    e1 = e1->optimize(result);
-    e2 = e2->optimize(result);
-    if (e1->isConst() == 1 && e2->isConst() == 1)
-	e = Xor(type, e1, e2);
-    else
-	e = this;
-    return e;
-}
-
-Expression *CommaExp::optimize(int result)
-{   Expression *e;
-
-    //printf("CommaExp::optimize(result = %d) %s\n", result, toChars());
-    e1 = e1->optimize(result & WANTinterpret);
-    e2 = e2->optimize(result);
-    if (!e1 || e1->op == TOKint64 || e1->op == TOKfloat64 || !e1->checkSideEffect(2))
-    {
-	e = e2;
-	if (e)
-	    e->type = type;
-    }
-    else
-	e = this;
-    //printf("-CommaExp::optimize(result = %d) %s\n", result, e->toChars());
-    return e;
-}
-
-Expression *ArrayLengthExp::optimize(int result)
-{   Expression *e;
-
-    //printf("ArrayLengthExp::optimize(result = %d) %s\n", result, toChars());
-    e1 = e1->optimize(WANTvalue | (result & WANTinterpret));
-    e = this;
-    if (e1->op == TOKstring || e1->op == TOKarrayliteral || e1->op == TOKassocarrayliteral)
-    {
-	e = ArrayLength(type, e1);
-    }
-    return e;
-}
-
-Expression *EqualExp::optimize(int result)
-{   Expression *e;
-
-    //printf("EqualExp::optimize(result = %x) %s\n", result, toChars());
-    e1 = e1->optimize(WANTvalue | (result & WANTinterpret));
-    e2 = e2->optimize(WANTvalue | (result & WANTinterpret));
-    e = this;
-
-    Expression *e1 = fromConstInitializer(this->e1);
-    Expression *e2 = fromConstInitializer(this->e2);
-
-    e = Equal(op, type, e1, e2);
-    if (e == EXP_CANT_INTERPRET)
-	e = this;
-    return e;
-}
-
-Expression *IdentityExp::optimize(int result)
-{   Expression *e;
-
-    //printf("IdentityExp::optimize(result = %d) %s\n", result, toChars());
-    e1 = e1->optimize(WANTvalue | (result & WANTinterpret));
-    e2 = e2->optimize(WANTvalue | (result & WANTinterpret));
-    e = this;
-
-    if (this->e1->isConst() && this->e2->isConst())
-    {
-	e = Identity(op, type, this->e1, this->e2);
-    }
-    return e;
-}
-
-Expression *IndexExp::optimize(int result)
-{   Expression *e;
-
-    //printf("IndexExp::optimize(result = %d) %s\n", result, toChars());
-    Expression *e1 = this->e1->optimize(WANTvalue | (result & WANTinterpret));
-    if (result & WANTinterpret)
-	e1 = fromConstInitializer(e1);
-    e2 = e2->optimize(WANTvalue | (result & WANTinterpret));
-    e = Index(type, e1, e2);
-    if (e == EXP_CANT_INTERPRET)
-	e = this;
-    return e;
-}
-
-Expression *SliceExp::optimize(int result)
-{   Expression *e;
-
-    //printf("SliceExp::optimize(result = %d) %s\n", result, toChars());
-    e = this;
-    e1 = e1->optimize(WANTvalue | (result & WANTinterpret));
-    if (!lwr)
-    {	if (e1->op == TOKstring)
-	{   // Convert slice of string literal into dynamic array
-	    Type *t = e1->type->toBasetype();
-	    if (t->next)
-		e = e1->castTo(NULL, t->next->arrayOf());
-	}
-	return e;
-    }
-    if (result & WANTinterpret)
-	e1 = fromConstInitializer(e1);
-    lwr = lwr->optimize(WANTvalue | (result & WANTinterpret));
-    upr = upr->optimize(WANTvalue | (result & WANTinterpret));
-    e = Slice(type, e1, lwr, upr);
-    if (e == EXP_CANT_INTERPRET)
-	e = this;
-    return e;
-}
-
-Expression *AndAndExp::optimize(int result)
-{   Expression *e;
-
-    //printf("AndAndExp::optimize(%d) %s\n", result, toChars());
-    e1 = e1->optimize(WANTflags | (result & WANTinterpret));
-    e = this;
-    if (e1->isBool(FALSE))
-    {
-	e = new CommaExp(loc, e1, new IntegerExp(loc, 0, type));
-	e->type = type;
-	e = e->optimize(result);
-    }
-    else
-    {
-	e2 = e2->optimize(WANTflags | (result & WANTinterpret));
-	if (result && e2->type->toBasetype()->ty == Tvoid && !global.errors)
-	    error("void has no value");
-	if (e1->isConst())
-	{
-	    if (e2->isConst())
-	    {	int n1 = e1->isBool(1);
-		int n2 = e2->isBool(1);
-
-		e = new IntegerExp(loc, n1 && n2, type);
-	    }
-	    else if (e1->isBool(TRUE))
-		e = new BoolExp(loc, e2, type);
-	}
-    }
-    return e;
-}
-
-Expression *OrOrExp::optimize(int result)
-{   Expression *e;
-
-    e1 = e1->optimize(WANTflags | (result & WANTinterpret));
-    e = this;
-    if (e1->isBool(TRUE))
-    {	// Replace with (e1, 1)
-	e = new CommaExp(loc, e1, new IntegerExp(loc, 1, type));
-	e->type = type;
-	e = e->optimize(result);
-    }
-    else
-    {
-	e2 = e2->optimize(WANTflags | (result & WANTinterpret));
-	if (result && e2->type->toBasetype()->ty == Tvoid && !global.errors)
-	    error("void has no value");
-	if (e1->isConst())
-	{
-	    if (e2->isConst())
-	    {	int n1 = e1->isBool(1);
-		int n2 = e2->isBool(1);
-
-		e = new IntegerExp(loc, n1 || n2, type);
-	    }
-	    else if (e1->isBool(FALSE))
-		e = new BoolExp(loc, e2, type);
-	}
-    }
-    return e;
-}
-
-Expression *CmpExp::optimize(int result)
-{   Expression *e;
-
-    //printf("CmpExp::optimize() %s\n", toChars());
-    e1 = e1->optimize(result);
-    e2 = e2->optimize(result);
-    if (e1->isConst() == 1 && e2->isConst() == 1)
-    {
-	e = Cmp(op, type, this->e1, this->e2);
-    }
-    else
-	e = this;
-    return e;
-}
-
-Expression *CatExp::optimize(int result)
-{   Expression *e;
-
-    //printf("CatExp::optimize(%d) %s\n", result, toChars());
-    e1 = e1->optimize(result);
-    e2 = e2->optimize(result);
-    e = Cat(type, e1, e2);
-    if (e == EXP_CANT_INTERPRET)
-	e = this;
-    return e;
-}
-
-
-Expression *CondExp::optimize(int result)
-{   Expression *e;
-
-    econd = econd->optimize(WANTflags | (result & WANTinterpret));
-    if (econd->isBool(TRUE))
-	e = e1->optimize(result);
-    else if (econd->isBool(FALSE))
-	e = e2->optimize(result);
-    else
-    {	e1 = e1->optimize(result);
-	e2 = e2->optimize(result);
-	e = this;
-    }
-    return e;
-}
-
-
+
+// Compiler implementation of the D programming language
+// Copyright (c) 1999-2009 by Digital Mars
+// All Rights Reserved
+// written by Walter Bright
+// http://www.digitalmars.com
+// License for redistribution is by either the Artistic License
+// in artistic.txt, or the GNU General Public License in gnu.txt.
+// See the included readme.txt for details.
+
+#include <stdio.h>
+#include <ctype.h>
+#include <assert.h>
+#include <math.h>
+
+#if __DMC__
+#include <complex.h>
+#endif
+
+#include "lexer.h"
+#include "mtype.h"
+#include "expression.h"
+#include "declaration.h"
+#include "aggregate.h"
+#include "init.h"
+
+
+#ifdef IN_GCC
+#include "d-gcc-real.h"
+
+/* %% fix? */
+extern "C" bool real_isnan (const real_t *);
+#endif
+
+static real_t zero;	// work around DMC bug for now
+
+
+/*************************************
+ * If expression is a variable with a const initializer,
+ * return that initializer.
+ */
+
+Expression *fromConstInitializer(Expression *e1)
+{
+    //printf("fromConstInitializer(%s)\n", e1->toChars());
+    if (e1->op == TOKvar)
+    {	VarExp *ve = (VarExp *)e1;
+	VarDeclaration *v = ve->var->isVarDeclaration();
+	if (v && v->isConst() && v->init)
+	{   Expression *ei = v->init->toExpression();
+	    if (ei && ei->type)
+		e1 = ei;
+	}
+    }
+    return e1;
+}
+
+
+Expression *Expression::optimize(int result)
+{
+    //printf("Expression::optimize(result = x%x) %s\n", result, toChars());
+    return this;
+}
+
+Expression *VarExp::optimize(int result)
+{
+    if (result & WANTinterpret)
+    {
+	return fromConstInitializer(this);
+    }
+    return this;
+}
+
+Expression *TupleExp::optimize(int result)
+{
+    for (size_t i = 0; i < exps->dim; i++)
+    {   Expression *e = (Expression *)exps->data[i];
+
+	e = e->optimize(WANTvalue | (result & WANTinterpret));
+	exps->data[i] = (void *)e;
+    }
+    return this;
+}
+
+Expression *ArrayLiteralExp::optimize(int result)
+{
+    if (elements)
+    {
+	for (size_t i = 0; i < elements->dim; i++)
+	{   Expression *e = (Expression *)elements->data[i];
+
+	    e = e->optimize(WANTvalue | (result & WANTinterpret));
+	    elements->data[i] = (void *)e;
+	}
+    }
+    return this;
+}
+
+Expression *AssocArrayLiteralExp::optimize(int result)
+{
+    assert(keys->dim == values->dim);
+    for (size_t i = 0; i < keys->dim; i++)
+    {   Expression *e = (Expression *)keys->data[i];
+
+	e = e->optimize(WANTvalue | (result & WANTinterpret));
+	keys->data[i] = (void *)e;
+
+	e = (Expression *)values->data[i];
+	e = e->optimize(WANTvalue | (result & WANTinterpret));
+	values->data[i] = (void *)e;
+    }
+    return this;
+}
+
+Expression *StructLiteralExp::optimize(int result)
+{
+    if (elements)
+    {
+	for (size_t i = 0; i < elements->dim; i++)
+	{   Expression *e = (Expression *)elements->data[i];
+	    if (!e)
+		continue;
+	    e = e->optimize(WANTvalue | (result & WANTinterpret));
+	    elements->data[i] = (void *)e;
+	}
+    }
+    return this;
+}
+
+Expression *TypeExp::optimize(int result)
+{
+    return this;
+}
+
+Expression *UnaExp::optimize(int result)
+{
+    e1 = e1->optimize(result);
+    return this;
+}
+
+Expression *NegExp::optimize(int result)
+{   Expression *e;
+
+    e1 = e1->optimize(result);
+    if (e1->isConst() == 1)
+    {
+	e = Neg(type, e1);
+    }
+    else
+	e = this;
+    return e;
+}
+
+Expression *ComExp::optimize(int result)
+{   Expression *e;
+
+    e1 = e1->optimize(result);
+    if (e1->isConst() == 1)
+    {
+	e = Com(type, e1);
+    }
+    else
+	e = this;
+    return e;
+}
+
+Expression *NotExp::optimize(int result)
+{   Expression *e;
+
+    e1 = e1->optimize(result);
+    if (e1->isConst() == 1)
+    {
+	e = Not(type, e1);
+    }
+    else
+	e = this;
+    return e;
+}
+
+Expression *BoolExp::optimize(int result)
+{   Expression *e;
+
+    e1 = e1->optimize(result);
+    if (e1->isConst() == 1)
+    {
+	e = Bool(type, e1);
+    }
+    else
+	e = this;
+    return e;
+}
+
+Expression *AddrExp::optimize(int result)
+{   Expression *e;
+
+    //printf("AddrExp::optimize(result = %d) %s\n", result, toChars());
+    // never try to interpret: it could change the semantics by turning
+    // const p = &s; into an something like const p = &(Struct());
+    e1 = e1->optimize(result & ~WANTinterpret);
+    // Convert &*ex to ex
+    if (e1->op == TOKstar)
+    {	Expression *ex;
+
+	ex = ((PtrExp *)e1)->e1;
+	if (type->equals(ex->type))
+	    e = ex;
+	else
+	{
+	    e = ex->copy();
+	    e->type = type;
+	}
+	return e;
+    }
+#if !IN_LLVM
+    if (e1->op == TOKvar)
+    {	VarExp *ve = (VarExp *)e1;
+	if (!ve->var->isOut() && !ve->var->isRef() &&
+	    !ve->var->isImportedSymbol())
+	{
+	    e = new SymOffExp(loc, ve->var, 0);
+	    e->type = type;
+	    return e;
+	}
+    }
+    if (e1->op == TOKindex)
+    {	// Convert &array[n] to &array+n
+	IndexExp *ae = (IndexExp *)e1;
+
+	if (ae->e2->op == TOKint64 && ae->e1->op == TOKvar)
+	{
+	    dinteger_t index = ae->e2->toInteger();
+	    VarExp *ve = (VarExp *)ae->e1;
+	    if (ve->type->ty == Tsarray && ve->type->next->ty != Tbit
+		&& !ve->var->isImportedSymbol())
+	    {
+		TypeSArray *ts = (TypeSArray *)ve->type;
+		dinteger_t dim = ts->dim->toInteger();
+		if (index < 0 || index >= dim)
+		    error("array index %jd is out of bounds [0..%jd]", index, dim);
+		e = new SymOffExp(loc, ve->var, index * ts->next->size());
+		e->type = type;
+		return e;
+	    }
+	}
+    }
+#endif
+    return this;
+}
+
+Expression *PtrExp::optimize(int result)
+{
+    //printf("PtrExp::optimize(result = x%x) %s\n", result, toChars());
+    e1 = e1->optimize(result);
+    // Convert *&ex to ex
+    if (e1->op == TOKaddress)
+    {	Expression *e;
+	Expression *ex;
+
+	ex = ((AddrExp *)e1)->e1;
+	if (type->equals(ex->type))
+	    e = ex;
+	else
+	{
+	    e = ex->copy();
+	    e->type = type;
+	}
+	return e;
+    }
+    // Constant fold *(&structliteral + offset)
+    if (e1->op == TOKadd)
+    {
+	Expression *e;
+	e = Ptr(type, e1);
+	if (e != EXP_CANT_INTERPRET)
+	    return e;
+    }
+
+    return this;
+}
+
+Expression *DotVarExp::optimize(int result)
+{
+    //printf("DotVarExp::optimize(result = x%x) %s\n", result, toChars());
+    e1 = e1->optimize(result);
+
+#if DMDV2
+    if (e1->op == TOKvar)
+    {	VarExp *ve = (VarExp *)e1;
+	VarDeclaration *v = ve->var->isVarDeclaration();
+	Expression *e = expandVar(result, v);
+	if (e && e->op == TOKstructliteral)
+	{   StructLiteralExp *sle = (StructLiteralExp *)e;
+	    VarDeclaration *vf = var->isVarDeclaration();
+	    if (vf)
+	    {
+		e = sle->getField(type, vf->offset);
+		if (e && e != EXP_CANT_INTERPRET)
+		    return e;
+	    }
+	}
+    }
+    else
+#endif
+    if (e1->op == TOKstructliteral)
+    {   StructLiteralExp *sle = (StructLiteralExp *)e1;
+	VarDeclaration *vf = var->isVarDeclaration();
+	if (vf)
+	{
+	    Expression *e = sle->getField(type, vf->offset);
+	    if (e && e != EXP_CANT_INTERPRET)
+		return e;
+	}
+    }
+
+    return this;
+}
+
+Expression *NewExp::optimize(int result)
+{
+    if (thisexp)
+	thisexp = thisexp->optimize(WANTvalue);
+
+    // Optimize parameters
+    if (newargs)
+    {
+	for (size_t i = 0; i < newargs->dim; i++)
+	{   Expression *e = (Expression *)newargs->data[i];
+
+	    e = e->optimize(WANTvalue);
+	    newargs->data[i] = (void *)e;
+	}
+    }
+
+    if (arguments)
+    {
+	for (size_t i = 0; i < arguments->dim; i++)
+	{   Expression *e = (Expression *)arguments->data[i];
+
+	    e = e->optimize(WANTvalue);
+	    arguments->data[i] = (void *)e;
+	}
+    }
+    return this;
+}
+
+Expression *CallExp::optimize(int result)
+{   Expression *e = this;
+
+    // Optimize parameters
+    if (arguments)
+    {
+	for (size_t i = 0; i < arguments->dim; i++)
+	{   Expression *e = (Expression *)arguments->data[i];
+
+	    e = e->optimize(WANTvalue);
+	    arguments->data[i] = (void *)e;
+	}
+    }
+
+    e1 = e1->optimize(result);
+    if (e1->op == TOKvar && result & WANTinterpret)
+    {
+	FuncDeclaration *fd = ((VarExp *)e1)->var->isFuncDeclaration();
+	if (fd)
+	{
+	    Expression *eresult = fd->interpret(NULL, arguments);
+	    if (eresult && eresult != EXP_VOID_INTERPRET)
+		e = eresult;
+	    else if (result & WANTinterpret)
+		error("cannot evaluate %s at compile time", toChars());
+	}
+    }
+    return e;
+}
+
+
+Expression *CastExp::optimize(int result)
+{
+    //printf("CastExp::optimize(result = %d) %s\n", result, toChars());
+    //printf("from %s to %s\n", type->toChars(), to->toChars());
+    //printf("from %s\n", type->toChars());
+    //printf("e1->type %s\n", e1->type->toChars());
+    //printf("type = %p\n", type);
+    assert(type);
+    enum TOK op1 = e1->op;
+
+    e1 = e1->optimize(result);
+    if (result & WANTinterpret)
+	e1 = fromConstInitializer(e1);
+
+    if ((e1->op == TOKstring || e1->op == TOKarrayliteral) &&
+	(type->ty == Tpointer || type->ty == Tarray) &&
+	type->next->equals(e1->type->next)
+       )
+    {
+	// make a copy before adjusting type to avoid
+	// messing up the type of an existing initializer
+	e1 = e1->syntaxCopy();
+	e1->type = type;
+	return e1;
+    }
+    /* The first test here is to prevent infinite loops
+     */
+    if (op1 != TOKarrayliteral && e1->op == TOKarrayliteral)
+	return e1->castTo(NULL, to);
+    if (e1->op == TOKnull &&
+	(type->ty == Tpointer || type->ty == Tclass))
+    {
+	e1->type = type;
+	return e1;
+    }
+
+    if (result & WANTflags && type->ty == Tclass && e1->type->ty == Tclass)
+    {
+	// See if we can remove an unnecessary cast
+	ClassDeclaration *cdfrom;
+	ClassDeclaration *cdto;
+	int offset;
+
+	cdfrom = e1->type->isClassHandle();
+	cdto   = type->isClassHandle();
+	if (cdto->isBaseOf(cdfrom, &offset) && offset == 0)
+	{
+	    e1->type = type;
+	    return e1;
+	}
+    }
+
+    Expression *e;
+
+    if (e1->isConst())
+    {
+	if (e1->op == TOKsymoff)
+	{
+	    if (type->size() == e1->type->size() &&
+		type->toBasetype()->ty != Tsarray)
+	    {
+		e1->type = type;
+		return e1;
+	    }
+	    return this;
+	}
+	if (to->toBasetype()->ty == Tvoid)
+	    e = this;
+	else
+	    e = Cast(type, to, e1);
+    }
+    else
+	e = this;
+    return e;
+}
+
+Expression *BinExp::optimize(int result)
+{
+    //printf("BinExp::optimize(result = %d) %s\n", result, toChars());
+    e1 = e1->optimize(result);
+    e2 = e2->optimize(result);
+    if (op == TOKshlass || op == TOKshrass || op == TOKushrass)
+    {
+	if (e2->isConst() == 1)
+	{
+	    dinteger_t i2 = e2->toInteger();
+	    d_uns64 sz = e1->type->size() * 8;
+	    if (i2 < 0 || i2 > sz)
+	    {   error("shift assign by %jd is outside the range 0..%zu", i2, sz);
+		e2 = new IntegerExp(0);
+	    }
+	}
+    }
+    return this;
+}
+
+Expression *AddExp::optimize(int result)
+{   Expression *e;
+
+    //printf("AddExp::optimize(%s)\n", toChars());
+    e1 = e1->optimize(result);
+    e2 = e2->optimize(result);
+    if (e1->isConst() && e2->isConst())
+    {
+	if (e1->op == TOKsymoff && e2->op == TOKsymoff)
+	    return this;
+	e = Add(type, e1, e2);
+    }
+    else
+	e = this;
+    return e;
+}
+
+Expression *MinExp::optimize(int result)
+{   Expression *e;
+
+    e1 = e1->optimize(result);
+    e2 = e2->optimize(result);
+    if (e1->isConst() && e2->isConst())
+    {
+	if (e2->op == TOKsymoff)
+	    return this;
+	e = Min(type, e1, e2);
+    }
+    else
+	e = this;
+    return e;
+}
+
+Expression *MulExp::optimize(int result)
+{   Expression *e;
+
+    //printf("MulExp::optimize(result = %d) %s\n", result, toChars());
+    e1 = e1->optimize(result);
+    e2 = e2->optimize(result);
+    if (e1->isConst() == 1 && e2->isConst() == 1)
+    {
+	e = Mul(type, e1, e2);
+    }
+    else
+	e = this;
+    return e;
+}
+
+Expression *DivExp::optimize(int result)
+{   Expression *e;
+
+    //printf("DivExp::optimize(%s)\n", toChars());
+    e1 = e1->optimize(result);
+    e2 = e2->optimize(result);
+    if (e1->isConst() == 1 && e2->isConst() == 1)
+    {
+	e = Div(type, e1, e2);
+    }
+    else
+	e = this;
+    return e;
+}
+
+Expression *ModExp::optimize(int result)
+{   Expression *e;
+
+    e1 = e1->optimize(result);
+    e2 = e2->optimize(result);
+    if (e1->isConst() == 1 && e2->isConst() == 1)
+    {
+	e = Mod(type, e1, e2);
+    }
+    else
+	e = this;
+    return e;
+}
+
+Expression *shift_optimize(int result, BinExp *e, Expression *(*shift)(Type *, Expression *, Expression *))
+{   Expression *ex = e;
+
+    e->e1 = e->e1->optimize(result);
+    e->e2 = e->e2->optimize(result);
+    if (e->e2->isConst() == 1)
+    {
+	dinteger_t i2 = e->e2->toInteger();
+	d_uns64 sz = e->e1->type->size() * 8;
+	if (i2 < 0 || i2 > sz)
+	{   e->error("shift by %jd is outside the range 0..%zu", i2, sz);
+	    e->e2 = new IntegerExp(0);
+	}
+	if (e->e1->isConst() == 1)
+	    ex = (*shift)(e->type, e->e1, e->e2);
+    }
+    return ex;
+}
+
+Expression *ShlExp::optimize(int result)
+{
+    //printf("ShlExp::optimize(result = %d) %s\n", result, toChars());
+    return shift_optimize(result, this, Shl);
+}
+
+Expression *ShrExp::optimize(int result)
+{
+    //printf("ShrExp::optimize(result = %d) %s\n", result, toChars());
+    return shift_optimize(result, this, Shr);
+}
+
+Expression *UshrExp::optimize(int result)
+{
+    //printf("UshrExp::optimize(result = %d) %s\n", result, toChars());
+    return shift_optimize(result, this, Ushr);
+}
+
+Expression *AndExp::optimize(int result)
+{   Expression *e;
+
+    e1 = e1->optimize(result);
+    e2 = e2->optimize(result);
+    if (e1->isConst() == 1 && e2->isConst() == 1)
+	e = And(type, e1, e2);
+    else
+	e = this;
+    return e;
+}
+
+Expression *OrExp::optimize(int result)
+{   Expression *e;
+
+    e1 = e1->optimize(result);
+    e2 = e2->optimize(result);
+    if (e1->isConst() == 1 && e2->isConst() == 1)
+	e = Or(type, e1, e2);
+    else
+	e = this;
+    return e;
+}
+
+Expression *XorExp::optimize(int result)
+{   Expression *e;
+
+    e1 = e1->optimize(result);
+    e2 = e2->optimize(result);
+    if (e1->isConst() == 1 && e2->isConst() == 1)
+	e = Xor(type, e1, e2);
+    else
+	e = this;
+    return e;
+}
+
+Expression *CommaExp::optimize(int result)
+{   Expression *e;
+
+    //printf("CommaExp::optimize(result = %d) %s\n", result, toChars());
+    e1 = e1->optimize(result & WANTinterpret);
+    e2 = e2->optimize(result);
+    if (!e1 || e1->op == TOKint64 || e1->op == TOKfloat64 || !e1->checkSideEffect(2))
+    {
+	e = e2;
+	if (e)
+	    e->type = type;
+    }
+    else
+	e = this;
+    //printf("-CommaExp::optimize(result = %d) %s\n", result, e->toChars());
+    return e;
+}
+
+Expression *ArrayLengthExp::optimize(int result)
+{   Expression *e;
+
+    //printf("ArrayLengthExp::optimize(result = %d) %s\n", result, toChars());
+    e1 = e1->optimize(WANTvalue | (result & WANTinterpret));
+    e = this;
+    if (e1->op == TOKstring || e1->op == TOKarrayliteral || e1->op == TOKassocarrayliteral)
+    {
+	e = ArrayLength(type, e1);
+    }
+    return e;
+}
+
+Expression *EqualExp::optimize(int result)
+{   Expression *e;
+
+    //printf("EqualExp::optimize(result = %x) %s\n", result, toChars());
+    e1 = e1->optimize(WANTvalue | (result & WANTinterpret));
+    e2 = e2->optimize(WANTvalue | (result & WANTinterpret));
+    e = this;
+
+    Expression *e1 = fromConstInitializer(this->e1);
+    Expression *e2 = fromConstInitializer(this->e2);
+
+    e = Equal(op, type, e1, e2);
+    if (e == EXP_CANT_INTERPRET)
+	e = this;
+    return e;
+}
+
+Expression *IdentityExp::optimize(int result)
+{   Expression *e;
+
+    //printf("IdentityExp::optimize(result = %d) %s\n", result, toChars());
+    e1 = e1->optimize(WANTvalue | (result & WANTinterpret));
+    e2 = e2->optimize(WANTvalue | (result & WANTinterpret));
+    e = this;
+
+    if (this->e1->isConst() && this->e2->isConst())
+    {
+	e = Identity(op, type, this->e1, this->e2);
+	if (e == EXP_CANT_INTERPRET)
+	    e = this;
+    }
+    return e;
+}
+
+Expression *IndexExp::optimize(int result)
+{   Expression *e;
+
+    //printf("IndexExp::optimize(result = %d) %s\n", result, toChars());
+    Expression *e1 = this->e1->optimize(WANTvalue | (result & WANTinterpret));
+    if (result & WANTinterpret)
+	e1 = fromConstInitializer(e1);
+    e2 = e2->optimize(WANTvalue | (result & WANTinterpret));
+    e = Index(type, e1, e2);
+    if (e == EXP_CANT_INTERPRET)
+	e = this;
+    return e;
+}
+
+Expression *SliceExp::optimize(int result)
+{   Expression *e;
+
+    //printf("SliceExp::optimize(result = %d) %s\n", result, toChars());
+    e = this;
+    e1 = e1->optimize(WANTvalue | (result & WANTinterpret));
+    if (!lwr)
+    {	if (e1->op == TOKstring)
+	{   // Convert slice of string literal into dynamic array
+	    Type *t = e1->type->toBasetype();
+	    if (t->next)
+		e = e1->castTo(NULL, t->next->arrayOf());
+	}
+	return e;
+    }
+    if (result & WANTinterpret)
+	e1 = fromConstInitializer(e1);
+    lwr = lwr->optimize(WANTvalue | (result & WANTinterpret));
+    upr = upr->optimize(WANTvalue | (result & WANTinterpret));
+    e = Slice(type, e1, lwr, upr);
+    if (e == EXP_CANT_INTERPRET)
+	e = this;
+    return e;
+}
+
+Expression *AndAndExp::optimize(int result)
+{   Expression *e;
+
+    //printf("AndAndExp::optimize(%d) %s\n", result, toChars());
+    e1 = e1->optimize(WANTflags | (result & WANTinterpret));
+    e = this;
+    if (e1->isBool(FALSE))
+    {
+	e = new CommaExp(loc, e1, new IntegerExp(loc, 0, type));
+	e->type = type;
+	e = e->optimize(result);
+    }
+    else
+    {
+	e2 = e2->optimize(WANTflags | (result & WANTinterpret));
+	if (result && e2->type->toBasetype()->ty == Tvoid && !global.errors)
+	    error("void has no value");
+	if (e1->isConst())
+	{
+	    if (e2->isConst())
+	    {	int n1 = e1->isBool(1);
+		int n2 = e2->isBool(1);
+
+		e = new IntegerExp(loc, n1 && n2, type);
+	    }
+	    else if (e1->isBool(TRUE))
+		e = new BoolExp(loc, e2, type);
+	}
+    }
+    return e;
+}
+
+Expression *OrOrExp::optimize(int result)
+{   Expression *e;
+
+    e1 = e1->optimize(WANTflags | (result & WANTinterpret));
+    e = this;
+    if (e1->isBool(TRUE))
+    {	// Replace with (e1, 1)
+	e = new CommaExp(loc, e1, new IntegerExp(loc, 1, type));
+	e->type = type;
+	e = e->optimize(result);
+    }
+    else
+    {
+	e2 = e2->optimize(WANTflags | (result & WANTinterpret));
+	if (result && e2->type->toBasetype()->ty == Tvoid && !global.errors)
+	    error("void has no value");
+	if (e1->isConst())
+	{
+	    if (e2->isConst())
+	    {	int n1 = e1->isBool(1);
+		int n2 = e2->isBool(1);
+
+		e = new IntegerExp(loc, n1 || n2, type);
+	    }
+	    else if (e1->isBool(FALSE))
+		e = new BoolExp(loc, e2, type);
+	}
+    }
+    return e;
+}
+
+Expression *CmpExp::optimize(int result)
+{   Expression *e;
+
+    //printf("CmpExp::optimize() %s\n", toChars());
+    e1 = e1->optimize(result);
+    e2 = e2->optimize(result);
+    if (e1->isConst() == 1 && e2->isConst() == 1)
+    {
+	e = Cmp(op, type, this->e1, this->e2);
+    }
+    else
+	e = this;
+    return e;
+}
+
+Expression *CatExp::optimize(int result)
+{   Expression *e;
+
+    //printf("CatExp::optimize(%d) %s\n", result, toChars());
+    e1 = e1->optimize(result);
+    e2 = e2->optimize(result);
+    e = Cat(type, e1, e2);
+    if (e == EXP_CANT_INTERPRET)
+	e = this;
+    return e;
+}
+
+
+Expression *CondExp::optimize(int result)
+{   Expression *e;
+
+    econd = econd->optimize(WANTflags | (result & WANTinterpret));
+    if (econd->isBool(TRUE))
+	e = e1->optimize(result);
+    else if (econd->isBool(FALSE))
+	e = e2->optimize(result);
+    else
+    {	e1 = e1->optimize(result);
+	e2 = e2->optimize(result);
+	e = this;
+    }
+    return e;
+}
+
+
--- a/dmd/parse.c	Fri Nov 06 21:51:41 2009 +0100
+++ b/dmd/parse.c	Fri Nov 06 23:58:01 2009 +0100
@@ -1,5338 +1,5339 @@
-
-// Compiler implementation of the D programming language
-// Copyright (c) 1999-2009 by Digital Mars
-// All Rights Reserved
-// written by Walter Bright
-// http://www.digitalmars.com
-// License for redistribution is by either the Artistic License
-// in artistic.txt, or the GNU General Public License in gnu.txt.
-// See the included readme.txt for details.
-
-// This is the D parser
-
-#include <stdio.h>
-#include <assert.h>
-
-#include "rmem.h"
-#include "lexer.h"
-#include "parse.h"
-#include "init.h"
-#include "attrib.h"
-#include "cond.h"
-#include "mtype.h"
-#include "template.h"
-#include "staticassert.h"
-#include "expression.h"
-#include "statement.h"
-#include "module.h"
-#include "dsymbol.h"
-#include "import.h"
-#include "declaration.h"
-#include "aggregate.h"
-#include "enum.h"
-#include "id.h"
-#include "version.h"
-#if DMDV2
-#include "aliasthis.h"
-#endif
-
-// How multiple declarations are parsed.
-// If 1, treat as C.
-// If 0, treat:
-//	int *p, i;
-// as:
-//	int* p;
-//	int* i;
-#define CDECLSYNTAX	0
-
-// Support C cast syntax:
-//	(type)(expression)
-#define CCASTSYNTAX	1
-
-// Support postfix C array declarations, such as
-//	int a[3][4];
-#define CARRAYDECL	1
-
-// Support left-to-right array declarations
-#define LTORARRAYDECL	1
-
-
-Parser::Parser(Module *module, unsigned char *base, unsigned length, int doDocComment)
-    : Lexer(module, base, 0, length, doDocComment, 0)
-{
-    //printf("Parser::Parser()\n");
-    md = NULL;
-    linkage = LINKd;
-    endloc = 0;
-    inBrackets = 0;
-    //nextToken();		// start up the scanner
-}
-
-Array *Parser::parseModule()
-{
-    Array *decldefs;
-
-    // ModuleDeclation leads off
-    if (token.value == TOKmodule)
-    {
-	unsigned char *comment = token.blockComment;
-
-	nextToken();
-#if DMDV2
-	if (token.value == TOKlparen)
-	{
-	    nextToken();
-	    if (token.value != TOKidentifier)
-	    {	error("module (system) identifier expected");
-		goto Lerr;
-	    }
-	    Identifier *id = token.ident;
-
-	    if (id == Id::system)
-		safe = TRUE;
-	    else
-		error("(safe) expected, not %s", id->toChars());
-	    nextToken();
-	    check(TOKrparen);
-	}
-#endif
-
-	if (token.value != TOKidentifier)
-	{   error("Identifier expected following module");
-	    goto Lerr;
-	}
-	else
-	{
-	    Array *a = NULL;
-	    Identifier *id;
-
-	    id = token.ident;
-	    while (nextToken() == TOKdot)
-	    {
-		if (!a)
-		    a = new Array();
-		a->push(id);
-		nextToken();
-		if (token.value != TOKidentifier)
-		{   error("Identifier expected following package");
-		    goto Lerr;
-		}
-		id = token.ident;
-	    }
-
-	    md = new ModuleDeclaration(a, id);
-
-	    if (token.value != TOKsemicolon)
-		error("';' expected following module declaration instead of %s", token.toChars());
-	    nextToken();
-	    addComment(mod, comment);
-	}
-    }
-
-    decldefs = parseDeclDefs(0);
-    if (token.value != TOKeof)
-    {	error("unrecognized declaration");
-	goto Lerr;
-    }
-    return decldefs;
-
-Lerr:
-    while (token.value != TOKsemicolon && token.value != TOKeof)
-	nextToken();
-    nextToken();
-    return new Array();
-}
-
-Array *Parser::parseDeclDefs(int once)
-{   Dsymbol *s;
-    Array *decldefs;
-    Array *a;
-    Array *aelse;
-    enum PROT prot;
-    unsigned stc;
-    Condition *condition;
-    unsigned char *comment;
-
-    //printf("Parser::parseDeclDefs()\n");
-    decldefs = new Array();
-    do
-    {
-	comment = token.blockComment;
-	switch (token.value)
-	{
-	    case TOKenum:
-		s = parseEnum();
-		break;
-
-	    case TOKstruct:
-	    case TOKunion:
-	    case TOKclass:
-	    case TOKinterface:
-		s = parseAggregate();
-		break;
-
-	    case TOKimport:
-		s = parseImport(decldefs, 0);
-		break;
-
-	    case TOKtemplate:
-		s = (Dsymbol *)parseTemplateDeclaration();
-		break;
-
-	    case TOKmixin:
-	    {	Loc loc = this->loc;
-		if (peek(&token)->value == TOKlparen)
-		{   // mixin(string)
-		    nextToken();
-		    check(TOKlparen, "mixin");
-		    Expression *e = parseAssignExp();
-		    check(TOKrparen);
-		    check(TOKsemicolon);
-		    s = new CompileDeclaration(loc, e);
-		    break;
-		}
-		s = parseMixin();
-		break;
-	    }
-
-	    CASE_BASIC_TYPES:
-	    case TOKalias:
-	    case TOKtypedef:
-	    case TOKidentifier:
-	    case TOKtypeof:
-	    case TOKdot:
-	    Ldeclaration:
-		a = parseDeclarations();
-		decldefs->append(a);
-		continue;
-
-	    case TOKthis:
-		s = parseCtor();
-		break;
-
-	    case TOKtilde:
-		s = parseDtor();
-		break;
-
-	    case TOKinvariant:
-#if 1
-		s = parseInvariant();
-#else
-		if (peek(&token)->value == TOKlcurly)
-		    s = parseInvariant();
-		else
-		{
-		    stc = STCinvariant;
-		    goto Lstc;
-		}
-#endif
-		break;
-
-	    case TOKunittest:
-		s = parseUnitTest();
-		break;
-
-	    case TOKnew:
-		s = parseNew();
-		break;
-
-	    case TOKdelete:
-		s = parseDelete();
-		break;
-
-	    case TOKeof:
-	    case TOKrcurly:
-		return decldefs;
-
-	    case TOKstatic:
-		nextToken();
-		if (token.value == TOKthis)
-		    s = parseStaticCtor();
-		else if (token.value == TOKtilde)
-		    s = parseStaticDtor();
-		else if (token.value == TOKassert)
-		    s = parseStaticAssert();
-		else if (token.value == TOKif)
-		{   condition = parseStaticIfCondition();
-		    a = parseBlock();
-		    aelse = NULL;
-		    if (token.value == TOKelse)
-		    {   nextToken();
-			aelse = parseBlock();
-		    }
-		    s = new StaticIfDeclaration(condition, a, aelse);
-		    break;
-		}
-		else if (token.value == TOKimport)
-		{
-		    s = parseImport(decldefs, 1);
-		}
-		else
-		{   stc = STCstatic;
-		    goto Lstc2;
-		}
-		break;
-
-	    case TOKconst:	  stc = STCconst;	 goto Lstc;
-	    case TOKfinal:	  stc = STCfinal;	 goto Lstc;
-	    case TOKauto:	  stc = STCauto;	 goto Lstc;
-	    case TOKscope:	  stc = STCscope;	 goto Lstc;
-	    case TOKoverride:	  stc = STCoverride;	 goto Lstc;
-	    case TOKabstract:	  stc = STCabstract;	 goto Lstc;
-	    case TOKsynchronized: stc = STCsynchronized; goto Lstc;
-	    case TOKdeprecated:   stc = STCdeprecated;	 goto Lstc;
-#if DMDV2
-	    case TOKnothrow:      stc = STCnothrow;	 goto Lstc;
-	    case TOKpure:         stc = STCpure;	 goto Lstc;
-	    case TOKref:          stc = STCref;          goto Lstc;
-	    case TOKtls:          stc = STCtls;		 goto Lstc;
-	    //case TOKmanifest:	  stc = STCmanifest;	 goto Lstc;
-#endif
-
-	    Lstc:
-		nextToken();
-	    Lstc2:
-		switch (token.value)
-		{
-		    case TOKconst:	  stc |= STCconst;	 goto Lstc;
-		    case TOKfinal:	  stc |= STCfinal;	 goto Lstc;
-		    case TOKauto:	  stc |= STCauto;	 goto Lstc;
-		    case TOKscope:	  stc |= STCscope;	 goto Lstc;
-		    case TOKoverride:	  stc |= STCoverride;	 goto Lstc;
-		    case TOKabstract:	  stc |= STCabstract;	 goto Lstc;
-		    case TOKsynchronized: stc |= STCsynchronized; goto Lstc;
-		    case TOKdeprecated:   stc |= STCdeprecated;	 goto Lstc;
-		    //case TOKinvariant:    stc |= STCinvariant;   goto Lstc;
-		    default:
-			break;
-		}
-
-		/* Look for auto initializers:
-		 *	storage_class identifier = initializer;
-		 */
-		if (token.value == TOKidentifier &&
-		    peek(&token)->value == TOKassign)
-		{
-		    while (1)
-		    {
-			Identifier *ident = token.ident;
-			nextToken();
-			nextToken();
-			Initializer *init = parseInitializer();
-			VarDeclaration *v = new VarDeclaration(loc, NULL, ident, init);
-			v->storage_class = stc;
-			s = v;
-			if (token.value == TOKsemicolon)
-			{
-			    nextToken();
-			}
-			else if (token.value == TOKcomma)
-			{
-			    nextToken();
-			    if (token.value == TOKidentifier &&
-				peek(&token)->value == TOKassign)
-			    {
-				decldefs->push(s);
-				addComment(s, comment);
-				continue;
-			    }
-			    else
-				error("Identifier expected following comma");
-			}
-			else
-			    error("semicolon expected following auto declaration, not '%s'", token.toChars());
-			break;
-		    }
-		}
-		else
-		{   a = parseBlock();
-		    s = new StorageClassDeclaration(stc, a);
-		}
-		break;
-
-	    case TOKextern:
-		if (peek(&token)->value != TOKlparen)
-		{   stc = STCextern;
-		    goto Lstc;
-		}
-	    {
-		enum LINK linksave = linkage;
-		linkage = parseLinkage();
-		a = parseBlock();
-		s = new LinkDeclaration(linkage, a);
-		linkage = linksave;
-		break;
-	    }
-	    case TOKprivate:	prot = PROTprivate;	goto Lprot;
-	    case TOKpackage:	prot = PROTpackage;	goto Lprot;
-	    case TOKprotected:	prot = PROTprotected;	goto Lprot;
-	    case TOKpublic:	prot = PROTpublic;	goto Lprot;
-	    case TOKexport:	prot = PROTexport;	goto Lprot;
-
-	    Lprot:
-		nextToken();
-		switch (token.value)
-		{
-		    case TOKprivate:
-		    case TOKpackage:
-		    case TOKprotected:
-		    case TOKpublic:
-		    case TOKexport:
-			error("redundant protection attribute");
-			break;
-		}
-		a = parseBlock();
-		s = new ProtDeclaration(prot, a);
-		break;
-
-	    case TOKalign:
-	    {	unsigned n;
-
-        // LDC better align code locations
-        Loc alignloc = loc;
-
-		s = NULL;
-		nextToken();
-		if (token.value == TOKlparen)
-		{
-		    nextToken();
-		    if (token.value == TOKint32v)
-			n = (unsigned)token.uns64value;
-		    else
-		    {	error("integer expected, not %s", token.toChars());
-			n = 1;
-		    }
-		    nextToken();
-		    check(TOKrparen);
-		}
-		else
-		    n = global.structalign;		// default
-
-		a = parseBlock();
-		s = new AlignDeclaration(alignloc, n, a);
-		break;
-	    }
-
-	    case TOKpragma:
-	    {	Identifier *ident;
-		Expressions *args = NULL;
-
-		nextToken();
-		check(TOKlparen);
-		if (token.value != TOKidentifier)
-		{   error("pragma(identifier expected");
-		    goto Lerror;
-		}
-		ident = token.ident;
-		nextToken();
-		if (token.value == TOKcomma && peekNext() != TOKrparen)
-		    args = parseArguments();	// pragma(identifier, args...)
-		else
-		    check(TOKrparen);		// pragma(identifier)
-
-		if (token.value == TOKsemicolon)
-		    a = NULL;
-		else
-		    a = parseBlock();
-		s = new PragmaDeclaration(loc, ident, args, a);
-		break;
-	    }
-
-	    case TOKdebug:
-		nextToken();
-		if (token.value == TOKassign)
-		{
-		    nextToken();
-		    if (token.value == TOKidentifier)
-			s = new DebugSymbol(loc, token.ident);
-		    else if (token.value == TOKint32v)
-			s = new DebugSymbol(loc, (unsigned)token.uns64value);
-		    else
-		    {	error("identifier or integer expected, not %s", token.toChars());
-			s = NULL;
-		    }
-		    nextToken();
-		    if (token.value != TOKsemicolon)
-			error("semicolon expected");
-		    nextToken();
-		    break;
-		}
-
-		condition = parseDebugCondition();
-		goto Lcondition;
-
-	    case TOKversion:
-		nextToken();
-		if (token.value == TOKassign)
-		{
-		    nextToken();
-		    if (token.value == TOKidentifier)
-			s = new VersionSymbol(loc, token.ident);
-		    else if (token.value == TOKint32v)
-			s = new VersionSymbol(loc, (unsigned)token.uns64value);
-		    else
-		    {	error("identifier or integer expected, not %s", token.toChars());
-			s = NULL;
-		    }
-		    nextToken();
-		    if (token.value != TOKsemicolon)
-			error("semicolon expected");
-		    nextToken();
-		    break;
-		}
-		condition = parseVersionCondition();
-		goto Lcondition;
-
-	    Lcondition:
-		a = parseBlock();
-		aelse = NULL;
-		if (token.value == TOKelse)
-		{   nextToken();
-		    aelse = parseBlock();
-		}
-		s = new ConditionalDeclaration(condition, a, aelse);
-		break;
-
-	    case TOKsemicolon:		// empty declaration
-		nextToken();
-		continue;
-
-	    default:
-		error("Declaration expected, not '%s'",token.toChars());
-	    Lerror:
-		while (token.value != TOKsemicolon && token.value != TOKeof)
-		    nextToken();
-		nextToken();
-		s = NULL;
-		continue;
-	}
-	if (s)
-	{   decldefs->push(s);
-	    addComment(s, comment);
-	}
-    } while (!once);
-    return decldefs;
-}
-
-
-/********************************************
- * Parse declarations after an align, protection, or extern decl.
- */
-
-Array *Parser::parseBlock()
-{
-    Array *a = NULL;
-    Dsymbol *s;
-
-    //printf("parseBlock()\n");
-    switch (token.value)
-    {
-	case TOKsemicolon:
-	    error("declaration expected following attribute, not ';'");
-	    nextToken();
-	    break;
-
-	case TOKeof:
-	    error("declaration expected following attribute, not EOF");
-	    break;
-
-	case TOKlcurly:
-	    nextToken();
-	    a = parseDeclDefs(0);
-	    if (token.value != TOKrcurly)
-	    {   /* { */
-		error("matching '}' expected, not %s", token.toChars());
-	    }
-	    else
-		nextToken();
-	    break;
-
-	case TOKcolon:
-	    nextToken();
-#if 0
-	    a = NULL;
-#else
-	    a = parseDeclDefs(0);	// grab declarations up to closing curly bracket
-#endif
-	    break;
-
-	default:
-	    a = parseDeclDefs(1);
-	    break;
-    }
-    return a;
-}
-
-/**********************************
- * Parse a static assertion.
- */
-
-StaticAssert *Parser::parseStaticAssert()
-{
-    Loc loc = this->loc;
-    Expression *exp;
-    Expression *msg = NULL;
-
-    //printf("parseStaticAssert()\n");
-    nextToken();
-    check(TOKlparen);
-    exp = parseAssignExp();
-    if (token.value == TOKcomma)
-    {	nextToken();
-	msg = parseAssignExp();
-    }
-    check(TOKrparen);
-    check(TOKsemicolon);
-    return new StaticAssert(loc, exp, msg);
-}
-
-/***********************************
- * Parse typeof(expression).
- * Current token is on the 'typeof'.
- */
-
-#if DMDV2
-TypeQualified *Parser::parseTypeof()
-{   TypeQualified *t;
-    Loc loc = this->loc;
-
-    nextToken();
-    check(TOKlparen);
-    if (token.value == TOKreturn)	// typeof(return)
-    {
-	nextToken();
-	t = new TypeReturn(loc);
-    }
-    else
-    {	Expression *exp = parseExpression();	// typeof(expression)
-	t = new TypeTypeof(loc, exp);
-    }
-    check(TOKrparen);
-    return t;
-}
-#endif
-
-/***********************************
- * Parse extern (linkage)
- * The parser is on the 'extern' token.
- */
-
-enum LINK Parser::parseLinkage()
-{
-    enum LINK link = LINKdefault;
-    nextToken();
-    assert(token.value == TOKlparen);
-    nextToken();
-    if (token.value == TOKidentifier)
-    {   Identifier *id = token.ident;
-
-	nextToken();
-	if (id == Id::Windows)
-	    link = LINKwindows;
-	else if (id == Id::Pascal)
-	    link = LINKpascal;
-	else if (id == Id::D)
-	    link = LINKd;
-	else if (id == Id::C)
-	{
-	    link = LINKc;
-	    if (token.value == TOKplusplus)
-	    {   link = LINKcpp;
-		nextToken();
-	    }
-	}
-	else if (id == Id::System)
-	{
-        // LDC we configure target at runtime
-        if (global.params.os == OSWindows)
-            link = LINKwindows;
-        else
-            link = LINKc;
-	}
-	else
-	{
-	    error("valid linkage identifiers are D, C, C++, Pascal, Windows, System");
-	    link = LINKd;
-	}
-    }
-    else
-    {
-	link = LINKd;		// default
-    }
-    check(TOKrparen);
-    return link;
-}
-
-/**************************************
- * Parse a debug conditional
- */
-
-Condition *Parser::parseDebugCondition()
-{
-    Condition *c;
-
-    if (token.value == TOKlparen)
-    {
-	nextToken();
-	unsigned level = 1;
-	Identifier *id = NULL;
-
-	if (token.value == TOKidentifier)
-	    id = token.ident;
-	else if (token.value == TOKint32v)
-	    level = (unsigned)token.uns64value;
-	else
-	    error("identifier or integer expected, not %s", token.toChars());
-	nextToken();
-	check(TOKrparen);
-	c = new DebugCondition(mod, level, id);
-    }
-    else
-	c = new DebugCondition(mod, 1, NULL);
-    return c;
-
-}
-
-/**************************************
- * Parse a version conditional
- */
-
-Condition *Parser::parseVersionCondition()
-{
-    Condition *c;
-    unsigned level = 1;
-    Identifier *id = NULL;
-
-    if (token.value == TOKlparen)
-    {
-	nextToken();
-	if (token.value == TOKidentifier)
-	    id = token.ident;
-	else if (token.value == TOKint32v)
-	    level = (unsigned)token.uns64value;
-#if DMDV2
-	/* Allow:
-	 *    version (unittest)
-	 * even though unittest is a keyword
-	 */
-	else if (token.value == TOKunittest)
-	    id = Lexer::idPool(Token::toChars(TOKunittest));
-#endif
-	else
-	    error("identifier or integer expected, not %s", token.toChars());
-	nextToken();
-	check(TOKrparen);
-
-    }
-    else
-       error("(condition) expected following version");
-    c = new VersionCondition(mod, level, id);
-    return c;
-
-}
-
-/***********************************************
- *	static if (expression)
- *	    body
- *	else
- *	    body
- */
-
-Condition *Parser::parseStaticIfCondition()
-{   Expression *exp;
-    Condition *condition;
-    Array *aif;
-    Array *aelse;
-    Loc loc = this->loc;
-
-    nextToken();
-    if (token.value == TOKlparen)
-    {
-	nextToken();
-	exp = parseAssignExp();
-	check(TOKrparen);
-    }
-    else
-    {   error("(expression) expected following static if");
-	exp = NULL;
-    }
-    condition = new StaticIfCondition(loc, exp);
-    return condition;
-}
-
-
-/*****************************************
- * Parse a constructor definition:
- *	this(arguments) { body }
- * Current token is 'this'.
- */
-
-CtorDeclaration *Parser::parseCtor()
-{
-    CtorDeclaration *f;
-    Arguments *arguments;
-    int varargs;
-    Loc loc = this->loc;
-
-    nextToken();
-    arguments = parseParameters(&varargs);
-    f = new CtorDeclaration(loc, 0, arguments, varargs);
-    parseContracts(f);
-    return f;
-}
-
-/*****************************************
- * Parse a destructor definition:
- *	~this() { body }
- * Current token is '~'.
- */
-
-DtorDeclaration *Parser::parseDtor()
-{
-    DtorDeclaration *f;
-    Loc loc = this->loc;
-
-    nextToken();
-    check(TOKthis);
-    check(TOKlparen);
-    check(TOKrparen);
-
-    f = new DtorDeclaration(loc, 0);
-    parseContracts(f);
-    return f;
-}
-
-/*****************************************
- * Parse a static constructor definition:
- *	static this() { body }
- * Current token is 'this'.
- */
-
-StaticCtorDeclaration *Parser::parseStaticCtor()
-{
-    StaticCtorDeclaration *f;
-    Loc loc = this->loc;
-
-    nextToken();
-    check(TOKlparen);
-    check(TOKrparen);
-
-    f = new StaticCtorDeclaration(loc, 0);
-    parseContracts(f);
-    return f;
-}
-
-/*****************************************
- * Parse a static destructor definition:
- *	static ~this() { body }
- * Current token is '~'.
- */
-
-StaticDtorDeclaration *Parser::parseStaticDtor()
-{
-    StaticDtorDeclaration *f;
-    Loc loc = this->loc;
-
-    nextToken();
-    check(TOKthis);
-    check(TOKlparen);
-    check(TOKrparen);
-
-    f = new StaticDtorDeclaration(loc, 0);
-    parseContracts(f);
-    return f;
-}
-
-/*****************************************
- * Parse an invariant definition:
- *	invariant() { body }
- * Current token is 'invariant'.
- */
-
-InvariantDeclaration *Parser::parseInvariant()
-{
-    InvariantDeclaration *f;
-    Loc loc = this->loc;
-
-    nextToken();
-    if (token.value == TOKlparen)	// optional ()
-    {
-	nextToken();
-	check(TOKrparen);
-    }
-
-    f = new InvariantDeclaration(loc, 0);
-    f->fbody = parseStatement(PScurly);
-    return f;
-}
-
-/*****************************************
- * Parse a unittest definition:
- *	unittest { body }
- * Current token is 'unittest'.
- */
-
-UnitTestDeclaration *Parser::parseUnitTest()
-{
-    UnitTestDeclaration *f;
-    Statement *body;
-    Loc loc = this->loc;
-
-    nextToken();
-
-    body = parseStatement(PScurly);
-
-    f = new UnitTestDeclaration(loc, this->loc);
-    f->fbody = body;
-    return f;
-}
-
-/*****************************************
- * Parse a new definition:
- *	new(arguments) { body }
- * Current token is 'new'.
- */
-
-NewDeclaration *Parser::parseNew()
-{
-    NewDeclaration *f;
-    Arguments *arguments;
-    int varargs;
-    Loc loc = this->loc;
-
-    nextToken();
-    arguments = parseParameters(&varargs);
-    f = new NewDeclaration(loc, 0, arguments, varargs);
-    parseContracts(f);
-    return f;
-}
-
-/*****************************************
- * Parse a delete definition:
- *	delete(arguments) { body }
- * Current token is 'delete'.
- */
-
-DeleteDeclaration *Parser::parseDelete()
-{
-    DeleteDeclaration *f;
-    Arguments *arguments;
-    int varargs;
-    Loc loc = this->loc;
-
-    nextToken();
-    arguments = parseParameters(&varargs);
-    if (varargs)
-	error("... not allowed in delete function parameter list");
-    f = new DeleteDeclaration(loc, 0, arguments);
-    parseContracts(f);
-    return f;
-}
-
-/**********************************************
- * Parse parameter list.
- */
-
-Arguments *Parser::parseParameters(int *pvarargs)
-{
-    Arguments *arguments = new Arguments();
-    int varargs = 0;
-    int hasdefault = 0;
-
-    check(TOKlparen);
-    while (1)
-    {   Type *tb;
-	Identifier *ai = NULL;
-	Type *at;
-	Argument *a;
-	unsigned storageClass;
-	Expression *ae;
-
-	storageClass = STCin;		// parameter is "in" by default
-	switch (token.value)
-	{
-	    case TOKrparen:
-		break;
-
-	    case TOKdotdotdot:
-		varargs = 1;
-		nextToken();
-		break;
-
-	    case TOKin:
-		storageClass = STCin;
-		nextToken();
-		goto L1;
-
-	    case TOKout:
-		storageClass = STCout;
-		nextToken();
-		goto L1;
-
-	    case TOKinout:
-	    case TOKref:
-		storageClass = STCref;
-		nextToken();
-		goto L1;
-
-	    case TOKlazy:
-		storageClass = STClazy;
-		nextToken();
-		goto L1;
-
-	    default:
-	    L1:
-		tb = parseBasicType();
-		at = parseDeclarator(tb, &ai);
-		ae = NULL;
-		if (token.value == TOKassign)	// = defaultArg
-		{   nextToken();
-		    ae = parseAssignExp();
-		    hasdefault = 1;
-		}
-		else
-		{   if (hasdefault)
-			error("default argument expected for %s",
-				ai ? ai->toChars() : at->toChars());
-		}
-		if (token.value == TOKdotdotdot)
-		{   /* This is:
-		     *	at ai ...
-		     */
-
-		    if (storageClass & (STCout | STCref))
-			error("variadic argument cannot be out or ref");
-		    varargs = 2;
-		    a = new Argument(storageClass, at, ai, ae);
-		    arguments->push(a);
-		    nextToken();
-		    break;
-		}
-		a = new Argument(storageClass, at, ai, ae);
-		arguments->push(a);
-		if (token.value == TOKcomma)
-		{   nextToken();
-		    continue;
-		}
-		break;
-	}
-	break;
-    }
-    check(TOKrparen);
-    *pvarargs = varargs;
-    return arguments;
-}
-
-
-/*************************************
- */
-
-EnumDeclaration *Parser::parseEnum()
-{   EnumDeclaration *e;
-    Identifier *id;
-    Type *memtype;
-    Loc loc = this->loc;
-
-    //printf("Parser::parseEnum()\n");
-    nextToken();
-    if (token.value == TOKidentifier)
-    {	id = token.ident;
-	nextToken();
-    }
-    else
-	id = NULL;
-
-    if (token.value == TOKcolon)
-    {
-	nextToken();
-	memtype = parseBasicType();
-    }
-    else
-	memtype = NULL;
-
-    e = new EnumDeclaration(loc, id, memtype);
-    if (token.value == TOKsemicolon && id)
- 	nextToken();
-    else if (token.value == TOKlcurly)
-    {
-	//printf("enum definition\n");
-	e->members = new Array();
-	nextToken();
-	unsigned char *comment = token.blockComment;
-	while (token.value != TOKrcurly)
-	{
-	    if (token.value == TOKidentifier)
-	    {	EnumMember *em;
-		Expression *value;
-		Identifier *ident;
-
-		loc = this->loc;
-		ident = token.ident;
-		value = NULL;
-		nextToken();
-		if (token.value == TOKassign)
-		{
-		    nextToken();
-		    value = parseAssignExp();
-		}
-		em = new EnumMember(loc, ident, value);
-		e->members->push(em);
-		if (token.value == TOKrcurly)
-		    ;
-		else
-		{   addComment(em, comment);
-		    comment = NULL;
-		    check(TOKcomma);
-		}
-		addComment(em, comment);
-		comment = token.blockComment;
-	    }
-	    else
-	    {	error("enum member expected");
-		nextToken();
-	    }
-	}
-	nextToken();
-    }
-    else
-	error("enum declaration is invalid");
-
-    //printf("-parseEnum() %s\n", e->toChars());
-    return e;
-}
-
-/********************************
- * Parse struct, union, interface, class.
- */
-
-Dsymbol *Parser::parseAggregate()
-{   AggregateDeclaration *a = NULL;
-    int anon = 0;
-    enum TOK tok;
-    Identifier *id;
-    TemplateParameters *tpl = NULL;
-
-    //printf("Parser::parseAggregate()\n");
-    tok = token.value;
-    nextToken();
-    if (token.value != TOKidentifier)
-    {	id = NULL;
-    }
-    else
-    {	id = token.ident;
-	nextToken();
-
-	if (token.value == TOKlparen)
-	{   // Class template declaration.
-
-	    // Gather template parameter list
-	    tpl = parseTemplateParameterList();
-	}
-    }
-
-    Loc loc = this->loc;
-    switch (tok)
-    {	case TOKclass:
-	case TOKinterface:
-	{
-	    if (!id)
-		error("anonymous classes not allowed");
-
-	    // Collect base class(es)
-	    BaseClasses *baseclasses = NULL;
-	    if (token.value == TOKcolon)
-	    {
-		nextToken();
-		baseclasses = parseBaseClasses();
-
-		if (token.value != TOKlcurly)
-		    error("members expected");
-	    }
-
-	    if (tok == TOKclass)
-		a = new ClassDeclaration(loc, id, baseclasses);
-	    else
-		a = new InterfaceDeclaration(loc, id, baseclasses);
-	    break;
-	}
-
-	case TOKstruct:
-	    if (id)
-		a = new StructDeclaration(loc, id);
-	    else
-		anon = 1;
-	    break;
-
-	case TOKunion:
-	    if (id)
-		a = new UnionDeclaration(loc, id);
-	    else
-		anon = 2;
-	    break;
-
-	default:
-	    assert(0);
-	    break;
-    }
-    if (a && token.value == TOKsemicolon)
-    { 	nextToken();
-    }
-    else if (token.value == TOKlcurly)
-    {
-	//printf("aggregate definition\n");
-	nextToken();
-	Array *decl = parseDeclDefs(0);
-	if (token.value != TOKrcurly)
-	    error("} expected following member declarations in aggregate");
-	nextToken();
-	if (anon)
-	{
-	    /* Anonymous structs/unions are more like attributes.
-	     */
-	    return new AnonDeclaration(loc, anon - 1, decl);
-	}
-	else
-	    a->members = decl;
-    }
-    else
-    {
-	error("{ } expected following aggregate declaration");
-	a = new StructDeclaration(loc, NULL);
-    }
-
-    if (tpl)
-    {	Array *decldefs;
-	TemplateDeclaration *tempdecl;
-
-	// Wrap a template around the aggregate declaration
-	decldefs = new Array();
-	decldefs->push(a);
-	tempdecl = new TemplateDeclaration(loc, id, tpl, NULL, decldefs);
-	return tempdecl;
-    }
-
-    return a;
-}
-
-/*******************************************
- */
-
-BaseClasses *Parser::parseBaseClasses()
-{
-    enum PROT protection = PROTpublic;
-    BaseClasses *baseclasses = new BaseClasses();
-
-    for (; 1; nextToken())
-    {
-	switch (token.value)
-	{
-	    case TOKidentifier:
-		break;
-	    case TOKprivate:
-		protection = PROTprivate;
-		continue;
-	    case TOKpackage:
-		protection = PROTpackage;
-		continue;
-	    case TOKprotected:
-		protection = PROTprotected;
-		continue;
-	    case TOKpublic:
-		protection = PROTpublic;
-		continue;
-	    default:
-		error("base classes expected instead of %s", token.toChars());
-		return NULL;
-	}
-	BaseClass *b = new BaseClass(parseBasicType(), protection);
-	baseclasses->push(b);
-	if (token.value != TOKcomma)
-	    break;
-	protection = PROTpublic;
-    }
-    return baseclasses;
-}
-
-/**************************************
- * Parse constraint.
- * Constraint is of the form:
- *	if ( ConstraintExpression )
- */
-
-#if DMDV2
-Expression *Parser::parseConstraint()
-{   Expression *e = NULL;
-
-    if (token.value == TOKif)
-    {
-	nextToken();	// skip over 'if'
-	check(TOKlparen);
-	e = parseExpression();
-	check(TOKrparen);
-    }
-    return e;
-}
-#endif
-
-/**************************************
- * Parse a TemplateDeclaration.
- */
-
-TemplateDeclaration *Parser::parseTemplateDeclaration()
-{
-    TemplateDeclaration *tempdecl;
-    Identifier *id;
-    TemplateParameters *tpl;
-    Array *decldefs;
-    Loc loc = this->loc;
-
-    nextToken();
-    if (token.value != TOKidentifier)
-    {   error("TemplateIdentifier expected following template");
-	goto Lerr;
-    }
-    id = token.ident;
-    nextToken();
-    tpl = parseTemplateParameterList();
-    if (!tpl)
-	goto Lerr;
-
-    if (token.value != TOKlcurly)
-    {	error("members of template declaration expected");
-	goto Lerr;
-    }
-    else
-    {
-	nextToken();
-	decldefs = parseDeclDefs(0);
-	if (token.value != TOKrcurly)
-	{   error("template member expected");
-	    goto Lerr;
-	}
-	nextToken();
-    }
-
-    tempdecl = new TemplateDeclaration(loc, id, tpl, NULL, decldefs);
-    return tempdecl;
-
-Lerr:
-    return NULL;
-}
-
-/******************************************
- * Parse template parameter list.
- */
-
-TemplateParameters *Parser::parseTemplateParameterList()
-{
-    TemplateParameters *tpl = new TemplateParameters();
-
-    if (token.value != TOKlparen)
-    {   error("parenthesized TemplateParameterList expected following TemplateIdentifier");
-	goto Lerr;
-    }
-    nextToken();
-
-    // Get array of TemplateParameters
-    if (token.value != TOKrparen)
-    {	int isvariadic = 0;
-
-	while (1)
-	{   TemplateParameter *tp;
-	    Identifier *tp_ident = NULL;
-	    Type *tp_spectype = NULL;
-	    Type *tp_valtype = NULL;
-	    Type *tp_defaulttype = NULL;
-	    Expression *tp_specvalue = NULL;
-	    Expression *tp_defaultvalue = NULL;
-	    Token *t;
-
-	    // Get TemplateParameter
-
-	    // First, look ahead to see if it is a TypeParameter or a ValueParameter
-	    t = peek(&token);
-	    if (token.value == TOKalias)
-	    {	// AliasParameter
-		nextToken();
-		if (token.value != TOKidentifier)
-		{   error("Identifier expected for template parameter");
-		    goto Lerr;
-		}
-		tp_ident = token.ident;
-		nextToken();
-		if (token.value == TOKcolon)	// : Type
-		{
-		    nextToken();
-		    tp_spectype = parseBasicType();
-		    tp_spectype = parseDeclarator(tp_spectype, NULL);
-		}
-		if (token.value == TOKassign)	// = Type
-		{
-		    nextToken();
-		    tp_defaulttype = parseBasicType();
-		    tp_defaulttype = parseDeclarator(tp_defaulttype, NULL);
-		}
-		tp = new TemplateAliasParameter(loc, tp_ident, tp_spectype, tp_defaulttype);
-	    }
-	    else if (t->value == TOKcolon || t->value == TOKassign ||
-		     t->value == TOKcomma || t->value == TOKrparen)
-	    {	// TypeParameter
-		if (token.value != TOKidentifier)
-		{   error("Identifier expected for template parameter");
-		    goto Lerr;
-		}
-		tp_ident = token.ident;
-		nextToken();
-		if (token.value == TOKcolon)	// : Type
-		{
-		    nextToken();
-		    tp_spectype = parseBasicType();
-		    tp_spectype = parseDeclarator(tp_spectype, NULL);
-		}
-		if (token.value == TOKassign)	// = Type
-		{
-		    nextToken();
-		    tp_defaulttype = parseBasicType();
-		    tp_defaulttype = parseDeclarator(tp_defaulttype, NULL);
-		}
-		tp = new TemplateTypeParameter(loc, tp_ident, tp_spectype, tp_defaulttype);
-	    }
-	    else if (token.value == TOKidentifier && t->value == TOKdotdotdot)
-	    {	// ident...
-		if (isvariadic)
-		    error("variadic template parameter must be last");
-		isvariadic = 1;
-		tp_ident = token.ident;
-		nextToken();
-		nextToken();
-		tp = new TemplateTupleParameter(loc, tp_ident);
-	    }
-#if DMDV2
-	    else if (token.value == TOKthis)
-	    {	// ThisParameter
-		nextToken();
-		if (token.value != TOKidentifier)
-		{   error("identifier expected for template this parameter");
-		    goto Lerr;
-		}
-		tp_ident = token.ident;
-		nextToken();
-		if (token.value == TOKcolon)	// : Type
-		{
-		    nextToken();
-		    tp_spectype = parseType();
-		}
-		if (token.value == TOKassign)	// = Type
-		{
-		    nextToken();
-		    tp_defaulttype = parseType();
-		}
-		tp = new TemplateThisParameter(loc, tp_ident, tp_spectype, tp_defaulttype);
-	    }
-#endif
-	    else
-	    {	// ValueParameter
-		tp_valtype = parseBasicType();
-		tp_valtype = parseDeclarator(tp_valtype, &tp_ident);
-		if (!tp_ident)
-		{
-		    error("identifier expected for template value parameter");
-		    tp_ident = new Identifier("error", TOKidentifier);
-		}
-		if (token.value == TOKcolon)	// : CondExpression
-		{
-		    nextToken();
-		    tp_specvalue = parseCondExp();
-		}
-		if (token.value == TOKassign)	// = CondExpression
-		{
-		    nextToken();
-		    tp_defaultvalue = parseCondExp();
-		}
-		tp = new TemplateValueParameter(loc, tp_ident, tp_valtype, tp_specvalue, tp_defaultvalue);
-	    }
-	    tpl->push(tp);
-	    if (token.value != TOKcomma)
-		break;
-	    nextToken();
-	}
-    }
-    check(TOKrparen);
-Lerr:
-    return tpl;
-}
-
-/******************************************
- * Parse template mixin.
- *	mixin Foo;
- *	mixin Foo!(args);
- *	mixin a.b.c!(args).Foo!(args);
- *	mixin Foo!(args) identifier;
- *	mixin typeof(expr).identifier!(args);
- */
-
-Dsymbol *Parser::parseMixin()
-{
-    TemplateMixin *tm;
-    Identifier *id;
-    Type *tqual;
-    Objects *tiargs;
-    Array *idents;
-
-    //printf("parseMixin()\n");
-    nextToken();
-    tqual = NULL;
-    if (token.value == TOKdot)
-    {
-	id = Id::empty;
-    }
-    else
-    {
-	if (token.value == TOKtypeof)
-	{   Expression *exp;
-
-	    nextToken();
-	    check(TOKlparen);
-	    exp = parseExpression();
-	    check(TOKrparen);
-	    tqual = new TypeTypeof(loc, exp);
-	    check(TOKdot);
-	}
-	if (token.value != TOKidentifier)
-	{
-	    error("identifier expected, not %s", token.toChars());
-	    id = Id::empty;
-	}
-	else
-	    id = token.ident;
-	nextToken();
-    }
-
-    idents = new Array();
-    while (1)
-    {
-	tiargs = NULL;
-	if (token.value == TOKnot)
-	{
-	    nextToken();
-	    tiargs = parseTemplateArgumentList();
-	}
-
-	if (token.value != TOKdot)
-	    break;
-
-	if (tiargs)
-	{   TemplateInstance *tempinst = new TemplateInstance(loc, id);
-	    tempinst->tiargs = tiargs;
-	    id = (Identifier *)tempinst;
-	    tiargs = NULL;
-	}
-	idents->push(id);
-
-	nextToken();
-	if (token.value != TOKidentifier)
-	{   error("identifier expected following '.' instead of '%s'", token.toChars());
-	    break;
-	}
-	id = token.ident;
-	nextToken();
-    }
-    idents->push(id);
-
-    if (token.value == TOKidentifier)
-    {
-	id = token.ident;
-	nextToken();
-    }
-    else
-	id = NULL;
-
-    tm = new TemplateMixin(loc, id, tqual, idents, tiargs);
-    if (token.value != TOKsemicolon)
-	error("';' expected after mixin");
-    nextToken();
-
-    return tm;
-}
-
-/******************************************
- * Parse template argument list.
- * Input:
- * 	current token is opening '('
- * Output:
- *	current token is one after closing ')'
- */
-
-Objects *Parser::parseTemplateArgumentList()
-{
-    //printf("Parser::parseTemplateArgumentList()\n");
-    Objects *tiargs = new Objects();
-    if (token.value != TOKlparen)
-    {   error("!(TemplateArgumentList) expected following TemplateIdentifier");
-	return tiargs;
-    }
-    nextToken();
-
-    // Get TemplateArgumentList
-    if (token.value != TOKrparen)
-    {
-	while (1)
-	{
-	    // See if it is an Expression or a Type
-	    if (isDeclaration(&token, 0, TOKreserved, NULL))
-	    {	// Type
-		Type *ta;
-
-		// Get TemplateArgument
-		ta = parseBasicType();
-		ta = parseDeclarator(ta, NULL);
-		tiargs->push(ta);
-	    }
-	    else
-	    {	// Expression
-		Expression *ea;
-
-		ea = parseAssignExp();
-		tiargs->push(ea);
-	    }
-	    if (token.value != TOKcomma)
-		break;
-	    nextToken();
-	}
-    }
-    check(TOKrparen, "template argument list");
-    return tiargs;
-}
-
-Import *Parser::parseImport(Array *decldefs, int isstatic)
-{   Import *s;
-    Identifier *id;
-    Identifier *aliasid = NULL;
-    Array *a;
-    Loc loc;
-
-    //printf("Parser::parseImport()\n");
-    do
-    {
-     L1:
-	nextToken();
-	if (token.value != TOKidentifier)
-	{   error("Identifier expected following import");
-	    break;
-	}
-
-	loc = this->loc;
-	a = NULL;
-	id = token.ident;
-	nextToken();
-	if (!aliasid && token.value == TOKassign)
-	{
-	    aliasid = id;
-	    goto L1;
-	}
-	while (token.value == TOKdot)
-	{
-	    if (!a)
-		a = new Array();
-	    a->push(id);
-	    nextToken();
-	    if (token.value != TOKidentifier)
-	    {   error("Identifier expected following package");
-		break;
-	    }
-	    id = token.ident;
-	    nextToken();
-	}
-
-	s = new Import(loc, a, id, aliasid, isstatic);
-	decldefs->push(s);
-
-	/* Look for
-	 *	: alias=name, alias=name;
-	 * syntax.
-	 */
-	if (token.value == TOKcolon)
-	{
-	    do
-	    {	Identifier *name;
-		Identifier *alias;
-
-		nextToken();
-		if (token.value != TOKidentifier)
-		{   error("Identifier expected following :");
-		    break;
-		}
-		alias = token.ident;
-		nextToken();
-		if (token.value == TOKassign)
-		{
-		    nextToken();
-		    if (token.value != TOKidentifier)
-		    {   error("Identifier expected following %s=", alias->toChars());
-			break;
-		    }
-		    name = token.ident;
-		    nextToken();
-		}
-		else
-		{   name = alias;
-		    alias = NULL;
-		}
-		s->addAlias(name, alias);
-	    } while (token.value == TOKcomma);
-	    break;	// no comma-separated imports of this form
-	}
-
-	aliasid = NULL;
-    } while (token.value == TOKcomma);
-
-    if (token.value == TOKsemicolon)
- 	nextToken();
-    else
-    {
-	error("';' expected");
-	nextToken();
-    }
-
-    return NULL;
-}
-
-#if DMDV2
-Type *Parser::parseType(Identifier **pident, TemplateParameters **tpl)
-{   Type *t;
-
-    /* Take care of the storage class prefixes that
-     * serve as type attributes:
-     *  const shared, shared const, const, invariant, shared
-     */
-    if (token.value == TOKconst && peekNext() == TOKshared && peekNext2() != TOKlparen ||
-	token.value == TOKshared && peekNext() == TOKconst && peekNext2() != TOKlparen)
-    {
-	nextToken();
-	nextToken();
-	/* shared const type
-	 */
-	t = parseType(pident, tpl);
-	t = t->makeSharedConst();
-	return t;
-    }
-    else if (token.value == TOKconst && peekNext() != TOKlparen)
-    {
-	nextToken();
-	/* const type
-	 */
-	t = parseType(pident, tpl);
-	t = t->makeConst();
-	return t;
-    }
-    else if ((token.value == TOKinvariant || token.value == TOKimmutable) &&
-             peekNext() != TOKlparen)
-    {
-	nextToken();
-	/* invariant type
-	 */
-	t = parseType(pident, tpl);
-	t = t->makeInvariant();
-	return t;
-    }
-    else if (token.value == TOKshared && peekNext() != TOKlparen)
-    {
-	nextToken();
-	/* shared type
-	 */
-	t = parseType(pident, tpl);
-	t = t->makeShared();
-	return t;
-    }
-    else
-	t = parseBasicType();
-    t = parseDeclarator(t, pident, tpl);
-    return t;
-}
-#endif
-
-Type *Parser::parseBasicType()
-{   Type *t;
-    Identifier *id;
-    TypeQualified *tid;
-    TemplateInstance *tempinst;
-
-    //printf("parseBasicType()\n");
-    switch (token.value)
-    {
-	CASE_BASIC_TYPES_X(t):
-	    nextToken();
-	    break;
-
-	case TOKidentifier:
-	    id = token.ident;
-	    nextToken();
-	    if (token.value == TOKnot)
-	    {
-		nextToken();
-		tempinst = new TemplateInstance(loc, id);
-		tempinst->tiargs = parseTemplateArgumentList();
-		tid = new TypeInstance(loc, tempinst);
-		goto Lident2;
-	    }
-	Lident:
-	    tid = new TypeIdentifier(loc, id);
-	Lident2:
-	    while (token.value == TOKdot)
-	    {	nextToken();
-		if (token.value != TOKidentifier)
-		{   error("identifier expected following '.' instead of '%s'", token.toChars());
-		    break;
-		}
-		id = token.ident;
-		nextToken();
-		if (token.value == TOKnot)
-		{
-		    nextToken();
-		    tempinst = new TemplateInstance(loc, id);
-		    tempinst->tiargs = parseTemplateArgumentList();
-		    tid->addIdent((Identifier *)tempinst);
-		}
-		else
-		    tid->addIdent(id);
-	    }
-	    t = tid;
-	    break;
-
-	case TOKdot:
-	    // Leading . as in .foo
-	    id = Id::empty;
-	    goto Lident;
-
-	case TOKtypeof:
-	{   Expression *exp;
-
-	    nextToken();
-	    check(TOKlparen);
-	    exp = parseExpression();
-	    check(TOKrparen);
-	    tid = new TypeTypeof(loc, exp);
-	    goto Lident2;
-	}
-
-	default:
-	    error("basic type expected, not %s", token.toChars());
-	    t = Type::tint32;
-	    break;
-    }
-    return t;
-}
-
-/******************************************
- * Parse things that follow the initial type t.
- *	t *
- *	t []
- *	t [type]
- *	t [expression]
- *	t [expression .. expression]
- *	t function
- *	t delegate
- */
-
-Type *Parser::parseBasicType2(Type *t)
-{
-    Type *ts;
-    Type *ta;
-
-    //printf("parseBasicType2()\n");
-    while (1)
-    {
-	switch (token.value)
-	{
-	    case TOKmul:
-		t = new TypePointer(t);
-		nextToken();
-		continue;
-
-	    case TOKlbracket:
-#if LTORARRAYDECL
-		// Handle []. Make sure things like
-		//     int[3][1] a;
-		// is (array[1] of array[3] of int)
-		nextToken();
-		if (token.value == TOKrbracket)
-		{
-		    t = new TypeDArray(t);			// []
-		    nextToken();
-		}
-		else if (isDeclaration(&token, 0, TOKrbracket, NULL))
-		{   // It's an associative array declaration
-		    Type *index;
-
-		    //printf("it's an associative array\n");
-		    index = parseBasicType();
-		    index = parseDeclarator(index, NULL);	// [ type ]
-		    t = new TypeAArray(t, index);
-		    check(TOKrbracket);
-		}
-		else
-		{
-		    //printf("it's [expression]\n");
-		    inBrackets++;
-		    Expression *e = parseExpression();		// [ expression ]
-		    if (token.value == TOKslice)
-		    {	Expression *e2;
-
-			nextToken();
-			e2 = parseExpression();			// [ exp .. exp ]
-			t = new TypeSlice(t, e, e2);
-		    }
-		    else
-			t = new TypeSArray(t,e);
-		    inBrackets--;
-		    check(TOKrbracket);
-		}
-		continue;
-#else
-		// Handle []. Make sure things like
-		//     int[3][1] a;
-		// is (array[3] of array[1] of int)
-		ts = t;
-		while (token.value == TOKlbracket)
-		{
-		    nextToken();
-		    if (token.value == TOKrbracket)
-		    {
-			ta = new TypeDArray(t);			// []
-			nextToken();
-		    }
-		    else if (isDeclaration(&token, 0, TOKrbracket, NULL))
-		    {   // It's an associative array declaration
-			Type *index;
-
-			//printf("it's an associative array\n");
-			index = parseBasicType();
-			index = parseDeclarator(index, NULL);	// [ type ]
-			check(TOKrbracket);
-			ta = new TypeAArray(t, index);
-		    }
-		    else
-		    {
-			//printf("it's [expression]\n");
-			Expression *e = parseExpression();	// [ expression ]
-			ta = new TypeSArray(t,e);
-			check(TOKrbracket);
-		    }
-		    Type **pt;
-		    for (pt = &ts; *pt != t; pt = &(*pt)->next)
-			;
-		    *pt = ta;
-		}
-		t = ts;
-		continue;
-#endif
-
-	    case TOKdelegate:
-	    case TOKfunction:
-	    {	// Handle delegate declaration:
-		//	t delegate(parameter list)
-		//	t function(parameter list)
-		Arguments *arguments;
-		int varargs;
-		enum TOK save = token.value;
-
-		nextToken();
-		arguments = parseParameters(&varargs);
-		t = new TypeFunction(arguments, t, varargs, linkage);
-		if (save == TOKdelegate)
-		    t = new TypeDelegate(t);
-		else
-		    t = new TypePointer(t);	// pointer to function
-		continue;
-	    }
-
-	    default:
-		ts = t;
-		break;
-	}
-	break;
-    }
-    return ts;
-}
-
-Type *Parser::parseDeclarator(Type *t, Identifier **pident, TemplateParameters **tpl)
-{   Type *ts;
-    Type *ta;
-
-    //printf("parseDeclarator(tpl = %p)\n", tpl);
-    t = parseBasicType2(t);
-
-    switch (token.value)
-    {
-
-	case TOKidentifier:
-	    if (pident)
-		*pident = token.ident;
-	    else
-		error("unexpected identifer '%s' in declarator", token.ident->toChars());
-	    ts = t;
-	    nextToken();
-	    break;
-
-	case TOKlparen:
-	    /* Parse things with parentheses around the identifier, like:
-	     *	int (*ident[3])[]
-	     * although the D style would be:
-	     *	int[]*[3] ident
-	     */
-	    nextToken();
-	    ts = parseDeclarator(t, pident);
-	    check(TOKrparen);
-	    break;
-
-	default:
-	    ts = t;
-	    break;
-    }
-
-    // parse DeclaratorSuffixes
-    while (1)
-    {
-	switch (token.value)
-	{
-#if CARRAYDECL
-	    /* Support C style array syntax:
-	     *   int ident[]
-	     * as opposed to D-style:
-	     *   int[] ident
-	     */
-	    case TOKlbracket:
-	    {	// This is the old C-style post [] syntax.
-		nextToken();
-		if (token.value == TOKrbracket)
-		{   // It's a dynamic array
-		    ta = new TypeDArray(t);		// []
-		    nextToken();
-		}
-		else if (isDeclaration(&token, 0, TOKrbracket, NULL))
-		{   // It's an associative array declaration
-		    Type *index;
-
-		    //printf("it's an associative array\n");
-		    index = parseBasicType();
-		    index = parseDeclarator(index, NULL);	// [ type ]
-		    check(TOKrbracket);
-		    ta = new TypeAArray(t, index);
-		}
-		else
-		{
-		    //printf("it's [expression]\n");
-		    Expression *e = parseExpression();		// [ expression ]
-		    ta = new TypeSArray(t, e);
-		    check(TOKrbracket);
-		}
-
-		/* Insert ta into
-		 *   ts -> ... -> t
-		 * so that
-		 *   ts -> ... -> ta -> t
-		 */
-		Type **pt;
-		for (pt = &ts; *pt != t; pt = &(*pt)->next)
-		    ;
-		*pt = ta;
-		continue;
-	    }
-#endif
-	    case TOKlparen:
-	    {	Arguments *arguments;
-		int varargs;
-
-		if (tpl)
-		{
-		    /* Look ahead to see if this is (...)(...),
-		     * i.e. a function template declaration
-		     */
-		    if (peekPastParen(&token)->value == TOKlparen)
-		    {   // It's a function template declaration
-			//printf("function template declaration\n");
-
-			// Gather template parameter list
-			*tpl = parseTemplateParameterList();
-		    }
-		}
-
-		arguments = parseParameters(&varargs);
-		Type *ta = new TypeFunction(arguments, t, varargs, linkage);
-		Type **pt;
-		for (pt = &ts; *pt != t; pt = &(*pt)->next)
-		    ;
-		*pt = ta;
-		break;
-	    }
-	}
-	break;
-    }
-
-    return ts;
-}
-
-/**********************************
- * Parse Declarations.
- * These can be:
- *	1. declarations at global/class level
- *	2. declarations at statement level
- * Return array of Declaration *'s.
- */
-
-Array *Parser::parseDeclarations()
-{
-    enum STC storage_class;
-    enum STC stc;
-    Type *ts;
-    Type *t;
-    Type *tfirst;
-    Identifier *ident;
-    Array *a;
-    enum TOK tok = TOKreserved;
-    unsigned char *comment = token.blockComment;
-    enum LINK link = linkage;
-
-    //printf("parseDeclarations()\n");
-    switch (token.value)
-    {
-	case TOKtypedef:
-	case TOKalias:
-	    tok = token.value;
-	    nextToken();
-	    break;
-
-	default:
-	    tok = TOKreserved;
-	    break;
-    }
-
-    storage_class = STCundefined;
-    while (1)
-    {
-	switch (token.value)
-	{
-	    case TOKconst:	stc = STCconst;		 goto L1;
-	    case TOKstatic:	stc = STCstatic;	 goto L1;
-	    case TOKfinal:	stc = STCfinal;		 goto L1;
-	    case TOKauto:	stc = STCauto;		 goto L1;
-	    case TOKscope:	stc = STCscope;		 goto L1;
-	    case TOKoverride:	stc = STCoverride;	 goto L1;
-	    case TOKabstract:	stc = STCabstract;	 goto L1;
-	    case TOKsynchronized: stc = STCsynchronized; goto L1;
-	    case TOKdeprecated: stc = STCdeprecated;	 goto L1;
-#if DMDV2
-	    case TOKnothrow:    stc = STCnothrow;	 goto L1;
-	    case TOKpure:       stc = STCpure;		 goto L1;
-	    case TOKref:        stc = STCref;            goto L1;
-	    case TOKtls:        stc = STCtls;		 goto L1;
-	    case TOKenum:	stc = STCmanifest;	 goto L1;
-#endif
-	    L1:
-		if (storage_class & stc)
-		    error("redundant storage class '%s'", token.toChars());
-		storage_class = (STC) (storage_class | stc);
-		nextToken();
-		continue;
-
-	    case TOKextern:
-		if (peek(&token)->value != TOKlparen)
-		{   stc = STCextern;
-		    goto L1;
-		}
-
-		link = parseLinkage();
-		continue;
-
-	    default:
-		break;
-	}
-	break;
-    }
-
-    a = new Array();
-
-    /* Look for auto initializers:
-     *	storage_class identifier = initializer;
-     */
-    while (storage_class &&
-	token.value == TOKidentifier &&
-	peek(&token)->value == TOKassign)
-    {
-	ident = token.ident;
-	nextToken();
-	nextToken();
-	Initializer *init = parseInitializer();
-	VarDeclaration *v = new VarDeclaration(loc, NULL, ident, init);
-	v->storage_class = storage_class;
-	a->push(v);
-	if (token.value == TOKsemicolon)
-	{
-	    nextToken();
-	    addComment(v, comment);
-	}
-	else if (token.value == TOKcomma)
-	{
-	    nextToken();
-	    if (!(token.value == TOKidentifier && peek(&token)->value == TOKassign))
-	    {
-		error("Identifier expected following comma");
-	    }
-	    else
-		continue;
-	}
-	else
-	    error("semicolon expected following auto declaration, not '%s'", token.toChars());
-	return a;
-    }
-
-    if (token.value == TOKclass)
-    {	AggregateDeclaration *s;
-
-	s = (AggregateDeclaration *)parseAggregate();
-	s->storage_class |= storage_class;
-	a->push(s);
-	addComment(s, comment);
-	return a;
-    }
-
-    ts = parseBasicType();
-    ts = parseBasicType2(ts);
-    tfirst = NULL;
-
-    while (1)
-    {
-	Loc loc = this->loc;
-	TemplateParameters *tpl = NULL;
-
-	ident = NULL;
-	t = parseDeclarator(ts, &ident, &tpl);
-	assert(t);
-	if (!tfirst)
-	    tfirst = t;
-	else if (t != tfirst)
-	    error("multiple declarations must have the same type, not %s and %s",
-		tfirst->toChars(), t->toChars());
-	if (!ident)
-	    error("no identifier for declarator %s", t->toChars());
-
-	if (tok == TOKtypedef || tok == TOKalias)
-	{   Declaration *v;
-	    Initializer *init = NULL;
-
-	    if (token.value == TOKassign)
-	    {
-		nextToken();
-		init = parseInitializer();
-	    }
-	    if (tok == TOKtypedef)
-		v = new TypedefDeclaration(loc, ident, t, init);
-	    else
-	    {	if (init)
-		    error("alias cannot have initializer");
-		v = new AliasDeclaration(loc, ident, t);
-	    }
-	    v->storage_class = storage_class;
-	    if (link == linkage)
-		a->push(v);
-	    else
-	    {
-		Array *ax = new Array();
-		ax->push(v);
-		Dsymbol *s = new LinkDeclaration(link, ax);
-		a->push(s);
-	    }
-	    switch (token.value)
-	    {   case TOKsemicolon:
-		    nextToken();
-		    addComment(v, comment);
-		    break;
-
-		case TOKcomma:
-		    nextToken();
-		    addComment(v, comment);
-		    continue;
-
-		default:
-		    error("semicolon expected to close %s declaration", Token::toChars(tok));
-		    break;
-	    }
-	}
-	else if (t->ty == Tfunction)
-	{   FuncDeclaration *f =
-		new FuncDeclaration(loc, 0, ident, storage_class, t);
-	    addComment(f, comment);
-	    parseContracts(f);
-	    addComment(f, NULL);
-	    Dsymbol *s;
-	    if (link == linkage)
-	    {
-		s = f;
-	    }
-	    else
-	    {
-		Array *ax = new Array();
-		ax->push(f);
-		s = new LinkDeclaration(link, ax);
-	    }
-	    if (tpl)			// it's a function template
-	    {   Array *decldefs;
-		TemplateDeclaration *tempdecl;
-
-		// Wrap a template around the aggregate declaration
-		decldefs = new Array();
-		decldefs->push(s);
-		tempdecl = new TemplateDeclaration(loc, s->ident, tpl, NULL, decldefs);
-		s = tempdecl;
-	    }
-	    addComment(s, comment);
-	    a->push(s);
-	}
-	else
-	{
-	    Initializer *init = NULL;
-	    if (token.value == TOKassign)
-	    {
-		nextToken();
-		init = parseInitializer();
-	    }
-
-	    VarDeclaration *v = new VarDeclaration(loc, t, ident, init);
-	    v->storage_class = storage_class;
-	    if (link == linkage)
-		a->push(v);
-	    else
-	    {
-		Array *ax = new Array();
-		ax->push(v);
-		Dsymbol *s = new LinkDeclaration(link, ax);
-		a->push(s);
-	    }
-	    switch (token.value)
-	    {   case TOKsemicolon:
-		    nextToken();
-		    addComment(v, comment);
-		    break;
-
-		case TOKcomma:
-		    nextToken();
-		    addComment(v, comment);
-		    continue;
-
-		default:
-		    error("semicolon expected, not '%s'", token.toChars());
-		    break;
-	    }
-	}
-	break;
-    }
-    return a;
-}
-
-/*****************************************
- * Parse auto declarations of the form:
- *   storageClass ident = init, ident = init, ... ;
- * and return the array of them.
- * Starts with token on the first ident.
- * Ends with scanner past closing ';'
- */
-
-#if DMDV2
-Array *Parser::parseAutoDeclarations(unsigned storageClass, unsigned char *comment)
-{
-    Array *a = new Array;
-
-    while (1)
-    {
-	Identifier *ident = token.ident;
-	nextToken();		// skip over ident
-	assert(token.value == TOKassign);
-	nextToken();		// skip over '='
-	Initializer *init = parseInitializer();
-	VarDeclaration *v = new VarDeclaration(loc, NULL, ident, init);
-	v->storage_class = storageClass;
-	a->push(v);
-	if (token.value == TOKsemicolon)
-	{
-	    nextToken();
-	    addComment(v, comment);
-	}
-	else if (token.value == TOKcomma)
-	{
-	    nextToken();
-	    if (token.value == TOKidentifier &&
-		peek(&token)->value == TOKassign)
-	    {
-		addComment(v, comment);
-		continue;
-	    }
-	    else
-		error("Identifier expected following comma");
-	}
-	else
-	    error("semicolon expected following auto declaration, not '%s'", token.toChars());
-	break;
-    }
-    return a;
-}
-#endif
-
-/*****************************************
- * Parse contracts following function declaration.
- */
-
-void Parser::parseContracts(FuncDeclaration *f)
-{
-    Type *tb;
-    enum LINK linksave = linkage;
-
-    // The following is irrelevant, as it is overridden by sc->linkage in
-    // TypeFunction::semantic
-    linkage = LINKd;		// nested functions have D linkage
-L1:
-    switch (token.value)
-    {
-	case TOKlcurly:
-	    if (f->frequire || f->fensure)
-		error("missing body { ... } after in or out");
-	    f->fbody = parseStatement(PSsemi);
-	    f->endloc = endloc;
-	    break;
-
-	case TOKbody:
-	    nextToken();
-	    f->fbody = parseStatement(PScurly);
-	    f->endloc = endloc;
-	    break;
-
-	case TOKsemicolon:
-	    if (f->frequire || f->fensure)
-		error("missing body { ... } after in or out");
-	    nextToken();
-	    break;
-
-#if 0	// Do we want this for function declarations, so we can do:
-    // int x, y, foo(), z;
-	case TOKcomma:
-	    nextToken();
-	    continue;
-#endif
-
-#if 0 // Dumped feature
-	case TOKthrow:
-	    if (!f->fthrows)
-		f->fthrows = new Array();
-	    nextToken();
-	    check(TOKlparen);
-	    while (1)
-	    {
-		tb = parseBasicType();
-		f->fthrows->push(tb);
-		if (token.value == TOKcomma)
-		{   nextToken();
-		    continue;
-		}
-		break;
-	    }
-	    check(TOKrparen);
-	    goto L1;
-#endif
-
-	case TOKin:
-	    nextToken();
-	    if (f->frequire)
-		error("redundant 'in' statement");
-	    f->frequire = parseStatement(PScurly | PSscope);
-	    goto L1;
-
-	case TOKout:
-	    // parse: out (identifier) { statement }
-	    nextToken();
-	    if (token.value != TOKlcurly)
-	    {
-		check(TOKlparen);
-		if (token.value != TOKidentifier)	   
-		    error("(identifier) following 'out' expected, not %s", token.toChars());
-		f->outId = token.ident;
-		nextToken();
-		check(TOKrparen);
-	    }
-	    if (f->fensure)
-		error("redundant 'out' statement");
-	    f->fensure = parseStatement(PScurly | PSscope);
-	    goto L1;
-
-	default:
-	    error("semicolon expected following function declaration");
-	    break;
-    }
-    linkage = linksave;
-}
-
-/*****************************************
- * Parse initializer for variable declaration.
- */
-
-Initializer *Parser::parseInitializer()
-{
-    StructInitializer *is;
-    ArrayInitializer *ia;
-    ExpInitializer *ie;
-    Expression *e;
-    Identifier *id;
-    Initializer *value;
-    int comma;
-    Loc loc = this->loc;
-    Token *t;
-    int braces;
-    int brackets;
-
-    switch (token.value)
-    {
-	case TOKlcurly:
-	    /* Scan ahead to see if it is a struct initializer or
-	     * a function literal.
-	     * If it contains a ';', it is a function literal.
-	     * Treat { } as a struct initializer.
-	     */
-	    braces = 1;
-	    for (t = peek(&token); 1; t = peek(t))
-	    {
-		switch (t->value)
-		{
-		    case TOKsemicolon:
-		    case TOKreturn:
-			goto Lexpression;
-
-		    case TOKlcurly:
-			braces++;
-			continue;
-
-		    case TOKrcurly:
-			if (--braces == 0)
-			    break;
-			continue;
-
-		    case TOKeof:
-			break;
-
-		    default:
-			continue;
-		}
-		break;
-	    }
-
-	    is = new StructInitializer(loc);
-	    nextToken();
-	    comma = 0;
-	    while (1)
-	    {
-		switch (token.value)
-		{
-		    case TOKidentifier:
-			if (comma == 1)
-			    error("comma expected separating field initializers");
-			t = peek(&token);
-			if (t->value == TOKcolon)
-			{
-			    id = token.ident;
-			    nextToken();
-			    nextToken();	// skip over ':'
-			}
-			else
-			{   id = NULL;
-			}
-			value = parseInitializer();
-			is->addInit(id, value);
-			comma = 1;
-			continue;
-
-		    case TOKcomma:
-			nextToken();
-			comma = 2;
-			continue;
-
-		    case TOKrcurly:		// allow trailing comma's
-			nextToken();
-			break;
-
-		    case TOKeof:
-			error("found EOF instead of initializer");
-			break;
-
-		    default:
-			value = parseInitializer();
-			is->addInit(NULL, value);
-			comma = 1;
-			continue;
-			//error("found '%s' instead of field initializer", token.toChars());
-			//break;
-		}
-		break;
-	    }
-	    return is;
-
-	case TOKlbracket:
-	    /* Scan ahead to see if it is an array initializer or
-	     * an expression.
-	     * If it ends with a ';', it is an array initializer.
-	     */
-	    brackets = 1;
-	    for (t = peek(&token); 1; t = peek(t))
-	    {
-		switch (t->value)
-		{
-		    case TOKlbracket:
-			brackets++;
-			continue;
-
-		    case TOKrbracket:
-			if (--brackets == 0)
-			{   t = peek(t);
-			    if (t->value != TOKsemicolon &&
-				t->value != TOKcomma &&
-				t->value != TOKrcurly)
-				goto Lexpression;
-			    break;
-			}
-			continue;
-
-		    case TOKeof:
-			break;
-
-		    default:
-			continue;
-		}
-		break;
-	    }
-
-	    ia = new ArrayInitializer(loc);
-	    nextToken();
-	    comma = 0;
-	    while (1)
-	    {
-		switch (token.value)
-		{
-		    default:
-			if (comma == 1)
-			{   error("comma expected separating array initializers, not %s", token.toChars());
-			    nextToken();
-			    break;
-			}
-			e = parseAssignExp();
-			if (!e)
-			    break;
-			if (token.value == TOKcolon)
-			{
-			    nextToken();
-			    value = parseInitializer();
-			}
-			else
-			{   value = new ExpInitializer(e->loc, e);
-			    e = NULL;
-			}
-			ia->addInit(e, value);
-			comma = 1;
-			continue;
-
-		    case TOKlcurly:
-		    case TOKlbracket:
-			if (comma == 1)
-			    error("comma expected separating array initializers, not %s", token.toChars());
-			value = parseInitializer();
-			ia->addInit(NULL, value);
-			comma = 1;
-			continue;
-
-		    case TOKcomma:
-			nextToken();
-			comma = 2;
-			continue;
-
-		    case TOKrbracket:		// allow trailing comma's
-			nextToken();
-			break;
-
-		    case TOKeof:
-			error("found '%s' instead of array initializer", token.toChars());
-			break;
-		}
-		break;
-	    }
-	    return ia;
-
-	case TOKvoid:
-	    t = peek(&token);
-	    if (t->value == TOKsemicolon || t->value == TOKcomma)
-	    {
-		nextToken();
-		return new VoidInitializer(loc);
-	    }
-	    goto Lexpression;
-
-	default:
-	Lexpression:
-	    e = parseAssignExp();
-	    ie = new ExpInitializer(loc, e);
-	    return ie;
-    }
-}
-
-/*****************************************
- * Parses default argument initializer expression that is an assign expression,
- * with special handling for __FILE__ and __LINE__.
- */
-
-#if DMDV2
-Expression *Parser::parseDefaultInitExp()
-{
-    if (token.value == TOKfile ||
-	token.value == TOKline)
-    {
-	Token *t = peek(&token);
-	if (t->value == TOKcomma || t->value == TOKrparen)
-	{   Expression *e;
-
-	    if (token.value == TOKfile)
-		e = new FileInitExp(loc);
-	    else
-		e = new LineInitExp(loc);
-	    nextToken();
-	    return e;
-	}
-    }
-
-    Expression *e = parseAssignExp();
-    return e;
-}
-#endif
-
-/*****************************************
- * Input:
- *	flags	PSxxxx
- */
-
-Statement *Parser::parseStatement(int flags)
-{   Statement *s;
-    Token *t;
-    Condition *condition;
-    Statement *ifbody;
-    Statement *elsebody;
-    Loc loc = this->loc;
-
-    //printf("parseStatement()\n");
-
-    if (flags & PScurly && token.value != TOKlcurly)
-	error("statement expected to be { }, not %s", token.toChars());
-
-    switch (token.value)
-    {
-	case TOKidentifier:
-	    /* A leading identifier can be a declaration, label, or expression.
-	     * The easiest case to check first is label:
-	     */
-	    t = peek(&token);
-	    if (t->value == TOKcolon)
-	    {	// It's a label
-
-		Identifier *ident = token.ident;
-		nextToken();
-		nextToken();
-		s = parseStatement(PSsemi);
-		s = new LabelStatement(loc, ident, s);
-		break;
-	    }
-	    // fallthrough to TOKdot
-	case TOKdot:
-	case TOKtypeof:
-	    if (isDeclaration(&token, 2, TOKreserved, NULL))
-		goto Ldeclaration;
-	    else
-		goto Lexp;
-	    break;
-
-	case TOKassert:
-	case TOKthis:
-	case TOKsuper:
-	case TOKint32v:
-	case TOKuns32v:
-	case TOKint64v:
-	case TOKuns64v:
-	case TOKfloat32v:
-	case TOKfloat64v:
-	case TOKfloat80v:
-	case TOKimaginary32v:
-	case TOKimaginary64v:
-	case TOKimaginary80v:
-	case TOKcharv:
-	case TOKwcharv:
-	case TOKdcharv:
-	case TOKnull:
-	case TOKtrue:
-	case TOKfalse:
-	case TOKstring:
-	case TOKlparen:
-	case TOKcast:
-	case TOKmul:
-	case TOKmin:
-	case TOKadd:
-	case TOKplusplus:
-	case TOKminusminus:
-	case TOKnew:
-	case TOKdelete:
-	case TOKdelegate:
-	case TOKfunction:
-	case TOKtypeid:
-	case TOKis:
-	case TOKlbracket:
-#if DMDV2
-	case TOKtraits:
-	case TOKfile:
-	case TOKline:
-#endif
-	Lexp:
-	{   Expression *exp;
-
-	    exp = parseExpression();
-	    check(TOKsemicolon, "statement");
-	    s = new ExpStatement(loc, exp);
-	    break;
-	}
-
-	case TOKstatic:
-	{   // Look ahead to see if it's static assert() or static if()
-	    Token *t;
-
-	    t = peek(&token);
-	    if (t->value == TOKassert)
-	    {
-		nextToken();
-		s = new StaticAssertStatement(parseStaticAssert());
-		break;
-	    }
-	    if (t->value == TOKif)
-	    {
-		nextToken();
-		condition = parseStaticIfCondition();
-		goto Lcondition;
-	    }
-	    goto Ldeclaration;
-	}
-
-	CASE_BASIC_TYPES:
-	case TOKtypedef:
-	case TOKalias:
-	case TOKconst:
-	case TOKauto:
-	case TOKextern:
-	case TOKfinal:
-	case TOKinvariant:
-#if DMDV2
-	case TOKimmutable:
-	case TOKshared:
-#endif
-//	case TOKtypeof:
-	Ldeclaration:
-	{   Array *a;
-
-	    a = parseDeclarations();
-	    if (a->dim > 1)
-	    {
-		Statements *as = new Statements();
-		as->reserve(a->dim);
-		for (int i = 0; i < a->dim; i++)
-		{
-		    Dsymbol *d = (Dsymbol *)a->data[i];
-		    s = new DeclarationStatement(loc, d);
-		    as->push(s);
-		}
-		s = new CompoundDeclarationStatement(loc, as);
-	    }
-	    else if (a->dim == 1)
-	    {
-		Dsymbol *d = (Dsymbol *)a->data[0];
-		s = new DeclarationStatement(loc, d);
-	    }
-	    else
-		assert(0);
-	    if (flags & PSscope)
-		s = new ScopeStatement(loc, s);
-	    break;
-	}
-
-	case TOKstruct:
-	case TOKunion:
-	case TOKclass:
-	case TOKinterface:
-	{   Dsymbol *d;
-
-	    d = parseAggregate();
-	    s = new DeclarationStatement(loc, d);
-	    break;
-	}
-
-	case TOKenum:
-	{   Dsymbol *d;
-
-	    d = parseEnum();
-	    s = new DeclarationStatement(loc, d);
-	    break;
-	}
-
-	case TOKmixin:
-	{   t = peek(&token);
-	    if (t->value == TOKlparen)
-	    {	// mixin(string)
-		nextToken();
-		check(TOKlparen, "mixin");
-		Expression *e = parseAssignExp();
-		check(TOKrparen);
-		check(TOKsemicolon);
-		s = new CompileStatement(loc, e);
-		break;
-	    }
-	    Dsymbol *d = parseMixin();
-	    s = new DeclarationStatement(loc, d);
-	    break;
-	}
-
-	case TOKlcurly:
-	{   Statements *statements;
-
-	    nextToken();
-	    statements = new Statements();
-	    while (token.value != TOKrcurly)
-	    {
-		statements->push(parseStatement(PSsemi | PScurlyscope));
-	    }
-	    endloc = this->loc;
-	    s = new CompoundStatement(loc, statements);
-	    if (flags & (PSscope | PScurlyscope))
-		s = new ScopeStatement(loc, s);
-	    nextToken();
-	    break;
-	}
-
-	case TOKwhile:
-	{   Expression *condition;
-	    Statement *body;
-
-	    nextToken();
-	    check(TOKlparen);
-	    condition = parseExpression();
-	    check(TOKrparen);
-	    body = parseStatement(PSscope);
-	    s = new WhileStatement(loc, condition, body);
-	    break;
-	}
-
-	case TOKsemicolon:
-	    if (!(flags & PSsemi))
-		error("use '{ }' for an empty statement, not a ';'");
-	    nextToken();
-	    s = new ExpStatement(loc, NULL);
-	    break;
-
-	case TOKdo:
-	{   Statement *body;
-	    Expression *condition;
-
-	    nextToken();
-	    body = parseStatement(PSscope);
-	    check(TOKwhile);
-	    check(TOKlparen);
-	    condition = parseExpression();
-	    check(TOKrparen);
-	    s = new DoStatement(loc, body, condition);
-	    break;
-	}
-
-	case TOKfor:
-	{
-	    Statement *init;
-	    Expression *condition;
-	    Expression *increment;
-	    Statement *body;
-
-	    nextToken();
-	    check(TOKlparen);
-	    if (token.value == TOKsemicolon)
-	    {	init = NULL;
-		nextToken();
-	    }
-	    else
-	    {	init = parseStatement(0);
-	    }
-	    if (token.value == TOKsemicolon)
-	    {
-		condition = NULL;
-		nextToken();
-	    }
-	    else
-	    {
-		condition = parseExpression();
-		check(TOKsemicolon, "for condition");
-	    }
-	    if (token.value == TOKrparen)
-	    {	increment = NULL;
-		nextToken();
-	    }
-	    else
-	    {	increment = parseExpression();
-		check(TOKrparen);
-	    }
-	    body = parseStatement(PSscope);
-	    s = new ForStatement(loc, init, condition, increment, body);
-	    if (init)
-		s = new ScopeStatement(loc, s);
-	    break;
-	}
-
-	case TOKforeach:
-	case TOKforeach_reverse:
-	{
-	    enum TOK op = token.value;
-	    Arguments *arguments;
-
-	    Statement *d;
-	    Statement *body;
-	    Expression *aggr;
-
-	    nextToken();
-	    check(TOKlparen);
-
-	    arguments = new Arguments();
-
-	    while (1)
-	    {
-		Type *tb;
-		Identifier *ai = NULL;
-		Type *at;
-		unsigned storageClass;
-		Argument *a;
-
-		storageClass = STCin;
-		if (token.value == TOKinout || token.value == TOKref)
-		{   storageClass = STCref;
-		    nextToken();
-		}
-		if (token.value == TOKidentifier)
-		{
-		    Token *t = peek(&token);
-		    if (t->value == TOKcomma || t->value == TOKsemicolon)
-		    {	ai = token.ident;
-			at = NULL;		// infer argument type
-			nextToken();
-			goto Larg;
-		    }
-		}
-		tb = parseBasicType();
-		at = parseDeclarator(tb, &ai);
-		if (!ai)
-		    error("no identifier for declarator %s", at->toChars());
-	      Larg:
-		a = new Argument(storageClass, at, ai, NULL);
-		arguments->push(a);
-		if (token.value == TOKcomma)
-		{   nextToken();
-		    continue;
-		}
-		break;
-	    }
-	    check(TOKsemicolon);
-
-	    aggr = parseExpression();
-	    check(TOKrparen);
-	    body = parseStatement(0);
-	    s = new ForeachStatement(loc, op, arguments, aggr, body);
-	    break;
-	}
-
-	case TOKif:
-	{   Argument *arg = NULL;
-	    Expression *condition;
-	    Statement *ifbody;
-	    Statement *elsebody;
-
-	    nextToken();
-	    check(TOKlparen);
-
-	    if (token.value == TOKauto)
-	    {
-		nextToken();
-		if (token.value == TOKidentifier)
-		{
-		    Token *t = peek(&token);
-		    if (t->value == TOKassign)
-		    {
-			arg = new Argument(STCin, NULL, token.ident, NULL);
-			nextToken();
-			nextToken();
-		    }
-		    else
-		    {   error("= expected following auto identifier");
-			goto Lerror;
-		    }
-		}
-		else
-		{   error("identifier expected following auto");
-		    goto Lerror;
-		}
-	    }
-	    else if (isDeclaration(&token, 2, TOKassign, NULL))
-	    {
-		Type *tb;
-		Type *at;
-		Identifier *ai;
-
-		tb = parseBasicType();
-		at = parseDeclarator(tb, &ai);
-		check(TOKassign);
-		arg = new Argument(STCin, at, ai, NULL);
-	    }
-
-	    // Check for " ident;"
-	    else if (token.value == TOKidentifier)
-	    {
-		Token *t = peek(&token);
-		if (t->value == TOKcomma || t->value == TOKsemicolon)
-		{
-		    arg = new Argument(STCin, NULL, token.ident, NULL);
-		    nextToken();
-		    nextToken();
-		    if (1 || !global.params.useDeprecated)
-			error("if (v; e) is deprecated, use if (auto v = e)");
-		}
-	    }
-
-	    condition = parseExpression();
-	    check(TOKrparen);
-	    ifbody = parseStatement(PSscope);
-	    if (token.value == TOKelse)
-	    {
-		nextToken();
-		elsebody = parseStatement(PSscope);
-	    }
-	    else
-		elsebody = NULL;
-	    s = new IfStatement(loc, arg, condition, ifbody, elsebody);
-	    break;
-	}
-
-	case TOKscope:
-	    if (peek(&token)->value != TOKlparen)
-		goto Ldeclaration;		// scope used as storage class
-	    nextToken();
-	    check(TOKlparen);
-	    if (token.value != TOKidentifier)
-	    {	error("scope identifier expected");
-		goto Lerror;
-	    }
-	    else
-	    {	TOK t = TOKon_scope_exit;
-		Identifier *id = token.ident;
-
-		if (id == Id::exit)
-		    t = TOKon_scope_exit;
-		else if (id == Id::failure)
-		    t = TOKon_scope_failure;
-		else if (id == Id::success)
-		    t = TOKon_scope_success;
-		else
-		    error("valid scope identifiers are exit, failure, or success, not %s", id->toChars());
-		nextToken();
-		check(TOKrparen);
-		Statement *st = parseStatement(PScurlyscope);
-		s = new OnScopeStatement(loc, t, st);
-		break;
-	    }
-
-	case TOKdebug:
-	    nextToken();
-	    condition = parseDebugCondition();
-	    goto Lcondition;
-
-	case TOKversion:
-	    nextToken();
-	    condition = parseVersionCondition();
-	    goto Lcondition;
-
-	Lcondition:
-	    ifbody = parseStatement(0 /*PSsemi*/);
-	    elsebody = NULL;
-	    if (token.value == TOKelse)
-	    {
-		nextToken();
-		elsebody = parseStatement(0 /*PSsemi*/);
-	    }
-	    s = new ConditionalStatement(loc, condition, ifbody, elsebody);
-	    break;
-
-	case TOKpragma:
-	{   Identifier *ident;
-	    Expressions *args = NULL;
-	    Statement *body;
-
-	    nextToken();
-	    check(TOKlparen);
-	    if (token.value != TOKidentifier)
-	    {   error("pragma(identifier expected");
-		goto Lerror;
-	    }
-	    ident = token.ident;
-	    nextToken();
-	    if (token.value == TOKcomma && peekNext() != TOKrparen)
-		args = parseArguments();	// pragma(identifier, args...);
-	    else
-		check(TOKrparen);		// pragma(identifier);
-	    if (token.value == TOKsemicolon)
-	    {	nextToken();
-		body = NULL;
-	    }
-	    else
-		body = parseStatement(PSsemi);
-	    s = new PragmaStatement(loc, ident, args, body);
-	    break;
-	}
-
-	case TOKswitch:
-	{   Expression *condition;
-	    Statement *body;
-
-	    nextToken();
-	    check(TOKlparen);
-	    condition = parseExpression();
-	    check(TOKrparen);
-	    body = parseStatement(PSscope);
-	    s = new SwitchStatement(loc, condition, body);
-	    break;
-	}
-
-	case TOKcase:
-	{   Expression *exp;
-	    Statements *statements;
-	    Array cases;	// array of Expression's
-
-	    while (1)
-	    {
-		nextToken();
-		exp = parseAssignExp();
-		cases.push(exp);
-		if (token.value != TOKcomma)
-		    break;
-	    }
-	    check(TOKcolon);
-
-	    statements = new Statements();
-	    while (token.value != TOKcase &&
-		   token.value != TOKdefault &&
-		   token.value != TOKrcurly)
-	    {
-		statements->push(parseStatement(PSsemi | PScurlyscope));
-	    }
-	    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--)
-	    {
-		exp = (Expression *)cases.data[i - 1];
-		s = new CaseStatement(loc, exp, s);
-	    }
-	    break;
-	}
-
-	case TOKdefault:
-	{
-	    Statements *statements;
-
-	    nextToken();
-	    check(TOKcolon);
-
-	    statements = new Statements();
-	    while (token.value != TOKcase &&
-		   token.value != TOKdefault &&
-		   token.value != TOKrcurly)
-	    {
-		statements->push(parseStatement(PSsemi | PScurlyscope));
-	    }
-	    s = new CompoundStatement(loc, statements);
-	    s = new ScopeStatement(loc, s);
-	    s = new DefaultStatement(loc, s);
-	    break;
-	}
-
-	case TOKreturn:
-	{   Expression *exp;
-
-	    nextToken();
-	    if (token.value == TOKsemicolon)
-		exp = NULL;
-	    else
-		exp = parseExpression();
-	    check(TOKsemicolon, "return statement");
-	    s = new ReturnStatement(loc, exp);
-	    break;
-	}
-
-	case TOKbreak:
-	{   Identifier *ident;
-
-	    nextToken();
-	    if (token.value == TOKidentifier)
-	    {	ident = token.ident;
-		nextToken();
-	    }
-	    else
-		ident = NULL;
-	    check(TOKsemicolon, "break statement");
-	    s = new BreakStatement(loc, ident);
-	    break;
-	}
-
-	case TOKcontinue:
-	{   Identifier *ident;
-
-	    nextToken();
-	    if (token.value == TOKidentifier)
-	    {	ident = token.ident;
-		nextToken();
-	    }
-	    else
-		ident = NULL;
-	    check(TOKsemicolon, "continue statement");
-	    s = new ContinueStatement(loc, ident);
-	    break;
-	}
-
-	case TOKgoto:
-	{   Identifier *ident;
-
-	    nextToken();
-	    if (token.value == TOKdefault)
-	    {
-		nextToken();
-		s = new GotoDefaultStatement(loc);
-	    }
-	    else if (token.value == TOKcase)
-	    {
-		Expression *exp = NULL;
-
-		nextToken();
-		if (token.value != TOKsemicolon)
-		    exp = parseExpression();
-		s = new GotoCaseStatement(loc, exp);
-	    }
-	    else
-	    {
-		if (token.value != TOKidentifier)
-		{   error("Identifier expected following goto");
-		    ident = NULL;
-		}
-		else
-		{   ident = token.ident;
-		    nextToken();
-		}
-		s = new GotoStatement(loc, ident);
-	    }
-	    check(TOKsemicolon, "goto statement");
-	    break;
-	}
-
-	case TOKsynchronized:
-	{   Expression *exp;
-	    Statement *body;
-
-	    nextToken();
-	    if (token.value == TOKlparen)
-	    {
-		nextToken();
-		exp = parseExpression();
-		check(TOKrparen);
-	    }
-	    else
-		exp = NULL;
-	    body = parseStatement(PSscope);
-	    s = new SynchronizedStatement(loc, exp, body);
-	    break;
-	}
-
-	case TOKwith:
-	{   Expression *exp;
-	    Statement *body;
-
-	    nextToken();
-	    check(TOKlparen);
-	    exp = parseExpression();
-	    check(TOKrparen);
-	    body = parseStatement(PSscope);
-	    s = new WithStatement(loc, exp, body);
-	    break;
-	}
-
-	case TOKtry:
-	{   Statement *body;
-	    Array *catches = NULL;
-	    Statement *finalbody = NULL;
-
-	    nextToken();
-	    body = parseStatement(PSscope);
-	    while (token.value == TOKcatch)
-	    {
-		Statement *handler;
-		Catch *c;
-		Type *t;
-		Identifier *id;
-		Loc loc = this->loc;
-
-		nextToken();
-		if (token.value == TOKlcurly)
-		{
-		    t = NULL;
-		    id = NULL;
-		}
-		else
-		{
-		    check(TOKlparen);
-		    t = parseBasicType();
-		    id = NULL;
-		    t = parseDeclarator(t, &id);
-		    check(TOKrparen);
-		}
-		handler = parseStatement(0);
-		c = new Catch(loc, t, id, handler);
-		if (!catches)
-		    catches = new Array();
-		catches->push(c);
-	    }
-
-	    if (token.value == TOKfinally)
-	    {	nextToken();
-		finalbody = parseStatement(0);
-	    }
-
-	    s = body;
-	    if (!catches && !finalbody)
-		error("catch or finally expected following try");
-	    else
-	    {	if (catches)
-		    s = new TryCatchStatement(loc, body, catches);
-		if (finalbody)
-		    s = new TryFinallyStatement(loc, s, finalbody);
-	    }
-	    break;
-	}
-
-	case TOKthrow:
-	{   Expression *exp;
-
-	    nextToken();
-	    exp = parseExpression();
-	    check(TOKsemicolon, "throw statement");
-	    s = new ThrowStatement(loc, exp);
-	    break;
-	}
-
-	case TOKvolatile:
-	    nextToken();
-	    s = parseStatement(PSsemi | PScurlyscope);
-#if DMDV2
-	    if (!global.params.useDeprecated)
-		error("volatile statements deprecated; used synchronized statements instead");
-#endif
-	    s = new VolatileStatement(loc, s);
-	    break;
-
-	case TOKasm:
-	{   Statements *statements;
-	    Identifier *label;
-	    Loc labelloc;
-	    Token *toklist;
-	    Token **ptoklist;
-
-	    // Parse the asm block into a sequence of AsmStatements,
-	    // each AsmStatement is one instruction.
-	    // Separate out labels.
-	    // Defer parsing of AsmStatements until semantic processing.
-
-	    nextToken();
-	    check(TOKlcurly);
-	    toklist = NULL;
-	    ptoklist = &toklist;
-	    label = NULL;
-	    statements = new Statements();
-	    while (1)
-	    {
-		switch (token.value)
-		{
-		    case TOKidentifier:
-			if (!toklist)
-			{
-			    // Look ahead to see if it is a label
-			    t = peek(&token);
-			    if (t->value == TOKcolon)
-			    {   // It's a label
-				label = token.ident;
-				labelloc = this->loc;
-				nextToken();
-				nextToken();
-				continue;
-			    }
-			}
-			goto Ldefault;
-
-		    case TOKrcurly:
-			if (toklist || label)
-			{
-			    error("asm statements must end in ';'");
-			}
-			break;
-
-		    case TOKsemicolon:
-			s = NULL;
-			if (toklist || label)
-			{   // Create AsmStatement from list of tokens we've saved
-			    s = new AsmStatement(this->loc, toklist);
-			    toklist = NULL;
-			    ptoklist = &toklist;
-			    if (label)
-			    {   s = new LabelStatement(labelloc, label, s);
-				label = NULL;
-			    }
-			    statements->push(s);
-			}
-			nextToken();
-			continue;
-
-		    case TOKeof:
-			/* { */
-			error("matching '}' expected, not end of file");
-			break;
-
-		    default:
-		    Ldefault:
-			*ptoklist = new Token();
-			memcpy(*ptoklist, &token, sizeof(Token));
-			ptoklist = &(*ptoklist)->next;
-			*ptoklist = NULL;
-
-			nextToken();
-			continue;
-		}
-		break;
-	    }
-        s = new AsmBlockStatement(loc, statements);
-	    nextToken();
-	    break;
-	}
-
-	default:
-	    error("found '%s' instead of statement", token.toChars());
-	    goto Lerror;
-
-	Lerror:
-	    while (token.value != TOKrcurly &&
-		   token.value != TOKsemicolon &&
-		   token.value != TOKeof)
-		nextToken();
-	    if (token.value == TOKsemicolon)
-		nextToken();
-	    s = NULL;
-	    break;
-    }
-
-    return s;
-}
-
-void Parser::check(enum TOK value)
-{
-    check(loc, value);
-}
-
-void Parser::check(Loc loc, enum TOK value)
-{
-    if (token.value != value)
-	error(loc, "found '%s' when expecting '%s'", token.toChars(), Token::toChars(value));
-    nextToken();
-}
-
-void Parser::check(enum TOK value, const char *string)
-{
-    if (token.value != value)
-	error("found '%s' when expecting '%s' following '%s'",
-	    token.toChars(), Token::toChars(value), string);
-    nextToken();
-}
-
-/************************************
- * Determine if the scanner is sitting on the start of a declaration.
- * Input:
- *	needId	0	no identifier
- *		1	identifier optional
- *		2	must have identifier
- */
-
-int Parser::isDeclaration(Token *t, int needId, enum TOK endtok, Token **pt)
-{
-    //printf("isDeclaration(needId = %d)\n", needId);
-    int haveId = 0;
-
-#if DMDV2
-    if ((t->value == TOKconst || t->value == TOKinvariant) &&
-	peek(t)->value != TOKlparen)
-    {	/* const type
-	 * invariant type
-	 */
-	t = peek(t);
-    }
-#endif
-
-    if (!isBasicType(&t))
-	return FALSE;
-    if (!isDeclarator(&t, &haveId, endtok))
-	return FALSE;
-    if ( needId == 1 ||
-	(needId == 0 && !haveId) ||
-	(needId == 2 &&  haveId))
-    {	if (pt)
-	    *pt = t;
-	return TRUE;
-    }
-    else
-	return FALSE;
-}
-
-int Parser::isBasicType(Token **pt)
-{
-    // This code parallels parseBasicType()
-    Token *t = *pt;
-    Token *t2;
-    int parens;
-
-    switch (t->value)
-    {
-	CASE_BASIC_TYPES:
-	    t = peek(t);
-	    break;
-
-	case TOKidentifier:
-	    t = peek(t);
-	    if (t->value == TOKnot)
-	    {
-		goto L4;
-	    }
-	    goto L3;
-	    while (1)
-	    {
-	L2:
-		t = peek(t);
-	L3:
-		if (t->value == TOKdot)
-		{
-	Ldot:
-		    t = peek(t);
-		    if (t->value != TOKidentifier)
-			goto Lfalse;
-		    t = peek(t);
-		    if (t->value != TOKnot)
-			goto L3;
-	L4:
-		    t = peek(t);
-		    if (t->value != TOKlparen)
-			goto Lfalse;
-		    if (!skipParens(t, &t))
-			goto Lfalse;
-		}
-		else
-		    break;
-	    }
-	    break;
-
-	case TOKdot:
-	    goto Ldot;
-
-	case TOKtypeof:
-	    /* typeof(exp).identifier...
-	     */
-	    t = peek(t);
-	    if (t->value != TOKlparen)
-		goto Lfalse;
-	    if (!skipParens(t, &t))
-		goto Lfalse;
-	    goto L2;
-
-	default:
-	    goto Lfalse;
-    }
-    *pt = t;
-    //printf("is\n");
-    return TRUE;
-
-Lfalse:
-    //printf("is not\n");
-    return FALSE;
-}
-
-int Parser::isDeclarator(Token **pt, int *haveId, enum TOK endtok)
-{   // This code parallels parseDeclarator()
-    Token *t = *pt;
-    int parens;
-
-    //printf("Parser::isDeclarator()\n");
-    //t->print();
-    if (t->value == TOKassign)
-	return FALSE;
-
-    while (1)
-    {
-	parens = FALSE;
-	switch (t->value)
-	{
-	    case TOKmul:
-	    //case TOKand:
-		t = peek(t);
-		continue;
-
-	    case TOKlbracket:
-		t = peek(t);
-		if (t->value == TOKrbracket)
-		{
-		    t = peek(t);
-		}
-		else if (isDeclaration(t, 0, TOKrbracket, &t))
-		{   // It's an associative array declaration
-		    t = peek(t);
-		}
-		else
-		{
-		    // [ expression ]
-		    // [ expression .. expression ]
-		    if (!isExpression(&t))
-			return FALSE;
-		    if (t->value == TOKslice)
-		    {	t = peek(t);
-			if (!isExpression(&t))
-			    return FALSE;
-		    }
-		    if (t->value != TOKrbracket)
-			return FALSE;
-		    t = peek(t);
-		}
-		continue;
-
-	    case TOKidentifier:
-		if (*haveId)
-		    return FALSE;
-		*haveId = TRUE;
-		t = peek(t);
-		break;
-
-	    case TOKlparen:
-		t = peek(t);
-
-		if (t->value == TOKrparen)
-		    return FALSE;		// () is not a declarator
-
-		/* Regard ( identifier ) as not a declarator
-		 * BUG: what about ( *identifier ) in
-		 *	f(*p)(x);
-		 * where f is a class instance with overloaded () ?
-		 * Should we just disallow C-style function pointer declarations?
-		 */
-		if (t->value == TOKidentifier)
-		{   Token *t2 = peek(t);
-		    if (t2->value == TOKrparen)
-			return FALSE;
-		}
-
-
-		if (!isDeclarator(&t, haveId, TOKrparen))
-		    return FALSE;
-		t = peek(t);
-		parens = TRUE;
-		break;
-
-	    case TOKdelegate:
-	    case TOKfunction:
-		t = peek(t);
-		if (!isParameters(&t))
-		    return FALSE;
-		continue;
-	}
-	break;
-    }
-
-    while (1)
-    {
-	switch (t->value)
-	{
-#if CARRAYDECL
-	    case TOKlbracket:
-		parens = FALSE;
-		t = peek(t);
-		if (t->value == TOKrbracket)
-		{
-		    t = peek(t);
-		}
-		else if (isDeclaration(t, 0, TOKrbracket, &t))
-		{   // It's an associative array declaration
-		    t = peek(t);
-		}
-		else
-		{
-		    // [ expression ]
-		    if (!isExpression(&t))
-			return FALSE;
-		    if (t->value != TOKrbracket)
-			return FALSE;
-		    t = peek(t);
-		}
-		continue;
-#endif
-
-	    case TOKlparen:
-		parens = FALSE;
-		if (!isParameters(&t))
-		    return FALSE;
-#if DMDV2
-		while (1)
-		{
-		    switch (t->value)
-		    {
-			case TOKconst:
-			case TOKinvariant:
-			case TOKimmutable:
-			case TOKshared:
-			case TOKpure:
-			case TOKnothrow:
-			    t = peek(t);
-			    continue;
-			default:
-			    break;
-		    }
-		    break;
-		}
-#endif
-		continue;
-
-	    // Valid tokens that follow a declaration
-	    case TOKrparen:
-	    case TOKrbracket:
-	    case TOKassign:
-	    case TOKcomma:
-	    case TOKsemicolon:
-	    case TOKlcurly:
-	    case TOKin:
-		// The !parens is to disallow unnecessary parentheses
-		if (!parens && (endtok == TOKreserved || endtok == t->value))
-		{   *pt = t;
-		    return TRUE;
-		}
-		return FALSE;
-
-	    default:
-		return FALSE;
-	}
-    }
-}
-
-
-int Parser::isParameters(Token **pt)
-{   // This code parallels parseParameters()
-    Token *t = *pt;
-    int tmp;
-
-    //printf("isParameters()\n");
-    if (t->value != TOKlparen)
-	return FALSE;
-
-    t = peek(t);
-    while (1)
-    {
-	switch (t->value)
-	{
-	    case TOKrparen:
-		break;
-
-	    case TOKdotdotdot:
-		t = peek(t);
-		break;
-
-	    case TOKin:
-	    case TOKout:
-	    case TOKinout:
-	    case TOKref:
-	    case TOKlazy:
-		t = peek(t);
-	    default:
-		if (!isBasicType(&t))
-		    return FALSE;
-		tmp = FALSE;
-		if (t->value != TOKdotdotdot &&
-		    !isDeclarator(&t, &tmp, TOKreserved))
-		    return FALSE;
-		if (t->value == TOKassign)
-		{   t = peek(t);
-		    if (!isExpression(&t))
-			return FALSE;
-		}
-		if (t->value == TOKdotdotdot)
-		{
-		    t = peek(t);
-		    break;
-		}
-		if (t->value == TOKcomma)
-		{   t = peek(t);
-		    continue;
-		}
-		break;
-	}
-	break;
-    }
-    if (t->value != TOKrparen)
-	return FALSE;
-    t = peek(t);
-    *pt = t;
-    return TRUE;
-}
-
-int Parser::isExpression(Token **pt)
-{
-    // This is supposed to determine if something is an expression.
-    // What it actually does is scan until a closing right bracket
-    // is found.
-
-    Token *t = *pt;
-    int brnest = 0;
-    int panest = 0;
-
-    for (;; t = peek(t))
-    {
-	switch (t->value)
-	{
-	    case TOKlbracket:
-		brnest++;
-		continue;
-
-	    case TOKrbracket:
-		if (--brnest >= 0)
-		    continue;
-		break;
-
-	    case TOKlparen:
-		panest++;
-		continue;
-
-	    case TOKcomma:
-		if (brnest || panest)
-		    continue;
-		break;
-
-	    case TOKrparen:
-		if (--panest >= 0)
-		    continue;
-		break;
-
-	    case TOKslice:
-		if (brnest)
-		    continue;
-		break;
-
-	    case TOKeof:
-		return FALSE;
-
-	    default:
-		continue;
-	}
-	break;
-    }
-
-    *pt = t;
-    return TRUE;
-}
-
-/**********************************************
- * Skip over
- *	instance foo.bar(parameters...)
- * Output:
- *	if (pt), *pt is set to the token following the closing )
- * Returns:
- *	1	it's valid instance syntax
- *	0	invalid instance syntax
- */
-
-int Parser::isTemplateInstance(Token *t, Token **pt)
-{
-    t = peek(t);
-    if (t->value != TOKdot)
-    {
-	if (t->value != TOKidentifier)
-	    goto Lfalse;
-	t = peek(t);
-    }
-    while (t->value == TOKdot)
-    {
-	t = peek(t);
-	if (t->value != TOKidentifier)
-	    goto Lfalse;
-	t = peek(t);
-    }
-    if (t->value != TOKlparen)
-	goto Lfalse;
-
-    // Skip over the template arguments
-    while (1)
-    {
-	while (1)
-	{
-	    t = peek(t);
-	    switch (t->value)
-	    {
-		case TOKlparen:
-		    if (!skipParens(t, &t))
-			goto Lfalse;
-		    continue;
-		case TOKrparen:
-		    break;
-		case TOKcomma:
-		    break;
-		case TOKeof:
-		case TOKsemicolon:
-		    goto Lfalse;
-		default:
-		    continue;
-	    }
-	    break;
-	}
-
-	if (t->value != TOKcomma)
-	    break;
-    }
-    if (t->value != TOKrparen)
-	goto Lfalse;
-    t = peek(t);
-    if (pt)
-	*pt = t;
-    return 1;
-
-Lfalse:
-    return 0;
-}
-
-/*******************************************
- * Skip parens, brackets.
- * Input:
- *	t is on opening (
- * Output:
- *	*pt is set to closing token, which is ')' on success
- * Returns:
- *	!=0	successful
- *	0	some parsing error
- */
-
-int Parser::skipParens(Token *t, Token **pt)
-{
-    int parens = 0;
-
-    while (1)
-    {
-	switch (t->value)
-	{
-	    case TOKlparen:
-		parens++;
-		break;
-
-	    case TOKrparen:
-		parens--;
-		if (parens < 0)
-		    goto Lfalse;
-		if (parens == 0)
-		    goto Ldone;
-		break;
-
-	    case TOKeof:
-	    case TOKsemicolon:
-		goto Lfalse;
-
-	     default:
-		break;
-	}
-	t = peek(t);
-    }
-
-  Ldone:
-    if (*pt)
-	*pt = t;
-    return 1;
-
-  Lfalse:
-    return 0;
-}
-
-/********************************* Expression Parser ***************************/
-
-Expression *Parser::parsePrimaryExp()
-{   Expression *e;
-    Type *t;
-    Identifier *id;
-    enum TOK save;
-    Loc loc = this->loc;
-
-    //printf("parsePrimaryExp(): loc = %d\n", loc.linnum);
-    switch (token.value)
-    {
-	case TOKidentifier:
-	    id = token.ident;
-	    nextToken();
-	    if (token.value == TOKnot && peek(&token)->value == TOKlparen)
-	    {	// identifier!(template-argument-list)
-		TemplateInstance *tempinst;
-
-		tempinst = new TemplateInstance(loc, id);
-		nextToken();
-		tempinst->tiargs = parseTemplateArgumentList();
-		e = new ScopeExp(loc, tempinst);
-	    }
-	    else
-		e = new IdentifierExp(loc, id);
-	    break;
-
-	case TOKdollar:
-	    if (!inBrackets)
-		error("'$' is valid only inside [] of index or slice");
-	    e = new DollarExp(loc);
-	    nextToken();
-	    break;
-
-	case TOKdot:
-	    // Signal global scope '.' operator with "" identifier
-	    e = new IdentifierExp(loc, Id::empty);
-	    break;
-
-	case TOKthis:
-	    e = new ThisExp(loc);
-	    nextToken();
-	    break;
-
-	case TOKsuper:
-	    e = new SuperExp(loc);
-	    nextToken();
-	    break;
-
-	case TOKint32v:
-	    e = new IntegerExp(loc, (d_int32)token.int64value, Type::tint32);
-	    nextToken();
-	    break;
-
-	case TOKuns32v:
-	    e = new IntegerExp(loc, (d_uns32)token.uns64value, Type::tuns32);
-	    nextToken();
-	    break;
-
-	case TOKint64v:
-	    e = new IntegerExp(loc, token.int64value, Type::tint64);
-	    nextToken();
-	    break;
-
-	case TOKuns64v:
-	    e = new IntegerExp(loc, token.uns64value, Type::tuns64);
-	    nextToken();
-	    break;
-
-	case TOKfloat32v:
-	    e = new RealExp(loc, token.float80value, Type::tfloat32);
-	    nextToken();
-	    break;
-
-	case TOKfloat64v:
-	    e = new RealExp(loc, token.float80value, Type::tfloat64);
-	    nextToken();
-	    break;
-
-	case TOKfloat80v:
-	    e = new RealExp(loc, token.float80value, Type::tfloat80);
-	    nextToken();
-	    break;
-
-	case TOKimaginary32v:
-	    e = new RealExp(loc, token.float80value, Type::timaginary32);
-	    nextToken();
-	    break;
-
-	case TOKimaginary64v:
-	    e = new RealExp(loc, token.float80value, Type::timaginary64);
-	    nextToken();
-	    break;
-
-	case TOKimaginary80v:
-	    e = new RealExp(loc, token.float80value, Type::timaginary80);
-	    nextToken();
-	    break;
-
-	case TOKnull:
-	    e = new NullExp(loc);
-	    nextToken();
-	    break;
-
-#if DMDV2
-	case TOKfile:
-	{   char *s = loc.filename ? loc.filename : mod->ident->toChars();
-	    e = new StringExp(loc, s, strlen(s), 0);
-	    nextToken();
-	    break;
-	}
-
-	case TOKline:
-	    e = new IntegerExp(loc, loc.linnum, Type::tint32);
-	    nextToken();
-	    break;
-#endif
-
-	case TOKtrue:
-	    e = new IntegerExp(loc, 1, Type::tbool);
-	    nextToken();
-	    break;
-
-	case TOKfalse:
-	    e = new IntegerExp(loc, 0, Type::tbool);
-	    nextToken();
-	    break;
-
-	case TOKcharv:
-	    e = new IntegerExp(loc, (d_uns8)token.uns64value, Type::tchar);
-	    nextToken();
-	    break;
-
-	case TOKwcharv:
-	    e = new IntegerExp(loc, (d_uns16)token.uns64value, Type::twchar);
-	    nextToken();
-	    break;
-
-	case TOKdcharv:
-	    e = new IntegerExp(loc, (d_uns32)token.uns64value, Type::tdchar);
-	    nextToken();
-	    break;
-
-	case TOKstring:
-	{   unsigned char *s;
-	    unsigned len;
-	    unsigned char postfix;
-
-	    // cat adjacent strings
-	    s = token.ustring;
-	    len = token.len;
-	    postfix = token.postfix;
-	    while (1)
-	    {
-		nextToken();
-		if (token.value == TOKstring)
-		{   unsigned len1;
-		    unsigned len2;
-		    unsigned char *s2;
-
-		    if (token.postfix)
-		    {	if (token.postfix != postfix)
-			    error("mismatched string literal postfixes '%c' and '%c'", postfix, token.postfix);
-			postfix = token.postfix;
-		    }
-
-		    len1 = len;
-		    len2 = token.len;
-		    len = len1 + len2;
-		    s2 = (unsigned char *)mem.malloc((len + 1) * sizeof(unsigned char));
-		    memcpy(s2, s, len1 * sizeof(unsigned char));
-		    memcpy(s2 + len1, token.ustring, (len2 + 1) * sizeof(unsigned char));
-		    s = s2;
-		}
-		else
-		    break;
-	    }
-	    e = new StringExp(loc, s, len, postfix);
-	    break;
-	}
-
-	CASE_BASIC_TYPES_X(t):
-	    nextToken();
-	L1:
-	    check(TOKdot, t->toChars());
-	    if (token.value != TOKidentifier)
-	    {   error("found '%s' when expecting identifier following '%s.'", token.toChars(), t->toChars());
-		goto Lerr;
-	    }
-	    e = typeDotIdExp(loc, t, token.ident);
-	    nextToken();
-	    break;
-
-	case TOKtypeof:
-	{   Expression *exp;
-
-	    nextToken();
-	    check(TOKlparen);
-	    exp = parseExpression();
-	    check(TOKrparen);
-	    t = new TypeTypeof(loc, exp);
-	    e = new TypeExp(loc, t);
-	    break;
-	}
-
-	case TOKtypeid:
-	{   Type *t;
-
-	    nextToken();
-	    check(TOKlparen, "typeid");
-	    t = parseBasicType();
-	    t = parseDeclarator(t,NULL);	// ( type )
-	    check(TOKrparen);
-	    e = new TypeidExp(loc, t);
-	    break;
-	}
-
-#if DMDV2
-	case TOKtraits:
-	{   /* __traits(identifier, args...)
-	     */
-	    Identifier *ident;
-	    Objects *args = NULL;
-
-	    nextToken();
-	    check(TOKlparen);
-	    if (token.value != TOKidentifier)
-	    {   error("__traits(identifier, args...) expected");
-		goto Lerr;
-	    }
-	    ident = token.ident;
-	    nextToken();
-	    if (token.value == TOKcomma)
-		args = parseTemplateArgumentList2();	// __traits(identifier, args...)
-	    else
-		check(TOKrparen);		// __traits(identifier)
-
-	    e = new TraitsExp(loc, ident, args);
-	    break;
-	}
-#endif
-
-	case TOKis:
-	{   Type *targ;
-	    Identifier *ident = NULL;
-	    Type *tspec = NULL;
-	    enum TOK tok = TOKreserved;
-	    enum TOK tok2 = TOKreserved;
-	    Loc loc = this->loc;
-
-	    nextToken();
-	    if (token.value == TOKlparen)
-	    {
-		nextToken();
-		targ = parseBasicType();
-		targ = parseDeclarator(targ, &ident);
-		if (token.value == TOKcolon || token.value == TOKequal)
-		{
-		    tok = token.value;
-		    nextToken();
-		    if (tok == TOKequal &&
-			(token.value == TOKtypedef ||
-			 token.value == TOKstruct ||
-			 token.value == TOKunion ||
-			 token.value == TOKclass ||
-			 token.value == TOKsuper ||
-			 token.value == TOKenum ||
-			 token.value == TOKinterface ||
-#if DMDV2
-			 token.value == TOKconst && peek(&token)->value == TOKrparen ||
-			 token.value == TOKinvariant && peek(&token)->value == TOKrparen ||
-			 token.value == TOKimmutable && peek(&token)->value == TOKrparen ||
-			 token.value == TOKshared && peek(&token)->value == TOKrparen ||
-#endif
-			 token.value == TOKfunction ||
-			 token.value == TOKdelegate ||
-			 token.value == TOKreturn))
-		    {
-			tok2 = token.value;
-			nextToken();
-		    }
-		    else
-		    {
-			tspec = parseBasicType();
-			tspec = parseDeclarator(tspec, NULL);
-		    }
-		}
-		check(TOKrparen);
-	    }
-	    else
-	    {   error("(type identifier : specialization) expected following is");
-		goto Lerr;
-	    }
-	    e = new IsExp(loc, targ, ident, tok, tspec, tok2);
-	    break;
-	}
-
-	case TOKassert:
-	{   Expression *msg = NULL;
-
-	    nextToken();
-	    check(TOKlparen, "assert");
-	    e = parseAssignExp();
-	    if (token.value == TOKcomma)
-	    {	nextToken();
-		msg = parseAssignExp();
-	    }
-	    check(TOKrparen);
-	    e = new AssertExp(loc, e, msg);
-	    break;
-	}
-
-	case TOKmixin:
-	{
-	    nextToken();
-	    check(TOKlparen, "mixin");
-	    e = parseAssignExp();
-	    check(TOKrparen);
-	    e = new CompileExp(loc, e);
-	    break;
-	}
-
-	case TOKimport:
-	{
-	    nextToken();
-	    check(TOKlparen, "import");
-	    e = parseAssignExp();
-	    check(TOKrparen);
-	    e = new FileExp(loc, e);
-	    break;
-	}
-
-	case TOKlparen:
-	    if (peekPastParen(&token)->value == TOKlcurly)
-	    {	// (arguments) { statements... }
-		save = TOKdelegate;
-		goto case_delegate;
-	    }
-	    // ( expression )
-	    nextToken();
-	    e = parseExpression();
-	    check(loc, TOKrparen);
-	    break;
-
-	case TOKlbracket:
-	{   /* Parse array literals and associative array literals:
-	     *	[ value, value, value ... ]
-	     *	[ key:value, key:value, key:value ... ]
-	     */
-	    Expressions *values = new Expressions();
-	    Expressions *keys = NULL;
-
-	    nextToken();
-	    if (token.value != TOKrbracket)
-	    {
-		while (token.value != TOKeof)
-		{
-		    Expression *e = parseAssignExp();
-		    if (token.value == TOKcolon && (keys || values->dim == 0))
-		    {	nextToken();
-			if (!keys)
-			    keys = new Expressions();
-			keys->push(e);
-			e = parseAssignExp();
-		    }
-		    else if (keys)
-		    {	error("'key:value' expected for associative array literal");
-			delete keys;
-			keys = NULL;
-		    }
-		    values->push(e);
-		    if (token.value == TOKrbracket)
-			break;
-		    check(TOKcomma);
-		}
-	    }
-	    check(TOKrbracket);
-
-	    if (keys)
-		e = new AssocArrayLiteralExp(loc, keys, values);
-	    else
-		e = new ArrayLiteralExp(loc, values);
-	    break;
-	}
-
-	case TOKlcurly:
-	    // { statements... }
-	    save = TOKdelegate;
-	    goto case_delegate;
-
-	case TOKfunction:
-	case TOKdelegate:
-	    save = token.value;
-	    nextToken();
-	case_delegate:
-	{
-	    /* function type(parameters) { body }
-	     * delegate type(parameters) { body }
-	     */
-	    Arguments *arguments;
-	    int varargs;
-	    FuncLiteralDeclaration *fd;
-	    Type *t;
-
-	    if (token.value == TOKlcurly)
-	    {
-		t = NULL;
-		varargs = 0;
-		arguments = new Arguments();
-	    }
-	    else
-	    {
-		if (token.value == TOKlparen)
-		    t = NULL;
-		else
-		{
-		    t = parseBasicType();
-		    t = parseBasicType2(t);	// function return type
-		}
-		arguments = parseParameters(&varargs);
-	    }
-	    t = new TypeFunction(arguments, t, varargs, linkage);
-	    fd = new FuncLiteralDeclaration(loc, 0, t, save, NULL);
-	    parseContracts(fd);
-	    e = new FuncExp(loc, fd);
-	    break;
-	}
-
-	default:
-	    error("expression expected, not '%s'", token.toChars());
-	Lerr:
-	    // Anything for e, as long as it's not NULL
-	    e = new IntegerExp(loc, 0, Type::tint32);
-	    nextToken();
-	    break;
-    }
-    return parsePostExp(e);
-}
-
-Expression *Parser::parsePostExp(Expression *e)
-{
-    Loc loc;
-
-    while (1)
-    {
-	loc = this->loc;
-	switch (token.value)
-	{
-	    case TOKdot:
-		nextToken();
-		if (token.value == TOKidentifier)
-		{   Identifier *id = token.ident;
-
-		    nextToken();
-		    if (token.value == TOKnot && peek(&token)->value == TOKlparen)
-		    {   // identifier!(template-argument-list)
-			TemplateInstance *tempinst;
-
-			tempinst = new TemplateInstance(loc, id);
-			nextToken();
-			tempinst->tiargs = parseTemplateArgumentList();
-			e = new DotTemplateInstanceExp(loc, e, tempinst);
-		    }
-		    else
-			e = new DotIdExp(loc, e, id);
-		    continue;
-		}
-		else if (token.value == TOKnew)
-		{
-		    e = parseNewExp(e);
-		    continue;
-		}
-		else
-		    error("identifier expected following '.', not '%s'", token.toChars());
-		break;
-
-	    case TOKplusplus:
-		e = new PostExp(TOKplusplus, loc, e);
-		break;
-
-	    case TOKminusminus:
-		e = new PostExp(TOKminusminus, loc, e);
-		break;
-
-	    case TOKlparen:
-		e = new CallExp(loc, e, parseArguments());
-		continue;
-
-	    case TOKlbracket:
-	    {	// array dereferences:
-		//	array[index]
-		//	array[]
-		//	array[lwr .. upr]
-		Expression *index;
-		Expression *upr;
-
-		inBrackets++;
-		nextToken();
-		if (token.value == TOKrbracket)
-		{   // array[]
-		    e = new SliceExp(loc, e, NULL, NULL);
-		    nextToken();
-		}
-		else
-		{
-		    index = parseAssignExp();
-		    if (token.value == TOKslice)
-		    {	// array[lwr .. upr]
-			nextToken();
-			upr = parseAssignExp();
-			e = new SliceExp(loc, e, index, upr);
-		    }
-		    else
-		    {	// array[index, i2, i3, i4, ...]
-			Expressions *arguments = new Expressions();
-			arguments->push(index);
-			if (token.value == TOKcomma)
-			{
-			    nextToken();
-			    while (1)
-			    {   Expression *arg;
-
-				arg = parseAssignExp();
-				arguments->push(arg);
-				if (token.value == TOKrbracket)
-				    break;
-				check(TOKcomma);
-			    }
-			}
-			e = new ArrayExp(loc, e, arguments);
-		    }
-		    check(TOKrbracket);
-		    inBrackets--;
-		}
-		continue;
-	    }
-
-	    default:
-		return e;
-	}
-	nextToken();
-    }
-}
-
-Expression *Parser::parseUnaryExp()
-{   Expression *e;
-    Loc loc = this->loc;
-
-    switch (token.value)
-    {
-	case TOKand:
-	    nextToken();
-	    e = parseUnaryExp();
-	    e = new AddrExp(loc, e);
-	    break;
-
-	case TOKplusplus:
-	    nextToken();
-	    e = parseUnaryExp();
-	    e = new AddAssignExp(loc, e, new IntegerExp(loc, 1, Type::tint32));
-	    break;
-
-	case TOKminusminus:
-	    nextToken();
-	    e = parseUnaryExp();
-	    e = new MinAssignExp(loc, e, new IntegerExp(loc, 1, Type::tint32));
-	    break;
-
-	case TOKmul:
-	    nextToken();
-	    e = parseUnaryExp();
-	    e = new PtrExp(loc, e);
-	    break;
-
-	case TOKmin:
-	    nextToken();
-	    e = parseUnaryExp();
-	    e = new NegExp(loc, e);
-	    break;
-
-	case TOKadd:
-	    nextToken();
-	    e = parseUnaryExp();
-	    e = new UAddExp(loc, e);
-	    break;
-
-	case TOKnot:
-	    nextToken();
-	    e = parseUnaryExp();
-	    e = new NotExp(loc, e);
-	    break;
-
-	case TOKtilde:
-	    nextToken();
-	    e = parseUnaryExp();
-	    e = new ComExp(loc, e);
-	    break;
-
-	case TOKdelete:
-	    nextToken();
-	    e = parseUnaryExp();
-	    e = new DeleteExp(loc, e);
-	    break;
-
-	case TOKnew:
-	    e = parseNewExp(NULL);
-	    break;
-
-	case TOKcast:				// cast(type) expression
-	{   Type *t;
-
-	    nextToken();
-	    check(TOKlparen);
-	    t = parseBasicType();
-	    t = parseDeclarator(t,NULL);	// ( type )
-	    check(TOKrparen);
-
-	    e = parseUnaryExp();
-	    e = new CastExp(loc, e, t);
-	    break;
-	}
-
-	case TOKlparen:
-	{   Token *tk;
-
-	    tk = peek(&token);
-#if CCASTSYNTAX
-	    // If cast
-	    if (isDeclaration(tk, 0, TOKrparen, &tk))
-	    {
-		tk = peek(tk);		// skip over right parenthesis
-		switch (tk->value)
-		{
-		    case TOKnot:
-			tk = peek(tk);
-			if (tk->value == TOKis)	// !is
-			    break;
-		    case TOKdot:
-		    case TOKplusplus:
-		    case TOKminusminus:
-		    case TOKdelete:
-		    case TOKnew:
-		    case TOKlparen:
-		    case TOKidentifier:
-		    case TOKthis:
-		    case TOKsuper:
-		    case TOKint32v:
-		    case TOKuns32v:
-		    case TOKint64v:
-		    case TOKuns64v:
-		    case TOKfloat32v:
-		    case TOKfloat64v:
-		    case TOKfloat80v:
-		    case TOKimaginary32v:
-		    case TOKimaginary64v:
-		    case TOKimaginary80v:
-		    case TOKnull:
-		    case TOKtrue:
-		    case TOKfalse:
-		    case TOKcharv:
-		    case TOKwcharv:
-		    case TOKdcharv:
-		    case TOKstring:
-#if 0
-		    case TOKtilde:
-		    case TOKand:
-		    case TOKmul:
-		    case TOKmin:
-		    case TOKadd:
-#endif
-		    case TOKfunction:
-		    case TOKdelegate:
-		    case TOKtypeof:
-#if DMDV2
-		    case TOKfile:
-		    case TOKline:
-#endif
-		    CASE_BASIC_TYPES:		// (type)int.size
-		    {	// (type) una_exp
-			Type *t;
-
-			nextToken();
-			t = parseBasicType();
-			t = parseDeclarator(t,NULL);
-			check(TOKrparen);
-
-			// if .identifier
-			if (token.value == TOKdot)
-			{
-			    nextToken();
-			    if (token.value != TOKidentifier)
-			    {   error("Identifier expected following (type).");
-				return NULL;
-			    }
-			    e = typeDotIdExp(loc, t, token.ident);
-			    nextToken();
-			    e = parsePostExp(e);
-			}
-			else
-			{
-			    e = parseUnaryExp();
-			    e = new CastExp(loc, e, t);
-			    error("C style cast illegal, use %s", e->toChars());
-			}
-			return e;
-		    }
-		}
-	    }
-#endif
-	    e = parsePrimaryExp();
-	    break;
-	}
-	default:
-	    e = parsePrimaryExp();
-	    break;
-    }
-    assert(e);
-    return e;
-}
-
-Expression *Parser::parseMulExp()
-{   Expression *e;
-    Expression *e2;
-    Loc loc = this->loc;
-
-    e = parseUnaryExp();
-    while (1)
-    {
-	switch (token.value)
-	{
-	    case TOKmul: nextToken(); e2 = parseUnaryExp(); e = new MulExp(loc,e,e2); continue;
-	    case TOKdiv:   nextToken(); e2 = parseUnaryExp(); e = new DivExp(loc,e,e2); continue;
-	    case TOKmod:  nextToken(); e2 = parseUnaryExp(); e = new ModExp(loc,e,e2); continue;
-
-	    default:
-		break;
-	}
-	break;
-    }
-    return e;
-}
-
-Expression *Parser::parseAddExp()
-{   Expression *e;
-    Expression *e2;
-    Loc loc = this->loc;
-
-    e = parseMulExp();
-    while (1)
-    {
-	switch (token.value)
-	{
-	    case TOKadd:    nextToken(); e2 = parseMulExp(); e = new AddExp(loc,e,e2); continue;
-	    case TOKmin:    nextToken(); e2 = parseMulExp(); e = new MinExp(loc,e,e2); continue;
-	    case TOKtilde:  nextToken(); e2 = parseMulExp(); e = new CatExp(loc,e,e2); continue;
-
-	    default:
-		break;
-	}
-	break;
-    }
-    return e;
-}
-
-Expression *Parser::parseShiftExp()
-{   Expression *e;
-    Expression *e2;
-    Loc loc = this->loc;
-
-    e = parseAddExp();
-    while (1)
-    {
-	switch (token.value)
-	{
-	    case TOKshl:  nextToken(); e2 = parseAddExp(); e = new ShlExp(loc,e,e2);  continue;
-	    case TOKshr:  nextToken(); e2 = parseAddExp(); e = new ShrExp(loc,e,e2);  continue;
-	    case TOKushr: nextToken(); e2 = parseAddExp(); e = new UshrExp(loc,e,e2); continue;
-
-	    default:
-		break;
-	}
-	break;
-    }
-    return e;
-}
-
-Expression *Parser::parseRelExp()
-{   Expression *e;
-    Expression *e2;
-    enum TOK op;
-    Loc loc = this->loc;
-
-    e = parseShiftExp();
-    while (1)
-    {
-	switch (token.value)
-	{
-	    case TOKlt:
-	    case TOKle:
-	    case TOKgt:
-	    case TOKge:
-	    case TOKunord:
-	    case TOKlg:
-	    case TOKleg:
-	    case TOKule:
-	    case TOKul:
-	    case TOKuge:
-	    case TOKug:
-	    case TOKue:
-		op = token.value;
-		nextToken();
-		e2 = parseShiftExp();
-		e = new CmpExp(op, loc, e, e2);
-		continue;
-
-	    case TOKin:
-		nextToken();
-		e2 = parseShiftExp();
-		e = new InExp(loc, e, e2);
-		continue;
-
-	    default:
-		break;
-	}
-	break;
-    }
-    return e;
-}
-
-Expression *Parser::parseEqualExp()
-{   Expression *e;
-    Expression *e2;
-    Token *t;
-    Loc loc = this->loc;
-
-    e = parseRelExp();
-    while (1)
-    {	enum TOK value = token.value;
-
-	switch (value)
-	{
-	    case TOKequal:
-	    case TOKnotequal:
-		nextToken();
-		e2 = parseRelExp();
-		e = new EqualExp(value, loc, e, e2);
-		continue;
-
-	    case TOKidentity:
-		error("'===' is no longer legal, use 'is' instead");
-		goto L1;
-
-	    case TOKnotidentity:
-		error("'!==' is no longer legal, use '!is' instead");
-		goto L1;
-
-	    case TOKis:
-		value = TOKidentity;
-		goto L1;
-
-	    case TOKnot:
-		// Attempt to identify '!is'
-		t = peek(&token);
-		if (t->value != TOKis)
-		    break;
-		nextToken();
-		value = TOKnotidentity;
-		goto L1;
-
-	    L1:
-		nextToken();
-		e2 = parseRelExp();
-		e = new IdentityExp(value, loc, e, e2);
-		continue;
-
-	    default:
-		break;
-	}
-	break;
-    }
-    return e;
-}
-
-Expression *Parser::parseCmpExp()
-{   Expression *e;
-    Expression *e2;
-    Token *t;
-    Loc loc = this->loc;
-
-    e = parseShiftExp();
-    enum TOK op = token.value;
-
-    switch (op)
-    {
-	case TOKequal:
-	case TOKnotequal:
-	    nextToken();
-	    e2 = parseShiftExp();
-	    e = new EqualExp(op, loc, e, e2);
-	    break;
-
-	case TOKis:
-	    op = TOKidentity;
-	    goto L1;
-
-	case TOKnot:
-	    // Attempt to identify '!is'
-	    t = peek(&token);
-	    if (t->value != TOKis)
-		break;
-	    nextToken();
-	    op = TOKnotidentity;
-	    goto L1;
-
-	L1:
-	    nextToken();
-	    e2 = parseShiftExp();
-	    e = new IdentityExp(op, loc, e, e2);
-	    break;
-
-	case TOKlt:
-	case TOKle:
-	case TOKgt:
-	case TOKge:
-	case TOKunord:
-	case TOKlg:
-	case TOKleg:
-	case TOKule:
-	case TOKul:
-	case TOKuge:
-	case TOKug:
-	case TOKue:
-	    nextToken();
-	    e2 = parseShiftExp();
-	    e = new CmpExp(op, loc, e, e2);
-	    break;
-
-	case TOKin:
-	    nextToken();
-	    e2 = parseShiftExp();
-	    e = new InExp(loc, e, e2);
-	    break;
-
-	default:
-	    break;
-    }
-    return e;
-}
-
-Expression *Parser::parseAndExp()
-{   Expression *e;
-    Expression *e2;
-    Loc loc = this->loc;
-
-    if (global.params.Dversion == 1)
-    {
-	e = parseEqualExp();
-	while (token.value == TOKand)
-	{
-	    nextToken();
-	    e2 = parseEqualExp();
-	    e = new AndExp(loc,e,e2);
-	    loc = this->loc;
-	}
-    }
-    else
-    {
-	e = parseCmpExp();
-	while (token.value == TOKand)
-	{
-	    nextToken();
-	    e2 = parseCmpExp();
-	    e = new AndExp(loc,e,e2);
-	    loc = this->loc;
-	}
-    }
-    return e;
-}
-
-Expression *Parser::parseXorExp()
-{   Expression *e;
-    Expression *e2;
-    Loc loc = this->loc;
-
-    e = parseAndExp();
-    while (token.value == TOKxor)
-    {
-	nextToken();
-	e2 = parseAndExp();
-	e = new XorExp(loc, e, e2);
-    }
-    return e;
-}
-
-Expression *Parser::parseOrExp()
-{   Expression *e;
-    Expression *e2;
-    Loc loc = this->loc;
-
-    e = parseXorExp();
-    while (token.value == TOKor)
-    {
-	nextToken();
-	e2 = parseXorExp();
-	e = new OrExp(loc, e, e2);
-    }
-    return e;
-}
-
-Expression *Parser::parseAndAndExp()
-{   Expression *e;
-    Expression *e2;
-    Loc loc = this->loc;
-
-    e = parseOrExp();
-    while (token.value == TOKandand)
-    {
-	nextToken();
-	e2 = parseOrExp();
-	e = new AndAndExp(loc, e, e2);
-    }
-    return e;
-}
-
-Expression *Parser::parseOrOrExp()
-{   Expression *e;
-    Expression *e2;
-    Loc loc = this->loc;
-
-    e = parseAndAndExp();
-    while (token.value == TOKoror)
-    {
-	nextToken();
-	e2 = parseAndAndExp();
-	e = new OrOrExp(loc, e, e2);
-    }
-    return e;
-}
-
-Expression *Parser::parseCondExp()
-{   Expression *e;
-    Expression *e1;
-    Expression *e2;
-    Loc loc = this->loc;
-
-    e = parseOrOrExp();
-    if (token.value == TOKquestion)
-    {
-	nextToken();
-	e1 = parseExpression();
-	check(TOKcolon);
-	e2 = parseCondExp();
-	e = new CondExp(loc, e, e1, e2);
-    }
-    return e;
-}
-
-Expression *Parser::parseAssignExp()
-{   Expression *e;
-    Expression *e2;
-    Loc loc;
-
-    e = parseCondExp();
-    while (1)
-    {
-	loc = this->loc;
-	switch (token.value)
-	{
-#define X(tok,ector) \
-	    case tok:  nextToken(); e2 = parseAssignExp(); e = new ector(loc,e,e2); continue;
-
-	    X(TOKassign,    AssignExp);
-	    X(TOKaddass,    AddAssignExp);
-	    X(TOKminass,    MinAssignExp);
-	    X(TOKmulass,    MulAssignExp);
-	    X(TOKdivass,    DivAssignExp);
-	    X(TOKmodass,    ModAssignExp);
-	    X(TOKandass,    AndAssignExp);
-	    X(TOKorass,     OrAssignExp);
-	    X(TOKxorass,    XorAssignExp);
-	    X(TOKshlass,    ShlAssignExp);
-	    X(TOKshrass,    ShrAssignExp);
-	    X(TOKushrass,   UshrAssignExp);
-	    X(TOKcatass,    CatAssignExp);
-
-#undef X
-	    default:
-		break;
-	}
-	break;
-    }
-    return e;
-}
-
-Expression *Parser::parseExpression()
-{   Expression *e;
-    Expression *e2;
-    Loc loc = this->loc;
-
-    //printf("Parser::parseExpression() loc = %d\n", loc.linnum);
-    e = parseAssignExp();
-    while (token.value == TOKcomma)
-    {
-	nextToken();
-	e2 = parseAssignExp();
-	e = new CommaExp(loc, e, e2);
-	loc = this->loc;
-    }
-    return e;
-}
-
-
-/*************************
- * Collect argument list.
- * Assume current token is '(' or '['.
- */
-
-Expressions *Parser::parseArguments()
-{   // function call
-    Expressions *arguments;
-    Expression *arg;
-    enum TOK endtok;
-
-    arguments = new Expressions();
-    if (token.value == TOKlbracket)
-	endtok = TOKrbracket;
-    else
-	endtok = TOKrparen;
-
-    {
-	nextToken();
-	if (token.value != endtok)
-	{
-	    while (1)
-	    {
-		arg = parseAssignExp();
-		arguments->push(arg);
-		if (token.value == endtok)
-		    break;
-		check(TOKcomma);
-	    }
-	}
-	check(endtok);
-    }
-    return arguments;
-}
-
-/*******************************************
- */
-
-Expression *Parser::parseNewExp(Expression *thisexp)
-{   Type *t;
-    Expressions *newargs;
-    Expressions *arguments = NULL;
-    Expression *e;
-    Loc loc = this->loc;
-
-    nextToken();
-    newargs = NULL;
-    if (token.value == TOKlparen)
-    {
-	newargs = parseArguments();
-    }
-
-    // An anonymous nested class starts with "class"
-    if (token.value == TOKclass)
-    {
-	nextToken();
-	if (token.value == TOKlparen)
-	    arguments = parseArguments();
-
-	BaseClasses *baseclasses = NULL;
-	if (token.value != TOKlcurly)
-	    baseclasses = parseBaseClasses();
-
-	Identifier *id = NULL;
-	ClassDeclaration *cd = new ClassDeclaration(loc, id, baseclasses);
-
-	if (token.value != TOKlcurly)
-	{   error("{ members } expected for anonymous class");
-	    cd->members = NULL;
-	}
-	else
-	{
-	    nextToken();
-	    Array *decl = parseDeclDefs(0);
-	    if (token.value != TOKrcurly)
-		error("class member expected");
-	    nextToken();
-	    cd->members = decl;
-	}
-
-	e = new NewAnonClassExp(loc, thisexp, newargs, cd, arguments);
-
-	return e;
-    }
-
-#if LTORARRAYDECL
-    t = parseBasicType();
-    t = parseBasicType2(t);
-    if (t->ty == Taarray)
-    {
-	Type *index = ((TypeAArray *)t)->index;
-
-	Expression *e = index->toExpression();
-	if (e)
-	{   arguments = new Expressions();
-	    arguments->push(e);
-	    t = new TypeDArray(t->next);
-	}
-	else
-	{
-	    error("need size of rightmost array, not type %s", index->toChars());
-	    return new NullExp(loc);
-	}
-    }
-    else if (t->ty == Tsarray)
-    {
-	TypeSArray *tsa = (TypeSArray *)t;
-	Expression *e = tsa->dim;
-
-	arguments = new Expressions();
-	arguments->push(e);
-	t = new TypeDArray(t->next);
-    }
-    else if (token.value == TOKlparen)
-    {
-	arguments = parseArguments();
-    }
-#else
-    t = parseBasicType();
-    while (token.value == TOKmul)
-    {   t = new TypePointer(t);
-	nextToken();
-    }
-    if (token.value == TOKlbracket)
-    {
-	Expression *e;
-
-	nextToken();
-	e = parseAssignExp();
-	arguments = new Array();
-	arguments->push(e);
-	check(TOKrbracket);
-	t = parseDeclarator(t, NULL);
-	t = new TypeDArray(t);
-    }
-    else if (token.value == TOKlparen)
-	arguments = parseArguments();
-#endif
-    e = new NewExp(loc, thisexp, newargs, t, arguments);
-    return e;
-}
-
-/**********************************************
- */
-
-void Parser::addComment(Dsymbol *s, unsigned char *blockComment)
-{
-    s->addComment(combineComments(blockComment, token.lineComment));
-    token.lineComment = NULL;
-}
-
-
-/********************************* ***************************/
-
+
+// Compiler implementation of the D programming language
+// Copyright (c) 1999-2009 by Digital Mars
+// All Rights Reserved
+// written by Walter Bright
+// http://www.digitalmars.com
+// License for redistribution is by either the Artistic License
+// in artistic.txt, or the GNU General Public License in gnu.txt.
+// See the included readme.txt for details.
+
+// This is the D parser
+
+#include <stdio.h>
+#include <assert.h>
+
+#include "rmem.h"
+#include "lexer.h"
+#include "parse.h"
+#include "init.h"
+#include "attrib.h"
+#include "cond.h"
+#include "mtype.h"
+#include "template.h"
+#include "staticassert.h"
+#include "expression.h"
+#include "statement.h"
+#include "module.h"
+#include "dsymbol.h"
+#include "import.h"
+#include "declaration.h"
+#include "aggregate.h"
+#include "enum.h"
+#include "id.h"
+#include "version.h"
+#if DMDV2
+#include "aliasthis.h"
+#endif
+
+// How multiple declarations are parsed.
+// If 1, treat as C.
+// If 0, treat:
+//	int *p, i;
+// as:
+//	int* p;
+//	int* i;
+#define CDECLSYNTAX	0
+
+// Support C cast syntax:
+//	(type)(expression)
+#define CCASTSYNTAX	1
+
+// Support postfix C array declarations, such as
+//	int a[3][4];
+#define CARRAYDECL	1
+
+// Support left-to-right array declarations
+#define LTORARRAYDECL	1
+
+
+Parser::Parser(Module *module, unsigned char *base, unsigned length, int doDocComment)
+    : Lexer(module, base, 0, length, doDocComment, 0)
+{
+    //printf("Parser::Parser()\n");
+    md = NULL;
+    linkage = LINKd;
+    endloc = 0;
+    inBrackets = 0;
+    //nextToken();		// start up the scanner
+}
+
+Array *Parser::parseModule()
+{
+    Array *decldefs;
+
+    // ModuleDeclation leads off
+    if (token.value == TOKmodule)
+    {
+	unsigned char *comment = token.blockComment;
+
+	nextToken();
+#if DMDV2
+	if (token.value == TOKlparen)
+	{
+	    nextToken();
+	    if (token.value != TOKidentifier)
+	    {	error("module (system) identifier expected");
+		goto Lerr;
+	    }
+	    Identifier *id = token.ident;
+
+	    if (id == Id::system)
+		safe = TRUE;
+	    else
+		error("(safe) expected, not %s", id->toChars());
+	    nextToken();
+	    check(TOKrparen);
+	}
+#endif
+
+	if (token.value != TOKidentifier)
+	{   error("Identifier expected following module");
+	    goto Lerr;
+	}
+	else
+	{
+	    Array *a = NULL;
+	    Identifier *id;
+
+	    id = token.ident;
+	    while (nextToken() == TOKdot)
+	    {
+		if (!a)
+		    a = new Array();
+		a->push(id);
+		nextToken();
+		if (token.value != TOKidentifier)
+		{   error("Identifier expected following package");
+		    goto Lerr;
+		}
+		id = token.ident;
+	    }
+
+	    md = new ModuleDeclaration(a, id);
+
+	    if (token.value != TOKsemicolon)
+		error("';' expected following module declaration instead of %s", token.toChars());
+	    nextToken();
+	    addComment(mod, comment);
+	}
+    }
+
+    decldefs = parseDeclDefs(0);
+    if (token.value != TOKeof)
+    {	error("unrecognized declaration");
+	goto Lerr;
+    }
+    return decldefs;
+
+Lerr:
+    while (token.value != TOKsemicolon && token.value != TOKeof)
+	nextToken();
+    nextToken();
+    return new Array();
+}
+
+Array *Parser::parseDeclDefs(int once)
+{   Dsymbol *s;
+    Array *decldefs;
+    Array *a;
+    Array *aelse;
+    enum PROT prot;
+    unsigned stc;
+    Condition *condition;
+    unsigned char *comment;
+
+    //printf("Parser::parseDeclDefs()\n");
+    decldefs = new Array();
+    do
+    {
+	comment = token.blockComment;
+	switch (token.value)
+	{
+	    case TOKenum:
+		s = parseEnum();
+		break;
+
+	    case TOKstruct:
+	    case TOKunion:
+	    case TOKclass:
+	    case TOKinterface:
+		s = parseAggregate();
+		break;
+
+	    case TOKimport:
+		s = parseImport(decldefs, 0);
+		break;
+
+	    case TOKtemplate:
+		s = (Dsymbol *)parseTemplateDeclaration();
+		break;
+
+	    case TOKmixin:
+	    {	Loc loc = this->loc;
+		if (peek(&token)->value == TOKlparen)
+		{   // mixin(string)
+		    nextToken();
+		    check(TOKlparen, "mixin");
+		    Expression *e = parseAssignExp();
+		    check(TOKrparen);
+		    check(TOKsemicolon);
+		    s = new CompileDeclaration(loc, e);
+		    break;
+		}
+		s = parseMixin();
+		break;
+	    }
+
+	    CASE_BASIC_TYPES:
+	    case TOKalias:
+	    case TOKtypedef:
+	    case TOKidentifier:
+	    case TOKtypeof:
+	    case TOKdot:
+	    Ldeclaration:
+		a = parseDeclarations();
+		decldefs->append(a);
+		continue;
+
+	    case TOKthis:
+		s = parseCtor();
+		break;
+
+	    case TOKtilde:
+		s = parseDtor();
+		break;
+
+	    case TOKinvariant:
+#if 1
+		s = parseInvariant();
+#else
+		if (peek(&token)->value == TOKlcurly)
+		    s = parseInvariant();
+		else
+		{
+		    stc = STCinvariant;
+		    goto Lstc;
+		}
+#endif
+		break;
+
+	    case TOKunittest:
+		s = parseUnitTest();
+		break;
+
+	    case TOKnew:
+		s = parseNew();
+		break;
+
+	    case TOKdelete:
+		s = parseDelete();
+		break;
+
+	    case TOKeof:
+	    case TOKrcurly:
+		return decldefs;
+
+	    case TOKstatic:
+		nextToken();
+		if (token.value == TOKthis)
+		    s = parseStaticCtor();
+		else if (token.value == TOKtilde)
+		    s = parseStaticDtor();
+		else if (token.value == TOKassert)
+		    s = parseStaticAssert();
+		else if (token.value == TOKif)
+		{   condition = parseStaticIfCondition();
+		    a = parseBlock();
+		    aelse = NULL;
+		    if (token.value == TOKelse)
+		    {   nextToken();
+			aelse = parseBlock();
+		    }
+		    s = new StaticIfDeclaration(condition, a, aelse);
+		    break;
+		}
+		else if (token.value == TOKimport)
+		{
+		    s = parseImport(decldefs, 1);
+		}
+		else
+		{   stc = STCstatic;
+		    goto Lstc2;
+		}
+		break;
+
+	    case TOKconst:	  stc = STCconst;	 goto Lstc;
+	    case TOKfinal:	  stc = STCfinal;	 goto Lstc;
+	    case TOKauto:	  stc = STCauto;	 goto Lstc;
+	    case TOKscope:	  stc = STCscope;	 goto Lstc;
+	    case TOKoverride:	  stc = STCoverride;	 goto Lstc;
+	    case TOKabstract:	  stc = STCabstract;	 goto Lstc;
+	    case TOKsynchronized: stc = STCsynchronized; goto Lstc;
+	    case TOKdeprecated:   stc = STCdeprecated;	 goto Lstc;
+#if DMDV2
+	    case TOKnothrow:      stc = STCnothrow;	 goto Lstc;
+	    case TOKpure:         stc = STCpure;	 goto Lstc;
+	    case TOKref:          stc = STCref;          goto Lstc;
+	    case TOKtls:          stc = STCtls;		 goto Lstc;
+	    //case TOKmanifest:	  stc = STCmanifest;	 goto Lstc;
+#endif
+
+	    Lstc:
+		nextToken();
+	    Lstc2:
+		switch (token.value)
+		{
+		    case TOKconst:	  stc |= STCconst;	 goto Lstc;
+		    case TOKfinal:	  stc |= STCfinal;	 goto Lstc;
+		    case TOKauto:	  stc |= STCauto;	 goto Lstc;
+		    case TOKscope:	  stc |= STCscope;	 goto Lstc;
+		    case TOKoverride:	  stc |= STCoverride;	 goto Lstc;
+		    case TOKabstract:	  stc |= STCabstract;	 goto Lstc;
+		    case TOKsynchronized: stc |= STCsynchronized; goto Lstc;
+		    case TOKdeprecated:   stc |= STCdeprecated;	 goto Lstc;
+		    //case TOKinvariant:    stc |= STCinvariant;   goto Lstc;
+		    default:
+			break;
+		}
+
+		/* Look for auto initializers:
+		 *	storage_class identifier = initializer;
+		 */
+		if (token.value == TOKidentifier &&
+		    peek(&token)->value == TOKassign)
+		{
+		    while (1)
+		    {
+			Identifier *ident = token.ident;
+			nextToken();
+			nextToken();
+			Initializer *init = parseInitializer();
+			VarDeclaration *v = new VarDeclaration(loc, NULL, ident, init);
+			v->storage_class = stc;
+			s = v;
+			if (token.value == TOKsemicolon)
+			{
+			    nextToken();
+			}
+			else if (token.value == TOKcomma)
+			{
+			    nextToken();
+			    if (token.value == TOKidentifier &&
+				peek(&token)->value == TOKassign)
+			    {
+				decldefs->push(s);
+				addComment(s, comment);
+				continue;
+			    }
+			    else
+				error("Identifier expected following comma");
+			}
+			else
+			    error("semicolon expected following auto declaration, not '%s'", token.toChars());
+			break;
+		    }
+		}
+		else
+		{   a = parseBlock();
+		    s = new StorageClassDeclaration(stc, a);
+		}
+		break;
+
+	    case TOKextern:
+		if (peek(&token)->value != TOKlparen)
+		{   stc = STCextern;
+		    goto Lstc;
+		}
+	    {
+		enum LINK linksave = linkage;
+		linkage = parseLinkage();
+		a = parseBlock();
+		s = new LinkDeclaration(linkage, a);
+		linkage = linksave;
+		break;
+	    }
+	    case TOKprivate:	prot = PROTprivate;	goto Lprot;
+	    case TOKpackage:	prot = PROTpackage;	goto Lprot;
+	    case TOKprotected:	prot = PROTprotected;	goto Lprot;
+	    case TOKpublic:	prot = PROTpublic;	goto Lprot;
+	    case TOKexport:	prot = PROTexport;	goto Lprot;
+
+	    Lprot:
+		nextToken();
+		switch (token.value)
+		{
+		    case TOKprivate:
+		    case TOKpackage:
+		    case TOKprotected:
+		    case TOKpublic:
+		    case TOKexport:
+			error("redundant protection attribute");
+			break;
+		}
+		a = parseBlock();
+		s = new ProtDeclaration(prot, a);
+		break;
+
+	    case TOKalign:
+	    {	unsigned n;
+
+        // LDC better align code locations
+        Loc alignloc = loc;
+
+		s = NULL;
+		nextToken();
+		if (token.value == TOKlparen)
+		{
+		    nextToken();
+		    if (token.value == TOKint32v)
+			n = (unsigned)token.uns64value;
+		    else
+		    {	error("integer expected, not %s", token.toChars());
+			n = 1;
+		    }
+		    nextToken();
+		    check(TOKrparen);
+		}
+		else
+		    n = global.structalign;		// default
+
+		a = parseBlock();
+		s = new AlignDeclaration(alignloc, n, a);
+		break;
+	    }
+
+	    case TOKpragma:
+	    {	Identifier *ident;
+		Expressions *args = NULL;
+
+		nextToken();
+		check(TOKlparen);
+		if (token.value != TOKidentifier)
+		{   error("pragma(identifier expected");
+		    goto Lerror;
+		}
+		ident = token.ident;
+		nextToken();
+		if (token.value == TOKcomma && peekNext() != TOKrparen)
+		    args = parseArguments();	// pragma(identifier, args...)
+		else
+		    check(TOKrparen);		// pragma(identifier)
+
+		if (token.value == TOKsemicolon)
+		    a = NULL;
+		else
+		    a = parseBlock();
+		s = new PragmaDeclaration(loc, ident, args, a);
+		break;
+	    }
+
+	    case TOKdebug:
+		nextToken();
+		if (token.value == TOKassign)
+		{
+		    nextToken();
+		    if (token.value == TOKidentifier)
+			s = new DebugSymbol(loc, token.ident);
+		    else if (token.value == TOKint32v)
+			s = new DebugSymbol(loc, (unsigned)token.uns64value);
+		    else
+		    {	error("identifier or integer expected, not %s", token.toChars());
+			s = NULL;
+		    }
+		    nextToken();
+		    if (token.value != TOKsemicolon)
+			error("semicolon expected");
+		    nextToken();
+		    break;
+		}
+
+		condition = parseDebugCondition();
+		goto Lcondition;
+
+	    case TOKversion:
+		nextToken();
+		if (token.value == TOKassign)
+		{
+		    nextToken();
+		    if (token.value == TOKidentifier)
+			s = new VersionSymbol(loc, token.ident);
+		    else if (token.value == TOKint32v)
+			s = new VersionSymbol(loc, (unsigned)token.uns64value);
+		    else
+		    {	error("identifier or integer expected, not %s", token.toChars());
+			s = NULL;
+		    }
+		    nextToken();
+		    if (token.value != TOKsemicolon)
+			error("semicolon expected");
+		    nextToken();
+		    break;
+		}
+		condition = parseVersionCondition();
+		goto Lcondition;
+
+	    Lcondition:
+		a = parseBlock();
+		aelse = NULL;
+		if (token.value == TOKelse)
+		{   nextToken();
+		    aelse = parseBlock();
+		}
+		s = new ConditionalDeclaration(condition, a, aelse);
+		break;
+
+	    case TOKsemicolon:		// empty declaration
+		nextToken();
+		continue;
+
+	    default:
+		error("Declaration expected, not '%s'",token.toChars());
+	    Lerror:
+		while (token.value != TOKsemicolon && token.value != TOKeof)
+		    nextToken();
+		nextToken();
+		s = NULL;
+		continue;
+	}
+	if (s)
+	{   decldefs->push(s);
+	    addComment(s, comment);
+	}
+    } while (!once);
+    return decldefs;
+}
+
+
+/********************************************
+ * Parse declarations after an align, protection, or extern decl.
+ */
+
+Array *Parser::parseBlock()
+{
+    Array *a = NULL;
+    Dsymbol *s;
+
+    //printf("parseBlock()\n");
+    switch (token.value)
+    {
+	case TOKsemicolon:
+	    error("declaration expected following attribute, not ';'");
+	    nextToken();
+	    break;
+
+	case TOKeof:
+	    error("declaration expected following attribute, not EOF");
+	    break;
+
+	case TOKlcurly:
+	    nextToken();
+	    a = parseDeclDefs(0);
+	    if (token.value != TOKrcurly)
+	    {   /* { */
+		error("matching '}' expected, not %s", token.toChars());
+	    }
+	    else
+		nextToken();
+	    break;
+
+	case TOKcolon:
+	    nextToken();
+#if 0
+	    a = NULL;
+#else
+	    a = parseDeclDefs(0);	// grab declarations up to closing curly bracket
+#endif
+	    break;
+
+	default:
+	    a = parseDeclDefs(1);
+	    break;
+    }
+    return a;
+}
+
+/**********************************
+ * Parse a static assertion.
+ */
+
+StaticAssert *Parser::parseStaticAssert()
+{
+    Loc loc = this->loc;
+    Expression *exp;
+    Expression *msg = NULL;
+
+    //printf("parseStaticAssert()\n");
+    nextToken();
+    check(TOKlparen);
+    exp = parseAssignExp();
+    if (token.value == TOKcomma)
+    {	nextToken();
+	msg = parseAssignExp();
+    }
+    check(TOKrparen);
+    check(TOKsemicolon);
+    return new StaticAssert(loc, exp, msg);
+}
+
+/***********************************
+ * Parse typeof(expression).
+ * Current token is on the 'typeof'.
+ */
+
+#if DMDV2
+TypeQualified *Parser::parseTypeof()
+{   TypeQualified *t;
+    Loc loc = this->loc;
+
+    nextToken();
+    check(TOKlparen);
+    if (token.value == TOKreturn)	// typeof(return)
+    {
+	nextToken();
+	t = new TypeReturn(loc);
+    }
+    else
+    {	Expression *exp = parseExpression();	// typeof(expression)
+	t = new TypeTypeof(loc, exp);
+    }
+    check(TOKrparen);
+    return t;
+}
+#endif
+
+/***********************************
+ * Parse extern (linkage)
+ * The parser is on the 'extern' token.
+ */
+
+enum LINK Parser::parseLinkage()
+{
+    enum LINK link = LINKdefault;
+    nextToken();
+    assert(token.value == TOKlparen);
+    nextToken();
+    if (token.value == TOKidentifier)
+    {   Identifier *id = token.ident;
+
+	nextToken();
+	if (id == Id::Windows)
+	    link = LINKwindows;
+	else if (id == Id::Pascal)
+	    link = LINKpascal;
+	else if (id == Id::D)
+	    link = LINKd;
+	else if (id == Id::C)
+	{
+	    link = LINKc;
+	    if (token.value == TOKplusplus)
+	    {   link = LINKcpp;
+		nextToken();
+	    }
+	}
+	else if (id == Id::System)
+	{
+        // LDC we configure target at runtime
+        if (global.params.os == OSWindows)
+            link = LINKwindows;
+        else
+            link = LINKc;
+	}
+	else
+	{
+	    error("valid linkage identifiers are D, C, C++, Pascal, Windows, System");
+	    link = LINKd;
+	}
+    }
+    else
+    {
+	link = LINKd;		// default
+    }
+    check(TOKrparen);
+    return link;
+}
+
+/**************************************
+ * Parse a debug conditional
+ */
+
+Condition *Parser::parseDebugCondition()
+{
+    Condition *c;
+
+    if (token.value == TOKlparen)
+    {
+	nextToken();
+	unsigned level = 1;
+	Identifier *id = NULL;
+
+	if (token.value == TOKidentifier)
+	    id = token.ident;
+	else if (token.value == TOKint32v)
+	    level = (unsigned)token.uns64value;
+	else
+	    error("identifier or integer expected, not %s", token.toChars());
+	nextToken();
+	check(TOKrparen);
+	c = new DebugCondition(mod, level, id);
+    }
+    else
+	c = new DebugCondition(mod, 1, NULL);
+    return c;
+
+}
+
+/**************************************
+ * Parse a version conditional
+ */
+
+Condition *Parser::parseVersionCondition()
+{
+    Condition *c;
+    unsigned level = 1;
+    Identifier *id = NULL;
+
+    if (token.value == TOKlparen)
+    {
+	nextToken();
+	if (token.value == TOKidentifier)
+	    id = token.ident;
+	else if (token.value == TOKint32v)
+	    level = (unsigned)token.uns64value;
+#if DMDV2
+	/* Allow:
+	 *    version (unittest)
+	 * even though unittest is a keyword
+	 */
+	else if (token.value == TOKunittest)
+	    id = Lexer::idPool(Token::toChars(TOKunittest));
+#endif
+	else
+	    error("identifier or integer expected, not %s", token.toChars());
+	nextToken();
+	check(TOKrparen);
+
+    }
+    else
+       error("(condition) expected following version");
+    c = new VersionCondition(mod, level, id);
+    return c;
+
+}
+
+/***********************************************
+ *	static if (expression)
+ *	    body
+ *	else
+ *	    body
+ */
+
+Condition *Parser::parseStaticIfCondition()
+{   Expression *exp;
+    Condition *condition;
+    Array *aif;
+    Array *aelse;
+    Loc loc = this->loc;
+
+    nextToken();
+    if (token.value == TOKlparen)
+    {
+	nextToken();
+	exp = parseAssignExp();
+	check(TOKrparen);
+    }
+    else
+    {   error("(expression) expected following static if");
+	exp = NULL;
+    }
+    condition = new StaticIfCondition(loc, exp);
+    return condition;
+}
+
+
+/*****************************************
+ * Parse a constructor definition:
+ *	this(arguments) { body }
+ * Current token is 'this'.
+ */
+
+CtorDeclaration *Parser::parseCtor()
+{
+    CtorDeclaration *f;
+    Arguments *arguments;
+    int varargs;
+    Loc loc = this->loc;
+
+    nextToken();
+    arguments = parseParameters(&varargs);
+    f = new CtorDeclaration(loc, 0, arguments, varargs);
+    parseContracts(f);
+    return f;
+}
+
+/*****************************************
+ * Parse a destructor definition:
+ *	~this() { body }
+ * Current token is '~'.
+ */
+
+DtorDeclaration *Parser::parseDtor()
+{
+    DtorDeclaration *f;
+    Loc loc = this->loc;
+
+    nextToken();
+    check(TOKthis);
+    check(TOKlparen);
+    check(TOKrparen);
+
+    f = new DtorDeclaration(loc, 0);
+    parseContracts(f);
+    return f;
+}
+
+/*****************************************
+ * Parse a static constructor definition:
+ *	static this() { body }
+ * Current token is 'this'.
+ */
+
+StaticCtorDeclaration *Parser::parseStaticCtor()
+{
+    StaticCtorDeclaration *f;
+    Loc loc = this->loc;
+
+    nextToken();
+    check(TOKlparen);
+    check(TOKrparen);
+
+    f = new StaticCtorDeclaration(loc, 0);
+    parseContracts(f);
+    return f;
+}
+
+/*****************************************
+ * Parse a static destructor definition:
+ *	static ~this() { body }
+ * Current token is '~'.
+ */
+
+StaticDtorDeclaration *Parser::parseStaticDtor()
+{
+    StaticDtorDeclaration *f;
+    Loc loc = this->loc;
+
+    nextToken();
+    check(TOKthis);
+    check(TOKlparen);
+    check(TOKrparen);
+
+    f = new StaticDtorDeclaration(loc, 0);
+    parseContracts(f);
+    return f;
+}
+
+/*****************************************
+ * Parse an invariant definition:
+ *	invariant() { body }
+ * Current token is 'invariant'.
+ */
+
+InvariantDeclaration *Parser::parseInvariant()
+{
+    InvariantDeclaration *f;
+    Loc loc = this->loc;
+
+    nextToken();
+    if (token.value == TOKlparen)	// optional ()
+    {
+	nextToken();
+	check(TOKrparen);
+    }
+
+    f = new InvariantDeclaration(loc, 0);
+    f->fbody = parseStatement(PScurly);
+    return f;
+}
+
+/*****************************************
+ * Parse a unittest definition:
+ *	unittest { body }
+ * Current token is 'unittest'.
+ */
+
+UnitTestDeclaration *Parser::parseUnitTest()
+{
+    UnitTestDeclaration *f;
+    Statement *body;
+    Loc loc = this->loc;
+
+    nextToken();
+
+    body = parseStatement(PScurly);
+
+    f = new UnitTestDeclaration(loc, this->loc);
+    f->fbody = body;
+    return f;
+}
+
+/*****************************************
+ * Parse a new definition:
+ *	new(arguments) { body }
+ * Current token is 'new'.
+ */
+
+NewDeclaration *Parser::parseNew()
+{
+    NewDeclaration *f;
+    Arguments *arguments;
+    int varargs;
+    Loc loc = this->loc;
+
+    nextToken();
+    arguments = parseParameters(&varargs);
+    f = new NewDeclaration(loc, 0, arguments, varargs);
+    parseContracts(f);
+    return f;
+}
+
+/*****************************************
+ * Parse a delete definition:
+ *	delete(arguments) { body }
+ * Current token is 'delete'.
+ */
+
+DeleteDeclaration *Parser::parseDelete()
+{
+    DeleteDeclaration *f;
+    Arguments *arguments;
+    int varargs;
+    Loc loc = this->loc;
+
+    nextToken();
+    arguments = parseParameters(&varargs);
+    if (varargs)
+	error("... not allowed in delete function parameter list");
+    f = new DeleteDeclaration(loc, 0, arguments);
+    parseContracts(f);
+    return f;
+}
+
+/**********************************************
+ * Parse parameter list.
+ */
+
+Arguments *Parser::parseParameters(int *pvarargs)
+{
+    Arguments *arguments = new Arguments();
+    int varargs = 0;
+    int hasdefault = 0;
+
+    check(TOKlparen);
+    while (1)
+    {   Type *tb;
+	Identifier *ai = NULL;
+	Type *at;
+	Argument *a;
+	unsigned storageClass;
+	Expression *ae;
+
+	storageClass = STCin;		// parameter is "in" by default
+	switch (token.value)
+	{
+	    case TOKrparen:
+		break;
+
+	    case TOKdotdotdot:
+		varargs = 1;
+		nextToken();
+		break;
+
+	    case TOKin:
+		storageClass = STCin;
+		nextToken();
+		goto L1;
+
+	    case TOKout:
+		storageClass = STCout;
+		nextToken();
+		goto L1;
+
+	    case TOKinout:
+	    case TOKref:
+		storageClass = STCref;
+		nextToken();
+		goto L1;
+
+	    case TOKlazy:
+		storageClass = STClazy;
+		nextToken();
+		goto L1;
+
+	    default:
+	    L1:
+		tb = parseBasicType();
+		at = parseDeclarator(tb, &ai);
+		ae = NULL;
+		if (token.value == TOKassign)	// = defaultArg
+		{   nextToken();
+		    ae = parseAssignExp();
+		    hasdefault = 1;
+		}
+		else
+		{   if (hasdefault)
+			error("default argument expected for %s",
+				ai ? ai->toChars() : at->toChars());
+		}
+		if (token.value == TOKdotdotdot)
+		{   /* This is:
+		     *	at ai ...
+		     */
+
+		    if (storageClass & (STCout | STCref))
+			error("variadic argument cannot be out or ref");
+		    varargs = 2;
+		    a = new Argument(storageClass, at, ai, ae);
+		    arguments->push(a);
+		    nextToken();
+		    break;
+		}
+		a = new Argument(storageClass, at, ai, ae);
+		arguments->push(a);
+		if (token.value == TOKcomma)
+		{   nextToken();
+		    continue;
+		}
+		break;
+	}
+	break;
+    }
+    check(TOKrparen);
+    *pvarargs = varargs;
+    return arguments;
+}
+
+
+/*************************************
+ */
+
+EnumDeclaration *Parser::parseEnum()
+{   EnumDeclaration *e;
+    Identifier *id;
+    Type *memtype;
+    Loc loc = this->loc;
+
+    //printf("Parser::parseEnum()\n");
+    nextToken();
+    if (token.value == TOKidentifier)
+    {	id = token.ident;
+	nextToken();
+    }
+    else
+	id = NULL;
+
+    if (token.value == TOKcolon)
+    {
+	nextToken();
+	memtype = parseBasicType();
+    }
+    else
+	memtype = NULL;
+
+    e = new EnumDeclaration(loc, id, memtype);
+    if (token.value == TOKsemicolon && id)
+ 	nextToken();
+    else if (token.value == TOKlcurly)
+    {
+	//printf("enum definition\n");
+	e->members = new Array();
+	nextToken();
+	unsigned char *comment = token.blockComment;
+	while (token.value != TOKrcurly)
+	{
+	    if (token.value == TOKidentifier)
+	    {	EnumMember *em;
+		Expression *value;
+		Identifier *ident;
+
+		loc = this->loc;
+		ident = token.ident;
+		value = NULL;
+		nextToken();
+		if (token.value == TOKassign)
+		{
+		    nextToken();
+		    value = parseAssignExp();
+		}
+		em = new EnumMember(loc, ident, value);
+		e->members->push(em);
+		if (token.value == TOKrcurly)
+		    ;
+		else
+		{   addComment(em, comment);
+		    comment = NULL;
+		    check(TOKcomma);
+		}
+		addComment(em, comment);
+		comment = token.blockComment;
+	    }
+	    else
+	    {	error("enum member expected");
+		nextToken();
+	    }
+	}
+	nextToken();
+    }
+    else
+	error("enum declaration is invalid");
+
+    //printf("-parseEnum() %s\n", e->toChars());
+    return e;
+}
+
+/********************************
+ * Parse struct, union, interface, class.
+ */
+
+Dsymbol *Parser::parseAggregate()
+{   AggregateDeclaration *a = NULL;
+    int anon = 0;
+    enum TOK tok;
+    Identifier *id;
+    TemplateParameters *tpl = NULL;
+
+    //printf("Parser::parseAggregate()\n");
+    tok = token.value;
+    nextToken();
+    if (token.value != TOKidentifier)
+    {	id = NULL;
+    }
+    else
+    {	id = token.ident;
+	nextToken();
+
+	if (token.value == TOKlparen)
+	{   // Class template declaration.
+
+	    // Gather template parameter list
+	    tpl = parseTemplateParameterList();
+	}
+    }
+
+    Loc loc = this->loc;
+    switch (tok)
+    {	case TOKclass:
+	case TOKinterface:
+	{
+	    if (!id)
+		error("anonymous classes not allowed");
+
+	    // Collect base class(es)
+	    BaseClasses *baseclasses = NULL;
+	    if (token.value == TOKcolon)
+	    {
+		nextToken();
+		baseclasses = parseBaseClasses();
+
+		if (token.value != TOKlcurly)
+		    error("members expected");
+	    }
+
+	    if (tok == TOKclass)
+		a = new ClassDeclaration(loc, id, baseclasses);
+	    else
+		a = new InterfaceDeclaration(loc, id, baseclasses);
+	    break;
+	}
+
+	case TOKstruct:
+	    if (id)
+		a = new StructDeclaration(loc, id);
+	    else
+		anon = 1;
+	    break;
+
+	case TOKunion:
+	    if (id)
+		a = new UnionDeclaration(loc, id);
+	    else
+		anon = 2;
+	    break;
+
+	default:
+	    assert(0);
+	    break;
+    }
+    if (a && token.value == TOKsemicolon)
+    { 	nextToken();
+    }
+    else if (token.value == TOKlcurly)
+    {
+	//printf("aggregate definition\n");
+	nextToken();
+	Array *decl = parseDeclDefs(0);
+	if (token.value != TOKrcurly)
+	    error("} expected following member declarations in aggregate");
+	nextToken();
+	if (anon)
+	{
+	    /* Anonymous structs/unions are more like attributes.
+	     */
+	    return new AnonDeclaration(loc, anon - 1, decl);
+	}
+	else
+	    a->members = decl;
+    }
+    else
+    {
+	error("{ } expected following aggregate declaration");
+	a = new StructDeclaration(loc, NULL);
+    }
+
+    if (tpl)
+    {	Array *decldefs;
+	TemplateDeclaration *tempdecl;
+
+	// Wrap a template around the aggregate declaration
+	decldefs = new Array();
+	decldefs->push(a);
+	tempdecl = new TemplateDeclaration(loc, id, tpl, NULL, decldefs);
+	return tempdecl;
+    }
+
+    return a;
+}
+
+/*******************************************
+ */
+
+BaseClasses *Parser::parseBaseClasses()
+{
+    enum PROT protection = PROTpublic;
+    BaseClasses *baseclasses = new BaseClasses();
+
+    for (; 1; nextToken())
+    {
+	switch (token.value)
+	{
+	    case TOKidentifier:
+		break;
+	    case TOKprivate:
+		protection = PROTprivate;
+		continue;
+	    case TOKpackage:
+		protection = PROTpackage;
+		continue;
+	    case TOKprotected:
+		protection = PROTprotected;
+		continue;
+	    case TOKpublic:
+		protection = PROTpublic;
+		continue;
+	    default:
+		error("base classes expected instead of %s", token.toChars());
+		return NULL;
+	}
+	BaseClass *b = new BaseClass(parseBasicType(), protection);
+	baseclasses->push(b);
+	if (token.value != TOKcomma)
+	    break;
+	protection = PROTpublic;
+    }
+    return baseclasses;
+}
+
+/**************************************
+ * Parse constraint.
+ * Constraint is of the form:
+ *	if ( ConstraintExpression )
+ */
+
+#if DMDV2
+Expression *Parser::parseConstraint()
+{   Expression *e = NULL;
+
+    if (token.value == TOKif)
+    {
+	nextToken();	// skip over 'if'
+	check(TOKlparen);
+	e = parseExpression();
+	check(TOKrparen);
+    }
+    return e;
+}
+#endif
+
+/**************************************
+ * Parse a TemplateDeclaration.
+ */
+
+TemplateDeclaration *Parser::parseTemplateDeclaration()
+{
+    TemplateDeclaration *tempdecl;
+    Identifier *id;
+    TemplateParameters *tpl;
+    Array *decldefs;
+    Loc loc = this->loc;
+
+    nextToken();
+    if (token.value != TOKidentifier)
+    {   error("TemplateIdentifier expected following template");
+	goto Lerr;
+    }
+    id = token.ident;
+    nextToken();
+    tpl = parseTemplateParameterList();
+    if (!tpl)
+	goto Lerr;
+
+    if (token.value != TOKlcurly)
+    {	error("members of template declaration expected");
+	goto Lerr;
+    }
+    else
+    {
+	nextToken();
+	decldefs = parseDeclDefs(0);
+	if (token.value != TOKrcurly)
+	{   error("template member expected");
+	    goto Lerr;
+	}
+	nextToken();
+    }
+
+    tempdecl = new TemplateDeclaration(loc, id, tpl, NULL, decldefs);
+    return tempdecl;
+
+Lerr:
+    return NULL;
+}
+
+/******************************************
+ * Parse template parameter list.
+ */
+
+TemplateParameters *Parser::parseTemplateParameterList()
+{
+    TemplateParameters *tpl = new TemplateParameters();
+
+    if (token.value != TOKlparen)
+    {   error("parenthesized TemplateParameterList expected following TemplateIdentifier");
+	goto Lerr;
+    }
+    nextToken();
+
+    // Get array of TemplateParameters
+    if (token.value != TOKrparen)
+    {	int isvariadic = 0;
+
+	while (1)
+	{   TemplateParameter *tp;
+	    Identifier *tp_ident = NULL;
+	    Type *tp_spectype = NULL;
+	    Type *tp_valtype = NULL;
+	    Type *tp_defaulttype = NULL;
+	    Expression *tp_specvalue = NULL;
+	    Expression *tp_defaultvalue = NULL;
+	    Token *t;
+
+	    // Get TemplateParameter
+
+	    // First, look ahead to see if it is a TypeParameter or a ValueParameter
+	    t = peek(&token);
+	    if (token.value == TOKalias)
+	    {	// AliasParameter
+		nextToken();
+		if (token.value != TOKidentifier)
+		{   error("Identifier expected for template parameter");
+		    goto Lerr;
+		}
+		tp_ident = token.ident;
+		nextToken();
+		if (token.value == TOKcolon)	// : Type
+		{
+		    nextToken();
+		    tp_spectype = parseBasicType();
+		    tp_spectype = parseDeclarator(tp_spectype, NULL);
+		}
+		if (token.value == TOKassign)	// = Type
+		{
+		    nextToken();
+		    tp_defaulttype = parseBasicType();
+		    tp_defaulttype = parseDeclarator(tp_defaulttype, NULL);
+		}
+		tp = new TemplateAliasParameter(loc, tp_ident, tp_spectype, tp_defaulttype);
+	    }
+	    else if (t->value == TOKcolon || t->value == TOKassign ||
+		     t->value == TOKcomma || t->value == TOKrparen)
+	    {	// TypeParameter
+		if (token.value != TOKidentifier)
+		{   error("Identifier expected for template parameter");
+		    goto Lerr;
+		}
+		tp_ident = token.ident;
+		nextToken();
+		if (token.value == TOKcolon)	// : Type
+		{
+		    nextToken();
+		    tp_spectype = parseBasicType();
+		    tp_spectype = parseDeclarator(tp_spectype, NULL);
+		}
+		if (token.value == TOKassign)	// = Type
+		{
+		    nextToken();
+		    tp_defaulttype = parseBasicType();
+		    tp_defaulttype = parseDeclarator(tp_defaulttype, NULL);
+		}
+		tp = new TemplateTypeParameter(loc, tp_ident, tp_spectype, tp_defaulttype);
+	    }
+	    else if (token.value == TOKidentifier && t->value == TOKdotdotdot)
+	    {	// ident...
+		if (isvariadic)
+		    error("variadic template parameter must be last");
+		isvariadic = 1;
+		tp_ident = token.ident;
+		nextToken();
+		nextToken();
+		tp = new TemplateTupleParameter(loc, tp_ident);
+	    }
+#if DMDV2
+	    else if (token.value == TOKthis)
+	    {	// ThisParameter
+		nextToken();
+		if (token.value != TOKidentifier)
+		{   error("identifier expected for template this parameter");
+		    goto Lerr;
+		}
+		tp_ident = token.ident;
+		nextToken();
+		if (token.value == TOKcolon)	// : Type
+		{
+		    nextToken();
+		    tp_spectype = parseType();
+		}
+		if (token.value == TOKassign)	// = Type
+		{
+		    nextToken();
+		    tp_defaulttype = parseType();
+		}
+		tp = new TemplateThisParameter(loc, tp_ident, tp_spectype, tp_defaulttype);
+	    }
+#endif
+	    else
+	    {	// ValueParameter
+		tp_valtype = parseBasicType();
+		tp_valtype = parseDeclarator(tp_valtype, &tp_ident);
+		if (!tp_ident)
+		{
+		    error("identifier expected for template value parameter");
+		    tp_ident = new Identifier("error", TOKidentifier);
+		}
+		if (token.value == TOKcolon)	// : CondExpression
+		{
+		    nextToken();
+		    tp_specvalue = parseCondExp();
+		}
+		if (token.value == TOKassign)	// = CondExpression
+		{
+		    nextToken();
+		    tp_defaultvalue = parseCondExp();
+		}
+		tp = new TemplateValueParameter(loc, tp_ident, tp_valtype, tp_specvalue, tp_defaultvalue);
+	    }
+	    tpl->push(tp);
+	    if (token.value != TOKcomma)
+		break;
+	    nextToken();
+	}
+    }
+    check(TOKrparen);
+Lerr:
+    return tpl;
+}
+
+/******************************************
+ * Parse template mixin.
+ *	mixin Foo;
+ *	mixin Foo!(args);
+ *	mixin a.b.c!(args).Foo!(args);
+ *	mixin Foo!(args) identifier;
+ *	mixin typeof(expr).identifier!(args);
+ */
+
+Dsymbol *Parser::parseMixin()
+{
+    TemplateMixin *tm;
+    Identifier *id;
+    Type *tqual;
+    Objects *tiargs;
+    Array *idents;
+
+    //printf("parseMixin()\n");
+    nextToken();
+    tqual = NULL;
+    if (token.value == TOKdot)
+    {
+	id = Id::empty;
+    }
+    else
+    {
+	if (token.value == TOKtypeof)
+	{   Expression *exp;
+
+	    nextToken();
+	    check(TOKlparen);
+	    exp = parseExpression();
+	    check(TOKrparen);
+	    tqual = new TypeTypeof(loc, exp);
+	    check(TOKdot);
+	}
+	if (token.value != TOKidentifier)
+	{
+	    error("identifier expected, not %s", token.toChars());
+	    id = Id::empty;
+	}
+	else
+	    id = token.ident;
+	nextToken();
+    }
+
+    idents = new Array();
+    while (1)
+    {
+	tiargs = NULL;
+	if (token.value == TOKnot)
+	{
+	    nextToken();
+	    tiargs = parseTemplateArgumentList();
+	}
+
+	if (token.value != TOKdot)
+	    break;
+
+	if (tiargs)
+	{   TemplateInstance *tempinst = new TemplateInstance(loc, id);
+	    tempinst->tiargs = tiargs;
+	    id = (Identifier *)tempinst;
+	    tiargs = NULL;
+	}
+	idents->push(id);
+
+	nextToken();
+	if (token.value != TOKidentifier)
+	{   error("identifier expected following '.' instead of '%s'", token.toChars());
+	    break;
+	}
+	id = token.ident;
+	nextToken();
+    }
+    idents->push(id);
+
+    if (token.value == TOKidentifier)
+    {
+	id = token.ident;
+	nextToken();
+    }
+    else
+	id = NULL;
+
+    tm = new TemplateMixin(loc, id, tqual, idents, tiargs);
+    if (token.value != TOKsemicolon)
+	error("';' expected after mixin");
+    nextToken();
+
+    return tm;
+}
+
+/******************************************
+ * Parse template argument list.
+ * Input:
+ * 	current token is opening '('
+ * Output:
+ *	current token is one after closing ')'
+ */
+
+Objects *Parser::parseTemplateArgumentList()
+{
+    //printf("Parser::parseTemplateArgumentList()\n");
+    Objects *tiargs = new Objects();
+    if (token.value != TOKlparen)
+    {   error("!(TemplateArgumentList) expected following TemplateIdentifier");
+	return tiargs;
+    }
+    nextToken();
+
+    // Get TemplateArgumentList
+    if (token.value != TOKrparen)
+    {
+	while (1)
+	{
+	    // See if it is an Expression or a Type
+	    if (isDeclaration(&token, 0, TOKreserved, NULL))
+	    {	// Type
+		Type *ta;
+
+		// Get TemplateArgument
+		ta = parseBasicType();
+		ta = parseDeclarator(ta, NULL);
+		tiargs->push(ta);
+	    }
+	    else
+	    {	// Expression
+		Expression *ea;
+
+		ea = parseAssignExp();
+		tiargs->push(ea);
+	    }
+	    if (token.value != TOKcomma)
+		break;
+	    nextToken();
+	}
+    }
+    check(TOKrparen, "template argument list");
+    return tiargs;
+}
+
+Import *Parser::parseImport(Array *decldefs, int isstatic)
+{   Import *s;
+    Identifier *id;
+    Identifier *aliasid = NULL;
+    Array *a;
+    Loc loc;
+
+    //printf("Parser::parseImport()\n");
+    do
+    {
+     L1:
+	nextToken();
+	if (token.value != TOKidentifier)
+	{   error("Identifier expected following import");
+	    break;
+	}
+
+	loc = this->loc;
+	a = NULL;
+	id = token.ident;
+	nextToken();
+	if (!aliasid && token.value == TOKassign)
+	{
+	    aliasid = id;
+	    goto L1;
+	}
+	while (token.value == TOKdot)
+	{
+	    if (!a)
+		a = new Array();
+	    a->push(id);
+	    nextToken();
+	    if (token.value != TOKidentifier)
+	    {   error("Identifier expected following package");
+		break;
+	    }
+	    id = token.ident;
+	    nextToken();
+	}
+
+	s = new Import(loc, a, id, aliasid, isstatic);
+	decldefs->push(s);
+
+	/* Look for
+	 *	: alias=name, alias=name;
+	 * syntax.
+	 */
+	if (token.value == TOKcolon)
+	{
+	    do
+	    {	Identifier *name;
+		Identifier *alias;
+
+		nextToken();
+		if (token.value != TOKidentifier)
+		{   error("Identifier expected following :");
+		    break;
+		}
+		alias = token.ident;
+		nextToken();
+		if (token.value == TOKassign)
+		{
+		    nextToken();
+		    if (token.value != TOKidentifier)
+		    {   error("Identifier expected following %s=", alias->toChars());
+			break;
+		    }
+		    name = token.ident;
+		    nextToken();
+		}
+		else
+		{   name = alias;
+		    alias = NULL;
+		}
+		s->addAlias(name, alias);
+	    } while (token.value == TOKcomma);
+	    break;	// no comma-separated imports of this form
+	}
+
+	aliasid = NULL;
+    } while (token.value == TOKcomma);
+
+    if (token.value == TOKsemicolon)
+ 	nextToken();
+    else
+    {
+	error("';' expected");
+	nextToken();
+    }
+
+    return NULL;
+}
+
+#if DMDV2
+Type *Parser::parseType(Identifier **pident, TemplateParameters **tpl)
+{   Type *t;
+
+    /* Take care of the storage class prefixes that
+     * serve as type attributes:
+     *  const shared, shared const, const, invariant, shared
+     */
+    if (token.value == TOKconst && peekNext() == TOKshared && peekNext2() != TOKlparen ||
+	token.value == TOKshared && peekNext() == TOKconst && peekNext2() != TOKlparen)
+    {
+	nextToken();
+	nextToken();
+	/* shared const type
+	 */
+	t = parseType(pident, tpl);
+	t = t->makeSharedConst();
+	return t;
+    }
+    else if (token.value == TOKconst && peekNext() != TOKlparen)
+    {
+	nextToken();
+	/* const type
+	 */
+	t = parseType(pident, tpl);
+	t = t->makeConst();
+	return t;
+    }
+    else if ((token.value == TOKinvariant || token.value == TOKimmutable) &&
+             peekNext() != TOKlparen)
+    {
+	nextToken();
+	/* invariant type
+	 */
+	t = parseType(pident, tpl);
+	t = t->makeInvariant();
+	return t;
+    }
+    else if (token.value == TOKshared && peekNext() != TOKlparen)
+    {
+	nextToken();
+	/* shared type
+	 */
+	t = parseType(pident, tpl);
+	t = t->makeShared();
+	return t;
+    }
+    else
+	t = parseBasicType();
+    t = parseDeclarator(t, pident, tpl);
+    return t;
+}
+#endif
+
+Type *Parser::parseBasicType()
+{   Type *t;
+    Identifier *id;
+    TypeQualified *tid;
+    TemplateInstance *tempinst;
+
+    //printf("parseBasicType()\n");
+    switch (token.value)
+    {
+	CASE_BASIC_TYPES_X(t):
+	    nextToken();
+	    break;
+
+	case TOKidentifier:
+	    id = token.ident;
+	    nextToken();
+	    if (token.value == TOKnot)
+	    {
+		nextToken();
+		tempinst = new TemplateInstance(loc, id);
+		tempinst->tiargs = parseTemplateArgumentList();
+		tid = new TypeInstance(loc, tempinst);
+		goto Lident2;
+	    }
+	Lident:
+	    tid = new TypeIdentifier(loc, id);
+	Lident2:
+	    while (token.value == TOKdot)
+	    {	nextToken();
+		if (token.value != TOKidentifier)
+		{   error("identifier expected following '.' instead of '%s'", token.toChars());
+		    break;
+		}
+		id = token.ident;
+		nextToken();
+		if (token.value == TOKnot)
+		{
+		    nextToken();
+		    tempinst = new TemplateInstance(loc, id);
+		    tempinst->tiargs = parseTemplateArgumentList();
+		    tid->addIdent((Identifier *)tempinst);
+		}
+		else
+		    tid->addIdent(id);
+	    }
+	    t = tid;
+	    break;
+
+	case TOKdot:
+	    // Leading . as in .foo
+	    id = Id::empty;
+	    goto Lident;
+
+	case TOKtypeof:
+	{   Expression *exp;
+
+	    nextToken();
+	    check(TOKlparen);
+	    exp = parseExpression();
+	    check(TOKrparen);
+	    tid = new TypeTypeof(loc, exp);
+	    goto Lident2;
+	}
+
+	default:
+	    error("basic type expected, not %s", token.toChars());
+	    t = Type::tint32;
+	    break;
+    }
+    return t;
+}
+
+/******************************************
+ * Parse things that follow the initial type t.
+ *	t *
+ *	t []
+ *	t [type]
+ *	t [expression]
+ *	t [expression .. expression]
+ *	t function
+ *	t delegate
+ */
+
+Type *Parser::parseBasicType2(Type *t)
+{
+    Type *ts;
+    Type *ta;
+
+    //printf("parseBasicType2()\n");
+    while (1)
+    {
+	switch (token.value)
+	{
+	    case TOKmul:
+		t = new TypePointer(t);
+		nextToken();
+		continue;
+
+	    case TOKlbracket:
+#if LTORARRAYDECL
+		// Handle []. Make sure things like
+		//     int[3][1] a;
+		// is (array[1] of array[3] of int)
+		nextToken();
+		if (token.value == TOKrbracket)
+		{
+		    t = new TypeDArray(t);			// []
+		    nextToken();
+		}
+		else if (isDeclaration(&token, 0, TOKrbracket, NULL))
+		{   // It's an associative array declaration
+		    Type *index;
+
+		    //printf("it's an associative array\n");
+		    index = parseBasicType();
+		    index = parseDeclarator(index, NULL);	// [ type ]
+		    t = new TypeAArray(t, index);
+		    check(TOKrbracket);
+		}
+		else
+		{
+		    //printf("it's [expression]\n");
+		    inBrackets++;
+		    Expression *e = parseExpression();		// [ expression ]
+		    if (token.value == TOKslice)
+		    {	Expression *e2;
+
+			nextToken();
+			e2 = parseExpression();			// [ exp .. exp ]
+			t = new TypeSlice(t, e, e2);
+		    }
+		    else
+			t = new TypeSArray(t,e);
+		    inBrackets--;
+		    check(TOKrbracket);
+		}
+		continue;
+#else
+		// Handle []. Make sure things like
+		//     int[3][1] a;
+		// is (array[3] of array[1] of int)
+		ts = t;
+		while (token.value == TOKlbracket)
+		{
+		    nextToken();
+		    if (token.value == TOKrbracket)
+		    {
+			ta = new TypeDArray(t);			// []
+			nextToken();
+		    }
+		    else if (isDeclaration(&token, 0, TOKrbracket, NULL))
+		    {   // It's an associative array declaration
+			Type *index;
+
+			//printf("it's an associative array\n");
+			index = parseBasicType();
+			index = parseDeclarator(index, NULL);	// [ type ]
+			check(TOKrbracket);
+			ta = new TypeAArray(t, index);
+		    }
+		    else
+		    {
+			//printf("it's [expression]\n");
+			Expression *e = parseExpression();	// [ expression ]
+			ta = new TypeSArray(t,e);
+			check(TOKrbracket);
+		    }
+		    Type **pt;
+		    for (pt = &ts; *pt != t; pt = &(*pt)->next)
+			;
+		    *pt = ta;
+		}
+		t = ts;
+		continue;
+#endif
+
+	    case TOKdelegate:
+	    case TOKfunction:
+	    {	// Handle delegate declaration:
+		//	t delegate(parameter list)
+		//	t function(parameter list)
+		Arguments *arguments;
+		int varargs;
+		enum TOK save = token.value;
+
+		nextToken();
+		arguments = parseParameters(&varargs);
+		t = new TypeFunction(arguments, t, varargs, linkage);
+		if (save == TOKdelegate)
+		    t = new TypeDelegate(t);
+		else
+		    t = new TypePointer(t);	// pointer to function
+		continue;
+	    }
+
+	    default:
+		ts = t;
+		break;
+	}
+	break;
+    }
+    return ts;
+}
+
+Type *Parser::parseDeclarator(Type *t, Identifier **pident, TemplateParameters **tpl)
+{   Type *ts;
+    Type *ta;
+
+    //printf("parseDeclarator(tpl = %p)\n", tpl);
+    t = parseBasicType2(t);
+
+    switch (token.value)
+    {
+
+	case TOKidentifier:
+	    if (pident)
+		*pident = token.ident;
+	    else
+		error("unexpected identifer '%s' in declarator", token.ident->toChars());
+	    ts = t;
+	    nextToken();
+	    break;
+
+	case TOKlparen:
+	    /* Parse things with parentheses around the identifier, like:
+	     *	int (*ident[3])[]
+	     * although the D style would be:
+	     *	int[]*[3] ident
+	     */
+	    nextToken();
+	    ts = parseDeclarator(t, pident);
+	    check(TOKrparen);
+	    break;
+
+	default:
+	    ts = t;
+	    break;
+    }
+
+    // parse DeclaratorSuffixes
+    while (1)
+    {
+	switch (token.value)
+	{
+#if CARRAYDECL
+	    /* Support C style array syntax:
+	     *   int ident[]
+	     * as opposed to D-style:
+	     *   int[] ident
+	     */
+	    case TOKlbracket:
+	    {	// This is the old C-style post [] syntax.
+		nextToken();
+		if (token.value == TOKrbracket)
+		{   // It's a dynamic array
+		    ta = new TypeDArray(t);		// []
+		    nextToken();
+		}
+		else if (isDeclaration(&token, 0, TOKrbracket, NULL))
+		{   // It's an associative array declaration
+		    Type *index;
+
+		    //printf("it's an associative array\n");
+		    index = parseBasicType();
+		    index = parseDeclarator(index, NULL);	// [ type ]
+		    check(TOKrbracket);
+		    ta = new TypeAArray(t, index);
+		}
+		else
+		{
+		    //printf("it's [expression]\n");
+		    Expression *e = parseExpression();		// [ expression ]
+		    ta = new TypeSArray(t, e);
+		    check(TOKrbracket);
+		}
+
+		/* Insert ta into
+		 *   ts -> ... -> t
+		 * so that
+		 *   ts -> ... -> ta -> t
+		 */
+		Type **pt;
+		for (pt = &ts; *pt != t; pt = &(*pt)->next)
+		    ;
+		*pt = ta;
+		continue;
+	    }
+#endif
+	    case TOKlparen:
+	    {	Arguments *arguments;
+		int varargs;
+
+		if (tpl)
+		{
+		    /* Look ahead to see if this is (...)(...),
+		     * i.e. a function template declaration
+		     */
+		    if (peekPastParen(&token)->value == TOKlparen)
+		    {   // It's a function template declaration
+			//printf("function template declaration\n");
+
+			// Gather template parameter list
+			*tpl = parseTemplateParameterList();
+		    }
+		}
+
+		arguments = parseParameters(&varargs);
+		Type *ta = new TypeFunction(arguments, t, varargs, linkage);
+		Type **pt;
+		for (pt = &ts; *pt != t; pt = &(*pt)->next)
+		    ;
+		*pt = ta;
+		break;
+	    }
+	}
+	break;
+    }
+
+    return ts;
+}
+
+/**********************************
+ * Parse Declarations.
+ * These can be:
+ *	1. declarations at global/class level
+ *	2. declarations at statement level
+ * Return array of Declaration *'s.
+ */
+
+Array *Parser::parseDeclarations()
+{
+    enum STC storage_class;
+    enum STC stc;
+    Type *ts;
+    Type *t;
+    Type *tfirst;
+    Identifier *ident;
+    Array *a;
+    enum TOK tok = TOKreserved;
+    unsigned char *comment = token.blockComment;
+    enum LINK link = linkage;
+
+    //printf("parseDeclarations()\n");
+    switch (token.value)
+    {
+	case TOKtypedef:
+	case TOKalias:
+	    tok = token.value;
+	    nextToken();
+	    break;
+
+	default:
+	    tok = TOKreserved;
+	    break;
+    }
+
+    storage_class = STCundefined;
+    while (1)
+    {
+	switch (token.value)
+	{
+	    case TOKconst:	stc = STCconst;		 goto L1;
+	    case TOKstatic:	stc = STCstatic;	 goto L1;
+	    case TOKfinal:	stc = STCfinal;		 goto L1;
+	    case TOKauto:	stc = STCauto;		 goto L1;
+	    case TOKscope:	stc = STCscope;		 goto L1;
+	    case TOKoverride:	stc = STCoverride;	 goto L1;
+	    case TOKabstract:	stc = STCabstract;	 goto L1;
+	    case TOKsynchronized: stc = STCsynchronized; goto L1;
+	    case TOKdeprecated: stc = STCdeprecated;	 goto L1;
+#if DMDV2
+	    case TOKnothrow:    stc = STCnothrow;	 goto L1;
+	    case TOKpure:       stc = STCpure;		 goto L1;
+	    case TOKref:        stc = STCref;            goto L1;
+	    case TOKtls:        stc = STCtls;		 goto L1;
+	    case TOKenum:	stc = STCmanifest;	 goto L1;
+#endif
+	    L1:
+		if (storage_class & stc)
+		    error("redundant storage class '%s'", token.toChars());
+		storage_class = (STC) (storage_class | stc);
+		nextToken();
+		continue;
+
+	    case TOKextern:
+		if (peek(&token)->value != TOKlparen)
+		{   stc = STCextern;
+		    goto L1;
+		}
+
+		link = parseLinkage();
+		continue;
+
+	    default:
+		break;
+	}
+	break;
+    }
+
+    a = new Array();
+
+    /* Look for auto initializers:
+     *	storage_class identifier = initializer;
+     */
+    while (storage_class &&
+	token.value == TOKidentifier &&
+	peek(&token)->value == TOKassign)
+    {
+	ident = token.ident;
+	nextToken();
+	nextToken();
+	Initializer *init = parseInitializer();
+	VarDeclaration *v = new VarDeclaration(loc, NULL, ident, init);
+	v->storage_class = storage_class;
+	a->push(v);
+	if (token.value == TOKsemicolon)
+	{
+	    nextToken();
+	    addComment(v, comment);
+	}
+	else if (token.value == TOKcomma)
+	{
+	    nextToken();
+	    if (!(token.value == TOKidentifier && peek(&token)->value == TOKassign))
+	    {
+		error("Identifier expected following comma");
+	    }
+	    else
+		continue;
+	}
+	else
+	    error("semicolon expected following auto declaration, not '%s'", token.toChars());
+	return a;
+    }
+
+    if (token.value == TOKclass)
+    {	AggregateDeclaration *s;
+
+	s = (AggregateDeclaration *)parseAggregate();
+	s->storage_class |= storage_class;
+	a->push(s);
+	addComment(s, comment);
+	return a;
+    }
+
+    ts = parseBasicType();
+    ts = parseBasicType2(ts);
+    tfirst = NULL;
+
+    while (1)
+    {
+	Loc loc = this->loc;
+	TemplateParameters *tpl = NULL;
+
+	ident = NULL;
+	t = parseDeclarator(ts, &ident, &tpl);
+	assert(t);
+	if (!tfirst)
+	    tfirst = t;
+	else if (t != tfirst)
+	    error("multiple declarations must have the same type, not %s and %s",
+		tfirst->toChars(), t->toChars());
+	if (!ident)
+	    error("no identifier for declarator %s", t->toChars());
+
+	if (tok == TOKtypedef || tok == TOKalias)
+	{   Declaration *v;
+	    Initializer *init = NULL;
+
+	    if (token.value == TOKassign)
+	    {
+		nextToken();
+		init = parseInitializer();
+	    }
+	    if (tok == TOKtypedef)
+		v = new TypedefDeclaration(loc, ident, t, init);
+	    else
+	    {	if (init)
+		    error("alias cannot have initializer");
+		v = new AliasDeclaration(loc, ident, t);
+	    }
+	    v->storage_class = storage_class;
+	    if (link == linkage)
+		a->push(v);
+	    else
+	    {
+		Array *ax = new Array();
+		ax->push(v);
+		Dsymbol *s = new LinkDeclaration(link, ax);
+		a->push(s);
+	    }
+	    switch (token.value)
+	    {   case TOKsemicolon:
+		    nextToken();
+		    addComment(v, comment);
+		    break;
+
+		case TOKcomma:
+		    nextToken();
+		    addComment(v, comment);
+		    continue;
+
+		default:
+		    error("semicolon expected to close %s declaration", Token::toChars(tok));
+		    break;
+	    }
+	}
+	else if (t->ty == Tfunction)
+	{   FuncDeclaration *f =
+		new FuncDeclaration(loc, 0, ident, storage_class, t);
+	    addComment(f, comment);
+	    parseContracts(f);
+	    addComment(f, NULL);
+	    Dsymbol *s;
+	    if (link == linkage)
+	    {
+		s = f;
+	    }
+	    else
+	    {
+		Array *ax = new Array();
+		ax->push(f);
+		s = new LinkDeclaration(link, ax);
+	    }
+	    if (tpl)			// it's a function template
+	    {   Array *decldefs;
+		TemplateDeclaration *tempdecl;
+
+		// Wrap a template around the aggregate declaration
+		decldefs = new Array();
+		decldefs->push(s);
+		tempdecl = new TemplateDeclaration(loc, s->ident, tpl, NULL, decldefs);
+		s = tempdecl;
+	    }
+	    addComment(s, comment);
+	    a->push(s);
+	}
+	else
+	{
+	    Initializer *init = NULL;
+	    if (token.value == TOKassign)
+	    {
+		nextToken();
+		init = parseInitializer();
+	    }
+
+	    VarDeclaration *v = new VarDeclaration(loc, t, ident, init);
+	    v->storage_class = storage_class;
+	    if (link == linkage)
+		a->push(v);
+	    else
+	    {
+		Array *ax = new Array();
+		ax->push(v);
+		Dsymbol *s = new LinkDeclaration(link, ax);
+		a->push(s);
+	    }
+	    switch (token.value)
+	    {   case TOKsemicolon:
+		    nextToken();
+		    addComment(v, comment);
+		    break;
+
+		case TOKcomma:
+		    nextToken();
+		    addComment(v, comment);
+		    continue;
+
+		default:
+		    error("semicolon expected, not '%s'", token.toChars());
+		    break;
+	    }
+	}
+	break;
+    }
+    return a;
+}
+
+/*****************************************
+ * Parse auto declarations of the form:
+ *   storageClass ident = init, ident = init, ... ;
+ * and return the array of them.
+ * Starts with token on the first ident.
+ * Ends with scanner past closing ';'
+ */
+
+#if DMDV2
+Array *Parser::parseAutoDeclarations(unsigned storageClass, unsigned char *comment)
+{
+    Array *a = new Array;
+
+    while (1)
+    {
+	Identifier *ident = token.ident;
+	nextToken();		// skip over ident
+	assert(token.value == TOKassign);
+	nextToken();		// skip over '='
+	Initializer *init = parseInitializer();
+	VarDeclaration *v = new VarDeclaration(loc, NULL, ident, init);
+	v->storage_class = storageClass;
+	a->push(v);
+	if (token.value == TOKsemicolon)
+	{
+	    nextToken();
+	    addComment(v, comment);
+	}
+	else if (token.value == TOKcomma)
+	{
+	    nextToken();
+	    if (token.value == TOKidentifier &&
+		peek(&token)->value == TOKassign)
+	    {
+		addComment(v, comment);
+		continue;
+	    }
+	    else
+		error("Identifier expected following comma");
+	}
+	else
+	    error("semicolon expected following auto declaration, not '%s'", token.toChars());
+	break;
+    }
+    return a;
+}
+#endif
+
+/*****************************************
+ * Parse contracts following function declaration.
+ */
+
+void Parser::parseContracts(FuncDeclaration *f)
+{
+    Type *tb;
+    enum LINK linksave = linkage;
+
+    // The following is irrelevant, as it is overridden by sc->linkage in
+    // TypeFunction::semantic
+    linkage = LINKd;		// nested functions have D linkage
+L1:
+    switch (token.value)
+    {
+	case TOKlcurly:
+	    if (f->frequire || f->fensure)
+		error("missing body { ... } after in or out");
+	    f->fbody = parseStatement(PSsemi);
+	    f->endloc = endloc;
+	    break;
+
+	case TOKbody:
+	    nextToken();
+	    f->fbody = parseStatement(PScurly);
+	    f->endloc = endloc;
+	    break;
+
+	case TOKsemicolon:
+	    if (f->frequire || f->fensure)
+		error("missing body { ... } after in or out");
+	    nextToken();
+	    break;
+
+#if 0	// Do we want this for function declarations, so we can do:
+    // int x, y, foo(), z;
+	case TOKcomma:
+	    nextToken();
+	    continue;
+#endif
+
+#if 0 // Dumped feature
+	case TOKthrow:
+	    if (!f->fthrows)
+		f->fthrows = new Array();
+	    nextToken();
+	    check(TOKlparen);
+	    while (1)
+	    {
+		tb = parseBasicType();
+		f->fthrows->push(tb);
+		if (token.value == TOKcomma)
+		{   nextToken();
+		    continue;
+		}
+		break;
+	    }
+	    check(TOKrparen);
+	    goto L1;
+#endif
+
+	case TOKin:
+	    nextToken();
+	    if (f->frequire)
+		error("redundant 'in' statement");
+	    f->frequire = parseStatement(PScurly | PSscope);
+	    goto L1;
+
+	case TOKout:
+	    // parse: out (identifier) { statement }
+	    nextToken();
+	    if (token.value != TOKlcurly)
+	    {
+		check(TOKlparen);
+		if (token.value != TOKidentifier)	   
+		    error("(identifier) following 'out' expected, not %s", token.toChars());
+		f->outId = token.ident;
+		nextToken();
+		check(TOKrparen);
+	    }
+	    if (f->fensure)
+		error("redundant 'out' statement");
+	    f->fensure = parseStatement(PScurly | PSscope);
+	    goto L1;
+
+	default:
+	    error("semicolon expected following function declaration");
+	    break;
+    }
+    linkage = linksave;
+}
+
+/*****************************************
+ * Parse initializer for variable declaration.
+ */
+
+Initializer *Parser::parseInitializer()
+{
+    StructInitializer *is;
+    ArrayInitializer *ia;
+    ExpInitializer *ie;
+    Expression *e;
+    Identifier *id;
+    Initializer *value;
+    int comma;
+    Loc loc = this->loc;
+    Token *t;
+    int braces;
+    int brackets;
+
+    switch (token.value)
+    {
+	case TOKlcurly:
+	    /* Scan ahead to see if it is a struct initializer or
+	     * a function literal.
+	     * If it contains a ';', it is a function literal.
+	     * Treat { } as a struct initializer.
+	     */
+	    braces = 1;
+	    for (t = peek(&token); 1; t = peek(t))
+	    {
+		switch (t->value)
+		{
+		    case TOKsemicolon:
+		    case TOKreturn:
+			goto Lexpression;
+
+		    case TOKlcurly:
+			braces++;
+			continue;
+
+		    case TOKrcurly:
+			if (--braces == 0)
+			    break;
+			continue;
+
+		    case TOKeof:
+			break;
+
+		    default:
+			continue;
+		}
+		break;
+	    }
+
+	    is = new StructInitializer(loc);
+	    nextToken();
+	    comma = 0;
+	    while (1)
+	    {
+		switch (token.value)
+		{
+		    case TOKidentifier:
+			if (comma == 1)
+			    error("comma expected separating field initializers");
+			t = peek(&token);
+			if (t->value == TOKcolon)
+			{
+			    id = token.ident;
+			    nextToken();
+			    nextToken();	// skip over ':'
+			}
+			else
+			{   id = NULL;
+			}
+			value = parseInitializer();
+			is->addInit(id, value);
+			comma = 1;
+			continue;
+
+		    case TOKcomma:
+			nextToken();
+			comma = 2;
+			continue;
+
+		    case TOKrcurly:		// allow trailing comma's
+			nextToken();
+			break;
+
+		    case TOKeof:
+			error("found EOF instead of initializer");
+			break;
+
+		    default:
+			value = parseInitializer();
+			is->addInit(NULL, value);
+			comma = 1;
+			continue;
+			//error("found '%s' instead of field initializer", token.toChars());
+			//break;
+		}
+		break;
+	    }
+	    return is;
+
+	case TOKlbracket:
+	    /* Scan ahead to see if it is an array initializer or
+	     * an expression.
+	     * If it ends with a ';', it is an array initializer.
+	     */
+	    brackets = 1;
+	    for (t = peek(&token); 1; t = peek(t))
+	    {
+		switch (t->value)
+		{
+		    case TOKlbracket:
+			brackets++;
+			continue;
+
+		    case TOKrbracket:
+			if (--brackets == 0)
+			{   t = peek(t);
+			    if (t->value != TOKsemicolon &&
+				t->value != TOKcomma &&
+				t->value != TOKrcurly)
+				goto Lexpression;
+			    break;
+			}
+			continue;
+
+		    case TOKeof:
+			break;
+
+		    default:
+			continue;
+		}
+		break;
+	    }
+
+	    ia = new ArrayInitializer(loc);
+	    nextToken();
+	    comma = 0;
+	    while (1)
+	    {
+		switch (token.value)
+		{
+		    default:
+			if (comma == 1)
+			{   error("comma expected separating array initializers, not %s", token.toChars());
+			    nextToken();
+			    break;
+			}
+			e = parseAssignExp();
+			if (!e)
+			    break;
+			if (token.value == TOKcolon)
+			{
+			    nextToken();
+			    value = parseInitializer();
+			}
+			else
+			{   value = new ExpInitializer(e->loc, e);
+			    e = NULL;
+			}
+			ia->addInit(e, value);
+			comma = 1;
+			continue;
+
+		    case TOKlcurly:
+		    case TOKlbracket:
+			if (comma == 1)
+			    error("comma expected separating array initializers, not %s", token.toChars());
+			value = parseInitializer();
+			ia->addInit(NULL, value);
+			comma = 1;
+			continue;
+
+		    case TOKcomma:
+			nextToken();
+			comma = 2;
+			continue;
+
+		    case TOKrbracket:		// allow trailing comma's
+			nextToken();
+			break;
+
+		    case TOKeof:
+			error("found '%s' instead of array initializer", token.toChars());
+			break;
+		}
+		break;
+	    }
+	    return ia;
+
+	case TOKvoid:
+	    t = peek(&token);
+	    if (t->value == TOKsemicolon || t->value == TOKcomma)
+	    {
+		nextToken();
+		return new VoidInitializer(loc);
+	    }
+	    goto Lexpression;
+
+	default:
+	Lexpression:
+	    e = parseAssignExp();
+	    ie = new ExpInitializer(loc, e);
+	    return ie;
+    }
+}
+
+/*****************************************
+ * Parses default argument initializer expression that is an assign expression,
+ * with special handling for __FILE__ and __LINE__.
+ */
+
+#if DMDV2
+Expression *Parser::parseDefaultInitExp()
+{
+    if (token.value == TOKfile ||
+	token.value == TOKline)
+    {
+	Token *t = peek(&token);
+	if (t->value == TOKcomma || t->value == TOKrparen)
+	{   Expression *e;
+
+	    if (token.value == TOKfile)
+		e = new FileInitExp(loc);
+	    else
+		e = new LineInitExp(loc);
+	    nextToken();
+	    return e;
+	}
+    }
+
+    Expression *e = parseAssignExp();
+    return e;
+}
+#endif
+
+/*****************************************
+ * Input:
+ *	flags	PSxxxx
+ */
+
+Statement *Parser::parseStatement(int flags)
+{   Statement *s;
+    Token *t;
+    Condition *condition;
+    Statement *ifbody;
+    Statement *elsebody;
+    Loc loc = this->loc;
+
+    //printf("parseStatement()\n");
+
+    if (flags & PScurly && token.value != TOKlcurly)
+	error("statement expected to be { }, not %s", token.toChars());
+
+    switch (token.value)
+    {
+	case TOKidentifier:
+	    /* A leading identifier can be a declaration, label, or expression.
+	     * The easiest case to check first is label:
+	     */
+	    t = peek(&token);
+	    if (t->value == TOKcolon)
+	    {	// It's a label
+
+		Identifier *ident = token.ident;
+		nextToken();
+		nextToken();
+		s = parseStatement(PSsemi);
+		s = new LabelStatement(loc, ident, s);
+		break;
+	    }
+	    // fallthrough to TOKdot
+	case TOKdot:
+	case TOKtypeof:
+	    if (isDeclaration(&token, 2, TOKreserved, NULL))
+		goto Ldeclaration;
+	    else
+		goto Lexp;
+	    break;
+
+	case TOKassert:
+	case TOKthis:
+	case TOKsuper:
+	case TOKint32v:
+	case TOKuns32v:
+	case TOKint64v:
+	case TOKuns64v:
+	case TOKfloat32v:
+	case TOKfloat64v:
+	case TOKfloat80v:
+	case TOKimaginary32v:
+	case TOKimaginary64v:
+	case TOKimaginary80v:
+	case TOKcharv:
+	case TOKwcharv:
+	case TOKdcharv:
+	case TOKnull:
+	case TOKtrue:
+	case TOKfalse:
+	case TOKstring:
+	case TOKlparen:
+	case TOKcast:
+	case TOKmul:
+	case TOKmin:
+	case TOKadd:
+	case TOKplusplus:
+	case TOKminusminus:
+	case TOKnew:
+	case TOKdelete:
+	case TOKdelegate:
+	case TOKfunction:
+	case TOKtypeid:
+	case TOKis:
+	case TOKlbracket:
+#if DMDV2
+	case TOKtraits:
+	case TOKfile:
+	case TOKline:
+#endif
+	Lexp:
+	{   Expression *exp;
+
+	    exp = parseExpression();
+	    check(TOKsemicolon, "statement");
+	    s = new ExpStatement(loc, exp);
+	    break;
+	}
+
+	case TOKstatic:
+	{   // Look ahead to see if it's static assert() or static if()
+	    Token *t;
+
+	    t = peek(&token);
+	    if (t->value == TOKassert)
+	    {
+		nextToken();
+		s = new StaticAssertStatement(parseStaticAssert());
+		break;
+	    }
+	    if (t->value == TOKif)
+	    {
+		nextToken();
+		condition = parseStaticIfCondition();
+		goto Lcondition;
+	    }
+	    goto Ldeclaration;
+	}
+
+	CASE_BASIC_TYPES:
+	case TOKtypedef:
+	case TOKalias:
+	case TOKconst:
+	case TOKauto:
+	case TOKextern:
+	case TOKfinal:
+	case TOKinvariant:
+#if DMDV2
+	case TOKimmutable:
+	case TOKshared:
+#endif
+//	case TOKtypeof:
+	Ldeclaration:
+	{   Array *a;
+
+	    a = parseDeclarations();
+	    if (a->dim > 1)
+	    {
+		Statements *as = new Statements();
+		as->reserve(a->dim);
+		for (int i = 0; i < a->dim; i++)
+		{
+		    Dsymbol *d = (Dsymbol *)a->data[i];
+		    s = new DeclarationStatement(loc, d);
+		    as->push(s);
+		}
+		s = new CompoundDeclarationStatement(loc, as);
+	    }
+	    else if (a->dim == 1)
+	    {
+		Dsymbol *d = (Dsymbol *)a->data[0];
+		s = new DeclarationStatement(loc, d);
+	    }
+	    else
+		assert(0);
+	    if (flags & PSscope)
+		s = new ScopeStatement(loc, s);
+	    break;
+	}
+
+	case TOKstruct:
+	case TOKunion:
+	case TOKclass:
+	case TOKinterface:
+	{   Dsymbol *d;
+
+	    d = parseAggregate();
+	    s = new DeclarationStatement(loc, d);
+	    break;
+	}
+
+	case TOKenum:
+	{   Dsymbol *d;
+
+	    d = parseEnum();
+	    s = new DeclarationStatement(loc, d);
+	    break;
+	}
+
+	case TOKmixin:
+	{   t = peek(&token);
+	    if (t->value == TOKlparen)
+	    {	// mixin(string)
+		nextToken();
+		check(TOKlparen, "mixin");
+		Expression *e = parseAssignExp();
+		check(TOKrparen);
+		check(TOKsemicolon);
+		s = new CompileStatement(loc, e);
+		break;
+	    }
+	    Dsymbol *d = parseMixin();
+	    s = new DeclarationStatement(loc, d);
+	    break;
+	}
+
+	case TOKlcurly:
+	{
+	    nextToken();
+	    Statements *statements = new Statements();
+	    while (token.value != TOKrcurly && token.value != TOKeof)
+	    {
+		statements->push(parseStatement(PSsemi | PScurlyscope));
+	    }
+	    endloc = this->loc;
+	    s = new CompoundStatement(loc, statements);
+	    if (flags & (PSscope | PScurlyscope))
+		s = new ScopeStatement(loc, s);
+	    nextToken();
+	    break;
+	}
+
+	case TOKwhile:
+	{   Expression *condition;
+	    Statement *body;
+
+	    nextToken();
+	    check(TOKlparen);
+	    condition = parseExpression();
+	    check(TOKrparen);
+	    body = parseStatement(PSscope);
+	    s = new WhileStatement(loc, condition, body);
+	    break;
+	}
+
+	case TOKsemicolon:
+	    if (!(flags & PSsemi))
+		error("use '{ }' for an empty statement, not a ';'");
+	    nextToken();
+	    s = new ExpStatement(loc, NULL);
+	    break;
+
+	case TOKdo:
+	{   Statement *body;
+	    Expression *condition;
+
+	    nextToken();
+	    body = parseStatement(PSscope);
+	    check(TOKwhile);
+	    check(TOKlparen);
+	    condition = parseExpression();
+	    check(TOKrparen);
+	    s = new DoStatement(loc, body, condition);
+	    break;
+	}
+
+	case TOKfor:
+	{
+	    Statement *init;
+	    Expression *condition;
+	    Expression *increment;
+	    Statement *body;
+
+	    nextToken();
+	    check(TOKlparen);
+	    if (token.value == TOKsemicolon)
+	    {	init = NULL;
+		nextToken();
+	    }
+	    else
+	    {	init = parseStatement(0);
+	    }
+	    if (token.value == TOKsemicolon)
+	    {
+		condition = NULL;
+		nextToken();
+	    }
+	    else
+	    {
+		condition = parseExpression();
+		check(TOKsemicolon, "for condition");
+	    }
+	    if (token.value == TOKrparen)
+	    {	increment = NULL;
+		nextToken();
+	    }
+	    else
+	    {	increment = parseExpression();
+		check(TOKrparen);
+	    }
+	    body = parseStatement(PSscope);
+	    s = new ForStatement(loc, init, condition, increment, body);
+	    if (init)
+		s = new ScopeStatement(loc, s);
+	    break;
+	}
+
+	case TOKforeach:
+	case TOKforeach_reverse:
+	{
+	    enum TOK op = token.value;
+	    Arguments *arguments;
+
+	    Statement *d;
+	    Statement *body;
+	    Expression *aggr;
+
+	    nextToken();
+	    check(TOKlparen);
+
+	    arguments = new Arguments();
+
+	    while (1)
+	    {
+		Type *tb;
+		Identifier *ai = NULL;
+		Type *at;
+		unsigned storageClass;
+		Argument *a;
+
+		storageClass = STCin;
+		if (token.value == TOKinout || token.value == TOKref)
+		{   storageClass = STCref;
+		    nextToken();
+		}
+		if (token.value == TOKidentifier)
+		{
+		    Token *t = peek(&token);
+		    if (t->value == TOKcomma || t->value == TOKsemicolon)
+		    {	ai = token.ident;
+			at = NULL;		// infer argument type
+			nextToken();
+			goto Larg;
+		    }
+		}
+		tb = parseBasicType();
+		at = parseDeclarator(tb, &ai);
+		if (!ai)
+		    error("no identifier for declarator %s", at->toChars());
+	      Larg:
+		a = new Argument(storageClass, at, ai, NULL);
+		arguments->push(a);
+		if (token.value == TOKcomma)
+		{   nextToken();
+		    continue;
+		}
+		break;
+	    }
+	    check(TOKsemicolon);
+
+	    aggr = parseExpression();
+	    check(TOKrparen);
+	    body = parseStatement(0);
+	    s = new ForeachStatement(loc, op, arguments, aggr, body);
+	    break;
+	}
+
+	case TOKif:
+	{   Argument *arg = NULL;
+	    Expression *condition;
+	    Statement *ifbody;
+	    Statement *elsebody;
+
+	    nextToken();
+	    check(TOKlparen);
+
+	    if (token.value == TOKauto)
+	    {
+		nextToken();
+		if (token.value == TOKidentifier)
+		{
+		    Token *t = peek(&token);
+		    if (t->value == TOKassign)
+		    {
+			arg = new Argument(STCin, NULL, token.ident, NULL);
+			nextToken();
+			nextToken();
+		    }
+		    else
+		    {   error("= expected following auto identifier");
+			goto Lerror;
+		    }
+		}
+		else
+		{   error("identifier expected following auto");
+		    goto Lerror;
+		}
+	    }
+	    else if (isDeclaration(&token, 2, TOKassign, NULL))
+	    {
+		Type *tb;
+		Type *at;
+		Identifier *ai;
+
+		tb = parseBasicType();
+		at = parseDeclarator(tb, &ai);
+		check(TOKassign);
+		arg = new Argument(STCin, at, ai, NULL);
+	    }
+
+	    // Check for " ident;"
+	    else if (token.value == TOKidentifier)
+	    {
+		Token *t = peek(&token);
+		if (t->value == TOKcomma || t->value == TOKsemicolon)
+		{
+		    arg = new Argument(STCin, NULL, token.ident, NULL);
+		    nextToken();
+		    nextToken();
+		    if (1 || !global.params.useDeprecated)
+			error("if (v; e) is deprecated, use if (auto v = e)");
+		}
+	    }
+
+	    condition = parseExpression();
+	    check(TOKrparen);
+	    ifbody = parseStatement(PSscope);
+	    if (token.value == TOKelse)
+	    {
+		nextToken();
+		elsebody = parseStatement(PSscope);
+	    }
+	    else
+		elsebody = NULL;
+	    s = new IfStatement(loc, arg, condition, ifbody, elsebody);
+	    break;
+	}
+
+	case TOKscope:
+	    if (peek(&token)->value != TOKlparen)
+		goto Ldeclaration;		// scope used as storage class
+	    nextToken();
+	    check(TOKlparen);
+	    if (token.value != TOKidentifier)
+	    {	error("scope identifier expected");
+		goto Lerror;
+	    }
+	    else
+	    {	TOK t = TOKon_scope_exit;
+		Identifier *id = token.ident;
+
+		if (id == Id::exit)
+		    t = TOKon_scope_exit;
+		else if (id == Id::failure)
+		    t = TOKon_scope_failure;
+		else if (id == Id::success)
+		    t = TOKon_scope_success;
+		else
+		    error("valid scope identifiers are exit, failure, or success, not %s", id->toChars());
+		nextToken();
+		check(TOKrparen);
+		Statement *st = parseStatement(PScurlyscope);
+		s = new OnScopeStatement(loc, t, st);
+		break;
+	    }
+
+	case TOKdebug:
+	    nextToken();
+	    condition = parseDebugCondition();
+	    goto Lcondition;
+
+	case TOKversion:
+	    nextToken();
+	    condition = parseVersionCondition();
+	    goto Lcondition;
+
+	Lcondition:
+	    ifbody = parseStatement(0 /*PSsemi*/);
+	    elsebody = NULL;
+	    if (token.value == TOKelse)
+	    {
+		nextToken();
+		elsebody = parseStatement(0 /*PSsemi*/);
+	    }
+	    s = new ConditionalStatement(loc, condition, ifbody, elsebody);
+	    break;
+
+	case TOKpragma:
+	{   Identifier *ident;
+	    Expressions *args = NULL;
+	    Statement *body;
+
+	    nextToken();
+	    check(TOKlparen);
+	    if (token.value != TOKidentifier)
+	    {   error("pragma(identifier expected");
+		goto Lerror;
+	    }
+	    ident = token.ident;
+	    nextToken();
+	    if (token.value == TOKcomma && peekNext() != TOKrparen)
+		args = parseArguments();	// pragma(identifier, args...);
+	    else
+		check(TOKrparen);		// pragma(identifier);
+	    if (token.value == TOKsemicolon)
+	    {	nextToken();
+		body = NULL;
+	    }
+	    else
+		body = parseStatement(PSsemi);
+	    s = new PragmaStatement(loc, ident, args, body);
+	    break;
+	}
+
+	case TOKswitch:
+	{   Expression *condition;
+	    Statement *body;
+
+	    nextToken();
+	    check(TOKlparen);
+	    condition = parseExpression();
+	    check(TOKrparen);
+	    body = parseStatement(PSscope);
+	    s = new SwitchStatement(loc, condition, body);
+	    break;
+	}
+
+	case TOKcase:
+	{   Expression *exp;
+	    Statements *statements;
+	    Array cases;	// array of Expression's
+
+	    while (1)
+	    {
+		nextToken();
+		exp = parseAssignExp();
+		cases.push(exp);
+		if (token.value != TOKcomma)
+		    break;
+	    }
+	    check(TOKcolon);
+
+	    statements = new Statements();
+	    while (token.value != TOKcase &&
+		   token.value != TOKdefault &&
+		   token.value != TOKeof &&
+		   token.value != TOKrcurly)
+	    {
+		statements->push(parseStatement(PSsemi | PScurlyscope));
+	    }
+	    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--)
+	    {
+		exp = (Expression *)cases.data[i - 1];
+		s = new CaseStatement(loc, exp, s);
+	    }
+	    break;
+	}
+
+	case TOKdefault:
+	{
+	    Statements *statements;
+
+	    nextToken();
+	    check(TOKcolon);
+
+	    statements = new Statements();
+	    while (token.value != TOKcase &&
+		   token.value != TOKdefault &&
+		   token.value != TOKeof &&
+		   token.value != TOKrcurly)
+	    {
+		statements->push(parseStatement(PSsemi | PScurlyscope));
+	    }
+	    s = new CompoundStatement(loc, statements);
+	    s = new ScopeStatement(loc, s);
+	    s = new DefaultStatement(loc, s);
+	    break;
+	}
+
+	case TOKreturn:
+	{   Expression *exp;
+
+	    nextToken();
+	    if (token.value == TOKsemicolon)
+		exp = NULL;
+	    else
+		exp = parseExpression();
+	    check(TOKsemicolon, "return statement");
+	    s = new ReturnStatement(loc, exp);
+	    break;
+	}
+
+	case TOKbreak:
+	{   Identifier *ident;
+
+	    nextToken();
+	    if (token.value == TOKidentifier)
+	    {	ident = token.ident;
+		nextToken();
+	    }
+	    else
+		ident = NULL;
+	    check(TOKsemicolon, "break statement");
+	    s = new BreakStatement(loc, ident);
+	    break;
+	}
+
+	case TOKcontinue:
+	{   Identifier *ident;
+
+	    nextToken();
+	    if (token.value == TOKidentifier)
+	    {	ident = token.ident;
+		nextToken();
+	    }
+	    else
+		ident = NULL;
+	    check(TOKsemicolon, "continue statement");
+	    s = new ContinueStatement(loc, ident);
+	    break;
+	}
+
+	case TOKgoto:
+	{   Identifier *ident;
+
+	    nextToken();
+	    if (token.value == TOKdefault)
+	    {
+		nextToken();
+		s = new GotoDefaultStatement(loc);
+	    }
+	    else if (token.value == TOKcase)
+	    {
+		Expression *exp = NULL;
+
+		nextToken();
+		if (token.value != TOKsemicolon)
+		    exp = parseExpression();
+		s = new GotoCaseStatement(loc, exp);
+	    }
+	    else
+	    {
+		if (token.value != TOKidentifier)
+		{   error("Identifier expected following goto");
+		    ident = NULL;
+		}
+		else
+		{   ident = token.ident;
+		    nextToken();
+		}
+		s = new GotoStatement(loc, ident);
+	    }
+	    check(TOKsemicolon, "goto statement");
+	    break;
+	}
+
+	case TOKsynchronized:
+	{   Expression *exp;
+	    Statement *body;
+
+	    nextToken();
+	    if (token.value == TOKlparen)
+	    {
+		nextToken();
+		exp = parseExpression();
+		check(TOKrparen);
+	    }
+	    else
+		exp = NULL;
+	    body = parseStatement(PSscope);
+	    s = new SynchronizedStatement(loc, exp, body);
+	    break;
+	}
+
+	case TOKwith:
+	{   Expression *exp;
+	    Statement *body;
+
+	    nextToken();
+	    check(TOKlparen);
+	    exp = parseExpression();
+	    check(TOKrparen);
+	    body = parseStatement(PSscope);
+	    s = new WithStatement(loc, exp, body);
+	    break;
+	}
+
+	case TOKtry:
+	{   Statement *body;
+	    Array *catches = NULL;
+	    Statement *finalbody = NULL;
+
+	    nextToken();
+	    body = parseStatement(PSscope);
+	    while (token.value == TOKcatch)
+	    {
+		Statement *handler;
+		Catch *c;
+		Type *t;
+		Identifier *id;
+		Loc loc = this->loc;
+
+		nextToken();
+		if (token.value == TOKlcurly)
+		{
+		    t = NULL;
+		    id = NULL;
+		}
+		else
+		{
+		    check(TOKlparen);
+		    t = parseBasicType();
+		    id = NULL;
+		    t = parseDeclarator(t, &id);
+		    check(TOKrparen);
+		}
+		handler = parseStatement(0);
+		c = new Catch(loc, t, id, handler);
+		if (!catches)
+		    catches = new Array();
+		catches->push(c);
+	    }
+
+	    if (token.value == TOKfinally)
+	    {	nextToken();
+		finalbody = parseStatement(0);
+	    }
+
+	    s = body;
+	    if (!catches && !finalbody)
+		error("catch or finally expected following try");
+	    else
+	    {	if (catches)
+		    s = new TryCatchStatement(loc, body, catches);
+		if (finalbody)
+		    s = new TryFinallyStatement(loc, s, finalbody);
+	    }
+	    break;
+	}
+
+	case TOKthrow:
+	{   Expression *exp;
+
+	    nextToken();
+	    exp = parseExpression();
+	    check(TOKsemicolon, "throw statement");
+	    s = new ThrowStatement(loc, exp);
+	    break;
+	}
+
+	case TOKvolatile:
+	    nextToken();
+	    s = parseStatement(PSsemi | PScurlyscope);
+#if DMDV2
+	    if (!global.params.useDeprecated)
+		error("volatile statements deprecated; used synchronized statements instead");
+#endif
+	    s = new VolatileStatement(loc, s);
+	    break;
+
+	case TOKasm:
+	{   Statements *statements;
+	    Identifier *label;
+	    Loc labelloc;
+	    Token *toklist;
+	    Token **ptoklist;
+
+	    // Parse the asm block into a sequence of AsmStatements,
+	    // each AsmStatement is one instruction.
+	    // Separate out labels.
+	    // Defer parsing of AsmStatements until semantic processing.
+
+	    nextToken();
+	    check(TOKlcurly);
+	    toklist = NULL;
+	    ptoklist = &toklist;
+	    label = NULL;
+	    statements = new Statements();
+	    while (1)
+	    {
+		switch (token.value)
+		{
+		    case TOKidentifier:
+			if (!toklist)
+			{
+			    // Look ahead to see if it is a label
+			    t = peek(&token);
+			    if (t->value == TOKcolon)
+			    {   // It's a label
+				label = token.ident;
+				labelloc = this->loc;
+				nextToken();
+				nextToken();
+				continue;
+			    }
+			}
+			goto Ldefault;
+
+		    case TOKrcurly:
+			if (toklist || label)
+			{
+			    error("asm statements must end in ';'");
+			}
+			break;
+
+		    case TOKsemicolon:
+			s = NULL;
+			if (toklist || label)
+			{   // Create AsmStatement from list of tokens we've saved
+			    s = new AsmStatement(this->loc, toklist);
+			    toklist = NULL;
+			    ptoklist = &toklist;
+			    if (label)
+			    {   s = new LabelStatement(labelloc, label, s);
+				label = NULL;
+			    }
+			    statements->push(s);
+			}
+			nextToken();
+			continue;
+
+		    case TOKeof:
+			/* { */
+			error("matching '}' expected, not end of file");
+			break;
+
+		    default:
+		    Ldefault:
+			*ptoklist = new Token();
+			memcpy(*ptoklist, &token, sizeof(Token));
+			ptoklist = &(*ptoklist)->next;
+			*ptoklist = NULL;
+
+			nextToken();
+			continue;
+		}
+		break;
+	    }
+        s = new AsmBlockStatement(loc, statements);
+	    nextToken();
+	    break;
+	}
+
+	default:
+	    error("found '%s' instead of statement", token.toChars());
+	    goto Lerror;
+
+	Lerror:
+	    while (token.value != TOKrcurly &&
+		   token.value != TOKsemicolon &&
+		   token.value != TOKeof)
+		nextToken();
+	    if (token.value == TOKsemicolon)
+		nextToken();
+	    s = NULL;
+	    break;
+    }
+
+    return s;
+}
+
+void Parser::check(enum TOK value)
+{
+    check(loc, value);
+}
+
+void Parser::check(Loc loc, enum TOK value)
+{
+    if (token.value != value)
+	error(loc, "found '%s' when expecting '%s'", token.toChars(), Token::toChars(value));
+    nextToken();
+}
+
+void Parser::check(enum TOK value, const char *string)
+{
+    if (token.value != value)
+	error("found '%s' when expecting '%s' following '%s'",
+	    token.toChars(), Token::toChars(value), string);
+    nextToken();
+}
+
+/************************************
+ * Determine if the scanner is sitting on the start of a declaration.
+ * Input:
+ *	needId	0	no identifier
+ *		1	identifier optional
+ *		2	must have identifier
+ */
+
+int Parser::isDeclaration(Token *t, int needId, enum TOK endtok, Token **pt)
+{
+    //printf("isDeclaration(needId = %d)\n", needId);
+    int haveId = 0;
+
+#if DMDV2
+    if ((t->value == TOKconst || t->value == TOKinvariant) &&
+	peek(t)->value != TOKlparen)
+    {	/* const type
+	 * invariant type
+	 */
+	t = peek(t);
+    }
+#endif
+
+    if (!isBasicType(&t))
+	return FALSE;
+    if (!isDeclarator(&t, &haveId, endtok))
+	return FALSE;
+    if ( needId == 1 ||
+	(needId == 0 && !haveId) ||
+	(needId == 2 &&  haveId))
+    {	if (pt)
+	    *pt = t;
+	return TRUE;
+    }
+    else
+	return FALSE;
+}
+
+int Parser::isBasicType(Token **pt)
+{
+    // This code parallels parseBasicType()
+    Token *t = *pt;
+    Token *t2;
+    int parens;
+
+    switch (t->value)
+    {
+	CASE_BASIC_TYPES:
+	    t = peek(t);
+	    break;
+
+	case TOKidentifier:
+	    t = peek(t);
+	    if (t->value == TOKnot)
+	    {
+		goto L4;
+	    }
+	    goto L3;
+	    while (1)
+	    {
+	L2:
+		t = peek(t);
+	L3:
+		if (t->value == TOKdot)
+		{
+	Ldot:
+		    t = peek(t);
+		    if (t->value != TOKidentifier)
+			goto Lfalse;
+		    t = peek(t);
+		    if (t->value != TOKnot)
+			goto L3;
+	L4:
+		    t = peek(t);
+		    if (t->value != TOKlparen)
+			goto Lfalse;
+		    if (!skipParens(t, &t))
+			goto Lfalse;
+		}
+		else
+		    break;
+	    }
+	    break;
+
+	case TOKdot:
+	    goto Ldot;
+
+	case TOKtypeof:
+	    /* typeof(exp).identifier...
+	     */
+	    t = peek(t);
+	    if (t->value != TOKlparen)
+		goto Lfalse;
+	    if (!skipParens(t, &t))
+		goto Lfalse;
+	    goto L2;
+
+	default:
+	    goto Lfalse;
+    }
+    *pt = t;
+    //printf("is\n");
+    return TRUE;
+
+Lfalse:
+    //printf("is not\n");
+    return FALSE;
+}
+
+int Parser::isDeclarator(Token **pt, int *haveId, enum TOK endtok)
+{   // This code parallels parseDeclarator()
+    Token *t = *pt;
+    int parens;
+
+    //printf("Parser::isDeclarator()\n");
+    //t->print();
+    if (t->value == TOKassign)
+	return FALSE;
+
+    while (1)
+    {
+	parens = FALSE;
+	switch (t->value)
+	{
+	    case TOKmul:
+	    //case TOKand:
+		t = peek(t);
+		continue;
+
+	    case TOKlbracket:
+		t = peek(t);
+		if (t->value == TOKrbracket)
+		{
+		    t = peek(t);
+		}
+		else if (isDeclaration(t, 0, TOKrbracket, &t))
+		{   // It's an associative array declaration
+		    t = peek(t);
+		}
+		else
+		{
+		    // [ expression ]
+		    // [ expression .. expression ]
+		    if (!isExpression(&t))
+			return FALSE;
+		    if (t->value == TOKslice)
+		    {	t = peek(t);
+			if (!isExpression(&t))
+			    return FALSE;
+		    }
+		    if (t->value != TOKrbracket)
+			return FALSE;
+		    t = peek(t);
+		}
+		continue;
+
+	    case TOKidentifier:
+		if (*haveId)
+		    return FALSE;
+		*haveId = TRUE;
+		t = peek(t);
+		break;
+
+	    case TOKlparen:
+		t = peek(t);
+
+		if (t->value == TOKrparen)
+		    return FALSE;		// () is not a declarator
+
+		/* Regard ( identifier ) as not a declarator
+		 * BUG: what about ( *identifier ) in
+		 *	f(*p)(x);
+		 * where f is a class instance with overloaded () ?
+		 * Should we just disallow C-style function pointer declarations?
+		 */
+		if (t->value == TOKidentifier)
+		{   Token *t2 = peek(t);
+		    if (t2->value == TOKrparen)
+			return FALSE;
+		}
+
+
+		if (!isDeclarator(&t, haveId, TOKrparen))
+		    return FALSE;
+		t = peek(t);
+		parens = TRUE;
+		break;
+
+	    case TOKdelegate:
+	    case TOKfunction:
+		t = peek(t);
+		if (!isParameters(&t))
+		    return FALSE;
+		continue;
+	}
+	break;
+    }
+
+    while (1)
+    {
+	switch (t->value)
+	{
+#if CARRAYDECL
+	    case TOKlbracket:
+		parens = FALSE;
+		t = peek(t);
+		if (t->value == TOKrbracket)
+		{
+		    t = peek(t);
+		}
+		else if (isDeclaration(t, 0, TOKrbracket, &t))
+		{   // It's an associative array declaration
+		    t = peek(t);
+		}
+		else
+		{
+		    // [ expression ]
+		    if (!isExpression(&t))
+			return FALSE;
+		    if (t->value != TOKrbracket)
+			return FALSE;
+		    t = peek(t);
+		}
+		continue;
+#endif
+
+	    case TOKlparen:
+		parens = FALSE;
+		if (!isParameters(&t))
+		    return FALSE;
+#if DMDV2
+		while (1)
+		{
+		    switch (t->value)
+		    {
+			case TOKconst:
+			case TOKinvariant:
+			case TOKimmutable:
+			case TOKshared:
+			case TOKpure:
+			case TOKnothrow:
+			    t = peek(t);
+			    continue;
+			default:
+			    break;
+		    }
+		    break;
+		}
+#endif
+		continue;
+
+	    // Valid tokens that follow a declaration
+	    case TOKrparen:
+	    case TOKrbracket:
+	    case TOKassign:
+	    case TOKcomma:
+	    case TOKsemicolon:
+	    case TOKlcurly:
+	    case TOKin:
+		// The !parens is to disallow unnecessary parentheses
+		if (!parens && (endtok == TOKreserved || endtok == t->value))
+		{   *pt = t;
+		    return TRUE;
+		}
+		return FALSE;
+
+	    default:
+		return FALSE;
+	}
+    }
+}
+
+
+int Parser::isParameters(Token **pt)
+{   // This code parallels parseParameters()
+    Token *t = *pt;
+    int tmp;
+
+    //printf("isParameters()\n");
+    if (t->value != TOKlparen)
+	return FALSE;
+
+    t = peek(t);
+    while (1)
+    {
+	switch (t->value)
+	{
+	    case TOKrparen:
+		break;
+
+	    case TOKdotdotdot:
+		t = peek(t);
+		break;
+
+	    case TOKin:
+	    case TOKout:
+	    case TOKinout:
+	    case TOKref:
+	    case TOKlazy:
+		t = peek(t);
+	    default:
+		if (!isBasicType(&t))
+		    return FALSE;
+		tmp = FALSE;
+		if (t->value != TOKdotdotdot &&
+		    !isDeclarator(&t, &tmp, TOKreserved))
+		    return FALSE;
+		if (t->value == TOKassign)
+		{   t = peek(t);
+		    if (!isExpression(&t))
+			return FALSE;
+		}
+		if (t->value == TOKdotdotdot)
+		{
+		    t = peek(t);
+		    break;
+		}
+		if (t->value == TOKcomma)
+		{   t = peek(t);
+		    continue;
+		}
+		break;
+	}
+	break;
+    }
+    if (t->value != TOKrparen)
+	return FALSE;
+    t = peek(t);
+    *pt = t;
+    return TRUE;
+}
+
+int Parser::isExpression(Token **pt)
+{
+    // This is supposed to determine if something is an expression.
+    // What it actually does is scan until a closing right bracket
+    // is found.
+
+    Token *t = *pt;
+    int brnest = 0;
+    int panest = 0;
+
+    for (;; t = peek(t))
+    {
+	switch (t->value)
+	{
+	    case TOKlbracket:
+		brnest++;
+		continue;
+
+	    case TOKrbracket:
+		if (--brnest >= 0)
+		    continue;
+		break;
+
+	    case TOKlparen:
+		panest++;
+		continue;
+
+	    case TOKcomma:
+		if (brnest || panest)
+		    continue;
+		break;
+
+	    case TOKrparen:
+		if (--panest >= 0)
+		    continue;
+		break;
+
+	    case TOKslice:
+		if (brnest)
+		    continue;
+		break;
+
+	    case TOKeof:
+		return FALSE;
+
+	    default:
+		continue;
+	}
+	break;
+    }
+
+    *pt = t;
+    return TRUE;
+}
+
+/**********************************************
+ * Skip over
+ *	instance foo.bar(parameters...)
+ * Output:
+ *	if (pt), *pt is set to the token following the closing )
+ * Returns:
+ *	1	it's valid instance syntax
+ *	0	invalid instance syntax
+ */
+
+int Parser::isTemplateInstance(Token *t, Token **pt)
+{
+    t = peek(t);
+    if (t->value != TOKdot)
+    {
+	if (t->value != TOKidentifier)
+	    goto Lfalse;
+	t = peek(t);
+    }
+    while (t->value == TOKdot)
+    {
+	t = peek(t);
+	if (t->value != TOKidentifier)
+	    goto Lfalse;
+	t = peek(t);
+    }
+    if (t->value != TOKlparen)
+	goto Lfalse;
+
+    // Skip over the template arguments
+    while (1)
+    {
+	while (1)
+	{
+	    t = peek(t);
+	    switch (t->value)
+	    {
+		case TOKlparen:
+		    if (!skipParens(t, &t))
+			goto Lfalse;
+		    continue;
+		case TOKrparen:
+		    break;
+		case TOKcomma:
+		    break;
+		case TOKeof:
+		case TOKsemicolon:
+		    goto Lfalse;
+		default:
+		    continue;
+	    }
+	    break;
+	}
+
+	if (t->value != TOKcomma)
+	    break;
+    }
+    if (t->value != TOKrparen)
+	goto Lfalse;
+    t = peek(t);
+    if (pt)
+	*pt = t;
+    return 1;
+
+Lfalse:
+    return 0;
+}
+
+/*******************************************
+ * Skip parens, brackets.
+ * Input:
+ *	t is on opening (
+ * Output:
+ *	*pt is set to closing token, which is ')' on success
+ * Returns:
+ *	!=0	successful
+ *	0	some parsing error
+ */
+
+int Parser::skipParens(Token *t, Token **pt)
+{
+    int parens = 0;
+
+    while (1)
+    {
+	switch (t->value)
+	{
+	    case TOKlparen:
+		parens++;
+		break;
+
+	    case TOKrparen:
+		parens--;
+		if (parens < 0)
+		    goto Lfalse;
+		if (parens == 0)
+		    goto Ldone;
+		break;
+
+	    case TOKeof:
+	    case TOKsemicolon:
+		goto Lfalse;
+
+	     default:
+		break;
+	}
+	t = peek(t);
+    }
+
+  Ldone:
+    if (*pt)
+	*pt = t;
+    return 1;
+
+  Lfalse:
+    return 0;
+}
+
+/********************************* Expression Parser ***************************/
+
+Expression *Parser::parsePrimaryExp()
+{   Expression *e;
+    Type *t;
+    Identifier *id;
+    enum TOK save;
+    Loc loc = this->loc;
+
+    //printf("parsePrimaryExp(): loc = %d\n", loc.linnum);
+    switch (token.value)
+    {
+	case TOKidentifier:
+	    id = token.ident;
+	    nextToken();
+	    if (token.value == TOKnot && peek(&token)->value == TOKlparen)
+	    {	// identifier!(template-argument-list)
+		TemplateInstance *tempinst;
+
+		tempinst = new TemplateInstance(loc, id);
+		nextToken();
+		tempinst->tiargs = parseTemplateArgumentList();
+		e = new ScopeExp(loc, tempinst);
+	    }
+	    else
+		e = new IdentifierExp(loc, id);
+	    break;
+
+	case TOKdollar:
+	    if (!inBrackets)
+		error("'$' is valid only inside [] of index or slice");
+	    e = new DollarExp(loc);
+	    nextToken();
+	    break;
+
+	case TOKdot:
+	    // Signal global scope '.' operator with "" identifier
+	    e = new IdentifierExp(loc, Id::empty);
+	    break;
+
+	case TOKthis:
+	    e = new ThisExp(loc);
+	    nextToken();
+	    break;
+
+	case TOKsuper:
+	    e = new SuperExp(loc);
+	    nextToken();
+	    break;
+
+	case TOKint32v:
+	    e = new IntegerExp(loc, (d_int32)token.int64value, Type::tint32);
+	    nextToken();
+	    break;
+
+	case TOKuns32v:
+	    e = new IntegerExp(loc, (d_uns32)token.uns64value, Type::tuns32);
+	    nextToken();
+	    break;
+
+	case TOKint64v:
+	    e = new IntegerExp(loc, token.int64value, Type::tint64);
+	    nextToken();
+	    break;
+
+	case TOKuns64v:
+	    e = new IntegerExp(loc, token.uns64value, Type::tuns64);
+	    nextToken();
+	    break;
+
+	case TOKfloat32v:
+	    e = new RealExp(loc, token.float80value, Type::tfloat32);
+	    nextToken();
+	    break;
+
+	case TOKfloat64v:
+	    e = new RealExp(loc, token.float80value, Type::tfloat64);
+	    nextToken();
+	    break;
+
+	case TOKfloat80v:
+	    e = new RealExp(loc, token.float80value, Type::tfloat80);
+	    nextToken();
+	    break;
+
+	case TOKimaginary32v:
+	    e = new RealExp(loc, token.float80value, Type::timaginary32);
+	    nextToken();
+	    break;
+
+	case TOKimaginary64v:
+	    e = new RealExp(loc, token.float80value, Type::timaginary64);
+	    nextToken();
+	    break;
+
+	case TOKimaginary80v:
+	    e = new RealExp(loc, token.float80value, Type::timaginary80);
+	    nextToken();
+	    break;
+
+	case TOKnull:
+	    e = new NullExp(loc);
+	    nextToken();
+	    break;
+
+#if DMDV2
+	case TOKfile:
+	{   char *s = loc.filename ? loc.filename : mod->ident->toChars();
+	    e = new StringExp(loc, s, strlen(s), 0);
+	    nextToken();
+	    break;
+	}
+
+	case TOKline:
+	    e = new IntegerExp(loc, loc.linnum, Type::tint32);
+	    nextToken();
+	    break;
+#endif
+
+	case TOKtrue:
+	    e = new IntegerExp(loc, 1, Type::tbool);
+	    nextToken();
+	    break;
+
+	case TOKfalse:
+	    e = new IntegerExp(loc, 0, Type::tbool);
+	    nextToken();
+	    break;
+
+	case TOKcharv:
+	    e = new IntegerExp(loc, (d_uns8)token.uns64value, Type::tchar);
+	    nextToken();
+	    break;
+
+	case TOKwcharv:
+	    e = new IntegerExp(loc, (d_uns16)token.uns64value, Type::twchar);
+	    nextToken();
+	    break;
+
+	case TOKdcharv:
+	    e = new IntegerExp(loc, (d_uns32)token.uns64value, Type::tdchar);
+	    nextToken();
+	    break;
+
+	case TOKstring:
+	{   unsigned char *s;
+	    unsigned len;
+	    unsigned char postfix;
+
+	    // cat adjacent strings
+	    s = token.ustring;
+	    len = token.len;
+	    postfix = token.postfix;
+	    while (1)
+	    {
+		nextToken();
+		if (token.value == TOKstring)
+		{   unsigned len1;
+		    unsigned len2;
+		    unsigned char *s2;
+
+		    if (token.postfix)
+		    {	if (token.postfix != postfix)
+			    error("mismatched string literal postfixes '%c' and '%c'", postfix, token.postfix);
+			postfix = token.postfix;
+		    }
+
+		    len1 = len;
+		    len2 = token.len;
+		    len = len1 + len2;
+		    s2 = (unsigned char *)mem.malloc((len + 1) * sizeof(unsigned char));
+		    memcpy(s2, s, len1 * sizeof(unsigned char));
+		    memcpy(s2 + len1, token.ustring, (len2 + 1) * sizeof(unsigned char));
+		    s = s2;
+		}
+		else
+		    break;
+	    }
+	    e = new StringExp(loc, s, len, postfix);
+	    break;
+	}
+
+	CASE_BASIC_TYPES_X(t):
+	    nextToken();
+	L1:
+	    check(TOKdot, t->toChars());
+	    if (token.value != TOKidentifier)
+	    {   error("found '%s' when expecting identifier following '%s.'", token.toChars(), t->toChars());
+		goto Lerr;
+	    }
+	    e = typeDotIdExp(loc, t, token.ident);
+	    nextToken();
+	    break;
+
+	case TOKtypeof:
+	{   Expression *exp;
+
+	    nextToken();
+	    check(TOKlparen);
+	    exp = parseExpression();
+	    check(TOKrparen);
+	    t = new TypeTypeof(loc, exp);
+	    e = new TypeExp(loc, t);
+	    break;
+	}
+
+	case TOKtypeid:
+	{   Type *t;
+
+	    nextToken();
+	    check(TOKlparen, "typeid");
+	    t = parseBasicType();
+	    t = parseDeclarator(t,NULL);	// ( type )
+	    check(TOKrparen);
+	    e = new TypeidExp(loc, t);
+	    break;
+	}
+
+#if DMDV2
+	case TOKtraits:
+	{   /* __traits(identifier, args...)
+	     */
+	    Identifier *ident;
+	    Objects *args = NULL;
+
+	    nextToken();
+	    check(TOKlparen);
+	    if (token.value != TOKidentifier)
+	    {   error("__traits(identifier, args...) expected");
+		goto Lerr;
+	    }
+	    ident = token.ident;
+	    nextToken();
+	    if (token.value == TOKcomma)
+		args = parseTemplateArgumentList2();	// __traits(identifier, args...)
+	    else
+		check(TOKrparen);		// __traits(identifier)
+
+	    e = new TraitsExp(loc, ident, args);
+	    break;
+	}
+#endif
+
+	case TOKis:
+	{   Type *targ;
+	    Identifier *ident = NULL;
+	    Type *tspec = NULL;
+	    enum TOK tok = TOKreserved;
+	    enum TOK tok2 = TOKreserved;
+	    Loc loc = this->loc;
+
+	    nextToken();
+	    if (token.value == TOKlparen)
+	    {
+		nextToken();
+		targ = parseBasicType();
+		targ = parseDeclarator(targ, &ident);
+		if (token.value == TOKcolon || token.value == TOKequal)
+		{
+		    tok = token.value;
+		    nextToken();
+		    if (tok == TOKequal &&
+			(token.value == TOKtypedef ||
+			 token.value == TOKstruct ||
+			 token.value == TOKunion ||
+			 token.value == TOKclass ||
+			 token.value == TOKsuper ||
+			 token.value == TOKenum ||
+			 token.value == TOKinterface ||
+#if DMDV2
+			 token.value == TOKconst && peek(&token)->value == TOKrparen ||
+			 token.value == TOKinvariant && peek(&token)->value == TOKrparen ||
+			 token.value == TOKimmutable && peek(&token)->value == TOKrparen ||
+			 token.value == TOKshared && peek(&token)->value == TOKrparen ||
+#endif
+			 token.value == TOKfunction ||
+			 token.value == TOKdelegate ||
+			 token.value == TOKreturn))
+		    {
+			tok2 = token.value;
+			nextToken();
+		    }
+		    else
+		    {
+			tspec = parseBasicType();
+			tspec = parseDeclarator(tspec, NULL);
+		    }
+		}
+		check(TOKrparen);
+	    }
+	    else
+	    {   error("(type identifier : specialization) expected following is");
+		goto Lerr;
+	    }
+	    e = new IsExp(loc, targ, ident, tok, tspec, tok2);
+	    break;
+	}
+
+	case TOKassert:
+	{   Expression *msg = NULL;
+
+	    nextToken();
+	    check(TOKlparen, "assert");
+	    e = parseAssignExp();
+	    if (token.value == TOKcomma)
+	    {	nextToken();
+		msg = parseAssignExp();
+	    }
+	    check(TOKrparen);
+	    e = new AssertExp(loc, e, msg);
+	    break;
+	}
+
+	case TOKmixin:
+	{
+	    nextToken();
+	    check(TOKlparen, "mixin");
+	    e = parseAssignExp();
+	    check(TOKrparen);
+	    e = new CompileExp(loc, e);
+	    break;
+	}
+
+	case TOKimport:
+	{
+	    nextToken();
+	    check(TOKlparen, "import");
+	    e = parseAssignExp();
+	    check(TOKrparen);
+	    e = new FileExp(loc, e);
+	    break;
+	}
+
+	case TOKlparen:
+	    if (peekPastParen(&token)->value == TOKlcurly)
+	    {	// (arguments) { statements... }
+		save = TOKdelegate;
+		goto case_delegate;
+	    }
+	    // ( expression )
+	    nextToken();
+	    e = parseExpression();
+	    check(loc, TOKrparen);
+	    break;
+
+	case TOKlbracket:
+	{   /* Parse array literals and associative array literals:
+	     *	[ value, value, value ... ]
+	     *	[ key:value, key:value, key:value ... ]
+	     */
+	    Expressions *values = new Expressions();
+	    Expressions *keys = NULL;
+
+	    nextToken();
+	    if (token.value != TOKrbracket)
+	    {
+		while (token.value != TOKeof)
+		{
+		    Expression *e = parseAssignExp();
+		    if (token.value == TOKcolon && (keys || values->dim == 0))
+		    {	nextToken();
+			if (!keys)
+			    keys = new Expressions();
+			keys->push(e);
+			e = parseAssignExp();
+		    }
+		    else if (keys)
+		    {	error("'key:value' expected for associative array literal");
+			delete keys;
+			keys = NULL;
+		    }
+		    values->push(e);
+		    if (token.value == TOKrbracket)
+			break;
+		    check(TOKcomma);
+		}
+	    }
+	    check(TOKrbracket);
+
+	    if (keys)
+		e = new AssocArrayLiteralExp(loc, keys, values);
+	    else
+		e = new ArrayLiteralExp(loc, values);
+	    break;
+	}
+
+	case TOKlcurly:
+	    // { statements... }
+	    save = TOKdelegate;
+	    goto case_delegate;
+
+	case TOKfunction:
+	case TOKdelegate:
+	    save = token.value;
+	    nextToken();
+	case_delegate:
+	{
+	    /* function type(parameters) { body }
+	     * delegate type(parameters) { body }
+	     */
+	    Arguments *arguments;
+	    int varargs;
+	    FuncLiteralDeclaration *fd;
+	    Type *t;
+
+	    if (token.value == TOKlcurly)
+	    {
+		t = NULL;
+		varargs = 0;
+		arguments = new Arguments();
+	    }
+	    else
+	    {
+		if (token.value == TOKlparen)
+		    t = NULL;
+		else
+		{
+		    t = parseBasicType();
+		    t = parseBasicType2(t);	// function return type
+		}
+		arguments = parseParameters(&varargs);
+	    }
+	    t = new TypeFunction(arguments, t, varargs, linkage);
+	    fd = new FuncLiteralDeclaration(loc, 0, t, save, NULL);
+	    parseContracts(fd);
+	    e = new FuncExp(loc, fd);
+	    break;
+	}
+
+	default:
+	    error("expression expected, not '%s'", token.toChars());
+	Lerr:
+	    // Anything for e, as long as it's not NULL
+	    e = new IntegerExp(loc, 0, Type::tint32);
+	    nextToken();
+	    break;
+    }
+    return parsePostExp(e);
+}
+
+Expression *Parser::parsePostExp(Expression *e)
+{
+    Loc loc;
+
+    while (1)
+    {
+	loc = this->loc;
+	switch (token.value)
+	{
+	    case TOKdot:
+		nextToken();
+		if (token.value == TOKidentifier)
+		{   Identifier *id = token.ident;
+
+		    nextToken();
+		    if (token.value == TOKnot && peek(&token)->value == TOKlparen)
+		    {   // identifier!(template-argument-list)
+			TemplateInstance *tempinst;
+
+			tempinst = new TemplateInstance(loc, id);
+			nextToken();
+			tempinst->tiargs = parseTemplateArgumentList();
+			e = new DotTemplateInstanceExp(loc, e, tempinst);
+		    }
+		    else
+			e = new DotIdExp(loc, e, id);
+		    continue;
+		}
+		else if (token.value == TOKnew)
+		{
+		    e = parseNewExp(e);
+		    continue;
+		}
+		else
+		    error("identifier expected following '.', not '%s'", token.toChars());
+		break;
+
+	    case TOKplusplus:
+		e = new PostExp(TOKplusplus, loc, e);
+		break;
+
+	    case TOKminusminus:
+		e = new PostExp(TOKminusminus, loc, e);
+		break;
+
+	    case TOKlparen:
+		e = new CallExp(loc, e, parseArguments());
+		continue;
+
+	    case TOKlbracket:
+	    {	// array dereferences:
+		//	array[index]
+		//	array[]
+		//	array[lwr .. upr]
+		Expression *index;
+		Expression *upr;
+
+		inBrackets++;
+		nextToken();
+		if (token.value == TOKrbracket)
+		{   // array[]
+		    e = new SliceExp(loc, e, NULL, NULL);
+		    nextToken();
+		}
+		else
+		{
+		    index = parseAssignExp();
+		    if (token.value == TOKslice)
+		    {	// array[lwr .. upr]
+			nextToken();
+			upr = parseAssignExp();
+			e = new SliceExp(loc, e, index, upr);
+		    }
+		    else
+		    {	// array[index, i2, i3, i4, ...]
+			Expressions *arguments = new Expressions();
+			arguments->push(index);
+			if (token.value == TOKcomma)
+			{
+			    nextToken();
+			    while (1)
+			    {   Expression *arg;
+
+				arg = parseAssignExp();
+				arguments->push(arg);
+				if (token.value == TOKrbracket)
+				    break;
+				check(TOKcomma);
+			    }
+			}
+			e = new ArrayExp(loc, e, arguments);
+		    }
+		    check(TOKrbracket);
+		    inBrackets--;
+		}
+		continue;
+	    }
+
+	    default:
+		return e;
+	}
+	nextToken();
+    }
+}
+
+Expression *Parser::parseUnaryExp()
+{   Expression *e;
+    Loc loc = this->loc;
+
+    switch (token.value)
+    {
+	case TOKand:
+	    nextToken();
+	    e = parseUnaryExp();
+	    e = new AddrExp(loc, e);
+	    break;
+
+	case TOKplusplus:
+	    nextToken();
+	    e = parseUnaryExp();
+	    e = new AddAssignExp(loc, e, new IntegerExp(loc, 1, Type::tint32));
+	    break;
+
+	case TOKminusminus:
+	    nextToken();
+	    e = parseUnaryExp();
+	    e = new MinAssignExp(loc, e, new IntegerExp(loc, 1, Type::tint32));
+	    break;
+
+	case TOKmul:
+	    nextToken();
+	    e = parseUnaryExp();
+	    e = new PtrExp(loc, e);
+	    break;
+
+	case TOKmin:
+	    nextToken();
+	    e = parseUnaryExp();
+	    e = new NegExp(loc, e);
+	    break;
+
+	case TOKadd:
+	    nextToken();
+	    e = parseUnaryExp();
+	    e = new UAddExp(loc, e);
+	    break;
+
+	case TOKnot:
+	    nextToken();
+	    e = parseUnaryExp();
+	    e = new NotExp(loc, e);
+	    break;
+
+	case TOKtilde:
+	    nextToken();
+	    e = parseUnaryExp();
+	    e = new ComExp(loc, e);
+	    break;
+
+	case TOKdelete:
+	    nextToken();
+	    e = parseUnaryExp();
+	    e = new DeleteExp(loc, e);
+	    break;
+
+	case TOKnew:
+	    e = parseNewExp(NULL);
+	    break;
+
+	case TOKcast:				// cast(type) expression
+	{   Type *t;
+
+	    nextToken();
+	    check(TOKlparen);
+	    t = parseBasicType();
+	    t = parseDeclarator(t,NULL);	// ( type )
+	    check(TOKrparen);
+
+	    e = parseUnaryExp();
+	    e = new CastExp(loc, e, t);
+	    break;
+	}
+
+	case TOKlparen:
+	{   Token *tk;
+
+	    tk = peek(&token);
+#if CCASTSYNTAX
+	    // If cast
+	    if (isDeclaration(tk, 0, TOKrparen, &tk))
+	    {
+		tk = peek(tk);		// skip over right parenthesis
+		switch (tk->value)
+		{
+		    case TOKnot:
+			tk = peek(tk);
+			if (tk->value == TOKis)	// !is
+			    break;
+		    case TOKdot:
+		    case TOKplusplus:
+		    case TOKminusminus:
+		    case TOKdelete:
+		    case TOKnew:
+		    case TOKlparen:
+		    case TOKidentifier:
+		    case TOKthis:
+		    case TOKsuper:
+		    case TOKint32v:
+		    case TOKuns32v:
+		    case TOKint64v:
+		    case TOKuns64v:
+		    case TOKfloat32v:
+		    case TOKfloat64v:
+		    case TOKfloat80v:
+		    case TOKimaginary32v:
+		    case TOKimaginary64v:
+		    case TOKimaginary80v:
+		    case TOKnull:
+		    case TOKtrue:
+		    case TOKfalse:
+		    case TOKcharv:
+		    case TOKwcharv:
+		    case TOKdcharv:
+		    case TOKstring:
+#if 0
+		    case TOKtilde:
+		    case TOKand:
+		    case TOKmul:
+		    case TOKmin:
+		    case TOKadd:
+#endif
+		    case TOKfunction:
+		    case TOKdelegate:
+		    case TOKtypeof:
+#if DMDV2
+		    case TOKfile:
+		    case TOKline:
+#endif
+		    CASE_BASIC_TYPES:		// (type)int.size
+		    {	// (type) una_exp
+			Type *t;
+
+			nextToken();
+			t = parseBasicType();
+			t = parseDeclarator(t,NULL);
+			check(TOKrparen);
+
+			// if .identifier
+			if (token.value == TOKdot)
+			{
+			    nextToken();
+			    if (token.value != TOKidentifier)
+			    {   error("Identifier expected following (type).");
+				return NULL;
+			    }
+			    e = typeDotIdExp(loc, t, token.ident);
+			    nextToken();
+			    e = parsePostExp(e);
+			}
+			else
+			{
+			    e = parseUnaryExp();
+			    e = new CastExp(loc, e, t);
+			    error("C style cast illegal, use %s", e->toChars());
+			}
+			return e;
+		    }
+		}
+	    }
+#endif
+	    e = parsePrimaryExp();
+	    break;
+	}
+	default:
+	    e = parsePrimaryExp();
+	    break;
+    }
+    assert(e);
+    return e;
+}
+
+Expression *Parser::parseMulExp()
+{   Expression *e;
+    Expression *e2;
+    Loc loc = this->loc;
+
+    e = parseUnaryExp();
+    while (1)
+    {
+	switch (token.value)
+	{
+	    case TOKmul: nextToken(); e2 = parseUnaryExp(); e = new MulExp(loc,e,e2); continue;
+	    case TOKdiv:   nextToken(); e2 = parseUnaryExp(); e = new DivExp(loc,e,e2); continue;
+	    case TOKmod:  nextToken(); e2 = parseUnaryExp(); e = new ModExp(loc,e,e2); continue;
+
+	    default:
+		break;
+	}
+	break;
+    }
+    return e;
+}
+
+Expression *Parser::parseAddExp()
+{   Expression *e;
+    Expression *e2;
+    Loc loc = this->loc;
+
+    e = parseMulExp();
+    while (1)
+    {
+	switch (token.value)
+	{
+	    case TOKadd:    nextToken(); e2 = parseMulExp(); e = new AddExp(loc,e,e2); continue;
+	    case TOKmin:    nextToken(); e2 = parseMulExp(); e = new MinExp(loc,e,e2); continue;
+	    case TOKtilde:  nextToken(); e2 = parseMulExp(); e = new CatExp(loc,e,e2); continue;
+
+	    default:
+		break;
+	}
+	break;
+    }
+    return e;
+}
+
+Expression *Parser::parseShiftExp()
+{   Expression *e;
+    Expression *e2;
+    Loc loc = this->loc;
+
+    e = parseAddExp();
+    while (1)
+    {
+	switch (token.value)
+	{
+	    case TOKshl:  nextToken(); e2 = parseAddExp(); e = new ShlExp(loc,e,e2);  continue;
+	    case TOKshr:  nextToken(); e2 = parseAddExp(); e = new ShrExp(loc,e,e2);  continue;
+	    case TOKushr: nextToken(); e2 = parseAddExp(); e = new UshrExp(loc,e,e2); continue;
+
+	    default:
+		break;
+	}
+	break;
+    }
+    return e;
+}
+
+Expression *Parser::parseRelExp()
+{   Expression *e;
+    Expression *e2;
+    enum TOK op;
+    Loc loc = this->loc;
+
+    e = parseShiftExp();
+    while (1)
+    {
+	switch (token.value)
+	{
+	    case TOKlt:
+	    case TOKle:
+	    case TOKgt:
+	    case TOKge:
+	    case TOKunord:
+	    case TOKlg:
+	    case TOKleg:
+	    case TOKule:
+	    case TOKul:
+	    case TOKuge:
+	    case TOKug:
+	    case TOKue:
+		op = token.value;
+		nextToken();
+		e2 = parseShiftExp();
+		e = new CmpExp(op, loc, e, e2);
+		continue;
+
+	    case TOKin:
+		nextToken();
+		e2 = parseShiftExp();
+		e = new InExp(loc, e, e2);
+		continue;
+
+	    default:
+		break;
+	}
+	break;
+    }
+    return e;
+}
+
+Expression *Parser::parseEqualExp()
+{   Expression *e;
+    Expression *e2;
+    Token *t;
+    Loc loc = this->loc;
+
+    e = parseRelExp();
+    while (1)
+    {	enum TOK value = token.value;
+
+	switch (value)
+	{
+	    case TOKequal:
+	    case TOKnotequal:
+		nextToken();
+		e2 = parseRelExp();
+		e = new EqualExp(value, loc, e, e2);
+		continue;
+
+	    case TOKidentity:
+		error("'===' is no longer legal, use 'is' instead");
+		goto L1;
+
+	    case TOKnotidentity:
+		error("'!==' is no longer legal, use '!is' instead");
+		goto L1;
+
+	    case TOKis:
+		value = TOKidentity;
+		goto L1;
+
+	    case TOKnot:
+		// Attempt to identify '!is'
+		t = peek(&token);
+		if (t->value != TOKis)
+		    break;
+		nextToken();
+		value = TOKnotidentity;
+		goto L1;
+
+	    L1:
+		nextToken();
+		e2 = parseRelExp();
+		e = new IdentityExp(value, loc, e, e2);
+		continue;
+
+	    default:
+		break;
+	}
+	break;
+    }
+    return e;
+}
+
+Expression *Parser::parseCmpExp()
+{   Expression *e;
+    Expression *e2;
+    Token *t;
+    Loc loc = this->loc;
+
+    e = parseShiftExp();
+    enum TOK op = token.value;
+
+    switch (op)
+    {
+	case TOKequal:
+	case TOKnotequal:
+	    nextToken();
+	    e2 = parseShiftExp();
+	    e = new EqualExp(op, loc, e, e2);
+	    break;
+
+	case TOKis:
+	    op = TOKidentity;
+	    goto L1;
+
+	case TOKnot:
+	    // Attempt to identify '!is'
+	    t = peek(&token);
+	    if (t->value != TOKis)
+		break;
+	    nextToken();
+	    op = TOKnotidentity;
+	    goto L1;
+
+	L1:
+	    nextToken();
+	    e2 = parseShiftExp();
+	    e = new IdentityExp(op, loc, e, e2);
+	    break;
+
+	case TOKlt:
+	case TOKle:
+	case TOKgt:
+	case TOKge:
+	case TOKunord:
+	case TOKlg:
+	case TOKleg:
+	case TOKule:
+	case TOKul:
+	case TOKuge:
+	case TOKug:
+	case TOKue:
+	    nextToken();
+	    e2 = parseShiftExp();
+	    e = new CmpExp(op, loc, e, e2);
+	    break;
+
+	case TOKin:
+	    nextToken();
+	    e2 = parseShiftExp();
+	    e = new InExp(loc, e, e2);
+	    break;
+
+	default:
+	    break;
+    }
+    return e;
+}
+
+Expression *Parser::parseAndExp()
+{   Expression *e;
+    Expression *e2;
+    Loc loc = this->loc;
+
+    if (global.params.Dversion == 1)
+    {
+	e = parseEqualExp();
+	while (token.value == TOKand)
+	{
+	    nextToken();
+	    e2 = parseEqualExp();
+	    e = new AndExp(loc,e,e2);
+	    loc = this->loc;
+	}
+    }
+    else
+    {
+	e = parseCmpExp();
+	while (token.value == TOKand)
+	{
+	    nextToken();
+	    e2 = parseCmpExp();
+	    e = new AndExp(loc,e,e2);
+	    loc = this->loc;
+	}
+    }
+    return e;
+}
+
+Expression *Parser::parseXorExp()
+{   Expression *e;
+    Expression *e2;
+    Loc loc = this->loc;
+
+    e = parseAndExp();
+    while (token.value == TOKxor)
+    {
+	nextToken();
+	e2 = parseAndExp();
+	e = new XorExp(loc, e, e2);
+    }
+    return e;
+}
+
+Expression *Parser::parseOrExp()
+{   Expression *e;
+    Expression *e2;
+    Loc loc = this->loc;
+
+    e = parseXorExp();
+    while (token.value == TOKor)
+    {
+	nextToken();
+	e2 = parseXorExp();
+	e = new OrExp(loc, e, e2);
+    }
+    return e;
+}
+
+Expression *Parser::parseAndAndExp()
+{   Expression *e;
+    Expression *e2;
+    Loc loc = this->loc;
+
+    e = parseOrExp();
+    while (token.value == TOKandand)
+    {
+	nextToken();
+	e2 = parseOrExp();
+	e = new AndAndExp(loc, e, e2);
+    }
+    return e;
+}
+
+Expression *Parser::parseOrOrExp()
+{   Expression *e;
+    Expression *e2;
+    Loc loc = this->loc;
+
+    e = parseAndAndExp();
+    while (token.value == TOKoror)
+    {
+	nextToken();
+	e2 = parseAndAndExp();
+	e = new OrOrExp(loc, e, e2);
+    }
+    return e;
+}
+
+Expression *Parser::parseCondExp()
+{   Expression *e;
+    Expression *e1;
+    Expression *e2;
+    Loc loc = this->loc;
+
+    e = parseOrOrExp();
+    if (token.value == TOKquestion)
+    {
+	nextToken();
+	e1 = parseExpression();
+	check(TOKcolon);
+	e2 = parseCondExp();
+	e = new CondExp(loc, e, e1, e2);
+    }
+    return e;
+}
+
+Expression *Parser::parseAssignExp()
+{   Expression *e;
+    Expression *e2;
+    Loc loc;
+
+    e = parseCondExp();
+    while (1)
+    {
+	loc = this->loc;
+	switch (token.value)
+	{
+#define X(tok,ector) \
+	    case tok:  nextToken(); e2 = parseAssignExp(); e = new ector(loc,e,e2); continue;
+
+	    X(TOKassign,    AssignExp);
+	    X(TOKaddass,    AddAssignExp);
+	    X(TOKminass,    MinAssignExp);
+	    X(TOKmulass,    MulAssignExp);
+	    X(TOKdivass,    DivAssignExp);
+	    X(TOKmodass,    ModAssignExp);
+	    X(TOKandass,    AndAssignExp);
+	    X(TOKorass,     OrAssignExp);
+	    X(TOKxorass,    XorAssignExp);
+	    X(TOKshlass,    ShlAssignExp);
+	    X(TOKshrass,    ShrAssignExp);
+	    X(TOKushrass,   UshrAssignExp);
+	    X(TOKcatass,    CatAssignExp);
+
+#undef X
+	    default:
+		break;
+	}
+	break;
+    }
+    return e;
+}
+
+Expression *Parser::parseExpression()
+{   Expression *e;
+    Expression *e2;
+    Loc loc = this->loc;
+
+    //printf("Parser::parseExpression() loc = %d\n", loc.linnum);
+    e = parseAssignExp();
+    while (token.value == TOKcomma)
+    {
+	nextToken();
+	e2 = parseAssignExp();
+	e = new CommaExp(loc, e, e2);
+	loc = this->loc;
+    }
+    return e;
+}
+
+
+/*************************
+ * Collect argument list.
+ * Assume current token is '(' or '['.
+ */
+
+Expressions *Parser::parseArguments()
+{   // function call
+    Expressions *arguments;
+    Expression *arg;
+    enum TOK endtok;
+
+    arguments = new Expressions();
+    if (token.value == TOKlbracket)
+	endtok = TOKrbracket;
+    else
+	endtok = TOKrparen;
+
+    {
+	nextToken();
+	if (token.value != endtok)
+	{
+	    while (1)
+	    {
+		arg = parseAssignExp();
+		arguments->push(arg);
+		if (token.value == endtok)
+		    break;
+		check(TOKcomma);
+	    }
+	}
+	check(endtok);
+    }
+    return arguments;
+}
+
+/*******************************************
+ */
+
+Expression *Parser::parseNewExp(Expression *thisexp)
+{   Type *t;
+    Expressions *newargs;
+    Expressions *arguments = NULL;
+    Expression *e;
+    Loc loc = this->loc;
+
+    nextToken();
+    newargs = NULL;
+    if (token.value == TOKlparen)
+    {
+	newargs = parseArguments();
+    }
+
+    // An anonymous nested class starts with "class"
+    if (token.value == TOKclass)
+    {
+	nextToken();
+	if (token.value == TOKlparen)
+	    arguments = parseArguments();
+
+	BaseClasses *baseclasses = NULL;
+	if (token.value != TOKlcurly)
+	    baseclasses = parseBaseClasses();
+
+	Identifier *id = NULL;
+	ClassDeclaration *cd = new ClassDeclaration(loc, id, baseclasses);
+
+	if (token.value != TOKlcurly)
+	{   error("{ members } expected for anonymous class");
+	    cd->members = NULL;
+	}
+	else
+	{
+	    nextToken();
+	    Array *decl = parseDeclDefs(0);
+	    if (token.value != TOKrcurly)
+		error("class member expected");
+	    nextToken();
+	    cd->members = decl;
+	}
+
+	e = new NewAnonClassExp(loc, thisexp, newargs, cd, arguments);
+
+	return e;
+    }
+
+#if LTORARRAYDECL
+    t = parseBasicType();
+    t = parseBasicType2(t);
+    if (t->ty == Taarray)
+    {
+	Type *index = ((TypeAArray *)t)->index;
+
+	Expression *e = index->toExpression();
+	if (e)
+	{   arguments = new Expressions();
+	    arguments->push(e);
+	    t = new TypeDArray(t->next);
+	}
+	else
+	{
+	    error("need size of rightmost array, not type %s", index->toChars());
+	    return new NullExp(loc);
+	}
+    }
+    else if (t->ty == Tsarray)
+    {
+	TypeSArray *tsa = (TypeSArray *)t;
+	Expression *e = tsa->dim;
+
+	arguments = new Expressions();
+	arguments->push(e);
+	t = new TypeDArray(t->next);
+    }
+    else if (token.value == TOKlparen)
+    {
+	arguments = parseArguments();
+    }
+#else
+    t = parseBasicType();
+    while (token.value == TOKmul)
+    {   t = new TypePointer(t);
+	nextToken();
+    }
+    if (token.value == TOKlbracket)
+    {
+	Expression *e;
+
+	nextToken();
+	e = parseAssignExp();
+	arguments = new Array();
+	arguments->push(e);
+	check(TOKrbracket);
+	t = parseDeclarator(t, NULL);
+	t = new TypeDArray(t);
+    }
+    else if (token.value == TOKlparen)
+	arguments = parseArguments();
+#endif
+    e = new NewExp(loc, thisexp, newargs, t, arguments);
+    return e;
+}
+
+/**********************************************
+ */
+
+void Parser::addComment(Dsymbol *s, unsigned char *blockComment)
+{
+    s->addComment(combineComments(blockComment, token.lineComment));
+    token.lineComment = NULL;
+}
+
+
+/********************************* ***************************/
+
--- a/dmd/root/async.c	Fri Nov 06 21:51:41 2009 +0100
+++ b/dmd/root/async.c	Fri Nov 06 23:58:01 2009 +0100
@@ -1,177 +1,182 @@
-
-#define _MT 1
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <assert.h>
-
-#if _WIN32
-
-#include <windows.h>
-#include <stdio.h>
-#include <errno.h>
-#include <process.h>
-
-#include "root.h"
-#include "rmem.h"
-
-static unsigned __stdcall startthread(void *p);
-
-struct FileData
-{
-    File *file;
-    int result;
-    HANDLE event;
-};
-
-struct AsyncRead
-{
-    static AsyncRead *create(size_t nfiles);
-    void addFile(File *file);
-    void start();
-    int read(size_t i);
-    static void dispose(AsyncRead *);
-
-    HANDLE hThread;
-
-    size_t filesdim;
-    size_t filesmax;
-    FileData files[1];
-};
-
-
-AsyncRead *AsyncRead::create(size_t nfiles)
-{
-    AsyncRead *aw = (AsyncRead *)mem.calloc(1, sizeof(AsyncRead) +
-				(nfiles - 1) * sizeof(FileData));
-    aw->filesmax = nfiles;
-    return aw;
-}
-
-void AsyncRead::addFile(File *file)
-{
-    //printf("addFile(file = %p)\n", file);
-    //printf("filesdim = %d, filesmax = %d\n", filesdim, filesmax);
-    assert(filesdim < filesmax);
-    files[filesdim].file = file;
-    files[filesdim].event = CreateEvent(NULL, TRUE, FALSE, NULL);
-    ResetEvent(files[filesdim].event);
-    filesdim++;
-}
-
-void AsyncRead::start()
-{
-    unsigned threadaddr;
-    hThread = (HANDLE) _beginthreadex(NULL,
-	0,
-	&startthread,
-	this,
-	0,
-	(unsigned *)&threadaddr);
-
-    if (hThread)
-    {
-	SetThreadPriority(hThread, THREAD_PRIORITY_HIGHEST);
-    }
-    else
-    {
-	assert(0);
-    }
-}
-
-int AsyncRead::read(size_t i)
-{
-    FileData *f = &files[i];
-    WaitForSingleObject(f->event, INFINITE);
-    Sleep(0);			// give up time slice
-    return f->result;
-}
-
-void AsyncRead::dispose(AsyncRead *aw)
-{
-    delete aw;
-}
-
-
-
-unsigned __stdcall startthread(void *p)
-{
-    AsyncRead *aw = (AsyncRead *)p;
-
-    for (size_t i = 0; i < aw->filesdim; i++)
-    {	FileData *f = &aw->files[i];
-
-	f->result = f->file->read();
-	SetEvent(f->event);
-    }
-    _endthreadex(EXIT_SUCCESS);
-    return EXIT_SUCCESS;		// if skidding
-}
-
-#else
-
-#include <stdio.h>
-#include <errno.h>
-
-#include "root.h"
-#include "rmem.h"
-
-struct FileData
-{
-    File *file;
-    int result;
-    //HANDLE event;
-};
-
-struct AsyncRead
-{
-    static AsyncRead *create(size_t nfiles);
-    void addFile(File *file);
-    void start();
-    int read(size_t i);
-    static void dispose(AsyncRead *);
-
-    //HANDLE hThread;
-
-    size_t filesdim;
-    size_t filesmax;
-    FileData files[1];
-};
-
-
-AsyncRead *AsyncRead::create(size_t nfiles)
-{
-    AsyncRead *aw = (AsyncRead *)mem.calloc(1, sizeof(AsyncRead) +
-				(nfiles - 1) * sizeof(FileData));
-    aw->filesmax = nfiles;
-    return aw;
-}
-
-void AsyncRead::addFile(File *file)
-{
-    //printf("addFile(file = %p)\n", file);
-    //printf("filesdim = %d, filesmax = %d\n", filesdim, filesmax);
-    assert(filesdim < filesmax);
-    files[filesdim].file = file;
-    //files[filesdim].event = CreateEvent(NULL, TRUE, FALSE, NULL);
-    //ResetEvent(files[filesdim].event);
-    filesdim++;
-}
-
-void AsyncRead::start()
-{
-}
-
-int AsyncRead::read(size_t i)
-{
-    FileData *f = &files[i];
-    f->result = f->file->read();
-    return f->result;
-}
-
-void AsyncRead::dispose(AsyncRead *aw)
-{
-    delete aw;
-}
-
-#endif
+
+#define _MT 1
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+
+#if _WIN32
+
+#include <windows.h>
+#include <stdio.h>
+#include <errno.h>
+#include <process.h>
+
+#include "root.h"
+#include "rmem.h"
+
+static unsigned __stdcall startthread(void *p);
+
+struct FileData
+{
+    File *file;
+    int result;
+    HANDLE event;
+};
+
+struct AsyncRead
+{
+    static AsyncRead *create(size_t nfiles);
+    void addFile(File *file);
+    void start();
+    int read(size_t i);
+    static void dispose(AsyncRead *);
+
+    HANDLE hThread;
+
+    size_t filesdim;
+    size_t filesmax;
+    FileData files[1];
+};
+
+
+AsyncRead *AsyncRead::create(size_t nfiles)
+{
+    AsyncRead *aw = (AsyncRead *)mem.calloc(1, sizeof(AsyncRead) +
+				(nfiles - 1) * sizeof(FileData));
+    aw->filesmax = nfiles;
+    return aw;
+}
+
+void AsyncRead::addFile(File *file)
+{
+    //printf("addFile(file = %p)\n", file);
+    //printf("filesdim = %d, filesmax = %d\n", filesdim, filesmax);
+    assert(filesdim < filesmax);
+    files[filesdim].file = file;
+    files[filesdim].event = CreateEvent(NULL, TRUE, FALSE, NULL);
+    ResetEvent(files[filesdim].event);
+    filesdim++;
+}
+
+void AsyncRead::start()
+{
+    //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);
+	}
+    }
+}
+
+int AsyncRead::read(size_t i)
+{
+    FileData *f = &files[i];
+    WaitForSingleObject(f->event, INFINITE);
+    Sleep(0);			// give up time slice
+    return f->result;
+}
+
+void AsyncRead::dispose(AsyncRead *aw)
+{
+    delete aw;
+}
+
+
+
+unsigned __stdcall startthread(void *p)
+{
+    AsyncRead *aw = (AsyncRead *)p;
+
+    //printf("aw->filesdim = %p %d\n", aw, aw->filesdim);
+    for (size_t i = 0; i < aw->filesdim; i++)
+    {	FileData *f = &aw->files[i];
+
+	f->result = f->file->read();
+	SetEvent(f->event);
+    }
+    _endthreadex(EXIT_SUCCESS);
+    return EXIT_SUCCESS;		// if skidding
+}
+
+#else
+
+#include <stdio.h>
+#include <errno.h>
+
+#include "root.h"
+#include "rmem.h"
+
+struct FileData
+{
+    File *file;
+    int result;
+    //HANDLE event;
+};
+
+struct AsyncRead
+{
+    static AsyncRead *create(size_t nfiles);
+    void addFile(File *file);
+    void start();
+    int read(size_t i);
+    static void dispose(AsyncRead *);
+
+    //HANDLE hThread;
+
+    size_t filesdim;
+    size_t filesmax;
+    FileData files[1];
+};
+
+
+AsyncRead *AsyncRead::create(size_t nfiles)
+{
+    AsyncRead *aw = (AsyncRead *)mem.calloc(1, sizeof(AsyncRead) +
+				(nfiles - 1) * sizeof(FileData));
+    aw->filesmax = nfiles;
+    return aw;
+}
+
+void AsyncRead::addFile(File *file)
+{
+    //printf("addFile(file = %p)\n", file);
+    //printf("filesdim = %d, filesmax = %d\n", filesdim, filesmax);
+    assert(filesdim < filesmax);
+    files[filesdim].file = file;
+    //files[filesdim].event = CreateEvent(NULL, TRUE, FALSE, NULL);
+    //ResetEvent(files[filesdim].event);
+    filesdim++;
+}
+
+void AsyncRead::start()
+{
+}
+
+int AsyncRead::read(size_t i)
+{
+    FileData *f = &files[i];
+    f->result = f->file->read();
+    return f->result;
+}
+
+void AsyncRead::dispose(AsyncRead *aw)
+{
+    delete aw;
+}
+
+#endif
--- a/dmd/root/man.c	Fri Nov 06 21:51:41 2009 +0100
+++ b/dmd/root/man.c	Fri Nov 06 23:58:01 2009 +0100
@@ -37,7 +37,7 @@
     pid_t childpid;
     const char *args[3];
 
-    char *browser = getenv("BROWSER");
+    const char *browser = getenv("BROWSER");
     if (browser)
 	browser = strdup(browser);
     else
--- a/dmd/root/root.c	Fri Nov 06 21:51:41 2009 +0100
+++ b/dmd/root/root.c	Fri Nov 06 23:58:01 2009 +0100
@@ -415,10 +415,12 @@
 			continue;
 #endif
 
+#if 0
 		    case ' ':
 		    case '\t':		// tabs in filenames?
 			if (!instring)	// if not in string
 			    break;	// treat as end of path
+#endif
 		    default:
                     Ldefault:
 			buf.writeByte(c);
--- a/dmd/scope.c	Fri Nov 06 21:51:41 2009 +0100
+++ b/dmd/scope.c	Fri Nov 06 23:58:01 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;
@@ -282,7 +284,7 @@
 	    //printf("\t\tsc->scopesym = %p\n", sc->scopesym);
 	    if (!sc->scopesym->symtab)
 		sc->scopesym->symtab = new DsymbolTable();
-	    return sc->scopesym->symtab->insert(s);
+	    return sc->scopesym->symtabInsert(s);
 	}
     }
     assert(0);
--- a/dmd/scope.h	Fri Nov 06 21:51:41 2009 +0100
+++ b/dmd/scope.h	Fri Nov 06 23:58:01 2009 +0100
@@ -1,125 +1,126 @@
-
-// Copyright (c) 1999-2009 by Digital Mars
-// All Rights Reserved
-// written by Walter Bright
-// http://www.digitalmars.com
-// License for redistribution is by either the Artistic License
-// in artistic.txt, or the GNU General Public License in gnu.txt.
-// See the included readme.txt for details.
-
-#ifndef DMD_SCOPE_H
-#define DMD_SCOPE_H
-
-#ifdef __DMC__
-#pragma once
-#endif
-
-struct Dsymbol;
-struct ScopeDsymbol;
-struct Array;
-struct Identifier;
-struct Module;
-struct Statement;
-struct SwitchStatement;
-struct TryFinallyStatement;
-struct LabelStatement;
-struct ForeachStatement;
-struct ClassDeclaration;
-struct AggregateDeclaration;
-struct AnonymousAggregateDeclaration;
-struct FuncDeclaration;
-struct DocComment;
-struct TemplateInstance;
-
-#if IN_LLVM
-struct EnclosingHandler;
-struct AnonDeclaration;
-#endif
-
-#if __GNUC__
-// Requires a full definition for PROT and LINK
-#include "dsymbol.h"    // PROT
-#include "mars.h"       // LINK
-#else
-enum LINK;
-enum PROT;
-#endif 
-
-struct Scope
-{
-    Scope *enclosing;		// enclosing Scope
-
-    Module *module;		// Root module
-    ScopeDsymbol *scopesym;	// current symbol
-    ScopeDsymbol *sd;		// if in static if, and declaring new symbols,
-				// sd gets the addMember()
-    FuncDeclaration *func;	// function we are in
-    Dsymbol *parent;		// parent to use
-    LabelStatement *slabel;	// enclosing labelled statement
-    SwitchStatement *sw;	// enclosing switch statement
-    TryFinallyStatement *enclosingFinally;	// enclosing try finally statement; set inside its finally block
-    TemplateInstance *tinst;    // enclosing template instance
-    Statement *enclosingScopeExit; // enclosing statement that wants to do something on scope exit
-    Statement *sbreak;		// enclosing statement that supports "break"
-    Statement *scontinue;	// enclosing statement that supports "continue"
-    ForeachStatement *fes;	// if nested function for ForeachStatement, this is it
-    unsigned offset;		// next offset to use in aggregate
-    int inunion;		// we're processing members of a union
-    int incontract;		// we're inside contract code
-    int nofree;			// set if shouldn't free it
-    int noctor;			// set if constructor calls aren't allowed
-    int intypeof;		// in typeof(exp)
-    int parameterSpecialization; // if in template parameter specialization
-    int noaccesscheck;		// don't do access checks
-
-    unsigned callSuper;		// primitive flow analysis for constructors
-#define	CSXthis_ctor	1	// called this()
-#define CSXsuper_ctor	2	// called super()
-#define CSXthis		4	// referenced this
-#define CSXsuper	8	// referenced super
-#define CSXlabel	0x10	// seen a label
-#define CSXreturn	0x20	// seen a return statement
-#define CSXany_ctor	0x40	// either this() or super() was called
-
-    unsigned structalign;	// alignment for struct members
-    enum LINK linkage;		// linkage for external functions
-
-    enum PROT protection;	// protection for class members
-    int explicitProtection;	// set if in an explicit protection attribute
-
-    unsigned stc;		// storage class
-
-    unsigned flags;
-#define SCOPEctor	1	// constructor type
-#define SCOPEstaticif	2	// inside static if
-#define SCOPEfree	4	// is on free list
-
-    AnonymousAggregateDeclaration *anonAgg;	// for temporary analysis
-
-    DocComment *lastdc;		// documentation comment for last symbol at this scope
-    unsigned lastoffset;	// offset in docbuf of where to insert next dec
-    OutBuffer *docbuf;		// buffer for documentation output
-
-    static Scope *freelist;
-    static void *operator new(size_t sz);
-    static Scope *createGlobal(Module *module);
-
-    Scope();
-    Scope(Module *module);
-    Scope(Scope *enclosing);
-
-    Scope *push();
-    Scope *push(ScopeDsymbol *ss);
-    Scope *pop();
-
-    void mergeCallSuper(Loc loc, unsigned cs);
-
-    Dsymbol *search(Loc loc, Identifier *ident, Dsymbol **pscopesym);
-    Dsymbol *insert(Dsymbol *s);
-
-    ClassDeclaration *getClassScope();
-    AggregateDeclaration *getStructClassScope();
-    void setNoFree();
-};
-
-#endif /* DMD_SCOPE_H */
+
+// Copyright (c) 1999-2009 by Digital Mars
+// All Rights Reserved
+// written by Walter Bright
+// http://www.digitalmars.com
+// License for redistribution is by either the Artistic License
+// in artistic.txt, or the GNU General Public License in gnu.txt.
+// See the included readme.txt for details.
+
+#ifndef DMD_SCOPE_H
+#define DMD_SCOPE_H
+
+#ifdef __DMC__
+#pragma once
+#endif
+
+struct Dsymbol;
+struct ScopeDsymbol;
+struct Array;
+struct Identifier;
+struct Module;
+struct Statement;
+struct SwitchStatement;
+struct TryFinallyStatement;
+struct LabelStatement;
+struct ForeachStatement;
+struct ClassDeclaration;
+struct AggregateDeclaration;
+struct AnonymousAggregateDeclaration;
+struct FuncDeclaration;
+struct DocComment;
+struct TemplateInstance;
+
+#if IN_LLVM
+struct EnclosingHandler;
+struct AnonDeclaration;
+#endif
+
+#if __GNUC__
+// Requires a full definition for PROT and LINK
+#include "dsymbol.h"    // PROT
+#include "mars.h"       // LINK
+#else
+enum LINK;
+enum PROT;
+#endif 
+
+struct Scope
+{
+    Scope *enclosing;		// enclosing Scope
+
+    Module *module;		// Root module
+    ScopeDsymbol *scopesym;	// current symbol
+    ScopeDsymbol *sd;		// if in static if, and declaring new symbols,
+				// sd gets the addMember()
+    FuncDeclaration *func;	// function we are in
+    Dsymbol *parent;		// parent to use
+    LabelStatement *slabel;	// enclosing labelled statement
+    SwitchStatement *sw;	// enclosing switch statement
+    TryFinallyStatement *enclosingFinally;	// enclosing try finally statement; set inside its finally block
+    TemplateInstance *tinst;    // enclosing template instance
+    Statement *enclosingScopeExit; // enclosing statement that wants to do something on scope exit
+    Statement *sbreak;		// enclosing statement that supports "break"
+    Statement *scontinue;	// enclosing statement that supports "continue"
+    ForeachStatement *fes;	// if nested function for ForeachStatement, this is it
+    unsigned offset;		// next offset to use in aggregate
+    int inunion;		// we're processing members of a union
+    int incontract;		// we're inside contract code
+    int nofree;			// set if shouldn't free it
+    int noctor;			// set if constructor calls aren't allowed
+    int intypeof;		// in typeof(exp)
+    int parameterSpecialization; // if in template parameter specialization
+    int noaccesscheck;		// don't do access checks
+    int mustsemantic;		// cannot defer semantic()
+
+    unsigned callSuper;		// primitive flow analysis for constructors
+#define	CSXthis_ctor	1	// called this()
+#define CSXsuper_ctor	2	// called super()
+#define CSXthis		4	// referenced this
+#define CSXsuper	8	// referenced super
+#define CSXlabel	0x10	// seen a label
+#define CSXreturn	0x20	// seen a return statement
+#define CSXany_ctor	0x40	// either this() or super() was called
+
+    unsigned structalign;	// alignment for struct members
+    enum LINK linkage;		// linkage for external functions
+
+    enum PROT protection;	// protection for class members
+    int explicitProtection;	// set if in an explicit protection attribute
+
+    unsigned stc;		// storage class
+
+    unsigned flags;
+#define SCOPEctor	1	// constructor type
+#define SCOPEstaticif	2	// inside static if
+#define SCOPEfree	4	// is on free list
+
+    AnonymousAggregateDeclaration *anonAgg;	// for temporary analysis
+
+    DocComment *lastdc;		// documentation comment for last symbol at this scope
+    unsigned lastoffset;	// offset in docbuf of where to insert next dec
+    OutBuffer *docbuf;		// buffer for documentation output
+
+    static Scope *freelist;
+    static void *operator new(size_t sz);
+    static Scope *createGlobal(Module *module);
+
+    Scope();
+    Scope(Module *module);
+    Scope(Scope *enclosing);
+
+    Scope *push();
+    Scope *push(ScopeDsymbol *ss);
+    Scope *pop();
+
+    void mergeCallSuper(Loc loc, unsigned cs);
+
+    Dsymbol *search(Loc loc, Identifier *ident, Dsymbol **pscopesym);
+    Dsymbol *insert(Dsymbol *s);
+
+    ClassDeclaration *getClassScope();
+    AggregateDeclaration *getStructClassScope();
+    void setNoFree();
+};
+
+#endif /* DMD_SCOPE_H */
--- a/dmd/statement.c	Fri Nov 06 21:51:41 2009 +0100
+++ b/dmd/statement.c	Fri Nov 06 23:58:01 2009 +0100
@@ -29,6 +29,8 @@
 #include "template.h"
 #include "attrib.h"
 
+extern int os_critsecsize();
+
 /******************************** Statement ***************************/
 
 Statement::Statement(Loc loc)
@@ -144,6 +146,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
@@ -154,7 +163,7 @@
  *	*sfinally	code executed in finally block
  */
 
-void Statement::scopeCode(Statement **sentry, Statement **sexception, Statement **sfinally)
+void Statement::scopeCode(Scope *sc, Statement **sentry, Statement **sexception, Statement **sfinally)
 {
     //printf("Statement::scopeCode()\n");
     //print();
@@ -175,6 +184,22 @@
 }
 
 
+/******************************** PeelStatement ***************************/
+
+PeelStatement::PeelStatement(Statement *s)
+    : Statement(s->loc)
+{
+    this->s = s;
+}
+
+Statement *PeelStatement::semantic(Scope *sc)
+{
+    /* "peel" off this wrapper, and don't run semantic()
+     * on the result.
+     */
+    return s;
+}
+
 /******************************** ExpStatement ***************************/
 
 ExpStatement::ExpStatement(Loc loc, Expression *exp)
@@ -236,6 +261,11 @@
     return result;
 }
 
+int ExpStatement::isEmpty()
+{
+    return exp == NULL;
+}
+
 
 /******************************** CompileStatement ***************************/
 
@@ -315,7 +345,7 @@
     return ds;
 }
 
-void DeclarationStatement::scopeCode(Statement **sentry, Statement **sexception, Statement **sfinally)
+void DeclarationStatement::scopeCode(Scope *sc, Statement **sentry, Statement **sexception, Statement **sfinally)
 {
     //printf("DeclarationStatement::scopeCode()\n");
     //print();
@@ -333,7 +363,7 @@
 	    if (v)
 	    {	Expression *e;
 
-		e = v->callScopeDtor();
+		e = v->callScopeDtor(sc);
 		if (e)
 		{
 		    //printf("dtor is: "); e->print();
@@ -407,7 +437,7 @@
 		Statement *sexception;
 		Statement *sfinally;
 
-		s->scopeCode(&sentry, &sexception, &sfinally);
+		s->scopeCode(sc, &sentry, &sexception, &sfinally);
 		if (sentry)
 		{
 		    sentry = sentry->semantic(sc);
@@ -555,11 +585,14 @@
 //printf("%s\n", s->toChars());
 	    if (!(result & BEfallthru) && !s->comeFrom())
 	    {
-		s->warning("statement is not reachable");
+		if (s->blockExit() != BEhalt && !s->isEmpty())
+		    s->warning("statement is not reachable");
 	    }
-
-	    result &= ~BEfallthru;
-	    result |= s->blockExit();
+	    else
+	    {
+		result &= ~BEfallthru;
+		result |= s->blockExit();
+	    }
 	}
     }
     return result;
@@ -580,6 +613,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 ***************************/
 
@@ -813,7 +856,7 @@
 	    Statement *sexception;
 	    Statement *sfinally;
 
-	    statement->scopeCode(&sentry, &sexception, &sfinally);
+	    statement->scopeCode(sc, &sentry, &sexception, &sfinally);
 	    if (sfinally)
 	    {
 		//printf("adding sfinally\n");
@@ -848,12 +891,19 @@
     return statement ? statement->blockExit() : BEfallthru;
 }
 
+
 int ScopeStatement::comeFrom()
 {
     //printf("ScopeStatement::comeFrom()\n");
     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('{');
@@ -884,46 +934,12 @@
 
 Statement *WhileStatement::semantic(Scope *sc)
 {
-#if 0
-    if (condition->op == TOKmatch)
-    {
-	/* Rewrite while (condition) body as:
-	 *   if (condition)
-	 *     do
-	 *       body
-	 *     while ((_match = _match.opNext), _match);
-	 */
-
-	Expression *ew = new IdentifierExp(0, Id::_match);
-	ew = new DotIdExp(0, ew, Id::next);
-	ew = new AssignExp(0, new IdentifierExp(0, Id::_match), ew);
-	////ew = new EqualExp(TOKnotequal, 0, ew, new NullExp(0));
-	Expression *ev = new IdentifierExp(0, Id::_match);
-	//ev = new CastExp(0, ev, Type::tvoidptr);
-	ew = new CommaExp(0, ew, ev);
-	Statement *sw = new DoStatement(loc, body, ew);
-	Statement *si = new IfStatement(loc, condition, sw, NULL);
-	return si->semantic(sc);
-    }
-#endif
-
-    condition = condition->semantic(sc);
-    condition = resolveProperties(sc, condition);
-    condition = condition->optimize(WANTvalue);
-    condition = condition->checkToBoolean();
-
-    sc->noctor++;
-
-    Scope *scd = sc->push();
-    scd->sbreak = this;
-    scd->scontinue = this;
-    if (body)
-	body = body->semantic(scd);
-    scd->pop();
-
-    sc->noctor--;
-
-    return this;
+    /* Rewrite as a for(;condition;) loop
+     */
+
+    Statement *s = new ForStatement(loc, NULL, condition, NULL, body);
+    s = s->semantic(sc);
+    return s;
 }
 
 int WhileStatement::hasBreak()
@@ -938,11 +954,13 @@
 
 int WhileStatement::usesEH()
 {
+    assert(0);
     return body ? body->usesEH() : 0;
 }
 
 int WhileStatement::blockExit()
 {
+    assert(0);
     //printf("WhileStatement::blockExit(%p)\n", this);
 
     int result = BEnone;
@@ -973,6 +991,7 @@
 
 int WhileStatement::comeFrom()
 {
+    assert(0);
     if (body)
 	return body->comeFrom();
     return FALSE;
@@ -1124,6 +1143,7 @@
     if (increment)
     {	increment = increment->semantic(sc);
 	increment = resolveProperties(sc, increment);
+	increment = increment->optimize(0);
     }
 
     sc->sbreak = this;
@@ -1136,14 +1156,14 @@
     return this;
 }
 
-void ForStatement::scopeCode(Statement **sentry, Statement **sexception, Statement **sfinally)
+void ForStatement::scopeCode(Scope *sc, Statement **sentry, Statement **sexception, Statement **sfinally)
 {
     //printf("ForStatement::scopeCode()\n");
     //print();
     if (init)
-	init->scopeCode(sentry, sexception, sfinally);
+	init->scopeCode(sc, sentry, sexception, sfinally);
     else
-	Statement::scopeCode(sentry, sexception, sfinally);
+	Statement::scopeCode(sc, sentry, sexception, sfinally);
 }
 
 int ForStatement::hasBreak()
@@ -1173,6 +1193,10 @@
     if (condition)
     {	if (condition->canThrow())
 	    result |= BEthrow;
+	if (condition->isBool(TRUE))
+	    result &= ~BEfallthru;
+	else if (condition->isBool(FALSE))
+	    return result;
     }
     else
 	result &= ~BEfallthru;	// the body must do the exiting
@@ -1352,9 +1376,8 @@
 		error("no storage class for value %s", arg->ident->toChars());
 	    Dsymbol *var;
 	    if (te)
-	    {
-		if (e->type->toBasetype()->ty == Tfunction &&
-		    e->op == TOKvar)
+	    {	Type *tb = e->type->toBasetype();
+		if ((tb->ty == Tfunction || tb->ty == Tsarray) && e->op == TOKvar)
 		{   VarExp *ve = (VarExp *)e;
 		    var = new AliasDeclaration(loc, arg->ident, ve->var);
 		}
@@ -1439,29 +1462,79 @@
 	    for (size_t i = 0; i < dim; i++)
 	    {	// Declare args
 		Argument *arg = (Argument *)arguments->data[i];
+		Type *argtype = arg->type->semantic(loc, sc);
 		VarDeclaration *var;
 
-		var = new VarDeclaration(loc, arg->type, arg->ident, NULL);
+		var = new VarDeclaration(loc, argtype, arg->ident, NULL);
 		var->storage_class |= STCforeach;
 		var->storage_class |= arg->storageClass & (STCin | STCout | STCref);
-#if 1
-		DeclarationExp *de = new DeclarationExp(loc, var);
-		de->semantic(sc);
-#else
-		var->semantic(sc);
-		if (!sc->insert(var))
-		    error("%s already defined", var->ident->toChars());
-#endif
+
 		if (dim == 2 && i == 0)
 		    key = var;
 		else
 		    value = var;
+#if 0
+		DeclarationExp *de = new DeclarationExp(loc, var);
+		de->semantic(sc);
+#endif
 	    }
 
-	    sc->sbreak = this;
-	    sc->scontinue = this;
-	    body = body->semantic(sc);
-
+#if 1
+	{
+	     /* Convert to a ForStatement
+	      *   foreach (key, value; a) body =>
+	      *   for (T[] tmp = a[], size_t key; key < tmp.length; ++key)
+	      *   { T value = tmp[k]; body }
+	      *
+	      *   foreach_reverse (key, value; a) body =>
+	      *   for (T[] tmp = a[], size_t key = tmp.length; key--; )
+	      *   { T value = tmp[k]; body }
+	      */
+	    Identifier *id = Lexer::uniqueId("__aggr");
+	    ExpInitializer *ie = new ExpInitializer(loc, new SliceExp(loc, aggr, NULL, NULL));
+	    VarDeclaration *tmp = new VarDeclaration(loc, aggr->type->nextOf()->arrayOf(), id, ie);
+
+	    Expression *tmp_length = new DotIdExp(loc, new VarExp(loc, tmp), Id::length);
+
+	    if (!key)
+	    {
+		Identifier *id = Lexer::uniqueId("__key");
+		key = new VarDeclaration(loc, Type::tsize_t, id, NULL);
+	    }
+	    if (op == TOKforeach_reverse)
+		key->init = new ExpInitializer(loc, tmp_length);
+	    else
+		key->init = new ExpInitializer(loc, new IntegerExp(0));
+
+	    Statements *cs = new Statements();
+	    cs->push(new DeclarationStatement(loc, new DeclarationExp(loc, tmp)));
+	    cs->push(new DeclarationStatement(loc, new DeclarationExp(loc, key)));
+	    Statement *forinit = new CompoundDeclarationStatement(loc, cs);
+
+	    Expression *cond;
+	    if (op == TOKforeach_reverse)
+		// key--
+		cond = new PostExp(TOKminusminus, loc, new VarExp(loc, key));
+	    else
+		// key < tmp.length
+		cond = new CmpExp(TOKlt, loc, new VarExp(loc, key), tmp_length);
+
+	    Expression *increment = NULL;
+	    if (op == TOKforeach)
+		// key += 1
+		increment = new AddAssignExp(loc, new VarExp(loc, key), new IntegerExp(1));
+
+	    // T value = tmp[key];
+	    value->init = new ExpInitializer(loc, new IndexExp(loc, new VarExp(loc, tmp), new VarExp(loc, key)));
+	    Statement *ds = new DeclarationStatement(loc, new DeclarationExp(loc, value));
+
+	    body = new CompoundStatement(loc, ds, body);
+
+	    ForStatement *fs = new ForStatement(loc, forinit, cond, increment, body);
+	    s = fs->semantic(sc);
+	    break;
+	}
+#else
 	    if (!value->type->equals(tab->next))
 	    {
 		if (aggr->op == TOKstring)
@@ -1471,20 +1544,28 @@
 			tab->toChars(), value->type->toChars());
 	    }
 
-	    if (key && key->type->ty != Tint32 && key->type->ty != Tuns32)
+	    if (key)
 	    {
-		if (global.params.is64bit)
+		if (key->type->ty != Tint32 && key->type->ty != Tuns32)
 		{
-		    if (key->type->ty != Tint64 && key->type->ty != Tuns64)
-			error("foreach: key type must be int or uint, long or ulong, not %s", key->type->toChars());
+		    if (global.params.is64bit)
+		    {
+			if (key->type->ty != Tint64 && key->type->ty != Tuns64)
+			    error("foreach: key type must be int or uint, long or ulong, not %s", key->type->toChars());
+		    }
+		    else
+			error("foreach: key type must be int or uint, not %s", key->type->toChars());
 		}
-		else
-		    error("foreach: key type must be int or uint, not %s", key->type->toChars());
+
+		if (key->storage_class & (STCout | STCref))
+		    error("foreach: key cannot be out or ref");
 	    }
 
-	    if (key && key->storage_class & (STCout | STCref))
-		error("foreach: key cannot be out or ref");
+	    sc->sbreak = this;
+	    sc->scontinue = this;
+	    body = body->semantic(sc);
 	    break;
+#endif
 
 	case Taarray:
 	    taa = (TypeAArray *)tab;
@@ -1504,9 +1585,9 @@
 #if DMDV2
 	{   /* Look for range iteration, i.e. the properties
 	     * .empty, .next, .retreat, .head and .rear
-	     *    foreach (e; range) { ... }
+	     *    foreach (e; aggr) { ... }
 	     * translates to:
-	     *    for (auto __r = range; !__r.empty; __r.next)
+	     *    for (auto __r = aggr[]; !__r.empty; __r.next)
 	     *    {   auto e = __r.head;
 	     *        ...
 	     *    }
@@ -1523,7 +1604,7 @@
 		idnext = Id::Fnext;
 	    }
 	    else
-	    {	idhead = Id::Frear;
+	    {	idhead = Id::Ftoe;
 		idnext = Id::Fretreat;
 	    }
 	    Dsymbol *shead = search_function(ad, idhead);
@@ -1533,9 +1614,15 @@
 	    /* Generate a temporary __r and initialize it with the aggregate.
 	     */
 	    Identifier *id = Identifier::generateId("__r");
-	    VarDeclaration *r = new VarDeclaration(loc, NULL, id, new ExpInitializer(loc, aggr));
-	    r->semantic(sc);
+	    Expression *rinit = new SliceExp(loc, aggr, NULL, NULL);
+	    rinit = rinit->trySemantic(sc);
+	    if (!rinit)			// if application of [] failed
+		rinit = aggr;
+	    VarDeclaration *r = new VarDeclaration(loc, NULL, id, new ExpInitializer(loc, rinit));
+//	    r->semantic(sc);
+//printf("r: %s, init: %s\n", r->toChars(), r->init->toChars());
 	    Statement *init = new DeclarationStatement(loc, r);
+//printf("init: %s\n", init->toChars());
 
 	    // !__r.empty
 	    Expression *e = new VarExp(loc, r);
@@ -1551,11 +1638,11 @@
 	     */
 	    e = new VarExp(loc, r);
 	    Expression *einit = new DotIdExp(loc, e, idhead);
-	    einit = einit->semantic(sc);
+//	    einit = einit->semantic(sc);
 	    Argument *arg = (Argument *)arguments->data[0];
 	    VarDeclaration *ve = new VarDeclaration(loc, arg->type, arg->ident, new ExpInitializer(loc, einit));
 	    ve->storage_class |= STCforeach;
-	    ve->storage_class |= arg->storageClass & (STCin | STCout | STCref | STCconst | STCinvariant);
+	    ve->storage_class |= arg->storageClass & (STCin | STCout | STCref | STC_TYPECTOR);
 
 	    DeclarationExp *de = new DeclarationExp(loc, ve);
 
@@ -1563,6 +1650,12 @@
 		new DeclarationStatement(loc, de), this->body);
 
 	    s = new ForStatement(loc, init, condition, increment, body);
+#if 0
+	    printf("init: %s\n", init->toChars());
+	    printf("condition: %s\n", condition->toChars());
+	    printf("increment: %s\n", increment->toChars());
+	    printf("body: %s\n", body->toChars());
+#endif
 	    s = s->semantic(sc);
 	    break;
 	}
@@ -1837,6 +1930,7 @@
 
 	default:
 	    error("foreach: %s is not an aggregate type", aggr->type->toChars());
+	    s = NULL;	// error recovery
 	    break;
     }
     sc->noctor--;
@@ -1872,6 +1966,7 @@
     return result;
 }
 
+
 int ForeachStatement::comeFrom()
 {
     if (body)
@@ -1908,6 +2003,216 @@
     buf->writenl();
 }
 
+/**************************** ForeachRangeStatement ***************************/
+
+#if DMDV2
+
+ForeachRangeStatement::ForeachRangeStatement(Loc loc, enum TOK op, Argument *arg,
+	Expression *lwr, Expression *upr, Statement *body)
+    : Statement(loc)
+{
+    this->op = op;
+    this->arg = arg;
+    this->lwr = lwr;
+    this->upr = upr;
+    this->body = body;
+
+    this->key = NULL;
+}
+
+Statement *ForeachRangeStatement::syntaxCopy()
+{
+    ForeachRangeStatement *s = new ForeachRangeStatement(loc, op,
+	arg->syntaxCopy(),
+	lwr->syntaxCopy(),
+	upr->syntaxCopy(),
+	body ? body->syntaxCopy() : NULL);
+    return s;
+}
+
+Statement *ForeachRangeStatement::semantic(Scope *sc)
+{
+    //printf("ForeachRangeStatement::semantic() %p\n", this);
+    ScopeDsymbol *sym;
+    Statement *s = this;
+
+    lwr = lwr->semantic(sc);
+    lwr = resolveProperties(sc, lwr);
+    lwr = lwr->optimize(WANTvalue);
+    if (!lwr->type)
+    {
+	error("invalid range lower bound %s", lwr->toChars());
+	return this;
+    }
+
+    upr = upr->semantic(sc);
+    upr = resolveProperties(sc, upr);
+    upr = upr->optimize(WANTvalue);
+    if (!upr->type)
+    {
+	error("invalid range upper bound %s", upr->toChars());
+	return this;
+    }
+
+    if (arg->type)
+    {
+	arg->type = arg->type->semantic(loc, sc);
+	lwr = lwr->implicitCastTo(sc, arg->type);
+	upr = upr->implicitCastTo(sc, arg->type);
+    }
+    else
+    {
+	/* Must infer types from lwr and upr
+	 */
+	AddExp ea(loc, lwr, upr);
+	ea.typeCombine(sc);
+	arg->type = ea.type->mutableOf();
+	lwr = ea.e1;
+	upr = ea.e2;
+    }
+#if 1
+    /* Convert to a for loop:
+     *	foreach (key; lwr .. upr) =>
+     *	for (auto key = lwr, auto tmp = upr; key < tmp; ++key)
+     *
+     *	foreach_reverse (key; lwr .. upr) =>
+     *	for (auto tmp = lwr, auto key = upr; key-- > tmp;)
+     */
+
+    ExpInitializer *ie = new ExpInitializer(loc, (op == TOKforeach) ? lwr : upr);
+    key = new VarDeclaration(loc, arg->type, arg->ident, ie);
+
+    Identifier *id = Lexer::uniqueId("__limit");
+    ie = new ExpInitializer(loc, (op == TOKforeach) ? upr : lwr);
+    VarDeclaration *tmp = new VarDeclaration(loc, arg->type, id, ie);
+
+    Statements *cs = new Statements();
+    // Keep order of evaluation as lwr, then upr
+    if (op == TOKforeach)
+    {
+	cs->push(new DeclarationStatement(loc, new DeclarationExp(loc, key)));
+	cs->push(new DeclarationStatement(loc, new DeclarationExp(loc, tmp)));
+    }
+    else
+    {
+	cs->push(new DeclarationStatement(loc, new DeclarationExp(loc, tmp)));
+	cs->push(new DeclarationStatement(loc, new DeclarationExp(loc, key)));
+    }
+    Statement *forinit = new CompoundDeclarationStatement(loc, cs);
+
+    Expression *cond;
+    if (op == TOKforeach_reverse)
+    {	// key-- > tmp
+	cond = new PostExp(TOKminusminus, loc, new VarExp(loc, key));
+	cond = new CmpExp(TOKgt, loc, cond, new VarExp(loc, tmp));
+    }
+    else
+	// key < tmp
+	cond = new CmpExp(TOKlt, loc, new VarExp(loc, key), new VarExp(loc, tmp));
+
+    Expression *increment = NULL;
+    if (op == TOKforeach)
+	// key += 1
+	increment = new AddAssignExp(loc, new VarExp(loc, key), new IntegerExp(1));
+
+    ForStatement *fs = new ForStatement(loc, forinit, cond, increment, body);
+    s = fs->semantic(sc);
+    return s;
+#else
+    if (!arg->type->isscalar())
+	error("%s is not a scalar type", arg->type->toChars());
+
+    sym = new ScopeDsymbol();
+    sym->parent = sc->scopesym;
+    sc = sc->push(sym);
+
+    sc->noctor++;
+
+    key = new VarDeclaration(loc, arg->type, arg->ident, NULL);
+    DeclarationExp *de = new DeclarationExp(loc, key);
+    de->semantic(sc);
+
+    if (key->storage_class)
+	error("foreach range: key cannot have storage class");
+
+    sc->sbreak = this;
+    sc->scontinue = this;
+    body = body->semantic(sc);
+
+    sc->noctor--;
+    sc->pop();
+    return s;
+#endif
+}
+
+int ForeachRangeStatement::hasBreak()
+{
+    return TRUE;
+}
+
+int ForeachRangeStatement::hasContinue()
+{
+    return TRUE;
+}
+
+int ForeachRangeStatement::usesEH()
+{
+    assert(0);
+    return body->usesEH();
+}
+
+int ForeachRangeStatement::blockExit()
+{
+    assert(0);
+    int result = BEfallthru;
+
+    if (lwr && lwr->canThrow())
+	result |= BEthrow;
+    else if (upr && upr->canThrow())
+	result |= BEthrow;
+
+    if (body)
+    {
+	result |= body->blockExit() & ~(BEbreak | BEcontinue);
+    }
+    return result;
+}
+
+
+int ForeachRangeStatement::comeFrom()
+{
+    assert(0);
+    if (body)
+	return body->comeFrom();
+    return FALSE;
+}
+
+void ForeachRangeStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    buf->writestring(Token::toChars(op));
+    buf->writestring(" (");
+
+    if (arg->type)
+	arg->type->toCBuffer(buf, arg->ident, hgs);
+    else
+	buf->writestring(arg->ident->toChars());
+
+    buf->writestring("; ");
+    lwr->toCBuffer(buf, hgs);
+    buf->writestring(" .. ");
+    upr->toCBuffer(buf, hgs);
+    buf->writebyte(')');
+    buf->writenl();
+    buf->writebyte('{');
+    buf->writenl();
+    if (body)
+	body->toCBuffer(buf, hgs);
+    buf->writebyte('}');
+    buf->writenl();
+}
+
+#endif
+
 /******************************** IfStatement ***************************/
 
 IfStatement::IfStatement(Loc loc, Argument *arg, Expression *condition, Statement *ifbody, Statement *elsebody)
@@ -2029,6 +2334,7 @@
     return result;
 }
 
+
 void IfStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
 {
     buf->writestring("if (");
@@ -2181,10 +2487,10 @@
                 if (e->op == TOKstring)
                 {
                     StringExp *se = (StringExp *)e;
-                    fprintf(stdmsg, "%.*s", (int)se->len, (char*)se->string);
+                    fprintf(stdmsg, "%.*s", (int)se->len, (char *)se->string);
                 }
                 else
-		    error("string expected for message, not '%s'", e->toChars());
+		    fprintf(stdmsg, e->toChars());
             }
             fprintf(stdmsg, "\n");
         }
@@ -2225,7 +2531,28 @@
     {
         sc->func->allowInlining = true;
     }
-
+#if DMDV2
+    else if (ident == Id::startaddress)
+    {
+	if (!args || args->dim != 1)
+	    error("function name expected for start address");
+	else
+	{
+	    Expression *e = (Expression *)args->data[0];
+	    e = e->semantic(sc);
+	    e = e->optimize(WANTvalue | WANTinterpret);
+	    args->data[0] = (void *)e;
+	    Dsymbol *sa = getDsymbol(e);
+	    if (!sa || !sa->isFuncDeclaration())
+		error("function name expected for start address, not '%s'", e->toChars());
+	    if (body)
+	    {
+		body = body->semantic(sc);
+	    }
+	    return this;
+	}
+    }
+#endif
     else
         error("unrecognized pragma(%s)", ident->toChars());
 
@@ -2253,6 +2580,7 @@
     return result;
 }
 
+
 void PragmaStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
 {
     buf->writestring("pragma (");
@@ -2302,6 +2630,11 @@
     return NULL;
 }
 
+int StaticAssertStatement::blockExit()
+{
+    return BEfallthru;
+}
+
 void StaticAssertStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
 {
     sa->toCBuffer(buf, hgs);
@@ -2425,6 +2758,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;
 }
@@ -2457,6 +2821,7 @@
     return result;
 }
 
+
 void SwitchStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
 {
     buf->writestring("switch (");
@@ -2571,6 +2936,7 @@
     return statement->blockExit();
 }
 
+
 int CaseStatement::comeFrom()
 {
     return TRUE;
@@ -2585,6 +2951,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)
@@ -2640,6 +3085,7 @@
     return statement->blockExit();
 }
 
+
 int DefaultStatement::comeFrom()
 {
     return TRUE;
@@ -2678,6 +3124,7 @@
     return BEgoto;
 }
 
+
 void GotoDefaultStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
 {
     buf->writestring("goto default;\n");
@@ -2725,6 +3172,7 @@
     return BEgoto;
 }
 
+
 void GotoCaseStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
 {
     buf->writestring("goto case");
@@ -2748,6 +3196,7 @@
     return BEthrow;
 }
 
+
 void SwitchErrorStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
 {
     buf->writestring("SwitchErrorStatement::toCBuffer()");
@@ -2841,7 +3290,9 @@
 		fd->nrvo_can = 0;
 	    else if (fd->nrvo_var == NULL)
 	    {	if (!v->isDataseg() && !v->isParameter() && v->toParent2() == fd)
+		{   //printf("Setting nrvo to %s\n", v->toChars());
 		    fd->nrvo_var = v;
+		}
 		else
 		    fd->nrvo_can = 0;
 	    }
@@ -2944,6 +3395,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));
@@ -2960,6 +3412,7 @@
 	    VarExp *v = new VarExp(0, fd->vresult);
 
 	    exp = new AssignExp(loc, v, exp);
+	    exp->op = TOKconstruct;
 	    exp = exp->semantic(sc);
 	}
 	//exp->dump(0);
@@ -2996,7 +3449,7 @@
 	return gs;
     }
 
-    if (exp && tbret->ty == Tvoid && !fd->isMain())
+    if (exp && tbret->ty == Tvoid && !implicit0)
     {
 	/* Replace:
 	 *	return exp;
@@ -3004,8 +3457,9 @@
 	 *	exp; return;
 	 */
 	Statement *s = new ExpStatement(loc, exp);
+	exp = NULL;
+	s = s->semantic(sc);
 	loc = 0;
-	exp = NULL;
 	return new CompoundStatement(loc, s, this);
     }
 
@@ -3020,6 +3474,7 @@
     return result;
 }
 
+
 void ReturnStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
 {
     buf->printf("return ");
@@ -3112,6 +3567,7 @@
     return ident ? BEgoto : BEbreak;
 }
 
+
 void BreakStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
 {
     buf->writestring("break");
@@ -3213,6 +3669,7 @@
     return ident ? BEgoto : BEcontinue;
 }
 
+
 void ContinueStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
 {
     buf->writestring("continue");
@@ -3256,21 +3713,87 @@
 Statement *SynchronizedStatement::semantic(Scope *sc)
 {
     if (exp)
-    {	ClassDeclaration *cd;
-
+    {
 	exp = exp->semantic(sc);
 	exp = resolveProperties(sc, exp);
-	cd = exp->type->isClassHandle();
+	ClassDeclaration *cd = exp->type->isClassHandle();
 	if (!cd)
 	    error("can only synchronize on class objects, not '%s'", exp->type->toChars());
 	else if (cd->isInterfaceDeclaration())
-	{   Type *t = new TypeIdentifier(0, Id::Object);
+	{   /* Cast the interface to an object, as the object has the monitor,
+	     * not the interface.
+	     */
+	    Type *t = new TypeIdentifier(0, Id::Object);
 
 	    t = t->semantic(0, sc);
 	    exp = new CastExp(loc, exp, t);
 	    exp = exp->semantic(sc);
 	}
+
+#if 0
+	/* Rewrite as:
+	 *  auto tmp = exp;
+	 *  _d_monitorenter(tmp);
+	 *  try { body } finally { _d_monitorexit(tmp); }
+	 */
+	Identifier *id = Lexer::uniqueId("__sync");
+	ExpInitializer *ie = new ExpInitializer(loc, exp);
+	VarDeclaration *tmp = new VarDeclaration(loc, exp->type, id, ie);
+
+	Statements *cs = new Statements();
+	cs->push(new DeclarationStatement(loc, new DeclarationExp(loc, tmp)));
+
+	FuncDeclaration *fdenter = FuncDeclaration::genCfunc(Type::tvoid, Id::monitorenter);
+	Expression *e = new CallExp(loc, new VarExp(loc, fdenter), new VarExp(loc, tmp));
+	e->type = Type::tvoid;			// do not run semantic on e
+	cs->push(new ExpStatement(loc, e));
+
+	FuncDeclaration *fdexit = FuncDeclaration::genCfunc(Type::tvoid, Id::monitorexit);
+	e = new CallExp(loc, new VarExp(loc, fdexit), new VarExp(loc, tmp));
+	e->type = Type::tvoid;			// do not run semantic on e
+	Statement *s = new ExpStatement(loc, e);
+	s = new TryFinallyStatement(loc, body, s);
+	cs->push(s);
+
+	s = new CompoundStatement(loc, cs);
+	return s->semantic(sc);
+#endif
     }
+#if 0
+    else
+    {	/* Generate our own critical section, then rewrite as:
+	 *  __gshared byte[CriticalSection.sizeof] critsec;
+	 *  _d_criticalenter(critsec.ptr);
+	 *  try { body } finally { _d_criticalexit(critsec.ptr); }
+	 */
+	Identifier *id = Lexer::uniqueId("__critsec");
+	Type *t = new TypeSArray(Type::tint8, new IntegerExp(PTRSIZE +  os_critsecsize()));
+	VarDeclaration *tmp = new VarDeclaration(loc, t, id, NULL);
+	tmp->storage_class |= STCgshared | STCstatic;
+
+	Statements *cs = new Statements();
+	cs->push(new DeclarationStatement(loc, new DeclarationExp(loc, tmp)));
+
+	FuncDeclaration *fdenter = FuncDeclaration::genCfunc(Type::tvoid, Id::criticalenter);
+	Expression *e = new DotIdExp(loc, new VarExp(loc, tmp), Id::ptr);
+	e = e->semantic(sc);
+	e = new CallExp(loc, new VarExp(loc, fdenter), e);
+	e->type = Type::tvoid;			// do not run semantic on e
+	cs->push(new ExpStatement(loc, e));
+
+	FuncDeclaration *fdexit = FuncDeclaration::genCfunc(Type::tvoid, Id::criticalexit);
+	e = new DotIdExp(loc, new VarExp(loc, tmp), Id::ptr);
+	e = e->semantic(sc);
+	e = new CallExp(loc, new VarExp(loc, fdexit), e);
+	e->type = Type::tvoid;			// do not run semantic on e
+	Statement *s = new ExpStatement(loc, e);
+	s = new TryFinallyStatement(loc, body, s);
+	cs->push(s);
+
+	s = new CompoundStatement(loc, cs);
+	return s->semantic(sc);
+    }
+#endif
     if (body)
     {
 	Statement* oldScopeExit = sc->enclosingScopeExit;
@@ -3301,6 +3824,7 @@
     return body ? body->blockExit() : BEfallthru;
 }
 
+
 void SynchronizedStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
 {
     buf->writestring("synchronized");
@@ -3418,6 +3942,7 @@
     return result;
 }
 
+
 /******************************** TryCatchStatement ***************************/
 
 TryCatchStatement::TryCatchStatement(Loc loc, Statement *body, Array *catches)
@@ -3462,6 +3987,11 @@
 		error("catch at %s hides catch at %s", sj, si);
 	}
     }
+
+    if (!body || body->isEmpty())
+    {
+	return NULL;
+    }
     return this;
 }
 
@@ -3476,10 +4006,9 @@
 }
 
 int TryCatchStatement::blockExit()
-{   int result;
-
+{
     assert(body);
-    result = body->blockExit();
+    int result = body->blockExit();
 
     for (size_t i = 0; i < catches->dim; i++)
     {
@@ -3689,7 +4218,7 @@
     return (tok != TOKon_scope_success);
 }
 
-void OnScopeStatement::scopeCode(Statement **sentry, Statement **sexception, Statement **sfinally)
+void OnScopeStatement::scopeCode(Scope *sc, Statement **sentry, Statement **sexception, Statement **sfinally)
 {
     //printf("OnScopeStatement::scopeCode()\n");
     //print();
@@ -3770,6 +4299,7 @@
     return BEthrow;  // obviously
 }
 
+
 void ThrowStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
 {
     buf->printf("throw ");
@@ -3827,6 +4357,7 @@
     return statement ? statement->blockExit() : BEfallthru;
 }
 
+
 void VolatileStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
 {
     buf->writestring("volatile");
@@ -3892,6 +4423,7 @@
     return BEgoto;
 }
 
+
 void GotoStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
 {
     buf->writestring("goto ");
@@ -3983,6 +4515,7 @@
     return statement ? statement->blockExit() : BEfallthru;
 }
 
+
 int LabelStatement::comeFrom()
 {
     //printf("LabelStatement::comeFrom()\n");
--- a/dmd/statement.h	Fri Nov 06 21:51:41 2009 +0100
+++ b/dmd/statement.h	Fri Nov 06 23:58:01 2009 +0100
@@ -1,889 +1,919 @@
-
-// Compiler implementation of the D programming language
-// Copyright (c) 1999-2008 by Digital Mars
-// All Rights Reserved
-// written by Walter Bright
-// http://www.digitalmars.com
-// License for redistribution is by either the Artistic License
-// in artistic.txt, or the GNU General Public License in gnu.txt.
-// See the included readme.txt for details.
-
-#ifndef DMD_STATEMENT_H
-#define DMD_STATEMENT_H
-
-#ifdef __DMC__
-#pragma once
-#endif /* __DMC__ */
-
-#include "root.h"
-
-#include "arraytypes.h"
-#include "dsymbol.h"
-#include "lexer.h"
-
-struct OutBuffer;
-struct Scope;
-struct Expression;
-struct LabelDsymbol;
-struct Identifier;
-struct IfStatement;
-struct DeclarationStatement;
-struct DefaultStatement;
-struct VarDeclaration;
-struct Condition;
-struct Module;
-struct Token;
-struct InlineCostState;
-struct InlineDoState;
-struct InlineScanState;
-struct ReturnStatement;
-struct CompoundStatement;
-struct Argument;
-struct StaticAssert;
-struct AsmStatement;
-struct AsmBlockStatement;
-struct GotoStatement;
-struct ScopeStatement;
-struct TryCatchStatement;
-struct TryFinallyStatement;
-struct HdrGenState;
-struct InterState;
-struct CaseStatement;
-struct LabelStatement;
-struct VolatileStatement;
-struct SynchronizedStatement;
-
-enum TOK;
-
-namespace llvm
-{
-    class Value;
-    class BasicBlock;
-    class ConstantInt;
-}
-
-// Back end
-struct IRState;
-struct Blockx;
-#if IN_LLVM
-struct DValue;
-typedef DValue elem;
-#endif
-
-#if IN_GCC
-union tree_node; typedef union tree_node block;
-//union tree_node; typedef union tree_node elem;
-#else
-struct block;
-//struct elem;
-#endif
-struct code;
-
-/* How a statement exits; this is returned by blockExit()
- */
-enum BE
-{
-    BEnone =	 0,
-    BEfallthru = 1,
-    BEthrow =    2,
-    BEreturn =   4,
-    BEgoto =     8,
-    BEhalt =	 0x10,
-    BEbreak =	 0x20,
-    BEcontinue = 0x40,
-    BEany = (BEfallthru | BEthrow | BEreturn | BEgoto | BEhalt),
-};
-
-struct Statement : Object
-{
-    Loc loc;
-
-    Statement(Loc loc);
-    virtual Statement *syntaxCopy();
-
-    void print();
-    char *toChars();
-
-    void error(const char *format, ...) IS_PRINTF(2);
-    void warning(const char *format, ...) IS_PRINTF(2);
-    virtual void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-    virtual TryCatchStatement *isTryCatchStatement() { return NULL; }
-    virtual GotoStatement *isGotoStatement() { return NULL; }
-    virtual AsmStatement *isAsmStatement() { return NULL; }
-    virtual AsmBlockStatement *isAsmBlockStatement() { return NULL; }
-#ifdef _DH
-    int incontract;
-#endif
-    virtual ScopeStatement *isScopeStatement() { return NULL; }
-    virtual Statement *semantic(Scope *sc);
-    Statement *semanticScope(Scope *sc, Statement *sbreak, Statement *scontinue);
-    virtual int hasBreak();
-    virtual int hasContinue();
-    virtual int usesEH();
-    virtual int blockExit();
-    virtual int comeFrom();
-    virtual void scopeCode(Statement **sentry, Statement **sexit, Statement **sfinally);
-    virtual Statements *flatten(Scope *sc);
-    virtual Expression *interpret(InterState *istate);
-
-    virtual int inlineCost(InlineCostState *ics);
-    virtual Expression *doInline(InlineDoState *ids);
-    virtual Statement *inlineScan(InlineScanState *iss);
-
-    // Back end
-    virtual void toIR(IRState *irs);
-
-    // Avoid dynamic_cast
-    virtual DeclarationStatement *isDeclarationStatement() { return NULL; }
-    virtual CompoundStatement *isCompoundStatement() { return NULL; }
-    virtual ReturnStatement *isReturnStatement() { return NULL; }
-    virtual IfStatement *isIfStatement() { return NULL; }
-    virtual CaseStatement* isCaseStatement() { return NULL; }
-
-    // LDC
-    virtual void toNakedIR(IRState *irs);
-    virtual AsmBlockStatement* endsWithAsm();
-};
-
-struct ExpStatement : Statement
-{
-    Expression *exp;
-
-    ExpStatement(Loc loc, Expression *exp);
-    Statement *syntaxCopy();
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-    Statement *semantic(Scope *sc);
-    Expression *interpret(InterState *istate);
-    int blockExit();
-
-    int inlineCost(InlineCostState *ics);
-    Expression *doInline(InlineDoState *ids);
-    Statement *inlineScan(InlineScanState *iss);
-
-    void toIR(IRState *irs);
-
-    // LDC
-    void toNakedIR(IRState *irs);
-};
-
-struct CompileStatement : Statement
-{
-    Expression *exp;
-
-    CompileStatement(Loc loc, Expression *exp);
-    Statement *syntaxCopy();
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-    Statements *flatten(Scope *sc);
-    Statement *semantic(Scope *sc);
-};
-
-struct DeclarationStatement : ExpStatement
-{
-    // Doing declarations as an expression, rather than a statement,
-    // makes inlining functions much easier.
-
-    DeclarationStatement(Loc loc, Dsymbol *s);
-    DeclarationStatement(Loc loc, Expression *exp);
-    Statement *syntaxCopy();
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-    void scopeCode(Statement **sentry, Statement **sexit, Statement **sfinally);
-
-    DeclarationStatement *isDeclarationStatement() { return this; }
-};
-
-struct CompoundStatement : Statement
-{
-    Statements *statements;
-
-    CompoundStatement(Loc loc, Statements *s);
-    CompoundStatement(Loc loc, Statement *s1, Statement *s2);
-    virtual Statement *syntaxCopy();
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-    virtual Statement *semantic(Scope *sc);
-    int usesEH();
-    int blockExit();
-    int comeFrom();
-    virtual Statements *flatten(Scope *sc);
-    ReturnStatement *isReturnStatement();
-    Expression *interpret(InterState *istate);
-
-    int inlineCost(InlineCostState *ics);
-    Expression *doInline(InlineDoState *ids);
-    Statement *inlineScan(InlineScanState *iss);
-
-    virtual void toIR(IRState *irs);
-
-    // LDC
-    virtual void toNakedIR(IRState *irs);
-    virtual AsmBlockStatement* endsWithAsm();
-
-    virtual CompoundStatement *isCompoundStatement() { return this; }
-};
-
-struct CompoundDeclarationStatement : CompoundStatement
-{
-    CompoundDeclarationStatement(Loc loc, Statements *s);
-    Statement *syntaxCopy();
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-};
-
-/* The purpose of this is so that continue will go to the next
- * of the statements, and break will go to the end of the statements.
- */
-struct UnrolledLoopStatement : Statement
-{
-    Statements *statements;
-
-    UnrolledLoopStatement(Loc loc, Statements *statements);
-    Statement *syntaxCopy();
-    Statement *semantic(Scope *sc);
-    int hasBreak();
-    int hasContinue();
-    int usesEH();
-    int blockExit();
-    int comeFrom();
-    Expression *interpret(InterState *istate);
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-
-    int inlineCost(InlineCostState *ics);
-    Expression *doInline(InlineDoState *ids);
-    Statement *inlineScan(InlineScanState *iss);
-
-    void toIR(IRState *irs);
-};
-
-struct ScopeStatement : Statement
-{
-    Statement *statement;
-
-    ScopeStatement(Loc loc, Statement *s);
-    Statement *syntaxCopy();
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-    ScopeStatement *isScopeStatement() { return this; }
-    Statement *semantic(Scope *sc);
-    int hasBreak();
-    int hasContinue();
-    int usesEH();
-    int blockExit();
-    int comeFrom();
-    Expression *interpret(InterState *istate);
-
-    Statement *inlineScan(InlineScanState *iss);
-
-    void toIR(IRState *irs);
-};
-
-struct WhileStatement : Statement
-{
-    Expression *condition;
-    Statement *body;
-
-    WhileStatement(Loc loc, Expression *c, Statement *b);
-    Statement *syntaxCopy();
-    Statement *semantic(Scope *sc);
-    int hasBreak();
-    int hasContinue();
-    int usesEH();
-    int blockExit();
-    int comeFrom();
-    Expression *interpret(InterState *istate);
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-
-    Statement *inlineScan(InlineScanState *iss);
-
-    void toIR(IRState *irs);
-};
-
-struct DoStatement : Statement
-{
-    Statement *body;
-    Expression *condition;
-
-    DoStatement(Loc loc, Statement *b, Expression *c);
-    Statement *syntaxCopy();
-    Statement *semantic(Scope *sc);
-    int hasBreak();
-    int hasContinue();
-    int usesEH();
-    int blockExit();
-    int comeFrom();
-    Expression *interpret(InterState *istate);
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-
-    Statement *inlineScan(InlineScanState *iss);
-
-    void toIR(IRState *irs);
-};
-
-struct ForStatement : Statement
-{
-    Statement *init;
-    Expression *condition;
-    Expression *increment;
-    Statement *body;
-
-    ForStatement(Loc loc, Statement *init, Expression *condition, Expression *increment, Statement *body);
-    Statement *syntaxCopy();
-    Statement *semantic(Scope *sc);
-    void scopeCode(Statement **sentry, Statement **sexit, Statement **sfinally);
-    int hasBreak();
-    int hasContinue();
-    int usesEH();
-    int blockExit();
-    int comeFrom();
-    Expression *interpret(InterState *istate);
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-
-    Statement *inlineScan(InlineScanState *iss);
-
-    void toIR(IRState *irs);
-};
-
-struct ForeachStatement : Statement
-{
-    enum TOK op;		// TOKforeach or TOKforeach_reverse
-    Arguments *arguments;	// array of Argument*'s
-    Expression *aggr;
-    Statement *body;
-
-    VarDeclaration *key;
-    VarDeclaration *value;
-
-    FuncDeclaration *func;	// function we're lexically in
-
-    Array cases;	// put breaks, continues, gotos and returns here
-    Array gotos;	// forward referenced goto's go here
-
-    ForeachStatement(Loc loc, enum TOK op, Arguments *arguments, Expression *aggr, Statement *body);
-    Statement *syntaxCopy();
-    Statement *semantic(Scope *sc);
-    int hasBreak();
-    int hasContinue();
-    int usesEH();
-    int blockExit();
-    int comeFrom();
-    Expression *interpret(InterState *istate);
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-
-    Statement *inlineScan(InlineScanState *iss);
-
-    void toIR(IRState *irs);
-};
-
-#if DMDV2
-struct ForeachRangeStatement : Statement
-{
-    enum TOK op;		// TOKforeach or TOKforeach_reverse
-    Argument *arg;		// loop index variable
-    Expression *lwr;
-    Expression *upr;
-    Statement *body;
-
-    VarDeclaration *key;
-
-    ForeachRangeStatement(Loc loc, enum TOK op, Argument *arg,
-	Expression *lwr, Expression *upr, Statement *body);
-    Statement *syntaxCopy();
-    Statement *semantic(Scope *sc);
-    int hasBreak();
-    int hasContinue();
-    int usesEH();
-    int blockExit();
-    int comeFrom();
-    Expression *interpret(InterState *istate);
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-
-    Statement *inlineScan(InlineScanState *iss);
-
-    void toIR(IRState *irs);
-};
-#endif
-
-struct IfStatement : Statement
-{
-    Argument *arg;
-    Expression *condition;
-    Statement *ifbody;
-    Statement *elsebody;
-
-    VarDeclaration *match;	// for MatchExpression results
-
-    IfStatement(Loc loc, Argument *arg, Expression *condition, Statement *ifbody, Statement *elsebody);
-    Statement *syntaxCopy();
-    Statement *semantic(Scope *sc);
-    Expression *interpret(InterState *istate);
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-    int usesEH();
-    int blockExit();
-    IfStatement *isIfStatement() { return this; }
-
-    int inlineCost(InlineCostState *ics);
-    Expression *doInline(InlineDoState *ids);
-    Statement *inlineScan(InlineScanState *iss);
-
-    void toIR(IRState *irs);
-};
-
-struct ConditionalStatement : Statement
-{
-    Condition *condition;
-    Statement *ifbody;
-    Statement *elsebody;
-
-    ConditionalStatement(Loc loc, Condition *condition, Statement *ifbody, Statement *elsebody);
-    Statement *syntaxCopy();
-    Statement *semantic(Scope *sc);
-    Statements *flatten(Scope *sc);
-    int usesEH();
-    int blockExit();
-
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-};
-
-struct PragmaStatement : Statement
-{
-    Identifier *ident;
-    Expressions *args;		// array of Expression's
-    Statement *body;
-
-    PragmaStatement(Loc loc, Identifier *ident, Expressions *args, Statement *body);
-    Statement *syntaxCopy();
-    Statement *semantic(Scope *sc);
-    int usesEH();
-    int blockExit();
-
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-};
-
-struct StaticAssertStatement : Statement
-{
-    StaticAssert *sa;
-
-    StaticAssertStatement(StaticAssert *sa);
-    Statement *syntaxCopy();
-    Statement *semantic(Scope *sc);
-
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-};
-
-struct SwitchStatement : Statement
-{
-    Expression *condition;
-    Statement *body;
-
-    DefaultStatement *sdefault;
-
-    Array gotoCases;		// array of unresolved GotoCaseStatement's
-    Array *cases;		// array of CaseStatement's
-    int hasNoDefault;		// !=0 if no default statement
-    
-    // LDC
-    Statement *enclosingScopeExit;
-
-    SwitchStatement(Loc loc, Expression *c, Statement *b);
-    Statement *syntaxCopy();
-    Statement *semantic(Scope *sc);
-    int hasBreak();
-    int usesEH();
-    int blockExit();
-    Expression *interpret(InterState *istate);
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-
-    Statement *inlineScan(InlineScanState *iss);
-
-    void toIR(IRState *irs);
-};
-
-struct CaseStatement : Statement
-{
-    Expression *exp;
-    Statement *statement;
-    int index;		// which case it is (since we sort this)
-    block *cblock;	// back end: label for the block
-
-    // LDC
-    Statement *enclosingScopeExit;
-
-    CaseStatement(Loc loc, Expression *exp, Statement *s);
-    Statement *syntaxCopy();
-    Statement *semantic(Scope *sc);
-    int compare(Object *obj);
-    int usesEH();
-    int blockExit();
-    int comeFrom();
-    Expression *interpret(InterState *istate);
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-
-    Statement *inlineScan(InlineScanState *iss);
-
-    void toIR(IRState *irs);
-
-    CaseStatement* isCaseStatement() { return this; }
-
-    // LDC
-    llvm::BasicBlock* bodyBB;
-    llvm::ConstantInt* llvmIdx;
-};
-
-struct DefaultStatement : Statement
-{
-    Statement *statement;
-#if IN_GCC
-    block *cblock;	// back end: label for the block
-#endif
-
-    // LDC
-    Statement *enclosingScopeExit;
-
-    DefaultStatement(Loc loc, Statement *s);
-    Statement *syntaxCopy();
-    Statement *semantic(Scope *sc);
-    int usesEH();
-    int blockExit();
-    int comeFrom();
-    Expression *interpret(InterState *istate);
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-
-    Statement *inlineScan(InlineScanState *iss);
-
-    void toIR(IRState *irs);
-
-    // LDC
-    llvm::BasicBlock* bodyBB;
-};
-
-struct GotoDefaultStatement : Statement
-{
-    SwitchStatement *sw;
-
-    GotoDefaultStatement(Loc loc);
-    Statement *syntaxCopy();
-    Statement *semantic(Scope *sc);
-    Expression *interpret(InterState *istate);
-    int blockExit();
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-
-    void toIR(IRState *irs);
-};
-
-struct GotoCaseStatement : Statement
-{
-    Expression *exp;		// NULL, or which case to goto
-    CaseStatement *cs;		// case statement it resolves to
-    SwitchStatement *sw;
-
-    GotoCaseStatement(Loc loc, Expression *exp);
-    Statement *syntaxCopy();
-    Statement *semantic(Scope *sc);
-    Expression *interpret(InterState *istate);
-    int blockExit();
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-
-    void toIR(IRState *irs);
-};
-
-struct SwitchErrorStatement : Statement
-{
-    SwitchErrorStatement(Loc loc);
-    int blockExit();
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-
-    void toIR(IRState *irs);
-};
-
-struct ReturnStatement : Statement
-{
-    Expression *exp;
-
-    ReturnStatement(Loc loc, Expression *exp);
-    Statement *syntaxCopy();
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-    Statement *semantic(Scope *sc);
-    int blockExit();
-    Expression *interpret(InterState *istate);
-
-    int inlineCost(InlineCostState *ics);
-    Expression *doInline(InlineDoState *ids);
-    Statement *inlineScan(InlineScanState *iss);
-
-    void toIR(IRState *irs);
-
-    ReturnStatement *isReturnStatement() { return this; }
-};
-
-struct BreakStatement : Statement
-{
-    Identifier *ident;
-
-    BreakStatement(Loc loc, Identifier *ident);
-    Statement *syntaxCopy();
-    Statement *semantic(Scope *sc);
-    Expression *interpret(InterState *istate);
-    int blockExit();
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-
-    void toIR(IRState *irs);
-
-    // LDC: only set if ident is set: label statement to jump to
-    LabelStatement *target;
-};
-
-struct ContinueStatement : Statement
-{
-    Identifier *ident;
-
-    ContinueStatement(Loc loc, Identifier *ident);
-    Statement *syntaxCopy();
-    Statement *semantic(Scope *sc);
-    Expression *interpret(InterState *istate);
-    int blockExit();
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-
-    void toIR(IRState *irs);
-
-    // LDC: only set if ident is set: label statement to jump to
-    LabelStatement *target;
-};
-
-struct SynchronizedStatement : Statement
-{
-    Expression *exp;
-    Statement *body;
-
-    SynchronizedStatement(Loc loc, Expression *exp, Statement *body);
-    Statement *syntaxCopy();
-    Statement *semantic(Scope *sc);
-    int hasBreak();
-    int hasContinue();
-    int usesEH();
-    int blockExit();
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-
-    Statement *inlineScan(InlineScanState *iss);
-
-// Back end
-    elem *esync;
-    SynchronizedStatement(Loc loc, elem *esync, Statement *body);
-    void toIR(IRState *irs);
-    llvm::Value* llsync;
-};
-
-struct WithStatement : Statement
-{
-    Expression *exp;
-    Statement *body;
-    VarDeclaration *wthis;
-
-    WithStatement(Loc loc, Expression *exp, Statement *body);
-    Statement *syntaxCopy();
-    Statement *semantic(Scope *sc);
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-    int usesEH();
-    int blockExit();
-
-    Statement *inlineScan(InlineScanState *iss);
-
-    void toIR(IRState *irs);
-};
-
-struct TryCatchStatement : Statement
-{
-    Statement *body;
-    Array *catches;
-
-    TryCatchStatement(Loc loc, Statement *body, Array *catches);
-    Statement *syntaxCopy();
-    Statement *semantic(Scope *sc);
-    int hasBreak();
-    int usesEH();
-    int blockExit();
-
-    Statement *inlineScan(InlineScanState *iss);
-
-    void toIR(IRState *irs);
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-    TryCatchStatement *isTryCatchStatement() { return this; }
-};
-
-struct Catch : Object
-{
-    Loc loc;
-    Type *type;
-    Identifier *ident;
-    VarDeclaration *var;
-    Statement *handler;
-
-    Catch(Loc loc, Type *t, Identifier *id, Statement *handler);
-    Catch *syntaxCopy();
-    void semantic(Scope *sc);
-    int blockExit();
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-};
-
-struct TryFinallyStatement : Statement
-{
-    Statement *body;
-    Statement *finalbody;
-
-    TryFinallyStatement(Loc loc, Statement *body, Statement *finalbody);
-    Statement *syntaxCopy();
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-    Statement *semantic(Scope *sc);
-    int hasBreak();
-    int hasContinue();
-    int usesEH();
-    int blockExit();
-
-    Statement *inlineScan(InlineScanState *iss);
-
-    void toIR(IRState *irs);
-};
-
-struct OnScopeStatement : Statement
-{
-    TOK tok;
-    Statement *statement;
-
-    OnScopeStatement(Loc loc, TOK tok, Statement *statement);
-    Statement *syntaxCopy();
-    int blockExit();
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-    Statement *semantic(Scope *sc);
-    int usesEH();
-    void scopeCode(Statement **sentry, Statement **sexit, Statement **sfinally);
-
-    void toIR(IRState *irs);
-};
-
-struct ThrowStatement : Statement
-{
-    Expression *exp;
-
-    ThrowStatement(Loc loc, Expression *exp);
-    Statement *syntaxCopy();
-    Statement *semantic(Scope *sc);
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-    int blockExit();
-
-    Statement *inlineScan(InlineScanState *iss);
-
-    void toIR(IRState *irs);
-};
-
-struct VolatileStatement : Statement
-{
-    Statement *statement;
-
-    VolatileStatement(Loc loc, Statement *statement);
-    Statement *syntaxCopy();
-    Statement *semantic(Scope *sc);
-    Statements *flatten(Scope *sc);
-    int blockExit();
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-
-    Statement *inlineScan(InlineScanState *iss);
-
-    void toIR(IRState *irs);
-};
-
-struct GotoStatement : Statement
-{
-    Identifier *ident;
-    LabelDsymbol *label;
-    TryFinallyStatement *enclosingFinally;
-    Statement* enclosingScopeExit;
-
-    GotoStatement(Loc loc, Identifier *ident);
-    Statement *syntaxCopy();
-    Statement *semantic(Scope *sc);
-    int blockExit();
-    Expression *interpret(InterState *istate);
-
-    void toIR(IRState *irs);
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-    GotoStatement *isGotoStatement() { return this; }
-};
-
-struct LabelStatement : Statement
-{
-    Identifier *ident;
-    Statement *statement;
-    TryFinallyStatement *enclosingFinally;
-    Statement* enclosingScopeExit;
-    block *lblock;		// back end
-    int isReturnLabel;
-
-    LabelStatement(Loc loc, Identifier *ident, Statement *statement);
-    Statement *syntaxCopy();
-    Statement *semantic(Scope *sc);
-    Statements *flatten(Scope *sc);
-    int usesEH();
-    int blockExit();
-    int comeFrom();
-    Expression *interpret(InterState *istate);
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-
-    Statement *inlineScan(InlineScanState *iss);
-
-    void toIR(IRState *irs);
-
-    // LDC
-    bool asmLabel;       // for labels inside inline assembler
-    void toNakedIR(IRState *irs);
-};
-
-struct LabelDsymbol : Dsymbol
-{
-    LabelStatement *statement;
-
-    LabelDsymbol(Identifier *ident);
-    LabelDsymbol *isLabel();
-};
-
-struct AsmStatement : Statement
-{
-    Token *tokens;
-    code *asmcode;
-    unsigned asmalign;		// alignment of this statement
-    unsigned refparam;		// !=0 if function parameter is referenced
-    unsigned naked;		// !=0 if function is to be naked
-
-    AsmStatement(Loc loc, Token *tokens);
-    Statement *syntaxCopy();
-    Statement *semantic(Scope *sc);
-    int blockExit();
-    int comeFrom();
-
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-    virtual AsmStatement *isAsmStatement() { return this; }
-
-    void toIR(IRState *irs);
-
-    // LDC
-    // non-zero if this is a branch, contains the target labels identifier
-    Identifier* isBranchToLabel;
-
-    void toNakedIR(IRState *irs);
-};
-
-struct AsmBlockStatement : CompoundStatement
-{
-    TryFinallyStatement* enclosingFinally;
-    Statement* enclosingScopeExit;
-
-    AsmBlockStatement(Loc loc, Statements *s);
-    Statements *flatten(Scope *sc);
-    Statement *syntaxCopy();
-    Statement *semantic(Scope *sc);
-
-    CompoundStatement *isCompoundStatement() { return NULL; }
-    AsmBlockStatement *isAsmBlockStatement() { return this; }
-
-    void toIR(IRState *irs);
-    void toNakedIR(IRState *irs);
-    AsmBlockStatement* endsWithAsm();
-
-    llvm::Value* abiret;
-};
-
-#endif /* DMD_STATEMENT_H */
+
+// Compiler implementation of the D programming language
+// Copyright (c) 1999-2008 by Digital Mars
+// All Rights Reserved
+// written by Walter Bright
+// http://www.digitalmars.com
+// License for redistribution is by either the Artistic License
+// in artistic.txt, or the GNU General Public License in gnu.txt.
+// See the included readme.txt for details.
+
+#ifndef DMD_STATEMENT_H
+#define DMD_STATEMENT_H
+
+#ifdef __DMC__
+#pragma once
+#endif /* __DMC__ */
+
+#include "root.h"
+
+#include "arraytypes.h"
+#include "dsymbol.h"
+#include "lexer.h"
+
+struct OutBuffer;
+struct Scope;
+struct Expression;
+struct LabelDsymbol;
+struct Identifier;
+struct IfStatement;
+struct DeclarationStatement;
+struct DefaultStatement;
+struct VarDeclaration;
+struct Condition;
+struct Module;
+struct Token;
+struct InlineCostState;
+struct InlineDoState;
+struct InlineScanState;
+struct ReturnStatement;
+struct CompoundStatement;
+struct Argument;
+struct StaticAssert;
+struct AsmStatement;
+struct AsmBlockStatement;
+struct GotoStatement;
+struct ScopeStatement;
+struct TryCatchStatement;
+struct TryFinallyStatement;
+struct HdrGenState;
+struct InterState;
+struct CaseStatement;
+struct LabelStatement;
+struct VolatileStatement;
+struct SynchronizedStatement;
+
+enum TOK;
+
+namespace llvm
+{
+    class Value;
+    class BasicBlock;
+    class ConstantInt;
+}
+
+// Back end
+struct IRState;
+struct Blockx;
+#if IN_LLVM
+struct DValue;
+typedef DValue elem;
+#endif
+
+#if IN_GCC
+union tree_node; typedef union tree_node block;
+//union tree_node; typedef union tree_node elem;
+#else
+struct block;
+//struct elem;
+#endif
+struct code;
+
+/* How a statement exits; this is returned by blockExit()
+ */
+enum BE
+{
+    BEnone =	 0,
+    BEfallthru = 1,
+    BEthrow =    2,
+    BEreturn =   4,
+    BEgoto =     8,
+    BEhalt =	 0x10,
+    BEbreak =	 0x20,
+    BEcontinue = 0x40,
+    BEany = (BEfallthru | BEthrow | BEreturn | BEgoto | BEhalt),
+};
+
+struct Statement : Object
+{
+    Loc loc;
+
+    Statement(Loc loc);
+    virtual Statement *syntaxCopy();
+
+    void print();
+    char *toChars();
+
+    void error(const char *format, ...) IS_PRINTF(2);
+    void warning(const char *format, ...) IS_PRINTF(2);
+    virtual void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+    virtual TryCatchStatement *isTryCatchStatement() { return NULL; }
+    virtual GotoStatement *isGotoStatement() { return NULL; }
+    virtual AsmStatement *isAsmStatement() { return NULL; }
+    virtual AsmBlockStatement *isAsmBlockStatement() { return NULL; }
+#ifdef _DH
+    int incontract;
+#endif
+    virtual ScopeStatement *isScopeStatement() { return NULL; }
+    virtual Statement *semantic(Scope *sc);
+    Statement *semanticScope(Scope *sc, Statement *sbreak, Statement *scontinue);
+    virtual int hasBreak();
+    virtual int hasContinue();
+    virtual int usesEH();
+    virtual int blockExit();
+    virtual int comeFrom();
+    virtual int isEmpty();
+    virtual void scopeCode(Scope *sc, Statement **sentry, Statement **sexit, Statement **sfinally);
+    virtual Statements *flatten(Scope *sc);
+    virtual Expression *interpret(InterState *istate);
+
+    virtual int inlineCost(InlineCostState *ics);
+    virtual Expression *doInline(InlineDoState *ids);
+    virtual Statement *inlineScan(InlineScanState *iss);
+
+    // Back end
+    virtual void toIR(IRState *irs);
+
+    // Avoid dynamic_cast
+    virtual DeclarationStatement *isDeclarationStatement() { return NULL; }
+    virtual CompoundStatement *isCompoundStatement() { return NULL; }
+    virtual ReturnStatement *isReturnStatement() { return NULL; }
+    virtual IfStatement *isIfStatement() { return NULL; }
+    virtual CaseStatement* isCaseStatement() { return NULL; }
+
+    // LDC
+    virtual void toNakedIR(IRState *irs);
+    virtual AsmBlockStatement* endsWithAsm();
+};
+
+struct PeelStatement : Statement
+{
+    Statement *s;
+
+    PeelStatement(Statement *s);
+    Statement *semantic(Scope *sc);
+};
+
+struct ExpStatement : Statement
+{
+    Expression *exp;
+
+    ExpStatement(Loc loc, Expression *exp);
+    Statement *syntaxCopy();
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+    Statement *semantic(Scope *sc);
+    Expression *interpret(InterState *istate);
+    int blockExit();
+    int isEmpty();
+
+    int inlineCost(InlineCostState *ics);
+    Expression *doInline(InlineDoState *ids);
+    Statement *inlineScan(InlineScanState *iss);
+
+    void toIR(IRState *irs);
+
+    // LDC
+    void toNakedIR(IRState *irs);
+};
+
+struct CompileStatement : Statement
+{
+    Expression *exp;
+
+    CompileStatement(Loc loc, Expression *exp);
+    Statement *syntaxCopy();
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+    Statements *flatten(Scope *sc);
+    Statement *semantic(Scope *sc);
+};
+
+struct DeclarationStatement : ExpStatement
+{
+    // Doing declarations as an expression, rather than a statement,
+    // makes inlining functions much easier.
+
+    DeclarationStatement(Loc loc, Dsymbol *s);
+    DeclarationStatement(Loc loc, Expression *exp);
+    Statement *syntaxCopy();
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+    void scopeCode(Scope *sc, Statement **sentry, Statement **sexit, Statement **sfinally);
+
+    DeclarationStatement *isDeclarationStatement() { return this; }
+};
+
+struct CompoundStatement : Statement
+{
+    Statements *statements;
+
+    CompoundStatement(Loc loc, Statements *s);
+    CompoundStatement(Loc loc, Statement *s1, Statement *s2);
+    virtual Statement *syntaxCopy();
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+    virtual Statement *semantic(Scope *sc);
+    int usesEH();
+    int blockExit();
+    int comeFrom();
+    int isEmpty();
+    virtual Statements *flatten(Scope *sc);
+    ReturnStatement *isReturnStatement();
+    Expression *interpret(InterState *istate);
+
+    int inlineCost(InlineCostState *ics);
+    Expression *doInline(InlineDoState *ids);
+    Statement *inlineScan(InlineScanState *iss);
+
+    virtual void toIR(IRState *irs);
+
+    // LDC
+    virtual void toNakedIR(IRState *irs);
+    virtual AsmBlockStatement* endsWithAsm();
+
+    virtual CompoundStatement *isCompoundStatement() { return this; }
+};
+
+struct CompoundDeclarationStatement : CompoundStatement
+{
+    CompoundDeclarationStatement(Loc loc, Statements *s);
+    Statement *syntaxCopy();
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+};
+
+/* The purpose of this is so that continue will go to the next
+ * of the statements, and break will go to the end of the statements.
+ */
+struct UnrolledLoopStatement : Statement
+{
+    Statements *statements;
+
+    UnrolledLoopStatement(Loc loc, Statements *statements);
+    Statement *syntaxCopy();
+    Statement *semantic(Scope *sc);
+    int hasBreak();
+    int hasContinue();
+    int usesEH();
+    int blockExit();
+    int comeFrom();
+    Expression *interpret(InterState *istate);
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+
+    int inlineCost(InlineCostState *ics);
+    Expression *doInline(InlineDoState *ids);
+    Statement *inlineScan(InlineScanState *iss);
+
+    void toIR(IRState *irs);
+};
+
+struct ScopeStatement : Statement
+{
+    Statement *statement;
+
+    ScopeStatement(Loc loc, Statement *s);
+    Statement *syntaxCopy();
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+    ScopeStatement *isScopeStatement() { return this; }
+    Statement *semantic(Scope *sc);
+    int hasBreak();
+    int hasContinue();
+    int usesEH();
+    int blockExit();
+    int comeFrom();
+    int isEmpty();
+    Expression *interpret(InterState *istate);
+
+    Statement *inlineScan(InlineScanState *iss);
+
+    void toIR(IRState *irs);
+};
+
+struct WhileStatement : Statement
+{
+    Expression *condition;
+    Statement *body;
+
+    WhileStatement(Loc loc, Expression *c, Statement *b);
+    Statement *syntaxCopy();
+    Statement *semantic(Scope *sc);
+    int hasBreak();
+    int hasContinue();
+    int usesEH();
+    int blockExit();
+    int comeFrom();
+    Expression *interpret(InterState *istate);
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+
+    Statement *inlineScan(InlineScanState *iss);
+
+    void toIR(IRState *irs);
+};
+
+struct DoStatement : Statement
+{
+    Statement *body;
+    Expression *condition;
+
+    DoStatement(Loc loc, Statement *b, Expression *c);
+    Statement *syntaxCopy();
+    Statement *semantic(Scope *sc);
+    int hasBreak();
+    int hasContinue();
+    int usesEH();
+    int blockExit();
+    int comeFrom();
+    Expression *interpret(InterState *istate);
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+
+    Statement *inlineScan(InlineScanState *iss);
+
+    void toIR(IRState *irs);
+};
+
+struct ForStatement : Statement
+{
+    Statement *init;
+    Expression *condition;
+    Expression *increment;
+    Statement *body;
+
+    ForStatement(Loc loc, Statement *init, Expression *condition, Expression *increment, Statement *body);
+    Statement *syntaxCopy();
+    Statement *semantic(Scope *sc);
+    void scopeCode(Scope *sc, Statement **sentry, Statement **sexit, Statement **sfinally);
+    int hasBreak();
+    int hasContinue();
+    int usesEH();
+    int blockExit();
+    int comeFrom();
+    Expression *interpret(InterState *istate);
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+
+    Statement *inlineScan(InlineScanState *iss);
+
+    void toIR(IRState *irs);
+};
+
+struct ForeachStatement : Statement
+{
+    enum TOK op;		// TOKforeach or TOKforeach_reverse
+    Arguments *arguments;	// array of Argument*'s
+    Expression *aggr;
+    Statement *body;
+
+    VarDeclaration *key;
+    VarDeclaration *value;
+
+    FuncDeclaration *func;	// function we're lexically in
+
+    Array cases;	// put breaks, continues, gotos and returns here
+    Array gotos;	// forward referenced goto's go here
+
+    ForeachStatement(Loc loc, enum TOK op, Arguments *arguments, Expression *aggr, Statement *body);
+    Statement *syntaxCopy();
+    Statement *semantic(Scope *sc);
+    int hasBreak();
+    int hasContinue();
+    int usesEH();
+    int blockExit();
+    int comeFrom();
+    Expression *interpret(InterState *istate);
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+
+    Statement *inlineScan(InlineScanState *iss);
+
+    void toIR(IRState *irs);
+};
+
+#if DMDV2
+struct ForeachRangeStatement : Statement
+{
+    enum TOK op;		// TOKforeach or TOKforeach_reverse
+    Argument *arg;		// loop index variable
+    Expression *lwr;
+    Expression *upr;
+    Statement *body;
+
+    VarDeclaration *key;
+
+    ForeachRangeStatement(Loc loc, enum TOK op, Argument *arg,
+	Expression *lwr, Expression *upr, Statement *body);
+    Statement *syntaxCopy();
+    Statement *semantic(Scope *sc);
+    int hasBreak();
+    int hasContinue();
+    int usesEH();
+    int blockExit();
+    int comeFrom();
+    Expression *interpret(InterState *istate);
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+
+    Statement *inlineScan(InlineScanState *iss);
+
+    void toIR(IRState *irs);
+};
+#endif
+
+struct IfStatement : Statement
+{
+    Argument *arg;
+    Expression *condition;
+    Statement *ifbody;
+    Statement *elsebody;
+
+    VarDeclaration *match;	// for MatchExpression results
+
+    IfStatement(Loc loc, Argument *arg, Expression *condition, Statement *ifbody, Statement *elsebody);
+    Statement *syntaxCopy();
+    Statement *semantic(Scope *sc);
+    Expression *interpret(InterState *istate);
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+    int usesEH();
+    int blockExit();
+    IfStatement *isIfStatement() { return this; }
+
+    int inlineCost(InlineCostState *ics);
+    Expression *doInline(InlineDoState *ids);
+    Statement *inlineScan(InlineScanState *iss);
+
+    void toIR(IRState *irs);
+};
+
+struct ConditionalStatement : Statement
+{
+    Condition *condition;
+    Statement *ifbody;
+    Statement *elsebody;
+
+    ConditionalStatement(Loc loc, Condition *condition, Statement *ifbody, Statement *elsebody);
+    Statement *syntaxCopy();
+    Statement *semantic(Scope *sc);
+    Statements *flatten(Scope *sc);
+    int usesEH();
+    int blockExit();
+
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+};
+
+struct PragmaStatement : Statement
+{
+    Identifier *ident;
+    Expressions *args;		// array of Expression's
+    Statement *body;
+
+    PragmaStatement(Loc loc, Identifier *ident, Expressions *args, Statement *body);
+    Statement *syntaxCopy();
+    Statement *semantic(Scope *sc);
+    int usesEH();
+    int blockExit();
+
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+};
+
+struct StaticAssertStatement : Statement
+{
+    StaticAssert *sa;
+
+    StaticAssertStatement(StaticAssert *sa);
+    Statement *syntaxCopy();
+    Statement *semantic(Scope *sc);
+    int blockExit();
+
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+};
+
+struct SwitchStatement : Statement
+{
+    Expression *condition;
+    Statement *body;
+
+    DefaultStatement *sdefault;
+
+    Array gotoCases;		// array of unresolved GotoCaseStatement's
+    Array *cases;		// array of CaseStatement's
+    int hasNoDefault;		// !=0 if no default statement
+    
+    // LDC
+    Statement *enclosingScopeExit;
+
+    SwitchStatement(Loc loc, Expression *c, Statement *b);
+    Statement *syntaxCopy();
+    Statement *semantic(Scope *sc);
+    int hasBreak();
+    int usesEH();
+    int blockExit();
+    Expression *interpret(InterState *istate);
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+
+    Statement *inlineScan(InlineScanState *iss);
+
+    void toIR(IRState *irs);
+};
+
+struct CaseStatement : Statement
+{
+    Expression *exp;
+    Statement *statement;
+
+    int index;		// which case it is (since we sort this)
+    block *cblock;	// back end: label for the block
+
+    // LDC
+    Statement *enclosingScopeExit;
+
+    CaseStatement(Loc loc, Expression *exp, Statement *s);
+    Statement *syntaxCopy();
+    Statement *semantic(Scope *sc);
+    int compare(Object *obj);
+    int usesEH();
+    int blockExit();
+    int comeFrom();
+    Expression *interpret(InterState *istate);
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+
+    Statement *inlineScan(InlineScanState *iss);
+
+    void toIR(IRState *irs);
+
+    CaseStatement* isCaseStatement() { return this; }
+    
+    // LDC
+    llvm::BasicBlock* bodyBB;
+    llvm::ConstantInt* llvmIdx;
+};
+
+#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;
+#if IN_GCC
+    block *cblock;	// back end: label for the block
+#endif
+
+    // LDC
+    Statement *enclosingScopeExit;
+
+    DefaultStatement(Loc loc, Statement *s);
+    Statement *syntaxCopy();
+    Statement *semantic(Scope *sc);
+    int usesEH();
+    int blockExit();
+    int comeFrom();
+    Expression *interpret(InterState *istate);
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+
+    Statement *inlineScan(InlineScanState *iss);
+
+    void toIR(IRState *irs);
+
+    // LDC
+    llvm::BasicBlock* bodyBB;
+};
+
+struct GotoDefaultStatement : Statement
+{
+    SwitchStatement *sw;
+
+    GotoDefaultStatement(Loc loc);
+    Statement *syntaxCopy();
+    Statement *semantic(Scope *sc);
+    Expression *interpret(InterState *istate);
+    int blockExit();
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+
+    void toIR(IRState *irs);
+};
+
+struct GotoCaseStatement : Statement
+{
+    Expression *exp;		// NULL, or which case to goto
+    CaseStatement *cs;		// case statement it resolves to
+    SwitchStatement *sw;
+
+    GotoCaseStatement(Loc loc, Expression *exp);
+    Statement *syntaxCopy();
+    Statement *semantic(Scope *sc);
+    Expression *interpret(InterState *istate);
+    int blockExit();
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+
+    void toIR(IRState *irs);
+};
+
+struct SwitchErrorStatement : Statement
+{
+    SwitchErrorStatement(Loc loc);
+    int blockExit();
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+
+    void toIR(IRState *irs);
+};
+
+struct ReturnStatement : Statement
+{
+    Expression *exp;
+
+    ReturnStatement(Loc loc, Expression *exp);
+    Statement *syntaxCopy();
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+    Statement *semantic(Scope *sc);
+    int blockExit();
+    Expression *interpret(InterState *istate);
+
+    int inlineCost(InlineCostState *ics);
+    Expression *doInline(InlineDoState *ids);
+    Statement *inlineScan(InlineScanState *iss);
+
+    void toIR(IRState *irs);
+
+    ReturnStatement *isReturnStatement() { return this; }
+};
+
+struct BreakStatement : Statement
+{
+    Identifier *ident;
+
+    BreakStatement(Loc loc, Identifier *ident);
+    Statement *syntaxCopy();
+    Statement *semantic(Scope *sc);
+    Expression *interpret(InterState *istate);
+    int blockExit();
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+
+    void toIR(IRState *irs);
+
+    // LDC: only set if ident is set: label statement to jump to
+    LabelStatement *target;
+};
+
+struct ContinueStatement : Statement
+{
+    Identifier *ident;
+
+    ContinueStatement(Loc loc, Identifier *ident);
+    Statement *syntaxCopy();
+    Statement *semantic(Scope *sc);
+    Expression *interpret(InterState *istate);
+    int blockExit();
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+
+    void toIR(IRState *irs);
+
+    // LDC: only set if ident is set: label statement to jump to
+    LabelStatement *target;
+};
+
+struct SynchronizedStatement : Statement
+{
+    Expression *exp;
+    Statement *body;
+
+    SynchronizedStatement(Loc loc, Expression *exp, Statement *body);
+    Statement *syntaxCopy();
+    Statement *semantic(Scope *sc);
+    int hasBreak();
+    int hasContinue();
+    int usesEH();
+    int blockExit();
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+
+    Statement *inlineScan(InlineScanState *iss);
+
+// Back end
+    elem *esync;
+    SynchronizedStatement(Loc loc, elem *esync, Statement *body);
+    void toIR(IRState *irs);
+    llvm::Value* llsync;
+};
+
+struct WithStatement : Statement
+{
+    Expression *exp;
+    Statement *body;
+    VarDeclaration *wthis;
+
+    WithStatement(Loc loc, Expression *exp, Statement *body);
+    Statement *syntaxCopy();
+    Statement *semantic(Scope *sc);
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+    int usesEH();
+    int blockExit();
+
+    Statement *inlineScan(InlineScanState *iss);
+
+    void toIR(IRState *irs);
+};
+
+struct TryCatchStatement : Statement
+{
+    Statement *body;
+    Array *catches;
+
+    TryCatchStatement(Loc loc, Statement *body, Array *catches);
+    Statement *syntaxCopy();
+    Statement *semantic(Scope *sc);
+    int hasBreak();
+    int usesEH();
+    int blockExit();
+
+    Statement *inlineScan(InlineScanState *iss);
+
+    void toIR(IRState *irs);
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+    TryCatchStatement *isTryCatchStatement() { return this; }
+};
+
+struct Catch : Object
+{
+    Loc loc;
+    Type *type;
+    Identifier *ident;
+    VarDeclaration *var;
+    Statement *handler;
+
+    Catch(Loc loc, Type *t, Identifier *id, Statement *handler);
+    Catch *syntaxCopy();
+    void semantic(Scope *sc);
+    int blockExit();
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+};
+
+struct TryFinallyStatement : Statement
+{
+    Statement *body;
+    Statement *finalbody;
+
+    TryFinallyStatement(Loc loc, Statement *body, Statement *finalbody);
+    Statement *syntaxCopy();
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+    Statement *semantic(Scope *sc);
+    int hasBreak();
+    int hasContinue();
+    int usesEH();
+    int blockExit();
+
+    Statement *inlineScan(InlineScanState *iss);
+
+    void toIR(IRState *irs);
+};
+
+struct OnScopeStatement : Statement
+{
+    TOK tok;
+    Statement *statement;
+
+    OnScopeStatement(Loc loc, TOK tok, Statement *statement);
+    Statement *syntaxCopy();
+    int blockExit();
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+    Statement *semantic(Scope *sc);
+    int usesEH();
+    void scopeCode(Scope *sc, Statement **sentry, Statement **sexit, Statement **sfinally);
+
+    void toIR(IRState *irs);
+};
+
+struct ThrowStatement : Statement
+{
+    Expression *exp;
+
+    ThrowStatement(Loc loc, Expression *exp);
+    Statement *syntaxCopy();
+    Statement *semantic(Scope *sc);
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+    int blockExit();
+
+    Statement *inlineScan(InlineScanState *iss);
+
+    void toIR(IRState *irs);
+};
+
+struct VolatileStatement : Statement
+{
+    Statement *statement;
+
+    VolatileStatement(Loc loc, Statement *statement);
+    Statement *syntaxCopy();
+    Statement *semantic(Scope *sc);
+    Statements *flatten(Scope *sc);
+    int blockExit();
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+
+    Statement *inlineScan(InlineScanState *iss);
+
+    void toIR(IRState *irs);
+};
+
+struct GotoStatement : Statement
+{
+    Identifier *ident;
+    LabelDsymbol *label;
+    TryFinallyStatement *enclosingFinally;
+    Statement* enclosingScopeExit;
+
+    GotoStatement(Loc loc, Identifier *ident);
+    Statement *syntaxCopy();
+    Statement *semantic(Scope *sc);
+    int blockExit();
+    Expression *interpret(InterState *istate);
+
+    void toIR(IRState *irs);
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+    GotoStatement *isGotoStatement() { return this; }
+};
+
+struct LabelStatement : Statement
+{
+    Identifier *ident;
+    Statement *statement;
+    TryFinallyStatement *enclosingFinally;
+    Statement* enclosingScopeExit;
+    block *lblock;		// back end
+    int isReturnLabel;
+
+    LabelStatement(Loc loc, Identifier *ident, Statement *statement);
+    Statement *syntaxCopy();
+    Statement *semantic(Scope *sc);
+    Statements *flatten(Scope *sc);
+    int usesEH();
+    int blockExit();
+    int comeFrom();
+    Expression *interpret(InterState *istate);
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+
+    Statement *inlineScan(InlineScanState *iss);
+
+    void toIR(IRState *irs);
+
+    // LDC
+    bool asmLabel;       // for labels inside inline assembler
+    void toNakedIR(IRState *irs);
+};
+
+struct LabelDsymbol : Dsymbol
+{
+    LabelStatement *statement;
+
+    LabelDsymbol(Identifier *ident);
+    LabelDsymbol *isLabel();
+};
+
+struct AsmStatement : Statement
+{
+    Token *tokens;
+    code *asmcode;
+    unsigned asmalign;		// alignment of this statement
+    unsigned refparam;		// !=0 if function parameter is referenced
+    unsigned naked;		// !=0 if function is to be naked
+
+    AsmStatement(Loc loc, Token *tokens);
+    Statement *syntaxCopy();
+    Statement *semantic(Scope *sc);
+    int blockExit();
+    int comeFrom();
+
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+    virtual AsmStatement *isAsmStatement() { return this; }
+
+    void toIR(IRState *irs);
+
+    // LDC
+    // non-zero if this is a branch, contains the target labels identifier
+    Identifier* isBranchToLabel;
+
+    void toNakedIR(IRState *irs);
+};
+
+struct AsmBlockStatement : CompoundStatement
+{
+    TryFinallyStatement* enclosingFinally;
+    Statement* enclosingScopeExit;
+
+    AsmBlockStatement(Loc loc, Statements *s);
+    Statements *flatten(Scope *sc);
+    Statement *syntaxCopy();
+    Statement *semantic(Scope *sc);
+
+    CompoundStatement *isCompoundStatement() { return NULL; }
+    AsmBlockStatement *isAsmBlockStatement() { return this; }
+
+    void toIR(IRState *irs);
+    void toNakedIR(IRState *irs);
+    AsmBlockStatement* endsWithAsm();
+
+    llvm::Value* abiret;
+};
+
+#endif /* DMD_STATEMENT_H */
--- a/dmd/struct.c	Fri Nov 06 21:51:41 2009 +0100
+++ b/dmd/struct.c	Fri Nov 06 23:58:01 2009 +0100
@@ -1,520 +1,520 @@
-
-// Compiler implementation of the D programming language
-// Copyright (c) 1999-2009 by Digital Mars
-// All Rights Reserved
-// written by Walter Bright
-// http://www.digitalmars.com
-// License for redistribution is by either the Artistic License
-// in artistic.txt, or the GNU General Public License in gnu.txt.
-// See the included readme.txt for details.
-
-#include <stdio.h>
-#include <assert.h>
-
-#include "root.h"
-#include "aggregate.h"
-#include "scope.h"
-#include "mtype.h"
-#include "declaration.h"
-#include "module.h"
-#include "id.h"
-#include "statement.h"
-
-/********************************* AggregateDeclaration ****************************/
-
-AggregateDeclaration::AggregateDeclaration(Loc loc, Identifier *id)
-    : ScopeDsymbol(id)
-{
-    this->loc = loc;
-
-    storage_class = 0;
-    protection = PROTpublic;
-    type = NULL;
-    handle = NULL;
-    structsize = 0;		// size of struct
-    alignsize = 0;		// size of struct for alignment purposes
-    structalign = 0;		// struct member alignment in effect
-    hasUnions = 0;
-    sizeok = 0;			// size not determined yet
-    isdeprecated = 0;
-    inv = NULL;
-    aggNew = NULL;
-    aggDelete = NULL;
-
-#if IN_DMD
-    stag = NULL;
-    sinit = NULL;
-#endif
-    scope = NULL;
-#if DMDV2
-    dtor = NULL;
-
-    ctor = NULL;
-    defaultCtor = NULL;
-#endif
-
-#if IN_LLVM
-    availableExternally = true; // assume this unless proven otherwise
-#endif
-}
-
-enum PROT AggregateDeclaration::prot()
-{
-    return protection;
-}
-
-void AggregateDeclaration::semantic2(Scope *sc)
-{
-    //printf("AggregateDeclaration::semantic2(%s)\n", toChars());
-    if (scope)
-    {	error("has forward references");
-	return;
-    }
-    if (members)
-    {
-	sc = sc->push(this);
-	for (size_t i = 0; i < members->dim; i++)
-	{
-	    Dsymbol *s = (Dsymbol *)members->data[i];
-	    s->semantic2(sc);
-	}
-	sc->pop();
-    }
-}
-
-void AggregateDeclaration::semantic3(Scope *sc)
-{   int i;
-
-    // LDC
-    if (!global.params.useAvailableExternally)
-        availableExternally = false;
-
-    //printf("AggregateDeclaration::semantic3(%s)\n", toChars());
-    if (members)
-    {
-	sc = sc->push(this);
-	for (i = 0; i < members->dim; i++)
-	{
-	    Dsymbol *s = (Dsymbol *)members->data[i];
-	    s->semantic3(sc);
-	}
-	sc->pop();
-    }
-}
-
-void AggregateDeclaration::inlineScan()
-{   int i;
-
-    //printf("AggregateDeclaration::inlineScan(%s)\n", toChars());
-    if (members)
-    {
-	for (i = 0; i < members->dim; i++)
-	{
-	    Dsymbol *s = (Dsymbol *)members->data[i];
-	    //printf("inline scan aggregate symbol '%s'\n", s->toChars());
-	    s->inlineScan();
-	}
-    }
-}
-
-unsigned AggregateDeclaration::size(Loc loc)
-{
-    //printf("AggregateDeclaration::size() = %d\n", structsize);
-    if (!members)
-	error(loc, "unknown size");
-    if (sizeok != 1)
-    {	error(loc, "no size yet for forward reference");
-	//*(char*)0=0;
-    }
-    return structsize;
-}
-
-Type *AggregateDeclaration::getType()
-{
-    return type;
-}
-
-int AggregateDeclaration::isDeprecated()
-{
-    return isdeprecated;
-}
-
-/****************************
- * Do byte or word alignment as necessary.
- * Align sizes of 0, as we may not know array sizes yet.
- */
-
-void AggregateDeclaration::alignmember(
-	unsigned salign,	// struct alignment that is in effect
-	unsigned size,		// alignment requirement of field
-	unsigned *poffset)
-{
-    //printf("salign = %d, size = %d, offset = %d\n",salign,size,offset);
-    if (salign > 1)
-    {
-	assert(size != 3);
-	int sa = size;
-	if (sa == 0 || salign < sa)
-	    sa = salign;
-	*poffset = (*poffset + sa - 1) & ~(sa - 1);
-    }
-    //printf("result = %d\n",offset);
-}
-
-
-void AggregateDeclaration::addField(Scope *sc, VarDeclaration *v)
-{
-    unsigned memsize;		// size of member
-    unsigned memalignsize;	// size of member for alignment purposes
-    unsigned xalign;		// alignment boundaries
-
-    //printf("AggregateDeclaration::addField('%s') %s\n", v->toChars(), toChars());
-
-    // Check for forward referenced types which will fail the size() call
-    Type *t = v->type->toBasetype();
-    if (t->ty == Tstruct /*&& isStructDeclaration()*/)
-    {	TypeStruct *ts = (TypeStruct *)t;
-#if DMDV2
-	if (ts->sym == this)
-	{
-	    error("cannot have field %s with same struct type", v->toChars());
-	}
-#endif
-
-	if (ts->sym->sizeok != 1)
-	{
-	    sizeok = 2;		// cannot finish; flag as forward referenced
-	    return;
-	}
-    }
-    if (t->ty == Tident)
-    {
-	sizeok = 2;		// cannot finish; flag as forward referenced
-	return;
-    }
-
-    memsize = v->type->size(loc);
-    memalignsize = v->type->alignsize();
-    xalign = v->type->memalign(sc->structalign);
-    alignmember(xalign, memalignsize, &sc->offset);
-    v->offset = sc->offset;
-    sc->offset += memsize;
-    if (sc->offset > structsize)
-	structsize = sc->offset;
-    if (sc->structalign < memalignsize)
-	memalignsize = sc->structalign;
-    if (alignsize < memalignsize)
-	alignsize = memalignsize;
-    //printf("\talignsize = %d\n", alignsize);
-
-    v->storage_class |= STCfield;
-    //printf(" addField '%s' to '%s' at offset %d, size = %d\n", v->toChars(), toChars(), v->offset, memsize);
-    fields.push(v);
-}
-
-
-/********************************* StructDeclaration ****************************/
-
-StructDeclaration::StructDeclaration(Loc loc, Identifier *id)
-    : AggregateDeclaration(loc, id)
-{
-    zeroInit = 0;	// assume false until we do semantic processing
-#if DMDV2
-    hasIdentityAssign = 0;
-    cpctor = NULL;
-    postblit = NULL;
-#endif
-
-    // For forward references
-    type = new TypeStruct(this);
-}
-
-Dsymbol *StructDeclaration::syntaxCopy(Dsymbol *s)
-{
-    StructDeclaration *sd;
-
-    if (s)
-	sd = (StructDeclaration *)s;
-    else
-	sd = new StructDeclaration(loc, ident);
-    ScopeDsymbol::syntaxCopy(sd);
-    return sd;
-}
-
-void StructDeclaration::semantic(Scope *sc)
-{   int i;
-    Scope *sc2;
-
-    //printf("+StructDeclaration::semantic(this=%p, '%s')\n", this, toChars());
-
-    //static int count; if (++count == 20) *(char*)0=0;
-
-    assert(type);
-    if (!members)			// if forward reference
-	return;
-
-    if (symtab)
-    {   if (!scope)
-            return;             // semantic() already completed
-    }
-    else
-        symtab = new DsymbolTable();
-
-    Scope *scx = NULL;
-    if (scope)
-    {   sc = scope;
-        scx = scope;            // save so we don't make redundant copies
-        scope = NULL;
-    }
-
-    parent = sc->parent;
-#if STRUCTTHISREF
-    handle = type;
-#else
-    handle = type->pointerTo();
-#endif
-    structalign = sc->structalign;
-    protection = sc->protection;
-    if (sc->stc & STCdeprecated)
-	isdeprecated = 1;
-    assert(!isAnonymous());
-    if (sc->stc & STCabstract)
-	error("structs, unions cannot be abstract");
-#if DMDV2
-    if (storage_class & STCinvariant)
-        type = type->invariantOf();
-    else if (storage_class & STCconst)
-        type = type->constOf();
-#endif
-
-    if (sizeok == 0)		// if not already done the addMember step
-    {
-	for (i = 0; i < members->dim; i++)
-	{
-	    Dsymbol *s = (Dsymbol *)members->data[i];
-	    //printf("adding member '%s' to '%s'\n", s->toChars(), this->toChars());
-	    s->addMember(sc, this, 1);
-	}
-    }
-
-    sizeok = 0;
-    sc2 = sc->push(this);
-    sc2->stc = 0;
-    sc2->parent = this;
-    if (isUnionDeclaration())
-	sc2->inunion = 1;
-    sc2->protection = PROTpublic;
-    sc2->explicitProtection = 0;
-
-    int members_dim = members->dim;
-    for (i = 0; i < members_dim; i++)
-    {
-	Dsymbol *s = (Dsymbol *)members->data[i];
-	s->semantic(sc2);
-	if (isUnionDeclaration())
-	    sc2->offset = 0;
-#if 0
-	if (sizeok == 2)
-	{   //printf("forward reference\n");
-	    break;
-	}
-#endif
-    }
-
-    /* The TypeInfo_Struct is expecting an opEquals and opCmp with
-     * a parameter that is a pointer to the struct. But if there
-     * isn't one, but is an opEquals or opCmp with a value, write
-     * another that is a shell around the value:
-     *	int opCmp(struct *p) { return opCmp(*p); }
-     */
-
-    TypeFunction *tfeqptr;
-    {
-	Arguments *arguments = new Arguments;
-	Argument *arg = new Argument(STCin, handle, Id::p, NULL);
-
-	arguments->push(arg);
-	tfeqptr = new TypeFunction(arguments, Type::tint32, 0, LINKd);
-	tfeqptr = (TypeFunction *)tfeqptr->semantic(0, sc);
-    }
-
-    TypeFunction *tfeq;
-    {
-	Arguments *arguments = new Arguments;
-	Argument *arg = new Argument(STCin, type, NULL, NULL);
-
-	arguments->push(arg);
-	tfeq = new TypeFunction(arguments, Type::tint32, 0, LINKd);
-	tfeq = (TypeFunction *)tfeq->semantic(0, sc);
-    }
-
-    Identifier *id = Id::eq;
-    for (int i = 0; i < 2; i++)
-    {
-	Dsymbol *s = search_function(this, id);
-	FuncDeclaration *fdx = s ? s->isFuncDeclaration() : NULL;
-	if (fdx)
-	{   FuncDeclaration *fd = fdx->overloadExactMatch(tfeqptr, getModule());
-	    if (!fd)
-	    {	fd = fdx->overloadExactMatch(tfeq, getModule());
-		if (fd)
-		{   // Create the thunk, fdptr
-		    FuncDeclaration *fdptr = new FuncDeclaration(loc, loc, fdx->ident, STCundefined, tfeqptr);
-		    Expression *e = new IdentifierExp(loc, Id::p);
-		    e = new PtrExp(loc, e);
-		    Expressions *args = new Expressions();
-		    args->push(e);
-		    e = new IdentifierExp(loc, id);
-		    e = new CallExp(loc, e, args);
-		    fdptr->fbody = new ReturnStatement(loc, e);
-		    ScopeDsymbol *s = fdx->parent->isScopeDsymbol();
-		    assert(s);
-		    s->members->push(fdptr);
-		    fdptr->addMember(sc, s, 1);
-		    fdptr->semantic(sc2);
-		}
-	    }
-	}
-
-	id = Id::cmp;
-    }
-#if DMDV2
-    dtor = buildDtor(sc2);
-    postblit = buildPostBlit(sc2);
-    cpctor = buildCpCtor(sc2);
-    buildOpAssign(sc2);
-#endif
-
-    sc2->pop();
-
-    if (sizeok == 2)
-    {	// semantic() failed because of forward references.
-	// Unwind what we did, and defer it for later
-	fields.setDim(0);
-	structsize = 0;
-	alignsize = 0;
-	structalign = 0;
-
-	scope = scx ? scx : new Scope(*sc);
-	scope->setNoFree();
-	scope->module->addDeferredSemantic(this);
-	//printf("\tdeferring %s\n", toChars());
-	return;
-    }
-
-    // 0 sized struct's are set to 1 byte
-    if (structsize == 0)
-    {
-	structsize = 1;
-	alignsize = 1;
-    }
-
-    // Round struct size up to next alignsize boundary.
-    // This will ensure that arrays of structs will get their internals
-    // aligned properly.
-    structsize = (structsize + alignsize - 1) & ~(alignsize - 1);
-
-    sizeok = 1;
-    Module::dprogress++;
-
-    //printf("-StructDeclaration::semantic(this=%p, '%s')\n", this, toChars());
-
-    // Determine if struct is all zeros or not
-    zeroInit = 1;
-    for (i = 0; i < fields.dim; i++)
-    {
-	Dsymbol *s = (Dsymbol *)fields.data[i];
-	VarDeclaration *vd = s->isVarDeclaration();
-	if (vd && !vd->isDataseg())
-	{
-	    if (vd->init)
-	    {
-		// Should examine init to see if it is really all 0's
-		zeroInit = 0;
-		break;
-	    }
-	    else
-	    {
-		if (!vd->type->isZeroInit(loc))
-		{
-		    zeroInit = 0;
-		    break;
-		}
-	    }
-	}
-    }
-
-    /* Look for special member functions.
-     */
-#if DMDV2
-    ctor =   (CtorDeclaration *)search(0, Id::ctor, 0);
-#endif
-    inv =    (InvariantDeclaration *)search(0, Id::classInvariant, 0);
-    aggNew =       (NewDeclaration *)search(0, Id::classNew,       0);
-    aggDelete = (DeleteDeclaration *)search(0, Id::classDelete,    0);
-
-    if (sc->func)
-    {
-	semantic2(sc);
-	semantic3(sc);
-    }
-}
-
-void StructDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{   int i;
-
-    buf->printf("%s ", kind());
-    if (!isAnonymous())
-	buf->writestring(toChars());
-    if (!members)
-    {
-	buf->writeByte(';');
-	buf->writenl();
-	return;
-    }
-    buf->writenl();
-    buf->writeByte('{');
-    buf->writenl();
-    for (i = 0; i < members->dim; i++)
-    {
-	Dsymbol *s = (Dsymbol *)members->data[i];
-
-	buf->writestring("    ");
-	s->toCBuffer(buf, hgs);
-    }
-    buf->writeByte('}');
-    buf->writenl();
-}
-
-
-const char *StructDeclaration::kind()
-{
-    return "struct";
-}
-
-/********************************* UnionDeclaration ****************************/
-
-UnionDeclaration::UnionDeclaration(Loc loc, Identifier *id)
-    : StructDeclaration(loc, id)
-{
-}
-
-Dsymbol *UnionDeclaration::syntaxCopy(Dsymbol *s)
-{
-    UnionDeclaration *ud;
-
-    if (s)
-	ud = (UnionDeclaration *)s;
-    else
-	ud = new UnionDeclaration(loc, ident);
-    StructDeclaration::syntaxCopy(ud);
-    return ud;
-}
-
-
-const char *UnionDeclaration::kind()
-{
-    return "union";
-}
-
-
+
+// Compiler implementation of the D programming language
+// Copyright (c) 1999-2009 by Digital Mars
+// All Rights Reserved
+// written by Walter Bright
+// http://www.digitalmars.com
+// License for redistribution is by either the Artistic License
+// in artistic.txt, or the GNU General Public License in gnu.txt.
+// See the included readme.txt for details.
+
+#include <stdio.h>
+#include <assert.h>
+
+#include "root.h"
+#include "aggregate.h"
+#include "scope.h"
+#include "mtype.h"
+#include "declaration.h"
+#include "module.h"
+#include "id.h"
+#include "statement.h"
+
+/********************************* AggregateDeclaration ****************************/
+
+AggregateDeclaration::AggregateDeclaration(Loc loc, Identifier *id)
+    : ScopeDsymbol(id)
+{
+    this->loc = loc;
+
+    storage_class = 0;
+    protection = PROTpublic;
+    type = NULL;
+    handle = NULL;
+    structsize = 0;		// size of struct
+    alignsize = 0;		// size of struct for alignment purposes
+    structalign = 0;		// struct member alignment in effect
+    hasUnions = 0;
+    sizeok = 0;			// size not determined yet
+    isdeprecated = 0;
+    inv = NULL;
+    aggNew = NULL;
+    aggDelete = NULL;
+
+#if IN_DMD
+    stag = NULL;
+    sinit = NULL;
+#endif
+#if DMDV2
+    dtor = NULL;
+
+    ctor = NULL;
+    defaultCtor = NULL;
+#endif
+
+#if IN_LLVM
+    availableExternally = true; // assume this unless proven otherwise
+#endif
+}
+
+enum PROT AggregateDeclaration::prot()
+{
+    return protection;
+}
+
+void AggregateDeclaration::semantic2(Scope *sc)
+{
+    //printf("AggregateDeclaration::semantic2(%s)\n", toChars());
+    if (scope && members)
+    {	error("has forward references");
+	return;
+    }
+    if (members)
+    {
+	sc = sc->push(this);
+	for (size_t i = 0; i < members->dim; i++)
+	{
+	    Dsymbol *s = (Dsymbol *)members->data[i];
+	    s->semantic2(sc);
+	}
+	sc->pop();
+    }
+}
+
+void AggregateDeclaration::semantic3(Scope *sc)
+{   int i;
+
+    // LDC
+    if (!global.params.useAvailableExternally)
+        availableExternally = false;
+
+    //printf("AggregateDeclaration::semantic3(%s)\n", toChars());
+    if (members)
+    {
+	sc = sc->push(this);
+	for (i = 0; i < members->dim; i++)
+	{
+	    Dsymbol *s = (Dsymbol *)members->data[i];
+	    s->semantic3(sc);
+	}
+	sc->pop();
+    }
+}
+
+void AggregateDeclaration::inlineScan()
+{   int i;
+
+    //printf("AggregateDeclaration::inlineScan(%s)\n", toChars());
+    if (members)
+    {
+	for (i = 0; i < members->dim; i++)
+	{
+	    Dsymbol *s = (Dsymbol *)members->data[i];
+	    //printf("inline scan aggregate symbol '%s'\n", s->toChars());
+	    s->inlineScan();
+	}
+    }
+}
+
+unsigned AggregateDeclaration::size(Loc loc)
+{
+    //printf("AggregateDeclaration::size() = %d\n", structsize);
+    if (!members)
+	error(loc, "unknown size");
+    if (sizeok != 1)
+    {	error(loc, "no size yet for forward reference");
+	//*(char*)0=0;
+    }
+    return structsize;
+}
+
+Type *AggregateDeclaration::getType()
+{
+    return type;
+}
+
+int AggregateDeclaration::isDeprecated()
+{
+    return isdeprecated;
+}
+
+/****************************
+ * Do byte or word alignment as necessary.
+ * Align sizes of 0, as we may not know array sizes yet.
+ */
+
+void AggregateDeclaration::alignmember(
+	unsigned salign,	// struct alignment that is in effect
+	unsigned size,		// alignment requirement of field
+	unsigned *poffset)
+{
+    //printf("salign = %d, size = %d, offset = %d\n",salign,size,offset);
+    if (salign > 1)
+    {
+	assert(size != 3);
+	int sa = size;
+	if (sa == 0 || salign < sa)
+	    sa = salign;
+	*poffset = (*poffset + sa - 1) & ~(sa - 1);
+    }
+    //printf("result = %d\n",offset);
+}
+
+
+void AggregateDeclaration::addField(Scope *sc, VarDeclaration *v)
+{
+    unsigned memsize;		// size of member
+    unsigned memalignsize;	// size of member for alignment purposes
+    unsigned xalign;		// alignment boundaries
+
+    //printf("AggregateDeclaration::addField('%s') %s\n", v->toChars(), toChars());
+
+    // Check for forward referenced types which will fail the size() call
+    Type *t = v->type->toBasetype();
+    if (t->ty == Tstruct /*&& isStructDeclaration()*/)
+    {	TypeStruct *ts = (TypeStruct *)t;
+#if DMDV2
+	if (ts->sym == this)
+	{
+	    error("cannot have field %s with same struct type", v->toChars());
+	}
+#endif
+
+	if (ts->sym->sizeok != 1)
+	{
+	    sizeok = 2;		// cannot finish; flag as forward referenced
+	    return;
+	}
+    }
+    if (t->ty == Tident)
+    {
+	sizeok = 2;		// cannot finish; flag as forward referenced
+	return;
+    }
+
+    memsize = v->type->size(loc);
+    memalignsize = v->type->alignsize();
+    xalign = v->type->memalign(sc->structalign);
+    alignmember(xalign, memalignsize, &sc->offset);
+    v->offset = sc->offset;
+    sc->offset += memsize;
+    if (sc->offset > structsize)
+	structsize = sc->offset;
+    if (sc->structalign < memalignsize)
+	memalignsize = sc->structalign;
+    if (alignsize < memalignsize)
+	alignsize = memalignsize;
+    //printf("\talignsize = %d\n", alignsize);
+
+    v->storage_class |= STCfield;
+    //printf(" addField '%s' to '%s' at offset %d, size = %d\n", v->toChars(), toChars(), v->offset, memsize);
+    fields.push(v);
+}
+
+
+/********************************* StructDeclaration ****************************/
+
+StructDeclaration::StructDeclaration(Loc loc, Identifier *id)
+    : AggregateDeclaration(loc, id)
+{
+    zeroInit = 0;	// assume false until we do semantic processing
+#if DMDV2
+    hasIdentityAssign = 0;
+    cpctor = NULL;
+    postblit = NULL;
+#endif
+
+    // For forward references
+    type = new TypeStruct(this);
+}
+
+Dsymbol *StructDeclaration::syntaxCopy(Dsymbol *s)
+{
+    StructDeclaration *sd;
+
+    if (s)
+	sd = (StructDeclaration *)s;
+    else
+	sd = new StructDeclaration(loc, ident);
+    ScopeDsymbol::syntaxCopy(sd);
+    return sd;
+}
+
+void StructDeclaration::semantic(Scope *sc)
+{   int i;
+    Scope *sc2;
+
+    //printf("+StructDeclaration::semantic(this=%p, '%s')\n", this, toChars());
+
+    //static int count; if (++count == 20) *(char*)0=0;
+
+    assert(type);
+    if (!members)			// if forward reference
+	return;
+
+    if (symtab)
+    {   if (!scope)
+            return;             // semantic() already completed
+    }
+    else
+        symtab = new DsymbolTable();
+
+    Scope *scx = NULL;
+    if (scope)
+    {   sc = scope;
+        scx = scope;            // save so we don't make redundant copies
+        scope = NULL;
+    }
+
+    parent = sc->parent;
+    type = type->semantic(loc, sc);
+#if STRUCTTHISREF
+    handle = type;
+#else
+    handle = type->pointerTo();
+#endif
+    structalign = sc->structalign;
+    protection = sc->protection;
+    if (sc->stc & STCdeprecated)
+	isdeprecated = 1;
+    assert(!isAnonymous());
+    if (sc->stc & STCabstract)
+	error("structs, unions cannot be abstract");
+#if DMDV2
+    if (storage_class & STCinvariant)
+        type = type->invariantOf();
+    else if (storage_class & STCconst)
+        type = type->constOf();
+#endif
+
+    if (sizeok == 0)		// if not already done the addMember step
+    {
+	for (i = 0; i < members->dim; i++)
+	{
+	    Dsymbol *s = (Dsymbol *)members->data[i];
+	    //printf("adding member '%s' to '%s'\n", s->toChars(), this->toChars());
+	    s->addMember(sc, this, 1);
+	}
+    }
+
+    sizeok = 0;
+    sc2 = sc->push(this);
+    sc2->stc = 0;
+    sc2->parent = this;
+    if (isUnionDeclaration())
+	sc2->inunion = 1;
+    sc2->protection = PROTpublic;
+    sc2->explicitProtection = 0;
+
+    int members_dim = members->dim;
+    for (i = 0; i < members_dim; i++)
+    {
+	Dsymbol *s = (Dsymbol *)members->data[i];
+	s->semantic(sc2);
+	if (isUnionDeclaration())
+	    sc2->offset = 0;
+#if 0
+	if (sizeok == 2)
+	{   //printf("forward reference\n");
+	    break;
+	}
+#endif
+    }
+
+    /* The TypeInfo_Struct is expecting an opEquals and opCmp with
+     * a parameter that is a pointer to the struct. But if there
+     * isn't one, but is an opEquals or opCmp with a value, write
+     * another that is a shell around the value:
+     *	int opCmp(struct *p) { return opCmp(*p); }
+     */
+
+    TypeFunction *tfeqptr;
+    {
+	Arguments *arguments = new Arguments;
+	Argument *arg = new Argument(STCin, handle, Id::p, NULL);
+
+	arguments->push(arg);
+	tfeqptr = new TypeFunction(arguments, Type::tint32, 0, LINKd);
+	tfeqptr = (TypeFunction *)tfeqptr->semantic(0, sc);
+    }
+
+    TypeFunction *tfeq;
+    {
+	Arguments *arguments = new Arguments;
+	Argument *arg = new Argument(STCin, type, NULL, NULL);
+
+	arguments->push(arg);
+	tfeq = new TypeFunction(arguments, Type::tint32, 0, LINKd);
+	tfeq = (TypeFunction *)tfeq->semantic(0, sc);
+    }
+
+    Identifier *id = Id::eq;
+    for (int i = 0; i < 2; i++)
+    {
+	Dsymbol *s = search_function(this, id);
+	FuncDeclaration *fdx = s ? s->isFuncDeclaration() : NULL;
+	if (fdx)
+	{   FuncDeclaration *fd = fdx->overloadExactMatch(tfeqptr, getModule());
+	    if (!fd)
+	    {	fd = fdx->overloadExactMatch(tfeq, getModule());
+		if (fd)
+		{   // Create the thunk, fdptr
+		    FuncDeclaration *fdptr = new FuncDeclaration(loc, loc, fdx->ident, STCundefined, tfeqptr);
+		    Expression *e = new IdentifierExp(loc, Id::p);
+		    e = new PtrExp(loc, e);
+		    Expressions *args = new Expressions();
+		    args->push(e);
+		    e = new IdentifierExp(loc, id);
+		    e = new CallExp(loc, e, args);
+		    fdptr->fbody = new ReturnStatement(loc, e);
+		    ScopeDsymbol *s = fdx->parent->isScopeDsymbol();
+		    assert(s);
+		    s->members->push(fdptr);
+		    fdptr->addMember(sc, s, 1);
+		    fdptr->semantic(sc2);
+		}
+	    }
+	}
+
+	id = Id::cmp;
+    }
+#if DMDV2
+    dtor = buildDtor(sc2);
+    postblit = buildPostBlit(sc2);
+    cpctor = buildCpCtor(sc2);
+    buildOpAssign(sc2);
+#endif
+
+    sc2->pop();
+
+    if (sizeok == 2)
+    {	// semantic() failed because of forward references.
+	// Unwind what we did, and defer it for later
+	fields.setDim(0);
+	structsize = 0;
+	alignsize = 0;
+	structalign = 0;
+
+	scope = scx ? scx : new Scope(*sc);
+	scope->setNoFree();
+	scope->module->addDeferredSemantic(this);
+	//printf("\tdeferring %s\n", toChars());
+	return;
+    }
+
+    // 0 sized struct's are set to 1 byte
+    if (structsize == 0)
+    {
+	structsize = 1;
+	alignsize = 1;
+    }
+
+    // Round struct size up to next alignsize boundary.
+    // This will ensure that arrays of structs will get their internals
+    // aligned properly.
+    structsize = (structsize + alignsize - 1) & ~(alignsize - 1);
+
+    sizeok = 1;
+    Module::dprogress++;
+
+    //printf("-StructDeclaration::semantic(this=%p, '%s')\n", this, toChars());
+
+    // Determine if struct is all zeros or not
+    zeroInit = 1;
+    for (i = 0; i < fields.dim; i++)
+    {
+	Dsymbol *s = (Dsymbol *)fields.data[i];
+	VarDeclaration *vd = s->isVarDeclaration();
+	if (vd && !vd->isDataseg())
+	{
+	    if (vd->init)
+	    {
+		// Should examine init to see if it is really all 0's
+		zeroInit = 0;
+		break;
+	    }
+	    else
+	    {
+		if (!vd->type->isZeroInit(loc))
+		{
+		    zeroInit = 0;
+		    break;
+		}
+	    }
+	}
+    }
+
+    /* Look for special member functions.
+     */
+#if DMDV2
+    ctor =   (CtorDeclaration *)search(0, Id::ctor, 0);
+#endif
+    inv =    (InvariantDeclaration *)search(0, Id::classInvariant, 0);
+    aggNew =       (NewDeclaration *)search(0, Id::classNew,       0);
+    aggDelete = (DeleteDeclaration *)search(0, Id::classDelete,    0);
+
+    if (sc->func)
+    {
+	semantic2(sc);
+	semantic3(sc);
+    }
+}
+
+void StructDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{   int i;
+
+    buf->printf("%s ", kind());
+    if (!isAnonymous())
+	buf->writestring(toChars());
+    if (!members)
+    {
+	buf->writeByte(';');
+	buf->writenl();
+	return;
+    }
+    buf->writenl();
+    buf->writeByte('{');
+    buf->writenl();
+    for (i = 0; i < members->dim; i++)
+    {
+	Dsymbol *s = (Dsymbol *)members->data[i];
+
+	buf->writestring("    ");
+	s->toCBuffer(buf, hgs);
+    }
+    buf->writeByte('}');
+    buf->writenl();
+}
+
+
+const char *StructDeclaration::kind()
+{
+    return "struct";
+}
+
+/********************************* UnionDeclaration ****************************/
+
+UnionDeclaration::UnionDeclaration(Loc loc, Identifier *id)
+    : StructDeclaration(loc, id)
+{
+}
+
+Dsymbol *UnionDeclaration::syntaxCopy(Dsymbol *s)
+{
+    UnionDeclaration *ud;
+
+    if (s)
+	ud = (UnionDeclaration *)s;
+    else
+	ud = new UnionDeclaration(loc, ident);
+    StructDeclaration::syntaxCopy(ud);
+    return ud;
+}
+
+
+const char *UnionDeclaration::kind()
+{
+    return "union";
+}
+
+
--- a/dmd/template.c	Fri Nov 06 21:51:41 2009 +0100
+++ b/dmd/template.c	Fri Nov 06 23:58:01 2009 +0100
@@ -310,7 +310,7 @@
     this->members = decldefs;
     this->overnext = NULL;
     this->overroot = NULL;
-    this->scope = NULL;
+    this->semanticRun = 0;
     this->onemember = NULL;
 }
 
@@ -350,8 +350,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)
     {
@@ -803,16 +804,19 @@
     {	// Set initial template arguments
 
 	nargsi = targsi->dim;
-	if (nargsi > parameters->dim)
+	size_t n = parameters->dim;
+	if (nargsi > n)
 	{   if (!tp)
 		goto Lnomatch;
 	    dedargs->setDim(nargsi);
 	    dedargs->zero();
 	}
-
-	memcpy(dedargs->data, targsi->data, nargsi * sizeof(*dedargs->data));
-
-	for (size_t i = 0; i < nargsi; i++)
+	else
+	    n = nargsi;
+
+	memcpy(dedargs->data, targsi->data, n * sizeof(*dedargs->data));
+
+	for (size_t i = 0; i < n; i++)
 	{   assert(i < parameters->dim);
 	    TemplateParameter *tp = (TemplateParameter *)parameters->data[i];
 	    MATCH m;
@@ -844,7 +848,7 @@
     fdtype = (TypeFunction *)fd->type;
 
     nfparams = Argument::dim(fdtype->parameters); // number of function parameters
-    nfargs = fargs->dim;		// number of function arguments
+    nfargs = fargs ? fargs->dim : 0;		// number of function arguments
 
     /* Check for match of function arguments with variadic template
      * parameter, such as:
@@ -854,7 +858,7 @@
      */
     if (tp)				// if variadic
     {
-	if (nfparams == 0)		// if no function parameters
+	if (nfparams == 0 && nfargs != 0)		// if no function parameters
 	{
 	    Tuple *t = new Tuple();
 	    //printf("t = %p\n", t);
@@ -1293,7 +1297,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;
@@ -1901,14 +1905,21 @@
 
       L2:
 
-	for (int i = 0; i < tempinst->tiargs->dim; i++)
+	for (int i = 0; 1; i++)
 	{
 	    //printf("\ttest: tempinst->tiargs[%d]\n", i);
+	    Object *o1;
+	    if (i < tempinst->tiargs->dim)
+		o1 = (Object *)tempinst->tiargs->data[i];
+	    else if (i < tempinst->tdtypes.dim && i < tp->tempinst->tiargs->dim)
+		// Pick up default arg
+		o1 = (Object *)tempinst->tdtypes.data[i];
+	    else
+		break;
+
 	    if (i >= tp->tempinst->tiargs->dim)
 		goto Lnomatch;
 
-	    int j;
-	    Object *o1 = (Object *)tempinst->tiargs->data[i];
 	    Object *o2 = (Object *)tp->tempinst->tiargs->data[i];
 
 	    Type *t1 = isType(o1);
@@ -1934,6 +1945,7 @@
 #endif
 
 	    TemplateTupleParameter *ttp;
+	    int j;
 	    if (t2 &&
 		t2->ty == Tident &&
 		i == tp->tempinst->tiargs->dim - 1 &&
@@ -3062,7 +3074,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;
@@ -3096,7 +3108,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;
@@ -3179,13 +3191,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;
 
     // get the enclosing template instance from the scope tinst
     tinst = sc->tinst;
@@ -3323,7 +3335,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++)
@@ -3344,9 +3356,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;
     }
 
@@ -3559,6 +3571,7 @@
 	    }
 	    else if (ta)
 	    {
+	      Ltype:
 		if (ta->ty == Ttuple)
 		{   // Expand tuple
 		    TypeTuple *tt = (TypeTuple *)ta;
@@ -3593,7 +3606,21 @@
 	    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)
 	{
@@ -3736,6 +3763,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;
@@ -3752,11 +3796,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
@@ -3964,6 +4004,7 @@
 	{   sinteger_t v;
 	    real_t r;
 
+	    ea = ea->optimize(WANTvalue | WANTinterpret);
 	    if (ea->op == TOKvar)
 	    {
 		sa = ((VarExp *)ea)->var;
@@ -4030,7 +4071,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++)
@@ -4040,7 +4081,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);
     }
 }
 
@@ -4048,9 +4089,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
@@ -4080,12 +4121,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;
@@ -4182,6 +4223,7 @@
 #endif
     if (!inst)
     {	error("cannot resolve forward reference");
+	errors = 1;
 	return this;
     }
 
@@ -4274,7 +4316,6 @@
     this->tqual = tqual;
     this->idents = idents;
     this->tiargs = tiargs ? tiargs : new Objects();
-    this->scope = NULL;
 }
 
 Dsymbol *TemplateMixin::syntaxCopy(Dsymbol *s)
@@ -4308,18 +4349,22 @@
     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()))
-    {
+	if (parent && toParent()->isAggregateDeclaration())
+	    semanticRun = 1;		// do over
+	else
+	{
 #if LOG
-	printf("\tsemantic done\n");
+	    printf("\tsemantic done\n");
 #endif
-	return;
+	    return;
+	}
     }
-    if (!semanticdone)
-	semanticdone = 1;
+    if (!semanticRun)
+	semanticRun = 1;
 #if LOG
     printf("\tdo semantic\n");
 #endif
@@ -4394,7 +4439,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
@@ -4402,7 +4447,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;
@@ -4420,6 +4465,8 @@
 
     // Run semantic on each argument, place results in tiargs[]
     semanticTiargs(sc);
+    if (errors)
+	return;
 
     tempdecl = findBestMatch(sc);
     if (!tempdecl)
@@ -4508,19 +4555,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());
@@ -4531,7 +4578,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;
@@ -4574,7 +4621,7 @@
 
     sc2->pop();
 
-    scope->pop();
+    argscope->pop();
 
 //    if (!isAnonymous())
     {
@@ -4588,9 +4635,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
@@ -4618,9 +4665,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/dmd/template.h	Fri Nov 06 21:51:41 2009 +0100
+++ b/dmd/template.h	Fri Nov 06 23:58:01 2009 +0100
@@ -60,7 +60,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
 
     TemplateDeclaration(Loc loc, Identifier *id, TemplateParameters *parameters,
@@ -73,6 +74,7 @@
     char *toChars();
 
     void emitComment(Scope *sc);
+    void toJsonBuffer(OutBuffer *buf);
 //    void toDocBuffer(OutBuffer *buf);
 
     MATCH matchWithInstance(TemplateInstance *ti, Objects *atypes, int flag);
@@ -282,7 +284,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
@@ -341,8 +343,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);
--- a/gen/classes.cpp	Fri Nov 06 21:51:41 2009 +0100
+++ b/gen/classes.cpp	Fri Nov 06 23:58:01 2009 +0100
@@ -732,11 +732,7 @@
 
     // class name
     // code from dmd
-#if DMDV2
     const char *name = cd->ident->toChars();
-#else
-    char *name = cd->ident->toChars();
-#endif
     size_t namelen = strlen(name);
     if (!(namelen > 9 && memcmp(name, "TypeInfo_", 9) == 0))
     {
--- a/gen/main.cpp	Fri Nov 06 21:51:41 2009 +0100
+++ b/gen/main.cpp	Fri Nov 06 23:58:01 2009 +0100
@@ -806,6 +806,17 @@
         fatal();
 #endif
 
+    // load all unconditional imports for better symbol resolving
+    for (int i = 0; i < modules.dim; i++)
+    {
+       m = (Module *)modules.data[i];
+       if (global.params.verbose)
+           printf("importall %s\n", m->toChars());
+       m->importAll(0);
+    }
+    if (global.errors)
+       fatal();
+
     // Do semantic analysis
     for (int i = 0; i < modules.dim; i++)
     {