changeset 1367:8026319762be

Merged DMD 1.045 !!!
author Tomas Lindquist Olsen <tomas.l.olsen gmail com>
date Sat, 16 May 2009 22:21:31 +0200
parents 81121ac19f61
children 1fbdfec6ea0d
files dmd/aggregate.h dmd/cast.c dmd/class.c dmd/cond.c dmd/constfold.c dmd/declaration.c dmd/declaration.h dmd/expression.c dmd/expression.h dmd/func.c dmd/init.c dmd/inline.c dmd/interpret.c dmd/lexer.c dmd/lexer.h dmd/mangle.c dmd/mars.h dmd/mtype.c dmd/mtype.h dmd/optimize.c dmd/parse.c dmd/parse.h dmd/root/man.c dmd/root/port.c dmd/root/port.h dmd/root/root.c dmd/root/root.h dmd/scope.h dmd/statement.c dmd/staticassert.c dmd/struct.c dmd/template.c dmd/template.h gen/classes.cpp gen/toir.cpp gen/typinf.cpp runtime/internal/genobj.d
diffstat 37 files changed, 9635 insertions(+), 9392 deletions(-) [+]
line wrap: on
line diff
--- a/dmd/aggregate.h	Sat May 16 18:37:16 2009 +0200
+++ b/dmd/aggregate.h	Sat May 16 22:21:31 2009 +0200
@@ -186,9 +186,9 @@
 };
 
 #if DMDV2
-#define CLASSINFO_SIZE 	(0x3C+16)	// value of ClassInfo.size
+#define CLASSINFO_SIZE 	(0x3C+16+4)	// value of ClassInfo.size
 #else
-#define CLASSINFO_SIZE 	(0x3C+12)	// value of ClassInfo.size
+#define CLASSINFO_SIZE 	(0x3C+12+4)	// value of ClassInfo.size
 #endif
 
 struct ClassDeclaration : AggregateDeclaration
--- a/dmd/cast.c	Sat May 16 18:37:16 2009 +0200
+++ b/dmd/cast.c	Sat May 16 22:21:31 2009 +0200
@@ -1511,6 +1511,9 @@
     {
      Lincompatible:
 	incompatibleTypes();
+	type = Type::terror;
+	e1 = new ErrorExp();
+	e2 = new ErrorExp();
     }
 Lret:
     if (!type)
--- a/dmd/class.c	Sat May 16 18:37:16 2009 +0200
+++ b/dmd/class.c	Sat May 16 22:21:31 2009 +0200
@@ -522,7 +522,7 @@
 		    else
 			assert(0);
 		    assert(!vthis);
-		    vthis = new ThisDeclaration(t);
+		    vthis = new ThisDeclaration(loc, t);
 		    members->push(vthis);
 		}
 	    }
@@ -1225,11 +1225,14 @@
 	{
 	    if (poffset)
 	    {	*poffset = b->offset;
+		if (j && bc->base->isInterfaceDeclaration())
+		    *poffset = OFFSET_RUNTIME;
 	    }
 	    return 1;
 	}
 	if (isBaseOf(b, poffset))
-	{
+	{   if (j && poffset && bc->base->isInterfaceDeclaration())
+		*poffset = OFFSET_RUNTIME;
 	    return 1;
 	}
     }
--- a/dmd/cond.c	Sat May 16 18:37:16 2009 +0200
+++ b/dmd/cond.c	Sat May 16 22:21:31 2009 +0200
@@ -137,6 +137,7 @@
 	"Posix",
 #endif
 	"OSX", "FreeBSD",
+	"Solaris",
 	"LittleEndian", "BigEndian",
 	"all",
 	"none",
--- a/dmd/constfold.c	Sat May 16 18:37:16 2009 +0200
+++ b/dmd/constfold.c	Sat May 16 22:21:31 2009 +0200
@@ -19,6 +19,7 @@
 
 #include "rmem.h"
 #include "root.h"
+#include "port.h"
 
 #include "mtype.h"
 #include "expression.h"
@@ -34,6 +35,10 @@
 
 static real_t zero;	// work around DMC bug for now
 
+#if __FreeBSD__
+#define fmodl fmod	// hack for now, fix later
+#endif
+
 #define LOG 0
 
 Expression *expType(Type *type, Expression *e)
@@ -460,7 +465,7 @@
 	n2 = e2->toInteger();
 	if (n2 == 0)
 	{   e2->error("divide by 0");
-	    e2 = new IntegerExp(0, 1, e2->type);
+	    e2 = new IntegerExp(loc, 1, e2->type);
 	    n2 = 1;
 	}
 	if (e1->type->isunsigned() || e2->type->isunsigned())
@@ -531,7 +536,7 @@
 	n2 = e2->toInteger();
 	if (n2 == 0)
 	{   e2->error("divide by 0");
-	    e2 = new IntegerExp(0, 1, e2->type);
+	    e2 = new IntegerExp(loc, 1, e2->type);
 	    n2 = 1;
 	}
 	if (e1->type->isunsigned() || e2->type->isunsigned())
@@ -640,26 +645,21 @@
 }
 
 Expression *And(Type *type, Expression *e1, Expression *e2)
-{   Expression *e;
-    Loc loc = e1->loc;
-
-    e = new IntegerExp(loc, e1->toInteger() & e2->toInteger(), type);
+{
+    Expression *e;
+    e = new IntegerExp(e1->loc, e1->toInteger() & e2->toInteger(), type);
     return e;
 }
 
 Expression *Or(Type *type, Expression *e1, Expression *e2)
 {   Expression *e;
-    Loc loc = e1->loc;
-
-    e = new IntegerExp(loc, e1->toInteger() | e2->toInteger(), type);
+    e = new IntegerExp(e1->loc, e1->toInteger() | e2->toInteger(), type);
     return e;
 }
 
 Expression *Xor(Type *type, Expression *e1, Expression *e2)
 {   Expression *e;
-    Loc loc = e1->loc;
-
-    e = new IntegerExp(loc, e1->toInteger() ^ e2->toInteger(), type);
+    e = new IntegerExp(e1->loc, e1->toInteger() ^ e2->toInteger(), type);
     return e;
 }
 
@@ -831,7 +831,7 @@
 #if __DMC__
 	cmp = (r1 == r2);
 #else
-	if (isnan(r1) || isnan(r2))	// if unordered
+	if (Port::isNan(r1) || Port::isNan(r2))	// if unordered
 	{
 	    cmp = 0;
 	}
@@ -926,11 +926,7 @@
 	}
 #else
 	// Don't rely on compiler, handle NAN arguments separately
-#if IN_GCC
-	if (real_isnan(&r1) || real_isnan(&r2))	// if unordered
-#else
-	if (isnan(r1) || isnan(r2))	// if unordered
-#endif
+	if (Port::isNan(r1) || Port::isNan(r2))	// if unordered
 	{
 	    switch (op)
 	    {
@@ -1313,6 +1309,7 @@
     Type *t2 = e2->type->toBasetype();
 
     //printf("Cat(e1 = %s, e2 = %s)\n", e1->toChars(), e2->toChars());
+    //printf("\tt1 = %s, t2 = %s\n", t1->toChars(), t2->toChars());
 
     if (e1->op == TOKnull && (e2->op == TOKint64 || e2->op == TOKstructliteral))
     {	e = e2;
@@ -1498,7 +1495,7 @@
 
 	if (type->toBasetype()->ty == Tsarray)
 	{
-	    e->type = new TypeSArray(e2->type, new IntegerExp(0, es1->elements->dim, Type::tindex));
+	    e->type = new TypeSArray(e2->type, new IntegerExp(loc, es1->elements->dim, Type::tindex));
 	    e->type = e->type->semantic(loc, NULL);
 	}
 	else
@@ -1515,7 +1512,7 @@
 
 	if (type->toBasetype()->ty == Tsarray)
 	{
-	    e->type = new TypeSArray(e1->type, new IntegerExp(0, es2->elements->dim, Type::tindex));
+	    e->type = new TypeSArray(e1->type, new IntegerExp(loc, es2->elements->dim, Type::tindex));
 	    e->type = e->type->semantic(loc, NULL);
 	}
 	else
--- a/dmd/declaration.c	Sat May 16 18:37:16 2009 +0200
+++ b/dmd/declaration.c	Sat May 16 22:21:31 2009 +0200
@@ -33,6 +33,7 @@
     storage_class = STCundefined;
     protection = PROTundefined;
     linkage = LINKdefault;
+    inuse = 0;
 }
 
 void Declaration::semantic(Scope *sc)
@@ -253,7 +254,6 @@
     this->hbasetype = NULL;
 #endif
     this->sem = 0;
-    this->inuse = 0;
     this->loc = loc;
 #if IN_DMD
     this->sinit = NULL;
@@ -482,7 +482,9 @@
 	}
     }
     else if (t)
+    {
 	type = t;
+    }
     if (overnext)
 	ScopeDsymbol::multiplyDefined(0, this, overnext);
     this->inSemantic = 0;
@@ -559,7 +561,7 @@
     //static int count; if (++count == 10) *(char*)0=0;
     if (inSemantic)
     {	error("recursive alias declaration");
-//	return this;
+	aliassym = new TypedefDeclaration(loc, ident, Type::terror, NULL);
     }
     Dsymbol *s = aliassym ? aliassym->toAlias() : this;
     return s;
@@ -619,7 +621,6 @@
     offset = 0;
     noauto = 0;
     nestedref = 0;
-    inuse = 0;
     ctorinit = 0;
     aliassym = NULL;
     onstack = 0;
@@ -1399,8 +1400,8 @@
 
 // For the "this" parameter to member functions
 
-ThisDeclaration::ThisDeclaration(Type *t)
-   : VarDeclaration(0, t, Id::This, NULL)
+ThisDeclaration::ThisDeclaration(Loc loc, Type *t)
+   : VarDeclaration(loc, t, Id::This, NULL)
 {
     noauto = 1;
 }
--- a/dmd/declaration.h	Sat May 16 18:37:16 2009 +0200
+++ b/dmd/declaration.h	Sat May 16 22:21:31 2009 +0200
@@ -68,6 +68,7 @@
     STCtemplateparameter = 0x40000,	// template parameter
     STCscope	    = 0x80000,		// template parameter
     STCinvariant    = 0x100000,
+    STCimmutable    = 0x100000,
     STCref	    = 0x200000,
     STCinit	    = 0x400000,		// has explicit initializer
     STCmanifest	    = 0x800000,		// manifest constant
@@ -76,6 +77,10 @@
     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
@@ -101,6 +106,7 @@
     unsigned storage_class;
     enum PROT protection;
     enum LINK linkage;
+    int inuse;			// used to detect cycles
 
     Declaration(Identifier *id);
     void semantic(Scope *sc);
@@ -177,7 +183,6 @@
 				// 1: semantic() is in progress
 				// 2: semantic() has been run
 				// 3: semantic2() has been run
-    int inuse;			// used to detect typedef cycles
 
     TypedefDeclaration(Loc loc, Identifier *ident, Type *basetype, Initializer *init);
     Dsymbol *syntaxCopy(Dsymbol *);
@@ -249,7 +254,6 @@
     unsigned offset;
     int noauto;			// no auto semantics
     int nestedref;		// referenced by a lexically nested function
-    int inuse;
     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
@@ -257,6 +261,7 @@
     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 *);
@@ -561,14 +566,22 @@
     void llvmDefine();
 #endif
 };
+
+struct TypeInfoSharedDeclaration : TypeInfoDeclaration
+{
+    TypeInfoSharedDeclaration(Type *tinfo);
+
+    void toDt(dt_t **pdt);
+};
 #endif
 
 /**************************************************************/
 
 struct ThisDeclaration : VarDeclaration
 {
-    ThisDeclaration(Type *t);
+    ThisDeclaration(Loc loc, Type *t);
     Dsymbol *syntaxCopy(Dsymbol *);
+    ThisDeclaration *isThisDeclaration() { return this; }
 };
 
 enum ILS
@@ -624,7 +637,11 @@
     ILS inlineStatus;
     int inlineNest;			// !=0 if nested inline
     int cantInterpret;			// !=0 if cannot interpret function
-    int semanticRun;			// !=0 if semantic3() had been run
+    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
--- a/dmd/expression.c	Sat May 16 18:37:16 2009 +0200
+++ b/dmd/expression.c	Sat May 16 22:21:31 2009 +0200
@@ -99,7 +99,6 @@
     precedence[TOKnull] = PREC_primary;
     precedence[TOKstring] = PREC_primary;
     precedence[TOKarrayliteral] = PREC_primary;
-    precedence[TOKtypedot] = PREC_primary;
     precedence[TOKtypeid] = PREC_primary;
     precedence[TOKis] = PREC_primary;
     precedence[TOKassert] = PREC_primary;
@@ -1558,6 +1557,22 @@
 	buf->printf("%jd", value);
 }
 
+/******************************** ErrorExp **************************/
+
+/* Use this expression for error recovery.
+ * It should behave as a 'sink' to prevent further cascaded error messages.
+ */
+
+ErrorExp::ErrorExp()
+    : IntegerExp(0, 0, Type::terror)
+{
+}
+
+void ErrorExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    buf->writestring("__error");
+}
+
 /******************************** RealExp **************************/
 
 RealExp::RealExp(Loc loc, real_t value, Type *type)
@@ -1940,7 +1955,7 @@
 	    {	Type *t = withsym->withstate->wthis->type;
 		if (t->ty == Tpointer)
 		    t = ((TypePointer *)t)->next;
-		e = new TypeDotIdExp(loc, t, ident);
+		e = typeDotIdExp(loc, t, ident);
 	    }
 	}
 	else
@@ -3288,38 +3303,11 @@
  *	cast(foo).size
  */
 
-TypeDotIdExp::TypeDotIdExp(Loc loc, Type *type, Identifier *ident)
-    : Expression(loc, TOKtypedot, sizeof(TypeDotIdExp))
-{
-    this->type = type;
-    this->ident = ident;
-}
-
-Expression *TypeDotIdExp::syntaxCopy()
-{
-    TypeDotIdExp *te = new TypeDotIdExp(loc, type->syntaxCopy(), ident);
-    return te;
-}
-
-Expression *TypeDotIdExp::semantic(Scope *sc)
-{   Expression *e;
-
-#if LOGSEMANTIC
-    printf("TypeDotIdExp::semantic()\n");
-#endif
-    e = new DotIdExp(loc, new TypeExp(loc, type), ident);
-    e = e->semantic(sc);
-    return e;
-}
-
-void TypeDotIdExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{
-    buf->writeByte('(');
-    type->toCBuffer(buf, NULL, hgs);
-    buf->writeByte(')');
-    buf->writeByte('.');
-    buf->writestring(ident->toChars());
-}
+Expression *typeDotIdExp(Loc loc, Type *type, Identifier *ident)
+{
+    return new DotIdExp(loc, new TypeExp(loc, type), ident);
+}
+
 
 /************************************************************/
 
@@ -5257,12 +5245,12 @@
 	    {
 		if (e1->op == TOKthis)
 		{
-		    e = new TypeDotIdExp(loc, cd->type, ident);
+		    e = typeDotIdExp(loc, cd->type, ident);
 		    return e->semantic(sc);
 		}
 		else if (cd->baseClass && e1->op == TOKsuper)
 		{
-		    e = new TypeDotIdExp(loc, cd->baseClass->type, ident);
+		    e = typeDotIdExp(loc, cd->baseClass->type, ident);
 		    return e->semantic(sc);
 		}
 	    }
@@ -5273,7 +5261,7 @@
 		{
 		    if (e1->op == TOKthis)
 		    {
-			e = new TypeDotIdExp(loc, sd->type, ident);
+			e = typeDotIdExp(loc, sd->type, ident);
 			return e->semantic(sc);
 		    }
 		}
@@ -5321,6 +5309,18 @@
 	return e;
     }
 
+    if (e1->op == TOKdottd)
+    {
+	error("template %s does not have property %s", e1->toChars(), ident->toChars());
+	return e1;
+    }
+
+    if (!e1->type)
+    {
+	error("expression %s does not have property %s", e1->toChars(), ident->toChars());
+	return e1;
+    }
+
     if (eright->op == TOKimport)	// also used for template alias's
     {
 	ScopeExp *ie = (ScopeExp *)eright;
@@ -5607,7 +5607,8 @@
 
 	if (!var->isFuncDeclaration())	// for functions, do checks after overload resolution
 	{
-	    AggregateDeclaration *ad = var->toParent()->isAggregateDeclaration();
+	    Dsymbol *vparent = var->toParent();
+	    AggregateDeclaration *ad = vparent ? vparent->isAggregateDeclaration() : NULL;
 	    e1 = getRightThis(loc, sc, ad, e1, var);
 	    if (!sc->noaccesscheck)
 		accessCheck(loc, sc, e1, var);
@@ -5802,10 +5803,11 @@
     id = ti->name;
     s2 = s->search(loc, id, 0);
     if (!s2)
-    {	if (s->ident)
+    {
+	if (!s->ident)
+	    error("template identifier %s is not a member of undefined %s", id->toChars(), s->kind());
+	else
 	    error("template identifier %s is not a member of %s %s", id->toChars(), s->kind(), s->ident->toChars());
-	else
-	    error("template identifier %s is not a member of %s", id->toChars(), s->kind());
 	goto Lerr;
     }
     s = s2;
@@ -7264,7 +7266,7 @@
 	else
 	{
 	    error("string slice [%ju .. %ju] is out of bounds", i1, i2);
-	    e = e1;
+	    e = new IntegerExp(0);
 	}
 	return e;
     }
@@ -9275,8 +9277,15 @@
     e = op_overload(sc);
     if (e)
     {
-	e = new CmpExp(op, loc, e, new IntegerExp(loc, 0, Type::tint32));
-	e = e->semantic(sc);
+	if (!e->type->isscalar() && e->type->equals(e1->type))
+	{
+	    error("recursive opCmp expansion");
+	    e = new ErrorExp();
+	}
+	else
+	{   e = new CmpExp(op, loc, e, new IntegerExp(loc, 0, Type::tint32));
+	    e = e->semantic(sc);
+	}
 	return e;
     }
 
--- a/dmd/expression.h	Sat May 16 18:37:16 2009 +0200
+++ b/dmd/expression.h	Sat May 16 22:21:31 2009 +0200
@@ -203,6 +203,13 @@
 #endif
 };
 
+struct ErrorExp : IntegerExp
+{
+    ErrorExp();
+
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+};
+
 struct RealExp : Expression
 {
     real_t value;
@@ -519,22 +526,13 @@
 #endif
 };
 
-struct TypeDotIdExp : Expression
-{
-    Identifier *ident;
-
-    TypeDotIdExp(Loc loc, Type *type, Identifier *ident);
-    Expression *syntaxCopy();
-    Expression *semantic(Scope *sc);
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+Expression *typeDotIdExp(Loc loc, Type *type, Identifier *ident);
 #if IN_DMD
-    elem *toElem(IRState *irs);
 #endif
 
 #if IN_LLVM
     DValue* toElem(IRState* irs);
 #endif
-};
 
 struct TypeExp : Expression
 {
--- a/dmd/func.c	Sat May 16 18:37:16 2009 +0200
+++ b/dmd/func.c	Sat May 16 22:21:31 2009 +0200
@@ -1,3059 +1,3070 @@
-
-// 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;
-
-    // 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 (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 or auto");
-
-    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)
-	return;
-    semanticRun = 1;
-
-    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(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(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->noauto = 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
-		    ThisExp *v = new ThisExp(0);
-		    v->type = vthis->type;
-                    e = new AssertExp(loc, v, NULL);
-
-                    // LDC: check for null this
-                    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 = 2;
-}
-
-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 (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 (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-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;
+
+    // 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 or auto");
+
+    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;
+
+    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->noauto = 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
+		    ThisExp *v = new ThisExp(0);
+		    v->type = vthis->type;
+                    e = new AssertExp(loc, v, NULL);
+
+                    // LDC: check for null this
+                    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);
+}
+
+
+
+
--- a/dmd/init.c	Sat May 16 18:37:16 2009 +0200
+++ b/dmd/init.c	Sat May 16 22:21:31 2009 +0200
@@ -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
@@ -568,7 +568,20 @@
     //printf("ExpInitializer::inferType() %s\n", toChars());
     exp = exp->semantic(sc);
     exp = resolveProperties(sc, exp);
-    return exp->type;
+
+#if DMDV2
+    // Give error for overloaded function addresses
+    if (exp->op == TOKsymoff)
+    {   SymOffExp *se = (SymOffExp *)exp;
+	if (se->hasOverloads && !se->var->isFuncDeclaration()->isUnique())
+	    exp->error("cannot infer type from overloaded function symbol %s", exp->toChars());
+    }
+#endif
+
+    Type *t = exp->type;
+    if (!t)
+	t = Initializer::inferType(sc);
+    return t;
 }
 
 Expression *ExpInitializer::toExpression()
--- a/dmd/inline.c	Sat May 16 18:37:16 2009 +0200
+++ b/dmd/inline.c	Sat May 16 22:21:31 2009 +0200
@@ -1,5 +1,5 @@
 
-// Copyright (c) 1999-2007 by Digital Mars
+// Copyright (c) 1999-2008 by Digital Mars
 // All Rights Reserved
 // written by Walter Bright
 // http://www.digitalmars.com
@@ -929,8 +929,11 @@
 
 Statement *ReturnStatement::inlineScan(InlineScanState *iss)
 {
+    //printf("ReturnStatement::inlineScan()\n");
     if (exp)
+    {
 	exp = exp->inlineScan(iss);
+    }
     return this;
 }
 
@@ -1234,7 +1237,7 @@
     if (needThis() && !hasthis)
 	return 0;
 
-    if (inlineNest || (!semanticRun && !hdrscan))
+    if (inlineNest || (semanticRun < 3 && !hdrscan))
     {
 #if CANINLINE_LOG
 	printf("\t1: no, inlineNest = %d, semanticRun = %d\n", inlineNest, semanticRun);
@@ -1246,13 +1249,13 @@
     {
 	case ILSyes:
 #if CANINLINE_LOG
-	    printf("\tyes\n");
+	    printf("\t1: yes %s\n", toChars());
 #endif
 	    return 1;
 
 	case ILSno:
 #if CANINLINE_LOG
-	    printf("\t2: no\n");
+	    printf("\t1: no %s\n", toChars());
 #endif
 	    return 0;
 
@@ -1338,7 +1341,7 @@
     if (!hdrscan)    // Don't modify inlineStatus for header content scan
 	inlineStatus = ILSyes;
 #if CANINLINE_LOG
-    printf("\tyes\n");
+    printf("\t2: yes %s\n", toChars());
 #endif
     return 1;
 
@@ -1346,7 +1349,7 @@
     if (!hdrscan)    // Don't modify inlineStatus for header content scan
 	inlineStatus = ILSno;
 #if CANINLINE_LOG
-    printf("\tno\n");
+    printf("\t2: no %s\n", toChars());
 #endif
     return 0;
 }
--- a/dmd/interpret.c	Sat May 16 18:37:16 2009 +0200
+++ b/dmd/interpret.c	Sat May 16 22:21:31 2009 +0200
@@ -69,7 +69,7 @@
     else if (ident == Id::aaValues)
 	return interpret_aaValues(istate, arguments);
 
-    if (cantInterpret || semanticRun == 1)
+    if (cantInterpret || semanticRun == 3)
 	return NULL;
 
     if (needThis() || isNested() || !fbody)
@@ -77,13 +77,13 @@
 	return NULL;
     }
 
-    if (semanticRun == 0 && scope)
+    if (semanticRun < 3 && scope)
     {
 	semantic3(scope);
 	if (global.errors)	// if errors compiling this function
 	    return NULL;
     }
-    if (semanticRun < 2)
+    if (semanticRun < 4)
 	return NULL;
 
     Type *tb = type->toBasetype();
@@ -1525,6 +1525,15 @@
 	{   error("variable %s is used before initialization", v->toChars());
 	    return e;
 	}
+	if (v->value == NULL && v->init->isVoidInitializer())
+	{   /* Since a void initializer initializes to undefined
+	     * values, it is valid here to use the default initializer.
+	     * No attempt is made to determine if someone actually relies
+	     * on the void value - to do that we'd need a VoidExp.
+	     * That's probably a good enhancement idea.
+	     */
+	    v->value = v->type->defaultInit();
+	}
 	Expression *vie = v->value;
 	if (vie->op == TOKvar)
 	{
--- a/dmd/lexer.c	Sat May 16 18:37:16 2009 +0200
+++ b/dmd/lexer.c	Sat May 16 22:21:31 2009 +0200
@@ -3072,7 +3072,6 @@
     Token::tochars[TOKdotvar]		= "dotvar";
     Token::tochars[TOKdottype]		= "dottype";
     Token::tochars[TOKsymoff]		= "symoff";
-    Token::tochars[TOKtypedot]		= "typedot";
     Token::tochars[TOKarraylength]	= "arraylength";
     Token::tochars[TOKarrayliteral]	= "arrayliteral";
     Token::tochars[TOKassocarrayliteral] = "assocarrayliteral";
--- a/dmd/lexer.h	Sat May 16 18:37:16 2009 +0200
+++ b/dmd/lexer.h	Sat May 16 22:21:31 2009 +0200
@@ -51,7 +51,7 @@
 	TOKnull,	TOKassert,
 	TOKtrue,	TOKfalse,
 	TOKarray,	TOKcall,
-	TOKaddress,	TOKtypedot,
+	TOKaddress,
 	TOKtype,	TOKthrow,
 	TOKnew,		TOKdelete,
 	TOKstar,	TOKsymoff,
--- a/dmd/mangle.c	Sat May 16 18:37:16 2009 +0200
+++ b/dmd/mangle.c	Sat May 16 22:21:31 2009 +0200
@@ -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
@@ -24,7 +24,7 @@
 #include "id.h"
 #include "module.h"
 
-#if TARGET_LINUX || TARGET_OSX
+#if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_SOLARIS
 char *cpp_mangle(Dsymbol *s);
 #endif
 
@@ -117,7 +117,7 @@
 		    return ident->toChars();
 
 		case LINKcpp:
-#if DMDV2 && (TARGET_LINUX || TARGET_OSX)
+#if DMDV2 && (TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_SOLARIS)
 		    return cpp_mangle(this);
 #else
 		    // Windows C++ mangling is done by C++ back end
@@ -220,7 +220,9 @@
     printf("\n");
 #endif
     id = ident ? ident->toChars() : toChars();
-    if (tempdecl->parent)
+    if (!tempdecl)
+	error("is not defined");
+    else if (tempdecl->parent)
     {
 	char *p = tempdecl->parent->mangle();
 	if (p[0] == '_' && p[1] == 'D')
--- a/dmd/mars.h	Sat May 16 18:37:16 2009 +0200
+++ b/dmd/mars.h	Sat May 16 22:21:31 2009 +0200
@@ -36,6 +36,8 @@
 	_WIN64		Windows for AMD64
 	linux		Linux
 	__APPLE__	Mac OSX
+	__FreeBSD__	FreeBSD
+	__sun&&__SVR4	Solaris, OpenSolaris (yes, both macros are necessary)
 
 For the target systems, there are the target operating system and
 the target object file format:
@@ -44,13 +46,15 @@
 	TARGET_WINDOS	Covers 32 bit windows and 64 bit windows
 	TARGET_LINUX	Covers 32 and 64 bit linux
 	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
 
     It is expected that the compiler for each platform will be able
     to generate 32 and 64 bit code from the same compiler binary.
 
     Target object module format:
 	OMFOBJ		Intel Object Module Format, used on Windows
-	ELFOBJ		Elf Object Module Format, used on linux
+	ELFOBJ		Elf Object Module Format, used on linux, FreeBSD and Solaris
 	MACHOBJ		Mach-O Object Module Format, used on Mac OSX
 
     There are currently no macros for byte endianness order.
@@ -81,7 +85,8 @@
 #define STRUCTTHISREF DMDV2	// if 'this' for struct is a reference, not a pointer
 #define SNAN_DEFAULT_INIT DMDV2	// if floats are default initialized to signalling NaN
 
-/* Other targets are TARGET_LINUX and TARGET_OSX, which are
+/* Other targets are TARGET_LINUX, TARGET_OSX, TARGET_FREEBSD and
+ * TARGET_SOLARIS, which are
  * set on the command line via the compiler makefile.
  */
 
@@ -90,7 +95,7 @@
 #define OMFOBJ 1
 #endif
 
-#if TARGET_LINUX
+#if TARGET_LINUX || TARGET_FREEBSD || TARGET_SOLARIS
 #ifndef ELFOBJ
 #define ELFOBJ 1
 #endif
--- a/dmd/mtype.c	Sat May 16 18:37:16 2009 +0200
+++ b/dmd/mtype.c	Sat May 16 22:21:31 2009 +0200
@@ -72,11 +72,16 @@
  */
 
 int PTRSIZE = 4;
+
+/* REALSIZE = size a real consumes in memory
+ * REALPAD = 'padding' added to the CPU real size to bring it up to REALSIZE
+ * REALALIGNSIZE = alignment for reals
+ */
 #if TARGET_OSX
 int REALSIZE = 16;
 int REALPAD = 6;
 int REALALIGNSIZE = 16;
-#elif TARGET_LINUX || TARGET_FREEBSD
+#elif TARGET_LINUX || TARGET_FREEBSD || TARGET_SOLARIS
 int REALSIZE = 12;
 int REALPAD = 2;
 int REALALIGNSIZE = 4;
@@ -85,6 +90,7 @@
 int REALPAD = 0;
 int REALALIGNSIZE = 2;
 #endif
+
 int Tsize_t = Tuns32;
 int Tptrdiff_t = Tint32;
 
@@ -405,7 +411,7 @@
 void Type::toCBuffer3(OutBuffer *buf, HdrGenState *hgs, int mod)
 {
     if (mod != this->mod)
-    {	char *p;
+    {	const char *p;
 
 	switch (this->mod)
 	{
@@ -432,20 +438,18 @@
  */
 
 Type *Type::merge()
-{   Type *t;
-
+{
     //printf("merge(%s)\n", toChars());
-    t = this;
+    Type *t = this;
     assert(t);
     if (!deco)
     {
-	OutBuffer buf;
-	StringValue *sv;
-
 	if (next)
 	    next = next->merge();
+
+	OutBuffer buf;
 	toDecoBuffer(&buf, false);
-	sv = stringtable.update((char *)buf.data, buf.offset);
+	StringValue *sv = stringtable.update((char *)buf.data, buf.offset);
 	if (sv->ptrvalue)
 	{   t = (Type *) sv->ptrvalue;
 	    assert(t->deco);
@@ -477,6 +481,28 @@
     return t;
 }
 
+/*************************************
+ * This version does a merge even if the deco is already computed.
+ * Necessary for types that have a deco, but are not merged.
+ */
+Type *Type::merge2()
+{
+    //printf("merge2(%s)\n", toChars());
+    Type *t = this;
+    assert(t);
+    if (!t->deco)
+	return t->merge();
+
+    StringValue *sv = deco_stringtable.lookup((char *)t->deco, strlen(t->deco));
+    if (sv && sv->ptrvalue)
+    {   t = (Type *) sv->ptrvalue;
+	assert(t->deco);
+    }
+    else
+	assert(0);
+    return t;
+}
+
 int Type::isbit()
 {
     return FALSE;
@@ -563,7 +589,7 @@
     return NULL;
 }
 
-int Type::isZeroInit()
+int Type::isZeroInit(Loc loc)
 {
     return 0;		// assume not
 }
@@ -625,9 +651,14 @@
 	e = defaultInit(loc);
     }
     else if (ident == Id::mangleof)
-    {
-	assert(deco);
-	e = new StringExp(loc, deco, strlen(deco), 'c');
+    {	const char *s;
+	if (!deco)
+	{   s = toChars();
+	    error(loc, "forward reference of type %s.mangleof", s);
+	}
+	else
+	    s = deco;
+	e = new StringExp(loc, (char *)s, strlen(s), 'c');
 	Scope sc;
 	e = e->semantic(&sc);
     }
@@ -1049,6 +1080,17 @@
     if (ty == Tvoid)
         return 1;
     return GetTypeAlignment(sir, this);
+#if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_SOLARIS
+	case Tint64:
+	case Tuns64:
+	case Tfloat64:
+	case Timaginary64:
+	case Tcomplex32:
+	case Tcomplex64:
+	    sz = 4;
+	    break;
+#endif
+
 }
 
 
@@ -1089,7 +1131,7 @@
 	    case Tfloat64:	fvalue = DBL_MAX;	goto Lfvalue;
 	    case Tcomplex80:
 	    case Timaginary80:
-	    case Tfloat80:	fvalue = LDBL_MAX;	goto Lfvalue;
+	    case Tfloat80:	fvalue = Port::ldbl_max; goto Lfvalue;
 	}
     }
     else if (ident == Id::min)
@@ -1402,7 +1444,7 @@
     return new IntegerExp(loc, value, this);
 }
 
-int TypeBasic::isZeroInit()
+int TypeBasic::isZeroInit(Loc loc)
 {
     switch (ty)
     {
@@ -2050,9 +2092,9 @@
     return next->defaultInit(loc);
 }
 
-int TypeSArray::isZeroInit()
-{
-    return next->isZeroInit();
+int TypeSArray::isZeroInit(Loc loc)
+{
+    return next->isZeroInit(loc);
 }
 
 
@@ -2209,7 +2251,7 @@
     return e;
 }
 
-int TypeDArray::isZeroInit()
+int TypeDArray::isZeroInit(Loc loc)
 {
     return 1;
 }
@@ -2481,7 +2523,7 @@
     return e;
 }
 
-int TypeAArray::isZeroInit()
+int TypeAArray::isZeroInit(Loc loc)
 {
     return TRUE;
 }
@@ -2594,7 +2636,7 @@
     return e;
 }
 
-int TypePointer::isZeroInit()
+int TypePointer::isZeroInit(Loc loc)
 {
     return 1;
 }
@@ -2660,7 +2702,7 @@
     return e;
 }
 
-int TypeReference::isZeroInit()
+int TypeReference::isZeroInit(Loc loc)
 {
     return 1;
 }
@@ -2841,7 +2883,7 @@
 
 void TypeFunction::toCBuffer(OutBuffer *buf, Identifier *ident, HdrGenState *hgs)
 {
-    char *p = NULL;
+    const char *p = NULL;
 
     if (inuse)
     {	inuse = 2;		// flag error to caller
@@ -2880,7 +2922,7 @@
 
 void TypeFunction::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
 {
-    char *p = NULL;
+    const char *p = NULL;
 
     if (inuse)
     {	inuse = 2;		// flag error to caller
@@ -3223,7 +3265,7 @@
     return e;
 }
 
-int TypeDelegate::isZeroInit()
+int TypeDelegate::isZeroInit(Loc loc)
 {
     return 1;
 }
@@ -3865,6 +3907,8 @@
 	    error(loc, "expression (%s) has no type", exp->toChars());
 	    goto Lerr;
 	}
+	if (t->ty == Ttypeof)
+	    error(loc, "forward reference to %s", toChars());
     }
 
     if (idents.dim)
@@ -3966,7 +4010,7 @@
 	printf("2: ");
 #endif
 	error(sym->loc, "enum %s is forward referenced", sym->toChars());
-	return tint32;
+	return terror;
     }
     return sym->memtype->toBasetype();
 }
@@ -4020,8 +4064,8 @@
     return em;
 
 Lfwd:
-    error(e->loc, "forward reference of %s.%s", toChars(), ident->toChars());
-    return new IntegerExp(0, 0, this);
+    error(e->loc, "forward reference of enum %s.%s", toChars(), ident->toChars());
+    return new IntegerExp(0, 0, Type::terror);
 }
 
 Expression *TypeEnum::getProperty(Loc loc, Identifier *ident)
@@ -4109,7 +4153,7 @@
     return e;
 }
 
-int TypeEnum::isZeroInit()
+int TypeEnum::isZeroInit(Loc loc)
 {
     return (sym->defaultval == 0);
 }
@@ -4300,7 +4344,7 @@
     return e;
 }
 
-int TypeTypedef::isZeroInit()
+int TypeTypedef::isZeroInit(Loc loc)
 {
     if (sym->init)
     {
@@ -4317,7 +4361,7 @@
 	sym->basetype = Type::terror;
     }
     sym->inuse = 1;
-    int result = sym->basetype->isZeroInit();
+    int result = sym->basetype->isZeroInit(loc);
     sym->inuse = 0;
     return result;
 }
@@ -4613,7 +4657,7 @@
     return new VarExp(sym->loc, d);
 }
 
-int TypeStruct::isZeroInit()
+int TypeStruct::isZeroInit(Loc loc)
 {
     return sym->zeroInit;
 }
@@ -5074,7 +5118,7 @@
     return e;
 }
 
-int TypeClass::isZeroInit()
+int TypeClass::isZeroInit(Loc loc)
 {
     return 1;
 }
--- a/dmd/mtype.h	Sat May 16 18:37:16 2009 +0200
+++ b/dmd/mtype.h	Sat May 16 22:21:31 2009 +0200
@@ -222,6 +222,7 @@
     // append the mangleof or a string uniquely identifying this type to buf
     virtual void toDecoBuffer(OutBuffer *buf, bool mangle);
     Type *merge();
+    Type *merge2();
     virtual void toCBuffer(OutBuffer *buf, Identifier *ident, HdrGenState *hgs);
     virtual void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
     void toCBuffer3(OutBuffer *buf, HdrGenState *hgs, int mod);
@@ -249,7 +250,7 @@
     virtual Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
     virtual unsigned memalign(unsigned salign);
     virtual Expression *defaultInit(Loc loc = 0);
-    virtual int isZeroInit();		// if initializer is 0
+    virtual int isZeroInit(Loc loc = 0);		// if initializer is 0
 #if IN_DMD
     virtual dt_t **toDt(dt_t **pdt);
 #endif
@@ -310,7 +311,7 @@
     int isunsigned();
     MATCH implicitConvTo(Type *to);
     Expression *defaultInit(Loc loc);
-    int isZeroInit();
+    int isZeroInit(Loc loc);
     int builtinTypeInfo();
 
     // For eliminating dynamic_cast
@@ -338,7 +339,7 @@
     void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
     Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
     int isString();
-    int isZeroInit();
+    int isZeroInit(Loc loc);
     unsigned memalign(unsigned salign);
     MATCH implicitConvTo(Type *to);
     Expression *defaultInit(Loc loc);
@@ -369,7 +370,7 @@
     void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
     Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
     int isString();
-    int isZeroInit();
+    int isZeroInit(Loc loc);
     int checkBoolean();
     MATCH implicitConvTo(Type *to);
     Expression *defaultInit(Loc loc);
@@ -397,7 +398,7 @@
     Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
     Expression *defaultInit(Loc loc);
     MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes);
-    int isZeroInit();
+    int isZeroInit(Loc loc);
     int checkBoolean();
     TypeInfoDeclaration *getTypeInfoDeclaration();
     int hasPointers();
@@ -422,7 +423,7 @@
     // LDC: pointers are unsigned
     int isunsigned() { return TRUE; };
     Expression *defaultInit(Loc loc);
-    int isZeroInit();
+    int isZeroInit(Loc loc);
     TypeInfoDeclaration *getTypeInfoDeclaration();
     int hasPointers();
 
@@ -439,7 +440,7 @@
     void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
     Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
     Expression *defaultInit(Loc loc);
-    int isZeroInit();
+    int isZeroInit(Loc loc);
 };
 
 enum RET
@@ -493,7 +494,7 @@
     unsigned alignsize(); // added in LDC
     void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
     Expression *defaultInit(Loc loc);
-    int isZeroInit();
+    int isZeroInit(Loc loc);
     int checkBoolean();
     TypeInfoDeclaration *getTypeInfoDeclaration();
     Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
@@ -580,7 +581,7 @@
     Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
     unsigned memalign(unsigned salign);
     Expression *defaultInit(Loc loc);
-    int isZeroInit();
+    int isZeroInit(Loc loc);
     int checkBoolean();
 #if IN_DMD
     dt_t **toDt(dt_t **pdt);
@@ -621,7 +622,7 @@
     MATCH implicitConvTo(Type *to);
     Type *toBasetype();
     Expression *defaultInit(Loc loc);
-    int isZeroInit();
+    int isZeroInit(Loc loc);
     MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes);
     TypeInfoDeclaration *getTypeInfoDeclaration();
     int hasPointers();
@@ -658,7 +659,7 @@
     Type *toBasetype();
     MATCH implicitConvTo(Type *to);
     Expression *defaultInit(Loc loc);
-    int isZeroInit();
+    int isZeroInit(Loc loc);
 #if IN_DMD
     dt_t **toDt(dt_t **pdt);
 #endif
@@ -689,12 +690,20 @@
     int isBaseOf(Type *t, int *poffset);
     MATCH implicitConvTo(Type *to);
     Expression *defaultInit(Loc loc);
-    int isZeroInit();
+    int isZeroInit(Loc loc);
     MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes);
     int isauto();
     int checkBoolean();
     TypeInfoDeclaration *getTypeInfoDeclaration();
     int hasPointers();
+    int builtinTypeInfo();
+#if DMDV2
+    Type *toHeadMutable();
+    MATCH constConv(Type *to);
+#if TARGET_LINUX || TARGET_OSX
+    void toCppMangle(OutBuffer *buf, CppMangleState *cms);
+#endif
+#endif
 
 #if IN_DMD
     type *toCtype();
--- a/dmd/optimize.c	Sat May 16 18:37:16 2009 +0200
+++ b/dmd/optimize.c	Sat May 16 22:21:31 2009 +0200
@@ -292,7 +292,7 @@
 	    if (vf)
 	    {
 		e = sle->getField(type, vf->offset);
-		if (e != EXP_CANT_INTERPRET)
+		if (e && e != EXP_CANT_INTERPRET)
 		    return e;
 	    }
 	}
@@ -305,7 +305,7 @@
 	if (vf)
 	{
 	    Expression *e = sle->getField(type, vf->offset);
-	    if (e != EXP_CANT_INTERPRET)
+	    if (e && e != EXP_CANT_INTERPRET)
 		return e;
 	}
     }
--- a/dmd/parse.c	Sat May 16 18:37:16 2009 +0200
+++ b/dmd/parse.c	Sat May 16 22:21:31 2009 +0200
@@ -1,5334 +1,5338 @@
-
-// 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 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 = new 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 = new 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:
+	{   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;
+}
+
+
+/********************************* ***************************/
+
--- a/dmd/parse.h	Sat May 16 18:37:16 2009 +0200
+++ b/dmd/parse.h	Sat May 16 22:21:31 2009 +0200
@@ -69,6 +69,7 @@
     Array *parseModule();
     Array *parseDeclDefs(int once);
     Array *parseBlock();
+    void composeStorageClass(unsigned stc);
     TemplateDeclaration *parseTemplateDeclaration();
     TemplateParameters *parseTemplateParameterList();
     Dsymbol *parseMixin();
--- a/dmd/root/man.c	Sat May 16 18:37:16 2009 +0200
+++ b/dmd/root/man.c	Sat May 16 22:21:31 2009 +0200
@@ -26,7 +26,7 @@
 
 #endif
 
-#if linux
+#if linux || __FreeBSD__ || __sun&&__SVR4
 
 #include	<sys/types.h>
 #include	<sys/wait.h>
@@ -98,5 +98,3 @@
 #endif
 
 
-#if __FreeBSD__
-#endif
--- a/dmd/root/port.c	Sat May 16 18:37:16 2009 +0200
+++ b/dmd/root/port.c	Sat May 16 22:21:31 2009 +0200
@@ -1,754 +1,759 @@
-
-// Copyright (c) 1999-2009 by Digital Mars
-// All Rights Reserved
-// written by Walter Bright
-// http://www.digitalmars.com
-
-#include "port.h"
-
-#if __DMC__
-#include <math.h>
-#include <float.h>
-#include <fp.h>
-#include <time.h>
-#include <stdlib.h>
-#include <string.h>
-
-double Port::nan = NAN;
-double Port::infinity = INFINITY;
-double Port::dbl_max = DBL_MAX;
-double Port::dbl_min = DBL_MIN;
-
-int Port::isNan(double r)
-{
-    return ::isnan(r);
-}
-
-int Port::isNan(long double r)
-{
-    return ::isnan(r);
-}
-
-int Port::isSignallingNan(double r)
-{
-    /* A signalling NaN is a NaN with 0 as the most significant bit of
-     * its significand, which is bit 51 of 0..63 for 64 bit doubles.
-     */
-    return isNan(r) && !((((unsigned char*)&r)[6]) & 8);
-}
-
-int Port::isSignallingNan(long double r)
-{
-    /* A signalling NaN is a NaN with 0 as the most significant bit of
-     * its significand, which is bit 62 of 0..79 for 80 bit reals.
-     */
-    return isNan(r) && !((((unsigned char*)&r)[7]) & 0x40);
-}
-
-int Port::isFinite(double r)
-{
-    return ::isfinite(r);
-}
-
-int Port::isInfinity(double r)
-{
-    return (::fpclassify(r) == FP_INFINITE);
-}
-
-int Port::Signbit(double r)
-{
-    return ::signbit(r);
-}
-
-double Port::floor(double d)
-{
-    return ::floor(d);
-}
-
-double Port::pow(double x, double y)
-{
-    return ::pow(x, y);
-}
-
-unsigned long long Port::strtoull(const char *p, char **pend, int base)
-{
-    return ::strtoull(p, pend, base);
-}
-
-char *Port::ull_to_string(char *buffer, ulonglong ull)
-{
-    sprintf(buffer, "%llu", ull);
-    return buffer;
-}
-
-wchar_t *Port::ull_to_string(wchar_t *buffer, ulonglong ull)
-{
-    swprintf(buffer, sizeof(ulonglong) * 3 + 1, L"%llu", ull);
-    return buffer;
-}
-
-double Port::ull_to_double(ulonglong ull)
-{
-    return (double) ull;
-}
-
-const char *Port::list_separator()
-{
-    // LOCALE_SLIST for Windows
-    return ",";
-}
-
-const wchar_t *Port::wlist_separator()
-{
-    // LOCALE_SLIST for Windows
-    return L",";
-}
-
-char *Port::strupr(char *s)
-{
-    return ::strupr(s);
-}
-
-#endif
-
-#if _MSC_VER
-
-// Disable useless warnings about unreferenced functions
-#pragma warning (disable : 4514)
-
-#include <math.h>
-#include <float.h>
-#include <time.h>
-#include <errno.h>
-#include <string.h>
-#include <ctype.h>
-#include <stdlib.h>
-
-static unsigned long nanarray[2]= { 0xFFFFFFFF, 0x7FFFFFFF };
-//static unsigned long nanarray[2] = {0,0x7FF80000 };
-double Port::nan = (*(double *)nanarray);
-
-//static unsigned long infinityarray[2] = {0,0x7FF00000 };
-static double zero = 0;
-double Port::infinity = 1 / zero;
-
-double Port::dbl_max = DBL_MAX;
-double Port::dbl_min = DBL_MIN;
-
-struct PortInitializer
-{
-    PortInitializer();
-};
-
-static PortInitializer portinitializer;
-
-PortInitializer::PortInitializer()
-{
-    Port::infinity = std::numeric_limits<long double>::infinity();
-}
-
-int Port::isNan(double r)
-{
-    return ::_isnan(r);
-}
-
-int Port::isNan(long double r)
-{
-    return ::_isnan(r);
-}
-
-int Port::isSignallingNan(double r)
-{
-    /* A signalling NaN is a NaN with 0 as the most significant bit of
-     * its significand, which is bit 51 of 0..63 for 64 bit doubles.
-     */
-    return isNan(r) && !((((unsigned char*)&r)[6]) & 8);
-}
-
-int Port::isSignallingNan(long double r)
-{
-    /* MSVC doesn't have 80 bit long doubles
-     */
-    return isSignallingNan((double) r);
-}
-
-int Port::isFinite(double r)
-{
-    return ::_finite(r);
-}
-
-int Port::isInfinity(double r)
-{
-    return (::_fpclass(r) & (_FPCLASS_NINF | _FPCLASS_PINF));
-}
-
-int Port::Signbit(double r)
-{
-    return (long)(((long *)&(r))[1] & 0x80000000);
-}
-
-double Port::floor(double d)
-{
-    return ::floor(d);
-}
-
-double Port::pow(double x, double y)
-{
-    if (y == 0)
-	return 1;		// even if x is NAN
-    return ::pow(x, y);
-}
-
-unsigned _int64 Port::strtoull(const char *p, char **pend, int base)
-{
-    unsigned _int64 number = 0;
-    int c;
-    int error;
-    #define ULLONG_MAX ((unsigned _int64)~0I64)
-
-    while (isspace(*p))		/* skip leading white space	*/
-	p++;
-    if (*p == '+')
-	p++;
-    switch (base)
-    {   case 0:
-	    base = 10;		/* assume decimal base		*/
-	    if (*p == '0')
-	    {   base = 8;	/* could be octal		*/
-		    p++;
-		    switch (*p)
-		    {   case 'x':
-			case 'X':
-			    base = 16;	/* hex			*/
-			    p++;
-			    break;
-#if BINARY
-			case 'b':
-			case 'B':
-			    base = 2;	/* binary		*/
-			    p++;
-			    break;
-#endif
-		    }
-	    }
-	    break;
-	case 16:			/* skip over '0x' and '0X'	*/
-	    if (*p == '0' && (p[1] == 'x' || p[1] == 'X'))
-		    p += 2;
-	    break;
-#if BINARY
-	case 2:			/* skip over '0b' and '0B'	*/
-	    if (*p == '0' && (p[1] == 'b' || p[1] == 'B'))
-		    p += 2;
-	    break;
-#endif
-    }
-    error = 0;
-    for (;;)
-    {   c = *p;
-	if (isdigit(c))
-		c -= '0';
-	else if (isalpha(c))
-		c = (c & ~0x20) - ('A' - 10);
-	else			/* unrecognized character	*/
-		break;
-	if (c >= base)		/* not in number base		*/
-		break;
-	if ((ULLONG_MAX - c) / base < number)
-		error = 1;
-	number = number * base + c;
-	p++;
-    }
-    if (pend)
-	*pend = (char *)p;
-    if (error)
-    {   number = ULLONG_MAX;
-	errno = ERANGE;
-    }
-    return number;
-}
-
-char *Port::ull_to_string(char *buffer, ulonglong ull)
-{
-    _ui64toa(ull, buffer, 10);
-    return buffer;
-}
-
-wchar_t *Port::ull_to_string(wchar_t *buffer, ulonglong ull)
-{
-    _ui64tow(ull, buffer, 10);
-    return buffer;
-}
-
-double Port::ull_to_double(ulonglong ull)
-{   double d;
-
-    if ((__int64) ull < 0)
-    {
-	// MSVC doesn't implement the conversion
-	d = (double) (__int64)(ull -  0x8000000000000000i64);
-	d += (double)(signed __int64)(0x7FFFFFFFFFFFFFFFi64) + 1.0;
-    }
-    else
-	d = (double)(__int64)ull;
-    return d;
-}
-
-const char *Port::list_separator()
-{
-    // LOCALE_SLIST for Windows
-    return ",";
-}
-
-const wchar_t *Port::wlist_separator()
-{
-    // LOCALE_SLIST for Windows
-    return L",";
-}
-
-char *Port::strupr(char *s)
-{
-    return ::strupr(s);
-}
-
-#endif
-
-#if linux || __APPLE__ || __FreeBSD__
-
-#include <math.h>
-#if linux
-#include <bits/nan.h>
-#include <bits/mathdef.h>
-#endif
-#include <time.h>
-#include <sys/time.h>
-#include <unistd.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <ctype.h>
-
-static double zero = 0;
-double Port::nan = NAN;
-double Port::infinity = 1 / zero;
-double Port::dbl_max = 1.7976931348623157e308;
-double Port::dbl_min = 5e-324;
-
-struct PortInitializer
-{
-    PortInitializer();
-};
-
-static PortInitializer portinitializer;
-
-PortInitializer::PortInitializer()
-{
-    // gcc nan's have the sign bit set by default, so turn it off
-    // Need the volatile to prevent gcc from doing incorrect
-    // constant folding.
-    volatile long double foo;
-    foo = NAN;
-    if (signbit(foo))	// signbit sometimes, not always, set
-	foo = -foo;	// turn off sign bit
-    Port::nan = foo;
-}
-
-#undef isnan
-int Port::isNan(double r)
-{
-#if __APPLE__
-    return __inline_isnan(r);
-#else
-    return ::isnan(r);
-#endif
-}
-
-int Port::isNan(long double r)
-{
-#if __APPLE__
-    return __inline_isnan(r);
-#else
-    return ::isnan(r);
-#endif
-}
-
-int Port::isSignallingNan(double r)
-{
-    /* A signalling NaN is a NaN with 0 as the most significant bit of
-     * its significand, which is bit 51 of 0..63 for 64 bit doubles.
-     */
-    return isNan(r) && !((((unsigned char*)&r)[6]) & 8);
-}
-
-int Port::isSignallingNan(long double r)
-{
-    /* A signalling NaN is a NaN with 0 as the most significant bit of
-     * its significand, which is bit 62 of 0..79 for 80 bit reals.
-     */
-    return isNan(r) && !((((unsigned char*)&r)[7]) & 0x40);
-}
-
-#undef isfinite
-int Port::isFinite(double r)
-{
-    return ::finite(r);
-}
-
-#undef isinf
-int Port::isInfinity(double r)
-{
-#if __APPLE__
-    return fpclassify(r) == FP_INFINITE;
-#else
-    return ::isinf(r);
-#endif
-}
-
-#undef signbit
-int Port::Signbit(double r)
-{
-    return (long)(((long *)&r)[1] & 0x80000000);
-}
-
-double Port::floor(double d)
-{
-    return ::floor(d);
-}
-
-double Port::pow(double x, double y)
-{
-    return ::pow(x, y);
-}
-
-unsigned long long Port::strtoull(const char *p, char **pend, int base)
-{
-    return ::strtoull(p, pend, base);
-}
-
-char *Port::ull_to_string(char *buffer, ulonglong ull)
-{
-    sprintf(buffer, "%llu", ull);
-    return buffer;
-}
-
-wchar_t *Port::ull_to_string(wchar_t *buffer, ulonglong ull)
-{
-    swprintf(buffer, sizeof(ulonglong) * 3 + 1, L"%llu", ull);
-    return buffer;
-}
-
-double Port::ull_to_double(ulonglong ull)
-{
-    return (double) ull;
-}
-
-const char *Port::list_separator()
-{
-    return ",";
-}
-
-const wchar_t *Port::wlist_separator()
-{
-    return L",";
-}
-
-char *Port::strupr(char *s)
-{
-    char *t = s;
-    
-    while (*s)
-    {
-	*s = toupper(*s);
-	s++;
-    }
-
-    return t;
-}
-
-#endif
-
-#if defined (__SVR4) && defined (__sun)
-
-#define __C99FEATURES__ 1	// Needed on Solaris for NaN and more
-#include <math.h>
-#include <time.h>
-#include <sys/time.h>
-#include <unistd.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <ctype.h>
-
-static double zero = 0;
-double Port::nan = NAN;
-double Port::infinity = 1 / zero;
-double Port::dbl_max = 1.7976931348623157e308;
-double Port::dbl_min = 5e-324;
-
-struct PortInitializer
-{
-    PortInitializer();
-};
-
-static PortInitializer portinitializer;
-
-PortInitializer::PortInitializer()
-{
-    // gcc nan's have the sign bit set by default, so turn it off
-    // Need the volatile to prevent gcc from doing incorrect
-    // constant folding.
-    volatile long double foo;
-    foo = NAN;
-    if (signbit(foo))	// signbit sometimes, not always, set
-	foo = -foo;	// turn off sign bit
-    Port::nan = foo;
-}
-
-#undef isnan
-int Port::isNan(double r)
-{
-#if __APPLE__
-    return __inline_isnan(r);
-#else
-    return ::isnan(r);
-#endif
-}
-
-int Port::isNan(long double r)
-{
-#if __APPLE__
-    return __inline_isnan(r);
-#else
-    return ::isnan(r);
-#endif
-}
-
-int Port::isSignallingNan(double r)
-{
-    /* A signalling NaN is a NaN with 0 as the most significant bit of
-     * its significand, which is bit 51 of 0..63 for 64 bit doubles.
-     */
-    return isNan(r) && !((((unsigned char*)&r)[6]) & 8);
-}
-
-int Port::isSignallingNan(long double r)
-{
-    /* A signalling NaN is a NaN with 0 as the most significant bit of
-     * its significand, which is bit 62 of 0..79 for 80 bit reals.
-     */
-    return isNan(r) && !((((unsigned char*)&r)[7]) & 0x40);
-}
-
-#undef isfinite
-int Port::isFinite(double r)
-{
-    return ::finite(r);
-}
-
-#undef isinf
-int Port::isInfinity(double r)
-{
-    return ::isinf(r);
-}
-
-#undef signbit
-int Port::Signbit(double r)
-{
-    return (long)(((long *)&r)[1] & 0x80000000);
-}
-
-double Port::floor(double d)
-{
-    return ::floor(d);
-}
-
-double Port::pow(double x, double y)
-{
-    return ::pow(x, y);
-}
-
-unsigned long long Port::strtoull(const char *p, char **pend, int base)
-{
-    return ::strtoull(p, pend, base);
-}
-
-char *Port::ull_to_string(char *buffer, ulonglong ull)
-{
-    sprintf(buffer, "%llu", ull);
-    return buffer;
-}
-
-wchar_t *Port::ull_to_string(wchar_t *buffer, ulonglong ull)
-{
-    swprintf(buffer, sizeof(ulonglong) * 3 + 1, L"%llu", ull);
-    return buffer;
-}
-
-double Port::ull_to_double(ulonglong ull)
-{
-    return (double) ull;
-}
-
-const char *Port::list_separator()
-{
-    return ",";
-}
-
-const wchar_t *Port::wlist_separator()
-{
-    return L",";
-}
-
-char *Port::strupr(char *s)
-{
-    char *t = s;
-    
-    while (*s)
-    {
-	*s = toupper(*s);
-	s++;
-    }
-
-    return t;
-}
-
-#endif
-
-#if IN_GCC
-
-#include <math.h>
-#include <bits/nan.h>
-#include <bits/mathdef.h>
-#include <time.h>
-#include <sys/time.h>
-#include <unistd.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <ctype.h>
-
-static double zero = 0;
-double Port::nan = NAN;
-double Port::infinity = 1 / zero;
-double Port::dbl_max = 1.7976931348623157e308;
-double Port::dbl_min = 5e-324;
-
-#include "d-gcc-real.h"
-extern "C" bool real_isnan (const real_t *);
-
-struct PortInitializer
-{
-    PortInitializer();
-};
-
-static PortInitializer portinitializer;
-
-PortInitializer::PortInitializer()
-{
-    Port::infinity = real_t::getinfinity();
-    Port::nan = real_t::getnan(real_t::LongDouble);
-}
-
-#undef isnan
-int Port::isNan(double r)
-{
-#if __APPLE__
-    return __inline_isnan(r);
-#else
-    return ::isnan(r);
-#endif
-}
-
-int Port::isNan(long double r)
-{
-    return real_isnan(&r);
-}
-
-int Port::isSignallingNan(double r)
-{
-    /* A signalling NaN is a NaN with 0 as the most significant bit of
-     * its significand, which is bit 51 of 0..63 for 64 bit doubles.
-     */
-    return isNan(r) && !((((unsigned char*)&r)[6]) & 8);
-}
-
-int Port::isSignallingNan(long double r)
-{
-    /* A signalling NaN is a NaN with 0 as the most significant bit of
-     * its significand, which is bit 62 of 0..79 for 80 bit reals.
-     */
-    return isNan(r) && !((((unsigned char*)&r)[7]) & 0x40);
-}
-
-#undef isfinite
-int Port::isFinite(double r)
-{
-    return ::finite(r);
-}
-
-#undef isinf
-int Port::isInfinity(double r)
-{
-    return ::isinf(r);
-}
-
-#undef signbit
-int Port::Signbit(double r)
-{
-    return (long)(((long *)&r)[1] & 0x80000000);
-}
-
-double Port::floor(double d)
-{
-    return ::floor(d);
-}
-
-double Port::pow(double x, double y)
-{
-    return ::pow(x, y);
-}
-
-unsigned long long Port::strtoull(const char *p, char **pend, int base)
-{
-    return ::strtoull(p, pend, base);
-}
-
-char *Port::ull_to_string(char *buffer, ulonglong ull)
-{
-    sprintf(buffer, "%llu", ull);
-    return buffer;
-}
-
-wchar_t *Port::ull_to_string(wchar_t *buffer, ulonglong ull)
-{
-    swprintf(buffer, L"%llu", ull);
-    return buffer;
-}
-
-double Port::ull_to_double(ulonglong ull)
-{
-    return (double) ull;
-}
-
-const char *Port::list_separator()
-{
-    return ",";
-}
-
-const wchar_t *Port::wlist_separator()
-{
-    return L",";
-}
-
-char *Port::strupr(char *s)
-{
-    char *t = s;
-    
-    while (*s)
-    {
-	*s = toupper(*s);
-	s++;
-    }
-
-    return t;
-}
-
-#endif
-
+
+// Copyright (c) 1999-2009 by Digital Mars
+// All Rights Reserved
+// written by Walter Bright
+// http://www.digitalmars.com
+
+#include "port.h"
+#if __DMC__
+#include <math.h>
+#include <float.h>
+#include <fp.h>
+#include <time.h>
+#include <stdlib.h>
+#include <string.h>
+
+double Port::nan = NAN;
+double Port::infinity = INFINITY;
+double Port::dbl_max = DBL_MAX;
+double Port::dbl_min = DBL_MIN;
+long double Port::ldbl_max = LDBL_MAX;
+
+int Port::isNan(double r)
+{
+    return ::isnan(r);
+}
+
+int Port::isNan(long double r)
+{
+    return ::isnan(r);
+}
+
+int Port::isSignallingNan(double r)
+{
+    /* A signalling NaN is a NaN with 0 as the most significant bit of
+     * its significand, which is bit 51 of 0..63 for 64 bit doubles.
+     */
+    return isNan(r) && !((((unsigned char*)&r)[6]) & 8);
+}
+
+int Port::isSignallingNan(long double r)
+{
+    /* A signalling NaN is a NaN with 0 as the most significant bit of
+     * its significand, which is bit 62 of 0..79 for 80 bit reals.
+     */
+    return isNan(r) && !((((unsigned char*)&r)[7]) & 0x40);
+}
+
+int Port::isFinite(double r)
+{
+    return ::isfinite(r);
+}
+
+int Port::isInfinity(double r)
+{
+    return (::fpclassify(r) == FP_INFINITE);
+}
+
+int Port::Signbit(double r)
+{
+    return ::signbit(r);
+}
+
+double Port::floor(double d)
+{
+    return ::floor(d);
+}
+
+double Port::pow(double x, double y)
+{
+    return ::pow(x, y);
+}
+
+unsigned long long Port::strtoull(const char *p, char **pend, int base)
+{
+    return ::strtoull(p, pend, base);
+}
+
+char *Port::ull_to_string(char *buffer, ulonglong ull)
+{
+    sprintf(buffer, "%llu", ull);
+    return buffer;
+}
+
+wchar_t *Port::ull_to_string(wchar_t *buffer, ulonglong ull)
+{
+    swprintf(buffer, sizeof(ulonglong) * 3 + 1, L"%llu", ull);
+    return buffer;
+}
+
+double Port::ull_to_double(ulonglong ull)
+{
+    return (double) ull;
+}
+
+const char *Port::list_separator()
+{
+    // LOCALE_SLIST for Windows
+    return ",";
+}
+
+const wchar_t *Port::wlist_separator()
+{
+    // LOCALE_SLIST for Windows
+    return L",";
+}
+
+char *Port::strupr(char *s)
+{
+    return ::strupr(s);
+}
+
+#endif
+
+#if _MSC_VER
+
+// Disable useless warnings about unreferenced functions
+#pragma warning (disable : 4514)
+
+#include <math.h>
+#include <float.h>
+#include <time.h>
+#include <errno.h>
+#include <string.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <limits> // for std::numeric_limits
+
+static unsigned long nanarray[2]= { 0xFFFFFFFF, 0x7FFFFFFF };
+//static unsigned long nanarray[2] = {0,0x7FF80000 };
+double Port::nan = (*(double *)nanarray);
+
+//static unsigned long infinityarray[2] = {0,0x7FF00000 };
+static double zero = 0;
+double Port::infinity = 1 / zero;
+
+double Port::dbl_max = DBL_MAX;
+double Port::dbl_min = DBL_MIN;
+long double Port::ldbl_max = LDBL_MAX;
+
+struct PortInitializer
+{
+    PortInitializer();
+};
+
+static PortInitializer portinitializer;
+
+PortInitializer::PortInitializer()
+{
+    Port::infinity = std::numeric_limits<long double>::infinity();
+}
+
+int Port::isNan(double r)
+{
+    return ::_isnan(r);
+}
+
+int Port::isNan(long double r)
+{
+    return ::_isnan(r);
+}
+
+int Port::isSignallingNan(double r)
+{
+    /* A signalling NaN is a NaN with 0 as the most significant bit of
+     * its significand, which is bit 51 of 0..63 for 64 bit doubles.
+     */
+    return isNan(r) && !((((unsigned char*)&r)[6]) & 8);
+}
+
+int Port::isSignallingNan(long double r)
+{
+    /* MSVC doesn't have 80 bit long doubles
+     */
+    return isSignallingNan((double) r);
+}
+
+int Port::isFinite(double r)
+{
+    return ::_finite(r);
+}
+
+int Port::isInfinity(double r)
+{
+    return (::_fpclass(r) & (_FPCLASS_NINF | _FPCLASS_PINF));
+}
+
+int Port::Signbit(double r)
+{
+    return (long)(((long *)&(r))[1] & 0x80000000);
+}
+
+double Port::floor(double d)
+{
+    return ::floor(d);
+}
+
+double Port::pow(double x, double y)
+{
+    if (y == 0)
+	return 1;		// even if x is NAN
+    return ::pow(x, y);
+}
+
+unsigned _int64 Port::strtoull(const char *p, char **pend, int base)
+{
+    unsigned _int64 number = 0;
+    int c;
+    int error;
+    #define ULLONG_MAX ((unsigned _int64)~0I64)
+
+    while (isspace(*p))		/* skip leading white space	*/
+	p++;
+    if (*p == '+')
+	p++;
+    switch (base)
+    {   case 0:
+	    base = 10;		/* assume decimal base		*/
+	    if (*p == '0')
+	    {   base = 8;	/* could be octal		*/
+		    p++;
+		    switch (*p)
+		    {   case 'x':
+			case 'X':
+			    base = 16;	/* hex			*/
+			    p++;
+			    break;
+#if BINARY
+			case 'b':
+			case 'B':
+			    base = 2;	/* binary		*/
+			    p++;
+			    break;
+#endif
+		    }
+	    }
+	    break;
+	case 16:			/* skip over '0x' and '0X'	*/
+	    if (*p == '0' && (p[1] == 'x' || p[1] == 'X'))
+		    p += 2;
+	    break;
+#if BINARY
+	case 2:			/* skip over '0b' and '0B'	*/
+	    if (*p == '0' && (p[1] == 'b' || p[1] == 'B'))
+		    p += 2;
+	    break;
+#endif
+    }
+    error = 0;
+    for (;;)
+    {   c = *p;
+	if (isdigit(c))
+		c -= '0';
+	else if (isalpha(c))
+		c = (c & ~0x20) - ('A' - 10);
+	else			/* unrecognized character	*/
+		break;
+	if (c >= base)		/* not in number base		*/
+		break;
+	if ((ULLONG_MAX - c) / base < number)
+		error = 1;
+	number = number * base + c;
+	p++;
+    }
+    if (pend)
+	*pend = (char *)p;
+    if (error)
+    {   number = ULLONG_MAX;
+	errno = ERANGE;
+    }
+    return number;
+}
+
+char *Port::ull_to_string(char *buffer, ulonglong ull)
+{
+    _ui64toa(ull, buffer, 10);
+    return buffer;
+}
+
+wchar_t *Port::ull_to_string(wchar_t *buffer, ulonglong ull)
+{
+    _ui64tow(ull, buffer, 10);
+    return buffer;
+}
+
+double Port::ull_to_double(ulonglong ull)
+{   double d;
+
+    if ((__int64) ull < 0)
+    {
+	// MSVC doesn't implement the conversion
+	d = (double) (__int64)(ull -  0x8000000000000000i64);
+	d += (double)(signed __int64)(0x7FFFFFFFFFFFFFFFi64) + 1.0;
+    }
+    else
+	d = (double)(__int64)ull;
+    return d;
+}
+
+const char *Port::list_separator()
+{
+    // LOCALE_SLIST for Windows
+    return ",";
+}
+
+const wchar_t *Port::wlist_separator()
+{
+    // LOCALE_SLIST for Windows
+    return L",";
+}
+
+char *Port::strupr(char *s)
+{
+    return ::strupr(s);
+}
+
+#endif
+
+#if linux || __APPLE__ || __FreeBSD__
+
+#include <math.h>
+#if linux
+#include <bits/nan.h>
+#include <bits/mathdef.h>
+#endif
+#include <time.h>
+#include <sys/time.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <float.h>
+
+static double zero = 0;
+double Port::nan = NAN;
+double Port::infinity = 1 / zero;
+double Port::dbl_max = 1.7976931348623157e308;
+double Port::dbl_min = 5e-324;
+long double Port::ldbl_max = LDBL_MAX;
+
+struct PortInitializer
+{
+    PortInitializer();
+};
+
+static PortInitializer portinitializer;
+
+PortInitializer::PortInitializer()
+{
+    // gcc nan's have the sign bit set by default, so turn it off
+    // Need the volatile to prevent gcc from doing incorrect
+    // constant folding.
+    volatile long double foo;
+    foo = NAN;
+    if (signbit(foo))	// signbit sometimes, not always, set
+	foo = -foo;	// turn off sign bit
+    Port::nan = foo;
+
+#if __FreeBSD__
+    // LDBL_MAX comes out as infinity. Fix.
+    static unsigned char x[sizeof(long double)] =
+	{ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0x7F };
+    Port::ldbl_max = *(long double *)&x[0];
+#endif
+}
+
+#undef isnan
+int Port::isNan(double r)
+{
+#if __APPLE__
+    return __inline_isnan(r);
+#else
+    return ::isnan(r);
+#endif
+}
+
+int Port::isNan(long double r)
+{
+#if __APPLE__
+    return __inline_isnan(r);
+#else
+    return ::isnan(r);
+#endif
+}
+
+int Port::isSignallingNan(double r)
+{
+    /* A signalling NaN is a NaN with 0 as the most significant bit of
+     * its significand, which is bit 51 of 0..63 for 64 bit doubles.
+     */
+    return isNan(r) && !((((unsigned char*)&r)[6]) & 8);
+}
+
+int Port::isSignallingNan(long double r)
+{
+    /* A signalling NaN is a NaN with 0 as the most significant bit of
+     * its significand, which is bit 62 of 0..79 for 80 bit reals.
+     */
+    return isNan(r) && !((((unsigned char*)&r)[7]) & 0x40);
+}
+
+#undef isfinite
+int Port::isFinite(double r)
+{
+    return ::finite(r);
+}
+
+#undef isinf
+int Port::isInfinity(double r)
+{
+#if __APPLE__
+    return fpclassify(r) == FP_INFINITE;
+#else
+    return ::isinf(r);
+#endif
+}
+
+#undef signbit
+int Port::Signbit(double r)
+{
+    return (long)(((long *)&r)[1] & 0x80000000);
+}
+
+double Port::floor(double d)
+{
+    return ::floor(d);
+}
+
+double Port::pow(double x, double y)
+{
+    return ::pow(x, y);
+}
+
+unsigned long long Port::strtoull(const char *p, char **pend, int base)
+{
+    return ::strtoull(p, pend, base);
+}
+
+char *Port::ull_to_string(char *buffer, ulonglong ull)
+{
+    sprintf(buffer, "%llu", ull);
+    return buffer;
+}
+
+wchar_t *Port::ull_to_string(wchar_t *buffer, ulonglong ull)
+{
+    swprintf(buffer, sizeof(ulonglong) * 3 + 1, L"%llu", ull);
+    return buffer;
+}
+
+double Port::ull_to_double(ulonglong ull)
+{
+    return (double) ull;
+}
+
+const char *Port::list_separator()
+{
+    return ",";
+}
+
+const wchar_t *Port::wlist_separator()
+{
+    return L",";
+}
+
+char *Port::strupr(char *s)
+{
+    char *t = s;
+    
+    while (*s)
+    {
+	*s = toupper(*s);
+	s++;
+    }
+
+    return t;
+}
+
+#endif
+
+#if __sun&&__SVR4
+
+#define __C99FEATURES__ 1	// Needed on Solaris for NaN and more
+#include <math.h>
+#include <time.h>
+#include <sys/time.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <float.h>
+#include <ieeefp.h>
+
+static double zero = 0;
+double Port::nan = NAN;
+double Port::infinity = 1 / zero;
+double Port::dbl_max = 1.7976931348623157e308;
+double Port::dbl_min = 5e-324;
+long double Port::ldbl_max = LDBL_MAX;
+
+struct PortInitializer
+{
+    PortInitializer();
+};
+
+static PortInitializer portinitializer;
+
+PortInitializer::PortInitializer()
+{
+    // gcc nan's have the sign bit set by default, so turn it off
+    // Need the volatile to prevent gcc from doing incorrect
+    // constant folding.
+    volatile long double foo;
+    foo = NAN;
+    if (signbit(foo))	// signbit sometimes, not always, set
+	foo = -foo;	// turn off sign bit
+    Port::nan = foo;
+}
+
+int Port::isNan(double r)
+{
+    return isnan(r);
+}
+
+int Port::isNan(long double r)
+{
+    return isnan(r);
+}
+
+int Port::isSignallingNan(double r)
+{
+    /* A signalling NaN is a NaN with 0 as the most significant bit of
+     * its significand, which is bit 51 of 0..63 for 64 bit doubles.
+     */
+    return isNan(r) && !((((unsigned char*)&r)[6]) & 8);
+}
+
+int Port::isSignallingNan(long double r)
+{
+    /* A signalling NaN is a NaN with 0 as the most significant bit of
+     * its significand, which is bit 62 of 0..79 for 80 bit reals.
+     */
+    return isNan(r) && !((((unsigned char*)&r)[7]) & 0x40);
+}
+
+#undef isfinite
+int Port::isFinite(double r)
+{
+    return finite(r);
+}
+
+int Port::isInfinity(double r)
+{
+    return isinf(r);
+}
+
+#undef signbit
+int Port::Signbit(double r)
+{
+    return (long)(((long *)&r)[1] & 0x80000000);
+}
+
+double Port::floor(double d)
+{
+    return ::floor(d);
+}
+
+double Port::pow(double x, double y)
+{
+    return ::pow(x, y);
+}
+
+unsigned long long Port::strtoull(const char *p, char **pend, int base)
+{
+    return ::strtoull(p, pend, base);
+}
+
+char *Port::ull_to_string(char *buffer, ulonglong ull)
+{
+    sprintf(buffer, "%llu", ull);
+    return buffer;
+}
+
+wchar_t *Port::ull_to_string(wchar_t *buffer, ulonglong ull)
+{
+    swprintf(buffer, sizeof(ulonglong) * 3 + 1, L"%llu", ull);
+    return buffer;
+}
+
+double Port::ull_to_double(ulonglong ull)
+{
+    return (double) ull;
+}
+
+const char *Port::list_separator()
+{
+    return ",";
+}
+
+const wchar_t *Port::wlist_separator()
+{
+    return L",";
+}
+
+char *Port::strupr(char *s)
+{
+    char *t = s;
+    
+    while (*s)
+    {
+	*s = toupper(*s);
+	s++;
+    }
+
+    return t;
+}
+
+#endif
+
+#if IN_GCC
+
+#include <math.h>
+#include <bits/nan.h>
+#include <bits/mathdef.h>
+#include <time.h>
+#include <sys/time.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+
+static double zero = 0;
+double Port::nan = NAN;
+double Port::infinity = 1 / zero;
+double Port::dbl_max = 1.7976931348623157e308;
+double Port::dbl_min = 5e-324;
+long double Port::ldbl_max = LDBL_MAX;
+
+#include "d-gcc-real.h"
+extern "C" bool real_isnan (const real_t *);
+
+struct PortInitializer
+{
+    PortInitializer();
+};
+
+static PortInitializer portinitializer;
+
+PortInitializer::PortInitializer()
+{
+    Port::infinity = real_t::getinfinity();
+    Port::nan = real_t::getnan(real_t::LongDouble);
+}
+
+#undef isnan
+int Port::isNan(double r)
+{
+#if __APPLE__
+    return __inline_isnan(r);
+#else
+    return ::isnan(r);
+#endif
+}
+
+int Port::isNan(long double r)
+{
+    return real_isnan(&r);
+}
+
+int Port::isSignallingNan(double r)
+{
+    /* A signalling NaN is a NaN with 0 as the most significant bit of
+     * its significand, which is bit 51 of 0..63 for 64 bit doubles.
+     */
+    return isNan(r) && !((((unsigned char*)&r)[6]) & 8);
+}
+
+int Port::isSignallingNan(long double r)
+{
+    /* A signalling NaN is a NaN with 0 as the most significant bit of
+     * its significand, which is bit 62 of 0..79 for 80 bit reals.
+     */
+    return isNan(r) && !((((unsigned char*)&r)[7]) & 0x40);
+}
+
+#undef isfinite
+int Port::isFinite(double r)
+{
+    return ::finite(r);
+}
+
+#undef isinf
+int Port::isInfinity(double r)
+{
+    return ::isinf(r);
+}
+
+#undef signbit
+int Port::Signbit(double r)
+{
+    return (long)(((long *)&r)[1] & 0x80000000);
+}
+
+double Port::floor(double d)
+{
+    return ::floor(d);
+}
+
+double Port::pow(double x, double y)
+{
+    return ::pow(x, y);
+}
+
+unsigned long long Port::strtoull(const char *p, char **pend, int base)
+{
+    return ::strtoull(p, pend, base);
+}
+
+char *Port::ull_to_string(char *buffer, ulonglong ull)
+{
+    sprintf(buffer, "%llu", ull);
+    return buffer;
+}
+
+wchar_t *Port::ull_to_string(wchar_t *buffer, ulonglong ull)
+{
+    swprintf(buffer, L"%llu", ull);
+    return buffer;
+}
+
+double Port::ull_to_double(ulonglong ull)
+{
+    return (double) ull;
+}
+
+const char *Port::list_separator()
+{
+    return ",";
+}
+
+const wchar_t *Port::wlist_separator()
+{
+    return L",";
+}
+
+char *Port::strupr(char *s)
+{
+    char *t = s;
+    
+    while (*s)
+    {
+	*s = toupper(*s);
+	s++;
+    }
+
+    return t;
+}
+
+#endif
+
--- a/dmd/root/port.h	Sat May 16 18:37:16 2009 +0200
+++ b/dmd/root/port.h	Sat May 16 22:21:31 2009 +0200
@@ -18,6 +18,11 @@
 #if _MSC_VER
 typedef __int64 longlong;
 typedef unsigned __int64 ulonglong;
+
+// According to VC 8.0 docs, long double is the same as double
+#define strtold strtod
+#define strtof  strtod
+
 #else
 typedef long long longlong;
 typedef unsigned long long ulonglong;
@@ -33,6 +38,7 @@
     static double infinity;
     static double dbl_max;
     static double dbl_min;
+    static long double ldbl_max;
 
 #if __GNUC__
     // These conflict with macros in math.h, should rename them
--- a/dmd/root/root.c	Sat May 16 18:37:16 2009 +0200
+++ b/dmd/root/root.c	Sat May 16 22:21:31 2009 +0200
@@ -7,6 +7,8 @@
 // in artistic.txt, or the GNU General Public License in gnu.txt.
 // See the included readme.txt for details.
 
+#define POSIX (linux || __APPLE__ || __FreeBSD__ || __sun&&__SVR4)
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <stdarg.h>
@@ -329,17 +331,21 @@
     namelen = strlen(name);
     f = (char *)mem.malloc(pathlen + 1 + namelen + 1);
     memcpy(f, path, pathlen);
-
-    if (
-	path[pathlen - 1] != '/'
-#if _WIN32
-	&& path[pathlen - 1] != '\\' && path[pathlen - 1] != ':'
-#endif
-    )
+#if POSIX
+    if (path[pathlen - 1] != '/')
     {	f[pathlen] = '/';
 	pathlen++;
     }
-
+#elif _WIN32
+    if (path[pathlen - 1] != '\\' &&
+	path[pathlen - 1] != '/'  &&
+	path[pathlen - 1] != ':')
+    {	f[pathlen] = '\\';
+	pathlen++;
+    }
+#else
+    assert(0);
+#endif
     memcpy(f + pathlen, name, namelen + 1);
     return f;
 }
@@ -475,20 +481,26 @@
 
 int FileName::compare(Object *obj)
 {
+    return compare(str, ((FileName *)obj)->str);
+}
+
+int FileName::compare(const char *name1, const char *name2)
+{
 #if _WIN32
-    return stricmp(str,((FileName *)obj)->str);
+    return stricmp(name1, name2);
 #else
-    return String::compare(obj);
+    return strcmp(name1, name2);
 #endif
 }
 
 int FileName::equals(Object *obj)
 {
-#if _WIN32
-    return stricmp(str,((FileName *)obj)->str) == 0;
-#else
-    return String::equals(obj);
-#endif
+    return compare(obj) == 0;
+}
+
+int FileName::equals(const char *name1, const char *name2)
+{
+    return compare(name1, name2) == 0;
 }
 
 /************************************
@@ -497,13 +509,15 @@
 
 int FileName::absolute(const char *name)
 {
-    return
 #if _WIN32
-	(*name == '\\') ||
-	(*name == '/')  ||
-	(*name && name[1] == ':') ||
+    return (*name == '\\') ||
+	   (*name == '/')  ||
+	   (*name && name[1] == ':');
+#elif POSIX
+    return (*name == '/');
+#else
+    assert(0);
 #endif
-	(*name == '/');
 }
 
 /********************************
@@ -523,13 +537,14 @@
 	switch (*e)
 	{   case '.':
 		return e + 1;
-
+#if POSIX
 	    case '/':
 	        break;
-
+#endif
 #if _WIN32
 	    case '\\':
 	    case ':':
+	    case '/':
 		break;
 #endif
 	    default:
@@ -578,7 +593,10 @@
     {
 	switch (*e)
 	{
-
+#if POSIX
+	    case '/':
+	       return e + 1;
+#endif
 #if _WIN32
 	    case '/':
 	    case '\\':
@@ -591,9 +609,6 @@
 		 */
 		if (e == str + 1 || e == str + len - 1)
 		    return e + 1;
-#else
-	    case '/':
-	       return e + 1;
 #endif
 	    default:
 		if (e == str)
@@ -623,13 +638,14 @@
 
     if (n > str)
     {
-
+#if POSIX
 	if (n[-1] == '/')
 	    n--;
-
-#if _WIN32
+#elif _WIN32
 	if (n[-1] == '\\' || n[-1] == '/')
 	    n--;
+#else
+	assert(0);
 #endif
     }
     pathlen = n - str;
@@ -643,7 +659,7 @@
  * Replace filename portion of path.
  */
 
-char *FileName::replaceName(char *path, char *name)
+const char *FileName::replaceName(const char *path, const char *name)
 {   char *f;
     char *n;
     size_t pathlen;
@@ -659,17 +675,21 @@
     namelen = strlen(name);
     f = (char *)mem.malloc(pathlen + 1 + namelen + 1);
     memcpy(f, path, pathlen);
-
-    if  (
-	path[pathlen - 1] != '/'
-#if _WIN32
-	&& path[pathlen - 1] != '\\' && path[pathlen - 1] != ':'
-#endif
-	)
+#if POSIX
+    if (path[pathlen - 1] != '/')
     {	f[pathlen] = '/';
 	pathlen++;
     }
-
+#elif _WIN32
+    if (path[pathlen - 1] != '\\' &&
+	path[pathlen - 1] != '/' &&
+	path[pathlen - 1] != ':')
+    {	f[pathlen] = '\\';
+	pathlen++;
+    }
+#else
+    assert(0);
+#endif
     memcpy(f + pathlen, name, namelen + 1);
     return f;
 }
@@ -736,9 +756,10 @@
 	return 0;
 #if POSIX
     return strcmp(e,ext) == 0;
-#endif
-#if _WIN32
+#elif _WIN32
     return stricmp(e,ext) == 0;
+#else
+    assert(0);
 #endif
 }
 
@@ -752,9 +773,10 @@
 
 #if _WIN32
     file.touchtime = mem.malloc(sizeof(WIN32_FIND_DATAA));	// keep same file time
-#endif
-#if POSIX
+#elif POSIX
     file.touchtime = mem.malloc(sizeof(struct stat)); // keep same file time
+#else
+    assert(0);
 #endif
     file.readv();
     file.name = to;
@@ -803,8 +825,7 @@
     if (S_ISDIR(st.st_mode))
 	return 2;
     return 1;
-#endif
-#if _WIN32
+#elif _WIN32
     DWORD dw;
     int result;
 
@@ -816,6 +837,8 @@
     else
 	result = 1;
     return result;
+#else
+    assert(0);
 #endif
 }
 
@@ -974,8 +997,7 @@
 err1:
     result = 1;
     return result;
-#endif
-#if _WIN32
+#elif _WIN32
     DWORD size;
     DWORD numread;
     HANDLE h;
@@ -1029,6 +1051,8 @@
 err1:
     result = 1;
     return result;
+#else
+    assert(0);
 #endif
 }
 
@@ -1040,8 +1064,7 @@
 {
 #if POSIX
     return read();
-#endif
-#if _WIN32
+#elif _WIN32
     HANDLE hFile;
     HANDLE hFileMap;
     DWORD size;
@@ -1081,6 +1104,8 @@
 
 Lerr:
     return GetLastError();			// failure
+#else
+    assert(0);
 #endif
 }
 
@@ -1124,8 +1149,7 @@
     ::remove(name);
 err:
     return 1;
-#endif
-#if _WIN32
+#elif _WIN32
     HANDLE h;
     DWORD numwritten;
     char *name;
@@ -1154,6 +1178,8 @@
     DeleteFileA(name);
 err:
     return 1;
+#else
+    assert(0);
 #endif
 }
 
@@ -1167,8 +1193,7 @@
 {
 #if POSIX
     return 1;
-#endif
-#if _WIN32
+#elif _WIN32
     HANDLE h;
     DWORD numwritten;
     char *name;
@@ -1203,6 +1228,8 @@
     CloseHandle(h);
 err:
     return 1;
+#else
+    assert(0);
 #endif
 }
 
@@ -1247,8 +1274,7 @@
 {
 #if POSIX
     return 0;
-#endif
-#if _WIN32
+#elif _WIN32
     DWORD dw;
     int result;
     char *name;
@@ -1265,6 +1291,8 @@
     else
 	result = 1;
     return result;
+#else
+    assert(0);
 #endif
 }
 
@@ -1272,9 +1300,10 @@
 {
 #if POSIX
     ::remove(this->name->toChars());
-#endif
-#if _WIN32
+#elif _WIN32
     DeleteFileA(this->name->toChars());
+#else
+    assert(0);
 #endif
 }
 
@@ -1287,8 +1316,7 @@
 {
 #if POSIX
     return NULL;
-#endif
-#if _WIN32
+#elif _WIN32
     HANDLE h;
     WIN32_FIND_DATAA fileinfo;
     Array *a;
@@ -1318,6 +1346,8 @@
 	FindClose(h);
     }
     return a;
+#else
+    assert(0);
 #endif
 }
 
@@ -1325,13 +1355,14 @@
 {
 #if POSIX
     return 0;
-#endif
-#if _WIN32
+#elif _WIN32
     if (!touchtime)
 	stat();
     if (!f->touchtime)
 	f->stat();
     return CompareFileTime(&((WIN32_FIND_DATAA *)touchtime)->ftLastWriteTime, &((WIN32_FIND_DATAA *)f->touchtime)->ftLastWriteTime);
+#else
+    assert(0);
 #endif
 }
 
@@ -1342,8 +1373,7 @@
     {
 	touchtime = mem.calloc(1, sizeof(struct stat));
     }
-#endif
-#if _WIN32
+#elif _WIN32
     HANDLE h;
 
     if (!touchtime)
@@ -1355,6 +1385,8 @@
     {
 	FindClose(h);
     }
+#else
+    assert(0);
 #endif
 }
 
@@ -1672,7 +1704,12 @@
     psize = sizeof(buffer);
     for (;;)
     {
-#if POSIX || IN_LLVM
+#if _WIN32
+	count = _vsnprintf(p,psize,format,args);
+	if (count != -1)
+	    break;
+	psize *= 2;
+#elif POSIX
         va_list va;
         va_copy(va, args);
 /*
@@ -1692,11 +1729,8 @@
 	    psize = count + 1;
 	else
 	    break;
-#elif _WIN32
-	count = _vsnprintf(p,psize,format,args);
-	if (count != -1)
-	    break;
-	psize *= 2;
+#else
+    assert(0);
 #endif
 	p = (char *) alloca(psize);	// buffer too small, try again with larger size
     }
@@ -1722,8 +1756,7 @@
 	if (count != -1)
 	    break;
 	psize *= 2;
-#endif
-#if POSIX
+#elif POSIX
         va_list va;
         va_copy(va, args);
 	count = vsnwprintf(p,psize,format,va);
@@ -1735,6 +1768,8 @@
 	    psize = count + 1;
 	else
 	    break;
+#else
+    assert(0);
 #endif
 	p = (dchar *) alloca(psize * 2);	// buffer too small, try again with larger size
     }
--- a/dmd/root/root.h	Sat May 16 18:37:16 2009 +0200
+++ b/dmd/root/root.h	Sat May 16 22:21:31 2009 +0200
@@ -128,7 +128,9 @@
     FileName(char *path, char *name);
     hash_t hashCode();
     int equals(Object *obj);
+    static int equals(const char *name1, const char *name2);
     int compare(Object *obj);
+    static int compare(const char *name1, const char *name2);
     static int absolute(const char *name);
     static char *ext(const char *);
     char *ext();
@@ -136,7 +138,7 @@
     static char *name(const char *);
     char *name();
     static char *path(const char *);
-    static char *replaceName(char *path, char *name);
+    static const char *replaceName(const char *path, const char *name);
 
     static char *combine(const char *path, const char *name);
     static Array *splitPath(const char *path);
--- a/dmd/scope.h	Sat May 16 18:37:16 2009 +0200
+++ b/dmd/scope.h	Sat May 16 22:21:31 2009 +0200
@@ -12,7 +12,7 @@
 
 #ifdef __DMC__
 #pragma once
-#endif /* __DMC__ */
+#endif
 
 struct Dsymbol;
 struct ScopeDsymbol;
@@ -29,10 +29,15 @@
 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
@@ -53,8 +58,8 @@
     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
-    TemplateInstance *tinst;	// enclosing template instance
     Statement *sbreak;		// enclosing statement that supports "break"
     Statement *scontinue;	// enclosing statement that supports "continue"
     ForeachStatement *fes;	// if nested function for ForeachStatement, this is it
--- a/dmd/statement.c	Sat May 16 18:37:16 2009 +0200
+++ b/dmd/statement.c	Sat May 16 22:21:31 2009 +0200
@@ -1128,7 +1128,8 @@
 
     sc->sbreak = this;
     sc->scontinue = this;
-    body = body->semantic(sc);
+    if (body)
+	body = body->semantic(sc);
     sc->noctor--;
 
     sc->pop();
--- a/dmd/staticassert.c	Sat May 16 18:37:16 2009 +0200
+++ b/dmd/staticassert.c	Sat May 16 22:21:31 2009 +0200
@@ -19,6 +19,7 @@
 #include "scope.h"
 #include "template.h"
 
+
 /********************************* AttribDeclaration ****************************/
 
 StaticAssert::StaticAssert(Loc loc, Expression *exp, Expression *msg)
@@ -47,6 +48,10 @@
 {
 }
 
+#include "scope.h"
+#include "template.h"
+#include "declaration.h"
+
 void StaticAssert::semantic2(Scope *sc)
 {
     Expression *e;
@@ -67,11 +72,12 @@
 	    error("%s", buf.toChars());
 	}
 	else
-	    error("is false");
-	if(sc->tinst)
+	    error("(%s) is false", exp->toChars());
+		if(sc->tinst)
 	    sc->tinst->printInstantiationTrace();
-	if (!global.gag)
-	    fatal();
+	  if (!global.gag) {
+	      fatal();
+	  }
     }
     else if (!e->isBool(TRUE))
     {
--- a/dmd/struct.c	Sat May 16 18:37:16 2009 +0200
+++ b/dmd/struct.c	Sat May 16 22:21:31 2009 +0200
@@ -427,7 +427,7 @@
 	    }
 	    else
 	    {
-		if (!vd->type->isZeroInit())
+		if (!vd->type->isZeroInit(loc))
 		{
 		    zeroInit = 0;
 		    break;
--- a/dmd/template.c	Sat May 16 18:37:16 2009 +0200
+++ b/dmd/template.c	Sat May 16 22:21:31 2009 +0200
@@ -1750,7 +1750,7 @@
 	    /* See if 'A' of the template parameter matches 'A'
 	     * of the type of the last function parameter.
 	     */
-	    Argument *fparam = (Argument *)tp->parameters->data[nfparams - 1];
+	    Argument *fparam = Argument::getNth(tp->parameters, nfparams - 1);
 	    if (fparam->type->ty != Tident)
 		goto L1;
 	    TypeIdentifier *tid = (TypeIdentifier *)fparam->type;
@@ -3059,6 +3059,7 @@
     this->tiargs = NULL;
     this->tempdecl = NULL;
     this->inst = NULL;
+    this->tinst = NULL;
     this->argsym = NULL;
     this->aliasdecl = NULL;
     this->semanticdone = 0;
@@ -3072,7 +3073,6 @@
 #if IN_LLVM
     // LDC
     this->emittedInModule = NULL;
-    this->tinst = NULL;
     this->tmodule = NULL;
 #endif
 }
@@ -3093,6 +3093,7 @@
     this->tiargs = tiargs;
     this->tempdecl = td;
     this->inst = NULL;
+    this->tinst = NULL;
     this->argsym = NULL;
     this->aliasdecl = NULL;
     this->semanticdone = 0;
@@ -3175,6 +3176,9 @@
 	return;
     }
 
+    // get the enclosing template instance from the scope tinst
+    tinst = sc->tinst;
+
     if (semanticdone != 0)
     {
 	error(loc, "recursive template expansion");
@@ -3420,6 +3424,14 @@
   __try
   {
 #endif
+    static int nest;
+    //printf("%d\n", nest);
+    if (++nest > 500)
+    {
+	global.gag = 0;			// ensure error message gets printed
+	error("recursive expansion");
+	fatal();
+    }
     for (int i = 0; i < members->dim; i++)
     {
 	Dsymbol *s = (Dsymbol *)members->data[i];
@@ -3432,6 +3444,7 @@
 	//printf("test4: isnested = %d, s->parent = %s\n", isnested, s->parent->toChars());
 	sc2->module->runDeferredSemantic();
     }
+    --nest;
 #if WINDOWS_SEH
   }
   __except (__ehfilter(GetExceptionInformation()))
@@ -3479,8 +3492,10 @@
     if (global.errors != errorsave)
     {
 	error("error instantiating");
-	if(tinst)
-	    tinst->printInstantiationTrace();
+	if (tinst && !global.gag)
+	{   tinst->printInstantiationTrace();
+	    fatal();
+	}
 	errors = 1;
 	if (global.gag)
 	    tempdecl->instances.remove(tempdecl_instance_idx);
@@ -3985,7 +4000,7 @@
 	  Lsa:
 	    buf.writeByte('S');
 	    Declaration *d = sa->isDeclaration();
-	    if (d && !d->type->deco)
+	    if (d && (!d->type || !d->type->deco))
 		error("forward reference of %s", d->toChars());
 	    else
 	    {
@@ -4089,6 +4104,12 @@
 
 #if IN_DMD
 
+void TemplateInstance::printInstantiationTrace()
+{
+    if (global.gag)
+	return;
+}
+
 void TemplateInstance::toObjFile(int multiobj)
 {
 #if LOG
@@ -4201,6 +4222,8 @@
     return s;
 }
 
+#if IN_LLVM
+
 void TemplateInstance::printInstantiationTrace()
 {
     if(global.gag)
@@ -4238,6 +4261,8 @@
     }
 }
 
+#endif
+
 /* ======================== TemplateMixin ================================ */
 
 TemplateMixin::TemplateMixin(Loc loc, Identifier *ident, Type *tqual,
@@ -4508,11 +4533,24 @@
     Scope *sc2;
     sc2 = scope->push(this);
     sc2->offset = sc->offset;
+
+    static int nest;
+    //printf("%d\n", nest);
+    if (++nest > 500)
+    {
+	global.gag = 0;			// ensure error message gets printed
+	error("recursive expansion");
+	fatal();
+    }
+
     for (int i = 0; i < members->dim; i++)
     {
 	Dsymbol *s = (Dsymbol *)members->data[i];
 	s->semantic(sc2);
     }
+
+    nest--;
+
     sc->offset = sc2->offset;
 
     /* The problem is when to parse the initializer for a variable.
--- a/dmd/template.h	Sat May 16 18:37:16 2009 +0200
+++ b/dmd/template.h	Sat May 16 22:21:31 2009 +0200
@@ -277,6 +277,7 @@
 
     TemplateDeclaration *tempdecl;	// referenced by foo.bar.abc
     TemplateInstance *inst;		// refer to existing instance
+    TemplateInstance *tinst;		// enclosing template instance
     ScopeDsymbol *argsym;		// argument symbol table
     AliasDeclaration *aliasdecl;	// !=NULL if instance is an alias for its
 					// sole member
@@ -308,6 +309,7 @@
     int oneMember(Dsymbol **ps);
     char *toChars();
     char *mangle();
+    void printInstantiationTrace();
 
 #if IN_DMD
     void toObjFile(int multiobj);			// compile to .obj file
@@ -327,10 +329,8 @@
 
 #if IN_LLVM
     // LDC
-    TemplateInstance *tinst; // enclosing template instance
     Module* tmodule; // module from outermost enclosing template instantiation
     Module* emittedInModule; // which module this template instance has been emitted in
-    void printInstantiationTrace();
 
     void codegen(Ir*);
 #endif
--- a/gen/classes.cpp	Sat May 16 18:37:16 2009 +0200
+++ b/gen/classes.cpp	Sat May 16 22:21:31 2009 +0200
@@ -806,6 +806,9 @@
         c = LLConstant::getNullValue(voidPtr);
     inits.push_back(c);
 
+    // typeinfo - since 1.045
+    inits.push_back(DtoTypeInfoOf(cd->type, true));
+
 #if DMDV2
 
     // xgetMembers
--- a/gen/toir.cpp	Sat May 16 18:37:16 2009 +0200
+++ b/gen/toir.cpp	Sat May 16 22:21:31 2009 +0200
@@ -1632,7 +1632,7 @@
         LLValue* mem = DtoNew(newtype);
         // init
         TypeStruct* ts = (TypeStruct*)ntype;
-        if (ts->isZeroInit()) {
+        if (ts->isZeroInit(ts->sym->loc)) {
             DtoAggrZeroInit(mem);
         }
         else {
@@ -2662,7 +2662,6 @@
 
 #define STUB(x) DValue *x::toElem(IRState * p) {error("Exp type "#x" not implemented: %s", toChars()); fatal(); return 0; }
 STUB(Expression);
-STUB(TypeDotIdExp);
 STUB(ScopeExp);
 STUB(TupleExp);
 
--- a/gen/typinf.cpp	Sat May 16 18:37:16 2009 +0200
+++ b/gen/typinf.cpp	Sat May 16 22:21:31 2009 +0200
@@ -253,6 +253,20 @@
 #endif
 }
 
+int TypeClass::builtinTypeInfo()
+{
+    /* This is statically put out with the ClassInfo, so
+     * claim it is built in so it isn't regenerated by each module.
+     */
+#if IN_DMD
+    return 1;
+#elif IN_LLVM
+    // FIXME if I enable this, the way LDC does typeinfo will cause a bunch
+    // of linker errors to missing class typeinfo definitions.
+    return 0;
+#endif
+}
+
 /* ========================================================================= */
 
 //////////////////////////////////////////////////////////////////////////////
--- a/runtime/internal/genobj.d	Sat May 16 18:37:16 2009 +0200
+++ b/runtime/internal/genobj.d	Sat May 16 22:21:31 2009 +0200
@@ -159,9 +159,11 @@
     //  2:                      // has no possible pointers into GC memory
     //  4:                      // has offTi[] member
     //  8:                      // has constructors
+    // 32:                      // has typeinfo
     void*       deallocator;
     OffsetTypeInfo[] offTi;
     void* defaultConstructor;   // default Constructor
+    TypeInfo typeinfo;
 
     /**
      * Search all modules for ClassInfo corresponding to classname.