changeset 1455:89e38fbfef1f

Automated merge with http://hg.dsource.org/projects/ldc
author Robert Clipsham <robert@octarineparrot.com>
date Mon, 01 Jun 2009 19:02:20 +0100
parents 301a916eceef (current diff) ff707c518ad7 (diff)
children 7b218ec1044f
files dmd2/array.c dmd2/dchar.c dmd2/dchar.h dmd2/e2ir.c.nolink dmd2/gnuc.c dmd2/gnuc.h dmd2/link.c.nolink dmd2/lstring.c dmd2/lstring.h dmd2/man.c dmd2/port.h dmd2/root.c dmd2/root.h dmd2/stringtable.c dmd2/stringtable.h gen/classes.cpp
diffstat 116 files changed, 67261 insertions(+), 65815 deletions(-) [+]
line wrap: on
line diff
--- a/.hgignore	Mon Jun 01 01:28:18 2009 +0200
+++ b/.hgignore	Mon Jun 01 19:02:20 2009 +0100
@@ -8,6 +8,7 @@
 *.a
 *.s
 *.so
+*.swp
 *.rej
 Makefile
 CMakeFiles
--- a/CMakeLists.txt	Mon Jun 01 01:28:18 2009 +0200
+++ b/CMakeLists.txt	Mon Jun 01 19:02:20 2009 +0100
@@ -70,10 +70,12 @@
 if(D_VERSION EQUAL 1)
 	set(DMDFE_PATH dmd)
 	set(LDC_EXE ldc)
+	set(LDMD_EXE ldmd)
 	add_definitions(-DDMDV1)
 elseif(D_VERSION EQUAL 2)
 	set(DMDFE_PATH dmd2)
 	set(LDC_EXE ldc2)
+	set(LDMD_EXE ldmd2)
 	add_definitions(-DDMDV2)
 else(D_VERSION EQUAL 1)
 	message(FATAL_ERROR "unsupported D version")
@@ -230,7 +232,7 @@
 # TODO: testrun
 
 install(TARGETS ${LDC_EXE} DESTINATION bin)
-install(FILES ${PROJECT_SOURCE_DIR}/bin/ldmd DESTINATION bin)
+install(FILES ${PROJECT_SOURCE_DIR}/bin/${LDMD_EXE} DESTINATION bin)
 install(FILES ${PROJECT_BINARY_DIR}/bin/${LDC_EXE}.conf DESTINATION ${CONF_INST_DIR})
 install(FILES ${PROJECT_BINARY_DIR}/bin/${LDC_EXE}.rebuild.conf DESTINATION ${CONF_INST_DIR})
 install(DIRECTORY ${PROJECT_BINARY_DIR}/lib DESTINATION . USE_SOURCE_PERMISSIONS)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bin/ldmd2	Mon Jun 01 19:02:20 2009 +0100
@@ -0,0 +1,43 @@
+#! /usr/bin/env bash
+
+# Default to 'ldc' next to this file
+LDC=`basename "$0"`/ldc2
+if [ ! -x "$LDC" ]; then
+    # If that doesn't work, assume this script was called via $PATH
+    # and do the same for ldc
+    if which ldc2 &> /dev/null; then
+        LDC=ldc2
+    else
+        echo 'ldc not found, check your installation' >/dev/stderr
+        exit 1
+    fi
+fi
+
+declare -a ARGS
+IDX=0
+for arg; do
+    case "$arg" in
+    -C*)
+        # turn -Cfoo into -foo.
+        # Useful for passing -inline to ldc, for instance.
+        arg="-${arg:2}"
+        ;;
+    -debug|-debug=*|-version=*)
+        arg="-d$arg"
+        ;;
+    -inline)
+        arg="-enable-inlining"
+        ;;
+    -fPIC)
+        arg="-relocation-model=pic"
+        ;;
+    --a|--b|--c|--f|--r|--w|--x|--y)
+        # "Hidden debug switches"
+        # Are these ever used?
+        arg="-hidden-debug${arg:1}"
+        ;;
+    esac
+    ARGS[IDX++]="$arg"
+done
+
+exec "$LDC" "${ARGS[@]}"
--- a/dmd2/access.c	Mon Jun 01 01:28:18 2009 +0200
+++ b/dmd2/access.c	Mon Jun 01 19:02:20 2009 +0100
@@ -1,424 +1,425 @@
-
-// Copyright (c) 1999-2006 by Digital Mars
-// All Rights Reserved
-// written by Walter Bright
-// http://www.digitalmars.com
-// License for redistribution is by either the Artistic License
-// in artistic.txt, or the GNU General Public License in gnu.txt.
-// See the included readme.txt for details.
-
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <assert.h>
-
-#include "root.h"
-#include "mem.h"
-
-#include "enum.h"
-#include "aggregate.h"
-#include "init.h"
-#include "attrib.h"
-#include "scope.h"
-#include "id.h"
-#include "mtype.h"
-#include "declaration.h"
-#include "aggregate.h"
-#include "expression.h"
-#include "module.h"
-
-#define LOG 0
-
-/* Code to do access checks
- */
-
-int hasPackageAccess(Scope *sc, Dsymbol *s);
-
-/****************************************
- * Return PROT access for Dsymbol smember in this declaration.
- */
-
-enum PROT AggregateDeclaration::getAccess(Dsymbol *smember)
-{
-    return PROTpublic;
-}
-
-enum PROT StructDeclaration::getAccess(Dsymbol *smember)
-{
-    enum PROT access_ret = PROTnone;
-
-#if LOG
-    printf("+StructDeclaration::getAccess(this = '%s', smember = '%s')\n",
-	toChars(), smember->toChars());
-#endif
-    if (smember->toParent() == this)
-    {
-	access_ret = smember->prot();
-    }
-    else if (smember->isDeclaration()->isStatic())
-    {
-	access_ret = smember->prot();
-    }
-    return access_ret;
-}
-
-enum PROT ClassDeclaration::getAccess(Dsymbol *smember)
-{
-    enum PROT access_ret = PROTnone;
-
-#if LOG
-    printf("+ClassDeclaration::getAccess(this = '%s', smember = '%s')\n",
-	toChars(), smember->toChars());
-#endif
-    if (smember->toParent() == this)
-    {
-	access_ret = smember->prot();
-    }
-    else
-    {
-	enum PROT access;
-	int i;
-
-	if (smember->isDeclaration()->isStatic())
-	{
-	    access_ret = smember->prot();
-	}
-
-	for (i = 0; i < baseclasses.dim; i++)
-	{   BaseClass *b = (BaseClass *)baseclasses.data[i];
-
-	    access = b->base->getAccess(smember);
-	    switch (access)
-	    {
-		case PROTnone:
-		    break;
-
-		case PROTprivate:
-		    access = PROTnone;	// private members of base class not accessible
-		    break;
-
-		case PROTpackage:
-		case PROTprotected:
-		case PROTpublic:
-		case PROTexport:
-		    // If access is to be tightened
-		    if (b->protection < access)
-			access = b->protection;
-
-		    // Pick path with loosest access
-		    if (access > access_ret)
-			access_ret = access;
-		    break;
-
-		default:
-		    assert(0);
-	    }
-	}
-    }
-#if LOG
-    printf("-ClassDeclaration::getAccess(this = '%s', smember = '%s') = %d\n",
-	toChars(), smember->toChars(), access_ret);
-#endif
-    return access_ret;
-}
-
-/********************************************************
- * Helper function for ClassDeclaration::accessCheck()
- * Returns:
- *	0	no access
- * 	1	access
- */
-
-static int accessCheckX(
-	Dsymbol *smember,
-	Dsymbol *sfunc,
-	AggregateDeclaration *dthis,
-	AggregateDeclaration *cdscope)
-{
-    assert(dthis);
-
-#if 0
-    printf("accessCheckX for %s.%s in function %s() in scope %s\n",
-	dthis->toChars(), smember->toChars(),
-	sfunc ? sfunc->toChars() : "NULL",
-	cdscope ? cdscope->toChars() : "NULL");
-#endif
-    if (dthis->hasPrivateAccess(sfunc) ||
-	dthis->isFriendOf(cdscope))
-    {
-	if (smember->toParent() == dthis)
-	    return 1;
-	else
-	{
-	    ClassDeclaration *cdthis = dthis->isClassDeclaration();
-	    if (cdthis)
-	    {
-		for (int i = 0; i < cdthis->baseclasses.dim; i++)
-		{   BaseClass *b = (BaseClass *)cdthis->baseclasses.data[i];
-		    enum PROT access;
-
-		    access = b->base->getAccess(smember);
-		    if (access >= PROTprotected ||
-			accessCheckX(smember, sfunc, b->base, cdscope)
-		       )
-			return 1;
-
-		}
-	    }
-	}
-    }
-    else
-    {
-	if (smember->toParent() != dthis)
-	{
-	    ClassDeclaration *cdthis = dthis->isClassDeclaration();
-	    if (cdthis)
-	    {
-		for (int i = 0; i < cdthis->baseclasses.dim; i++)
-		{   BaseClass *b = (BaseClass *)cdthis->baseclasses.data[i];
-
-		    if (accessCheckX(smember, sfunc, b->base, cdscope))
-			return 1;
-		}
-	    }
-	}
-    }
-    return 0;
-}
-
-/*******************************
- * Do access check for member of this class, this class being the
- * type of the 'this' pointer used to access smember.
- */
-
-void AggregateDeclaration::accessCheck(Loc loc, Scope *sc, Dsymbol *smember)
-{
-    int result;
-
-    FuncDeclaration *f = sc->func;
-    AggregateDeclaration *cdscope = sc->getStructClassScope();
-    enum PROT access;
-
-#if LOG
-    printf("AggregateDeclaration::accessCheck() for %s.%s in function %s() in scope %s\n",
-	toChars(), smember->toChars(),
-	f ? f->toChars() : NULL,
-	cdscope ? cdscope->toChars() : NULL);
-#endif
-
-    Dsymbol *smemberparent = smember->toParent();
-    if (!smemberparent || !smemberparent->isAggregateDeclaration())
-    {
-#if LOG
-	printf("not an aggregate member\n");
-#endif
-	return;				// then it is accessible
-    }
-
-    // BUG: should enable this check
-    //assert(smember->parent->isBaseOf(this, NULL));
-
-    if (smemberparent == this)
-    {	enum PROT access = smember->prot();
-
-	result = access >= PROTpublic ||
-		hasPrivateAccess(f) ||
-		isFriendOf(cdscope) ||
-		(access == PROTpackage && hasPackageAccess(sc, this));
-#if LOG
-	printf("result1 = %d\n", result);
-#endif
-    }
-    else if ((access = this->getAccess(smember)) >= PROTpublic)
-    {
-	result = 1;
-#if LOG
-	printf("result2 = %d\n", result);
-#endif
-    }
-    else if (access == PROTpackage && hasPackageAccess(sc, this))
-    {
-	result = 1;
-#if LOG
-	printf("result3 = %d\n", result);
-#endif
-    }
-    else
-    {
-	result = accessCheckX(smember, f, this, cdscope);
-#if LOG
-	printf("result4 = %d\n", result);
-#endif
-    }
-    if (!result)
-    {
-	error(loc, "member %s is not accessible", smember->toChars());
-halt();
-    }
-}
-
-/****************************************   
- * Determine if this is the same or friend of cd.
- */
-
-int AggregateDeclaration::isFriendOf(AggregateDeclaration *cd)
-{
-#if LOG
-    printf("AggregateDeclaration::isFriendOf(this = '%s', cd = '%s')\n", toChars(), cd ? cd->toChars() : "null");
-#endif
-    if (this == cd)
-	return 1;
-
-    // Friends if both are in the same module
-    //if (toParent() == cd->toParent())
-    if (cd && getModule() == cd->getModule())
-    {
-#if LOG
-	printf("\tin same module\n");
-#endif
-	return 1;
-    }
-
-#if LOG
-    printf("\tnot friend\n");
-#endif
-    return 0;
-}
-
-/****************************************
- * Determine if scope sc has package level access to s.
- */
-
-int hasPackageAccess(Scope *sc, Dsymbol *s)
-{
-#if LOG
-    printf("hasPackageAccess(s = '%s', sc = '%p')\n", s->toChars(), sc);
-#endif
-
-    for (; s; s = s->parent)
-    {
-	if (s->isPackage() && !s->isModule())
-	    break;
-    }
-#if LOG
-    if (s)
-	printf("\tthis is in package '%s'\n", s->toChars());
-#endif
-
-    if (s && s == sc->module->parent)
-    {
-#if LOG
-	printf("\ts is in same package as sc\n");
-#endif
-	return 1;
-    }
-
-
-#if LOG
-    printf("\tno package access\n");
-#endif
-    return 0;
-}
-
-/**********************************
- * Determine if smember has access to private members of this declaration.
- */
-
-int AggregateDeclaration::hasPrivateAccess(Dsymbol *smember)
-{
-    if (smember)
-    {	AggregateDeclaration *cd = NULL;
-	Dsymbol *smemberparent = smember->toParent();
-	if (smemberparent)
-	    cd = smemberparent->isAggregateDeclaration();
-
-#if LOG
-	printf("AggregateDeclaration::hasPrivateAccess(class %s, member %s)\n",
-		toChars(), smember->toChars());
-#endif
-
-	if (this == cd)		// smember is a member of this class
-	{
-#if LOG
-	    printf("\tyes 1\n");
-#endif
-	    return 1;		// so we get private access
-	}
-
-	// If both are members of the same module, grant access
-	while (1)
-	{   Dsymbol *sp = smember->toParent();
-	    if (sp->isFuncDeclaration() && smember->isFuncDeclaration())
-		smember = sp;
-	    else
-		break;
-	}
-	if (!cd && toParent() == smember->toParent())
-	{
-#if LOG
-	    printf("\tyes 2\n");
-#endif
-	    return 1;
-	}
-	if (!cd && getModule() == smember->getModule())
-	{
-#if LOG
-	    printf("\tyes 3\n");
-#endif
-	    return 1;
-	}
-    }
-#if LOG
-    printf("\tno\n");
-#endif
-    return 0;
-}
-
-/****************************************
- * Check access to d for expression e.d
- */
-
-void accessCheck(Loc loc, Scope *sc, Expression *e, Declaration *d)
-{
-#if LOG
-    if (e)
-    {	printf("accessCheck(%s . %s)\n", e->toChars(), d->toChars());
-	printf("\te->type = %s\n", e->type->toChars());
-    }
-    else
-    {
-	//printf("accessCheck(%s)\n", d->toChars());
-    }
-#endif
-    if (!e)
-    {
-	if (d->prot() == PROTprivate && d->getModule() != sc->module ||
-	    d->prot() == PROTpackage && !hasPackageAccess(sc, d))
-
-	    error(loc, "%s %s.%s is not accessible from %s",
-		d->kind(), d->getModule()->toChars(), d->toChars(), sc->module->toChars());
-    }
-    else if (e->type->ty == Tclass)
-    {   // Do access check
-	ClassDeclaration *cd;
-
-	cd = (ClassDeclaration *)(((TypeClass *)e->type)->sym);
-#if 1
-	if (e->op == TOKsuper)
-	{   ClassDeclaration *cd2;
-
-	    cd2 = sc->func->toParent()->isClassDeclaration();
-	    if (cd2)
-		cd = cd2;
-	}
-#endif
-	cd->accessCheck(loc, sc, d);
-    }
-    else if (e->type->ty == Tstruct)
-    {   // Do access check
-	StructDeclaration *cd;
-
-	cd = (StructDeclaration *)(((TypeStruct *)e->type)->sym);
-	cd->accessCheck(loc, sc, d);
-    }
-}
+
+// Copyright (c) 1999-2006 by Digital Mars
+// All Rights Reserved
+// written by Walter Bright
+// http://www.digitalmars.com
+// License for redistribution is by either the Artistic License
+// in artistic.txt, or the GNU General Public License in gnu.txt.
+// See the included readme.txt for details.
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+
+#include "root.h"
+#include "rmem.h"
+
+#include "enum.h"
+#include "aggregate.h"
+#include "init.h"
+#include "attrib.h"
+#include "scope.h"
+#include "id.h"
+#include "mtype.h"
+#include "declaration.h"
+#include "aggregate.h"
+#include "expression.h"
+#include "module.h"
+
+#define LOG 0
+
+/* Code to do access checks
+ */
+
+int hasPackageAccess(Scope *sc, Dsymbol *s);
+
+/****************************************
+ * Return PROT access for Dsymbol smember in this declaration.
+ */
+
+enum PROT AggregateDeclaration::getAccess(Dsymbol *smember)
+{
+    return PROTpublic;
+}
+
+enum PROT StructDeclaration::getAccess(Dsymbol *smember)
+{
+    enum PROT access_ret = PROTnone;
+
+#if LOG
+    printf("+StructDeclaration::getAccess(this = '%s', smember = '%s')\n",
+	toChars(), smember->toChars());
+#endif
+    if (smember->toParent() == this)
+    {
+	access_ret = smember->prot();
+    }
+    else if (smember->isDeclaration()->isStatic())
+    {
+	access_ret = smember->prot();
+    }
+    return access_ret;
+}
+
+enum PROT ClassDeclaration::getAccess(Dsymbol *smember)
+{
+    enum PROT access_ret = PROTnone;
+
+#if LOG
+    printf("+ClassDeclaration::getAccess(this = '%s', smember = '%s')\n",
+	toChars(), smember->toChars());
+#endif
+    if (smember->toParent() == this)
+    {
+	access_ret = smember->prot();
+    }
+    else
+    {
+	enum PROT access;
+	int i;
+
+	if (smember->isDeclaration()->isStatic())
+	{
+	    access_ret = smember->prot();
+	}
+
+	for (i = 0; i < baseclasses.dim; i++)
+	{   BaseClass *b = (BaseClass *)baseclasses.data[i];
+
+	    access = b->base->getAccess(smember);
+	    switch (access)
+	    {
+		case PROTnone:
+		    break;
+
+		case PROTprivate:
+		    access = PROTnone;	// private members of base class not accessible
+		    break;
+
+		case PROTpackage:
+		case PROTprotected:
+		case PROTpublic:
+		case PROTexport:
+		    // If access is to be tightened
+		    if (b->protection < access)
+			access = b->protection;
+
+		    // Pick path with loosest access
+		    if (access > access_ret)
+			access_ret = access;
+		    break;
+
+		default:
+		    assert(0);
+	    }
+	}
+    }
+#if LOG
+    printf("-ClassDeclaration::getAccess(this = '%s', smember = '%s') = %d\n",
+	toChars(), smember->toChars(), access_ret);
+#endif
+    return access_ret;
+}
+
+/********************************************************
+ * Helper function for ClassDeclaration::accessCheck()
+ * Returns:
+ *	0	no access
+ * 	1	access
+ */
+
+static int accessCheckX(
+	Dsymbol *smember,
+	Dsymbol *sfunc,
+	AggregateDeclaration *dthis,
+	AggregateDeclaration *cdscope)
+{
+    assert(dthis);
+
+#if 0
+    printf("accessCheckX for %s.%s in function %s() in scope %s\n",
+	dthis->toChars(), smember->toChars(),
+	sfunc ? sfunc->toChars() : "NULL",
+	cdscope ? cdscope->toChars() : "NULL");
+#endif
+    if (dthis->hasPrivateAccess(sfunc) ||
+	dthis->isFriendOf(cdscope))
+    {
+	if (smember->toParent() == dthis)
+	    return 1;
+	else
+	{
+	    ClassDeclaration *cdthis = dthis->isClassDeclaration();
+	    if (cdthis)
+	    {
+		for (int i = 0; i < cdthis->baseclasses.dim; i++)
+		{   BaseClass *b = (BaseClass *)cdthis->baseclasses.data[i];
+		    enum PROT access;
+
+		    access = b->base->getAccess(smember);
+		    if (access >= PROTprotected ||
+			accessCheckX(smember, sfunc, b->base, cdscope)
+		       )
+			return 1;
+
+		}
+	    }
+	}
+    }
+    else
+    {
+	if (smember->toParent() != dthis)
+	{
+	    ClassDeclaration *cdthis = dthis->isClassDeclaration();
+	    if (cdthis)
+	    {
+		for (int i = 0; i < cdthis->baseclasses.dim; i++)
+		{   BaseClass *b = (BaseClass *)cdthis->baseclasses.data[i];
+
+		    if (accessCheckX(smember, sfunc, b->base, cdscope))
+			return 1;
+		}
+	    }
+	}
+    }
+    return 0;
+}
+
+/*******************************
+ * Do access check for member of this class, this class being the
+ * type of the 'this' pointer used to access smember.
+ */
+
+void AggregateDeclaration::accessCheck(Loc loc, Scope *sc, Dsymbol *smember)
+{
+    int result;
+
+    FuncDeclaration *f = sc->func;
+    AggregateDeclaration *cdscope = sc->getStructClassScope();
+    enum PROT access;
+
+#if LOG
+    printf("AggregateDeclaration::accessCheck() for %s.%s in function %s() in scope %s\n",
+	toChars(), smember->toChars(),
+	f ? f->toChars() : NULL,
+	cdscope ? cdscope->toChars() : NULL);
+#endif
+
+    Dsymbol *smemberparent = smember->toParent();
+    if (!smemberparent || !smemberparent->isAggregateDeclaration())
+    {
+#if LOG
+	printf("not an aggregate member\n");
+#endif
+	return;				// then it is accessible
+    }
+
+    // BUG: should enable this check
+    //assert(smember->parent->isBaseOf(this, NULL));
+
+    if (smemberparent == this)
+    {	enum PROT access = smember->prot();
+
+	result = access >= PROTpublic ||
+		hasPrivateAccess(f) ||
+		isFriendOf(cdscope) ||
+		(access == PROTpackage && hasPackageAccess(sc, this));
+#if LOG
+	printf("result1 = %d\n", result);
+#endif
+    }
+    else if ((access = this->getAccess(smember)) >= PROTpublic)
+    {
+	result = 1;
+#if LOG
+	printf("result2 = %d\n", result);
+#endif
+    }
+    else if (access == PROTpackage && hasPackageAccess(sc, this))
+    {
+	result = 1;
+#if LOG
+	printf("result3 = %d\n", result);
+#endif
+    }
+    else
+    {
+	result = accessCheckX(smember, f, this, cdscope);
+#if LOG
+	printf("result4 = %d\n", result);
+#endif
+    }
+    if (!result)
+    {
+	error(loc, "member %s is not accessible", smember->toChars());
+halt();
+    }
+}
+
+/****************************************
+ * Determine if this is the same or friend of cd.
+ */
+
+int AggregateDeclaration::isFriendOf(AggregateDeclaration *cd)
+{
+#if LOG
+    printf("AggregateDeclaration::isFriendOf(this = '%s', cd = '%s')\n", toChars(), cd ? cd->toChars() : "null");
+#endif
+    if (this == cd)
+	return 1;
+
+    // Friends if both are in the same module
+    //if (toParent() == cd->toParent())
+    if (cd && getModule() == cd->getModule())
+    {
+#if LOG
+	printf("\tin same module\n");
+#endif
+	return 1;
+    }
+
+#if LOG
+    printf("\tnot friend\n");
+#endif
+    return 0;
+}
+
+/****************************************
+ * Determine if scope sc has package level access to s.
+ */
+
+int hasPackageAccess(Scope *sc, Dsymbol *s)
+{
+#if LOG
+    printf("hasPackageAccess(s = '%s', sc = '%p')\n", s->toChars(), sc);
+#endif
+
+    for (; s; s = s->parent)
+    {
+	if (s->isPackage() && !s->isModule())
+	    break;
+    }
+#if LOG
+    if (s)
+	printf("\tthis is in package '%s'\n", s->toChars());
+#endif
+
+    if (s && s == sc->module->parent)
+    {
+#if LOG
+	printf("\ts is in same package as sc\n");
+#endif
+	return 1;
+    }
+
+
+#if LOG
+    printf("\tno package access\n");
+#endif
+    return 0;
+}
+
+/**********************************
+ * Determine if smember has access to private members of this declaration.
+ */
+
+int AggregateDeclaration::hasPrivateAccess(Dsymbol *smember)
+{
+    if (smember)
+    {	AggregateDeclaration *cd = NULL;
+	Dsymbol *smemberparent = smember->toParent();
+	if (smemberparent)
+	    cd = smemberparent->isAggregateDeclaration();
+
+#if LOG
+	printf("AggregateDeclaration::hasPrivateAccess(class %s, member %s)\n",
+		toChars(), smember->toChars());
+#endif
+
+	if (this == cd)		// smember is a member of this class
+	{
+#if LOG
+	    printf("\tyes 1\n");
+#endif
+	    return 1;		// so we get private access
+	}
+
+	// If both are members of the same module, grant access
+	while (1)
+	{   Dsymbol *sp = smember->toParent();
+	    if (sp->isFuncDeclaration() && smember->isFuncDeclaration())
+		smember = sp;
+	    else
+		break;
+	}
+	if (!cd && toParent() == smember->toParent())
+	{
+#if LOG
+	    printf("\tyes 2\n");
+#endif
+	    return 1;
+	}
+	if (!cd && getModule() == smember->getModule())
+	{
+#if LOG
+	    printf("\tyes 3\n");
+#endif
+	    return 1;
+	}
+    }
+#if LOG
+    printf("\tno\n");
+#endif
+    return 0;
+}
+
+/****************************************
+ * Check access to d for expression e.d
+ */
+
+void accessCheck(Loc loc, Scope *sc, Expression *e, Declaration *d)
+{
+#if LOG
+    if (e)
+    {	printf("accessCheck(%s . %s)\n", e->toChars(), d->toChars());
+	printf("\te->type = %s\n", e->type->toChars());
+    }
+    else
+    {
+	//printf("accessCheck(%s)\n", d->toChars());
+    }
+#endif
+    if (!e)
+    {
+	if (d->getModule() != sc->module)
+	    if (d->prot() == PROTprivate ||
+		d->prot() == PROTpackage && !hasPackageAccess(sc, d))
+
+		error(loc, "%s %s.%s is not accessible from %s",
+		    d->kind(), d->getModule()->toChars(), d->toChars(), sc->module->toChars());
+    }
+    else if (e->type->ty == Tclass)
+    {   // Do access check
+	ClassDeclaration *cd;
+
+	cd = (ClassDeclaration *)(((TypeClass *)e->type)->sym);
+#if 1
+	if (e->op == TOKsuper)
+	{   ClassDeclaration *cd2;
+
+	    cd2 = sc->func->toParent()->isClassDeclaration();
+	    if (cd2)
+		cd = cd2;
+	}
+#endif
+	cd->accessCheck(loc, sc, d);
+    }
+    else if (e->type->ty == Tstruct)
+    {   // Do access check
+	StructDeclaration *cd;
+
+	cd = (StructDeclaration *)(((TypeStruct *)e->type)->sym);
+	cd->accessCheck(loc, sc, d);
+    }
+}
--- a/dmd2/aggregate.h	Mon Jun 01 01:28:18 2009 +0200
+++ b/dmd2/aggregate.h	Mon Jun 01 19:02:20 2009 +0100
@@ -1,292 +1,320 @@
-
-// Compiler implementation of the D programming language
-// Copyright (c) 1999-2008 by Digital Mars
-// All Rights Reserved
-// written by Walter Bright
-// http://www.digitalmars.com
-// License for redistribution is by either the Artistic License
-// in artistic.txt, or the GNU General Public License in gnu.txt.
-// See the included readme.txt for details.
-
-#ifndef DMD_AGGREGATE_H
-#define DMD_AGGREGATE_H
-
-#ifdef __DMC__
-#pragma once
-#endif /* __DMC__ */
-
-#include "root.h"
-#include "dsymbol.h"
-
-#include <vector>
-#include <set>
-#include <map>
-
-struct Identifier;
-struct Type;
-struct TypeFunction;
-struct Expression;
-struct FuncDeclaration;
-struct CtorDeclaration;
-struct DtorDeclaration;
-struct InvariantDeclaration;
-struct NewDeclaration;
-struct DeleteDeclaration;
-struct InterfaceDeclaration;
-struct ClassInfoDeclaration;
-struct VarDeclaration;
-struct dt_t;
-
-namespace llvm
-{
-    class Type;
-    class Value;
-    class Constant;
-    class ConstantStruct;
-    class GlobalVariable;
-}
-
-struct AggregateDeclaration : ScopeDsymbol
-{
-    Type *type;
-    unsigned storage_class;
-    enum PROT protection;
-    Type *handle;		// 'this' type
-    unsigned structsize;	// size of struct
-    unsigned alignsize;		// size of struct for alignment purposes
-    unsigned structalign;	// struct member alignment in effect
-    int hasUnions;		// set if aggregate has overlapping fields
-    Array fields;		// VarDeclaration fields
-    unsigned sizeok;		// set when structsize contains valid data
-				// 0: no size
-				// 1: size is correct
-				// 2: cannot determine size; fwd referenced
-    int isdeprecated;		// !=0 if deprecated
-    Scope *scope;		// !=NULL means context to use
-
-    // Special member functions
-    InvariantDeclaration *inv;		// invariant
-    NewDeclaration *aggNew;		// allocator
-    DeleteDeclaration *aggDelete;	// deallocator
-
-#if DMDV2
-    CtorDeclaration *ctor;
-    CtorDeclaration *defaultCtor;	// default constructor
-#endif
-
-    FuncDeclarations dtors;	// Array of destructors
-    FuncDeclaration *dtor;	// aggregate destructor
-
-#ifdef IN_GCC
-    Array methods;              // flat list of all methods for debug information
-#endif
-
-    AggregateDeclaration(Loc loc, Identifier *id);
-    void semantic2(Scope *sc);
-    void semantic3(Scope *sc);
-    void inlineScan();
-    unsigned size(Loc loc);
-    static void alignmember(unsigned salign, unsigned size, unsigned *poffset);
-    Type *getType();
-    void addField(Scope *sc, VarDeclaration *v);
-    int isDeprecated();		// is aggregate deprecated?
-    FuncDeclaration *buildDtor(Scope *sc);
-
-    void emitComment(Scope *sc);
-    void toDocBuffer(OutBuffer *buf);
-
-    // For access checking
-    virtual PROT getAccess(Dsymbol *smember);	// determine access to smember
-    int isFriendOf(AggregateDeclaration *cd);
-    int hasPrivateAccess(Dsymbol *smember);	// does smember have private access to members of this class?
-    void accessCheck(Loc loc, Scope *sc, Dsymbol *smember);
-
-    enum PROT prot();
-
-    // Back end
-    Symbol *stag;		// tag symbol for debug data
-    Symbol *sinit;
-    Symbol *toInitializer();
-
-    AggregateDeclaration *isAggregateDeclaration() { return this; }
-};
-
-struct AnonymousAggregateDeclaration : AggregateDeclaration
-{
-    AnonymousAggregateDeclaration()
-	: AggregateDeclaration(0, NULL)
-    {
-    }
-
-    AnonymousAggregateDeclaration *isAnonymousAggregateDeclaration() { return this; }
-};
-
-struct StructDeclaration : AggregateDeclaration
-{
-    int zeroInit;		// !=0 if initialize with 0 fill
-#if DMDV2
-    int hasIdentityAssign;	// !=0 if has identity opAssign
-    FuncDeclaration *cpctor;	// generated copy-constructor, if any
-
-    FuncDeclarations postblits;	// Array of postblit functions
-    FuncDeclaration *postblit;	// aggregate postblit
-#endif
-
-    StructDeclaration(Loc loc, Identifier *id);
-    Dsymbol *syntaxCopy(Dsymbol *s);
-    void semantic(Scope *sc);
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-    char *mangle();
-    const char *kind();
-    int needOpAssign();
-    FuncDeclaration *buildOpAssign(Scope *sc);
-    FuncDeclaration *buildPostBlit(Scope *sc);
-    FuncDeclaration *buildCpCtor(Scope *sc);
-    void toDocBuffer(OutBuffer *buf);
-
-    PROT getAccess(Dsymbol *smember);	// determine access to smember
-
-    void toObjFile(int multiobj);			// compile to .obj file
-    void toDt(dt_t **pdt);
-    void toDebug();			// to symbolic debug info
-
-    StructDeclaration *isStructDeclaration() { return this; }
-};
-
-struct UnionDeclaration : StructDeclaration
-{
-    UnionDeclaration(Loc loc, Identifier *id);
-    Dsymbol *syntaxCopy(Dsymbol *s);
-    const char *kind();
-
-    UnionDeclaration *isUnionDeclaration() { return this; }
-};
-
-struct BaseClass
-{
-    Type *type;				// (before semantic processing)
-    enum PROT protection;		// protection for the base interface
-
-    ClassDeclaration *base;
-    int offset;				// 'this' pointer offset
-    Array vtbl;				// for interfaces: Array of FuncDeclaration's
-					// making up the vtbl[]
-
-    int baseInterfaces_dim;
-    BaseClass *baseInterfaces;		// if BaseClass is an interface, these
-					// are a copy of the InterfaceDeclaration::interfaces
-
-    BaseClass();
-    BaseClass(Type *type, enum PROT protection);
-
-    int fillVtbl(ClassDeclaration *cd, Array *vtbl, int newinstance);
-    void copyBaseInterfaces(BaseClasses *);
-};
-
-#if DMDV2
-#define CLASSINFO_SIZE 	(0x3C+16)	// value of ClassInfo.size
-#else
-#define CLASSINFO_SIZE 	(0x3C+12)	// value of ClassInfo.size
-#endif
-
-struct ClassDeclaration : AggregateDeclaration
-{
-    static ClassDeclaration *object;
-    static ClassDeclaration *classinfo;
-
-    ClassDeclaration *baseClass;	// NULL only if this is Object
-    FuncDeclaration *staticCtor;
-    FuncDeclaration *staticDtor;
-    Array vtbl;				// Array of FuncDeclaration's making up the vtbl[]
-    Array vtblFinal;			// More FuncDeclaration's that aren't in vtbl[]
-
-    BaseClasses baseclasses;		// Array of BaseClass's; first is super,
-					// rest are Interface's
-
-    int interfaces_dim;
-    BaseClass **interfaces;		// interfaces[interfaces_dim] for this class
-					// (does not include baseClass)
-
-    BaseClasses *vtblInterfaces;	// array of base interfaces that have
-					// their own vtbl[]
-
-    ClassInfoDeclaration *vclassinfo;	// the ClassInfo object for this ClassDeclaration
-    int com;				// !=0 if this is a COM class (meaning
-					// it derives from IUnknown)
-    int isauto;				// !=0 if this is an auto class
-    int isabstract;			// !=0 if abstract class
-
-    int isnested;			// !=0 if is nested
-    VarDeclaration *vthis;		// 'this' parameter if this class is nested
-
-    int inuse;				// to prevent recursive attempts
-
-    ClassDeclaration(Loc loc, Identifier *id, BaseClasses *baseclasses);
-    Dsymbol *syntaxCopy(Dsymbol *s);
-    void semantic(Scope *sc);
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-    int isBaseOf2(ClassDeclaration *cd);
-
-    #define OFFSET_RUNTIME 0x76543210
-    virtual int isBaseOf(ClassDeclaration *cd, int *poffset);
-
-    Dsymbol *search(Loc, Identifier *ident, int flags);
-#if DMDV2
-    int isFuncHidden(FuncDeclaration *fd);
-#endif
-    FuncDeclaration *findFunc(Identifier *ident, TypeFunction *tf);
-    void interfaceSemantic(Scope *sc);
-    int isNested();
-    int isCOMclass();
-    virtual int isCOMinterface();
-#if DMDV2
-    virtual int isCPPinterface();
-#endif
-    int isAbstract();
-    virtual int vtblOffset();
-    const char *kind();
-    char *mangle();
-    void toDocBuffer(OutBuffer *buf);
-
-    PROT getAccess(Dsymbol *smember);	// determine access to smember
-
-    void addLocalClass(ClassDeclarations *);
-
-    // Back end
-    void toObjFile(int multiobj);			// compile to .obj file
-    void toDebug();
-    unsigned baseVtblOffset(BaseClass *bc);
-    Symbol *toSymbol();
-    Symbol *toVtblSymbol();
-    void toDt(dt_t **pdt);
-    void toDt2(dt_t **pdt, ClassDeclaration *cd);
-
-    Symbol *vtblsym;
-
-    ClassDeclaration *isClassDeclaration() { return (ClassDeclaration *)this; }
-};
-
-struct InterfaceDeclaration : ClassDeclaration
-{
-#if DMDV2
-    int cpp;				// !=0 if this is a C++ interface
-#endif
-    InterfaceDeclaration(Loc loc, Identifier *id, BaseClasses *baseclasses);
-    Dsymbol *syntaxCopy(Dsymbol *s);
-    void semantic(Scope *sc);
-    int isBaseOf(ClassDeclaration *cd, int *poffset);
-    int isBaseOf(BaseClass *bc, int *poffset);
-    const char *kind();
-    int vtblOffset();
-#if DMDV2
-    int isCPPinterface();
-#endif
-    virtual int isCOMinterface();
-
-    void toObjFile(int multiobj);			// compile to .obj file
-    Symbol *toSymbol();
-
-    InterfaceDeclaration *isInterfaceDeclaration() { return this; }
-};
-
-#endif /* DMD_AGGREGATE_H */
+
+// Compiler implementation of the D programming language
+// Copyright (c) 1999-2008 by Digital Mars
+// All Rights Reserved
+// written by Walter Bright
+// http://www.digitalmars.com
+// License for redistribution is by either the Artistic License
+// in artistic.txt, or the GNU General Public License in gnu.txt.
+// See the included readme.txt for details.
+
+#ifndef DMD_AGGREGATE_H
+#define DMD_AGGREGATE_H
+
+#ifdef __DMC__
+#pragma once
+#endif /* __DMC__ */
+
+#include "root.h"
+#include "dsymbol.h"
+
+#if IN_LLVM
+#include <vector>
+#include <set>
+#include <map>
+#endif
+
+struct Identifier;
+struct Type;
+struct TypeFunction;
+struct Expression;
+struct FuncDeclaration;
+struct CtorDeclaration;
+struct DtorDeclaration;
+struct InvariantDeclaration;
+struct NewDeclaration;
+struct DeleteDeclaration;
+struct InterfaceDeclaration;
+struct ClassInfoDeclaration;
+struct VarDeclaration;
+struct dt_t;
+
+#if IN_LLVM
+namespace llvm
+{
+    class Type;
+    class Value;
+    class Constant;
+    class ConstantStruct;
+    class GlobalVariable;
+}
+#endif
+
+struct AggregateDeclaration : ScopeDsymbol
+{
+    Type *type;
+    unsigned storage_class;
+    enum PROT protection;
+    Type *handle;		// 'this' type
+    unsigned structsize;	// size of struct
+    unsigned alignsize;		// size of struct for alignment purposes
+    unsigned structalign;	// struct member alignment in effect
+    int hasUnions;		// set if aggregate has overlapping fields
+    Array fields;		// VarDeclaration fields
+    unsigned sizeok;		// set when structsize contains valid data
+				// 0: no size
+				// 1: size is correct
+				// 2: cannot determine size; fwd referenced
+    int isdeprecated;		// !=0 if deprecated
+    Scope *scope;		// !=NULL means context to use
+
+    int isnested;		// !=0 if is nested
+    VarDeclaration *vthis;	// 'this' parameter if this aggregate is nested
+
+    // Special member functions
+    InvariantDeclaration *inv;		// invariant
+    NewDeclaration *aggNew;		// allocator
+    DeleteDeclaration *aggDelete;	// deallocator
+
+#if DMDV2
+    //CtorDeclaration *ctor;
+    Dsymbol *ctor;			// CtorDeclaration or TemplateDeclaration
+    CtorDeclaration *defaultCtor;	// default constructor
+    Dsymbol *aliasthis;			// forward unresolved lookups to aliasthis
+#endif
+
+    FuncDeclarations dtors;	// Array of destructors
+    FuncDeclaration *dtor;	// aggregate destructor
+
+#ifdef IN_GCC
+    Array methods;              // flat list of all methods for debug information
+#endif
+
+    AggregateDeclaration(Loc loc, Identifier *id);
+    void semantic2(Scope *sc);
+    void semantic3(Scope *sc);
+    void inlineScan();
+    unsigned size(Loc loc);
+    static void alignmember(unsigned salign, unsigned size, unsigned *poffset);
+    Type *getType();
+    void addField(Scope *sc, VarDeclaration *v);
+    int isDeprecated();		// is aggregate deprecated?
+    FuncDeclaration *buildDtor(Scope *sc);
+    int isNested();
+
+    void emitComment(Scope *sc);
+    void toDocBuffer(OutBuffer *buf);
+
+    // For access checking
+    virtual PROT getAccess(Dsymbol *smember);	// determine access to smember
+    int isFriendOf(AggregateDeclaration *cd);
+    int hasPrivateAccess(Dsymbol *smember);	// does smember have private access to members of this class?
+    void accessCheck(Loc loc, Scope *sc, Dsymbol *smember);
+
+    enum PROT prot();
+
+#if IN_DMD
+    // Back end
+    Symbol *stag;		// tag symbol for debug data
+    Symbol *sinit;
+    Symbol *toInitializer();
+#endif
+
+    AggregateDeclaration *isAggregateDeclaration() { return this; }
+};
+
+struct AnonymousAggregateDeclaration : AggregateDeclaration
+{
+    AnonymousAggregateDeclaration()
+	: AggregateDeclaration(0, NULL)
+    {
+    }
+
+    AnonymousAggregateDeclaration *isAnonymousAggregateDeclaration() { return this; }
+};
+
+struct StructDeclaration : AggregateDeclaration
+{
+    int zeroInit;		// !=0 if initialize with 0 fill
+#if DMDV2
+    int hasIdentityAssign;	// !=0 if has identity opAssign
+    FuncDeclaration *cpctor;	// generated copy-constructor, if any
+
+    FuncDeclarations postblits;	// Array of postblit functions
+    FuncDeclaration *postblit;	// aggregate postblit
+#endif
+
+    StructDeclaration(Loc loc, Identifier *id);
+    Dsymbol *syntaxCopy(Dsymbol *s);
+    void semantic(Scope *sc);
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+    char *mangle();
+    const char *kind();
+    int needOpAssign();
+    FuncDeclaration *buildOpAssign(Scope *sc);
+    FuncDeclaration *buildPostBlit(Scope *sc);
+    FuncDeclaration *buildCpCtor(Scope *sc);
+    void toDocBuffer(OutBuffer *buf);
+
+    PROT getAccess(Dsymbol *smember);	// determine access to smember
+
+#if IN_DMD
+    void toObjFile(int multiobj);			// compile to .obj file
+    void toDt(dt_t **pdt);
+    void toDebug();			// to symbolic debug info
+#endif
+
+    StructDeclaration *isStructDeclaration() { return this; }
+
+#if IN_LLVM
+    void codegen(Ir*);
+#endif
+};
+
+struct UnionDeclaration : StructDeclaration
+{
+    UnionDeclaration(Loc loc, Identifier *id);
+    Dsymbol *syntaxCopy(Dsymbol *s);
+    const char *kind();
+
+    UnionDeclaration *isUnionDeclaration() { return this; }
+};
+
+// warning: two classes with the same base class share the same
+//   BaseClass instance.
+struct BaseClass
+{
+    Type *type;				// (before semantic processing)
+    enum PROT protection;		// protection for the base interface
+
+    ClassDeclaration *base;
+    int offset;				// 'this' pointer offset
+    Array vtbl;				// for interfaces: Array of FuncDeclaration's
+					// making up the vtbl[]
+
+    int baseInterfaces_dim;
+    BaseClass *baseInterfaces;		// if BaseClass is an interface, these
+					// are a copy of the InterfaceDeclaration::interfaces
+
+    BaseClass();
+    BaseClass(Type *type, enum PROT protection);
+
+    int fillVtbl(ClassDeclaration *cd, Array *vtbl, int newinstance);
+    void copyBaseInterfaces(BaseClasses *);
+};
+
+#if DMDV2
+#define CLASSINFO_SIZE 	(0x3C+16+4)	// value of ClassInfo.size
+#else
+#define CLASSINFO_SIZE 	(0x3C+12+4)	// value of ClassInfo.size
+#endif
+
+struct ClassDeclaration : AggregateDeclaration
+{
+    static ClassDeclaration *object;
+    static ClassDeclaration *classinfo;
+
+    ClassDeclaration *baseClass;	// NULL only if this is Object
+    FuncDeclaration *staticCtor;
+    FuncDeclaration *staticDtor;
+    Array vtbl;				// Array of FuncDeclaration's making up the vtbl[]
+    Array vtblFinal;			// More FuncDeclaration's that aren't in vtbl[]
+
+    BaseClasses baseclasses;		// Array of BaseClass's; first is super,
+					// rest are Interface's
+
+    int interfaces_dim;
+    BaseClass **interfaces;		// interfaces[interfaces_dim] for this class
+					// (does not include baseClass)
+
+    BaseClasses *vtblInterfaces;	// array of base interfaces that have
+					// their own vtbl[]
+
+    ClassInfoDeclaration *vclassinfo;	// the ClassInfo object for this ClassDeclaration
+    int com;				// !=0 if this is a COM class (meaning
+					// it derives from IUnknown)
+    int isauto;				// !=0 if this is an auto class
+    int isabstract;			// !=0 if abstract class
+
+    int inuse;				// to prevent recursive attempts
+
+    ClassDeclaration(Loc loc, Identifier *id, BaseClasses *baseclasses);
+    Dsymbol *syntaxCopy(Dsymbol *s);
+    void semantic(Scope *sc);
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+    int isBaseOf2(ClassDeclaration *cd);
+
+    #define OFFSET_RUNTIME 0x76543210
+    virtual int isBaseOf(ClassDeclaration *cd, int *poffset);
+
+    Dsymbol *search(Loc, Identifier *ident, int flags);
+#if DMDV2
+    int isFuncHidden(FuncDeclaration *fd);
+#endif
+    FuncDeclaration *findFunc(Identifier *ident, TypeFunction *tf);
+    void interfaceSemantic(Scope *sc);
+    int isCOMclass();
+    virtual int isCOMinterface();
+#if DMDV2
+    virtual int isCPPinterface();
+#endif
+    int isAbstract();
+    virtual int vtblOffset();
+    const char *kind();
+    char *mangle();
+    void toDocBuffer(OutBuffer *buf);
+
+    PROT getAccess(Dsymbol *smember);	// determine access to smember
+
+    void addLocalClass(ClassDeclarations *);
+
+#if IN_DMD
+    // Back end
+    void toObjFile(int multiobj);			// compile to .obj file
+    void toDebug();
+    unsigned baseVtblOffset(BaseClass *bc);
+    Symbol *toSymbol();
+    Symbol *toVtblSymbol();
+    void toDt(dt_t **pdt);
+    void toDt2(dt_t **pdt, ClassDeclaration *cd);
+
+    Symbol *vtblsym;
+#endif
+
+    ClassDeclaration *isClassDeclaration() { return (ClassDeclaration *)this; }
+
+#if IN_LLVM
+    virtual void codegen(Ir*);
+#endif
+};
+
+struct InterfaceDeclaration : ClassDeclaration
+{
+#if DMDV2
+    int cpp;				// !=0 if this is a C++ interface
+#endif
+    InterfaceDeclaration(Loc loc, Identifier *id, BaseClasses *baseclasses);
+    Dsymbol *syntaxCopy(Dsymbol *s);
+    void semantic(Scope *sc);
+    int isBaseOf(ClassDeclaration *cd, int *poffset);
+    int isBaseOf(BaseClass *bc, int *poffset);
+    const char *kind();
+    int vtblOffset();
+#if DMDV2
+    int isCPPinterface();
+#endif
+    virtual int isCOMinterface();
+
+#if IN_DMD
+    void toObjFile(int multiobj);			// compile to .obj file
+    Symbol *toSymbol();
+#endif
+
+    InterfaceDeclaration *isInterfaceDeclaration() { return this; }
+
+#if IN_LLVM
+    void codegen(Ir*);
+#endif
+};
+
+#endif /* DMD_AGGREGATE_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd2/aliasthis.c	Mon Jun 01 19:02:20 2009 +0100
@@ -0,0 +1,72 @@
+
+// Compiler implementation of the D programming language
+// Copyright (c) 2009-2009 by Digital Mars
+// All Rights Reserved
+// written by Walter Bright
+// http://www.digitalmars.com
+// License for redistribution is by either the Artistic License
+// in artistic.txt, or the GNU General Public License in gnu.txt.
+// See the included readme.txt for details.
+
+#include <stdio.h>
+#include <assert.h>
+
+#include "mars.h"
+#include "identifier.h"
+#include "aliasthis.h"
+#include "scope.h"
+#include "aggregate.h"
+#include "dsymbol.h"
+
+#if DMDV2
+
+
+AliasThis::AliasThis(Loc loc, Identifier *ident)
+    : Dsymbol(NULL)		// it's anonymous (no identifier)
+{
+    this->loc = loc;
+    this->ident = ident;
+}
+
+Dsymbol *AliasThis::syntaxCopy(Dsymbol *s)
+{
+    assert(!s);
+    /* Since there is no semantic information stored here,
+     * we don't need to copy it.
+     */
+    return this;
+}
+
+void AliasThis::semantic(Scope *sc)
+{
+    Dsymbol *parent = sc->parent;
+    if (parent)
+	parent = parent->pastMixin();
+    AggregateDeclaration *ad = NULL;
+    if (parent)
+	ad = parent->isAggregateDeclaration();
+    if (ad)
+    {
+	if (ad->aliasthis)
+	    error("there can be only one alias this");
+	assert(ad->members);
+	Dsymbol *s = ad->search(loc, ident, 0);
+	ad->aliasthis = s;
+    }
+    else
+	error("alias this can only appear in struct or class declaration, not %s", parent ? parent->toChars() : "nowhere");
+}
+
+const char *AliasThis::kind()
+{
+    return "alias this";
+}
+
+void AliasThis::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    buf->writestring("alias ");
+    buf->writestring(ident->toChars());
+    buf->writestring(" this;\n");
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd2/aliasthis.h	Mon Jun 01 19:02:20 2009 +0100
@@ -0,0 +1,41 @@
+
+// Compiler implementation of the D programming language
+// Copyright (c) 2009-2009 by Digital Mars
+// All Rights Reserved
+// written by Walter Bright
+// http://www.digitalmars.com
+// License for redistribution is by either the Artistic License
+// in artistic.txt, or the GNU General Public License in gnu.txt.
+// See the included readme.txt for details.
+
+#ifndef DMD_ALIASTHIS_H
+#define DMD_ALIASTHIS_H
+
+#ifdef __DMC__
+#pragma once
+#endif /* __DMC__ */
+
+#include "mars.h"
+#include "dsymbol.h"
+
+/**************************************************************/
+
+#if DMDV2
+
+struct AliasThis : Dsymbol
+{
+   // alias Identifier this;
+    Identifier *ident;
+
+    AliasThis(Loc loc, Identifier *ident);
+
+    Dsymbol *syntaxCopy(Dsymbol *);
+    void semantic(Scope *sc);
+    const char *kind();
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+    AliasThis *isAliasThis() { return this; }
+};
+
+#endif
+
+#endif
--- a/dmd2/array.c	Mon Jun 01 01:28:18 2009 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,220 +0,0 @@
-
-// Copyright (c) 1999-2006 by Digital Mars
-// All Rights Reserved
-// written by Walter Bright
-// 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 <stdlib.h>
-#include <stdarg.h>
-#include <string.h>
-#include <assert.h>
-
-#if _MSC_VER || __MINGW32__
-#include <malloc.h>
-#endif
-
-#if IN_GCC
-#include "gdc_alloca.h"
-#endif
-
-#if _WIN32
-#include <windows.h>
-#endif
-
-#ifndef _WIN32
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <unistd.h>
-#include <utime.h>
-#endif
-
-#include "port.h"
-#include "root.h"
-#include "dchar.h"
-#include "mem.h"
-
-
-/********************************* Array ****************************/
-
-Array::Array()
-{
-    data = NULL;
-    dim = 0;
-    allocdim = 0;
-}
-
-Array::~Array()
-{
-    mem.free(data);
-}
-
-void Array::mark()
-{   unsigned u;
-
-    mem.mark(data);
-    for (u = 0; u < dim; u++)
-	mem.mark(data[u]);	// BUG: what if arrays of Object's?
-}
-
-void Array::reserve(unsigned nentries)
-{
-    //printf("Array::reserve: size = %d, offset = %d, nbytes = %d\n", size, offset, nbytes);
-    if (allocdim - dim < nentries)
-    {
-	allocdim = dim + nentries;
-	data = (void **)mem.realloc(data, allocdim * sizeof(*data));
-    }
-}
-
-void Array::setDim(unsigned newdim)
-{
-    if (dim < newdim)
-    {
-	reserve(newdim - dim);
-    }
-    dim = newdim;
-}
-
-void Array::fixDim()
-{
-    if (dim != allocdim)
-    {	data = (void **)mem.realloc(data, dim * sizeof(*data));
-	allocdim = dim;
-    }
-}
-
-void Array::push(void *ptr)
-{
-    reserve(1);
-    data[dim++] = ptr;
-}
-
-void *Array::pop()
-{
-    return data[--dim];
-}
-
-void Array::shift(void *ptr)
-{
-    reserve(1);
-    memmove(data + 1, data, dim * sizeof(*data));
-    data[0] = ptr;
-    dim++;
-}
-
-void Array::insert(unsigned index, void *ptr)
-{
-    reserve(1);
-    memmove(data + index + 1, data + index, (dim - index) * sizeof(*data));
-    data[index] = ptr;
-    dim++;
-}
-
-
-void Array::insert(unsigned index, Array *a)
-{
-    if (a)
-    {	unsigned d;
-
-	d = a->dim;
-	reserve(d);
-	if (dim != index)
-	    memmove(data + index + d, data + index, (dim - index) * sizeof(*data));
-	memcpy(data + index, a->data, d * sizeof(*data));
-	dim += d;
-    }
-}
-
-
-/***********************************
- * Append array a to this array.
- */
-
-void Array::append(Array *a)
-{
-    insert(dim, a);
-}
-
-void Array::remove(unsigned i)
-{
-    memmove(data + i, data + i + 1, (dim - i) * sizeof(data[0]));
-    dim--;
-}
-
-char *Array::toChars()
-{
-    unsigned len;
-    unsigned u;
-    char **buf;
-    char *str;
-    char *p;
-
-    buf = (char **)alloca(dim * sizeof(char *));
-    len = 2;
-    for (u = 0; u < dim; u++)
-    {
-	buf[u] = ((Object *)data[u])->toChars();
-	len += strlen(buf[u]) + 1;
-    }
-    str = (char *)mem.malloc(len);
-
-    str[0] = '[';
-    p = str + 1;
-    for (u = 0; u < dim; u++)
-    {
-	if (u)
-	    *p++ = ',';
-	len = strlen(buf[u]);
-	memcpy(p,buf[u],len);
-	p += len;
-    }
-    *p++ = ']';
-    *p = 0;
-    return str;
-}
-
-void Array::zero()
-{
-    memset(data,0,dim * sizeof(data[0]));
-}
-
-void *Array::tos()
-{
-    return dim ? data[dim - 1] : NULL;
-}
-
-int
-#if _WIN32
-  __cdecl
-#endif
-	Array_sort_compare(const void *x, const void *y)
-{
-    Object *ox = *(Object **)x;
-    Object *oy = *(Object **)y;
-
-    return ox->compare(oy);
-}
-
-void Array::sort()
-{
-    if (dim)
-    {
-	qsort(data, dim, sizeof(Object *), Array_sort_compare);
-    }
-}
-
-Array *Array::copy()
-{
-    Array *a = new Array();
-
-    a->setDim(dim);
-    memcpy(a->data, data, dim * sizeof(void *));
-    return a;
-}
-
--- a/dmd2/arrayop.c	Mon Jun 01 01:28:18 2009 +0200
+++ b/dmd2/arrayop.c	Mon Jun 01 19:02:20 2009 +0100
@@ -1,494 +1,505 @@
-
-// 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 <string.h>
-#include <assert.h>
-
-#if _WIN32 || IN_GCC  || IN_LLVM
-#include "mem.h"
-#else
-#include "../root/mem.h"
-#endif
-
-#include "stringtable.h"
-
-#include "expression.h"
-#include "statement.h"
-#include "mtype.h"
-#include "declaration.h"
-#include "scope.h"
-#include "id.h"
-#include "module.h"
-#include "init.h"
-
-
-/***********************************
- * Construct the array operation expression.
- */
-
-Expression *BinExp::arrayOp(Scope *sc)
-{
-    Expressions *arguments = new Expressions();
-
-    /* The expression to generate an array operation for is mangled
-     * into a name to use as the array operation function name.
-     * Mangle in the operands and operators in RPN order, and type.
-     */
-    OutBuffer buf;
-    buf.writestring("_array");
-    buildArrayIdent(&buf, arguments);
-    buf.writeByte('_');
-
-    /* Append deco of array element type
-     */
-#if DMDV2
-    buf.writestring(type->toBasetype()->nextOf()->toBasetype()->mutableOf()->deco);
-#else
-    buf.writestring(type->toBasetype()->nextOf()->toBasetype()->deco);
-#endif
-
-    size_t namelen = buf.offset;
-    buf.writeByte(0);
-    char *name = (char *)buf.extractData();
-
-    /* Look up name in hash table
-     */
-    StringValue *sv = sc->module->arrayfuncs.update(name, namelen);
-    FuncDeclaration *fd = (FuncDeclaration *)sv->ptrvalue;
-    if (!fd)
-    {
-//     /* Some of the array op functions are written as library functions,
-//      * presumably to optimize them with special CPU vector instructions.
-//      * List those library functions here, in alpha order.
-//      */
-//     static const char *libArrayopFuncs[] =
-//     {
-//         "_arrayExpSliceAddass_a",
-//         "_arrayExpSliceAddass_d",       // T[]+=T
-//         "_arrayExpSliceAddass_f",       // T[]+=T
-//         "_arrayExpSliceAddass_g",
-//         "_arrayExpSliceAddass_h",
-//         "_arrayExpSliceAddass_i",
-//         "_arrayExpSliceAddass_k",
-//         "_arrayExpSliceAddass_s",
-//         "_arrayExpSliceAddass_t",
-//         "_arrayExpSliceAddass_u",
-//         "_arrayExpSliceAddass_w",
-// 
-//         "_arrayExpSliceDivass_d",       // T[]/=T
-//         "_arrayExpSliceDivass_f",       // T[]/=T
-// 
-//         "_arrayExpSliceMinSliceAssign_a",
-//         "_arrayExpSliceMinSliceAssign_d",   // T[]=T-T[]
-//         "_arrayExpSliceMinSliceAssign_f",   // T[]=T-T[]
-//         "_arrayExpSliceMinSliceAssign_g",
-//         "_arrayExpSliceMinSliceAssign_h",
-//         "_arrayExpSliceMinSliceAssign_i",
-//         "_arrayExpSliceMinSliceAssign_k",
-//         "_arrayExpSliceMinSliceAssign_s",
-//         "_arrayExpSliceMinSliceAssign_t",
-//         "_arrayExpSliceMinSliceAssign_u",
-//         "_arrayExpSliceMinSliceAssign_w",
-// 
-//         "_arrayExpSliceMinass_a",
-//         "_arrayExpSliceMinass_d",       // T[]-=T
-//         "_arrayExpSliceMinass_f",       // T[]-=T
-//         "_arrayExpSliceMinass_g",
-//         "_arrayExpSliceMinass_h",
-//         "_arrayExpSliceMinass_i",
-//         "_arrayExpSliceMinass_k",
-//         "_arrayExpSliceMinass_s",
-//         "_arrayExpSliceMinass_t",
-//         "_arrayExpSliceMinass_u",
-//         "_arrayExpSliceMinass_w",
-// 
-//         "_arrayExpSliceMulass_d",       // T[]*=T
-//         "_arrayExpSliceMulass_f",       // T[]*=T
-//         "_arrayExpSliceMulass_i",
-//         "_arrayExpSliceMulass_k",
-//         "_arrayExpSliceMulass_s",
-//         "_arrayExpSliceMulass_t",
-//         "_arrayExpSliceMulass_u",
-//         "_arrayExpSliceMulass_w",
-// 
-//         "_arraySliceExpAddSliceAssign_a",
-//         "_arraySliceExpAddSliceAssign_d",   // T[]=T[]+T
-//         "_arraySliceExpAddSliceAssign_f",   // T[]=T[]+T
-//         "_arraySliceExpAddSliceAssign_g",
-//         "_arraySliceExpAddSliceAssign_h",
-//         "_arraySliceExpAddSliceAssign_i",
-//         "_arraySliceExpAddSliceAssign_k",
-//         "_arraySliceExpAddSliceAssign_s",
-//         "_arraySliceExpAddSliceAssign_t",
-//         "_arraySliceExpAddSliceAssign_u",
-//         "_arraySliceExpAddSliceAssign_w",
-// 
-//         "_arraySliceExpDivSliceAssign_d",   // T[]=T[]/T
-//         "_arraySliceExpDivSliceAssign_f",   // T[]=T[]/T
-// 
-//         "_arraySliceExpMinSliceAssign_a",
-//         "_arraySliceExpMinSliceAssign_d",   // T[]=T[]-T
-//         "_arraySliceExpMinSliceAssign_f",   // T[]=T[]-T
-//         "_arraySliceExpMinSliceAssign_g",
-//         "_arraySliceExpMinSliceAssign_h",
-//         "_arraySliceExpMinSliceAssign_i",
-//         "_arraySliceExpMinSliceAssign_k",
-//         "_arraySliceExpMinSliceAssign_s",
-//         "_arraySliceExpMinSliceAssign_t",
-//         "_arraySliceExpMinSliceAssign_u",
-//         "_arraySliceExpMinSliceAssign_w",
-// 
-//         "_arraySliceExpMulSliceAddass_d",   // T[] += T[]*T
-//         "_arraySliceExpMulSliceAddass_f",
-//         "_arraySliceExpMulSliceAddass_r",
-// 
-//         "_arraySliceExpMulSliceAssign_d",   // T[]=T[]*T
-//         "_arraySliceExpMulSliceAssign_f",   // T[]=T[]*T
-//         "_arraySliceExpMulSliceAssign_i",
-//         "_arraySliceExpMulSliceAssign_k",
-//         "_arraySliceExpMulSliceAssign_s",
-//         "_arraySliceExpMulSliceAssign_t",
-//         "_arraySliceExpMulSliceAssign_u",
-//         "_arraySliceExpMulSliceAssign_w",
-// 
-//         "_arraySliceExpMulSliceMinass_d",   // T[] -= T[]*T
-//         "_arraySliceExpMulSliceMinass_f",
-//         "_arraySliceExpMulSliceMinass_r",
-// 
-//         "_arraySliceSliceAddSliceAssign_a",
-//         "_arraySliceSliceAddSliceAssign_d", // T[]=T[]+T[]
-//         "_arraySliceSliceAddSliceAssign_f", // T[]=T[]+T[]
-//         "_arraySliceSliceAddSliceAssign_g",
-//         "_arraySliceSliceAddSliceAssign_h",
-//         "_arraySliceSliceAddSliceAssign_i",
-//         "_arraySliceSliceAddSliceAssign_k",
-//         "_arraySliceSliceAddSliceAssign_r", // T[]=T[]+T[]
-//         "_arraySliceSliceAddSliceAssign_s",
-//         "_arraySliceSliceAddSliceAssign_t",
-//         "_arraySliceSliceAddSliceAssign_u",
-//         "_arraySliceSliceAddSliceAssign_w",
-// 
-//         "_arraySliceSliceAddass_a",
-//         "_arraySliceSliceAddass_d",     // T[]+=T[]
-//         "_arraySliceSliceAddass_f",     // T[]+=T[]
-//         "_arraySliceSliceAddass_g",
-//         "_arraySliceSliceAddass_h",
-//         "_arraySliceSliceAddass_i",
-//         "_arraySliceSliceAddass_k",
-//         "_arraySliceSliceAddass_s",
-//         "_arraySliceSliceAddass_t",
-//         "_arraySliceSliceAddass_u",
-//         "_arraySliceSliceAddass_w",
-// 
-//         "_arraySliceSliceMinSliceAssign_a",
-//         "_arraySliceSliceMinSliceAssign_d", // T[]=T[]-T[]
-//         "_arraySliceSliceMinSliceAssign_f", // T[]=T[]-T[]
-//         "_arraySliceSliceMinSliceAssign_g",
-//         "_arraySliceSliceMinSliceAssign_h",
-//         "_arraySliceSliceMinSliceAssign_i",
-//         "_arraySliceSliceMinSliceAssign_k",
-//         "_arraySliceSliceMinSliceAssign_r", // T[]=T[]-T[]
-//         "_arraySliceSliceMinSliceAssign_s",
-//         "_arraySliceSliceMinSliceAssign_t",
-//         "_arraySliceSliceMinSliceAssign_u",
-//         "_arraySliceSliceMinSliceAssign_w",
-// 
-//         "_arraySliceSliceMinass_a",
-//         "_arraySliceSliceMinass_d",     // T[]-=T[]
-//         "_arraySliceSliceMinass_f",     // T[]-=T[]
-//         "_arraySliceSliceMinass_g",
-//         "_arraySliceSliceMinass_h",
-//         "_arraySliceSliceMinass_i",
-//         "_arraySliceSliceMinass_k",
-//         "_arraySliceSliceMinass_s",
-//         "_arraySliceSliceMinass_t",
-//         "_arraySliceSliceMinass_u",
-//         "_arraySliceSliceMinass_w",
-// 
-//         "_arraySliceSliceMulSliceAssign_d", // T[]=T[]*T[]
-//         "_arraySliceSliceMulSliceAssign_f", // T[]=T[]*T[]
-//         "_arraySliceSliceMulSliceAssign_i",
-//         "_arraySliceSliceMulSliceAssign_k",
-//         "_arraySliceSliceMulSliceAssign_s",
-//         "_arraySliceSliceMulSliceAssign_t",
-//         "_arraySliceSliceMulSliceAssign_u",
-//         "_arraySliceSliceMulSliceAssign_w",
-// 
-//         "_arraySliceSliceMulass_d",     // T[]*=T[]
-//         "_arraySliceSliceMulass_f",     // T[]*=T[]
-//         "_arraySliceSliceMulass_i",
-//         "_arraySliceSliceMulass_k",
-//         "_arraySliceSliceMulass_s",
-//         "_arraySliceSliceMulass_t",
-//         "_arraySliceSliceMulass_u",
-//         "_arraySliceSliceMulass_w",
-//     };
-// 
-//     int i = binary(name, libArrayopFuncs, sizeof(libArrayopFuncs) / sizeof(char *));
-//     if (i == -1)
-//     {
-// #ifdef DEBUG    // Make sure our array is alphabetized
-//         for (i = 0; i < sizeof(libArrayopFuncs) / sizeof(char *); i++)
-//         {
-//         if (strcmp(name, libArrayopFuncs[i]) == 0)
-//             assert(0);
-//         }
-// #endif
-
-        /* Not in library, so generate it.
-         * Construct the function body:
-         *  foreach (i; 0 .. p.length)    for (size_t i = 0; i < p.length; i++)
-         *      loopbody;
-         *  return p;
-         */
-
-        Arguments *fparams = new Arguments();
-        Expression *loopbody = buildArrayLoop(fparams);
-        Argument *p = (Argument *)fparams->data[0 /*fparams->dim - 1*/];
-#if DMDV1
-        // for (size_t i = 0; i < p.length; i++)
-        Initializer *init = new ExpInitializer(0, new IntegerExp(0, 0, Type::tsize_t));
-        Dsymbol *d = new VarDeclaration(0, Type::tsize_t, Id::p, init);
-        Statement *s1 = new ForStatement(0,
-        new DeclarationStatement(0, d),
-        new CmpExp(TOKlt, 0, new IdentifierExp(0, Id::p), new ArrayLengthExp(0, new IdentifierExp(0, p->ident))),
-        new PostExp(TOKplusplus, 0, new IdentifierExp(0, Id::p)),
-        new ExpStatement(0, loopbody));
-#else
-        // foreach (i; 0 .. p.length)
-        Statement *s1 = new ForeachRangeStatement(0, TOKforeach,
-        new Argument(0, NULL, Id::p, NULL),
-        new IntegerExp(0, 0, Type::tint32),
-        new ArrayLengthExp(0, new IdentifierExp(0, p->ident)),
-        new ExpStatement(0, loopbody));
-#endif
-        Statement *s2 = new ReturnStatement(0, new IdentifierExp(0, p->ident));
-        //printf("s2: %s\n", s2->toChars());
-        Statement *fbody = new CompoundStatement(0, s1, s2);
-
-        /* Construct the function
-         */
-        TypeFunction *ftype = new TypeFunction(fparams, type, 0, LINKc);
-        //printf("ftype: %s\n", ftype->toChars());
-        fd = new FuncDeclaration(0, 0, Lexer::idPool(name), STCundefined, ftype);
-        fd->fbody = fbody;
-        fd->protection = PROTprotected;
-        fd->linkage = LINKd;
-
-        // special attention for array ops
-        fd->isArrayOp = true;
-
-        sc->module->members->push(fd);
-
-        sc = sc->push();
-        sc->parent = sc->module;
-        sc->stc = 0;
-        sc->linkage = LINKd;
-        fd->semantic(sc);
-        sc->pop();
-//     }
-//     else
-//     {   /* In library, refer to it.
-//          */
-//         // FIXME
-//         fd = FuncDeclaration::genCfunc(NULL, type, name);
-//     }
-    sv->ptrvalue = fd;  // cache symbol in hash table
-    }
-
-    /* Call the function fd(arguments)
-     */
-    Expression *ec = new VarExp(0, fd);
-    Expression *e = new CallExp(loc, ec, arguments);
-    e->type = type;
-    return e;
-}
-
-/******************************************
- * Construct the identifier for the array operation function,
- * and build the argument list to pass to it.
- */
-
-void Expression::buildArrayIdent(OutBuffer *buf, Expressions *arguments)
-{
-    buf->writestring("Exp");
-    arguments->shift(this);
-}
-
-void SliceExp::buildArrayIdent(OutBuffer *buf, Expressions *arguments)
-{
-    buf->writestring("Slice");
-    arguments->shift(this);
-}
-
-void AssignExp::buildArrayIdent(OutBuffer *buf, Expressions *arguments)
-{
-    /* Evaluate assign expressions right to left
-     */
-    e2->buildArrayIdent(buf, arguments);
-    e1->buildArrayIdent(buf, arguments);
-    buf->writestring("Assign");
-}
-
-#define X(Str) \
-void Str##AssignExp::buildArrayIdent(OutBuffer *buf, Expressions *arguments) \
-{							\
-    /* Evaluate assign expressions right to left	\
-     */							\
-    e2->buildArrayIdent(buf, arguments);		\
-    e1->buildArrayIdent(buf, arguments);		\
-    buf->writestring(#Str);				\
-    buf->writestring("ass");				\
-}
-
-X(Add)
-X(Min)
-X(Mul)
-X(Div)
-X(Mod)
-X(Xor)
-X(And)
-X(Or)
-
-#undef X
-
-void NegExp::buildArrayIdent(OutBuffer *buf, Expressions *arguments)
-{
-    e1->buildArrayIdent(buf, arguments);
-    buf->writestring("Neg");
-}
-
-void ComExp::buildArrayIdent(OutBuffer *buf, Expressions *arguments)
-{
-    e1->buildArrayIdent(buf, arguments);
-    buf->writestring("Com");
-}
-
-#define X(Str) \
-void Str##Exp::buildArrayIdent(OutBuffer *buf, Expressions *arguments)	\
-{									\
-    /* Evaluate assign expressions left to right			\
-     */									\
-    e1->buildArrayIdent(buf, arguments);				\
-    e2->buildArrayIdent(buf, arguments);				\
-    buf->writestring(#Str);						\
-}
-
-X(Add)
-X(Min)
-X(Mul)
-X(Div)
-X(Mod)
-X(Xor)
-X(And)
-X(Or)
-
-#undef X
-
-/******************************************
- * Construct the inner loop for the array operation function,
- * and build the parameter list.
- */
-
-Expression *Expression::buildArrayLoop(Arguments *fparams)
-{
-    Identifier *id = Identifier::generateId("c", fparams->dim);
-    Argument *param = new Argument(0, type, id, NULL);
-    fparams->shift(param);
-    Expression *e = new IdentifierExp(0, id);
-    return e;
-}
-
-Expression *SliceExp::buildArrayLoop(Arguments *fparams)
-{
-    Identifier *id = Identifier::generateId("p", fparams->dim);
-    Argument *param = new Argument(STCconst, type, id, NULL);
-    fparams->shift(param);
-    Expression *e = new IdentifierExp(0, id);
-    Expressions *arguments = new Expressions();
-    Expression *index = new IdentifierExp(0, Id::p);
-    arguments->push(index);
-    e = new ArrayExp(0, e, arguments);
-    return e;
-}
-
-Expression *AssignExp::buildArrayLoop(Arguments *fparams)
-{
-    /* Evaluate assign expressions right to left
-     */
-    Expression *ex2 = e2->buildArrayLoop(fparams);
-    Expression *ex1 = e1->buildArrayLoop(fparams);
-    Argument *param = (Argument *)fparams->data[0];
-    param->storageClass = 0;
-    Expression *e = new AssignExp(0, ex1, ex2);
-    return e;
-}
-
-#define X(Str) \
-Expression *Str##AssignExp::buildArrayLoop(Arguments *fparams)	\
-{								\
-    /* Evaluate assign expressions right to left		\
-     */								\
-    Expression *ex2 = e2->buildArrayLoop(fparams);		\
-    Expression *ex1 = e1->buildArrayLoop(fparams);		\
-    Argument *param = (Argument *)fparams->data[0];		\
-    param->storageClass = 0;					\
-    Expression *e = new Str##AssignExp(0, ex1, ex2);		\
-    return e;							\
-}
-
-X(Add)
-X(Min)
-X(Mul)
-X(Div)
-X(Mod)
-X(Xor)
-X(And)
-X(Or)
-
-#undef X
-
-Expression *NegExp::buildArrayLoop(Arguments *fparams)
-{
-    Expression *ex1 = e1->buildArrayLoop(fparams);
-    Expression *e = new NegExp(0, ex1);
-    return e;
-}
-
-Expression *ComExp::buildArrayLoop(Arguments *fparams)
-{
-    Expression *ex1 = e1->buildArrayLoop(fparams);
-    Expression *e = new ComExp(0, ex1);
-    return e;
-}
-
-#define X(Str) \
-Expression *Str##Exp::buildArrayLoop(Arguments *fparams)	\
-{								\
-    /* Evaluate assign expressions left to right		\
-     */								\
-    Expression *ex1 = e1->buildArrayLoop(fparams);		\
-    Expression *ex2 = e2->buildArrayLoop(fparams);		\
-    Expression *e = new Str##Exp(0, ex1, ex2);			\
-    return e;							\
-}
-
-X(Add)
-X(Min)
-X(Mul)
-X(Div)
-X(Mod)
-X(Xor)
-X(And)
-X(Or)
-
-#undef X
-
-
+
+// 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 <string.h>
+#include <assert.h>
+
+#include "rmem.h"
+
+#include "stringtable.h"
+
+#include "expression.h"
+#include "statement.h"
+#include "mtype.h"
+#include "declaration.h"
+#include "scope.h"
+#include "id.h"
+#include "module.h"
+#include "init.h"
+
+#if IN_DMD
+extern int binary(const char *p , const char **tab, int high);
+
+/**************************************
+ * Hash table of array op functions already generated or known about.
+ */
+
+StringTable arrayfuncs;
+#endif
+
+/***********************************
+ * Construct the array operation expression.
+ */
+
+Expression *BinExp::arrayOp(Scope *sc)
+{
+    Expressions *arguments = new Expressions();
+
+    /* The expression to generate an array operation for is mangled
+     * into a name to use as the array operation function name.
+     * Mangle in the operands and operators in RPN order, and type.
+     */
+    OutBuffer buf;
+    buf.writestring("_array");
+    buildArrayIdent(&buf, arguments);
+    buf.writeByte('_');
+
+    /* Append deco of array element type
+     */
+#if DMDV2
+    buf.writestring(type->toBasetype()->nextOf()->toBasetype()->mutableOf()->deco);
+#else
+    buf.writestring(type->toBasetype()->nextOf()->toBasetype()->deco);
+#endif
+
+    size_t namelen = buf.offset;
+    buf.writeByte(0);
+    char *name = (char *)buf.extractData();
+
+    /* Look up name in hash table
+     */
+#if IN_LLVM
+    StringValue *sv = sc->module->arrayfuncs.update(name, namelen);
+#else
+    StringValue *sv = arrayfuncs.update(name, namelen);
+#endif
+    FuncDeclaration *fd = (FuncDeclaration *)sv->ptrvalue;
+    if (!fd)
+    {
+#if IN_DMD
+	/* Some of the array op functions are written as library functions,
+	 * presumably to optimize them with special CPU vector instructions.
+	 * List those library functions here, in alpha order.
+	 */
+	static const char *libArrayopFuncs[] =
+	{
+	    "_arrayExpSliceAddass_a",
+	    "_arrayExpSliceAddass_d",		// T[]+=T
+	    "_arrayExpSliceAddass_f",		// T[]+=T
+	    "_arrayExpSliceAddass_g",
+	    "_arrayExpSliceAddass_h",
+	    "_arrayExpSliceAddass_i",
+	    "_arrayExpSliceAddass_k",
+	    "_arrayExpSliceAddass_s",
+	    "_arrayExpSliceAddass_t",
+	    "_arrayExpSliceAddass_u",
+	    "_arrayExpSliceAddass_w",
+
+	    "_arrayExpSliceDivass_d",		// T[]/=T
+	    "_arrayExpSliceDivass_f",		// T[]/=T
+
+	    "_arrayExpSliceMinSliceAssign_a",
+	    "_arrayExpSliceMinSliceAssign_d",	// T[]=T-T[]
+	    "_arrayExpSliceMinSliceAssign_f",	// T[]=T-T[]
+	    "_arrayExpSliceMinSliceAssign_g",
+	    "_arrayExpSliceMinSliceAssign_h",
+	    "_arrayExpSliceMinSliceAssign_i",
+	    "_arrayExpSliceMinSliceAssign_k",
+	    "_arrayExpSliceMinSliceAssign_s",
+	    "_arrayExpSliceMinSliceAssign_t",
+	    "_arrayExpSliceMinSliceAssign_u",
+	    "_arrayExpSliceMinSliceAssign_w",
+
+	    "_arrayExpSliceMinass_a",
+	    "_arrayExpSliceMinass_d",		// T[]-=T
+	    "_arrayExpSliceMinass_f",		// T[]-=T
+	    "_arrayExpSliceMinass_g",
+	    "_arrayExpSliceMinass_h",
+	    "_arrayExpSliceMinass_i",
+	    "_arrayExpSliceMinass_k",
+	    "_arrayExpSliceMinass_s",
+	    "_arrayExpSliceMinass_t",
+	    "_arrayExpSliceMinass_u",
+	    "_arrayExpSliceMinass_w",
+
+	    "_arrayExpSliceMulass_d",		// T[]*=T
+	    "_arrayExpSliceMulass_f",		// T[]*=T
+	    "_arrayExpSliceMulass_i",
+	    "_arrayExpSliceMulass_k",
+	    "_arrayExpSliceMulass_s",
+	    "_arrayExpSliceMulass_t",
+	    "_arrayExpSliceMulass_u",
+	    "_arrayExpSliceMulass_w",
+
+	    "_arraySliceExpAddSliceAssign_a",
+	    "_arraySliceExpAddSliceAssign_d",	// T[]=T[]+T
+	    "_arraySliceExpAddSliceAssign_f",	// T[]=T[]+T
+	    "_arraySliceExpAddSliceAssign_g",
+	    "_arraySliceExpAddSliceAssign_h",
+	    "_arraySliceExpAddSliceAssign_i",
+	    "_arraySliceExpAddSliceAssign_k",
+	    "_arraySliceExpAddSliceAssign_s",
+	    "_arraySliceExpAddSliceAssign_t",
+	    "_arraySliceExpAddSliceAssign_u",
+	    "_arraySliceExpAddSliceAssign_w",
+
+	    "_arraySliceExpDivSliceAssign_d",	// T[]=T[]/T
+	    "_arraySliceExpDivSliceAssign_f",	// T[]=T[]/T
+
+	    "_arraySliceExpMinSliceAssign_a",
+	    "_arraySliceExpMinSliceAssign_d",	// T[]=T[]-T
+	    "_arraySliceExpMinSliceAssign_f",	// T[]=T[]-T
+	    "_arraySliceExpMinSliceAssign_g",
+	    "_arraySliceExpMinSliceAssign_h",
+	    "_arraySliceExpMinSliceAssign_i",
+	    "_arraySliceExpMinSliceAssign_k",
+	    "_arraySliceExpMinSliceAssign_s",
+	    "_arraySliceExpMinSliceAssign_t",
+	    "_arraySliceExpMinSliceAssign_u",
+	    "_arraySliceExpMinSliceAssign_w",
+
+	    "_arraySliceExpMulSliceAddass_d",	// T[] += T[]*T
+	    "_arraySliceExpMulSliceAddass_f",
+	    "_arraySliceExpMulSliceAddass_r",
+
+	    "_arraySliceExpMulSliceAssign_d",	// T[]=T[]*T
+	    "_arraySliceExpMulSliceAssign_f",	// T[]=T[]*T
+	    "_arraySliceExpMulSliceAssign_i",
+	    "_arraySliceExpMulSliceAssign_k",
+	    "_arraySliceExpMulSliceAssign_s",
+	    "_arraySliceExpMulSliceAssign_t",
+	    "_arraySliceExpMulSliceAssign_u",
+	    "_arraySliceExpMulSliceAssign_w",
+
+	    "_arraySliceExpMulSliceMinass_d",	// T[] -= T[]*T
+	    "_arraySliceExpMulSliceMinass_f",
+	    "_arraySliceExpMulSliceMinass_r",
+
+	    "_arraySliceSliceAddSliceAssign_a",
+	    "_arraySliceSliceAddSliceAssign_d",	// T[]=T[]+T[]
+	    "_arraySliceSliceAddSliceAssign_f",	// T[]=T[]+T[]
+	    "_arraySliceSliceAddSliceAssign_g",
+	    "_arraySliceSliceAddSliceAssign_h",
+	    "_arraySliceSliceAddSliceAssign_i",
+	    "_arraySliceSliceAddSliceAssign_k",
+	    "_arraySliceSliceAddSliceAssign_r",	// T[]=T[]+T[]
+	    "_arraySliceSliceAddSliceAssign_s",
+	    "_arraySliceSliceAddSliceAssign_t",
+	    "_arraySliceSliceAddSliceAssign_u",
+	    "_arraySliceSliceAddSliceAssign_w",
+
+	    "_arraySliceSliceAddass_a",
+	    "_arraySliceSliceAddass_d",		// T[]+=T[]
+	    "_arraySliceSliceAddass_f",		// T[]+=T[]
+	    "_arraySliceSliceAddass_g",
+	    "_arraySliceSliceAddass_h",
+	    "_arraySliceSliceAddass_i",
+	    "_arraySliceSliceAddass_k",
+	    "_arraySliceSliceAddass_s",
+	    "_arraySliceSliceAddass_t",
+	    "_arraySliceSliceAddass_u",
+	    "_arraySliceSliceAddass_w",
+
+	    "_arraySliceSliceMinSliceAssign_a",
+	    "_arraySliceSliceMinSliceAssign_d",	// T[]=T[]-T[]
+	    "_arraySliceSliceMinSliceAssign_f",	// T[]=T[]-T[]
+	    "_arraySliceSliceMinSliceAssign_g",
+	    "_arraySliceSliceMinSliceAssign_h",
+	    "_arraySliceSliceMinSliceAssign_i",
+	    "_arraySliceSliceMinSliceAssign_k",
+	    "_arraySliceSliceMinSliceAssign_r",	// T[]=T[]-T[]
+	    "_arraySliceSliceMinSliceAssign_s",
+	    "_arraySliceSliceMinSliceAssign_t",
+	    "_arraySliceSliceMinSliceAssign_u",
+	    "_arraySliceSliceMinSliceAssign_w",
+
+	    "_arraySliceSliceMinass_a",
+	    "_arraySliceSliceMinass_d",		// T[]-=T[]
+	    "_arraySliceSliceMinass_f",		// T[]-=T[]
+	    "_arraySliceSliceMinass_g",
+	    "_arraySliceSliceMinass_h",
+	    "_arraySliceSliceMinass_i",
+	    "_arraySliceSliceMinass_k",
+	    "_arraySliceSliceMinass_s",
+	    "_arraySliceSliceMinass_t",
+	    "_arraySliceSliceMinass_u",
+	    "_arraySliceSliceMinass_w",
+
+	    "_arraySliceSliceMulSliceAssign_d",	// T[]=T[]*T[]
+	    "_arraySliceSliceMulSliceAssign_f",	// T[]=T[]*T[]
+	    "_arraySliceSliceMulSliceAssign_i",
+	    "_arraySliceSliceMulSliceAssign_k",
+	    "_arraySliceSliceMulSliceAssign_s",
+	    "_arraySliceSliceMulSliceAssign_t",
+	    "_arraySliceSliceMulSliceAssign_u",
+	    "_arraySliceSliceMulSliceAssign_w",
+
+	    "_arraySliceSliceMulass_d",		// T[]*=T[]
+	    "_arraySliceSliceMulass_f",		// T[]*=T[]
+	    "_arraySliceSliceMulass_i",
+	    "_arraySliceSliceMulass_k",
+	    "_arraySliceSliceMulass_s",
+	    "_arraySliceSliceMulass_t",
+	    "_arraySliceSliceMulass_u",
+	    "_arraySliceSliceMulass_w",
+	};
+
+	int i = binary(name, libArrayopFuncs, sizeof(libArrayopFuncs) / sizeof(char *));
+	if (i == -1)
+	{
+#ifdef DEBUG	// Make sure our array is alphabetized
+	    for (i = 0; i < sizeof(libArrayopFuncs) / sizeof(char *); i++)
+	    {
+		if (strcmp(name, libArrayopFuncs[i]) == 0)
+		    assert(0);
+	    }
+#endif
+#endif
+	    /* Not in library, so generate it.
+	     * Construct the function body:
+	     *	foreach (i; 0 .. p.length)    for (size_t i = 0; i < p.length; i++)
+	     *	    loopbody;
+	     *	return p;
+	     */
+
+	    Arguments *fparams = new Arguments();
+	    Expression *loopbody = buildArrayLoop(fparams);
+	    Argument *p = (Argument *)fparams->data[0 /*fparams->dim - 1*/];
+#if DMDV1
+	    // for (size_t i = 0; i < p.length; i++)
+	    Initializer *init = new ExpInitializer(0, new IntegerExp(0, 0, Type::tsize_t));
+	    Dsymbol *d = new VarDeclaration(0, Type::tsize_t, Id::p, init);
+	    Statement *s1 = new ForStatement(0,
+		new DeclarationStatement(0, d),
+		new CmpExp(TOKlt, 0, new IdentifierExp(0, Id::p), new ArrayLengthExp(0, new IdentifierExp(0, p->ident))),
+		new PostExp(TOKplusplus, 0, new IdentifierExp(0, Id::p)),
+		new ExpStatement(0, loopbody));
+#else
+	    // foreach (i; 0 .. p.length)
+	    Statement *s1 = new ForeachRangeStatement(0, TOKforeach,
+		new Argument(0, NULL, Id::p, NULL),
+		new IntegerExp(0, 0, Type::tint32),
+		new ArrayLengthExp(0, new IdentifierExp(0, p->ident)),
+		new ExpStatement(0, loopbody));
+#endif
+	    Statement *s2 = new ReturnStatement(0, new IdentifierExp(0, p->ident));
+	    //printf("s2: %s\n", s2->toChars());
+	    Statement *fbody = new CompoundStatement(0, s1, s2);
+
+	    /* Construct the function
+	     */
+	    TypeFunction *ftype = new TypeFunction(fparams, type, 0, LINKc);
+	    //printf("ftype: %s\n", ftype->toChars());
+	    fd = new FuncDeclaration(0, 0, Lexer::idPool(name), STCundefined, ftype);
+	    fd->fbody = fbody;
+	    fd->protection = PROTpublic;
+	    fd->linkage = LINKd;
+
+   		// special attention for array ops
+        fd->isArrayOp = true;
+
+	    sc->module->importedFrom->members->push(fd);
+
+	    sc = sc->push();
+	    sc->parent = sc->module->importedFrom;
+	    sc->stc = 0;
+	    sc->linkage = LINKc;
+	    fd->semantic(sc);
+	    sc->pop();
+#if IN_DMD
+	}
+	else
+	{   /* In library, refer to it.
+	     */
+	    fd = FuncDeclaration::genCfunc(type, name);
+	}
+#endif
+	sv->ptrvalue = fd;	// cache symbol in hash table
+    }
+
+    /* Call the function fd(arguments)
+     */
+    Expression *ec = new VarExp(0, fd);
+    Expression *e = new CallExp(loc, ec, arguments);
+    e->type = type;
+    return e;
+}
+
+/******************************************
+ * Construct the identifier for the array operation function,
+ * and build the argument list to pass to it.
+ */
+
+void Expression::buildArrayIdent(OutBuffer *buf, Expressions *arguments)
+{
+    buf->writestring("Exp");
+    arguments->shift(this);
+}
+
+void SliceExp::buildArrayIdent(OutBuffer *buf, Expressions *arguments)
+{
+    buf->writestring("Slice");
+    arguments->shift(this);
+}
+
+void AssignExp::buildArrayIdent(OutBuffer *buf, Expressions *arguments)
+{
+    /* Evaluate assign expressions right to left
+     */
+    e2->buildArrayIdent(buf, arguments);
+    e1->buildArrayIdent(buf, arguments);
+    buf->writestring("Assign");
+}
+
+#define X(Str) \
+void Str##AssignExp::buildArrayIdent(OutBuffer *buf, Expressions *arguments) \
+{							\
+    /* Evaluate assign expressions right to left	\
+     */							\
+    e2->buildArrayIdent(buf, arguments);		\
+    e1->buildArrayIdent(buf, arguments);		\
+    buf->writestring(#Str);				\
+    buf->writestring("ass");				\
+}
+
+X(Add)
+X(Min)
+X(Mul)
+X(Div)
+X(Mod)
+X(Xor)
+X(And)
+X(Or)
+
+#undef X
+
+void NegExp::buildArrayIdent(OutBuffer *buf, Expressions *arguments)
+{
+    e1->buildArrayIdent(buf, arguments);
+    buf->writestring("Neg");
+}
+
+void ComExp::buildArrayIdent(OutBuffer *buf, Expressions *arguments)
+{
+    e1->buildArrayIdent(buf, arguments);
+    buf->writestring("Com");
+}
+
+#define X(Str) \
+void Str##Exp::buildArrayIdent(OutBuffer *buf, Expressions *arguments)	\
+{									\
+    /* Evaluate assign expressions left to right			\
+     */									\
+    e1->buildArrayIdent(buf, arguments);				\
+    e2->buildArrayIdent(buf, arguments);				\
+    buf->writestring(#Str);						\
+}
+
+X(Add)
+X(Min)
+X(Mul)
+X(Div)
+X(Mod)
+X(Xor)
+X(And)
+X(Or)
+
+#undef X
+
+/******************************************
+ * Construct the inner loop for the array operation function,
+ * and build the parameter list.
+ */
+
+Expression *Expression::buildArrayLoop(Arguments *fparams)
+{
+    Identifier *id = Identifier::generateId("c", fparams->dim);
+    Argument *param = new Argument(0, type, id, NULL);
+    fparams->shift(param);
+    Expression *e = new IdentifierExp(0, id);
+    return e;
+}
+
+Expression *SliceExp::buildArrayLoop(Arguments *fparams)
+{
+    Identifier *id = Identifier::generateId("p", fparams->dim);
+    Argument *param = new Argument(STCconst, type, id, NULL);
+    fparams->shift(param);
+    Expression *e = new IdentifierExp(0, id);
+    Expressions *arguments = new Expressions();
+    Expression *index = new IdentifierExp(0, Id::p);
+    arguments->push(index);
+    e = new ArrayExp(0, e, arguments);
+    return e;
+}
+
+Expression *AssignExp::buildArrayLoop(Arguments *fparams)
+{
+    /* Evaluate assign expressions right to left
+     */
+    Expression *ex2 = e2->buildArrayLoop(fparams);
+    Expression *ex1 = e1->buildArrayLoop(fparams);
+    Argument *param = (Argument *)fparams->data[0];
+    param->storageClass = 0;
+    Expression *e = new AssignExp(0, ex1, ex2);
+    return e;
+}
+
+#define X(Str) \
+Expression *Str##AssignExp::buildArrayLoop(Arguments *fparams)	\
+{								\
+    /* Evaluate assign expressions right to left		\
+     */								\
+    Expression *ex2 = e2->buildArrayLoop(fparams);		\
+    Expression *ex1 = e1->buildArrayLoop(fparams);		\
+    Argument *param = (Argument *)fparams->data[0];		\
+    param->storageClass = 0;					\
+    Expression *e = new Str##AssignExp(0, ex1, ex2);		\
+    return e;							\
+}
+
+X(Add)
+X(Min)
+X(Mul)
+X(Div)
+X(Mod)
+X(Xor)
+X(And)
+X(Or)
+
+#undef X
+
+Expression *NegExp::buildArrayLoop(Arguments *fparams)
+{
+    Expression *ex1 = e1->buildArrayLoop(fparams);
+    Expression *e = new NegExp(0, ex1);
+    return e;
+}
+
+Expression *ComExp::buildArrayLoop(Arguments *fparams)
+{
+    Expression *ex1 = e1->buildArrayLoop(fparams);
+    Expression *e = new ComExp(0, ex1);
+    return e;
+}
+
+#define X(Str) \
+Expression *Str##Exp::buildArrayLoop(Arguments *fparams)	\
+{								\
+    /* Evaluate assign expressions left to right		\
+     */								\
+    Expression *ex1 = e1->buildArrayLoop(fparams);		\
+    Expression *ex2 = e2->buildArrayLoop(fparams);		\
+    Expression *e = new Str##Exp(0, ex1, ex2);			\
+    return e;							\
+}
+
+X(Add)
+X(Min)
+X(Mul)
+X(Div)
+X(Mod)
+X(Xor)
+X(And)
+X(Or)
+
+#undef X
+
+
--- a/dmd2/attrib.c	Mon Jun 01 01:28:18 2009 +0200
+++ b/dmd2/attrib.c	Mon Jun 01 19:02:20 2009 +0100
@@ -1,1483 +1,1553 @@
-
-// 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 <stdlib.h>
-#include <assert.h>
-
-#if _WIN32 || IN_GCC || IN_LLVM
-#include "mem.h"
-#elif POSIX
-#include "../root/mem.h"
-#endif
-
-#include "init.h"
-#include "declaration.h"
-#include "attrib.h"
-#include "cond.h"
-#include "scope.h"
-#include "id.h"
-#include "expression.h"
-#include "dsymbol.h"
-#include "aggregate.h"
-#include "module.h"
-#include "parse.h"
-#include "template.h"
-
-#include "../gen/enums.h"
-
-
-#include "llvm/Support/CommandLine.h"
-
-static llvm::cl::opt<bool> ignoreUnsupportedPragmas("ignore",
-    llvm::cl::desc("Ignore unsupported pragmas"),
-    llvm::cl::ZeroOrMore);
-
-
-
-extern void obj_includelib(const char *name);
-void obj_startaddress(Symbol *s);
-
-
-/********************************* AttribDeclaration ****************************/
-
-AttribDeclaration::AttribDeclaration(Array *decl)
-	: Dsymbol()
-{
-    this->decl = decl;
-}
-
-Array *AttribDeclaration::include(Scope *sc, ScopeDsymbol *sd)
-{
-    return decl;
-}
-
-int AttribDeclaration::addMember(Scope *sc, ScopeDsymbol *sd, int memnum)
-{
-    int m = 0;
-    Array *d = include(sc, sd);
-
-    if (d)
-    {
-	for (unsigned i = 0; i < d->dim; i++)
-	{   Dsymbol *s = (Dsymbol *)d->data[i];
-	    m |= s->addMember(sc, sd, m | memnum);
-	}
-    }
-    return m;
-}
-
-void AttribDeclaration::semantic(Scope *sc)
-{
-    Array *d = include(sc, NULL);
-
-    //printf("\tAttribDeclaration::semantic '%s', d = %p\n",toChars(), d);
-    if (d)
-    {
-	for (unsigned i = 0; i < d->dim; i++)
-	{
-	    Dsymbol *s = (Dsymbol *)d->data[i];
-
-	    s->semantic(sc);
-	}
-    }
-}
-
-void AttribDeclaration::semantic2(Scope *sc)
-{
-    Array *d = include(sc, NULL);
-
-    if (d)
-    {
-	for (unsigned i = 0; i < d->dim; i++)
-	{   Dsymbol *s = (Dsymbol *)d->data[i];
-	    s->semantic2(sc);
-	}
-    }
-}
-
-void AttribDeclaration::semantic3(Scope *sc)
-{
-    Array *d = include(sc, NULL);
-
-    if (d)
-    {
-	for (unsigned i = 0; i < d->dim; i++)
-	{   Dsymbol *s = (Dsymbol *)d->data[i];
-	    s->semantic3(sc);
-	}
-    }
-}
-
-void AttribDeclaration::inlineScan()
-{
-    Array *d = include(NULL, NULL);
-
-    if (d)
-    {
-	for (unsigned i = 0; i < d->dim; i++)
-	{   Dsymbol *s = (Dsymbol *)d->data[i];
-	    //printf("AttribDeclaration::inlineScan %s\n", s->toChars());
-	    s->inlineScan();
-	}
-    }
-}
-
-void AttribDeclaration::addComment(unsigned char *comment)
-{
-    if (comment)
-    {
-	Array *d = include(NULL, NULL);
-
-	if (d)
-	{
-	    for (unsigned i = 0; i < d->dim; i++)
-	    {   Dsymbol *s = (Dsymbol *)d->data[i];
-		//printf("AttribDeclaration::addComment %s\n", s->toChars());
-		s->addComment(comment);
-	    }
-	}
-    }
-}
-
-void AttribDeclaration::emitComment(Scope *sc)
-{
-    //printf("AttribDeclaration::emitComment(sc = %p)\n", sc);
-
-    /* If generating doc comment, skip this because if we're inside
-     * a template, then include(NULL, NULL) will fail.
-     */
-//    if (sc->docbuf)
-//	return;
-
-    Array *d = include(NULL, NULL);
-
-    if (d)
-    {
-	for (unsigned i = 0; i < d->dim; i++)
-	{   Dsymbol *s = (Dsymbol *)d->data[i];
-	    //printf("AttribDeclaration::emitComment %s\n", s->toChars());
-	    s->emitComment(sc);
-	}
-    }
-}
-
-void AttribDeclaration::toObjFile(int multiobj)
-{
-    Array *d = include(NULL, NULL);
-
-    if (d)
-    {
-	for (unsigned i = 0; i < d->dim; i++)
-	{   Dsymbol *s = (Dsymbol *)d->data[i];
-	    s->toObjFile(multiobj);
-	}
-    }
-}
-
-int AttribDeclaration::cvMember(unsigned char *p)
-{
-    int nwritten = 0;
-    int n;
-    Array *d = include(NULL, NULL);
-
-    if (d)
-    {
-	for (unsigned i = 0; i < d->dim; i++)
-	{   Dsymbol *s = (Dsymbol *)d->data[i];
-	    n = s->cvMember(p);
-	    if (p)
-		p += n;
-	    nwritten += n;
-	}
-    }
-    return nwritten;
-}
-
-int AttribDeclaration::hasPointers()
-{
-    Array *d = include(NULL, NULL);
-
-    if (d)
-    {
-	for (size_t i = 0; i < d->dim; i++)
-	{
-	    Dsymbol *s = (Dsymbol *)d->data[i];
-	    if (s->hasPointers())
-		return 1;
-	}
-    }
-    return 0;
-}
-
-const char *AttribDeclaration::kind()
-{
-    return "attribute";
-}
-
-int AttribDeclaration::oneMember(Dsymbol **ps)
-{
-    Array *d = include(NULL, NULL);
-
-    return Dsymbol::oneMembers(d, ps);
-}
-
-void AttribDeclaration::checkCtorConstInit()
-{
-    Array *d = include(NULL, NULL);
-
-    if (d)
-    {
-	for (unsigned i = 0; i < d->dim; i++)
-	{   Dsymbol *s = (Dsymbol *)d->data[i];
-	    s->checkCtorConstInit();
-	}
-    }
-}
-
-/****************************************
- */
-
-void AttribDeclaration::addLocalClass(ClassDeclarations *aclasses)
-{
-    Array *d = include(NULL, NULL);
-
-    if (d)
-    {
-	for (unsigned i = 0; i < d->dim; i++)
-	{   Dsymbol *s = (Dsymbol *)d->data[i];
-	    s->addLocalClass(aclasses);
-	}
-    }
-}
-
-
-void AttribDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{
-    if (decl)
-    {
-	buf->writenl();
-	buf->writeByte('{');
-	buf->writenl();
-	for (unsigned i = 0; i < decl->dim; i++)
-	{
-	    Dsymbol *s = (Dsymbol *)decl->data[i];
-
-	    buf->writestring("    ");
-	    s->toCBuffer(buf, hgs);
-	}
-	buf->writeByte('}');
-    }
-    else
-	buf->writeByte(';');
-    buf->writenl();
-}
-
-/************************* StorageClassDeclaration ****************************/
-
-StorageClassDeclaration::StorageClassDeclaration(unsigned stc, Array *decl)
-	: AttribDeclaration(decl)
-{
-    this->stc = stc;
-}
-
-Dsymbol *StorageClassDeclaration::syntaxCopy(Dsymbol *s)
-{
-    StorageClassDeclaration *scd;
-
-    assert(!s);
-    scd = new StorageClassDeclaration(stc, Dsymbol::arraySyntaxCopy(decl));
-    return scd;
-}
-
-void StorageClassDeclaration::semantic(Scope *sc)
-{
-    if (decl)
-    {	unsigned stc_save = sc->stc;
-
-	/* These sets of storage classes are mutually exclusive,
-	 * so choose the innermost or most recent one.
-	 */
-	if (stc & (STCauto | STCscope | STCstatic | STCextern | STCmanifest))
-	    sc->stc &= ~(STCauto | STCscope | STCstatic | STCextern | STCmanifest);
-	if (stc & (STCauto | STCscope | STCstatic | STCtls | STCmanifest))
-	    sc->stc &= ~(STCauto | STCscope | STCstatic | STCtls | STCmanifest);
-	if (stc & (STCconst | STCinvariant | STCmanifest))
-	    sc->stc &= ~(STCconst | STCinvariant | STCmanifest);
-	sc->stc |= stc;
-	for (unsigned i = 0; i < decl->dim; i++)
-	{
-	    Dsymbol *s = (Dsymbol *)decl->data[i];
-
-	    s->semantic(sc);
-	}
-	sc->stc = stc_save;
-    }
-    else
-	sc->stc = stc;
-}
-
-void StorageClassDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{
-    struct SCstring
-    {
-	int stc;
-	enum TOK tok;
-    };
-
-    static SCstring table[] =
-    {
-	{ STCauto,         TOKauto },
-	{ STCscope,        TOKscope },
-	{ STCstatic,       TOKstatic },
-	{ STCextern,       TOKextern },
-	{ STCconst,        TOKconst },
-	{ STCinvariant,    TOKimmutable },
-	{ STCshared,       TOKshared },
-	{ STCfinal,        TOKfinal },
-	{ STCabstract,     TOKabstract },
-	{ STCsynchronized, TOKsynchronized },
-	{ STCdeprecated,   TOKdeprecated },
-	{ STCoverride,     TOKoverride },
-	{ STCnothrow,      TOKnothrow },
-	{ STCpure,         TOKpure },
-	{ STCref,          TOKref },
-	{ STCtls,          TOKtls },
-    };
-
-    int written = 0;
-    for (int i = 0; i < sizeof(table)/sizeof(table[0]); i++)
-    {
-	if (stc & table[i].stc)
-	{
-	    if (written)
-		buf->writeByte(' ');
-	    written = 1;
-	    buf->writestring(Token::toChars(table[i].tok));
-	}
-    }
-
-    AttribDeclaration::toCBuffer(buf, hgs);
-}
-
-/********************************* LinkDeclaration ****************************/
-
-LinkDeclaration::LinkDeclaration(enum LINK p, Array *decl)
-	: AttribDeclaration(decl)
-{
-    //printf("LinkDeclaration(linkage = %d, decl = %p)\n", p, decl);
-    linkage = p;
-}
-
-Dsymbol *LinkDeclaration::syntaxCopy(Dsymbol *s)
-{
-    LinkDeclaration *ld;
-
-    assert(!s);
-    ld = new LinkDeclaration(linkage, Dsymbol::arraySyntaxCopy(decl));
-    return ld;
-}
-
-void LinkDeclaration::semantic(Scope *sc)
-{
-    //printf("LinkDeclaration::semantic(linkage = %d, decl = %p)\n", linkage, decl);
-    if (decl)
-    {	enum LINK linkage_save = sc->linkage;
-
-	sc->linkage = linkage;
-	for (unsigned i = 0; i < decl->dim; i++)
-	{
-	    Dsymbol *s = (Dsymbol *)decl->data[i];
-
-	    s->semantic(sc);
-	}
-	sc->linkage = linkage_save;
-    }
-    else
-    {
-	sc->linkage = linkage;
-    }
-}
-
-void LinkDeclaration::semantic3(Scope *sc)
-{
-    //printf("LinkDeclaration::semantic3(linkage = %d, decl = %p)\n", linkage, decl);
-    if (decl)
-    {	enum LINK linkage_save = sc->linkage;
-
-	sc->linkage = linkage;
-	for (unsigned i = 0; i < decl->dim; i++)
-	{
-	    Dsymbol *s = (Dsymbol *)decl->data[i];
-
-	    s->semantic3(sc);
-	}
-	sc->linkage = linkage_save;
-    }
-    else
-    {
-	sc->linkage = linkage;
-    }
-}
-
-void LinkDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{   const char *p;
-
-    switch (linkage)
-    {
-	case LINKd:		p = "D";		break;
-	case LINKc:		p = "C";		break;
-	case LINKcpp:		p = "C++";		break;
-	case LINKwindows:	p = "Windows";		break;
-	case LINKpascal:	p = "Pascal";		break;
-
-    // LDC
-    case LINKintrinsic: p = "Intrinsic"; break;
-
-	default:
-	    assert(0);
-	    break;
-    }
-    buf->writestring("extern (");
-    buf->writestring(p);
-    buf->writestring(") ");
-    AttribDeclaration::toCBuffer(buf, hgs);
-}
-
-char *LinkDeclaration::toChars()
-{
-    return (char *)"extern ()";
-}
-
-/********************************* ProtDeclaration ****************************/
-
-ProtDeclaration::ProtDeclaration(enum PROT p, Array *decl)
-	: AttribDeclaration(decl)
-{
-    protection = p;
-    //printf("decl = %p\n", decl);
-}
-
-Dsymbol *ProtDeclaration::syntaxCopy(Dsymbol *s)
-{
-    ProtDeclaration *pd;
-
-    assert(!s);
-    pd = new ProtDeclaration(protection, Dsymbol::arraySyntaxCopy(decl));
-    return pd;
-}
-
-void ProtDeclaration::semantic(Scope *sc)
-{
-    if (decl)
-    {	enum PROT protection_save = sc->protection;
-	int explicitProtection_save = sc->explicitProtection;
-
-	sc->protection = protection;
-	sc->explicitProtection = 1;
-	for (unsigned i = 0; i < decl->dim; i++)
-	{
-	    Dsymbol *s = (Dsymbol *)decl->data[i];
-
-	    s->semantic(sc);
-	}
-	sc->protection = protection_save;
-	sc->explicitProtection = explicitProtection_save;
-    }
-    else
-    {	sc->protection = protection;
-	sc->explicitProtection = 1;
-    }
-}
-
-void ProtDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{   const char *p;
-
-    switch (protection)
-    {
-	case PROTprivate:	p = "private";		break;
-	case PROTpackage:	p = "package";		break;
-	case PROTprotected:	p = "protected";	break;
-	case PROTpublic:	p = "public";		break;
-	case PROTexport:	p = "export";		break;
-	default:
-	    assert(0);
-	    break;
-    }
-    buf->writestring(p);
-    AttribDeclaration::toCBuffer(buf, hgs);
-}
-
-/********************************* AlignDeclaration ****************************/
-
-AlignDeclaration::AlignDeclaration(Loc loc, unsigned sa, Array *decl)
-	: AttribDeclaration(decl)
-{
-    this->loc = loc;
-    salign = sa;
-}
-
-Dsymbol *AlignDeclaration::syntaxCopy(Dsymbol *s)
-{
-    AlignDeclaration *ad;
-
-    assert(!s);
-    ad = new AlignDeclaration(loc, salign, Dsymbol::arraySyntaxCopy(decl));
-    return ad;
-}
-
-void AlignDeclaration::semantic(Scope *sc)
-{
-// LDC
-// we only support packed structs, as from the spec: align(1) struct Packed { ... }
-// other alignments are simply ignored. my tests show this is what llvm-gcc does too ...
-
-    //printf("\tAlignDeclaration::semantic '%s'\n",toChars());
-    if (decl)
-    {	unsigned salign_save = sc->structalign;
-
-	for (unsigned i = 0; i < decl->dim; i++)
-	{
-	    Dsymbol *s = (Dsymbol *)decl->data[i];
-
-        if (s->isStructDeclaration() && salign == 1)
-        {
-            sc->structalign = salign;
-            s->semantic(sc);
-            sc->structalign = salign_save;
-        }
-        else
-        {
-            s->semantic(sc);
-        }
-	}
-	sc->structalign = salign_save;
-    }
-    else
-    assert(0 && "what kind of align use triggers this?");
-}
-
-
-void AlignDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{
-    buf->printf("align (%d)", salign);
-    AttribDeclaration::toCBuffer(buf, hgs);
-}
-
-/********************************* AnonDeclaration ****************************/
-
-AnonDeclaration::AnonDeclaration(Loc loc, int isunion, Array *decl)
-	: AttribDeclaration(decl)
-{
-    this->loc = loc;
-    this->isunion = isunion;
-    this->scope = NULL;
-    this->sem = 0;
-}
-
-Dsymbol *AnonDeclaration::syntaxCopy(Dsymbol *s)
-{
-    AnonDeclaration *ad;
-
-    assert(!s);
-    ad = new AnonDeclaration(loc, isunion, Dsymbol::arraySyntaxCopy(decl));
-    return ad;
-}
-
-void AnonDeclaration::semantic(Scope *sc)
-{
-    //printf("\tAnonDeclaration::semantic %s %p\n", isunion ? "union" : "struct", this);
-
-    Scope *scx = NULL;
-    if (scope)
-    {   sc = scope;
-	scx = scope;
-	scope = NULL;
-    }
-
-    assert(sc->parent);
-
-    Dsymbol *parent = sc->parent->pastMixin();
-    AggregateDeclaration *ad = parent->isAggregateDeclaration();
-
-    if (!ad || (!ad->isStructDeclaration() && !ad->isClassDeclaration()))
-    {
-	error("can only be a part of an aggregate");
-	return;
-    }
-
-    if (decl)
-    {
-	AnonymousAggregateDeclaration aad;
-	int adisunion;
-
-	if (sc->anonAgg)
-	{   ad = sc->anonAgg;
-	    adisunion = sc->inunion;
-	}
-	else
-	    adisunion = ad->isUnionDeclaration() != NULL;
-
-//	printf("\tsc->anonAgg = %p\n", sc->anonAgg);
-//	printf("\tad  = %p\n", ad);
-//	printf("\taad = %p\n", &aad);
-
-	sc = sc->push();
-	sc->anonAgg = &aad;
-	sc->stc &= ~(STCauto | STCscope | STCstatic | STCtls);
-	sc->inunion = isunion;
-	sc->offset = 0;
-	sc->flags = 0;
-	aad.structalign = sc->structalign;
-	aad.parent = ad;
-	for (unsigned i = 0; i < decl->dim; i++)
-	{
-	    Dsymbol *s = (Dsymbol *)decl->data[i];
-
-	    s->semantic(sc);
-	    if (isunion)
-		sc->offset = 0;
-	    if (aad.sizeok == 2)
-	    {
-		break;
-	    }
-	}
-	sc = sc->pop();
-
-	// If failed due to forward references, unwind and try again later
-	if (aad.sizeok == 2)
-	{
-	    ad->sizeok = 2;
-	    //printf("\tsetting ad->sizeok %p to 2\n", ad);
-	    if (!sc->anonAgg)
-	    {
-		scope = scx ? scx : new Scope(*sc);
-		scope->setNoFree();
-		scope->module->addDeferredSemantic(this);
-	    }
-	    //printf("\tforward reference %p\n", this);
-	    return;
-	}
-	if (sem == 0)
-	{   Module::dprogress++;
-	    sem = 1;
-	    //printf("\tcompleted %p\n", this);
-	}
-	else
-	    ;//printf("\talready completed %p\n", this);
-
-	// 0 sized structs are set to 1 byte
-	if (aad.structsize == 0)
-	{
-	    aad.structsize = 1;
-	    aad.alignsize = 1;
-	}
-
-	// Align size of anonymous aggregate
-//printf("aad.structalign = %d, aad.alignsize = %d, sc->offset = %d\n", aad.structalign, aad.alignsize, sc->offset);
-	ad->alignmember(aad.structalign, aad.alignsize, &sc->offset);
-	//ad->structsize = sc->offset;
-//printf("sc->offset = %d\n", sc->offset);
-
-	// Add members of aad to ad
-	//printf("\tadding members of aad (%p) to '%s'\n", &aad, ad->toChars());
-	for (unsigned i = 0; i < aad.fields.dim; i++)
-	{
-	    VarDeclaration *v = (VarDeclaration *)aad.fields.data[i];
-
-        // LDC
-        v->offset2 = sc->offset;
-
-	    v->offset += sc->offset;
-
-        // LDC
-        if (!v->anonDecl)
-            v->anonDecl = this;
-
-	    ad->fields.push(v);
-	}
-
-	// Add size of aad to ad
-	if (adisunion)
-	{
-	    if (aad.structsize > ad->structsize)
-		ad->structsize = aad.structsize;
-	    sc->offset = 0;
-	}
-	else
-	{
-	    ad->structsize = sc->offset + aad.structsize;
-	    sc->offset = ad->structsize;
-	}
-
-	if (ad->alignsize < aad.alignsize)
-	    ad->alignsize = aad.alignsize;
-    }
-}
-
-
-void AnonDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{
-    buf->printf(isunion ? "union" : "struct");
-    buf->writestring("\n{\n");
-    if (decl)
-    {
-	for (unsigned i = 0; i < decl->dim; i++)
-	{
-	    Dsymbol *s = (Dsymbol *)decl->data[i];
-
-	    //buf->writestring("    ");
-	    s->toCBuffer(buf, hgs);
-	}
-    }
-    buf->writestring("}\n");
-}
-
-const char *AnonDeclaration::kind()
-{
-    return (isunion ? "anonymous union" : "anonymous struct");
-}
-
-/********************************* PragmaDeclaration ****************************/
-
-static bool parseStringExp(Expression* e, std::string& res)
-{
-    StringExp *s = NULL;
-
-    e = e->optimize(WANTvalue);
-    if (e->op == TOKstring && (s = (StringExp *)e))
-    {
-        char* str = (char*)s->string;
-        res = str;
-        return true;
-    }
-    return false;
-}
-
-PragmaDeclaration::PragmaDeclaration(Loc loc, Identifier *ident, Expressions *args, Array *decl)
-	: AttribDeclaration(decl)
-{
-    this->loc = loc;
-    this->ident = ident;
-    this->args = args;
-}
-
-Dsymbol *PragmaDeclaration::syntaxCopy(Dsymbol *s)
-{
-    PragmaDeclaration *pd;
-
-    assert(!s);
-    pd = new PragmaDeclaration(loc, ident,
-	Expression::arraySyntaxCopy(args), Dsymbol::arraySyntaxCopy(decl));
-    return pd;
-}
-
-void PragmaDeclaration::semantic(Scope *sc)
-{   // Should be merged with PragmaStatement
-
-#if IN_LLVM
-    int llvm_internal = 0;
-    std::string arg1str;
-
-#endif
-
-    //printf("\tPragmaDeclaration::semantic '%s'\n",toChars());
-    if (ident == Id::msg)
-    {
-	if (args)
-	{
-	    for (size_t i = 0; i < args->dim; i++)
-	    {
-		Expression *e = (Expression *)args->data[i];
-
-		e = e->semantic(sc);
-		e = e->optimize(WANTvalue | WANTinterpret);
-		if (e->op == TOKstring)
-		{
-		    StringExp *se = (StringExp *)e;
-		    fprintf(stdmsg, "%.*s", (int)se->len, se->string);
-		}
-		else
-		    error("string expected for message, not '%s'", e->toChars());
-	    }
-	    fprintf(stdmsg, "\n");
-	}
-	goto Lnodecl;
-    }
-    else if (ident == Id::lib)
-    {
-	if (!args || args->dim != 1)
-	    error("string expected for library name");
-	else
-	{
-	    Expression *e = (Expression *)args->data[0];
-
-	    e = e->semantic(sc);
-	    e = e->optimize(WANTvalue | WANTinterpret);
-	    args->data[0] = (void *)e;
-	    if (e->op != TOKstring)
-		error("string expected for library name, not '%s'", e->toChars());
-	    else if (global.params.verbose)
-	    {
-		StringExp *se = (StringExp *)e;
-		char *name = (char *)mem.malloc(se->len + 1);
-		memcpy(name, se->string, se->len);
-		name[se->len] = 0;
-		printf("library   %s\n", name);
-		mem.free(name);
-	    }
-	}
-	goto Lnodecl;
-    }
-#if IN_GCC
-    else if (ident == Id::GNU_asm)
-    {
-	if (! args || args->dim != 2)
-	    error("identifier and string expected for asm name");
-	else
-	{
-	    Expression *e;
-	    Declaration *d = NULL;
-	    StringExp *s = NULL;
-
-	    e = (Expression *)args->data[0];
-	    e = e->semantic(sc);
-	    if (e->op == TOKvar)
-	    {
-		d = ((VarExp *)e)->var;
-		if (! d->isFuncDeclaration() && ! d->isVarDeclaration())
-		    d = NULL;
-	    }
-	    if (!d)
-		error("first argument of GNU_asm must be a function or variable declaration");
-
-	    e = (Expression *)args->data[1];
-	    e = e->semantic(sc);
-	    e = e->optimize(WANTvalue);
-	    if (e->op == TOKstring && ((StringExp *)e)->sz == 1)
-		s = ((StringExp *)e);
-	    else
-		error("second argument of GNU_asm must be a char string");
-
-	    if (d && s)
-		d->c_ident = Lexer::idPool((char*) s->string);
-	}
-	goto Lnodecl;
-    }
-#endif
-    else if (ident == Id::startaddress)
-    {
-	if (!args || args->dim != 1)
-	    error("function name expected for start address");
-	else
-	{
-	    Expression *e = (Expression *)args->data[0];
-	    e = e->semantic(sc);
-	    e = e->optimize(WANTvalue | WANTinterpret);
-	    args->data[0] = (void *)e;
-	    Dsymbol *sa = getDsymbol(e);
-	    if (!sa || !sa->isFuncDeclaration())
-		error("function name expected for start address, not '%s'", e->toChars());
-	}
-	goto Lnodecl;
-    }
-
-    /////////////////////////////////////////////////////////////
-    /////////////////////////////////////////////////////////////
-    // LDC
-#if IN_LLVM
-
-    // pragma(intrinsic, "string") { funcdecl(s) }
-    else if (ident == Id::intrinsic)
-    {
-        Expression* expr = (Expression *)args->data[0];
-        expr = expr->semantic(sc);
-        if (!args || args->dim != 1 || !parseStringExp(expr, arg1str))
-        {
-             error("requires exactly 1 string literal parameter");
-             fatal();
-        }
-        llvm_internal = LLVMintrinsic;
-    }
-
-    // pragma(notypeinfo) { typedecl(s) }
-    else if (ident == Id::no_typeinfo)
-    {
-        if (args && args->dim > 0)
-        {
-             error("takes no parameters");
-             fatal();
-        }
-        llvm_internal = LLVMno_typeinfo;
-    }
-
-    // pragma(nomoduleinfo) ;
-    else if (ident == Id::no_moduleinfo)
-    {
-        if (args && args->dim > 0)
-        {
-             error("takes no parameters");
-             fatal();
-        }
-        llvm_internal = LLVMno_moduleinfo;
-    }
-
-    // pragma(alloca) { funcdecl(s) }
-    else if (ident == Id::Alloca)
-    {
-        if (args && args->dim > 0)
-        {
-             error("takes no parameters");
-             fatal();
-        }
-        llvm_internal = LLVMalloca;
-    }
-
-    // pragma(va_start) { templdecl(s) }
-    else if (ident == Id::vastart)
-    {
-        if (args && args->dim > 0)
-        {
-             error("takes no parameters");
-             fatal();
-        }
-        llvm_internal = LLVMva_start;
-    }
-
-    // pragma(va_copy) { funcdecl(s) }
-    else if (ident == Id::vacopy)
-    {
-        if (args && args->dim > 0)
-        {
-             error("takes no parameters");
-             fatal();
-        }
-        llvm_internal = LLVMva_copy;
-    }
-
-    // pragma(va_end) { funcdecl(s) }
-    else if (ident == Id::vaend)
-    {
-        if (args && args->dim > 0)
-        {
-             error("takes no parameters");
-             fatal();
-        }
-        llvm_internal = LLVMva_end;
-    }
-
-    // pragma(va_arg) { templdecl(s) }
-    else if (ident == Id::vaarg)
-    {
-        if (args && args->dim > 0)
-        {
-             error("takes no parameters");
-             fatal();
-        }
-        llvm_internal = LLVMva_arg;
-    }
-    
-    // pragma(ldc, "string") { templdecl(s) }
-    else if (ident == Id::ldc)
-    {
-        Expression* expr = (Expression *)args->data[0];
-        expr = expr->semantic(sc);
-        if (!args || args->dim != 1 || !parseStringExp(expr, arg1str))
-        {
-             error("requires exactly 1 string literal parameter");
-             fatal();
-        }
-        else if (arg1str == "verbose")
-        {
-            sc->module->llvmForceLogging = true;
-        }
-        else
-        {
-            error("command '%s' invalid");
-            fatal();
-        }
-    }
-
-#endif
-    // LDC
-    /////////////////////////////////////////////////////////////
-    /////////////////////////////////////////////////////////////
-
-    else if (ignoreUnsupportedPragmas)
-    {
-	if (global.params.verbose)
-	{
-	    /* Print unrecognized pragmas
-	     */
-	    printf("pragma    %s", ident->toChars());
-	    if (args)
-	    {
-		for (size_t i = 0; i < args->dim; i++)
-		{
-		    Expression *e = (Expression *)args->data[i];
-		    e = e->semantic(sc);
-		    e = e->optimize(WANTvalue | WANTinterpret);
-		    if (i == 0)
-			printf(" (");
-		    else
-			printf(",");
-		    printf("%s", e->toChars());
-		}
-		if (args->dim)
-		    printf(")");
-	    }
-	    printf("\n");
-	}
-	goto Lnodecl;
-    }
-    else
-	error("unrecognized pragma(%s)", ident->toChars());
-
-    if (decl)
-    {
-	for (unsigned i = 0; i < decl->dim; i++)
-	{
-	    Dsymbol *s = (Dsymbol *)decl->data[i];
-
-	    s->semantic(sc);
-
-// LDC
-#if IN_LLVM
-
-        if (llvm_internal)
-        {
-        if (s->llvmInternal)
-        {
-            error("multiple LDC specific pragmas not allowed not affect the same declaration ('%s' at '%s')", s->toChars(), s->loc.toChars());
-            fatal();
-        }
-        switch(llvm_internal)
-        {
-        case LLVMintrinsic:
-            if (FuncDeclaration* fd = s->isFuncDeclaration())
-            {
-                fd->llvmInternal = llvm_internal;
-                fd->intrinsicName = arg1str;
-                fd->linkage = LINKintrinsic;
-                ((TypeFunction*)fd->type)->linkage = LINKintrinsic;
-            }
-            else if (TemplateDeclaration* td = s->isTemplateDeclaration())
-            {
-                td->llvmInternal = llvm_internal;
-                td->intrinsicName = arg1str;
-            }
-            else
-            {
-                error("only allowed on function declarations");
-                fatal();
-            }
-            break;
-
-        case LLVMva_start:
-        case LLVMva_arg:
-            if (TemplateDeclaration* td = s->isTemplateDeclaration())
-            {
-                if (td->parameters->dim != 1)
-                {
-                    error("the '%s' pragma template must have exactly one template parameter", ident->toChars());
-                    fatal();
-                }
-                else if (!td->onemember)
-                {
-                    error("the '%s' pragma template must have exactly one member", ident->toChars());
-                    fatal();
-                }
-                else if (td->overnext || td->overroot)
-                {
-                    error("the '%s' pragma template must not be overloaded", ident->toChars());
-                    fatal();
-                }
-                td->llvmInternal = llvm_internal;
-            }
-            else
-            {
-                error("the '%s' pragma is only allowed on template declarations", ident->toChars());
-                fatal();
-            }
-            break;
-
-        case LLVMva_copy:
-        case LLVMva_end:
-            if (FuncDeclaration* fd = s->isFuncDeclaration())
-            {
-                fd->llvmInternal = llvm_internal;
-            }
-            else
-            {
-                error("the '%s' pragma is only allowed on function declarations", ident->toChars());
-                fatal();
-            }
-            break;
-
-        case LLVMno_typeinfo:
-            s->llvmInternal = llvm_internal;
-            break;
-
-        case LLVMalloca:
-            if (FuncDeclaration* fd = s->isFuncDeclaration())
-            {
-                fd->llvmInternal = llvm_internal;
-            }
-            else
-            {
-                error("the '%s' pragma must only be used on function declarations of type 'void* function(uint nbytes)'", ident->toChars());
-                fatal();
-            }
-            break;
-
-        default:
-            warning("the LDC specific pragma '%s' is not yet implemented, ignoring", ident->toChars());
-        }
-        }
-
-#endif // LDC
-
-    }
-    }
-    return;
-
-Lnodecl:
-    if (decl)
-	error("pragma is missing closing ';'");
-}
-
-int PragmaDeclaration::oneMember(Dsymbol **ps)
-{
-    *ps = NULL;
-    return TRUE;
-}
-
-const char *PragmaDeclaration::kind()
-{
-    return "pragma";
-}
-
-void PragmaDeclaration::toObjFile(int multiobj)
-{
-    if (ident == Id::lib)
-    {
-	assert(args && args->dim == 1);
-
-	Expression *e = (Expression *)args->data[0];
-
-	assert(e->op == TOKstring);
-
-	StringExp *se = (StringExp *)e;
-	char *name = (char *)mem.malloc(se->len + 1);
-	memcpy(name, se->string, se->len);
-	name[se->len] = 0;
-	obj_includelib(name);
-    }
-    else if (ident == Id::startaddress)
-    {
-	assert(args && args->dim == 1);
-	Expression *e = (Expression *)args->data[0];
-	Dsymbol *sa = getDsymbol(e);
-	FuncDeclaration *f = sa->isFuncDeclaration();
-	assert(f);
-	Symbol *s = f->toSymbol();
-    assert(0 && "startaddress pragma not implemented");
-// 	obj_startaddress(s);
-    }
-    AttribDeclaration::toObjFile(multiobj);
-}
-
-void PragmaDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{
-    buf->printf("pragma (%s", ident->toChars());
-    if (args && args->dim)
-    {
-        buf->writestring(", ");
-        argsToCBuffer(buf, args, hgs);
-    }
-    buf->writeByte(')');
-    AttribDeclaration::toCBuffer(buf, hgs);
-}
-
-
-/********************************* ConditionalDeclaration ****************************/
-
-ConditionalDeclaration::ConditionalDeclaration(Condition *condition, Array *decl, Array *elsedecl)
-	: AttribDeclaration(decl)
-{
-    //printf("ConditionalDeclaration::ConditionalDeclaration()\n");
-    this->condition = condition;
-    this->elsedecl = elsedecl;
-}
-
-Dsymbol *ConditionalDeclaration::syntaxCopy(Dsymbol *s)
-{
-    ConditionalDeclaration *dd;
-
-    assert(!s);
-    dd = new ConditionalDeclaration(condition->syntaxCopy(),
-	Dsymbol::arraySyntaxCopy(decl),
-	Dsymbol::arraySyntaxCopy(elsedecl));
-    return dd;
-}
-
-
-int ConditionalDeclaration::oneMember(Dsymbol **ps)
-{
-    //printf("ConditionalDeclaration::oneMember(), inc = %d\n", condition->inc);
-    if (condition->inc)
-    {
-	Array *d = condition->include(NULL, NULL) ? decl : elsedecl;
-	return Dsymbol::oneMembers(d, ps);
-    }
-    *ps = NULL;
-    return TRUE;
-}
-
-void ConditionalDeclaration::emitComment(Scope *sc)
-{
-    //printf("ConditionalDeclaration::emitComment(sc = %p)\n", sc);
-    if (condition->inc)
-    {
-	AttribDeclaration::emitComment(sc);
-    }
-}
-
-// Decide if 'then' or 'else' code should be included
-
-Array *ConditionalDeclaration::include(Scope *sc, ScopeDsymbol *sd)
-{
-    //printf("ConditionalDeclaration::include()\n");
-    assert(condition);
-    return condition->include(sc, sd) ? decl : elsedecl;
-}
-
-
-void ConditionalDeclaration::addComment(unsigned char *comment)
-{
-    /* Because addComment is called by the parser, if we called
-     * include() it would define a version before it was used.
-     * But it's no problem to drill down to both decl and elsedecl,
-     * so that's the workaround.
-     */
-
-    if (comment)
-    {
-	Array *d = decl;
-
-	for (int j = 0; j < 2; j++)
-	{
-	    if (d)
-	    {
-		for (unsigned i = 0; i < d->dim; i++)
-		{   Dsymbol *s;
-
-		    s = (Dsymbol *)d->data[i];
-		    //printf("ConditionalDeclaration::addComment %s\n", s->toChars());
-		    s->addComment(comment);
-		}
-	    }
-	    d = elsedecl;
-	}
-    }
-}
-
-void ConditionalDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{
-    condition->toCBuffer(buf, hgs);
-    if (decl || elsedecl)
-    {
-	buf->writenl();
-	buf->writeByte('{');
-	buf->writenl();
-	if (decl)
-	{
-	    for (unsigned i = 0; i < decl->dim; i++)
-	    {
-		Dsymbol *s = (Dsymbol *)decl->data[i];
-
-		buf->writestring("    ");
-		s->toCBuffer(buf, hgs);
-	    }
-	}
-	buf->writeByte('}');
-	if (elsedecl)
-	{
-	    buf->writenl();
-	    buf->writestring("else");
-	    buf->writenl();
-	    buf->writeByte('{');
-	    buf->writenl();
-	    for (unsigned i = 0; i < elsedecl->dim; i++)
-	    {
-		Dsymbol *s = (Dsymbol *)elsedecl->data[i];
-
-		buf->writestring("    ");
-		s->toCBuffer(buf, hgs);
-	    }
-	    buf->writeByte('}');
-	}
-    }
-    else
-	buf->writeByte(':');
-    buf->writenl();
-}
-
-/***************************** StaticIfDeclaration ****************************/
-
-StaticIfDeclaration::StaticIfDeclaration(Condition *condition,
-	Array *decl, Array *elsedecl)
-	: ConditionalDeclaration(condition, decl, elsedecl)
-{
-    //printf("StaticIfDeclaration::StaticIfDeclaration()\n");
-    sd = NULL;
-    addisdone = 0;
-}
-
-
-Dsymbol *StaticIfDeclaration::syntaxCopy(Dsymbol *s)
-{
-    StaticIfDeclaration *dd;
-
-    assert(!s);
-    dd = new StaticIfDeclaration(condition->syntaxCopy(),
-	Dsymbol::arraySyntaxCopy(decl),
-	Dsymbol::arraySyntaxCopy(elsedecl));
-    return dd;
-}
-
-
-int StaticIfDeclaration::addMember(Scope *sc, ScopeDsymbol *sd, int memnum)
-{
-    //printf("StaticIfDeclaration::addMember() '%s'\n",toChars());
-    /* This is deferred until semantic(), so that
-     * expressions in the condition can refer to declarations
-     * in the same scope, such as:
-     *
-     * template Foo(int i)
-     * {
-     *     const int j = i + 1;
-     *     static if (j == 3)
-     *         const int k;
-     * }
-     */
-    this->sd = sd;
-    int m = 0;
-
-    if (memnum == 0)
-    {	m = AttribDeclaration::addMember(sc, sd, memnum);
-	addisdone = 1;
-    }
-    return m;
-}
-
-
-void StaticIfDeclaration::semantic(Scope *sc)
-{
-    Array *d = include(sc, sd);
-
-    //printf("\tStaticIfDeclaration::semantic '%s', d = %p\n",toChars(), d);
-    if (d)
-    {
-	if (!addisdone)
-	{   AttribDeclaration::addMember(sc, sd, 1);
-	    addisdone = 1;
-	}
-
-	for (unsigned i = 0; i < d->dim; i++)
-	{
-	    Dsymbol *s = (Dsymbol *)d->data[i];
-
-	    s->semantic(sc);
-	}
-    }
-}
-
-const char *StaticIfDeclaration::kind()
-{
-    return "static if";
-}
-
-
-/***************************** CompileDeclaration *****************************/
-
-CompileDeclaration::CompileDeclaration(Loc loc, Expression *exp)
-    : AttribDeclaration(NULL)
-{
-    //printf("CompileDeclaration(loc = %d)\n", loc.linnum);
-    this->loc = loc;
-    this->exp = exp;
-    this->sd = NULL;
-    this->compiled = 0;
-}
-
-Dsymbol *CompileDeclaration::syntaxCopy(Dsymbol *s)
-{
-    //printf("CompileDeclaration::syntaxCopy('%s')\n", toChars());
-    CompileDeclaration *sc = new CompileDeclaration(loc, exp->syntaxCopy());
-    return sc;
-}
-
-int CompileDeclaration::addMember(Scope *sc, ScopeDsymbol *sd, int memnum)
-{
-    //printf("CompileDeclaration::addMember(sc = %p, memnum = %d)\n", sc, memnum);
-    this->sd = sd;
-    if (memnum == 0)
-    {	/* No members yet, so parse the mixin now
-	 */
-	compileIt(sc);
-	memnum |= AttribDeclaration::addMember(sc, sd, memnum);
-	compiled = 1;
-    }
-    return memnum;
-}
-
-void CompileDeclaration::compileIt(Scope *sc)
-{
-    //printf("CompileDeclaration::compileIt(loc = %d)\n", loc.linnum);
-    exp = exp->semantic(sc);
-    exp = resolveProperties(sc, exp);
-    exp = exp->optimize(WANTvalue | WANTinterpret);
-    if (exp->op != TOKstring)
-    {	exp->error("argument to mixin must be a string, not (%s)", exp->toChars());
-    }
-    else
-    {
-	StringExp *se = (StringExp *)exp;
-	se = se->toUTF8(sc);
-	Parser p(sc->module, (unsigned char *)se->string, se->len, 0);
-	p.loc = loc;
-	p.nextToken();
-	decl = p.parseDeclDefs(0);
-	if (p.token.value != TOKeof)
-	    exp->error("incomplete mixin declaration (%s)", se->toChars());
-    }
-}
-
-void CompileDeclaration::semantic(Scope *sc)
-{
-    //printf("CompileDeclaration::semantic()\n");
-
-    if (!compiled)
-    {
-	compileIt(sc);
-	AttribDeclaration::addMember(sc, sd, 0);
-	compiled = 1;
-    }
-    AttribDeclaration::semantic(sc);
-}
-
-void CompileDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{
-    buf->writestring("mixin(");
-    exp->toCBuffer(buf, hgs);
-    buf->writestring(");");
-    buf->writenl();
-}
+
+// Compiler implementation of the D programming language
+// Copyright (c) 1999-2009 by Digital Mars
+// All Rights Reserved
+// written by Walter Bright
+// http://www.digitalmars.com
+// License for redistribution is by either the Artistic License
+// in artistic.txt, or the GNU General Public License in gnu.txt.
+// See the included readme.txt for details.
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+
+#include "rmem.h"
+
+#include "init.h"
+#include "declaration.h"
+#include "attrib.h"
+#include "cond.h"
+#include "scope.h"
+#include "id.h"
+#include "expression.h"
+#include "dsymbol.h"
+#include "aggregate.h"
+#include "module.h"
+#include "parse.h"
+#include "template.h"
+
+#if IN_LLVM
+#include "../gen/enums.h"
+
+#include "llvm/Support/CommandLine.h"
+
+static llvm::cl::opt<bool> ignoreUnsupportedPragmas("ignore",
+    llvm::cl::desc("Ignore unsupported pragmas"),
+    llvm::cl::ZeroOrMore);
+
+#endif
+
+
+extern void obj_includelib(const char *name);
+
+#if IN_DMD
+void obj_startaddress(Symbol *s);
+#endif
+
+
+/********************************* AttribDeclaration ****************************/
+
+AttribDeclaration::AttribDeclaration(Array *decl)
+	: Dsymbol()
+{
+    this->decl = decl;
+}
+
+Array *AttribDeclaration::include(Scope *sc, ScopeDsymbol *sd)
+{
+    return decl;
+}
+
+int AttribDeclaration::addMember(Scope *sc, ScopeDsymbol *sd, int memnum)
+{
+    int m = 0;
+    Array *d = include(sc, sd);
+
+    if (d)
+    {
+	for (unsigned i = 0; i < d->dim; i++)
+	{   Dsymbol *s = (Dsymbol *)d->data[i];
+	    m |= s->addMember(sc, sd, m | memnum);
+	}
+    }
+    return m;
+}
+
+void AttribDeclaration::semantic(Scope *sc)
+{
+    Array *d = include(sc, NULL);
+
+    //printf("\tAttribDeclaration::semantic '%s', d = %p\n",toChars(), d);
+    if (d)
+    {
+	for (unsigned i = 0; i < d->dim; i++)
+	{
+	    Dsymbol *s = (Dsymbol *)d->data[i];
+
+	    s->semantic(sc);
+	}
+    }
+}
+
+void AttribDeclaration::semantic2(Scope *sc)
+{
+    Array *d = include(sc, NULL);
+
+    if (d)
+    {
+	for (unsigned i = 0; i < d->dim; i++)
+	{   Dsymbol *s = (Dsymbol *)d->data[i];
+	    s->semantic2(sc);
+	}
+    }
+}
+
+void AttribDeclaration::semantic3(Scope *sc)
+{
+    Array *d = include(sc, NULL);
+
+    if (d)
+    {
+	for (unsigned i = 0; i < d->dim; i++)
+	{   Dsymbol *s = (Dsymbol *)d->data[i];
+	    s->semantic3(sc);
+	}
+    }
+}
+
+void AttribDeclaration::inlineScan()
+{
+    Array *d = include(NULL, NULL);
+
+    if (d)
+    {
+	for (unsigned i = 0; i < d->dim; i++)
+	{   Dsymbol *s = (Dsymbol *)d->data[i];
+	    //printf("AttribDeclaration::inlineScan %s\n", s->toChars());
+	    s->inlineScan();
+	}
+    }
+}
+
+void AttribDeclaration::addComment(unsigned char *comment)
+{
+    if (comment)
+    {
+	Array *d = include(NULL, NULL);
+
+	if (d)
+	{
+	    for (unsigned i = 0; i < d->dim; i++)
+	    {   Dsymbol *s = (Dsymbol *)d->data[i];
+		//printf("AttribDeclaration::addComment %s\n", s->toChars());
+		s->addComment(comment);
+	    }
+	}
+    }
+}
+
+void AttribDeclaration::emitComment(Scope *sc)
+{
+    //printf("AttribDeclaration::emitComment(sc = %p)\n", sc);
+
+    /* A general problem with this, illustrated by BUGZILLA 2516,
+     * is that attributes are not transmitted through to the underlying
+     * member declarations for template bodies, because semantic analysis
+     * is not done for template declaration bodies
+     * (only template instantiations).
+     * Hence, Ddoc omits attributes from template members.
+     */
+
+    Array *d = include(NULL, NULL);
+
+    if (d)
+    {
+	for (unsigned i = 0; i < d->dim; i++)
+	{   Dsymbol *s = (Dsymbol *)d->data[i];
+	    //printf("AttribDeclaration::emitComment %s\n", s->toChars());
+	    s->emitComment(sc);
+	}
+    }
+}
+
+#if IN_DMD
+
+void AttribDeclaration::toObjFile(int multiobj)
+{
+    Array *d = include(NULL, NULL);
+
+    if (d)
+    {
+	for (unsigned i = 0; i < d->dim; i++)
+	{   Dsymbol *s = (Dsymbol *)d->data[i];
+	    s->toObjFile(multiobj);
+	}
+    }
+}
+
+int AttribDeclaration::cvMember(unsigned char *p)
+{
+    int nwritten = 0;
+    int n;
+    Array *d = include(NULL, NULL);
+
+    if (d)
+    {
+	for (unsigned i = 0; i < d->dim; i++)
+	{   Dsymbol *s = (Dsymbol *)d->data[i];
+	    n = s->cvMember(p);
+	    if (p)
+		p += n;
+	    nwritten += n;
+	}
+    }
+    return nwritten;
+}
+#endif
+
+int AttribDeclaration::hasPointers()
+{
+    Array *d = include(NULL, NULL);
+
+    if (d)
+    {
+	for (size_t i = 0; i < d->dim; i++)
+	{
+	    Dsymbol *s = (Dsymbol *)d->data[i];
+	    if (s->hasPointers())
+		return 1;
+	}
+    }
+    return 0;
+}
+
+const char *AttribDeclaration::kind()
+{
+    return "attribute";
+}
+
+int AttribDeclaration::oneMember(Dsymbol **ps)
+{
+    Array *d = include(NULL, NULL);
+
+    return Dsymbol::oneMembers(d, ps);
+}
+
+void AttribDeclaration::checkCtorConstInit()
+{
+    Array *d = include(NULL, NULL);
+
+    if (d)
+    {
+	for (unsigned i = 0; i < d->dim; i++)
+	{   Dsymbol *s = (Dsymbol *)d->data[i];
+	    s->checkCtorConstInit();
+	}
+    }
+}
+
+/****************************************
+ */
+
+void AttribDeclaration::addLocalClass(ClassDeclarations *aclasses)
+{
+    Array *d = include(NULL, NULL);
+
+    if (d)
+    {
+	for (unsigned i = 0; i < d->dim; i++)
+	{   Dsymbol *s = (Dsymbol *)d->data[i];
+	    s->addLocalClass(aclasses);
+	}
+    }
+}
+
+
+void AttribDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    if (decl)
+    {
+	buf->writenl();
+	buf->writeByte('{');
+	buf->writenl();
+	for (unsigned i = 0; i < decl->dim; i++)
+	{
+	    Dsymbol *s = (Dsymbol *)decl->data[i];
+
+	    buf->writestring("    ");
+	    s->toCBuffer(buf, hgs);
+	}
+	buf->writeByte('}');
+    }
+    else
+	buf->writeByte(';');
+    buf->writenl();
+}
+
+/************************* StorageClassDeclaration ****************************/
+
+StorageClassDeclaration::StorageClassDeclaration(unsigned stc, Array *decl)
+	: AttribDeclaration(decl)
+{
+    this->stc = stc;
+}
+
+Dsymbol *StorageClassDeclaration::syntaxCopy(Dsymbol *s)
+{
+    StorageClassDeclaration *scd;
+
+    assert(!s);
+    scd = new StorageClassDeclaration(stc, Dsymbol::arraySyntaxCopy(decl));
+    return scd;
+}
+
+void StorageClassDeclaration::semantic(Scope *sc)
+{
+    if (decl)
+    {	unsigned stc_save = sc->stc;
+
+	if (stc & (STCauto | STCscope | STCstatic | STCextern))
+	    sc->stc &= ~(STCauto | STCscope | STCstatic | STCextern);
+	sc->stc |= stc;
+	for (unsigned i = 0; i < decl->dim; i++)
+	{
+	    Dsymbol *s = (Dsymbol *)decl->data[i];
+
+	    s->semantic(sc);
+	}
+	sc->stc = stc_save;
+    }
+    else
+	sc->stc = stc;
+}
+
+void StorageClassDeclaration::stcToCBuffer(OutBuffer *buf, int stc)
+{
+    struct SCstring
+    {
+	int stc;
+	enum TOK tok;
+    };
+
+    static SCstring table[] =
+    {
+	{ STCauto,         TOKauto },
+	{ STCscope,        TOKscope },
+	{ STCstatic,       TOKstatic },
+	{ STCextern,       TOKextern },
+	{ STCconst,        TOKconst },
+	{ STCimmutable,    TOKimmutable },
+	{ STCshared,       TOKshared },
+	{ STCfinal,        TOKfinal },
+	{ STCabstract,     TOKabstract },
+	{ STCsynchronized, TOKsynchronized },
+	{ STCdeprecated,   TOKdeprecated },
+	{ STCoverride,     TOKoverride },
+	{ STCnothrow,      TOKnothrow },
+	{ STCpure,         TOKpure },
+	{ STCref,          TOKref },
+	{ STCtls,          TOKtls },
+	{ STCgshared,      TOKgshared },
+	{ STClazy,         TOKlazy },
+	{ STCalias,        TOKalias },
+	{ STCout,          TOKout },
+	{ STCin,           TOKin },
+    };
+
+    for (int i = 0; i < sizeof(table)/sizeof(table[0]); i++)
+    {
+	if (stc & table[i].stc)
+	{
+	    buf->writestring(Token::toChars(table[i].tok));
+	    buf->writeByte(' ');
+	}
+    }
+}
+
+void StorageClassDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    stcToCBuffer(buf, stc);
+    AttribDeclaration::toCBuffer(buf, hgs);
+}
+
+/********************************* LinkDeclaration ****************************/
+
+LinkDeclaration::LinkDeclaration(enum LINK p, Array *decl)
+	: AttribDeclaration(decl)
+{
+    //printf("LinkDeclaration(linkage = %d, decl = %p)\n", p, decl);
+    linkage = p;
+}
+
+Dsymbol *LinkDeclaration::syntaxCopy(Dsymbol *s)
+{
+    LinkDeclaration *ld;
+
+    assert(!s);
+    ld = new LinkDeclaration(linkage, Dsymbol::arraySyntaxCopy(decl));
+    return ld;
+}
+
+void LinkDeclaration::semantic(Scope *sc)
+{
+    //printf("LinkDeclaration::semantic(linkage = %d, decl = %p)\n", linkage, decl);
+    if (decl)
+    {	enum LINK linkage_save = sc->linkage;
+
+	sc->linkage = linkage;
+	for (unsigned i = 0; i < decl->dim; i++)
+	{
+	    Dsymbol *s = (Dsymbol *)decl->data[i];
+
+	    s->semantic(sc);
+	}
+	sc->linkage = linkage_save;
+    }
+    else
+    {
+	sc->linkage = linkage;
+    }
+}
+
+void LinkDeclaration::semantic3(Scope *sc)
+{
+    //printf("LinkDeclaration::semantic3(linkage = %d, decl = %p)\n", linkage, decl);
+    if (decl)
+    {	enum LINK linkage_save = sc->linkage;
+
+	sc->linkage = linkage;
+	for (unsigned i = 0; i < decl->dim; i++)
+	{
+	    Dsymbol *s = (Dsymbol *)decl->data[i];
+
+	    s->semantic3(sc);
+	}
+	sc->linkage = linkage_save;
+    }
+    else
+    {
+	sc->linkage = linkage;
+    }
+}
+
+void LinkDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{   const char *p;
+
+    switch (linkage)
+    {
+	case LINKd:		p = "D";		break;
+	case LINKc:		p = "C";		break;
+	case LINKcpp:		p = "C++";		break;
+	case LINKwindows:	p = "Windows";		break;
+	case LINKpascal:	p = "Pascal";		break;
+
+#if IN_LLVM
+    case LINKintrinsic: p = "Intrinsic"; break;
+#endif
+	default:
+	    assert(0);
+	    break;
+    }
+    buf->writestring("extern (");
+    buf->writestring(p);
+    buf->writestring(") ");
+    AttribDeclaration::toCBuffer(buf, hgs);
+}
+
+char *LinkDeclaration::toChars()
+{
+    return (char *)"extern ()";
+}
+
+/********************************* ProtDeclaration ****************************/
+
+ProtDeclaration::ProtDeclaration(enum PROT p, Array *decl)
+	: AttribDeclaration(decl)
+{
+    protection = p;
+    //printf("decl = %p\n", decl);
+}
+
+Dsymbol *ProtDeclaration::syntaxCopy(Dsymbol *s)
+{
+    ProtDeclaration *pd;
+
+    assert(!s);
+    pd = new ProtDeclaration(protection, Dsymbol::arraySyntaxCopy(decl));
+    return pd;
+}
+
+void ProtDeclaration::semantic(Scope *sc)
+{
+    if (decl)
+    {	enum PROT protection_save = sc->protection;
+	int explicitProtection_save = sc->explicitProtection;
+
+	sc->protection = protection;
+	sc->explicitProtection = 1;
+	for (unsigned i = 0; i < decl->dim; i++)
+	{
+	    Dsymbol *s = (Dsymbol *)decl->data[i];
+
+	    s->semantic(sc);
+	}
+	sc->protection = protection_save;
+	sc->explicitProtection = explicitProtection_save;
+    }
+    else
+    {	sc->protection = protection;
+	sc->explicitProtection = 1;
+    }
+}
+
+void ProtDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{   const char *p;
+
+    switch (protection)
+    {
+	case PROTprivate:	p = "private";		break;
+	case PROTpackage:	p = "package";		break;
+	case PROTprotected:	p = "protected";	break;
+	case PROTpublic:	p = "public";		break;
+	case PROTexport:	p = "export";		break;
+	default:
+	    assert(0);
+	    break;
+    }
+    buf->writestring(p);
+    AttribDeclaration::toCBuffer(buf, hgs);
+}
+
+/********************************* AlignDeclaration ****************************/
+
+AlignDeclaration::AlignDeclaration(Loc loc, unsigned sa, Array *decl)
+	: AttribDeclaration(decl)
+{
+    this->loc = loc;
+    salign = sa;
+}
+
+Dsymbol *AlignDeclaration::syntaxCopy(Dsymbol *s)
+{
+    AlignDeclaration *ad;
+
+    assert(!s);
+    ad = new AlignDeclaration(loc, salign, Dsymbol::arraySyntaxCopy(decl));
+    return ad;
+}
+
+void AlignDeclaration::semantic(Scope *sc)
+{
+// LDC
+// we only support packed structs, as from the spec: align(1) struct Packed { ... }
+// other alignments are simply ignored. my tests show this is what llvm-gcc does too ...
+
+    //printf("\tAlignDeclaration::semantic '%s'\n",toChars());
+    if (decl)
+    {	unsigned salign_save = sc->structalign;
+#if IN_DMD
+	sc->structalign = salign;
+#endif
+	for (unsigned i = 0; i < decl->dim; i++)
+	{
+	    Dsymbol *s = (Dsymbol *)decl->data[i];
+
+        if (s->isStructDeclaration() && salign == 1)
+        {
+            sc->structalign = salign;
+            s->semantic(sc);
+            sc->structalign = salign_save;
+        }
+        else
+        {
+            s->semantic(sc);
+        }
+	}
+	sc->structalign = salign_save;
+    }
+    else
+    assert(0 && "what kind of align use triggers this?");
+}
+
+
+void AlignDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    buf->printf("align (%d)", salign);
+    AttribDeclaration::toCBuffer(buf, hgs);
+}
+
+/********************************* AnonDeclaration ****************************/
+
+AnonDeclaration::AnonDeclaration(Loc loc, int isunion, Array *decl)
+	: AttribDeclaration(decl)
+{
+    this->loc = loc;
+    this->isunion = isunion;
+    this->scope = NULL;
+    this->sem = 0;
+}
+
+Dsymbol *AnonDeclaration::syntaxCopy(Dsymbol *s)
+{
+    AnonDeclaration *ad;
+
+    assert(!s);
+    ad = new AnonDeclaration(loc, isunion, Dsymbol::arraySyntaxCopy(decl));
+    return ad;
+}
+
+void AnonDeclaration::semantic(Scope *sc)
+{
+    //printf("\tAnonDeclaration::semantic %s %p\n", isunion ? "union" : "struct", this);
+
+    Scope *scx = NULL;
+    if (scope)
+    {   sc = scope;
+	scx = scope;
+	scope = NULL;
+    }
+
+    assert(sc->parent);
+
+    Dsymbol *parent = sc->parent->pastMixin();
+    AggregateDeclaration *ad = parent->isAggregateDeclaration();
+
+    if (!ad || (!ad->isStructDeclaration() && !ad->isClassDeclaration()))
+    {
+	error("can only be a part of an aggregate");
+	return;
+    }
+
+    if (decl)
+    {
+	AnonymousAggregateDeclaration aad;
+	int adisunion;
+
+	if (sc->anonAgg)
+	{   ad = sc->anonAgg;
+	    adisunion = sc->inunion;
+	}
+	else
+	    adisunion = ad->isUnionDeclaration() != NULL;
+
+//	printf("\tsc->anonAgg = %p\n", sc->anonAgg);
+//	printf("\tad  = %p\n", ad);
+//	printf("\taad = %p\n", &aad);
+
+	sc = sc->push();
+	sc->anonAgg = &aad;
+	sc->stc &= ~(STCauto | STCscope | STCstatic | STCtls | STCgshared);
+	sc->inunion = isunion;
+	sc->offset = 0;
+	sc->flags = 0;
+	aad.structalign = sc->structalign;
+	aad.parent = ad;
+
+	for (unsigned i = 0; i < decl->dim; i++)
+	{
+	    Dsymbol *s = (Dsymbol *)decl->data[i];
+
+	    s->semantic(sc);
+	    if (isunion)
+		sc->offset = 0;
+	    if (aad.sizeok == 2)
+	    {
+		break;
+	    }
+	}
+	sc = sc->pop();
+
+	// If failed due to forward references, unwind and try again later
+	if (aad.sizeok == 2)
+	{
+	    ad->sizeok = 2;
+	    //printf("\tsetting ad->sizeok %p to 2\n", ad);
+	    if (!sc->anonAgg)
+	    {
+		scope = scx ? scx : new Scope(*sc);
+		scope->setNoFree();
+		scope->module->addDeferredSemantic(this);
+	    }
+	    //printf("\tforward reference %p\n", this);
+	    return;
+	}
+	if (sem == 0)
+	{   Module::dprogress++;
+	    sem = 1;
+	    //printf("\tcompleted %p\n", this);
+	}
+	else
+	    ;//printf("\talready completed %p\n", this);
+
+	// 0 sized structs are set to 1 byte
+	if (aad.structsize == 0)
+	{
+	    aad.structsize = 1;
+	    aad.alignsize = 1;
+	}
+
+	// Align size of anonymous aggregate
+//printf("aad.structalign = %d, aad.alignsize = %d, sc->offset = %d\n", aad.structalign, aad.alignsize, sc->offset);
+	ad->alignmember(aad.structalign, aad.alignsize, &sc->offset);
+	//ad->structsize = sc->offset;
+//printf("sc->offset = %d\n", sc->offset);
+
+	// Add members of aad to ad
+	//printf("\tadding members of aad to '%s'\n", ad->toChars());
+	for (unsigned i = 0; i < aad.fields.dim; i++)
+	{
+	    VarDeclaration *v = (VarDeclaration *)aad.fields.data[i];
+
+#if IN_LLVM
+        v->offset2 = sc->offset;
+#endif
+	    v->offset += sc->offset;
+
+#if IN_LLVM
+        if (!v->anonDecl)
+            v->anonDecl = this;
+#endif
+	    ad->fields.push(v);
+	}
+
+	// Add size of aad to ad
+	if (adisunion)
+	{
+	    if (aad.structsize > ad->structsize)
+		ad->structsize = aad.structsize;
+	    sc->offset = 0;
+	}
+	else
+	{
+	    ad->structsize = sc->offset + aad.structsize;
+	    sc->offset = ad->structsize;
+	}
+
+	if (ad->alignsize < aad.alignsize)
+	    ad->alignsize = aad.alignsize;
+    }
+}
+
+
+void AnonDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    buf->printf(isunion ? "union" : "struct");
+    buf->writestring("\n{\n");
+    if (decl)
+    {
+	for (unsigned i = 0; i < decl->dim; i++)
+	{
+	    Dsymbol *s = (Dsymbol *)decl->data[i];
+
+	    //buf->writestring("    ");
+	    s->toCBuffer(buf, hgs);
+	}
+    }
+    buf->writestring("}\n");
+}
+
+const char *AnonDeclaration::kind()
+{
+    return (isunion ? "anonymous union" : "anonymous struct");
+}
+
+/********************************* PragmaDeclaration ****************************/
+
+static bool parseStringExp(Expression* e, std::string& res)
+{
+    StringExp *s = NULL;
+
+    e = e->optimize(WANTvalue);
+    if (e->op == TOKstring && (s = (StringExp *)e))
+    {
+        char* str = (char*)s->string;
+        res = str;
+        return true;
+    }
+    return false;
+}
+
+PragmaDeclaration::PragmaDeclaration(Loc loc, Identifier *ident, Expressions *args, Array *decl)
+	: AttribDeclaration(decl)
+{
+    this->loc = loc;
+    this->ident = ident;
+    this->args = args;
+}
+
+Dsymbol *PragmaDeclaration::syntaxCopy(Dsymbol *s)
+{
+    //printf("PragmaDeclaration::syntaxCopy(%s)\n", toChars());
+    PragmaDeclaration *pd;
+
+    assert(!s);
+    pd = new PragmaDeclaration(loc, ident,
+	Expression::arraySyntaxCopy(args), Dsymbol::arraySyntaxCopy(decl));
+    return pd;
+}
+
+void PragmaDeclaration::semantic(Scope *sc)
+{   // Should be merged with PragmaStatement
+
+#if IN_LLVM
+    int llvm_internal = 0;
+    std::string arg1str;
+#endif
+
+    //printf("\tPragmaDeclaration::semantic '%s'\n",toChars());
+    if (ident == Id::msg)
+    {
+	if (args)
+	{
+	    for (size_t i = 0; i < args->dim; i++)
+	    {
+		Expression *e = (Expression *)args->data[i];
+
+		e = e->semantic(sc);
+		e = e->optimize(WANTvalue | WANTinterpret);
+		if (e->op == TOKstring)
+		{
+		    StringExp *se = (StringExp *)e;
+		    fprintf(stdmsg, "%.*s", (int)se->len, (char*)se->string);
+		}
+		else
+		    error("string expected for message, not '%s'", e->toChars());
+	    }
+	    fprintf(stdmsg, "\n");
+	}
+	goto Lnodecl;
+    }
+    else if (ident == Id::lib)
+    {
+	if (!args || args->dim != 1)
+	    error("string expected for library name");
+	else
+	{
+	    Expression *e = (Expression *)args->data[0];
+
+	    e = e->semantic(sc);
+	    e = e->optimize(WANTvalue | WANTinterpret);
+	    args->data[0] = (void *)e;
+	    if (e->op != TOKstring)
+		error("string expected for library name, not '%s'", e->toChars());
+	    else if (global.params.verbose)
+	    {
+		StringExp *se = (StringExp *)e;
+		char *name = (char *)mem.malloc(se->len + 1);
+		memcpy(name, se->string, se->len);
+		name[se->len] = 0;
+		printf("library   %s\n", name);
+		mem.free(name);
+	    }
+	}
+	goto Lnodecl;
+    }
+#if IN_GCC
+    else if (ident == Id::GNU_asm)
+    {
+	if (! args || args->dim != 2)
+	    error("identifier and string expected for asm name");
+	else
+	{
+	    Expression *e;
+	    Declaration *d = NULL;
+	    StringExp *s = NULL;
+
+	    e = (Expression *)args->data[0];
+	    e = e->semantic(sc);
+	    if (e->op == TOKvar)
+	    {
+		d = ((VarExp *)e)->var;
+		if (! d->isFuncDeclaration() && ! d->isVarDeclaration())
+		    d = NULL;
+	    }
+	    if (!d)
+		error("first argument of GNU_asm must be a function or variable declaration");
+
+	    e = (Expression *)args->data[1];
+	    e = e->semantic(sc);
+	    e = e->optimize(WANTvalue);
+	    if (e->op == TOKstring && ((StringExp *)e)->sz == 1)
+		s = ((StringExp *)e);
+	    else
+		error("second argument of GNU_asm must be a char string");
+
+	    if (d && s)
+		d->c_ident = Lexer::idPool((char*) s->string);
+	}
+	goto Lnodecl;
+    }
+#endif
+    else if (ident == Id::startaddress)
+    {
+	if (!args || args->dim != 1)
+	    error("function name expected for start address");
+	else
+	{
+	    Expression *e = (Expression *)args->data[0];
+	    e = e->semantic(sc);
+	    e = e->optimize(WANTvalue | WANTinterpret);
+	    args->data[0] = (void *)e;
+	    Dsymbol *sa = getDsymbol(e);
+	    if (!sa || !sa->isFuncDeclaration())
+		error("function name expected for start address, not '%s'", e->toChars());
+	}
+	goto Lnodecl;
+    }
+
+// LDC
+#if IN_LLVM
+
+    // pragma(intrinsic, "string") { funcdecl(s) }
+    else if (ident == Id::intrinsic)
+    {
+        Expression* expr = (Expression *)args->data[0];
+        expr = expr->semantic(sc);
+        if (!args || args->dim != 1 || !parseStringExp(expr, arg1str))
+        {
+             error("requires exactly 1 string literal parameter");
+             fatal();
+        }
+        llvm_internal = LLVMintrinsic;
+    }
+
+    // pragma(notypeinfo) { typedecl(s) }
+    else if (ident == Id::no_typeinfo)
+    {
+        if (args && args->dim > 0)
+        {
+             error("takes no parameters");
+             fatal();
+        }
+        llvm_internal = LLVMno_typeinfo;
+    }
+
+    // pragma(nomoduleinfo) ;
+    else if (ident == Id::no_moduleinfo)
+    {
+        if (args && args->dim > 0)
+        {
+             error("takes no parameters");
+             fatal();
+        }
+        llvm_internal = LLVMno_moduleinfo;
+    }
+
+    // pragma(alloca) { funcdecl(s) }
+    else if (ident == Id::Alloca)
+    {
+        if (args && args->dim > 0)
+        {
+             error("takes no parameters");
+             fatal();
+        }
+        llvm_internal = LLVMalloca;
+    }
+
+    // pragma(va_start) { templdecl(s) }
+    else if (ident == Id::vastart)
+    {
+        if (args && args->dim > 0)
+        {
+             error("takes no parameters");
+             fatal();
+        }
+        llvm_internal = LLVMva_start;
+    }
+
+    // pragma(va_copy) { funcdecl(s) }
+    else if (ident == Id::vacopy)
+    {
+        if (args && args->dim > 0)
+        {
+             error("takes no parameters");
+             fatal();
+        }
+        llvm_internal = LLVMva_copy;
+    }
+
+    // pragma(va_end) { funcdecl(s) }
+    else if (ident == Id::vaend)
+    {
+        if (args && args->dim > 0)
+        {
+             error("takes no parameters");
+             fatal();
+        }
+        llvm_internal = LLVMva_end;
+    }
+
+    // pragma(va_arg) { templdecl(s) }
+    else if (ident == Id::vaarg)
+    {
+        if (args && args->dim > 0)
+        {
+             error("takes no parameters");
+             fatal();
+        }
+        llvm_internal = LLVMva_arg;
+    }
+    
+    // pragma(ldc, "string") { templdecl(s) }
+    else if (ident == Id::ldc)
+    {
+        Expression* expr = (Expression *)args->data[0];
+        expr = expr->semantic(sc);
+        if (!args || args->dim != 1 || !parseStringExp(expr, arg1str))
+        {
+             error("requires exactly 1 string literal parameter");
+             fatal();
+        }
+        else if (arg1str == "verbose")
+        {
+            sc->module->llvmForceLogging = true;
+        }
+        else
+        {
+            error("command '%s' invalid", expr->toChars());
+            fatal();
+        }
+    }
+
+    // pragma(llvm_inline_asm) { templdecl(s) }
+    else if (ident == Id::llvm_inline_asm)
+    {
+        if (args && args->dim > 0)
+        {
+             error("takes no parameters");
+             fatal();
+        }
+        llvm_internal = LLVMinline_asm;
+    }
+
+#endif // LDC
+
+    else if (ignoreUnsupportedPragmas)
+    {
+	if (global.params.verbose)
+	{
+	    /* Print unrecognized pragmas
+	     */
+	    printf("pragma    %s", ident->toChars());
+	    if (args)
+	    {
+		for (size_t i = 0; i < args->dim; i++)
+		{
+                    // ignore errors in ignored pragmas.
+                    global.gag++;
+                    unsigned errors_save = global.errors;
+
+		    Expression *e = (Expression *)args->data[i];
+		    e = e->semantic(sc);
+		    e = e->optimize(WANTvalue | WANTinterpret);
+		    if (i == 0)
+			printf(" (");
+		    else
+			printf(",");
+		    printf("%s", e->toChars());
+
+                    // restore error state.
+                    global.gag--;
+                    global.errors = errors_save;
+		}
+		if (args->dim)
+		    printf(")");
+	    }
+	    printf("\n");
+	}
+    }
+    else
+	error("unrecognized pragma(%s)", ident->toChars());
+
+    if (decl)
+    {
+	for (unsigned i = 0; i < decl->dim; i++)
+	{
+	    Dsymbol *s = (Dsymbol *)decl->data[i];
+
+	    s->semantic(sc);
+
+// LDC
+#if IN_LLVM
+
+        if (llvm_internal)
+        {
+        if (s->llvmInternal)
+        {
+            error("multiple LDC specific pragmas not allowed not affect the same declaration ('%s' at '%s')", s->toChars(), s->loc.toChars());
+            fatal();
+        }
+        switch(llvm_internal)
+        {
+        case LLVMintrinsic:
+            if (FuncDeclaration* fd = s->isFuncDeclaration())
+            {
+                fd->llvmInternal = llvm_internal;
+                fd->intrinsicName = arg1str;
+                fd->linkage = LINKintrinsic;
+                ((TypeFunction*)fd->type)->linkage = LINKintrinsic;
+            }
+            else if (TemplateDeclaration* td = s->isTemplateDeclaration())
+            {
+                td->llvmInternal = llvm_internal;
+                td->intrinsicName = arg1str;
+            }
+            else
+            {
+                error("only allowed on function declarations");
+                fatal();
+            }
+            break;
+
+        case LLVMva_start:
+        case LLVMva_arg:
+            if (TemplateDeclaration* td = s->isTemplateDeclaration())
+            {
+                if (td->parameters->dim != 1)
+                {
+                    error("the '%s' pragma template must have exactly one template parameter", ident->toChars());
+                    fatal();
+                }
+                else if (!td->onemember)
+                {
+                    error("the '%s' pragma template must have exactly one member", ident->toChars());
+                    fatal();
+                }
+                else if (td->overnext || td->overroot)
+                {
+                    error("the '%s' pragma template must not be overloaded", ident->toChars());
+                    fatal();
+                }
+                td->llvmInternal = llvm_internal;
+            }
+            else
+            {
+                error("the '%s' pragma is only allowed on template declarations", ident->toChars());
+                fatal();
+            }
+            break;
+
+        case LLVMva_copy:
+        case LLVMva_end:
+            if (FuncDeclaration* fd = s->isFuncDeclaration())
+            {
+                fd->llvmInternal = llvm_internal;
+            }
+            else
+            {
+                error("the '%s' pragma is only allowed on function declarations", ident->toChars());
+                fatal();
+            }
+            break;
+
+        case LLVMno_typeinfo:
+            s->llvmInternal = llvm_internal;
+            break;
+
+        case LLVMalloca:
+            if (FuncDeclaration* fd = s->isFuncDeclaration())
+            {
+                fd->llvmInternal = llvm_internal;
+            }
+            else
+            {
+                error("the '%s' pragma must only be used on function declarations of type 'void* function(uint nbytes)'", ident->toChars());
+                fatal();
+            }
+            break;
+
+        case LLVMinline_asm:
+            if (TemplateDeclaration* td = s->isTemplateDeclaration())
+            {
+                if (td->parameters->dim > 1)
+                {
+                    error("the '%s' pragma template must have exactly zero or one template parameters", ident->toChars());
+                    fatal();
+                }
+                else if (!td->onemember)
+                {
+                    error("the '%s' pragma template must have exactly one member", ident->toChars());
+                    fatal();
+                }
+                td->llvmInternal = llvm_internal;
+            }
+            else
+            {
+                error("the '%s' pragma is only allowed on template declarations", ident->toChars());
+                fatal();
+            }
+            break;
+
+        default:
+            warning("the LDC specific pragma '%s' is not yet implemented, ignoring", ident->toChars());
+        }
+        }
+
+#endif // LDC
+
+    }
+    }
+    return;
+
+Lnodecl:
+    if (decl)
+	error("pragma is missing closing ';'");
+}
+
+int PragmaDeclaration::oneMember(Dsymbol **ps)
+{
+    *ps = NULL;
+    return TRUE;
+}
+
+const char *PragmaDeclaration::kind()
+{
+    return "pragma";
+}
+
+#if IN_DMD
+void PragmaDeclaration::toObjFile(int multiobj)
+{
+    if (ident == Id::lib)
+    {
+	assert(args && args->dim == 1);
+
+	Expression *e = (Expression *)args->data[0];
+
+	assert(e->op == TOKstring);
+
+	StringExp *se = (StringExp *)e;
+	char *name = (char *)mem.malloc(se->len + 1);
+	memcpy(name, se->string, se->len);
+	name[se->len] = 0;
+#if OMFOBJ
+	/* The OMF format allows library names to be inserted
+	 * into the object file. The linker will then automatically
+	 * search that library, too.
+	 */
+	obj_includelib(name);
+#elif ELFOBJ || MACHOBJ
+	/* The format does not allow embedded library names,
+	 * so instead append the library name to the list to be passed
+	 * to the linker.
+	 */
+	global.params.libfiles->push((void *) name);
+#else
+	error("pragma lib not supported");
+#endif
+    }
+#if DMDV2
+    else if (ident == Id::startaddress)
+    {
+	assert(args && args->dim == 1);
+	Expression *e = (Expression *)args->data[0];
+	Dsymbol *sa = getDsymbol(e);
+	FuncDeclaration *f = sa->isFuncDeclaration();
+	assert(f);
+	Symbol *s = f->toSymbol();
+	obj_startaddress(s);
+    }
+#endif
+    AttribDeclaration::toObjFile(multiobj);
+}
+#endif
+
+void PragmaDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    buf->printf("pragma (%s", ident->toChars());
+    if (args && args->dim)
+    {
+        buf->writestring(", ");
+        argsToCBuffer(buf, args, hgs);
+    }
+    buf->writeByte(')');
+    AttribDeclaration::toCBuffer(buf, hgs);
+}
+
+
+/********************************* ConditionalDeclaration ****************************/
+
+ConditionalDeclaration::ConditionalDeclaration(Condition *condition, Array *decl, Array *elsedecl)
+	: AttribDeclaration(decl)
+{
+    //printf("ConditionalDeclaration::ConditionalDeclaration()\n");
+    this->condition = condition;
+    this->elsedecl = elsedecl;
+}
+
+Dsymbol *ConditionalDeclaration::syntaxCopy(Dsymbol *s)
+{
+    ConditionalDeclaration *dd;
+
+    assert(!s);
+    dd = new ConditionalDeclaration(condition->syntaxCopy(),
+	Dsymbol::arraySyntaxCopy(decl),
+	Dsymbol::arraySyntaxCopy(elsedecl));
+    return dd;
+}
+
+
+int ConditionalDeclaration::oneMember(Dsymbol **ps)
+{
+    //printf("ConditionalDeclaration::oneMember(), inc = %d\n", condition->inc);
+    if (condition->inc)
+    {
+	Array *d = condition->include(NULL, NULL) ? decl : elsedecl;
+	return Dsymbol::oneMembers(d, ps);
+    }
+    *ps = NULL;
+    return TRUE;
+}
+
+void ConditionalDeclaration::emitComment(Scope *sc)
+{
+    //printf("ConditionalDeclaration::emitComment(sc = %p)\n", sc);
+    if (condition->inc)
+    {
+	AttribDeclaration::emitComment(sc);
+    }
+    else if (sc->docbuf)
+    {
+	/* If generating doc comment, be careful because if we're inside
+	 * a template, then include(NULL, NULL) will fail.
+	 */
+	Array *d = decl ? decl : elsedecl;
+	for (unsigned i = 0; i < d->dim; i++)
+	{   Dsymbol *s = (Dsymbol *)d->data[i];
+	    s->emitComment(sc);
+	}
+    }
+}
+
+// Decide if 'then' or 'else' code should be included
+
+Array *ConditionalDeclaration::include(Scope *sc, ScopeDsymbol *sd)
+{
+    //printf("ConditionalDeclaration::include()\n");
+    assert(condition);
+    return condition->include(sc, sd) ? decl : elsedecl;
+}
+
+
+void ConditionalDeclaration::addComment(unsigned char *comment)
+{
+    /* Because addComment is called by the parser, if we called
+     * include() it would define a version before it was used.
+     * But it's no problem to drill down to both decl and elsedecl,
+     * so that's the workaround.
+     */
+
+    if (comment)
+    {
+	Array *d = decl;
+
+	for (int j = 0; j < 2; j++)
+	{
+	    if (d)
+	    {
+		for (unsigned i = 0; i < d->dim; i++)
+		{   Dsymbol *s;
+
+		    s = (Dsymbol *)d->data[i];
+		    //printf("ConditionalDeclaration::addComment %s\n", s->toChars());
+		    s->addComment(comment);
+		}
+	    }
+	    d = elsedecl;
+	}
+    }
+}
+
+void ConditionalDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    condition->toCBuffer(buf, hgs);
+    if (decl || elsedecl)
+    {
+	buf->writenl();
+	buf->writeByte('{');
+	buf->writenl();
+	if (decl)
+	{
+	    for (unsigned i = 0; i < decl->dim; i++)
+	    {
+		Dsymbol *s = (Dsymbol *)decl->data[i];
+
+		buf->writestring("    ");
+		s->toCBuffer(buf, hgs);
+	    }
+	}
+	buf->writeByte('}');
+	if (elsedecl)
+	{
+	    buf->writenl();
+	    buf->writestring("else");
+	    buf->writenl();
+	    buf->writeByte('{');
+	    buf->writenl();
+	    for (unsigned i = 0; i < elsedecl->dim; i++)
+	    {
+		Dsymbol *s = (Dsymbol *)elsedecl->data[i];
+
+		buf->writestring("    ");
+		s->toCBuffer(buf, hgs);
+	    }
+	    buf->writeByte('}');
+	}
+    }
+    else
+	buf->writeByte(':');
+    buf->writenl();
+}
+
+/***************************** StaticIfDeclaration ****************************/
+
+StaticIfDeclaration::StaticIfDeclaration(Condition *condition,
+	Array *decl, Array *elsedecl)
+	: ConditionalDeclaration(condition, decl, elsedecl)
+{
+    //printf("StaticIfDeclaration::StaticIfDeclaration()\n");
+    sd = NULL;
+    addisdone = 0;
+}
+
+
+Dsymbol *StaticIfDeclaration::syntaxCopy(Dsymbol *s)
+{
+    StaticIfDeclaration *dd;
+
+    assert(!s);
+    dd = new StaticIfDeclaration(condition->syntaxCopy(),
+	Dsymbol::arraySyntaxCopy(decl),
+	Dsymbol::arraySyntaxCopy(elsedecl));
+    return dd;
+}
+
+
+int StaticIfDeclaration::addMember(Scope *sc, ScopeDsymbol *sd, int memnum)
+{
+    //printf("StaticIfDeclaration::addMember() '%s'\n",toChars());
+    /* This is deferred until semantic(), so that
+     * expressions in the condition can refer to declarations
+     * in the same scope, such as:
+     *
+     * template Foo(int i)
+     * {
+     *     const int j = i + 1;
+     *     static if (j == 3)
+     *         const int k;
+     * }
+     */
+    this->sd = sd;
+    int m = 0;
+
+    if (memnum == 0)
+    {	m = AttribDeclaration::addMember(sc, sd, memnum);
+	addisdone = 1;
+    }
+    return m;
+}
+
+
+void StaticIfDeclaration::semantic(Scope *sc)
+{
+    Array *d = include(sc, sd);
+
+    //printf("\tStaticIfDeclaration::semantic '%s', d = %p\n",toChars(), d);
+    if (d)
+    {
+	if (!addisdone)
+	{   AttribDeclaration::addMember(sc, sd, 1);
+	    addisdone = 1;
+	}
+
+	for (unsigned i = 0; i < d->dim; i++)
+	{
+	    Dsymbol *s = (Dsymbol *)d->data[i];
+
+	    s->semantic(sc);
+	}
+    }
+}
+
+const char *StaticIfDeclaration::kind()
+{
+    return "static if";
+}
+
+
+/***************************** CompileDeclaration *****************************/
+
+CompileDeclaration::CompileDeclaration(Loc loc, Expression *exp)
+    : AttribDeclaration(NULL)
+{
+    //printf("CompileDeclaration(loc = %d)\n", loc.linnum);
+    this->loc = loc;
+    this->exp = exp;
+    this->sd = NULL;
+    this->compiled = 0;
+}
+
+Dsymbol *CompileDeclaration::syntaxCopy(Dsymbol *s)
+{
+    //printf("CompileDeclaration::syntaxCopy('%s')\n", toChars());
+    CompileDeclaration *sc = new CompileDeclaration(loc, exp->syntaxCopy());
+    return sc;
+}
+
+int CompileDeclaration::addMember(Scope *sc, ScopeDsymbol *sd, int memnum)
+{
+    //printf("CompileDeclaration::addMember(sc = %p, memnum = %d)\n", sc, memnum);
+    this->sd = sd;
+    if (memnum == 0)
+    {	/* No members yet, so parse the mixin now
+	 */
+	compileIt(sc);
+	memnum |= AttribDeclaration::addMember(sc, sd, memnum);
+	compiled = 1;
+    }
+    return memnum;
+}
+
+void CompileDeclaration::compileIt(Scope *sc)
+{
+    //printf("CompileDeclaration::compileIt(loc = %d)\n", loc.linnum);
+    exp = exp->semantic(sc);
+    exp = resolveProperties(sc, exp);
+    exp = exp->optimize(WANTvalue | WANTinterpret);
+    if (exp->op != TOKstring)
+    {	exp->error("argument to mixin must be a string, not (%s)", exp->toChars());
+    }
+    else
+    {
+	StringExp *se = (StringExp *)exp;
+	se = se->toUTF8(sc);
+	Parser p(sc->module, (unsigned char *)se->string, se->len, 0);
+	p.loc = loc;
+	p.nextToken();
+	decl = p.parseDeclDefs(0);
+	if (p.token.value != TOKeof)
+	    exp->error("incomplete mixin declaration (%s)", se->toChars());
+    }
+}
+
+void CompileDeclaration::semantic(Scope *sc)
+{
+    //printf("CompileDeclaration::semantic()\n");
+
+    if (!compiled)
+    {
+	compileIt(sc);
+	AttribDeclaration::addMember(sc, sd, 0);
+	compiled = 1;
+    }
+    AttribDeclaration::semantic(sc);
+}
+
+void CompileDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    buf->writestring("mixin(");
+    exp->toCBuffer(buf, hgs);
+    buf->writestring(");");
+    buf->writenl();
+}
--- a/dmd2/attrib.h	Mon Jun 01 01:28:18 2009 +0200
+++ b/dmd2/attrib.h	Mon Jun 01 19:02:20 2009 +0100
@@ -50,8 +50,14 @@
     void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
     AttribDeclaration *isAttribDeclaration() { return this; }
 
-    virtual void toObjFile(int multiobj);			// compile to .obj file
+#if IN_DMD
+    void toObjFile(int multiobj);			// compile to .obj file
     int cvMember(unsigned char *p);
+#endif
+
+#if IN_LLVM
+    virtual void codegen(Ir*);
+#endif
 };
 
 struct StorageClassDeclaration: AttribDeclaration
@@ -62,6 +68,8 @@
     Dsymbol *syntaxCopy(Dsymbol *s);
     void semantic(Scope *sc);
     void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+
+    static void stcToCBuffer(OutBuffer *buf, int stc);
 };
 
 struct LinkDeclaration : AttribDeclaration
@@ -107,9 +115,6 @@
     void semantic(Scope *sc);
     void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
     const char *kind();
-
-    // LDC
-    void toObjFile(int multiobj);           // compile to .obj file
 };
 
 struct PragmaDeclaration : AttribDeclaration
@@ -122,7 +127,14 @@
     int oneMember(Dsymbol **ps);
     void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
     const char *kind();
+
+#if IN_DMD
     void toObjFile(int multiobj);			// compile to .obj file
+#endif
+
+#if IN_LLVM
+    void codegen(Ir*);
+#endif
 };
 
 struct ConditionalDeclaration : AttribDeclaration
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd2/backendlicense.txt	Mon Jun 01 19:02:20 2009 +0100
@@ -0,0 +1,42 @@
+
+The Software is not generally available software. It has not undergone
+testing and may contain errors. The Software was not designed to operate
+after December 31, 1999. It may be incomplete and it may not function
+properly. No support or maintenance is provided with this Software. Do
+not install or distribute the Software if
+you are not accustomed to using or distributing experimental software.
+Do not use this software for life critical applications, or applications
+that could cause significant harm or property damage.
+
+Digital Mars licenses the Software to you on an "AS IS" basis, without
+warranty of any kind. DIGITAL MARS AND SYMANTEC HEREBY EXPRESSLY DISCLAIM
+ALL WARRANTIES AND CONDITIONS, EITHER EXPRESS OR IMPLIED, INCLUDING,
+BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OR CONDITIONS OF MERCHANTABILITY,
+NONINFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE. You are solely
+responsible for determining the appropriateness of using this Software and
+assume all risks associated with the use of this Software, including but not
+limited to the risks of program errors, damage
+to or loss of data, programs or equipment, unavailability or interruption of
+operations and third party claims. You agree to defend, indemnify and hold
+Digital Mars and Symantec, its subsidiaries, affiliates, directors, officers,
+employees and agents harmless from all claims or demands made against them
+(and any related losses, damages, expenses
+and costs) arising out of your use of the Software. DIGITAL MARS AND SYMANTEC
+WILL NOT BE LIABLE FOR ANY DIRECT DAMAGES OR FOR ANY SPECIAL, INCIDENTAL, OR
+INDIRECT DAMAGES OR FOR ANY ECONOMIC CONSEQUENTIAL DAMAGES (INCLUDING
+LOST PROFITS OR SAVINGS), EVEN IF DIGITAL MARS OR SYMANTEC HAS BEEN ADVISED
+OF THE POSSIBILITY OF SUCH DAMAGES.
+Digital Mars and Symantec will not be liable for the loss of, or damage to,
+your records or data, the records or
+data of any third party, or any damages claimed by you based on a third party
+claim.
+
+If you send any messages to Digital Mars, on either the Digital Mars
+newsgroups, the Digital Mars mailing list, or via email, you agree not
+to make any claims of intellectual
+property rights over the contents of those messages.
+
+The Software is copyrighted and comes with a single user license,
+and may not be redistributed. If you wish to obtain a redistribution license,
+please contact Digital Mars.
+
--- a/dmd2/builtin.c	Mon Jun 01 01:28:18 2009 +0200
+++ b/dmd2/builtin.c	Mon Jun 01 19:02:20 2009 +0100
@@ -1,6 +1,6 @@
 
 // Compiler implementation of the D programming language
-// Copyright (c) 1999-2007 by Digital Mars
+// Copyright (c) 1999-2009 by Digital Mars
 // All Rights Reserved
 // written by Walter Bright
 // http://www.digitalmars.com
@@ -23,12 +23,15 @@
 #include "id.h"
 #include "module.h"
 
+#if DMDV2
+
 /**********************************
- * Determine if function is a builtin one.
+ * Determine if function is a builtin one that we can
+ * evaluate at compile time.
  */
 enum BUILTIN FuncDeclaration::isBuiltin()
 {
-    static const char FeZe[] = "FeZe";	// real function(real)
+    static const char FeZe[] = "FNaNbeZe";	// pure nothrow real function(real)
 
     //printf("FuncDeclaration::isBuiltin() %s\n", toChars());
     if (builtin == BUILTINunknown)
@@ -36,10 +39,12 @@
 	builtin = BUILTINnot;
 	if (parent && parent->isModule())
 	{
+	    // If it's in the std.math package
 	    if (parent->ident == Id::math &&
 		parent->parent && parent->parent->ident == Id::std &&
 		!parent->parent->parent)
 	    {
+		//printf("deco = %s\n", type->deco);
 		if (strcmp(type->deco, FeZe) == 0)
 		{
 		    if (ident == Id::sin)
@@ -54,6 +59,13 @@
 			builtin = BUILTINfabs;
 		    //printf("builtin = %d\n", builtin);
 		}
+		// if float or double versions
+		else if (strcmp(type->deco, "FNaNbdZd") == 0 ||
+			 strcmp(type->deco, "FNaNbfZf") == 0)
+		{
+		    if (ident == Id::_sqrt)
+			builtin = BUILTINsqrt;
+		}
 	    }
 	}
     }
@@ -75,28 +87,30 @@
     {
 	case BUILTINsin:
 	    if (arg0->op == TOKfloat64)
-		e = new RealExp(0, sinl(arg0->toReal()), Type::tfloat80);
+		e = new RealExp(0, sinl(arg0->toReal()), arg0->type);
 	    break;
 
 	case BUILTINcos:
 	    if (arg0->op == TOKfloat64)
-		e = new RealExp(0, cosl(arg0->toReal()), Type::tfloat80);
+		e = new RealExp(0, cosl(arg0->toReal()), arg0->type);
 	    break;
 
 	case BUILTINtan:
 	    if (arg0->op == TOKfloat64)
-		e = new RealExp(0, tanl(arg0->toReal()), Type::tfloat80);
+		e = new RealExp(0, tanl(arg0->toReal()), arg0->type);
 	    break;
 
 	case BUILTINsqrt:
 	    if (arg0->op == TOKfloat64)
-		e = new RealExp(0, sqrtl(arg0->toReal()), Type::tfloat80);
+		e = new RealExp(0, sqrtl(arg0->toReal()), arg0->type);
 	    break;
 
 	case BUILTINfabs:
 	    if (arg0->op == TOKfloat64)
-		e = new RealExp(0, fabsl(arg0->toReal()), Type::tfloat80);
+		e = new RealExp(0, fabsl(arg0->toReal()), arg0->type);
 	    break;
     }
     return e;
 }
+
+#endif
--- a/dmd2/cast.c	Mon Jun 01 01:28:18 2009 +0200
+++ b/dmd2/cast.c	Mon Jun 01 19:02:20 2009 +0100
@@ -1,1705 +1,1779 @@
-
-// 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>
-
-#if _WIN32 || IN_GCC || IN_LLVM
-#include "mem.h"
-#else
-#include "../root/mem.h"
-#endif
-
-#include "expression.h"
-#include "mtype.h"
-#include "utf.h"
-#include "declaration.h"
-#include "aggregate.h"
-
-/* ==================== implicitCast ====================== */
-
-/**************************************
- * Do an implicit cast.
- * Issue error if it can't be done.
- */
-
-Expression *Expression::implicitCastTo(Scope *sc, Type *t)
-{
-    //printf("Expression::implicitCastTo(%s of type %s) => %s\n", toChars(), type->toChars(), t->toChars());
-
-    MATCH match = implicitConvTo(t);
-    if (match)
-    {	TY tyfrom = type->toBasetype()->ty;
-	TY tyto = t->toBasetype()->ty;
-	if (global.params.warnings &&
-	    Type::impcnvWarn[tyfrom][tyto] &&
-	    op != TOKint64)
-	{
-	    Expression *e = optimize(WANTflags | WANTvalue);
-
-	    if (e->op == TOKint64)
-		return e->implicitCastTo(sc, t);
-
-	    if (tyfrom == Tint32 &&
-		(op == TOKadd || op == TOKmin ||
-		 op == TOKand || op == TOKor || op == TOKxor)
-	       )
-	    {
-		/* This is really only a semi-kludge fix,
-		 * we really should look at the operands of op
-		 * and see if they are narrower types.
-		 * For example, b=b|b and b=b|7 and s=b+b should be allowed,
-		 * but b=b|i should be an error.
-		 */
-		;
-	    }
-	    else
-	    {
-		warning("%s: implicit conversion of expression (%s) of type %s to %s can cause loss of data",
-		    loc.toChars(), toChars(), type->toChars(), t->toChars());
-	    }
-	}
-#if DMDV2
-	if (match == MATCHconst && t == type->constOf())
-	{
-	    Expression *e = copy();
-	    e->type = t;
-	    return e;
-	}
-#endif
-	return castTo(sc, t);
-    }
-
-    Expression *e = optimize(WANTflags | WANTvalue);
-    if (e != this)
-	return e->implicitCastTo(sc, t);
-
-#if 0
-printf("ty = %d\n", type->ty);
-print();
-type->print();
-printf("to:\n");
-t->print();
-printf("%p %p type: %s to: %s\n", type->deco, t->deco, type->deco, t->deco);
-//printf("%p %p %p\n", type->nextOf()->arrayOf(), type, t);
-fflush(stdout);
-#endif
-    if (!t->deco)
-    {	/* Can happen with:
-	 *    enum E { One }
-	 *    class A
-	 *    { static void fork(EDG dg) { dg(E.One); }
-	 *	alias void delegate(E) EDG;
-	 *    }
-	 * Should eventually make it work.
-	 */
-	error("forward reference to type %s", t->toChars());
-    }
-    else if (t->reliesOnTident())
-	error("forward reference to type %s", t->reliesOnTident()->toChars());
-
-    error("cannot implicitly convert expression (%s) of type %s to %s",
-	toChars(), type->toChars(), t->toChars());
-    return castTo(sc, t);
-}
-
-/*******************************************
- * Return !=0 if we can implicitly convert this to type t.
- * Don't do the actual cast.
- */
-
-MATCH Expression::implicitConvTo(Type *t)
-{
-#if 0
-    printf("Expression::implicitConvTo(this=%s, type=%s, t=%s)\n",
-	toChars(), type->toChars(), t->toChars());
-#endif
-    //static int nest; if (++nest == 10) halt();
-    if (!type)
-    {	error("%s is not an expression", toChars());
-	type = Type::terror;
-    }
-    Expression *e = optimize(WANTvalue | WANTflags);
-    if (e->type == t)
-	return MATCHexact;
-    if (e != this)
-    {	//printf("\toptimized to %s of type %s\n", e->toChars(), e->type->toChars());
-	return e->implicitConvTo(t);
-    }
-    MATCH match = type->implicitConvTo(t);
-    if (match != MATCHnomatch)
-	return match;
-#if 0
-    Type *tb = t->toBasetype();
-    if (tb->ty == Tdelegate)
-    {	TypeDelegate *td = (TypeDelegate *)tb;
-	TypeFunction *tf = (TypeFunction *)td->nextOf();
-
-	if (!tf->varargs &&
-	    !(tf->arguments && tf->arguments->dim)
-	   )
-	{
-	    match = type->implicitConvTo(tf->nextOf());
-	    if (match)
-		return match;
-	    if (tf->nextOf()->toBasetype()->ty == Tvoid)
-		return MATCHconvert;
-	}
-    }
-#endif
-    return MATCHnomatch;
-}
-
-
-MATCH IntegerExp::implicitConvTo(Type *t)
-{
-#if 0
-    printf("IntegerExp::implicitConvTo(this=%s, type=%s, t=%s)\n",
-	toChars(), type->toChars(), t->toChars());
-#endif
-    MATCH m = type->implicitConvTo(t);
-    if (m >= MATCHconst)
-	return m;
-
-    TY ty = type->toBasetype()->ty;
-    TY toty = t->toBasetype()->ty;
-
-    if (m == MATCHnomatch && t->ty == Tenum)
-	goto Lno;
-
-    switch (ty)
-    {
-	case Tbit:
-	case Tbool:
-	    value &= 1;
-	    ty = Tint32;
-	    break;
-
-	case Tint8:
-	    value = (signed char)value;
-	    ty = Tint32;
-	    break;
-
-	case Tchar:
-	case Tuns8:
-	    value &= 0xFF;
-	    ty = Tint32;
-	    break;
-
-	case Tint16:
-	    value = (short)value;
-	    ty = Tint32;
-	    break;
-
-	case Tuns16:
-	case Twchar:
-	    value &= 0xFFFF;
-	    ty = Tint32;
-	    break;
-
-	case Tint32:
-	    value = (int)value;
-	    break;
-
-	case Tuns32:
-	case Tdchar:
-	    value &= 0xFFFFFFFF;
-	    ty = Tuns32;
-	    break;
-
-	default:
-	    break;
-    }
-
-    // Only allow conversion if no change in value
-    switch (toty)
-    {
-	case Tbit:
-	case Tbool:
-	    if ((value & 1) != value)
-		goto Lno;
-	    goto Lyes;
-
-	case Tint8:
-	    if ((signed char)value != value)
-		goto Lno;
-	    goto Lyes;
-
-	case Tchar:
-	case Tuns8:
-	    //printf("value = %llu %llu\n", (integer_t)(unsigned char)value, value);
-	    if ((unsigned char)value != value)
-		goto Lno;
-	    goto Lyes;
-
-	case Tint16:
-	    if ((short)value != value)
-		goto Lno;
-	    goto Lyes;
-
-	case Tuns16:
-	    if ((unsigned short)value != value)
-		goto Lno;
-	    goto Lyes;
-
-	case Tint32:
-	    if (ty == Tuns32)
-	    {
-	    }
-	    else if ((int)value != value)
-		goto Lno;
-	    goto Lyes;
-
-	case Tuns32:
-	    if (ty == Tint32)
-	    {
-	    }
-	    else if ((unsigned)value != value)
-		goto Lno;
-	    goto Lyes;
-
-	case Tdchar:
-	    if (value > 0x10FFFFUL)
-		goto Lno;
-	    goto Lyes;
-
-	case Twchar:
-	    if ((unsigned short)value != value)
-		goto Lno;
-	    goto Lyes;
-
-	case Tfloat32:
-	{
-	    volatile float f;
-	    if (type->isunsigned())
-	    {
-		f = (float)value;
-		if (f != value)
-		    goto Lno;
-	    }
-	    else
-	    {
-		f = (float)(long long)value;
-		if (f != (long long)value)
-		    goto Lno;
-	    }
-	    goto Lyes;
-	}
-
-	case Tfloat64:
-	{
-	    volatile double f;
-	    if (type->isunsigned())
-	    {
-		f = (double)value;
-		if (f != value)
-		    goto Lno;
-	    }
-	    else
-	    {
-		f = (double)(long long)value;
-		if (f != (long long)value)
-		    goto Lno;
-	    }
-	    goto Lyes;
-	}
-
-	case Tfloat80:
-	{
-	    volatile long double f;
-	    if (type->isunsigned())
-	    {
-		f = (long double)value;
-		if (f != value)
-		    goto Lno;
-	    }
-	    else
-	    {
-		f = (long double)(long long)value;
-		if (f != (long long)value)
-		    goto Lno;
-	    }
-	    goto Lyes;
-	}
-
-	case Tpointer:
-//printf("type = %s\n", type->toBasetype()->toChars());
-//printf("t = %s\n", t->toBasetype()->toChars());
-	    if (ty == Tpointer &&
-	        type->toBasetype()->nextOf()->ty == t->toBasetype()->nextOf()->ty)
-	    {	/* Allow things like:
-		 *	const char* P = cast(char *)3;
-		 *	char* q = P;
-		 */
-		goto Lyes;
-	    }
-	    break;
-    }
-    return Expression::implicitConvTo(t);
-
-Lyes:
-    //printf("MATCHconvert\n");
-    return MATCHconvert;
-
-Lno:
-    //printf("MATCHnomatch\n");
-    return MATCHnomatch;
-}
-
-MATCH NullExp::implicitConvTo(Type *t)
-{
-#if 0
-    printf("NullExp::implicitConvTo(this=%s, type=%s, t=%s, committed = %d)\n",
-	toChars(), type->toChars(), t->toChars(), committed);
-#endif
-    if (this->type->equals(t))
-	return MATCHexact;
-
-    /* Allow implicit conversions from invariant to mutable|const,
-     * and mutable to invariant. It works because, after all, a null
-     * doesn't actually point to anything.
-     */
-    if (t->invariantOf()->equals(type->invariantOf()))
-	return MATCHconst;
-
-    // NULL implicitly converts to any pointer type or dynamic array
-    if (type->ty == Tpointer && type->nextOf()->ty == Tvoid)
-    {
-	if (t->ty == Ttypedef)
-	    t = ((TypeTypedef *)t)->sym->basetype;
-	if (t->ty == Tpointer || t->ty == Tarray ||
-	    t->ty == Taarray  || t->ty == Tclass ||
-	    t->ty == Tdelegate)
-	    return committed ? MATCHconvert : MATCHexact;
-    }
-    return Expression::implicitConvTo(t);
-}
-
-#if DMDV2
-MATCH StructLiteralExp::implicitConvTo(Type *t)
-{
-#if 0
-    printf("StructLiteralExp::implicitConvTo(this=%s, type=%s, t=%s)\n",
-	toChars(), type->toChars(), t->toChars());
-#endif
-    MATCH m = Expression::implicitConvTo(t);
-    if (m != MATCHnomatch)
-	return m;
-    if (type->ty == t->ty && type->ty == Tstruct &&
-	((TypeStruct *)type)->sym == ((TypeStruct *)t)->sym)
-    {
-	m = MATCHconst;
-	for (int i = 0; i < elements->dim; i++)
-	{   Expression *e = (Expression *)elements->data[i];
-	    Type *te = e->type;
-	    if (t->mod == 0)
-		te = te->mutableOf();
-	    else
-	    {	assert(t->mod == MODinvariant);
-		te = te->invariantOf();
-	    }
-	    MATCH m2 = e->implicitConvTo(te);
-	    //printf("\t%s => %s, match = %d\n", e->toChars(), te->toChars(), m2);
-	    if (m2 < m)
-		m = m2;
-	}
-    }
-    return m;
-}
-#endif
-
-MATCH StringExp::implicitConvTo(Type *t)
-{   MATCH m;
-
-#if 0
-    printf("StringExp::implicitConvTo(this=%s, committed=%d, type=%s, t=%s)\n",
-	toChars(), committed, type->toChars(), t->toChars());
-#endif
-    if (!committed)
-    {
-    if (!committed && t->ty == Tpointer && t->nextOf()->ty == Tvoid)
-    {
-	return MATCHnomatch;
-    }
-    if (type->ty == Tsarray || type->ty == Tarray || type->ty == Tpointer)
-    {
-	TY tyn = type->nextOf()->ty;
-	if (tyn == Tchar || tyn == Twchar || tyn == Tdchar)
-	{   Type *tn;
-	    MATCH m;
-
-	    switch (t->ty)
-	    {
-		case Tsarray:
-		    if (type->ty == Tsarray)
-		    {
-			if (((TypeSArray *)type)->dim->toInteger() !=
-			    ((TypeSArray *)t)->dim->toInteger())
-			    return MATCHnomatch;
-			TY tynto = t->nextOf()->ty;
-			if (tynto == Tchar || tynto == Twchar || tynto == Tdchar)
-			    return MATCHexact;
-		    }
-		case Tarray:
-		case Tpointer:
-		    tn = t->nextOf();
-		    m = MATCHexact;
-		    if (type->nextOf()->mod != tn->mod)
-		    {	if (!tn->isConst())
-			    return MATCHnomatch;
-			m = MATCHconst;
-		    }
-		    switch (tn->ty)
-		    {
-			case Tchar:
-			case Twchar:
-			case Tdchar:
-			    return m;
-		    }
-		    break;
-	    }
-	}
-    }
-    }
-    return Expression::implicitConvTo(t);
-#if 0
-    m = (MATCH)type->implicitConvTo(t);
-    if (m)
-    {
-	return m;
-    }
-
-    return MATCHnomatch;
-#endif
-}
-
-MATCH ArrayLiteralExp::implicitConvTo(Type *t)
-{   MATCH result = MATCHexact;
-
-#if 0
-    printf("ArrayLiteralExp::implicitConvTo(this=%s, type=%s, t=%s)\n",
-	toChars(), type->toChars(), t->toChars());
-#endif
-    Type *typeb = type->toBasetype();
-    Type *tb = t->toBasetype();
-    if ((tb->ty == Tarray || tb->ty == Tsarray) &&
-	(typeb->ty == Tarray || typeb->ty == Tsarray))
-    {
-	if (tb->ty == Tsarray)
-	{   TypeSArray *tsa = (TypeSArray *)tb;
-	    if (elements->dim != tsa->dim->toInteger())
-		result = MATCHnomatch;
-	}
-
-	for (int i = 0; i < elements->dim; i++)
-	{   Expression *e = (Expression *)elements->data[i];
-	    MATCH m = (MATCH)e->implicitConvTo(tb->nextOf());
-	    if (m < result)
-		result = m;			// remember worst match
-	    if (result == MATCHnomatch)
-		break;				// no need to check for worse
-	}
-	return result;
-    }
-    else
-	return Expression::implicitConvTo(t);
-}
-
-MATCH AssocArrayLiteralExp::implicitConvTo(Type *t)
-{   MATCH result = MATCHexact;
-
-    Type *typeb = type->toBasetype();
-    Type *tb = t->toBasetype();
-    if (tb->ty == Taarray && typeb->ty == Taarray)
-    {
-	for (size_t i = 0; i < keys->dim; i++)
-	{   Expression *e = (Expression *)keys->data[i];
-	    MATCH m = (MATCH)e->implicitConvTo(((TypeAArray *)tb)->index);
-	    if (m < result)
-		result = m;			// remember worst match
-	    if (result == MATCHnomatch)
-		break;				// no need to check for worse
-	    e = (Expression *)values->data[i];
-	    m = (MATCH)e->implicitConvTo(tb->nextOf());
-	    if (m < result)
-		result = m;			// remember worst match
-	    if (result == MATCHnomatch)
-		break;				// no need to check for worse
-	}
-	return result;
-    }
-    else
-	return Expression::implicitConvTo(t);
-}
-
-MATCH AddrExp::implicitConvTo(Type *t)
-{
-#if 0
-    printf("AddrExp::implicitConvTo(this=%s, type=%s, t=%s)\n",
-	toChars(), type->toChars(), t->toChars());
-#endif
-    MATCH result;
-
-    result = type->implicitConvTo(t);
-    //printf("\tresult = %d\n", result);
-
-    if (result == MATCHnomatch)
-    {
-	// Look for pointers to functions where the functions are overloaded.
-
-	t = t->toBasetype();
-
-	if (e1->op == TOKoverloadset &&
-	    (t->ty == Tpointer || t->ty == Tdelegate) && t->nextOf()->ty == Tfunction)
-	{   OverExp *eo = (OverExp *)e1;
-	    FuncDeclaration *f = NULL;
-	    for (int i = 0; i < eo->vars->a.dim; i++)
-	    {   Dsymbol *s = (Dsymbol *)eo->vars->a.data[i];
-		FuncDeclaration *f2 = s->isFuncDeclaration();
-		assert(f2);
-		if (f2->overloadExactMatch(t->nextOf()))
-		{   if (f)
-			/* Error if match in more than one overload set,
-			 * even if one is a 'better' match than the other.
-			 */
-			ScopeDsymbol::multiplyDefined(loc, f, f2);
-		    else
-			f = f2;
-		    result = MATCHexact;
-		}
-	    }
-	}
-
-	if (type->ty == Tpointer && type->nextOf()->ty == Tfunction &&
-	    t->ty == Tpointer && t->nextOf()->ty == Tfunction &&
-	    e1->op == TOKvar)
-	{
-// LDC: it happens for us
-#if !IN_LLVM
-	    /* I don't think this can ever happen -
-	     * it should have been
-	     * converted to a SymOffExp.
-	     */
-	    assert(0);
-#endif
-	    VarExp *ve = (VarExp *)e1;
-	    FuncDeclaration *f = ve->var->isFuncDeclaration();
-	    if (f && f->overloadExactMatch(t->nextOf()))
-		result = MATCHexact;
-	}
-    }
-    //printf("\tresult = %d\n", result);
-    return result;
-}
-
-MATCH SymOffExp::implicitConvTo(Type *t)
-{
-#if 0
-    printf("SymOffExp::implicitConvTo(this=%s, type=%s, t=%s)\n",
-	toChars(), type->toChars(), t->toChars());
-#endif
-    MATCH result;
-
-    result = type->implicitConvTo(t);
-    //printf("\tresult = %d\n", result);
-
-    if (result == MATCHnomatch)
-    {
-	// Look for pointers to functions where the functions are overloaded.
-	FuncDeclaration *f;
-
-	t = t->toBasetype();
-	if (type->ty == Tpointer && type->nextOf()->ty == Tfunction &&
-	    (t->ty == Tpointer || t->ty == Tdelegate) && t->nextOf()->ty == Tfunction)
-	{
-	    f = var->isFuncDeclaration();
-	    if (f)
-	    {	f = f->overloadExactMatch(t->nextOf());
-		if (f)
-		{   if ((t->ty == Tdelegate && (f->needThis() || f->isNested())) ||
-			(t->ty == Tpointer && !(f->needThis() || f->isNested())))
-		    {
-			result = MATCHexact;
-		    }
-		}
-	    }
-	}
-    }
-    //printf("\tresult = %d\n", result);
-    return result;
-}
-
-MATCH DelegateExp::implicitConvTo(Type *t)
-{
-#if 0
-    printf("DelegateExp::implicitConvTo(this=%s, type=%s, t=%s)\n",
-	toChars(), type->toChars(), t->toChars());
-#endif
-    MATCH result;
-
-    result = type->implicitConvTo(t);
-
-    if (result == MATCHnomatch)
-    {
-	// Look for pointers to functions where the functions are overloaded.
-	FuncDeclaration *f;
-
-	t = t->toBasetype();
-	if (type->ty == Tdelegate && type->nextOf()->ty == Tfunction &&
-	    t->ty == Tdelegate && t->nextOf()->ty == Tfunction)
-	{
-	    if (func && func->overloadExactMatch(t->nextOf()))
-		result = MATCHexact;
-	}
-    }
-    return result;
-}
-
-MATCH CondExp::implicitConvTo(Type *t)
-{
-    MATCH m1;
-    MATCH m2;
-
-    m1 = e1->implicitConvTo(t);
-    m2 = e2->implicitConvTo(t);
-
-    // Pick the worst match
-    return (m1 < m2) ? m1 : m2;
-}
-
-
-/* ==================== castTo ====================== */
-
-/**************************************
- * Do an explicit cast.
- */
-
-Expression *Expression::castTo(Scope *sc, Type *t)
-{
-    //printf("Expression::castTo(this=%s, t=%s)\n", toChars(), t->toChars());
-#if 0
-    printf("Expression::castTo(this=%s, type=%s, t=%s)\n",
-	toChars(), type->toChars(), t->toChars());
-#endif
-    if (type == t)
-	return this;
-    Expression *e = this;
-    Type *tb = t->toBasetype();
-    Type *typeb = type->toBasetype();
-    if (tb != typeb)
-    {
-	// Do (type *) cast of (type [dim])
-	if (tb->ty == Tpointer &&
-	    typeb->ty == Tsarray
-	   )
-	{
-	    //printf("Converting [dim] to *\n");
-
-	    if (typeb->size(loc) == 0)
-		e = new NullExp(loc);
-	    else
-		e = new AddrExp(loc, e);
-	}
-#if 0
-	else if (tb->ty == Tdelegate && type->ty != Tdelegate)
-	{
-	    TypeDelegate *td = (TypeDelegate *)tb;
-	    TypeFunction *tf = (TypeFunction *)td->nextOf();
-	    return toDelegate(sc, tf->nextOf());
-	}
-#endif
-	else
-	{
-	    e = new CastExp(loc, e, tb);
-	}
-    }
-    else
-    {
-	e = e->copy();	// because of COW for assignment to e->type
-    }
-    assert(e != this);
-    e->type = t;
-    //printf("Returning: %s\n", e->toChars());
-    return e;
-}
-
-
-Expression *RealExp::castTo(Scope *sc, Type *t)
-{   Expression *e = this;
-    if (type != t)
-    {
-	if ((type->isreal() && t->isreal()) ||
-	    (type->isimaginary() && t->isimaginary())
-	   )
-	{   e = copy();
-	    e->type = t;
-	}
-	else
-	    e = Expression::castTo(sc, t);
-    }
-    return e;
-}
-
-
-Expression *ComplexExp::castTo(Scope *sc, Type *t)
-{   Expression *e = this;
-    if (type != t)
-    {
-	if (type->iscomplex() && t->iscomplex())
-	{   e = copy();
-	    e->type = t;
-	}
-	else
-	    e = Expression::castTo(sc, t);
-    }
-    return e;
-}
-
-
-Expression *NullExp::castTo(Scope *sc, Type *t)
-{   NullExp *e;
-    Type *tb;
-
-    //printf("NullExp::castTo(t = %p)\n", t);
-    if (type == t)
-    {
-	committed = 1;
-	return this;
-    }
-    e = (NullExp *)copy();
-    e->committed = 1;
-    tb = t->toBasetype();
-    e->type = type->toBasetype();
-    if (tb != e->type)
-    {
-	// NULL implicitly converts to any pointer type or dynamic array
-	if (e->type->ty == Tpointer && e->type->nextOf()->ty == Tvoid &&
-	    (tb->ty == Tpointer || tb->ty == Tarray || tb->ty == Taarray ||
-	     tb->ty == Tdelegate))
-	{
-#if 0
-	    if (tb->ty == Tdelegate)
-	    {   TypeDelegate *td = (TypeDelegate *)tb;
-		TypeFunction *tf = (TypeFunction *)td->nextOf();
-
-		if (!tf->varargs &&
-		    !(tf->arguments && tf->arguments->dim)
-		   )
-		{
-		    return Expression::castTo(sc, t);
-		}
-	    }
-#endif
-	}
-	else
-	{
-	    return e->Expression::castTo(sc, t);
-	}
-    }
-    e->type = t;
-    return e;
-}
-
-Expression *StringExp::castTo(Scope *sc, Type *t)
-{
-    /* This follows copy-on-write; any changes to 'this'
-     * will result in a copy.
-     * The this->string member is considered immutable.
-     */
-    StringExp *se;
-    Type *tb;
-    int copied = 0;
-
-    //printf("StringExp::castTo(t = %s), '%s' committed = %d\n", t->toChars(), toChars(), committed);
-
-    if (!committed && t->ty == Tpointer && t->nextOf()->ty == Tvoid)
-    {
-	error("cannot convert string literal to void*");
-    }
-
-    se = this;
-    if (!committed)
-    {   se = (StringExp *)copy();
-	se->committed = 1;
-	copied = 1;
-    }
-
-    if (type == t)
-    {
-	return se;
-    }
-
-    tb = t->toBasetype();
-    //printf("\ttype = %s\n", type->toChars());
-    if (tb->ty == Tdelegate && type->toBasetype()->ty != Tdelegate)
-	return Expression::castTo(sc, t);
-
-    Type *typeb = type->toBasetype();
-    if (typeb == tb)
-    {
-	if (!copied)
-	{   se = (StringExp *)copy();
-	    copied = 1;
-	}
-	se->type = t;
-	return se;
-    }
-
-    if (tb->ty != Tsarray && tb->ty != Tarray && tb->ty != Tpointer)
-    {	if (!copied)
-	{   se = (StringExp *)copy();
-	    copied = 1;
-	}
-	goto Lcast;
-    }
-    if (typeb->ty != Tsarray && typeb->ty != Tarray && typeb->ty != Tpointer)
-    {	if (!copied)
-	{   se = (StringExp *)copy();
-	    copied = 1;
-	}
-	goto Lcast;
-    }
-
-    if (typeb->nextOf()->size() == tb->nextOf()->size())
-    {
-	if (!copied)
-	{   se = (StringExp *)copy();
-	    copied = 1;
-	}
-	if (tb->ty == Tsarray)
-	    goto L2;	// handle possible change in static array dimension
-	se->type = t;
-	return se;
-    }
-
-    if (committed)
-	goto Lcast;
-
-#define X(tf,tt)	((tf) * 256 + (tt))
-    {
-    OutBuffer buffer;
-    size_t newlen = 0;
-    int tfty = typeb->nextOf()->toBasetype()->ty;
-    int ttty = tb->nextOf()->toBasetype()->ty;
-    switch (X(tfty, ttty))
-    {
-	case X(Tchar, Tchar):
-	case X(Twchar,Twchar):
-	case X(Tdchar,Tdchar):
-	    break;
-
-	case X(Tchar, Twchar):
-	    for (size_t u = 0; u < len;)
-	    {	unsigned c;
-		const char *p = utf_decodeChar((unsigned char *)se->string, len, &u, &c);
-		if (p)
-		    error("%s", p);
-		else
-		    buffer.writeUTF16(c);
-	    }
-	    newlen = buffer.offset / 2;
-	    buffer.writeUTF16(0);
-	    goto L1;
-
-	case X(Tchar, Tdchar):
-	    for (size_t u = 0; u < len;)
-	    {	unsigned c;
-		const char *p = utf_decodeChar((unsigned char *)se->string, len, &u, &c);
-		if (p)
-		    error("%s", p);
-		buffer.write4(c);
-		newlen++;
-	    }
-	    buffer.write4(0);
-	    goto L1;
-
-	case X(Twchar,Tchar):
-	    for (size_t u = 0; u < len;)
-	    {	unsigned c;
-		const char *p = utf_decodeWchar((unsigned short *)se->string, len, &u, &c);
-		if (p)
-		    error("%s", p);
-		else
-		    buffer.writeUTF8(c);
-	    }
-	    newlen = buffer.offset;
-	    buffer.writeUTF8(0);
-	    goto L1;
-
-	case X(Twchar,Tdchar):
-	    for (size_t u = 0; u < len;)
-	    {	unsigned c;
-		const char *p = utf_decodeWchar((unsigned short *)se->string, len, &u, &c);
-		if (p)
-		    error("%s", p);
-		buffer.write4(c);
-		newlen++;
-	    }
-	    buffer.write4(0);
-	    goto L1;
-
-	case X(Tdchar,Tchar):
-	    for (size_t u = 0; u < len; u++)
-	    {
-		unsigned c = ((unsigned *)se->string)[u];
-		if (!utf_isValidDchar(c))
-		    error("invalid UCS-32 char \\U%08x", c);
-		else
-		    buffer.writeUTF8(c);
-		newlen++;
-	    }
-	    newlen = buffer.offset;
-	    buffer.writeUTF8(0);
-	    goto L1;
-
-	case X(Tdchar,Twchar):
-	    for (size_t u = 0; u < len; u++)
-	    {
-		unsigned c = ((unsigned *)se->string)[u];
-		if (!utf_isValidDchar(c))
-		    error("invalid UCS-32 char \\U%08x", c);
-		else
-		    buffer.writeUTF16(c);
-		newlen++;
-	    }
-	    newlen = buffer.offset / 2;
-	    buffer.writeUTF16(0);
-	    goto L1;
-
-	L1:
-	    if (!copied)
-	    {   se = (StringExp *)copy();
-		copied = 1;
-	    }
-	    se->string = buffer.extractData();
-	    se->len = newlen;
-	    se->sz = tb->nextOf()->size();
-	    break;
-
-	default:
-	    assert(typeb->nextOf()->size() != tb->nextOf()->size());
-	    goto Lcast;
-    }
-    }
-#undef X
-L2:
-    assert(copied);
-
-    // See if need to truncate or extend the literal
-    if (tb->ty == Tsarray)
-    {
-	int dim2 = ((TypeSArray *)tb)->dim->toInteger();
-
-	//printf("dim from = %d, to = %d\n", se->len, dim2);
-
-	// Changing dimensions
-	if (dim2 != se->len)
-	{
-	    // Copy when changing the string literal
-	    unsigned newsz = se->sz;
-	    void *s;
-	    int d;
-
-	    d = (dim2 < se->len) ? dim2 : se->len;
-	    s = (unsigned char *)mem.malloc((dim2 + 1) * newsz);
-	    memcpy(s, se->string, d * newsz);
-	    // Extend with 0, add terminating 0
-	    memset((char *)s + d * newsz, 0, (dim2 + 1 - d) * newsz);
-	    se->string = s;
-	    se->len = dim2;
-	}
-    }
-    se->type = t;
-    return se;
-
-Lcast:
-    Expression *e = new CastExp(loc, se, t);
-    e->type = t;	// so semantic() won't be run on e
-    return e;
-}
-
-Expression *AddrExp::castTo(Scope *sc, Type *t)
-{
-    Type *tb;
-
-#if 0
-    printf("AddrExp::castTo(this=%s, type=%s, t=%s)\n",
-	toChars(), type->toChars(), t->toChars());
-#endif
-    Expression *e = this;
-
-    tb = t->toBasetype();
-    type = type->toBasetype();
-    if (tb != type)
-    {
-	// Look for pointers to functions where the functions are overloaded.
-
-	if (e1->op == TOKoverloadset &&
-	    (t->ty == Tpointer || t->ty == Tdelegate) && t->nextOf()->ty == Tfunction)
-	{   OverExp *eo = (OverExp *)e1;
-	    FuncDeclaration *f = NULL;
-	    for (int i = 0; i < eo->vars->a.dim; i++)
-	    {   Dsymbol *s = (Dsymbol *)eo->vars->a.data[i];
-		FuncDeclaration *f2 = s->isFuncDeclaration();
-		assert(f2);
-		if (f2->overloadExactMatch(t->nextOf()))
-		{   if (f)
-			/* Error if match in more than one overload set,
-			 * even if one is a 'better' match than the other.
-			 */
-			ScopeDsymbol::multiplyDefined(loc, f, f2);
-		    else
-			f = f2;
-		}
-	    }
-	    if (f)
-	    {	f->tookAddressOf++;
-		SymOffExp *se = new SymOffExp(loc, f, 0, 0);
-		se->semantic(sc);
-		// Let SymOffExp::castTo() do the heavy lifting
-		return se->castTo(sc, t);
-	    }
-	}
-
-
-	if (type->ty == Tpointer && type->nextOf()->ty == Tfunction &&
-	    tb->ty == Tpointer && tb->nextOf()->ty == Tfunction &&
-	    e1->op == TOKvar)
-	{
-	    VarExp *ve = (VarExp *)e1;
-	    FuncDeclaration *f = ve->var->isFuncDeclaration();
-	    if (f)
-	    {
-// LDC: not in ldc
-#if !IN_LLVM
-		assert(0);	// should be SymOffExp instead
-#endif
-		f = f->overloadExactMatch(tb->nextOf());
-		if (f)
-		{
-		    e = new VarExp(loc, f);
-		    e->type = f->type;
-		    e = new AddrExp(loc, e);
-		    e->type = t;
-		    return e;
-		}
-	    }
-	}
-	e = Expression::castTo(sc, t);
-    }
-    e->type = t;
-    return e;
-}
-
-
-Expression *TupleExp::castTo(Scope *sc, Type *t)
-{   TupleExp *e = (TupleExp *)copy();
-    e->exps = (Expressions *)exps->copy();
-    for (size_t i = 0; i < e->exps->dim; i++)
-    {   Expression *ex = (Expression *)e->exps->data[i];
-	ex = ex->castTo(sc, t);
-	e->exps->data[i] = (void *)ex;
-    }
-    return e;
-}
-
-
-Expression *ArrayLiteralExp::castTo(Scope *sc, Type *t)
-{
-#if 0
-    printf("ArrayLiteralExp::castTo(this=%s, type=%s, => %s)\n",
-	toChars(), type->toChars(), t->toChars());
-#endif
-    if (type == t)
-	return this;
-    ArrayLiteralExp *e = this;
-    Type *typeb = type->toBasetype();
-    Type *tb = t->toBasetype();
-    if ((tb->ty == Tarray || tb->ty == Tsarray) &&
-	(typeb->ty == Tarray || typeb->ty == Tsarray) &&
-	// Not trying to convert non-void[] to void[]
-	!(tb->nextOf()->toBasetype()->ty == Tvoid && typeb->nextOf()->toBasetype()->ty != Tvoid))
-    {
-	if (tb->ty == Tsarray)
-	{   TypeSArray *tsa = (TypeSArray *)tb;
-	    if (elements->dim != tsa->dim->toInteger())
-		goto L1;
-	}
-
-	e = (ArrayLiteralExp *)copy();
-	e->elements = (Expressions *)elements->copy();
-	for (int i = 0; i < elements->dim; i++)
-	{   Expression *ex = (Expression *)elements->data[i];
-	    ex = ex->castTo(sc, tb->nextOf());
-	    e->elements->data[i] = (void *)ex;
-	}
-	e->type = t;
-	return e;
-    }
-    if (tb->ty == Tpointer && typeb->ty == Tsarray)
-    {
-	e = (ArrayLiteralExp *)copy();
-	e->type = typeb->nextOf()->pointerTo();
-    }
-L1:
-    return e->Expression::castTo(sc, t);
-}
-
-Expression *AssocArrayLiteralExp::castTo(Scope *sc, Type *t)
-{
-    if (type == t)
-	return this;
-    AssocArrayLiteralExp *e = this;
-    Type *typeb = type->toBasetype();
-    Type *tb = t->toBasetype();
-    if (tb->ty == Taarray && typeb->ty == Taarray &&
-	tb->nextOf()->toBasetype()->ty != Tvoid)
-    {
-	e = (AssocArrayLiteralExp *)copy();
-	e->keys = (Expressions *)keys->copy();
-	e->values = (Expressions *)values->copy();
-	assert(keys->dim == values->dim);
-	for (size_t i = 0; i < keys->dim; i++)
-	{   Expression *ex = (Expression *)values->data[i];
-	    ex = ex->castTo(sc, tb->nextOf());
-	    e->values->data[i] = (void *)ex;
-
-	    ex = (Expression *)keys->data[i];
-	    ex = ex->castTo(sc, ((TypeAArray *)tb)->index);
-	    e->keys->data[i] = (void *)ex;
-	}
-	e->type = t;
-	return e;
-    }
-L1:
-    return e->Expression::castTo(sc, t);
-}
-
-Expression *SymOffExp::castTo(Scope *sc, Type *t)
-{
-#if 0
-    printf("SymOffExp::castTo(this=%s, type=%s, t=%s)\n",
-	toChars(), type->toChars(), t->toChars());
-#endif
-    if (type == t && hasOverloads == 0)
-	return this;
-    Expression *e;
-    Type *tb = t->toBasetype();
-    Type *typeb = type->toBasetype();
-    if (tb != typeb)
-    {
-	// Look for pointers to functions where the functions are overloaded.
-	FuncDeclaration *f;
-
-	if (hasOverloads &&
-	    typeb->ty == Tpointer && typeb->nextOf()->ty == Tfunction &&
-	    (tb->ty == Tpointer || tb->ty == Tdelegate) && tb->nextOf()->ty == Tfunction)
-	{
-	    f = var->isFuncDeclaration();
-	    if (f)
-	    {
-		f = f->overloadExactMatch(tb->nextOf());
-		if (f)
-		{
-		    if (tb->ty == Tdelegate && f->needThis() && hasThis(sc))
-		    {
-			e = new DelegateExp(loc, new ThisExp(loc), f);
-			e = e->semantic(sc);
-		    }
-		    else if (tb->ty == Tdelegate && f->isNested())
-		    {
-			e = new DelegateExp(loc, new IntegerExp(0), f);
-			e = e->semantic(sc);
-		    }
-		    else
-		    {
-			e = new SymOffExp(loc, f, 0);
-			e->type = t;
-		    }
-		    f->tookAddressOf++;
-		    return e;
-		}
-	    }
-	}
-	e = Expression::castTo(sc, t);
-    }
-    else
-    {	e = copy();
-	e->type = t;
-	((SymOffExp *)e)->hasOverloads = 0;
-    }
-    return e;
-}
-
-Expression *DelegateExp::castTo(Scope *sc, Type *t)
-{
-#if 0
-    printf("DelegateExp::castTo(this=%s, type=%s, t=%s)\n",
-	toChars(), type->toChars(), t->toChars());
-#endif
-    static char msg[] = "cannot form delegate due to covariant return type";
-
-    Expression *e = this;
-    Type *tb = t->toBasetype();
-    Type *typeb = type->toBasetype();
-    if (tb != typeb)
-    {
-	// Look for delegates to functions where the functions are overloaded.
-	FuncDeclaration *f;
-
-	if (typeb->ty == Tdelegate && typeb->nextOf()->ty == Tfunction &&
-	    tb->ty == Tdelegate && tb->nextOf()->ty == Tfunction)
-	{
-	    if (func)
-	    {
-		f = func->overloadExactMatch(tb->nextOf());
-		if (f)
-		{   int offset;
-		    if (f->tintro && f->tintro->nextOf()->isBaseOf(f->type->nextOf(), &offset) && offset)
-			error("%s", msg);
-		    f->tookAddressOf++;
-		    e = new DelegateExp(loc, e1, f);
-		    e->type = t;
-		    return e;
-		}
-		if (func->tintro)
-		    error("%s", msg);
-	    }
-	}
-	e = Expression::castTo(sc, t);
-    }
-    else
-    {	int offset;
-
-	func->tookAddressOf++;
-	if (func->tintro && func->tintro->nextOf()->isBaseOf(func->type->nextOf(), &offset) && offset)
-	    error("%s", msg);
-	e = copy();
-	e->type = t;
-    }
-    return e;
-}
-
-Expression *CondExp::castTo(Scope *sc, Type *t)
-{
-    Expression *e = this;
-
-    if (type != t)
-    {
-	if (1 || e1->op == TOKstring || e2->op == TOKstring)
-	{   e = new CondExp(loc, econd, e1->castTo(sc, t), e2->castTo(sc, t));
-	    e->type = t;
-	}
-	else
-	    e = Expression::castTo(sc, t);
-    }
-    return e;
-}
-
-/* ==================== ====================== */
-
-/****************************************
- * Scale addition/subtraction to/from pointer.
- */
-
-Expression *BinExp::scaleFactor(Scope *sc)
-{   d_uns64 stride;
-    Type *t1b = e1->type->toBasetype();
-    Type *t2b = e2->type->toBasetype();
-
-    if (t1b->ty == Tpointer && t2b->isintegral())
-    {   // Need to adjust operator by the stride
-	// Replace (ptr + int) with (ptr + (int * stride))
-	Type *t = Type::tptrdiff_t;
-
-	stride = t1b->nextOf()->size(loc);
-	if (!t->equals(t2b))
-	    e2 = e2->castTo(sc, t);
-    // LDC: llvm uses typesafe pointer arithmetic
-    #if !IN_LLVM
-	e2 = new MulExp(loc, e2, new IntegerExp(0, stride, t));
-    #endif
-	e2->type = t;
-	type = e1->type;
-    }
-    else if (t2b->ty == Tpointer && t1b->isintegral())
-    {   // Need to adjust operator by the stride
-	// Replace (int + ptr) with (ptr + (int * stride))
-	Type *t = Type::tptrdiff_t;
-	Expression *e;
-
-	stride = t2b->nextOf()->size(loc);
-	if (!t->equals(t1b))
-	    e = e1->castTo(sc, t);
-	else
-	    e = e1;
-    #if !IN_LLVM
-	e = new MulExp(loc, e, new IntegerExp(0, stride, t));
-    #endif
-	e->type = t;
-	type = e2->type;
-	e1 = e2;
-	e2 = e;
-    }
-    return this;
-}
-
-/**************************************
- * Combine types.
- * Output:
- *	*pt	merged type, if *pt is not NULL
- *	*pe1	rewritten e1
- *	*pe2	rewritten e2
- * Returns:
- *	!=0	success
- *	0	failed
- */
-
-int typeMerge(Scope *sc, Expression *e, Type **pt, Expression **pe1, Expression **pe2)
-{
-    //printf("typeMerge() %s op %s\n", (*pe1)->toChars(), (*pe2)->toChars());
-    //dump(0);
-
-    Expression *e1 = (*pe1)->integralPromotions(sc);
-    Expression *e2 = (*pe2)->integralPromotions(sc);
-
-    Type *t1 = e1->type;
-    Type *t2 = e2->type;
-    assert(t1);
-    Type *t = t1;
-
-    //if (t1) printf("\tt1 = %s\n", t1->toChars());
-    //if (t2) printf("\tt2 = %s\n", t2->toChars());
-#ifdef DEBUG
-    if (!t2) printf("\te2 = '%s'\n", e2->toChars());
-#endif
-    assert(t2);
-
-    Type *t1b = t1->toBasetype();
-    Type *t2b = t2->toBasetype();
-
-    TY ty = (TY)Type::impcnvResult[t1b->ty][t2b->ty];
-    if (ty != Terror)
-    {	TY ty1;
-	TY ty2;
-
-	ty1 = (TY)Type::impcnvType1[t1b->ty][t2b->ty];
-	ty2 = (TY)Type::impcnvType2[t1b->ty][t2b->ty];
-
-	if (t1b->ty == ty1)	// if no promotions
-	{
-	    if (t1 == t2)
-	    {
-		t = t1;
-		goto Lret;
-	    }
-
-	    if (t1b == t2b)
-	    {
-		t = t1b;
-		goto Lret;
-	    }
-	}
-
-	t = Type::basic[ty];
-
-	t1 = Type::basic[ty1];
-	t2 = Type::basic[ty2];
-	e1 = e1->castTo(sc, t1);
-	e2 = e2->castTo(sc, t2);
-	//printf("after typeCombine():\n");
-	//dump(0);
-	//printf("ty = %d, ty1 = %d, ty2 = %d\n", ty, ty1, ty2);
-	goto Lret;
-    }
-
-    t1 = t1b;
-    t2 = t2b;
-
-Lagain:
-    if (t1 == t2)
-    {
-    }
-    else if (t1->ty == Tpointer && t2->ty == Tpointer)
-    {
-	// Bring pointers to compatible type
-	Type *t1n = t1->nextOf();
-	Type *t2n = t2->nextOf();
-
-	if (t1n == t2n)
-	    ;
-	else if (t1n->ty == Tvoid)	// pointers to void are always compatible
-	    t = t2;
-	else if (t2n->ty == Tvoid)
-	    ;
-	else if (t1n->mod != t2n->mod)
-	{
-	    t1 = t1n->mutableOf()->constOf()->pointerTo();
-	    t2 = t2n->mutableOf()->constOf()->pointerTo();
-	    t = t1;
-	    goto Lagain;
-	}
-	else if (t1n->ty == Tclass && t2n->ty == Tclass)
-	{   ClassDeclaration *cd1 = t1n->isClassHandle();
-	    ClassDeclaration *cd2 = t2n->isClassHandle();
-	    int offset;
-
-	    if (cd1->isBaseOf(cd2, &offset))
-	    {
-		if (offset)
-		    e2 = e2->castTo(sc, t);
-	    }
-	    else if (cd2->isBaseOf(cd1, &offset))
-	    {
-		t = t2;
-		if (offset)
-		    e1 = e1->castTo(sc, t);
-	    }
-	    else
-		goto Lincompatible;
-	}
-	else
-	    goto Lincompatible;
-    }
-    else if ((t1->ty == Tsarray || t1->ty == Tarray) &&
-	     e2->op == TOKnull && t2->ty == Tpointer && t2->nextOf()->ty == Tvoid)
-    {	/*  (T[n] op void*)
-	 *  (T[] op void*)
-	 */
-	goto Lx1;
-    }
-    else if ((t2->ty == Tsarray || t2->ty == Tarray) &&
-	     e1->op == TOKnull && t1->ty == Tpointer && t1->nextOf()->ty == Tvoid)
-    {	/*  (void* op T[n])
-	 *  (void* op T[])
-	 */
-	goto Lx2;
-    }
-    else if ((t1->ty == Tsarray || t1->ty == Tarray) && t1->implicitConvTo(t2))
-    {
-	goto Lt2;
-    }
-    else if ((t2->ty == Tsarray || t2->ty == Tarray) && t2->implicitConvTo(t1))
-    {
-	goto Lt1;
-    }
-    /* If one is mutable and the other invariant, then retry
-     * with both of them as const
-     */
-    else if ((t1->ty == Tsarray || t1->ty == Tarray || t1->ty == Tpointer) &&
-	     (t2->ty == Tsarray || t2->ty == Tarray || t2->ty == Tpointer) &&
-	     t1->nextOf()->mod != t2->nextOf()->mod
-	    )
-    {
-	if (t1->ty == Tpointer)
-	    t1 = t1->nextOf()->mutableOf()->constOf()->pointerTo();
-	else
-	    t1 = t1->nextOf()->mutableOf()->constOf()->arrayOf();
-
-	if (t2->ty == Tpointer)
-	    t2 = t2->nextOf()->mutableOf()->constOf()->pointerTo();
-	else
-	    t2 = t2->nextOf()->mutableOf()->constOf()->arrayOf();
-	t = t1;
-	goto Lagain;
-    }
-    else if (t1->ty == Tclass || t2->ty == Tclass)
-    {
-	while (1)
-	{
-	    int i1 = e2->implicitConvTo(t1);
-	    int i2 = e1->implicitConvTo(t2);
-
-	    if (i1 && i2)
-	    {
-		// We have the case of class vs. void*, so pick class
-		if (t1->ty == Tpointer)
-		    i1 = 0;
-		else if (t2->ty == Tpointer)
-		    i2 = 0;
-	    }
-
-	    if (i2)
-	    {
-		goto Lt2;
-	    }
-	    else if (i1)
-	    {
-		goto Lt1;
-	    }
-	    else if (t1->ty == Tclass && t2->ty == Tclass)
-	    {	TypeClass *tc1 = (TypeClass *)t1;
-		TypeClass *tc2 = (TypeClass *)t2;
-
-		/* Pick 'tightest' type
-		 */
-		ClassDeclaration *cd1 = tc1->sym->baseClass;
-		ClassDeclaration *cd2 = tc2->sym->baseClass;
-
-		if (cd1 && cd2)
-		{   t1 = cd1->type;
-		    t2 = cd2->type;
-		}
-		else if (cd1)
-		    t1 = cd1->type;
-		else if (cd2)
-		    t2 = cd2->type;
-		else
-		    goto Lincompatible;
-	    }
-	    else
-		goto Lincompatible;
-	}
-    }
-    else if (t1->ty == Tstruct && t2->ty == Tstruct)
-    {
-	if (((TypeStruct *)t1)->sym != ((TypeStruct *)t2)->sym)
-	    goto Lincompatible;
-    }
-    else if ((e1->op == TOKstring || e1->op == TOKnull) && e1->implicitConvTo(t2))
-    {
-	goto Lt2;
-    }
-    else if ((e2->op == TOKstring || e2->op == TOKnull) && e2->implicitConvTo(t1))
-    {
-	goto Lt1;
-    }
-    else if (t1->ty == Tsarray && t2->ty == Tsarray &&
-	     e2->implicitConvTo(t1->nextOf()->arrayOf()))
-    {
-     Lx1:
-	t = t1->nextOf()->arrayOf();
-	e1 = e1->castTo(sc, t);
-	e2 = e2->castTo(sc, t);
-    }
-    else if (t1->ty == Tsarray && t2->ty == Tsarray &&
-	     e1->implicitConvTo(t2->nextOf()->arrayOf()))
-    {
-     Lx2:
-	t = t2->nextOf()->arrayOf();
-	e1 = e1->castTo(sc, t);
-	e2 = e2->castTo(sc, t);
-    }
-    else if (t1->isintegral() && t2->isintegral())
-    {
-	assert(0);
-    }
-    else if (e1->op == TOKslice && t1->ty == Tarray &&
-	     e2->implicitConvTo(t1->nextOf()))
-    {	// T[] op T
-	e2 = e2->castTo(sc, t1->nextOf());
-	t = t1->nextOf()->arrayOf();
-    }
-    else if (e2->op == TOKslice && t2->ty == Tarray &&
-	     e1->implicitConvTo(t2->nextOf()))
-    {	// T op T[]
-	e1 = e1->castTo(sc, t2->nextOf());
-	t = t2->nextOf()->arrayOf();
-
-	//printf("test %s\n", e->toChars());
-	e1 = e1->optimize(WANTvalue);
-	if (e && e->isCommutative() && e1->isConst())
-	{   /* Swap operands to minimize number of functions generated
-	     */
-	    //printf("swap %s\n", e->toChars());
-	    Expression *tmp = e1;
-	    e1 = e2;
-	    e2 = tmp;
-	}
-    }
-    else
-    {
-     Lincompatible:
-	return 0;
-    }
-Lret:
-    if (!*pt)
-	*pt = t;
-    *pe1 = e1;
-    *pe2 = e2;
-#if 0
-    printf("-typeMerge() %s op %s\n", e1->toChars(), e2->toChars());
-    if (e1->type) printf("\tt1 = %s\n", e1->type->toChars());
-    if (e2->type) printf("\tt2 = %s\n", e2->type->toChars());
-    printf("\ttype = %s\n", t->toChars());
-#endif
-    //dump(0);
-    return 1;
-
-
-Lt1:
-    e2 = e2->castTo(sc, t1);
-    t = t1;
-    goto Lret;
-
-Lt2:
-    e1 = e1->castTo(sc, t2);
-    t = t2;
-    goto Lret;
-}
-
-/************************************
- * Bring leaves to common type.
- */
-
-Expression *BinExp::typeCombine(Scope *sc)
-{
-    Type *t1 = e1->type->toBasetype();
-    Type *t2 = e2->type->toBasetype();
-
-    if (op == TOKmin || op == TOKadd)
-    {
-	if (t1 == t2 && (t1->ty == Tstruct || t1->ty == Tclass))
-	    goto Lerror;
-    }
-
-    if (!typeMerge(sc, this, &type, &e1, &e2))
-	goto Lerror;
-    return this;
-
-Lerror:
-    incompatibleTypes();
-    type = Type::terror;
-    return this;
-}
-
-/***********************************
- * Do integral promotions (convertchk).
- * Don't convert <array of> to <pointer to>
- */
-
-Expression *Expression::integralPromotions(Scope *sc)
-{
-    Expression *e = this;
-
-    //printf("integralPromotions %s %s\n", e->toChars(), e->type->toChars());
-    switch (type->toBasetype()->ty)
-    {
-	case Tvoid:
-	    error("void has no value");
-	    break;
-
-	case Tint8:
-	case Tuns8:
-	case Tint16:
-	case Tuns16:
-	case Tbit:
-	case Tbool:
-	case Tchar:
-	case Twchar:
-	    e = e->castTo(sc, Type::tint32);
-	    break;
-
-	case Tdchar:
-	    e = e->castTo(sc, Type::tuns32);
-	    break;
-    }
-    return e;
-}
-
+
+// Copyright (c) 1999-2009 by Digital Mars
+// All Rights Reserved
+// written by Walter Bright
+// http://www.digitalmars.com
+// License for redistribution is by either the Artistic License
+// in artistic.txt, or the GNU General Public License in gnu.txt.
+// See the included readme.txt for details.
+
+#include <stdio.h>
+#include <assert.h>
+
+#include "rmem.h"
+
+#include "expression.h"
+#include "mtype.h"
+#include "utf.h"
+#include "declaration.h"
+#include "aggregate.h"
+
+/* ==================== implicitCast ====================== */
+
+/**************************************
+ * Do an implicit cast.
+ * Issue error if it can't be done.
+ */
+
+Expression *Expression::implicitCastTo(Scope *sc, Type *t)
+{
+    //printf("Expression::implicitCastTo(%s of type %s) => %s\n", toChars(), type->toChars(), t->toChars());
+
+    MATCH match = implicitConvTo(t);
+    if (match)
+    {	TY tyfrom = type->toBasetype()->ty;
+	TY tyto = t->toBasetype()->ty;
+	if (global.params.warnings &&
+	    Type::impcnvWarn[tyfrom][tyto] &&
+	    op != TOKint64)
+	{
+	    Expression *e = optimize(WANTflags | WANTvalue);
+
+	    if (e->op == TOKint64)
+		return e->implicitCastTo(sc, t);
+
+	    if (tyfrom == Tint32 &&
+		(op == TOKadd || op == TOKmin ||
+		 op == TOKand || op == TOKor || op == TOKxor)
+	       )
+	    {
+		/* This is really only a semi-kludge fix,
+		 * we really should look at the operands of op
+		 * and see if they are narrower types.
+		 * For example, b=b|b and b=b|7 and s=b+b should be allowed,
+		 * but b=b|i should be an error.
+		 */
+		;
+	    }
+	    else
+	    {
+		warning("implicit conversion of expression (%s) of type %s to %s can cause loss of data",
+		    toChars(), type->toChars(), t->toChars());
+	    }
+	}
+#if DMDV2
+	if (match == MATCHconst && t == type->constOf())
+	{
+	    Expression *e = copy();
+	    e->type = t;
+	    return e;
+	}
+#endif
+	return castTo(sc, t);
+    }
+
+    Expression *e = optimize(WANTflags | WANTvalue);
+    if (e != this)
+	return e->implicitCastTo(sc, t);
+
+#if 0
+printf("ty = %d\n", type->ty);
+print();
+type->print();
+printf("to:\n");
+t->print();
+printf("%p %p type: %s to: %s\n", type->deco, t->deco, type->deco, t->deco);
+//printf("%p %p %p\n", type->nextOf()->arrayOf(), type, t);
+fflush(stdout);
+#endif
+    if (!t->deco)
+    {	/* Can happen with:
+	 *    enum E { One }
+	 *    class A
+	 *    { static void fork(EDG dg) { dg(E.One); }
+	 *	alias void delegate(E) EDG;
+	 *    }
+	 * Should eventually make it work.
+	 */
+	error("forward reference to type %s", t->toChars());
+    }
+    else if (t->reliesOnTident())
+	error("forward reference to type %s", t->reliesOnTident()->toChars());
+
+    error("cannot implicitly convert expression (%s) of type %s to %s",
+	toChars(), type->toChars(), t->toChars());
+    return castTo(sc, t);
+}
+
+Expression *StringExp::implicitCastTo(Scope *sc, Type *t)
+{
+    //printf("StringExp::implicitCastTo(%s of type %s) => %s\n", toChars(), type->toChars(), t->toChars());
+    unsigned char committed = this->committed;
+    Expression *e = Expression::implicitCastTo(sc, t);
+    if (e->op == TOKstring)
+    {
+	// Retain polysemous nature if it started out that way
+	((StringExp *)e)->committed = committed;
+    }
+    return e;
+}
+
+/*******************************************
+ * Return !=0 if we can implicitly convert this to type t.
+ * Don't do the actual cast.
+ */
+
+MATCH Expression::implicitConvTo(Type *t)
+{
+#if 0
+    printf("Expression::implicitConvTo(this=%s, type=%s, t=%s)\n",
+	toChars(), type->toChars(), t->toChars());
+#endif
+    //static int nest; if (++nest == 10) halt();
+    if (!type)
+    {	error("%s is not an expression", toChars());
+	type = Type::terror;
+    }
+    Expression *e = optimize(WANTvalue | WANTflags);
+    if (e->type == t)
+	return MATCHexact;
+    if (e != this)
+    {	//printf("\toptimized to %s of type %s\n", e->toChars(), e->type->toChars());
+	return e->implicitConvTo(t);
+    }
+    MATCH match = type->implicitConvTo(t);
+    if (match != MATCHnomatch)
+	return match;
+#if 0
+    Type *tb = t->toBasetype();
+    if (tb->ty == Tdelegate)
+    {	TypeDelegate *td = (TypeDelegate *)tb;
+	TypeFunction *tf = (TypeFunction *)td->nextOf();
+
+	if (!tf->varargs &&
+	    !(tf->arguments && tf->arguments->dim)
+	   )
+	{
+	    match = type->implicitConvTo(tf->nextOf());
+	    if (match)
+		return match;
+	    if (tf->nextOf()->toBasetype()->ty == Tvoid)
+		return MATCHconvert;
+	}
+    }
+#endif
+    return MATCHnomatch;
+}
+
+
+MATCH IntegerExp::implicitConvTo(Type *t)
+{
+#if 0
+    printf("IntegerExp::implicitConvTo(this=%s, type=%s, t=%s)\n",
+	toChars(), type->toChars(), t->toChars());
+#endif
+    MATCH m = type->implicitConvTo(t);
+    if (m >= MATCHconst)
+	return m;
+
+    TY ty = type->toBasetype()->ty;
+    TY toty = t->toBasetype()->ty;
+
+    if (m == MATCHnomatch && t->ty == Tenum)
+	goto Lno;
+
+    switch (ty)
+    {
+	case Tbit:
+	case Tbool:
+	    value &= 1;
+	    ty = Tint32;
+	    break;
+
+	case Tint8:
+	    value = (signed char)value;
+	    ty = Tint32;
+	    break;
+
+	case Tchar:
+	case Tuns8:
+	    value &= 0xFF;
+	    ty = Tint32;
+	    break;
+
+	case Tint16:
+	    value = (short)value;
+	    ty = Tint32;
+	    break;
+
+	case Tuns16:
+	case Twchar:
+	    value &= 0xFFFF;
+	    ty = Tint32;
+	    break;
+
+	case Tint32:
+	    value = (int)value;
+	    break;
+
+	case Tuns32:
+	case Tdchar:
+	    value &= 0xFFFFFFFF;
+	    ty = Tuns32;
+	    break;
+
+	default:
+	    break;
+    }
+
+    // Only allow conversion if no change in value
+    switch (toty)
+    {
+	case Tbit:
+	case Tbool:
+	    if ((value & 1) != value)
+		goto Lno;
+	    goto Lyes;
+
+	case Tint8:
+	    if ((signed char)value != value)
+		goto Lno;
+	    goto Lyes;
+
+	case Tchar:
+	case Tuns8:
+	    //printf("value = %llu %llu\n", (dinteger_t)(unsigned char)value, value);
+	    if ((unsigned char)value != value)
+		goto Lno;
+	    goto Lyes;
+
+	case Tint16:
+	    if ((short)value != value)
+		goto Lno;
+	    goto Lyes;
+
+	case Tuns16:
+	    if ((unsigned short)value != value)
+		goto Lno;
+	    goto Lyes;
+
+	case Tint32:
+	    if (ty == Tuns32)
+	    {
+	    }
+	    else if ((int)value != value)
+		goto Lno;
+	    goto Lyes;
+
+	case Tuns32:
+	    if (ty == Tint32)
+	    {
+	    }
+	    else if ((unsigned)value != value)
+		goto Lno;
+	    goto Lyes;
+
+	case Tdchar:
+	    if (value > 0x10FFFFUL)
+		goto Lno;
+	    goto Lyes;
+
+	case Twchar:
+	    if ((unsigned short)value != value)
+		goto Lno;
+	    goto Lyes;
+
+	case Tfloat32:
+	{
+	    volatile float f;
+	    if (type->isunsigned())
+	    {
+		f = (float)value;
+		if (f != value)
+		    goto Lno;
+	    }
+	    else
+	    {
+		f = (float)(long long)value;
+		if (f != (long long)value)
+		    goto Lno;
+	    }
+	    goto Lyes;
+	}
+
+	case Tfloat64:
+	{
+	    volatile double f;
+	    if (type->isunsigned())
+	    {
+		f = (double)value;
+		if (f != value)
+		    goto Lno;
+	    }
+	    else
+	    {
+		f = (double)(long long)value;
+		if (f != (long long)value)
+		    goto Lno;
+	    }
+	    goto Lyes;
+	}
+
+	case Tfloat80:
+	{
+	    volatile long double f;
+	    if (type->isunsigned())
+	    {
+		f = (long double)value;
+		if (f != value)
+		    goto Lno;
+	    }
+	    else
+	    {
+		f = (long double)(long long)value;
+		if (f != (long long)value)
+		    goto Lno;
+	    }
+	    goto Lyes;
+	}
+
+	case Tpointer:
+//printf("type = %s\n", type->toBasetype()->toChars());
+//printf("t = %s\n", t->toBasetype()->toChars());
+	    if (ty == Tpointer &&
+	        type->toBasetype()->nextOf()->ty == t->toBasetype()->nextOf()->ty)
+	    {	/* Allow things like:
+		 *	const char* P = cast(char *)3;
+		 *	char* q = P;
+		 */
+		goto Lyes;
+	    }
+	    break;
+    }
+    return Expression::implicitConvTo(t);
+
+Lyes:
+    //printf("MATCHconvert\n");
+    return MATCHconvert;
+
+Lno:
+    //printf("MATCHnomatch\n");
+    return MATCHnomatch;
+}
+
+MATCH NullExp::implicitConvTo(Type *t)
+{
+#if 0
+    printf("NullExp::implicitConvTo(this=%s, type=%s, t=%s, committed = %d)\n",
+	toChars(), type->toChars(), t->toChars(), committed);
+#endif
+    if (this->type->equals(t))
+	return MATCHexact;
+
+    /* Allow implicit conversions from invariant to mutable|const,
+     * and mutable to invariant. It works because, after all, a null
+     * doesn't actually point to anything.
+     */
+    if (t->invariantOf()->equals(type->invariantOf()))
+	return MATCHconst;
+
+    // NULL implicitly converts to any pointer type or dynamic array
+    if (type->ty == Tpointer && type->nextOf()->ty == Tvoid)
+    {
+	if (t->ty == Ttypedef)
+	    t = ((TypeTypedef *)t)->sym->basetype;
+	if (t->ty == Tpointer || t->ty == Tarray ||
+	    t->ty == Taarray  || t->ty == Tclass ||
+	    t->ty == Tdelegate)
+	    return committed ? MATCHconvert : MATCHexact;
+    }
+    return Expression::implicitConvTo(t);
+}
+
+#if DMDV2
+MATCH StructLiteralExp::implicitConvTo(Type *t)
+{
+#if 0
+    printf("StructLiteralExp::implicitConvTo(this=%s, type=%s, t=%s)\n",
+	toChars(), type->toChars(), t->toChars());
+#endif
+    MATCH m = Expression::implicitConvTo(t);
+    if (m != MATCHnomatch)
+	return m;
+    if (type->ty == t->ty && type->ty == Tstruct &&
+	((TypeStruct *)type)->sym == ((TypeStruct *)t)->sym)
+    {
+	m = MATCHconst;
+	for (int i = 0; i < elements->dim; i++)
+	{   Expression *e = (Expression *)elements->data[i];
+	    Type *te = e->type;
+	    if (t->mod == 0)
+		te = te->mutableOf();
+	    else
+	    {	assert(t->mod == MODinvariant);
+		te = te->invariantOf();
+	    }
+	    MATCH m2 = e->implicitConvTo(te);
+	    //printf("\t%s => %s, match = %d\n", e->toChars(), te->toChars(), m2);
+	    if (m2 < m)
+		m = m2;
+	}
+    }
+    return m;
+}
+#endif
+
+MATCH StringExp::implicitConvTo(Type *t)
+{   MATCH m;
+
+#if 0
+    printf("StringExp::implicitConvTo(this=%s, committed=%d, type=%s, t=%s)\n",
+	toChars(), committed, type->toChars(), t->toChars());
+#endif
+    if (!committed)
+    {
+    if (!committed && t->ty == Tpointer && t->nextOf()->ty == Tvoid)
+    {
+	return MATCHnomatch;
+    }
+    if (type->ty == Tsarray || type->ty == Tarray || type->ty == Tpointer)
+    {
+	TY tyn = type->nextOf()->ty;
+	if (tyn == Tchar || tyn == Twchar || tyn == Tdchar)
+	{   Type *tn;
+	    MATCH m;
+
+	    switch (t->ty)
+	    {
+		case Tsarray:
+		    if (type->ty == Tsarray)
+		    {
+			if (((TypeSArray *)type)->dim->toInteger() !=
+			    ((TypeSArray *)t)->dim->toInteger())
+			    return MATCHnomatch;
+			TY tynto = t->nextOf()->ty;
+			if (tynto == Tchar || tynto == Twchar || tynto == Tdchar)
+			    return MATCHexact;
+		    }
+		    else if (type->ty == Tarray)
+		    {
+			if (length() >
+			    ((TypeSArray *)t)->dim->toInteger())
+			    return MATCHnomatch;
+			TY tynto = t->nextOf()->ty;
+			if (tynto == Tchar || tynto == Twchar || tynto == Tdchar)
+			    return MATCHexact;
+		    }
+		case Tarray:
+		case Tpointer:
+		    tn = t->nextOf();
+		    m = MATCHexact;
+		    if (type->nextOf()->mod != tn->mod)
+		    {	if (!tn->isConst())
+			    return MATCHnomatch;
+			m = MATCHconst;
+		    }
+		    switch (tn->ty)
+		    {
+			case Tchar:
+			case Twchar:
+			case Tdchar:
+			    return m;
+		    }
+		    break;
+	    }
+	}
+    }
+    }
+    return Expression::implicitConvTo(t);
+#if 0
+    m = (MATCH)type->implicitConvTo(t);
+    if (m)
+    {
+	return m;
+    }
+
+    return MATCHnomatch;
+#endif
+}
+
+MATCH ArrayLiteralExp::implicitConvTo(Type *t)
+{   MATCH result = MATCHexact;
+
+#if 0
+    printf("ArrayLiteralExp::implicitConvTo(this=%s, type=%s, t=%s)\n",
+	toChars(), type->toChars(), t->toChars());
+#endif
+    Type *typeb = type->toBasetype();
+    Type *tb = t->toBasetype();
+    if ((tb->ty == Tarray || tb->ty == Tsarray) &&
+	(typeb->ty == Tarray || typeb->ty == Tsarray))
+    {
+	if (tb->ty == Tsarray)
+	{   TypeSArray *tsa = (TypeSArray *)tb;
+	    if (elements->dim != tsa->dim->toInteger())
+		result = MATCHnomatch;
+	}
+
+	for (int i = 0; i < elements->dim; i++)
+	{   Expression *e = (Expression *)elements->data[i];
+	    MATCH m = (MATCH)e->implicitConvTo(tb->nextOf());
+	    if (m < result)
+		result = m;			// remember worst match
+	    if (result == MATCHnomatch)
+		break;				// no need to check for worse
+	}
+	return result;
+    }
+    else
+	return Expression::implicitConvTo(t);
+}
+
+MATCH AssocArrayLiteralExp::implicitConvTo(Type *t)
+{   MATCH result = MATCHexact;
+
+    Type *typeb = type->toBasetype();
+    Type *tb = t->toBasetype();
+    if (tb->ty == Taarray && typeb->ty == Taarray)
+    {
+	for (size_t i = 0; i < keys->dim; i++)
+	{   Expression *e = (Expression *)keys->data[i];
+	    MATCH m = (MATCH)e->implicitConvTo(((TypeAArray *)tb)->index);
+	    if (m < result)
+		result = m;			// remember worst match
+	    if (result == MATCHnomatch)
+		break;				// no need to check for worse
+	    e = (Expression *)values->data[i];
+	    m = (MATCH)e->implicitConvTo(tb->nextOf());
+	    if (m < result)
+		result = m;			// remember worst match
+	    if (result == MATCHnomatch)
+		break;				// no need to check for worse
+	}
+	return result;
+    }
+    else
+	return Expression::implicitConvTo(t);
+}
+
+MATCH AddrExp::implicitConvTo(Type *t)
+{
+#if 0
+    printf("AddrExp::implicitConvTo(this=%s, type=%s, t=%s)\n",
+	toChars(), type->toChars(), t->toChars());
+#endif
+    MATCH result;
+
+    result = type->implicitConvTo(t);
+    //printf("\tresult = %d\n", result);
+
+    if (result == MATCHnomatch)
+    {
+	// Look for pointers to functions where the functions are overloaded.
+
+	t = t->toBasetype();
+
+	if (e1->op == TOKoverloadset &&
+	    (t->ty == Tpointer || t->ty == Tdelegate) && t->nextOf()->ty == Tfunction)
+	{   OverExp *eo = (OverExp *)e1;
+	    FuncDeclaration *f = NULL;
+	    for (int i = 0; i < eo->vars->a.dim; i++)
+	    {   Dsymbol *s = (Dsymbol *)eo->vars->a.data[i];
+		FuncDeclaration *f2 = s->isFuncDeclaration();
+		assert(f2);
+		if (f2->overloadExactMatch(t->nextOf(), m))
+		{   if (f)
+			/* Error if match in more than one overload set,
+			 * even if one is a 'better' match than the other.
+			 */
+			ScopeDsymbol::multiplyDefined(loc, f, f2);
+		    else
+			f = f2;
+		    result = MATCHexact;
+		}
+	    }
+	}
+
+	if (type->ty == Tpointer && type->nextOf()->ty == Tfunction &&
+	    t->ty == Tpointer && t->nextOf()->ty == Tfunction &&
+	    e1->op == TOKvar)
+	{
+	    /* I don't think this can ever happen -
+	     * it should have been
+	     * converted to a SymOffExp.
+	     */
+	    assert(0);
+	    VarExp *ve = (VarExp *)e1;
+	    FuncDeclaration *f = ve->var->isFuncDeclaration();
+	    if (f && f->overloadExactMatch(t->nextOf(), m))
+		result = MATCHexact;
+	}
+    }
+    //printf("\tresult = %d\n", result);
+    return result;
+}
+
+MATCH SymOffExp::implicitConvTo(Type *t)
+{
+#if 0
+    printf("SymOffExp::implicitConvTo(this=%s, type=%s, t=%s)\n",
+	toChars(), type->toChars(), t->toChars());
+#endif
+    MATCH result;
+
+    result = type->implicitConvTo(t);
+    //printf("\tresult = %d\n", result);
+
+    if (result == MATCHnomatch)
+    {
+	// Look for pointers to functions where the functions are overloaded.
+	FuncDeclaration *f;
+
+	t = t->toBasetype();
+	if (type->ty == Tpointer && type->nextOf()->ty == Tfunction &&
+	    (t->ty == Tpointer || t->ty == Tdelegate) && t->nextOf()->ty == Tfunction)
+	{
+	    f = var->isFuncDeclaration();
+	    if (f)
+	    {	f = f->overloadExactMatch(t->nextOf(), m);
+		if (f)
+		{   if ((t->ty == Tdelegate && (f->needThis() || f->isNested())) ||
+			(t->ty == Tpointer && !(f->needThis() || f->isNested())))
+		    {
+			result = MATCHexact;
+		    }
+		}
+	    }
+	}
+    }
+    //printf("\tresult = %d\n", result);
+    return result;
+}
+
+MATCH DelegateExp::implicitConvTo(Type *t)
+{
+#if 0
+    printf("DelegateExp::implicitConvTo(this=%s, type=%s, t=%s)\n",
+	toChars(), type->toChars(), t->toChars());
+#endif
+    MATCH result;
+
+    result = type->implicitConvTo(t);
+
+    if (result == MATCHnomatch)
+    {
+	// Look for pointers to functions where the functions are overloaded.
+	FuncDeclaration *f;
+
+	t = t->toBasetype();
+	if (type->ty == Tdelegate && type->nextOf()->ty == Tfunction &&
+	    t->ty == Tdelegate && t->nextOf()->ty == Tfunction)
+	{
+	    if (func && func->overloadExactMatch(t->nextOf(), m))
+		result = MATCHexact;
+	}
+    }
+    return result;
+}
+
+MATCH CondExp::implicitConvTo(Type *t)
+{
+    MATCH m1;
+    MATCH m2;
+
+    m1 = e1->implicitConvTo(t);
+    m2 = e2->implicitConvTo(t);
+
+    // Pick the worst match
+    return (m1 < m2) ? m1 : m2;
+}
+
+
+/* ==================== castTo ====================== */
+
+/**************************************
+ * Do an explicit cast.
+ */
+
+Expression *Expression::castTo(Scope *sc, Type *t)
+{
+    //printf("Expression::castTo(this=%s, t=%s)\n", toChars(), t->toChars());
+#if 0
+    printf("Expression::castTo(this=%s, type=%s, t=%s)\n",
+	toChars(), type->toChars(), t->toChars());
+#endif
+    if (type == t)
+	return this;
+    Expression *e = this;
+    Type *tb = t->toBasetype();
+    Type *typeb = type->toBasetype();
+    if (tb != typeb)
+    {
+	// Do (type *) cast of (type [dim])
+	if (tb->ty == Tpointer &&
+	    typeb->ty == Tsarray
+	   )
+	{
+	    //printf("Converting [dim] to *\n");
+
+	    if (typeb->size(loc) == 0)
+		e = new NullExp(loc);
+	    else
+		e = new AddrExp(loc, e);
+	}
+#if 0
+	else if (tb->ty == Tdelegate && type->ty != Tdelegate)
+	{
+	    TypeDelegate *td = (TypeDelegate *)tb;
+	    TypeFunction *tf = (TypeFunction *)td->nextOf();
+	    return toDelegate(sc, tf->nextOf());
+	}
+#endif
+	else
+	{
+	    if (typeb->ty == Tstruct)
+	    {   TypeStruct *ts = (TypeStruct *)typeb;
+		if (!(tb->ty == Tstruct && ts->sym == ((TypeStruct *)tb)->sym) &&
+		    ts->sym->aliasthis)
+		{   /* Forward the cast to our alias this member, rewrite to:
+		     *   cast(to)e1.aliasthis
+		     */
+		    Expression *e1 = new DotIdExp(loc, this, ts->sym->aliasthis->ident);
+		    Expression *e = new CastExp(loc, e1, tb);
+		    e = e->semantic(sc);
+		    return e;
+		}
+	    }
+	    else if (typeb->ty == Tclass)
+	    {   TypeClass *ts = (TypeClass *)typeb;
+		if (tb->ty != Tclass &&
+		    ts->sym->aliasthis)
+		{   /* Forward the cast to our alias this member, rewrite to:
+		     *   cast(to)e1.aliasthis
+		     */
+		    Expression *e1 = new DotIdExp(loc, this, ts->sym->aliasthis->ident);
+		    Expression *e = new CastExp(loc, e1, tb);
+		    e = e->semantic(sc);
+		    return e;
+		}
+	    }
+	    e = new CastExp(loc, e, tb);
+	}
+    }
+    else
+    {
+	e = e->copy();	// because of COW for assignment to e->type
+    }
+    assert(e != this);
+    e->type = t;
+    //printf("Returning: %s\n", e->toChars());
+    return e;
+}
+
+
+Expression *RealExp::castTo(Scope *sc, Type *t)
+{   Expression *e = this;
+    if (type != t)
+    {
+	if ((type->isreal() && t->isreal()) ||
+	    (type->isimaginary() && t->isimaginary())
+	   )
+	{   e = copy();
+	    e->type = t;
+	}
+	else
+	    e = Expression::castTo(sc, t);
+    }
+    return e;
+}
+
+
+Expression *ComplexExp::castTo(Scope *sc, Type *t)
+{   Expression *e = this;
+    if (type != t)
+    {
+	if (type->iscomplex() && t->iscomplex())
+	{   e = copy();
+	    e->type = t;
+	}
+	else
+	    e = Expression::castTo(sc, t);
+    }
+    return e;
+}
+
+
+Expression *NullExp::castTo(Scope *sc, Type *t)
+{   NullExp *e;
+    Type *tb;
+
+    //printf("NullExp::castTo(t = %p)\n", t);
+    if (type == t)
+    {
+	committed = 1;
+	return this;
+    }
+    e = (NullExp *)copy();
+    e->committed = 1;
+    tb = t->toBasetype();
+    e->type = type->toBasetype();
+    if (tb != e->type)
+    {
+	// NULL implicitly converts to any pointer type or dynamic array
+	if (e->type->ty == Tpointer && e->type->nextOf()->ty == Tvoid &&
+	    (tb->ty == Tpointer || tb->ty == Tarray || tb->ty == Taarray ||
+	     tb->ty == Tdelegate))
+	{
+#if 0
+	    if (tb->ty == Tdelegate)
+	    {   TypeDelegate *td = (TypeDelegate *)tb;
+		TypeFunction *tf = (TypeFunction *)td->nextOf();
+
+		if (!tf->varargs &&
+		    !(tf->arguments && tf->arguments->dim)
+		   )
+		{
+		    return Expression::castTo(sc, t);
+		}
+	    }
+#endif
+	}
+	else
+	{
+	    return e->Expression::castTo(sc, t);
+	}
+    }
+    e->type = t;
+    return e;
+}
+
+Expression *StringExp::castTo(Scope *sc, Type *t)
+{
+    /* This follows copy-on-write; any changes to 'this'
+     * will result in a copy.
+     * The this->string member is considered immutable.
+     */
+    StringExp *se;
+    Type *tb;
+    int copied = 0;
+
+    //printf("StringExp::castTo(t = %s), '%s' committed = %d\n", t->toChars(), toChars(), committed);
+
+    if (!committed && t->ty == Tpointer && t->nextOf()->ty == Tvoid)
+    {
+	error("cannot convert string literal to void*");
+    }
+
+    se = this;
+    if (!committed)
+    {   se = (StringExp *)copy();
+	se->committed = 1;
+	copied = 1;
+    }
+
+    if (type == t)
+    {
+	return se;
+    }
+
+    tb = t->toBasetype();
+    //printf("\ttype = %s\n", type->toChars());
+    if (tb->ty == Tdelegate && type->toBasetype()->ty != Tdelegate)
+	return Expression::castTo(sc, t);
+
+    Type *typeb = type->toBasetype();
+    if (typeb == tb)
+    {
+	if (!copied)
+	{   se = (StringExp *)copy();
+	    copied = 1;
+	}
+	se->type = t;
+	return se;
+    }
+
+    if (committed && tb->ty == Tsarray && typeb->ty == Tarray)
+    {
+	se = (StringExp *)copy();
+	se->sz = tb->nextOf()->size();
+	se->len = (len * sz) / se->sz;
+	se->committed = 1;
+	se->type = t;
+	return se;
+    }
+
+    if (tb->ty != Tsarray && tb->ty != Tarray && tb->ty != Tpointer)
+    {	if (!copied)
+	{   se = (StringExp *)copy();
+	    copied = 1;
+	}
+	goto Lcast;
+    }
+    if (typeb->ty != Tsarray && typeb->ty != Tarray && typeb->ty != Tpointer)
+    {	if (!copied)
+	{   se = (StringExp *)copy();
+	    copied = 1;
+	}
+	goto Lcast;
+    }
+
+    if (typeb->nextOf()->size() == tb->nextOf()->size())
+    {
+	if (!copied)
+	{   se = (StringExp *)copy();
+	    copied = 1;
+	}
+	if (tb->ty == Tsarray)
+	    goto L2;	// handle possible change in static array dimension
+	se->type = t;
+	return se;
+    }
+
+    if (committed)
+	goto Lcast;
+
+#define X(tf,tt)	((tf) * 256 + (tt))
+    {
+    OutBuffer buffer;
+    size_t newlen = 0;
+    int tfty = typeb->nextOf()->toBasetype()->ty;
+    int ttty = tb->nextOf()->toBasetype()->ty;
+    switch (X(tfty, ttty))
+    {
+	case X(Tchar, Tchar):
+	case X(Twchar,Twchar):
+	case X(Tdchar,Tdchar):
+	    break;
+
+	case X(Tchar, Twchar):
+	    for (size_t u = 0; u < len;)
+	    {	unsigned c;
+		const char *p = utf_decodeChar((unsigned char *)se->string, len, &u, &c);
+		if (p)
+		    error("%s", p);
+		else
+		    buffer.writeUTF16(c);
+	    }
+	    newlen = buffer.offset / 2;
+	    buffer.writeUTF16(0);
+	    goto L1;
+
+	case X(Tchar, Tdchar):
+	    for (size_t u = 0; u < len;)
+	    {	unsigned c;
+		const char *p = utf_decodeChar((unsigned char *)se->string, len, &u, &c);
+		if (p)
+		    error("%s", p);
+		buffer.write4(c);
+		newlen++;
+	    }
+	    buffer.write4(0);
+	    goto L1;
+
+	case X(Twchar,Tchar):
+	    for (size_t u = 0; u < len;)
+	    {	unsigned c;
+		const char *p = utf_decodeWchar((unsigned short *)se->string, len, &u, &c);
+		if (p)
+		    error("%s", p);
+		else
+		    buffer.writeUTF8(c);
+	    }
+	    newlen = buffer.offset;
+	    buffer.writeUTF8(0);
+	    goto L1;
+
+	case X(Twchar,Tdchar):
+	    for (size_t u = 0; u < len;)
+	    {	unsigned c;
+		const char *p = utf_decodeWchar((unsigned short *)se->string, len, &u, &c);
+		if (p)
+		    error("%s", p);
+		buffer.write4(c);
+		newlen++;
+	    }
+	    buffer.write4(0);
+	    goto L1;
+
+	case X(Tdchar,Tchar):
+	    for (size_t u = 0; u < len; u++)
+	    {
+		unsigned c = ((unsigned *)se->string)[u];
+		if (!utf_isValidDchar(c))
+		    error("invalid UCS-32 char \\U%08x", c);
+		else
+		    buffer.writeUTF8(c);
+		newlen++;
+	    }
+	    newlen = buffer.offset;
+	    buffer.writeUTF8(0);
+	    goto L1;
+
+	case X(Tdchar,Twchar):
+	    for (size_t u = 0; u < len; u++)
+	    {
+		unsigned c = ((unsigned *)se->string)[u];
+		if (!utf_isValidDchar(c))
+		    error("invalid UCS-32 char \\U%08x", c);
+		else
+		    buffer.writeUTF16(c);
+		newlen++;
+	    }
+	    newlen = buffer.offset / 2;
+	    buffer.writeUTF16(0);
+	    goto L1;
+
+	L1:
+	    if (!copied)
+	    {   se = (StringExp *)copy();
+		copied = 1;
+	    }
+	    se->string = buffer.extractData();
+	    se->len = newlen;
+	    se->sz = tb->nextOf()->size();
+	    break;
+
+	default:
+	    assert(typeb->nextOf()->size() != tb->nextOf()->size());
+	    goto Lcast;
+    }
+    }
+#undef X
+L2:
+    assert(copied);
+
+    // See if need to truncate or extend the literal
+    if (tb->ty == Tsarray)
+    {
+	int dim2 = ((TypeSArray *)tb)->dim->toInteger();
+
+	//printf("dim from = %d, to = %d\n", se->len, dim2);
+
+	// Changing dimensions
+	if (dim2 != se->len)
+	{
+	    // Copy when changing the string literal
+	    unsigned newsz = se->sz;
+	    void *s;
+	    int d;
+
+	    d = (dim2 < se->len) ? dim2 : se->len;
+	    s = (unsigned char *)mem.malloc((dim2 + 1) * newsz);
+	    memcpy(s, se->string, d * newsz);
+	    // Extend with 0, add terminating 0
+	    memset((char *)s + d * newsz, 0, (dim2 + 1 - d) * newsz);
+	    se->string = s;
+	    se->len = dim2;
+	}
+    }
+    se->type = t;
+    return se;
+
+Lcast:
+    Expression *e = new CastExp(loc, se, t);
+    e->type = t;	// so semantic() won't be run on e
+    return e;
+}
+
+Expression *AddrExp::castTo(Scope *sc, Type *t)
+{
+    Type *tb;
+
+#if 0
+    printf("AddrExp::castTo(this=%s, type=%s, t=%s)\n",
+	toChars(), type->toChars(), t->toChars());
+#endif
+    Expression *e = this;
+
+    tb = t->toBasetype();
+    type = type->toBasetype();
+    if (tb != type)
+    {
+	// Look for pointers to functions where the functions are overloaded.
+
+	if (e1->op == TOKoverloadset &&
+	    (t->ty == Tpointer || t->ty == Tdelegate) && t->nextOf()->ty == Tfunction)
+	{   OverExp *eo = (OverExp *)e1;
+	    FuncDeclaration *f = NULL;
+	    for (int i = 0; i < eo->vars->a.dim; i++)
+	    {   Dsymbol *s = (Dsymbol *)eo->vars->a.data[i];
+		FuncDeclaration *f2 = s->isFuncDeclaration();
+		assert(f2);
+		if (f2->overloadExactMatch(t->nextOf(), m))
+		{   if (f)
+			/* Error if match in more than one overload set,
+			 * even if one is a 'better' match than the other.
+			 */
+			ScopeDsymbol::multiplyDefined(loc, f, f2);
+		    else
+			f = f2;
+		}
+	    }
+	    if (f)
+	    {	f->tookAddressOf++;
+		SymOffExp *se = new SymOffExp(loc, f, 0, 0);
+		se->semantic(sc);
+		// Let SymOffExp::castTo() do the heavy lifting
+		return se->castTo(sc, t);
+	    }
+	}
+
+
+	if (type->ty == Tpointer && type->nextOf()->ty == Tfunction &&
+	    tb->ty == Tpointer && tb->nextOf()->ty == Tfunction &&
+	    e1->op == TOKvar)
+	{
+	    VarExp *ve = (VarExp *)e1;
+	    FuncDeclaration *f = ve->var->isFuncDeclaration();
+	    if (f)
+	    {
+		assert(0);	// should be SymOffExp instead
+		f = f->overloadExactMatch(tb->nextOf(), m);
+		if (f)
+		{
+		    e = new VarExp(loc, f);
+		    e->type = f->type;
+		    e = new AddrExp(loc, e);
+		    e->type = t;
+		    return e;
+		}
+	    }
+	}
+	e = Expression::castTo(sc, t);
+    }
+    e->type = t;
+    return e;
+}
+
+
+Expression *TupleExp::castTo(Scope *sc, Type *t)
+{   TupleExp *e = (TupleExp *)copy();
+    e->exps = (Expressions *)exps->copy();
+    for (size_t i = 0; i < e->exps->dim; i++)
+    {   Expression *ex = (Expression *)e->exps->data[i];
+	ex = ex->castTo(sc, t);
+	e->exps->data[i] = (void *)ex;
+    }
+    return e;
+}
+
+
+Expression *ArrayLiteralExp::castTo(Scope *sc, Type *t)
+{
+#if 0
+    printf("ArrayLiteralExp::castTo(this=%s, type=%s, => %s)\n",
+	toChars(), type->toChars(), t->toChars());
+#endif
+    if (type == t)
+	return this;
+    ArrayLiteralExp *e = this;
+    Type *typeb = type->toBasetype();
+    Type *tb = t->toBasetype();
+    if ((tb->ty == Tarray || tb->ty == Tsarray) &&
+	(typeb->ty == Tarray || typeb->ty == Tsarray) &&
+	// Not trying to convert non-void[] to void[]
+	!(tb->nextOf()->toBasetype()->ty == Tvoid && typeb->nextOf()->toBasetype()->ty != Tvoid))
+    {
+	if (tb->ty == Tsarray)
+	{   TypeSArray *tsa = (TypeSArray *)tb;
+	    if (elements->dim != tsa->dim->toInteger())
+		goto L1;
+	}
+
+	e = (ArrayLiteralExp *)copy();
+	e->elements = (Expressions *)elements->copy();
+	for (int i = 0; i < elements->dim; i++)
+	{   Expression *ex = (Expression *)elements->data[i];
+	    ex = ex->castTo(sc, tb->nextOf());
+	    e->elements->data[i] = (void *)ex;
+	}
+	e->type = t;
+	return e;
+    }
+    if (tb->ty == Tpointer && typeb->ty == Tsarray)
+    {
+	Type *tp = typeb->nextOf()->pointerTo();
+	if (!tp->equals(e->type))
+	{   e = (ArrayLiteralExp *)copy();
+	    e->type = tp;
+	}
+    }
+L1:
+    return e->Expression::castTo(sc, t);
+}
+
+Expression *AssocArrayLiteralExp::castTo(Scope *sc, Type *t)
+{
+    if (type == t)
+	return this;
+    AssocArrayLiteralExp *e = this;
+    Type *typeb = type->toBasetype();
+    Type *tb = t->toBasetype();
+    if (tb->ty == Taarray && typeb->ty == Taarray &&
+	tb->nextOf()->toBasetype()->ty != Tvoid)
+    {
+	e = (AssocArrayLiteralExp *)copy();
+	e->keys = (Expressions *)keys->copy();
+	e->values = (Expressions *)values->copy();
+	assert(keys->dim == values->dim);
+	for (size_t i = 0; i < keys->dim; i++)
+	{   Expression *ex = (Expression *)values->data[i];
+	    ex = ex->castTo(sc, tb->nextOf());
+	    e->values->data[i] = (void *)ex;
+
+	    ex = (Expression *)keys->data[i];
+	    ex = ex->castTo(sc, ((TypeAArray *)tb)->index);
+	    e->keys->data[i] = (void *)ex;
+	}
+	e->type = t;
+	return e;
+    }
+L1:
+    return e->Expression::castTo(sc, t);
+}
+
+Expression *SymOffExp::castTo(Scope *sc, Type *t)
+{
+#if 0
+    printf("SymOffExp::castTo(this=%s, type=%s, t=%s)\n",
+	toChars(), type->toChars(), t->toChars());
+#endif
+    if (type == t && hasOverloads == 0)
+	return this;
+    Expression *e;
+    Type *tb = t->toBasetype();
+    Type *typeb = type->toBasetype();
+    if (tb != typeb)
+    {
+	// Look for pointers to functions where the functions are overloaded.
+	FuncDeclaration *f;
+
+	if (hasOverloads &&
+	    typeb->ty == Tpointer && typeb->nextOf()->ty == Tfunction &&
+	    (tb->ty == Tpointer || tb->ty == Tdelegate) && tb->nextOf()->ty == Tfunction)
+	{
+	    f = var->isFuncDeclaration();
+	    if (f)
+	    {
+		f = f->overloadExactMatch(tb->nextOf(), m);
+		if (f)
+		{
+		    if (tb->ty == Tdelegate && f->needThis() && hasThis(sc))
+		    {
+			e = new DelegateExp(loc, new ThisExp(loc), f);
+			e = e->semantic(sc);
+		    }
+		    else if (tb->ty == Tdelegate && f->isNested())
+		    {
+			e = new DelegateExp(loc, new IntegerExp(0), f);
+			e = e->semantic(sc);
+		    }
+		    else
+		    {
+			e = new SymOffExp(loc, f, 0);
+			e->type = t;
+		    }
+		    f->tookAddressOf++;
+		    return e;
+		}
+	    }
+	}
+	e = Expression::castTo(sc, t);
+    }
+    else
+    {	e = copy();
+	e->type = t;
+	((SymOffExp *)e)->hasOverloads = 0;
+    }
+    return e;
+}
+
+Expression *DelegateExp::castTo(Scope *sc, Type *t)
+{
+#if 0
+    printf("DelegateExp::castTo(this=%s, type=%s, t=%s)\n",
+	toChars(), type->toChars(), t->toChars());
+#endif
+    static char msg[] = "cannot form delegate due to covariant return type";
+
+    Expression *e = this;
+    Type *tb = t->toBasetype();
+    Type *typeb = type->toBasetype();
+    if (tb != typeb)
+    {
+	// Look for delegates to functions where the functions are overloaded.
+	FuncDeclaration *f;
+
+	if (typeb->ty == Tdelegate && typeb->nextOf()->ty == Tfunction &&
+	    tb->ty == Tdelegate && tb->nextOf()->ty == Tfunction)
+	{
+	    if (func)
+	    {
+		f = func->overloadExactMatch(tb->nextOf(), m);
+		if (f)
+		{   int offset;
+		    if (f->tintro && f->tintro->nextOf()->isBaseOf(f->type->nextOf(), &offset) && offset)
+			error("%s", msg);
+		    f->tookAddressOf++;
+		    e = new DelegateExp(loc, e1, f);
+		    e->type = t;
+		    return e;
+		}
+		if (func->tintro)
+		    error("%s", msg);
+	    }
+	}
+	e = Expression::castTo(sc, t);
+    }
+    else
+    {	int offset;
+
+	func->tookAddressOf++;
+	if (func->tintro && func->tintro->nextOf()->isBaseOf(func->type->nextOf(), &offset) && offset)
+	    error("%s", msg);
+	e = copy();
+	e->type = t;
+    }
+    return e;
+}
+
+Expression *CondExp::castTo(Scope *sc, Type *t)
+{
+    Expression *e = this;
+
+    if (type != t)
+    {
+	if (1 || e1->op == TOKstring || e2->op == TOKstring)
+	{   e = new CondExp(loc, econd, e1->castTo(sc, t), e2->castTo(sc, t));
+	    e->type = t;
+	}
+	else
+	    e = Expression::castTo(sc, t);
+    }
+    return e;
+}
+
+/* ==================== ====================== */
+
+/****************************************
+ * Scale addition/subtraction to/from pointer.
+ */
+
+Expression *BinExp::scaleFactor(Scope *sc)
+{   d_uns64 stride;
+    Type *t1b = e1->type->toBasetype();
+    Type *t2b = e2->type->toBasetype();
+
+    if (t1b->ty == Tpointer && t2b->isintegral())
+    {   // Need to adjust operator by the stride
+	// Replace (ptr + int) with (ptr + (int * stride))
+	Type *t = Type::tptrdiff_t;
+
+	stride = t1b->nextOf()->size(loc);
+	if (!t->equals(t2b))
+	    e2 = e2->castTo(sc, t);
+	e2 = new MulExp(loc, e2, new IntegerExp(0, stride, t));
+	e2->type = t;
+	type = e1->type;
+    }
+    else if (t2b->ty == Tpointer && t1b->isintegral())
+    {   // Need to adjust operator by the stride
+	// Replace (int + ptr) with (ptr + (int * stride))
+	Type *t = Type::tptrdiff_t;
+	Expression *e;
+
+	stride = t2b->nextOf()->size(loc);
+	if (!t->equals(t1b))
+	    e = e1->castTo(sc, t);
+	else
+	    e = e1;
+	e = new MulExp(loc, e, new IntegerExp(0, stride, t));
+	e->type = t;
+	type = e2->type;
+	e1 = e2;
+	e2 = e;
+    }
+    return this;
+}
+
+/**************************************
+ * Combine types.
+ * Output:
+ *	*pt	merged type, if *pt is not NULL
+ *	*pe1	rewritten e1
+ *	*pe2	rewritten e2
+ * Returns:
+ *	!=0	success
+ *	0	failed
+ */
+
+int typeMerge(Scope *sc, Expression *e, Type **pt, Expression **pe1, Expression **pe2)
+{
+    //printf("typeMerge() %s op %s\n", (*pe1)->toChars(), (*pe2)->toChars());
+    //dump(0);
+
+    Expression *e1 = (*pe1)->integralPromotions(sc);
+    Expression *e2 = (*pe2)->integralPromotions(sc);
+
+    Type *t1 = e1->type;
+    Type *t2 = e2->type;
+    assert(t1);
+    Type *t = t1;
+
+    //if (t1) printf("\tt1 = %s\n", t1->toChars());
+    //if (t2) printf("\tt2 = %s\n", t2->toChars());
+#ifdef DEBUG
+    if (!t2) printf("\te2 = '%s'\n", e2->toChars());
+#endif
+    assert(t2);
+
+    Type *t1b = t1->toBasetype();
+    Type *t2b = t2->toBasetype();
+
+    TY ty = (TY)Type::impcnvResult[t1b->ty][t2b->ty];
+    if (ty != Terror)
+    {	TY ty1;
+	TY ty2;
+
+	ty1 = (TY)Type::impcnvType1[t1b->ty][t2b->ty];
+	ty2 = (TY)Type::impcnvType2[t1b->ty][t2b->ty];
+
+	if (t1b->ty == ty1)	// if no promotions
+	{
+	    if (t1 == t2)
+	    {
+		t = t1;
+		goto Lret;
+	    }
+
+	    if (t1b == t2b)
+	    {
+		t = t1b;
+		goto Lret;
+	    }
+	}
+
+	t = Type::basic[ty];
+
+	t1 = Type::basic[ty1];
+	t2 = Type::basic[ty2];
+	e1 = e1->castTo(sc, t1);
+	e2 = e2->castTo(sc, t2);
+	//printf("after typeCombine():\n");
+	//dump(0);
+	//printf("ty = %d, ty1 = %d, ty2 = %d\n", ty, ty1, ty2);
+	goto Lret;
+    }
+
+    t1 = t1b;
+    t2 = t2b;
+
+Lagain:
+    if (t1 == t2)
+    {
+    }
+    else if (t1->ty == Tpointer && t2->ty == Tpointer)
+    {
+	// Bring pointers to compatible type
+	Type *t1n = t1->nextOf();
+	Type *t2n = t2->nextOf();
+
+	if (t1n == t2n)
+	    ;
+	else if (t1n->ty == Tvoid)	// pointers to void are always compatible
+	    t = t2;
+	else if (t2n->ty == Tvoid)
+	    ;
+	else if (t1n->mod != t2n->mod)
+	{
+	    t1 = t1n->mutableOf()->constOf()->pointerTo();
+	    t2 = t2n->mutableOf()->constOf()->pointerTo();
+	    t = t1;
+	    goto Lagain;
+	}
+	else if (t1n->ty == Tclass && t2n->ty == Tclass)
+	{   ClassDeclaration *cd1 = t1n->isClassHandle();
+	    ClassDeclaration *cd2 = t2n->isClassHandle();
+	    int offset;
+
+	    if (cd1->isBaseOf(cd2, &offset))
+	    {
+		if (offset)
+		    e2 = e2->castTo(sc, t);
+	    }
+	    else if (cd2->isBaseOf(cd1, &offset))
+	    {
+		t = t2;
+		if (offset)
+		    e1 = e1->castTo(sc, t);
+	    }
+	    else
+		goto Lincompatible;
+	}
+	else
+	    goto Lincompatible;
+    }
+    else if ((t1->ty == Tsarray || t1->ty == Tarray) &&
+	     e2->op == TOKnull && t2->ty == Tpointer && t2->nextOf()->ty == Tvoid)
+    {	/*  (T[n] op void*)
+	 *  (T[] op void*)
+	 */
+	goto Lx1;
+    }
+    else if ((t2->ty == Tsarray || t2->ty == Tarray) &&
+	     e1->op == TOKnull && t1->ty == Tpointer && t1->nextOf()->ty == Tvoid)
+    {	/*  (void* op T[n])
+	 *  (void* op T[])
+	 */
+	goto Lx2;
+    }
+    else if ((t1->ty == Tsarray || t1->ty == Tarray) && t1->implicitConvTo(t2))
+    {
+	goto Lt2;
+    }
+    else if ((t2->ty == Tsarray || t2->ty == Tarray) && t2->implicitConvTo(t1))
+    {
+	goto Lt1;
+    }
+    /* If one is mutable and the other invariant, then retry
+     * with both of them as const
+     */
+    else if ((t1->ty == Tsarray || t1->ty == Tarray || t1->ty == Tpointer) &&
+	     (t2->ty == Tsarray || t2->ty == Tarray || t2->ty == Tpointer) &&
+	     t1->nextOf()->mod != t2->nextOf()->mod
+	    )
+    {
+	if (t1->ty == Tpointer)
+	    t1 = t1->nextOf()->mutableOf()->constOf()->pointerTo();
+	else
+	    t1 = t1->nextOf()->mutableOf()->constOf()->arrayOf();
+
+	if (t2->ty == Tpointer)
+	    t2 = t2->nextOf()->mutableOf()->constOf()->pointerTo();
+	else
+	    t2 = t2->nextOf()->mutableOf()->constOf()->arrayOf();
+	t = t1;
+	goto Lagain;
+    }
+    else if (t1->ty == Tclass || t2->ty == Tclass)
+    {
+	while (1)
+	{
+	    int i1 = e2->implicitConvTo(t1);
+	    int i2 = e1->implicitConvTo(t2);
+
+	    if (i1 && i2)
+	    {
+		// We have the case of class vs. void*, so pick class
+		if (t1->ty == Tpointer)
+		    i1 = 0;
+		else if (t2->ty == Tpointer)
+		    i2 = 0;
+	    }
+
+	    if (i2)
+	    {
+		goto Lt2;
+	    }
+	    else if (i1)
+	    {
+		goto Lt1;
+	    }
+	    else if (t1->ty == Tclass && t2->ty == Tclass)
+	    {	TypeClass *tc1 = (TypeClass *)t1;
+		TypeClass *tc2 = (TypeClass *)t2;
+
+		/* Pick 'tightest' type
+		 */
+		ClassDeclaration *cd1 = tc1->sym->baseClass;
+		ClassDeclaration *cd2 = tc2->sym->baseClass;
+
+		if (cd1 && cd2)
+		{   t1 = cd1->type;
+		    t2 = cd2->type;
+		}
+		else if (cd1)
+		    t1 = cd1->type;
+		else if (cd2)
+		    t2 = cd2->type;
+		else
+		    goto Lincompatible;
+	    }
+	    else
+		goto Lincompatible;
+	}
+    }
+    else if (t1->ty == Tstruct && t2->ty == Tstruct)
+    {
+	if (((TypeStruct *)t1)->sym != ((TypeStruct *)t2)->sym)
+	    goto Lincompatible;
+    }
+    else if ((e1->op == TOKstring || e1->op == TOKnull) && e1->implicitConvTo(t2))
+    {
+	goto Lt2;
+    }
+    else if ((e2->op == TOKstring || e2->op == TOKnull) && e2->implicitConvTo(t1))
+    {
+	goto Lt1;
+    }
+    else if (t1->ty == Tsarray && t2->ty == Tsarray &&
+	     e2->implicitConvTo(t1->nextOf()->arrayOf()))
+    {
+     Lx1:
+	t = t1->nextOf()->arrayOf();
+	e1 = e1->castTo(sc, t);
+	e2 = e2->castTo(sc, t);
+    }
+    else if (t1->ty == Tsarray && t2->ty == Tsarray &&
+	     e1->implicitConvTo(t2->nextOf()->arrayOf()))
+    {
+     Lx2:
+	t = t2->nextOf()->arrayOf();
+	e1 = e1->castTo(sc, t);
+	e2 = e2->castTo(sc, t);
+    }
+    else if (t1->isintegral() && t2->isintegral())
+    {
+	assert(0);
+    }
+    else if (e1->op == TOKslice && t1->ty == Tarray &&
+	     e2->implicitConvTo(t1->nextOf()))
+    {	// T[] op T
+	e2 = e2->castTo(sc, t1->nextOf());
+	t = t1->nextOf()->arrayOf();
+    }
+    else if (e2->op == TOKslice && t2->ty == Tarray &&
+	     e1->implicitConvTo(t2->nextOf()))
+    {	// T op T[]
+	e1 = e1->castTo(sc, t2->nextOf());
+	t = t2->nextOf()->arrayOf();
+
+	//printf("test %s\n", e->toChars());
+	e1 = e1->optimize(WANTvalue);
+	if (e && e->isCommutative() && e1->isConst())
+	{   /* Swap operands to minimize number of functions generated
+	     */
+	    //printf("swap %s\n", e->toChars());
+	    Expression *tmp = e1;
+	    e1 = e2;
+	    e2 = tmp;
+	}
+    }
+    else
+    {
+     Lincompatible:
+	return 0;
+    }
+Lret:
+    if (!*pt)
+	*pt = t;
+    *pe1 = e1;
+    *pe2 = e2;
+#if 0
+    printf("-typeMerge() %s op %s\n", e1->toChars(), e2->toChars());
+    if (e1->type) printf("\tt1 = %s\n", e1->type->toChars());
+    if (e2->type) printf("\tt2 = %s\n", e2->type->toChars());
+    printf("\ttype = %s\n", t->toChars());
+#endif
+    //dump(0);
+    return 1;
+
+
+Lt1:
+    e2 = e2->castTo(sc, t1);
+    t = t1;
+    goto Lret;
+
+Lt2:
+    e1 = e1->castTo(sc, t2);
+    t = t2;
+    goto Lret;
+}
+
+/************************************
+ * Bring leaves to common type.
+ */
+
+Expression *BinExp::typeCombine(Scope *sc)
+{
+    Type *t1 = e1->type->toBasetype();
+    Type *t2 = e2->type->toBasetype();
+
+    if (op == TOKmin || op == TOKadd)
+    {
+	if (t1 == t2 && (t1->ty == Tstruct || t1->ty == Tclass))
+	    goto Lerror;
+    }
+
+    if (!typeMerge(sc, this, &type, &e1, &e2))
+	goto Lerror;
+    return this;
+
+Lerror:
+    incompatibleTypes();
+    type = Type::terror;
+    e1 = new ErrorExp();
+    e2 = new ErrorExp();
+    return this;
+}
+
+/***********************************
+ * Do integral promotions (convertchk).
+ * Don't convert <array of> to <pointer to>
+ */
+
+Expression *Expression::integralPromotions(Scope *sc)
+{
+    Expression *e = this;
+
+    //printf("integralPromotions %s %s\n", e->toChars(), e->type->toChars());
+    switch (type->toBasetype()->ty)
+    {
+	case Tvoid:
+	    error("void has no value");
+	    break;
+
+	case Tint8:
+	case Tuns8:
+	case Tint16:
+	case Tuns16:
+	case Tbit:
+	case Tbool:
+	case Tchar:
+	case Twchar:
+	    e = e->castTo(sc, Type::tint32);
+	    break;
+
+	case Tdchar:
+	    e = e->castTo(sc, Type::tuns32);
+	    break;
+    }
+    return e;
+}
+
+/***********************************
+ * See if both types are arrays that can be compared
+ * for equality. Return !=0 if so.
+ * If they are arrays, but incompatible, issue error.
+ * This is to enable comparing things like an immutable
+ * array with a mutable one.
+ */
+
+int arrayTypeCompatible(Loc loc, Type *t1, Type *t2)
+{
+    t1 = t1->toBasetype();
+    t2 = t2->toBasetype();
+
+    if ((t1->ty == Tarray || t1->ty == Tsarray || t1->ty == Tpointer) &&
+	(t2->ty == Tarray || t2->ty == Tsarray || t2->ty == Tpointer))
+    {
+	if (t1->nextOf()->implicitConvTo(t2->nextOf()) < MATCHconst &&
+	    t2->nextOf()->implicitConvTo(t1->nextOf()) < MATCHconst &&
+	    (t1->nextOf()->ty != Tvoid && t2->nextOf()->ty != Tvoid))
+	{
+	    error(loc, "array equality comparison type mismatch, %s vs %s", t1->toChars(), t2->toChars());
+	}
+	return 1;
+    }
+    return 0;
+}
--- a/dmd2/class.c	Mon Jun 01 01:28:18 2009 +0200
+++ b/dmd2/class.c	Mon Jun 01 19:02:20 2009 +0100
@@ -1,1420 +1,1434 @@
-
-// 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 <stdlib.h>
-#include <assert.h>
-
-#include "root.h"
-#include "mem.h"
-
-#include "enum.h"
-#include "init.h"
-#include "attrib.h"
-#include "declaration.h"
-#include "aggregate.h"
-#include "id.h"
-#include "mtype.h"
-#include "scope.h"
-#include "module.h"
-#include "expression.h"
-#include "statement.h"
-
-/********************************* ClassDeclaration ****************************/
-
-ClassDeclaration *ClassDeclaration::classinfo;
-ClassDeclaration *ClassDeclaration::object;
-
-ClassDeclaration::ClassDeclaration(Loc loc, Identifier *id, BaseClasses *baseclasses)
-    : AggregateDeclaration(loc, id)
-{
-    static char msg[] = "only object.d can define this reserved class name";
-
-    if (baseclasses)
-	this->baseclasses = *baseclasses;
-    baseClass = NULL;
-
-    interfaces_dim = 0;
-    interfaces = NULL;
-
-    vtblInterfaces = NULL;
-
-    //printf("ClassDeclaration(%s), dim = %d\n", id->toChars(), this->baseclasses.dim);
-
-    // For forward references
-    type = new TypeClass(this);
-    handle = type;
-
-    staticCtor = NULL;
-    staticDtor = NULL;
-
-    vtblsym = NULL;
-    vclassinfo = NULL;
-
-    if (id)
-    {	// Look for special class names
-
-	if (id == Id::__sizeof || id == Id::alignof || id == Id::mangleof)
-	    error("illegal class name");
-
-	// BUG: What if this is the wrong TypeInfo, i.e. it is nested?
-	if (id->toChars()[0] == 'T')
-	{
-	    if (id == Id::TypeInfo)
-	    {	if (Type::typeinfo)
-		    Type::typeinfo->error("%s", msg);
-		Type::typeinfo = this;
-	    }
-
-	    if (id == Id::TypeInfo_Class)
-	    {	if (Type::typeinfoclass)
-		    Type::typeinfoclass->error("%s", msg);
-		Type::typeinfoclass = this;
-	    }
-
-	    if (id == Id::TypeInfo_Interface)
-	    {	if (Type::typeinfointerface)
-		    Type::typeinfointerface->error("%s", msg);
-		Type::typeinfointerface = this;
-	    }
-
-	    if (id == Id::TypeInfo_Struct)
-	    {	if (Type::typeinfostruct)
-		    Type::typeinfostruct->error("%s", msg);
-		Type::typeinfostruct = this;
-	    }
-
-	    if (id == Id::TypeInfo_Typedef)
-	    {	if (Type::typeinfotypedef)
-		    Type::typeinfotypedef->error("%s", msg);
-		Type::typeinfotypedef = this;
-	    }
-
-	    if (id == Id::TypeInfo_Pointer)
-	    {	if (Type::typeinfopointer)
-		    Type::typeinfopointer->error("%s", msg);
-		Type::typeinfopointer = this;
-	    }
-
-	    if (id == Id::TypeInfo_Array)
-	    {	if (Type::typeinfoarray)
-		    Type::typeinfoarray->error("%s", msg);
-		Type::typeinfoarray = this;
-	    }
-
-	    if (id == Id::TypeInfo_StaticArray)
-	    {	//if (Type::typeinfostaticarray)
-		    //Type::typeinfostaticarray->error("%s", msg);
-		Type::typeinfostaticarray = this;
-	    }
-
-	    if (id == Id::TypeInfo_AssociativeArray)
-	    {	if (Type::typeinfoassociativearray)
-		    Type::typeinfoassociativearray->error("%s", msg);
-		Type::typeinfoassociativearray = this;
-	    }
-
-	    if (id == Id::TypeInfo_Enum)
-	    {	if (Type::typeinfoenum)
-		    Type::typeinfoenum->error("%s", msg);
-		Type::typeinfoenum = this;
-	    }
-
-	    if (id == Id::TypeInfo_Function)
-	    {	if (Type::typeinfofunction)
-		    Type::typeinfofunction->error("%s", msg);
-		Type::typeinfofunction = this;
-	    }
-
-	    if (id == Id::TypeInfo_Delegate)
-	    {	if (Type::typeinfodelegate)
-		    Type::typeinfodelegate->error("%s", msg);
-		Type::typeinfodelegate = this;
-	    }
-
-	    if (id == Id::TypeInfo_Tuple)
-	    {	if (Type::typeinfotypelist)
-		    Type::typeinfotypelist->error("%s", msg);
-		Type::typeinfotypelist = this;
-	    }
-
-#if DMDV2
-	    if (id == Id::TypeInfo_Const)
-	    {	if (Type::typeinfoconst)
-		    Type::typeinfoconst->error("%s", msg);
-		Type::typeinfoconst = this;
-	    }
-
-	    if (id == Id::TypeInfo_Invariant)
-	    {	if (Type::typeinfoinvariant)
-		    Type::typeinfoinvariant->error("%s", msg);
-		Type::typeinfoinvariant = this;
-	    }
-#endif
-	}
-
-	if (id == Id::Object)
-	{   if (object)
-		object->error("%s", msg);
-	    object = this;
-	}
-
-	if (id == Id::ClassInfo)
-	{   if (classinfo)
-		classinfo->error("%s", msg);
-	    classinfo = this;
-	}
-
-	if (id == Id::ModuleInfo)
-	{   if (Module::moduleinfo)
-		Module::moduleinfo->error("%s", msg);
-	    Module::moduleinfo = this;
-	}
-    }
-
-    com = 0;
-    isauto = 0;
-    isabstract = 0;
-    isnested = 0;
-    vthis = NULL;
-    inuse = 0;
-}
-
-Dsymbol *ClassDeclaration::syntaxCopy(Dsymbol *s)
-{
-    ClassDeclaration *cd;
-
-    //printf("ClassDeclaration::syntaxCopy('%s')\n", toChars());
-    if (s)
-	cd = (ClassDeclaration *)s;
-    else
-	cd = new ClassDeclaration(loc, ident, NULL);
-
-    cd->storage_class |= storage_class;
-
-    cd->baseclasses.setDim(this->baseclasses.dim);
-    for (int i = 0; i < cd->baseclasses.dim; i++)
-    {
-	BaseClass *b = (BaseClass *)this->baseclasses.data[i];
-	BaseClass *b2 = new BaseClass(b->type->syntaxCopy(), b->protection);
-	cd->baseclasses.data[i] = b2;
-    }
-
-    ScopeDsymbol::syntaxCopy(cd);
-    return cd;
-}
-
-void ClassDeclaration::semantic(Scope *sc)
-{   int i;
-    unsigned offset;
-
-    //printf("ClassDeclaration::semantic(%s), type = %p, sizeok = %d, this = %p\n", toChars(), type, sizeok, this);
-    //printf("\tparent = %p, '%s'\n", sc->parent, sc->parent ? sc->parent->toChars() : "");
-    //printf("sc->stc = %x\n", sc->stc);
-
-    //{ static int n;  if (++n == 20) *(char*)0=0; }
-
-    if (!ident)		// if anonymous class
-    {	const char *id = "__anonclass";
-
-	ident = Identifier::generateId(id);
-    }
-
-    if (!scope)
-    {
-	if (!parent && sc->parent && !sc->parent->isModule())
-	    parent = sc->parent;
-
-	type = type->semantic(loc, sc);
-	handle = handle->semantic(loc, sc);
-    }
-    if (!members)			// if forward reference
-    {	//printf("\tclass '%s' is forward referenced\n", toChars());
-	return;
-    }
-    if (symtab)
-    {	if (!scope)
-	{   //printf("\tsemantic for '%s' is already completed\n", toChars());
-	    return;		// semantic() already completed
-	}
-    }
-    else
-	symtab = new DsymbolTable();
-
-    Scope *scx = NULL;
-    if (scope)
-    {	sc = scope;
-	scx = scope;		// save so we don't make redundant copies
-	scope = NULL;
-    }
-#ifdef IN_GCC
-    methods.setDim(0);
-#endif
-
-    if (sc->stc & STCdeprecated)
-    {
-	isdeprecated = 1;
-    }
-
-    if (sc->linkage == LINKcpp)
-	error("cannot create C++ classes");
-
-    // Expand any tuples in baseclasses[]
-    for (i = 0; i < baseclasses.dim; )
-    {	BaseClass *b = (BaseClass *)baseclasses.data[i];
-	b->type = b->type->semantic(loc, sc);
-	Type *tb = b->type->toBasetype();
-
-	if (tb->ty == Ttuple)
-	{   TypeTuple *tup = (TypeTuple *)tb;
-	    enum PROT protection = b->protection;
-	    baseclasses.remove(i);
-	    size_t dim = Argument::dim(tup->arguments);
-	    for (size_t j = 0; j < dim; j++)
-	    {	Argument *arg = Argument::getNth(tup->arguments, j);
-		b = new BaseClass(arg->type, protection);
-		baseclasses.insert(i + j, b);
-	    }
-	}
-	else
-	    i++;
-    }
-
-    // See if there's a base class as first in baseclasses[]
-    if (baseclasses.dim)
-    {	TypeClass *tc;
-	BaseClass *b;
-	Type *tb;
-
-	b = (BaseClass *)baseclasses.data[0];
-	//b->type = b->type->semantic(loc, sc);
-	tb = b->type->toBasetype();
-	if (tb->ty != Tclass)
-	{   error("base type must be class or interface, not %s", b->type->toChars());
-	    baseclasses.remove(0);
-	}
-	else
-	{
-	    tc = (TypeClass *)(tb);
-
-	    if (tc->sym->isDeprecated())
-	    {
-		if (!isDeprecated())
-		{
-		    // Deriving from deprecated class makes this one deprecated too
-		    isdeprecated = 1;
-
-		    tc->checkDeprecated(loc, sc);
-		}
-	    }
-
-	    if (tc->sym->isInterfaceDeclaration())
-		;
-	    else
-	    {
-		for (ClassDeclaration *cdb = tc->sym; cdb; cdb = cdb->baseClass)
-		{
-		    if (cdb == this)
-		    {
-			error("circular inheritance");
-			baseclasses.remove(0);
-			goto L7;
-		    }
-		}
-		if (!tc->sym->symtab || tc->sym->scope || tc->sym->sizeok == 0)
-		{
-		    //error("forward reference of base class %s", baseClass->toChars());
-		    // Forward reference of base class, try again later
-		    //printf("\ttry later, forward reference of base class %s\n", tc->sym->toChars());
-		    scope = scx ? scx : new Scope(*sc);
-		    scope->setNoFree();
-		    scope->module->addDeferredSemantic(this);
-		    return;
-		}
-		else
-		{   baseClass = tc->sym;
-		    b->base = baseClass;
-		}
-	     L7: ;
-	    }
-	}
-    }
-
-    // Treat the remaining entries in baseclasses as interfaces
-    // Check for errors, handle forward references
-    for (i = (baseClass ? 1 : 0); i < baseclasses.dim; )
-    {	TypeClass *tc;
-	BaseClass *b;
-	Type *tb;
-
-	b = (BaseClass *)baseclasses.data[i];
-	b->type = b->type->semantic(loc, sc);
-	tb = b->type->toBasetype();
-	if (tb->ty == Tclass)
-	    tc = (TypeClass *)tb;
-	else
-	    tc = NULL;
-	if (!tc || !tc->sym->isInterfaceDeclaration())
-	{
-	    error("base type must be interface, not %s", b->type->toChars());
-	    baseclasses.remove(i);
-	    continue;
-	}
-	else
-	{
-	    if (tc->sym->isDeprecated())
-	    {
-		if (!isDeprecated())
-		{
-		    // Deriving from deprecated class makes this one deprecated too
-		    isdeprecated = 1;
-
-		    tc->checkDeprecated(loc, sc);
-		}
-	    }
-
-	    // Check for duplicate interfaces
-	    for (size_t j = (baseClass ? 1 : 0); j < i; j++)
-	    {
-		BaseClass *b2 = (BaseClass *)baseclasses.data[j];
-		if (b2->base == tc->sym)
-		    error("inherits from duplicate interface %s", b2->base->toChars());
-	    }
-
-	    b->base = tc->sym;
-	    if (!b->base->symtab || b->base->scope)
-	    {
-		//error("forward reference of base class %s", baseClass->toChars());
-		// Forward reference of base, try again later
-		//printf("\ttry later, forward reference of base %s\n", baseClass->toChars());
-		scope = scx ? scx : new Scope(*sc);
-		scope->setNoFree();
-		scope->module->addDeferredSemantic(this);
-		return;
-	    }
-	}
-	i++;
-    }
-
-
-    // If no base class, and this is not an Object, use Object as base class
-    if (!baseClass && ident != Id::Object)
-    {
-	// BUG: what if Object is redefined in an inner scope?
-	Type *tbase = new TypeIdentifier(0, Id::Object);
-	BaseClass *b;
-	TypeClass *tc;
-	Type *bt;
-
-	if (!object)
-	{
-	    error("missing or corrupt object.d");
-	    fatal();
-	}
-	bt = tbase->semantic(loc, sc)->toBasetype();
-	b = new BaseClass(bt, PROTpublic);
-	baseclasses.shift(b);
-	assert(b->type->ty == Tclass);
-	tc = (TypeClass *)(b->type);
-	baseClass = tc->sym;
-	assert(!baseClass->isInterfaceDeclaration());
-	b->base = baseClass;
-    }
-
-    interfaces_dim = baseclasses.dim;
-    interfaces = (BaseClass **)baseclasses.data;
-
-
-    if (baseClass)
-    {
-	if (baseClass->storage_class & STCfinal)
-	    error("cannot inherit from final class %s", baseClass->toChars());
-
-	interfaces_dim--;
-	interfaces++;
-
-	// Copy vtbl[] from base class
-	vtbl.setDim(baseClass->vtbl.dim);
-	memcpy(vtbl.data, baseClass->vtbl.data, sizeof(void *) * vtbl.dim);
-
-	// Inherit properties from base class
-	com = baseClass->isCOMclass();
-	isauto = baseClass->isauto;
-	vthis = baseClass->vthis;
-	storage_class |= baseClass->storage_class & (STCconst | STCinvariant);
-    }
-    else
-    {
-	// No base class, so this is the root of the class hierarchy
-	vtbl.setDim(0);
-	vtbl.push(this);		// leave room for classinfo as first member
-    }
-
-    protection = sc->protection;
-    storage_class |= sc->stc;
-
-    if (sizeok == 0)
-    {
-	interfaceSemantic(sc);
-
-	for (i = 0; i < members->dim; i++)
-	{
-	    Dsymbol *s = (Dsymbol *)members->data[i];
-	    s->addMember(sc, this, 1);
-	}
-
-	/* If this is a nested class, add the hidden 'this'
-	 * member which is a pointer to the enclosing scope.
-	 */
-	if (vthis)		// if inheriting from nested class
-	{   // Use the base class's 'this' member
-	    isnested = 1;
-	    if (storage_class & STCstatic)
-		error("static class cannot inherit from nested class %s", baseClass->toChars());
-	    if (toParent2() != baseClass->toParent2())
-	    {
-		if (toParent2())
-		{
-		    error("is nested within %s, but super class %s is nested within %s",
-			toParent2()->toChars(),
-			baseClass->toChars(),
-			baseClass->toParent2()->toChars());
-		}
-		else
-		{
-		    error("is not nested, but super class %s is nested within %s",
-			baseClass->toChars(),
-			baseClass->toParent2()->toChars());
-		}
-		isnested = 0;
-	    }
-	}
-	else if (!(storage_class & STCstatic))
-	{   Dsymbol *s = toParent2();
-	    if (s)
-	    {
-		ClassDeclaration *cd = s->isClassDeclaration();
-		FuncDeclaration *fd = s->isFuncDeclaration();
-
-
-		if (cd || fd)
-		{   isnested = 1;
-		    Type *t;
-		    if (cd)
-			t = cd->type;
-		    else if (fd)
-		    {	AggregateDeclaration *ad = fd->isMember2();
-			if (ad)
-			    t = ad->handle;
-			else
-			{
-			    t = new TypePointer(Type::tvoid);
-			    t = t->semantic(0, sc);
-			}
-		    }
-		    else
-			assert(0);
-		    assert(!vthis);
-		    vthis = new ThisDeclaration(t);
-		    members->push(vthis);
-		}
-	    }
-	}
-    }
-
-    if (storage_class & (STCauto | STCscope))
-	isauto = 1;
-    if (storage_class & STCabstract)
-	isabstract = 1;
-    if (storage_class & STCinvariant)
-	type = type->invariantOf();
-    else if (storage_class & STCconst)
-	type = type->constOf();
-
-    sc = sc->push(this);
-    sc->stc &= ~(STCfinal | STCauto | STCscope | STCstatic |
-		 STCabstract | STCdeprecated | STCconst | STCinvariant | STCtls);
-    sc->stc |= storage_class & (STCconst | STCinvariant);
-    sc->parent = this;
-    sc->inunion = 0;
-
-    if (isCOMclass())
-	sc->linkage = LINKwindows;
-    sc->protection = PROTpublic;
-    sc->explicitProtection = 0;
-    sc->structalign = 8;
-    structalign = sc->structalign;
-    if (baseClass)
-    {	sc->offset = baseClass->structsize;
-	alignsize = baseClass->alignsize;
-//	if (isnested)
-//	    sc->offset += PTRSIZE;	// room for uplevel context pointer
-    }
-    else
-    {	sc->offset = PTRSIZE * 2;	// allow room for __vptr and __monitor
-	alignsize = PTRSIZE;
-    }
-    structsize = sc->offset;
-    Scope scsave = *sc;
-    int members_dim = members->dim;
-    sizeok = 0;
-    for (i = 0; i < members_dim; i++)
-    {
-	Dsymbol *s = (Dsymbol *)members->data[i];
-	s->semantic(sc);
-    }
-
-    if (sizeok == 2)
-    {	// semantic() failed because of forward references.
-	// Unwind what we did, and defer it for later
-	fields.setDim(0);
-	structsize = 0;
-	alignsize = 0;
-	structalign = 0;
-
-	sc = sc->pop();
-
-	scope = scx ? scx : new Scope(*sc);
-	scope->setNoFree();
-	scope->module->addDeferredSemantic(this);
-
-	//printf("\tsemantic('%s') failed due to forward references\n", toChars());
-	return;
-    }
-
-    //printf("\tsemantic('%s') successful\n", toChars());
-
-    structsize = sc->offset;
-    //members->print();
-
-    /* Look for special member functions.
-     * They must be in this class, not in a base class.
-     */
-    ctor = (CtorDeclaration *)search(0, Id::ctor, 0);
-    if (ctor && (ctor->toParent() != this || !ctor->isCtorDeclaration()))
-	ctor = NULL;
-
-//    dtor = (DtorDeclaration *)search(Id::dtor, 0);
-//    if (dtor && dtor->toParent() != this)
-//	dtor = NULL;
-
-//    inv = (InvariantDeclaration *)search(Id::classInvariant, 0);
-//    if (inv && inv->toParent() != this)
-//	inv = NULL;
-
-    // Can be in base class
-    aggNew    = (NewDeclaration *)search(0, Id::classNew, 0);
-    aggDelete = (DeleteDeclaration *)search(0, Id::classDelete, 0);
-
-    // If this class has no constructor, but base class does, create
-    // a constructor:
-    //    this() { }
-    if (!ctor && baseClass && baseClass->ctor)
-    {
-	//printf("Creating default this(){} for class %s\n", toChars());
-	ctor = new CtorDeclaration(loc, 0, NULL, 0);
-	ctor->fbody = new CompoundStatement(0, new Statements());
-	members->push(ctor);
-	ctor->addMember(sc, this, 1);
-	*sc = scsave;	// why? What about sc->nofree?
-	sc->offset = structsize;
-	ctor->semantic(sc);
-	defaultCtor = ctor;
-    }
-
-#if 0
-    if (baseClass)
-    {	if (!aggDelete)
-	    aggDelete = baseClass->aggDelete;
-	if (!aggNew)
-	    aggNew = baseClass->aggNew;
-    }
-#endif
-
-    // Allocate instance of each new interface
-    for (i = 0; i < vtblInterfaces->dim; i++)
-    {
-	BaseClass *b = (BaseClass *)vtblInterfaces->data[i];
-	unsigned thissize = PTRSIZE;
-
-	alignmember(structalign, thissize, &sc->offset);
-	assert(b->offset == 0);
-	b->offset = sc->offset;
-
-	// Take care of single inheritance offsets
-	while (b->baseInterfaces_dim)
-	{
-	    b = &b->baseInterfaces[0];
-	    b->offset = sc->offset;
-	}
-
-	sc->offset += thissize;
-	if (alignsize < thissize)
-	    alignsize = thissize;
-    }
-    structsize = sc->offset;
-    sizeok = 1;
-    Module::dprogress++;
-
-    dtor = buildDtor(sc);
-
-    sc->pop();
-
-#if 0 // Do not call until toObjfile() because of forward references
-    // Fill in base class vtbl[]s
-    for (i = 0; i < vtblInterfaces->dim; i++)
-    {
-	BaseClass *b = (BaseClass *)vtblInterfaces->data[i];
-
-	//b->fillVtbl(this, &b->vtbl, 1);
-    }
-#endif
-    //printf("-ClassDeclaration::semantic(%s), type = %p\n", toChars(), type);
-}
-
-void ClassDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{
-    if (!isAnonymous())
-    {
-	buf->printf("%s ", kind());
-	buf->writestring(toChars());
-	if (baseclasses.dim)
-	    buf->writestring(" : ");
-    }
-    for (int i = 0; i < baseclasses.dim; i++)
-    {
-	BaseClass *b = (BaseClass *)baseclasses.data[i];
-
-	if (i)
-	    buf->writeByte(',');
-	//buf->writestring(b->base->ident->toChars());
-	b->type->toCBuffer(buf, NULL, hgs);
-    }
-    buf->writenl();
-    buf->writeByte('{');
-    buf->writenl();
-    for (int i = 0; i < members->dim; i++)
-    {
-	Dsymbol *s = (Dsymbol *)members->data[i];
-
-	buf->writestring("    ");
-	s->toCBuffer(buf, hgs);
-    }
-    buf->writestring("}");
-    buf->writenl();
-}
-
-#if 0
-void ClassDeclaration::defineRef(Dsymbol *s)
-{
-    ClassDeclaration *cd;
-
-    AggregateDeclaration::defineRef(s);
-    cd = s->isClassDeclaration();
-    baseType = cd->baseType;
-    cd->baseType = NULL;
-}
-#endif
-
-/*********************************************
- * Determine if 'this' is a base class of cd.
- * This is used to detect circular inheritance only.
- */
-
-int ClassDeclaration::isBaseOf2(ClassDeclaration *cd)
-{
-    if (!cd)
-	return 0;
-    //printf("ClassDeclaration::isBaseOf2(this = '%s', cd = '%s')\n", toChars(), cd->toChars());
-    for (int i = 0; i < cd->baseclasses.dim; i++)
-    {	BaseClass *b = (BaseClass *)cd->baseclasses.data[i];
-
-	if (b->base == this || isBaseOf2(b->base))
-	    return 1;
-    }
-    return 0;
-}
-
-/*******************************************
- * Determine if 'this' is a base class of cd.
- */
-
-int ClassDeclaration::isBaseOf(ClassDeclaration *cd, int *poffset)
-{
-    //printf("ClassDeclaration::isBaseOf(this = '%s', cd = '%s')\n", toChars(), cd->toChars());
-    if (poffset)
-	*poffset = 0;
-    while (cd)
-    {
-	if (this == cd->baseClass)
-	    return 1;
-
-	/* cd->baseClass might not be set if cd is forward referenced.
-	 */
-	if (!cd->baseClass && cd->baseclasses.dim && !cd->isInterfaceDeclaration())
-	{
-	    cd->error("base class is forward referenced by %s", toChars());
-	}
-
-	cd = cd->baseClass;
-    }
-    return 0;
-}
-
-Dsymbol *ClassDeclaration::search(Loc loc, Identifier *ident, int flags)
-{
-    Dsymbol *s;
-
-    //printf("%s.ClassDeclaration::search('%s')\n", toChars(), ident->toChars());
-    if (scope)
-	semantic(scope);
-
-    if (!members || !symtab || scope)
-    {	error("is forward referenced when looking for '%s'", ident->toChars());
-	//*(char*)0=0;
-	return NULL;
-    }
-
-    s = ScopeDsymbol::search(loc, ident, flags);
-    if (!s)
-    {
-	// Search bases classes in depth-first, left to right order
-
-	int i;
-
-	for (i = 0; i < baseclasses.dim; i++)
-	{
-	    BaseClass *b = (BaseClass *)baseclasses.data[i];
-
-	    if (b->base)
-	    {
-		if (!b->base->symtab)
-		    error("base %s is forward referenced", b->base->ident->toChars());
-		else
-		{
-		    s = b->base->search(loc, ident, flags);
-		    if (s == this)	// happens if s is nested in this and derives from this
-			s = NULL;
-		    else if (s)
-			break;
-		}
-	    }
-	}
-    }
-    return s;
-}
-
-/**********************************************************
- * fd is in the vtbl[] for this class.
- * Return 1 if function is hidden (not findable through search).
- */
-
-#if DMDV2
-int isf(void *param, FuncDeclaration *fd)
-{
-    //printf("param = %p, fd = %p %s\n", param, fd, fd->toChars());
-    return param == fd;
-}
-
-int ClassDeclaration::isFuncHidden(FuncDeclaration *fd)
-{
-    //printf("ClassDeclaration::isFuncHidden(class = %s, fd = %s)\n", toChars(), fd->toChars());
-    Dsymbol *s = search(0, fd->ident, 4|2);
-    if (!s)
-    {	//printf("not found\n");
-	/* Because, due to a hack, if there are multiple definitions
-	 * of fd->ident, NULL is returned.
-	 */
-	return 0;
-    }
-    s = s->toAlias();
-    OverloadSet *os = s->isOverloadSet();
-    if (os)
-    {
-	for (int i = 0; i < os->a.dim; i++)
-	{   Dsymbol *s = (Dsymbol *)os->a.data[i];
-	    FuncDeclaration *f2 = s->isFuncDeclaration();
-	    if (f2 && overloadApply(f2, &isf, fd))
-		return 0;
-	}
-	return 1;
-    }
-    else
-    {
-	FuncDeclaration *fdstart = s->isFuncDeclaration();
-	//printf("%s fdstart = %p\n", s->kind(), fdstart);
-	return !overloadApply(fdstart, &isf, fd);
-    }
-}
-#endif
-
-/****************
- * Find virtual function matching identifier and type.
- * Used to build virtual function tables for interface implementations.
- */
-
-FuncDeclaration *ClassDeclaration::findFunc(Identifier *ident, TypeFunction *tf)
-{
-    //printf("ClassDeclaration::findFunc(%s, %s) %s\n", ident->toChars(), tf->toChars(), toChars());
-
-    ClassDeclaration *cd = this;
-    Array *vtbl = &cd->vtbl;
-    while (1)
-    {
-	for (size_t i = 0; i < vtbl->dim; i++)
-	{
-	    FuncDeclaration *fd = (FuncDeclaration *)vtbl->data[i];
-
-	    //printf("\t[%d] = %s\n", i, fd->toChars());
-	    if (ident == fd->ident &&
-		//tf->equals(fd->type)
-		fd->type->covariant(tf) == 1
-	       )
-	    {   //printf("\t\tfound\n");
-		return fd;
-	    }
-	    //else printf("\t\t%d\n", fd->type->covariant(tf));
-	}
-	if (!cd)
-	    break;
-	vtbl = &cd->vtblFinal;
-	cd = cd->baseClass;
-    }
-
-    return NULL;
-}
-
-void ClassDeclaration::interfaceSemantic(Scope *sc)
-{
-    InterfaceDeclaration *id = isInterfaceDeclaration();
-
-    vtblInterfaces = new BaseClasses();
-    vtblInterfaces->reserve(interfaces_dim);
-
-    for (size_t i = 0; i < interfaces_dim; i++)
-    {
-	BaseClass *b = interfaces[i];
-
-	// If this is an interface, and it derives from a COM interface,
-	// then this is a COM interface too.
-	if (b->base->isCOMinterface())
-	    com = 1;
-
-	if (b->base->isCPPinterface() && id)
-	    id->cpp = 1;
-
-	vtblInterfaces->push(b);
-	b->copyBaseInterfaces(vtblInterfaces);
-    }
-}
-
-/****************************************
- */
-
-int ClassDeclaration::isCOMclass()
-{
-    return com;
-}
-
-int ClassDeclaration::isCOMinterface()
-{
-    return 0;
-}
-
-int ClassDeclaration::isCPPinterface()
-{
-    return 0;
-}
-
-
-/****************************************
- */
-
-int ClassDeclaration::isAbstract()
-{
-    if (isabstract)
-	return TRUE;
-    for (int i = 1; i < vtbl.dim; i++)
-    {
-	FuncDeclaration *fd = ((Dsymbol *)vtbl.data[i])->isFuncDeclaration();
-
-	//printf("\tvtbl[%d] = %p\n", i, fd);
-	if (!fd || fd->isAbstract())
-	{
-	    isabstract |= 1;
-	    return TRUE;
-	}
-    }
-    return FALSE;
-}
-
-
-/****************************************
- * Returns !=0 if there's an extra member which is the 'this'
- * pointer to the enclosing context (enclosing class or function)
- */
-
-int ClassDeclaration::isNested()
-{
-    return isnested;
-}
-
-/****************************************
- * Determine if slot 0 of the vtbl[] is reserved for something else.
- * For class objects, yes, this is where the classinfo ptr goes.
- * For COM interfaces, no.
- * For non-COM interfaces, yes, this is where the Interface ptr goes.
- */
-
-int ClassDeclaration::vtblOffset()
-{
-    return 1;
-}
-
-/****************************************
- */
-
-const char *ClassDeclaration::kind()
-{
-    return "class";
-}
-
-/****************************************
- */
-
-void ClassDeclaration::addLocalClass(ClassDeclarations *aclasses)
-{
-    aclasses->push(this);
-}
-
-/********************************* InterfaceDeclaration ****************************/
-
-InterfaceDeclaration::InterfaceDeclaration(Loc loc, Identifier *id, BaseClasses *baseclasses)
-    : ClassDeclaration(loc, id, baseclasses)
-{
-    com = 0;
-    cpp = 0;
-    if (id == Id::IUnknown)	// IUnknown is the root of all COM interfaces
-    {	com = 1;
-	cpp = 1;		// IUnknown is also a C++ interface
-    }
-}
-
-Dsymbol *InterfaceDeclaration::syntaxCopy(Dsymbol *s)
-{
-    InterfaceDeclaration *id;
-
-    if (s)
-	id = (InterfaceDeclaration *)s;
-    else
-	id = new InterfaceDeclaration(loc, ident, NULL);
-
-    ClassDeclaration::syntaxCopy(id);
-    return id;
-}
-
-void InterfaceDeclaration::semantic(Scope *sc)
-{   int i;
-
-    //printf("InterfaceDeclaration::semantic(%s), type = %p\n", toChars(), type);
-    if (inuse)
-	return;
-    if (!scope)
-    {	type = type->semantic(loc, sc);
-	handle = handle->semantic(loc, sc);
-    }
-    if (!members)			// if forward reference
-    {	//printf("\tinterface '%s' is forward referenced\n", toChars());
-	return;
-    }
-    if (symtab)			// if already done
-    {	if (!scope)
-	    return;
-    }
-    else
-	symtab = new DsymbolTable();
-
-    Scope *scx = NULL;
-    if (scope)
-    {	sc = scope;
-	scx = scope;		// save so we don't make redundant copies
-	scope = NULL;
-    }
-
-    if (sc->stc & STCdeprecated)
-    {
-	isdeprecated = 1;
-    }
-
-    // Expand any tuples in baseclasses[]
-    for (i = 0; i < baseclasses.dim; )
-    {	BaseClass *b = (BaseClass *)baseclasses.data[0];
-	b->type = b->type->semantic(loc, sc);
-	Type *tb = b->type->toBasetype();
-
-	if (tb->ty == Ttuple)
-	{   TypeTuple *tup = (TypeTuple *)tb;
-	    enum PROT protection = b->protection;
-	    baseclasses.remove(i);
-	    size_t dim = Argument::dim(tup->arguments);
-	    for (size_t j = 0; j < dim; j++)
-	    {	Argument *arg = Argument::getNth(tup->arguments, j);
-		b = new BaseClass(arg->type, protection);
-		baseclasses.insert(i + j, b);
-	    }
-	}
-	else
-	    i++;
-    }
-
-    if (!baseclasses.dim && sc->linkage == LINKcpp)
-	cpp = 1;
-
-    // Check for errors, handle forward references
-    for (i = 0; i < baseclasses.dim; )
-    {	TypeClass *tc;
-	BaseClass *b;
-	Type *tb;
-
-	b = (BaseClass *)baseclasses.data[i];
-	b->type = b->type->semantic(loc, sc);
-	tb = b->type->toBasetype();
-	if (tb->ty == Tclass)
-	    tc = (TypeClass *)tb;
-	else
-	    tc = NULL;
-	if (!tc || !tc->sym->isInterfaceDeclaration())
-	{
-	    error("base type must be interface, not %s", b->type->toChars());
-	    baseclasses.remove(i);
-	    continue;
-	}
-	else
-	{
-	    // Check for duplicate interfaces
-	    for (size_t j = 0; j < i; j++)
-	    {
-		BaseClass *b2 = (BaseClass *)baseclasses.data[j];
-		if (b2->base == tc->sym)
-		    error("inherits from duplicate interface %s", b2->base->toChars());
-	    }
-
-	    b->base = tc->sym;
-	    if (b->base == this || isBaseOf2(b->base))
-	    {
-		error("circular inheritance of interface");
-		baseclasses.remove(i);
-		continue;
-	    }
-	    if (!b->base->symtab || b->base->scope || b->base->inuse)
-	    {
-		//error("forward reference of base class %s", baseClass->toChars());
-		// Forward reference of base, try again later
-		//printf("\ttry later, forward reference of base %s\n", b->base->toChars());
-		scope = scx ? scx : new Scope(*sc);
-		scope->setNoFree();
-		scope->module->addDeferredSemantic(this);
-		return;
-	    }
-	}
-#if 0
-	// Inherit const/invariant from base class
-	storage_class |= b->base->storage_class & (STCconst | STCinvariant);
-#endif
-	i++;
-    }
-
-    interfaces_dim = baseclasses.dim;
-    interfaces = (BaseClass **)baseclasses.data;
-
-    interfaceSemantic(sc);
-
-    if (vtblOffset())
-	vtbl.push(this);		// leave room at vtbl[0] for classinfo
-
-    // Cat together the vtbl[]'s from base interfaces
-    for (i = 0; i < interfaces_dim; i++)
-    {	BaseClass *b = interfaces[i];
-
-	// Skip if b has already appeared
-	for (int k = 0; k < i; k++)
-	{
-	    if (b == interfaces[i])
-		goto Lcontinue;
-	}
-
-	// Copy vtbl[] from base class
-	if (b->base->vtblOffset())
-	{   int d = b->base->vtbl.dim;
-	    if (d > 1)
-	    {
-		vtbl.reserve(d - 1);
-		for (int j = 1; j < d; j++)
-		    vtbl.push(b->base->vtbl.data[j]);
-	    }
-	}
-	else
-	{
-	    vtbl.append(&b->base->vtbl);
-	}
-
-      Lcontinue:
-	;
-    }
-
-    protection = sc->protection;
-    storage_class |= sc->stc & (STCconst | STCinvariant);
-
-    for (i = 0; i < members->dim; i++)
-    {
-	Dsymbol *s = (Dsymbol *)members->data[i];
-	s->addMember(sc, this, 1);
-    }
-
-    sc = sc->push(this);
-    sc->stc &= ~(STCfinal | STCauto | STCscope | STCstatic |
-                 STCabstract | STCdeprecated | STCconst | STCinvariant | STCtls);
-    sc->stc |= storage_class & (STCconst | STCinvariant);
-    sc->parent = this;
-    if (isCOMinterface())
-	sc->linkage = LINKwindows;
-    else if (isCPPinterface())
-	sc->linkage = LINKcpp;
-    sc->structalign = 8;
-    structalign = sc->structalign;
-    sc->offset = PTRSIZE * 2;
-    inuse++;
-    for (i = 0; i < members->dim; i++)
-    {
-	Dsymbol *s = (Dsymbol *)members->data[i];
-	s->semantic(sc);
-    }
-    inuse--;
-    //members->print();
-    sc->pop();
-    //printf("-InterfaceDeclaration::semantic(%s), type = %p\n", toChars(), type);
-}
-
-
-/*******************************************
- * Determine if 'this' is a base class of cd.
- * (Actually, if it is an interface supported by cd)
- * Output:
- *	*poffset	offset to start of class
- *			OFFSET_RUNTIME	must determine offset at runtime
- * Returns:
- *	0	not a base
- *	1	is a base
- */
-
-int InterfaceDeclaration::isBaseOf(ClassDeclaration *cd, int *poffset)
-{
-    unsigned j;
-
-    //printf("%s.InterfaceDeclaration::isBaseOf(cd = '%s')\n", toChars(), cd->toChars());
-    assert(!baseClass);
-    for (j = 0; j < cd->interfaces_dim; j++)
-    {
-	BaseClass *b = cd->interfaces[j];
-
-	//printf("\tbase %s\n", b->base->toChars());
-	if (this == b->base)
-	{
-	    //printf("\tfound at offset %d\n", b->offset);
-	    if (poffset)
-	    {	*poffset = b->offset;
-		if (j && cd->isInterfaceDeclaration())
-		    *poffset = OFFSET_RUNTIME;
-	    }
-	    return 1;
-	}
-	if (isBaseOf(b, poffset))
-	{   if (j && poffset && cd->isInterfaceDeclaration())
-		*poffset = OFFSET_RUNTIME;
-	    return 1;
-	}
-    }
-
-    if (cd->baseClass && isBaseOf(cd->baseClass, poffset))
-	return 1;
-
-    if (poffset)
-	*poffset = 0;
-    return 0;
-}
-
-
-int InterfaceDeclaration::isBaseOf(BaseClass *bc, int *poffset)
-{
-    //printf("%s.InterfaceDeclaration::isBaseOf(bc = '%s')\n", toChars(), bc->base->toChars());
-    for (unsigned j = 0; j < bc->baseInterfaces_dim; j++)
-    {
-	BaseClass *b = &bc->baseInterfaces[j];
-
-	if (this == b->base)
-	{
-	    if (poffset)
-	    {	*poffset = b->offset;
-	    }
-	    return 1;
-	}
-	if (isBaseOf(b, poffset))
-	{
-	    return 1;
-	}
-    }
-    if (poffset)
-	*poffset = 0;
-    return 0;
-}
-
-/****************************************
- * Determine if slot 0 of the vtbl[] is reserved for something else.
- * For class objects, yes, this is where the ClassInfo ptr goes.
- * For COM interfaces, no.
- * For non-COM interfaces, yes, this is where the Interface ptr goes.
- */
-
-int InterfaceDeclaration::vtblOffset()
-{
-    if (isCOMinterface() || isCPPinterface())
-	return 0;
-    return 1;
-}
-
-int InterfaceDeclaration::isCOMinterface()
-{
-    return com;
-}
-
-int InterfaceDeclaration::isCPPinterface()
-{
-    return cpp;
-}
-
-/*******************************************
- */
-
-const char *InterfaceDeclaration::kind()
-{
-    return "interface";
-}
-
-
-/******************************** BaseClass *****************************/
-
-BaseClass::BaseClass()
-{
-    memset(this, 0, sizeof(BaseClass));
-}
-
-BaseClass::BaseClass(Type *type, enum PROT protection)
-{
-    //printf("BaseClass(this = %p, '%s')\n", this, type->toChars());
-    this->type = type;
-    this->protection = protection;
-    base = NULL;
-    offset = 0;
-
-    baseInterfaces_dim = 0;
-    baseInterfaces = NULL;
-}
-
-/****************************************
- * Fill in vtbl[] for base class based on member functions of class cd.
- * Input:
- *	vtbl		if !=NULL, fill it in
- *	newinstance	!=0 means all entries must be filled in by members
- *			of cd, not members of any base classes of cd.
- * Returns:
- *	!=0 if any entries were filled in by members of cd (not exclusively
- *	by base classes)
- */
-
-int BaseClass::fillVtbl(ClassDeclaration *cd, Array *vtbl, int newinstance)
-{
-    ClassDeclaration *id = base;
-    int j;
-    int result = 0;
-
-    //printf("BaseClass::fillVtbl(this='%s', cd='%s')\n", base->toChars(), cd->toChars());
-    if (vtbl)
-	vtbl->setDim(base->vtbl.dim);
-
-    // first entry is ClassInfo reference
-    for (j = base->vtblOffset(); j < base->vtbl.dim; j++)
-    {
-	FuncDeclaration *ifd = ((Dsymbol *)base->vtbl.data[j])->isFuncDeclaration();
-	FuncDeclaration *fd;
-	TypeFunction *tf;
-
-	//printf("        vtbl[%d] is '%s'\n", j, ifd ? ifd->toChars() : "null");
-
-	assert(ifd);
-	// Find corresponding function in this class
-	tf = (ifd->type->ty == Tfunction) ? (TypeFunction *)(ifd->type) : NULL;
-	fd = cd->findFunc(ifd->ident, tf);
-	if (fd && !fd->isAbstract())
-	{
-	    //printf("            found\n");
-	    // Check that calling conventions match
-	    if (fd->linkage != ifd->linkage)
-		fd->error("linkage doesn't match interface function");
-
-	    // Check that it is current
-	    if (newinstance &&
-		fd->toParent() != cd &&
-		ifd->toParent() == base)
-		cd->error("interface function %s.%s is not implemented",
-		    id->toChars(), ifd->ident->toChars());
-
-	    if (fd->toParent() == cd)
-		result = 1;
-	}
-	else
-	{
-	    //printf("            not found\n");
-	    // BUG: should mark this class as abstract?
-	    if (!cd->isAbstract())
-		cd->error("interface function %s.%s isn't implemented",
-		    id->toChars(), ifd->ident->toChars());
-	    fd = NULL;
-	}
-	if (vtbl)
-	    vtbl->data[j] = fd;
-    }
-
-    return result;
-}
-
-void BaseClass::copyBaseInterfaces(BaseClasses *vtblInterfaces)
-{
-    //printf("+copyBaseInterfaces(), %s\n", base->toChars());
-//    if (baseInterfaces_dim)
-//	return;
-
-    baseInterfaces_dim = base->interfaces_dim;
-    baseInterfaces = (BaseClass *)mem.calloc(baseInterfaces_dim, sizeof(BaseClass));
-
-    //printf("%s.copyBaseInterfaces()\n", base->toChars());
-    for (int i = 0; i < baseInterfaces_dim; i++)
-    {
-	BaseClass *b = &baseInterfaces[i];
-	BaseClass *b2 = base->interfaces[i];
-
-	assert(b2->vtbl.dim == 0);	// should not be filled yet
-	memcpy(b, b2, sizeof(BaseClass));
-
-	if (i)				// single inheritance is i==0
-	    vtblInterfaces->push(b);	// only need for M.I.
-	b->copyBaseInterfaces(vtblInterfaces);
-    }
-    //printf("-copyBaseInterfaces\n");
-}
+
+// 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 <stdlib.h>
+#include <assert.h>
+
+#include "root.h"
+#include "rmem.h"
+
+#include "enum.h"
+#include "init.h"
+#include "attrib.h"
+#include "declaration.h"
+#include "aggregate.h"
+#include "id.h"
+#include "mtype.h"
+#include "scope.h"
+#include "module.h"
+#include "expression.h"
+#include "statement.h"
+
+/********************************* ClassDeclaration ****************************/
+
+ClassDeclaration *ClassDeclaration::classinfo;
+ClassDeclaration *ClassDeclaration::object;
+
+ClassDeclaration::ClassDeclaration(Loc loc, Identifier *id, BaseClasses *baseclasses)
+    : AggregateDeclaration(loc, id)
+{
+    static char msg[] = "only object.d can define this reserved class name";
+
+    if (baseclasses)
+	this->baseclasses = *baseclasses;
+    baseClass = NULL;
+
+    interfaces_dim = 0;
+    interfaces = NULL;
+
+    vtblInterfaces = NULL;
+
+    //printf("ClassDeclaration(%s), dim = %d\n", id->toChars(), this->baseclasses.dim);
+
+    // For forward references
+    type = new TypeClass(this);
+    handle = type;
+
+    staticCtor = NULL;
+    staticDtor = NULL;
+
+#if IN_DMD
+    vtblsym = NULL;
+#endif
+    vclassinfo = NULL;
+
+    if (id)
+    {	// Look for special class names
+
+	if (id == Id::__sizeof || id == Id::alignof || id == Id::mangleof)
+	    error("illegal class name");
+
+	// BUG: What if this is the wrong TypeInfo, i.e. it is nested?
+	if (id->toChars()[0] == 'T')
+	{
+	    if (id == Id::TypeInfo)
+	    {	if (Type::typeinfo)
+		    Type::typeinfo->error("%s", msg);
+		Type::typeinfo = this;
+	    }
+
+	    if (id == Id::TypeInfo_Class)
+	    {	if (Type::typeinfoclass)
+		    Type::typeinfoclass->error("%s", msg);
+		Type::typeinfoclass = this;
+	    }
+
+	    if (id == Id::TypeInfo_Interface)
+	    {	if (Type::typeinfointerface)
+		    Type::typeinfointerface->error("%s", msg);
+		Type::typeinfointerface = this;
+	    }
+
+	    if (id == Id::TypeInfo_Struct)
+	    {	if (Type::typeinfostruct)
+		    Type::typeinfostruct->error("%s", msg);
+		Type::typeinfostruct = this;
+	    }
+
+	    if (id == Id::TypeInfo_Typedef)
+	    {	if (Type::typeinfotypedef)
+		    Type::typeinfotypedef->error("%s", msg);
+		Type::typeinfotypedef = this;
+	    }
+
+	    if (id == Id::TypeInfo_Pointer)
+	    {	if (Type::typeinfopointer)
+		    Type::typeinfopointer->error("%s", msg);
+		Type::typeinfopointer = this;
+	    }
+
+	    if (id == Id::TypeInfo_Array)
+	    {	if (Type::typeinfoarray)
+		    Type::typeinfoarray->error("%s", msg);
+		Type::typeinfoarray = this;
+	    }
+
+	    if (id == Id::TypeInfo_StaticArray)
+	    {	//if (Type::typeinfostaticarray)
+		    //Type::typeinfostaticarray->error("%s", msg);
+		Type::typeinfostaticarray = this;
+	    }
+
+	    if (id == Id::TypeInfo_AssociativeArray)
+	    {	if (Type::typeinfoassociativearray)
+		    Type::typeinfoassociativearray->error("%s", msg);
+		Type::typeinfoassociativearray = this;
+	    }
+
+	    if (id == Id::TypeInfo_Enum)
+	    {	if (Type::typeinfoenum)
+		    Type::typeinfoenum->error("%s", msg);
+		Type::typeinfoenum = this;
+	    }
+
+	    if (id == Id::TypeInfo_Function)
+	    {	if (Type::typeinfofunction)
+		    Type::typeinfofunction->error("%s", msg);
+		Type::typeinfofunction = this;
+	    }
+
+	    if (id == Id::TypeInfo_Delegate)
+	    {	if (Type::typeinfodelegate)
+		    Type::typeinfodelegate->error("%s", msg);
+		Type::typeinfodelegate = this;
+	    }
+
+	    if (id == Id::TypeInfo_Tuple)
+	    {	if (Type::typeinfotypelist)
+		    Type::typeinfotypelist->error("%s", msg);
+		Type::typeinfotypelist = this;
+	    }
+
+#if DMDV2
+	    if (id == Id::TypeInfo_Const)
+	    {	if (Type::typeinfoconst)
+		    Type::typeinfoconst->error("%s", msg);
+		Type::typeinfoconst = this;
+	    }
+
+	    if (id == Id::TypeInfo_Invariant)
+	    {	if (Type::typeinfoinvariant)
+		    Type::typeinfoinvariant->error("%s", msg);
+		Type::typeinfoinvariant = this;
+	    }
+
+	    if (id == Id::TypeInfo_Shared)
+	    {	if (Type::typeinfoshared)
+		    Type::typeinfoshared->error("%s", msg);
+		Type::typeinfoshared = this;
+	    }
+#endif
+	}
+
+	if (id == Id::Object)
+	{   if (object)
+		object->error("%s", msg);
+	    object = this;
+	}
+
+	if (id == Id::ClassInfo)
+	{   if (classinfo)
+		classinfo->error("%s", msg);
+	    classinfo = this;
+	}
+
+	if (id == Id::ModuleInfo)
+	{   if (Module::moduleinfo)
+		Module::moduleinfo->error("%s", msg);
+	    Module::moduleinfo = this;
+	}
+    }
+
+    com = 0;
+    isauto = 0;
+    isabstract = 0;
+    inuse = 0;
+}
+
+Dsymbol *ClassDeclaration::syntaxCopy(Dsymbol *s)
+{
+    ClassDeclaration *cd;
+
+    //printf("ClassDeclaration::syntaxCopy('%s')\n", toChars());
+    if (s)
+	cd = (ClassDeclaration *)s;
+    else
+	cd = new ClassDeclaration(loc, ident, NULL);
+
+    cd->storage_class |= storage_class;
+
+    cd->baseclasses.setDim(this->baseclasses.dim);
+    for (int i = 0; i < cd->baseclasses.dim; i++)
+    {
+	BaseClass *b = (BaseClass *)this->baseclasses.data[i];
+	BaseClass *b2 = new BaseClass(b->type->syntaxCopy(), b->protection);
+	cd->baseclasses.data[i] = b2;
+    }
+
+    ScopeDsymbol::syntaxCopy(cd);
+    return cd;
+}
+
+void ClassDeclaration::semantic(Scope *sc)
+{   int i;
+    unsigned offset;
+
+    //printf("ClassDeclaration::semantic(%s), type = %p, sizeok = %d, this = %p\n", toChars(), type, sizeok, this);
+    //printf("\tparent = %p, '%s'\n", sc->parent, sc->parent ? sc->parent->toChars() : "");
+    //printf("sc->stc = %x\n", sc->stc);
+
+    //{ static int n;  if (++n == 20) *(char*)0=0; }
+
+    if (!ident)		// if anonymous class
+    {	const char *id = "__anonclass";
+
+	ident = Identifier::generateId(id);
+    }
+
+    if (!scope)
+    {
+	if (!parent && sc->parent && !sc->parent->isModule())
+	    parent = sc->parent;
+
+	type = type->semantic(loc, sc);
+	handle = handle->semantic(loc, sc);
+    }
+    if (!members)			// if forward reference
+    {	//printf("\tclass '%s' is forward referenced\n", toChars());
+	return;
+    }
+    if (symtab)
+    {	if (!scope)
+	{   //printf("\tsemantic for '%s' is already completed\n", toChars());
+	    return;		// semantic() already completed
+	}
+    }
+    else
+	symtab = new DsymbolTable();
+
+    Scope *scx = NULL;
+    if (scope)
+    {	sc = scope;
+	scx = scope;		// save so we don't make redundant copies
+	scope = NULL;
+    }
+#ifdef IN_GCC
+    methods.setDim(0);
+#endif
+
+    if (sc->stc & STCdeprecated)
+    {
+	isdeprecated = 1;
+    }
+
+    if (sc->linkage == LINKcpp)
+	error("cannot create C++ classes");
+
+    // Expand any tuples in baseclasses[]
+    for (i = 0; i < baseclasses.dim; )
+    {	BaseClass *b = (BaseClass *)baseclasses.data[i];
+	b->type = b->type->semantic(loc, sc);
+	Type *tb = b->type->toBasetype();
+
+	if (tb->ty == Ttuple)
+	{   TypeTuple *tup = (TypeTuple *)tb;
+	    enum PROT protection = b->protection;
+	    baseclasses.remove(i);
+	    size_t dim = Argument::dim(tup->arguments);
+	    for (size_t j = 0; j < dim; j++)
+	    {	Argument *arg = Argument::getNth(tup->arguments, j);
+		b = new BaseClass(arg->type, protection);
+		baseclasses.insert(i + j, b);
+	    }
+	}
+	else
+	    i++;
+    }
+
+    // See if there's a base class as first in baseclasses[]
+    if (baseclasses.dim)
+    {	TypeClass *tc;
+	BaseClass *b;
+	Type *tb;
+
+	b = (BaseClass *)baseclasses.data[0];
+	//b->type = b->type->semantic(loc, sc);
+	tb = b->type->toBasetype();
+	if (tb->ty != Tclass)
+	{   error("base type must be class or interface, not %s", b->type->toChars());
+	    baseclasses.remove(0);
+	}
+	else
+	{
+	    tc = (TypeClass *)(tb);
+
+	    if (tc->sym->isDeprecated())
+	    {
+		if (!isDeprecated())
+		{
+		    // Deriving from deprecated class makes this one deprecated too
+		    isdeprecated = 1;
+
+		    tc->checkDeprecated(loc, sc);
+		}
+	    }
+
+	    if (tc->sym->isInterfaceDeclaration())
+		;
+	    else
+	    {
+		for (ClassDeclaration *cdb = tc->sym; cdb; cdb = cdb->baseClass)
+		{
+		    if (cdb == this)
+		    {
+			error("circular inheritance");
+			baseclasses.remove(0);
+			goto L7;
+		    }
+		}
+		if (!tc->sym->symtab || tc->sym->scope || tc->sym->sizeok == 0)
+		{
+		    //error("forward reference of base class %s", baseClass->toChars());
+		    // Forward reference of base class, try again later
+		    //printf("\ttry later, forward reference of base class %s\n", tc->sym->toChars());
+		    scope = scx ? scx : new Scope(*sc);
+		    scope->setNoFree();
+		    scope->module->addDeferredSemantic(this);
+		    return;
+		}
+		else
+		{   baseClass = tc->sym;
+		    b->base = baseClass;
+		}
+	     L7: ;
+	    }
+	}
+    }
+
+    // Treat the remaining entries in baseclasses as interfaces
+    // Check for errors, handle forward references
+    for (i = (baseClass ? 1 : 0); i < baseclasses.dim; )
+    {	TypeClass *tc;
+	BaseClass *b;
+	Type *tb;
+
+	b = (BaseClass *)baseclasses.data[i];
+	b->type = b->type->semantic(loc, sc);
+	tb = b->type->toBasetype();
+	if (tb->ty == Tclass)
+	    tc = (TypeClass *)tb;
+	else
+	    tc = NULL;
+	if (!tc || !tc->sym->isInterfaceDeclaration())
+	{
+	    error("base type must be interface, not %s", b->type->toChars());
+	    baseclasses.remove(i);
+	    continue;
+	}
+	else
+	{
+	    if (tc->sym->isDeprecated())
+	    {
+		if (!isDeprecated())
+		{
+		    // Deriving from deprecated class makes this one deprecated too
+		    isdeprecated = 1;
+
+		    tc->checkDeprecated(loc, sc);
+		}
+	    }
+
+	    // Check for duplicate interfaces
+	    for (size_t j = (baseClass ? 1 : 0); j < i; j++)
+	    {
+		BaseClass *b2 = (BaseClass *)baseclasses.data[j];
+		if (b2->base == tc->sym)
+		    error("inherits from duplicate interface %s", b2->base->toChars());
+	    }
+
+	    b->base = tc->sym;
+	    if (!b->base->symtab || b->base->scope)
+	    {
+		//error("forward reference of base class %s", baseClass->toChars());
+		// Forward reference of base, try again later
+		//printf("\ttry later, forward reference of base %s\n", baseClass->toChars());
+		scope = scx ? scx : new Scope(*sc);
+		scope->setNoFree();
+		scope->module->addDeferredSemantic(this);
+		return;
+	    }
+	}
+	i++;
+    }
+
+
+    // If no base class, and this is not an Object, use Object as base class
+    if (!baseClass && ident != Id::Object)
+    {
+	// BUG: what if Object is redefined in an inner scope?
+	Type *tbase = new TypeIdentifier(0, Id::Object);
+	BaseClass *b;
+	TypeClass *tc;
+	Type *bt;
+
+	if (!object)
+	{
+	    error("missing or corrupt object.d");
+	    fatal();
+	}
+	bt = tbase->semantic(loc, sc)->toBasetype();
+	b = new BaseClass(bt, PROTpublic);
+	baseclasses.shift(b);
+	assert(b->type->ty == Tclass);
+	tc = (TypeClass *)(b->type);
+	baseClass = tc->sym;
+	assert(!baseClass->isInterfaceDeclaration());
+	b->base = baseClass;
+    }
+
+    interfaces_dim = baseclasses.dim;
+    interfaces = (BaseClass **)baseclasses.data;
+
+
+    if (baseClass)
+    {
+	if (baseClass->storage_class & STCfinal)
+	    error("cannot inherit from final class %s", baseClass->toChars());
+
+	interfaces_dim--;
+	interfaces++;
+
+	// Copy vtbl[] from base class
+	vtbl.setDim(baseClass->vtbl.dim);
+	memcpy(vtbl.data, baseClass->vtbl.data, sizeof(void *) * vtbl.dim);
+
+	// Inherit properties from base class
+	com = baseClass->isCOMclass();
+	isauto = baseClass->isauto;
+	vthis = baseClass->vthis;
+	storage_class |= baseClass->storage_class & STC_TYPECTOR;
+    }
+    else
+    {
+	// No base class, so this is the root of the class hierarchy
+	vtbl.setDim(0);
+	vtbl.push(this);		// leave room for classinfo as first member
+    }
+
+    protection = sc->protection;
+    storage_class |= sc->stc;
+
+    if (sizeok == 0)
+    {
+	interfaceSemantic(sc);
+
+	for (i = 0; i < members->dim; i++)
+	{
+	    Dsymbol *s = (Dsymbol *)members->data[i];
+	    s->addMember(sc, this, 1);
+	}
+
+	/* If this is a nested class, add the hidden 'this'
+	 * member which is a pointer to the enclosing scope.
+	 */
+	if (vthis)		// if inheriting from nested class
+	{   // Use the base class's 'this' member
+	    isnested = 1;
+	    if (storage_class & STCstatic)
+		error("static class cannot inherit from nested class %s", baseClass->toChars());
+	    if (toParent2() != baseClass->toParent2())
+	    {
+		if (toParent2())
+		{
+		    error("is nested within %s, but super class %s is nested within %s",
+			toParent2()->toChars(),
+			baseClass->toChars(),
+			baseClass->toParent2()->toChars());
+		}
+		else
+		{
+		    error("is not nested, but super class %s is nested within %s",
+			baseClass->toChars(),
+			baseClass->toParent2()->toChars());
+		}
+		isnested = 0;
+	    }
+	}
+	else if (!(storage_class & STCstatic))
+	{   Dsymbol *s = toParent2();
+	    if (s)
+	    {
+		AggregateDeclaration *ad = s->isClassDeclaration();
+		FuncDeclaration *fd = s->isFuncDeclaration();
+
+
+		if (ad || fd)
+		{   isnested = 1;
+		    Type *t;
+		    if (ad)
+			t = ad->handle;
+		    else if (fd)
+		    {	AggregateDeclaration *ad = fd->isMember2();
+			if (ad)
+			    t = ad->handle;
+			else
+			{
+			    t = Type::tvoidptr;
+			}
+		    }
+		    else
+			assert(0);
+		    if (t->ty == Tstruct)	// ref to struct
+			t = Type::tvoidptr;
+		    assert(!vthis);
+		    vthis = new ThisDeclaration(loc, t);
+		    members->push(vthis);
+		}
+	    }
+	}
+    }
+
+    if (storage_class & (STCauto | STCscope))
+	isauto = 1;
+    if (storage_class & STCabstract)
+	isabstract = 1;
+    if (storage_class & STCimmutable)
+	type = type->invariantOf();
+    else if (storage_class & STCconst)
+	type = type->constOf();
+    else if (storage_class & STCshared)
+	type = type->sharedOf();
+
+    sc = sc->push(this);
+    sc->stc &= ~(STCfinal | STCauto | STCscope | STCstatic |
+		 STCabstract | STCdeprecated | STC_TYPECTOR | STCtls | STCgshared);
+    sc->stc |= storage_class & STC_TYPECTOR;
+    sc->parent = this;
+    sc->inunion = 0;
+
+    if (isCOMclass())
+    {
+#if _WIN32
+	sc->linkage = LINKwindows;
+#else
+	/* This enables us to use COM objects under Linux and
+	 * work with things like XPCOM
+	 */
+	sc->linkage = LINKc;
+#endif
+    }
+    sc->protection = PROTpublic;
+    sc->explicitProtection = 0;
+    sc->structalign = 8;
+    structalign = sc->structalign;
+    if (baseClass)
+    {	sc->offset = baseClass->structsize;
+	alignsize = baseClass->alignsize;
+//	if (isnested)
+//	    sc->offset += PTRSIZE;	// room for uplevel context pointer
+    }
+    else
+    {	sc->offset = PTRSIZE * 2;	// allow room for __vptr and __monitor
+	alignsize = PTRSIZE;
+    }
+    structsize = sc->offset;
+    Scope scsave = *sc;
+    int members_dim = members->dim;
+    sizeok = 0;
+    for (i = 0; i < members_dim; i++)
+    {
+	Dsymbol *s = (Dsymbol *)members->data[i];
+	s->semantic(sc);
+    }
+
+    if (sizeok == 2)
+    {	// semantic() failed because of forward references.
+	// Unwind what we did, and defer it for later
+	fields.setDim(0);
+	structsize = 0;
+	alignsize = 0;
+	structalign = 0;
+
+	sc = sc->pop();
+
+	scope = scx ? scx : new Scope(*sc);
+	scope->setNoFree();
+	scope->module->addDeferredSemantic(this);
+
+	//printf("\tsemantic('%s') failed due to forward references\n", toChars());
+	return;
+    }
+
+    //printf("\tsemantic('%s') successful\n", toChars());
+
+    structsize = sc->offset;
+    //members->print();
+
+    /* Look for special member functions.
+     * They must be in this class, not in a base class.
+     */
+    ctor = (CtorDeclaration *)search(0, Id::ctor, 0);
+    if (ctor && (ctor->toParent() != this || !ctor->isCtorDeclaration()))
+	ctor = NULL;
+
+//    dtor = (DtorDeclaration *)search(Id::dtor, 0);
+//    if (dtor && dtor->toParent() != this)
+//	dtor = NULL;
+
+//    inv = (InvariantDeclaration *)search(Id::classInvariant, 0);
+//    if (inv && inv->toParent() != this)
+//	inv = NULL;
+
+    // Can be in base class
+    aggNew    = (NewDeclaration *)search(0, Id::classNew, 0);
+    aggDelete = (DeleteDeclaration *)search(0, Id::classDelete, 0);
+
+    // If this class has no constructor, but base class does, create
+    // a constructor:
+    //    this() { }
+    if (!ctor && baseClass && baseClass->ctor)
+    {
+	//printf("Creating default this(){} for class %s\n", toChars());
+	CtorDeclaration *ctor = new CtorDeclaration(loc, 0, NULL, 0);
+	ctor->fbody = new CompoundStatement(0, new Statements());
+	members->push(ctor);
+	ctor->addMember(sc, this, 1);
+	*sc = scsave;	// why? What about sc->nofree?
+	sc->offset = structsize;
+	ctor->semantic(sc);
+	this->ctor = ctor;
+	defaultCtor = ctor;
+    }
+
+#if 0
+    if (baseClass)
+    {	if (!aggDelete)
+	    aggDelete = baseClass->aggDelete;
+	if (!aggNew)
+	    aggNew = baseClass->aggNew;
+    }
+#endif
+
+    // Allocate instance of each new interface
+    for (i = 0; i < vtblInterfaces->dim; i++)
+    {
+	BaseClass *b = (BaseClass *)vtblInterfaces->data[i];
+	unsigned thissize = PTRSIZE;
+
+	alignmember(structalign, thissize, &sc->offset);
+	assert(b->offset == 0);
+	b->offset = sc->offset;
+
+	// Take care of single inheritance offsets
+	while (b->baseInterfaces_dim)
+	{
+	    b = &b->baseInterfaces[0];
+	    b->offset = sc->offset;
+	}
+
+	sc->offset += thissize;
+	if (alignsize < thissize)
+	    alignsize = thissize;
+    }
+    structsize = sc->offset;
+    sizeok = 1;
+    Module::dprogress++;
+
+    dtor = buildDtor(sc);
+
+    sc->pop();
+
+#if 0 // Do not call until toObjfile() because of forward references
+    // Fill in base class vtbl[]s
+    for (i = 0; i < vtblInterfaces->dim; i++)
+    {
+	BaseClass *b = (BaseClass *)vtblInterfaces->data[i];
+
+	//b->fillVtbl(this, &b->vtbl, 1);
+    }
+#endif
+    //printf("-ClassDeclaration::semantic(%s), type = %p\n", toChars(), type);
+}
+
+void ClassDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    if (!isAnonymous())
+    {
+	buf->printf("%s ", kind());
+	buf->writestring(toChars());
+	if (baseclasses.dim)
+	    buf->writestring(" : ");
+    }
+    for (int i = 0; i < baseclasses.dim; i++)
+    {
+	BaseClass *b = (BaseClass *)baseclasses.data[i];
+
+	if (i)
+	    buf->writeByte(',');
+	//buf->writestring(b->base->ident->toChars());
+	b->type->toCBuffer(buf, NULL, hgs);
+    }
+    buf->writenl();
+    buf->writeByte('{');
+    buf->writenl();
+    for (int i = 0; i < members->dim; i++)
+    {
+	Dsymbol *s = (Dsymbol *)members->data[i];
+
+	buf->writestring("    ");
+	s->toCBuffer(buf, hgs);
+    }
+    buf->writestring("}");
+    buf->writenl();
+}
+
+#if 0
+void ClassDeclaration::defineRef(Dsymbol *s)
+{
+    ClassDeclaration *cd;
+
+    AggregateDeclaration::defineRef(s);
+    cd = s->isClassDeclaration();
+    baseType = cd->baseType;
+    cd->baseType = NULL;
+}
+#endif
+
+/*********************************************
+ * Determine if 'this' is a base class of cd.
+ * This is used to detect circular inheritance only.
+ */
+
+int ClassDeclaration::isBaseOf2(ClassDeclaration *cd)
+{
+    if (!cd)
+	return 0;
+    //printf("ClassDeclaration::isBaseOf2(this = '%s', cd = '%s')\n", toChars(), cd->toChars());
+    for (int i = 0; i < cd->baseclasses.dim; i++)
+    {	BaseClass *b = (BaseClass *)cd->baseclasses.data[i];
+
+	if (b->base == this || isBaseOf2(b->base))
+	    return 1;
+    }
+    return 0;
+}
+
+/*******************************************
+ * Determine if 'this' is a base class of cd.
+ */
+
+int ClassDeclaration::isBaseOf(ClassDeclaration *cd, int *poffset)
+{
+    //printf("ClassDeclaration::isBaseOf(this = '%s', cd = '%s')\n", toChars(), cd->toChars());
+    if (poffset)
+	*poffset = 0;
+    while (cd)
+    {
+	if (this == cd->baseClass)
+	    return 1;
+
+	/* cd->baseClass might not be set if cd is forward referenced.
+	 */
+	if (!cd->baseClass && cd->baseclasses.dim && !cd->isInterfaceDeclaration())
+	{
+	    cd->error("base class is forward referenced by %s", toChars());
+	}
+
+	cd = cd->baseClass;
+    }
+    return 0;
+}
+
+Dsymbol *ClassDeclaration::search(Loc loc, Identifier *ident, int flags)
+{
+    Dsymbol *s;
+
+    //printf("%s.ClassDeclaration::search('%s')\n", toChars(), ident->toChars());
+    if (scope)
+	semantic(scope);
+
+    if (!members || !symtab || scope)
+    {	error("is forward referenced when looking for '%s'", ident->toChars());
+	//*(char*)0=0;
+	return NULL;
+    }
+
+    s = ScopeDsymbol::search(loc, ident, flags);
+    if (!s)
+    {
+	// Search bases classes in depth-first, left to right order
+
+	int i;
+
+	for (i = 0; i < baseclasses.dim; i++)
+	{
+	    BaseClass *b = (BaseClass *)baseclasses.data[i];
+
+	    if (b->base)
+	    {
+		if (!b->base->symtab)
+		    error("base %s is forward referenced", b->base->ident->toChars());
+		else
+		{
+		    s = b->base->search(loc, ident, flags);
+		    if (s == this)	// happens if s is nested in this and derives from this
+			s = NULL;
+		    else if (s)
+			break;
+		}
+	    }
+	}
+    }
+    return s;
+}
+
+/**********************************************************
+ * fd is in the vtbl[] for this class.
+ * Return 1 if function is hidden (not findable through search).
+ */
+
+#if DMDV2
+int isf(void *param, FuncDeclaration *fd)
+{
+    //printf("param = %p, fd = %p %s\n", param, fd, fd->toChars());
+    return param == fd;
+}
+
+int ClassDeclaration::isFuncHidden(FuncDeclaration *fd)
+{
+    //printf("ClassDeclaration::isFuncHidden(class = %s, fd = %s)\n", toChars(), fd->toChars());
+    Dsymbol *s = search(0, fd->ident, 4|2);
+    if (!s)
+    {	//printf("not found\n");
+	/* Because, due to a hack, if there are multiple definitions
+	 * of fd->ident, NULL is returned.
+	 */
+	return 0;
+    }
+    s = s->toAlias();
+    OverloadSet *os = s->isOverloadSet();
+    if (os)
+    {
+	for (int i = 0; i < os->a.dim; i++)
+	{   Dsymbol *s = (Dsymbol *)os->a.data[i];
+	    FuncDeclaration *f2 = s->isFuncDeclaration();
+	    if (f2 && overloadApply(getModule(), f2, &isf, fd))
+		return 0;
+	}
+	return 1;
+    }
+    else
+    {
+	FuncDeclaration *fdstart = s->isFuncDeclaration();
+	//printf("%s fdstart = %p\n", s->kind(), fdstart);
+	return !overloadApply(getModule(), fdstart, &isf, fd);
+    }
+}
+#endif
+
+/****************
+ * Find virtual function matching identifier and type.
+ * Used to build virtual function tables for interface implementations.
+ */
+
+FuncDeclaration *ClassDeclaration::findFunc(Identifier *ident, TypeFunction *tf)
+{
+    //printf("ClassDeclaration::findFunc(%s, %s) %s\n", ident->toChars(), tf->toChars(), toChars());
+
+    ClassDeclaration *cd = this;
+    Array *vtbl = &cd->vtbl;
+    while (1)
+    {
+	for (size_t i = 0; i < vtbl->dim; i++)
+	{
+	    FuncDeclaration *fd = ((Dsymbol*)vtbl->data[i])->isFuncDeclaration();
+	    if (!fd)
+		continue;		// the first entry might be a ClassInfo
+
+	    //printf("\t[%d] = %s\n", i, fd->toChars());
+	    if (ident == fd->ident &&
+		//tf->equals(fd->type)
+		fd->type->covariant(tf) == 1
+	       )
+	    {   //printf("\t\tfound\n");
+		return fd;
+	    }
+	    //else printf("\t\t%d\n", fd->type->covariant(tf));
+	}
+	if (!cd)
+	    break;
+	vtbl = &cd->vtblFinal;
+	cd = cd->baseClass;
+    }
+
+    return NULL;
+}
+
+void ClassDeclaration::interfaceSemantic(Scope *sc)
+{
+    InterfaceDeclaration *id = isInterfaceDeclaration();
+
+    vtblInterfaces = new BaseClasses();
+    vtblInterfaces->reserve(interfaces_dim);
+
+    for (size_t i = 0; i < interfaces_dim; i++)
+    {
+	BaseClass *b = interfaces[i];
+
+	// If this is an interface, and it derives from a COM interface,
+	// then this is a COM interface too.
+	if (b->base->isCOMinterface())
+	    com = 1;
+
+	if (b->base->isCPPinterface() && id)
+	    id->cpp = 1;
+
+	vtblInterfaces->push(b);
+	b->copyBaseInterfaces(vtblInterfaces);
+    }
+}
+
+/****************************************
+ */
+
+int ClassDeclaration::isCOMclass()
+{
+    return com;
+}
+
+int ClassDeclaration::isCOMinterface()
+{
+    return 0;
+}
+
+int ClassDeclaration::isCPPinterface()
+{
+    return 0;
+}
+
+
+/****************************************
+ */
+
+int ClassDeclaration::isAbstract()
+{
+    if (isabstract)
+	return TRUE;
+    for (int i = 1; i < vtbl.dim; i++)
+    {
+	FuncDeclaration *fd = ((Dsymbol *)vtbl.data[i])->isFuncDeclaration();
+
+	//printf("\tvtbl[%d] = %p\n", i, fd);
+	if (!fd || fd->isAbstract())
+	{
+	    isabstract |= 1;
+	    return TRUE;
+	}
+    }
+    return FALSE;
+}
+
+
+/****************************************
+ * Determine if slot 0 of the vtbl[] is reserved for something else.
+ * For class objects, yes, this is where the classinfo ptr goes.
+ * For COM interfaces, no.
+ * For non-COM interfaces, yes, this is where the Interface ptr goes.
+ */
+
+int ClassDeclaration::vtblOffset()
+{
+    return 1;
+}
+
+/****************************************
+ */
+
+const char *ClassDeclaration::kind()
+{
+    return "class";
+}
+
+/****************************************
+ */
+
+void ClassDeclaration::addLocalClass(ClassDeclarations *aclasses)
+{
+    aclasses->push(this);
+}
+
+/********************************* InterfaceDeclaration ****************************/
+
+InterfaceDeclaration::InterfaceDeclaration(Loc loc, Identifier *id, BaseClasses *baseclasses)
+    : ClassDeclaration(loc, id, baseclasses)
+{
+    com = 0;
+    cpp = 0;
+    if (id == Id::IUnknown)	// IUnknown is the root of all COM interfaces
+    {	com = 1;
+	cpp = 1;		// IUnknown is also a C++ interface
+    }
+}
+
+Dsymbol *InterfaceDeclaration::syntaxCopy(Dsymbol *s)
+{
+    InterfaceDeclaration *id;
+
+    if (s)
+	id = (InterfaceDeclaration *)s;
+    else
+	id = new InterfaceDeclaration(loc, ident, NULL);
+
+    ClassDeclaration::syntaxCopy(id);
+    return id;
+}
+
+void InterfaceDeclaration::semantic(Scope *sc)
+{   int i;
+
+    //printf("InterfaceDeclaration::semantic(%s), type = %p\n", toChars(), type);
+    if (inuse)
+	return;
+    if (!scope)
+    {	type = type->semantic(loc, sc);
+	handle = handle->semantic(loc, sc);
+    }
+    if (!members)			// if forward reference
+    {	//printf("\tinterface '%s' is forward referenced\n", toChars());
+	return;
+    }
+    if (symtab)			// if already done
+    {	if (!scope)
+	    return;
+    }
+    else
+	symtab = new DsymbolTable();
+
+    Scope *scx = NULL;
+    if (scope)
+    {	sc = scope;
+	scx = scope;		// save so we don't make redundant copies
+	scope = NULL;
+    }
+
+    if (sc->stc & STCdeprecated)
+    {
+	isdeprecated = 1;
+    }
+
+    // Expand any tuples in baseclasses[]
+    for (i = 0; i < baseclasses.dim; )
+    {	BaseClass *b = (BaseClass *)baseclasses.data[0];
+	b->type = b->type->semantic(loc, sc);
+	Type *tb = b->type->toBasetype();
+
+	if (tb->ty == Ttuple)
+	{   TypeTuple *tup = (TypeTuple *)tb;
+	    enum PROT protection = b->protection;
+	    baseclasses.remove(i);
+	    size_t dim = Argument::dim(tup->arguments);
+	    for (size_t j = 0; j < dim; j++)
+	    {	Argument *arg = Argument::getNth(tup->arguments, j);
+		b = new BaseClass(arg->type, protection);
+		baseclasses.insert(i + j, b);
+	    }
+	}
+	else
+	    i++;
+    }
+
+    if (!baseclasses.dim && sc->linkage == LINKcpp)
+	cpp = 1;
+
+    // Check for errors, handle forward references
+    for (i = 0; i < baseclasses.dim; )
+    {	TypeClass *tc;
+	BaseClass *b;
+	Type *tb;
+
+	b = (BaseClass *)baseclasses.data[i];
+	b->type = b->type->semantic(loc, sc);
+	tb = b->type->toBasetype();
+	if (tb->ty == Tclass)
+	    tc = (TypeClass *)tb;
+	else
+	    tc = NULL;
+	if (!tc || !tc->sym->isInterfaceDeclaration())
+	{
+	    error("base type must be interface, not %s", b->type->toChars());
+	    baseclasses.remove(i);
+	    continue;
+	}
+	else
+	{
+	    // Check for duplicate interfaces
+	    for (size_t j = 0; j < i; j++)
+	    {
+		BaseClass *b2 = (BaseClass *)baseclasses.data[j];
+		if (b2->base == tc->sym)
+		    error("inherits from duplicate interface %s", b2->base->toChars());
+	    }
+
+	    b->base = tc->sym;
+	    if (b->base == this || isBaseOf2(b->base))
+	    {
+		error("circular inheritance of interface");
+		baseclasses.remove(i);
+		continue;
+	    }
+	    if (!b->base->symtab || b->base->scope || b->base->inuse)
+	    {
+		//error("forward reference of base class %s", baseClass->toChars());
+		// Forward reference of base, try again later
+		//printf("\ttry later, forward reference of base %s\n", b->base->toChars());
+		scope = scx ? scx : new Scope(*sc);
+		scope->setNoFree();
+		scope->module->addDeferredSemantic(this);
+		return;
+	    }
+	}
+#if 0
+	// Inherit const/invariant from base class
+	storage_class |= b->base->storage_class & STC_TYPECTOR;
+#endif
+	i++;
+    }
+
+    interfaces_dim = baseclasses.dim;
+    interfaces = (BaseClass **)baseclasses.data;
+
+    interfaceSemantic(sc);
+
+    if (vtblOffset())
+	vtbl.push(this);		// leave room at vtbl[0] for classinfo
+
+    // Cat together the vtbl[]'s from base interfaces
+    for (i = 0; i < interfaces_dim; i++)
+    {	BaseClass *b = interfaces[i];
+
+	// Skip if b has already appeared
+	for (int k = 0; k < i; k++)
+	{
+	    if (b == interfaces[i])
+		goto Lcontinue;
+	}
+
+	// Copy vtbl[] from base class
+	if (b->base->vtblOffset())
+	{   int d = b->base->vtbl.dim;
+	    if (d > 1)
+	    {
+		vtbl.reserve(d - 1);
+		for (int j = 1; j < d; j++)
+		    vtbl.push(b->base->vtbl.data[j]);
+	    }
+	}
+	else
+	{
+	    vtbl.append(&b->base->vtbl);
+	}
+
+      Lcontinue:
+	;
+    }
+
+    protection = sc->protection;
+    storage_class |= sc->stc & STC_TYPECTOR;
+
+    for (i = 0; i < members->dim; i++)
+    {
+	Dsymbol *s = (Dsymbol *)members->data[i];
+	s->addMember(sc, this, 1);
+    }
+
+    sc = sc->push(this);
+    sc->stc &= ~(STCfinal | STCauto | STCscope | STCstatic |
+                 STCabstract | STCdeprecated | STC_TYPECTOR | STCtls | STCgshared);
+    sc->stc |= storage_class & STC_TYPECTOR;
+    sc->parent = this;
+    if (isCOMinterface())
+	sc->linkage = LINKwindows;
+    else if (isCPPinterface())
+	sc->linkage = LINKcpp;
+    sc->structalign = 8;
+    structalign = sc->structalign;
+    sc->offset = PTRSIZE * 2;
+    inuse++;
+    for (i = 0; i < members->dim; i++)
+    {
+	Dsymbol *s = (Dsymbol *)members->data[i];
+	s->semantic(sc);
+    }
+    inuse--;
+    //members->print();
+    sc->pop();
+    //printf("-InterfaceDeclaration::semantic(%s), type = %p\n", toChars(), type);
+}
+
+
+/*******************************************
+ * Determine if 'this' is a base class of cd.
+ * (Actually, if it is an interface supported by cd)
+ * Output:
+ *	*poffset	offset to start of class
+ *			OFFSET_RUNTIME	must determine offset at runtime
+ * Returns:
+ *	0	not a base
+ *	1	is a base
+ */
+
+int InterfaceDeclaration::isBaseOf(ClassDeclaration *cd, int *poffset)
+{
+    unsigned j;
+
+    //printf("%s.InterfaceDeclaration::isBaseOf(cd = '%s')\n", toChars(), cd->toChars());
+    assert(!baseClass);
+    for (j = 0; j < cd->interfaces_dim; j++)
+    {
+	BaseClass *b = cd->interfaces[j];
+
+	//printf("\tbase %s\n", b->base->toChars());
+	if (this == b->base)
+	{
+	    //printf("\tfound at offset %d\n", b->offset);
+	    if (poffset)
+	    {	*poffset = b->offset;
+		if (j && cd->isInterfaceDeclaration())
+		    *poffset = OFFSET_RUNTIME;
+	    }
+	    return 1;
+	}
+	if (isBaseOf(b, poffset))
+	{   if (j && poffset && cd->isInterfaceDeclaration())
+		*poffset = OFFSET_RUNTIME;
+	    return 1;
+	}
+    }
+
+    if (cd->baseClass && isBaseOf(cd->baseClass, poffset))
+	return 1;
+
+    if (poffset)
+	*poffset = 0;
+    return 0;
+}
+
+
+int InterfaceDeclaration::isBaseOf(BaseClass *bc, int *poffset)
+{
+    //printf("%s.InterfaceDeclaration::isBaseOf(bc = '%s')\n", toChars(), bc->base->toChars());
+    for (unsigned j = 0; j < bc->baseInterfaces_dim; j++)
+    {
+	BaseClass *b = &bc->baseInterfaces[j];
+
+	if (this == b->base)
+	{
+	    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;
+	}
+    }
+    if (poffset)
+	*poffset = 0;
+    return 0;
+}
+
+/****************************************
+ * Determine if slot 0 of the vtbl[] is reserved for something else.
+ * For class objects, yes, this is where the ClassInfo ptr goes.
+ * For COM interfaces, no.
+ * For non-COM interfaces, yes, this is where the Interface ptr goes.
+ */
+
+int InterfaceDeclaration::vtblOffset()
+{
+    if (isCOMinterface() || isCPPinterface())
+	return 0;
+    return 1;
+}
+
+int InterfaceDeclaration::isCOMinterface()
+{
+    return com;
+}
+
+int InterfaceDeclaration::isCPPinterface()
+{
+    return cpp;
+}
+
+/*******************************************
+ */
+
+const char *InterfaceDeclaration::kind()
+{
+    return "interface";
+}
+
+
+/******************************** BaseClass *****************************/
+
+BaseClass::BaseClass()
+{
+    memset(this, 0, sizeof(BaseClass));
+}
+
+BaseClass::BaseClass(Type *type, enum PROT protection)
+{
+    //printf("BaseClass(this = %p, '%s')\n", this, type->toChars());
+    this->type = type;
+    this->protection = protection;
+    base = NULL;
+    offset = 0;
+
+    baseInterfaces_dim = 0;
+    baseInterfaces = NULL;
+}
+
+/****************************************
+ * Fill in vtbl[] for base class based on member functions of class cd.
+ * Input:
+ *	vtbl		if !=NULL, fill it in
+ *	newinstance	!=0 means all entries must be filled in by members
+ *			of cd, not members of any base classes of cd.
+ * Returns:
+ *	!=0 if any entries were filled in by members of cd (not exclusively
+ *	by base classes)
+ */
+
+int BaseClass::fillVtbl(ClassDeclaration *cd, Array *vtbl, int newinstance)
+{
+    ClassDeclaration *id = base;
+    int j;
+    int result = 0;
+
+    //printf("BaseClass::fillVtbl(this='%s', cd='%s')\n", base->toChars(), cd->toChars());
+    if (vtbl)
+	vtbl->setDim(base->vtbl.dim);
+
+    // first entry is ClassInfo reference
+    for (j = base->vtblOffset(); j < base->vtbl.dim; j++)
+    {
+	FuncDeclaration *ifd = ((Dsymbol *)base->vtbl.data[j])->isFuncDeclaration();
+	FuncDeclaration *fd;
+	TypeFunction *tf;
+
+	//printf("        vtbl[%d] is '%s'\n", j, ifd ? ifd->toChars() : "null");
+
+	assert(ifd);
+	// Find corresponding function in this class
+	tf = (ifd->type->ty == Tfunction) ? (TypeFunction *)(ifd->type) : NULL;
+	fd = cd->findFunc(ifd->ident, tf);
+	if (fd && !fd->isAbstract())
+	{
+	    //printf("            found\n");
+	    // Check that calling conventions match
+	    if (fd->linkage != ifd->linkage)
+		fd->error("linkage doesn't match interface function");
+
+	    // Check that it is current
+	    if (newinstance &&
+		fd->toParent() != cd &&
+		ifd->toParent() == base)
+		cd->error("interface function %s.%s is not implemented",
+		    id->toChars(), ifd->ident->toChars());
+
+	    if (fd->toParent() == cd)
+		result = 1;
+	}
+	else
+	{
+	    //printf("            not found\n");
+	    // BUG: should mark this class as abstract?
+	    if (!cd->isAbstract())
+		cd->error("interface function %s.%s isn't implemented",
+		    id->toChars(), ifd->ident->toChars());
+	    fd = NULL;
+	}
+	if (vtbl)
+	    vtbl->data[j] = fd;
+    }
+
+    return result;
+}
+
+void BaseClass::copyBaseInterfaces(BaseClasses *vtblInterfaces)
+{
+    //printf("+copyBaseInterfaces(), %s\n", base->toChars());
+//    if (baseInterfaces_dim)
+//	return;
+
+    baseInterfaces_dim = base->interfaces_dim;
+    baseInterfaces = (BaseClass *)mem.calloc(baseInterfaces_dim, sizeof(BaseClass));
+
+    //printf("%s.copyBaseInterfaces()\n", base->toChars());
+    for (int i = 0; i < baseInterfaces_dim; i++)
+    {
+	BaseClass *b = &baseInterfaces[i];
+	BaseClass *b2 = base->interfaces[i];
+
+	assert(b2->vtbl.dim == 0);	// should not be filled yet
+	memcpy(b, b2, sizeof(BaseClass));
+
+	if (i)				// single inheritance is i==0
+	    vtblInterfaces->push(b);	// only need for M.I.
+	b->copyBaseInterfaces(vtblInterfaces);
+    }
+    //printf("-copyBaseInterfaces\n");
+}
--- a/dmd2/clone.c	Mon Jun 01 01:28:18 2009 +0200
+++ b/dmd2/clone.c	Mon Jun 01 19:02:20 2009 +0100
@@ -1,437 +1,443 @@
-
-// 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 "root.h"
-#include "aggregate.h"
-#include "scope.h"
-#include "mtype.h"
-#include "declaration.h"
-#include "module.h"
-#include "id.h"
-#include "expression.h"
-#include "statement.h"
-#include "init.h"
-
-
-/*******************************************
- * We need an opAssign for the struct if
- * it has a destructor or a postblit.
- * We need to generate one if a user-specified one does not exist.
- */
-
-int StructDeclaration::needOpAssign()
-{
-#define X 0
-    if (X) printf("StructDeclaration::needOpAssign() %s\n", toChars());
-    if (hasIdentityAssign)
-	goto Ldontneed;
-
-    if (dtor || postblit)
-	goto Lneed;
-
-    /* If any of the fields need an opAssign, then we
-     * need it too.
-     */
-    for (size_t i = 0; i < fields.dim; i++)
-    {
-	Dsymbol *s = (Dsymbol *)fields.data[i];
-	VarDeclaration *v = s->isVarDeclaration();
-	assert(v && v->storage_class & STCfield);
-	Type *tv = v->type->toBasetype();
-	while (tv->ty == Tsarray)
-	{   TypeSArray *ta = (TypeSArray *)tv;
-	    tv = tv->nextOf()->toBasetype();
-	}
-	if (tv->ty == Tstruct)
-	{   TypeStruct *ts = (TypeStruct *)tv;
-	    StructDeclaration *sd = ts->sym;
-	    if (sd->needOpAssign())
-		goto Lneed;
-	}
-    }
-Ldontneed:
-    if (X) printf("\tdontneed\n");
-    return 0;
-
-Lneed:
-    if (X) printf("\tneed\n");
-    return 1;
-#undef X
-}
-
-/******************************************
- * Build opAssign for struct.
- *	S* opAssign(S s) { ... }
- */
-
-FuncDeclaration *StructDeclaration::buildOpAssign(Scope *sc)
-{
-    if (!needOpAssign())
-	return NULL;
-
-    //printf("StructDeclaration::buildOpAssign() %s\n", toChars());
-
-    FuncDeclaration *fop = NULL;
-
-    Argument *param = new Argument(STCnodtor, type, Id::p, NULL);
-    Arguments *fparams = new Arguments;
-    fparams->push(param);
-    Type *ftype = new TypeFunction(fparams, handle, FALSE, LINKd);
-#if STRUCTTHISREF
-    ((TypeFunction *)ftype)->isref = 1;
-#endif
-
-    fop = new FuncDeclaration(0, 0, Id::assign, STCundefined, ftype);
-
-    Expression *e = NULL;
-    if (postblit)
-    {	/* Swap:
-	 *    tmp = *this; *this = s; tmp.dtor();
-	 */
-	//printf("\tswap copy\n");
-	Identifier *idtmp = Lexer::uniqueId("__tmp");
-	VarDeclaration *tmp;
-	AssignExp *ec = NULL;
-	if (dtor)
-	{
-	    tmp = new VarDeclaration(0, type, idtmp, new VoidInitializer(0));
-	    tmp->noauto = 1;
-	    e = new DeclarationExp(0, tmp);
-	    ec = new AssignExp(0,
-		new VarExp(0, tmp),
-#if STRUCTTHISREF
-		new ThisExp(0)
-#else
-		new PtrExp(0, new ThisExp(0))
-#endif
-		);
-	    ec->op = TOKblit;
-	    e = Expression::combine(e, ec);
-	}
-	ec = new AssignExp(0,
-#if STRUCTTHISREF
-		new ThisExp(0),
-#else
-		new PtrExp(0, new ThisExp(0)),
-#endif
-		new IdentifierExp(0, Id::p));
-	ec->op = TOKblit;
-	e = Expression::combine(e, ec);
-	if (dtor)
-	{
-	    /* Instead of running the destructor on s, run it
-	     * on tmp. This avoids needing to copy tmp back in to s.
-	     */
-	    Expression *ec = new DotVarExp(0, new VarExp(0, tmp), dtor, 0);
-	    ec = new CallExp(0, ec);
-	    e = Expression::combine(e, ec);
-	}
-    }
-    else
-    {	/* Do memberwise copy
-	 */
-	//printf("\tmemberwise copy\n");
-	for (size_t i = 0; i < fields.dim; i++)
-	{
-	    Dsymbol *s = (Dsymbol *)fields.data[i];
-	    VarDeclaration *v = s->isVarDeclaration();
-	    assert(v && v->storage_class & STCfield);
-	    // this.v = s.v;
-	    AssignExp *ec = new AssignExp(0,
-		new DotVarExp(0, new ThisExp(0), v, 0),
-		new DotVarExp(0, new IdentifierExp(0, Id::p), v, 0));
-	    ec->op = TOKblit;
-	    e = Expression::combine(e, ec);
-	}
-    }
-    Statement *s1 = new ExpStatement(0, e);
-
-    /* Add:
-     *   return this;
-     */
-    e = new ThisExp(0);
-    Statement *s2 = new ReturnStatement(0, e);
-
-    fop->fbody = new CompoundStatement(0, s1, s2);
-
-    members->push(fop);
-    fop->addMember(sc, this, 1);
-
-    sc = sc->push();
-    sc->stc = 0;
-    sc->linkage = LINKd;
-
-    fop->semantic(sc);
-
-    sc->pop();
-
-    //printf("-StructDeclaration::buildOpAssign() %s\n", toChars());
-
-    return fop;
-}
-
-/*******************************************
- * Build copy constructor for struct.
- * Copy constructors are compiler generated only, and are only
- * callable from the compiler. They are not user accessible.
- * A copy constructor is:
- *    void cpctpr(ref S s)
- *    {
- *	*this = s;
- *	this.postBlit();
- *    }
- * This is done so:
- *	- postBlit() never sees uninitialized data
- *	- memcpy can be much more efficient than memberwise copy
- *	- no fields are overlooked
- */
-
-FuncDeclaration *StructDeclaration::buildCpCtor(Scope *sc)
-{
-    //printf("StructDeclaration::buildCpCtor() %s\n", toChars());
-    FuncDeclaration *fcp = NULL;
-
-    /* Copy constructor is only necessary if there is a postblit function,
-     * otherwise the code generator will just do a bit copy.
-     */
-    if (postblit)
-    {
-	//printf("generating cpctor\n");
-
-	Argument *param = new Argument(STCref, type, Id::p, NULL);
-	Arguments *fparams = new Arguments;
-	fparams->push(param);
-	Type *ftype = new TypeFunction(fparams, Type::tvoid, FALSE, LINKd);
-
-	fcp = new FuncDeclaration(0, 0, Id::cpctor, STCundefined, ftype);
-
-	// Build *this = p;
-	Expression *e = new ThisExp(0);
-#if !STRUCTTHISREF
-	e = new PtrExp(0, e);
-#endif
-	AssignExp *ea = new AssignExp(0, e, new IdentifierExp(0, Id::p));
-	ea->op = TOKblit;
-	Statement *s = new ExpStatement(0, ea);
-
-	// Build postBlit();
-	e = new VarExp(0, postblit, 0);
-	e = new CallExp(0, e);
-
-	s = new CompoundStatement(0, s, new ExpStatement(0, e));
-	fcp->fbody = s;
-
-	members->push(fcp);
-
-	sc = sc->push();
-	sc->stc = 0;
-	sc->linkage = LINKd;
-
-	fcp->semantic(sc);
-
-	sc->pop();
-    }
-
-    return fcp;
-}
-
-/*****************************************
- * Create inclusive postblit for struct by aggregating
- * all the postblits in postblits[] with the postblits for
- * all the members.
- * Note the close similarity with AggregateDeclaration::buildDtor(),
- * and the ordering changes (runs forward instead of backwards).
- */
-
-#if DMDV2
-FuncDeclaration *StructDeclaration::buildPostBlit(Scope *sc)
-{
-    //printf("StructDeclaration::buildPostBlit() %s\n", toChars());
-    Expression *e = NULL;
-
-    for (size_t i = 0; i < fields.dim; i++)
-    {
-	Dsymbol *s = (Dsymbol *)fields.data[i];
-	VarDeclaration *v = s->isVarDeclaration();
-	assert(v && v->storage_class & STCfield);
-	Type *tv = v->type->toBasetype();
-	size_t dim = 1;
-	while (tv->ty == Tsarray)
-	{   TypeSArray *ta = (TypeSArray *)tv;
-	    dim *= ((TypeSArray *)tv)->dim->toInteger();
-	    tv = tv->nextOf()->toBasetype();
-	}
-	if (tv->ty == Tstruct)
-	{   TypeStruct *ts = (TypeStruct *)tv;
-	    StructDeclaration *sd = ts->sym;
-	    if (sd->postblit)
-	    {	Expression *ex;
-
-		// this.v
-		ex = new ThisExp(0);
-		ex = new DotVarExp(0, ex, v, 0);
-
-		if (dim == 1)
-		{   // this.v.dtor()
-		    ex = new DotVarExp(0, ex, sd->postblit, 0);
-		    ex = new CallExp(0, ex);
-		}
-		else
-		{
-		    // Typeinfo.postblit(cast(void*)&this.v);
-		    Expression *ea = new AddrExp(0, ex);
-		    ea = new CastExp(0, ea, Type::tvoid->pointerTo());
-
-		    Expression *et = v->type->getTypeInfo(sc);
-		    et = new DotIdExp(0, et, Id::postblit);
-
-		    ex = new CallExp(0, et, ea);
-		}
-		e = Expression::combine(e, ex);	// combine in forward order
-	    }
-	}
-    }
-
-    /* Build our own "postblit" which executes e
-     */
-    if (e)
-    {	//printf("Building __fieldPostBlit()\n");
-	PostBlitDeclaration *dd = new PostBlitDeclaration(0, 0, Lexer::idPool("__fieldPostBlit"));
-	dd->fbody = new ExpStatement(0, e);
-	dtors.push(dd);
-	members->push(dd);
-	dd->semantic(sc);
-    }
-
-    switch (postblits.dim)
-    {
-	case 0:
-	    return NULL;
-
-	case 1:
-	    return (FuncDeclaration *)postblits.data[0];
-
-	default:
-	    e = NULL;
-	    for (size_t i = 0; i < postblits.dim; i++)
-	    {	FuncDeclaration *fd = (FuncDeclaration *)postblits.data[i];
-		Expression *ex = new ThisExp(0);
-		ex = new DotVarExp(0, ex, fd, 0);
-		ex = new CallExp(0, ex);
-		e = Expression::combine(e, ex);
-	    }
-	    PostBlitDeclaration *dd = new PostBlitDeclaration(0, 0, Lexer::idPool("__aggrPostBlit"));
-	    dd->fbody = new ExpStatement(0, e);
-	    members->push(dd);
-	    dd->semantic(sc);
-	    return dd;
-    }
-}
-
-#endif
-
-/*****************************************
- * Create inclusive destructor for struct/class by aggregating
- * all the destructors in dtors[] with the destructors for
- * all the members.
- * Note the close similarity with StructDeclaration::buildPostBlit(),
- * and the ordering changes (runs backward instead of forwards).
- */
-
-FuncDeclaration *AggregateDeclaration::buildDtor(Scope *sc)
-{
-    //printf("AggregateDeclaration::buildDtor() %s\n", toChars());
-    Expression *e = NULL;
-
-#if DMDV2
-    for (size_t i = 0; i < fields.dim; i++)
-    {
-	Dsymbol *s = (Dsymbol *)fields.data[i];
-	VarDeclaration *v = s->isVarDeclaration();
-	assert(v && v->storage_class & STCfield);
-	Type *tv = v->type->toBasetype();
-	size_t dim = 1;
-	while (tv->ty == Tsarray)
-	{   TypeSArray *ta = (TypeSArray *)tv;
-	    dim *= ((TypeSArray *)tv)->dim->toInteger();
-	    tv = tv->nextOf()->toBasetype();
-	}
-	if (tv->ty == Tstruct)
-	{   TypeStruct *ts = (TypeStruct *)tv;
-	    StructDeclaration *sd = ts->sym;
-	    if (sd->dtor)
-	    {	Expression *ex;
-
-		// this.v
-		ex = new ThisExp(0);
-		ex = new DotVarExp(0, ex, v, 0);
-
-		if (dim == 1)
-		{   // this.v.dtor()
-		    ex = new DotVarExp(0, ex, sd->dtor, 0);
-		    ex = new CallExp(0, ex);
-		}
-		else
-		{
-		    // Typeinfo.destroy(cast(void*)&this.v);
-		    Expression *ea = new AddrExp(0, ex);
-		    ea = new CastExp(0, ea, Type::tvoid->pointerTo());
-
-		    Expression *et = v->type->getTypeInfo(sc);
-		    et = new DotIdExp(0, et, Id::destroy);
-
-		    ex = new CallExp(0, et, ea);
-		}
-		e = Expression::combine(ex, e);	// combine in reverse order
-	    }
-	}
-    }
-
-    /* Build our own "destructor" which executes e
-     */
-    if (e)
-    {	//printf("Building __fieldDtor()\n");
-	DtorDeclaration *dd = new DtorDeclaration(0, 0, Lexer::idPool("__fieldDtor"));
-	dd->fbody = new ExpStatement(0, e);
-	dtors.shift(dd);
-	members->push(dd);
-	dd->semantic(sc);
-    }
-#endif
-
-    switch (dtors.dim)
-    {
-	case 0:
-	    return NULL;
-
-	case 1:
-	    return (FuncDeclaration *)dtors.data[0];
-
-	default:
-	    e = NULL;
-	    for (size_t i = 0; i < dtors.dim; i++)
-	    {	FuncDeclaration *fd = (FuncDeclaration *)dtors.data[i];
-		Expression *ex = new ThisExp(0);
-		ex = new DotVarExp(0, ex, fd, 0);
-		ex = new CallExp(0, ex);
-		e = Expression::combine(ex, e);
-	    }
-	    DtorDeclaration *dd = new DtorDeclaration(0, 0, Lexer::idPool("__aggrDtor"));
-	    dd->fbody = new ExpStatement(0, e);
-	    members->push(dd);
-	    dd->semantic(sc);
-	    return dd;
-    }
-}
-
-
+
+// 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 "root.h"
+#include "aggregate.h"
+#include "scope.h"
+#include "mtype.h"
+#include "declaration.h"
+#include "module.h"
+#include "id.h"
+#include "expression.h"
+#include "statement.h"
+#include "init.h"
+
+
+/*******************************************
+ * We need an opAssign for the struct if
+ * it has a destructor or a postblit.
+ * We need to generate one if a user-specified one does not exist.
+ */
+
+int StructDeclaration::needOpAssign()
+{
+#define X 0
+    if (X) printf("StructDeclaration::needOpAssign() %s\n", toChars());
+    if (hasIdentityAssign)
+	goto Ldontneed;
+
+    if (dtor || postblit)
+	goto Lneed;
+
+    /* If any of the fields need an opAssign, then we
+     * need it too.
+     */
+    for (size_t i = 0; i < fields.dim; i++)
+    {
+	Dsymbol *s = (Dsymbol *)fields.data[i];
+	VarDeclaration *v = s->isVarDeclaration();
+	assert(v && v->storage_class & STCfield);
+	if (v->storage_class & STCref)
+	    continue;
+	Type *tv = v->type->toBasetype();
+	while (tv->ty == Tsarray)
+	{   TypeSArray *ta = (TypeSArray *)tv;
+	    tv = tv->nextOf()->toBasetype();
+	}
+	if (tv->ty == Tstruct)
+	{   TypeStruct *ts = (TypeStruct *)tv;
+	    StructDeclaration *sd = ts->sym;
+	    if (sd->needOpAssign())
+		goto Lneed;
+	}
+    }
+Ldontneed:
+    if (X) printf("\tdontneed\n");
+    return 0;
+
+Lneed:
+    if (X) printf("\tneed\n");
+    return 1;
+#undef X
+}
+
+/******************************************
+ * Build opAssign for struct.
+ *	S* opAssign(S s) { ... }
+ */
+
+FuncDeclaration *StructDeclaration::buildOpAssign(Scope *sc)
+{
+    if (!needOpAssign())
+	return NULL;
+
+    //printf("StructDeclaration::buildOpAssign() %s\n", toChars());
+
+    FuncDeclaration *fop = NULL;
+
+    Argument *param = new Argument(STCnodtor, type, Id::p, NULL);
+    Arguments *fparams = new Arguments;
+    fparams->push(param);
+    Type *ftype = new TypeFunction(fparams, handle, FALSE, LINKd);
+#if STRUCTTHISREF
+    ((TypeFunction *)ftype)->isref = 1;
+#endif
+
+    fop = new FuncDeclaration(0, 0, Id::assign, STCundefined, ftype);
+
+    Expression *e = NULL;
+    if (postblit)
+    {	/* Swap:
+	 *    tmp = *this; *this = s; tmp.dtor();
+	 */
+	//printf("\tswap copy\n");
+	Identifier *idtmp = Lexer::uniqueId("__tmp");
+	VarDeclaration *tmp;
+	AssignExp *ec = NULL;
+	if (dtor)
+	{
+	    tmp = new VarDeclaration(0, type, idtmp, new VoidInitializer(0));
+	    tmp->noauto = 1;
+	    e = new DeclarationExp(0, tmp);
+	    ec = new AssignExp(0,
+		new VarExp(0, tmp),
+#if STRUCTTHISREF
+		new ThisExp(0)
+#else
+		new PtrExp(0, new ThisExp(0))
+#endif
+		);
+	    ec->op = TOKblit;
+	    e = Expression::combine(e, ec);
+	}
+	ec = new AssignExp(0,
+#if STRUCTTHISREF
+		new ThisExp(0),
+#else
+		new PtrExp(0, new ThisExp(0)),
+#endif
+		new IdentifierExp(0, Id::p));
+	ec->op = TOKblit;
+	e = Expression::combine(e, ec);
+	if (dtor)
+	{
+	    /* Instead of running the destructor on s, run it
+	     * on tmp. This avoids needing to copy tmp back in to s.
+	     */
+	    Expression *ec = new DotVarExp(0, new VarExp(0, tmp), dtor, 0);
+	    ec = new CallExp(0, ec);
+	    e = Expression::combine(e, ec);
+	}
+    }
+    else
+    {	/* Do memberwise copy
+	 */
+	//printf("\tmemberwise copy\n");
+	for (size_t i = 0; i < fields.dim; i++)
+	{
+	    Dsymbol *s = (Dsymbol *)fields.data[i];
+	    VarDeclaration *v = s->isVarDeclaration();
+	    assert(v && v->storage_class & STCfield);
+	    // this.v = s.v;
+	    AssignExp *ec = new AssignExp(0,
+		new DotVarExp(0, new ThisExp(0), v, 0),
+		new DotVarExp(0, new IdentifierExp(0, Id::p), v, 0));
+	    ec->op = TOKblit;
+	    e = Expression::combine(e, ec);
+	}
+    }
+    Statement *s1 = new ExpStatement(0, e);
+
+    /* Add:
+     *   return this;
+     */
+    e = new ThisExp(0);
+    Statement *s2 = new ReturnStatement(0, e);
+
+    fop->fbody = new CompoundStatement(0, s1, s2);
+
+    members->push(fop);
+    fop->addMember(sc, this, 1);
+
+    sc = sc->push();
+    sc->stc = 0;
+    sc->linkage = LINKd;
+
+    fop->semantic(sc);
+
+    sc->pop();
+
+    //printf("-StructDeclaration::buildOpAssign() %s\n", toChars());
+
+    return fop;
+}
+
+/*******************************************
+ * Build copy constructor for struct.
+ * Copy constructors are compiler generated only, and are only
+ * callable from the compiler. They are not user accessible.
+ * A copy constructor is:
+ *    void cpctpr(ref S s)
+ *    {
+ *	*this = s;
+ *	this.postBlit();
+ *    }
+ * This is done so:
+ *	- postBlit() never sees uninitialized data
+ *	- memcpy can be much more efficient than memberwise copy
+ *	- no fields are overlooked
+ */
+
+FuncDeclaration *StructDeclaration::buildCpCtor(Scope *sc)
+{
+    //printf("StructDeclaration::buildCpCtor() %s\n", toChars());
+    FuncDeclaration *fcp = NULL;
+
+    /* Copy constructor is only necessary if there is a postblit function,
+     * otherwise the code generator will just do a bit copy.
+     */
+    if (postblit)
+    {
+	//printf("generating cpctor\n");
+
+	Argument *param = new Argument(STCref, type, Id::p, NULL);
+	Arguments *fparams = new Arguments;
+	fparams->push(param);
+	Type *ftype = new TypeFunction(fparams, Type::tvoid, FALSE, LINKd);
+
+	fcp = new FuncDeclaration(0, 0, Id::cpctor, STCundefined, ftype);
+
+	// Build *this = p;
+	Expression *e = new ThisExp(0);
+#if !STRUCTTHISREF
+	e = new PtrExp(0, e);
+#endif
+	AssignExp *ea = new AssignExp(0, e, new IdentifierExp(0, Id::p));
+	ea->op = TOKblit;
+	Statement *s = new ExpStatement(0, ea);
+
+	// Build postBlit();
+	e = new VarExp(0, postblit, 0);
+	e = new CallExp(0, e);
+
+	s = new CompoundStatement(0, s, new ExpStatement(0, e));
+	fcp->fbody = s;
+
+	members->push(fcp);
+
+	sc = sc->push();
+	sc->stc = 0;
+	sc->linkage = LINKd;
+
+	fcp->semantic(sc);
+
+	sc->pop();
+    }
+
+    return fcp;
+}
+
+/*****************************************
+ * Create inclusive postblit for struct by aggregating
+ * all the postblits in postblits[] with the postblits for
+ * all the members.
+ * Note the close similarity with AggregateDeclaration::buildDtor(),
+ * and the ordering changes (runs forward instead of backwards).
+ */
+
+#if DMDV2
+FuncDeclaration *StructDeclaration::buildPostBlit(Scope *sc)
+{
+    //printf("StructDeclaration::buildPostBlit() %s\n", toChars());
+    Expression *e = NULL;
+
+    for (size_t i = 0; i < fields.dim; i++)
+    {
+	Dsymbol *s = (Dsymbol *)fields.data[i];
+	VarDeclaration *v = s->isVarDeclaration();
+	assert(v && v->storage_class & STCfield);
+	if (v->storage_class & STCref)
+	    continue;
+	Type *tv = v->type->toBasetype();
+	size_t dim = 1;
+	while (tv->ty == Tsarray)
+	{   TypeSArray *ta = (TypeSArray *)tv;
+	    dim *= ((TypeSArray *)tv)->dim->toInteger();
+	    tv = tv->nextOf()->toBasetype();
+	}
+	if (tv->ty == Tstruct)
+	{   TypeStruct *ts = (TypeStruct *)tv;
+	    StructDeclaration *sd = ts->sym;
+	    if (sd->postblit)
+	    {	Expression *ex;
+
+		// this.v
+		ex = new ThisExp(0);
+		ex = new DotVarExp(0, ex, v, 0);
+
+		if (dim == 1)
+		{   // this.v.postblit()
+		    ex = new DotVarExp(0, ex, sd->postblit, 0);
+		    ex = new CallExp(0, ex);
+		}
+		else
+		{
+		    // Typeinfo.postblit(cast(void*)&this.v);
+		    Expression *ea = new AddrExp(0, ex);
+		    ea = new CastExp(0, ea, Type::tvoid->pointerTo());
+
+		    Expression *et = v->type->getTypeInfo(sc);
+		    et = new DotIdExp(0, et, Id::postblit);
+
+		    ex = new CallExp(0, et, ea);
+		}
+		e = Expression::combine(e, ex);	// combine in forward order
+	    }
+	}
+    }
+
+    /* Build our own "postblit" which executes e
+     */
+    if (e)
+    {	//printf("Building __fieldPostBlit()\n");
+	PostBlitDeclaration *dd = new PostBlitDeclaration(0, 0, Lexer::idPool("__fieldPostBlit"));
+	dd->fbody = new ExpStatement(0, e);
+	postblits.shift(dd);
+	members->push(dd);
+	dd->semantic(sc);
+    }
+
+    switch (postblits.dim)
+    {
+	case 0:
+	    return NULL;
+
+	case 1:
+	    return (FuncDeclaration *)postblits.data[0];
+
+	default:
+	    e = NULL;
+	    for (size_t i = 0; i < postblits.dim; i++)
+	    {	FuncDeclaration *fd = (FuncDeclaration *)postblits.data[i];
+		Expression *ex = new ThisExp(0);
+		ex = new DotVarExp(0, ex, fd, 0);
+		ex = new CallExp(0, ex);
+		e = Expression::combine(e, ex);
+	    }
+	    PostBlitDeclaration *dd = new PostBlitDeclaration(0, 0, Lexer::idPool("__aggrPostBlit"));
+	    dd->fbody = new ExpStatement(0, e);
+	    members->push(dd);
+	    dd->semantic(sc);
+	    return dd;
+    }
+}
+
+#endif
+
+/*****************************************
+ * Create inclusive destructor for struct/class by aggregating
+ * all the destructors in dtors[] with the destructors for
+ * all the members.
+ * Note the close similarity with StructDeclaration::buildPostBlit(),
+ * and the ordering changes (runs backward instead of forwards).
+ */
+
+FuncDeclaration *AggregateDeclaration::buildDtor(Scope *sc)
+{
+    //printf("AggregateDeclaration::buildDtor() %s\n", toChars());
+    Expression *e = NULL;
+
+#if DMDV2
+    for (size_t i = 0; i < fields.dim; i++)
+    {
+	Dsymbol *s = (Dsymbol *)fields.data[i];
+	VarDeclaration *v = s->isVarDeclaration();
+	assert(v && v->storage_class & STCfield);
+	if (v->storage_class & STCref)
+	    continue;
+	Type *tv = v->type->toBasetype();
+	size_t dim = 1;
+	while (tv->ty == Tsarray)
+	{   TypeSArray *ta = (TypeSArray *)tv;
+	    dim *= ((TypeSArray *)tv)->dim->toInteger();
+	    tv = tv->nextOf()->toBasetype();
+	}
+	if (tv->ty == Tstruct)
+	{   TypeStruct *ts = (TypeStruct *)tv;
+	    StructDeclaration *sd = ts->sym;
+	    if (sd->dtor)
+	    {	Expression *ex;
+
+		// this.v
+		ex = new ThisExp(0);
+		ex = new DotVarExp(0, ex, v, 0);
+
+		if (dim == 1)
+		{   // this.v.dtor()
+		    ex = new DotVarExp(0, ex, sd->dtor, 0);
+		    ex = new CallExp(0, ex);
+		}
+		else
+		{
+		    // Typeinfo.destroy(cast(void*)&this.v);
+		    Expression *ea = new AddrExp(0, ex);
+		    ea = new CastExp(0, ea, Type::tvoid->pointerTo());
+
+		    Expression *et = v->type->getTypeInfo(sc);
+		    et = new DotIdExp(0, et, Id::destroy);
+
+		    ex = new CallExp(0, et, ea);
+		}
+		e = Expression::combine(ex, e);	// combine in reverse order
+	    }
+	}
+    }
+
+    /* Build our own "destructor" which executes e
+     */
+    if (e)
+    {	//printf("Building __fieldDtor()\n");
+	DtorDeclaration *dd = new DtorDeclaration(0, 0, Lexer::idPool("__fieldDtor"));
+	dd->fbody = new ExpStatement(0, e);
+	dtors.shift(dd);
+	members->push(dd);
+	dd->semantic(sc);
+    }
+#endif
+
+    switch (dtors.dim)
+    {
+	case 0:
+	    return NULL;
+
+	case 1:
+	    return (FuncDeclaration *)dtors.data[0];
+
+	default:
+	    e = NULL;
+	    for (size_t i = 0; i < dtors.dim; i++)
+	    {	FuncDeclaration *fd = (FuncDeclaration *)dtors.data[i];
+		Expression *ex = new ThisExp(0);
+		ex = new DotVarExp(0, ex, fd, 0);
+		ex = new CallExp(0, ex);
+		e = Expression::combine(ex, e);
+	    }
+	    DtorDeclaration *dd = new DtorDeclaration(0, 0, Lexer::idPool("__aggrDtor"));
+	    dd->fbody = new ExpStatement(0, e);
+	    members->push(dd);
+	    dd->semantic(sc);
+	    return dd;
+    }
+}
+
+
--- a/dmd2/cond.c	Mon Jun 01 01:28:18 2009 +0200
+++ b/dmd2/cond.c	Mon Jun 01 19:02:20 2009 +0100
@@ -1,391 +1,405 @@
-
-// 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 "id.h"
-#include "init.h"
-#include "declaration.h"
-#include "identifier.h"
-#include "expression.h"
-#include "cond.h"
-#include "module.h"
-#include "template.h"
-#include "lexer.h"
-#ifdef _DH
-#include "mtype.h"
-#include "scope.h"
-#endif
-
-int findCondition(Array *ids, Identifier *ident)
-{
-    if (ids)
-    {
-	for (int i = 0; i < ids->dim; i++)
-	{
-	    const char *id = (const char *)ids->data[i];
-
-	    if (strcmp(id, ident->toChars()) == 0)
-		return TRUE;
-	}
-    }
-
-    return FALSE;
-}
-
-/* ============================================================ */
-
-Condition::Condition(Loc loc)
-{
-    this->loc = loc;
-    inc = 0;
-}
-
-/* ============================================================ */
-
-DVCondition::DVCondition(Module *mod, unsigned level, Identifier *ident)
-	: Condition(0)
-{
-    this->mod = mod;
-    this->level = level;
-    this->ident = ident;
-}
-
-Condition *DVCondition::syntaxCopy()
-{
-    return this;	// don't need to copy
-}
-
-/* ============================================================ */
-
-void DebugCondition::setGlobalLevel(unsigned level)
-{
-    global.params.debuglevel = level;
-}
-
-void DebugCondition::addGlobalIdent(const char *ident)
-{
-    if (!global.params.debugids)
-	global.params.debugids = new Array();
-    global.params.debugids->push((void *)ident);
-}
-
-
-DebugCondition::DebugCondition(Module *mod, unsigned level, Identifier *ident)
-    : DVCondition(mod, level, ident)
-{
-}
-
-int DebugCondition::include(Scope *sc, ScopeDsymbol *s)
-{
-    //printf("DebugCondition::include() level = %d, debuglevel = %d\n", level, global.params.debuglevel);
-    if (inc == 0)
-    {
-	inc = 2;
-	if (ident)
-	{
-	    if (findCondition(mod->debugids, ident))
-		inc = 1;
-	    else if (findCondition(global.params.debugids, ident))
-		inc = 1;
-	    else
-	    {	if (!mod->debugidsNot)
-		    mod->debugidsNot = new Array();
-		mod->debugidsNot->push(ident->toChars());
-	    }
-	}
-	else if (level <= global.params.debuglevel || level <= mod->debuglevel)
-	    inc = 1;
-    }
-    return (inc == 1);
-}
-
-void DebugCondition::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{
-    if (ident)
-	buf->printf("debug (%s)", ident->toChars());
-    else
-	buf->printf("debug (%u)", level);
-}
-
-/* ============================================================ */
-
-void VersionCondition::setGlobalLevel(unsigned level)
-{
-    global.params.versionlevel = level;
-}
-
-void VersionCondition::checkPredefined(Loc loc, const char *ident)
-{
-    static const char* reserved[] =
-    {
-	"DigitalMars", "LLVM", "LDC", "LLVM64",
-    "X86", "X86_64", "PPC", "PPC64",
-	"Windows", "Win32", "Win64",
-	"linux", "darwin", "Posix",
-	"LittleEndian", "BigEndian",
-	"all",
-	"none",
-    };
-
-    for (unsigned i = 0; i < sizeof(reserved) / sizeof(reserved[0]); i++)
-    {
-	if (strcmp(ident, reserved[i]) == 0)
-	    goto Lerror;
-    }
-
-    if (ident[0] == 'D' && ident[1] == '_')
-	goto Lerror;
-
-    return;
-
-  Lerror:
-    error(loc, "version identifier '%s' is reserved and cannot be set", ident);
-}
-
-void VersionCondition::addGlobalIdent(const char *ident)
-{
-    checkPredefined(0, ident);
-    addPredefinedGlobalIdent(ident);
-}
-
-void VersionCondition::addPredefinedGlobalIdent(const char *ident)
-{
-    if (!global.params.versionids)
-	global.params.versionids = new Array();
-    global.params.versionids->push((void *)ident);
-}
-
-
-VersionCondition::VersionCondition(Module *mod, unsigned level, Identifier *ident)
-    : DVCondition(mod, level, ident)
-{
-}
-
-int VersionCondition::include(Scope *sc, ScopeDsymbol *s)
-{
-    //printf("VersionCondition::include() level = %d, versionlevel = %d\n", level, global.params.versionlevel);
-    //if (ident) printf("\tident = '%s'\n", ident->toChars());
-    if (inc == 0)
-    {
-	inc = 2;
-	if (ident)
-	{
-	    if (findCondition(mod->versionids, ident))
-		inc = 1;
-	    else if (findCondition(global.params.versionids, ident))
-		inc = 1;
-	    else
-	    {
-		if (!mod->versionidsNot)
-		    mod->versionidsNot = new Array();
-		mod->versionidsNot->push(ident->toChars());
-	    }
-	}
-	else if (level <= global.params.versionlevel || level <= mod->versionlevel)
-	    inc = 1;
-    }
-    return (inc == 1);
-}
-
-void VersionCondition::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{
-    if (ident)
-	buf->printf("version (%s)", ident->toChars());
-    else
-	buf->printf("version (%u)", level);
-}
-
-
-/**************************** StaticIfCondition *******************************/
-
-StaticIfCondition::StaticIfCondition(Loc loc, Expression *exp)
-    : Condition(loc)
-{
-    this->exp = exp;
-}
-
-Condition *StaticIfCondition::syntaxCopy()
-{
-    return new StaticIfCondition(loc, exp->syntaxCopy());
-}
-
-int StaticIfCondition::include(Scope *sc, ScopeDsymbol *s)
-{
-#if 0
-    printf("StaticIfCondition::include(sc = %p, s = %p)\n", sc, s);
-    if (s)
-    {
-	printf("\ts = '%s', kind = %s\n", s->toChars(), s->kind());
-    }
-#endif
-    if (inc == 0)
-    {
-	if (!sc)
-	{
-	    error(loc, "static if conditional cannot be at global scope");
-	    inc = 2;
-	    return 0;
-	}
-
-	sc = sc->push(sc->scopesym);
-	sc->sd = s;			// s gets any addMember()
-	sc->flags |= SCOPEstaticif;
-	Expression *e = exp->semantic(sc);
-	sc->pop();
-	e = e->optimize(WANTvalue | WANTinterpret);
-	if (e->isBool(TRUE))
-	    inc = 1;
-	else if (e->isBool(FALSE))
-	    inc = 2;
-	else
-	{
-	    e->error("expression %s is not constant or does not evaluate to a bool", e->toChars());
-	    inc = 2;
-	}
-    }
-    return (inc == 1);
-}
-
-void StaticIfCondition::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{
-    buf->writestring("static if(");
-    exp->toCBuffer(buf, hgs);
-    buf->writeByte(')');
-}
-
-
-/**************************** IftypeCondition *******************************/
-
-IftypeCondition::IftypeCondition(Loc loc, Type *targ, Identifier *id, enum TOK tok, Type *tspec)
-    : Condition(loc)
-{
-    this->targ = targ;
-    this->id = id;
-    this->tok = tok;
-    this->tspec = tspec;
-}
-
-Condition *IftypeCondition::syntaxCopy()
-{
-    return new IftypeCondition(loc,
-	targ->syntaxCopy(),
-	id,
-	tok,
-	tspec ? tspec->syntaxCopy() : NULL);
-}
-
-int IftypeCondition::include(Scope *sc, ScopeDsymbol *sd)
-{
-    //printf("IftypeCondition::include()\n");
-    if (inc == 0)
-    {
-	if (!sc)
-	{
-	    error(loc, "iftype conditional cannot be at global scope");
-	    inc = 2;
-	    return 0;
-	}
-	unsigned errors = global.errors;
-	global.gag++;			// suppress printing of error messages
-	targ = targ->semantic(loc, sc);
-	global.gag--;
-	if (errors != global.errors)	// if any errors happened
-	{   inc = 2;			// then condition is false
-	    global.errors = errors;
-	}
-	else if (id && tspec)
-	{
-	    /* Evaluate to TRUE if targ matches tspec.
-	     * If TRUE, declare id as an alias for the specialized type.
-	     */
-
-	    MATCH m;
-	    TemplateTypeParameter tp(loc, id, NULL, NULL);
-
-	    TemplateParameters parameters;
-	    parameters.setDim(1);
-	    parameters.data[0] = (void *)&tp;
-
-	    Objects dedtypes;
-	    dedtypes.setDim(1);
-
-	    m = targ->deduceType(NULL, tspec, &parameters, &dedtypes);
-	    if (m == MATCHnomatch ||
-		(m != MATCHexact && tok == TOKequal))
-		inc = 2;
-	    else
-	    {
-		inc = 1;
-		Type *tded = (Type *)dedtypes.data[0];
-		if (!tded)
-		    tded = targ;
-		Dsymbol *s = new AliasDeclaration(loc, id, tded);
-		s->semantic(sc);
-		sc->insert(s);
-		if (sd)
-		    s->addMember(sc, sd, 1);
-	    }
-	}
-	else if (id)
-	{
-	    /* Declare id as an alias for type targ. Evaluate to TRUE
-	     */
-	    Dsymbol *s = new AliasDeclaration(loc, id, targ);
-	    s->semantic(sc);
-	    sc->insert(s);
-	    if (sd)
-		s->addMember(sc, sd, 1);
-	    inc = 1;
-	}
-	else if (tspec)
-	{
-	    /* Evaluate to TRUE if targ matches tspec
-	     */
-	    tspec = tspec->semantic(loc, sc);
-	    //printf("targ  = %s\n", targ->toChars());
-	    //printf("tspec = %s\n", tspec->toChars());
-	    if (tok == TOKcolon)
-	    {   if (targ->implicitConvTo(tspec))
-		    inc = 1;
-		else
-		    inc = 2;
-	    }
-	    else /* == */
-	    {	if (targ->equals(tspec))
-		    inc = 1;
-		else
-		    inc = 2;
-	    }
-	}
-	else
-	     inc = 1;
-	//printf("inc = %d\n", inc);
-    }
-    return (inc == 1);
-}
-
-void IftypeCondition::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{
-    buf->writestring("iftype(");
-    targ->toCBuffer(buf, id, hgs);
-    if (tspec)
-    {
-	if (tok == TOKcolon)
-	    buf->writestring(" : ");
-	else
-	    buf->writestring(" == ");
-	tspec->toCBuffer(buf, NULL, hgs);
-    }
-    buf->writeByte(')');
-}
-
-
+
+// 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 "id.h"
+#include "init.h"
+#include "declaration.h"
+#include "identifier.h"
+#include "expression.h"
+#include "cond.h"
+#include "module.h"
+#include "template.h"
+#include "lexer.h"
+#ifdef _DH
+#include "mtype.h"
+#include "scope.h"
+#endif
+
+int findCondition(Array *ids, Identifier *ident)
+{
+    if (ids)
+    {
+	for (int i = 0; i < ids->dim; i++)
+	{
+	    const char *id = (const char *)ids->data[i];
+
+	    if (strcmp(id, ident->toChars()) == 0)
+		return TRUE;
+	}
+    }
+
+    return FALSE;
+}
+
+/* ============================================================ */
+
+Condition::Condition(Loc loc)
+{
+    this->loc = loc;
+    inc = 0;
+}
+
+/* ============================================================ */
+
+DVCondition::DVCondition(Module *mod, unsigned level, Identifier *ident)
+	: Condition(0)
+{
+    this->mod = mod;
+    this->level = level;
+    this->ident = ident;
+}
+
+Condition *DVCondition::syntaxCopy()
+{
+    return this;	// don't need to copy
+}
+
+/* ============================================================ */
+
+void DebugCondition::setGlobalLevel(unsigned level)
+{
+    global.params.debuglevel = level;
+}
+
+void DebugCondition::addGlobalIdent(const char *ident)
+{
+    if (!global.params.debugids)
+	global.params.debugids = new Array();
+    global.params.debugids->push((void *)ident);
+}
+
+
+DebugCondition::DebugCondition(Module *mod, unsigned level, Identifier *ident)
+    : DVCondition(mod, level, ident)
+{
+}
+
+int DebugCondition::include(Scope *sc, ScopeDsymbol *s)
+{
+    //printf("DebugCondition::include() level = %d, debuglevel = %d\n", level, global.params.debuglevel);
+    if (inc == 0)
+    {
+	inc = 2;
+	if (ident)
+	{
+	    if (findCondition(mod->debugids, ident))
+		inc = 1;
+	    else if (findCondition(global.params.debugids, ident))
+		inc = 1;
+	    else
+	    {	if (!mod->debugidsNot)
+		    mod->debugidsNot = new Array();
+		mod->debugidsNot->push(ident->toChars());
+	    }
+	}
+	else if (level <= global.params.debuglevel || level <= mod->debuglevel)
+	    inc = 1;
+    }
+    return (inc == 1);
+}
+
+void DebugCondition::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    if (ident)
+	buf->printf("debug (%s)", ident->toChars());
+    else
+	buf->printf("debug (%u)", level);
+}
+
+/* ============================================================ */
+
+void VersionCondition::setGlobalLevel(unsigned level)
+{
+    global.params.versionlevel = level;
+}
+
+void VersionCondition::checkPredefined(Loc loc, const char *ident)
+{
+    static const char* reserved[] =
+    {
+	"DigitalMars", "X86", "X86_64",
+	"Windows", "Win32", "Win64",
+	"linux",
+#if DMDV2
+	/* Although Posix is predefined by D1, disallowing its
+	 * redefinition breaks makefiles and older builds.
+	 */
+	"Posix",
+	"D_NET",
+#endif
+	"OSX", "FreeBSD",
+	"Solaris",
+	"LittleEndian", "BigEndian",
+	"all",
+	"none",
+
+    // LDC
+    "LLVM", "LDC", "LLVM64",
+    "PPC", "PPC64",
+    "darwin","solaris","freebsd"
+    };
+
+    for (unsigned i = 0; i < sizeof(reserved) / sizeof(reserved[0]); i++)
+    {
+	if (strcmp(ident, reserved[i]) == 0)
+	    goto Lerror;
+    }
+
+    if (ident[0] == 'D' && ident[1] == '_')
+	goto Lerror;
+
+    return;
+
+  Lerror:
+    error(loc, "version identifier '%s' is reserved and cannot be set", ident);
+}
+
+void VersionCondition::addGlobalIdent(const char *ident)
+{
+    checkPredefined(0, ident);
+    addPredefinedGlobalIdent(ident);
+}
+
+void VersionCondition::addPredefinedGlobalIdent(const char *ident)
+{
+    if (!global.params.versionids)
+	global.params.versionids = new Array();
+    global.params.versionids->push((void *)ident);
+}
+
+
+VersionCondition::VersionCondition(Module *mod, unsigned level, Identifier *ident)
+    : DVCondition(mod, level, ident)
+{
+}
+
+int VersionCondition::include(Scope *sc, ScopeDsymbol *s)
+{
+    //printf("VersionCondition::include() level = %d, versionlevel = %d\n", level, global.params.versionlevel);
+    //if (ident) printf("\tident = '%s'\n", ident->toChars());
+    if (inc == 0)
+    {
+	inc = 2;
+	if (ident)
+	{
+	    if (findCondition(mod->versionids, ident))
+		inc = 1;
+	    else if (findCondition(global.params.versionids, ident))
+		inc = 1;
+	    else
+	    {
+		if (!mod->versionidsNot)
+		    mod->versionidsNot = new Array();
+		mod->versionidsNot->push(ident->toChars());
+	    }
+	}
+	else if (level <= global.params.versionlevel || level <= mod->versionlevel)
+	    inc = 1;
+    }
+    return (inc == 1);
+}
+
+void VersionCondition::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    if (ident)
+	buf->printf("version (%s)", ident->toChars());
+    else
+	buf->printf("version (%u)", level);
+}
+
+
+/**************************** StaticIfCondition *******************************/
+
+StaticIfCondition::StaticIfCondition(Loc loc, Expression *exp)
+    : Condition(loc)
+{
+    this->exp = exp;
+}
+
+Condition *StaticIfCondition::syntaxCopy()
+{
+    return new StaticIfCondition(loc, exp->syntaxCopy());
+}
+
+int StaticIfCondition::include(Scope *sc, ScopeDsymbol *s)
+{
+#if 0
+    printf("StaticIfCondition::include(sc = %p, s = %p)\n", sc, s);
+    if (s)
+    {
+	printf("\ts = '%s', kind = %s\n", s->toChars(), s->kind());
+    }
+#endif
+    if (inc == 0)
+    {
+	if (!sc)
+	{
+	    error(loc, "static if conditional cannot be at global scope");
+	    inc = 2;
+	    return 0;
+	}
+
+	sc = sc->push(sc->scopesym);
+	sc->sd = s;			// s gets any addMember()
+	sc->flags |= SCOPEstaticif;
+	Expression *e = exp->semantic(sc);
+	sc->pop();
+	e = e->optimize(WANTvalue | WANTinterpret);
+	if (e->isBool(TRUE))
+	    inc = 1;
+	else if (e->isBool(FALSE))
+	    inc = 2;
+	else
+	{
+	    e->error("expression %s is not constant or does not evaluate to a bool", e->toChars());
+	    inc = 2;
+	}
+    }
+    return (inc == 1);
+}
+
+void StaticIfCondition::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    buf->writestring("static if(");
+    exp->toCBuffer(buf, hgs);
+    buf->writeByte(')');
+}
+
+
+/**************************** IftypeCondition *******************************/
+
+IftypeCondition::IftypeCondition(Loc loc, Type *targ, Identifier *id, enum TOK tok, Type *tspec)
+    : Condition(loc)
+{
+    this->targ = targ;
+    this->id = id;
+    this->tok = tok;
+    this->tspec = tspec;
+}
+
+Condition *IftypeCondition::syntaxCopy()
+{
+    return new IftypeCondition(loc,
+	targ->syntaxCopy(),
+	id,
+	tok,
+	tspec ? tspec->syntaxCopy() : NULL);
+}
+
+int IftypeCondition::include(Scope *sc, ScopeDsymbol *sd)
+{
+    //printf("IftypeCondition::include()\n");
+    if (inc == 0)
+    {
+	if (!sc)
+	{
+	    error(loc, "iftype conditional cannot be at global scope");
+	    inc = 2;
+	    return 0;
+	}
+	Type *t = targ->trySemantic(loc, sc);
+	if (t)
+	    targ = t;
+	else
+	    inc = 2;			// condition is false
+
+	if (!t)
+	{
+	}
+	else if (id && tspec)
+	{
+	    /* Evaluate to TRUE if targ matches tspec.
+	     * If TRUE, declare id as an alias for the specialized type.
+	     */
+
+	    MATCH m;
+	    TemplateTypeParameter tp(loc, id, NULL, NULL);
+
+	    TemplateParameters parameters;
+	    parameters.setDim(1);
+	    parameters.data[0] = (void *)&tp;
+
+	    Objects dedtypes;
+	    dedtypes.setDim(1);
+
+	    m = targ->deduceType(NULL, tspec, &parameters, &dedtypes);
+	    if (m == MATCHnomatch ||
+		(m != MATCHexact && tok == TOKequal))
+		inc = 2;
+	    else
+	    {
+		inc = 1;
+		Type *tded = (Type *)dedtypes.data[0];
+		if (!tded)
+		    tded = targ;
+		Dsymbol *s = new AliasDeclaration(loc, id, tded);
+		s->semantic(sc);
+		sc->insert(s);
+		if (sd)
+		    s->addMember(sc, sd, 1);
+	    }
+	}
+	else if (id)
+	{
+	    /* Declare id as an alias for type targ. Evaluate to TRUE
+	     */
+	    Dsymbol *s = new AliasDeclaration(loc, id, targ);
+	    s->semantic(sc);
+	    sc->insert(s);
+	    if (sd)
+		s->addMember(sc, sd, 1);
+	    inc = 1;
+	}
+	else if (tspec)
+	{
+	    /* Evaluate to TRUE if targ matches tspec
+	     */
+	    tspec = tspec->semantic(loc, sc);
+	    //printf("targ  = %s\n", targ->toChars());
+	    //printf("tspec = %s\n", tspec->toChars());
+	    if (tok == TOKcolon)
+	    {   if (targ->implicitConvTo(tspec))
+		    inc = 1;
+		else
+		    inc = 2;
+	    }
+	    else /* == */
+	    {	if (targ->equals(tspec))
+		    inc = 1;
+		else
+		    inc = 2;
+	    }
+	}
+	else
+	     inc = 1;
+	//printf("inc = %d\n", inc);
+    }
+    return (inc == 1);
+}
+
+void IftypeCondition::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    buf->writestring("iftype(");
+    targ->toCBuffer(buf, id, hgs);
+    if (tspec)
+    {
+	if (tok == TOKcolon)
+	    buf->writestring(" : ");
+	else
+	    buf->writestring(" == ");
+	tspec->toCBuffer(buf, NULL, hgs);
+    }
+    buf->writeByte(')');
+}
+
+
--- a/dmd2/constfold.c	Mon Jun 01 01:28:18 2009 +0200
+++ b/dmd2/constfold.c	Mon Jun 01 19:02:20 2009 +0100
@@ -1,1606 +1,1596 @@
-
-// Compiler implementation of the D programming language
-// Copyright (c) 1999-2007 by Digital Mars
-// All Rights Reserved
-// written by Walter Bright
-// http://www.digitalmars.com
-// License for redistribution is by either the Artistic License
-// in artistic.txt, or the GNU General Public License in gnu.txt.
-// See the included readme.txt for details.
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <assert.h>
-#include <math.h>
-
-#if __DMC__
-#include <complex.h>
-#endif
-
-#include "mem.h"
-#include "root.h"
-
-#include "mtype.h"
-#include "expression.h"
-#include "aggregate.h"
-#include "declaration.h"
-
-#ifdef IN_GCC
-#include "d-gcc-real.h"
-
-/* %% fix? */
-extern "C" bool real_isnan (const real_t *);
-#endif
-
-static real_t zero;	// work around DMC bug for now
-
-#define LOG 0
-
-Expression *expType(Type *type, Expression *e)
-{
-    if (type != e->type)
-    {
-	e = e->copy();
-	e->type = type;
-    }
-    return e;
-}
-
-/* ================================== isConst() ============================== */
-
-int Expression::isConst()
-{
-    //printf("Expression::isConst(): %s\n", toChars());
-    return 0;
-}
-
-int IntegerExp::isConst()
-{
-    return 1;
-}
-
-int RealExp::isConst()
-{
-    return 1;
-}
-
-int ComplexExp::isConst()
-{
-    return 1;
-}
-
-int SymOffExp::isConst()
-{
-    return 2;
-}
-
-/* =============================== constFold() ============================== */
-
-/* The constFold() functions were redundant with the optimize() ones,
- * and so have been folded in with them.
- */
-
-/* ========================================================================== */
-
-Expression *Neg(Type *type, Expression *e1)
-{   Expression *e;
-    Loc loc = e1->loc;
-
-    if (e1->type->isreal())
-    {
-	e = new RealExp(loc, -e1->toReal(), type);
-    }
-    else if (e1->type->isimaginary())
-    {
-	e = new RealExp(loc, -e1->toImaginary(), type);
-    }
-    else if (e1->type->iscomplex())
-    {
-	e = new ComplexExp(loc, -e1->toComplex(), type);
-    }
-    else
-	e = new IntegerExp(loc, -e1->toInteger(), type);
-    return e;
-}
-
-Expression *Com(Type *type, Expression *e1)
-{   Expression *e;
-    Loc loc = e1->loc;
-
-    e = new IntegerExp(loc, ~e1->toInteger(), type);
-    return e;
-}
-
-Expression *Not(Type *type, Expression *e1)
-{   Expression *e;
-    Loc loc = e1->loc;
-
-    e = new IntegerExp(loc, e1->isBool(0), type);
-    return e;
-}
-
-Expression *Bool(Type *type, Expression *e1)
-{   Expression *e;
-    Loc loc = e1->loc;
-
-    e = new IntegerExp(loc, e1->isBool(1), type);
-    return e;
-}
-
-Expression *Add(Type *type, Expression *e1, Expression *e2)
-{   Expression *e;
-    Loc loc = e1->loc;
-
-#if LOG
-    printf("Add(e1 = %s, e2 = %s)\n", e1->toChars(), e2->toChars());
-#endif
-    if (type->isreal())
-    {
-	e = new RealExp(loc, e1->toReal() + e2->toReal(), type);
-    }
-    else if (type->isimaginary())
-    {
-	e = new RealExp(loc, e1->toImaginary() + e2->toImaginary(), type);
-    }
-    else if (type->iscomplex())
-    {
-	// This rigamarole is necessary so that -0.0 doesn't get
-	// converted to +0.0 by doing an extraneous add with +0.0
-	complex_t c1;
-	real_t r1;
-	real_t i1;
-
-	complex_t c2;
-	real_t r2;
-	real_t i2;
-
-	complex_t v;
-	int x;
-
-	if (e1->type->isreal())
-	{   r1 = e1->toReal();
-	    x = 0;
-	}
-	else if (e1->type->isimaginary())
-	{   i1 = e1->toImaginary();
-	    x = 3;
-	}
-	else
-	{   c1 = e1->toComplex();
-	    x = 6;
-	}
-
-	if (e2->type->isreal())
-	{   r2 = e2->toReal();
-	}
-	else if (e2->type->isimaginary())
-	{   i2 = e2->toImaginary();
-	    x += 1;
-	}
-	else
-	{   c2 = e2->toComplex();
-	    x += 2;
-	}
-
-	switch (x)
-	{
-#if __DMC__
-	    case 0+0:	v = (complex_t) (r1 + r2);	break;
-	    case 0+1:	v = r1 + i2 * I;		break;
-	    case 0+2:	v = r1 + c2;			break;
-	    case 3+0:	v = i1 * I + r2;		break;
-	    case 3+1:	v = (complex_t) ((i1 + i2) * I); break;
-	    case 3+2:	v = i1 * I + c2;		break;
-	    case 6+0:	v = c1 + r2;			break;
-	    case 6+1:	v = c1 + i2 * I;		break;
-	    case 6+2:	v = c1 + c2;			break;
-#else
-	    case 0+0:	v = complex_t(r1 + r2, 0);	break;
-	    case 0+1:	v = complex_t(r1, i2);		break;
-	    case 0+2:	v = complex_t(r1 + creall(c2), cimagl(c2));	break;
-	    case 3+0:	v = complex_t(r2, i1);		break;
-	    case 3+1:	v = complex_t(0, i1 + i2);	break;
-	    case 3+2:	v = complex_t(creall(c2), i1 + cimagl(c2));	break;
-	    case 6+0:	v = complex_t(creall(c1) + r2, cimagl(c2));	break;
-	    case 6+1:	v = complex_t(creall(c1), cimagl(c1) + i2);	break;
-	    case 6+2:	v = c1 + c2;			break;
-#endif
-	    default: assert(0);
-	}
-	e = new ComplexExp(loc, v, type);
-    }
-    else if (e1->op == TOKsymoff)
-    {
-	SymOffExp *soe = (SymOffExp *)e1;
-	e = new SymOffExp(loc, soe->var, soe->offset + e2->toInteger());
-	e->type = type;
-    }
-    else if (e2->op == TOKsymoff)
-    {
-	SymOffExp *soe = (SymOffExp *)e2;
-	e = new SymOffExp(loc, soe->var, soe->offset + e1->toInteger());
-	e->type = type;
-    }
-    else
-	e = new IntegerExp(loc, e1->toInteger() + e2->toInteger(), type);
-    return e;
-}
-
-
-Expression *Min(Type *type, Expression *e1, Expression *e2)
-{   Expression *e;
-    Loc loc = e1->loc;
-
-    if (type->isreal())
-    {
-	e = new RealExp(loc, e1->toReal() - e2->toReal(), type);
-    }
-    else if (type->isimaginary())
-    {
-	e = new RealExp(loc, e1->toImaginary() - e2->toImaginary(), type);
-    }
-    else if (type->iscomplex())
-    {
-	// This rigamarole is necessary so that -0.0 doesn't get
-	// converted to +0.0 by doing an extraneous add with +0.0
-	complex_t c1;
-	real_t r1;
-	real_t i1;
-
-	complex_t c2;
-	real_t r2;
-	real_t i2;
-
-	complex_t v;
-	int x;
-
-	if (e1->type->isreal())
-	{   r1 = e1->toReal();
-	    x = 0;
-	}
-	else if (e1->type->isimaginary())
-	{   i1 = e1->toImaginary();
-	    x = 3;
-	}
-	else
-	{   c1 = e1->toComplex();
-	    x = 6;
-	}
-
-	if (e2->type->isreal())
-	{   r2 = e2->toReal();
-	}
-	else if (e2->type->isimaginary())
-	{   i2 = e2->toImaginary();
-	    x += 1;
-	}
-	else
-	{   c2 = e2->toComplex();
-	    x += 2;
-	}
-
-	switch (x)
-	{
-#if __DMC__
-	    case 0+0:	v = (complex_t) (r1 - r2);	break;
-	    case 0+1:	v = r1 - i2 * I;		break;
-	    case 0+2:	v = r1 - c2;			break;
-	    case 3+0:	v = i1 * I - r2;		break;
-	    case 3+1:	v = (complex_t) ((i1 - i2) * I); break;
-	    case 3+2:	v = i1 * I - c2;		break;
-	    case 6+0:	v = c1 - r2;			break;
-	    case 6+1:	v = c1 - i2 * I;		break;
-	    case 6+2:	v = c1 - c2;			break;
-#else
-	    case 0+0:	v = complex_t(r1 - r2, 0);	break;
-	    case 0+1:	v = complex_t(r1, -i2);		break;
-	    case 0+2:	v = complex_t(r1 - creall(c2), -cimagl(c2));	break;
-	    case 3+0:	v = complex_t(-r2, i1);		break;
-	    case 3+1:	v = complex_t(0, i1 - i2);	break;
-	    case 3+2:	v = complex_t(-creall(c2), i1 - cimagl(c2));	break;
-	    case 6+0:	v = complex_t(creall(c1) - r2, cimagl(c1));	break;
-	    case 6+1:	v = complex_t(creall(c1), cimagl(c1) - i2);	break;
-	    case 6+2:	v = c1 - c2;			break;
-#endif
-	    default: assert(0);
-	}
-	e = new ComplexExp(loc, v, type);
-    }
-    else if (e1->op == TOKsymoff)
-    {
-	SymOffExp *soe = (SymOffExp *)e1;
-	e = new SymOffExp(loc, soe->var, soe->offset - e2->toInteger());
-	e->type = type;
-    }
-    else
-    {
-	e = new IntegerExp(loc, e1->toInteger() - e2->toInteger(), type);
-    }
-    return e;
-}
-
-Expression *Mul(Type *type, Expression *e1, Expression *e2)
-{   Expression *e;
-    Loc loc = e1->loc;
-
-    if (type->isfloating())
-    {   complex_t c;
-#ifdef IN_GCC
-	real_t r;
-#else
-	d_float80 r;
-#endif
-
-	if (e1->type->isreal())
-	{
-#if __DMC__
-	    c = e1->toReal() * e2->toComplex();
-#else
-	    r = e1->toReal();
-	    c = e2->toComplex();
-	    c = complex_t(r * creall(c), r * cimagl(c));
-#endif
-	}
-	else if (e1->type->isimaginary())
-	{
-#if __DMC__
-	    c = e1->toImaginary() * I * e2->toComplex();
-#else
-	    r = e1->toImaginary();
-	    c = e2->toComplex();
-	    c = complex_t(-r * cimagl(c), r * creall(c));
-#endif
-	}
-	else if (e2->type->isreal())
-	{
-#if __DMC__
-	    c = e2->toReal() * e1->toComplex();
-#else
-	    r = e2->toReal();
-	    c = e1->toComplex();
-	    c = complex_t(r * creall(c), r * cimagl(c));
-#endif
-	}
-	else if (e2->type->isimaginary())
-	{
-#if __DMC__
-	    c = e1->toComplex() * e2->toImaginary() * I;
-#else
-	    r = e2->toImaginary();
-	    c = e1->toComplex();
-	    c = complex_t(-r * cimagl(c), r * creall(c));
-#endif
-	}
-	else
-	    c = e1->toComplex() * e2->toComplex();
-
-	if (type->isreal())
-	    e = new RealExp(loc, creall(c), type);
-	else if (type->isimaginary())
-	    e = new RealExp(loc, cimagl(c), type);
-	else if (type->iscomplex())
-	    e = new ComplexExp(loc, c, type);
-	else
-	    assert(0);
-    }
-    else
-    {
-	e = new IntegerExp(loc, e1->toInteger() * e2->toInteger(), type);
-    }
-    return e;
-}
-
-Expression *Div(Type *type, Expression *e1, Expression *e2)
-{   Expression *e;
-    Loc loc = e1->loc;
-
-    if (type->isfloating())
-    {   complex_t c;
-#ifdef IN_GCC
-	real_t r;
-#else
-	d_float80 r;
-#endif
-
-	//e1->type->print();
-	//e2->type->print();
-	if (e2->type->isreal())
-	{
-	    if (e1->type->isreal())
-	    {
-		e = new RealExp(loc, e1->toReal() / e2->toReal(), type);
-		return e;
-	    }
-#if __DMC__
-	    //r = e2->toReal();
-	    //c = e1->toComplex();
-	    //printf("(%Lg + %Lgi) / %Lg\n", creall(c), cimagl(c), r);
-
-	    c = e1->toComplex() / e2->toReal();
-#else
-	    r = e2->toReal();
-	    c = e1->toComplex();
-	    c = complex_t(creall(c) / r, cimagl(c) / r);
-#endif
-	}
-	else if (e2->type->isimaginary())
-	{
-#if __DMC__
-	    //r = e2->toImaginary();
-	    //c = e1->toComplex();
-	    //printf("(%Lg + %Lgi) / %Lgi\n", creall(c), cimagl(c), r);
-
-	    c = e1->toComplex() / (e2->toImaginary() * I);
-#else
-	    r = e2->toImaginary();
-	    c = e1->toComplex();
-	    c = complex_t(cimagl(c) / r, -creall(c) / r);
-#endif
-	}
-	else
-	{
-	    c = e1->toComplex() / e2->toComplex();
-	}
-
-	if (type->isreal())
-	    e = new RealExp(loc, creall(c), type);
-	else if (type->isimaginary())
-	    e = new RealExp(loc, cimagl(c), type);
-	else if (type->iscomplex())
-	    e = new ComplexExp(loc, c, type);
-	else
-	    assert(0);
-    }
-    else
-    {   sinteger_t n1;
-	sinteger_t n2;
-	sinteger_t n;
-
-	n1 = e1->toInteger();
-	n2 = e2->toInteger();
-	if (n2 == 0)
-	{   e2->error("divide by 0");
-	    e2 = new IntegerExp(loc, 1, e2->type);
-	    n2 = 1;
-	}
-	if (e1->type->isunsigned() || e2->type->isunsigned())
-	    n = ((d_uns64) n1) / ((d_uns64) n2);
-	else
-	    n = n1 / n2;
-	e = new IntegerExp(loc, n, type);
-    }
-    return e;
-}
-
-Expression *Mod(Type *type, Expression *e1, Expression *e2)
-{   Expression *e;
-    Loc loc = e1->loc;
-
-    if (type->isfloating())
-    {
-	complex_t c;
-
-	if (e2->type->isreal())
-	{   real_t r2 = e2->toReal();
-
-#ifdef __DMC__
-	    c = fmodl(e1->toReal(), r2) + fmodl(e1->toImaginary(), r2) * I;
-#elif defined(IN_GCC)
-	    c = complex_t(e1->toReal() % r2, e1->toImaginary() % r2);
-#elif (defined(__FreeBSD__) && __FreeBSD_version < 800000) || defined(__arm__) || defined(__thumb__)
-	// freebsd is kinda messed up. the STABLE branch doesn't support C99's fmodl !?!
-	// arm also doesn't like fmodl
-	    c = complex_t(fmod(e1->toReal(), r2), fmod(e1->toImaginary(), r2));
-#else
-	    c = complex_t(fmodl(e1->toReal(), r2), fmodl(e1->toImaginary(), r2));
-#endif
-	}
-	else if (e2->type->isimaginary())
-	{   real_t i2 = e2->toImaginary();
-
-#ifdef __DMC__
-	    c = fmodl(e1->toReal(), i2) + fmodl(e1->toImaginary(), i2) * I;
-#elif defined(IN_GCC)
-	    c = complex_t(e1->toReal() % i2, e1->toImaginary() % i2);
-#elif (defined(__FreeBSD__) && __FreeBSD_version < 800000) || defined(__arm__) || defined(__thumb__)
-        // freebsd is kinda messed up. the STABLE branch doesn't support C99's fmodl !?!
-	// arm also doesn't like fmodl
-	    c = complex_t(fmod(e1->toReal(), i2), fmod(e1->toImaginary(), i2));
-#else
-	    c = complex_t(fmodl(e1->toReal(), i2), fmodl(e1->toImaginary(), i2));
-#endif
-	}
-	else
-	    assert(0);
-
-	if (type->isreal())
-	    e = new RealExp(loc, creall(c), type);
-	else if (type->isimaginary())
-	    e = new RealExp(loc, cimagl(c), type);
-	else if (type->iscomplex())
-	    e = new ComplexExp(loc, c, type);
-	else
-	    assert(0);
-    }
-    else
-    {   sinteger_t n1;
-	sinteger_t n2;
-	sinteger_t n;
-
-	n1 = e1->toInteger();
-	n2 = e2->toInteger();
-	if (n2 == 0)
-	{   e2->error("divide by 0");
-	    e2 = new IntegerExp(loc, 1, e2->type);
-	    n2 = 1;
-	}
-	if (e1->type->isunsigned() || e2->type->isunsigned())
-	    n = ((d_uns64) n1) % ((d_uns64) n2);
-	else
-	    n = n1 % n2;
-	e = new IntegerExp(loc, n, type);
-    }
-    return e;
-}
-
-Expression *Shl(Type *type, Expression *e1, Expression *e2)
-{   Expression *e;
-    Loc loc = e1->loc;
-
-    e = new IntegerExp(loc, e1->toInteger() << e2->toInteger(), type);
-    return e;
-}
-
-Expression *Shr(Type *type, Expression *e1, Expression *e2)
-{   Expression *e;
-    Loc loc = e1->loc;
-    unsigned count;
-    integer_t value;
-
-    value = e1->toInteger();
-    count = e2->toInteger();
-    switch (e1->type->toBasetype()->ty)
-    {
-	case Tint8:
-		value = (d_int8)(value) >> count;
-		break;
-
-	case Tuns8:
-		value = (d_uns8)(value) >> count;
-		break;
-
-	case Tint16:
-		value = (d_int16)(value) >> count;
-		break;
-
-	case Tuns16:
-		value = (d_uns16)(value) >> count;
-		break;
-
-	case Tint32:
-		value = (d_int32)(value) >> count;
-		break;
-
-	case Tuns32:
-		value = (d_uns32)(value) >> count;
-		break;
-
-	case Tint64:
-		value = (d_int64)(value) >> count;
-		break;
-
-	case Tuns64:
-		value = (d_uns64)(value) >> count;
-		break;
-
-	default:
-		assert(0);
-    }
-    e = new IntegerExp(loc, value, type);
-    return e;
-}
-
-Expression *Ushr(Type *type, Expression *e1, Expression *e2)
-{   Expression *e;
-    Loc loc = e1->loc;
-    unsigned count;
-    integer_t value;
-
-    value = e1->toInteger();
-    count = e2->toInteger();
-    switch (e1->type->toBasetype()->ty)
-    {
-	case Tint8:
-	case Tuns8:
-		assert(0);		// no way to trigger this
-		value = (value & 0xFF) >> count;
-		break;
-
-	case Tint16:
-	case Tuns16:
-		assert(0);		// no way to trigger this
-		value = (value & 0xFFFF) >> count;
-		break;
-
-	case Tint32:
-	case Tuns32:
-		value = (value & 0xFFFFFFFF) >> count;
-		break;
-
-	case Tint64:
-	case Tuns64:
-		value = (d_uns64)(value) >> count;
-		break;
-
-	default:
-		assert(0);
-    }
-    e = new IntegerExp(loc, value, type);
-    return e;
-}
-
-Expression *And(Type *type, Expression *e1, Expression *e2)
-{
-    Expression *e;
-    e = new IntegerExp(e1->loc, e1->toInteger() & e2->toInteger(), type);
-    return e;
-}
-
-Expression *Or(Type *type, Expression *e1, Expression *e2)
-{   Expression *e;
-    e = new IntegerExp(e1->loc, e1->toInteger() | e2->toInteger(), type);
-    return e;
-}
-
-Expression *Xor(Type *type, Expression *e1, Expression *e2)
-{   Expression *e;
-    e = new IntegerExp(e1->loc, e1->toInteger() ^ e2->toInteger(), type);
-    return e;
-}
-
-/* Also returns EXP_CANT_INTERPRET if cannot be computed.
- */
-Expression *Equal(enum TOK op, Type *type, Expression *e1, Expression *e2)
-{   Expression *e;
-    Loc loc = e1->loc;
-    int cmp;
-    real_t r1;
-    real_t r2;
-
-    //printf("Equal(e1 = %s, e2 = %s)\n", e1->toChars(), e2->toChars());
-
-    assert(op == TOKequal || op == TOKnotequal);
-
-    if (e1->op == TOKnull)
-    {
-	if (e2->op == TOKnull)
-	    cmp = 1;
-	else if (e2->op == TOKstring)
-	{   StringExp *es2 = (StringExp *)e2;
-	    cmp = (0 == es2->len);
-	}
-	else if (e2->op == TOKarrayliteral)
-	{   ArrayLiteralExp *es2 = (ArrayLiteralExp *)e2;
-	    cmp = !es2->elements || (0 == es2->elements->dim);
-	}
-	else
-	    return EXP_CANT_INTERPRET;
-    }
-    else if (e2->op == TOKnull)
-    {
-	if (e1->op == TOKstring)
-	{   StringExp *es1 = (StringExp *)e1;
-	    cmp = (0 == es1->len);
-	}
-	else if (e1->op == TOKarrayliteral)
-	{   ArrayLiteralExp *es1 = (ArrayLiteralExp *)e1;
-	    cmp = !es1->elements || (0 == es1->elements->dim);
-	}
-	else
-	    return EXP_CANT_INTERPRET;
-    }
-    else if (e1->op == TOKstring && e2->op == TOKstring)
-    {	StringExp *es1 = (StringExp *)e1;
-	StringExp *es2 = (StringExp *)e2;
-
-	if (es1->sz != es2->sz)
-	{
-	    assert(global.errors);
-	    return EXP_CANT_INTERPRET;
-	}
-	if (es1->len == es2->len &&
-	    memcmp(es1->string, es2->string, es1->sz * es1->len) == 0)
-	    cmp = 1;
-	else
-	    cmp = 0;
-    }
-    else if (e1->op == TOKarrayliteral && e2->op == TOKarrayliteral)
-    {   ArrayLiteralExp *es1 = (ArrayLiteralExp *)e1;
-	ArrayLiteralExp *es2 = (ArrayLiteralExp *)e2;
-
-	if ((!es1->elements || !es1->elements->dim) &&
-	    (!es2->elements || !es2->elements->dim))
-	    cmp = 1;		// both arrays are empty
-	else if (!es1->elements || !es2->elements)
-	    cmp = 0;
-	else if (es1->elements->dim != es2->elements->dim)
-	    cmp = 0;
-	else
-	{
-	    for (size_t i = 0; i < es1->elements->dim; i++)
-	    {   Expression *ee1 = (Expression *)es1->elements->data[i];
-		Expression *ee2 = (Expression *)es2->elements->data[i];
-
-		Expression *v = Equal(TOKequal, Type::tint32, ee1, ee2);
-		if (v == EXP_CANT_INTERPRET)
-		    return EXP_CANT_INTERPRET;
-		cmp = v->toInteger();
-		if (cmp == 0)
-		    break;
-	    }
-	}
-    }
-    else if (e1->op == TOKarrayliteral && e2->op == TOKstring)
-    {	// Swap operands and use common code
-	Expression *e = e1;
-	e1 = e2;
-	e2 = e;
-	goto Lsa;
-    }
-    else if (e1->op == TOKstring && e2->op == TOKarrayliteral)
-    {
-     Lsa:
-	StringExp *es1 = (StringExp *)e1;
-	ArrayLiteralExp *es2 = (ArrayLiteralExp *)e2;
-	size_t dim1 = es1->len;
-	size_t dim2 = es2->elements ? es2->elements->dim : 0;
-	if (dim1 != dim2)
-	    cmp = 0;
-	else
-	{
-	    for (size_t i = 0; i < dim1; i++)
-	    {
-		uinteger_t c = es1->charAt(i);
-		Expression *ee2 = (Expression *)es2->elements->data[i];
-		if (ee2->isConst() != 1)
-		    return EXP_CANT_INTERPRET;
-		cmp = (c == ee2->toInteger());
-		if (cmp == 0)
-		    break;
-	    }
-	}
-    }
-    else if (e1->op == TOKstructliteral && e2->op == TOKstructliteral)
-    {   StructLiteralExp *es1 = (StructLiteralExp *)e1;
-	StructLiteralExp *es2 = (StructLiteralExp *)e2;
-
-	if (es1->sd != es2->sd)
-	    cmp = 0;
-	else if ((!es1->elements || !es1->elements->dim) &&
-	    (!es2->elements || !es2->elements->dim))
-	    cmp = 1;		// both arrays are empty
-	else if (!es1->elements || !es2->elements)
-	    cmp = 0;
-	else if (es1->elements->dim != es2->elements->dim)
-	    cmp = 0;
-	else
-	{
-	    cmp = 1;
-	    for (size_t i = 0; i < es1->elements->dim; i++)
-	    {   Expression *ee1 = (Expression *)es1->elements->data[i];
-		Expression *ee2 = (Expression *)es2->elements->data[i];
-
-		if (ee1 == ee2)
-		    continue;
-		if (!ee1 || !ee2)
-		{   cmp = 0;
-		    break;
-		}
-		Expression *v = Equal(TOKequal, Type::tint32, ee1, ee2);
-		if (v == EXP_CANT_INTERPRET)
-		    return EXP_CANT_INTERPRET;
-		cmp = v->toInteger();
-		if (cmp == 0)
-		    break;
-	    }
-	}
-    }
-#if 0 // Should handle this
-    else if (e1->op == TOKarrayliteral && e2->op == TOKstring)
-    {
-    }
-#endif
-    else if (e1->isConst() != 1 || e2->isConst() != 1)
-	return EXP_CANT_INTERPRET;
-    else if (e1->type->isreal())
-    {
-	r1 = e1->toReal();
-	r2 = e2->toReal();
-	goto L1;
-    }
-    else if (e1->type->isimaginary())
-    {
-	r1 = e1->toImaginary();
-	r2 = e2->toImaginary();
-     L1:
-#if __DMC__
-	cmp = (r1 == r2);
-#else
-	if (isnan(r1) || isnan(r2))	// if unordered
-	{
-	    cmp = 0;
-	}
-	else
-	{
-	    cmp = (r1 == r2);
-	}
-#endif
-    }
-    else if (e1->type->iscomplex())
-    {
-	cmp = e1->toComplex() == e2->toComplex();
-    }
-    else if (e1->type->isintegral())
-    {
-	cmp = (e1->toInteger() == e2->toInteger());
-    }
-    else
-	return EXP_CANT_INTERPRET;
-    if (op == TOKnotequal)
-	cmp ^= 1;
-    e = new IntegerExp(loc, cmp, type);
-    return e;
-}
-
-Expression *Identity(enum TOK op, Type *type, Expression *e1, Expression *e2)
-{   Expression *e;
-    Loc loc = e1->loc;
-    int cmp;
-
-    if (e1->op == TOKnull && e2->op == TOKnull)
-    {
-	cmp = 1;
-    }
-    else if (e1->op == TOKsymoff && e2->op == TOKsymoff)
-    {
-	SymOffExp *es1 = (SymOffExp *)e1;
-	SymOffExp *es2 = (SymOffExp *)e2;
-
-	cmp = (es1->var == es2->var && es1->offset == es2->offset);
-    }
-    else if (e1->isConst() == 1 && e2->isConst() == 1)
-	return Equal((op == TOKidentity) ? TOKequal : TOKnotequal,
-		type, e1, e2);
-    else
-	assert(0);
-    if (op == TOKnotidentity)
-	cmp ^= 1;
-    return new IntegerExp(loc, cmp, type);
-}
-
-
-Expression *Cmp(enum TOK op, Type *type, Expression *e1, Expression *e2)
-{   Expression *e;
-    Loc loc = e1->loc;
-    integer_t n;
-    real_t r1;
-    real_t r2;
-
-    //printf("Cmp(e1 = %s, e2 = %s)\n", e1->toChars(), e2->toChars());
-
-    if (e1->op == TOKstring && e2->op == TOKstring)
-    {	StringExp *es1 = (StringExp *)e1;
-	StringExp *es2 = (StringExp *)e2;
-	size_t sz = es1->sz;
-	assert(sz == es2->sz);
-
-	size_t len = es1->len;
-	if (es2->len < len)
-	    len = es2->len;
-
-	int cmp = memcmp(es1->string, es2->string, sz * len);
-	if (cmp == 0)
-	    cmp = es1->len - es2->len;
-
-	switch (op)
-	{
-	    case TOKlt:	n = cmp <  0;	break;
-	    case TOKle:	n = cmp <= 0;	break;
-	    case TOKgt:	n = cmp >  0;	break;
-	    case TOKge:	n = cmp >= 0;	break;
-
-	    case TOKleg:   n = 1;		break;
-	    case TOKlg:	   n = cmp != 0;	break;
-	    case TOKunord: n = 0;		break;
-	    case TOKue:	   n = cmp == 0;	break;
-	    case TOKug:	   n = cmp >  0;	break;
-	    case TOKuge:   n = cmp >= 0;	break;
-	    case TOKul:	   n = cmp <  0;	break;
-	    case TOKule:   n = cmp <= 0;	break;
-
-	    default:
-		assert(0);
-	}
-    }
-    else if (e1->isConst() != 1 || e2->isConst() != 1)
-	return EXP_CANT_INTERPRET;
-    else if (e1->type->isreal())
-    {
-	r1 = e1->toReal();
-	r2 = e2->toReal();
-	goto L1;
-    }
-    else if (e1->type->isimaginary())
-    {
-	r1 = e1->toImaginary();
-	r2 = e2->toImaginary();
-     L1:
-#if __DMC__
-	// DMC is the only compiler I know of that handles NAN arguments
-	// correctly in comparisons.
-	switch (op)
-	{
-	    case TOKlt:	   n = r1 <  r2;	break;
-	    case TOKle:	   n = r1 <= r2;	break;
-	    case TOKgt:	   n = r1 >  r2;	break;
-	    case TOKge:	   n = r1 >= r2;	break;
-
-	    case TOKleg:   n = r1 <>=  r2;	break;
-	    case TOKlg:	   n = r1 <>   r2;	break;
-	    case TOKunord: n = r1 !<>= r2;	break;
-	    case TOKue:	   n = r1 !<>  r2;	break;
-	    case TOKug:	   n = r1 !<=  r2;	break;
-	    case TOKuge:   n = r1 !<   r2;	break;
-	    case TOKul:	   n = r1 !>=  r2;	break;
-	    case TOKule:   n = r1 !>   r2;	break;
-
-	    default:
-		assert(0);
-	}
-#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
-	{
-	    switch (op)
-	    {
-		case TOKlt:	n = 0;	break;
-		case TOKle:	n = 0;	break;
-		case TOKgt:	n = 0;	break;
-		case TOKge:	n = 0;	break;
-
-		case TOKleg:	n = 0;	break;
-		case TOKlg:	n = 0;	break;
-		case TOKunord:	n = 1;	break;
-		case TOKue:	n = 1;	break;
-		case TOKug:	n = 1;	break;
-		case TOKuge:	n = 1;	break;
-		case TOKul:	n = 1;	break;
-		case TOKule:	n = 1;	break;
-
-		default:
-		    assert(0);
-	    }
-	}
-	else
-	{
-	    switch (op)
-	    {
-		case TOKlt:	n = r1 <  r2;	break;
-		case TOKle:	n = r1 <= r2;	break;
-		case TOKgt:	n = r1 >  r2;	break;
-		case TOKge:	n = r1 >= r2;	break;
-
-		case TOKleg:	n = 1;		break;
-		case TOKlg:	n = r1 != r2;	break;
-		case TOKunord:	n = 0;		break;
-		case TOKue:	n = r1 == r2;	break;
-		case TOKug:	n = r1 >  r2;	break;
-		case TOKuge:	n = r1 >= r2;	break;
-		case TOKul:	n = r1 <  r2;	break;
-		case TOKule:	n = r1 <= r2;	break;
-
-		default:
-		    assert(0);
-	    }
-	}
-#endif
-    }
-    else if (e1->type->iscomplex())
-    {
-	assert(0);
-    }
-    else
-    {   sinteger_t n1;
-	sinteger_t n2;
-
-	n1 = e1->toInteger();
-	n2 = e2->toInteger();
-	if (e1->type->isunsigned() || e2->type->isunsigned())
-	{
-	    switch (op)
-	    {
-		case TOKlt:	n = ((d_uns64) n1) <  ((d_uns64) n2);	break;
-		case TOKle:	n = ((d_uns64) n1) <= ((d_uns64) n2);	break;
-		case TOKgt:	n = ((d_uns64) n1) >  ((d_uns64) n2);	break;
-		case TOKge:	n = ((d_uns64) n1) >= ((d_uns64) n2);	break;
-
-		case TOKleg:	n = 1;					break;
-		case TOKlg:	n = ((d_uns64) n1) != ((d_uns64) n2);	break;
-		case TOKunord:	n = 0;					break;
-		case TOKue:	n = ((d_uns64) n1) == ((d_uns64) n2);	break;
-		case TOKug:	n = ((d_uns64) n1) >  ((d_uns64) n2);	break;
-		case TOKuge:	n = ((d_uns64) n1) >= ((d_uns64) n2);	break;
-		case TOKul:	n = ((d_uns64) n1) <  ((d_uns64) n2);	break;
-		case TOKule:	n = ((d_uns64) n1) <= ((d_uns64) n2);	break;
-
-		default:
-		    assert(0);
-	    }
-	}
-	else
-	{
-	    switch (op)
-	    {
-		case TOKlt:	n = n1 <  n2;	break;
-		case TOKle:	n = n1 <= n2;	break;
-		case TOKgt:	n = n1 >  n2;	break;
-		case TOKge:	n = n1 >= n2;	break;
-
-		case TOKleg:	n = 1;		break;
-		case TOKlg:	n = n1 != n2;	break;
-		case TOKunord:	n = 0;		break;
-		case TOKue:	n = n1 == n2;	break;
-		case TOKug:	n = n1 >  n2;	break;
-		case TOKuge:	n = n1 >= n2;	break;
-		case TOKul:	n = n1 <  n2;	break;
-		case TOKule:	n = n1 <= n2;	break;
-
-		default:
-		    assert(0);
-	    }
-	}
-    }
-    e = new IntegerExp(loc, n, type);
-    return e;
-}
-
-/* Also returns EXP_CANT_INTERPRET if cannot be computed.
- *  to:	type to cast to
- *  type: type to paint the result
- */
-
-Expression *Cast(Type *type, Type *to, Expression *e1)
-{   Expression *e = EXP_CANT_INTERPRET;
-    Loc loc = e1->loc;
-
-    //printf("Cast(type = %s, to = %s, e1 = %s)\n", type->toChars(), to->toChars(), e1->toChars());
-    //printf("\te1->type = %s\n", e1->type->toChars());
-    if (e1->type->equals(type) && type->equals(to))
-	return e1;
-    if (e1->type->implicitConvTo(to) >= MATCHconst ||
-	to->implicitConvTo(e1->type) >= MATCHconst)
-	return expType(to, e1);
-
-    Type *tb = to->toBasetype();
-    Type *typeb = type->toBasetype();
-
-    if (e1->op == TOKstring)
-    {
-	if (tb->ty == Tarray && typeb->ty == Tarray &&
-	    tb->nextOf()->size() == typeb->nextOf()->size())
-	{
-	    return expType(to, e1);
-	}
-    }
-
-    if (e1->isConst() != 1)
-	return EXP_CANT_INTERPRET;
-
-    if (tb->ty == Tbool)
-	e = new IntegerExp(loc, e1->toInteger() != 0, type);
-    else if (type->isintegral())
-    {
-	if (e1->type->isfloating())
-	{   integer_t result;
-	    real_t r = e1->toReal();
-
-	    switch (typeb->ty)
-	    {
-		case Tint8:	result = (d_int8)r;	break;
-		case Tchar:
-		case Tuns8:	result = (d_uns8)r;	break;
-		case Tint16:	result = (d_int16)r;	break;
-		case Twchar:
-		case Tuns16:	result = (d_uns16)r;	break;
-		case Tint32:	result = (d_int32)r;	break;
-		case Tdchar:
-		case Tuns32:	result = (d_uns32)r;	break;
-		case Tint64:	result = (d_int64)r;	break;
-		case Tuns64:	result = (d_uns64)r;	break;
-		default:
-		    assert(0);
-	    }
-
-	    e = new IntegerExp(loc, result, type);
-	}
-	else if (type->isunsigned())
-	    e = new IntegerExp(loc, e1->toUInteger(), type);
-	else
-	    e = new IntegerExp(loc, e1->toInteger(), type);
-    }
-    else if (tb->isreal())
-    {   real_t value = e1->toReal();
-
-	e = new RealExp(loc, value, type);
-    }
-    else if (tb->isimaginary())
-    {   real_t value = e1->toImaginary();
-
-	e = new RealExp(loc, value, type);
-    }
-    else if (tb->iscomplex())
-    {   complex_t value = e1->toComplex();
-
-	e = new ComplexExp(loc, value, type);
-    }
-    else if (tb->isscalar())
-	e = new IntegerExp(loc, e1->toInteger(), type);
-    else if (tb->ty == Tvoid)
-	e = EXP_CANT_INTERPRET;
-    else if (tb->ty == Tstruct && e1->op == TOKint64)
-    {	// Struct = 0;
-	StructDeclaration *sd = tb->toDsymbol(NULL)->isStructDeclaration();
-	assert(sd);
-	Expressions *elements = new Expressions;
-	for (size_t i = 0; i < sd->fields.dim; i++)
-	{   Dsymbol *s = (Dsymbol *)sd->fields.data[i];
-	    VarDeclaration *v = s->isVarDeclaration();
-	    assert(v);
-
-	    Expression *exp = new IntegerExp(0);
-	    exp = Cast(v->type, v->type, exp);
-	    if (exp == EXP_CANT_INTERPRET)
-		return exp;
-	    elements->push(exp);
-	}
-	e = new StructLiteralExp(loc, sd, elements);
-	e->type = type;
-    }
-    else
-    {
-	error(loc, "cannot cast %s to %s", e1->type->toChars(), type->toChars());
-	e = new IntegerExp(loc, 0, Type::tint32);
-    }
-    return e;
-}
-
-
-Expression *ArrayLength(Type *type, Expression *e1)
-{   Expression *e;
-    Loc loc = e1->loc;
-
-    if (e1->op == TOKstring)
-    {	StringExp *es1 = (StringExp *)e1;
-
-	e = new IntegerExp(loc, es1->len, type);
-    }
-    else if (e1->op == TOKarrayliteral)
-    {	ArrayLiteralExp *ale = (ArrayLiteralExp *)e1;
-	size_t dim;
-
-	dim = ale->elements ? ale->elements->dim : 0;
-	e = new IntegerExp(loc, dim, type);
-    }
-    else if (e1->op == TOKassocarrayliteral)
-    {	AssocArrayLiteralExp *ale = (AssocArrayLiteralExp *)e1;
-	size_t dim = ale->keys->dim;
-
-	e = new IntegerExp(loc, dim, type);
-    }
-    else
-	e = EXP_CANT_INTERPRET;
-    return e;
-}
-
-/* Also return EXP_CANT_INTERPRET if this fails
- */
-Expression *Index(Type *type, Expression *e1, Expression *e2)
-{   Expression *e = EXP_CANT_INTERPRET;
-    Loc loc = e1->loc;
-
-    //printf("Index(e1 = %s, e2 = %s)\n", e1->toChars(), e2->toChars());
-    assert(e1->type);
-    if (e1->op == TOKstring && e2->op == TOKint64)
-    {	StringExp *es1 = (StringExp *)e1;
-	uinteger_t i = e2->toInteger();
-
-	if (i >= es1->len)
-        e1->error("string index %llu is out of bounds [0 .. %"PRIuSIZE"]", i, es1->len);
-	else
-	{   unsigned value = es1->charAt(i);
-	    e = new IntegerExp(loc, value, type);
-	}
-    }
-    else if (e1->type->toBasetype()->ty == Tsarray && e2->op == TOKint64)
-    {	TypeSArray *tsa = (TypeSArray *)e1->type->toBasetype();
-	uinteger_t length = tsa->dim->toInteger();
-	uinteger_t i = e2->toInteger();
-
-	if (i >= length)
-	{
-        e2->error("array index %llu is out of bounds %s[0 .. %llu]", i, e1->toChars(), length);
-	}
-	else if (e1->op == TOKarrayliteral && !e1->checkSideEffect(2))
-	{   ArrayLiteralExp *ale = (ArrayLiteralExp *)e1;
-	    e = (Expression *)ale->elements->data[i];
-	    e->type = type;
-	}
-    }
-    else if (e1->type->toBasetype()->ty == Tarray && e2->op == TOKint64)
-    {
-	uinteger_t i = e2->toInteger();
-
-	if (e1->op == TOKarrayliteral && !e1->checkSideEffect(2))
-	{   ArrayLiteralExp *ale = (ArrayLiteralExp *)e1;
-	    if (i >= ale->elements->dim)
-	    {
-            e2->error("array index %llu is out of bounds %s[0 .. %u]", i, e1->toChars(), ale->elements->dim);
-	    }
-	    else
-	    {	e = (Expression *)ale->elements->data[i];
-		e->type = type;
-	    }
-	}
-    }
-    else if (e1->op == TOKassocarrayliteral && !e1->checkSideEffect(2))
-    {
-	AssocArrayLiteralExp *ae = (AssocArrayLiteralExp *)e1;
-	/* Search the keys backwards, in case there are duplicate keys
-	 */
-	for (size_t i = ae->keys->dim; i;)
-	{
-	    i--;
-	    Expression *ekey = (Expression *)ae->keys->data[i];
-	    Expression *ex = Equal(TOKequal, Type::tbool, ekey, e2);
-	    if (ex == EXP_CANT_INTERPRET)
-		return ex;
-	    if (ex->isBool(TRUE))
-	    {	e = (Expression *)ae->values->data[i];
-		e->type = type;
-		break;
-	    }
-	}
-    }
-    return e;
-}
-
-/* Also return EXP_CANT_INTERPRET if this fails
- */
-Expression *Slice(Type *type, Expression *e1, Expression *lwr, Expression *upr)
-{   Expression *e = EXP_CANT_INTERPRET;
-    Loc loc = e1->loc;
-
-#if LOG
-    printf("Slice()\n");
-    if (lwr)
-    {	printf("\te1 = %s\n", e1->toChars());
-	printf("\tlwr = %s\n", lwr->toChars());
-	printf("\tupr = %s\n", upr->toChars());
-    }
-#endif
-    if (e1->op == TOKstring && lwr->op == TOKint64 && upr->op == TOKint64)
-    {	StringExp *es1 = (StringExp *)e1;
-	uinteger_t ilwr = lwr->toInteger();
-	uinteger_t iupr = upr->toInteger();
-
-	if (iupr > es1->len || ilwr > iupr)
-        e1->error("string slice [%llu .. %llu] is out of bounds", ilwr, iupr);
-	else
-	{   integer_t value;
-	    void *s;
-	    size_t len = iupr - ilwr;
-	    int sz = es1->sz;
-	    StringExp *es;
-
-	    s = mem.malloc((len + 1) * sz);
-	    memcpy((unsigned char *)s, (unsigned char *)es1->string + ilwr * sz, len * sz);
-	    memset((unsigned char *)s + len * sz, 0, sz);
-
-	    es = new StringExp(loc, s, len, es1->postfix);
-	    es->sz = sz;
-	    es->committed = 1;
-	    es->type = type;
-	    e = es;
-	}
-    }
-    else if (e1->op == TOKarrayliteral &&
-	    lwr->op == TOKint64 && upr->op == TOKint64 &&
-	    !e1->checkSideEffect(2))
-    {	ArrayLiteralExp *es1 = (ArrayLiteralExp *)e1;
-	uinteger_t ilwr = lwr->toInteger();
-	uinteger_t iupr = upr->toInteger();
-
-	if (iupr > es1->elements->dim || ilwr > iupr)
-        e1->error("array slice [%llu .. %llu] is out of bounds", ilwr, iupr);
-	else
-	{
-	    Expressions *elements = new Expressions();
-	    elements->setDim(iupr - ilwr);
-	    memcpy(elements->data,
-		   es1->elements->data + ilwr,
-		   (iupr - ilwr) * sizeof(es1->elements->data[0]));
-	    e = new ArrayLiteralExp(e1->loc, elements);
-	    e->type = type;
-	}
-    }
-    return e;
-}
-
-/* Also return EXP_CANT_INTERPRET if this fails
- */
-Expression *Cat(Type *type, Expression *e1, Expression *e2)
-{   Expression *e = EXP_CANT_INTERPRET;
-    Loc loc = e1->loc;
-    Type *t;
-    Type *t1 = e1->type->toBasetype();
-    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;
-	goto L2;
-    }
-    else if ((e1->op == TOKint64 || e1->op == TOKstructliteral) && e2->op == TOKnull)
-    {	e = e1;
-     L2:
-	Type *tn = e->type->toBasetype();
-	if (tn->ty == Tchar || tn->ty == Twchar || tn->ty == Tdchar)
-	{
-	    // Create a StringExp
-	    void *s;
-	    StringExp *es;
-	    size_t len = 1;
-	    int sz = tn->size();
-	    integer_t v = e->toInteger();
-
-	    s = mem.malloc((len + 1) * sz);
-	    memcpy((unsigned char *)s, &v, sz);
-
-	    // Add terminating 0
-	    memset((unsigned char *)s + len * sz, 0, sz);
-
-	    es = new StringExp(loc, s, len);
-	    es->sz = sz;
-	    es->committed = 1;
-	    e = es;
-	}
-	else
-	{   // Create an ArrayLiteralExp
-	    Expressions *elements = new Expressions();
-	    elements->push(e);
-	    e = new ArrayLiteralExp(e->loc, elements);
-	}
-	e->type = type;
-	return e;
-    }
-    else if (e1->op == TOKstring && e2->op == TOKstring)
-    {
-	// Concatenate the strings
-	void *s;
-	StringExp *es1 = (StringExp *)e1;
-	StringExp *es2 = (StringExp *)e2;
-	StringExp *es;
-	Type *t;
-	size_t len = es1->len + es2->len;
-	int sz = es1->sz;
-
-	if (sz != es2->sz)
-	{
-	    /* Can happen with:
-	     *   auto s = "foo"d ~ "bar"c;
-	     */
-	    assert(global.errors);
-	    return e;
-	}
-	s = mem.malloc((len + 1) * sz);
-	memcpy(s, es1->string, es1->len * sz);
-	memcpy((unsigned char *)s + es1->len * sz, es2->string, es2->len * sz);
-
-	// Add terminating 0
-	memset((unsigned char *)s + len * sz, 0, sz);
-
-	es = new StringExp(loc, s, len);
-	es->sz = sz;
-	es->committed = es1->committed | es2->committed;
-	if (es1->committed)
-	    t = es1->type;
-	else
-	    t = es2->type;
-	es->type = type;
-	e = es;
-    }
-    else if (e1->op == TOKstring && e2->op == TOKint64)
-    {
-	// Concatenate the strings
-	void *s;
-	StringExp *es1 = (StringExp *)e1;
-	StringExp *es;
-	Type *t;
-	size_t len = es1->len + 1;
-	int sz = es1->sz;
-	integer_t v = e2->toInteger();
-
-	s = mem.malloc((len + 1) * sz);
-	memcpy(s, es1->string, es1->len * sz);
-	memcpy((unsigned char *)s + es1->len * sz, &v, sz);
-
-	// Add terminating 0
-	memset((unsigned char *)s + len * sz, 0, sz);
-
-	es = new StringExp(loc, s, len);
-	es->sz = sz;
-	es->committed = es1->committed;
-	t = es1->type;
-	es->type = type;
-	e = es;
-    }
-    else if (e1->op == TOKint64 && e2->op == TOKstring)
-    {
-	// Concatenate the strings
-	void *s;
-	StringExp *es2 = (StringExp *)e2;
-	StringExp *es;
-	Type *t;
-	size_t len = 1 + es2->len;
-	int sz = es2->sz;
-	integer_t v = e1->toInteger();
-
-	s = mem.malloc((len + 1) * sz);
-	memcpy((unsigned char *)s, &v, sz);
-	memcpy((unsigned char *)s + sz, es2->string, es2->len * sz);
-
-	// Add terminating 0
-	memset((unsigned char *)s + len * sz, 0, sz);
-
-	es = new StringExp(loc, s, len);
-	es->sz = sz;
-	es->committed = es2->committed;
-	t = es2->type;
-	es->type = type;
-	e = es;
-    }
-    else if (e1->op == TOKarrayliteral && e2->op == TOKarrayliteral &&
-	t1->nextOf()->equals(t2->nextOf()))
-    {
-	// Concatenate the arrays
-	ArrayLiteralExp *es1 = (ArrayLiteralExp *)e1;
-	ArrayLiteralExp *es2 = (ArrayLiteralExp *)e2;
-
-	es1 = new ArrayLiteralExp(es1->loc, (Expressions *)es1->elements->copy());
-	es1->elements->insert(es1->elements->dim, es2->elements);
-	e = es1;
-
-	if (type->toBasetype()->ty == Tsarray)
-	{
-	    e->type = new TypeSArray(t1->nextOf(), new IntegerExp(loc, es1->elements->dim, Type::tindex));
-	    e->type = e->type->semantic(loc, NULL);
-	}
-	else
-	    e->type = type;
-    }
-    else if (e1->op == TOKarrayliteral && e2->op == TOKnull &&
-	t1->nextOf()->equals(t2->nextOf()))
-    {
-	e = e1;
-	goto L3;
-    }
-    else if (e1->op == TOKnull && e2->op == TOKarrayliteral &&
-	t1->nextOf()->equals(t2->nextOf()))
-    {
-	e = e2;
-     L3:
-	// Concatenate the array with null
-	ArrayLiteralExp *es = (ArrayLiteralExp *)e;
-
-	es = new ArrayLiteralExp(es->loc, (Expressions *)es->elements->copy());
-	e = es;
-
-	if (type->toBasetype()->ty == Tsarray)
-	{
-	    e->type = new TypeSArray(t1->nextOf(), new IntegerExp(loc, es->elements->dim, Type::tindex));
-	    e->type = e->type->semantic(loc, NULL);
-	}
-	else
-	    e->type = type;
-    }
-    else if ((e1->op == TOKarrayliteral || e1->op == TOKnull) &&
-	e1->type->toBasetype()->nextOf()->equals(e2->type))
-    {
-	ArrayLiteralExp *es1;
-	if (e1->op == TOKarrayliteral)
-	{   es1 = (ArrayLiteralExp *)e1;
-	    es1 = new ArrayLiteralExp(es1->loc, (Expressions *)es1->elements->copy());
-	    es1->elements->push(e2);
-	}
-	else
-	{
-	    es1 = new ArrayLiteralExp(e1->loc, e2);
-	}
-	e = es1;
-
-	if (type->toBasetype()->ty == Tsarray)
-	{
-	    e->type = new TypeSArray(e2->type, new IntegerExp(loc, es1->elements->dim, Type::tindex));
-	    e->type = e->type->semantic(loc, NULL);
-	}
-	else
-	    e->type = type;
-    }
-    else if (e2->op == TOKarrayliteral &&
-	e2->type->toBasetype()->nextOf()->equals(e1->type))
-    {
-	ArrayLiteralExp *es2 = (ArrayLiteralExp *)e2;
-
-	es2 = new ArrayLiteralExp(es2->loc, (Expressions *)es2->elements->copy());
-	es2->elements->shift(e1);
-	e = es2;
-
-	if (type->toBasetype()->ty == Tsarray)
-	{
-	    e->type = new TypeSArray(e1->type, new IntegerExp(loc, es2->elements->dim, Type::tindex));
-	    e->type = e->type->semantic(loc, NULL);
-	}
-	else
-	    e->type = type;
-    }
-    else if (e1->op == TOKnull && e2->op == TOKstring)
-    {
-	t = e1->type;
-	e = e2;
-	goto L1;
-    }
-    else if (e1->op == TOKstring && e2->op == TOKnull)
-    {	e = e1;
-	t = e2->type;
-      L1:
-	Type *tb = t->toBasetype();
-	if (tb->ty == Tarray && tb->nextOf()->equals(e->type))
-	{   Expressions *expressions = new Expressions();
-	    expressions->push(e);
-	    e = new ArrayLiteralExp(loc, expressions);
-	    e->type = t;
-	}
-	if (!e->type->equals(type))
-	{   StringExp *se = (StringExp *)e->copy();
-	    e = se->castTo(NULL, type);
-	}
-    }
-    return e;
-}
-
-Expression *Ptr(Type *type, Expression *e1)
-{
-    //printf("Ptr(e1 = %s)\n", e1->toChars());
-    if (e1->op == TOKadd)
-    {	AddExp *ae = (AddExp *)e1;
-	if (ae->e1->op == TOKaddress && ae->e2->op == TOKint64)
-	{   AddrExp *ade = (AddrExp *)ae->e1;
-	    if (ade->e1->op == TOKstructliteral)
-	    {	StructLiteralExp *se = (StructLiteralExp *)ade->e1;
-		unsigned offset = ae->e2->toInteger();
-		Expression *e = se->getField(type, offset);
-		if (!e)
-		    e = EXP_CANT_INTERPRET;
-		return e;
-	    }
-	}
-    }
-    return EXP_CANT_INTERPRET;
-}
-
+
+// Compiler implementation of the D programming language
+// Copyright (c) 1999-2009 by Digital Mars
+// All Rights Reserved
+// written by Walter Bright
+// http://www.digitalmars.com
+// License for redistribution is by either the Artistic License
+// in artistic.txt, or the GNU General Public License in gnu.txt.
+// See the included readme.txt for details.
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <math.h>
+
+#if __DMC__
+#include <complex.h>
+#endif
+
+#include "rmem.h"
+#include "root.h"
+#include "port.h"
+
+#include "mtype.h"
+#include "expression.h"
+#include "aggregate.h"
+#include "declaration.h"
+
+#if __FreeBSD__
+#define fmodl fmod	// hack for now, fix later
+#endif
+
+#define LOG 0
+
+Expression *expType(Type *type, Expression *e)
+{
+    if (type != e->type)
+    {
+	e = e->copy();
+	e->type = type;
+    }
+    return e;
+}
+
+/* ================================== isConst() ============================== */
+
+int Expression::isConst()
+{
+    //printf("Expression::isConst(): %s\n", toChars());
+    return 0;
+}
+
+int IntegerExp::isConst()
+{
+    return 1;
+}
+
+int RealExp::isConst()
+{
+    return 1;
+}
+
+int ComplexExp::isConst()
+{
+    return 1;
+}
+
+int SymOffExp::isConst()
+{
+    return 2;
+}
+
+/* =============================== constFold() ============================== */
+
+/* The constFold() functions were redundant with the optimize() ones,
+ * and so have been folded in with them.
+ */
+
+/* ========================================================================== */
+
+Expression *Neg(Type *type, Expression *e1)
+{   Expression *e;
+    Loc loc = e1->loc;
+
+    if (e1->type->isreal())
+    {
+	e = new RealExp(loc, -e1->toReal(), type);
+    }
+    else if (e1->type->isimaginary())
+    {
+	e = new RealExp(loc, -e1->toImaginary(), type);
+    }
+    else if (e1->type->iscomplex())
+    {
+	e = new ComplexExp(loc, -e1->toComplex(), type);
+    }
+    else
+	e = new IntegerExp(loc, -e1->toInteger(), type);
+    return e;
+}
+
+Expression *Com(Type *type, Expression *e1)
+{   Expression *e;
+    Loc loc = e1->loc;
+
+    e = new IntegerExp(loc, ~e1->toInteger(), type);
+    return e;
+}
+
+Expression *Not(Type *type, Expression *e1)
+{   Expression *e;
+    Loc loc = e1->loc;
+
+    e = new IntegerExp(loc, e1->isBool(0), type);
+    return e;
+}
+
+Expression *Bool(Type *type, Expression *e1)
+{   Expression *e;
+    Loc loc = e1->loc;
+
+    e = new IntegerExp(loc, e1->isBool(1), type);
+    return e;
+}
+
+Expression *Add(Type *type, Expression *e1, Expression *e2)
+{   Expression *e;
+    Loc loc = e1->loc;
+
+#if LOG
+    printf("Add(e1 = %s, e2 = %s)\n", e1->toChars(), e2->toChars());
+#endif
+    if (type->isreal())
+    {
+	e = new RealExp(loc, e1->toReal() + e2->toReal(), type);
+    }
+    else if (type->isimaginary())
+    {
+	e = new RealExp(loc, e1->toImaginary() + e2->toImaginary(), type);
+    }
+    else if (type->iscomplex())
+    {
+	// This rigamarole is necessary so that -0.0 doesn't get
+	// converted to +0.0 by doing an extraneous add with +0.0
+	complex_t c1;
+	real_t r1;
+	real_t i1;
+
+	complex_t c2;
+	real_t r2;
+	real_t i2;
+
+	complex_t v;
+	int x;
+
+	if (e1->type->isreal())
+	{   r1 = e1->toReal();
+	    x = 0;
+	}
+	else if (e1->type->isimaginary())
+	{   i1 = e1->toImaginary();
+	    x = 3;
+	}
+	else
+	{   c1 = e1->toComplex();
+	    x = 6;
+	}
+
+	if (e2->type->isreal())
+	{   r2 = e2->toReal();
+	}
+	else if (e2->type->isimaginary())
+	{   i2 = e2->toImaginary();
+	    x += 1;
+	}
+	else
+	{   c2 = e2->toComplex();
+	    x += 2;
+	}
+
+	switch (x)
+	{
+#if __DMC__
+	    case 0+0:	v = (complex_t) (r1 + r2);	break;
+	    case 0+1:	v = r1 + i2 * I;		break;
+	    case 0+2:	v = r1 + c2;			break;
+	    case 3+0:	v = i1 * I + r2;		break;
+	    case 3+1:	v = (complex_t) ((i1 + i2) * I); break;
+	    case 3+2:	v = i1 * I + c2;		break;
+	    case 6+0:	v = c1 + r2;			break;
+	    case 6+1:	v = c1 + i2 * I;		break;
+	    case 6+2:	v = c1 + c2;			break;
+#else
+	    case 0+0:	v = complex_t(r1 + r2, 0);	break;
+	    case 0+1:	v = complex_t(r1, i2);		break;
+	    case 0+2:	v = complex_t(r1 + creall(c2), cimagl(c2));	break;
+	    case 3+0:	v = complex_t(r2, i1);		break;
+	    case 3+1:	v = complex_t(0, i1 + i2);	break;
+	    case 3+2:	v = complex_t(creall(c2), i1 + cimagl(c2));	break;
+	    case 6+0:	v = complex_t(creall(c1) + r2, cimagl(c2));	break;
+	    case 6+1:	v = complex_t(creall(c1), cimagl(c1) + i2);	break;
+	    case 6+2:	v = c1 + c2;			break;
+#endif
+	    default: assert(0);
+	}
+	e = new ComplexExp(loc, v, type);
+    }
+    else if (e1->op == TOKsymoff)
+    {
+	SymOffExp *soe = (SymOffExp *)e1;
+	e = new SymOffExp(loc, soe->var, soe->offset + e2->toInteger());
+	e->type = type;
+    }
+    else if (e2->op == TOKsymoff)
+    {
+	SymOffExp *soe = (SymOffExp *)e2;
+	e = new SymOffExp(loc, soe->var, soe->offset + e1->toInteger());
+	e->type = type;
+    }
+    else
+	e = new IntegerExp(loc, e1->toInteger() + e2->toInteger(), type);
+    return e;
+}
+
+
+Expression *Min(Type *type, Expression *e1, Expression *e2)
+{   Expression *e;
+    Loc loc = e1->loc;
+
+    if (type->isreal())
+    {
+	e = new RealExp(loc, e1->toReal() - e2->toReal(), type);
+    }
+    else if (type->isimaginary())
+    {
+	e = new RealExp(loc, e1->toImaginary() - e2->toImaginary(), type);
+    }
+    else if (type->iscomplex())
+    {
+	// This rigamarole is necessary so that -0.0 doesn't get
+	// converted to +0.0 by doing an extraneous add with +0.0
+	complex_t c1;
+	real_t r1;
+	real_t i1;
+
+	complex_t c2;
+	real_t r2;
+	real_t i2;
+
+	complex_t v;
+	int x;
+
+	if (e1->type->isreal())
+	{   r1 = e1->toReal();
+	    x = 0;
+	}
+	else if (e1->type->isimaginary())
+	{   i1 = e1->toImaginary();
+	    x = 3;
+	}
+	else
+	{   c1 = e1->toComplex();
+	    x = 6;
+	}
+
+	if (e2->type->isreal())
+	{   r2 = e2->toReal();
+	}
+	else if (e2->type->isimaginary())
+	{   i2 = e2->toImaginary();
+	    x += 1;
+	}
+	else
+	{   c2 = e2->toComplex();
+	    x += 2;
+	}
+
+	switch (x)
+	{
+#if __DMC__
+	    case 0+0:	v = (complex_t) (r1 - r2);	break;
+	    case 0+1:	v = r1 - i2 * I;		break;
+	    case 0+2:	v = r1 - c2;			break;
+	    case 3+0:	v = i1 * I - r2;		break;
+	    case 3+1:	v = (complex_t) ((i1 - i2) * I); break;
+	    case 3+2:	v = i1 * I - c2;		break;
+	    case 6+0:	v = c1 - r2;			break;
+	    case 6+1:	v = c1 - i2 * I;		break;
+	    case 6+2:	v = c1 - c2;			break;
+#else
+	    case 0+0:	v = complex_t(r1 - r2, 0);	break;
+	    case 0+1:	v = complex_t(r1, -i2);		break;
+	    case 0+2:	v = complex_t(r1 - creall(c2), -cimagl(c2));	break;
+	    case 3+0:	v = complex_t(-r2, i1);		break;
+	    case 3+1:	v = complex_t(0, i1 - i2);	break;
+	    case 3+2:	v = complex_t(-creall(c2), i1 - cimagl(c2));	break;
+	    case 6+0:	v = complex_t(creall(c1) - r2, cimagl(c1));	break;
+	    case 6+1:	v = complex_t(creall(c1), cimagl(c1) - i2);	break;
+	    case 6+2:	v = c1 - c2;			break;
+#endif
+	    default: assert(0);
+	}
+	e = new ComplexExp(loc, v, type);
+    }
+    else if (e1->op == TOKsymoff)
+    {
+	SymOffExp *soe = (SymOffExp *)e1;
+	e = new SymOffExp(loc, soe->var, soe->offset - e2->toInteger());
+	e->type = type;
+    }
+    else
+    {
+	e = new IntegerExp(loc, e1->toInteger() - e2->toInteger(), type);
+    }
+    return e;
+}
+
+Expression *Mul(Type *type, Expression *e1, Expression *e2)
+{   Expression *e;
+    Loc loc = e1->loc;
+
+    if (type->isfloating())
+    {   complex_t c;
+#ifdef IN_GCC
+	real_t r;
+#else
+	d_float80 r;
+#endif
+
+	if (e1->type->isreal())
+	{
+#if __DMC__
+	    c = e1->toReal() * e2->toComplex();
+#else
+	    r = e1->toReal();
+	    c = e2->toComplex();
+	    c = complex_t(r * creall(c), r * cimagl(c));
+#endif
+	}
+	else if (e1->type->isimaginary())
+	{
+#if __DMC__
+	    c = e1->toImaginary() * I * e2->toComplex();
+#else
+	    r = e1->toImaginary();
+	    c = e2->toComplex();
+	    c = complex_t(-r * cimagl(c), r * creall(c));
+#endif
+	}
+	else if (e2->type->isreal())
+	{
+#if __DMC__
+	    c = e2->toReal() * e1->toComplex();
+#else
+	    r = e2->toReal();
+	    c = e1->toComplex();
+	    c = complex_t(r * creall(c), r * cimagl(c));
+#endif
+	}
+	else if (e2->type->isimaginary())
+	{
+#if __DMC__
+	    c = e1->toComplex() * e2->toImaginary() * I;
+#else
+	    r = e2->toImaginary();
+	    c = e1->toComplex();
+	    c = complex_t(-r * cimagl(c), r * creall(c));
+#endif
+	}
+	else
+	    c = e1->toComplex() * e2->toComplex();
+
+	if (type->isreal())
+	    e = new RealExp(loc, creall(c), type);
+	else if (type->isimaginary())
+	    e = new RealExp(loc, cimagl(c), type);
+	else if (type->iscomplex())
+	    e = new ComplexExp(loc, c, type);
+	else
+	    assert(0);
+    }
+    else
+    {
+	e = new IntegerExp(loc, e1->toInteger() * e2->toInteger(), type);
+    }
+    return e;
+}
+
+Expression *Div(Type *type, Expression *e1, Expression *e2)
+{   Expression *e;
+    Loc loc = e1->loc;
+
+    if (type->isfloating())
+    {   complex_t c;
+#ifdef IN_GCC
+	real_t r;
+#else
+	d_float80 r;
+#endif
+
+	//e1->type->print();
+	//e2->type->print();
+	if (e2->type->isreal())
+	{
+	    if (e1->type->isreal())
+	    {
+		e = new RealExp(loc, e1->toReal() / e2->toReal(), type);
+		return e;
+	    }
+#if __DMC__
+	    //r = e2->toReal();
+	    //c = e1->toComplex();
+	    //printf("(%Lg + %Lgi) / %Lg\n", creall(c), cimagl(c), r);
+
+	    c = e1->toComplex() / e2->toReal();
+#else
+	    r = e2->toReal();
+	    c = e1->toComplex();
+	    c = complex_t(creall(c) / r, cimagl(c) / r);
+#endif
+	}
+	else if (e2->type->isimaginary())
+	{
+#if __DMC__
+	    //r = e2->toImaginary();
+	    //c = e1->toComplex();
+	    //printf("(%Lg + %Lgi) / %Lgi\n", creall(c), cimagl(c), r);
+
+	    c = e1->toComplex() / (e2->toImaginary() * I);
+#else
+	    r = e2->toImaginary();
+	    c = e1->toComplex();
+	    c = complex_t(cimagl(c) / r, -creall(c) / r);
+#endif
+	}
+	else
+	{
+	    c = e1->toComplex() / e2->toComplex();
+	}
+
+	if (type->isreal())
+	    e = new RealExp(loc, creall(c), type);
+	else if (type->isimaginary())
+	    e = new RealExp(loc, cimagl(c), type);
+	else if (type->iscomplex())
+	    e = new ComplexExp(loc, c, type);
+	else
+	    assert(0);
+    }
+    else
+    {   sinteger_t n1;
+	sinteger_t n2;
+	sinteger_t n;
+
+	n1 = e1->toInteger();
+	n2 = e2->toInteger();
+	if (n2 == 0)
+	{   e2->error("divide by 0");
+	    e2 = new IntegerExp(loc, 1, e2->type);
+	    n2 = 1;
+	}
+	if (e1->type->isunsigned() || e2->type->isunsigned())
+	    n = ((d_uns64) n1) / ((d_uns64) n2);
+	else
+	    n = n1 / n2;
+	e = new IntegerExp(loc, n, type);
+    }
+    return e;
+}
+
+Expression *Mod(Type *type, Expression *e1, Expression *e2)
+{   Expression *e;
+    Loc loc = e1->loc;
+
+    if (type->isfloating())
+    {
+	complex_t c;
+
+	if (e2->type->isreal())
+	{   real_t r2 = e2->toReal();
+
+#ifdef __DMC__
+	    c = fmodl(e1->toReal(), r2) + fmodl(e1->toImaginary(), r2) * I;
+#elif defined(IN_GCC)
+	    c = complex_t(e1->toReal() % r2, e1->toImaginary() % r2);
+#elif (defined(__FreeBSD__) && __FreeBSD_version < 800000) || defined(__arm__) || defined(__thumb__)
+	// freebsd is kinda messed up. the STABLE branch doesn't support C99's fmodl !?!
+	// arm also doesn't like fmodl
+	    c = complex_t(fmod(e1->toReal(), r2), fmod(e1->toImaginary(), r2));
+#else
+	    c = complex_t(fmodl(e1->toReal(), r2), fmodl(e1->toImaginary(), r2));
+#endif
+	}
+	else if (e2->type->isimaginary())
+	{   real_t i2 = e2->toImaginary();
+
+#ifdef __DMC__
+	    c = fmodl(e1->toReal(), i2) + fmodl(e1->toImaginary(), i2) * I;
+#elif defined(IN_GCC)
+	    c = complex_t(e1->toReal() % i2, e1->toImaginary() % i2);
+#elif (defined(__FreeBSD__) && __FreeBSD_version < 800000) || defined(__arm__) || defined(__thumb__)
+        // freebsd is kinda messed up. the STABLE branch doesn't support C99's fmodl !?!
+	// arm also doesn't like fmodl
+	    c = complex_t(fmod(e1->toReal(), i2), fmod(e1->toImaginary(), i2));
+#else
+	    c = complex_t(fmodl(e1->toReal(), i2), fmodl(e1->toImaginary(), i2));
+#endif
+	}
+	else
+	    assert(0);
+
+	if (type->isreal())
+	    e = new RealExp(loc, creall(c), type);
+	else if (type->isimaginary())
+	    e = new RealExp(loc, cimagl(c), type);
+	else if (type->iscomplex())
+	    e = new ComplexExp(loc, c, type);
+	else
+	    assert(0);
+    }
+    else
+    {   sinteger_t n1;
+	sinteger_t n2;
+	sinteger_t n;
+
+	n1 = e1->toInteger();
+	n2 = e2->toInteger();
+	if (n2 == 0)
+	{   e2->error("divide by 0");
+	    e2 = new IntegerExp(loc, 1, e2->type);
+	    n2 = 1;
+	}
+	if (e1->type->isunsigned() || e2->type->isunsigned())
+	    n = ((d_uns64) n1) % ((d_uns64) n2);
+	else
+	    n = n1 % n2;
+	e = new IntegerExp(loc, n, type);
+    }
+    return e;
+}
+
+Expression *Shl(Type *type, Expression *e1, Expression *e2)
+{   Expression *e;
+    Loc loc = e1->loc;
+
+    e = new IntegerExp(loc, e1->toInteger() << e2->toInteger(), type);
+    return e;
+}
+
+Expression *Shr(Type *type, Expression *e1, Expression *e2)
+{   Expression *e;
+    Loc loc = e1->loc;
+    unsigned count;
+    dinteger_t value;
+
+    value = e1->toInteger();
+    count = e2->toInteger();
+    switch (e1->type->toBasetype()->ty)
+    {
+	case Tint8:
+		value = (d_int8)(value) >> count;
+		break;
+
+	case Tuns8:
+		value = (d_uns8)(value) >> count;
+		break;
+
+	case Tint16:
+		value = (d_int16)(value) >> count;
+		break;
+
+	case Tuns16:
+		value = (d_uns16)(value) >> count;
+		break;
+
+	case Tint32:
+		value = (d_int32)(value) >> count;
+		break;
+
+	case Tuns32:
+		value = (d_uns32)(value) >> count;
+		break;
+
+	case Tint64:
+		value = (d_int64)(value) >> count;
+		break;
+
+	case Tuns64:
+		value = (d_uns64)(value) >> count;
+		break;
+
+	default:
+		assert(0);
+    }
+    e = new IntegerExp(loc, value, type);
+    return e;
+}
+
+Expression *Ushr(Type *type, Expression *e1, Expression *e2)
+{   Expression *e;
+    Loc loc = e1->loc;
+    unsigned count;
+    dinteger_t value;
+
+    value = e1->toInteger();
+    count = e2->toInteger();
+    switch (e1->type->toBasetype()->ty)
+    {
+	case Tint8:
+	case Tuns8:
+		assert(0);		// no way to trigger this
+		value = (value & 0xFF) >> count;
+		break;
+
+	case Tint16:
+	case Tuns16:
+		assert(0);		// no way to trigger this
+		value = (value & 0xFFFF) >> count;
+		break;
+
+	case Tint32:
+	case Tuns32:
+		value = (value & 0xFFFFFFFF) >> count;
+		break;
+
+	case Tint64:
+	case Tuns64:
+		value = (d_uns64)(value) >> count;
+		break;
+
+	default:
+		assert(0);
+    }
+    e = new IntegerExp(loc, value, type);
+    return e;
+}
+
+Expression *And(Type *type, Expression *e1, Expression *e2)
+{
+    Expression *e;
+    e = new IntegerExp(e1->loc, e1->toInteger() & e2->toInteger(), type);
+    return e;
+}
+
+Expression *Or(Type *type, Expression *e1, Expression *e2)
+{   Expression *e;
+    e = new IntegerExp(e1->loc, e1->toInteger() | e2->toInteger(), type);
+    return e;
+}
+
+Expression *Xor(Type *type, Expression *e1, Expression *e2)
+{   Expression *e;
+    e = new IntegerExp(e1->loc, e1->toInteger() ^ e2->toInteger(), type);
+    return e;
+}
+
+/* Also returns EXP_CANT_INTERPRET if cannot be computed.
+ */
+Expression *Equal(enum TOK op, Type *type, Expression *e1, Expression *e2)
+{   Expression *e;
+    Loc loc = e1->loc;
+    int cmp;
+    real_t r1;
+    real_t r2;
+
+    //printf("Equal(e1 = %s, e2 = %s)\n", e1->toChars(), e2->toChars());
+
+    assert(op == TOKequal || op == TOKnotequal);
+
+    if (e1->op == TOKnull)
+    {
+	if (e2->op == TOKnull)
+	    cmp = 1;
+	else if (e2->op == TOKstring)
+	{   StringExp *es2 = (StringExp *)e2;
+	    cmp = (0 == es2->len);
+	}
+	else if (e2->op == TOKarrayliteral)
+	{   ArrayLiteralExp *es2 = (ArrayLiteralExp *)e2;
+	    cmp = !es2->elements || (0 == es2->elements->dim);
+	}
+	else
+	    return EXP_CANT_INTERPRET;
+    }
+    else if (e2->op == TOKnull)
+    {
+	if (e1->op == TOKstring)
+	{   StringExp *es1 = (StringExp *)e1;
+	    cmp = (0 == es1->len);
+	}
+	else if (e1->op == TOKarrayliteral)
+	{   ArrayLiteralExp *es1 = (ArrayLiteralExp *)e1;
+	    cmp = !es1->elements || (0 == es1->elements->dim);
+	}
+	else
+	    return EXP_CANT_INTERPRET;
+    }
+    else if (e1->op == TOKstring && e2->op == TOKstring)
+    {	StringExp *es1 = (StringExp *)e1;
+	StringExp *es2 = (StringExp *)e2;
+
+	if (es1->sz != es2->sz)
+	{
+	    assert(global.errors);
+	    return EXP_CANT_INTERPRET;
+	}
+	if (es1->len == es2->len &&
+	    memcmp(es1->string, es2->string, es1->sz * es1->len) == 0)
+	    cmp = 1;
+	else
+	    cmp = 0;
+    }
+    else if (e1->op == TOKarrayliteral && e2->op == TOKarrayliteral)
+    {   ArrayLiteralExp *es1 = (ArrayLiteralExp *)e1;
+	ArrayLiteralExp *es2 = (ArrayLiteralExp *)e2;
+
+	if ((!es1->elements || !es1->elements->dim) &&
+	    (!es2->elements || !es2->elements->dim))
+	    cmp = 1;		// both arrays are empty
+	else if (!es1->elements || !es2->elements)
+	    cmp = 0;
+	else if (es1->elements->dim != es2->elements->dim)
+	    cmp = 0;
+	else
+	{
+	    for (size_t i = 0; i < es1->elements->dim; i++)
+	    {   Expression *ee1 = (Expression *)es1->elements->data[i];
+		Expression *ee2 = (Expression *)es2->elements->data[i];
+
+		Expression *v = Equal(TOKequal, Type::tint32, ee1, ee2);
+		if (v == EXP_CANT_INTERPRET)
+		    return EXP_CANT_INTERPRET;
+		cmp = v->toInteger();
+		if (cmp == 0)
+		    break;
+	    }
+	}
+    }
+    else if (e1->op == TOKarrayliteral && e2->op == TOKstring)
+    {	// Swap operands and use common code
+	Expression *e = e1;
+	e1 = e2;
+	e2 = e;
+	goto Lsa;
+    }
+    else if (e1->op == TOKstring && e2->op == TOKarrayliteral)
+    {
+     Lsa:
+	StringExp *es1 = (StringExp *)e1;
+	ArrayLiteralExp *es2 = (ArrayLiteralExp *)e2;
+	size_t dim1 = es1->len;
+	size_t dim2 = es2->elements ? es2->elements->dim : 0;
+	if (dim1 != dim2)
+	    cmp = 0;
+	else
+	{
+	    for (size_t i = 0; i < dim1; i++)
+	    {
+		uinteger_t c = es1->charAt(i);
+		Expression *ee2 = (Expression *)es2->elements->data[i];
+		if (ee2->isConst() != 1)
+		    return EXP_CANT_INTERPRET;
+		cmp = (c == ee2->toInteger());
+		if (cmp == 0)
+		    break;
+	    }
+	}
+    }
+    else if (e1->op == TOKstructliteral && e2->op == TOKstructliteral)
+    {   StructLiteralExp *es1 = (StructLiteralExp *)e1;
+	StructLiteralExp *es2 = (StructLiteralExp *)e2;
+
+	if (es1->sd != es2->sd)
+	    cmp = 0;
+	else if ((!es1->elements || !es1->elements->dim) &&
+	    (!es2->elements || !es2->elements->dim))
+	    cmp = 1;		// both arrays are empty
+	else if (!es1->elements || !es2->elements)
+	    cmp = 0;
+	else if (es1->elements->dim != es2->elements->dim)
+	    cmp = 0;
+	else
+	{
+	    cmp = 1;
+	    for (size_t i = 0; i < es1->elements->dim; i++)
+	    {   Expression *ee1 = (Expression *)es1->elements->data[i];
+		Expression *ee2 = (Expression *)es2->elements->data[i];
+
+		if (ee1 == ee2)
+		    continue;
+		if (!ee1 || !ee2)
+		{   cmp = 0;
+		    break;
+		}
+		Expression *v = Equal(TOKequal, Type::tint32, ee1, ee2);
+		if (v == EXP_CANT_INTERPRET)
+		    return EXP_CANT_INTERPRET;
+		cmp = v->toInteger();
+		if (cmp == 0)
+		    break;
+	    }
+	}
+    }
+#if 0 // Should handle this
+    else if (e1->op == TOKarrayliteral && e2->op == TOKstring)
+    {
+    }
+#endif
+    else if (e1->isConst() != 1 || e2->isConst() != 1)
+	return EXP_CANT_INTERPRET;
+    else if (e1->type->isreal())
+    {
+	r1 = e1->toReal();
+	r2 = e2->toReal();
+	goto L1;
+    }
+    else if (e1->type->isimaginary())
+    {
+	r1 = e1->toImaginary();
+	r2 = e2->toImaginary();
+     L1:
+#if __DMC__
+	cmp = (r1 == r2);
+#else
+	if (Port::isNan(r1) || Port::isNan(r2))	// if unordered
+	{
+	    cmp = 0;
+	}
+	else
+	{
+	    cmp = (r1 == r2);
+	}
+#endif
+    }
+    else if (e1->type->iscomplex())
+    {
+	cmp = e1->toComplex() == e2->toComplex();
+    }
+    else if (e1->type->isintegral())
+    {
+	cmp = (e1->toInteger() == e2->toInteger());
+    }
+    else
+	return EXP_CANT_INTERPRET;
+    if (op == TOKnotequal)
+	cmp ^= 1;
+    e = new IntegerExp(loc, cmp, type);
+    return e;
+}
+
+Expression *Identity(enum TOK op, Type *type, Expression *e1, Expression *e2)
+{   Expression *e;
+    Loc loc = e1->loc;
+    int cmp;
+
+    if (e1->op == TOKnull && e2->op == TOKnull)
+    {
+	cmp = 1;
+    }
+    else if (e1->op == TOKsymoff && e2->op == TOKsymoff)
+    {
+	SymOffExp *es1 = (SymOffExp *)e1;
+	SymOffExp *es2 = (SymOffExp *)e2;
+
+	cmp = (es1->var == es2->var && es1->offset == es2->offset);
+    }
+    else if (e1->isConst() == 1 && e2->isConst() == 1)
+	return Equal((op == TOKidentity) ? TOKequal : TOKnotequal,
+		type, e1, e2);
+    else
+	assert(0);
+    if (op == TOKnotidentity)
+	cmp ^= 1;
+    return new IntegerExp(loc, cmp, type);
+}
+
+
+Expression *Cmp(enum TOK op, Type *type, Expression *e1, Expression *e2)
+{   Expression *e;
+    Loc loc = e1->loc;
+    dinteger_t n;
+    real_t r1;
+    real_t r2;
+
+    //printf("Cmp(e1 = %s, e2 = %s)\n", e1->toChars(), e2->toChars());
+
+    if (e1->op == TOKstring && e2->op == TOKstring)
+    {	StringExp *es1 = (StringExp *)e1;
+	StringExp *es2 = (StringExp *)e2;
+	size_t sz = es1->sz;
+	assert(sz == es2->sz);
+
+	size_t len = es1->len;
+	if (es2->len < len)
+	    len = es2->len;
+
+	int cmp = memcmp(es1->string, es2->string, sz * len);
+	if (cmp == 0)
+	    cmp = es1->len - es2->len;
+
+	switch (op)
+	{
+	    case TOKlt:	n = cmp <  0;	break;
+	    case TOKle:	n = cmp <= 0;	break;
+	    case TOKgt:	n = cmp >  0;	break;
+	    case TOKge:	n = cmp >= 0;	break;
+
+	    case TOKleg:   n = 1;		break;
+	    case TOKlg:	   n = cmp != 0;	break;
+	    case TOKunord: n = 0;		break;
+	    case TOKue:	   n = cmp == 0;	break;
+	    case TOKug:	   n = cmp >  0;	break;
+	    case TOKuge:   n = cmp >= 0;	break;
+	    case TOKul:	   n = cmp <  0;	break;
+	    case TOKule:   n = cmp <= 0;	break;
+
+	    default:
+		assert(0);
+	}
+    }
+    else if (e1->isConst() != 1 || e2->isConst() != 1)
+	return EXP_CANT_INTERPRET;
+    else if (e1->type->isreal())
+    {
+	r1 = e1->toReal();
+	r2 = e2->toReal();
+	goto L1;
+    }
+    else if (e1->type->isimaginary())
+    {
+	r1 = e1->toImaginary();
+	r2 = e2->toImaginary();
+     L1:
+#if __DMC__
+	// DMC is the only compiler I know of that handles NAN arguments
+	// correctly in comparisons.
+	switch (op)
+	{
+	    case TOKlt:	   n = r1 <  r2;	break;
+	    case TOKle:	   n = r1 <= r2;	break;
+	    case TOKgt:	   n = r1 >  r2;	break;
+	    case TOKge:	   n = r1 >= r2;	break;
+
+	    case TOKleg:   n = r1 <>=  r2;	break;
+	    case TOKlg:	   n = r1 <>   r2;	break;
+	    case TOKunord: n = r1 !<>= r2;	break;
+	    case TOKue:	   n = r1 !<>  r2;	break;
+	    case TOKug:	   n = r1 !<=  r2;	break;
+	    case TOKuge:   n = r1 !<   r2;	break;
+	    case TOKul:	   n = r1 !>=  r2;	break;
+	    case TOKule:   n = r1 !>   r2;	break;
+
+	    default:
+		assert(0);
+	}
+#else
+	// Don't rely on compiler, handle NAN arguments separately
+	if (Port::isNan(r1) || Port::isNan(r2))	// if unordered
+	{
+	    switch (op)
+	    {
+		case TOKlt:	n = 0;	break;
+		case TOKle:	n = 0;	break;
+		case TOKgt:	n = 0;	break;
+		case TOKge:	n = 0;	break;
+
+		case TOKleg:	n = 0;	break;
+		case TOKlg:	n = 0;	break;
+		case TOKunord:	n = 1;	break;
+		case TOKue:	n = 1;	break;
+		case TOKug:	n = 1;	break;
+		case TOKuge:	n = 1;	break;
+		case TOKul:	n = 1;	break;
+		case TOKule:	n = 1;	break;
+
+		default:
+		    assert(0);
+	    }
+	}
+	else
+	{
+	    switch (op)
+	    {
+		case TOKlt:	n = r1 <  r2;	break;
+		case TOKle:	n = r1 <= r2;	break;
+		case TOKgt:	n = r1 >  r2;	break;
+		case TOKge:	n = r1 >= r2;	break;
+
+		case TOKleg:	n = 1;		break;
+		case TOKlg:	n = r1 != r2;	break;
+		case TOKunord:	n = 0;		break;
+		case TOKue:	n = r1 == r2;	break;
+		case TOKug:	n = r1 >  r2;	break;
+		case TOKuge:	n = r1 >= r2;	break;
+		case TOKul:	n = r1 <  r2;	break;
+		case TOKule:	n = r1 <= r2;	break;
+
+		default:
+		    assert(0);
+	    }
+	}
+#endif
+    }
+    else if (e1->type->iscomplex())
+    {
+	assert(0);
+    }
+    else
+    {   sinteger_t n1;
+	sinteger_t n2;
+
+	n1 = e1->toInteger();
+	n2 = e2->toInteger();
+	if (e1->type->isunsigned() || e2->type->isunsigned())
+	{
+	    switch (op)
+	    {
+		case TOKlt:	n = ((d_uns64) n1) <  ((d_uns64) n2);	break;
+		case TOKle:	n = ((d_uns64) n1) <= ((d_uns64) n2);	break;
+		case TOKgt:	n = ((d_uns64) n1) >  ((d_uns64) n2);	break;
+		case TOKge:	n = ((d_uns64) n1) >= ((d_uns64) n2);	break;
+
+		case TOKleg:	n = 1;					break;
+		case TOKlg:	n = ((d_uns64) n1) != ((d_uns64) n2);	break;
+		case TOKunord:	n = 0;					break;
+		case TOKue:	n = ((d_uns64) n1) == ((d_uns64) n2);	break;
+		case TOKug:	n = ((d_uns64) n1) >  ((d_uns64) n2);	break;
+		case TOKuge:	n = ((d_uns64) n1) >= ((d_uns64) n2);	break;
+		case TOKul:	n = ((d_uns64) n1) <  ((d_uns64) n2);	break;
+		case TOKule:	n = ((d_uns64) n1) <= ((d_uns64) n2);	break;
+
+		default:
+		    assert(0);
+	    }
+	}
+	else
+	{
+	    switch (op)
+	    {
+		case TOKlt:	n = n1 <  n2;	break;
+		case TOKle:	n = n1 <= n2;	break;
+		case TOKgt:	n = n1 >  n2;	break;
+		case TOKge:	n = n1 >= n2;	break;
+
+		case TOKleg:	n = 1;		break;
+		case TOKlg:	n = n1 != n2;	break;
+		case TOKunord:	n = 0;		break;
+		case TOKue:	n = n1 == n2;	break;
+		case TOKug:	n = n1 >  n2;	break;
+		case TOKuge:	n = n1 >= n2;	break;
+		case TOKul:	n = n1 <  n2;	break;
+		case TOKule:	n = n1 <= n2;	break;
+
+		default:
+		    assert(0);
+	    }
+	}
+    }
+    e = new IntegerExp(loc, n, type);
+    return e;
+}
+
+/* Also returns EXP_CANT_INTERPRET if cannot be computed.
+ *  to:	type to cast to
+ *  type: type to paint the result
+ */
+
+Expression *Cast(Type *type, Type *to, Expression *e1)
+{   Expression *e = EXP_CANT_INTERPRET;
+    Loc loc = e1->loc;
+
+    //printf("Cast(type = %s, to = %s, e1 = %s)\n", type->toChars(), to->toChars(), e1->toChars());
+    //printf("\te1->type = %s\n", e1->type->toChars());
+    if (e1->type->equals(type) && type->equals(to))
+	return e1;
+    if (e1->type->implicitConvTo(to) >= MATCHconst ||
+	to->implicitConvTo(e1->type) >= MATCHconst)
+	return expType(to, e1);
+
+    Type *tb = to->toBasetype();
+    Type *typeb = type->toBasetype();
+
+    if (e1->op == TOKstring)
+    {
+	if (tb->ty == Tarray && typeb->ty == Tarray &&
+	    tb->nextOf()->size() == typeb->nextOf()->size())
+	{
+	    return expType(to, e1);
+	}
+    }
+
+    if (e1->isConst() != 1)
+	return EXP_CANT_INTERPRET;
+
+    if (tb->ty == Tbool)
+	e = new IntegerExp(loc, e1->toInteger() != 0, type);
+    else if (type->isintegral())
+    {
+	if (e1->type->isfloating())
+	{   dinteger_t result;
+	    real_t r = e1->toReal();
+
+	    switch (typeb->ty)
+	    {
+		case Tint8:	result = (d_int8)r;	break;
+		case Tchar:
+		case Tuns8:	result = (d_uns8)r;	break;
+		case Tint16:	result = (d_int16)r;	break;
+		case Twchar:
+		case Tuns16:	result = (d_uns16)r;	break;
+		case Tint32:	result = (d_int32)r;	break;
+		case Tdchar:
+		case Tuns32:	result = (d_uns32)r;	break;
+		case Tint64:	result = (d_int64)r;	break;
+		case Tuns64:	result = (d_uns64)r;	break;
+		default:
+		    assert(0);
+	    }
+
+	    e = new IntegerExp(loc, result, type);
+	}
+	else if (type->isunsigned())
+	    e = new IntegerExp(loc, e1->toUInteger(), type);
+	else
+	    e = new IntegerExp(loc, e1->toInteger(), type);
+    }
+    else if (tb->isreal())
+    {   real_t value = e1->toReal();
+
+	e = new RealExp(loc, value, type);
+    }
+    else if (tb->isimaginary())
+    {   real_t value = e1->toImaginary();
+
+	e = new RealExp(loc, value, type);
+    }
+    else if (tb->iscomplex())
+    {   complex_t value = e1->toComplex();
+
+	e = new ComplexExp(loc, value, type);
+    }
+    else if (tb->isscalar())
+	e = new IntegerExp(loc, e1->toInteger(), type);
+    else if (tb->ty == Tvoid)
+	e = EXP_CANT_INTERPRET;
+    else if (tb->ty == Tstruct && e1->op == TOKint64)
+    {	// Struct = 0;
+	StructDeclaration *sd = tb->toDsymbol(NULL)->isStructDeclaration();
+	assert(sd);
+	Expressions *elements = new Expressions;
+	for (size_t i = 0; i < sd->fields.dim; i++)
+	{   Dsymbol *s = (Dsymbol *)sd->fields.data[i];
+	    VarDeclaration *v = s->isVarDeclaration();
+	    assert(v);
+
+	    Expression *exp = new IntegerExp(0);
+	    exp = Cast(v->type, v->type, exp);
+	    if (exp == EXP_CANT_INTERPRET)
+		return exp;
+	    elements->push(exp);
+	}
+	e = new StructLiteralExp(loc, sd, elements);
+	e->type = type;
+    }
+    else
+    {
+	error(loc, "cannot cast %s to %s", e1->type->toChars(), type->toChars());
+	e = new IntegerExp(loc, 0, Type::tint32);
+    }
+    return e;
+}
+
+
+Expression *ArrayLength(Type *type, Expression *e1)
+{   Expression *e;
+    Loc loc = e1->loc;
+
+    if (e1->op == TOKstring)
+    {	StringExp *es1 = (StringExp *)e1;
+
+	e = new IntegerExp(loc, es1->len, type);
+    }
+    else if (e1->op == TOKarrayliteral)
+    {	ArrayLiteralExp *ale = (ArrayLiteralExp *)e1;
+	size_t dim;
+
+	dim = ale->elements ? ale->elements->dim : 0;
+	e = new IntegerExp(loc, dim, type);
+    }
+    else if (e1->op == TOKassocarrayliteral)
+    {	AssocArrayLiteralExp *ale = (AssocArrayLiteralExp *)e1;
+	size_t dim = ale->keys->dim;
+
+	e = new IntegerExp(loc, dim, type);
+    }
+    else
+	e = EXP_CANT_INTERPRET;
+    return e;
+}
+
+/* Also return EXP_CANT_INTERPRET if this fails
+ */
+Expression *Index(Type *type, Expression *e1, Expression *e2)
+{   Expression *e = EXP_CANT_INTERPRET;
+    Loc loc = e1->loc;
+
+    //printf("Index(e1 = %s, e2 = %s)\n", e1->toChars(), e2->toChars());
+    assert(e1->type);
+    if (e1->op == TOKstring && e2->op == TOKint64)
+    {	StringExp *es1 = (StringExp *)e1;
+	uinteger_t i = e2->toInteger();
+
+	if (i >= es1->len)
+	    e1->error("string index %ju is out of bounds [0 .. %zu]", i, es1->len);
+	else
+	{   unsigned value = es1->charAt(i);
+	    e = new IntegerExp(loc, value, type);
+	}
+    }
+    else if (e1->type->toBasetype()->ty == Tsarray && e2->op == TOKint64)
+    {	TypeSArray *tsa = (TypeSArray *)e1->type->toBasetype();
+	uinteger_t length = tsa->dim->toInteger();
+	uinteger_t i = e2->toInteger();
+
+	if (i >= length)
+	{   e2->error("array index %ju is out of bounds %s[0 .. %ju]", i, e1->toChars(), length);
+	}
+	else if (e1->op == TOKarrayliteral && !e1->checkSideEffect(2))
+	{   ArrayLiteralExp *ale = (ArrayLiteralExp *)e1;
+	    e = (Expression *)ale->elements->data[i];
+	    e->type = type;
+	}
+    }
+    else if (e1->type->toBasetype()->ty == Tarray && e2->op == TOKint64)
+    {
+	uinteger_t i = e2->toInteger();
+
+	if (e1->op == TOKarrayliteral && !e1->checkSideEffect(2))
+	{   ArrayLiteralExp *ale = (ArrayLiteralExp *)e1;
+	    if (i >= ale->elements->dim)
+	    {   e2->error("array index %ju is out of bounds %s[0 .. %u]", i, e1->toChars(), ale->elements->dim);
+	    }
+	    else
+	    {	e = (Expression *)ale->elements->data[i];
+		e->type = type;
+	    }
+	}
+    }
+    else if (e1->op == TOKassocarrayliteral && !e1->checkSideEffect(2))
+    {
+	AssocArrayLiteralExp *ae = (AssocArrayLiteralExp *)e1;
+	/* Search the keys backwards, in case there are duplicate keys
+	 */
+	for (size_t i = ae->keys->dim; i;)
+	{
+	    i--;
+	    Expression *ekey = (Expression *)ae->keys->data[i];
+	    Expression *ex = Equal(TOKequal, Type::tbool, ekey, e2);
+	    if (ex == EXP_CANT_INTERPRET)
+		return ex;
+	    if (ex->isBool(TRUE))
+	    {	e = (Expression *)ae->values->data[i];
+		e->type = type;
+		break;
+	    }
+	}
+    }
+    return e;
+}
+
+/* Also return EXP_CANT_INTERPRET if this fails
+ */
+Expression *Slice(Type *type, Expression *e1, Expression *lwr, Expression *upr)
+{   Expression *e = EXP_CANT_INTERPRET;
+    Loc loc = e1->loc;
+
+#if LOG
+    printf("Slice()\n");
+    if (lwr)
+    {	printf("\te1 = %s\n", e1->toChars());
+	printf("\tlwr = %s\n", lwr->toChars());
+	printf("\tupr = %s\n", upr->toChars());
+    }
+#endif
+    if (e1->op == TOKstring && lwr->op == TOKint64 && upr->op == TOKint64)
+    {	StringExp *es1 = (StringExp *)e1;
+	uinteger_t ilwr = lwr->toInteger();
+	uinteger_t iupr = upr->toInteger();
+
+	if (iupr > es1->len || ilwr > iupr)
+	    e1->error("string slice [%ju .. %ju] is out of bounds", ilwr, iupr);
+	else
+	{   dinteger_t value;
+	    void *s;
+	    size_t len = iupr - ilwr;
+	    int sz = es1->sz;
+	    StringExp *es;
+
+	    s = mem.malloc((len + 1) * sz);
+	    memcpy((unsigned char *)s, (unsigned char *)es1->string + ilwr * sz, len * sz);
+	    memset((unsigned char *)s + len * sz, 0, sz);
+
+	    es = new StringExp(loc, s, len, es1->postfix);
+	    es->sz = sz;
+	    es->committed = 1;
+	    es->type = type;
+	    e = es;
+	}
+    }
+    else if (e1->op == TOKarrayliteral &&
+	    lwr->op == TOKint64 && upr->op == TOKint64 &&
+	    !e1->checkSideEffect(2))
+    {	ArrayLiteralExp *es1 = (ArrayLiteralExp *)e1;
+	uinteger_t ilwr = lwr->toInteger();
+	uinteger_t iupr = upr->toInteger();
+
+	if (iupr > es1->elements->dim || ilwr > iupr)
+	    e1->error("array slice [%ju .. %ju] is out of bounds", ilwr, iupr);
+	else
+	{
+	    Expressions *elements = new Expressions();
+	    elements->setDim(iupr - ilwr);
+	    memcpy(elements->data,
+		   es1->elements->data + ilwr,
+		   (iupr - ilwr) * sizeof(es1->elements->data[0]));
+	    e = new ArrayLiteralExp(e1->loc, elements);
+	    e->type = type;
+	}
+    }
+    return e;
+}
+
+/* Also return EXP_CANT_INTERPRET if this fails
+ */
+Expression *Cat(Type *type, Expression *e1, Expression *e2)
+{   Expression *e = EXP_CANT_INTERPRET;
+    Loc loc = e1->loc;
+    Type *t;
+    Type *t1 = e1->type->toBasetype();
+    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;
+	goto L2;
+    }
+    else if ((e1->op == TOKint64 || e1->op == TOKstructliteral) && e2->op == TOKnull)
+    {	e = e1;
+     L2:
+	Type *tn = e->type->toBasetype();
+	if (tn->ty == Tchar || tn->ty == Twchar || tn->ty == Tdchar)
+	{
+	    // Create a StringExp
+	    void *s;
+	    StringExp *es;
+	    size_t len = 1;
+	    int sz = tn->size();
+	    dinteger_t v = e->toInteger();
+
+	    s = mem.malloc((len + 1) * sz);
+	    memcpy((unsigned char *)s, &v, sz);
+
+	    // Add terminating 0
+	    memset((unsigned char *)s + len * sz, 0, sz);
+
+	    es = new StringExp(loc, s, len);
+	    es->sz = sz;
+	    es->committed = 1;
+	    e = es;
+	}
+	else
+	{   // Create an ArrayLiteralExp
+	    Expressions *elements = new Expressions();
+	    elements->push(e);
+	    e = new ArrayLiteralExp(e->loc, elements);
+	}
+	e->type = type;
+	return e;
+    }
+    else if (e1->op == TOKstring && e2->op == TOKstring)
+    {
+	// Concatenate the strings
+	void *s;
+	StringExp *es1 = (StringExp *)e1;
+	StringExp *es2 = (StringExp *)e2;
+	StringExp *es;
+	Type *t;
+	size_t len = es1->len + es2->len;
+	int sz = es1->sz;
+
+	if (sz != es2->sz)
+	{
+	    /* Can happen with:
+	     *   auto s = "foo"d ~ "bar"c;
+	     */
+	    assert(global.errors);
+	    return e;
+	}
+	s = mem.malloc((len + 1) * sz);
+	memcpy(s, es1->string, es1->len * sz);
+	memcpy((unsigned char *)s + es1->len * sz, es2->string, es2->len * sz);
+
+	// Add terminating 0
+	memset((unsigned char *)s + len * sz, 0, sz);
+
+	es = new StringExp(loc, s, len);
+	es->sz = sz;
+	es->committed = es1->committed | es2->committed;
+	if (es1->committed)
+	    t = es1->type;
+	else
+	    t = es2->type;
+	es->type = type;
+	e = es;
+    }
+    else if (e1->op == TOKstring && e2->op == TOKint64)
+    {
+	// Concatenate the strings
+	void *s;
+	StringExp *es1 = (StringExp *)e1;
+	StringExp *es;
+	Type *t;
+	size_t len = es1->len + 1;
+	int sz = es1->sz;
+	dinteger_t v = e2->toInteger();
+
+	s = mem.malloc((len + 1) * sz);
+	memcpy(s, es1->string, es1->len * sz);
+	memcpy((unsigned char *)s + es1->len * sz, &v, sz);
+
+	// Add terminating 0
+	memset((unsigned char *)s + len * sz, 0, sz);
+
+	es = new StringExp(loc, s, len);
+	es->sz = sz;
+	es->committed = es1->committed;
+	t = es1->type;
+	es->type = type;
+	e = es;
+    }
+    else if (e1->op == TOKint64 && e2->op == TOKstring)
+    {
+	// Concatenate the strings
+	void *s;
+	StringExp *es2 = (StringExp *)e2;
+	StringExp *es;
+	Type *t;
+	size_t len = 1 + es2->len;
+	int sz = es2->sz;
+	dinteger_t v = e1->toInteger();
+
+	s = mem.malloc((len + 1) * sz);
+	memcpy((unsigned char *)s, &v, sz);
+	memcpy((unsigned char *)s + sz, es2->string, es2->len * sz);
+
+	// Add terminating 0
+	memset((unsigned char *)s + len * sz, 0, sz);
+
+	es = new StringExp(loc, s, len);
+	es->sz = sz;
+	es->committed = es2->committed;
+	t = es2->type;
+	es->type = type;
+	e = es;
+    }
+    else if (e1->op == TOKarrayliteral && e2->op == TOKarrayliteral &&
+	t1->nextOf()->equals(t2->nextOf()))
+    {
+	// Concatenate the arrays
+	ArrayLiteralExp *es1 = (ArrayLiteralExp *)e1;
+	ArrayLiteralExp *es2 = (ArrayLiteralExp *)e2;
+
+	es1 = new ArrayLiteralExp(es1->loc, (Expressions *)es1->elements->copy());
+	es1->elements->insert(es1->elements->dim, es2->elements);
+	e = es1;
+
+	if (type->toBasetype()->ty == Tsarray)
+	{
+	    e->type = new TypeSArray(t1->nextOf(), new IntegerExp(loc, es1->elements->dim, Type::tindex));
+	    e->type = e->type->semantic(loc, NULL);
+	}
+	else
+	    e->type = type;
+    }
+    else if (e1->op == TOKarrayliteral && e2->op == TOKnull &&
+	t1->nextOf()->equals(t2->nextOf()))
+    {
+	e = e1;
+	goto L3;
+    }
+    else if (e1->op == TOKnull && e2->op == TOKarrayliteral &&
+	t1->nextOf()->equals(t2->nextOf()))
+    {
+	e = e2;
+     L3:
+	// Concatenate the array with null
+	ArrayLiteralExp *es = (ArrayLiteralExp *)e;
+
+	es = new ArrayLiteralExp(es->loc, (Expressions *)es->elements->copy());
+	e = es;
+
+	if (type->toBasetype()->ty == Tsarray)
+	{
+	    e->type = new TypeSArray(t1->nextOf(), new IntegerExp(loc, es->elements->dim, Type::tindex));
+	    e->type = e->type->semantic(loc, NULL);
+	}
+	else
+	    e->type = type;
+    }
+    else if ((e1->op == TOKarrayliteral || e1->op == TOKnull) &&
+	e1->type->toBasetype()->nextOf()->equals(e2->type))
+    {
+	ArrayLiteralExp *es1;
+	if (e1->op == TOKarrayliteral)
+	{   es1 = (ArrayLiteralExp *)e1;
+	    es1 = new ArrayLiteralExp(es1->loc, (Expressions *)es1->elements->copy());
+	    es1->elements->push(e2);
+	}
+	else
+	{
+	    es1 = new ArrayLiteralExp(e1->loc, e2);
+	}
+	e = es1;
+
+	if (type->toBasetype()->ty == Tsarray)
+	{
+	    e->type = new TypeSArray(e2->type, new IntegerExp(loc, es1->elements->dim, Type::tindex));
+	    e->type = e->type->semantic(loc, NULL);
+	}
+	else
+	    e->type = type;
+    }
+    else if (e2->op == TOKarrayliteral &&
+	e2->type->toBasetype()->nextOf()->equals(e1->type))
+    {
+	ArrayLiteralExp *es2 = (ArrayLiteralExp *)e2;
+
+	es2 = new ArrayLiteralExp(es2->loc, (Expressions *)es2->elements->copy());
+	es2->elements->shift(e1);
+	e = es2;
+
+	if (type->toBasetype()->ty == Tsarray)
+	{
+	    e->type = new TypeSArray(e1->type, new IntegerExp(loc, es2->elements->dim, Type::tindex));
+	    e->type = e->type->semantic(loc, NULL);
+	}
+	else
+	    e->type = type;
+    }
+    else if (e1->op == TOKnull && e2->op == TOKstring)
+    {
+	t = e1->type;
+	e = e2;
+	goto L1;
+    }
+    else if (e1->op == TOKstring && e2->op == TOKnull)
+    {	e = e1;
+	t = e2->type;
+      L1:
+	Type *tb = t->toBasetype();
+	if (tb->ty == Tarray && tb->nextOf()->equals(e->type))
+	{   Expressions *expressions = new Expressions();
+	    expressions->push(e);
+	    e = new ArrayLiteralExp(loc, expressions);
+	    e->type = t;
+	}
+	if (!e->type->equals(type))
+	{   StringExp *se = (StringExp *)e->copy();
+	    e = se->castTo(NULL, type);
+	}
+    }
+    return e;
+}
+
+Expression *Ptr(Type *type, Expression *e1)
+{
+    //printf("Ptr(e1 = %s)\n", e1->toChars());
+    if (e1->op == TOKadd)
+    {	AddExp *ae = (AddExp *)e1;
+	if (ae->e1->op == TOKaddress && ae->e2->op == TOKint64)
+	{   AddrExp *ade = (AddrExp *)ae->e1;
+	    if (ade->e1->op == TOKstructliteral)
+	    {	StructLiteralExp *se = (StructLiteralExp *)ade->e1;
+		unsigned offset = ae->e2->toInteger();
+		Expression *e = se->getField(type, offset);
+		if (!e)
+		    e = EXP_CANT_INTERPRET;
+		return e;
+	    }
+	}
+    }
+    return EXP_CANT_INTERPRET;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd2/cppmangle.c	Mon Jun 01 19:02:20 2009 +0100
@@ -0,0 +1,381 @@
+
+// Compiler implementation of the D programming language
+// Copyright (c) 1999-2007 by Digital Mars
+// All Rights Reserved
+// written by Walter Bright
+// http://www.digitalmars.com
+// License for redistribution is by either the Artistic License
+// in artistic.txt, or the GNU General Public License in gnu.txt.
+// See the included readme.txt for details.
+
+#include <stdio.h>
+#include <assert.h>
+
+#include "mars.h"
+#include "dsymbol.h"
+#include "mtype.h"
+#include "scope.h"
+#include "init.h"
+#include "expression.h"
+#include "attrib.h"
+#include "declaration.h"
+#include "template.h"
+#include "id.h"
+#include "enum.h"
+#include "import.h"
+#include "aggregate.h"
+
+#if DMDV2
+
+/* Do mangling for C++ linkage.
+ * Follows Itanium C++ ABI 1.86
+ * No attempt is made to support mangling of templates, operator
+ * overloading, or special functions.
+ *
+ * So why don't we use the C++ ABI for D name mangling?
+ * Because D supports a lot of things (like modules) that the C++
+ * ABI has no concept of. These affect every D mangled name,
+ * so nothing would be compatible anyway.
+ */
+
+struct CppMangleState
+{
+    static Array components;
+
+    int substitute(OutBuffer *buf, void *p);
+};
+
+Array CppMangleState::components;
+
+
+void writeBase36(OutBuffer *buf, unsigned i)
+{
+    if (i >= 36)
+    {
+	writeBase36(buf, i / 36);
+	i %= 36;
+    }
+    if (i < 10)
+	buf->writeByte(i + '0');
+    else if (i < 36)
+	buf->writeByte(i - 10 + 'A');
+    else
+	assert(0);
+}
+
+int CppMangleState::substitute(OutBuffer *buf, void *p)
+{
+    for (size_t i = 0; i < components.dim; i++)
+    {
+	if (p == components.data[i])
+	{
+	    /* Sequence is S_, S0_, .., S9_, SA_, ..., SZ_, S10_, ...
+	     */
+	    buf->writeByte('S');
+	    if (i)
+		writeBase36(buf, i - 1);
+	    buf->writeByte('_');
+	    return 1;
+	}
+    }
+    components.push(p);
+    return 0;
+}
+
+void source_name(OutBuffer *buf, Dsymbol *s)
+{
+    char *name = s->ident->toChars();
+    buf->printf("%d%s", strlen(name), name);
+}
+
+void prefix_name(OutBuffer *buf, CppMangleState *cms, Dsymbol *s)
+{
+    if (!cms->substitute(buf, s))
+    {
+	Dsymbol *p = s->toParent();
+	if (p && !p->isModule())
+	{
+	    prefix_name(buf, cms, p);
+	}
+	source_name(buf, s);
+    }
+}
+
+void cpp_mangle_name(OutBuffer *buf, CppMangleState *cms, Dsymbol *s)
+{
+    Dsymbol *p = s->toParent();
+    if (p && !p->isModule())
+    {
+	buf->writeByte('N');
+
+	FuncDeclaration *fd = s->isFuncDeclaration();
+	if (fd->isConst())
+	    buf->writeByte('K');
+
+	prefix_name(buf, cms, p);
+	source_name(buf, s);
+
+	buf->writeByte('E');
+    }
+    else
+	source_name(buf, s);
+}
+
+
+char *cpp_mangle(Dsymbol *s)
+{
+    /*
+     * <mangled-name> ::= _Z <encoding>
+     * <encoding> ::= <function name> <bare-function-type>
+     *	       ::= <data name>
+     *	       ::= <special-name>
+     */
+
+    CppMangleState cms;
+    memset(&cms, 0, sizeof(cms));
+    cms.components.setDim(0);
+
+    OutBuffer buf;
+#if MACHOBJ
+    buf.writestring("__Z");
+#else
+    buf.writestring("_Z");
+#endif
+
+    cpp_mangle_name(&buf, &cms, s);
+
+    FuncDeclaration *fd = s->isFuncDeclaration();
+    if (fd)
+    {	// add <bare-function-type>
+	TypeFunction *tf = (TypeFunction *)fd->type;
+	assert(tf->ty == Tfunction);
+	Argument::argsCppMangle(&buf, &cms, tf->parameters, tf->varargs);
+    }
+    buf.writeByte(0);
+    return (char *)buf.extractData();
+}
+
+/* ============= Type Encodings ============================================= */
+
+void Type::toCppMangle(OutBuffer *buf, CppMangleState *cms)
+{
+    /* Make this the 'vendor extended type' when there is no
+     * C++ analog.
+     * u <source-name>
+     */
+    if (!cms->substitute(buf, this))
+    {	assert(deco);
+	buf->printf("u%d%s", strlen(deco), deco);
+    }
+}
+
+void TypeBasic::toCppMangle(OutBuffer *buf, CppMangleState *cms)
+{   char c;
+    char p = 0;
+
+    /* ABI spec says:
+     * v	void
+     * w	wchar_t
+     * b	bool
+     * c	char
+     * a	signed char
+     * h	unsigned char
+     * s	short
+     * t	unsigned short
+     * i	int
+     * j	unsigned int
+     * l	long
+     * m	unsigned long
+     * x	long long, __int64
+     * y	unsigned long long, __int64
+     * n	__int128
+     * o	unsigned __int128
+     * f	float
+     * d	double
+     * e	long double, __float80
+     * g	__float128
+     * z	ellipsis
+     * u <source-name>	# vendor extended type
+     */
+
+    switch (ty)
+    {
+	case Tvoid:	c = 'v';	break;
+	case Tint8:	c = 'a';	break;
+	case Tuns8:	c = 'h';	break;
+	case Tint16:	c = 's';	break;
+	case Tuns16:	c = 't';	break;
+	case Tint32:	c = 'i';	break;
+	case Tuns32:	c = 'j';	break;
+	case Tfloat32:	c = 'f';	break;
+	case Tint64:	c = 'x';	break;
+	case Tuns64:	c = 'y';	break;
+	case Tfloat64:	c = 'd';	break;
+	case Tfloat80:	c = 'e';	break;
+	case Tbool:	c = 'b';	break;
+	case Tchar:	c = 'c';	break;
+	case Twchar:	c = 't';	break;
+	case Tdchar:	c = 'w';	break;
+
+	case Timaginary32: p = 'G'; c = 'f';	break;
+	case Timaginary64: p = 'G'; c = 'd';	break;
+	case Timaginary80: p = 'G'; c = 'e';	break;
+	case Tcomplex32:   p = 'C'; c = 'f';	break;
+	case Tcomplex64:   p = 'C'; c = 'd';	break;
+	case Tcomplex80:   p = 'C'; c = 'e';	break;
+
+	default:	assert(0);
+    }
+    if (p)
+    {
+	if (cms->substitute(buf, this))
+	    return;
+	buf->writeByte(p);
+    }
+    buf->writeByte(c);
+}
+
+
+void TypeSArray::toCppMangle(OutBuffer *buf, CppMangleState *cms)
+{
+    if (!cms->substitute(buf, this))
+    {	buf->printf("A%ju_", dim ? dim->toInteger() : 0);
+	next->toCppMangle(buf, cms);
+    }
+}
+
+void TypeDArray::toCppMangle(OutBuffer *buf, CppMangleState *cms)
+{
+    Type::toCppMangle(buf, cms);
+}
+
+
+void TypeAArray::toCppMangle(OutBuffer *buf, CppMangleState *cms)
+{
+    Type::toCppMangle(buf, cms);
+}
+
+
+void TypePointer::toCppMangle(OutBuffer *buf, CppMangleState *cms)
+{
+    if (!cms->substitute(buf, this))
+    {	buf->writeByte('P');
+	next->toCppMangle(buf, cms);
+    }
+}
+
+
+void TypeReference::toCppMangle(OutBuffer *buf, CppMangleState *cms)
+{
+    if (!cms->substitute(buf, this))
+    {	buf->writeByte('R');
+	next->toCppMangle(buf, cms);
+    }
+}
+
+
+void TypeFunction::toCppMangle(OutBuffer *buf, CppMangleState *cms)
+{   /*
+     *	<function-type> ::= F [Y] <bare-function-type> E
+     *	<bare-function-type> ::= <signature type>+
+     *	# types are possible return type, then parameter types
+     */
+
+    /* ABI says:
+	"The type of a non-static member function is considered to be different,
+	for the purposes of substitution, from the type of a namespace-scope or
+	static member function whose type appears similar. The types of two
+	non-static member functions are considered to be different, for the
+	purposes of substitution, if the functions are members of different
+	classes. In other words, for the purposes of substitution, the class of
+	which the function is a member is considered part of the type of
+	function."
+
+	BUG: Right now, types of functions are never merged, so our simplistic
+	component matcher always finds them to be different.
+	We should use Type::equals on these, and use different
+	TypeFunctions for non-static member functions, and non-static
+	member functions of different classes.
+     */
+    if (!cms->substitute(buf, this))
+    {
+	buf->writeByte('F');
+	if (linkage == LINKc)
+	    buf->writeByte('Y');
+	next->toCppMangle(buf, cms);
+	Argument::argsCppMangle(buf, cms, parameters, varargs);
+	buf->writeByte('E');
+    }
+}
+
+
+void TypeDelegate::toCppMangle(OutBuffer *buf, CppMangleState *cms)
+{
+    Type::toCppMangle(buf, cms);
+}
+
+
+void TypeStruct::toCppMangle(OutBuffer *buf, CppMangleState *cms)
+{
+    if (!cms->substitute(buf, sym))
+	cpp_mangle_name(buf, cms, sym);
+}
+
+
+void TypeEnum::toCppMangle(OutBuffer *buf, CppMangleState *cms)
+{
+    if (!cms->substitute(buf, sym))
+	cpp_mangle_name(buf, cms, sym);
+}
+
+
+void TypeTypedef::toCppMangle(OutBuffer *buf, CppMangleState *cms)
+{
+    Type::toCppMangle(buf, cms);
+}
+
+
+void TypeClass::toCppMangle(OutBuffer *buf, CppMangleState *cms)
+{
+    if (!cms->substitute(buf, this))
+    {	buf->writeByte('P');
+	if (!cms->substitute(buf, sym))
+	    cpp_mangle_name(buf, cms, sym);
+    }
+}
+
+
+
+void Argument::argsCppMangle(OutBuffer *buf, CppMangleState *cms, Arguments *arguments, int varargs)
+{   int n = 0;
+    if (arguments)
+    {
+	for (size_t i = 0; i < arguments->dim; i++)
+	{   Argument *arg = (Argument *)arguments->data[i];
+	    Type *t = arg->type;
+	    if (arg->storageClass & (STCout | STCref))
+		t = t->referenceTo();
+	    else if (arg->storageClass & STClazy)
+	    {	// Mangle as delegate
+		Type *td = new TypeFunction(NULL, t, 0, LINKd);
+		td = new TypeDelegate(td);
+		t = t->merge();
+	    }
+	    if (t->ty == Tsarray)
+	    {	// Mangle static arrays as pointers
+		t = t->pointerTo();
+	    }
+	    t->toCppMangle(buf, cms);
+
+	    n++;
+	}
+    }
+    if (varargs)
+	buf->writestring("z");
+    else if (!n)
+	buf->writeByte('v');		// encode ( ) arguments
+}
+
+
+#endif
+
--- a/dmd2/dchar.c	Mon Jun 01 01:28:18 2009 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,482 +0,0 @@
-
-// Copyright (c) 1999-2006 by Digital Mars
-// All Rights Reserved
-// written by Walter Bright
-// 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 <stdlib.h>
-#include <stdint.h>
-#include <assert.h>
-
-#include "dchar.h"
-#include "mem.h"
-
-#if M_UNICODE
-
-// Converts a char string to Unicode
-
-dchar *Dchar::dup(char *p)
-{
-    dchar *s;
-    size_t len;
-
-    if (!p)
-	return NULL;
-    len = strlen(p);
-    s = (dchar *)mem.malloc((len + 1) * sizeof(dchar));
-    for (unsigned i = 0; i < len; i++)
-    {
-	s[i] = (dchar)(p[i] & 0xFF);
-    }
-    s[len] = 0;
-    return s;
-}
-
-dchar *Dchar::memchr(dchar *p, int c, int count)
-{
-    int u;
-
-    for (u = 0; u < count; u++)
-    {
-	if (p[u] == c)
-	    return p + u;
-    }
-    return NULL;
-}
-
-#if _WIN32 && __DMC__
-__declspec(naked)
-unsigned Dchar::calcHash(const dchar *str, unsigned len)
-{
-    __asm
-    {
-	mov	ECX,4[ESP]
-	mov	EDX,8[ESP]
-	xor	EAX,EAX
-	test	EDX,EDX
-	je	L92
-
-LC8:	cmp	EDX,1
-	je	L98
-	cmp	EDX,2
-	je	LAE
-
-	add	EAX,[ECX]
-//	imul	EAX,EAX,025h
-	lea	EAX,[EAX][EAX*8]
-	add	ECX,4
-	sub	EDX,2
-	jmp	LC8
-
-L98:	mov	DX,[ECX]
-	and	EDX,0FFFFh
-	add	EAX,EDX
-	ret
-
-LAE:	add	EAX,[ECX]
-L92:	ret
-    }
-}
-#else
-hash_t Dchar::calcHash(const dchar *str, size_t len)
-{
-    unsigned hash = 0;
-
-    for (;;)
-    {
-	switch (len)
-	{
-	    case 0:
-		return hash;
-
-	    case 1:
-		hash += *(const uint16_t *)str;
-		return hash;
-
-	    case 2:
-		hash += *(const uint32_t *)str;
-		return hash;
-
-	    default:
-		hash += *(const uint32_t *)str;
-		hash *= 37;
-		str += 2;
-		len -= 2;
-		break;
-	}
-    }
-}
-#endif
-
-hash_t Dchar::icalcHash(const dchar *str, size_t len)
-{
-    hash_t hash = 0;
-
-    for (;;)
-    {
-	switch (len)
-	{
-	    case 0:
-		return hash;
-
-	    case 1:
-		hash += *(const uint16_t *)str | 0x20;
-		return hash;
-
-	    case 2:
-		hash += *(const uint32_t *)str | 0x200020;
-		return hash;
-
-	    default:
-		hash += *(const uint32_t *)str | 0x200020;
-		hash *= 37;
-		str += 2;
-		len -= 2;
-		break;
-	}
-    }
-}
-
-#elif MCBS
-
-hash_t Dchar::calcHash(const dchar *str, size_t len)
-{
-    hash_t hash = 0;
-
-    while (1)
-    {
-	switch (len)
-	{
-	    case 0:
-		return hash;
-
-	    case 1:
-		hash *= 37;
-		hash += *(const uint8_t *)str;
-		return hash;
-
-	    case 2:
-		hash *= 37;
-		hash += *(const uint16_t *)str;
-		return hash;
-
-	    case 3:
-		hash *= 37;
-		hash += (*(const uint16_t *)str << 8) +
-			((const uint8_t *)str)[2];
-		return hash;
-
-	    default:
-		hash *= 37;
-		hash += *(const uint32_t *)str;
-		str += 4;
-		len -= 4;
-		break;
-	}
-    }
-}
-
-#elif UTF8
-
-// Specification is: http://anubis.dkuug.dk/JTC1/SC2/WG2/docs/n1335
-
-char Dchar::mblen[256] =
-{
-    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
-    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
-    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
-    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
-    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
-    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
-    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
-    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
-    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
-    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
-    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
-    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
-    2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
-    2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
-    3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
-    4,4,4,4,4,4,4,4,5,5,5,5,6,6,1,1,
-};
-
-dchar *Dchar::dec(dchar *pstart, dchar *p)
-{
-    while ((p[-1] & 0xC0) == 0x80)
-	p--;
-    return p;
-}
-
-int Dchar::get(dchar *p)
-{
-    unsigned c;
-    unsigned char *q = (unsigned char *)p;
-
-    c = q[0];
-    switch (mblen[c])
-    {
-	case 2:
-	    c = ((c    - 0xC0) << 6) |
-		 (q[1] - 0x80);
-	    break;
-
-	case 3:
-	    c = ((c    - 0xE0) << 12) |
-		((q[1] - 0x80) <<  6) |
-		 (q[2] - 0x80);
-	    break;
-
-	case 4:
-	    c = ((c    - 0xF0) << 18) |
-		((q[1] - 0x80) << 12) |
-		((q[2] - 0x80) <<  6) |
-		 (q[3] - 0x80);
-	    break;
-
-	case 5:
-	    c = ((c    - 0xF8) << 24) |
-		((q[1] - 0x80) << 18) |
-		((q[2] - 0x80) << 12) |
-		((q[3] - 0x80) <<  6) |
-		 (q[4] - 0x80);
-	    break;
-
-	case 6:
-	    c = ((c    - 0xFC) << 30) |
-		((q[1] - 0x80) << 24) |
-		((q[2] - 0x80) << 18) |
-		((q[3] - 0x80) << 12) |
-		((q[4] - 0x80) <<  6) |
-		 (q[5] - 0x80);
-	    break;
-    }
-    return c;
-}
-
-dchar *Dchar::put(dchar *p, unsigned c)
-{
-    if (c <= 0x7F)
-    {
-	*p++ = c;
-    }
-    else if (c <= 0x7FF)
-    {
-	p[0] = 0xC0 + (c >> 6);
-	p[1] = 0x80 + (c & 0x3F);
-	p += 2;
-    }
-    else if (c <= 0xFFFF)
-    {
-	p[0] = 0xE0 + (c >> 12);
-	p[1] = 0x80 + ((c >> 6) & 0x3F);
-	p[2] = 0x80 + (c & 0x3F);
-	p += 3;
-    }
-    else if (c <= 0x1FFFFF)
-    {
-	p[0] = 0xF0 + (c >> 18);
-	p[1] = 0x80 + ((c >> 12) & 0x3F);
-	p[2] = 0x80 + ((c >> 6) & 0x3F);
-	p[3] = 0x80 + (c & 0x3F);
-	p += 4;
-    }
-    else if (c <= 0x3FFFFFF)
-    {
-	p[0] = 0xF8 + (c >> 24);
-	p[1] = 0x80 + ((c >> 18) & 0x3F);
-	p[2] = 0x80 + ((c >> 12) & 0x3F);
-	p[3] = 0x80 + ((c >> 6) & 0x3F);
-	p[4] = 0x80 + (c & 0x3F);
-	p += 5;
-    }
-    else if (c <= 0x7FFFFFFF)
-    {
-	p[0] = 0xFC + (c >> 30);
-	p[1] = 0x80 + ((c >> 24) & 0x3F);
-	p[2] = 0x80 + ((c >> 18) & 0x3F);
-	p[3] = 0x80 + ((c >> 12) & 0x3F);
-	p[4] = 0x80 + ((c >> 6) & 0x3F);
-	p[5] = 0x80 + (c & 0x3F);
-	p += 6;
-    }
-    else
-	assert(0);		// not a UCS-4 character
-    return p;
-}
-
-hash_t Dchar::calcHash(const dchar *str, size_t len)
-{
-    hash_t hash = 0;
-
-    while (1)
-    {
-	switch (len)
-	{
-	    case 0:
-		return hash;
-
-	    case 1:
-		hash *= 37;
-		hash += *(const uint8_t *)str;
-		return hash;
-
-	    case 2:
-		hash *= 37;
-#if __I86__
-		hash += *(const uint16_t *)str;
-#else
-		hash += str[0] * 256 + str[1];
-#endif
-		return hash;
-
-	    case 3:
-		hash *= 37;
-#if __I86__
-		hash += (*(const uint16_t *)str << 8) +
-			((const uint8_t *)str)[2];
-#else
-		hash += (str[0] * 256 + str[1]) * 256 + str[2];
-#endif
-		return hash;
-
-	    default:
-		hash *= 37;
-#if __I86__
-		hash += *(const uint32_t *)str;
-#else
-		hash += ((str[0] * 256 + str[1]) * 256 + str[2]) * 256 + str[3];
-#endif
-
-		str += 4;
-		len -= 4;
-		break;
-	}
-    }
-}
-
-#else // ascii
-
-hash_t Dchar::calcHash(const dchar *str, size_t len)
-{
-    hash_t hash = 0;
-
-    while (1)
-    {
-	switch (len)
-	{
-	    case 0:
-		return hash;
-
-	    case 1:
-		hash *= 37;
-		hash += *(const uint8_t *)str;
-		return hash;
-
-	    case 2:
-		hash *= 37;
-#if __I86__
-		hash += *(const uint16_t *)str;
-#else
-		hash += str[0] * 256 + str[1];
-#endif
-		return hash;
-
-	    case 3:
-		hash *= 37;
-#if __I86__
-		hash += (*(const uint16_t *)str << 8) +
-			((const uint8_t *)str)[2];
-#else
-		hash += (str[0] * 256 + str[1]) * 256 + str[2];
-#endif
-		return hash;
-
-	    default:
-		hash *= 37;
-#if __I86__
-		hash += *(const uint32_t *)str;
-#else
-		hash += ((str[0] * 256 + str[1]) * 256 + str[2]) * 256 + str[3];
-#endif
-		str += 4;
-		len -= 4;
-		break;
-	}
-    }
-}
-
-hash_t Dchar::icalcHash(const dchar *str, size_t len)
-{
-    hash_t hash = 0;
-
-    while (1)
-    {
-	switch (len)
-	{
-	    case 0:
-		return hash;
-
-	    case 1:
-		hash *= 37;
-		hash += *(const uint8_t *)str | 0x20;
-		return hash;
-
-	    case 2:
-		hash *= 37;
-		hash += *(const uint16_t *)str | 0x2020;
-		return hash;
-
-	    case 3:
-		hash *= 37;
-		hash += ((*(const uint16_t *)str << 8) +
-			 ((const uint8_t *)str)[2]) | 0x202020;
-		return hash;
-
-	    default:
-		hash *= 37;
-		hash += *(const uint32_t *)str | 0x20202020;
-		str += 4;
-		len -= 4;
-		break;
-	}
-    }
-}
-
-#endif
-
-#if 0
-#include <stdio.h>
-
-void main()
-{
-    // Print out values to hardcode into Dchar::mblen[]
-    int c;
-    int s;
-
-    for (c = 0; c < 256; c++)
-    {
-	s = 1;
-	if (c >= 0xC0 && c <= 0xDF)
-	    s = 2;
-	if (c >= 0xE0 && c <= 0xEF)
-	    s = 3;
-	if (c >= 0xF0 && c <= 0xF7)
-	    s = 4;
-	if (c >= 0xF8 && c <= 0xFB)
-	    s = 5;
-	if (c >= 0xFC && c <= 0xFD)
-	    s = 6;
-
-	printf("%d", s);
-	if ((c & 15) == 15)
-	    printf(",\n");
-	else
-	    printf(",");
-    }
-}
-#endif
--- a/dmd2/dchar.h	Mon Jun 01 01:28:18 2009 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,194 +0,0 @@
-
-// Copyright (c) 1999-2006 by Digital Mars
-// All Rights Reserved
-// written by Walter Bright
-// www.digitalmars.com
-// License for redistribution is by either the Artistic License
-// in artistic.txt, or the GNU General Public License in gnu.txt.
-// See the included readme.txt for details.
-
-
-#ifndef DCHAR_H
-#define DCHAR_H
-
-#if __GNUC__ && !_WIN32
-#include "gnuc.h"
-#endif
-
-#if _MSC_VER
-    // Disable useless warnings about unreferenced functions
-    #pragma warning (disable : 4514)
-#endif
-
-//#include "root.h"
-typedef size_t hash_t;
-
-#undef TEXT
-
-// NOTE: All functions accepting pointer arguments must not be NULL
-
-#if M_UNICODE
-
-#include <string.h>
-#include <wchar.h>
-
-typedef wchar_t dchar;
-#define TEXT(x)		L##x
-
-#define Dchar_mbmax	1
-
-struct Dchar
-{
-    static dchar *inc(dchar *p) { return p + 1; }
-    static dchar *dec(dchar *pstart, dchar *p) { (void)pstart; return p - 1; }
-    static int len(const dchar *p) { return wcslen(p); }
-    static dchar get(dchar *p) { return *p; }
-    static dchar getprev(dchar *pstart, dchar *p) { (void)pstart; return p[-1]; }
-    static dchar *put(dchar *p, dchar c) { *p = c; return p + 1; }
-    static int cmp(dchar *s1, dchar *s2)
-    {
-#if __DMC__
-	if (!*s1 && !*s2)	// wcscmp is broken
-	    return 0;
-#endif
-	return wcscmp(s1, s2);
-#if 0
-	return (*s1 == *s2)
-	    ? wcscmp(s1, s2)
-	    : ((int)*s1 - (int)*s2);
-#endif
-    }
-    static int memcmp(const dchar *s1, const dchar *s2, int nchars) { return ::memcmp(s1, s2, nchars * sizeof(dchar)); }
-    static int isDigit(dchar c) { return '0' <= c && c <= '9'; }
-    static int isAlpha(dchar c) { return iswalpha(c); }
-    static int isUpper(dchar c) { return iswupper(c); }
-    static int isLower(dchar c) { return iswlower(c); }
-    static int isLocaleUpper(dchar c) { return isUpper(c); }
-    static int isLocaleLower(dchar c) { return isLower(c); }
-    static int toLower(dchar c) { return isUpper(c) ? towlower(c) : c; }
-    static int toLower(dchar *p) { return toLower(*p); }
-    static int toUpper(dchar c) { return isLower(c) ? towupper(c) : c; }
-    static dchar *dup(dchar *p) { return ::_wcsdup(p); }	// BUG: out of memory?
-    static dchar *dup(char *p);
-    static dchar *chr(dchar *p, unsigned c) { return wcschr(p, (dchar)c); }
-    static dchar *rchr(dchar *p, unsigned c) { return wcsrchr(p, (dchar)c); }
-    static dchar *memchr(dchar *p, int c, int count);
-    static dchar *cpy(dchar *s1, dchar *s2) { return wcscpy(s1, s2); }
-    static dchar *str(dchar *s1, dchar *s2) { return wcsstr(s1, s2); }
-    static hash_t calcHash(const dchar *str, size_t len);
-
-    // Case insensitive versions
-    static int icmp(dchar *s1, dchar *s2) { return wcsicmp(s1, s2); }
-    static int memicmp(const dchar *s1, const dchar *s2, int nchars) { return ::wcsnicmp(s1, s2, nchars); }
-    static hash_t icalcHash(const dchar *str, size_t len);
-};
-
-#elif MCBS
-
-#include <limits.h>
-#include <mbstring.h>
-
-typedef char dchar;
-#define TEXT(x)		x
-
-#define Dchar_mbmax	MB_LEN_MAX
-
-#elif UTF8
-
-typedef char dchar;
-#define TEXT(x)		x
-
-#define Dchar_mbmax	6
-
-struct Dchar
-{
-    static char mblen[256];
-
-    static dchar *inc(dchar *p) { return p + mblen[*p & 0xFF]; }
-    static dchar *dec(dchar *pstart, dchar *p);
-    static int len(const dchar *p) { return strlen(p); }
-    static int get(dchar *p);
-    static int getprev(dchar *pstart, dchar *p)
-	{ return *dec(pstart, p) & 0xFF; }
-    static dchar *put(dchar *p, unsigned c);
-    static int cmp(dchar *s1, dchar *s2) { return strcmp(s1, s2); }
-    static int memcmp(const dchar *s1, const dchar *s2, int nchars) { return ::memcmp(s1, s2, nchars); }
-    static int isDigit(dchar c) { return '0' <= c && c <= '9'; }
-    static int isAlpha(dchar c) { return c <= 0x7F ? isalpha(c) : 0; }
-    static int isUpper(dchar c) { return c <= 0x7F ? isupper(c) : 0; }
-    static int isLower(dchar c) { return c <= 0x7F ? islower(c) : 0; }
-    static int isLocaleUpper(dchar c) { return isUpper(c); }
-    static int isLocaleLower(dchar c) { return isLower(c); }
-    static int toLower(dchar c) { return isUpper(c) ? tolower(c) : c; }
-    static int toLower(dchar *p) { return toLower(*p); }
-    static int toUpper(dchar c) { return isLower(c) ? toupper(c) : c; }
-    static dchar *dup(dchar *p) { return ::strdup(p); }	// BUG: out of memory?
-    static dchar *chr(dchar *p, int c) { return strchr(p, c); }
-    static dchar *rchr(dchar *p, int c) { return strrchr(p, c); }
-    static dchar *memchr(dchar *p, int c, int count)
-	{ return (dchar *)::memchr(p, c, count); }
-    static dchar *cpy(dchar *s1, dchar *s2) { return strcpy(s1, s2); }
-    static dchar *str(dchar *s1, dchar *s2) { return strstr(s1, s2); }
-    static hash_t calcHash(const dchar *str, size_t len);
-
-    // Case insensitive versions
-    static int icmp(dchar *s1, dchar *s2) { return _mbsicmp(s1, s2); }
-    static int memicmp(const dchar *s1, const dchar *s2, int nchars) { return ::_mbsnicmp(s1, s2, nchars); }
-};
-
-#else
-
-#include <string.h>
-
-#ifndef GCC_SAFE_DMD
-#include <ctype.h>
-#endif
-
-typedef char dchar;
-#define TEXT(x)		x
-
-#define Dchar_mbmax	1
-
-struct Dchar
-{
-    static dchar *inc(dchar *p) { return p + 1; }
-    static dchar *dec(dchar *pstart, dchar *p) { return p - 1; }
-    static int len(const dchar *p) { return strlen(p); }
-    static int get(dchar *p) { return *p & 0xFF; }
-    static int getprev(dchar *pstart, dchar *p) { return p[-1] & 0xFF; }
-    static dchar *put(dchar *p, unsigned c) { *p = c; return p + 1; }
-    static int cmp(dchar *s1, dchar *s2) { return strcmp(s1, s2); }
-    static int memcmp(const dchar *s1, const dchar *s2, int nchars) { return ::memcmp(s1, s2, nchars); }
-    static int isDigit(dchar c) { return '0' <= c && c <= '9'; }
-#ifndef GCC_SAFE_DMD
-    static int isAlpha(dchar c) { return isalpha(c); }
-    static int isUpper(dchar c) { return isupper(c); }
-    static int isLower(dchar c) { return islower(c); }
-    static int isLocaleUpper(dchar c) { return isupper(c); }
-    static int isLocaleLower(dchar c) { return islower(c); }
-    static int toLower(dchar c) { return isupper(c) ? tolower(c) : c; }
-    static int toLower(dchar *p) { return toLower(*p); }
-    static int toUpper(dchar c) { return islower(c) ? toupper(c) : c; }
-    static dchar *dup(dchar *p) { return ::strdup(p); }	// BUG: out of memory?
-#endif
-    static dchar *chr(dchar *p, int c) { return strchr(p, c); }
-    static dchar *rchr(dchar *p, int c) { return strrchr(p, c); }
-    static dchar *memchr(dchar *p, int c, int count)
-	{ return (dchar *)::memchr(p, c, count); }
-    static dchar *cpy(dchar *s1, dchar *s2) { return strcpy(s1, s2); }
-    static dchar *str(dchar *s1, dchar *s2) { return strstr(s1, s2); }
-    static hash_t calcHash(const dchar *str, size_t len);
-
-    // Case insensitive versions
-#ifdef __GNUC__
-    static int icmp(dchar *s1, dchar *s2) { return strcasecmp(s1, s2); }
-#else
-    static int icmp(dchar *s1, dchar *s2) { return stricmp(s1, s2); }
-#endif
-    static int memicmp(const dchar *s1, const dchar *s2, int nchars) { return ::memicmp(s1, s2, nchars); }
-    static hash_t icalcHash(const dchar *str, size_t len);
-};
-
-#endif
-#endif
-
--- a/dmd2/declaration.c	Mon Jun 01 01:28:18 2009 +0200
+++ b/dmd2/declaration.c	Mon Jun 01 19:02:20 2009 +0100
@@ -1,1660 +1,1716 @@
-
-// 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 "init.h"
-#include "declaration.h"
-#include "attrib.h"
-#include "mtype.h"
-#include "template.h"
-#include "scope.h"
-#include "aggregate.h"
-#include "module.h"
-#include "id.h"
-#include "expression.h"
-#include "hdrgen.h"
-
-/********************************* Declaration ****************************/
-
-Declaration::Declaration(Identifier *id)
-    : Dsymbol(id)
-{
-    type = NULL;
-    originalType = NULL;
-    storage_class = STCundefined;
-    protection = PROTundefined;
-    linkage = LINKdefault;
-}
-
-void Declaration::semantic(Scope *sc)
-{
-}
-
-const char *Declaration::kind()
-{
-    return "declaration";
-}
-
-unsigned Declaration::size(Loc loc)
-{
-    assert(type);
-    return type->size();
-}
-
-int Declaration::isStaticConstructor()
-{
-    return FALSE;
-}
-
-int Declaration::isStaticDestructor()
-{
-    return FALSE;
-}
-
-int Declaration::isDelete()
-{
-    return FALSE;
-}
-
-int Declaration::isDataseg()
-{
-    return FALSE;
-}
-
-int Declaration::isCodeseg()
-{
-    return FALSE;
-}
-
-enum PROT Declaration::prot()
-{
-    return protection;
-}
-
-/*************************************
- * Check to see if declaration can be modified in this context (sc).
- * Issue error if not.
- */
-
-#if DMDV2
-void Declaration::checkModify(Loc loc, Scope *sc, Type *t)
-{
-    if (sc->incontract && isParameter())
-	error(loc, "cannot modify parameter '%s' in contract", toChars());
-
-    if (isCtorinit())
-    {	// It's only modifiable if inside the right constructor
-	Dsymbol *s = sc->func;
-	while (1)
-	{
-	    FuncDeclaration *fd = NULL;
-	    if (s)
-		fd = s->isFuncDeclaration();
-	    if (fd &&
-		((fd->isCtorDeclaration() && storage_class & STCfield) ||
-		 (fd->isStaticCtorDeclaration() && !(storage_class & STCfield))) &&
-		fd->toParent() == toParent()
-	       )
-	    {
-		VarDeclaration *v = isVarDeclaration();
-		assert(v);
-		v->ctorinit = 1;
-		//printf("setting ctorinit\n");
-	    }
-	    else
-	    {
-		if (s)
-		{   s = s->toParent2();
-		    continue;
-		}
-		else
-		{
-		    const char *p = isStatic() ? "static " : "";
-		    error(loc, "can only initialize %sconst %s inside %sconstructor",
-			p, toChars(), p);
-		}
-	    }
-	    break;
-	}
-    }
-    else
-    {
-	VarDeclaration *v = isVarDeclaration();
-	if (v && v->canassign == 0)
-	{
-	    const char *p = NULL;
-	    if (isConst())
-		p = "const";
-	    else if (isInvariant())
-		p = "invariant";
-	    else if (storage_class & STCmanifest)
-		p = "manifest constant";
-	    else if (!t->isAssignable())
-		p = "struct with immutable members";
-	    if (p)
-	    {	error(loc, "cannot modify %s", p);
-		halt();
-	    }
-	}
-    }
-}
-#endif
-
-
-/********************************* TupleDeclaration ****************************/
-
-TupleDeclaration::TupleDeclaration(Loc loc, Identifier *id, Objects *objects)
-    : Declaration(id)
-{
-    this->type = NULL;
-    this->objects = objects;
-    this->isexp = 0;
-    this->tupletype = NULL;
-}
-
-Dsymbol *TupleDeclaration::syntaxCopy(Dsymbol *s)
-{
-    assert(0);
-    return NULL;
-}
-
-const char *TupleDeclaration::kind()
-{
-    return "tuple";
-}
-
-Type *TupleDeclaration::getType()
-{
-    /* If this tuple represents a type, return that type
-     */
-
-    //printf("TupleDeclaration::getType() %s\n", toChars());
-    if (isexp)
-	return NULL;
-    if (!tupletype)
-    {
-	/* It's only a type tuple if all the Object's are types
-	 */
-	for (size_t i = 0; i < objects->dim; i++)
-	{   Object *o = (Object *)objects->data[i];
-
-	    if (o->dyncast() != DYNCAST_TYPE)
-	    {
-		//printf("\tnot[%d], %p, %d\n", i, o, o->dyncast());
-		return NULL;
-	    }
-	}
-
-	/* We know it's a type tuple, so build the TypeTuple
-	 */
-	Arguments *args = new Arguments();
-	args->setDim(objects->dim);
-	OutBuffer buf;
-	for (size_t i = 0; i < objects->dim; i++)
-	{   Type *t = (Type *)objects->data[i];
-
-	    //printf("type = %s\n", t->toChars());
-#if 0
-	    buf.printf("_%s_%d", ident->toChars(), i);
-	    char *name = (char *)buf.extractData();
-	    Identifier *id = new Identifier(name, TOKidentifier);
-	    Argument *arg = new Argument(STCin, t, id, NULL);
-#else
-	    Argument *arg = new Argument(0, t, NULL, NULL);
-#endif
-	    args->data[i] = (void *)arg;
-	}
-
-	tupletype = new TypeTuple(args);
-    }
-
-    return tupletype;
-}
-
-int TupleDeclaration::needThis()
-{
-    //printf("TupleDeclaration::needThis(%s)\n", toChars());
-    for (size_t i = 0; i < objects->dim; i++)
-    {   Object *o = (Object *)objects->data[i];
-	if (o->dyncast() == DYNCAST_EXPRESSION)
-	{   Expression *e = (Expression *)o;
-	    if (e->op == TOKdsymbol)
-	    {	DsymbolExp *ve = (DsymbolExp *)e;
-		Declaration *d = ve->s->isDeclaration();
-		if (d && d->needThis())
-		{
-		    return 1;
-		}
-	    }
-	}
-    }
-    return 0;
-}
-
-/********************************* TypedefDeclaration ****************************/
-
-TypedefDeclaration::TypedefDeclaration(Loc loc, Identifier *id, Type *basetype, Initializer *init)
-    : Declaration(id)
-{
-    this->type = new TypeTypedef(this);
-    this->basetype = basetype->toBasetype();
-    this->init = init;
-#ifdef _DH
-    this->htype = NULL;
-    this->hbasetype = NULL;
-#endif
-    this->sem = 0;
-    this->inuse = 0;
-    this->loc = loc;
-    this->sinit = NULL;
-}
-
-Dsymbol *TypedefDeclaration::syntaxCopy(Dsymbol *s)
-{
-    Type *basetype = this->basetype->syntaxCopy();
-
-    Initializer *init = NULL;
-    if (this->init)
-	init = this->init->syntaxCopy();
-
-    assert(!s);
-    TypedefDeclaration *st;
-    st = new TypedefDeclaration(loc, ident, basetype, init);
-#ifdef _DH
-    // Syntax copy for header file
-    if (!htype)      // Don't overwrite original
-    {	if (type)    // Make copy for both old and new instances
-	{   htype = type->syntaxCopy();
-	    st->htype = type->syntaxCopy();
-	}
-    }
-    else            // Make copy of original for new instance
-        st->htype = htype->syntaxCopy();
-    if (!hbasetype)
-    {	if (basetype)
-	{   hbasetype = basetype->syntaxCopy();
-	    st->hbasetype = basetype->syntaxCopy();
-	}
-    }
-    else
-        st->hbasetype = hbasetype->syntaxCopy();
-#endif
-    return st;
-}
-
-void TypedefDeclaration::semantic(Scope *sc)
-{
-    //printf("TypedefDeclaration::semantic(%s) sem = %d\n", toChars(), sem);
-    if (sem == 0)
-    {	sem = 1;
-	basetype = basetype->semantic(loc, sc);
-	sem = 2;
-	type = type->semantic(loc, sc);
-	if (sc->parent->isFuncDeclaration() && init)
-	    semantic2(sc);
-	storage_class |= sc->stc & STCdeprecated;
-    }
-    else if (sem == 1)
-    {
-	error("circular definition");
-    }
-}
-
-void TypedefDeclaration::semantic2(Scope *sc)
-{
-    //printf("TypedefDeclaration::semantic2(%s) sem = %d\n", toChars(), sem);
-    if (sem == 2)
-    {	sem = 3;
-	if (init)
-	{
-	    init = init->semantic(sc, basetype);
-
-	    ExpInitializer *ie = init->isExpInitializer();
-	    if (ie)
-	    {
-		if (ie->exp->type == basetype)
-		    ie->exp->type = type;
-	    }
-	}
-    }
-}
-
-const char *TypedefDeclaration::kind()
-{
-    return "typedef";
-}
-
-Type *TypedefDeclaration::getType()
-{
-    return type;
-}
-
-void TypedefDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{
-    buf->writestring("typedef ");
-    basetype->toCBuffer(buf, ident, hgs);
-    if (init)
-    {
-	buf->writestring(" = ");
-	init->toCBuffer(buf, hgs);
-    }
-    buf->writeByte(';');
-    buf->writenl();
-}
-
-/********************************* AliasDeclaration ****************************/
-
-AliasDeclaration::AliasDeclaration(Loc loc, Identifier *id, Type *type)
-    : Declaration(id)
-{
-    //printf("AliasDeclaration(id = '%s', type = %p)\n", id->toChars(), type);
-    //printf("type = '%s'\n", type->toChars());
-    this->loc = loc;
-    this->type = type;
-    this->aliassym = NULL;
-#ifdef _DH
-    this->htype = NULL;
-    this->haliassym = NULL;
-#endif
-    this->overnext = NULL;
-    this->inSemantic = 0;
-    assert(type);
-}
-
-AliasDeclaration::AliasDeclaration(Loc loc, Identifier *id, Dsymbol *s)
-    : Declaration(id)
-{
-    //printf("AliasDeclaration(id = '%s', s = %p)\n", id->toChars(), s);
-    assert(s != this);
-    this->loc = loc;
-    this->type = NULL;
-    this->aliassym = s;
-#ifdef _DH
-    this->htype = NULL;
-    this->haliassym = NULL;
-#endif
-    this->overnext = NULL;
-    this->inSemantic = 0;
-    assert(s);
-}
-
-Dsymbol *AliasDeclaration::syntaxCopy(Dsymbol *s)
-{
-    //printf("AliasDeclaration::syntaxCopy()\n");
-    assert(!s);
-    AliasDeclaration *sa;
-    if (type)
-	sa = new AliasDeclaration(loc, ident, type->syntaxCopy());
-    else
-	sa = new AliasDeclaration(loc, ident, aliassym->syntaxCopy(NULL));
-#ifdef _DH
-    // Syntax copy for header file
-    if (!htype)	    // Don't overwrite original
-    {	if (type)	// Make copy for both old and new instances
-	{   htype = type->syntaxCopy();
-	    sa->htype = type->syntaxCopy();
-	}
-    }
-    else			// Make copy of original for new instance
-	sa->htype = htype->syntaxCopy();
-    if (!haliassym)
-    {	if (aliassym)
-	{   haliassym = aliassym->syntaxCopy(s);
-	    sa->haliassym = aliassym->syntaxCopy(s);
-	}
-    }
-    else
-	sa->haliassym = haliassym->syntaxCopy(s);
-#endif
-    return sa;
-}
-
-void AliasDeclaration::semantic(Scope *sc)
-{
-    //printf("AliasDeclaration::semantic() %s\n", toChars());
-    if (aliassym)
-    {
-	if (aliassym->isTemplateInstance())
-	    aliassym->semantic(sc);
-	return;
-    }
-    this->inSemantic = 1;
-
-    if (storage_class & STCconst)
-	error("cannot be const");
-
-    storage_class |= sc->stc & STCdeprecated;
-
-    // Given:
-    //	alias foo.bar.abc def;
-    // it is not knowable from the syntax whether this is an alias
-    // for a type or an alias for a symbol. It is up to the semantic()
-    // pass to distinguish.
-    // If it is a type, then type is set and getType() will return that
-    // type. If it is a symbol, then aliassym is set and type is NULL -
-    // toAlias() will return aliasssym.
-
-    Dsymbol *s;
-    Type *t;
-    Expression *e;
-
-    /* This section is needed because resolve() will:
-     *   const x = 3;
-     *   alias x y;
-     * try to alias y to 3.
-     */
-    s = type->toDsymbol(sc);
-    if (s && ((s->getType() && type->equals(s->getType())) || s->isEnumMember()))
-	goto L2;			// it's a symbolic alias
-
-    //printf("alias type is %s\n", type->toChars());
-    type->resolve(loc, sc, &e, &t, &s);
-    if (s)
-    {
-	goto L2;
-    }
-    else if (e)
-    {
-	// Try to convert Expression to Dsymbol
-	s = getDsymbol(e);
-	if (s)
-	    goto L2;
-
-	error("cannot alias an expression %s", e->toChars());
-	t = e->type;
-    }
-    else if (t)
-	type = t;
-    if (overnext)
-	ScopeDsymbol::multiplyDefined(0, this, overnext);
-    this->inSemantic = 0;
-    return;
-
-  L2:
-    //printf("alias is a symbol %s %s\n", s->kind(), s->toChars());
-    type = NULL;
-    VarDeclaration *v = s->isVarDeclaration();
-    if (v && v->linkage == LINKdefault)
-    {
-	error("forward reference of %s", v->toChars());
-	s = NULL;
-    }
-    else
-    {
-	FuncDeclaration *f = s->toAlias()->isFuncDeclaration();
-	if (f)
-	{
-	    if (overnext)
-	    {
-		FuncAliasDeclaration *fa = new FuncAliasDeclaration(f);
-		if (!fa->overloadInsert(overnext))
-		    ScopeDsymbol::multiplyDefined(0, f, overnext);
-		overnext = NULL;
-		s = fa;
-		s->parent = sc->parent;
-	    }
-	}
-	if (overnext)
-	    ScopeDsymbol::multiplyDefined(0, s, overnext);
-	if (s == this)
-	{
-	    assert(global.errors);
-	    s = NULL;
-	}
-    }
-    aliassym = s;
-    this->inSemantic = 0;
-}
-
-int AliasDeclaration::overloadInsert(Dsymbol *s)
-{
-    /* Don't know yet what the aliased symbol is, so assume it can
-     * be overloaded and check later for correctness.
-     */
-
-    //printf("AliasDeclaration::overloadInsert('%s')\n", s->toChars());
-    if (overnext == NULL)
-    {	overnext = s;
-	return TRUE;
-    }
-    else
-    {
-	return overnext->overloadInsert(s);
-    }
-}
-
-const char *AliasDeclaration::kind()
-{
-    return "alias";
-}
-
-Type *AliasDeclaration::getType()
-{
-    return type;
-}
-
-Dsymbol *AliasDeclaration::toAlias()
-{
-    //printf("AliasDeclaration::toAlias('%s', this = %p, aliassym = %p, kind = '%s')\n", toChars(), this, aliassym, aliassym ? aliassym->kind() : "");
-    assert(this != aliassym);
-    //static int count; if (++count == 10) *(char*)0=0;
-    if (inSemantic)
-    {	error("recursive alias declaration");
-//	return this;
-    }
-    Dsymbol *s = aliassym ? aliassym->toAlias() : this;
-    return s;
-}
-
-void AliasDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{
-    buf->writestring("alias ");
-#if 0 && _DH
-    if (hgs->hdrgen)
-    {
-	if (haliassym)
-	{
-	    haliassym->toCBuffer(buf, hgs);
-	    buf->writeByte(' ');
-	    buf->writestring(ident->toChars());
-	}
-	else
-	    htype->toCBuffer(buf, ident, hgs);
-    }
-    else
-#endif
-    {
-	if (aliassym)
-	{
-	    aliassym->toCBuffer(buf, hgs);
-	    buf->writeByte(' ');
-	    buf->writestring(ident->toChars());
-	}
-	else
-	    type->toCBuffer(buf, ident, hgs);
-    }
-    buf->writeByte(';');
-    buf->writenl();
-}
-
-/********************************* VarDeclaration ****************************/
-
-VarDeclaration::VarDeclaration(Loc loc, Type *type, Identifier *id, Initializer *init)
-    : Declaration(id)
-{
-    //printf("VarDeclaration('%s')\n", id->toChars());
-#ifdef DEBUG
-    if (!type && !init)
-    {	printf("VarDeclaration('%s')\n", id->toChars());
-	//*(char*)0=0;
-    }
-#endif
-    assert(type || init);
-    this->type = type;
-    this->init = init;
-#ifdef _DH
-    this->htype = NULL;
-    this->hinit = NULL;
-#endif
-    this->loc = loc;
-    offset = 0;
-    noauto = 0;
-    inuse = 0;
-    ctorinit = 0;
-    aliassym = NULL;
-    onstack = 0;
-    canassign = 0;
-    value = NULL;
-    scope = NULL;
-
-    // LDC
-    anonDecl = NULL;
-    offset2 = 0;
-    nakedUse = false;
-}
-
-Dsymbol *VarDeclaration::syntaxCopy(Dsymbol *s)
-{
-    //printf("VarDeclaration::syntaxCopy(%s)\n", toChars());
-
-    VarDeclaration *sv;
-    if (s)
-    {	sv = (VarDeclaration *)s;
-    }
-    else
-    {
-	Initializer *init = NULL;
-	if (this->init)
-	{   init = this->init->syntaxCopy();
-	    //init->isExpInitializer()->exp->print();
-	    //init->isExpInitializer()->exp->dump(0);
-	}
-
-	sv = new VarDeclaration(loc, type ? type->syntaxCopy() : NULL, ident, init);
-	sv->storage_class = storage_class;
-    }
-#ifdef _DH
-    // Syntax copy for header file
-    if (!htype)      // Don't overwrite original
-    {	if (type)    // Make copy for both old and new instances
-	{   htype = type->syntaxCopy();
-	    sv->htype = type->syntaxCopy();
-	}
-    }
-    else            // Make copy of original for new instance
-        sv->htype = htype->syntaxCopy();
-    if (!hinit)
-    {	if (init)
-	{   hinit = init->syntaxCopy();
-	    sv->hinit = init->syntaxCopy();
-	}
-    }
-    else
-        sv->hinit = hinit->syntaxCopy();
-#endif
-    return sv;
-}
-
-void VarDeclaration::semantic(Scope *sc)
-{
-#if 0
-    printf("VarDeclaration::semantic('%s', parent = '%s')\n", toChars(), sc->parent->toChars());
-    printf(" type = %s\n", type ? type->toChars() : "null");
-    printf(" stc = x%x\n", sc->stc);
-    printf(" storage_class = x%x\n", storage_class);
-    printf("linkage = %d\n", sc->linkage);
-    //if (strcmp(toChars(), "mul") == 0) halt();
-#endif
-
-    storage_class |= sc->stc;
-    if (storage_class & STCextern && init)
-	error("extern symbols cannot have initializers");
-
-    /* If auto type inference, do the inference
-     */
-    int inferred = 0;
-    if (!type)
-    {	inuse++;
-	type = init->inferType(sc);
-	inuse--;
-	inferred = 1;
-
-	/* This is a kludge to support the existing syntax for RAII
-	 * declarations.
-	 */
-	storage_class &= ~STCauto;
-	originalType = type;
-    }
-    else
-    {	if (!originalType)
-	    originalType = type;
-	type = type->semantic(loc, sc);
-    }
-    //printf(" semantic type = %s\n", type ? type->toChars() : "null");
-
-    type->checkDeprecated(loc, sc);
-    linkage = sc->linkage;
-    this->parent = sc->parent;
-    //printf("this = %p, parent = %p, '%s'\n", this, parent, parent->toChars());
-    protection = sc->protection;
-    //printf("sc->stc = %x\n", sc->stc);
-    //printf("storage_class = x%x\n", storage_class);
-
-    Dsymbol *parent = toParent();
-    FuncDeclaration *fd = parent->isFuncDeclaration();
-
-    Type *tb = type->toBasetype();
-    if (tb->ty == Tvoid && !(storage_class & STClazy))
-    {	error("voids have no value");
-	type = Type::terror;
-	tb = type;
-    }
-    if (tb->ty == Tfunction)
-    {	error("cannot be declared to be a function");
-	type = Type::terror;
-	tb = type;
-    }
-    if (tb->ty == Tstruct)
-    {	TypeStruct *ts = (TypeStruct *)tb;
-
-	if (!ts->sym->members)
-	{
-	    error("no definition of struct %s", ts->toChars());
-	}
-    }
-
-    if (tb->ty == Ttuple)
-    {   /* Instead, declare variables for each of the tuple elements
-	 * and add those.
-	 */
-	TypeTuple *tt = (TypeTuple *)tb;
-	size_t nelems = Argument::dim(tt->arguments);
-	Objects *exps = new Objects();
-	exps->setDim(nelems);
-	Expression *ie = init ? init->toExpression() : NULL;
-
-	for (size_t i = 0; i < nelems; i++)
-	{   Argument *arg = Argument::getNth(tt->arguments, i);
-
-	    OutBuffer buf;
-        buf.printf("_%s_field_%"PRIuSIZE, ident->toChars(), i);
-	    buf.writeByte(0);
-	    char *name = (char *)buf.extractData();
-	    Identifier *id = new Identifier(name, TOKidentifier);
-
-	    Expression *einit = ie;
-	    if (ie && ie->op == TOKtuple)
-	    {	einit = (Expression *)((TupleExp *)ie)->exps->data[i];
-	    }
-	    Initializer *ti = init;
-	    if (einit)
-	    {	ti = new ExpInitializer(einit->loc, einit);
-	    }
-
-	    VarDeclaration *v = new VarDeclaration(loc, arg->type, id, ti);
-	    //printf("declaring field %s of type %s\n", v->toChars(), v->type->toChars());
-	    v->semantic(sc);
-
-	    if (sc->scopesym)
-	    {	//printf("adding %s to %s\n", v->toChars(), sc->scopesym->toChars());
-		if (sc->scopesym->members)
-		    sc->scopesym->members->push(v);
-	    }
-
-	    Expression *e = new DsymbolExp(loc, v);
-	    exps->data[i] = e;
-	}
-	TupleDeclaration *v2 = new TupleDeclaration(loc, ident, exps);
-	v2->isexp = 1;
-	aliassym = v2;
-	return;
-    }
-
-Lagain:
-    if (storage_class & STCinvariant)
-    {
-	type = type->invariantOf();
-    }
-    else if (storage_class & (STCconst | STCin))
-    {
-	if (!type->isInvariant())
-	    type = type->constOf();
-    }
-    else if (type->isConst())
-	storage_class |= STCconst;
-    else if (type->isInvariant())
-	storage_class |= STCinvariant;
-
-    if (isSynchronized())
-    {
-	error("variable %s cannot be synchronized", toChars());
-    }
-    else if (isOverride())
-    {
-	error("override cannot be applied to variable");
-    }
-    else if (isAbstract())
-    {
-	error("abstract cannot be applied to variable");
-    }
-    else if (storage_class & STCfinal)
-    {
-	error("final cannot be applied to variable");
-    }
-
-    if (storage_class & (STCstatic | STCextern | STCmanifest | STCtemplateparameter | STCtls))
-    {
-    }
-    else
-    {
-	AggregateDeclaration *aad = sc->anonAgg;
-	if (!aad)
-	    aad = parent->isAggregateDeclaration();
-	if (aad)
-	{   assert(!(storage_class & (STCextern | STCstatic | STCtls)));
-
-	    if (storage_class & (STCconst | STCinvariant) && init)
-	    {
-		if (!type->toBasetype()->isTypeBasic())
-		    storage_class |= STCstatic;
-	    }
-	    else
-		aad->addField(sc, this);
-	}
-
-	InterfaceDeclaration *id = parent->isInterfaceDeclaration();
-	if (id)
-	{
-	    error("field not allowed in interface");
-	}
-
-	/* Templates cannot add fields to aggregates
-	 */
-	TemplateInstance *ti = parent->isTemplateInstance();
-	if (ti)
-	{
-	    // Take care of nested templates
-	    while (1)
-	    {
-		TemplateInstance *ti2 = ti->tempdecl->parent->isTemplateInstance();
-		if (!ti2)
-		    break;
-		ti = ti2;
-	    }
-
-	    // If it's a member template
-	    AggregateDeclaration *ad = ti->tempdecl->isMember();
-	    if (ad && storage_class != STCundefined)
-	    {
-		error("cannot use template to add field to aggregate '%s'", ad->toChars());
-	    }
-	}
-    }
-
-    if ((storage_class & (STCref | STCparameter | STCforeach)) == STCref)
-	error("only parameters or foreach declarations can be ref");
-
-    if (type->isauto() && !noauto)
-    {
-	if (storage_class & (STCfield | STCout | STCref | STCstatic | STCmanifest | STCtls) || !fd)
-	{
-	    error("globals, statics, fields, manifest constants, ref and out parameters cannot be auto");
-	}
-
-	if (!(storage_class & (STCauto | STCscope)))
-	{
-	    if (!(storage_class & STCparameter) && ident != Id::withSym)
-		error("reference to scope class must be scope");
-	}
-    }
-
-    if ((isConst() || isInvariant()) && !init && !fd)
-    {	// Initialize by constructor only
-	storage_class |= STCctorinit;
-    }
-
-    if (init)
-	storage_class |= STCinit;     // remember we had an explicit initializer
-    else if (storage_class & STCmanifest)
-	error("manifest constants must have initializers");
-
-    enum TOK op = TOKconstruct;
-    if (!init && !sc->inunion && !isStatic() && fd &&
-	(!(storage_class & (STCfield | STCin | STCforeach | STCparameter)) || (storage_class & STCout)) &&
-	type->size() != 0)
-    {
-	// Provide a default initializer
-	//printf("Providing default initializer for '%s'\n", toChars());
-	if (type->ty == Tstruct &&
-	    ((TypeStruct *)type)->sym->zeroInit == 1)
-	{   /* If a struct is all zeros, as a special case
-	     * set it's initializer to the integer 0.
-	     * In AssignExp::toElem(), we check for this and issue
-	     * a memset() to initialize the struct.
-	     * Must do same check in interpreter.
-	     */
-	    Expression *e = new IntegerExp(loc, 0, Type::tint32);
-	    Expression *e1;
-	    e1 = new VarExp(loc, this);
-	    e = new AssignExp(loc, e1, e);
-	    e->type = e1->type;		// don't type check this, it would fail
-	    init = new ExpInitializer(loc, e);
-	    return;
-	}
-	else if (type->ty == Ttypedef)
-	{   TypeTypedef *td = (TypeTypedef *)type;
-	    if (td->sym->init)
-	    {	init = td->sym->init;
-		ExpInitializer *ie = init->isExpInitializer();
-		if (ie)
-		    // Make copy so we can modify it
-		    init = new ExpInitializer(ie->loc, ie->exp);
-	    }
-	    else
-		init = getExpInitializer();
-	}
-	else
-	{
-	    init = getExpInitializer();
-	}
-	// Default initializer is always a blit
-	op = TOKblit;
-    }
-
-    if (init)
-    {
-	sc = sc->push();
-	sc->stc &= ~(STCconst | STCinvariant | STCpure | STCnothrow | STCref | STCshared);
-
-	ArrayInitializer *ai = init->isArrayInitializer();
-	if (ai && tb->ty == Taarray)
-	{
-	    init = ai->toAssocArrayInitializer();
-	}
-
-	StructInitializer *si = init->isStructInitializer();
-	ExpInitializer *ei = init->isExpInitializer();
-
-	// See if initializer is a NewExp that can be allocated on the stack
-	if (ei && isScope() && ei->exp->op == TOKnew)
-	{   NewExp *ne = (NewExp *)ei->exp;
-	    if (!(ne->newargs && ne->newargs->dim))
-	    {	ne->onstack = 1;
-		onstack = 1;
-		if (type->isBaseOf(ne->newtype->semantic(loc, sc), NULL))
-		    onstack = 2;
-	    }
-	}
-
-	// If inside function, there is no semantic3() call
-	if (sc->func)
-	{
-	    // If local variable, use AssignExp to handle all the various
-	    // possibilities.
-	    if (fd && !isStatic() && !(storage_class & STCmanifest) &&
-		!init->isVoidInitializer())
-	    {
-		//printf("fd = '%s', var = '%s'\n", fd->toChars(), toChars());
-		if (!ei)
-		{
-		    Expression *e = init->toExpression();
-		    if (!e)
-		    {
-			init = init->semantic(sc, type);
-			e = init->toExpression();
-			if (!e)
-			{   error("is not a static and cannot have static initializer");
-			    return;
-			}
-		    }
-		    ei = new ExpInitializer(init->loc, e);
-		    init = ei;
-		}
-
-		Expression *e1 = new VarExp(loc, this);
-
-		Type *t = type->toBasetype();
-		if (t->ty == Tsarray)
-		{
-		    ei->exp = ei->exp->semantic(sc);
-		    if (!ei->exp->implicitConvTo(type))
-		    {
-			int dim = ((TypeSArray *)t)->dim->toInteger();
-			// If multidimensional static array, treat as one large array
-			while (1)
-			{
-			    t = t->nextOf()->toBasetype();
-			    if (t->ty != Tsarray)
-				break;
-			    dim *= ((TypeSArray *)t)->dim->toInteger();
-			    e1->type = new TypeSArray(t->nextOf(), new IntegerExp(0, dim, Type::tindex));
-			}
-		    }
-		    e1 = new SliceExp(loc, e1, NULL, NULL);
-		}
-		else if (t->ty == Tstruct)
-		{
-		    ei->exp = ei->exp->semantic(sc);
-
-		    /* Look to see if initializer is a call to the constructor
-		     */
-		    StructDeclaration *sd = ((TypeStruct *)t)->sym;
-		    if (sd->ctor &&		// there are constructors
-			ei->exp->type->ty == Tstruct &&	// rvalue is the same struct
-			((TypeStruct *)ei->exp->type)->sym == sd &&
-			ei->exp->op == TOKstar)
-		    {
-			/* Look for form of constructor call which is:
-			 *    *__ctmp.ctor(arguments...)
-			 */
-			PtrExp *pe = (PtrExp *)ei->exp;
-			if (pe->e1->op == TOKcall)
-			{   CallExp *ce = (CallExp *)pe->e1;
-			    if (ce->e1->op == TOKdotvar)
-			    {	DotVarExp *dve = (DotVarExp *)ce->e1;
-				if (dve->var->isCtorDeclaration())
-				{   /* It's a constructor call, currently constructing
-				     * a temporary __ctmp.
-				     */
-				    /* Before calling the constructor, initialize
-				     * variable with a bit copy of the default
-				     * initializer
-				     */
-				    Expression *e = new AssignExp(loc, new VarExp(loc, this), t->defaultInit(loc));
-				    e->op = TOKblit;
-				    e->type = t;
-				    ei->exp = new CommaExp(loc, e, ei->exp);
-
-				    /* Replace __ctmp being constructed with e1
-				     */
-				    dve->e1 = e1;
-				    return;
-				}
-			    }
-			}
-		    }
-
-		    if (!ei->exp->implicitConvTo(type))
-		    {	Type *ti = ei->exp->type->toBasetype();
-			// Don't cast away invariant or mutability in initializer
-			if (!(ti->ty == Tstruct && t->toDsymbol(sc) == ti->toDsymbol(sc)))
-			    ei->exp = new CastExp(loc, ei->exp, type);
-		    }
-		}
-		ei->exp = new AssignExp(loc, e1, ei->exp);
-		ei->exp->op = op;
-		canassign++;
-		ei->exp = ei->exp->semantic(sc);
-		canassign--;
-		ei->exp->optimize(WANTvalue);
-	    }
-	    else
-	    {
-		init = init->semantic(sc, type);
-	    }
-	}
-	else if (storage_class & (STCconst | STCinvariant | STCmanifest) ||
-		 type->isConst() || type->isInvariant())
-	{
-	    /* Because we may need the results of a const declaration in a
-	     * subsequent type, such as an array dimension, before semantic2()
-	     * gets ordinarily run, try to run semantic2() now.
-	     * Ignore failure.
-	     */
-
-	    if (!global.errors && !inferred)
-	    {
-		unsigned errors = global.errors;
-		global.gag++;
-		//printf("+gag\n");
-		Expression *e;
-		Initializer *i2 = init;
-		inuse++;
-		if (ei)
-		{
-		    e = ei->exp->syntaxCopy();
-		    e = e->semantic(sc);
-		    e = e->implicitCastTo(sc, type);
-		}
-		else if (si || ai)
-		{   i2 = init->syntaxCopy();
-		    i2 = i2->semantic(sc, type);
-		}
-		inuse--;
-		global.gag--;
-		//printf("-gag\n");
-		if (errors != global.errors)	// if errors happened
-		{
-		    if (global.gag == 0)
-			global.errors = errors;	// act as if nothing happened
-
-		    /* Save scope for later use, to try again
-		     */
-		    scope = new Scope(*sc);
-		    scope->setNoFree();
-		}
-		else if (ei)
-		{
-		    if (isDataseg())
-			/* static const/invariant does CTFE
-			 */
-			e = e->optimize(WANTvalue | WANTinterpret);
-		    else
-			e = e->optimize(WANTvalue);
-		    if (e->op == TOKint64 || e->op == TOKstring)
-		    {
-			ei->exp = e;		// no errors, keep result
-		    }
-		    else
-		    {
-			/* Save scope for later use, to try again
-			 */
-			scope = new Scope(*sc);
-			scope->setNoFree();
-		    }
-		}
-		else
-		    init = i2;		// no errors, keep result
-	    }
-	}
-	sc = sc->pop();
-    }
-}
-
-void VarDeclaration::semantic2(Scope *sc)
-{
-    //printf("VarDeclaration::semantic2('%s')\n", toChars());
-    if (init && !toParent()->isFuncDeclaration())
-    {	inuse++;
-#if 0
-	ExpInitializer *ei = init->isExpInitializer();
-	if (ei)
-	{
-	    ei->exp->dump(0);
-	    printf("type = %p\n", ei->exp->type);
-	}
-#endif
-	init = init->semantic(sc, type);
-	inuse--;
-    }
-}
-
-const char *VarDeclaration::kind()
-{
-    return "variable";
-}
-
-Dsymbol *VarDeclaration::toAlias()
-{
-    //printf("VarDeclaration::toAlias('%s', this = %p, aliassym = %p)\n", toChars(), this, aliassym);
-    assert(this != aliassym);
-    Dsymbol *s = aliassym ? aliassym->toAlias() : this;
-    return s;
-}
-
-void VarDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{
-    if (storage_class & STCconst)
-	buf->writestring("const ");
-    if (storage_class & STCstatic)
-	buf->writestring("static ");
-    if (storage_class & STCauto)
-	buf->writestring("auto ");
-#if DMDV2
-    if (storage_class & STCmanifest)
-	buf->writestring("manifest ");
-    if (storage_class & STCinvariant)
-	buf->writestring("invariant ");
-    if (storage_class & STCtls)
-	buf->writestring("__thread ");
-#endif
-
-    if (type)
-	type->toCBuffer(buf, ident, hgs);
-    else
-	buf->writestring(ident->toChars());
-    if (init)
-    {	buf->writestring(" = ");
-	ExpInitializer *ie = init->isExpInitializer();
-	if (ie && (ie->exp->op == TOKconstruct || ie->exp->op == TOKblit))
-	    ((AssignExp *)ie->exp)->e2->toCBuffer(buf, hgs);
-	else
-	    init->toCBuffer(buf, hgs);
-    }
-    buf->writeByte(';');
-    buf->writenl();
-}
-
-int VarDeclaration::needThis()
-{
-    //printf("VarDeclaration::needThis(%s, x%x)\n", toChars(), storage_class);
-    return storage_class & STCfield;
-}
-
-int VarDeclaration::isImportedSymbol()
-{
-    if (protection == PROTexport && !init &&
-	(storage_class & STCstatic || parent->isModule()))
-	return TRUE;
-    return FALSE;
-}
-
-void VarDeclaration::checkCtorConstInit()
-{
-#if 0 /* doesn't work if more than one static ctor */
-    if (ctorinit == 0 && isCtorinit() && !(storage_class & STCfield))
-	error("missing initializer in static constructor for const variable");
-#endif
-}
-
-/************************************
- * Check to see if this variable is actually in an enclosing function
- * rather than the current one.
- */
-
-void VarDeclaration::checkNestedReference(Scope *sc, Loc loc)
-{
-    if (parent && !isDataseg() && parent != sc->parent &&
-	!(storage_class & STCmanifest))
-    {
-	// The function that this variable is in
-	FuncDeclaration *fdv = toParent()->isFuncDeclaration();
-	// The current function
-	FuncDeclaration *fdthis = sc->parent->isFuncDeclaration();
-
-	if (fdv && fdthis && fdv != fdthis)
-	{
-	    if (loc.filename)
-		fdthis->getLevel(loc, fdv);
-
-	    for (int i = 0; i < nestedrefs.dim; i++)
-	    {	FuncDeclaration *f = (FuncDeclaration *)nestedrefs.data[i];
-		if (f == fdthis)
-		    goto L1;
-	    }
-        fdv->nestedVars.insert(this);
-	    nestedrefs.push(fdthis);
-	  L1: ;
-
-
-	    for (int i = 0; i < fdv->closureVars.dim; i++)
-	    {	Dsymbol *s = (Dsymbol *)fdv->closureVars.data[i];
-		if (s == this)
-		    goto L2;
-	    }
-
-	    fdv->closureVars.push(this);
-	  L2: ;
-
-	    //printf("var %s in function %s is nested ref\n", toChars(), fdv->toChars());
-	}
-    }
-}
-
-/****************************
- * Get ExpInitializer for a variable, if there is one.
- */
-
-ExpInitializer *VarDeclaration::getExpInitializer()
-{
-    ExpInitializer *ei;
-
-    if (init)
-	ei = init->isExpInitializer();
-    else
-    {
-	Expression *e = type->defaultInit(loc);
-	if (e)
-	    ei = new ExpInitializer(loc, e);
-	else
-	    ei = NULL;
-    }
-    return ei;
-}
-
-/*******************************************
- * If variable has a constant expression initializer, get it.
- * Otherwise, return NULL.
- */
-
-Expression *VarDeclaration::getConstInitializer()
-{
-    if ((isConst() || isInvariant() || storage_class & STCmanifest) &&
-	storage_class & STCinit)
-    {
-	ExpInitializer *ei = getExpInitializer();
-	if (ei)
-	    return ei->exp;
-    }
-
-    return NULL;
-}
-
-/*************************************
- * Return !=0 if we can take the address of this variable.
- */
-
-int VarDeclaration::canTakeAddressOf()
-{
-#if 0
-    /* Global variables and struct/class fields of the form:
-     *	const int x = 3;
-     * are not stored and hence cannot have their address taken.
-     */
-    if ((isConst() || isInvariant()) &&
-	storage_class & STCinit &&
-	(!(storage_class & (STCstatic | STCextern)) || (storage_class & STCfield)) &&
-	(!parent || toParent()->isModule() || toParent()->isTemplateInstance()) &&
-	type->toBasetype()->isTypeBasic()
-       )
-    {
-	return 0;
-    }
-#else
-    if (storage_class & STCmanifest)
-	return 0;
-#endif
-    return 1;
-}
-
-/*******************************
- * Does symbol go into data segment?
- * Includes extern variables.
- */
-
-int VarDeclaration::isDataseg()
-{
-#if 0
-    printf("VarDeclaration::isDataseg(%p, '%s')\n", this, toChars());
-    printf("%x, %p, %p\n", storage_class & (STCstatic | STCconst), parent->isModule(), parent->isTemplateInstance());
-    printf("parent = '%s'\n", parent->toChars());
-#endif
-    if (storage_class & STCmanifest)
-	return 0;
-    Dsymbol *parent = this->toParent();
-    if (!parent && !(storage_class & STCstatic))
-    {	error("forward referenced");
-	type = Type::terror;
-	return 0;
-    }
-    return canTakeAddressOf() &&
-	(storage_class & (STCstatic | STCextern | STCtls) ||
-	 toParent()->isModule() ||
-	 toParent()->isTemplateInstance());
-}
-
-int VarDeclaration::hasPointers()
-{
-    //printf("VarDeclaration::hasPointers() %s, ty = %d\n", toChars(), type->ty);
-    return (!isDataseg() && type->hasPointers());
-}
-
-/******************************************
- * Return TRUE if variable needs to call the destructor.
- */
-
-int VarDeclaration::needsAutoDtor()
-{
-    //printf("VarDeclaration::needsAutoDtor() %s\n", toChars());
-
-    if (noauto || storage_class & STCnodtor)
-	return FALSE;
-
-    // Destructors for structs and arrays of structs
-    Type *tv = type->toBasetype();
-    while (tv->ty == Tsarray)
-    {   TypeSArray *ta = (TypeSArray *)tv;
-	tv = tv->nextOf()->toBasetype();
-    }
-    if (tv->ty == Tstruct)
-    {   TypeStruct *ts = (TypeStruct *)tv;
-	StructDeclaration *sd = ts->sym;
-	if (sd->dtor)
-	    return TRUE;
-    }
-
-    // Destructors for classes
-    if (storage_class & (STCauto | STCscope))
-    {
-	if (type->isClassHandle())
-	    return TRUE;
-    }
-    return FALSE;
-}
-
-
-/******************************************
- * If a variable has an auto destructor call, return call for it.
- * Otherwise, return NULL.
- */
-
-Expression *VarDeclaration::callAutoDtor(Scope *sc)
-{   Expression *e = NULL;
-
-    //printf("VarDeclaration::callAutoDtor() %s\n", toChars());
-
-    if (noauto || storage_class & STCnodtor)
-	return NULL;
-
-    // Destructors for structs and arrays of structs
-    bool array = false;
-    Type *tv = type->toBasetype();
-    while (tv->ty == Tsarray)
-    {   TypeSArray *ta = (TypeSArray *)tv;
-	array = true;
-	tv = tv->nextOf()->toBasetype();
-    }
-    if (tv->ty == Tstruct)
-    {   TypeStruct *ts = (TypeStruct *)tv;
-	StructDeclaration *sd = ts->sym;
-	if (sd->dtor)
-	{
-	    if (array)
-	    {
-		// Typeinfo.destroy(cast(void*)&v);
-		Expression *ea = new SymOffExp(loc, this, 0, 0);
-		ea = new CastExp(loc, ea, Type::tvoid->pointerTo());
-		Expressions *args = new Expressions();
-		args->push(ea);
-
-		Expression *et = type->getTypeInfo(sc);
-		et = new DotIdExp(loc, et, Id::destroy);
-
-		e = new CallExp(loc, et, args);
-	    }
-	    else
-	    {
-		e = new VarExp(loc, this);
-		e = new DotVarExp(loc, e, sd->dtor, 0);
-		e = new CallExp(loc, e);
-	    }
-	    return e;
-	}
-    }
-
-    // Destructors for classes
-    if (storage_class & (STCauto | STCscope))
-    {
-	for (ClassDeclaration *cd = type->isClassHandle();
-	     cd;
-	     cd = cd->baseClass)
-	{
-	    /* We can do better if there's a way with onstack
-	     * classes to determine if there's no way the monitor
-	     * could be set.
-	     */
-	    //if (cd->isInterfaceDeclaration())
-		//error("interface %s cannot be scope", cd->toChars());
-	    if (1 || onstack || cd->dtors.dim)	// if any destructors
-	    {
-		// delete this;
-		Expression *ec;
-
-		ec = new VarExp(loc, this);
-		e = new DeleteExp(loc, ec);
-		e->type = Type::tvoid;
-		break;
-	    }
-	}
-    }
-    return e;
-}
-
-
-/********************************* ClassInfoDeclaration ****************************/
-
-ClassInfoDeclaration::ClassInfoDeclaration(ClassDeclaration *cd)
-    : VarDeclaration(0, ClassDeclaration::classinfo->type, cd->ident, NULL)
-{
-    this->cd = cd;
-    storage_class = STCstatic;
-}
-
-Dsymbol *ClassInfoDeclaration::syntaxCopy(Dsymbol *s)
-{
-    assert(0);		// should never be produced by syntax
-    return NULL;
-}
-
-void ClassInfoDeclaration::semantic(Scope *sc)
-{
-}
-
-/********************************* ModuleInfoDeclaration ****************************/
-
-ModuleInfoDeclaration::ModuleInfoDeclaration(Module *mod)
-    : VarDeclaration(0, Module::moduleinfo->type, mod->ident, NULL)
-{
-    this->mod = mod;
-    storage_class = STCstatic;
-}
-
-Dsymbol *ModuleInfoDeclaration::syntaxCopy(Dsymbol *s)
-{
-    assert(0);		// should never be produced by syntax
-    return NULL;
-}
-
-void ModuleInfoDeclaration::semantic(Scope *sc)
-{
-}
-
-/********************************* TypeInfoDeclaration ****************************/
-
-TypeInfoDeclaration::TypeInfoDeclaration(Type *tinfo, int internal)
-    : VarDeclaration(0, Type::typeinfo->type, tinfo->getTypeInfoIdent(internal), NULL)
-{
-    this->tinfo = tinfo;
-    storage_class = STCstatic;
-    protection = PROTpublic;
-    linkage = LINKc;
-}
-
-Dsymbol *TypeInfoDeclaration::syntaxCopy(Dsymbol *s)
-{
-    assert(0);		// should never be produced by syntax
-    return NULL;
-}
-
-void TypeInfoDeclaration::semantic(Scope *sc)
-{
-    assert(linkage == LINKc);
-}
-
-/***************************** TypeInfoConstDeclaration **********************/
-
-#if DMDV2
-TypeInfoConstDeclaration::TypeInfoConstDeclaration(Type *tinfo)
-    : TypeInfoDeclaration(tinfo, 0)
-{
-}
-#endif
-
-/***************************** TypeInfoInvariantDeclaration **********************/
-
-#if DMDV2
-TypeInfoInvariantDeclaration::TypeInfoInvariantDeclaration(Type *tinfo)
-    : TypeInfoDeclaration(tinfo, 0)
-{
-}
-#endif
-
-/***************************** TypeInfoStructDeclaration **********************/
-
-TypeInfoStructDeclaration::TypeInfoStructDeclaration(Type *tinfo)
-    : TypeInfoDeclaration(tinfo, 0)
-{
-}
-
-/***************************** TypeInfoClassDeclaration ***********************/
-
-TypeInfoClassDeclaration::TypeInfoClassDeclaration(Type *tinfo)
-    : TypeInfoDeclaration(tinfo, 0)
-{
-}
-
-/***************************** TypeInfoInterfaceDeclaration *******************/
-
-TypeInfoInterfaceDeclaration::TypeInfoInterfaceDeclaration(Type *tinfo)
-    : TypeInfoDeclaration(tinfo, 0)
-{
-}
-
-/***************************** TypeInfoTypedefDeclaration *********************/
-
-TypeInfoTypedefDeclaration::TypeInfoTypedefDeclaration(Type *tinfo)
-    : TypeInfoDeclaration(tinfo, 0)
-{
-}
-
-/***************************** TypeInfoPointerDeclaration *********************/
-
-TypeInfoPointerDeclaration::TypeInfoPointerDeclaration(Type *tinfo)
-    : TypeInfoDeclaration(tinfo, 0)
-{
-}
-
-/***************************** TypeInfoArrayDeclaration ***********************/
-
-TypeInfoArrayDeclaration::TypeInfoArrayDeclaration(Type *tinfo)
-    : TypeInfoDeclaration(tinfo, 0)
-{
-}
-
-/***************************** TypeInfoStaticArrayDeclaration *****************/
-
-TypeInfoStaticArrayDeclaration::TypeInfoStaticArrayDeclaration(Type *tinfo)
-    : TypeInfoDeclaration(tinfo, 0)
-{
-}
-
-/***************************** TypeInfoAssociativeArrayDeclaration ************/
-
-TypeInfoAssociativeArrayDeclaration::TypeInfoAssociativeArrayDeclaration(Type *tinfo)
-    : TypeInfoDeclaration(tinfo, 0)
-{
-}
-
-/***************************** TypeInfoEnumDeclaration ***********************/
-
-TypeInfoEnumDeclaration::TypeInfoEnumDeclaration(Type *tinfo)
-    : TypeInfoDeclaration(tinfo, 0)
-{
-}
-
-/***************************** TypeInfoFunctionDeclaration ********************/
-
-TypeInfoFunctionDeclaration::TypeInfoFunctionDeclaration(Type *tinfo)
-    : TypeInfoDeclaration(tinfo, 0)
-{
-}
-
-/***************************** TypeInfoDelegateDeclaration ********************/
-
-TypeInfoDelegateDeclaration::TypeInfoDelegateDeclaration(Type *tinfo)
-    : TypeInfoDeclaration(tinfo, 0)
-{
-}
-
-/***************************** TypeInfoTupleDeclaration **********************/
-
-TypeInfoTupleDeclaration::TypeInfoTupleDeclaration(Type *tinfo)
-    : TypeInfoDeclaration(tinfo, 0)
-{
-}
-
-/********************************* ThisDeclaration ****************************/
-
-// For the "this" parameter to member functions
-
-ThisDeclaration::ThisDeclaration(Type *t)
-   : VarDeclaration(0, t, Id::This, NULL)
-{
-    noauto = 1;
-}
-
-Dsymbol *ThisDeclaration::syntaxCopy(Dsymbol *s)
-{
-    assert(0);		// should never be produced by syntax
-    return NULL;
-}
-
- 
-/********************** StaticStructInitDeclaration ***************************/ 
- 
-StaticStructInitDeclaration::StaticStructInitDeclaration(Loc loc, StructDeclaration *dsym) 
-    : Declaration(new Identifier("", TOKidentifier)) 
-{ 
-    this->loc = loc; 
-    this->dsym = dsym; 
-    storage_class |= STCconst; 
-} 
+
+// Compiler implementation of the D programming language
+// Copyright (c) 1999-2009 by Digital Mars
+// All Rights Reserved
+// written by Walter Bright
+// http://www.digitalmars.com
+// License for redistribution is by either the Artistic License
+// in artistic.txt, or the GNU General Public License in gnu.txt.
+// See the included readme.txt for details.
+
+#include <stdio.h>
+#include <assert.h>
+
+#include "init.h"
+#include "declaration.h"
+#include "attrib.h"
+#include "mtype.h"
+#include "template.h"
+#include "scope.h"
+#include "aggregate.h"
+#include "module.h"
+#include "id.h"
+#include "expression.h"
+#include "hdrgen.h"
+
+/********************************* Declaration ****************************/
+
+Declaration::Declaration(Identifier *id)
+    : Dsymbol(id)
+{
+    type = NULL;
+    originalType = NULL;
+    storage_class = STCundefined;
+    protection = PROTundefined;
+    linkage = LINKdefault;
+    inuse = 0;
+}
+
+void Declaration::semantic(Scope *sc)
+{
+}
+
+const char *Declaration::kind()
+{
+    return "declaration";
+}
+
+unsigned Declaration::size(Loc loc)
+{
+    assert(type);
+    return type->size();
+}
+
+int Declaration::isStaticConstructor()
+{
+    return FALSE;
+}
+
+int Declaration::isStaticDestructor()
+{
+    return FALSE;
+}
+
+int Declaration::isDelete()
+{
+    return FALSE;
+}
+
+int Declaration::isDataseg()
+{
+    return FALSE;
+}
+
+int Declaration::isThreadlocal()
+{
+    return FALSE;
+}
+
+int Declaration::isCodeseg()
+{
+    return FALSE;
+}
+
+enum PROT Declaration::prot()
+{
+    return protection;
+}
+
+/*************************************
+ * Check to see if declaration can be modified in this context (sc).
+ * Issue error if not.
+ */
+
+#if DMDV2
+void Declaration::checkModify(Loc loc, Scope *sc, Type *t)
+{
+    if (sc->incontract && isParameter())
+	error(loc, "cannot modify parameter '%s' in contract", toChars());
+
+    if (isCtorinit())
+    {	// It's only modifiable if inside the right constructor
+	Dsymbol *s = sc->func;
+	while (1)
+	{
+	    FuncDeclaration *fd = NULL;
+	    if (s)
+		fd = s->isFuncDeclaration();
+	    if (fd &&
+		((fd->isCtorDeclaration() && storage_class & STCfield) ||
+		 (fd->isStaticCtorDeclaration() && !(storage_class & STCfield))) &&
+		fd->toParent() == toParent()
+	       )
+	    {
+		VarDeclaration *v = isVarDeclaration();
+		assert(v);
+		v->ctorinit = 1;
+		//printf("setting ctorinit\n");
+	    }
+	    else
+	    {
+		if (s)
+		{   s = s->toParent2();
+		    continue;
+		}
+		else
+		{
+		    const char *p = isStatic() ? "static " : "";
+		    error(loc, "can only initialize %sconst %s inside %sconstructor",
+			p, toChars(), p);
+		}
+	    }
+	    break;
+	}
+    }
+    else
+    {
+	VarDeclaration *v = isVarDeclaration();
+	if (v && v->canassign == 0)
+	{
+	    const char *p = NULL;
+	    if (isConst())
+		p = "const";
+	    else if (isInvariant())
+		p = "mutable";
+	    else if (storage_class & STCmanifest)
+		p = "enum";
+	    else if (!t->isAssignable())
+		p = "struct with immutable members";
+	    if (p)
+	    {	error(loc, "cannot modify %s", p);
+	    }
+	}
+    }
+}
+#endif
+
+
+/********************************* TupleDeclaration ****************************/
+
+TupleDeclaration::TupleDeclaration(Loc loc, Identifier *id, Objects *objects)
+    : Declaration(id)
+{
+    this->type = NULL;
+    this->objects = objects;
+    this->isexp = 0;
+    this->tupletype = NULL;
+}
+
+Dsymbol *TupleDeclaration::syntaxCopy(Dsymbol *s)
+{
+    assert(0);
+    return NULL;
+}
+
+const char *TupleDeclaration::kind()
+{
+    return "tuple";
+}
+
+Type *TupleDeclaration::getType()
+{
+    /* If this tuple represents a type, return that type
+     */
+
+    //printf("TupleDeclaration::getType() %s\n", toChars());
+    if (isexp)
+	return NULL;
+    if (!tupletype)
+    {
+	/* It's only a type tuple if all the Object's are types
+	 */
+	for (size_t i = 0; i < objects->dim; i++)
+	{   Object *o = (Object *)objects->data[i];
+
+	    if (o->dyncast() != DYNCAST_TYPE)
+	    {
+		//printf("\tnot[%d], %p, %d\n", i, o, o->dyncast());
+		return NULL;
+	    }
+	}
+
+	/* We know it's a type tuple, so build the TypeTuple
+	 */
+	Arguments *args = new Arguments();
+	args->setDim(objects->dim);
+	OutBuffer buf;
+	for (size_t i = 0; i < objects->dim; i++)
+	{   Type *t = (Type *)objects->data[i];
+
+	    //printf("type = %s\n", t->toChars());
+#if 0
+	    buf.printf("_%s_%d", ident->toChars(), i);
+	    char *name = (char *)buf.extractData();
+	    Identifier *id = new Identifier(name, TOKidentifier);
+	    Argument *arg = new Argument(STCin, t, id, NULL);
+#else
+	    Argument *arg = new Argument(0, t, NULL, NULL);
+#endif
+	    args->data[i] = (void *)arg;
+	}
+
+	tupletype = new TypeTuple(args);
+    }
+
+    return tupletype;
+}
+
+int TupleDeclaration::needThis()
+{
+    //printf("TupleDeclaration::needThis(%s)\n", toChars());
+    for (size_t i = 0; i < objects->dim; i++)
+    {   Object *o = (Object *)objects->data[i];
+	if (o->dyncast() == DYNCAST_EXPRESSION)
+	{   Expression *e = (Expression *)o;
+	    if (e->op == TOKdsymbol)
+	    {	DsymbolExp *ve = (DsymbolExp *)e;
+		Declaration *d = ve->s->isDeclaration();
+		if (d && d->needThis())
+		{
+		    return 1;
+		}
+	    }
+	}
+    }
+    return 0;
+}
+
+/********************************* TypedefDeclaration ****************************/
+
+TypedefDeclaration::TypedefDeclaration(Loc loc, Identifier *id, Type *basetype, Initializer *init)
+    : Declaration(id)
+{
+    this->type = new TypeTypedef(this);
+    this->basetype = basetype->toBasetype();
+    this->init = init;
+#ifdef _DH
+    this->htype = NULL;
+    this->hbasetype = NULL;
+#endif
+    this->sem = 0;
+    this->loc = loc;
+#if IN_DMD
+    this->sinit = NULL;
+#endif
+}
+
+Dsymbol *TypedefDeclaration::syntaxCopy(Dsymbol *s)
+{
+    Type *basetype = this->basetype->syntaxCopy();
+
+    Initializer *init = NULL;
+    if (this->init)
+	init = this->init->syntaxCopy();
+
+    assert(!s);
+    TypedefDeclaration *st;
+    st = new TypedefDeclaration(loc, ident, basetype, init);
+#ifdef _DH
+    // Syntax copy for header file
+    if (!htype)      // Don't overwrite original
+    {	if (type)    // Make copy for both old and new instances
+	{   htype = type->syntaxCopy();
+	    st->htype = type->syntaxCopy();
+	}
+    }
+    else            // Make copy of original for new instance
+        st->htype = htype->syntaxCopy();
+    if (!hbasetype)
+    {	if (basetype)
+	{   hbasetype = basetype->syntaxCopy();
+	    st->hbasetype = basetype->syntaxCopy();
+	}
+    }
+    else
+        st->hbasetype = hbasetype->syntaxCopy();
+#endif
+    return st;
+}
+
+void TypedefDeclaration::semantic(Scope *sc)
+{
+    //printf("TypedefDeclaration::semantic(%s) sem = %d\n", toChars(), sem);
+    if (sem == 0)
+    {	sem = 1;
+	basetype = basetype->semantic(loc, sc);
+	sem = 2;
+	type = type->semantic(loc, sc);
+	if (sc->parent->isFuncDeclaration() && init)
+	    semantic2(sc);
+	storage_class |= sc->stc & STCdeprecated;
+    }
+    else if (sem == 1)
+    {
+	error("circular definition");
+    }
+}
+
+void TypedefDeclaration::semantic2(Scope *sc)
+{
+    //printf("TypedefDeclaration::semantic2(%s) sem = %d\n", toChars(), sem);
+    if (sem == 2)
+    {	sem = 3;
+	if (init)
+	{
+	    init = init->semantic(sc, basetype);
+
+	    ExpInitializer *ie = init->isExpInitializer();
+	    if (ie)
+	    {
+		if (ie->exp->type == basetype)
+		    ie->exp->type = type;
+	    }
+	}
+    }
+}
+
+const char *TypedefDeclaration::kind()
+{
+    return "typedef";
+}
+
+Type *TypedefDeclaration::getType()
+{
+    return type;
+}
+
+void TypedefDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    buf->writestring("typedef ");
+    basetype->toCBuffer(buf, ident, hgs);
+    if (init)
+    {
+	buf->writestring(" = ");
+	init->toCBuffer(buf, hgs);
+    }
+    buf->writeByte(';');
+    buf->writenl();
+}
+
+/********************************* AliasDeclaration ****************************/
+
+AliasDeclaration::AliasDeclaration(Loc loc, Identifier *id, Type *type)
+    : Declaration(id)
+{
+    //printf("AliasDeclaration(id = '%s', type = %p)\n", id->toChars(), type);
+    //printf("type = '%s'\n", type->toChars());
+    this->loc = loc;
+    this->type = type;
+    this->aliassym = NULL;
+#ifdef _DH
+    this->htype = NULL;
+    this->haliassym = NULL;
+#endif
+    this->overnext = NULL;
+    this->inSemantic = 0;
+    this->importprot = PROTundefined;
+    assert(type);
+}
+
+AliasDeclaration::AliasDeclaration(Loc loc, Identifier *id, Dsymbol *s)
+    : Declaration(id)
+{
+    //printf("AliasDeclaration(id = '%s', s = %p)\n", id->toChars(), s);
+    assert(s != this);
+    this->loc = loc;
+    this->type = NULL;
+    this->aliassym = s;
+#ifdef _DH
+    this->htype = NULL;
+    this->haliassym = NULL;
+#endif
+    this->overnext = NULL;
+    this->inSemantic = 0;
+    assert(s);
+}
+
+Dsymbol *AliasDeclaration::syntaxCopy(Dsymbol *s)
+{
+    //printf("AliasDeclaration::syntaxCopy()\n");
+    assert(!s);
+    AliasDeclaration *sa;
+    if (type)
+	sa = new AliasDeclaration(loc, ident, type->syntaxCopy());
+    else
+	sa = new AliasDeclaration(loc, ident, aliassym->syntaxCopy(NULL));
+#ifdef _DH
+    // Syntax copy for header file
+    if (!htype)	    // Don't overwrite original
+    {	if (type)	// Make copy for both old and new instances
+	{   htype = type->syntaxCopy();
+	    sa->htype = type->syntaxCopy();
+	}
+    }
+    else			// Make copy of original for new instance
+	sa->htype = htype->syntaxCopy();
+    if (!haliassym)
+    {	if (aliassym)
+	{   haliassym = aliassym->syntaxCopy(s);
+	    sa->haliassym = aliassym->syntaxCopy(s);
+	}
+    }
+    else
+	sa->haliassym = haliassym->syntaxCopy(s);
+#endif
+    return sa;
+}
+
+void AliasDeclaration::semantic(Scope *sc)
+{
+    //printf("AliasDeclaration::semantic() %s\n", toChars());
+    if (aliassym)
+    {
+	if (aliassym->isTemplateInstance())
+	    aliassym->semantic(sc);
+	return;
+    }
+    this->inSemantic = 1;
+
+    if (storage_class & STCconst)
+	error("cannot be const");
+
+    storage_class |= sc->stc & STCdeprecated;
+
+    // Given:
+    //	alias foo.bar.abc def;
+    // it is not knowable from the syntax whether this is an alias
+    // for a type or an alias for a symbol. It is up to the semantic()
+    // pass to distinguish.
+    // If it is a type, then type is set and getType() will return that
+    // type. If it is a symbol, then aliassym is set and type is NULL -
+    // toAlias() will return aliasssym.
+
+    Dsymbol *s;
+    Type *t;
+    Expression *e;
+
+    /* This section is needed because resolve() will:
+     *   const x = 3;
+     *   alias x y;
+     * try to alias y to 3.
+     */
+    s = type->toDsymbol(sc);
+    if (s && ((s->getType() && type->equals(s->getType())) || s->isEnumMember()))
+	goto L2;			// it's a symbolic alias
+
+    if (storage_class & STCref)
+    {	// For 'ref' to be attached to function types, and picked
+	// up by Type::resolve(), it has to go into sc.
+	sc = sc->push();
+	sc->stc |= STCref;
+	type->resolve(loc, sc, &e, &t, &s);
+	sc = sc->pop();
+    }
+    else
+	type->resolve(loc, sc, &e, &t, &s);
+    if (s)
+    {
+	goto L2;
+    }
+    else if (e)
+    {
+	// Try to convert Expression to Dsymbol
+	s = getDsymbol(e);
+	if (s)
+	    goto L2;
+
+	error("cannot alias an expression %s", e->toChars());
+	t = e->type;
+    }
+    else if (t)
+	type = t;
+    if (overnext)
+	ScopeDsymbol::multiplyDefined(0, this, overnext);
+    this->inSemantic = 0;
+    return;
+
+  L2:
+    //printf("alias is a symbol %s %s\n", s->kind(), s->toChars());
+    type = NULL;
+    VarDeclaration *v = s->isVarDeclaration();
+    if (v && v->linkage == LINKdefault)
+    {
+	error("forward reference of %s", v->toChars());
+	s = NULL;
+    }
+    else
+    {
+	FuncDeclaration *f = s->toAlias()->isFuncDeclaration();
+	if (f)
+	{
+	    if (overnext)
+	    {
+		FuncAliasDeclaration *fa = new FuncAliasDeclaration(f);
+		fa->importprot = importprot;
+		if (!fa->overloadInsert(overnext))
+		    ScopeDsymbol::multiplyDefined(0, f, overnext);
+		overnext = NULL;
+		s = fa;
+		s->parent = sc->parent;
+	    }
+	}
+	if (overnext)
+	    ScopeDsymbol::multiplyDefined(0, s, overnext);
+	if (s == this)
+	{
+	    assert(global.errors);
+	    s = NULL;
+	}
+    }
+    aliassym = s;
+    this->inSemantic = 0;
+}
+
+int AliasDeclaration::overloadInsert(Dsymbol *s)
+{
+    /* Don't know yet what the aliased symbol is, so assume it can
+     * be overloaded and check later for correctness.
+     */
+
+    //printf("AliasDeclaration::overloadInsert('%s')\n", s->toChars());
+    if (overnext == NULL)
+    {	overnext = s;
+	return TRUE;
+    }
+    else
+    {
+	return overnext->overloadInsert(s);
+    }
+}
+
+const char *AliasDeclaration::kind()
+{
+    return "alias";
+}
+
+Type *AliasDeclaration::getType()
+{
+    return type;
+}
+
+Dsymbol *AliasDeclaration::toAlias()
+{
+    //printf("AliasDeclaration::toAlias('%s', this = %p, aliassym = %p, kind = '%s')\n", toChars(), this, aliassym, aliassym ? aliassym->kind() : "");
+    assert(this != aliassym);
+    //static int count; if (++count == 10) *(char*)0=0;
+    if (inSemantic)
+    {	error("recursive alias declaration");
+	aliassym = new TypedefDeclaration(loc, ident, Type::terror, NULL);
+    }
+    Dsymbol *s = aliassym ? aliassym->toAlias() : this;
+    return s;
+}
+
+void AliasDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    buf->writestring("alias ");
+#if 0 && _DH
+    if (hgs->hdrgen)
+    {
+	if (haliassym)
+	{
+	    buf->writestring(haliassym->toChars());
+	    buf->writeByte(' ');
+	    buf->writestring(ident->toChars());
+	}
+	else
+	    htype->toCBuffer(buf, ident, hgs);
+    }
+    else
+#endif
+    {
+	if (aliassym)
+	{
+	    aliassym->toCBuffer(buf, hgs);
+	    buf->writeByte(' ');
+	    buf->writestring(ident->toChars());
+	}
+	else
+	    type->toCBuffer(buf, ident, hgs);
+    }
+    buf->writeByte(';');
+    buf->writenl();
+}
+
+/********************************* VarDeclaration ****************************/
+
+VarDeclaration::VarDeclaration(Loc loc, Type *type, Identifier *id, Initializer *init)
+    : Declaration(id)
+{
+    //printf("VarDeclaration('%s')\n", id->toChars());
+#ifdef DEBUG
+    if (!type && !init)
+    {	printf("VarDeclaration('%s')\n", id->toChars());
+	//*(char*)0=0;
+    }
+#endif
+    assert(type || init);
+    this->type = type;
+    this->init = init;
+#ifdef _DH
+    this->htype = NULL;
+    this->hinit = NULL;
+#endif
+    this->loc = loc;
+    offset = 0;
+    noauto = 0;
+    ctorinit = 0;
+    aliassym = NULL;
+    onstack = 0;
+    canassign = 0;
+    value = NULL;
+    scope = NULL;
+#if IN_LLVM
+    aggrIndex = 0;
+
+    // LDC
+    anonDecl = NULL;
+    offset2 = 0;
+
+    nakedUse = false;
+#endif
+}
+
+Dsymbol *VarDeclaration::syntaxCopy(Dsymbol *s)
+{
+    //printf("VarDeclaration::syntaxCopy(%s)\n", toChars());
+
+    VarDeclaration *sv;
+    if (s)
+    {	sv = (VarDeclaration *)s;
+    }
+    else
+    {
+	Initializer *init = NULL;
+	if (this->init)
+	{   init = this->init->syntaxCopy();
+	    //init->isExpInitializer()->exp->print();
+	    //init->isExpInitializer()->exp->dump(0);
+	}
+
+	sv = new VarDeclaration(loc, type ? type->syntaxCopy() : NULL, ident, init);
+	sv->storage_class = storage_class;
+    }
+#ifdef _DH
+    // Syntax copy for header file
+    if (!htype)      // Don't overwrite original
+    {	if (type)    // Make copy for both old and new instances
+	{   htype = type->syntaxCopy();
+	    sv->htype = type->syntaxCopy();
+	}
+    }
+    else            // Make copy of original for new instance
+        sv->htype = htype->syntaxCopy();
+    if (!hinit)
+    {	if (init)
+	{   hinit = init->syntaxCopy();
+	    sv->hinit = init->syntaxCopy();
+	}
+    }
+    else
+        sv->hinit = hinit->syntaxCopy();
+#endif
+    return sv;
+}
+
+void VarDeclaration::semantic(Scope *sc)
+{
+#if 0
+    printf("VarDeclaration::semantic('%s', parent = '%s')\n", toChars(), sc->parent->toChars());
+    printf(" type = %s\n", type ? type->toChars() : "null");
+    printf(" stc = x%x\n", sc->stc);
+    printf(" storage_class = x%x\n", storage_class);
+    printf("linkage = %d\n", sc->linkage);
+    //if (strcmp(toChars(), "mul") == 0) halt();
+#endif
+
+    storage_class |= sc->stc;
+    if (storage_class & STCextern && init)
+	error("extern symbols cannot have initializers");
+
+    /* If auto type inference, do the inference
+     */
+    int inferred = 0;
+    if (!type)
+    {	inuse++;
+	type = init->inferType(sc);
+	inuse--;
+	inferred = 1;
+
+	/* This is a kludge to support the existing syntax for RAII
+	 * declarations.
+	 */
+	storage_class &= ~STCauto;
+	originalType = type;
+    }
+    else
+    {	if (!originalType)
+	    originalType = type;
+	type = type->semantic(loc, sc);
+    }
+    //printf(" semantic type = %s\n", type ? type->toChars() : "null");
+
+    type->checkDeprecated(loc, sc);
+    linkage = sc->linkage;
+    this->parent = sc->parent;
+    //printf("this = %p, parent = %p, '%s'\n", this, parent, parent->toChars());
+    protection = sc->protection;
+    //printf("sc->stc = %x\n", sc->stc);
+    //printf("storage_class = x%x\n", storage_class);
+
+    if (storage_class & STCgshared && global.params.safe && !sc->module->safe)
+    {
+	error("__gshared not allowed in safe mode; use shared");
+    }
+
+    Dsymbol *parent = toParent();
+    FuncDeclaration *fd = parent->isFuncDeclaration();
+
+    Type *tb = type->toBasetype();
+    if (tb->ty == Tvoid && !(storage_class & STClazy))
+    {	error("voids have no value");
+	type = Type::terror;
+	tb = type;
+    }
+    if (tb->ty == Tfunction)
+    {	error("cannot be declared to be a function");
+	type = Type::terror;
+	tb = type;
+    }
+    if (tb->ty == Tstruct)
+    {	TypeStruct *ts = (TypeStruct *)tb;
+
+	if (!ts->sym->members)
+	{
+	    error("no definition of struct %s", ts->toChars());
+	}
+    }
+
+    if (tb->ty == Ttuple)
+    {   /* Instead, declare variables for each of the tuple elements
+	 * and add those.
+	 */
+	TypeTuple *tt = (TypeTuple *)tb;
+	size_t nelems = Argument::dim(tt->arguments);
+	Objects *exps = new Objects();
+	exps->setDim(nelems);
+	Expression *ie = init ? init->toExpression() : NULL;
+
+	for (size_t i = 0; i < nelems; i++)
+	{   Argument *arg = Argument::getNth(tt->arguments, i);
+
+	    OutBuffer buf;
+	    buf.printf("_%s_field_%zu", ident->toChars(), i);
+	    buf.writeByte(0);
+	    char *name = (char *)buf.extractData();
+	    Identifier *id = new Identifier(name, TOKidentifier);
+
+	    Expression *einit = ie;
+	    if (ie && ie->op == TOKtuple)
+	    {	einit = (Expression *)((TupleExp *)ie)->exps->data[i];
+	    }
+	    Initializer *ti = init;
+	    if (einit)
+	    {	ti = new ExpInitializer(einit->loc, einit);
+	    }
+
+	    VarDeclaration *v = new VarDeclaration(loc, arg->type, id, ti);
+	    //printf("declaring field %s of type %s\n", v->toChars(), v->type->toChars());
+	    v->semantic(sc);
+            
+/*
+// removed for LDC since TupleDeclaration::toObj already creates the fields;
+// adding them to the scope again leads to duplicates
+	    if (sc->scopesym)
+	    {	//printf("adding %s to %s\n", v->toChars(), sc->scopesym->toChars());
+		if (sc->scopesym->members)
+		    sc->scopesym->members->push(v);
+	    }
+*/
+	    Expression *e = new DsymbolExp(loc, v);
+	    exps->data[i] = e;
+	}
+	TupleDeclaration *v2 = new TupleDeclaration(loc, ident, exps);
+	v2->isexp = 1;
+	aliassym = v2;
+	return;
+    }
+
+Lagain:
+    /* Storage class can modify the type
+     */
+    type = type->addStorageClass(storage_class);
+
+    /* Adjust storage class to reflect type
+     */
+    if (type->isConst())
+    {	storage_class |= STCconst;
+	if (type->isShared())
+	    storage_class |= STCshared;
+    }
+    else if (type->isInvariant())
+	storage_class |= STCimmutable;
+    else if (type->isShared())
+	storage_class |= STCshared;
+
+    if (isSynchronized())
+    {
+	error("variable %s cannot be synchronized", toChars());
+    }
+    else if (isOverride())
+    {
+	error("override cannot be applied to variable");
+    }
+    else if (isAbstract())
+    {
+	error("abstract cannot be applied to variable");
+    }
+    else if (storage_class & STCfinal)
+    {
+	error("final cannot be applied to variable");
+    }
+
+    if (storage_class & (STCstatic | STCextern | STCmanifest | STCtemplateparameter | STCtls | STCgshared))
+    {
+    }
+    else
+    {
+	AggregateDeclaration *aad = sc->anonAgg;
+	if (!aad)
+	    aad = parent->isAggregateDeclaration();
+	if (aad)
+	{   assert(!(storage_class & (STCextern | STCstatic | STCtls | STCgshared)));
+
+	    if (storage_class & (STCconst | STCimmutable) && init)
+	    {
+		if (!type->toBasetype()->isTypeBasic())
+		    storage_class |= STCstatic;
+	    }
+	    else
+		aad->addField(sc, this);
+	}
+
+	InterfaceDeclaration *id = parent->isInterfaceDeclaration();
+	if (id)
+	{
+	    error("field not allowed in interface");
+	}
+
+	/* Templates cannot add fields to aggregates
+	 */
+	TemplateInstance *ti = parent->isTemplateInstance();
+	if (ti)
+	{
+	    // Take care of nested templates
+	    while (1)
+	    {
+		TemplateInstance *ti2 = ti->tempdecl->parent->isTemplateInstance();
+		if (!ti2)
+		    break;
+		ti = ti2;
+	    }
+
+	    // If it's a member template
+	    AggregateDeclaration *ad = ti->tempdecl->isMember();
+	    if (ad && storage_class != STCundefined)
+	    {
+		error("cannot use template to add field to aggregate '%s'", ad->toChars());
+	    }
+	}
+    }
+
+    if ((storage_class & (STCref | STCparameter | STCforeach)) == STCref &&
+	ident != Id::This)
+    {
+	error("only parameters or foreach declarations can be ref");
+    }
+
+    if (type->isauto() && !noauto)
+    {
+	if (storage_class & (STCfield | STCout | STCref | STCstatic | STCmanifest | STCtls | STCgshared) || !fd)
+	{
+	    error("globals, statics, fields, manifest constants, ref and out parameters cannot be scope");
+	}
+
+	if (!(storage_class & (STCauto | STCscope)))
+	{
+	    if (!(storage_class & STCparameter) && ident != Id::withSym)
+		error("reference to scope class must be scope");
+	}
+    }
+
+    if ((isConst() || isInvariant()) && !init && !fd)
+    {	// Initialize by constructor only
+	storage_class |= STCctorinit;
+    }
+
+    if (init)
+	storage_class |= STCinit;     // remember we had an explicit initializer
+    else if (storage_class & STCmanifest)
+	error("manifest constants must have initializers");
+
+    enum TOK op = TOKconstruct;
+    if (!init && !sc->inunion && !isStatic() && fd &&
+	(!(storage_class & (STCfield | STCin | STCforeach | STCparameter)) || (storage_class & STCout)) &&
+	type->size() != 0)
+    {
+	// Provide a default initializer
+	//printf("Providing default initializer for '%s'\n", toChars());
+	if (type->ty == Tstruct &&
+	    ((TypeStruct *)type)->sym->zeroInit == 1)
+	{   /* If a struct is all zeros, as a special case
+	     * set it's initializer to the integer 0.
+	     * In AssignExp::toElem(), we check for this and issue
+	     * a memset() to initialize the struct.
+	     * Must do same check in interpreter.
+	     */
+	    Expression *e = new IntegerExp(loc, 0, Type::tint32);
+	    Expression *e1;
+	    e1 = new VarExp(loc, this);
+	    e = new AssignExp(loc, e1, e);
+	    e->op = TOKconstruct;
+	    e->type = e1->type;		// don't type check this, it would fail
+	    init = new ExpInitializer(loc, e);
+	    return;
+	}
+	else if (type->ty == Ttypedef)
+	{   TypeTypedef *td = (TypeTypedef *)type;
+	    if (td->sym->init)
+	    {	init = td->sym->init;
+		ExpInitializer *ie = init->isExpInitializer();
+		if (ie)
+		    // Make copy so we can modify it
+		    init = new ExpInitializer(ie->loc, ie->exp);
+	    }
+	    else
+		init = getExpInitializer();
+	}
+	else
+	{
+	    init = getExpInitializer();
+	}
+	// Default initializer is always a blit
+	op = TOKblit;
+    }
+
+    if (init)
+    {
+	sc = sc->push();
+	sc->stc &= ~(STC_TYPECTOR | STCpure | STCnothrow | STCref);
+
+	ArrayInitializer *ai = init->isArrayInitializer();
+	if (ai && tb->ty == Taarray)
+	{
+	    init = ai->toAssocArrayInitializer();
+	}
+
+	StructInitializer *si = init->isStructInitializer();
+	ExpInitializer *ei = init->isExpInitializer();
+
+	// See if initializer is a NewExp that can be allocated on the stack
+	if (ei && isScope() && ei->exp->op == TOKnew)
+	{   NewExp *ne = (NewExp *)ei->exp;
+	    if (!(ne->newargs && ne->newargs->dim))
+	    {	ne->onstack = 1;
+		onstack = 1;
+		if (type->isBaseOf(ne->newtype->semantic(loc, sc), NULL))
+		    onstack = 2;
+	    }
+	}
+
+	// If inside function, there is no semantic3() call
+	if (sc->func)
+	{
+	    // If local variable, use AssignExp to handle all the various
+	    // possibilities.
+	    if (fd &&
+		!(storage_class & (STCmanifest | STCstatic | STCtls | STCgshared | STCextern)) &&
+		!init->isVoidInitializer())
+	    {
+		//printf("fd = '%s', var = '%s'\n", fd->toChars(), toChars());
+		if (!ei)
+		{
+		    Expression *e = init->toExpression();
+		    if (!e)
+		    {
+			init = init->semantic(sc, type);
+			e = init->toExpression();
+			if (!e)
+			{   error("is not a static and cannot have static initializer");
+			    return;
+			}
+		    }
+		    ei = new ExpInitializer(init->loc, e);
+		    init = ei;
+		}
+
+		Expression *e1 = new VarExp(loc, this);
+
+		Type *t = type->toBasetype();
+		if (t->ty == Tsarray)
+		{
+		    ei->exp = ei->exp->semantic(sc);
+		    if (!ei->exp->implicitConvTo(type))
+		    {
+			int dim = ((TypeSArray *)t)->dim->toInteger();
+			// If multidimensional static array, treat as one large array
+			while (1)
+			{
+			    t = t->nextOf()->toBasetype();
+			    if (t->ty != Tsarray)
+				break;
+			    dim *= ((TypeSArray *)t)->dim->toInteger();
+			    e1->type = new TypeSArray(t->nextOf(), new IntegerExp(0, dim, Type::tindex));
+			}
+		    }
+		    e1 = new SliceExp(loc, e1, NULL, NULL);
+		}
+		else if (t->ty == Tstruct)
+		{
+		    ei->exp = ei->exp->semantic(sc);
+
+		    /* Look to see if initializer is a call to the constructor
+		     */
+		    StructDeclaration *sd = ((TypeStruct *)t)->sym;
+		    if (sd->ctor &&		// there are constructors
+			ei->exp->type->ty == Tstruct &&	// rvalue is the same struct
+			((TypeStruct *)ei->exp->type)->sym == sd &&
+			ei->exp->op == TOKstar)
+		    {
+			/* Look for form of constructor call which is:
+			 *    *__ctmp.ctor(arguments...)
+			 */
+			PtrExp *pe = (PtrExp *)ei->exp;
+			if (pe->e1->op == TOKcall)
+			{   CallExp *ce = (CallExp *)pe->e1;
+			    if (ce->e1->op == TOKdotvar)
+			    {	DotVarExp *dve = (DotVarExp *)ce->e1;
+				if (dve->var->isCtorDeclaration())
+				{   /* It's a constructor call, currently constructing
+				     * a temporary __ctmp.
+				     */
+				    /* Before calling the constructor, initialize
+				     * variable with a bit copy of the default
+				     * initializer
+				     */
+				    Expression *e = new AssignExp(loc, new VarExp(loc, this), t->defaultInit(loc));
+				    e->op = TOKblit;
+				    e->type = t;
+				    ei->exp = new CommaExp(loc, e, ei->exp);
+
+				    /* Replace __ctmp being constructed with e1
+				     */
+				    dve->e1 = e1;
+				    return;
+				}
+			    }
+			}
+		    }
+
+		    if (!ei->exp->implicitConvTo(type))
+		    {	Type *ti = ei->exp->type->toBasetype();
+			// Don't cast away invariant or mutability in initializer
+			if (!(ti->ty == Tstruct && t->toDsymbol(sc) == ti->toDsymbol(sc)))
+			    ei->exp = new CastExp(loc, ei->exp, type);
+		    }
+		}
+		ei->exp = new AssignExp(loc, e1, ei->exp);
+		ei->exp->op = op;
+		canassign++;
+		ei->exp = ei->exp->semantic(sc);
+		canassign--;
+		ei->exp->optimize(WANTvalue);
+	    }
+	    else
+	    {
+		init = init->semantic(sc, type);
+	    }
+	}
+	else if (storage_class & (STCconst | STCimmutable | STCmanifest) ||
+		 type->isConst() || type->isInvariant())
+	{
+	    /* Because we may need the results of a const declaration in a
+	     * subsequent type, such as an array dimension, before semantic2()
+	     * gets ordinarily run, try to run semantic2() now.
+	     * Ignore failure.
+	     */
+
+	    if (!global.errors && !inferred)
+	    {
+		unsigned errors = global.errors;
+		global.gag++;
+		//printf("+gag\n");
+		Expression *e;
+		Initializer *i2 = init;
+		inuse++;
+		if (ei)
+		{
+		    e = ei->exp->syntaxCopy();
+		    e = e->semantic(sc);
+		    e = e->implicitCastTo(sc, type);
+		}
+		else if (si || ai)
+		{   i2 = init->syntaxCopy();
+		    i2 = i2->semantic(sc, type);
+		}
+		inuse--;
+		global.gag--;
+		//printf("-gag\n");
+		if (errors != global.errors)	// if errors happened
+		{
+		    if (global.gag == 0)
+			global.errors = errors;	// act as if nothing happened
+
+		    /* Save scope for later use, to try again
+		     */
+		    scope = new Scope(*sc);
+		    scope->setNoFree();
+		}
+		else if (ei)
+		{
+		    if (isDataseg())
+			/* static const/invariant does CTFE
+			 */
+			e = e->optimize(WANTvalue | WANTinterpret);
+		    else
+			e = e->optimize(WANTvalue);
+		    if (e->op == TOKint64 || e->op == TOKstring)
+		    {
+			ei->exp = e;		// no errors, keep result
+		    }
+		    else
+		    {
+			/* Save scope for later use, to try again
+			 */
+			scope = new Scope(*sc);
+			scope->setNoFree();
+		    }
+		}
+		else
+		    init = i2;		// no errors, keep result
+	    }
+	}
+	sc = sc->pop();
+    }
+}
+
+void VarDeclaration::semantic2(Scope *sc)
+{
+    //printf("VarDeclaration::semantic2('%s')\n", toChars());
+    if (init && !toParent()->isFuncDeclaration())
+    {	inuse++;
+#if 0
+	ExpInitializer *ei = init->isExpInitializer();
+	if (ei)
+	{
+	    ei->exp->dump(0);
+	    printf("type = %p\n", ei->exp->type);
+	}
+#endif
+	init = init->semantic(sc, type);
+	inuse--;
+    }
+}
+
+const char *VarDeclaration::kind()
+{
+    return "variable";
+}
+
+Dsymbol *VarDeclaration::toAlias()
+{
+    //printf("VarDeclaration::toAlias('%s', this = %p, aliassym = %p)\n", toChars(), this, aliassym);
+    assert(this != aliassym);
+    Dsymbol *s = aliassym ? aliassym->toAlias() : this;
+    return s;
+}
+
+void VarDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    StorageClassDeclaration::stcToCBuffer(buf, storage_class);
+
+    /* If changing, be sure and fix CompoundDeclarationStatement::toCBuffer()
+     * too.
+     */
+    if (type)
+	type->toCBuffer(buf, ident, hgs);
+    else
+	buf->writestring(ident->toChars());
+    if (init)
+    {	buf->writestring(" = ");
+	ExpInitializer *ie = init->isExpInitializer();
+	if (ie && (ie->exp->op == TOKconstruct || ie->exp->op == TOKblit))
+	    ((AssignExp *)ie->exp)->e2->toCBuffer(buf, hgs);
+	else
+	    init->toCBuffer(buf, hgs);
+    }
+    buf->writeByte(';');
+    buf->writenl();
+}
+
+int VarDeclaration::needThis()
+{
+    //printf("VarDeclaration::needThis(%s, x%x)\n", toChars(), storage_class);
+    return storage_class & STCfield;
+}
+
+int VarDeclaration::isImportedSymbol()
+{
+    if (protection == PROTexport && !init &&
+	(storage_class & STCstatic || parent->isModule()))
+	return TRUE;
+    return FALSE;
+}
+
+void VarDeclaration::checkCtorConstInit()
+{
+#if 0 /* doesn't work if more than one static ctor */
+    if (ctorinit == 0 && isCtorinit() && !(storage_class & STCfield))
+	error("missing initializer in static constructor for const variable");
+#endif
+}
+
+/************************************
+ * Check to see if this variable is actually in an enclosing function
+ * rather than the current one.
+ */
+
+void VarDeclaration::checkNestedReference(Scope *sc, Loc loc)
+{
+    if (parent && !isDataseg() && parent != sc->parent &&
+	!(storage_class & STCmanifest))
+    {
+	// The function that this variable is in
+	FuncDeclaration *fdv = toParent()->isFuncDeclaration();
+	// The current function
+	FuncDeclaration *fdthis = sc->parent->isFuncDeclaration();
+
+	if (fdv && fdthis && fdv != fdthis)
+	{
+	    if (loc.filename)
+		fdthis->getLevel(loc, fdv);
+
+	    for (int i = 0; i < nestedrefs.dim; i++)
+	    {	FuncDeclaration *f = (FuncDeclaration *)nestedrefs.data[i];
+		if (f == fdthis)
+		    goto L1;
+	    }
+	    nestedrefs.push(fdthis);
+	  L1: ;
+
+
+	    for (int i = 0; i < fdv->closureVars.dim; i++)
+	    {	Dsymbol *s = (Dsymbol *)fdv->closureVars.data[i];
+		if (s == this)
+		    goto L2;
+	    }
+
+	    fdv->closureVars.push(this);
+	  L2: ;
+
+	    //printf("fdthis is %s\n", fdthis->toChars());
+	    //printf("var %s in function %s is nested ref\n", toChars(), fdv->toChars());
+	}
+    }
+}
+
+/****************************
+ * Get ExpInitializer for a variable, if there is one.
+ */
+
+ExpInitializer *VarDeclaration::getExpInitializer()
+{
+    ExpInitializer *ei;
+
+    if (init)
+	ei = init->isExpInitializer();
+    else
+    {
+	Expression *e = type->defaultInit(loc);
+	if (e)
+	    ei = new ExpInitializer(loc, e);
+	else
+	    ei = NULL;
+    }
+    return ei;
+}
+
+/*******************************************
+ * If variable has a constant expression initializer, get it.
+ * Otherwise, return NULL.
+ */
+
+Expression *VarDeclaration::getConstInitializer()
+{
+    if ((isConst() || isInvariant() || storage_class & STCmanifest) &&
+	storage_class & STCinit)
+    {
+	ExpInitializer *ei = getExpInitializer();
+	if (ei)
+	    return ei->exp;
+    }
+
+    return NULL;
+}
+
+/*************************************
+ * Return !=0 if we can take the address of this variable.
+ */
+
+int VarDeclaration::canTakeAddressOf()
+{
+#if 0
+    /* Global variables and struct/class fields of the form:
+     *	const int x = 3;
+     * are not stored and hence cannot have their address taken.
+     */
+    if ((isConst() || isInvariant()) &&
+	storage_class & STCinit &&
+	(!(storage_class & (STCstatic | STCextern)) || (storage_class & STCfield)) &&
+	(!parent || toParent()->isModule() || toParent()->isTemplateInstance()) &&
+	type->toBasetype()->isTypeBasic()
+       )
+    {
+	return 0;
+    }
+#else
+    if (storage_class & STCmanifest)
+	return 0;
+#endif
+    return 1;
+}
+
+/*******************************
+ * Does symbol go into data segment?
+ * Includes extern variables.
+ */
+
+int VarDeclaration::isDataseg()
+{
+#if 0
+    printf("VarDeclaration::isDataseg(%p, '%s')\n", this, toChars());
+    printf("%x, %p, %p\n", storage_class & (STCstatic | STCconst), parent->isModule(), parent->isTemplateInstance());
+    printf("parent = '%s'\n", parent->toChars());
+#endif
+    if (storage_class & STCmanifest)
+	return 0;
+    Dsymbol *parent = this->toParent();
+    if (!parent && !(storage_class & STCstatic))
+    {	error("forward referenced");
+	type = Type::terror;
+	return 0;
+    }
+    return canTakeAddressOf() &&
+	(storage_class & (STCstatic | STCextern | STCtls | STCgshared) ||
+	 toParent()->isModule() ||
+	 toParent()->isTemplateInstance());
+}
+
+/************************************
+ * Does symbol go into thread local storage?
+ */
+
+int VarDeclaration::isThreadlocal()
+{
+    //printf("VarDeclaration::isThreadlocal(%p, '%s')\n", this, toChars());
+#if 0 || TARGET_OSX
+    /* To be thread-local, must use the __thread storage class.
+     * BUG: OSX doesn't support thread local yet.
+     */
+    return isDataseg() &&
+	(storage_class & (STCtls | STCconst | STCimmutable | STCshared | STCgshared)) == STCtls;
+#else
+    /* Data defaults to being thread-local. It is not thread-local
+     * if it is immutable, const or shared.
+     */
+    int i = isDataseg() &&
+	!(storage_class & (STCimmutable | STCconst | STCshared | STCgshared));
+    //printf("\treturn %d\n", i);
+    return i;
+#endif
+}
+
+int VarDeclaration::hasPointers()
+{
+    //printf("VarDeclaration::hasPointers() %s, ty = %d\n", toChars(), type->ty);
+    return (!isDataseg() && type->hasPointers());
+}
+
+/******************************************
+ * Return TRUE if variable needs to call the destructor.
+ */
+
+int VarDeclaration::needsAutoDtor()
+{
+    //printf("VarDeclaration::needsAutoDtor() %s\n", toChars());
+
+    if (noauto || storage_class & STCnodtor)
+	return FALSE;
+
+    // Destructors for structs and arrays of structs
+    Type *tv = type->toBasetype();
+    while (tv->ty == Tsarray)
+    {   TypeSArray *ta = (TypeSArray *)tv;
+	tv = tv->nextOf()->toBasetype();
+    }
+    if (tv->ty == Tstruct)
+    {   TypeStruct *ts = (TypeStruct *)tv;
+	StructDeclaration *sd = ts->sym;
+	if (sd->dtor)
+	    return TRUE;
+    }
+
+    // Destructors for classes
+    if (storage_class & (STCauto | STCscope))
+    {
+	if (type->isClassHandle())
+	    return TRUE;
+    }
+    return FALSE;
+}
+
+
+/******************************************
+ * If a variable has an auto destructor call, return call for it.
+ * Otherwise, return NULL.
+ */
+
+Expression *VarDeclaration::callAutoDtor(Scope *sc)
+{   Expression *e = NULL;
+
+    //printf("VarDeclaration::callAutoDtor() %s\n", toChars());
+
+    if (noauto || storage_class & STCnodtor)
+	return NULL;
+
+    // Destructors for structs and arrays of structs
+    bool array = false;
+    Type *tv = type->toBasetype();
+    while (tv->ty == Tsarray)
+    {   TypeSArray *ta = (TypeSArray *)tv;
+	array = true;
+	tv = tv->nextOf()->toBasetype();
+    }
+    if (tv->ty == Tstruct)
+    {   TypeStruct *ts = (TypeStruct *)tv;
+	StructDeclaration *sd = ts->sym;
+	if (sd->dtor)
+	{
+	    if (array)
+	    {
+		// Typeinfo.destroy(cast(void*)&v);
+		Expression *ea = new SymOffExp(loc, this, 0, 0);
+		ea = new CastExp(loc, ea, Type::tvoid->pointerTo());
+		Expressions *args = new Expressions();
+		args->push(ea);
+
+		Expression *et = type->getTypeInfo(sc);
+		et = new DotIdExp(loc, et, Id::destroy);
+
+		e = new CallExp(loc, et, args);
+	    }
+	    else
+	    {
+		e = new VarExp(loc, this);
+		e = new DotVarExp(loc, e, sd->dtor, 0);
+		e = new CallExp(loc, e);
+	    }
+	    return e;
+	}
+    }
+
+    // Destructors for classes
+    if (storage_class & (STCauto | STCscope))
+    {
+	for (ClassDeclaration *cd = type->isClassHandle();
+	     cd;
+	     cd = cd->baseClass)
+	{
+	    /* We can do better if there's a way with onstack
+	     * classes to determine if there's no way the monitor
+	     * could be set.
+	     */
+	    //if (cd->isInterfaceDeclaration())
+		//error("interface %s cannot be scope", cd->toChars());
+	    if (1 || onstack || cd->dtors.dim)	// if any destructors
+	    {
+		// delete this;
+		Expression *ec;
+
+		ec = new VarExp(loc, this);
+		e = new DeleteExp(loc, ec);
+		e->type = Type::tvoid;
+		break;
+	    }
+	}
+    }
+    return e;
+}
+
+
+/********************************* ClassInfoDeclaration ****************************/
+
+ClassInfoDeclaration::ClassInfoDeclaration(ClassDeclaration *cd)
+    : VarDeclaration(0, ClassDeclaration::classinfo->type, cd->ident, NULL)
+{
+    this->cd = cd;
+    storage_class = STCstatic | STCgshared;
+}
+
+Dsymbol *ClassInfoDeclaration::syntaxCopy(Dsymbol *s)
+{
+    assert(0);		// should never be produced by syntax
+    return NULL;
+}
+
+void ClassInfoDeclaration::semantic(Scope *sc)
+{
+}
+
+/********************************* ModuleInfoDeclaration ****************************/
+
+ModuleInfoDeclaration::ModuleInfoDeclaration(Module *mod)
+    : VarDeclaration(0, Module::moduleinfo->type, mod->ident, NULL)
+{
+    this->mod = mod;
+    storage_class = STCstatic | STCgshared;
+}
+
+Dsymbol *ModuleInfoDeclaration::syntaxCopy(Dsymbol *s)
+{
+    assert(0);		// should never be produced by syntax
+    return NULL;
+}
+
+void ModuleInfoDeclaration::semantic(Scope *sc)
+{
+}
+
+/********************************* TypeInfoDeclaration ****************************/
+
+TypeInfoDeclaration::TypeInfoDeclaration(Type *tinfo, int internal)
+    : VarDeclaration(0, Type::typeinfo->type, tinfo->getTypeInfoIdent(internal), NULL)
+{
+    this->tinfo = tinfo;
+    storage_class = STCstatic | STCgshared;
+    protection = PROTpublic;
+    linkage = LINKc;
+}
+
+Dsymbol *TypeInfoDeclaration::syntaxCopy(Dsymbol *s)
+{
+    assert(0);		// should never be produced by syntax
+    return NULL;
+}
+
+void TypeInfoDeclaration::semantic(Scope *sc)
+{
+    assert(linkage == LINKc);
+}
+
+/***************************** TypeInfoConstDeclaration **********************/
+
+#if DMDV2
+TypeInfoConstDeclaration::TypeInfoConstDeclaration(Type *tinfo)
+    : TypeInfoDeclaration(tinfo, 0)
+{
+}
+#endif
+
+/***************************** TypeInfoInvariantDeclaration **********************/
+
+#if DMDV2
+TypeInfoInvariantDeclaration::TypeInfoInvariantDeclaration(Type *tinfo)
+    : TypeInfoDeclaration(tinfo, 0)
+{
+}
+#endif
+
+/***************************** TypeInfoSharedDeclaration **********************/
+
+#if DMDV2
+TypeInfoSharedDeclaration::TypeInfoSharedDeclaration(Type *tinfo)
+    : TypeInfoDeclaration(tinfo, 0)
+{
+}
+#endif
+
+/***************************** TypeInfoStructDeclaration **********************/
+
+TypeInfoStructDeclaration::TypeInfoStructDeclaration(Type *tinfo)
+    : TypeInfoDeclaration(tinfo, 0)
+{
+}
+
+/***************************** TypeInfoClassDeclaration ***********************/
+
+TypeInfoClassDeclaration::TypeInfoClassDeclaration(Type *tinfo)
+    : TypeInfoDeclaration(tinfo, 0)
+{
+}
+
+/***************************** TypeInfoInterfaceDeclaration *******************/
+
+TypeInfoInterfaceDeclaration::TypeInfoInterfaceDeclaration(Type *tinfo)
+    : TypeInfoDeclaration(tinfo, 0)
+{
+}
+
+/***************************** TypeInfoTypedefDeclaration *********************/
+
+TypeInfoTypedefDeclaration::TypeInfoTypedefDeclaration(Type *tinfo)
+    : TypeInfoDeclaration(tinfo, 0)
+{
+}
+
+/***************************** TypeInfoPointerDeclaration *********************/
+
+TypeInfoPointerDeclaration::TypeInfoPointerDeclaration(Type *tinfo)
+    : TypeInfoDeclaration(tinfo, 0)
+{
+}
+
+/***************************** TypeInfoArrayDeclaration ***********************/
+
+TypeInfoArrayDeclaration::TypeInfoArrayDeclaration(Type *tinfo)
+    : TypeInfoDeclaration(tinfo, 0)
+{
+}
+
+/***************************** TypeInfoStaticArrayDeclaration *****************/
+
+TypeInfoStaticArrayDeclaration::TypeInfoStaticArrayDeclaration(Type *tinfo)
+    : TypeInfoDeclaration(tinfo, 0)
+{
+}
+
+/***************************** TypeInfoAssociativeArrayDeclaration ************/
+
+TypeInfoAssociativeArrayDeclaration::TypeInfoAssociativeArrayDeclaration(Type *tinfo)
+    : TypeInfoDeclaration(tinfo, 0)
+{
+}
+
+/***************************** TypeInfoEnumDeclaration ***********************/
+
+TypeInfoEnumDeclaration::TypeInfoEnumDeclaration(Type *tinfo)
+    : TypeInfoDeclaration(tinfo, 0)
+{
+}
+
+/***************************** TypeInfoFunctionDeclaration ********************/
+
+TypeInfoFunctionDeclaration::TypeInfoFunctionDeclaration(Type *tinfo)
+    : TypeInfoDeclaration(tinfo, 0)
+{
+}
+
+/***************************** TypeInfoDelegateDeclaration ********************/
+
+TypeInfoDelegateDeclaration::TypeInfoDelegateDeclaration(Type *tinfo)
+    : TypeInfoDeclaration(tinfo, 0)
+{
+}
+
+/***************************** TypeInfoTupleDeclaration **********************/
+
+TypeInfoTupleDeclaration::TypeInfoTupleDeclaration(Type *tinfo)
+    : TypeInfoDeclaration(tinfo, 0)
+{
+}
+
+/********************************* ThisDeclaration ****************************/
+
+// For the "this" parameter to member functions
+
+ThisDeclaration::ThisDeclaration(Loc loc, Type *t)
+   : VarDeclaration(loc, t, Id::This, NULL)
+{
+    noauto = 1;
+}
+
+Dsymbol *ThisDeclaration::syntaxCopy(Dsymbol *s)
+{
+    assert(0);		// should never be produced by syntax
+    return NULL;
+}
+
+/********************** StaticStructInitDeclaration ***************************/
+
+StaticStructInitDeclaration::StaticStructInitDeclaration(Loc loc, StructDeclaration *dsym)
+    : Declaration(new Identifier("", TOKidentifier))
+{
+    this->loc = loc;
+    this->dsym = dsym;
+    storage_class |= STCconst;
+}
--- a/dmd2/declaration.h	Mon Jun 01 01:28:18 2009 +0200
+++ b/dmd2/declaration.h	Mon Jun 01 19:02:20 2009 +0100
@@ -1,857 +1,971 @@
-
-// Compiler implementation of the D programming language
-// Copyright (c) 1999-2008 by Digital Mars
-// All Rights Reserved
-// written by Walter Bright
-// http://www.digitalmars.com
-// License for redistribution is by either the Artistic License
-// in artistic.txt, or the GNU General Public License in gnu.txt.
-// See the included readme.txt for details.
-
-#ifndef DMD_DECLARATION_H
-#define DMD_DECLARATION_H
-
-#ifdef __DMC__
-#pragma once
-#endif /* __DMC__ */
-
-#include <set>
-#include <map>
-#include <string>
-
-#include "dsymbol.h"
-#include "lexer.h"
-#include "mtype.h"
-
-struct Expression;
-struct Statement;
-struct LabelDsymbol;
-struct LabelStatement;
-struct Initializer;
-struct Module;
-struct InlineScanState;
-struct ForeachStatement;
-struct FuncDeclaration;
-struct ExpInitializer;
-struct StructDeclaration;
-struct TupleType;
-struct InterState;
-struct IRState;
-struct AnonDeclaration;
-
-enum PROT;
-enum LINK;
-enum TOK;
-enum MATCH;
-
-enum STC
-{
-    STCundefined    = 0,
-    STCstatic	    = 1,
-    STCextern	    = 2,
-    STCconst	    = 4,
-    STCfinal	    = 8,
-    STCabstract     = 0x10,
-    STCparameter    = 0x20,
-    STCfield	    = 0x40,
-    STCoverride	    = 0x80,
-    STCauto         = 0x100,
-    STCsynchronized = 0x200,
-    STCdeprecated   = 0x400,
-    STCin           = 0x800,		// in parameter
-    STCout          = 0x1000,		// out parameter
-    STClazy	    = 0x2000,		// lazy parameter
-    STCforeach      = 0x4000,		// variable for foreach loop
-    STCcomdat       = 0x8000,		// should go into COMDAT record
-    STCvariadic     = 0x10000,		// variadic function argument
-    STCctorinit     = 0x20000,		// can only be set inside constructor
-    STCtemplateparameter = 0x40000,	// template parameter
-    STCscope	    = 0x80000,		// template parameter
-    STCinvariant    = 0x100000,
-    STCref	    = 0x200000,
-    STCinit	    = 0x400000,		// has explicit initializer
-    STCmanifest	    = 0x800000,		// manifest constant
-    STCnodtor	    = 0x1000000,	// don't run destructor
-    STCnothrow	    = 0x2000000,	// never throws exceptions
-    STCpure	    = 0x4000000,	// pure function
-    STCtls	    = 0x8000000,	// thread local
-    STCalias	    = 0x10000000,	// alias parameter
-    STCshared       = 0x20000000,	// accessible from multiple threads
-};
-
-struct Match
-{
-    int count;			// number of matches found
-    MATCH last;			// match level of lastf
-    FuncDeclaration *lastf;	// last matching function we found
-    FuncDeclaration *nextf;	// current matching function
-    FuncDeclaration *anyf;	// pick a func, any func, to use for error recovery
-};
-
-void overloadResolveX(Match *m, FuncDeclaration *f,
-	Expression *ethis, Expressions *arguments);
-int overloadApply(FuncDeclaration *fstart,
-	int (*fp)(void *, FuncDeclaration *),
-	void *param);
-
-/**************************************************************/
-
-struct Declaration : Dsymbol
-{
-    Type *type;
-    Type *originalType;		// before semantic analysis
-    unsigned storage_class;
-    enum PROT protection;
-    enum LINK linkage;
-
-    Declaration(Identifier *id);
-    void semantic(Scope *sc);
-    const char *kind();
-    unsigned size(Loc loc);
-    void checkModify(Loc loc, Scope *sc, Type *t);
-
-    void emitComment(Scope *sc);
-    void toDocBuffer(OutBuffer *buf);
-
-    char *mangle();
-    int isStatic() { return storage_class & STCstatic; }
-    virtual int isStaticConstructor();
-    virtual int isStaticDestructor();
-    virtual int isDelete();
-    virtual int isDataseg();
-    virtual int isCodeseg();
-    int isCtorinit()     { return storage_class & STCctorinit; }
-    int isFinal()        { return storage_class & STCfinal; }
-    int isAbstract()     { return storage_class & STCabstract; }
-    int isConst()        { return storage_class & STCconst; }
-    int isInvariant()    { return storage_class & STCinvariant; }
-    int isAuto()         { return storage_class & STCauto; }
-    int isScope()        { return storage_class & (STCscope | STCauto); }
-    int isSynchronized() { return storage_class & STCsynchronized; }
-    int isParameter()    { return storage_class & STCparameter; }
-    int isDeprecated()   { return storage_class & STCdeprecated; }
-    int isOverride()     { return storage_class & STCoverride; }
-
-    int isIn()    { return storage_class & STCin; }
-    int isOut()   { return storage_class & STCout; }
-    int isRef()   { return storage_class & STCref; }
-
-    enum PROT prot();
-
-    Declaration *isDeclaration() { return this; }
-
-    // llvm
-    virtual void toObjFile(int unused = 0);           // compile to .obj file
-};
-
-/**************************************************************/
-
-struct TupleDeclaration : Declaration
-{
-    Objects *objects;
-    int isexp;			// 1: expression tuple
-
-    TypeTuple *tupletype;	// !=NULL if this is a type tuple
-
-    TupleDeclaration(Loc loc, Identifier *ident, Objects *objects);
-    Dsymbol *syntaxCopy(Dsymbol *);
-    const char *kind();
-    Type *getType();
-    int needThis();
-
-    TupleDeclaration *isTupleDeclaration() { return this; }
-
-    // LDC we need this
-    void toObjFile(int multiobj);           // compile to .obj file
-};
-
-/**************************************************************/
-
-struct TypedefDeclaration : Declaration
-{
-    Type *basetype;
-    Initializer *init;
-    int sem;			// 0: semantic() has not been run
-				// 1: semantic() is in progress
-				// 2: semantic() has been run
-				// 3: semantic2() has been run
-    int inuse;			// used to detect typedef cycles
-
-    TypedefDeclaration(Loc loc, Identifier *ident, Type *basetype, Initializer *init);
-    Dsymbol *syntaxCopy(Dsymbol *);
-    void semantic(Scope *sc);
-    void semantic2(Scope *sc);
-    char *mangle();
-    const char *kind();
-    Type *getType();
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-#ifdef _DH
-    Type *htype;
-    Type *hbasetype;
-#endif
-
-    void toDocBuffer(OutBuffer *buf);
-
-    void toObjFile(int multiobj);			// compile to .obj file
-    void toDebug();
-    int cvMember(unsigned char *p);
-
-    TypedefDeclaration *isTypedefDeclaration() { return this; }
-
-    Symbol *sinit;
-    Symbol *toInitializer();
-};
-
-/**************************************************************/
-
-struct AliasDeclaration : Declaration
-{
-    Dsymbol *aliassym;
-    Dsymbol *overnext;		// next in overload list
-    int inSemantic;
-
-    AliasDeclaration(Loc loc, Identifier *ident, Type *type);
-    AliasDeclaration(Loc loc, Identifier *ident, Dsymbol *s);
-    Dsymbol *syntaxCopy(Dsymbol *);
-    void semantic(Scope *sc);
-    int overloadInsert(Dsymbol *s);
-    const char *kind();
-    Type *getType();
-    Dsymbol *toAlias();
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-#ifdef _DH
-    Type *htype;
-    Dsymbol *haliassym;
-#endif
-
-    void toDocBuffer(OutBuffer *buf);
-
-    AliasDeclaration *isAliasDeclaration() { return this; }
-};
-
-/**************************************************************/
-
-struct VarDeclaration : Declaration
-{
-    Initializer *init;
-    unsigned offset;
-    int noauto;			// no auto semantics
-    FuncDeclarations nestedrefs; // referenced by these lexically nested functions
-    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
-    int canassign;		// it can be assigned to
-    Dsymbol *aliassym;		// if redone as alias to another symbol
-    Expression *value;		// when interpreting, this is the value
-				// (NULL if value not determinable)
-    Scope *scope;		// !=NULL means context to use
-
-    VarDeclaration(Loc loc, Type *t, Identifier *id, Initializer *init);
-    Dsymbol *syntaxCopy(Dsymbol *);
-    void semantic(Scope *sc);
-    void semantic2(Scope *sc);
-    const char *kind();
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-#ifdef _DH
-    Type *htype;
-    Initializer *hinit;
-#endif
-    int needThis();
-    int isImportedSymbol();
-    int isDataseg();
-    int hasPointers();
-    int canTakeAddressOf();
-    int needsAutoDtor();
-    Expression *callAutoDtor(Scope *sc);
-    ExpInitializer *getExpInitializer();
-    Expression *getConstInitializer();
-    void checkCtorConstInit();
-    void checkNestedReference(Scope *sc, Loc loc);
-    Dsymbol *toAlias();
-
-    Symbol *toSymbol();
-    void toObjFile(int multiobj);			// compile to .obj file
-    int cvMember(unsigned char *p);
-
-    // Eliminate need for dynamic_cast
-    VarDeclaration *isVarDeclaration() { return (VarDeclaration *)this; }
-
-    // LDC
-    AnonDeclaration* anonDecl;
-    unsigned offset2;
-    bool nakedUse;
-};
-
-/**************************************************************/
-
-// LDC uses this to denote static struct initializers
-
-struct StaticStructInitDeclaration : Declaration
-{
-    StructDeclaration *dsym;
-
-    StaticStructInitDeclaration(Loc loc, StructDeclaration *dsym);
-
-    Symbol *toSymbol();
-
-    // Eliminate need for dynamic_cast
-    StaticStructInitDeclaration *isStaticStructInitDeclaration() { return (StaticStructInitDeclaration *)this; }
-};
-
-struct ClassInfoDeclaration : VarDeclaration
-{
-    ClassDeclaration *cd;
-
-    ClassInfoDeclaration(ClassDeclaration *cd);
-    Dsymbol *syntaxCopy(Dsymbol *);
-    void semantic(Scope *sc);
-
-    void emitComment(Scope *sc);
-
-    Symbol *toSymbol();
-
-    ClassInfoDeclaration* isClassInfoDeclaration() { return this; }
-};
-
-struct ModuleInfoDeclaration : VarDeclaration
-{
-    Module *mod;
-
-    ModuleInfoDeclaration(Module *mod);
-    Dsymbol *syntaxCopy(Dsymbol *);
-    void semantic(Scope *sc);
-
-    void emitComment(Scope *sc);
-
-    Symbol *toSymbol();
-};
-
-struct TypeInfoDeclaration : VarDeclaration
-{
-    Type *tinfo;
-
-    TypeInfoDeclaration(Type *tinfo, int internal);
-    Dsymbol *syntaxCopy(Dsymbol *);
-    void semantic(Scope *sc);
-
-    void emitComment(Scope *sc);
-
-    Symbol *toSymbol();
-    void toObjFile(int multiobj);			// compile to .obj file
-    virtual void toDt(dt_t **pdt);
-
-    virtual TypeInfoDeclaration* isTypeInfoDeclaration() { return this; }
-
-    // LDC
-    virtual void llvmDeclare();
-    virtual void llvmDefine();
-};
-
-struct TypeInfoStructDeclaration : TypeInfoDeclaration
-{
-    TypeInfoStructDeclaration(Type *tinfo);
-
-    void toDt(dt_t **pdt);
-
-    // LDC
-    void llvmDeclare();
-    void llvmDefine();
-};
-
-struct TypeInfoClassDeclaration : TypeInfoDeclaration
-{
-    TypeInfoClassDeclaration(Type *tinfo);
-
-    void toDt(dt_t **pdt);
-
-    // LDC
-    void llvmDeclare();
-    void llvmDefine();
-};
-
-struct TypeInfoInterfaceDeclaration : TypeInfoDeclaration
-{
-    TypeInfoInterfaceDeclaration(Type *tinfo);
-
-    void toDt(dt_t **pdt);
-
-    // LDC
-    void llvmDeclare();
-    void llvmDefine();
-};
-
-struct TypeInfoTypedefDeclaration : TypeInfoDeclaration
-{
-    TypeInfoTypedefDeclaration(Type *tinfo);
-
-    void toDt(dt_t **pdt);
-
-    // LDC
-    void llvmDeclare();
-    void llvmDefine();
-};
-
-struct TypeInfoPointerDeclaration : TypeInfoDeclaration
-{
-    TypeInfoPointerDeclaration(Type *tinfo);
-
-    void toDt(dt_t **pdt);
-
-    // LDC
-    void llvmDeclare();
-    void llvmDefine();
-};
-
-struct TypeInfoArrayDeclaration : TypeInfoDeclaration
-{
-    TypeInfoArrayDeclaration(Type *tinfo);
-
-    void toDt(dt_t **pdt);
-
-    // LDC
-    void llvmDeclare();
-    void llvmDefine();
-};
-
-struct TypeInfoStaticArrayDeclaration : TypeInfoDeclaration
-{
-    TypeInfoStaticArrayDeclaration(Type *tinfo);
-
-    void toDt(dt_t **pdt);
-
-    // LDC
-    void llvmDeclare();
-    void llvmDefine();
-};
-
-struct TypeInfoAssociativeArrayDeclaration : TypeInfoDeclaration
-{
-    TypeInfoAssociativeArrayDeclaration(Type *tinfo);
-
-    void toDt(dt_t **pdt);
-
-    // LDC
-    void llvmDeclare();
-    void llvmDefine();
-};
-
-struct TypeInfoEnumDeclaration : TypeInfoDeclaration
-{
-    TypeInfoEnumDeclaration(Type *tinfo);
-
-    void toDt(dt_t **pdt);
-
-    // LDC
-    void llvmDeclare();
-    void llvmDefine();
-};
-
-struct TypeInfoFunctionDeclaration : TypeInfoDeclaration
-{
-    TypeInfoFunctionDeclaration(Type *tinfo);
-
-    void toDt(dt_t **pdt);
-
-    // LDC
-    void llvmDeclare();
-    void llvmDefine();
-};
-
-struct TypeInfoDelegateDeclaration : TypeInfoDeclaration
-{
-    TypeInfoDelegateDeclaration(Type *tinfo);
-
-    void toDt(dt_t **pdt);
-
-    // LDC
-    void llvmDeclare();
-    void llvmDefine();
-};
-
-struct TypeInfoTupleDeclaration : TypeInfoDeclaration
-{
-    TypeInfoTupleDeclaration(Type *tinfo);
-
-    void toDt(dt_t **pdt);
-
-    // LDC
-    void llvmDeclare();
-    void llvmDefine();
-};
-
-#if DMDV2
-struct TypeInfoConstDeclaration : TypeInfoDeclaration
-{
-    TypeInfoConstDeclaration(Type *tinfo);
-
-    void toDt(dt_t **pdt);
-
-    // LDC
-    void llvmDeclare();
-    void llvmDefine();
-};
-
-struct TypeInfoInvariantDeclaration : TypeInfoDeclaration
-{
-    TypeInfoInvariantDeclaration(Type *tinfo);
-
-    void toDt(dt_t **pdt);
-
-    // LDC
-    void llvmDeclare();
-    void llvmDefine();
-};
-#endif
-
-/**************************************************************/
-
-struct ThisDeclaration : VarDeclaration
-{
-    ThisDeclaration(Type *t);
-    Dsymbol *syntaxCopy(Dsymbol *);
-};
-
-enum ILS
-{
-    ILSuninitialized,	// not computed yet
-    ILSno,		// cannot inline
-    ILSyes,		// can inline
-};
-
-/**************************************************************/
-#if DMDV2
-
-enum BUILTIN
-{
-    BUILTINunknown = -1,	// not known if this is a builtin
-    BUILTINnot,			// this is not a builtin
-    BUILTINsin,			// std.math.sin
-    BUILTINcos,			// std.math.cos
-    BUILTINtan,			// std.math.tan
-    BUILTINsqrt,		// std.math.sqrt
-    BUILTINfabs,		// std.math.fabs
-};
-
-Expression *eval_builtin(enum BUILTIN builtin, Expressions *arguments);
-
-#endif
-
-struct FuncDeclaration : Declaration
-{
-    Array *fthrows;			// Array of Type's of exceptions (not used)
-    Statement *frequire;
-    Statement *fensure;
-    Statement *fbody;
-
-    Identifier *outId;			// identifier for out statement
-    VarDeclaration *vresult;		// variable corresponding to outId
-    LabelDsymbol *returnLabel;		// where the return goes
-
-    DsymbolTable *localsymtab;		// used to prevent symbols in different
-					// scopes from having the same name
-    VarDeclaration *vthis;		// 'this' parameter (member and nested)
-    VarDeclaration *v_arguments;	// '_arguments' parameter
-#if IN_GCC
-    VarDeclaration *v_argptr;	        // '_argptr' variable
-#endif
-    Dsymbols *parameters;		// Array of VarDeclaration's for parameters
-    DsymbolTable *labtab;		// statement label symbol table
-    Declaration *overnext;		// next in overload list
-    Loc endloc;				// location of closing curly bracket
-    int vtblIndex;			// for member functions, index into vtbl[]
-    int naked;				// !=0 if naked
-    int inlineAsm;			// !=0 if has inline assembler
-    ILS inlineStatus;
-    int inlineNest;			// !=0 if nested inline
-    int cantInterpret;			// !=0 if cannot interpret function
-    int semanticRun;			// !=0 if semantic3() had been run
-					// this function's frame ptr
-    ForeachStatement *fes;		// if foreach body, this is the foreach
-    int introducing;			// !=0 if 'introducing' function
-    Type *tintro;			// if !=NULL, then this is the type
-					// of the 'introducing' function
-					// this one is overriding
-    int inferRetType;			// !=0 if return type is to be inferred
-    Scope *scope;			// !=NULL means context to use
-
-    // Things that should really go into Scope
-    int hasReturnExp;			// 1 if there's a return exp; statement
-					// 2 if there's a throw statement
-					// 4 if there's an assert(0)
-					// 8 if there's inline asm
-
-    // Support for NRVO (named return value optimization)
-    int nrvo_can;			// !=0 means we can do it
-    VarDeclaration *nrvo_var;		// variable to replace with shidden
-    Symbol *shidden;			// hidden pointer passed to function
-
-#if DMDV2
-    enum BUILTIN builtin;		// set if this is a known, builtin
-					// function we can evaluate at compile
-					// time
-
-    int tookAddressOf;			// set if someone took the address of
-					// this function
-    Dsymbols closureVars;		// local variables in this function
-					// which are referenced by nested
-					// functions
-#else
-    int nestedFrameRef;			// !=0 if nested variables referenced
-#endif
-
-    FuncDeclaration(Loc loc, Loc endloc, Identifier *id, enum STC storage_class, Type *type);
-    Dsymbol *syntaxCopy(Dsymbol *);
-    void semantic(Scope *sc);
-    void semantic2(Scope *sc);
-    void semantic3(Scope *sc);
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-    void bodyToCBuffer(OutBuffer *buf, HdrGenState *hgs);
-    int overrides(FuncDeclaration *fd);
-    int findVtblIndex(Array *vtbl, int dim);
-    int overloadInsert(Dsymbol *s);
-    FuncDeclaration *overloadExactMatch(Type *t);
-    FuncDeclaration *overloadResolve(Loc loc, Expression *ethis, Expressions *arguments, int flags = 0);
-    MATCH leastAsSpecialized(FuncDeclaration *g);
-    LabelDsymbol *searchLabel(Identifier *ident);
-    AggregateDeclaration *isThis();
-    AggregateDeclaration *isMember2();
-    int getLevel(Loc loc, FuncDeclaration *fd);	// lexical nesting level difference
-    void appendExp(Expression *e);
-    void appendState(Statement *s);
-    char *mangle();
-    int isMain();
-    int isWinMain();
-    int isDllMain();
-    enum BUILTIN isBuiltin();
-    int isExport();
-    int isImportedSymbol();
-    int isAbstract();
-    int isCodeseg();
-    int isOverloadable();
-    virtual int isNested();
-    int needThis();
-    virtual int isVirtual();
-    virtual int isFinal();
-    virtual int addPreInvariant();
-    virtual int addPostInvariant();
-    Expression *interpret(InterState *istate, Expressions *arguments);
-    void inlineScan();
-    int canInline(int hasthis, int hdrscan = 0);
-    Expression *doInline(InlineScanState *iss, Expression *ethis, Array *arguments);
-    const char *kind();
-    void toDocBuffer(OutBuffer *buf);
-    FuncDeclaration *isUnique();
-    int needsClosure();
-
-// LDC: give argument types to runtime functions
-    static FuncDeclaration *genCfunc(Arguments *args, Type *treturn, const char *name);
-    static FuncDeclaration *genCfunc(Arguments *args, Type *treturn, Identifier *id);
-
-    Symbol *toSymbol();
-    Symbol *toThunkSymbol(int offset);	// thunk version
-    void toObjFile(int multiobj);			// compile to .obj file
-    int cvMember(unsigned char *p);
-    void buildClosure(IRState *irs);
-
-    FuncDeclaration *isFuncDeclaration() { return this; }
-
-    // LDC stuff
-
-    // vars declared in this function that nested funcs reference
-    // is this is not empty, nestedFrameRef is set and these VarDecls
-    // probably have nestedref set too, see VarDeclaration::checkNestedReference
-    std::set<VarDeclaration*> nestedVars;
-
-    std::string intrinsicName;
-
-    bool isIntrinsic();
-    bool isVaIntrinsic();
-
-    // we keep our own table of label statements as LabelDsymbolS
-    // don't always carry their corresponding statement along ...
-    typedef std::map<const char*, LabelStatement*> LabelMap;
-    LabelMap labmap;
-
-    // if this is an array operation it gets a little special attention
-    bool isArrayOp;
-
-    // true if overridden with the pragma(allow_inline); stmt
-    bool allowInlining;
-};
-
-struct FuncAliasDeclaration : FuncDeclaration
-{
-    FuncDeclaration *funcalias;
-
-    FuncAliasDeclaration(FuncDeclaration *funcalias);
-
-    FuncAliasDeclaration *isFuncAliasDeclaration() { return this; }
-    const char *kind();
-    Symbol *toSymbol();
-};
-
-struct FuncLiteralDeclaration : FuncDeclaration
-{
-    enum TOK tok;			// TOKfunction or TOKdelegate
-
-    FuncLiteralDeclaration(Loc loc, Loc endloc, Type *type, enum TOK tok,
-	ForeachStatement *fes);
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-    Dsymbol *syntaxCopy(Dsymbol *);
-    int isNested();
-    int isVirtual();
-
-    FuncLiteralDeclaration *isFuncLiteralDeclaration() { return this; }
-    const char *kind();
-};
-
-struct CtorDeclaration : FuncDeclaration
-{   Arguments *arguments;
-    int varargs;
-
-    CtorDeclaration(Loc loc, Loc endloc, Arguments *arguments, int varargs);
-    Dsymbol *syntaxCopy(Dsymbol *);
-    void semantic(Scope *sc);
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-    const char *kind();
-    char *toChars();
-    int isVirtual();
-    int addPreInvariant();
-    int addPostInvariant();
-    void toDocBuffer(OutBuffer *buf);
-
-    CtorDeclaration *isCtorDeclaration() { return this; }
-};
-
-#if DMDV2
-struct PostBlitDeclaration : FuncDeclaration
-{
-    PostBlitDeclaration(Loc loc, Loc endloc);
-    PostBlitDeclaration(Loc loc, Loc endloc, Identifier *id);
-    Dsymbol *syntaxCopy(Dsymbol *);
-    void semantic(Scope *sc);
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-    int isVirtual();
-    int addPreInvariant();
-    int addPostInvariant();
-    int overloadInsert(Dsymbol *s);
-    void emitComment(Scope *sc);
-
-    PostBlitDeclaration *isPostBlitDeclaration() { return this; }
-};
-#endif
-
-struct DtorDeclaration : FuncDeclaration
-{
-    DtorDeclaration(Loc loc, Loc endloc);
-    DtorDeclaration(Loc loc, Loc endloc, Identifier *id);
-    Dsymbol *syntaxCopy(Dsymbol *);
-    void semantic(Scope *sc);
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-    int isVirtual();
-    int addPreInvariant();
-    int addPostInvariant();
-    int overloadInsert(Dsymbol *s);
-    void emitComment(Scope *sc);
-
-    DtorDeclaration *isDtorDeclaration() { return this; }
-};
-
-struct StaticCtorDeclaration : FuncDeclaration
-{
-    StaticCtorDeclaration(Loc loc, Loc endloc);
-    Dsymbol *syntaxCopy(Dsymbol *);
-    void semantic(Scope *sc);
-    AggregateDeclaration *isThis();
-    int isStaticConstructor();
-    int isVirtual();
-    int addPreInvariant();
-    int addPostInvariant();
-    void emitComment(Scope *sc);
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-
-    StaticCtorDeclaration *isStaticCtorDeclaration() { return this; }
-};
-
-struct StaticDtorDeclaration : FuncDeclaration
-{   VarDeclaration *vgate;	// 'gate' variable
-
-    StaticDtorDeclaration(Loc loc, Loc endloc);
-    Dsymbol *syntaxCopy(Dsymbol *);
-    void semantic(Scope *sc);
-    AggregateDeclaration *isThis();
-    int isStaticDestructor();
-    int isVirtual();
-    int addPreInvariant();
-    int addPostInvariant();
-    void emitComment(Scope *sc);
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-
-    StaticDtorDeclaration *isStaticDtorDeclaration() { return this; }
-};
-
-struct InvariantDeclaration : FuncDeclaration
-{
-    InvariantDeclaration(Loc loc, Loc endloc);
-    Dsymbol *syntaxCopy(Dsymbol *);
-    void semantic(Scope *sc);
-    int isVirtual();
-    int addPreInvariant();
-    int addPostInvariant();
-    void emitComment(Scope *sc);
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-
-    InvariantDeclaration *isInvariantDeclaration() { return this; }
-};
-
-
-struct UnitTestDeclaration : FuncDeclaration
-{
-    UnitTestDeclaration(Loc loc, Loc endloc);
-    Dsymbol *syntaxCopy(Dsymbol *);
-    void semantic(Scope *sc);
-    AggregateDeclaration *isThis();
-    int isVirtual();
-    int addPreInvariant();
-    int addPostInvariant();
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-
-    UnitTestDeclaration *isUnitTestDeclaration() { return this; }
-};
-
-struct NewDeclaration : FuncDeclaration
-{   Arguments *arguments;
-    int varargs;
-
-    NewDeclaration(Loc loc, Loc endloc, Arguments *arguments, int varargs);
-    Dsymbol *syntaxCopy(Dsymbol *);
-    void semantic(Scope *sc);
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-    const char *kind();
-    int isVirtual();
-    int addPreInvariant();
-    int addPostInvariant();
-
-    NewDeclaration *isNewDeclaration() { return this; }
-};
-
-
-struct DeleteDeclaration : FuncDeclaration
-{   Arguments *arguments;
-
-    DeleteDeclaration(Loc loc, Loc endloc, Arguments *arguments);
-    Dsymbol *syntaxCopy(Dsymbol *);
-    void semantic(Scope *sc);
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-    const char *kind();
-    int isDelete();
-    int isVirtual();
-    int addPreInvariant();
-    int addPostInvariant();
-#ifdef _DH
-    DeleteDeclaration *isDeleteDeclaration() { return this; }
-#endif
-};
-
-#endif /* DMD_DECLARATION_H */
+
+// Compiler implementation of the D programming language
+// Copyright (c) 1999-2008 by Digital Mars
+// All Rights Reserved
+// written by Walter Bright
+// http://www.digitalmars.com
+// License for redistribution is by either the Artistic License
+// in artistic.txt, or the GNU General Public License in gnu.txt.
+// See the included readme.txt for details.
+
+#ifndef DMD_DECLARATION_H
+#define DMD_DECLARATION_H
+
+#ifdef __DMC__
+#pragma once
+#endif /* __DMC__ */
+
+#if IN_LLVM
+#include <set>
+#include <map>
+#include <string>
+#endif
+
+#include "dsymbol.h"
+#include "lexer.h"
+#include "mtype.h"
+
+struct Expression;
+struct Statement;
+struct LabelDsymbol;
+#if IN_LLVM
+struct LabelStatement;
+#endif
+struct Initializer;
+struct Module;
+struct InlineScanState;
+struct ForeachStatement;
+struct FuncDeclaration;
+struct ExpInitializer;
+struct StructDeclaration;
+struct TupleType;
+struct InterState;
+struct IRState;
+#if IN_LLVM
+struct AnonDeclaration;
+#endif
+
+enum PROT;
+enum LINK;
+enum TOK;
+enum MATCH;
+
+enum STC
+{
+    STCundefined    = 0,
+    STCstatic	    = 1,
+    STCextern	    = 2,
+    STCconst	    = 4,
+    STCfinal	    = 8,
+    STCabstract     = 0x10,
+    STCparameter    = 0x20,
+    STCfield	    = 0x40,
+    STCoverride	    = 0x80,
+    STCauto         = 0x100,
+    STCsynchronized = 0x200,
+    STCdeprecated   = 0x400,
+    STCin           = 0x800,		// in parameter
+    STCout          = 0x1000,		// out parameter
+    STClazy	    = 0x2000,		// lazy parameter
+    STCforeach      = 0x4000,		// variable for foreach loop
+    STCcomdat       = 0x8000,		// should go into COMDAT record
+    STCvariadic     = 0x10000,		// variadic function argument
+    STCctorinit     = 0x20000,		// can only be set inside constructor
+    STCtemplateparameter = 0x40000,	// template parameter
+    STCscope	    = 0x80000,		// template parameter
+    STCinvariant    = 0x100000,
+    STCimmutable    = 0x100000,
+    STCref	    = 0x200000,
+    STCinit	    = 0x400000,		// has explicit initializer
+    STCmanifest	    = 0x800000,		// manifest constant
+    STCnodtor	    = 0x1000000,	// don't run destructor
+    STCnothrow	    = 0x2000000,	// never throws exceptions
+    STCpure	    = 0x4000000,	// pure function
+    STCtls	    = 0x8000000,	// thread local
+    STCalias	    = 0x10000000,	// alias parameter
+    STCshared       = 0x20000000,	// accessible from multiple threads
+    STCgshared      = 0x40000000,	// accessible from multiple threads
+					// but not typed as "shared"
+    STC_TYPECTOR    = (STCconst | STCimmutable | STCshared),
+};
+
+struct Match
+{
+    int count;			// number of matches found
+    MATCH last;			// match level of lastf
+    FuncDeclaration *lastf;	// last matching function we found
+    FuncDeclaration *nextf;	// current matching function
+    FuncDeclaration *anyf;	// pick a func, any func, to use for error recovery
+};
+
+void overloadResolveX(Match *m, FuncDeclaration *f,
+	Expression *ethis, Expressions *arguments, Module* from);
+int overloadApply(Module* from, FuncDeclaration *fstart,
+	int (*fp)(void *, FuncDeclaration *),
+	void *param);
+
+/**************************************************************/
+
+struct Declaration : Dsymbol
+{
+    Type *type;
+    Type *originalType;		// before semantic analysis
+    unsigned storage_class;
+    enum PROT protection;
+    enum LINK linkage;
+    int inuse;			// used to detect cycles
+
+    Declaration(Identifier *id);
+    void semantic(Scope *sc);
+    const char *kind();
+    unsigned size(Loc loc);
+    void checkModify(Loc loc, Scope *sc, Type *t);
+
+    void emitComment(Scope *sc);
+    void toDocBuffer(OutBuffer *buf);
+
+    char *mangle();
+    int isStatic() { return storage_class & STCstatic; }
+    virtual int isStaticConstructor();
+    virtual int isStaticDestructor();
+    virtual int isDelete();
+    virtual int isDataseg();
+    virtual int isThreadlocal();
+    virtual int isCodeseg();
+    int isCtorinit()     { return storage_class & STCctorinit; }
+    int isFinal()        { return storage_class & STCfinal; }
+    int isAbstract()     { return storage_class & STCabstract; }
+    int isConst()        { return storage_class & STCconst; }
+    int isInvariant()    { return storage_class & STCinvariant; }
+    int isAuto()         { return storage_class & STCauto; }
+    int isScope()        { return storage_class & (STCscope | STCauto); }
+    int isSynchronized() { return storage_class & STCsynchronized; }
+    int isParameter()    { return storage_class & STCparameter; }
+    int isDeprecated()   { return storage_class & STCdeprecated; }
+    int isOverride()     { return storage_class & STCoverride; }
+
+    int isIn()    { return storage_class & STCin; }
+    int isOut()   { return storage_class & STCout; }
+    int isRef()   { return storage_class & STCref; }
+
+    enum PROT prot();
+
+    Declaration *isDeclaration() { return this; }
+
+#if IN_LLVM
+    /// Codegen traversal
+    virtual void codegen(Ir* ir);
+#endif
+};
+
+/**************************************************************/
+
+struct TupleDeclaration : Declaration
+{
+    Objects *objects;
+    int isexp;			// 1: expression tuple
+
+    TypeTuple *tupletype;	// !=NULL if this is a type tuple
+
+    TupleDeclaration(Loc loc, Identifier *ident, Objects *objects);
+    Dsymbol *syntaxCopy(Dsymbol *);
+    const char *kind();
+    Type *getType();
+    int needThis();
+
+    TupleDeclaration *isTupleDeclaration() { return this; }
+
+#if IN_LLVM
+    /// Codegen traversal
+    void codegen(Ir* ir);
+#endif
+};
+
+/**************************************************************/
+
+struct TypedefDeclaration : Declaration
+{
+    Type *basetype;
+    Initializer *init;
+    int sem;			// 0: semantic() has not been run
+				// 1: semantic() is in progress
+				// 2: semantic() has been run
+				// 3: semantic2() has been run
+
+    TypedefDeclaration(Loc loc, Identifier *ident, Type *basetype, Initializer *init);
+    Dsymbol *syntaxCopy(Dsymbol *);
+    void semantic(Scope *sc);
+    void semantic2(Scope *sc);
+    char *mangle();
+    const char *kind();
+    Type *getType();
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+#ifdef _DH
+    Type *htype;
+    Type *hbasetype;
+#endif
+
+    void toDocBuffer(OutBuffer *buf);
+
+#if IN_DMD
+    void toObjFile(int multiobj);			// compile to .obj file
+    void toDebug();
+    int cvMember(unsigned char *p);
+#endif
+
+    TypedefDeclaration *isTypedefDeclaration() { return this; }
+
+#if IN_DMD
+    Symbol *sinit;
+    Symbol *toInitializer();
+#endif
+
+#if IN_LLVM
+    /// Codegen traversal
+    void codegen(Ir* ir);
+#endif
+};
+
+/**************************************************************/
+
+struct AliasDeclaration : Declaration
+{
+    Dsymbol *aliassym;
+    Dsymbol *overnext;		// next in overload list
+    int inSemantic;
+    PROT importprot;	// if generated by import, store its protection
+
+    AliasDeclaration(Loc loc, Identifier *ident, Type *type);
+    AliasDeclaration(Loc loc, Identifier *ident, Dsymbol *s);
+    Dsymbol *syntaxCopy(Dsymbol *);
+    void semantic(Scope *sc);
+    int overloadInsert(Dsymbol *s);
+    const char *kind();
+    Type *getType();
+    Dsymbol *toAlias();
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+#ifdef _DH
+    Type *htype;
+    Dsymbol *haliassym;
+#endif
+
+    void toDocBuffer(OutBuffer *buf);
+
+    AliasDeclaration *isAliasDeclaration() { return this; }
+};
+
+/**************************************************************/
+
+struct VarDeclaration : Declaration
+{
+    Initializer *init;
+    unsigned offset;
+    int noauto;			// no auto semantics
+    FuncDeclarations nestedrefs; // referenced by these lexically nested functions
+    int ctorinit;		// it has been initialized in a ctor
+    int onstack;		// 1: it has been allocated on the stack
+				// 2: on stack, run destructor anyway
+    int canassign;		// it can be assigned to
+    Dsymbol *aliassym;		// if redone as alias to another symbol
+    Expression *value;		// when interpreting, this is the value
+				// (NULL if value not determinable)
+    Scope *scope;		// !=NULL means context to use
+
+    VarDeclaration(Loc loc, Type *t, Identifier *id, Initializer *init);
+    Dsymbol *syntaxCopy(Dsymbol *);
+    void semantic(Scope *sc);
+    void semantic2(Scope *sc);
+    const char *kind();
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+#ifdef _DH
+    Type *htype;
+    Initializer *hinit;
+#endif
+    int needThis();
+    int isImportedSymbol();
+    int isDataseg();
+    int isThreadlocal();
+    int hasPointers();
+    int canTakeAddressOf();
+    int needsAutoDtor();
+    Expression *callAutoDtor(Scope *sc);
+    ExpInitializer *getExpInitializer();
+    Expression *getConstInitializer();
+    void checkCtorConstInit();
+    void checkNestedReference(Scope *sc, Loc loc);
+    Dsymbol *toAlias();
+
+#if IN_DMD
+    void toObjFile(int multiobj);			// compile to .obj file
+    Symbol *toSymbol();
+    int cvMember(unsigned char *p);
+#endif
+
+    // Eliminate need for dynamic_cast
+    VarDeclaration *isVarDeclaration() { return (VarDeclaration *)this; }
+
+#if IN_LLVM
+    /// Codegen traversal
+    virtual void codegen(Ir* ir);
+
+    /// Index into parent aggregate.
+    /// Set during type generation.
+    unsigned aggrIndex;
+
+    // FIXME: we're not using these anymore!
+    AnonDeclaration* anonDecl;
+    unsigned offset2;
+
+    /// This var is used by a naked function.
+    bool nakedUse;
+#endif
+};
+
+/**************************************************************/
+
+// LDC uses this to denote static struct initializers
+
+struct StaticStructInitDeclaration : Declaration
+{
+    StructDeclaration *dsym;
+
+    StaticStructInitDeclaration(Loc loc, StructDeclaration *dsym);
+
+#if IN_DMD
+    Symbol *toSymbol();
+#endif
+
+    // Eliminate need for dynamic_cast
+    StaticStructInitDeclaration *isStaticStructInitDeclaration() { return (StaticStructInitDeclaration *)this; }
+};
+
+struct ClassInfoDeclaration : VarDeclaration
+{
+    ClassDeclaration *cd;
+
+    ClassInfoDeclaration(ClassDeclaration *cd);
+    Dsymbol *syntaxCopy(Dsymbol *);
+    void semantic(Scope *sc);
+
+    void emitComment(Scope *sc);
+
+#if IN_DMD
+    Symbol *toSymbol();
+#endif
+
+    ClassInfoDeclaration* isClassInfoDeclaration() { return this; }
+};
+
+struct ModuleInfoDeclaration : VarDeclaration
+{
+    Module *mod;
+
+    ModuleInfoDeclaration(Module *mod);
+    Dsymbol *syntaxCopy(Dsymbol *);
+    void semantic(Scope *sc);
+
+    void emitComment(Scope *sc);
+
+#if IN_DMD
+    Symbol *toSymbol();
+#endif
+};
+
+struct TypeInfoDeclaration : VarDeclaration
+{
+    Type *tinfo;
+
+    TypeInfoDeclaration(Type *tinfo, int internal);
+    Dsymbol *syntaxCopy(Dsymbol *);
+    void semantic(Scope *sc);
+
+    void emitComment(Scope *sc);
+
+#if IN_DMD
+    void toObjFile(int multiobj);			// compile to .obj file
+    Symbol *toSymbol();
+    virtual void toDt(dt_t **pdt);
+#endif
+
+    virtual TypeInfoDeclaration* isTypeInfoDeclaration() { return this; }
+
+#if IN_LLVM
+    /// Codegen traversal
+    void codegen(Ir* ir);
+    virtual void llvmDefine();
+#endif
+};
+
+struct TypeInfoStructDeclaration : TypeInfoDeclaration
+{
+    TypeInfoStructDeclaration(Type *tinfo);
+
+#if IN_DMD
+    void toDt(dt_t **pdt);
+#endif
+
+#if IN_LLVM
+    void llvmDefine();
+#endif
+};
+
+struct TypeInfoClassDeclaration : TypeInfoDeclaration
+{
+    TypeInfoClassDeclaration(Type *tinfo);
+
+#if IN_DMD
+    void toDt(dt_t **pdt);
+#endif
+
+#if IN_LLVM
+    void llvmDefine();
+#endif
+};
+
+struct TypeInfoInterfaceDeclaration : TypeInfoDeclaration
+{
+    TypeInfoInterfaceDeclaration(Type *tinfo);
+
+#if IN_DMD
+    void toDt(dt_t **pdt);
+#endif
+
+#if IN_LLVM
+    void llvmDefine();
+#endif
+};
+
+struct TypeInfoTypedefDeclaration : TypeInfoDeclaration
+{
+    TypeInfoTypedefDeclaration(Type *tinfo);
+
+#if IN_DMD
+    void toDt(dt_t **pdt);
+#endif
+
+#if IN_LLVM
+    void llvmDefine();
+#endif
+};
+
+struct TypeInfoPointerDeclaration : TypeInfoDeclaration
+{
+    TypeInfoPointerDeclaration(Type *tinfo);
+
+#if IN_DMD
+    void toDt(dt_t **pdt);
+#endif
+
+#if IN_LLVM
+    void llvmDefine();
+#endif
+};
+
+struct TypeInfoArrayDeclaration : TypeInfoDeclaration
+{
+    TypeInfoArrayDeclaration(Type *tinfo);
+
+#if IN_DMD
+    void toDt(dt_t **pdt);
+#endif
+
+#if IN_LLVM
+    void llvmDefine();
+#endif
+};
+
+struct TypeInfoStaticArrayDeclaration : TypeInfoDeclaration
+{
+    TypeInfoStaticArrayDeclaration(Type *tinfo);
+
+#if IN_DMD
+    void toDt(dt_t **pdt);
+#endif
+
+#if IN_LLVM
+    void llvmDefine();
+#endif
+};
+
+struct TypeInfoAssociativeArrayDeclaration : TypeInfoDeclaration
+{
+    TypeInfoAssociativeArrayDeclaration(Type *tinfo);
+
+#if IN_DMD
+    void toDt(dt_t **pdt);
+#endif
+
+#if IN_LLVM
+    void llvmDefine();
+#endif
+};
+
+struct TypeInfoEnumDeclaration : TypeInfoDeclaration
+{
+    TypeInfoEnumDeclaration(Type *tinfo);
+
+#if IN_DMD
+    void toDt(dt_t **pdt);
+#endif
+
+#if IN_LLVM
+    void llvmDefine();
+#endif
+};
+
+struct TypeInfoFunctionDeclaration : TypeInfoDeclaration
+{
+    TypeInfoFunctionDeclaration(Type *tinfo);
+
+#if IN_DMD
+    void toDt(dt_t **pdt);
+#endif
+
+#if IN_LLVM
+    void llvmDefine();
+#endif
+};
+
+struct TypeInfoDelegateDeclaration : TypeInfoDeclaration
+{
+    TypeInfoDelegateDeclaration(Type *tinfo);
+
+#if IN_DMD
+    void toDt(dt_t **pdt);
+#endif
+
+#if IN_LLVM
+    void llvmDefine();
+#endif
+};
+
+struct TypeInfoTupleDeclaration : TypeInfoDeclaration
+{
+    TypeInfoTupleDeclaration(Type *tinfo);
+
+#if IN_DMD
+    void toDt(dt_t **pdt);
+#endif
+
+#if IN_LLVM
+    void llvmDefine();
+#endif
+};
+
+#if DMDV2
+struct TypeInfoConstDeclaration : TypeInfoDeclaration
+{
+    TypeInfoConstDeclaration(Type *tinfo);
+
+#if IN_DMD
+    void toDt(dt_t **pdt);
+#endif
+
+#if IN_LLVM
+    void llvmDefine();
+#endif
+};
+
+struct TypeInfoInvariantDeclaration : TypeInfoDeclaration
+{
+    TypeInfoInvariantDeclaration(Type *tinfo);
+
+#if IN_DMD
+    void toDt(dt_t **pdt);
+#endif
+
+#if IN_LLVM
+    void llvmDefine();
+#endif
+};
+
+struct TypeInfoSharedDeclaration : TypeInfoDeclaration
+{
+    TypeInfoSharedDeclaration(Type *tinfo);
+
+#if IN_DMD
+    void toDt(dt_t **pdt);
+#endif
+};
+#endif
+
+/**************************************************************/
+
+struct ThisDeclaration : VarDeclaration
+{
+    ThisDeclaration(Loc loc, Type *t);
+    Dsymbol *syntaxCopy(Dsymbol *);
+    ThisDeclaration *isThisDeclaration() { return this; }
+};
+
+enum ILS
+{
+    ILSuninitialized,	// not computed yet
+    ILSno,		// cannot inline
+    ILSyes,		// can inline
+};
+
+/**************************************************************/
+#if DMDV2
+
+enum BUILTIN
+{
+    BUILTINunknown = -1,	// not known if this is a builtin
+    BUILTINnot,			// this is not a builtin
+    BUILTINsin,			// std.math.sin
+    BUILTINcos,			// std.math.cos
+    BUILTINtan,			// std.math.tan
+    BUILTINsqrt,		// std.math.sqrt
+    BUILTINfabs,		// std.math.fabs
+};
+
+Expression *eval_builtin(enum BUILTIN builtin, Expressions *arguments);
+
+#endif
+
+struct FuncDeclaration : Declaration
+{
+    Array *fthrows;			// Array of Type's of exceptions (not used)
+    Statement *frequire;
+    Statement *fensure;
+    Statement *fbody;
+
+    Identifier *outId;			// identifier for out statement
+    VarDeclaration *vresult;		// variable corresponding to outId
+    LabelDsymbol *returnLabel;		// where the return goes
+
+    DsymbolTable *localsymtab;		// used to prevent symbols in different
+					// scopes from having the same name
+    VarDeclaration *vthis;		// 'this' parameter (member and nested)
+    VarDeclaration *v_arguments;	// '_arguments' parameter
+#if IN_GCC
+    VarDeclaration *v_argptr;	        // '_argptr' variable
+#endif
+    Dsymbols *parameters;		// Array of VarDeclaration's for parameters
+    DsymbolTable *labtab;		// statement label symbol table
+    Declaration *overnext;		// next in overload list
+    Loc endloc;				// location of closing curly bracket
+    int vtblIndex;			// for member functions, index into vtbl[]
+    int naked;				// !=0 if naked
+    int inlineAsm;			// !=0 if has inline assembler
+    ILS inlineStatus;
+    int inlineNest;			// !=0 if nested inline
+    int cantInterpret;			// !=0 if cannot interpret function
+    int semanticRun;			// 1 semantic() run
+					// 2 semantic2() run
+					// 3 semantic3() started
+					// 4 semantic3() done
+					// 5 toObjFile() run
+					// this function's frame ptr
+    ForeachStatement *fes;		// if foreach body, this is the foreach
+    int introducing;			// !=0 if 'introducing' function
+    Type *tintro;			// if !=NULL, then this is the type
+					// of the 'introducing' function
+					// this one is overriding
+    int inferRetType;			// !=0 if return type is to be inferred
+    Scope *scope;			// !=NULL means context to use
+
+    // Things that should really go into Scope
+    int hasReturnExp;			// 1 if there's a return exp; statement
+					// 2 if there's a throw statement
+					// 4 if there's an assert(0)
+					// 8 if there's inline asm
+
+    // Support for NRVO (named return value optimization)
+    int nrvo_can;			// !=0 means we can do it
+    VarDeclaration *nrvo_var;		// variable to replace with shidden
+#if IN_DMD
+    Symbol *shidden;			// hidden pointer passed to function
+#endif
+
+#if DMDV2
+    enum BUILTIN builtin;		// set if this is a known, builtin
+					// function we can evaluate at compile
+					// time
+
+    int tookAddressOf;			// set if someone took the address of
+					// this function
+    Dsymbols closureVars;		// local variables in this function
+					// which are referenced by nested
+					// functions
+#else
+    int nestedFrameRef;			// !=0 if nested variables referenced
+#endif
+
+    FuncDeclaration(Loc loc, Loc endloc, Identifier *id, enum STC storage_class, Type *type);
+    Dsymbol *syntaxCopy(Dsymbol *);
+    void semantic(Scope *sc);
+    void semantic2(Scope *sc);
+    void semantic3(Scope *sc);
+    // called from semantic3
+    void varArgs(Scope *sc, TypeFunction*, VarDeclaration *&, VarDeclaration *&);
+
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+    void bodyToCBuffer(OutBuffer *buf, HdrGenState *hgs);
+    int overrides(FuncDeclaration *fd);
+    int findVtblIndex(Array *vtbl, int dim);
+    int overloadInsert(Dsymbol *s);
+    FuncDeclaration *overloadExactMatch(Type *t, Module* from);
+    FuncDeclaration *overloadResolve(Loc loc, Expression *ethis, Expressions *arguments, int flags = 0, Module* from=NULL);
+    MATCH leastAsSpecialized(FuncDeclaration *g);
+    LabelDsymbol *searchLabel(Identifier *ident);
+    AggregateDeclaration *isThis();
+    AggregateDeclaration *isMember2();
+    int getLevel(Loc loc, FuncDeclaration *fd);	// lexical nesting level difference
+    void appendExp(Expression *e);
+    void appendState(Statement *s);
+    char *mangle();
+    int isMain();
+    int isWinMain();
+    int isDllMain();
+    enum BUILTIN isBuiltin();
+    int isExport();
+    int isImportedSymbol();
+    int isAbstract();
+    int isCodeseg();
+    int isOverloadable();
+    int isPure();
+    virtual int isNested();
+    int needThis();
+    virtual int isVirtual();
+    virtual int isFinal();
+    virtual int addPreInvariant();
+    virtual int addPostInvariant();
+    Expression *interpret(InterState *istate, Expressions *arguments);
+    void inlineScan();
+    int canInline(int hasthis, int hdrscan = 0);
+    Expression *doInline(InlineScanState *iss, Expression *ethis, Array *arguments);
+    const char *kind();
+    void toDocBuffer(OutBuffer *buf);
+    FuncDeclaration *isUnique();
+    int needsClosure();
+
+// LDC: give argument types to runtime functions
+    static FuncDeclaration *genCfunc(Arguments *args, Type *treturn, const char *name);
+    static FuncDeclaration *genCfunc(Arguments *args, Type *treturn, Identifier *id);
+
+#if IN_DMD
+    Symbol *toSymbol();
+    Symbol *toThunkSymbol(int offset);	// thunk version
+    void toObjFile(int multiobj);			// compile to .obj file
+    int cvMember(unsigned char *p);
+    void buildClosure(IRState *irs); // Should this be inside or outside the #if IN_DMD?
+#endif
+    FuncDeclaration *isFuncDeclaration() { return this; }
+
+#if IN_LLVM
+    // LDC stuff
+
+    /// Codegen traversal
+    void codegen(Ir* ir);
+
+    // vars declared in this function that nested funcs reference
+    // is this is not empty, nestedFrameRef is set and these VarDecls
+    // probably have nestedref set too, see VarDeclaration::checkNestedReference
+    std::set<VarDeclaration*> nestedVars;
+
+    std::string intrinsicName;
+
+    bool isIntrinsic();
+    bool isVaIntrinsic();
+
+    // we keep our own table of label statements as LabelDsymbolS
+    // don't always carry their corresponding statement along ...
+    typedef std::map<const char*, LabelStatement*> LabelMap;
+    LabelMap labmap;
+
+    // if this is an array operation it gets a little special attention
+    bool isArrayOp;
+
+    // true if overridden with the pragma(allow_inline); stmt
+    bool allowInlining;
+#endif
+};
+
+FuncDeclaration *resolveFuncCall(Scope *sc, Loc loc, Dsymbol *s,
+	Objects *tiargs,
+	Expression *ethis,
+	Expressions *arguments,
+	int flags);
+
+
+struct FuncAliasDeclaration : FuncDeclaration
+{
+    FuncDeclaration *funcalias;
+    PROT importprot;	// if generated by import, store its protection
+    
+    FuncAliasDeclaration(FuncDeclaration *funcalias);
+
+    FuncAliasDeclaration *isFuncAliasDeclaration() { return this; }
+    const char *kind();
+#if IN_DMD
+    Symbol *toSymbol();
+#endif
+};
+
+struct FuncLiteralDeclaration : FuncDeclaration
+{
+    enum TOK tok;			// TOKfunction or TOKdelegate
+
+    FuncLiteralDeclaration(Loc loc, Loc endloc, Type *type, enum TOK tok,
+	ForeachStatement *fes);
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+    Dsymbol *syntaxCopy(Dsymbol *);
+    int isNested();
+    int isVirtual();
+
+    FuncLiteralDeclaration *isFuncLiteralDeclaration() { return this; }
+    const char *kind();
+};
+
+struct CtorDeclaration : FuncDeclaration
+{   Arguments *arguments;
+    int varargs;
+
+    CtorDeclaration(Loc loc, Loc endloc, Arguments *arguments, int varargs);
+    Dsymbol *syntaxCopy(Dsymbol *);
+    void semantic(Scope *sc);
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+    const char *kind();
+    char *toChars();
+    int isVirtual();
+    int addPreInvariant();
+    int addPostInvariant();
+    void toDocBuffer(OutBuffer *buf);
+
+    CtorDeclaration *isCtorDeclaration() { return this; }
+};
+
+#if DMDV2
+struct PostBlitDeclaration : FuncDeclaration
+{
+    PostBlitDeclaration(Loc loc, Loc endloc);
+    PostBlitDeclaration(Loc loc, Loc endloc, Identifier *id);
+    Dsymbol *syntaxCopy(Dsymbol *);
+    void semantic(Scope *sc);
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+    int isVirtual();
+    int addPreInvariant();
+    int addPostInvariant();
+    int overloadInsert(Dsymbol *s);
+    void emitComment(Scope *sc);
+
+    PostBlitDeclaration *isPostBlitDeclaration() { return this; }
+};
+#endif
+
+struct DtorDeclaration : FuncDeclaration
+{
+    DtorDeclaration(Loc loc, Loc endloc);
+    DtorDeclaration(Loc loc, Loc endloc, Identifier *id);
+    Dsymbol *syntaxCopy(Dsymbol *);
+    void semantic(Scope *sc);
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+    const char *kind();
+    char *toChars();
+    int isVirtual();
+    int addPreInvariant();
+    int addPostInvariant();
+    int overloadInsert(Dsymbol *s);
+    void emitComment(Scope *sc);
+
+    DtorDeclaration *isDtorDeclaration() { return this; }
+};
+
+struct StaticCtorDeclaration : FuncDeclaration
+{
+    StaticCtorDeclaration(Loc loc, Loc endloc);
+    Dsymbol *syntaxCopy(Dsymbol *);
+    void semantic(Scope *sc);
+    AggregateDeclaration *isThis();
+    int isStaticConstructor();
+    int isVirtual();
+    int addPreInvariant();
+    int addPostInvariant();
+    void emitComment(Scope *sc);
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+
+    StaticCtorDeclaration *isStaticCtorDeclaration() { return this; }
+};
+
+struct StaticDtorDeclaration : FuncDeclaration
+{   VarDeclaration *vgate;	// 'gate' variable
+
+    StaticDtorDeclaration(Loc loc, Loc endloc);
+    Dsymbol *syntaxCopy(Dsymbol *);
+    void semantic(Scope *sc);
+    AggregateDeclaration *isThis();
+    int isStaticDestructor();
+    int isVirtual();
+    int addPreInvariant();
+    int addPostInvariant();
+    void emitComment(Scope *sc);
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+
+    StaticDtorDeclaration *isStaticDtorDeclaration() { return this; }
+};
+
+struct InvariantDeclaration : FuncDeclaration
+{
+    InvariantDeclaration(Loc loc, Loc endloc);
+    Dsymbol *syntaxCopy(Dsymbol *);
+    void semantic(Scope *sc);
+    int isVirtual();
+    int addPreInvariant();
+    int addPostInvariant();
+    void emitComment(Scope *sc);
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+
+    InvariantDeclaration *isInvariantDeclaration() { return this; }
+};
+
+
+struct UnitTestDeclaration : FuncDeclaration
+{
+    UnitTestDeclaration(Loc loc, Loc endloc);
+    Dsymbol *syntaxCopy(Dsymbol *);
+    void semantic(Scope *sc);
+    AggregateDeclaration *isThis();
+    int isVirtual();
+    int addPreInvariant();
+    int addPostInvariant();
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+
+    UnitTestDeclaration *isUnitTestDeclaration() { return this; }
+};
+
+struct NewDeclaration : FuncDeclaration
+{   Arguments *arguments;
+    int varargs;
+
+    NewDeclaration(Loc loc, Loc endloc, Arguments *arguments, int varargs);
+    Dsymbol *syntaxCopy(Dsymbol *);
+    void semantic(Scope *sc);
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+    const char *kind();
+    int isVirtual();
+    int addPreInvariant();
+    int addPostInvariant();
+
+    NewDeclaration *isNewDeclaration() { return this; }
+};
+
+
+struct DeleteDeclaration : FuncDeclaration
+{   Arguments *arguments;
+
+    DeleteDeclaration(Loc loc, Loc endloc, Arguments *arguments);
+    Dsymbol *syntaxCopy(Dsymbol *);
+    void semantic(Scope *sc);
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+    const char *kind();
+    int isDelete();
+    int isVirtual();
+    int addPreInvariant();
+    int addPostInvariant();
+#ifdef _DH
+    DeleteDeclaration *isDeleteDeclaration() { return this; }
+#endif
+};
+
+#endif /* DMD_DECLARATION_H */
--- a/dmd2/doc.c	Mon Jun 01 01:28:18 2009 +0200
+++ b/dmd2/doc.c	Mon Jun 01 19:02:20 2009 +0100
@@ -1,2028 +1,2019 @@
-
-// 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.
-
-// This implements the Ddoc capability.
-
-#include <stdio.h>
-#include <string.h>
-#include <time.h>
-#include <ctype.h>
-#include <assert.h>
-
-#if IN_GCC || IN_LLVM
-#include "mem.h"
-#else
-#if _WIN32
-#include "..\root\mem.h"
-#elif POSIX
-#include "../root/mem.h"
-#else
-#error "fix this"
-#endif
-#endif
-
-#include "root.h"
-
-#include "mars.h"
-#include "dsymbol.h"
-#include "macro.h"
-#include "template.h"
-#include "lexer.h"
-#include "aggregate.h"
-#include "declaration.h"
-#include "enum.h"
-#include "id.h"
-#include "module.h"
-#include "scope.h"
-#include "hdrgen.h"
-#include "doc.h"
-#include "mtype.h"
-
-struct Escape
-{
-    const char *strings[256];
-
-    static const char *escapeChar(unsigned c);
-};
-
-struct Section
-{
-    unsigned char *name;
-    unsigned namelen;
-
-    unsigned char *body;
-    unsigned bodylen;
-
-    int nooutput;
-
-    virtual void write(DocComment *dc, Scope *sc, Dsymbol *s, OutBuffer *buf);
-};
-
-struct ParamSection : Section
-{
-    void write(DocComment *dc, Scope *sc, Dsymbol *s, OutBuffer *buf);
-};
-
-struct MacroSection : Section
-{
-    void write(DocComment *dc, Scope *sc, Dsymbol *s, OutBuffer *buf);
-};
-
-struct DocComment
-{
-    Array sections;		// Section*[]
-
-    Section *summary;
-    Section *copyright;
-    Section *macros;
-    Macro **pmacrotable;
-    Escape **pescapetable;
-
-    DocComment();
-
-    static DocComment *parse(Scope *sc, Dsymbol *s, unsigned char *comment);
-    static void parseMacros(Escape **pescapetable, Macro **pmacrotable, unsigned char *m, unsigned mlen);
-    static void parseEscapes(Escape **pescapetable, unsigned char *textstart, unsigned textlen);
-
-    void parseSections(unsigned char *comment);
-    void writeSections(Scope *sc, Dsymbol *s, OutBuffer *buf);
-};
-
-
-int cmp(const char *stringz, void *s, size_t slen);
-int icmp(const char *stringz, void *s, size_t slen);
-int isDitto(unsigned char *comment);
-unsigned char *skipwhitespace(unsigned char *p);
-unsigned skiptoident(OutBuffer *buf, unsigned i);
-unsigned skippastident(OutBuffer *buf, unsigned i);
-unsigned skippastURL(OutBuffer *buf, unsigned i);
-void highlightText(Scope *sc, Dsymbol *s, OutBuffer *buf, unsigned offset);
-void highlightCode(Scope *sc, Dsymbol *s, OutBuffer *buf, unsigned offset);
-void highlightCode2(Scope *sc, Dsymbol *s, OutBuffer *buf, unsigned offset);
-Argument *isFunctionParameter(Dsymbol *s, unsigned char *p, unsigned len);
-
-static unsigned char ddoc_default[] = "\
-DDOC =	<html><head>\n\
-	<META http-equiv=\"content-type\" content=\"text/html; charset=utf-8\">\n\
-	<title>$(TITLE)</title>\n\
-	</head><body>\n\
-	<h1>$(TITLE)</h1>\n\
-	$(BODY)\n\
-	<hr>$(SMALL Page generated by $(LINK2 http://www.digitalmars.com/d/2.0/ddoc.html, Ddoc). $(COPYRIGHT))\n\
-	</body></html>\n\
-\n\
-B =	<b>$0</b>\n\
-I =	<i>$0</i>\n\
-U =	<u>$0</u>\n\
-P =	<p>$0</p>\n\
-DL =	<dl>$0</dl>\n\
-DT =	<dt>$0</dt>\n\
-DD =	<dd>$0</dd>\n\
-TABLE =	<table>$0</table>\n\
-TR =	<tr>$0</tr>\n\
-TH =	<th>$0</th>\n\
-TD =	<td>$0</td>\n\
-OL =	<ol>$0</ol>\n\
-UL =	<ul>$0</ul>\n\
-LI =	<li>$0</li>\n\
-BIG =	<big>$0</big>\n\
-SMALL =	<small>$0</small>\n\
-BR =	<br>\n\
-LINK =	<a href=\"$0\">$0</a>\n\
-LINK2 =	<a href=\"$1\">$+</a>\n\
-\n\
-RED =	<font color=red>$0</font>\n\
-BLUE =	<font color=blue>$0</font>\n\
-GREEN =	<font color=green>$0</font>\n\
-YELLOW =<font color=yellow>$0</font>\n\
-BLACK =	<font color=black>$0</font>\n\
-WHITE =	<font color=white>$0</font>\n\
-\n\
-D_CODE = <pre class=\"d_code\">$0</pre>\n\
-D_COMMENT = $(GREEN $0)\n\
-D_STRING  = $(RED $0)\n\
-D_KEYWORD = $(BLUE $0)\n\
-D_PSYMBOL = $(U $0)\n\
-D_PARAM	  = $(I $0)\n\
-\n\
-DDOC_COMMENT   = <!-- $0 -->\n\
-DDOC_DECL      = $(DT $(BIG $0))\n\
-DDOC_DECL_DD   = $(DD $0)\n\
-DDOC_DITTO     = $(BR)$0\n\
-DDOC_SECTIONS  = $0\n\
-DDOC_SUMMARY   = $0$(BR)$(BR)\n\
-DDOC_DESCRIPTION = $0$(BR)$(BR)\n\
-DDOC_AUTHORS   = $(B Authors:)$(BR)\n$0$(BR)$(BR)\n\
-DDOC_BUGS      = $(RED BUGS:)$(BR)\n$0$(BR)$(BR)\n\
-DDOC_COPYRIGHT = $(B Copyright:)$(BR)\n$0$(BR)$(BR)\n\
-DDOC_DATE      = $(B Date:)$(BR)\n$0$(BR)$(BR)\n\
-DDOC_DEPRECATED = $(RED Deprecated:)$(BR)\n$0$(BR)$(BR)\n\
-DDOC_EXAMPLES  = $(B Examples:)$(BR)\n$0$(BR)$(BR)\n\
-DDOC_HISTORY   = $(B History:)$(BR)\n$0$(BR)$(BR)\n\
-DDOC_LICENSE   = $(B License:)$(BR)\n$0$(BR)$(BR)\n\
-DDOC_RETURNS   = $(B Returns:)$(BR)\n$0$(BR)$(BR)\n\
-DDOC_SEE_ALSO  = $(B See Also:)$(BR)\n$0$(BR)$(BR)\n\
-DDOC_STANDARDS = $(B Standards:)$(BR)\n$0$(BR)$(BR)\n\
-DDOC_THROWS    = $(B Throws:)$(BR)\n$0$(BR)$(BR)\n\
-DDOC_VERSION   = $(B Version:)$(BR)\n$0$(BR)$(BR)\n\
-DDOC_SECTION_H = $(B $0)$(BR)\n\
-DDOC_SECTION   = $0$(BR)$(BR)\n\
-DDOC_MEMBERS   = $(DL $0)\n\
-DDOC_MODULE_MEMBERS = $(DDOC_MEMBERS $0)\n\
-DDOC_CLASS_MEMBERS  = $(DDOC_MEMBERS $0)\n\
-DDOC_STRUCT_MEMBERS = $(DDOC_MEMBERS $0)\n\
-DDOC_ENUM_MEMBERS   = $(DDOC_MEMBERS $0)\n\
-DDOC_TEMPLATE_MEMBERS = $(DDOC_MEMBERS $0)\n\
-DDOC_PARAMS    = $(B Params:)$(BR)\n$(TABLE $0)$(BR)\n\
-DDOC_PARAM_ROW = $(TR $0)\n\
-DDOC_PARAM_ID  = $(TD $0)\n\
-DDOC_PARAM_DESC = $(TD $0)\n\
-DDOC_BLANKLINE	= $(BR)$(BR)\n\
-\n\
-DDOC_PSYMBOL	= $(U $0)\n\
-DDOC_KEYWORD	= $(B $0)\n\
-DDOC_PARAM	= $(I $0)\n\
-\n\
-ESCAPES = /</&lt;/\n\
-	  />/&gt;/\n\
-	  /&/&amp;/\n\
-";
-
-static char ddoc_decl_s[] = "$(DDOC_DECL ";
-static char ddoc_decl_e[] = ")\n";
-
-static char ddoc_decl_dd_s[] = "$(DDOC_DECL_DD ";
-static char ddoc_decl_dd_e[] = ")\n";
-
-
-/****************************************************
- */
-
-void Module::gendocfile()
-{
-    static OutBuffer mbuf;
-    static int mbuf_done;
-
-    OutBuffer buf;
-
-    //printf("Module::gendocfile()\n");
-
-    if (!mbuf_done)		// if not already read the ddoc files
-    {	mbuf_done = 1;
-
-	// Use our internal default
-	mbuf.write(ddoc_default, sizeof(ddoc_default) - 1);
-
-	// Override with DDOCFILE specified in the sc.ini file
-	char *p = getenv("DDOCFILE");
-	if (p)
-	    global.params.ddocfiles->shift(p);
-
-	// Override with the ddoc macro files from the command line
-	for (int i = 0; i < global.params.ddocfiles->dim; i++)
-	{
-	    FileName f((char *)global.params.ddocfiles->data[i], 0);
-	    File file(&f);
-	    file.readv();
-	    // BUG: convert file contents to UTF-8 before use
-
-	    //printf("file: '%.*s'\n", file.len, file.buffer);
-	    mbuf.write(file.buffer, file.len);
-	}
-    }
-    DocComment::parseMacros(&escapetable, &macrotable, mbuf.data, mbuf.offset);
-
-    Scope *sc = Scope::createGlobal(this);	// create root scope
-    sc->docbuf = &buf;
-
-    DocComment *dc = DocComment::parse(sc, this, comment);
-    dc->pmacrotable = &macrotable;
-    dc->pescapetable = &escapetable;
-
-    // Generate predefined macros
-
-    // Set the title to be the name of the module
-    {	char *p = toPrettyChars();
-	Macro::define(&macrotable, (unsigned char *)"TITLE", 5, (unsigned char *)p, strlen(p));
-    }
-
-    time_t t;
-    time(&t);
-    char *p = ctime(&t);
-    p = mem.strdup(p);
-    Macro::define(&macrotable, (unsigned char *)"DATETIME", 8, (unsigned char *)p, strlen(p));
-    Macro::define(&macrotable, (unsigned char *)"YEAR", 4, (unsigned char *)p + 20, 4);
-
-    char *docfilename = docfile->toChars();
-    Macro::define(&macrotable, (unsigned char *)"DOCFILENAME", 11, (unsigned char *)docfilename, strlen(docfilename));
-
-    if (dc->copyright)
-    {
-	dc->copyright->nooutput = 1;
-	Macro::define(&macrotable, (unsigned char *)"COPYRIGHT", 9, dc->copyright->body, dc->copyright->bodylen);
-    }
-
-    buf.printf("$(DDOC_COMMENT Generated by Ddoc from %s)\n", srcfile->toChars());
-    if (isDocFile)
-    {
-	size_t commentlen = strlen((char *)comment);
-	if (dc->macros)
-	{
-	    commentlen = dc->macros->name - comment;
-	    dc->macros->write(dc, sc, this, sc->docbuf);
-	}
-	sc->docbuf->write(comment, commentlen);
-	highlightText(NULL, this, sc->docbuf, 0);
-    }
-    else
-    {
-	dc->writeSections(sc, this, sc->docbuf);
-	emitMemberComments(sc);
-    }
-
-    //printf("BODY= '%.*s'\n", buf.offset, buf.data);
-    Macro::define(&macrotable, (unsigned char *)"BODY", 4, buf.data, buf.offset);
-
-    OutBuffer buf2;
-    buf2.writestring("$(DDOC)\n");
-    unsigned end = buf2.offset;
-    macrotable->expand(&buf2, 0, &end, NULL, 0);
-
-#if 1
-    /* Remove all the escape sequences from buf2,
-     * and make CR-LF the newline.
-     */
-    {
-	buf.setsize(0);
-	buf.reserve(buf2.offset);
-	unsigned char *p = buf2.data;
-	for (unsigned j = 0; j < buf2.offset; j++)
-	{
-	    unsigned char c = p[j];
-	    if (c == 0xFF && j + 1 < buf2.offset)
-	    {
-		j++;
-		continue;
-	    }
-	    if (c == '\n')
-		buf.writeByte('\r');
-	    else if (c == '\r')
-	    {
-		buf.writestring("\r\n");
-		if (j + 1 < buf2.offset && p[j + 1] == '\n')
-		{
-		    j++;
-		}
-		continue;
-	    }
-	    buf.writeByte(c);
-	}
-    }
-
-    // Transfer image to file
-    assert(docfile);
-    docfile->setbuffer(buf.data, buf.offset);
-    docfile->ref = 1;
-    char *pt = FileName::path(docfile->toChars());
-    if (*pt)
-	FileName::ensurePathExists(pt);
-    mem.free(pt);
-    docfile->writev();
-#else
-    /* Remove all the escape sequences from buf2
-     */
-    {	unsigned i = 0;
-	unsigned char *p = buf2.data;
-	for (unsigned j = 0; j < buf2.offset; j++)
-	{
-	    if (p[j] == 0xFF && j + 1 < buf2.offset)
-	    {
-		j++;
-		continue;
-	    }
-	    p[i] = p[j];
-	    i++;
-	}
-	buf2.setsize(i);
-    }
-
-    // Transfer image to file
-    docfile->setbuffer(buf2.data, buf2.offset);
-    docfile->ref = 1;
-    char *pt = FileName::path(docfile->toChars());
-    if (*pt)
-	FileName::ensurePathExists(pt);
-    mem.free(pt);
-    docfile->writev();
-#endif
-}
-
-/******************************* emitComment **********************************/
-
-/*
- * Emit doc comment to documentation file
- */
-
-void Dsymbol::emitDitto(Scope *sc)
-{
-    //printf("Dsymbol::emitDitto() %s %s\n", kind(), toChars());
-    OutBuffer *buf = sc->docbuf;
-    unsigned o;
-    OutBuffer b;
-
-    b.writestring("$(DDOC_DITTO ");
-	o = b.offset;
-	toDocBuffer(&b);
-	//printf("b: '%.*s'\n", b.offset, b.data);
-	/* If 'this' is a function template, then highlightCode() was
-	 * already run by FuncDeclaration::toDocbuffer().
-	 */
-	TemplateDeclaration *td;
-	if (parent &&
-	    (td = parent->isTemplateDeclaration()) != NULL &&
-	    td->onemember == this)
-	{
-	}
-	else
-	    highlightCode(sc, this, &b, o);
-    b.writeByte(')');
-    buf->spread(sc->lastoffset, b.offset);
-    memcpy(buf->data + sc->lastoffset, b.data, b.offset);
-    sc->lastoffset += b.offset;
-}
-
-void ScopeDsymbol::emitMemberComments(Scope *sc)
-{
-    //printf("ScopeDsymbol::emitMemberComments() %s\n", toChars());
-    OutBuffer *buf = sc->docbuf;
-
-    if (members)
-    {	const char *m = "$(DDOC_MEMBERS \n";
-
-	if (isModule())
-	    m = "$(DDOC_MODULE_MEMBERS \n";
-	else if (isClassDeclaration())
-	    m = "$(DDOC_CLASS_MEMBERS \n";
-	else if (isStructDeclaration())
-	    m = "$(DDOC_STRUCT_MEMBERS \n";
-	else if (isEnumDeclaration())
-	    m = "$(DDOC_ENUM_MEMBERS \n";
-	else if (isTemplateDeclaration())
-	    m = "$(DDOC_TEMPLATE_MEMBERS \n";
-
-	unsigned offset1 = buf->offset;		// save starting offset
-	buf->writestring(m);
-	unsigned offset2 = buf->offset;		// to see if we write anything
-	sc = sc->push(this);
-	for (int i = 0; i < members->dim; i++)
-	{
-	    Dsymbol *s = (Dsymbol *)members->data[i];
-	    //printf("\ts = '%s'\n", s->toChars());
-	    s->emitComment(sc);
-	}
-	sc->pop();
-	if (buf->offset == offset2)
-	{
-	    /* Didn't write out any members, so back out last write
-	     */
-	    buf->offset = offset1;
-	}
-	else
-	    buf->writestring(")\n");
-    }
-}
-
-void emitProtection(OutBuffer *buf, PROT prot)
-{
-    const char *p;
-
-    switch (prot)
-    {
-	case PROTpackage:	p = "package";	 break;
-	case PROTprotected:	p = "protected"; break;
-	case PROTexport:	p = "export";	 break;
-	default:		p = NULL;	 break;
-    }
-    if (p)
-	buf->printf("%s ", p);
-}
-
-void Dsymbol::emitComment(Scope *sc)		   { }
-void InvariantDeclaration::emitComment(Scope *sc)  { }
-#if DMDV2
-void PostBlitDeclaration::emitComment(Scope *sc)   { }
-#endif
-void DtorDeclaration::emitComment(Scope *sc)	   { }
-void StaticCtorDeclaration::emitComment(Scope *sc) { }
-void StaticDtorDeclaration::emitComment(Scope *sc) { }
-void ClassInfoDeclaration::emitComment(Scope *sc)  { }
-void ModuleInfoDeclaration::emitComment(Scope *sc) { }
-void TypeInfoDeclaration::emitComment(Scope *sc)   { }
-
-
-void Declaration::emitComment(Scope *sc)
-{
-    //printf("Declaration::emitComment(%p '%s'), comment = '%s'\n", this, toChars(), comment);
-    //printf("type = %p\n", type);
-
-    if (protection == PROTprivate || !ident ||
-	(!type && !isCtorDeclaration() && !isAliasDeclaration()))
-	return;
-    if (!comment)
-	return;
-
-    OutBuffer *buf = sc->docbuf;
-    DocComment *dc = DocComment::parse(sc, this, comment);
-    unsigned o;
-
-    if (!dc)
-    {
-	emitDitto(sc);
-	return;
-    }
-    dc->pmacrotable = &sc->module->macrotable;
-
-    buf->writestring(ddoc_decl_s);
-	o = buf->offset;
-	toDocBuffer(buf);
-	highlightCode(sc, this, buf, o);
-	sc->lastoffset = buf->offset;
-    buf->writestring(ddoc_decl_e);
-
-    buf->writestring(ddoc_decl_dd_s);
-    dc->writeSections(sc, this, buf);
-    buf->writestring(ddoc_decl_dd_e);
-}
-
-void AggregateDeclaration::emitComment(Scope *sc)
-{
-    //printf("AggregateDeclaration::emitComment() '%s'\n", toChars());
-    if (prot() == PROTprivate)
-	return;
-    if (!comment)
-	return;
-
-    OutBuffer *buf = sc->docbuf;
-    DocComment *dc = DocComment::parse(sc, this, comment);
-
-    if (!dc)
-    {
-	emitDitto(sc);
-	return;
-    }
-    dc->pmacrotable = &sc->module->macrotable;
-
-    buf->writestring(ddoc_decl_s);
-    toDocBuffer(buf);
-    sc->lastoffset = buf->offset;
-    buf->writestring(ddoc_decl_e);
-
-    buf->writestring(ddoc_decl_dd_s);
-    dc->writeSections(sc, this, buf);
-    emitMemberComments(sc);
-    buf->writestring(ddoc_decl_dd_e);
-}
-
-void TemplateDeclaration::emitComment(Scope *sc)
-{
-    //printf("TemplateDeclaration::emitComment() '%s', kind = %s\n", toChars(), kind());
-    if (prot() == PROTprivate)
-	return;
-
-    unsigned char *com = comment;
-    int hasmembers = 1;
-
-    Dsymbol *ss = this;
-
-    if (onemember)
-    {
-	ss = onemember->isAggregateDeclaration();
-	if (!ss)
-	{
-	    ss = onemember->isFuncDeclaration();
-	    if (ss)
-	    {	hasmembers = 0;
-		if (com != ss->comment)
-		    com = Lexer::combineComments(com, ss->comment);
-	    }
-	    else
-		ss = this;
-	}
-    }
-
-    if (!com)
-	return;
-
-    OutBuffer *buf = sc->docbuf;
-    DocComment *dc = DocComment::parse(sc, this, com);
-    unsigned o;
-
-    if (!dc)
-    {
-	ss->emitDitto(sc);
-	return;
-    }
-    dc->pmacrotable = &sc->module->macrotable;
-
-    buf->writestring(ddoc_decl_s);
-	o = buf->offset;
-	ss->toDocBuffer(buf);
-	if (ss == this)
-	    highlightCode(sc, this, buf, o);
-	sc->lastoffset = buf->offset;
-    buf->writestring(ddoc_decl_e);
-
-    buf->writestring(ddoc_decl_dd_s);
-    dc->writeSections(sc, this, buf);
-    if (hasmembers)
-	((ScopeDsymbol *)ss)->emitMemberComments(sc);
-    buf->writestring(ddoc_decl_dd_e);
-}
-
-void EnumDeclaration::emitComment(Scope *sc)
-{
-    if (prot() == PROTprivate)
-	return;
-//    if (!comment)
-    {	if (isAnonymous() && members)
-	{
-	    for (int i = 0; i < members->dim; i++)
-	    {
-		Dsymbol *s = (Dsymbol *)members->data[i];
-		s->emitComment(sc);
-	    }
-	    return;
-	}
-    }
-    if (!comment)
-	return;
-    if (isAnonymous())
-	return;
-
-    OutBuffer *buf = sc->docbuf;
-    DocComment *dc = DocComment::parse(sc, this, comment);
-
-    if (!dc)
-    {
-	emitDitto(sc);
-	return;
-    }
-    dc->pmacrotable = &sc->module->macrotable;
-
-    buf->writestring(ddoc_decl_s);
-	toDocBuffer(buf);
-	sc->lastoffset = buf->offset;
-    buf->writestring(ddoc_decl_e);
-
-    buf->writestring(ddoc_decl_dd_s);
-    dc->writeSections(sc, this, buf);
-    emitMemberComments(sc);
-    buf->writestring(ddoc_decl_dd_e);
-}
-
-void EnumMember::emitComment(Scope *sc)
-{
-    //printf("EnumMember::emitComment(%p '%s'), comment = '%s'\n", this, toChars(), comment);
-    if (prot() == PROTprivate)
-	return;
-    if (!comment)
-	return;
-
-    OutBuffer *buf = sc->docbuf;
-    DocComment *dc = DocComment::parse(sc, this, comment);
-    unsigned o;
-
-    if (!dc)
-    {
-	emitDitto(sc);
-	return;
-    }
-    dc->pmacrotable = &sc->module->macrotable;
-
-    buf->writestring(ddoc_decl_s);
-	o = buf->offset;
-	toDocBuffer(buf);
-	highlightCode(sc, this, buf, o);
-	sc->lastoffset = buf->offset;
-    buf->writestring(ddoc_decl_e);
-
-    buf->writestring(ddoc_decl_dd_s);
-    dc->writeSections(sc, this, buf);
-    buf->writestring(ddoc_decl_dd_e);
-}
-
-/******************************* toDocBuffer **********************************/
-
-void Dsymbol::toDocBuffer(OutBuffer *buf)
-{
-    //printf("Dsymbol::toDocbuffer() %s\n", toChars());
-    HdrGenState hgs;
-
-    hgs.ddoc = 1;
-    toCBuffer(buf, &hgs);
-}
-
-void prefix(OutBuffer *buf, Dsymbol *s)
-{
-    if (s->isDeprecated())
-	buf->writestring("deprecated ");
-    Declaration *d = s->isDeclaration();
-    if (d)
-    {
-	emitProtection(buf, d->protection);
-	if (d->isAbstract())
-	    buf->writestring("abstract ");
-	if (d->isStatic())
-	    buf->writestring("static ");
-	if (d->isConst())
-	    buf->writestring("const ");
-#if DMDV2
-	if (d->isInvariant())
-	    buf->writestring("invariant ");
-#endif
-	if (d->isFinal())
-	    buf->writestring("final ");
-	if (d->isSynchronized())
-	    buf->writestring("synchronized ");
-    }
-}
-
-void Declaration::toDocBuffer(OutBuffer *buf)
-{
-    //printf("Declaration::toDocbuffer() %s, originalType = %p\n", toChars(), originalType);
-    if (ident)
-    {
-	prefix(buf, this);
-
-	if (type)
-	{   HdrGenState hgs;
-	    hgs.ddoc = 1;
-	    if (originalType)
-	    {	//originalType->print();
-		originalType->toCBuffer(buf, ident, &hgs);
-	    }
-	    else
-		type->toCBuffer(buf, ident, &hgs);
-	}
-	else
-	    buf->writestring(ident->toChars());
-	buf->writestring(";\n");
-    }
-}
-
-
-void AliasDeclaration::toDocBuffer(OutBuffer *buf)
-{
-    //printf("AliasDeclaration::toDocbuffer() %s\n", toChars());
-    if (ident)
-    {
-	if (isDeprecated())
-	    buf->writestring("deprecated ");
-
-	emitProtection(buf, protection);
-	buf->writestring("alias ");
-	buf->writestring(toChars());
-	buf->writestring(";\n");
-    }
-}
-
-
-void TypedefDeclaration::toDocBuffer(OutBuffer *buf)
-{
-    if (ident)
-    {
-	if (isDeprecated())
-	    buf->writestring("deprecated ");
-
-	emitProtection(buf, protection);
-	buf->writestring("typedef ");
-	buf->writestring(toChars());
-	buf->writestring(";\n");
-    }
-}
-
-
-void FuncDeclaration::toDocBuffer(OutBuffer *buf)
-{
-    //printf("FuncDeclaration::toDocbuffer() %s\n", toChars());
-    if (ident)
-    {
-	TemplateDeclaration *td;
-
-	if (parent &&
-	    (td = parent->isTemplateDeclaration()) != NULL &&
-	    td->onemember == this)
-	{   /* It's a function template
-	     */
-	    HdrGenState hgs;
-	    unsigned o = buf->offset;
-	    TypeFunction *tf = (TypeFunction *)type;
-
-	    hgs.ddoc = 1;
-	    prefix(buf, td);
-	    tf->next->toCBuffer(buf, NULL, &hgs);
-	    buf->writeByte(' ');
-	    buf->writestring(ident->toChars());
-	    buf->writeByte('(');
-	    for (int i = 0; i < td->origParameters->dim; i++)
-	    {
-		TemplateParameter *tp = (TemplateParameter *)td->origParameters->data[i];
-		if (i)
-		    buf->writestring(", ");
-		tp->toCBuffer(buf, &hgs);
-	    }
-	    buf->writeByte(')');
-	    Argument::argsToCBuffer(buf, &hgs, tf->parameters, tf->varargs);
-	    buf->writestring(";\n");
-
-	    highlightCode(NULL, this, buf, o);
-	}
-	else
-	{
-	    Declaration::toDocBuffer(buf);
-	}
-    }
-}
-
-void CtorDeclaration::toDocBuffer(OutBuffer *buf)
-{
-    HdrGenState hgs;
-
-    buf->writestring("this");
-    Argument::argsToCBuffer(buf, &hgs, arguments, varargs);
-    buf->writestring(";\n");
-}
-
-
-void AggregateDeclaration::toDocBuffer(OutBuffer *buf)
-{
-    if (ident)
-    {
-#if 0
-	emitProtection(buf, protection);
-#endif
-	buf->printf("%s $(DDOC_PSYMBOL %s)", kind(), toChars());
-	buf->writestring(";\n");
-    }
-}
-
-void StructDeclaration::toDocBuffer(OutBuffer *buf)
-{
-    //printf("StructDeclaration::toDocbuffer() %s\n", toChars());
-    if (ident)
-    {
-#if 0
-	emitProtection(buf, protection);
-#endif
-	TemplateDeclaration *td;
-
-	if (parent &&
-	    (td = parent->isTemplateDeclaration()) != NULL &&
-	    td->onemember == this)
-	{   unsigned o = buf->offset;
-	    td->toDocBuffer(buf);
-	    highlightCode(NULL, this, buf, o);
-	}
-	else
-	{
-	    buf->printf("%s $(DDOC_PSYMBOL %s)", kind(), toChars());
-	}
-	buf->writestring(";\n");
-    }
-}
-
-void ClassDeclaration::toDocBuffer(OutBuffer *buf)
-{
-    //printf("ClassDeclaration::toDocbuffer() %s\n", toChars());
-    if (ident)
-    {
-#if 0
-	emitProtection(buf, protection);
-#endif
-	TemplateDeclaration *td;
-
-	if (parent &&
-	    (td = parent->isTemplateDeclaration()) != NULL &&
-	    td->onemember == this)
-	{   unsigned o = buf->offset;
-	    td->toDocBuffer(buf);
-	    highlightCode(NULL, this, buf, o);
-	}
-	else
-	{
-	    buf->printf("%s $(DDOC_PSYMBOL %s)", kind(), toChars());
-	}
-	int any = 0;
-	for (int i = 0; i < baseclasses.dim; i++)
-	{   BaseClass *bc = (BaseClass *)baseclasses.data[i];
-
-	    if (bc->protection == PROTprivate)
-		continue;
-	    if (bc->base && bc->base->ident == Id::Object)
-		continue;
-
-	    if (any)
-		buf->writestring(", ");
-	    else
-	    {	buf->writestring(": ");
-		any = 1;
-	    }
-	    emitProtection(buf, bc->protection);
-	    if (bc->base)
-	    {
-		buf->writestring(bc->base->toPrettyChars());
-	    }
-	    else
-	    {
-		HdrGenState hgs;
-		bc->type->toCBuffer(buf, NULL, &hgs);
-	    }
-	}
-	buf->writestring(";\n");
-    }
-}
-
-
-void EnumDeclaration::toDocBuffer(OutBuffer *buf)
-{
-    if (ident)
-    {
-	buf->printf("%s $(DDOC_PSYMBOL %s)", kind(), toChars());
-	buf->writestring(";\n");
-    }
-}
-
-void EnumMember::toDocBuffer(OutBuffer *buf)
-{
-    if (ident)
-    {
-	buf->writestring(toChars());
-    }
-}
-
-
-/********************************* DocComment *********************************/
-
-DocComment::DocComment()
-{
-    memset(this, 0, sizeof(DocComment));
-}
-
-DocComment *DocComment::parse(Scope *sc, Dsymbol *s, unsigned char *comment)
-{   unsigned idlen;
-
-    //printf("parse(%s): '%s'\n", s->toChars(), comment);
-    if (sc->lastdc && isDitto(comment))
-	return NULL;
-
-    DocComment *dc = new DocComment();
-    if (!comment)
-	return dc;
-
-    dc->parseSections(comment);
-
-    for (int i = 0; i < dc->sections.dim; i++)
-    {	Section *s = (Section *)dc->sections.data[i];
-
-	if (icmp("copyright", s->name, s->namelen) == 0)
-	{
-	    dc->copyright = s;
-	}
-	if (icmp("macros", s->name, s->namelen) == 0)
-	{
-	    dc->macros = s;
-	}
-    }
-
-    sc->lastdc = dc;
-    return dc;
-}
-
-/*****************************************
- * Parse next paragraph out of *pcomment.
- * Update *pcomment to point past paragraph.
- * Returns NULL if no more paragraphs.
- * If paragraph ends in 'identifier:',
- * then (*pcomment)[0 .. idlen] is the identifier.
- */
-
-void DocComment::parseSections(unsigned char *comment)
-{   unsigned char *p;
-    unsigned char *pstart;
-    unsigned char *pend;
-    unsigned char *q;
-    unsigned char *idstart;
-    unsigned idlen;
-
-    unsigned char *name = NULL;
-    unsigned namelen = 0;
-
-    //printf("parseSections('%s')\n", comment);
-    p = comment;
-    while (*p)
-    {
-	p = skipwhitespace(p);
-	pstart = p;
-
-	/* Find end of section, which is ended by one of:
-	 *	'identifier:'
-	 *	'\0'
-	 */
-	idlen = 0;
-	while (1)
-	{
-	    if (isalpha(*p) || *p == '_')
-	    {
-		q = p + 1;
-		while (isalnum(*q) || *q == '_')
-		    q++;
-		if (*q == ':')	// identifier: ends it
-		{   idlen = q - p;
-		    idstart = p;
-		    for (pend = p; pend > pstart; pend--)
-		    {	if (pend[-1] == '\n')
-			    break;
-		    }
-		    p = q + 1;
-		    break;
-		}
-	    }
-	    while (1)
-	    {
-		if (!*p)
-		{   pend = p;
-		    goto L1;
-		}
-		if (*p == '\n')
-		{   p++;
-		    if (*p == '\n' && !summary && !namelen)
-		    {
-			pend = p;
-			p++;
-			goto L1;
-		    }
-		    break;
-		}
-		p++;
-	    }
-	    p = skipwhitespace(p);
-	}
-      L1:
-
-	if (namelen || pstart < pend)
-	{
-	    Section *s;
-	    if (icmp("Params", name, namelen) == 0)
-		s = new ParamSection();
-	    else if (icmp("Macros", name, namelen) == 0)
-		s = new MacroSection();
-	    else
-		s = new Section();
-	    s->name = name;
-	    s->namelen = namelen;
-	    s->body = pstart;
-	    s->bodylen = pend - pstart;
-	    s->nooutput = 0;
-
-	    //printf("Section: '%.*s' = '%.*s'\n", s->namelen, s->name, s->bodylen, s->body);
-
-	    sections.push(s);
-
-	    if (!summary && !namelen)
-		summary = s;
-	}
-
-	if (idlen)
-	{   name = idstart;
-	    namelen = idlen;
-	}
-	else
-	{   name = NULL;
-	    namelen = 0;
-	    if (!*p)
-		break;
-	}
-    }
-}
-
-void DocComment::writeSections(Scope *sc, Dsymbol *s, OutBuffer *buf)
-{
-    //printf("DocComment::writeSections()\n");
-    if (sections.dim)
-    {
-	buf->writestring("$(DDOC_SECTIONS \n");
-	for (int i = 0; i < sections.dim; i++)
-	{   Section *sec = (Section *)sections.data[i];
-
-	    if (sec->nooutput)
-		continue;
-	    //printf("Section: '%.*s' = '%.*s'\n", sec->namelen, sec->name, sec->bodylen, sec->body);
-	    if (sec->namelen || i)
-		sec->write(this, sc, s, buf);
-	    else
-	    {
-		buf->writestring("$(DDOC_SUMMARY ");
-		    unsigned o = buf->offset;
-		    buf->write(sec->body, sec->bodylen);
-		    highlightText(sc, s, buf, o);
-		buf->writestring(")\n");
-	    }
-	}
-	buf->writestring(")\n");
-    }
-    else
-    {
-	buf->writestring("$(DDOC_BLANKLINE)\n");
-    }
-}
-
-/***************************************************
- */
-
-void Section::write(DocComment *dc, Scope *sc, Dsymbol *s, OutBuffer *buf)
-{
-    if (namelen)
-    {
-	static const char *table[] =
-	{	"AUTHORS", "BUGS", "COPYRIGHT", "DATE",
-		"DEPRECATED", "EXAMPLES", "HISTORY", "LICENSE",
-		"RETURNS", "SEE_ALSO", "STANDARDS", "THROWS",
-		"VERSION" };
-
-	for (int i = 0; i < sizeof(table) / sizeof(table[0]); i++)
-	{
-	    if (icmp(table[i], name, namelen) == 0)
-	    {
-		buf->printf("$(DDOC_%s ", table[i]);
-		goto L1;
-	    }
-	}
-
-	buf->writestring("$(DDOC_SECTION ");
-	    // Replace _ characters with spaces
-	    buf->writestring("$(DDOC_SECTION_H ");
-	    for (unsigned u = 0; u < namelen; u++)
-	    {   unsigned char c = name[u];
-		buf->writeByte((c == '_') ? ' ' : c);
-	    }
-	    buf->writestring(":)\n");
-    }
-    else
-    {
-	buf->writestring("$(DDOC_DESCRIPTION ");
-    }
-  L1:
-    unsigned o = buf->offset;
-    buf->write(body, bodylen);
-    highlightText(sc, s, buf, o);
-    buf->writestring(")\n");
-}
-
-/***************************************************
- */
-
-void ParamSection::write(DocComment *dc, Scope *sc, Dsymbol *s, OutBuffer *buf)
-{
-    unsigned char *p = body;
-    unsigned len = bodylen;
-    unsigned char *pend = p + len;
-
-    unsigned char *tempstart;
-    unsigned templen;
-
-    unsigned char *namestart;
-    unsigned namelen = 0;	// !=0 if line continuation
-
-    unsigned char *textstart;
-    unsigned textlen;
-
-    unsigned o;
-    Argument *arg;
-
-    buf->writestring("$(DDOC_PARAMS \n");
-    while (p < pend)
-    {
-	// Skip to start of macro
-	for (; 1; p++)
-	{
-	    switch (*p)
-	    {
-		case ' ':
-		case '\t':
-		    continue;
-
-		case '\n':
-		    p++;
-		    goto Lcont;
-
-		default:
-		    if (!(isalpha(*p) || *p == '_'))
-		    {
-			if (namelen)
-			    goto Ltext;		// continuation of prev macro
-			goto Lskipline;
-		    }
-		    break;
-	    }
-	    break;
-	}
-	tempstart = p;
-
-	while (isalnum(*p) || *p == '_')
-	    p++;
-	templen = p - tempstart;
-
-	while (*p == ' ' || *p == '\t')
-	    p++;
-
-	if (*p != '=')
-	{   if (namelen)
-		goto Ltext;		// continuation of prev macro
-	    goto Lskipline;
-	}
-	p++;
-
-	if (namelen)
-	{   // Output existing param
-
-	L1:
-	    //printf("param '%.*s' = '%.*s'\n", namelen, namestart, textlen, textstart);
-	    HdrGenState hgs;
-	    buf->writestring("$(DDOC_PARAM_ROW ");
-		buf->writestring("$(DDOC_PARAM_ID ");
-		    o = buf->offset;
-		    arg = isFunctionParameter(s, namestart, namelen);
-		    if (arg && arg->type && arg->ident)
-			arg->type->toCBuffer(buf, arg->ident, &hgs);
-		    else
-			buf->write(namestart, namelen);
-		    highlightCode(sc, s, buf, o);
-		buf->writestring(")\n");
-
-		buf->writestring("$(DDOC_PARAM_DESC ");
-		    o = buf->offset;
-		    buf->write(textstart, textlen);
-		    highlightText(sc, s, buf, o);
-		buf->writestring(")");
-	    buf->writestring(")\n");
-	    namelen = 0;
-	    if (p >= pend)
-		break;
-	}
-
-	namestart = tempstart;
-	namelen = templen;
-
-	while (*p == ' ' || *p == '\t')
-	    p++;
-	textstart = p;
-
-      Ltext:
-	while (*p != '\n')
-	    p++;
-	textlen = p - textstart;
-	p++;
-
-     Lcont:
-	continue;
-
-     Lskipline:
-	// Ignore this line
-	while (*p++ != '\n')
-	    ;
-    }
-    if (namelen)
-	goto L1;		// write out last one
-    buf->writestring(")\n");
-}
-
-/***************************************************
- */
-
-void MacroSection::write(DocComment *dc, Scope *sc, Dsymbol *s, OutBuffer *buf)
-{
-    //printf("MacroSection::write()\n");
-    DocComment::parseMacros(dc->pescapetable, dc->pmacrotable, body, bodylen);
-}
-
-/************************************************
- * Parse macros out of Macros: section.
- * Macros are of the form:
- *	name1 = value1
- *
- *	name2 = value2
- */
-
-void DocComment::parseMacros(Escape **pescapetable, Macro **pmacrotable, unsigned char *m, unsigned mlen)
-{
-    unsigned char *p = m;
-    unsigned len = mlen;
-    unsigned char *pend = p + len;
-
-    unsigned char *tempstart;
-    unsigned templen;
-
-    unsigned char *namestart;
-    unsigned namelen = 0;	// !=0 if line continuation
-
-    unsigned char *textstart;
-    unsigned textlen;
-
-    while (p < pend)
-    {
-	// Skip to start of macro
-	for (; 1; p++)
-	{
-	    if (p >= pend)
-		goto Ldone;
-	    switch (*p)
-	    {
-		case ' ':
-		case '\t':
-		    continue;
-
-		case '\n':
-		    p++;
-		    goto Lcont;
-
-		default:
-		    if (!(isalpha(*p) || *p == '_'))
-		    {
-			if (namelen)
-			    goto Ltext;		// continuation of prev macro
-			goto Lskipline;
-		    }
-		    break;
-	    }
-	    break;
-	}
-	tempstart = p;
-
-	while (1)
-	{
-	    if (p >= pend)
-		goto Ldone;
-	    if (!(isalnum(*p) || *p == '_'))
-		break;
-	    p++;
-	}
-	templen = p - tempstart;
-
-	while (1)
-	{
-	    if (p >= pend)
-		goto Ldone;
-	    if (!(*p == ' ' || *p == '\t'))
-		break;
-	    p++;
-	}
-
-	if (*p != '=')
-	{   if (namelen)
-		goto Ltext;		// continuation of prev macro
-	    goto Lskipline;
-	}
-	p++;
-	if (p >= pend)
-	    goto Ldone;
-
-	if (namelen)
-	{   // Output existing macro
-	L1:
-	    //printf("macro '%.*s' = '%.*s'\n", namelen, namestart, textlen, textstart);
-	    if (icmp("ESCAPES", namestart, namelen) == 0)
-		parseEscapes(pescapetable, textstart, textlen);
-	    else
-		Macro::define(pmacrotable, namestart, namelen, textstart, textlen);
-	    namelen = 0;
-	    if (p >= pend)
-		break;
-	}
-
-	namestart = tempstart;
-	namelen = templen;
-
-	while (p < pend && (*p == ' ' || *p == '\t'))
-	    p++;
-	textstart = p;
-
-      Ltext:
-	while (p < pend && *p != '\n')
-	    p++;
-	textlen = p - textstart;
-
-	// Remove trailing \r if there is one
-	if (p > m && p[-1] == '\r')
-	    textlen--;
-
-	p++;
-	//printf("p = %p, pend = %p\n", p, pend);
-
-     Lcont:
-	continue;
-
-     Lskipline:
-	// Ignore this line
-	while (p < pend && *p++ != '\n')
-	    ;
-    }
-Ldone:
-    if (namelen)
-	goto L1;		// write out last one
-}
-
-/**************************************
- * Parse escapes of the form:
- *	/c/string/
- * where c is a single character.
- * Multiple escapes can be separated
- * by whitespace and/or commas.
- */
-
-void DocComment::parseEscapes(Escape **pescapetable, unsigned char *textstart, unsigned textlen)
-{   Escape *escapetable = *pescapetable;
-
-    if (!escapetable)
-    {	escapetable = new Escape;
-	*pescapetable = escapetable;
-    }
-    unsigned char *p = textstart;
-    unsigned char *pend = p + textlen;
-
-    while (1)
-    {
-	while (1)
-	{
-	    if (p + 4 >= pend)
-		return;
-	    if (!(*p == ' ' || *p == '\t' || *p == '\n' || *p == ','))
-		break;
-	    p++;
-	}
-	if (p[0] != '/' || p[2] != '/')
-	    return;
-	unsigned char c = p[1];
-	p += 3;
-	unsigned char *start = p;
-	while (1)
-	{
-	    if (p >= pend)
-		return;
-	    if (*p == '/')
-		break;
-	    p++;
-	}
-	size_t len = p - start;
-	char *s = (char *)memcpy(mem.malloc(len + 1), start, len);
-	s[len] = 0;
-	escapetable->strings[c] = s;
-	//printf("%c = '%s'\n", c, s);
-	p++;
-    }
-}
-
-
-/******************************************
- * Compare 0-terminated string with length terminated string.
- * Return < 0, ==0, > 0
- */
-
-int cmp(const char *stringz, void *s, size_t slen)
-{
-    size_t len1 = strlen(stringz);
-
-    if (len1 != slen)
-	return len1 - slen;
-    return memcmp(stringz, s, slen);
-}
-
-int icmp(const char *stringz, void *s, size_t slen)
-{
-    size_t len1 = strlen(stringz);
-
-    if (len1 != slen)
-	return len1 - slen;
-    return memicmp(stringz, (char *)s, slen);
-}
-
-/*****************************************
- * Return !=0 if comment consists entirely of "ditto".
- */
-
-int isDitto(unsigned char *comment)
-{
-    if (comment)
-    {
-	unsigned char *p = skipwhitespace(comment);
-
-	if (memicmp((char *)p, "ditto", 5) == 0 && *skipwhitespace(p + 5) == 0)
-	    return 1;
-    }
-    return 0;
-}
-
-/**********************************************
- * Skip white space.
- */
-
-unsigned char *skipwhitespace(unsigned char *p)
-{
-    for (; 1; p++)
-    {	switch (*p)
-	{
-	    case ' ':
-	    case '\t':
-	    case '\n':
-		continue;
-	}
-	break;
-    }
-    return p;
-}
-
-
-/************************************************
- * Scan forward to one of:
- *	start of identifier
- *	beginning of next line
- *	end of buf
- */
-
-unsigned skiptoident(OutBuffer *buf, unsigned i)
-{
-    for (; i < buf->offset; i++)
-    {
-	// BUG: handle unicode alpha's
-	unsigned char c = buf->data[i];
-	if (isalpha(c) || c == '_')
-	    break;
-	if (c == '\n')
-	    break;
-    }
-    return i;
-}
-
-/************************************************
- * Scan forward past end of identifier.
- */
-
-unsigned skippastident(OutBuffer *buf, unsigned i)
-{
-    for (; i < buf->offset; i++)
-    {
-	// BUG: handle unicode alpha's
-	unsigned char c = buf->data[i];
-	if (!(isalnum(c) || c == '_'))
-	    break;
-    }
-    return i;
-}
-
-
-/************************************************
- * Scan forward past URL starting at i.
- * We don't want to highlight parts of a URL.
- * Returns:
- *	i if not a URL
- *	index just past it if it is a URL
- */
-
-unsigned skippastURL(OutBuffer *buf, unsigned i)
-{   unsigned length = buf->offset - i;
-    unsigned char *p = &buf->data[i];
-    unsigned j;
-    unsigned sawdot = 0;
-
-    if (length > 7 && memicmp((char *)p, "http://", 7) == 0)
-    {
-	j = 7;
-    }
-    else if (length > 8 && memicmp((char *)p, "https://", 8) == 0)
-    {
-	j = 8;
-    }
-    else
-	goto Lno;
-
-    for (; j < length; j++)
-    {	unsigned char c = p[j];
-	if (isalnum(c))
-	    continue;
-        if (c == '-' || c == '_' || c == '?' ||
-            c == '=' || c == '%' || c == '&' ||
-            c == '/' || c == '+' || c == '#' ||
-            c == '~')
-            continue;
-        if (c == '.')
-        {
-            sawdot = 1;
-            continue;
-        }
-        break;
-    }
-    if (sawdot)
-	return i + j;
-
-Lno:
-    return i;
-}
-
-
-/****************************************************
- */
-
-int isKeyword(unsigned char *p, unsigned len)
-{
-    static const char *table[] = { "true", "false", "null" };
-
-    for (int i = 0; i < sizeof(table) / sizeof(table[0]); i++)
-    {
-	if (cmp(table[i], p, len) == 0)
-	    return 1;
-    }
-    return 0;
-}
-
-/****************************************************
- */
-
-Argument *isFunctionParameter(Dsymbol *s, unsigned char *p, unsigned len)
-{
-    FuncDeclaration *f = s->isFuncDeclaration();
-
-    /* f->type may be NULL for template members.
-     */
-    if (f && f->type)
-    {
-	TypeFunction *tf;
-	if (f->originalType)
-	{
-	    tf = (TypeFunction *)f->originalType;
-	}
-	else
-	    tf = (TypeFunction *)f->type;
-
-	if (tf->parameters)
-	{
-	    for (size_t k = 0; k < tf->parameters->dim; k++)
-	    {   Argument *arg = (Argument *)tf->parameters->data[k];
-
-		if (arg->ident && cmp(arg->ident->toChars(), p, len) == 0)
-		{
-		    return arg;
-		}
-	    }
-	}
-    }
-    return NULL;
-}
-
-/**************************************************
- * Highlight text section.
- */
-
-void highlightText(Scope *sc, Dsymbol *s, OutBuffer *buf, unsigned offset)
-{
-    //printf("highlightText()\n");
-    const char *sid = s->ident->toChars();
-    FuncDeclaration *f = s->isFuncDeclaration();
-    unsigned char *p;
-    const char *se;
-
-    int leadingBlank = 1;
-    int inCode = 0;
-    int inComment = 0;			// in <!-- ... --> comment
-    unsigned iCodeStart;		// start of code section
-
-    unsigned iLineStart = offset;
-
-    for (unsigned i = offset; i < buf->offset; i++)
-    {	unsigned char c = buf->data[i];
-
-     Lcont:
-	switch (c)
-	{
-	    case ' ':
-	    case '\t':
-		break;
-
-	    case '\n':
-		if (sc && !inCode && i == iLineStart && i + 1 < buf->offset)	// if "\n\n"
-		{
-		    static char blankline[] = "$(DDOC_BLANKLINE)\n";
-
-		    i = buf->insert(i, blankline, sizeof(blankline) - 1);
-		}
-		leadingBlank = 1;
-		iLineStart = i + 1;
-		break;
-
-	    case '<':
-		leadingBlank = 0;
-		if (inCode)
-		    break;
-		p = &buf->data[i];
-
-		// Skip over comments
-		if (p[1] == '!' && p[2] == '-' && p[3] == '-')
-		{   unsigned j = i + 4;
-		    p += 4;
-		    while (1)
-		    {
-			if (j == buf->offset)
-			    goto L1;
-			if (p[0] == '-' && p[1] == '-' && p[2] == '>')
-			{
-			    i = j + 2;	// place on closing '>'
-			    break;
-			}
-			j++;
-			p++;
-		    }
-		    break;
-		}
-
-		// Skip over HTML tag
-		if (isalpha(p[1]) || (p[1] == '/' && isalpha(p[2])))
-		{   unsigned j = i + 2;
-		    p += 2;
-		    while (1)
-		    {
-			if (j == buf->offset)
-			    goto L1;
-			if (p[0] == '>')
-			{
-			    i = j;	// place on closing '>'
-			    break;
-			}
-			j++;
-			p++;
-		    }
-		    break;
-		}
-
-	    L1:
-		// Replace '<' with '&lt;' character entity
-		se = Escape::escapeChar('<');
-		if (se)
-		{   size_t len = strlen(se);
-		    buf->remove(i, 1);
-		    i = buf->insert(i, se, len);
-		    i--;	// point to ';'
-		}
-		break;
-
-	    case '>':
-		leadingBlank = 0;
-		if (inCode)
-		    break;
-		// Replace '>' with '&gt;' character entity
-		se = Escape::escapeChar('>');
-		if (se)
-		{   size_t len = strlen(se);
-		    buf->remove(i, 1);
-		    i = buf->insert(i, se, len);
-		    i--;	// point to ';'
-		}
-		break;
-
-	    case '&':
-		leadingBlank = 0;
-		if (inCode)
-		    break;
-		p = &buf->data[i];
-		if (p[1] == '#' || isalpha(p[1]))
-		    break;			// already a character entity
-		// Replace '&' with '&amp;' character entity
-		se = Escape::escapeChar('&');
-		if (se)
-		{   size_t len = strlen(se);
-		    buf->remove(i, 1);
-		    i = buf->insert(i, se, len);
-		    i--;	// point to ';'
-		}
-		break;
-
-	    case '-':
-		/* A line beginning with --- delimits a code section.
-		 * inCode tells us if it is start or end of a code section.
-		 */
-		if (leadingBlank)
-		{   int istart = i;
-		    int eollen = 0;
-
-		    leadingBlank = 0;
-		    while (1)
-		    {
-			++i;
-			if (i >= buf->offset)
-			    break;
-			c = buf->data[i];
-			if (c == '\n')
-			{   eollen = 1;
-			    break;
-			}
-			if (c == '\r')
-			{
-			    eollen = 1;
-			    if (i + 1 >= buf->offset)
-				break;
-			    if (buf->data[i + 1] == '\n')
-			    {	eollen = 2;
-				break;
-			    }
-			}
-			// BUG: handle UTF PS and LS too
-			if (c != '-')
-			    goto Lcont;
-		    }
-		    if (i - istart < 3)
-			goto Lcont;
-
-		    // We have the start/end of a code section
-
-		    // Remove the entire --- line, including blanks and \n
-		    buf->remove(iLineStart, i - iLineStart + eollen);
-		    i = iLineStart;
-
-		    if (inCode)
-		    {
-			inCode = 0;
-			// The code section is from iCodeStart to i
-			OutBuffer codebuf;
-
-			codebuf.write(buf->data + iCodeStart, i - iCodeStart);
-			codebuf.writeByte(0);
-			highlightCode2(sc, s, &codebuf, 0);
-			buf->remove(iCodeStart, i - iCodeStart);
-			i = buf->insert(iCodeStart, codebuf.data, codebuf.offset);
-			i = buf->insert(i, ")\n", 2);
-			i--;
-		    }
-		    else
-		    {	static char pre[] = "$(D_CODE \n";
-
-			inCode = 1;
-			i = buf->insert(i, pre, sizeof(pre) - 1);
-			iCodeStart = i;
-			i--;		// place i on >
-		    }
-		}
-		break;
-
-	    default:
-		leadingBlank = 0;
-		if (sc && !inCode && (isalpha(c) || c == '_'))
-		{   unsigned j;
-
-		    j = skippastident(buf, i);
-		    if (j > i)
-		    {
-			unsigned k = skippastURL(buf, i);
-			if (k > i)
-			{   i = k - 1;
-			    break;
-			}
-
-			if (buf->data[i] == '_')	// leading '_' means no highlight
-			{
-			    buf->remove(i, 1);
-			    i = j - 1;
-			}
-			else
-			{
-			    if (cmp(sid, buf->data + i, j - i) == 0)
-			    {
-				i = buf->bracket(i, "$(DDOC_PSYMBOL ", j, ")") - 1;
-				break;
-			    }
-			    else if (isKeyword(buf->data + i, j - i))
-			    {
-				i = buf->bracket(i, "$(DDOC_KEYWORD ", j, ")") - 1;
-				break;
-			    }
-			    else
-			    {
-				if (f && isFunctionParameter(f, buf->data + i, j - i))
-				{
-				    //printf("highlighting arg '%s', i = %d, j = %d\n", arg->ident->toChars(), i, j);
-				    i = buf->bracket(i, "$(DDOC_PARAM ", j, ")") - 1;
-				    break;
-				}
-			    }
-			    i = j - 1;
-			}
-		    }
-		}
-		break;
-	}
-    }
-  Ldone:
-    ;
-}
-
-/**************************************************
- * Highlight code for DDOC section.
- */
-
-void highlightCode(Scope *sc, Dsymbol *s, OutBuffer *buf, unsigned offset)
-{
-    char *sid = s->ident->toChars();
-    FuncDeclaration *f = s->isFuncDeclaration();
-
-    //printf("highlightCode(s = '%s', kind = %s)\n", sid, s->kind());
-    for (unsigned i = offset; i < buf->offset; i++)
-    {	unsigned char c = buf->data[i];
-	const char *se;
-
-	se = Escape::escapeChar(c);
-	if (se)
-	{
-	    size_t len = strlen(se);
-	    buf->remove(i, 1);
-	    i = buf->insert(i, se, len);
-	    i--;		// point to ';'
-	}
-	else if (isalpha(c) || c == '_')
-	{   unsigned j;
-
-	    j = skippastident(buf, i);
-	    if (j > i)
-	    {
-		if (cmp(sid, buf->data + i, j - i) == 0)
-		{
-		    i = buf->bracket(i, "$(DDOC_PSYMBOL ", j, ")") - 1;
-		    continue;
-		}
-		else if (f)
-		{
-		    if (isFunctionParameter(f, buf->data + i, j - i))
-		    {
-			//printf("highlighting arg '%s', i = %d, j = %d\n", arg->ident->toChars(), i, j);
-			i = buf->bracket(i, "$(DDOC_PARAM ", j, ")") - 1;
-			continue;
-		    }
-		}
-		i = j - 1;
-	    }
-	}
-    }
-}
-
-/****************************************
- */
-
-void highlightCode3(OutBuffer *buf, unsigned char *p, unsigned char *pend)
-{
-    for (; p < pend; p++)
-    {	const char *s = Escape::escapeChar(*p);
-	if (s)
-	    buf->writestring(s);
-	else
-	    buf->writeByte(*p);
-    }
-}
-
-/**************************************************
- * Highlight code for CODE section.
- */
-
-
-void highlightCode2(Scope *sc, Dsymbol *s, OutBuffer *buf, unsigned offset)
-{
-    char *sid = s->ident->toChars();
-    FuncDeclaration *f = s->isFuncDeclaration();
-    unsigned errorsave = global.errors;
-    Lexer lex(NULL, buf->data, 0, buf->offset - 1, 0, 1);
-    Token tok;
-    OutBuffer res;
-    unsigned char *lastp = buf->data;
-    const char *highlight;
-
-    //printf("highlightCode2('%.*s')\n", buf->offset - 1, buf->data);
-    res.reserve(buf->offset);
-    while (1)
-    {
-	lex.scan(&tok);
-	highlightCode3(&res, lastp, tok.ptr);
-	highlight = NULL;
-	switch (tok.value)
-	{
-	    case TOKidentifier:
-		if (!sc)
-		    break;
-		if (cmp(sid, tok.ptr, lex.p - tok.ptr) == 0)
-		{
-		    highlight = "$(D_PSYMBOL ";
-		    break;
-		}
-		else if (f)
-		{
-		    if (isFunctionParameter(f, tok.ptr, lex.p - tok.ptr))
-		    {
-			//printf("highlighting arg '%s', i = %d, j = %d\n", arg->ident->toChars(), i, j);
-			highlight = "$(D_PARAM ";
-			break;
-		    }
-		}
-		break;
-
-	    case TOKcomment:
-		highlight = "$(D_COMMENT ";
-		break;
-
-	    case TOKstring:
-		highlight = "$(D_STRING ";
-		break;
-
-	    default:
-		if (tok.isKeyword())
-		    highlight = "$(D_KEYWORD ";
-		break;
-	}
-	if (highlight)
-	    res.writestring(highlight);
-	highlightCode3(&res, tok.ptr, lex.p);
-	if (highlight)
-	    res.writeByte(')');
-	if (tok.value == TOKeof)
-	    break;
-	lastp = lex.p;
-    }
-    buf->setsize(offset);
-    buf->write(&res);
-    global.errors = errorsave;
-}
-
-/***************************************
- * Find character string to replace c with.
- */
-
-const char *Escape::escapeChar(unsigned c)
-{   const char *s;
-
-    switch (c)
-    {
-	case '<':
-	    s = "&lt;";
-	    break;
-	case '>':
-	    s = "&gt;";
-	    break;
-	case '&':
-	    s = "&amp;";
-	    break;
-	default:
-	    s = NULL;
-	    break;
-    }
-    return s;
-}
-
+
+// 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.
+
+// This implements the Ddoc capability.
+
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+#include <ctype.h>
+#include <assert.h>
+
+#include "rmem.h"
+#include "root.h"
+
+#include "mars.h"
+#include "dsymbol.h"
+#include "macro.h"
+#include "template.h"
+#include "lexer.h"
+#include "aggregate.h"
+#include "declaration.h"
+#include "enum.h"
+#include "id.h"
+#include "module.h"
+#include "scope.h"
+#include "hdrgen.h"
+#include "doc.h"
+#include "mtype.h"
+
+struct Escape
+{
+    const char *strings[256];
+
+    static const char *escapeChar(unsigned c);
+};
+
+struct Section
+{
+    unsigned char *name;
+    unsigned namelen;
+
+    unsigned char *body;
+    unsigned bodylen;
+
+    int nooutput;
+
+    virtual void write(DocComment *dc, Scope *sc, Dsymbol *s, OutBuffer *buf);
+};
+
+struct ParamSection : Section
+{
+    void write(DocComment *dc, Scope *sc, Dsymbol *s, OutBuffer *buf);
+};
+
+struct MacroSection : Section
+{
+    void write(DocComment *dc, Scope *sc, Dsymbol *s, OutBuffer *buf);
+};
+
+struct DocComment
+{
+    Array sections;		// Section*[]
+
+    Section *summary;
+    Section *copyright;
+    Section *macros;
+    Macro **pmacrotable;
+    Escape **pescapetable;
+
+    DocComment();
+
+    static DocComment *parse(Scope *sc, Dsymbol *s, unsigned char *comment);
+    static void parseMacros(Escape **pescapetable, Macro **pmacrotable, unsigned char *m, unsigned mlen);
+    static void parseEscapes(Escape **pescapetable, unsigned char *textstart, unsigned textlen);
+
+    void parseSections(unsigned char *comment);
+    void writeSections(Scope *sc, Dsymbol *s, OutBuffer *buf);
+};
+
+
+int cmp(const char *stringz, void *s, size_t slen);
+int icmp(const char *stringz, void *s, size_t slen);
+int isDitto(unsigned char *comment);
+unsigned char *skipwhitespace(unsigned char *p);
+unsigned skiptoident(OutBuffer *buf, unsigned i);
+unsigned skippastident(OutBuffer *buf, unsigned i);
+unsigned skippastURL(OutBuffer *buf, unsigned i);
+void highlightText(Scope *sc, Dsymbol *s, OutBuffer *buf, unsigned offset);
+void highlightCode(Scope *sc, Dsymbol *s, OutBuffer *buf, unsigned offset);
+void highlightCode2(Scope *sc, Dsymbol *s, OutBuffer *buf, unsigned offset);
+Argument *isFunctionParameter(Dsymbol *s, unsigned char *p, unsigned len);
+
+static unsigned char ddoc_default[] = "\
+DDOC =	<html><head>\n\
+	<META http-equiv=\"content-type\" content=\"text/html; charset=utf-8\">\n\
+	<title>$(TITLE)</title>\n\
+	</head><body>\n\
+	<h1>$(TITLE)</h1>\n\
+	$(BODY)\n\
+	<hr>$(SMALL Page generated by $(LINK2 http://www.digitalmars.com/d/2.0/ddoc.html, Ddoc). $(COPYRIGHT))\n\
+	</body></html>\n\
+\n\
+B =	<b>$0</b>\n\
+I =	<i>$0</i>\n\
+U =	<u>$0</u>\n\
+P =	<p>$0</p>\n\
+DL =	<dl>$0</dl>\n\
+DT =	<dt>$0</dt>\n\
+DD =	<dd>$0</dd>\n\
+TABLE =	<table>$0</table>\n\
+TR =	<tr>$0</tr>\n\
+TH =	<th>$0</th>\n\
+TD =	<td>$0</td>\n\
+OL =	<ol>$0</ol>\n\
+UL =	<ul>$0</ul>\n\
+LI =	<li>$0</li>\n\
+BIG =	<big>$0</big>\n\
+SMALL =	<small>$0</small>\n\
+BR =	<br>\n\
+LINK =	<a href=\"$0\">$0</a>\n\
+LINK2 =	<a href=\"$1\">$+</a>\n\
+\n\
+RED =	<font color=red>$0</font>\n\
+BLUE =	<font color=blue>$0</font>\n\
+GREEN =	<font color=green>$0</font>\n\
+YELLOW =<font color=yellow>$0</font>\n\
+BLACK =	<font color=black>$0</font>\n\
+WHITE =	<font color=white>$0</font>\n\
+\n\
+D_CODE = <pre class=\"d_code\">$0</pre>\n\
+D_COMMENT = $(GREEN $0)\n\
+D_STRING  = $(RED $0)\n\
+D_KEYWORD = $(BLUE $0)\n\
+D_PSYMBOL = $(U $0)\n\
+D_PARAM	  = $(I $0)\n\
+\n\
+DDOC_COMMENT   = <!-- $0 -->\n\
+DDOC_DECL      = $(DT $(BIG $0))\n\
+DDOC_DECL_DD   = $(DD $0)\n\
+DDOC_DITTO     = $(BR)$0\n\
+DDOC_SECTIONS  = $0\n\
+DDOC_SUMMARY   = $0$(BR)$(BR)\n\
+DDOC_DESCRIPTION = $0$(BR)$(BR)\n\
+DDOC_AUTHORS   = $(B Authors:)$(BR)\n$0$(BR)$(BR)\n\
+DDOC_BUGS      = $(RED BUGS:)$(BR)\n$0$(BR)$(BR)\n\
+DDOC_COPYRIGHT = $(B Copyright:)$(BR)\n$0$(BR)$(BR)\n\
+DDOC_DATE      = $(B Date:)$(BR)\n$0$(BR)$(BR)\n\
+DDOC_DEPRECATED = $(RED Deprecated:)$(BR)\n$0$(BR)$(BR)\n\
+DDOC_EXAMPLES  = $(B Examples:)$(BR)\n$0$(BR)$(BR)\n\
+DDOC_HISTORY   = $(B History:)$(BR)\n$0$(BR)$(BR)\n\
+DDOC_LICENSE   = $(B License:)$(BR)\n$0$(BR)$(BR)\n\
+DDOC_RETURNS   = $(B Returns:)$(BR)\n$0$(BR)$(BR)\n\
+DDOC_SEE_ALSO  = $(B See Also:)$(BR)\n$0$(BR)$(BR)\n\
+DDOC_STANDARDS = $(B Standards:)$(BR)\n$0$(BR)$(BR)\n\
+DDOC_THROWS    = $(B Throws:)$(BR)\n$0$(BR)$(BR)\n\
+DDOC_VERSION   = $(B Version:)$(BR)\n$0$(BR)$(BR)\n\
+DDOC_SECTION_H = $(B $0)$(BR)\n\
+DDOC_SECTION   = $0$(BR)$(BR)\n\
+DDOC_MEMBERS   = $(DL $0)\n\
+DDOC_MODULE_MEMBERS = $(DDOC_MEMBERS $0)\n\
+DDOC_CLASS_MEMBERS  = $(DDOC_MEMBERS $0)\n\
+DDOC_STRUCT_MEMBERS = $(DDOC_MEMBERS $0)\n\
+DDOC_ENUM_MEMBERS   = $(DDOC_MEMBERS $0)\n\
+DDOC_TEMPLATE_MEMBERS = $(DDOC_MEMBERS $0)\n\
+DDOC_PARAMS    = $(B Params:)$(BR)\n$(TABLE $0)$(BR)\n\
+DDOC_PARAM_ROW = $(TR $0)\n\
+DDOC_PARAM_ID  = $(TD $0)\n\
+DDOC_PARAM_DESC = $(TD $0)\n\
+DDOC_BLANKLINE	= $(BR)$(BR)\n\
+\n\
+DDOC_PSYMBOL	= $(U $0)\n\
+DDOC_KEYWORD	= $(B $0)\n\
+DDOC_PARAM	= $(I $0)\n\
+\n\
+ESCAPES = /</&lt;/\n\
+	  />/&gt;/\n\
+	  /&/&amp;/\n\
+";
+
+static char ddoc_decl_s[] = "$(DDOC_DECL ";
+static char ddoc_decl_e[] = ")\n";
+
+static char ddoc_decl_dd_s[] = "$(DDOC_DECL_DD ";
+static char ddoc_decl_dd_e[] = ")\n";
+
+
+/****************************************************
+ */
+
+void Module::gendocfile()
+{
+    static OutBuffer mbuf;
+    static int mbuf_done;
+
+    OutBuffer buf;
+
+    //printf("Module::gendocfile()\n");
+
+    if (!mbuf_done)		// if not already read the ddoc files
+    {	mbuf_done = 1;
+
+	// Use our internal default
+	mbuf.write(ddoc_default, sizeof(ddoc_default) - 1);
+
+	// Override with DDOCFILE specified in the sc.ini file
+	char *p = getenv("DDOCFILE");
+	if (p)
+	    global.params.ddocfiles->shift(p);
+
+	// Override with the ddoc macro files from the command line
+	for (int i = 0; i < global.params.ddocfiles->dim; i++)
+	{
+	    FileName f((char *)global.params.ddocfiles->data[i], 0);
+	    File file(&f);
+	    file.readv();
+	    // BUG: convert file contents to UTF-8 before use
+
+	    //printf("file: '%.*s'\n", file.len, file.buffer);
+	    mbuf.write(file.buffer, file.len);
+	}
+    }
+    DocComment::parseMacros(&escapetable, &macrotable, mbuf.data, mbuf.offset);
+
+    Scope *sc = Scope::createGlobal(this);	// create root scope
+    sc->docbuf = &buf;
+
+    DocComment *dc = DocComment::parse(sc, this, comment);
+    dc->pmacrotable = &macrotable;
+    dc->pescapetable = &escapetable;
+
+    // Generate predefined macros
+
+    // Set the title to be the name of the module
+    {	char *p = toPrettyChars();
+	Macro::define(&macrotable, (unsigned char *)"TITLE", 5, (unsigned char *)p, strlen(p));
+    }
+
+    time_t t;
+    time(&t);
+    char *p = ctime(&t);
+    p = mem.strdup(p);
+    Macro::define(&macrotable, (unsigned char *)"DATETIME", 8, (unsigned char *)p, strlen(p));
+    Macro::define(&macrotable, (unsigned char *)"YEAR", 4, (unsigned char *)p + 20, 4);
+
+    char *docfilename = docfile->toChars();
+    Macro::define(&macrotable, (unsigned char *)"DOCFILENAME", 11, (unsigned char *)docfilename, strlen(docfilename));
+
+    if (dc->copyright)
+    {
+	dc->copyright->nooutput = 1;
+	Macro::define(&macrotable, (unsigned char *)"COPYRIGHT", 9, dc->copyright->body, dc->copyright->bodylen);
+    }
+
+    buf.printf("$(DDOC_COMMENT Generated by Ddoc from %s)\n", srcfile->toChars());
+    if (isDocFile)
+    {
+	size_t commentlen = strlen((char *)comment);
+	if (dc->macros)
+	{
+	    commentlen = dc->macros->name - comment;
+	    dc->macros->write(dc, sc, this, sc->docbuf);
+	}
+	sc->docbuf->write(comment, commentlen);
+	highlightText(NULL, this, sc->docbuf, 0);
+    }
+    else
+    {
+	dc->writeSections(sc, this, sc->docbuf);
+	emitMemberComments(sc);
+    }
+
+    //printf("BODY= '%.*s'\n", buf.offset, buf.data);
+    Macro::define(&macrotable, (unsigned char *)"BODY", 4, buf.data, buf.offset);
+
+    OutBuffer buf2;
+    buf2.writestring("$(DDOC)\n");
+    unsigned end = buf2.offset;
+    macrotable->expand(&buf2, 0, &end, NULL, 0);
+
+#if 1
+    /* Remove all the escape sequences from buf2,
+     * and make CR-LF the newline.
+     */
+    {
+	buf.setsize(0);
+	buf.reserve(buf2.offset);
+	unsigned char *p = buf2.data;
+	for (unsigned j = 0; j < buf2.offset; j++)
+	{
+	    unsigned char c = p[j];
+	    if (c == 0xFF && j + 1 < buf2.offset)
+	    {
+		j++;
+		continue;
+	    }
+	    if (c == '\n')
+		buf.writeByte('\r');
+	    else if (c == '\r')
+	    {
+		buf.writestring("\r\n");
+		if (j + 1 < buf2.offset && p[j + 1] == '\n')
+		{
+		    j++;
+		}
+		continue;
+	    }
+	    buf.writeByte(c);
+	}
+    }
+
+    // Transfer image to file
+    assert(docfile);
+    docfile->setbuffer(buf.data, buf.offset);
+    docfile->ref = 1;
+    char *pt = FileName::path(docfile->toChars());
+    if (*pt)
+	FileName::ensurePathExists(pt);
+    mem.free(pt);
+    docfile->writev();
+#else
+    /* Remove all the escape sequences from buf2
+     */
+    {	unsigned i = 0;
+	unsigned char *p = buf2.data;
+	for (unsigned j = 0; j < buf2.offset; j++)
+	{
+	    if (p[j] == 0xFF && j + 1 < buf2.offset)
+	    {
+		j++;
+		continue;
+	    }
+	    p[i] = p[j];
+	    i++;
+	}
+	buf2.setsize(i);
+    }
+
+    // Transfer image to file
+    docfile->setbuffer(buf2.data, buf2.offset);
+    docfile->ref = 1;
+    char *pt = FileName::path(docfile->toChars());
+    if (*pt)
+	FileName::ensurePathExists(pt);
+    mem.free(pt);
+    docfile->writev();
+#endif
+}
+
+/******************************* emitComment **********************************/
+
+/*
+ * Emit doc comment to documentation file
+ */
+
+void Dsymbol::emitDitto(Scope *sc)
+{
+    //printf("Dsymbol::emitDitto() %s %s\n", kind(), toChars());
+    OutBuffer *buf = sc->docbuf;
+    unsigned o;
+    OutBuffer b;
+
+    b.writestring("$(DDOC_DITTO ");
+	o = b.offset;
+	toDocBuffer(&b);
+	//printf("b: '%.*s'\n", b.offset, b.data);
+	/* If 'this' is a function template, then highlightCode() was
+	 * already run by FuncDeclaration::toDocbuffer().
+	 */
+	TemplateDeclaration *td;
+	if (parent &&
+	    (td = parent->isTemplateDeclaration()) != NULL &&
+	    td->onemember == this)
+	{
+	}
+	else
+	    highlightCode(sc, this, &b, o);
+    b.writeByte(')');
+    buf->spread(sc->lastoffset, b.offset);
+    memcpy(buf->data + sc->lastoffset, b.data, b.offset);
+    sc->lastoffset += b.offset;
+}
+
+void ScopeDsymbol::emitMemberComments(Scope *sc)
+{
+    //printf("ScopeDsymbol::emitMemberComments() %s\n", toChars());
+    OutBuffer *buf = sc->docbuf;
+
+    if (members)
+    {	const char *m = "$(DDOC_MEMBERS \n";
+
+	if (isModule())
+	    m = "$(DDOC_MODULE_MEMBERS \n";
+	else if (isClassDeclaration())
+	    m = "$(DDOC_CLASS_MEMBERS \n";
+	else if (isStructDeclaration())
+	    m = "$(DDOC_STRUCT_MEMBERS \n";
+	else if (isEnumDeclaration())
+	    m = "$(DDOC_ENUM_MEMBERS \n";
+	else if (isTemplateDeclaration())
+	    m = "$(DDOC_TEMPLATE_MEMBERS \n";
+
+	unsigned offset1 = buf->offset;		// save starting offset
+	buf->writestring(m);
+	unsigned offset2 = buf->offset;		// to see if we write anything
+	sc = sc->push(this);
+	for (int i = 0; i < members->dim; i++)
+	{
+	    Dsymbol *s = (Dsymbol *)members->data[i];
+	    //printf("\ts = '%s'\n", s->toChars());
+	    s->emitComment(sc);
+	}
+	sc->pop();
+	if (buf->offset == offset2)
+	{
+	    /* Didn't write out any members, so back out last write
+	     */
+	    buf->offset = offset1;
+	}
+	else
+	    buf->writestring(")\n");
+    }
+}
+
+void emitProtection(OutBuffer *buf, PROT prot)
+{
+    const char *p;
+
+    switch (prot)
+    {
+	case PROTpackage:	p = "package";	 break;
+	case PROTprotected:	p = "protected"; break;
+	case PROTexport:	p = "export";	 break;
+	default:		p = NULL;	 break;
+    }
+    if (p)
+	buf->printf("%s ", p);
+}
+
+void Dsymbol::emitComment(Scope *sc)		   { }
+void InvariantDeclaration::emitComment(Scope *sc)  { }
+#if DMDV2
+void PostBlitDeclaration::emitComment(Scope *sc)   { }
+#endif
+void DtorDeclaration::emitComment(Scope *sc)	   { }
+void StaticCtorDeclaration::emitComment(Scope *sc) { }
+void StaticDtorDeclaration::emitComment(Scope *sc) { }
+void ClassInfoDeclaration::emitComment(Scope *sc)  { }
+void ModuleInfoDeclaration::emitComment(Scope *sc) { }
+void TypeInfoDeclaration::emitComment(Scope *sc)   { }
+
+
+void Declaration::emitComment(Scope *sc)
+{
+    //printf("Declaration::emitComment(%p '%s'), comment = '%s'\n", this, toChars(), comment);
+    //printf("type = %p\n", type);
+
+    if (protection == PROTprivate || !ident ||
+	(!type && !isCtorDeclaration() && !isAliasDeclaration()))
+	return;
+    if (!comment)
+	return;
+
+    OutBuffer *buf = sc->docbuf;
+    DocComment *dc = DocComment::parse(sc, this, comment);
+    unsigned o;
+
+    if (!dc)
+    {
+	emitDitto(sc);
+	return;
+    }
+    dc->pmacrotable = &sc->module->macrotable;
+
+    buf->writestring(ddoc_decl_s);
+	o = buf->offset;
+	toDocBuffer(buf);
+	highlightCode(sc, this, buf, o);
+	sc->lastoffset = buf->offset;
+    buf->writestring(ddoc_decl_e);
+
+    buf->writestring(ddoc_decl_dd_s);
+    dc->writeSections(sc, this, buf);
+    buf->writestring(ddoc_decl_dd_e);
+}
+
+void AggregateDeclaration::emitComment(Scope *sc)
+{
+    //printf("AggregateDeclaration::emitComment() '%s'\n", toChars());
+    if (prot() == PROTprivate)
+	return;
+    if (!comment)
+	return;
+
+    OutBuffer *buf = sc->docbuf;
+    DocComment *dc = DocComment::parse(sc, this, comment);
+
+    if (!dc)
+    {
+	emitDitto(sc);
+	return;
+    }
+    dc->pmacrotable = &sc->module->macrotable;
+
+    buf->writestring(ddoc_decl_s);
+    toDocBuffer(buf);
+    sc->lastoffset = buf->offset;
+    buf->writestring(ddoc_decl_e);
+
+    buf->writestring(ddoc_decl_dd_s);
+    dc->writeSections(sc, this, buf);
+    emitMemberComments(sc);
+    buf->writestring(ddoc_decl_dd_e);
+}
+
+void TemplateDeclaration::emitComment(Scope *sc)
+{
+    //printf("TemplateDeclaration::emitComment() '%s', kind = %s\n", toChars(), kind());
+    if (prot() == PROTprivate)
+	return;
+
+    unsigned char *com = comment;
+    int hasmembers = 1;
+
+    Dsymbol *ss = this;
+
+    if (onemember)
+    {
+	ss = onemember->isAggregateDeclaration();
+	if (!ss)
+	{
+	    ss = onemember->isFuncDeclaration();
+	    if (ss)
+	    {	hasmembers = 0;
+		if (com != ss->comment)
+		    com = Lexer::combineComments(com, ss->comment);
+	    }
+	    else
+		ss = this;
+	}
+    }
+
+    if (!com)
+	return;
+
+    OutBuffer *buf = sc->docbuf;
+    DocComment *dc = DocComment::parse(sc, this, com);
+    unsigned o;
+
+    if (!dc)
+    {
+	ss->emitDitto(sc);
+	return;
+    }
+    dc->pmacrotable = &sc->module->macrotable;
+
+    buf->writestring(ddoc_decl_s);
+	o = buf->offset;
+	ss->toDocBuffer(buf);
+	if (ss == this)
+	    highlightCode(sc, this, buf, o);
+	sc->lastoffset = buf->offset;
+    buf->writestring(ddoc_decl_e);
+
+    buf->writestring(ddoc_decl_dd_s);
+    dc->writeSections(sc, this, buf);
+    if (hasmembers)
+	((ScopeDsymbol *)ss)->emitMemberComments(sc);
+    buf->writestring(ddoc_decl_dd_e);
+}
+
+void EnumDeclaration::emitComment(Scope *sc)
+{
+    if (prot() == PROTprivate)
+	return;
+//    if (!comment)
+    {	if (isAnonymous() && members)
+	{
+	    for (int i = 0; i < members->dim; i++)
+	    {
+		Dsymbol *s = (Dsymbol *)members->data[i];
+		s->emitComment(sc);
+	    }
+	    return;
+	}
+    }
+    if (!comment)
+	return;
+    if (isAnonymous())
+	return;
+
+    OutBuffer *buf = sc->docbuf;
+    DocComment *dc = DocComment::parse(sc, this, comment);
+
+    if (!dc)
+    {
+	emitDitto(sc);
+	return;
+    }
+    dc->pmacrotable = &sc->module->macrotable;
+
+    buf->writestring(ddoc_decl_s);
+	toDocBuffer(buf);
+	sc->lastoffset = buf->offset;
+    buf->writestring(ddoc_decl_e);
+
+    buf->writestring(ddoc_decl_dd_s);
+    dc->writeSections(sc, this, buf);
+    emitMemberComments(sc);
+    buf->writestring(ddoc_decl_dd_e);
+}
+
+void EnumMember::emitComment(Scope *sc)
+{
+    //printf("EnumMember::emitComment(%p '%s'), comment = '%s'\n", this, toChars(), comment);
+    if (prot() == PROTprivate)
+	return;
+    if (!comment)
+	return;
+
+    OutBuffer *buf = sc->docbuf;
+    DocComment *dc = DocComment::parse(sc, this, comment);
+    unsigned o;
+
+    if (!dc)
+    {
+	emitDitto(sc);
+	return;
+    }
+    dc->pmacrotable = &sc->module->macrotable;
+
+    buf->writestring(ddoc_decl_s);
+	o = buf->offset;
+	toDocBuffer(buf);
+	highlightCode(sc, this, buf, o);
+	sc->lastoffset = buf->offset;
+    buf->writestring(ddoc_decl_e);
+
+    buf->writestring(ddoc_decl_dd_s);
+    dc->writeSections(sc, this, buf);
+    buf->writestring(ddoc_decl_dd_e);
+}
+
+/******************************* toDocBuffer **********************************/
+
+void Dsymbol::toDocBuffer(OutBuffer *buf)
+{
+    //printf("Dsymbol::toDocbuffer() %s\n", toChars());
+    HdrGenState hgs;
+
+    hgs.ddoc = 1;
+    toCBuffer(buf, &hgs);
+}
+
+void prefix(OutBuffer *buf, Dsymbol *s)
+{
+    if (s->isDeprecated())
+	buf->writestring("deprecated ");
+    Declaration *d = s->isDeclaration();
+    if (d)
+    {
+	emitProtection(buf, d->protection);
+	if (d->isAbstract())
+	    buf->writestring("abstract ");
+	if (d->isStatic())
+	    buf->writestring("static ");
+	if (d->isConst())
+	    buf->writestring("const ");
+#if DMDV2
+	if (d->isInvariant())
+	    buf->writestring("invariant ");
+#endif
+	if (d->isFinal())
+	    buf->writestring("final ");
+	if (d->isSynchronized())
+	    buf->writestring("synchronized ");
+    }
+}
+
+void Declaration::toDocBuffer(OutBuffer *buf)
+{
+    //printf("Declaration::toDocbuffer() %s, originalType = %p\n", toChars(), originalType);
+    if (ident)
+    {
+	prefix(buf, this);
+
+	if (type)
+	{   HdrGenState hgs;
+	    hgs.ddoc = 1;
+	    if (originalType)
+	    {	//originalType->print();
+		originalType->toCBuffer(buf, ident, &hgs);
+	    }
+	    else
+		type->toCBuffer(buf, ident, &hgs);
+	}
+	else
+	    buf->writestring(ident->toChars());
+	buf->writestring(";\n");
+    }
+}
+
+
+void AliasDeclaration::toDocBuffer(OutBuffer *buf)
+{
+    //printf("AliasDeclaration::toDocbuffer() %s\n", toChars());
+    if (ident)
+    {
+	if (isDeprecated())
+	    buf->writestring("deprecated ");
+
+	emitProtection(buf, protection);
+	buf->writestring("alias ");
+	buf->writestring(toChars());
+	buf->writestring(";\n");
+    }
+}
+
+
+void TypedefDeclaration::toDocBuffer(OutBuffer *buf)
+{
+    if (ident)
+    {
+	if (isDeprecated())
+	    buf->writestring("deprecated ");
+
+	emitProtection(buf, protection);
+	buf->writestring("typedef ");
+	buf->writestring(toChars());
+	buf->writestring(";\n");
+    }
+}
+
+
+void FuncDeclaration::toDocBuffer(OutBuffer *buf)
+{
+    //printf("FuncDeclaration::toDocbuffer() %s\n", toChars());
+    if (ident)
+    {
+	TemplateDeclaration *td;
+
+	if (parent &&
+	    (td = parent->isTemplateDeclaration()) != NULL &&
+	    td->onemember == this)
+	{   /* It's a function template
+	     */
+	    HdrGenState hgs;
+	    unsigned o = buf->offset;
+	    TypeFunction *tf = (TypeFunction *)type;
+
+	    hgs.ddoc = 1;
+	    prefix(buf, td);
+	    tf->next->toCBuffer(buf, NULL, &hgs);
+	    buf->writeByte(' ');
+	    buf->writestring(ident->toChars());
+	    buf->writeByte('(');
+	    for (int i = 0; i < td->origParameters->dim; i++)
+	    {
+		TemplateParameter *tp = (TemplateParameter *)td->origParameters->data[i];
+		if (i)
+		    buf->writestring(", ");
+		tp->toCBuffer(buf, &hgs);
+	    }
+	    buf->writeByte(')');
+	    Argument::argsToCBuffer(buf, &hgs, tf->parameters, tf->varargs);
+	    buf->writestring(";\n");
+
+	    highlightCode(NULL, this, buf, o);
+	}
+	else
+	{
+	    Declaration::toDocBuffer(buf);
+	}
+    }
+}
+
+void CtorDeclaration::toDocBuffer(OutBuffer *buf)
+{
+    HdrGenState hgs;
+
+    buf->writestring("this");
+    Argument::argsToCBuffer(buf, &hgs, arguments, varargs);
+    buf->writestring(";\n");
+}
+
+
+void AggregateDeclaration::toDocBuffer(OutBuffer *buf)
+{
+    if (ident)
+    {
+#if 0
+	emitProtection(buf, protection);
+#endif
+	buf->printf("%s $(DDOC_PSYMBOL %s)", kind(), toChars());
+	buf->writestring(";\n");
+    }
+}
+
+void StructDeclaration::toDocBuffer(OutBuffer *buf)
+{
+    //printf("StructDeclaration::toDocbuffer() %s\n", toChars());
+    if (ident)
+    {
+#if 0
+	emitProtection(buf, protection);
+#endif
+	TemplateDeclaration *td;
+
+	if (parent &&
+	    (td = parent->isTemplateDeclaration()) != NULL &&
+	    td->onemember == this)
+	{   unsigned o = buf->offset;
+	    td->toDocBuffer(buf);
+	    highlightCode(NULL, this, buf, o);
+	}
+	else
+	{
+	    buf->printf("%s $(DDOC_PSYMBOL %s)", kind(), toChars());
+	}
+	buf->writestring(";\n");
+    }
+}
+
+void ClassDeclaration::toDocBuffer(OutBuffer *buf)
+{
+    //printf("ClassDeclaration::toDocbuffer() %s\n", toChars());
+    if (ident)
+    {
+#if 0
+	emitProtection(buf, protection);
+#endif
+	TemplateDeclaration *td;
+
+	if (parent &&
+	    (td = parent->isTemplateDeclaration()) != NULL &&
+	    td->onemember == this)
+	{   unsigned o = buf->offset;
+	    td->toDocBuffer(buf);
+	    highlightCode(NULL, this, buf, o);
+	}
+	else
+	{
+	    if (isAbstract())
+		buf->writestring("abstract ");
+	    buf->printf("%s $(DDOC_PSYMBOL %s)", kind(), toChars());
+	}
+	int any = 0;
+	for (int i = 0; i < baseclasses.dim; i++)
+	{   BaseClass *bc = (BaseClass *)baseclasses.data[i];
+
+	    if (bc->protection == PROTprivate)
+		continue;
+	    if (bc->base && bc->base->ident == Id::Object)
+		continue;
+
+	    if (any)
+		buf->writestring(", ");
+	    else
+	    {	buf->writestring(": ");
+		any = 1;
+	    }
+	    emitProtection(buf, bc->protection);
+	    if (bc->base)
+	    {
+		buf->writestring(bc->base->toPrettyChars());
+	    }
+	    else
+	    {
+		HdrGenState hgs;
+		bc->type->toCBuffer(buf, NULL, &hgs);
+	    }
+	}
+	buf->writestring(";\n");
+    }
+}
+
+
+void EnumDeclaration::toDocBuffer(OutBuffer *buf)
+{
+    if (ident)
+    {
+	buf->printf("%s $(DDOC_PSYMBOL %s)", kind(), toChars());
+	buf->writestring(";\n");
+    }
+}
+
+void EnumMember::toDocBuffer(OutBuffer *buf)
+{
+    if (ident)
+    {
+	buf->writestring(toChars());
+    }
+}
+
+
+/********************************* DocComment *********************************/
+
+DocComment::DocComment()
+{
+    memset(this, 0, sizeof(DocComment));
+}
+
+DocComment *DocComment::parse(Scope *sc, Dsymbol *s, unsigned char *comment)
+{   unsigned idlen;
+
+    //printf("parse(%s): '%s'\n", s->toChars(), comment);
+    if (sc->lastdc && isDitto(comment))
+	return NULL;
+
+    DocComment *dc = new DocComment();
+    if (!comment)
+	return dc;
+
+    dc->parseSections(comment);
+
+    for (int i = 0; i < dc->sections.dim; i++)
+    {	Section *s = (Section *)dc->sections.data[i];
+
+	if (icmp("copyright", s->name, s->namelen) == 0)
+	{
+	    dc->copyright = s;
+	}
+	if (icmp("macros", s->name, s->namelen) == 0)
+	{
+	    dc->macros = s;
+	}
+    }
+
+    sc->lastdc = dc;
+    return dc;
+}
+
+/*****************************************
+ * Parse next paragraph out of *pcomment.
+ * Update *pcomment to point past paragraph.
+ * Returns NULL if no more paragraphs.
+ * If paragraph ends in 'identifier:',
+ * then (*pcomment)[0 .. idlen] is the identifier.
+ */
+
+void DocComment::parseSections(unsigned char *comment)
+{   unsigned char *p;
+    unsigned char *pstart;
+    unsigned char *pend;
+    unsigned char *q;
+    unsigned char *idstart;
+    unsigned idlen;
+
+    unsigned char *name = NULL;
+    unsigned namelen = 0;
+
+    //printf("parseSections('%s')\n", comment);
+    p = comment;
+    while (*p)
+    {
+	p = skipwhitespace(p);
+	pstart = p;
+
+	/* Find end of section, which is ended by one of:
+	 *	'identifier:'
+	 *	'\0'
+	 */
+	idlen = 0;
+	while (1)
+	{
+	    if (isalpha(*p) || *p == '_')
+	    {
+		q = p + 1;
+		while (isalnum(*q) || *q == '_')
+		    q++;
+		if (*q == ':')	// identifier: ends it
+		{   idlen = q - p;
+		    idstart = p;
+		    for (pend = p; pend > pstart; pend--)
+		    {	if (pend[-1] == '\n')
+			    break;
+		    }
+		    p = q + 1;
+		    break;
+		}
+	    }
+	    while (1)
+	    {
+		if (!*p)
+		{   pend = p;
+		    goto L1;
+		}
+		if (*p == '\n')
+		{   p++;
+		    if (*p == '\n' && !summary && !namelen)
+		    {
+			pend = p;
+			p++;
+			goto L1;
+		    }
+		    break;
+		}
+		p++;
+	    }
+	    p = skipwhitespace(p);
+	}
+      L1:
+
+	if (namelen || pstart < pend)
+	{
+	    Section *s;
+	    if (icmp("Params", name, namelen) == 0)
+		s = new ParamSection();
+	    else if (icmp("Macros", name, namelen) == 0)
+		s = new MacroSection();
+	    else
+		s = new Section();
+	    s->name = name;
+	    s->namelen = namelen;
+	    s->body = pstart;
+	    s->bodylen = pend - pstart;
+	    s->nooutput = 0;
+
+	    //printf("Section: '%.*s' = '%.*s'\n", s->namelen, s->name, s->bodylen, s->body);
+
+	    sections.push(s);
+
+	    if (!summary && !namelen)
+		summary = s;
+	}
+
+	if (idlen)
+	{   name = idstart;
+	    namelen = idlen;
+	}
+	else
+	{   name = NULL;
+	    namelen = 0;
+	    if (!*p)
+		break;
+	}
+    }
+}
+
+void DocComment::writeSections(Scope *sc, Dsymbol *s, OutBuffer *buf)
+{
+    //printf("DocComment::writeSections()\n");
+    if (sections.dim)
+    {
+	buf->writestring("$(DDOC_SECTIONS \n");
+	for (int i = 0; i < sections.dim; i++)
+	{   Section *sec = (Section *)sections.data[i];
+
+	    if (sec->nooutput)
+		continue;
+	    //printf("Section: '%.*s' = '%.*s'\n", sec->namelen, sec->name, sec->bodylen, sec->body);
+	    if (sec->namelen || i)
+		sec->write(this, sc, s, buf);
+	    else
+	    {
+		buf->writestring("$(DDOC_SUMMARY ");
+		    unsigned o = buf->offset;
+		    buf->write(sec->body, sec->bodylen);
+		    highlightText(sc, s, buf, o);
+		buf->writestring(")\n");
+	    }
+	}
+	buf->writestring(")\n");
+    }
+    else
+    {
+	buf->writestring("$(DDOC_BLANKLINE)\n");
+    }
+}
+
+/***************************************************
+ */
+
+void Section::write(DocComment *dc, Scope *sc, Dsymbol *s, OutBuffer *buf)
+{
+    if (namelen)
+    {
+	static const char *table[] =
+	{	"AUTHORS", "BUGS", "COPYRIGHT", "DATE",
+		"DEPRECATED", "EXAMPLES", "HISTORY", "LICENSE",
+		"RETURNS", "SEE_ALSO", "STANDARDS", "THROWS",
+		"VERSION" };
+
+	for (int i = 0; i < sizeof(table) / sizeof(table[0]); i++)
+	{
+	    if (icmp(table[i], name, namelen) == 0)
+	    {
+		buf->printf("$(DDOC_%s ", table[i]);
+		goto L1;
+	    }
+	}
+
+	buf->writestring("$(DDOC_SECTION ");
+	    // Replace _ characters with spaces
+	    buf->writestring("$(DDOC_SECTION_H ");
+	    for (unsigned u = 0; u < namelen; u++)
+	    {   unsigned char c = name[u];
+		buf->writeByte((c == '_') ? ' ' : c);
+	    }
+	    buf->writestring(":)\n");
+    }
+    else
+    {
+	buf->writestring("$(DDOC_DESCRIPTION ");
+    }
+  L1:
+    unsigned o = buf->offset;
+    buf->write(body, bodylen);
+    highlightText(sc, s, buf, o);
+    buf->writestring(")\n");
+}
+
+/***************************************************
+ */
+
+void ParamSection::write(DocComment *dc, Scope *sc, Dsymbol *s, OutBuffer *buf)
+{
+    unsigned char *p = body;
+    unsigned len = bodylen;
+    unsigned char *pend = p + len;
+
+    unsigned char *tempstart;
+    unsigned templen;
+
+    unsigned char *namestart;
+    unsigned namelen = 0;	// !=0 if line continuation
+
+    unsigned char *textstart;
+    unsigned textlen;
+
+    unsigned o;
+    Argument *arg;
+
+    buf->writestring("$(DDOC_PARAMS \n");
+    while (p < pend)
+    {
+	// Skip to start of macro
+	for (; 1; p++)
+	{
+	    switch (*p)
+	    {
+		case ' ':
+		case '\t':
+		    continue;
+
+		case '\n':
+		    p++;
+		    goto Lcont;
+
+		default:
+		    if (!(isalpha(*p) || *p == '_'))
+		    {
+			if (namelen)
+			    goto Ltext;		// continuation of prev macro
+			goto Lskipline;
+		    }
+		    break;
+	    }
+	    break;
+	}
+	tempstart = p;
+
+	while (isalnum(*p) || *p == '_')
+	    p++;
+	templen = p - tempstart;
+
+	while (*p == ' ' || *p == '\t')
+	    p++;
+
+	if (*p != '=')
+	{   if (namelen)
+		goto Ltext;		// continuation of prev macro
+	    goto Lskipline;
+	}
+	p++;
+
+	if (namelen)
+	{   // Output existing param
+
+	L1:
+	    //printf("param '%.*s' = '%.*s'\n", namelen, namestart, textlen, textstart);
+	    HdrGenState hgs;
+	    buf->writestring("$(DDOC_PARAM_ROW ");
+		buf->writestring("$(DDOC_PARAM_ID ");
+		    o = buf->offset;
+		    arg = isFunctionParameter(s, namestart, namelen);
+		    if (arg && arg->type && arg->ident)
+			arg->type->toCBuffer(buf, arg->ident, &hgs);
+		    else
+			buf->write(namestart, namelen);
+		    highlightCode(sc, s, buf, o);
+		buf->writestring(")\n");
+
+		buf->writestring("$(DDOC_PARAM_DESC ");
+		    o = buf->offset;
+		    buf->write(textstart, textlen);
+		    highlightText(sc, s, buf, o);
+		buf->writestring(")");
+	    buf->writestring(")\n");
+	    namelen = 0;
+	    if (p >= pend)
+		break;
+	}
+
+	namestart = tempstart;
+	namelen = templen;
+
+	while (*p == ' ' || *p == '\t')
+	    p++;
+	textstart = p;
+
+      Ltext:
+	while (*p != '\n')
+	    p++;
+	textlen = p - textstart;
+	p++;
+
+     Lcont:
+	continue;
+
+     Lskipline:
+	// Ignore this line
+	while (*p++ != '\n')
+	    ;
+    }
+    if (namelen)
+	goto L1;		// write out last one
+    buf->writestring(")\n");
+}
+
+/***************************************************
+ */
+
+void MacroSection::write(DocComment *dc, Scope *sc, Dsymbol *s, OutBuffer *buf)
+{
+    //printf("MacroSection::write()\n");
+    DocComment::parseMacros(dc->pescapetable, dc->pmacrotable, body, bodylen);
+}
+
+/************************************************
+ * Parse macros out of Macros: section.
+ * Macros are of the form:
+ *	name1 = value1
+ *
+ *	name2 = value2
+ */
+
+void DocComment::parseMacros(Escape **pescapetable, Macro **pmacrotable, unsigned char *m, unsigned mlen)
+{
+    unsigned char *p = m;
+    unsigned len = mlen;
+    unsigned char *pend = p + len;
+
+    unsigned char *tempstart;
+    unsigned templen;
+
+    unsigned char *namestart;
+    unsigned namelen = 0;	// !=0 if line continuation
+
+    unsigned char *textstart;
+    unsigned textlen;
+
+    while (p < pend)
+    {
+	// Skip to start of macro
+	for (; 1; p++)
+	{
+	    if (p >= pend)
+		goto Ldone;
+	    switch (*p)
+	    {
+		case ' ':
+		case '\t':
+		    continue;
+
+		case '\n':
+		    p++;
+		    goto Lcont;
+
+		default:
+		    if (!(isalpha(*p) || *p == '_'))
+		    {
+			if (namelen)
+			    goto Ltext;		// continuation of prev macro
+			goto Lskipline;
+		    }
+		    break;
+	    }
+	    break;
+	}
+	tempstart = p;
+
+	while (1)
+	{
+	    if (p >= pend)
+		goto Ldone;
+	    if (!(isalnum(*p) || *p == '_'))
+		break;
+	    p++;
+	}
+	templen = p - tempstart;
+
+	while (1)
+	{
+	    if (p >= pend)
+		goto Ldone;
+	    if (!(*p == ' ' || *p == '\t'))
+		break;
+	    p++;
+	}
+
+	if (*p != '=')
+	{   if (namelen)
+		goto Ltext;		// continuation of prev macro
+	    goto Lskipline;
+	}
+	p++;
+	if (p >= pend)
+	    goto Ldone;
+
+	if (namelen)
+	{   // Output existing macro
+	L1:
+	    //printf("macro '%.*s' = '%.*s'\n", namelen, namestart, textlen, textstart);
+	    if (icmp("ESCAPES", namestart, namelen) == 0)
+		parseEscapes(pescapetable, textstart, textlen);
+	    else
+		Macro::define(pmacrotable, namestart, namelen, textstart, textlen);
+	    namelen = 0;
+	    if (p >= pend)
+		break;
+	}
+
+	namestart = tempstart;
+	namelen = templen;
+
+	while (p < pend && (*p == ' ' || *p == '\t'))
+	    p++;
+	textstart = p;
+
+      Ltext:
+	while (p < pend && *p != '\n')
+	    p++;
+	textlen = p - textstart;
+
+	// Remove trailing \r if there is one
+	if (p > m && p[-1] == '\r')
+	    textlen--;
+
+	p++;
+	//printf("p = %p, pend = %p\n", p, pend);
+
+     Lcont:
+	continue;
+
+     Lskipline:
+	// Ignore this line
+	while (p < pend && *p++ != '\n')
+	    ;
+    }
+Ldone:
+    if (namelen)
+	goto L1;		// write out last one
+}
+
+/**************************************
+ * Parse escapes of the form:
+ *	/c/string/
+ * where c is a single character.
+ * Multiple escapes can be separated
+ * by whitespace and/or commas.
+ */
+
+void DocComment::parseEscapes(Escape **pescapetable, unsigned char *textstart, unsigned textlen)
+{   Escape *escapetable = *pescapetable;
+
+    if (!escapetable)
+    {	escapetable = new Escape;
+	*pescapetable = escapetable;
+    }
+    unsigned char *p = textstart;
+    unsigned char *pend = p + textlen;
+
+    while (1)
+    {
+	while (1)
+	{
+	    if (p + 4 >= pend)
+		return;
+	    if (!(*p == ' ' || *p == '\t' || *p == '\n' || *p == ','))
+		break;
+	    p++;
+	}
+	if (p[0] != '/' || p[2] != '/')
+	    return;
+	unsigned char c = p[1];
+	p += 3;
+	unsigned char *start = p;
+	while (1)
+	{
+	    if (p >= pend)
+		return;
+	    if (*p == '/')
+		break;
+	    p++;
+	}
+	size_t len = p - start;
+	char *s = (char *)memcpy(mem.malloc(len + 1), start, len);
+	s[len] = 0;
+	escapetable->strings[c] = s;
+	//printf("%c = '%s'\n", c, s);
+	p++;
+    }
+}
+
+
+/******************************************
+ * Compare 0-terminated string with length terminated string.
+ * Return < 0, ==0, > 0
+ */
+
+int cmp(const char *stringz, void *s, size_t slen)
+{
+    size_t len1 = strlen(stringz);
+
+    if (len1 != slen)
+	return len1 - slen;
+    return memcmp(stringz, s, slen);
+}
+
+int icmp(const char *stringz, void *s, size_t slen)
+{
+    size_t len1 = strlen(stringz);
+
+    if (len1 != slen)
+	return len1 - slen;
+    return memicmp(stringz, (char *)s, slen);
+}
+
+/*****************************************
+ * Return !=0 if comment consists entirely of "ditto".
+ */
+
+int isDitto(unsigned char *comment)
+{
+    if (comment)
+    {
+	unsigned char *p = skipwhitespace(comment);
+
+	if (memicmp((char *)p, "ditto", 5) == 0 && *skipwhitespace(p + 5) == 0)
+	    return 1;
+    }
+    return 0;
+}
+
+/**********************************************
+ * Skip white space.
+ */
+
+unsigned char *skipwhitespace(unsigned char *p)
+{
+    for (; 1; p++)
+    {	switch (*p)
+	{
+	    case ' ':
+	    case '\t':
+	    case '\n':
+		continue;
+	}
+	break;
+    }
+    return p;
+}
+
+
+/************************************************
+ * Scan forward to one of:
+ *	start of identifier
+ *	beginning of next line
+ *	end of buf
+ */
+
+unsigned skiptoident(OutBuffer *buf, unsigned i)
+{
+    for (; i < buf->offset; i++)
+    {
+	// BUG: handle unicode alpha's
+	unsigned char c = buf->data[i];
+	if (isalpha(c) || c == '_')
+	    break;
+	if (c == '\n')
+	    break;
+    }
+    return i;
+}
+
+/************************************************
+ * Scan forward past end of identifier.
+ */
+
+unsigned skippastident(OutBuffer *buf, unsigned i)
+{
+    for (; i < buf->offset; i++)
+    {
+	// BUG: handle unicode alpha's
+	unsigned char c = buf->data[i];
+	if (!(isalnum(c) || c == '_'))
+	    break;
+    }
+    return i;
+}
+
+
+/************************************************
+ * Scan forward past URL starting at i.
+ * We don't want to highlight parts of a URL.
+ * Returns:
+ *	i if not a URL
+ *	index just past it if it is a URL
+ */
+
+unsigned skippastURL(OutBuffer *buf, unsigned i)
+{   unsigned length = buf->offset - i;
+    unsigned char *p = &buf->data[i];
+    unsigned j;
+    unsigned sawdot = 0;
+
+    if (length > 7 && memicmp((char *)p, "http://", 7) == 0)
+    {
+	j = 7;
+    }
+    else if (length > 8 && memicmp((char *)p, "https://", 8) == 0)
+    {
+	j = 8;
+    }
+    else
+	goto Lno;
+
+    for (; j < length; j++)
+    {	unsigned char c = p[j];
+	if (isalnum(c))
+	    continue;
+        if (c == '-' || c == '_' || c == '?' ||
+            c == '=' || c == '%' || c == '&' ||
+            c == '/' || c == '+' || c == '#' ||
+            c == '~')
+            continue;
+        if (c == '.')
+        {
+            sawdot = 1;
+            continue;
+        }
+        break;
+    }
+    if (sawdot)
+	return i + j;
+
+Lno:
+    return i;
+}
+
+
+/****************************************************
+ */
+
+int isKeyword(unsigned char *p, unsigned len)
+{
+    static const char *table[] = { "true", "false", "null" };
+
+    for (int i = 0; i < sizeof(table) / sizeof(table[0]); i++)
+    {
+	if (cmp(table[i], p, len) == 0)
+	    return 1;
+    }
+    return 0;
+}
+
+/****************************************************
+ */
+
+Argument *isFunctionParameter(Dsymbol *s, unsigned char *p, unsigned len)
+{
+    FuncDeclaration *f = s->isFuncDeclaration();
+
+    /* f->type may be NULL for template members.
+     */
+    if (f && f->type)
+    {
+	TypeFunction *tf;
+	if (f->originalType)
+	{
+	    tf = (TypeFunction *)f->originalType;
+	}
+	else
+	    tf = (TypeFunction *)f->type;
+
+	if (tf->parameters)
+	{
+	    for (size_t k = 0; k < tf->parameters->dim; k++)
+	    {   Argument *arg = (Argument *)tf->parameters->data[k];
+
+		if (arg->ident && cmp(arg->ident->toChars(), p, len) == 0)
+		{
+		    return arg;
+		}
+	    }
+	}
+    }
+    return NULL;
+}
+
+/**************************************************
+ * Highlight text section.
+ */
+
+void highlightText(Scope *sc, Dsymbol *s, OutBuffer *buf, unsigned offset)
+{
+    //printf("highlightText()\n");
+    const char *sid = s->ident->toChars();
+    FuncDeclaration *f = s->isFuncDeclaration();
+    unsigned char *p;
+    const char *se;
+
+    int leadingBlank = 1;
+    int inCode = 0;
+    int inComment = 0;			// in <!-- ... --> comment
+    unsigned iCodeStart;		// start of code section
+
+    unsigned iLineStart = offset;
+
+    for (unsigned i = offset; i < buf->offset; i++)
+    {	unsigned char c = buf->data[i];
+
+     Lcont:
+	switch (c)
+	{
+	    case ' ':
+	    case '\t':
+		break;
+
+	    case '\n':
+		if (sc && !inCode && i == iLineStart && i + 1 < buf->offset)	// if "\n\n"
+		{
+		    static char blankline[] = "$(DDOC_BLANKLINE)\n";
+
+		    i = buf->insert(i, blankline, sizeof(blankline) - 1);
+		}
+		leadingBlank = 1;
+		iLineStart = i + 1;
+		break;
+
+	    case '<':
+		leadingBlank = 0;
+		if (inCode)
+		    break;
+		p = &buf->data[i];
+
+		// Skip over comments
+		if (p[1] == '!' && p[2] == '-' && p[3] == '-')
+		{   unsigned j = i + 4;
+		    p += 4;
+		    while (1)
+		    {
+			if (j == buf->offset)
+			    goto L1;
+			if (p[0] == '-' && p[1] == '-' && p[2] == '>')
+			{
+			    i = j + 2;	// place on closing '>'
+			    break;
+			}
+			j++;
+			p++;
+		    }
+		    break;
+		}
+
+		// Skip over HTML tag
+		if (isalpha(p[1]) || (p[1] == '/' && isalpha(p[2])))
+		{   unsigned j = i + 2;
+		    p += 2;
+		    while (1)
+		    {
+			if (j == buf->offset)
+			    goto L1;
+			if (p[0] == '>')
+			{
+			    i = j;	// place on closing '>'
+			    break;
+			}
+			j++;
+			p++;
+		    }
+		    break;
+		}
+
+	    L1:
+		// Replace '<' with '&lt;' character entity
+		se = Escape::escapeChar('<');
+		if (se)
+		{   size_t len = strlen(se);
+		    buf->remove(i, 1);
+		    i = buf->insert(i, se, len);
+		    i--;	// point to ';'
+		}
+		break;
+
+	    case '>':
+		leadingBlank = 0;
+		if (inCode)
+		    break;
+		// Replace '>' with '&gt;' character entity
+		se = Escape::escapeChar('>');
+		if (se)
+		{   size_t len = strlen(se);
+		    buf->remove(i, 1);
+		    i = buf->insert(i, se, len);
+		    i--;	// point to ';'
+		}
+		break;
+
+	    case '&':
+		leadingBlank = 0;
+		if (inCode)
+		    break;
+		p = &buf->data[i];
+		if (p[1] == '#' || isalpha(p[1]))
+		    break;			// already a character entity
+		// Replace '&' with '&amp;' character entity
+		se = Escape::escapeChar('&');
+		if (se)
+		{   size_t len = strlen(se);
+		    buf->remove(i, 1);
+		    i = buf->insert(i, se, len);
+		    i--;	// point to ';'
+		}
+		break;
+
+	    case '-':
+		/* A line beginning with --- delimits a code section.
+		 * inCode tells us if it is start or end of a code section.
+		 */
+		if (leadingBlank)
+		{   int istart = i;
+		    int eollen = 0;
+
+		    leadingBlank = 0;
+		    while (1)
+		    {
+			++i;
+			if (i >= buf->offset)
+			    break;
+			c = buf->data[i];
+			if (c == '\n')
+			{   eollen = 1;
+			    break;
+			}
+			if (c == '\r')
+			{
+			    eollen = 1;
+			    if (i + 1 >= buf->offset)
+				break;
+			    if (buf->data[i + 1] == '\n')
+			    {	eollen = 2;
+				break;
+			    }
+			}
+			// BUG: handle UTF PS and LS too
+			if (c != '-')
+			    goto Lcont;
+		    }
+		    if (i - istart < 3)
+			goto Lcont;
+
+		    // We have the start/end of a code section
+
+		    // Remove the entire --- line, including blanks and \n
+		    buf->remove(iLineStart, i - iLineStart + eollen);
+		    i = iLineStart;
+
+		    if (inCode)
+		    {
+			inCode = 0;
+			// The code section is from iCodeStart to i
+			OutBuffer codebuf;
+
+			codebuf.write(buf->data + iCodeStart, i - iCodeStart);
+			codebuf.writeByte(0);
+			highlightCode2(sc, s, &codebuf, 0);
+			buf->remove(iCodeStart, i - iCodeStart);
+			i = buf->insert(iCodeStart, codebuf.data, codebuf.offset);
+			i = buf->insert(i, ")\n", 2);
+			i--;
+		    }
+		    else
+		    {	static char pre[] = "$(D_CODE \n";
+
+			inCode = 1;
+			i = buf->insert(i, pre, sizeof(pre) - 1);
+			iCodeStart = i;
+			i--;		// place i on >
+		    }
+		}
+		break;
+
+	    default:
+		leadingBlank = 0;
+		if (sc && !inCode && (isalpha(c) || c == '_'))
+		{   unsigned j;
+
+		    j = skippastident(buf, i);
+		    if (j > i)
+		    {
+			unsigned k = skippastURL(buf, i);
+			if (k > i)
+			{   i = k - 1;
+			    break;
+			}
+
+			if (buf->data[i] == '_')	// leading '_' means no highlight
+			{
+			    buf->remove(i, 1);
+			    i = j - 1;
+			}
+			else
+			{
+			    if (cmp(sid, buf->data + i, j - i) == 0)
+			    {
+				i = buf->bracket(i, "$(DDOC_PSYMBOL ", j, ")") - 1;
+				break;
+			    }
+			    else if (isKeyword(buf->data + i, j - i))
+			    {
+				i = buf->bracket(i, "$(DDOC_KEYWORD ", j, ")") - 1;
+				break;
+			    }
+			    else
+			    {
+				if (f && isFunctionParameter(f, buf->data + i, j - i))
+				{
+				    //printf("highlighting arg '%s', i = %d, j = %d\n", arg->ident->toChars(), i, j);
+				    i = buf->bracket(i, "$(DDOC_PARAM ", j, ")") - 1;
+				    break;
+				}
+			    }
+			    i = j - 1;
+			}
+		    }
+		}
+		break;
+	}
+    }
+  Ldone:
+    ;
+}
+
+/**************************************************
+ * Highlight code for DDOC section.
+ */
+
+void highlightCode(Scope *sc, Dsymbol *s, OutBuffer *buf, unsigned offset)
+{
+    char *sid = s->ident->toChars();
+    FuncDeclaration *f = s->isFuncDeclaration();
+
+    //printf("highlightCode(s = '%s', kind = %s)\n", sid, s->kind());
+    for (unsigned i = offset; i < buf->offset; i++)
+    {	unsigned char c = buf->data[i];
+	const char *se;
+
+	se = Escape::escapeChar(c);
+	if (se)
+	{
+	    size_t len = strlen(se);
+	    buf->remove(i, 1);
+	    i = buf->insert(i, se, len);
+	    i--;		// point to ';'
+	}
+	else if (isalpha(c) || c == '_')
+	{   unsigned j;
+
+	    j = skippastident(buf, i);
+	    if (j > i)
+	    {
+		if (cmp(sid, buf->data + i, j - i) == 0)
+		{
+		    i = buf->bracket(i, "$(DDOC_PSYMBOL ", j, ")") - 1;
+		    continue;
+		}
+		else if (f)
+		{
+		    if (isFunctionParameter(f, buf->data + i, j - i))
+		    {
+			//printf("highlighting arg '%s', i = %d, j = %d\n", arg->ident->toChars(), i, j);
+			i = buf->bracket(i, "$(DDOC_PARAM ", j, ")") - 1;
+			continue;
+		    }
+		}
+		i = j - 1;
+	    }
+	}
+    }
+}
+
+/****************************************
+ */
+
+void highlightCode3(OutBuffer *buf, unsigned char *p, unsigned char *pend)
+{
+    for (; p < pend; p++)
+    {	const char *s = Escape::escapeChar(*p);
+	if (s)
+	    buf->writestring(s);
+	else
+	    buf->writeByte(*p);
+    }
+}
+
+/**************************************************
+ * Highlight code for CODE section.
+ */
+
+
+void highlightCode2(Scope *sc, Dsymbol *s, OutBuffer *buf, unsigned offset)
+{
+    char *sid = s->ident->toChars();
+    FuncDeclaration *f = s->isFuncDeclaration();
+    unsigned errorsave = global.errors;
+    Lexer lex(NULL, buf->data, 0, buf->offset - 1, 0, 1);
+    Token tok;
+    OutBuffer res;
+    unsigned char *lastp = buf->data;
+    const char *highlight;
+
+    //printf("highlightCode2('%.*s')\n", buf->offset - 1, buf->data);
+    res.reserve(buf->offset);
+    while (1)
+    {
+	lex.scan(&tok);
+	highlightCode3(&res, lastp, tok.ptr);
+	highlight = NULL;
+	switch (tok.value)
+	{
+	    case TOKidentifier:
+		if (!sc)
+		    break;
+		if (cmp(sid, tok.ptr, lex.p - tok.ptr) == 0)
+		{
+		    highlight = "$(D_PSYMBOL ";
+		    break;
+		}
+		else if (f)
+		{
+		    if (isFunctionParameter(f, tok.ptr, lex.p - tok.ptr))
+		    {
+			//printf("highlighting arg '%s', i = %d, j = %d\n", arg->ident->toChars(), i, j);
+			highlight = "$(D_PARAM ";
+			break;
+		    }
+		}
+		break;
+
+	    case TOKcomment:
+		highlight = "$(D_COMMENT ";
+		break;
+
+	    case TOKstring:
+		highlight = "$(D_STRING ";
+		break;
+
+	    default:
+		if (tok.isKeyword())
+		    highlight = "$(D_KEYWORD ";
+		break;
+	}
+	if (highlight)
+	    res.writestring(highlight);
+	highlightCode3(&res, tok.ptr, lex.p);
+	if (highlight)
+	    res.writeByte(')');
+	if (tok.value == TOKeof)
+	    break;
+	lastp = lex.p;
+    }
+    buf->setsize(offset);
+    buf->write(&res);
+    global.errors = errorsave;
+}
+
+/***************************************
+ * Find character string to replace c with.
+ */
+
+const char *Escape::escapeChar(unsigned c)
+{   const char *s;
+
+    switch (c)
+    {
+	case '<':
+	    s = "&lt;";
+	    break;
+	case '>':
+	    s = "&gt;";
+	    break;
+	case '&':
+	    s = "&amp;";
+	    break;
+	default:
+	    s = NULL;
+	    break;
+    }
+    return s;
+}
+
--- a/dmd2/dsymbol.c	Mon Jun 01 01:28:18 2009 +0200
+++ b/dmd2/dsymbol.c	Mon Jun 01 19:02:20 2009 +0100
@@ -1,1201 +1,1230 @@
-
-// 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 <string.h>
-#include <assert.h>
-
-#include "mem.h"
-
-#include "mars.h"
-#include "dsymbol.h"
-#include "aggregate.h"
-#include "identifier.h"
-#include "module.h"
-#include "mtype.h"
-#include "expression.h"
-#include "statement.h"
-#include "declaration.h"
-#include "id.h"
-#include "scope.h"
-#include "init.h"
-#include "import.h"
-#include "template.h"
-#include "attrib.h"
-
-#include "../gen/enums.h"
-
-/****************************** Dsymbol ******************************/
-
-Dsymbol::Dsymbol()
-{
-    //printf("Dsymbol::Dsymbol(%p)\n", this);
-    this->ident = NULL;
-    this->c_ident = NULL;
-    this->parent = NULL;
-    this->csym = NULL;
-    this->isym = NULL;
-    this->loc = 0;
-    this->comment = NULL;
-
-    this->llvmInternal = LLVMnone;
-}
-
-Dsymbol::Dsymbol(Identifier *ident)
-{
-    //printf("Dsymbol::Dsymbol(%p, ident)\n", this);
-    this->ident = ident;
-    this->c_ident = NULL;
-    this->parent = NULL;
-    this->csym = NULL;
-    this->isym = NULL;
-    this->loc = 0;
-    this->comment = NULL;
-
-    this->llvmInternal = LLVMnone;
-}
-
-int Dsymbol::equals(Object *o)
-{   Dsymbol *s;
-
-    if (this == o)
-	return TRUE;
-    s = (Dsymbol *)(o);
-    if (s && ident->equals(s->ident))
-	return TRUE;
-    return FALSE;
-}
-
-/**************************************
- * Copy the syntax.
- * Used for template instantiations.
- * If s is NULL, allocate the new object, otherwise fill it in.
- */
-
-Dsymbol *Dsymbol::syntaxCopy(Dsymbol *s)
-{
-    print();
-    printf("%s %s\n", kind(), toChars());
-    assert(0);
-    return NULL;
-}
-
-/**************************************
- * Determine if this symbol is only one.
- * Returns:
- *	FALSE, *ps = NULL: There are 2 or more symbols
- *	TRUE,  *ps = NULL: There are zero symbols
- *	TRUE,  *ps = symbol: The one and only one symbol
- */
-
-int Dsymbol::oneMember(Dsymbol **ps)
-{
-    //printf("Dsymbol::oneMember()\n");
-    *ps = this;
-    return TRUE;
-}
-
-/*****************************************
- * Same as Dsymbol::oneMember(), but look at an array of Dsymbols.
- */
-
-int Dsymbol::oneMembers(Array *members, Dsymbol **ps)
-{
-    //printf("Dsymbol::oneMembers() %d\n", members ? members->dim : 0);
-    Dsymbol *s = NULL;
-
-    if (members)
-    {
-	for (int i = 0; i < members->dim; i++)
-	{   Dsymbol *sx = (Dsymbol *)members->data[i];
-
-	    int x = sx->oneMember(ps);
-	    //printf("\t[%d] kind %s = %d, s = %p\n", i, sx->kind(), x, *ps);
-	    if (!x)
-	    {
-		//printf("\tfalse 1\n");
-		assert(*ps == NULL);
-		return FALSE;
-	    }
-	    if (*ps)
-	    {
-		if (s)			// more than one symbol
-		{   *ps = NULL;
-		    //printf("\tfalse 2\n");
-		    return FALSE;
-		}
-		s = *ps;
-	    }
-	}
-    }
-    *ps = s;		// s is the one symbol, NULL if none
-    //printf("\ttrue\n");
-    return TRUE;
-}
-
-/*****************************************
- * Is Dsymbol a variable that contains pointers?
- */
-
-int Dsymbol::hasPointers()
-{
-    //printf("Dsymbol::hasPointers() %s\n", toChars());
-    return 0;
-}
-
-char *Dsymbol::toChars()
-{
-    return ident ? ident->toChars() : (char *)"__anonymous";
-}
-
-char *Dsymbol::toPrettyChars()
-{   Dsymbol *p;
-    char *s;
-    char *q;
-    size_t len;
-
-    //printf("Dsymbol::toPrettyChars() '%s'\n", toChars());
-    if (!parent)
-	return toChars();
-
-    len = 0;
-    for (p = this; p; p = p->parent)
-	len += strlen(p->toChars()) + 1;
-
-    s = (char *)mem.malloc(len);
-    q = s + len - 1;
-    *q = 0;
-    for (p = this; p; p = p->parent)
-    {
-	char *t = p->toChars();
-	len = strlen(t);
-	q -= len;
-	memcpy(q, t, len);
-	if (q == s)
-	    break;
-	q--;
-	*q = '.';
-    }
-    return s;
-}
-
-char *Dsymbol::locToChars()
-{
-    OutBuffer buf;
-    char *p;
-
-    Module *m = getModule();
-
-    if (m && m->srcfile)
-	loc.filename = m->srcfile->toChars();
-    return loc.toChars();
-}
-
-const char *Dsymbol::kind()
-{
-    return "symbol";
-}
-
-/*********************************
- * If this symbol is really an alias for another,
- * return that other.
- */
-
-Dsymbol *Dsymbol::toAlias()
-{
-    return this;
-}
-
-Dsymbol *Dsymbol::toParent()
-{
-    return parent ? parent->pastMixin() : NULL;
-}
-
-Dsymbol *Dsymbol::pastMixin()
-{
-    Dsymbol *s = this;
-
-    //printf("Dsymbol::pastMixin() %s\n", toChars());
-    while (s && s->isTemplateMixin())
-	s = s->parent;
-    return s;
-}
-
-/**********************************
- * Use this instead of toParent() when looking for the
- * 'this' pointer of the enclosing function/class.
- */
-
-Dsymbol *Dsymbol::toParent2()
-{
-    Dsymbol *s = parent;
-    while (s && s->isTemplateInstance())
-	s = s->parent;
-    return s;
-}
-
-TemplateInstance *Dsymbol::inTemplateInstance()
-{
-    for (Dsymbol *parent = this->parent; parent; parent = parent->parent)
-    {
-	TemplateInstance *ti = parent->isTemplateInstance();
-	if (ti)
-	    return ti;
-    }
-    return NULL;
-}
-
-int Dsymbol::isAnonymous()
-{
-    return ident ? 0 : 1;
-}
-
-void Dsymbol::semantic(Scope *sc)
-{
-    error("%p has no semantic routine", this);
-}
-
-void Dsymbol::semantic2(Scope *sc)
-{
-    // Most Dsymbols have no further semantic analysis needed
-}
-
-void Dsymbol::semantic3(Scope *sc)
-{
-    // Most Dsymbols have no further semantic analysis needed
-}
-
-void Dsymbol::inlineScan()
-{
-    // Most Dsymbols have no further semantic analysis needed
-}
-
-/*********************************************
- * Search for ident as member of s.
- * Input:
- *	flags:	1	don't find private members
- *		2	don't give error messages
- *		4	return NULL if ambiguous
- * Returns:
- *	NULL if not found
- */
-
-Dsymbol *Dsymbol::search(Loc loc, Identifier *ident, int flags)
-{
-    //printf("Dsymbol::search(this=%p,%s, ident='%s')\n", this, toChars(), ident->toChars());
-    return NULL;
-}
-
-/***************************************
- * Search for identifier id as a member of 'this'.
- * id may be a template instance.
- * Returns:
- *	symbol found, NULL if not
- */
-
-Dsymbol *Dsymbol::searchX(Loc loc, Scope *sc, Identifier *id)
-{
-    //printf("Dsymbol::searchX(this=%p,%s, ident='%s')\n", this, toChars(), ident->toChars());
-    Dsymbol *s = toAlias();
-    Dsymbol *sm;
-
-    switch (id->dyncast())
-    {
-	case DYNCAST_IDENTIFIER:
-	    sm = s->search(loc, id, 0);
-	    break;
-
-	case DYNCAST_DSYMBOL:
-	{   // It's a template instance
-	    //printf("\ttemplate instance id\n");
-	    Dsymbol *st = (Dsymbol *)id;
-	    TemplateInstance *ti = st->isTemplateInstance();
-	    id = ti->name;
-	    sm = s->search(loc, id, 0);
-	    if (!sm)
-	    {   error("template identifier %s is not a member of %s %s",
-		    id->toChars(), s->kind(), s->toChars());
-		return NULL;
-	    }
-	    sm = sm->toAlias();
-	    TemplateDeclaration *td = sm->isTemplateDeclaration();
-	    if (!td)
-	    {
-		error("%s is not a template, it is a %s", id->toChars(), sm->kind());
-		return NULL;
-	    }
-	    ti->tempdecl = td;
-	    if (!ti->semanticdone)
-		ti->semantic(sc);
-	    sm = ti->toAlias();
-	    break;
-	}
-
-	default:
-	    assert(0);
-    }
-    return sm;
-}
-
-int Dsymbol::overloadInsert(Dsymbol *s)
-{
-    //printf("Dsymbol::overloadInsert('%s')\n", s->toChars());
-    return FALSE;
-}
-
-void Dsymbol::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{
-    buf->writestring(toChars());
-}
-
-unsigned Dsymbol::size(Loc loc)
-{
-    error("Dsymbol '%s' has no size\n", toChars());
-    return 0;
-}
-
-int Dsymbol::isforwardRef()
-{
-    return FALSE;
-}
-
-AggregateDeclaration *Dsymbol::isThis()
-{
-    return NULL;
-}
-
-ClassDeclaration *Dsymbol::isClassMember()	// are we a member of a class?
-{
-    Dsymbol *parent = toParent();
-    if (parent && parent->isClassDeclaration())
-	return (ClassDeclaration *)parent;
-    return NULL;
-}
-
-void Dsymbol::defineRef(Dsymbol *s)
-{
-    assert(0);
-}
-
-int Dsymbol::isExport()
-{
-    return FALSE;
-}
-
-int Dsymbol::isImportedSymbol()
-{
-    return FALSE;
-}
-
-int Dsymbol::isDeprecated()
-{
-    return FALSE;
-}
-
-int Dsymbol::isOverloadable()
-{
-    return 0;
-}
-
-LabelDsymbol *Dsymbol::isLabel()		// is this a LabelDsymbol()?
-{
-    return NULL;
-}
-
-AggregateDeclaration *Dsymbol::isMember()	// is this a member of an AggregateDeclaration?
-{
-    //printf("Dsymbol::isMember() %s\n", toChars());
-    Dsymbol *parent = toParent();
-    //printf("parent is %s %s\n", parent->kind(), parent->toChars());
-    return parent ? parent->isAggregateDeclaration() : NULL;
-}
-
-Type *Dsymbol::getType()
-{
-    return NULL;
-}
-
-int Dsymbol::needThis()
-{
-    return FALSE;
-}
-
-int Dsymbol::addMember(Scope *sc, ScopeDsymbol *sd, int memnum)
-{
-    //printf("Dsymbol::addMember('%s')\n", toChars());
-    //printf("Dsymbol::addMember(this = %p, '%s' scopesym = '%s')\n", this, toChars(), sd->toChars());
-    //printf("Dsymbol::addMember(this = %p, '%s' sd = %p, sd->symtab = %p)\n", this, toChars(), sd, sd->symtab);
-    parent = sd;
-    if (!isAnonymous())		// no name, so can't add it to symbol table
-    {
-	if (!sd->symtab->insert(this))	// if name is already defined
-	{
-	    Dsymbol *s2;
-
-	    s2 = sd->symtab->lookup(ident);
-	    if (!s2->overloadInsert(this))
-	    {
-		sd->multiplyDefined(0, this, s2);
-	    }
-	}
-	if (sd->isAggregateDeclaration() || sd->isEnumDeclaration())
-	{
-	    if (ident == Id::__sizeof || ident == Id::alignof || ident == Id::mangleof)
-		error(".%s property cannot be redefined", ident->toChars());
-	}
-	return 1;
-    }
-    return 0;
-}
-
-void Dsymbol::error(const char *format, ...)
-{
-    //printf("Dsymbol::error()\n");
-    if (!global.gag)
-    {
-	char *p = locToChars();
-
-	if (*p)
-	    fprintf(stdmsg, "%s: ", p);
-	mem.free(p);
-
-	fprintf(stdmsg, "Error: ");
-	if (isAnonymous())
-	    fprintf(stdmsg, "%s ", kind());
-	else
-	    fprintf(stdmsg, "%s %s ", kind(), toPrettyChars());
-
-	va_list ap;
-	va_start(ap, format);
-	vfprintf(stdmsg, format, ap);
-	va_end(ap);
-
-	fprintf(stdmsg, "\n");
-	fflush(stdmsg);
-    }
-    global.errors++;
-
-    //fatal();
-}
-
-void Dsymbol::error(Loc loc, const char *format, ...)
-{
-    if (!global.gag)
-    {
-	char *p = loc.toChars();
-	if (!*p)
-	    p = locToChars();
-
-	if (*p)
-	    fprintf(stdmsg, "%s: ", p);
-	mem.free(p);
-
-	fprintf(stdmsg, "Error: ");
-	fprintf(stdmsg, "%s %s ", kind(), toPrettyChars());
-
-	va_list ap;
-	va_start(ap, format);
-	vfprintf(stdmsg, format, ap);
-	va_end(ap);
-
-	fprintf(stdmsg, "\n");
-	fflush(stdmsg);
-    }
-
-    global.errors++;
-
-    //fatal();
-}
-
-void Dsymbol::checkDeprecated(Loc loc, Scope *sc)
-{
-    if (!global.params.useDeprecated && isDeprecated())
-    {
-	// Don't complain if we're inside a deprecated symbol's scope
-	for (Dsymbol *sp = sc->parent; sp; sp = sp->parent)
-	{   if (sp->isDeprecated())
-		return;
-	}
-
-	for (; sc; sc = sc->enclosing)
-	{
-	    if (sc->scopesym && sc->scopesym->isDeprecated())
-		return;
-
-	    // If inside a StorageClassDeclaration that is deprecated
-	    if (sc->stc & STCdeprecated)
-		return;
-	}
-
-	error(loc, "is deprecated");
-    }
-}
-
-/**********************************
- * Determine which Module a Dsymbol is in.
- */
-
-Module *Dsymbol::getModule()
-{
-    Module *m;
-    Dsymbol *s;
-
-    //printf("Dsymbol::getModule()\n");
-    s = this;
-    while (s)
-    {
-	//printf("\ts = '%s'\n", s->toChars());
-	m = s->isModule();
-	if (m)
-	    return m;
-	s = s->parent;
-    }
-    return NULL;
-}
-
-
-/**********************************
- * Determine which Module a Dsymbol will be compiled in.
- * This may be different from getModule for templates.
- */
-
-Module *Dsymbol::getCompilationModule()
-{
-    Module *m;
-    TemplateInstance *ti;
-    Dsymbol *s;
-
-    //printf("Dsymbol::getModule()\n");
-    s = this;
-    while (s)
-    {
-    //printf("\ts = '%s'\n", s->toChars());
-    m = s->isModule();
-    if (m)
-        return m;
-    ti = s->isTemplateInstance();
-    if (ti && ti->tmodule)
-        return ti->tmodule;
-    s = s->parent;
-    }
-    return NULL;
-}
-
-/*************************************
- */
-
-enum PROT Dsymbol::prot()
-{
-    return PROTpublic;
-}
-
-/*************************************
- * Do syntax copy of an array of Dsymbol's.
- */
-
-
-Array *Dsymbol::arraySyntaxCopy(Array *a)
-{
-
-    Array *b = NULL;
-    if (a)
-    {
-	b = a->copy();
-	for (int i = 0; i < b->dim; i++)
-	{
-	    Dsymbol *s = (Dsymbol *)b->data[i];
-
-	    s = s->syntaxCopy(NULL);
-	    b->data[i] = (void *)s;
-	}
-    }
-    return b;
-}
-
-
-/****************************************
- * Add documentation comment to Dsymbol.
- * Ignore NULL comments.
- */
-
-void Dsymbol::addComment(unsigned char *comment)
-{
-    //if (comment)
-	//printf("adding comment '%s' to symbol %p '%s'\n", comment, this, toChars());
-
-    if (!this->comment)
-	this->comment = comment;
-#if 1
-    else if (comment && strcmp((char *)comment, (char *)this->comment))
-    {	// Concatenate the two
-	this->comment = Lexer::combineComments(this->comment, comment);
-    }
-#endif
-}
-
-/********************************* OverloadSet ****************************/
-
-OverloadSet::OverloadSet()
-    : Dsymbol()
-{
-}
-
-void OverloadSet::push(Dsymbol *s)
-{
-    a.push(s);
-}
-
-const char *OverloadSet::kind()
-{
-    return "overloadset";
-}
-
-
-/********************************* ScopeDsymbol ****************************/
-
-ScopeDsymbol::ScopeDsymbol()
-    : Dsymbol()
-{
-    members = NULL;
-    symtab = NULL;
-    imports = NULL;
-    prots = NULL;
-}
-
-ScopeDsymbol::ScopeDsymbol(Identifier *id)
-    : Dsymbol(id)
-{
-    members = NULL;
-    symtab = NULL;
-    imports = NULL;
-    prots = NULL;
-}
-
-Dsymbol *ScopeDsymbol::syntaxCopy(Dsymbol *s)
-{
-    //printf("ScopeDsymbol::syntaxCopy('%s')\n", toChars());
-
-    ScopeDsymbol *sd;
-    if (s)
-	sd = (ScopeDsymbol *)s;
-    else
-	sd = new ScopeDsymbol(ident);
-    sd->members = arraySyntaxCopy(members);
-    return sd;
-}
-
-Dsymbol *ScopeDsymbol::search(Loc loc, Identifier *ident, int flags)
-{
-    //printf("%s->ScopeDsymbol::search(ident='%s', flags=x%x)\n", toChars(), ident->toChars(), flags);
-    //if (strcmp(ident->toChars(),"c") == 0) *(char*)0=0;
-
-    // Look in symbols declared in this module
-    Dsymbol *s = symtab ? symtab->lookup(ident) : NULL;
-
-    // hide private nonlocal symbols
-    if (flags & 1 && s && s->prot() == PROTprivate)
-	s = NULL;
-
-    if (s)
-    {
-	//printf("\ts = '%s.%s'\n",toChars(),s->toChars());
-    }
-    else if (imports)
-    {
-	OverloadSet *a = NULL;
-
-	// Look in imported modules
-	for (int i = 0; i < imports->dim; i++)
-	{   ScopeDsymbol *ss = (ScopeDsymbol *)imports->data[i];
-	    Dsymbol *s2;
-
-	    // If private import, don't search it
-	    if (flags & 1 && prots[i] == PROTprivate)
-		continue;
-
-	    //printf("\tscanning import '%s', prots = %d, isModule = %p, isImport = %p\n", ss->toChars(), prots[i], ss->isModule(), ss->isImport());
-	    /* Don't find private members if ss is a module
-	     */
-	    s2 = ss->search(loc, ident, ss->isModule() ? 1 : 0);
-	    if (!s)
-		s = s2;
-	    else if (s2 && s != s2)
-	    {
-		if (s->toAlias() == s2->toAlias())
-		{
-		    /* After following aliases, we found the same symbol,
-		     * so it's not an ambiguity.
-		     * But if one alias is deprecated, prefer the other.
-		     */
-		    if (s->isDeprecated())
-			s = s2;
-		}
-		else
-		{
-		    /* Two imports of the same module should be regarded as
-		     * the same.
-		     */
-		    Import *i1 = s->isImport();
-		    Import *i2 = s2->isImport();
-		    if (!(i1 && i2 &&
-			  (i1->mod == i2->mod ||
-			   (!i1->parent->isImport() && !i2->parent->isImport() &&
-			    i1->ident->equals(i2->ident))
-			  )
-			 )
-		       )
-		    {
-			/* If both s2 and s are overloadable (though we only
-			 * need to check s once)
-			 */
-			if (s2->isOverloadable() && (a || s->isOverloadable()))
-			{   if (!a)
-				a = new OverloadSet();
-			    /* Don't add to a[] if s2 is alias of previous sym
-			     */
-			    for (int j = 0; j < a->a.dim; j++)
-			    {	Dsymbol *s3 = (Dsymbol *)a->a.data[j];
-				if (s2->toAlias() == s3->toAlias())
-				{
-				    if (s3->isDeprecated())
-					a->a.data[j] = (void *)s2;
-				    goto Lcontinue;
-				}
-			    }
-			    a->push(s2);
-			Lcontinue:
-			    continue;
-			}
-			if (flags & 4)		// if return NULL on ambiguity
-			    return NULL;
-			if (!(flags & 2))
-			    ss->multiplyDefined(loc, s, s2);
-			break;
-		    }
-		}
-	    }
-	}
-
-	/* Build special symbol if we had multiple finds
-	 */
-	if (a)
-	{   assert(s);
-	    a->push(s);
-	    s = a;
-	}
-
-	if (s)
-	{
-	    Declaration *d = s->isDeclaration();
-	    if (d && d->protection == PROTprivate &&
-		!d->parent->isTemplateMixin() &&
-		!(flags & 2))
-		error("%s is private", d->toPrettyChars());
-	}
-    }
-    return s;
-}
-
-void ScopeDsymbol::importScope(ScopeDsymbol *s, enum PROT protection)
-{
-    //printf("%s->ScopeDsymbol::importScope(%s, %d)\n", toChars(), s->toChars(), protection);
-
-    // No circular or redundant import's
-    if (s != this)
-    {
-	if (!imports)
-	    imports = new Array();
-	else
-	{
-	    for (int i = 0; i < imports->dim; i++)
-	    {   ScopeDsymbol *ss;
-
-		ss = (ScopeDsymbol *) imports->data[i];
-		if (ss == s)			// if already imported
-		{
-		    if (protection > prots[i])
-			prots[i] = protection;	// upgrade access
-		    return;
-		}
-	    }
-	}
-	imports->push(s);
-	prots = (unsigned char *)mem.realloc(prots, imports->dim * sizeof(prots[0]));
-	prots[imports->dim - 1] = protection;
-    }
-}
-
-int ScopeDsymbol::isforwardRef()
-{
-    return (members == NULL);
-}
-
-void ScopeDsymbol::defineRef(Dsymbol *s)
-{
-    ScopeDsymbol *ss;
-
-    ss = s->isScopeDsymbol();
-    members = ss->members;
-    ss->members = NULL;
-}
-
-void ScopeDsymbol::multiplyDefined(Loc loc, Dsymbol *s1, Dsymbol *s2)
-{
-#if 0
-    printf("ScopeDsymbol::multiplyDefined()\n");
-    printf("s1 = %p, '%s' kind = '%s', parent = %s\n", s1, s1->toChars(), s1->kind(), s1->parent ? s1->parent->toChars() : "");
-    printf("s2 = %p, '%s' kind = '%s', parent = %s\n", s2, s2->toChars(), s2->kind(), s2->parent ? s2->parent->toChars() : "");
-#endif
-    if (loc.filename)
-    {	::error(loc, "%s at %s conflicts with %s at %s",
-	    s1->toPrettyChars(),
-	    s1->locToChars(),
-	    s2->toPrettyChars(),
-	    s2->locToChars());
-    }
-    else
-    {
-	s1->error(loc, "conflicts with %s %s at %s",
-	    s2->kind(),
-	    s2->toPrettyChars(),
-	    s2->locToChars());
-    }
-halt();
-}
-
-Dsymbol *ScopeDsymbol::nameCollision(Dsymbol *s)
-{
-    Dsymbol *sprev;
-
-    // Look to see if we are defining a forward referenced symbol
-
-    sprev = symtab->lookup(s->ident);
-    assert(sprev);
-    if (s->equals(sprev))		// if the same symbol
-    {
-	if (s->isforwardRef())		// if second declaration is a forward reference
-	    return sprev;
-	if (sprev->isforwardRef())
-	{
-	    sprev->defineRef(s);	// copy data from s into sprev
-	    return sprev;
-	}
-    }
-    multiplyDefined(0, s, sprev);
-    return sprev;
-}
-
-const char *ScopeDsymbol::kind()
-{
-    return "ScopeDsymbol";
-}
-
-
-/***************************************
- * Determine number of Dsymbols, folding in AttribDeclaration members.
- */
-
-size_t ScopeDsymbol::dim(Array *members)
-{
-    size_t n = 0;
-    if (members)
-    {
-	for (size_t i = 0; i < members->dim; i++)
-	{   Dsymbol *s = (Dsymbol *)members->data[i];
-	    AttribDeclaration *a = s->isAttribDeclaration();
-
-	    if (a)
-	    {
-		n += dim(a->decl);
-	    }
-	    else
-		n++;
-	}
-    }
-    return n;
-}
-
-/***************************************
- * Get nth Dsymbol, folding in AttribDeclaration members.
- * Returns:
- *	Dsymbol*	nth Dsymbol
- *	NULL		not found, *pn gets incremented by the number
- *			of Dsymbols
- */
-
-Dsymbol *ScopeDsymbol::getNth(Array *members, size_t nth, size_t *pn)
-{
-    if (!members)
-	return NULL;
-
-    size_t n = 0;
-    for (size_t i = 0; i < members->dim; i++)
-    {   Dsymbol *s = (Dsymbol *)members->data[i];
-	AttribDeclaration *a = s->isAttribDeclaration();
-
-	if (a)
-	{
-	    s = getNth(a->decl, nth - n, &n);
-	    if (s)
-		return s;
-	}
-	else if (n == nth)
-	    return s;
-	else
-	    n++;
-    }
-
-    if (pn)
-	*pn += n;
-    return NULL;
-}
-
-/*******************************************
- * Look for member of the form:
- *	const(MemberInfo)[] getMembers(string);
- * Returns NULL if not found
- */
-
-#if DMDV2
-FuncDeclaration *ScopeDsymbol::findGetMembers()
-{
-    Dsymbol *s = search_function(this, Id::getmembers);
-    FuncDeclaration *fdx = s ? s->isFuncDeclaration() : NULL;
-
-#if 0  // Finish
-    static TypeFunction *tfgetmembers;
-
-    if (!tfgetmembers)
-    {
-	Scope sc;
-	Arguments *arguments = new Arguments;
-	Arguments *arg = new Argument(STCin, Type::tchar->constOf()->arrayOf(), NULL, NULL);
-	arguments->push(arg);
-
-	Type *tret = NULL;
-	tfgetmembers = new TypeFunction(arguments, tret, 0, LINKd);
-	tfgetmembers = (TypeFunction *)tfgetmembers->semantic(0, &sc);
-    }
-    if (fdx)
-	fdx = fdx->overloadExactMatch(tfgetmembers);
-#endif
-    if (fdx && fdx->isVirtual())
-	fdx = NULL;
-
-    return fdx;
-}
-#endif
-
-
-/****************************** WithScopeSymbol ******************************/
-
-WithScopeSymbol::WithScopeSymbol(WithStatement *withstate)
-    : ScopeDsymbol()
-{
-    this->withstate = withstate;
-}
-
-Dsymbol *WithScopeSymbol::search(Loc loc, Identifier *ident, int flags)
-{
-    // Acts as proxy to the with class declaration
-    return withstate->exp->type->toDsymbol(NULL)->search(loc, ident, 0);
-}
-
-/****************************** ArrayScopeSymbol ******************************/
-
-ArrayScopeSymbol::ArrayScopeSymbol(Scope *sc, Expression *e)
-    : ScopeDsymbol()
-{
-    assert(e->op == TOKindex || e->op == TOKslice);
-    exp = e;
-    type = NULL;
-    td = NULL;
-    this->sc = sc;
-}
-
-ArrayScopeSymbol::ArrayScopeSymbol(Scope *sc, TypeTuple *t)
-    : ScopeDsymbol()
-{
-    exp = NULL;
-    type = t;
-    td = NULL;
-    this->sc = sc;
-}
-
-ArrayScopeSymbol::ArrayScopeSymbol(Scope *sc, TupleDeclaration *s)
-    : ScopeDsymbol()
-{
-    exp = NULL;
-    type = NULL;
-    td = s;
-    this->sc = sc;
-}
-
-Dsymbol *ArrayScopeSymbol::search(Loc loc, Identifier *ident, int flags)
-{
-    //printf("ArrayScopeSymbol::search('%s', flags = %d)\n", ident->toChars(), flags);
-    if (ident == Id::length || ident == Id::dollar)
-    {	VarDeclaration **pvar;
-	Expression *ce;
-
-    L1:
-
-	if (td)
- 	{
-	    VarDeclaration *v = new VarDeclaration(loc, Type::tsize_t, Id::dollar, NULL);
-	    Expression *e = new IntegerExp(0, td->objects->dim, Type::tsize_t);
-	    v->init = new ExpInitializer(0, e);
-	    v->storage_class |= STCstatic | STCconst;
-	    v->semantic(sc);
-	    return v;
-	}
-
-	if (type)
- 	{
-	    VarDeclaration *v = new VarDeclaration(loc, Type::tsize_t, Id::dollar, NULL);
-	    Expression *e = new IntegerExp(0, type->arguments->dim, Type::tsize_t);
-	    v->init = new ExpInitializer(0, e);
-	    v->storage_class |= STCstatic | STCconst;
-	    v->semantic(sc);
-	    return v;
-	}
-
-	if (exp->op == TOKindex)
-	{
-	    IndexExp *ie = (IndexExp *)exp;
-
-	    pvar = &ie->lengthVar;
-	    ce = ie->e1;
-	}
-	else if (exp->op == TOKslice)
-	{
-	    SliceExp *se = (SliceExp *)exp;
-
-	    pvar = &se->lengthVar;
-	    ce = se->e1;
-	}
-	else
-	    return NULL;
-
-	if (ce->op == TOKtype)
-	{
-	    Type *t = ((TypeExp *)ce)->type;
-	    if (t->ty == Ttuple)
-	    {	type = (TypeTuple *)t;
-		goto L1;
-	    }
-	}
-
-	if (!*pvar)
-	{
-	    VarDeclaration *v = new VarDeclaration(loc, Type::tsize_t, Id::dollar, NULL);
-
-	    if (ce->op == TOKvar)
-	    {	// if ce is const, get its initializer
-		ce = fromConstInitializer(WANTvalue | WANTinterpret, ce);
-	    }
-
-	    if (ce->op == TOKstring)
-	    {	/* It is for a string literal, so the
-		 * length will be a const.
-		 */
-		Expression *e = new IntegerExp(0, ((StringExp *)ce)->len, Type::tsize_t);
-		v->init = new ExpInitializer(0, e);
-		v->storage_class |= STCstatic | STCconst;
-	    }
-	    else if (ce->op == TOKarrayliteral)
-	    {	/* It is for an array literal, so the
-		 * length will be a const.
-		 */
-		Expression *e = new IntegerExp(0, ((ArrayLiteralExp *)ce)->elements->dim, Type::tsize_t);
-		v->init = new ExpInitializer(0, e);
-		v->storage_class |= STCstatic | STCconst;
-	    }
-	    else if (ce->op == TOKtuple)
-	    {	/* It is for an expression tuple, so the
-		 * length will be a const.
-		 */
-		Expression *e = new IntegerExp(0, ((TupleExp *)ce)->exps->dim, Type::tsize_t);
-		v->init = new ExpInitializer(0, e);
-		v->storage_class |= STCstatic | STCconst;
-	    }
-	    *pvar = v;
-	}
-	(*pvar)->semantic(sc);
-	return (*pvar);
-    }
-    return NULL;
-}
-
-
-/****************************** DsymbolTable ******************************/
-
-DsymbolTable::DsymbolTable()
-{
-    tab = new StringTable;
-}
-
-DsymbolTable::~DsymbolTable()
-{
-    delete tab;
-}
-
-Dsymbol *DsymbolTable::lookup(Identifier *ident)
-{   StringValue *sv;
-
-#ifdef DEBUG
-    assert(ident);
-    assert(tab);
-#endif
-    sv = tab->lookup((char*)ident->string, ident->len);
-    return (Dsymbol *)(sv ? sv->ptrvalue : NULL);
-}
-
-Dsymbol *DsymbolTable::insert(Dsymbol *s)
-{   StringValue *sv;
-    Identifier *ident;
-
-    //printf("DsymbolTable::insert(this = %p, '%s')\n", this, s->ident->toChars());
-    ident = s->ident;
-#ifdef DEBUG
-    assert(ident);
-    assert(tab);
-#endif
-    sv = tab->insert(ident->toChars(), ident->len);
-    if (!sv)
-	return NULL;		// already in table
-    sv->ptrvalue = s;
-    return s;
-}
-
-Dsymbol *DsymbolTable::insert(Identifier *ident, Dsymbol *s)
-{   StringValue *sv;
-
-    //printf("DsymbolTable::insert()\n");
-    sv = tab->insert(ident->toChars(), ident->len);
-    if (!sv)
-	return NULL;		// already in table
-    sv->ptrvalue = s;
-    return s;
-}
-
-Dsymbol *DsymbolTable::update(Dsymbol *s)
-{   StringValue *sv;
-    Identifier *ident;
-
-    ident = s->ident;
-    sv = tab->update(ident->toChars(), ident->len);
-    sv->ptrvalue = s;
-    return s;
-}
-
-
-
-
+
+// 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 <string.h>
+#include <assert.h>
+
+#include "rmem.h"
+
+#include "mars.h"
+#include "dsymbol.h"
+#include "aggregate.h"
+#include "identifier.h"
+#include "module.h"
+#include "mtype.h"
+#include "expression.h"
+#include "statement.h"
+#include "declaration.h"
+#include "id.h"
+#include "scope.h"
+#include "init.h"
+#include "import.h"
+#include "template.h"
+#include "attrib.h"
+
+#if IN_LLVM
+#include "../gen/enums.h"
+#endif
+
+/****************************** Dsymbol ******************************/
+
+Dsymbol::Dsymbol()
+{
+    //printf("Dsymbol::Dsymbol(%p)\n", this);
+    this->ident = NULL;
+    this->c_ident = NULL;
+    this->parent = NULL;
+#if IN_DMD
+    this->csym = NULL;
+    this->isym = NULL;
+#endif
+    this->loc = 0;
+    this->comment = NULL;
+
+#if IN_LLVM
+    this->llvmInternal = LLVMnone;
+    this->irsym = NULL;
+#endif
+}
+
+Dsymbol::Dsymbol(Identifier *ident)
+{
+    //printf("Dsymbol::Dsymbol(%p, ident)\n", this);
+    this->ident = ident;
+    this->c_ident = NULL;
+    this->parent = NULL;
+#if IN_DMD
+    this->csym = NULL;
+    this->isym = NULL;
+#endif
+    this->loc = 0;
+    this->comment = NULL;
+
+#if IN_LLVM
+    this->llvmInternal = LLVMnone;
+    this->irsym = NULL;
+#endif
+}
+
+int Dsymbol::equals(Object *o)
+{   Dsymbol *s;
+
+    if (this == o)
+	return TRUE;
+    s = (Dsymbol *)(o);
+    if (s && ident->equals(s->ident))
+	return TRUE;
+    return FALSE;
+}
+
+/**************************************
+ * Copy the syntax.
+ * Used for template instantiations.
+ * If s is NULL, allocate the new object, otherwise fill it in.
+ */
+
+Dsymbol *Dsymbol::syntaxCopy(Dsymbol *s)
+{
+    print();
+    printf("%s %s\n", kind(), toChars());
+    assert(0);
+    return NULL;
+}
+
+/**************************************
+ * Determine if this symbol is only one.
+ * Returns:
+ *	FALSE, *ps = NULL: There are 2 or more symbols
+ *	TRUE,  *ps = NULL: There are zero symbols
+ *	TRUE,  *ps = symbol: The one and only one symbol
+ */
+
+int Dsymbol::oneMember(Dsymbol **ps)
+{
+    //printf("Dsymbol::oneMember()\n");
+    *ps = this;
+    return TRUE;
+}
+
+/*****************************************
+ * Same as Dsymbol::oneMember(), but look at an array of Dsymbols.
+ */
+
+int Dsymbol::oneMembers(Array *members, Dsymbol **ps)
+{
+    //printf("Dsymbol::oneMembers() %d\n", members ? members->dim : 0);
+    Dsymbol *s = NULL;
+
+    if (members)
+    {
+	for (int i = 0; i < members->dim; i++)
+	{   Dsymbol *sx = (Dsymbol *)members->data[i];
+
+	    int x = sx->oneMember(ps);
+	    //printf("\t[%d] kind %s = %d, s = %p\n", i, sx->kind(), x, *ps);
+	    if (!x)
+	    {
+		//printf("\tfalse 1\n");
+		assert(*ps == NULL);
+		return FALSE;
+	    }
+	    if (*ps)
+	    {
+		if (s)			// more than one symbol
+		{   *ps = NULL;
+		    //printf("\tfalse 2\n");
+		    return FALSE;
+		}
+		s = *ps;
+	    }
+	}
+    }
+    *ps = s;		// s is the one symbol, NULL if none
+    //printf("\ttrue\n");
+    return TRUE;
+}
+
+/*****************************************
+ * Is Dsymbol a variable that contains pointers?
+ */
+
+int Dsymbol::hasPointers()
+{
+    //printf("Dsymbol::hasPointers() %s\n", toChars());
+    return 0;
+}
+
+char *Dsymbol::toChars()
+{
+    return ident ? ident->toChars() : (char *)"__anonymous";
+}
+
+char *Dsymbol::toPrettyChars()
+{   Dsymbol *p;
+    char *s;
+    char *q;
+    size_t len;
+
+    //printf("Dsymbol::toPrettyChars() '%s'\n", toChars());
+    if (!parent)
+	return toChars();
+
+    len = 0;
+    for (p = this; p; p = p->parent)
+	len += strlen(p->toChars()) + 1;
+
+    s = (char *)mem.malloc(len);
+    q = s + len - 1;
+    *q = 0;
+    for (p = this; p; p = p->parent)
+    {
+	char *t = p->toChars();
+	len = strlen(t);
+	q -= len;
+	memcpy(q, t, len);
+	if (q == s)
+	    break;
+	q--;
+	*q = '.';
+    }
+    return s;
+}
+
+char *Dsymbol::locToChars()
+{
+    OutBuffer buf;
+    char *p;
+
+    Module *m = getModule();
+
+    if (m && m->srcfile)
+	loc.filename = m->srcfile->toChars();
+    return loc.toChars();
+}
+
+const char *Dsymbol::kind()
+{
+    return "symbol";
+}
+
+/*********************************
+ * If this symbol is really an alias for another,
+ * return that other.
+ */
+
+Dsymbol *Dsymbol::toAlias()
+{
+    return this;
+}
+
+Dsymbol *Dsymbol::toParent()
+{
+    return parent ? parent->pastMixin() : NULL;
+}
+
+Dsymbol *Dsymbol::pastMixin()
+{
+    Dsymbol *s = this;
+
+    //printf("Dsymbol::pastMixin() %s\n", toChars());
+    while (s && s->isTemplateMixin())
+	s = s->parent;
+    return s;
+}
+
+/**********************************
+ * Use this instead of toParent() when looking for the
+ * 'this' pointer of the enclosing function/class.
+ */
+
+Dsymbol *Dsymbol::toParent2()
+{
+    Dsymbol *s = parent;
+    while (s && s->isTemplateInstance())
+	s = s->parent;
+    return s;
+}
+
+TemplateInstance *Dsymbol::inTemplateInstance()
+{
+    for (Dsymbol *parent = this->parent; parent; parent = parent->parent)
+    {
+	TemplateInstance *ti = parent->isTemplateInstance();
+	if (ti)
+	    return ti;
+    }
+    return NULL;
+}
+
+int Dsymbol::isAnonymous()
+{
+    return ident ? 0 : 1;
+}
+
+void Dsymbol::semantic(Scope *sc)
+{
+    error("%p has no semantic routine", this);
+}
+
+void Dsymbol::semantic2(Scope *sc)
+{
+    // Most Dsymbols have no further semantic analysis needed
+}
+
+void Dsymbol::semantic3(Scope *sc)
+{
+    // Most Dsymbols have no further semantic analysis needed
+}
+
+void Dsymbol::inlineScan()
+{
+    // Most Dsymbols have no further semantic analysis needed
+}
+
+/*********************************************
+ * Search for ident as member of s.
+ * Input:
+ *	flags:	1	don't find private members
+ *		2	don't give error messages
+ *		4	return NULL if ambiguous
+ * Returns:
+ *	NULL if not found
+ */
+
+Dsymbol *Dsymbol::search(Loc loc, Identifier *ident, int flags)
+{
+    //printf("Dsymbol::search(this=%p,%s, ident='%s')\n", this, toChars(), ident->toChars());
+    return NULL;
+}
+
+/***************************************
+ * Search for identifier id as a member of 'this'.
+ * id may be a template instance.
+ * Returns:
+ *	symbol found, NULL if not
+ */
+
+Dsymbol *Dsymbol::searchX(Loc loc, Scope *sc, Identifier *id)
+{
+    //printf("Dsymbol::searchX(this=%p,%s, ident='%s')\n", this, toChars(), ident->toChars());
+    Dsymbol *s = toAlias();
+    Dsymbol *sm;
+
+    switch (id->dyncast())
+    {
+	case DYNCAST_IDENTIFIER:
+	    sm = s->search(loc, id, 0);
+	    break;
+
+	case DYNCAST_DSYMBOL:
+	{   // It's a template instance
+	    //printf("\ttemplate instance id\n");
+	    Dsymbol *st = (Dsymbol *)id;
+	    TemplateInstance *ti = st->isTemplateInstance();
+	    id = ti->name;
+	    sm = s->search(loc, id, 0);
+	    if (!sm)
+	    {   error("template identifier %s is not a member of %s %s",
+		    id->toChars(), s->kind(), s->toChars());
+		return NULL;
+	    }
+	    sm = sm->toAlias();
+	    TemplateDeclaration *td = sm->isTemplateDeclaration();
+	    if (!td)
+	    {
+		error("%s is not a template, it is a %s", id->toChars(), sm->kind());
+		return NULL;
+	    }
+	    ti->tempdecl = td;
+	    if (!ti->semanticdone)
+		ti->semantic(sc);
+	    sm = ti->toAlias();
+	    break;
+	}
+
+	default:
+	    assert(0);
+    }
+    return sm;
+}
+
+int Dsymbol::overloadInsert(Dsymbol *s)
+{
+    //printf("Dsymbol::overloadInsert('%s')\n", s->toChars());
+    return FALSE;
+}
+
+void Dsymbol::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    buf->writestring(toChars());
+}
+
+unsigned Dsymbol::size(Loc loc)
+{
+    error("Dsymbol '%s' has no size\n", toChars());
+    return 0;
+}
+
+int Dsymbol::isforwardRef()
+{
+    return FALSE;
+}
+
+AggregateDeclaration *Dsymbol::isThis()
+{
+    return NULL;
+}
+
+ClassDeclaration *Dsymbol::isClassMember()	// are we a member of a class?
+{
+    Dsymbol *parent = toParent();
+    if (parent && parent->isClassDeclaration())
+	return (ClassDeclaration *)parent;
+    return NULL;
+}
+
+void Dsymbol::defineRef(Dsymbol *s)
+{
+    assert(0);
+}
+
+int Dsymbol::isExport()
+{
+    return FALSE;
+}
+
+int Dsymbol::isImportedSymbol()
+{
+    return FALSE;
+}
+
+int Dsymbol::isDeprecated()
+{
+    return FALSE;
+}
+
+int Dsymbol::isOverloadable()
+{
+    return 0;
+}
+
+LabelDsymbol *Dsymbol::isLabel()		// is this a LabelDsymbol()?
+{
+    return NULL;
+}
+
+AggregateDeclaration *Dsymbol::isMember()	// is this a member of an AggregateDeclaration?
+{
+    //printf("Dsymbol::isMember() %s\n", toChars());
+    Dsymbol *parent = toParent();
+    //printf("parent is %s %s\n", parent->kind(), parent->toChars());
+    return parent ? parent->isAggregateDeclaration() : NULL;
+}
+
+Type *Dsymbol::getType()
+{
+    return NULL;
+}
+
+int Dsymbol::needThis()
+{
+    return FALSE;
+}
+
+int Dsymbol::addMember(Scope *sc, ScopeDsymbol *sd, int memnum)
+{
+    //printf("Dsymbol::addMember('%s')\n", toChars());
+    //printf("Dsymbol::addMember(this = %p, '%s' scopesym = '%s')\n", this, toChars(), sd->toChars());
+    //printf("Dsymbol::addMember(this = %p, '%s' sd = %p, sd->symtab = %p)\n", this, toChars(), sd, sd->symtab);
+    parent = sd;
+    if (!isAnonymous())		// no name, so can't add it to symbol table
+    {
+	if (!sd->symtab->insert(this))	// if name is already defined
+	{
+	    Dsymbol *s2;
+
+	    s2 = sd->symtab->lookup(ident);
+	    if (!s2->overloadInsert(this))
+	    {
+		sd->multiplyDefined(0, this, s2);
+	    }
+	}
+	if (sd->isAggregateDeclaration() || sd->isEnumDeclaration())
+	{
+	    if (ident == Id::__sizeof || ident == Id::alignof || ident == Id::mangleof)
+		error(".%s property cannot be redefined", ident->toChars());
+	}
+	return 1;
+    }
+    return 0;
+}
+
+void Dsymbol::error(const char *format, ...)
+{
+    //printf("Dsymbol::error()\n");
+    if (!global.gag)
+    {
+	char *p = locToChars();
+
+	if (*p)
+	    fprintf(stdmsg, "%s: ", p);
+	mem.free(p);
+
+	fprintf(stdmsg, "Error: ");
+	if (isAnonymous())
+	    fprintf(stdmsg, "%s ", kind());
+	else
+	    fprintf(stdmsg, "%s %s ", kind(), toPrettyChars());
+
+	va_list ap;
+	va_start(ap, format);
+	vfprintf(stdmsg, format, ap);
+	va_end(ap);
+
+	fprintf(stdmsg, "\n");
+	fflush(stdmsg);
+    }
+    global.errors++;
+
+    //fatal();
+}
+
+void Dsymbol::error(Loc loc, const char *format, ...)
+{
+    if (!global.gag)
+    {
+	char *p = loc.toChars();
+	if (!*p)
+	    p = locToChars();
+
+	if (*p)
+	    fprintf(stdmsg, "%s: ", p);
+	mem.free(p);
+
+	fprintf(stdmsg, "Error: ");
+	fprintf(stdmsg, "%s %s ", kind(), toPrettyChars());
+
+	va_list ap;
+	va_start(ap, format);
+	vfprintf(stdmsg, format, ap);
+	va_end(ap);
+
+	fprintf(stdmsg, "\n");
+	fflush(stdmsg);
+    }
+
+    global.errors++;
+
+    //fatal();
+}
+
+void Dsymbol::checkDeprecated(Loc loc, Scope *sc)
+{
+    if (!global.params.useDeprecated && isDeprecated())
+    {
+	// Don't complain if we're inside a deprecated symbol's scope
+	for (Dsymbol *sp = sc->parent; sp; sp = sp->parent)
+	{   if (sp->isDeprecated())
+		return;
+	}
+
+	for (; sc; sc = sc->enclosing)
+	{
+	    if (sc->scopesym && sc->scopesym->isDeprecated())
+		return;
+
+	    // If inside a StorageClassDeclaration that is deprecated
+	    if (sc->stc & STCdeprecated)
+		return;
+	}
+
+	error(loc, "is deprecated");
+    }
+}
+
+/**********************************
+ * Determine which Module a Dsymbol is in.
+ */
+
+Module *Dsymbol::getModule()
+{
+    Module *m;
+    Dsymbol *s;
+
+    //printf("Dsymbol::getModule()\n");
+    s = this;
+    while (s)
+    {
+	//printf("\ts = '%s'\n", s->toChars());
+	m = s->isModule();
+	if (m)
+	    return m;
+	s = s->parent;
+    }
+    return NULL;
+}
+
+
+/**********************************
+ * Determine which Module a Dsymbol will be compiled in.
+ * This may be different from getModule for templates.
+ */
+
+Module *Dsymbol::getCompilationModule()
+{
+    Module *m;
+    TemplateInstance *ti;
+    Dsymbol *s;
+
+    //printf("Dsymbol::getModule()\n");
+    s = this;
+    while (s)
+    {
+	//printf("\ts = '%s'\n", s->toChars());
+	m = s->isModule();
+	if (m)
+	    return m;
+	ti = s->isTemplateInstance();
+	if (ti && ti->tmodule)
+	    return ti->tmodule;
+	s = s->parent;
+    }
+    return NULL;
+}
+
+/*************************************
+ */
+
+enum PROT Dsymbol::prot()
+{
+    return PROTpublic;
+}
+
+/*************************************
+ * Do syntax copy of an array of Dsymbol's.
+ */
+
+
+Array *Dsymbol::arraySyntaxCopy(Array *a)
+{
+
+    Array *b = NULL;
+    if (a)
+    {
+	b = a->copy();
+	for (int i = 0; i < b->dim; i++)
+	{
+	    Dsymbol *s = (Dsymbol *)b->data[i];
+
+	    s = s->syntaxCopy(NULL);
+	    b->data[i] = (void *)s;
+	}
+    }
+    return b;
+}
+
+
+/****************************************
+ * Add documentation comment to Dsymbol.
+ * Ignore NULL comments.
+ */
+
+void Dsymbol::addComment(unsigned char *comment)
+{
+    //if (comment)
+	//printf("adding comment '%s' to symbol %p '%s'\n", comment, this, toChars());
+
+    if (!this->comment)
+	this->comment = comment;
+#if 1
+    else if (comment && strcmp((char *)comment, (char *)this->comment))
+    {	// Concatenate the two
+	this->comment = Lexer::combineComments(this->comment, comment);
+    }
+#endif
+}
+
+/********************************* OverloadSet ****************************/
+
+OverloadSet::OverloadSet()
+    : Dsymbol()
+{
+}
+
+void OverloadSet::push(Dsymbol *s)
+{
+    a.push(s);
+}
+
+const char *OverloadSet::kind()
+{
+    return "overloadset";
+}
+
+
+/********************************* ScopeDsymbol ****************************/
+
+ScopeDsymbol::ScopeDsymbol()
+    : Dsymbol()
+{
+    members = NULL;
+    symtab = NULL;
+    imports = NULL;
+    prots = NULL;
+}
+
+ScopeDsymbol::ScopeDsymbol(Identifier *id)
+    : Dsymbol(id)
+{
+    members = NULL;
+    symtab = NULL;
+    imports = NULL;
+    prots = NULL;
+}
+
+Dsymbol *ScopeDsymbol::syntaxCopy(Dsymbol *s)
+{
+    //printf("ScopeDsymbol::syntaxCopy('%s')\n", toChars());
+
+    ScopeDsymbol *sd;
+    if (s)
+	sd = (ScopeDsymbol *)s;
+    else
+	sd = new ScopeDsymbol(ident);
+    sd->members = arraySyntaxCopy(members);
+    return sd;
+}
+
+Dsymbol *ScopeDsymbol::search(Loc loc, Identifier *ident, int flags)
+{
+    //printf("%s->ScopeDsymbol::search(ident='%s', flags=x%x)\n", toChars(), ident->toChars(), flags);
+    //if (strcmp(ident->toChars(),"c") == 0) *(char*)0=0;
+
+    // Look in symbols declared in this module
+    Dsymbol *s = symtab ? symtab->lookup(ident) : NULL;
+
+    // hide the aliases generated by selective or renamed private imports
+    if (s && flags & 1)
+        if (AliasDeclaration* ad = s->isAliasDeclaration())
+	    // may be a private alias to a function that is overloaded. these
+	    // are sorted out during overload resolution, accept them here
+	    if (ad->importprot == PROTprivate && !ad->aliassym->isFuncAliasDeclaration())
+		s = NULL;
+
+    if (s)
+    {
+	//printf("\ts = '%s.%s'\n",toChars(),s->toChars());
+    }
+    else if (imports)
+    {
+	OverloadSet *a = NULL;
+
+	// Look in imported modules
+	for (int i = 0; i < imports->dim; i++)
+	{   ScopeDsymbol *ss = (ScopeDsymbol *)imports->data[i];
+	    Dsymbol *s2;
+
+	    // If private import, don't search it
+	    if (flags & 1 && prots[i] == PROTprivate)
+		continue;
+
+	    //printf("\tscanning import '%s', prots = %d, isModule = %p, isImport = %p\n", ss->toChars(), prots[i], ss->isModule(), ss->isImport());
+	    /* Don't find private members if ss is a module
+	     */
+	    s2 = ss->search(loc, ident, ss->isModule() ? 1 : 0);
+	    if (!s)
+		s = s2;
+	    else if (s2 && s != s2)
+	    {
+		if (s->toAlias() == s2->toAlias())
+		{
+		    /* After following aliases, we found the same symbol,
+		     * so it's not an ambiguity.
+		     * But if one alias is deprecated, prefer the other.
+		     */
+		    if (s->isDeprecated())
+			s = s2;
+		}
+		else
+		{
+		    /* Two imports of the same module should be regarded as
+		     * the same.
+		     */
+		    Import *i1 = s->isImport();
+		    Import *i2 = s2->isImport();
+		    if (!(i1 && i2 &&
+			  (i1->mod == i2->mod ||
+			   (!i1->parent->isImport() && !i2->parent->isImport() &&
+			    i1->ident->equals(i2->ident))
+			  )
+			 )
+		       )
+		    {
+			/* If both s2 and s are overloadable (though we only
+			 * need to check s once)
+			 */
+			if (s2->isOverloadable() && (a || s->isOverloadable()))
+			{   if (!a)
+				a = new OverloadSet();
+			    /* Don't add to a[] if s2 is alias of previous sym
+			     */
+			    for (int j = 0; j < a->a.dim; j++)
+			    {	Dsymbol *s3 = (Dsymbol *)a->a.data[j];
+				if (s2->toAlias() == s3->toAlias())
+				{
+				    if (s3->isDeprecated())
+					a->a.data[j] = (void *)s2;
+				    goto Lcontinue;
+				}
+			    }
+			    a->push(s2);
+			Lcontinue:
+			    continue;
+			}
+			if (flags & 4)		// if return NULL on ambiguity
+			    return NULL;
+			if (!(flags & 2))
+			    ss->multiplyDefined(loc, s, s2);
+			break;
+		    }
+		}
+	    }
+	}
+
+	/* Build special symbol if we had multiple finds
+	 */
+	if (a)
+	{   assert(s);
+	    a->push(s);
+	    s = a;
+	}
+
+	if (s)
+	{
+	    Declaration *d = s->isDeclaration();
+	    if (d && d->protection == PROTprivate &&
+		!d->parent->isTemplateMixin() &&
+		!(flags & 2))
+		error("%s is private", d->toPrettyChars());
+	}
+    }
+    return s;
+}
+
+void ScopeDsymbol::importScope(ScopeDsymbol *s, enum PROT protection)
+{
+    //printf("%s->ScopeDsymbol::importScope(%s, %d)\n", toChars(), s->toChars(), protection);
+
+    // No circular or redundant import's
+    if (s != this)
+    {
+	if (!imports)
+	    imports = new Array();
+	else
+	{
+	    for (int i = 0; i < imports->dim; i++)
+	    {   ScopeDsymbol *ss;
+
+		ss = (ScopeDsymbol *) imports->data[i];
+		if (ss == s)			// if already imported
+		{
+		    if (protection > prots[i])
+			prots[i] = protection;	// upgrade access
+		    return;
+		}
+	    }
+	}
+	imports->push(s);
+	prots = (unsigned char *)mem.realloc(prots, imports->dim * sizeof(prots[0]));
+	prots[imports->dim - 1] = protection;
+    }
+}
+
+int ScopeDsymbol::isforwardRef()
+{
+    return (members == NULL);
+}
+
+void ScopeDsymbol::defineRef(Dsymbol *s)
+{
+    ScopeDsymbol *ss;
+
+    ss = s->isScopeDsymbol();
+    members = ss->members;
+    ss->members = NULL;
+}
+
+void ScopeDsymbol::multiplyDefined(Loc loc, Dsymbol *s1, Dsymbol *s2)
+{
+#if 0
+    printf("ScopeDsymbol::multiplyDefined()\n");
+    printf("s1 = %p, '%s' kind = '%s', parent = %s\n", s1, s1->toChars(), s1->kind(), s1->parent ? s1->parent->toChars() : "");
+    printf("s2 = %p, '%s' kind = '%s', parent = %s\n", s2, s2->toChars(), s2->kind(), s2->parent ? s2->parent->toChars() : "");
+#endif
+    if (loc.filename)
+    {	::error(loc, "%s at %s conflicts with %s at %s",
+	    s1->toPrettyChars(),
+	    s1->locToChars(),
+	    s2->toPrettyChars(),
+	    s2->locToChars());
+    }
+    else
+    {
+	s1->error(loc, "conflicts with %s %s at %s",
+	    s2->kind(),
+	    s2->toPrettyChars(),
+	    s2->locToChars());
+    }
+}
+
+Dsymbol *ScopeDsymbol::nameCollision(Dsymbol *s)
+{
+    Dsymbol *sprev;
+
+    // Look to see if we are defining a forward referenced symbol
+
+    sprev = symtab->lookup(s->ident);
+    assert(sprev);
+    if (s->equals(sprev))		// if the same symbol
+    {
+	if (s->isforwardRef())		// if second declaration is a forward reference
+	    return sprev;
+	if (sprev->isforwardRef())
+	{
+	    sprev->defineRef(s);	// copy data from s into sprev
+	    return sprev;
+	}
+    }
+    multiplyDefined(0, s, sprev);
+    return sprev;
+}
+
+const char *ScopeDsymbol::kind()
+{
+    return "ScopeDsymbol";
+}
+
+
+/***************************************
+ * Determine number of Dsymbols, folding in AttribDeclaration members.
+ */
+
+size_t ScopeDsymbol::dim(Array *members)
+{
+    size_t n = 0;
+    if (members)
+    {
+	for (size_t i = 0; i < members->dim; i++)
+	{   Dsymbol *s = (Dsymbol *)members->data[i];
+	    AttribDeclaration *a = s->isAttribDeclaration();
+
+	    if (a)
+	    {
+		n += dim(a->decl);
+	    }
+	    else
+		n++;
+	}
+    }
+    return n;
+}
+
+/***************************************
+ * Get nth Dsymbol, folding in AttribDeclaration members.
+ * Returns:
+ *	Dsymbol*	nth Dsymbol
+ *	NULL		not found, *pn gets incremented by the number
+ *			of Dsymbols
+ */
+
+Dsymbol *ScopeDsymbol::getNth(Array *members, size_t nth, size_t *pn)
+{
+    if (!members)
+	return NULL;
+
+    size_t n = 0;
+    for (size_t i = 0; i < members->dim; i++)
+    {   Dsymbol *s = (Dsymbol *)members->data[i];
+	AttribDeclaration *a = s->isAttribDeclaration();
+
+	if (a)
+	{
+	    s = getNth(a->decl, nth - n, &n);
+	    if (s)
+		return s;
+	}
+	else if (n == nth)
+	    return s;
+	else
+	    n++;
+    }
+
+    if (pn)
+	*pn += n;
+    return NULL;
+}
+
+/*******************************************
+ * Look for member of the form:
+ *	const(MemberInfo)[] getMembers(string);
+ * Returns NULL if not found
+ */
+
+#if DMDV2
+FuncDeclaration *ScopeDsymbol::findGetMembers()
+{
+    Dsymbol *s = search_function(this, Id::getmembers);
+    FuncDeclaration *fdx = s ? s->isFuncDeclaration() : NULL;
+
+#if 0  // Finish
+    static TypeFunction *tfgetmembers;
+
+    if (!tfgetmembers)
+    {
+	Scope sc;
+	Arguments *arguments = new Arguments;
+	Arguments *arg = new Argument(STCin, Type::tchar->constOf()->arrayOf(), NULL, NULL);
+	arguments->push(arg);
+
+	Type *tret = NULL;
+	tfgetmembers = new TypeFunction(arguments, tret, 0, LINKd);
+	tfgetmembers = (TypeFunction *)tfgetmembers->semantic(0, &sc);
+    }
+    if (fdx)
+	fdx = fdx->overloadExactMatch(tfgetmembers);
+#endif
+    if (fdx && fdx->isVirtual())
+	fdx = NULL;
+
+    return fdx;
+}
+#endif
+
+
+/****************************** WithScopeSymbol ******************************/
+
+WithScopeSymbol::WithScopeSymbol(WithStatement *withstate)
+    : ScopeDsymbol()
+{
+    this->withstate = withstate;
+}
+
+Dsymbol *WithScopeSymbol::search(Loc loc, Identifier *ident, int flags)
+{
+    // Acts as proxy to the with class declaration
+    return withstate->exp->type->toDsymbol(NULL)->search(loc, ident, 0);
+}
+
+/****************************** ArrayScopeSymbol ******************************/
+
+ArrayScopeSymbol::ArrayScopeSymbol(Scope *sc, Expression *e)
+    : ScopeDsymbol()
+{
+    assert(e->op == TOKindex || e->op == TOKslice);
+    exp = e;
+    type = NULL;
+    td = NULL;
+    this->sc = sc;
+}
+
+ArrayScopeSymbol::ArrayScopeSymbol(Scope *sc, TypeTuple *t)
+    : ScopeDsymbol()
+{
+    exp = NULL;
+    type = t;
+    td = NULL;
+    this->sc = sc;
+}
+
+ArrayScopeSymbol::ArrayScopeSymbol(Scope *sc, TupleDeclaration *s)
+    : ScopeDsymbol()
+{
+    exp = NULL;
+    type = NULL;
+    td = s;
+    this->sc = sc;
+}
+
+Dsymbol *ArrayScopeSymbol::search(Loc loc, Identifier *ident, int flags)
+{
+    //printf("ArrayScopeSymbol::search('%s', flags = %d)\n", ident->toChars(), flags);
+    if (ident == Id::length || ident == Id::dollar)
+    {	VarDeclaration **pvar;
+	Expression *ce;
+
+    L1:
+
+	if (td)
+ 	{   /* $ gives the number of elements in the tuple
+	     */
+	    VarDeclaration *v = new VarDeclaration(loc, Type::tsize_t, Id::dollar, NULL);
+	    Expression *e = new IntegerExp(0, td->objects->dim, Type::tsize_t);
+	    v->init = new ExpInitializer(0, e);
+	    v->storage_class |= STCstatic | STCconst;
+	    v->semantic(sc);
+	    return v;
+	}
+
+	if (type)
+ 	{   /* $ gives the number of type entries in the type tuple
+	     */
+	    VarDeclaration *v = new VarDeclaration(loc, Type::tsize_t, Id::dollar, NULL);
+	    Expression *e = new IntegerExp(0, type->arguments->dim, Type::tsize_t);
+	    v->init = new ExpInitializer(0, e);
+	    v->storage_class |= STCstatic | STCconst;
+	    v->semantic(sc);
+	    return v;
+	}
+
+	if (exp->op == TOKindex)
+	{   /* array[index] where index is some function of $
+	     */
+	    IndexExp *ie = (IndexExp *)exp;
+
+	    pvar = &ie->lengthVar;
+	    ce = ie->e1;
+	}
+	else if (exp->op == TOKslice)
+	{   /* array[lwr .. upr] where lwr or upr is some function of $
+	     */
+	    SliceExp *se = (SliceExp *)exp;
+
+	    pvar = &se->lengthVar;
+	    ce = se->e1;
+	}
+	else
+	    /* Didn't find $, look in enclosing scope(s).
+	     */
+	    return NULL;
+
+	/* If we are indexing into an array that is really a type
+	 * tuple, rewrite this as an index into a type tuple and
+	 * try again.
+	 */
+	if (ce->op == TOKtype)
+	{
+	    Type *t = ((TypeExp *)ce)->type;
+	    if (t->ty == Ttuple)
+	    {	type = (TypeTuple *)t;
+		goto L1;
+	    }
+	}
+
+	/* *pvar is lazily initialized, so if we refer to $
+	 * multiple times, it gets set only once.
+	 */
+	if (!*pvar)		// if not already initialized
+	{   /* Create variable v and set it to the value of $,
+	     * which will be a constant.
+	     */
+	    VarDeclaration *v = new VarDeclaration(loc, Type::tsize_t, Id::dollar, NULL);
+
+	    if (ce->op == TOKvar)
+	    {	// if ce is const, get its initializer
+		ce = fromConstInitializer(WANTvalue | WANTinterpret, ce);
+	    }
+
+	    if (ce->op == TOKstring)
+	    {	/* It is for a string literal, so the
+		 * length will be a const.
+		 */
+		Expression *e = new IntegerExp(0, ((StringExp *)ce)->len, Type::tsize_t);
+		v->init = new ExpInitializer(0, e);
+		v->storage_class |= STCstatic | STCconst;
+	    }
+	    else if (ce->op == TOKarrayliteral)
+	    {	/* It is for an array literal, so the
+		 * length will be a const.
+		 */
+		Expression *e = new IntegerExp(0, ((ArrayLiteralExp *)ce)->elements->dim, Type::tsize_t);
+		v->init = new ExpInitializer(0, e);
+		v->storage_class |= STCstatic | STCconst;
+	    }
+	    else if (ce->op == TOKtuple)
+	    {	/* It is for an expression tuple, so the
+		 * length will be a const.
+		 */
+		Expression *e = new IntegerExp(0, ((TupleExp *)ce)->exps->dim, Type::tsize_t);
+		v->init = new ExpInitializer(0, e);
+		v->storage_class |= STCstatic | STCconst;
+	    }
+	    *pvar = v;
+	}
+	(*pvar)->semantic(sc);
+	return (*pvar);
+    }
+    return NULL;
+}
+
+
+/****************************** DsymbolTable ******************************/
+
+DsymbolTable::DsymbolTable()
+{
+    tab = new StringTable;
+}
+
+DsymbolTable::~DsymbolTable()
+{
+    delete tab;
+}
+
+Dsymbol *DsymbolTable::lookup(Identifier *ident)
+{
+#ifdef DEBUG
+    assert(ident);
+    assert(tab);
+#endif
+    StringValue *sv = tab->lookup((char*)ident->string, ident->len);
+    return (Dsymbol *)(sv ? sv->ptrvalue : NULL);
+}
+
+Dsymbol *DsymbolTable::insert(Dsymbol *s)
+{   StringValue *sv;
+    Identifier *ident;
+
+    //printf("DsymbolTable::insert(this = %p, '%s')\n", this, s->ident->toChars());
+    ident = s->ident;
+#ifdef DEBUG
+    assert(ident);
+    assert(tab);
+#endif
+    sv = tab->insert(ident->toChars(), ident->len);
+    if (!sv)
+	return NULL;		// already in table
+    sv->ptrvalue = s;
+    return s;
+}
+
+Dsymbol *DsymbolTable::insert(Identifier *ident, Dsymbol *s)
+{   StringValue *sv;
+
+    //printf("DsymbolTable::insert()\n");
+    sv = tab->insert(ident->toChars(), ident->len);
+    if (!sv)
+	return NULL;		// already in table
+    sv->ptrvalue = s;
+    return s;
+}
+
+Dsymbol *DsymbolTable::update(Dsymbol *s)
+{   StringValue *sv;
+    Identifier *ident;
+
+    ident = s->ident;
+    sv = tab->update(ident->toChars(), ident->len);
+    sv->ptrvalue = s;
+    return s;
+}
+
+
+
+
--- a/dmd2/dsymbol.h	Mon Jun 01 01:28:18 2009 +0200
+++ b/dmd2/dsymbol.h	Mon Jun 01 19:02:20 2009 +0100
@@ -1,326 +1,352 @@
-
-// Compiler implementation of the D programming language
-// Copyright (c) 1999-2008 by Digital Mars
-// All Rights Reserved
-// written by Walter Bright
-// http://www.digitalmars.com
-// License for redistribution is by either the Artistic License
-// in artistic.txt, or the GNU General Public License in gnu.txt.
-// See the included readme.txt for details.
-
-#ifndef DMD_DSYMBOL_H
-#define DMD_DSYMBOL_H
-
-#ifdef __DMC__
-#pragma once
-#endif /* __DMC__ */
-
-#include "root.h"
-#include "stringtable.h"
-
-#include "mars.h"
-#include "arraytypes.h"
-
-// llvm
-#include "../ir/irsymbol.h"
-
-struct Identifier;
-struct Scope;
-struct DsymbolTable;
-struct Declaration;
-struct TupleDeclaration;
-struct TypedefDeclaration;
-struct AliasDeclaration;
-struct AggregateDeclaration;
-struct EnumDeclaration;
-struct ClassDeclaration;
-struct InterfaceDeclaration;
-struct StructDeclaration;
-struct UnionDeclaration;
-struct FuncDeclaration;
-struct FuncAliasDeclaration;
-struct FuncLiteralDeclaration;
-struct CtorDeclaration;
-struct PostBlitDeclaration;
-struct DtorDeclaration;
-struct StaticCtorDeclaration;
-struct StaticDtorDeclaration;
-struct InvariantDeclaration;
-struct UnitTestDeclaration;
-struct NewDeclaration;
-struct VarDeclaration;
-struct AttribDeclaration;
-struct Symbol;
-struct Package;
-struct Module;
-struct Import;
-struct Type;
-struct TypeTuple;
-struct WithStatement;
-struct LabelDsymbol;
-struct TemplateDeclaration;
-struct TemplateInstance;
-struct TemplateMixin;
-struct EnumMember;
-struct ScopeDsymbol;
-struct WithScopeSymbol;
-struct ArrayScopeSymbol;
-struct StaticStructInitDeclaration;
-struct Expression;
-struct DeleteDeclaration;
-struct HdrGenState;
-struct OverloadSet;
-struct TypeInfoDeclaration;
-struct ClassInfoDeclaration;
-
-#if IN_GCC
-union tree_node;
-typedef union tree_node TYPE;
-#else
-struct TYPE;
-#endif
-
-// llvm
-#if IN_LLVM
-namespace llvm
-{
-    class Value;
-}
-#endif
-
-enum PROT
-{
-    PROTundefined,
-    PROTnone,		// no access
-    PROTprivate,
-    PROTpackage,
-    PROTprotected,
-    PROTpublic,
-    PROTexport,
-};
-
-
-struct Dsymbol : Object
-{
-    Identifier *ident;
-    Identifier *c_ident;
-    Dsymbol *parent;
-    Symbol *csym;		// symbol for code generator
-    Symbol *isym;		// import version of csym
-    unsigned char *comment;	// documentation comment for this Dsymbol
-    Loc loc;			// where defined
-
-    Dsymbol();
-    Dsymbol(Identifier *);
-    char *toChars();
-    char *toPrettyChars();
-    char *locToChars();
-    int equals(Object *o);
-    int isAnonymous();
-    void error(Loc loc, const char *format, ...);
-    void error(const char *format, ...);
-    void checkDeprecated(Loc loc, Scope *sc);
-    Module *getModule();
-    Module *getCompilationModule(); // possibly different for templates
-    Dsymbol *pastMixin();
-    Dsymbol *toParent();
-    Dsymbol *toParent2();
-    TemplateInstance *inTemplateInstance();
-
-    int dyncast() { return DYNCAST_DSYMBOL; }	// kludge for template.isSymbol()
-
-    static Array *arraySyntaxCopy(Array *a);
-
-    virtual const char *kind();
-    virtual Dsymbol *toAlias();			// resolve real symbol
-    virtual int addMember(Scope *sc, ScopeDsymbol *s, int memnum);
-    virtual void semantic(Scope *sc);
-    virtual void semantic2(Scope *sc);
-    virtual void semantic3(Scope *sc);
-    virtual void inlineScan();
-    virtual Dsymbol *search(Loc loc, Identifier *ident, int flags);
-    Dsymbol *searchX(Loc loc, Scope *sc, Identifier *id);
-    virtual int overloadInsert(Dsymbol *s);
-#ifdef _DH
-    char *toHChars();
-    virtual void toHBuffer(OutBuffer *buf, HdrGenState *hgs);
-#endif
-    virtual void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-    virtual void toDocBuffer(OutBuffer *buf);
-    virtual unsigned size(Loc loc);
-    virtual int isforwardRef();
-    virtual void defineRef(Dsymbol *s);
-    virtual AggregateDeclaration *isThis();	// is a 'this' required to access the member
-    virtual ClassDeclaration *isClassMember();	// are we a member of a class?
-    virtual int isExport();			// is Dsymbol exported?
-    virtual int isImportedSymbol();		// is Dsymbol imported?
-    virtual int isDeprecated();			// is Dsymbol deprecated?
-    virtual int isOverloadable();
-    virtual LabelDsymbol *isLabel();		// is this a LabelDsymbol?
-    virtual AggregateDeclaration *isMember();	// is this symbol a member of an AggregateDeclaration?
-    virtual Type *getType();			// is this a type?
-    virtual char *mangle();
-    virtual int needThis();			// need a 'this' pointer?
-    virtual enum PROT prot();
-    virtual Dsymbol *syntaxCopy(Dsymbol *s);	// copy only syntax trees
-    virtual int oneMember(Dsymbol **ps);
-    static int oneMembers(Array *members, Dsymbol **ps);
-    virtual int hasPointers();
-    virtual void addLocalClass(ClassDeclarations *) { }
-    virtual void checkCtorConstInit() { }
-
-    virtual void addComment(unsigned char *comment);
-    virtual void emitComment(Scope *sc);
-    void emitDitto(Scope *sc);
-
-    // Backend
-
-    virtual Symbol *toSymbol();			// to backend symbol
-    virtual void toObjFile(int multiobj);			// compile to .obj file
-    virtual int cvMember(unsigned char *p);	// emit cv debug info for member
-
-    Symbol *toImport();				// to backend import symbol
-    static Symbol *toImport(Symbol *s);		// to backend import symbol
-
-    Symbol *toSymbolX(const char *prefix, int sclass, TYPE *t, const char *suffix);	// helper
-
-    // Eliminate need for dynamic_cast
-    virtual Package *isPackage() { return NULL; }
-    virtual Module *isModule() { return NULL; }
-    virtual EnumMember *isEnumMember() { return NULL; }
-    virtual TemplateDeclaration *isTemplateDeclaration() { return NULL; }
-    virtual TemplateInstance *isTemplateInstance() { return NULL; }
-    virtual TemplateMixin *isTemplateMixin() { return NULL; }
-    virtual Declaration *isDeclaration() { return NULL; }
-    virtual TupleDeclaration *isTupleDeclaration() { return NULL; }
-    virtual TypedefDeclaration *isTypedefDeclaration() { return NULL; }
-    virtual AliasDeclaration *isAliasDeclaration() { return NULL; }
-    virtual AggregateDeclaration *isAggregateDeclaration() { return NULL; }
-    virtual FuncDeclaration *isFuncDeclaration() { return NULL; }
-    virtual FuncAliasDeclaration *isFuncAliasDeclaration() { return NULL; }
-    virtual FuncLiteralDeclaration *isFuncLiteralDeclaration() { return NULL; }
-    virtual CtorDeclaration *isCtorDeclaration() { return NULL; }
-    virtual PostBlitDeclaration *isPostBlitDeclaration() { return NULL; }
-    virtual DtorDeclaration *isDtorDeclaration() { return NULL; }
-    virtual StaticCtorDeclaration *isStaticCtorDeclaration() { return NULL; }
-    virtual StaticDtorDeclaration *isStaticDtorDeclaration() { return NULL; }
-    virtual InvariantDeclaration *isInvariantDeclaration() { return NULL; }
-    virtual UnitTestDeclaration *isUnitTestDeclaration() { return NULL; }
-    virtual NewDeclaration *isNewDeclaration() { return NULL; }
-    virtual VarDeclaration *isVarDeclaration() { return NULL; }
-    virtual ClassDeclaration *isClassDeclaration() { return NULL; }
-    virtual StructDeclaration *isStructDeclaration() { return NULL; }
-    virtual UnionDeclaration *isUnionDeclaration() { return NULL; }
-    virtual InterfaceDeclaration *isInterfaceDeclaration() { return NULL; }
-    virtual ScopeDsymbol *isScopeDsymbol() { return NULL; }
-    virtual WithScopeSymbol *isWithScopeSymbol() { return NULL; }
-    virtual ArrayScopeSymbol *isArrayScopeSymbol() { return NULL; }
-    virtual Import *isImport() { return NULL; }
-    virtual EnumDeclaration *isEnumDeclaration() { return NULL; }
-#ifdef _DH
-    virtual DeleteDeclaration *isDeleteDeclaration() { return NULL; }
-#endif
-    virtual StaticStructInitDeclaration *isStaticStructInitDeclaration() { return NULL; }
-    virtual AttribDeclaration *isAttribDeclaration() { return NULL; }
-    virtual OverloadSet *isOverloadSet() { return NULL; }
-    virtual TypeInfoDeclaration* isTypeInfoDeclaration() { return NULL; }
-    virtual ClassInfoDeclaration* isClassInfoDeclaration() { return NULL; }
-
-    // llvm stuff
-    int llvmInternal;
-
-    IrDsymbol ir;
-};
-
-// Dsymbol that generates a scope
-
-struct ScopeDsymbol : Dsymbol
-{
-    Array *members;		// all Dsymbol's in this scope
-    DsymbolTable *symtab;	// members[] sorted into table
-
-    Array *imports;		// imported ScopeDsymbol's
-    unsigned char *prots;	// array of PROT, one for each import
-
-    ScopeDsymbol();
-    ScopeDsymbol(Identifier *id);
-    Dsymbol *syntaxCopy(Dsymbol *s);
-    Dsymbol *search(Loc loc, Identifier *ident, int flags);
-    void importScope(ScopeDsymbol *s, enum PROT protection);
-    int isforwardRef();
-    void defineRef(Dsymbol *s);
-    static void multiplyDefined(Loc loc, Dsymbol *s1, Dsymbol *s2);
-    Dsymbol *nameCollision(Dsymbol *s);
-    const char *kind();
-    FuncDeclaration *findGetMembers();
-
-    void emitMemberComments(Scope *sc);
-
-    static size_t dim(Array *members);
-    static Dsymbol *getNth(Array *members, size_t nth, size_t *pn = NULL);
-
-    ScopeDsymbol *isScopeDsymbol() { return this; }
-};
-
-// With statement scope
-
-struct WithScopeSymbol : ScopeDsymbol
-{
-    WithStatement *withstate;
-
-    WithScopeSymbol(WithStatement *withstate);
-    Dsymbol *search(Loc loc, Identifier *ident, int flags);
-
-    WithScopeSymbol *isWithScopeSymbol() { return this; }
-};
-
-// Array Index/Slice scope
-
-struct ArrayScopeSymbol : ScopeDsymbol
-{
-    Expression *exp;	// IndexExp or SliceExp
-    TypeTuple *type;	// for tuple[length]
-    TupleDeclaration *td;	// for tuples of objects
-    Scope *sc;
-
-    ArrayScopeSymbol(Scope *sc, Expression *e);
-    ArrayScopeSymbol(Scope *sc, TypeTuple *t);
-    ArrayScopeSymbol(Scope *sc, TupleDeclaration *td);
-    Dsymbol *search(Loc loc, Identifier *ident, int flags);
-
-    ArrayScopeSymbol *isArrayScopeSymbol() { return this; }
-};
-
-// Overload Sets
-
-struct OverloadSet : Dsymbol
-{
-    Dsymbols a;		// array of Dsymbols
-
-    OverloadSet();
-    void push(Dsymbol *s);
-    OverloadSet *isOverloadSet() { return this; }
-    const char *kind();
-};
-
-// Table of Dsymbol's
-
-struct DsymbolTable : Object
-{
-    StringTable *tab;
-
-    DsymbolTable();
-    ~DsymbolTable();
-
-    // Look up Identifier. Return Dsymbol if found, NULL if not.
-    Dsymbol *lookup(Identifier *ident);
-
-    // Insert Dsymbol in table. Return NULL if already there.
-    Dsymbol *insert(Dsymbol *s);
-
-    // Look for Dsymbol in table. If there, return it. If not, insert s and return that.
-    Dsymbol *update(Dsymbol *s);
-    Dsymbol *insert(Identifier *ident, Dsymbol *s);	// when ident and s are not the same
-};
-
-#endif /* DMD_DSYMBOL_H */
+
+// Compiler implementation of the D programming language
+// Copyright (c) 1999-2008 by Digital Mars
+// All Rights Reserved
+// written by Walter Bright
+// http://www.digitalmars.com
+// License for redistribution is by either the Artistic License
+// in artistic.txt, or the GNU General Public License in gnu.txt.
+// See the included readme.txt for details.
+
+#ifndef DMD_DSYMBOL_H
+#define DMD_DSYMBOL_H
+
+#ifdef __DMC__
+#pragma once
+#endif /* __DMC__ */
+
+#include "root.h"
+#include "stringtable.h"
+
+#include "mars.h"
+#include "arraytypes.h"
+
+#if IN_LLVM
+#include "../ir/irdsymbol.h"
+#endif
+
+struct Identifier;
+struct Scope;
+struct DsymbolTable;
+struct Declaration;
+struct ThisDeclaration;
+struct TupleDeclaration;
+struct TypedefDeclaration;
+struct AliasDeclaration;
+struct AggregateDeclaration;
+struct EnumDeclaration;
+struct ClassDeclaration;
+struct InterfaceDeclaration;
+struct StructDeclaration;
+struct UnionDeclaration;
+struct FuncDeclaration;
+struct FuncAliasDeclaration;
+struct FuncLiteralDeclaration;
+struct CtorDeclaration;
+struct PostBlitDeclaration;
+struct DtorDeclaration;
+struct StaticCtorDeclaration;
+struct StaticDtorDeclaration;
+struct InvariantDeclaration;
+struct UnitTestDeclaration;
+struct NewDeclaration;
+struct VarDeclaration;
+struct AttribDeclaration;
+#if IN_DMD
+struct Symbol;
+#endif
+struct Package;
+struct Module;
+struct Import;
+struct Type;
+struct TypeTuple;
+struct WithStatement;
+struct LabelDsymbol;
+struct TemplateDeclaration;
+struct TemplateInstance;
+struct TemplateMixin;
+struct EnumMember;
+struct ScopeDsymbol;
+struct WithScopeSymbol;
+struct ArrayScopeSymbol;
+struct StaticStructInitDeclaration;
+struct Expression;
+struct DeleteDeclaration;
+struct HdrGenState;
+struct OverloadSet;
+#if IN_LLVM
+struct TypeInfoDeclaration;
+struct ClassInfoDeclaration;
+#endif
+
+#if IN_DMD
+struct Symbol;
+#endif
+
+#if IN_GCC
+union tree_node;
+typedef union tree_node TYPE;
+#else
+struct TYPE;
+#endif
+
+#if IN_LLVM
+class Ir;
+class IrSymbol;
+namespace llvm
+{
+    class Value;
+}
+#endif
+#if IN_DMD
+// Back end
+struct Classsym;
+#endif
+
+enum PROT
+{
+    PROTundefined,
+    PROTnone,		// no access
+    PROTprivate,
+    PROTpackage,
+    PROTprotected,
+    PROTpublic,
+    PROTexport,
+};
+
+
+struct Dsymbol : Object
+{
+    Identifier *ident;
+    Identifier *c_ident;
+    Dsymbol *parent;
+#if IN_DMD
+    Symbol *csym;		// symbol for code generator
+    Symbol *isym;		// import version of csym
+#endif
+    unsigned char *comment;	// documentation comment for this Dsymbol
+    Loc loc;			// where defined
+
+    Dsymbol();
+    Dsymbol(Identifier *);
+    char *toChars();
+    char *toPrettyChars();
+    char *locToChars();
+    int equals(Object *o);
+    int isAnonymous();
+    void error(Loc loc, const char *format, ...) IS_PRINTF(3);
+    void error(const char *format, ...) IS_PRINTF(2);
+    void checkDeprecated(Loc loc, Scope *sc);
+    Module *getModule();        // module where declared
+    Module *getCompilationModule(); // possibly different for templates
+    Dsymbol *pastMixin();
+    Dsymbol *toParent();
+    Dsymbol *toParent2();
+    TemplateInstance *inTemplateInstance();
+
+    int dyncast() { return DYNCAST_DSYMBOL; }	// kludge for template.isSymbol()
+
+    static Array *arraySyntaxCopy(Array *a);
+
+    virtual const char *kind();
+    virtual Dsymbol *toAlias();			// resolve real symbol
+    virtual int addMember(Scope *sc, ScopeDsymbol *s, int memnum);
+    virtual void semantic(Scope *sc);
+    virtual void semantic2(Scope *sc);
+    virtual void semantic3(Scope *sc);
+    virtual void inlineScan();
+    virtual Dsymbol *search(Loc loc, Identifier *ident, int flags);
+    Dsymbol *searchX(Loc loc, Scope *sc, Identifier *id);
+    virtual int overloadInsert(Dsymbol *s);
+#ifdef _DH
+    char *toHChars();
+    virtual void toHBuffer(OutBuffer *buf, HdrGenState *hgs);
+#endif
+    virtual void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+    virtual void toDocBuffer(OutBuffer *buf);
+    virtual unsigned size(Loc loc);
+    virtual int isforwardRef();
+    virtual void defineRef(Dsymbol *s);
+    virtual AggregateDeclaration *isThis();	// is a 'this' required to access the member
+    virtual ClassDeclaration *isClassMember();	// are we a member of a class?
+    virtual int isExport();			// is Dsymbol exported?
+    virtual int isImportedSymbol();		// is Dsymbol imported?
+    virtual int isDeprecated();			// is Dsymbol deprecated?
+    virtual int isOverloadable();
+    virtual LabelDsymbol *isLabel();		// is this a LabelDsymbol?
+    virtual AggregateDeclaration *isMember();	// is this symbol a member of an AggregateDeclaration?
+    virtual Type *getType();			// is this a type?
+    virtual char *mangle();
+    virtual int needThis();			// need a 'this' pointer?
+    virtual enum PROT prot();
+    virtual Dsymbol *syntaxCopy(Dsymbol *s);	// copy only syntax trees
+    virtual int oneMember(Dsymbol **ps);
+    static int oneMembers(Array *members, Dsymbol **ps);
+    virtual int hasPointers();
+    virtual void addLocalClass(ClassDeclarations *) { }
+    virtual void checkCtorConstInit() { }
+
+    virtual void addComment(unsigned char *comment);
+    virtual void emitComment(Scope *sc);
+    void emitDitto(Scope *sc);
+
+#if IN_DMD
+    // Backend
+
+    virtual Symbol *toSymbol();			// to backend symbol
+    virtual void toObjFile(int multiobj);			// compile to .obj file
+    virtual int cvMember(unsigned char *p);	// emit cv debug info for member
+
+    Symbol *toImport();				// to backend import symbol
+    static Symbol *toImport(Symbol *s);		// to backend import symbol
+
+    Symbol *toSymbolX(const char *prefix, int sclass, TYPE *t, const char *suffix);	// helper
+#endif
+
+    // Eliminate need for dynamic_cast
+    virtual Package *isPackage() { return NULL; }
+    virtual Module *isModule() { return NULL; }
+    virtual EnumMember *isEnumMember() { return NULL; }
+    virtual TemplateDeclaration *isTemplateDeclaration() { return NULL; }
+    virtual TemplateInstance *isTemplateInstance() { return NULL; }
+    virtual TemplateMixin *isTemplateMixin() { return NULL; }
+    virtual Declaration *isDeclaration() { return NULL; }
+    virtual ThisDeclaration *isThisDeclaration() { return NULL; }
+    virtual TupleDeclaration *isTupleDeclaration() { return NULL; }
+    virtual TypedefDeclaration *isTypedefDeclaration() { return NULL; }
+    virtual AliasDeclaration *isAliasDeclaration() { return NULL; }
+    virtual AggregateDeclaration *isAggregateDeclaration() { return NULL; }
+    virtual FuncDeclaration *isFuncDeclaration() { return NULL; }
+    virtual FuncAliasDeclaration *isFuncAliasDeclaration() { return NULL; }
+    virtual FuncLiteralDeclaration *isFuncLiteralDeclaration() { return NULL; }
+    virtual CtorDeclaration *isCtorDeclaration() { return NULL; }
+    virtual PostBlitDeclaration *isPostBlitDeclaration() { return NULL; }
+    virtual DtorDeclaration *isDtorDeclaration() { return NULL; }
+    virtual StaticCtorDeclaration *isStaticCtorDeclaration() { return NULL; }
+    virtual StaticDtorDeclaration *isStaticDtorDeclaration() { return NULL; }
+    virtual InvariantDeclaration *isInvariantDeclaration() { return NULL; }
+    virtual UnitTestDeclaration *isUnitTestDeclaration() { return NULL; }
+    virtual NewDeclaration *isNewDeclaration() { return NULL; }
+    virtual VarDeclaration *isVarDeclaration() { return NULL; }
+    virtual ClassDeclaration *isClassDeclaration() { return NULL; }
+    virtual StructDeclaration *isStructDeclaration() { return NULL; }
+    virtual UnionDeclaration *isUnionDeclaration() { return NULL; }
+    virtual InterfaceDeclaration *isInterfaceDeclaration() { return NULL; }
+    virtual ScopeDsymbol *isScopeDsymbol() { return NULL; }
+    virtual WithScopeSymbol *isWithScopeSymbol() { return NULL; }
+    virtual ArrayScopeSymbol *isArrayScopeSymbol() { return NULL; }
+    virtual Import *isImport() { return NULL; }
+    virtual EnumDeclaration *isEnumDeclaration() { return NULL; }
+#ifdef _DH
+    virtual DeleteDeclaration *isDeleteDeclaration() { return NULL; }
+#endif
+    virtual StaticStructInitDeclaration *isStaticStructInitDeclaration() { return NULL; }
+    virtual AttribDeclaration *isAttribDeclaration() { return NULL; }
+    virtual OverloadSet *isOverloadSet() { return NULL; }
+    virtual TypeInfoDeclaration* isTypeInfoDeclaration() { return NULL; }
+    virtual ClassInfoDeclaration* isClassInfoDeclaration() { return NULL; }
+
+#if IN_LLVM
+    /// Codegen traversal
+    virtual void codegen(Ir* ir);
+
+    // llvm stuff
+    int llvmInternal;
+
+    IrDsymbol ir;
+    IrSymbol* irsym;
+#endif
+};
+
+// Dsymbol that generates a scope
+
+struct ScopeDsymbol : Dsymbol
+{
+    Array *members;		// all Dsymbol's in this scope
+    DsymbolTable *symtab;	// members[] sorted into table
+
+    Array *imports;		// imported ScopeDsymbol's
+    unsigned char *prots;	// array of PROT, one for each import
+
+    ScopeDsymbol();
+    ScopeDsymbol(Identifier *id);
+    Dsymbol *syntaxCopy(Dsymbol *s);
+    Dsymbol *search(Loc loc, Identifier *ident, int flags);
+    void importScope(ScopeDsymbol *s, enum PROT protection);
+    int isforwardRef();
+    void defineRef(Dsymbol *s);
+    static void multiplyDefined(Loc loc, Dsymbol *s1, Dsymbol *s2);
+    Dsymbol *nameCollision(Dsymbol *s);
+    const char *kind();
+    FuncDeclaration *findGetMembers();
+
+    void emitMemberComments(Scope *sc);
+
+    static size_t dim(Array *members);
+    static Dsymbol *getNth(Array *members, size_t nth, size_t *pn = NULL);
+
+    ScopeDsymbol *isScopeDsymbol() { return this; }
+};
+
+// With statement scope
+
+struct WithScopeSymbol : ScopeDsymbol
+{
+    WithStatement *withstate;
+
+    WithScopeSymbol(WithStatement *withstate);
+    Dsymbol *search(Loc loc, Identifier *ident, int flags);
+
+    WithScopeSymbol *isWithScopeSymbol() { return this; }
+};
+
+// Array Index/Slice scope
+
+struct ArrayScopeSymbol : ScopeDsymbol
+{
+    Expression *exp;	// IndexExp or SliceExp
+    TypeTuple *type;	// for tuple[length]
+    TupleDeclaration *td;	// for tuples of objects
+    Scope *sc;
+
+    ArrayScopeSymbol(Scope *sc, Expression *e);
+    ArrayScopeSymbol(Scope *sc, TypeTuple *t);
+    ArrayScopeSymbol(Scope *sc, TupleDeclaration *td);
+    Dsymbol *search(Loc loc, Identifier *ident, int flags);
+
+    ArrayScopeSymbol *isArrayScopeSymbol() { return this; }
+};
+
+// Overload Sets
+
+struct OverloadSet : Dsymbol
+{
+    Dsymbols a;		// array of Dsymbols
+
+    OverloadSet();
+    void push(Dsymbol *s);
+    OverloadSet *isOverloadSet() { return this; }
+    const char *kind();
+};
+
+// Table of Dsymbol's
+
+struct DsymbolTable : Object
+{
+    StringTable *tab;
+
+    DsymbolTable();
+    ~DsymbolTable();
+
+    // Look up Identifier. Return Dsymbol if found, NULL if not.
+    Dsymbol *lookup(Identifier *ident);
+
+    // Insert Dsymbol in table. Return NULL if already there.
+    Dsymbol *insert(Dsymbol *s);
+
+    // Look for Dsymbol in table. If there, return it. If not, insert s and return that.
+    Dsymbol *update(Dsymbol *s);
+    Dsymbol *insert(Identifier *ident, Dsymbol *s);	// when ident and s are not the same
+};
+
+#endif /* DMD_DSYMBOL_H */
--- a/dmd2/dump.c	Mon Jun 01 01:28:18 2009 +0200
+++ b/dmd2/dump.c	Mon Jun 01 19:02:20 2009 +0100
@@ -52,7 +52,7 @@
 void IntegerExp::dump(int i)
 {
     indent(i);
-    printf("%p %lld type=%s\n", this, (intmax_t)value, type_print(type));
+    printf("%p %jd type=%s\n", this, (intmax_t)value, type_print(type));
 }
 
 void IdentifierExp::dump(int i)
--- a/dmd2/e2ir.c.nolink	Mon Jun 01 01:28:18 2009 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,4679 +0,0 @@
-
-// 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	<string.h>
-#include	<time.h>
-#include	<complex.h>
-
-#include	"lexer.h"
-#include	"expression.h"
-#include	"mtype.h"
-#include	"dsymbol.h"
-#include	"declaration.h"
-#include	"enum.h"
-#include	"aggregate.h"
-#include	"attrib.h"
-#include	"module.h"
-#include	"init.h"
-#include	"template.h"
-
-#if _WIN32
-#include	"..\tk\mem.h"	// for mem_malloc
-#elif linux
-#include	"../tk/mem.h"	// for mem_malloc
-#endif
-
-#include	"cc.h"
-#include	"el.h"
-#include	"oper.h"
-#include	"global.h"
-#include	"code.h"
-#include	"type.h"
-#include	"dt.h"
-#include	"irstate.h"
-#include	"id.h"
-#include	"type.h"
-#include	"toir.h"
-
-static char __file__[] = __FILE__;	/* for tassert.h		*/
-#include	"tassert.h"
-
-
-elem *addressElem(elem *e, Type *t);
-elem *array_toPtr(Type *t, elem *e);
-elem *bit_assign(enum OPER op, elem *eb, elem *ei, elem *ev, int result);
-elem *bit_read(elem *eb, elem *ei, int result);
-elem *exp2_copytotemp(elem *e);
-
-#define el_setLoc(e,loc)	((e)->Esrcpos.Sfilename = (loc).filename, \
-				 (e)->Esrcpos.Slinnum = (loc).linnum)
-
-/************************************
- * Call a function.
- */
-
-elem *callfunc(Loc loc,
-	IRState *irs,
-	int directcall,		// 1: don't do virtual call
-	Type *tret,		// return type
-	elem *ec,		// evaluates to function address
-	Type *ectype,		// original type of ec
-	FuncDeclaration *fd,	// if !=NULL, this is the function being called
-	Type *t,		// TypeDelegate or TypeFunction for this function
-	elem *ehidden,		// if !=NULL, this is the 'hidden' argument
-	Array *arguments)
-{
-    elem *ep;
-    elem *e;
-    elem *ethis = NULL;
-    elem *eside = NULL;
-    int i;
-    tym_t ty;
-    tym_t tyret;
-    enum RET retmethod;
-    int reverse;
-    TypeFunction *tf;
-    int op;
-
-#if 0
-    printf("callfunc(directcall = %d, tret = '%s', ec = %p, fd = %p)\n",
-	directcall, tret->toChars(), ec, fd);
-    printf("ec: "); elem_print(ec);
-    if (fd)
-	printf("fd = '%s'\n", fd->toChars());
-#endif
-
-    t = t->toBasetype();
-    if (t->ty == Tdelegate)
-    {
-	// A delegate consists of:
-	//	{ Object *this; Function *funcptr; }
-	assert(!fd);
-	assert(t->nextOf()->ty == Tfunction);
-	tf = (TypeFunction *)(t->nextOf());
-	ethis = ec;
-	ec = el_same(&ethis);
-	ethis = el_una(OP64_32, TYnptr, ethis);	// get this
-	ec = array_toPtr(t, ec);		// get funcptr
-	ec = el_una(OPind, tf->totym(), ec);
-    }
-    else
-    {	assert(t->ty == Tfunction);
-	tf = (TypeFunction *)(t);
-    }
-    retmethod = tf->retStyle();
-    ty = ec->Ety;
-    if (fd)
-	ty = fd->toSymbol()->Stype->Tty;
-    reverse = tyrevfunc(ty);
-    ep = NULL;
-    if (arguments)
-    {
-	// j=1 if _arguments[] is first argument
-	int j = (tf->linkage == LINKd && tf->varargs == 1);
-
-	for (i = 0; i < arguments->dim ; i++)
-	{   Expression *arg;
-	    elem *ea;
-
-	    arg = (Expression *)arguments->data[i];
-	    //printf("\targ[%d]: %s\n", i, arg->toChars());
-
-	    size_t nparams = Argument::dim(tf->parameters);
-	    if (i - j < nparams && i >= j)
-	    {
-		Argument *p = Argument::getNth(tf->parameters, i - j);
-
-		if (p->storageClass & (STCout | STCref))
-		{
-		    // Convert argument to a pointer,
-		    // use AddrExp::toElem()
-		    Expression *ae = arg->addressOf(NULL);
-		    ea = ae->toElem(irs);
-		    goto L1;
-		}
-	    }
-	    ea = arg->toElem(irs);
-	L1:
-	    if (ea->Ety == TYstruct)
-	    {
-		ea = el_una(OPstrpar, TYstruct, ea);
-		ea->Enumbytes = ea->E1->Enumbytes;
-		assert(ea->Enumbytes);
-	    }
-	    if (reverse)
-		ep = el_param(ep,ea);
-	    else
-		ep = el_param(ea,ep);
-	}
-    }
-
-    if (retmethod == RETstack)
-    {
-	if (!ehidden)
-	{   // Don't have one, so create one
-	    type *t;
-
-	    if (tf->next->toBasetype()->ty == Tstruct)
-		t = tf->next->toCtype();
-	    else
-		t = type_fake(tf->next->totym());
-	    Symbol *stmp = symbol_genauto(t);
-	    ehidden = el_ptr(stmp);
-	}
-	if (ep)
-	{
-#if 0 // BUG: implement
-	    if (reverse && type_mangle(tfunc) == mTYman_cpp)
-		ep = el_param(ehidden,ep);
-	    else
-#endif
-		ep = el_param(ep,ehidden);
-	}
-	else
-	    ep = ehidden;
-	ehidden = NULL;
-    }
-    assert(ehidden == NULL);
-
-    if (fd && fd->isMember2())
-    {
-	InterfaceDeclaration *intd;
-	Symbol *sfunc;
-	AggregateDeclaration *ad;
-
-	ad = fd->isThis();
-	if (ad)
-	{
-	    ethis = ec;
-	    if (ad->handle->ty == Tpointer && tybasic(ec->Ety) != TYnptr)
-	    {
-		ethis = addressElem(ec, ectype);
-	    }
-	}
-	else
-	{
-	    // Evaluate ec for side effects
-	    eside = ec;
-	}
-	sfunc = fd->toSymbol();
-
-	if (!fd->isVirtual() ||
-	    directcall ||		// BUG: fix
-	    fd->isFinal()
-	   )
-	{
-	    // make static call
-	    ec = el_var(sfunc);
-	}
-	else
-	{
-	    // make virtual call
-	    elem *ev;
-	    unsigned vindex;
-
-	    assert(ethis);
-	    ev = el_same(&ethis);
-	    ev = el_una(OPind, TYnptr, ev);
-	    vindex = fd->vtblIndex;
-
-	    // Build *(ev + vindex * 4)
-	    ec = el_bin(OPadd,TYnptr,ev,el_long(TYint, vindex * 4));
-	    ec = el_una(OPind,TYnptr,ec);
-	    ec = el_una(OPind,tybasic(sfunc->Stype->Tty),ec);
-	}
-    }
-    else if (fd && fd->isNested())
-    {
-	assert(!ethis);
-	ethis = getEthis(0, irs, fd);
-
-    }
-
-    ep = el_param(ep, ethis);
-
-    tyret = tret->totym();
-
-    // Look for intrinsic functions
-    if (ec->Eoper == OPvar && (op = intrinsic_op(ec->EV.sp.Vsym->Sident)) != -1)
-    {
-	el_free(ec);
-	if (OTbinary(op))
-	{
-	    ep->Eoper = op;
-	    ep->Ety = tyret;
-	    e = ep;
-	    if (op == OPscale)
-	    {	elem *et;
-
-		et = e->E1;
-		e->E1 = el_una(OPs32_d, TYdouble, e->E2);
-		e->E1 = el_una(OPd_ld, TYldouble, e->E1);
-		e->E2 = et;
-		e->Ety = tyret;
-	    }
-	}
-	else
-	    e = el_una(op,tyret,ep);
-    }
-    else if (ep)
-	e = el_bin(OPcall,tyret,ec,ep);
-    else
-	e = el_una(OPucall,tyret,ec);
-
-    if (retmethod == RETstack)
-    {
-	e->Ety = TYnptr;
-	e = el_una(OPind, tyret, e);
-    }
-
-#if DMDV2
-    if (tf->isref)
-    {
-	e->Ety = TYnptr;
-	e = el_una(OPind, tyret, e);
-    }
-#endif
-
-    if (tybasic(tyret) == TYstruct)
-    {
-	e->Enumbytes = tret->size();
-    }
-    e = el_combine(eside, e);
-    return e;
-}
-
-/*******************************************
- * Take address of an elem.
- */
-
-elem *addressElem(elem *e, Type *t)
-{
-    elem **pe;
-
-    //printf("addressElem()\n");
-
-    for (pe = &e; (*pe)->Eoper == OPcomma; pe = &(*pe)->E2)
-	;
-    if ((*pe)->Eoper != OPvar && (*pe)->Eoper != OPind)
-    {	Symbol *stmp;
-	elem *eeq;
-	elem *e = *pe;
-	type *tx;
-
-	// Convert to ((tmp=e),tmp)
-	TY ty;
-	if (t && ((ty = t->toBasetype()->ty) == Tstruct || ty == Tsarray))
-	    tx = t->toCtype();
-	else
-	    tx = type_fake(e->Ety);
-	stmp = symbol_genauto(tx);
-	eeq = el_bin(OPeq,e->Ety,el_var(stmp),e);
-	if (e->Ety == TYstruct)
-	{
-	    eeq->Eoper = OPstreq;
-	    eeq->Enumbytes = e->Enumbytes;
-	}
-	else if (e->Ety == TYarray)
-	{
-	    eeq->Eoper = OPstreq;
-	    eeq->Ejty = eeq->Ety = TYstruct;
-	    eeq->Enumbytes = t->size();
-	}
-	*pe = el_bin(OPcomma,e->Ety,eeq,el_var(stmp));
-    }
-    e = el_una(OPaddr,TYnptr,e);
-    return e;
-}
-
-/*****************************************
- * Convert array to a pointer to the data.
- */
-
-elem *array_toPtr(Type *t, elem *e)
-{
-    //printf("array_toPtr()\n");
-    //elem_print(e);
-    t = t->toBasetype();
-    switch (t->ty)
-    {
-	case Tpointer:
-	    break;
-
-	case Tarray:
-	case Tdelegate:
-	    if (e->Eoper == OPcomma)
-	    {
-		e->Ety = TYnptr;
-		e->E2 = array_toPtr(t, e->E2);
-	    }
-	    else if (e->Eoper == OPpair)
-	    {
-		e->Eoper = OPcomma;
-		e->Ety = TYnptr;
-	    }
-	    else
-	    {
-#if 1
-		e = el_una(OPmsw, TYnptr, e);
-#else
-		e = el_una(OPaddr, TYnptr, e);
-		e = el_bin(OPadd, TYnptr, e, el_long(TYint, 4));
-		e = el_una(OPind, TYnptr, e);
-#endif
-	    }
-	    break;
-
-	case Tsarray:
-	    e = el_una(OPaddr, TYnptr, e);
-	    break;
-
-	default:
-	    t->print();
-	    assert(0);
-    }
-    return e;
-}
-
-/*****************************************
- * Convert array to a dynamic array.
- */
-
-elem *array_toDarray(Type *t, elem *e)
-{
-    unsigned dim;
-    elem *ef = NULL;
-    elem *ex;
-
-    //printf("array_toDarray(t = %s)\n", t->toChars());
-    //elem_print(e);
-    t = t->toBasetype();
-    switch (t->ty)
-    {
-	case Tarray:
-	    break;
-
-	case Tsarray:
-	    e = el_una(OPaddr, TYnptr, e);
-	    dim = ((TypeSArray *)t)->dim->toInteger();
-	    e = el_pair(TYullong, el_long(TYint, dim), e);
-	    break;
-
-	default:
-	L1:
-	    switch (e->Eoper)
-	    {
-		case OPconst:
-		{
-		    size_t len = tysize[tybasic(e->Ety)];
-		    elem *es = el_calloc();
-		    es->Eoper = OPstring;
-
-		    // Match MEM_PH_FREE for OPstring in ztc\el.c
-		    es->EV.ss.Vstring = (char *)mem_malloc(len);
-		    memcpy(es->EV.ss.Vstring, &e->EV, len);
-
-		    es->EV.ss.Vstrlen = len;
-		    es->Ety = TYnptr;
-		    e = es;
-		    break;
-		}
-
-		case OPvar:
-		    e = el_una(OPaddr, TYnptr, e);
-		    break;
-
-		case OPcomma:
-		    ef = el_combine(ef, e->E1);
-		    ex = e;
-		    e = e->E2;
-		    ex->E1 = NULL;
-		    ex->E2 = NULL;
-		    el_free(ex);
-		    goto L1;
-
-		case OPind:
-		    ex = e;
-		    e = e->E1;
-		    ex->E1 = NULL;
-		    ex->E2 = NULL;
-		    el_free(ex);
-		    break;
-
-		default:
-		{
-		    // Copy expression to a variable and take the
-		    // address of that variable.
-		    Symbol *stmp;
-		    tym_t ty = tybasic(e->Ety);
-
-		    if (ty == TYstruct)
-		    {
-			if (e->Enumbytes == 4)
-			    ty = TYint;
-			else if (e->Enumbytes == 8)
-			    ty = TYllong;
-		    }
-		    e->Ety = ty;
-		    stmp = symbol_genauto(type_fake(ty));
-		    e = el_bin(OPeq, e->Ety, el_var(stmp), e);
-		    e = el_bin(OPcomma, TYnptr, e, el_una(OPaddr, TYnptr, el_var(stmp)));
-		    break;
-		}
-	    }
-	    dim = 1;
-	    e = el_pair(TYullong, el_long(TYint, dim), e);
-	    break;
-    }
-    return el_combine(ef, e);
-}
-
-/*****************************************
- * Evaluate elem and convert to dynamic array.
- */
-
-elem *eval_Darray(IRState *irs, Expression *e)
-{
-    elem *ex;
-
-    ex = e->toElem(irs);
-    return array_toDarray(e->type, ex);
-}
-
-/************************************
- */
-
-elem *sarray_toDarray(Loc loc, Type *tfrom, Type *tto, elem *e)
-{
-    //printf("sarray_toDarray()\n");
-    //elem_print(e);
-
-    elem *elen;
-    unsigned dim = ((TypeSArray *)tfrom)->dim->toInteger();
-
-    if (tto)
-    {
-	unsigned fsize = tfrom->nextOf()->size();
-	unsigned tsize = tto->nextOf()->size();
-
-	if ((dim * fsize) % tsize != 0)
-	{
-	  Lerr:
-	    error(loc, "cannot cast %s to %s since sizes don't line up", tfrom->toChars(), tto->toChars());
-	}
-	dim = (dim * fsize) / tsize;
-    }
-  L1:
-    elen = el_long(TYint, dim);
-    e = el_una(OPaddr, TYnptr, e);
-    e = el_pair(TYullong, elen, e);
-    return e;
-}
-
-/*******************************************
- * Set an array pointed to by eptr to evalue:
- *	eptr[0..edim] = evalue;
- * Input:
- *	eptr	where to write the data to
- *	evalue	value to write
- *	edim	number of times to write evalue to eptr[]
- *	tb	type of evalue
- */
-
-elem *setArray(elem *eptr, elem *edim, Type *tb, elem *evalue, IRState *irs, int op)
-{   int r;
-    elem *e;
-    int sz = tb->size();
-
-    if (tb->ty == Tfloat80 || tb->ty == Timaginary80)
-	r = RTLSYM_MEMSET80;
-    else if (tb->ty == Tcomplex80)
-	r = RTLSYM_MEMSET160;
-    else if (tb->ty == Tcomplex64)
-	r = RTLSYM_MEMSET128;
-    else
-    {
-	switch (sz)
-	{
-	    case 1:	 r = RTLSYM_MEMSET8;	break;
-	    case 2:	 r = RTLSYM_MEMSET16;	break;
-	    case 4:	 r = RTLSYM_MEMSET32;	break;
-	    case 8:	 r = RTLSYM_MEMSET64;	break;
-	    default:	 r = RTLSYM_MEMSETN;	break;
-	}
-
-	/* Determine if we need to do postblit
-	 */
-	if (op != TOKblit)
-	{
-	    Type *t = tb;
-	    while (t->ty == Tsarray)
-		t = t->nextOf()->toBasetype();
-	    if (t->ty == Tstruct)
-	    {   StructDeclaration *sd = ((TypeStruct *)t)->sym;
-		if (sd->postblit)
-		{   /* Need to do postblit.
-		     *   void *_d_arraysetassign(void *p, void *value, int dim, TypeInfo ti);
-		     */
-		    r = (op == TOKconstruct) ? RTLSYM_ARRAYSETCTOR : RTLSYM_ARRAYSETASSIGN;
-		    evalue = el_una(OPaddr, TYnptr, evalue);
-		    Expression *ti = tb->getTypeInfo(NULL);
-		    elem *eti = ti->toElem(irs);
-		    e = el_params(eti, edim, evalue, eptr, NULL);
-		    e = el_bin(OPcall,TYnptr,el_var(rtlsym[r]),e);
-		    return e;
-		}
-	    }
-	}
-
-	if (r == RTLSYM_MEMSETN)
-	{
-	    // void *_memsetn(void *p, void *value, int dim, int sizelem)
-	    evalue = el_una(OPaddr, TYnptr, evalue);
-	    elem *esz = el_long(TYint, sz);
-	    e = el_params(esz, edim, evalue, eptr, NULL);
-	    e = el_bin(OPcall,TYnptr,el_var(rtlsym[r]),e);
-	    return e;
-	}
-    }
-    if (sz > 1 && sz <= 8 &&
-	evalue->Eoper == OPconst && el_allbits(evalue, 0))
-    {
-	r = RTLSYM_MEMSET8;
-	edim = el_bin(OPmul, TYuint, edim, el_long(TYuint, sz));
-    }
-
-    if (evalue->Ety == TYstruct)
-    {
-	evalue = el_una(OPstrpar, TYstruct, evalue);
-	evalue->Enumbytes = evalue->E1->Enumbytes;
-	assert(evalue->Enumbytes);
-    }
-
-    // Be careful about parameter side effect ordering
-    if (r == RTLSYM_MEMSET8)
-    {
-	e = el_param(edim, evalue);
-	e = el_bin(OPmemset,TYnptr,eptr,e);
-    }
-    else
-    {
-	e = el_params(edim, evalue, eptr, NULL);
-	e = el_bin(OPcall,TYnptr,el_var(rtlsym[r]),e);
-    }
-    return e;
-}
-
-/***************************************
- */
-
-elem *Expression::toElem(IRState *irs)
-{
-    print();
-    assert(0);
-    return NULL;
-}
-
-/************************************
- */
-
-elem *SymbolExp::toElem(IRState *irs)
-{   Symbol *s;
-    elem *e;
-    tym_t tym;
-    Type *tb = (op == TOKsymoff) ? var->type->toBasetype() : type->toBasetype();
-    int offset = (op == TOKsymoff) ? ((SymOffExp*)this)->offset : 0;
-    FuncDeclaration *fd;
-    VarDeclaration *v = var->isVarDeclaration();
-
-    //printf("SymbolExp::toElem('%s') %p\n", toChars(), this);
-    //printf("\tparent = '%s'\n", var->parent ? var->parent->toChars() : "null");
-    if (op == TOKvar && var->needThis())
-    {
-	error("need 'this' to access member %s", toChars());
-	return el_long(TYint, 0);
-    }
-    s = var->toSymbol();
-    fd = NULL;
-    if (var->toParent2())
-	fd = var->toParent2()->isFuncDeclaration();
-
-    int nrvo = 0;
-    if (fd && fd->nrvo_can && fd->nrvo_var == var)
-    {
-	s = fd->shidden;
-	nrvo = 1;
-    }
-
-    if (s->Sclass == SCauto || s->Sclass == SCparameter)
-    {
-	if (fd && fd != irs->getFunc())
-	{   // 'var' is a variable in an enclosing function.
-	    elem *ethis;
-	    int soffset;
-
-	    ethis = getEthis(loc, irs, fd);
-	    ethis = el_una(OPaddr, TYnptr, ethis);
-
-	    if (v && v->offset)
-		soffset = v->offset;
-	    else
-	    {
-		soffset = s->Soffset;
-		/* If fd is a non-static member function of a class or struct,
-		 * then ethis isn't the frame pointer.
-		 * ethis is the 'this' pointer to the class/struct instance.
-		 * We must offset it.
-		 */
-		if (fd->vthis)
-		{
-		    soffset -= fd->vthis->toSymbol()->Soffset;
-		}
-		//printf("\tSoffset = x%x, sthis->Soffset = x%x\n", s->Soffset, irs->sthis->Soffset);
-	    }
-
-	    if (!nrvo)
-		soffset += offset;
-
-	    e = el_bin(OPadd, TYnptr, ethis, el_long(TYnptr, soffset));
-	    if (op == TOKvar)
-		e = el_una(OPind, TYnptr, e);
-	    if ((var->isParameter() && tb->ty == Tsarray) || var->isOut() || var->isRef())
-		e = el_una(OPind, s->ty(), e);
-	    else if (op == TOKsymoff && nrvo)
-            {   e = el_una(OPind, TYnptr, e);
-                e = el_bin(OPadd, e->Ety, e, el_long(TYint, offset));
-            }
-	    goto L1;
-	}
-    }
-
-    /* If var is a member of a closure
-     */
-    if (v && v->offset)
-    {	assert(irs->sclosure);
-	e = el_var(irs->sclosure);
-	e = el_bin(OPadd, TYnptr, e, el_long(TYint, v->offset));
-	if (op == TOKvar)
-	{   e = el_una(OPind, type->totym(), e);
-	    if (tybasic(e->Ety) == TYstruct)
-		e->Enumbytes = type->size();
-	    el_setLoc(e, loc);
-	}
-	if ((var->isParameter() && tb->ty == Tsarray) || var->isOut() || var->isRef())
-	{   e->Ety = TYnptr;
-	    e = el_una(OPind, s->ty(), e);
-	}
-	else if (op == TOKsymoff && nrvo)
-	{   e = el_una(OPind, TYnptr, e);
-	    e = el_bin(OPadd, e->Ety, e, el_long(TYint, offset));
-	}
-	else if (op == TOKsymoff)
-	{
-	    e = el_bin(OPadd, e->Ety, e, el_long(TYint, offset));
-	}
-	goto L1;
-    }
-
-    if (s->Sclass == SCauto && s->Ssymnum == -1)
-    {
-	//printf("\tadding symbol\n");
-	symbol_add(s);
-    }
-
-    if (var->isImportedSymbol())
-    {
-	assert(op == TOKvar);
-	e = el_var(var->toImport());
-	e = el_una(OPind,s->ty(),e);
-    }
-    else if ((var->isParameter() && tb->ty == Tsarray) || var->isOut() || var->isRef())
-    {	// Static arrays are really passed as pointers to the array
-	// Out parameters are really references
-	e = el_var(s);
-	e->Ety = TYnptr;
-	if (op == TOKvar)
-	    e = el_una(OPind, s->ty(), e);
-	else if (offset)
-            e = el_bin(OPadd, TYnptr, e, el_long(TYint, offset));
-    }
-    else if (op == TOKvar)
-	e = el_var(s);
-    else
-    {   e = nrvo ? el_var(s) : el_ptr(s);
-        e = el_bin(OPadd, e->Ety, e, el_long(TYint, offset));
-    }
-L1:
-    if (op == TOKvar)
-    {
-	if (nrvo)
-	{
-	    e->Ety = TYnptr;
-	    e = el_una(OPind, 0, e);
-	}
-	if (tb->ty == Tfunction)
-	{
-	    tym = s->Stype->Tty;
-	}
-	else
-	    tym = type->totym();
-	e->Ejty = e->Ety = tym;
-	if (tybasic(tym) == TYstruct)
-	{
-	    e->Enumbytes = type->size();
-	}
-	else if (tybasic(tym) == TYarray)
-	{
-	    e->Ejty = e->Ety = TYstruct;
-	    e->Enumbytes = type->size();
-	}
-    }
-    el_setLoc(e,loc);
-    return e;
-}
-
-#if 0
-elem *VarExp::toElem(IRState *irs)
-{   Symbol *s;
-    elem *e;
-    tym_t tym;
-    Type *tb = type->toBasetype();
-    FuncDeclaration *fd;
-    VarDeclaration *v = var->isVarDeclaration();
-
-    //printf("VarExp::toElem('%s') %p\n", toChars(), this);
-    //printf("\tparent = '%s'\n", var->parent ? var->parent->toChars() : "null");
-    if (var->needThis())
-    {
-	error("need 'this' to access member %s", toChars());
-	return el_long(TYint, 0);
-    }
-    s = var->toSymbol();
-    fd = NULL;
-    if (var->toParent2())
-	fd = var->toParent2()->isFuncDeclaration();
-
-    int nrvo = 0;
-    if (fd && fd->nrvo_can && fd->nrvo_var == var)
-    {
-	s = fd->shidden;
-	nrvo = 1;
-    }
-
-    if (s->Sclass == SCauto || s->Sclass == SCparameter)
-    {
-	if (fd && fd != irs->getFunc())
-	{   // 'var' is a variable in an enclosing function.
-	    elem *ethis;
-	    int soffset;
-
-	    ethis = getEthis(loc, irs, fd);
-	    ethis = el_una(OPaddr, TYnptr, ethis);
-
-	    if (v && v->offset)
-		soffset = v->offset;
-	    else
-	    {
-		soffset = s->Soffset;
-		/* If fd is a non-static member function of a class or struct,
-		 * then ethis isn't the frame pointer.
-		 * ethis is the 'this' pointer to the class/struct instance.
-		 * We must offset it.
-		 */
-		if (fd->vthis)
-		{
-		    soffset -= fd->vthis->toSymbol()->Soffset;
-		}
-		//printf("\tSoffset = x%x, sthis->Soffset = x%x\n", s->Soffset, irs->sthis->Soffset);
-	    }
-
-	    ethis = el_bin(OPadd, TYnptr, ethis, el_long(TYnptr, soffset));
-	    e = el_una(OPind, 0, ethis);
-	    if ((var->isParameter() && tb->ty == Tsarray) || var->isOut() || var->isRef())
-		goto L2;
-	    goto L1;
-	}
-    }
-
-    /* If var is a member of a closure
-     */
-    if (v && v->offset)
-    {	assert(irs->sclosure);
-	e = el_var(irs->sclosure);
-	e = el_bin(OPadd, TYnptr, e, el_long(TYint, v->offset));
-	e = el_una(OPind, type->totym(), e);
-	if (tybasic(e->Ety) == TYstruct)
-	    e->Enumbytes = type->size();
-	el_setLoc(e, loc);
-
-	if ((var->isParameter() && tb->ty == Tsarray) || var->isOut() || var->isRef())
-	    goto L2;
-	goto L1;
-    }
-
-    if (s->Sclass == SCauto && s->Ssymnum == -1)
-    {
-	//printf("\tadding symbol\n");
-	symbol_add(s);
-    }
-
-    if (var->isImportedSymbol())
-    {
-	e = el_var(var->toImport());
-	e = el_una(OPind,s->ty(),e);
-    }
-    else if ((var->isParameter() && tb->ty == Tsarray) || var->isOut() || var->isRef())
-    {	// Static arrays are really passed as pointers to the array
-	// Out parameters are really references
-	e = el_var(s);
-L2:
-	e->Ety = TYnptr;
-	e = el_una(OPind, s->ty(), e);
-    }
-    else
-	e = el_var(s);
-L1:
-    if (nrvo)
-    {
-	e->Ety = TYnptr;
-	e = el_una(OPind, 0, e);
-    }
-    if (tb->ty == Tfunction)
-    {
-	tym = s->Stype->Tty;
-    }
-    else
-	tym = type->totym();
-    e->Ejty = e->Ety = tym;
-    if (tybasic(tym) == TYstruct)
-    {
-	e->Enumbytes = type->size();
-    }
-    else if (tybasic(tym) == TYarray)
-    {
-	e->Ejty = e->Ety = TYstruct;
-	e->Enumbytes = type->size();
-    }
-    el_setLoc(e,loc);
-    return e;
-}
-#endif
-
-#if 0
-elem *SymOffExp::toElem(IRState *irs)
-{   Symbol *s;
-    elem *e;
-    Type *tb = var->type->toBasetype();
-    VarDeclaration *v = var->isVarDeclaration();
-    FuncDeclaration *fd = NULL;
-    if (var->toParent2())
-	fd = var->toParent2()->isFuncDeclaration();
-
-    //printf("SymOffExp::toElem(): %s\n", toChars());
-    s = var->toSymbol();
-
-    int nrvo = 0;
-    if (fd && fd->nrvo_can && fd->nrvo_var == var)
-    { 	s = fd->shidden;
-	nrvo = 1;
-    }
-
-    if (s->Sclass == SCauto && s->Ssymnum == -1)
-	symbol_add(s);
-    assert(!var->isImportedSymbol());
-
-    // This code closely parallels that in VarExp::toElem()
-    if (s->Sclass == SCauto || s->Sclass == SCparameter)
-    {
-	if (fd && fd != irs->getFunc())
-	{   // 'var' is a variable in an enclosing function.
-	    elem *ethis;
-	    int soffset;
-
-	    ethis = getEthis(loc, irs, fd);
-	    ethis = el_una(OPaddr, TYnptr, ethis);
-
-	    if (v && v->offset)
-		soffset = v->offset;
-	    else
-	    {
-		soffset = s->Soffset;
-		/* If fd is a non-static member function of a class or struct,
-		 * then ethis isn't the frame pointer.
-		 * ethis is the 'this' pointer to the class/struct instance.
-		 * We must offset it.
-		 */
-		if (fd->vthis)
-		{
-		    soffset -= fd->vthis->toSymbol()->Soffset;
-		}
-		//printf("\tSoffset = x%x, sthis->Soffset = x%x\n", s->Soffset, irs->sthis->Soffset);
-	    }
-
-	    if (!nrvo)
-		soffset += offset;
-	    e = el_bin(OPadd, TYnptr, ethis, el_long(TYnptr, soffset));
-	    if ((var->isParameter() && tb->ty == Tsarray) || var->isOut() || var->isRef())
-		e = el_una(OPind, s->ty(), e);
-	    else if (nrvo)
-	    {	e = el_una(OPind, TYnptr, e);
-		e = el_bin(OPadd, e->Ety, e, el_long(TYint, offset));
-	    }
-	    goto L1;
-	}
-    }
-
-    /* If var is a member of a closure
-     */
-    if (v && v->offset)
-    {	assert(irs->sclosure);
-	e = el_var(irs->sclosure);
-	e = el_bin(OPadd, TYnptr, e, el_long(TYint, v->offset));
-	if ((var->isParameter() && tb->ty == Tsarray) || var->isOut() || var->isRef())
-	    e = el_una(OPind, s->ty(), e);
-	else if (nrvo)
-	{   e = el_una(OPind, TYnptr, e);
-	    e = el_bin(OPadd, e->Ety, e, el_long(TYint, offset));
-	}
-	goto L1;
-    }
-
-    if ((var->isParameter() && tb->ty == Tsarray) || var->isOut() || var->isRef())
-    {   // Static arrays are really passed as pointers to the array
-        // Out parameters are really references
-        e = el_var(s);
-        e->Ety = TYnptr;
-	if (offset)
-	    e = el_bin(OPadd, TYnptr, e, el_long(TYint, offset));
-    }
-    else
-    {	e = nrvo ? el_var(s) : el_ptr(s);
-	e = el_bin(OPadd, e->Ety, e, el_long(TYint, offset));
-    }
-
-L1:
-    el_setLoc(e,loc);
-    return e;
-}
-#endif
-
-/**************************************
- */
-
-elem *FuncExp::toElem(IRState *irs)
-{
-    elem *e;
-    Symbol *s;
-
-    //printf("FuncExp::toElem() %s\n", toChars());
-    s = fd->toSymbol();
-    e = el_ptr(s);
-    if (fd->isNested())
-    {
-	elem *ethis = getEthis(loc, irs, fd);
-	e = el_pair(TYullong, ethis, e);
-    }
-
-    irs->deferToObj->push(fd);
-    el_setLoc(e,loc);
-    return e;
-}
-
-/**************************************
- */
-
-elem *Dsymbol_toElem(Dsymbol *s, IRState *irs)
-{
-    elem *e = NULL;
-    Symbol *sp;
-    AttribDeclaration *ad;
-    VarDeclaration *vd;
-    ClassDeclaration *cd;
-    StructDeclaration *sd;
-    FuncDeclaration *fd;
-    TemplateMixin *tm;
-    TupleDeclaration *td;
-    TypedefDeclaration *tyd;
-
-    //printf("Dsymbol_toElem() %s\n", s->toChars());
-    ad = s->isAttribDeclaration();
-    if (ad)
-    {
-	Array *decl = ad->include(NULL, NULL);
-	if (decl && decl->dim)
-	{
-	    for (size_t i = 0; i < decl->dim; i++)
-	    {
-		s = (Dsymbol *)decl->data[i];
-		e = el_combine(e, Dsymbol_toElem(s, irs));
-	    }
-	}
-    }
-    else if ((vd = s->isVarDeclaration()) != NULL)
-    {
-	s = s->toAlias();
-	if (s != vd)
-	    return Dsymbol_toElem(s, irs);
-	if (vd->isStatic() || vd->storage_class & STCextern)
-	    vd->toObjFile(0);
-	else
-	{
-	    sp = s->toSymbol();
-	    symbol_add(sp);
-	    //printf("\tadding symbol '%s'\n", sp->Sident);
-	    if (vd->init)
-	    {
-		ExpInitializer *ie;
-
-		ie = vd->init->isExpInitializer();
-		if (ie)
-		    e = ie->exp->toElem(irs);
-	    }
-	}
-    }
-    else if ((cd = s->isClassDeclaration()) != NULL)
-    {
-	irs->deferToObj->push(s);
-    }
-    else if ((sd = s->isStructDeclaration()) != NULL)
-    {
-	irs->deferToObj->push(sd);
-    }
-    else if ((fd = s->isFuncDeclaration()) != NULL)
-    {
-	//printf("function %s\n", fd->toChars());
-	irs->deferToObj->push(fd);
-    }
-    else if ((tm = s->isTemplateMixin()) != NULL)
-    {
-	//printf("%s\n", tm->toChars());
-	if (tm->members)
-	{
-	    for (size_t i = 0; i < tm->members->dim; i++)
-	    {
-		Dsymbol *sm = (Dsymbol *)tm->members->data[i];
-		e = el_combine(e, Dsymbol_toElem(sm, irs));
-	    }
-	}
-    }
-    else if ((td = s->isTupleDeclaration()) != NULL)
-    {
-	for (size_t i = 0; i < td->objects->dim; i++)
-	{   Object *o = (Object *)td->objects->data[i];
-	    if (o->dyncast() == DYNCAST_EXPRESSION)
-	    {	Expression *eo = (Expression *)o;
-		if (eo->op == TOKdsymbol)
-		{   DsymbolExp *se = (DsymbolExp *)eo;
-		    e = el_combine(e, Dsymbol_toElem(se->s, irs));
-		}
-	    }
-	}
-    }
-    else if ((tyd = s->isTypedefDeclaration()) != NULL)
-    {
-	irs->deferToObj->push(tyd);
-    }
-    return e;
-}
-
-elem *DeclarationExp::toElem(IRState *irs)
-{   elem *e;
-
-    //printf("DeclarationExp::toElem() %s\n", toChars());
-    e = Dsymbol_toElem(declaration, irs);
-    return e;
-}
-
-/***************************************
- */
-
-elem *ThisExp::toElem(IRState *irs)
-{   elem *ethis;
-    FuncDeclaration *fd;
-
-    //printf("ThisExp::toElem()\n");
-    assert(irs->sthis);
-
-    if (var)
-    {
-	assert(var->parent);
-	fd = var->toParent2()->isFuncDeclaration();
-	assert(fd);
-	ethis = getEthis(loc, irs, fd);
-    }
-    else
-	ethis = el_var(irs->sthis);
-
-    el_setLoc(ethis,loc);
-    return ethis;
-}
-
-/***************************************
- */
-
-elem *IntegerExp::toElem(IRState *irs)
-{   elem *e;
-
-    e = el_long(type->totym(), value);
-    el_setLoc(e,loc);
-    return e;
-}
-
-/***************************************
- */
-
-elem *RealExp::toElem(IRState *irs)
-{   union eve c;
-    tym_t ty;
-
-    //printf("RealExp::toElem(%p)\n", this);
-    memset(&c, 0, sizeof(c));
-    ty = type->toBasetype()->totym();
-    switch (ty)
-    {
-	case TYfloat:
-	case TYifloat:
-	    c.Vfloat = value;
-	    break;
-
-	case TYdouble:
-	case TYidouble:
-	    c.Vdouble = value;
-	    break;
-
-	case TYldouble:
-	case TYildouble:
-	    c.Vldouble = value;
-	    break;
-
-	default:
-	    print();
-	    type->print();
-	    type->toBasetype()->print();
-	    printf("ty = %d, tym = %x\n", type->ty, ty);
-	    assert(0);
-    }
-    return el_const(ty, &c);
-}
-
-
-/***************************************
- */
-
-elem *ComplexExp::toElem(IRState *irs)
-{   union eve c;
-    tym_t ty;
-    real_t re;
-    real_t im;
-
-    re = creall(value);
-    im = cimagl(value);
-
-    memset(&c, 0, sizeof(c));
-    ty = type->totym();
-    switch (ty)
-    {
-	case TYcfloat:
-	    c.Vcfloat.re = (float) re;
-	    c.Vcfloat.im = (float) im;
-	    break;
-
-	case TYcdouble:
-	    c.Vcdouble.re = (double) re;
-	    c.Vcdouble.im = (double) im;
-	    break;
-
-	case TYcldouble:
-	    c.Vcldouble.re = re;
-	    c.Vcldouble.im = im;
-	    break;
-
-	default:
-	    assert(0);
-    }
-    return el_const(ty, &c);
-}
-
-/***************************************
- */
-
-elem *NullExp::toElem(IRState *irs)
-{
-    return el_long(type->totym(), 0);
-}
-
-/***************************************
- */
-
-struct StringTab
-{
-    Module *m;		// module we're generating code for
-    Symbol *si;
-    void *string;
-    size_t sz;
-    size_t len;
-};
-
-#define STSIZE 16
-StringTab stringTab[STSIZE];
-size_t stidx;
-
-static Symbol *assertexp_sfilename = NULL;
-static char *assertexp_name = NULL;
-static Module *assertexp_mn = NULL;
-
-void clearStringTab()
-{
-    //printf("clearStringTab()\n");
-    memset(stringTab, 0, sizeof(stringTab));
-    stidx = 0;
-
-    assertexp_sfilename = NULL;
-    assertexp_name = NULL;
-    assertexp_mn = NULL;
-}
-
-elem *StringExp::toElem(IRState *irs)
-{
-    elem *e;
-    Type *tb= type->toBasetype();
-
-
-#if 0
-    printf("StringExp::toElem() %s, type = %s\n", toChars(), type->toChars());
-#endif
-
-    if (tb->ty == Tarray)
-    {
-	Symbol *si;
-	dt_t *dt;
-	StringTab *st;
-
-#if 0
-	printf("irs->m = %p\n", irs->m);
-	printf(" m   = %s\n", irs->m->toChars());
-	printf(" len = %d\n", len);
-	printf(" sz  = %d\n", sz);
-#endif
-	for (size_t i = 0; i < STSIZE; i++)
-	{
-	    st = &stringTab[(stidx + i) % STSIZE];
-	    //if (!st->m) continue;
-	    //printf(" st.m   = %s\n", st->m->toChars());
-	    //printf(" st.len = %d\n", st->len);
-	    //printf(" st.sz  = %d\n", st->sz);
-	    if (st->m == irs->m &&
-		st->si &&
-		st->len == len &&
-		st->sz == sz &&
-		memcmp(st->string, string, sz * len) == 0)
-	    {
-		//printf("use cached value\n");
-		si = st->si;	// use cached value
-		goto L1;
-	    }
-	}
-
-	stidx = (stidx + 1) % STSIZE;
-	st = &stringTab[stidx];
-
-	dt = NULL;
-	toDt(&dt);
-
-	si = symbol_generate(SCstatic,type_fake(TYdarray));
-	si->Sdt = dt;
-	si->Sfl = FLdata;
-#if ELFOBJ // Burton
-	si->Sseg = CDATA;
-#endif
-	outdata(si);
-
-	st->m = irs->m;
-	st->si = si;
-	st->string = string;
-	st->len = len;
-	st->sz = sz;
-    L1:
-	e = el_var(si);
-    }
-    else if (tb->ty == Tsarray)
-    {
-	Symbol *si;
-	dt_t *dt = NULL;
-
-	toDt(&dt);
-	dtnzeros(&dt, sz);		// leave terminating 0
-
-	si = symbol_generate(SCstatic,type_allocn(TYarray, tschar));
-	si->Sdt = dt;
-	si->Sfl = FLdata;
-
-#if ELFOBJ // Burton
-	si->Sseg = CDATA;
-#endif
-	outdata(si);
-
-	e = el_var(si);
-    }
-    else if (tb->ty == Tpointer)
-    {
-	e = el_calloc();
-	e->Eoper = OPstring;
-#if 1
-	// Match MEM_PH_FREE for OPstring in ztc\el.c
-	e->EV.ss.Vstring = (char *)mem_malloc((len + 1) * sz);
-	memcpy(e->EV.ss.Vstring, string, (len + 1) * sz);
-#else
-	e->EV.ss.Vstring = (char *)string;
-#endif
-	e->EV.ss.Vstrlen = (len + 1) * sz;
-	e->Ety = TYnptr;
-    }
-    else
-    {
-	printf("type is %s\n", type->toChars());
-	assert(0);
-    }
-    el_setLoc(e,loc);
-    return e;
-}
-
-elem *NewExp::toElem(IRState *irs)
-{   elem *e;
-    Type *t;
-    Type *ectype;
-
-    //printf("NewExp::toElem() %s\n", toChars());
-    t = type->toBasetype();
-    //printf("\ttype = %s\n", t->toChars());
-    //if (member)
-	//printf("\tmember = %s\n", member->toChars());
-    if (t->ty == Tclass)
-    {
-	Symbol *csym;
-
-	t = newtype->toBasetype();
-	assert(t->ty == Tclass);
-	TypeClass *tclass = (TypeClass *)(t);
-	ClassDeclaration *cd = tclass->sym;
-
-	/* Things to do:
-	 * 1) ex: call allocator
-	 * 2) ey: set vthis for nested classes
-	 * 3) ez: call constructor
-	 */
-
-	elem *ex = NULL;
-	elem *ey = NULL;
-	elem *ez = NULL;
-
-	if (allocator || onstack)
-	{   elem *ei;
-	    Symbol *si;
-
-	    if (onstack)
-	    {
-		/* Create an instance of the class on the stack,
-		 * and call it stmp.
-		 * Set ex to be the &stmp.
-		 */
-		Symbol *s = symbol_calloc(tclass->sym->toChars());
-		s->Sclass = SCstruct;
-		s->Sstruct = struct_calloc();
-		s->Sstruct->Sflags |= 0;
-		s->Sstruct->Salignsize = tclass->sym->alignsize;
-		s->Sstruct->Sstructalign = tclass->sym->structalign;
-		s->Sstruct->Sstructsize = tclass->sym->structsize;
-
-		::type *tc = type_alloc(TYstruct);
-		tc->Ttag = (Classsym *)s;                // structure tag name
-		tc->Tcount++;
-		s->Stype = tc;
-
-		Symbol *stmp = symbol_genauto(tc);
-		ex = el_ptr(stmp);
-	    }
-	    else
-	    {
-		ex = el_var(allocator->toSymbol());
-		ex = callfunc(loc, irs, 1, type, ex, allocator->type,
-			allocator, allocator->type, NULL, newargs);
-	    }
-
-	    si = tclass->sym->toInitializer();
-	    ei = el_var(si);
-
-	    if (cd->isNested())
-	    {
-		ey = el_same(&ex);
-		ez = el_copytree(ey);
-	    }
-	    else if (member)
-		ez = el_same(&ex);
-
-	    ex = el_una(OPind, TYstruct, ex);
-	    ex = el_bin(OPstreq, TYnptr, ex, ei);
-	    ex->Enumbytes = cd->size(loc);
-	    ex = el_una(OPaddr, TYnptr, ex);
-	    ectype = tclass;
-	}
-	else
-	{
-	    csym = cd->toSymbol();
-	    ex = el_bin(OPcall,TYnptr,el_var(rtlsym[RTLSYM_NEWCLASS]),el_ptr(csym));
-	    ectype = NULL;
-
-	    if (cd->isNested())
-	    {
-		ey = el_same(&ex);
-		ez = el_copytree(ey);
-	    }
-	    else if (member)
-		ez = el_same(&ex);
-//elem_print(ex);
-//elem_print(ey);
-//elem_print(ez);
-	}
-
-	if (thisexp)
-	{   ClassDeclaration *cdthis = thisexp->type->isClassHandle();
-	    assert(cdthis);
-	    //printf("cd = %s\n", cd->toChars());
-	    //printf("cdthis = %s\n", cdthis->toChars());
-	    assert(cd->isNested());
-	    int offset = 0;
-	    Dsymbol *cdp = cd->toParent2();	// class we're nested in
-	    elem *ethis;
-
-//printf("member = %p\n", member);
-//printf("cdp = %s\n", cdp->toChars());
-//printf("cdthis = %s\n", cdthis->toChars());
-	    if (cdp != cdthis)
-	    {	int i = cdp->isClassDeclaration()->isBaseOf(cdthis, &offset);
-		assert(i);
-	    }
-	    ethis = thisexp->toElem(irs);
-	    if (offset)
-		ethis = el_bin(OPadd, TYnptr, ethis, el_long(TYint, offset));
-
-	    ey = el_bin(OPadd, TYnptr, ey, el_long(TYint, cd->vthis->offset));
-	    ey = el_una(OPind, TYnptr, ey);
-	    ey = el_bin(OPeq, TYnptr, ey, ethis);
-
-//printf("ex: "); elem_print(ex);
-//printf("ey: "); elem_print(ey);
-//printf("ez: "); elem_print(ez);
-	}
-	else if (cd->isNested())
-	{   /* Initialize cd->vthis:
-	     *	*(ey + cd.vthis.offset) = this;
-	     */
-	    elem *ethis;
-	    FuncDeclaration *thisfd = irs->getFunc();
-	    int offset = 0;
-	    Dsymbol *cdp = cd->toParent2();	// class/func we're nested in
-
-	    if (cdp == thisfd)
-	    {	/* Class we're new'ing is a local class in this function:
-		 *	void thisfd() { class cd { } }
-		 */
-		if (irs->sclosure)
-		    ethis = el_var(irs->sclosure);
-		else if (irs->sthis)
-		{
-#if DMDV2
-		    if (thisfd->closureVars.dim)
-#else
-		    if (thisfd->nestedFrameRef)
-#endif
-			ethis = el_ptr(irs->sthis);
-		    else
-			ethis = el_var(irs->sthis);
-		}
-		else
-		{
-		    ethis = el_long(TYnptr, 0);
-#if DMDV2
-		    if (thisfd->closureVars.dim)
-#else
-		    if (thisfd->nestedFrameRef)
-#endif
-			ethis->Eoper = OPframeptr;
-		}
-	    }
-	    else if (thisfd->vthis &&
-		  (cdp == thisfd->toParent2() ||
-		   (cdp->isClassDeclaration() &&
-		    cdp->isClassDeclaration()->isBaseOf(thisfd->toParent2()->isClassDeclaration(), &offset)
-		   )
-		  )
-		)
-	    {	/* Class we're new'ing is at the same level as thisfd
-		 */
-		assert(offset == 0);	// BUG: should handle this case
-		ethis = el_var(irs->sthis);
-	    }
-	    else
-	    {
-		ethis = getEthis(loc, irs, cd->toParent2());
-		ethis = el_una(OPaddr, TYnptr, ethis);
-	    }
-
-	    ey = el_bin(OPadd, TYnptr, ey, el_long(TYint, cd->vthis->offset));
-	    ey = el_una(OPind, TYnptr, ey);
-	    ey = el_bin(OPeq, TYnptr, ey, ethis);
-
-	}
-
-	if (member)
-	    // Call constructor
-	    ez = callfunc(loc, irs, 1, type, ez, ectype, member, member->type, NULL, arguments);
-
-	e = el_combine(ex, ey);
-	e = el_combine(e, ez);
-    }
-    else if (t->ty == Tpointer && t->nextOf()->toBasetype()->ty == Tstruct)
-    {
-	Symbol *csym;
-
-	t = newtype->toBasetype();
-	assert(t->ty == Tstruct);
-	TypeStruct *tclass = (TypeStruct *)(t);
-	StructDeclaration *cd = tclass->sym;
-
-	/* Things to do:
-	 * 1) ex: call allocator
-	 * 2) ey: set vthis for nested classes
-	 * 3) ez: call constructor
-	 */
-
-	elem *ex = NULL;
-	elem *ey = NULL;
-	elem *ez = NULL;
-
-	if (allocator)
-	{   elem *ei;
-	    Symbol *si;
-
-	    ex = el_var(allocator->toSymbol());
-	    ex = callfunc(loc, irs, 1, type, ex, allocator->type,
-			allocator, allocator->type, NULL, newargs);
-
-	    si = tclass->sym->toInitializer();
-	    ei = el_var(si);
-
-	    if (member)
-		ez = el_same(&ex);
-	    else
-	    {	/* Statically intialize with default initializer
-		 */
-		ex = el_una(OPind, TYstruct, ex);
-		ex = el_bin(OPstreq, TYnptr, ex, ei);
-		ex->Enumbytes = cd->size(loc);
-		ex = el_una(OPaddr, TYnptr, ex);
-	    }
-	    ectype = tclass;
-	}
-	else
-	{
-	    d_uns64 elemsize = cd->size(loc);
-
-	    // call _d_newarrayT(ti, 1)
-	    e = el_long(TYsize_t, 1);
-	    e = el_param(e, type->getTypeInfo(NULL)->toElem(irs));
-
-	    int rtl = t->isZeroInit() ? RTLSYM_NEWARRAYT : RTLSYM_NEWARRAYIT;
-	    e = el_bin(OPcall,TYdarray,el_var(rtlsym[rtl]),e);
-
-	    // The new functions return an array, so convert to a pointer
-	    // ex -> (unsigned)(e >> 32)
-	    e = el_bin(OPshr, TYdarray, e, el_long(TYint, 32));
-	    ex = el_una(OP64_32, TYnptr, e);
-
-	    ectype = NULL;
-
-	    if (member)
-		ez = el_same(&ex);
-//elem_print(ex);
-//elem_print(ey);
-//elem_print(ez);
-	}
-
-	if (member)
-	    // Call constructor
-	    ez = callfunc(loc, irs, 1, type, ez, ectype, member, member->type, NULL, arguments);
-
-	e = el_combine(ex, ey);
-	e = el_combine(e, ez);
-    }
-    else if (t->ty == Tarray)
-    {
-	TypeDArray *tda = (TypeDArray *)(t);
-
-	assert(arguments && arguments->dim >= 1);
-	if (arguments->dim == 1)
-	{   // Single dimension array allocations
-	    Expression *arg = (Expression *)arguments->data[0];	// gives array length
-	    e = arg->toElem(irs);
-	    d_uns64 elemsize = tda->next->size();
-
-	    // call _d_newT(ti, arg)
-	    e = el_param(e, type->getTypeInfo(NULL)->toElem(irs));
-	    int rtl = tda->next->isZeroInit() ? RTLSYM_NEWARRAYT : RTLSYM_NEWARRAYIT;
-	    e = el_bin(OPcall,TYdarray,el_var(rtlsym[rtl]),e);
-	}
-	else
-	{   // Multidimensional array allocations
-	    e = el_long(TYint, arguments->dim);
-	    for (size_t i = 0; i < arguments->dim; i++)
-	    {
-		Expression *arg = (Expression *)arguments->data[i];	// gives array length
-		e = el_param(arg->toElem(irs), e);
-		assert(t->ty == Tarray);
-		t = t->nextOf();
-		assert(t);
-	    }
-
-	    e = el_param(e, type->getTypeInfo(NULL)->toElem(irs));
-
-	    int rtl = t->isZeroInit() ? RTLSYM_NEWARRAYMT : RTLSYM_NEWARRAYMIT;
-	    e = el_bin(OPcall,TYdarray,el_var(rtlsym[rtl]),e);
-	}
-    }
-    else if (t->ty == Tpointer)
-    {
-	TypePointer *tp = (TypePointer *)t;
-	d_uns64 elemsize = tp->next->size();
-	Expression *di = tp->next->defaultInit();
-	d_uns64 disize = di->type->size();
-
-	// call _d_newarrayT(ti, 1)
-	e = el_long(TYsize_t, 1);
-	e = el_param(e, type->getTypeInfo(NULL)->toElem(irs));
-
-	int rtl = tp->next->isZeroInit() ? RTLSYM_NEWARRAYT : RTLSYM_NEWARRAYIT;
-	e = el_bin(OPcall,TYdarray,el_var(rtlsym[rtl]),e);
-
-	// The new functions return an array, so convert to a pointer
-	// e -> (unsigned)(e >> 32)
-	e = el_bin(OPshr, TYdarray, e, el_long(TYint, 32));
-	e = el_una(OP64_32, t->totym(), e);
-    }
-    else
-    {
-	assert(0);
-    }
-
-    el_setLoc(e,loc);
-    return e;
-}
-
-//////////////////////////// Unary ///////////////////////////////
-
-/***************************************
- */
-
-elem *NegExp::toElem(IRState *irs)
-{
-    elem *e = el_una(OPneg, type->totym(), e1->toElem(irs));
-    el_setLoc(e,loc);
-    return e;
-}
-
-/***************************************
- */
-
-elem *ComExp::toElem(IRState *irs)
-{   elem *e;
-
-    elem *e1 = this->e1->toElem(irs);
-    tym_t ty = type->totym();
-    if (this->e1->type->toBasetype()->ty == Tbool)
-	e = el_bin(OPxor, ty, e1, el_long(ty, 1));
-    else
-	e = el_una(OPcom,ty,e1);
-    el_setLoc(e,loc);
-    return e;
-}
-
-/***************************************
- */
-
-elem *NotExp::toElem(IRState *irs)
-{
-    elem *e = el_una(OPnot, type->totym(), e1->toElem(irs));
-    el_setLoc(e,loc);
-    return e;
-}
-
-
-/***************************************
- */
-
-elem *HaltExp::toElem(IRState *irs)
-{   elem *e;
-
-    e = el_calloc();
-    e->Ety = TYvoid;
-    e->Eoper = OPhalt;
-    el_setLoc(e,loc);
-    return e;
-}
-
-/********************************************
- */
-
-elem *AssertExp::toElem(IRState *irs)
-{   elem *e;
-    elem *ea;
-    Type *t1 = e1->type->toBasetype();
-
-    //printf("AssertExp::toElem() %s\n", toChars());
-    if (global.params.useAssert)
-    {
-	e = e1->toElem(irs);
-
-	InvariantDeclaration *inv = (InvariantDeclaration *)(void *)1;
-
-	// If e1 is a class object, call the class invariant on it
-	if (global.params.useInvariants && t1->ty == Tclass &&
-	    !((TypeClass *)t1)->sym->isInterfaceDeclaration())
-	{
-#if TARGET_LINUX
-	    e = el_bin(OPcall, TYvoid, el_var(rtlsym[RTLSYM__DINVARIANT]), e);
-#else
-	    e = el_bin(OPcall, TYvoid, el_var(rtlsym[RTLSYM_DINVARIANT]), e);
-#endif
-	}
-	// If e1 is a struct object, call the struct invariant on it
-	else if (global.params.useInvariants &&
-	    t1->ty == Tpointer &&
-	    t1->nextOf()->ty == Tstruct &&
-	    (inv = ((TypeStruct *)t1->nextOf())->sym->inv) != NULL)
-	{
-	    e = callfunc(loc, irs, 1, inv->type->nextOf(), e, e1->type, inv, inv->type, NULL, NULL);
-	}
-	else
-	{
-	    // Construct: (e1 || ModuleAssert(line))
-	    Symbol *sassert;
-	    Module *m = irs->blx->module;
-	    char *mname = m->srcfile->toChars();
-
-	    //printf("filename = '%s'\n", loc.filename);
-	    //printf("module = '%s'\n", m->srcfile->toChars());
-
-	    /* If the source file name has changed, probably due
-	     * to a #line directive.
-	     */
-	    if (loc.filename && (msg || strcmp(loc.filename, mname) != 0))
-	    {	elem *efilename;
-
-		/* Cache values.
-		 */
-		//static Symbol *assertexp_sfilename = NULL;
-		//static char *assertexp_name = NULL;
-		//static Module *assertexp_mn = NULL;
-
-		if (!assertexp_sfilename || strcmp(loc.filename, assertexp_name) != 0 || assertexp_mn != m)
-		{
-		    dt_t *dt = NULL;
-		    char *id;
-		    int len;
-
-		    id = loc.filename;
-		    len = strlen(id);
-		    dtdword(&dt, len);
-		    dtabytes(&dt,TYnptr, 0, len + 1, id);
-
-		    assertexp_sfilename = symbol_generate(SCstatic,type_fake(TYdarray));
-		    assertexp_sfilename->Sdt = dt;
-		    assertexp_sfilename->Sfl = FLdata;
-#if ELFOBJ
-		    assertexp_sfilename->Sseg = CDATA;
-#endif
-		    outdata(assertexp_sfilename);
-
-		    assertexp_mn = m;
-		    assertexp_name = id;
-		}
-
-		efilename = el_var(assertexp_sfilename);
-
-		if (msg)
-		{   elem *emsg = msg->toElem(irs);
-		    ea = el_var(rtlsym[RTLSYM_DASSERT_MSG]);
-		    ea = el_bin(OPcall, TYvoid, ea, el_params(el_long(TYint, loc.linnum), efilename, emsg, NULL));
-		}
-		else
-		{
-		    ea = el_var(rtlsym[RTLSYM_DASSERT]);
-		    ea = el_bin(OPcall, TYvoid, ea, el_param(el_long(TYint, loc.linnum), efilename));
-		}
-	    }
-	    else
-	    {
-		sassert = m->toModuleAssert();
-		ea = el_bin(OPcall,TYvoid,el_var(sassert),
-		    el_long(TYint, loc.linnum));
-	    }
-	    e = el_bin(OPoror,TYvoid,e,ea);
-	}
-    }
-    else
-    {	// BUG: should replace assert(0); with a HLT instruction
-	e = el_long(TYint, 0);
-    }
-    el_setLoc(e,loc);
-    return e;
-}
-
-elem *PostExp::toElem(IRState *irs)
-{   elem *e;
-    elem *einc;
-
-    e = e1->toElem(irs);
-    einc = e2->toElem(irs);
-    e = el_bin((op == TOKplusplus) ? OPpostinc : OPpostdec,
-		e->Ety,e,einc);
-    el_setLoc(e,loc);
-    return e;
-}
-
-//////////////////////////// Binary ///////////////////////////////
-
-/********************************************
- */
-
-elem *BinExp::toElemBin(IRState *irs,int op)
-{
-    //printf("toElemBin() '%s'\n", toChars());
-
-    tym_t tym = type->totym();
-
-    elem *el = e1->toElem(irs);
-    elem *er = e2->toElem(irs);
-    elem *e = el_bin(op,tym,el,er);
-    el_setLoc(e,loc);
-    return e;
-}
-
-
-/***************************************
- */
-
-elem *AddExp::toElem(IRState *irs)
-{   elem *e;
-    Type *tb1 = e1->type->toBasetype();
-    Type *tb2 = e2->type->toBasetype();
-
-    if ((tb1->ty == Tarray || tb1->ty == Tsarray) &&
-	(tb2->ty == Tarray || tb2->ty == Tsarray)
-       )
-    {
-	error("Array operation %s not implemented", toChars());
-    }
-    else
-	e = toElemBin(irs,OPadd);
-    return e;
-}
-
-/***************************************
- */
-
-elem *MinExp::toElem(IRState *irs)
-{
-    return toElemBin(irs,OPmin);
-}
-
-/***************************************
- */
-
-elem *CatExp::toElem(IRState *irs)
-{   elem *e;
-
-#if 0
-    printf("CatExp::toElem()\n");
-    print();
-#endif
-
-    Type *tb1 = e1->type->toBasetype();
-    Type *tb2 = e2->type->toBasetype();
-    Type *tn;
-
-#if 0
-    if ((tb1->ty == Tarray || tb1->ty == Tsarray) &&
-	(tb2->ty == Tarray || tb2->ty == Tsarray)
-       )
-#endif
-
-    Type *ta = tb1->nextOf() ? e1->type : e2->type;
-    tn = tb1->nextOf() ? tb1->nextOf() : tb2->nextOf();
-    {
-	if (e1->op == TOKcat)
-	{
-	    elem *ep;
-	    CatExp *ce = this;
-	    int n = 2;
-
-	    ep = eval_Darray(irs, ce->e2);
-	    do
-	    {
-		n++;
-		ce = (CatExp *)ce->e1;
-		ep = el_param(ep, eval_Darray(irs, ce->e2));
-	    } while (ce->e1->op == TOKcat);
-	    ep = el_param(ep, eval_Darray(irs, ce->e1));
-#if 1
-	    ep = el_params(
-			   ep,
-			   el_long(TYint, n),
-			   ta->getTypeInfo(NULL)->toElem(irs),
-			   NULL);
-	    e = el_bin(OPcall, TYdarray, el_var(rtlsym[RTLSYM_ARRAYCATNT]), ep);
-#else
-	    ep = el_params(
-			   ep,
-			   el_long(TYint, n),
-			   el_long(TYint, tn->size()),
-			   NULL);
-	    e = el_bin(OPcall, TYdarray, el_var(rtlsym[RTLSYM_ARRAYCATN]), ep);
-#endif
-	}
-	else
-	{
-	    elem *e1;
-	    elem *e2;
-	    elem *ep;
-
-	    e1 = eval_Darray(irs, this->e1);
-	    e2 = eval_Darray(irs, this->e2);
-#if 1
-	    ep = el_params(e2, e1, ta->getTypeInfo(NULL)->toElem(irs), NULL);
-	    e = el_bin(OPcall, TYdarray, el_var(rtlsym[RTLSYM_ARRAYCATT]), ep);
-#else
-	    ep = el_params(el_long(TYint, tn->size()), e2, e1, NULL);
-	    e = el_bin(OPcall, TYdarray, el_var(rtlsym[RTLSYM_ARRAYCAT]), ep);
-#endif
-	}
-	el_setLoc(e,loc);
-    }
-#if 0
-    else if ((tb1->ty == Tarray || tb1->ty == Tsarray) &&
-	     e2->type->equals(tb1->next))
-    {
-	error("array cat with element not implemented");
-	e = el_long(TYint, 0);
-    }
-    else
-	assert(0);
-#endif
-    return e;
-}
-
-/***************************************
- */
-
-elem *MulExp::toElem(IRState *irs)
-{
-    return toElemBin(irs,OPmul);
-}
-
-/************************************
- */
-
-elem *DivExp::toElem(IRState *irs)
-{
-    return toElemBin(irs,OPdiv);
-}
-
-/***************************************
- */
-
-elem *ModExp::toElem(IRState *irs)
-{
-    elem *e;
-    elem *e1;
-    elem *e2;
-    tym_t tym;
-
-    tym = type->totym();
-
-    e1 = this->e1->toElem(irs);
-    e2 = this->e2->toElem(irs);
-
-#if 0 // Now inlined
-    if (this->e1->type->isfloating())
-    {	elem *ep;
-
-	switch (this->e1->type->ty)
-	{
-	    case Tfloat32:
-	    case Timaginary32:
-		e1 = el_una(OPf_d, TYdouble, e1);
-		e2 = el_una(OPf_d, TYdouble, e2);
-	    case Tfloat64:
-	    case Timaginary64:
-		e1 = el_una(OPd_ld, TYldouble, e1);
-		e2 = el_una(OPd_ld, TYldouble, e2);
-		break;
-	    case Tfloat80:
-	    case Timaginary80:
-		break;
-	    default:
-		assert(0);
-		break;
-	}
-	ep = el_param(e2,e1);
-	e = el_bin(OPcall,tym,el_var(rtlsym[RTLSYM_MODULO]),ep);
-    }
-    else
-#endif
-	e = el_bin(OPmod,tym,e1,e2);
-    el_setLoc(e,loc);
-    return e;
-}
-
-/***************************************
- */
-
-elem *CmpExp::toElem(IRState *irs)
-{
-    elem *e;
-    enum OPER eop;
-    Type *t1 = e1->type->toBasetype();
-    Type *t2 = e2->type->toBasetype();
-
-    switch (op)
-    {
-	case TOKlt:	eop = OPlt;	break;
-	case TOKgt:	eop = OPgt;	break;
-	case TOKle:	eop = OPle;	break;
-	case TOKge:	eop = OPge;	break;
-	case TOKequal:	eop = OPeqeq;	break;
-	case TOKnotequal: eop = OPne;	break;
-
-	// NCEG floating point compares
-	case TOKunord:	eop = OPunord;	break;
-	case TOKlg:	eop = OPlg;	break;
-	case TOKleg:	eop = OPleg;	break;
-	case TOKule:	eop = OPule;	break;
-	case TOKul:	eop = OPul;	break;
-	case TOKuge:	eop = OPuge;	break;
-	case TOKug:	eop = OPug;	break;
-	case TOKue:	eop = OPue;	break;
-	default:
-	    dump(0);
-	    assert(0);
-    }
-    if (!t1->isfloating())
-    {
-	// Convert from floating point compare to equivalent
-	// integral compare
-	eop = (enum OPER)rel_integral(eop);
-    }
-    if ((int)eop > 1 && t1->ty == Tclass && t2->ty == Tclass)
-    {
-#if 1
-	assert(0);
-#else
-	elem *ec1;
-	elem *ec2;
-
-	ec1 = e1->toElem(irs);
-	ec2 = e2->toElem(irs);
-	e = el_bin(OPcall,TYint,el_var(rtlsym[RTLSYM_OBJ_CMP]),el_param(ec1, ec2));
-	e = el_bin(eop, TYint, e, el_long(TYint, 0));
-#endif
-    }
-    else if ((int)eop > 1 &&
-	     (t1->ty == Tarray || t1->ty == Tsarray) &&
-	     (t2->ty == Tarray || t2->ty == Tsarray))
-    {
-	elem *ea1;
-	elem *ea2;
-	elem *ep;
-	Type *telement = t1->nextOf()->toBasetype();
-	int rtlfunc;
-
-	ea1 = e1->toElem(irs);
-	ea1 = array_toDarray(t1, ea1);
-	ea2 = e2->toElem(irs);
-	ea2 = array_toDarray(t2, ea2);
-
-#if 1
-	ep = el_params(telement->arrayOf()->getInternalTypeInfo(NULL)->toElem(irs),
-		ea2, ea1, NULL);
-	rtlfunc = RTLSYM_ARRAYCMP2;
-#else
-	ep = el_params(telement->getInternalTypeInfo(NULL)->toElem(irs), ea2, ea1, NULL);
-	rtlfunc = RTLSYM_ARRAYCMP;
-#endif
-	e = el_bin(OPcall, TYint, el_var(rtlsym[rtlfunc]), ep);
-	e = el_bin(eop, TYint, e, el_long(TYint, 0));
-	el_setLoc(e,loc);
-    }
-    else
-    {
-	if ((int)eop <= 1)
-	{
-	    /* The result is determinate, create:
-	     *   (e1 , e2) , eop
-	     */
-	    e = toElemBin(irs,OPcomma);
-	    e = el_bin(OPcomma,e->Ety,e,el_long(e->Ety,(int)eop));
-	}
-	else
-	    e = toElemBin(irs,eop);
-    }
-    return e;
-}
-
-elem *EqualExp::toElem(IRState *irs)
-{
-    //printf("EqualExp::toElem() %s\n", toChars());
-
-    elem *e;
-    enum OPER eop;
-    Type *t1 = e1->type->toBasetype();
-    Type *t2 = e2->type->toBasetype();
-
-    switch (op)
-    {
-	case TOKequal:		eop = OPeqeq;	break;
-	case TOKnotequal:	eop = OPne;	break;
-	default:
-	    dump(0);
-	    assert(0);
-    }
-
-    //printf("EqualExp::toElem()\n");
-    if (t1->ty == Tstruct)
-    {	// Do bit compare of struct's
-	elem *es1;
-	elem *es2;
-	elem *ecount;
-
-	es1 = e1->toElem(irs);
-	es2 = e2->toElem(irs);
-#if 1
-	es1 = addressElem(es1, t1);
-	es2 = addressElem(es2, t2);
-#else
-	es1 = el_una(OPaddr, TYnptr, es1);
-	es2 = el_una(OPaddr, TYnptr, es2);
-#endif
-	e = el_param(es1, es2);
-	ecount = el_long(TYint, t1->size());
-	e = el_bin(OPmemcmp, TYint, e, ecount);
-	e = el_bin(eop, TYint, e, el_long(TYint, 0));
-	el_setLoc(e,loc);
-    }
-#if 0
-    else if (t1->ty == Tclass && t2->ty == Tclass)
-    {
-	elem *ec1;
-	elem *ec2;
-
-	ec1 = e1->toElem(irs);
-	ec2 = e2->toElem(irs);
-	e = el_bin(OPcall,TYint,el_var(rtlsym[RTLSYM_OBJ_EQ]),el_param(ec1, ec2));
-    }
-#endif
-    else if ((t1->ty == Tarray || t1->ty == Tsarray) &&
-	     (t2->ty == Tarray || t2->ty == Tsarray))
-    {
-	elem *ea1;
-	elem *ea2;
-	elem *ep;
-	Type *telement = t1->nextOf()->toBasetype();
-	int rtlfunc;
-
-	ea1 = e1->toElem(irs);
-	ea1 = array_toDarray(t1, ea1);
-	ea2 = e2->toElem(irs);
-	ea2 = array_toDarray(t2, ea2);
-
-#if 1
-	ep = el_params(telement->arrayOf()->getInternalTypeInfo(NULL)->toElem(irs),
-		ea2, ea1, NULL);
-	rtlfunc = RTLSYM_ARRAYEQ2;
-#else
-	ep = el_params(telement->getInternalTypeInfo(NULL)->toElem(irs), ea2, ea1, NULL);
-	rtlfunc = RTLSYM_ARRAYEQ;
-#endif
-	e = el_bin(OPcall, TYint, el_var(rtlsym[rtlfunc]), ep);
-	if (op == TOKnotequal)
-	    e = el_bin(OPxor, TYint, e, el_long(TYint, 1));
-	el_setLoc(e,loc);
-    }
-    else
-	e = toElemBin(irs, eop);
-    return e;
-}
-
-elem *IdentityExp::toElem(IRState *irs)
-{
-    elem *e;
-    enum OPER eop;
-    Type *t1 = e1->type->toBasetype();
-    Type *t2 = e2->type->toBasetype();
-
-    switch (op)
-    {
-	case TOKidentity:	eop = OPeqeq;	break;
-	case TOKnotidentity:	eop = OPne;	break;
-	default:
-	    dump(0);
-	    assert(0);
-    }
-
-    //printf("IdentityExp::toElem() %s\n", toChars());
-
-    if (t1->ty == Tstruct)
-    {	// Do bit compare of struct's
-	elem *es1;
-	elem *es2;
-	elem *ecount;
-
-	es1 = e1->toElem(irs);
-	es1 = addressElem(es1, e1->type);
-	//es1 = el_una(OPaddr, TYnptr, es1);
-	es2 = e2->toElem(irs);
-	es2 = addressElem(es2, e2->type);
-	//es2 = el_una(OPaddr, TYnptr, es2);
-	e = el_param(es1, es2);
-	ecount = el_long(TYint, t1->size());
-	e = el_bin(OPmemcmp, TYint, e, ecount);
-	e = el_bin(eop, TYint, e, el_long(TYint, 0));
-	el_setLoc(e,loc);
-    }
-    else if ((t1->ty == Tarray || t1->ty == Tsarray) &&
-	     (t2->ty == Tarray || t2->ty == Tsarray))
-    {
-	elem *ea1;
-	elem *ea2;
-
-	ea1 = e1->toElem(irs);
-	ea1 = array_toDarray(t1, ea1);
-	ea2 = e2->toElem(irs);
-	ea2 = array_toDarray(t2, ea2);
-
-	e = el_bin(eop, type->totym(), ea1, ea2);
-	el_setLoc(e,loc);
-    }
-    else
-	e = toElemBin(irs, eop);
-
-    return e;
-}
-
-
-/***************************************
- */
-
-elem *InExp::toElem(IRState *irs)
-{   elem *e;
-    elem *key = e1->toElem(irs);
-    elem *aa = e2->toElem(irs);
-    elem *ep;
-    elem *keyti;
-    TypeAArray *taa = (TypeAArray *)e2->type->toBasetype();
-    
-
-    // set to:
-    //	aaIn(aa, keyti, key);
-
-    if (key->Ety == TYstruct)
-    {
-	key = el_una(OPstrpar, TYstruct, key);
-	key->Enumbytes = key->E1->Enumbytes;
-	assert(key->Enumbytes);
-    }
-
-    Symbol *s = taa->aaGetSymbol("In", 0);
-    keyti = taa->index->getInternalTypeInfo(NULL)->toElem(irs);
-    ep = el_params(key, keyti, aa, NULL);
-    e = el_bin(OPcall, type->totym(), el_var(s), ep);
-
-    el_setLoc(e,loc);
-    return e;
-}
-
-/***************************************
- */
-
-elem *RemoveExp::toElem(IRState *irs)
-{   elem *e;
-    Type *tb = e1->type->toBasetype();
-    assert(tb->ty == Taarray);
-    TypeAArray *taa = (TypeAArray *)tb;
-    elem *ea = e1->toElem(irs);
-    elem *ekey = e2->toElem(irs);
-    elem *ep;
-    elem *keyti;
-
-    if (ekey->Ety == TYstruct)
-    {
-	ekey = el_una(OPstrpar, TYstruct, ekey);
-	ekey->Enumbytes = ekey->E1->Enumbytes;
-	assert(ekey->Enumbytes);
-    }
-
-    Symbol *s = taa->aaGetSymbol("Del", 0);
-    keyti = taa->index->getInternalTypeInfo(NULL)->toElem(irs);
-    ep = el_params(ekey, keyti, ea, NULL);
-    e = el_bin(OPcall, TYnptr, el_var(s), ep);
-
-    el_setLoc(e,loc);
-    return e;
-}
-
-/***************************************
- */
-
-elem *AssignExp::toElem(IRState *irs)
-{   elem *e;
-    IndexExp *ae;
-    int r;
-    Type *t1b;
-
-    //printf("AssignExp::toElem('%s')\n", toChars());
-    t1b = e1->type->toBasetype();
-
-    // Look for array.length = n
-    if (e1->op == TOKarraylength)
-    {
-	// Generate:
-	//	_d_arraysetlength(e2, sizeelem, &ale->e1);
-
-	ArrayLengthExp *ale = (ArrayLengthExp *)e1;
-	elem *p1;
-	elem *p2;
-	elem *p3;
-	elem *ep;
-	Type *t1;
-
-	p1 = e2->toElem(irs);
-	p3 = ale->e1->toElem(irs);
-	p3 = addressElem(p3, NULL);
-	t1 = ale->e1->type->toBasetype();
-
-#if 1
-	// call _d_arraysetlengthT(ti, e2, &ale->e1);
-	p2 = t1->getTypeInfo(NULL)->toElem(irs);
-	ep = el_params(p3, p1, p2, NULL);	// c function
-	r = t1->nextOf()->isZeroInit() ? RTLSYM_ARRAYSETLENGTHT : RTLSYM_ARRAYSETLENGTHIT;
-#else
-	if (t1->next->isZeroInit())
-	{   p2 = t1->getTypeInfo(NULL)->toElem(irs);
-	    ep = el_params(p3, p1, p2, NULL);	// c function
-	    r = RTLSYM_ARRAYSETLENGTHT;
-	}
-	else
-	{
-	    p2 = el_long(TYint, t1->next->size());
-	    ep = el_params(p3, p2, p1, NULL);	// c function
-	    Expression *init = t1->next->defaultInit();
-	    ep = el_param(el_long(TYint, init->type->size()), ep);
-	    elem *ei = init->toElem(irs);
-	    ep = el_param(ei, ep);
-	    r = RTLSYM_ARRAYSETLENGTH3;
-	}
-#endif
-
-	e = el_bin(OPcall, type->totym(), el_var(rtlsym[r]), ep);
-	el_setLoc(e, loc);
-	return e;
-    }
-
-    // Look for array[]=n
-    if (e1->op == TOKslice)
-    {
-	SliceExp *are = (SliceExp *)(e1);
-	Type *t1 = t1b;
-	Type *t2 = e2->type->toBasetype();
-
-	// which we do if the 'next' types match
-	if (ismemset)
-	{   // Do a memset for array[]=v
-	    //printf("Lpair %s\n", toChars());
-	    SliceExp *are = (SliceExp *)e1;
-	    elem *elwr;
-	    elem *eupr;
-	    elem *n1;
-	    elem *evalue;
-	    elem *enbytes;
-	    elem *elength;
-	    elem *einit;
-	    integer_t value;
-	    Type *ta = are->e1->type->toBasetype();
-	    Type *tb = ta->nextOf()->toBasetype();
-	    int sz = tb->size();
-	    tym_t tym = type->totym();
-
-	    n1 = are->e1->toElem(irs);
-	    elwr = are->lwr ? are->lwr->toElem(irs) : NULL;
-	    eupr = are->upr ? are->upr->toElem(irs) : NULL;
-
-	    elem *n1x = n1;
-
-	    // Look for array[]=n
-	    if (ta->ty == Tsarray)
-	    {
-		TypeSArray *ts;
-
-		ts = (TypeSArray *) ta;
-		n1 = array_toPtr(ta, n1);
-		enbytes = ts->dim->toElem(irs);
-		n1x = n1;
-		n1 = el_same(&n1x);
-		einit = resolveLengthVar(are->lengthVar, &n1, ta);
-	    }
-	    else if (ta->ty == Tarray)
-	    {
-		n1 = el_same(&n1x);
-		einit = resolveLengthVar(are->lengthVar, &n1, ta);
-		enbytes = el_copytree(n1);
-		n1 = array_toPtr(ta, n1);
-		enbytes = el_una(OP64_32, TYint, enbytes);
-	    }
-	    else if (ta->ty == Tpointer)
-	    {
-		n1 = el_same(&n1x);
-		enbytes = el_long(TYint, -1);	// largest possible index
-		einit = NULL;
-	    }
-
-	    // Enforce order of evaluation of n1[elwr..eupr] as n1,elwr,eupr
-	    elem *elwrx = elwr;
-	    if (elwr) elwr = el_same(&elwrx);
-	    elem *euprx = eupr;
-	    if (eupr) eupr = el_same(&euprx);
-
-#if 0
-	    printf("sz = %d\n", sz);
-	    printf("n1x\n");
-	    elem_print(n1x);
-	    printf("einit\n");
-	    elem_print(einit);
-	    printf("elwrx\n");
-	    elem_print(elwrx);
-	    printf("euprx\n");
-	    elem_print(euprx);
-	    printf("n1\n");
-	    elem_print(n1);
-	    printf("elwr\n");
-	    elem_print(elwr);
-	    printf("eupr\n");
-	    elem_print(eupr);
-	    printf("enbytes\n");
-	    elem_print(enbytes);
-#endif
-	    einit = el_combine(n1x, einit);
-	    einit = el_combine(einit, elwrx);
-	    einit = el_combine(einit, euprx);
-
-	    evalue = this->e2->toElem(irs);
-
-#if 0
-	    printf("n1\n");
-	    elem_print(n1);
-	    printf("enbytes\n");
-	    elem_print(enbytes);
-#endif
-
-	    if (global.params.useArrayBounds && eupr && ta->ty != Tpointer)
-	    {
-		elem *c1;
-		elem *c2;
-		elem *ea;
-		elem *eb;
-		elem *enbytesx;
-
-		assert(elwr);
-		enbytesx = enbytes;
-		enbytes = el_same(&enbytesx);
-		c1 = el_bin(OPle, TYint, el_copytree(eupr), enbytesx);
-		c2 = el_bin(OPle, TYint, el_copytree(elwr), el_copytree(eupr));
-		c1 = el_bin(OPandand, TYint, c1, c2);
-
-		// Construct: (c1 || ModuleArray(line))
-		Symbol *sassert;
-
-		sassert = irs->blx->module->toModuleArray();
-		ea = el_bin(OPcall,TYvoid,el_var(sassert), el_long(TYint, loc.linnum));
-		eb = el_bin(OPoror,TYvoid,c1,ea);
-		einit = el_combine(einit, eb);
-	    }
-
-	    if (elwr)
-	    {   elem *elwr2;
-
-		el_free(enbytes);
-		elwr2 = el_copytree(elwr);
-		elwr2 = el_bin(OPmul, TYint, elwr2, el_long(TYint, sz));
-		n1 = el_bin(OPadd, TYnptr, n1, elwr2);
-		enbytes = el_bin(OPmin, TYint, eupr, elwr);
-		elength = el_copytree(enbytes);
-	    }
-	    else
-		elength = el_copytree(enbytes);
-	    e = setArray(n1, enbytes, tb, evalue, irs, op);
-	Lpair:
-	    e = el_pair(TYullong, elength, e);
-	Lret2:
-	    e = el_combine(einit, e);
-	    //elem_print(e);
-	    goto Lret;
-	}
-#if 0
-	else if (e2->op == TOKadd || e2->op == TOKmin)
-	{
-	    /* It's ea[] = eb[] +- ec[]
-	     */
-	    BinExp *e2a = (BinExp *)e2;
-	    Type *t = e2->type->toBasetype()->nextOf()->toBasetype();
-	    if (t->ty != Tfloat32 && t->ty != Tfloat64 && t->ty != Tfloat80)
-	    {
-		e2->error("array add/min for %s not supported", t->toChars());
-		return el_long(TYint, 0);
-	    }
-	    elem *ea = e1->toElem(irs);
-	    ea = array_toDarray(e1->type, ea);
-	    elem *eb = e2a->e1->toElem(irs);
-	    eb = array_toDarray(e2a->e1->type, eb);
-	    elem *ec = e2a->e2->toElem(irs);
-	    ec = array_toDarray(e2a->e2->type, ec);
-
-	    int rtl = RTLSYM_ARRAYASSADDFLOAT;
-	    if (t->ty == Tfloat64)
-		rtl = RTLSYM_ARRAYASSADDDOUBLE;
-	    else if (t->ty == Tfloat80)
-		rtl = RTLSYM_ARRAYASSADDREAL;
-	    if (e2->op == TOKmin)
-	    {
-		rtl = RTLSYM_ARRAYASSMINFLOAT;
-		if (t->ty == Tfloat64)
-		    rtl = RTLSYM_ARRAYASSMINDOUBLE;
-		else if (t->ty == Tfloat80)
-		    rtl = RTLSYM_ARRAYASSMINREAL;
-	    }
-
-	    /* Set parameters so the order of evaluation is eb, ec, ea
-	     */
-	    elem *ep = el_params(eb, ec, ea, NULL);
-	    e = el_bin(OPcall, type->totym(), el_var(rtlsym[rtl]), ep);
-	    goto Lret;
-	}
-#endif
-	else
-	{
-	    /* It's array1[]=array2[]
-	     * which is a memcpy
-	     */
-	    elem *eto;
-	    elem *efrom;
-	    elem *esize;
-	    elem *ep;
-
-	    eto = e1->toElem(irs);
-	    efrom = e2->toElem(irs);
-
-	    unsigned size = t1->nextOf()->size();
-	    esize = el_long(TYint, size);
-
-	    /* Determine if we need to do postblit
-	     */
-	    int postblit = 0;
-	    Type *t = t1;
-	    do
-		t = t->nextOf()->toBasetype();
-	    while (t->ty == Tsarray);
-	    if (t->ty == Tstruct)
-	    {	StructDeclaration *sd = ((TypeStruct *)t)->sym;
-		if (sd->postblit)
-		    postblit = 1;
-	    }
-
-	    assert(e2->type->ty != Tpointer);
-
-	    if (!postblit && !global.params.useArrayBounds)
-	    {	elem *epto;
-		elem *epfr;
-		elem *elen;
-		elem *ex;
-
-		ex = el_same(&eto);
-
-		// Determine if elen is a constant
-		if (eto->Eoper == OPpair &&
-		    eto->E1->Eoper == OPconst)
-		{
-		    elen = el_copytree(eto->E1);
-		}
-		else
-		{
-		    // It's not a constant, so pull it from the dynamic array
-		    elen = el_una(OP64_32, TYint, el_copytree(ex));
-		}
-
-		esize = el_bin(OPmul, TYint, elen, esize);
-		epto = array_toPtr(e1->type, ex);
-		epfr = array_toPtr(e2->type, efrom);
-		e = el_bin(OPmemcpy, TYnptr, epto, el_param(epfr, esize));
-		e = el_pair(eto->Ety, el_copytree(elen), e);
-		e = el_combine(eto, e);
-	    }
-#if DMDV2
-	    else if (postblit && op != TOKblit)
-	    {
-		/* Generate:
-		 *	_d_arrayassign(ti, efrom, eto)
-		 * or:
-		 *	_d_arrayctor(ti, efrom, eto)
-		 */
-		el_free(esize);
-		Expression *ti = t1->nextOf()->toBasetype()->getTypeInfo(NULL);
-		ep = el_params(eto, efrom, ti->toElem(irs), NULL);
-		int rtl = (op == TOKconstruct) ? RTLSYM_ARRAYCTOR : RTLSYM_ARRAYASSIGN;
-		e = el_bin(OPcall, type->totym(), el_var(rtlsym[rtl]), ep);
-	    }
-#endif
-	    else
-	    {
-		// Generate:
-		//	_d_arraycopy(eto, efrom, esize)
-
-		ep = el_params(eto, efrom, esize, NULL);
-		e = el_bin(OPcall, type->totym(), el_var(rtlsym[RTLSYM_ARRAYCOPY]), ep);
-	    }
-	    el_setLoc(e, loc);
-	    return e;
-	}
-    }
-
-    if (e1->op == TOKindex)
-    {
-	elem *eb;
-	elem *ei;
-	elem *ev;
-	TY ty;
-	Type *ta;
-
-	ae = (IndexExp *)(e1);
-	ta = ae->e1->type->toBasetype();
-	ty = ta->ty;
-    }
-#if 1
-    /* This will work if we can distinguish an assignment from
-     * an initialization of the lvalue. It'll work if the latter.
-     * If the former, because of aliasing of the return value with
-     * function arguments, it'll fail.
-     */
-    if (op == TOKconstruct && e2->op == TOKcall)
-    {	CallExp *ce = (CallExp *)e2;
-
-	TypeFunction *tf = (TypeFunction *)ce->e1->type->toBasetype();
-	if (tf->ty == Tfunction && tf->retStyle() == RETstack)
-	{
-	    elem *ehidden = e1->toElem(irs);
-	    ehidden = el_una(OPaddr, TYnptr, ehidden);
-	    assert(!irs->ehidden);
-	    irs->ehidden = ehidden;
-	    e = e2->toElem(irs);
-	    goto Lret;
-	}
-    }
-#endif
-    if (t1b->ty == Tstruct)
-    {
-	if (e2->op == TOKint64)
-	{   /* Implement:
-	     *	(struct = 0)
-	     * with:
-	     *	memset(&struct, 0, struct.sizeof)
-	     */
-	    elem *el = e1->toElem(irs);
-	    elem *enbytes = el_long(TYint, e1->type->size());
-	    elem *evalue = el_long(TYint, 0);
-
-	    el = el_una(OPaddr, TYnptr, el);
-	    e = el_param(enbytes, evalue);
-	    e = el_bin(OPmemset,TYnptr,el,e);
-	    el_setLoc(e, loc);
-	    //e = el_una(OPind, TYstruct, e);
-	}
-	else
-	{
-	    elem *e1;
-	    elem *e2;
-	    tym_t tym;
-
-	    //printf("toElemBin() '%s'\n", toChars());
-
-	    tym = type->totym();
-
-	    e1 = this->e1->toElem(irs);
-	    elem *ex = e1;
-	    if (e1->Eoper == OPind)
-		ex = e1->E1;
-	    if (this->e2->op == TOKstructliteral &&
-		ex->Eoper == OPvar && ex->EV.sp.Voffset == 0)
-	    {	StructLiteralExp *se = (StructLiteralExp *)this->e2;
-
-		Symbol *symSave = se->sym;
-		size_t soffsetSave = se->soffset;
-		int fillHolesSave = se->fillHoles;
-
-		se->sym = ex->EV.sp.Vsym;
-		se->soffset = 0;
-		se->fillHoles = (op == TOKconstruct || op == TOKblit) ? 1 : 0;
-
-		el_free(e1);
-		e = this->e2->toElem(irs);
-
-		se->sym = symSave;
-		se->soffset = soffsetSave;
-		se->fillHoles = fillHolesSave;
-	    }
-	    else
-	    {
-		e2 = this->e2->toElem(irs);
-		e = el_bin(OPstreq,tym,e1,e2);
-		e->Enumbytes = this->e1->type->size();
-	    }
-	    goto Lret;
-	}
-    }
-    else
-	e = toElemBin(irs,OPeq);
-    return e;
-
-  Lret:
-    el_setLoc(e,loc);
-    return e;
-}
-
-/***************************************
- */
-
-elem *AddAssignExp::toElem(IRState *irs)
-{
-    //printf("AddAssignExp::toElem() %s\n", toChars());
-    elem *e;
-    Type *tb1 = e1->type->toBasetype();
-    Type *tb2 = e2->type->toBasetype();
-
-    if ((tb1->ty == Tarray || tb1->ty == Tsarray) &&
-	(tb2->ty == Tarray || tb2->ty == Tsarray)
-       )
-    {
-	error("Array operations not implemented");
-    }
-    else
-	e = toElemBin(irs,OPaddass);
-    return e;
-}
-
-
-/***************************************
- */
-
-elem *MinAssignExp::toElem(IRState *irs)
-{
-    return toElemBin(irs,OPminass);
-}
-
-/***************************************
- */
-
-elem *CatAssignExp::toElem(IRState *irs)
-{
-    //printf("CatAssignExp::toElem('%s')\n", toChars());
-    elem *e;
-    Type *tb1 = e1->type->toBasetype();
-    Type *tb2 = e2->type->toBasetype();
-
-    if (tb1->ty == Tarray || tb2->ty == Tsarray)
-    {   elem *e1;
-	elem *e2;
-	elem *ep;
-
-	e1 = this->e1->toElem(irs);
-	e1 = el_una(OPaddr, TYnptr, e1);
-
-	e2 = this->e2->toElem(irs);
-	if (e2->Ety == TYstruct)
-	{
-	    e2 = el_una(OPstrpar, TYstruct, e2);
-	    e2->Enumbytes = e2->E1->Enumbytes;
-	    assert(e2->Enumbytes);
-	}
-
-	Type *tb1n = tb1->nextOf()->toBasetype();
-	if ((tb2->ty == Tarray || tb2->ty == Tsarray) &&
-	    tb1n->equals(tb2->nextOf()->toBasetype()))
-	{   // Append array
-#if 1
-	    ep = el_params(e2, e1, this->e1->type->getTypeInfo(NULL)->toElem(irs), NULL);
-	    e = el_bin(OPcall, TYdarray, el_var(rtlsym[RTLSYM_ARRAYAPPENDT]), ep);
-#else
-	    ep = el_params(el_long(TYint, tb1n->size()), e2, e1, NULL);
-	    e = el_bin(OPcall, TYdarray, el_var(rtlsym[RTLSYM_ARRAYAPPEND]), ep);
-#endif
-	}
-	else
-	{   // Append element
-#if 1
-	    ep = el_params(e2, e1, this->e1->type->getTypeInfo(NULL)->toElem(irs), NULL);
-	    e = el_bin(OPcall, TYdarray, el_var(rtlsym[RTLSYM_ARRAYAPPENDCT]), ep);
-#else
-	    ep = el_params(e2, el_long(TYint, tb1n->size()), e1, NULL);
-	    e = el_bin(OPcall, TYdarray, el_var(rtlsym[RTLSYM_ARRAYAPPENDC]), ep);
-#endif
-	}
-	el_setLoc(e,loc);
-    }
-    else
-	assert(0);
-    return e;
-}
-
-
-/***************************************
- */
-
-elem *DivAssignExp::toElem(IRState *irs)
-{
-    return toElemBin(irs,OPdivass);
-}
-
-
-/***************************************
- */
-
-elem *ModAssignExp::toElem(IRState *irs)
-{
-    return toElemBin(irs,OPmodass);
-}
-
-
-/***************************************
- */
-
-elem *MulAssignExp::toElem(IRState *irs)
-{
-    return toElemBin(irs,OPmulass);
-}
-
-
-/***************************************
- */
-
-elem *ShlAssignExp::toElem(IRState *irs)
-{   elem *e;
-
-    e = toElemBin(irs,OPshlass);
-    return e;
-}
-
-
-/***************************************
- */
-
-elem *ShrAssignExp::toElem(IRState *irs)
-{
-    return toElemBin(irs,OPshrass);
-}
-
-
-/***************************************
- */
-
-elem *UshrAssignExp::toElem(IRState *irs)
-{
-    elem *eleft  = e1->toElem(irs);
-    eleft->Ety = touns(eleft->Ety);
-    elem *eright = e2->toElem(irs);
-    elem *e = el_bin(OPshrass, type->totym(), eleft, eright);
-    el_setLoc(e, loc);
-    return e;
-}
-
-
-/***************************************
- */
-
-elem *AndAssignExp::toElem(IRState *irs)
-{
-    return toElemBin(irs,OPandass);
-}
-
-
-/***************************************
- */
-
-elem *OrAssignExp::toElem(IRState *irs)
-{
-    return toElemBin(irs,OPorass);
-}
-
-
-/***************************************
- */
-
-elem *XorAssignExp::toElem(IRState *irs)
-{
-    return toElemBin(irs,OPxorass);
-}
-
-
-/***************************************
- */
-
-elem *AndAndExp::toElem(IRState *irs)
-{
-    elem *e = toElemBin(irs,OPandand);
-    if (global.params.cov && e2->loc.linnum)
-	e->E2 = el_combine(incUsageElem(irs, e2->loc), e->E2);
-    return e;
-}
-
-
-/***************************************
- */
-
-elem *OrOrExp::toElem(IRState *irs)
-{
-    elem *e = toElemBin(irs,OPoror);
-    if (global.params.cov && e2->loc.linnum)
-	e->E2 = el_combine(incUsageElem(irs, e2->loc), e->E2);
-    return e;
-}
-
-
-/***************************************
- */
-
-elem *XorExp::toElem(IRState *irs)
-{
-    return toElemBin(irs,OPxor);
-}
-
-
-/***************************************
- */
-
-elem *AndExp::toElem(IRState *irs)
-{
-    return toElemBin(irs,OPand);
-}
-
-
-/***************************************
- */
-
-elem *OrExp::toElem(IRState *irs)
-{
-    return toElemBin(irs,OPor);
-}
-
-
-/***************************************
- */
-
-elem *ShlExp::toElem(IRState *irs)
-{
-    return toElemBin(irs, OPshl);
-}
-
-
-/***************************************
- */
-
-elem *ShrExp::toElem(IRState *irs)
-{
-    return toElemBin(irs,OPshr);
-}
-
-
-/***************************************
- */
-
-elem *UshrExp::toElem(IRState *irs)
-{
-    elem *eleft  = e1->toElem(irs);
-    eleft->Ety = touns(eleft->Ety);
-    elem *eright = e2->toElem(irs);
-    elem *e = el_bin(OPshr, type->totym(), eleft, eright);
-    el_setLoc(e, loc);
-    return e;
-}
-
-/****************************************
- */
-
-elem *CommaExp::toElem(IRState *irs)
-{
-    assert(e1 && e2);
-    elem *eleft  = e1->toElem(irs);
-    elem *eright = e2->toElem(irs);
-    elem *e = el_combine(eleft, eright);
-    if (e)
-	el_setLoc(e, loc);
-    return e;
-}
-
-
-/***************************************
- */
-
-elem *CondExp::toElem(IRState *irs)
-{   elem *eleft;
-    elem *eright;
-
-    elem *ec = econd->toElem(irs);
-
-    eleft = e1->toElem(irs);
-    tym_t ty = eleft->Ety;
-    if (global.params.cov && e1->loc.linnum)
-	eleft = el_combine(incUsageElem(irs, e1->loc), eleft);
-
-    eright = e2->toElem(irs);
-    if (global.params.cov && e2->loc.linnum)
-	eright = el_combine(incUsageElem(irs, e2->loc), eright);
-
-    elem *e = el_bin(OPcond, ty, ec, el_bin(OPcolon, ty, eleft, eright));
-    if (tybasic(ty) == TYstruct)
-	e->Enumbytes = e1->type->size();
-    el_setLoc(e, loc);
-    return e;
-}
-
-
-/***************************************
- */
-
-elem *TypeDotIdExp::toElem(IRState *irs)
-{
-    print();
-    assert(0);
-    return NULL;
-}
-
-elem *TypeExp::toElem(IRState *irs)
-{
-#ifdef DEBUG
-    printf("TypeExp::toElem()\n");
-#endif
-    error("type %s is not an expression", toChars());
-    return el_long(TYint, 0);
-}
-
-elem *ScopeExp::toElem(IRState *irs)
-{
-    error("%s is not an expression", sds->toChars());
-    return el_long(TYint, 0);
-}
-
-elem *DotVarExp::toElem(IRState *irs)
-{
-    // *(&e + offset)
-
-    //printf("DotVarExp::toElem('%s')\n", toChars());
-
-    VarDeclaration *v = var->isVarDeclaration();
-    if (!v)
-    {
-	error("%s is not a field", var->toChars());
-    }
-
-    elem *e = e1->toElem(irs);
-    Type *tb1 = e1->type->toBasetype();
-    if (tb1->ty != Tclass && tb1->ty != Tpointer)
-	e = el_una(OPaddr, TYnptr, e);
-    e = el_bin(OPadd, TYnptr, e, el_long(TYint, v ? v->offset : 0));
-    e = el_una(OPind, type->totym(), e);
-    if (tybasic(e->Ety) == TYstruct)
-    {
-	e->Enumbytes = type->size();
-    }
-    el_setLoc(e,loc);
-    return e;
-}
-
-elem *DelegateExp::toElem(IRState *irs)
-{
-    elem *e;
-    elem *ethis;
-    elem *ep;
-    Symbol *sfunc;
-    int directcall = 0;
-
-    //printf("DelegateExp::toElem() '%s'\n", toChars());
-    sfunc = func->toSymbol();
-    if (func->isNested())
-    {
-	ep = el_ptr(sfunc);
-	ethis = getEthis(loc, irs, func);
-    }
-    else
-    {
-	ethis = e1->toElem(irs);
-	if (e1->type->ty != Tclass && e1->type->ty != Tpointer)
-	    ethis = el_una(OPaddr, TYnptr, ethis);
-
-	if (e1->op == TOKsuper)
-	    directcall = 1;
-
-	if (!func->isThis())
-	    error("delegates are only for non-static functions");
-
-	if (!func->isVirtual() ||
-	    directcall ||
-	    func->isFinal())
-	{
-	    ep = el_ptr(sfunc);
-	}
-	else
-	{
-	    // Get pointer to function out of virtual table
-	    unsigned vindex;
-
-	    assert(ethis);
-	    ep = el_same(&ethis);
-	    ep = el_una(OPind, TYnptr, ep);
-	    vindex = func->vtblIndex;
-
-	    // Build *(ep + vindex * 4)
-	    ep = el_bin(OPadd,TYnptr,ep,el_long(TYint, vindex * 4));
-	    ep = el_una(OPind,TYnptr,ep);
-	}
-
-//	if (func->tintro)
-//	    func->error(loc, "cannot form delegate due to covariant return type");
-    }
-    if (ethis->Eoper == OPcomma)
-    {
-	ethis->E2 = el_pair(TYullong, ethis->E2, ep);
-	ethis->Ety = TYullong;
-	e = ethis;
-    }
-    else
-	e = el_pair(TYullong, ethis, ep);
-    el_setLoc(e,loc);
-    return e;
-}
-
-elem *DotTypeExp::toElem(IRState *irs)
-{
-    // Just a pass-thru to e1
-    elem *e;
-
-    //printf("DotTypeExp::toElem() %s\n", toChars());
-    e = e1->toElem(irs);
-    el_setLoc(e,loc);
-    return e;
-}
-
-elem *CallExp::toElem(IRState *irs)
-{
-    //printf("CallExp::toElem('%s')\n", toChars());
-    assert(e1->type);
-    elem *ec;
-    int directcall;
-    FuncDeclaration *fd;
-    Type *t1 = e1->type->toBasetype();
-    Type *ectype = t1;
-
-    elem *ehidden = irs->ehidden;
-    irs->ehidden = NULL;
-
-    directcall = 0;
-    fd = NULL;
-    if (e1->op == TOKdotvar && t1->ty != Tdelegate)
-    {	DotVarExp *dve = (DotVarExp *)e1;
-
-	fd = dve->var->isFuncDeclaration();
-	Expression *ex = dve->e1;
-	while (1)
-	{
-	    switch (ex->op)
-	    {
-		case TOKsuper:		// super.member() calls directly
-		case TOKdottype:	// type.member() calls directly
-		    directcall = 1;
-		    break;
-
-		case TOKcast:
-		    ex = ((CastExp *)ex)->e1;
-		    continue;
-
-		default:
-		    //ex->dump(0);
-		    break;
-	    }
-	    break;
-	}
-	ec = dve->e1->toElem(irs);
-	ectype = dve->e1->type->toBasetype();
-    }
-    else if (e1->op == TOKvar)
-    {
-	fd = ((VarExp *)e1)->var->isFuncDeclaration();
-
-	if (fd && fd->ident == Id::alloca &&
-	    !fd->fbody && fd->linkage == LINKc &&
-	    arguments && arguments->dim == 1)
-	{   Expression *arg = (Expression *)arguments->data[0];
-	    arg = arg->optimize(WANTvalue);
-	    if (arg->isConst() && arg->type->isintegral())
-	    {	integer_t sz = arg->toInteger();
-		if (sz > 0 && sz < 0x40000)
-		{
-		    // It's an alloca(sz) of a fixed amount.
-		    // Replace with an array allocated on the stack
-		    // of the same size: char[sz] tmp;
-
-		    Symbol *stmp;
-		    ::type *t;
-
-		    assert(!ehidden);
-		    t = type_allocn(TYarray, tschar);
-		    t->Tdim = sz;
-		    stmp = symbol_genauto(t);
-		    ec = el_ptr(stmp);
-		    el_setLoc(ec,loc);
-		    return ec;
-		}
-	    }
-	}
-
-	ec = e1->toElem(irs);
-    }
-    else
-    {
-	ec = e1->toElem(irs);
-    }
-    ec = callfunc(loc, irs, directcall, type, ec, ectype, fd, t1, ehidden, arguments);
-    el_setLoc(ec,loc);
-    return ec;
-}
-
-elem *AddrExp::toElem(IRState *irs)
-{   elem *e;
-    elem **pe;
-
-    //printf("AddrExp::toElem('%s')\n", toChars());
-
-    e = e1->toElem(irs);
-    e = addressElem(e, e1->type);
-L2:
-    e->Ety = type->totym();
-    el_setLoc(e,loc);
-    return e;
-}
-
-elem *PtrExp::toElem(IRState *irs)
-{   elem *e;
-
-    //printf("PtrExp::toElem() %s\n", toChars());
-    e = e1->toElem(irs);
-    e = el_una(OPind,type->totym(),e);
-    if (tybasic(e->Ety) == TYstruct)
-    {
-	e->Enumbytes = type->size();
-    }
-    el_setLoc(e,loc);
-    return e;
-}
-
-elem *BoolExp::toElem(IRState *irs)
-{   elem *e1;
-
-    e1 = this->e1->toElem(irs);
-    return el_una(OPbool,type->totym(),e1);
-}
-
-elem *DeleteExp::toElem(IRState *irs)
-{   elem *e;
-    int rtl;
-    Type *tb;
-
-    //printf("DeleteExp::toElem()\n");
-    if (e1->op == TOKindex)
-    {
-	IndexExp *ae = (IndexExp *)(e1);
-	tb = ae->e1->type->toBasetype();
-	if (tb->ty == Taarray)
-	{
-	    TypeAArray *taa = (TypeAArray *)tb;
-	    elem *ea = ae->e1->toElem(irs);
-	    elem *ekey = ae->e2->toElem(irs);
-	    elem *ep;
-	    elem *keyti;
-
-	    if (ekey->Ety == TYstruct)
-	    {
-		ekey = el_una(OPstrpar, TYstruct, ekey);
-		ekey->Enumbytes = ekey->E1->Enumbytes;
-		assert(ekey->Enumbytes);
-	    }
-
-	    Symbol *s = taa->aaGetSymbol("Del", 0);
-	    keyti = taa->index->getInternalTypeInfo(NULL)->toElem(irs);
-	    ep = el_params(ekey, keyti, ea, NULL);
-	    e = el_bin(OPcall, TYnptr, el_var(s), ep);
-	    goto Lret;
-	}
-    }
-    //e1->type->print();
-    e = e1->toElem(irs);
-    tb = e1->type->toBasetype();
-    switch (tb->ty)
-    {
-	case Tarray:
-	{   e = addressElem(e, e1->type);
-	    rtl = RTLSYM_DELARRAYT;
-
-	    /* See if we need to run destructors on the array contents
-	     */
-	    elem *et = NULL;
-	    Type *tv = tb->nextOf()->toBasetype();
-	    while (tv->ty == Tsarray)
-	    {   TypeSArray *ta = (TypeSArray *)tv;
-		tv = tv->nextOf()->toBasetype();
-	    }
-	    if (tv->ty == Tstruct)
-	    {   TypeStruct *ts = (TypeStruct *)tv;
-		StructDeclaration *sd = ts->sym;
-		if (sd->dtor)
-		    et = tb->nextOf()->getTypeInfo(NULL)->toElem(irs);
-	    }
-	    if (!et)				// if no destructors needed
-		et = el_long(TYnptr, 0);	// pass null for TypeInfo
-	    e = el_params(et, e, NULL);
-	    // call _d_delarray_t(e, et);
-	    e = el_bin(OPcall, TYvoid, el_var(rtlsym[rtl]), e);
-	    goto Lret;
-	}
-	case Tclass:
-	    if (e1->op == TOKvar)
-	    {	VarExp *ve = (VarExp *)e1;
-		if (ve->var->isVarDeclaration() &&
-		    ve->var->isVarDeclaration()->onstack)
-		{
-		    rtl = RTLSYM_CALLFINALIZER;
-		    if (tb->isClassHandle()->isInterfaceDeclaration())
-			rtl = RTLSYM_CALLINTERFACEFINALIZER;
-		    break;
-		}
-	    }
-	    e = addressElem(e, e1->type);
-	    rtl = RTLSYM_DELCLASS;
-	    if (tb->isClassHandle()->isInterfaceDeclaration())
-		rtl = RTLSYM_DELINTERFACE;
-	    break;
-
-	case Tpointer:
-	    e = addressElem(e, e1->type);
-	    rtl = RTLSYM_DELMEMORY;
-	    break;
-
-	default:
-	    assert(0);
-	    break;
-    }
-    e = el_bin(OPcall, TYvoid, el_var(rtlsym[rtl]), e);
-
-  Lret:
-    el_setLoc(e,loc);
-    return e;
-}
-
-elem *CastExp::toElem(IRState *irs)
-{   elem *e;
-    TY fty;
-    TY tty;
-    tym_t ftym;
-    tym_t ttym;
-    enum OPER eop;
-    Type *t;
-    Type *tfrom;
-
-#if 0
-    printf("CastExp::toElem()\n");
-    print();
-    printf("\tfrom: %s\n", e1->type->toChars());
-    printf("\tto  : %s\n", to->toChars());
-#endif
-
-    e = e1->toElem(irs);
-    tfrom = e1->type->toBasetype();
-    t = to->toBasetype();		// skip over typedef's
-    if (t->equals(tfrom))
-	goto Lret;
-
-    fty = tfrom->ty;
-    //printf("fty = %d\n", fty);
-    tty = t->ty;
-
-    if (tty == Tpointer && fty == Tarray
-#if 0
-	&& (t->next->ty == Tvoid || t->next->equals(e1->type->next))
-#endif
-       )
-    {
-	if (e->Eoper == OPvar)
-	{
-	    // e1 -> *(&e1 + 4)
-	    e = el_una(OPaddr, TYnptr, e);
-	    e = el_bin(OPadd, TYnptr, e, el_long(TYint, 4));
-	    e = el_una(OPind,t->totym(),e);
-	}
-	else
-	{
-	    // e1 -> (unsigned)(e1 >> 32)
-	    e = el_bin(OPshr, TYullong, e, el_long(TYint, 32));
-	    e = el_una(OP64_32, t->totym(), e);
-	}
-	goto Lret;
-    }
-
-    if (tty == Tpointer && fty == Tsarray
-#if 0
-	&& (t->next->ty == Tvoid || t->next->equals(e1->type->next))
-#endif
-	)
-    {
-	// e1 -> &e1
-	e = el_una(OPaddr, TYnptr, e);
-	goto Lret;
-    }
-
-    // Convert from static array to dynamic array
-    if (tty == Tarray && fty == Tsarray)
-    {
-	e = sarray_toDarray(loc, tfrom, t, e);
-	goto Lret;
-    }
-
-    // Convert from dynamic array to dynamic array
-    if (tty == Tarray && fty == Tarray)
-    {
-	unsigned fsize = tfrom->nextOf()->size();
-	unsigned tsize = t->nextOf()->size();
-
-	if (fsize != tsize)
-	{
-	    elem *ep;
-
-	    ep = el_params(e, el_long(TYint, fsize), el_long(TYint, tsize), NULL);
-	    e = el_bin(OPcall, type->totym(), el_var(rtlsym[RTLSYM_ARRAYCAST]), ep);
-	}
-	goto Lret;
-    }
-
-    // Casting from base class to derived class requires a runtime check
-    if (fty == Tclass && tty == Tclass)
-    {
-	// Casting from derived class to base class is a no-op
-	ClassDeclaration *cdfrom;
-	ClassDeclaration *cdto;
-	int offset;
-	int rtl = RTLSYM_DYNAMIC_CAST;
-
-	cdfrom = e1->type->isClassHandle();
-	cdto   = t->isClassHandle();
-	if (cdfrom->isInterfaceDeclaration())
-	{
-	    rtl = RTLSYM_INTERFACE_CAST;
-	    if (cdfrom->isCPPinterface())
-	    {
-		if (cdto->isCPPinterface())
-		{
-		    /* Casting from a C++ interface to a C++ interface
-		     * is always a 'paint' operation
-		     */
-		    goto Lret;			// no-op
-		}
-
-		/* Casting from a C++ interface to a class
-		 * always results in null because there is no runtime
-		 * information available to do it.
-		 *
-		 * Casting from a C++ interface to a non-C++ interface
-		 * always results in null because there's no way one
-		 * can be derived from the other.
-		 */
-		e = el_bin(OPcomma, TYnptr, e, el_long(TYnptr, 0));
-		goto Lret;
-	    }
-	}
-	if (cdto->isBaseOf(cdfrom, &offset) && offset != OFFSET_RUNTIME)
-	{
-	    /* The offset from cdfrom=>cdto is known at compile time.
-	     */
-	
-	    //printf("offset = %d\n", offset);
-	    if (offset)
-	    {	/* Rewrite cast as (e ? e + offset : null)
-		 */
-		elem *etmp;
-		elem *ex;
-
-		if (e1->op == TOKthis)
-		{   // Assume 'this' is never null, so skip null check
-		    e = el_bin(OPadd, TYnptr, e, el_long(TYint, offset));
-		}
-		else
-		{
-		    etmp = el_same(&e);
-		    ex = el_bin(OPadd, TYnptr, etmp, el_long(TYint, offset));
-		    ex = el_bin(OPcolon, TYnptr, ex, el_long(TYnptr, 0));
-		    e = el_bin(OPcond, TYnptr, e, ex);
-		}
-	    }
-	    goto Lret;			// no-op
-	}
-
-	/* The offset from cdfrom=>cdto can only be determined at runtime.
-	 */
-	elem *ep;
-
-	ep = el_param(el_ptr(cdto->toSymbol()), e);
-	e = el_bin(OPcall, TYnptr, el_var(rtlsym[rtl]), ep);
-	goto Lret;
-    }
-
-    ftym = e->Ety;
-    ttym = t->totym();
-    if (ftym == ttym)
-	goto Lret;
-
-    switch (tty)
-    {
-	case Tpointer:
-	    if (fty == Tdelegate)
-		goto Lpaint;
-	    tty = Tuns32;
-	    break;
-
-	case Tchar:	tty = Tuns8;	break;
-	case Twchar:	tty = Tuns16;	break;
-	case Tdchar:	tty = Tuns32;	break;
-	case Tvoid:	goto Lpaint;
-
-	case Tbool:
-	{
-	    // Construct e?true:false
-	    elem *eq;
-
-	    e = el_una(OPbool, ttym, e);
-	    goto Lret;
-	}
-    }
-
-    switch (fty)
-    {
-	case Tpointer:	fty = Tuns32;	break;
-	case Tchar:	fty = Tuns8;	break;
-	case Twchar:	fty = Tuns16;	break;
-	case Tdchar:	fty = Tuns32;	break;
-    }
-
-    #define X(fty, tty) ((fty) * TMAX + (tty))
-Lagain:
-    switch (X(fty,tty))
-    {
-#if 0
-	case X(Tbit,Tint8):
-	case X(Tbit,Tuns8):
-				goto Lpaint;
-	case X(Tbit,Tint16):
-	case X(Tbit,Tuns16):
-	case X(Tbit,Tint32):
-	case X(Tbit,Tuns32):	eop = OPu8_16;	goto Leop;
-	case X(Tbit,Tint64):
-	case X(Tbit,Tuns64):
-	case X(Tbit,Tfloat32):
-	case X(Tbit,Tfloat64):
-	case X(Tbit,Tfloat80):
-	case X(Tbit,Tcomplex32):
-	case X(Tbit,Tcomplex64):
-	case X(Tbit,Tcomplex80):
-				e = el_una(OPu8_16, TYuint, e);
-				fty = Tuns32;
-				goto Lagain;
-	case X(Tbit,Timaginary32):
-	case X(Tbit,Timaginary64):
-	case X(Tbit,Timaginary80): goto Lzero;
-#endif
-	/* ============================= */
-
-	case X(Tbool,Tint8):
-	case X(Tbool,Tuns8):
-				goto Lpaint;
-	case X(Tbool,Tint16):
-	case X(Tbool,Tuns16):
-	case X(Tbool,Tint32):
-	case X(Tbool,Tuns32):	eop = OPu8_16;	goto Leop;
-	case X(Tbool,Tint64):
-	case X(Tbool,Tuns64):
-	case X(Tbool,Tfloat32):
-	case X(Tbool,Tfloat64):
-	case X(Tbool,Tfloat80):
-	case X(Tbool,Tcomplex32):
-	case X(Tbool,Tcomplex64):
-	case X(Tbool,Tcomplex80):
-				e = el_una(OPu8_16, TYuint, e);
-				fty = Tuns32;
-				goto Lagain;
-	case X(Tbool,Timaginary32):
-	case X(Tbool,Timaginary64):
-	case X(Tbool,Timaginary80): goto Lzero;
-
-	/* ============================= */
-
-	case X(Tint8,Tuns8):	goto Lpaint;
-	case X(Tint8,Tint16):
-	case X(Tint8,Tuns16):
-	case X(Tint8,Tint32):
-	case X(Tint8,Tuns32):	eop = OPs8_16;	goto Leop;
-	case X(Tint8,Tint64):
-	case X(Tint8,Tuns64):
-	case X(Tint8,Tfloat32):
-	case X(Tint8,Tfloat64):
-	case X(Tint8,Tfloat80):
-	case X(Tint8,Tcomplex32):
-	case X(Tint8,Tcomplex64):
-	case X(Tint8,Tcomplex80):
-				e = el_una(OPs8_16, TYint, e);
-				fty = Tint32;
-				goto Lagain;
-	case X(Tint8,Timaginary32):
-	case X(Tint8,Timaginary64):
-	case X(Tint8,Timaginary80): goto Lzero;
-
-	/* ============================= */
-
-	case X(Tuns8,Tint8):	goto Lpaint;
-	case X(Tuns8,Tint16):
-	case X(Tuns8,Tuns16):
-	case X(Tuns8,Tint32):
-	case X(Tuns8,Tuns32):	eop = OPu8_16;	goto Leop;
-	case X(Tuns8,Tint64):
-	case X(Tuns8,Tuns64):
-	case X(Tuns8,Tfloat32):
-	case X(Tuns8,Tfloat64):
-	case X(Tuns8,Tfloat80):
-	case X(Tuns8,Tcomplex32):
-	case X(Tuns8,Tcomplex64):
-	case X(Tuns8,Tcomplex80):
-				e = el_una(OPu8_16, TYuint, e);
-				fty = Tuns32;
-				goto Lagain;
-	case X(Tuns8,Timaginary32):
-	case X(Tuns8,Timaginary64):
-	case X(Tuns8,Timaginary80): goto Lzero;
-
-	/* ============================= */
-
-	case X(Tint16,Tint8):
-	case X(Tint16,Tuns8):	eop = OP16_8;	goto Leop;
-	case X(Tint16,Tuns16):	goto Lpaint;
-	case X(Tint16,Tint32):
-	case X(Tint16,Tuns32):	eop = OPs16_32;	goto Leop;
-	case X(Tint16,Tint64):
-	case X(Tint16,Tuns64):	e = el_una(OPs16_32, TYint, e);
-				fty = Tint32;
-				goto Lagain;
-	case X(Tint16,Tfloat32):
-	case X(Tint16,Tfloat64):
-	case X(Tint16,Tfloat80):
-	case X(Tint16,Tcomplex32):
-	case X(Tint16,Tcomplex64):
-	case X(Tint16,Tcomplex80):
-				e = el_una(OPs16_d, TYdouble, e);
-				fty = Tfloat64;
-				goto Lagain;
-	case X(Tint16,Timaginary32):
-	case X(Tint16,Timaginary64):
-	case X(Tint16,Timaginary80): goto Lzero;
-
-	/* ============================= */
-
-	case X(Tuns16,Tint8):
-	case X(Tuns16,Tuns8):	eop = OP16_8;	goto Leop;
-	case X(Tuns16,Tint16):	goto Lpaint;
-	case X(Tuns16,Tint32):
-	case X(Tuns16,Tuns32):	eop = OPu16_32;	goto Leop;
-	case X(Tuns16,Tint64):
-	case X(Tuns16,Tuns64):
-	case X(Tuns16,Tfloat64):
-	case X(Tuns16,Tfloat32):
-	case X(Tuns16,Tfloat80):
-	case X(Tuns16,Tcomplex32):
-	case X(Tuns16,Tcomplex64):
-	case X(Tuns16,Tcomplex80):
-				e = el_una(OPu16_32, TYuint, e);
-				fty = Tuns32;
-				goto Lagain;
-	case X(Tuns16,Timaginary32):
-	case X(Tuns16,Timaginary64):
-	case X(Tuns16,Timaginary80): goto Lzero;
-
-	/* ============================= */
-
-	case X(Tint32,Tint8):
-	case X(Tint32,Tuns8):	e = el_una(OP32_16, TYshort, e);
-				fty = Tint16;
-				goto Lagain;
-	case X(Tint32,Tint16):
-	case X(Tint32,Tuns16):	eop = OP32_16;	goto Leop;
-	case X(Tint32,Tuns32):	goto Lpaint;
-	case X(Tint32,Tint64):
-	case X(Tint32,Tuns64):	eop = OPs32_64;	goto Leop;
-	case X(Tint32,Tfloat32):
-	case X(Tint32,Tfloat64):
-	case X(Tint32,Tfloat80):
-	case X(Tint32,Tcomplex32):
-	case X(Tint32,Tcomplex64):
-	case X(Tint32,Tcomplex80):
-				e = el_una(OPs32_d, TYdouble, e);
-				fty = Tfloat64;
-				goto Lagain;
-	case X(Tint32,Timaginary32):
-	case X(Tint32,Timaginary64):
-	case X(Tint32,Timaginary80): goto Lzero;
-
-	/* ============================= */
-
-	case X(Tuns32,Tint8):
-	case X(Tuns32,Tuns8):	e = el_una(OP32_16, TYshort, e);
-				fty = Tuns16;
-				goto Lagain;
-	case X(Tuns32,Tint16):
-	case X(Tuns32,Tuns16):	eop = OP32_16;	goto Leop;
-	case X(Tuns32,Tint32):	goto Lpaint;
-	case X(Tuns32,Tint64):
-	case X(Tuns32,Tuns64):	eop = OPu32_64;	goto Leop;
-	case X(Tuns32,Tfloat32):
-	case X(Tuns32,Tfloat64):
-	case X(Tuns32,Tfloat80):
-	case X(Tuns32,Tcomplex32):
-	case X(Tuns32,Tcomplex64):
-	case X(Tuns32,Tcomplex80):
-				e = el_una(OPu32_d, TYdouble, e);
-				fty = Tfloat64;
-				goto Lagain;
-	case X(Tuns32,Timaginary32):
-	case X(Tuns32,Timaginary64):
-	case X(Tuns32,Timaginary80): goto Lzero;
-
-	/* ============================= */
-
-	case X(Tint64,Tint8):
-	case X(Tint64,Tuns8):
-	case X(Tint64,Tint16):
-	case X(Tint64,Tuns16):	e = el_una(OP64_32, TYint, e);
-				fty = Tint32;
-				goto Lagain;
-	case X(Tint64,Tint32):
-	case X(Tint64,Tuns32):	eop = OP64_32; goto Leop;
-	case X(Tint64,Tuns64):	goto Lpaint;
-	case X(Tint64,Tfloat32):
-	case X(Tint64,Tfloat64):
-	case X(Tint64,Tfloat80):
-	case X(Tint64,Tcomplex32):
-	case X(Tint64,Tcomplex64):
-	case X(Tint64,Tcomplex80):
-				e = el_una(OPs64_d, TYdouble, e);
-				fty = Tfloat64;
-				goto Lagain;
-	case X(Tint64,Timaginary32):
-	case X(Tint64,Timaginary64):
-	case X(Tint64,Timaginary80): goto Lzero;
-
-	/* ============================= */
-
-	case X(Tuns64,Tint8):
-	case X(Tuns64,Tuns8):
-	case X(Tuns64,Tint16):
-	case X(Tuns64,Tuns16):	e = el_una(OP64_32, TYint, e);
-				fty = Tint32;
-				goto Lagain;
-	case X(Tuns64,Tint32):
-	case X(Tuns64,Tuns32):	eop = OP64_32;	goto Leop;
-	case X(Tuns64,Tint64):	goto Lpaint;
-	case X(Tuns64,Tfloat32):
-	case X(Tuns64,Tfloat64):
-	case X(Tuns64,Tfloat80):
-	case X(Tuns64,Tcomplex32):
-	case X(Tuns64,Tcomplex64):
-	case X(Tuns64,Tcomplex80):
-				 e = el_una(OPu64_d, TYdouble, e);
-				 fty = Tfloat64;
-				 goto Lagain;
-	case X(Tuns64,Timaginary32):
-	case X(Tuns64,Timaginary64):
-	case X(Tuns64,Timaginary80): goto Lzero;
-
-	/* ============================= */
-
-	case X(Tfloat32,Tint8):
-	case X(Tfloat32,Tuns8):
-	case X(Tfloat32,Tint16):
-	case X(Tfloat32,Tuns16):
-	case X(Tfloat32,Tint32):
-	case X(Tfloat32,Tuns32):
-	case X(Tfloat32,Tint64):
-	case X(Tfloat32,Tuns64):
-	case X(Tfloat32,Tfloat80): e = el_una(OPf_d, TYdouble, e);
-				   fty = Tfloat64;
-				   goto Lagain;
-	case X(Tfloat32,Tfloat64): eop = OPf_d;	goto Leop;
-	case X(Tfloat32,Timaginary32): goto Lzero;
-	case X(Tfloat32,Timaginary64): goto Lzero;
-	case X(Tfloat32,Timaginary80): goto Lzero;
-	case X(Tfloat32,Tcomplex32):
-	case X(Tfloat32,Tcomplex64):
-	case X(Tfloat32,Tcomplex80):
-	    e = el_bin(OPadd,TYcfloat,el_long(TYifloat,0),e);
-	    fty = Tcomplex32;
-	    goto Lagain;
-
-	/* ============================= */
-
-	case X(Tfloat64,Tint8):
-	case X(Tfloat64,Tuns8):    e = el_una(OPd_s16, TYshort, e);
-				   fty = Tint16;
-				   goto Lagain;
-	case X(Tfloat64,Tint16):   eop = OPd_s16; goto Leop;
-	case X(Tfloat64,Tuns16):   eop = OPd_u16; goto Leop;
-	case X(Tfloat64,Tint32):   eop = OPd_s32; goto Leop;
-	case X(Tfloat64,Tuns32):   eop = OPd_u32; goto Leop;
-	case X(Tfloat64,Tint64):   eop = OPd_s64; goto Leop;
-	case X(Tfloat64,Tuns64):   eop = OPd_u64; goto Leop;
-	case X(Tfloat64,Tfloat32): eop = OPd_f;   goto Leop;
-	case X(Tfloat64,Tfloat80): eop = OPd_ld;  goto Leop;
-	case X(Tfloat64,Timaginary32):	goto Lzero;
-	case X(Tfloat64,Timaginary64):	goto Lzero;
-	case X(Tfloat64,Timaginary80):	goto Lzero;
-	case X(Tfloat64,Tcomplex32):
-	case X(Tfloat64,Tcomplex64):
-	case X(Tfloat64,Tcomplex80):
-	    e = el_bin(OPadd,TYcfloat,el_long(TYidouble,0),e);
-	    fty = Tcomplex64;
-	    goto Lagain;
-
-	/* ============================= */
-
-	case X(Tfloat80,Tint8):
-	case X(Tfloat80,Tuns8):
-	case X(Tfloat80,Tint16):
-	case X(Tfloat80,Tuns16):
-	case X(Tfloat80,Tint32):
-	case X(Tfloat80,Tuns32):
-	case X(Tfloat80,Tint64):
-	case X(Tfloat80,Tuns64):
-	case X(Tfloat80,Tfloat32): e = el_una(OPld_d, TYdouble, e);
-				   fty = Tfloat64;
-				   goto Lagain;
-	case X(Tfloat80,Tfloat64): eop = OPld_d; goto Leop;
-	case X(Tfloat80,Timaginary32): goto Lzero;
-	case X(Tfloat80,Timaginary64): goto Lzero;
-	case X(Tfloat80,Timaginary80): goto Lzero;
-	case X(Tfloat80,Tcomplex32):
-	case X(Tfloat80,Tcomplex64):
-	case X(Tfloat80,Tcomplex80):
-	    e = el_bin(OPadd,TYcldouble,e,el_long(TYildouble,0));
-	    fty = Tcomplex80;
-	    goto Lagain;
-
-	/* ============================= */
-
-	case X(Timaginary32,Tint8):
-	case X(Timaginary32,Tuns8):
-	case X(Timaginary32,Tint16):
-	case X(Timaginary32,Tuns16):
-	case X(Timaginary32,Tint32):
-	case X(Timaginary32,Tuns32):
-	case X(Timaginary32,Tint64):
-	case X(Timaginary32,Tuns64):
-	case X(Timaginary32,Tfloat32):
-	case X(Timaginary32,Tfloat64):
-	case X(Timaginary32,Tfloat80):	goto Lzero;
-	case X(Timaginary32,Timaginary64): eop = OPf_d;	goto Leop;
-	case X(Timaginary32,Timaginary80):
-				   e = el_una(OPf_d, TYidouble, e);
-				   fty = Timaginary64;
-				   goto Lagain;
-	case X(Timaginary32,Tcomplex32):
-	case X(Timaginary32,Tcomplex64):
-	case X(Timaginary32,Tcomplex80):
-	    e = el_bin(OPadd,TYcfloat,el_long(TYfloat,0),e);
-	    fty = Tcomplex32;
-	    goto Lagain;
-
-	/* ============================= */
-
-	case X(Timaginary64,Tint8):
-	case X(Timaginary64,Tuns8):
-	case X(Timaginary64,Tint16):
-	case X(Timaginary64,Tuns16):
-	case X(Timaginary64,Tint32):
-	case X(Timaginary64,Tuns32):
-	case X(Timaginary64,Tint64):
-	case X(Timaginary64,Tuns64):
-	case X(Timaginary64,Tfloat32):
-	case X(Timaginary64,Tfloat64):
-	case X(Timaginary64,Tfloat80):	goto Lzero;
-	case X(Timaginary64,Timaginary32): eop = OPd_f;   goto Leop;
-	case X(Timaginary64,Timaginary80): eop = OPd_ld;  goto Leop;
-	case X(Timaginary64,Tcomplex32):
-	case X(Timaginary64,Tcomplex64):
-	case X(Timaginary64,Tcomplex80):
-	    e = el_bin(OPadd,TYcdouble,el_long(TYdouble,0),e);
-	    fty = Tcomplex64;
-	    goto Lagain;
-
-	/* ============================= */
-
-	case X(Timaginary80,Tint8):
-	case X(Timaginary80,Tuns8):
-	case X(Timaginary80,Tint16):
-	case X(Timaginary80,Tuns16):
-	case X(Timaginary80,Tint32):
-	case X(Timaginary80,Tuns32):
-	case X(Timaginary80,Tint64):
-	case X(Timaginary80,Tuns64):
-	case X(Timaginary80,Tfloat32):
-	case X(Timaginary80,Tfloat64):
-	case X(Timaginary80,Tfloat80):	goto Lzero;
-	case X(Timaginary80,Timaginary32): e = el_una(OPf_d, TYidouble, e);
-				   fty = Timaginary64;
-				   goto Lagain;
-	case X(Timaginary80,Timaginary64): eop = OPld_d; goto Leop;
-	case X(Timaginary80,Tcomplex32):
-	case X(Timaginary80,Tcomplex64):
-	case X(Timaginary80,Tcomplex80):
-	    e = el_bin(OPadd,TYcldouble,el_long(TYldouble,0),e);
-	    fty = Tcomplex80;
-	    goto Lagain;
-
-	/* ============================= */
-
-	case X(Tcomplex32,Tint8):
-	case X(Tcomplex32,Tuns8):
-	case X(Tcomplex32,Tint16):
-	case X(Tcomplex32,Tuns16):
-	case X(Tcomplex32,Tint32):
-	case X(Tcomplex32,Tuns32):
-	case X(Tcomplex32,Tint64):
-	case X(Tcomplex32,Tuns64):
-	case X(Tcomplex32,Tfloat32):
-	case X(Tcomplex32,Tfloat64):
-	case X(Tcomplex32,Tfloat80):
-		e = el_una(OPc_r, TYfloat, e);
-		fty = Tfloat32;
-		goto Lagain;
-	case X(Tcomplex32,Timaginary32):
-	case X(Tcomplex32,Timaginary64):
-	case X(Tcomplex32,Timaginary80):
-		e = el_una(OPc_i, TYifloat, e);
-		fty = Timaginary32;
-		goto Lagain;
-	case X(Tcomplex32,Tcomplex64):
-	case X(Tcomplex32,Tcomplex80):
-		e = el_una(OPf_d, TYcdouble, e);
-		fty = Tcomplex64;
-		goto Lagain;
-
-	/* ============================= */
-
-	case X(Tcomplex64,Tint8):
-	case X(Tcomplex64,Tuns8):
-	case X(Tcomplex64,Tint16):
-	case X(Tcomplex64,Tuns16):
-	case X(Tcomplex64,Tint32):
-	case X(Tcomplex64,Tuns32):
-	case X(Tcomplex64,Tint64):
-	case X(Tcomplex64,Tuns64):
-	case X(Tcomplex64,Tfloat32):
-	case X(Tcomplex64,Tfloat64):
-	case X(Tcomplex64,Tfloat80):
-		e = el_una(OPc_r, TYdouble, e);
-		fty = Tfloat64;
-		goto Lagain;
-	case X(Tcomplex64,Timaginary32):
-	case X(Tcomplex64,Timaginary64):
-	case X(Tcomplex64,Timaginary80):
-		e = el_una(OPc_i, TYidouble, e);
-		fty = Timaginary64;
-		goto Lagain;
-	case X(Tcomplex64,Tcomplex32):	 eop = OPd_f;	goto Leop;
-	case X(Tcomplex64,Tcomplex80):	 eop = OPd_ld;	goto Leop;
-
-	/* ============================= */
-
-	case X(Tcomplex80,Tint8):
-	case X(Tcomplex80,Tuns8):
-	case X(Tcomplex80,Tint16):
-	case X(Tcomplex80,Tuns16):
-	case X(Tcomplex80,Tint32):
-	case X(Tcomplex80,Tuns32):
-	case X(Tcomplex80,Tint64):
-	case X(Tcomplex80,Tuns64):
-	case X(Tcomplex80,Tfloat32):
-	case X(Tcomplex80,Tfloat64):
-	case X(Tcomplex80,Tfloat80):
-		e = el_una(OPc_r, TYldouble, e);
-		fty = Tfloat80;
-		goto Lagain;
-	case X(Tcomplex80,Timaginary32):
-	case X(Tcomplex80,Timaginary64):
-	case X(Tcomplex80,Timaginary80):
-		e = el_una(OPc_i, TYildouble, e);
-		fty = Timaginary80;
-		goto Lagain;
-	case X(Tcomplex80,Tcomplex32):
-	case X(Tcomplex80,Tcomplex64):
-		e = el_una(OPld_d, TYcdouble, e);
-		fty = Tcomplex64;
-		goto Lagain;
-
-	/* ============================= */
-
-	default:
-	    if (fty == tty)
-		goto Lpaint;
-	    //dump(0);
-	    //printf("fty = %d, tty = %d\n", fty, tty);
-	    error("e2ir: cannot cast from %s to %s", e1->type->toChars(), t->toChars());
-	    goto Lzero;
-
-	Lzero:
-	    e = el_long(ttym, 0);
-	    break;
-
-	Lpaint:
-	    e->Ety = ttym;
-	    break;
-
-	Leop:
-	    e = el_una(eop, ttym, e);
-	    break;
-    }
-Lret:
-    // Adjust for any type paints
-    t = type->toBasetype();
-    e->Ety = t->totym();
-
-    el_setLoc(e,loc);
-    return e;
-}
-
-elem *ArrayLengthExp::toElem(IRState *irs)
-{
-    elem *e = e1->toElem(irs);
-    e = el_una(OP64_32, type->totym(), e);
-    el_setLoc(e,loc);
-    return e;
-}
-
-elem *SliceExp::toElem(IRState *irs)
-{   elem *e;
-    Type *t1;
-
-    //printf("SliceExp::toElem()\n");
-    t1 = e1->type->toBasetype();
-    e = e1->toElem(irs);
-    if (lwr)
-    {	elem *elwr;
-	elem *elwr2;
-	elem *eupr;
-	elem *eptr;
-	elem *einit;
-	int sz;
-
-	einit = resolveLengthVar(lengthVar, &e, t1);
-
-	sz = t1->nextOf()->size();
-
-	elwr = lwr->toElem(irs);
-	eupr = upr->toElem(irs);
-
-	elwr2 = el_same(&elwr);
-
-	// Create an array reference where:
-	// length is (upr - lwr)
-	// pointer is (ptr + lwr*sz)
-	// Combine as (length pair ptr)
-
-	if (global.params.useArrayBounds)
-	{
-	    // Checks (unsigned compares):
-	    //	upr <= array.length
-	    //	lwr <= upr
-
-	    elem *c1;
-	    elem *c2;
-	    elem *ea;
-	    elem *eb;
-	    elem *eupr2;
-	    elem *elength;
-
-	    if (t1->ty == Tpointer)
-	    {
-		// Just do lwr <= upr check
-
-		eupr2 = el_same(&eupr);
-		eupr2->Ety = TYuint;			// make sure unsigned comparison
-		c1 = el_bin(OPle, TYint, elwr2, eupr2);
-		c1 = el_combine(eupr, c1);
-		goto L2;
-	    }
-	    else if (t1->ty == Tsarray)
-	    {	TypeSArray *tsa = (TypeSArray *)t1;
-		integer_t length = tsa->dim->toInteger();
-
-		elength = el_long(TYuint, length);
-		goto L1;
-	    }
-	    else if (t1->ty == Tarray)
-	    {
-		if (lengthVar)
-		    elength = el_var(lengthVar->toSymbol());
-		else
-		{
-		    elength = e;
-		    e = el_same(&elength);
-		    elength = el_una(OP64_32, TYuint, elength);
-		}
-	    L1:
-		eupr2 = el_same(&eupr);
-		c1 = el_bin(OPle, TYint, eupr, elength);
-		eupr2->Ety = TYuint;			// make sure unsigned comparison
-		c2 = el_bin(OPle, TYint, elwr2, eupr2);
-		c1 = el_bin(OPandand, TYint, c1, c2);	// (c1 && c2)
-
-	    L2:
-		// Construct: (c1 || ModuleArray(line))
-		Symbol *sassert;
-
-		sassert = irs->blx->module->toModuleArray();
-		ea = el_bin(OPcall,TYvoid,el_var(sassert), el_long(TYint, loc.linnum));
-		eb = el_bin(OPoror,TYvoid,c1,ea);
-		elwr = el_combine(elwr, eb);
-
-		elwr2 = el_copytree(elwr2);
-		eupr = el_copytree(eupr2);
-	    }
-	}
-
-	eptr = array_toPtr(e1->type, e);
-
-	elem *elength = el_bin(OPmin, TYint, eupr, elwr2);
-	eptr = el_bin(OPadd, TYnptr, eptr, el_bin(OPmul, TYint, el_copytree(elwr2), el_long(TYint, sz)));
-
-	e = el_pair(TYullong, elength, eptr);
-	e = el_combine(elwr, e);
-	e = el_combine(einit, e);
-    }
-    else if (t1->ty == Tsarray)
-    {
-	e = sarray_toDarray(loc, t1, NULL, e);
-    }
-    el_setLoc(e,loc);
-    return e;
-}
-
-elem *IndexExp::toElem(IRState *irs)
-{   elem *e;
-    elem *n1 = e1->toElem(irs);
-    elem *n2;
-    elem *eb = NULL;
-    Type *t1;
-
-    //printf("IndexExp::toElem() %s\n", toChars());
-    t1 = e1->type->toBasetype();
-    if (t1->ty == Taarray)
-    {
-	// set to:
-	//	*aaGet(aa, keyti, valuesize, index);
-
-	TypeAArray *taa = (TypeAArray *)t1;
-	elem *keyti;
-	elem *ep;
-	int vsize = taa->next->size();
-	elem *valuesize;
-	Symbol *s;
-
-	// n2 becomes the index, also known as the key
-	n2 = e2->toElem(irs);
-	if (n2->Ety == TYstruct || n2->Ety == TYarray)
-	{
-	    n2 = el_una(OPstrpar, TYstruct, n2);
-	    n2->Enumbytes = n2->E1->Enumbytes;
-	    //printf("numbytes = %d\n", n2->Enumbytes);
-	    assert(n2->Enumbytes);
-	}
-	valuesize = el_long(TYuint, vsize);	// BUG: should be TYsize_t
-	//printf("valuesize: "); elem_print(valuesize);
-	if (modifiable)
-	{
-	    n1 = el_una(OPaddr, TYnptr, n1);
-	    s = taa->aaGetSymbol("Get", 1);
-	}
-	else
-	{
-	    s = taa->aaGetSymbol("GetRvalue", 1);
-	}
-	//printf("taa->index = %s\n", taa->index->toChars());
-	keyti = taa->index->getInternalTypeInfo(NULL)->toElem(irs);
-	//keyti = taa->index->getTypeInfo(NULL)->toElem(irs);
-	//printf("keyti:\n");
-	//elem_print(keyti);
-	ep = el_params(n2, valuesize, keyti, n1, NULL);
-	e = el_bin(OPcall, TYnptr, el_var(s), ep);
-	if (global.params.useArrayBounds)
-	{
-	    elem *n;
-	    elem *ea;
-
-	    n = el_same(&e);
-
-	    // Construct: ((e || ModuleAssert(line)),n)
-	    Symbol *sassert;
-
-	    sassert = irs->blx->module->toModuleArray();
-	    ea = el_bin(OPcall,TYvoid,el_var(sassert),
-		el_long(TYint, loc.linnum));
-	    e = el_bin(OPoror,TYvoid,e,ea);
-	    e = el_bin(OPcomma, TYnptr, e, n);
-	}
-	e = el_una(OPind, type->totym(), e);
-	if (tybasic(e->Ety) == TYstruct)
-	    e->Enumbytes = type->size();
-    }
-    else
-    {	elem *einit;
-
-	einit = resolveLengthVar(lengthVar, &n1, t1);
-	n2 = e2->toElem(irs);
-
-	if (global.params.useArrayBounds)
-	{
-	    elem *elength;
-	    elem *n2x;
-	    elem *ea;
-
-	    if (t1->ty == Tsarray)
-	    {	TypeSArray *tsa = (TypeSArray *)t1;
-		integer_t length = tsa->dim->toInteger();
-
-		elength = el_long(TYuint, length);
-		goto L1;
-	    }
-	    else if (t1->ty == Tarray)
-	    {
-		elength = n1;
-		n1 = el_same(&elength);
-		elength = el_una(OP64_32, TYuint, elength);
-	    L1:
-		n2x = n2;
-		n2 = el_same(&n2x);
-		n2x = el_bin(OPlt, TYint, n2x, elength);
-
-		// Construct: (n2x || ModuleAssert(line))
-		Symbol *sassert;
-
-		sassert = irs->blx->module->toModuleArray();
-		ea = el_bin(OPcall,TYvoid,el_var(sassert),
-		    el_long(TYint, loc.linnum));
-		eb = el_bin(OPoror,TYvoid,n2x,ea);
-	    }
-	}
-
-	n1 = array_toPtr(t1, n1);
-
-	{   elem *escale;
-
-	    escale = el_long(TYint, t1->nextOf()->size());
-	    n2 = el_bin(OPmul, TYint, n2, escale);
-	    e = el_bin(OPadd, TYnptr, n1, n2);
-	    e = el_una(OPind, type->totym(), e);
-	    if (tybasic(e->Ety) == TYstruct || tybasic(e->Ety) == TYarray)
-	    {	e->Ety = TYstruct;
-		e->Enumbytes = type->size();
-	    }
-	}
-
-	eb = el_combine(einit, eb);
-	e = el_combine(eb, e);
-    }
-    el_setLoc(e,loc);
-    return e;
-}
-
-
-elem *TupleExp::toElem(IRState *irs)
-{   elem *e = NULL;
-
-    //printf("TupleExp::toElem() %s\n", toChars());
-    for (size_t i = 0; i < exps->dim; i++)
-    {	Expression *el = (Expression *)exps->data[i];
-	elem *ep = el->toElem(irs);
-
-	e = el_combine(e, ep);
-    }
-    return e;
-}
-
-
-elem *ArrayLiteralExp::toElem(IRState *irs)
-{   elem *e;
-    size_t dim;
-
-    //printf("ArrayLiteralExp::toElem() %s\n", toChars());
-    if (elements)
-    {
-	dim = elements->dim;
-	e = el_long(TYint, dim);
-	for (size_t i = 0; i < dim; i++)
-	{   Expression *el = (Expression *)elements->data[i];
-	    elem *ep = el->toElem(irs);
-
-	    if (tybasic(ep->Ety) == TYstruct || tybasic(ep->Ety) == TYarray)
-	    {
-		ep = el_una(OPstrpar, TYstruct, ep);
-		ep->Enumbytes = el->type->size();
-	    }
-	    e = el_param(ep, e);
-	}
-    }
-    else
-    {	dim = 0;
-	e = el_long(TYint, 0);
-    }
-    Type *tb = type->toBasetype();
-#if 1
-    e = el_param(e, type->getTypeInfo(NULL)->toElem(irs));
-
-    // call _d_arrayliteralT(ti, dim, ...)
-    e = el_bin(OPcall,TYnptr,el_var(rtlsym[RTLSYM_ARRAYLITERALT]),e);
-#else
-    e = el_param(e, el_long(TYint, tb->next->size()));
-
-    // call _d_arrayliteral(size, dim, ...)
-    e = el_bin(OPcall,TYnptr,el_var(rtlsym[RTLSYM_ARRAYLITERAL]),e);
-#endif
-    if (tb->ty == Tarray)
-    {
-	e = el_pair(TYullong, el_long(TYint, dim), e);
-    }
-    else if (tb->ty == Tpointer)
-    {
-    }
-    else
-    {
-	e = el_una(OPind,TYstruct,e);
-	e->Enumbytes = type->size();
-    }
-
-    el_setLoc(e,loc);
-    return e;
-}
-
-
-elem *AssocArrayLiteralExp::toElem(IRState *irs)
-{   elem *e;
-    size_t dim;
-
-    //printf("AssocArrayLiteralExp::toElem() %s\n", toChars());
-    dim = keys->dim;
-    e = el_long(TYint, dim);
-    for (size_t i = 0; i < dim; i++)
-    {   Expression *el = (Expression *)keys->data[i];
-
-	for (int j = 0; j < 2; j++)
-	{
-	    elem *ep = el->toElem(irs);
-
-	    if (tybasic(ep->Ety) == TYstruct || tybasic(ep->Ety) == TYarray)
-	    {
-		ep = el_una(OPstrpar, TYstruct, ep);
-		ep->Enumbytes = el->type->size();
-	    }
-//printf("[%d] %s\n", i, el->toChars());
-//elem_print(ep);
-	    e = el_param(ep, e);
-	    el = (Expression *)values->data[i];
-	}
-    }
-
-    Type *t = type->toBasetype()->mutableOf();
-    assert(t->ty == Taarray);
-    TypeAArray *ta = (TypeAArray *)t;
-
-    /* Unfortunately, the hash function for Aa (array of chars) is custom and
-     * different from Axa and Aya, which get the generic hash function.
-     * So, rewrite the type of the AArray so that if it's key type
-     * is an array of const or invariant, make it an array of mutable.
-     */
-    Type *tkey = ta->index->toBasetype();
-    if (tkey->ty == Tarray)
-    {
-	tkey = tkey->nextOf()->mutableOf()->arrayOf();
-	tkey = tkey->semantic(0, NULL);
-	ta = new TypeAArray(ta->nextOf(), tkey);
-	ta = (TypeAArray *)ta->merge();
-    }
-
-    e = el_param(e, ta->getTypeInfo(NULL)->toElem(irs));
-
-    // call _d_assocarrayliteralT(ti, dim, ...)
-    e = el_bin(OPcall,TYnptr,el_var(rtlsym[RTLSYM_ASSOCARRAYLITERALT]),e);
-
-    el_setLoc(e,loc);
-    return e;
-}
-
-
-/*******************************************
- * Generate elem to zero fill contents of Symbol stmp
- * from *poffset..offset2.
- * May store anywhere from 0..maxoff, as this function
- * tries to use aligned int stores whereever possible.
- * Update *poffset to end of initialized hole; *poffset will be >= offset2.
- */
-
-elem *fillHole(Symbol *stmp, size_t *poffset, size_t offset2, size_t maxoff)
-{   elem *e = NULL;
-    int basealign = 1;
-
-    while (*poffset < offset2)
-    {   tym_t ty;
-	elem *e1;
-
-	if (tybasic(stmp->Stype->Tty) == TYnptr)
-	    e1 = el_var(stmp);
-	else
-	    e1 = el_ptr(stmp);
-	if (basealign)
-	    *poffset &= ~3;
-	basealign = 1;
-	size_t sz = maxoff - *poffset;
-	switch (sz)
-	{   case 1: ty = TYchar;	break;
-	    case 2: ty = TYshort;	break;
-	    case 3:
-		ty = TYshort;
-		basealign = 0;
-		break;
-	    default:
-		ty = TYlong;
-		break;
-	}
-	e1 = el_bin(OPadd, TYnptr, e1, el_long(TYsize_t, *poffset));
-	e1 = el_una(OPind, ty, e1);
-	e1 = el_bin(OPeq, ty, e1, el_long(ty, 0));
-	e = el_combine(e, e1);
-	*poffset += tysize[ty];
-    }
-    return e;
-}
-
-elem *StructLiteralExp::toElem(IRState *irs)
-{   elem *e;
-    size_t dim;
-
-    //printf("StructLiteralExp::toElem() %s\n", toChars());
-
-    // struct symbol to initialize with the literal
-    Symbol *stmp = sym ? sym : symbol_genauto(sd->type->toCtype());
-
-    e = NULL;
-
-    if (fillHoles)
-    {
-	/* Initialize all alignment 'holes' to zero.
-	 * Do before initializing fields, as the hole filling process
-	 * can spill over into the fields.
-	 */
-	size_t offset = 0;
-	for (size_t i = 0; i < sd->fields.dim; i++)
-	{
-	    Dsymbol *s = (Dsymbol *)sd->fields.data[i];
-	    VarDeclaration *v = s->isVarDeclaration();
-	    assert(v);
-
-	    e = el_combine(e, fillHole(stmp, &offset, v->offset, sd->structsize));
-	    size_t vend = v->offset + v->type->size();
-	    if (offset < vend)
-		offset = vend;
-	}
-	e = el_combine(e, fillHole(stmp, &offset, sd->structsize, sd->structsize));
-    }
-
-    if (elements)
-    {
-	dim = elements->dim;
-	assert(dim <= sd->fields.dim);
-	for (size_t i = 0; i < dim; i++)
-	{   Expression *el = (Expression *)elements->data[i];
-	    if (!el)
-		continue;
-
-	    Dsymbol *s = (Dsymbol *)sd->fields.data[i];
-	    VarDeclaration *v = s->isVarDeclaration();
-	    assert(v);
-
-	    elem *e1;
-	    if (tybasic(stmp->Stype->Tty) == TYnptr)
-	    {	e1 = el_var(stmp);
-		e1->EV.sp.Voffset = soffset;
-	    }
-	    else
-	    {	e1 = el_ptr(stmp);
-		if (soffset)
-		    e1 = el_bin(OPadd, TYnptr, e1, el_long(TYsize_t, soffset));
-	    }
-	    e1 = el_bin(OPadd, TYnptr, e1, el_long(TYsize_t, v->offset));
-	    elem *ec = e1;			// pointer to destination
-
-	    elem *ep = el->toElem(irs);
-
-	    Type *t1b = v->type->toBasetype();
-	    Type *t2b = el->type->toBasetype();
-	    if (t1b->ty == Tsarray)
-	    {
-		if (t2b->implicitConvTo(t1b))
-		{
-#if DMDV2
-		    // Determine if postblit is needed
-		    int postblit = 0;
-		    Type *t = t1b;
-		    do
-		    {
-			t = t->nextOf()->toBasetype();
-		    } while (t->ty == Tsarray);
-		    if (t->ty == Tstruct)
-		    {	StructDeclaration *sd = ((TypeStruct *)t)->sym;
-			if (sd->postblit)
-			    postblit = 1;
-		    }
-
-		    if (postblit)
-		    {
-			/* Generate:
-			 *	_d_arrayctor(ti, From: ep, To: e1)
-			 */
-			Expression *ti = t1b->nextOf()->toBasetype()->getTypeInfo(NULL);
-			elem *esize = el_long(TYsize_t, ((TypeSArray *)t1b)->dim->toInteger());
-			e1 = el_pair(TYdarray, esize, e1);
-			ep = el_pair(TYdarray, el_copytree(esize), array_toPtr(el->type, ep));
-			ep = el_params(e1, ep, ti->toElem(irs), NULL);
-			int rtl = RTLSYM_ARRAYCTOR;
-			e1 = el_bin(OPcall, type->totym(), el_var(rtlsym[rtl]), ep);
-		    }
-		    else
-#endif
-		    {
-			elem *esize = el_long(TYsize_t, t1b->size());
-			ep = array_toPtr(el->type, ep);
-			e1 = el_bin(OPmemcpy, TYnptr, e1, el_param(ep, esize));
-		    }
-		}
-		else
-		{
-		    elem *edim = el_long(TYsize_t, t1b->size() / t2b->size());
-		    e1 = setArray(e1, edim, t2b, ep, irs, TOKconstruct);
-		}
-	    }
-	    else
-	    {
-		tym_t ty = v->type->totym();
-		e1 = el_una(OPind, ty, e1);
-		if (ty == TYstruct)
-		    e1->Enumbytes = v->type->size();
-		e1 = el_bin(OPeq, ty, e1, ep);
-		if (ty == TYstruct)
-		{   e1->Eoper = OPstreq;
-		    e1->Enumbytes = v->type->size();
-		}
-#if DMDV2
-		/* Call postBlit() on e1
-		 */
-		Type *tb = v->type->toBasetype();
-		if (tb->ty == Tstruct)
-		{   StructDeclaration *sd = ((TypeStruct *)tb)->sym;
-		    if (sd->postblit)
-		    {	FuncDeclaration *fd = sd->postblit;
-			ec = el_copytree(ec);
-			ec = callfunc(loc, irs, 1, Type::tvoid, ec, tb->pointerTo(), fd, fd->type, NULL, NULL);
-			e1 = el_bin(OPcomma, ec->Ety, e1, ec);
-		    }
-		}
-#endif
-	    }
-	    e = el_combine(e, e1);
-	}
-    }
-
-    elem *ev = el_var(stmp);
-    ev->Enumbytes = sd->structsize;
-    e = el_combine(e, ev);
-    el_setLoc(e,loc);
-    return e;
-}
--- a/dmd2/entity.c	Mon Jun 01 01:28:18 2009 +0200
+++ b/dmd2/entity.c	Mon Jun 01 19:02:20 2009 +0100
@@ -1,5 +1,5 @@
 
-// Copyright (c) 1999-2008 by Digital Mars
+// Copyright (c) 1999-2009 by Digital Mars
 // All Rights Reserved
 // written by Walter Bright
 // http://www.digitalmars.com
--- a/dmd2/enum.c	Mon Jun 01 01:28:18 2009 +0200
+++ b/dmd2/enum.c	Mon Jun 01 19:02:20 2009 +0100
@@ -30,7 +30,9 @@
     maxval = NULL;
     minval = NULL;
     defaultval = NULL;
+#if IN_DMD
     sinit = NULL;
+#endif
     scope = NULL;
     isdeprecated = 0;
 }
--- a/dmd2/enum.h	Mon Jun 01 01:28:18 2009 +0200
+++ b/dmd2/enum.h	Mon Jun 01 19:02:20 2009 +0100
@@ -1,90 +1,96 @@
-
-// Compiler implementation of the D programming language
-// Copyright (c) 1999-2008 by Digital Mars
-// All Rights Reserved
-// written by Walter Bright
-// http://www.digitalmars.com
-// License for redistribution is by either the Artistic License
-// in artistic.txt, or the GNU General Public License in gnu.txt.
-// See the included readme.txt for details.
-
-#ifndef DMD_ENUM_H
-#define DMD_ENUM_H
-
-#ifdef __DMC__
-#pragma once
-#endif /* __DMC__ */
-
-#include "root.h"
-#include "dsymbol.h"
-
-struct Identifier;
-struct Type;
-struct Expression;
-#ifdef _DH
-struct HdrGenState;
-#endif
-
-
-struct EnumDeclaration : ScopeDsymbol
-{   /* enum ident : memtype { ... }
-     */
-    Type *type;			// the TypeEnum
-    Type *memtype;		// type of the members
-
-#if DMDV1
-    integer_t maxval;
-    integer_t minval;
-    integer_t defaultval;	// default initializer
-#else
-    Expression *maxval;
-    Expression *minval;
-    Expression *defaultval;	// default initializer
-
-    Scope *scope;		// !=NULL means context to use
-#endif
-    int isdeprecated;
-
-    EnumDeclaration(Loc loc, Identifier *id, Type *memtype);
-    Dsymbol *syntaxCopy(Dsymbol *s);
-    void semantic(Scope *sc);
-    int oneMember(Dsymbol **ps);
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-    Type *getType();
-    const char *kind();
-#if DMDV2
-    Dsymbol *search(Loc, Identifier *ident, int flags);
-#endif
-    int isDeprecated();			// is Dsymbol deprecated?
-
-    void emitComment(Scope *sc);
-    void toDocBuffer(OutBuffer *buf);
-
-    EnumDeclaration *isEnumDeclaration() { return this; }
-
-    void toObjFile(int multiobj);			// compile to .obj file
-    void toDebug();
-    int cvMember(unsigned char *p);
-
-    Symbol *sinit;
-    Symbol *toInitializer();
-};
-
-
-struct EnumMember : Dsymbol
-{
-    Expression *value;
-    Type *type;
-
-    EnumMember(Loc loc, Identifier *id, Expression *value, Type *type);
-    Dsymbol *syntaxCopy(Dsymbol *s);
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-    const char *kind();
-
-    void emitComment(Scope *sc);
-    void toDocBuffer(OutBuffer *buf);
-
-    EnumMember *isEnumMember() { return this; }
-};
-
-#endif /* DMD_ENUM_H */
+
+// Compiler implementation of the D programming language
+// Copyright (c) 1999-2008 by Digital Mars
+// All Rights Reserved
+// written by Walter Bright
+// http://www.digitalmars.com
+// License for redistribution is by either the Artistic License
+// in artistic.txt, or the GNU General Public License in gnu.txt.
+// See the included readme.txt for details.
+
+#ifndef DMD_ENUM_H
+#define DMD_ENUM_H
+
+#ifdef __DMC__
+#pragma once
+#endif /* __DMC__ */
+
+#include "root.h"
+#include "dsymbol.h"
+
+struct Identifier;
+struct Type;
+struct Expression;
+#ifdef _DH
+struct HdrGenState;
+#endif
+
+
+struct EnumDeclaration : ScopeDsymbol
+{   /* enum ident : memtype { ... }
+     */
+    Type *type;			// the TypeEnum
+    Type *memtype;		// type of the members
+
+#if DMDV1
+    dinteger_t maxval;
+    dinteger_t minval;
+    dinteger_t defaultval;	// default initializer
+#else
+    Expression *maxval;
+    Expression *minval;
+    Expression *defaultval;	// default initializer
+
+    Scope *scope;		// !=NULL means context to use
+#endif
+    int isdeprecated;
+
+    EnumDeclaration(Loc loc, Identifier *id, Type *memtype);
+    Dsymbol *syntaxCopy(Dsymbol *s);
+    void semantic(Scope *sc);
+    int oneMember(Dsymbol **ps);
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+    Type *getType();
+    const char *kind();
+#if DMDV2
+    Dsymbol *search(Loc, Identifier *ident, int flags);
+#endif
+    int isDeprecated();			// is Dsymbol deprecated?
+
+    void emitComment(Scope *sc);
+    void toDocBuffer(OutBuffer *buf);
+
+    EnumDeclaration *isEnumDeclaration() { return this; }
+
+#if IN_DMD
+    void toObjFile(int multiobj);			// compile to .obj file
+    void toDebug();
+    int cvMember(unsigned char *p);
+
+    Symbol *sinit;
+    Symbol *toInitializer();
+#endif
+
+#if IN_LLVM
+    void codegen(Ir*);
+#endif
+};
+
+
+struct EnumMember : Dsymbol
+{
+    Expression *value;
+    Type *type;
+
+    EnumMember(Loc loc, Identifier *id, Expression *value, Type *type);
+    Dsymbol *syntaxCopy(Dsymbol *s);
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+    const char *kind();
+
+    void emitComment(Scope *sc);
+    void toDocBuffer(OutBuffer *buf);
+
+    EnumMember *isEnumMember() { return this; }
+};
+
+#endif /* DMD_ENUM_H */
--- a/dmd2/expression.c	Mon Jun 01 01:28:18 2009 +0200
+++ b/dmd2/expression.c	Mon Jun 01 19:02:20 2009 +0100
@@ -1,9754 +1,10129 @@
-
-// 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 <stdlib.h>
-#include <ctype.h>
-#include <assert.h>
-#if _MSC_VER
-#include <complex>
-#else
-#endif
-#include <math.h>
-
-#if _WIN32 && __DMC__
-extern "C" char * __cdecl __locale_decpoint;
-#endif
-
-#if __MINGW32__
-#ifndef isnan
-#define isnan _isnan
-#endif
-#endif
-
-#ifdef __APPLE__
-#ifndef isnan
-int isnan(double);
-#endif
-#endif
-
-#if IN_GCC
-// Issues with using -include total.h (defines integer_t) and then complex.h fails...
-#undef integer_t
-#endif
-
-#ifdef __APPLE__
-#define integer_t dmd_integer_t
-#endif
-
-#if IN_GCC || IN_LLVM
-#include "mem.h"
-#elif _WIN32
-#include "..\root\mem.h"
-#elif POSIX
-#include "../root/mem.h"
-#endif
-
-//#include "port.h"
-#include "mtype.h"
-#include "init.h"
-#include "expression.h"
-#include "template.h"
-#include "utf.h"
-#include "enum.h"
-#include "scope.h"
-#include "statement.h"
-#include "declaration.h"
-#include "aggregate.h"
-#include "import.h"
-#include "id.h"
-#include "dsymbol.h"
-#include "module.h"
-#include "attrib.h"
-#include "hdrgen.h"
-#include "parse.h"
-
-Expression *createTypeInfoArray(Scope *sc, Expression *args[], int dim);
-Expression *expandVar(int result, VarDeclaration *v);
-
-#define LOGSEMANTIC	0
-
-/**********************************
- * Set operator precedence for each operator.
- */
-
-// Operator precedence - greater values are higher precedence
-
-enum PREC
-{
-    PREC_zero,
-    PREC_expr,
-    PREC_assign,
-    PREC_cond,
-    PREC_oror,
-    PREC_andand,
-    PREC_or,
-    PREC_xor,
-    PREC_and,
-    PREC_equal,
-    PREC_rel,
-    PREC_shift,
-    PREC_add,
-    PREC_mul,
-    PREC_unary,
-    PREC_primary,
-};
-
-enum PREC precedence[TOKMAX];
-
-void initPrecedence()
-{
-    precedence[TOKdotvar] = PREC_primary;
-    precedence[TOKimport] = PREC_primary;
-    precedence[TOKidentifier] = PREC_primary;
-    precedence[TOKthis] = PREC_primary;
-    precedence[TOKsuper] = PREC_primary;
-    precedence[TOKint64] = PREC_primary;
-    precedence[TOKfloat64] = PREC_primary;
-    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;
-    precedence[TOKfunction] = PREC_primary;
-    precedence[TOKvar] = PREC_primary;
-#if DMDV2
-    precedence[TOKdefault] = PREC_primary;
-#endif
-
-    // post
-    precedence[TOKdotti] = PREC_primary;
-    precedence[TOKdot] = PREC_primary;
-//  precedence[TOKarrow] = PREC_primary;
-    precedence[TOKplusplus] = PREC_primary;
-    precedence[TOKminusminus] = PREC_primary;
-    precedence[TOKcall] = PREC_primary;
-    precedence[TOKslice] = PREC_primary;
-    precedence[TOKarray] = PREC_primary;
-
-    precedence[TOKaddress] = PREC_unary;
-    precedence[TOKstar] = PREC_unary;
-    precedence[TOKneg] = PREC_unary;
-    precedence[TOKuadd] = PREC_unary;
-    precedence[TOKnot] = PREC_unary;
-    precedence[TOKtobool] = PREC_add;
-    precedence[TOKtilde] = PREC_unary;
-    precedence[TOKdelete] = PREC_unary;
-    precedence[TOKnew] = PREC_unary;
-    precedence[TOKcast] = PREC_unary;
-
-    precedence[TOKmul] = PREC_mul;
-    precedence[TOKdiv] = PREC_mul;
-    precedence[TOKmod] = PREC_mul;
-
-    precedence[TOKadd] = PREC_add;
-    precedence[TOKmin] = PREC_add;
-    precedence[TOKcat] = PREC_add;
-
-    precedence[TOKshl] = PREC_shift;
-    precedence[TOKshr] = PREC_shift;
-    precedence[TOKushr] = PREC_shift;
-
-    precedence[TOKlt] = PREC_rel;
-    precedence[TOKle] = PREC_rel;
-    precedence[TOKgt] = PREC_rel;
-    precedence[TOKge] = PREC_rel;
-    precedence[TOKunord] = PREC_rel;
-    precedence[TOKlg] = PREC_rel;
-    precedence[TOKleg] = PREC_rel;
-    precedence[TOKule] = PREC_rel;
-    precedence[TOKul] = PREC_rel;
-    precedence[TOKuge] = PREC_rel;
-    precedence[TOKug] = PREC_rel;
-    precedence[TOKue] = PREC_rel;
-    precedence[TOKin] = PREC_rel;
-
-    precedence[TOKequal] = PREC_equal;
-    precedence[TOKnotequal] = PREC_equal;
-    precedence[TOKidentity] = PREC_equal;
-    precedence[TOKnotidentity] = PREC_equal;
-
-    precedence[TOKand] = PREC_and;
-
-    precedence[TOKxor] = PREC_xor;
-
-    precedence[TOKor] = PREC_or;
-
-    precedence[TOKandand] = PREC_andand;
-
-    precedence[TOKoror] = PREC_oror;
-
-    precedence[TOKquestion] = PREC_cond;
-
-    precedence[TOKassign] = PREC_assign;
-    precedence[TOKconstruct] = PREC_assign;
-    precedence[TOKblit] = PREC_assign;
-    precedence[TOKaddass] = PREC_assign;
-    precedence[TOKminass] = PREC_assign;
-    precedence[TOKcatass] = PREC_assign;
-    precedence[TOKmulass] = PREC_assign;
-    precedence[TOKdivass] = PREC_assign;
-    precedence[TOKmodass] = PREC_assign;
-    precedence[TOKshlass] = PREC_assign;
-    precedence[TOKshrass] = PREC_assign;
-    precedence[TOKushrass] = PREC_assign;
-    precedence[TOKandass] = PREC_assign;
-    precedence[TOKorass] = PREC_assign;
-    precedence[TOKxorass] = PREC_assign;
-
-    precedence[TOKcomma] = PREC_expr;
-}
-
-/*************************************************************
- * Given var, we need to get the
- * right 'this' pointer if var is in an outer class, but our
- * existing 'this' pointer is in an inner class.
- * Input:
- *	e1	existing 'this'
- *	ad	struct or class we need the correct 'this' for
- *	var	the specific member of ad we're accessing
- */
-
-Expression *getRightThis(Loc loc, Scope *sc, AggregateDeclaration *ad,
-	Expression *e1, Declaration *var)
-{
-    //printf("\ngetRightThis(e1 = %s, ad = %s, var = %s)\n", e1->toChars(), ad->toChars(), var->toChars());
- L1:
-    Type *t = e1->type->toBasetype();
-    //printf("e1->type = %s, var->type = %s\n", e1->type->toChars(), var->type->toChars());
-
-    /* If e1 is not the 'this' pointer for ad
-     */
-    if (ad &&
-	!(t->ty == Tpointer && t->nextOf()->ty == Tstruct &&
-	  ((TypeStruct *)t->nextOf())->sym == ad)
-	&&
-	!(t->ty == Tstruct &&
-	  ((TypeStruct *)t)->sym == ad)
-       )
-    {
-	ClassDeclaration *cd = ad->isClassDeclaration();
-	ClassDeclaration *tcd = t->isClassHandle();
-
-	/* e1 is the right this if ad is a base class of e1
-	 */
-	if (!cd || !tcd ||
-	    !(tcd == cd || cd->isBaseOf(tcd, NULL))
-	   )
-	{
-	    /* Only classes can be inner classes with an 'outer'
-	     * member pointing to the enclosing class instance
-	     */
-	    if (tcd && tcd->isNested())
-	    {   /* e1 is the 'this' pointer for an inner class: tcd.
-		 * Rewrite it as the 'this' pointer for the outer class.
-		 */
-
-		e1 = new DotVarExp(loc, e1, tcd->vthis);
-		e1->type = tcd->vthis->type;
-		// Do not call checkNestedRef()
-		//e1 = e1->semantic(sc);
-
-		// Skip up over nested functions, and get the enclosing
-		// class type.
-		int n = 0;
-		Dsymbol *s;
-		for (s = tcd->toParent();
-		     s && s->isFuncDeclaration();
-		     s = s->toParent())
-		{   FuncDeclaration *f = s->isFuncDeclaration();
-		    if (f->vthis)
-		    {
-			//printf("rewriting e1 to %s's this\n", f->toChars());
-			n++;
-
-            // LDC seems dmd misses it sometimes here :/
-        #if DMDV2
-            // FIXME!!!!
-        #else
-            f->vthis->nestedref = 1;
-        #endif
-
-			e1 = new VarExp(loc, f->vthis);
-		    }
-		}
-		if (s && s->isClassDeclaration())
-		{   e1->type = s->isClassDeclaration()->type;
-		    if (n > 1)
-			e1 = e1->semantic(sc);
-		}
-		else
-		    e1 = e1->semantic(sc);
-		goto L1;
-	    }
-	    /* Can't find a path from e1 to ad
-	     */
-	    e1->error("this for %s needs to be type %s not type %s",
-		var->toChars(), ad->toChars(), t->toChars());
-	}
-    }
-    return e1;
-}
-
-/*****************************************
- * Determine if 'this' is available.
- * If it is, return the FuncDeclaration that has it.
- */
-
-FuncDeclaration *hasThis(Scope *sc)
-{   FuncDeclaration *fd;
-    FuncDeclaration *fdthis;
-
-    //printf("hasThis()\n");
-    fdthis = sc->parent->isFuncDeclaration();
-    //printf("fdthis = %p, '%s'\n", fdthis, fdthis ? fdthis->toChars() : "");
-
-    // Go upwards until we find the enclosing member function
-    fd = fdthis;
-    while (1)
-    {
-	if (!fd)
-	{
-	    goto Lno;
-	}
-	if (!fd->isNested())
-	    break;
-
-	Dsymbol *parent = fd->parent;
-	while (parent)
-	{
-	    TemplateInstance *ti = parent->isTemplateInstance();
-	    if (ti)
-		parent = ti->parent;
-	    else
-		break;
-	}
-
-	fd = fd->parent->isFuncDeclaration();
-    }
-
-    if (!fd->isThis())
-    {   //printf("test '%s'\n", fd->toChars());
-	goto Lno;
-    }
-
-    assert(fd->vthis);
-    return fd;
-
-Lno:
-    return NULL;		// don't have 'this' available
-}
-
-
-/***************************************
- * Pull out any properties.
- */
-
-Expression *resolveProperties(Scope *sc, Expression *e)
-{
-    //printf("resolveProperties(%s)\n", e->toChars());
-    if (e->type)
-    {
-	Type *t = e->type->toBasetype();
-
-	if (t->ty == Tfunction || e->op == TOKoverloadset)
-	{
-	    e = new CallExp(e->loc, e);
-	    e = e->semantic(sc);
-	}
-
-	/* Look for e being a lazy parameter; rewrite as delegate call
-	 */
-	else if (e->op == TOKvar)
-	{   VarExp *ve = (VarExp *)e;
-
-	    if (ve->var->storage_class & STClazy)
-	    {
-		e = new CallExp(e->loc, e);
-		e = e->semantic(sc);
-	    }
-	}
-
-	else if (e->op == TOKdotexp)
-	{
-	    e->error("expression has no value");
-	}
-
-    }
-    return e;
-}
-
-/******************************
- * Perform semantic() on an array of Expressions.
- */
-
-void arrayExpressionSemantic(Expressions *exps, Scope *sc)
-{
-    if (exps)
-    {
-	for (size_t i = 0; i < exps->dim; i++)
-	{   Expression *e = (Expression *)exps->data[i];
-
-	    e = e->semantic(sc);
-	    exps->data[i] = (void *)e;
-	}
-    }
-}
-
-
-/******************************
- * Perform canThrow() on an array of Expressions.
- */
-
-#if DMDV2
-int arrayExpressionCanThrow(Expressions *exps)
-{
-    if (exps)
-    {
-	for (size_t i = 0; i < exps->dim; i++)
-	{   Expression *e = (Expression *)exps->data[i];
-	    if (e && e->canThrow())
-		return 1;
-	}
-    }
-    return 0;
-}
-#endif
-
-/****************************************
- * Expand tuples.
- */
-
-void expandTuples(Expressions *exps)
-{
-    //printf("expandTuples()\n");
-    if (exps)
-    {
-	for (size_t i = 0; i < exps->dim; i++)
-	{   Expression *arg = (Expression *)exps->data[i];
-	    if (!arg)
-		continue;
-
-	    // Look for tuple with 0 members
-	    if (arg->op == TOKtype)
-	    {	TypeExp *e = (TypeExp *)arg;
-		if (e->type->toBasetype()->ty == Ttuple)
-		{   TypeTuple *tt = (TypeTuple *)e->type->toBasetype();
-
-		    if (!tt->arguments || tt->arguments->dim == 0)
-		    {
-			exps->remove(i);
-			if (i == exps->dim)
-			    return;
-			i--;
-			continue;
-		    }
-		}
-	    }
-
-	    // Inline expand all the tuples
-	    while (arg->op == TOKtuple)
-	    {	TupleExp *te = (TupleExp *)arg;
-
-		exps->remove(i);		// remove arg
-		exps->insert(i, te->exps);	// replace with tuple contents
-		if (i == exps->dim)
-		    return;		// empty tuple, no more arguments
-		arg = (Expression *)exps->data[i];
-	    }
-	}
-    }
-}
-
-/****************************************
- * Preprocess arguments to function.
- */
-
-void preFunctionArguments(Loc loc, Scope *sc, Expressions *exps)
-{
-    if (exps)
-    {
-	expandTuples(exps);
-
-	for (size_t i = 0; i < exps->dim; i++)
-	{   Expression *arg = (Expression *)exps->data[i];
-
-	    if (!arg->type)
-	    {
-#ifdef DEBUG
-		if (!global.gag)
-		    printf("1: \n");
-#endif
-		arg->error("%s is not an expression", arg->toChars());
-		arg = new IntegerExp(arg->loc, 0, Type::tint32);
-	    }
-
-	    arg = resolveProperties(sc, arg);
-	    exps->data[i] = (void *) arg;
-
-	    //arg->rvalue();
-#if 0
-	    if (arg->type->ty == Tfunction)
-	    {
-		arg = new AddrExp(arg->loc, arg);
-		arg = arg->semantic(sc);
-		exps->data[i] = (void *) arg;
-	    }
-#endif
-	}
-    }
-}
-
-/*********************************************
- * Call copy constructor for struct value argument.
- */
-#if DMDV2
-Expression *callCpCtor(Loc loc, Scope *sc, Expression *e)
-{
-    Type *tb = e->type->toBasetype();
-    assert(tb->ty == Tstruct);
-    StructDeclaration *sd = ((TypeStruct *)tb)->sym;
-    if (sd->cpctor)
-    {
-	/* Create a variable tmp, and replace the argument e with:
-	 *	(tmp = e),tmp
-	 * and let AssignExp() handle the construction.
-	 * This is not the most efficent, ideally tmp would be constructed
-	 * directly onto the stack.
-	 */
-	Identifier *idtmp = Lexer::uniqueId("__tmp");
-	VarDeclaration *tmp = new VarDeclaration(loc, tb, idtmp, new ExpInitializer(0, e));
-	Expression *ae = new DeclarationExp(loc, tmp);
-	e = new CommaExp(loc, ae, new VarExp(loc, tmp));
-	e = e->semantic(sc);
-    }
-    return e;
-}
-#endif
-
-/****************************************
- * Now that we know the exact type of the function we're calling,
- * the arguments[] need to be adjusted:
- *	1. implicitly convert argument to the corresponding parameter type
- *	2. add default arguments for any missing arguments
- *	3. do default promotions on arguments corresponding to ...
- *	4. add hidden _arguments[] argument
- *	5. call copy constructor for struct value arguments
- */
-
-void functionArguments(Loc loc, Scope *sc, TypeFunction *tf, Expressions *arguments)
-{
-    unsigned n;
-
-    //printf("functionArguments()\n");
-    assert(arguments);
-    size_t nargs = arguments ? arguments->dim : 0;
-    size_t nparams = Argument::dim(tf->parameters);
-
-    if (nargs > nparams && tf->varargs == 0)
-        error(loc, "expected %"PRIuSIZE" arguments, not %"PRIuSIZE, nparams, nargs);
-
-    n = (nargs > nparams) ? nargs : nparams;	// n = max(nargs, nparams)
-
-    int done = 0;
-    for (size_t i = 0; i < n; i++)
-    {
-	Expression *arg;
-
-	if (i < nargs)
-	    arg = (Expression *)arguments->data[i];
-	else
-	    arg = NULL;
-	Type *tb;
-
-	if (i < nparams)
-	{
-	    Argument *p = Argument::getNth(tf->parameters, i);
-
-	    if (!arg)
-	    {
-		if (!p->defaultArg)
-		{
-		    if (tf->varargs == 2 && i + 1 == nparams)
-			goto L2;
-            error(loc, "expected %"PRIuSIZE" arguments, not %"PRIuSIZE, nparams, nargs);
-		    break;
-		}
-		arg = p->defaultArg;
-#if DMDV2
-		if (arg->op == TOKdefault)
-		{   DefaultInitExp *de = (DefaultInitExp *)arg;
-		    arg = de->resolve(loc, sc);
-		}
-		else
-#endif
-		    arg = arg->copy();
-		arguments->push(arg);
-		nargs++;
-	    }
-
-	    if (tf->varargs == 2 && i + 1 == nparams)
-	    {
-		//printf("\t\tvarargs == 2, p->type = '%s'\n", p->type->toChars());
-		if (arg->implicitConvTo(p->type))
-		{
-		    if (nargs != nparams)
-                error(loc, "expected %"PRIuSIZE" arguments, not %"PRIuSIZE, nparams, nargs);
-		    goto L1;
-		}
-	     L2:
-		Type *tb = p->type->toBasetype();
-		Type *tret = p->isLazyArray();
-		switch (tb->ty)
-		{
-		    case Tsarray:
-		    case Tarray:
-		    {	// Create a static array variable v of type arg->type
-#ifdef IN_GCC
-			/* GCC 4.0 does not like zero length arrays used like
-			   this; pass a null array value instead. Could also
-			   just make a one-element array. */
-			if (nargs - i == 0)
-			{
-			    arg = new NullExp(loc);
-			    break;
-			}
-#endif
-			Identifier *id = Lexer::uniqueId("__arrayArg");
-			Type *t = new TypeSArray(((TypeArray *)tb)->next, new IntegerExp(nargs - i));
-			t = t->semantic(loc, sc);
-			VarDeclaration *v = new VarDeclaration(loc, t, id, new VoidInitializer(loc));
-			v->semantic(sc);
-			v->parent = sc->parent;
-			//sc->insert(v);
-
-			Expression *c = new DeclarationExp(0, v);
-			c->type = v->type;
-
-			for (size_t u = i; u < nargs; u++)
-			{   Expression *a = (Expression *)arguments->data[u];
-			    if (tret && !((TypeArray *)tb)->next->equals(a->type))
-				a = a->toDelegate(sc, tret);
-
-			    Expression *e = new VarExp(loc, v);
-			    e = new IndexExp(loc, e, new IntegerExp(u + 1 - nparams));
-			    AssignExp *ae = new AssignExp(loc, e, a);
-			    ae->op = TOKconstruct;
-			    if (c)
-				c = new CommaExp(loc, c, ae);
-			    else
-				c = ae;
-			}
-			arg = new VarExp(loc, v);
-			if (c)
-			    arg = new CommaExp(loc, c, arg);
-			break;
-		    }
-		    case Tclass:
-		    {	/* Set arg to be:
-			 *	new Tclass(arg0, arg1, ..., argn)
-			 */
-			Expressions *args = new Expressions();
-			args->setDim(nargs - i);
-			for (size_t u = i; u < nargs; u++)
-			    args->data[u - i] = arguments->data[u];
-			arg = new NewExp(loc, NULL, NULL, p->type, args);
-			break;
-		    }
-		    default:
-			if (!arg)
-			{   error(loc, "not enough arguments");
-			    return;
-		        }
-			break;
-		}
-		arg = arg->semantic(sc);
-		//printf("\targ = '%s'\n", arg->toChars());
-		arguments->setDim(i + 1);
-		done = 1;
-	    }
-
-	L1:
-	    if (!(p->storageClass & STClazy && p->type->ty == Tvoid))
-	    {
-		if (p->type != arg->type)
-		{
-		    //printf("arg->type = %s, p->type = %s\n", arg->type->toChars(), p->type->toChars());
-		    arg = arg->implicitCastTo(sc, p->type);
-		    arg = arg->optimize(WANTvalue);
-		}
-	    }
-	    if (p->storageClass & STCref)
-	    {
-		arg = arg->toLvalue(sc, arg);
-	    }
-	    else if (p->storageClass & STCout)
-	    {
-		arg = arg->modifiableLvalue(sc, arg);
-	    }
-
-        tb = arg->type->toBasetype();
-
-// LDC we don't want this!
-#if !IN_LLVM
-	    // Convert static arrays to pointers
-	    if (tb->ty == Tsarray)
-	    {
-		arg = arg->checkToPointer();
-	    }
-#endif
-
-
-	    if (tb->ty == Tstruct && !(p->storageClass & (STCref | STCout)))
-	    {
-		arg = callCpCtor(loc, sc, arg);
-	    }
-
-	    // Convert lazy argument to a delegate
-	    if (p->storageClass & STClazy)
-	    {
-		arg = arg->toDelegate(sc, p->type);
-	    }
-
-	    /* Look for arguments that cannot 'escape' from the called
-	     * function.
-	     */
-	    if (!tf->parameterEscapes(p))
-	    {
-		/* Function literals can only appear once, so if this
-		 * appearance was scoped, there cannot be any others.
-		 */
-		if (arg->op == TOKfunction)
-		{   FuncExp *fe = (FuncExp *)arg;
-		    fe->fd->tookAddressOf = 0;
-		}
-
-		/* For passing a delegate to a scoped parameter,
-		 * this doesn't count as taking the address of it.
-		 * We only worry about 'escaping' references to the function.
-		 */
-		else if (arg->op == TOKdelegate)
-		{   DelegateExp *de = (DelegateExp *)arg;
-		    if (de->e1->op == TOKvar)
-		    {	VarExp *ve = (VarExp *)de->e1;
-			FuncDeclaration *f = ve->var->isFuncDeclaration();
-			if (f)
-			{   f->tookAddressOf--;
-			    //printf("tookAddressOf = %d\n", f->tookAddressOf);
-			}
-		    }
-		}
-	    }
-	}
-	else
-	{
-
-	    // If not D linkage, do promotions
-        // LDC: don't do promotions on intrinsics
-	    if (tf->linkage != LINKd && tf->linkage != LINKintrinsic)
-	    {
-		// Promote bytes, words, etc., to ints
-		arg = arg->integralPromotions(sc);
-
-		// Promote floats to doubles
-		switch (arg->type->ty)
-		{
-		    case Tfloat32:
-			arg = arg->castTo(sc, Type::tfloat64);
-			break;
-
-		    case Timaginary32:
-			arg = arg->castTo(sc, Type::timaginary64);
-			break;
-		}
-	    }
-
-	    // Convert static arrays to dynamic arrays
-	    tb = arg->type->toBasetype();
-	    if (tb->ty == Tsarray)
-	    {	TypeSArray *ts = (TypeSArray *)tb;
-		Type *ta = ts->next->arrayOf();
-		if (ts->size(arg->loc) == 0)
-		{   arg = new NullExp(arg->loc);
-		    arg->type = ta;
-		}
-		else
-		    arg = arg->castTo(sc, ta);
-	    }
-#if DMDV2
-	    if (tb->ty == Tstruct)
-	    {
-		arg = callCpCtor(loc, sc, arg);
-	    }
-
-	    // Give error for overloaded function addresses
-	    if (arg->op == TOKsymoff)
-	    {	SymOffExp *se = (SymOffExp *)arg;
-		if (se->hasOverloads && !se->var->isFuncDeclaration()->isUnique())
-		    arg->error("function %s is overloaded", arg->toChars());
-	    }
-#endif
-	    arg->rvalue();
-	}
-	arg = arg->optimize(WANTvalue);
-	arguments->data[i] = (void *) arg;
-	if (done)
-	    break;
-    }
-
-#if !IN_LLVM
-    // If D linkage and variadic, add _arguments[] as first argument
-    if (tf->linkage == LINKd && tf->varargs == 1)
-    {
-	Expression *e;
-
-	e = createTypeInfoArray(sc, (Expression **)&arguments->data[nparams],
-		arguments->dim - nparams);
-	arguments->insert(0, e);
-    }
-#endif
-}
-
-/**************************************************
- * Write expression out to buf, but wrap it
- * in ( ) if its precedence is less than pr.
- */
-
-void expToCBuffer(OutBuffer *buf, HdrGenState *hgs, Expression *e, enum PREC pr)
-{
-    //if (precedence[e->op] == 0) e->dump(0);
-    if (precedence[e->op] < pr)
-    {
-	buf->writeByte('(');
-	e->toCBuffer(buf, hgs);
-	buf->writeByte(')');
-    }
-    else
-	e->toCBuffer(buf, hgs);
-}
-
-/**************************************************
- * Write out argument list to buf.
- */
-
-void argsToCBuffer(OutBuffer *buf, Expressions *arguments, HdrGenState *hgs)
-{
-    if (arguments)
-    {
-	for (size_t i = 0; i < arguments->dim; i++)
-	{   Expression *arg = (Expression *)arguments->data[i];
-
-	    if (arg)
-	    {	if (i)
-		    buf->writeByte(',');
-		expToCBuffer(buf, hgs, arg, PREC_assign);
-	    }
-	}
-    }
-}
-
-/**************************************************
- * Write out argument types to buf.
- */
-
-void argExpTypesToCBuffer(OutBuffer *buf, Expressions *arguments, HdrGenState *hgs)
-{
-    if (arguments)
-    {	OutBuffer argbuf;
-
-	for (size_t i = 0; i < arguments->dim; i++)
-	{   Expression *arg = (Expression *)arguments->data[i];
-
-	    if (i)
-		buf->writeByte(',');
-	    argbuf.reset();
-	    arg->type->toCBuffer2(&argbuf, hgs, 0);
-	    buf->write(&argbuf);
-	}
-    }
-}
-
-/******************************** Expression **************************/
-
-Expression::Expression(Loc loc, enum TOK op, int size)
-    : loc(loc)
-{
-    //printf("Expression::Expression(op = %d) this = %p\n", op, this);
-    this->loc = loc;
-    this->op = op;
-    this->size = size;
-    type = NULL;
-}
-
-Expression *Expression::syntaxCopy()
-{
-    //printf("Expression::syntaxCopy()\n");
-    //dump(0);
-    return copy();
-}
-
-/*********************************
- * Does *not* do a deep copy.
- */
-
-Expression *Expression::copy()
-{
-    Expression *e;
-    if (!size)
-    {
-#ifdef DEBUG
-	fprintf(stdmsg, "No expression copy for: %s\n", toChars());
-	printf("op = %d\n", op);
-	dump(0);
-#endif
-	assert(0);
-    }
-    e = (Expression *)mem.malloc(size);
-    //printf("Expression::copy(op = %d) e = %p\n", op, e);
-    return (Expression *)memcpy(e, this, size);
-}
-
-/**************************
- * Semantically analyze Expression.
- * Determine types, fold constants, etc.
- */
-
-Expression *Expression::semantic(Scope *sc)
-{
-#if LOGSEMANTIC
-    printf("Expression::semantic() %s\n", toChars());
-#endif
-    if (type)
-	type = type->semantic(loc, sc);
-    else
-	type = Type::tvoid;
-    return this;
-}
-
-void Expression::print()
-{
-    fprintf(stdmsg, "%s\n", toChars());
-    fflush(stdmsg);
-}
-
-char *Expression::toChars()
-{   OutBuffer *buf;
-    HdrGenState hgs;
-
-    memset(&hgs, 0, sizeof(hgs));
-    buf = new OutBuffer();
-    toCBuffer(buf, &hgs);
-    return buf->toChars();
-}
-
-void Expression::error(const char *format, ...)
-{
-    va_list ap;
-    va_start(ap, format);
-    ::verror(loc, format, ap);
-    va_end( ap );
-}
-
-void Expression::rvalue()
-{
-    if (type && type->toBasetype()->ty == Tvoid)
-    {	error("expression %s is void and has no value", toChars());
-#if 0
-	dump(0);
-	halt();
-#endif
-	type = Type::tint32;
-    }
-}
-
-Expression *Expression::combine(Expression *e1, Expression *e2)
-{
-    if (e1)
-    {
-	if (e2)
-	{
-	    e1 = new CommaExp(e1->loc, e1, e2);
-	    e1->type = e2->type;
-	}
-    }
-    else
-	e1 = e2;
-    return e1;
-}
-
-integer_t Expression::toInteger()
-{
-    //printf("Expression %s\n", Token::toChars(op));
-    error("Integer constant expression expected instead of %s", toChars());
-    return 0;
-}
-
-uinteger_t Expression::toUInteger()
-{
-    //printf("Expression %s\n", Token::toChars(op));
-    return (uinteger_t)toInteger();
-}
-
-real_t Expression::toReal()
-{
-    error("Floating point constant expression expected instead of %s", toChars());
-    return 0;
-}
-
-real_t Expression::toImaginary()
-{
-    error("Floating point constant expression expected instead of %s", toChars());
-    return 0;
-}
-
-complex_t Expression::toComplex()
-{
-    error("Floating point constant expression expected instead of %s", toChars());
-#ifdef IN_GCC
-    return complex_t(real_t(0)); // %% nicer
-#else
-    return 0;
-#endif
-}
-
-void Expression::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{
-    buf->writestring(Token::toChars(op));
-}
-
-void Expression::toMangleBuffer(OutBuffer *buf)
-{
-    error("expression %s is not a valid template value argument", toChars());
-}
-
-/***************************************
- * Return !=0 if expression is an lvalue.
- */
-
-int Expression::isLvalue()
-{
-    return 0;
-}
-
-/*******************************
- * Give error if we're not an lvalue.
- * If we can, convert expression to be an lvalue.
- */
-
-Expression *Expression::toLvalue(Scope *sc, Expression *e)
-{
-    if (!e)
-	e = this;
-    else if (!loc.filename)
-	loc = e->loc;
-    error("%s is not an lvalue", e->toChars());
-    return this;
-}
-
-Expression *Expression::modifiableLvalue(Scope *sc, Expression *e)
-{
-    //printf("Expression::modifiableLvalue() %s, type = %s\n", toChars(), type->toChars());
-
-    // See if this expression is a modifiable lvalue (i.e. not const)
-    if (type && (!type->isMutable() || !type->isAssignable()))
-	error("%s is not mutable", e->toChars());
-
-    return toLvalue(sc, e);
-}
-
-/************************************
- * Detect cases where pointers to the stack can 'escape' the
- * lifetime of the stack frame.
- */
-
-void Expression::checkEscape()
-{
-}
-
-void Expression::checkScalar()
-{
-    if (!type->isscalar())
-	error("'%s' is not a scalar, it is a %s", toChars(), type->toChars());
-}
-
-void Expression::checkNoBool()
-{
-    if (type->toBasetype()->ty == Tbool)
-	error("operation not allowed on bool '%s'", toChars());
-}
-
-Expression *Expression::checkIntegral()
-{
-    if (!type->isintegral())
-    {	error("'%s' is not of integral type, it is a %s", toChars(), type->toChars());
-	return new IntegerExp(0);
-    }
-    return this;
-}
-
-Expression *Expression::checkArithmetic()
-{
-    if (!type->isintegral() && !type->isfloating())
-    {	error("'%s' is not of arithmetic type, it is a %s", toChars(), type->toChars());
-	return new IntegerExp(0);
-    }
-    return this;
-}
-
-void Expression::checkDeprecated(Scope *sc, Dsymbol *s)
-{
-    s->checkDeprecated(loc, sc);
-}
-
-/********************************
- * Check for expressions that have no use.
- * Input:
- *	flag	0 not going to use the result, so issue error message if no
- *		  side effects
- *		1 the result of the expression is used, but still check
- *		  for useless subexpressions
- *		2 do not issue error messages, just return !=0 if expression
- *		  has side effects
- */
-
-int Expression::checkSideEffect(int flag)
-{
-    if (flag == 0)
-    {	if (op == TOKimport)
-	{
-	    error("%s has no effect", toChars());
-	}
-	else
-	    error("%s has no effect in expression (%s)",
-		Token::toChars(op), toChars());
-    }
-    return 0;
-}
-
-/*****************************
- * Check that expression can be tested for true or false.
- */
-
-Expression *Expression::checkToBoolean()
-{
-    // Default is 'yes' - do nothing
-
-#ifdef DEBUG
-    if (!type)
-	dump(0);
-#endif
-
-    if (!type->checkBoolean())
-    {
-	error("expression %s of type %s does not have a boolean value", toChars(), type->toChars());
-    }
-    return this;
-}
-
-/****************************
- */
-
-Expression *Expression::checkToPointer()
-{
-    Expression *e;
-    Type *tb;
-
-    //printf("Expression::checkToPointer()\n");
-    e = this;
-
-    // If C static array, convert to pointer
-    tb = type->toBasetype();
-    if (tb->ty == Tsarray)
-    {	TypeSArray *ts = (TypeSArray *)tb;
-	if (ts->size(loc) == 0)
-	    e = new NullExp(loc);
-	else
-	    e = new AddrExp(loc, this);
-	e->type = ts->next->pointerTo();
-    }
-    return e;
-}
-
-/******************************
- * Take address of expression.
- */
-
-Expression *Expression::addressOf(Scope *sc)
-{
-    Expression *e;
-
-    //printf("Expression::addressOf()\n");
-    e = toLvalue(sc, NULL);
-    e = new AddrExp(loc, e);
-    e->type = type->pointerTo();
-    return e;
-}
-
-/******************************
- * If this is a reference, dereference it.
- */
-
-Expression *Expression::deref()
-{
-    //printf("Expression::deref()\n");
-    if (type->ty == Treference)
-    {	Expression *e;
-
-	e = new PtrExp(loc, this);
-	e->type = ((TypeReference *)type)->next;
-	return e;
-    }
-    return this;
-}
-
-/********************************
- * Does this expression statically evaluate to a boolean TRUE or FALSE?
- */
-
-int Expression::isBool(int result)
-{
-    return FALSE;
-}
-
-/********************************
- * Does this expression result in either a 1 or a 0?
- */
-
-int Expression::isBit()
-{
-    return FALSE;
-}
-
-/********************************
- * Can this expression throw an exception?
- * Valid only after semantic() pass.
- */
-
-int Expression::canThrow()
-{
-    return FALSE;
-}
-
-
-
-Expressions *Expression::arraySyntaxCopy(Expressions *exps)
-{   Expressions *a = NULL;
-
-    if (exps)
-    {
-	a = new Expressions();
-	a->setDim(exps->dim);
-	for (int i = 0; i < a->dim; i++)
-	{   Expression *e = (Expression *)exps->data[i];
-
-	    e = e->syntaxCopy();
-	    a->data[i] = e;
-	}
-    }
-    return a;
-}
-
-/******************************** IntegerExp **************************/
-
-IntegerExp::IntegerExp(Loc loc, integer_t value, Type *type)
-	: Expression(loc, TOKint64, sizeof(IntegerExp))
-{
-    //printf("IntegerExp(value = %lld, type = '%s')\n", value, type ? type->toChars() : "");
-    if (type && !type->isscalar())
-    {
-	//printf("%s, loc = %d\n", toChars(), loc.linnum);
-	error("integral constant must be scalar type, not %s", type->toChars());
-	type = Type::terror;
-    }
-    this->type = type;
-    this->value = value;
-}
-
-IntegerExp::IntegerExp(integer_t value)
-	: Expression(0, TOKint64, sizeof(IntegerExp))
-{
-    this->type = Type::tint32;
-    this->value = value;
-}
-
-int IntegerExp::equals(Object *o)
-{   IntegerExp *ne;
-
-    if (this == o ||
-	(((Expression *)o)->op == TOKint64 &&
-	 ((ne = (IntegerExp *)o), type->toHeadMutable()->equals(ne->type->toHeadMutable())) &&
-	 value == ne->value))
-	return 1;
-    return 0;
-}
-
-char *IntegerExp::toChars()
-{
-#if 1
-    return Expression::toChars();
-#else
-    static char buffer[sizeof(value) * 3 + 1];
-    sprintf(buffer, "%lld", value);
-    return buffer;
-#endif
-}
-
-integer_t IntegerExp::toInteger()
-{   Type *t;
-
-    t = type;
-    while (t)
-    {
-	switch (t->ty)
-	{
-	    case Tbit:
-	    case Tbool:		value = (value != 0);		break;
-	    case Tint8:		value = (d_int8)  value;	break;
-	    case Tchar:
-	    case Tuns8:		value = (d_uns8)  value;	break;
-	    case Tint16:	value = (d_int16) value;	break;
-	    case Twchar:
-	    case Tuns16:	value = (d_uns16) value;	break;
-	    case Tint32:	value = (d_int32) value;	break;
-	    case Tdchar:
-	    case Tuns32:	value = (d_uns32) value;	break;
-	    case Tint64:	value = (d_int64) value;	break;
-	    case Tuns64:	value = (d_uns64) value;	break;
-	    case Tpointer:
-                // FIXME: Other pointer widths than 32 and 64?
-                if (PTRSIZE == 4)
-                    value = (d_uns32) value;
-                else
-                    value = (d_uns64) value;
-                break;
-
-	    case Tenum:
-	    {
-		TypeEnum *te = (TypeEnum *)t;
-		t = te->sym->memtype;
-		continue;
-	    }
-
-	    case Ttypedef:
-	    {
-		TypeTypedef *tt = (TypeTypedef *)t;
-		t = tt->sym->basetype;
-		continue;
-	    }
-
-	    default:
-		/* This can happen if errors, such as
-		 * the type is painted on like in fromConstInitializer().
-		 */
-		if (!global.errors)
-		{   type->print();
-		    assert(0);
-		}
-		break;
-	}
-	break;
-    }
-    return value;
-}
-
-real_t IntegerExp::toReal()
-{
-    Type *t;
-
-    toInteger();
-    t = type->toBasetype();
-    if (t->ty == Tuns64)
-	return (real_t)(d_uns64)value;
-    else
-	return (real_t)(d_int64)value;
-}
-
-real_t IntegerExp::toImaginary()
-{
-    return (real_t) 0;
-}
-
-complex_t IntegerExp::toComplex()
-{
-    return toReal();
-}
-
-int IntegerExp::isBool(int result)
-{
-    return result ? value != 0 : value == 0;
-}
-
-Expression *IntegerExp::semantic(Scope *sc)
-{
-    if (!type)
-    {
-	// Determine what the type of this number is
-	integer_t number = value;
-
-	if (number & 0x8000000000000000LL)
-	    type = Type::tuns64;
-	else if (number & 0xFFFFFFFF80000000LL)
-	    type = Type::tint64;
-	else
-	    type = Type::tint32;
-    }
-    else
-    {	if (!type->deco)
-	    type = type->semantic(loc, sc);
-    }
-    return this;
-}
-
-Expression *IntegerExp::toLvalue(Scope *sc, Expression *e)
-{
-    if (!e)
-	e = this;
-    else if (!loc.filename)
-	loc = e->loc;
-    e->error("constant %s is not an lvalue", e->toChars());
-    return this;
-}
-
-void IntegerExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{
-    integer_t v = toInteger();
-
-    if (type)
-    {	Type *t = type;
-
-      L1:
-	switch (t->ty)
-	{
-	    case Tenum:
-	    {   TypeEnum *te = (TypeEnum *)t;
-		buf->printf("cast(%s)", te->sym->toChars());
-		t = te->sym->memtype;
-		goto L1;
-	    }
-
-	    case Ttypedef:
-	    {	TypeTypedef *tt = (TypeTypedef *)t;
-		buf->printf("cast(%s)", tt->sym->toChars());
-		t = tt->sym->basetype;
-		goto L1;
-	    }
-
-	    case Twchar:	// BUG: need to cast(wchar)
-	    case Tdchar:	// BUG: need to cast(dchar)
-		if ((uinteger_t)v > 0xFF)
-		{
-		     buf->printf("'\\U%08x'", v);
-		     break;
-		}
-	    case Tchar:
-		if (v == '\'')
-		    buf->writestring("'\\''");
-		else if (isprint(v) && v != '\\')
-		    buf->printf("'%c'", (int)v);
-		else
-		    buf->printf("'\\x%02x'", (int)v);
-		break;
-
-	    case Tint8:
-		buf->writestring("cast(byte)");
-		goto L2;
-
-	    case Tint16:
-		buf->writestring("cast(short)");
-		goto L2;
-
-	    case Tint32:
-	    L2:
-		buf->printf("%d", (int)v);
-		break;
-
-	    case Tuns8:
-		buf->writestring("cast(ubyte)");
-		goto L3;
-
-	    case Tuns16:
-		buf->writestring("cast(ushort)");
-		goto L3;
-
-	    case Tuns32:
-	    L3:
-		buf->printf("%du", (unsigned)v);
-		break;
-
-	    case Tint64:
-		buf->printf("%lldL", v);
-		break;
-
-	    case Tuns64:
-            L4:
-		buf->printf("%lluLU", v);
-		break;
-
-	    case Tbit:
-	    case Tbool:
-		buf->writestring((char *)(v ? "true" : "false"));
-		break;
-
-	    case Tpointer:
-		buf->writestring("cast(");
-		buf->writestring(t->toChars());
-		buf->writeByte(')');
-                // FIXME: Other pointer widths than 32 and 64?
-                if (PTRSIZE == 4)
-                    goto L3;
-                else
-                    goto L4;
-
-	    default:
-		/* This can happen if errors, such as
-		 * the type is painted on like in fromConstInitializer().
-		 */
-		if (!global.errors)
-		{
-#ifdef DEBUG
-		    t->print();
-#endif
-		    assert(0);
-		}
-		break;
-	}
-    }
-    else if (v & 0x8000000000000000LL)
-	buf->printf("0x%llx", v);
-    else
-	buf->printf("%lld", v);
-}
-
-void IntegerExp::toMangleBuffer(OutBuffer *buf)
-{
-    if ((sinteger_t)value < 0)
-	buf->printf("N%lld", -value);
-    else
-	buf->printf("%lld", value);
-}
-
-/******************************** RealExp **************************/
-
-RealExp::RealExp(Loc loc, real_t value, Type *type)
-	: Expression(loc, TOKfloat64, sizeof(RealExp))
-{
-    //printf("RealExp::RealExp(%Lg)\n", value);
-    this->value = value;
-    this->type = type;
-}
-
-char *RealExp::toChars()
-{
-    char buffer[sizeof(value) * 3 + 8 + 1 + 1];
-
-#ifdef IN_GCC
-    value.format(buffer, sizeof(buffer));
-    if (type->isimaginary())
-	strcat(buffer, "i");
-#else
-    sprintf(buffer, type->isimaginary() ? "%Lgi" : "%Lg", value);
-#endif
-    assert(strlen(buffer) < sizeof(buffer));
-    return mem.strdup(buffer);
-}
-
-integer_t RealExp::toInteger()
-{
-#ifdef IN_GCC
-    return toReal().toInt();
-#else
-    return (sinteger_t) toReal();
-#endif
-}
-
-uinteger_t RealExp::toUInteger()
-{
-#ifdef IN_GCC
-    return (uinteger_t) toReal().toInt();
-#else
-    return (uinteger_t) toReal();
-#endif
-}
-
-real_t RealExp::toReal()
-{
-    return type->isreal() ? value : 0;
-}
-
-real_t RealExp::toImaginary()
-{
-    return type->isreal() ? 0 : value;
-}
-
-complex_t RealExp::toComplex()
-{
-#ifdef __DMC__
-    return toReal() + toImaginary() * I;
-#else
-    return complex_t(toReal(), toImaginary());
-#endif
-}
-
-/********************************
- * Test to see if two reals are the same.
- * Regard NaN's as equivalent.
- * Regard +0 and -0 as different.
- */
-
-int RealEquals(real_t x1, real_t x2)
-{
-    return // special case nans
-	   (isnan(x1) && isnan(x2)) ||
-	   // and zero, in order to distinguish +0 from -0
-	   (x1 == 0 && x2 == 0 && 1./x1 == 1./x2) ||
-	   // otherwise just compare
-	   (x1 != 0. && x1 == x2);
-}
-
-int RealExp::equals(Object *o)
-{   RealExp *ne;
-
-    if (this == o ||
-	(((Expression *)o)->op == TOKfloat64 &&
-	 ((ne = (RealExp *)o), type->toHeadMutable()->equals(ne->type->toHeadMutable())) &&
-	 RealEquals(value, ne->value)
-        )
-       )
-	return 1;
-    return 0;
-}
-
-Expression *RealExp::semantic(Scope *sc)
-{
-    if (!type)
-	type = Type::tfloat64;
-    else
-	type = type->semantic(loc, sc);
-    return this;
-}
-
-int RealExp::isBool(int result)
-{
-#ifdef IN_GCC
-    return result ? (! value.isZero()) : (value.isZero());
-#else
-    return result ? (value != 0)
-		  : (value == 0);
-#endif
-}
-
-void floatToBuffer(OutBuffer *buf, Type *type, real_t value)
-{
-    /* In order to get an exact representation, try converting it
-     * to decimal then back again. If it matches, use it.
-     * If it doesn't, fall back to hex, which is
-     * always exact.
-     */
-    char buffer[25];
-    sprintf(buffer, "%Lg", value);
-    assert(strlen(buffer) < sizeof(buffer));
-#if _WIN32 && __DMC__
-    char *save = __locale_decpoint;
-    __locale_decpoint = ".";
-    real_t r = strtold(buffer, NULL);
-    __locale_decpoint = save;
-#else
-    real_t r = strtold(buffer, NULL);
-#endif
-    if (r == value)			// if exact duplication
-	buf->writestring(buffer);
-    else
-	buf->printf("%La", value);	// ensure exact duplication
-
-    if (type)
-    {
-	Type *t = type->toBasetype();
-	switch (t->ty)
-	{
-	    case Tfloat32:
-	    case Timaginary32:
-	    case Tcomplex32:
-		buf->writeByte('F');
-		break;
-
-	    case Tfloat80:
-	    case Timaginary80:
-	    case Tcomplex80:
-		buf->writeByte('L');
-		break;
-
-	    default:
-		break;
-	}
-	if (t->isimaginary())
-	    buf->writeByte('i');
-    }
-}
-
-void RealExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{
-    floatToBuffer(buf, type, value);
-}
-
-void realToMangleBuffer(OutBuffer *buf, real_t value)
-{
-    /* Rely on %A to get portable mangling.
-     * Must munge result to get only identifier characters.
-     *
-     * Possible values from %A	=> mangled result
-     * NAN			=> NAN
-     * -INF			=> NINF
-     * INF			=> INF
-     * -0X1.1BC18BA997B95P+79	=> N11BC18BA997B95P79
-     * 0X1.9P+2			=> 19P2
-     */
-
-    if (isnan(value))
-	buf->writestring("NAN");	// no -NAN bugs
-    else
-    {
-	char buffer[32];
-	int n = sprintf(buffer, "%LA", value);
-	assert(n > 0 && n < sizeof(buffer));
-	for (int i = 0; i < n; i++)
-	{   char c = buffer[i];
-
-	    switch (c)
-	    {
-		case '-':
-		    buf->writeByte('N');
-		    break;
-
-		case '+':
-		case 'X':
-		case '.':
-		    break;
-
-		case '0':
-		    if (i < 2)
-			break;		// skip leading 0X
-		default:
-		    buf->writeByte(c);
-		    break;
-	    }
-	}
-    }
-}
-
-void RealExp::toMangleBuffer(OutBuffer *buf)
-{
-    buf->writeByte('e');
-    realToMangleBuffer(buf, value);
-}
-
-
-/******************************** ComplexExp **************************/
-
-ComplexExp::ComplexExp(Loc loc, complex_t value, Type *type)
-	: Expression(loc, TOKcomplex80, sizeof(ComplexExp))
-{
-    this->value = value;
-    this->type = type;
-    //printf("ComplexExp::ComplexExp(%s)\n", toChars());
-}
-
-char *ComplexExp::toChars()
-{
-    char buffer[sizeof(value) * 3 + 8 + 1];
-
-#ifdef IN_GCC
-    char buf1[sizeof(value) * 3 + 8 + 1];
-    char buf2[sizeof(value) * 3 + 8 + 1];
-    creall(value).format(buf1, sizeof(buf1));
-    cimagl(value).format(buf2, sizeof(buf2));
-    sprintf(buffer, "(%s+%si)", buf1, buf2);
-#else
-    sprintf(buffer, "(%Lg+%Lgi)", creall(value), cimagl(value));
-    assert(strlen(buffer) < sizeof(buffer));
-#endif
-    return mem.strdup(buffer);
-}
-
-integer_t ComplexExp::toInteger()
-{
-#ifdef IN_GCC
-    return (sinteger_t) toReal().toInt();
-#else
-    return (sinteger_t) toReal();
-#endif
-}
-
-uinteger_t ComplexExp::toUInteger()
-{
-#ifdef IN_GCC
-    return (uinteger_t) toReal().toInt();
-#else
-    return (uinteger_t) toReal();
-#endif
-}
-
-real_t ComplexExp::toReal()
-{
-    return creall(value);
-}
-
-real_t ComplexExp::toImaginary()
-{
-    return cimagl(value);
-}
-
-complex_t ComplexExp::toComplex()
-{
-    return value;
-}
-
-int ComplexExp::equals(Object *o)
-{   ComplexExp *ne;
-
-    if (this == o ||
-	(((Expression *)o)->op == TOKcomplex80 &&
-	 ((ne = (ComplexExp *)o), type->toHeadMutable()->equals(ne->type->toHeadMutable())) &&
-	 RealEquals(creall(value), creall(ne->value)) &&
-	 RealEquals(cimagl(value), cimagl(ne->value))
-	)
-       )
-	return 1;
-    return 0;
-}
-
-Expression *ComplexExp::semantic(Scope *sc)
-{
-    if (!type)
-	type = Type::tcomplex80;
-    else
-	type = type->semantic(loc, sc);
-    return this;
-}
-
-int ComplexExp::isBool(int result)
-{
-    if (result)
-	return (bool)(value);
-    else
-	return !value;
-}
-
-void ComplexExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{
-    /* Print as:
-     *  (re+imi)
-     */
-#ifdef IN_GCC
-    char buf1[sizeof(value) * 3 + 8 + 1];
-    char buf2[sizeof(value) * 3 + 8 + 1];
-    creall(value).format(buf1, sizeof(buf1));
-    cimagl(value).format(buf2, sizeof(buf2));
-    buf->printf("(%s+%si)", buf1, buf2);
-#else
-    buf->writeByte('(');
-    floatToBuffer(buf, type, creall(value));
-    buf->writeByte('+');
-    floatToBuffer(buf, type, cimagl(value));
-    buf->writestring("i)");
-#endif
-}
-
-void ComplexExp::toMangleBuffer(OutBuffer *buf)
-{
-    buf->writeByte('c');
-    real_t r = toReal();
-    realToMangleBuffer(buf, r);
-    buf->writeByte('c');	// separate the two
-    r = toImaginary();
-    realToMangleBuffer(buf, r);
-}
-
-/******************************** IdentifierExp **************************/
-
-IdentifierExp::IdentifierExp(Loc loc, Identifier *ident)
-	: Expression(loc, TOKidentifier, sizeof(IdentifierExp))
-{
-    this->ident = ident;
-}
-
-Expression *IdentifierExp::semantic(Scope *sc)
-{
-    Dsymbol *s;
-    Dsymbol *scopesym;
-
-#if LOGSEMANTIC
-    printf("IdentifierExp::semantic('%s')\n", ident->toChars());
-#endif
-    s = sc->search(loc, ident, &scopesym);
-    if (s)
-    {	Expression *e;
-	WithScopeSymbol *withsym;
-
-	/* See if the symbol was a member of an enclosing 'with'
-	 */
-	withsym = scopesym->isWithScopeSymbol();
-	if (withsym)
-	{
-	    s = s->toAlias();
-
-	    // Same as wthis.ident
-	    if (s->needThis() || s->isTemplateDeclaration())
-	    {
-		e = new VarExp(loc, withsym->withstate->wthis);
-		e = new DotIdExp(loc, e, ident);
-	    }
-	    else
-	    {	Type *t = withsym->withstate->wthis->type;
-		if (t->ty == Tpointer)
-		    t = ((TypePointer *)t)->next;
-		e = new TypeDotIdExp(loc, t, ident);
-	    }
-	}
-	else
-	{
-	    /* If f is really a function template,
-	     * then replace f with the function template declaration.
-	     */
-	    FuncDeclaration *f = s->isFuncDeclaration();
-	    if (f && f->parent)
-	    {   TemplateInstance *ti = f->parent->isTemplateInstance();
-
-		if (ti &&
-		    !ti->isTemplateMixin() &&
-		    (ti->name == f->ident ||
-		     ti->toAlias()->ident == f->ident)
-		    &&
-		    ti->tempdecl && ti->tempdecl->onemember)
-		{
-		    TemplateDeclaration *tempdecl = ti->tempdecl;
-		    if (tempdecl->overroot)         // if not start of overloaded list of TemplateDeclaration's
-			tempdecl = tempdecl->overroot; // then get the start
-		    e = new TemplateExp(loc, tempdecl);
-		    e = e->semantic(sc);
-		    return e;
-		}
-	    }
-	    // Haven't done overload resolution yet, so pass 1
-	    e = new DsymbolExp(loc, s, 1);
-	}
-	return e->semantic(sc);
-    }
-    error("undefined identifier %s", ident->toChars());
-    type = Type::terror;
-    return this;
-}
-
-char *IdentifierExp::toChars()
-{
-    return ident->toChars();
-}
-
-void IdentifierExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{
-    if (hgs->hdrgen)
-	buf->writestring(ident->toHChars2());
-    else
-	buf->writestring(ident->toChars());
-}
-
-int IdentifierExp::isLvalue()
-{
-    return 1;
-}
-
-Expression *IdentifierExp::toLvalue(Scope *sc, Expression *e)
-{
-#if 0
-    tym = tybasic(e1->ET->Tty);
-    if (!(tyscalar(tym) ||
-	  tym == TYstruct ||
-	  tym == TYarray && e->Eoper == TOKaddr))
-	    synerr(EM_lvalue);	// lvalue expected
-#endif
-    return this;
-}
-
-/******************************** DollarExp **************************/
-
-DollarExp::DollarExp(Loc loc)
-	: IdentifierExp(loc, Id::dollar)
-{
-}
-
-/******************************** DsymbolExp **************************/
-
-DsymbolExp::DsymbolExp(Loc loc, Dsymbol *s, int hasOverloads)
-	: Expression(loc, TOKdsymbol, sizeof(DsymbolExp))
-{
-    this->s = s;
-    this->hasOverloads = hasOverloads;
-}
-
-Expression *DsymbolExp::semantic(Scope *sc)
-{
-#if LOGSEMANTIC
-    printf("DsymbolExp::semantic('%s')\n", s->toChars());
-#endif
-
-Lagain:
-    EnumMember *em;
-    Expression *e;
-    VarDeclaration *v;
-    FuncDeclaration *f;
-    FuncLiteralDeclaration *fld;
-    OverloadSet *o;
-    Declaration *d;
-    ClassDeclaration *cd;
-    ClassDeclaration *thiscd = NULL;
-    Import *imp;
-    Package *pkg;
-    Type *t;
-
-    //printf("DsymbolExp:: %p '%s' is a symbol\n", this, toChars());
-    //printf("s = '%s', s->kind = '%s'\n", s->toChars(), s->kind());
-    if (type)
-	return this;
-    if (!s->isFuncDeclaration())	// functions are checked after overloading
-	checkDeprecated(sc, s);
-    s = s->toAlias();
-    //printf("s = '%s', s->kind = '%s', s->needThis() = %p\n", s->toChars(), s->kind(), s->needThis());
-    if (!s->isFuncDeclaration())
-	checkDeprecated(sc, s);
-
-    if (sc->func)
-	thiscd = sc->func->parent->isClassDeclaration();
-
-    // BUG: This should happen after overload resolution for functions, not before
-    if (s->needThis())
-    {
-	if (hasThis(sc) && !s->isFuncDeclaration())
-	{
-	    // Supply an implicit 'this', as in
-	    //	  this.ident
-
-	    DotVarExp *de;
-
-	    de = new DotVarExp(loc, new ThisExp(loc), s->isDeclaration());
-	    return de->semantic(sc);
-	}
-    }
-
-    em = s->isEnumMember();
-    if (em)
-    {
-	e = em->value;
-	e = e->semantic(sc);
-	return e;
-    }
-    v = s->isVarDeclaration();
-    if (v)
-    {
-	//printf("Identifier '%s' is a variable, type '%s'\n", toChars(), v->type->toChars());
-	if (!type)
-	{   type = v->type;
-	    if (!v->type)
-	    {	error("forward reference of %s", v->toChars());
-		type = Type::terror;
-	    }
-	}
-	e = new VarExp(loc, v);
-	e->type = type;
-	e = e->semantic(sc);
-	return e->deref();
-    }
-    fld = s->isFuncLiteralDeclaration();
-    if (fld)
-    {	//printf("'%s' is a function literal\n", fld->toChars());
-	e = new FuncExp(loc, fld);
-	return e->semantic(sc);
-    }
-    f = s->isFuncDeclaration();
-    if (f)
-    {	//printf("'%s' is a function\n", f->toChars());
-	return new VarExp(loc, f, hasOverloads);
-    }
-    o = s->isOverloadSet();
-    if (o)
-    {	//printf("'%s' is an overload set\n", o->toChars());
-	return new OverExp(o);
-    }
-    cd = s->isClassDeclaration();
-    if (cd && thiscd && cd->isBaseOf(thiscd, NULL) && sc->func->needThis())
-    {
-	// We need to add an implicit 'this' if cd is this class or a base class.
-	DotTypeExp *dte;
-
-	dte = new DotTypeExp(loc, new ThisExp(loc), s);
-	return dte->semantic(sc);
-    }
-    imp = s->isImport();
-    if (imp)
-    {
-	ScopeExp *ie;
-
-	ie = new ScopeExp(loc, imp->pkg);
-	return ie->semantic(sc);
-    }
-    pkg = s->isPackage();
-    if (pkg)
-    {
-	ScopeExp *ie;
-
-	ie = new ScopeExp(loc, pkg);
-	return ie->semantic(sc);
-    }
-    Module *mod = s->isModule();
-    if (mod)
-    {
-	ScopeExp *ie;
-
-	ie = new ScopeExp(loc, mod);
-	return ie->semantic(sc);
-    }
-
-    t = s->getType();
-    if (t)
-    {
-	return new TypeExp(loc, t);
-    }
-
-    TupleDeclaration *tup = s->isTupleDeclaration();
-    if (tup)
-    {
-	e = new TupleExp(loc, tup);
-	e = e->semantic(sc);
-	return e;
-    }
-
-    TemplateInstance *ti = s->isTemplateInstance();
-    if (ti && !global.errors)
-    {   if (!ti->semanticdone)
-	    ti->semantic(sc);
-	s = ti->inst->toAlias();
-	if (!s->isTemplateInstance())
-	    goto Lagain;
-	e = new ScopeExp(loc, ti);
-	e = e->semantic(sc);
-	return e;
-    }
-
-    TemplateDeclaration *td = s->isTemplateDeclaration();
-    if (td)
-    {
-	e = new TemplateExp(loc, td);
-	e = e->semantic(sc);
-	return e;
-    }
-
-Lerr:
-    error("%s '%s' is not a variable", s->kind(), s->toChars());
-    type = Type::terror;
-    return this;
-}
-
-char *DsymbolExp::toChars()
-{
-    return s->toChars();
-}
-
-void DsymbolExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{
-    buf->writestring(s->toChars());
-}
-
-int DsymbolExp::isLvalue()
-{
-    return 1;
-}
-
-Expression *DsymbolExp::toLvalue(Scope *sc, Expression *e)
-{
-#if 0
-    tym = tybasic(e1->ET->Tty);
-    if (!(tyscalar(tym) ||
-	  tym == TYstruct ||
-	  tym == TYarray && e->Eoper == TOKaddr))
-	    synerr(EM_lvalue);	// lvalue expected
-#endif
-    return this;
-}
-
-/******************************** ThisExp **************************/
-
-ThisExp::ThisExp(Loc loc)
-	: Expression(loc, TOKthis, sizeof(ThisExp))
-{
-    var = NULL;
-}
-
-Expression *ThisExp::semantic(Scope *sc)
-{   FuncDeclaration *fd;
-    FuncDeclaration *fdthis;
-    int nested = 0;
-
-#if LOGSEMANTIC
-    printf("ThisExp::semantic()\n");
-#endif
-    if (type)
-    {	//assert(global.errors || var);
-	return this;
-    }
-
-    /* Special case for typeof(this) and typeof(super) since both
-     * should work even if they are not inside a non-static member function
-     */
-    if (sc->intypeof)
-    {
-	// Find enclosing struct or class
-	for (Dsymbol *s = sc->parent; 1; s = s->parent)
-	{
-	    ClassDeclaration *cd;
-	    StructDeclaration *sd;
-
-	    if (!s)
-	    {
-		error("%s is not in a struct or class scope", toChars());
-		goto Lerr;
-	    }
-	    cd = s->isClassDeclaration();
-	    if (cd)
-	    {
-		type = cd->type;
-		return this;
-	    }
-	    sd = s->isStructDeclaration();
-	    if (sd)
-	    {
-#if STRUCTTHISREF
-		type = sd->type;
-#else
-		type = sd->type->pointerTo();
-#endif
-		return this;
-	    }
-	}
-    }
-
-    fdthis = sc->parent->isFuncDeclaration();
-    fd = hasThis(sc);	// fd is the uplevel function with the 'this' variable
-    if (!fd)
-	goto Lerr;
-
-    assert(fd->vthis);
-    var = fd->vthis;
-    assert(var->parent);
-    type = var->type;
-    var->isVarDeclaration()->checkNestedReference(sc, loc);
-    if (!sc->intypeof)
-	sc->callSuper |= CSXthis;
-    return this;
-
-Lerr:
-    error("'this' is only defined in non-static member functions, not %s", sc->parent->toChars());
-    type = Type::terror;
-    return this;
-}
-
-int ThisExp::isBool(int result)
-{
-    return result ? TRUE : FALSE;
-}
-
-void ThisExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{
-    buf->writestring("this");
-}
-
-int ThisExp::isLvalue()
-{
-    return 1;
-}
-
-Expression *ThisExp::toLvalue(Scope *sc, Expression *e)
-{
-    return this;
-}
-
-/******************************** SuperExp **************************/
-
-SuperExp::SuperExp(Loc loc)
-	: ThisExp(loc)
-{
-    op = TOKsuper;
-}
-
-Expression *SuperExp::semantic(Scope *sc)
-{   FuncDeclaration *fd;
-    FuncDeclaration *fdthis;
-    ClassDeclaration *cd;
-    Dsymbol *s;
-
-#if LOGSEMANTIC
-    printf("SuperExp::semantic('%s')\n", toChars());
-#endif
-    if (type)
-	return this;
-
-    /* Special case for typeof(this) and typeof(super) since both
-     * should work even if they are not inside a non-static member function
-     */
-    if (sc->intypeof)
-    {
-	// Find enclosing class
-	for (Dsymbol *s = sc->parent; 1; s = s->parent)
-	{
-	    ClassDeclaration *cd;
-
-	    if (!s)
-	    {
-		error("%s is not in a class scope", toChars());
-		goto Lerr;
-	    }
-	    cd = s->isClassDeclaration();
-	    if (cd)
-	    {
-		cd = cd->baseClass;
-		if (!cd)
-		{   error("class %s has no 'super'", s->toChars());
-		    goto Lerr;
-		}
-		type = cd->type;
-		return this;
-	    }
-	}
-    }
-
-    fdthis = sc->parent->isFuncDeclaration();
-    fd = hasThis(sc);
-    if (!fd)
-	goto Lerr;
-    assert(fd->vthis);
-    var = fd->vthis;
-    assert(var->parent);
-
-    s = fd->toParent();
-    while (s && s->isTemplateInstance())
-	s = s->toParent();
-    assert(s);
-    cd = s->isClassDeclaration();
-//printf("parent is %s %s\n", fd->toParent()->kind(), fd->toParent()->toChars());
-    if (!cd)
-	goto Lerr;
-    if (!cd->baseClass)
-    {
-	error("no base class for %s", cd->toChars());
-	type = fd->vthis->type;
-    }
-    else
-    {
-	type = cd->baseClass->type;
-    }
-
-    var->isVarDeclaration()->checkNestedReference(sc, loc);
-
-    if (!sc->intypeof)
-	sc->callSuper |= CSXsuper;
-    return this;
-
-
-Lerr:
-    error("'super' is only allowed in non-static class member functions");
-    type = Type::tint32;
-    return this;
-}
-
-void SuperExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{
-    buf->writestring("super");
-}
-
-
-/******************************** NullExp **************************/
-
-NullExp::NullExp(Loc loc)
-	: Expression(loc, TOKnull, sizeof(NullExp))
-{
-    committed = 0;
-}
-
-Expression *NullExp::semantic(Scope *sc)
-{
-#if LOGSEMANTIC
-    printf("NullExp::semantic('%s')\n", toChars());
-#endif
-    // NULL is the same as (void *)0
-    if (!type)
-	type = Type::tvoid->pointerTo();
-    return this;
-}
-
-int NullExp::isBool(int result)
-{
-    return result ? FALSE : TRUE;
-}
-
-void NullExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{
-    buf->writestring("null");
-}
-
-void NullExp::toMangleBuffer(OutBuffer *buf)
-{
-    buf->writeByte('n');
-}
-
-/******************************** StringExp **************************/
-
-StringExp::StringExp(Loc loc, char *string)
-	: Expression(loc, TOKstring, sizeof(StringExp))
-{
-    this->string = string;
-    this->len = strlen(string);
-    this->sz = 1;
-    this->committed = 0;
-    this->postfix = 0;
-}
-
-StringExp::StringExp(Loc loc, void *string, size_t len)
-	: Expression(loc, TOKstring, sizeof(StringExp))
-{
-    this->string = string;
-    this->len = len;
-    this->sz = 1;
-    this->committed = 0;
-    this->postfix = 0;
-}
-
-StringExp::StringExp(Loc loc, void *string, size_t len, unsigned char postfix)
-	: Expression(loc, TOKstring, sizeof(StringExp))
-{
-    this->string = string;
-    this->len = len;
-    this->sz = 1;
-    this->committed = 0;
-    this->postfix = postfix;
-}
-
-#if 0
-Expression *StringExp::syntaxCopy()
-{
-    printf("StringExp::syntaxCopy() %s\n", toChars());
-    return copy();
-}
-#endif
-
-int StringExp::equals(Object *o)
-{
-    //printf("StringExp::equals('%s')\n", o->toChars());
-    if (o && o->dyncast() == DYNCAST_EXPRESSION)
-    {	Expression *e = (Expression *)o;
-
-	if (e->op == TOKstring)
-	{
-	    return compare(o) == 0;
-	}
-    }
-    return FALSE;
-}
-
-char *StringExp::toChars()
-{
-    OutBuffer buf;
-    HdrGenState hgs;
-    char *p;
-
-    memset(&hgs, 0, sizeof(hgs));
-    toCBuffer(&buf, &hgs);
-    buf.writeByte(0);
-    p = (char *)buf.data;
-    buf.data = NULL;
-    return p;
-}
-
-Expression *StringExp::semantic(Scope *sc)
-{
-#if LOGSEMANTIC
-    printf("StringExp::semantic() %s\n", toChars());
-#endif
-    if (!type)
-    {	OutBuffer buffer;
-	size_t newlen = 0;
-	const char *p;
-	size_t u;
-	unsigned c;
-
-	switch (postfix)
-	{
-	    case 'd':
-		for (u = 0; u < len;)
-		{
-		    p = utf_decodeChar((unsigned char *)string, len, &u, &c);
-		    if (p)
-		    {	error("%s", p);
-			break;
-		    }
-		    else
-		    {	buffer.write4(c);
-			newlen++;
-		    }
-		}
-		buffer.write4(0);
-		string = buffer.extractData();
-		len = newlen;
-		sz = 4;
-		type = new TypeSArray(Type::tdchar, new IntegerExp(loc, len, Type::tindex));
-		committed = 1;
-		break;
-
-	    case 'w':
-		for (u = 0; u < len;)
-		{
-		    p = utf_decodeChar((unsigned char *)string, len, &u, &c);
-		    if (p)
-		    {	error("%s", p);
-			break;
-		    }
-		    else
-		    {	buffer.writeUTF16(c);
-			newlen++;
-			if (c >= 0x10000)
-			    newlen++;
-		    }
-		}
-		buffer.writeUTF16(0);
-		string = buffer.extractData();
-		len = newlen;
-		sz = 2;
-		type = new TypeSArray(Type::twchar, new IntegerExp(loc, len, Type::tindex));
-		committed = 1;
-		break;
-
-	    case 'c':
-		committed = 1;
-	    default:
-		type = new TypeSArray(Type::tchar, new IntegerExp(loc, len, Type::tindex));
-		break;
-	}
-	type = type->semantic(loc, sc);
-	type = type->invariantOf();
-	//printf("type = %s\n", type->toChars());
-    }
-    return this;
-}
-
-/****************************************
- * Convert string to char[].
- */
-
-StringExp *StringExp::toUTF8(Scope *sc)
-{
-    if (sz != 1)
-    {	// Convert to UTF-8 string
-	committed = 0;
-	Expression *e = castTo(sc, Type::tchar->arrayOf());
-	e = e->optimize(WANTvalue);
-	assert(e->op == TOKstring);
-	StringExp *se = (StringExp *)e;
-	assert(se->sz == 1);
-	return se;
-    }
-    return this;
-}
-
-int StringExp::compare(Object *obj)
-{
-    // Used to sort case statement expressions so we can do an efficient lookup
-    StringExp *se2 = (StringExp *)(obj);
-
-    // This is a kludge so isExpression() in template.c will return 5
-    // for StringExp's.
-    if (!se2)
-	return 5;
-
-    assert(se2->op == TOKstring);
-
-    int len1 = len;
-    int len2 = se2->len;
-
-    if (len1 == len2)
-    {
-	switch (sz)
-	{
-	    case 1:
-		return strcmp((char *)string, (char *)se2->string);
-
-	    case 2:
-	    {	unsigned u;
-		d_wchar *s1 = (d_wchar *)string;
-		d_wchar *s2 = (d_wchar *)se2->string;
-
-		for (u = 0; u < len; u++)
-		{
-		    if (s1[u] != s2[u])
-			return s1[u] - s2[u];
-		}
-	    }
-
-	    case 4:
-	    {	unsigned u;
-		d_dchar *s1 = (d_dchar *)string;
-		d_dchar *s2 = (d_dchar *)se2->string;
-
-		for (u = 0; u < len; u++)
-		{
-		    if (s1[u] != s2[u])
-			return s1[u] - s2[u];
-		}
-	    }
-	    break;
-
-	    default:
-		assert(0);
-	}
-    }
-    return len1 - len2;
-}
-
-int StringExp::isBool(int result)
-{
-    return result ? TRUE : FALSE;
-}
-
-unsigned StringExp::charAt(size_t i)
-{   unsigned value;
-
-    switch (sz)
-    {
-	case 1:
-	    value = ((unsigned char *)string)[i];
-	    break;
-
-	case 2:
-	    value = ((unsigned short *)string)[i];
-	    break;
-
-	case 4:
-	    value = ((unsigned int *)string)[i];
-	    break;
-
-	default:
-	    assert(0);
-	    break;
-    }
-    return value;
-}
-
-void StringExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{
-    buf->writeByte('"');
-    for (size_t i = 0; i < len; i++)
-    {	unsigned c = charAt(i);
-
-	switch (c)
-	{
-	    case '"':
-	    case '\\':
-		if (!hgs->console)
-		    buf->writeByte('\\');
-	    default:
-		if (c <= 0xFF)
-		{   if (c <= 0x7F && (isprint(c) || hgs->console))
-			buf->writeByte(c);
-		    else
-			buf->printf("\\x%02x", c);
-		}
-		else if (c <= 0xFFFF)
-		    buf->printf("\\x%02x\\x%02x", c & 0xFF, c >> 8);
-		else
-		    buf->printf("\\x%02x\\x%02x\\x%02x\\x%02x",
-			c & 0xFF, (c >> 8) & 0xFF, (c >> 16) & 0xFF, c >> 24);
-		break;
-	}
-    }
-    buf->writeByte('"');
-    if (postfix)
-	buf->writeByte(postfix);
-}
-
-void StringExp::toMangleBuffer(OutBuffer *buf)
-{   char m;
-    OutBuffer tmp;
-    const char *p;
-    unsigned c;
-    size_t u;
-    unsigned char *q;
-    unsigned qlen;
-
-    /* Write string in UTF-8 format
-     */
-    switch (sz)
-    {	case 1:
-	    m = 'a';
-	    q = (unsigned char *)string;
-	    qlen = len;
-	    break;
-	case 2:
-	    m = 'w';
-	    for (u = 0; u < len; )
-	    {
-                p = utf_decodeWchar((unsigned short *)string, len, &u, &c);
-                if (p)
-                    error("%s", p);
-                else
-                    tmp.writeUTF8(c);
-	    }
-	    q = tmp.data;
-	    qlen = tmp.offset;
-	    break;
-	case 4:
-	    m = 'd';
-            for (u = 0; u < len; u++)
-            {
-                c = ((unsigned *)string)[u];
-                if (!utf_isValidDchar(c))
-                    error("invalid UCS-32 char \\U%08x", c);
-                else
-                    tmp.writeUTF8(c);
-            }
-	    q = tmp.data;
-	    qlen = tmp.offset;
-	    break;
-	default:
-	    assert(0);
-    }
-    buf->writeByte(m);
-    buf->printf("%d_", qlen);
-    for (size_t i = 0; i < qlen; i++)
-	buf->printf("%02x", q[i]);
-}
-
-/************************ ArrayLiteralExp ************************************/
-
-// [ e1, e2, e3, ... ]
-
-ArrayLiteralExp::ArrayLiteralExp(Loc loc, Expressions *elements)
-    : Expression(loc, TOKarrayliteral, sizeof(ArrayLiteralExp))
-{
-    this->elements = elements;
-}
-
-ArrayLiteralExp::ArrayLiteralExp(Loc loc, Expression *e)
-    : Expression(loc, TOKarrayliteral, sizeof(ArrayLiteralExp))
-{
-    elements = new Expressions;
-    elements->push(e);
-}
-
-Expression *ArrayLiteralExp::syntaxCopy()
-{
-    return new ArrayLiteralExp(loc, arraySyntaxCopy(elements));
-}
-
-Expression *ArrayLiteralExp::semantic(Scope *sc)
-{   Expression *e;
-    Type *t0 = NULL;
-
-#if LOGSEMANTIC
-    printf("ArrayLiteralExp::semantic('%s')\n", toChars());
-#endif
-    if (type)
-	return this;
-
-    // Run semantic() on each element
-    for (int i = 0; i < elements->dim; i++)
-    {	e = (Expression *)elements->data[i];
-	e = e->semantic(sc);
-	elements->data[i] = (void *)e;
-    }
-    expandTuples(elements);
-    for (int i = 0; i < elements->dim; i++)
-    {	e = (Expression *)elements->data[i];
-
-	if (!e->type)
-	    error("%s has no value", e->toChars());
-	e = resolveProperties(sc, e);
-
-	unsigned char committed = 1;
-	if (e->op == TOKstring)
-	    committed = ((StringExp *)e)->committed;
-
-	if (!t0)
-	{   t0 = e->type;
-	    // Convert any static arrays to dynamic arrays
-	    if (t0->ty == Tsarray)
-	    {
-		t0 = ((TypeSArray *)t0)->next->arrayOf();
-		e = e->implicitCastTo(sc, t0);
-	    }
-	}
-	else
-	    e = e->implicitCastTo(sc, t0);
-	if (!committed && e->op == TOKstring)
-	{   StringExp *se = (StringExp *)e;
-	    se->committed = 0;
-	}
-	elements->data[i] = (void *)e;
-    }
-
-    if (!t0)
-	t0 = Type::tvoid;
-    type = new TypeSArray(t0, new IntegerExp(elements->dim));
-    type = type->semantic(loc, sc);
-    return this;
-}
-
-int ArrayLiteralExp::checkSideEffect(int flag)
-{   int f = 0;
-
-    for (size_t i = 0; i < elements->dim; i++)
-    {	Expression *e = (Expression *)elements->data[i];
-
-	f |= e->checkSideEffect(2);
-    }
-    if (flag == 0 && f == 0)
-	Expression::checkSideEffect(0);
-    return f;
-}
-
-int ArrayLiteralExp::isBool(int result)
-{
-    size_t dim = elements ? elements->dim : 0;
-    return result ? (dim != 0) : (dim == 0);
-}
-
-int ArrayLiteralExp::canThrow()
-{
-    return 1;	// because it can fail allocating memory
-}
-
-void ArrayLiteralExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{
-    buf->writeByte('[');
-    argsToCBuffer(buf, elements, hgs);
-    buf->writeByte(']');
-}
-
-void ArrayLiteralExp::toMangleBuffer(OutBuffer *buf)
-{
-    size_t dim = elements ? elements->dim : 0;
-    buf->printf("A%u", dim);
-    for (size_t i = 0; i < dim; i++)
-    {	Expression *e = (Expression *)elements->data[i];
-	e->toMangleBuffer(buf);
-    }
-}
-
-/************************ AssocArrayLiteralExp ************************************/
-
-// [ key0 : value0, key1 : value1, ... ]
-
-AssocArrayLiteralExp::AssocArrayLiteralExp(Loc loc,
-		Expressions *keys, Expressions *values)
-    : Expression(loc, TOKassocarrayliteral, sizeof(AssocArrayLiteralExp))
-{
-    assert(keys->dim == values->dim);
-    this->keys = keys;
-    this->values = values;
-}
-
-Expression *AssocArrayLiteralExp::syntaxCopy()
-{
-    return new AssocArrayLiteralExp(loc,
-	arraySyntaxCopy(keys), arraySyntaxCopy(values));
-}
-
-Expression *AssocArrayLiteralExp::semantic(Scope *sc)
-{   Expression *e;
-    Type *tkey = NULL;
-    Type *tvalue = NULL;
-
-#if LOGSEMANTIC
-    printf("AssocArrayLiteralExp::semantic('%s')\n", toChars());
-#endif
-
-    // Run semantic() on each element
-    for (size_t i = 0; i < keys->dim; i++)
-    {	Expression *key = (Expression *)keys->data[i];
-	Expression *value = (Expression *)values->data[i];
-
-	key = key->semantic(sc);
-	value = value->semantic(sc);
-
-	keys->data[i] = (void *)key;
-	values->data[i] = (void *)value;
-    }
-    expandTuples(keys);
-    expandTuples(values);
-    if (keys->dim != values->dim)
-    {
-	error("number of keys is %u, must match number of values %u", keys->dim, values->dim);
-	keys->setDim(0);
-	values->setDim(0);
-    }
-    for (size_t i = 0; i < keys->dim; i++)
-    {	Expression *key = (Expression *)keys->data[i];
-	Expression *value = (Expression *)values->data[i];
-
-	if (!key->type)
-	    error("%s has no value", key->toChars());
-	if (!value->type)
-	    error("%s has no value", value->toChars());
-	key = resolveProperties(sc, key);
-	value = resolveProperties(sc, value);
-
-	if (!tkey)
-	    tkey = key->type;
-	else
-	    key = key->implicitCastTo(sc, tkey);
-	keys->data[i] = (void *)key;
-
-	if (!tvalue)
-	    tvalue = value->type;
-	else
-	    value = value->implicitCastTo(sc, tvalue);
-	values->data[i] = (void *)value;
-    }
-
-    if (!tkey)
-	tkey = Type::tvoid;
-    if (!tvalue)
-	tvalue = Type::tvoid;
-    type = new TypeAArray(tvalue, tkey);
-    type = type->semantic(loc, sc);
-    return this;
-}
-
-int AssocArrayLiteralExp::checkSideEffect(int flag)
-{   int f = 0;
-
-    for (size_t i = 0; i < keys->dim; i++)
-    {	Expression *key = (Expression *)keys->data[i];
-	Expression *value = (Expression *)values->data[i];
-
-	f |= key->checkSideEffect(2);
-	f |= value->checkSideEffect(2);
-    }
-    if (flag == 0 && f == 0)
-	Expression::checkSideEffect(0);
-    return f;
-}
-
-int AssocArrayLiteralExp::isBool(int result)
-{
-    size_t dim = keys->dim;
-    return result ? (dim != 0) : (dim == 0);
-}
-
-int AssocArrayLiteralExp::canThrow()
-{
-    return 1;
-}
-
-void AssocArrayLiteralExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{
-    buf->writeByte('[');
-    for (size_t i = 0; i < keys->dim; i++)
-    {	Expression *key = (Expression *)keys->data[i];
-	Expression *value = (Expression *)values->data[i];
-
-	if (i)
-	    buf->writeByte(',');
-	expToCBuffer(buf, hgs, key, PREC_assign);
-	buf->writeByte(':');
-	expToCBuffer(buf, hgs, value, PREC_assign);
-    }
-    buf->writeByte(']');
-}
-
-void AssocArrayLiteralExp::toMangleBuffer(OutBuffer *buf)
-{
-    size_t dim = keys->dim;
-    buf->printf("A%u", dim);
-    for (size_t i = 0; i < dim; i++)
-    {	Expression *key = (Expression *)keys->data[i];
-	Expression *value = (Expression *)values->data[i];
-
-	key->toMangleBuffer(buf);
-	value->toMangleBuffer(buf);
-    }
-}
-
-/************************ StructLiteralExp ************************************/
-
-// sd( e1, e2, e3, ... )
-
-StructLiteralExp::StructLiteralExp(Loc loc, StructDeclaration *sd, Expressions *elements)
-    : Expression(loc, TOKstructliteral, sizeof(StructLiteralExp))
-{
-    this->sd = sd;
-    this->elements = elements;
-    this->sym = NULL;
-    this->soffset = 0;
-    this->fillHoles = 1;
-}
-
-Expression *StructLiteralExp::syntaxCopy()
-{
-    return new StructLiteralExp(loc, sd, arraySyntaxCopy(elements));
-}
-
-Expression *StructLiteralExp::semantic(Scope *sc)
-{   Expression *e;
-
-#if LOGSEMANTIC
-    printf("StructLiteralExp::semantic('%s')\n", toChars());
-#endif
-    if (type)
-	return this;
-
-    // Run semantic() on each element
-    for (size_t i = 0; i < elements->dim; i++)
-    {	e = (Expression *)elements->data[i];
-	if (!e)
-	    continue;
-	e = e->semantic(sc);
-	elements->data[i] = (void *)e;
-    }
-    expandTuples(elements);
-    size_t offset = 0;
-    for (size_t i = 0; i < elements->dim; i++)
-    {	e = (Expression *)elements->data[i];
-	if (!e)
-	    continue;
-
-	if (!e->type)
-	    error("%s has no value", e->toChars());
-	e = resolveProperties(sc, e);
-	if (i >= sd->fields.dim)
-	{   error("more initializers than fields of %s", sd->toChars());
-	    break;
-	}
-	Dsymbol *s = (Dsymbol *)sd->fields.data[i];
-	VarDeclaration *v = s->isVarDeclaration();
-	assert(v);
-	if (v->offset < offset)
-	    error("overlapping initialization for %s", v->toChars());
-	offset = v->offset + v->type->size();
-
-	Type *telem = v->type;
-	while (!e->implicitConvTo(telem) && telem->toBasetype()->ty == Tsarray)
-	{   /* Static array initialization, as in:
-	     *	T[3][5] = e;
-	     */
-	    telem = telem->toBasetype()->nextOf();
-	}
-
-	e = e->implicitCastTo(sc, telem);
-
-	elements->data[i] = (void *)e;
-    }
-
-    /* Fill out remainder of elements[] with default initializers for fields[]
-     */
-    for (size_t i = elements->dim; i < sd->fields.dim; i++)
-    {	Dsymbol *s = (Dsymbol *)sd->fields.data[i];
-	VarDeclaration *v = s->isVarDeclaration();
-	assert(v);
-
-	if (v->offset < offset)
-	{   e = NULL;
-	    sd->hasUnions = 1;
-	}
-	else
-	{
-	    if (v->init)
-	    {   e = v->init->toExpression();
-		if (!e)
-		    error("cannot make expression out of initializer for %s", v->toChars());
-	    }
-	    else
-	    {	e = v->type->defaultInit();
-		e->loc = loc;
-	    }
-	    offset = v->offset + v->type->size();
-	}
-	elements->push(e);
-    }
-
-    type = sd->type;
-    return this;
-}
-
-/**************************************
- * Gets expression at offset of type.
- * Returns NULL if not found.
- */
-
-Expression *StructLiteralExp::getField(Type *type, unsigned offset)
-{
-    //printf("StructLiteralExp::getField(this = %s, type = %s, offset = %u)\n",
-//	/*toChars()*/"", type->toChars(), offset);
-    Expression *e = NULL;
-    int i = getFieldIndex(type, offset);
-
-    if (i != -1)
-    {
-	//printf("\ti = %d\n", i);
-	assert(i < elements->dim);
-	e = (Expression *)elements->data[i];
-	if (e)
-	{
-	    e = e->copy();
-	    e->type = type;
-	}
-    }
-    return e;
-}
-
-/************************************
- * Get index of field.
- * Returns -1 if not found. 
- */
-
-int StructLiteralExp::getFieldIndex(Type *type, unsigned offset)
-{
-    /* Find which field offset is by looking at the field offsets
-     */
-    for (size_t i = 0; i < sd->fields.dim; i++)
-    {
-	Dsymbol *s = (Dsymbol *)sd->fields.data[i];
-	VarDeclaration *v = s->isVarDeclaration();
-	assert(v);
-
-	if (offset == v->offset &&
-	    type->size() == v->type->size())
-	{   Expression *e = (Expression *)elements->data[i];
-	    if (e)
-	    {
-		return i;
-	    }
-	    break;
-	}
-    }
-    return -1;
-}
-
-int StructLiteralExp::isLvalue()
-{
-    return 1;
-}
-
-Expression *StructLiteralExp::toLvalue(Scope *sc, Expression *e)
-{
-    return this;
-}
-
-
-int StructLiteralExp::checkSideEffect(int flag)
-{   int f = 0;
-
-    for (size_t i = 0; i < elements->dim; i++)
-    {	Expression *e = (Expression *)elements->data[i];
-	if (!e)
-	    continue;
-
-	f |= e->checkSideEffect(2);
-    }
-    if (flag == 0 && f == 0)
-	Expression::checkSideEffect(0);
-    return f;
-}
-
-int StructLiteralExp::canThrow()
-{
-    return arrayExpressionCanThrow(elements);
-}
-
-void StructLiteralExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{
-    buf->writestring(sd->toChars());
-    buf->writeByte('(');
-    argsToCBuffer(buf, elements, hgs);
-    buf->writeByte(')');
-}
-
-void StructLiteralExp::toMangleBuffer(OutBuffer *buf)
-{
-    size_t dim = elements ? elements->dim : 0;
-    buf->printf("S%u", dim);
-    for (size_t i = 0; i < dim; i++)
-    {	Expression *e = (Expression *)elements->data[i];
-	if (e)
-	    e->toMangleBuffer(buf);
-	else
-	    buf->writeByte('v');	// 'v' for void
-    }
-}
-
-/************************ TypeDotIdExp ************************************/
-
-/* Things like:
- *	int.size
- *	foo.size
- *	(foo).size
- *	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());
-}
-
-/************************************************************/
-
-// Mainly just a placeholder
-
-TypeExp::TypeExp(Loc loc, Type *type)
-    : Expression(loc, TOKtype, sizeof(TypeExp))
-{
-    //printf("TypeExp::TypeExp(%s)\n", type->toChars());
-    this->type = type;
-}
-
-Expression *TypeExp::semantic(Scope *sc)
-{
-    //printf("TypeExp::semantic(%s)\n", type->toChars());
-    type = type->semantic(loc, sc);
-    return this;
-}
-
-void TypeExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{
-    type->toCBuffer(buf, NULL, hgs);
-}
-
-/************************************************************/
-
-// Mainly just a placeholder
-
-ScopeExp::ScopeExp(Loc loc, ScopeDsymbol *pkg)
-    : Expression(loc, TOKimport, sizeof(ScopeExp))
-{
-    //printf("ScopeExp::ScopeExp(pkg = '%s')\n", pkg->toChars());
-    //static int count; if (++count == 38) *(char*)0=0;
-    this->sds = pkg;
-}
-
-Expression *ScopeExp::syntaxCopy()
-{
-    ScopeExp *se = new ScopeExp(loc, (ScopeDsymbol *)sds->syntaxCopy(NULL));
-    return se;
-}
-
-Expression *ScopeExp::semantic(Scope *sc)
-{
-    TemplateInstance *ti;
-    ScopeDsymbol *sds2;
-
-#if LOGSEMANTIC
-    printf("+ScopeExp::semantic('%s')\n", toChars());
-#endif
-Lagain:
-    ti = sds->isTemplateInstance();
-    if (ti && !global.errors)
-    {	Dsymbol *s;
-	if (!ti->semanticdone)
-	    ti->semantic(sc);
-	s = ti->inst->toAlias();
-	sds2 = s->isScopeDsymbol();
-	if (!sds2)
-	{   Expression *e;
-
-	    //printf("s = %s, '%s'\n", s->kind(), s->toChars());
-	    if (ti->withsym)
-	    {
-		// Same as wthis.s
-		e = new VarExp(loc, ti->withsym->withstate->wthis);
-		e = new DotVarExp(loc, e, s->isDeclaration());
-	    }
-	    else
-		e = new DsymbolExp(loc, s);
-	    e = e->semantic(sc);
-	    //printf("-1ScopeExp::semantic()\n");
-	    return e;
-	}
-	if (sds2 != sds)
-	{
-	    sds = sds2;
-	    goto Lagain;
-	}
-	//printf("sds = %s, '%s'\n", sds->kind(), sds->toChars());
-    }
-    else
-    {
-	//printf("sds = %s, '%s'\n", sds->kind(), sds->toChars());
-	//printf("\tparent = '%s'\n", sds->parent->toChars());
-	sds->semantic(sc);
-    }
-    type = Type::tvoid;
-    //printf("-2ScopeExp::semantic() %s\n", toChars());
-    return this;
-}
-
-void ScopeExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{
-    if (sds->isTemplateInstance())
-    {
-        sds->toCBuffer(buf, hgs);
-    }
-    else
-    {
-	buf->writestring(sds->kind());
-	buf->writestring(" ");
-	buf->writestring(sds->toChars());
-    }
-}
-
-/********************** TemplateExp **************************************/
-
-// Mainly just a placeholder
-
-TemplateExp::TemplateExp(Loc loc, TemplateDeclaration *td)
-    : Expression(loc, TOKtemplate, sizeof(TemplateExp))
-{
-    //printf("TemplateExp(): %s\n", td->toChars());
-    this->td = td;
-}
-
-void TemplateExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{
-    buf->writestring(td->toChars());
-}
-
-void TemplateExp::rvalue()
-{
-    error("template %s has no value", toChars());
-}
-
-/********************** NewExp **************************************/
-
-/* thisexp.new(newargs) newtype(arguments) */
-
-NewExp::NewExp(Loc loc, Expression *thisexp, Expressions *newargs,
-	Type *newtype, Expressions *arguments)
-    : Expression(loc, TOKnew, sizeof(NewExp))
-{
-    this->thisexp = thisexp;
-    this->newargs = newargs;
-    this->newtype = newtype;
-    this->arguments = arguments;
-    member = NULL;
-    allocator = NULL;
-    onstack = 0;
-}
-
-Expression *NewExp::syntaxCopy()
-{
-    return new NewExp(loc,
-	thisexp ? thisexp->syntaxCopy() : NULL,
-	arraySyntaxCopy(newargs),
-	newtype->syntaxCopy(), arraySyntaxCopy(arguments));
-}
-
-
-Expression *NewExp::semantic(Scope *sc)
-{   int i;
-    Type *tb;
-    ClassDeclaration *cdthis = NULL;
-
-#if LOGSEMANTIC
-    printf("NewExp::semantic() %s\n", toChars());
-    if (thisexp)
-	printf("\tthisexp = %s\n", thisexp->toChars());
-    printf("\tnewtype: %s\n", newtype->toChars());
-#endif
-    if (type)			// if semantic() already run
-	return this;
-
-Lagain:
-    if (thisexp)
-    {	thisexp = thisexp->semantic(sc);
-	cdthis = thisexp->type->isClassHandle();
-	if (cdthis)
-	{
-	    sc = sc->push(cdthis);
-	    type = newtype->semantic(loc, sc);
-	    sc = sc->pop();
-	}
-	else
-	{
-	    error("'this' for nested class must be a class type, not %s", thisexp->type->toChars());
-	    type = newtype->semantic(loc, sc);
-	}
-    }
-    else
-	type = newtype->semantic(loc, sc);
-    newtype = type;		// in case type gets cast to something else
-    tb = type->toBasetype();
-    //printf("tb: %s, deco = %s\n", tb->toChars(), tb->deco);
-
-    arrayExpressionSemantic(newargs, sc);
-    preFunctionArguments(loc, sc, newargs);
-    arrayExpressionSemantic(arguments, sc);
-    preFunctionArguments(loc, sc, arguments);
-
-    if (thisexp && tb->ty != Tclass)
-	error("e.new is only for allocating nested classes, not %s", tb->toChars());
-
-    if (tb->ty == Tclass)
-    {	TypeFunction *tf;
-
-	TypeClass *tc = (TypeClass *)(tb);
-	ClassDeclaration *cd = tc->sym->isClassDeclaration();
-	if (cd->isInterfaceDeclaration())
-	    error("cannot create instance of interface %s", cd->toChars());
-	else if (cd->isAbstract())
-	{   error("cannot create instance of abstract class %s", cd->toChars());
-	    for (int i = 0; i < cd->vtbl.dim; i++)
-	    {	FuncDeclaration *fd = ((Dsymbol *)cd->vtbl.data[i])->isFuncDeclaration();
-		if (fd && fd->isAbstract())
-		    error("function %s is abstract", fd->toChars());
-	    }
-	}
-	checkDeprecated(sc, cd);
-	if (cd->isNested())
-	{   /* We need a 'this' pointer for the nested class.
-	     * Ensure we have the right one.
-	     */
-	    Dsymbol *s = cd->toParent2();
-	    ClassDeclaration *cdn = s->isClassDeclaration();
-	    FuncDeclaration *fdn = s->isFuncDeclaration();
-
-	    //printf("cd isNested, cdn = %s\n", cdn ? cdn->toChars() : "null");
-	    if (cdn)
-	    {
-		if (!cdthis)
-		{
-		    // Supply an implicit 'this' and try again
-		    thisexp = new ThisExp(loc);
-		    for (Dsymbol *sp = sc->parent; 1; sp = sp->parent)
-		    {	if (!sp)
-			{
-			    error("outer class %s 'this' needed to 'new' nested class %s", cdn->toChars(), cd->toChars());
-			    break;
-			}
-			ClassDeclaration *cdp = sp->isClassDeclaration();
-			if (!cdp)
-			    continue;
-			if (cdp == cdn || cdn->isBaseOf(cdp, NULL))
-			    break;
-			// Add a '.outer' and try again
-			thisexp = new DotIdExp(loc, thisexp, Id::outer);
-		    }
-		    if (!global.errors)
-			goto Lagain;
-		}
-		if (cdthis)
-		{
-		    //printf("cdthis = %s\n", cdthis->toChars());
-		    if (cdthis != cdn && !cdn->isBaseOf(cdthis, NULL))
-			error("'this' for nested class must be of type %s, not %s", cdn->toChars(), thisexp->type->toChars());
-		}
-#if 0
-		else
-		{
-		    for (Dsymbol *sf = sc->func; 1; sf= sf->toParent2()->isFuncDeclaration())
-		    {
-			if (!sf)
-			{
-			    error("outer class %s 'this' needed to 'new' nested class %s", cdn->toChars(), cd->toChars());
-			    break;
-			}
-			printf("sf = %s\n", sf->toChars());
-			AggregateDeclaration *ad = sf->isThis();
-			if (ad && (ad == cdn || cdn->isBaseOf(ad->isClassDeclaration(), NULL)))
-			    break;
-		    }
-		}
-#endif
-	    }
-        // LDC , check if reachable
-	    else if (fdn)
-	    {
-		// make sure the parent context fdn of cd is reachable from sc
-		for (Dsymbol *sp = sc->parent; 1; sp = sp->parent)
-		{
-		    if (fdn == sp)
-			break;
-		    FuncDeclaration *fsp = sp ? sp->isFuncDeclaration() : NULL;
-		    if (!sp || (fsp && fsp->isStatic()))
-		    {
-			error("outer function context of %s is needed to 'new' nested class %s", fdn->toPrettyChars(), cd->toPrettyChars());
-			break;
-		    }
-		}
-		
-	    }
-        else
-        assert(0);   
-	}
-	else if (thisexp)
-	    error("e.new is only for allocating nested classes");
-
-	FuncDeclaration *f = cd->ctor;
-	if (f)
-	{
-	    assert(f);
-	    f = f->overloadResolve(loc, NULL, arguments);
-	    checkDeprecated(sc, f);
-	    member = f->isCtorDeclaration();
-	    assert(member);
-
-	    cd->accessCheck(loc, sc, member);
-
-	    tf = (TypeFunction *)f->type;
-//	    type = tf->next;
-
-	    if (!arguments)
-		arguments = new Expressions();
-	    functionArguments(loc, sc, tf, arguments);
-	}
-	else
-	{
-	    if (arguments && arguments->dim)
-		error("no constructor for %s", cd->toChars());
-	}
-
-	if (cd->aggNew)
-	{
-	    // Prepend the size_t size argument to newargs[]
-	    Expression *e = new IntegerExp(loc, cd->size(loc), Type::tsize_t);
-	    if (!newargs)
-		newargs = new Expressions();
-	    newargs->shift(e);
-
-	    f = cd->aggNew->overloadResolve(loc, NULL, newargs);
-	    allocator = f->isNewDeclaration();
-	    assert(allocator);
-
-	    tf = (TypeFunction *)f->type;
-	    functionArguments(loc, sc, tf, newargs);
-	}
-	else
-	{
-	    if (newargs && newargs->dim)
-		error("no allocator for %s", cd->toChars());
-	}
-    }
-    else if (tb->ty == Tstruct)
-    {
-	TypeStruct *ts = (TypeStruct *)tb;
-	StructDeclaration *sd = ts->sym;
-	TypeFunction *tf;
-
-	FuncDeclaration *f = sd->ctor;
-	if (f && arguments && arguments->dim)
-	{
-	    assert(f);
-	    f = f->overloadResolve(loc, NULL, arguments);
-	    checkDeprecated(sc, f);
-	    member = f->isCtorDeclaration();
-	    assert(member);
-
-	    sd->accessCheck(loc, sc, member);
-
-	    tf = (TypeFunction *)f->type;
-//	    type = tf->next;
-
-	    if (!arguments)
-		arguments = new Expressions();
-	    functionArguments(loc, sc, tf, arguments);
-	}
-	else
-	{
-	    if (arguments && arguments->dim)
-		error("no constructor for %s", sd->toChars());
-	}
-
-
-	if (sd->aggNew)
-	{
-	    // Prepend the uint size argument to newargs[]
-	    Expression *e = new IntegerExp(loc, sd->size(loc), Type::tuns32);
-	    if (!newargs)
-		newargs = new Expressions();
-	    newargs->shift(e);
-
-	    f = sd->aggNew->overloadResolve(loc, NULL, newargs);
-	    allocator = f->isNewDeclaration();
-	    assert(allocator);
-
-	    tf = (TypeFunction *)f->type;
-	    functionArguments(loc, sc, tf, newargs);
-#if 0
-	    e = new VarExp(loc, f);
-	    e = new CallExp(loc, e, newargs);
-	    e = e->semantic(sc);
-	    e->type = type->pointerTo();
-	    return e;
-#endif
-	}
-	else
-	{
-	    if (newargs && newargs->dim)
-		error("no allocator for %s", sd->toChars());
-	}
-
-	type = type->pointerTo();
-    }
-    else if (tb->ty == Tarray && (arguments && arguments->dim))
-    {
-	for (size_t i = 0; i < arguments->dim; i++)
-	{
-	    if (tb->ty != Tarray)
-	    {	error("too many arguments for array");
-		arguments->dim = i;
-		break;
-	    }
-
-	    Expression *arg = (Expression *)arguments->data[i];
-	    arg = resolveProperties(sc, arg);
-	    arg = arg->implicitCastTo(sc, Type::tsize_t);
-	    arg = arg->optimize(WANTvalue);
-	    if (arg->op == TOKint64 && (long long)arg->toInteger() < 0)
-		error("negative array index %s", arg->toChars());
-	    arguments->data[i] = (void *) arg;
-	    tb = ((TypeDArray *)tb)->next->toBasetype();
-	}
-    }
-    else if (tb->isscalar())
-    {
-	if (arguments && arguments->dim)
-	    error("no constructor for %s", type->toChars());
-
-	type = type->pointerTo();
-    }
-    else
-    {
-	error("new can only create structs, dynamic arrays or class objects, not %s's", type->toChars());
-	type = type->pointerTo();
-    }
-
-//printf("NewExp: '%s'\n", toChars());
-//printf("NewExp:type '%s'\n", type->toChars());
-
-    return this;
-}
-
-int NewExp::checkSideEffect(int flag)
-{
-    return 1;
-}
-
-int NewExp::canThrow()
-{
-    return 1;
-}
-
-void NewExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{   int i;
-
-    if (thisexp)
-    {	expToCBuffer(buf, hgs, thisexp, PREC_primary);
-	buf->writeByte('.');
-    }
-    buf->writestring("new ");
-    if (newargs && newargs->dim)
-    {
-	buf->writeByte('(');
-	argsToCBuffer(buf, newargs, hgs);
-	buf->writeByte(')');
-    }
-    newtype->toCBuffer(buf, NULL, hgs);
-    if (arguments && arguments->dim)
-    {
-	buf->writeByte('(');
-	argsToCBuffer(buf, arguments, hgs);
-	buf->writeByte(')');
-    }
-}
-
-/********************** NewAnonClassExp **************************************/
-
-NewAnonClassExp::NewAnonClassExp(Loc loc, Expression *thisexp,
-	Expressions *newargs, ClassDeclaration *cd, Expressions *arguments)
-    : Expression(loc, TOKnewanonclass, sizeof(NewAnonClassExp))
-{
-    this->thisexp = thisexp;
-    this->newargs = newargs;
-    this->cd = cd;
-    this->arguments = arguments;
-}
-
-Expression *NewAnonClassExp::syntaxCopy()
-{
-    return new NewAnonClassExp(loc,
-	thisexp ? thisexp->syntaxCopy() : NULL,
-	arraySyntaxCopy(newargs),
-	(ClassDeclaration *)cd->syntaxCopy(NULL),
-	arraySyntaxCopy(arguments));
-}
-
-
-Expression *NewAnonClassExp::semantic(Scope *sc)
-{
-#if LOGSEMANTIC
-    printf("NewAnonClassExp::semantic() %s\n", toChars());
-    //printf("thisexp = %p\n", thisexp);
-    //printf("type: %s\n", type->toChars());
-#endif
-
-    Expression *d = new DeclarationExp(loc, cd);
-    d = d->semantic(sc);
-
-    Expression *n = new NewExp(loc, thisexp, newargs, cd->type, arguments);
-
-    Expression *c = new CommaExp(loc, d, n);
-    return c->semantic(sc);
-}
-
-int NewAnonClassExp::checkSideEffect(int flag)
-{
-    return 1;
-}
-
-int NewAnonClassExp::canThrow()
-{
-    return 1;
-}
-
-void NewAnonClassExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{   int i;
-
-    if (thisexp)
-    {	expToCBuffer(buf, hgs, thisexp, PREC_primary);
-	buf->writeByte('.');
-    }
-    buf->writestring("new");
-    if (newargs && newargs->dim)
-    {
-	buf->writeByte('(');
-	argsToCBuffer(buf, newargs, hgs);
-	buf->writeByte(')');
-    }
-    buf->writestring(" class ");
-    if (arguments && arguments->dim)
-    {
-	buf->writeByte('(');
-	argsToCBuffer(buf, arguments, hgs);
-	buf->writeByte(')');
-    }
-    //buf->writestring(" { }");
-    if (cd)
-    {
-        cd->toCBuffer(buf, hgs);
-    }
-}
-
-/********************** SymbolExp **************************************/
-
-SymbolExp::SymbolExp(Loc loc, enum TOK op, int size, Declaration *var, int hasOverloads)
-    : Expression(loc, op, size)
-{
-    assert(var);
-    this->var = var;
-    this->hasOverloads = hasOverloads;
-}
-
-/********************** SymOffExp **************************************/
-
-SymOffExp::SymOffExp(Loc loc, Declaration *var, unsigned offset, int hasOverloads)
-    : SymbolExp(loc, TOKsymoff, sizeof(SymOffExp), var, hasOverloads)
-{
-    this->offset = offset;
-
-    VarDeclaration *v = var->isVarDeclaration();
-    if (v && v->needThis())
-	error("need 'this' for address of %s", v->toChars());
-}
-
-Expression *SymOffExp::semantic(Scope *sc)
-{
-#if LOGSEMANTIC
-    printf("SymOffExp::semantic('%s')\n", toChars());
-#endif
-    //var->semantic(sc);
-    if (!type)
-	type = var->type->pointerTo();
-    VarDeclaration *v = var->isVarDeclaration();
-    if (v)
-    {
-    v->checkNestedReference(sc, loc);
-    }
-    return this;
-}
-
-int SymOffExp::isBool(int result)
-{
-    return result ? TRUE : FALSE;
-}
-
-void SymOffExp::checkEscape()
-{
-    VarDeclaration *v = var->isVarDeclaration();
-    if (v)
-    {
-	if (!v->isDataseg())
-	    error("escaping reference to local variable %s", v->toChars());
-    }
-}
-
-void SymOffExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{
-    if (offset)
-	buf->printf("(& %s+%u)", var->toChars(), offset);
-    else
-	buf->printf("& %s", var->toChars());
-}
-
-/******************************** VarExp **************************/
-
-VarExp::VarExp(Loc loc, Declaration *var, int hasOverloads)
-    : SymbolExp(loc, TOKvar, sizeof(VarExp), var, hasOverloads)
-{
-    //printf("VarExp(this = %p, '%s', loc = %s)\n", this, var->toChars(), loc.toChars());
-    //if (strcmp(var->ident->toChars(), "func") == 0) halt();
-    this->type = var->type;
-}
-
-int VarExp::equals(Object *o)
-{   VarExp *ne;
-
-    if (this == o ||
-	(((Expression *)o)->op == TOKvar &&
-	 ((ne = (VarExp *)o), type->toHeadMutable()->equals(ne->type->toHeadMutable())) &&
-	 var == ne->var))
-	return 1;
-    return 0;
-}
-
-Expression *VarExp::semantic(Scope *sc)
-{   FuncLiteralDeclaration *fd;
-
-#if LOGSEMANTIC
-    printf("VarExp::semantic(%s)\n", toChars());
-#endif
-    if (!type)
-    {	type = var->type;
-#if 0
-	if (var->storage_class & STClazy)
-	{
-	    TypeFunction *tf = new TypeFunction(NULL, type, 0, LINKd);
-	    type = new TypeDelegate(tf);
-	    type = type->semantic(loc, sc);
-	}
-#endif
-    }
-
-    VarDeclaration *v = var->isVarDeclaration();
-    if (v)
-    {
-#if 0
-	if ((v->isConst() || v->isInvariant()) &&
-	    type->toBasetype()->ty != Tsarray && v->init)
-	{
-	    ExpInitializer *ei = v->init->isExpInitializer();
-	    if (ei)
-	    {
-		//ei->exp->implicitCastTo(sc, type)->print();
-		return ei->exp->implicitCastTo(sc, type);
-	    }
-	}
-#endif
-	v->checkNestedReference(sc, loc);
-    }
-#if 0
-    else if ((fd = var->isFuncLiteralDeclaration()) != NULL)
-    {	Expression *e;
-	e = new FuncExp(loc, fd);
-	e->type = type;
-	return e;
-    }
-#endif
-    return this;
-}
-
-char *VarExp::toChars()
-{
-    return var->toChars();
-}
-
-void VarExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{
-    buf->writestring(var->toChars());
-}
-
-void VarExp::checkEscape()
-{
-    VarDeclaration *v = var->isVarDeclaration();
-    if (v)
-    {	Type *tb = v->type->toBasetype();
-	// if reference type
-	if (tb->ty == Tarray || tb->ty == Tsarray || tb->ty == Tclass)
-	{
-	    if ((v->isAuto() || v->isScope()) && !v->noauto)
-		error("escaping reference to auto local %s", v->toChars());
-	    else if (v->storage_class & STCvariadic)
-		error("escaping reference to variadic parameter %s", v->toChars());
-	}
-    }
-}
-
-int VarExp::isLvalue()
-{
-    if (var->storage_class & STClazy)
-	return 0;
-    return 1;
-}
-
-Expression *VarExp::toLvalue(Scope *sc, Expression *e)
-{
-#if 0
-    tym = tybasic(e1->ET->Tty);
-    if (!(tyscalar(tym) ||
-	  tym == TYstruct ||
-	  tym == TYarray && e->Eoper == TOKaddr))
-	    synerr(EM_lvalue);	// lvalue expected
-#endif
-    if (var->storage_class & STClazy)
-	error("lazy variables cannot be lvalues");
-    return this;
-}
-
-Expression *VarExp::modifiableLvalue(Scope *sc, Expression *e)
-{
-    //printf("VarExp::modifiableLvalue('%s')\n", var->toChars());
-    if (type && type->toBasetype()->ty == Tsarray)
-	error("cannot change reference to static array '%s'", var->toChars());
-
-    var->checkModify(loc, sc, type);
-
-    // See if this expression is a modifiable lvalue (i.e. not const)
-    return toLvalue(sc, e);
-}
-
-
-/******************************** OverExp **************************/
-
-#if DMDV2
-OverExp::OverExp(OverloadSet *s)
-	: Expression(loc, TOKoverloadset, sizeof(OverExp))
-{
-    //printf("OverExp(this = %p, '%s')\n", this, var->toChars());
-    vars = s;
-    type = Type::tvoid;
-}
-
-int OverExp::isLvalue()
-{
-    return 1;
-}
-
-Expression *OverExp::toLvalue(Scope *sc, Expression *e)
-{
-    return this;
-}
-#endif
-
-
-/******************************** TupleExp **************************/
-
-TupleExp::TupleExp(Loc loc, Expressions *exps)
-	: Expression(loc, TOKtuple, sizeof(TupleExp))
-{
-    //printf("TupleExp(this = %p)\n", this);
-    this->exps = exps;
-    this->type = NULL;
-}
-
-
-TupleExp::TupleExp(Loc loc, TupleDeclaration *tup)
-	: Expression(loc, TOKtuple, sizeof(TupleExp))
-{
-    exps = new Expressions();
-    type = NULL;
-
-    exps->reserve(tup->objects->dim);
-    for (size_t i = 0; i < tup->objects->dim; i++)
-    {   Object *o = (Object *)tup->objects->data[i];
-	if (o->dyncast() == DYNCAST_EXPRESSION)
-	{
-	    Expression *e = (Expression *)o;
-	    e = e->syntaxCopy();
-	    exps->push(e);
-	}
-	else if (o->dyncast() == DYNCAST_DSYMBOL)
-	{
-	    Dsymbol *s = (Dsymbol *)o;
-	    Expression *e = new DsymbolExp(loc, s);
-	    exps->push(e);
-	}
-	else if (o->dyncast() == DYNCAST_TYPE)
-	{
-	    Type *t = (Type *)o;
-	    Expression *e = new TypeExp(loc, t);
-	    exps->push(e);
-	}
-	else
-	{
-	    error("%s is not an expression", o->toChars());
-	}
-    }
-}
-
-int TupleExp::equals(Object *o)
-{   TupleExp *ne;
-
-    if (this == o)
-	return 1;
-    if (((Expression *)o)->op == TOKtuple)
-    {
-	TupleExp *te = (TupleExp *)o;
-	if (exps->dim != te->exps->dim)
-	    return 0;
-	for (size_t i = 0; i < exps->dim; i++)
-	{   Expression *e1 = (Expression *)exps->data[i];
-	    Expression *e2 = (Expression *)te->exps->data[i];
-
-	    if (!e1->equals(e2))
-		return 0;
-	}
-	return 1;
-    }
-    return 0;
-}
-
-Expression *TupleExp::syntaxCopy()
-{
-    return new TupleExp(loc, arraySyntaxCopy(exps));
-}
-
-Expression *TupleExp::semantic(Scope *sc)
-{
-#if LOGSEMANTIC
-    printf("+TupleExp::semantic(%s)\n", toChars());
-#endif
-    if (type)
-	return this;
-
-    // Run semantic() on each argument
-    for (size_t i = 0; i < exps->dim; i++)
-    {	Expression *e = (Expression *)exps->data[i];
-
-	e = e->semantic(sc);
-	if (!e->type)
-	{   error("%s has no value", e->toChars());
-	    e->type = Type::terror;
-	}
-	exps->data[i] = (void *)e;
-    }
-
-    expandTuples(exps);
-    if (0 && exps->dim == 1)
-    {
-	return (Expression *)exps->data[0];
-    }
-    type = new TypeTuple(exps);
-    //printf("-TupleExp::semantic(%s)\n", toChars());
-    return this;
-}
-
-void TupleExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{
-    buf->writestring("tuple(");
-    argsToCBuffer(buf, exps, hgs);
-    buf->writeByte(')');
-}
-
-int TupleExp::checkSideEffect(int flag)
-{   int f = 0;
-
-    for (int i = 0; i < exps->dim; i++)
-    {	Expression *e = (Expression *)exps->data[i];
-
-	f |= e->checkSideEffect(2);
-    }
-    if (flag == 0 && f == 0)
-	Expression::checkSideEffect(0);
-    return f;
-}
-
-int TupleExp::canThrow()
-{
-    return arrayExpressionCanThrow(exps);
-}
-
-void TupleExp::checkEscape()
-{
-    for (size_t i = 0; i < exps->dim; i++)
-    {   Expression *e = (Expression *)exps->data[i];
-	e->checkEscape();
-    }
-}
-
-/******************************** FuncExp *********************************/
-
-FuncExp::FuncExp(Loc loc, FuncLiteralDeclaration *fd)
-	: Expression(loc, TOKfunction, sizeof(FuncExp))
-{
-    this->fd = fd;
-}
-
-Expression *FuncExp::syntaxCopy()
-{
-    return new FuncExp(loc, (FuncLiteralDeclaration *)fd->syntaxCopy(NULL));
-}
-
-Expression *FuncExp::semantic(Scope *sc)
-{
-#if LOGSEMANTIC
-    printf("FuncExp::semantic(%s)\n", toChars());
-#endif
-    if (!type)
-    {
-	fd->semantic(sc);
-	fd->parent = sc->parent;
-	if (global.errors)
-	{
-	}
-	else
-	{
-	    fd->semantic2(sc);
-	    if (!global.errors)
-	    {
-		fd->semantic3(sc);
-
-		if (!global.errors && global.params.useInline)
-		    fd->inlineScan();
-	    }
-	}
-
-	// Type is a "delegate to" or "pointer to" the function literal
-	if (fd->isNested())
-	{
-	    type = new TypeDelegate(fd->type);
-	    type = type->semantic(loc, sc);
-	}
-	else
-	{
-	    type = fd->type->pointerTo();
-	}
-	fd->tookAddressOf++;
-    }
-    return this;
-}
-
-char *FuncExp::toChars()
-{
-    return fd->toChars();
-}
-
-void FuncExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{
-    buf->writestring(fd->toChars());
-}
-
-
-/******************************** DeclarationExp **************************/
-
-DeclarationExp::DeclarationExp(Loc loc, Dsymbol *declaration)
-	: Expression(loc, TOKdeclaration, sizeof(DeclarationExp))
-{
-    this->declaration = declaration;
-}
-
-Expression *DeclarationExp::syntaxCopy()
-{
-    return new DeclarationExp(loc, declaration->syntaxCopy(NULL));
-}
-
-Expression *DeclarationExp::semantic(Scope *sc)
-{
-    if (type)
-	return this;
-
-#if LOGSEMANTIC
-    printf("DeclarationExp::semantic() %s\n", toChars());
-#endif
-
-    /* This is here to support extern(linkage) declaration,
-     * where the extern(linkage) winds up being an AttribDeclaration
-     * wrapper.
-     */
-    Dsymbol *s = declaration;
-
-    AttribDeclaration *ad = declaration->isAttribDeclaration();
-    if (ad)
-    {
-	if (ad->decl && ad->decl->dim == 1)
-	    s = (Dsymbol *)ad->decl->data[0];
-    }
-
-    if (s->isVarDeclaration())
-    {	// Do semantic() on initializer first, so:
-	//	int a = a;
-	// will be illegal.
-	declaration->semantic(sc);
-	s->parent = sc->parent;
-    }
-
-    //printf("inserting '%s' %p into sc = %p\n", s->toChars(), s, sc);
-    // Insert into both local scope and function scope.
-    // Must be unique in both.
-    if (s->ident)
-    {
-	if (!sc->insert(s))
-	    error("declaration %s is already defined", s->toPrettyChars());
-	else if (sc->func)
-	{   VarDeclaration *v = s->isVarDeclaration();
-	    if (s->isFuncDeclaration() &&
-		!sc->func->localsymtab->insert(s))
-		error("declaration %s is already defined in another scope in %s", s->toPrettyChars(), sc->func->toChars());
-	    else if (!global.params.useDeprecated)
-	    {	// Disallow shadowing
-
-		for (Scope *scx = sc->enclosing; scx && scx->func == sc->func; scx = scx->enclosing)
-		{   Dsymbol *s2;
-
-		    if (scx->scopesym && scx->scopesym->symtab &&
-			(s2 = scx->scopesym->symtab->lookup(s->ident)) != NULL &&
-			s != s2)
-		    {
-			error("shadowing declaration %s is deprecated", s->toPrettyChars());
-		    }
-		}
-	    }
-	}
-    }
-    if (!s->isVarDeclaration())
-    {
-	declaration->semantic(sc);
-	s->parent = sc->parent;
-    }
-    if (!global.errors)
-    {
-	declaration->semantic2(sc);
-	if (!global.errors)
-	{
-	    declaration->semantic3(sc);
-
-	    if (!global.errors && global.params.useInline)
-		declaration->inlineScan();
-	}
-    }
-
-    type = Type::tvoid;
-    return this;
-}
-
-int DeclarationExp::checkSideEffect(int flag)
-{
-    return 1;
-}
-
-int DeclarationExp::canThrow()
-{
-    VarDeclaration *v = declaration->isVarDeclaration();
-    if (v && v->init)
-    {	ExpInitializer *ie = v->init->isExpInitializer();
-	return ie && ie->exp->canThrow();
-    }
-    return 0;
-}
-
-void DeclarationExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{
-    declaration->toCBuffer(buf, hgs);
-}
-
-
-/************************ TypeidExp ************************************/
-
-/*
- *	typeid(int)
- */
-
-TypeidExp::TypeidExp(Loc loc, Type *typeidType)
-    : Expression(loc, TOKtypeid, sizeof(TypeidExp))
-{
-    this->typeidType = typeidType;
-}
-
-
-Expression *TypeidExp::syntaxCopy()
-{
-    return new TypeidExp(loc, typeidType->syntaxCopy());
-}
-
-
-Expression *TypeidExp::semantic(Scope *sc)
-{   Expression *e;
-
-#if LOGSEMANTIC
-    printf("TypeidExp::semantic()\n");
-#endif
-    typeidType = typeidType->semantic(loc, sc);
-    e = typeidType->getTypeInfo(sc);
-    if (e->loc.linnum == 0)
-	e->loc = loc;		// so there's at least some line number info
-    return e;
-}
-
-void TypeidExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{
-    buf->writestring("typeid(");
-    typeidType->toCBuffer(buf, NULL, hgs);
-    buf->writeByte(')');
-}
-
-/************************ TraitsExp ************************************/
-#if DMDV2
-/*
- *	__traits(identifier, args...)
- */
-
-TraitsExp::TraitsExp(Loc loc, Identifier *ident, Objects *args)
-    : Expression(loc, TOKtraits, sizeof(TraitsExp))
-{
-    this->ident = ident;
-    this->args = args;
-}
-
-
-Expression *TraitsExp::syntaxCopy()
-{
-    return new TraitsExp(loc, ident, TemplateInstance::arraySyntaxCopy(args));
-}
-
-
-void TraitsExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{
-    buf->writestring("__traits(");
-    buf->writestring(ident->toChars());
-    if (args)
-    {
-	for (int i = 0; i < args->dim; i++)
-	{
-	    buf->writeByte(',');
-	    Object *oarg = (Object *)args->data[i];
-	    ObjectToCBuffer(buf, hgs, oarg);
-	}
-    }
-    buf->writeByte(')');
-}
-#endif
-
-/************************************************************/
-
-HaltExp::HaltExp(Loc loc)
-	: Expression(loc, TOKhalt, sizeof(HaltExp))
-{
-}
-
-Expression *HaltExp::semantic(Scope *sc)
-{
-#if LOGSEMANTIC
-    printf("HaltExp::semantic()\n");
-#endif
-    type = Type::tvoid;
-    return this;
-}
-
-int HaltExp::checkSideEffect(int flag)
-{
-    return 1;
-}
-
-void HaltExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{
-    buf->writestring("halt");
-}
-
-/************************************************************/
-
-IsExp::IsExp(Loc loc, Type *targ, Identifier *id, enum TOK tok,
-	Type *tspec, enum TOK tok2, TemplateParameters *parameters)
-	: Expression(loc, TOKis, sizeof(IsExp))
-{
-    this->targ = targ;
-    this->id = id;
-    this->tok = tok;
-    this->tspec = tspec;
-    this->tok2 = tok2;
-    this->parameters = parameters;
-}
-
-Expression *IsExp::syntaxCopy()
-{
-    // This section is identical to that in TemplateDeclaration::syntaxCopy()
-    TemplateParameters *p = NULL;
-    if (parameters)
-    {
-	p = new TemplateParameters();
-	p->setDim(parameters->dim);
-	for (int i = 0; i < p->dim; i++)
-	{   TemplateParameter *tp = (TemplateParameter *)parameters->data[i];
-	    p->data[i] = (void *)tp->syntaxCopy();
-	}
-    }
-
-    return new IsExp(loc,
-	targ->syntaxCopy(),
-	id,
-	tok,
-	tspec ? tspec->syntaxCopy() : NULL,
-	tok2,
-	p);
-}
-
-Expression *IsExp::semantic(Scope *sc)
-{   Type *tded;
-
-    /* is(targ id tok tspec)
-     * is(targ id == tok2)
-     */
-
-    //printf("IsExp::semantic(%s)\n", toChars());
-    if (id && !(sc->flags & SCOPEstaticif))
-	error("can only declare type aliases within static if conditionals");
-
-    unsigned errors_save = global.errors;
-    global.errors = 0;
-    global.gag++;			// suppress printing of error messages
-    targ = targ->semantic(loc, sc);
-    global.gag--;
-    unsigned gerrors = global.errors;
-    global.errors = errors_save;
-
-    if (gerrors)			// if any errors happened
-    {					// then condition is false
-	goto Lno;
-    }
-    else if (tok2 != TOKreserved)
-    {
-	switch (tok2)
-	{
-	    case TOKtypedef:
-		if (targ->ty != Ttypedef)
-		    goto Lno;
-		tded = ((TypeTypedef *)targ)->sym->basetype;
-		break;
-
-	    case TOKstruct:
-		if (targ->ty != Tstruct)
-		    goto Lno;
-		if (((TypeStruct *)targ)->sym->isUnionDeclaration())
-		    goto Lno;
-		tded = targ;
-		break;
-
-	    case TOKunion:
-		if (targ->ty != Tstruct)
-		    goto Lno;
-		if (!((TypeStruct *)targ)->sym->isUnionDeclaration())
-		    goto Lno;
-		tded = targ;
-		break;
-
-	    case TOKclass:
-		if (targ->ty != Tclass)
-		    goto Lno;
-		if (((TypeClass *)targ)->sym->isInterfaceDeclaration())
-		    goto Lno;
-		tded = targ;
-		break;
-
-	    case TOKinterface:
-		if (targ->ty != Tclass)
-		    goto Lno;
-		if (!((TypeClass *)targ)->sym->isInterfaceDeclaration())
-		    goto Lno;
-		tded = targ;
-		break;
-#if DMDV2
-	    case TOKconst:
-		if (!targ->isConst())
-		    goto Lno;
-		tded = targ;
-		break;
-
-	    case TOKinvariant:
-	    case TOKimmutable:
-		if (!targ->isInvariant())
-		    goto Lno;
-		tded = targ;
-		break;
-#endif
-
-	    case TOKsuper:
-		// If class or interface, get the base class and interfaces
-		if (targ->ty != Tclass)
-		    goto Lno;
-		else
-		{   ClassDeclaration *cd = ((TypeClass *)targ)->sym;
-		    Arguments *args = new Arguments;
-		    args->reserve(cd->baseclasses.dim);
-		    for (size_t i = 0; i < cd->baseclasses.dim; i++)
-		    {	BaseClass *b = (BaseClass *)cd->baseclasses.data[i];
-			args->push(new Argument(STCin, b->type, NULL, NULL));
-		    }
-		    tded = new TypeTuple(args);
-		}
-		break;
-
-	    case TOKenum:
-		if (targ->ty != Tenum)
-		    goto Lno;
-		tded = ((TypeEnum *)targ)->sym->memtype;
-		break;
-
-	    case TOKdelegate:
-		if (targ->ty != Tdelegate)
-		    goto Lno;
-		tded = ((TypeDelegate *)targ)->next;	// the underlying function type
-		break;
-
-	    case TOKfunction:
-	    {
-		if (targ->ty != Tfunction)
-		    goto Lno;
-		tded = targ;
-
-		/* Generate tuple from function parameter types.
-		 */
-		assert(tded->ty == Tfunction);
-		Arguments *params = ((TypeFunction *)tded)->parameters;
-		size_t dim = Argument::dim(params);
-		Arguments *args = new Arguments;
-		args->reserve(dim);
-		for (size_t i = 0; i < dim; i++)
-		{   Argument *arg = Argument::getNth(params, i);
-		    assert(arg && arg->type);
-		    args->push(new Argument(arg->storageClass, arg->type, NULL, NULL));
-		}
-		tded = new TypeTuple(args);
-		break;
-	    }
-	    case TOKreturn:
-		/* Get the 'return type' for the function,
-		 * delegate, or pointer to function.
-		 */
-		if (targ->ty == Tfunction)
-		    tded = ((TypeFunction *)targ)->next;
-		else if (targ->ty == Tdelegate)
-		{   tded = ((TypeDelegate *)targ)->next;
-		    tded = ((TypeFunction *)tded)->next;
-		}
-		else if (targ->ty == Tpointer &&
-			 ((TypePointer *)targ)->next->ty == Tfunction)
-		{   tded = ((TypePointer *)targ)->next;
-		    tded = ((TypeFunction *)tded)->next;
-		}
-		else
-		    goto Lno;
-		break;
-
-	    default:
-		assert(0);
-	}
-	goto Lyes;
-    }
-    else if (id && tspec)
-    {
-	/* Evaluate to TRUE if targ matches tspec.
-	 * If TRUE, declare id as an alias for the specialized type.
-	 */
-
-	MATCH m;
-	assert(parameters && parameters->dim);
-
-	Objects dedtypes;
-	dedtypes.setDim(parameters->dim);
-	dedtypes.zero();
-
-	m = targ->deduceType(NULL, tspec, parameters, &dedtypes);
-	if (m == MATCHnomatch ||
-	    (m != MATCHexact && tok == TOKequal))
-	    goto Lno;
-	else
-	{
-	    tded = (Type *)dedtypes.data[0];
-	    if (!tded)
-		tded = targ;
-
-	    Objects tiargs;
-	    tiargs.setDim(1);
-	    tiargs.data[0] = (void *)targ;
-
-	    for (int i = 1; i < parameters->dim; i++)
-	    {	TemplateParameter *tp = (TemplateParameter *)parameters->data[i];
-		Declaration *s;
-
-		m = tp->matchArg(sc, &tiargs, i, parameters, &dedtypes, &s);
-		if (m == MATCHnomatch)
-		    goto Lno;
-		s->semantic(sc);
-		if (!sc->insert(s))
-		    error("declaration %s is already defined", s->toChars());
-#if 0
-		Object *o = (Object *)dedtypes.data[i];
-		Dsymbol *s = TemplateDeclaration::declareParameter(loc, sc, tp, o);
-#endif
-		if (sc->sd)
-		    s->addMember(sc, sc->sd, 1);
-	    }
-
-	    goto Lyes;
-	}
-    }
-    else if (id)
-    {
-	/* Declare id as an alias for type targ. Evaluate to TRUE
-	 */
-	tded = targ;
-	goto Lyes;
-    }
-    else if (tspec)
-    {
-	/* Evaluate to TRUE if targ matches tspec
-	 */
-	tspec = tspec->semantic(loc, sc);
-	//printf("targ  = %s\n", targ->toChars());
-	//printf("tspec = %s\n", tspec->toChars());
-	if (tok == TOKcolon)
-	{   if (targ->implicitConvTo(tspec))
-		goto Lyes;
-	    else
-		goto Lno;
-	}
-	else /* == */
-	{   if (targ->equals(tspec))
-		goto Lyes;
-	    else
-		goto Lno;
-	}
-    }
-
-Lyes:
-    if (id)
-    {
-	Dsymbol *s = new AliasDeclaration(loc, id, tded);
-	s->semantic(sc);
-	if (!sc->insert(s))
-	    error("declaration %s is already defined", s->toChars());
-	if (sc->sd)
-	    s->addMember(sc, sc->sd, 1);
-    }
-//printf("Lyes\n");
-    return new IntegerExp(loc, 1, Type::tbool);
-
-Lno:
-//printf("Lno\n");
-    return new IntegerExp(loc, 0, Type::tbool);
-}
-
-void IsExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{
-    buf->writestring("is(");
-    targ->toCBuffer(buf, id, hgs);
-    if (tok2 != TOKreserved)
-    {
-	buf->printf(" %s %s", Token::toChars(tok), Token::toChars(tok2));
-    }
-    else if (tspec)
-    {
-	if (tok == TOKcolon)
-	    buf->writestring(" : ");
-	else
-	    buf->writestring(" == ");
-	tspec->toCBuffer(buf, NULL, hgs);
-    }
-#if DMDV2
-    if (parameters)
-    {	// First parameter is already output, so start with second
-	for (int i = 1; i < parameters->dim; i++)
-	{
-	    buf->writeByte(',');
-	    TemplateParameter *tp = (TemplateParameter *)parameters->data[i];
-	    tp->toCBuffer(buf, hgs);
-	}
-    }
-#endif
-    buf->writeByte(')');
-}
-
-
-/************************************************************/
-
-UnaExp::UnaExp(Loc loc, enum TOK op, int size, Expression *e1)
-	: Expression(loc, op, size)
-{
-    this->e1 = e1;
-}
-
-Expression *UnaExp::syntaxCopy()
-{   UnaExp *e;
-
-    e = (UnaExp *)copy();
-    e->type = NULL;
-    e->e1 = e->e1->syntaxCopy();
-    return e;
-}
-
-Expression *UnaExp::semantic(Scope *sc)
-{
-#if LOGSEMANTIC
-    printf("UnaExp::semantic('%s')\n", toChars());
-#endif
-    e1 = e1->semantic(sc);
-//    if (!e1->type)
-//	error("%s has no value", e1->toChars());
-    return this;
-}
-
-int UnaExp::canThrow()
-{
-    return e1->canThrow();
-}
-
-void UnaExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{
-    buf->writestring(Token::toChars(op));
-    expToCBuffer(buf, hgs, e1, precedence[op]);
-}
-
-/************************************************************/
-
-BinExp::BinExp(Loc loc, enum TOK op, int size, Expression *e1, Expression *e2)
-	: Expression(loc, op, size)
-{
-    this->e1 = e1;
-    this->e2 = e2;
-}
-
-Expression *BinExp::syntaxCopy()
-{   BinExp *e;
-
-    e = (BinExp *)copy();
-    e->type = NULL;
-    e->e1 = e->e1->syntaxCopy();
-    e->e2 = e->e2->syntaxCopy();
-    return e;
-}
-
-Expression *BinExp::semantic(Scope *sc)
-{
-#if LOGSEMANTIC
-    printf("BinExp::semantic('%s')\n", toChars());
-#endif
-    e1 = e1->semantic(sc);
-    if (!e1->type &&
-	!(op == TOKassign && e1->op == TOKdottd))	// a.template = e2
-    {
-	error("%s has no value", e1->toChars());
-	e1->type = Type::terror;
-    }
-    e2 = e2->semantic(sc);
-    if (!e2->type)
-    {
-	error("%s has no value", e2->toChars());
-	e2->type = Type::terror;
-    }
-    return this;
-}
-
-Expression *BinExp::semanticp(Scope *sc)
-{
-    BinExp::semantic(sc);
-    e1 = resolveProperties(sc, e1);
-    e2 = resolveProperties(sc, e2);
-    return this;
-}
-
-/***************************
- * Common semantic routine for some xxxAssignExp's.
- */
-
-Expression *BinExp::commonSemanticAssign(Scope *sc)
-{   Expression *e;
-
-    if (!type)
-    {
-	BinExp::semantic(sc);
-	e2 = resolveProperties(sc, e2);
-
-	e = op_overload(sc);
-	if (e)
-	    return e;
-
-	if (e1->op == TOKslice)
-	{   // T[] op= ...
-	    typeCombine(sc);
-	    type = e1->type;
-	    return arrayOp(sc);
-	}
-
-	e1 = e1->modifiableLvalue(sc, e1);
-	e1->checkScalar();
-	type = e1->type;
-	if (type->toBasetype()->ty == Tbool)
-	{
-	    error("operator not allowed on bool expression %s", toChars());
-	}
-	typeCombine(sc);
-	e1->checkArithmetic();
-	e2->checkArithmetic();
-
-	if (op == TOKmodass && e2->type->iscomplex())
-	{   error("cannot perform modulo complex arithmetic");
-	    return new IntegerExp(0);
-	}
-    }
-    return this;
-}
-
-Expression *BinExp::commonSemanticAssignIntegral(Scope *sc)
-{   Expression *e;
-
-    if (!type)
-    {
-	BinExp::semantic(sc);
-	e2 = resolveProperties(sc, e2);
-
-	e = op_overload(sc);
-	if (e)
-	    return e;
-
-	if (e1->op == TOKslice)
-	{   // T[] op= ...
-	    typeCombine(sc);
-	    type = e1->type;
-	    return arrayOp(sc);
-	}
-
-	e1 = e1->modifiableLvalue(sc, e1);
-	e1->checkScalar();
-	type = e1->type;
-	if (type->toBasetype()->ty == Tbool)
-	{
-	    e2 = e2->implicitCastTo(sc, type);
-	}
-
-	typeCombine(sc);
-	e1->checkIntegral();
-	e2->checkIntegral();
-    }
-    return this;
-}
-
-int BinExp::checkSideEffect(int flag)
-{
-    if (op == TOKplusplus ||
-	   op == TOKminusminus ||
-	   op == TOKassign ||
-	   op == TOKconstruct ||
-	   op == TOKblit ||
-	   op == TOKaddass ||
-	   op == TOKminass ||
-	   op == TOKcatass ||
-	   op == TOKmulass ||
-	   op == TOKdivass ||
-	   op == TOKmodass ||
-	   op == TOKshlass ||
-	   op == TOKshrass ||
-	   op == TOKushrass ||
-	   op == TOKandass ||
-	   op == TOKorass ||
-	   op == TOKxorass ||
-	   op == TOKin ||
-	   op == TOKremove)
-	return 1;
-    return Expression::checkSideEffect(flag);
-}
-
-void BinExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{
-    expToCBuffer(buf, hgs, e1, precedence[op]);
-    buf->writeByte(' ');
-    buf->writestring(Token::toChars(op));
-    buf->writeByte(' ');
-    expToCBuffer(buf, hgs, e2, (enum PREC)(precedence[op] + 1));
-}
-
-int BinExp::isunsigned()
-{
-    return e1->type->isunsigned() || e2->type->isunsigned();
-}
-
-int BinExp::canThrow()
-{
-    return e1->canThrow() || e2->canThrow();
-}
-
-void BinExp::incompatibleTypes()
-{
-    error("incompatible types for ((%s) %s (%s)): '%s' and '%s'",
-         e1->toChars(), Token::toChars(op), e2->toChars(),
-         e1->type->toChars(), e2->type->toChars());
-}
-
-/************************************************************/
-
-CompileExp::CompileExp(Loc loc, Expression *e)
-	: UnaExp(loc, TOKmixin, sizeof(CompileExp), e)
-{
-}
-
-Expression *CompileExp::semantic(Scope *sc)
-{
-#if LOGSEMANTIC
-    printf("CompileExp::semantic('%s')\n", toChars());
-#endif
-    UnaExp::semantic(sc);
-    e1 = resolveProperties(sc, e1);
-    e1 = e1->optimize(WANTvalue | WANTinterpret);
-    if (e1->op != TOKstring)
-    {	error("argument to mixin must be a string, not (%s)", e1->toChars());
-	type = Type::terror;
-	return this;
-    }
-    StringExp *se = (StringExp *)e1;
-    se = se->toUTF8(sc);
-    Parser p(sc->module, (unsigned char *)se->string, se->len, 0);
-    p.loc = loc;
-    p.nextToken();
-    //printf("p.loc.linnum = %d\n", p.loc.linnum);
-    Expression *e = p.parseExpression();
-    if (p.token.value != TOKeof)
-	error("incomplete mixin expression (%s)", se->toChars());
-    return e->semantic(sc);
-}
-
-void CompileExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{
-    buf->writestring("mixin(");
-    expToCBuffer(buf, hgs, e1, PREC_assign);
-    buf->writeByte(')');
-}
-
-/************************************************************/
-
-FileExp::FileExp(Loc loc, Expression *e)
-	: UnaExp(loc, TOKmixin, sizeof(FileExp), e)
-{
-}
-
-Expression *FileExp::semantic(Scope *sc)
-{   char *name;
-    StringExp *se;
-
-#if LOGSEMANTIC
-    printf("FileExp::semantic('%s')\n", toChars());
-#endif
-    UnaExp::semantic(sc);
-    e1 = resolveProperties(sc, e1);
-    e1 = e1->optimize(WANTvalue);
-    if (e1->op != TOKstring)
-    {	error("file name argument must be a string, not (%s)", e1->toChars());
-	goto Lerror;
-    }
-    se = (StringExp *)e1;
-    se = se->toUTF8(sc);
-    name = (char *)se->string;
-
-    if (!global.params.fileImppath)
-    {	error("need -Jpath switch to import text file %s", name);
-	goto Lerror;
-    }
-
-    if (name != FileName::name(name))
-    {	error("use -Jpath switch to provide path for filename %s", name);
-	goto Lerror;
-    }
-
-    name = FileName::searchPath(global.filePath, name, 0);
-    if (!name)
-    {	error("file %s cannot be found, check -Jpath", se->toChars());
-	goto Lerror;
-    }
-
-    if (global.params.verbose)
-	printf("file      %s\t(%s)\n", se->string, name);
-
-    {	File f(name);
-	if (f.read())
-	{   error("cannot read file %s", f.toChars());
-	    goto Lerror;
-	}
-	else
-	{
-	    f.ref = 1;
-	    se = new StringExp(loc, f.buffer, f.len);
-	}
-    }
-  Lret:
-    return se->semantic(sc);
-
-  Lerror:
-    se = new StringExp(loc, (char *)"");
-    goto Lret;
-}
-
-void FileExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{
-    buf->writestring("import(");
-    expToCBuffer(buf, hgs, e1, PREC_assign);
-    buf->writeByte(')');
-}
-
-/************************************************************/
-
-AssertExp::AssertExp(Loc loc, Expression *e, Expression *msg)
-	: UnaExp(loc, TOKassert, sizeof(AssertExp), e)
-{
-    this->msg = msg;
-}
-
-Expression *AssertExp::syntaxCopy()
-{
-    AssertExp *ae = new AssertExp(loc, e1->syntaxCopy(),
-				       msg ? msg->syntaxCopy() : NULL);
-    return ae;
-}
-
-Expression *AssertExp::semantic(Scope *sc)
-{
-#if LOGSEMANTIC
-    printf("AssertExp::semantic('%s')\n", toChars());
-#endif
-    UnaExp::semantic(sc);
-    e1 = resolveProperties(sc, e1);
-    // BUG: see if we can do compile time elimination of the Assert
-    e1 = e1->optimize(WANTvalue);
-    e1 = e1->checkToBoolean();
-    if (msg)
-    {
-	msg = msg->semantic(sc);
-	msg = resolveProperties(sc, msg);
-	msg = msg->implicitCastTo(sc, Type::tchar->constOf()->arrayOf());
-	msg = msg->optimize(WANTvalue);
-    }
-    if (e1->isBool(FALSE))
-    {
-	FuncDeclaration *fd = sc->parent->isFuncDeclaration();
-	fd->hasReturnExp |= 4;
-
-	if (!global.params.useAssert)
-	{   Expression *e = new HaltExp(loc);
-	    e = e->semantic(sc);
-	    return e;
-	}
-    }
-    type = Type::tvoid;
-    return this;
-}
-
-int AssertExp::checkSideEffect(int flag)
-{
-    return 1;
-}
-
-int AssertExp::canThrow()
-{
-    return (global.params.useAssert != 0);
-}
-
-void AssertExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{
-    buf->writestring("assert(");
-    expToCBuffer(buf, hgs, e1, PREC_assign);
-    if (msg)
-    {
-	buf->writeByte(',');
-	expToCBuffer(buf, hgs, msg, PREC_assign);
-    }
-    buf->writeByte(')');
-}
-
-/************************************************************/
-
-DotIdExp::DotIdExp(Loc loc, Expression *e, Identifier *ident)
-	: UnaExp(loc, TOKdot, sizeof(DotIdExp), e)
-{
-    this->ident = ident;
-}
-
-Expression *DotIdExp::semantic(Scope *sc)
-{   Expression *e;
-    Expression *eleft;
-    Expression *eright;
-
-#if LOGSEMANTIC
-    printf("DotIdExp::semantic(this = %p, '%s')\n", this, toChars());
-    //printf("e1->op = %d, '%s'\n", e1->op, Token::toChars(e1->op));
-#endif
-
-//{ static int z; fflush(stdout); if (++z == 10) *(char*)0=0; }
-
-#if 0
-    /* Don't do semantic analysis if we'll be converting
-     * it to a string.
-     */
-    if (ident == Id::stringof)
-    {	char *s = e1->toChars();
-	e = new StringExp(loc, s, strlen(s), 'c');
-	e = e->semantic(sc);
-	return e;
-    }
-#endif
-
-    /* Special case: rewrite this.id and super.id
-     * to be classtype.id and baseclasstype.id
-     * if we have no this pointer.
-     */
-    if ((e1->op == TOKthis || e1->op == TOKsuper) && !hasThis(sc))
-    {	ClassDeclaration *cd;
-	StructDeclaration *sd;
-	AggregateDeclaration *ad;
-
-	ad = sc->getStructClassScope();
-	if (ad)
-	{
-	    cd = ad->isClassDeclaration();
-	    if (cd)
-	    {
-		if (e1->op == TOKthis)
-		{
-		    e = new TypeDotIdExp(loc, cd->type, ident);
-		    return e->semantic(sc);
-		}
-		else if (cd->baseClass && e1->op == TOKsuper)
-		{
-		    e = new TypeDotIdExp(loc, cd->baseClass->type, ident);
-		    return e->semantic(sc);
-		}
-	    }
-	    else
-	    {
-		sd = ad->isStructDeclaration();
-		if (sd)
-		{
-		    if (e1->op == TOKthis)
-		    {
-			e = new TypeDotIdExp(loc, sd->type, ident);
-			return e->semantic(sc);
-		    }
-		}
-	    }
-	}
-    }
-
-    UnaExp::semantic(sc);
-
-    if (e1->op == TOKdotexp)
-    {
-	DotExp *de = (DotExp *)e1;
-	eleft = de->e1;
-	eright = de->e2;
-    }
-    else
-    {
-	e1 = resolveProperties(sc, e1);
-	eleft = NULL;
-	eright = e1;
-    }
-#if DMDV2
-    if (e1->op == TOKtuple && ident == Id::offsetof)
-    {	/* 'distribute' the .offsetof to each of the tuple elements.
-	 */
-	TupleExp *te = (TupleExp *)e1;
-	Expressions *exps = new Expressions();
-	exps->setDim(te->exps->dim);
-	for (int i = 0; i < exps->dim; i++)
-	{   Expression *e = (Expression *)te->exps->data[i];
-	    e = e->semantic(sc);
-	    e = new DotIdExp(e->loc, e, Id::offsetof);
-	    exps->data[i] = (void *)e;
-	}
-	e = new TupleExp(loc, exps);
-	e = e->semantic(sc);
-	return e;
-    }
-#endif
-
-    if (e1->op == TOKtuple && ident == Id::length)
-    {
-	TupleExp *te = (TupleExp *)e1;
-	e = new IntegerExp(loc, te->exps->dim, Type::tsize_t);
-	return e;
-    }
-
-    Type *t1b = e1->type->toBasetype();
-
-    if (eright->op == TOKimport)	// also used for template alias's
-    {
-	ScopeExp *ie = (ScopeExp *)eright;
-
-	/* Disable access to another module's private imports.
-	 * The check for 'is sds our current module' is because
-	 * the current module should have access to its own imports.
-	 */
-	Dsymbol *s = ie->sds->search(loc, ident,
-	    (ie->sds->isModule() && ie->sds != sc->module) ? 1 : 0);
-	if (s)
-	{
-	    s = s->toAlias();
-	    checkDeprecated(sc, s);
-
-	    EnumMember *em = s->isEnumMember();
-	    if (em)
-	    {
-		e = em->value;
-		e = e->semantic(sc);
-		return e;
-	    }
-
-	    VarDeclaration *v = s->isVarDeclaration();
-	    if (v)
-	    {
-		//printf("DotIdExp:: Identifier '%s' is a variable, type '%s'\n", toChars(), v->type->toChars());
-		if (v->inuse)
-		{
-		    error("circular reference to '%s'", v->toChars());
-		    type = Type::tint32;
-		    return this;
-		}
-		type = v->type;
-#if 0
-		if (v->isConst() || v->isInvariant())
-		{
-		    if (v->init)
-		    {
-			ExpInitializer *ei = v->init->isExpInitializer();
-			if (ei)
-			{
-    //printf("\tei: %p (%s)\n", ei->exp, ei->exp->toChars());
-    //ei->exp = ei->exp->semantic(sc);
-			    if (ei->exp->type == type)
-			    {
-				e = ei->exp->copy();	// make copy so we can change loc
-				e->loc = loc;
-				return e;
-			    }
-			}
-		    }
-		    else if (type->isscalar())
-		    {
-			e = type->defaultInit();
-			e->loc = loc;
-			return e;
-		    }
-		}
-#endif
-		if (v->needThis())
-		{
-		    if (!eleft)
-			eleft = new ThisExp(loc);
-		    e = new DotVarExp(loc, eleft, v);
-		    e = e->semantic(sc);
-		}
-		else
-		{
-		    e = new VarExp(loc, v);
-		    if (eleft)
-		    {	e = new CommaExp(loc, eleft, e);
-			e->type = v->type;
-		    }
-		}
-		return e->deref();
-	    }
-
-	    FuncDeclaration *f = s->isFuncDeclaration();
-	    if (f)
-	    {
-		//printf("it's a function\n");
-		if (f->needThis())
-		{
-		    if (!eleft)
-			eleft = new ThisExp(loc);
-		    e = new DotVarExp(loc, eleft, f);
-		    e = e->semantic(sc);
-		}
-		else
-		{
-		    e = new VarExp(loc, f, 1);
-		    if (eleft)
-		    {	e = new CommaExp(loc, eleft, e);
-			e->type = f->type;
-		    }
-		}
-		return e;
-	    }
-
-	    OverloadSet *o = s->isOverloadSet();
-	    if (o)
-	    {   //printf("'%s' is an overload set\n", o->toChars());
-		return new OverExp(o);
-	    }
-
-	    Type *t = s->getType();
-	    if (t)
-	    {
-		return new TypeExp(loc, t);
-	    }
-
-	    TupleDeclaration *tup = s->isTupleDeclaration();
-	    if (tup)
-	    {
-		if (eleft)
-		    error("cannot have e.tuple");
-		e = new TupleExp(loc, tup);
-		e = e->semantic(sc);
-		return e;
-	    }
-
-	    ScopeDsymbol *sds = s->isScopeDsymbol();
-	    if (sds)
-	    {
-		//printf("it's a ScopeDsymbol\n");
-		e = new ScopeExp(loc, sds);
-		e = e->semantic(sc);
-		if (eleft)
-		    e = new DotExp(loc, eleft, e);
-		return e;
-	    }
-
-	    Import *imp = s->isImport();
-	    if (imp)
-	    {
-		ScopeExp *ie;
-
-		ie = new ScopeExp(loc, imp->pkg);
-		return ie->semantic(sc);
-	    }
-
-	    // BUG: handle other cases like in IdentifierExp::semantic()
-#ifdef DEBUG
-	    printf("s = '%s', kind = '%s'\n", s->toChars(), s->kind());
-#endif
-	    assert(0);
-	}
-	else if (ident == Id::stringof)
-	{   char *s = ie->toChars();
-	    e = new StringExp(loc, s, strlen(s), 'c');
-	    e = e->semantic(sc);
-	    return e;
-	}
-	error("undefined identifier %s", toChars());
-	type = Type::tvoid;
-	return this;
-    }
-    else if (t1b->ty == Tpointer &&
-	     ident != Id::init && ident != Id::__sizeof &&
-	     ident != Id::alignof && ident != Id::offsetof &&
-	     ident != Id::mangleof && ident != Id::stringof)
-    {	/* Rewrite:
-         *   p.ident
-         * as:
-         *   (*p).ident
-         */
-	e = new PtrExp(loc, e1);
-	e->type = ((TypePointer *)t1b)->next;
-	return e->type->dotExp(sc, e, ident);
-    }
-    else if (t1b->ty == Tarray ||
-             t1b->ty == Tsarray ||
-	     t1b->ty == Taarray)
-    {	/* If ident is not a valid property, rewrite:
-	 *   e1.ident
-         * as:
-         *   .ident(e1)
-         */
-	unsigned errors = global.errors;
-	global.gag++;
-	e = e1->type->dotExp(sc, e1, ident);
-	global.gag--;
-	if (errors != global.errors)	// if failed to find the property
-	{
-	    global.errors = errors;
-	    e = new DotIdExp(loc, new IdentifierExp(loc, Id::empty), ident);
-	    e = new CallExp(loc, e, e1);
-	}
-	e = e->semantic(sc);
-	return e;
-    }
-    else
-    {
-	e = e1->type->dotExp(sc, e1, ident);
-	e = e->semantic(sc);
-	return e;
-    }
-}
-
-void DotIdExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{
-    //printf("DotIdExp::toCBuffer()\n");
-    expToCBuffer(buf, hgs, e1, PREC_primary);
-    buf->writeByte('.');
-    buf->writestring(ident->toChars());
-}
-
-/********************** DotTemplateExp ***********************************/
-
-// Mainly just a placeholder
-
-DotTemplateExp::DotTemplateExp(Loc loc, Expression *e, TemplateDeclaration *td)
-	: UnaExp(loc, TOKdottd, sizeof(DotTemplateExp), e)
-  
-{
-    this->td = td;
-}
-
-void DotTemplateExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{
-    expToCBuffer(buf, hgs, e1, PREC_primary);
-    buf->writeByte('.');
-    buf->writestring(td->toChars());
-}
-
-
-/************************************************************/
-
-DotVarExp::DotVarExp(Loc loc, Expression *e, Declaration *v, int hasOverloads)
-	: UnaExp(loc, TOKdotvar, sizeof(DotVarExp), e)
-{
-    //printf("DotVarExp()\n");
-    this->var = v;
-    this->hasOverloads = hasOverloads;
-}
-
-Expression *DotVarExp::semantic(Scope *sc)
-{
-#if LOGSEMANTIC
-    printf("DotVarExp::semantic('%s')\n", toChars());
-#endif
-    if (!type)
-    {
-	var = var->toAlias()->isDeclaration();
-
-	TupleDeclaration *tup = var->isTupleDeclaration();
-	if (tup)
-	{   /* Replace:
-	     *	e1.tuple(a, b, c)
-	     * with:
-	     *	tuple(e1.a, e1.b, e1.c)
-	     */
-	    Expressions *exps = new Expressions;
-
-	    exps->reserve(tup->objects->dim);
-	    for (size_t i = 0; i < tup->objects->dim; i++)
-	    {   Object *o = (Object *)tup->objects->data[i];
-		if (o->dyncast() != DYNCAST_EXPRESSION)
-		{
-		    error("%s is not an expression", o->toChars());
-		}
-		else
-		{
-		    Expression *e = (Expression *)o;
-		    if (e->op != TOKdsymbol)
-			error("%s is not a member", e->toChars());
-		    else
-		    {	DsymbolExp *ve = (DsymbolExp *)e;
-
-			e = new DotVarExp(loc, e1, ve->s->isDeclaration());
-			exps->push(e);
-		    }
-		}
-	    }
-	    Expression *e = new TupleExp(loc, exps);
-	    e = e->semantic(sc);
-	    return e;
-	}
-
-	e1 = e1->semantic(sc);
-	type = var->type;
-	if (!type && global.errors)
-	{   // var is goofed up, just return 0
-	    return new IntegerExp(0);
-	}
-	assert(type);
-
-	if (!var->isFuncDeclaration())	// for functions, do checks after overload resolution
-	{
-	    Type *t1 = e1->type;
-	    if (t1->ty == Tpointer)
-		t1 = t1->nextOf();
-	    if (t1->isConst())
-		type = type->constOf();
-	    else if (t1->isInvariant())
-		type = type->invariantOf();
-
-	    AggregateDeclaration *ad = var->toParent()->isAggregateDeclaration();
-	    e1 = getRightThis(loc, sc, ad, e1, var);
-	    if (!sc->noaccesscheck)
-		accessCheck(loc, sc, e1, var);
-
-	    VarDeclaration *v = var->isVarDeclaration();
-	    Expression *e = expandVar(WANTvalue, v);
-	    if (e)
-		return e;
-	}
-    }
-    //printf("-DotVarExp::semantic('%s')\n", toChars());
-    return this;
-}
-
-int DotVarExp::isLvalue()
-{
-    return 1;
-}
-
-Expression *DotVarExp::toLvalue(Scope *sc, Expression *e)
-{
-    //printf("DotVarExp::toLvalue(%s)\n", toChars());
-    return this;
-}
-
-Expression *DotVarExp::modifiableLvalue(Scope *sc, Expression *e)
-{
-#if 0
-    printf("DotVarExp::modifiableLvalue(%s)\n", toChars());
-    printf("e1->type = %s\n", e1->type->toChars());
-    printf("var->type = %s\n", var->type->toChars());
-#endif
-
-    if (var->isCtorinit())
-    {	// It's only modifiable if inside the right constructor
-	Dsymbol *s = sc->func;
-	while (1)
-	{
-	    FuncDeclaration *fd = NULL;
-	    if (s)
-		fd = s->isFuncDeclaration();
-	    if (fd &&
-		((fd->isCtorDeclaration() && var->storage_class & STCfield) ||
-		 (fd->isStaticCtorDeclaration() && !(var->storage_class & STCfield))) &&
-		fd->toParent() == var->toParent() &&
-		e1->op == TOKthis
-	       )
-	    {
-		VarDeclaration *v = var->isVarDeclaration();
-		assert(v);
-		v->ctorinit = 1;
-		//printf("setting ctorinit\n");
-	    }
-	    else
-	    {
-		if (s)
-		{   s = s->toParent2();
-		    continue;
-		}
-		else
-		{
-		    const char *p = var->isStatic() ? "static " : "";
-		    error("can only initialize %sconst member %s inside %sconstructor",
-			p, var->toChars(), p);
-		}
-	    }
-	    break;
-	}
-    }
-    else
-    {
-	Type *t1 = e1->type->toBasetype();
-
-	if (!t1->isMutable() ||
-	    (t1->ty == Tpointer && !t1->nextOf()->isMutable()) ||
-	    !var->type->isMutable() ||
-	    !var->type->isAssignable() ||
-	    var->storage_class & STCmanifest
-	   )
-	    error("cannot modify const/invariant %s", toChars());
-    }
-    return this;
-}
-
-void DotVarExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{
-    expToCBuffer(buf, hgs, e1, PREC_primary);
-    buf->writeByte('.');
-    buf->writestring(var->toChars());
-}
-
-/************************************************************/
-
-/* Things like:
- *	foo.bar!(args)
- */
-
-DotTemplateInstanceExp::DotTemplateInstanceExp(Loc loc, Expression *e, TemplateInstance *ti)
-	: UnaExp(loc, TOKdotti, sizeof(DotTemplateInstanceExp), e)
-{
-    //printf("DotTemplateInstanceExp()\n");
-    this->ti = ti;
-}
-
-Expression *DotTemplateInstanceExp::syntaxCopy()
-{
-    DotTemplateInstanceExp *de = new DotTemplateInstanceExp(loc,
-	e1->syntaxCopy(),
-	(TemplateInstance *)ti->syntaxCopy(NULL));
-    return de;
-}
-
-Expression *DotTemplateInstanceExp::semantic(Scope *sc)
-{   Dsymbol *s;
-    Dsymbol *s2;
-    TemplateDeclaration *td;
-    Expression *e;
-    Identifier *id;
-    Type *t1;
-    Expression *eleft = NULL;
-    Expression *eright;
-
-#if LOGSEMANTIC
-    printf("DotTemplateInstanceExp::semantic('%s')\n", toChars());
-#endif
-    //e1->print();
-    //print();
-    e1 = e1->semantic(sc);
-    t1 = e1->type;
-    if (t1)
-	t1 = t1->toBasetype();
-    //t1->print();
-
-    /* Extract the following from e1:
-     *	s: the symbol which ti should be a member of
-     *	eleft: if not NULL, it is the 'this' pointer for ti
-     */
-
-    if (e1->op == TOKdotexp)
-    {	DotExp *de = (DotExp *)e1;
-	eleft = de->e1;
-	eright = de->e2;
-    }
-    else
-    {	eleft = NULL;
-	eright = e1;
-    }
-    if (eright->op == TOKimport)
-    {
-	s = ((ScopeExp *)eright)->sds;
-    }
-    else if (e1->op == TOKtype)
-    {
-	s = t1->isClassHandle();
-	if (!s)
-	{   if (t1->ty == Tstruct)
-		s = ((TypeStruct *)t1)->sym;
-	    else
-		goto L1;
-	}
-    }
-    else if (t1 && (t1->ty == Tstruct || t1->ty == Tclass))
-    {
-	s = t1->toDsymbol(sc);
-	eleft = e1;
-    }
-    else if (t1 && t1->ty == Tpointer)
-    {
-	t1 = ((TypePointer *)t1)->next->toBasetype();
-	if (t1->ty != Tstruct)
-	    goto L1;
-	s = t1->toDsymbol(sc);
-	eleft = e1;
-    }
-    else
-    {
-      L1:
-	error("template %s is not a member of %s", ti->toChars(), e1->toChars());
-	goto Lerr;
-    }
-
-    assert(s);
-    id = ti->name;
-    s2 = s->search(loc, id, 0);
-    if (!s2)
-    {	error("template identifier %s is not a member of %s %s", id->toChars(), s->kind(), s->ident->toChars());
-	goto Lerr;
-    }
-    s = s2;
-    s->semantic(sc);
-    s = s->toAlias();
-    td = s->isTemplateDeclaration();
-    if (!td)
-    {
-	error("%s is not a template", id->toChars());
-	goto Lerr;
-    }
-    if (global.errors)
-	goto Lerr;
-
-    ti->tempdecl = td;
-
-    if (eleft)
-    {	Declaration *v;
-
-	ti->semantic(sc);
-	s = ti->inst->toAlias();
-	v = s->isDeclaration();
-	if (v)
-	{   e = new DotVarExp(loc, eleft, v);
-	    e = e->semantic(sc);
-	    return e;
-	}
-    }
-
-    e = new ScopeExp(loc, ti);
-    if (eleft)
-    {
-	e = new DotExp(loc, eleft, e);
-    }
-    e = e->semantic(sc);
-    return e;
-
-Lerr:
-    return new IntegerExp(loc, 0, Type::tint32);
-}
-
-void DotTemplateInstanceExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{
-    expToCBuffer(buf, hgs, e1, PREC_primary);
-    buf->writeByte('.');
-    ti->toCBuffer(buf, hgs);
-}
-
-/************************************************************/
-
-DelegateExp::DelegateExp(Loc loc, Expression *e, FuncDeclaration *f, int hasOverloads)
-	: UnaExp(loc, TOKdelegate, sizeof(DelegateExp), e)
-{
-    this->func = f;
-    this->hasOverloads = hasOverloads;
-}
-
-Expression *DelegateExp::semantic(Scope *sc)
-{
-#if LOGSEMANTIC
-    printf("DelegateExp::semantic('%s')\n", toChars());
-#endif
-    if (!type)
-    {
-	e1 = e1->semantic(sc);
-    // LDC we need a copy as we store the LLVM tpye in TypeFunction, and delegate/members have different types for 'this'
-	type = new TypeDelegate(func->type->syntaxCopy());
-	type = type->semantic(loc, sc);
-	AggregateDeclaration *ad = func->toParent()->isAggregateDeclaration();
-	if (func->needThis())
-	    e1 = getRightThis(loc, sc, ad, e1, func);
-    }
-    return this;
-}
-
-void DelegateExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{
-    buf->writeByte('&');
-    if (!func->isNested())
-    {
-	expToCBuffer(buf, hgs, e1, PREC_primary);
-	buf->writeByte('.');
-    }
-    buf->writestring(func->toChars());
-}
-
-/************************************************************/
-
-DotTypeExp::DotTypeExp(Loc loc, Expression *e, Dsymbol *s)
-	: UnaExp(loc, TOKdottype, sizeof(DotTypeExp), e)
-{
-    this->sym = s;
-    this->type = s->getType();
-}
-
-Expression *DotTypeExp::semantic(Scope *sc)
-{
-#if LOGSEMANTIC
-    printf("DotTypeExp::semantic('%s')\n", toChars());
-#endif
-    UnaExp::semantic(sc);
-    return this;
-}
-
-void DotTypeExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{
-    expToCBuffer(buf, hgs, e1, PREC_primary);
-    buf->writeByte('.');
-    buf->writestring(sym->toChars());
-}
-
-/************************************************************/
-
-CallExp::CallExp(Loc loc, Expression *e, Expressions *exps)
-	: UnaExp(loc, TOKcall, sizeof(CallExp), e)
-{
-    this->arguments = exps;
-}
-
-CallExp::CallExp(Loc loc, Expression *e)
-	: UnaExp(loc, TOKcall, sizeof(CallExp), e)
-{
-    this->arguments = NULL;
-}
-
-CallExp::CallExp(Loc loc, Expression *e, Expression *earg1)
-	: UnaExp(loc, TOKcall, sizeof(CallExp), e)
-{
-    Expressions *arguments = new Expressions();
-    arguments->setDim(1);
-    arguments->data[0] = (void *)earg1;
-
-    this->arguments = arguments;
-}
-
-CallExp::CallExp(Loc loc, Expression *e, Expression *earg1, Expression *earg2)
-	: UnaExp(loc, TOKcall, sizeof(CallExp), e)
-{
-    Expressions *arguments = new Expressions();
-    arguments->setDim(2);
-    arguments->data[0] = (void *)earg1;
-    arguments->data[1] = (void *)earg2;
-
-    this->arguments = arguments;
-}
-
-Expression *CallExp::syntaxCopy()
-{
-    return new CallExp(loc, e1->syntaxCopy(), arraySyntaxCopy(arguments));
-}
-
-
-Expression *CallExp::semantic(Scope *sc)
-{
-    TypeFunction *tf;
-    FuncDeclaration *f;
-    int i;
-    Type *t1;
-    int istemp;
-    Objects *targsi = NULL;	// initial list of template arguments
-
-#if LOGSEMANTIC
-    printf("CallExp::semantic() %s\n", toChars());
-#endif
-    if (type)
-	return this;		// semantic() already run
-#if 0
-    if (arguments && arguments->dim)
-    {
-	Expression *earg = (Expression *)arguments->data[0];
-	earg->print();
-	if (earg->type) earg->type->print();
-    }
-#endif
-
-    if (e1->op == TOKdelegate)
-    {	DelegateExp *de = (DelegateExp *)e1;
-
-	e1 = new DotVarExp(de->loc, de->e1, de->func);
-	return semantic(sc);
-    }
-
-    /* Transform:
-     *	array.id(args) into .id(array,args)
-     *	aa.remove(arg) into delete aa[arg]
-     */
-    if (e1->op == TOKdot)
-    {
-	// BUG: we should handle array.a.b.c.e(args) too
-
-	DotIdExp *dotid = (DotIdExp *)(e1);
-	dotid->e1 = dotid->e1->semantic(sc);
-	assert(dotid->e1);
-	if (dotid->e1->type)
-	{
-	    TY e1ty = dotid->e1->type->toBasetype()->ty;
-	    if (e1ty == Taarray && dotid->ident == Id::remove)
-	    {
-		if (!arguments || arguments->dim != 1)
-		{   error("expected key as argument to aa.remove()");
-		    goto Lagain;
-		}
-		Expression *key = (Expression *)arguments->data[0];
-		key = key->semantic(sc);
-		key = resolveProperties(sc, key);
-		key->rvalue();
-
-		TypeAArray *taa = (TypeAArray *)dotid->e1->type->toBasetype();
-		key = key->implicitCastTo(sc, taa->index);
-
-		return new RemoveExp(loc, dotid->e1, key);
-	    }
-	    else if (e1ty == Tarray || e1ty == Tsarray || e1ty == Taarray)
-	    {
-		if (!arguments)
-		    arguments = new Expressions();
-		arguments->shift(dotid->e1);
-		e1 = new DotIdExp(dotid->loc, new IdentifierExp(dotid->loc, Id::empty), dotid->ident);
-	    }
-	}
-    }
-
-#if DMDV2
-    /* This recognizes:
-     *	foo!(tiargs)(funcargs)
-     */
-    if (e1->op == TOKimport && !e1->type)
-    {	ScopeExp *se = (ScopeExp *)e1;
-	TemplateInstance *ti = se->sds->isTemplateInstance();
-	if (ti && !ti->semanticdone)
-	{
-	    /* Attempt to instantiate ti. If that works, go with it.
-	     * If not, go with partial explicit specialization.
-	     */
-	    ti->semanticTiargs(sc);
-	    unsigned errors = global.errors;
-	    global.gag++;
-	    ti->semantic(sc);
-	    global.gag--;
-	    if (errors != global.errors)
-	    {
-		/* Didn't work, go with partial explicit specialization
-		 */
-		global.errors = errors;
-		targsi = ti->tiargs;
-		e1 = new IdentifierExp(loc, ti->name);
-	    }
-	}
-    }
-
-    /* This recognizes:
-     *	expr.foo!(tiargs)(funcargs)
-     */
-    if (e1->op == TOKdotti && !e1->type)
-    {	DotTemplateInstanceExp *se = (DotTemplateInstanceExp *)e1;
-	TemplateInstance *ti = se->ti;
-	if (!ti->semanticdone)
-	{
-	    /* Attempt to instantiate ti. If that works, go with it.
-	     * If not, go with partial explicit specialization.
-	     */
-	    ti->semanticTiargs(sc);
-	    Expression *etmp;
-	    unsigned errors = global.errors;
-	    global.gag++;
-	    etmp = e1->semantic(sc);
-	    global.gag--;
-	    if (errors != global.errors)
-	    {
-		global.errors = errors;
-		targsi = ti->tiargs;
-		e1 = new DotIdExp(loc, se->e1, ti->name);
-	    }
-	    else
-		e1 = etmp;
-	}
-    }
-#endif
-
-    istemp = 0;
-Lagain:
-    //printf("Lagain: %s\n", toChars());
-    f = NULL;
-    if (e1->op == TOKthis || e1->op == TOKsuper)
-    {
-	// semantic() run later for these
-    }
-    else
-    {
-	UnaExp::semantic(sc);
-
-	/* Look for e1 being a lazy parameter
-	 */
-	if (e1->op == TOKvar)
-	{   VarExp *ve = (VarExp *)e1;
-
-	    if (ve->var->storage_class & STClazy)
-	    {
-		TypeFunction *tf = new TypeFunction(NULL, ve->var->type, 0, LINKd);
-		TypeDelegate *t = new TypeDelegate(tf);
-		ve->type = t->semantic(loc, sc);
-	    }
-	}
-
-	if (e1->op == TOKimport)
-	{   // Perhaps this should be moved to ScopeExp::semantic()
-	    ScopeExp *se = (ScopeExp *)e1;
-	    e1 = new DsymbolExp(loc, se->sds);
-	    e1 = e1->semantic(sc);
-	}
-#if 1	// patch for #540 by Oskar Linde
-	else if (e1->op == TOKdotexp)
-	{
-	    DotExp *de = (DotExp *) e1;
-
-	    if (de->e2->op == TOKimport)
-	    {   // This should *really* be moved to ScopeExp::semantic()
-		ScopeExp *se = (ScopeExp *)de->e2;
-		de->e2 = new DsymbolExp(loc, se->sds);
-		de->e2 = de->e2->semantic(sc);
-	    }
-
-	    if (de->e2->op == TOKtemplate)
-	    {   TemplateExp *te = (TemplateExp *) de->e2;
-		e1 = new DotTemplateExp(loc,de->e1,te->td);
-	    }
-	}
-#endif
-    }
-
-    if (e1->op == TOKcomma)
-    {
-	CommaExp *ce = (CommaExp *)e1;
-
-	e1 = ce->e2;
-	e1->type = ce->type;
-	ce->e2 = this;
-	ce->type = NULL;
-	return ce->semantic(sc);
-    }
-
-    t1 = NULL;
-    if (e1->type)
-	t1 = e1->type->toBasetype();
-
-    // Check for call operator overload
-    if (t1)
-    {	AggregateDeclaration *ad;
-
-	if (t1->ty == Tstruct)
-	{
-	    ad = ((TypeStruct *)t1)->sym;
-
-	    // First look for constructor
-	    if (ad->ctor && arguments && arguments->dim)
-	    {
-		// Create variable that will get constructed
-		Identifier *idtmp = Lexer::uniqueId("__ctmp");
-		VarDeclaration *tmp = new VarDeclaration(loc, t1, idtmp, NULL);
-		Expression *av = new DeclarationExp(loc, tmp);
-		av = new CommaExp(loc, av, new VarExp(loc, tmp));
-
-		Expression *e = new DotVarExp(loc, av, ad->ctor, 1);
-		e = new CallExp(loc, e, arguments);
-#if !STRUCTTHISREF
-		/* Constructors return a pointer to the instance
-		 */
-		e = new PtrExp(loc, e);
-#endif
-		e = e->semantic(sc);
-		return e;
-	    }
-
-	    // No constructor, look for overload of opCall
-	    if (search_function(ad, Id::call))
-		goto L1;	// overload of opCall, therefore it's a call
-
-	    if (e1->op != TOKtype)
-		error("%s %s does not overload ()", ad->kind(), ad->toChars());
-	    /* It's a struct literal
-	     */
-	    Expression *e = new StructLiteralExp(loc, (StructDeclaration *)ad, arguments);
-	    e = e->semantic(sc);
-	    e->type = e1->type;		// in case e1->type was a typedef
-	    return e;
-	}
-	else if (t1->ty == Tclass)
-	{
-	    ad = ((TypeClass *)t1)->sym;
-	    goto L1;
-	L1:
-	    // Rewrite as e1.call(arguments)
-	    Expression *e = new DotIdExp(loc, e1, Id::call);
-	    e = new CallExp(loc, e, arguments);
-	    e = e->semantic(sc);
-	    return e;
-	}
-    }
-
-    arrayExpressionSemantic(arguments, sc);
-    preFunctionArguments(loc, sc, arguments);
-
-    if (e1->op == TOKdotvar && t1->ty == Tfunction ||
-        e1->op == TOKdottd)
-    {
-	DotVarExp *dve;
-	DotTemplateExp *dte;
-	AggregateDeclaration *ad;
-	UnaExp *ue = (UnaExp *)(e1);
-
-    	if (e1->op == TOKdotvar)
-        {   // Do overload resolution
-	    dve = (DotVarExp *)(e1);
-
-	    f = dve->var->isFuncDeclaration();
-	    assert(f);
-	    f = f->overloadResolve(loc, ue->e1, arguments);
-
-	    ad = f->toParent()->isAggregateDeclaration();
-	}
-        else
-        {   dte = (DotTemplateExp *)(e1);
-	    TemplateDeclaration *td = dte->td;
-	    assert(td);
-	    if (!arguments)
-		// Should fix deduceFunctionTemplate() so it works on NULL argument
-		arguments = new Expressions();
-	    f = td->deduceFunctionTemplate(sc, loc, targsi, ue->e1, arguments);
-	    if (!f)
-	    {	type = Type::terror;
-		return this;
-	    }
-	    ad = td->toParent()->isAggregateDeclaration();
-	}	
-	if (f->needThis())
-	{
-	    ue->e1 = getRightThis(loc, sc, ad, ue->e1, f);
-	}
-
-	/* Cannot call public functions from inside invariant
-	 * (because then the invariant would have infinite recursion)
-	 */
-	if (sc->func && sc->func->isInvariantDeclaration() &&
-	    ue->e1->op == TOKthis &&
-	    f->addPostInvariant()
-	   )
-	{
-	    error("cannot call public/export function %s from invariant", f->toChars());
-	}
-
-	checkDeprecated(sc, f);
-	accessCheck(loc, sc, ue->e1, f);
-	if (!f->needThis())
-	{
-	    VarExp *ve = new VarExp(loc, f);
-	    e1 = new CommaExp(loc, ue->e1, ve);
-	    e1->type = f->type;
-	}
-	else
-	{
-	    if (e1->op == TOKdotvar)		
-		dve->var = f;
-	    else
-		e1 = new DotVarExp(loc, dte->e1, f);
-	    e1->type = f->type;
-#if 0
-	    printf("ue->e1 = %s\n", ue->e1->toChars());
-	    printf("f = %s\n", f->toChars());
-	    printf("t = %s\n", t->toChars());
-	    printf("e1 = %s\n", e1->toChars());
-	    printf("e1->type = %s\n", e1->type->toChars());
-#endif
-	    // Const member function can take const/invariant/mutable this
-	    if (!(f->type->isConst()))
-	    {
-		// Check for const/invariant compatibility
-		Type *tthis = ue->e1->type->toBasetype();
-		if (tthis->ty == Tpointer)
-		    tthis = tthis->nextOf()->toBasetype();
-		if (f->type->isInvariant())
-		{
-		    if (tthis->mod != MODinvariant)
-			error("%s can only be called on an invariant object", e1->toChars());
-		}
-		else
-		{
-		    if (tthis->mod != 0)
-		    {	//printf("mod = %x\n", tthis->mod);
-			error("%s can only be called on a mutable object, not %s", e1->toChars(), tthis->toChars());
-		    }
-		}
-
-		/* Cannot call mutable method on a final struct
-		 */
-		if (tthis->ty == Tstruct &&
-		    ue->e1->op == TOKvar)
-		{   VarExp *v = (VarExp *)ue->e1;
-		    if (v->var->storage_class & STCfinal)
-			error("cannot call mutable method on final struct");
-		}
-	    }
-
-	    // See if we need to adjust the 'this' pointer
-	    AggregateDeclaration *ad = f->isThis();
-	    ClassDeclaration *cd = ue->e1->type->isClassHandle();
-	    if (ad && cd && ad->isClassDeclaration() && ad != cd &&
-		ue->e1->op != TOKsuper)
-	    {
-		ue->e1 = ue->e1->castTo(sc, ad->type); //new CastExp(loc, ue->e1, ad->type);
-		ue->e1 = ue->e1->semantic(sc);
-	    }
-	}
-	t1 = e1->type;
-    }
-    else if (e1->op == TOKsuper)
-    {
-	// Base class constructor call
-	ClassDeclaration *cd = NULL;
-
-	if (sc->func)
-	    cd = sc->func->toParent()->isClassDeclaration();
-	if (!cd || !cd->baseClass || !sc->func->isCtorDeclaration())
-	{
-	    error("super class constructor call must be in a constructor");
-	    type = Type::terror;
-	    return this;
-	}
-	else
-	{
-	    f = cd->baseClass->ctor;
-	    if (!f)
-	    {	error("no super class constructor for %s", cd->baseClass->toChars());
-		type = Type::terror;
-		return this;
-	    }
-	    else
-	    {
-		if (!sc->intypeof)
-		{
-#if 0
-		    if (sc->callSuper & (CSXthis | CSXsuper))
-			error("reference to this before super()");
-#endif
-		    if (sc->noctor || sc->callSuper & CSXlabel)
-			error("constructor calls not allowed in loops or after labels");
-		    if (sc->callSuper & (CSXsuper_ctor | CSXthis_ctor))
-			error("multiple constructor calls");
-		    sc->callSuper |= CSXany_ctor | CSXsuper_ctor;
-		}
-
-		f = f->overloadResolve(loc, NULL, arguments);
-		checkDeprecated(sc, f);
-		e1 = new DotVarExp(e1->loc, e1, f);
-		e1 = e1->semantic(sc);
-		t1 = e1->type;
-	    }
-	}
-    }
-    else if (e1->op == TOKthis)
-    {
-	// same class constructor call
-	ClassDeclaration *cd = NULL;
-
-	if (sc->func)
-	    cd = sc->func->toParent()->isClassDeclaration();
-	if (!cd || !sc->func->isCtorDeclaration())
-	{
-	    error("class constructor call must be in a constructor");
-	    type = Type::terror;
-	    return this;
-	}
-	else
-	{
-	    if (!sc->intypeof)
-	    {
-#if 0
-		if (sc->callSuper & (CSXthis | CSXsuper))
-		    error("reference to this before super()");
-#endif
-		if (sc->noctor || sc->callSuper & CSXlabel)
-		    error("constructor calls not allowed in loops or after labels");
-		if (sc->callSuper & (CSXsuper_ctor | CSXthis_ctor))
-		    error("multiple constructor calls");
-		sc->callSuper |= CSXany_ctor | CSXthis_ctor;
-	    }
-
-	    f = cd->ctor;
-	    f = f->overloadResolve(loc, NULL, arguments);
-	    checkDeprecated(sc, f);
-	    e1 = new DotVarExp(e1->loc, e1, f);
-	    e1 = e1->semantic(sc);
-	    t1 = e1->type;
-
-	    // BUG: this should really be done by checking the static
-	    // call graph
-	    if (f == sc->func)
-		error("cyclic constructor call");
-	}
-    }
-    else if (e1->op == TOKoverloadset)
-    {
-	OverExp *eo = (OverExp *)e1;
-	FuncDeclaration *f = NULL;
-	for (int i = 0; i < eo->vars->a.dim; i++)
-	{   Dsymbol *s = (Dsymbol *)eo->vars->a.data[i];
-	    FuncDeclaration *f2 = s->isFuncDeclaration();
-	    if (f2)
-	    {
-		f2 = f2->overloadResolve(loc, NULL, arguments, 1);
-	    }
-	    else
-	    {	TemplateDeclaration *td = s->isTemplateDeclaration();
-		assert(td);
-		f2 = td->deduceFunctionTemplate(sc, loc, targsi, NULL, arguments, 1);
-	    }
-	    if (f2)
-	    {	if (f)
-		    /* Error if match in more than one overload set,
-		     * even if one is a 'better' match than the other.
-		     */
-		    ScopeDsymbol::multiplyDefined(loc, f, f2);
-		else
-		    f = f2;
-	    }
-	}
-	if (!f)
-	{   /* No overload matches, just set f and rely on error
-	     * message being generated later.
-	     */
-	    f = (FuncDeclaration *)eo->vars->a.data[0];
-	}
-	e1 = new VarExp(loc, f);
-	goto Lagain;
-    }
-    else if (!t1)
-    {
-	error("function expected before (), not '%s'", e1->toChars());
-	type = Type::terror;
-	return this;
-    }
-    else if (t1->ty != Tfunction)
-    {
-	if (t1->ty == Tdelegate)
-	{   TypeDelegate *td = (TypeDelegate *)t1;
-	    assert(td->next->ty == Tfunction);
-	    tf = (TypeFunction *)(td->next);
-	    goto Lcheckargs;
-	}
-	else if (t1->ty == Tpointer && ((TypePointer *)t1)->next->ty == Tfunction)
-	{   Expression *e;
-
-	    e = new PtrExp(loc, e1);
-	    t1 = ((TypePointer *)t1)->next;
-	    e->type = t1;
-	    e1 = e;
-	}
-	else if (e1->op == TOKtemplate)
-	{
-	    TemplateExp *te = (TemplateExp *)e1;
-	    f = te->td->deduceFunctionTemplate(sc, loc, targsi, NULL, arguments);
-	    if (!f)
-	    {	type = Type::terror;
-		return this;
-	    }
-	    if (f->needThis() && hasThis(sc))
-	    {
-		// Supply an implicit 'this', as in
-		//	  this.ident
-
-		e1 = new DotTemplateExp(loc, (new ThisExp(loc))->semantic(sc), te->td);
-		goto Lagain;
-	    }
-
-	    e1 = new VarExp(loc, f);
-	    goto Lagain;
-	}
-	else
-	{   error("function expected before (), not %s of type %s", e1->toChars(), e1->type->toChars());
-	    type = Type::terror;
-	    return this;
-	}
-    }
-    else if (e1->op == TOKvar)
-    {
-	// Do overload resolution
-	VarExp *ve = (VarExp *)e1;
-
-	f = ve->var->isFuncDeclaration();
-	assert(f);
-
-	if (ve->hasOverloads)
-	    f = f->overloadResolve(loc, NULL, arguments);
-	checkDeprecated(sc, f);
-
-	if (f->needThis() && hasThis(sc))
-	{
-	    // Supply an implicit 'this', as in
-	    //	  this.ident
-
-	    e1 = new DotVarExp(loc, new ThisExp(loc), f);
-	    goto Lagain;
-	}
-
-	accessCheck(loc, sc, NULL, f);
-
-	ve->var = f;
-//	ve->hasOverloads = 0;
-	ve->type = f->type;
-	t1 = f->type;
-    }
-    assert(t1->ty == Tfunction);
-    tf = (TypeFunction *)(t1);
-
-Lcheckargs:
-    assert(tf->ty == Tfunction);
-    type = tf->next;
-
-    if (!arguments)
-	arguments = new Expressions();
-    functionArguments(loc, sc, tf, arguments);
-
-    assert(type);
-
-    if (f && f->tintro)
-    {
-	Type *t = type;
-	int offset = 0;
-	TypeFunction *tf = (TypeFunction *)f->tintro;
-
-	if (tf->next->isBaseOf(t, &offset) && offset)
-	{
-	    type = tf->next;
-	    return castTo(sc, t);
-	}
-    }
-
-    return this;
-}
-
-int CallExp::checkSideEffect(int flag)
-{
-    return 1;
-}
-
-int CallExp::canThrow()
-{
-    return 1;
-}
-
-int CallExp::isLvalue()
-{
-    if (type->toBasetype()->ty == Tstruct)
-	return 1;
-    Type *tb = e1->type->toBasetype();
-    if (tb->ty == Tfunction && ((TypeFunction *)tb)->isref)
-	return 1;		// function returns a reference
-    return 0;
-}
-
-Expression *CallExp::toLvalue(Scope *sc, Expression *e)
-{
-    if (isLvalue())
-	return this;
-    return Expression::toLvalue(sc, e);
-}
-
-void CallExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{   int i;
-
-    expToCBuffer(buf, hgs, e1, precedence[op]);
-    buf->writeByte('(');
-    argsToCBuffer(buf, arguments, hgs);
-    buf->writeByte(')');
-}
-
-
-/************************************************************/
-
-AddrExp::AddrExp(Loc loc, Expression *e)
-	: UnaExp(loc, TOKaddress, sizeof(AddrExp), e)
-{
-}
-
-Expression *AddrExp::semantic(Scope *sc)
-{
-#if LOGSEMANTIC
-    printf("AddrExp::semantic('%s')\n", toChars());
-#endif
-    if (!type)
-    {
-	UnaExp::semantic(sc);
-	e1 = e1->toLvalue(sc, NULL);
-	if (!e1->type)
-	{
-	    error("cannot take address of %s", e1->toChars());
-	    type = Type::tint32;
-	    return this;
-	}
-	type = e1->type->pointerTo();
-
-	// See if this should really be a delegate
-	if (e1->op == TOKdotvar)
-	{
-	    DotVarExp *dve = (DotVarExp *)e1;
-	    FuncDeclaration *f = dve->var->isFuncDeclaration();
-
-	    if (f)
-	    {
-		if (!dve->hasOverloads)
-		    f->tookAddressOf++;
-		Expression *e = new DelegateExp(loc, dve->e1, f, dve->hasOverloads);
-		e = e->semantic(sc);
-		return e;
-	    }
-	}
-	else if (e1->op == TOKvar)
-	{
-	    VarExp *ve = (VarExp *)e1;
-
-	    VarDeclaration *v = ve->var->isVarDeclaration();
-	    if (v && !v->canTakeAddressOf())
-		error("cannot take address of %s", e1->toChars());
-
-	    FuncDeclaration *f = ve->var->isFuncDeclaration();
-
-	    if (f)
-	    {
-		if (!ve->hasOverloads ||
-		    /* Because nested functions cannot be overloaded,
-		     * mark here that we took its address because castTo()
-		     * may not be called with an exact match.
-		     */
-		    f->toParent2()->isFuncDeclaration())
-		    f->tookAddressOf++;
-
-        // LDC
-        if (f && f->isIntrinsic())
-        {
-            error("cannot take the address of intrinsic function %s", e1->toChars());
-            return this;
-        }
-
-		if (f->isNested())
-		{
-		    Expression *e = new DelegateExp(loc, e1, f, ve->hasOverloads);
-		    e = e->semantic(sc);
-		    return e;
-		}
-		if (f->needThis() && hasThis(sc))
-		{
-		    /* Should probably supply 'this' after overload resolution,
-		     * not before.
-		     */
-		    Expression *ethis = new ThisExp(loc);
-		    Expression *e = new DelegateExp(loc, ethis, f, ve->hasOverloads);
-		    e = e->semantic(sc);
-		    return e;
-		}
-	    }
-	}
-	return optimize(WANTvalue);
-    }
-    return this;
-}
-
-/************************************************************/
-
-PtrExp::PtrExp(Loc loc, Expression *e)
-	: UnaExp(loc, TOKstar, sizeof(PtrExp), e)
-{
-    if (e->type)
-	type = ((TypePointer *)e->type)->next;
-}
-
-PtrExp::PtrExp(Loc loc, Expression *e, Type *t)
-	: UnaExp(loc, TOKstar, sizeof(PtrExp), e)
-{
-    type = t;
-}
-
-Expression *PtrExp::semantic(Scope *sc)
-{   Type *tb;
-
-#if LOGSEMANTIC
-    printf("PtrExp::semantic('%s')\n", toChars());
-#endif
-    if (!type)
-    {
-	UnaExp::semantic(sc);
-	e1 = resolveProperties(sc, e1);
-	if (!e1->type)
-	    printf("PtrExp::semantic('%s')\n", toChars());
-	Expression *e = op_overload(sc);
-	if (e)
-	    return e;
-	tb = e1->type->toBasetype();
-	switch (tb->ty)
-	{
-	    case Tpointer:
-		type = ((TypePointer *)tb)->next;
-		break;
-
-	    case Tsarray:
-	    case Tarray:
-		type = ((TypeArray *)tb)->next;
-		e1 = e1->castTo(sc, type->pointerTo());
-		break;
-
-	    default:
-		error("can only * a pointer, not a '%s'", e1->type->toChars());
-		type = Type::tint32;
-		break;
-	}
-	rvalue();
-    }
-    return this;
-}
-
-int PtrExp::isLvalue()
-{
-    return 1;
-}
-
-Expression *PtrExp::toLvalue(Scope *sc, Expression *e)
-{
-#if 0
-    tym = tybasic(e1->ET->Tty);
-    if (!(tyscalar(tym) ||
-	  tym == TYstruct ||
-	  tym == TYarray && e->Eoper == TOKaddr))
-	    synerr(EM_lvalue);	// lvalue expected
-#endif
-    return this;
-}
-
-Expression *PtrExp::modifiableLvalue(Scope *sc, Expression *e)
-{
-    //printf("PtrExp::modifiableLvalue() %s, type %s\n", toChars(), type->toChars());
-
-    if (e1->op == TOKsymoff)
-    {	SymOffExp *se = (SymOffExp *)e1;
-	se->var->checkModify(loc, sc, type);
-	//return toLvalue(sc, e);
-    }
-
-    return Expression::modifiableLvalue(sc, e);
-}
-
-
-void PtrExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{
-    buf->writeByte('*');
-    expToCBuffer(buf, hgs, e1, precedence[op]);
-}
-
-/************************************************************/
-
-NegExp::NegExp(Loc loc, Expression *e)
-	: UnaExp(loc, TOKneg, sizeof(NegExp), e)
-{
-}
-
-Expression *NegExp::semantic(Scope *sc)
-{   Expression *e;
-
-#if LOGSEMANTIC
-    printf("NegExp::semantic('%s')\n", toChars());
-#endif
-    if (!type)
-    {
-	UnaExp::semantic(sc);
-	e1 = resolveProperties(sc, e1);
-	e = op_overload(sc);
-	if (e)
-	    return e;
-
-	e1->checkNoBool();
-	if (e1->op != TOKslice)
-	    e1->checkArithmetic();
-	type = e1->type;
-    }
-    return this;
-}
-
-/************************************************************/
-
-UAddExp::UAddExp(Loc loc, Expression *e)
-	: UnaExp(loc, TOKuadd, sizeof(UAddExp), e)
-{
-}
-
-Expression *UAddExp::semantic(Scope *sc)
-{   Expression *e;
-
-#if LOGSEMANTIC
-    printf("UAddExp::semantic('%s')\n", toChars());
-#endif
-    assert(!type);
-    UnaExp::semantic(sc);
-    e1 = resolveProperties(sc, e1);
-    e = op_overload(sc);
-    if (e)
-	return e;
-    e1->checkNoBool();
-    e1->checkArithmetic();
-    return e1;
-}
-
-/************************************************************/
-
-ComExp::ComExp(Loc loc, Expression *e)
-	: UnaExp(loc, TOKtilde, sizeof(ComExp), e)
-{
-}
-
-Expression *ComExp::semantic(Scope *sc)
-{   Expression *e;
-
-    if (!type)
-    {
-	UnaExp::semantic(sc);
-	e1 = resolveProperties(sc, e1);
-	e = op_overload(sc);
-	if (e)
-	    return e;
-
-	e1->checkNoBool();
-	if (e1->op != TOKslice)
-	    e1 = e1->checkIntegral();
-	type = e1->type;
-    }
-    return this;
-}
-
-/************************************************************/
-
-NotExp::NotExp(Loc loc, Expression *e)
-	: UnaExp(loc, TOKnot, sizeof(NotExp), e)
-{
-}
-
-Expression *NotExp::semantic(Scope *sc)
-{
-    UnaExp::semantic(sc);
-    e1 = resolveProperties(sc, e1);
-    e1 = e1->checkToBoolean();
-    type = Type::tboolean;
-    return this;
-}
-
-int NotExp::isBit()
-{
-    return TRUE;
-}
-
-
-
-/************************************************************/
-
-BoolExp::BoolExp(Loc loc, Expression *e, Type *t)
-	: UnaExp(loc, TOKtobool, sizeof(BoolExp), e)
-{
-    type = t;
-}
-
-Expression *BoolExp::semantic(Scope *sc)
-{
-    UnaExp::semantic(sc);
-    e1 = resolveProperties(sc, e1);
-    e1 = e1->checkToBoolean();
-    type = Type::tboolean;
-    return this;
-}
-
-int BoolExp::isBit()
-{
-    return TRUE;
-}
-
-/************************************************************/
-
-DeleteExp::DeleteExp(Loc loc, Expression *e)
-	: UnaExp(loc, TOKdelete, sizeof(DeleteExp), e)
-{
-}
-
-Expression *DeleteExp::semantic(Scope *sc)
-{
-    Type *tb;
-
-    UnaExp::semantic(sc);
-    e1 = resolveProperties(sc, e1);
-    e1 = e1->toLvalue(sc, NULL);
-    type = Type::tvoid;
-
-    tb = e1->type->toBasetype();
-    switch (tb->ty)
-    {	case Tclass:
-	{   TypeClass *tc = (TypeClass *)tb;
-	    ClassDeclaration *cd = tc->sym;
-
-	    if (cd->isCOMinterface())
-	    {	/* Because COM classes are deleted by IUnknown.Release()
-		 */
-		error("cannot delete instance of COM interface %s", cd->toChars());
-	    }
-	    break;
-	}
-	case Tpointer:
-	    tb = ((TypePointer *)tb)->next->toBasetype();
-	    if (tb->ty == Tstruct)
-	    {
-		TypeStruct *ts = (TypeStruct *)tb;
-		StructDeclaration *sd = ts->sym;
-		FuncDeclaration *f = sd->aggDelete;
-		FuncDeclaration *fd = sd->dtor;
-
-		if (!f && !fd)
-		    break;
-
-		/* Construct:
-		 *	ea = copy e1 to a tmp to do side effects only once
-		 *	eb = call destructor
-		 *	ec = call deallocator
-		 */
-		Expression *ea = NULL;
-		Expression *eb = NULL;
-		Expression *ec = NULL;
-		VarDeclaration *v;
-
-		if (fd && f)
-		{   Identifier *id = Lexer::idPool("__tmp");
-		    v = new VarDeclaration(loc, e1->type, id, new ExpInitializer(loc, e1));
-		    v->semantic(sc);
-		    v->parent = sc->parent;
-		    ea = new DeclarationExp(loc, v);
-		    ea->type = v->type;
-		}
-
-		if (fd)
-		{   Expression *e = ea ? new VarExp(loc, v) : e1;
-		    e = new DotVarExp(0, e, fd, 0);
-		    eb = new CallExp(loc, e);
-		    eb = eb->semantic(sc);
-		}
-
-		if (f)
-		{
-		    Type *tpv = Type::tvoid->pointerTo();
-		    Expression *e = ea ? new VarExp(loc, v) : e1->castTo(sc, tpv);
-		    e = new CallExp(loc, new VarExp(loc, f), e);
-		    ec = e->semantic(sc);
-		}
-		ea = combine(ea, eb);
-		ea = combine(ea, ec);
-		assert(ea);
-		return ea;
-	    }
-	    break;
-
-	case Tarray:
-	    /* BUG: look for deleting arrays of structs with dtors.
-	     */
-	    break;
-
-	default:
-	    if (e1->op == TOKindex)
-	    {
-		IndexExp *ae = (IndexExp *)(e1);
-		Type *tb1 = ae->e1->type->toBasetype();
-		if (tb1->ty == Taarray)
-		    break;
-	    }
-	    error("cannot delete type %s", e1->type->toChars());
-	    break;
-    }
-
-    if (e1->op == TOKindex)
-    {
-	IndexExp *ae = (IndexExp *)(e1);
-	Type *tb1 = ae->e1->type->toBasetype();
-	if (tb1->ty == Taarray)
-	{   if (!global.params.useDeprecated)
-		error("delete aa[key] deprecated, use aa.remove(key)");
-	}
-    }
-
-    return this;
-}
-
-int DeleteExp::checkSideEffect(int flag)
-{
-    return 1;
-}
-
-Expression *DeleteExp::checkToBoolean()
-{
-    error("delete does not give a boolean result");
-    return this;
-}
-
-void DeleteExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{
-    buf->writestring("delete ");
-    expToCBuffer(buf, hgs, e1, precedence[op]);
-}
-
-/************************************************************/
-
-CastExp::CastExp(Loc loc, Expression *e, Type *t)
-	: UnaExp(loc, TOKcast, sizeof(CastExp), e)
-{
-    to = t;
-    this->tok = TOKreserved;
-}
-
-/* For cast(const) and cast(invariant)
- */
-CastExp::CastExp(Loc loc, Expression *e, enum TOK tok)
-	: UnaExp(loc, TOKcast, sizeof(CastExp), e)
-{
-    to = NULL;
-    this->tok = tok;
-}
-
-Expression *CastExp::syntaxCopy()
-{
-    return to ? new CastExp(loc, e1->syntaxCopy(), to->syntaxCopy())
-	      : new CastExp(loc, e1->syntaxCopy(), tok);
-}
-
-
-Expression *CastExp::semantic(Scope *sc)
-{   Expression *e;
-    BinExp *b;
-    UnaExp *u;
-
-#if LOGSEMANTIC
-    printf("CastExp::semantic('%s')\n", toChars());
-#endif
-
-//static int x; assert(++x < 10);
-
-    if (type)
-	return this;
-    UnaExp::semantic(sc);
-    if (e1->type)		// if not a tuple
-    {
-	e1 = resolveProperties(sc, e1);
-
-	/* Handle cast(const) and cast(invariant)
-	 */
-	if (!to)
-	{   if (tok == TOKconst)
-		to = e1->type->constOf();
-	    else if (tok == TOKinvariant || tok == TOKimmutable)
-		to = e1->type->invariantOf();
-	    else
-		assert(0);
-	}
-	else
-	    to = to->semantic(loc, sc);
-
-	e = op_overload(sc);
-	if (e)
-	{
-	    return e->implicitCastTo(sc, to);
-	}
-
-	Type *tob = to->toBasetype();
-	if (tob->ty == Tstruct &&
-	    !tob->equals(e1->type->toBasetype()) &&
-	    ((TypeStruct *)to)->sym->search(0, Id::call, 0)
-	   )
-	{
-	    /* Look to replace:
-	     *	cast(S)t
-	     * with:
-	     *	S(t)
-	     */
-
-	    // Rewrite as to.call(e1)
-	    e = new TypeExp(loc, to);
-	    e = new DotIdExp(loc, e, Id::call);
-	    e = new CallExp(loc, e, e1);
-	    e = e->semantic(sc);
-	    return e;
-	}
-    }
-    else if (!to)
-    {	error("cannot cast tuple");
-	to = Type::terror;
-    }
-    e = e1->castTo(sc, to);
-    return e;
-}
-
-int CastExp::checkSideEffect(int flag)
-{
-    /* if not:
-     *  cast(void)
-     *  cast(classtype)func()
-     */
-    if (!to->equals(Type::tvoid) &&
-	!(to->ty == Tclass && e1->op == TOKcall && e1->type->ty == Tclass))
-	return Expression::checkSideEffect(flag);
-    return 1;
-}
-
-void CastExp::checkEscape()
-{   Type *tb = type->toBasetype();
-    if (tb->ty == Tarray && e1->op == TOKvar &&
-	e1->type->toBasetype()->ty == Tsarray)
-    {	VarExp *ve = (VarExp *)e1;
-	VarDeclaration *v = ve->var->isVarDeclaration();
-	if (v)
-	{
-	    if (!v->isDataseg() && !v->isParameter())
-		error("escaping reference to local %s", v->toChars());
-	}
-    }
-}
-
-void CastExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{
-    buf->writestring("cast(");
-    if (to)
-	to->toCBuffer(buf, NULL, hgs);
-    else
-	buf->writestring(Token::tochars[tok]);
-    buf->writeByte(')');
-    expToCBuffer(buf, hgs, e1, precedence[op]);
-}
-
-
-/************************************************************/
-
-SliceExp::SliceExp(Loc loc, Expression *e1, Expression *lwr, Expression *upr)
-	: UnaExp(loc, TOKslice, sizeof(SliceExp), e1)
-{
-    this->upr = upr;
-    this->lwr = lwr;
-    lengthVar = NULL;
-}
-
-Expression *SliceExp::syntaxCopy()
-{
-    Expression *lwr = NULL;
-    if (this->lwr)
-	lwr = this->lwr->syntaxCopy();
-
-    Expression *upr = NULL;
-    if (this->upr)
-	upr = this->upr->syntaxCopy();
-
-    return new SliceExp(loc, e1->syntaxCopy(), lwr, upr);
-}
-
-Expression *SliceExp::semantic(Scope *sc)
-{   Expression *e;
-    AggregateDeclaration *ad;
-    //FuncDeclaration *fd;
-    ScopeDsymbol *sym;
-
-#if LOGSEMANTIC
-    printf("SliceExp::semantic('%s')\n", toChars());
-#endif
-    if (type)
-	return this;
-
-    UnaExp::semantic(sc);
-    e1 = resolveProperties(sc, e1);
-
-    e = this;
-
-    Type *t = e1->type->toBasetype();
-    if (t->ty == Tpointer)
-    {
-	if (!lwr || !upr)
-	    error("need upper and lower bound to slice pointer");
-    }
-    else if (t->ty == Tarray)
-    {
-    }
-    else if (t->ty == Tsarray)
-    {
-    }
-    else if (t->ty == Tclass)
-    {
-        ad = ((TypeClass *)t)->sym;
-        goto L1;
-    }
-    else if (t->ty == Tstruct)
-    {
-        ad = ((TypeStruct *)t)->sym;
-
-    L1:
-	if (search_function(ad, Id::slice))
-        {
-            // Rewrite as e1.slice(lwr, upr)
-	    e = new DotIdExp(loc, e1, Id::slice);
-
-	    if (lwr)
-	    {
-		assert(upr);
-		e = new CallExp(loc, e, lwr, upr);
-	    }
-	    else
-	    {	assert(!upr);
-		e = new CallExp(loc, e);
-	    }
-	    e = e->semantic(sc);
-	    return e;
-        }
-	goto Lerror;
-    }
-    else if (t->ty == Ttuple)
-    {
-	if (!lwr && !upr)
-	    return e1;
-	if (!lwr || !upr)
-	{   error("need upper and lower bound to slice tuple");
-	    goto Lerror;
-	}
-    }
-    else
-	goto Lerror;
-
-    if (t->ty == Tsarray || t->ty == Tarray || t->ty == Ttuple)
-    {
-	sym = new ArrayScopeSymbol(sc, this);
-	sym->loc = loc;
-	sym->parent = sc->scopesym;
-	sc = sc->push(sym);
-    }
-
-    if (lwr)
-    {	lwr = lwr->semantic(sc);
-	lwr = resolveProperties(sc, lwr);
-	lwr = lwr->implicitCastTo(sc, Type::tsize_t);
-    }
-    if (upr)
-    {	upr = upr->semantic(sc);
-	upr = resolveProperties(sc, upr);
-	upr = upr->implicitCastTo(sc, Type::tsize_t);
-    }
-
-    if (t->ty == Tsarray || t->ty == Tarray || t->ty == Ttuple)
-	sc->pop();
-
-    if (t->ty == Ttuple)
-    {
-	lwr = lwr->optimize(WANTvalue);
-	upr = upr->optimize(WANTvalue);
-	uinteger_t i1 = lwr->toUInteger();
-	uinteger_t i2 = upr->toUInteger();
-
-	size_t length;
-	TupleExp *te;
-	TypeTuple *tup;
-
-	if (e1->op == TOKtuple)		// slicing an expression tuple
-	{   te = (TupleExp *)e1;
-	    length = te->exps->dim;
-	}
-	else if (e1->op == TOKtype)	// slicing a type tuple
-	{   tup = (TypeTuple *)t;
-	    length = Argument::dim(tup->arguments);
-	}
-	else
-	    assert(0);
-
-	if (i1 <= i2 && i2 <= length)
-	{   size_t j1 = (size_t) i1;
-	    size_t j2 = (size_t) i2;
-
-	    if (e1->op == TOKtuple)
-	    {	Expressions *exps = new Expressions;
-		exps->setDim(j2 - j1);
-		for (size_t i = 0; i < j2 - j1; i++)
-		{   Expression *e = (Expression *)te->exps->data[j1 + i];
-		    exps->data[i] = (void *)e;
-		}
-		e = new TupleExp(loc, exps);
-	    }
-	    else
-	    {	Arguments *args = new Arguments;
-		args->reserve(j2 - j1);
-		for (size_t i = j1; i < j2; i++)
-		{   Argument *arg = Argument::getNth(tup->arguments, i);
-		    args->push(arg);
-		}
-		e = new TypeExp(e1->loc, new TypeTuple(args));
-	    }
-	    e = e->semantic(sc);
-	}
-	else
-	{
-	    error("string slice [%llu .. %llu] is out of bounds", i1, i2);
-	    e = e1;
-	}
-	return e;
-    }
-
-    type = t->nextOf()->arrayOf();
-    return e;
-
-Lerror:
-    char *s;
-    if (t->ty == Tvoid)
-	s = e1->toChars();
-    else
-	s = t->toChars();
-    error("%s cannot be sliced with []", s);
-    type = Type::terror;
-    return e;
-}
-
-void SliceExp::checkEscape()
-{
-    e1->checkEscape();
-}
-
-int SliceExp::isLvalue()
-{
-    return 1;
-}
-
-Expression *SliceExp::toLvalue(Scope *sc, Expression *e)
-{
-    return this;
-}
-
-Expression *SliceExp::modifiableLvalue(Scope *sc, Expression *e)
-{
-    error("slice expression %s is not a modifiable lvalue", toChars());
-    return this;
-}
-
-void SliceExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{
-    expToCBuffer(buf, hgs, e1, precedence[op]);
-    buf->writeByte('[');
-    if (upr || lwr)
-    {
-	if (lwr)
-	    expToCBuffer(buf, hgs, lwr, PREC_assign);
-	else
-	    buf->writeByte('0');
-	buf->writestring("..");
-	if (upr)
-	    expToCBuffer(buf, hgs, upr, PREC_assign);
-	else
-	    buf->writestring("length");		// BUG: should be array.length
-    }
-    buf->writeByte(']');
-}
-
-/********************** ArrayLength **************************************/
-
-ArrayLengthExp::ArrayLengthExp(Loc loc, Expression *e1)
-	: UnaExp(loc, TOKarraylength, sizeof(ArrayLengthExp), e1)
-{
-}
-
-Expression *ArrayLengthExp::semantic(Scope *sc)
-{   Expression *e;
-
-#if LOGSEMANTIC
-    printf("ArrayLengthExp::semantic('%s')\n", toChars());
-#endif
-    if (!type)
-    {
-	UnaExp::semantic(sc);
-	e1 = resolveProperties(sc, e1);
-
-	type = Type::tsize_t;
-    }
-    return this;
-}
-
-void ArrayLengthExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{
-    expToCBuffer(buf, hgs, e1, PREC_primary);
-    buf->writestring(".length");
-}
-
-/*********************** ArrayExp *************************************/
-
-// e1 [ i1, i2, i3, ... ]
-
-ArrayExp::ArrayExp(Loc loc, Expression *e1, Expressions *args)
-	: UnaExp(loc, TOKarray, sizeof(ArrayExp), e1)
-{
-    arguments = args;
-}
-
-Expression *ArrayExp::syntaxCopy()
-{
-    return new ArrayExp(loc, e1->syntaxCopy(), arraySyntaxCopy(arguments));
-}
-
-Expression *ArrayExp::semantic(Scope *sc)
-{   Expression *e;
-    Type *t1;
-
-#if LOGSEMANTIC
-    printf("ArrayExp::semantic('%s')\n", toChars());
-#endif
-    UnaExp::semantic(sc);
-    e1 = resolveProperties(sc, e1);
-
-    t1 = e1->type->toBasetype();
-    if (t1->ty != Tclass && t1->ty != Tstruct)
-    {	// Convert to IndexExp
-	if (arguments->dim != 1)
-	    error("only one index allowed to index %s", t1->toChars());
-	e = new IndexExp(loc, e1, (Expression *)arguments->data[0]);
-	return e->semantic(sc);
-    }
-
-    // Run semantic() on each argument
-    for (size_t i = 0; i < arguments->dim; i++)
-    {	e = (Expression *)arguments->data[i];
-
-	e = e->semantic(sc);
-	if (!e->type)
-	    error("%s has no value", e->toChars());
-	arguments->data[i] = (void *)e;
-    }
-
-    expandTuples(arguments);
-    assert(arguments && arguments->dim);
-
-    e = op_overload(sc);
-    if (!e)
-    {	error("no [] operator overload for type %s", e1->type->toChars());
-	e = e1;
-    }
-    return e;
-}
-
-
-int ArrayExp::isLvalue()
-{
-    if (type && type->toBasetype()->ty == Tvoid)
-	return 0;
-    return 1;
-}
-
-Expression *ArrayExp::toLvalue(Scope *sc, Expression *e)
-{
-    if (type && type->toBasetype()->ty == Tvoid)
-	error("voids have no value");
-    return this;
-}
-
-
-void ArrayExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{   int i;
-
-    expToCBuffer(buf, hgs, e1, PREC_primary);
-    buf->writeByte('[');
-    argsToCBuffer(buf, arguments, hgs);
-    buf->writeByte(']');
-}
-
-/************************* DotExp ***********************************/
-
-DotExp::DotExp(Loc loc, Expression *e1, Expression *e2)
-	: BinExp(loc, TOKdotexp, sizeof(DotExp), e1, e2)
-{
-}
-
-Expression *DotExp::semantic(Scope *sc)
-{
-#if LOGSEMANTIC
-    printf("DotExp::semantic('%s')\n", toChars());
-    if (type) printf("\ttype = %s\n", type->toChars());
-#endif
-    e1 = e1->semantic(sc);
-    e2 = e2->semantic(sc);
-    if (e2->op == TOKimport)
-    {
-	ScopeExp *se = (ScopeExp *)e2;
-	TemplateDeclaration *td = se->sds->isTemplateDeclaration();
-	if (td)
-	{   Expression *e = new DotTemplateExp(loc, e1, td);
-	    e = e->semantic(sc);
-	    return e;
-	}
-    }
-    if (!type)
-	type = e2->type;
-    return this;
-}
-
-
-/************************* CommaExp ***********************************/
-
-CommaExp::CommaExp(Loc loc, Expression *e1, Expression *e2)
-	: BinExp(loc, TOKcomma, sizeof(CommaExp), e1, e2)
-{
-}
-
-Expression *CommaExp::semantic(Scope *sc)
-{
-    if (!type)
-    {	BinExp::semanticp(sc);
-	type = e2->type;
-    }
-    return this;
-}
-
-void CommaExp::checkEscape()
-{
-    e2->checkEscape();
-}
-
-int CommaExp::isLvalue()
-{
-    return e2->isLvalue();
-}
-
-Expression *CommaExp::toLvalue(Scope *sc, Expression *e)
-{
-    e2 = e2->toLvalue(sc, NULL);
-    return this;
-}
-
-Expression *CommaExp::modifiableLvalue(Scope *sc, Expression *e)
-{
-    e2 = e2->modifiableLvalue(sc, e);
-    return this;
-}
-
-int CommaExp::isBool(int result)
-{
-    return e2->isBool(result);
-}
-
-int CommaExp::checkSideEffect(int flag)
-{
-    if (flag == 2)
-	return e1->checkSideEffect(2) || e2->checkSideEffect(2);
-    else
-    {
-	// Don't check e1 until we cast(void) the a,b code generation
-	return e2->checkSideEffect(flag);
-    }
-}
-
-/************************** IndexExp **********************************/
-
-// e1 [ e2 ]
-
-IndexExp::IndexExp(Loc loc, Expression *e1, Expression *e2)
-	: BinExp(loc, TOKindex, sizeof(IndexExp), e1, e2)
-{
-    //printf("IndexExp::IndexExp('%s')\n", toChars());
-    lengthVar = NULL;
-    modifiable = 0;	// assume it is an rvalue
-}
-
-Expression *IndexExp::semantic(Scope *sc)
-{   Expression *e;
-    BinExp *b;
-    UnaExp *u;
-    Type *t1;
-    ScopeDsymbol *sym;
-
-#if LOGSEMANTIC
-    printf("IndexExp::semantic('%s')\n", toChars());
-#endif
-    if (type)
-	return this;
-    if (!e1->type)
-	e1 = e1->semantic(sc);
-    assert(e1->type);		// semantic() should already be run on it
-    e = this;
-
-    // Note that unlike C we do not implement the int[ptr]
-
-    t1 = e1->type->toBasetype();
-
-    if (t1->ty == Tsarray || t1->ty == Tarray || t1->ty == Ttuple)
-    {	// Create scope for 'length' variable
-	sym = new ArrayScopeSymbol(sc, this);
-	sym->loc = loc;
-	sym->parent = sc->scopesym;
-	sc = sc->push(sym);
-    }
-
-    e2 = e2->semantic(sc);
-    if (!e2->type)
-    {
-	error("%s has no value", e2->toChars());
-	e2->type = Type::terror;
-    }
-    e2 = resolveProperties(sc, e2);
-
-    if (t1->ty == Tsarray || t1->ty == Tarray || t1->ty == Ttuple)
-	sc = sc->pop();
-
-    switch (t1->ty)
-    {
-	case Tpointer:
-	case Tarray:
-	    e2 = e2->implicitCastTo(sc, Type::tsize_t);
-	    e->type = ((TypeNext *)t1)->next;
-	    break;
-
-	case Tsarray:
-	{
-	    e2 = e2->implicitCastTo(sc, Type::tsize_t);
-
-	    TypeSArray *tsa = (TypeSArray *)t1;
-
-#if 0 	// Don't do now, because it might be short-circuit evaluated
-	    // Do compile time array bounds checking if possible
-	    e2 = e2->optimize(WANTvalue);
-	    if (e2->op == TOKint64)
-	    {
-		integer_t index = e2->toInteger();
-		integer_t length = tsa->dim->toInteger();
-		if (index < 0 || index >= length)
-		    error("array index [%lld] is outside array bounds [0 .. %lld]",
-			    index, length);
-	    }
-#endif
-	    e->type = t1->nextOf();
-	    break;
-	}
-
-	case Taarray:
-	{   TypeAArray *taa = (TypeAArray *)t1;
-
-	    e2 = e2->implicitCastTo(sc, taa->index);	// type checking
-	    type = taa->next;
-	    break;
-	}
-
-	case Ttuple:
-	{
-	    e2 = e2->implicitCastTo(sc, Type::tsize_t);
-	    e2 = e2->optimize(WANTvalue | WANTinterpret);
-	    uinteger_t index = e2->toUInteger();
-	    size_t length;
-	    TupleExp *te;
-	    TypeTuple *tup;
-
-	    if (e1->op == TOKtuple)
-	    {	te = (TupleExp *)e1;
-		length = te->exps->dim;
-	    }
-	    else if (e1->op == TOKtype)
-	    {
-		tup = (TypeTuple *)t1;
-		length = Argument::dim(tup->arguments);
-	    }
-	    else
-		assert(0);
-
-	    if (index < length)
-	    {
-
-		if (e1->op == TOKtuple)
-		    e = (Expression *)te->exps->data[(size_t)index];
-		else
-		    e = new TypeExp(e1->loc, Argument::getNth(tup->arguments, (size_t)index)->type);
-	    }
-	    else
-	    {
-        error("array index [%llu] is outside array bounds [0 .. %"PRIuSIZE"]",
-            index, length);
-        e = e1;
-	    }
-	    break;
-	}
-
-	default:
-	    error("%s must be an array or pointer type, not %s",
-		e1->toChars(), e1->type->toChars());
-	    type = Type::tint32;
-	    break;
-    }
-    return e;
-}
-
-int IndexExp::isLvalue()
-{
-    return 1;
-}
-
-Expression *IndexExp::toLvalue(Scope *sc, Expression *e)
-{
-//    if (type && type->toBasetype()->ty == Tvoid)
-//	error("voids have no value");
-    return this;
-}
-
-Expression *IndexExp::modifiableLvalue(Scope *sc, Expression *e)
-{
-    //printf("IndexExp::modifiableLvalue(%s)\n", toChars());
-    modifiable = 1;
-    if (e1->op == TOKstring)
-	error("string literals are immutable");
-    if (type && !type->isMutable())
-	error("%s isn't mutable", e->toChars());
-    if (e1->type->toBasetype()->ty == Taarray)
-	e1 = e1->modifiableLvalue(sc, e1);
-    return toLvalue(sc, e);
-}
-
-void IndexExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{
-    expToCBuffer(buf, hgs, e1, PREC_primary);
-    buf->writeByte('[');
-    expToCBuffer(buf, hgs, e2, PREC_assign);
-    buf->writeByte(']');
-}
-
-
-/************************* PostExp ***********************************/
-
-PostExp::PostExp(enum TOK op, Loc loc, Expression *e)
-	: BinExp(loc, op, sizeof(PostExp), e,
-	  new IntegerExp(loc, 1, Type::tint32))
-{
-}
-
-Expression *PostExp::semantic(Scope *sc)
-{   Expression *e = this;
-
-    if (!type)
-    {
-	BinExp::semantic(sc);
-	e2 = resolveProperties(sc, e2);
-
-	e = op_overload(sc);
-	if (e)
-	    return e;
-
-	e = this;
-	e1 = e1->modifiableLvalue(sc, e1);
-	e1->checkScalar();
-	e1->checkNoBool();
-	if (e1->type->ty == Tpointer)
-	    e = scaleFactor(sc);
-	else
-	    e2 = e2->castTo(sc, e1->type);
-	e->type = e1->type;
-    }
-    return e;
-}
-
-void PostExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{
-    expToCBuffer(buf, hgs, e1, precedence[op]);
-    buf->writestring((op == TOKplusplus) ? (char *)"++" : (char *)"--");
-}
-
-/************************************************************/
-
-/* op can be TOKassign, TOKconstruct, or TOKblit */
-
-AssignExp::AssignExp(Loc loc, Expression *e1, Expression *e2)
-	: BinExp(loc, TOKassign, sizeof(AssignExp), e1, e2)
-{
-    ismemset = 0;
-}
-
-Expression *AssignExp::semantic(Scope *sc)
-{
-    Expression *e1old = e1;
-
-#if LOGSEMANTIC
-    printf("AssignExp::semantic('%s')\n", toChars());
-#endif
-    //printf("e1->op = %d, '%s'\n", e1->op, Token::toChars(e1->op));
-    //printf("e2->op = %d, '%s'\n", e2->op, Token::toChars(e2->op));
-
-    if (type)
-	return this;
-
-    if (e2->op == TOKcomma)
-    {	/* Rewrite to get rid of the comma from rvalue
-	 */
-	AssignExp *ea = new AssignExp(loc, e1, ((CommaExp *)e2)->e2);
-	ea->op = op;
-	Expression *e = new CommaExp(loc, ((CommaExp *)e2)->e1, ea);
-	return e->semantic(sc);
-    }
-
-    /* Look for operator overloading of a[i]=value.
-     * Do it before semantic() otherwise the a[i] will have been
-     * converted to a.opIndex() already.
-     */
-    if (e1->op == TOKarray)
-    {
-	ArrayExp *ae = (ArrayExp *)e1;
-	AggregateDeclaration *ad;
-	Identifier *id = Id::index;
-
-	ae->e1 = ae->e1->semantic(sc);
-	Type *t1 = ae->e1->type->toBasetype();
-	if (t1->ty == Tstruct)
-	{
-	    ad = ((TypeStruct *)t1)->sym;
-	    goto L1;
-	}
-	else if (t1->ty == Tclass)
-	{
-	    ad = ((TypeClass *)t1)->sym;
-	  L1:
-	    // Rewrite (a[i] = value) to (a.opIndexAssign(value, i))
-	    if (search_function(ad, Id::indexass))
-	    {	Expression *e = new DotIdExp(loc, ae->e1, Id::indexass);
-		Expressions *a = (Expressions *)ae->arguments->copy();
-
-		a->insert(0, e2);
-		e = new CallExp(loc, e, a);
-		e = e->semantic(sc);
-		return e;
-	    }
-	    else
-	    {
-		// Rewrite (a[i] = value) to (a.opIndex(i, value))
-		if (search_function(ad, id))
-		{   Expression *e = new DotIdExp(loc, ae->e1, id);
-
-		    if (1 || !global.params.useDeprecated)
-			error("operator [] assignment overload with opIndex(i, value) illegal, use opIndexAssign(value, i)");
-
-		    e = new CallExp(loc, e, (Expression *)ae->arguments->data[0], e2);
-		    e = e->semantic(sc);
-		    return e;
-		}
-	    }
-	}
-    }
-    /* Look for operator overloading of a[i..j]=value.
-     * Do it before semantic() otherwise the a[i..j] will have been
-     * converted to a.opSlice() already.
-     */
-    if (e1->op == TOKslice)
-    {	Type *t1;
-	SliceExp *ae = (SliceExp *)e1;
-	AggregateDeclaration *ad;
-	Identifier *id = Id::index;
-
-	ae->e1 = ae->e1->semantic(sc);
-	ae->e1 = resolveProperties(sc, ae->e1);
-	t1 = ae->e1->type->toBasetype();
-	if (t1->ty == Tstruct)
-	{
-	    ad = ((TypeStruct *)t1)->sym;
-	    goto L2;
-	}
-	else if (t1->ty == Tclass)
-	{
-	    ad = ((TypeClass *)t1)->sym;
-	  L2:
-	    // Rewrite (a[i..j] = value) to (a.opIndexAssign(value, i, j))
-	    if (search_function(ad, Id::sliceass))
-	    {	Expression *e = new DotIdExp(loc, ae->e1, Id::sliceass);
-		Expressions *a = new Expressions();
-
-		a->push(e2);
-		if (ae->lwr)
-		{   a->push(ae->lwr);
-		    assert(ae->upr);
-		    a->push(ae->upr);
-		}
-		else
-		    assert(!ae->upr);
-		e = new CallExp(loc, e, a);
-		e = e->semantic(sc);
-		return e;
-	    }
-	}
-    }
-
-    BinExp::semantic(sc);
-
-    if (e1->op == TOKdottd)
-    {	// Rewrite a.b=e2, when b is a template, as a.b(e2)
-	Expression *e = new CallExp(loc, e1, e2);
-	e = e->semantic(sc);
-	return e;
-    }
-
-    e2 = resolveProperties(sc, e2);
-    assert(e1->type);
-
-    /* Rewrite tuple assignment as a tuple of assignments.
-     */
-    if (e1->op == TOKtuple && e2->op == TOKtuple)
-    {	TupleExp *tup1 = (TupleExp *)e1;
-	TupleExp *tup2 = (TupleExp *)e2;
-	size_t dim = tup1->exps->dim;
-	if (dim != tup2->exps->dim)
-	{
-	    error("mismatched tuple lengths, %d and %d", (int)dim, (int)tup2->exps->dim);
-	}
-	else
-	{   Expressions *exps = new Expressions;
-	    exps->setDim(dim);
-
-	    for (int i = 0; i < dim; i++)
-	    {	Expression *ex1 = (Expression *)tup1->exps->data[i];
-		Expression *ex2 = (Expression *)tup2->exps->data[i];
-		exps->data[i] = (void *) new AssignExp(loc, ex1, ex2);
-	    }
-	    Expression *e = new TupleExp(loc, exps);
-	    e = e->semantic(sc);
-	    return e;
-	}
-    }
-
-    Type *t1 = e1->type->toBasetype();
-
-    if (t1->ty == Tfunction)
-    {	// Rewrite f=value to f(value)
-	Expression *e = new CallExp(loc, e1, e2);
-	e = e->semantic(sc);
-	return e;
-    }
-
-    /* If it is an assignment from a 'foreign' type,
-     * check for operator overloading.
-     */
-    if (t1->ty == Tstruct)
-    {
-	StructDeclaration *sd = ((TypeStruct *)t1)->sym;
-	if (op == TOKassign)
-	{
-	    Expression *e = op_overload(sc);
-	    if (e)
-		return e;
-	}
-	else if (op == TOKconstruct)
-	{   Type *t2 = e2->type->toBasetype();
-	    if (t2->ty == Tstruct &&
-		sd == ((TypeStruct *)t2)->sym &&
-		sd->cpctor)
-	    {	/* We have a copy constructor for this
-		 */
-		if (e2->op == TOKvar || e2->op == TOKstar)
-		{   /* Write as:
-		     *	e1.cpctor(e2);
-		     */
-		    Expression *e = new DotVarExp(loc, e1, sd->cpctor, 0);
-		    e = new CallExp(loc, e, e2);
-		    return e->semantic(sc);
-		}
-		else if (e2->op == TOKquestion)
-		{   /* Write as:
-		     *	a ? e1 = b : e1 = c;
-		     */
-		    CondExp *ec = (CondExp *)e2;
-		    AssignExp *ea1 = new AssignExp(ec->e1->loc, e1, ec->e1);
-		    ea1->op = op;
-		    AssignExp *ea2 = new AssignExp(ec->e1->loc, e1, ec->e2);
-		    ea2->op = op;
-		    Expression *e = new CondExp(loc, ec->econd, ea1, ea2);
-		    return e->semantic(sc);
-		}
-	    }
-	}
-    }
-    else if (t1->ty == Tclass)
-    {	// Disallow assignment operator overloads for same type
-	if (!e2->type->implicitConvTo(e1->type))
-	{
-	    Expression *e = op_overload(sc);
-	    if (e)
-		return e;
-	}
-    }
-
-    if (t1->ty == Tsarray)
-    {	// Convert e1 to e1[]
-	Expression *e = new SliceExp(e1->loc, e1, NULL, NULL);
-	e1 = e->semantic(sc);
-	t1 = e1->type->toBasetype();
-    }
-
-    e2->rvalue();
-
-    if (e1->op == TOKarraylength)
-    {
-	// e1 is not an lvalue, but we let code generator handle it
-	ArrayLengthExp *ale = (ArrayLengthExp *)e1;
-
-	ale->e1 = ale->e1->modifiableLvalue(sc, e1);
-    }
-    else if (e1->op == TOKslice)
-    {
-	Type *tn = e1->type->nextOf();
-	if (tn && !tn->isMutable() && op != TOKconstruct)
-	    error("slice %s is not mutable", e1->toChars());
-    }
-    else
-    {	// Try to do a decent error message with the expression
-	// before it got constant folded
-	if (e1->op != TOKvar)
-	    e1 = e1->optimize(WANTvalue);
-
-	if (op != TOKconstruct)
-	    e1 = e1->modifiableLvalue(sc, e1old);
-    }
-
-    Type *t2 = e2->type;
-    if (e1->op == TOKslice &&
-	t1->nextOf() &&
-	e2->implicitConvTo(t1->nextOf())
-       )
-    {	// memset
-	ismemset = 1;	// make it easy for back end to tell what this is
-	e2 = e2->implicitCastTo(sc, t1->nextOf());
-    }
-    else if (t1->ty == Tsarray)
-    {
-	/* Should have already converted e1 => e1[]
-	 */
-	assert(0);
-	//error("cannot assign to static array %s", e1->toChars());
-    }
-    else if (e1->op == TOKslice)
-    {
-	e2 = e2->implicitCastTo(sc, e1->type->constOf());
-    }
-    else
-    {
-	e2 = e2->implicitCastTo(sc, e1->type);
-    }
-
-    /* Look for array operations
-     */
-    if (e1->op == TOKslice && !ismemset &&
-	(e2->op == TOKadd || e2->op == TOKmin ||
-	 e2->op == TOKmul || e2->op == TOKdiv ||
-	 e2->op == TOKmod || e2->op == TOKxor ||
-	 e2->op == TOKand || e2->op == TOKor  ||
-	 e2->op == TOKtilde || e2->op == TOKneg))
-    {
-	type = e1->type;
-	return arrayOp(sc);
-    }
-
-    type = e1->type;
-    assert(type);
-    return this;
-}
-
-Expression *AssignExp::checkToBoolean()
-{
-    // Things like:
-    //	if (a = b) ...
-    // are usually mistakes.
-
-    error("'=' does not give a boolean result");
-    return this;
-}
-
-/************************************************************/
-
-AddAssignExp::AddAssignExp(Loc loc, Expression *e1, Expression *e2)
-	: BinExp(loc, TOKaddass, sizeof(AddAssignExp), e1, e2)
-{
-}
-
-Expression *AddAssignExp::semantic(Scope *sc)
-{   Expression *e;
-
-    if (type)
-	return this;
-
-    BinExp::semantic(sc);
-    e2 = resolveProperties(sc, e2);
-
-    e = op_overload(sc);
-    if (e)
-	return e;
-
-    Type *tb1 = e1->type->toBasetype();
-    Type *tb2 = e2->type->toBasetype();
-
-    if (e1->op == TOKslice)
-    {
-	typeCombine(sc);
-	type = e1->type;
-	return arrayOp(sc);
-    }
-    else
-    {
-	e1 = e1->modifiableLvalue(sc, e1);
-    }
-
-    if ((tb1->ty == Tarray || tb1->ty == Tsarray) &&
-	(tb2->ty == Tarray || tb2->ty == Tsarray) &&
-	tb1->nextOf()->equals(tb2->nextOf())
-       )
-    {
-	type = e1->type;
-	typeCombine(sc);
-	e = this;
-    }
-    else
-    {
-	e1->checkScalar();
-	e1->checkNoBool();
-	if (tb1->ty == Tpointer && tb2->isintegral())
-	    e = scaleFactor(sc);
-	else if (tb1->ty == Tbit || tb1->ty == Tbool)
-	{
-#if 0
-	    // Need to rethink this
-	    if (e1->op != TOKvar)
-	    {   // Rewrite e1+=e2 to (v=&e1),*v=*v+e2
-		VarDeclaration *v;
-		Expression *ea;
-		Expression *ex;
-
-		Identifier *id = Lexer::uniqueId("__name");
-
-		v = new VarDeclaration(loc, tb1->pointerTo(), id, NULL);
-		v->semantic(sc);
-		if (!sc->insert(v))
-		    assert(0);
-		v->parent = sc->func;
-
-		ea = new AddrExp(loc, e1);
-		ea = new AssignExp(loc, new VarExp(loc, v), ea);
-
-		ex = new VarExp(loc, v);
-		ex = new PtrExp(loc, ex);
-		e = new AddExp(loc, ex, e2);
-		e = new CastExp(loc, e, e1->type);
-		e = new AssignExp(loc, ex->syntaxCopy(), e);
-
-		e = new CommaExp(loc, ea, e);
-	    }
-	    else
-#endif
-	    {   // Rewrite e1+=e2 to e1=e1+e2
-		// BUG: doesn't account for side effects in e1
-		// BUG: other assignment operators for bits aren't handled at all
-		e = new AddExp(loc, e1, e2);
-		e = new CastExp(loc, e, e1->type);
-		e = new AssignExp(loc, e1->syntaxCopy(), e);
-	    }
-	    e = e->semantic(sc);
-	}
-	else
-	{
-	    type = e1->type;
-	    typeCombine(sc);
-	    e1->checkArithmetic();
-	    e2->checkArithmetic();
-	    if (type->isreal() || type->isimaginary())
-	    {
-		assert(global.errors || e2->type->isfloating());
-		e2 = e2->castTo(sc, e1->type);
-	    }
-	    e = this;
-
-	    if (e2->type->iscomplex() && !type->iscomplex())
-		error("Cannot assign %s to %s", e2->type->toChars(), type->toChars());
-	}
-    }
-    return e;
-}
-
-/************************************************************/
-
-MinAssignExp::MinAssignExp(Loc loc, Expression *e1, Expression *e2)
-	: BinExp(loc, TOKminass, sizeof(MinAssignExp), e1, e2)
-{
-}
-
-Expression *MinAssignExp::semantic(Scope *sc)
-{   Expression *e;
-
-    if (type)
-	return this;
-
-    BinExp::semantic(sc);
-    e2 = resolveProperties(sc, e2);
-
-    e = op_overload(sc);
-    if (e)
-	return e;
-
-    if (e1->op == TOKslice)
-    {	// T[] -= ...
-	typeCombine(sc);
-	type = e1->type;
-	return arrayOp(sc);
-    }
-
-    e1 = e1->modifiableLvalue(sc, e1);
-    e1->checkScalar();
-    e1->checkNoBool();
-    if (e1->type->ty == Tpointer && e2->type->isintegral())
-	e = scaleFactor(sc);
-    else
-    {
-	e1 = e1->checkArithmetic();
-	e2 = e2->checkArithmetic();
-	type = e1->type;
-	typeCombine(sc);
-	if (type->isreal() || type->isimaginary())
-	{
-	    assert(e2->type->isfloating());
-	    e2 = e2->castTo(sc, e1->type);
-	}
-	e = this;
-
-	if (e2->type->iscomplex() && !type->iscomplex())
-	    error("Cannot assign %s to %s", e2->type->toChars(), type->toChars());
-    }
-    return e;
-}
-
-/************************************************************/
-
-CatAssignExp::CatAssignExp(Loc loc, Expression *e1, Expression *e2)
-	: BinExp(loc, TOKcatass, sizeof(CatAssignExp), e1, e2)
-{
-}
-
-Expression *CatAssignExp::semantic(Scope *sc)
-{   Expression *e;
-
-    BinExp::semantic(sc);
-    e2 = resolveProperties(sc, e2);
-
-    e = op_overload(sc);
-    if (e)
-	return e;
-
-    if (e1->op == TOKslice)
-    {	SliceExp *se = (SliceExp *)e1;
-
-	if (se->e1->type->toBasetype()->ty == Tsarray)
-	    error("cannot append to static array %s", se->e1->type->toChars());
-    }
-
-    e1 = e1->modifiableLvalue(sc, e1);
-
-    Type *tb1 = e1->type->toBasetype();
-    Type *tb2 = e2->type->toBasetype();
-
-    e2->rvalue();
-
-    if ((tb1->ty == Tarray) &&
-	(tb2->ty == Tarray || tb2->ty == Tsarray) &&
-	(e2->implicitConvTo(e1->type) ||
-	 tb2->nextOf()->implicitConvTo(tb1->nextOf()))
-       )
-    {	// Append array
-	e2 = e2->castTo(sc, e1->type);
-	type = e1->type;
-	e = this;
-    }
-    else if ((tb1->ty == Tarray) &&
-	e2->implicitConvTo(tb1->nextOf())
-       )
-    {	// Append element
-	e2 = e2->castTo(sc, tb1->nextOf());
-	type = e1->type;
-	e = this;
-    }
-    else
-    {
-	error("cannot append type %s to type %s", tb2->toChars(), tb1->toChars());
-	type = Type::tint32;
-	e = this;
-    }
-    return e;
-}
-
-/************************************************************/
-
-MulAssignExp::MulAssignExp(Loc loc, Expression *e1, Expression *e2)
-	: BinExp(loc, TOKmulass, sizeof(MulAssignExp), e1, e2)
-{
-}
-
-Expression *MulAssignExp::semantic(Scope *sc)
-{   Expression *e;
-
-    BinExp::semantic(sc);
-    e2 = resolveProperties(sc, e2);
-
-    e = op_overload(sc);
-    if (e)
-	return e;
-
-    if (e1->op == TOKslice)
-    {	// T[] -= ...
-	typeCombine(sc);
-	type = e1->type;
-	return arrayOp(sc);
-    }
-
-    e1 = e1->modifiableLvalue(sc, e1);
-    e1->checkScalar();
-    e1->checkNoBool();
-    type = e1->type;
-    typeCombine(sc);
-    e1->checkArithmetic();
-    e2->checkArithmetic();
-    if (e2->type->isfloating())
-    {	Type *t1;
-	Type *t2;
-
-	t1 = e1->type;
-	t2 = e2->type;
-	if (t1->isreal())
-	{
-	    if (t2->isimaginary() || t2->iscomplex())
-	    {
-		e2 = e2->castTo(sc, t1);
-	    }
-	}
-	else if (t1->isimaginary())
-	{
-	    if (t2->isimaginary() || t2->iscomplex())
-	    {
-		switch (t1->ty)
-		{
-		    case Timaginary32: t2 = Type::tfloat32; break;
-		    case Timaginary64: t2 = Type::tfloat64; break;
-		    case Timaginary80: t2 = Type::tfloat80; break;
-		    default:
-			assert(0);
-		}
-		e2 = e2->castTo(sc, t2);
-	    }
-	}
-
-	if (e2->type->iscomplex() && !type->iscomplex())
-	    error("Cannot assign %s to %s", e2->type->toChars(), type->toChars());
-    }
-    return this;
-}
-
-/************************************************************/
-
-DivAssignExp::DivAssignExp(Loc loc, Expression *e1, Expression *e2)
-	: BinExp(loc, TOKdivass, sizeof(DivAssignExp), e1, e2)
-{
-}
-
-Expression *DivAssignExp::semantic(Scope *sc)
-{   Expression *e;
-
-    BinExp::semantic(sc);
-    e2 = resolveProperties(sc, e2);
-
-    e = op_overload(sc);
-    if (e)
-	return e;
-
-    if (e1->op == TOKslice)
-    {	// T[] -= ...
-	typeCombine(sc);
-	type = e1->type;
-	return arrayOp(sc);
-    }
-
-    e1 = e1->modifiableLvalue(sc, e1);
-    e1->checkScalar();
-    e1->checkNoBool();
-    type = e1->type;
-    typeCombine(sc);
-    e1->checkArithmetic();
-    e2->checkArithmetic();
-    if (e2->type->isimaginary())
-    {	Type *t1;
-	Type *t2;
-
-	t1 = e1->type;
-	if (t1->isreal())
-	{   // x/iv = i(-x/v)
-	    // Therefore, the result is 0
-	    e2 = new CommaExp(loc, e2, new RealExp(loc, 0, t1));
-	    e2->type = t1;
-	    e = new AssignExp(loc, e1, e2);
-	    e->type = t1;
-	    return e;
-	}
-	else if (t1->isimaginary())
-	{   Expression *e;
-
-	    switch (t1->ty)
-	    {
-		case Timaginary32: t2 = Type::tfloat32; break;
-		case Timaginary64: t2 = Type::tfloat64; break;
-		case Timaginary80: t2 = Type::tfloat80; break;
-		default:
-		    assert(0);
-	    }
-	    e2 = e2->castTo(sc, t2);
-	    e = new AssignExp(loc, e1, e2);
-	    e->type = t1;
-	    return e;
-	}
-    }
-
-    if (e2->type->iscomplex() && !type->iscomplex())
-	error("Cannot assign %s to %s", e2->type->toChars(), type->toChars());
-
-    return this;
-}
-
-/************************************************************/
-
-ModAssignExp::ModAssignExp(Loc loc, Expression *e1, Expression *e2)
-	: BinExp(loc, TOKmodass, sizeof(ModAssignExp), e1, e2)
-{
-}
-
-Expression *ModAssignExp::semantic(Scope *sc)
-{
-    return commonSemanticAssign(sc);
-}
-
-/************************************************************/
-
-ShlAssignExp::ShlAssignExp(Loc loc, Expression *e1, Expression *e2)
-	: BinExp(loc, TOKshlass, sizeof(ShlAssignExp), e1, e2)
-{
-}
-
-Expression *ShlAssignExp::semantic(Scope *sc)
-{   Expression *e;
-
-    //printf("ShlAssignExp::semantic()\n");
-    BinExp::semantic(sc);
-    e2 = resolveProperties(sc, e2);
-
-    e = op_overload(sc);
-    if (e)
-	return e;
-
-    e1 = e1->modifiableLvalue(sc, e1);
-    e1->checkScalar();
-    e1->checkNoBool();
-    type = e1->type;
-    typeCombine(sc);
-    e1->checkIntegral();
-    e2 = e2->checkIntegral();
-    //e2 = e2->castTo(sc, Type::tshiftcnt);
-    e2 = e2->castTo(sc, e1->type); // LDC
-    return this;
-}
-
-/************************************************************/
-
-ShrAssignExp::ShrAssignExp(Loc loc, Expression *e1, Expression *e2)
-	: BinExp(loc, TOKshrass, sizeof(ShrAssignExp), e1, e2)
-{
-}
-
-Expression *ShrAssignExp::semantic(Scope *sc)
-{   Expression *e;
-
-    BinExp::semantic(sc);
-    e2 = resolveProperties(sc, e2);
-
-    e = op_overload(sc);
-    if (e)
-	return e;
-
-    e1 = e1->modifiableLvalue(sc, e1);
-    e1->checkScalar();
-    e1->checkNoBool();
-    type = e1->type;
-    typeCombine(sc);
-    e1->checkIntegral();
-    e2 = e2->checkIntegral();
-    //e2 = e2->castTo(sc, Type::tshiftcnt);
-    e2 = e2->castTo(sc, e1->type); // LDC
-    return this;
-}
-
-/************************************************************/
-
-UshrAssignExp::UshrAssignExp(Loc loc, Expression *e1, Expression *e2)
-	: BinExp(loc, TOKushrass, sizeof(UshrAssignExp), e1, e2)
-{
-}
-
-Expression *UshrAssignExp::semantic(Scope *sc)
-{   Expression *e;
-
-    BinExp::semantic(sc);
-    e2 = resolveProperties(sc, e2);
-
-    e = op_overload(sc);
-    if (e)
-	return e;
-
-    e1 = e1->modifiableLvalue(sc, e1);
-    e1->checkScalar();
-    e1->checkNoBool();
-    type = e1->type;
-    typeCombine(sc);
-    e1->checkIntegral();
-    e2 = e2->checkIntegral();
-    //e2 = e2->castTo(sc, Type::tshiftcnt);
-    e2 = e2->castTo(sc, e1->type); // LDC
-    return this;
-}
-
-/************************************************************/
-
-AndAssignExp::AndAssignExp(Loc loc, Expression *e1, Expression *e2)
-	: BinExp(loc, TOKandass, sizeof(AndAssignExp), e1, e2)
-{
-}
-
-Expression *AndAssignExp::semantic(Scope *sc)
-{
-    return commonSemanticAssignIntegral(sc);
-}
-
-/************************************************************/
-
-OrAssignExp::OrAssignExp(Loc loc, Expression *e1, Expression *e2)
-	: BinExp(loc, TOKorass, sizeof(OrAssignExp), e1, e2)
-{
-}
-
-Expression *OrAssignExp::semantic(Scope *sc)
-{
-    return commonSemanticAssignIntegral(sc);
-}
-
-/************************************************************/
-
-XorAssignExp::XorAssignExp(Loc loc, Expression *e1, Expression *e2)
-	: BinExp(loc, TOKxorass, sizeof(XorAssignExp), e1, e2)
-{
-}
-
-Expression *XorAssignExp::semantic(Scope *sc)
-{
-    return commonSemanticAssignIntegral(sc);
-}
-
-/************************* AddExp *****************************/
-
-AddExp::AddExp(Loc loc, Expression *e1, Expression *e2)
-	: BinExp(loc, TOKadd, sizeof(AddExp), e1, e2)
-{
-}
-
-Expression *AddExp::semantic(Scope *sc)
-{   Expression *e;
-
-#if LOGSEMANTIC
-    printf("AddExp::semantic('%s')\n", toChars());
-#endif
-    if (!type)
-    {
-	BinExp::semanticp(sc);
-
-	e = op_overload(sc);
-	if (e)
-	    return e;
-
-	Type *tb1 = e1->type->toBasetype();
-	Type *tb2 = e2->type->toBasetype();
-
-        if ((tb1->ty == Tarray || tb1->ty == Tsarray) &&
-            (tb2->ty == Tarray || tb2->ty == Tsarray) &&
-            tb1->nextOf()->equals(tb2->nextOf())
-           )
-        {
-            type = e1->type;
-            e = this;
-        }
-	else if (tb1->ty == Tpointer && e2->type->isintegral() ||
-	    tb2->ty == Tpointer && e1->type->isintegral())
-	    e = scaleFactor(sc);
-	else if (tb1->ty == Tpointer && tb2->ty == Tpointer)
-	{
-	    incompatibleTypes();
-	    type = e1->type;
-	    e = this;
-	}
-	else
-	{
-	    typeCombine(sc);
-	    if ((e1->type->isreal() && e2->type->isimaginary()) ||
-		(e1->type->isimaginary() && e2->type->isreal()))
-	    {
-		switch (type->toBasetype()->ty)
-		{
-		    case Tfloat32:
-		    case Timaginary32:
-			type = Type::tcomplex32;
-			break;
-
-		    case Tfloat64:
-		    case Timaginary64:
-			type = Type::tcomplex64;
-			break;
-
-		    case Tfloat80:
-		    case Timaginary80:
-			type = Type::tcomplex80;
-			break;
-
-		    default:
-			assert(0);
-		}
-	    }
-	    e = this;
-	}
-	return e;
-    }
-    return this;
-}
-
-/************************************************************/
-
-MinExp::MinExp(Loc loc, Expression *e1, Expression *e2)
-	: BinExp(loc, TOKmin, sizeof(MinExp), e1, e2)
-{
-}
-
-Expression *MinExp::semantic(Scope *sc)
-{   Expression *e;
-    Type *t1;
-    Type *t2;
-
-#if LOGSEMANTIC
-    printf("MinExp::semantic('%s')\n", toChars());
-#endif
-    if (type)
-	return this;
-
-    BinExp::semanticp(sc);
-
-    e = op_overload(sc);
-    if (e)
-	return e;
-
-    e = this;
-    t1 = e1->type->toBasetype();
-    t2 = e2->type->toBasetype();
-    if (t1->ty == Tpointer)
-    {
-	if (t2->ty == Tpointer)
-	{   // Need to divide the result by the stride
-	    // Replace (ptr - ptr) with (ptr - ptr) / stride
-	    d_int64 stride;
-	    Expression *e;
-
-	    typeCombine(sc);		// make sure pointer types are compatible
-	    type = Type::tptrdiff_t;
-	    stride = t2->nextOf()->size();
-	    if (stride == 0)
-	    {
-		e = new IntegerExp(loc, 0, Type::tptrdiff_t);
-	    }
-	    else
-	    {
-		e = new DivExp(loc, this, new IntegerExp(0, stride, Type::tptrdiff_t));
-		e->type = Type::tptrdiff_t;
-	    }
-	    return e;
-	}
-	else if (t2->isintegral())
-	    e = scaleFactor(sc);
-	else
-	{   error("incompatible types for minus");
-	    return new IntegerExp(0);
-	}
-    }
-    else if (t2->ty == Tpointer)
-    {
-	type = e2->type;
-	error("can't subtract pointer from %s", e1->type->toChars());
-	return new IntegerExp(0);
-    }
-    else
-    {
-	typeCombine(sc);
-	t1 = e1->type->toBasetype();
-	t2 = e2->type->toBasetype();
-	if ((t1->isreal() && t2->isimaginary()) ||
-	    (t1->isimaginary() && t2->isreal()))
-	{
-	    switch (type->ty)
-	    {
-		case Tfloat32:
-		case Timaginary32:
-		    type = Type::tcomplex32;
-		    break;
-
-		case Tfloat64:
-		case Timaginary64:
-		    type = Type::tcomplex64;
-		    break;
-
-		case Tfloat80:
-		case Timaginary80:
-		    type = Type::tcomplex80;
-		    break;
-
-		default:
-		    assert(0);
-	    }
-	}
-    }
-    return e;
-}
-
-/************************* CatExp *****************************/
-
-CatExp::CatExp(Loc loc, Expression *e1, Expression *e2)
-	: BinExp(loc, TOKcat, sizeof(CatExp), e1, e2)
-{
-}
-
-Expression *CatExp::semantic(Scope *sc)
-{   Expression *e;
-
-    //printf("CatExp::semantic() %s\n", toChars());
-    if (!type)
-    {
-	BinExp::semanticp(sc);
-	e = op_overload(sc);
-	if (e)
-	    return e;
-
-	Type *tb1 = e1->type->toBasetype();
-	Type *tb2 = e2->type->toBasetype();
-
-
-	/* BUG: Should handle things like:
-	 *	char c;
-	 *	c ~ ' '
-	 *	' ' ~ c;
-	 */
-
-#if 0
-	e1->type->print();
-	e2->type->print();
-#endif
-	if ((tb1->ty == Tsarray || tb1->ty == Tarray) &&
-	    e2->type->implicitConvTo(tb1->nextOf()) >= MATCHconst)
-	{
-	    type = tb1->nextOf()->arrayOf();
-	    if (tb2->ty == Tarray)
-	    {	// Make e2 into [e2]
-		e2 = new ArrayLiteralExp(e2->loc, e2);
-		e2->type = type;
-	    }
-	    return this;
-	}
-	else if ((tb2->ty == Tsarray || tb2->ty == Tarray) &&
-	    e1->type->implicitConvTo(tb2->nextOf()) >= MATCHconst)
-	{
-	    type = tb2->nextOf()->arrayOf();
-	    if (tb1->ty == Tarray)
-	    {	// Make e1 into [e1]
-		e1 = new ArrayLiteralExp(e1->loc, e1);
-		e1->type = type;
-	    }
-	    return this;
-	}
-
-	if ((tb1->ty == Tsarray || tb1->ty == Tarray) &&
-	    (tb2->ty == Tsarray || tb2->ty == Tarray) &&
-	    (tb1->nextOf()->mod || tb2->nextOf()->mod) &&
-	    (tb1->nextOf()->mod != tb2->nextOf()->mod)
-	   )
-	{
-	    Type *t1 = tb1->nextOf()->mutableOf()->constOf()->arrayOf();
-	    Type *t2 = tb2->nextOf()->mutableOf()->constOf()->arrayOf();
-	    if (e1->op == TOKstring && !((StringExp *)e1)->committed)
-		e1->type = t1;
-	    else
-		e1 = e1->castTo(sc, t1);
-	    if (e2->op == TOKstring && !((StringExp *)e2)->committed)
-		e2->type = t2;
-	    else
-		e2 = e2->castTo(sc, t2);
-	}
-
-	typeCombine(sc);
-	type = type->toHeadMutable();
-
-	Type *tb = type->toBasetype();
-	if (tb->ty == Tsarray)
-	    type = tb->nextOf()->arrayOf();
-	if (type->ty == Tarray && tb1->nextOf() && tb2->nextOf() &&
-	    tb1->nextOf()->mod != tb2->nextOf()->mod)
-	{
-	    type = type->nextOf()->toHeadMutable()->arrayOf();
-	}
-#if 0
-	e1->type->print();
-	e2->type->print();
-	type->print();
-	print();
-#endif
-	Type *t1 = e1->type->toBasetype();
-	Type *t2 = e2->type->toBasetype();
-	if (e1->op == TOKstring && e2->op == TOKstring)
-	    e = optimize(WANTvalue);
-	else if ((t1->ty == Tarray || t1->ty == Tsarray) &&
-		 (t2->ty == Tarray || t2->ty == Tsarray))
-	{
-	    e = this;
-	}
-	else
-	{
-	    //printf("(%s) ~ (%s)\n", e1->toChars(), e2->toChars());
-	    error("Can only concatenate arrays, not (%s ~ %s)",
-		e1->type->toChars(), e2->type->toChars());
-	    type = Type::tint32;
-	    e = this;
-	}
-	e->type = e->type->semantic(loc, sc);
-	return e;
-    }
-    return this;
-}
-
-/************************************************************/
-
-MulExp::MulExp(Loc loc, Expression *e1, Expression *e2)
-	: BinExp(loc, TOKmul, sizeof(MulExp), e1, e2)
-{
-}
-
-Expression *MulExp::semantic(Scope *sc)
-{   Expression *e;
-
-#if 0
-    printf("MulExp::semantic() %s\n", toChars());
-#endif
-    if (type)
-    {
-	return this;
-    }
-
-    BinExp::semanticp(sc);
-    e = op_overload(sc);
-    if (e)
-	return e;
-
-    typeCombine(sc);
-    if (e1->op != TOKslice && e2->op != TOKslice)
-    {	e1->checkArithmetic();
-	e2->checkArithmetic();
-    }
-    if (type->isfloating())
-    {	Type *t1 = e1->type;
-	Type *t2 = e2->type;
-
-	if (t1->isreal())
-	{
-	    type = t2;
-	}
-	else if (t2->isreal())
-	{
-	    type = t1;
-	}
-	else if (t1->isimaginary())
-	{
-	    if (t2->isimaginary())
-	    {	Expression *e;
-
-		switch (t1->ty)
-		{
-		    case Timaginary32:	type = Type::tfloat32;	break;
-		    case Timaginary64:	type = Type::tfloat64;	break;
-		    case Timaginary80:	type = Type::tfloat80;	break;
-		    default:		assert(0);
-		}
-
-		// iy * iv = -yv
-		e1->type = type;
-		e2->type = type;
-		e = new NegExp(loc, this);
-		e = e->semantic(sc);
-		return e;
-	    }
-	    else
-		type = t2;	// t2 is complex
-	}
-	else if (t2->isimaginary())
-	{
-	    type = t1;	// t1 is complex
-	}
-    }
-    return this;
-}
-
-/************************************************************/
-
-DivExp::DivExp(Loc loc, Expression *e1, Expression *e2)
-	: BinExp(loc, TOKdiv, sizeof(DivExp), e1, e2)
-{
-}
-
-Expression *DivExp::semantic(Scope *sc)
-{   Expression *e;
-
-    if (type)
-	return this;
-
-    BinExp::semanticp(sc);
-    e = op_overload(sc);
-    if (e)
-	return e;
-
-    typeCombine(sc);
-    if (e1->op != TOKslice && e2->op != TOKslice)
-    {	e1->checkArithmetic();
-	e2->checkArithmetic();
-    }
-    if (type->isfloating())
-    {	Type *t1 = e1->type;
-	Type *t2 = e2->type;
-
-	if (t1->isreal())
-	{
-	    type = t2;
-	    if (t2->isimaginary())
-	    {	Expression *e;
-
-		// x/iv = i(-x/v)
-		e2->type = t1;
-		e = new NegExp(loc, this);
-		e = e->semantic(sc);
-		return e;
-	    }
-	}
-	else if (t2->isreal())
-	{
-	    type = t1;
-	}
-	else if (t1->isimaginary())
-	{
-	    if (t2->isimaginary())
-	    {
-		switch (t1->ty)
-		{
-		    case Timaginary32:	type = Type::tfloat32;	break;
-		    case Timaginary64:	type = Type::tfloat64;	break;
-		    case Timaginary80:	type = Type::tfloat80;	break;
-		    default:		assert(0);
-		}
-	    }
-	    else
-		type = t2;	// t2 is complex
-	}
-	else if (t2->isimaginary())
-	{
-	    type = t1;	// t1 is complex
-	}
-    }
-    return this;
-}
-
-/************************************************************/
-
-ModExp::ModExp(Loc loc, Expression *e1, Expression *e2)
-	: BinExp(loc, TOKmod, sizeof(ModExp), e1, e2)
-{
-}
-
-Expression *ModExp::semantic(Scope *sc)
-{   Expression *e;
-
-    if (type)
-	return this;
-
-    BinExp::semanticp(sc);
-    e = op_overload(sc);
-    if (e)
-	return e;
-
-    typeCombine(sc);
-    if (e1->op != TOKslice && e2->op != TOKslice)
-    {	e1->checkArithmetic();
-	e2->checkArithmetic();
-    }
-    if (type->isfloating())
-    {	type = e1->type;
-	if (e2->type->iscomplex())
-	{   error("cannot perform modulo complex arithmetic");
-	    return new IntegerExp(0);
-	}
-    }
-    return this;
-}
-
-/************************************************************/
-
-ShlExp::ShlExp(Loc loc, Expression *e1, Expression *e2)
-	: BinExp(loc, TOKshl, sizeof(ShlExp), e1, e2)
-{
-}
-
-Expression *ShlExp::semantic(Scope *sc)
-{   Expression *e;
-
-    //printf("ShlExp::semantic(), type = %p\n", type);
-    if (!type)
-    {	BinExp::semanticp(sc);
-	e = op_overload(sc);
-	if (e)
-	    return e;
-	e1 = e1->checkIntegral();
-	e2 = e2->checkIntegral();
-	e1 = e1->integralPromotions(sc);
-	//e2 = e2->castTo(sc, Type::tshiftcnt);
-    e2 = e2->castTo(sc, e1->type); // LDC
-	type = e1->type;
-    }
-    return this;
-}
-
-/************************************************************/
-
-ShrExp::ShrExp(Loc loc, Expression *e1, Expression *e2)
-	: BinExp(loc, TOKshr, sizeof(ShrExp), e1, e2)
-{
-}
-
-Expression *ShrExp::semantic(Scope *sc)
-{   Expression *e;
-
-    if (!type)
-    {	BinExp::semanticp(sc);
-	e = op_overload(sc);
-	if (e)
-	    return e;
-	e1 = e1->checkIntegral();
-	e2 = e2->checkIntegral();
-	e1 = e1->integralPromotions(sc);
-	//e2 = e2->castTo(sc, Type::tshiftcnt);
-    e2 = e2->castTo(sc, e1->type); // LDC
-	type = e1->type;
-    }
-    return this;
-}
-
-/************************************************************/
-
-UshrExp::UshrExp(Loc loc, Expression *e1, Expression *e2)
-	: BinExp(loc, TOKushr, sizeof(UshrExp), e1, e2)
-{
-}
-
-Expression *UshrExp::semantic(Scope *sc)
-{   Expression *e;
-
-    if (!type)
-    {	BinExp::semanticp(sc);
-	e = op_overload(sc);
-	if (e)
-	    return e;
-	e1 = e1->checkIntegral();
-	e2 = e2->checkIntegral();
-	e1 = e1->integralPromotions(sc);
-	//e2 = e2->castTo(sc, Type::tshiftcnt);
-    e2 = e2->castTo(sc, e1->type); // LDC
-	type = e1->type;
-    }
-    return this;
-}
-
-/************************************************************/
-
-AndExp::AndExp(Loc loc, Expression *e1, Expression *e2)
-	: BinExp(loc, TOKand, sizeof(AndExp), e1, e2)
-{
-}
-
-Expression *AndExp::semantic(Scope *sc)
-{   Expression *e;
-
-    if (!type)
-    {	BinExp::semanticp(sc);
-	e = op_overload(sc);
-	if (e)
-	    return e;
-	if (e1->type->toBasetype()->ty == Tbool &&
-	    e2->type->toBasetype()->ty == Tbool)
-	{
-	    type = e1->type;
-	    e = this;
-	}
-	else
-	{
-	    typeCombine(sc);
-	    if (e1->op != TOKslice && e2->op != TOKslice)
-	    {   e1->checkIntegral();
-		e2->checkIntegral();
-	    }
-	}
-    }
-    return this;
-}
-
-/************************************************************/
-
-OrExp::OrExp(Loc loc, Expression *e1, Expression *e2)
-	: BinExp(loc, TOKor, sizeof(OrExp), e1, e2)
-{
-}
-
-Expression *OrExp::semantic(Scope *sc)
-{   Expression *e;
-
-    if (!type)
-    {	BinExp::semanticp(sc);
-	e = op_overload(sc);
-	if (e)
-	    return e;
-	if (e1->type->toBasetype()->ty == Tbool &&
-	    e2->type->toBasetype()->ty == Tbool)
-	{
-	    type = e1->type;
-	    e = this;
-	}
-	else
-	{
-	    typeCombine(sc);
-	    if (e1->op != TOKslice && e2->op != TOKslice)
-	    {   e1->checkIntegral();
-		e2->checkIntegral();
-	    }
-	}
-    }
-    return this;
-}
-
-/************************************************************/
-
-XorExp::XorExp(Loc loc, Expression *e1, Expression *e2)
-	: BinExp(loc, TOKxor, sizeof(XorExp), e1, e2)
-{
-}
-
-Expression *XorExp::semantic(Scope *sc)
-{   Expression *e;
-
-    if (!type)
-    {	BinExp::semanticp(sc);
-	e = op_overload(sc);
-	if (e)
-	    return e;
-	if (e1->type->toBasetype()->ty == Tbool &&
-	    e2->type->toBasetype()->ty == Tbool)
-	{
-	    type = e1->type;
-	    e = this;
-	}
-	else
-	{
-	    typeCombine(sc);
-	    if (e1->op != TOKslice && e2->op != TOKslice)
-	    {   e1->checkIntegral();
-		e2->checkIntegral();
-	    }
-	}
-    }
-    return this;
-}
-
-
-/************************************************************/
-
-OrOrExp::OrOrExp(Loc loc, Expression *e1, Expression *e2)
-	: BinExp(loc, TOKoror, sizeof(OrOrExp), e1, e2)
-{
-}
-
-Expression *OrOrExp::semantic(Scope *sc)
-{
-    unsigned cs1;
-
-    // same as for AndAnd
-    e1 = e1->semantic(sc);
-    e1 = resolveProperties(sc, e1);
-    e1 = e1->checkToPointer();
-    e1 = e1->checkToBoolean();
-    cs1 = sc->callSuper;
-
-    if (sc->flags & SCOPEstaticif)
-    {
-	/* If in static if, don't evaluate e2 if we don't have to.
-	 */
-	e1 = e1->optimize(WANTflags);
-	if (e1->isBool(TRUE))
-	{
-	    return new IntegerExp(loc, 1, Type::tboolean);
-	}
-    }
-
-    e2 = e2->semantic(sc);
-    sc->mergeCallSuper(loc, cs1);
-    e2 = resolveProperties(sc, e2);
-    e2 = e2->checkToPointer();
-
-    type = Type::tboolean;
-    if (e1->type->ty == Tvoid)
-	type = Type::tvoid;
-    if (e2->op == TOKtype || e2->op == TOKimport)
-	error("%s is not an expression", e2->toChars());
-    return this;
-}
-
-Expression *OrOrExp::checkToBoolean()
-{
-    e2 = e2->checkToBoolean();
-    return this;
-}
-
-int OrOrExp::isBit()
-{
-    return TRUE;
-}
-
-int OrOrExp::checkSideEffect(int flag)
-{
-    if (flag == 2)
-    {
-	return e1->checkSideEffect(2) || e2->checkSideEffect(2);
-    }
-    else
-    {	e1->checkSideEffect(1);
-	return e2->checkSideEffect(flag);
-    }
-}
-
-/************************************************************/
-
-AndAndExp::AndAndExp(Loc loc, Expression *e1, Expression *e2)
-	: BinExp(loc, TOKandand, sizeof(AndAndExp), e1, e2)
-{
-}
-
-Expression *AndAndExp::semantic(Scope *sc)
-{
-    unsigned cs1;
-
-    // same as for OrOr
-    e1 = e1->semantic(sc);
-    e1 = resolveProperties(sc, e1);
-    e1 = e1->checkToPointer();
-    e1 = e1->checkToBoolean();
-    cs1 = sc->callSuper;
-
-    if (sc->flags & SCOPEstaticif)
-    {
-	/* If in static if, don't evaluate e2 if we don't have to.
-	 */
-	e1 = e1->optimize(WANTflags);
-	if (e1->isBool(FALSE))
-	{
-	    return new IntegerExp(loc, 0, Type::tboolean);
-	}
-    }
-
-    e2 = e2->semantic(sc);
-    sc->mergeCallSuper(loc, cs1);
-    e2 = resolveProperties(sc, e2);
-    e2 = e2->checkToPointer();
-
-    type = Type::tboolean;
-    if (e1->type->ty == Tvoid)
-	type = Type::tvoid;
-    if (e2->op == TOKtype || e2->op == TOKimport)
-	error("%s is not an expression", e2->toChars());
-    return this;
-}
-
-Expression *AndAndExp::checkToBoolean()
-{
-    e2 = e2->checkToBoolean();
-    return this;
-}
-
-int AndAndExp::isBit()
-{
-    return TRUE;
-}
-
-int AndAndExp::checkSideEffect(int flag)
-{
-    if (flag == 2)
-    {
-	return e1->checkSideEffect(2) || e2->checkSideEffect(2);
-    }
-    else
-    {
-	e1->checkSideEffect(1);
-	return e2->checkSideEffect(flag);
-    }
-}
-
-/************************************************************/
-
-InExp::InExp(Loc loc, Expression *e1, Expression *e2)
-	: BinExp(loc, TOKin, sizeof(InExp), e1, e2)
-{
-}
-
-Expression *InExp::semantic(Scope *sc)
-{   Expression *e;
-
-    if (type)
-	return this;
-
-    BinExp::semanticp(sc);
-    e = op_overload(sc);
-    if (e)
-	return e;
-
-    //type = Type::tboolean;
-    Type *t2b = e2->type->toBasetype();
-    if (t2b->ty != Taarray)
-    {
-	error("rvalue of in expression must be an associative array, not %s", e2->type->toChars());
-	type = Type::terror;
-    }
-    else
-    {
-	TypeAArray *ta = (TypeAArray *)t2b;
-
-	// Convert key to type of key
-	e1 = e1->implicitCastTo(sc, ta->index);
-
-	// Return type is pointer to value
-	type = ta->nextOf()->pointerTo();
-    }
-    return this;
-}
-
-int InExp::isBit()
-{
-    return FALSE;
-}
-
-
-/************************************************************/
-
-/* This deletes the key e1 from the associative array e2
- */
-
-RemoveExp::RemoveExp(Loc loc, Expression *e1, Expression *e2)
-	: BinExp(loc, TOKremove, sizeof(RemoveExp), e1, e2)
-{
-    type = Type::tvoid;
-}
-
-/************************************************************/
-
-CmpExp::CmpExp(enum TOK op, Loc loc, Expression *e1, Expression *e2)
-	: BinExp(loc, op, sizeof(CmpExp), e1, e2)
-{
-}
-
-Expression *CmpExp::semantic(Scope *sc)
-{   Expression *e;
-    Type *t1;
-    Type *t2;
-
-#if LOGSEMANTIC
-    printf("CmpExp::semantic('%s')\n", toChars());
-#endif
-    if (type)
-	return this;
-
-    BinExp::semanticp(sc);
-
-    if (e1->type->toBasetype()->ty == Tclass && e2->op == TOKnull ||
-	e2->type->toBasetype()->ty == Tclass && e1->op == TOKnull)
-    {
-	error("do not use null when comparing class types");
-    }
-
-    e = op_overload(sc);
-    if (e)
-    {
-	e = new CmpExp(op, loc, e, new IntegerExp(loc, 0, Type::tint32));
-	e = e->semantic(sc);
-	return e;
-    }
-
-    typeCombine(sc);
-    type = Type::tboolean;
-
-    // Special handling for array comparisons
-    t1 = e1->type->toBasetype();
-    t2 = e2->type->toBasetype();
-    if ((t1->ty == Tarray || t1->ty == Tsarray || t1->ty == Tpointer) &&
-	(t2->ty == Tarray || t2->ty == Tsarray || t2->ty == Tpointer))
-    {
-	if (t1->nextOf()->implicitConvTo(t2->nextOf()) < MATCHconst &&
-	    t2->nextOf()->implicitConvTo(t1->nextOf()) < MATCHconst &&
-	    (t1->nextOf()->ty != Tvoid && t2->nextOf()->ty != Tvoid))
-	    error("array comparison type mismatch, %s vs %s", t1->nextOf()->toChars(), t2->nextOf()->toChars());
-	e = this;
-    }
-    else if (t1->ty == Tstruct || t2->ty == Tstruct ||
-	     (t1->ty == Tclass && t2->ty == Tclass))
-    {
-	if (t2->ty == Tstruct)
-	    error("need member function opCmp() for %s %s to compare", t2->toDsymbol(sc)->kind(), t2->toChars());
-	else
-	    error("need member function opCmp() for %s %s to compare", t1->toDsymbol(sc)->kind(), t1->toChars());
-	e = this;
-    }
-#if 1
-    else if (t1->iscomplex() || t2->iscomplex())
-    {
-	error("compare not defined for complex operands");
-	e = new IntegerExp(0);
-    }
-#endif
-    else
-	e = this;
-    //printf("CmpExp: %s\n", e->toChars());
-    return e;
-}
-
-int CmpExp::isBit()
-{
-    return TRUE;
-}
-
-
-/************************************************************/
-
-EqualExp::EqualExp(enum TOK op, Loc loc, Expression *e1, Expression *e2)
-	: BinExp(loc, op, sizeof(EqualExp), e1, e2)
-{
-    assert(op == TOKequal || op == TOKnotequal);
-}
-
-Expression *EqualExp::semantic(Scope *sc)
-{   Expression *e;
-    Type *t1;
-    Type *t2;
-
-    //printf("EqualExp::semantic('%s')\n", toChars());
-    if (type)
-	return this;
-
-    BinExp::semanticp(sc);
-
-    /* Before checking for operator overloading, check to see if we're
-     * comparing the addresses of two statics. If so, we can just see
-     * if they are the same symbol.
-     */
-    if (e1->op == TOKaddress && e2->op == TOKaddress)
-    {	AddrExp *ae1 = (AddrExp *)e1;
-	AddrExp *ae2 = (AddrExp *)e2;
-
-	if (ae1->e1->op == TOKvar && ae2->e1->op == TOKvar)
-	{   VarExp *ve1 = (VarExp *)ae1->e1;
-	    VarExp *ve2 = (VarExp *)ae2->e1;
-
-	    if (ve1->var == ve2->var /*|| ve1->var->toSymbol() == ve2->var->toSymbol()*/)
-	    {
-		// They are the same, result is 'true' for ==, 'false' for !=
-		e = new IntegerExp(loc, (op == TOKequal), Type::tboolean);
-		return e;
-	    }
-	}
-    }
-
-    if (e1->type->toBasetype()->ty == Tclass && e2->op == TOKnull ||
-	e2->type->toBasetype()->ty == Tclass && e1->op == TOKnull)
-    {
-	error("use '%s' instead of '%s' when comparing with null",
-		Token::toChars(op == TOKequal ? TOKidentity : TOKnotidentity),
-		Token::toChars(op));
-    }
-
-    //if (e2->op != TOKnull)
-    {
-	e = op_overload(sc);
-	if (e)
-	{
-	    if (op == TOKnotequal)
-	    {
-		e = new NotExp(e->loc, e);
-		e = e->semantic(sc);
-	    }
-	    return e;
-	}
-    }
-
-    e = typeCombine(sc);
-    type = Type::tboolean;
-
-    // Special handling for array comparisons
-    t1 = e1->type->toBasetype();
-    t2 = e2->type->toBasetype();
-
-    if ((t1->ty == Tarray || t1->ty == Tsarray || t1->ty == Tpointer) &&
-	(t2->ty == Tarray || t2->ty == Tsarray || t2->ty == Tpointer))
-    {
-	if (t1->nextOf()->implicitConvTo(t2->nextOf()) < MATCHconst &&
-	    t2->nextOf()->implicitConvTo(t1->nextOf()) < MATCHconst &&
-	    (t1->nextOf()->ty != Tvoid && t2->nextOf()->ty != Tvoid))
-	    error("array equality comparison type mismatch, %s vs %s", t1->toChars(), t2->toChars());
-    }
-    else
-    {
-	if (e1->type != e2->type && e1->type->isfloating() && e2->type->isfloating())
-	{
-	    // Cast both to complex
-	    e1 = e1->castTo(sc, Type::tcomplex80);
-	    e2 = e2->castTo(sc, Type::tcomplex80);
-	}
-    }
-    return e;
-}
-
-int EqualExp::isBit()
-{
-    return TRUE;
-}
-
-
-
-/************************************************************/
-
-IdentityExp::IdentityExp(enum TOK op, Loc loc, Expression *e1, Expression *e2)
-	: BinExp(loc, op, sizeof(IdentityExp), e1, e2)
-{
-}
-
-Expression *IdentityExp::semantic(Scope *sc)
-{
-    if (type)
-	return this;
-
-    BinExp::semanticp(sc);
-    type = Type::tboolean;
-    typeCombine(sc);
-    if (e1->type != e2->type && e1->type->isfloating() && e2->type->isfloating())
-    {
-	// Cast both to complex
-	e1 = e1->castTo(sc, Type::tcomplex80);
-	e2 = e2->castTo(sc, Type::tcomplex80);
-    }
-    return this;
-}
-
-int IdentityExp::isBit()
-{
-    return TRUE;
-}
-
-
-/****************************************************************/
-
-CondExp::CondExp(Loc loc, Expression *econd, Expression *e1, Expression *e2)
-	: BinExp(loc, TOKquestion, sizeof(CondExp), e1, e2)
-{
-    this->econd = econd;
-}
-
-Expression *CondExp::syntaxCopy()
-{
-    return new CondExp(loc, econd->syntaxCopy(), e1->syntaxCopy(), e2->syntaxCopy());
-}
-
-
-Expression *CondExp::semantic(Scope *sc)
-{   Type *t1;
-    Type *t2;
-    unsigned cs0;
-    unsigned cs1;
-
-#if LOGSEMANTIC
-    printf("CondExp::semantic('%s')\n", toChars());
-#endif
-    if (type)
-	return this;
-
-    econd = econd->semantic(sc);
-    econd = resolveProperties(sc, econd);
-    econd = econd->checkToPointer();
-    econd = econd->checkToBoolean();
-
-#if 0	/* this cannot work right because the types of e1 and e2
- 	 * both contribute to the type of the result.
-	 */
-    if (sc->flags & SCOPEstaticif)
-    {
-	/* If in static if, don't evaluate what we don't have to.
-	 */
-	econd = econd->optimize(WANTflags);
-	if (econd->isBool(TRUE))
-	{
-	    e1 = e1->semantic(sc);
-	    e1 = resolveProperties(sc, e1);
-	    return e1;
-	}
-	else if (econd->isBool(FALSE))
-	{
-	    e2 = e2->semantic(sc);
-	    e2 = resolveProperties(sc, e2);
-	    return e2;
-	}
-    }
-#endif
-
-
-    cs0 = sc->callSuper;
-    e1 = e1->semantic(sc);
-    e1 = resolveProperties(sc, e1);
-    cs1 = sc->callSuper;
-    sc->callSuper = cs0;
-    e2 = e2->semantic(sc);
-    e2 = resolveProperties(sc, e2);
-    sc->mergeCallSuper(loc, cs1);
-
-
-    // If either operand is void, the result is void
-    t1 = e1->type;
-    t2 = e2->type;
-    if (t1->ty == Tvoid || t2->ty == Tvoid)
-	type = Type::tvoid;
-    else if (t1 == t2)
-	type = t1;
-    else
-    {
-	typeCombine(sc);
-	switch (e1->type->toBasetype()->ty)
-	{
-	    case Tcomplex32:
-	    case Tcomplex64:
-	    case Tcomplex80:
-		e2 = e2->castTo(sc, e1->type);
-		break;
-	}
-	switch (e2->type->toBasetype()->ty)
-	{
-	    case Tcomplex32:
-	    case Tcomplex64:
-	    case Tcomplex80:
-		e1 = e1->castTo(sc, e2->type);
-		break;
-	}
-	if (type->toBasetype()->ty == Tarray)
-	{
-	    e1 = e1->castTo(sc, type);
-	    e2 = e2->castTo(sc, type);
-	}
-    }
-#if 0
-    printf("res: %s\n", type->toChars());
-    printf("e1 : %s\n", e1->type->toChars());
-    printf("e2 : %s\n", e2->type->toChars());
-#endif
-    return this;
-}
-
-int CondExp::isLvalue()
-{
-    return e1->isLvalue() && e2->isLvalue();
-}
-
-Expression *CondExp::toLvalue(Scope *sc, Expression *ex)
-{
-    PtrExp *e;
-
-    // convert (econd ? e1 : e2) to *(econd ? &e1 : &e2)
-    e = new PtrExp(loc, this, type);
-
-    e1 = e1->addressOf(sc);
-    //e1 = e1->toLvalue(sc, NULL);
-
-    e2 = e2->addressOf(sc);
-    //e2 = e2->toLvalue(sc, NULL);
-
-    typeCombine(sc);
-
-    type = e2->type;
-    return e;
-}
-
-Expression *CondExp::modifiableLvalue(Scope *sc, Expression *e)
-{
-    error("conditional expression %s is not a modifiable lvalue", toChars());
-    return this;
-}
-
-void CondExp::checkEscape()
-{
-    e1->checkEscape();
-    e2->checkEscape();
-}
-
-
-Expression *CondExp::checkToBoolean()
-{
-    e1 = e1->checkToBoolean();
-    e2 = e2->checkToBoolean();
-    return this;
-}
-
-int CondExp::checkSideEffect(int flag)
-{
-    if (flag == 2)
-    {
-	return econd->checkSideEffect(2) ||
-		e1->checkSideEffect(2) ||
-		e2->checkSideEffect(2);
-    }
-    else
-    {
-	econd->checkSideEffect(1);
-	e1->checkSideEffect(flag);
-	return e2->checkSideEffect(flag);
-    }
-}
-
-int CondExp::canThrow()
-{
-    return econd->canThrow() || e1->canThrow() || e2->canThrow();
-}
-
-
-void CondExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{
-    expToCBuffer(buf, hgs, econd, PREC_oror);
-    buf->writestring(" ? ");
-    expToCBuffer(buf, hgs, e1, PREC_expr);
-    buf->writestring(" : ");
-    expToCBuffer(buf, hgs, e2, PREC_cond);
-}
-
-
-/****************************************************************/
-
-DefaultInitExp::DefaultInitExp(Loc loc, enum TOK subop, int size)
-    : Expression(loc, TOKdefault, size)
-{
-    this->subop = subop;
-}
-
-void DefaultInitExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{
-    buf->writestring(Token::toChars(subop));
-}
-
-/****************************************************************/
-
-FileInitExp::FileInitExp(Loc loc)
-    : DefaultInitExp(loc, TOKfile, sizeof(FileInitExp))
-{
-}
-
-Expression *FileInitExp::semantic(Scope *sc)
-{
-    //printf("FileInitExp::semantic()\n");
-    type = Type::tchar->invariantOf()->arrayOf();
-    return this;
-}
-
-Expression *FileInitExp::resolve(Loc loc, Scope *sc)
-{
-    //printf("FileInitExp::resolve() %s\n", toChars());
-    char *s = loc.filename ? loc.filename : sc->module->ident->toChars();
-    Expression *e = new StringExp(loc, s);
-    e = e->semantic(sc);
-    e = e->castTo(sc, type);
-    return e;
-}
-
-/****************************************************************/
-
-LineInitExp::LineInitExp(Loc loc)
-    : DefaultInitExp(loc, TOKline, sizeof(LineInitExp))
-{
-}
-
-Expression *LineInitExp::semantic(Scope *sc)
-{
-    type = Type::tint32;
-    return this;
-}
-
-Expression *LineInitExp::resolve(Loc loc, Scope *sc)
-{
-    Expression *e = new IntegerExp(loc, loc.linnum, Type::tint32);
-    e = e->castTo(sc, type);
-    return e;
-}
-
-/****************************************************************/
-/****************************************************************/
-/****************************************************************/
-
-#if IN_LLVM
-
-// Strictly LDC specific stuff
-
-GEPExp::GEPExp(Loc loc, Expression* e, Identifier* id, unsigned idx)
-    : UnaExp(loc, TOKgep, sizeof(GEPExp), e)
-{
-    index = idx;
-    ident = id;
-}
-
-void GEPExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{
-    expToCBuffer(buf, hgs, e1, PREC_primary);
-    buf->writeByte('.');
-    buf->writestring(ident->toChars());
-}
-
-Expression* GEPExp::toLvalue(Scope* sc, Expression* e)
-{
-    // GEP's are always lvalues, at least in the "LLVM sense" ...
-    return this;
-}
-
-#endif
-
-/****************************************************************/
-/****************************************************************/
-/****************************************************************/
+
+// Compiler implementation of the D programming language
+// Copyright (c) 1999-2009 by Digital Mars
+// All Rights Reserved
+// written by Walter Bright
+// http://www.digitalmars.com
+// License for redistribution is by either the Artistic License
+// in artistic.txt, or the GNU General Public License in gnu.txt.
+// See the included readme.txt for details.
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <math.h>
+#include <assert.h>
+#if _MSC_VER
+#include <complex>
+#else
+#if IN_DMD
+#include <complex.h>
+#endif
+#endif
+
+#if _WIN32 && __DMC__
+extern "C" char * __cdecl __locale_decpoint;
+#endif
+
+#if __MINGW32__
+#ifndef isnan
+#define isnan _isnan
+#endif
+#endif
+
+#ifdef __APPLE__
+#ifndef isnan
+int isnan(double);
+#endif
+#endif
+
+#include "rmem.h"
+#if IN_DMD
+#include "port.h"
+#endif
+#include "mtype.h"
+#include "init.h"
+#include "expression.h"
+#include "template.h"
+#include "utf.h"
+#include "enum.h"
+#include "scope.h"
+#include "statement.h"
+#include "declaration.h"
+#include "aggregate.h"
+#include "import.h"
+#include "id.h"
+#include "dsymbol.h"
+#include "module.h"
+#include "attrib.h"
+#include "hdrgen.h"
+#include "parse.h"
+
+#if IN_DMD
+Expression *createTypeInfoArray(Scope *sc, Expression *args[], int dim);
+#endif
+Expression *expandVar(int result, VarDeclaration *v);
+
+#define LOGSEMANTIC	0
+
+/**********************************
+ * Set operator precedence for each operator.
+ */
+
+// Operator precedence - greater values are higher precedence
+
+enum PREC
+{
+    PREC_zero,
+    PREC_expr,
+    PREC_assign,
+    PREC_cond,
+    PREC_oror,
+    PREC_andand,
+    PREC_or,
+    PREC_xor,
+    PREC_and,
+    PREC_equal,
+    PREC_rel,
+    PREC_shift,
+    PREC_add,
+    PREC_mul,
+    PREC_unary,
+    PREC_primary,
+};
+
+enum PREC precedence[TOKMAX];
+
+void initPrecedence()
+{
+    precedence[TOKdotvar] = PREC_primary;
+    precedence[TOKimport] = PREC_primary;
+    precedence[TOKidentifier] = PREC_primary;
+    precedence[TOKthis] = PREC_primary;
+    precedence[TOKsuper] = PREC_primary;
+    precedence[TOKint64] = PREC_primary;
+    precedence[TOKfloat64] = PREC_primary;
+    precedence[TOKnull] = PREC_primary;
+    precedence[TOKstring] = PREC_primary;
+    precedence[TOKarrayliteral] = PREC_primary;
+    precedence[TOKtypeid] = PREC_primary;
+    precedence[TOKis] = PREC_primary;
+    precedence[TOKassert] = PREC_primary;
+    precedence[TOKfunction] = PREC_primary;
+    precedence[TOKvar] = PREC_primary;
+#if DMDV2
+    precedence[TOKdefault] = PREC_primary;
+#endif
+
+    // post
+    precedence[TOKdotti] = PREC_primary;
+    precedence[TOKdot] = PREC_primary;
+//  precedence[TOKarrow] = PREC_primary;
+    precedence[TOKplusplus] = PREC_primary;
+    precedence[TOKminusminus] = PREC_primary;
+    precedence[TOKcall] = PREC_primary;
+    precedence[TOKslice] = PREC_primary;
+    precedence[TOKarray] = PREC_primary;
+
+    precedence[TOKaddress] = PREC_unary;
+    precedence[TOKstar] = PREC_unary;
+    precedence[TOKneg] = PREC_unary;
+    precedence[TOKuadd] = PREC_unary;
+    precedence[TOKnot] = PREC_unary;
+    precedence[TOKtobool] = PREC_add;
+    precedence[TOKtilde] = PREC_unary;
+    precedence[TOKdelete] = PREC_unary;
+    precedence[TOKnew] = PREC_unary;
+    precedence[TOKcast] = PREC_unary;
+
+    precedence[TOKmul] = PREC_mul;
+    precedence[TOKdiv] = PREC_mul;
+    precedence[TOKmod] = PREC_mul;
+
+    precedence[TOKadd] = PREC_add;
+    precedence[TOKmin] = PREC_add;
+    precedence[TOKcat] = PREC_add;
+
+    precedence[TOKshl] = PREC_shift;
+    precedence[TOKshr] = PREC_shift;
+    precedence[TOKushr] = PREC_shift;
+
+    precedence[TOKlt] = PREC_rel;
+    precedence[TOKle] = PREC_rel;
+    precedence[TOKgt] = PREC_rel;
+    precedence[TOKge] = PREC_rel;
+    precedence[TOKunord] = PREC_rel;
+    precedence[TOKlg] = PREC_rel;
+    precedence[TOKleg] = PREC_rel;
+    precedence[TOKule] = PREC_rel;
+    precedence[TOKul] = PREC_rel;
+    precedence[TOKuge] = PREC_rel;
+    precedence[TOKug] = PREC_rel;
+    precedence[TOKue] = PREC_rel;
+    precedence[TOKin] = PREC_rel;
+
+#if 0
+    precedence[TOKequal] = PREC_equal;
+    precedence[TOKnotequal] = PREC_equal;
+    precedence[TOKidentity] = PREC_equal;
+    precedence[TOKnotidentity] = PREC_equal;
+#else
+    /* Note that we changed precedence, so that < and != have the same
+     * precedence. This change is in the parser, too.
+     */
+    precedence[TOKequal] = PREC_rel;
+    precedence[TOKnotequal] = PREC_rel;
+    precedence[TOKidentity] = PREC_rel;
+    precedence[TOKnotidentity] = PREC_rel;
+#endif
+
+    precedence[TOKand] = PREC_and;
+
+    precedence[TOKxor] = PREC_xor;
+
+    precedence[TOKor] = PREC_or;
+
+    precedence[TOKandand] = PREC_andand;
+
+    precedence[TOKoror] = PREC_oror;
+
+    precedence[TOKquestion] = PREC_cond;
+
+    precedence[TOKassign] = PREC_assign;
+    precedence[TOKconstruct] = PREC_assign;
+    precedence[TOKblit] = PREC_assign;
+    precedence[TOKaddass] = PREC_assign;
+    precedence[TOKminass] = PREC_assign;
+    precedence[TOKcatass] = PREC_assign;
+    precedence[TOKmulass] = PREC_assign;
+    precedence[TOKdivass] = PREC_assign;
+    precedence[TOKmodass] = PREC_assign;
+    precedence[TOKshlass] = PREC_assign;
+    precedence[TOKshrass] = PREC_assign;
+    precedence[TOKushrass] = PREC_assign;
+    precedence[TOKandass] = PREC_assign;
+    precedence[TOKorass] = PREC_assign;
+    precedence[TOKxorass] = PREC_assign;
+
+    precedence[TOKcomma] = PREC_expr;
+}
+
+/*************************************************************
+ * Given var, we need to get the
+ * right 'this' pointer if var is in an outer class, but our
+ * existing 'this' pointer is in an inner class.
+ * Input:
+ *	e1	existing 'this'
+ *	ad	struct or class we need the correct 'this' for
+ *	var	the specific member of ad we're accessing
+ */
+
+Expression *getRightThis(Loc loc, Scope *sc, AggregateDeclaration *ad,
+	Expression *e1, Declaration *var)
+{
+    //printf("\ngetRightThis(e1 = %s, ad = %s, var = %s)\n", e1->toChars(), ad->toChars(), var->toChars());
+ L1:
+    Type *t = e1->type->toBasetype();
+    //printf("e1->type = %s, var->type = %s\n", e1->type->toChars(), var->type->toChars());
+
+    /* If e1 is not the 'this' pointer for ad
+     */
+    if (ad &&
+	!(t->ty == Tpointer && t->nextOf()->ty == Tstruct &&
+	  ((TypeStruct *)t->nextOf())->sym == ad)
+	&&
+	!(t->ty == Tstruct &&
+	  ((TypeStruct *)t)->sym == ad)
+       )
+    {
+	ClassDeclaration *cd = ad->isClassDeclaration();
+	ClassDeclaration *tcd = t->isClassHandle();
+
+	/* e1 is the right this if ad is a base class of e1
+	 */
+	if (!cd || !tcd ||
+	    !(tcd == cd || cd->isBaseOf(tcd, NULL))
+	   )
+	{
+	    /* Only classes can be inner classes with an 'outer'
+	     * member pointing to the enclosing class instance
+	     */
+	    if (tcd && tcd->isNested())
+	    {   /* e1 is the 'this' pointer for an inner class: tcd.
+		 * Rewrite it as the 'this' pointer for the outer class.
+		 */
+
+		e1 = new DotVarExp(loc, e1, tcd->vthis);
+		e1->type = tcd->vthis->type;
+		// Do not call checkNestedRef()
+		//e1 = e1->semantic(sc);
+
+		// Skip up over nested functions, and get the enclosing
+		// class type.
+		int n = 0;
+		Dsymbol *s;
+		for (s = tcd->toParent();
+		     s && s->isFuncDeclaration();
+		     s = s->toParent())
+		{   FuncDeclaration *f = s->isFuncDeclaration();
+		    if (f->vthis)
+		    {
+			//printf("rewriting e1 to %s's this\n", f->toChars());
+			n++;
+
+            // LDC seems dmd misses it sometimes here :/
+            //f->vthis->nestedrefs = 1;
+
+			e1 = new VarExp(loc, f->vthis);
+		    }
+		}
+		if (s && s->isClassDeclaration())
+		{   e1->type = s->isClassDeclaration()->type;
+		    if (n > 1)
+			e1 = e1->semantic(sc);
+		}
+		else
+		    e1 = e1->semantic(sc);
+		goto L1;
+	    }
+	    /* Can't find a path from e1 to ad
+	     */
+	    e1->error("this for %s needs to be type %s not type %s",
+		var->toChars(), ad->toChars(), t->toChars());
+	}
+    }
+    return e1;
+}
+
+/*****************************************
+ * Determine if 'this' is available.
+ * If it is, return the FuncDeclaration that has it.
+ */
+
+FuncDeclaration *hasThis(Scope *sc)
+{   FuncDeclaration *fd;
+    FuncDeclaration *fdthis;
+
+    //printf("hasThis()\n");
+    fdthis = sc->parent->isFuncDeclaration();
+    //printf("fdthis = %p, '%s'\n", fdthis, fdthis ? fdthis->toChars() : "");
+
+    // Go upwards until we find the enclosing member function
+    fd = fdthis;
+    while (1)
+    {
+	if (!fd)
+	{
+	    goto Lno;
+	}
+	if (!fd->isNested())
+	    break;
+
+	Dsymbol *parent = fd->parent;
+	while (parent)
+	{
+	    TemplateInstance *ti = parent->isTemplateInstance();
+	    if (ti)
+		parent = ti->parent;
+	    else
+		break;
+	}
+
+	fd = fd->parent->isFuncDeclaration();
+    }
+
+    if (!fd->isThis())
+    {   //printf("test '%s'\n", fd->toChars());
+	goto Lno;
+    }
+
+    assert(fd->vthis);
+    return fd;
+
+Lno:
+    return NULL;		// don't have 'this' available
+}
+
+
+/***************************************
+ * Pull out any properties.
+ */
+
+Expression *resolveProperties(Scope *sc, Expression *e)
+{
+    //printf("resolveProperties(%s)\n", e->toChars());
+    if (e->type)
+    {
+	Type *t = e->type->toBasetype();
+
+	if (t->ty == Tfunction || e->op == TOKoverloadset)
+	{
+	    e = new CallExp(e->loc, e);
+	    e = e->semantic(sc);
+	}
+
+	/* Look for e being a lazy parameter; rewrite as delegate call
+	 */
+	else if (e->op == TOKvar)
+	{   VarExp *ve = (VarExp *)e;
+
+	    if (ve->var->storage_class & STClazy)
+	    {
+		e = new CallExp(e->loc, e);
+		e = e->semantic(sc);
+	    }
+	}
+
+	else if (e->op == TOKdotexp)
+	{
+	    e->error("expression has no value");
+	}
+
+    }
+    return e;
+}
+
+/******************************
+ * Perform semantic() on an array of Expressions.
+ */
+
+void arrayExpressionSemantic(Expressions *exps, Scope *sc)
+{
+    if (exps)
+    {
+	for (size_t i = 0; i < exps->dim; i++)
+	{   Expression *e = (Expression *)exps->data[i];
+
+	    e = e->semantic(sc);
+	    exps->data[i] = (void *)e;
+	}
+    }
+}
+
+
+/******************************
+ * Perform canThrow() on an array of Expressions.
+ */
+
+#if DMDV2
+int arrayExpressionCanThrow(Expressions *exps)
+{
+    if (exps)
+    {
+	for (size_t i = 0; i < exps->dim; i++)
+	{   Expression *e = (Expression *)exps->data[i];
+	    if (e && e->canThrow())
+		return 1;
+	}
+    }
+    return 0;
+}
+#endif
+
+/****************************************
+ * Expand tuples.
+ */
+
+void expandTuples(Expressions *exps)
+{
+    //printf("expandTuples()\n");
+    if (exps)
+    {
+	for (size_t i = 0; i < exps->dim; i++)
+	{   Expression *arg = (Expression *)exps->data[i];
+	    if (!arg)
+		continue;
+
+	    // Look for tuple with 0 members
+	    if (arg->op == TOKtype)
+	    {	TypeExp *e = (TypeExp *)arg;
+		if (e->type->toBasetype()->ty == Ttuple)
+		{   TypeTuple *tt = (TypeTuple *)e->type->toBasetype();
+
+		    if (!tt->arguments || tt->arguments->dim == 0)
+		    {
+			exps->remove(i);
+			if (i == exps->dim)
+			    return;
+			i--;
+			continue;
+		    }
+		}
+	    }
+
+	    // Inline expand all the tuples
+	    while (arg->op == TOKtuple)
+	    {	TupleExp *te = (TupleExp *)arg;
+
+		exps->remove(i);		// remove arg
+		exps->insert(i, te->exps);	// replace with tuple contents
+		if (i == exps->dim)
+		    return;		// empty tuple, no more arguments
+		arg = (Expression *)exps->data[i];
+	    }
+	}
+    }
+}
+
+/****************************************
+ * Preprocess arguments to function.
+ */
+
+void preFunctionArguments(Loc loc, Scope *sc, Expressions *exps)
+{
+    if (exps)
+    {
+	expandTuples(exps);
+
+	for (size_t i = 0; i < exps->dim; i++)
+	{   Expression *arg = (Expression *)exps->data[i];
+
+	    if (!arg->type)
+	    {
+#ifdef DEBUG
+		if (!global.gag)
+		    printf("1: \n");
+#endif
+		arg->error("%s is not an expression", arg->toChars());
+		arg = new IntegerExp(arg->loc, 0, Type::tint32);
+	    }
+
+	    arg = resolveProperties(sc, arg);
+	    exps->data[i] = (void *) arg;
+
+	    //arg->rvalue();
+#if 0
+	    if (arg->type->ty == Tfunction)
+	    {
+		arg = new AddrExp(arg->loc, arg);
+		arg = arg->semantic(sc);
+		exps->data[i] = (void *) arg;
+	    }
+#endif
+	}
+    }
+}
+
+/*********************************************
+ * Call copy constructor for struct value argument.
+ */
+#if DMDV2
+Expression *callCpCtor(Loc loc, Scope *sc, Expression *e)
+{
+    Type *tb = e->type->toBasetype();
+    assert(tb->ty == Tstruct);
+    StructDeclaration *sd = ((TypeStruct *)tb)->sym;
+    if (sd->cpctor)
+    {
+	/* Create a variable tmp, and replace the argument e with:
+	 *	(tmp = e),tmp
+	 * and let AssignExp() handle the construction.
+	 * This is not the most efficent, ideally tmp would be constructed
+	 * directly onto the stack.
+	 */
+	Identifier *idtmp = Lexer::uniqueId("__tmp");
+	VarDeclaration *tmp = new VarDeclaration(loc, tb, idtmp, new ExpInitializer(0, e));
+	Expression *ae = new DeclarationExp(loc, tmp);
+	e = new CommaExp(loc, ae, new VarExp(loc, tmp));
+	e = e->semantic(sc);
+    }
+    return e;
+}
+#endif
+
+/****************************************
+ * Now that we know the exact type of the function we're calling,
+ * the arguments[] need to be adjusted:
+ *	1. implicitly convert argument to the corresponding parameter type
+ *	2. add default arguments for any missing arguments
+ *	3. do default promotions on arguments corresponding to ...
+ *	4. add hidden _arguments[] argument
+ *	5. call copy constructor for struct value arguments
+ */
+
+void functionArguments(Loc loc, Scope *sc, TypeFunction *tf, Expressions *arguments)
+{
+    unsigned n;
+
+    //printf("functionArguments()\n");
+    assert(arguments);
+    size_t nargs = arguments ? arguments->dim : 0;
+    size_t nparams = Argument::dim(tf->parameters);
+
+    if (nargs > nparams && tf->varargs == 0)
+	error(loc, "expected %zu arguments, not %zu for non-variadic function type %s", nparams, nargs, tf->toChars());
+
+    n = (nargs > nparams) ? nargs : nparams;	// n = max(nargs, nparams)
+
+    int done = 0;
+    for (size_t i = 0; i < n; i++)
+    {
+	Expression *arg;
+
+	if (i < nargs)
+	    arg = (Expression *)arguments->data[i];
+	else
+	    arg = NULL;
+	Type *tb;
+
+	if (i < nparams)
+	{
+	    Argument *p = Argument::getNth(tf->parameters, i);
+
+	    if (!arg)
+	    {
+		if (!p->defaultArg)
+		{
+		    if (tf->varargs == 2 && i + 1 == nparams)
+			goto L2;
+		    error(loc, "expected %zu function arguments, not %zu", nparams, nargs);
+		    break;
+		}
+		arg = p->defaultArg;
+#if DMDV2
+		if (arg->op == TOKdefault)
+		{   DefaultInitExp *de = (DefaultInitExp *)arg;
+		    arg = de->resolve(loc, sc);
+		}
+		else
+#endif
+		    arg = arg->copy();
+		arguments->push(arg);
+		nargs++;
+	    }
+
+	    if (tf->varargs == 2 && i + 1 == nparams)
+	    {
+		//printf("\t\tvarargs == 2, p->type = '%s'\n", p->type->toChars());
+		if (arg->implicitConvTo(p->type))
+		{
+		    if (nargs != nparams)
+		        error(loc, "expected %zu function arguments, not %zu", nparams, nargs);
+		    goto L1;
+		}
+	     L2:
+		Type *tb = p->type->toBasetype();
+		Type *tret = p->isLazyArray();
+		switch (tb->ty)
+		{
+		    case Tsarray:
+		    case Tarray:
+		    {	// Create a static array variable v of type arg->type
+#ifdef IN_GCC
+			/* GCC 4.0 does not like zero length arrays used like
+			   this; pass a null array value instead. Could also
+			   just make a one-element array. */
+			if (nargs - i == 0)
+			{
+			    arg = new NullExp(loc);
+			    break;
+			}
+#endif
+			Identifier *id = Lexer::uniqueId("__arrayArg");
+			Type *t = new TypeSArray(((TypeArray *)tb)->next, new IntegerExp(nargs - i));
+			t = t->semantic(loc, sc);
+			VarDeclaration *v = new VarDeclaration(loc, t, id, new VoidInitializer(loc));
+			v->semantic(sc);
+			v->parent = sc->parent;
+			//sc->insert(v);
+
+			Expression *c = new DeclarationExp(0, v);
+			c->type = v->type;
+
+			for (size_t u = i; u < nargs; u++)
+			{   Expression *a = (Expression *)arguments->data[u];
+			    if (tret && !((TypeArray *)tb)->next->equals(a->type))
+				a = a->toDelegate(sc, tret);
+
+			    Expression *e = new VarExp(loc, v);
+			    e = new IndexExp(loc, e, new IntegerExp(u + 1 - nparams));
+			    AssignExp *ae = new AssignExp(loc, e, a);
+#if DMDV2
+			    ae->op = TOKconstruct;
+#endif
+			    if (c)
+				c = new CommaExp(loc, c, ae);
+			    else
+				c = ae;
+			}
+			arg = new VarExp(loc, v);
+			if (c)
+			    arg = new CommaExp(loc, c, arg);
+			break;
+		    }
+		    case Tclass:
+		    {	/* Set arg to be:
+			 *	new Tclass(arg0, arg1, ..., argn)
+			 */
+			Expressions *args = new Expressions();
+			args->setDim(nargs - i);
+			for (size_t u = i; u < nargs; u++)
+			    args->data[u - i] = arguments->data[u];
+			arg = new NewExp(loc, NULL, NULL, p->type, args);
+			break;
+		    }
+		    default:
+			if (!arg)
+			{   error(loc, "not enough arguments");
+			    return;
+		        }
+			break;
+		}
+		arg = arg->semantic(sc);
+		//printf("\targ = '%s'\n", arg->toChars());
+		arguments->setDim(i + 1);
+		done = 1;
+	    }
+
+	L1:
+	    if (!(p->storageClass & STClazy && p->type->ty == Tvoid))
+	    {
+		if (p->type != arg->type)
+		{
+		    //printf("arg->type = %s, p->type = %s\n", arg->type->toChars(), p->type->toChars());
+		    arg = arg->implicitCastTo(sc, p->type);
+		    arg = arg->optimize(WANTvalue);
+		}
+	    }
+	    if (p->storageClass & STCref)
+	    {
+		arg = arg->toLvalue(sc, arg);
+	    }
+	    else if (p->storageClass & STCout)
+	    {
+		arg = arg->modifiableLvalue(sc, arg);
+	    }
+
+// LDC we don't want this!
+#if !IN_LLVM
+	    // Convert static arrays to pointers
+	    tb = arg->type->toBasetype();
+	    if (tb->ty == Tsarray)
+	    {
+		arg = arg->checkToPointer();
+	    }
+#endif
+#if DMDV2
+	    if (tb->ty == Tstruct && !(p->storageClass & (STCref | STCout)))
+	    {
+		arg = callCpCtor(loc, sc, arg);
+	    }
+#endif
+
+	    // Convert lazy argument to a delegate
+	    if (p->storageClass & STClazy)
+	    {
+		arg = arg->toDelegate(sc, p->type);
+	    }
+#if DMDV2
+	    /* Look for arguments that cannot 'escape' from the called
+	     * function.
+	     */
+	    if (!tf->parameterEscapes(p))
+	    {
+		/* Function literals can only appear once, so if this
+		 * appearance was scoped, there cannot be any others.
+		 */
+		if (arg->op == TOKfunction)
+		{   FuncExp *fe = (FuncExp *)arg;
+		    fe->fd->tookAddressOf = 0;
+		}
+
+		/* For passing a delegate to a scoped parameter,
+		 * this doesn't count as taking the address of it.
+		 * We only worry about 'escaping' references to the function.
+		 */
+		else if (arg->op == TOKdelegate)
+		{   DelegateExp *de = (DelegateExp *)arg;
+		    if (de->e1->op == TOKvar)
+		    {	VarExp *ve = (VarExp *)de->e1;
+			FuncDeclaration *f = ve->var->isFuncDeclaration();
+			if (f)
+			{   f->tookAddressOf--;
+			    //printf("tookAddressOf = %d\n", f->tookAddressOf);
+			}
+		    }
+		}
+	    }
+#endif
+	}
+	else
+	{
+
+	    // If not D linkage, do promotions
+        // LDC: don't do promotions on intrinsics
+	    if (tf->linkage != LINKd && tf->linkage != LINKintrinsic)
+	    {
+		// Promote bytes, words, etc., to ints
+		arg = arg->integralPromotions(sc);
+
+		// Promote floats to doubles
+		switch (arg->type->ty)
+		{
+		    case Tfloat32:
+			arg = arg->castTo(sc, Type::tfloat64);
+			break;
+
+		    case Timaginary32:
+			arg = arg->castTo(sc, Type::timaginary64);
+			break;
+		}
+	    }
+
+	    // Convert static arrays to dynamic arrays
+	    tb = arg->type->toBasetype();
+	    if (tb->ty == Tsarray)
+	    {	TypeSArray *ts = (TypeSArray *)tb;
+		Type *ta = ts->next->arrayOf();
+		if (ts->size(arg->loc) == 0)
+		{   arg = new NullExp(arg->loc);
+		    arg->type = ta;
+		}
+		else
+		    arg = arg->castTo(sc, ta);
+	    }
+#if DMDV2
+	    if (tb->ty == Tstruct)
+	    {
+		arg = callCpCtor(loc, sc, arg);
+	    }
+
+	    // Give error for overloaded function addresses
+	    if (arg->op == TOKsymoff)
+	    {	SymOffExp *se = (SymOffExp *)arg;
+		if (se->hasOverloads && !se->var->isFuncDeclaration()->isUnique())
+		    arg->error("function %s is overloaded", arg->toChars());
+	    }
+#endif
+	    arg->rvalue();
+	}
+	arg = arg->optimize(WANTvalue);
+	arguments->data[i] = (void *) arg;
+	if (done)
+	    break;
+    }
+
+#if !IN_LLVM
+    // If D linkage and variadic, add _arguments[] as first argument
+    if (tf->linkage == LINKd && tf->varargs == 1)
+    {
+	Expression *e;
+
+	e = createTypeInfoArray(sc, (Expression **)&arguments->data[nparams],
+		arguments->dim - nparams);
+	arguments->insert(0, e);
+    }
+#endif
+}
+
+/**************************************************
+ * Write expression out to buf, but wrap it
+ * in ( ) if its precedence is less than pr.
+ */
+
+void expToCBuffer(OutBuffer *buf, HdrGenState *hgs, Expression *e, enum PREC pr)
+{
+    //if (precedence[e->op] == 0) e->dump(0);
+    if (precedence[e->op] < pr ||
+	/* Despite precedence, we don't allow a<b<c expressions.
+	 * They must be parenthesized.
+	 */
+	(pr == PREC_rel && precedence[e->op] == pr))
+    {
+	buf->writeByte('(');
+	e->toCBuffer(buf, hgs);
+	buf->writeByte(')');
+    }
+    else
+	e->toCBuffer(buf, hgs);
+}
+
+/**************************************************
+ * Write out argument list to buf.
+ */
+
+void argsToCBuffer(OutBuffer *buf, Expressions *arguments, HdrGenState *hgs)
+{
+    if (arguments)
+    {
+	for (size_t i = 0; i < arguments->dim; i++)
+	{   Expression *arg = (Expression *)arguments->data[i];
+
+	    if (arg)
+	    {	if (i)
+		    buf->writeByte(',');
+		expToCBuffer(buf, hgs, arg, PREC_assign);
+	    }
+	}
+    }
+}
+
+/**************************************************
+ * Write out argument types to buf.
+ */
+
+void argExpTypesToCBuffer(OutBuffer *buf, Expressions *arguments, HdrGenState *hgs)
+{
+    if (arguments)
+    {	OutBuffer argbuf;
+
+	for (size_t i = 0; i < arguments->dim; i++)
+	{   Expression *arg = (Expression *)arguments->data[i];
+
+	    if (i)
+		buf->writeByte(',');
+	    argbuf.reset();
+	    arg->type->toCBuffer2(&argbuf, hgs, 0);
+	    buf->write(&argbuf);
+	}
+    }
+}
+
+/******************************** Expression **************************/
+
+Expression::Expression(Loc loc, enum TOK op, int size)
+    : loc(loc)
+{
+    //printf("Expression::Expression(op = %d) this = %p\n", op, this);
+    this->loc = loc;
+    this->op = op;
+    this->size = size;
+    type = NULL;
+}
+
+Expression *Expression::syntaxCopy()
+{
+    //printf("Expression::syntaxCopy()\n");
+    //dump(0);
+    return copy();
+}
+
+/*********************************
+ * Does *not* do a deep copy.
+ */
+
+Expression *Expression::copy()
+{
+    Expression *e;
+    if (!size)
+    {
+#ifdef DEBUG
+	fprintf(stdmsg, "No expression copy for: %s\n", toChars());
+	printf("op = %d\n", op);
+	dump(0);
+#endif
+	assert(0);
+    }
+    e = (Expression *)mem.malloc(size);
+    //printf("Expression::copy(op = %d) e = %p\n", op, e);
+    return (Expression *)memcpy(e, this, size);
+}
+
+/**************************
+ * Semantically analyze Expression.
+ * Determine types, fold constants, etc.
+ */
+
+Expression *Expression::semantic(Scope *sc)
+{
+#if LOGSEMANTIC
+    printf("Expression::semantic() %s\n", toChars());
+#endif
+    if (type)
+	type = type->semantic(loc, sc);
+    else
+	type = Type::tvoid;
+    return this;
+}
+
+/**********************************
+ * Try to run semantic routines.
+ * If they fail, return NULL.
+ */
+
+Expression *Expression::trySemantic(Scope *sc)
+{
+    unsigned errors = global.errors;
+    global.gag++;
+    Expression *e = semantic(sc);
+    global.gag--;
+    if (errors != global.errors)
+    {
+	global.errors = errors;
+	e = NULL;
+    }
+    return e;
+}
+
+void Expression::print()
+{
+    fprintf(stdmsg, "%s\n", toChars());
+    fflush(stdmsg);
+}
+
+char *Expression::toChars()
+{   OutBuffer *buf;
+    HdrGenState hgs;
+
+    memset(&hgs, 0, sizeof(hgs));
+    buf = new OutBuffer();
+    toCBuffer(buf, &hgs);
+    return buf->toChars();
+}
+
+void Expression::error(const char *format, ...)
+{
+    va_list ap;
+    va_start(ap, format);
+    ::verror(loc, format, ap);
+    va_end( ap );
+}
+
+void Expression::warning(const char *format, ...)
+{
+    if (global.params.warnings && !global.gag)
+    {
+	va_list ap;
+	va_start(ap, format);
+	::vwarning(loc, format, ap);
+	va_end( ap );
+    }
+}
+
+void Expression::rvalue()
+{
+    if (type && type->toBasetype()->ty == Tvoid)
+    {	error("expression %s is void and has no value", toChars());
+#if 0
+	dump(0);
+	halt();
+#endif
+	type = Type::tint32;
+    }
+}
+
+Expression *Expression::combine(Expression *e1, Expression *e2)
+{
+    if (e1)
+    {
+	if (e2)
+	{
+	    e1 = new CommaExp(e1->loc, e1, e2);
+	    e1->type = e2->type;
+	}
+    }
+    else
+	e1 = e2;
+    return e1;
+}
+
+dinteger_t Expression::toInteger()
+{
+    //printf("Expression %s\n", Token::toChars(op));
+    error("Integer constant expression expected instead of %s", toChars());
+    return 0;
+}
+
+uinteger_t Expression::toUInteger()
+{
+    //printf("Expression %s\n", Token::toChars(op));
+    return (uinteger_t)toInteger();
+}
+
+real_t Expression::toReal()
+{
+    error("Floating point constant expression expected instead of %s", toChars());
+    return 0;
+}
+
+real_t Expression::toImaginary()
+{
+    error("Floating point constant expression expected instead of %s", toChars());
+    return 0;
+}
+
+complex_t Expression::toComplex()
+{
+    error("Floating point constant expression expected instead of %s", toChars());
+#ifdef IN_GCC
+    return complex_t(real_t(0)); // %% nicer
+#else
+    return 0;
+#endif
+}
+
+void Expression::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    buf->writestring(Token::toChars(op));
+}
+
+void Expression::toMangleBuffer(OutBuffer *buf)
+{
+    error("expression %s is not a valid template value argument", toChars());
+}
+
+/***************************************
+ * Return !=0 if expression is an lvalue.
+ */
+#if DMDV2
+int Expression::isLvalue()
+{
+    return 0;
+}
+#endif
+
+/*******************************
+ * Give error if we're not an lvalue.
+ * If we can, convert expression to be an lvalue.
+ */
+
+Expression *Expression::toLvalue(Scope *sc, Expression *e)
+{
+    if (!e)
+	e = this;
+    else if (!loc.filename)
+	loc = e->loc;
+    error("%s is not an lvalue", e->toChars());
+    return this;
+}
+
+Expression *Expression::modifiableLvalue(Scope *sc, Expression *e)
+{
+    //printf("Expression::modifiableLvalue() %s, type = %s\n", toChars(), type->toChars());
+
+    // See if this expression is a modifiable lvalue (i.e. not const)
+#if DMDV2
+    if (type && (!type->isMutable() || !type->isAssignable()))
+	error("%s is not mutable", e->toChars());
+#endif
+    return toLvalue(sc, e);
+}
+
+/************************************
+ * Detect cases where pointers to the stack can 'escape' the
+ * lifetime of the stack frame.
+ */
+
+void Expression::checkEscape()
+{
+}
+
+void Expression::checkScalar()
+{
+    if (!type->isscalar())
+	error("'%s' is not a scalar, it is a %s", toChars(), type->toChars());
+}
+
+void Expression::checkNoBool()
+{
+    if (type->toBasetype()->ty == Tbool)
+	error("operation not allowed on bool '%s'", toChars());
+}
+
+Expression *Expression::checkIntegral()
+{
+    if (!type->isintegral())
+    {	error("'%s' is not of integral type, it is a %s", toChars(), type->toChars());
+	return new ErrorExp();
+    }
+    return this;
+}
+
+Expression *Expression::checkArithmetic()
+{
+    if (!type->isintegral() && !type->isfloating())
+    {	error("'%s' is not of arithmetic type, it is a %s", toChars(), type->toChars());
+	return new ErrorExp();
+    }
+    return this;
+}
+
+void Expression::checkDeprecated(Scope *sc, Dsymbol *s)
+{
+    s->checkDeprecated(loc, sc);
+}
+
+#if DMDV2
+void Expression::checkPurity(Scope *sc, FuncDeclaration *f)
+{
+#if 1
+    if (sc->func)
+    {
+	FuncDeclaration *outerfunc=sc->func;
+	while (outerfunc->toParent2() && outerfunc->toParent2()->isFuncDeclaration())
+	{
+	    outerfunc = outerfunc->toParent2()->isFuncDeclaration();
+	}
+	if (outerfunc->isPure()  && !sc->intypeof && (!f->isNested() && !f->isPure()))
+	    error("pure function '%s' cannot call impure function '%s'\n",
+		sc->func->toChars(), f->toChars());
+    }
+#else
+    if (sc->func && sc->func->isPure() && !sc->intypeof && !f->isPure())
+	error("pure function '%s' cannot call impure function '%s'\n",
+	    sc->func->toChars(), f->toChars());
+#endif
+}
+#endif
+
+/********************************
+ * Check for expressions that have no use.
+ * Input:
+ *	flag	0 not going to use the result, so issue error message if no
+ *		  side effects
+ *		1 the result of the expression is used, but still check
+ *		  for useless subexpressions
+ *		2 do not issue error messages, just return !=0 if expression
+ *		  has side effects
+ */
+
+int Expression::checkSideEffect(int flag)
+{
+    if (flag == 0)
+    {	if (op == TOKimport)
+	{
+	    error("%s has no effect", toChars());
+	}
+	else
+	    error("%s has no effect in expression (%s)",
+		Token::toChars(op), toChars());
+    }
+    return 0;
+}
+
+/*****************************
+ * Check that expression can be tested for true or false.
+ */
+
+Expression *Expression::checkToBoolean()
+{
+    // Default is 'yes' - do nothing
+
+#ifdef DEBUG
+    if (!type)
+	dump(0);
+#endif
+
+    if (!type->checkBoolean())
+    {
+	error("expression %s of type %s does not have a boolean value", toChars(), type->toChars());
+    }
+    return this;
+}
+
+/****************************
+ */
+
+Expression *Expression::checkToPointer()
+{
+    Expression *e;
+    Type *tb;
+
+    //printf("Expression::checkToPointer()\n");
+    e = this;
+
+    // If C static array, convert to pointer
+    tb = type->toBasetype();
+    if (tb->ty == Tsarray)
+    {	TypeSArray *ts = (TypeSArray *)tb;
+	if (ts->size(loc) == 0)
+	    e = new NullExp(loc);
+	else
+	    e = new AddrExp(loc, this);
+	e->type = ts->next->pointerTo();
+    }
+    return e;
+}
+
+/******************************
+ * Take address of expression.
+ */
+
+Expression *Expression::addressOf(Scope *sc)
+{
+    Expression *e;
+
+    //printf("Expression::addressOf()\n");
+    e = toLvalue(sc, NULL);
+    e = new AddrExp(loc, e);
+    e->type = type->pointerTo();
+    return e;
+}
+
+/******************************
+ * If this is a reference, dereference it.
+ */
+
+Expression *Expression::deref()
+{
+    //printf("Expression::deref()\n");
+    if (type->ty == Treference)
+    {	Expression *e;
+
+	e = new PtrExp(loc, this);
+	e->type = ((TypeReference *)type)->next;
+	return e;
+    }
+    return this;
+}
+
+/********************************
+ * Does this expression statically evaluate to a boolean TRUE or FALSE?
+ */
+
+int Expression::isBool(int result)
+{
+    return FALSE;
+}
+
+/********************************
+ * Does this expression result in either a 1 or a 0?
+ */
+
+int Expression::isBit()
+{
+    return FALSE;
+}
+
+/********************************
+ * Can this expression throw an exception?
+ * Valid only after semantic() pass.
+ */
+
+int Expression::canThrow()
+{
+#if DMDV2
+    return FALSE;
+#else
+    return TRUE;
+#endif
+}
+
+
+
+Expressions *Expression::arraySyntaxCopy(Expressions *exps)
+{   Expressions *a = NULL;
+
+    if (exps)
+    {
+	a = new Expressions();
+	a->setDim(exps->dim);
+	for (int i = 0; i < a->dim; i++)
+	{   Expression *e = (Expression *)exps->data[i];
+
+	    e = e->syntaxCopy();
+	    a->data[i] = e;
+	}
+    }
+    return a;
+}
+
+/******************************** IntegerExp **************************/
+
+IntegerExp::IntegerExp(Loc loc, dinteger_t value, Type *type)
+	: Expression(loc, TOKint64, sizeof(IntegerExp))
+{
+    //printf("IntegerExp(value = %lld, type = '%s')\n", value, type ? type->toChars() : "");
+    if (type && !type->isscalar())
+    {
+	//printf("%s, loc = %d\n", toChars(), loc.linnum);
+	error("integral constant must be scalar type, not %s", type->toChars());
+	type = Type::terror;
+    }
+    this->type = type;
+    this->value = value;
+}
+
+IntegerExp::IntegerExp(dinteger_t value)
+	: Expression(0, TOKint64, sizeof(IntegerExp))
+{
+    this->type = Type::tint32;
+    this->value = value;
+}
+
+int IntegerExp::equals(Object *o)
+{   IntegerExp *ne;
+
+    if (this == o ||
+	(((Expression *)o)->op == TOKint64 &&
+	 ((ne = (IntegerExp *)o), type->toHeadMutable()->equals(ne->type->toHeadMutable())) &&
+	 value == ne->value))
+	return 1;
+    return 0;
+}
+
+char *IntegerExp::toChars()
+{
+#if 1
+    return Expression::toChars();
+#else
+    static char buffer[sizeof(value) * 3 + 1];
+
+    sprintf(buffer, "%jd", value);
+    return buffer;
+#endif
+}
+
+dinteger_t IntegerExp::toInteger()
+{   Type *t;
+
+    t = type;
+    while (t)
+    {
+	switch (t->ty)
+	{
+	    case Tbit:
+	    case Tbool:		value = (value != 0);		break;
+	    case Tint8:		value = (d_int8)  value;	break;
+	    case Tchar:
+	    case Tuns8:		value = (d_uns8)  value;	break;
+	    case Tint16:	value = (d_int16) value;	break;
+	    case Twchar:
+	    case Tuns16:	value = (d_uns16) value;	break;
+	    case Tint32:	value = (d_int32) value;	break;
+	    case Tdchar:
+	    case Tuns32:	value = (d_uns32) value;	break;
+	    case Tint64:	value = (d_int64) value;	break;
+	    case Tuns64:	value = (d_uns64) value;	break;
+	    case Tpointer:
+                if (PTRSIZE == 4)
+                    value = (d_uns32) value;
+                else if (PTRSIZE == 8)
+                    value = (d_uns64) value;
+		else
+		    assert(0);
+                break;
+
+	    case Tenum:
+	    {
+		TypeEnum *te = (TypeEnum *)t;
+		t = te->sym->memtype;
+		continue;
+	    }
+
+	    case Ttypedef:
+	    {
+		TypeTypedef *tt = (TypeTypedef *)t;
+		t = tt->sym->basetype;
+		continue;
+	    }
+
+	    default:
+		/* This can happen if errors, such as
+		 * the type is painted on like in fromConstInitializer().
+		 */
+		if (!global.errors)
+		{   type->print();
+		    assert(0);
+		}
+		break;
+	}
+	break;
+    }
+    return value;
+}
+
+real_t IntegerExp::toReal()
+{
+    Type *t;
+
+    toInteger();
+    t = type->toBasetype();
+    if (t->ty == Tuns64)
+	return (real_t)(d_uns64)value;
+    else
+	return (real_t)(d_int64)value;
+}
+
+real_t IntegerExp::toImaginary()
+{
+    return (real_t) 0;
+}
+
+complex_t IntegerExp::toComplex()
+{
+    return toReal();
+}
+
+int IntegerExp::isBool(int result)
+{
+    return result ? value != 0 : value == 0;
+}
+
+Expression *IntegerExp::semantic(Scope *sc)
+{
+    if (!type)
+    {
+	// Determine what the type of this number is
+	dinteger_t number = value;
+
+	if (number & 0x8000000000000000LL)
+	    type = Type::tuns64;
+	else if (number & 0xFFFFFFFF80000000LL)
+	    type = Type::tint64;
+	else
+	    type = Type::tint32;
+    }
+    else
+    {	if (!type->deco)
+	    type = type->semantic(loc, sc);
+    }
+    return this;
+}
+
+Expression *IntegerExp::toLvalue(Scope *sc, Expression *e)
+{
+    if (!e)
+	e = this;
+    else if (!loc.filename)
+	loc = e->loc;
+    e->error("constant %s is not an lvalue", e->toChars());
+    return this;
+}
+
+void IntegerExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    dinteger_t v = toInteger();
+
+    if (type)
+    {	Type *t = type;
+
+      L1:
+	switch (t->ty)
+	{
+	    case Tenum:
+	    {   TypeEnum *te = (TypeEnum *)t;
+		buf->printf("cast(%s)", te->sym->toChars());
+		t = te->sym->memtype;
+		goto L1;
+	    }
+
+	    case Ttypedef:
+	    {	TypeTypedef *tt = (TypeTypedef *)t;
+		buf->printf("cast(%s)", tt->sym->toChars());
+		t = tt->sym->basetype;
+		goto L1;
+	    }
+
+	    case Twchar:	// BUG: need to cast(wchar)
+	    case Tdchar:	// BUG: need to cast(dchar)
+		if ((uinteger_t)v > 0xFF)
+		{
+		     buf->printf("'\\U%08x'", (unsigned)v);
+		     break;
+		}
+	    case Tchar:
+		if (v == '\'')
+		    buf->writestring("'\\''");
+		else if (isprint(v) && v != '\\')
+		    buf->printf("'%c'", (int)v);
+		else
+		    buf->printf("'\\x%02x'", (int)v);
+		break;
+
+	    case Tint8:
+		buf->writestring("cast(byte)");
+		goto L2;
+
+	    case Tint16:
+		buf->writestring("cast(short)");
+		goto L2;
+
+	    case Tint32:
+	    L2:
+		buf->printf("%d", (int)v);
+		break;
+
+	    case Tuns8:
+		buf->writestring("cast(ubyte)");
+		goto L3;
+
+	    case Tuns16:
+		buf->writestring("cast(ushort)");
+		goto L3;
+
+	    case Tuns32:
+	    L3:
+		buf->printf("%du", (unsigned)v);
+		break;
+
+	    case Tint64:
+		buf->printf("%jdL", v);
+		break;
+
+	    case Tuns64:
+	    L4:
+		buf->printf("%juLU", v);
+		break;
+
+	    case Tbit:
+	    case Tbool:
+		buf->writestring((char *)(v ? "true" : "false"));
+		break;
+
+	    case Tpointer:
+		buf->writestring("cast(");
+		buf->writestring(t->toChars());
+		buf->writeByte(')');
+                if (PTRSIZE == 4)
+                    goto L3;
+                else if (PTRSIZE == 8)
+                    goto L4;
+		else
+		    assert(0);
+
+	    default:
+		/* This can happen if errors, such as
+		 * the type is painted on like in fromConstInitializer().
+		 */
+		if (!global.errors)
+		{
+#ifdef DEBUG
+		    t->print();
+#endif
+		    assert(0);
+		}
+		break;
+	}
+    }
+    else if (v & 0x8000000000000000LL)
+	buf->printf("0x%jx", v);
+    else
+	buf->printf("%jd", v);
+}
+
+void IntegerExp::toMangleBuffer(OutBuffer *buf)
+{
+    if ((sinteger_t)value < 0)
+	buf->printf("N%jd", -value);
+    else
+	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)
+	: Expression(loc, TOKfloat64, sizeof(RealExp))
+{
+    //printf("RealExp::RealExp(%Lg)\n", value);
+    this->value = value;
+    this->type = type;
+}
+
+char *RealExp::toChars()
+{
+    char buffer[sizeof(value) * 3 + 8 + 1 + 1];
+
+#ifdef IN_GCC
+    value.format(buffer, sizeof(buffer));
+    if (type->isimaginary())
+	strcat(buffer, "i");
+#else
+    sprintf(buffer, type->isimaginary() ? "%Lgi" : "%Lg", value);
+#endif
+    assert(strlen(buffer) < sizeof(buffer));
+    return mem.strdup(buffer);
+}
+
+dinteger_t RealExp::toInteger()
+{
+#ifdef IN_GCC
+    return toReal().toInt();
+#else
+    return (sinteger_t) toReal();
+#endif
+}
+
+uinteger_t RealExp::toUInteger()
+{
+#ifdef IN_GCC
+    return (uinteger_t) toReal().toInt();
+#else
+    return (uinteger_t) toReal();
+#endif
+}
+
+real_t RealExp::toReal()
+{
+    return type->isreal() ? value : 0;
+}
+
+real_t RealExp::toImaginary()
+{
+    return type->isreal() ? 0 : value;
+}
+
+complex_t RealExp::toComplex()
+{
+#ifdef __DMC__
+    return toReal() + toImaginary() * I;
+#else
+    return complex_t(toReal(), toImaginary());
+#endif
+}
+
+/********************************
+ * Test to see if two reals are the same.
+ * Regard NaN's as equivalent.
+ * Regard +0 and -0 as different.
+ */
+
+int RealEquals(real_t x1, real_t x2)
+{
+//#if 1
+//    return (Port::isNan(x1) && Port::isNan(x2)) ||
+//#elif __APPLE__
+#if __APPLE__
+    return (__inline_isnan(x1) && __inline_isnan(x2)) ||
+#else
+    return // special case nans
+	   (isnan(x1) && isnan(x2)) ||
+#endif
+	   // and zero, in order to distinguish +0 from -0
+	   (x1 == 0 && x2 == 0 && 1./x1 == 1./x2) ||
+	   // otherwise just compare
+	   (x1 != 0. && x1 == x2);
+}
+
+int RealExp::equals(Object *o)
+{   RealExp *ne;
+
+    if (this == o ||
+	(((Expression *)o)->op == TOKfloat64 &&
+	 ((ne = (RealExp *)o), type->toHeadMutable()->equals(ne->type->toHeadMutable())) &&
+	 RealEquals(value, ne->value)
+        )
+       )
+	return 1;
+    return 0;
+}
+
+Expression *RealExp::semantic(Scope *sc)
+{
+    if (!type)
+	type = Type::tfloat64;
+    else
+	type = type->semantic(loc, sc);
+    return this;
+}
+
+int RealExp::isBool(int result)
+{
+#ifdef IN_GCC
+    return result ? (! value.isZero()) : (value.isZero());
+#else
+    return result ? (value != 0)
+		  : (value == 0);
+#endif
+}
+
+void floatToBuffer(OutBuffer *buf, Type *type, real_t value)
+{
+    /* In order to get an exact representation, try converting it
+     * to decimal then back again. If it matches, use it.
+     * If it doesn't, fall back to hex, which is
+     * always exact.
+     */
+    char buffer[25];
+    sprintf(buffer, "%Lg", value);
+    assert(strlen(buffer) < sizeof(buffer));
+#if _WIN32 && __DMC__
+    char *save = __locale_decpoint;
+    __locale_decpoint = ".";
+    real_t r = strtold(buffer, NULL);
+    __locale_decpoint = save;
+#else
+    real_t r = strtold(buffer, NULL);
+#endif
+    if (r == value)			// if exact duplication
+	buf->writestring(buffer);
+    else
+	buf->printf("%La", value);	// ensure exact duplication
+
+    if (type)
+    {
+	Type *t = type->toBasetype();
+	switch (t->ty)
+	{
+	    case Tfloat32:
+	    case Timaginary32:
+	    case Tcomplex32:
+		buf->writeByte('F');
+		break;
+
+	    case Tfloat80:
+	    case Timaginary80:
+	    case Tcomplex80:
+		buf->writeByte('L');
+		break;
+
+	    default:
+		break;
+	}
+	if (t->isimaginary())
+	    buf->writeByte('i');
+    }
+}
+
+void RealExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    floatToBuffer(buf, type, value);
+}
+
+void realToMangleBuffer(OutBuffer *buf, real_t value)
+{
+    /* Rely on %A to get portable mangling.
+     * Must munge result to get only identifier characters.
+     *
+     * Possible values from %A	=> mangled result
+     * NAN			=> NAN
+     * -INF			=> NINF
+     * INF			=> INF
+     * -0X1.1BC18BA997B95P+79	=> N11BC18BA997B95P79
+     * 0X1.9P+2			=> 19P2
+     */
+
+//#if 1
+//    if (Port::isNan(value))
+//#elif __APPLE__
+#if __APPLE__
+    if (__inline_isnan(value))
+#else
+    if (isnan(value))
+#endif
+	buf->writestring("NAN");	// no -NAN bugs
+    else
+    {
+	char buffer[32];
+	int n = sprintf(buffer, "%LA", value);
+	assert(n > 0 && n < sizeof(buffer));
+	for (int i = 0; i < n; i++)
+	{   char c = buffer[i];
+
+	    switch (c)
+	    {
+		case '-':
+		    buf->writeByte('N');
+		    break;
+
+		case '+':
+		case 'X':
+		case '.':
+		    break;
+
+		case '0':
+		    if (i < 2)
+			break;		// skip leading 0X
+		default:
+		    buf->writeByte(c);
+		    break;
+	    }
+	}
+    }
+}
+
+void RealExp::toMangleBuffer(OutBuffer *buf)
+{
+    buf->writeByte('e');
+    realToMangleBuffer(buf, value);
+}
+
+
+/******************************** ComplexExp **************************/
+
+ComplexExp::ComplexExp(Loc loc, complex_t value, Type *type)
+	: Expression(loc, TOKcomplex80, sizeof(ComplexExp))
+{
+    this->value = value;
+    this->type = type;
+    //printf("ComplexExp::ComplexExp(%s)\n", toChars());
+}
+
+char *ComplexExp::toChars()
+{
+    char buffer[sizeof(value) * 3 + 8 + 1];
+
+#ifdef IN_GCC
+    char buf1[sizeof(value) * 3 + 8 + 1];
+    char buf2[sizeof(value) * 3 + 8 + 1];
+    creall(value).format(buf1, sizeof(buf1));
+    cimagl(value).format(buf2, sizeof(buf2));
+    sprintf(buffer, "(%s+%si)", buf1, buf2);
+#else
+    sprintf(buffer, "(%Lg+%Lgi)", creall(value), cimagl(value));
+    assert(strlen(buffer) < sizeof(buffer));
+#endif
+    return mem.strdup(buffer);
+}
+
+dinteger_t ComplexExp::toInteger()
+{
+#ifdef IN_GCC
+    return (sinteger_t) toReal().toInt();
+#else
+    return (sinteger_t) toReal();
+#endif
+}
+
+uinteger_t ComplexExp::toUInteger()
+{
+#ifdef IN_GCC
+    return (uinteger_t) toReal().toInt();
+#else
+    return (uinteger_t) toReal();
+#endif
+}
+
+real_t ComplexExp::toReal()
+{
+    return creall(value);
+}
+
+real_t ComplexExp::toImaginary()
+{
+    return cimagl(value);
+}
+
+complex_t ComplexExp::toComplex()
+{
+    return value;
+}
+
+int ComplexExp::equals(Object *o)
+{   ComplexExp *ne;
+
+    if (this == o ||
+	(((Expression *)o)->op == TOKcomplex80 &&
+	 ((ne = (ComplexExp *)o), type->toHeadMutable()->equals(ne->type->toHeadMutable())) &&
+	 RealEquals(creall(value), creall(ne->value)) &&
+	 RealEquals(cimagl(value), cimagl(ne->value))
+	)
+       )
+	return 1;
+    return 0;
+}
+
+Expression *ComplexExp::semantic(Scope *sc)
+{
+    if (!type)
+	type = Type::tcomplex80;
+    else
+	type = type->semantic(loc, sc);
+    return this;
+}
+
+int ComplexExp::isBool(int result)
+{
+    if (result)
+	return (bool)(value);
+    else
+	return !value;
+}
+
+void ComplexExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    /* Print as:
+     *  (re+imi)
+     */
+#ifdef IN_GCC
+    char buf1[sizeof(value) * 3 + 8 + 1];
+    char buf2[sizeof(value) * 3 + 8 + 1];
+    creall(value).format(buf1, sizeof(buf1));
+    cimagl(value).format(buf2, sizeof(buf2));
+    buf->printf("(%s+%si)", buf1, buf2);
+#else
+    buf->writeByte('(');
+    floatToBuffer(buf, type, creall(value));
+    buf->writeByte('+');
+    floatToBuffer(buf, type, cimagl(value));
+    buf->writestring("i)");
+#endif
+}
+
+void ComplexExp::toMangleBuffer(OutBuffer *buf)
+{
+    buf->writeByte('c');
+    real_t r = toReal();
+    realToMangleBuffer(buf, r);
+    buf->writeByte('c');	// separate the two
+    r = toImaginary();
+    realToMangleBuffer(buf, r);
+}
+
+/******************************** IdentifierExp **************************/
+
+IdentifierExp::IdentifierExp(Loc loc, Identifier *ident)
+	: Expression(loc, TOKidentifier, sizeof(IdentifierExp))
+{
+    this->ident = ident;
+}
+
+Expression *IdentifierExp::semantic(Scope *sc)
+{
+    Dsymbol *s;
+    Dsymbol *scopesym;
+
+#if LOGSEMANTIC
+    printf("IdentifierExp::semantic('%s')\n", ident->toChars());
+#endif
+    s = sc->search(loc, ident, &scopesym);
+    if (s)
+    {	Expression *e;
+	WithScopeSymbol *withsym;
+
+	/* See if the symbol was a member of an enclosing 'with'
+	 */
+	withsym = scopesym->isWithScopeSymbol();
+	if (withsym)
+	{
+	    s = s->toAlias();
+
+	    // Same as wthis.ident
+	    if (s->needThis() || s->isTemplateDeclaration())
+	    {
+		e = new VarExp(loc, withsym->withstate->wthis);
+		e = new DotIdExp(loc, e, ident);
+	    }
+	    else
+	    {	Type *t = withsym->withstate->wthis->type;
+		if (t->ty == Tpointer)
+		    t = ((TypePointer *)t)->next;
+		e = typeDotIdExp(loc, t, ident);
+	    }
+	}
+	else
+	{
+	    /* If f is really a function template,
+	     * then replace f with the function template declaration.
+	     */
+	    FuncDeclaration *f = s->isFuncDeclaration();
+	    if (f && f->parent)
+	    {   TemplateInstance *ti = f->parent->isTemplateInstance();
+
+		if (ti &&
+		    !ti->isTemplateMixin() &&
+		    (ti->name == f->ident ||
+		     ti->toAlias()->ident == f->ident)
+		    &&
+		    ti->tempdecl && ti->tempdecl->onemember)
+		{
+		    TemplateDeclaration *tempdecl = ti->tempdecl;
+		    if (tempdecl->overroot)         // if not start of overloaded list of TemplateDeclaration's
+			tempdecl = tempdecl->overroot; // then get the start
+		    e = new TemplateExp(loc, tempdecl);
+		    e = e->semantic(sc);
+		    return e;
+		}
+	    }
+	    // Haven't done overload resolution yet, so pass 1
+	    e = new DsymbolExp(loc, s, 1);
+	}
+	return e->semantic(sc);
+    }
+    error("undefined identifier %s", ident->toChars());
+    type = Type::terror;
+    return this;
+}
+
+char *IdentifierExp::toChars()
+{
+    return ident->toChars();
+}
+
+void IdentifierExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    if (hgs->hdrgen)
+	buf->writestring(ident->toHChars2());
+    else
+	buf->writestring(ident->toChars());
+}
+
+#if DMDV2
+int IdentifierExp::isLvalue()
+{
+    return 1;
+}
+#endif
+
+Expression *IdentifierExp::toLvalue(Scope *sc, Expression *e)
+{
+#if 0
+    tym = tybasic(e1->ET->Tty);
+    if (!(tyscalar(tym) ||
+	  tym == TYstruct ||
+	  tym == TYarray && e->Eoper == TOKaddr))
+	    synerr(EM_lvalue);	// lvalue expected
+#endif
+    return this;
+}
+
+/******************************** DollarExp **************************/
+
+DollarExp::DollarExp(Loc loc)
+	: IdentifierExp(loc, Id::dollar)
+{
+}
+
+/******************************** DsymbolExp **************************/
+
+DsymbolExp::DsymbolExp(Loc loc, Dsymbol *s, int hasOverloads)
+	: Expression(loc, TOKdsymbol, sizeof(DsymbolExp))
+{
+    this->s = s;
+    this->hasOverloads = hasOverloads;
+}
+
+Expression *DsymbolExp::semantic(Scope *sc)
+{
+#if LOGSEMANTIC
+    printf("DsymbolExp::semantic('%s')\n", s->toChars());
+#endif
+
+Lagain:
+    EnumMember *em;
+    Expression *e;
+    VarDeclaration *v;
+    FuncDeclaration *f;
+    FuncLiteralDeclaration *fld;
+    OverloadSet *o;
+    Declaration *d;
+    ClassDeclaration *cd;
+    ClassDeclaration *thiscd = NULL;
+    Import *imp;
+    Package *pkg;
+    Type *t;
+
+    //printf("DsymbolExp:: %p '%s' is a symbol\n", this, toChars());
+    //printf("s = '%s', s->kind = '%s'\n", s->toChars(), s->kind());
+    if (type)
+	return this;
+    if (!s->isFuncDeclaration())	// functions are checked after overloading
+	checkDeprecated(sc, s);
+    s = s->toAlias();
+    //printf("s = '%s', s->kind = '%s', s->needThis() = %p\n", s->toChars(), s->kind(), s->needThis());
+    if (!s->isFuncDeclaration())
+	checkDeprecated(sc, s);
+
+    if (sc->func)
+	thiscd = sc->func->parent->isClassDeclaration();
+
+    // BUG: This should happen after overload resolution for functions, not before
+    if (s->needThis())
+    {
+	if (hasThis(sc)
+#if DMDV2
+		&& !s->isFuncDeclaration()
+#endif
+	    )
+	{
+	    // Supply an implicit 'this', as in
+	    //	  this.ident
+
+	    DotVarExp *de;
+
+	    de = new DotVarExp(loc, new ThisExp(loc), s->isDeclaration());
+	    return de->semantic(sc);
+	}
+    }
+
+    em = s->isEnumMember();
+    if (em)
+    {
+	e = em->value;
+	e = e->semantic(sc);
+	return e;
+    }
+    v = s->isVarDeclaration();
+    if (v)
+    {
+	//printf("Identifier '%s' is a variable, type '%s'\n", toChars(), v->type->toChars());
+	if (!type)
+	{   type = v->type;
+	    if (!v->type)
+	    {	error("forward reference of %s", v->toChars());
+		type = Type::terror;
+	    }
+	}
+	e = new VarExp(loc, v);
+	e->type = type;
+	e = e->semantic(sc);
+	return e->deref();
+    }
+    fld = s->isFuncLiteralDeclaration();
+    if (fld)
+    {	//printf("'%s' is a function literal\n", fld->toChars());
+	e = new FuncExp(loc, fld);
+	return e->semantic(sc);
+    }
+    f = s->isFuncDeclaration();
+    if (f)
+    {	//printf("'%s' is a function\n", f->toChars());
+	return new VarExp(loc, f, hasOverloads);
+    }
+    o = s->isOverloadSet();
+    if (o)
+    {	//printf("'%s' is an overload set\n", o->toChars());
+	return new OverExp(o);
+    }
+    cd = s->isClassDeclaration();
+    if (cd && thiscd && cd->isBaseOf(thiscd, NULL) && sc->func->needThis())
+    {
+	// We need to add an implicit 'this' if cd is this class or a base class.
+	DotTypeExp *dte;
+
+	dte = new DotTypeExp(loc, new ThisExp(loc), s);
+	return dte->semantic(sc);
+    }
+    imp = s->isImport();
+    if (imp)
+    {
+	if (!imp->pkg)
+	{   error("forward reference of import %s", imp->toChars());
+	    return this;
+	}
+	ScopeExp *ie = new ScopeExp(loc, imp->pkg);
+	return ie->semantic(sc);
+    }
+    pkg = s->isPackage();
+    if (pkg)
+    {
+	ScopeExp *ie;
+
+	ie = new ScopeExp(loc, pkg);
+	return ie->semantic(sc);
+    }
+    Module *mod = s->isModule();
+    if (mod)
+    {
+	ScopeExp *ie;
+
+	ie = new ScopeExp(loc, mod);
+	return ie->semantic(sc);
+    }
+
+    t = s->getType();
+    if (t)
+    {
+	return new TypeExp(loc, t);
+    }
+
+    TupleDeclaration *tup = s->isTupleDeclaration();
+    if (tup)
+    {
+	e = new TupleExp(loc, tup);
+	e = e->semantic(sc);
+	return e;
+    }
+
+    TemplateInstance *ti = s->isTemplateInstance();
+    if (ti && !global.errors)
+    {   if (!ti->semanticdone)
+	    ti->semantic(sc);
+	s = ti->inst->toAlias();
+	if (!s->isTemplateInstance())
+	    goto Lagain;
+	e = new ScopeExp(loc, ti);
+	e = e->semantic(sc);
+	return e;
+    }
+
+    TemplateDeclaration *td = s->isTemplateDeclaration();
+    if (td)
+    {
+	e = new TemplateExp(loc, td);
+	e = e->semantic(sc);
+	return e;
+    }
+
+Lerr:
+    error("%s '%s' is not a variable", s->kind(), s->toChars());
+    type = Type::terror;
+    return this;
+}
+
+char *DsymbolExp::toChars()
+{
+    return s->toChars();
+}
+
+void DsymbolExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    buf->writestring(s->toChars());
+}
+
+#if DMDV2
+int DsymbolExp::isLvalue()
+{
+    return 1;
+}
+#endif
+
+Expression *DsymbolExp::toLvalue(Scope *sc, Expression *e)
+{
+#if 0
+    tym = tybasic(e1->ET->Tty);
+    if (!(tyscalar(tym) ||
+	  tym == TYstruct ||
+	  tym == TYarray && e->Eoper == TOKaddr))
+	    synerr(EM_lvalue);	// lvalue expected
+#endif
+    return this;
+}
+
+/******************************** ThisExp **************************/
+
+ThisExp::ThisExp(Loc loc)
+	: Expression(loc, TOKthis, sizeof(ThisExp))
+{
+    //printf("ThisExp::ThisExp() loc = %d\n", loc.linnum);
+    var = NULL;
+}
+
+Expression *ThisExp::semantic(Scope *sc)
+{   FuncDeclaration *fd;
+    FuncDeclaration *fdthis;
+    int nested = 0;
+
+#if LOGSEMANTIC
+    printf("ThisExp::semantic()\n");
+#endif
+    if (type)
+    {	//assert(global.errors || var);
+	return this;
+    }
+
+    /* Special case for typeof(this) and typeof(super) since both
+     * should work even if they are not inside a non-static member function
+     */
+    if (sc->intypeof)
+    {
+	// Find enclosing struct or class
+	for (Dsymbol *s = sc->parent; 1; s = s->parent)
+	{
+	    if (!s)
+	    {
+		error("%s is not in a class or struct scope", toChars());
+		goto Lerr;
+	    }
+	    ClassDeclaration *cd = s->isClassDeclaration();
+	    if (cd)
+	    {
+		type = cd->type;
+		return this;
+	    }
+	    StructDeclaration *sd = s->isStructDeclaration();
+	    if (sd)
+	    {
+#if STRUCTTHISREF
+		type = sd->type;
+#else
+		type = sd->type->pointerTo();
+#endif
+		return this;
+	    }
+	}
+    }
+
+    fdthis = sc->parent->isFuncDeclaration();
+    fd = hasThis(sc);	// fd is the uplevel function with the 'this' variable
+    if (!fd)
+	goto Lerr;
+
+    assert(fd->vthis);
+    var = fd->vthis;
+    assert(var->parent);
+    type = var->type;
+    var->isVarDeclaration()->checkNestedReference(sc, loc);
+    if (!sc->intypeof)
+	sc->callSuper |= CSXthis;
+    return this;
+
+Lerr:
+    error("'this' is only defined in non-static member functions, not %s", sc->parent->toChars());
+    type = Type::terror;
+    return this;
+}
+
+int ThisExp::isBool(int result)
+{
+    return result ? TRUE : FALSE;
+}
+
+void ThisExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    buf->writestring("this");
+}
+
+#if DMDV2
+int ThisExp::isLvalue()
+{
+    return 1;
+}
+#endif
+
+Expression *ThisExp::toLvalue(Scope *sc, Expression *e)
+{
+    return this;
+}
+
+/******************************** SuperExp **************************/
+
+SuperExp::SuperExp(Loc loc)
+	: ThisExp(loc)
+{
+    op = TOKsuper;
+}
+
+Expression *SuperExp::semantic(Scope *sc)
+{   FuncDeclaration *fd;
+    FuncDeclaration *fdthis;
+    ClassDeclaration *cd;
+    Dsymbol *s;
+
+#if LOGSEMANTIC
+    printf("SuperExp::semantic('%s')\n", toChars());
+#endif
+    if (type)
+	return this;
+
+    /* Special case for typeof(this) and typeof(super) since both
+     * should work even if they are not inside a non-static member function
+     */
+    if (sc->intypeof)
+    {
+	// Find enclosing class
+	for (Dsymbol *s = sc->parent; 1; s = s->parent)
+	{
+	    ClassDeclaration *cd;
+
+	    if (!s)
+	    {
+		error("%s is not in a class scope", toChars());
+		goto Lerr;
+	    }
+	    cd = s->isClassDeclaration();
+	    if (cd)
+	    {
+		cd = cd->baseClass;
+		if (!cd)
+		{   error("class %s has no 'super'", s->toChars());
+		    goto Lerr;
+		}
+		type = cd->type;
+		return this;
+	    }
+	}
+    }
+
+    fdthis = sc->parent->isFuncDeclaration();
+    fd = hasThis(sc);
+    if (!fd)
+	goto Lerr;
+    assert(fd->vthis);
+    var = fd->vthis;
+    assert(var->parent);
+
+    s = fd->toParent();
+    while (s && s->isTemplateInstance())
+	s = s->toParent();
+    assert(s);
+    cd = s->isClassDeclaration();
+//printf("parent is %s %s\n", fd->toParent()->kind(), fd->toParent()->toChars());
+    if (!cd)
+	goto Lerr;
+    if (!cd->baseClass)
+    {
+	error("no base class for %s", cd->toChars());
+	type = fd->vthis->type;
+    }
+    else
+    {
+	type = cd->baseClass->type;
+    }
+
+    var->isVarDeclaration()->checkNestedReference(sc, loc);
+
+    if (!sc->intypeof)
+	sc->callSuper |= CSXsuper;
+    return this;
+
+
+Lerr:
+    error("'super' is only allowed in non-static class member functions");
+    type = Type::tint32;
+    return this;
+}
+
+void SuperExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    buf->writestring("super");
+}
+
+
+/******************************** NullExp **************************/
+
+NullExp::NullExp(Loc loc)
+	: Expression(loc, TOKnull, sizeof(NullExp))
+{
+    committed = 0;
+}
+
+Expression *NullExp::semantic(Scope *sc)
+{
+#if LOGSEMANTIC
+    printf("NullExp::semantic('%s')\n", toChars());
+#endif
+    // NULL is the same as (void *)0
+    if (!type)
+	type = Type::tvoid->pointerTo();
+    return this;
+}
+
+int NullExp::isBool(int result)
+{
+    return result ? FALSE : TRUE;
+}
+
+void NullExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    buf->writestring("null");
+}
+
+void NullExp::toMangleBuffer(OutBuffer *buf)
+{
+    buf->writeByte('n');
+}
+
+/******************************** StringExp **************************/
+
+StringExp::StringExp(Loc loc, char *string)
+	: Expression(loc, TOKstring, sizeof(StringExp))
+{
+    this->string = string;
+    this->len = strlen(string);
+    this->sz = 1;
+    this->committed = 0;
+    this->postfix = 0;
+}
+
+StringExp::StringExp(Loc loc, void *string, size_t len)
+	: Expression(loc, TOKstring, sizeof(StringExp))
+{
+    this->string = string;
+    this->len = len;
+    this->sz = 1;
+    this->committed = 0;
+    this->postfix = 0;
+}
+
+StringExp::StringExp(Loc loc, void *string, size_t len, unsigned char postfix)
+	: Expression(loc, TOKstring, sizeof(StringExp))
+{
+    this->string = string;
+    this->len = len;
+    this->sz = 1;
+    this->committed = 0;
+    this->postfix = postfix;
+}
+
+#if 0
+Expression *StringExp::syntaxCopy()
+{
+    printf("StringExp::syntaxCopy() %s\n", toChars());
+    return copy();
+}
+#endif
+
+int StringExp::equals(Object *o)
+{
+    //printf("StringExp::equals('%s')\n", o->toChars());
+    if (o && o->dyncast() == DYNCAST_EXPRESSION)
+    {	Expression *e = (Expression *)o;
+
+	if (e->op == TOKstring)
+	{
+	    return compare(o) == 0;
+	}
+    }
+    return FALSE;
+}
+
+char *StringExp::toChars()
+{
+    OutBuffer buf;
+    HdrGenState hgs;
+    char *p;
+
+    memset(&hgs, 0, sizeof(hgs));
+    toCBuffer(&buf, &hgs);
+    buf.writeByte(0);
+    p = (char *)buf.data;
+    buf.data = NULL;
+    return p;
+}
+
+Expression *StringExp::semantic(Scope *sc)
+{
+#if LOGSEMANTIC
+    printf("StringExp::semantic() %s\n", toChars());
+#endif
+    if (!type)
+    {	OutBuffer buffer;
+	size_t newlen = 0;
+	const char *p;
+	size_t u;
+	unsigned c;
+
+	switch (postfix)
+	{
+	    case 'd':
+		for (u = 0; u < len;)
+		{
+		    p = utf_decodeChar((unsigned char *)string, len, &u, &c);
+		    if (p)
+		    {	error("%s", p);
+			break;
+		    }
+		    else
+		    {	buffer.write4(c);
+			newlen++;
+		    }
+		}
+		buffer.write4(0);
+		string = buffer.extractData();
+		len = newlen;
+		sz = 4;
+		//type = new TypeSArray(Type::tdchar, new IntegerExp(loc, len, Type::tindex));
+		type = new TypeDArray(Type::tdchar->invariantOf());
+		committed = 1;
+		break;
+
+	    case 'w':
+		for (u = 0; u < len;)
+		{
+		    p = utf_decodeChar((unsigned char *)string, len, &u, &c);
+		    if (p)
+		    {	error("%s", p);
+			break;
+		    }
+		    else
+		    {	buffer.writeUTF16(c);
+			newlen++;
+			if (c >= 0x10000)
+			    newlen++;
+		    }
+		}
+		buffer.writeUTF16(0);
+		string = buffer.extractData();
+		len = newlen;
+		sz = 2;
+		//type = new TypeSArray(Type::twchar, new IntegerExp(loc, len, Type::tindex));
+		type = new TypeDArray(Type::twchar->invariantOf());
+		committed = 1;
+		break;
+
+	    case 'c':
+		committed = 1;
+	    default:
+		//type = new TypeSArray(Type::tchar, new IntegerExp(loc, len, Type::tindex));
+		type = new TypeDArray(Type::tchar->invariantOf());
+		break;
+	}
+	type = type->semantic(loc, sc);
+	//type = type->invariantOf();
+	//printf("type = %s\n", type->toChars());
+    }
+    return this;
+}
+
+/**********************************
+ * Return length of string.
+ */
+
+size_t StringExp::length()
+{
+    size_t result = 0;
+    dchar_t c;
+    const char *p;
+
+    switch (sz)
+    {
+	case 1:
+	    for (size_t u = 0; u < len;)
+	    {
+		p = utf_decodeChar((unsigned char *)string, len, &u, &c);
+		if (p)
+		{   error("%s", p);
+		    break;
+		}
+		else
+		    result++;
+	    }
+	    break;
+
+	case 2:
+	    for (size_t u = 0; u < len;)
+	    {
+		p = utf_decodeWchar((unsigned short *)string, len, &u, &c);
+		if (p)
+		{   error("%s", p);
+		    break;
+		}
+		else
+		    result++;
+	    }
+	    break;
+
+	case 4:
+	    result = len;
+	    break;
+
+	default:
+	    assert(0);
+    }
+    return result;
+}
+
+/****************************************
+ * Convert string to char[].
+ */
+
+StringExp *StringExp::toUTF8(Scope *sc)
+{
+    if (sz != 1)
+    {	// Convert to UTF-8 string
+	committed = 0;
+	Expression *e = castTo(sc, Type::tchar->arrayOf());
+	e = e->optimize(WANTvalue);
+	assert(e->op == TOKstring);
+	StringExp *se = (StringExp *)e;
+	assert(se->sz == 1);
+	return se;
+    }
+    return this;
+}
+
+int StringExp::compare(Object *obj)
+{
+    // Used to sort case statement expressions so we can do an efficient lookup
+    StringExp *se2 = (StringExp *)(obj);
+
+    // This is a kludge so isExpression() in template.c will return 5
+    // for StringExp's.
+    if (!se2)
+	return 5;
+
+    assert(se2->op == TOKstring);
+
+    int len1 = len;
+    int len2 = se2->len;
+
+    if (len1 == len2)
+    {
+	switch (sz)
+	{
+	    case 1:
+		return strcmp((char *)string, (char *)se2->string);
+
+	    case 2:
+	    {	unsigned u;
+		d_wchar *s1 = (d_wchar *)string;
+		d_wchar *s2 = (d_wchar *)se2->string;
+
+		for (u = 0; u < len; u++)
+		{
+		    if (s1[u] != s2[u])
+			return s1[u] - s2[u];
+		}
+	    }
+
+	    case 4:
+	    {	unsigned u;
+		d_dchar *s1 = (d_dchar *)string;
+		d_dchar *s2 = (d_dchar *)se2->string;
+
+		for (u = 0; u < len; u++)
+		{
+		    if (s1[u] != s2[u])
+			return s1[u] - s2[u];
+		}
+	    }
+	    break;
+
+	    default:
+		assert(0);
+	}
+    }
+    return len1 - len2;
+}
+
+int StringExp::isBool(int result)
+{
+    return result ? TRUE : FALSE;
+}
+
+unsigned StringExp::charAt(size_t i)
+{   unsigned value;
+
+    switch (sz)
+    {
+	case 1:
+	    value = ((unsigned char *)string)[i];
+	    break;
+
+	case 2:
+	    value = ((unsigned short *)string)[i];
+	    break;
+
+	case 4:
+	    value = ((unsigned int *)string)[i];
+	    break;
+
+	default:
+	    assert(0);
+	    break;
+    }
+    return value;
+}
+
+void StringExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    buf->writeByte('"');
+    for (size_t i = 0; i < len; i++)
+    {	unsigned c = charAt(i);
+
+	switch (c)
+	{
+	    case '"':
+	    case '\\':
+		if (!hgs->console)
+		    buf->writeByte('\\');
+	    default:
+		if (c <= 0xFF)
+		{   if (c <= 0x7F && (isprint(c) || hgs->console))
+			buf->writeByte(c);
+		    else
+			buf->printf("\\x%02x", c);
+		}
+		else if (c <= 0xFFFF)
+		    buf->printf("\\x%02x\\x%02x", c & 0xFF, c >> 8);
+		else
+		    buf->printf("\\x%02x\\x%02x\\x%02x\\x%02x",
+			c & 0xFF, (c >> 8) & 0xFF, (c >> 16) & 0xFF, c >> 24);
+		break;
+	}
+    }
+    buf->writeByte('"');
+    if (postfix)
+	buf->writeByte(postfix);
+}
+
+void StringExp::toMangleBuffer(OutBuffer *buf)
+{   char m;
+    OutBuffer tmp;
+    const char *p;
+    unsigned c;
+    size_t u;
+    unsigned char *q;
+    unsigned qlen;
+
+    /* Write string in UTF-8 format
+     */
+    switch (sz)
+    {	case 1:
+	    m = 'a';
+	    q = (unsigned char *)string;
+	    qlen = len;
+	    break;
+	case 2:
+	    m = 'w';
+	    for (u = 0; u < len; )
+	    {
+                p = utf_decodeWchar((unsigned short *)string, len, &u, &c);
+                if (p)
+                    error("%s", p);
+                else
+                    tmp.writeUTF8(c);
+	    }
+	    q = tmp.data;
+	    qlen = tmp.offset;
+	    break;
+	case 4:
+	    m = 'd';
+            for (u = 0; u < len; u++)
+            {
+                c = ((unsigned *)string)[u];
+                if (!utf_isValidDchar(c))
+                    error("invalid UCS-32 char \\U%08x", c);
+                else
+                    tmp.writeUTF8(c);
+            }
+	    q = tmp.data;
+	    qlen = tmp.offset;
+	    break;
+	default:
+	    assert(0);
+    }
+    buf->writeByte(m);
+    buf->printf("%d_", qlen);
+    for (size_t i = 0; i < qlen; i++)
+	buf->printf("%02x", q[i]);
+}
+
+/************************ ArrayLiteralExp ************************************/
+
+// [ e1, e2, e3, ... ]
+
+ArrayLiteralExp::ArrayLiteralExp(Loc loc, Expressions *elements)
+    : Expression(loc, TOKarrayliteral, sizeof(ArrayLiteralExp))
+{
+    this->elements = elements;
+}
+
+ArrayLiteralExp::ArrayLiteralExp(Loc loc, Expression *e)
+    : Expression(loc, TOKarrayliteral, sizeof(ArrayLiteralExp))
+{
+    elements = new Expressions;
+    elements->push(e);
+}
+
+Expression *ArrayLiteralExp::syntaxCopy()
+{
+    return new ArrayLiteralExp(loc, arraySyntaxCopy(elements));
+}
+
+Expression *ArrayLiteralExp::semantic(Scope *sc)
+{   Expression *e;
+    Type *t0 = NULL;
+
+#if LOGSEMANTIC
+    printf("ArrayLiteralExp::semantic('%s')\n", toChars());
+#endif
+    if (type)
+	return this;
+
+    // Run semantic() on each element
+    for (int i = 0; i < elements->dim; i++)
+    {	e = (Expression *)elements->data[i];
+	e = e->semantic(sc);
+	elements->data[i] = (void *)e;
+    }
+    expandTuples(elements);
+    for (int i = 0; i < elements->dim; i++)
+    {	e = (Expression *)elements->data[i];
+
+	if (!e->type)
+	    error("%s has no value", e->toChars());
+	e = resolveProperties(sc, e);
+
+	unsigned char committed = 1;
+	if (e->op == TOKstring)
+	    committed = ((StringExp *)e)->committed;
+
+	if (!t0)
+	{   t0 = e->type;
+	    // Convert any static arrays to dynamic arrays
+	    if (t0->ty == Tsarray)
+	    {
+		t0 = ((TypeSArray *)t0)->next->arrayOf();
+		e = e->implicitCastTo(sc, t0);
+	    }
+	}
+	else
+	    e = e->implicitCastTo(sc, t0);
+	if (!committed && e->op == TOKstring)
+	{   StringExp *se = (StringExp *)e;
+	    se->committed = 0;
+	}
+	elements->data[i] = (void *)e;
+    }
+
+    if (!t0)
+	t0 = Type::tvoid;
+    type = new TypeSArray(t0, new IntegerExp(elements->dim));
+    type = type->semantic(loc, sc);
+    return this;
+}
+
+int ArrayLiteralExp::checkSideEffect(int flag)
+{   int f = 0;
+
+    for (size_t i = 0; i < elements->dim; i++)
+    {	Expression *e = (Expression *)elements->data[i];
+
+	f |= e->checkSideEffect(2);
+    }
+    if (flag == 0 && f == 0)
+	Expression::checkSideEffect(0);
+    return f;
+}
+
+int ArrayLiteralExp::isBool(int result)
+{
+    size_t dim = elements ? elements->dim : 0;
+    return result ? (dim != 0) : (dim == 0);
+}
+
+#if DMDV2
+int ArrayLiteralExp::canThrow()
+{
+    return 1;	// because it can fail allocating memory
+}
+#endif
+
+void ArrayLiteralExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    buf->writeByte('[');
+    argsToCBuffer(buf, elements, hgs);
+    buf->writeByte(']');
+}
+
+void ArrayLiteralExp::toMangleBuffer(OutBuffer *buf)
+{
+    size_t dim = elements ? elements->dim : 0;
+    buf->printf("A%zu", dim);
+    for (size_t i = 0; i < dim; i++)
+    {	Expression *e = (Expression *)elements->data[i];
+	e->toMangleBuffer(buf);
+    }
+}
+
+/************************ AssocArrayLiteralExp ************************************/
+
+// [ key0 : value0, key1 : value1, ... ]
+
+AssocArrayLiteralExp::AssocArrayLiteralExp(Loc loc,
+		Expressions *keys, Expressions *values)
+    : Expression(loc, TOKassocarrayliteral, sizeof(AssocArrayLiteralExp))
+{
+    assert(keys->dim == values->dim);
+    this->keys = keys;
+    this->values = values;
+}
+
+Expression *AssocArrayLiteralExp::syntaxCopy()
+{
+    return new AssocArrayLiteralExp(loc,
+	arraySyntaxCopy(keys), arraySyntaxCopy(values));
+}
+
+Expression *AssocArrayLiteralExp::semantic(Scope *sc)
+{   Expression *e;
+    Type *tkey = NULL;
+    Type *tvalue = NULL;
+
+#if LOGSEMANTIC
+    printf("AssocArrayLiteralExp::semantic('%s')\n", toChars());
+#endif
+
+    // Run semantic() on each element
+    for (size_t i = 0; i < keys->dim; i++)
+    {	Expression *key = (Expression *)keys->data[i];
+	Expression *value = (Expression *)values->data[i];
+
+	key = key->semantic(sc);
+	value = value->semantic(sc);
+
+	keys->data[i] = (void *)key;
+	values->data[i] = (void *)value;
+    }
+    expandTuples(keys);
+    expandTuples(values);
+    if (keys->dim != values->dim)
+    {
+	error("number of keys is %u, must match number of values %u", keys->dim, values->dim);
+	keys->setDim(0);
+	values->setDim(0);
+    }
+    for (size_t i = 0; i < keys->dim; i++)
+    {	Expression *key = (Expression *)keys->data[i];
+	Expression *value = (Expression *)values->data[i];
+
+	if (!key->type)
+	    error("%s has no value", key->toChars());
+	if (!value->type)
+	    error("%s has no value", value->toChars());
+	key = resolveProperties(sc, key);
+	value = resolveProperties(sc, value);
+
+	if (!tkey)
+	    tkey = key->type;
+	else
+	    key = key->implicitCastTo(sc, tkey);
+	keys->data[i] = (void *)key;
+
+	if (!tvalue)
+	    tvalue = value->type;
+	else
+	    value = value->implicitCastTo(sc, tvalue);
+	values->data[i] = (void *)value;
+    }
+
+    if (!tkey)
+	tkey = Type::tvoid;
+    if (!tvalue)
+	tvalue = Type::tvoid;
+    type = new TypeAArray(tvalue, tkey);
+    type = type->semantic(loc, sc);
+    return this;
+}
+
+int AssocArrayLiteralExp::checkSideEffect(int flag)
+{   int f = 0;
+
+    for (size_t i = 0; i < keys->dim; i++)
+    {	Expression *key = (Expression *)keys->data[i];
+	Expression *value = (Expression *)values->data[i];
+
+	f |= key->checkSideEffect(2);
+	f |= value->checkSideEffect(2);
+    }
+    if (flag == 0 && f == 0)
+	Expression::checkSideEffect(0);
+    return f;
+}
+
+int AssocArrayLiteralExp::isBool(int result)
+{
+    size_t dim = keys->dim;
+    return result ? (dim != 0) : (dim == 0);
+}
+
+#if DMDV2
+int AssocArrayLiteralExp::canThrow()
+{
+    return 1;
+}
+#endif
+
+void AssocArrayLiteralExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    buf->writeByte('[');
+    for (size_t i = 0; i < keys->dim; i++)
+    {	Expression *key = (Expression *)keys->data[i];
+	Expression *value = (Expression *)values->data[i];
+
+	if (i)
+	    buf->writeByte(',');
+	expToCBuffer(buf, hgs, key, PREC_assign);
+	buf->writeByte(':');
+	expToCBuffer(buf, hgs, value, PREC_assign);
+    }
+    buf->writeByte(']');
+}
+
+void AssocArrayLiteralExp::toMangleBuffer(OutBuffer *buf)
+{
+    size_t dim = keys->dim;
+    buf->printf("A%zu", dim);
+    for (size_t i = 0; i < dim; i++)
+    {	Expression *key = (Expression *)keys->data[i];
+	Expression *value = (Expression *)values->data[i];
+
+	key->toMangleBuffer(buf);
+	value->toMangleBuffer(buf);
+    }
+}
+
+/************************ StructLiteralExp ************************************/
+
+// sd( e1, e2, e3, ... )
+
+StructLiteralExp::StructLiteralExp(Loc loc, StructDeclaration *sd, Expressions *elements)
+    : Expression(loc, TOKstructliteral, sizeof(StructLiteralExp))
+{
+    this->sd = sd;
+    this->elements = elements;
+#if IN_DMD
+    this->sym = NULL;
+#endif
+    this->soffset = 0;
+    this->fillHoles = 1;
+}
+
+Expression *StructLiteralExp::syntaxCopy()
+{
+    return new StructLiteralExp(loc, sd, arraySyntaxCopy(elements));
+}
+
+Expression *StructLiteralExp::semantic(Scope *sc)
+{   Expression *e;
+    int nfields = sd->fields.dim - sd->isnested;
+
+#if LOGSEMANTIC
+    printf("StructLiteralExp::semantic('%s')\n", toChars());
+#endif
+    if (type)
+	return this;
+
+    // Run semantic() on each element
+    for (size_t i = 0; i < elements->dim; i++)
+    {	e = (Expression *)elements->data[i];
+	if (!e)
+	    continue;
+	e = e->semantic(sc);
+	elements->data[i] = (void *)e;
+    }
+    expandTuples(elements);
+    size_t offset = 0;
+    for (size_t i = 0; i < elements->dim; i++)
+    {	e = (Expression *)elements->data[i];
+	if (!e)
+	    continue;
+
+	if (!e->type)
+	    error("%s has no value", e->toChars());
+	e = resolveProperties(sc, e);
+	if (i >= nfields)
+	{   error("more initializers than fields of %s", sd->toChars());
+	    break;
+	}
+	Dsymbol *s = (Dsymbol *)sd->fields.data[i];
+	VarDeclaration *v = s->isVarDeclaration();
+	assert(v);
+	if (v->offset < offset)
+	    error("overlapping initialization for %s", v->toChars());
+	offset = v->offset + v->type->size();
+
+	Type *telem = v->type;
+	while (!e->implicitConvTo(telem) && telem->toBasetype()->ty == Tsarray)
+	{   /* Static array initialization, as in:
+	     *	T[3][5] = e;
+	     */
+	    telem = telem->toBasetype()->nextOf();
+	}
+
+	e = e->implicitCastTo(sc, telem);
+
+	elements->data[i] = (void *)e;
+    }
+
+    /* Fill out remainder of elements[] with default initializers for fields[]
+     */
+    for (size_t i = elements->dim; i < nfields; i++)
+    {	Dsymbol *s = (Dsymbol *)sd->fields.data[i];
+	VarDeclaration *v = s->isVarDeclaration();
+	assert(v);
+	assert(!v->isThisDeclaration());
+
+	if (v->offset < offset)
+	{   e = NULL;
+	    sd->hasUnions = 1;
+	}
+	else
+	{
+	    if (v->init)
+	    {   e = v->init->toExpression();
+		if (!e)
+		    error("cannot make expression out of initializer for %s", v->toChars());
+	    }
+	    else
+	    {	e = v->type->defaultInit();
+		e->loc = loc;
+	    }
+	    offset = v->offset + v->type->size();
+	}
+	elements->push(e);
+    }
+
+    type = sd->type;
+    return this;
+}
+
+/**************************************
+ * Gets expression at offset of type.
+ * Returns NULL if not found.
+ */
+
+Expression *StructLiteralExp::getField(Type *type, unsigned offset)
+{
+    //printf("StructLiteralExp::getField(this = %s, type = %s, offset = %u)\n",
+//	/*toChars()*/"", type->toChars(), offset);
+    Expression *e = NULL;
+    int i = getFieldIndex(type, offset);
+
+    if (i != -1)
+    {
+	//printf("\ti = %d\n", i);
+	assert(i < elements->dim);
+	e = (Expression *)elements->data[i];
+	if (e)
+	{
+	    e = e->copy();
+	    e->type = type;
+	}
+    }
+    return e;
+}
+
+/************************************
+ * Get index of field.
+ * Returns -1 if not found. 
+ */
+
+int StructLiteralExp::getFieldIndex(Type *type, unsigned offset)
+{
+    /* Find which field offset is by looking at the field offsets
+     */
+    if (elements->dim)
+    {
+	for (size_t i = 0; i < sd->fields.dim; i++)
+	{
+	    Dsymbol *s = (Dsymbol *)sd->fields.data[i];
+	    VarDeclaration *v = s->isVarDeclaration();
+	    assert(v);
+
+	    if (offset == v->offset &&
+		type->size() == v->type->size())
+	    {   Expression *e = (Expression *)elements->data[i];
+		if (e)
+		{
+		    return i;
+		}
+		break;
+	    }
+	}
+    }
+    return -1;
+}
+
+#if DMDV2
+int StructLiteralExp::isLvalue()
+{
+    return 1;
+}
+#endif
+
+/*
+Removed in LDC. See declaration.
+Expression *StructLiteralExp::toLvalue(Scope *sc, Expression *e)
+{
+    return this;
+}
+*/
+
+
+int StructLiteralExp::checkSideEffect(int flag)
+{   int f = 0;
+
+    for (size_t i = 0; i < elements->dim; i++)
+    {	Expression *e = (Expression *)elements->data[i];
+	if (!e)
+	    continue;
+
+	f |= e->checkSideEffect(2);
+    }
+    if (flag == 0 && f == 0)
+	Expression::checkSideEffect(0);
+    return f;
+}
+
+#if DMDV2
+int StructLiteralExp::canThrow()
+{
+    return arrayExpressionCanThrow(elements);
+}
+#endif
+
+void StructLiteralExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    buf->writestring(sd->toChars());
+    buf->writeByte('(');
+    argsToCBuffer(buf, elements, hgs);
+    buf->writeByte(')');
+}
+
+void StructLiteralExp::toMangleBuffer(OutBuffer *buf)
+{
+    size_t dim = elements ? elements->dim : 0;
+    buf->printf("S%zu", dim);
+    for (size_t i = 0; i < dim; i++)
+    {	Expression *e = (Expression *)elements->data[i];
+	if (e)
+	    e->toMangleBuffer(buf);
+	else
+	    buf->writeByte('v');	// 'v' for void
+    }
+}
+
+/************************ TypeDotIdExp ************************************/
+
+/* Things like:
+ *	int.size
+ *	foo.size
+ *	(foo).size
+ *	cast(foo).size
+ */
+
+Expression *typeDotIdExp(Loc loc, Type *type, Identifier *ident)
+{
+    return new DotIdExp(loc, new TypeExp(loc, type), ident);
+}
+
+
+/************************************************************/
+
+// Mainly just a placeholder
+
+TypeExp::TypeExp(Loc loc, Type *type)
+    : Expression(loc, TOKtype, sizeof(TypeExp))
+{
+    //printf("TypeExp::TypeExp(%s)\n", type->toChars());
+    this->type = type;
+}
+
+Expression *TypeExp::syntaxCopy()
+{
+    //printf("TypeExp::syntaxCopy()\n");
+    return new TypeExp(loc, type->syntaxCopy());
+}
+
+Expression *TypeExp::semantic(Scope *sc)
+{
+    //printf("TypeExp::semantic(%s)\n", type->toChars());
+    type = type->semantic(loc, sc);
+    return this;
+}
+
+void TypeExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    type->toCBuffer(buf, NULL, hgs);
+}
+
+/************************************************************/
+
+// Mainly just a placeholder
+
+ScopeExp::ScopeExp(Loc loc, ScopeDsymbol *pkg)
+    : Expression(loc, TOKimport, sizeof(ScopeExp))
+{
+    //printf("ScopeExp::ScopeExp(pkg = '%s')\n", pkg->toChars());
+    //static int count; if (++count == 38) *(char*)0=0;
+    this->sds = pkg;
+}
+
+Expression *ScopeExp::syntaxCopy()
+{
+    ScopeExp *se = new ScopeExp(loc, (ScopeDsymbol *)sds->syntaxCopy(NULL));
+    return se;
+}
+
+Expression *ScopeExp::semantic(Scope *sc)
+{
+    TemplateInstance *ti;
+    ScopeDsymbol *sds2;
+
+#if LOGSEMANTIC
+    printf("+ScopeExp::semantic('%s')\n", toChars());
+#endif
+Lagain:
+    ti = sds->isTemplateInstance();
+    if (ti && !global.errors)
+    {	Dsymbol *s;
+	if (!ti->semanticdone)
+	    ti->semantic(sc);
+	s = ti->inst->toAlias();
+	sds2 = s->isScopeDsymbol();
+	if (!sds2)
+	{   Expression *e;
+
+	    //printf("s = %s, '%s'\n", s->kind(), s->toChars());
+	    if (ti->withsym)
+	    {
+		// Same as wthis.s
+		e = new VarExp(loc, ti->withsym->withstate->wthis);
+		e = new DotVarExp(loc, e, s->isDeclaration());
+	    }
+	    else
+		e = new DsymbolExp(loc, s);
+	    e = e->semantic(sc);
+	    //printf("-1ScopeExp::semantic()\n");
+	    return e;
+	}
+	if (sds2 != sds)
+	{
+	    sds = sds2;
+	    goto Lagain;
+	}
+	//printf("sds = %s, '%s'\n", sds->kind(), sds->toChars());
+    }
+    else
+    {
+	//printf("sds = %s, '%s'\n", sds->kind(), sds->toChars());
+	//printf("\tparent = '%s'\n", sds->parent->toChars());
+	sds->semantic(sc);
+    }
+    type = Type::tvoid;
+    //printf("-2ScopeExp::semantic() %s\n", toChars());
+    return this;
+}
+
+void ScopeExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    if (sds->isTemplateInstance())
+    {
+        sds->toCBuffer(buf, hgs);
+    }
+    else
+    {
+	buf->writestring(sds->kind());
+	buf->writestring(" ");
+	buf->writestring(sds->toChars());
+    }
+}
+
+/********************** TemplateExp **************************************/
+
+// Mainly just a placeholder
+
+TemplateExp::TemplateExp(Loc loc, TemplateDeclaration *td)
+    : Expression(loc, TOKtemplate, sizeof(TemplateExp))
+{
+    //printf("TemplateExp(): %s\n", td->toChars());
+    this->td = td;
+}
+
+void TemplateExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    buf->writestring(td->toChars());
+}
+
+void TemplateExp::rvalue()
+{
+    error("template %s has no value", toChars());
+}
+
+/********************** NewExp **************************************/
+
+/* thisexp.new(newargs) newtype(arguments) */
+
+NewExp::NewExp(Loc loc, Expression *thisexp, Expressions *newargs,
+	Type *newtype, Expressions *arguments)
+    : Expression(loc, TOKnew, sizeof(NewExp))
+{
+    this->thisexp = thisexp;
+    this->newargs = newargs;
+    this->newtype = newtype;
+    this->arguments = arguments;
+    member = NULL;
+    allocator = NULL;
+    onstack = 0;
+}
+
+Expression *NewExp::syntaxCopy()
+{
+    return new NewExp(loc,
+	thisexp ? thisexp->syntaxCopy() : NULL,
+	arraySyntaxCopy(newargs),
+	newtype->syntaxCopy(), arraySyntaxCopy(arguments));
+}
+
+
+Expression *NewExp::semantic(Scope *sc)
+{   int i;
+    Type *tb;
+    ClassDeclaration *cdthis = NULL;
+
+#if LOGSEMANTIC
+    printf("NewExp::semantic() %s\n", toChars());
+    if (thisexp)
+	printf("\tthisexp = %s\n", thisexp->toChars());
+    printf("\tnewtype: %s\n", newtype->toChars());
+#endif
+    if (type)			// if semantic() already run
+	return this;
+
+Lagain:
+    if (thisexp)
+    {	thisexp = thisexp->semantic(sc);
+	cdthis = thisexp->type->isClassHandle();
+	if (cdthis)
+	{
+	    sc = sc->push(cdthis);
+	    type = newtype->semantic(loc, sc);
+	    sc = sc->pop();
+	}
+	else
+	{
+	    error("'this' for nested class must be a class type, not %s", thisexp->type->toChars());
+	    type = newtype->semantic(loc, sc);
+	}
+    }
+    else
+	type = newtype->semantic(loc, sc);
+    newtype = type;		// in case type gets cast to something else
+    tb = type->toBasetype();
+    //printf("tb: %s, deco = %s\n", tb->toChars(), tb->deco);
+
+    arrayExpressionSemantic(newargs, sc);
+    preFunctionArguments(loc, sc, newargs);
+    arrayExpressionSemantic(arguments, sc);
+    preFunctionArguments(loc, sc, arguments);
+
+    if (thisexp && tb->ty != Tclass)
+	error("e.new is only for allocating nested classes, not %s", tb->toChars());
+
+    if (tb->ty == Tclass)
+    {	TypeFunction *tf;
+
+	TypeClass *tc = (TypeClass *)(tb);
+	ClassDeclaration *cd = tc->sym->isClassDeclaration();
+	if (cd->isInterfaceDeclaration())
+	    error("cannot create instance of interface %s", cd->toChars());
+	else if (cd->isAbstract())
+	{   error("cannot create instance of abstract class %s", cd->toChars());
+	    for (int i = 0; i < cd->vtbl.dim; i++)
+	    {	FuncDeclaration *fd = ((Dsymbol *)cd->vtbl.data[i])->isFuncDeclaration();
+		if (fd && fd->isAbstract())
+		    error("function %s is abstract", fd->toChars());
+	    }
+	}
+	checkDeprecated(sc, cd);
+	if (cd->isNested())
+	{   /* We need a 'this' pointer for the nested class.
+	     * Ensure we have the right one.
+	     */
+	    Dsymbol *s = cd->toParent2();
+	    ClassDeclaration *cdn = s->isClassDeclaration();
+	    FuncDeclaration *fdn = s->isFuncDeclaration();
+
+	    //printf("cd isNested, cdn = %s\n", cdn ? cdn->toChars() : "null");
+	    if (cdn)
+	    {
+		if (!cdthis)
+		{
+		    // Supply an implicit 'this' and try again
+		    thisexp = new ThisExp(loc);
+		    for (Dsymbol *sp = sc->parent; 1; sp = sp->parent)
+		    {	if (!sp)
+			{
+			    error("outer class %s 'this' needed to 'new' nested class %s", cdn->toChars(), cd->toChars());
+			    break;
+			}
+			ClassDeclaration *cdp = sp->isClassDeclaration();
+			if (!cdp)
+			    continue;
+			if (cdp == cdn || cdn->isBaseOf(cdp, NULL))
+			    break;
+			// Add a '.outer' and try again
+			thisexp = new DotIdExp(loc, thisexp, Id::outer);
+		    }
+		    if (!global.errors)
+			goto Lagain;
+		}
+		if (cdthis)
+		{
+		    //printf("cdthis = %s\n", cdthis->toChars());
+		    if (cdthis != cdn && !cdn->isBaseOf(cdthis, NULL))
+			error("'this' for nested class must be of type %s, not %s", cdn->toChars(), thisexp->type->toChars());
+		}
+#if 0
+		else
+		{
+		    for (Dsymbol *sf = sc->func; 1; sf= sf->toParent2()->isFuncDeclaration())
+		    {
+			if (!sf)
+			{
+			    error("outer class %s 'this' needed to 'new' nested class %s", cdn->toChars(), cd->toChars());
+			    break;
+			}
+			printf("sf = %s\n", sf->toChars());
+			AggregateDeclaration *ad = sf->isThis();
+			if (ad && (ad == cdn || cdn->isBaseOf(ad->isClassDeclaration(), NULL)))
+			    break;
+		    }
+		}
+#endif
+	    }
+	    else if (fdn) // Possible problems here, no obvious solution when merging
+	    {	/* The nested class cd is nested inside a function,
+		 * we'll let getEthis() look for errors.
+		 */
+		//printf("nested class %s is nested inside function %s, we're in %s\n", cd->toChars(), fdn->toChars(), sc->func->toChars());
+		if (thisexp)
+		    // Because thisexp cannot be a function frame pointer
+		    error("e.new is only for allocating nested classes");
+	    }
+	    else
+		assert(0);
+	}
+	else if (thisexp)
+	    error("e.new is only for allocating nested classes");
+
+	FuncDeclaration *f = NULL;
+	if (cd->ctor)
+	    f = resolveFuncCall(sc, loc, cd->ctor, NULL, NULL, arguments, 0);
+	if (f)
+	{
+	    checkDeprecated(sc, f);
+	    member = f->isCtorDeclaration();
+	    assert(member);
+
+	    cd->accessCheck(loc, sc, member);
+
+	    tf = (TypeFunction *)f->type;
+
+	    if (!arguments)
+		arguments = new Expressions();
+	    functionArguments(loc, sc, tf, arguments);
+	}
+	else
+	{
+	    if (arguments && arguments->dim)
+		error("no constructor for %s", cd->toChars());
+	}
+
+	if (cd->aggNew)
+	{
+	    // Prepend the size argument to newargs[]
+	    Expression *e = new IntegerExp(loc, cd->size(loc), Type::tsize_t);
+	    if (!newargs)
+		newargs = new Expressions();
+	    newargs->shift(e);
+
+	    f = cd->aggNew->overloadResolve(loc, NULL, newargs);
+	    allocator = f->isNewDeclaration();
+	    assert(allocator);
+
+	    tf = (TypeFunction *)f->type;
+	    functionArguments(loc, sc, tf, newargs);
+	}
+	else
+	{
+	    if (newargs && newargs->dim)
+		error("no allocator for %s", cd->toChars());
+	}
+    }
+    else if (tb->ty == Tstruct)
+    {
+	TypeStruct *ts = (TypeStruct *)tb;
+	StructDeclaration *sd = ts->sym;
+	TypeFunction *tf;
+
+	FuncDeclaration *f = NULL;
+	if (sd->ctor)
+	    f = resolveFuncCall(sc, loc, sd->ctor, NULL, NULL, arguments, 0);
+	if (f)
+	{
+	    checkDeprecated(sc, f);
+	    member = f->isCtorDeclaration();
+	    assert(member);
+
+	    sd->accessCheck(loc, sc, member);
+
+	    tf = (TypeFunction *)f->type;
+//	    type = tf->next;
+
+	    if (!arguments)
+		arguments = new Expressions();
+	    functionArguments(loc, sc, tf, arguments);
+	}
+	else
+	{
+	    if (arguments && arguments->dim)
+		error("no constructor for %s", sd->toChars());
+	}
+
+
+	if (sd->aggNew)
+	{
+	    // Prepend the uint size argument to newargs[]
+	    Expression *e = new IntegerExp(loc, sd->size(loc), Type::tuns32);
+	    if (!newargs)
+		newargs = new Expressions();
+	    newargs->shift(e);
+
+	    f = sd->aggNew->overloadResolve(loc, NULL, newargs);
+	    allocator = f->isNewDeclaration();
+	    assert(allocator);
+
+	    tf = (TypeFunction *)f->type;
+	    functionArguments(loc, sc, tf, newargs);
+#if 0
+	    e = new VarExp(loc, f);
+	    e = new CallExp(loc, e, newargs);
+	    e = e->semantic(sc);
+	    e->type = type->pointerTo();
+	    return e;
+#endif
+	}
+	else
+	{
+	    if (newargs && newargs->dim)
+		error("no allocator for %s", sd->toChars());
+	}
+
+	type = type->pointerTo();
+    }
+    else if (tb->ty == Tarray && (arguments && arguments->dim))
+    {
+	for (size_t i = 0; i < arguments->dim; i++)
+	{
+	    if (tb->ty != Tarray)
+	    {	error("too many arguments for array");
+		arguments->dim = i;
+		break;
+	    }
+
+	    Expression *arg = (Expression *)arguments->data[i];
+	    arg = resolveProperties(sc, arg);
+	    arg = arg->implicitCastTo(sc, Type::tsize_t);
+	    arg = arg->optimize(WANTvalue);
+	    if (arg->op == TOKint64 && (long long)arg->toInteger() < 0)
+		error("negative array index %s", arg->toChars());
+	    arguments->data[i] = (void *) arg;
+	    tb = ((TypeDArray *)tb)->next->toBasetype();
+	}
+    }
+    else if (tb->isscalar())
+    {
+	if (arguments && arguments->dim)
+	    error("no constructor for %s", type->toChars());
+
+	type = type->pointerTo();
+    }
+    else
+    {
+	error("new can only create structs, dynamic arrays or class objects, not %s's", type->toChars());
+	type = type->pointerTo();
+    }
+
+//printf("NewExp: '%s'\n", toChars());
+//printf("NewExp:type '%s'\n", type->toChars());
+
+    return this;
+}
+
+int NewExp::checkSideEffect(int flag)
+{
+    return 1;
+}
+
+#if DMDV2
+int NewExp::canThrow()
+{
+    return 1;
+}
+#endif
+
+void NewExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{   int i;
+
+    if (thisexp)
+    {	expToCBuffer(buf, hgs, thisexp, PREC_primary);
+	buf->writeByte('.');
+    }
+    buf->writestring("new ");
+    if (newargs && newargs->dim)
+    {
+	buf->writeByte('(');
+	argsToCBuffer(buf, newargs, hgs);
+	buf->writeByte(')');
+    }
+    newtype->toCBuffer(buf, NULL, hgs);
+    if (arguments && arguments->dim)
+    {
+	buf->writeByte('(');
+	argsToCBuffer(buf, arguments, hgs);
+	buf->writeByte(')');
+    }
+}
+
+/********************** NewAnonClassExp **************************************/
+
+NewAnonClassExp::NewAnonClassExp(Loc loc, Expression *thisexp,
+	Expressions *newargs, ClassDeclaration *cd, Expressions *arguments)
+    : Expression(loc, TOKnewanonclass, sizeof(NewAnonClassExp))
+{
+    this->thisexp = thisexp;
+    this->newargs = newargs;
+    this->cd = cd;
+    this->arguments = arguments;
+}
+
+Expression *NewAnonClassExp::syntaxCopy()
+{
+    return new NewAnonClassExp(loc,
+	thisexp ? thisexp->syntaxCopy() : NULL,
+	arraySyntaxCopy(newargs),
+	(ClassDeclaration *)cd->syntaxCopy(NULL),
+	arraySyntaxCopy(arguments));
+}
+
+
+Expression *NewAnonClassExp::semantic(Scope *sc)
+{
+#if LOGSEMANTIC
+    printf("NewAnonClassExp::semantic() %s\n", toChars());
+    //printf("thisexp = %p\n", thisexp);
+    //printf("type: %s\n", type->toChars());
+#endif
+
+    Expression *d = new DeclarationExp(loc, cd);
+    d = d->semantic(sc);
+
+    Expression *n = new NewExp(loc, thisexp, newargs, cd->type, arguments);
+
+    Expression *c = new CommaExp(loc, d, n);
+    return c->semantic(sc);
+}
+
+int NewAnonClassExp::checkSideEffect(int flag)
+{
+    return 1;
+}
+
+#if DMDV2
+int NewAnonClassExp::canThrow()
+{
+    return 1;
+}
+#endif
+
+void NewAnonClassExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{   int i;
+
+    if (thisexp)
+    {	expToCBuffer(buf, hgs, thisexp, PREC_primary);
+	buf->writeByte('.');
+    }
+    buf->writestring("new");
+    if (newargs && newargs->dim)
+    {
+	buf->writeByte('(');
+	argsToCBuffer(buf, newargs, hgs);
+	buf->writeByte(')');
+    }
+    buf->writestring(" class ");
+    if (arguments && arguments->dim)
+    {
+	buf->writeByte('(');
+	argsToCBuffer(buf, arguments, hgs);
+	buf->writeByte(')');
+    }
+    //buf->writestring(" { }");
+    if (cd)
+    {
+        cd->toCBuffer(buf, hgs);
+    }
+}
+
+/********************** SymbolExp **************************************/
+
+#if DMDV2
+SymbolExp::SymbolExp(Loc loc, enum TOK op, int size, Declaration *var, int hasOverloads)
+    : Expression(loc, op, size)
+{
+    assert(var);
+    this->var = var;
+    this->hasOverloads = hasOverloads;
+}
+#endif
+
+/********************** SymOffExp **************************************/
+
+SymOffExp::SymOffExp(Loc loc, Declaration *var, unsigned offset, int hasOverloads)
+    : SymbolExp(loc, TOKsymoff, sizeof(SymOffExp), var, hasOverloads)
+{
+    this->offset = offset;
+    m = NULL;
+    VarDeclaration *v = var->isVarDeclaration();
+    if (v && v->needThis())
+	error("need 'this' for address of %s", v->toChars());
+}
+
+Expression *SymOffExp::semantic(Scope *sc)
+{
+#if LOGSEMANTIC
+    printf("SymOffExp::semantic('%s')\n", toChars());
+#endif
+    //var->semantic(sc);
+    m = sc->module;
+    if (!type)
+	type = var->type->pointerTo();
+    VarDeclaration *v = var->isVarDeclaration();
+    if (v)
+	v->checkNestedReference(sc, loc);
+    return this;
+}
+
+int SymOffExp::isBool(int result)
+{
+    return result ? TRUE : FALSE;
+}
+
+void SymOffExp::checkEscape()
+{
+    VarDeclaration *v = var->isVarDeclaration();
+    if (v)
+    {
+	if (!v->isDataseg())
+	    error("escaping reference to local variable %s", v->toChars());
+    }
+}
+
+void SymOffExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    if (offset)
+	buf->printf("(& %s+%u)", var->toChars(), offset);
+    else
+	buf->printf("& %s", var->toChars());
+}
+
+/******************************** VarExp **************************/
+
+VarExp::VarExp(Loc loc, Declaration *var, int hasOverloads)
+    : SymbolExp(loc, TOKvar, sizeof(VarExp), var, hasOverloads)
+{
+    //printf("VarExp(this = %p, '%s', loc = %s)\n", this, var->toChars(), loc.toChars());
+    //if (strcmp(var->ident->toChars(), "func") == 0) halt();
+    this->type = var->type;
+}
+
+int VarExp::equals(Object *o)
+{   VarExp *ne;
+
+    if (this == o ||
+	(((Expression *)o)->op == TOKvar &&
+	 ((ne = (VarExp *)o), type->toHeadMutable()->equals(ne->type->toHeadMutable())) &&
+	 var == ne->var))
+	return 1;
+    return 0;
+}
+
+Expression *VarExp::semantic(Scope *sc)
+{   FuncLiteralDeclaration *fd;
+
+#if LOGSEMANTIC
+    printf("VarExp::semantic(%s)\n", toChars());
+#endif
+    if (!type)
+    {	type = var->type;
+#if 0
+	if (var->storage_class & STClazy)
+	{
+	    TypeFunction *tf = new TypeFunction(NULL, type, 0, LINKd);
+	    type = new TypeDelegate(tf);
+	    type = type->semantic(loc, sc);
+	}
+#endif
+    }
+    /* Fix for 1161 doesn't work because it causes protection
+     * problems when instantiating imported templates passing private
+     * variables as alias template parameters.
+     */
+    //accessCheck(loc, sc, NULL, var);
+
+    VarDeclaration *v = var->isVarDeclaration();
+    if (v)
+    {
+#if 0
+	if ((v->isConst() || v->isInvariant()) &&
+	    type->toBasetype()->ty != Tsarray && v->init)
+	{
+	    ExpInitializer *ei = v->init->isExpInitializer();
+	    if (ei)
+	    {
+		//ei->exp->implicitCastTo(sc, type)->print();
+		return ei->exp->implicitCastTo(sc, type);
+	    }
+	}
+#endif
+	v->checkNestedReference(sc, loc);
+#if DMDV2
+#if 1
+	if (sc->func)
+	{
+	    /* Determine if sc->func is pure or if any function that
+	     * encloses it is also pure.
+	     */
+	    bool hasPureParent = false;
+	    for (FuncDeclaration *outerfunc = sc->func; outerfunc;)
+	    {
+		if (outerfunc->isPure())
+		{
+		    hasPureParent = true;
+		    break;
+		}
+		Dsymbol *parent = outerfunc->toParent2();
+	        if (!parent)
+		    break;
+		outerfunc = parent->isFuncDeclaration();
+	    }
+
+	    /* If ANY of its enclosing functions are pure,
+	     * it cannot do anything impure.
+	     * If it is pure, it cannot access any mutable variables other
+	     * than those inside itself
+	     */
+	    if (hasPureParent && !sc->intypeof && v->isDataseg() &&
+		!v->isInvariant())
+	    {
+		error("pure function '%s' cannot access mutable static data '%s'",
+		    sc->func->toChars(), v->toChars());
+	    }
+	    else if (sc->func->isPure() && sc->parent != v->parent &&
+		!sc->intypeof && !v->isInvariant() &&
+		!(v->storage_class & STCmanifest))
+	    {
+		error("pure nested function '%s' cannot access mutable data '%s'",
+		    sc->func->toChars(), v->toChars());
+		if (v->isEnumDeclaration())
+		    error("enum");
+	    }	
+	}
+#else
+	if (sc->func && sc->func->isPure() && !sc->intypeof)
+	{
+	    if (v->isDataseg() && !v->isInvariant())
+		error("pure function '%s' cannot access mutable static data '%s'", sc->func->toChars(), v->toChars());
+	}
+#endif
+#endif
+    }
+#if 0
+    else if ((fd = var->isFuncLiteralDeclaration()) != NULL)
+    {	Expression *e;
+	e = new FuncExp(loc, fd);
+	e->type = type;
+	return e;
+    }
+#endif
+    return this;
+}
+
+char *VarExp::toChars()
+{
+    return var->toChars();
+}
+
+void VarExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    buf->writestring(var->toChars());
+}
+
+void VarExp::checkEscape()
+{
+    VarDeclaration *v = var->isVarDeclaration();
+    if (v)
+    {	Type *tb = v->type->toBasetype();
+	// if reference type
+	if (tb->ty == Tarray || tb->ty == Tsarray || tb->ty == Tclass)
+	{
+	    if ((v->isAuto() || v->isScope()) && !v->noauto)
+		error("escaping reference to scope local %s", v->toChars());
+	    else if (v->storage_class & STCvariadic)
+		error("escaping reference to variadic parameter %s", v->toChars());
+	}
+    }
+}
+
+#if DMDV2
+int VarExp::isLvalue()
+{
+    if (var->storage_class & STClazy)
+	return 0;
+    return 1;
+}
+#endif
+
+Expression *VarExp::toLvalue(Scope *sc, Expression *e)
+{
+#if 0
+    tym = tybasic(e1->ET->Tty);
+    if (!(tyscalar(tym) ||
+	  tym == TYstruct ||
+	  tym == TYarray && e->Eoper == TOKaddr))
+	    synerr(EM_lvalue);	// lvalue expected
+#endif
+    if (var->storage_class & STClazy)
+	error("lazy variables cannot be lvalues");
+    return this;
+}
+
+Expression *VarExp::modifiableLvalue(Scope *sc, Expression *e)
+{
+    //printf("VarExp::modifiableLvalue('%s')\n", var->toChars());
+    if (type && type->toBasetype()->ty == Tsarray)
+	error("cannot change reference to static array '%s'", var->toChars());
+
+    var->checkModify(loc, sc, type);
+
+    // See if this expression is a modifiable lvalue (i.e. not const)
+    return toLvalue(sc, e);
+}
+
+
+/******************************** OverExp **************************/
+
+#if DMDV2
+OverExp::OverExp(OverloadSet *s)
+	: Expression(loc, TOKoverloadset, sizeof(OverExp))
+{
+    //printf("OverExp(this = %p, '%s')\n", this, var->toChars());
+    vars = s;
+    type = Type::tvoid;
+}
+
+int OverExp::isLvalue()
+{
+    return 1;
+}
+
+Expression *OverExp::toLvalue(Scope *sc, Expression *e)
+{
+    return this;
+}
+#endif
+
+
+/******************************** TupleExp **************************/
+
+TupleExp::TupleExp(Loc loc, Expressions *exps)
+	: Expression(loc, TOKtuple, sizeof(TupleExp))
+{
+    //printf("TupleExp(this = %p)\n", this);
+    this->exps = exps;
+    this->type = NULL;
+}
+
+
+TupleExp::TupleExp(Loc loc, TupleDeclaration *tup)
+	: Expression(loc, TOKtuple, sizeof(TupleExp))
+{
+    exps = new Expressions();
+    type = NULL;
+
+    exps->reserve(tup->objects->dim);
+    for (size_t i = 0; i < tup->objects->dim; i++)
+    {   Object *o = (Object *)tup->objects->data[i];
+	if (o->dyncast() == DYNCAST_EXPRESSION)
+	{
+	    Expression *e = (Expression *)o;
+	    e = e->syntaxCopy();
+	    exps->push(e);
+	}
+	else if (o->dyncast() == DYNCAST_DSYMBOL)
+	{
+	    Dsymbol *s = (Dsymbol *)o;
+	    Expression *e = new DsymbolExp(loc, s);
+	    exps->push(e);
+	}
+	else if (o->dyncast() == DYNCAST_TYPE)
+	{
+	    Type *t = (Type *)o;
+	    Expression *e = new TypeExp(loc, t);
+	    exps->push(e);
+	}
+	else
+	{
+	    error("%s is not an expression", o->toChars());
+	}
+    }
+}
+
+int TupleExp::equals(Object *o)
+{   TupleExp *ne;
+
+    if (this == o)
+	return 1;
+    if (((Expression *)o)->op == TOKtuple)
+    {
+	TupleExp *te = (TupleExp *)o;
+	if (exps->dim != te->exps->dim)
+	    return 0;
+	for (size_t i = 0; i < exps->dim; i++)
+	{   Expression *e1 = (Expression *)exps->data[i];
+	    Expression *e2 = (Expression *)te->exps->data[i];
+
+	    if (!e1->equals(e2))
+		return 0;
+	}
+	return 1;
+    }
+    return 0;
+}
+
+Expression *TupleExp::syntaxCopy()
+{
+    return new TupleExp(loc, arraySyntaxCopy(exps));
+}
+
+Expression *TupleExp::semantic(Scope *sc)
+{
+#if LOGSEMANTIC
+    printf("+TupleExp::semantic(%s)\n", toChars());
+#endif
+    if (type)
+	return this;
+
+    // Run semantic() on each argument
+    for (size_t i = 0; i < exps->dim; i++)
+    {	Expression *e = (Expression *)exps->data[i];
+
+	e = e->semantic(sc);
+	if (!e->type)
+	{   error("%s has no value", e->toChars());
+	    e->type = Type::terror;
+	}
+	exps->data[i] = (void *)e;
+    }
+
+    expandTuples(exps);
+    if (0 && exps->dim == 1)
+    {
+	return (Expression *)exps->data[0];
+    }
+    type = new TypeTuple(exps);
+    //printf("-TupleExp::semantic(%s)\n", toChars());
+    return this;
+}
+
+void TupleExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    buf->writestring("tuple(");
+    argsToCBuffer(buf, exps, hgs);
+    buf->writeByte(')');
+}
+
+int TupleExp::checkSideEffect(int flag)
+{   int f = 0;
+
+    for (int i = 0; i < exps->dim; i++)
+    {	Expression *e = (Expression *)exps->data[i];
+
+	f |= e->checkSideEffect(2);
+    }
+    if (flag == 0 && f == 0)
+	Expression::checkSideEffect(0);
+    return f;
+}
+
+#if DMDV2
+int TupleExp::canThrow()
+{
+    return arrayExpressionCanThrow(exps);
+}
+#endif
+
+void TupleExp::checkEscape()
+{
+    for (size_t i = 0; i < exps->dim; i++)
+    {   Expression *e = (Expression *)exps->data[i];
+	e->checkEscape();
+    }
+}
+
+/******************************** FuncExp *********************************/
+
+FuncExp::FuncExp(Loc loc, FuncLiteralDeclaration *fd)
+	: Expression(loc, TOKfunction, sizeof(FuncExp))
+{
+    this->fd = fd;
+}
+
+Expression *FuncExp::syntaxCopy()
+{
+    return new FuncExp(loc, (FuncLiteralDeclaration *)fd->syntaxCopy(NULL));
+}
+
+Expression *FuncExp::semantic(Scope *sc)
+{
+#if LOGSEMANTIC
+    printf("FuncExp::semantic(%s)\n", toChars());
+#endif
+    if (!type)
+    {
+	fd->semantic(sc);
+	//fd->parent = sc->parent;
+	if (global.errors)
+	{
+	}
+	else
+	{
+	    fd->semantic2(sc);
+	    if (!global.errors)
+	    {
+		fd->semantic3(sc);
+
+		if (!global.errors && global.params.useInline)
+		    fd->inlineScan();
+	    }
+	}
+
+	// Type is a "delegate to" or "pointer to" the function literal
+	if (fd->isNested())
+	{
+	    type = new TypeDelegate(fd->type);
+	    type = type->semantic(loc, sc);
+	}
+	else
+	{
+	    type = fd->type->pointerTo();
+	}
+	fd->tookAddressOf++;
+    }
+    return this;
+}
+
+char *FuncExp::toChars()
+{
+    return fd->toChars();
+}
+
+void FuncExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    fd->toCBuffer(buf, hgs);
+    //buf->writestring(fd->toChars());
+}
+
+
+/******************************** DeclarationExp **************************/
+
+DeclarationExp::DeclarationExp(Loc loc, Dsymbol *declaration)
+	: Expression(loc, TOKdeclaration, sizeof(DeclarationExp))
+{
+    this->declaration = declaration;
+}
+
+Expression *DeclarationExp::syntaxCopy()
+{
+    return new DeclarationExp(loc, declaration->syntaxCopy(NULL));
+}
+
+Expression *DeclarationExp::semantic(Scope *sc)
+{
+    if (type)
+	return this;
+
+#if LOGSEMANTIC
+    printf("DeclarationExp::semantic() %s\n", toChars());
+#endif
+
+    /* This is here to support extern(linkage) declaration,
+     * where the extern(linkage) winds up being an AttribDeclaration
+     * wrapper.
+     */
+    Dsymbol *s = declaration;
+
+    AttribDeclaration *ad = declaration->isAttribDeclaration();
+    if (ad)
+    {
+	if (ad->decl && ad->decl->dim == 1)
+	    s = (Dsymbol *)ad->decl->data[0];
+    }
+
+    if (s->isVarDeclaration())
+    {	// Do semantic() on initializer first, so:
+	//	int a = a;
+	// will be illegal.
+	declaration->semantic(sc);
+	s->parent = sc->parent;
+    }
+
+    //printf("inserting '%s' %p into sc = %p\n", s->toChars(), s, sc);
+    // Insert into both local scope and function scope.
+    // Must be unique in both.
+    if (s->ident)
+    {
+	if (!sc->insert(s))
+	    error("declaration %s is already defined", s->toPrettyChars());
+	else if (sc->func)
+	{   VarDeclaration *v = s->isVarDeclaration();
+	    if (s->isFuncDeclaration() &&
+		!sc->func->localsymtab->insert(s))
+		error("declaration %s is already defined in another scope in %s", s->toPrettyChars(), sc->func->toChars());
+	    else if (!global.params.useDeprecated)
+	    {	// Disallow shadowing
+
+		for (Scope *scx = sc->enclosing; scx && scx->func == sc->func; scx = scx->enclosing)
+		{   Dsymbol *s2;
+
+		    if (scx->scopesym && scx->scopesym->symtab &&
+			(s2 = scx->scopesym->symtab->lookup(s->ident)) != NULL &&
+			s != s2)
+		    {
+			error("shadowing declaration %s is deprecated", s->toPrettyChars());
+		    }
+		}
+	    }
+	}
+    }
+    if (!s->isVarDeclaration())
+    {
+	declaration->semantic(sc);
+	s->parent = sc->parent;
+    }
+    if (!global.errors)
+    {
+	declaration->semantic2(sc);
+	if (!global.errors)
+	{
+	    declaration->semantic3(sc);
+
+	    if (!global.errors && global.params.useInline)
+		declaration->inlineScan();
+	}
+    }
+
+    type = Type::tvoid;
+    return this;
+}
+
+int DeclarationExp::checkSideEffect(int flag)
+{
+    return 1;
+}
+
+#if DMDV2
+int DeclarationExp::canThrow()
+{
+    VarDeclaration *v = declaration->isVarDeclaration();
+    if (v && v->init)
+    {	ExpInitializer *ie = v->init->isExpInitializer();
+	return ie && ie->exp->canThrow();
+    }
+    return 0;
+}
+#endif
+
+void DeclarationExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    declaration->toCBuffer(buf, hgs);
+}
+
+
+/************************ TypeidExp ************************************/
+
+/*
+ *	typeid(int)
+ */
+
+TypeidExp::TypeidExp(Loc loc, Type *typeidType)
+    : Expression(loc, TOKtypeid, sizeof(TypeidExp))
+{
+    this->typeidType = typeidType;
+}
+
+
+Expression *TypeidExp::syntaxCopy()
+{
+    return new TypeidExp(loc, typeidType->syntaxCopy());
+}
+
+
+Expression *TypeidExp::semantic(Scope *sc)
+{   Expression *e;
+
+#if LOGSEMANTIC
+    printf("TypeidExp::semantic()\n");
+#endif
+    typeidType = typeidType->semantic(loc, sc);
+    e = typeidType->getTypeInfo(sc);
+    if (e->loc.linnum == 0)
+	e->loc = loc;		// so there's at least some line number info
+    return e;
+}
+
+void TypeidExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    buf->writestring("typeid(");
+    typeidType->toCBuffer(buf, NULL, hgs);
+    buf->writeByte(')');
+}
+
+/************************ TraitsExp ************************************/
+#if DMDV2
+/*
+ *	__traits(identifier, args...)
+ */
+
+TraitsExp::TraitsExp(Loc loc, Identifier *ident, Objects *args)
+    : Expression(loc, TOKtraits, sizeof(TraitsExp))
+{
+    this->ident = ident;
+    this->args = args;
+}
+
+
+Expression *TraitsExp::syntaxCopy()
+{
+    return new TraitsExp(loc, ident, TemplateInstance::arraySyntaxCopy(args));
+}
+
+
+void TraitsExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    buf->writestring("__traits(");
+    buf->writestring(ident->toChars());
+    if (args)
+    {
+	for (int i = 0; i < args->dim; i++)
+	{
+	    buf->writeByte(',');
+	    Object *oarg = (Object *)args->data[i];
+	    ObjectToCBuffer(buf, hgs, oarg);
+	}
+    }
+    buf->writeByte(')');
+}
+#endif
+
+/************************************************************/
+
+HaltExp::HaltExp(Loc loc)
+	: Expression(loc, TOKhalt, sizeof(HaltExp))
+{
+}
+
+Expression *HaltExp::semantic(Scope *sc)
+{
+#if LOGSEMANTIC
+    printf("HaltExp::semantic()\n");
+#endif
+    type = Type::tvoid;
+    return this;
+}
+
+int HaltExp::checkSideEffect(int flag)
+{
+    return 1;
+}
+
+void HaltExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    buf->writestring("halt");
+}
+
+/************************************************************/
+
+IsExp::IsExp(Loc loc, Type *targ, Identifier *id, enum TOK tok,
+	Type *tspec, enum TOK tok2, TemplateParameters *parameters)
+	: Expression(loc, TOKis, sizeof(IsExp))
+{
+    this->targ = targ;
+    this->id = id;
+    this->tok = tok;
+    this->tspec = tspec;
+    this->tok2 = tok2;
+    this->parameters = parameters;
+}
+
+Expression *IsExp::syntaxCopy()
+{
+    // This section is identical to that in TemplateDeclaration::syntaxCopy()
+    TemplateParameters *p = NULL;
+    if (parameters)
+    {
+	p = new TemplateParameters();
+	p->setDim(parameters->dim);
+	for (int i = 0; i < p->dim; i++)
+	{   TemplateParameter *tp = (TemplateParameter *)parameters->data[i];
+	    p->data[i] = (void *)tp->syntaxCopy();
+	}
+    }
+
+    return new IsExp(loc,
+	targ->syntaxCopy(),
+	id,
+	tok,
+	tspec ? tspec->syntaxCopy() : NULL,
+	tok2,
+	p);
+}
+
+Expression *IsExp::semantic(Scope *sc)
+{   Type *tded;
+
+    /* is(targ id tok tspec)
+     * is(targ id == tok2)
+     */
+
+    //printf("IsExp::semantic(%s)\n", toChars());
+    if (id && !(sc->flags & SCOPEstaticif))
+	error("can only declare type aliases within static if conditionals");
+
+    Type *t = targ->trySemantic(loc, sc);
+    if (!t)
+	goto Lno;			// errors, so condition is false
+    targ = t;
+    if (tok2 != TOKreserved)
+    {
+	switch (tok2)
+	{
+	    case TOKtypedef:
+		if (targ->ty != Ttypedef)
+		    goto Lno;
+		tded = ((TypeTypedef *)targ)->sym->basetype;
+		break;
+
+	    case TOKstruct:
+		if (targ->ty != Tstruct)
+		    goto Lno;
+		if (((TypeStruct *)targ)->sym->isUnionDeclaration())
+		    goto Lno;
+		tded = targ;
+		break;
+
+	    case TOKunion:
+		if (targ->ty != Tstruct)
+		    goto Lno;
+		if (!((TypeStruct *)targ)->sym->isUnionDeclaration())
+		    goto Lno;
+		tded = targ;
+		break;
+
+	    case TOKclass:
+		if (targ->ty != Tclass)
+		    goto Lno;
+		if (((TypeClass *)targ)->sym->isInterfaceDeclaration())
+		    goto Lno;
+		tded = targ;
+		break;
+
+	    case TOKinterface:
+		if (targ->ty != Tclass)
+		    goto Lno;
+		if (!((TypeClass *)targ)->sym->isInterfaceDeclaration())
+		    goto Lno;
+		tded = targ;
+		break;
+#if DMDV2
+	    case TOKconst:
+		if (!targ->isConst())
+		    goto Lno;
+		tded = targ;
+		break;
+
+	    case TOKinvariant:
+	    case TOKimmutable:
+		if (!targ->isInvariant())
+		    goto Lno;
+		tded = targ;
+		break;
+#endif
+
+	    case TOKsuper:
+		// If class or interface, get the base class and interfaces
+		if (targ->ty != Tclass)
+		    goto Lno;
+		else
+		{   ClassDeclaration *cd = ((TypeClass *)targ)->sym;
+		    Arguments *args = new Arguments;
+		    args->reserve(cd->baseclasses.dim);
+		    for (size_t i = 0; i < cd->baseclasses.dim; i++)
+		    {	BaseClass *b = (BaseClass *)cd->baseclasses.data[i];
+			args->push(new Argument(STCin, b->type, NULL, NULL));
+		    }
+		    tded = new TypeTuple(args);
+		}
+		break;
+
+	    case TOKenum:
+		if (targ->ty != Tenum)
+		    goto Lno;
+		tded = ((TypeEnum *)targ)->sym->memtype;
+		break;
+
+	    case TOKdelegate:
+		if (targ->ty != Tdelegate)
+		    goto Lno;
+		tded = ((TypeDelegate *)targ)->next;	// the underlying function type
+		break;
+
+	    case TOKfunction:
+	    {
+		if (targ->ty != Tfunction)
+		    goto Lno;
+		tded = targ;
+
+		/* Generate tuple from function parameter types.
+		 */
+		assert(tded->ty == Tfunction);
+		Arguments *params = ((TypeFunction *)tded)->parameters;
+		size_t dim = Argument::dim(params);
+		Arguments *args = new Arguments;
+		args->reserve(dim);
+		for (size_t i = 0; i < dim; i++)
+		{   Argument *arg = Argument::getNth(params, i);
+		    assert(arg && arg->type);
+		    args->push(new Argument(arg->storageClass, arg->type, NULL, NULL));
+		}
+		tded = new TypeTuple(args);
+		break;
+	    }
+	    case TOKreturn:
+		/* Get the 'return type' for the function,
+		 * delegate, or pointer to function.
+		 */
+		if (targ->ty == Tfunction)
+		    tded = ((TypeFunction *)targ)->next;
+		else if (targ->ty == Tdelegate)
+		{   tded = ((TypeDelegate *)targ)->next;
+		    tded = ((TypeFunction *)tded)->next;
+		}
+		else if (targ->ty == Tpointer &&
+			 ((TypePointer *)targ)->next->ty == Tfunction)
+		{   tded = ((TypePointer *)targ)->next;
+		    tded = ((TypeFunction *)tded)->next;
+		}
+		else
+		    goto Lno;
+		break;
+
+	    default:
+		assert(0);
+	}
+	goto Lyes;
+    }
+    else if (id && tspec)
+    {
+	/* Evaluate to TRUE if targ matches tspec.
+	 * If TRUE, declare id as an alias for the specialized type.
+	 */
+
+	MATCH m;
+	assert(parameters && parameters->dim);
+
+	Objects dedtypes;
+	dedtypes.setDim(parameters->dim);
+	dedtypes.zero();
+
+	m = targ->deduceType(NULL, tspec, parameters, &dedtypes);
+	if (m == MATCHnomatch ||
+	    (m != MATCHexact && tok == TOKequal))
+	{
+	    goto Lno;
+	}
+	else
+	{
+	    tded = (Type *)dedtypes.data[0];
+	    if (!tded)
+		tded = targ;
+
+	    Objects tiargs;
+	    tiargs.setDim(1);
+	    tiargs.data[0] = (void *)targ;
+
+	    /* Declare trailing parameters
+	     */
+	    for (int i = 1; i < parameters->dim; i++)
+	    {	TemplateParameter *tp = (TemplateParameter *)parameters->data[i];
+		Declaration *s = NULL;
+
+		m = tp->matchArg(sc, &tiargs, i, parameters, &dedtypes, &s);
+		if (m == MATCHnomatch)
+		    goto Lno;
+		s->semantic(sc);
+		if (!sc->insert(s))
+		    error("declaration %s is already defined", s->toChars());
+#if 0
+		Object *o = (Object *)dedtypes.data[i];
+		Dsymbol *s = TemplateDeclaration::declareParameter(loc, sc, tp, o);
+#endif
+		if (sc->sd)
+		    s->addMember(sc, sc->sd, 1);
+	    }
+
+	    goto Lyes;
+	}
+    }
+    else if (id)
+    {
+	/* Declare id as an alias for type targ. Evaluate to TRUE
+	 */
+	tded = targ;
+	goto Lyes;
+    }
+    else if (tspec)
+    {
+	/* Evaluate to TRUE if targ matches tspec
+	 * is(targ == tspec)
+	 * is(targ : tspec)
+	 */
+	tspec = tspec->semantic(loc, sc);
+	//printf("targ  = %s\n", targ->toChars());
+	//printf("tspec = %s\n", tspec->toChars());
+	if (tok == TOKcolon)
+	{   if (targ->implicitConvTo(tspec))
+		goto Lyes;
+	    else
+		goto Lno;
+	}
+	else /* == */
+	{   if (targ->equals(tspec))
+		goto Lyes;
+	    else
+		goto Lno;
+	}
+    }
+
+Lyes:
+    if (id)
+    {
+	Dsymbol *s = new AliasDeclaration(loc, id, tded);
+	s->semantic(sc);
+	if (!sc->insert(s))
+	    error("declaration %s is already defined", s->toChars());
+	if (sc->sd)
+	    s->addMember(sc, sc->sd, 1);
+    }
+//printf("Lyes\n");
+    return new IntegerExp(loc, 1, Type::tbool);
+
+Lno:
+//printf("Lno\n");
+    return new IntegerExp(loc, 0, Type::tbool);
+}
+
+void IsExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    buf->writestring("is(");
+    targ->toCBuffer(buf, id, hgs);
+    if (tok2 != TOKreserved)
+    {
+	buf->printf(" %s %s", Token::toChars(tok), Token::toChars(tok2));
+    }
+    else if (tspec)
+    {
+	if (tok == TOKcolon)
+	    buf->writestring(" : ");
+	else
+	    buf->writestring(" == ");
+	tspec->toCBuffer(buf, NULL, hgs);
+    }
+#if DMDV2
+    if (parameters)
+    {	// First parameter is already output, so start with second
+	for (int i = 1; i < parameters->dim; i++)
+	{
+	    buf->writeByte(',');
+	    TemplateParameter *tp = (TemplateParameter *)parameters->data[i];
+	    tp->toCBuffer(buf, hgs);
+	}
+    }
+#endif
+    buf->writeByte(')');
+}
+
+
+/************************************************************/
+
+UnaExp::UnaExp(Loc loc, enum TOK op, int size, Expression *e1)
+	: Expression(loc, op, size)
+{
+    this->e1 = e1;
+}
+
+Expression *UnaExp::syntaxCopy()
+{   UnaExp *e;
+
+    e = (UnaExp *)copy();
+    e->type = NULL;
+    e->e1 = e->e1->syntaxCopy();
+    return e;
+}
+
+Expression *UnaExp::semantic(Scope *sc)
+{
+#if LOGSEMANTIC
+    printf("UnaExp::semantic('%s')\n", toChars());
+#endif
+    e1 = e1->semantic(sc);
+//    if (!e1->type)
+//	error("%s has no value", e1->toChars());
+    return this;
+}
+
+#if DMDV2
+int UnaExp::canThrow()
+{
+    return e1->canThrow();
+}
+#endif
+
+void UnaExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    buf->writestring(Token::toChars(op));
+    expToCBuffer(buf, hgs, e1, precedence[op]);
+}
+
+/************************************************************/
+
+BinExp::BinExp(Loc loc, enum TOK op, int size, Expression *e1, Expression *e2)
+	: Expression(loc, op, size)
+{
+    this->e1 = e1;
+    this->e2 = e2;
+}
+
+Expression *BinExp::syntaxCopy()
+{   BinExp *e;
+
+    e = (BinExp *)copy();
+    e->type = NULL;
+    e->e1 = e->e1->syntaxCopy();
+    e->e2 = e->e2->syntaxCopy();
+    return e;
+}
+
+Expression *BinExp::semantic(Scope *sc)
+{
+#if LOGSEMANTIC
+    printf("BinExp::semantic('%s')\n", toChars());
+#endif
+    e1 = e1->semantic(sc);
+    if (!e1->type &&
+	!(op == TOKassign && e1->op == TOKdottd))	// a.template = e2
+    {
+	error("%s has no value", e1->toChars());
+	e1->type = Type::terror;
+    }
+    e2 = e2->semantic(sc);
+    if (!e2->type)
+    {
+	error("%s has no value", e2->toChars());
+	e2->type = Type::terror;
+    }
+    return this;
+}
+
+Expression *BinExp::semanticp(Scope *sc)
+{
+    BinExp::semantic(sc);
+    e1 = resolveProperties(sc, e1);
+    e2 = resolveProperties(sc, e2);
+    return this;
+}
+
+/***************************
+ * Common semantic routine for some xxxAssignExp's.
+ */
+
+Expression *BinExp::commonSemanticAssign(Scope *sc)
+{   Expression *e;
+
+    if (!type)
+    {
+	BinExp::semantic(sc);
+	e2 = resolveProperties(sc, e2);
+
+	e = op_overload(sc);
+	if (e)
+	    return e;
+
+	if (e1->op == TOKslice)
+	{   // T[] op= ...
+	    typeCombine(sc);
+	    type = e1->type;
+	    return arrayOp(sc);
+	}
+
+	e1 = e1->modifiableLvalue(sc, e1);
+	e1->checkScalar();
+	type = e1->type;
+	if (type->toBasetype()->ty == Tbool)
+	{
+	    error("operator not allowed on bool expression %s", toChars());
+	}
+	typeCombine(sc);
+	e1->checkArithmetic();
+	e2->checkArithmetic();
+
+	if (op == TOKmodass && e2->type->iscomplex())
+	{   error("cannot perform modulo complex arithmetic");
+	    return new ErrorExp();
+	}
+    }
+    return this;
+}
+
+Expression *BinExp::commonSemanticAssignIntegral(Scope *sc)
+{   Expression *e;
+
+    if (!type)
+    {
+	BinExp::semantic(sc);
+	e2 = resolveProperties(sc, e2);
+
+	e = op_overload(sc);
+	if (e)
+	    return e;
+
+	if (e1->op == TOKslice)
+	{   // T[] op= ...
+	    typeCombine(sc);
+	    type = e1->type;
+	    return arrayOp(sc);
+	}
+
+	e1 = e1->modifiableLvalue(sc, e1);
+	e1->checkScalar();
+	type = e1->type;
+	if (type->toBasetype()->ty == Tbool)
+	{
+	    e2 = e2->implicitCastTo(sc, type);
+	}
+
+	typeCombine(sc);
+	e1->checkIntegral();
+	e2->checkIntegral();
+    }
+    return this;
+}
+
+int BinExp::checkSideEffect(int flag)
+{
+    if (op == TOKplusplus ||
+	   op == TOKminusminus ||
+	   op == TOKassign ||
+	   op == TOKconstruct ||
+	   op == TOKblit ||
+	   op == TOKaddass ||
+	   op == TOKminass ||
+	   op == TOKcatass ||
+	   op == TOKmulass ||
+	   op == TOKdivass ||
+	   op == TOKmodass ||
+	   op == TOKshlass ||
+	   op == TOKshrass ||
+	   op == TOKushrass ||
+	   op == TOKandass ||
+	   op == TOKorass ||
+	   op == TOKxorass ||
+	   op == TOKin ||
+	   op == TOKremove)
+	return 1;
+    return Expression::checkSideEffect(flag);
+}
+
+void BinExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    expToCBuffer(buf, hgs, e1, precedence[op]);
+    buf->writeByte(' ');
+    buf->writestring(Token::toChars(op));
+    buf->writeByte(' ');
+    expToCBuffer(buf, hgs, e2, (enum PREC)(precedence[op] + 1));
+}
+
+int BinExp::isunsigned()
+{
+    return e1->type->isunsigned() || e2->type->isunsigned();
+}
+
+#if DMDV2
+int BinExp::canThrow()
+{
+    return e1->canThrow() || e2->canThrow();
+}
+#endif
+
+void BinExp::incompatibleTypes()
+{
+    error("incompatible types for ((%s) %s (%s)): '%s' and '%s'",
+         e1->toChars(), Token::toChars(op), e2->toChars(),
+         e1->type->toChars(), e2->type->toChars());
+}
+
+/************************************************************/
+
+CompileExp::CompileExp(Loc loc, Expression *e)
+	: UnaExp(loc, TOKmixin, sizeof(CompileExp), e)
+{
+}
+
+Expression *CompileExp::semantic(Scope *sc)
+{
+#if LOGSEMANTIC
+    printf("CompileExp::semantic('%s')\n", toChars());
+#endif
+    UnaExp::semantic(sc);
+    e1 = resolveProperties(sc, e1);
+    e1 = e1->optimize(WANTvalue | WANTinterpret);
+    if (e1->op != TOKstring)
+    {	error("argument to mixin must be a string, not (%s)", e1->toChars());
+	type = Type::terror;
+	return this;
+    }
+    StringExp *se = (StringExp *)e1;
+    se = se->toUTF8(sc);
+    Parser p(sc->module, (unsigned char *)se->string, se->len, 0);
+    p.loc = loc;
+    p.nextToken();
+    //printf("p.loc.linnum = %d\n", p.loc.linnum);
+    Expression *e = p.parseExpression();
+    if (p.token.value != TOKeof)
+	error("incomplete mixin expression (%s)", se->toChars());
+    return e->semantic(sc);
+}
+
+void CompileExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    buf->writestring("mixin(");
+    expToCBuffer(buf, hgs, e1, PREC_assign);
+    buf->writeByte(')');
+}
+
+/************************************************************/
+
+FileExp::FileExp(Loc loc, Expression *e)
+	: UnaExp(loc, TOKmixin, sizeof(FileExp), e)
+{
+}
+
+Expression *FileExp::semantic(Scope *sc)
+{   char *name;
+    StringExp *se;
+
+#if LOGSEMANTIC
+    printf("FileExp::semantic('%s')\n", toChars());
+#endif
+    UnaExp::semantic(sc);
+    e1 = resolveProperties(sc, e1);
+    e1 = e1->optimize(WANTvalue);
+    if (e1->op != TOKstring)
+    {	error("file name argument must be a string, not (%s)", e1->toChars());
+	goto Lerror;
+    }
+    se = (StringExp *)e1;
+    se = se->toUTF8(sc);
+    name = (char *)se->string;
+
+    if (!global.params.fileImppath)
+    {	error("need -Jpath switch to import text file %s", name);
+	goto Lerror;
+    }
+
+    if (name != FileName::name(name))
+    {	error("use -Jpath switch to provide path for filename %s", name);
+	goto Lerror;
+    }
+
+    name = FileName::searchPath(global.filePath, name, 0);
+    if (!name)
+    {	error("file %s cannot be found, check -Jpath", se->toChars());
+	goto Lerror;
+    }
+
+    if (global.params.verbose)
+	printf("file      %s\t(%s)\n", (char*)se->string, name);
+
+    {	File f(name);
+	if (f.read())
+	{   error("cannot read file %s", f.toChars());
+	    goto Lerror;
+	}
+	else
+	{
+	    f.ref = 1;
+	    se = new StringExp(loc, f.buffer, f.len);
+	}
+    }
+  Lret:
+    return se->semantic(sc);
+
+  Lerror:
+    se = new StringExp(loc, (char *)"");
+    goto Lret;
+}
+
+void FileExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    buf->writestring("import(");
+    expToCBuffer(buf, hgs, e1, PREC_assign);
+    buf->writeByte(')');
+}
+
+/************************************************************/
+
+AssertExp::AssertExp(Loc loc, Expression *e, Expression *msg)
+	: UnaExp(loc, TOKassert, sizeof(AssertExp), e)
+{
+    this->msg = msg;
+}
+
+Expression *AssertExp::syntaxCopy()
+{
+    AssertExp *ae = new AssertExp(loc, e1->syntaxCopy(),
+				       msg ? msg->syntaxCopy() : NULL);
+    return ae;
+}
+
+Expression *AssertExp::semantic(Scope *sc)
+{
+#if LOGSEMANTIC
+    printf("AssertExp::semantic('%s')\n", toChars());
+#endif
+    UnaExp::semantic(sc);
+    e1 = resolveProperties(sc, e1);
+    // BUG: see if we can do compile time elimination of the Assert
+    e1 = e1->optimize(WANTvalue);
+    e1 = e1->checkToBoolean();
+    if (msg)
+    {
+	msg = msg->semantic(sc);
+	msg = resolveProperties(sc, msg);
+	msg = msg->implicitCastTo(sc, Type::tchar->constOf()->arrayOf());
+	msg = msg->optimize(WANTvalue);
+    }
+    if (e1->isBool(FALSE))
+    {
+	FuncDeclaration *fd = sc->parent->isFuncDeclaration();
+	fd->hasReturnExp |= 4;
+
+	if (!global.params.useAssert)
+	{   Expression *e = new HaltExp(loc);
+	    e = e->semantic(sc);
+	    return e;
+	}
+    }
+    type = Type::tvoid;
+    return this;
+}
+
+int AssertExp::checkSideEffect(int flag)
+{
+    return 1;
+}
+
+#if DMDV2
+int AssertExp::canThrow()
+{
+    /* assert()s are non-recoverable errors, so functions that
+     * use them can be considered "nothrow"
+     */
+    return 0; //(global.params.useAssert != 0);
+}
+#endif
+
+void AssertExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    buf->writestring("assert(");
+    expToCBuffer(buf, hgs, e1, PREC_assign);
+    if (msg)
+    {
+	buf->writeByte(',');
+	expToCBuffer(buf, hgs, msg, PREC_assign);
+    }
+    buf->writeByte(')');
+}
+
+/************************************************************/
+
+DotIdExp::DotIdExp(Loc loc, Expression *e, Identifier *ident)
+	: UnaExp(loc, TOKdot, sizeof(DotIdExp), e)
+{
+    this->ident = ident;
+}
+
+Expression *DotIdExp::semantic(Scope *sc)
+{   Expression *e;
+    Expression *eleft;
+    Expression *eright;
+
+#if LOGSEMANTIC
+    printf("DotIdExp::semantic(this = %p, '%s')\n", this, toChars());
+    //printf("e1->op = %d, '%s'\n", e1->op, Token::toChars(e1->op));
+#endif
+
+//{ static int z; fflush(stdout); if (++z == 10) *(char*)0=0; }
+
+#if 0
+    /* Don't do semantic analysis if we'll be converting
+     * it to a string.
+     */
+    if (ident == Id::stringof)
+    {	char *s = e1->toChars();
+	e = new StringExp(loc, s, strlen(s), 'c');
+	e = e->semantic(sc);
+	return e;
+    }
+#endif
+
+    /* Special case: rewrite this.id and super.id
+     * to be classtype.id and baseclasstype.id
+     * if we have no this pointer.
+     */
+    if ((e1->op == TOKthis || e1->op == TOKsuper) && !hasThis(sc))
+    {	ClassDeclaration *cd;
+	StructDeclaration *sd;
+	AggregateDeclaration *ad;
+
+	ad = sc->getStructClassScope();
+	if (ad)
+	{
+	    cd = ad->isClassDeclaration();
+	    if (cd)
+	    {
+		if (e1->op == TOKthis)
+		{
+		    e = typeDotIdExp(loc, cd->type, ident);
+		    return e->semantic(sc);
+		}
+		else if (cd->baseClass && e1->op == TOKsuper)
+		{
+		    e = typeDotIdExp(loc, cd->baseClass->type, ident);
+		    return e->semantic(sc);
+		}
+	    }
+	    else
+	    {
+		sd = ad->isStructDeclaration();
+		if (sd)
+		{
+		    if (e1->op == TOKthis)
+		    {
+			e = typeDotIdExp(loc, sd->type, ident);
+			return e->semantic(sc);
+		    }
+		}
+	    }
+	}
+    }
+
+    UnaExp::semantic(sc);
+
+    if (e1->op == TOKdotexp)
+    {
+	DotExp *de = (DotExp *)e1;
+	eleft = de->e1;
+	eright = de->e2;
+    }
+    else
+    {
+	e1 = resolveProperties(sc, e1);
+	eleft = NULL;
+	eright = e1;
+    }
+#if DMDV2
+    if (e1->op == TOKtuple && ident == Id::offsetof)
+    {	/* 'distribute' the .offsetof to each of the tuple elements.
+	 */
+	TupleExp *te = (TupleExp *)e1;
+	Expressions *exps = new Expressions();
+	exps->setDim(te->exps->dim);
+	for (int i = 0; i < exps->dim; i++)
+	{   Expression *e = (Expression *)te->exps->data[i];
+	    e = e->semantic(sc);
+	    e = new DotIdExp(e->loc, e, Id::offsetof);
+	    exps->data[i] = (void *)e;
+	}
+	e = new TupleExp(loc, exps);
+	e = e->semantic(sc);
+	return e;
+    }
+#endif
+
+    if (e1->op == TOKtuple && ident == Id::length)
+    {
+	TupleExp *te = (TupleExp *)e1;
+	e = new IntegerExp(loc, te->exps->dim, Type::tsize_t);
+	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;
+    }
+
+    Type *t1b = e1->type->toBasetype();
+
+    if (eright->op == TOKimport)	// also used for template alias's
+    {
+	ScopeExp *ie = (ScopeExp *)eright;
+
+	/* Disable access to another module's private imports.
+	 * The check for 'is sds our current module' is because
+	 * the current module should have access to its own imports.
+	 */
+	Dsymbol *s = ie->sds->search(loc, ident,
+	    (ie->sds->isModule() && ie->sds != sc->module) ? 1 : 0);
+	if (s)
+	{
+	    s = s->toAlias();
+	    checkDeprecated(sc, s);
+
+	    EnumMember *em = s->isEnumMember();
+	    if (em)
+	    {
+		e = em->value;
+		e = e->semantic(sc);
+		return e;
+	    }
+
+	    VarDeclaration *v = s->isVarDeclaration();
+	    if (v)
+	    {
+		//printf("DotIdExp:: Identifier '%s' is a variable, type '%s'\n", toChars(), v->type->toChars());
+		if (v->inuse)
+		{
+		    error("circular reference to '%s'", v->toChars());
+		    type = Type::tint32;
+		    return this;
+		}
+		type = v->type;
+		if (v->needThis())
+		{
+		    if (!eleft)
+			eleft = new ThisExp(loc);
+		    e = new DotVarExp(loc, eleft, v);
+		    e = e->semantic(sc);
+		}
+		else
+		{
+		    e = new VarExp(loc, v);
+		    if (eleft)
+		    {	e = new CommaExp(loc, eleft, e);
+			e->type = v->type;
+		    }
+		}
+		return e->deref();
+	    }
+
+	    FuncDeclaration *f = s->isFuncDeclaration();
+	    if (f)
+	    {
+		//printf("it's a function\n");
+		if (f->needThis())
+		{
+		    if (!eleft)
+			eleft = new ThisExp(loc);
+		    e = new DotVarExp(loc, eleft, f);
+		    e = e->semantic(sc);
+		}
+		else
+		{
+		    e = new VarExp(loc, f, 1);
+		    if (eleft)
+		    {	e = new CommaExp(loc, eleft, e);
+			e->type = f->type;
+		    }
+		}
+		return e;
+	    }
+#if DMDV2
+	    OverloadSet *o = s->isOverloadSet();
+	    if (o)
+	    {   //printf("'%s' is an overload set\n", o->toChars());
+		return new OverExp(o);
+	    }
+#endif
+
+	    Type *t = s->getType();
+	    if (t)
+	    {
+		return new TypeExp(loc, t);
+	    }
+
+	    TupleDeclaration *tup = s->isTupleDeclaration();
+	    if (tup)
+	    {
+		if (eleft)
+		    error("cannot have e.tuple");
+		e = new TupleExp(loc, tup);
+		e = e->semantic(sc);
+		return e;
+	    }
+
+	    ScopeDsymbol *sds = s->isScopeDsymbol();
+	    if (sds)
+	    {
+		//printf("it's a ScopeDsymbol\n");
+		e = new ScopeExp(loc, sds);
+		e = e->semantic(sc);
+		if (eleft)
+		    e = new DotExp(loc, eleft, e);
+		return e;
+	    }
+
+	    Import *imp = s->isImport();
+	    if (imp)
+	    {
+		ScopeExp *ie;
+
+		ie = new ScopeExp(loc, imp->pkg);
+		return ie->semantic(sc);
+	    }
+
+	    // BUG: handle other cases like in IdentifierExp::semantic()
+#ifdef DEBUG
+	    printf("s = '%s', kind = '%s'\n", s->toChars(), s->kind());
+#endif
+	    assert(0);
+	}
+	else if (ident == Id::stringof)
+	{   char *s = ie->toChars();
+	    e = new StringExp(loc, s, strlen(s), 'c');
+	    e = e->semantic(sc);
+	    return e;
+	}
+	error("undefined identifier %s", toChars());
+	type = Type::tvoid;
+	return this;
+    }
+    else if (t1b->ty == Tpointer &&
+	     ident != Id::init && ident != Id::__sizeof &&
+	     ident != Id::alignof && ident != Id::offsetof &&
+	     ident != Id::mangleof && ident != Id::stringof)
+    {	/* Rewrite:
+         *   p.ident
+         * as:
+         *   (*p).ident
+         */
+	e = new PtrExp(loc, e1);
+	e->type = ((TypePointer *)t1b)->next;
+	return e->type->dotExp(sc, e, ident);
+    }
+#if DMDV2
+    else if (t1b->ty == Tarray ||
+             t1b->ty == Tsarray ||
+	     t1b->ty == Taarray)
+    {	/* If ident is not a valid property, rewrite:
+	 *   e1.ident
+         * as:
+         *   .ident(e1)
+         */
+	unsigned errors = global.errors;
+	global.gag++;
+	e = e1->type->dotExp(sc, e1, ident);
+	global.gag--;
+	if (errors != global.errors)	// if failed to find the property
+	{
+	    global.errors = errors;
+	    e = new DotIdExp(loc, new IdentifierExp(loc, Id::empty), ident);
+	    e = new CallExp(loc, e, e1);
+	}
+	e = e->semantic(sc);
+	return e;
+    }
+#endif
+    else
+    {
+	e = e1->type->dotExp(sc, e1, ident);
+	e = e->semantic(sc);
+	return e;
+    }
+}
+
+void DotIdExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    //printf("DotIdExp::toCBuffer()\n");
+    expToCBuffer(buf, hgs, e1, PREC_primary);
+    buf->writeByte('.');
+    buf->writestring(ident->toChars());
+}
+
+/********************** DotTemplateExp ***********************************/
+
+// Mainly just a placeholder
+
+DotTemplateExp::DotTemplateExp(Loc loc, Expression *e, TemplateDeclaration *td)
+	: UnaExp(loc, TOKdottd, sizeof(DotTemplateExp), e)
+  
+{
+    this->td = td;
+}
+
+void DotTemplateExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    expToCBuffer(buf, hgs, e1, PREC_primary);
+    buf->writeByte('.');
+    buf->writestring(td->toChars());
+}
+
+
+/************************************************************/
+
+DotVarExp::DotVarExp(Loc loc, Expression *e, Declaration *v, int hasOverloads)
+	: UnaExp(loc, TOKdotvar, sizeof(DotVarExp), e)
+{
+    //printf("DotVarExp()\n");
+    this->var = v;
+    this->hasOverloads = hasOverloads;
+}
+
+Expression *DotVarExp::semantic(Scope *sc)
+{
+#if LOGSEMANTIC
+    printf("DotVarExp::semantic('%s')\n", toChars());
+#endif
+    if (!type)
+    {
+	var = var->toAlias()->isDeclaration();
+
+	TupleDeclaration *tup = var->isTupleDeclaration();
+	if (tup)
+	{   /* Replace:
+	     *	e1.tuple(a, b, c)
+	     * with:
+	     *	tuple(e1.a, e1.b, e1.c)
+	     */
+	    Expressions *exps = new Expressions;
+
+	    exps->reserve(tup->objects->dim);
+	    for (size_t i = 0; i < tup->objects->dim; i++)
+	    {   Object *o = (Object *)tup->objects->data[i];
+		if (o->dyncast() != DYNCAST_EXPRESSION)
+		{
+		    error("%s is not an expression", o->toChars());
+		}
+		else
+		{
+		    Expression *e = (Expression *)o;
+		    if (e->op != TOKdsymbol)
+			error("%s is not a member", e->toChars());
+		    else
+		    {	DsymbolExp *ve = (DsymbolExp *)e;
+
+			e = new DotVarExp(loc, e1, ve->s->isDeclaration());
+			exps->push(e);
+		    }
+		}
+	    }
+	    Expression *e = new TupleExp(loc, exps);
+	    e = e->semantic(sc);
+	    return e;
+	}
+
+	e1 = e1->semantic(sc);
+	type = var->type;
+	if (!type && global.errors)
+	{   // var is goofed up, just return 0
+	    return new ErrorExp();
+	}
+	assert(type);
+
+	if (!var->isFuncDeclaration())	// for functions, do checks after overload resolution
+	{
+	    Type *t1 = e1->type;
+	    if (t1->ty == Tpointer)
+		t1 = t1->nextOf();
+
+	    type = type->addMod(t1->mod);
+
+	    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);
+
+	    VarDeclaration *v = var->isVarDeclaration();
+	    Expression *e = expandVar(WANTvalue, v);
+	    if (e)
+		return e;
+	}
+    }
+    //printf("-DotVarExp::semantic('%s')\n", toChars());
+    return this;
+}
+
+#if DMDV2
+int DotVarExp::isLvalue()
+{
+    return 1;
+}
+#endif
+
+Expression *DotVarExp::toLvalue(Scope *sc, Expression *e)
+{
+    //printf("DotVarExp::toLvalue(%s)\n", toChars());
+    return this;
+}
+
+Expression *DotVarExp::modifiableLvalue(Scope *sc, Expression *e)
+{
+#if 0
+    printf("DotVarExp::modifiableLvalue(%s)\n", toChars());
+    printf("e1->type = %s\n", e1->type->toChars());
+    printf("var->type = %s\n", var->type->toChars());
+#endif
+
+    if (var->isCtorinit())
+    {	// It's only modifiable if inside the right constructor
+	Dsymbol *s = sc->func;
+	while (1)
+	{
+	    FuncDeclaration *fd = NULL;
+	    if (s)
+		fd = s->isFuncDeclaration();
+	    if (fd &&
+		((fd->isCtorDeclaration() && var->storage_class & STCfield) ||
+		 (fd->isStaticCtorDeclaration() && !(var->storage_class & STCfield))) &&
+		fd->toParent() == var->toParent() &&
+		e1->op == TOKthis
+	       )
+	    {
+		VarDeclaration *v = var->isVarDeclaration();
+		assert(v);
+		v->ctorinit = 1;
+		//printf("setting ctorinit\n");
+	    }
+	    else
+	    {
+		if (s)
+		{   s = s->toParent2();
+		    continue;
+		}
+		else
+		{
+		    const char *p = var->isStatic() ? "static " : "";
+		    error("can only initialize %sconst member %s inside %sconstructor",
+			p, var->toChars(), p);
+		}
+	    }
+	    break;
+	}
+    }
+#if DMDV2
+    else
+    {
+	Type *t1 = e1->type->toBasetype();
+
+	if (!t1->isMutable() ||
+	    (t1->ty == Tpointer && !t1->nextOf()->isMutable()) ||
+	    !var->type->isMutable() ||
+	    !var->type->isAssignable() ||
+	    var->storage_class & STCmanifest
+	   )
+	    error("cannot modify const/immutable expression %s", toChars());
+    }
+#endif
+    return this;
+}
+
+void DotVarExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    expToCBuffer(buf, hgs, e1, PREC_primary);
+    buf->writeByte('.');
+    buf->writestring(var->toChars());
+}
+
+/************************************************************/
+
+/* Things like:
+ *	foo.bar!(args)
+ */
+
+DotTemplateInstanceExp::DotTemplateInstanceExp(Loc loc, Expression *e, TemplateInstance *ti)
+	: UnaExp(loc, TOKdotti, sizeof(DotTemplateInstanceExp), e)
+{
+    //printf("DotTemplateInstanceExp()\n");
+    this->ti = ti;
+}
+
+Expression *DotTemplateInstanceExp::syntaxCopy()
+{
+    DotTemplateInstanceExp *de = new DotTemplateInstanceExp(loc,
+	e1->syntaxCopy(),
+	(TemplateInstance *)ti->syntaxCopy(NULL));
+    return de;
+}
+
+Expression *DotTemplateInstanceExp::semantic(Scope *sc)
+{   Dsymbol *s;
+    Dsymbol *s2;
+    TemplateDeclaration *td;
+    Expression *e;
+    Identifier *id;
+    Type *t1;
+    Expression *eleft = NULL;
+    Expression *eright;
+
+#if LOGSEMANTIC
+    printf("DotTemplateInstanceExp::semantic('%s')\n", toChars());
+#endif
+    //e1->print();
+    //print();
+    e1 = e1->semantic(sc);
+    t1 = e1->type;
+    if (t1)
+	t1 = t1->toBasetype();
+    //t1->print();
+
+    /* Extract the following from e1:
+     *	s: the symbol which ti should be a member of
+     *	eleft: if not NULL, it is the 'this' pointer for ti
+     */
+
+    if (e1->op == TOKdotexp)
+    {	DotExp *de = (DotExp *)e1;
+	eleft = de->e1;
+	eright = de->e2;
+    }
+    else
+    {	eleft = NULL;
+	eright = e1;
+    }
+    if (eright->op == TOKimport)
+    {
+	s = ((ScopeExp *)eright)->sds;
+    }
+    else if (e1->op == TOKtype)
+    {
+	s = t1->isClassHandle();
+	if (!s)
+	{   if (t1->ty == Tstruct)
+		s = ((TypeStruct *)t1)->sym;
+	    else
+		goto L1;
+	}
+    }
+    else if (t1 && (t1->ty == Tstruct || t1->ty == Tclass))
+    {
+	s = t1->toDsymbol(sc);
+	eleft = e1;
+    }
+    else if (t1 && t1->ty == Tpointer)
+    {
+	t1 = ((TypePointer *)t1)->next->toBasetype();
+	if (t1->ty != Tstruct)
+	    goto L1;
+	s = t1->toDsymbol(sc);
+	eleft = e1;
+    }
+    else
+    {
+      L1:
+	error("template %s is not a member of %s", ti->toChars(), e1->toChars());
+	goto Lerr;
+    }
+
+    assert(s);
+    id = ti->name;
+    s2 = s->search(loc, id, 0);
+    if (!s2)
+    {
+	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());
+	goto Lerr;
+    }
+    s = s2;
+    s->semantic(sc);
+    s = s->toAlias();
+    td = s->isTemplateDeclaration();
+    if (!td)
+    {
+	error("%s is not a template", id->toChars());
+	goto Lerr;
+    }
+    if (global.errors)
+	goto Lerr;
+
+    ti->tempdecl = td;
+
+    if (eleft)
+    {	Declaration *v;
+
+	ti->semantic(sc);
+	s = ti->inst->toAlias();
+	v = s->isDeclaration();
+	if (v)
+	{   e = new DotVarExp(loc, eleft, v);
+	    e = e->semantic(sc);
+	    return e;
+	}
+    }
+
+    e = new ScopeExp(loc, ti);
+    if (eleft)
+    {
+	e = new DotExp(loc, eleft, e);
+    }
+    e = e->semantic(sc);
+    return e;
+
+Lerr:
+    return new ErrorExp();
+}
+
+void DotTemplateInstanceExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    expToCBuffer(buf, hgs, e1, PREC_primary);
+    buf->writeByte('.');
+    ti->toCBuffer(buf, hgs);
+}
+
+/************************************************************/
+
+DelegateExp::DelegateExp(Loc loc, Expression *e, FuncDeclaration *f, int hasOverloads)
+	: UnaExp(loc, TOKdelegate, sizeof(DelegateExp), e)
+{
+    this->func = f;
+    this->hasOverloads = hasOverloads;
+}
+
+Expression *DelegateExp::semantic(Scope *sc)
+{
+#if LOGSEMANTIC
+    printf("DelegateExp::semantic('%s')\n", toChars());
+#endif
+    if (!type)
+    {
+	m = sc->module;
+	e1 = e1->semantic(sc);
+    // LDC we need a copy as we store the LLVM tpye in TypeFunction, and delegate/members have different types for 'this'
+	type = new TypeDelegate(func->type->syntaxCopy());
+	type = type->semantic(loc, sc);
+	AggregateDeclaration *ad = func->toParent()->isAggregateDeclaration();
+	if (func->needThis())
+	    e1 = getRightThis(loc, sc, ad, e1, func);
+    }
+    return this;
+}
+
+void DelegateExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    buf->writeByte('&');
+    if (!func->isNested())
+    {
+	expToCBuffer(buf, hgs, e1, PREC_primary);
+	buf->writeByte('.');
+    }
+    buf->writestring(func->toChars());
+}
+
+/************************************************************/
+
+DotTypeExp::DotTypeExp(Loc loc, Expression *e, Dsymbol *s)
+	: UnaExp(loc, TOKdottype, sizeof(DotTypeExp), e)
+{
+    this->sym = s;
+    this->type = s->getType();
+}
+
+Expression *DotTypeExp::semantic(Scope *sc)
+{
+#if LOGSEMANTIC
+    printf("DotTypeExp::semantic('%s')\n", toChars());
+#endif
+    UnaExp::semantic(sc);
+    return this;
+}
+
+void DotTypeExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    expToCBuffer(buf, hgs, e1, PREC_primary);
+    buf->writeByte('.');
+    buf->writestring(sym->toChars());
+}
+
+/************************************************************/
+
+CallExp::CallExp(Loc loc, Expression *e, Expressions *exps)
+	: UnaExp(loc, TOKcall, sizeof(CallExp), e)
+{
+    this->arguments = exps;
+}
+
+CallExp::CallExp(Loc loc, Expression *e)
+	: UnaExp(loc, TOKcall, sizeof(CallExp), e)
+{
+    this->arguments = NULL;
+}
+
+CallExp::CallExp(Loc loc, Expression *e, Expression *earg1)
+	: UnaExp(loc, TOKcall, sizeof(CallExp), e)
+{
+    Expressions *arguments = new Expressions();
+    arguments->setDim(1);
+    arguments->data[0] = (void *)earg1;
+
+    this->arguments = arguments;
+}
+
+CallExp::CallExp(Loc loc, Expression *e, Expression *earg1, Expression *earg2)
+	: UnaExp(loc, TOKcall, sizeof(CallExp), e)
+{
+    Expressions *arguments = new Expressions();
+    arguments->setDim(2);
+    arguments->data[0] = (void *)earg1;
+    arguments->data[1] = (void *)earg2;
+
+    this->arguments = arguments;
+}
+
+Expression *CallExp::syntaxCopy()
+{
+    return new CallExp(loc, e1->syntaxCopy(), arraySyntaxCopy(arguments));
+}
+
+
+Expression *CallExp::semantic(Scope *sc)
+{
+    TypeFunction *tf;
+    FuncDeclaration *f;
+    int i;
+    Type *t1;
+    int istemp;
+    Objects *targsi = NULL;	// initial list of template arguments
+    TemplateInstance *tierror = NULL;
+
+#if LOGSEMANTIC
+    printf("CallExp::semantic() %s\n", toChars());
+#endif
+    if (type)
+	return this;		// semantic() already run
+#if 0
+    if (arguments && arguments->dim)
+    {
+	Expression *earg = (Expression *)arguments->data[0];
+	earg->print();
+	if (earg->type) earg->type->print();
+    }
+#endif
+
+    if (e1->op == TOKdelegate)
+    {	DelegateExp *de = (DelegateExp *)e1;
+
+	e1 = new DotVarExp(de->loc, de->e1, de->func);
+	return semantic(sc);
+    }
+
+    /* Transform:
+     *	array.id(args) into .id(array,args)
+     *	aa.remove(arg) into delete aa[arg]
+     */
+    if (e1->op == TOKdot)
+    {
+	// BUG: we should handle array.a.b.c.e(args) too
+
+	DotIdExp *dotid = (DotIdExp *)(e1);
+	dotid->e1 = dotid->e1->semantic(sc);
+	assert(dotid->e1);
+	if (dotid->e1->type)
+	{
+	    TY e1ty = dotid->e1->type->toBasetype()->ty;
+	    if (e1ty == Taarray && dotid->ident == Id::remove)
+	    {
+		if (!arguments || arguments->dim != 1)
+		{   error("expected key as argument to aa.remove()");
+		    goto Lagain;
+		}
+		Expression *key = (Expression *)arguments->data[0];
+		key = key->semantic(sc);
+		key = resolveProperties(sc, key);
+		key->rvalue();
+
+		TypeAArray *taa = (TypeAArray *)dotid->e1->type->toBasetype();
+		key = key->implicitCastTo(sc, taa->index);
+
+		return new RemoveExp(loc, dotid->e1, key);
+	    }
+	    else if (e1ty == Tarray || e1ty == Tsarray || e1ty == Taarray)
+	    {
+		if (!arguments)
+		    arguments = new Expressions();
+		arguments->shift(dotid->e1);
+#if DMDV2
+		e1 = new DotIdExp(dotid->loc, new IdentifierExp(dotid->loc, Id::empty), dotid->ident);
+#else
+		e1 = new IdentifierExp(dotid->loc, dotid->ident);
+#endif
+	    }
+	}
+    }
+
+#if DMDV2
+    /* This recognizes:
+     *	foo!(tiargs)(funcargs)
+     */
+    if (e1->op == TOKimport && !e1->type)
+    {	ScopeExp *se = (ScopeExp *)e1;
+	TemplateInstance *ti = se->sds->isTemplateInstance();
+	if (ti && !ti->semanticdone)
+	{
+	    /* Attempt to instantiate ti. If that works, go with it.
+	     * If not, go with partial explicit specialization.
+	     */
+	    ti->semanticTiargs(sc);
+	    unsigned errors = global.errors;
+	    global.gag++;
+	    ti->semantic(sc);
+	    global.gag--;
+	    if (errors != global.errors)
+	    {
+		/* Didn't work, go with partial explicit specialization
+		 */
+		global.errors = errors;
+		targsi = ti->tiargs;
+		tierror = ti;			// for error reporting
+		e1 = new IdentifierExp(loc, ti->name);
+	    }
+	}
+    }
+
+    /* This recognizes:
+     *	expr.foo!(tiargs)(funcargs)
+     */
+    if (e1->op == TOKdotti && !e1->type)
+    {	DotTemplateInstanceExp *se = (DotTemplateInstanceExp *)e1;
+	TemplateInstance *ti = se->ti;
+	if (!ti->semanticdone)
+	{
+	    /* Attempt to instantiate ti. If that works, go with it.
+	     * If not, go with partial explicit specialization.
+	     */
+	    ti->semanticTiargs(sc);
+	    Expression *etmp = e1->trySemantic(sc);
+	    if (etmp)
+		e1 = etmp;	// it worked
+	    else		// didn't work
+	    {
+		targsi = ti->tiargs;
+		tierror = ti;		// for error reporting
+		e1 = new DotIdExp(loc, se->e1, ti->name);
+	    }
+	}
+    }
+#endif
+
+    istemp = 0;
+Lagain:
+    //printf("Lagain: %s\n", toChars());
+    f = NULL;
+    if (e1->op == TOKthis || e1->op == TOKsuper)
+    {
+	// semantic() run later for these
+    }
+    else
+    {
+	UnaExp::semantic(sc);
+
+	/* Look for e1 being a lazy parameter
+	 */
+	if (e1->op == TOKvar)
+	{   VarExp *ve = (VarExp *)e1;
+
+	    if (ve->var->storage_class & STClazy)
+	    {
+		TypeFunction *tf = new TypeFunction(NULL, ve->var->type, 0, LINKd);
+		TypeDelegate *t = new TypeDelegate(tf);
+		ve->type = t->semantic(loc, sc);
+	    }
+	}
+
+	if (e1->op == TOKimport)
+	{   // Perhaps this should be moved to ScopeExp::semantic()
+	    ScopeExp *se = (ScopeExp *)e1;
+	    e1 = new DsymbolExp(loc, se->sds);
+	    e1 = e1->semantic(sc);
+	}
+#if 1	// patch for #540 by Oskar Linde
+	else if (e1->op == TOKdotexp)
+	{
+	    DotExp *de = (DotExp *) e1;
+
+	    if (de->e2->op == TOKimport)
+	    {   // This should *really* be moved to ScopeExp::semantic()
+		ScopeExp *se = (ScopeExp *)de->e2;
+		de->e2 = new DsymbolExp(loc, se->sds);
+		de->e2 = de->e2->semantic(sc);
+	    }
+
+	    if (de->e2->op == TOKtemplate)
+	    {   TemplateExp *te = (TemplateExp *) de->e2;
+		e1 = new DotTemplateExp(loc,de->e1,te->td);
+	    }
+	}
+#endif
+    }
+
+    if (e1->op == TOKcomma)
+    {
+	CommaExp *ce = (CommaExp *)e1;
+
+	e1 = ce->e2;
+	e1->type = ce->type;
+	ce->e2 = this;
+	ce->type = NULL;
+	return ce->semantic(sc);
+    }
+
+    t1 = NULL;
+    if (e1->type)
+	t1 = e1->type->toBasetype();
+
+    // Check for call operator overload
+    if (t1)
+    {	AggregateDeclaration *ad;
+
+	if (t1->ty == Tstruct)
+	{
+	    ad = ((TypeStruct *)t1)->sym;
+
+	    // First look for constructor
+	    if (ad->ctor && arguments && arguments->dim)
+	    {
+		// Create variable that will get constructed
+		Identifier *idtmp = Lexer::uniqueId("__ctmp");
+		VarDeclaration *tmp = new VarDeclaration(loc, t1, idtmp, NULL);
+		Expression *av = new DeclarationExp(loc, tmp);
+		av = new CommaExp(loc, av, new VarExp(loc, tmp));
+
+		Expression *e;
+		CtorDeclaration *cf = ad->ctor->isCtorDeclaration();
+		if (cf)
+		    e = new DotVarExp(loc, av, cf, 1);
+		else
+		{   TemplateDeclaration *td = ad->ctor->isTemplateDeclaration();
+		    assert(td);
+		    e = new DotTemplateExp(loc, av, td);
+		}
+		e = new CallExp(loc, e, arguments);
+#if !STRUCTTHISREF
+		/* Constructors return a pointer to the instance
+		 */
+		e = new PtrExp(loc, e);
+#endif
+		e = e->semantic(sc);
+		return e;
+	    }
+
+	    // No constructor, look for overload of opCall
+	    if (search_function(ad, Id::call))
+		goto L1;	// overload of opCall, therefore it's a call
+
+	    if (e1->op != TOKtype)
+		error("%s %s does not overload ()", ad->kind(), ad->toChars());
+	    /* It's a struct literal
+	     */
+	    Expression *e = new StructLiteralExp(loc, (StructDeclaration *)ad, arguments);
+	    e = e->semantic(sc);
+	    e->type = e1->type;		// in case e1->type was a typedef
+	    return e;
+	}
+	else if (t1->ty == Tclass)
+	{
+	    ad = ((TypeClass *)t1)->sym;
+	    goto L1;
+	L1:
+	    // Rewrite as e1.call(arguments)
+	    Expression *e = new DotIdExp(loc, e1, Id::call);
+	    e = new CallExp(loc, e, arguments);
+	    e = e->semantic(sc);
+	    return e;
+	}
+    }
+
+    arrayExpressionSemantic(arguments, sc);
+    preFunctionArguments(loc, sc, arguments);
+
+    if (e1->op == TOKdotvar && t1->ty == Tfunction ||
+        e1->op == TOKdottd)
+    {
+	DotVarExp *dve;
+	DotTemplateExp *dte;
+	AggregateDeclaration *ad;
+	UnaExp *ue = (UnaExp *)(e1);
+
+    	if (e1->op == TOKdotvar)
+        {   // Do overload resolution
+	    dve = (DotVarExp *)(e1);
+
+	    f = dve->var->isFuncDeclaration();
+	    assert(f);
+	    f = f->overloadResolve(loc, ue->e1, arguments);
+
+	    ad = f->toParent()->isAggregateDeclaration();
+	}
+        else
+        {   dte = (DotTemplateExp *)(e1);
+	    TemplateDeclaration *td = dte->td;
+	    assert(td);
+	    if (!arguments)
+		// Should fix deduceFunctionTemplate() so it works on NULL argument
+		arguments = new Expressions();
+	    f = td->deduceFunctionTemplate(sc, loc, targsi, ue->e1, arguments);
+	    if (!f)
+	    {	type = Type::terror;
+		return this;
+	    }
+	    ad = td->toParent()->isAggregateDeclaration();
+	}	
+	if (f->needThis())
+	{
+	    ue->e1 = getRightThis(loc, sc, ad, ue->e1, f);
+	}
+
+	/* Cannot call public functions from inside invariant
+	 * (because then the invariant would have infinite recursion)
+	 */
+	if (sc->func && sc->func->isInvariantDeclaration() &&
+	    ue->e1->op == TOKthis &&
+	    f->addPostInvariant()
+	   )
+	{
+	    error("cannot call public/export function %s from immutable", f->toChars());
+	}
+
+	checkDeprecated(sc, f);
+#if DMDV2
+	checkPurity(sc, f);
+#endif
+	accessCheck(loc, sc, ue->e1, f);
+	if (!f->needThis())
+	{
+	    VarExp *ve = new VarExp(loc, f);
+	    e1 = new CommaExp(loc, ue->e1, ve);
+	    e1->type = f->type;
+	}
+	else
+	{
+	    if (e1->op == TOKdotvar)		
+		dve->var = f;
+	    else
+		e1 = new DotVarExp(loc, dte->e1, f);
+	    e1->type = f->type;
+#if 0
+	    printf("ue->e1 = %s\n", ue->e1->toChars());
+	    printf("f = %s\n", f->toChars());
+	    printf("t = %s\n", t->toChars());
+	    printf("e1 = %s\n", e1->toChars());
+	    printf("e1->type = %s\n", e1->type->toChars());
+#endif
+	    // Const member function can take const/immutable/mutable this
+	    if (!(f->type->isConst()))
+	    {
+		// Check for const/immutable compatibility
+		Type *tthis = ue->e1->type->toBasetype();
+		if (tthis->ty == Tpointer)
+		    tthis = tthis->nextOf()->toBasetype();
+		if (f->type->isInvariant())
+		{
+		    if (tthis->mod != MODinvariant)
+			error("%s can only be called on an invariant object", e1->toChars());
+		}
+		else
+		{
+		    if (tthis->mod != 0)
+		    {	//printf("mod = %x\n", tthis->mod);
+			error("%s can only be called on a mutable object, not %s", e1->toChars(), tthis->toChars());
+		    }
+		}
+
+		/* Cannot call mutable method on a final struct
+		 */
+		if (tthis->ty == Tstruct &&
+		    ue->e1->op == TOKvar)
+		{   VarExp *v = (VarExp *)ue->e1;
+		    if (v->var->storage_class & STCfinal)
+			error("cannot call mutable method on final struct");
+		}
+	    }
+
+	    // See if we need to adjust the 'this' pointer
+	    AggregateDeclaration *ad = f->isThis();
+	    ClassDeclaration *cd = ue->e1->type->isClassHandle();
+	    if (ad && cd && ad->isClassDeclaration() && ad != cd &&
+		ue->e1->op != TOKsuper)
+	    {
+		ue->e1 = ue->e1->castTo(sc, ad->type); //new CastExp(loc, ue->e1, ad->type);
+		ue->e1 = ue->e1->semantic(sc);
+	    }
+	}
+	t1 = e1->type;
+    }
+    else if (e1->op == TOKsuper)
+    {
+	// Base class constructor call
+	ClassDeclaration *cd = NULL;
+
+	if (sc->func)
+	    cd = sc->func->toParent()->isClassDeclaration();
+	if (!cd || !cd->baseClass || !sc->func->isCtorDeclaration())
+	{
+	    error("super class constructor call must be in a constructor");
+	    type = Type::terror;
+	    return this;
+	}
+	else
+	{
+	    if (!cd->baseClass->ctor)
+	    {	error("no super class constructor for %s", cd->baseClass->toChars());
+		type = Type::terror;
+		return this;
+	    }
+	    else
+	    {
+		if (!sc->intypeof)
+		{
+#if 0
+		    if (sc->callSuper & (CSXthis | CSXsuper))
+			error("reference to this before super()");
+#endif
+		    if (sc->noctor || sc->callSuper & CSXlabel)
+			error("constructor calls not allowed in loops or after labels");
+		    if (sc->callSuper & (CSXsuper_ctor | CSXthis_ctor))
+			error("multiple constructor calls");
+		    sc->callSuper |= CSXany_ctor | CSXsuper_ctor;
+		}
+
+		f = resolveFuncCall(sc, loc, cd->baseClass->ctor, NULL, NULL, arguments, 0);
+		checkDeprecated(sc, f);
+#if DMDV2
+		checkPurity(sc, f);
+#endif
+		e1 = new DotVarExp(e1->loc, e1, f);
+		e1 = e1->semantic(sc);
+		t1 = e1->type;
+	    }
+	}
+    }
+    else if (e1->op == TOKthis)
+    {
+	// same class constructor call
+	AggregateDeclaration *cd = NULL;
+
+	if (sc->func)
+	    cd = sc->func->toParent()->isAggregateDeclaration();
+	if (!cd || !sc->func->isCtorDeclaration())
+	{
+	    error("constructor call must be in a constructor");
+	    type = Type::terror;
+	    return this;
+	}
+	else
+	{
+	    if (!sc->intypeof)
+	    {
+#if 0
+		if (sc->callSuper & (CSXthis | CSXsuper))
+		    error("reference to this before super()");
+#endif
+		if (sc->noctor || sc->callSuper & CSXlabel)
+		    error("constructor calls not allowed in loops or after labels");
+		if (sc->callSuper & (CSXsuper_ctor | CSXthis_ctor))
+		    error("multiple constructor calls");
+		sc->callSuper |= CSXany_ctor | CSXthis_ctor;
+	    }
+
+	    f = resolveFuncCall(sc, loc, cd->ctor, NULL, NULL, arguments, 0);
+	    checkDeprecated(sc, f);
+#if DMDV2
+	    checkPurity(sc, f);
+#endif
+	    e1 = new DotVarExp(e1->loc, e1, f);
+	    e1 = e1->semantic(sc);
+	    t1 = e1->type;
+
+	    // BUG: this should really be done by checking the static
+	    // call graph
+	    if (f == sc->func)
+		error("cyclic constructor call");
+	}
+    }
+    else if (e1->op == TOKoverloadset)
+    {
+	OverExp *eo = (OverExp *)e1;
+	FuncDeclaration *f = NULL;
+	for (int i = 0; i < eo->vars->a.dim; i++)
+	{   Dsymbol *s = (Dsymbol *)eo->vars->a.data[i];
+	    FuncDeclaration *f2 = s->isFuncDeclaration();
+	    if (f2)
+	    {
+		f2 = f2->overloadResolve(loc, NULL, arguments, 1);
+	    }
+	    else
+	    {	TemplateDeclaration *td = s->isTemplateDeclaration();
+		assert(td);
+		f2 = td->deduceFunctionTemplate(sc, loc, targsi, NULL, arguments, 1);
+	    }
+	    if (f2)
+	    {	if (f)
+		    /* Error if match in more than one overload set,
+		     * even if one is a 'better' match than the other.
+		     */
+		    ScopeDsymbol::multiplyDefined(loc, f, f2);
+		else
+		    f = f2;
+	    }
+	}
+	if (!f)
+	{   /* No overload matches, just set f and rely on error
+	     * message being generated later.
+	     */
+	    f = (FuncDeclaration *)eo->vars->a.data[0];
+	}
+	e1 = new VarExp(loc, f);
+	goto Lagain;
+    }
+    else if (!t1)
+    {
+	error("function expected before (), not '%s'", e1->toChars());
+	type = Type::terror;
+	return this;
+    }
+    else if (t1->ty != Tfunction)
+    {
+	if (t1->ty == Tdelegate)
+	{   TypeDelegate *td = (TypeDelegate *)t1;
+	    assert(td->next->ty == Tfunction);
+	    tf = (TypeFunction *)(td->next);
+	    if (sc->func && sc->func->isPure() && !tf->ispure)
+	    {
+		error("pure function '%s' cannot call impure delegate '%s'", sc->func->toChars(), e1->toChars());
+	    }
+	    goto Lcheckargs;
+	}
+	else if (t1->ty == Tpointer && ((TypePointer *)t1)->next->ty == Tfunction)
+	{   Expression *e;
+
+	    e = new PtrExp(loc, e1);
+	    t1 = ((TypePointer *)t1)->next;
+	    if (sc->func && sc->func->isPure() && !((TypeFunction *)t1)->ispure)
+	    {
+		error("pure function '%s' cannot call impure function pointer '%s'", sc->func->toChars(), e1->toChars());
+	    }
+	    e->type = t1;
+	    e1 = e;
+	}
+	else if (e1->op == TOKtemplate)
+	{
+	    TemplateExp *te = (TemplateExp *)e1;
+	    f = te->td->deduceFunctionTemplate(sc, loc, targsi, NULL, arguments);
+	    if (!f)
+	    {	if (tierror)
+		    tierror->error("errors instantiating template");	// give better error message
+		type = Type::terror;
+		return this;
+	    }
+	    if (f->needThis() && hasThis(sc))
+	    {
+		// Supply an implicit 'this', as in
+		//	  this.ident
+
+		e1 = new DotTemplateExp(loc, (new ThisExp(loc))->semantic(sc), te->td);
+		goto Lagain;
+	    }
+
+	    e1 = new VarExp(loc, f);
+	    goto Lagain;
+	}
+	else
+	{   error("function expected before (), not %s of type %s", e1->toChars(), e1->type->toChars());
+	    type = Type::terror;
+	    return this;
+	}
+    }
+    else if (e1->op == TOKvar)
+    {
+	// Do overload resolution
+	VarExp *ve = (VarExp *)e1;
+
+	f = ve->var->isFuncDeclaration();
+	assert(f);
+
+	if (ve->hasOverloads)
+	    f = f->overloadResolve(loc, NULL, arguments);
+	checkDeprecated(sc, f);
+#if DMDV2
+	checkPurity(sc, f);
+#endif
+
+	if (f->needThis() && hasThis(sc))
+	{
+	    // Supply an implicit 'this', as in
+	    //	  this.ident
+
+	    e1 = new DotVarExp(loc, new ThisExp(loc), f);
+	    goto Lagain;
+	}
+
+	accessCheck(loc, sc, NULL, f);
+
+	ve->var = f;
+//	ve->hasOverloads = 0;
+	ve->type = f->type;
+	t1 = f->type;
+    }
+    assert(t1->ty == Tfunction);
+    tf = (TypeFunction *)(t1);
+
+Lcheckargs:
+    assert(tf->ty == Tfunction);
+    type = tf->next;
+
+    if (!arguments)
+	arguments = new Expressions();
+    functionArguments(loc, sc, tf, arguments);
+
+    if (!type)
+    {
+	error("forward reference to inferred return type of function call %s", toChars());
+	type = Type::terror;
+    }
+
+    if (f && f->tintro)
+    {
+	Type *t = type;
+	int offset = 0;
+	TypeFunction *tf = (TypeFunction *)f->tintro;
+
+	if (tf->next->isBaseOf(t, &offset) && offset)
+	{
+	    type = tf->next;
+	    return castTo(sc, t);
+	}
+    }
+
+    return this;
+}
+
+int CallExp::checkSideEffect(int flag)
+{
+#if DMDV2
+    if (flag != 2)
+	return 1;
+
+    if (e1->checkSideEffect(2))
+	return 1;
+
+    /* If any of the arguments have side effects, this expression does
+     */
+    for (size_t i = 0; i < arguments->dim; i++)
+    {   Expression *e = (Expression *)arguments->data[i];
+
+	if (e->checkSideEffect(2))
+	    return 1;
+    }
+
+    /* If calling a function or delegate that is typed as pure,
+     * then this expression has no side effects.
+     */
+    Type *t = e1->type->toBasetype();
+    if (t->ty == Tfunction && ((TypeFunction *)t)->ispure)
+	return 0;
+    if (t->ty == Tdelegate && ((TypeFunction *)((TypeDelegate *)t)->next)->ispure)
+	return 0;
+#endif
+    return 1;
+}
+
+#if DMDV2
+int CallExp::canThrow()
+{
+    //printf("CallExp::canThrow() %s\n", toChars());
+    if (e1->canThrow())
+	return 1;
+
+    /* If any of the arguments can throw, then this expression can throw
+     */
+    for (size_t i = 0; i < arguments->dim; i++)
+    {   Expression *e = (Expression *)arguments->data[i];
+
+	if (e && e->canThrow())
+	    return 1;
+    }
+
+    if (global.errors && !e1->type)
+	return 0;			// error recovery
+
+    /* If calling a function or delegate that is typed as nothrow,
+     * then this expression cannot throw.
+     * Note that pure functions can throw.
+     */
+    Type *t = e1->type->toBasetype();
+    if (t->ty == Tfunction && ((TypeFunction *)t)->isnothrow)
+	return 0;
+    if (t->ty == Tdelegate && ((TypeFunction *)((TypeDelegate *)t)->next)->isnothrow)
+	return 0;
+
+    return 1;
+}
+#endif
+
+#if DMDV2
+int CallExp::isLvalue()
+{
+//    if (type->toBasetype()->ty == Tstruct)
+//	return 1;
+    Type *tb = e1->type->toBasetype();
+    if (tb->ty == Tfunction && ((TypeFunction *)tb)->isref)
+	return 1;		// function returns a reference
+    return 0;
+}
+#endif
+
+Expression *CallExp::toLvalue(Scope *sc, Expression *e)
+{
+    if (isLvalue())
+	return this;
+    return Expression::toLvalue(sc, e);
+}
+
+void CallExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{   int i;
+
+    expToCBuffer(buf, hgs, e1, precedence[op]);
+    buf->writeByte('(');
+    argsToCBuffer(buf, arguments, hgs);
+    buf->writeByte(')');
+}
+
+
+/************************************************************/
+
+AddrExp::AddrExp(Loc loc, Expression *e)
+	: UnaExp(loc, TOKaddress, sizeof(AddrExp), e)
+{
+    m = NULL;
+}
+
+Expression *AddrExp::semantic(Scope *sc)
+{
+#if LOGSEMANTIC
+    printf("AddrExp::semantic('%s')\n", toChars());
+#endif
+    if (!type)
+    {
+	m = sc->module;
+	UnaExp::semantic(sc);
+	e1 = e1->toLvalue(sc, NULL);
+	if (!e1->type)
+	{
+	    error("cannot take address of %s", e1->toChars());
+	    type = Type::tint32;
+	    return this;
+	}
+	type = e1->type->pointerTo();
+
+	// See if this should really be a delegate
+	if (e1->op == TOKdotvar)
+	{
+	    DotVarExp *dve = (DotVarExp *)e1;
+	    FuncDeclaration *f = dve->var->isFuncDeclaration();
+
+	    if (f)
+	    {
+		if (!dve->hasOverloads)
+		    f->tookAddressOf++;
+		Expression *e = new DelegateExp(loc, dve->e1, f, dve->hasOverloads);
+		e = e->semantic(sc);
+		return e;
+	    }
+	}
+	else if (e1->op == TOKvar)
+	{
+	    VarExp *ve = (VarExp *)e1;
+
+	    VarDeclaration *v = ve->var->isVarDeclaration();
+	    if (v && !v->canTakeAddressOf())
+		error("cannot take address of %s", e1->toChars());
+
+	    FuncDeclaration *f = ve->var->isFuncDeclaration();
+
+	    if (f)
+	    {
+		if (!ve->hasOverloads ||
+		    /* Because nested functions cannot be overloaded,
+		     * mark here that we took its address because castTo()
+		     * may not be called with an exact match.
+		     */
+		    f->toParent2()->isFuncDeclaration())
+		    f->tookAddressOf++;
+		if (f->isNested())
+		{
+		    Expression *e = new DelegateExp(loc, e1, f, ve->hasOverloads);
+		    e = e->semantic(sc);
+		    return e;
+		}
+		if (f->needThis() && hasThis(sc))
+		{
+		    /* Should probably supply 'this' after overload resolution,
+		     * not before.
+		     */
+		    Expression *ethis = new ThisExp(loc);
+		    Expression *e = new DelegateExp(loc, ethis, f, ve->hasOverloads);
+		    e = e->semantic(sc);
+		    return e;
+		}
+	    }
+	}
+	return optimize(WANTvalue);
+    }
+    return this;
+}
+
+/************************************************************/
+
+PtrExp::PtrExp(Loc loc, Expression *e)
+	: UnaExp(loc, TOKstar, sizeof(PtrExp), e)
+{
+    if (e->type)
+	type = ((TypePointer *)e->type)->next;
+}
+
+PtrExp::PtrExp(Loc loc, Expression *e, Type *t)
+	: UnaExp(loc, TOKstar, sizeof(PtrExp), e)
+{
+    type = t;
+}
+
+Expression *PtrExp::semantic(Scope *sc)
+{   Type *tb;
+
+#if LOGSEMANTIC
+    printf("PtrExp::semantic('%s')\n", toChars());
+#endif
+    if (!type)
+    {
+	UnaExp::semantic(sc);
+	e1 = resolveProperties(sc, e1);
+	if (!e1->type)
+	    printf("PtrExp::semantic('%s')\n", toChars());
+	Expression *e = op_overload(sc);
+	if (e)
+	    return e;
+	tb = e1->type->toBasetype();
+	switch (tb->ty)
+	{
+	    case Tpointer:
+		type = ((TypePointer *)tb)->next;
+		break;
+
+	    case Tsarray:
+	    case Tarray:
+		type = ((TypeArray *)tb)->next;
+		e1 = e1->castTo(sc, type->pointerTo());
+		break;
+
+	    default:
+		error("can only * a pointer, not a '%s'", e1->type->toChars());
+		type = Type::tint32;
+		break;
+	}
+	rvalue();
+    }
+    return this;
+}
+
+#if DMDV2
+int PtrExp::isLvalue()
+{
+    return 1;
+}
+#endif
+
+Expression *PtrExp::toLvalue(Scope *sc, Expression *e)
+{
+#if 0
+    tym = tybasic(e1->ET->Tty);
+    if (!(tyscalar(tym) ||
+	  tym == TYstruct ||
+	  tym == TYarray && e->Eoper == TOKaddr))
+	    synerr(EM_lvalue);	// lvalue expected
+#endif
+    return this;
+}
+
+#if DMDV2
+Expression *PtrExp::modifiableLvalue(Scope *sc, Expression *e)
+{
+    //printf("PtrExp::modifiableLvalue() %s, type %s\n", toChars(), type->toChars());
+
+    if (e1->op == TOKsymoff)
+    {	SymOffExp *se = (SymOffExp *)e1;
+	se->var->checkModify(loc, sc, type);
+	//return toLvalue(sc, e);
+    }
+
+    return Expression::modifiableLvalue(sc, e);
+}
+#endif
+
+void PtrExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    buf->writeByte('*');
+    expToCBuffer(buf, hgs, e1, precedence[op]);
+}
+
+/************************************************************/
+
+NegExp::NegExp(Loc loc, Expression *e)
+	: UnaExp(loc, TOKneg, sizeof(NegExp), e)
+{
+}
+
+Expression *NegExp::semantic(Scope *sc)
+{   Expression *e;
+
+#if LOGSEMANTIC
+    printf("NegExp::semantic('%s')\n", toChars());
+#endif
+    if (!type)
+    {
+	UnaExp::semantic(sc);
+	e1 = resolveProperties(sc, e1);
+	e = op_overload(sc);
+	if (e)
+	    return e;
+
+	e1->checkNoBool();
+	if (e1->op != TOKslice)
+	    e1->checkArithmetic();
+	type = e1->type;
+    }
+    return this;
+}
+
+/************************************************************/
+
+UAddExp::UAddExp(Loc loc, Expression *e)
+	: UnaExp(loc, TOKuadd, sizeof(UAddExp), e)
+{
+}
+
+Expression *UAddExp::semantic(Scope *sc)
+{   Expression *e;
+
+#if LOGSEMANTIC
+    printf("UAddExp::semantic('%s')\n", toChars());
+#endif
+    assert(!type);
+    UnaExp::semantic(sc);
+    e1 = resolveProperties(sc, e1);
+    e = op_overload(sc);
+    if (e)
+	return e;
+    e1->checkNoBool();
+    e1->checkArithmetic();
+    return e1;
+}
+
+/************************************************************/
+
+ComExp::ComExp(Loc loc, Expression *e)
+	: UnaExp(loc, TOKtilde, sizeof(ComExp), e)
+{
+}
+
+Expression *ComExp::semantic(Scope *sc)
+{   Expression *e;
+
+    if (!type)
+    {
+	UnaExp::semantic(sc);
+	e1 = resolveProperties(sc, e1);
+	e = op_overload(sc);
+	if (e)
+	    return e;
+
+	e1->checkNoBool();
+	if (e1->op != TOKslice)
+	    e1 = e1->checkIntegral();
+	type = e1->type;
+    }
+    return this;
+}
+
+/************************************************************/
+
+NotExp::NotExp(Loc loc, Expression *e)
+	: UnaExp(loc, TOKnot, sizeof(NotExp), e)
+{
+}
+
+Expression *NotExp::semantic(Scope *sc)
+{
+    UnaExp::semantic(sc);
+    e1 = resolveProperties(sc, e1);
+    e1 = e1->checkToBoolean();
+    type = Type::tboolean;
+    return this;
+}
+
+int NotExp::isBit()
+{
+    return TRUE;
+}
+
+
+
+/************************************************************/
+
+BoolExp::BoolExp(Loc loc, Expression *e, Type *t)
+	: UnaExp(loc, TOKtobool, sizeof(BoolExp), e)
+{
+    type = t;
+}
+
+Expression *BoolExp::semantic(Scope *sc)
+{
+    UnaExp::semantic(sc);
+    e1 = resolveProperties(sc, e1);
+    e1 = e1->checkToBoolean();
+    type = Type::tboolean;
+    return this;
+}
+
+int BoolExp::isBit()
+{
+    return TRUE;
+}
+
+/************************************************************/
+
+DeleteExp::DeleteExp(Loc loc, Expression *e)
+	: UnaExp(loc, TOKdelete, sizeof(DeleteExp), e)
+{
+}
+
+Expression *DeleteExp::semantic(Scope *sc)
+{
+    Type *tb;
+
+    UnaExp::semantic(sc);
+    e1 = resolveProperties(sc, e1);
+    e1 = e1->toLvalue(sc, NULL);
+    type = Type::tvoid;
+
+    tb = e1->type->toBasetype();
+    switch (tb->ty)
+    {	case Tclass:
+	{   TypeClass *tc = (TypeClass *)tb;
+	    ClassDeclaration *cd = tc->sym;
+
+	    if (cd->isCOMinterface())
+	    {	/* Because COM classes are deleted by IUnknown.Release()
+		 */
+		error("cannot delete instance of COM interface %s", cd->toChars());
+	    }
+	    break;
+	}
+	case Tpointer:
+	    tb = ((TypePointer *)tb)->next->toBasetype();
+	    if (tb->ty == Tstruct)
+	    {
+		TypeStruct *ts = (TypeStruct *)tb;
+		StructDeclaration *sd = ts->sym;
+		FuncDeclaration *f = sd->aggDelete;
+		FuncDeclaration *fd = sd->dtor;
+
+		if (!f && !fd)
+		    break;
+
+		/* Construct:
+		 *	ea = copy e1 to a tmp to do side effects only once
+		 *	eb = call destructor
+		 *	ec = call deallocator
+		 */
+		Expression *ea = NULL;
+		Expression *eb = NULL;
+		Expression *ec = NULL;
+		VarDeclaration *v;
+
+		if (fd && f)
+		{   Identifier *id = Lexer::idPool("__tmp");
+		    v = new VarDeclaration(loc, e1->type, id, new ExpInitializer(loc, e1));
+		    v->semantic(sc);
+		    v->parent = sc->parent;
+		    ea = new DeclarationExp(loc, v);
+		    ea->type = v->type;
+		}
+
+		if (fd)
+		{   Expression *e = ea ? new VarExp(loc, v) : e1;
+		    e = new DotVarExp(0, e, fd, 0);
+		    eb = new CallExp(loc, e);
+		    eb = eb->semantic(sc);
+		}
+
+		if (f)
+		{
+		    Type *tpv = Type::tvoid->pointerTo();
+		    Expression *e = ea ? new VarExp(loc, v) : e1->castTo(sc, tpv);
+		    e = new CallExp(loc, new VarExp(loc, f), e);
+		    ec = e->semantic(sc);
+		}
+		ea = combine(ea, eb);
+		ea = combine(ea, ec);
+		assert(ea);
+		return ea;
+	    }
+	    break;
+
+	case Tarray:
+	    /* BUG: look for deleting arrays of structs with dtors.
+	     */
+	    break;
+
+	default:
+	    if (e1->op == TOKindex)
+	    {
+		IndexExp *ae = (IndexExp *)(e1);
+		Type *tb1 = ae->e1->type->toBasetype();
+		if (tb1->ty == Taarray)
+		    break;
+	    }
+	    error("cannot delete type %s", e1->type->toChars());
+	    break;
+    }
+
+    if (e1->op == TOKindex)
+    {
+	IndexExp *ae = (IndexExp *)(e1);
+	Type *tb1 = ae->e1->type->toBasetype();
+	if (tb1->ty == Taarray)
+	{   if (!global.params.useDeprecated)
+		error("delete aa[key] deprecated, use aa.remove(key)");
+	}
+    }
+
+    return this;
+}
+
+int DeleteExp::checkSideEffect(int flag)
+{
+    return 1;
+}
+
+Expression *DeleteExp::checkToBoolean()
+{
+    error("delete does not give a boolean result");
+    return this;
+}
+
+void DeleteExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    buf->writestring("delete ");
+    expToCBuffer(buf, hgs, e1, precedence[op]);
+}
+
+/************************************************************/
+
+CastExp::CastExp(Loc loc, Expression *e, Type *t)
+	: UnaExp(loc, TOKcast, sizeof(CastExp), e)
+{
+    to = t;
+    this->mod = ~0;
+}
+
+#if DMDV2
+/* For cast(const) and cast(immutable)
+ */
+CastExp::CastExp(Loc loc, Expression *e, unsigned mod)
+	: UnaExp(loc, TOKcast, sizeof(CastExp), e)
+{
+    to = NULL;
+    this->mod = mod;
+}
+#endif
+
+Expression *CastExp::syntaxCopy()
+{
+    return to ? new CastExp(loc, e1->syntaxCopy(), to->syntaxCopy())
+	      : new CastExp(loc, e1->syntaxCopy(), mod);
+}
+
+
+Expression *CastExp::semantic(Scope *sc)
+{   Expression *e;
+    BinExp *b;
+    UnaExp *u;
+
+#if LOGSEMANTIC
+    printf("CastExp::semantic('%s')\n", toChars());
+#endif
+
+//static int x; assert(++x < 10);
+
+    if (type)
+	return this;
+    UnaExp::semantic(sc);
+    if (e1->type)		// if not a tuple
+    {
+	e1 = resolveProperties(sc, e1);
+
+	if (!to)
+	{
+	    /* Handle cast(const) and cast(immutable), etc.
+	     */
+	    to = e1->type->castMod(mod);
+	}
+	else
+	    to = to->semantic(loc, sc);
+
+	if (!to->equals(e1->type))
+	{
+	    e = op_overload(sc);
+	    if (e)
+	    {
+		return e->implicitCastTo(sc, to);
+	    }
+	}
+
+	Type *t1b = e1->type->toBasetype();
+	Type *tob = to->toBasetype();
+	if (tob->ty == Tstruct &&
+	    !tob->equals(t1b) &&
+	    ((TypeStruct *)tob)->sym->search(0, Id::call, 0)
+	   )
+	{
+	    /* Look to replace:
+	     *	cast(S)t
+	     * with:
+	     *	S(t)
+	     */
+
+	    // Rewrite as to.call(e1)
+	    e = new TypeExp(loc, to);
+	    e = new DotIdExp(loc, e, Id::call);
+	    e = new CallExp(loc, e, e1);
+	    e = e->semantic(sc);
+	    return e;
+	}
+    }
+    else if (!to)
+    {	error("cannot cast tuple");
+	to = Type::terror;
+    }
+
+    if (global.params.safe && !sc->module->safe && !sc->intypeof)
+    {	// Disallow unsafe casts
+	Type *tob = to->toBasetype();
+	Type *t1b = e1->type->toBasetype();
+	if (!t1b->isMutable() && tob->isMutable())
+	{   // Cast not mutable to mutable
+	  Lunsafe:
+	    error("cast from %s to %s not allowed in safe mode", e1->type->toChars(), to->toChars());
+	}
+	else if (t1b->isShared() && !tob->isShared())
+	    // Cast away shared
+	    goto Lunsafe;
+	else if (tob->ty == Tpointer)
+	{   if (t1b->ty != Tpointer)
+		goto Lunsafe;
+	    Type *tobn = tob->nextOf()->toBasetype();
+	    Type *t1bn = t1b->nextOf()->toBasetype();
+
+	    if (!t1bn->isMutable() && tobn->isMutable())
+		// Cast away pointer to not mutable
+		goto Lunsafe;
+
+	    if (t1bn->isShared() && !tobn->isShared())
+		// Cast away pointer to shared
+		goto Lunsafe;
+
+	    if (tobn->isTypeBasic() && tobn->size() < t1bn->size())
+		// Allow things like casting a long* to an int*
+		;
+	    else if (tobn->ty != Tvoid)
+		// Cast to a pointer other than void*
+		goto Lunsafe;
+	}
+
+	// BUG: Check for casting array types, such as void[] to int*[]
+    }
+
+    e = e1->castTo(sc, to);
+    return e;
+}
+
+int CastExp::checkSideEffect(int flag)
+{
+    /* if not:
+     *  cast(void)
+     *  cast(classtype)func()
+     */
+    if (!to->equals(Type::tvoid) &&
+	!(to->ty == Tclass && e1->op == TOKcall && e1->type->ty == Tclass))
+	return Expression::checkSideEffect(flag);
+    return 1;
+}
+
+void CastExp::checkEscape()
+{   Type *tb = type->toBasetype();
+    if (tb->ty == Tarray && e1->op == TOKvar &&
+	e1->type->toBasetype()->ty == Tsarray)
+    {	VarExp *ve = (VarExp *)e1;
+	VarDeclaration *v = ve->var->isVarDeclaration();
+	if (v)
+	{
+	    if (!v->isDataseg() && !v->isParameter())
+		error("escaping reference to local %s", v->toChars());
+	}
+    }
+}
+
+void CastExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    buf->writestring("cast(");
+#if DMDV1
+    to->toCBuffer(buf, NULL, hgs);
+#else
+    if (to)
+	to->toCBuffer(buf, NULL, hgs);
+    else
+    {
+	switch (mod)
+	{   case 0:
+		break;
+	    case MODconst:
+		buf->writestring(Token::tochars[TOKconst]);
+		break;
+	    case MODinvariant:
+		buf->writestring(Token::tochars[TOKimmutable]);
+		break;
+	    case MODshared:
+		buf->writestring(Token::tochars[TOKshared]);
+		break;
+	    case MODshared | MODconst:
+		buf->writestring(Token::tochars[TOKshared]);
+		buf->writeByte(' ');
+		buf->writestring(Token::tochars[TOKconst]);
+		break;
+	    default:
+		assert(0);
+	}
+    }
+#endif
+    buf->writeByte(')');
+    expToCBuffer(buf, hgs, e1, precedence[op]);
+}
+
+
+/************************************************************/
+
+SliceExp::SliceExp(Loc loc, Expression *e1, Expression *lwr, Expression *upr)
+	: UnaExp(loc, TOKslice, sizeof(SliceExp), e1)
+{
+    this->upr = upr;
+    this->lwr = lwr;
+    lengthVar = NULL;
+}
+
+Expression *SliceExp::syntaxCopy()
+{
+    Expression *lwr = NULL;
+    if (this->lwr)
+	lwr = this->lwr->syntaxCopy();
+
+    Expression *upr = NULL;
+    if (this->upr)
+	upr = this->upr->syntaxCopy();
+
+    return new SliceExp(loc, e1->syntaxCopy(), lwr, upr);
+}
+
+Expression *SliceExp::semantic(Scope *sc)
+{   Expression *e;
+    AggregateDeclaration *ad;
+    //FuncDeclaration *fd;
+    ScopeDsymbol *sym;
+
+#if LOGSEMANTIC
+    printf("SliceExp::semantic('%s')\n", toChars());
+#endif
+    if (type)
+	return this;
+
+    UnaExp::semantic(sc);
+    e1 = resolveProperties(sc, e1);
+
+    e = this;
+
+    Type *t = e1->type->toBasetype();
+    if (t->ty == Tpointer)
+    {
+	if (!lwr || !upr)
+	    error("need upper and lower bound to slice pointer");
+    }
+    else if (t->ty == Tarray)
+    {
+    }
+    else if (t->ty == Tsarray)
+    {
+    }
+    else if (t->ty == Tclass)
+    {
+        ad = ((TypeClass *)t)->sym;
+        goto L1;
+    }
+    else if (t->ty == Tstruct)
+    {
+        ad = ((TypeStruct *)t)->sym;
+
+    L1:
+	if (search_function(ad, Id::slice))
+        {
+            // Rewrite as e1.slice(lwr, upr)
+	    e = new DotIdExp(loc, e1, Id::slice);
+
+	    if (lwr)
+	    {
+		assert(upr);
+		e = new CallExp(loc, e, lwr, upr);
+	    }
+	    else
+	    {	assert(!upr);
+		e = new CallExp(loc, e);
+	    }
+	    e = e->semantic(sc);
+	    return e;
+        }
+	goto Lerror;
+    }
+    else if (t->ty == Ttuple)
+    {
+	if (!lwr && !upr)
+	    return e1;
+	if (!lwr || !upr)
+	{   error("need upper and lower bound to slice tuple");
+	    goto Lerror;
+	}
+    }
+    else
+	goto Lerror;
+
+    if (t->ty == Tsarray || t->ty == Tarray || t->ty == Ttuple)
+    {
+	sym = new ArrayScopeSymbol(sc, this);
+	sym->loc = loc;
+	sym->parent = sc->scopesym;
+	sc = sc->push(sym);
+    }
+
+    if (lwr)
+    {	lwr = lwr->semantic(sc);
+	lwr = resolveProperties(sc, lwr);
+	lwr = lwr->implicitCastTo(sc, Type::tsize_t);
+    }
+    if (upr)
+    {	upr = upr->semantic(sc);
+	upr = resolveProperties(sc, upr);
+	upr = upr->implicitCastTo(sc, Type::tsize_t);
+    }
+
+    if (t->ty == Tsarray || t->ty == Tarray || t->ty == Ttuple)
+	sc->pop();
+
+    if (t->ty == Ttuple)
+    {
+	lwr = lwr->optimize(WANTvalue);
+	upr = upr->optimize(WANTvalue);
+	uinteger_t i1 = lwr->toUInteger();
+	uinteger_t i2 = upr->toUInteger();
+
+	size_t length;
+	TupleExp *te;
+	TypeTuple *tup;
+
+	if (e1->op == TOKtuple)		// slicing an expression tuple
+	{   te = (TupleExp *)e1;
+	    length = te->exps->dim;
+	}
+	else if (e1->op == TOKtype)	// slicing a type tuple
+	{   tup = (TypeTuple *)t;
+	    length = Argument::dim(tup->arguments);
+	}
+	else
+	    assert(0);
+
+	if (i1 <= i2 && i2 <= length)
+	{   size_t j1 = (size_t) i1;
+	    size_t j2 = (size_t) i2;
+
+	    if (e1->op == TOKtuple)
+	    {	Expressions *exps = new Expressions;
+		exps->setDim(j2 - j1);
+		for (size_t i = 0; i < j2 - j1; i++)
+		{   Expression *e = (Expression *)te->exps->data[j1 + i];
+		    exps->data[i] = (void *)e;
+		}
+		e = new TupleExp(loc, exps);
+	    }
+	    else
+	    {	Arguments *args = new Arguments;
+		args->reserve(j2 - j1);
+		for (size_t i = j1; i < j2; i++)
+		{   Argument *arg = Argument::getNth(tup->arguments, i);
+		    args->push(arg);
+		}
+		e = new TypeExp(e1->loc, new TypeTuple(args));
+	    }
+	    e = e->semantic(sc);
+	}
+	else
+	{
+	    error("string slice [%ju .. %ju] is out of bounds", i1, i2);
+	    e = new ErrorExp();
+	}
+	return e;
+    }
+
+    if (t->ty == Tarray)
+    {
+	type = e1->type;
+    }
+    else
+	type = t->nextOf()->arrayOf();
+    return e;
+
+Lerror:
+    char *s;
+    if (t->ty == Tvoid)
+	s = e1->toChars();
+    else
+	s = t->toChars();
+    error("%s cannot be sliced with []", s);
+    e = new ErrorExp();
+    return e;
+}
+
+void SliceExp::checkEscape()
+{
+    e1->checkEscape();
+}
+
+#if DMDV2
+int SliceExp::isLvalue()
+{
+    return 1;
+}
+#endif
+
+Expression *SliceExp::toLvalue(Scope *sc, Expression *e)
+{
+    return this;
+}
+
+Expression *SliceExp::modifiableLvalue(Scope *sc, Expression *e)
+{
+    error("slice expression %s is not a modifiable lvalue", toChars());
+    return this;
+}
+
+void SliceExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    expToCBuffer(buf, hgs, e1, precedence[op]);
+    buf->writeByte('[');
+    if (upr || lwr)
+    {
+	if (lwr)
+	    expToCBuffer(buf, hgs, lwr, PREC_assign);
+	else
+	    buf->writeByte('0');
+	buf->writestring("..");
+	if (upr)
+	    expToCBuffer(buf, hgs, upr, PREC_assign);
+	else
+	    buf->writestring("length");		// BUG: should be array.length
+    }
+    buf->writeByte(']');
+}
+
+/********************** ArrayLength **************************************/
+
+ArrayLengthExp::ArrayLengthExp(Loc loc, Expression *e1)
+	: UnaExp(loc, TOKarraylength, sizeof(ArrayLengthExp), e1)
+{
+}
+
+Expression *ArrayLengthExp::semantic(Scope *sc)
+{   Expression *e;
+
+#if LOGSEMANTIC
+    printf("ArrayLengthExp::semantic('%s')\n", toChars());
+#endif
+    if (!type)
+    {
+	UnaExp::semantic(sc);
+	e1 = resolveProperties(sc, e1);
+
+	type = Type::tsize_t;
+    }
+    return this;
+}
+
+void ArrayLengthExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    expToCBuffer(buf, hgs, e1, PREC_primary);
+    buf->writestring(".length");
+}
+
+/*********************** ArrayExp *************************************/
+
+// e1 [ i1, i2, i3, ... ]
+
+ArrayExp::ArrayExp(Loc loc, Expression *e1, Expressions *args)
+	: UnaExp(loc, TOKarray, sizeof(ArrayExp), e1)
+{
+    arguments = args;
+}
+
+Expression *ArrayExp::syntaxCopy()
+{
+    return new ArrayExp(loc, e1->syntaxCopy(), arraySyntaxCopy(arguments));
+}
+
+Expression *ArrayExp::semantic(Scope *sc)
+{   Expression *e;
+    Type *t1;
+
+#if LOGSEMANTIC
+    printf("ArrayExp::semantic('%s')\n", toChars());
+#endif
+    UnaExp::semantic(sc);
+    e1 = resolveProperties(sc, e1);
+
+    t1 = e1->type->toBasetype();
+    if (t1->ty != Tclass && t1->ty != Tstruct)
+    {	// Convert to IndexExp
+	if (arguments->dim != 1)
+	    error("only one index allowed to index %s", t1->toChars());
+	e = new IndexExp(loc, e1, (Expression *)arguments->data[0]);
+	return e->semantic(sc);
+    }
+
+    // Run semantic() on each argument
+    for (size_t i = 0; i < arguments->dim; i++)
+    {	e = (Expression *)arguments->data[i];
+
+	e = e->semantic(sc);
+	if (!e->type)
+	    error("%s has no value", e->toChars());
+	arguments->data[i] = (void *)e;
+    }
+
+    expandTuples(arguments);
+    assert(arguments && arguments->dim);
+
+    e = op_overload(sc);
+    if (!e)
+    {	error("no [] operator overload for type %s", e1->type->toChars());
+	e = e1;
+    }
+    return e;
+}
+
+#if DMDV2
+int ArrayExp::isLvalue()
+{
+    if (type && type->toBasetype()->ty == Tvoid)
+	return 0;
+    return 1;
+}
+#endif
+
+Expression *ArrayExp::toLvalue(Scope *sc, Expression *e)
+{
+    if (type && type->toBasetype()->ty == Tvoid)
+	error("voids have no value");
+    return this;
+}
+
+
+void ArrayExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{   int i;
+
+    expToCBuffer(buf, hgs, e1, PREC_primary);
+    buf->writeByte('[');
+    argsToCBuffer(buf, arguments, hgs);
+    buf->writeByte(']');
+}
+
+/************************* DotExp ***********************************/
+
+DotExp::DotExp(Loc loc, Expression *e1, Expression *e2)
+	: BinExp(loc, TOKdotexp, sizeof(DotExp), e1, e2)
+{
+}
+
+Expression *DotExp::semantic(Scope *sc)
+{
+#if LOGSEMANTIC
+    printf("DotExp::semantic('%s')\n", toChars());
+    if (type) printf("\ttype = %s\n", type->toChars());
+#endif
+    e1 = e1->semantic(sc);
+    e2 = e2->semantic(sc);
+    if (e2->op == TOKimport)
+    {
+	ScopeExp *se = (ScopeExp *)e2;
+	TemplateDeclaration *td = se->sds->isTemplateDeclaration();
+	if (td)
+	{   Expression *e = new DotTemplateExp(loc, e1, td);
+	    e = e->semantic(sc);
+	    return e;
+	}
+    }
+    if (!type)
+	type = e2->type;
+    return this;
+}
+
+
+/************************* CommaExp ***********************************/
+
+CommaExp::CommaExp(Loc loc, Expression *e1, Expression *e2)
+	: BinExp(loc, TOKcomma, sizeof(CommaExp), e1, e2)
+{
+}
+
+Expression *CommaExp::semantic(Scope *sc)
+{
+    if (!type)
+    {	BinExp::semanticp(sc);
+	type = e2->type;
+    }
+    return this;
+}
+
+void CommaExp::checkEscape()
+{
+    e2->checkEscape();
+}
+
+#if DMDV2
+int CommaExp::isLvalue()
+{
+    return e2->isLvalue();
+}
+#endif
+
+Expression *CommaExp::toLvalue(Scope *sc, Expression *e)
+{
+    e2 = e2->toLvalue(sc, NULL);
+    return this;
+}
+
+Expression *CommaExp::modifiableLvalue(Scope *sc, Expression *e)
+{
+    e2 = e2->modifiableLvalue(sc, e);
+    return this;
+}
+
+int CommaExp::isBool(int result)
+{
+    return e2->isBool(result);
+}
+
+int CommaExp::checkSideEffect(int flag)
+{
+    if (flag == 2)
+	return e1->checkSideEffect(2) || e2->checkSideEffect(2);
+    else
+    {
+	// Don't check e1 until we cast(void) the a,b code generation
+	return e2->checkSideEffect(flag);
+    }
+}
+
+/************************** IndexExp **********************************/
+
+// e1 [ e2 ]
+
+IndexExp::IndexExp(Loc loc, Expression *e1, Expression *e2)
+	: BinExp(loc, TOKindex, sizeof(IndexExp), e1, e2)
+{
+    //printf("IndexExp::IndexExp('%s')\n", toChars());
+    lengthVar = NULL;
+    modifiable = 0;	// assume it is an rvalue
+}
+
+Expression *IndexExp::semantic(Scope *sc)
+{   Expression *e;
+    BinExp *b;
+    UnaExp *u;
+    Type *t1;
+    ScopeDsymbol *sym;
+
+#if LOGSEMANTIC
+    printf("IndexExp::semantic('%s')\n", toChars());
+#endif
+    if (type)
+	return this;
+    if (!e1->type)
+	e1 = e1->semantic(sc);
+    assert(e1->type);		// semantic() should already be run on it
+    e = this;
+
+    // Note that unlike C we do not implement the int[ptr]
+
+    t1 = e1->type->toBasetype();
+
+    if (t1->ty == Tsarray || t1->ty == Tarray || t1->ty == Ttuple)
+    {	// Create scope for 'length' variable
+	sym = new ArrayScopeSymbol(sc, this);
+	sym->loc = loc;
+	sym->parent = sc->scopesym;
+	sc = sc->push(sym);
+    }
+
+    e2 = e2->semantic(sc);
+    if (!e2->type)
+    {
+	error("%s has no value", e2->toChars());
+	e2->type = Type::terror;
+    }
+    e2 = resolveProperties(sc, e2);
+
+    if (t1->ty == Tsarray || t1->ty == Tarray || t1->ty == Ttuple)
+	sc = sc->pop();
+
+    switch (t1->ty)
+    {
+	case Tpointer:
+	case Tarray:
+	    e2 = e2->implicitCastTo(sc, Type::tsize_t);
+	    e->type = ((TypeNext *)t1)->next;
+	    break;
+
+	case Tsarray:
+	{
+	    e2 = e2->implicitCastTo(sc, Type::tsize_t);
+
+	    TypeSArray *tsa = (TypeSArray *)t1;
+
+#if 0 	// Don't do now, because it might be short-circuit evaluated
+	    // Do compile time array bounds checking if possible
+	    e2 = e2->optimize(WANTvalue);
+	    if (e2->op == TOKint64)
+	    {
+		dinteger_t index = e2->toInteger();
+		dinteger_t length = tsa->dim->toInteger();
+		if (index < 0 || index >= length)
+		    error("array index [%lld] is outside array bounds [0 .. %lld]",
+			    index, length);
+	    }
+#endif
+	    e->type = t1->nextOf();
+	    break;
+	}
+
+	case Taarray:
+	{   TypeAArray *taa = (TypeAArray *)t1;
+	    if (!arrayTypeCompatible(e2->loc, e2->type, taa->index))
+	    {
+		e2 = e2->implicitCastTo(sc, taa->index);	// type checking
+	    }
+	    type = taa->next;
+	    break;
+	}
+
+	case Ttuple:
+	{
+	    e2 = e2->implicitCastTo(sc, Type::tsize_t);
+	    e2 = e2->optimize(WANTvalue | WANTinterpret);
+	    uinteger_t index = e2->toUInteger();
+	    size_t length;
+	    TupleExp *te;
+	    TypeTuple *tup;
+
+	    if (e1->op == TOKtuple)
+	    {	te = (TupleExp *)e1;
+		length = te->exps->dim;
+	    }
+	    else if (e1->op == TOKtype)
+	    {
+		tup = (TypeTuple *)t1;
+		length = Argument::dim(tup->arguments);
+	    }
+	    else
+		assert(0);
+
+	    if (index < length)
+	    {
+
+		if (e1->op == TOKtuple)
+		    e = (Expression *)te->exps->data[(size_t)index];
+		else
+		    e = new TypeExp(e1->loc, Argument::getNth(tup->arguments, (size_t)index)->type);
+	    }
+	    else
+	    {
+		error("array index [%ju] is outside array bounds [0 .. %zu]",
+			index, length);
+		e = e1;
+	    }
+	    break;
+	}
+
+	default:
+	    error("%s must be an array or pointer type, not %s",
+		e1->toChars(), e1->type->toChars());
+	    type = Type::tint32;
+	    break;
+    }
+    return e;
+}
+
+#if DMDV2
+int IndexExp::isLvalue()
+{
+    return 1;
+}
+#endif
+
+Expression *IndexExp::toLvalue(Scope *sc, Expression *e)
+{
+//    if (type && type->toBasetype()->ty == Tvoid)
+//	error("voids have no value");
+    return this;
+}
+
+Expression *IndexExp::modifiableLvalue(Scope *sc, Expression *e)
+{
+    //printf("IndexExp::modifiableLvalue(%s)\n", toChars());
+    modifiable = 1;
+    if (e1->op == TOKstring)
+	error("string literals are immutable");
+    if (type && !type->isMutable())
+	error("%s isn't mutable", e->toChars());
+    if (e1->type->toBasetype()->ty == Taarray)
+	e1 = e1->modifiableLvalue(sc, e1);
+    return toLvalue(sc, e);
+}
+
+void IndexExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    expToCBuffer(buf, hgs, e1, PREC_primary);
+    buf->writeByte('[');
+    expToCBuffer(buf, hgs, e2, PREC_assign);
+    buf->writeByte(']');
+}
+
+
+/************************* PostExp ***********************************/
+
+PostExp::PostExp(enum TOK op, Loc loc, Expression *e)
+	: BinExp(loc, op, sizeof(PostExp), e,
+	  new IntegerExp(loc, 1, Type::tint32))
+{
+}
+
+Expression *PostExp::semantic(Scope *sc)
+{   Expression *e = this;
+
+    if (!type)
+    {
+	BinExp::semantic(sc);
+	e2 = resolveProperties(sc, e2);
+
+	e = op_overload(sc);
+	if (e)
+	    return e;
+
+	e = this;
+	e1 = e1->modifiableLvalue(sc, e1);
+	e1->checkScalar();
+	e1->checkNoBool();
+	if (e1->type->ty == Tpointer)
+	    e = scaleFactor(sc);
+	else
+	    e2 = e2->castTo(sc, e1->type);
+	e->type = e1->type;
+    }
+    return e;
+}
+
+void PostExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    expToCBuffer(buf, hgs, e1, precedence[op]);
+    buf->writestring((op == TOKplusplus) ? (char *)"++" : (char *)"--");
+}
+
+/************************************************************/
+
+/* op can be TOKassign, TOKconstruct, or TOKblit */
+
+AssignExp::AssignExp(Loc loc, Expression *e1, Expression *e2)
+	: BinExp(loc, TOKassign, sizeof(AssignExp), e1, e2)
+{
+    ismemset = 0;
+}
+
+Expression *AssignExp::semantic(Scope *sc)
+{
+    Expression *e1old = e1;
+
+#if LOGSEMANTIC
+    printf("AssignExp::semantic('%s')\n", toChars());
+#endif
+    //printf("e1->op = %d, '%s'\n", e1->op, Token::toChars(e1->op));
+    //printf("e2->op = %d, '%s'\n", e2->op, Token::toChars(e2->op));
+
+    if (type)
+	return this;
+
+    if (e2->op == TOKcomma)
+    {	/* Rewrite to get rid of the comma from rvalue
+	 */
+	AssignExp *ea = new AssignExp(loc, e1, ((CommaExp *)e2)->e2);
+	ea->op = op;
+	Expression *e = new CommaExp(loc, ((CommaExp *)e2)->e1, ea);
+	return e->semantic(sc);
+    }
+
+    /* Look for operator overloading of a[i]=value.
+     * Do it before semantic() otherwise the a[i] will have been
+     * converted to a.opIndex() already.
+     */
+    if (e1->op == TOKarray)
+    {
+	ArrayExp *ae = (ArrayExp *)e1;
+	AggregateDeclaration *ad;
+	Identifier *id = Id::index;
+
+	ae->e1 = ae->e1->semantic(sc);
+	Type *t1 = ae->e1->type->toBasetype();
+	if (t1->ty == Tstruct)
+	{
+	    ad = ((TypeStruct *)t1)->sym;
+	    goto L1;
+	}
+	else if (t1->ty == Tclass)
+	{
+	    ad = ((TypeClass *)t1)->sym;
+	  L1:
+	    // Rewrite (a[i] = value) to (a.opIndexAssign(value, i))
+	    if (search_function(ad, Id::indexass))
+	    {	Expression *e = new DotIdExp(loc, ae->e1, Id::indexass);
+		Expressions *a = (Expressions *)ae->arguments->copy();
+
+		a->insert(0, e2);
+		e = new CallExp(loc, e, a);
+		e = e->semantic(sc);
+		return e;
+	    }
+	    else
+	    {
+		// Rewrite (a[i] = value) to (a.opIndex(i, value))
+		if (search_function(ad, id))
+		{   Expression *e = new DotIdExp(loc, ae->e1, id);
+
+		    if (1 || !global.params.useDeprecated)
+			error("operator [] assignment overload with opIndex(i, value) illegal, use opIndexAssign(value, i)");
+
+		    e = new CallExp(loc, e, (Expression *)ae->arguments->data[0], e2);
+		    e = e->semantic(sc);
+		    return e;
+		}
+	    }
+	}
+    }
+    /* Look for operator overloading of a[i..j]=value.
+     * Do it before semantic() otherwise the a[i..j] will have been
+     * converted to a.opSlice() already.
+     */
+    if (e1->op == TOKslice)
+    {	Type *t1;
+	SliceExp *ae = (SliceExp *)e1;
+	AggregateDeclaration *ad;
+	Identifier *id = Id::index;
+
+	ae->e1 = ae->e1->semantic(sc);
+	ae->e1 = resolveProperties(sc, ae->e1);
+	t1 = ae->e1->type->toBasetype();
+	if (t1->ty == Tstruct)
+	{
+	    ad = ((TypeStruct *)t1)->sym;
+	    goto L2;
+	}
+	else if (t1->ty == Tclass)
+	{
+	    ad = ((TypeClass *)t1)->sym;
+	  L2:
+	    // Rewrite (a[i..j] = value) to (a.opIndexAssign(value, i, j))
+	    if (search_function(ad, Id::sliceass))
+	    {	Expression *e = new DotIdExp(loc, ae->e1, Id::sliceass);
+		Expressions *a = new Expressions();
+
+		a->push(e2);
+		if (ae->lwr)
+		{   a->push(ae->lwr);
+		    assert(ae->upr);
+		    a->push(ae->upr);
+		}
+		else
+		    assert(!ae->upr);
+		e = new CallExp(loc, e, a);
+		e = e->semantic(sc);
+		return e;
+	    }
+	}
+    }
+
+    BinExp::semantic(sc);
+
+    if (e1->op == TOKdottd)
+    {	// Rewrite a.b=e2, when b is a template, as a.b(e2)
+	Expression *e = new CallExp(loc, e1, e2);
+	e = e->semantic(sc);
+	return e;
+    }
+
+    e2 = resolveProperties(sc, e2);
+    assert(e1->type);
+
+    /* Rewrite tuple assignment as a tuple of assignments.
+     */
+    if (e1->op == TOKtuple && e2->op == TOKtuple)
+    {	TupleExp *tup1 = (TupleExp *)e1;
+	TupleExp *tup2 = (TupleExp *)e2;
+	size_t dim = tup1->exps->dim;
+	if (dim != tup2->exps->dim)
+	{
+	    error("mismatched tuple lengths, %d and %d", (int)dim, (int)tup2->exps->dim);
+	}
+	else
+	{   Expressions *exps = new Expressions;
+	    exps->setDim(dim);
+
+	    for (int i = 0; i < dim; i++)
+	    {	Expression *ex1 = (Expression *)tup1->exps->data[i];
+		Expression *ex2 = (Expression *)tup2->exps->data[i];
+		exps->data[i] = (void *) new AssignExp(loc, ex1, ex2);
+	    }
+	    Expression *e = new TupleExp(loc, exps);
+	    e = e->semantic(sc);
+	    return e;
+	}
+    }
+
+    Type *t1 = e1->type->toBasetype();
+
+    if (t1->ty == Tfunction)
+    {	// Rewrite f=value to f(value)
+	Expression *e = new CallExp(loc, e1, e2);
+	e = e->semantic(sc);
+	return e;
+    }
+
+    /* If it is an assignment from a 'foreign' type,
+     * check for operator overloading.
+     */
+    if (t1->ty == Tstruct)
+    {
+	StructDeclaration *sd = ((TypeStruct *)t1)->sym;
+	if (op == TOKassign)
+	{
+	    Expression *e = op_overload(sc);
+	    if (e)
+		return e;
+	}
+	else if (op == TOKconstruct)
+	{   Type *t2 = e2->type->toBasetype();
+	    if (t2->ty == Tstruct &&
+		sd == ((TypeStruct *)t2)->sym &&
+		sd->cpctor)
+	    {	/* We have a copy constructor for this
+		 */
+		if (e2->op == TOKvar || e2->op == TOKstar)
+		{   /* Write as:
+		     *	e1.cpctor(e2);
+		     */
+		    Expression *e = new DotVarExp(loc, e1, sd->cpctor, 0);
+		    e = new CallExp(loc, e, e2);
+		    return e->semantic(sc);
+		}
+		else if (e2->op == TOKquestion)
+		{   /* Write as:
+		     *	a ? e1 = b : e1 = c;
+		     */
+		    CondExp *ec = (CondExp *)e2;
+		    AssignExp *ea1 = new AssignExp(ec->e1->loc, e1, ec->e1);
+		    ea1->op = op;
+		    AssignExp *ea2 = new AssignExp(ec->e1->loc, e1, ec->e2);
+		    ea2->op = op;
+		    Expression *e = new CondExp(loc, ec->econd, ea1, ea2);
+		    return e->semantic(sc);
+		}
+	    }
+	}
+    }
+    else if (t1->ty == Tclass)
+    {	// Disallow assignment operator overloads for same type
+	if (!e2->type->implicitConvTo(e1->type))
+	{
+	    Expression *e = op_overload(sc);
+	    if (e)
+		return e;
+	}
+    }
+
+    if (t1->ty == Tsarray)
+    {	// Convert e1 to e1[]
+	Expression *e = new SliceExp(e1->loc, e1, NULL, NULL);
+	e1 = e->semantic(sc);
+	t1 = e1->type->toBasetype();
+    }
+
+    e2->rvalue();
+
+    if (e1->op == TOKarraylength)
+    {
+	// e1 is not an lvalue, but we let code generator handle it
+	ArrayLengthExp *ale = (ArrayLengthExp *)e1;
+
+	ale->e1 = ale->e1->modifiableLvalue(sc, e1);
+    }
+    else if (e1->op == TOKslice)
+    {
+	Type *tn = e1->type->nextOf();
+	if (tn && !tn->isMutable() && op != TOKconstruct)
+	    error("slice %s is not mutable", e1->toChars());
+    }
+    else
+    {	// Try to do a decent error message with the expression
+	// before it got constant folded
+	if (e1->op != TOKvar)
+	    e1 = e1->optimize(WANTvalue);
+
+	if (op != TOKconstruct)
+	    e1 = e1->modifiableLvalue(sc, e1old);
+    }
+
+    Type *t2 = e2->type;
+    if (e1->op == TOKslice &&
+	t1->nextOf() &&
+	e2->implicitConvTo(t1->nextOf())
+       )
+    {	// memset
+	ismemset = 1;	// make it easy for back end to tell what this is
+	e2 = e2->implicitCastTo(sc, t1->nextOf());
+    }
+    else if (t1->ty == Tsarray)
+    {
+	/* Should have already converted e1 => e1[]
+	 */
+	assert(0);
+	//error("cannot assign to static array %s", e1->toChars());
+    }
+    else if (e1->op == TOKslice)
+    {
+	e2 = e2->implicitCastTo(sc, e1->type->constOf());
+    }
+    else
+    {
+	e2 = e2->implicitCastTo(sc, e1->type);
+    }
+
+    /* Look for array operations
+     */
+    if (e1->op == TOKslice && !ismemset &&
+	(e2->op == TOKadd || e2->op == TOKmin ||
+	 e2->op == TOKmul || e2->op == TOKdiv ||
+	 e2->op == TOKmod || e2->op == TOKxor ||
+	 e2->op == TOKand || e2->op == TOKor  ||
+	 e2->op == TOKtilde || e2->op == TOKneg))
+    {
+	type = e1->type;
+	return arrayOp(sc);
+    }
+
+    type = e1->type;
+    assert(type);
+    return this;
+}
+
+Expression *AssignExp::checkToBoolean()
+{
+    // Things like:
+    //	if (a = b) ...
+    // are usually mistakes.
+
+    error("'=' does not give a boolean result");
+    return this;
+}
+
+/************************************************************/
+
+AddAssignExp::AddAssignExp(Loc loc, Expression *e1, Expression *e2)
+	: BinExp(loc, TOKaddass, sizeof(AddAssignExp), e1, e2)
+{
+}
+
+Expression *AddAssignExp::semantic(Scope *sc)
+{   Expression *e;
+
+    if (type)
+	return this;
+
+    BinExp::semantic(sc);
+    e2 = resolveProperties(sc, e2);
+
+    e = op_overload(sc);
+    if (e)
+	return e;
+
+    Type *tb1 = e1->type->toBasetype();
+    Type *tb2 = e2->type->toBasetype();
+
+    if (e1->op == TOKslice)
+    {
+	typeCombine(sc);
+	type = e1->type;
+	return arrayOp(sc);
+    }
+    else
+    {
+	e1 = e1->modifiableLvalue(sc, e1);
+    }
+
+    if ((tb1->ty == Tarray || tb1->ty == Tsarray) &&
+	(tb2->ty == Tarray || tb2->ty == Tsarray) &&
+	tb1->nextOf()->equals(tb2->nextOf())
+       )
+    {
+	type = e1->type;
+	typeCombine(sc);
+	e = this;
+    }
+    else
+    {
+	e1->checkScalar();
+	e1->checkNoBool();
+	if (tb1->ty == Tpointer && tb2->isintegral())
+	    e = scaleFactor(sc);
+	else if (tb1->ty == Tbit || tb1->ty == Tbool)
+	{
+#if 0
+	    // Need to rethink this
+	    if (e1->op != TOKvar)
+	    {   // Rewrite e1+=e2 to (v=&e1),*v=*v+e2
+		VarDeclaration *v;
+		Expression *ea;
+		Expression *ex;
+
+		Identifier *id = Lexer::uniqueId("__name");
+
+		v = new VarDeclaration(loc, tb1->pointerTo(), id, NULL);
+		v->semantic(sc);
+		if (!sc->insert(v))
+		    assert(0);
+		v->parent = sc->func;
+
+		ea = new AddrExp(loc, e1);
+		ea = new AssignExp(loc, new VarExp(loc, v), ea);
+
+		ex = new VarExp(loc, v);
+		ex = new PtrExp(loc, ex);
+		e = new AddExp(loc, ex, e2);
+		e = new CastExp(loc, e, e1->type);
+		e = new AssignExp(loc, ex->syntaxCopy(), e);
+
+		e = new CommaExp(loc, ea, e);
+	    }
+	    else
+#endif
+	    {   // Rewrite e1+=e2 to e1=e1+e2
+		// BUG: doesn't account for side effects in e1
+		// BUG: other assignment operators for bits aren't handled at all
+		e = new AddExp(loc, e1, e2);
+		e = new CastExp(loc, e, e1->type);
+		e = new AssignExp(loc, e1->syntaxCopy(), e);
+	    }
+	    e = e->semantic(sc);
+	}
+	else
+	{
+	    type = e1->type;
+	    typeCombine(sc);
+	    e1->checkArithmetic();
+	    e2->checkArithmetic();
+	    if (type->isreal() || type->isimaginary())
+	    {
+		assert(global.errors || e2->type->isfloating());
+		e2 = e2->castTo(sc, e1->type);
+	    }
+	    e = this;
+
+	    if (e2->type->iscomplex() && !type->iscomplex())
+		error("Cannot assign %s to %s", e2->type->toChars(), type->toChars());
+	}
+    }
+    return e;
+}
+
+/************************************************************/
+
+MinAssignExp::MinAssignExp(Loc loc, Expression *e1, Expression *e2)
+	: BinExp(loc, TOKminass, sizeof(MinAssignExp), e1, e2)
+{
+}
+
+Expression *MinAssignExp::semantic(Scope *sc)
+{   Expression *e;
+
+    if (type)
+	return this;
+
+    BinExp::semantic(sc);
+    e2 = resolveProperties(sc, e2);
+
+    e = op_overload(sc);
+    if (e)
+	return e;
+
+    if (e1->op == TOKslice)
+    {	// T[] -= ...
+	typeCombine(sc);
+	type = e1->type;
+	return arrayOp(sc);
+    }
+
+    e1 = e1->modifiableLvalue(sc, e1);
+    e1->checkScalar();
+    e1->checkNoBool();
+    if (e1->type->ty == Tpointer && e2->type->isintegral())
+	e = scaleFactor(sc);
+    else
+    {
+	e1 = e1->checkArithmetic();
+	e2 = e2->checkArithmetic();
+	type = e1->type;
+	typeCombine(sc);
+	if (type->isreal() || type->isimaginary())
+	{
+	    assert(e2->type->isfloating());
+	    e2 = e2->castTo(sc, e1->type);
+	}
+	e = this;
+
+	if (e2->type->iscomplex() && !type->iscomplex())
+	    error("Cannot assign %s to %s", e2->type->toChars(), type->toChars());
+    }
+    return e;
+}
+
+/************************************************************/
+
+CatAssignExp::CatAssignExp(Loc loc, Expression *e1, Expression *e2)
+	: BinExp(loc, TOKcatass, sizeof(CatAssignExp), e1, e2)
+{
+}
+
+Expression *CatAssignExp::semantic(Scope *sc)
+{   Expression *e;
+
+    BinExp::semantic(sc);
+    e2 = resolveProperties(sc, e2);
+
+    e = op_overload(sc);
+    if (e)
+	return e;
+
+    if (e1->op == TOKslice)
+    {	SliceExp *se = (SliceExp *)e1;
+
+	if (se->e1->type->toBasetype()->ty == Tsarray)
+	    error("cannot append to static array %s", se->e1->type->toChars());
+    }
+
+    e1 = e1->modifiableLvalue(sc, e1);
+
+    Type *tb1 = e1->type->toBasetype();
+    Type *tb2 = e2->type->toBasetype();
+
+    e2->rvalue();
+
+    if ((tb1->ty == Tarray) &&
+	(tb2->ty == Tarray || tb2->ty == Tsarray) &&
+	(e2->implicitConvTo(e1->type) ||
+	 tb2->nextOf()->implicitConvTo(tb1->nextOf()))
+       )
+    {	// Append array
+	e2 = e2->castTo(sc, e1->type);
+	type = e1->type;
+	e = this;
+    }
+    else if ((tb1->ty == Tarray) &&
+	e2->implicitConvTo(tb1->nextOf())
+       )
+    {	// Append element
+	e2 = e2->castTo(sc, tb1->nextOf());
+	type = e1->type;
+	e = this;
+    }
+    else
+    {
+	error("cannot append type %s to type %s", tb2->toChars(), tb1->toChars());
+	type = Type::tint32;
+	e = this;
+    }
+    return e;
+}
+
+/************************************************************/
+
+MulAssignExp::MulAssignExp(Loc loc, Expression *e1, Expression *e2)
+	: BinExp(loc, TOKmulass, sizeof(MulAssignExp), e1, e2)
+{
+}
+
+Expression *MulAssignExp::semantic(Scope *sc)
+{   Expression *e;
+
+    BinExp::semantic(sc);
+    e2 = resolveProperties(sc, e2);
+
+    e = op_overload(sc);
+    if (e)
+	return e;
+
+    if (e1->op == TOKslice)
+    {	// T[] -= ...
+	typeCombine(sc);
+	type = e1->type;
+	return arrayOp(sc);
+    }
+
+    e1 = e1->modifiableLvalue(sc, e1);
+    e1->checkScalar();
+    e1->checkNoBool();
+    type = e1->type;
+    typeCombine(sc);
+    e1->checkArithmetic();
+    e2->checkArithmetic();
+    if (e2->type->isfloating())
+    {	Type *t1;
+	Type *t2;
+
+	t1 = e1->type;
+	t2 = e2->type;
+	if (t1->isreal())
+	{
+	    if (t2->isimaginary() || t2->iscomplex())
+	    {
+		e2 = e2->castTo(sc, t1);
+	    }
+	}
+	else if (t1->isimaginary())
+	{
+	    if (t2->isimaginary() || t2->iscomplex())
+	    {
+		switch (t1->ty)
+		{
+		    case Timaginary32: t2 = Type::tfloat32; break;
+		    case Timaginary64: t2 = Type::tfloat64; break;
+		    case Timaginary80: t2 = Type::tfloat80; break;
+		    default:
+			assert(0);
+		}
+		e2 = e2->castTo(sc, t2);
+	    }
+	}
+
+	if (e2->type->iscomplex() && !type->iscomplex())
+	    error("Cannot assign %s to %s", e2->type->toChars(), type->toChars());
+    }
+    return this;
+}
+
+/************************************************************/
+
+DivAssignExp::DivAssignExp(Loc loc, Expression *e1, Expression *e2)
+	: BinExp(loc, TOKdivass, sizeof(DivAssignExp), e1, e2)
+{
+}
+
+Expression *DivAssignExp::semantic(Scope *sc)
+{   Expression *e;
+
+    BinExp::semantic(sc);
+    e2 = resolveProperties(sc, e2);
+
+    e = op_overload(sc);
+    if (e)
+	return e;
+
+    if (e1->op == TOKslice)
+    {	// T[] -= ...
+	typeCombine(sc);
+	type = e1->type;
+	return arrayOp(sc);
+    }
+
+    e1 = e1->modifiableLvalue(sc, e1);
+    e1->checkScalar();
+    e1->checkNoBool();
+    type = e1->type;
+    typeCombine(sc);
+    e1->checkArithmetic();
+    e2->checkArithmetic();
+    if (e2->type->isimaginary())
+    {	Type *t1;
+	Type *t2;
+
+	t1 = e1->type;
+	if (t1->isreal())
+	{   // x/iv = i(-x/v)
+	    // Therefore, the result is 0
+	    e2 = new CommaExp(loc, e2, new RealExp(loc, 0, t1));
+	    e2->type = t1;
+	    e = new AssignExp(loc, e1, e2);
+	    e->type = t1;
+	    return e;
+	}
+	else if (t1->isimaginary())
+	{   Expression *e;
+
+	    switch (t1->ty)
+	    {
+		case Timaginary32: t2 = Type::tfloat32; break;
+		case Timaginary64: t2 = Type::tfloat64; break;
+		case Timaginary80: t2 = Type::tfloat80; break;
+		default:
+		    assert(0);
+	    }
+	    e2 = e2->castTo(sc, t2);
+	    e = new AssignExp(loc, e1, e2);
+	    e->type = t1;
+	    return e;
+	}
+    }
+
+    if (e2->type->iscomplex() && !type->iscomplex())
+	error("Cannot assign %s to %s", e2->type->toChars(), type->toChars());
+
+    return this;
+}
+
+/************************************************************/
+
+ModAssignExp::ModAssignExp(Loc loc, Expression *e1, Expression *e2)
+	: BinExp(loc, TOKmodass, sizeof(ModAssignExp), e1, e2)
+{
+}
+
+Expression *ModAssignExp::semantic(Scope *sc)
+{
+    return commonSemanticAssign(sc);
+}
+
+/************************************************************/
+
+ShlAssignExp::ShlAssignExp(Loc loc, Expression *e1, Expression *e2)
+	: BinExp(loc, TOKshlass, sizeof(ShlAssignExp), e1, e2)
+{
+}
+
+Expression *ShlAssignExp::semantic(Scope *sc)
+{   Expression *e;
+
+    //printf("ShlAssignExp::semantic()\n");
+    BinExp::semantic(sc);
+    e2 = resolveProperties(sc, e2);
+
+    e = op_overload(sc);
+    if (e)
+	return e;
+
+    e1 = e1->modifiableLvalue(sc, e1);
+    e1->checkScalar();
+    e1->checkNoBool();
+    type = e1->type;
+    typeCombine(sc);
+    e1->checkIntegral();
+    e2 = e2->checkIntegral();
+    //e2 = e2->castTo(sc, Type::tshiftcnt);
+    e2 = e2->castTo(sc, e1->type); // LDC
+    return this;
+}
+
+/************************************************************/
+
+ShrAssignExp::ShrAssignExp(Loc loc, Expression *e1, Expression *e2)
+	: BinExp(loc, TOKshrass, sizeof(ShrAssignExp), e1, e2)
+{
+}
+
+Expression *ShrAssignExp::semantic(Scope *sc)
+{   Expression *e;
+
+    BinExp::semantic(sc);
+    e2 = resolveProperties(sc, e2);
+
+    e = op_overload(sc);
+    if (e)
+	return e;
+
+    e1 = e1->modifiableLvalue(sc, e1);
+    e1->checkScalar();
+    e1->checkNoBool();
+    type = e1->type;
+    typeCombine(sc);
+    e1->checkIntegral();
+    e2 = e2->checkIntegral();
+    //e2 = e2->castTo(sc, Type::tshiftcnt);
+    e2 = e2->castTo(sc, e1->type); // LDC
+    return this;
+}
+
+/************************************************************/
+
+UshrAssignExp::UshrAssignExp(Loc loc, Expression *e1, Expression *e2)
+	: BinExp(loc, TOKushrass, sizeof(UshrAssignExp), e1, e2)
+{
+}
+
+Expression *UshrAssignExp::semantic(Scope *sc)
+{   Expression *e;
+
+    BinExp::semantic(sc);
+    e2 = resolveProperties(sc, e2);
+
+    e = op_overload(sc);
+    if (e)
+	return e;
+
+    e1 = e1->modifiableLvalue(sc, e1);
+    e1->checkScalar();
+    e1->checkNoBool();
+    type = e1->type;
+    typeCombine(sc);
+    e1->checkIntegral();
+    e2 = e2->checkIntegral();
+    //e2 = e2->castTo(sc, Type::tshiftcnt);
+    e2 = e2->castTo(sc, e1->type); // LDC
+    return this;
+}
+
+/************************************************************/
+
+AndAssignExp::AndAssignExp(Loc loc, Expression *e1, Expression *e2)
+	: BinExp(loc, TOKandass, sizeof(AndAssignExp), e1, e2)
+{
+}
+
+Expression *AndAssignExp::semantic(Scope *sc)
+{
+    return commonSemanticAssignIntegral(sc);
+}
+
+/************************************************************/
+
+OrAssignExp::OrAssignExp(Loc loc, Expression *e1, Expression *e2)
+	: BinExp(loc, TOKorass, sizeof(OrAssignExp), e1, e2)
+{
+}
+
+Expression *OrAssignExp::semantic(Scope *sc)
+{
+    return commonSemanticAssignIntegral(sc);
+}
+
+/************************************************************/
+
+XorAssignExp::XorAssignExp(Loc loc, Expression *e1, Expression *e2)
+	: BinExp(loc, TOKxorass, sizeof(XorAssignExp), e1, e2)
+{
+}
+
+Expression *XorAssignExp::semantic(Scope *sc)
+{
+    return commonSemanticAssignIntegral(sc);
+}
+
+/************************* AddExp *****************************/
+
+AddExp::AddExp(Loc loc, Expression *e1, Expression *e2)
+	: BinExp(loc, TOKadd, sizeof(AddExp), e1, e2)
+{
+}
+
+Expression *AddExp::semantic(Scope *sc)
+{   Expression *e;
+
+#if LOGSEMANTIC
+    printf("AddExp::semantic('%s')\n", toChars());
+#endif
+    if (!type)
+    {
+	BinExp::semanticp(sc);
+
+	e = op_overload(sc);
+	if (e)
+	    return e;
+
+	Type *tb1 = e1->type->toBasetype();
+	Type *tb2 = e2->type->toBasetype();
+
+        if ((tb1->ty == Tarray || tb1->ty == Tsarray) &&
+            (tb2->ty == Tarray || tb2->ty == Tsarray) &&
+            tb1->nextOf()->equals(tb2->nextOf())
+           )
+        {
+            type = e1->type;
+            e = this;
+        }
+	else if (tb1->ty == Tpointer && e2->type->isintegral() ||
+	    tb2->ty == Tpointer && e1->type->isintegral())
+	    e = scaleFactor(sc);
+	else if (tb1->ty == Tpointer && tb2->ty == Tpointer)
+	{
+	    incompatibleTypes();
+	    type = e1->type;
+	    e = this;
+	}
+	else
+	{
+	    typeCombine(sc);
+	    if ((e1->type->isreal() && e2->type->isimaginary()) ||
+		(e1->type->isimaginary() && e2->type->isreal()))
+	    {
+		switch (type->toBasetype()->ty)
+		{
+		    case Tfloat32:
+		    case Timaginary32:
+			type = Type::tcomplex32;
+			break;
+
+		    case Tfloat64:
+		    case Timaginary64:
+			type = Type::tcomplex64;
+			break;
+
+		    case Tfloat80:
+		    case Timaginary80:
+			type = Type::tcomplex80;
+			break;
+
+		    default:
+			assert(0);
+		}
+	    }
+	    e = this;
+	}
+	return e;
+    }
+    return this;
+}
+
+/************************************************************/
+
+MinExp::MinExp(Loc loc, Expression *e1, Expression *e2)
+	: BinExp(loc, TOKmin, sizeof(MinExp), e1, e2)
+{
+}
+
+Expression *MinExp::semantic(Scope *sc)
+{   Expression *e;
+    Type *t1;
+    Type *t2;
+
+#if LOGSEMANTIC
+    printf("MinExp::semantic('%s')\n", toChars());
+#endif
+    if (type)
+	return this;
+
+    BinExp::semanticp(sc);
+
+    e = op_overload(sc);
+    if (e)
+	return e;
+
+    e = this;
+    t1 = e1->type->toBasetype();
+    t2 = e2->type->toBasetype();
+    if (t1->ty == Tpointer)
+    {
+	if (t2->ty == Tpointer)
+	{   // Need to divide the result by the stride
+	    // Replace (ptr - ptr) with (ptr - ptr) / stride
+	    d_int64 stride;
+	    Expression *e;
+
+	    typeCombine(sc);		// make sure pointer types are compatible
+	    type = Type::tptrdiff_t;
+	    stride = t2->nextOf()->size();
+	    if (stride == 0)
+	    {
+		e = new IntegerExp(loc, 0, Type::tptrdiff_t);
+	    }
+	    else
+	    {
+		e = new DivExp(loc, this, new IntegerExp(0, stride, Type::tptrdiff_t));
+		e->type = Type::tptrdiff_t;
+	    }
+	    return e;
+	}
+	else if (t2->isintegral())
+	    e = scaleFactor(sc);
+	else
+	{   error("incompatible types for minus");
+	    return new ErrorExp();
+	}
+    }
+    else if (t2->ty == Tpointer)
+    {
+	type = e2->type;
+	error("can't subtract pointer from %s", e1->type->toChars());
+	return new ErrorExp();
+    }
+    else
+    {
+	typeCombine(sc);
+	t1 = e1->type->toBasetype();
+	t2 = e2->type->toBasetype();
+	if ((t1->isreal() && t2->isimaginary()) ||
+	    (t1->isimaginary() && t2->isreal()))
+	{
+	    switch (type->ty)
+	    {
+		case Tfloat32:
+		case Timaginary32:
+		    type = Type::tcomplex32;
+		    break;
+
+		case Tfloat64:
+		case Timaginary64:
+		    type = Type::tcomplex64;
+		    break;
+
+		case Tfloat80:
+		case Timaginary80:
+		    type = Type::tcomplex80;
+		    break;
+
+		default:
+		    assert(0);
+	    }
+	}
+    }
+    return e;
+}
+
+/************************* CatExp *****************************/
+
+CatExp::CatExp(Loc loc, Expression *e1, Expression *e2)
+	: BinExp(loc, TOKcat, sizeof(CatExp), e1, e2)
+{
+}
+
+Expression *CatExp::semantic(Scope *sc)
+{   Expression *e;
+
+    //printf("CatExp::semantic() %s\n", toChars());
+    if (!type)
+    {
+	BinExp::semanticp(sc);
+	e = op_overload(sc);
+	if (e)
+	    return e;
+
+	Type *tb1 = e1->type->toBasetype();
+	Type *tb2 = e2->type->toBasetype();
+
+
+	/* BUG: Should handle things like:
+	 *	char c;
+	 *	c ~ ' '
+	 *	' ' ~ c;
+	 */
+
+#if 0
+	e1->type->print();
+	e2->type->print();
+#endif
+	if ((tb1->ty == Tsarray || tb1->ty == Tarray) &&
+	    e2->type->implicitConvTo(tb1->nextOf()) >= MATCHconst)
+	{
+	    type = tb1->nextOf()->arrayOf();
+	    if (tb2->ty == Tarray)
+	    {	// Make e2 into [e2]
+		e2 = new ArrayLiteralExp(e2->loc, e2);
+		e2->type = type;
+	    }
+	    return this;
+	}
+	else if ((tb2->ty == Tsarray || tb2->ty == Tarray) &&
+	    e1->type->implicitConvTo(tb2->nextOf()) >= MATCHconst)
+	{
+	    type = tb2->nextOf()->arrayOf();
+	    if (tb1->ty == Tarray)
+	    {	// Make e1 into [e1]
+		e1 = new ArrayLiteralExp(e1->loc, e1);
+		e1->type = type;
+	    }
+	    return this;
+	}
+
+	if ((tb1->ty == Tsarray || tb1->ty == Tarray) &&
+	    (tb2->ty == Tsarray || tb2->ty == Tarray) &&
+	    (tb1->nextOf()->mod || tb2->nextOf()->mod) &&
+	    (tb1->nextOf()->mod != tb2->nextOf()->mod)
+	   )
+	{
+	    Type *t1 = tb1->nextOf()->mutableOf()->constOf()->arrayOf();
+	    Type *t2 = tb2->nextOf()->mutableOf()->constOf()->arrayOf();
+	    if (e1->op == TOKstring && !((StringExp *)e1)->committed)
+		e1->type = t1;
+	    else
+		e1 = e1->castTo(sc, t1);
+	    if (e2->op == TOKstring && !((StringExp *)e2)->committed)
+		e2->type = t2;
+	    else
+		e2 = e2->castTo(sc, t2);
+	}
+
+	typeCombine(sc);
+	type = type->toHeadMutable();
+
+	Type *tb = type->toBasetype();
+	if (tb->ty == Tsarray)
+	    type = tb->nextOf()->arrayOf();
+	if (type->ty == Tarray && tb1->nextOf() && tb2->nextOf() &&
+	    tb1->nextOf()->mod != tb2->nextOf()->mod)
+	{
+	    type = type->nextOf()->toHeadMutable()->arrayOf();
+	}
+#if 0
+	e1->type->print();
+	e2->type->print();
+	type->print();
+	print();
+#endif
+	Type *t1 = e1->type->toBasetype();
+	Type *t2 = e2->type->toBasetype();
+	if (e1->op == TOKstring && e2->op == TOKstring)
+	    e = optimize(WANTvalue);
+	else if ((t1->ty == Tarray || t1->ty == Tsarray) &&
+		 (t2->ty == Tarray || t2->ty == Tsarray))
+	{
+	    e = this;
+	}
+	else
+	{
+	    //printf("(%s) ~ (%s)\n", e1->toChars(), e2->toChars());
+	    error("Can only concatenate arrays, not (%s ~ %s)",
+		e1->type->toChars(), e2->type->toChars());
+	    type = Type::tint32;
+	    e = this;
+	}
+	e->type = e->type->semantic(loc, sc);
+	return e;
+    }
+    return this;
+}
+
+/************************************************************/
+
+MulExp::MulExp(Loc loc, Expression *e1, Expression *e2)
+	: BinExp(loc, TOKmul, sizeof(MulExp), e1, e2)
+{
+}
+
+Expression *MulExp::semantic(Scope *sc)
+{   Expression *e;
+
+#if 0
+    printf("MulExp::semantic() %s\n", toChars());
+#endif
+    if (type)
+    {
+	return this;
+    }
+
+    BinExp::semanticp(sc);
+    e = op_overload(sc);
+    if (e)
+	return e;
+
+    typeCombine(sc);
+    if (e1->op != TOKslice && e2->op != TOKslice)
+    {	e1->checkArithmetic();
+	e2->checkArithmetic();
+    }
+    if (type->isfloating())
+    {	Type *t1 = e1->type;
+	Type *t2 = e2->type;
+
+	if (t1->isreal())
+	{
+	    type = t2;
+	}
+	else if (t2->isreal())
+	{
+	    type = t1;
+	}
+	else if (t1->isimaginary())
+	{
+	    if (t2->isimaginary())
+	    {	Expression *e;
+
+		switch (t1->ty)
+		{
+		    case Timaginary32:	type = Type::tfloat32;	break;
+		    case Timaginary64:	type = Type::tfloat64;	break;
+		    case Timaginary80:	type = Type::tfloat80;	break;
+		    default:		assert(0);
+		}
+
+		// iy * iv = -yv
+		e1->type = type;
+		e2->type = type;
+		e = new NegExp(loc, this);
+		e = e->semantic(sc);
+		return e;
+	    }
+	    else
+		type = t2;	// t2 is complex
+	}
+	else if (t2->isimaginary())
+	{
+	    type = t1;	// t1 is complex
+	}
+    }
+    return this;
+}
+
+/************************************************************/
+
+DivExp::DivExp(Loc loc, Expression *e1, Expression *e2)
+	: BinExp(loc, TOKdiv, sizeof(DivExp), e1, e2)
+{
+}
+
+Expression *DivExp::semantic(Scope *sc)
+{   Expression *e;
+
+    if (type)
+	return this;
+
+    BinExp::semanticp(sc);
+    e = op_overload(sc);
+    if (e)
+	return e;
+
+    typeCombine(sc);
+    if (e1->op != TOKslice && e2->op != TOKslice)
+    {	e1->checkArithmetic();
+	e2->checkArithmetic();
+    }
+    if (type->isfloating())
+    {	Type *t1 = e1->type;
+	Type *t2 = e2->type;
+
+	if (t1->isreal())
+	{
+	    type = t2;
+	    if (t2->isimaginary())
+	    {	Expression *e;
+
+		// x/iv = i(-x/v)
+		e2->type = t1;
+		e = new NegExp(loc, this);
+		e = e->semantic(sc);
+		return e;
+	    }
+	}
+	else if (t2->isreal())
+	{
+	    type = t1;
+	}
+	else if (t1->isimaginary())
+	{
+	    if (t2->isimaginary())
+	    {
+		switch (t1->ty)
+		{
+		    case Timaginary32:	type = Type::tfloat32;	break;
+		    case Timaginary64:	type = Type::tfloat64;	break;
+		    case Timaginary80:	type = Type::tfloat80;	break;
+		    default:		assert(0);
+		}
+	    }
+	    else
+		type = t2;	// t2 is complex
+	}
+	else if (t2->isimaginary())
+	{
+	    type = t1;	// t1 is complex
+	}
+    }
+    return this;
+}
+
+/************************************************************/
+
+ModExp::ModExp(Loc loc, Expression *e1, Expression *e2)
+	: BinExp(loc, TOKmod, sizeof(ModExp), e1, e2)
+{
+}
+
+Expression *ModExp::semantic(Scope *sc)
+{   Expression *e;
+
+    if (type)
+	return this;
+
+    BinExp::semanticp(sc);
+    e = op_overload(sc);
+    if (e)
+	return e;
+
+    typeCombine(sc);
+    if (e1->op != TOKslice && e2->op != TOKslice)
+    {	e1->checkArithmetic();
+	e2->checkArithmetic();
+    }
+    if (type->isfloating())
+    {	type = e1->type;
+	if (e2->type->iscomplex())
+	{   error("cannot perform modulo complex arithmetic");
+	    return new ErrorExp();
+	}
+    }
+    return this;
+}
+
+/************************************************************/
+
+ShlExp::ShlExp(Loc loc, Expression *e1, Expression *e2)
+	: BinExp(loc, TOKshl, sizeof(ShlExp), e1, e2)
+{
+}
+
+Expression *ShlExp::semantic(Scope *sc)
+{   Expression *e;
+
+    //printf("ShlExp::semantic(), type = %p\n", type);
+    if (!type)
+    {	BinExp::semanticp(sc);
+	e = op_overload(sc);
+	if (e)
+	    return e;
+	e1 = e1->checkIntegral();
+	e2 = e2->checkIntegral();
+	e1 = e1->integralPromotions(sc);
+	//e2 = e2->castTo(sc, Type::tshiftcnt);
+    e2 = e2->castTo(sc, e1->type); // LDC
+	type = e1->type;
+    }
+    return this;
+}
+
+/************************************************************/
+
+ShrExp::ShrExp(Loc loc, Expression *e1, Expression *e2)
+	: BinExp(loc, TOKshr, sizeof(ShrExp), e1, e2)
+{
+}
+
+Expression *ShrExp::semantic(Scope *sc)
+{   Expression *e;
+
+    if (!type)
+    {	BinExp::semanticp(sc);
+	e = op_overload(sc);
+	if (e)
+	    return e;
+	e1 = e1->checkIntegral();
+	e2 = e2->checkIntegral();
+	e1 = e1->integralPromotions(sc);
+	e2 = e2->castTo(sc, Type::tshiftcnt);
+	type = e1->type;
+    }
+    return this;
+}
+
+/************************************************************/
+
+UshrExp::UshrExp(Loc loc, Expression *e1, Expression *e2)
+	: BinExp(loc, TOKushr, sizeof(UshrExp), e1, e2)
+{
+}
+
+Expression *UshrExp::semantic(Scope *sc)
+{   Expression *e;
+
+    if (!type)
+    {	BinExp::semanticp(sc);
+	e = op_overload(sc);
+	if (e)
+	    return e;
+	e1 = e1->checkIntegral();
+	e2 = e2->checkIntegral();
+	e1 = e1->integralPromotions(sc);
+	e2 = e2->castTo(sc, Type::tshiftcnt);
+	type = e1->type;
+    }
+    return this;
+}
+
+/************************************************************/
+
+AndExp::AndExp(Loc loc, Expression *e1, Expression *e2)
+	: BinExp(loc, TOKand, sizeof(AndExp), e1, e2)
+{
+}
+
+Expression *AndExp::semantic(Scope *sc)
+{   Expression *e;
+
+    if (!type)
+    {	BinExp::semanticp(sc);
+	e = op_overload(sc);
+	if (e)
+	    return e;
+	if (e1->type->toBasetype()->ty == Tbool &&
+	    e2->type->toBasetype()->ty == Tbool)
+	{
+	    type = e1->type;
+	    e = this;
+	}
+	else
+	{
+	    typeCombine(sc);
+	    if (e1->op != TOKslice && e2->op != TOKslice)
+	    {   e1->checkIntegral();
+		e2->checkIntegral();
+	    }
+	}
+    }
+    return this;
+}
+
+/************************************************************/
+
+OrExp::OrExp(Loc loc, Expression *e1, Expression *e2)
+	: BinExp(loc, TOKor, sizeof(OrExp), e1, e2)
+{
+}
+
+Expression *OrExp::semantic(Scope *sc)
+{   Expression *e;
+
+    if (!type)
+    {	BinExp::semanticp(sc);
+	e = op_overload(sc);
+	if (e)
+	    return e;
+	if (e1->type->toBasetype()->ty == Tbool &&
+	    e2->type->toBasetype()->ty == Tbool)
+	{
+	    type = e1->type;
+	    e = this;
+	}
+	else
+	{
+	    typeCombine(sc);
+	    if (e1->op != TOKslice && e2->op != TOKslice)
+	    {   e1->checkIntegral();
+		e2->checkIntegral();
+	    }
+	}
+    }
+    return this;
+}
+
+/************************************************************/
+
+XorExp::XorExp(Loc loc, Expression *e1, Expression *e2)
+	: BinExp(loc, TOKxor, sizeof(XorExp), e1, e2)
+{
+}
+
+Expression *XorExp::semantic(Scope *sc)
+{   Expression *e;
+
+    if (!type)
+    {	BinExp::semanticp(sc);
+	e = op_overload(sc);
+	if (e)
+	    return e;
+	if (e1->type->toBasetype()->ty == Tbool &&
+	    e2->type->toBasetype()->ty == Tbool)
+	{
+	    type = e1->type;
+	    e = this;
+	}
+	else
+	{
+	    typeCombine(sc);
+	    if (e1->op != TOKslice && e2->op != TOKslice)
+	    {   e1->checkIntegral();
+		e2->checkIntegral();
+	    }
+	}
+    }
+    return this;
+}
+
+
+/************************************************************/
+
+OrOrExp::OrOrExp(Loc loc, Expression *e1, Expression *e2)
+	: BinExp(loc, TOKoror, sizeof(OrOrExp), e1, e2)
+{
+}
+
+Expression *OrOrExp::semantic(Scope *sc)
+{
+    unsigned cs1;
+
+    // same as for AndAnd
+    e1 = e1->semantic(sc);
+    e1 = resolveProperties(sc, e1);
+    e1 = e1->checkToPointer();
+    e1 = e1->checkToBoolean();
+    cs1 = sc->callSuper;
+
+    if (sc->flags & SCOPEstaticif)
+    {
+	/* If in static if, don't evaluate e2 if we don't have to.
+	 */
+	e1 = e1->optimize(WANTflags);
+	if (e1->isBool(TRUE))
+	{
+	    return new IntegerExp(loc, 1, Type::tboolean);
+	}
+    }
+
+    e2 = e2->semantic(sc);
+    sc->mergeCallSuper(loc, cs1);
+    e2 = resolveProperties(sc, e2);
+    e2 = e2->checkToPointer();
+
+    type = Type::tboolean;
+    if (e2->type->ty == Tvoid)
+	type = Type::tvoid;
+    if (e2->op == TOKtype || e2->op == TOKimport)
+	error("%s is not an expression", e2->toChars());
+    return this;
+}
+
+Expression *OrOrExp::checkToBoolean()
+{
+    e2 = e2->checkToBoolean();
+    return this;
+}
+
+int OrOrExp::isBit()
+{
+    return TRUE;
+}
+
+int OrOrExp::checkSideEffect(int flag)
+{
+    if (flag == 2)
+    {
+	return e1->checkSideEffect(2) || e2->checkSideEffect(2);
+    }
+    else
+    {	e1->checkSideEffect(1);
+	return e2->checkSideEffect(flag);
+    }
+}
+
+/************************************************************/
+
+AndAndExp::AndAndExp(Loc loc, Expression *e1, Expression *e2)
+	: BinExp(loc, TOKandand, sizeof(AndAndExp), e1, e2)
+{
+}
+
+Expression *AndAndExp::semantic(Scope *sc)
+{
+    unsigned cs1;
+
+    // same as for OrOr
+    e1 = e1->semantic(sc);
+    e1 = resolveProperties(sc, e1);
+    e1 = e1->checkToPointer();
+    e1 = e1->checkToBoolean();
+    cs1 = sc->callSuper;
+
+    if (sc->flags & SCOPEstaticif)
+    {
+	/* If in static if, don't evaluate e2 if we don't have to.
+	 */
+	e1 = e1->optimize(WANTflags);
+	if (e1->isBool(FALSE))
+	{
+	    return new IntegerExp(loc, 0, Type::tboolean);
+	}
+    }
+
+    e2 = e2->semantic(sc);
+    sc->mergeCallSuper(loc, cs1);
+    e2 = resolveProperties(sc, e2);
+    e2 = e2->checkToPointer();
+
+    type = Type::tboolean;
+    if (e2->type->ty == Tvoid)
+	type = Type::tvoid;
+    if (e2->op == TOKtype || e2->op == TOKimport)
+	error("%s is not an expression", e2->toChars());
+    return this;
+}
+
+Expression *AndAndExp::checkToBoolean()
+{
+    e2 = e2->checkToBoolean();
+    return this;
+}
+
+int AndAndExp::isBit()
+{
+    return TRUE;
+}
+
+int AndAndExp::checkSideEffect(int flag)
+{
+    if (flag == 2)
+    {
+	return e1->checkSideEffect(2) || e2->checkSideEffect(2);
+    }
+    else
+    {
+	e1->checkSideEffect(1);
+	return e2->checkSideEffect(flag);
+    }
+}
+
+/************************************************************/
+
+InExp::InExp(Loc loc, Expression *e1, Expression *e2)
+	: BinExp(loc, TOKin, sizeof(InExp), e1, e2)
+{
+}
+
+Expression *InExp::semantic(Scope *sc)
+{   Expression *e;
+
+    if (type)
+	return this;
+
+    BinExp::semanticp(sc);
+    e = op_overload(sc);
+    if (e)
+	return e;
+
+    //type = Type::tboolean;
+    Type *t2b = e2->type->toBasetype();
+    if (t2b->ty != Taarray)
+    {
+	error("rvalue of in expression must be an associative array, not %s", e2->type->toChars());
+	type = Type::terror;
+    }
+    else
+    {
+	TypeAArray *ta = (TypeAArray *)t2b;
+
+	// Special handling for array keys
+	if (!arrayTypeCompatible(e1->loc, e1->type, ta->index))
+	{
+	    // Convert key to type of key
+	    e1 = e1->implicitCastTo(sc, ta->index);
+	}
+
+	// Return type is pointer to value
+	type = ta->nextOf()->pointerTo();
+    }
+    return this;
+}
+
+int InExp::isBit()
+{
+    return FALSE;
+}
+
+
+/************************************************************/
+
+/* This deletes the key e1 from the associative array e2
+ */
+
+RemoveExp::RemoveExp(Loc loc, Expression *e1, Expression *e2)
+	: BinExp(loc, TOKremove, sizeof(RemoveExp), e1, e2)
+{
+    type = Type::tvoid;
+}
+
+/************************************************************/
+
+CmpExp::CmpExp(enum TOK op, Loc loc, Expression *e1, Expression *e2)
+	: BinExp(loc, op, sizeof(CmpExp), e1, e2)
+{
+}
+
+Expression *CmpExp::semantic(Scope *sc)
+{   Expression *e;
+    Type *t1;
+    Type *t2;
+
+#if LOGSEMANTIC
+    printf("CmpExp::semantic('%s')\n", toChars());
+#endif
+    if (type)
+	return this;
+
+    BinExp::semanticp(sc);
+
+    if (e1->type->toBasetype()->ty == Tclass && e2->op == TOKnull ||
+	e2->type->toBasetype()->ty == Tclass && e1->op == TOKnull)
+    {
+	error("do not use null when comparing class types");
+    }
+
+    e = op_overload(sc);
+    if (e)
+    {
+	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;
+    }
+
+    typeCombine(sc);
+    type = Type::tboolean;
+
+    // Special handling for array comparisons
+    t1 = e1->type->toBasetype();
+    t2 = e2->type->toBasetype();
+    if ((t1->ty == Tarray || t1->ty == Tsarray || t1->ty == Tpointer) &&
+	(t2->ty == Tarray || t2->ty == Tsarray || t2->ty == Tpointer))
+    {
+	if (t1->nextOf()->implicitConvTo(t2->nextOf()) < MATCHconst &&
+	    t2->nextOf()->implicitConvTo(t1->nextOf()) < MATCHconst &&
+	    (t1->nextOf()->ty != Tvoid && t2->nextOf()->ty != Tvoid))
+	    error("array comparison type mismatch, %s vs %s", t1->nextOf()->toChars(), t2->nextOf()->toChars());
+	e = this;
+    }
+    else if (t1->ty == Tstruct || t2->ty == Tstruct ||
+	     (t1->ty == Tclass && t2->ty == Tclass))
+    {
+	if (t2->ty == Tstruct)
+	    error("need member function opCmp() for %s %s to compare", t2->toDsymbol(sc)->kind(), t2->toChars());
+	else
+	    error("need member function opCmp() for %s %s to compare", t1->toDsymbol(sc)->kind(), t1->toChars());
+	e = this;
+    }
+#if 1
+    else if (t1->iscomplex() || t2->iscomplex())
+    {
+	error("compare not defined for complex operands");
+	e = new ErrorExp();
+    }
+#endif
+    else
+	e = this;
+    //printf("CmpExp: %s\n", e->toChars());
+    return e;
+}
+
+int CmpExp::isBit()
+{
+    return TRUE;
+}
+
+
+/************************************************************/
+
+EqualExp::EqualExp(enum TOK op, Loc loc, Expression *e1, Expression *e2)
+	: BinExp(loc, op, sizeof(EqualExp), e1, e2)
+{
+    assert(op == TOKequal || op == TOKnotequal);
+}
+
+Expression *EqualExp::semantic(Scope *sc)
+{   Expression *e;
+    Type *t1;
+    Type *t2;
+
+    //printf("EqualExp::semantic('%s')\n", toChars());
+    if (type)
+	return this;
+
+    BinExp::semanticp(sc);
+
+    /* Before checking for operator overloading, check to see if we're
+     * comparing the addresses of two statics. If so, we can just see
+     * if they are the same symbol.
+     */
+    if (e1->op == TOKaddress && e2->op == TOKaddress)
+    {	AddrExp *ae1 = (AddrExp *)e1;
+	AddrExp *ae2 = (AddrExp *)e2;
+
+	if (ae1->e1->op == TOKvar && ae2->e1->op == TOKvar)
+	{   VarExp *ve1 = (VarExp *)ae1->e1;
+	    VarExp *ve2 = (VarExp *)ae2->e1;
+
+	    if (ve1->var == ve2->var /*|| ve1->var->toSymbol() == ve2->var->toSymbol()*/)
+	    {
+		// They are the same, result is 'true' for ==, 'false' for !=
+		e = new IntegerExp(loc, (op == TOKequal), Type::tboolean);
+		return e;
+	    }
+	}
+    }
+
+    if (e1->type->toBasetype()->ty == Tclass && e2->op == TOKnull ||
+	e2->type->toBasetype()->ty == Tclass && e1->op == TOKnull)
+    {
+	error("use '%s' instead of '%s' when comparing with null",
+		Token::toChars(op == TOKequal ? TOKidentity : TOKnotidentity),
+		Token::toChars(op));
+    }
+
+    //if (e2->op != TOKnull)
+    {
+	e = op_overload(sc);
+	if (e)
+	{
+	    if (op == TOKnotequal)
+	    {
+		e = new NotExp(e->loc, e);
+		e = e->semantic(sc);
+	    }
+	    return e;
+	}
+    }
+
+    e = typeCombine(sc);
+    type = Type::tboolean;
+
+    // Special handling for array comparisons
+    if (!arrayTypeCompatible(loc, e1->type, e2->type))
+    {
+	if (e1->type != e2->type && e1->type->isfloating() && e2->type->isfloating())
+	{
+	    // Cast both to complex
+	    e1 = e1->castTo(sc, Type::tcomplex80);
+	    e2 = e2->castTo(sc, Type::tcomplex80);
+	}
+    }
+    return e;
+}
+
+int EqualExp::isBit()
+{
+    return TRUE;
+}
+
+
+
+/************************************************************/
+
+IdentityExp::IdentityExp(enum TOK op, Loc loc, Expression *e1, Expression *e2)
+	: BinExp(loc, op, sizeof(IdentityExp), e1, e2)
+{
+}
+
+Expression *IdentityExp::semantic(Scope *sc)
+{
+    if (type)
+	return this;
+
+    BinExp::semanticp(sc);
+    type = Type::tboolean;
+    typeCombine(sc);
+    if (e1->type != e2->type && e1->type->isfloating() && e2->type->isfloating())
+    {
+	// Cast both to complex
+	e1 = e1->castTo(sc, Type::tcomplex80);
+	e2 = e2->castTo(sc, Type::tcomplex80);
+    }
+    return this;
+}
+
+int IdentityExp::isBit()
+{
+    return TRUE;
+}
+
+
+/****************************************************************/
+
+CondExp::CondExp(Loc loc, Expression *econd, Expression *e1, Expression *e2)
+	: BinExp(loc, TOKquestion, sizeof(CondExp), e1, e2)
+{
+    this->econd = econd;
+}
+
+Expression *CondExp::syntaxCopy()
+{
+    return new CondExp(loc, econd->syntaxCopy(), e1->syntaxCopy(), e2->syntaxCopy());
+}
+
+
+Expression *CondExp::semantic(Scope *sc)
+{   Type *t1;
+    Type *t2;
+    unsigned cs0;
+    unsigned cs1;
+
+#if LOGSEMANTIC
+    printf("CondExp::semantic('%s')\n", toChars());
+#endif
+    if (type)
+	return this;
+
+    econd = econd->semantic(sc);
+    econd = resolveProperties(sc, econd);
+    econd = econd->checkToPointer();
+    econd = econd->checkToBoolean();
+
+#if 0	/* this cannot work right because the types of e1 and e2
+ 	 * both contribute to the type of the result.
+	 */
+    if (sc->flags & SCOPEstaticif)
+    {
+	/* If in static if, don't evaluate what we don't have to.
+	 */
+	econd = econd->optimize(WANTflags);
+	if (econd->isBool(TRUE))
+	{
+	    e1 = e1->semantic(sc);
+	    e1 = resolveProperties(sc, e1);
+	    return e1;
+	}
+	else if (econd->isBool(FALSE))
+	{
+	    e2 = e2->semantic(sc);
+	    e2 = resolveProperties(sc, e2);
+	    return e2;
+	}
+    }
+#endif
+
+
+    cs0 = sc->callSuper;
+    e1 = e1->semantic(sc);
+    e1 = resolveProperties(sc, e1);
+    cs1 = sc->callSuper;
+    sc->callSuper = cs0;
+    e2 = e2->semantic(sc);
+    e2 = resolveProperties(sc, e2);
+    sc->mergeCallSuper(loc, cs1);
+
+
+    // If either operand is void, the result is void
+    t1 = e1->type;
+    t2 = e2->type;
+    if (t1->ty == Tvoid || t2->ty == Tvoid)
+	type = Type::tvoid;
+    else if (t1 == t2)
+	type = t1;
+    else
+    {
+	typeCombine(sc);
+	switch (e1->type->toBasetype()->ty)
+	{
+	    case Tcomplex32:
+	    case Tcomplex64:
+	    case Tcomplex80:
+		e2 = e2->castTo(sc, e1->type);
+		break;
+	}
+	switch (e2->type->toBasetype()->ty)
+	{
+	    case Tcomplex32:
+	    case Tcomplex64:
+	    case Tcomplex80:
+		e1 = e1->castTo(sc, e2->type);
+		break;
+	}
+	if (type->toBasetype()->ty == Tarray)
+	{
+	    e1 = e1->castTo(sc, type);
+	    e2 = e2->castTo(sc, type);
+	}
+    }
+#if 0
+    printf("res: %s\n", type->toChars());
+    printf("e1 : %s\n", e1->type->toChars());
+    printf("e2 : %s\n", e2->type->toChars());
+#endif
+    return this;
+}
+
+#if DMDV2
+int CondExp::isLvalue()
+{
+    return e1->isLvalue() && e2->isLvalue();
+}
+#endif
+
+Expression *CondExp::toLvalue(Scope *sc, Expression *ex)
+{
+    PtrExp *e;
+
+    // convert (econd ? e1 : e2) to *(econd ? &e1 : &e2)
+    e = new PtrExp(loc, this, type);
+
+    e1 = e1->addressOf(sc);
+    //e1 = e1->toLvalue(sc, NULL);
+
+    e2 = e2->addressOf(sc);
+    //e2 = e2->toLvalue(sc, NULL);
+
+    typeCombine(sc);
+
+    type = e2->type;
+    return e;
+}
+
+Expression *CondExp::modifiableLvalue(Scope *sc, Expression *e)
+{
+    error("conditional expression %s is not a modifiable lvalue", toChars());
+    return this;
+}
+
+void CondExp::checkEscape()
+{
+    e1->checkEscape();
+    e2->checkEscape();
+}
+
+
+Expression *CondExp::checkToBoolean()
+{
+    e1 = e1->checkToBoolean();
+    e2 = e2->checkToBoolean();
+    return this;
+}
+
+int CondExp::checkSideEffect(int flag)
+{
+    if (flag == 2)
+    {
+	return econd->checkSideEffect(2) ||
+		e1->checkSideEffect(2) ||
+		e2->checkSideEffect(2);
+    }
+    else
+    {
+	econd->checkSideEffect(1);
+	e1->checkSideEffect(flag);
+	return e2->checkSideEffect(flag);
+    }
+}
+
+#if DMDV2
+int CondExp::canThrow()
+{
+    return econd->canThrow() || e1->canThrow() || e2->canThrow();
+}
+#endif
+
+void CondExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    expToCBuffer(buf, hgs, econd, PREC_oror);
+    buf->writestring(" ? ");
+    expToCBuffer(buf, hgs, e1, PREC_expr);
+    buf->writestring(" : ");
+    expToCBuffer(buf, hgs, e2, PREC_cond);
+}
+
+/************************************************************/
+
+#if IN_LLVM
+
+// Strictly LDC specific stuff
+
+GEPExp::GEPExp(Loc loc, Expression* e, Identifier* id, unsigned idx)
+    : UnaExp(loc, TOKgep, sizeof(GEPExp), e)
+{
+    index = idx;
+    ident = id;
+}
+
+void GEPExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    expToCBuffer(buf, hgs, e1, PREC_primary);
+    buf->writeByte('.');
+    buf->writestring(ident->toChars());
+}
+
+Expression* GEPExp::toLvalue(Scope* sc, Expression* e)
+{
+    // GEP's are always lvalues, at least in the "LLVM sense" ...
+    return this;
+}
+
+#endif
+
+/****************************************************************/
+
+DefaultInitExp::DefaultInitExp(Loc loc, enum TOK subop, int size)
+    : Expression(loc, TOKdefault, size)
+{
+    this->subop = subop;
+}
+
+void DefaultInitExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    buf->writestring(Token::toChars(subop));
+}
+
+/****************************************************************/
+
+FileInitExp::FileInitExp(Loc loc)
+    : DefaultInitExp(loc, TOKfile, sizeof(FileInitExp))
+{
+}
+
+Expression *FileInitExp::semantic(Scope *sc)
+{
+    //printf("FileInitExp::semantic()\n");
+    type = Type::tchar->invariantOf()->arrayOf();
+    return this;
+}
+
+Expression *FileInitExp::resolve(Loc loc, Scope *sc)
+{
+    //printf("FileInitExp::resolve() %s\n", toChars());
+    const char *s = loc.filename ? loc.filename : sc->module->ident->toChars();
+    Expression *e = new StringExp(loc, (char *)s);
+    e = e->semantic(sc);
+    e = e->castTo(sc, type);
+    return e;
+}
+
+/****************************************************************/
+
+LineInitExp::LineInitExp(Loc loc)
+    : DefaultInitExp(loc, TOKline, sizeof(LineInitExp))
+{
+}
+
+Expression *LineInitExp::semantic(Scope *sc)
+{
+    type = Type::tint32;
+    return this;
+}
+
+Expression *LineInitExp::resolve(Loc loc, Scope *sc)
+{
+    Expression *e = new IntegerExp(loc, loc.linnum, Type::tint32);
+    e = e->castTo(sc, type);
+    return e;
+}
+
+
--- a/dmd2/expression.h	Mon Jun 01 01:28:18 2009 +0200
+++ b/dmd2/expression.h	Mon Jun 01 19:02:20 2009 +0100
@@ -1,1619 +1,1973 @@
-
-// Compiler implementation of the D programming language
-// Copyright (c) 1999-2008 by Digital Mars
-// All Rights Reserved
-// written by Walter Bright
-// http://www.digitalmars.com
-// License for redistribution is by either the Artistic License
-// in artistic.txt, or the GNU General Public License in gnu.txt.
-// See the included readme.txt for details.
-
-#ifndef DMD_EXPRESSION_H
-#define DMD_EXPRESSION_H
-
-#include "mars.h"
-#include "identifier.h"
-#include "lexer.h"
-#include "arraytypes.h"
-
-struct Type;
-struct Scope;
-struct TupleDeclaration;
-struct VarDeclaration;
-struct FuncDeclaration;
-struct FuncLiteralDeclaration;
-struct Declaration;
-struct CtorDeclaration;
-struct NewDeclaration;
-struct Dsymbol;
-struct Import;
-struct Module;
-struct ScopeDsymbol;
-struct InlineCostState;
-struct InlineDoState;
-struct InlineScanState;
-struct Expression;
-struct Declaration;
-struct AggregateDeclaration;
-struct StructDeclaration;
-struct TemplateInstance;
-struct TemplateDeclaration;
-struct ClassDeclaration;
-struct HdrGenState;
-struct BinExp;
-struct InterState;
-struct Symbol;		// back end symbol
-struct OverloadSet;
-namespace llvm
-{
-    class Constant;
-    class ConstantInt;
-}
-
-enum TOK;
-
-// Back end
-struct IRState;
-struct dt_t;
-
-#if IN_LLVM
-struct DValue;
-typedef DValue elem;
-#else
-#ifdef IN_GCC
-union tree_node; typedef union tree_node elem;
-#else
-struct elem;
-#endif
-#endif
-
-void initPrecedence();
-
-Expression *resolveProperties(Scope *sc, Expression *e);
-void accessCheck(Loc loc, Scope *sc, Expression *e, Declaration *d);
-Expression *build_overload(Loc loc, Scope *sc, Expression *ethis, Expression *earg, Identifier *id);
-Dsymbol *search_function(ScopeDsymbol *ad, Identifier *funcid);
-void inferApplyArgTypes(enum TOK op, Arguments *arguments, Expression *aggr);
-void argExpTypesToCBuffer(OutBuffer *buf, Expressions *arguments, HdrGenState *hgs);
-void argsToCBuffer(OutBuffer *buf, Expressions *arguments, HdrGenState *hgs);
-void expandTuples(Expressions *exps);
-FuncDeclaration *hasThis(Scope *sc);
-Expression *fromConstInitializer(int result, Expression *e);
-int arrayExpressionCanThrow(Expressions *exps);
-
-struct Expression : Object
-{
-    Loc loc;			// file location
-    enum TOK op;		// handy to minimize use of dynamic_cast
-    Type *type;			// !=NULL means that semantic() has been run
-    int size;			// # of bytes in Expression so we can copy() it
-
-    Expression(Loc loc, enum TOK op, int size);
-    Expression *copy();
-    virtual Expression *syntaxCopy();
-    virtual Expression *semantic(Scope *sc);
-
-    int dyncast() { return DYNCAST_EXPRESSION; }	// kludge for template.isExpression()
-
-    void print();
-    char *toChars();
-    virtual void dump(int indent);
-    void error(const char *format, ...);
-    virtual void rvalue();
-
-    static Expression *combine(Expression *e1, Expression *e2);
-    static Expressions *arraySyntaxCopy(Expressions *exps);
-
-    virtual integer_t toInteger();
-    virtual uinteger_t toUInteger();
-    virtual real_t toReal();
-    virtual real_t toImaginary();
-    virtual complex_t toComplex();
-    virtual void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-    virtual void toMangleBuffer(OutBuffer *buf);
-    virtual int isLvalue();
-    virtual Expression *toLvalue(Scope *sc, Expression *e);
-    virtual Expression *modifiableLvalue(Scope *sc, Expression *e);
-    Expression *implicitCastTo(Scope *sc, Type *t);
-    virtual MATCH implicitConvTo(Type *t);
-    virtual Expression *castTo(Scope *sc, Type *t);
-    virtual void checkEscape();
-    void checkScalar();
-    void checkNoBool();
-    Expression *checkIntegral();
-    Expression *checkArithmetic();
-    void checkDeprecated(Scope *sc, Dsymbol *s);
-    virtual Expression *checkToBoolean();
-    Expression *checkToPointer();
-    Expression *addressOf(Scope *sc);
-    Expression *deref();
-    Expression *integralPromotions(Scope *sc);
-
-    Expression *toDelegate(Scope *sc, Type *t);
-    virtual void scanForNestedRef(Scope *sc);
-
-    virtual Expression *optimize(int result);
-    #define WANTflags	1
-    #define WANTvalue	2
-    #define WANTinterpret 4
-
-    virtual Expression *interpret(InterState *istate);
-
-    virtual int isConst();
-    virtual int isBool(int result);
-    virtual int isBit();
-    virtual int checkSideEffect(int flag);
-    virtual int canThrow();
-
-    virtual int inlineCost(InlineCostState *ics);
-    virtual Expression *doInline(InlineDoState *ids);
-    virtual Expression *inlineScan(InlineScanState *iss);
-
-    // For operator overloading
-    virtual int isCommutative();
-    virtual Identifier *opId();
-    virtual Identifier *opId_r();
-
-    // For array ops
-    virtual void buildArrayIdent(OutBuffer *buf, Expressions *arguments);
-    virtual Expression *buildArrayLoop(Arguments *fparams);
-
-    // Back end
-    virtual elem *toElem(IRState *irs);
-    virtual dt_t **toDt(dt_t **pdt);
-    // LDC
-    virtual llvm::Constant *toConstElem(IRState *irs);
-};
-
-struct IntegerExp : Expression
-{
-    integer_t value;
-
-    IntegerExp(Loc loc, integer_t value, Type *type);
-    IntegerExp(integer_t value);
-    int equals(Object *o);
-    Expression *semantic(Scope *sc);
-    Expression *interpret(InterState *istate);
-    char *toChars();
-    void dump(int indent);
-    integer_t toInteger();
-    real_t toReal();
-    real_t toImaginary();
-    complex_t toComplex();
-    int isConst();
-    int isBool(int result);
-    MATCH implicitConvTo(Type *t);
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-    void toMangleBuffer(OutBuffer *buf);
-    Expression *toLvalue(Scope *sc, Expression *e);
-    elem *toElem(IRState *irs);
-    dt_t **toDt(dt_t **pdt);
-    // LDC
-    virtual llvm::Constant *toConstElem(IRState *irs);
-};
-
-struct RealExp : Expression
-{
-    real_t value;
-
-    RealExp(Loc loc, real_t value, Type *type);
-    int equals(Object *o);
-    Expression *semantic(Scope *sc);
-    Expression *interpret(InterState *istate);
-    char *toChars();
-    integer_t toInteger();
-    uinteger_t toUInteger();
-    real_t toReal();
-    real_t toImaginary();
-    complex_t toComplex();
-    Expression *castTo(Scope *sc, Type *t);
-    int isConst();
-    int isBool(int result);
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-    void toMangleBuffer(OutBuffer *buf);
-    elem *toElem(IRState *irs);
-    dt_t **toDt(dt_t **pdt);
-    // LDC
-    virtual llvm::Constant *toConstElem(IRState *irs);
-};
-
-struct ComplexExp : Expression
-{
-    complex_t value;
-
-    ComplexExp(Loc loc, complex_t value, Type *type);
-    int equals(Object *o);
-    Expression *semantic(Scope *sc);
-    Expression *interpret(InterState *istate);
-    char *toChars();
-    integer_t toInteger();
-    uinteger_t toUInteger();
-    real_t toReal();
-    real_t toImaginary();
-    complex_t toComplex();
-    Expression *castTo(Scope *sc, Type *t);
-    int isConst();
-    int isBool(int result);
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-    void toMangleBuffer(OutBuffer *buf);
-#ifdef _DH
-    OutBuffer hexp;
-#endif
-    elem *toElem(IRState *irs);
-    dt_t **toDt(dt_t **pdt);
-    // LDC
-    virtual llvm::Constant *toConstElem(IRState *irs);
-};
-
-struct IdentifierExp : Expression
-{
-    Identifier *ident;
-    Declaration *var;
-
-    IdentifierExp(Loc loc, Identifier *ident);
-    IdentifierExp(Loc loc, Declaration *var);
-    Expression *semantic(Scope *sc);
-    char *toChars();
-    void dump(int indent);
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-    int isLvalue();
-    Expression *toLvalue(Scope *sc, Expression *e);
-};
-
-struct DollarExp : IdentifierExp
-{
-    DollarExp(Loc loc);
-};
-
-struct DsymbolExp : Expression
-{
-    Dsymbol *s;
-    int hasOverloads;
-
-    DsymbolExp(Loc loc, Dsymbol *s, int hasOverloads = 0);
-    Expression *semantic(Scope *sc);
-    char *toChars();
-    void dump(int indent);
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-    int isLvalue();
-    Expression *toLvalue(Scope *sc, Expression *e);
-};
-
-struct ThisExp : Expression
-{
-    Declaration *var;
-
-    ThisExp(Loc loc);
-    Expression *semantic(Scope *sc);
-    int isBool(int result);
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-    int isLvalue();
-    Expression *toLvalue(Scope *sc, Expression *e);
-    void scanForNestedRef(Scope *sc);
-
-    int inlineCost(InlineCostState *ics);
-    Expression *doInline(InlineDoState *ids);
-    //Expression *inlineScan(InlineScanState *iss);
-
-    elem *toElem(IRState *irs);
-};
-
-struct SuperExp : ThisExp
-{
-    SuperExp(Loc loc);
-    Expression *semantic(Scope *sc);
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-    void scanForNestedRef(Scope *sc);
-
-    int inlineCost(InlineCostState *ics);
-    Expression *doInline(InlineDoState *ids);
-    //Expression *inlineScan(InlineScanState *iss);
-};
-
-struct NullExp : Expression
-{
-    unsigned char committed;	// !=0 if type is committed
-
-    NullExp(Loc loc);
-    Expression *semantic(Scope *sc);
-    int isBool(int result);
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-    void toMangleBuffer(OutBuffer *buf);
-    MATCH implicitConvTo(Type *t);
-    Expression *castTo(Scope *sc, Type *t);
-    Expression *interpret(InterState *istate);
-    elem *toElem(IRState *irs);
-    dt_t **toDt(dt_t **pdt);
-    // LDC
-    virtual llvm::Constant *toConstElem(IRState *irs);
-};
-
-struct StringExp : Expression
-{
-    void *string;	// char, wchar, or dchar data
-    size_t len;		// number of chars, wchars, or dchars
-    unsigned char sz;	// 1: char, 2: wchar, 4: dchar
-    unsigned char committed;	// !=0 if type is committed
-    unsigned char postfix;	// 'c', 'w', 'd'
-
-    StringExp(Loc loc, char *s);
-    StringExp(Loc loc, void *s, size_t len);
-    StringExp(Loc loc, void *s, size_t len, unsigned char postfix);
-    //Expression *syntaxCopy();
-    int equals(Object *o);
-    char *toChars();
-    Expression *semantic(Scope *sc);
-    Expression *interpret(InterState *istate);
-    StringExp *toUTF8(Scope *sc);
-    MATCH implicitConvTo(Type *t);
-    Expression *castTo(Scope *sc, Type *t);
-    int compare(Object *obj);
-    int isBool(int result);
-    unsigned charAt(size_t i);
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-    void toMangleBuffer(OutBuffer *buf);
-    elem *toElem(IRState *irs);
-    dt_t **toDt(dt_t **pdt);
-    // LDC
-    virtual llvm::Constant *toConstElem(IRState *irs);
-};
-
-// Tuple
-
-struct TupleExp : Expression
-{
-    Expressions *exps;
-
-    TupleExp(Loc loc, Expressions *exps);
-    TupleExp(Loc loc, TupleDeclaration *tup);
-    Expression *syntaxCopy();
-    int equals(Object *o);
-    Expression *semantic(Scope *sc);
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-    void scanForNestedRef(Scope *sc);
-    void checkEscape();
-    int checkSideEffect(int flag);
-    Expression *optimize(int result);
-    Expression *interpret(InterState *istate);
-    Expression *castTo(Scope *sc, Type *t);
-    elem *toElem(IRState *irs);
-    int canThrow();
-
-    int inlineCost(InlineCostState *ics);
-    Expression *doInline(InlineDoState *ids);
-    Expression *inlineScan(InlineScanState *iss);
-};
-
-struct ArrayLiteralExp : Expression
-{
-    Expressions *elements;
-
-    ArrayLiteralExp(Loc loc, Expressions *elements);
-    ArrayLiteralExp(Loc loc, Expression *e);
-
-    Expression *syntaxCopy();
-    Expression *semantic(Scope *sc);
-    int isBool(int result);
-    elem *toElem(IRState *irs);
-    int checkSideEffect(int flag);
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-    void toMangleBuffer(OutBuffer *buf);
-    void scanForNestedRef(Scope *sc);
-    Expression *optimize(int result);
-    Expression *interpret(InterState *istate);
-    MATCH implicitConvTo(Type *t);
-    Expression *castTo(Scope *sc, Type *t);
-    dt_t **toDt(dt_t **pdt);
-    int canThrow();
-
-    int inlineCost(InlineCostState *ics);
-    Expression *doInline(InlineDoState *ids);
-    Expression *inlineScan(InlineScanState *iss);
-    // LDC
-    virtual llvm::Constant *toConstElem(IRState *irs);
-};
-
-struct AssocArrayLiteralExp : Expression
-{
-    Expressions *keys;
-    Expressions *values;
-
-    AssocArrayLiteralExp(Loc loc, Expressions *keys, Expressions *values);
-
-    Expression *syntaxCopy();
-    Expression *semantic(Scope *sc);
-    int isBool(int result);
-    elem *toElem(IRState *irs);
-    int checkSideEffect(int flag);
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-    void toMangleBuffer(OutBuffer *buf);
-    void scanForNestedRef(Scope *sc);
-    Expression *optimize(int result);
-    Expression *interpret(InterState *istate);
-    MATCH implicitConvTo(Type *t);
-    Expression *castTo(Scope *sc, Type *t);
-    int canThrow();
-
-    int inlineCost(InlineCostState *ics);
-    Expression *doInline(InlineDoState *ids);
-    Expression *inlineScan(InlineScanState *iss);
-    // LDC
-    virtual llvm::Constant *toConstElem(IRState *irs);
-};
-
-struct StructLiteralExp : Expression
-{
-    StructDeclaration *sd;		// which aggregate this is for
-    Expressions *elements;	// parallels sd->fields[] with
-				// NULL entries for fields to skip
-
-    Symbol *sym;		// back end symbol to initialize with literal
-    size_t soffset;		// offset from start of s
-    int fillHoles;		// fill alignment 'holes' with zero
-
-    StructLiteralExp(Loc loc, StructDeclaration *sd, Expressions *elements);
-
-    Expression *syntaxCopy();
-    Expression *semantic(Scope *sc);
-    Expression *getField(Type *type, unsigned offset);
-    int getFieldIndex(Type *type, unsigned offset);
-    elem *toElem(IRState *irs);
-    int checkSideEffect(int flag);
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-    void toMangleBuffer(OutBuffer *buf);
-    void scanForNestedRef(Scope *sc);
-    Expression *optimize(int result);
-    Expression *interpret(InterState *istate);
-    dt_t **toDt(dt_t **pdt);
-    int isLvalue();
-    Expression *toLvalue(Scope *sc, Expression *e);
-    int canThrow();
-    MATCH implicitConvTo(Type *t);
-
-    int inlineCost(InlineCostState *ics);
-    Expression *doInline(InlineDoState *ids);
-    Expression *inlineScan(InlineScanState *iss);
-    // LDC
-    virtual llvm::Constant *toConstElem(IRState *irs);
-};
-
-struct TypeDotIdExp : Expression
-{
-    Identifier *ident;
-
-    TypeDotIdExp(Loc loc, Type *type, Identifier *ident);
-    Expression *syntaxCopy();
-    Expression *semantic(Scope *sc);
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-    elem *toElem(IRState *irs);
-};
-
-struct TypeExp : Expression
-{
-    TypeExp(Loc loc, Type *type);
-    Expression *semantic(Scope *sc);
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-    Expression *optimize(int result);
-    elem *toElem(IRState *irs);
-};
-
-struct ScopeExp : Expression
-{
-    ScopeDsymbol *sds;
-
-    ScopeExp(Loc loc, ScopeDsymbol *sds);
-    Expression *syntaxCopy();
-    Expression *semantic(Scope *sc);
-    elem *toElem(IRState *irs);
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-};
-
-struct TemplateExp : Expression
-{
-    TemplateDeclaration *td;
-
-    TemplateExp(Loc loc, TemplateDeclaration *td);
-    void rvalue();
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-};
-
-struct NewExp : Expression
-{
-    /* thisexp.new(newargs) newtype(arguments)
-     */
-    Expression *thisexp;	// if !NULL, 'this' for class being allocated
-    Expressions *newargs;	// Array of Expression's to call new operator
-    Type *newtype;
-    Expressions *arguments;	// Array of Expression's
-
-    CtorDeclaration *member;	// constructor function
-    NewDeclaration *allocator;	// allocator function
-    int onstack;		// allocate on stack
-
-    NewExp(Loc loc, Expression *thisexp, Expressions *newargs,
-	Type *newtype, Expressions *arguments);
-    Expression *syntaxCopy();
-    Expression *semantic(Scope *sc);
-    elem *toElem(IRState *irs);
-    int checkSideEffect(int flag);
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-    void scanForNestedRef(Scope *sc);
-    int canThrow();
-
-    //int inlineCost(InlineCostState *ics);
-    Expression *doInline(InlineDoState *ids);
-    //Expression *inlineScan(InlineScanState *iss);
-};
-
-struct NewAnonClassExp : Expression
-{
-    /* thisexp.new(newargs) class baseclasses { } (arguments)
-     */
-    Expression *thisexp;	// if !NULL, 'this' for class being allocated
-    Expressions *newargs;	// Array of Expression's to call new operator
-    ClassDeclaration *cd;	// class being instantiated
-    Expressions *arguments;	// Array of Expression's to call class constructor
-
-    NewAnonClassExp(Loc loc, Expression *thisexp, Expressions *newargs,
-	ClassDeclaration *cd, Expressions *arguments);
-    Expression *syntaxCopy();
-    Expression *semantic(Scope *sc);
-    int checkSideEffect(int flag);
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-    int canThrow();
-};
-
-struct SymbolExp : Expression
-{
-    Declaration *var;
-    int hasOverloads;
-
-    SymbolExp(Loc loc, enum TOK op, int size, Declaration *var, int hasOverloads);
-
-    elem *toElem(IRState *irs);
-};
-
-// Offset from symbol
-
-struct SymOffExp : SymbolExp
-{
-    unsigned offset;
-
-    SymOffExp(Loc loc, Declaration *var, unsigned offset, int hasOverloads = 0);
-    Expression *semantic(Scope *sc);
-    void checkEscape();
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-    int isConst();
-    int isBool(int result);
-    Expression *doInline(InlineDoState *ids);
-    MATCH implicitConvTo(Type *t);
-    Expression *castTo(Scope *sc, Type *t);
-    void scanForNestedRef(Scope *sc);
-
-    dt_t **toDt(dt_t **pdt);
-
-    // LDC
-    elem *toElem(IRState* irs);
-};
-
-// Variable
-
-struct VarExp : SymbolExp
-{
-    VarExp(Loc loc, Declaration *var, int hasOverloads = 0);
-    int equals(Object *o);
-    Expression *semantic(Scope *sc);
-    Expression *optimize(int result);
-    Expression *interpret(InterState *istate);
-    void dump(int indent);
-    char *toChars();
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-    void checkEscape();
-    int isLvalue();
-    Expression *toLvalue(Scope *sc, Expression *e);
-    Expression *modifiableLvalue(Scope *sc, Expression *e);
-    dt_t **toDt(dt_t **pdt);
-    void scanForNestedRef(Scope *sc);
-
-    int inlineCost(InlineCostState *ics);
-    Expression *doInline(InlineDoState *ids);
-    //Expression *inlineScan(InlineScanState *iss);
-    // LDC
-    virtual llvm::Constant *toConstElem(IRState *irs);
-    virtual elem *toElem(IRState* irs);
-};
-
-#if DMDV2
-// Overload Set
-
-struct OverExp : Expression
-{
-    OverloadSet *vars;
-
-    OverExp(OverloadSet *s);
-    int isLvalue();
-    Expression *toLvalue(Scope *sc, Expression *e);
-};
-#endif
-
-// Function/Delegate literal
-
-struct FuncExp : Expression
-{
-    FuncLiteralDeclaration *fd;
-
-    FuncExp(Loc loc, FuncLiteralDeclaration *fd);
-    Expression *syntaxCopy();
-    Expression *semantic(Scope *sc);
-    void scanForNestedRef(Scope *sc);
-    char *toChars();
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-    elem *toElem(IRState *irs);
-
-    int inlineCost(InlineCostState *ics);
-    //Expression *doInline(InlineDoState *ids);
-    //Expression *inlineScan(InlineScanState *iss);
-
-    // LDC
-    virtual llvm::Constant *toConstElem(IRState *irs);
-};
-
-// Declaration of a symbol
-
-struct DeclarationExp : Expression
-{
-    Dsymbol *declaration;
-
-    DeclarationExp(Loc loc, Dsymbol *declaration);
-    Expression *syntaxCopy();
-    Expression *semantic(Scope *sc);
-    Expression *interpret(InterState *istate);
-    int checkSideEffect(int flag);
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-    elem *toElem(IRState *irs);
-    void scanForNestedRef(Scope *sc);
-    int canThrow();
-
-    int inlineCost(InlineCostState *ics);
-    Expression *doInline(InlineDoState *ids);
-    Expression *inlineScan(InlineScanState *iss);
-};
-
-struct TypeidExp : Expression
-{
-    Type *typeidType;
-
-    TypeidExp(Loc loc, Type *typeidType);
-    Expression *syntaxCopy();
-    Expression *semantic(Scope *sc);
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-};
-
-#if DMDV2
-struct TraitsExp : Expression
-{
-    Identifier *ident;
-    Objects *args;
-
-    TraitsExp(Loc loc, Identifier *ident, Objects *args);
-    Expression *syntaxCopy();
-    Expression *semantic(Scope *sc);
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-};
-#endif
-
-struct HaltExp : Expression
-{
-    HaltExp(Loc loc);
-    Expression *semantic(Scope *sc);
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-    int checkSideEffect(int flag);
-
-    elem *toElem(IRState *irs);
-};
-
-struct IsExp : Expression
-{
-    /* is(targ id tok tspec)
-     * is(targ id == tok2)
-     */
-    Type *targ;
-    Identifier *id;	// can be NULL
-    enum TOK tok;	// ':' or '=='
-    Type *tspec;	// can be NULL
-    enum TOK tok2;	// 'struct', 'union', 'typedef', etc.
-    TemplateParameters *parameters;
-
-    IsExp(Loc loc, Type *targ, Identifier *id, enum TOK tok, Type *tspec,
-	enum TOK tok2, TemplateParameters *parameters);
-    Expression *syntaxCopy();
-    Expression *semantic(Scope *sc);
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-};
-
-/****************************************************************/
-
-struct UnaExp : Expression
-{
-    Expression *e1;
-
-    UnaExp(Loc loc, enum TOK op, int size, Expression *e1);
-    Expression *syntaxCopy();
-    Expression *semantic(Scope *sc);
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-    Expression *optimize(int result);
-    void dump(int indent);
-    void scanForNestedRef(Scope *sc);
-    Expression *interpretCommon(InterState *istate, Expression *(*fp)(Type *, Expression *));
-    int canThrow();
-
-    int inlineCost(InlineCostState *ics);
-    Expression *doInline(InlineDoState *ids);
-    Expression *inlineScan(InlineScanState *iss);
-
-    Expression *op_overload(Scope *sc);	// doesn't need to be virtual
-};
-
-struct BinExp : Expression
-{
-    Expression *e1;
-    Expression *e2;
-
-    BinExp(Loc loc, enum TOK op, int size, Expression *e1, Expression *e2);
-    Expression *syntaxCopy();
-    Expression *semantic(Scope *sc);
-    Expression *semanticp(Scope *sc);
-    Expression *commonSemanticAssign(Scope *sc);
-    Expression *commonSemanticAssignIntegral(Scope *sc);
-    int checkSideEffect(int flag);
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-    Expression *scaleFactor(Scope *sc);
-    Expression *typeCombine(Scope *sc);
-    Expression *optimize(int result);
-    int isunsigned();
-    void incompatibleTypes();
-    void dump(int indent);
-    void scanForNestedRef(Scope *sc);
-    Expression *interpretCommon(InterState *istate, Expression *(*fp)(Type *, Expression *, Expression *));
-    Expression *interpretCommon2(InterState *istate, Expression *(*fp)(TOK, Type *, Expression *, Expression *));
-    Expression *interpretAssignCommon(InterState *istate, Expression *(*fp)(Type *, Expression *, Expression *), int post = 0);
-    int canThrow();
-    Expression *arrayOp(Scope *sc);
-
-    int inlineCost(InlineCostState *ics);
-    Expression *doInline(InlineDoState *ids);
-    Expression *inlineScan(InlineScanState *iss);
-
-    Expression *op_overload(Scope *sc);
-
-    elem *toElemBin(IRState *irs, int op);
-};
-
-struct BinAssignExp : BinExp
-{
-    BinAssignExp(Loc loc, enum TOK op, int size, Expression *e1, Expression *e2);
-    int checkSideEffect(int flag);
-};
-
-/****************************************************************/
-
-struct CompileExp : UnaExp
-{
-    CompileExp(Loc loc, Expression *e);
-    Expression *semantic(Scope *sc);
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-};
-
-struct FileExp : UnaExp
-{
-    FileExp(Loc loc, Expression *e);
-    Expression *semantic(Scope *sc);
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-};
-
-struct AssertExp : UnaExp
-{
-    Expression *msg;
-
-    AssertExp(Loc loc, Expression *e, Expression *msg = NULL);
-    Expression *syntaxCopy();
-    Expression *semantic(Scope *sc);
-    Expression *interpret(InterState *istate);
-    int checkSideEffect(int flag);
-    int canThrow();
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-
-    int inlineCost(InlineCostState *ics);
-    Expression *doInline(InlineDoState *ids);
-    Expression *inlineScan(InlineScanState *iss);
-
-    elem *toElem(IRState *irs);
-};
-
-struct DotIdExp : UnaExp
-{
-    Identifier *ident;
-
-    DotIdExp(Loc loc, Expression *e, Identifier *ident);
-    Expression *semantic(Scope *sc);
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-    void dump(int i);
-};
-
-struct DotTemplateExp : UnaExp
-{
-    TemplateDeclaration *td;
-    
-    DotTemplateExp(Loc loc, Expression *e, TemplateDeclaration *td);
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-};
-
-struct DotVarExp : UnaExp
-{
-    Declaration *var;
-    int hasOverloads;
-
-    DotVarExp(Loc loc, Expression *e, Declaration *var, int hasOverloads = 0);
-    Expression *semantic(Scope *sc);
-    int isLvalue();
-    Expression *toLvalue(Scope *sc, Expression *e);
-    Expression *modifiableLvalue(Scope *sc, Expression *e);
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-    void dump(int indent);
-    elem *toElem(IRState *irs);
-
-    //LDC: since we don't convert abc.def -> *(&abc + ABC.def.offsetof)
-    // these are needed
-    Expression *optimize(int result);
-    Expression *interpret(InterState *istate);
-};
-
-struct DotTemplateInstanceExp : UnaExp
-{
-    TemplateInstance *ti;
-
-    DotTemplateInstanceExp(Loc loc, Expression *e, TemplateInstance *ti);
-    Expression *syntaxCopy();
-    Expression *semantic(Scope *sc);
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-    void dump(int indent);
-};
-
-struct DelegateExp : UnaExp
-{
-    FuncDeclaration *func;
-    int hasOverloads;
-
-    DelegateExp(Loc loc, Expression *e, FuncDeclaration *func, int hasOverloads = 0);
-    Expression *semantic(Scope *sc);
-    MATCH implicitConvTo(Type *t);
-    Expression *castTo(Scope *sc, Type *t);
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-    void dump(int indent);
-
-    int inlineCost(InlineCostState *ics);
-    elem *toElem(IRState *irs);
-};
-
-struct DotTypeExp : UnaExp
-{
-    Dsymbol *sym;		// symbol that represents a type
-
-    DotTypeExp(Loc loc, Expression *e, Dsymbol *sym);
-    Expression *semantic(Scope *sc);
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-    elem *toElem(IRState *irs);
-};
-
-struct CallExp : UnaExp
-{
-    Expressions *arguments;	// function arguments
-
-    CallExp(Loc loc, Expression *e, Expressions *exps);
-    CallExp(Loc loc, Expression *e);
-    CallExp(Loc loc, Expression *e, Expression *earg1);
-    CallExp(Loc loc, Expression *e, Expression *earg1, Expression *earg2);
-
-    Expression *syntaxCopy();
-    Expression *semantic(Scope *sc);
-    Expression *optimize(int result);
-    Expression *interpret(InterState *istate);
-    int checkSideEffect(int flag);
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-    void dump(int indent);
-    elem *toElem(IRState *irs);
-    void scanForNestedRef(Scope *sc);
-    int isLvalue();
-    Expression *toLvalue(Scope *sc, Expression *e);
-    int canThrow();
-
-    int inlineCost(InlineCostState *ics);
-    Expression *doInline(InlineDoState *ids);
-    Expression *inlineScan(InlineScanState *iss);
-};
-
-struct AddrExp : UnaExp
-{
-    AddrExp(Loc loc, Expression *e);
-    Expression *semantic(Scope *sc);
-    elem *toElem(IRState *irs);
-    MATCH implicitConvTo(Type *t);
-    Expression *castTo(Scope *sc, Type *t);
-    Expression *optimize(int result);
-    // LDC
-    virtual llvm::Constant *toConstElem(IRState *irs);
-};
-
-struct PtrExp : UnaExp
-{
-    PtrExp(Loc loc, Expression *e);
-    PtrExp(Loc loc, Expression *e, Type *t);
-    Expression *semantic(Scope *sc);
-    int isLvalue();
-    Expression *toLvalue(Scope *sc, Expression *e);
-    Expression *modifiableLvalue(Scope *sc, Expression *e);
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-    elem *toElem(IRState *irs);
-    Expression *optimize(int result);
-    Expression *interpret(InterState *istate);
-
-    // For operator overloading
-    Identifier *opId();
-};
-
-struct NegExp : UnaExp
-{
-    NegExp(Loc loc, Expression *e);
-    Expression *semantic(Scope *sc);
-    Expression *optimize(int result);
-    Expression *interpret(InterState *istate);
-    void buildArrayIdent(OutBuffer *buf, Expressions *arguments);
-    Expression *buildArrayLoop(Arguments *fparams);
-
-    // For operator overloading
-    Identifier *opId();
-
-    elem *toElem(IRState *irs);
-};
-
-struct UAddExp : UnaExp
-{
-    UAddExp(Loc loc, Expression *e);
-    Expression *semantic(Scope *sc);
-
-    // For operator overloading
-    Identifier *opId();
-};
-
-struct ComExp : UnaExp
-{
-    ComExp(Loc loc, Expression *e);
-    Expression *semantic(Scope *sc);
-    Expression *optimize(int result);
-    Expression *interpret(InterState *istate);
-    void buildArrayIdent(OutBuffer *buf, Expressions *arguments);
-    Expression *buildArrayLoop(Arguments *fparams);
-
-    // For operator overloading
-    Identifier *opId();
-
-    elem *toElem(IRState *irs);
-};
-
-struct NotExp : UnaExp
-{
-    NotExp(Loc loc, Expression *e);
-    Expression *semantic(Scope *sc);
-    Expression *optimize(int result);
-    Expression *interpret(InterState *istate);
-    int isBit();
-    elem *toElem(IRState *irs);
-};
-
-struct BoolExp : UnaExp
-{
-    BoolExp(Loc loc, Expression *e, Type *type);
-    Expression *semantic(Scope *sc);
-    Expression *optimize(int result);
-    Expression *interpret(InterState *istate);
-    int isBit();
-    elem *toElem(IRState *irs);
-};
-
-struct DeleteExp : UnaExp
-{
-    DeleteExp(Loc loc, Expression *e);
-    Expression *semantic(Scope *sc);
-    Expression *checkToBoolean();
-    int checkSideEffect(int flag);
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-    elem *toElem(IRState *irs);
-};
-
-struct CastExp : UnaExp
-{
-    // Possible to cast to one type while painting to another type
-    Type *to;			// type to cast to
-    enum TOK tok;		// TOKconst or TOKinvariant
-
-    CastExp(Loc loc, Expression *e, Type *t);
-    CastExp(Loc loc, Expression *e, enum TOK tok);
-    Expression *syntaxCopy();
-    Expression *semantic(Scope *sc);
-    Expression *optimize(int result);
-    Expression *interpret(InterState *istate);
-    int checkSideEffect(int flag);
-    void checkEscape();
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-    elem *toElem(IRState *irs);
-
-    // For operator overloading
-    Identifier *opId();
-
-    // LDC
-    virtual llvm::Constant *toConstElem(IRState *irs);
-};
-
-
-struct SliceExp : UnaExp
-{
-    Expression *upr;		// NULL if implicit 0
-    Expression *lwr;		// NULL if implicit [length - 1]
-    VarDeclaration *lengthVar;
-
-    SliceExp(Loc loc, Expression *e1, Expression *lwr, Expression *upr);
-    Expression *syntaxCopy();
-    Expression *semantic(Scope *sc);
-    void checkEscape();
-    int isLvalue();
-    Expression *toLvalue(Scope *sc, Expression *e);
-    Expression *modifiableLvalue(Scope *sc, Expression *e);
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-    Expression *optimize(int result);
-    Expression *interpret(InterState *istate);
-    void dump(int indent);
-    elem *toElem(IRState *irs);
-    void scanForNestedRef(Scope *sc);
-    void buildArrayIdent(OutBuffer *buf, Expressions *arguments);
-    Expression *buildArrayLoop(Arguments *fparams);
-
-    int inlineCost(InlineCostState *ics);
-    Expression *doInline(InlineDoState *ids);
-    Expression *inlineScan(InlineScanState *iss);
-
-    // LDC
-    virtual llvm::Constant *toConstElem(IRState *irs);
-};
-
-struct ArrayLengthExp : UnaExp
-{
-    ArrayLengthExp(Loc loc, Expression *e1);
-    Expression *semantic(Scope *sc);
-    Expression *optimize(int result);
-    Expression *interpret(InterState *istate);
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-    elem *toElem(IRState *irs);
-};
-
-// e1[a0,a1,a2,a3,...]
-
-struct ArrayExp : UnaExp
-{
-    Expressions *arguments;		// Array of Expression's
-
-    ArrayExp(Loc loc, Expression *e1, Expressions *arguments);
-    Expression *syntaxCopy();
-    Expression *semantic(Scope *sc);
-    int isLvalue();
-    Expression *toLvalue(Scope *sc, Expression *e);
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-    void scanForNestedRef(Scope *sc);
-
-    // For operator overloading
-    Identifier *opId();
-
-    int inlineCost(InlineCostState *ics);
-    Expression *doInline(InlineDoState *ids);
-    Expression *inlineScan(InlineScanState *iss);
-};
-
-/****************************************************************/
-
-struct DotExp : BinExp
-{
-    DotExp(Loc loc, Expression *e1, Expression *e2);
-    Expression *semantic(Scope *sc);
-};
-
-struct CommaExp : BinExp
-{
-    CommaExp(Loc loc, Expression *e1, Expression *e2);
-    Expression *semantic(Scope *sc);
-    void checkEscape();
-    int isLvalue();
-    Expression *toLvalue(Scope *sc, Expression *e);
-    Expression *modifiableLvalue(Scope *sc, Expression *e);
-    int isBool(int result);
-    int checkSideEffect(int flag);
-    Expression *optimize(int result);
-    Expression *interpret(InterState *istate);
-    elem *toElem(IRState *irs);
-};
-
-struct IndexExp : BinExp
-{
-    VarDeclaration *lengthVar;
-    int modifiable;
-
-    IndexExp(Loc loc, Expression *e1, Expression *e2);
-    Expression *semantic(Scope *sc);
-    int isLvalue();
-    Expression *toLvalue(Scope *sc, Expression *e);
-    Expression *modifiableLvalue(Scope *sc, Expression *e);
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-    Expression *optimize(int result);
-    Expression *interpret(InterState *istate);
-    Expression *doInline(InlineDoState *ids);
-    void scanForNestedRef(Scope *sc);
-
-    elem *toElem(IRState *irs);
-
-    // LDC
-    virtual llvm::Constant *toConstElem(IRState *irs);
-};
-
-/* For both i++ and i--
- */
-struct PostExp : BinExp
-{
-    PostExp(enum TOK op, Loc loc, Expression *e);
-    Expression *semantic(Scope *sc);
-    Expression *interpret(InterState *istate);
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-    Identifier *opId();    // For operator overloading
-    elem *toElem(IRState *irs);
-};
-
-struct AssignExp : BinExp
-{   int ismemset;	// !=0 if setting the contents of an array
-
-    AssignExp(Loc loc, Expression *e1, Expression *e2);
-    Expression *semantic(Scope *sc);
-    Expression *checkToBoolean();
-    Expression *interpret(InterState *istate);
-    Identifier *opId();    // For operator overloading
-    void buildArrayIdent(OutBuffer *buf, Expressions *arguments);
-    Expression *buildArrayLoop(Arguments *fparams);
-    elem *toElem(IRState *irs);
-};
-
-#define ASSIGNEXP(op)	\
-struct op##AssignExp : BinExp					\
-{								\
-    op##AssignExp(Loc loc, Expression *e1, Expression *e2);	\
-    Expression *semantic(Scope *sc);				\
-    Expression *interpret(InterState *istate);			\
-    X(void buildArrayIdent(OutBuffer *buf, Expressions *arguments);) \
-    X(Expression *buildArrayLoop(Arguments *fparams);)		\
-								\
-    Identifier *opId();    /* For operator overloading */	\
-								\
-    elem *toElem(IRState *irs);					\
-};
-
-#define X(a) a
-ASSIGNEXP(Add)
-ASSIGNEXP(Min)
-ASSIGNEXP(Mul)
-ASSIGNEXP(Div)
-ASSIGNEXP(Mod)
-ASSIGNEXP(And)
-ASSIGNEXP(Or)
-ASSIGNEXP(Xor)
-#undef X
-
-#define X(a)
-
-ASSIGNEXP(Shl)
-ASSIGNEXP(Shr)
-ASSIGNEXP(Ushr)
-ASSIGNEXP(Cat)
-
-#undef X
-#undef ASSIGNEXP
-
-struct AddExp : BinExp
-{
-    AddExp(Loc loc, Expression *e1, Expression *e2);
-    Expression *semantic(Scope *sc);
-    Expression *optimize(int result);
-    Expression *interpret(InterState *istate);
-    void buildArrayIdent(OutBuffer *buf, Expressions *arguments);
-    Expression *buildArrayLoop(Arguments *fparams);
-
-    // For operator overloading
-    int isCommutative();
-    Identifier *opId();
-    Identifier *opId_r();
-
-    elem *toElem(IRState *irs);
-};
-
-struct MinExp : BinExp
-{
-    MinExp(Loc loc, Expression *e1, Expression *e2);
-    Expression *semantic(Scope *sc);
-    Expression *optimize(int result);
-    Expression *interpret(InterState *istate);
-    void buildArrayIdent(OutBuffer *buf, Expressions *arguments);
-    Expression *buildArrayLoop(Arguments *fparams);
-
-    // For operator overloading
-    Identifier *opId();
-    Identifier *opId_r();
-
-    elem *toElem(IRState *irs);
-};
-
-struct CatExp : BinExp
-{
-    CatExp(Loc loc, Expression *e1, Expression *e2);
-    Expression *semantic(Scope *sc);
-    Expression *optimize(int result);
-    Expression *interpret(InterState *istate);
-
-    // For operator overloading
-    Identifier *opId();
-    Identifier *opId_r();
-
-    elem *toElem(IRState *irs);
-};
-
-struct MulExp : BinExp
-{
-    MulExp(Loc loc, Expression *e1, Expression *e2);
-    Expression *semantic(Scope *sc);
-    Expression *optimize(int result);
-    Expression *interpret(InterState *istate);
-    void buildArrayIdent(OutBuffer *buf, Expressions *arguments);
-    Expression *buildArrayLoop(Arguments *fparams);
-
-    // For operator overloading
-    int isCommutative();
-    Identifier *opId();
-    Identifier *opId_r();
-
-    elem *toElem(IRState *irs);
-};
-
-struct DivExp : BinExp
-{
-    DivExp(Loc loc, Expression *e1, Expression *e2);
-    Expression *semantic(Scope *sc);
-    Expression *optimize(int result);
-    Expression *interpret(InterState *istate);
-    void buildArrayIdent(OutBuffer *buf, Expressions *arguments);
-    Expression *buildArrayLoop(Arguments *fparams);
-
-    // For operator overloading
-    Identifier *opId();
-    Identifier *opId_r();
-
-    elem *toElem(IRState *irs);
-};
-
-struct ModExp : BinExp
-{
-    ModExp(Loc loc, Expression *e1, Expression *e2);
-    Expression *semantic(Scope *sc);
-    Expression *optimize(int result);
-    Expression *interpret(InterState *istate);
-    void buildArrayIdent(OutBuffer *buf, Expressions *arguments);
-    Expression *buildArrayLoop(Arguments *fparams);
-
-    // For operator overloading
-    Identifier *opId();
-    Identifier *opId_r();
-
-    elem *toElem(IRState *irs);
-};
-
-struct ShlExp : BinExp
-{
-    ShlExp(Loc loc, Expression *e1, Expression *e2);
-    Expression *semantic(Scope *sc);
-    Expression *optimize(int result);
-    Expression *interpret(InterState *istate);
-
-    // For operator overloading
-    Identifier *opId();
-    Identifier *opId_r();
-
-    elem *toElem(IRState *irs);
-};
-
-struct ShrExp : BinExp
-{
-    ShrExp(Loc loc, Expression *e1, Expression *e2);
-    Expression *semantic(Scope *sc);
-    Expression *optimize(int result);
-    Expression *interpret(InterState *istate);
-
-    // For operator overloading
-    Identifier *opId();
-    Identifier *opId_r();
-
-    elem *toElem(IRState *irs);
-};
-
-struct UshrExp : BinExp
-{
-    UshrExp(Loc loc, Expression *e1, Expression *e2);
-    Expression *semantic(Scope *sc);
-    Expression *optimize(int result);
-    Expression *interpret(InterState *istate);
-
-    // For operator overloading
-    Identifier *opId();
-    Identifier *opId_r();
-
-    elem *toElem(IRState *irs);
-};
-
-struct AndExp : BinExp
-{
-    AndExp(Loc loc, Expression *e1, Expression *e2);
-    Expression *semantic(Scope *sc);
-    Expression *optimize(int result);
-    Expression *interpret(InterState *istate);
-    void buildArrayIdent(OutBuffer *buf, Expressions *arguments);
-    Expression *buildArrayLoop(Arguments *fparams);
-
-    // For operator overloading
-    int isCommutative();
-    Identifier *opId();
-    Identifier *opId_r();
-
-    elem *toElem(IRState *irs);
-};
-
-struct OrExp : BinExp
-{
-    OrExp(Loc loc, Expression *e1, Expression *e2);
-    Expression *semantic(Scope *sc);
-    Expression *optimize(int result);
-    Expression *interpret(InterState *istate);
-    void buildArrayIdent(OutBuffer *buf, Expressions *arguments);
-    Expression *buildArrayLoop(Arguments *fparams);
-
-    // For operator overloading
-    int isCommutative();
-    Identifier *opId();
-    Identifier *opId_r();
-
-    elem *toElem(IRState *irs);
-};
-
-struct XorExp : BinExp
-{
-    XorExp(Loc loc, Expression *e1, Expression *e2);
-    Expression *semantic(Scope *sc);
-    Expression *optimize(int result);
-    Expression *interpret(InterState *istate);
-    void buildArrayIdent(OutBuffer *buf, Expressions *arguments);
-    Expression *buildArrayLoop(Arguments *fparams);
-
-    // For operator overloading
-    int isCommutative();
-    Identifier *opId();
-    Identifier *opId_r();
-
-    elem *toElem(IRState *irs);
-};
-
-struct OrOrExp : BinExp
-{
-    OrOrExp(Loc loc, Expression *e1, Expression *e2);
-    Expression *semantic(Scope *sc);
-    Expression *checkToBoolean();
-    int isBit();
-    Expression *optimize(int result);
-    Expression *interpret(InterState *istate);
-    int checkSideEffect(int flag);
-    elem *toElem(IRState *irs);
-};
-
-struct AndAndExp : BinExp
-{
-    AndAndExp(Loc loc, Expression *e1, Expression *e2);
-    Expression *semantic(Scope *sc);
-    Expression *checkToBoolean();
-    int isBit();
-    Expression *optimize(int result);
-    Expression *interpret(InterState *istate);
-    int checkSideEffect(int flag);
-    elem *toElem(IRState *irs);
-};
-
-struct CmpExp : BinExp
-{
-    CmpExp(enum TOK op, Loc loc, Expression *e1, Expression *e2);
-    Expression *semantic(Scope *sc);
-    Expression *optimize(int result);
-    Expression *interpret(InterState *istate);
-    int isBit();
-
-    // For operator overloading
-    int isCommutative();
-    Identifier *opId();
-
-    elem *toElem(IRState *irs);
-};
-
-struct InExp : BinExp
-{
-    InExp(Loc loc, Expression *e1, Expression *e2);
-    Expression *semantic(Scope *sc);
-    int isBit();
-
-    // For operator overloading
-    Identifier *opId();
-    Identifier *opId_r();
-
-    elem *toElem(IRState *irs);
-};
-
-struct RemoveExp : BinExp
-{
-    RemoveExp(Loc loc, Expression *e1, Expression *e2);
-    elem *toElem(IRState *irs);
-};
-
-// == and !=
-
-struct EqualExp : BinExp
-{
-    EqualExp(enum TOK op, Loc loc, Expression *e1, Expression *e2);
-    Expression *semantic(Scope *sc);
-    Expression *optimize(int result);
-    Expression *interpret(InterState *istate);
-    int isBit();
-
-    // For operator overloading
-    int isCommutative();
-    Identifier *opId();
-
-    elem *toElem(IRState *irs);
-};
-
-// === and !===
-
-struct IdentityExp : BinExp
-{
-    IdentityExp(enum TOK op, Loc loc, Expression *e1, Expression *e2);
-    Expression *semantic(Scope *sc);
-    int isBit();
-    Expression *optimize(int result);
-    Expression *interpret(InterState *istate);
-    elem *toElem(IRState *irs);
-};
-
-/****************************************************************/
-
-struct CondExp : BinExp
-{
-    Expression *econd;
-
-    CondExp(Loc loc, Expression *econd, Expression *e1, Expression *e2);
-    Expression *syntaxCopy();
-    Expression *semantic(Scope *sc);
-    Expression *optimize(int result);
-    Expression *interpret(InterState *istate);
-    void checkEscape();
-    int isLvalue();
-    Expression *toLvalue(Scope *sc, Expression *e);
-    Expression *modifiableLvalue(Scope *sc, Expression *e);
-    Expression *checkToBoolean();
-    int checkSideEffect(int flag);
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-    MATCH implicitConvTo(Type *t);
-    Expression *castTo(Scope *sc, Type *t);
-    void scanForNestedRef(Scope *sc);
-    int canThrow();
-
-    int inlineCost(InlineCostState *ics);
-    Expression *doInline(InlineDoState *ids);
-    Expression *inlineScan(InlineScanState *iss);
-
-    elem *toElem(IRState *irs);
-};
-
-#if DMDV2
-/****************************************************************/
-
-struct DefaultInitExp : Expression
-{
-    enum TOK subop;		// which of the derived classes this is
-
-    DefaultInitExp(Loc loc, enum TOK subop, int size);
-    virtual Expression *resolve(Loc loc, Scope *sc) = 0;
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-};
-
-struct FileInitExp : DefaultInitExp
-{
-    FileInitExp(Loc loc);
-    Expression *semantic(Scope *sc);
-    Expression *resolve(Loc loc, Scope *sc);
-};
-
-struct LineInitExp : DefaultInitExp
-{
-    LineInitExp(Loc loc);
-    Expression *semantic(Scope *sc);
-    Expression *resolve(Loc loc, Scope *sc);
-};
-#endif
-
-/****************************************************************/
-
-#if IN_LLVM
-
-// this stuff is strictly LDC
-
-struct GEPExp : UnaExp
-{
-    unsigned index;
-    Identifier* ident;
-
-    GEPExp(Loc loc, Expression* e, Identifier* id, unsigned idx);
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-    Expression *toLvalue(Scope *sc, Expression *e);
-
-    elem *toElem(IRState *irs);
-    llvm::Constant *toConstElem(IRState *irs);
-};
-
-#endif
-
-/****************************************************************/
-
-/* Special values used by the interpreter
- */
-#define EXP_CANT_INTERPRET	((Expression *)1)
-#define EXP_CONTINUE_INTERPRET	((Expression *)2)
-#define EXP_BREAK_INTERPRET	((Expression *)3)
-#define EXP_GOTO_INTERPRET	((Expression *)4)
-#define EXP_VOID_INTERPRET	((Expression *)5)
-
-Expression *expType(Type *type, Expression *e);
-
-Expression *Neg(Type *type, Expression *e1);
-Expression *Com(Type *type, Expression *e1);
-Expression *Not(Type *type, Expression *e1);
-Expression *Bool(Type *type, Expression *e1);
-Expression *Cast(Type *type, Type *to, Expression *e1);
-Expression *ArrayLength(Type *type, Expression *e1);
-Expression *Ptr(Type *type, Expression *e1);
-
-Expression *Add(Type *type, Expression *e1, Expression *e2);
-Expression *Min(Type *type, Expression *e1, Expression *e2);
-Expression *Mul(Type *type, Expression *e1, Expression *e2);
-Expression *Div(Type *type, Expression *e1, Expression *e2);
-Expression *Mod(Type *type, Expression *e1, Expression *e2);
-Expression *Shl(Type *type, Expression *e1, Expression *e2);
-Expression *Shr(Type *type, Expression *e1, Expression *e2);
-Expression *Ushr(Type *type, Expression *e1, Expression *e2);
-Expression *And(Type *type, Expression *e1, Expression *e2);
-Expression *Or(Type *type, Expression *e1, Expression *e2);
-Expression *Xor(Type *type, Expression *e1, Expression *e2);
-Expression *Index(Type *type, Expression *e1, Expression *e2);
-Expression *Cat(Type *type, Expression *e1, Expression *e2);
-
-Expression *Equal(enum TOK op, Type *type, Expression *e1, Expression *e2);
-Expression *Cmp(enum TOK op, Type *type, Expression *e1, Expression *e2);
-Expression *Identity(enum TOK op, Type *type, Expression *e1, Expression *e2);
-
-Expression *Slice(Type *type, Expression *e1, Expression *lwr, Expression *upr);
-
-#endif /* DMD_EXPRESSION_H */
+
+// Compiler implementation of the D programming language
+// Copyright (c) 1999-2008 by Digital Mars
+// All Rights Reserved
+// written by Walter Bright
+// http://www.digitalmars.com
+// License for redistribution is by either the Artistic License
+// in artistic.txt, or the GNU General Public License in gnu.txt.
+// See the included readme.txt for details.
+
+#ifndef DMD_EXPRESSION_H
+#define DMD_EXPRESSION_H
+
+#include "mars.h"
+#include "identifier.h"
+#include "lexer.h"
+#include "arraytypes.h"
+
+struct Type;
+struct Scope;
+struct TupleDeclaration;
+struct VarDeclaration;
+struct FuncDeclaration;
+struct FuncLiteralDeclaration;
+struct Declaration;
+struct CtorDeclaration;
+struct NewDeclaration;
+struct Dsymbol;
+struct Import;
+struct Module;
+struct ScopeDsymbol;
+struct InlineCostState;
+struct InlineDoState;
+struct InlineScanState;
+struct Expression;
+struct Declaration;
+struct AggregateDeclaration;
+struct StructDeclaration;
+struct TemplateInstance;
+struct TemplateDeclaration;
+struct ClassDeclaration;
+struct HdrGenState;
+struct BinExp;
+struct InterState;
+#if IN_DMD
+struct Symbol;		// back end symbol
+#endif
+struct OverloadSet;
+
+enum TOK;
+
+#if IN_DMD
+// Back end
+struct IRState;
+struct dt_t;
+#endif
+
+#ifdef IN_GCC
+union tree_node; typedef union tree_node elem;
+#endif
+#if IN_DMD
+struct elem;
+#endif
+
+#if IN_LLVM
+struct IRState;
+struct DValue;
+namespace llvm {
+    class Constant;
+    class ConstantInt;
+}
+#endif
+
+void initPrecedence();
+
+Expression *resolveProperties(Scope *sc, Expression *e);
+void accessCheck(Loc loc, Scope *sc, Expression *e, Declaration *d);
+Expression *build_overload(Loc loc, Scope *sc, Expression *ethis, Expression *earg, Identifier *id);
+Dsymbol *search_function(ScopeDsymbol *ad, Identifier *funcid);
+void inferApplyArgTypes(enum TOK op, Arguments *arguments, Expression *aggr, Module *from);
+void argExpTypesToCBuffer(OutBuffer *buf, Expressions *arguments, HdrGenState *hgs);
+void argsToCBuffer(OutBuffer *buf, Expressions *arguments, HdrGenState *hgs);
+void expandTuples(Expressions *exps);
+FuncDeclaration *hasThis(Scope *sc);
+Expression *fromConstInitializer(int result, Expression *e);
+int arrayExpressionCanThrow(Expressions *exps);
+
+struct Expression : Object
+{
+    Loc loc;			// file location
+    enum TOK op;		// handy to minimize use of dynamic_cast
+    Type *type;			// !=NULL means that semantic() has been run
+    int size;			// # of bytes in Expression so we can copy() it
+
+    Expression(Loc loc, enum TOK op, int size);
+    Expression *copy();
+    virtual Expression *syntaxCopy();
+    virtual Expression *semantic(Scope *sc);
+    Expression *trySemantic(Scope *sc);
+
+    int dyncast() { return DYNCAST_EXPRESSION; }	// kludge for template.isExpression()
+
+    void print();
+    char *toChars();
+    virtual void dump(int indent);
+    void error(const char *format, ...) IS_PRINTF(2);
+    void warning(const char *format, ...) IS_PRINTF(2);
+    virtual void rvalue();
+
+    static Expression *combine(Expression *e1, Expression *e2);
+    static Expressions *arraySyntaxCopy(Expressions *exps);
+
+    virtual dinteger_t toInteger();
+    virtual uinteger_t toUInteger();
+    virtual real_t toReal();
+    virtual real_t toImaginary();
+    virtual complex_t toComplex();
+    virtual void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+    virtual void toMangleBuffer(OutBuffer *buf);
+    virtual int isLvalue();
+    virtual Expression *toLvalue(Scope *sc, Expression *e);
+    virtual Expression *modifiableLvalue(Scope *sc, Expression *e);
+    virtual Expression *implicitCastTo(Scope *sc, Type *t);
+    virtual MATCH implicitConvTo(Type *t);
+    virtual Expression *castTo(Scope *sc, Type *t);
+    virtual void checkEscape();
+    void checkScalar();
+    void checkNoBool();
+    Expression *checkIntegral();
+    Expression *checkArithmetic();
+    void checkDeprecated(Scope *sc, Dsymbol *s);
+    void checkPurity(Scope *sc, FuncDeclaration *f);
+    virtual Expression *checkToBoolean();
+    Expression *checkToPointer();
+    Expression *addressOf(Scope *sc);
+    Expression *deref();
+    Expression *integralPromotions(Scope *sc);
+
+    Expression *toDelegate(Scope *sc, Type *t);
+    virtual void scanForNestedRef(Scope *sc);
+
+    virtual Expression *optimize(int result);
+    #define WANTflags	1
+    #define WANTvalue	2
+    #define WANTinterpret 4
+
+    virtual Expression *interpret(InterState *istate);
+
+    virtual int isConst();
+    virtual int isBool(int result);
+    virtual int isBit();
+    virtual int checkSideEffect(int flag);
+    virtual int canThrow();
+
+    virtual int inlineCost(InlineCostState *ics);
+    virtual Expression *doInline(InlineDoState *ids);
+    virtual Expression *inlineScan(InlineScanState *iss);
+
+    // For operator overloading
+    virtual int isCommutative();
+    virtual Identifier *opId();
+    virtual Identifier *opId_r();
+
+    // For array ops
+    virtual void buildArrayIdent(OutBuffer *buf, Expressions *arguments);
+    virtual Expression *buildArrayLoop(Arguments *fparams);
+
+#if IN_DMD
+    // Back end
+    virtual elem *toElem(IRState *irs);
+    virtual dt_t **toDt(dt_t **pdt);
+#endif
+
+#if IN_LLVM
+    virtual DValue* toElem(IRState* irs);
+    virtual llvm::Constant *toConstElem(IRState *irs);
+    virtual void cacheLvalue(IRState* irs);
+
+    llvm::Value* cachedLvalue;
+#endif
+};
+
+struct IntegerExp : Expression
+{
+    dinteger_t value;
+
+    IntegerExp(Loc loc, dinteger_t value, Type *type);
+    IntegerExp(dinteger_t value);
+    int equals(Object *o);
+    Expression *semantic(Scope *sc);
+    Expression *interpret(InterState *istate);
+    char *toChars();
+    void dump(int indent);
+    dinteger_t toInteger();
+    real_t toReal();
+    real_t toImaginary();
+    complex_t toComplex();
+    int isConst();
+    int isBool(int result);
+    MATCH implicitConvTo(Type *t);
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+    void toMangleBuffer(OutBuffer *buf);
+    Expression *toLvalue(Scope *sc, Expression *e);
+#if IN_DMD
+    elem *toElem(IRState *irs);
+    dt_t **toDt(dt_t **pdt);
+#elif IN_LLVM
+    DValue* toElem(IRState* irs);
+    llvm::Constant *toConstElem(IRState *irs);
+#endif
+};
+
+struct ErrorExp : IntegerExp
+{
+    ErrorExp();
+
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+};
+
+struct RealExp : Expression
+{
+    real_t value;
+
+    RealExp(Loc loc, real_t value, Type *type);
+    int equals(Object *o);
+    Expression *semantic(Scope *sc);
+    Expression *interpret(InterState *istate);
+    char *toChars();
+    dinteger_t toInteger();
+    uinteger_t toUInteger();
+    real_t toReal();
+    real_t toImaginary();
+    complex_t toComplex();
+    Expression *castTo(Scope *sc, Type *t);
+    int isConst();
+    int isBool(int result);
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+    void toMangleBuffer(OutBuffer *buf);
+#if IN_DMD
+    elem *toElem(IRState *irs);
+    dt_t **toDt(dt_t **pdt);
+#elif IN_LLVM
+    DValue* toElem(IRState* irs);
+    llvm::Constant *toConstElem(IRState *irs);
+#endif
+};
+
+struct ComplexExp : Expression
+{
+    complex_t value;
+
+    ComplexExp(Loc loc, complex_t value, Type *type);
+    int equals(Object *o);
+    Expression *semantic(Scope *sc);
+    Expression *interpret(InterState *istate);
+    char *toChars();
+    dinteger_t toInteger();
+    uinteger_t toUInteger();
+    real_t toReal();
+    real_t toImaginary();
+    complex_t toComplex();
+    Expression *castTo(Scope *sc, Type *t);
+    int isConst();
+    int isBool(int result);
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+    void toMangleBuffer(OutBuffer *buf);
+#ifdef _DH
+    OutBuffer hexp;
+#endif
+#if IN_DMD
+    elem *toElem(IRState *irs);
+    dt_t **toDt(dt_t **pdt);
+#elif IN_LLVM
+    DValue* toElem(IRState* irs);
+    llvm::Constant *toConstElem(IRState *irs);
+#endif
+};
+
+struct IdentifierExp : Expression
+{
+    Identifier *ident;
+    Declaration *var;
+
+    IdentifierExp(Loc loc, Identifier *ident);
+    IdentifierExp(Loc loc, Declaration *var);
+    Expression *semantic(Scope *sc);
+    char *toChars();
+    void dump(int indent);
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+    int isLvalue();
+    Expression *toLvalue(Scope *sc, Expression *e);
+};
+
+struct DollarExp : IdentifierExp
+{
+    DollarExp(Loc loc);
+};
+
+struct DsymbolExp : Expression
+{
+    Dsymbol *s;
+    int hasOverloads;
+
+    DsymbolExp(Loc loc, Dsymbol *s, int hasOverloads = 0);
+    Expression *semantic(Scope *sc);
+    char *toChars();
+    void dump(int indent);
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+    int isLvalue();
+    Expression *toLvalue(Scope *sc, Expression *e);
+};
+
+struct ThisExp : Expression
+{
+    Declaration *var;
+
+    ThisExp(Loc loc);
+    Expression *semantic(Scope *sc);
+    int isBool(int result);
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+    int isLvalue();
+    Expression *toLvalue(Scope *sc, Expression *e);
+    void scanForNestedRef(Scope *sc);
+
+    int inlineCost(InlineCostState *ics);
+    Expression *doInline(InlineDoState *ids);
+    //Expression *inlineScan(InlineScanState *iss);
+
+#if IN_DMD
+    elem *toElem(IRState *irs);
+#endif
+
+#if IN_LLVM
+    DValue* toElem(IRState* irs);
+#endif
+};
+
+struct SuperExp : ThisExp
+{
+    SuperExp(Loc loc);
+    Expression *semantic(Scope *sc);
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+    void scanForNestedRef(Scope *sc);
+
+    int inlineCost(InlineCostState *ics);
+    Expression *doInline(InlineDoState *ids);
+    //Expression *inlineScan(InlineScanState *iss);
+};
+
+struct NullExp : Expression
+{
+    unsigned char committed;	// !=0 if type is committed
+
+    NullExp(Loc loc);
+    Expression *semantic(Scope *sc);
+    int isBool(int result);
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+    void toMangleBuffer(OutBuffer *buf);
+    MATCH implicitConvTo(Type *t);
+    Expression *castTo(Scope *sc, Type *t);
+    Expression *interpret(InterState *istate);
+#if IN_DMD
+    elem *toElem(IRState *irs);
+    dt_t **toDt(dt_t **pdt);
+#elif IN_LLVM
+    DValue* toElem(IRState* irs);
+    llvm::Constant *toConstElem(IRState *irs);
+#endif
+};
+
+struct StringExp : Expression
+{
+    void *string;	// char, wchar, or dchar data
+    size_t len;		// number of chars, wchars, or dchars
+    unsigned char sz;	// 1: char, 2: wchar, 4: dchar
+    unsigned char committed;	// !=0 if type is committed
+    unsigned char postfix;	// 'c', 'w', 'd'
+
+    StringExp(Loc loc, char *s);
+    StringExp(Loc loc, void *s, size_t len);
+    StringExp(Loc loc, void *s, size_t len, unsigned char postfix);
+    //Expression *syntaxCopy();
+    int equals(Object *o);
+    char *toChars();
+    Expression *semantic(Scope *sc);
+    Expression *interpret(InterState *istate);
+    size_t length();
+    StringExp *toUTF8(Scope *sc);
+    Expression *implicitCastTo(Scope *sc, Type *t);
+    MATCH implicitConvTo(Type *t);
+    Expression *castTo(Scope *sc, Type *t);
+    int compare(Object *obj);
+    int isBool(int result);
+    unsigned charAt(size_t i);
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+    void toMangleBuffer(OutBuffer *buf);
+#if IN_DMD
+    elem *toElem(IRState *irs);
+    dt_t **toDt(dt_t **pdt);
+#elif IN_LLVM
+    DValue* toElem(IRState* irs);
+    llvm::Constant *toConstElem(IRState *irs);
+#endif
+};
+
+// Tuple
+
+struct TupleExp : Expression
+{
+    Expressions *exps;
+
+    TupleExp(Loc loc, Expressions *exps);
+    TupleExp(Loc loc, TupleDeclaration *tup);
+    Expression *syntaxCopy();
+    int equals(Object *o);
+    Expression *semantic(Scope *sc);
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+    void scanForNestedRef(Scope *sc);
+    void checkEscape();
+    int checkSideEffect(int flag);
+    Expression *optimize(int result);
+    Expression *interpret(InterState *istate);
+    Expression *castTo(Scope *sc, Type *t);
+#if IN_DMD
+    elem *toElem(IRState *irs);
+#endif
+    int canThrow();
+
+    int inlineCost(InlineCostState *ics);
+    Expression *doInline(InlineDoState *ids);
+    Expression *inlineScan(InlineScanState *iss);
+
+#if IN_LLVM
+    DValue* toElem(IRState* irs);
+#endif
+};
+
+struct ArrayLiteralExp : Expression
+{
+    Expressions *elements;
+
+    ArrayLiteralExp(Loc loc, Expressions *elements);
+    ArrayLiteralExp(Loc loc, Expression *e);
+
+    Expression *syntaxCopy();
+    Expression *semantic(Scope *sc);
+    int isBool(int result);
+    int checkSideEffect(int flag);
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+    void toMangleBuffer(OutBuffer *buf);
+    void scanForNestedRef(Scope *sc);
+    Expression *optimize(int result);
+    Expression *interpret(InterState *istate);
+    MATCH implicitConvTo(Type *t);
+    Expression *castTo(Scope *sc, Type *t);
+    int canThrow();
+
+    int inlineCost(InlineCostState *ics);
+    Expression *doInline(InlineDoState *ids);
+    Expression *inlineScan(InlineScanState *iss);
+
+#if IN_DMD
+    elem *toElem(IRState *irs);
+    dt_t **toDt(dt_t **pdt);
+#elif IN_LLVM
+    DValue* toElem(IRState* irs);
+    llvm::Constant *toConstElem(IRState *irs);
+#endif
+};
+
+struct AssocArrayLiteralExp : Expression
+{
+    Expressions *keys;
+    Expressions *values;
+
+    AssocArrayLiteralExp(Loc loc, Expressions *keys, Expressions *values);
+
+    Expression *syntaxCopy();
+    Expression *semantic(Scope *sc);
+    int isBool(int result);
+#if IN_DMD
+    elem *toElem(IRState *irs);
+#endif
+    int checkSideEffect(int flag);
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+    void toMangleBuffer(OutBuffer *buf);
+    void scanForNestedRef(Scope *sc);
+    Expression *optimize(int result);
+    Expression *interpret(InterState *istate);
+    MATCH implicitConvTo(Type *t);
+    Expression *castTo(Scope *sc, Type *t);
+    int canThrow();
+
+    int inlineCost(InlineCostState *ics);
+    Expression *doInline(InlineDoState *ids);
+    Expression *inlineScan(InlineScanState *iss);
+
+#if IN_LLVM
+    DValue* toElem(IRState* irs);
+    llvm::Constant *toConstElem(IRState *irs);
+#endif
+};
+
+struct StructLiteralExp : Expression
+{
+    StructDeclaration *sd;		// which aggregate this is for
+    Expressions *elements;	// parallels sd->fields[] with
+				// NULL entries for fields to skip
+
+#if IN_DMD
+    Symbol *sym;		// back end symbol to initialize with literal
+#endif
+    size_t soffset;		// offset from start of s
+    int fillHoles;		// fill alignment 'holes' with zero
+
+    StructLiteralExp(Loc loc, StructDeclaration *sd, Expressions *elements);
+
+    Expression *syntaxCopy();
+    Expression *semantic(Scope *sc);
+    Expression *getField(Type *type, unsigned offset);
+    int getFieldIndex(Type *type, unsigned offset);
+    int checkSideEffect(int flag);
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+    void toMangleBuffer(OutBuffer *buf);
+    void scanForNestedRef(Scope *sc);
+    Expression *optimize(int result);
+    Expression *interpret(InterState *istate);
+    int isLvalue();
+    // LDC: struct literals aren't lvalues! Taking their address can lead to 
+    //      incorrect behavior, see LDC#218, DMD#2682
+    // Expression *toLvalue(Scope *sc, Expression *e);
+    int canThrow();
+    MATCH implicitConvTo(Type *t);
+
+    int inlineCost(InlineCostState *ics);
+    Expression *doInline(InlineDoState *ids);
+    Expression *inlineScan(InlineScanState *iss);
+
+#if IN_DMD
+    elem *toElem(IRState *irs);
+    dt_t **toDt(dt_t **pdt);
+#elif IN_LLVM
+    DValue* toElem(IRState* irs);
+    llvm::Constant *toConstElem(IRState *irs);
+#endif
+};
+
+Expression *typeDotIdExp(Loc loc, Type *type, Identifier *ident);
+#if IN_DMD
+#endif
+
+#if IN_LLVM
+    DValue* toElem(IRState* irs);
+#endif
+
+struct TypeExp : Expression
+{
+    TypeExp(Loc loc, Type *type);
+    Expression *syntaxCopy();
+    Expression *semantic(Scope *sc);
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+    Expression *optimize(int result);
+#if IN_DMD
+    elem *toElem(IRState *irs);
+#endif
+
+#if IN_LLVM
+    DValue* toElem(IRState* irs);
+#endif
+};
+
+struct ScopeExp : Expression
+{
+    ScopeDsymbol *sds;
+
+    ScopeExp(Loc loc, ScopeDsymbol *sds);
+    Expression *syntaxCopy();
+    Expression *semantic(Scope *sc);
+#if IN_DMD
+    elem *toElem(IRState *irs);
+#endif
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+
+#if IN_LLVM
+    DValue* toElem(IRState* irs);
+#endif
+};
+
+struct TemplateExp : Expression
+{
+    TemplateDeclaration *td;
+
+    TemplateExp(Loc loc, TemplateDeclaration *td);
+    void rvalue();
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+};
+
+struct NewExp : Expression
+{
+    /* thisexp.new(newargs) newtype(arguments)
+     */
+    Expression *thisexp;	// if !NULL, 'this' for class being allocated
+    Expressions *newargs;	// Array of Expression's to call new operator
+    Type *newtype;
+    Expressions *arguments;	// Array of Expression's
+
+    CtorDeclaration *member;	// constructor function
+    NewDeclaration *allocator;	// allocator function
+    int onstack;		// allocate on stack
+
+    NewExp(Loc loc, Expression *thisexp, Expressions *newargs,
+	Type *newtype, Expressions *arguments);
+    Expression *syntaxCopy();
+    Expression *semantic(Scope *sc);
+#if IN_DMD
+    elem *toElem(IRState *irs);
+#endif
+    int checkSideEffect(int flag);
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+    void scanForNestedRef(Scope *sc);
+    int canThrow();
+
+    //int inlineCost(InlineCostState *ics);
+    Expression *doInline(InlineDoState *ids);
+    //Expression *inlineScan(InlineScanState *iss);
+
+#if IN_LLVM
+    DValue* toElem(IRState* irs);
+#endif
+};
+
+struct NewAnonClassExp : Expression
+{
+    /* thisexp.new(newargs) class baseclasses { } (arguments)
+     */
+    Expression *thisexp;	// if !NULL, 'this' for class being allocated
+    Expressions *newargs;	// Array of Expression's to call new operator
+    ClassDeclaration *cd;	// class being instantiated
+    Expressions *arguments;	// Array of Expression's to call class constructor
+
+    NewAnonClassExp(Loc loc, Expression *thisexp, Expressions *newargs,
+	ClassDeclaration *cd, Expressions *arguments);
+    Expression *syntaxCopy();
+    Expression *semantic(Scope *sc);
+    int checkSideEffect(int flag);
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+    int canThrow();
+};
+
+struct SymbolExp : Expression
+{
+    Declaration *var;
+    int hasOverloads;
+
+    SymbolExp(Loc loc, enum TOK op, int size, Declaration *var, int hasOverloads);
+
+#if IN_DMD
+    elem *toElem(IRState *irs);
+#endif
+
+#if IN_LLVM
+    DValue* toElem(IRState* irs);
+#endif
+};
+
+// Offset from symbol
+
+struct SymOffExp : SymbolExp
+{
+    unsigned offset;
+    Module* m;	// starting point for overload resolution
+
+    SymOffExp(Loc loc, Declaration *var, unsigned offset, int hasOverloads = 0);
+    Expression *semantic(Scope *sc);
+    void checkEscape();
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+    int isConst();
+    int isBool(int result);
+    Expression *doInline(InlineDoState *ids);
+    MATCH implicitConvTo(Type *t);
+    Expression *castTo(Scope *sc, Type *t);
+    void scanForNestedRef(Scope *sc);
+
+#if IN_DMD
+    dt_t **toDt(dt_t **pdt);
+#endif
+
+#if IN_LLVM
+    DValue* toElem(IRState* irs);
+#endif
+};
+
+// Variable
+
+struct VarExp : SymbolExp
+{
+    VarExp(Loc loc, Declaration *var, int hasOverloads = 0);
+    int equals(Object *o);
+    Expression *semantic(Scope *sc);
+    Expression *optimize(int result);
+    Expression *interpret(InterState *istate);
+    void dump(int indent);
+    char *toChars();
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+    void checkEscape();
+    int isLvalue();
+    Expression *toLvalue(Scope *sc, Expression *e);
+    Expression *modifiableLvalue(Scope *sc, Expression *e);
+#if IN_DMD
+    dt_t **toDt(dt_t **pdt);
+#endif
+    void scanForNestedRef(Scope *sc);
+
+    int inlineCost(InlineCostState *ics);
+    Expression *doInline(InlineDoState *ids);
+    //Expression *inlineScan(InlineScanState *iss);
+
+#if IN_LLVM
+    DValue* toElem(IRState* irs);
+    llvm::Constant *toConstElem(IRState *irs);
+    void cacheLvalue(IRState* irs);
+#endif
+};
+
+#if DMDV2
+// Overload Set
+
+struct OverExp : Expression
+{
+    OverloadSet *vars;
+
+    OverExp(OverloadSet *s);
+    int isLvalue();
+    Expression *toLvalue(Scope *sc, Expression *e);
+};
+#endif
+
+// Function/Delegate literal
+
+struct FuncExp : Expression
+{
+    FuncLiteralDeclaration *fd;
+
+    FuncExp(Loc loc, FuncLiteralDeclaration *fd);
+    Expression *syntaxCopy();
+    Expression *semantic(Scope *sc);
+    void scanForNestedRef(Scope *sc);
+    char *toChars();
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+#if IN_DMD
+    elem *toElem(IRState *irs);
+#endif
+
+    int inlineCost(InlineCostState *ics);
+    //Expression *doInline(InlineDoState *ids);
+    //Expression *inlineScan(InlineScanState *iss);
+
+#if IN_LLVM
+    DValue* toElem(IRState* irs);
+    llvm::Constant *toConstElem(IRState *irs);
+#endif
+};
+
+// Declaration of a symbol
+
+struct DeclarationExp : Expression
+{
+    Dsymbol *declaration;
+
+    DeclarationExp(Loc loc, Dsymbol *declaration);
+    Expression *syntaxCopy();
+    Expression *semantic(Scope *sc);
+    Expression *interpret(InterState *istate);
+    int checkSideEffect(int flag);
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+#if IN_DMD
+    elem *toElem(IRState *irs);
+#endif
+    void scanForNestedRef(Scope *sc);
+    int canThrow();
+
+    int inlineCost(InlineCostState *ics);
+    Expression *doInline(InlineDoState *ids);
+    Expression *inlineScan(InlineScanState *iss);
+
+#if IN_LLVM
+    DValue* toElem(IRState* irs);
+#endif
+};
+
+struct TypeidExp : Expression
+{
+    Type *typeidType;
+
+    TypeidExp(Loc loc, Type *typeidType);
+    Expression *syntaxCopy();
+    Expression *semantic(Scope *sc);
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+};
+
+#if DMDV2
+struct TraitsExp : Expression
+{
+    Identifier *ident;
+    Objects *args;
+
+    TraitsExp(Loc loc, Identifier *ident, Objects *args);
+    Expression *syntaxCopy();
+    Expression *semantic(Scope *sc);
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+};
+#endif
+
+struct HaltExp : Expression
+{
+    HaltExp(Loc loc);
+    Expression *semantic(Scope *sc);
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+    int checkSideEffect(int flag);
+
+#if IN_DMD
+    elem *toElem(IRState *irs);
+#endif
+
+#if IN_LLVM
+    DValue* toElem(IRState* irs);
+#endif
+};
+
+struct IsExp : Expression
+{
+    /* is(targ id tok tspec)
+     * is(targ id == tok2)
+     */
+    Type *targ;
+    Identifier *id;	// can be NULL
+    enum TOK tok;	// ':' or '=='
+    Type *tspec;	// can be NULL
+    enum TOK tok2;	// 'struct', 'union', 'typedef', etc.
+    TemplateParameters *parameters;
+
+    IsExp(Loc loc, Type *targ, Identifier *id, enum TOK tok, Type *tspec,
+	enum TOK tok2, TemplateParameters *parameters);
+    Expression *syntaxCopy();
+    Expression *semantic(Scope *sc);
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+};
+
+/****************************************************************/
+
+struct UnaExp : Expression
+{
+    Expression *e1;
+
+    UnaExp(Loc loc, enum TOK op, int size, Expression *e1);
+    Expression *syntaxCopy();
+    Expression *semantic(Scope *sc);
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+    Expression *optimize(int result);
+    void dump(int indent);
+    void scanForNestedRef(Scope *sc);
+    Expression *interpretCommon(InterState *istate, Expression *(*fp)(Type *, Expression *));
+    int canThrow();
+
+    int inlineCost(InlineCostState *ics);
+    Expression *doInline(InlineDoState *ids);
+    Expression *inlineScan(InlineScanState *iss);
+
+    Expression *op_overload(Scope *sc);	// doesn't need to be virtual
+};
+
+struct BinExp : Expression
+{
+    Expression *e1;
+    Expression *e2;
+
+    BinExp(Loc loc, enum TOK op, int size, Expression *e1, Expression *e2);
+    Expression *syntaxCopy();
+    Expression *semantic(Scope *sc);
+    Expression *semanticp(Scope *sc);
+    Expression *commonSemanticAssign(Scope *sc);
+    Expression *commonSemanticAssignIntegral(Scope *sc);
+    int checkSideEffect(int flag);
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+    Expression *scaleFactor(Scope *sc);
+    Expression *typeCombine(Scope *sc);
+    Expression *optimize(int result);
+    int isunsigned();
+    void incompatibleTypes();
+    void dump(int indent);
+    void scanForNestedRef(Scope *sc);
+    Expression *interpretCommon(InterState *istate, Expression *(*fp)(Type *, Expression *, Expression *));
+    Expression *interpretCommon2(InterState *istate, Expression *(*fp)(TOK, Type *, Expression *, Expression *));
+    Expression *interpretAssignCommon(InterState *istate, Expression *(*fp)(Type *, Expression *, Expression *), int post = 0);
+    int canThrow();
+    Expression *arrayOp(Scope *sc);
+
+    int inlineCost(InlineCostState *ics);
+    Expression *doInline(InlineDoState *ids);
+    Expression *inlineScan(InlineScanState *iss);
+
+    Expression *op_overload(Scope *sc);
+
+#if IN_DMD
+    elem *toElemBin(IRState *irs, int op);
+#endif
+};
+
+struct BinAssignExp : BinExp
+{
+    BinAssignExp(Loc loc, enum TOK op, int size, Expression *e1, Expression *e2);
+    int checkSideEffect(int flag);
+};
+
+/****************************************************************/
+
+struct CompileExp : UnaExp
+{
+    CompileExp(Loc loc, Expression *e);
+    Expression *semantic(Scope *sc);
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+};
+
+struct FileExp : UnaExp
+{
+    FileExp(Loc loc, Expression *e);
+    Expression *semantic(Scope *sc);
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+};
+
+struct AssertExp : UnaExp
+{
+    Expression *msg;
+
+    AssertExp(Loc loc, Expression *e, Expression *msg = NULL);
+    Expression *syntaxCopy();
+    Expression *semantic(Scope *sc);
+    Expression *interpret(InterState *istate);
+    int checkSideEffect(int flag);
+    int canThrow();
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+
+    int inlineCost(InlineCostState *ics);
+    Expression *doInline(InlineDoState *ids);
+    Expression *inlineScan(InlineScanState *iss);
+
+#if IN_DMD
+    elem *toElem(IRState *irs);
+#endif
+
+#if IN_LLVM
+    DValue* toElem(IRState* irs);
+#endif
+};
+
+struct DotIdExp : UnaExp
+{
+    Identifier *ident;
+
+    DotIdExp(Loc loc, Expression *e, Identifier *ident);
+    Expression *semantic(Scope *sc);
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+    void dump(int i);
+};
+
+struct DotTemplateExp : UnaExp
+{
+    TemplateDeclaration *td;
+    
+    DotTemplateExp(Loc loc, Expression *e, TemplateDeclaration *td);
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+};
+
+struct DotVarExp : UnaExp
+{
+    Declaration *var;
+    int hasOverloads;
+
+    DotVarExp(Loc loc, Expression *e, Declaration *var, int hasOverloads = 0);
+    Expression *semantic(Scope *sc);
+    int isLvalue();
+    Expression *toLvalue(Scope *sc, Expression *e);
+    Expression *modifiableLvalue(Scope *sc, Expression *e);
+    Expression *optimize(int result);
+    Expression *interpret(InterState *istate);
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+    void dump(int indent);
+#if IN_DMD
+    elem *toElem(IRState *irs);
+#endif
+
+#if IN_LLVM
+    DValue* toElem(IRState* irs);
+    void cacheLvalue(IRState* irs);
+#endif
+};
+
+struct DotTemplateInstanceExp : UnaExp
+{
+    TemplateInstance *ti;
+
+    DotTemplateInstanceExp(Loc loc, Expression *e, TemplateInstance *ti);
+    Expression *syntaxCopy();
+    Expression *semantic(Scope *sc);
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+    void dump(int indent);
+};
+
+struct DelegateExp : UnaExp
+{
+    FuncDeclaration *func;
+    Module* m;	// starting point for overload resolution
+    int hasOverloads;
+
+    DelegateExp(Loc loc, Expression *e, FuncDeclaration *func, int hasOverloads = 0);
+    Expression *semantic(Scope *sc);
+    MATCH implicitConvTo(Type *t);
+    Expression *castTo(Scope *sc, Type *t);
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+    void dump(int indent);
+
+    int inlineCost(InlineCostState *ics);
+#if IN_DMD
+    elem *toElem(IRState *irs);
+#endif
+
+#if IN_LLVM
+    DValue* toElem(IRState* irs);
+#endif
+};
+
+struct DotTypeExp : UnaExp
+{
+    Dsymbol *sym;		// symbol that represents a type
+
+    DotTypeExp(Loc loc, Expression *e, Dsymbol *sym);
+    Expression *semantic(Scope *sc);
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+#if IN_DMD
+    elem *toElem(IRState *irs);
+#endif
+
+#if IN_LLVM
+    DValue* toElem(IRState* irs);
+#endif
+};
+
+struct CallExp : UnaExp
+{
+    Expressions *arguments;	// function arguments
+
+    CallExp(Loc loc, Expression *e, Expressions *exps);
+    CallExp(Loc loc, Expression *e);
+    CallExp(Loc loc, Expression *e, Expression *earg1);
+    CallExp(Loc loc, Expression *e, Expression *earg1, Expression *earg2);
+
+    Expression *syntaxCopy();
+    Expression *semantic(Scope *sc);
+    Expression *optimize(int result);
+    Expression *interpret(InterState *istate);
+    int checkSideEffect(int flag);
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+    void dump(int indent);
+#if IN_DMD
+    elem *toElem(IRState *irs);
+#endif
+    void scanForNestedRef(Scope *sc);
+    int isLvalue();
+    Expression *toLvalue(Scope *sc, Expression *e);
+    int canThrow();
+
+    int inlineCost(InlineCostState *ics);
+    Expression *doInline(InlineDoState *ids);
+    Expression *inlineScan(InlineScanState *iss);
+
+#if IN_LLVM
+    DValue* toElem(IRState* irs);
+#endif
+};
+
+struct AddrExp : UnaExp
+{
+    Module* m;	// starting point for overload resolution
+
+    AddrExp(Loc loc, Expression *e);
+    Expression *semantic(Scope *sc);
+#if IN_DMD
+    elem *toElem(IRState *irs);
+#endif
+    MATCH implicitConvTo(Type *t);
+    Expression *castTo(Scope *sc, Type *t);
+    Expression *optimize(int result);
+
+#if IN_LLVM
+    DValue* toElem(IRState* irs);
+    llvm::Constant *toConstElem(IRState *irs);
+#endif
+};
+
+struct PtrExp : UnaExp
+{
+    PtrExp(Loc loc, Expression *e);
+    PtrExp(Loc loc, Expression *e, Type *t);
+    Expression *semantic(Scope *sc);
+    int isLvalue();
+    Expression *toLvalue(Scope *sc, Expression *e);
+    Expression *modifiableLvalue(Scope *sc, Expression *e);
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+#if IN_DMD
+    elem *toElem(IRState *irs);
+#endif
+    Expression *optimize(int result);
+    Expression *interpret(InterState *istate);
+
+    // For operator overloading
+    Identifier *opId();
+
+#if IN_LLVM
+    DValue* toElem(IRState* irs);
+    void cacheLvalue(IRState* irs);
+#endif
+};
+
+struct NegExp : UnaExp
+{
+    NegExp(Loc loc, Expression *e);
+    Expression *semantic(Scope *sc);
+    Expression *optimize(int result);
+    Expression *interpret(InterState *istate);
+    void buildArrayIdent(OutBuffer *buf, Expressions *arguments);
+    Expression *buildArrayLoop(Arguments *fparams);
+
+    // For operator overloading
+    Identifier *opId();
+
+#if IN_DMD
+    elem *toElem(IRState *irs);
+#endif
+
+#if IN_LLVM
+    DValue* toElem(IRState* irs);
+#endif
+};
+
+struct UAddExp : UnaExp
+{
+    UAddExp(Loc loc, Expression *e);
+    Expression *semantic(Scope *sc);
+
+    // For operator overloading
+    Identifier *opId();
+};
+
+struct ComExp : UnaExp
+{
+    ComExp(Loc loc, Expression *e);
+    Expression *semantic(Scope *sc);
+    Expression *optimize(int result);
+    Expression *interpret(InterState *istate);
+    void buildArrayIdent(OutBuffer *buf, Expressions *arguments);
+    Expression *buildArrayLoop(Arguments *fparams);
+
+    // For operator overloading
+    Identifier *opId();
+
+#if IN_DMD
+    elem *toElem(IRState *irs);
+#endif
+
+#if IN_LLVM
+    DValue* toElem(IRState* irs);
+#endif
+};
+
+struct NotExp : UnaExp
+{
+    NotExp(Loc loc, Expression *e);
+    Expression *semantic(Scope *sc);
+    Expression *optimize(int result);
+    Expression *interpret(InterState *istate);
+    int isBit();
+#if IN_DMD
+    elem *toElem(IRState *irs);
+#endif
+
+#if IN_LLVM
+    DValue* toElem(IRState* irs);
+#endif
+};
+
+struct BoolExp : UnaExp
+{
+    BoolExp(Loc loc, Expression *e, Type *type);
+    Expression *semantic(Scope *sc);
+    Expression *optimize(int result);
+    Expression *interpret(InterState *istate);
+    int isBit();
+#if IN_DMD
+    elem *toElem(IRState *irs);
+#endif
+
+#if IN_LLVM
+    DValue* toElem(IRState* irs);
+#endif
+};
+
+struct DeleteExp : UnaExp
+{
+    DeleteExp(Loc loc, Expression *e);
+    Expression *semantic(Scope *sc);
+    Expression *checkToBoolean();
+    int checkSideEffect(int flag);
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+#if IN_DMD
+    elem *toElem(IRState *irs);
+#endif
+
+#if IN_LLVM
+    DValue* toElem(IRState* irs);
+#endif
+};
+
+struct CastExp : UnaExp
+{
+    // Possible to cast to one type while painting to another type
+    Type *to;			// type to cast to
+    unsigned mod;		// MODxxxxx
+
+    CastExp(Loc loc, Expression *e, Type *t);
+    CastExp(Loc loc, Expression *e, unsigned mod);
+    Expression *syntaxCopy();
+    Expression *semantic(Scope *sc);
+    Expression *optimize(int result);
+    Expression *interpret(InterState *istate);
+    int checkSideEffect(int flag);
+    void checkEscape();
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+#if IN_DMD
+    elem *toElem(IRState *irs);
+#endif
+
+    // For operator overloading
+    Identifier *opId();
+
+#if IN_LLVM
+    DValue* toElem(IRState* irs);
+    llvm::Constant *toConstElem(IRState *irs);
+#endif
+};
+
+
+struct SliceExp : UnaExp
+{
+    Expression *upr;		// NULL if implicit 0
+    Expression *lwr;		// NULL if implicit [length - 1]
+    VarDeclaration *lengthVar;
+
+    SliceExp(Loc loc, Expression *e1, Expression *lwr, Expression *upr);
+    Expression *syntaxCopy();
+    Expression *semantic(Scope *sc);
+    void checkEscape();
+    int isLvalue();
+    Expression *toLvalue(Scope *sc, Expression *e);
+    Expression *modifiableLvalue(Scope *sc, Expression *e);
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+    Expression *optimize(int result);
+    Expression *interpret(InterState *istate);
+    void dump(int indent);
+#if IN_DMD
+    elem *toElem(IRState *irs);
+#endif
+    void scanForNestedRef(Scope *sc);
+    void buildArrayIdent(OutBuffer *buf, Expressions *arguments);
+    Expression *buildArrayLoop(Arguments *fparams);
+
+    int inlineCost(InlineCostState *ics);
+    Expression *doInline(InlineDoState *ids);
+    Expression *inlineScan(InlineScanState *iss);
+
+#if IN_LLVM
+    DValue* toElem(IRState* irs);
+    llvm::Constant *toConstElem(IRState *irs);
+#endif
+};
+
+struct ArrayLengthExp : UnaExp
+{
+    ArrayLengthExp(Loc loc, Expression *e1);
+    Expression *semantic(Scope *sc);
+    Expression *optimize(int result);
+    Expression *interpret(InterState *istate);
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+#if IN_DMD
+    elem *toElem(IRState *irs);
+#endif
+
+#if IN_LLVM
+    DValue* toElem(IRState* irs);
+#endif
+};
+
+// e1[a0,a1,a2,a3,...]
+
+struct ArrayExp : UnaExp
+{
+    Expressions *arguments;		// Array of Expression's
+
+    ArrayExp(Loc loc, Expression *e1, Expressions *arguments);
+    Expression *syntaxCopy();
+    Expression *semantic(Scope *sc);
+    int isLvalue();
+    Expression *toLvalue(Scope *sc, Expression *e);
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+    void scanForNestedRef(Scope *sc);
+
+    // For operator overloading
+    Identifier *opId();
+
+    int inlineCost(InlineCostState *ics);
+    Expression *doInline(InlineDoState *ids);
+    Expression *inlineScan(InlineScanState *iss);
+};
+
+/****************************************************************/
+
+struct DotExp : BinExp
+{
+    DotExp(Loc loc, Expression *e1, Expression *e2);
+    Expression *semantic(Scope *sc);
+};
+
+struct CommaExp : BinExp
+{
+    CommaExp(Loc loc, Expression *e1, Expression *e2);
+    Expression *semantic(Scope *sc);
+    void checkEscape();
+    int isLvalue();
+    Expression *toLvalue(Scope *sc, Expression *e);
+    Expression *modifiableLvalue(Scope *sc, Expression *e);
+    int isBool(int result);
+    int checkSideEffect(int flag);
+    Expression *optimize(int result);
+    Expression *interpret(InterState *istate);
+#if IN_DMD
+    elem *toElem(IRState *irs);
+#endif
+
+#if IN_LLVM
+    DValue* toElem(IRState* irs);
+#endif
+};
+
+struct IndexExp : BinExp
+{
+    VarDeclaration *lengthVar;
+    int modifiable;
+
+    IndexExp(Loc loc, Expression *e1, Expression *e2);
+    Expression *semantic(Scope *sc);
+    int isLvalue();
+    Expression *toLvalue(Scope *sc, Expression *e);
+    Expression *modifiableLvalue(Scope *sc, Expression *e);
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+    Expression *optimize(int result);
+    Expression *interpret(InterState *istate);
+    Expression *doInline(InlineDoState *ids);
+    void scanForNestedRef(Scope *sc);
+
+#if IN_DMD
+    elem *toElem(IRState *irs);
+#elif IN_LLVM
+    DValue* toElem(IRState* irs);
+    llvm::Constant *toConstElem(IRState *irs);
+    void cacheLvalue(IRState* irs);
+#endif
+};
+
+/* For both i++ and i--
+ */
+struct PostExp : BinExp
+{
+    PostExp(enum TOK op, Loc loc, Expression *e);
+    Expression *semantic(Scope *sc);
+    Expression *interpret(InterState *istate);
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+    Identifier *opId();    // For operator overloading
+#if IN_DMD
+    elem *toElem(IRState *irs);
+#endif
+
+#if IN_LLVM
+    DValue* toElem(IRState* irs);
+#endif
+};
+
+struct AssignExp : BinExp
+{   int ismemset;	// !=0 if setting the contents of an array
+
+    AssignExp(Loc loc, Expression *e1, Expression *e2);
+    Expression *semantic(Scope *sc);
+    Expression *checkToBoolean();
+    Expression *interpret(InterState *istate);
+    Identifier *opId();    // For operator overloading
+    void buildArrayIdent(OutBuffer *buf, Expressions *arguments);
+    Expression *buildArrayLoop(Arguments *fparams);
+#if IN_DMD
+    elem *toElem(IRState *irs);
+#endif
+
+#if IN_LLVM
+    DValue* toElem(IRState* irs);
+#endif
+};
+
+#if IN_DMD
+#define ASSIGNEXP_TOELEM    elem *toElem(IRState *irs);
+#elif IN_LLVM
+#define ASSIGNEXP_TOELEM    DValue* toElem(IRState *irs);
+#else
+#define ASSIGNEXP_TOELEM
+#endif
+
+#define ASSIGNEXP(op)	\
+struct op##AssignExp : BinExp					\
+{								\
+    op##AssignExp(Loc loc, Expression *e1, Expression *e2);	\
+    Expression *semantic(Scope *sc);				\
+    Expression *interpret(InterState *istate);			\
+    X(void buildArrayIdent(OutBuffer *buf, Expressions *arguments);) \
+    X(Expression *buildArrayLoop(Arguments *fparams);)		\
+								\
+    Identifier *opId();    /* For operator overloading */	\
+								\
+    ASSIGNEXP_TOELEM					\
+};
+
+#define X(a) a
+ASSIGNEXP(Add)
+ASSIGNEXP(Min)
+ASSIGNEXP(Mul)
+ASSIGNEXP(Div)
+ASSIGNEXP(Mod)
+ASSIGNEXP(And)
+ASSIGNEXP(Or)
+ASSIGNEXP(Xor)
+#undef X
+
+#define X(a)
+
+ASSIGNEXP(Shl)
+ASSIGNEXP(Shr)
+ASSIGNEXP(Ushr)
+ASSIGNEXP(Cat)
+
+#undef X
+#undef ASSIGNEXP
+#undef ASSIGNEXP_TOELEM
+
+struct AddExp : BinExp
+{
+    AddExp(Loc loc, Expression *e1, Expression *e2);
+    Expression *semantic(Scope *sc);
+    Expression *optimize(int result);
+    Expression *interpret(InterState *istate);
+    void buildArrayIdent(OutBuffer *buf, Expressions *arguments);
+    Expression *buildArrayLoop(Arguments *fparams);
+
+    // For operator overloading
+    int isCommutative();
+    Identifier *opId();
+    Identifier *opId_r();
+
+#if IN_DMD
+    elem *toElem(IRState *irs);
+#endif
+
+#if IN_LLVM
+    DValue* toElem(IRState* irs);
+#endif
+};
+
+struct MinExp : BinExp
+{
+    MinExp(Loc loc, Expression *e1, Expression *e2);
+    Expression *semantic(Scope *sc);
+    Expression *optimize(int result);
+    Expression *interpret(InterState *istate);
+    void buildArrayIdent(OutBuffer *buf, Expressions *arguments);
+    Expression *buildArrayLoop(Arguments *fparams);
+
+    // For operator overloading
+    Identifier *opId();
+    Identifier *opId_r();
+
+#if IN_DMD
+    elem *toElem(IRState *irs);
+#endif
+
+#if IN_LLVM
+    DValue* toElem(IRState* irs);
+#endif
+};
+
+struct CatExp : BinExp
+{
+    CatExp(Loc loc, Expression *e1, Expression *e2);
+    Expression *semantic(Scope *sc);
+    Expression *optimize(int result);
+    Expression *interpret(InterState *istate);
+
+    // For operator overloading
+    Identifier *opId();
+    Identifier *opId_r();
+
+#if IN_DMD
+    elem *toElem(IRState *irs);
+#endif
+
+#if IN_LLVM
+    DValue* toElem(IRState* irs);
+#endif
+};
+
+struct MulExp : BinExp
+{
+    MulExp(Loc loc, Expression *e1, Expression *e2);
+    Expression *semantic(Scope *sc);
+    Expression *optimize(int result);
+    Expression *interpret(InterState *istate);
+    void buildArrayIdent(OutBuffer *buf, Expressions *arguments);
+    Expression *buildArrayLoop(Arguments *fparams);
+
+    // For operator overloading
+    int isCommutative();
+    Identifier *opId();
+    Identifier *opId_r();
+
+#if IN_DMD
+    elem *toElem(IRState *irs);
+#endif
+
+#if IN_LLVM
+    DValue* toElem(IRState* irs);
+#endif
+};
+
+struct DivExp : BinExp
+{
+    DivExp(Loc loc, Expression *e1, Expression *e2);
+    Expression *semantic(Scope *sc);
+    Expression *optimize(int result);
+    Expression *interpret(InterState *istate);
+    void buildArrayIdent(OutBuffer *buf, Expressions *arguments);
+    Expression *buildArrayLoop(Arguments *fparams);
+
+    // For operator overloading
+    Identifier *opId();
+    Identifier *opId_r();
+
+#if IN_DMD
+    elem *toElem(IRState *irs);
+#endif
+
+#if IN_LLVM
+    DValue* toElem(IRState* irs);
+#endif
+};
+
+struct ModExp : BinExp
+{
+    ModExp(Loc loc, Expression *e1, Expression *e2);
+    Expression *semantic(Scope *sc);
+    Expression *optimize(int result);
+    Expression *interpret(InterState *istate);
+    void buildArrayIdent(OutBuffer *buf, Expressions *arguments);
+    Expression *buildArrayLoop(Arguments *fparams);
+
+    // For operator overloading
+    Identifier *opId();
+    Identifier *opId_r();
+
+#if IN_DMD
+    elem *toElem(IRState *irs);
+#endif
+
+#if IN_LLVM
+    DValue* toElem(IRState* irs);
+#endif
+};
+
+struct ShlExp : BinExp
+{
+    ShlExp(Loc loc, Expression *e1, Expression *e2);
+    Expression *semantic(Scope *sc);
+    Expression *optimize(int result);
+    Expression *interpret(InterState *istate);
+
+    // For operator overloading
+    Identifier *opId();
+    Identifier *opId_r();
+
+#if IN_DMD
+    elem *toElem(IRState *irs);
+#endif
+
+#if IN_LLVM
+    DValue* toElem(IRState* irs);
+#endif
+};
+
+struct ShrExp : BinExp
+{
+    ShrExp(Loc loc, Expression *e1, Expression *e2);
+    Expression *semantic(Scope *sc);
+    Expression *optimize(int result);
+    Expression *interpret(InterState *istate);
+
+    // For operator overloading
+    Identifier *opId();
+    Identifier *opId_r();
+
+#if IN_DMD
+    elem *toElem(IRState *irs);
+#endif
+
+#if IN_LLVM
+    DValue* toElem(IRState* irs);
+#endif
+};
+
+struct UshrExp : BinExp
+{
+    UshrExp(Loc loc, Expression *e1, Expression *e2);
+    Expression *semantic(Scope *sc);
+    Expression *optimize(int result);
+    Expression *interpret(InterState *istate);
+
+    // For operator overloading
+    Identifier *opId();
+    Identifier *opId_r();
+
+#if IN_DMD
+    elem *toElem(IRState *irs);
+#endif
+
+#if IN_LLVM
+    DValue* toElem(IRState* irs);
+#endif
+};
+
+struct AndExp : BinExp
+{
+    AndExp(Loc loc, Expression *e1, Expression *e2);
+    Expression *semantic(Scope *sc);
+    Expression *optimize(int result);
+    Expression *interpret(InterState *istate);
+    void buildArrayIdent(OutBuffer *buf, Expressions *arguments);
+    Expression *buildArrayLoop(Arguments *fparams);
+
+    // For operator overloading
+    int isCommutative();
+    Identifier *opId();
+    Identifier *opId_r();
+
+#if IN_DMD
+    elem *toElem(IRState *irs);
+#endif
+
+#if IN_LLVM
+    DValue* toElem(IRState* irs);
+#endif
+};
+
+struct OrExp : BinExp
+{
+    OrExp(Loc loc, Expression *e1, Expression *e2);
+    Expression *semantic(Scope *sc);
+    Expression *optimize(int result);
+    Expression *interpret(InterState *istate);
+    void buildArrayIdent(OutBuffer *buf, Expressions *arguments);
+    Expression *buildArrayLoop(Arguments *fparams);
+
+    // For operator overloading
+    int isCommutative();
+    Identifier *opId();
+    Identifier *opId_r();
+
+#if IN_DMD
+    elem *toElem(IRState *irs);
+#endif
+
+#if IN_LLVM
+    DValue* toElem(IRState* irs);
+#endif
+};
+
+struct XorExp : BinExp
+{
+    XorExp(Loc loc, Expression *e1, Expression *e2);
+    Expression *semantic(Scope *sc);
+    Expression *optimize(int result);
+    Expression *interpret(InterState *istate);
+    void buildArrayIdent(OutBuffer *buf, Expressions *arguments);
+    Expression *buildArrayLoop(Arguments *fparams);
+
+    // For operator overloading
+    int isCommutative();
+    Identifier *opId();
+    Identifier *opId_r();
+
+#if IN_DMD
+    elem *toElem(IRState *irs);
+#endif
+
+#if IN_LLVM
+    DValue* toElem(IRState* irs);
+#endif
+};
+
+struct OrOrExp : BinExp
+{
+    OrOrExp(Loc loc, Expression *e1, Expression *e2);
+    Expression *semantic(Scope *sc);
+    Expression *checkToBoolean();
+    int isBit();
+    Expression *optimize(int result);
+    Expression *interpret(InterState *istate);
+    int checkSideEffect(int flag);
+#if IN_DMD
+    elem *toElem(IRState *irs);
+#endif
+
+#if IN_LLVM
+    DValue* toElem(IRState* irs);
+#endif
+};
+
+struct AndAndExp : BinExp
+{
+    AndAndExp(Loc loc, Expression *e1, Expression *e2);
+    Expression *semantic(Scope *sc);
+    Expression *checkToBoolean();
+    int isBit();
+    Expression *optimize(int result);
+    Expression *interpret(InterState *istate);
+    int checkSideEffect(int flag);
+#if IN_DMD
+    elem *toElem(IRState *irs);
+#endif
+
+#if IN_LLVM
+    DValue* toElem(IRState* irs);
+#endif
+};
+
+struct CmpExp : BinExp
+{
+    CmpExp(enum TOK op, Loc loc, Expression *e1, Expression *e2);
+    Expression *semantic(Scope *sc);
+    Expression *optimize(int result);
+    Expression *interpret(InterState *istate);
+    int isBit();
+
+    // For operator overloading
+    int isCommutative();
+    Identifier *opId();
+
+#if IN_DMD
+    elem *toElem(IRState *irs);
+#endif
+
+#if IN_LLVM
+    DValue* toElem(IRState* irs);
+#endif
+};
+
+struct InExp : BinExp
+{
+    InExp(Loc loc, Expression *e1, Expression *e2);
+    Expression *semantic(Scope *sc);
+    int isBit();
+
+    // For operator overloading
+    Identifier *opId();
+    Identifier *opId_r();
+
+#if IN_DMD
+    elem *toElem(IRState *irs);
+#endif
+
+#if IN_LLVM
+    DValue* toElem(IRState* irs);
+#endif
+};
+
+struct RemoveExp : BinExp
+{
+    RemoveExp(Loc loc, Expression *e1, Expression *e2);
+#if IN_DMD
+    elem *toElem(IRState *irs);
+#endif
+
+#if IN_LLVM
+    DValue* toElem(IRState* irs);
+#endif
+};
+
+// == and !=
+
+struct EqualExp : BinExp
+{
+    EqualExp(enum TOK op, Loc loc, Expression *e1, Expression *e2);
+    Expression *semantic(Scope *sc);
+    Expression *optimize(int result);
+    Expression *interpret(InterState *istate);
+    int isBit();
+
+    // For operator overloading
+    int isCommutative();
+    Identifier *opId();
+
+#if IN_DMD
+    elem *toElem(IRState *irs);
+#endif
+
+#if IN_LLVM
+    DValue* toElem(IRState* irs);
+#endif
+};
+
+// === and !===
+
+struct IdentityExp : BinExp
+{
+    IdentityExp(enum TOK op, Loc loc, Expression *e1, Expression *e2);
+    Expression *semantic(Scope *sc);
+    int isBit();
+    Expression *optimize(int result);
+    Expression *interpret(InterState *istate);
+#if IN_DMD
+    elem *toElem(IRState *irs);
+#endif
+
+#if IN_LLVM
+    DValue* toElem(IRState* irs);
+#endif
+};
+
+/****************************************************************/
+
+struct CondExp : BinExp
+{
+    Expression *econd;
+
+    CondExp(Loc loc, Expression *econd, Expression *e1, Expression *e2);
+    Expression *syntaxCopy();
+    Expression *semantic(Scope *sc);
+    Expression *optimize(int result);
+    Expression *interpret(InterState *istate);
+    void checkEscape();
+    int isLvalue();
+    Expression *toLvalue(Scope *sc, Expression *e);
+    Expression *modifiableLvalue(Scope *sc, Expression *e);
+    Expression *checkToBoolean();
+    int checkSideEffect(int flag);
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+    MATCH implicitConvTo(Type *t);
+    Expression *castTo(Scope *sc, Type *t);
+    void scanForNestedRef(Scope *sc);
+    int canThrow();
+
+    int inlineCost(InlineCostState *ics);
+    Expression *doInline(InlineDoState *ids);
+    Expression *inlineScan(InlineScanState *iss);
+
+#if IN_DMD
+    elem *toElem(IRState *irs);
+#endif
+
+#if IN_LLVM
+    DValue* toElem(IRState* irs);
+#endif
+};
+
+#if DMDV2
+/****************************************************************/
+
+struct DefaultInitExp : Expression
+{
+    enum TOK subop;		// which of the derived classes this is
+
+    DefaultInitExp(Loc loc, enum TOK subop, int size);
+    virtual Expression *resolve(Loc loc, Scope *sc) = 0;
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+};
+
+struct FileInitExp : DefaultInitExp
+{
+    FileInitExp(Loc loc);
+    Expression *semantic(Scope *sc);
+    Expression *resolve(Loc loc, Scope *sc);
+};
+
+struct LineInitExp : DefaultInitExp
+{
+    LineInitExp(Loc loc);
+    Expression *semantic(Scope *sc);
+    Expression *resolve(Loc loc, Scope *sc);
+};
+#endif
+
+/****************************************************************/
+
+#if IN_LLVM
+
+// this stuff is strictly LDC
+
+struct GEPExp : UnaExp
+{
+    unsigned index;
+    Identifier* ident;
+
+    GEPExp(Loc loc, Expression* e, Identifier* id, unsigned idx);
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+    Expression *toLvalue(Scope *sc, Expression *e);
+
+    DValue* toElem(IRState* irs);
+    llvm::Constant *toConstElem(IRState *irs);
+};
+
+#endif
+
+/****************************************************************/
+
+/* Special values used by the interpreter
+ */
+#define EXP_CANT_INTERPRET	((Expression *)1)
+#define EXP_CONTINUE_INTERPRET	((Expression *)2)
+#define EXP_BREAK_INTERPRET	((Expression *)3)
+#define EXP_GOTO_INTERPRET	((Expression *)4)
+#define EXP_VOID_INTERPRET	((Expression *)5)
+
+Expression *expType(Type *type, Expression *e);
+
+Expression *Neg(Type *type, Expression *e1);
+Expression *Com(Type *type, Expression *e1);
+Expression *Not(Type *type, Expression *e1);
+Expression *Bool(Type *type, Expression *e1);
+Expression *Cast(Type *type, Type *to, Expression *e1);
+Expression *ArrayLength(Type *type, Expression *e1);
+Expression *Ptr(Type *type, Expression *e1);
+
+Expression *Add(Type *type, Expression *e1, Expression *e2);
+Expression *Min(Type *type, Expression *e1, Expression *e2);
+Expression *Mul(Type *type, Expression *e1, Expression *e2);
+Expression *Div(Type *type, Expression *e1, Expression *e2);
+Expression *Mod(Type *type, Expression *e1, Expression *e2);
+Expression *Shl(Type *type, Expression *e1, Expression *e2);
+Expression *Shr(Type *type, Expression *e1, Expression *e2);
+Expression *Ushr(Type *type, Expression *e1, Expression *e2);
+Expression *And(Type *type, Expression *e1, Expression *e2);
+Expression *Or(Type *type, Expression *e1, Expression *e2);
+Expression *Xor(Type *type, Expression *e1, Expression *e2);
+Expression *Index(Type *type, Expression *e1, Expression *e2);
+Expression *Cat(Type *type, Expression *e1, Expression *e2);
+
+Expression *Equal(enum TOK op, Type *type, Expression *e1, Expression *e2);
+Expression *Cmp(enum TOK op, Type *type, Expression *e1, Expression *e2);
+Expression *Identity(enum TOK op, Type *type, Expression *e1, Expression *e2);
+
+Expression *Slice(Type *type, Expression *e1, Expression *lwr, Expression *upr);
+
+#endif /* DMD_EXPRESSION_H */
--- a/dmd2/func.c	Mon Jun 01 01:28:18 2009 +0200
+++ b/dmd2/func.c	Mon Jun 01 19:02:20 2009 +0100
@@ -1,3108 +1,3319 @@
-// 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;
-    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;
-    shidden = NULL;
-    builtin = BUILTINunknown;
-    tookAddressOf = 0;
-
-    // LDC
-    isArrayOp = false;
-    allowInlining = false;
-}
-
-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
-
-    storage_class |= sc->stc & ~STCref;
-    //printf("function storage_class = x%x\n", storage_class);
-
-    if (!originalType)
-	originalType = type;
-    if (!type->deco && type->nextOf())
-    {
-#if 1
-	/* Apply const and invariant storage class
-	 * to the function type
-	 */
-	type = type->semantic(loc, sc);
-	if (storage_class & STCinvariant)
-	{   // Don't use toInvariant(), as that will do a merge()
-	    type = type->makeInvariant();
-	    type->deco = type->merge()->deco;
-	}
-	else if (storage_class & STCconst)
-	{
-	    if (!type->isInvariant())
-	    {	// Don't use toConst(), as that will do a merge()
-		type = type->makeConst();
-		type->deco = type->merge()->deco;
-	    }
-	}
-#else
-	if (storage_class & (STCconst | STCinvariant))
-	{
-	    /* Apply const and invariant storage class
-	     * to the function's return type
-	     */
-	    Type *tn = type->nextOf();
-	    if (storage_class & STCconst)
-		tn = tn->makeConst();
-	    if (storage_class & STCinvariant)
-		tn = tn->makeInvariant();
-	    ((TypeNext *)type)->next = tn;
-	}
-
-	type = type->semantic(loc, sc);
-#endif
-    }
-    //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;
-    Dsymbol *parent = toParent();
-
-    if (storage_class & STCscope)
-	error("functions cannot be scope");
-
-    if (isAbstract() && !isVirtual())
-	error("non-virtual functions cannot be abstract");
-
-    if ((f->isConst() || f->isInvariant()) && !isThis())
-	error("without 'this' cannot be const/invariant");
-
-    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)
-    {
-	if (isCtorDeclaration())
-	{
-	    return;
-	}
-#if 0
-	// Verify no constructors, destructors, etc.
-	if (isCtorDeclaration()
-	    //||isDtorDeclaration()
-	    //|| isInvariantDeclaration()
-	    //|| isUnitTestDeclaration()
-	   )
-	{
-	    error("special member functions not allowed for %ss", sd->kind());
-	}
-
-	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() ||
-	    isPostBlitDeclaration() ||
-	    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);
-			if (f && f->isFinal() && f->prot() != PROTprivate)
-			    error("cannot override final function %s", f->toPrettyChars());
-		    }
-		}
-
-		if (isFinal())
-		{
-		    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() && global.params.warnings)
-		    warning("%s: overrides base class function %s, but is not marked with 'override'", locToChars(), 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++)
-	{
-	    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;
-		}
-	    }
-	}
-
-	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:
-    if (sd)
-    {
-	sd->hasIdentityAssign = 1;	// don't need to generate it
-	goto Ldone;
-    }
-    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);
-
-    // 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 | STCconst | STCfinal | STCinvariant | STCtls);
-	sc2->protection = PROTpublic;
-	sc2->explicitProtection = 0;
-	sc2->structalign = 8;
-	sc2->incontract = 0;
-	sc2->tf = NULL;
-	sc2->tfOfTry = 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);
-		Type *thandle = ad->handle;
-		if (storage_class & STCconst || type->isConst())
-		{
-#if STRUCTTHISREF
-		    thandle = thandle->constOf();
-#else
-		    if (thandle->ty == Tclass)
-			thandle = thandle->constOf();
-		    else
-		    {	assert(thandle->ty == Tpointer);
-			thandle = thandle->nextOf()->constOf()->pointerTo();
-		    }
-#endif
-		}
-		else if (storage_class & STCinvariant || type->isInvariant())
-		{
-#if STRUCTTHISREF
-		    thandle = thandle->invariantOf();
-#else
-		    if (thandle->ty == Tclass)
-			thandle = thandle->invariantOf();
-		    else
-		    {	assert(thandle->ty == Tpointer);
-			thandle = thandle->nextOf()->invariantOf()->pointerTo();
-		    }
-#endif
-		}
-		v = new ThisDeclaration(thandle);
-		v->storage_class |= STCparameter;
-#if STRUCTTHISREF
-		if (thandle->ty == Tstruct)
-		    v->storage_class |= STCref;
-#endif
-		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;
-	    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;
-		v_arguments->semantic(sc2);
-		sc2->insert(v_arguments);
-		v_arguments->parent = this;
-
-		//t = Type::typeinfo->type->constOf()->arrayOf();
-		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;
-	    }
-	}
-
-	// 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
-	 * and install them in parameters[]
-	 */
-	size_t nparams = Argument::dim(f->parameters);
-	if (nparams)
-	{   /* parameters[] has all the tuples removed, as the back end
-	     * doesn't know about tuples
-	     */
-	    parameters = new Dsymbols();
-	    parameters->reserve(nparams);
-	    for (size_t i = 0; i < nparams; i++)
-	    {
-		Argument *arg = Argument::getNth(f->parameters, i);
-		Identifier *id = arg->ident;
-		if (!id)
-		{
-		    /* Generate identifier for un-named parameter,
-		     * because we need it later on.
-		     */
-		    arg->ident = id = Identifier::generateId("_param_", i);
-		}
-		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 | STCfinal | STCconst | STCinvariant | STCnodtor);
-		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
-		    Expression *v = new ThisExp(0);
-		    v->type = vthis->type;
-#if STRUCTTHISREF
-		    if (ad->isStructDeclaration())
-			v = v->addressOf(sc);
-#endif
-		    e = new AssertExp(0, v);
-		}
-		if (e)
-		{
-		    ExpStatement *s = new ExpStatement(0, e);
-		    if (fensure)
-			fensure = new CompoundStatement(0, s, fensure);
-		    else
-			fensure = s;
-		}
-	    }
-
-	    if (fensure)
-	    {	returnLabel = new LabelDsymbol(Id::returnLabel);
-		LabelStatement *ls = new LabelStatement(0, Id::returnLabel, fensure);
-		ls->isReturnLabel = 1;
-		returnLabel->statement = ls;
-	    }
-	    sc2 = sc2->pop();
-	}
-
-	sc2->incontract--;
-
-	if (fbody)
-	{   ClassDeclaration *cd = isClassMember();
-
-	    /* If this is a class constructor
-	     */
-	    if (isCtorDeclaration() && cd)
-	    {
-		for (int i = 0; i < cd->fields.dim; i++)
-		{   VarDeclaration *v = (VarDeclaration *)cd->fields.data[i];
-
-		    v->ctorinit = 0;
-		}
-	    }
-
-	    if (inferRetType || f->retStyle() != RETstack)
-		nrvo_can = 0;
-
-	    fbody = fbody->semantic(sc2);
-
-	    if (inferRetType)
-	    {	// If no return type inferred yet, then infer a void
-		if (!type->nextOf())
-		{
-		    ((TypeFunction *)type)->next = Type::tvoid;
-		    type = type->semantic(loc, sc);
-		}
-		f = (TypeFunction *)type;
-	    }
-
-	    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 final 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)
-	    {
-		int offend = fbody ? fbody->blockExit() & BEfallthru : TRUE;
-		//int offend = fbody ? fbody->fallOffEnd() : TRUE;
-
-		if (type->nextOf()->ty == Tvoid)
-		{
-		    if (offend && isMain())
-		    {	// Add a return 0; statement
-			Statement *s = new ReturnStatement(0, new IntegerExp(0));
-			fbody = new CompoundStatement(0, fbody, s);
-		    }
-		}
-		else
-		{
-		    if (offend)
-		    {   Expression *e;
-
-			if (global.params.warnings)
-			{   warning("%s: no return at end of function", locToChars());
-			}
-
-			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->op = TOKconstruct;
-		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;
-		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
-		    Expression *v = new ThisExp(0);
-		    v->type = vthis->type;
-#if STRUCTTHISREF
-		    if (ad->isStructDeclaration())
-			v = v->addressOf(sc);
-#endif
-		    Expression *se = new StringExp(0, (char *)"null this");
-		    se = se->semantic(sc);
-		    se->type = Type::tchar->arrayOf();
-		    e = new AssertExp(loc, v, se);
-		}
-		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);
-
-	    /* Append destructor calls for parameters as finally blocks.
-	     */
-	    if (parameters)
-	    {	for (size_t i = 0; i < parameters->dim; i++)
-		{
-		    VarDeclaration *v = (VarDeclaration *)parameters->data[i];
-
-		    if (v->storage_class & (STCref | STCout))
-			continue;
-
-		    /* Don't do this for static arrays, since static
-		     * arrays are called by reference. Remove this
-		     * when we change them to call by value.
-		     */
-		    if (v->type->toBasetype()->ty == Tsarray)
-			continue;
-
-		    Expression *e = v->callAutoDtor(sc);
-		    if (e)
-		    {	Statement *s = new ExpStatement(0, e);
-			s = s->semantic(sc);
-			if (fbody->blockExit() == BEfallthru)
-			    fbody = new CompoundStatement(0, fbody, s);
-			else
-			    fbody = new TryFinallyStatement(0, fbody, s);
-		    }
-		}
-	    }
-	}
-
-	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 0
-    /* Disable this check because:
-     *	const void foo();
-     * semantic() isn't run yet on foo(), so the const hasn't been
-     * applied yet.
-     */
-    if (type)
-    {   printf("type = %s\n", type->toChars());
-	printf("f->type = %s\n", f->type->toChars());
-    }
-    if (type && f->type &&	// can be NULL for overloaded constructors
-	f->type->covariant(type) &&
-	f->type->mod == type->mod &&
-	!isFuncAliasDeclaration())
-    {
-	//printf("\tfalse: conflict %s\n", kind());
-	return FALSE;
-    }
-#endif
-
-    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(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 (overloadApply(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;
-	    }
-	    else
-	    {
-		f = d->isFuncDeclaration();
-		if (!f)
-		{   d->error("is aliased to a function");
-		    break;		// BUG: should print error message?
-		}
-		if ((*fp)(param, f))
-		    return 1;
-
-		next = f->overnext;
-	    }
-	}
-    }
-    return 0;
-}
-
-/********************************************
- * If there are no overloads of function f, return that function,
- * otherwise return NULL.
- */
-
-static int fpunique(void *param, FuncDeclaration *f)
-{   FuncDeclaration **pf = (FuncDeclaration **)param;
-
-    if (*pf)
-    {	*pf = NULL;
-	return 1;		// ambiguous, done
-    }
-    else
-    {	*pf = f;
-	return 0;
-    }
-}
-
-FuncDeclaration *FuncDeclaration::isUnique()
-{   FuncDeclaration *result = NULL;
-
-    overloadApply(this, &fpunique, &result);
-    return result;
-}
-
-/********************************************
- * Find function in overload list that exactly matches t.
- */
-
-struct Param1
-{
-    Type *t;		// type to match
-    FuncDeclaration *f;	// return value
-};
-
-int fp1(void *param, FuncDeclaration *f)
-{   Param1 *p = (Param1 *)param;
-    Type *t = p->t;
-
-    if (t->equals(f->type))
-    {	p->f = f;
-	return 1;
-    }
-
-#if DMDV2
-    /* Allow covariant matches, if it's just a const conversion
-     * of the return type
-     */
-    if (t->ty == Tfunction)
-    {   TypeFunction *tf = (TypeFunction *)f->type;
-	if (tf->covariant(t) == 1 &&
-	    tf->nextOf()->implicitConvTo(t->nextOf()) >= MATCHconst)
-	{
-	    p->f = f;
-	    return 1;
-	}
-    }
-#endif
-    return 0;
-}
-
-FuncDeclaration *FuncDeclaration::overloadExactMatch(Type *t)
-{
-    Param1 p;
-    p.t = t;
-    p.f = NULL;
-    overloadApply(this, &fp1, &p);
-    return p.f;
-}
-
-
-/********************************************
- * Decide which function matches the arguments best.
- */
-
-struct Param2
-{
-    Match *m;
-    Expression *ethis;
-    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(f->needThis() ? p->ethis : NULL, arguments);
-	//printf("match = %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;
-
-	    /* Try to disambiguate using template-style partial ordering rules.
-	     * In essence, if f() and g() are ambiguous, if f() can call g(),
-	     * but g() cannot call f(), then pick f().
-	     * This is because f() is "more specialized."
-	     */
-	    {
-	    MATCH c1 = f->leastAsSpecialized(m->lastf);
-	    MATCH c2 = m->lastf->leastAsSpecialized(f);
-	    //printf("c1 = %d, c2 = %d\n", c1, c2);
-	    if (c1 > c2)
-		goto LfIsBetter;
-	    if (c1 < c2)
-		goto LlastIsBetter;
-	    }
-
-	Lambiguous:
-	    m->nextf = f;
-	    m->count++;
-	    return 0;
-
-	LfIsBetter:
-	    m->last = match;
-	    m->lastf = f;
-	    m->count = 1;
-	    return 0;
-
-	LlastIsBetter:
-	    return 0;
-	}
-    }
-    return 0;
-}
-
-void overloadResolveX(Match *m, FuncDeclaration *fstart,
-	Expression *ethis, Expressions *arguments)
-{
-    Param2 p;
-    p.m = m;
-    p.ethis = ethis;
-    p.arguments = arguments;
-    overloadApply(fstart, &fp2, &p);
-}
-
-
-FuncDeclaration *FuncDeclaration::overloadResolve(Loc loc, Expression *ethis, Expressions *arguments, int flags)
-{
-    TypeFunction *tf;
-    Match m;
-
-#if 0
-printf("FuncDeclaration::overloadResolve('%s')\n", toChars());
-if (arguments)
-{   int i;
-
-    for (i = 0; i < arguments->dim; i++)
-    {   Expression *arg;
-
-	arg = (Expression *)arguments->data[i];
-	assert(arg->type);
-	printf("\t%s: ", arg->toChars());
-	arg->type->print();
-    }
-}
-#endif
-
-    memset(&m, 0, sizeof(m));
-    m.last = MATCHnomatch;
-    overloadResolveX(&m, this, ethis, arguments);
-
-    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)
-	{
-	    if (flags & 1)		// if do not print error messages
-		return NULL;		// no match
-
-	    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;
-	}
-    }
-}
-
-/*************************************
- * Determine partial specialization order of 'this' vs g.
- * This is very similar to TemplateDeclaration::leastAsSpecialized().
- * Returns:
- *	match	'this' is at least as specialized as g
- *	0	g is more specialized than 'this'
- */
-
-MATCH FuncDeclaration::leastAsSpecialized(FuncDeclaration *g)
-{
-#define LOG_LEASTAS     0
-
-#if LOG_LEASTAS
-    printf("%s.leastAsSpecialized(%s)\n", toChars(), g->toChars());
-#endif
-
-    /* This works by calling g() with f()'s parameters, and
-     * if that is possible, then f() is at least as specialized
-     * as g() is.
-     */
-
-    TypeFunction *tf = (TypeFunction *)type;
-    TypeFunction *tg = (TypeFunction *)g->type;
-    size_t nfparams = Argument::dim(tf->parameters);
-    size_t ngparams = Argument::dim(tg->parameters);
-    MATCH match = MATCHexact;
-
-    /* If both functions have a 'this' pointer, and the mods are not
-     * the same and g's is not const, then this is less specialized.
-     */
-    if (needThis() && g->needThis())
-    {
-	if (tf->mod != tg->mod)
-	{
-	    if (tg->mod == MODconst)
-		match = MATCHconst;
-	    else
-		return MATCHnomatch;
-	}
-    }
-
-    /* Create a dummy array of arguments out of the parameters to f()
-     */
-    Expressions args;
-    args.setDim(nfparams);
-    for (int u = 0; u < nfparams; u++)
-    {
-	Argument *p = Argument::getNth(tf->parameters, u);
-	Expression *e;
-	if (p->storageClass & (STCref | STCout))
-	{
-	    e = new IdentifierExp(0, p->ident);
-	    e->type = p->type;
-	}
-	else
-	    e = p->type->defaultInit();
-	args.data[u] = e;
-    }
-
-    MATCH m = (MATCH) tg->callMatch(NULL, &args);
-    if (m)
-    {
-        /* A variadic parameter list is less specialized than a
-         * non-variadic one.
-         */
-        if (tf->varargs && !tg->varargs)
-            goto L1;	// less specialized
-
-#if LOG_LEASTAS
-        printf("  matches %d, so is least as specialized\n", m);
-#endif
-        return m;
-    }
-  L1:
-#if LOG_LEASTAS
-    printf("  doesn't match, so is not as specialized\n");
-#endif
-    return MATCHnomatch;
-}
-
-/********************************
- * 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("isMember:%p isStatic:%d private:%d ctor:%d !Dlinkage:%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
-}
-
-int FuncDeclaration::isOverloadable()
-{
-    return 1;			// functions can be overloaded
-}
-
-// 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("\ttoParent2() = '%s'\n", toParent2()->toChars());
-    return ((storage_class & STCstatic) == 0) &&
-	   (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 &&
-	    ident != Id::cpctor);
-}
-
-int FuncDeclaration::addPostInvariant()
-{
-    AggregateDeclaration *ad = isThis();
-    return (ad &&
-	    ad->inv &&
-	    //ad->isClassDeclaration() &&
-	    global.params.useInvariants &&
-	    (protection == PROTpublic || protection == PROTexport) &&
-	    !naked &&
-	    ident != Id::cpctor);
-}
-
-/**********************************
- * 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;
-}
-
-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)
-{
-    AggregateDeclaration *ad;
-    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();
-    ad = parent->isAggregateDeclaration();
-    if (!ad || parent->isUnionDeclaration())
-    {
-	error("constructors are only for class or struct definitions");
-	fatal();
-	tret = Type::tvoid;
-    }
-    else
-    {	tret = ad->handle;
-	assert(tret);
-    }
-    type = new TypeFunction(arguments, tret, varargs, LINKd);
-#if STRUCTTHISREF
-    if (ad && ad->isStructDeclaration())
-	((TypeFunction *)type)->isref = 1;
-#endif
-    if (!originalType)
-	originalType = type;
-
-    sc->flags |= SCOPEctor;
-    type = type->semantic(loc, sc);
-    sc->flags &= ~SCOPEctor;
-
-    // Append:
-    //	return this;
-    // to the function body
-    if (fbody)
-    {
-	Expression *e = new ThisExp(0);
-	Statement *s = new ReturnStatement(0, e);
-	fbody = new CompoundStatement(0, fbody, s);
-    }
-
-    FuncDeclaration::semantic(sc);
-
-    sc->pop();
-
-    // See if it's the default constructor
-    if (ad && varargs == 0 && Argument::dim(arguments) == 0)
-    {	if (ad->isStructDeclaration())
-	    error("default constructor not allowed for structs");
-	else
-	    ad->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);
-}
-
-/********************************* PostBlitDeclaration ****************************/
-
-PostBlitDeclaration::PostBlitDeclaration(Loc loc, Loc endloc)
-    : FuncDeclaration(loc, endloc, Id::_postblit, STCundefined, NULL)
-{
-}
-
-PostBlitDeclaration::PostBlitDeclaration(Loc loc, Loc endloc, Identifier *id)
-    : FuncDeclaration(loc, endloc, id, STCundefined, NULL)
-{
-}
-
-Dsymbol *PostBlitDeclaration::syntaxCopy(Dsymbol *s)
-{
-    assert(!s);
-    PostBlitDeclaration *dd = new PostBlitDeclaration(loc, endloc, ident);
-    return FuncDeclaration::syntaxCopy(dd);
-}
-
-
-void PostBlitDeclaration::semantic(Scope *sc)
-{
-    //printf("PostBlitDeclaration::semantic() %s\n", toChars());
-    //printf("ident: %s, %s, %p, %p\n", ident->toChars(), Id::dtor->toChars(), ident, Id::dtor);
-    parent = sc->parent;
-    Dsymbol *parent = toParent();
-    StructDeclaration *ad = parent->isStructDeclaration();
-    if (!ad)
-    {
-	error("post blits are only for struct/union definitions, not %s %s", parent->kind(), parent->toChars());
-    }
-    else if (ident == Id::_postblit)
-	ad->postblits.push(this);
-    type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd);
-
-    sc = sc->push();
-    sc->stc &= ~STCstatic;		// not static
-    sc->linkage = LINKd;
-
-    FuncDeclaration::semantic(sc);
-
-    sc->pop();
-}
-
-int PostBlitDeclaration::overloadInsert(Dsymbol *s)
-{
-    return FALSE;	// cannot overload postblits
-}
-
-int PostBlitDeclaration::addPreInvariant()
-{
-    return FALSE;
-}
-
-int PostBlitDeclaration::addPostInvariant()
-{
-    return (vthis && global.params.useInvariants);
-}
-
-int PostBlitDeclaration::isVirtual()
-{
-    return FALSE;
-}
-
-void PostBlitDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{
-    if (hgs->hdrgen)
-	return;
-    buf->writestring("=this()");
-    bodyToCBuffer(buf, hgs);
-}
-
-/********************************* DtorDeclaration ****************************/
-
-DtorDeclaration::DtorDeclaration(Loc loc, Loc endloc)
-    : FuncDeclaration(loc, endloc, Id::dtor, STCundefined, NULL)
-{
-}
-
-DtorDeclaration::DtorDeclaration(Loc loc, Loc endloc, Identifier *id)
-    : FuncDeclaration(loc, endloc, id, STCundefined, NULL)
-{
-}
-
-Dsymbol *DtorDeclaration::syntaxCopy(Dsymbol *s)
-{
-    assert(!s);
-    DtorDeclaration *dd = new DtorDeclaration(loc, endloc, ident);
-    return FuncDeclaration::syntaxCopy(dd);
-}
-
-
-void DtorDeclaration::semantic(Scope *sc)
-{
-    //printf("DtorDeclaration::semantic() %s\n", toChars());
-    //printf("ident: %s, %s, %p, %p\n", ident->toChars(), Id::dtor->toChars(), ident, Id::dtor);
-    parent = sc->parent;
-    Dsymbol *parent = toParent();
-    AggregateDeclaration *ad = parent->isAggregateDeclaration();
-    if (!ad)
-    {
-	error("destructors are only for class/struct/union definitions, not %s %s", parent->kind(), parent->toChars());
-	fatal();
-    }
-    else if (ident == Id::dtor)
-	ad->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 only are 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 uint
-    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);
+    //printf("storage_class = x%x\n", storage_class);
+    this->storage_class = storage_class;
+    this->type = type;
+    this->loc = loc;
+    this->endloc = endloc;
+    fthrows = NULL;
+    frequire = NULL;
+    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;
+    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
+
+    builtin = BUILTINunknown;
+    tookAddressOf = 0;
+
+#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, parent = %s\n", sc->parent->toChars(), parent ? parent->toChars() : "");
+    printf("type: %p, %s\n", type, type->toChars());
+#endif
+
+    if (semanticRun && isFuncLiteralDeclaration())
+    {
+	/* Member functions that have return types that are
+	 * forward references can have semantic() run more than
+	 * once on them.
+	 * See test\interface2.d, test20
+	 */
+	return;
+    }
+    assert(semanticRun <= 1);
+    semanticRun = 1;
+
+    storage_class |= sc->stc & ~STCref;
+    //printf("function storage_class = x%x\n", storage_class);
+
+    if (!originalType)
+	originalType = type;
+    if (!type->deco && type->nextOf())
+    {
+	/* Apply const and invariant storage class
+	 * to the function type
+	 */
+	type = type->semantic(loc, sc);
+	unsigned stc = storage_class;
+	if (type->isInvariant())
+	    stc |= STCimmutable;
+	if (type->isConst())
+	    stc |= STCconst;
+	if (type->isShared())
+	    stc |= STCshared;
+	switch (stc & STC_TYPECTOR)
+	{
+	    case STCimmutable:
+	    case STCimmutable | STCconst:
+	    case STCimmutable | STCconst | STCshared:
+	    case STCimmutable | STCshared:
+		// Don't use toInvariant(), as that will do a merge()
+		type = type->makeInvariant();
+		type->deco = type->merge()->deco;
+		break;
+
+	    case STCconst:
+		type = type->makeConst();
+		type->deco = type->merge()->deco;
+		break;
+
+	    case STCshared | STCconst:
+		type = type->makeSharedConst();
+		type->deco = type->merge()->deco;
+		break;
+
+	    case STCshared:
+		type = type->makeShared();
+		type->deco = type->merge()->deco;
+		break;
+
+	    case 0:
+		break;
+
+	    default:
+		assert(0);
+	}
+    }
+    //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;
+    Dsymbol *parent = toParent();
+
+    if (storage_class & STCscope)
+	error("functions cannot be scope");
+
+    if (isAbstract() && !isVirtual())
+	error("non-virtual functions cannot be abstract");
+
+    if ((f->isConst() || f->isInvariant()) && !isThis())
+	error("without 'this' cannot be const/immutable");
+
+    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)
+    {
+	if (isCtorDeclaration())
+	{
+	    return;
+	}
+#if 0
+	// Verify no constructors, destructors, etc.
+	if (isCtorDeclaration()
+	    //||isDtorDeclaration()
+	    //|| isInvariantDeclaration()
+	    //|| isUnitTestDeclaration()
+	   )
+	{
+	    error("special member functions not allowed for %ss", sd->kind());
+	}
+
+	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() ||
+	    isPostBlitDeclaration() ||
+	    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++)
+	{
+	    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;
+		}
+	    }
+	}
+
+	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:
+    if (sd)
+    {
+	sd->hasIdentityAssign = 1;	// don't need to generate it
+	goto Ldone;
+    }
+    error("identity assignment operator overload is illegal");
+}
+
+void FuncDeclaration::semantic2(Scope *sc)
+{
+}
+
+// Do the semantic analysis on the internals of the function.
+
+void FuncDeclaration::semantic3(Scope *sc)
+{   TypeFunction *f;
+    VarDeclaration *argptr = NULL;
+    VarDeclaration *_arguments = NULL;
+
+    if (!parent)
+    {
+	if (global.errors)
+	    return;
+	//printf("FuncDeclaration::semantic3(%s '%s', sc = %p)\n", kind(), toChars(), sc);
+	assert(0);
+    }
+    //printf("FuncDeclaration::semantic3('%s.%s', sc = %p, loc = %s)\n", parent->toChars(), toChars(), sc, loc.toChars());
+    //fflush(stdout);
+    //printf("storage class = x%x %x\n", sc->stc, storage_class);
+    //{ static int x; if (++x == 2) *(char*)0=0; }
+    //printf("\tlinkage = %d\n", sc->linkage);
+
+    //printf(" sc->incontract = %d\n", sc->incontract);
+    if (semanticRun >= 3)
+	return;
+    semanticRun = 3;
+
+    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 | STC_TYPECTOR | STCfinal | STCtls | STCgshared | STCref);
+	sc2->protection = PROTpublic;
+	sc2->explicitProtection = 0;
+	sc2->structalign = 8;
+	sc2->incontract = 0;
+#if !IN_LLVM
+	sc2->tf = NULL;
+#else
+	sc2->enclosingFinally = NULL;
+	sc2->enclosingScopeExit = NULL;
+#endif
+	sc2->noctor = 0;
+
+	// Declare 'this'
+	AggregateDeclaration *ad = isThis();
+	if (ad)
+	{   VarDeclaration *v;
+
+	    if (isFuncLiteralDeclaration() && isNested())
+	    {
+		error("literals cannot be class members");
+		return;
+	    }
+	    else
+	    {
+		assert(!isNested());	// can't be both member and nested
+		assert(ad->handle);
+		Type *thandle = ad->handle;
+#if STRUCTTHISREF
+		thandle = thandle->addMod(type->mod);
+		thandle = thandle->addStorageClass(storage_class);
+		if (isPure())
+		    thandle = thandle->addMod(MODconst);
+#else
+		if (storage_class & STCconst || type->isConst())
+		{
+		    assert(0); // BUG: shared not handled
+		    if (thandle->ty == Tclass)
+			thandle = thandle->constOf();
+		    else
+		    {	assert(thandle->ty == Tpointer);
+			thandle = thandle->nextOf()->constOf()->pointerTo();
+		    }
+		}
+		else if (storage_class & STCimmutable || type->isInvariant())
+		{
+		    if (thandle->ty == Tclass)
+			thandle = thandle->invariantOf();
+		    else
+		    {	assert(thandle->ty == Tpointer);
+			thandle = thandle->nextOf()->invariantOf()->pointerTo();
+		    }
+		}
+		else if (storage_class & STCshared || type->isShared())
+		{
+		    assert(0);  // not implemented
+		}
+#endif
+		v = new ThisDeclaration(loc, thandle);
+		v->storage_class |= STCparameter;
+#if STRUCTTHISREF
+		if (thandle->ty == Tstruct)
+		    v->storage_class |= STCref;
+#endif
+		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;
+	    v->semantic(sc2);
+	    if (!sc2->insert(v))
+		assert(0);
+	    v->parent = this;
+	    vthis = v;
+	}
+
+	// Declare hidden variable _arguments[] and _argptr
+	if (f->varargs == 1)
+	{
+#if TARGET_NET
+        varArgs(sc2, f, argptr, _arguments);
+#else
+        Type *t;
+
+	    if (f->linkage == LINKd)
+	    {	// Declare _arguments[]
+#if BREAKABI
+		v_arguments = new VarDeclaration(0, Type::typeinfotypelist->type, Id::_arguments_typeinfo, NULL);
+		v_arguments->storage_class = STCparameter;
+		v_arguments->semantic(sc2);
+		sc2->insert(v_arguments);
+		v_arguments->parent = this;
+
+		//t = Type::typeinfo->type->constOf()->arrayOf();
+		t = Type::typeinfo->type->arrayOf();
+		_arguments = new VarDeclaration(0, t, Id::_arguments, NULL);
+		_arguments->semantic(sc2);
+		sc2->insert(_arguments);
+		_arguments->parent = this;
+#else
+		t = Type::typeinfo->type->arrayOf();
+		v_arguments = new VarDeclaration(0, t, Id::_arguments, NULL);
+		v_arguments->storage_class = STCparameter | STCin;
+		v_arguments->semantic(sc2);
+		sc2->insert(v_arguments);
+		v_arguments->parent = this;
+#endif
+	    }
+	    if (f->linkage == LINKd || (parameters && parameters->dim))
+	    {	// Declare _argptr
+#if IN_GCC
+		t = d_gcc_builtin_va_list_d_type;
+#else
+		t = Type::tvoid->pointerTo();
+#endif
+		argptr = new VarDeclaration(0, t, Id::_argptr, NULL);
+		argptr->semantic(sc2);
+		sc2->insert(argptr);
+		argptr->parent = this;
+	    }
+#endif
+	}
+
+#if IN_LLVM
+        // LDC make sure argument type is semanticed.
+        // Turns TypeTuple!(int, int) into two int parameters, for instance.
+        if (f->parameters)
+        {
+            for (size_t i = 0; i < Argument::dim(f->parameters); i++)
+	    {	Argument *arg = (Argument *)Argument::getNth(f->parameters, i);
+                Type* nw = arg->type->semantic(0, sc);
+                if (arg->type != nw) {
+                    arg->type = nw;
+                    // Examine this index again.
+                    // This is important if it turned into a tuple.
+                    // In particular, the empty tuple should be handled or the
+                    // next parameter will be skipped.
+                    // FIXME: Maybe we only need to do this for tuples,
+                    //        and can add tuple.length after decrement?
+                    i--;
+                }
+            }
+            // 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
+	 * and install them in parameters[]
+	 */
+	size_t nparams = Argument::dim(f->parameters);
+	if (nparams)
+	{   /* parameters[] has all the tuples removed, as the back end
+	     * doesn't know about tuples
+	     */
+	    parameters = new Dsymbols();
+	    parameters->reserve(nparams);
+	    for (size_t i = 0; i < nparams; i++)
+	    {
+		Argument *arg = Argument::getNth(f->parameters, i);
+		Identifier *id = arg->ident;
+		if (!id)
+		{
+		    /* Generate identifier for un-named parameter,
+		     * because we need it later on.
+		     */
+		    arg->ident = id = Identifier::generateId("_param_", i);
+		}
+		Type *vtype = arg->type;
+		if (isPure())
+		    vtype = vtype->addMod(MODconst);
+		VarDeclaration *v = new VarDeclaration(loc, vtype, id, NULL);
+		//printf("declaring parameter %s of type %s\n", v->toChars(), v->type->toChars());
+		v->storage_class |= STCparameter;
+		if (f->varargs == 2 && i + 1 == nparams)
+		    v->storage_class |= STCvariadic;
+		v->storage_class |= arg->storageClass & (STCin | STCout | STCref | STClazy | STCfinal | STC_TYPECTOR | STCnodtor);
+		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
+		    Expression *v = new ThisExp(0);
+		    v->type = vthis->type;
+#if STRUCTTHISREF
+		    if (ad->isStructDeclaration())
+			v = v->addressOf(sc);
+#endif
+		    e = new AssertExp(0, v);
+		}
+		if (e)
+		{
+		    ExpStatement *s = new ExpStatement(0, e);
+		    if (fensure)
+			fensure = new CompoundStatement(0, s, fensure);
+		    else
+			fensure = s;
+		}
+	    }
+
+	    if (fensure)
+	    {	returnLabel = new LabelDsymbol(Id::returnLabel);
+		LabelStatement *ls = new LabelStatement(0, Id::returnLabel, fensure);
+		ls->isReturnLabel = 1;
+		returnLabel->statement = ls;
+	    }
+	    sc2 = sc2->pop();
+	}
+
+	sc2->incontract--;
+
+	if (fbody)
+	{   ClassDeclaration *cd = isClassMember();
+
+	    /* If this is a class constructor
+	     */
+	    if (isCtorDeclaration() && cd)
+	    {
+		for (int i = 0; i < cd->fields.dim; i++)
+		{   VarDeclaration *v = (VarDeclaration *)cd->fields.data[i];
+
+		    v->ctorinit = 0;
+		}
+	    }
+
+	    if (inferRetType || f->retStyle() != RETstack)
+		nrvo_can = 0;
+
+	    fbody = fbody->semantic(sc2);
+
+	    if (inferRetType)
+	    {	// If no return type inferred yet, then infer a void
+		if (!type->nextOf())
+		{
+		    ((TypeFunction *)type)->next = Type::tvoid;
+		    type = type->semantic(loc, sc);
+		}
+		f = (TypeFunction *)type;
+	    }
+
+	    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 final 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);
+
+		    e = e->trySemantic(sc2);
+		    if (!e)
+			error("no match for implicit super() call in constructor");
+		    else
+		    {
+			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)
+	    {
+		int blockexit = fbody ? fbody->blockExit() : 0;
+		if (f->isnothrow && blockexit & BEthrow)
+		    error("'%s' is nothrow yet may throw", toChars());
+
+		int offend = blockexit & BEfallthru;
+
+		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->op = TOKconstruct;
+		e = e->semantic(sc2);
+		a->push(new ExpStatement(0, e));
+	    }
+
+#endif // !IN_LLVM
+
+	    // Merge contracts together with body into one compound statement
+
+#ifdef _DH
+	    if (frequire && global.params.useIn)
+	    {	frequire->incontract = 1;
+		a->push(frequire);
+	    }
+#else
+	    if (frequire && global.params.useIn)
+		a->push(frequire);
+#endif
+
+	    // Precondition invariant
+	    if (addPreInvariant())
+	    {
+		Expression *e = NULL;
+                Expression *ee = NULL;
+		if (isDtorDeclaration())
+		{
+		    // Call invariant directly only if it exists
+		    InvariantDeclaration *inv = ad->inv;
+		    ClassDeclaration *cd = ad->isClassDeclaration();
+
+		    while (!inv && cd)
+		    {
+			cd = cd->baseClass;
+			if (!cd)
+			    break;
+			inv = cd->inv;
+		    }
+		    if (inv)
+		    {
+			e = new DsymbolExp(0, inv);
+			e = new CallExp(0, e);
+			e = e->semantic(sc2);
+		    }
+		}
+		else
+		{   // Call invariant virtually
+		    Expression *v = new ThisExp(0);
+		    v->type = vthis->type;
+#if STRUCTTHISREF
+		    if (ad->isStructDeclaration())
+			v = v->addressOf(sc);
+#endif
+#if IN_LLVM
+                    //e = new AssertExp(loc, v, NULL);
+
+                    // LDC: check for null this
+                    //v = new ThisExp(0);
+                    //v->type = vthis->type;
+                    //v->var = vthis; // Error: Expression has no property var... in D1 typeof(v) == ThisExp
+
+                    //NullExp *nv = new NullExp(0);
+                    //nv->type = v->type;
+
+                    //IdentityExp *ie = new IdentityExp(TOKnotidentity, 0, v, nv);
+                    //ie->type = Type::tbool;
+#endif
+		    Expression *se = new StringExp(0, (char *)"null this");
+		    se = se->semantic(sc);
+		    se->type = Type::tchar->arrayOf();
+//#if IN_LLVM
+//		    ee = new AssertExp(loc, ie, se);
+//#else
+		    e = new AssertExp(loc, v, se);
+//#endif
+		}
+                if (ee)
+                {
+                    ExpStatement *s = new ExpStatement(0, ee);
+                    a->push(s);
+                }
+		if (e)
+		{
+		    ExpStatement *s = new ExpStatement(0, e);
+		    a->push(s);
+		}
+	    }
+
+	    if (fbody)
+		a->push(fbody);
+
+	    if (fensure)
+	    {
+		a->push(returnLabel->statement);
+
+		if (type->nextOf()->ty != Tvoid)
+		{
+		    // Create: return vresult;
+		    assert(vresult);
+		    Expression *e = new VarExp(0, vresult);
+		    if (tintro)
+		    {	e = e->implicitCastTo(sc, tintro->nextOf());
+			e = e->semantic(sc);
+		    }
+		    ReturnStatement *s = new ReturnStatement(0, e);
+		    a->push(s);
+		}
+	    }
+
+	    fbody = new CompoundStatement(0, a);
+
+#if IN_LLVM
+	    // 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);
+	    }
+#endif
+
+	    /* Append destructor calls for parameters as finally blocks.
+	     */
+	    if (parameters)
+	    {	for (size_t i = 0; i < parameters->dim; i++)
+		{
+		    VarDeclaration *v = (VarDeclaration *)parameters->data[i];
+
+		    if (v->storage_class & (STCref | STCout))
+			continue;
+
+		    /* Don't do this for static arrays, since static
+		     * arrays are called by reference. Remove this
+		     * when we change them to call by value.
+		     */
+		    if (v->type->toBasetype()->ty == Tsarray)
+			continue;
+
+		    Expression *e = v->callAutoDtor(sc);
+		    if (e)
+		    {	Statement *s = new ExpStatement(0, e);
+			s = s->semantic(sc);
+			if (fbody->blockExit() == BEfallthru)
+			    fbody = new CompoundStatement(0, fbody, s);
+			else
+			    fbody = new TryFinallyStatement(0, fbody, s);
+		    }
+		}
+	    }
+	}
+
+	sc2->callSuper = 0;
+	sc2->pop();
+    }
+    semanticRun = 4;
+}
+
+void FuncDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    //printf("FuncDeclaration::toCBuffer() '%s'\n", toChars());
+
+    StorageClassDeclaration::stcToCBuffer(buf, storage_class);
+    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 0
+    /* Disable this check because:
+     *	const void foo();
+     * semantic() isn't run yet on foo(), so the const hasn't been
+     * applied yet.
+     */
+    if (type)
+    {   printf("type = %s\n", type->toChars());
+	printf("f->type = %s\n", f->type->toChars());
+    }
+    if (type && f->type &&	// can be NULL for overloaded constructors
+	f->type->covariant(type) &&
+	f->type->mod == type->mod &&
+	!isFuncAliasDeclaration())
+    {
+	//printf("\tfalse: conflict %s\n", kind());
+	return FALSE;
+    }
+#endif
+
+    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 IN_LLVM
+		if (a->importprot == PROTprivate && a->getModule() != from)
+		    if (FuncDeclaration* fd = next->isFuncDeclaration())
+			next = fd->overnext;
+#endif
+	    }
+	    else
+	    {
+		f = d->isFuncDeclaration();
+		if (!f)
+		{   d->error("is aliased to a function");
+		    break;		// BUG: should print error message?
+		}
+		if ((*fp)(param, f))
+		    return 1;
+
+		next = f->overnext;
+	    }
+	}
+    }
+    return 0;
+}
+
+/********************************************
+ * If there are no overloads of function f, return that function,
+ * otherwise return NULL.
+ */
+
+static int fpunique(void *param, FuncDeclaration *f)
+{   FuncDeclaration **pf = (FuncDeclaration **)param;
+
+    if (*pf)
+    {	*pf = NULL;
+	return 1;		// ambiguous, done
+    }
+    else
+    {	*pf = f;
+	return 0;
+    }
+}
+
+FuncDeclaration *FuncDeclaration::isUnique()
+{   FuncDeclaration *result = NULL;
+
+    overloadApply(getModule(), this, &fpunique, &result);
+    return result;
+}
+
+/********************************************
+ * Find function in overload list that exactly matches t.
+ */
+
+struct Param1
+{
+    Type *t;		// type to match
+    FuncDeclaration *f;	// return value
+};
+
+int fp1(void *param, FuncDeclaration *f)
+{   Param1 *p = (Param1 *)param;
+    Type *t = p->t;
+
+    if (t->equals(f->type))
+    {	p->f = f;
+	return 1;
+    }
+
+#if DMDV2
+    /* Allow covariant matches, if it's just a const conversion
+     * of the return type
+     */
+    if (t->ty == Tfunction)
+    {   TypeFunction *tf = (TypeFunction *)f->type;
+	if (tf->covariant(t) == 1 &&
+	    tf->nextOf()->implicitConvTo(t->nextOf()) >= MATCHconst)
+	{
+	    p->f = f;
+	    return 1;
+	}
+    }
+#endif
+    return 0;
+}
+
+FuncDeclaration *FuncDeclaration::overloadExactMatch(Type *t, Module* from)
+{
+    Param1 p;
+    p.t = t;
+    p.f = NULL;
+    overloadApply(from, this, &fp1, &p);
+    return p.f;
+}
+
+
+/********************************************
+ * Decide which function matches the arguments best.
+ */
+
+struct Param2
+{
+    Match *m;
+    Expression *ethis;
+    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(f->needThis() ? p->ethis : NULL, arguments);
+	//printf("match = %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;
+
+	    /* Try to disambiguate using template-style partial ordering rules.
+	     * In essence, if f() and g() are ambiguous, if f() can call g(),
+	     * but g() cannot call f(), then pick f().
+	     * This is because f() is "more specialized."
+	     */
+	    {
+	    MATCH c1 = f->leastAsSpecialized(m->lastf);
+	    MATCH c2 = m->lastf->leastAsSpecialized(f);
+	    //printf("c1 = %d, c2 = %d\n", c1, c2);
+	    if (c1 > c2)
+		goto LfIsBetter;
+	    if (c1 < c2)
+		goto LlastIsBetter;
+	    }
+
+	Lambiguous:
+	    m->nextf = f;
+	    m->count++;
+	    return 0;
+
+	LfIsBetter:
+	    m->last = match;
+	    m->lastf = f;
+	    m->count = 1;
+	    return 0;
+
+	LlastIsBetter:
+	    return 0;
+	}
+    }
+    return 0;
+}
+
+void overloadResolveX(Match *m, FuncDeclaration *fstart,
+	Expression *ethis, Expressions *arguments, Module* from)
+{
+    Param2 p;
+    p.m = m;
+    p.ethis = ethis;
+    p.arguments = arguments;
+    overloadApply(from, fstart, &fp2, &p);
+}
+
+
+FuncDeclaration *FuncDeclaration::overloadResolve(Loc loc, Expression *ethis, Expressions *arguments, int flags, 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, ethis, 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)
+	{
+	    if (flags & 1)		// if do not print error messages
+		return NULL;		// no match
+
+	    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;
+	}
+    }
+}
+
+/*************************************
+ * Determine partial specialization order of 'this' vs g.
+ * This is very similar to TemplateDeclaration::leastAsSpecialized().
+ * Returns:
+ *	match	'this' is at least as specialized as g
+ *	0	g is more specialized than 'this'
+ */
+
+MATCH FuncDeclaration::leastAsSpecialized(FuncDeclaration *g)
+{
+#define LOG_LEASTAS     0
+
+#if LOG_LEASTAS
+    printf("%s.leastAsSpecialized(%s)\n", toChars(), g->toChars());
+#endif
+
+    /* This works by calling g() with f()'s parameters, and
+     * if that is possible, then f() is at least as specialized
+     * as g() is.
+     */
+
+    TypeFunction *tf = (TypeFunction *)type;
+    TypeFunction *tg = (TypeFunction *)g->type;
+    size_t nfparams = Argument::dim(tf->parameters);
+    size_t ngparams = Argument::dim(tg->parameters);
+    MATCH match = MATCHexact;
+
+    /* If both functions have a 'this' pointer, and the mods are not
+     * the same and g's is not const, then this is less specialized.
+     */
+    if (needThis() && g->needThis())
+    {
+	if (tf->mod != tg->mod)
+	{
+	    if (tg->mod == MODconst)
+		match = MATCHconst;
+	    else
+		return MATCHnomatch;
+	}
+    }
+
+    /* Create a dummy array of arguments out of the parameters to f()
+     */
+    Expressions args;
+    args.setDim(nfparams);
+    for (int u = 0; u < nfparams; u++)
+    {
+	Argument *p = Argument::getNth(tf->parameters, u);
+	Expression *e;
+	if (p->storageClass & (STCref | STCout))
+	{
+	    e = new IdentifierExp(0, p->ident);
+	    e->type = p->type;
+	}
+	else
+	    e = p->type->defaultInit();
+	args.data[u] = e;
+    }
+
+    MATCH m = (MATCH) tg->callMatch(NULL, &args);
+    if (m)
+    {
+        /* A variadic parameter list is less specialized than a
+         * non-variadic one.
+         */
+        if (tf->varargs && !tg->varargs)
+            goto L1;	// less specialized
+
+#if LOG_LEASTAS
+        printf("  matches %d, so is least as specialized\n", m);
+#endif
+        return m;
+    }
+  L1:
+#if LOG_LEASTAS
+    printf("  doesn't match, so is not as specialized\n");
+#endif
+    return MATCHnomatch;
+}
+
+/*******************************************
+ * Given a symbol that could be either a FuncDeclaration or
+ * a function template, resolve it to a function symbol.
+ *	sc		instantiation scope
+ *	loc		instantiation location
+ *	targsi		initial list of template arguments
+ *	ethis		if !NULL, the 'this' pointer argument
+ *	fargs		arguments to function
+ *	flags		1: do not issue error message on no match, just return NULL
+ */
+
+FuncDeclaration *resolveFuncCall(Scope *sc, Loc loc, Dsymbol *s,
+	Objects *tiargs,
+	Expression *ethis,
+	Expressions *arguments,
+	int flags)
+{
+    if (!s)
+	return NULL;			// no match
+    FuncDeclaration *f = s->isFuncDeclaration();
+    if (f)
+	f = f->overloadResolve(loc, ethis, arguments);
+    else
+    {	TemplateDeclaration *td = s->isTemplateDeclaration();
+	assert(td);
+	f = td->deduceFunctionTemplate(sc, loc, tiargs, NULL, arguments, flags);
+    }
+    return f;
+}
+
+/********************************
+ * 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
+	{
+	    AggregateDeclaration *thiscd = s->isAggregateDeclaration();
+	    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("isMember:%p isStatic:%d private:%d ctor:%d !Dlinkage:%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
+}
+
+int FuncDeclaration::isOverloadable()
+{
+    return 1;			// functions can be overloaded
+}
+
+int FuncDeclaration::isPure()
+{
+    //printf("FuncDeclaration::isPure() '%s'\n", toChars());
+    assert(type->ty == Tfunction);
+    return ((TypeFunction *)this->type)->ispure;
+}
+
+// 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("\ttoParent2() = '%s'\n", toParent2()->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 &&
+	    ident != Id::cpctor);
+}
+
+int FuncDeclaration::addPostInvariant()
+{
+    AggregateDeclaration *ad = isThis();
+    return (ad &&
+	    ad->inv &&
+	    //ad->isClassDeclaration() &&
+	    global.params.useInvariants &&
+	    (protection == PROTpublic || protection == PROTexport) &&
+	    !naked &&
+	    ident != Id::cpctor);
+}
+
+/**********************************
+ * 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, %p, %d\n", f->toChars(), f->isVirtual(), f->isThis(), 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;
+#if IN_LLVM
+    importprot = PROTundefined;
+#endif
+}
+
+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 = Lexer::uniqueId(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);
+	f->ident = ident;		// keep old identifier
+    }
+    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)
+{
+    AggregateDeclaration *ad;
+    Type *tret;
+
+    //printf("CtorDeclaration::semantic() %s\n", toChars());
+    if (type)
+	return;
+
+    sc = sc->push();
+    sc->stc &= ~STCstatic;		// not a static constructor
+
+    parent = sc->parent;
+    Dsymbol *parent = toParent2();
+    ad = parent->isAggregateDeclaration();
+    if (!ad || parent->isUnionDeclaration())
+    {
+	error("constructors are only for class or struct definitions");
+    fatal();
+	tret = Type::tvoid;
+    }
+    else
+    {	tret = ad->handle;
+	assert(tret);
+    }
+    type = new TypeFunction(arguments, tret, varargs, LINKd);
+#if STRUCTTHISREF
+    if (ad && ad->isStructDeclaration())
+	((TypeFunction *)type)->isref = 1;
+#endif
+    if (!originalType)
+	originalType = type;
+
+    sc->flags |= SCOPEctor;
+    type = type->semantic(loc, sc);
+    sc->flags &= ~SCOPEctor;
+
+    // Append:
+    //	return this;
+    // to the function body
+    if (fbody)
+    {
+	Expression *e = new ThisExp(loc);
+	Statement *s = new ReturnStatement(loc, e);
+	fbody = new CompoundStatement(loc, fbody, s);
+    }
+
+    FuncDeclaration::semantic(sc);
+
+    sc->pop();
+
+    // See if it's the default constructor
+    if (ad && varargs == 0 && Argument::dim(arguments) == 0)
+    {	if (ad->isStructDeclaration())
+	    error("default constructor not allowed for structs");
+	else
+	    ad->defaultCtor = this;
+    }
+}
+
+const char *CtorDeclaration::kind()
+{
+    return "constructor";
+}
+
+char *CtorDeclaration::toChars()
+{
+    return (char *)"this";
+}
+
+int CtorDeclaration::isVirtual()
+{
+    return FALSE;
+}
+
+int CtorDeclaration::addPreInvariant()
+{
+    return FALSE;
+}
+
+int CtorDeclaration::addPostInvariant()
+{
+    return (isThis() && vthis && global.params.useInvariants);
+}
+
+
+void CtorDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    buf->writestring("this");
+    Argument::argsToCBuffer(buf, hgs, arguments, varargs);
+    bodyToCBuffer(buf, hgs);
+}
+
+/********************************* PostBlitDeclaration ****************************/
+
+PostBlitDeclaration::PostBlitDeclaration(Loc loc, Loc endloc)
+    : FuncDeclaration(loc, endloc, Id::_postblit, STCundefined, NULL)
+{
+}
+
+PostBlitDeclaration::PostBlitDeclaration(Loc loc, Loc endloc, Identifier *id)
+    : FuncDeclaration(loc, endloc, id, STCundefined, NULL)
+{
+}
+
+Dsymbol *PostBlitDeclaration::syntaxCopy(Dsymbol *s)
+{
+    assert(!s);
+    PostBlitDeclaration *dd = new PostBlitDeclaration(loc, endloc, ident);
+    return FuncDeclaration::syntaxCopy(dd);
+}
+
+
+void PostBlitDeclaration::semantic(Scope *sc)
+{
+    //printf("PostBlitDeclaration::semantic() %s\n", toChars());
+    //printf("ident: %s, %s, %p, %p\n", ident->toChars(), Id::dtor->toChars(), ident, Id::dtor);
+    parent = sc->parent;
+    Dsymbol *parent = toParent();
+    StructDeclaration *ad = parent->isStructDeclaration();
+    if (!ad)
+    {
+	error("post blits are only for struct/union definitions, not %s %s", parent->kind(), parent->toChars());
+    }
+    else if (ident == Id::_postblit)
+	ad->postblits.push(this);
+    type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd);
+
+    sc = sc->push();
+    sc->stc &= ~STCstatic;		// not static
+    sc->linkage = LINKd;
+
+    FuncDeclaration::semantic(sc);
+
+    sc->pop();
+}
+
+int PostBlitDeclaration::overloadInsert(Dsymbol *s)
+{
+    return FALSE;	// cannot overload postblits
+}
+
+int PostBlitDeclaration::addPreInvariant()
+{
+    return FALSE;
+}
+
+int PostBlitDeclaration::addPostInvariant()
+{
+    return (isThis() && vthis && global.params.useInvariants);
+}
+
+int PostBlitDeclaration::isVirtual()
+{
+    return FALSE;
+}
+
+void PostBlitDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    if (hgs->hdrgen)
+	return;
+    buf->writestring("=this()");
+    bodyToCBuffer(buf, hgs);
+}
+
+/********************************* DtorDeclaration ****************************/
+
+DtorDeclaration::DtorDeclaration(Loc loc, Loc endloc)
+    : FuncDeclaration(loc, endloc, Id::dtor, STCundefined, NULL)
+{
+}
+
+DtorDeclaration::DtorDeclaration(Loc loc, Loc endloc, Identifier *id)
+    : FuncDeclaration(loc, endloc, id, STCundefined, NULL)
+{
+}
+
+Dsymbol *DtorDeclaration::syntaxCopy(Dsymbol *s)
+{
+    assert(!s);
+    DtorDeclaration *dd = new DtorDeclaration(loc, endloc, ident);
+    return FuncDeclaration::syntaxCopy(dd);
+}
+
+
+void DtorDeclaration::semantic(Scope *sc)
+{
+    //printf("DtorDeclaration::semantic() %s\n", toChars());
+    //printf("ident: %s, %s, %p, %p\n", ident->toChars(), Id::dtor->toChars(), ident, Id::dtor);
+    parent = sc->parent;
+    Dsymbol *parent = toParent();
+    AggregateDeclaration *ad = parent->isAggregateDeclaration();
+    if (!ad)
+    {
+	error("destructors are only for class/struct/union definitions, not %s %s", parent->kind(), parent->toChars());
+    fatal();
+    }
+    else if (ident == Id::dtor)
+	ad->dtors.push(this);
+    type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd);
+
+    sc = sc->push();
+    sc->stc &= ~STCstatic;		// not a static destructor
+    sc->linkage = LINKd;
+
+    FuncDeclaration::semantic(sc);
+
+    sc->pop();
+}
+
+int DtorDeclaration::overloadInsert(Dsymbol *s)
+{
+    return FALSE;	// cannot overload destructors
+}
+
+int DtorDeclaration::addPreInvariant()
+{
+    return (isThis() && vthis && global.params.useInvariants);
+}
+
+int DtorDeclaration::addPostInvariant()
+{
+    return FALSE;
+}
+
+const char *DtorDeclaration::kind()
+{	
+    return "destructor";
+}
+
+char *DtorDeclaration::toChars()
+{
+    return (char *)"~this";
+}
+
+int DtorDeclaration::isVirtual()
+{
+    /* This should be FALSE so that dtor's don't get put into the vtbl[],
+     * but doing so will require recompiling everything.
+     */
+#if BREAKABI
+    return FALSE;
+#else
+    return FuncDeclaration::isVirtual();
+#endif
+}
+
+void DtorDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    if (hgs->hdrgen)
+	return;
+    buf->writestring("~this()");
+    bodyToCBuffer(buf, hgs);
+}
+
+/********************************* StaticCtorDeclaration ****************************/
+
+StaticCtorDeclaration::StaticCtorDeclaration(Loc loc, Loc endloc)
+    : FuncDeclaration(loc, endloc,
+      Identifier::generateId("_staticCtor"), STCstatic, NULL)
+{
+}
+
+Dsymbol *StaticCtorDeclaration::syntaxCopy(Dsymbol *s)
+{
+    StaticCtorDeclaration *scd;
+
+    assert(!s);
+    scd = new StaticCtorDeclaration(loc, endloc);
+    return FuncDeclaration::syntaxCopy(scd);
+}
+
+
+void StaticCtorDeclaration::semantic(Scope *sc)
+{
+    //printf("StaticCtorDeclaration::semantic()\n");
+
+    type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd);
+
+    /* If the static ctor appears within a template instantiation,
+     * it could get called multiple times by the module constructors
+     * for different modules. Thus, protect it with a gate.
+     */
+    if (inTemplateInstance())
+    {
+	/* Add this prefix to the function:
+	 *	static int gate;
+	 *	if (++gate != 1) return;
+	 * Note that this is not thread safe; should not have threads
+	 * during static construction.
+	 */
+	Identifier *id = Lexer::idPool("__gate");
+	VarDeclaration *v = new VarDeclaration(0, Type::tint32, id, NULL);
+	v->storage_class = STCstatic;
+	Statements *sa = new Statements();
+	Statement *s = new DeclarationStatement(0, v);
+	sa->push(s);
+	Expression *e = new IdentifierExp(0, id);
+	e = new AddAssignExp(0, e, new IntegerExp(1));
+	e = new EqualExp(TOKnotequal, 0, e, new IntegerExp(1));
+	s = new IfStatement(0, NULL, e, new ReturnStatement(0, NULL), NULL);
+	sa->push(s);
+	if (fbody)
+	    sa->push(fbody);
+	fbody = new CompoundStatement(0, sa);
+    }
+
+    FuncDeclaration::semantic(sc);
+
+    // We're going to need ModuleInfo
+    Module *m = getModule();
+    if (!m)
+	m = sc->module;
+    if (m)
+    {	m->needmoduleinfo = 1;
+#ifdef IN_GCC
+	m->strictlyneedmoduleinfo = 1;
+#endif
+    }
+}
+
+AggregateDeclaration *StaticCtorDeclaration::isThis()
+{
+    return NULL;
+}
+
+int StaticCtorDeclaration::isStaticConstructor()
+{
+    return TRUE;
+}
+
+int StaticCtorDeclaration::isVirtual()
+{
+    return FALSE;
+}
+
+int StaticCtorDeclaration::addPreInvariant()
+{
+    return FALSE;
+}
+
+int StaticCtorDeclaration::addPostInvariant()
+{
+    return FALSE;
+}
+
+void StaticCtorDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    if (hgs->hdrgen)
+    {	buf->writestring("static this();\n");
+	return;
+    }
+    buf->writestring("static this()");
+    bodyToCBuffer(buf, hgs);
+}
+
+/********************************* StaticDtorDeclaration ****************************/
+
+StaticDtorDeclaration::StaticDtorDeclaration(Loc loc, Loc endloc)
+    : FuncDeclaration(loc, endloc,
+      Identifier::generateId("_staticDtor"), STCstatic, NULL)
+{
+    vgate = NULL;
+}
+
+Dsymbol *StaticDtorDeclaration::syntaxCopy(Dsymbol *s)
+{
+    StaticDtorDeclaration *sdd;
+
+    assert(!s);
+    sdd = new StaticDtorDeclaration(loc, endloc);
+    return FuncDeclaration::syntaxCopy(sdd);
+}
+
+
+void StaticDtorDeclaration::semantic(Scope *sc)
+{
+    ClassDeclaration *cd;
+    Type *tret;
+
+    cd = sc->scopesym->isClassDeclaration();
+    if (!cd)
+    {
+    }
+    type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd);
+
+    /* If the static ctor appears within a template instantiation,
+     * it could get called multiple times by the module constructors
+     * for different modules. Thus, protect it with a gate.
+     */
+    if (inTemplateInstance())
+    {
+	/* Add this prefix to the function:
+	 *	static int gate;
+	 *	if (--gate != 0) return;
+	 * Increment gate during constructor execution.
+	 * Note that this is not thread safe; should not have threads
+	 * during static destruction.
+	 */
+	Identifier *id = Lexer::idPool("__gate");
+	VarDeclaration *v = new VarDeclaration(0, Type::tint32, id, NULL);
+	v->storage_class = STCstatic;
+	Statements *sa = new Statements();
+	Statement *s = new DeclarationStatement(0, v);
+	sa->push(s);
+	Expression *e = new IdentifierExp(0, id);
+	e = new AddAssignExp(0, e, new IntegerExp((uint64_t)-1));
+	e = new EqualExp(TOKnotequal, 0, e, new IntegerExp(0));
+	s = new IfStatement(0, NULL, e, new ReturnStatement(0, NULL), NULL);
+	sa->push(s);
+	if (fbody)
+	    sa->push(fbody);
+	fbody = new CompoundStatement(0, sa);
+	vgate = v;
+    }
+
+    FuncDeclaration::semantic(sc);
+
+    // We're going to need ModuleInfo
+    Module *m = getModule();
+    if (!m)
+	m = sc->module;
+    if (m)
+    {	m->needmoduleinfo = 1;
+#ifdef IN_GCC
+	m->strictlyneedmoduleinfo = 1;
+#endif
+    }
+}
+
+AggregateDeclaration *StaticDtorDeclaration::isThis()
+{
+    return NULL;
+}
+
+int StaticDtorDeclaration::isStaticDestructor()
+{
+    return TRUE;
+}
+
+int StaticDtorDeclaration::isVirtual()
+{
+    return FALSE;
+}
+
+int StaticDtorDeclaration::addPreInvariant()
+{
+    return FALSE;
+}
+
+int StaticDtorDeclaration::addPostInvariant()
+{
+    return FALSE;
+}
+
+void StaticDtorDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    if (hgs->hdrgen)
+	return;
+    buf->writestring("static ~this()");
+    bodyToCBuffer(buf, hgs);
+}
+
+/********************************* InvariantDeclaration ****************************/
+
+InvariantDeclaration::InvariantDeclaration(Loc loc, Loc endloc)
+    : FuncDeclaration(loc, endloc, Id::classInvariant, STCundefined, NULL)
+{
+}
+
+Dsymbol *InvariantDeclaration::syntaxCopy(Dsymbol *s)
+{
+    InvariantDeclaration *id;
+
+    assert(!s);
+    id = new InvariantDeclaration(loc, endloc);
+    FuncDeclaration::syntaxCopy(id);
+    return id;
+}
+
+
+void InvariantDeclaration::semantic(Scope *sc)
+{
+    AggregateDeclaration *ad;
+    Type *tret;
+
+    parent = sc->parent;
+    Dsymbol *parent = toParent();
+    ad = parent->isAggregateDeclaration();
+    if (!ad)
+    {
+	error("invariants are only for struct/union/class definitions");
+	return;
+    }
+    else if (ad->inv && ad->inv != this)
+    {
+	error("more than one invariant for %s", ad->toChars());
+    }
+    ad->inv = this;
+    type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd);
+
+    sc = sc->push();
+    sc->stc &= ~STCstatic;		// not a static invariant
+    sc->incontract++;
+    sc->linkage = LINKd;
+
+    FuncDeclaration::semantic(sc);
+
+    sc->pop();
+}
+
+int InvariantDeclaration::isVirtual()
+{
+    return FALSE;
+}
+
+int InvariantDeclaration::addPreInvariant()
+{
+    return FALSE;
+}
+
+int InvariantDeclaration::addPostInvariant()
+{
+    return FALSE;
+}
+
+void InvariantDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    if (hgs->hdrgen)
+	return;
+    buf->writestring("invariant");
+    bodyToCBuffer(buf, hgs);
+}
+
+
+/********************************* UnitTestDeclaration ****************************/
+
+/*******************************
+ * Generate unique unittest function Id so we can have multiple
+ * instances per module.
+ */
+
+static Identifier *unitTestId()
+{
+    return Lexer::uniqueId("__unittest");
+}
+
+UnitTestDeclaration::UnitTestDeclaration(Loc loc, Loc endloc)
+    : FuncDeclaration(loc, endloc, unitTestId(), STCundefined, NULL)
+{
+}
+
+Dsymbol *UnitTestDeclaration::syntaxCopy(Dsymbol *s)
+{
+    UnitTestDeclaration *utd;
+
+    assert(!s);
+    utd = new UnitTestDeclaration(loc, endloc);
+    return FuncDeclaration::syntaxCopy(utd);
+}
+
+
+void UnitTestDeclaration::semantic(Scope *sc)
+{
+    if (global.params.useUnitTests)
+    {
+	type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd);
+	Scope *sc2 = sc->push();
+	sc2->linkage = LINKd;
+	FuncDeclaration::semantic(sc2);
+	sc2->pop();
+    }
+
+    // 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/dmd2/gnuc.c	Mon Jun 01 01:28:18 2009 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,55 +0,0 @@
-
-// Put functions in here missing from gnu C
-
-#include "gnuc.h"
-
-int memicmp(const char *s1, const char *s2, int n)
-{
-    int result = 0;
-
-    for (int i = 0; i < n; i++)
-    {	char c1 = s1[i];
-	char c2 = s2[i];
-
-	result = c1 - c2;
-	if (result)
-	{
-	    if ('A' <= c1 && c1 <= 'Z')
-		c1 += 'a' - 'A';
-	    if ('A' <= c2 && c2 <= 'Z')
-		c2 += 'a' - 'A';
-	    result = c1 - c2;
-	    if (result)
-		break;
-	}
-    }
-    return result;
-}
-
-int stricmp(const char *s1, const char *s2)
-{
-    int result = 0;
-
-    for (;;)
-    {	char c1 = *s1;
-	char c2 = *s2;
-
-	result = c1 - c2;
-	if (result)
-	{
-	    if ('A' <= c1 && c1 <= 'Z')
-		c1 += 'a' - 'A';
-	    if ('A' <= c2 && c2 <= 'Z')
-		c2 += 'a' - 'A';
-	    result = c1 - c2;
-	    if (result)
-		break;
-	}
-	if (!c1)
-	    break;
-	s1++;
-	s2++;
-    }
-    return result;
-}
-
--- a/dmd2/gnuc.h	Mon Jun 01 01:28:18 2009 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,8 +0,0 @@
-
-#ifndef _GNUC_H
-#define _GNUC_H 1
-
-int memicmp(const char *s1, const char *s2, int n);
-int stricmp(const char *s1, const char *s2);
-
-#endif
--- a/dmd2/hdrgen.c	Mon Jun 01 01:28:18 2009 +0200
+++ b/dmd2/hdrgen.c	Mon Jun 01 19:02:20 2009 +0100
@@ -24,17 +24,7 @@
 #include <complex.h>
 #endif
 
-#if IN_GCC || IN_LLVM
-#include "mem.h"
-#else
-#if _WIN32
-#include "..\root\mem.h"
-#elif POSIX
-#include "../root/mem.h"
-#else
-#error "fix this"
-#endif
-#endif
+#include "rmem.h"
 
 #include "id.h"
 #include "init.h"
--- a/dmd2/html.c	Mon Jun 01 01:28:18 2009 +0200
+++ b/dmd2/html.c	Mon Jun 01 19:02:20 2009 +0100
@@ -1,5 +1,5 @@
 
-// Copyright (c) 1999-2006 by Digital Mars
+// Copyright (c) 1999-2009 by Digital Mars
 // All Rights Reserved
 // written by Walter Bright
 // http://www.digitalmars.com
@@ -107,10 +107,10 @@
 		{   // Comments start with <!--
 		    scanComment();
 		}
-  		else if(p[1] == '!' && isCDATAStart())
-  		{
-  		    scanCDATA();
-  		}
+		else if(p[1] == '!' && isCDATAStart())
+		{
+		    scanCDATA();
+		}
 		else if (p[1] == '/' && istagstart(*skipWhite(p + 2)))
 		    skipTag();
 		else if (istagstart(*skipWhite(p + 1)))
@@ -550,6 +550,7 @@
     }
 }
 
+
 /********************************************
  * Convert an HTML character entity into a character.
  * Forms are:
@@ -716,3 +717,4 @@
     return 0;
 }
 
+
--- a/dmd2/html.h	Mon Jun 01 01:28:18 2009 +0200
+++ b/dmd2/html.h	Mon Jun 01 19:02:20 2009 +0100
@@ -1,9 +1,8 @@
 
-// Compiler implementation of the D programming language
 // Copyright (c) 1999-2006 by Digital Mars
 // All Rights Reserved
 // written by Walter Bright
-// http://www.digitalmars.com
+// 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.
@@ -27,7 +26,7 @@
 
     Html(const char *sourcename, unsigned char *base, unsigned length);
 
-    void error(const char *format, ...);
+    void error(const char *format, ...) IS_PRINTF(2);
     void extractCode(OutBuffer *buf);
     void skipTag();
     void skipString();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd2/id.c	Mon Jun 01 19:02:20 2009 +0100
@@ -0,0 +1,463 @@
+// File generated by idgen.c
+#include "id.h"
+#include "identifier.h"
+#include "lexer.h"
+Identifier *Id::IUnknown;
+Identifier *Id::Object;
+Identifier *Id::object;
+Identifier *Id::max;
+Identifier *Id::min;
+Identifier *Id::This;
+Identifier *Id::ctor;
+Identifier *Id::dtor;
+Identifier *Id::cpctor;
+Identifier *Id::_postblit;
+Identifier *Id::classInvariant;
+Identifier *Id::unitTest;
+Identifier *Id::init;
+Identifier *Id::size;
+Identifier *Id::__sizeof;
+Identifier *Id::alignof;
+Identifier *Id::mangleof;
+Identifier *Id::stringof;
+Identifier *Id::tupleof;
+Identifier *Id::length;
+Identifier *Id::remove;
+Identifier *Id::ptr;
+Identifier *Id::funcptr;
+Identifier *Id::dollar;
+Identifier *Id::offset;
+Identifier *Id::offsetof;
+Identifier *Id::ModuleInfo;
+Identifier *Id::ClassInfo;
+Identifier *Id::classinfo;
+Identifier *Id::typeinfo;
+Identifier *Id::outer;
+Identifier *Id::Exception;
+Identifier *Id::Throwable;
+Identifier *Id::withSym;
+Identifier *Id::result;
+Identifier *Id::returnLabel;
+Identifier *Id::delegate;
+Identifier *Id::line;
+Identifier *Id::empty;
+Identifier *Id::p;
+Identifier *Id::coverage;
+Identifier *Id::__vptr;
+Identifier *Id::__monitor;
+Identifier *Id::system;
+Identifier *Id::TypeInfo;
+Identifier *Id::TypeInfo_Class;
+Identifier *Id::TypeInfo_Interface;
+Identifier *Id::TypeInfo_Struct;
+Identifier *Id::TypeInfo_Enum;
+Identifier *Id::TypeInfo_Typedef;
+Identifier *Id::TypeInfo_Pointer;
+Identifier *Id::TypeInfo_Array;
+Identifier *Id::TypeInfo_StaticArray;
+Identifier *Id::TypeInfo_AssociativeArray;
+Identifier *Id::TypeInfo_Function;
+Identifier *Id::TypeInfo_Delegate;
+Identifier *Id::TypeInfo_Tuple;
+Identifier *Id::TypeInfo_Const;
+Identifier *Id::TypeInfo_Invariant;
+Identifier *Id::TypeInfo_Shared;
+Identifier *Id::elements;
+Identifier *Id::_arguments_typeinfo;
+Identifier *Id::_arguments;
+Identifier *Id::_argptr;
+Identifier *Id::_match;
+Identifier *Id::destroy;
+Identifier *Id::postblit;
+Identifier *Id::LINE;
+Identifier *Id::FILE;
+Identifier *Id::DATE;
+Identifier *Id::TIME;
+Identifier *Id::TIMESTAMP;
+Identifier *Id::VENDOR;
+Identifier *Id::VERSIONX;
+Identifier *Id::EOFX;
+Identifier *Id::nan;
+Identifier *Id::infinity;
+Identifier *Id::dig;
+Identifier *Id::epsilon;
+Identifier *Id::mant_dig;
+Identifier *Id::max_10_exp;
+Identifier *Id::max_exp;
+Identifier *Id::min_10_exp;
+Identifier *Id::min_exp;
+Identifier *Id::re;
+Identifier *Id::im;
+Identifier *Id::C;
+Identifier *Id::D;
+Identifier *Id::Windows;
+Identifier *Id::Pascal;
+Identifier *Id::System;
+Identifier *Id::exit;
+Identifier *Id::success;
+Identifier *Id::failure;
+Identifier *Id::keys;
+Identifier *Id::values;
+Identifier *Id::rehash;
+Identifier *Id::sort;
+Identifier *Id::reverse;
+Identifier *Id::dup;
+Identifier *Id::idup;
+Identifier *Id::___out;
+Identifier *Id::___in;
+Identifier *Id::__int;
+Identifier *Id::__dollar;
+Identifier *Id::__LOCAL_SIZE;
+Identifier *Id::uadd;
+Identifier *Id::neg;
+Identifier *Id::com;
+Identifier *Id::add;
+Identifier *Id::add_r;
+Identifier *Id::sub;
+Identifier *Id::sub_r;
+Identifier *Id::mul;
+Identifier *Id::mul_r;
+Identifier *Id::div;
+Identifier *Id::div_r;
+Identifier *Id::mod;
+Identifier *Id::mod_r;
+Identifier *Id::eq;
+Identifier *Id::cmp;
+Identifier *Id::iand;
+Identifier *Id::iand_r;
+Identifier *Id::ior;
+Identifier *Id::ior_r;
+Identifier *Id::ixor;
+Identifier *Id::ixor_r;
+Identifier *Id::shl;
+Identifier *Id::shl_r;
+Identifier *Id::shr;
+Identifier *Id::shr_r;
+Identifier *Id::ushr;
+Identifier *Id::ushr_r;
+Identifier *Id::cat;
+Identifier *Id::cat_r;
+Identifier *Id::assign;
+Identifier *Id::addass;
+Identifier *Id::subass;
+Identifier *Id::mulass;
+Identifier *Id::divass;
+Identifier *Id::modass;
+Identifier *Id::andass;
+Identifier *Id::orass;
+Identifier *Id::xorass;
+Identifier *Id::shlass;
+Identifier *Id::shrass;
+Identifier *Id::ushrass;
+Identifier *Id::catass;
+Identifier *Id::postinc;
+Identifier *Id::postdec;
+Identifier *Id::index;
+Identifier *Id::indexass;
+Identifier *Id::slice;
+Identifier *Id::sliceass;
+Identifier *Id::call;
+Identifier *Id::cast;
+Identifier *Id::match;
+Identifier *Id::next;
+Identifier *Id::opIn;
+Identifier *Id::opIn_r;
+Identifier *Id::opStar;
+Identifier *Id::opDot;
+Identifier *Id::opImplicitCast;
+Identifier *Id::classNew;
+Identifier *Id::classDelete;
+Identifier *Id::apply;
+Identifier *Id::applyReverse;
+Identifier *Id::Fempty;
+Identifier *Id::Fhead;
+Identifier *Id::Ftoe;
+Identifier *Id::Fnext;
+Identifier *Id::Fretreat;
+Identifier *Id::adDup;
+Identifier *Id::adReverse;
+Identifier *Id::aaLen;
+Identifier *Id::aaKeys;
+Identifier *Id::aaValues;
+Identifier *Id::aaRehash;
+Identifier *Id::GNU_asm;
+Identifier *Id::lib;
+Identifier *Id::msg;
+Identifier *Id::startaddress;
+Identifier *Id::intrinsic;
+Identifier *Id::va_intrinsic;
+Identifier *Id::no_typeinfo;
+Identifier *Id::no_moduleinfo;
+Identifier *Id::Alloca;
+Identifier *Id::vastart;
+Identifier *Id::vacopy;
+Identifier *Id::vaend;
+Identifier *Id::vaarg;
+Identifier *Id::ldc;
+Identifier *Id::allow_inline;
+Identifier *Id::llvm_inline_asm;
+Identifier *Id::tohash;
+Identifier *Id::tostring;
+Identifier *Id::getmembers;
+Identifier *Id::main;
+Identifier *Id::WinMain;
+Identifier *Id::DllMain;
+Identifier *Id::tls_get_addr;
+Identifier *Id::std;
+Identifier *Id::math;
+Identifier *Id::sin;
+Identifier *Id::cos;
+Identifier *Id::tan;
+Identifier *Id::_sqrt;
+Identifier *Id::fabs;
+Identifier *Id::isAbstractClass;
+Identifier *Id::isArithmetic;
+Identifier *Id::isAssociativeArray;
+Identifier *Id::isFinalClass;
+Identifier *Id::isFloating;
+Identifier *Id::isIntegral;
+Identifier *Id::isScalar;
+Identifier *Id::isStaticArray;
+Identifier *Id::isUnsigned;
+Identifier *Id::isVirtualFunction;
+Identifier *Id::isAbstractFunction;
+Identifier *Id::isFinalFunction;
+Identifier *Id::hasMember;
+Identifier *Id::getMember;
+Identifier *Id::getVirtualFunctions;
+Identifier *Id::classInstanceSize;
+Identifier *Id::allMembers;
+Identifier *Id::derivedMembers;
+Identifier *Id::isSame;
+Identifier *Id::compiles;
+void Id::initialize()
+{
+    IUnknown = Lexer::idPool("IUnknown");
+    Object = Lexer::idPool("Object");
+    object = Lexer::idPool("object");
+    max = Lexer::idPool("max");
+    min = Lexer::idPool("min");
+    This = Lexer::idPool("this");
+    ctor = Lexer::idPool("__ctor");
+    dtor = Lexer::idPool("__dtor");
+    cpctor = Lexer::idPool("__cpctor");
+    _postblit = Lexer::idPool("__postblit");
+    classInvariant = Lexer::idPool("__invariant");
+    unitTest = Lexer::idPool("__unitTest");
+    init = Lexer::idPool("init");
+    size = Lexer::idPool("size");
+    __sizeof = Lexer::idPool("sizeof");
+    alignof = Lexer::idPool("alignof");
+    mangleof = Lexer::idPool("mangleof");
+    stringof = Lexer::idPool("stringof");
+    tupleof = Lexer::idPool("tupleof");
+    length = Lexer::idPool("length");
+    remove = Lexer::idPool("remove");
+    ptr = Lexer::idPool("ptr");
+    funcptr = Lexer::idPool("funcptr");
+    dollar = Lexer::idPool("__dollar");
+    offset = Lexer::idPool("offset");
+    offsetof = Lexer::idPool("offsetof");
+    ModuleInfo = Lexer::idPool("ModuleInfo");
+    ClassInfo = Lexer::idPool("ClassInfo");
+    classinfo = Lexer::idPool("classinfo");
+    typeinfo = Lexer::idPool("typeinfo");
+    outer = Lexer::idPool("outer");
+    Exception = Lexer::idPool("Exception");
+    Throwable = Lexer::idPool("Throwable");
+    withSym = Lexer::idPool("__withSym");
+    result = Lexer::idPool("__result");
+    returnLabel = Lexer::idPool("__returnLabel");
+    delegate = Lexer::idPool("delegate");
+    line = Lexer::idPool("line");
+    empty = Lexer::idPool("");
+    p = Lexer::idPool("p");
+    coverage = Lexer::idPool("__coverage");
+    __vptr = Lexer::idPool("__vptr");
+    __monitor = Lexer::idPool("__monitor");
+    system = Lexer::idPool("system");
+    TypeInfo = Lexer::idPool("TypeInfo");
+    TypeInfo_Class = Lexer::idPool("TypeInfo_Class");
+    TypeInfo_Interface = Lexer::idPool("TypeInfo_Interface");
+    TypeInfo_Struct = Lexer::idPool("TypeInfo_Struct");
+    TypeInfo_Enum = Lexer::idPool("TypeInfo_Enum");
+    TypeInfo_Typedef = Lexer::idPool("TypeInfo_Typedef");
+    TypeInfo_Pointer = Lexer::idPool("TypeInfo_Pointer");
+    TypeInfo_Array = Lexer::idPool("TypeInfo_Array");
+    TypeInfo_StaticArray = Lexer::idPool("TypeInfo_StaticArray");
+    TypeInfo_AssociativeArray = Lexer::idPool("TypeInfo_AssociativeArray");
+    TypeInfo_Function = Lexer::idPool("TypeInfo_Function");
+    TypeInfo_Delegate = Lexer::idPool("TypeInfo_Delegate");
+    TypeInfo_Tuple = Lexer::idPool("TypeInfo_Tuple");
+    TypeInfo_Const = Lexer::idPool("TypeInfo_Const");
+    TypeInfo_Invariant = Lexer::idPool("TypeInfo_Invariant");
+    TypeInfo_Shared = Lexer::idPool("TypeInfo_Shared");
+    elements = Lexer::idPool("elements");
+    _arguments_typeinfo = Lexer::idPool("_arguments_typeinfo");
+    _arguments = Lexer::idPool("_arguments");
+    _argptr = Lexer::idPool("_argptr");
+    _match = Lexer::idPool("_match");
+    destroy = Lexer::idPool("destroy");
+    postblit = Lexer::idPool("postblit");
+    LINE = Lexer::idPool("__LINE__");
+    FILE = Lexer::idPool("__FILE__");
+    DATE = Lexer::idPool("__DATE__");
+    TIME = Lexer::idPool("__TIME__");
+    TIMESTAMP = Lexer::idPool("__TIMESTAMP__");
+    VENDOR = Lexer::idPool("__VENDOR__");
+    VERSIONX = Lexer::idPool("__VERSION__");
+    EOFX = Lexer::idPool("__EOF__");
+    nan = Lexer::idPool("nan");
+    infinity = Lexer::idPool("infinity");
+    dig = Lexer::idPool("dig");
+    epsilon = Lexer::idPool("epsilon");
+    mant_dig = Lexer::idPool("mant_dig");
+    max_10_exp = Lexer::idPool("max_10_exp");
+    max_exp = Lexer::idPool("max_exp");
+    min_10_exp = Lexer::idPool("min_10_exp");
+    min_exp = Lexer::idPool("min_exp");
+    re = Lexer::idPool("re");
+    im = Lexer::idPool("im");
+    C = Lexer::idPool("C");
+    D = Lexer::idPool("D");
+    Windows = Lexer::idPool("Windows");
+    Pascal = Lexer::idPool("Pascal");
+    System = Lexer::idPool("System");
+    exit = Lexer::idPool("exit");
+    success = Lexer::idPool("success");
+    failure = Lexer::idPool("failure");
+    keys = Lexer::idPool("keys");
+    values = Lexer::idPool("values");
+    rehash = Lexer::idPool("rehash");
+    sort = Lexer::idPool("sort");
+    reverse = Lexer::idPool("reverse");
+    dup = Lexer::idPool("dup");
+    idup = Lexer::idPool("idup");
+    ___out = Lexer::idPool("out");
+    ___in = Lexer::idPool("in");
+    __int = Lexer::idPool("int");
+    __dollar = Lexer::idPool("$");
+    __LOCAL_SIZE = Lexer::idPool("__LOCAL_SIZE");
+    uadd = Lexer::idPool("opPos");
+    neg = Lexer::idPool("opNeg");
+    com = Lexer::idPool("opCom");
+    add = Lexer::idPool("opAdd");
+    add_r = Lexer::idPool("opAdd_r");
+    sub = Lexer::idPool("opSub");
+    sub_r = Lexer::idPool("opSub_r");
+    mul = Lexer::idPool("opMul");
+    mul_r = Lexer::idPool("opMul_r");
+    div = Lexer::idPool("opDiv");
+    div_r = Lexer::idPool("opDiv_r");
+    mod = Lexer::idPool("opMod");
+    mod_r = Lexer::idPool("opMod_r");
+    eq = Lexer::idPool("opEquals");
+    cmp = Lexer::idPool("opCmp");
+    iand = Lexer::idPool("opAnd");
+    iand_r = Lexer::idPool("opAnd_r");
+    ior = Lexer::idPool("opOr");
+    ior_r = Lexer::idPool("opOr_r");
+    ixor = Lexer::idPool("opXor");
+    ixor_r = Lexer::idPool("opXor_r");
+    shl = Lexer::idPool("opShl");
+    shl_r = Lexer::idPool("opShl_r");
+    shr = Lexer::idPool("opShr");
+    shr_r = Lexer::idPool("opShr_r");
+    ushr = Lexer::idPool("opUShr");
+    ushr_r = Lexer::idPool("opUShr_r");
+    cat = Lexer::idPool("opCat");
+    cat_r = Lexer::idPool("opCat_r");
+    assign = Lexer::idPool("opAssign");
+    addass = Lexer::idPool("opAddAssign");
+    subass = Lexer::idPool("opSubAssign");
+    mulass = Lexer::idPool("opMulAssign");
+    divass = Lexer::idPool("opDivAssign");
+    modass = Lexer::idPool("opModAssign");
+    andass = Lexer::idPool("opAndAssign");
+    orass = Lexer::idPool("opOrAssign");
+    xorass = Lexer::idPool("opXorAssign");
+    shlass = Lexer::idPool("opShlAssign");
+    shrass = Lexer::idPool("opShrAssign");
+    ushrass = Lexer::idPool("opUShrAssign");
+    catass = Lexer::idPool("opCatAssign");
+    postinc = Lexer::idPool("opPostInc");
+    postdec = Lexer::idPool("opPostDec");
+    index = Lexer::idPool("opIndex");
+    indexass = Lexer::idPool("opIndexAssign");
+    slice = Lexer::idPool("opSlice");
+    sliceass = Lexer::idPool("opSliceAssign");
+    call = Lexer::idPool("opCall");
+    cast = Lexer::idPool("opCast");
+    match = Lexer::idPool("opMatch");
+    next = Lexer::idPool("opNext");
+    opIn = Lexer::idPool("opIn");
+    opIn_r = Lexer::idPool("opIn_r");
+    opStar = Lexer::idPool("opStar");
+    opDot = Lexer::idPool("opDot");
+    opImplicitCast = Lexer::idPool("opImplicitCast");
+    classNew = Lexer::idPool("new");
+    classDelete = Lexer::idPool("delete");
+    apply = Lexer::idPool("opApply");
+    applyReverse = Lexer::idPool("opApplyReverse");
+    Fempty = Lexer::idPool("empty");
+    Fhead = Lexer::idPool("front");
+    Ftoe = Lexer::idPool("back");
+    Fnext = Lexer::idPool("popFront");
+    Fretreat = Lexer::idPool("popBack");
+    adDup = Lexer::idPool("_adDupT");
+    adReverse = Lexer::idPool("_adReverse");
+    aaLen = Lexer::idPool("_aaLen");
+    aaKeys = Lexer::idPool("_aaKeys");
+    aaValues = Lexer::idPool("_aaValues");
+    aaRehash = Lexer::idPool("_aaRehash");
+    GNU_asm = Lexer::idPool("GNU_asm");
+    lib = Lexer::idPool("lib");
+    msg = Lexer::idPool("msg");
+    startaddress = Lexer::idPool("startaddress");
+    intrinsic = Lexer::idPool("intrinsic");
+    va_intrinsic = Lexer::idPool("va_intrinsic");
+    no_typeinfo = Lexer::idPool("no_typeinfo");
+    no_moduleinfo = Lexer::idPool("no_moduleinfo");
+    Alloca = Lexer::idPool("alloca");
+    vastart = Lexer::idPool("va_start");
+    vacopy = Lexer::idPool("va_copy");
+    vaend = Lexer::idPool("va_end");
+    vaarg = Lexer::idPool("va_arg");
+    ldc = Lexer::idPool("ldc");
+    allow_inline = Lexer::idPool("allow_inline");
+    llvm_inline_asm = Lexer::idPool("llvm_inline_asm");
+    tohash = Lexer::idPool("toHash");
+    tostring = Lexer::idPool("toString");
+    getmembers = Lexer::idPool("getMembers");
+    main = Lexer::idPool("main");
+    WinMain = Lexer::idPool("WinMain");
+    DllMain = Lexer::idPool("DllMain");
+    tls_get_addr = Lexer::idPool("___tls_get_addr");
+    std = Lexer::idPool("std");
+    math = Lexer::idPool("math");
+    sin = Lexer::idPool("sin");
+    cos = Lexer::idPool("cos");
+    tan = Lexer::idPool("tan");
+    _sqrt = Lexer::idPool("sqrt");
+    fabs = Lexer::idPool("fabs");
+    isAbstractClass = Lexer::idPool("isAbstractClass");
+    isArithmetic = Lexer::idPool("isArithmetic");
+    isAssociativeArray = Lexer::idPool("isAssociativeArray");
+    isFinalClass = Lexer::idPool("isFinalClass");
+    isFloating = Lexer::idPool("isFloating");
+    isIntegral = Lexer::idPool("isIntegral");
+    isScalar = Lexer::idPool("isScalar");
+    isStaticArray = Lexer::idPool("isStaticArray");
+    isUnsigned = Lexer::idPool("isUnsigned");
+    isVirtualFunction = Lexer::idPool("isVirtualFunction");
+    isAbstractFunction = Lexer::idPool("isAbstractFunction");
+    isFinalFunction = Lexer::idPool("isFinalFunction");
+    hasMember = Lexer::idPool("hasMember");
+    getMember = Lexer::idPool("getMember");
+    getVirtualFunctions = Lexer::idPool("getVirtualFunctions");
+    classInstanceSize = Lexer::idPool("classInstanceSize");
+    allMembers = Lexer::idPool("allMembers");
+    derivedMembers = Lexer::idPool("derivedMembers");
+    isSame = Lexer::idPool("isSame");
+    compiles = Lexer::idPool("compiles");
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd2/id.h	Mon Jun 01 19:02:20 2009 +0100
@@ -0,0 +1,237 @@
+// File generated by idgen.c
+#ifndef DMD_ID_H
+#define DMD_ID_H 1
+struct Identifier;
+struct Id
+{
+    static Identifier *IUnknown;
+    static Identifier *Object;
+    static Identifier *object;
+    static Identifier *max;
+    static Identifier *min;
+    static Identifier *This;
+    static Identifier *ctor;
+    static Identifier *dtor;
+    static Identifier *cpctor;
+    static Identifier *_postblit;
+    static Identifier *classInvariant;
+    static Identifier *unitTest;
+    static Identifier *init;
+    static Identifier *size;
+    static Identifier *__sizeof;
+    static Identifier *alignof;
+    static Identifier *mangleof;
+    static Identifier *stringof;
+    static Identifier *tupleof;
+    static Identifier *length;
+    static Identifier *remove;
+    static Identifier *ptr;
+    static Identifier *funcptr;
+    static Identifier *dollar;
+    static Identifier *offset;
+    static Identifier *offsetof;
+    static Identifier *ModuleInfo;
+    static Identifier *ClassInfo;
+    static Identifier *classinfo;
+    static Identifier *typeinfo;
+    static Identifier *outer;
+    static Identifier *Exception;
+    static Identifier *Throwable;
+    static Identifier *withSym;
+    static Identifier *result;
+    static Identifier *returnLabel;
+    static Identifier *delegate;
+    static Identifier *line;
+    static Identifier *empty;
+    static Identifier *p;
+    static Identifier *coverage;
+    static Identifier *__vptr;
+    static Identifier *__monitor;
+    static Identifier *system;
+    static Identifier *TypeInfo;
+    static Identifier *TypeInfo_Class;
+    static Identifier *TypeInfo_Interface;
+    static Identifier *TypeInfo_Struct;
+    static Identifier *TypeInfo_Enum;
+    static Identifier *TypeInfo_Typedef;
+    static Identifier *TypeInfo_Pointer;
+    static Identifier *TypeInfo_Array;
+    static Identifier *TypeInfo_StaticArray;
+    static Identifier *TypeInfo_AssociativeArray;
+    static Identifier *TypeInfo_Function;
+    static Identifier *TypeInfo_Delegate;
+    static Identifier *TypeInfo_Tuple;
+    static Identifier *TypeInfo_Const;
+    static Identifier *TypeInfo_Invariant;
+    static Identifier *TypeInfo_Shared;
+    static Identifier *elements;
+    static Identifier *_arguments_typeinfo;
+    static Identifier *_arguments;
+    static Identifier *_argptr;
+    static Identifier *_match;
+    static Identifier *destroy;
+    static Identifier *postblit;
+    static Identifier *LINE;
+    static Identifier *FILE;
+    static Identifier *DATE;
+    static Identifier *TIME;
+    static Identifier *TIMESTAMP;
+    static Identifier *VENDOR;
+    static Identifier *VERSIONX;
+    static Identifier *EOFX;
+    static Identifier *nan;
+    static Identifier *infinity;
+    static Identifier *dig;
+    static Identifier *epsilon;
+    static Identifier *mant_dig;
+    static Identifier *max_10_exp;
+    static Identifier *max_exp;
+    static Identifier *min_10_exp;
+    static Identifier *min_exp;
+    static Identifier *re;
+    static Identifier *im;
+    static Identifier *C;
+    static Identifier *D;
+    static Identifier *Windows;
+    static Identifier *Pascal;
+    static Identifier *System;
+    static Identifier *exit;
+    static Identifier *success;
+    static Identifier *failure;
+    static Identifier *keys;
+    static Identifier *values;
+    static Identifier *rehash;
+    static Identifier *sort;
+    static Identifier *reverse;
+    static Identifier *dup;
+    static Identifier *idup;
+    static Identifier *___out;
+    static Identifier *___in;
+    static Identifier *__int;
+    static Identifier *__dollar;
+    static Identifier *__LOCAL_SIZE;
+    static Identifier *uadd;
+    static Identifier *neg;
+    static Identifier *com;
+    static Identifier *add;
+    static Identifier *add_r;
+    static Identifier *sub;
+    static Identifier *sub_r;
+    static Identifier *mul;
+    static Identifier *mul_r;
+    static Identifier *div;
+    static Identifier *div_r;
+    static Identifier *mod;
+    static Identifier *mod_r;
+    static Identifier *eq;
+    static Identifier *cmp;
+    static Identifier *iand;
+    static Identifier *iand_r;
+    static Identifier *ior;
+    static Identifier *ior_r;
+    static Identifier *ixor;
+    static Identifier *ixor_r;
+    static Identifier *shl;
+    static Identifier *shl_r;
+    static Identifier *shr;
+    static Identifier *shr_r;
+    static Identifier *ushr;
+    static Identifier *ushr_r;
+    static Identifier *cat;
+    static Identifier *cat_r;
+    static Identifier *assign;
+    static Identifier *addass;
+    static Identifier *subass;
+    static Identifier *mulass;
+    static Identifier *divass;
+    static Identifier *modass;
+    static Identifier *andass;
+    static Identifier *orass;
+    static Identifier *xorass;
+    static Identifier *shlass;
+    static Identifier *shrass;
+    static Identifier *ushrass;
+    static Identifier *catass;
+    static Identifier *postinc;
+    static Identifier *postdec;
+    static Identifier *index;
+    static Identifier *indexass;
+    static Identifier *slice;
+    static Identifier *sliceass;
+    static Identifier *call;
+    static Identifier *cast;
+    static Identifier *match;
+    static Identifier *next;
+    static Identifier *opIn;
+    static Identifier *opIn_r;
+    static Identifier *opStar;
+    static Identifier *opDot;
+    static Identifier *opImplicitCast;
+    static Identifier *classNew;
+    static Identifier *classDelete;
+    static Identifier *apply;
+    static Identifier *applyReverse;
+    static Identifier *Fempty;
+    static Identifier *Fhead;
+    static Identifier *Ftoe;
+    static Identifier *Fnext;
+    static Identifier *Fretreat;
+    static Identifier *adDup;
+    static Identifier *adReverse;
+    static Identifier *aaLen;
+    static Identifier *aaKeys;
+    static Identifier *aaValues;
+    static Identifier *aaRehash;
+    static Identifier *GNU_asm;
+    static Identifier *lib;
+    static Identifier *msg;
+    static Identifier *startaddress;
+    static Identifier *intrinsic;
+    static Identifier *va_intrinsic;
+    static Identifier *no_typeinfo;
+    static Identifier *no_moduleinfo;
+    static Identifier *Alloca;
+    static Identifier *vastart;
+    static Identifier *vacopy;
+    static Identifier *vaend;
+    static Identifier *vaarg;
+    static Identifier *ldc;
+    static Identifier *allow_inline;
+    static Identifier *llvm_inline_asm;
+    static Identifier *tohash;
+    static Identifier *tostring;
+    static Identifier *getmembers;
+    static Identifier *main;
+    static Identifier *WinMain;
+    static Identifier *DllMain;
+    static Identifier *tls_get_addr;
+    static Identifier *std;
+    static Identifier *math;
+    static Identifier *sin;
+    static Identifier *cos;
+    static Identifier *tan;
+    static Identifier *_sqrt;
+    static Identifier *fabs;
+    static Identifier *isAbstractClass;
+    static Identifier *isArithmetic;
+    static Identifier *isAssociativeArray;
+    static Identifier *isFinalClass;
+    static Identifier *isFloating;
+    static Identifier *isIntegral;
+    static Identifier *isScalar;
+    static Identifier *isStaticArray;
+    static Identifier *isUnsigned;
+    static Identifier *isVirtualFunction;
+    static Identifier *isAbstractFunction;
+    static Identifier *isFinalFunction;
+    static Identifier *hasMember;
+    static Identifier *getMember;
+    static Identifier *getVirtualFunctions;
+    static Identifier *classInstanceSize;
+    static Identifier *allMembers;
+    static Identifier *derivedMembers;
+    static Identifier *isSame;
+    static Identifier *compiles;
+    static void initialize();
+};
+#endif
--- a/dmd2/identifier.c	Mon Jun 01 01:28:18 2009 +0200
+++ b/dmd2/identifier.c	Mon Jun 01 19:02:20 2009 +0100
@@ -1,101 +1,102 @@
-
-// Compiler implementation of the D programming language
-// Copyright (c) 1999-2006 by Digital Mars
-// All Rights Reserved
-// written by Walter Bright
-// http://www.digitalmars.com
-// License for redistribution is by either the Artistic License
-// in artistic.txt, or the GNU General Public License in gnu.txt.
-// See the included readme.txt for details.
-
-#include <stdio.h>
-#include <string.h>
-
-#include "root.h"
-#include "identifier.h"
-#include "mars.h"
-#include "lexer.h"
-#include "id.h"
-
-Identifier::Identifier(const char *string, int value)
-{
-    //printf("Identifier('%s', %d)\n", string, value);
-    this->string = string;
-    this->value = value;
-    this->len = strlen(string);
-}
-
-hash_t Identifier::hashCode()
-{
-    return String::calcHash(string);
-}
-
-int Identifier::equals(Object *o)
-{
-    return this == o || memcmp(string,o->toChars(),len+1) == 0;
-}
-
-int Identifier::compare(Object *o)
-{
-    return memcmp(string, o->toChars(), len + 1);
-}
-
-char *Identifier::toChars()
-{
-    return (char *)string;
-}
-
-const char *Identifier::toHChars2()
-{
-    const char *p = NULL;
-
-    if (this == Id::ctor) p = "this";
-    else if (this == Id::dtor) p = "~this";
-    else if (this == Id::classInvariant) p = "invariant";
-    else if (this == Id::unitTest) p = "unittest";
-    else if (this == Id::dollar) p = "$";
-    else if (this == Id::withSym) p = "with";
-    else if (this == Id::result) p = "result";
-    else if (this == Id::returnLabel) p = "return";
-    else
-    {	p = toChars();
-	if (*p == '_')
-	{
-	    if (memcmp(p, "_staticCtor", 11) == 0)
-		p = "static this";
-	    else if (memcmp(p, "_staticDtor", 11) == 0)
-		p = "static ~this";
-	}
-    }
-
-    return p;
-}
-
-void Identifier::print()
-{
-    fprintf(stdmsg, "%s",string);
-}
-
-int Identifier::dyncast()
-{
-    return DYNCAST_IDENTIFIER;
-}
-
-
-Identifier *Identifier::generateId(const char *prefix)
-{
-    static size_t i;
-
-    return generateId(prefix, ++i);
-}
-
-Identifier *Identifier::generateId(const char *prefix, size_t i)
-{   OutBuffer buf;
-
-    buf.writestring(prefix);
-    buf.printf("%"PRIuSIZE, i);
-
-    char *id = buf.toChars();
-    buf.data = NULL;
-    return Lexer::idPool(id);
-}
+
+// Compiler implementation of the D programming language
+// Copyright (c) 1999-2006 by Digital Mars
+// All Rights Reserved
+// written by Walter Bright
+// http://www.digitalmars.com
+// License for redistribution is by either the Artistic License
+// in artistic.txt, or the GNU General Public License in gnu.txt.
+// See the included readme.txt for details.
+
+#include <stdio.h>
+#include <string.h>
+
+#include "root.h"
+#include "identifier.h"
+#include "mars.h"
+#include "lexer.h"
+#include "id.h"
+
+Identifier::Identifier(const char *string, int value)
+{
+    //printf("Identifier('%s', %d)\n", string, value);
+    this->string = string;
+    this->value = value;
+    this->len = strlen(string);
+}
+
+hash_t Identifier::hashCode()
+{
+    return String::calcHash(string);
+}
+
+int Identifier::equals(Object *o)
+{
+    return this == o || memcmp(string,o->toChars(),len+1) == 0;
+}
+
+int Identifier::compare(Object *o)
+{
+    return memcmp(string, o->toChars(), len + 1);
+}
+
+char *Identifier::toChars()
+{
+    return (char *)string;
+}
+
+const char *Identifier::toHChars2()
+{
+    const char *p = NULL;
+
+    if (this == Id::ctor) p = "this";
+    else if (this == Id::dtor) p = "~this";
+    else if (this == Id::classInvariant) p = "invariant";
+    else if (this == Id::unitTest) p = "unittest";
+    else if (this == Id::dollar) p = "$";
+    else if (this == Id::withSym) p = "with";
+    else if (this == Id::result) p = "result";
+    else if (this == Id::returnLabel) p = "return";
+    else
+    {	p = toChars();
+	if (*p == '_')
+	{
+	    if (memcmp(p, "_staticCtor", 11) == 0)
+		p = "static this";
+	    else if (memcmp(p, "_staticDtor", 11) == 0)
+		p = "static ~this";
+	}
+    }
+
+    return p;
+}
+
+void Identifier::print()
+{
+    fprintf(stdmsg, "%s",string);
+}
+
+int Identifier::dyncast()
+{
+    return DYNCAST_IDENTIFIER;
+}
+
+// BUG: these are redundant with Lexer::uniqueId()
+
+Identifier *Identifier::generateId(const char *prefix)
+{
+    static size_t i;
+
+    return generateId(prefix, ++i);
+}
+
+Identifier *Identifier::generateId(const char *prefix, size_t i)
+{   OutBuffer buf;
+
+    buf.writestring(prefix);
+    buf.printf("%zu", i);
+
+    char *id = buf.toChars();
+    buf.data = NULL;
+    return Lexer::idPool(id);
+}
--- a/dmd2/identifier.h	Mon Jun 01 01:28:18 2009 +0200
+++ b/dmd2/identifier.h	Mon Jun 01 19:02:20 2009 +0100
@@ -17,10 +17,12 @@
 
 #include "root.h"
 
+#if IN_LLVM
 namespace llvm
 {
     class Value;
 }
+#endif
 
 struct Identifier : Object
 {
Binary file dmd2/idgen has changed
--- a/dmd2/idgen.c	Mon Jun 01 01:28:18 2009 +0200
+++ b/dmd2/idgen.c	Mon Jun 01 19:02:20 2009 +0100
@@ -1,363 +1,379 @@
-
-// 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.
-
-// Program to generate string files in d data structures.
-// Saves much tedious typing, and eliminates typo problems.
-// Generates:
-//	id.h
-//	id.c
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdarg.h>
-#include <assert.h>
-
-struct Msgtable
-{
-	const char *ident;	// name to use in DMD source
-	const char *name;	// name in D executable
-};
-
-Msgtable msgtable[] =
-{
-    { "IUnknown" },
-    { "Object" },
-    { "object" },
-    { "max" },
-    { "min" },
-    { "This", "this" },
-    { "ctor", "__ctor" },
-    { "dtor", "__dtor" },
-    { "cpctor", "__cpctor" },
-    { "_postblit", "__postblit" },
-    { "classInvariant", "__invariant" },
-    { "unitTest", "__unitTest" },
-    { "init" },
-    { "size" },
-    { "__sizeof", "sizeof" },
-    { "alignof" },
-    { "mangleof" },
-    { "stringof" },
-    { "tupleof" },
-    { "length" },
-    { "remove" },
-    { "ptr" },
-    { "funcptr" },
-    { "dollar", "__dollar" },
-    { "offset" },
-    { "offsetof" },
-    { "ModuleInfo" },
-    { "ClassInfo" },
-    { "classinfo" },
-    { "typeinfo" },
-    { "outer" },
-    { "Exception" },
-    { "withSym", "__withSym" },
-    { "result", "__result" },
-    { "returnLabel", "__returnLabel" },
-    { "delegate" },
-    { "line" },
-    { "empty", "" },
-    { "p" },
-    { "coverage", "__coverage" },
-    { "__vptr" },
-    { "__monitor" },
-    { "system" },
-
-    { "TypeInfo" },
-    { "TypeInfo_Class" },
-    { "TypeInfo_Interface" },
-    { "TypeInfo_Struct" },
-    { "TypeInfo_Enum" },
-    { "TypeInfo_Typedef" },
-    { "TypeInfo_Pointer" },
-    { "TypeInfo_Array" },
-    { "TypeInfo_StaticArray" },
-    { "TypeInfo_AssociativeArray" },
-    { "TypeInfo_Function" },
-    { "TypeInfo_Delegate" },
-    { "TypeInfo_Tuple" },
-    { "TypeInfo_Const" },
-    { "TypeInfo_Invariant" },
-    { "elements" },
-    { "_arguments_typeinfo" },
-    { "_arguments" },
-    { "_argptr" },
-    { "_match" },
-    { "destroy" },
-    { "postblit" },
-
-    { "LINE", "__LINE__" },
-    { "FILE", "__FILE__" },
-    { "DATE", "__DATE__" },
-    { "TIME", "__TIME__" },
-    { "TIMESTAMP", "__TIMESTAMP__" },
-    { "VENDOR", "__VENDOR__" },
-    { "VERSIONX", "__VERSION__" },
-    { "EOFX", "__EOF__" },
-
-    { "nan" },
-    { "infinity" },
-    { "dig" },
-    { "epsilon" },
-    { "mant_dig" },
-    { "max_10_exp" },
-    { "max_exp" },
-    { "min_10_exp" },
-    { "min_exp" },
-    { "re" },
-    { "im" },
-
-    { "C" },
-    { "D" },
-    { "Windows" },
-    { "Pascal" },
-    { "System" },
-
-    { "exit" },
-    { "success" },
-    { "failure" },
-
-    { "keys" },
-    { "values" },
-    { "rehash" },
-
-    { "sort" },
-    { "reverse" },
-    { "dup" },
-    { "idup" },
-
-    // For inline assembler
-    { "___out", "out" },
-    { "___in", "in" },
-    { "__int", "int" },
-    { "__dollar", "$" },
-    { "__LOCAL_SIZE" },
-
-    // For operator overloads
-    { "uadd",	 "opPos" },
-    { "neg",     "opNeg" },
-    { "com",     "opCom" },
-    { "add",     "opAdd" },
-    { "add_r",   "opAdd_r" },
-    { "sub",     "opSub" },
-    { "sub_r",   "opSub_r" },
-    { "mul",     "opMul" },
-    { "mul_r",   "opMul_r" },
-    { "div",     "opDiv" },
-    { "div_r",   "opDiv_r" },
-    { "mod",     "opMod" },
-    { "mod_r",   "opMod_r" },
-    { "eq",      "opEquals" },
-    { "cmp",     "opCmp" },
-    { "iand",    "opAnd" },
-    { "iand_r",  "opAnd_r" },
-    { "ior",     "opOr" },
-    { "ior_r",   "opOr_r" },
-    { "ixor",    "opXor" },
-    { "ixor_r",  "opXor_r" },
-    { "shl",     "opShl" },
-    { "shl_r",   "opShl_r" },
-    { "shr",     "opShr" },
-    { "shr_r",   "opShr_r" },
-    { "ushr",    "opUShr" },
-    { "ushr_r",  "opUShr_r" },
-    { "cat",     "opCat" },
-    { "cat_r",   "opCat_r" },
-    { "assign",  "opAssign" },
-    { "addass",  "opAddAssign" },
-    { "subass",  "opSubAssign" },
-    { "mulass",  "opMulAssign" },
-    { "divass",  "opDivAssign" },
-    { "modass",  "opModAssign" },
-    { "andass",  "opAndAssign" },
-    { "orass",   "opOrAssign" },
-    { "xorass",  "opXorAssign" },
-    { "shlass",  "opShlAssign" },
-    { "shrass",  "opShrAssign" },
-    { "ushrass", "opUShrAssign" },
-    { "catass",  "opCatAssign" },
-    { "postinc", "opPostInc" },
-    { "postdec", "opPostDec" },
-    { "index",	 "opIndex" },
-    { "indexass", "opIndexAssign" },
-    { "slice",	 "opSlice" },
-    { "sliceass", "opSliceAssign" },
-    { "call",	 "opCall" },
-    { "cast",	 "opCast" },
-    { "match",	 "opMatch" },
-    { "next",	 "opNext" },
-    { "opIn" },
-    { "opIn_r" },
-    { "opStar" },
-    { "opDot" },
-    { "opImplicitCast" },
-
-    { "classNew", "new" },
-    { "classDelete", "delete" },
-
-    // For foreach
-    { "apply", "opApply" },
-    { "applyReverse", "opApplyReverse" },
-
-    { "Fempty", "empty" },
-    { "Fhead", "head" },
-    { "Ftoe", "toe" },
-    { "Fnext", "next" },
-    { "Fretreat", "retreat" },
-
-    { "adDup", "_adDupT" },
-    { "adReverse", "_adReverse" },
-
-    // For internal functions
-    { "aaLen", "_aaLen" },
-    { "aaKeys", "_aaKeys" },
-    { "aaValues", "_aaValues" },
-    { "aaRehash", "_aaRehash" },
-
-    // For pragma's
-    { "GNU_asm" },
-    { "lib" },
-    { "msg" },
-    { "startaddress" },
-
-    // LDC pragma's
-    { "intrinsic" },
-    { "va_intrinsic" },
-    { "no_typeinfo" },
-    { "no_moduleinfo" },
-    { "Alloca", "alloca" },
-    { "vastart", "va_start" },
-    { "vacopy", "va_copy" },
-    { "vaend", "va_end" },
-    { "vaarg", "va_arg" },
-    { "ldc" },
-    { "allow_inline" },
-
-    // For special functions
-    { "tohash", "toHash" },
-    { "tostring", "toString" },
-    { "getmembers", "getMembers" },
-
-    // Special functions
-    //{ "alloca" },
-    { "main" },
-    { "WinMain" },
-    { "DllMain" },
-
-    // Builtin functions
-    { "std" },
-    { "math" },
-    { "sin" },
-    { "cos" },
-    { "tan" },
-    { "_sqrt", "sqrt" },
-    { "fabs" },
-
-    // Traits
-    { "isAbstractClass" },
-    { "isArithmetic" },
-    { "isAssociativeArray" },
-    { "isFinalClass" },
-    { "isFloating" },
-    { "isIntegral" },
-    { "isScalar" },
-    { "isStaticArray" },
-    { "isUnsigned" },
-    { "isVirtualFunction" },
-    { "isAbstractFunction" },
-    { "isFinalFunction" },
-    { "hasMember" },
-    { "getMember" },
-    { "getVirtualFunctions" },
-    { "classInstanceSize" },
-    { "allMembers" },
-    { "derivedMembers" },
-    { "isSame" },
-    { "compiles" },
-};
-
-
-int main()
-{
-    FILE *fp;
-    unsigned i;
-
-    {
-	fp = fopen("id.h","w");
-	if (!fp)
-	{   printf("can't open id.h\n");
-	    exit(EXIT_FAILURE);
-	}
-
-	fprintf(fp, "// File generated by idgen.c\n");
-#if __DMC__
-	fprintf(fp, "#pragma once\n");
-#endif
-	fprintf(fp, "#ifndef DMD_ID_H\n");
-	fprintf(fp, "#define DMD_ID_H 1\n");
-	fprintf(fp, "struct Identifier;\n");
-	fprintf(fp, "struct Id\n");
-	fprintf(fp, "{\n");
-
-	for (i = 0; i < sizeof(msgtable) / sizeof(msgtable[0]); i++)
-	{   const char *id = msgtable[i].ident;
-
-	    fprintf(fp,"    static Identifier *%s;\n", id);
-	}
-
-	fprintf(fp, "    static void initialize();\n");
-	fprintf(fp, "};\n");
-	fprintf(fp, "#endif\n");
-
-	fclose(fp);
-    }
-
-    {
-	fp = fopen("id.c","w");
-	if (!fp)
-	{   printf("can't open id.c\n");
-	    exit(EXIT_FAILURE);
-	}
-
-	fprintf(fp, "// File generated by idgen.c\n");
-	fprintf(fp, "#include \"id.h\"\n");
-	fprintf(fp, "#include \"identifier.h\"\n");
-	fprintf(fp, "#include \"lexer.h\"\n");
-
-	for (i = 0; i < sizeof(msgtable) / sizeof(msgtable[0]); i++)
-	{   const char *id = msgtable[i].ident;
-	    const char *p = msgtable[i].name;
-
-	    if (!p)
-		p = id;
-	    fprintf(fp,"Identifier *Id::%s;\n", id);
-	}
-
-	fprintf(fp, "void Id::initialize()\n");
-	fprintf(fp, "{\n");
-
-	for (i = 0; i < sizeof(msgtable) / sizeof(msgtable[0]); i++)
-	{   const char *id = msgtable[i].ident;
-	    const char *p = msgtable[i].name;
-
-	    if (!p)
-		p = id;
-	    fprintf(fp,"    %s = Lexer::idPool(\"%s\");\n", id, p);
-	}
-
-	fprintf(fp, "}\n");
-
-	fclose(fp);
-    }
-
-    return EXIT_SUCCESS;
-}
+
+// 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.
+
+// Program to generate string files in d data structures.
+// Saves much tedious typing, and eliminates typo problems.
+// Generates:
+//	id.h
+//	id.c
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <assert.h>
+
+struct Msgtable
+{
+	const char *ident;	// name to use in DMD source
+	const char *name;	// name in D executable
+};
+
+Msgtable msgtable[] =
+{
+    { "IUnknown" },
+    { "Object" },
+    { "object" },
+    { "max" },
+    { "min" },
+    { "This", "this" },
+    { "ctor", "__ctor" },
+    { "dtor", "__dtor" },
+    { "cpctor", "__cpctor" },
+    { "_postblit", "__postblit" },
+    { "classInvariant", "__invariant" },
+    { "unitTest", "__unitTest" },
+    { "init" },
+    { "size" },
+    { "__sizeof", "sizeof" },
+    { "alignof" },
+    { "mangleof" },
+    { "stringof" },
+    { "tupleof" },
+    { "length" },
+    { "remove" },
+    { "ptr" },
+    { "funcptr" },
+    { "dollar", "__dollar" },
+    { "offset" },
+    { "offsetof" },
+    { "ModuleInfo" },
+    { "ClassInfo" },
+    { "classinfo" },
+    { "typeinfo" },
+    { "outer" },
+    { "Exception" },
+    { "Throwable" },
+    { "withSym", "__withSym" },
+    { "result", "__result" },
+    { "returnLabel", "__returnLabel" },
+    { "delegate" },
+    { "line" },
+    { "empty", "" },
+    { "p" },
+    { "coverage", "__coverage" },
+    { "__vptr" },
+    { "__monitor" },
+    { "system" },
+
+    { "TypeInfo" },
+    { "TypeInfo_Class" },
+    { "TypeInfo_Interface" },
+    { "TypeInfo_Struct" },
+    { "TypeInfo_Enum" },
+    { "TypeInfo_Typedef" },
+    { "TypeInfo_Pointer" },
+    { "TypeInfo_Array" },
+    { "TypeInfo_StaticArray" },
+    { "TypeInfo_AssociativeArray" },
+    { "TypeInfo_Function" },
+    { "TypeInfo_Delegate" },
+    { "TypeInfo_Tuple" },
+    { "TypeInfo_Const" },
+    { "TypeInfo_Invariant" },
+    { "TypeInfo_Shared" },
+    { "elements" },
+    { "_arguments_typeinfo" },
+    { "_arguments" },
+    { "_argptr" },
+    { "_match" },
+    { "destroy" },
+    { "postblit" },
+
+    { "LINE", "__LINE__" },
+    { "FILE", "__FILE__" },
+    { "DATE", "__DATE__" },
+    { "TIME", "__TIME__" },
+    { "TIMESTAMP", "__TIMESTAMP__" },
+    { "VENDOR", "__VENDOR__" },
+    { "VERSIONX", "__VERSION__" },
+    { "EOFX", "__EOF__" },
+
+    { "nan" },
+    { "infinity" },
+    { "dig" },
+    { "epsilon" },
+    { "mant_dig" },
+    { "max_10_exp" },
+    { "max_exp" },
+    { "min_10_exp" },
+    { "min_exp" },
+    { "re" },
+    { "im" },
+
+    { "C" },
+    { "D" },
+    { "Windows" },
+    { "Pascal" },
+    { "System" },
+
+    { "exit" },
+    { "success" },
+    { "failure" },
+
+    { "keys" },
+    { "values" },
+    { "rehash" },
+
+    { "sort" },
+    { "reverse" },
+    { "dup" },
+    { "idup" },
+
+    // For inline assembler
+    { "___out", "out" },
+    { "___in", "in" },
+    { "__int", "int" },
+    { "__dollar", "$" },
+    { "__LOCAL_SIZE" },
+
+    // For operator overloads
+    { "uadd",	 "opPos" },
+    { "neg",     "opNeg" },
+    { "com",     "opCom" },
+    { "add",     "opAdd" },
+    { "add_r",   "opAdd_r" },
+    { "sub",     "opSub" },
+    { "sub_r",   "opSub_r" },
+    { "mul",     "opMul" },
+    { "mul_r",   "opMul_r" },
+    { "div",     "opDiv" },
+    { "div_r",   "opDiv_r" },
+    { "mod",     "opMod" },
+    { "mod_r",   "opMod_r" },
+    { "eq",      "opEquals" },
+    { "cmp",     "opCmp" },
+    { "iand",    "opAnd" },
+    { "iand_r",  "opAnd_r" },
+    { "ior",     "opOr" },
+    { "ior_r",   "opOr_r" },
+    { "ixor",    "opXor" },
+    { "ixor_r",  "opXor_r" },
+    { "shl",     "opShl" },
+    { "shl_r",   "opShl_r" },
+    { "shr",     "opShr" },
+    { "shr_r",   "opShr_r" },
+    { "ushr",    "opUShr" },
+    { "ushr_r",  "opUShr_r" },
+    { "cat",     "opCat" },
+    { "cat_r",   "opCat_r" },
+    { "assign",  "opAssign" },
+    { "addass",  "opAddAssign" },
+    { "subass",  "opSubAssign" },
+    { "mulass",  "opMulAssign" },
+    { "divass",  "opDivAssign" },
+    { "modass",  "opModAssign" },
+    { "andass",  "opAndAssign" },
+    { "orass",   "opOrAssign" },
+    { "xorass",  "opXorAssign" },
+    { "shlass",  "opShlAssign" },
+    { "shrass",  "opShrAssign" },
+    { "ushrass", "opUShrAssign" },
+    { "catass",  "opCatAssign" },
+    { "postinc", "opPostInc" },
+    { "postdec", "opPostDec" },
+    { "index",	 "opIndex" },
+    { "indexass", "opIndexAssign" },
+    { "slice",	 "opSlice" },
+    { "sliceass", "opSliceAssign" },
+    { "call",	 "opCall" },
+    { "cast",	 "opCast" },
+    { "match",	 "opMatch" },
+    { "next",	 "opNext" },
+    { "opIn" },
+    { "opIn_r" },
+    { "opStar" },
+    { "opDot" },
+    { "opImplicitCast" },
+
+    { "classNew", "new" },
+    { "classDelete", "delete" },
+
+    // For foreach
+    { "apply", "opApply" },
+    { "applyReverse", "opApplyReverse" },
+
+#if 1
+    { "Fempty", "empty" },
+    { "Fhead", "front" },
+    { "Ftoe", "back" },
+    { "Fnext", "popFront" },
+    { "Fretreat", "popBack" },
+#else
+    { "Fempty", "empty" },
+    { "Fhead", "head" },
+    { "Ftoe", "toe" },
+    { "Fnext", "next" },
+    { "Fretreat", "retreat" },
+#endif
+
+    { "adDup", "_adDupT" },
+    { "adReverse", "_adReverse" },
+
+    // For internal functions
+    { "aaLen", "_aaLen" },
+    { "aaKeys", "_aaKeys" },
+    { "aaValues", "_aaValues" },
+    { "aaRehash", "_aaRehash" },
+
+    // For pragma's
+    { "GNU_asm" },
+    { "lib" },
+    { "msg" },
+    { "startaddress" },
+
+#if IN_LLVM
+    // LDC pragma's
+    { "intrinsic" },
+    { "va_intrinsic" },
+    { "no_typeinfo" },
+    { "no_moduleinfo" },
+    { "Alloca", "alloca" },
+    { "vastart", "va_start" },
+    { "vacopy", "va_copy" },
+    { "vaend", "va_end" },
+    { "vaarg", "va_arg" },
+    { "ldc" },
+    { "allow_inline" },
+    { "llvm_inline_asm" },
+#endif
+
+    // For special functions
+    { "tohash", "toHash" },
+    { "tostring", "toString" },
+    { "getmembers", "getMembers" },
+
+    // Special functions
+#if IN_DMD
+    { "alloca" },
+#endif
+    { "main" },
+    { "WinMain" },
+    { "DllMain" },
+    { "tls_get_addr", "___tls_get_addr" },
+
+    // Builtin functions
+    { "std" },
+    { "math" },
+    { "sin" },
+    { "cos" },
+    { "tan" },
+    { "_sqrt", "sqrt" },
+    { "fabs" },
+
+    // Traits
+    { "isAbstractClass" },
+    { "isArithmetic" },
+    { "isAssociativeArray" },
+    { "isFinalClass" },
+    { "isFloating" },
+    { "isIntegral" },
+    { "isScalar" },
+    { "isStaticArray" },
+    { "isUnsigned" },
+    { "isVirtualFunction" },
+    { "isAbstractFunction" },
+    { "isFinalFunction" },
+    { "hasMember" },
+    { "getMember" },
+    { "getVirtualFunctions" },
+    { "classInstanceSize" },
+    { "allMembers" },
+    { "derivedMembers" },
+    { "isSame" },
+    { "compiles" },
+};
+
+
+int main()
+{
+    FILE *fp;
+    unsigned i;
+
+    {
+	fp = fopen("id.h","w");
+	if (!fp)
+	{   printf("can't open id.h\n");
+	    exit(EXIT_FAILURE);
+	}
+
+	fprintf(fp, "// File generated by idgen.c\n");
+#if __DMC__
+	fprintf(fp, "#pragma once\n");
+#endif
+	fprintf(fp, "#ifndef DMD_ID_H\n");
+	fprintf(fp, "#define DMD_ID_H 1\n");
+	fprintf(fp, "struct Identifier;\n");
+	fprintf(fp, "struct Id\n");
+	fprintf(fp, "{\n");
+
+	for (i = 0; i < sizeof(msgtable) / sizeof(msgtable[0]); i++)
+	{   const char *id = msgtable[i].ident;
+
+	    fprintf(fp,"    static Identifier *%s;\n", id);
+	}
+
+	fprintf(fp, "    static void initialize();\n");
+	fprintf(fp, "};\n");
+	fprintf(fp, "#endif\n");
+
+	fclose(fp);
+    }
+
+    {
+	fp = fopen("id.c","w");
+	if (!fp)
+	{   printf("can't open id.c\n");
+	    exit(EXIT_FAILURE);
+	}
+
+	fprintf(fp, "// File generated by idgen.c\n");
+	fprintf(fp, "#include \"id.h\"\n");
+	fprintf(fp, "#include \"identifier.h\"\n");
+	fprintf(fp, "#include \"lexer.h\"\n");
+
+	for (i = 0; i < sizeof(msgtable) / sizeof(msgtable[0]); i++)
+	{   const char *id = msgtable[i].ident;
+	    const char *p = msgtable[i].name;
+
+	    if (!p)
+		p = id;
+	    fprintf(fp,"Identifier *Id::%s;\n", id);
+	}
+
+	fprintf(fp, "void Id::initialize()\n");
+	fprintf(fp, "{\n");
+
+	for (i = 0; i < sizeof(msgtable) / sizeof(msgtable[0]); i++)
+	{   const char *id = msgtable[i].ident;
+	    const char *p = msgtable[i].name;
+
+	    if (!p)
+		p = id;
+	    fprintf(fp,"    %s = Lexer::idPool(\"%s\");\n", id, p);
+	}
+
+	fprintf(fp, "}\n");
+
+	fclose(fp);
+    }
+
+    return EXIT_SUCCESS;
+}
Binary file dmd2/impcnvgen has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd2/impcnvtab.c	Mon Jun 01 19:02:20 2009 +0100
@@ -0,0 +1,182 @@
+// This file is generated by impcnvgen.c
+#include "mtype.h"
+unsigned char Type::impcnvResult[TMAX][TMAX] =
+{
+36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
+36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
+36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
+36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
+36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
+36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
+36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
+36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
+36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
+36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
+36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
+36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
+36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
+36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
+36,36,36,36,36,36,36,36,36,36,36,36,36,36,18,18,18,18,18,19,20,21,22,23,24,22,23,24,28,29,30,36,18,36,36,36,36,36,36,36,36,36,
+36,36,36,36,36,36,36,36,36,36,36,36,36,36,18,18,18,18,18,19,20,21,22,23,24,22,23,24,28,29,30,36,18,36,36,36,36,36,36,36,36,36,
+36,36,36,36,36,36,36,36,36,36,36,36,36,36,18,18,18,18,18,19,20,21,22,23,24,22,23,24,28,29,30,36,18,36,36,36,36,36,36,36,36,36,
+36,36,36,36,36,36,36,36,36,36,36,36,36,36,18,18,18,18,18,19,20,21,22,23,24,22,23,24,28,29,30,36,18,36,36,36,36,36,36,36,36,36,
+36,36,36,36,36,36,36,36,36,36,36,36,36,36,18,18,18,18,18,19,20,21,22,23,24,22,23,24,28,29,30,36,18,36,36,36,36,36,36,36,36,36,
+36,36,36,36,36,36,36,36,36,36,36,36,36,36,19,19,19,19,19,19,20,21,22,23,24,22,23,24,28,29,30,36,19,36,36,36,36,36,36,36,36,36,
+36,36,36,36,36,36,36,36,36,36,36,36,36,36,20,20,20,20,20,20,20,21,22,23,24,22,23,24,28,29,30,36,20,36,36,36,36,36,36,36,36,36,
+36,36,36,36,36,36,36,36,36,36,36,36,36,36,21,21,21,21,21,21,21,21,22,23,24,22,23,24,28,29,30,36,21,36,36,36,36,36,36,36,36,36,
+36,36,36,36,36,36,36,36,36,36,36,36,36,36,22,22,22,22,22,22,22,22,22,23,24,22,23,24,28,29,30,36,22,36,36,36,36,36,36,36,36,36,
+36,36,36,36,36,36,36,36,36,36,36,36,36,36,23,23,23,23,23,23,23,23,23,23,24,23,23,24,29,29,30,36,23,36,36,36,36,36,36,36,36,36,
+36,36,36,36,36,36,36,36,36,36,36,36,36,36,24,24,24,24,24,24,24,24,24,24,24,24,24,24,30,30,30,36,24,36,36,36,36,36,36,36,36,36,
+36,36,36,36,36,36,36,36,36,36,36,36,36,36,22,22,22,22,22,22,22,22,22,23,24,25,26,27,28,29,30,36,22,36,36,36,36,36,36,36,36,36,
+36,36,36,36,36,36,36,36,36,36,36,36,36,36,23,23,23,23,23,23,23,23,23,23,24,26,26,27,29,29,30,36,23,36,36,36,36,36,36,36,36,36,
+36,36,36,36,36,36,36,36,36,36,36,36,36,36,24,24,24,24,24,24,24,24,24,24,24,27,27,27,30,30,30,36,24,36,36,36,36,36,36,36,36,36,
+36,36,36,36,36,36,36,36,36,36,36,36,36,36,28,28,28,28,28,28,28,28,28,29,30,28,29,30,28,29,30,36,28,36,36,36,36,36,36,36,36,36,
+36,36,36,36,36,36,36,36,36,36,36,36,36,36,29,29,29,29,29,29,29,29,29,29,30,29,29,30,29,29,30,36,29,36,36,36,36,36,36,36,36,36,
+36,36,36,36,36,36,36,36,36,36,36,36,36,36,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,36,30,36,36,36,36,36,36,36,36,36,
+36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
+36,36,36,36,36,36,36,36,36,36,36,36,36,36,18,18,18,18,18,19,20,21,22,23,24,22,23,24,28,29,30,36,32,36,36,36,36,36,36,36,36,36,
+36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
+36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
+36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
+36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
+36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
+36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
+36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
+36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
+36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
+};
+unsigned char Type::impcnvType1[TMAX][TMAX] =
+{
+36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
+36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
+36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
+36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
+36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
+36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
+36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
+36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
+36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
+36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
+36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
+36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
+36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
+36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
+36,36,36,36,36,36,36,36,36,36,36,36,36,36,18,18,18,18,18,19,20,21,22,23,24,22,23,24,22,23,24,36,18,36,36,36,36,36,36,36,36,36,
+36,36,36,36,36,36,36,36,36,36,36,36,36,36,18,18,18,18,18,19,20,21,22,23,24,22,23,24,22,23,24,36,18,36,36,36,36,36,36,36,36,36,
+36,36,36,36,36,36,36,36,36,36,36,36,36,36,18,18,18,18,18,19,20,21,22,23,24,22,23,24,22,23,24,36,18,36,36,36,36,36,36,36,36,36,
+36,36,36,36,36,36,36,36,36,36,36,36,36,36,18,18,18,18,18,19,20,21,22,23,24,22,23,24,22,23,24,36,18,36,36,36,36,36,36,36,36,36,
+36,36,36,36,36,36,36,36,36,36,36,36,36,36,18,18,18,18,18,19,20,21,22,23,24,22,23,24,22,23,24,36,18,36,36,36,36,36,36,36,36,36,
+36,36,36,36,36,36,36,36,36,36,36,36,36,36,19,19,19,19,19,19,20,21,22,23,24,22,23,24,22,23,24,36,19,36,36,36,36,36,36,36,36,36,
+36,36,36,36,36,36,36,36,36,36,36,36,36,36,20,20,20,20,20,20,20,21,22,23,24,22,23,24,22,23,24,36,20,36,36,36,36,36,36,36,36,36,
+36,36,36,36,36,36,36,36,36,36,36,36,36,36,21,21,21,21,21,21,21,21,22,23,24,22,23,24,22,23,24,36,21,36,36,36,36,36,36,36,36,36,
+36,36,36,36,36,36,36,36,36,36,36,36,36,36,22,22,22,22,22,22,22,22,22,23,24,22,23,24,22,23,24,36,22,36,36,36,36,36,36,36,36,36,
+36,36,36,36,36,36,36,36,36,36,36,36,36,36,23,23,23,23,23,23,23,23,23,23,24,23,23,24,23,23,24,36,23,36,36,36,36,36,36,36,36,36,
+36,36,36,36,36,36,36,36,36,36,36,36,36,36,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,36,24,36,36,36,36,36,36,36,36,36,
+36,36,36,36,36,36,36,36,36,36,36,36,36,36,25,25,25,25,25,25,25,25,25,26,27,25,26,27,25,26,27,36,25,36,36,36,36,36,36,36,36,36,
+36,36,36,36,36,36,36,36,36,36,36,36,36,36,26,26,26,26,26,26,26,26,26,26,27,26,26,27,26,26,27,36,26,36,36,36,36,36,36,36,36,36,
+36,36,36,36,36,36,36,36,36,36,36,36,36,36,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,36,27,36,36,36,36,36,36,36,36,36,
+36,36,36,36,36,36,36,36,36,36,36,36,36,36,28,28,28,28,28,28,28,28,28,29,30,28,29,30,28,29,30,36,28,36,36,36,36,36,36,36,36,36,
+36,36,36,36,36,36,36,36,36,36,36,36,36,36,29,29,29,29,29,29,29,29,29,29,30,29,29,30,29,29,30,36,29,36,36,36,36,36,36,36,36,36,
+36,36,36,36,36,36,36,36,36,36,36,36,36,36,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,36,30,36,36,36,36,36,36,36,36,36,
+36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
+36,36,36,36,36,36,36,36,36,36,36,36,36,36,18,18,18,18,18,19,20,21,22,23,24,22,23,24,22,23,24,36,32,36,36,36,36,36,36,36,36,36,
+36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
+36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
+36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
+36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
+36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
+36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
+36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
+36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
+36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
+};
+unsigned char Type::impcnvType2[TMAX][TMAX] =
+{
+36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
+36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
+36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
+36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
+36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
+36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
+36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
+36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
+36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
+36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
+36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
+36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
+36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
+36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
+36,36,36,36,36,36,36,36,36,36,36,36,36,36,18,18,18,18,18,19,20,21,22,23,24,25,26,27,28,29,30,36,18,36,36,36,36,36,36,36,36,36,
+36,36,36,36,36,36,36,36,36,36,36,36,36,36,18,18,18,18,18,19,20,21,22,23,24,25,26,27,28,29,30,36,18,36,36,36,36,36,36,36,36,36,
+36,36,36,36,36,36,36,36,36,36,36,36,36,36,18,18,18,18,18,19,20,21,22,23,24,25,26,27,28,29,30,36,18,36,36,36,36,36,36,36,36,36,
+36,36,36,36,36,36,36,36,36,36,36,36,36,36,18,18,18,18,18,19,20,21,22,23,24,25,26,27,28,29,30,36,18,36,36,36,36,36,36,36,36,36,
+36,36,36,36,36,36,36,36,36,36,36,36,36,36,18,18,18,18,18,19,20,21,22,23,24,25,26,27,28,29,30,36,18,36,36,36,36,36,36,36,36,36,
+36,36,36,36,36,36,36,36,36,36,36,36,36,36,19,19,19,19,19,19,20,21,22,23,24,25,26,27,28,29,30,36,19,36,36,36,36,36,36,36,36,36,
+36,36,36,36,36,36,36,36,36,36,36,36,36,36,20,20,20,20,20,20,20,21,22,23,24,25,26,27,28,29,30,36,20,36,36,36,36,36,36,36,36,36,
+36,36,36,36,36,36,36,36,36,36,36,36,36,36,21,21,21,21,21,21,21,21,22,23,24,25,26,27,28,29,30,36,21,36,36,36,36,36,36,36,36,36,
+36,36,36,36,36,36,36,36,36,36,36,36,36,36,22,22,22,22,22,22,22,22,22,23,24,25,26,27,28,29,30,36,22,36,36,36,36,36,36,36,36,36,
+36,36,36,36,36,36,36,36,36,36,36,36,36,36,23,23,23,23,23,23,23,23,23,23,24,26,26,27,29,29,30,36,23,36,36,36,36,36,36,36,36,36,
+36,36,36,36,36,36,36,36,36,36,36,36,36,36,24,24,24,24,24,24,24,24,24,24,24,27,27,27,30,30,30,36,24,36,36,36,36,36,36,36,36,36,
+36,36,36,36,36,36,36,36,36,36,36,36,36,36,22,22,22,22,22,22,22,22,22,23,24,25,26,27,28,29,30,36,22,36,36,36,36,36,36,36,36,36,
+36,36,36,36,36,36,36,36,36,36,36,36,36,36,23,23,23,23,23,23,23,23,23,23,24,26,26,27,29,29,30,36,23,36,36,36,36,36,36,36,36,36,
+36,36,36,36,36,36,36,36,36,36,36,36,36,36,24,24,24,24,24,24,24,24,24,24,24,27,27,27,30,30,30,36,24,36,36,36,36,36,36,36,36,36,
+36,36,36,36,36,36,36,36,36,36,36,36,36,36,22,22,22,22,22,22,22,22,22,23,24,25,26,27,28,29,30,36,22,36,36,36,36,36,36,36,36,36,
+36,36,36,36,36,36,36,36,36,36,36,36,36,36,23,23,23,23,23,23,23,23,23,23,24,26,26,27,29,29,30,36,23,36,36,36,36,36,36,36,36,36,
+36,36,36,36,36,36,36,36,36,36,36,36,36,36,24,24,24,24,24,24,24,24,24,24,24,27,27,27,30,30,30,36,24,36,36,36,36,36,36,36,36,36,
+36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
+36,36,36,36,36,36,36,36,36,36,36,36,36,36,18,18,18,18,18,19,20,21,22,23,24,25,26,27,28,29,30,36,32,36,36,36,36,36,36,36,36,36,
+36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
+36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
+36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
+36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
+36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
+36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
+36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
+36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
+36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
+};
+unsigned char Type::impcnvWarn[TMAX][TMAX] =
+{
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+};
--- a/dmd2/import.c	Mon Jun 01 01:28:18 2009 +0200
+++ b/dmd2/import.c	Mon Jun 01 19:02:20 2009 +0100
@@ -1,262 +1,373 @@
-
-// Compiler implementation of the D programming language
-// Copyright (c) 1999-2006 by Digital Mars
-// All Rights Reserved
-// written by Walter Bright
-// http://www.digitalmars.com
-// License for redistribution is by either the Artistic License
-// in artistic.txt, or the GNU General Public License in gnu.txt.
-// See the included readme.txt for details.
-
-#include <stdio.h>
-#include <assert.h>
-
-#include "root.h"
-#include "dsymbol.h"
-#include "import.h"
-#include "identifier.h"
-#include "module.h"
-#include "scope.h"
-#include "hdrgen.h"
-#include "mtype.h"
-#include "declaration.h"
-#include "id.h"
-
-/********************************* Import ****************************/
-
-Import::Import(Loc loc, Array *packages, Identifier *id, Identifier *aliasId,
-	int isstatic)
-    : Dsymbol(id)
-{
-    this->loc = loc;
-    this->packages = packages;
-    this->id = id;
-    this->aliasId = aliasId;
-    this->isstatic = isstatic;
-    protection = PROTundefined;
-    pkg = NULL;
-    mod = NULL;
-
-    if (aliasId)
-	this->ident = aliasId;
-    // Kludge to change Import identifier to first package
-    else if (packages && packages->dim)
-	this->ident = (Identifier *)packages->data[0];
-}
-
-void Import::addAlias(Identifier *name, Identifier *alias)
-{
-    if (isstatic)
-	error("cannot have an import bind list");
-
-    if (!aliasId)
-	this->ident = NULL;	// make it an anonymous import
-
-    names.push(name);
-    aliases.push(alias);
-}
-
-const char *Import::kind()
-{
-    return isstatic ? (char *)"static import" : (char *)"import";
-}
-
-enum PROT Import::prot()
-{
-    return protection;
-}
-
-Dsymbol *Import::syntaxCopy(Dsymbol *s)
-{
-    assert(!s);
-
-    Import *si;
-
-    si = new Import(loc, packages, id, aliasId, isstatic);
-
-    for (size_t i = 0; i < names.dim; i++)
-    {
-	si->addAlias((Identifier *)names.data[i], (Identifier *)aliases.data[i]);
-    }
-
-    return si;
-}
-
-void Import::load(Scope *sc)
-{
-    DsymbolTable *dst;
-    Dsymbol *s;
-
-    //printf("Import::load('%s')\n", toChars());
-
-    // See if existing module
-    dst = Package::resolve(packages, NULL, &pkg);
-
-    s = dst->lookup(id);
-    if (s)
-    {
-	if (s->isModule())
-	    mod = (Module *)s;
-	else
-	    error("package and module have the same name");
-    }
-
-    if (!mod)
-    {
-	// Load module
-	mod = Module::load(loc, packages, id);
-	dst->insert(id, mod);		// id may be different from mod->ident,
-					// if so then insert alias
-	if (!mod->importedFrom)
-	    mod->importedFrom = sc ? sc->module->importedFrom : Module::rootModule;
-    }
-    if (!pkg)
-	pkg = mod;
-    mod->semantic();
-
-    //printf("-Import::load('%s'), pkg = %p\n", toChars(), pkg);
-}
-
-
-void Import::semantic(Scope *sc)
-{
-    //printf("Import::semantic('%s')\n", toChars());
-
-    load(sc);
-
-    if (mod)
-    {
-#if 0
-	if (mod->loc.linnum != 0)
-	{   /* If the line number is not 0, then this is not
-	     * a 'root' module, i.e. it was not specified on the command line.
-	     */
-	    mod->importedFrom = sc->module->importedFrom;
-	    assert(mod->importedFrom);
-	}
-#endif
-
-	/* Default to private importing
-	 */
-	protection = sc->protection;
-	if (!sc->explicitProtection)
-	    protection = PROTprivate;
-
-	if (!isstatic && !aliasId && !names.dim)
-	{
-	    sc->scopesym->importScope(mod, protection);
-	}
-
-	// Modules need a list of each imported module
-	sc->module->aimports.push(mod);
-
-	if (mod->needmoduleinfo)
-	    sc->module->needmoduleinfo = 1;
-
-	sc = sc->push(mod);
-	for (size_t i = 0; i < aliasdecls.dim; i++)
-	{   AliasDeclaration *ad = (AliasDeclaration *)aliasdecls.data[i];
-
-	    //printf("\tImport alias semantic('%s')\n", s->toChars());
-	    if (!mod->search(loc, (Identifier *)names.data[i], 0))
-		error("%s not found", ((Identifier *)names.data[i])->toChars());
-
-	    ad->semantic(sc);
-	    ad->protection = protection;
-	}
-	sc = sc->pop();
-    }
-    //printf("-Import::semantic('%s'), pkg = %p\n", toChars(), pkg);
-}
-
-void Import::semantic2(Scope *sc)
-{
-    //printf("Import::semantic2('%s')\n", toChars());
-    mod->semantic2();
-    if (mod->needmoduleinfo)
-	sc->module->needmoduleinfo = 1;
-}
-
-Dsymbol *Import::toAlias()
-{
-    if (aliasId)
-	return mod;
-    return this;
-}
-
-/*****************************
- * Add import to sd's symbol table.
- */
-
-int Import::addMember(Scope *sc, ScopeDsymbol *sd, int memnum)
-{
-    int result = 0;
-
-    if (names.dim == 0)
-	return Dsymbol::addMember(sc, sd, memnum);
-
-    if (aliasId)
-	result = Dsymbol::addMember(sc, sd, memnum);
-
-    /* Instead of adding the import to sd's symbol table,
-     * add each of the alias=name pairs
-     */
-    for (size_t i = 0; i < names.dim; i++)
-    {
-	Identifier *name = (Identifier *)names.data[i];
-	Identifier *alias = (Identifier *)aliases.data[i];
-
-	if (!alias)
-	    alias = name;
-
-	TypeIdentifier *tname = new TypeIdentifier(loc, name);
-	AliasDeclaration *ad = new AliasDeclaration(loc, alias, tname);
-	result |= ad->addMember(sc, sd, memnum);
-
-	aliasdecls.push(ad);
-    }
-
-    return result;
-}
-
-Dsymbol *Import::search(Loc loc, Identifier *ident, int flags)
-{
-    //printf("%s.Import::search(ident = '%s', flags = x%x)\n", toChars(), ident->toChars(), flags);
-
-    if (!pkg)
-	load(NULL);
-
-    // Forward it to the package/module
-    return pkg->search(loc, ident, flags);
-}
-
-int Import::overloadInsert(Dsymbol *s)
-{
-    // Allow multiple imports of the same name
-    return s->isImport() != NULL;
-}
-
-void Import::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{
-    if (hgs->hdrgen && id == Id::object)
-	return;		// object is imported by default
-
-    if (isstatic)
-	buf->writestring("static ");
-    buf->writestring("import ");
-    if (aliasId)
-    {
-	buf->printf("%s = ", aliasId->toChars());
-    }
-    if (packages && packages->dim)
-    {
-	for (size_t i = 0; i < packages->dim; i++)
-	{   Identifier *pid = (Identifier *)packages->data[i];
-
-	    buf->printf("%s.", pid->toChars());
-	}
-    }
-    buf->printf("%s;", id->toChars());
-    buf->writenl();
-}
-
+
+// Compiler implementation of the D programming language
+// Copyright (c) 1999-2009 by Digital Mars
+// All Rights Reserved
+// written by Walter Bright
+// http://www.digitalmars.com
+// License for redistribution is by either the Artistic License
+// in artistic.txt, or the GNU General Public License in gnu.txt.
+// See the included readme.txt for details.
+
+#include <stdio.h>
+#include <assert.h>
+
+#include "root.h"
+#include "dsymbol.h"
+#include "import.h"
+#include "identifier.h"
+#include "module.h"
+#include "scope.h"
+#include "hdrgen.h"
+#include "mtype.h"
+#include "declaration.h"
+#include "id.h"
+
+/********************************* Import ****************************/
+
+Import::Import(Loc loc, Array *packages, Identifier *id, Identifier *aliasId,
+	int isstatic)
+    : Dsymbol(id)
+{
+    assert(id);
+    this->loc = loc;
+    this->packages = packages;
+    this->id = id;
+    this->aliasId = aliasId;
+    this->isstatic = isstatic;
+#if IN_LLVM
+    protection = PROTundefined;
+#endif
+    pkg = NULL;
+    mod = NULL;
+
+    if (aliasId)
+	this->ident = aliasId;
+    // Kludge to change Import identifier to first package
+    else if (packages && packages->dim)
+	this->ident = (Identifier *)packages->data[0];
+}
+
+void Import::addAlias(Identifier *name, Identifier *alias)
+{
+    if (isstatic)
+	error("cannot have an import bind list");
+
+    if (!aliasId)
+	this->ident = NULL;	// make it an anonymous import
+
+    names.push(name);
+    aliases.push(alias);
+}
+
+const char *Import::kind()
+{
+    return isstatic ? (char *)"static import" : (char *)"import";
+}
+
+#if IN_LLVM
+enum PROT Import::prot()
+{
+    return protection;
+}
+#endif
+
+Dsymbol *Import::syntaxCopy(Dsymbol *s)
+{
+    assert(!s);
+
+    Import *si;
+
+    si = new Import(loc, packages, id, aliasId, isstatic);
+
+    for (size_t i = 0; i < names.dim; i++)
+    {
+	si->addAlias((Identifier *)names.data[i], (Identifier *)aliases.data[i]);
+    }
+
+    return si;
+}
+
+void Import::load(Scope *sc)
+{
+    DsymbolTable *dst;
+    Dsymbol *s;
+
+    //printf("Import::load('%s')\n", toChars());
+
+    // See if existing module
+    dst = Package::resolve(packages, NULL, &pkg);
+
+    s = dst->lookup(id);
+    if (s)
+    {
+	if (s->isModule())
+	    mod = (Module *)s;
+	else
+	    error("package and module have the same name");
+    }
+
+    if (!mod)
+    {
+	// Load module
+	mod = Module::load(loc, packages, id);
+	dst->insert(id, mod);		// id may be different from mod->ident,
+					// if so then insert alias
+	if (!mod->importedFrom)
+	    mod->importedFrom = sc ? sc->module->importedFrom : Module::rootModule;
+    }
+    if (!pkg)
+	pkg = mod;
+
+    //printf("-Import::load('%s'), pkg = %p\n", toChars(), pkg);
+}
+
+#if IN_LLVM
+char* escapePath(char* fname, char* buffer, int bufLen) {
+    char* res = buffer;
+    bufLen -= 2;    // for \0 and an occasional escape char
+    int dst = 0;
+    for (; dst < bufLen && *fname; ++dst, ++fname) {
+	switch (*fname) {
+	    case '(':
+	    case ')':
+	    case '\\':
+		    buffer[dst++] = '\\';
+		    // fall through
+
+	    default:
+		    buffer[dst] = *fname;
+	}
+    }
+    buffer[dst] = '\0';
+    return buffer;
+}
+#endif
+
+void Import::semantic(Scope *sc)
+{
+    //printf("Import::semantic('%s')\n", toChars());
+
+    load(sc);
+
+    if (mod)
+    {
+#if 0
+	if (mod->loc.linnum != 0)
+	{   /* If the line number is not 0, then this is not
+	     * a 'root' module, i.e. it was not specified on the command line.
+	     */
+	    mod->importedFrom = sc->module->importedFrom;
+	    assert(mod->importedFrom);
+	}
+#endif
+
+	// Modules need a list of each imported module
+	//printf("%s imports %s\n", sc->module->toChars(), mod->toChars());
+	sc->module->aimports.push(mod);
+
+	mod->semantic();
+
+	if (!isstatic && !aliasId && !names.dim)
+	{
+	    /* Default to private importing
+	     */
+	    enum PROT prot = sc->protection;
+	    if (!sc->explicitProtection)
+		prot = PROTprivate;
+	    sc->scopesym->importScope(mod, prot);
+	}
+
+	if (mod->needmoduleinfo)
+	    sc->module->needmoduleinfo = 1;
+
+	sc = sc->push(mod);
+	for (size_t i = 0; i < aliasdecls.dim; i++)
+	{   AliasDeclaration *ad = (AliasDeclaration *)aliasdecls.data[i];
+
+	    //printf("\tImport alias semantic('%s')\n", s->toChars());
+	    if (!mod->search(loc, (Identifier *)names.data[i], 0))
+		error("%s not found", ((Identifier *)names.data[i])->toChars());
+
+	    ad->importprot = protection;
+	    ad->semantic(sc);
+	}
+	sc = sc->pop();
+    }
+    //printf("-Import::semantic('%s'), pkg = %p\n", toChars(), pkg);
+
+
+    if (global.params.moduleDeps != NULL) {
+	char fnameBuf[262];		// MAX_PATH+2
+
+	OutBuffer *const ob = global.params.moduleDeps;
+	ob->printf("%s (%s) : ",
+	    sc->module->toPrettyChars(),
+	    escapePath(sc->module->srcfile->toChars(), fnameBuf, sizeof(fnameBuf) / sizeof(*fnameBuf))
+	);
+
+	char* protStr = "";
+	switch (sc->protection) {
+	    case PROTpublic: protStr = "public"; break;
+	    case PROTprivate: protStr = "private"; break;
+	    case PROTpackage: protStr = "package"; break;
+	    default: break;
+	}
+	ob->writestring(protStr);
+	if (isstatic) {
+	    ob->writestring(" static");
+	}
+	ob->writestring(" : ");
+
+	if (this->packages) {
+	    for (size_t i = 0; i < this->packages->dim; i++) {
+		Identifier *pid = (Identifier *)this->packages->data[i];
+		ob->printf("%s.", pid->toChars());
+	    }
+	}
+
+	ob->printf("%s (%s)",
+	    this->id->toChars(),
+	    mod ? escapePath(mod->srcfile->toChars(), fnameBuf, sizeof(fnameBuf) / sizeof(*fnameBuf)) : "???"
+	);
+
+	if (aliasId) {
+	    ob->printf(" -> %s", aliasId->toChars());
+	} else {
+	    if (names.dim > 0) {
+		ob->writestring(" : ");
+		for (size_t i = 0; i < names.dim; i++)
+		{
+		    if (i > 0) {
+			ob->writebyte(',');
+		    }
+
+		    Identifier *name = (Identifier *)names.data[i];
+		    Identifier *alias = (Identifier *)aliases.data[i];
+
+		    if (!alias) {
+			ob->printf("%s", name->toChars());
+			alias = name;
+		    } else {
+			ob->printf("%s=%s", alias->toChars(), name->toChars());
+		    }
+		}
+	    }
+	}
+
+	ob->writenl();
+    }
+}
+
+void Import::semantic2(Scope *sc)
+{
+    //printf("Import::semantic2('%s')\n", toChars());
+    mod->semantic2();
+    if (mod->needmoduleinfo)
+	sc->module->needmoduleinfo = 1;
+}
+
+Dsymbol *Import::toAlias()
+{
+    if (aliasId)
+	return mod;
+    return this;
+}
+
+/*****************************
+ * Add import to sd's symbol table.
+ */
+
+int Import::addMember(Scope *sc, ScopeDsymbol *sd, int memnum)
+{
+    int result = 0;
+
+    if (names.dim == 0)
+	return Dsymbol::addMember(sc, sd, memnum);
+
+    if (aliasId)
+	result = Dsymbol::addMember(sc, sd, memnum);
+
+    /* Instead of adding the import to sd's symbol table,
+     * add each of the alias=name pairs
+     */
+    for (size_t i = 0; i < names.dim; i++)
+    {
+	Identifier *name = (Identifier *)names.data[i];
+	Identifier *alias = (Identifier *)aliases.data[i];
+
+	if (!alias)
+	    alias = name;
+
+	TypeIdentifier *tname = new TypeIdentifier(loc, name);
+	AliasDeclaration *ad = new AliasDeclaration(loc, alias, tname);
+	result |= ad->addMember(sc, sd, memnum);
+
+	aliasdecls.push(ad);
+    }
+
+    return result;
+}
+
+Dsymbol *Import::search(Loc loc, Identifier *ident, int flags)
+{
+    //printf("%s.Import::search(ident = '%s', flags = x%x)\n", toChars(), ident->toChars(), flags);
+
+    if (!pkg)
+    {	load(NULL);
+	mod->semantic();
+    }
+
+    // Forward it to the package/module
+    return pkg->search(loc, ident, flags);
+}
+
+int Import::overloadInsert(Dsymbol *s)
+{
+    // Allow multiple imports of the same name
+    return s->isImport() != NULL;
+}
+
+void Import::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    if (hgs->hdrgen && id == Id::object)
+	return;		// object is imported by default
+
+    if (isstatic)
+	buf->writestring("static ");
+    buf->writestring("import ");
+    if (aliasId)
+    {
+	buf->printf("%s = ", aliasId->toChars());
+    }
+    if (packages && packages->dim)
+    {
+	for (size_t i = 0; i < packages->dim; i++)
+	{   Identifier *pid = (Identifier *)packages->data[i];
+
+	    buf->printf("%s.", pid->toChars());
+	}
+    }
+    buf->printf("%s", id->toChars());
+    if (names.dim > 0) {
+	buf->writebyte(':');
+	for (size_t i = 0; i < names.dim; i++)
+	{
+	    if (i > 0) {
+		    buf->writebyte(',');
+	    }
+
+	    Identifier *name = (Identifier *)names.data[i];
+	    Identifier *alias = (Identifier *)aliases.data[i];
+
+	    if (!alias) {
+		buf->printf("%s", name->toChars());
+		alias = name;
+	    } else {
+		buf->printf("%s=%s", alias->toChars(), name->toChars());
+	    }
+	}
+    }
+    buf->writebyte(';');
+    buf->writenl();
+}
+
--- a/dmd2/inifile.c	Mon Jun 01 01:28:18 2009 +0200
+++ b/dmd2/inifile.c	Mon Jun 01 19:02:20 2009 +0100
@@ -1,300 +1,316 @@
-
-// Copyright (c) 1999-2006 by Digital Mars
-// All Rights Reserved
-// written by Walter Bright
-// http://www.digitalmars.com
-
-
-#include	<stdio.h>
-#include	<string.h>
-#include	<stdlib.h>
-#include	<ctype.h>
-
-#include	"root.h"
-#include	"mem.h"
-
-#ifdef __MINGW32__
-#include <malloc.h>
-#endif
-
-#define LOG	0
-
-char *skipspace(const char *p);
-
-#if __GNUC__
-char *strupr(char *s)
-{
-    char *t = s;
-    
-    while (*s)
-    {
-	*s = toupper(*s);
-	s++;
-    }
-
-    return t;
-}
-#endif /* unix */
-
-/*****************************
- * Read and analyze .ini file.
- * Input:
- *	argv0	program name (argv[0])
- *	inifile	.ini file name
- */
-
-void inifile(char *argv0x, const char *inifilex)
-{
-    char *argv0 = (char *)argv0x;
-    char *inifile = (char *)inifilex;	// do const-correct later
-    char *path;		// need path for @P macro
-    char *filename;
-    OutBuffer buf;
-    int i;
-    int k;
-    int envsection = 0;
-
-#if LOG
-    printf("inifile(argv0 = '%s', inifile = '%s')\n", argv0, inifile);
-#endif
-    if (FileName::absolute(inifile))
-    {
-	filename = inifile;
-    }
-    else
-    {
-	/* Look for inifile in the following sequence of places:
-	 *	o current directory
-	 *	o home directory
-	 *	o directory off of argv0
-	 *	o /etc/
-	 */
-	if (FileName::exists(inifile))
-	{
-	    filename = inifile;
-	}
-	else
-	{
-	    filename = FileName::combine(getenv("HOME"), inifile);
-	    if (!FileName::exists(filename))
-	    {
-		filename = FileName::replaceName(argv0, inifile);
-		if (!FileName::exists(filename))
-		{
-#if POSIX
-
-#if 0
-#if __GLIBC__	    // This fix by Thomas Kuehne
-		    /* argv0 might be a symbolic link,
-		     * so try again looking past it to the real path
-		     */
-		    char* real_argv0 = realpath(argv0, NULL);
-		    if (real_argv0)
-		    {
-			filename = FileName::replaceName(real_argv0, inifile);
-			free(real_argv0);
-			if (FileName::exists(filename))
-			    goto Ldone;
-		    }
-#else
-#error use of glibc non-standard extension realpath(char*, NULL)
-#endif
-#endif
-
-	// old way; problem is that argv0 might not be on the PATH at all
-	// and some other instance might be found
-
-		    // Search PATH for argv0
-		    const char *p = getenv("PATH");
-		    Array *paths = FileName::splitPath(p);
-		    filename = FileName::searchPath(paths, argv0, 0);
-		    if (!filename)
-			goto Letc;		// argv0 not found on path
-		    filename = FileName::replaceName(filename, inifile);
-		    if (FileName::exists(filename))
-			goto Ldone;
-#endif
-
-		    // Search /etc/ for inifile
-		Letc:
-		    filename = FileName::combine((char *)"/etc/", inifile);
-
-		Ldone:
-		    ;
-		}
-	    }
-	}
-    }
-    path = FileName::path(filename);
-#if LOG
-    printf("\tpath = '%s', filename = '%s'\n", path, filename);
-#endif
-
-    File file(filename);
-
-    if (file.read())
-	return;			// error reading file
-
-    // Parse into lines
-    int eof = 0;
-    for (i = 0; i < file.len && !eof; i++)
-    {
-	int linestart = i;
-
-	for (; i < file.len; i++)
-	{
-	    switch (file.buffer[i])
-	    {
-		case '\r':
-		    break;
-
-		case '\n':
-		    // Skip if it was preceded by '\r'
-		    if (i && file.buffer[i - 1] == '\r')
-			goto Lskip;
-		    break;
-
-		case 0:
-		case 0x1A:
-		    eof = 1;
-		    break;
-
-		default:
-		    continue;
-	    }
-	    break;
-	}
-
-	// The line is file.buffer[linestart..i]
-	char *line;
-	int len;
-	char *p;
-	char *pn;
-
-	line = (char *)&file.buffer[linestart];
-	len = i - linestart;
-
-	buf.reset();
-
-	// First, expand the macros.
-	// Macros are bracketed by % characters.
-
-	for (k = 0; k < len; k++)
-	{
-	    if (line[k] == '%')
-	    {
-		int j;
-
-		for (j = k + 1; j < len; j++)
-		{
-		    if (line[j] == '%')
-		    {
-			if (j - k == 3 && memicmp(&line[k + 1], "@P", 2) == 0)
-			{
-			    // %@P% is special meaning the path to the .ini file
-			    p = path;
-			    if (!*p)
-				p = (char *)".";
-			}
-			else
-			{   int len = j - k;
-			    char tmp[10];	// big enough most of the time
-
-			    if (len <= sizeof(tmp))
-				p = tmp;
-			    else
-				p = (char *)alloca(len);
-			    len--;
-			    memcpy(p, &line[k + 1], len);
-			    p[len] = 0;
-			    strupr(p);
-			    p = getenv(p);
-			    if (!p)
-				p = (char *)"";
-			}
-			buf.writestring(p);
-			k = j;
-			goto L1;
-		    }
-		}
-	    }
-	    buf.writeByte(line[k]);
-	 L1:
-	    ;
-	}
-
-	// Remove trailing spaces
-	while (buf.offset && isspace(buf.data[buf.offset - 1]))
-	    buf.offset--;
-
-	p = buf.toChars();
-
-	// The expanded line is in p.
-	// Now parse it for meaning.
-
-	p = skipspace(p);
-	switch (*p)
-	{
-	    case ';':		// comment
-	    case 0:		// blank
-		break;
-
-	    case '[':		// look for [Environment]
-		p = skipspace(p + 1);
-		for (pn = p; isalnum(*pn); pn++)
-		    ;
-		if (pn - p == 11 &&
-		    memicmp(p, "Environment", 11) == 0 &&
-		    *skipspace(pn) == ']'
-		   )
-		    envsection = 1;
-		else
-		    envsection = 0;
-		break;
-
-	    default:
-		if (envsection)
-		{
-		    pn = p;
-
-		    // Convert name to upper case;
-		    // remove spaces bracketing =
-		    for (p = pn; *p; p++)
-		    {   if (islower(*p))
-			    *p &= ~0x20;
-			else if (isspace(*p))
-			    memmove(p, p + 1, strlen(p));
-			else if (*p == '=')
-			{
-			    p++;
-			    while (isspace(*p))
-				memmove(p, p + 1, strlen(p));
-			    break;
-			}
-		    }
-
-		    putenv(strdup(pn));
-#if LOG
-		    printf("\tputenv('%s')\n", pn);
-		    //printf("getenv(\"TEST\") = '%s'\n",getenv("TEST"));
-#endif
-		}
-		break;
-	}
-
-     Lskip:
-	;
-    }
-}
-
-/********************
- * Skip spaces.
- */
-
-char *skipspace(const char *p)
-{
-    while (isspace(*p))
-	p++;
-    return (char *)p;
-}
-
+/*
+ * Some portions copyright (c) 1994-1995 by Symantec
+ * Copyright (c) 1999-2009 by Digital Mars
+ * All Rights Reserved
+ * http://www.digitalmars.com
+ * Written by Walter Bright
+ *
+ * This source file is made available for personal use
+ * only. The license is in /dmd/src/dmd/backendlicense.txt
+ * For any other uses, please contact Digital Mars.
+ */
+
+#include	<stdio.h>
+#include	<string.h>
+#include	<stdlib.h>
+#include	<ctype.h>
+
+#if __APPLE__
+#include	<sys/syslimits.h>
+#endif
+#if __FreeBSD__ || __sun&&__SVR4
+// for PATH_MAX
+#include	<limits.h>
+#endif
+
+#if __sun&&__SVR4
+#include	<alloca.h>
+#endif
+
+#include	"root.h"
+#include	"rmem.h"
+
+#define LOG	0
+
+char *skipspace(const char *p);
+
+#if __GNUC__
+char *strupr(char *s)
+{
+    char *t = s;
+    
+    while (*s)
+    {
+	*s = toupper(*s);
+	s++;
+    }
+
+    return t;
+}
+#endif /* unix */
+
+/*****************************
+ * Read and analyze .ini file.
+ * Input:
+ *	argv0	program name (argv[0])
+ *	inifile	.ini file name
+ */
+
+void inifile(const char *argv0x, const char *inifilex)
+{
+    char *argv0 = (char *)argv0x;
+    char *inifile = (char *)inifilex;	// do const-correct later
+    char *path;		// need path for @P macro
+    char *filename;
+    OutBuffer buf;
+    int i;
+    int k;
+    int envsection = 0;
+
+#if LOG
+    printf("inifile(argv0 = '%s', inifile = '%s')\n", argv0, inifile);
+#endif
+    if (FileName::absolute(inifile))
+    {
+	filename = inifile;
+    }
+    else
+    {
+	/* Look for inifile in the following sequence of places:
+	 *	o current directory
+	 *	o home directory
+	 *	o directory off of argv0
+	 *	o /etc/
+	 */
+	if (FileName::exists(inifile))
+	{
+	    filename = inifile;
+	}
+	else
+	{
+	    filename = FileName::combine(getenv("HOME"), inifile);
+	    if (!FileName::exists(filename))
+	    {
+		filename = (char *)FileName::replaceName(argv0, inifile);
+		if (!FileName::exists(filename))
+		{
+#if linux || __APPLE__ || __FreeBSD__ || __sun&&__SVR4
+#if __GLIBC__ || __APPLE__ || __FreeBSD__ || __sun&&__SVR4   // This fix by Thomas Kuehne
+		    /* argv0 might be a symbolic link,
+		     * so try again looking past it to the real path
+		     */
+#if __APPLE__ || __FreeBSD__ || __sun&&__SVR4
+		    char resolved_name[PATH_MAX + 1];
+		    char* real_argv0 = realpath(argv0, resolved_name);
+#else
+		    char* real_argv0 = realpath(argv0, NULL);
+#endif
+		    //printf("argv0 = %s, real_argv0 = %p\n", argv0, real_argv0);
+		    if (real_argv0)
+		    {
+			filename = (char *)FileName::replaceName(real_argv0, inifile);
+#if !(__APPLE__ || __FreeBSD__ || __sun&&__SVR4)
+			free(real_argv0);
+#endif
+			if (FileName::exists(filename))
+			    goto Ldone;
+		    }
+#else
+#error use of glibc non-standard extension realpath(char*, NULL)
+#endif
+		    if (1){
+		    // Search PATH for argv0
+		    const char *p = getenv("PATH");
+		    Array *paths = FileName::splitPath(p);
+		    filename = FileName::searchPath(paths, argv0, 0);
+		    if (!filename)
+			goto Letc;		// argv0 not found on path
+		    filename = (char *)FileName::replaceName(filename, inifile);
+		    if (FileName::exists(filename))
+			goto Ldone;
+		    }
+#endif
+
+		    // Search /etc/ for inifile
+		Letc:
+		    filename = FileName::combine((char *)"/etc/", inifile);
+
+		Ldone:
+		    ;
+		}
+	    }
+	}
+    }
+    path = FileName::path(filename);
+#if LOG
+    printf("\tpath = '%s', filename = '%s'\n", path, filename);
+#endif
+
+    File file(filename);
+
+    if (file.read())
+	return;			// error reading file
+
+    // Parse into lines
+    int eof = 0;
+    for (i = 0; i < file.len && !eof; i++)
+    {
+	int linestart = i;
+
+	for (; i < file.len; i++)
+	{
+	    switch (file.buffer[i])
+	    {
+		case '\r':
+		    break;
+
+		case '\n':
+		    // Skip if it was preceded by '\r'
+		    if (i && file.buffer[i - 1] == '\r')
+			goto Lskip;
+		    break;
+
+		case 0:
+		case 0x1A:
+		    eof = 1;
+		    break;
+
+		default:
+		    continue;
+	    }
+	    break;
+	}
+
+	// The line is file.buffer[linestart..i]
+	char *line;
+	int len;
+	char *p;
+	char *pn;
+
+	line = (char *)&file.buffer[linestart];
+	len = i - linestart;
+
+	buf.reset();
+
+	// First, expand the macros.
+	// Macros are bracketed by % characters.
+
+	for (k = 0; k < len; k++)
+	{
+	    if (line[k] == '%')
+	    {
+		int j;
+
+		for (j = k + 1; j < len; j++)
+		{
+		    if (line[j] == '%')
+		    {
+			if (j - k == 3 && memicmp(&line[k + 1], "@P", 2) == 0)
+			{
+			    // %@P% is special meaning the path to the .ini file
+			    p = path;
+			    if (!*p)
+				p = (char *)".";
+			}
+			else
+			{   int len = j - k;
+			    char tmp[10];	// big enough most of the time
+
+			    if (len <= sizeof(tmp))
+				p = tmp;
+			    else
+				p = (char *)alloca(len);
+			    len--;
+			    memcpy(p, &line[k + 1], len);
+			    p[len] = 0;
+			    strupr(p);
+			    p = getenv(p);
+			    if (!p)
+				p = (char *)"";
+			}
+			buf.writestring(p);
+			k = j;
+			goto L1;
+		    }
+		}
+	    }
+	    buf.writeByte(line[k]);
+	 L1:
+	    ;
+	}
+
+	// Remove trailing spaces
+	while (buf.offset && isspace(buf.data[buf.offset - 1]))
+	    buf.offset--;
+
+	p = buf.toChars();
+
+	// The expanded line is in p.
+	// Now parse it for meaning.
+
+	p = skipspace(p);
+	switch (*p)
+	{
+	    case ';':		// comment
+	    case 0:		// blank
+		break;
+
+	    case '[':		// look for [Environment]
+		p = skipspace(p + 1);
+		for (pn = p; isalnum(*pn); pn++)
+		    ;
+		if (pn - p == 11 &&
+		    memicmp(p, "Environment", 11) == 0 &&
+		    *skipspace(pn) == ']'
+		   )
+		    envsection = 1;
+		else
+		    envsection = 0;
+		break;
+
+	    default:
+		if (envsection)
+		{
+		    pn = p;
+
+		    // Convert name to upper case;
+		    // remove spaces bracketing =
+		    for (p = pn; *p; p++)
+		    {   if (islower(*p))
+			    *p &= ~0x20;
+			else if (isspace(*p))
+			    memmove(p, p + 1, strlen(p));
+			else if (*p == '=')
+			{
+			    p++;
+			    while (isspace(*p))
+				memmove(p, p + 1, strlen(p));
+			    break;
+			}
+		    }
+
+		    putenv(strdup(pn));
+#if LOG
+		    printf("\tputenv('%s')\n", pn);
+		    //printf("getenv(\"TEST\") = '%s'\n",getenv("TEST"));
+#endif
+		}
+		break;
+	}
+
+     Lskip:
+	;
+    }
+}
+
+/********************
+ * Skip spaces.
+ */
+
+char *skipspace(const char *p)
+{
+    while (isspace(*p))
+	p++;
+    return (char *)p;
+}
+
--- a/dmd2/init.c	Mon Jun 01 01:28:18 2009 +0200
+++ b/dmd2/init.c	Mon Jun 01 19:02:20 2009 +0100
@@ -1,598 +1,599 @@
-
-// Compiler implementation of the D programming language
-// Copyright (c) 1999-2007 by Digital Mars
-// All Rights Reserved
-// written by Walter Bright
-// http://www.digitalmars.com
-// License for redistribution is by either the Artistic License
-// in artistic.txt, or the GNU General Public License in gnu.txt.
-// See the included readme.txt for details.
-
-#include <stdio.h>
-#include <assert.h>
-
-#include "mars.h"
-#include "init.h"
-#include "expression.h"
-#include "statement.h"
-#include "identifier.h"
-#include "declaration.h"
-#include "aggregate.h"
-#include "scope.h"
-#include "mtype.h"
-#include "hdrgen.h"
-
-/********************************** Initializer *******************************/
-
-Initializer::Initializer(Loc loc)
-{
-    this->loc = loc;
-}
-
-Initializer *Initializer::syntaxCopy()
-{
-    return this;
-}
-
-Initializer *Initializer::semantic(Scope *sc, Type *t)
-{
-    return this;
-}
-
-Type *Initializer::inferType(Scope *sc)
-{
-    error(loc, "cannot infer type from initializer");
-    return Type::terror;
-}
-
-Initializers *Initializer::arraySyntaxCopy(Initializers *ai)
-{   Initializers *a = NULL;
-
-    if (ai)
-    {
-	a = new Initializers();
-	a->setDim(ai->dim);
-	for (int i = 0; i < a->dim; i++)
-	{   Initializer *e = (Initializer *)ai->data[i];
-
-	    e = e->syntaxCopy();
-	    a->data[i] = e;
-	}
-    }
-    return a;
-}
-
-char *Initializer::toChars()
-{   OutBuffer *buf;
-    HdrGenState hgs;
-
-    memset(&hgs, 0, sizeof(hgs));
-    buf = new OutBuffer();
-    toCBuffer(buf, &hgs);
-    return buf->toChars();
-}
-
-/********************************** VoidInitializer ***************************/
-
-VoidInitializer::VoidInitializer(Loc loc)
-    : Initializer(loc)
-{
-    type = NULL;
-}
-
-
-Initializer *VoidInitializer::syntaxCopy()
-{
-    return new VoidInitializer(loc);
-}
-
-
-Initializer *VoidInitializer::semantic(Scope *sc, Type *t)
-{
-    //printf("VoidInitializer::semantic(t = %p)\n", t);
-    type = t;
-    return this;
-}
-
-
-Expression *VoidInitializer::toExpression()
-{
-    error(loc, "void initializer has no value");
-    return new IntegerExp(0);
-}
-
-
-void VoidInitializer::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{
-    buf->writestring("void");
-}
-
-
-/********************************** StructInitializer *************************/
-
-StructInitializer::StructInitializer(Loc loc)
-    : Initializer(loc)
-{
-    ad = NULL;
-}
-
-Initializer *StructInitializer::syntaxCopy()
-{
-    StructInitializer *ai = new StructInitializer(loc);
-
-    assert(field.dim == value.dim);
-    ai->field.setDim(field.dim);
-    ai->value.setDim(value.dim);
-    for (int i = 0; i < field.dim; i++)
-    {    
-	ai->field.data[i] = field.data[i];
-
-	Initializer *init = (Initializer *)value.data[i];
-	init = init->syntaxCopy();
-	ai->value.data[i] = init;
-    }
-    return ai;
-}
-
-void StructInitializer::addInit(Identifier *field, Initializer *value)
-{
-    //printf("StructInitializer::addInit(field = %p, value = %p)\n", field, value);
-    this->field.push(field);
-    this->value.push(value);
-}
-
-Initializer *StructInitializer::semantic(Scope *sc, Type *t)
-{
-    TypeStruct *ts;
-    int errors = 0;
-
-    //printf("StructInitializer::semantic(t = %s) %s\n", t->toChars(), toChars());
-    vars.setDim(field.dim);
-    t = t->toBasetype();
-    if (t->ty == Tstruct)
-    {	unsigned i;
-	unsigned fieldi = 0;
-
-	ts = (TypeStruct *)t;
-	ad = ts->sym;
-	for (i = 0; i < field.dim; i++)
-	{
-	    Identifier *id = (Identifier *)field.data[i];
-	    Initializer *val = (Initializer *)value.data[i];
-	    Dsymbol *s;
-	    VarDeclaration *v;
-
-	    if (id == NULL)
-	    {
-		if (fieldi >= ad->fields.dim)
-		{   error(loc, "too many initializers for %s", ad->toChars());
-		    field.remove(i);
-		    i--;
-		    continue;
-		}
-		else
-		{
-		    s = (Dsymbol *)ad->fields.data[fieldi];
-		}
-	    }
-	    else
-	    {
-		//s = ad->symtab->lookup(id);
-		s = ad->search(loc, id, 0);
-		if (!s)
-		{
-		    error(loc, "'%s' is not a member of '%s'", id->toChars(), t->toChars());
-		    continue;
-		}
-
-		// Find out which field index it is
-		for (fieldi = 0; 1; fieldi++)
-		{
-		    if (fieldi >= ad->fields.dim)
-		    {
-			s->error("is not a per-instance initializable field");
-			break;
-		    }
-		    if (s == (Dsymbol *)ad->fields.data[fieldi])
-			break;
-		}
-	    }
-	    if (s && (v = s->isVarDeclaration()) != NULL)
-	    {
-		val = val->semantic(sc, v->type);
-		value.data[i] = (void *)val;
-		vars.data[i] = (void *)v;
-	    }
-	    else
-	    {	error(loc, "%s is not a field of %s", id ? id->toChars() : s->toChars(), ad->toChars());
-		errors = 1;
-	    }
-	    fieldi++;
-	}
-    }
-    else if (t->ty == Tdelegate && value.dim == 0)
-    {	/* Rewrite as empty delegate literal { }
-	 */
-	Arguments *arguments = new Arguments;
-	Type *tf = new TypeFunction(arguments, NULL, 0, LINKd);
-	FuncLiteralDeclaration *fd = new FuncLiteralDeclaration(loc, 0, tf, TOKdelegate, NULL);
-	fd->fbody = new CompoundStatement(loc, new Statements());
-	fd->endloc = loc;
-	Expression *e = new FuncExp(loc, fd);
-	ExpInitializer *ie = new ExpInitializer(loc, e);
-	return ie->semantic(sc, t);
-    }
-    else
-    {
-	error(loc, "a struct is not a valid initializer for a %s", t->toChars());
-	errors = 1;
-    }
-    if (errors)
-    {
-	field.setDim(0);
-	value.setDim(0);
-	vars.setDim(0);
-    }
-    return this;
-}
-
-
-/***************************************
- * This works by transforming a struct initializer into
- * a struct literal. In the future, the two should be the
- * same thing.
- */
-Expression *StructInitializer::toExpression()
-{   Expression *e;
-
-    //printf("StructInitializer::toExpression() %s\n", toChars());
-    if (!ad)				// if fwd referenced
-    {
-	return NULL;
-    }
-    StructDeclaration *sd = ad->isStructDeclaration();
-    if (!sd)
-	return NULL;
-    Expressions *elements = new Expressions();
-    for (size_t i = 0; i < value.dim; i++)
-    {
-	if (field.data[i])
-	    goto Lno;
-	Initializer *iz = (Initializer *)value.data[i];
-	if (!iz)
-	    goto Lno;
-	Expression *ex = iz->toExpression();
-	if (!ex)
-	    goto Lno;
-	elements->push(ex);
-    }
-    e = new StructLiteralExp(loc, sd, elements);
-    e->type = sd->type;
-    return e;
-
-Lno:
-    delete elements;
-    //error(loc, "struct initializers as expressions are not allowed");
-    return NULL;
-}
-
-
-void StructInitializer::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{
-    //printf("StructInitializer::toCBuffer()\n");
-    buf->writebyte('{');
-    for (int i = 0; i < field.dim; i++)
-    {
-        if (i > 0)
-	    buf->writebyte(',');
-        Identifier *id = (Identifier *)field.data[i];
-        if (id)
-        {
-            buf->writestring(id->toChars());
-            buf->writebyte(':');
-        }
-        Initializer *iz = (Initializer *)value.data[i];
-        if (iz)
-            iz->toCBuffer(buf, hgs);
-    }
-    buf->writebyte('}');
-}
-
-/********************************** ArrayInitializer ************************************/
-
-ArrayInitializer::ArrayInitializer(Loc loc)
-    : Initializer(loc)
-{
-    dim = 0;
-    type = NULL;
-    sem = 0;
-}
-
-Initializer *ArrayInitializer::syntaxCopy()
-{
-    //printf("ArrayInitializer::syntaxCopy()\n");
-
-    ArrayInitializer *ai = new ArrayInitializer(loc);
-
-    assert(index.dim == value.dim);
-    ai->index.setDim(index.dim);
-    ai->value.setDim(value.dim);
-    for (int i = 0; i < ai->value.dim; i++)
-    {	Expression *e = (Expression *)index.data[i];
-	if (e)
-	    e = e->syntaxCopy();
-	ai->index.data[i] = e;
-
-	Initializer *init = (Initializer *)value.data[i];
-	init = init->syntaxCopy();
-	ai->value.data[i] = init;
-    }
-    return ai;
-}
-
-void ArrayInitializer::addInit(Expression *index, Initializer *value)
-{
-    this->index.push(index);
-    this->value.push(value);
-    dim = 0;
-    type = NULL;
-}
-
-Initializer *ArrayInitializer::semantic(Scope *sc, Type *t)
-{   unsigned i;
-    unsigned length;
-
-    //printf("ArrayInitializer::semantic(%s)\n", t->toChars());
-    if (sem)				// if semantic() already run
-	return this;
-    sem = 1;
-    type = t;
-    t = t->toBasetype();
-    switch (t->ty)
-    {
-	case Tpointer:
-	case Tsarray:
-	case Tarray:
-	    break;
-
-	default:
-	    error(loc, "cannot use array to initialize %s", type->toChars());
-	    return this;
-    }
-
-    length = 0;
-    for (i = 0; i < index.dim; i++)
-    {	Expression *idx;
-	Initializer *val;
-
-	idx = (Expression *)index.data[i];
-	if (idx)
-	{   idx = idx->semantic(sc);
-	    idx = idx->optimize(WANTvalue | WANTinterpret);
-	    index.data[i] = (void *)idx;
-	    length = idx->toInteger();
-	}
-
-	val = (Initializer *)value.data[i];
-	val = val->semantic(sc, t->nextOf());
-	value.data[i] = (void *)val;
-	length++;
-	if (length == 0)
-	    error(loc, "array dimension overflow");
-	if (length > dim)
-	    dim = length;
-    }
-    unsigned long amax = 0x80000000;
-    if ((unsigned long) dim * t->nextOf()->size() >= amax)
-	error(loc, "array dimension %u exceeds max of %ju", dim, amax / t->nextOf()->size());
-    return this;
-}
-
-/********************************
- * If possible, convert array initializer to array literal.
- */
-
-Expression *ArrayInitializer::toExpression()
-{   Expressions *elements;
-    Expression *e;
-
-    //printf("ArrayInitializer::toExpression()\n");
-    //static int i; if (++i == 2) halt();
-    elements = new Expressions();
-    for (size_t i = 0; i < value.dim; i++)
-    {
-	if (index.data[i])
-	    goto Lno;
-	Initializer *iz = (Initializer *)value.data[i];
-	if (!iz)
-	    goto Lno;
-	Expression *ex = iz->toExpression();
-	if (!ex)
-	    goto Lno;
-	elements->push(ex);
-    }
-    e = new ArrayLiteralExp(loc, elements);
-    e->type = type;
-    return e;
-
-Lno:
-    delete elements;
-    error(loc, "array initializers as expressions are not allowed");
-    return NULL;
-}
-
-
-/********************************
- * If possible, convert array initializer to associative array initializer.
- */
-
-Initializer *ArrayInitializer::toAssocArrayInitializer()
-{   Expressions *keys;
-    Expressions *values;
-    Expression *e;
-
-    //printf("ArrayInitializer::toAssocArrayInitializer()\n");
-    //static int i; if (++i == 2) halt();
-    keys = new Expressions();
-    keys->setDim(value.dim);
-    values = new Expressions();
-    values->setDim(value.dim);
-
-    for (size_t i = 0; i < value.dim; i++)
-    {
-	e = (Expression *)index.data[i];
-	if (!e)
-	    goto Lno;
-	keys->data[i] = (void *)e;
-
-	Initializer *iz = (Initializer *)value.data[i];
-	if (!iz)
-	    goto Lno;
-	e = iz->toExpression();
-	if (!e)
-	    goto Lno;
-	values->data[i] = (void *)e;
-    }
-    e = new AssocArrayLiteralExp(loc, keys, values);
-    return new ExpInitializer(loc, e);
-
-Lno:
-    delete keys;
-    delete values;
-    error(loc, "not an associative array initializer");
-    return this;
-}
-
-
-Type *ArrayInitializer::inferType(Scope *sc)
-{
-    for (size_t i = 0; i < value.dim; i++)
-    {
-	if (index.data[i])
-	    goto Lno;
-    }
-    if (value.dim)
-    {
-	Initializer *iz = (Initializer *)value.data[0];
-	if (iz)
-	{   Type *t = iz->inferType(sc);
-	    t = new TypeSArray(t, new IntegerExp(value.dim));
-	    t = t->semantic(loc, sc);
-	    return t;
-	}
-    }
-
-Lno:
-    error(loc, "cannot infer type from this array initializer");
-    return Type::terror;
-}
-
-
-void ArrayInitializer::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{
-    buf->writebyte('[');
-    for (int i = 0; i < index.dim; i++)
-    {
-        if (i > 0)
-	    buf->writebyte(',');
-        Expression *ex = (Expression *)index.data[i];
-        if (ex)
-        {
-            ex->toCBuffer(buf, hgs);
-            buf->writebyte(':');
-        }
-        Initializer *iz = (Initializer *)value.data[i];
-        if (iz)
-            iz->toCBuffer(buf, hgs);
-    }
-    buf->writebyte(']');
-}
-
-
-/********************************** ExpInitializer ************************************/
-
-ExpInitializer::ExpInitializer(Loc loc, Expression *exp)
-    : Initializer(loc)
-{
-    this->exp = exp;
-}
-
-Initializer *ExpInitializer::syntaxCopy()
-{
-    return new ExpInitializer(loc, exp->syntaxCopy());
-}
-
-Initializer *ExpInitializer::semantic(Scope *sc, Type *t)
-{
-    //printf("ExpInitializer::semantic(%s), type = %s\n", exp->toChars(), t->toChars());
-    exp = exp->semantic(sc);
-    exp = resolveProperties(sc, exp);
-    exp = exp->optimize(WANTvalue | WANTinterpret);
-    Type *tb = t->toBasetype();
-
-    /* Look for case of initializing a static array with a too-short
-     * string literal, such as:
-     *	char[5] foo = "abc";
-     * Allow this by doing an explicit cast, which will lengthen the string
-     * literal.
-     */
-    if (exp->op == TOKstring && tb->ty == Tsarray && exp->type->ty == Tsarray)
-    {	StringExp *se = (StringExp *)exp;
-
-	if (!se->committed && se->type->ty == Tsarray &&
-	    ((TypeSArray *)se->type)->dim->toInteger() <
-	    ((TypeSArray *)t)->dim->toInteger())
-	{
-	    exp = se->castTo(sc, t);
-	    goto L1;
-	}
-    }
-
-    // Look for the case of statically initializing an array
-    // with a single member.
-    if (tb->ty == Tsarray &&
-	!tb->nextOf()->equals(exp->type->toBasetype()->nextOf()) &&
-	exp->implicitConvTo(tb->nextOf())
-       )
-    {
-	t = tb->nextOf();
-    }
-
-    exp = exp->implicitCastTo(sc, t);
-L1:
-    exp = exp->optimize(WANTvalue | WANTinterpret);
-    //printf("-ExpInitializer::semantic(): "); exp->print();
-    return this;
-}
-
-Type *ExpInitializer::inferType(Scope *sc)
-{
-    //printf("ExpInitializer::inferType() %s\n", toChars());
-    exp = exp->semantic(sc);
-    exp = resolveProperties(sc, exp);
-
-    // 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());
-    }
-
-    Type *t = exp->type;
-    return t;
-    //return t->ty == Tsarray ? t : t->toHeadMutable();
-}
-
-Expression *ExpInitializer::toExpression()
-{
-    return exp;
-}
-
-
-void ExpInitializer::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{
-    exp->toCBuffer(buf, hgs);
-}
-
-
-
+
+// Compiler implementation of the D programming language
+// Copyright (c) 1999-2009 by Digital Mars
+// All Rights Reserved
+// written by Walter Bright
+// http://www.digitalmars.com
+// License for redistribution is by either the Artistic License
+// in artistic.txt, or the GNU General Public License in gnu.txt.
+// See the included readme.txt for details.
+
+#include <stdio.h>
+#include <assert.h>
+
+#include "mars.h"
+#include "init.h"
+#include "expression.h"
+#include "statement.h"
+#include "identifier.h"
+#include "declaration.h"
+#include "aggregate.h"
+#include "scope.h"
+#include "mtype.h"
+#include "hdrgen.h"
+
+/********************************** Initializer *******************************/
+
+Initializer::Initializer(Loc loc)
+{
+    this->loc = loc;
+}
+
+Initializer *Initializer::syntaxCopy()
+{
+    return this;
+}
+
+Initializer *Initializer::semantic(Scope *sc, Type *t)
+{
+    return this;
+}
+
+Type *Initializer::inferType(Scope *sc)
+{
+    error(loc, "cannot infer type from initializer");
+    return Type::terror;
+}
+
+Initializers *Initializer::arraySyntaxCopy(Initializers *ai)
+{   Initializers *a = NULL;
+
+    if (ai)
+    {
+	a = new Initializers();
+	a->setDim(ai->dim);
+	for (int i = 0; i < a->dim; i++)
+	{   Initializer *e = (Initializer *)ai->data[i];
+
+	    e = e->syntaxCopy();
+	    a->data[i] = e;
+	}
+    }
+    return a;
+}
+
+char *Initializer::toChars()
+{   OutBuffer *buf;
+    HdrGenState hgs;
+
+    memset(&hgs, 0, sizeof(hgs));
+    buf = new OutBuffer();
+    toCBuffer(buf, &hgs);
+    return buf->toChars();
+}
+
+/********************************** VoidInitializer ***************************/
+
+VoidInitializer::VoidInitializer(Loc loc)
+    : Initializer(loc)
+{
+    type = NULL;
+}
+
+
+Initializer *VoidInitializer::syntaxCopy()
+{
+    return new VoidInitializer(loc);
+}
+
+
+Initializer *VoidInitializer::semantic(Scope *sc, Type *t)
+{
+    //printf("VoidInitializer::semantic(t = %p)\n", t);
+    type = t;
+    return this;
+}
+
+
+Expression *VoidInitializer::toExpression()
+{
+    error(loc, "void initializer has no value");
+    return new IntegerExp(0);
+}
+
+
+void VoidInitializer::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    buf->writestring("void");
+}
+
+
+/********************************** StructInitializer *************************/
+
+StructInitializer::StructInitializer(Loc loc)
+    : Initializer(loc)
+{
+    ad = NULL;
+}
+
+Initializer *StructInitializer::syntaxCopy()
+{
+    StructInitializer *ai = new StructInitializer(loc);
+
+    assert(field.dim == value.dim);
+    ai->field.setDim(field.dim);
+    ai->value.setDim(value.dim);
+    for (int i = 0; i < field.dim; i++)
+    {    
+	ai->field.data[i] = field.data[i];
+
+	Initializer *init = (Initializer *)value.data[i];
+	init = init->syntaxCopy();
+	ai->value.data[i] = init;
+    }
+    return ai;
+}
+
+void StructInitializer::addInit(Identifier *field, Initializer *value)
+{
+    //printf("StructInitializer::addInit(field = %p, value = %p)\n", field, value);
+    this->field.push(field);
+    this->value.push(value);
+}
+
+Initializer *StructInitializer::semantic(Scope *sc, Type *t)
+{
+    TypeStruct *ts;
+    int errors = 0;
+
+    //printf("StructInitializer::semantic(t = %s) %s\n", t->toChars(), toChars());
+    vars.setDim(field.dim);
+    t = t->toBasetype();
+    if (t->ty == Tstruct)
+    {	unsigned i;
+	unsigned fieldi = 0;
+
+	ts = (TypeStruct *)t;
+	ad = ts->sym;
+	for (i = 0; i < field.dim; i++)
+	{
+	    Identifier *id = (Identifier *)field.data[i];
+	    Initializer *val = (Initializer *)value.data[i];
+	    Dsymbol *s;
+	    VarDeclaration *v;
+
+	    if (id == NULL)
+	    {
+		if (fieldi >= ad->fields.dim)
+		{   error(loc, "too many initializers for %s", ad->toChars());
+		    field.remove(i);
+		    i--;
+		    continue;
+		}
+		else
+		{
+		    s = (Dsymbol *)ad->fields.data[fieldi];
+		}
+	    }
+	    else
+	    {
+		//s = ad->symtab->lookup(id);
+		s = ad->search(loc, id, 0);
+		if (!s)
+		{
+		    error(loc, "'%s' is not a member of '%s'", id->toChars(), t->toChars());
+		    continue;
+		}
+
+		// Find out which field index it is
+		for (fieldi = 0; 1; fieldi++)
+		{
+		    if (fieldi >= ad->fields.dim)
+		    {
+			s->error("is not a per-instance initializable field");
+			break;
+		    }
+		    if (s == (Dsymbol *)ad->fields.data[fieldi])
+			break;
+		}
+	    }
+	    if (s && (v = s->isVarDeclaration()) != NULL)
+	    {
+		val = val->semantic(sc, v->type);
+		value.data[i] = (void *)val;
+		vars.data[i] = (void *)v;
+	    }
+	    else
+	    {	error(loc, "%s is not a field of %s", id ? id->toChars() : s->toChars(), ad->toChars());
+		errors = 1;
+	    }
+	    fieldi++;
+	}
+    }
+    else if (t->ty == Tdelegate && value.dim == 0)
+    {	/* Rewrite as empty delegate literal { }
+	 */
+	Arguments *arguments = new Arguments;
+	Type *tf = new TypeFunction(arguments, NULL, 0, LINKd);
+	FuncLiteralDeclaration *fd = new FuncLiteralDeclaration(loc, 0, tf, TOKdelegate, NULL);
+	fd->fbody = new CompoundStatement(loc, new Statements());
+	fd->endloc = loc;
+	Expression *e = new FuncExp(loc, fd);
+	ExpInitializer *ie = new ExpInitializer(loc, e);
+	return ie->semantic(sc, t);
+    }
+    else
+    {
+	error(loc, "a struct is not a valid initializer for a %s", t->toChars());
+	errors = 1;
+    }
+    if (errors)
+    {
+	field.setDim(0);
+	value.setDim(0);
+	vars.setDim(0);
+    }
+    return this;
+}
+
+
+/***************************************
+ * This works by transforming a struct initializer into
+ * a struct literal. In the future, the two should be the
+ * same thing.
+ */
+Expression *StructInitializer::toExpression()
+{   Expression *e;
+
+    //printf("StructInitializer::toExpression() %s\n", toChars());
+    if (!ad)				// if fwd referenced
+    {
+	return NULL;
+    }
+    StructDeclaration *sd = ad->isStructDeclaration();
+    if (!sd)
+	return NULL;
+    Expressions *elements = new Expressions();
+    for (size_t i = 0; i < value.dim; i++)
+    {
+	if (field.data[i])
+	    goto Lno;
+	Initializer *iz = (Initializer *)value.data[i];
+	if (!iz)
+	    goto Lno;
+	Expression *ex = iz->toExpression();
+	if (!ex)
+	    goto Lno;
+	elements->push(ex);
+    }
+    e = new StructLiteralExp(loc, sd, elements);
+    e->type = sd->type;
+    return e;
+
+Lno:
+    delete elements;
+    //error(loc, "struct initializers as expressions are not allowed");
+    return NULL;
+}
+
+
+void StructInitializer::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    //printf("StructInitializer::toCBuffer()\n");
+    buf->writebyte('{');
+    for (int i = 0; i < field.dim; i++)
+    {
+        if (i > 0)
+	    buf->writebyte(',');
+        Identifier *id = (Identifier *)field.data[i];
+        if (id)
+        {
+            buf->writestring(id->toChars());
+            buf->writebyte(':');
+        }
+        Initializer *iz = (Initializer *)value.data[i];
+        if (iz)
+            iz->toCBuffer(buf, hgs);
+    }
+    buf->writebyte('}');
+}
+
+/********************************** ArrayInitializer ************************************/
+
+ArrayInitializer::ArrayInitializer(Loc loc)
+    : Initializer(loc)
+{
+    dim = 0;
+    type = NULL;
+    sem = 0;
+}
+
+Initializer *ArrayInitializer::syntaxCopy()
+{
+    //printf("ArrayInitializer::syntaxCopy()\n");
+
+    ArrayInitializer *ai = new ArrayInitializer(loc);
+
+    assert(index.dim == value.dim);
+    ai->index.setDim(index.dim);
+    ai->value.setDim(value.dim);
+    for (int i = 0; i < ai->value.dim; i++)
+    {	Expression *e = (Expression *)index.data[i];
+	if (e)
+	    e = e->syntaxCopy();
+	ai->index.data[i] = e;
+
+	Initializer *init = (Initializer *)value.data[i];
+	init = init->syntaxCopy();
+	ai->value.data[i] = init;
+    }
+    return ai;
+}
+
+void ArrayInitializer::addInit(Expression *index, Initializer *value)
+{
+    this->index.push(index);
+    this->value.push(value);
+    dim = 0;
+    type = NULL;
+}
+
+Initializer *ArrayInitializer::semantic(Scope *sc, Type *t)
+{   unsigned i;
+    unsigned length;
+
+    //printf("ArrayInitializer::semantic(%s)\n", t->toChars());
+    if (sem)				// if semantic() already run
+	return this;
+    sem = 1;
+    type = t;
+    t = t->toBasetype();
+    switch (t->ty)
+    {
+	case Tpointer:
+	case Tsarray:
+	case Tarray:
+	    break;
+
+	default:
+	    error(loc, "cannot use array to initialize %s", type->toChars());
+	    return this;
+    }
+
+    length = 0;
+    for (i = 0; i < index.dim; i++)
+    {	Expression *idx;
+	Initializer *val;
+
+	idx = (Expression *)index.data[i];
+	if (idx)
+	{   idx = idx->semantic(sc);
+	    idx = idx->optimize(WANTvalue | WANTinterpret);
+	    index.data[i] = (void *)idx;
+	    length = idx->toInteger();
+	}
+
+	val = (Initializer *)value.data[i];
+	val = val->semantic(sc, t->nextOf());
+	value.data[i] = (void *)val;
+	length++;
+	if (length == 0)
+	    error(loc, "array dimension overflow");
+	if (length > dim)
+	    dim = length;
+    }
+    unsigned long amax = 0x80000000;
+    if ((unsigned long) dim * t->nextOf()->size() >= amax)
+	error(loc, "array dimension %u exceeds max of %ju", dim, amax / t->nextOf()->size());
+    return this;
+}
+
+/********************************
+ * If possible, convert array initializer to array literal.
+ */
+
+Expression *ArrayInitializer::toExpression()
+{   Expressions *elements;
+    Expression *e;
+
+    //printf("ArrayInitializer::toExpression()\n");
+    //static int i; if (++i == 2) halt();
+    elements = new Expressions();
+    for (size_t i = 0; i < value.dim; i++)
+    {
+	if (index.data[i])
+	    goto Lno;
+	Initializer *iz = (Initializer *)value.data[i];
+	if (!iz)
+	    goto Lno;
+	Expression *ex = iz->toExpression();
+	if (!ex)
+	    goto Lno;
+	elements->push(ex);
+    }
+    e = new ArrayLiteralExp(loc, elements);
+    e->type = type;
+    return e;
+
+Lno:
+    delete elements;
+    error(loc, "array initializers as expressions are not allowed");
+    return NULL;
+}
+
+
+/********************************
+ * If possible, convert array initializer to associative array initializer.
+ */
+
+Initializer *ArrayInitializer::toAssocArrayInitializer()
+{   Expressions *keys;
+    Expressions *values;
+    Expression *e;
+
+    //printf("ArrayInitializer::toAssocArrayInitializer()\n");
+    //static int i; if (++i == 2) halt();
+    keys = new Expressions();
+    keys->setDim(value.dim);
+    values = new Expressions();
+    values->setDim(value.dim);
+
+    for (size_t i = 0; i < value.dim; i++)
+    {
+	e = (Expression *)index.data[i];
+	if (!e)
+	    goto Lno;
+	keys->data[i] = (void *)e;
+
+	Initializer *iz = (Initializer *)value.data[i];
+	if (!iz)
+	    goto Lno;
+	e = iz->toExpression();
+	if (!e)
+	    goto Lno;
+	values->data[i] = (void *)e;
+    }
+    e = new AssocArrayLiteralExp(loc, keys, values);
+    return new ExpInitializer(loc, e);
+
+Lno:
+    delete keys;
+    delete values;
+    error(loc, "not an associative array initializer");
+    return this;
+}
+
+
+Type *ArrayInitializer::inferType(Scope *sc)
+{
+    for (size_t i = 0; i < value.dim; i++)
+    {
+	if (index.data[i])
+	    goto Lno;
+    }
+    if (value.dim)
+    {
+	Initializer *iz = (Initializer *)value.data[0];
+	if (iz)
+	{   Type *t = iz->inferType(sc);
+	    t = new TypeSArray(t, new IntegerExp(value.dim));
+	    t = t->semantic(loc, sc);
+	    return t;
+	}
+    }
+
+Lno:
+    error(loc, "cannot infer type from this array initializer");
+    return Type::terror;
+}
+
+
+void ArrayInitializer::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    buf->writebyte('[');
+    for (int i = 0; i < index.dim; i++)
+    {
+        if (i > 0)
+	    buf->writebyte(',');
+        Expression *ex = (Expression *)index.data[i];
+        if (ex)
+        {
+            ex->toCBuffer(buf, hgs);
+            buf->writebyte(':');
+        }
+        Initializer *iz = (Initializer *)value.data[i];
+        if (iz)
+            iz->toCBuffer(buf, hgs);
+    }
+    buf->writebyte(']');
+}
+
+
+/********************************** ExpInitializer ************************************/
+
+ExpInitializer::ExpInitializer(Loc loc, Expression *exp)
+    : Initializer(loc)
+{
+    this->exp = exp;
+}
+
+Initializer *ExpInitializer::syntaxCopy()
+{
+    return new ExpInitializer(loc, exp->syntaxCopy());
+}
+
+Initializer *ExpInitializer::semantic(Scope *sc, Type *t)
+{
+    //printf("ExpInitializer::semantic(%s), type = %s\n", exp->toChars(), t->toChars());
+    exp = exp->semantic(sc);
+    exp = resolveProperties(sc, exp);
+    exp = exp->optimize(WANTvalue | WANTinterpret);
+    Type *tb = t->toBasetype();
+
+    /* Look for case of initializing a static array with a too-short
+     * string literal, such as:
+     *	char[5] foo = "abc";
+     * Allow this by doing an explicit cast, which will lengthen the string
+     * literal.
+     */
+    if (exp->op == TOKstring && tb->ty == Tsarray && exp->type->ty == Tsarray)
+    {	StringExp *se = (StringExp *)exp;
+
+	if (!se->committed && se->type->ty == Tsarray &&
+	    ((TypeSArray *)se->type)->dim->toInteger() <
+	    ((TypeSArray *)t)->dim->toInteger())
+	{
+	    exp = se->castTo(sc, t);
+	    goto L1;
+	}
+    }
+
+    // Look for the case of statically initializing an array
+    // with a single member.
+    if (tb->ty == Tsarray &&
+	!tb->nextOf()->equals(exp->type->toBasetype()->nextOf()) &&
+	exp->implicitConvTo(tb->nextOf())
+       )
+    {
+	t = tb->nextOf();
+    }
+
+    exp = exp->implicitCastTo(sc, t);
+L1:
+    exp = exp->optimize(WANTvalue | WANTinterpret);
+    //printf("-ExpInitializer::semantic(): "); exp->print();
+    return this;
+}
+
+Type *ExpInitializer::inferType(Scope *sc)
+{
+    //printf("ExpInitializer::inferType() %s\n", toChars());
+    exp = exp->semantic(sc);
+    exp = resolveProperties(sc, exp);
+
+    // 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());
+    }
+
+    Type *t = exp->type;
+    if (!t)
+	t = Initializer::inferType(sc);
+    return t;
+}
+
+Expression *ExpInitializer::toExpression()
+{
+    return exp;
+}
+
+
+void ExpInitializer::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    exp->toCBuffer(buf, hgs);
+}
+
+
+
--- a/dmd2/init.h	Mon Jun 01 01:28:18 2009 +0200
+++ b/dmd2/init.h	Mon Jun 01 19:02:20 2009 +0100
@@ -26,7 +26,6 @@
 struct StructInitializer;
 struct ArrayInitializer;
 struct ExpInitializer;
-struct StructInitializer;
 #ifdef _DH
 struct HdrGenState;
 #endif
@@ -45,7 +44,9 @@
 
     static Initializers *arraySyntaxCopy(Initializers *ai);
 
+#if IN_DMD
     virtual dt_t *toDt();
+#endif
 
     virtual VoidInitializer *isVoidInitializer() { return NULL; }
     virtual StructInitializer  *isStructInitializer()  { return NULL; }
@@ -63,7 +64,9 @@
     Expression *toExpression();
     void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
 
+#if IN_DMD
     dt_t *toDt();
+#endif
 
     virtual VoidInitializer *isVoidInitializer() { return this; }
 };
@@ -83,9 +86,11 @@
     Expression *toExpression();
     void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
 
+#if IN_DMD
     dt_t *toDt();
+#endif
 
-    StructInitializer  *isStructInitializer()  { return this; }
+    StructInitializer *isStructInitializer() { return this; }
 };
 
 struct ArrayInitializer : Initializer
@@ -105,8 +110,10 @@
     Initializer *toAssocArrayInitializer();
     void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
 
+#if IN_DMD
     dt_t *toDt();
     dt_t *toDtBit();	// for bit arrays
+#endif
 
     ArrayInitializer *isArrayInitializer() { return this; }
 };
@@ -122,7 +129,9 @@
     Expression *toExpression();
     void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
 
+#if IN_DMD
     dt_t *toDt();
+#endif
 
     virtual ExpInitializer *isExpInitializer() { return this; }
 };
--- a/dmd2/inline.c	Mon Jun 01 01:28:18 2009 +0200
+++ b/dmd2/inline.c	Mon Jun 01 19:02:20 2009 +0100
@@ -1,1469 +1,1475 @@
-
-// Copyright (c) 1999-2008 by Digital Mars
-// All Rights Reserved
-// written by Walter Bright
-// http://www.digitalmars.com
-// License for redistribution is by either the Artistic License
-// in artistic.txt, or the GNU General Public License in gnu.txt.
-// See the included readme.txt for details.
-
-// Routines to perform function inlining
-
-#define LOG 0
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <assert.h>
-
-#include "id.h"
-#include "init.h"
-#include "declaration.h"
-#include "aggregate.h"
-#include "expression.h"
-#include "statement.h"
-#include "mtype.h"
-
-/* ========== Compute cost of inlining =============== */
-
-/* Walk trees to determine if inlining can be done, and if so,
- * if it is too complex to be worth inlining or not.
- */
-
-struct InlineCostState
-{
-    int nested;
-    int hasthis;
-    int hdrscan;    // !=0 if inline scan for 'header' content
-    FuncDeclaration *fd;
-};
-
-const int COST_MAX = 250;
-
-int Statement::inlineCost(InlineCostState *ics)
-{
-    return COST_MAX;		// default is we can't inline it
-}
-
-int ExpStatement::inlineCost(InlineCostState *ics)
-{
-    return exp ? exp->inlineCost(ics) : 0;
-}
-
-int CompoundStatement::inlineCost(InlineCostState *ics)
-{   int cost = 0;
-
-    for (size_t i = 0; i < statements->dim; i++)
-    {	Statement *s = (Statement *) statements->data[i];
-	if (s)
-	{
-	    cost += s->inlineCost(ics);
-	    if (cost >= COST_MAX)
-		break;
-	}
-    }
-    return cost;
-}
-
-int UnrolledLoopStatement::inlineCost(InlineCostState *ics)
-{   int cost = 0;
-
-    for (size_t i = 0; i < statements->dim; i++)
-    {	Statement *s = (Statement *) statements->data[i];
-	if (s)
-	{
-	    cost += s->inlineCost(ics);
-	    if (cost >= COST_MAX)
-		break;
-	}
-    }
-    return cost;
-}
-
-int IfStatement::inlineCost(InlineCostState *ics)
-{
-    int cost;
-
-    /* Can't declare variables inside ?: expressions, so
-     * we cannot inline if a variable is declared.
-     */
-    if (arg)
-	return COST_MAX;
-
-    cost = condition->inlineCost(ics);
-
-    /* Specifically allow:
-     *	if (condition)
-     *	    return exp1;
-     *	else
-     *	    return exp2;
-     * Otherwise, we can't handle return statements nested in if's.
-     */
-
-    if (elsebody && ifbody &&
-	ifbody->isReturnStatement() &&
-	elsebody->isReturnStatement())
-    {
-	cost += ifbody->inlineCost(ics);
-	cost += elsebody->inlineCost(ics);
-	//printf("cost = %d\n", cost);
-    }
-    else
-    {
-	ics->nested += 1;
-	if (ifbody)
-	    cost += ifbody->inlineCost(ics);
-	if (elsebody)
-	    cost += elsebody->inlineCost(ics);
-	ics->nested -= 1;
-    }
-    return cost;
-}
-
-int ReturnStatement::inlineCost(InlineCostState *ics)
-{
-    // Can't handle return statements nested in if's
-    if (ics->nested)
-	return COST_MAX;
-    return exp ? exp->inlineCost(ics) : 0;
-}
-
-/* -------------------------- */
-
-int arrayInlineCost(InlineCostState *ics, Array *arguments)
-{   int cost = 0;
-
-    if (arguments)
-    {
-	for (int i = 0; i < arguments->dim; i++)
-	{   Expression *e = (Expression *)arguments->data[i];
-
-	    if (e)
-		cost += e->inlineCost(ics);
-	}
-    }
-    return cost;
-}
-
-int Expression::inlineCost(InlineCostState *ics)
-{
-    return 1;
-}
-
-int VarExp::inlineCost(InlineCostState *ics)
-{
-    //printf("VarExp::inlineCost() %s\n", toChars());
-    return 1;
-}
-
-int ThisExp::inlineCost(InlineCostState *ics)
-{
-    FuncDeclaration *fd = ics->fd;
-    if (!ics->hdrscan)
-	if (fd->isNested() || !ics->hasthis)
-	    return COST_MAX;
-    return 1;
-}
-
-int SuperExp::inlineCost(InlineCostState *ics)
-{
-    FuncDeclaration *fd = ics->fd;
-    if (!ics->hdrscan)
-	if (fd->isNested() || !ics->hasthis)
-	    return COST_MAX;
-    return 1;
-}
-
-int TupleExp::inlineCost(InlineCostState *ics)
-{
-    return 1 + arrayInlineCost(ics, exps);
-}
-
-int ArrayLiteralExp::inlineCost(InlineCostState *ics)
-{
-    return 1 + arrayInlineCost(ics, elements);
-}
-
-int AssocArrayLiteralExp::inlineCost(InlineCostState *ics)
-{
-    return 1 + arrayInlineCost(ics, keys) + arrayInlineCost(ics, values);
-}
-
-int StructLiteralExp::inlineCost(InlineCostState *ics)
-{
-    return 1 + arrayInlineCost(ics, elements);
-}
-
-int FuncExp::inlineCost(InlineCostState *ics)
-{
-    // Right now, this makes the function be output to the .obj file twice.
-    return COST_MAX;
-}
-
-int DelegateExp::inlineCost(InlineCostState *ics)
-{
-    return COST_MAX;
-}
-
-int DeclarationExp::inlineCost(InlineCostState *ics)
-{   int cost = 0;
-    VarDeclaration *vd;
-
-    //printf("DeclarationExp::inlineCost()\n");
-    vd = declaration->isVarDeclaration();
-    if (vd)
-    {
-	TupleDeclaration *td = vd->toAlias()->isTupleDeclaration();
-	if (td)
-	{
-#if 1
-	    return COST_MAX;	// finish DeclarationExp::doInline
-#else
-	    for (size_t i = 0; i < td->objects->dim; i++)
-	    {   Object *o = (Object *)td->objects->data[i];
-		if (o->dyncast() != DYNCAST_EXPRESSION)
-		    return COST_MAX;
-		Expression *eo = (Expression *)o;
-		if (eo->op != TOKdsymbol)
-		    return COST_MAX;
-	    }
-	    return td->objects->dim;
-#endif
-	}
-	if (!ics->hdrscan && vd->isDataseg())
-	    return COST_MAX;
-	cost += 1;
-
-	// Scan initializer (vd->init)
-	if (vd->init)
-	{
-	    ExpInitializer *ie = vd->init->isExpInitializer();
-
-	    if (ie)
-	    {
-		cost += ie->exp->inlineCost(ics);
-	    }
-	}
-    }
-
-    // These can contain functions, which when copied, get output twice.
-    if (declaration->isStructDeclaration() ||
-	declaration->isClassDeclaration() ||
-	declaration->isFuncDeclaration() ||
-	declaration->isTypedefDeclaration() ||
-	declaration->isTemplateMixin())
-	return COST_MAX;
-
-    //printf("DeclarationExp::inlineCost('%s')\n", toChars());
-    return cost;
-}
-
-int UnaExp::inlineCost(InlineCostState *ics)
-{
-    return 1 + e1->inlineCost(ics);
-}
-
-int AssertExp::inlineCost(InlineCostState *ics)
-{
-    return 1 + e1->inlineCost(ics) + (msg ? msg->inlineCost(ics) : 0);
-}
-
-int BinExp::inlineCost(InlineCostState *ics)
-{
-    return 1 + e1->inlineCost(ics) + e2->inlineCost(ics);
-}
-
-int CallExp::inlineCost(InlineCostState *ics)
-{
-    return 1 + e1->inlineCost(ics) + arrayInlineCost(ics, arguments);
-}
-
-int SliceExp::inlineCost(InlineCostState *ics)
-{   int cost;
-
-    cost = 1 + e1->inlineCost(ics);
-    if (lwr)
-	cost += lwr->inlineCost(ics);
-    if (upr)
-	cost += upr->inlineCost(ics);
-    return cost;
-}
-
-int ArrayExp::inlineCost(InlineCostState *ics)
-{
-    return 1 + e1->inlineCost(ics) + arrayInlineCost(ics, arguments);
-}
-
-
-int CondExp::inlineCost(InlineCostState *ics)
-{
-    return 1 +
-	 e1->inlineCost(ics) +
-	 e2->inlineCost(ics) +
-	 econd->inlineCost(ics);
-}
-
-
-/* ======================== Perform the inlining ============================== */
-
-/* Inlining is done by:
- * o	Converting to an Expression
- * o	Copying the trees of the function to be inlined
- * o	Renaming the variables
- */
-
-struct InlineDoState
-{
-    VarDeclaration *vthis;
-    Array from;		// old Dsymbols
-    Array to;		// parallel array of new Dsymbols
-    Dsymbol *parent;	// new parent
-};
-
-Expression *Statement::doInline(InlineDoState *ids)
-{
-    assert(0);
-    return NULL;		// default is we can't inline it
-}
-
-Expression *ExpStatement::doInline(InlineDoState *ids)
-{
-#if LOG
-    if (exp) printf("ExpStatement::doInline() '%s'\n", exp->toChars());
-#endif
-    return exp ? exp->doInline(ids) : NULL;
-}
-
-Expression *CompoundStatement::doInline(InlineDoState *ids)
-{
-    Expression *e = NULL;
-
-    //printf("CompoundStatement::doInline() %d\n", statements->dim);
-    for (size_t i = 0; i < statements->dim; i++)
-    {	Statement *s = (Statement *) statements->data[i];
-	if (s)
-	{
-	    Expression *e2 = s->doInline(ids);
-	    e = Expression::combine(e, e2);
-	    if (s->isReturnStatement())
-		break;
-
-	    /* Check for:
-	     *	if (condition)
-	     *	    return exp1;
-	     *	else
-	     *	    return exp2;
-	     */
-	    IfStatement *ifs = s->isIfStatement();
-	    if (ifs && ifs->elsebody && ifs->ifbody &&
-		ifs->ifbody->isReturnStatement() &&
-		ifs->elsebody->isReturnStatement()
-	       )
-		break;
-
-	}
-    }
-    return e;
-}
-
-Expression *UnrolledLoopStatement::doInline(InlineDoState *ids)
-{
-    Expression *e = NULL;
-
-    //printf("UnrolledLoopStatement::doInline() %d\n", statements->dim);
-    for (size_t i = 0; i < statements->dim; i++)
-    {	Statement *s = (Statement *) statements->data[i];
-	if (s)
-	{
-	    Expression *e2 = s->doInline(ids);
-	    e = Expression::combine(e, e2);
-	    if (s->isReturnStatement())
-		break;
-	}
-    }
-    return e;
-}
-
-Expression *IfStatement::doInline(InlineDoState *ids)
-{
-    Expression *econd;
-    Expression *e1;
-    Expression *e2;
-    Expression *e;
-
-    assert(!arg);
-    econd = condition->doInline(ids);
-    assert(econd);
-    if (ifbody)
-	e1 = ifbody->doInline(ids);
-    else
-	e1 = NULL;
-    if (elsebody)
-	e2 = elsebody->doInline(ids);
-    else
-	e2 = NULL;
-    if (e1 && e2)
-    {
-	e = new CondExp(econd->loc, econd, e1, e2);
-	e->type = e1->type;
-    }
-    else if (e1)
-    {
-	e = new AndAndExp(econd->loc, econd, e1);
-	e->type = Type::tvoid;
-    }
-    else if (e2)
-    {
-	e = new OrOrExp(econd->loc, econd, e2);
-	e->type = Type::tvoid;
-    }
-    else
-    {
-	e = econd;
-    }
-    return e;
-}
-
-Expression *ReturnStatement::doInline(InlineDoState *ids)
-{
-    //printf("ReturnStatement::doInline() '%s'\n", exp ? exp->toChars() : "");
-    return exp ? exp->doInline(ids) : 0;
-}
-
-/* --------------------------------------------------------------- */
-
-/******************************
- * Perform doInline() on an array of Expressions.
- */
-
-Expressions *arrayExpressiondoInline(Expressions *a, InlineDoState *ids)
-{   Expressions *newa = NULL;
-
-    if (a)
-    {
-	newa = new Expressions();
-	newa->setDim(a->dim);
-
-	for (int i = 0; i < a->dim; i++)
-	{   Expression *e = (Expression *)a->data[i];
-
-	    if (e)
-	    {
-		e = e->doInline(ids);
-		newa->data[i] = (void *)e;
-	    }
-	}
-    }
-    return newa;
-}
-
-Expression *Expression::doInline(InlineDoState *ids)
-{
-    //printf("Expression::doInline(%s): %s\n", Token::toChars(op), toChars());
-    return copy();
-}
-
-Expression *SymOffExp::doInline(InlineDoState *ids)
-{
-    int i;
-
-    //printf("SymOffExp::doInline(%s)\n", toChars());
-    for (i = 0; i < ids->from.dim; i++)
-    {
-	if (var == (Declaration *)ids->from.data[i])
-	{
-	    SymOffExp *se = (SymOffExp *)copy();
-
-	    se->var = (Declaration *)ids->to.data[i];
-	    return se;
-	}
-    }
-    return this;
-}
-
-Expression *VarExp::doInline(InlineDoState *ids)
-{
-    int i;
-
-    //printf("VarExp::doInline(%s)\n", toChars());
-    for (i = 0; i < ids->from.dim; i++)
-    {
-	if (var == (Declaration *)ids->from.data[i])
-	{
-	    VarExp *ve = (VarExp *)copy();
-
-	    ve->var = (Declaration *)ids->to.data[i];
-	    return ve;
-	}
-    }
-    return this;
-}
-
-Expression *ThisExp::doInline(InlineDoState *ids)
-{
-    //if (!ids->vthis)
-	//error("no 'this' when inlining %s", ids->parent->toChars());
-    if (!ids->vthis)
-    {
-	return this;
-    }
-
-    VarExp *ve = new VarExp(loc, ids->vthis);
-    ve->type = type;
-    return ve;
-}
-
-Expression *SuperExp::doInline(InlineDoState *ids)
-{
-    assert(ids->vthis);
-
-    VarExp *ve = new VarExp(loc, ids->vthis);
-    ve->type = type;
-    return ve;
-}
-
-Expression *DeclarationExp::doInline(InlineDoState *ids)
-{   DeclarationExp *de = (DeclarationExp *)copy();
-    VarDeclaration *vd;
-
-    //printf("DeclarationExp::doInline(%s)\n", toChars());
-    vd = declaration->isVarDeclaration();
-    if (vd)
-    {
-#if 0
-	// Need to figure this out before inlining can work for tuples
-	TupleDeclaration *td = vd->toAlias()->isTupleDeclaration();
-	if (td)
-	{
-	    for (size_t i = 0; i < td->objects->dim; i++)
-	    {   DsymbolExp *se = (DsymbolExp *)td->objects->data[i];
-		assert(se->op == TOKdsymbol);
-		se->s;
-	    }
-	    return st->objects->dim;
-	}
-#endif
-	if (vd->isStatic())
-	    ;
-	else
-	{
-	    VarDeclaration *vto;
-
-	    vto = new VarDeclaration(vd->loc, vd->type, vd->ident, vd->init);
-	    *vto = *vd;
-	    vto->parent = ids->parent;
-	    vto->csym = NULL;
-	    vto->isym = NULL;
-
-	    ids->from.push(vd);
-	    ids->to.push(vto);
-
-	    if (vd->init)
-	    {
-		if (vd->init->isVoidInitializer())
-		{
-		    vto->init = new VoidInitializer(vd->init->loc);
-		}
-		else
-		{
-		    Expression *e = vd->init->toExpression();
-		    assert(e);
-		    vto->init = new ExpInitializer(e->loc, e->doInline(ids));
-		}
-	    }
-	    de->declaration = (Dsymbol *) (void *)vto;
-	}
-    }
-    /* This needs work, like DeclarationExp::toElem(), if we are
-     * to handle TemplateMixin's. For now, we just don't inline them.
-     */
-    return de;
-}
-
-Expression *NewExp::doInline(InlineDoState *ids)
-{
-    //printf("NewExp::doInline(): %s\n", toChars());
-    NewExp *ne = (NewExp *)copy();
-
-    if (thisexp)
-	ne->thisexp = thisexp->doInline(ids);
-    ne->newargs = arrayExpressiondoInline(ne->newargs, ids);
-    ne->arguments = arrayExpressiondoInline(ne->arguments, ids);
-    return ne;
-}
-
-Expression *UnaExp::doInline(InlineDoState *ids)
-{
-    UnaExp *ue = (UnaExp *)copy();
-
-    ue->e1 = e1->doInline(ids);
-    return ue;
-}
-
-Expression *AssertExp::doInline(InlineDoState *ids)
-{
-    AssertExp *ae = (AssertExp *)copy();
-
-    ae->e1 = e1->doInline(ids);
-    if (msg)
-	ae->msg = msg->doInline(ids);
-    return ae;
-}
-
-Expression *BinExp::doInline(InlineDoState *ids)
-{
-    BinExp *be = (BinExp *)copy();
-
-    be->e1 = e1->doInline(ids);
-    be->e2 = e2->doInline(ids);
-    return be;
-}
-
-Expression *CallExp::doInline(InlineDoState *ids)
-{
-    CallExp *ce;
-
-    ce = (CallExp *)copy();
-    ce->e1 = e1->doInline(ids);
-    ce->arguments = arrayExpressiondoInline(arguments, ids);
-    return ce;
-}
-
-
-Expression *IndexExp::doInline(InlineDoState *ids)
-{
-    IndexExp *are = (IndexExp *)copy();
-
-    are->e1 = e1->doInline(ids);
-
-    if (lengthVar)
-    {	//printf("lengthVar\n");
-	VarDeclaration *vd = lengthVar;
-	ExpInitializer *ie;
-	ExpInitializer *ieto;
-	VarDeclaration *vto;
-
-	vto = new VarDeclaration(vd->loc, vd->type, vd->ident, vd->init);
-	*vto = *vd;
-	vto->parent = ids->parent;
-	vto->csym = NULL;
-	vto->isym = NULL;
-
-	ids->from.push(vd);
-	ids->to.push(vto);
-
-	if (vd->init)
-	{
-	    ie = vd->init->isExpInitializer();
-	    assert(ie);
-	    ieto = new ExpInitializer(ie->loc, ie->exp->doInline(ids));
-	    vto->init = ieto;
-	}
-
-	are->lengthVar = (VarDeclaration *) (void *)vto;
-    }
-    are->e2 = e2->doInline(ids);
-    return are;
-}
-
-
-Expression *SliceExp::doInline(InlineDoState *ids)
-{
-    SliceExp *are = (SliceExp *)copy();
-
-    are->e1 = e1->doInline(ids);
-
-    if (lengthVar)
-    {	//printf("lengthVar\n");
-	VarDeclaration *vd = lengthVar;
-	ExpInitializer *ie;
-	ExpInitializer *ieto;
-	VarDeclaration *vto;
-
-	vto = new VarDeclaration(vd->loc, vd->type, vd->ident, vd->init);
-	*vto = *vd;
-	vto->parent = ids->parent;
-	vto->csym = NULL;
-	vto->isym = NULL;
-
-	ids->from.push(vd);
-	ids->to.push(vto);
-
-	if (vd->init)
-	{
-	    ie = vd->init->isExpInitializer();
-	    assert(ie);
-	    ieto = new ExpInitializer(ie->loc, ie->exp->doInline(ids));
-	    vto->init = ieto;
-	}
-
-	are->lengthVar = (VarDeclaration *) (void *)vto;
-    }
-    if (lwr)
-	are->lwr = lwr->doInline(ids);
-    if (upr)
-	are->upr = upr->doInline(ids);
-    return are;
-}
-
-
-Expression *TupleExp::doInline(InlineDoState *ids)
-{
-    TupleExp *ce;
-
-    ce = (TupleExp *)copy();
-    ce->exps = arrayExpressiondoInline(exps, ids);
-    return ce;
-}
-
-
-Expression *ArrayLiteralExp::doInline(InlineDoState *ids)
-{
-    ArrayLiteralExp *ce;
-
-    ce = (ArrayLiteralExp *)copy();
-    ce->elements = arrayExpressiondoInline(elements, ids);
-    return ce;
-}
-
-
-Expression *AssocArrayLiteralExp::doInline(InlineDoState *ids)
-{
-    AssocArrayLiteralExp *ce;
-
-    ce = (AssocArrayLiteralExp *)copy();
-    ce->keys = arrayExpressiondoInline(keys, ids);
-    ce->values = arrayExpressiondoInline(values, ids);
-    return ce;
-}
-
-
-Expression *StructLiteralExp::doInline(InlineDoState *ids)
-{
-    StructLiteralExp *ce;
-
-    ce = (StructLiteralExp *)copy();
-    ce->elements = arrayExpressiondoInline(elements, ids);
-    return ce;
-}
-
-
-Expression *ArrayExp::doInline(InlineDoState *ids)
-{
-    ArrayExp *ce;
-
-    ce = (ArrayExp *)copy();
-    ce->e1 = e1->doInline(ids);
-    ce->arguments = arrayExpressiondoInline(arguments, ids);
-    return ce;
-}
-
-
-Expression *CondExp::doInline(InlineDoState *ids)
-{
-    CondExp *ce = (CondExp *)copy();
-
-    ce->econd = econd->doInline(ids);
-    ce->e1 = e1->doInline(ids);
-    ce->e2 = e2->doInline(ids);
-    return ce;
-}
-
-
-/* ========== Walk the parse trees, and inline expand functions ============= */
-
-/* Walk the trees, looking for functions to inline.
- * Inline any that can be.
- */
-
-struct InlineScanState
-{
-    FuncDeclaration *fd;	// function being scanned
-};
-
-Statement *Statement::inlineScan(InlineScanState *iss)
-{
-    return this;
-}
-
-Statement *ExpStatement::inlineScan(InlineScanState *iss)
-{
-#if LOG
-    printf("ExpStatement::inlineScan(%s)\n", toChars());
-#endif
-    if (exp)
-	exp = exp->inlineScan(iss);
-    return this;
-}
-
-Statement *CompoundStatement::inlineScan(InlineScanState *iss)
-{
-    for (size_t i = 0; i < statements->dim; i++)
-    {	Statement *s = (Statement *) statements->data[i];
-	if (s)
-	    statements->data[i] = (void *)s->inlineScan(iss);
-    }
-    return this;
-}
-
-Statement *UnrolledLoopStatement::inlineScan(InlineScanState *iss)
-{
-    for (size_t i = 0; i < statements->dim; i++)
-    {	Statement *s = (Statement *) statements->data[i];
-	if (s)
-	    statements->data[i] = (void *)s->inlineScan(iss);
-    }
-    return this;
-}
-
-Statement *ScopeStatement::inlineScan(InlineScanState *iss)
-{
-    if (statement)
-	statement = statement->inlineScan(iss);
-    return this;
-}
-
-Statement *WhileStatement::inlineScan(InlineScanState *iss)
-{
-    condition = condition->inlineScan(iss);
-    body = body ? body->inlineScan(iss) : NULL;
-    return this;
-}
-
-
-Statement *DoStatement::inlineScan(InlineScanState *iss)
-{
-    body = body ? body->inlineScan(iss) : NULL;
-    condition = condition->inlineScan(iss);
-    return this;
-}
-
-
-Statement *ForStatement::inlineScan(InlineScanState *iss)
-{
-    if (init)
-	init = init->inlineScan(iss);
-    if (condition)
-	condition = condition->inlineScan(iss);
-    if (increment)
-	increment = increment->inlineScan(iss);
-    body = body->inlineScan(iss);
-    return this;
-}
-
-
-Statement *ForeachStatement::inlineScan(InlineScanState *iss)
-{
-    aggr = aggr->inlineScan(iss);
-    if (body)
-	body = body->inlineScan(iss);
-    return this;
-}
-
-
-#if DMDV2
-Statement *ForeachRangeStatement::inlineScan(InlineScanState *iss)
-{
-    lwr = lwr->inlineScan(iss);
-    upr = upr->inlineScan(iss);
-    if (body)
-	body = body->inlineScan(iss);
-    return this;
-}
-#endif
-
-
-Statement *IfStatement::inlineScan(InlineScanState *iss)
-{
-    condition = condition->inlineScan(iss);
-    if (ifbody)
-	ifbody = ifbody->inlineScan(iss);
-    if (elsebody)
-	elsebody = elsebody->inlineScan(iss);
-    return this;
-}
-
-
-Statement *SwitchStatement::inlineScan(InlineScanState *iss)
-{
-    //printf("SwitchStatement::inlineScan()\n");
-    condition = condition->inlineScan(iss);
-    body = body ? body->inlineScan(iss) : NULL;
-    if (sdefault)
-	sdefault = (DefaultStatement *)sdefault->inlineScan(iss);
-    if (cases)
-    {
-	for (int i = 0; i < cases->dim; i++)
-	{   Statement *s;
-
-	    s = (Statement *) cases->data[i];
-	    cases->data[i] = (void *)s->inlineScan(iss);
-	}
-    }
-    return this;
-}
-
-
-Statement *CaseStatement::inlineScan(InlineScanState *iss)
-{
-    //printf("CaseStatement::inlineScan()\n");
-    exp = exp->inlineScan(iss);
-    if (statement)
-	statement = statement->inlineScan(iss);
-    return this;
-}
-
-
-Statement *DefaultStatement::inlineScan(InlineScanState *iss)
-{
-    if (statement)
-	statement = statement->inlineScan(iss);
-    return this;
-}
-
-
-Statement *ReturnStatement::inlineScan(InlineScanState *iss)
-{
-    //printf("ReturnStatement::inlineScan()\n");
-    if (exp)
-    {
-	exp = exp->inlineScan(iss);
-    }
-    return this;
-}
-
-
-Statement *SynchronizedStatement::inlineScan(InlineScanState *iss)
-{
-    if (exp)
-	exp = exp->inlineScan(iss);
-    if (body)
-	body = body->inlineScan(iss);
-    return this;
-}
-
-
-Statement *WithStatement::inlineScan(InlineScanState *iss)
-{
-    if (exp)
-	exp = exp->inlineScan(iss);
-    if (body)
-	body = body->inlineScan(iss);
-    return this;
-}
-
-
-Statement *TryCatchStatement::inlineScan(InlineScanState *iss)
-{
-    if (body)
-	body = body->inlineScan(iss);
-    if (catches)
-    {
-	for (int i = 0; i < catches->dim; i++)
-	{   Catch *c = (Catch *)catches->data[i];
-
-	    if (c->handler)
-		c->handler = c->handler->inlineScan(iss);
-	}
-    }
-    return this;
-}
-
-
-Statement *TryFinallyStatement::inlineScan(InlineScanState *iss)
-{
-    if (body)
-	body = body->inlineScan(iss);
-    if (finalbody)
-	finalbody = finalbody->inlineScan(iss);
-    return this;
-}
-
-
-Statement *ThrowStatement::inlineScan(InlineScanState *iss)
-{
-    if (exp)
-	exp = exp->inlineScan(iss);
-    return this;
-}
-
-
-Statement *VolatileStatement::inlineScan(InlineScanState *iss)
-{
-    if (statement)
-	statement = statement->inlineScan(iss);
-    return this;
-}
-
-
-Statement *LabelStatement::inlineScan(InlineScanState *iss)
-{
-    if (statement)
-	statement = statement->inlineScan(iss);
-    return this;
-}
-
-/* -------------------------- */
-
-void arrayInlineScan(InlineScanState *iss, Array *arguments)
-{
-    if (arguments)
-    {
-	for (int i = 0; i < arguments->dim; i++)
-	{   Expression *e = (Expression *)arguments->data[i];
-
-	    if (e)
-	    {
-		e = e->inlineScan(iss);
-		arguments->data[i] = (void *)e;
-	    }
-	}
-    }
-}
-
-Expression *Expression::inlineScan(InlineScanState *iss)
-{
-    return this;
-}
-
-void scanVar(Dsymbol *s, InlineScanState *iss)
-{
-    VarDeclaration *vd = s->isVarDeclaration();
-    if (vd)
-    {
-	TupleDeclaration *td = vd->toAlias()->isTupleDeclaration();
-	if (td)
-	{
-	    for (size_t i = 0; i < td->objects->dim; i++)
-	    {   DsymbolExp *se = (DsymbolExp *)td->objects->data[i];
-		assert(se->op == TOKdsymbol);
-		scanVar(se->s, iss);
-	    }
-	}
-	else
-	{
-	    // Scan initializer (vd->init)
-	    if (vd->init)
-	    {
-		ExpInitializer *ie = vd->init->isExpInitializer();
-
-		if (ie)
-		{
-		    ie->exp = ie->exp->inlineScan(iss);
-		}
-	    }
-	}
-    }
-}
-
-Expression *DeclarationExp::inlineScan(InlineScanState *iss)
-{
-    //printf("DeclarationExp::inlineScan()\n");
-    scanVar(declaration, iss);
-    return this;
-}
-
-Expression *UnaExp::inlineScan(InlineScanState *iss)
-{
-    e1 = e1->inlineScan(iss);
-    return this;
-}
-
-Expression *AssertExp::inlineScan(InlineScanState *iss)
-{
-    e1 = e1->inlineScan(iss);
-    if (msg)
-	msg = msg->inlineScan(iss);
-    return this;
-}
-
-Expression *BinExp::inlineScan(InlineScanState *iss)
-{
-    e1 = e1->inlineScan(iss);
-    e2 = e2->inlineScan(iss);
-    return this;
-}
-
-
-Expression *CallExp::inlineScan(InlineScanState *iss)
-{   Expression *e = this;
-
-    //printf("CallExp::inlineScan()\n");
-    e1 = e1->inlineScan(iss);
-    arrayInlineScan(iss, arguments);
-
-    if (e1->op == TOKvar)
-    {
-	VarExp *ve = (VarExp *)e1;
-	FuncDeclaration *fd = ve->var->isFuncDeclaration();
-
-	if (fd && fd != iss->fd && fd->canInline(0))
-	{
-	    e = fd->doInline(iss, NULL, arguments);
-	}
-    }
-    else if (e1->op == TOKdotvar)
-    {
-	DotVarExp *dve = (DotVarExp *)e1;
-	FuncDeclaration *fd = dve->var->isFuncDeclaration();
-
-	if (fd && fd != iss->fd && fd->canInline(1))
-	{
-	    if (dve->e1->op == TOKcall &&
-		dve->e1->type->toBasetype()->ty == Tstruct)
-	    {
-		/* To create ethis, we'll need to take the address
-		 * of dve->e1, but this won't work if dve->e1 is
-		 * a function call.
-		 */
-		;
-	    }
-	    else
-		e = fd->doInline(iss, dve->e1, arguments);
-	}
-    }
-
-    return e;
-}
-
-
-Expression *SliceExp::inlineScan(InlineScanState *iss)
-{
-    e1 = e1->inlineScan(iss);
-    if (lwr)
-	lwr = lwr->inlineScan(iss);
-    if (upr)
-	upr = upr->inlineScan(iss);
-    return this;
-}
-
-
-Expression *TupleExp::inlineScan(InlineScanState *iss)
-{   Expression *e = this;
-
-    //printf("TupleExp::inlineScan()\n");
-    arrayInlineScan(iss, exps);
-
-    return e;
-}
-
-
-Expression *ArrayLiteralExp::inlineScan(InlineScanState *iss)
-{   Expression *e = this;
-
-    //printf("ArrayLiteralExp::inlineScan()\n");
-    arrayInlineScan(iss, elements);
-
-    return e;
-}
-
-
-Expression *AssocArrayLiteralExp::inlineScan(InlineScanState *iss)
-{   Expression *e = this;
-
-    //printf("AssocArrayLiteralExp::inlineScan()\n");
-    arrayInlineScan(iss, keys);
-    arrayInlineScan(iss, values);
-
-    return e;
-}
-
-
-Expression *StructLiteralExp::inlineScan(InlineScanState *iss)
-{   Expression *e = this;
-
-    //printf("StructLiteralExp::inlineScan()\n");
-    arrayInlineScan(iss, elements);
-
-    return e;
-}
-
-
-Expression *ArrayExp::inlineScan(InlineScanState *iss)
-{   Expression *e = this;
-
-    //printf("ArrayExp::inlineScan()\n");
-    e1 = e1->inlineScan(iss);
-    arrayInlineScan(iss, arguments);
-
-    return e;
-}
-
-
-Expression *CondExp::inlineScan(InlineScanState *iss)
-{
-    econd = econd->inlineScan(iss);
-    e1 = e1->inlineScan(iss);
-    e2 = e2->inlineScan(iss);
-    return this;
-}
-
-
-/* ==========  =============== */
-
-void FuncDeclaration::inlineScan()
-{
-    InlineScanState iss;
-
-#if LOG
-    printf("FuncDeclaration::inlineScan('%s')\n", toChars());
-#endif
-    memset(&iss, 0, sizeof(iss));
-    iss.fd = this;
-    if (fbody)
-    {
-	inlineNest++;
-	fbody = fbody->inlineScan(&iss);
-	inlineNest--;
-    }
-}
-
-int FuncDeclaration::canInline(int hasthis, int hdrscan)
-{
-    InlineCostState ics;
-    int cost;
-
-#define CANINLINE_LOG 0
-
-#if CANINLINE_LOG
-    printf("FuncDeclaration::canInline(hasthis = %d, '%s')\n", hasthis, toChars());
-#endif
-
-    if (needThis() && !hasthis)
-	return 0;
-
-    if (inlineNest || (!semanticRun && !hdrscan))
-    {
-#if CANINLINE_LOG
-	printf("\t1: no, inlineNest = %d, semanticRun = %d\n", inlineNest, semanticRun);
-#endif
-	return 0;
-    }
-
-    switch (inlineStatus)
-    {
-	case ILSyes:
-#if CANINLINE_LOG
-	    printf("\t1: yes %s\n", toChars());
-#endif
-	    return 1;
-
-	case ILSno:
-#if CANINLINE_LOG
-	    printf("\t1: no %s\n", toChars());
-#endif
-	    return 0;
-
-	case ILSuninitialized:
-	    break;
-
-	default:
-	    assert(0);
-    }
-
-    if (type)
-    {	assert(type->ty == Tfunction);
-	TypeFunction *tf = (TypeFunction *)(type);
-	if (tf->varargs == 1)	// no variadic parameter lists
-	    goto Lno;
-
-	/* Don't inline a function that returns non-void, but has
-	 * no return expression.
-	 */
-	if (tf->next && tf->next->ty != Tvoid &&
-	    !(hasReturnExp & 1) &&
-	    !hdrscan)
-	    goto Lno;
-    }
-    else
-    {	CtorDeclaration *ctor = isCtorDeclaration();
-
-	if (ctor && ctor->varargs == 1)
-	    goto Lno;
-    }
-
-    if (
-	!fbody ||
-	!hdrscan &&
-	(
-#if 0
-	isCtorDeclaration() ||	// cannot because need to convert:
-				//	return;
-				// to:
-				//	return this;
-#endif
-	isSynchronized() ||
-	isImportedSymbol() ||
-#if DMDV2
-	closureVars.dim ||	// no nested references to this frame
-#else
-	nestedFrameRef ||	// no nested references to this frame
-#endif
-	(isVirtual() && !isFinal())
-       ))
-    {
-	goto Lno;
-    }
-
-    /* If any parameters are Tsarray's (which are passed by reference)
-     * or out parameters (also passed by reference), don't do inlining.
-     */
-    if (parameters)
-    {
-	for (int i = 0; i < parameters->dim; i++)
-	{
-	    VarDeclaration *v = (VarDeclaration *)parameters->data[i];
-	    if (v->isOut() || v->isRef() || v->type->toBasetype()->ty == Tsarray)
-		goto Lno;
-	}
-    }
-
-    memset(&ics, 0, sizeof(ics));
-    ics.hasthis = hasthis;
-    ics.fd = this;
-    ics.hdrscan = hdrscan;
-    cost = fbody->inlineCost(&ics);
-#if CANINLINE_LOG
-    printf("cost = %d\n", cost);
-#endif
-    if (cost >= COST_MAX)
-	goto Lno;
-
-    if (!hdrscan)    // Don't scan recursively for header content scan
-	inlineScan();
-
-Lyes:
-    if (!hdrscan)    // Don't modify inlineStatus for header content scan
-	inlineStatus = ILSyes;
-#if CANINLINE_LOG
-    printf("\t2: yes %s\n", toChars());
-#endif
-    return 1;
-
-Lno:
-    if (!hdrscan)    // Don't modify inlineStatus for header content scan
-	inlineStatus = ILSno;
-#if CANINLINE_LOG
-    printf("\t2: no %s\n", toChars());
-#endif
-    return 0;
-}
-
-Expression *FuncDeclaration::doInline(InlineScanState *iss, Expression *ethis, Array *arguments)
-{
-    InlineDoState ids;
-    DeclarationExp *de;
-    Expression *e = NULL;
-
-#if LOG
-    printf("FuncDeclaration::doInline('%s')\n", toChars());
-#endif
-
-    memset(&ids, 0, sizeof(ids));
-    ids.parent = iss->fd;
-
-    // Set up vthis
-    if (ethis)
-    {
-	VarDeclaration *vthis;
-	ExpInitializer *ei;
-	VarExp *ve;
-
-#if STRUCTTHISREF
-	if (ethis->type->ty == Tpointer)
-	{   Type *t = ethis->type->nextOf();
-	    ethis = new PtrExp(ethis->loc, ethis);
-	    ethis->type = t;
-	}
-	ei = new ExpInitializer(ethis->loc, ethis);
-
-	vthis = new VarDeclaration(ethis->loc, ethis->type, Id::This, ei);
-	if (ethis->type->ty != Tclass)
-	    vthis->storage_class = STCref;
-	else
-	    vthis->storage_class = STCin;
-#else
-	if (ethis->type->ty != Tclass && ethis->type->ty != Tpointer)
-	{
-	    ethis = ethis->addressOf(NULL);
-	}
-
-	ei = new ExpInitializer(ethis->loc, ethis);
-
-	vthis = new VarDeclaration(ethis->loc, ethis->type, Id::This, ei);
-	vthis->storage_class = STCin;
-#endif
-	vthis->linkage = LINKd;
-	vthis->parent = iss->fd;
-
-	ve = new VarExp(vthis->loc, vthis);
-	ve->type = vthis->type;
-
-	ei->exp = new AssignExp(vthis->loc, ve, ethis);
-	ei->exp->type = ve->type;
-#if STRUCTTHISREF
-	if (ethis->type->ty != Tclass)
-	{   /* This is a reference initialization, not a simple assignment.
-	     */
-	    ei->exp->op = TOKconstruct;
-	}
-#endif
-
-	ids.vthis = vthis;
-    }
-
-    // Set up parameters
-    if (ethis)
-    {
-	e = new DeclarationExp(0, ids.vthis);
-	e->type = Type::tvoid;
-    }
-
-    if (arguments && arguments->dim)
-    {
-	assert(parameters->dim == arguments->dim);
-
-	for (int i = 0; i < arguments->dim; i++)
-	{
-	    VarDeclaration *vfrom = (VarDeclaration *)parameters->data[i];
-	    VarDeclaration *vto;
-	    Expression *arg = (Expression *)arguments->data[i];
-	    ExpInitializer *ei;
-	    VarExp *ve;
-
-	    ei = new ExpInitializer(arg->loc, arg);
-
-	    vto = new VarDeclaration(vfrom->loc, vfrom->type, vfrom->ident, ei);
-	    vto->storage_class |= vfrom->storage_class & (STCin | STCout | STClazy | STCref);
-	    vto->linkage = vfrom->linkage;
-	    vto->parent = iss->fd;
-	    //printf("vto = '%s', vto->storage_class = x%x\n", vto->toChars(), vto->storage_class);
-	    //printf("vto->parent = '%s'\n", iss->fd->toChars());
-
-	    ve = new VarExp(vto->loc, vto);
-	    //ve->type = vto->type;
-	    ve->type = arg->type;
-
-	    ei->exp = new AssignExp(vto->loc, ve, arg);
-	    ei->exp->type = ve->type;
-//ve->type->print();
-//arg->type->print();
-//ei->exp->print();
-
-	    ids.from.push(vfrom);
-	    ids.to.push(vto);
-
-	    de = new DeclarationExp(0, vto);
-	    de->type = Type::tvoid;
-
-	    e = Expression::combine(e, de);
-	}
-    }
-
-    inlineNest++;
-    Expression *eb = fbody->doInline(&ids);
-    inlineNest--;
-    return Expression::combine(e, eb);
-}
-
-
-
+
+// Copyright (c) 1999-2008 by Digital Mars
+// All Rights Reserved
+// written by Walter Bright
+// http://www.digitalmars.com
+// License for redistribution is by either the Artistic License
+// in artistic.txt, or the GNU General Public License in gnu.txt.
+// See the included readme.txt for details.
+
+// Routines to perform function inlining
+
+#define LOG 0
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+
+#include "id.h"
+#include "init.h"
+#include "declaration.h"
+#include "aggregate.h"
+#include "expression.h"
+#include "statement.h"
+#include "mtype.h"
+
+/* ========== Compute cost of inlining =============== */
+
+/* Walk trees to determine if inlining can be done, and if so,
+ * if it is too complex to be worth inlining or not.
+ */
+
+struct InlineCostState
+{
+    int nested;
+    int hasthis;
+    int hdrscan;    // !=0 if inline scan for 'header' content
+    FuncDeclaration *fd;
+};
+
+const int COST_MAX = 250;
+
+int Statement::inlineCost(InlineCostState *ics)
+{
+    return COST_MAX;		// default is we can't inline it
+}
+
+int ExpStatement::inlineCost(InlineCostState *ics)
+{
+    return exp ? exp->inlineCost(ics) : 0;
+}
+
+int CompoundStatement::inlineCost(InlineCostState *ics)
+{   int cost = 0;
+
+    for (size_t i = 0; i < statements->dim; i++)
+    {	Statement *s = (Statement *) statements->data[i];
+	if (s)
+	{
+	    cost += s->inlineCost(ics);
+	    if (cost >= COST_MAX)
+		break;
+	}
+    }
+    return cost;
+}
+
+int UnrolledLoopStatement::inlineCost(InlineCostState *ics)
+{   int cost = 0;
+
+    for (size_t i = 0; i < statements->dim; i++)
+    {	Statement *s = (Statement *) statements->data[i];
+	if (s)
+	{
+	    cost += s->inlineCost(ics);
+	    if (cost >= COST_MAX)
+		break;
+	}
+    }
+    return cost;
+}
+
+int IfStatement::inlineCost(InlineCostState *ics)
+{
+    int cost;
+
+    /* Can't declare variables inside ?: expressions, so
+     * we cannot inline if a variable is declared.
+     */
+    if (arg)
+	return COST_MAX;
+
+    cost = condition->inlineCost(ics);
+
+    /* Specifically allow:
+     *	if (condition)
+     *	    return exp1;
+     *	else
+     *	    return exp2;
+     * Otherwise, we can't handle return statements nested in if's.
+     */
+
+    if (elsebody && ifbody &&
+	ifbody->isReturnStatement() &&
+	elsebody->isReturnStatement())
+    {
+	cost += ifbody->inlineCost(ics);
+	cost += elsebody->inlineCost(ics);
+	//printf("cost = %d\n", cost);
+    }
+    else
+    {
+	ics->nested += 1;
+	if (ifbody)
+	    cost += ifbody->inlineCost(ics);
+	if (elsebody)
+	    cost += elsebody->inlineCost(ics);
+	ics->nested -= 1;
+    }
+    return cost;
+}
+
+int ReturnStatement::inlineCost(InlineCostState *ics)
+{
+    // Can't handle return statements nested in if's
+    if (ics->nested)
+	return COST_MAX;
+    return exp ? exp->inlineCost(ics) : 0;
+}
+
+/* -------------------------- */
+
+int arrayInlineCost(InlineCostState *ics, Array *arguments)
+{   int cost = 0;
+
+    if (arguments)
+    {
+	for (int i = 0; i < arguments->dim; i++)
+	{   Expression *e = (Expression *)arguments->data[i];
+
+	    if (e)
+		cost += e->inlineCost(ics);
+	}
+    }
+    return cost;
+}
+
+int Expression::inlineCost(InlineCostState *ics)
+{
+    return 1;
+}
+
+int VarExp::inlineCost(InlineCostState *ics)
+{
+    //printf("VarExp::inlineCost() %s\n", toChars());
+    return 1;
+}
+
+int ThisExp::inlineCost(InlineCostState *ics)
+{
+    FuncDeclaration *fd = ics->fd;
+    if (!ics->hdrscan)
+	if (fd->isNested() || !ics->hasthis)
+	    return COST_MAX;
+    return 1;
+}
+
+int SuperExp::inlineCost(InlineCostState *ics)
+{
+    FuncDeclaration *fd = ics->fd;
+    if (!ics->hdrscan)
+	if (fd->isNested() || !ics->hasthis)
+	    return COST_MAX;
+    return 1;
+}
+
+int TupleExp::inlineCost(InlineCostState *ics)
+{
+    return 1 + arrayInlineCost(ics, exps);
+}
+
+int ArrayLiteralExp::inlineCost(InlineCostState *ics)
+{
+    return 1 + arrayInlineCost(ics, elements);
+}
+
+int AssocArrayLiteralExp::inlineCost(InlineCostState *ics)
+{
+    return 1 + arrayInlineCost(ics, keys) + arrayInlineCost(ics, values);
+}
+
+int StructLiteralExp::inlineCost(InlineCostState *ics)
+{
+    return 1 + arrayInlineCost(ics, elements);
+}
+
+int FuncExp::inlineCost(InlineCostState *ics)
+{
+    // Right now, this makes the function be output to the .obj file twice.
+    return COST_MAX;
+}
+
+int DelegateExp::inlineCost(InlineCostState *ics)
+{
+    return COST_MAX;
+}
+
+int DeclarationExp::inlineCost(InlineCostState *ics)
+{   int cost = 0;
+    VarDeclaration *vd;
+
+    //printf("DeclarationExp::inlineCost()\n");
+    vd = declaration->isVarDeclaration();
+    if (vd)
+    {
+	TupleDeclaration *td = vd->toAlias()->isTupleDeclaration();
+	if (td)
+	{
+#if 1
+	    return COST_MAX;	// finish DeclarationExp::doInline
+#else
+	    for (size_t i = 0; i < td->objects->dim; i++)
+	    {   Object *o = (Object *)td->objects->data[i];
+		if (o->dyncast() != DYNCAST_EXPRESSION)
+		    return COST_MAX;
+		Expression *eo = (Expression *)o;
+		if (eo->op != TOKdsymbol)
+		    return COST_MAX;
+	    }
+	    return td->objects->dim;
+#endif
+	}
+	if (!ics->hdrscan && vd->isDataseg())
+	    return COST_MAX;
+	cost += 1;
+
+	// Scan initializer (vd->init)
+	if (vd->init)
+	{
+	    ExpInitializer *ie = vd->init->isExpInitializer();
+
+	    if (ie)
+	    {
+		cost += ie->exp->inlineCost(ics);
+	    }
+	}
+    }
+
+    // These can contain functions, which when copied, get output twice.
+    if (declaration->isStructDeclaration() ||
+	declaration->isClassDeclaration() ||
+	declaration->isFuncDeclaration() ||
+	declaration->isTypedefDeclaration() ||
+	declaration->isTemplateMixin())
+	return COST_MAX;
+
+    //printf("DeclarationExp::inlineCost('%s')\n", toChars());
+    return cost;
+}
+
+int UnaExp::inlineCost(InlineCostState *ics)
+{
+    return 1 + e1->inlineCost(ics);
+}
+
+int AssertExp::inlineCost(InlineCostState *ics)
+{
+    return 1 + e1->inlineCost(ics) + (msg ? msg->inlineCost(ics) : 0);
+}
+
+int BinExp::inlineCost(InlineCostState *ics)
+{
+    return 1 + e1->inlineCost(ics) + e2->inlineCost(ics);
+}
+
+int CallExp::inlineCost(InlineCostState *ics)
+{
+    return 1 + e1->inlineCost(ics) + arrayInlineCost(ics, arguments);
+}
+
+int SliceExp::inlineCost(InlineCostState *ics)
+{   int cost;
+
+    cost = 1 + e1->inlineCost(ics);
+    if (lwr)
+	cost += lwr->inlineCost(ics);
+    if (upr)
+	cost += upr->inlineCost(ics);
+    return cost;
+}
+
+int ArrayExp::inlineCost(InlineCostState *ics)
+{
+    return 1 + e1->inlineCost(ics) + arrayInlineCost(ics, arguments);
+}
+
+
+int CondExp::inlineCost(InlineCostState *ics)
+{
+    return 1 +
+	 e1->inlineCost(ics) +
+	 e2->inlineCost(ics) +
+	 econd->inlineCost(ics);
+}
+
+
+/* ======================== Perform the inlining ============================== */
+
+/* Inlining is done by:
+ * o	Converting to an Expression
+ * o	Copying the trees of the function to be inlined
+ * o	Renaming the variables
+ */
+
+struct InlineDoState
+{
+    VarDeclaration *vthis;
+    Array from;		// old Dsymbols
+    Array to;		// parallel array of new Dsymbols
+    Dsymbol *parent;	// new parent
+};
+
+Expression *Statement::doInline(InlineDoState *ids)
+{
+    assert(0);
+    return NULL;		// default is we can't inline it
+}
+
+Expression *ExpStatement::doInline(InlineDoState *ids)
+{
+#if LOG
+    if (exp) printf("ExpStatement::doInline() '%s'\n", exp->toChars());
+#endif
+    return exp ? exp->doInline(ids) : NULL;
+}
+
+Expression *CompoundStatement::doInline(InlineDoState *ids)
+{
+    Expression *e = NULL;
+
+    //printf("CompoundStatement::doInline() %d\n", statements->dim);
+    for (size_t i = 0; i < statements->dim; i++)
+    {	Statement *s = (Statement *) statements->data[i];
+	if (s)
+	{
+	    Expression *e2 = s->doInline(ids);
+	    e = Expression::combine(e, e2);
+	    if (s->isReturnStatement())
+		break;
+
+	    /* Check for:
+	     *	if (condition)
+	     *	    return exp1;
+	     *	else
+	     *	    return exp2;
+	     */
+	    IfStatement *ifs = s->isIfStatement();
+	    if (ifs && ifs->elsebody && ifs->ifbody &&
+		ifs->ifbody->isReturnStatement() &&
+		ifs->elsebody->isReturnStatement()
+	       )
+		break;
+
+	}
+    }
+    return e;
+}
+
+Expression *UnrolledLoopStatement::doInline(InlineDoState *ids)
+{
+    Expression *e = NULL;
+
+    //printf("UnrolledLoopStatement::doInline() %d\n", statements->dim);
+    for (size_t i = 0; i < statements->dim; i++)
+    {	Statement *s = (Statement *) statements->data[i];
+	if (s)
+	{
+	    Expression *e2 = s->doInline(ids);
+	    e = Expression::combine(e, e2);
+	    if (s->isReturnStatement())
+		break;
+	}
+    }
+    return e;
+}
+
+Expression *IfStatement::doInline(InlineDoState *ids)
+{
+    Expression *econd;
+    Expression *e1;
+    Expression *e2;
+    Expression *e;
+
+    assert(!arg);
+    econd = condition->doInline(ids);
+    assert(econd);
+    if (ifbody)
+	e1 = ifbody->doInline(ids);
+    else
+	e1 = NULL;
+    if (elsebody)
+	e2 = elsebody->doInline(ids);
+    else
+	e2 = NULL;
+    if (e1 && e2)
+    {
+	e = new CondExp(econd->loc, econd, e1, e2);
+	e->type = e1->type;
+    }
+    else if (e1)
+    {
+	e = new AndAndExp(econd->loc, econd, e1);
+	e->type = Type::tvoid;
+    }
+    else if (e2)
+    {
+	e = new OrOrExp(econd->loc, econd, e2);
+	e->type = Type::tvoid;
+    }
+    else
+    {
+	e = econd;
+    }
+    return e;
+}
+
+Expression *ReturnStatement::doInline(InlineDoState *ids)
+{
+    //printf("ReturnStatement::doInline() '%s'\n", exp ? exp->toChars() : "");
+    return exp ? exp->doInline(ids) : 0;
+}
+
+/* --------------------------------------------------------------- */
+
+/******************************
+ * Perform doInline() on an array of Expressions.
+ */
+
+Expressions *arrayExpressiondoInline(Expressions *a, InlineDoState *ids)
+{   Expressions *newa = NULL;
+
+    if (a)
+    {
+	newa = new Expressions();
+	newa->setDim(a->dim);
+
+	for (int i = 0; i < a->dim; i++)
+	{   Expression *e = (Expression *)a->data[i];
+
+	    if (e)
+	    {
+		e = e->doInline(ids);
+		newa->data[i] = (void *)e;
+	    }
+	}
+    }
+    return newa;
+}
+
+Expression *Expression::doInline(InlineDoState *ids)
+{
+    //printf("Expression::doInline(%s): %s\n", Token::toChars(op), toChars());
+    return copy();
+}
+
+Expression *SymOffExp::doInline(InlineDoState *ids)
+{
+    int i;
+
+    //printf("SymOffExp::doInline(%s)\n", toChars());
+    for (i = 0; i < ids->from.dim; i++)
+    {
+	if (var == (Declaration *)ids->from.data[i])
+	{
+	    SymOffExp *se = (SymOffExp *)copy();
+
+	    se->var = (Declaration *)ids->to.data[i];
+	    return se;
+	}
+    }
+    return this;
+}
+
+Expression *VarExp::doInline(InlineDoState *ids)
+{
+    int i;
+
+    //printf("VarExp::doInline(%s)\n", toChars());
+    for (i = 0; i < ids->from.dim; i++)
+    {
+	if (var == (Declaration *)ids->from.data[i])
+	{
+	    VarExp *ve = (VarExp *)copy();
+
+	    ve->var = (Declaration *)ids->to.data[i];
+	    return ve;
+	}
+    }
+    return this;
+}
+
+Expression *ThisExp::doInline(InlineDoState *ids)
+{
+    //if (!ids->vthis)
+	//error("no 'this' when inlining %s", ids->parent->toChars());
+    if (!ids->vthis)
+    {
+	return this;
+    }
+
+    VarExp *ve = new VarExp(loc, ids->vthis);
+    ve->type = type;
+    return ve;
+}
+
+Expression *SuperExp::doInline(InlineDoState *ids)
+{
+    assert(ids->vthis);
+
+    VarExp *ve = new VarExp(loc, ids->vthis);
+    ve->type = type;
+    return ve;
+}
+
+Expression *DeclarationExp::doInline(InlineDoState *ids)
+{   DeclarationExp *de = (DeclarationExp *)copy();
+    VarDeclaration *vd;
+
+    //printf("DeclarationExp::doInline(%s)\n", toChars());
+    vd = declaration->isVarDeclaration();
+    if (vd)
+    {
+#if 0
+	// Need to figure this out before inlining can work for tuples
+	TupleDeclaration *td = vd->toAlias()->isTupleDeclaration();
+	if (td)
+	{
+	    for (size_t i = 0; i < td->objects->dim; i++)
+	    {   DsymbolExp *se = (DsymbolExp *)td->objects->data[i];
+		assert(se->op == TOKdsymbol);
+		se->s;
+	    }
+	    return st->objects->dim;
+	}
+#endif
+	if (vd->isStatic())
+	    ;
+	else
+	{
+	    VarDeclaration *vto;
+
+	    vto = new VarDeclaration(vd->loc, vd->type, vd->ident, vd->init);
+	    *vto = *vd;
+	    vto->parent = ids->parent;
+#if IN_DMD
+	    vto->csym = NULL;
+	    vto->isym = NULL;
+#endif
+
+	    ids->from.push(vd);
+	    ids->to.push(vto);
+
+	    if (vd->init)
+	    {
+		if (vd->init->isVoidInitializer())
+		{
+		    vto->init = new VoidInitializer(vd->init->loc);
+		}
+		else
+		{
+		    Expression *e = vd->init->toExpression();
+		    assert(e);
+		    vto->init = new ExpInitializer(e->loc, e->doInline(ids));
+		}
+	    }
+	    de->declaration = (Dsymbol *) (void *)vto;
+	}
+    }
+    /* This needs work, like DeclarationExp::toElem(), if we are
+     * to handle TemplateMixin's. For now, we just don't inline them.
+     */
+    return de;
+}
+
+Expression *NewExp::doInline(InlineDoState *ids)
+{
+    //printf("NewExp::doInline(): %s\n", toChars());
+    NewExp *ne = (NewExp *)copy();
+
+    if (thisexp)
+	ne->thisexp = thisexp->doInline(ids);
+    ne->newargs = arrayExpressiondoInline(ne->newargs, ids);
+    ne->arguments = arrayExpressiondoInline(ne->arguments, ids);
+    return ne;
+}
+
+Expression *UnaExp::doInline(InlineDoState *ids)
+{
+    UnaExp *ue = (UnaExp *)copy();
+
+    ue->e1 = e1->doInline(ids);
+    return ue;
+}
+
+Expression *AssertExp::doInline(InlineDoState *ids)
+{
+    AssertExp *ae = (AssertExp *)copy();
+
+    ae->e1 = e1->doInline(ids);
+    if (msg)
+	ae->msg = msg->doInline(ids);
+    return ae;
+}
+
+Expression *BinExp::doInline(InlineDoState *ids)
+{
+    BinExp *be = (BinExp *)copy();
+
+    be->e1 = e1->doInline(ids);
+    be->e2 = e2->doInline(ids);
+    return be;
+}
+
+Expression *CallExp::doInline(InlineDoState *ids)
+{
+    CallExp *ce;
+
+    ce = (CallExp *)copy();
+    ce->e1 = e1->doInline(ids);
+    ce->arguments = arrayExpressiondoInline(arguments, ids);
+    return ce;
+}
+
+
+Expression *IndexExp::doInline(InlineDoState *ids)
+{
+    IndexExp *are = (IndexExp *)copy();
+
+    are->e1 = e1->doInline(ids);
+
+    if (lengthVar)
+    {	//printf("lengthVar\n");
+	VarDeclaration *vd = lengthVar;
+	ExpInitializer *ie;
+	ExpInitializer *ieto;
+	VarDeclaration *vto;
+
+	vto = new VarDeclaration(vd->loc, vd->type, vd->ident, vd->init);
+	*vto = *vd;
+	vto->parent = ids->parent;
+#if IN_DMD
+	vto->csym = NULL;
+	vto->isym = NULL;
+#endif
+
+	ids->from.push(vd);
+	ids->to.push(vto);
+
+	if (vd->init)
+	{
+	    ie = vd->init->isExpInitializer();
+	    assert(ie);
+	    ieto = new ExpInitializer(ie->loc, ie->exp->doInline(ids));
+	    vto->init = ieto;
+	}
+
+	are->lengthVar = (VarDeclaration *) (void *)vto;
+    }
+    are->e2 = e2->doInline(ids);
+    return are;
+}
+
+
+Expression *SliceExp::doInline(InlineDoState *ids)
+{
+    SliceExp *are = (SliceExp *)copy();
+
+    are->e1 = e1->doInline(ids);
+
+    if (lengthVar)
+    {	//printf("lengthVar\n");
+	VarDeclaration *vd = lengthVar;
+	ExpInitializer *ie;
+	ExpInitializer *ieto;
+	VarDeclaration *vto;
+
+	vto = new VarDeclaration(vd->loc, vd->type, vd->ident, vd->init);
+	*vto = *vd;
+	vto->parent = ids->parent;
+#if IN_DMD
+	vto->csym = NULL;
+	vto->isym = NULL;
+#endif
+
+	ids->from.push(vd);
+	ids->to.push(vto);
+
+	if (vd->init)
+	{
+	    ie = vd->init->isExpInitializer();
+	    assert(ie);
+	    ieto = new ExpInitializer(ie->loc, ie->exp->doInline(ids));
+	    vto->init = ieto;
+	}
+
+	are->lengthVar = (VarDeclaration *) (void *)vto;
+    }
+    if (lwr)
+	are->lwr = lwr->doInline(ids);
+    if (upr)
+	are->upr = upr->doInline(ids);
+    return are;
+}
+
+
+Expression *TupleExp::doInline(InlineDoState *ids)
+{
+    TupleExp *ce;
+
+    ce = (TupleExp *)copy();
+    ce->exps = arrayExpressiondoInline(exps, ids);
+    return ce;
+}
+
+
+Expression *ArrayLiteralExp::doInline(InlineDoState *ids)
+{
+    ArrayLiteralExp *ce;
+
+    ce = (ArrayLiteralExp *)copy();
+    ce->elements = arrayExpressiondoInline(elements, ids);
+    return ce;
+}
+
+
+Expression *AssocArrayLiteralExp::doInline(InlineDoState *ids)
+{
+    AssocArrayLiteralExp *ce;
+
+    ce = (AssocArrayLiteralExp *)copy();
+    ce->keys = arrayExpressiondoInline(keys, ids);
+    ce->values = arrayExpressiondoInline(values, ids);
+    return ce;
+}
+
+
+Expression *StructLiteralExp::doInline(InlineDoState *ids)
+{
+    StructLiteralExp *ce;
+
+    ce = (StructLiteralExp *)copy();
+    ce->elements = arrayExpressiondoInline(elements, ids);
+    return ce;
+}
+
+
+Expression *ArrayExp::doInline(InlineDoState *ids)
+{
+    ArrayExp *ce;
+
+    ce = (ArrayExp *)copy();
+    ce->e1 = e1->doInline(ids);
+    ce->arguments = arrayExpressiondoInline(arguments, ids);
+    return ce;
+}
+
+
+Expression *CondExp::doInline(InlineDoState *ids)
+{
+    CondExp *ce = (CondExp *)copy();
+
+    ce->econd = econd->doInline(ids);
+    ce->e1 = e1->doInline(ids);
+    ce->e2 = e2->doInline(ids);
+    return ce;
+}
+
+
+/* ========== Walk the parse trees, and inline expand functions ============= */
+
+/* Walk the trees, looking for functions to inline.
+ * Inline any that can be.
+ */
+
+struct InlineScanState
+{
+    FuncDeclaration *fd;	// function being scanned
+};
+
+Statement *Statement::inlineScan(InlineScanState *iss)
+{
+    return this;
+}
+
+Statement *ExpStatement::inlineScan(InlineScanState *iss)
+{
+#if LOG
+    printf("ExpStatement::inlineScan(%s)\n", toChars());
+#endif
+    if (exp)
+	exp = exp->inlineScan(iss);
+    return this;
+}
+
+Statement *CompoundStatement::inlineScan(InlineScanState *iss)
+{
+    for (size_t i = 0; i < statements->dim; i++)
+    {	Statement *s = (Statement *) statements->data[i];
+	if (s)
+	    statements->data[i] = (void *)s->inlineScan(iss);
+    }
+    return this;
+}
+
+Statement *UnrolledLoopStatement::inlineScan(InlineScanState *iss)
+{
+    for (size_t i = 0; i < statements->dim; i++)
+    {	Statement *s = (Statement *) statements->data[i];
+	if (s)
+	    statements->data[i] = (void *)s->inlineScan(iss);
+    }
+    return this;
+}
+
+Statement *ScopeStatement::inlineScan(InlineScanState *iss)
+{
+    if (statement)
+	statement = statement->inlineScan(iss);
+    return this;
+}
+
+Statement *WhileStatement::inlineScan(InlineScanState *iss)
+{
+    condition = condition->inlineScan(iss);
+    body = body ? body->inlineScan(iss) : NULL;
+    return this;
+}
+
+
+Statement *DoStatement::inlineScan(InlineScanState *iss)
+{
+    body = body ? body->inlineScan(iss) : NULL;
+    condition = condition->inlineScan(iss);
+    return this;
+}
+
+
+Statement *ForStatement::inlineScan(InlineScanState *iss)
+{
+    if (init)
+	init = init->inlineScan(iss);
+    if (condition)
+	condition = condition->inlineScan(iss);
+    if (increment)
+	increment = increment->inlineScan(iss);
+    body = body->inlineScan(iss);
+    return this;
+}
+
+
+Statement *ForeachStatement::inlineScan(InlineScanState *iss)
+{
+    aggr = aggr->inlineScan(iss);
+    if (body)
+	body = body->inlineScan(iss);
+    return this;
+}
+
+
+#if DMDV2
+Statement *ForeachRangeStatement::inlineScan(InlineScanState *iss)
+{
+    lwr = lwr->inlineScan(iss);
+    upr = upr->inlineScan(iss);
+    if (body)
+	body = body->inlineScan(iss);
+    return this;
+}
+#endif
+
+
+Statement *IfStatement::inlineScan(InlineScanState *iss)
+{
+    condition = condition->inlineScan(iss);
+    if (ifbody)
+	ifbody = ifbody->inlineScan(iss);
+    if (elsebody)
+	elsebody = elsebody->inlineScan(iss);
+    return this;
+}
+
+
+Statement *SwitchStatement::inlineScan(InlineScanState *iss)
+{
+    //printf("SwitchStatement::inlineScan()\n");
+    condition = condition->inlineScan(iss);
+    body = body ? body->inlineScan(iss) : NULL;
+    if (sdefault)
+	sdefault = (DefaultStatement *)sdefault->inlineScan(iss);
+    if (cases)
+    {
+	for (int i = 0; i < cases->dim; i++)
+	{   Statement *s;
+
+	    s = (Statement *) cases->data[i];
+	    cases->data[i] = (void *)s->inlineScan(iss);
+	}
+    }
+    return this;
+}
+
+
+Statement *CaseStatement::inlineScan(InlineScanState *iss)
+{
+    //printf("CaseStatement::inlineScan()\n");
+    exp = exp->inlineScan(iss);
+    if (statement)
+	statement = statement->inlineScan(iss);
+    return this;
+}
+
+
+Statement *DefaultStatement::inlineScan(InlineScanState *iss)
+{
+    if (statement)
+	statement = statement->inlineScan(iss);
+    return this;
+}
+
+
+Statement *ReturnStatement::inlineScan(InlineScanState *iss)
+{
+    //printf("ReturnStatement::inlineScan()\n");
+    if (exp)
+    {
+	exp = exp->inlineScan(iss);
+    }
+    return this;
+}
+
+
+Statement *SynchronizedStatement::inlineScan(InlineScanState *iss)
+{
+    if (exp)
+	exp = exp->inlineScan(iss);
+    if (body)
+	body = body->inlineScan(iss);
+    return this;
+}
+
+
+Statement *WithStatement::inlineScan(InlineScanState *iss)
+{
+    if (exp)
+	exp = exp->inlineScan(iss);
+    if (body)
+	body = body->inlineScan(iss);
+    return this;
+}
+
+
+Statement *TryCatchStatement::inlineScan(InlineScanState *iss)
+{
+    if (body)
+	body = body->inlineScan(iss);
+    if (catches)
+    {
+	for (int i = 0; i < catches->dim; i++)
+	{   Catch *c = (Catch *)catches->data[i];
+
+	    if (c->handler)
+		c->handler = c->handler->inlineScan(iss);
+	}
+    }
+    return this;
+}
+
+
+Statement *TryFinallyStatement::inlineScan(InlineScanState *iss)
+{
+    if (body)
+	body = body->inlineScan(iss);
+    if (finalbody)
+	finalbody = finalbody->inlineScan(iss);
+    return this;
+}
+
+
+Statement *ThrowStatement::inlineScan(InlineScanState *iss)
+{
+    if (exp)
+	exp = exp->inlineScan(iss);
+    return this;
+}
+
+
+Statement *VolatileStatement::inlineScan(InlineScanState *iss)
+{
+    if (statement)
+	statement = statement->inlineScan(iss);
+    return this;
+}
+
+
+Statement *LabelStatement::inlineScan(InlineScanState *iss)
+{
+    if (statement)
+	statement = statement->inlineScan(iss);
+    return this;
+}
+
+/* -------------------------- */
+
+void arrayInlineScan(InlineScanState *iss, Array *arguments)
+{
+    if (arguments)
+    {
+	for (int i = 0; i < arguments->dim; i++)
+	{   Expression *e = (Expression *)arguments->data[i];
+
+	    if (e)
+	    {
+		e = e->inlineScan(iss);
+		arguments->data[i] = (void *)e;
+	    }
+	}
+    }
+}
+
+Expression *Expression::inlineScan(InlineScanState *iss)
+{
+    return this;
+}
+
+void scanVar(Dsymbol *s, InlineScanState *iss)
+{
+    VarDeclaration *vd = s->isVarDeclaration();
+    if (vd)
+    {
+	TupleDeclaration *td = vd->toAlias()->isTupleDeclaration();
+	if (td)
+	{
+	    for (size_t i = 0; i < td->objects->dim; i++)
+	    {   DsymbolExp *se = (DsymbolExp *)td->objects->data[i];
+		assert(se->op == TOKdsymbol);
+		scanVar(se->s, iss);
+	    }
+	}
+	else
+	{
+	    // Scan initializer (vd->init)
+	    if (vd->init)
+	    {
+		ExpInitializer *ie = vd->init->isExpInitializer();
+
+		if (ie)
+		{
+		    ie->exp = ie->exp->inlineScan(iss);
+		}
+	    }
+	}
+    }
+}
+
+Expression *DeclarationExp::inlineScan(InlineScanState *iss)
+{
+    //printf("DeclarationExp::inlineScan()\n");
+    scanVar(declaration, iss);
+    return this;
+}
+
+Expression *UnaExp::inlineScan(InlineScanState *iss)
+{
+    e1 = e1->inlineScan(iss);
+    return this;
+}
+
+Expression *AssertExp::inlineScan(InlineScanState *iss)
+{
+    e1 = e1->inlineScan(iss);
+    if (msg)
+	msg = msg->inlineScan(iss);
+    return this;
+}
+
+Expression *BinExp::inlineScan(InlineScanState *iss)
+{
+    e1 = e1->inlineScan(iss);
+    e2 = e2->inlineScan(iss);
+    return this;
+}
+
+
+Expression *CallExp::inlineScan(InlineScanState *iss)
+{   Expression *e = this;
+
+    //printf("CallExp::inlineScan()\n");
+    e1 = e1->inlineScan(iss);
+    arrayInlineScan(iss, arguments);
+
+    if (e1->op == TOKvar)
+    {
+	VarExp *ve = (VarExp *)e1;
+	FuncDeclaration *fd = ve->var->isFuncDeclaration();
+
+	if (fd && fd != iss->fd && fd->canInline(0))
+	{
+	    e = fd->doInline(iss, NULL, arguments);
+	}
+    }
+    else if (e1->op == TOKdotvar)
+    {
+	DotVarExp *dve = (DotVarExp *)e1;
+	FuncDeclaration *fd = dve->var->isFuncDeclaration();
+
+	if (fd && fd != iss->fd && fd->canInline(1))
+	{
+	    if (dve->e1->op == TOKcall &&
+		dve->e1->type->toBasetype()->ty == Tstruct)
+	    {
+		/* To create ethis, we'll need to take the address
+		 * of dve->e1, but this won't work if dve->e1 is
+		 * a function call.
+		 */
+		;
+	    }
+	    else
+		e = fd->doInline(iss, dve->e1, arguments);
+	}
+    }
+
+    return e;
+}
+
+
+Expression *SliceExp::inlineScan(InlineScanState *iss)
+{
+    e1 = e1->inlineScan(iss);
+    if (lwr)
+	lwr = lwr->inlineScan(iss);
+    if (upr)
+	upr = upr->inlineScan(iss);
+    return this;
+}
+
+
+Expression *TupleExp::inlineScan(InlineScanState *iss)
+{   Expression *e = this;
+
+    //printf("TupleExp::inlineScan()\n");
+    arrayInlineScan(iss, exps);
+
+    return e;
+}
+
+
+Expression *ArrayLiteralExp::inlineScan(InlineScanState *iss)
+{   Expression *e = this;
+
+    //printf("ArrayLiteralExp::inlineScan()\n");
+    arrayInlineScan(iss, elements);
+
+    return e;
+}
+
+
+Expression *AssocArrayLiteralExp::inlineScan(InlineScanState *iss)
+{   Expression *e = this;
+
+    //printf("AssocArrayLiteralExp::inlineScan()\n");
+    arrayInlineScan(iss, keys);
+    arrayInlineScan(iss, values);
+
+    return e;
+}
+
+
+Expression *StructLiteralExp::inlineScan(InlineScanState *iss)
+{   Expression *e = this;
+
+    //printf("StructLiteralExp::inlineScan()\n");
+    arrayInlineScan(iss, elements);
+
+    return e;
+}
+
+
+Expression *ArrayExp::inlineScan(InlineScanState *iss)
+{   Expression *e = this;
+
+    //printf("ArrayExp::inlineScan()\n");
+    e1 = e1->inlineScan(iss);
+    arrayInlineScan(iss, arguments);
+
+    return e;
+}
+
+
+Expression *CondExp::inlineScan(InlineScanState *iss)
+{
+    econd = econd->inlineScan(iss);
+    e1 = e1->inlineScan(iss);
+    e2 = e2->inlineScan(iss);
+    return this;
+}
+
+
+/* ==========  =============== */
+
+void FuncDeclaration::inlineScan()
+{
+    InlineScanState iss;
+
+#if LOG
+    printf("FuncDeclaration::inlineScan('%s')\n", toChars());
+#endif
+    memset(&iss, 0, sizeof(iss));
+    iss.fd = this;
+    if (fbody)
+    {
+	inlineNest++;
+	fbody = fbody->inlineScan(&iss);
+	inlineNest--;
+    }
+}
+
+int FuncDeclaration::canInline(int hasthis, int hdrscan)
+{
+    InlineCostState ics;
+    int cost;
+
+#define CANINLINE_LOG 0
+
+#if CANINLINE_LOG
+    printf("FuncDeclaration::canInline(hasthis = %d, '%s')\n", hasthis, toChars());
+#endif
+
+    if (needThis() && !hasthis)
+	return 0;
+
+    if (inlineNest || (semanticRun < 3 && !hdrscan))
+    {
+#if CANINLINE_LOG
+	printf("\t1: no, inlineNest = %d, semanticRun = %d\n", inlineNest, semanticRun);
+#endif
+	return 0;
+    }
+
+    switch (inlineStatus)
+    {
+	case ILSyes:
+#if CANINLINE_LOG
+	    printf("\t1: yes %s\n", toChars());
+#endif
+	    return 1;
+
+	case ILSno:
+#if CANINLINE_LOG
+	    printf("\t1: no %s\n", toChars());
+#endif
+	    return 0;
+
+	case ILSuninitialized:
+	    break;
+
+	default:
+	    assert(0);
+    }
+
+    if (type)
+    {	assert(type->ty == Tfunction);
+	TypeFunction *tf = (TypeFunction *)(type);
+	if (tf->varargs == 1)	// no variadic parameter lists
+	    goto Lno;
+
+	/* Don't inline a function that returns non-void, but has
+	 * no return expression.
+	 */
+	if (tf->next && tf->next->ty != Tvoid &&
+	    !(hasReturnExp & 1) &&
+	    !hdrscan)
+	    goto Lno;
+    }
+    else
+    {	CtorDeclaration *ctor = isCtorDeclaration();
+
+	if (ctor && ctor->varargs == 1)
+	    goto Lno;
+    }
+
+    if (
+	!fbody ||
+	!hdrscan &&
+	(
+#if 0
+	isCtorDeclaration() ||	// cannot because need to convert:
+				//	return;
+				// to:
+				//	return this;
+#endif
+	isSynchronized() ||
+	isImportedSymbol() ||
+#if DMDV2
+	closureVars.dim ||	// no nested references to this frame
+#else
+	nestedFrameRef ||	// no nested references to this frame
+#endif
+	(isVirtual() && !isFinal())
+       ))
+    {
+	goto Lno;
+    }
+
+    /* If any parameters are Tsarray's (which are passed by reference)
+     * or out parameters (also passed by reference), don't do inlining.
+     */
+    if (parameters)
+    {
+	for (int i = 0; i < parameters->dim; i++)
+	{
+	    VarDeclaration *v = (VarDeclaration *)parameters->data[i];
+	    if (v->isOut() || v->isRef() || v->type->toBasetype()->ty == Tsarray)
+		goto Lno;
+	}
+    }
+
+    memset(&ics, 0, sizeof(ics));
+    ics.hasthis = hasthis;
+    ics.fd = this;
+    ics.hdrscan = hdrscan;
+    cost = fbody->inlineCost(&ics);
+#if CANINLINE_LOG
+    printf("cost = %d\n", cost);
+#endif
+    if (cost >= COST_MAX)
+	goto Lno;
+
+    if (!hdrscan)    // Don't scan recursively for header content scan
+	inlineScan();
+
+Lyes:
+    if (!hdrscan)    // Don't modify inlineStatus for header content scan
+	inlineStatus = ILSyes;
+#if CANINLINE_LOG
+    printf("\t2: yes %s\n", toChars());
+#endif
+    return 1;
+
+Lno:
+    if (!hdrscan)    // Don't modify inlineStatus for header content scan
+	inlineStatus = ILSno;
+#if CANINLINE_LOG
+    printf("\t2: no %s\n", toChars());
+#endif
+    return 0;
+}
+
+Expression *FuncDeclaration::doInline(InlineScanState *iss, Expression *ethis, Array *arguments)
+{
+    InlineDoState ids;
+    DeclarationExp *de;
+    Expression *e = NULL;
+
+#if LOG
+    printf("FuncDeclaration::doInline('%s')\n", toChars());
+#endif
+
+    memset(&ids, 0, sizeof(ids));
+    ids.parent = iss->fd;
+
+    // Set up vthis
+    if (ethis)
+    {
+	VarDeclaration *vthis;
+	ExpInitializer *ei;
+	VarExp *ve;
+
+#if STRUCTTHISREF
+	if (ethis->type->ty == Tpointer)
+	{   Type *t = ethis->type->nextOf();
+	    ethis = new PtrExp(ethis->loc, ethis);
+	    ethis->type = t;
+	}
+	ei = new ExpInitializer(ethis->loc, ethis);
+
+	vthis = new VarDeclaration(ethis->loc, ethis->type, Id::This, ei);
+	if (ethis->type->ty != Tclass)
+	    vthis->storage_class = STCref;
+	else
+	    vthis->storage_class = STCin;
+#else
+	if (ethis->type->ty != Tclass && ethis->type->ty != Tpointer)
+	{
+	    ethis = ethis->addressOf(NULL);
+	}
+
+	ei = new ExpInitializer(ethis->loc, ethis);
+
+	vthis = new VarDeclaration(ethis->loc, ethis->type, Id::This, ei);
+	vthis->storage_class = STCin;
+#endif
+	vthis->linkage = LINKd;
+	vthis->parent = iss->fd;
+
+	ve = new VarExp(vthis->loc, vthis);
+	ve->type = vthis->type;
+
+	ei->exp = new AssignExp(vthis->loc, ve, ethis);
+	ei->exp->type = ve->type;
+#if STRUCTTHISREF
+	if (ethis->type->ty != Tclass)
+	{   /* This is a reference initialization, not a simple assignment.
+	     */
+	    ei->exp->op = TOKconstruct;
+	}
+#endif
+
+	ids.vthis = vthis;
+    }
+
+    // Set up parameters
+    if (ethis)
+    {
+	e = new DeclarationExp(0, ids.vthis);
+	e->type = Type::tvoid;
+    }
+
+    if (arguments && arguments->dim)
+    {
+	assert(parameters->dim == arguments->dim);
+
+	for (int i = 0; i < arguments->dim; i++)
+	{
+	    VarDeclaration *vfrom = (VarDeclaration *)parameters->data[i];
+	    VarDeclaration *vto;
+	    Expression *arg = (Expression *)arguments->data[i];
+	    ExpInitializer *ei;
+	    VarExp *ve;
+
+	    ei = new ExpInitializer(arg->loc, arg);
+
+	    vto = new VarDeclaration(vfrom->loc, vfrom->type, vfrom->ident, ei);
+	    vto->storage_class |= vfrom->storage_class & (STCin | STCout | STClazy | STCref);
+	    vto->linkage = vfrom->linkage;
+	    vto->parent = iss->fd;
+	    //printf("vto = '%s', vto->storage_class = x%x\n", vto->toChars(), vto->storage_class);
+	    //printf("vto->parent = '%s'\n", iss->fd->toChars());
+
+	    ve = new VarExp(vto->loc, vto);
+	    //ve->type = vto->type;
+	    ve->type = arg->type;
+
+	    ei->exp = new AssignExp(vto->loc, ve, arg);
+	    ei->exp->type = ve->type;
+//ve->type->print();
+//arg->type->print();
+//ei->exp->print();
+
+	    ids.from.push(vfrom);
+	    ids.to.push(vto);
+
+	    de = new DeclarationExp(0, vto);
+	    de->type = Type::tvoid;
+
+	    e = Expression::combine(e, de);
+	}
+    }
+
+    inlineNest++;
+    Expression *eb = fbody->doInline(&ids);
+    inlineNest--;
+    return Expression::combine(e, eb);
+}
+
+
+
--- a/dmd2/interpret.c	Mon Jun 01 01:28:18 2009 +0200
+++ b/dmd2/interpret.c	Mon Jun 01 19:02:20 2009 +0100
@@ -12,7 +12,7 @@
 #include <stdlib.h>
 #include <assert.h>
 
-#include "mem.h"
+#include "rmem.h"
 
 #include "statement.h"
 #include "expression.h"
@@ -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 (global.errors)	// if errors compiling this function
+	    return NULL;
     }
-    if (semanticRun < 2)
+    if (semanticRun < 4)
 	return NULL;
 
     Type *tb = type->toBasetype();
@@ -987,7 +987,11 @@
 {
     Expression *e = EXP_CANT_INTERPRET;
     VarDeclaration *v = d->isVarDeclaration();
+#if IN_LLVM
     StaticStructInitDeclaration *s = d->isStaticStructInitDeclaration();
+#else
+    SymbolDeclaration *s = d->isSymbolDeclaration();
+#endif
     if (v)
     {
 #if DMDV2
@@ -1513,6 +1517,80 @@
 	}
     }
     /* Assignment to struct member of the form:
+     *   v.var = e2
+     */
+    else if (e1->op == TOKdotvar && ((DotVarExp *)e1)->e1->op == TOKvar)
+    {	VarExp *ve = (VarExp *)((DotVarExp *)e1)->e1;
+	VarDeclaration *v = ve->var->isVarDeclaration();
+
+	if (v->isDataseg())
+	    return EXP_CANT_INTERPRET;
+	if (fp && !v->value)
+	{   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)
+	{
+	    Declaration *d = ((VarExp *)vie)->var;
+	    vie = getVarExp(e1->loc, istate, d);
+	}
+	if (vie->op != TOKstructliteral)
+	    return EXP_CANT_INTERPRET;
+	StructLiteralExp *se = (StructLiteralExp *)vie;
+	VarDeclaration *vf = ((DotVarExp *)e1)->var->isVarDeclaration();
+	if (!vf)
+	    return EXP_CANT_INTERPRET;
+	int fieldi = se->getFieldIndex(type, vf->offset);
+	if (fieldi == -1)
+	    return EXP_CANT_INTERPRET;
+	Expression *ev = se->getField(type, vf->offset);
+	if (fp)
+	    e2 = (*fp)(type, ev, e2);
+	else
+	    e2 = Cast(type, type, e2);
+	if (e2 == EXP_CANT_INTERPRET)
+	    return e2;
+
+	if (!v->isParameter())
+	{
+	    for (size_t i = 0; 1; i++)
+	    {
+		if (i == istate->vars.dim)
+		{   istate->vars.push(v);
+		    break;
+		}
+		if (v == (VarDeclaration *)istate->vars.data[i])
+		    break;
+	    }
+	}
+
+	/* Create new struct literal reflecting updated fieldi
+	 */
+	Expressions *expsx = new Expressions();
+	expsx->setDim(se->elements->dim);
+	for (size_t j = 0; j < expsx->dim; j++)
+	{
+	    if (j == fieldi)
+		expsx->data[j] = (void *)e2;
+	    else
+		expsx->data[j] = se->elements->data[j];
+	}
+	v->value = new StructLiteralExp(se->loc, se->sd, expsx);
+	v->value->type = se->type;
+
+	e = Cast(type, type, post ? ev : e2);
+    }
+    /* Assignment to struct member of the form:
      *   *(symoffexp) = e2
      */
     else if (e1->op == TOKstar && ((PtrExp *)e1)->e1->op == TOKsymoff)
@@ -2159,21 +2237,29 @@
 Expression *DotVarExp::interpret(InterState *istate)
 {   Expression *e = EXP_CANT_INTERPRET;
 
-    Expression *ex = e1->interpret(istate);
-
-    // Constant fold structliteral.member
-    if (ex != EXP_CANT_INTERPRET && ex->op == TOKstructliteral)
-    {	StructLiteralExp *se = (StructLiteralExp *)ex;
+#if LOG
+    printf("DotVarExp::interpret() %s\n", toChars());
+#endif
 
-	VarDeclaration* v;
-	if (v = var->isVarDeclaration())
-	{
-	    e = se->getField(type, v->offset);
-	    if (!e)
-		e = EXP_CANT_INTERPRET;
+    Expression *ex = e1->interpret(istate);
+    if (ex != EXP_CANT_INTERPRET)
+    {
+	if (ex->op == TOKstructliteral)
+	{   StructLiteralExp *se = (StructLiteralExp *)ex;
+	    VarDeclaration *v = var->isVarDeclaration();
+	    if (v)
+	    {	e = se->getField(type, v->offset);
+		if (!e)
+		    e = EXP_CANT_INTERPRET;
+		return e;
+	    }
 	}
     }
 
+#if LOG
+    if (e == EXP_CANT_INTERPRET)
+	printf("DotVarExp::interpret() %s = EXP_CANT_INTERPRET\n", toChars());
+#endif
     return e;
 }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd2/irstate.c	Mon Jun 01 19:02:20 2009 +0100
@@ -0,0 +1,164 @@
+
+// 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
+
+#include <stdio.h>
+
+#include "irstate.h"
+
+IRState::IRState(IRState *irs, Statement *s)
+{
+    prev = irs;
+    statement = s;
+    symbol = NULL;
+    breakBlock = NULL;
+    contBlock = NULL;
+    switchBlock = NULL;
+    defaultBlock = NULL;
+    ident = NULL;
+    ehidden = NULL;
+    startaddress = NULL;
+    if (irs)
+    {
+	m = irs->m;
+	shidden = irs->shidden;
+	sclosure = irs->sclosure;
+	sthis = irs->sthis;
+	blx = irs->blx;
+	deferToObj = irs->deferToObj;
+    }
+    else
+    {
+	m = NULL;
+	shidden = NULL;
+	sclosure = NULL;
+	sthis = NULL;
+	blx = NULL;
+	deferToObj = NULL;
+    }
+}
+
+IRState::IRState(IRState *irs, Dsymbol *s)
+{
+    prev = irs;
+    statement = NULL;
+    symbol = s;
+    breakBlock = NULL;
+    contBlock = NULL;
+    switchBlock = NULL;
+    defaultBlock = NULL;
+    ident = NULL;
+    ehidden = NULL;
+    startaddress = NULL;
+    if (irs)
+    {
+	m = irs->m;
+	shidden = irs->shidden;
+	sclosure = irs->sclosure;
+	sthis = irs->sthis;
+	blx = irs->blx;
+	deferToObj = irs->deferToObj;
+    }
+    else
+    {
+	m = NULL;
+	shidden = NULL;
+	sclosure = NULL;
+	sthis = NULL;
+	blx = NULL;
+	deferToObj = NULL;
+    }
+}
+
+IRState::IRState(Module *m, Dsymbol *s)
+{
+    prev = NULL;
+    statement = NULL;
+    this->m = m;
+    symbol = s;
+    breakBlock = NULL;
+    contBlock = NULL;
+    switchBlock = NULL;
+    defaultBlock = NULL;
+    ident = NULL;
+    ehidden = NULL;
+    shidden = NULL;
+    sclosure = NULL;
+    sthis = NULL;
+    blx = NULL;
+    deferToObj = NULL;
+    startaddress = NULL;
+}
+
+block *IRState::getBreakBlock(Identifier *ident)
+{
+    IRState *bc;
+
+    for (bc = this; bc; bc = bc->prev)
+    {
+	if (ident)
+	{
+	    if (bc->prev && bc->prev->ident == ident)
+		return bc->breakBlock;
+	}
+	else if (bc->breakBlock)
+	    return bc->breakBlock;
+    }
+    return NULL;
+}
+
+block *IRState::getContBlock(Identifier *ident)
+{
+    IRState *bc;
+
+    for (bc = this; bc; bc = bc->prev)
+    {
+	if (ident)
+	{
+	    if (bc->prev && bc->prev->ident == ident)
+		return bc->contBlock;
+	}
+	else if (bc->contBlock)
+	    return bc->contBlock;
+    }
+    return NULL;
+}
+
+block *IRState::getSwitchBlock()
+{
+    IRState *bc;
+
+    for (bc = this; bc; bc = bc->prev)
+    {
+	if (bc->switchBlock)
+	    return bc->switchBlock;
+    }
+    return NULL;
+}
+
+block *IRState::getDefaultBlock()
+{
+    IRState *bc;
+
+    for (bc = this; bc; bc = bc->prev)
+    {
+	if (bc->defaultBlock)
+	    return bc->defaultBlock;
+    }
+    return NULL;
+}
+
+FuncDeclaration *IRState::getFunc()
+{
+    IRState *bc;
+
+    for (bc = this; bc->prev; bc = bc->prev)
+    {
+    }
+    return (FuncDeclaration *)(bc->symbol);
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd2/irstate.h	Mon Jun 01 19:02:20 2009 +0100
@@ -0,0 +1,57 @@
+
+// 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
+
+#ifndef DMD_CONTEXT_H
+#define DMD_CONTEXT_H
+
+#ifdef __DMC__
+#pragma once
+#endif /* __DMC__ */
+
+struct Module;
+struct Statement;
+struct block;
+struct Dsymbol;
+struct Identifier;
+struct Symbol;
+struct FuncDeclaration;
+struct Blockx;
+struct Array;
+struct elem;
+
+struct IRState
+{
+    IRState *prev;
+    Statement *statement;
+    Module *m;			// module
+    Dsymbol *symbol;
+    Identifier *ident;
+    Symbol *shidden;		// hidden parameter to function
+    Symbol *sthis;		// 'this' parameter to function (member and nested)
+    Symbol *sclosure;		// pointer to closure instance
+    Blockx *blx;
+    Array *deferToObj;		// array of Dsymbol's to run toObjFile(int multiobj) on later
+    elem *ehidden;		// transmit hidden pointer to CallExp::toElem()
+    Symbol *startaddress;
+
+    block *breakBlock;
+    block *contBlock;
+    block *switchBlock;
+    block *defaultBlock;
+
+    IRState(IRState *irs, Statement *s);
+    IRState(IRState *irs, Dsymbol *s);
+    IRState(Module *m, Dsymbol *s);
+
+    block *getBreakBlock(Identifier *ident);
+    block *getContBlock(Identifier *ident);
+    block *getSwitchBlock();
+    block *getDefaultBlock();
+    FuncDeclaration *getFunc();
+};
+
+#endif /* DMD_CONTEXT_H */
--- a/dmd2/lexer.c	Mon Jun 01 01:28:18 2009 +0200
+++ b/dmd2/lexer.c	Mon Jun 01 19:02:20 2009 +0100
@@ -1,3109 +1,3108 @@
-
-// 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.
-
-/* Lexical Analyzer */
-
-#include <stdio.h>
-#include <string.h>
-#include <ctype.h>
-#include <stdarg.h>
-#include <errno.h>
-#include <wchar.h>
-#include <stdlib.h>
-#include <assert.h>
-#include <sys/time.h>
-#include <math.h>
-
-#ifdef IN_GCC
-
-#include <time.h>
-#include "mem.h"
-
-#else
-
-#if __GNUC__
-#include <time.h>
-#endif
-
-#if IN_LLVM
-#include "mem.h"
-#elif _WIN32
-#include "..\root\mem.h"
-#else
-#include "../root/mem.h"
-#endif
-#endif
-
-#include "stringtable.h"
-
-#include "lexer.h"
-#include "utf.h"
-#include "identifier.h"
-#include "id.h"
-#include "module.h"
-
-#if _WIN32 && __DMC__
-// from \dm\src\include\setlocal.h
-extern "C" char * __cdecl __locale_decpoint;
-#endif
-
-extern int HtmlNamedEntity(unsigned char *p, int length);
-
-#define LS 0x2028	// UTF line separator
-#define PS 0x2029	// UTF paragraph separator
-
-/********************************************
- * Do our own char maps
- */
-
-static unsigned char cmtable[256];
-
-const int CMoctal =	0x1;
-const int CMhex =	0x2;
-const int CMidchar =	0x4;
-
-inline unsigned char isoctal (unsigned char c) { return cmtable[c] & CMoctal; }
-inline unsigned char ishex   (unsigned char c) { return cmtable[c] & CMhex; }
-inline unsigned char isidchar(unsigned char c) { return cmtable[c] & CMidchar; }
-
-static void cmtable_init()
-{
-    for (unsigned c = 0; c < sizeof(cmtable) / sizeof(cmtable[0]); c++)
-    {
-	if ('0' <= c && c <= '7')
-	    cmtable[c] |= CMoctal;
-	if (isdigit(c) || ('a' <= c && c <= 'f') || ('A' <= c && c <= 'F'))
-	    cmtable[c] |= CMhex;
-	if (isalnum(c) || c == '_')
-	    cmtable[c] |= CMidchar;
-    }
-}
-
-
-/************************* Token **********************************************/
-
-const char *Token::tochars[TOKMAX];
-
-void *Token::operator new(size_t size)
-{   Token *t;
-
-    if (Lexer::freelist)
-    {
-	t = Lexer::freelist;
-	Lexer::freelist = t->next;
-	return t;
-    }
-
-    return ::operator new(size);
-}
-
-#ifdef DEBUG
-void Token::print()
-{
-    fprintf(stdmsg, "%s\n", toChars());
-}
-#endif
-
-const char *Token::toChars()
-{   const char *p;
-    static char buffer[3 + 3 * sizeof(value) + 1];
-
-    p = buffer;
-    switch (value)
-    {
-	case TOKint32v:
-#if IN_GCC
-	    sprintf(buffer,"%d",(d_int32)int64value);
-#else
-	    sprintf(buffer,"%d",int32value);
-#endif
-	    break;
-
-	case TOKuns32v:
-	case TOKcharv:
-	case TOKwcharv:
-	case TOKdcharv:
-#if IN_GCC
-	    sprintf(buffer,"%uU",(d_uns32)uns64value);
-#else
-	    sprintf(buffer,"%uU",uns32value);
-#endif
-	    break;
-
-	case TOKint64v:
-	    sprintf(buffer,"%lldL",int64value);
-	    break;
-
-	case TOKuns64v:
-	    sprintf(buffer,"%lluUL",uns64value);
-	    break;
-
-#if IN_GCC
-	case TOKfloat32v:
-	case TOKfloat64v:
-	case TOKfloat80v:
-	    float80value.format(buffer, sizeof(buffer));
-	    break;
-	case TOKimaginary32v:
-	case TOKimaginary64v:
-	case TOKimaginary80v:
-	    float80value.format(buffer, sizeof(buffer));
-	    // %% buffer
-	    strcat(buffer, "i");
-	    break;
-#else
-	case TOKfloat32v:
-	    sprintf(buffer,"%Lgf", float80value);
-	    break;
-
-	case TOKfloat64v:
-	    sprintf(buffer,"%Lg", float80value);
-	    break;
-
-	case TOKfloat80v:
-	    sprintf(buffer,"%LgL", float80value);
-	    break;
-
-	case TOKimaginary32v:
-	    sprintf(buffer,"%Lgfi", float80value);
-	    break;
-
-	case TOKimaginary64v:
-	    sprintf(buffer,"%Lgi", float80value);
-	    break;
-
-	case TOKimaginary80v:
-	    sprintf(buffer,"%LgLi", float80value);
-	    break;
-#endif
-
-	case TOKstring:
-#if CSTRINGS
-	    p = string;
-#else
-	{   OutBuffer buf;
-
-	    buf.writeByte('"');
-	    for (size_t i = 0; i < len; )
-	    {	unsigned c;
-
-		utf_decodeChar((unsigned char *)ustring, len, &i, &c);
-		switch (c)
-		{
-		    case 0:
-			break;
-
-		    case '"':
-		    case '\\':
-			buf.writeByte('\\');
-		    default:
-			if (isprint(c))
-			    buf.writeByte(c);
-			else if (c <= 0x7F)
-			    buf.printf("\\x%02x", c);
-			else if (c <= 0xFFFF)
-			    buf.printf("\\u%04x", c);
-			else
-			    buf.printf("\\U%08x", c);
-			continue;
-		}
-		break;
-	    }
-	    buf.writeByte('"');
-	    if (postfix)
-		buf.writeByte('"');
-	    buf.writeByte(0);
-	    p = (char *)buf.extractData();
-	}
-#endif
-	    break;
-
-	case TOKidentifier:
-	case TOKenum:
-	case TOKstruct:
-	case TOKimport:
-	CASE_BASIC_TYPES:
-	    p = ident->toChars();
-	    break;
-
-	default:
-	    p = toChars(value);
-	    break;
-    }
-    return p;
-}
-
-const char *Token::toChars(enum TOK value)
-{   const char *p;
-    static char buffer[3 + 3 * sizeof(value) + 1];
-
-    p = tochars[value];
-    if (!p)
-    {	sprintf(buffer,"TOK%d",value);
-	p = buffer;
-    }
-    return p;
-}
-
-/*************************** Lexer ********************************************/
-
-Token *Lexer::freelist = NULL;
-StringTable Lexer::stringtable;
-OutBuffer Lexer::stringbuffer;
-
-Lexer::Lexer(Module *mod,
-	unsigned char *base, unsigned begoffset, unsigned endoffset,
-	int doDocComment, int commentToken)
-    : loc(mod, 1)
-{
-    //printf("Lexer::Lexer(%p,%d)\n",base,length);
-    //printf("lexer.mod = %p, %p\n", mod, this->loc.mod);
-    memset(&token,0,sizeof(token));
-    this->base = base;
-    this->end  = base + endoffset;
-    p = base + begoffset;
-    this->mod = mod;
-    this->doDocComment = doDocComment;
-    this->anyToken = 0;
-    this->commentToken = commentToken;
-    //initKeywords();
-
-    /* If first line starts with '#!', ignore the line
-     */
-
-    if (p[0] == '#' && p[1] =='!')
-    {
-	p += 2;
-	while (1)
-	{   unsigned char c = *p;
-	    switch (c)
-	    {
-		case '\n':
-		    p++;
-		    break;
-
-		case '\r':
-		    p++;
-		    if (*p == '\n')
-			p++;
-		    break;
-
-		case 0:
-		case 0x1A:
-		    break;
-
-		default:
-		    if (c & 0x80)
-		    {   unsigned u = decodeUTF();
-			if (u == PS || u == LS)
-			    break;
-		    }
-		    p++;
-		    continue;
-	    }
-	    break;
-	}
-	loc.linnum = 2;
-    }
-}
-
-
-void Lexer::error(const char *format, ...)
-{
-    if (mod && !global.gag)
-    {
-	char *p = loc.toChars();
-	if (*p)
-	    fprintf(stdmsg, "%s: ", p);
-	mem.free(p);
-
-	va_list ap;
-	va_start(ap, format);
-	vfprintf(stdmsg, format, ap);
-	va_end(ap);
-
-	fprintf(stdmsg, "\n");
-	fflush(stdmsg);
-
-	if (global.errors >= 20)	// moderate blizzard of cascading messages
-	    fatal();
-    }
-    global.errors++;
-}
-
-void Lexer::error(Loc loc, const char *format, ...)
-{
-    if (mod && !global.gag)
-    {
-	char *p = loc.toChars();
-	if (*p)
-	    fprintf(stdmsg, "%s: ", p);
-	mem.free(p);
-
-	va_list ap;
-	va_start(ap, format);
-	vfprintf(stdmsg, format, ap);
-	va_end(ap);
-
-	fprintf(stdmsg, "\n");
-	fflush(stdmsg);
-
-	if (global.errors >= 20)	// moderate blizzard of cascading messages
-	    fatal();
-    }
-    global.errors++;
-}
-
-TOK Lexer::nextToken()
-{   Token *t;
-
-    if (token.next)
-    {
-	t = token.next;
-	memcpy(&token,t,sizeof(Token));
-	t->next = freelist;
-	freelist = t;
-    }
-    else
-    {
-	scan(&token);
-    }
-    //token.print();
-    return token.value;
-}
-
-Token *Lexer::peek(Token *ct)
-{   Token *t;
-
-    if (ct->next)
-	t = ct->next;
-    else
-    {
-	t = new Token();
-	scan(t);
-	t->next = NULL;
-	ct->next = t;
-    }
-    return t;
-}
-
-/***********************
- * Look ahead at next token's value.
- */
-
-TOK Lexer::peekNext()
-{
-    return peek(&token)->value;
-}
-
-/*********************************
- * tk is on the opening (.
- * Look ahead and return token that is past the closing ).
- */
-
-Token *Lexer::peekPastParen(Token *tk)
-{
-    //printf("peekPastParen()\n");
-    int parens = 1;
-    int curlynest = 0;
-    while (1)
-    {
-	tk = peek(tk);
-	//tk->print();
-	switch (tk->value)
-	{
-	    case TOKlparen:
-		parens++;
-		continue;
-
-	    case TOKrparen:
-		--parens;
-		if (parens)
-		    continue;
-		tk = peek(tk);
-		break;
-
-	    case TOKlcurly:
-		curlynest++;
-		continue;
-
-	    case TOKrcurly:
-		if (--curlynest >= 0)
-		    continue;
-		break;
-
-	    case TOKsemicolon:
-		if (curlynest)
-		    continue;
-		break;
-
-	    case TOKeof:
-		break;
-
-	    default:
-		continue;
-	}
-	return tk;
-    }
-}
-
-/**********************************
- * Determine if string is a valid Identifier.
- * Placed here because of commonality with Lexer functionality.
- * Returns:
- *	0	invalid
- */
-
-int Lexer::isValidIdentifier(char *p)
-{
-    size_t len;
-    size_t idx;
-
-    if (!p || !*p)
-	goto Linvalid;
-
-    if (*p >= '0' && *p <= '9')		// beware of isdigit() on signed chars
-	goto Linvalid;
-
-    len = strlen(p);
-    idx = 0;
-    while (p[idx])
-    {   dchar_t dc;
-
-	const char *q = utf_decodeChar((unsigned char *)p, len, &idx, &dc);
-	if (q)
-	    goto Linvalid;
-
-	if (!((dc >= 0x80 && isUniAlpha(dc)) || isalnum(dc) || dc == '_'))
-	    goto Linvalid;
-    }
-    return 1;
-
-Linvalid:
-    return 0;
-}
-
-/****************************
- * Turn next token in buffer into a token.
- */
-
-void Lexer::scan(Token *t)
-{
-    unsigned lastLine = loc.linnum;
-    unsigned linnum;
-
-    t->blockComment = NULL;
-    t->lineComment = NULL;
-    while (1)
-    {
-	t->ptr = p;
-	//printf("p = %p, *p = '%c'\n",p,*p);
-	switch (*p)
-	{
-	    case 0:
-	    case 0x1A:
-		t->value = TOKeof;			// end of file
-		return;
-
-	    case ' ':
-	    case '\t':
-	    case '\v':
-	    case '\f':
-		p++;
-		continue;			// skip white space
-
-	    case '\r':
-		p++;
-		if (*p != '\n')			// if CR stands by itself
-		    loc.linnum++;
-		continue;			// skip white space
-
-	    case '\n':
-		p++;
-		loc.linnum++;
-		continue;			// skip white space
-
-	    case '0':  	case '1':   case '2':   case '3':   case '4':
-	    case '5':  	case '6':   case '7':   case '8':   case '9':
-		t->value = number(t);
-		return;
-
-#if CSTRINGS
-	    case '\'':
-		t->value = charConstant(t, 0);
-		return;
-
-	    case '"':
-		t->value = stringConstant(t,0);
-		return;
-
-	    case 'l':
-	    case 'L':
-		if (p[1] == '\'')
-		{
-		    p++;
-		    t->value = charConstant(t, 1);
-		    return;
-		}
-		else if (p[1] == '"')
-		{
-		    p++;
-		    t->value = stringConstant(t, 1);
-		    return;
-		}
-#else
-	    case '\'':
-		t->value = charConstant(t,0);
-		return;
-
-	    case 'r':
-		if (p[1] != '"')
-		    goto case_ident;
-		p++;
-	    case '`':
-		t->value = wysiwygStringConstant(t, *p);
-		return;
-
-	    case 'x':
-		if (p[1] != '"')
-		    goto case_ident;
-		p++;
-		t->value = hexStringConstant(t);
-		return;
-
-#if DMDV2
-	    case 'q':
-		if (p[1] == '"')
-		{
-		    p++;
-		    t->value = delimitedStringConstant(t);
-		    return;
-		}
-		else if (p[1] == '{')
-		{
-		    p++;
-		    t->value = tokenStringConstant(t);
-		    return;
-		}
-		else
-		    goto case_ident;
-#endif
-
-	    case '"':
-		t->value = escapeStringConstant(t,0);
-		return;
-
-	    case '\\':			// escaped string literal
-	    {	unsigned c;
-
-		stringbuffer.reset();
-		do
-		{
-		    p++;
-		    switch (*p)
-		    {
-			case 'u':
-			case 'U':
-			case '&':
-			    c = escapeSequence();
-			    stringbuffer.writeUTF8(c);
-			    break;
-
-			default:
-			    c = escapeSequence();
-			    stringbuffer.writeByte(c);
-			    break;
-		    }
-		} while (*p == '\\');
-		t->len = stringbuffer.offset;
-		stringbuffer.writeByte(0);
-		t->ustring = (unsigned char *)mem.malloc(stringbuffer.offset);
-		memcpy(t->ustring, stringbuffer.data, stringbuffer.offset);
-		t->postfix = 0;
-		t->value = TOKstring;
-		return;
-	    }
-
-	    case 'l':
-	    case 'L':
-#endif
-	    case 'a':  	case 'b':   case 'c':   case 'd':   case 'e':
-	    case 'f':  	case 'g':   case 'h':   case 'i':   case 'j':
-	    case 'k':  	            case 'm':   case 'n':   case 'o':
-#if DMDV2
-	    case 'p':  	/*case 'q': case 'r':*/ case 's':   case 't':
-#else
-	    case 'p':  	case 'q': /*case 'r':*/ case 's':   case 't':
-#endif
-	    case 'u':  	case 'v':   case 'w': /*case 'x':*/ case 'y':
-	    case 'z':
-	    case 'A':  	case 'B':   case 'C':   case 'D':   case 'E':
-	    case 'F':  	case 'G':   case 'H':   case 'I':   case 'J':
-	    case 'K':  	            case 'M':   case 'N':   case 'O':
-	    case 'P':  	case 'Q':   case 'R':   case 'S':   case 'T':
-	    case 'U':  	case 'V':   case 'W':   case 'X':   case 'Y':
-	    case 'Z':
-	    case '_':
-	    case_ident:
-	    {   unsigned char c;
-		StringValue *sv;
-		Identifier *id;
-
-		do
-		{
-		    c = *++p;
-		} while (isidchar(c) || (c & 0x80 && isUniAlpha(decodeUTF())));
-		sv = stringtable.update((char *)t->ptr, p - t->ptr);
-		id = (Identifier *) sv->ptrvalue;
-		if (!id)
-		{   id = new Identifier(sv->lstring.string,TOKidentifier);
-		    sv->ptrvalue = id;
-		}
-		t->ident = id;
-		t->value = (enum TOK) id->value;
-		anyToken = 1;
-		if (*t->ptr == '_')	// if special identifier token
-		{
-		    static char date[11+1];
-		    static char time[8+1];
-		    static char timestamp[24+1];
-
-		    if (!date[0])	// lazy evaluation
-		    {   time_t t;
-			char *p;
-
-			::time(&t);
-			p = ctime(&t);
-			assert(p);
-			sprintf(date, "%.6s %.4s", p + 4, p + 20);
-			sprintf(time, "%.8s", p + 11);
-			sprintf(timestamp, "%.24s", p);
-		    }
-
-#if DMDV1
-		    if (mod && id == Id::FILE)
-		    {
-			t->ustring = (unsigned char *)(loc.filename ? loc.filename : mod->ident->toChars());
-			goto Lstring;
-		    }
-		    else if (mod && id == Id::LINE)
-		    {
-			t->value = TOKint64v;
-			t->uns64value = loc.linnum;
-		    }
-		    else
-#endif
-		    if (id == Id::DATE)
-		    {
-			t->ustring = (unsigned char *)date;
-			goto Lstring;
-		    }
-		    else if (id == Id::TIME)
-		    {
-			t->ustring = (unsigned char *)time;
-			goto Lstring;
-		    }
-		    else if (id == Id::VENDOR)
-		    {
-			t->ustring = (unsigned char *)"LDC";
-			goto Lstring;
-		    }
-		    else if (id == Id::TIMESTAMP)
-		    {
-			t->ustring = (unsigned char *)timestamp;
-		     Lstring:
-			t->value = TOKstring;
-		     Llen:
-			t->postfix = 0;
-			t->len = strlen((char *)t->ustring);
-		    }
-		    else if (id == Id::VERSIONX)
-		    {	unsigned major = 0;
-			unsigned minor = 0;
-
-			for (const char *p = global.version + 1; 1; p++)
-			{
-			    char c = *p;
-			    if (isdigit(c))
-				minor = minor * 10 + c - '0';
-			    else if (c == '.')
-			    {	major = minor;
-				minor = 0;
-			    }
-			    else
-				break;
-			}
-			t->value = TOKint64v;
-			t->uns64value = major * 1000 + minor;
-		    }
-#if DMDV2
-		    else if (id == Id::EOFX)
-		    {
-			t->value = TOKeof;
-			// Advance scanner to end of file
-			while (!(*p == 0 || *p == 0x1A))
-			    p++;
-		    }
-#endif
-		}
-		//printf("t->value = %d\n",t->value);
-		return;
-	    }
-
-	    case '/':
-		p++;
-		switch (*p)
-		{
-		    case '=':
-			p++;
-			t->value = TOKdivass;
-			return;
-
-		    case '*':
-			p++;
-			linnum = loc.linnum;
-			while (1)
-			{
-			    while (1)
-			    {	unsigned char c = *p;
-				switch (c)
-				{
-				    case '/':
-					break;
-
-				    case '\n':
-					loc.linnum++;
-					p++;
-					continue;
-
-				    case '\r':
-					p++;
-					if (*p != '\n')
-					    loc.linnum++;
-					continue;
-
-				    case 0:
-				    case 0x1A:
-					error("unterminated /* */ comment");
-					p = end;
-					t->value = TOKeof;
-					return;
-
-				    default:
-					if (c & 0x80)
-					{   unsigned u = decodeUTF();
-					    if (u == PS || u == LS)
-						loc.linnum++;
-					}
-					p++;
-					continue;
-				}
-				break;
-			    }
-			    p++;
-			    if (p[-2] == '*' && p - 3 != t->ptr)
-				break;
-			}
-			if (commentToken)
-			{
-			    t->value = TOKcomment;
-			    return;
-			}
-			else if (doDocComment && t->ptr[2] == '*' && p - 4 != t->ptr)
-			{   // if /** but not /**/
-			    getDocComment(t, lastLine == linnum);
-			}
-			continue;
-
-		    case '/':		// do // style comments
-			linnum = loc.linnum;
-			while (1)
-			{   unsigned char c = *++p;
-			    switch (c)
-			    {
-				case '\n':
-				    break;
-
-				case '\r':
-				    if (p[1] == '\n')
-					p++;
-				    break;
-
-				case 0:
-				case 0x1A:
-				    if (commentToken)
-				    {
-					p = end;
-					t->value = TOKcomment;
-					return;
-				    }
-				    if (doDocComment && t->ptr[2] == '/')
-					getDocComment(t, lastLine == linnum);
-				    p = end;
-				    t->value = TOKeof;
-				    return;
-
-				default:
-				    if (c & 0x80)
-				    {   unsigned u = decodeUTF();
-					if (u == PS || u == LS)
-					    break;
-				    }
-				    continue;
-			    }
-			    break;
-			}
-
-			if (commentToken)
-			{
-			    p++;
-			    loc.linnum++;
-			    t->value = TOKcomment;
-			    return;
-			}
-			if (doDocComment && t->ptr[2] == '/')
-			    getDocComment(t, lastLine == linnum);
-
-			p++;
-			loc.linnum++;
-			continue;
-
-		    case '+':
-		    {	int nest;
-
-			linnum = loc.linnum;
-			p++;
-			nest = 1;
-			while (1)
-			{   unsigned char c = *p;
-			    switch (c)
-			    {
-				case '/':
-				    p++;
-				    if (*p == '+')
-				    {
-					p++;
-					nest++;
-				    }
-				    continue;
-
-				case '+':
-				    p++;
-				    if (*p == '/')
-				    {
-					p++;
-					if (--nest == 0)
-					    break;
-				    }
-				    continue;
-
-				case '\r':
-				    p++;
-				    if (*p != '\n')
-					loc.linnum++;
-				    continue;
-
-				case '\n':
-				    loc.linnum++;
-				    p++;
-				    continue;
-
-				case 0:
-				case 0x1A:
-				    error("unterminated /+ +/ comment");
-				    p = end;
-				    t->value = TOKeof;
-				    return;
-
-				default:
-				    if (c & 0x80)
-				    {   unsigned u = decodeUTF();
-					if (u == PS || u == LS)
-					    loc.linnum++;
-				    }
-				    p++;
-				    continue;
-			    }
-			    break;
-			}
-			if (commentToken)
-			{
-			    t->value = TOKcomment;
-			    return;
-			}
-			if (doDocComment && t->ptr[2] == '+' && p - 4 != t->ptr)
-			{   // if /++ but not /++/
-			    getDocComment(t, lastLine == linnum);
-			}
-			continue;
-		    }
-		}
-		t->value = TOKdiv;
-		return;
-
-	    case '.':
-		p++;
-		if (isdigit(*p))
-		{   /* Note that we don't allow ._1 and ._ as being
-		     * valid floating point numbers.
-		     */
-		    p--;
-		    t->value = inreal(t);
-		}
-		else if (p[0] == '.')
-		{
-		    if (p[1] == '.')
-		    {   p += 2;
-			t->value = TOKdotdotdot;
-		    }
-		    else
-		    {   p++;
-			t->value = TOKslice;
-		    }
-		}
-		else
-		    t->value = TOKdot;
-		return;
-
-	    case '&':
-		p++;
-		if (*p == '=')
-		{   p++;
-		    t->value = TOKandass;
-		}
-		else if (*p == '&')
-		{   p++;
-		    t->value = TOKandand;
-		}
-		else
-		    t->value = TOKand;
-		return;
-
-	    case '|':
-		p++;
-		if (*p == '=')
-		{   p++;
-		    t->value = TOKorass;
-		}
-		else if (*p == '|')
-		{   p++;
-		    t->value = TOKoror;
-		}
-		else
-		    t->value = TOKor;
-		return;
-
-	    case '-':
-		p++;
-		if (*p == '=')
-		{   p++;
-		    t->value = TOKminass;
-		}
-#if 0
-		else if (*p == '>')
-		{   p++;
-		    t->value = TOKarrow;
-		}
-#endif
-		else if (*p == '-')
-		{   p++;
-		    t->value = TOKminusminus;
-		}
-		else
-		    t->value = TOKmin;
-		return;
-
-	    case '+':
-		p++;
-		if (*p == '=')
-		{   p++;
-		    t->value = TOKaddass;
-		}
-		else if (*p == '+')
-		{   p++;
-		    t->value = TOKplusplus;
-		}
-		else
-		    t->value = TOKadd;
-		return;
-
-	    case '<':
-		p++;
-		if (*p == '=')
-		{   p++;
-		    t->value = TOKle;			// <=
-		}
-		else if (*p == '<')
-		{   p++;
-		    if (*p == '=')
-		    {   p++;
-			t->value = TOKshlass;		// <<=
-		    }
-		    else
-			t->value = TOKshl;		// <<
-		}
-		else if (*p == '>')
-		{   p++;
-		    if (*p == '=')
-		    {   p++;
-			t->value = TOKleg;		// <>=
-		    }
-		    else
-			t->value = TOKlg;		// <>
-		}
-		else
-		    t->value = TOKlt;			// <
-		return;
-
-	    case '>':
-		p++;
-		if (*p == '=')
-		{   p++;
-		    t->value = TOKge;			// >=
-		}
-		else if (*p == '>')
-		{   p++;
-		    if (*p == '=')
-		    {   p++;
-			t->value = TOKshrass;		// >>=
-		    }
-		    else if (*p == '>')
-		    {	p++;
-			if (*p == '=')
-			{   p++;
-			    t->value = TOKushrass;	// >>>=
-			}
-			else
-			    t->value = TOKushr;		// >>>
-		    }
-		    else
-			t->value = TOKshr;		// >>
-		}
-		else
-		    t->value = TOKgt;			// >
-		return;
-
-	    case '!':
-		p++;
-		if (*p == '=')
-		{   p++;
-		    if (*p == '=' && global.params.Dversion == 1)
-		    {	p++;
-			t->value = TOKnotidentity;	// !==
-		    }
-		    else
-			t->value = TOKnotequal;		// !=
-		}
-		else if (*p == '<')
-		{   p++;
-		    if (*p == '>')
-		    {	p++;
-			if (*p == '=')
-			{   p++;
-			    t->value = TOKunord; // !<>=
-			}
-			else
-			    t->value = TOKue;	// !<>
-		    }
-		    else if (*p == '=')
-		    {	p++;
-			t->value = TOKug;	// !<=
-		    }
-		    else
-			t->value = TOKuge;	// !<
-		}
-		else if (*p == '>')
-		{   p++;
-		    if (*p == '=')
-		    {	p++;
-			t->value = TOKul;	// !>=
-		    }
-		    else
-			t->value = TOKule;	// !>
-		}
-		else
-		    t->value = TOKnot;		// !
-		return;
-
-	    case '=':
-		p++;
-		if (*p == '=')
-		{   p++;
-		    if (*p == '=' && global.params.Dversion == 1)
-		    {	p++;
-			t->value = TOKidentity;		// ===
-		    }
-		    else
-			t->value = TOKequal;		// ==
-		}
-		else
-		    t->value = TOKassign;		// =
-		return;
-
-	    case '~':
-		p++;
-		if (*p == '=')
-		{   p++;
-		    t->value = TOKcatass;		// ~=
-		}
-		else
-		    t->value = TOKtilde;		// ~
-		return;
-
-#define SINGLE(c,tok) case c: p++; t->value = tok; return;
-
-	    SINGLE('(',	TOKlparen)
-	    SINGLE(')', TOKrparen)
-	    SINGLE('[', TOKlbracket)
-	    SINGLE(']', TOKrbracket)
-	    SINGLE('{', TOKlcurly)
-	    SINGLE('}', TOKrcurly)
-	    SINGLE('?', TOKquestion)
-	    SINGLE(',', TOKcomma)
-	    SINGLE(';', TOKsemicolon)
-	    SINGLE(':', TOKcolon)
-	    SINGLE('$', TOKdollar)
-
-#undef SINGLE
-
-#define DOUBLE(c1,tok1,c2,tok2)		\
-	    case c1:			\
-		p++;			\
-		if (*p == c2)		\
-		{   p++;		\
-		    t->value = tok2;	\
-		}			\
-		else			\
-		    t->value = tok1;	\
-		return;
-
-	    DOUBLE('*', TOKmul, '=', TOKmulass)
-	    DOUBLE('%', TOKmod, '=', TOKmodass)
-	    DOUBLE('^', TOKxor, '=', TOKxorass)
-
-#undef DOUBLE
-
-	    case '#':
-		p++;
-		pragma();
-		continue;
-
-	    default:
-	    {	unsigned char c = *p;
-
-		if (c & 0x80)
-		{   unsigned u = decodeUTF();
-
-		    // Check for start of unicode identifier
-		    if (isUniAlpha(u))
-			goto case_ident;
-
-		    if (u == PS || u == LS)
-		    {
-			loc.linnum++;
-			p++;
-			continue;
-		    }
-		}
-		if (isprint(c))
-		    error("unsupported char '%c'", c);
-		else
-		    error("unsupported char 0x%02x", c);
-		p++;
-		continue;
-	    }
-	}
-    }
-}
-
-/*******************************************
- * Parse escape sequence.
- */
-
-unsigned Lexer::escapeSequence()
-{   unsigned c;
-    int n;
-    int ndigits;
-
-    c = *p;
-    switch (c)
-    {
-	case '\'':
-	case '"':
-	case '?':
-	case '\\':
-	Lconsume:
-		p++;
-		break;
-
-	case 'a':	c = 7;		goto Lconsume;
-	case 'b':	c = 8;		goto Lconsume;
-	case 'f':	c = 12;		goto Lconsume;
-	case 'n':	c = 10;		goto Lconsume;
-	case 'r':	c = 13;		goto Lconsume;
-	case 't':	c = 9;		goto Lconsume;
-	case 'v':	c = 11;		goto Lconsume;
-
-	case 'u':
-		ndigits = 4;
-		goto Lhex;
-	case 'U':
-		ndigits = 8;
-		goto Lhex;
-	case 'x':
-		ndigits = 2;
-	Lhex:
-		p++;
-		c = *p;
-		if (ishex(c))
-		{   unsigned v;
-
-		    n = 0;
-		    v = 0;
-		    while (1)
-		    {
-			if (isdigit(c))
-			    c -= '0';
-			else if (islower(c))
-			    c -= 'a' - 10;
-			else
-			    c -= 'A' - 10;
-			v = v * 16 + c;
-			c = *++p;
-			if (++n == ndigits)
-			    break;
-			if (!ishex(c))
-			{   error("escape hex sequence has %d hex digits instead of %d", n, ndigits);
-			    break;
-			}
-		    }
-		    if (ndigits != 2 && !utf_isValidDchar(v))
-			error("invalid UTF character \\U%08x", v);
-		    c = v;
-		}
-		else
-		    error("undefined escape hex sequence \\%c\n",c);
-		break;
-
-	case '&':			// named character entity
-		for (unsigned char *idstart = ++p; 1; p++)
-		{
-		    switch (*p)
-		    {
-			case ';':
-			    c = HtmlNamedEntity(idstart, p - idstart);
-			    if (c == ~0)
-			    {   error("unnamed character entity &%.*s;", (int)(p - idstart), idstart);
-				c = ' ';
-			    }
-			    p++;
-			    break;
-
-			default:
-			    if (isalpha(*p) ||
-				(p != idstart + 1 && isdigit(*p)))
-				continue;
-			    error("unterminated named entity");
-			    break;
-		    }
-		    break;
-		}
-		break;
-
-	case 0:
-	case 0x1A:			// end of file
-		c = '\\';
-		break;
-
-	default:
-		if (isoctal(c))
-		{   unsigned v;
-
-		    n = 0;
-		    v = 0;
-		    do
-		    {
-			v = v * 8 + (c - '0');
-			c = *++p;
-		    } while (++n < 3 && isoctal(c));
-		    c = v;
-		    if (c > 0xFF)
-			error("0%03o is larger than a byte", c);
-		}
-		else
-		    error("undefined escape sequence \\%c\n",c);
-		break;
-    }
-    return c;
-}
-
-/**************************************
- */
-
-TOK Lexer::wysiwygStringConstant(Token *t, int tc)
-{   unsigned c;
-    Loc start = loc;
-
-    p++;
-    stringbuffer.reset();
-    while (1)
-    {
-	c = *p++;
-	switch (c)
-	{
-	    case '\n':
-		loc.linnum++;
-		break;
-
-	    case '\r':
-		if (*p == '\n')
-		    continue;	// ignore
-		c = '\n';	// treat EndOfLine as \n character
-		loc.linnum++;
-		break;
-
-	    case 0:
-	    case 0x1A:
-		error("unterminated string constant starting at %s", start.toChars());
-		t->ustring = (unsigned char *)"";
-		t->len = 0;
-		t->postfix = 0;
-		return TOKstring;
-
-	    case '"':
-	    case '`':
-		if (c == tc)
-		{
-		    t->len = stringbuffer.offset;
-		    stringbuffer.writeByte(0);
-		    t->ustring = (unsigned char *)mem.malloc(stringbuffer.offset);
-		    memcpy(t->ustring, stringbuffer.data, stringbuffer.offset);
-		    stringPostfix(t);
-		    return TOKstring;
-		}
-		break;
-
-	    default:
-		if (c & 0x80)
-		{   p--;
-		    unsigned u = decodeUTF();
-		    p++;
-		    if (u == PS || u == LS)
-			loc.linnum++;
-		    stringbuffer.writeUTF8(u);
-		    continue;
-		}
-		break;
-	}
-	stringbuffer.writeByte(c);
-    }
-}
-
-/**************************************
- * Lex hex strings:
- *	x"0A ae 34FE BD"
- */
-
-TOK Lexer::hexStringConstant(Token *t)
-{   unsigned c;
-    Loc start = loc;
-    unsigned n = 0;
-    unsigned v;
-
-    p++;
-    stringbuffer.reset();
-    while (1)
-    {
-	c = *p++;
-	switch (c)
-	{
-	    case ' ':
-	    case '\t':
-	    case '\v':
-	    case '\f':
-		continue;			// skip white space
-
-	    case '\r':
-		if (*p == '\n')
-		    continue;			// ignore
-		// Treat isolated '\r' as if it were a '\n'
-	    case '\n':
-		loc.linnum++;
-		continue;
-
-	    case 0:
-	    case 0x1A:
-		error("unterminated string constant starting at %s", start.toChars());
-		t->ustring = (unsigned char *)"";
-		t->len = 0;
-		t->postfix = 0;
-		return TOKstring;
-
-	    case '"':
-		if (n & 1)
-		{   error("odd number (%d) of hex characters in hex string", n);
-		    stringbuffer.writeByte(v);
-		}
-		t->len = stringbuffer.offset;
-		stringbuffer.writeByte(0);
-		t->ustring = (unsigned char *)mem.malloc(stringbuffer.offset);
-		memcpy(t->ustring, stringbuffer.data, stringbuffer.offset);
-		stringPostfix(t);
-		return TOKstring;
-
-	    default:
-		if (c >= '0' && c <= '9')
-		    c -= '0';
-		else if (c >= 'a' && c <= 'f')
-		    c -= 'a' - 10;
-		else if (c >= 'A' && c <= 'F')
-		    c -= 'A' - 10;
-		else if (c & 0x80)
-		{   p--;
-		    unsigned u = decodeUTF();
-		    p++;
-		    if (u == PS || u == LS)
-			loc.linnum++;
-		    else
-			error("non-hex character \\u%x", u);
-		}
-		else
-		    error("non-hex character '%c'", c);
-		if (n & 1)
-		{   v = (v << 4) | c;
-		    stringbuffer.writeByte(v);
-		}
-		else
-		    v = c;
-		n++;
-		break;
-	}
-    }
-}
-
-
-#if DMDV2
-/**************************************
- * Lex delimited strings:
- *	q"(foo(xxx))"   // "foo(xxx)"
- *	q"[foo(]"       // "foo("
- *	q"/foo]/"       // "foo]"
- *	q"HERE
- *	foo
- *	HERE"		// "foo\n"
- * Input:
- *	p is on the "
- */
-
-TOK Lexer::delimitedStringConstant(Token *t)
-{   unsigned c;
-    Loc start = loc;
-    unsigned delimleft = 0;
-    unsigned delimright = 0;
-    unsigned nest = 1;
-    unsigned nestcount;
-    Identifier *hereid = NULL;
-    unsigned blankrol = 0;
-    unsigned startline = 0;
-
-    p++;
-    stringbuffer.reset();
-    while (1)
-    {
-	c = *p++;
-	//printf("c = '%c'\n", c);
-	switch (c)
-	{
-	    case '\n':
-	    Lnextline:
-		loc.linnum++;
-		startline = 1;
-		if (blankrol)
-		{   blankrol = 0;
-		    continue;
-		}
-		if (hereid)
-		{
-		    stringbuffer.writeUTF8(c);
-		    continue;
-		}
-		break;
-
-	    case '\r':
-		if (*p == '\n')
-		    continue;	// ignore
-		c = '\n';	// treat EndOfLine as \n character
-		goto Lnextline;
-
-	    case 0:
-	    case 0x1A:
-		goto Lerror;
-
-	    default:
-		if (c & 0x80)
-		{   p--;
-		    c = decodeUTF();
-		    p++;
-		    if (c == PS || c == LS)
-			goto Lnextline;
-		}
-		break;
-	}
-	if (delimleft == 0)
-	{   delimleft = c;
-	    nest = 1;
-	    nestcount = 1;
-	    if (c == '(')
-		delimright = ')';
-	    else if (c == '{')
-		delimright = '}';
-	    else if (c == '[')
-		delimright = ']';
-	    else if (c == '<')
-		delimright = '>';
-	    else if (isalpha(c) || c == '_' || (c >= 0x80 && isUniAlpha(c)))
-	    {	// Start of identifier; must be a heredoc
-		Token t;
-		p--;
-		scan(&t);		// read in heredoc identifier
-		if (t.value != TOKidentifier)
-		{   error("identifier expected for heredoc, not %s", t.toChars());
-		    delimright = c;
-		}
-		else
-		{   hereid = t.ident;
-		    //printf("hereid = '%s'\n", hereid->toChars());
-		    blankrol = 1;
-		}
-		nest = 0;
-	    }
-	    else
-	    {	delimright = c;
-		nest = 0;
-	    }
-	}
-	else
-	{
-	    if (blankrol)
-	    {	error("heredoc rest of line should be blank");
-		blankrol = 0;
-		continue;
-	    }
-	    if (nest == 1)
-	    {
-		if (c == delimleft)
-		    nestcount++;
-		else if (c == delimright)
-		{   nestcount--;
-		    if (nestcount == 0)
-			goto Ldone;
-		}
-	    }
-	    else if (c == delimright)
-		goto Ldone;
-	    if (startline && isalpha(c))
-	    {	Token t;
-		unsigned char *psave = p;
-		p--;
-		scan(&t);		// read in possible heredoc identifier
-		//printf("endid = '%s'\n", t.ident->toChars());
-		if (t.value == TOKidentifier && t.ident->equals(hereid))
-		{   /* should check that rest of line is blank
-		     */
-		    goto Ldone;
-		}
-		p = psave;
-	    }
-	    stringbuffer.writeUTF8(c);
-	    startline = 0;
-	}
-    }
-
-Ldone:
-    if (*p == '"')
-	p++;
-    else
-	error("delimited string must end in %c\"", delimright);
-    t->len = stringbuffer.offset;
-    stringbuffer.writeByte(0);
-    t->ustring = (unsigned char *)mem.malloc(stringbuffer.offset);
-    memcpy(t->ustring, stringbuffer.data, stringbuffer.offset);
-    stringPostfix(t);
-    return TOKstring;
-
-Lerror:
-    error("unterminated string constant starting at %s", start.toChars());
-    t->ustring = (unsigned char *)"";
-    t->len = 0;
-    t->postfix = 0;
-    return TOKstring;
-}
-
-/**************************************
- * Lex delimited strings:
- *	q{ foo(xxx) } // " foo(xxx) "
- *	q{foo(}       // "foo("
- *	q{{foo}"}"}   // "{foo}"}""
- * Input:
- *	p is on the q
- */
-
-TOK Lexer::tokenStringConstant(Token *t)
-{
-    unsigned nest = 1;
-    Loc start = loc;
-    unsigned char *pstart = ++p;
-
-    while (1)
-    {	Token tok;
-
-	scan(&tok);
-	switch (tok.value)
-	{
-	    case TOKlcurly:
-		nest++;
-		continue;
-
-	    case TOKrcurly:
-		if (--nest == 0)
-		    goto Ldone;
-		continue;
-
-	    case TOKeof:
-		goto Lerror;
-
-	    default:
-		continue;
-	}
-    }
-
-Ldone:
-    t->len = p - 1 - pstart;
-    t->ustring = (unsigned char *)mem.malloc(t->len + 1);
-    memcpy(t->ustring, pstart, t->len);
-    t->ustring[t->len] = 0;
-    stringPostfix(t);
-    return TOKstring;
-
-Lerror:
-    error("unterminated token string constant starting at %s", start.toChars());
-    t->ustring = (unsigned char *)"";
-    t->len = 0;
-    t->postfix = 0;
-    return TOKstring;
-}
-
-#endif
-
-
-/**************************************
- */
-
-TOK Lexer::escapeStringConstant(Token *t, int wide)
-{   unsigned c;
-    Loc start = loc;
-
-    p++;
-    stringbuffer.reset();
-    while (1)
-    {
-	c = *p++;
-	switch (c)
-	{
-	    case '\\':
-		switch (*p)
-		{
-		    case 'u':
-		    case 'U':
-		    case '&':
-			c = escapeSequence();
-			stringbuffer.writeUTF8(c);
-			continue;
-
-		    default:
-			c = escapeSequence();
-			break;
-		}
-		break;
-
-	    case '\n':
-		loc.linnum++;
-		break;
-
-	    case '\r':
-		if (*p == '\n')
-		    continue;	// ignore
-		c = '\n';	// treat EndOfLine as \n character
-		loc.linnum++;
-		break;
-
-	    case '"':
-		t->len = stringbuffer.offset;
-		stringbuffer.writeByte(0);
-		t->ustring = (unsigned char *)mem.malloc(stringbuffer.offset);
-		memcpy(t->ustring, stringbuffer.data, stringbuffer.offset);
-		stringPostfix(t);
-		return TOKstring;
-
-	    case 0:
-	    case 0x1A:
-		p--;
-		error("unterminated string constant starting at %s", start.toChars());
-		t->ustring = (unsigned char *)"";
-		t->len = 0;
-		t->postfix = 0;
-		return TOKstring;
-
-	    default:
-		if (c & 0x80)
-		{
-		    p--;
-		    c = decodeUTF();
-		    if (c == LS || c == PS)
-		    {	c = '\n';
-			loc.linnum++;
-		    }
-		    p++;
-		    stringbuffer.writeUTF8(c);
-		    continue;
-		}
-		break;
-	}
-	stringbuffer.writeByte(c);
-    }
-}
-
-/**************************************
- */
-
-TOK Lexer::charConstant(Token *t, int wide)
-{
-    unsigned c;
-    TOK tk = TOKcharv;
-
-    //printf("Lexer::charConstant\n");
-    p++;
-    c = *p++;
-    switch (c)
-    {
-	case '\\':
-	    switch (*p)
-	    {
-		case 'u':
-		    t->uns64value = escapeSequence();
-		    tk = TOKwcharv;
-		    break;
-
-		case 'U':
-		case '&':
-		    t->uns64value = escapeSequence();
-		    tk = TOKdcharv;
-		    break;
-
-		default:
-		    t->uns64value = escapeSequence();
-		    break;
-	    }
-	    break;
-
-	case '\n':
-	L1:
-	    loc.linnum++;
-	case '\r':
-	case 0:
-	case 0x1A:
-	case '\'':
-	    error("unterminated character constant");
-	    return tk;
-
-	default:
-	    if (c & 0x80)
-	    {
-		p--;
-		c = decodeUTF();
-		p++;
-		if (c == LS || c == PS)
-		    goto L1;
-		if (c < 0xD800 || (c >= 0xE000 && c < 0xFFFE))
-		    tk = TOKwcharv;
-		else
-		    tk = TOKdcharv;
-	    }
-	    t->uns64value = c;
-	    break;
-    }
-
-    if (*p != '\'')
-    {	error("unterminated character constant");
-	return tk;
-    }
-    p++;
-    return tk;
-}
-
-/***************************************
- * Get postfix of string literal.
- */
-
-void Lexer::stringPostfix(Token *t)
-{
-    switch (*p)
-    {
-	case 'c':
-	case 'w':
-	case 'd':
-	    t->postfix = *p;
-	    p++;
-	    break;
-
-	default:
-	    t->postfix = 0;
-	    break;
-    }
-}
-
-/***************************************
- * Read \u or \U unicode sequence
- * Input:
- *	u	'u' or 'U'
- */
-
-#if 0
-unsigned Lexer::wchar(unsigned u)
-{
-    unsigned value;
-    unsigned n;
-    unsigned char c;
-    unsigned nchars;
-
-    nchars = (u == 'U') ? 8 : 4;
-    value = 0;
-    for (n = 0; 1; n++)
-    {
-	++p;
-	if (n == nchars)
-	    break;
-	c = *p;
-	if (!ishex(c))
-	{   error("\\%c sequence must be followed by %d hex characters", u, nchars);
-	    break;
-	}
-	if (isdigit(c))
-	    c -= '0';
-	else if (islower(c))
-	    c -= 'a' - 10;
-	else
-	    c -= 'A' - 10;
-	value <<= 4;
-	value |= c;
-    }
-    return value;
-}
-#endif
-
-/**************************************
- * Read in a number.
- * If it's an integer, store it in tok.TKutok.Vlong.
- *	integers can be decimal, octal or hex
- *	Handle the suffixes U, UL, LU, L, etc.
- * If it's double, store it in tok.TKutok.Vdouble.
- * Returns:
- *	TKnum
- *	TKdouble,...
- */
-
-TOK Lexer::number(Token *t)
-{
-    // We use a state machine to collect numbers
-    enum STATE { STATE_initial, STATE_0, STATE_decimal, STATE_octal, STATE_octale,
-	STATE_hex, STATE_binary, STATE_hex0, STATE_binary0,
-	STATE_hexh, STATE_error };
-    enum STATE state;
-
-    enum FLAGS
-    {	FLAGS_decimal  = 1,		// decimal
-	FLAGS_unsigned = 2,		// u or U suffix
-	FLAGS_long     = 4,		// l or L suffix
-    };
-    enum FLAGS flags = FLAGS_decimal;
-
-    int i;
-    int base;
-    unsigned c;
-    unsigned char *start;
-    TOK result;
-
-    //printf("Lexer::number()\n");
-    state = STATE_initial;
-    base = 0;
-    stringbuffer.reset();
-    start = p;
-    while (1)
-    {
-	c = *p;
-	switch (state)
-	{
-	    case STATE_initial:		// opening state
-		if (c == '0')
-		    state = STATE_0;
-		else
-		    state = STATE_decimal;
-		break;
-
-	    case STATE_0:
-		flags = (FLAGS) (flags & ~FLAGS_decimal);
-		switch (c)
-		{
-#if ZEROH
-		    case 'H':			// 0h
-		    case 'h':
-			goto hexh;
-#endif
-		    case 'X':
-		    case 'x':
-			state = STATE_hex0;
-			break;
-
-		    case '.':
-			if (p[1] == '.')	// .. is a separate token
-			    goto done;
-		    case 'i':
-		    case 'f':
-		    case 'F':
-			goto real;
-#if ZEROH
-		    case 'E':
-		    case 'e':
-			goto case_hex;
-#endif
-		    case 'B':
-		    case 'b':
-			state = STATE_binary0;
-			break;
-
-		    case '0': case '1': case '2': case '3':
-		    case '4': case '5': case '6': case '7':
-			state = STATE_octal;
-			break;
-
-#if ZEROH
-		    case '8': case '9': case 'A':
-		    case 'C': case 'D': case 'F':
-		    case 'a': case 'c': case 'd': case 'f':
-		    case_hex:
-			state = STATE_hexh;
-			break;
-#endif
-		    case '_':
-			state = STATE_octal;
-			p++;
-			continue;
-
-		    case 'L':
-			if (p[1] == 'i')
-			    goto real;
-			goto done;
-
-		    default:
-			goto done;
-		}
-		break;
-
-	    case STATE_decimal:		// reading decimal number
-		if (!isdigit(c))
-		{
-#if ZEROH
-		    if (ishex(c)
-			|| c == 'H' || c == 'h'
-		       )
-			goto hexh;
-#endif
-		    if (c == '_')		// ignore embedded _
-		    {	p++;
-			continue;
-		    }
-		    if (c == '.' && p[1] != '.')
-			goto real;
-		    else if (c == 'i' || c == 'f' || c == 'F' ||
-			     c == 'e' || c == 'E')
-		    {
-	    real:	// It's a real number. Back up and rescan as a real
-			p = start;
-			return inreal(t);
-		    }
-		    else if (c == 'L' && p[1] == 'i')
-			goto real;
-		    goto done;
-		}
-		break;
-
-	    case STATE_hex0:		// reading hex number
-	    case STATE_hex:
-		if (!ishex(c))
-		{
-		    if (c == '_')		// ignore embedded _
-		    {	p++;
-			continue;
-		    }
-		    if (c == '.' && p[1] != '.')
-			goto real;
-		    if (c == 'P' || c == 'p' || c == 'i')
-			goto real;
-		    if (state == STATE_hex0)
-			error("Hex digit expected, not '%c'", c);
-		    goto done;
-		}
-		state = STATE_hex;
-		break;
-
-#if ZEROH
-	    hexh:
-		state = STATE_hexh;
-	    case STATE_hexh:		// parse numbers like 0FFh
-		if (!ishex(c))
-		{
-		    if (c == 'H' || c == 'h')
-		    {
-			p++;
-			base = 16;
-			goto done;
-		    }
-		    else
-		    {
-			// Check for something like 1E3 or 0E24
-			if (memchr((char *)stringbuffer.data, 'E', stringbuffer.offset) ||
-			    memchr((char *)stringbuffer.data, 'e', stringbuffer.offset))
-			    goto real;
-			error("Hex digit expected, not '%c'", c);
-			goto done;
-		    }
-		}
-		break;
-#endif
-
-	    case STATE_octal:		// reading octal number
-	    case STATE_octale:		// reading octal number with non-octal digits
-		if (!isoctal(c))
-		{
-#if ZEROH
-		    if (ishex(c)
-			|| c == 'H' || c == 'h'
-		       )
-			goto hexh;
-#endif
-		    if (c == '_')		// ignore embedded _
-		    {	p++;
-			continue;
-		    }
-		    if (c == '.' && p[1] != '.')
-			goto real;
-		    if (c == 'i')
-			goto real;
-		    if (isdigit(c))
-		    {
-			state = STATE_octale;
-		    }
-		    else
-			goto done;
-		}
-		break;
-
-	    case STATE_binary0:		// starting binary number
-	    case STATE_binary:		// reading binary number
-		if (c != '0' && c != '1')
-		{
-#if ZEROH
-		    if (ishex(c)
-			|| c == 'H' || c == 'h'
-		       )
-			goto hexh;
-#endif
-		    if (c == '_')		// ignore embedded _
-		    {	p++;
-			continue;
-		    }
-		    if (state == STATE_binary0)
-		    {	error("binary digit expected");
-			state = STATE_error;
-			break;
-		    }
-		    else
-			goto done;
-		}
-		state = STATE_binary;
-		break;
-
-	    case STATE_error:		// for error recovery
-		if (!isdigit(c))	// scan until non-digit
-		    goto done;
-		break;
-
-	    default:
-		assert(0);
-	}
-	stringbuffer.writeByte(c);
-	p++;
-    }
-done:
-    stringbuffer.writeByte(0);		// terminate string
-    if (state == STATE_octale)
-	error("Octal digit expected");
-
-    uinteger_t n;			// unsigned >=64 bit integer type
-
-    if (stringbuffer.offset == 2 && (state == STATE_decimal || state == STATE_0))
-	n = stringbuffer.data[0] - '0';
-    else
-    {
-	// Convert string to integer
-#if __DMC__
-	errno = 0;
-	n = strtoull((char *)stringbuffer.data,NULL,base);
-	if (errno == ERANGE)
-	    error("integer overflow");
-#else
-	// Not everybody implements strtoull()
-	char *p = (char *)stringbuffer.data;
-	int r = 10, d;
-
-	if (*p == '0')
-	{
-	    if (p[1] == 'x' || p[1] == 'X')
-		p += 2, r = 16;
-	    else if (p[1] == 'b' || p[1] == 'B')
-		p += 2, r = 2;
-	    else if (isdigit(p[1]))
-		p += 1, r = 8;
-	}
-
-	n = 0;
-	while (1)
-	{
-	    if (*p >= '0' && *p <= '9')
-		d = *p - '0';
-	    else if (*p >= 'a' && *p <= 'z')
-		d = *p - 'a' + 10;
-	    else if (*p >= 'A' && *p <= 'Z')
-		d = *p - 'A' + 10;
-	    else
-		break;
-	    if (d >= r)
-		break;
-	    uinteger_t n2 = n * r;
-	    //printf("n2 / r = %llx, n = %llx\n", n2/r, n);
-	    if (n2 / r != n || n2 + d < n)
-	    {
-		error ("integer overflow");
-		break;
-	    }
-
-	    n = n2 + d;
-	    p++;
-	}
-#endif
-	if (sizeof(n) > 8 &&
-	    n > 0xFFFFFFFFFFFFFFFFULL)	// if n needs more than 64 bits
-	    error("integer overflow");
-    }
-
-    // Parse trailing 'u', 'U', 'l' or 'L' in any combination
-    while (1)
-    {   unsigned char f;
-
-	switch (*p)
-	{   case 'U':
-	    case 'u':
-		f = FLAGS_unsigned;
-		goto L1;
-
-	    case 'l':
-		if (1 || !global.params.useDeprecated)
-		    error("'l' suffix is deprecated, use 'L' instead");
-	    case 'L':
-		f = FLAGS_long;
-	    L1:
-		p++;
-		if (flags & f)
-		    error("unrecognized token");
-		flags = (FLAGS) (flags | f);
-		continue;
-	    default:
-		break;
-	}
-	break;
-    }
-
-    switch (flags)
-    {
-	case 0:
-	    /* Octal or Hexadecimal constant.
-	     * First that fits: int, uint, long, ulong
-	     */
-	    if (n & 0x8000000000000000LL)
-		    result = TOKuns64v;
-	    else if (n & 0xFFFFFFFF00000000LL)
-		    result = TOKint64v;
-	    else if (n & 0x80000000)
-		    result = TOKuns32v;
-	    else
-		    result = TOKint32v;
-	    break;
-
-	case FLAGS_decimal:
-	    /* First that fits: int, long, long long
-	     */
-	    if (n & 0x8000000000000000LL)
-	    {	    error("signed integer overflow");
-		    result = TOKuns64v;
-	    }
-	    else if (n & 0xFFFFFFFF80000000LL)
-		    result = TOKint64v;
-	    else
-		    result = TOKint32v;
-	    break;
-
-	case FLAGS_unsigned:
-	case FLAGS_decimal | FLAGS_unsigned:
-	    /* First that fits: uint, ulong
-	     */
-	    if (n & 0xFFFFFFFF00000000LL)
-		    result = TOKuns64v;
-	    else
-		    result = TOKuns32v;
-	    break;
-
-	case FLAGS_decimal | FLAGS_long:
-	    if (n & 0x8000000000000000LL)
-	    {	    error("signed integer overflow");
-		    result = TOKuns64v;
-	    }
-	    else
-		    result = TOKint64v;
-	    break;
-
-	case FLAGS_long:
-	    if (n & 0x8000000000000000LL)
-		    result = TOKuns64v;
-	    else
-		    result = TOKint64v;
-	    break;
-
-	case FLAGS_unsigned | FLAGS_long:
-	case FLAGS_decimal | FLAGS_unsigned | FLAGS_long:
-	    result = TOKuns64v;
-	    break;
-
-	default:
-	    #ifdef DEBUG
-		printf("%x\n",flags);
-	    #endif
-	    assert(0);
-    }
-    t->uns64value = n;
-    return result;
-}
-
-/**************************************
- * Read in characters, converting them to real.
- * Bugs:
- *	Exponent overflow not detected.
- *	Too much requested precision is not detected.
- */
-
-TOK Lexer::inreal(Token *t)
-#ifdef __DMC__
-__in
-{
-    assert(*p == '.' || isdigit(*p));
-}
-__out (result)
-{
-    switch (result)
-    {
-	case TOKfloat32v:
-	case TOKfloat64v:
-	case TOKfloat80v:
-	case TOKimaginary32v:
-	case TOKimaginary64v:
-	case TOKimaginary80v:
-	    break;
-
-	default:
-	    assert(0);
-    }
-}
-__body
-#endif /* __DMC__ */
-{   int dblstate;
-    unsigned c;
-    char hex;			// is this a hexadecimal-floating-constant?
-    TOK result;
-
-    //printf("Lexer::inreal()\n");
-    stringbuffer.reset();
-    dblstate = 0;
-    hex = 0;
-Lnext:
-    while (1)
-    {
-	// Get next char from input
-	c = *p++;
-	//printf("dblstate = %d, c = '%c'\n", dblstate, c);
-	while (1)
-	{
-	    switch (dblstate)
-	    {
-		case 0:			// opening state
-		    if (c == '0')
-			dblstate = 9;
-		    else if (c == '.')
-			dblstate = 3;
-		    else
-			dblstate = 1;
-		    break;
-
-		case 9:
-		    dblstate = 1;
-		    if (c == 'X' || c == 'x')
-		    {	hex++;
-			break;
-		    }
-		case 1:			// digits to left of .
-		case 3:			// digits to right of .
-		case 7:			// continuing exponent digits
-		    if (!isdigit(c) && !(hex && isxdigit(c)))
-		    {
-			if (c == '_')
-			    goto Lnext;	// ignore embedded '_'
-			dblstate++;
-			continue;
-		    }
-		    break;
-
-		case 2:			// no more digits to left of .
-		    if (c == '.')
-		    {   dblstate++;
-			break;
-		    }
-		case 4:			// no more digits to right of .
-		    if ((c == 'E' || c == 'e') ||
-			hex && (c == 'P' || c == 'p'))
-		    {   dblstate = 5;
-			hex = 0;	// exponent is always decimal
-			break;
-		    }
-		    if (hex)
-			error("binary-exponent-part required");
-		    goto done;
-
-		case 5:			// looking immediately to right of E
-		    dblstate++;
-		    if (c == '-' || c == '+')
-			break;
-		case 6:			// 1st exponent digit expected
-		    if (!isdigit(c))
-			error("exponent expected");
-		    dblstate++;
-		    break;
-
-		case 8:			// past end of exponent digits
-		    goto done;
-	    }
-	    break;
-	}
-	stringbuffer.writeByte(c);
-    }
-done:
-    p--;
-
-    stringbuffer.writeByte(0);
-
-#if _WIN32 && __DMC__
-    char *save = __locale_decpoint;
-    __locale_decpoint = ".";
-#endif
-#ifdef IN_GCC
-    t->float80value = real_t::parse((char *)stringbuffer.data, real_t::LongDouble);
-#else
-    t->float80value = strtold((char *)stringbuffer.data, NULL);
-#endif
-    errno = 0;
-    float strtofres;
-    double strtodres;
-    switch (*p)
-    {
-	case 'F':
-	case 'f':
-#ifdef IN_GCC
-	    real_t::parse((char *)stringbuffer.data, real_t::Float);
-#else
-	    strtofres = strtof((char *)stringbuffer.data, NULL);
-	    // LDC change: don't error on gradual underflow
-	    if (errno == ERANGE && 
-		    strtofres != 0 && strtofres != HUGE_VALF && strtofres != -HUGE_VALF)
-		errno = 0;
-#endif
-	    result = TOKfloat32v;
-	    p++;
-	    break;
-
-	default:
-#ifdef IN_GCC
-	    real_t::parse((char *)stringbuffer.data, real_t::Double);
-#else	    
-	    strtodres = strtod((char *)stringbuffer.data, NULL);
-	    // LDC change: don't error on gradual underflow
-	    if (errno == ERANGE && 
-		    strtodres != 0 && strtodres != HUGE_VAL && strtodres != -HUGE_VAL)
-		errno = 0;
-#endif
-	    result = TOKfloat64v;
-	    break;
-
-	case 'l':
-	    if (!global.params.useDeprecated)
-		error("'l' suffix is deprecated, use 'L' instead");
-	case 'L':
-	    result = TOKfloat80v;
-	    p++;
-	    break;
-    }
-    if (*p == 'i' || *p == 'I')
-    {
-	if (!global.params.useDeprecated && *p == 'I')
-	    error("'I' suffix is deprecated, use 'i' instead");
-	p++;
-	switch (result)
-	{
-	    case TOKfloat32v:
-		result = TOKimaginary32v;
-		break;
-	    case TOKfloat64v:
-		result = TOKimaginary64v;
-		break;
-	    case TOKfloat80v:
-		result = TOKimaginary80v;
-		break;
-	}
-    }
-#if _WIN32 && __DMC__
-    __locale_decpoint = save;
-#endif
-    if (errno == ERANGE)
-	error("number is not representable");
-    return result;
-}
-
-/*********************************************
- * Do pragma.
- * Currently, the only pragma supported is:
- *	#line linnum [filespec]
- */
-
-void Lexer::pragma()
-{
-    Token tok;
-    int linnum;
-    char *filespec = NULL;
-    Loc loc = this->loc;
-
-    scan(&tok);
-    if (tok.value != TOKidentifier || tok.ident != Id::line)
-	goto Lerr;
-
-    scan(&tok);
-    if (tok.value == TOKint32v || tok.value == TOKint64v)
-	linnum = tok.uns64value - 1;
-    else
-	goto Lerr;
-
-    while (1)
-    {
-	switch (*p)
-	{
-	    case 0:
-	    case 0x1A:
-	    case '\n':
-	    Lnewline:
-		this->loc.linnum = linnum;
-		if (filespec)
-		    this->loc.filename = filespec;
-		return;
-
-	    case '\r':
-		p++;
-		if (*p != '\n')
-		{   p--;
-		    goto Lnewline;
-		}
-		continue;
-
-	    case ' ':
-	    case '\t':
-	    case '\v':
-	    case '\f':
-		p++;
-		continue;			// skip white space
-
-	    case '_':
-		if (mod && memcmp(p, "__FILE__", 8) == 0)
-		{
-		    p += 8;
-		    filespec = mem.strdup(loc.filename ? loc.filename : mod->ident->toChars());
-		}
-		continue;
-
-	    case '"':
-		if (filespec)
-		    goto Lerr;
-		stringbuffer.reset();
-		p++;
-		while (1)
-		{   unsigned c;
-
-		    c = *p;
-		    switch (c)
-		    {
-			case '\n':
-			case '\r':
-			case 0:
-			case 0x1A:
-			    goto Lerr;
-
-			case '"':
-			    stringbuffer.writeByte(0);
-			    filespec = mem.strdup((char *)stringbuffer.data);
-			    p++;
-			    break;
-
-			default:
-			    if (c & 0x80)
-			    {   unsigned u = decodeUTF();
-				if (u == PS || u == LS)
-				    goto Lerr;
-			    }
-			    stringbuffer.writeByte(c);
-			    p++;
-			    continue;
-		    }
-		    break;
-		}
-		continue;
-
-	    default:
-		if (*p & 0x80)
-		{   unsigned u = decodeUTF();
-		    if (u == PS || u == LS)
-			goto Lnewline;
-		}
-		goto Lerr;
-	}
-    }
-
-Lerr:
-    error(loc, "#line integer [\"filespec\"]\\n expected");
-}
-
-
-/********************************************
- * Decode UTF character.
- * Issue error messages for invalid sequences.
- * Return decoded character, advance p to last character in UTF sequence.
- */
-
-unsigned Lexer::decodeUTF()
-{
-    dchar_t u;
-    unsigned char c;
-    unsigned char *s = p;
-    size_t len;
-    size_t idx;
-    const char *msg;
-
-    c = *s;
-    assert(c & 0x80);
-
-    // Check length of remaining string up to 6 UTF-8 characters
-    for (len = 1; len < 6 && s[len]; len++)
-	;
-
-    idx = 0;
-    msg = utf_decodeChar(s, len, &idx, &u);
-    p += idx - 1;
-    if (msg)
-    {
-	error("%s", msg);
-    }
-    return u;
-}
-
-
-/***************************************************
- * Parse doc comment embedded between t->ptr and p.
- * Remove trailing blanks and tabs from lines.
- * Replace all newlines with \n.
- * Remove leading comment character from each line.
- * Decide if it's a lineComment or a blockComment.
- * Append to previous one for this token.
- */
-
-void Lexer::getDocComment(Token *t, unsigned lineComment)
-{
-    /* ct tells us which kind of comment it is: '/', '*', or '+'
-     */
-    unsigned char ct = t->ptr[2];
-
-    /* Start of comment text skips over / * *, / + +, or / / /
-     */
-    unsigned char *q = t->ptr + 3;	// start of comment text
-
-    unsigned char *qend = p;
-    if (ct == '*' || ct == '+')
-	qend -= 2;
-
-    /* Scan over initial row of ****'s or ++++'s or ////'s
-     */
-    for (; q < qend; q++)
-    {
-	if (*q != ct)
-	    break;
-    }
-
-    /* Remove trailing row of ****'s or ++++'s
-     */
-    if (ct != '/')
-    {
-	for (; q < qend; qend--)
-	{
-	    if (qend[-1] != ct)
-		break;
-	}
-    }
-
-    /* Comment is now [q .. qend].
-     * Canonicalize it into buf[].
-     */
-    OutBuffer buf;
-    int linestart = 0;
-
-    for (; q < qend; q++)
-    {
-	unsigned char c = *q;
-
-	switch (c)
-	{
-	    case '*':
-	    case '+':
-		if (linestart && c == ct)
-		{   linestart = 0;
-		    /* Trim preceding whitespace up to preceding \n
-		     */
-		    while (buf.offset && (buf.data[buf.offset - 1] == ' ' || buf.data[buf.offset - 1] == '\t'))
-			buf.offset--;
-		    continue;
-		}
-		break;
-
-	    case ' ':
-	    case '\t':
-		break;
-
-	    case '\r':
-		if (q[1] == '\n')
-		    continue;		// skip the \r
-		goto Lnewline;
-
-	    default:
-		if (c == 226)
-		{
-		    // If LS or PS
-		    if (q[1] == 128 &&
-			(q[2] == 168 || q[2] == 169))
-		    {
-			q += 2;
-			goto Lnewline;
-		    }
-		}
-		linestart = 0;
-		break;
-
-	    Lnewline:
-		c = '\n';		// replace all newlines with \n
-	    case '\n':
-		linestart = 1;
-
-		/* Trim trailing whitespace
-		 */
-		while (buf.offset && (buf.data[buf.offset - 1] == ' ' || buf.data[buf.offset - 1] == '\t'))
-		    buf.offset--;
-
-		break;
-	}
-	buf.writeByte(c);
-    }
-
-    // Always end with a newline
-    if (!buf.offset || buf.data[buf.offset - 1] != '\n')
-	buf.writeByte('\n');
-
-    buf.writeByte(0);
-
-    // It's a line comment if the start of the doc comment comes
-    // after other non-whitespace on the same line.
-    unsigned char** dc = (lineComment && anyToken)
-			 ? &t->lineComment
-			 : &t->blockComment;
-
-    // Combine with previous doc comment, if any
-    if (*dc)
-	*dc = combineComments(*dc, (unsigned char *)buf.data);
-    else
-	*dc = (unsigned char *)buf.extractData();
-}
-
-/********************************************
- * Combine two document comments into one,
- * separated by a newline.
- */
-
-unsigned char *Lexer::combineComments(unsigned char *c1, unsigned char *c2)
-{
-    //printf("Lexer::combineComments('%s', '%s')\n", c1, c2);
-
-    unsigned char *c = c2;
-
-    if (c1)
-    {	c = c1;
-	if (c2)
-	{   size_t len1 = strlen((char *)c1);
-	    size_t len2 = strlen((char *)c2);
-
-	    c = (unsigned char *)mem.malloc(len1 + 1 + len2 + 1);
-	    memcpy(c, c1, len1);
-	    if (len1 && c1[len1 - 1] != '\n')
-	    {	c[len1] = '\n';
-		len1++;
-	    }
-	    memcpy(c + len1, c2, len2);
-	    c[len1 + len2] = 0;
-	}
-    }
-    return c;
-}
-
-/********************************************
- * Create an identifier in the string table.
- */
-
-Identifier *Lexer::idPool(const char *s)
-{
-    size_t len = strlen(s);
-    StringValue *sv = stringtable.update(s, len);
-    Identifier *id = (Identifier *) sv->ptrvalue;
-    if (!id)
-    {
-	id = new Identifier(sv->lstring.string, TOKidentifier);
-	sv->ptrvalue = id;
-    }
-    return id;
-}
-
-/*********************************************
- * Create a unique identifier using the prefix s.
- */
-
-Identifier *Lexer::uniqueId(const char *s, int num)
-{   char buffer[32];
-    size_t slen = strlen(s);
-
-    assert(slen + sizeof(num) * 3 + 1 <= sizeof(buffer));
-    sprintf(buffer, "%s%d", s, num);
-    return idPool(buffer);
-}
-
-Identifier *Lexer::uniqueId(const char *s)
-{
-    static int num;
-    return uniqueId(s, ++num);
-}
-
-/****************************************
- */
-
-struct Keyword
-{   const char *name;
-    enum TOK value;
-};
-
-static Keyword keywords[] =
-{
-//    {	"",		TOK	},
-
-    {	"this",		TOKthis		},
-    {	"super",	TOKsuper	},
-    {	"assert",	TOKassert	},
-    {	"null",		TOKnull		},
-    {	"true",		TOKtrue		},
-    {	"false",	TOKfalse	},
-    {	"cast",		TOKcast		},
-    {	"new",		TOKnew		},
-    {	"delete",	TOKdelete	},
-    {	"throw",	TOKthrow	},
-    {	"module",	TOKmodule	},
-    {	"pragma",	TOKpragma	},
-    {	"typeof",	TOKtypeof	},
-    {	"typeid",	TOKtypeid	},
-
-    {	"template",	TOKtemplate	},
-
-    {	"void",		TOKvoid		},
-    {	"byte",		TOKint8		},
-    {	"ubyte",	TOKuns8		},
-    {	"short",	TOKint16	},
-    {	"ushort",	TOKuns16	},
-    {	"int",		TOKint32	},
-    {	"uint",		TOKuns32	},
-    {	"long",		TOKint64	},
-    {	"ulong",	TOKuns64	},
-    {	"cent",		TOKcent,	},
-    {	"ucent",	TOKucent,	},
-    {	"float",	TOKfloat32	},
-    {	"double",	TOKfloat64	},
-    {	"real",		TOKfloat80	},
-
-    {	"bool",		TOKbool		},
-    {	"char",		TOKchar		},
-    {	"wchar",	TOKwchar	},
-    {	"dchar",	TOKdchar	},
-
-    {	"ifloat",	TOKimaginary32	},
-    {	"idouble",	TOKimaginary64	},
-    {	"ireal",	TOKimaginary80	},
-
-    {	"cfloat",	TOKcomplex32	},
-    {	"cdouble",	TOKcomplex64	},
-    {	"creal",	TOKcomplex80	},
-
-    {	"delegate",	TOKdelegate	},
-    {	"function",	TOKfunction	},
-
-    {	"is",		TOKis		},
-    {	"if",		TOKif		},
-    {	"else",		TOKelse		},
-    {	"while",	TOKwhile	},
-    {	"for",		TOKfor		},
-    {	"do",		TOKdo		},
-    {	"switch",	TOKswitch	},
-    {	"case",		TOKcase		},
-    {	"default",	TOKdefault	},
-    {	"break",	TOKbreak	},
-    {	"continue",	TOKcontinue	},
-    {	"synchronized",	TOKsynchronized	},
-    {	"return",	TOKreturn	},
-    {	"goto",		TOKgoto		},
-    {	"try",		TOKtry		},
-    {	"catch",	TOKcatch	},
-    {	"finally",	TOKfinally	},
-    {	"with",		TOKwith		},
-    {	"asm",		TOKasm		},
-    {	"foreach",	TOKforeach	},
-    {	"foreach_reverse",	TOKforeach_reverse	},
-    {	"scope",	TOKscope	},
-
-    {	"struct",	TOKstruct	},
-    {	"class",	TOKclass	},
-    {	"interface",	TOKinterface	},
-    {	"union",	TOKunion	},
-    {	"enum",		TOKenum		},
-    {	"import",	TOKimport	},
-    {	"mixin",	TOKmixin	},
-    {	"static",	TOKstatic	},
-    {	"final",	TOKfinal	},
-    {	"const",	TOKconst	},
-    {	"typedef",	TOKtypedef	},
-    {	"alias",	TOKalias	},
-    {	"override",	TOKoverride	},
-    {	"abstract",	TOKabstract	},
-    {	"volatile",	TOKvolatile	},
-    {	"debug",	TOKdebug	},
-    {	"deprecated",	TOKdeprecated	},
-    {	"in",		TOKin		},
-    {	"out",		TOKout		},
-    {	"inout",	TOKinout	},
-    {	"lazy",		TOKlazy		},
-    {	"auto",		TOKauto		},
-
-    {	"align",	TOKalign	},
-    {	"extern",	TOKextern	},
-    {	"private",	TOKprivate	},
-    {	"package",	TOKpackage	},
-    {	"protected",	TOKprotected	},
-    {	"public",	TOKpublic	},
-    {	"export",	TOKexport	},
-
-    {	"body",		TOKbody		},
-    {	"invariant",	TOKinvariant	},
-    {	"unittest",	TOKunittest	},
-    {	"version",	TOKversion	},
-    //{	"manifest",	TOKmanifest	},
-
-    // Added after 1.0
-    {	"ref",		TOKref		},
-    {	"macro",	TOKmacro	},
-#if DMDV2
-    {	"pure",		TOKpure		},
-    {	"nothrow",	TOKnothrow	},
-    {	"__thread",	TOKtls		},
-    {	"__traits",	TOKtraits	},
-    {	"__overloadset", TOKoverloadset	},
-    {	"__FILE__",	TOKfile		},
-    {	"__LINE__",	TOKline		},
-    {	"shared",	TOKshared	},
-    {	"immutable",	TOKimmutable	},
-#endif
-};
-
-int Token::isKeyword()
-{
-    for (unsigned u = 0; u < sizeof(keywords) / sizeof(keywords[0]); u++)
-    {
-	if (keywords[u].value == value)
-	    return 1;
-    }
-    return 0;
-}
-
-void Lexer::initKeywords()
-{   StringValue *sv;
-    unsigned u;
-    enum TOK v;
-    unsigned nkeywords = sizeof(keywords) / sizeof(keywords[0]);
-
-    if (global.params.Dversion == 1)
-	nkeywords -= 2;
-
-    cmtable_init();
-
-    for (u = 0; u < nkeywords; u++)
-    {	const char *s;
-
-	//printf("keyword[%d] = '%s'\n",u, keywords[u].name);
-	s = keywords[u].name;
-	v = keywords[u].value;
-	sv = stringtable.insert(s, strlen(s));
-	sv->ptrvalue = (void *) new Identifier(sv->lstring.string,v);
-
-	//printf("tochars[%d] = '%s'\n",v, s);
-	Token::tochars[v] = s;
-    }
-
-    Token::tochars[TOKeof]		= "EOF";
-    Token::tochars[TOKlcurly]		= "{";
-    Token::tochars[TOKrcurly]		= "}";
-    Token::tochars[TOKlparen]		= "(";
-    Token::tochars[TOKrparen]		= ")";
-    Token::tochars[TOKlbracket]		= "[";
-    Token::tochars[TOKrbracket]		= "]";
-    Token::tochars[TOKsemicolon]	= ";";
-    Token::tochars[TOKcolon]		= ":";
-    Token::tochars[TOKcomma]		= ",";
-    Token::tochars[TOKdot]		= ".";
-    Token::tochars[TOKxor]		= "^";
-    Token::tochars[TOKxorass]		= "^=";
-    Token::tochars[TOKassign]		= "=";
-    Token::tochars[TOKconstruct]	= "=";
-#if DMDV2
-    Token::tochars[TOKblit]		= "=";
-#endif
-    Token::tochars[TOKlt]		= "<";
-    Token::tochars[TOKgt]		= ">";
-    Token::tochars[TOKle]		= "<=";
-    Token::tochars[TOKge]		= ">=";
-    Token::tochars[TOKequal]		= "==";
-    Token::tochars[TOKnotequal]		= "!=";
-    Token::tochars[TOKnotidentity]	= "!is";
-    Token::tochars[TOKtobool]		= "!!";
-
-    Token::tochars[TOKunord]		= "!<>=";
-    Token::tochars[TOKue]		= "!<>";
-    Token::tochars[TOKlg]		= "<>";
-    Token::tochars[TOKleg]		= "<>=";
-    Token::tochars[TOKule]		= "!>";
-    Token::tochars[TOKul]		= "!>=";
-    Token::tochars[TOKuge]		= "!<";
-    Token::tochars[TOKug]		= "!<=";
-
-    Token::tochars[TOKnot]		= "!";
-    Token::tochars[TOKtobool]		= "!!";
-    Token::tochars[TOKshl]		= "<<";
-    Token::tochars[TOKshr]		= ">>";
-    Token::tochars[TOKushr]		= ">>>";
-    Token::tochars[TOKadd]		= "+";
-    Token::tochars[TOKmin]		= "-";
-    Token::tochars[TOKmul]		= "*";
-    Token::tochars[TOKdiv]		= "/";
-    Token::tochars[TOKmod]		= "%";
-    Token::tochars[TOKslice]		= "..";
-    Token::tochars[TOKdotdotdot]	= "...";
-    Token::tochars[TOKand]		= "&";
-    Token::tochars[TOKandand]		= "&&";
-    Token::tochars[TOKor]		= "|";
-    Token::tochars[TOKoror]		= "||";
-    Token::tochars[TOKarray]		= "[]";
-    Token::tochars[TOKindex]		= "[i]";
-    Token::tochars[TOKaddress]		= "&";
-    Token::tochars[TOKstar]		= "*";
-    Token::tochars[TOKtilde]		= "~";
-    Token::tochars[TOKdollar]		= "$";
-    Token::tochars[TOKcast]		= "cast";
-    Token::tochars[TOKplusplus]		= "++";
-    Token::tochars[TOKminusminus]	= "--";
-    Token::tochars[TOKtype]		= "type";
-    Token::tochars[TOKquestion]		= "?";
-    Token::tochars[TOKneg]		= "-";
-    Token::tochars[TOKuadd]		= "+";
-    Token::tochars[TOKvar]		= "var";
-    Token::tochars[TOKaddass]		= "+=";
-    Token::tochars[TOKminass]		= "-=";
-    Token::tochars[TOKmulass]		= "*=";
-    Token::tochars[TOKdivass]		= "/=";
-    Token::tochars[TOKmodass]		= "%=";
-    Token::tochars[TOKshlass]		= "<<=";
-    Token::tochars[TOKshrass]		= ">>=";
-    Token::tochars[TOKushrass]		= ">>>=";
-    Token::tochars[TOKandass]		= "&=";
-    Token::tochars[TOKorass]		= "|=";
-    Token::tochars[TOKcatass]		= "~=";
-    Token::tochars[TOKcat]		= "~";
-    Token::tochars[TOKcall]		= "call";
-    Token::tochars[TOKidentity]		= "is";
-    Token::tochars[TOKnotidentity]	= "!is";
-
-    Token::tochars[TOKorass]		= "|=";
-    Token::tochars[TOKidentifier]	= "identifier";
-
-     // For debugging
-    Token::tochars[TOKdotexp]		= "dotexp";
-    Token::tochars[TOKdotti]		= "dotti";
-    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";
-    Token::tochars[TOKstructliteral]	= "structliteral";
-    Token::tochars[TOKstring]		= "string";
-    Token::tochars[TOKdsymbol]		= "symbol";
-    Token::tochars[TOKtuple]		= "tuple";
-    Token::tochars[TOKdeclaration]	= "declaration";
-    Token::tochars[TOKdottd]		= "dottd";
-    Token::tochars[TOKon_scope_exit]	= "scope(exit)";
-}
+
+// 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.
+
+#if IN_LLVM
+#include <cmath>
+#endif
+
+/* Lexical Analyzer */
+
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <stdarg.h>
+#include <errno.h>
+#include <wchar.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <time.h>	// for time() and ctime()
+
+#include "rmem.h"
+
+#include "stringtable.h"
+
+#include "lexer.h"
+#include "utf.h"
+#include "identifier.h"
+#include "id.h"
+#include "module.h"
+
+#if _WIN32 && __DMC__
+// from \dm\src\include\setlocal.h
+extern "C" char * __cdecl __locale_decpoint;
+#endif
+
+extern int HtmlNamedEntity(unsigned char *p, int length);
+
+#define LS 0x2028	// UTF line separator
+#define PS 0x2029	// UTF paragraph separator
+
+/********************************************
+ * Do our own char maps
+ */
+
+static unsigned char cmtable[256];
+
+const int CMoctal =	0x1;
+const int CMhex =	0x2;
+const int CMidchar =	0x4;
+
+inline unsigned char isoctal (unsigned char c) { return cmtable[c] & CMoctal; }
+inline unsigned char ishex   (unsigned char c) { return cmtable[c] & CMhex; }
+inline unsigned char isidchar(unsigned char c) { return cmtable[c] & CMidchar; }
+
+static void cmtable_init()
+{
+    for (unsigned c = 0; c < sizeof(cmtable) / sizeof(cmtable[0]); c++)
+    {
+	if ('0' <= c && c <= '7')
+	    cmtable[c] |= CMoctal;
+	if (isdigit(c) || ('a' <= c && c <= 'f') || ('A' <= c && c <= 'F'))
+	    cmtable[c] |= CMhex;
+	if (isalnum(c) || c == '_')
+	    cmtable[c] |= CMidchar;
+    }
+}
+
+
+/************************* Token **********************************************/
+
+const char *Token::tochars[TOKMAX];
+
+void *Token::operator new(size_t size)
+{   Token *t;
+
+    if (Lexer::freelist)
+    {
+	t = Lexer::freelist;
+	Lexer::freelist = t->next;
+	return t;
+    }
+
+    return ::operator new(size);
+}
+
+#ifdef DEBUG
+void Token::print()
+{
+    fprintf(stdmsg, "%s\n", toChars());
+}
+#endif
+
+const char *Token::toChars()
+{   const char *p;
+    static char buffer[3 + 3 * sizeof(value) + 1];
+
+    p = buffer;
+    switch (value)
+    {
+	case TOKint32v:
+	    sprintf(buffer,"%d",(d_int32)int64value);
+	    break;
+
+	case TOKuns32v:
+	case TOKcharv:
+	case TOKwcharv:
+	case TOKdcharv:
+	    sprintf(buffer,"%uU",(d_uns32)uns64value);
+	    break;
+
+	case TOKint64v:
+	    sprintf(buffer,"%jdL",int64value);
+	    break;
+
+	case TOKuns64v:
+	    sprintf(buffer,"%juUL",uns64value);
+	    break;
+
+#if IN_GCC
+	case TOKfloat32v:
+	case TOKfloat64v:
+	case TOKfloat80v:
+	    float80value.format(buffer, sizeof(buffer));
+	    break;
+	case TOKimaginary32v:
+	case TOKimaginary64v:
+	case TOKimaginary80v:
+	    float80value.format(buffer, sizeof(buffer));
+	    // %% buffer
+	    strcat(buffer, "i");
+	    break;
+#else
+	case TOKfloat32v:
+	    sprintf(buffer,"%Lgf", float80value);
+	    break;
+
+	case TOKfloat64v:
+	    sprintf(buffer,"%Lg", float80value);
+	    break;
+
+	case TOKfloat80v:
+	    sprintf(buffer,"%LgL", float80value);
+	    break;
+
+	case TOKimaginary32v:
+	    sprintf(buffer,"%Lgfi", float80value);
+	    break;
+
+	case TOKimaginary64v:
+	    sprintf(buffer,"%Lgi", float80value);
+	    break;
+
+	case TOKimaginary80v:
+	    sprintf(buffer,"%LgLi", float80value);
+	    break;
+#endif
+
+	case TOKstring:
+#if CSTRINGS
+	    p = string;
+#else
+	{   OutBuffer buf;
+
+	    buf.writeByte('"');
+	    for (size_t i = 0; i < len; )
+	    {	unsigned c;
+
+		utf_decodeChar((unsigned char *)ustring, len, &i, &c);
+		switch (c)
+		{
+		    case 0:
+			break;
+
+		    case '"':
+		    case '\\':
+			buf.writeByte('\\');
+		    default:
+			if (isprint(c))
+			    buf.writeByte(c);
+			else if (c <= 0x7F)
+			    buf.printf("\\x%02x", c);
+			else if (c <= 0xFFFF)
+			    buf.printf("\\u%04x", c);
+			else
+			    buf.printf("\\U%08x", c);
+			continue;
+		}
+		break;
+	    }
+	    buf.writeByte('"');
+	    if (postfix)
+		buf.writeByte('"');
+	    buf.writeByte(0);
+	    p = (char *)buf.extractData();
+	}
+#endif
+	    break;
+
+	case TOKidentifier:
+	case TOKenum:
+	case TOKstruct:
+	case TOKimport:
+	CASE_BASIC_TYPES:
+	    p = ident->toChars();
+	    break;
+
+	default:
+	    p = toChars(value);
+	    break;
+    }
+    return p;
+}
+
+const char *Token::toChars(enum TOK value)
+{   const char *p;
+    static char buffer[3 + 3 * sizeof(value) + 1];
+
+    p = tochars[value];
+    if (!p)
+    {	sprintf(buffer,"TOK%d",value);
+	p = buffer;
+    }
+    return p;
+}
+
+/*************************** Lexer ********************************************/
+
+Token *Lexer::freelist = NULL;
+StringTable Lexer::stringtable;
+OutBuffer Lexer::stringbuffer;
+
+Lexer::Lexer(Module *mod,
+	unsigned char *base, unsigned begoffset, unsigned endoffset,
+	int doDocComment, int commentToken)
+    : loc(mod, 1)
+{
+    //printf("Lexer::Lexer(%p,%d)\n",base,length);
+    //printf("lexer.mod = %p, %p\n", mod, this->loc.mod);
+    memset(&token,0,sizeof(token));
+    this->base = base;
+    this->end  = base + endoffset;
+    p = base + begoffset;
+    this->mod = mod;
+    this->doDocComment = doDocComment;
+    this->anyToken = 0;
+    this->commentToken = commentToken;
+    //initKeywords();
+
+    /* If first line starts with '#!', ignore the line
+     */
+
+    if (p[0] == '#' && p[1] =='!')
+    {
+	p += 2;
+	while (1)
+	{   unsigned char c = *p;
+	    switch (c)
+	    {
+		case '\n':
+		    p++;
+		    break;
+
+		case '\r':
+		    p++;
+		    if (*p == '\n')
+			p++;
+		    break;
+
+		case 0:
+		case 0x1A:
+		    break;
+
+		default:
+		    if (c & 0x80)
+		    {   unsigned u = decodeUTF();
+			if (u == PS || u == LS)
+			    break;
+		    }
+		    p++;
+		    continue;
+	    }
+	    break;
+	}
+	loc.linnum = 2;
+    }
+}
+
+
+void Lexer::error(const char *format, ...)
+{
+    if (mod && !global.gag)
+    {
+	char *p = loc.toChars();
+	if (*p)
+	    fprintf(stdmsg, "%s: ", p);
+	mem.free(p);
+
+	va_list ap;
+	va_start(ap, format);
+	vfprintf(stdmsg, format, ap);
+	va_end(ap);
+
+	fprintf(stdmsg, "\n");
+	fflush(stdmsg);
+
+	if (global.errors >= 20)	// moderate blizzard of cascading messages
+	    fatal();
+    }
+    global.errors++;
+}
+
+void Lexer::error(Loc loc, const char *format, ...)
+{
+    if (mod && !global.gag)
+    {
+	char *p = loc.toChars();
+	if (*p)
+	    fprintf(stdmsg, "%s: ", p);
+	mem.free(p);
+
+	va_list ap;
+	va_start(ap, format);
+	vfprintf(stdmsg, format, ap);
+	va_end(ap);
+
+	fprintf(stdmsg, "\n");
+	fflush(stdmsg);
+
+	if (global.errors >= 20)	// moderate blizzard of cascading messages
+	    fatal();
+    }
+    global.errors++;
+}
+
+TOK Lexer::nextToken()
+{   Token *t;
+
+    if (token.next)
+    {
+	t = token.next;
+	memcpy(&token,t,sizeof(Token));
+	t->next = freelist;
+	freelist = t;
+    }
+    else
+    {
+	scan(&token);
+    }
+    //token.print();
+    return token.value;
+}
+
+Token *Lexer::peek(Token *ct)
+{   Token *t;
+
+    if (ct->next)
+	t = ct->next;
+    else
+    {
+	t = new Token();
+	scan(t);
+	t->next = NULL;
+	ct->next = t;
+    }
+    return t;
+}
+
+/***********************
+ * Look ahead at next token's value.
+ */
+
+TOK Lexer::peekNext()
+{
+    return peek(&token)->value;
+}
+
+/***********************
+ * Look 2 tokens ahead at value.
+ */
+
+TOK Lexer::peekNext2()
+{
+    Token *t = peek(&token);
+    return peek(t)->value;
+}
+
+/*********************************
+ * tk is on the opening (.
+ * Look ahead and return token that is past the closing ).
+ */
+
+Token *Lexer::peekPastParen(Token *tk)
+{
+    //printf("peekPastParen()\n");
+    int parens = 1;
+    int curlynest = 0;
+    while (1)
+    {
+	tk = peek(tk);
+	//tk->print();
+	switch (tk->value)
+	{
+	    case TOKlparen:
+		parens++;
+		continue;
+
+	    case TOKrparen:
+		--parens;
+		if (parens)
+		    continue;
+		tk = peek(tk);
+		break;
+
+	    case TOKlcurly:
+		curlynest++;
+		continue;
+
+	    case TOKrcurly:
+		if (--curlynest >= 0)
+		    continue;
+		break;
+
+	    case TOKsemicolon:
+		if (curlynest)
+		    continue;
+		break;
+
+	    case TOKeof:
+		break;
+
+	    default:
+		continue;
+	}
+	return tk;
+    }
+}
+
+/**********************************
+ * Determine if string is a valid Identifier.
+ * Placed here because of commonality with Lexer functionality.
+ * Returns:
+ *	0	invalid
+ */
+
+int Lexer::isValidIdentifier(char *p)
+{
+    size_t len;
+    size_t idx;
+
+    if (!p || !*p)
+	goto Linvalid;
+
+    if (*p >= '0' && *p <= '9')		// beware of isdigit() on signed chars
+	goto Linvalid;
+
+    len = strlen(p);
+    idx = 0;
+    while (p[idx])
+    {   dchar_t dc;
+
+	const char *q = utf_decodeChar((unsigned char *)p, len, &idx, &dc);
+	if (q)
+	    goto Linvalid;
+
+	if (!((dc >= 0x80 && isUniAlpha(dc)) || isalnum(dc) || dc == '_'))
+	    goto Linvalid;
+    }
+    return 1;
+
+Linvalid:
+    return 0;
+}
+
+/****************************
+ * Turn next token in buffer into a token.
+ */
+
+void Lexer::scan(Token *t)
+{
+    unsigned lastLine = loc.linnum;
+    unsigned linnum;
+
+    t->blockComment = NULL;
+    t->lineComment = NULL;
+    while (1)
+    {
+	t->ptr = p;
+	//printf("p = %p, *p = '%c'\n",p,*p);
+	switch (*p)
+	{
+	    case 0:
+	    case 0x1A:
+		t->value = TOKeof;			// end of file
+		return;
+
+	    case ' ':
+	    case '\t':
+	    case '\v':
+	    case '\f':
+		p++;
+		continue;			// skip white space
+
+	    case '\r':
+		p++;
+		if (*p != '\n')			// if CR stands by itself
+		    loc.linnum++;
+		continue;			// skip white space
+
+	    case '\n':
+		p++;
+		loc.linnum++;
+		continue;			// skip white space
+
+	    case '0':  	case '1':   case '2':   case '3':   case '4':
+	    case '5':  	case '6':   case '7':   case '8':   case '9':
+		t->value = number(t);
+		return;
+
+#if CSTRINGS
+	    case '\'':
+		t->value = charConstant(t, 0);
+		return;
+
+	    case '"':
+		t->value = stringConstant(t,0);
+		return;
+
+	    case 'l':
+	    case 'L':
+		if (p[1] == '\'')
+		{
+		    p++;
+		    t->value = charConstant(t, 1);
+		    return;
+		}
+		else if (p[1] == '"')
+		{
+		    p++;
+		    t->value = stringConstant(t, 1);
+		    return;
+		}
+#else
+	    case '\'':
+		t->value = charConstant(t,0);
+		return;
+
+	    case 'r':
+		if (p[1] != '"')
+		    goto case_ident;
+		p++;
+	    case '`':
+		t->value = wysiwygStringConstant(t, *p);
+		return;
+
+	    case 'x':
+		if (p[1] != '"')
+		    goto case_ident;
+		p++;
+		t->value = hexStringConstant(t);
+		return;
+
+#if DMDV2
+	    case 'q':
+		if (p[1] == '"')
+		{
+		    p++;
+		    t->value = delimitedStringConstant(t);
+		    return;
+		}
+		else if (p[1] == '{')
+		{
+		    p++;
+		    t->value = tokenStringConstant(t);
+		    return;
+		}
+		else
+		    goto case_ident;
+#endif
+
+	    case '"':
+		t->value = escapeStringConstant(t,0);
+		return;
+#if ! TEXTUAL_ASSEMBLY_OUT
+	    case '\\':			// escaped string literal
+	    {	unsigned c;
+		unsigned char *pstart = p;
+
+		stringbuffer.reset();
+		do
+		{
+		    p++;
+		    switch (*p)
+		    {
+			case 'u':
+			case 'U':
+			case '&':
+			    c = escapeSequence();
+			    stringbuffer.writeUTF8(c);
+			    break;
+
+			default:
+			    c = escapeSequence();
+			    stringbuffer.writeByte(c);
+			    break;
+		    }
+		} while (*p == '\\');
+		t->len = stringbuffer.offset;
+		stringbuffer.writeByte(0);
+		t->ustring = (unsigned char *)mem.malloc(stringbuffer.offset);
+		memcpy(t->ustring, stringbuffer.data, stringbuffer.offset);
+		t->postfix = 0;
+		t->value = TOKstring;
+		if (!global.params.useDeprecated)
+		    error("Escape String literal %.*s is deprecated, use double quoted string literal \"%.*s\" instead", p - pstart, pstart, p - pstart, pstart);
+		return;
+	    }
+#endif
+	    case 'l':
+	    case 'L':
+#endif
+	    case 'a':  	case 'b':   case 'c':   case 'd':   case 'e':
+	    case 'f':  	case 'g':   case 'h':   case 'i':   case 'j':
+	    case 'k':  	            case 'm':   case 'n':   case 'o':
+#if DMDV2
+	    case 'p':  	/*case 'q': case 'r':*/ case 's':   case 't':
+#else
+	    case 'p':  	case 'q': /*case 'r':*/ case 's':   case 't':
+#endif
+	    case 'u':  	case 'v':   case 'w': /*case 'x':*/ case 'y':
+	    case 'z':
+	    case 'A':  	case 'B':   case 'C':   case 'D':   case 'E':
+	    case 'F':  	case 'G':   case 'H':   case 'I':   case 'J':
+	    case 'K':  	            case 'M':   case 'N':   case 'O':
+	    case 'P':  	case 'Q':   case 'R':   case 'S':   case 'T':
+	    case 'U':  	case 'V':   case 'W':   case 'X':   case 'Y':
+	    case 'Z':
+	    case '_':
+	    case_ident:
+	    {   unsigned char c;
+		StringValue *sv;
+		Identifier *id;
+
+		do
+		{
+		    c = *++p;
+		} while (isidchar(c) || (c & 0x80 && isUniAlpha(decodeUTF())));
+		sv = stringtable.update((char *)t->ptr, p - t->ptr);
+		id = (Identifier *) sv->ptrvalue;
+		if (!id)
+		{   id = new Identifier(sv->lstring.string,TOKidentifier);
+		    sv->ptrvalue = id;
+		}
+		t->ident = id;
+		t->value = (enum TOK) id->value;
+		anyToken = 1;
+		if (*t->ptr == '_')	// if special identifier token
+		{
+		    static char date[11+1];
+		    static char time[8+1];
+		    static char timestamp[24+1];
+
+		    if (!date[0])	// lazy evaluation
+		    {   time_t t;
+			char *p;
+
+			::time(&t);
+			p = ctime(&t);
+			assert(p);
+			sprintf(date, "%.6s %.4s", p + 4, p + 20);
+			sprintf(time, "%.8s", p + 11);
+			sprintf(timestamp, "%.24s", p);
+		    }
+
+#if DMDV1
+		    if (mod && id == Id::FILE)
+		    {
+			t->ustring = (unsigned char *)(loc.filename ? loc.filename : mod->ident->toChars());
+			goto Lstr;
+		    }
+		    else if (mod && id == Id::LINE)
+		    {
+			t->value = TOKint64v;
+			t->uns64value = loc.linnum;
+		    }
+		    else
+#endif
+		    if (id == Id::DATE)
+		    {
+			t->ustring = (unsigned char *)date;
+			goto Lstr;
+		    }
+		    else if (id == Id::TIME)
+		    {
+			t->ustring = (unsigned char *)time;
+			goto Lstr;
+		    }
+		    else if (id == Id::VENDOR)
+		    {
+			t->ustring = (unsigned char *)"LDC";
+			goto Lstr;
+		    }
+		    else if (id == Id::TIMESTAMP)
+		    {
+			t->ustring = (unsigned char *)timestamp;
+		     Lstr:
+			t->value = TOKstring;
+		     Llen:
+			t->postfix = 0;
+			t->len = strlen((char *)t->ustring);
+		    }
+		    else if (id == Id::VERSIONX)
+		    {	unsigned major = 0;
+			unsigned minor = 0;
+
+			for (const char *p = global.version + 1; 1; p++)
+			{
+			    char c = *p;
+			    if (isdigit(c))
+				minor = minor * 10 + c - '0';
+			    else if (c == '.')
+			    {	major = minor;
+				minor = 0;
+			    }
+			    else
+				break;
+			}
+			t->value = TOKint64v;
+			t->uns64value = major * 1000 + minor;
+		    }
+#if DMDV2
+		    else if (id == Id::EOFX)
+		    {
+			t->value = TOKeof;
+			// Advance scanner to end of file
+			while (!(*p == 0 || *p == 0x1A))
+			    p++;
+		    }
+#endif
+		}
+		//printf("t->value = %d\n",t->value);
+		return;
+	    }
+
+	    case '/':
+		p++;
+		switch (*p)
+		{
+		    case '=':
+			p++;
+			t->value = TOKdivass;
+			return;
+
+		    case '*':
+			p++;
+			linnum = loc.linnum;
+			while (1)
+			{
+			    while (1)
+			    {	unsigned char c = *p;
+				switch (c)
+				{
+				    case '/':
+					break;
+
+				    case '\n':
+					loc.linnum++;
+					p++;
+					continue;
+
+				    case '\r':
+					p++;
+					if (*p != '\n')
+					    loc.linnum++;
+					continue;
+
+				    case 0:
+				    case 0x1A:
+					error("unterminated /* */ comment");
+					p = end;
+					t->value = TOKeof;
+					return;
+
+				    default:
+					if (c & 0x80)
+					{   unsigned u = decodeUTF();
+					    if (u == PS || u == LS)
+						loc.linnum++;
+					}
+					p++;
+					continue;
+				}
+				break;
+			    }
+			    p++;
+			    if (p[-2] == '*' && p - 3 != t->ptr)
+				break;
+			}
+			if (commentToken)
+			{
+			    t->value = TOKcomment;
+			    return;
+			}
+			else if (doDocComment && t->ptr[2] == '*' && p - 4 != t->ptr)
+			{   // if /** but not /**/
+			    getDocComment(t, lastLine == linnum);
+			}
+			continue;
+
+		    case '/':		// do // style comments
+			linnum = loc.linnum;
+			while (1)
+			{   unsigned char c = *++p;
+			    switch (c)
+			    {
+				case '\n':
+				    break;
+
+				case '\r':
+				    if (p[1] == '\n')
+					p++;
+				    break;
+
+				case 0:
+				case 0x1A:
+				    if (commentToken)
+				    {
+					p = end;
+					t->value = TOKcomment;
+					return;
+				    }
+				    if (doDocComment && t->ptr[2] == '/')
+					getDocComment(t, lastLine == linnum);
+				    p = end;
+				    t->value = TOKeof;
+				    return;
+
+				default:
+				    if (c & 0x80)
+				    {   unsigned u = decodeUTF();
+					if (u == PS || u == LS)
+					    break;
+				    }
+				    continue;
+			    }
+			    break;
+			}
+
+			if (commentToken)
+			{
+			    p++;
+			    loc.linnum++;
+			    t->value = TOKcomment;
+			    return;
+			}
+			if (doDocComment && t->ptr[2] == '/')
+			    getDocComment(t, lastLine == linnum);
+
+			p++;
+			loc.linnum++;
+			continue;
+
+		    case '+':
+		    {	int nest;
+
+			linnum = loc.linnum;
+			p++;
+			nest = 1;
+			while (1)
+			{   unsigned char c = *p;
+			    switch (c)
+			    {
+				case '/':
+				    p++;
+				    if (*p == '+')
+				    {
+					p++;
+					nest++;
+				    }
+				    continue;
+
+				case '+':
+				    p++;
+				    if (*p == '/')
+				    {
+					p++;
+					if (--nest == 0)
+					    break;
+				    }
+				    continue;
+
+				case '\r':
+				    p++;
+				    if (*p != '\n')
+					loc.linnum++;
+				    continue;
+
+				case '\n':
+				    loc.linnum++;
+				    p++;
+				    continue;
+
+				case 0:
+				case 0x1A:
+				    error("unterminated /+ +/ comment");
+				    p = end;
+				    t->value = TOKeof;
+				    return;
+
+				default:
+				    if (c & 0x80)
+				    {   unsigned u = decodeUTF();
+					if (u == PS || u == LS)
+					    loc.linnum++;
+				    }
+				    p++;
+				    continue;
+			    }
+			    break;
+			}
+			if (commentToken)
+			{
+			    t->value = TOKcomment;
+			    return;
+			}
+			if (doDocComment && t->ptr[2] == '+' && p - 4 != t->ptr)
+			{   // if /++ but not /++/
+			    getDocComment(t, lastLine == linnum);
+			}
+			continue;
+		    }
+		}
+		t->value = TOKdiv;
+		return;
+
+	    case '.':
+		p++;
+		if (isdigit(*p))
+		{   /* Note that we don't allow ._1 and ._ as being
+		     * valid floating point numbers.
+		     */
+		    p--;
+		    t->value = inreal(t);
+		}
+		else if (p[0] == '.')
+		{
+		    if (p[1] == '.')
+		    {   p += 2;
+			t->value = TOKdotdotdot;
+		    }
+		    else
+		    {   p++;
+			t->value = TOKslice;
+		    }
+		}
+		else
+		    t->value = TOKdot;
+		return;
+
+	    case '&':
+		p++;
+		if (*p == '=')
+		{   p++;
+		    t->value = TOKandass;
+		}
+		else if (*p == '&')
+		{   p++;
+		    t->value = TOKandand;
+		}
+		else
+		    t->value = TOKand;
+		return;
+
+	    case '|':
+		p++;
+		if (*p == '=')
+		{   p++;
+		    t->value = TOKorass;
+		}
+		else if (*p == '|')
+		{   p++;
+		    t->value = TOKoror;
+		}
+		else
+		    t->value = TOKor;
+		return;
+
+	    case '-':
+		p++;
+		if (*p == '=')
+		{   p++;
+		    t->value = TOKminass;
+		}
+#if 0
+		else if (*p == '>')
+		{   p++;
+		    t->value = TOKarrow;
+		}
+#endif
+		else if (*p == '-')
+		{   p++;
+		    t->value = TOKminusminus;
+		}
+		else
+		    t->value = TOKmin;
+		return;
+
+	    case '+':
+		p++;
+		if (*p == '=')
+		{   p++;
+		    t->value = TOKaddass;
+		}
+		else if (*p == '+')
+		{   p++;
+		    t->value = TOKplusplus;
+		}
+		else
+		    t->value = TOKadd;
+		return;
+
+	    case '<':
+		p++;
+		if (*p == '=')
+		{   p++;
+		    t->value = TOKle;			// <=
+		}
+		else if (*p == '<')
+		{   p++;
+		    if (*p == '=')
+		    {   p++;
+			t->value = TOKshlass;		// <<=
+		    }
+		    else
+			t->value = TOKshl;		// <<
+		}
+		else if (*p == '>')
+		{   p++;
+		    if (*p == '=')
+		    {   p++;
+			t->value = TOKleg;		// <>=
+		    }
+		    else
+			t->value = TOKlg;		// <>
+		}
+		else
+		    t->value = TOKlt;			// <
+		return;
+
+	    case '>':
+		p++;
+		if (*p == '=')
+		{   p++;
+		    t->value = TOKge;			// >=
+		}
+		else if (*p == '>')
+		{   p++;
+		    if (*p == '=')
+		    {   p++;
+			t->value = TOKshrass;		// >>=
+		    }
+		    else if (*p == '>')
+		    {	p++;
+			if (*p == '=')
+			{   p++;
+			    t->value = TOKushrass;	// >>>=
+			}
+			else
+			    t->value = TOKushr;		// >>>
+		    }
+		    else
+			t->value = TOKshr;		// >>
+		}
+		else
+		    t->value = TOKgt;			// >
+		return;
+
+	    case '!':
+		p++;
+		if (*p == '=')
+		{   p++;
+		    if (*p == '=' && global.params.Dversion == 1)
+		    {	p++;
+			t->value = TOKnotidentity;	// !==
+		    }
+		    else
+			t->value = TOKnotequal;		// !=
+		}
+		else if (*p == '<')
+		{   p++;
+		    if (*p == '>')
+		    {	p++;
+			if (*p == '=')
+			{   p++;
+			    t->value = TOKunord; // !<>=
+			}
+			else
+			    t->value = TOKue;	// !<>
+		    }
+		    else if (*p == '=')
+		    {	p++;
+			t->value = TOKug;	// !<=
+		    }
+		    else
+			t->value = TOKuge;	// !<
+		}
+		else if (*p == '>')
+		{   p++;
+		    if (*p == '=')
+		    {	p++;
+			t->value = TOKul;	// !>=
+		    }
+		    else
+			t->value = TOKule;	// !>
+		}
+		else
+		    t->value = TOKnot;		// !
+		return;
+
+	    case '=':
+		p++;
+		if (*p == '=')
+		{   p++;
+		    if (*p == '=' && global.params.Dversion == 1)
+		    {	p++;
+			t->value = TOKidentity;		// ===
+		    }
+		    else
+			t->value = TOKequal;		// ==
+		}
+		else
+		    t->value = TOKassign;		// =
+		return;
+
+	    case '~':
+		p++;
+		if (*p == '=')
+		{   p++;
+		    t->value = TOKcatass;		// ~=
+		}
+		else
+		    t->value = TOKtilde;		// ~
+		return;
+
+#define SINGLE(c,tok) case c: p++; t->value = tok; return;
+
+	    SINGLE('(',	TOKlparen)
+	    SINGLE(')', TOKrparen)
+	    SINGLE('[', TOKlbracket)
+	    SINGLE(']', TOKrbracket)
+	    SINGLE('{', TOKlcurly)
+	    SINGLE('}', TOKrcurly)
+	    SINGLE('?', TOKquestion)
+	    SINGLE(',', TOKcomma)
+	    SINGLE(';', TOKsemicolon)
+	    SINGLE(':', TOKcolon)
+	    SINGLE('$', TOKdollar)
+
+#undef SINGLE
+
+#define DOUBLE(c1,tok1,c2,tok2)		\
+	    case c1:			\
+		p++;			\
+		if (*p == c2)		\
+		{   p++;		\
+		    t->value = tok2;	\
+		}			\
+		else			\
+		    t->value = tok1;	\
+		return;
+
+	    DOUBLE('*', TOKmul, '=', TOKmulass)
+	    DOUBLE('%', TOKmod, '=', TOKmodass)
+	    DOUBLE('^', TOKxor, '=', TOKxorass)
+
+#undef DOUBLE
+
+	    case '#':
+		p++;
+		pragma();
+		continue;
+
+	    default:
+	    {	unsigned char c = *p;
+
+		if (c & 0x80)
+		{   unsigned u = decodeUTF();
+
+		    // Check for start of unicode identifier
+		    if (isUniAlpha(u))
+			goto case_ident;
+
+		    if (u == PS || u == LS)
+		    {
+			loc.linnum++;
+			p++;
+			continue;
+		    }
+		}
+		if (isprint(c))
+		    error("unsupported char '%c'", c);
+		else
+		    error("unsupported char 0x%02x", c);
+		p++;
+		continue;
+	    }
+	}
+    }
+}
+
+/*******************************************
+ * Parse escape sequence.
+ */
+
+unsigned Lexer::escapeSequence()
+{   unsigned c = *p;
+
+#ifdef TEXTUAL_ASSEMBLY_OUT
+    return c;
+#endif
+    int n;
+    int ndigits;
+
+    switch (c)
+    {
+	case '\'':
+	case '"':
+	case '?':
+	case '\\':
+	Lconsume:
+		p++;
+		break;
+
+	case 'a':	c = 7;		goto Lconsume;
+	case 'b':	c = 8;		goto Lconsume;
+	case 'f':	c = 12;		goto Lconsume;
+	case 'n':	c = 10;		goto Lconsume;
+	case 'r':	c = 13;		goto Lconsume;
+	case 't':	c = 9;		goto Lconsume;
+	case 'v':	c = 11;		goto Lconsume;
+
+	case 'u':
+		ndigits = 4;
+		goto Lhex;
+	case 'U':
+		ndigits = 8;
+		goto Lhex;
+	case 'x':
+		ndigits = 2;
+	Lhex:
+		p++;
+		c = *p;
+		if (ishex(c))
+		{   unsigned v;
+
+		    n = 0;
+		    v = 0;
+		    while (1)
+		    {
+			if (isdigit(c))
+			    c -= '0';
+			else if (islower(c))
+			    c -= 'a' - 10;
+			else
+			    c -= 'A' - 10;
+			v = v * 16 + c;
+			c = *++p;
+			if (++n == ndigits)
+			    break;
+			if (!ishex(c))
+			{   error("escape hex sequence has %d hex digits instead of %d", n, ndigits);
+			    break;
+			}
+		    }
+		    if (ndigits != 2 && !utf_isValidDchar(v))
+			error("invalid UTF character \\U%08x", v);
+		    c = v;
+		}
+		else
+		    error("undefined escape hex sequence \\%c\n",c);
+		break;
+
+	case '&':			// named character entity
+		for (unsigned char *idstart = ++p; 1; p++)
+		{
+		    switch (*p)
+		    {
+			case ';':
+			    c = HtmlNamedEntity(idstart, p - idstart);
+			    if (c == ~0)
+			    {   error("unnamed character entity &%.*s;", (int)(p - idstart), idstart);
+				c = ' ';
+			    }
+			    p++;
+			    break;
+
+			default:
+			    if (isalpha(*p) ||
+				(p != idstart + 1 && isdigit(*p)))
+				continue;
+			    error("unterminated named entity");
+			    break;
+		    }
+		    break;
+		}
+		break;
+
+	case 0:
+	case 0x1A:			// end of file
+		c = '\\';
+		break;
+
+	default:
+		if (isoctal(c))
+		{   unsigned v;
+
+		    n = 0;
+		    v = 0;
+		    do
+		    {
+			v = v * 8 + (c - '0');
+			c = *++p;
+		    } while (++n < 3 && isoctal(c));
+		    c = v;
+		    if (c > 0xFF)
+			error("0%03o is larger than a byte", c);
+		}
+		else
+		    error("undefined escape sequence \\%c\n",c);
+		break;
+    }
+    return c;
+}
+
+/**************************************
+ */
+
+TOK Lexer::wysiwygStringConstant(Token *t, int tc)
+{   unsigned c;
+    Loc start = loc;
+
+    p++;
+    stringbuffer.reset();
+    while (1)
+    {
+	c = *p++;
+	switch (c)
+	{
+	    case '\n':
+		loc.linnum++;
+		break;
+
+	    case '\r':
+		if (*p == '\n')
+		    continue;	// ignore
+		c = '\n';	// treat EndOfLine as \n character
+		loc.linnum++;
+		break;
+
+	    case 0:
+	    case 0x1A:
+		error("unterminated string constant starting at %s", start.toChars());
+		t->ustring = (unsigned char *)"";
+		t->len = 0;
+		t->postfix = 0;
+		return TOKstring;
+
+	    case '"':
+	    case '`':
+		if (c == tc)
+		{
+		    t->len = stringbuffer.offset;
+		    stringbuffer.writeByte(0);
+		    t->ustring = (unsigned char *)mem.malloc(stringbuffer.offset);
+		    memcpy(t->ustring, stringbuffer.data, stringbuffer.offset);
+		    stringPostfix(t);
+		    return TOKstring;
+		}
+		break;
+
+	    default:
+		if (c & 0x80)
+		{   p--;
+		    unsigned u = decodeUTF();
+		    p++;
+		    if (u == PS || u == LS)
+			loc.linnum++;
+		    stringbuffer.writeUTF8(u);
+		    continue;
+		}
+		break;
+	}
+	stringbuffer.writeByte(c);
+    }
+}
+
+/**************************************
+ * Lex hex strings:
+ *	x"0A ae 34FE BD"
+ */
+
+TOK Lexer::hexStringConstant(Token *t)
+{   unsigned c;
+    Loc start = loc;
+    unsigned n = 0;
+    unsigned v;
+
+    p++;
+    stringbuffer.reset();
+    while (1)
+    {
+	c = *p++;
+	switch (c)
+	{
+	    case ' ':
+	    case '\t':
+	    case '\v':
+	    case '\f':
+		continue;			// skip white space
+
+	    case '\r':
+		if (*p == '\n')
+		    continue;			// ignore
+		// Treat isolated '\r' as if it were a '\n'
+	    case '\n':
+		loc.linnum++;
+		continue;
+
+	    case 0:
+	    case 0x1A:
+		error("unterminated string constant starting at %s", start.toChars());
+		t->ustring = (unsigned char *)"";
+		t->len = 0;
+		t->postfix = 0;
+		return TOKstring;
+
+	    case '"':
+		if (n & 1)
+		{   error("odd number (%d) of hex characters in hex string", n);
+		    stringbuffer.writeByte(v);
+		}
+		t->len = stringbuffer.offset;
+		stringbuffer.writeByte(0);
+		t->ustring = (unsigned char *)mem.malloc(stringbuffer.offset);
+		memcpy(t->ustring, stringbuffer.data, stringbuffer.offset);
+		stringPostfix(t);
+		return TOKstring;
+
+	    default:
+		if (c >= '0' && c <= '9')
+		    c -= '0';
+		else if (c >= 'a' && c <= 'f')
+		    c -= 'a' - 10;
+		else if (c >= 'A' && c <= 'F')
+		    c -= 'A' - 10;
+		else if (c & 0x80)
+		{   p--;
+		    unsigned u = decodeUTF();
+		    p++;
+		    if (u == PS || u == LS)
+			loc.linnum++;
+		    else
+			error("non-hex character \\u%x", u);
+		}
+		else
+		    error("non-hex character '%c'", c);
+		if (n & 1)
+		{   v = (v << 4) | c;
+		    stringbuffer.writeByte(v);
+		}
+		else
+		    v = c;
+		n++;
+		break;
+	}
+    }
+}
+
+
+#if DMDV2
+/**************************************
+ * Lex delimited strings:
+ *	q"(foo(xxx))"   // "foo(xxx)"
+ *	q"[foo(]"       // "foo("
+ *	q"/foo]/"       // "foo]"
+ *	q"HERE
+ *	foo
+ *	HERE"		// "foo\n"
+ * Input:
+ *	p is on the "
+ */
+
+TOK Lexer::delimitedStringConstant(Token *t)
+{   unsigned c;
+    Loc start = loc;
+    unsigned delimleft = 0;
+    unsigned delimright = 0;
+    unsigned nest = 1;
+    unsigned nestcount;
+    Identifier *hereid = NULL;
+    unsigned blankrol = 0;
+    unsigned startline = 0;
+
+    p++;
+    stringbuffer.reset();
+    while (1)
+    {
+	c = *p++;
+	//printf("c = '%c'\n", c);
+	switch (c)
+	{
+	    case '\n':
+	    Lnextline:
+		loc.linnum++;
+		startline = 1;
+		if (blankrol)
+		{   blankrol = 0;
+		    continue;
+		}
+		if (hereid)
+		{
+		    stringbuffer.writeUTF8(c);
+		    continue;
+		}
+		break;
+
+	    case '\r':
+		if (*p == '\n')
+		    continue;	// ignore
+		c = '\n';	// treat EndOfLine as \n character
+		goto Lnextline;
+
+	    case 0:
+	    case 0x1A:
+		goto Lerror;
+
+	    default:
+		if (c & 0x80)
+		{   p--;
+		    c = decodeUTF();
+		    p++;
+		    if (c == PS || c == LS)
+			goto Lnextline;
+		}
+		break;
+	}
+	if (delimleft == 0)
+	{   delimleft = c;
+	    nest = 1;
+	    nestcount = 1;
+	    if (c == '(')
+		delimright = ')';
+	    else if (c == '{')
+		delimright = '}';
+	    else if (c == '[')
+		delimright = ']';
+	    else if (c == '<')
+		delimright = '>';
+	    else if (isalpha(c) || c == '_' || (c >= 0x80 && isUniAlpha(c)))
+	    {	// Start of identifier; must be a heredoc
+		Token t;
+		p--;
+		scan(&t);		// read in heredoc identifier
+		if (t.value != TOKidentifier)
+		{   error("identifier expected for heredoc, not %s", t.toChars());
+		    delimright = c;
+		}
+		else
+		{   hereid = t.ident;
+		    //printf("hereid = '%s'\n", hereid->toChars());
+		    blankrol = 1;
+		}
+		nest = 0;
+	    }
+	    else
+	    {	delimright = c;
+		nest = 0;
+		if (isspace(c))
+		    error("delimiter cannot be whitespace");
+	    }
+	}
+	else
+	{
+	    if (blankrol)
+	    {	error("heredoc rest of line should be blank");
+		blankrol = 0;
+		continue;
+	    }
+	    if (nest == 1)
+	    {
+		if (c == delimleft)
+		    nestcount++;
+		else if (c == delimright)
+		{   nestcount--;
+		    if (nestcount == 0)
+			goto Ldone;
+		}
+	    }
+	    else if (c == delimright)
+		goto Ldone;
+	    if (startline && isalpha(c) && hereid)
+	    {	Token t;
+		unsigned char *psave = p;
+		p--;
+		scan(&t);		// read in possible heredoc identifier
+		//printf("endid = '%s'\n", t.ident->toChars());
+		if (t.value == TOKidentifier && t.ident->equals(hereid))
+		{   /* should check that rest of line is blank
+		     */
+		    goto Ldone;
+		}
+		p = psave;
+	    }
+	    stringbuffer.writeUTF8(c);
+	    startline = 0;
+	}
+    }
+
+Ldone:
+    if (*p == '"')
+	p++;
+    else
+	error("delimited string must end in %c\"", delimright);
+    t->len = stringbuffer.offset;
+    stringbuffer.writeByte(0);
+    t->ustring = (unsigned char *)mem.malloc(stringbuffer.offset);
+    memcpy(t->ustring, stringbuffer.data, stringbuffer.offset);
+    stringPostfix(t);
+    return TOKstring;
+
+Lerror:
+    error("unterminated string constant starting at %s", start.toChars());
+    t->ustring = (unsigned char *)"";
+    t->len = 0;
+    t->postfix = 0;
+    return TOKstring;
+}
+
+/**************************************
+ * Lex delimited strings:
+ *	q{ foo(xxx) } // " foo(xxx) "
+ *	q{foo(}       // "foo("
+ *	q{{foo}"}"}   // "{foo}"}""
+ * Input:
+ *	p is on the q
+ */
+
+TOK Lexer::tokenStringConstant(Token *t)
+{
+    unsigned nest = 1;
+    Loc start = loc;
+    unsigned char *pstart = ++p;
+
+    while (1)
+    {	Token tok;
+
+	scan(&tok);
+	switch (tok.value)
+	{
+	    case TOKlcurly:
+		nest++;
+		continue;
+
+	    case TOKrcurly:
+		if (--nest == 0)
+		    goto Ldone;
+		continue;
+
+	    case TOKeof:
+		goto Lerror;
+
+	    default:
+		continue;
+	}
+    }
+
+Ldone:
+    t->len = p - 1 - pstart;
+    t->ustring = (unsigned char *)mem.malloc(t->len + 1);
+    memcpy(t->ustring, pstart, t->len);
+    t->ustring[t->len] = 0;
+    stringPostfix(t);
+    return TOKstring;
+
+Lerror:
+    error("unterminated token string constant starting at %s", start.toChars());
+    t->ustring = (unsigned char *)"";
+    t->len = 0;
+    t->postfix = 0;
+    return TOKstring;
+}
+
+#endif
+
+
+/**************************************
+ */
+
+TOK Lexer::escapeStringConstant(Token *t, int wide)
+{   unsigned c;
+    Loc start = loc;
+
+    p++;
+    stringbuffer.reset();
+    while (1)
+    {
+	c = *p++;
+	switch (c)
+	{
+#if !( TEXTUAL_ASSEMBLY_OUT )
+	    case '\\':
+		switch (*p)
+		{
+		    case 'u':
+		    case 'U':
+		    case '&':
+			c = escapeSequence();
+			stringbuffer.writeUTF8(c);
+			continue;
+
+		    default:
+			c = escapeSequence();
+			break;
+		}
+		break;
+#endif
+	    case '\n':
+		loc.linnum++;
+		break;
+
+	    case '\r':
+		if (*p == '\n')
+		    continue;	// ignore
+		c = '\n';	// treat EndOfLine as \n character
+		loc.linnum++;
+		break;
+
+	    case '"':
+		t->len = stringbuffer.offset;
+		stringbuffer.writeByte(0);
+		t->ustring = (unsigned char *)mem.malloc(stringbuffer.offset);
+		memcpy(t->ustring, stringbuffer.data, stringbuffer.offset);
+		stringPostfix(t);
+		return TOKstring;
+
+	    case 0:
+	    case 0x1A:
+		p--;
+		error("unterminated string constant starting at %s", start.toChars());
+		t->ustring = (unsigned char *)"";
+		t->len = 0;
+		t->postfix = 0;
+		return TOKstring;
+
+	    default:
+		if (c & 0x80)
+		{
+		    p--;
+		    c = decodeUTF();
+		    if (c == LS || c == PS)
+		    {	c = '\n';
+			loc.linnum++;
+		    }
+		    p++;
+		    stringbuffer.writeUTF8(c);
+		    continue;
+		}
+		break;
+	}
+	stringbuffer.writeByte(c);
+    }
+}
+
+/**************************************
+ */
+
+TOK Lexer::charConstant(Token *t, int wide)
+{
+    unsigned c;
+    TOK tk = TOKcharv;
+
+    //printf("Lexer::charConstant\n");
+    p++;
+    c = *p++;
+    switch (c)
+    {
+#if ! TEXTUAL_ASSEMBLY_OUT
+	case '\\':
+	    switch (*p)
+	    {
+		case 'u':
+		    t->uns64value = escapeSequence();
+		    tk = TOKwcharv;
+		    break;
+
+		case 'U':
+		case '&':
+		    t->uns64value = escapeSequence();
+		    tk = TOKdcharv;
+		    break;
+
+		default:
+		    t->uns64value = escapeSequence();
+		    break;
+	    }
+	    break;
+#endif
+	case '\n':
+	L1:
+	    loc.linnum++;
+	case '\r':
+	case 0:
+	case 0x1A:
+	case '\'':
+	    error("unterminated character constant");
+	    return tk;
+
+	default:
+	    if (c & 0x80)
+	    {
+		p--;
+		c = decodeUTF();
+		p++;
+		if (c == LS || c == PS)
+		    goto L1;
+		if (c < 0xD800 || (c >= 0xE000 && c < 0xFFFE))
+		    tk = TOKwcharv;
+		else
+		    tk = TOKdcharv;
+	    }
+	    t->uns64value = c;
+	    break;
+    }
+
+    if (*p != '\'')
+    {	error("unterminated character constant");
+	return tk;
+    }
+    p++;
+    return tk;
+}
+
+/***************************************
+ * Get postfix of string literal.
+ */
+
+void Lexer::stringPostfix(Token *t)
+{
+    switch (*p)
+    {
+	case 'c':
+	case 'w':
+	case 'd':
+	    t->postfix = *p;
+	    p++;
+	    break;
+
+	default:
+	    t->postfix = 0;
+	    break;
+    }
+}
+
+/***************************************
+ * Read \u or \U unicode sequence
+ * Input:
+ *	u	'u' or 'U'
+ */
+
+#if 0
+unsigned Lexer::wchar(unsigned u)
+{
+    unsigned value;
+    unsigned n;
+    unsigned char c;
+    unsigned nchars;
+
+    nchars = (u == 'U') ? 8 : 4;
+    value = 0;
+    for (n = 0; 1; n++)
+    {
+	++p;
+	if (n == nchars)
+	    break;
+	c = *p;
+	if (!ishex(c))
+	{   error("\\%c sequence must be followed by %d hex characters", u, nchars);
+	    break;
+	}
+	if (isdigit(c))
+	    c -= '0';
+	else if (islower(c))
+	    c -= 'a' - 10;
+	else
+	    c -= 'A' - 10;
+	value <<= 4;
+	value |= c;
+    }
+    return value;
+}
+#endif
+
+/**************************************
+ * Read in a number.
+ * If it's an integer, store it in tok.TKutok.Vlong.
+ *	integers can be decimal, octal or hex
+ *	Handle the suffixes U, UL, LU, L, etc.
+ * If it's double, store it in tok.TKutok.Vdouble.
+ * Returns:
+ *	TKnum
+ *	TKdouble,...
+ */
+
+TOK Lexer::number(Token *t)
+{
+    // We use a state machine to collect numbers
+    enum STATE { STATE_initial, STATE_0, STATE_decimal, STATE_octal, STATE_octale,
+	STATE_hex, STATE_binary, STATE_hex0, STATE_binary0,
+	STATE_hexh, STATE_error };
+    enum STATE state;
+
+    enum FLAGS
+    {	FLAGS_decimal  = 1,		// decimal
+	FLAGS_unsigned = 2,		// u or U suffix
+	FLAGS_long     = 4,		// l or L suffix
+    };
+    enum FLAGS flags = FLAGS_decimal;
+
+    int i;
+    int base;
+    unsigned c;
+    unsigned char *start;
+    TOK result;
+
+    //printf("Lexer::number()\n");
+    state = STATE_initial;
+    base = 0;
+    stringbuffer.reset();
+    start = p;
+    while (1)
+    {
+	c = *p;
+	switch (state)
+	{
+	    case STATE_initial:		// opening state
+		if (c == '0')
+		    state = STATE_0;
+		else
+		    state = STATE_decimal;
+		break;
+
+	    case STATE_0:
+		flags = (FLAGS) (flags & ~FLAGS_decimal);
+		switch (c)
+		{
+#if ZEROH
+		    case 'H':			// 0h
+		    case 'h':
+			goto hexh;
+#endif
+		    case 'X':
+		    case 'x':
+			state = STATE_hex0;
+			break;
+
+		    case '.':
+			if (p[1] == '.')	// .. is a separate token
+			    goto done;
+		    case 'i':
+		    case 'f':
+		    case 'F':
+			goto real;
+#if ZEROH
+		    case 'E':
+		    case 'e':
+			goto case_hex;
+#endif
+		    case 'B':
+		    case 'b':
+			state = STATE_binary0;
+			break;
+
+		    case '0': case '1': case '2': case '3':
+		    case '4': case '5': case '6': case '7':
+			state = STATE_octal;
+			break;
+
+#if ZEROH
+		    case '8': case '9': case 'A':
+		    case 'C': case 'D': case 'F':
+		    case 'a': case 'c': case 'd': case 'f':
+		    case_hex:
+			state = STATE_hexh;
+			break;
+#endif
+		    case '_':
+			state = STATE_octal;
+			p++;
+			continue;
+
+		    case 'L':
+			if (p[1] == 'i')
+			    goto real;
+			goto done;
+
+		    default:
+			goto done;
+		}
+		break;
+
+	    case STATE_decimal:		// reading decimal number
+		if (!isdigit(c))
+		{
+#if ZEROH
+		    if (ishex(c)
+			|| c == 'H' || c == 'h'
+		       )
+			goto hexh;
+#endif
+		    if (c == '_')		// ignore embedded _
+		    {	p++;
+			continue;
+		    }
+		    if (c == '.' && p[1] != '.')
+			goto real;
+		    else if (c == 'i' || c == 'f' || c == 'F' ||
+			     c == 'e' || c == 'E')
+		    {
+	    real:	// It's a real number. Back up and rescan as a real
+			p = start;
+			return inreal(t);
+		    }
+		    else if (c == 'L' && p[1] == 'i')
+			goto real;
+		    goto done;
+		}
+		break;
+
+	    case STATE_hex0:		// reading hex number
+	    case STATE_hex:
+		if (!ishex(c))
+		{
+		    if (c == '_')		// ignore embedded _
+		    {	p++;
+			continue;
+		    }
+		    if (c == '.' && p[1] != '.')
+			goto real;
+		    if (c == 'P' || c == 'p' || c == 'i')
+			goto real;
+		    if (state == STATE_hex0)
+			error("Hex digit expected, not '%c'", c);
+		    goto done;
+		}
+		state = STATE_hex;
+		break;
+
+#if ZEROH
+	    hexh:
+		state = STATE_hexh;
+	    case STATE_hexh:		// parse numbers like 0FFh
+		if (!ishex(c))
+		{
+		    if (c == 'H' || c == 'h')
+		    {
+			p++;
+			base = 16;
+			goto done;
+		    }
+		    else
+		    {
+			// Check for something like 1E3 or 0E24
+			if (memchr((char *)stringbuffer.data, 'E', stringbuffer.offset) ||
+			    memchr((char *)stringbuffer.data, 'e', stringbuffer.offset))
+			    goto real;
+			error("Hex digit expected, not '%c'", c);
+			goto done;
+		    }
+		}
+		break;
+#endif
+
+	    case STATE_octal:		// reading octal number
+	    case STATE_octale:		// reading octal number with non-octal digits
+		if (!isoctal(c))
+		{
+#if ZEROH
+		    if (ishex(c)
+			|| c == 'H' || c == 'h'
+		       )
+			goto hexh;
+#endif
+		    if (c == '_')		// ignore embedded _
+		    {	p++;
+			continue;
+		    }
+		    if (c == '.' && p[1] != '.')
+			goto real;
+		    if (c == 'i')
+			goto real;
+		    if (isdigit(c))
+		    {
+			state = STATE_octale;
+		    }
+		    else
+			goto done;
+		}
+		break;
+
+	    case STATE_binary0:		// starting binary number
+	    case STATE_binary:		// reading binary number
+		if (c != '0' && c != '1')
+		{
+#if ZEROH
+		    if (ishex(c)
+			|| c == 'H' || c == 'h'
+		       )
+			goto hexh;
+#endif
+		    if (c == '_')		// ignore embedded _
+		    {	p++;
+			continue;
+		    }
+		    if (state == STATE_binary0)
+		    {	error("binary digit expected");
+			state = STATE_error;
+			break;
+		    }
+		    else
+			goto done;
+		}
+		state = STATE_binary;
+		break;
+
+	    case STATE_error:		// for error recovery
+		if (!isdigit(c))	// scan until non-digit
+		    goto done;
+		break;
+
+	    default:
+		assert(0);
+	}
+	stringbuffer.writeByte(c);
+	p++;
+    }
+done:
+    stringbuffer.writeByte(0);		// terminate string
+    if (state == STATE_octale)
+	error("Octal digit expected");
+
+    uinteger_t n;			// unsigned >=64 bit integer type
+
+    if (stringbuffer.offset == 2 && (state == STATE_decimal || state == STATE_0))
+	n = stringbuffer.data[0] - '0';
+    else
+    {
+	// Convert string to integer
+#if __DMC__
+	errno = 0;
+	n = strtoull((char *)stringbuffer.data,NULL,base);
+	if (errno == ERANGE)
+	    error("integer overflow");
+#else
+	// Not everybody implements strtoull()
+	char *p = (char *)stringbuffer.data;
+	int r = 10, d;
+
+	if (*p == '0')
+	{
+	    if (p[1] == 'x' || p[1] == 'X')
+		p += 2, r = 16;
+	    else if (p[1] == 'b' || p[1] == 'B')
+		p += 2, r = 2;
+	    else if (isdigit(p[1]))
+		p += 1, r = 8;
+	}
+
+	n = 0;
+	while (1)
+	{
+	    if (*p >= '0' && *p <= '9')
+		d = *p - '0';
+	    else if (*p >= 'a' && *p <= 'z')
+		d = *p - 'a' + 10;
+	    else if (*p >= 'A' && *p <= 'Z')
+		d = *p - 'A' + 10;
+	    else
+		break;
+	    if (d >= r)
+		break;
+	    uinteger_t n2 = n * r;
+	    //printf("n2 / r = %llx, n = %llx\n", n2/r, n);
+	    if (n2 / r != n || n2 + d < n)
+	    {
+		error ("integer overflow");
+		break;
+	    }
+
+	    n = n2 + d;
+	    p++;
+	}
+#endif
+	if (sizeof(n) > 8 &&
+	    n > 0xFFFFFFFFFFFFFFFFULL)	// if n needs more than 64 bits
+	    error("integer overflow");
+    }
+
+    // Parse trailing 'u', 'U', 'l' or 'L' in any combination
+    while (1)
+    {   unsigned char f;
+
+	switch (*p)
+	{   case 'U':
+	    case 'u':
+		f = FLAGS_unsigned;
+		goto L1;
+
+	    case 'l':
+		if (1 || !global.params.useDeprecated)
+		    error("'l' suffix is deprecated, use 'L' instead");
+	    case 'L':
+		f = FLAGS_long;
+	    L1:
+		p++;
+		if (flags & f)
+		    error("unrecognized token");
+		flags = (FLAGS) (flags | f);
+		continue;
+	    default:
+		break;
+	}
+	break;
+    }
+
+    switch (flags)
+    {
+	case 0:
+	    /* Octal or Hexadecimal constant.
+	     * First that fits: int, uint, long, ulong
+	     */
+	    if (n & 0x8000000000000000LL)
+		    result = TOKuns64v;
+	    else if (n & 0xFFFFFFFF00000000LL)
+		    result = TOKint64v;
+	    else if (n & 0x80000000)
+		    result = TOKuns32v;
+	    else
+		    result = TOKint32v;
+	    break;
+
+	case FLAGS_decimal:
+	    /* First that fits: int, long, long long
+	     */
+	    if (n & 0x8000000000000000LL)
+	    {	    error("signed integer overflow");
+		    result = TOKuns64v;
+	    }
+	    else if (n & 0xFFFFFFFF80000000LL)
+		    result = TOKint64v;
+	    else
+		    result = TOKint32v;
+	    break;
+
+	case FLAGS_unsigned:
+	case FLAGS_decimal | FLAGS_unsigned:
+	    /* First that fits: uint, ulong
+	     */
+	    if (n & 0xFFFFFFFF00000000LL)
+		    result = TOKuns64v;
+	    else
+		    result = TOKuns32v;
+	    break;
+
+	case FLAGS_decimal | FLAGS_long:
+	    if (n & 0x8000000000000000LL)
+	    {	    error("signed integer overflow");
+		    result = TOKuns64v;
+	    }
+	    else
+		    result = TOKint64v;
+	    break;
+
+	case FLAGS_long:
+	    if (n & 0x8000000000000000LL)
+		    result = TOKuns64v;
+	    else
+		    result = TOKint64v;
+	    break;
+
+	case FLAGS_unsigned | FLAGS_long:
+	case FLAGS_decimal | FLAGS_unsigned | FLAGS_long:
+	    result = TOKuns64v;
+	    break;
+
+	default:
+	    #ifdef DEBUG
+		printf("%x\n",flags);
+	    #endif
+	    assert(0);
+    }
+    t->uns64value = n;
+    return result;
+}
+
+/**************************************
+ * Read in characters, converting them to real.
+ * Bugs:
+ *	Exponent overflow not detected.
+ *	Too much requested precision is not detected.
+ */
+
+TOK Lexer::inreal(Token *t)
+#ifdef __DMC__
+__in
+{
+    assert(*p == '.' || isdigit(*p));
+}
+__out (result)
+{
+    switch (result)
+    {
+	case TOKfloat32v:
+	case TOKfloat64v:
+	case TOKfloat80v:
+	case TOKimaginary32v:
+	case TOKimaginary64v:
+	case TOKimaginary80v:
+	    break;
+
+	default:
+	    assert(0);
+    }
+}
+__body
+#endif /* __DMC__ */
+{   int dblstate;
+    unsigned c;
+    char hex;			// is this a hexadecimal-floating-constant?
+    TOK result;
+
+    //printf("Lexer::inreal()\n");
+    stringbuffer.reset();
+    dblstate = 0;
+    hex = 0;
+Lnext:
+    while (1)
+    {
+	// Get next char from input
+	c = *p++;
+	//printf("dblstate = %d, c = '%c'\n", dblstate, c);
+	while (1)
+	{
+	    switch (dblstate)
+	    {
+		case 0:			// opening state
+		    if (c == '0')
+			dblstate = 9;
+		    else if (c == '.')
+			dblstate = 3;
+		    else
+			dblstate = 1;
+		    break;
+
+		case 9:
+		    dblstate = 1;
+		    if (c == 'X' || c == 'x')
+		    {	hex++;
+			break;
+		    }
+		case 1:			// digits to left of .
+		case 3:			// digits to right of .
+		case 7:			// continuing exponent digits
+		    if (!isdigit(c) && !(hex && isxdigit(c)))
+		    {
+			if (c == '_')
+			    goto Lnext;	// ignore embedded '_'
+			dblstate++;
+			continue;
+		    }
+		    break;
+
+		case 2:			// no more digits to left of .
+		    if (c == '.')
+		    {   dblstate++;
+			break;
+		    }
+		case 4:			// no more digits to right of .
+		    if ((c == 'E' || c == 'e') ||
+			hex && (c == 'P' || c == 'p'))
+		    {   dblstate = 5;
+			hex = 0;	// exponent is always decimal
+			break;
+		    }
+		    if (hex)
+			error("binary-exponent-part required");
+		    goto done;
+
+		case 5:			// looking immediately to right of E
+		    dblstate++;
+		    if (c == '-' || c == '+')
+			break;
+		case 6:			// 1st exponent digit expected
+		    if (!isdigit(c))
+			error("exponent expected");
+		    dblstate++;
+		    break;
+
+		case 8:			// past end of exponent digits
+		    goto done;
+	    }
+	    break;
+	}
+	stringbuffer.writeByte(c);
+    }
+done:
+    p--;
+
+    stringbuffer.writeByte(0);
+
+#if _WIN32 && __DMC__
+    char *save = __locale_decpoint;
+    __locale_decpoint = ".";
+#endif
+#ifdef IN_GCC
+    t->float80value = real_t::parse((char *)stringbuffer.data, real_t::LongDouble);
+#else
+    t->float80value = strtold((char *)stringbuffer.data, NULL);
+#endif
+    errno = 0;
+    float strtofres;
+    double strtodres;
+    switch (*p)
+    {
+	case 'F':
+	case 'f':
+#ifdef IN_GCC
+	    real_t::parse((char *)stringbuffer.data, real_t::Float);
+#else
+	    strtofres = strtof((char *)stringbuffer.data, NULL);
+	    // LDC change: don't error on gradual underflow
+	    if (errno == ERANGE && 
+		    strtofres != 0 && strtofres != HUGE_VALF && strtofres != -HUGE_VALF)
+		errno = 0;
+#endif
+	    result = TOKfloat32v;
+	    p++;
+	    break;
+
+	default:
+#ifdef IN_GCC
+	    real_t::parse((char *)stringbuffer.data, real_t::Double);
+#else	    
+	    strtodres = strtod((char *)stringbuffer.data, NULL);
+	    // LDC change: don't error on gradual underflow
+	    if (errno == ERANGE && 
+		    strtodres != 0 && strtodres != HUGE_VAL && strtodres != -HUGE_VAL)
+		errno = 0;
+#endif
+	    result = TOKfloat64v;
+	    break;
+
+	case 'l':
+	    if (!global.params.useDeprecated)
+		error("'l' suffix is deprecated, use 'L' instead");
+	case 'L':
+	    result = TOKfloat80v;
+	    p++;
+	    break;
+    }
+    if (*p == 'i' || *p == 'I')
+    {
+	if (!global.params.useDeprecated && *p == 'I')
+	    error("'I' suffix is deprecated, use 'i' instead");
+	p++;
+	switch (result)
+	{
+	    case TOKfloat32v:
+		result = TOKimaginary32v;
+		break;
+	    case TOKfloat64v:
+		result = TOKimaginary64v;
+		break;
+	    case TOKfloat80v:
+		result = TOKimaginary80v;
+		break;
+	}
+    }
+#if _WIN32 && __DMC__
+    __locale_decpoint = save;
+#endif
+    if (errno == ERANGE)
+	error("number is not representable");
+    return result;
+}
+
+/*********************************************
+ * Do pragma.
+ * Currently, the only pragma supported is:
+ *	#line linnum [filespec]
+ */
+
+void Lexer::pragma()
+{
+    Token tok;
+    int linnum;
+    char *filespec = NULL;
+    Loc loc = this->loc;
+
+    scan(&tok);
+    if (tok.value != TOKidentifier || tok.ident != Id::line)
+	goto Lerr;
+
+    scan(&tok);
+    if (tok.value == TOKint32v || tok.value == TOKint64v)
+	linnum = tok.uns64value - 1;
+    else
+	goto Lerr;
+
+    while (1)
+    {
+	switch (*p)
+	{
+	    case 0:
+	    case 0x1A:
+	    case '\n':
+	    Lnewline:
+		this->loc.linnum = linnum;
+		if (filespec)
+		    this->loc.filename = filespec;
+		return;
+
+	    case '\r':
+		p++;
+		if (*p != '\n')
+		{   p--;
+		    goto Lnewline;
+		}
+		continue;
+
+	    case ' ':
+	    case '\t':
+	    case '\v':
+	    case '\f':
+		p++;
+		continue;			// skip white space
+
+	    case '_':
+		if (mod && memcmp(p, "__FILE__", 8) == 0)
+		{
+		    p += 8;
+		    filespec = mem.strdup(loc.filename ? loc.filename : mod->ident->toChars());
+		}
+		continue;
+
+	    case '"':
+		if (filespec)
+		    goto Lerr;
+		stringbuffer.reset();
+		p++;
+		while (1)
+		{   unsigned c;
+
+		    c = *p;
+		    switch (c)
+		    {
+			case '\n':
+			case '\r':
+			case 0:
+			case 0x1A:
+			    goto Lerr;
+
+			case '"':
+			    stringbuffer.writeByte(0);
+			    filespec = mem.strdup((char *)stringbuffer.data);
+			    p++;
+			    break;
+
+			default:
+			    if (c & 0x80)
+			    {   unsigned u = decodeUTF();
+				if (u == PS || u == LS)
+				    goto Lerr;
+			    }
+			    stringbuffer.writeByte(c);
+			    p++;
+			    continue;
+		    }
+		    break;
+		}
+		continue;
+
+	    default:
+		if (*p & 0x80)
+		{   unsigned u = decodeUTF();
+		    if (u == PS || u == LS)
+			goto Lnewline;
+		}
+		goto Lerr;
+	}
+    }
+
+Lerr:
+    error(loc, "#line integer [\"filespec\"]\\n expected");
+}
+
+
+/********************************************
+ * Decode UTF character.
+ * Issue error messages for invalid sequences.
+ * Return decoded character, advance p to last character in UTF sequence.
+ */
+
+unsigned Lexer::decodeUTF()
+{
+    dchar_t u;
+    unsigned char c;
+    unsigned char *s = p;
+    size_t len;
+    size_t idx;
+    const char *msg;
+
+    c = *s;
+    assert(c & 0x80);
+
+    // Check length of remaining string up to 6 UTF-8 characters
+    for (len = 1; len < 6 && s[len]; len++)
+	;
+
+    idx = 0;
+    msg = utf_decodeChar(s, len, &idx, &u);
+    p += idx - 1;
+    if (msg)
+    {
+	error("%s", msg);
+    }
+    return u;
+}
+
+
+/***************************************************
+ * Parse doc comment embedded between t->ptr and p.
+ * Remove trailing blanks and tabs from lines.
+ * Replace all newlines with \n.
+ * Remove leading comment character from each line.
+ * Decide if it's a lineComment or a blockComment.
+ * Append to previous one for this token.
+ */
+
+void Lexer::getDocComment(Token *t, unsigned lineComment)
+{
+    /* ct tells us which kind of comment it is: '/', '*', or '+'
+     */
+    unsigned char ct = t->ptr[2];
+
+    /* Start of comment text skips over / * *, / + +, or / / /
+     */
+    unsigned char *q = t->ptr + 3;	// start of comment text
+
+    unsigned char *qend = p;
+    if (ct == '*' || ct == '+')
+	qend -= 2;
+
+    /* Scan over initial row of ****'s or ++++'s or ////'s
+     */
+    for (; q < qend; q++)
+    {
+	if (*q != ct)
+	    break;
+    }
+
+    /* Remove trailing row of ****'s or ++++'s
+     */
+    if (ct != '/')
+    {
+	for (; q < qend; qend--)
+	{
+	    if (qend[-1] != ct)
+		break;
+	}
+    }
+
+    /* Comment is now [q .. qend].
+     * Canonicalize it into buf[].
+     */
+    OutBuffer buf;
+    int linestart = 0;
+
+    for (; q < qend; q++)
+    {
+	unsigned char c = *q;
+
+	switch (c)
+	{
+	    case '*':
+	    case '+':
+		if (linestart && c == ct)
+		{   linestart = 0;
+		    /* Trim preceding whitespace up to preceding \n
+		     */
+		    while (buf.offset && (buf.data[buf.offset - 1] == ' ' || buf.data[buf.offset - 1] == '\t'))
+			buf.offset--;
+		    continue;
+		}
+		break;
+
+	    case ' ':
+	    case '\t':
+		break;
+
+	    case '\r':
+		if (q[1] == '\n')
+		    continue;		// skip the \r
+		goto Lnewline;
+
+	    default:
+		if (c == 226)
+		{
+		    // If LS or PS
+		    if (q[1] == 128 &&
+			(q[2] == 168 || q[2] == 169))
+		    {
+			q += 2;
+			goto Lnewline;
+		    }
+		}
+		linestart = 0;
+		break;
+
+	    Lnewline:
+		c = '\n';		// replace all newlines with \n
+	    case '\n':
+		linestart = 1;
+
+		/* Trim trailing whitespace
+		 */
+		while (buf.offset && (buf.data[buf.offset - 1] == ' ' || buf.data[buf.offset - 1] == '\t'))
+		    buf.offset--;
+
+		break;
+	}
+	buf.writeByte(c);
+    }
+
+    // Always end with a newline
+    if (!buf.offset || buf.data[buf.offset - 1] != '\n')
+	buf.writeByte('\n');
+
+    buf.writeByte(0);
+
+    // It's a line comment if the start of the doc comment comes
+    // after other non-whitespace on the same line.
+    unsigned char** dc = (lineComment && anyToken)
+			 ? &t->lineComment
+			 : &t->blockComment;
+
+    // Combine with previous doc comment, if any
+    if (*dc)
+	*dc = combineComments(*dc, (unsigned char *)buf.data);
+    else
+	*dc = (unsigned char *)buf.extractData();
+}
+
+/********************************************
+ * Combine two document comments into one,
+ * separated by a newline.
+ */
+
+unsigned char *Lexer::combineComments(unsigned char *c1, unsigned char *c2)
+{
+    //printf("Lexer::combineComments('%s', '%s')\n", c1, c2);
+
+    unsigned char *c = c2;
+
+    if (c1)
+    {	c = c1;
+	if (c2)
+	{   size_t len1 = strlen((char *)c1);
+	    size_t len2 = strlen((char *)c2);
+
+	    c = (unsigned char *)mem.malloc(len1 + 1 + len2 + 1);
+	    memcpy(c, c1, len1);
+	    if (len1 && c1[len1 - 1] != '\n')
+	    {	c[len1] = '\n';
+		len1++;
+	    }
+	    memcpy(c + len1, c2, len2);
+	    c[len1 + len2] = 0;
+	}
+    }
+    return c;
+}
+
+/********************************************
+ * Create an identifier in the string table.
+ */
+
+Identifier *Lexer::idPool(const char *s)
+{
+    size_t len = strlen(s);
+    StringValue *sv = stringtable.update(s, len);
+    Identifier *id = (Identifier *) sv->ptrvalue;
+    if (!id)
+    {
+	id = new Identifier(sv->lstring.string, TOKidentifier);
+	sv->ptrvalue = id;
+    }
+    return id;
+}
+
+/*********************************************
+ * Create a unique identifier using the prefix s.
+ */
+
+Identifier *Lexer::uniqueId(const char *s, int num)
+{   char buffer[32];
+    size_t slen = strlen(s);
+
+    assert(slen + sizeof(num) * 3 + 1 <= sizeof(buffer));
+    sprintf(buffer, "%s%d", s, num);
+    return idPool(buffer);
+}
+
+Identifier *Lexer::uniqueId(const char *s)
+{
+    static int num;
+    return uniqueId(s, ++num);
+}
+
+/****************************************
+ */
+
+struct Keyword
+{   const char *name;
+    enum TOK value;
+};
+
+static Keyword keywords[] =
+{
+//    {	"",		TOK	},
+
+    {	"this",		TOKthis		},
+    {	"super",	TOKsuper	},
+    {	"assert",	TOKassert	},
+    {	"null",		TOKnull		},
+    {	"true",		TOKtrue		},
+    {	"false",	TOKfalse	},
+    {	"cast",		TOKcast		},
+    {	"new",		TOKnew		},
+    {	"delete",	TOKdelete	},
+    {	"throw",	TOKthrow	},
+    {	"module",	TOKmodule	},
+    {	"pragma",	TOKpragma	},
+    {	"typeof",	TOKtypeof	},
+    {	"typeid",	TOKtypeid	},
+
+    {	"template",	TOKtemplate	},
+
+    {	"void",		TOKvoid		},
+    {	"byte",		TOKint8		},
+    {	"ubyte",	TOKuns8		},
+    {	"short",	TOKint16	},
+    {	"ushort",	TOKuns16	},
+    {	"int",		TOKint32	},
+    {	"uint",		TOKuns32	},
+    {	"long",		TOKint64	},
+    {	"ulong",	TOKuns64	},
+    {	"cent",		TOKcent,	},
+    {	"ucent",	TOKucent,	},
+    {	"float",	TOKfloat32	},
+    {	"double",	TOKfloat64	},
+    {	"real",		TOKfloat80	},
+
+    {	"bool",		TOKbool		},
+    {	"char",		TOKchar		},
+    {	"wchar",	TOKwchar	},
+    {	"dchar",	TOKdchar	},
+
+    {	"ifloat",	TOKimaginary32	},
+    {	"idouble",	TOKimaginary64	},
+    {	"ireal",	TOKimaginary80	},
+
+    {	"cfloat",	TOKcomplex32	},
+    {	"cdouble",	TOKcomplex64	},
+    {	"creal",	TOKcomplex80	},
+
+    {	"delegate",	TOKdelegate	},
+    {	"function",	TOKfunction	},
+
+    {	"is",		TOKis		},
+    {	"if",		TOKif		},
+    {	"else",		TOKelse		},
+    {	"while",	TOKwhile	},
+    {	"for",		TOKfor		},
+    {	"do",		TOKdo		},
+    {	"switch",	TOKswitch	},
+    {	"case",		TOKcase		},
+    {	"default",	TOKdefault	},
+    {	"break",	TOKbreak	},
+    {	"continue",	TOKcontinue	},
+    {	"synchronized",	TOKsynchronized	},
+    {	"return",	TOKreturn	},
+    {	"goto",		TOKgoto		},
+    {	"try",		TOKtry		},
+    {	"catch",	TOKcatch	},
+    {	"finally",	TOKfinally	},
+    {	"with",		TOKwith		},
+    {	"asm",		TOKasm		},
+    {	"foreach",	TOKforeach	},
+    {	"foreach_reverse",	TOKforeach_reverse	},
+    {	"scope",	TOKscope	},
+
+    {	"struct",	TOKstruct	},
+    {	"class",	TOKclass	},
+    {	"interface",	TOKinterface	},
+    {	"union",	TOKunion	},
+    {	"enum",		TOKenum		},
+    {	"import",	TOKimport	},
+    {	"mixin",	TOKmixin	},
+    {	"static",	TOKstatic	},
+    {	"final",	TOKfinal	},
+    {	"const",	TOKconst	},
+    {	"typedef",	TOKtypedef	},
+    {	"alias",	TOKalias	},
+    {	"override",	TOKoverride	},
+    {	"abstract",	TOKabstract	},
+    {	"volatile",	TOKvolatile	},
+    {	"debug",	TOKdebug	},
+    {	"deprecated",	TOKdeprecated	},
+    {	"in",		TOKin		},
+    {	"out",		TOKout		},
+    {	"inout",	TOKinout	},
+    {	"lazy",		TOKlazy		},
+    {	"auto",		TOKauto		},
+
+    {	"align",	TOKalign	},
+    {	"extern",	TOKextern	},
+    {	"private",	TOKprivate	},
+    {	"package",	TOKpackage	},
+    {	"protected",	TOKprotected	},
+    {	"public",	TOKpublic	},
+    {	"export",	TOKexport	},
+
+    {	"body",		TOKbody		},
+    {	"invariant",	TOKinvariant	},
+    {	"unittest",	TOKunittest	},
+    {	"version",	TOKversion	},
+    //{	"manifest",	TOKmanifest	},
+
+    // Added after 1.0
+    {	"ref",		TOKref		},
+    {	"macro",	TOKmacro	},
+#if DMDV2
+    {	"pure",		TOKpure		},
+    {	"nothrow",	TOKnothrow	},
+    {	"__thread",	TOKtls		},
+    {	"__gshared",	TOKgshared	},
+    {	"__traits",	TOKtraits	},
+    {	"__overloadset", TOKoverloadset	},
+    {	"__FILE__",	TOKfile		},
+    {	"__LINE__",	TOKline		},
+    {	"shared",	TOKshared	},
+    {	"immutable",	TOKimmutable	},
+#endif
+};
+
+int Token::isKeyword()
+{
+    for (unsigned u = 0; u < sizeof(keywords) / sizeof(keywords[0]); u++)
+    {
+	if (keywords[u].value == value)
+	    return 1;
+    }
+    return 0;
+}
+
+void Lexer::initKeywords()
+{   StringValue *sv;
+    unsigned u;
+    enum TOK v;
+    unsigned nkeywords = sizeof(keywords) / sizeof(keywords[0]);
+
+    if (global.params.Dversion == 1)
+	nkeywords -= 2;
+
+    cmtable_init();
+
+    for (u = 0; u < nkeywords; u++)
+    {	const char *s;
+
+	//printf("keyword[%d] = '%s'\n",u, keywords[u].name);
+	s = keywords[u].name;
+	v = keywords[u].value;
+	sv = stringtable.insert(s, strlen(s));
+	sv->ptrvalue = (void *) new Identifier(sv->lstring.string,v);
+
+	//printf("tochars[%d] = '%s'\n",v, s);
+	Token::tochars[v] = s;
+    }
+
+    Token::tochars[TOKeof]		= "EOF";
+    Token::tochars[TOKlcurly]		= "{";
+    Token::tochars[TOKrcurly]		= "}";
+    Token::tochars[TOKlparen]		= "(";
+    Token::tochars[TOKrparen]		= ")";
+    Token::tochars[TOKlbracket]		= "[";
+    Token::tochars[TOKrbracket]		= "]";
+    Token::tochars[TOKsemicolon]	= ";";
+    Token::tochars[TOKcolon]		= ":";
+    Token::tochars[TOKcomma]		= ",";
+    Token::tochars[TOKdot]		= ".";
+    Token::tochars[TOKxor]		= "^";
+    Token::tochars[TOKxorass]		= "^=";
+    Token::tochars[TOKassign]		= "=";
+    Token::tochars[TOKconstruct]	= "=";
+#if DMDV2
+    Token::tochars[TOKblit]		= "=";
+#endif
+    Token::tochars[TOKlt]		= "<";
+    Token::tochars[TOKgt]		= ">";
+    Token::tochars[TOKle]		= "<=";
+    Token::tochars[TOKge]		= ">=";
+    Token::tochars[TOKequal]		= "==";
+    Token::tochars[TOKnotequal]		= "!=";
+    Token::tochars[TOKnotidentity]	= "!is";
+    Token::tochars[TOKtobool]		= "!!";
+
+    Token::tochars[TOKunord]		= "!<>=";
+    Token::tochars[TOKue]		= "!<>";
+    Token::tochars[TOKlg]		= "<>";
+    Token::tochars[TOKleg]		= "<>=";
+    Token::tochars[TOKule]		= "!>";
+    Token::tochars[TOKul]		= "!>=";
+    Token::tochars[TOKuge]		= "!<";
+    Token::tochars[TOKug]		= "!<=";
+
+    Token::tochars[TOKnot]		= "!";
+    Token::tochars[TOKtobool]		= "!!";
+    Token::tochars[TOKshl]		= "<<";
+    Token::tochars[TOKshr]		= ">>";
+    Token::tochars[TOKushr]		= ">>>";
+    Token::tochars[TOKadd]		= "+";
+    Token::tochars[TOKmin]		= "-";
+    Token::tochars[TOKmul]		= "*";
+    Token::tochars[TOKdiv]		= "/";
+    Token::tochars[TOKmod]		= "%";
+    Token::tochars[TOKslice]		= "..";
+    Token::tochars[TOKdotdotdot]	= "...";
+    Token::tochars[TOKand]		= "&";
+    Token::tochars[TOKandand]		= "&&";
+    Token::tochars[TOKor]		= "|";
+    Token::tochars[TOKoror]		= "||";
+    Token::tochars[TOKarray]		= "[]";
+    Token::tochars[TOKindex]		= "[i]";
+    Token::tochars[TOKaddress]		= "&";
+    Token::tochars[TOKstar]		= "*";
+    Token::tochars[TOKtilde]		= "~";
+    Token::tochars[TOKdollar]		= "$";
+    Token::tochars[TOKcast]		= "cast";
+    Token::tochars[TOKplusplus]		= "++";
+    Token::tochars[TOKminusminus]	= "--";
+    Token::tochars[TOKtype]		= "type";
+    Token::tochars[TOKquestion]		= "?";
+    Token::tochars[TOKneg]		= "-";
+    Token::tochars[TOKuadd]		= "+";
+    Token::tochars[TOKvar]		= "var";
+    Token::tochars[TOKaddass]		= "+=";
+    Token::tochars[TOKminass]		= "-=";
+    Token::tochars[TOKmulass]		= "*=";
+    Token::tochars[TOKdivass]		= "/=";
+    Token::tochars[TOKmodass]		= "%=";
+    Token::tochars[TOKshlass]		= "<<=";
+    Token::tochars[TOKshrass]		= ">>=";
+    Token::tochars[TOKushrass]		= ">>>=";
+    Token::tochars[TOKandass]		= "&=";
+    Token::tochars[TOKorass]		= "|=";
+    Token::tochars[TOKcatass]		= "~=";
+    Token::tochars[TOKcat]		= "~";
+    Token::tochars[TOKcall]		= "call";
+    Token::tochars[TOKidentity]		= "is";
+    Token::tochars[TOKnotidentity]	= "!is";
+
+    Token::tochars[TOKorass]		= "|=";
+    Token::tochars[TOKidentifier]	= "identifier";
+
+     // For debugging
+    Token::tochars[TOKdotexp]		= "dotexp";
+    Token::tochars[TOKdotti]		= "dotti";
+    Token::tochars[TOKdotvar]		= "dotvar";
+    Token::tochars[TOKdottype]		= "dottype";
+    Token::tochars[TOKsymoff]		= "symoff";
+    Token::tochars[TOKarraylength]	= "arraylength";
+    Token::tochars[TOKarrayliteral]	= "arrayliteral";
+    Token::tochars[TOKassocarrayliteral] = "assocarrayliteral";
+    Token::tochars[TOKstructliteral]	= "structliteral";
+    Token::tochars[TOKstring]		= "string";
+    Token::tochars[TOKdsymbol]		= "symbol";
+    Token::tochars[TOKtuple]		= "tuple";
+    Token::tochars[TOKdeclaration]	= "declaration";
+    Token::tochars[TOKdottd]		= "dottd";
+    Token::tochars[TOKon_scope_exit]	= "scope(exit)";
+    Token::tochars[TOKon_scope_success]	= "scope(success)";
+    Token::tochars[TOKon_scope_failure]	= "scope(failure)";
+}
--- a/dmd2/lexer.h	Mon Jun 01 01:28:18 2009 +0200
+++ b/dmd2/lexer.h	Mon Jun 01 19:02:20 2009 +0100
@@ -1,307 +1,309 @@
-
-// Compiler implementation of the D programming language
-// Copyright (c) 1999-2008 by Digital Mars
-// All Rights Reserved
-// written by Walter Bright
-// http://www.digitalmars.com
-// License for redistribution is by either the Artistic License
-// in artistic.txt, or the GNU General Public License in gnu.txt.
-// See the included readme.txt for details.
-
-#ifndef DMD_LEXER_H
-#define DMD_LEXER_H
-
-#ifdef __DMC__
-#pragma once
-#endif /* __DMC__ */
-
-#include "root.h"
-#include "mars.h"
-
-struct StringTable;
-struct Identifier;
-struct Module;
-
-/* Tokens:
-	(	)
-	[	]
-	{	}
-	<	>	<=	>=	==	!=	===	!==
-	<<	>>	<<=	>>=	>>>	>>>=
-	+	-	+=	-=
-	*	/	%	*=	/=	%=
-	&	| 	^	&=	|=	^=
-	=	!	~
-	++	--
-	.	->	:	,
-	?	&&	||
- */
-
-enum TOK
-{
-	TOKreserved,
-
-	// Other
-	TOKlparen,	TOKrparen,
-	TOKlbracket,	TOKrbracket,
-	TOKlcurly,	TOKrcurly,
-	TOKcolon,	TOKneg,
-	TOKsemicolon,	TOKdotdotdot,
-	TOKeof,		TOKcast,
-	TOKnull,	TOKassert,
-	TOKtrue,	TOKfalse,
-	TOKarray,	TOKcall,
-	TOKaddress,	TOKtypedot,
-	TOKtype,	TOKthrow,
-	TOKnew,		TOKdelete,
-	TOKstar,	TOKsymoff,
-	TOKvar,		TOKdotvar,
-	TOKdotti,	TOKdotexp,
-	TOKdottype,	TOKslice,
-	TOKarraylength,	TOKversion,
-	TOKmodule,	TOKdollar,
-	TOKtemplate,	TOKdottd,
-	TOKdeclaration,	TOKtypeof,
-	TOKpragma,	TOKdsymbol,
-	TOKtypeid,	TOKuadd,
-	TOKremove,
-	TOKnewanonclass, TOKcomment,
-	TOKarrayliteral, TOKassocarrayliteral,
-	TOKstructliteral,
-
-	// Operators
-	TOKlt,		TOKgt,
-	TOKle,		TOKge,
-	TOKequal,	TOKnotequal,
-	TOKidentity,	TOKnotidentity,
-	TOKindex,	TOKis,
-	TOKtobool,
-
-// 60
-	// NCEG floating point compares
-	// !<>=     <>    <>=    !>     !>=   !<     !<=   !<>
-	TOKunord,TOKlg,TOKleg,TOKule,TOKul,TOKuge,TOKug,TOKue,
-
-	TOKshl,		TOKshr,
-	TOKshlass,	TOKshrass,
-	TOKushr,	TOKushrass,
-	TOKcat,		TOKcatass,	// ~ ~=
-	TOKadd,		TOKmin,		TOKaddass,	TOKminass,
-	TOKmul,		TOKdiv,		TOKmod,
-	TOKmulass,	TOKdivass,	TOKmodass,
-	TOKand,		TOKor,		TOKxor,
-	TOKandass,	TOKorass,	TOKxorass,
-	TOKassign,	TOKnot,		TOKtilde,
-	TOKplusplus,	TOKminusminus,	TOKconstruct,	TOKblit,
-	TOKdot,		TOKarrow,	TOKcomma,
-	TOKquestion,	TOKandand,	TOKoror,
-
-// 104
-	// Numeric literals
-	TOKint32v, TOKuns32v,
-	TOKint64v, TOKuns64v,
-	TOKfloat32v, TOKfloat64v, TOKfloat80v,
-	TOKimaginary32v, TOKimaginary64v, TOKimaginary80v,
-
-	// Char constants
-	TOKcharv, TOKwcharv, TOKdcharv,
-
-	// Leaf operators
-	TOKidentifier,	TOKstring,
-	TOKthis,	TOKsuper,
-	TOKhalt,	TOKtuple,
-
-	// Basic types
-	TOKvoid,
-	TOKint8, TOKuns8,
-	TOKint16, TOKuns16,
-	TOKint32, TOKuns32,
-	TOKint64, TOKuns64,
-	TOKfloat32, TOKfloat64, TOKfloat80,
-	TOKimaginary32, TOKimaginary64, TOKimaginary80,
-	TOKcomplex32, TOKcomplex64, TOKcomplex80,
-	TOKchar, TOKwchar, TOKdchar, TOKbit, TOKbool,
-	TOKcent, TOKucent,
-
-	// Aggregates
-	TOKstruct, TOKclass, TOKinterface, TOKunion, TOKenum, TOKimport,
-	TOKtypedef, TOKalias, TOKoverride, TOKdelegate, TOKfunction,
-	TOKmixin,
-
-	TOKalign, TOKextern, TOKprivate, TOKprotected, TOKpublic, TOKexport,
-	TOKstatic, /*TOKvirtual,*/ TOKfinal, TOKconst, TOKabstract, TOKvolatile,
-	TOKdebug, TOKdeprecated, TOKin, TOKout, TOKinout, TOKlazy,
-	TOKauto, TOKpackage, TOKmanifest, TOKimmutable,
-
-	// Statements
-	TOKif, TOKelse, TOKwhile, TOKfor, TOKdo, TOKswitch,
-	TOKcase, TOKdefault, TOKbreak, TOKcontinue, TOKwith,
-	TOKsynchronized, TOKreturn, TOKgoto, TOKtry, TOKcatch, TOKfinally,
-	TOKasm, TOKforeach, TOKforeach_reverse,
-	TOKscope,
-	TOKon_scope_exit, TOKon_scope_failure, TOKon_scope_success,
-
-	// Contracts
-	TOKbody, TOKinvariant,
-
-	// Testing
-	TOKunittest,
-
-	// Added after 1.0
-	TOKref,
-	TOKmacro,
-#if DMDV2
-	TOKtraits,
-	TOKoverloadset,
-	TOKpure,
-	TOKnothrow,
-	TOKtls,
-	TOKline,
-	TOKfile,
-    TOKshared,
-#endif
-
-// LDC specific
-#if IN_LLVM
-    TOKgep,
-#endif
-
-	TOKMAX
-};
-
-#define CASE_BASIC_TYPES			\
-	case TOKwchar: case TOKdchar:		\
-	case TOKbit: case TOKbool: case TOKchar:	\
-	case TOKint8: case TOKuns8:		\
-	case TOKint16: case TOKuns16:		\
-	case TOKint32: case TOKuns32:		\
-	case TOKint64: case TOKuns64:		\
-	case TOKfloat32: case TOKfloat64: case TOKfloat80:		\
-	case TOKimaginary32: case TOKimaginary64: case TOKimaginary80:	\
-	case TOKcomplex32: case TOKcomplex64: case TOKcomplex80:	\
-	case TOKvoid
-
-#define CASE_BASIC_TYPES_X(t)					\
-	case TOKvoid:	 t = Type::tvoid;  goto LabelX;		\
-	case TOKint8:	 t = Type::tint8;  goto LabelX;		\
-	case TOKuns8:	 t = Type::tuns8;  goto LabelX;		\
-	case TOKint16:	 t = Type::tint16; goto LabelX;		\
-	case TOKuns16:	 t = Type::tuns16; goto LabelX;		\
-	case TOKint32:	 t = Type::tint32; goto LabelX;		\
-	case TOKuns32:	 t = Type::tuns32; goto LabelX;		\
-	case TOKint64:	 t = Type::tint64; goto LabelX;		\
-	case TOKuns64:	 t = Type::tuns64; goto LabelX;		\
-	case TOKfloat32: t = Type::tfloat32; goto LabelX;	\
-	case TOKfloat64: t = Type::tfloat64; goto LabelX;	\
-	case TOKfloat80: t = Type::tfloat80; goto LabelX;	\
-	case TOKimaginary32: t = Type::timaginary32; goto LabelX;	\
-	case TOKimaginary64: t = Type::timaginary64; goto LabelX;	\
-	case TOKimaginary80: t = Type::timaginary80; goto LabelX;	\
-	case TOKcomplex32: t = Type::tcomplex32; goto LabelX;	\
-	case TOKcomplex64: t = Type::tcomplex64; goto LabelX;	\
-	case TOKcomplex80: t = Type::tcomplex80; goto LabelX;	\
-	case TOKbit:	 t = Type::tbit;     goto LabelX;	\
-	case TOKbool:	 t = Type::tbool;    goto LabelX;	\
-	case TOKchar:	 t = Type::tchar;    goto LabelX;	\
-	case TOKwchar:	 t = Type::twchar; goto LabelX;	\
-	case TOKdchar:	 t = Type::tdchar; goto LabelX;	\
-	LabelX
-
-struct Token
-{
-    Token *next;
-    unsigned char *ptr;		// pointer to first character of this token within buffer
-    enum TOK value;
-    unsigned char *blockComment; // doc comment string prior to this token
-    unsigned char *lineComment;	 // doc comment for previous token
-    union
-    {
-	// Integers
-	d_int32 int32value;
-	d_uns32	uns32value;
-	d_int64	int64value;
-	d_uns64	uns64value;
-
-	// Floats
-#ifdef IN_GCC
-	// real_t float80value; // can't use this in a union!
-#else
-	d_float80 float80value;
-#endif
-
-	struct
-	{   unsigned char *ustring;	// UTF8 string
-	    unsigned len;
-	    unsigned char postfix;	// 'c', 'w', 'd'
-	};
-
-	Identifier *ident;
-    };
-#ifdef IN_GCC
-    real_t float80value; // can't use this in a union!
-#endif
-
-    static const char *tochars[TOKMAX];
-    static void *operator new(size_t sz);
-
-    int isKeyword();
-    void print();
-    const char *toChars();
-    static const char *toChars(enum TOK);
-};
-
-struct Lexer
-{
-    static StringTable stringtable;
-    static OutBuffer stringbuffer;
-    static Token *freelist;
-
-    Loc loc;			// for error messages
-
-    unsigned char *base;	// pointer to start of buffer
-    unsigned char *end;		// past end of buffer
-    unsigned char *p;		// current character
-    Token token;
-    Module *mod;
-    int doDocComment;		// collect doc comment information
-    int anyToken;		// !=0 means seen at least one token
-    int commentToken;		// !=0 means comments are TOKcomment's
-
-    Lexer(Module *mod,
-	unsigned char *base, unsigned begoffset, unsigned endoffset,
-	int doDocComment, int commentToken);
-
-    static void initKeywords();
-    static Identifier *idPool(const char *s);
-    static Identifier *uniqueId(const char *s);
-    static Identifier *uniqueId(const char *s, int num);
-
-    TOK nextToken();
-    TOK peekNext();
-    void scan(Token *t);
-    Token *peek(Token *t);
-    Token *peekPastParen(Token *t);
-    unsigned escapeSequence();
-    TOK wysiwygStringConstant(Token *t, int tc);
-    TOK hexStringConstant(Token *t);
-#if DMDV2
-    TOK delimitedStringConstant(Token *t);
-    TOK tokenStringConstant(Token *t);
-#endif
-    TOK escapeStringConstant(Token *t, int wide);
-    TOK charConstant(Token *t, int wide);
-    void stringPostfix(Token *t);
-    unsigned wchar(unsigned u);
-    TOK number(Token *t);
-    TOK inreal(Token *t);
-    void error(const char *format, ...);
-    void error(Loc loc, const char *format, ...);
-    void pragma();
-    unsigned decodeUTF();
-    void getDocComment(Token *t, unsigned lineComment);
-
-    static int isValidIdentifier(char *p);
-    static unsigned char *combineComments(unsigned char *c1, unsigned char *c2);
-};
-
-#endif /* DMD_LEXER_H */
+
+// Compiler implementation of the D programming language
+// Copyright (c) 1999-2008 by Digital Mars
+// All Rights Reserved
+// written by Walter Bright
+// http://www.digitalmars.com
+// License for redistribution is by either the Artistic License
+// in artistic.txt, or the GNU General Public License in gnu.txt.
+// See the included readme.txt for details.
+
+#ifndef DMD_LEXER_H
+#define DMD_LEXER_H
+
+#ifdef __DMC__
+#pragma once
+#endif /* __DMC__ */
+
+#include "root.h"
+#include "mars.h"
+
+struct StringTable;
+struct Identifier;
+struct Module;
+
+/* Tokens:
+	(	)
+	[	]
+	{	}
+	<	>	<=	>=	==	!=	===	!==
+	<<	>>	<<=	>>=	>>>	>>>=
+	+	-	+=	-=
+	*	/	%	*=	/=	%=
+	&	| 	^	&=	|=	^=
+	=	!	~
+	++	--
+	.	->	:	,
+	?	&&	||
+ */
+
+enum TOK
+{
+	TOKreserved,
+
+	// Other
+	TOKlparen,	TOKrparen,
+	TOKlbracket,	TOKrbracket,
+	TOKlcurly,	TOKrcurly,
+	TOKcolon,	TOKneg,
+	TOKsemicolon,	TOKdotdotdot,
+	TOKeof,		TOKcast,
+	TOKnull,	TOKassert,
+	TOKtrue,	TOKfalse,
+	TOKarray,	TOKcall,
+	TOKaddress,
+	TOKtype,	TOKthrow,
+	TOKnew,		TOKdelete,
+	TOKstar,	TOKsymoff,
+	TOKvar,		TOKdotvar,
+	TOKdotti,	TOKdotexp,
+	TOKdottype,	TOKslice,
+	TOKarraylength,	TOKversion,
+	TOKmodule,	TOKdollar,
+	TOKtemplate,	TOKdottd,
+	TOKdeclaration,	TOKtypeof,
+	TOKpragma,	TOKdsymbol,
+	TOKtypeid,	TOKuadd,
+	TOKremove,
+	TOKnewanonclass, TOKcomment,
+	TOKarrayliteral, TOKassocarrayliteral,
+	TOKstructliteral,
+
+	// Operators
+	TOKlt,		TOKgt,
+	TOKle,		TOKge,
+	TOKequal,	TOKnotequal,
+	TOKidentity,	TOKnotidentity,
+	TOKindex,	TOKis,
+	TOKtobool,
+
+// 60
+	// NCEG floating point compares
+	// !<>=     <>    <>=    !>     !>=   !<     !<=   !<>
+	TOKunord,TOKlg,TOKleg,TOKule,TOKul,TOKuge,TOKug,TOKue,
+
+	TOKshl,		TOKshr,
+	TOKshlass,	TOKshrass,
+	TOKushr,	TOKushrass,
+	TOKcat,		TOKcatass,	// ~ ~=
+	TOKadd,		TOKmin,		TOKaddass,	TOKminass,
+	TOKmul,		TOKdiv,		TOKmod,
+	TOKmulass,	TOKdivass,	TOKmodass,
+	TOKand,		TOKor,		TOKxor,
+	TOKandass,	TOKorass,	TOKxorass,
+	TOKassign,	TOKnot,		TOKtilde,
+	TOKplusplus,	TOKminusminus,	TOKconstruct,	TOKblit,
+	TOKdot,		TOKarrow,	TOKcomma,
+	TOKquestion,	TOKandand,	TOKoror,
+
+// 104
+	// Numeric literals
+	TOKint32v, TOKuns32v,
+	TOKint64v, TOKuns64v,
+	TOKfloat32v, TOKfloat64v, TOKfloat80v,
+	TOKimaginary32v, TOKimaginary64v, TOKimaginary80v,
+
+	// Char constants
+	TOKcharv, TOKwcharv, TOKdcharv,
+
+	// Leaf operators
+	TOKidentifier,	TOKstring,
+	TOKthis,	TOKsuper,
+	TOKhalt,	TOKtuple,
+
+	// Basic types
+	TOKvoid,
+	TOKint8, TOKuns8,
+	TOKint16, TOKuns16,
+	TOKint32, TOKuns32,
+	TOKint64, TOKuns64,
+	TOKfloat32, TOKfloat64, TOKfloat80,
+	TOKimaginary32, TOKimaginary64, TOKimaginary80,
+	TOKcomplex32, TOKcomplex64, TOKcomplex80,
+	TOKchar, TOKwchar, TOKdchar, TOKbit, TOKbool,
+	TOKcent, TOKucent,
+
+	// Aggregates
+	TOKstruct, TOKclass, TOKinterface, TOKunion, TOKenum, TOKimport,
+	TOKtypedef, TOKalias, TOKoverride, TOKdelegate, TOKfunction,
+	TOKmixin,
+
+	TOKalign, TOKextern, TOKprivate, TOKprotected, TOKpublic, TOKexport,
+	TOKstatic, /*TOKvirtual,*/ TOKfinal, TOKconst, TOKabstract, TOKvolatile,
+	TOKdebug, TOKdeprecated, TOKin, TOKout, TOKinout, TOKlazy,
+	TOKauto, TOKpackage, TOKmanifest, TOKimmutable,
+
+	// Statements
+	TOKif, TOKelse, TOKwhile, TOKfor, TOKdo, TOKswitch,
+	TOKcase, TOKdefault, TOKbreak, TOKcontinue, TOKwith,
+	TOKsynchronized, TOKreturn, TOKgoto, TOKtry, TOKcatch, TOKfinally,
+	TOKasm, TOKforeach, TOKforeach_reverse,
+	TOKscope,
+	TOKon_scope_exit, TOKon_scope_failure, TOKon_scope_success,
+
+	// Contracts
+	TOKbody, TOKinvariant,
+
+	// Testing
+	TOKunittest,
+
+	// Added after 1.0
+	TOKref,
+	TOKmacro,
+#if DMDV2
+	TOKtraits,
+	TOKoverloadset,
+	TOKpure,
+	TOKnothrow,
+	TOKtls,
+	TOKgshared,
+	TOKline,
+	TOKfile,
+    TOKshared,
+#endif
+
+// LDC specific
+#if IN_LLVM
+    TOKgep,
+#endif
+
+	TOKMAX
+};
+
+#define CASE_BASIC_TYPES			\
+	case TOKwchar: case TOKdchar:		\
+	case TOKbit: case TOKbool: case TOKchar:	\
+	case TOKint8: case TOKuns8:		\
+	case TOKint16: case TOKuns16:		\
+	case TOKint32: case TOKuns32:		\
+	case TOKint64: case TOKuns64:		\
+	case TOKfloat32: case TOKfloat64: case TOKfloat80:		\
+	case TOKimaginary32: case TOKimaginary64: case TOKimaginary80:	\
+	case TOKcomplex32: case TOKcomplex64: case TOKcomplex80:	\
+	case TOKvoid
+
+#define CASE_BASIC_TYPES_X(t)					\
+	case TOKvoid:	 t = Type::tvoid;  goto LabelX;		\
+	case TOKint8:	 t = Type::tint8;  goto LabelX;		\
+	case TOKuns8:	 t = Type::tuns8;  goto LabelX;		\
+	case TOKint16:	 t = Type::tint16; goto LabelX;		\
+	case TOKuns16:	 t = Type::tuns16; goto LabelX;		\
+	case TOKint32:	 t = Type::tint32; goto LabelX;		\
+	case TOKuns32:	 t = Type::tuns32; goto LabelX;		\
+	case TOKint64:	 t = Type::tint64; goto LabelX;		\
+	case TOKuns64:	 t = Type::tuns64; goto LabelX;		\
+	case TOKfloat32: t = Type::tfloat32; goto LabelX;	\
+	case TOKfloat64: t = Type::tfloat64; goto LabelX;	\
+	case TOKfloat80: t = Type::tfloat80; goto LabelX;	\
+	case TOKimaginary32: t = Type::timaginary32; goto LabelX;	\
+	case TOKimaginary64: t = Type::timaginary64; goto LabelX;	\
+	case TOKimaginary80: t = Type::timaginary80; goto LabelX;	\
+	case TOKcomplex32: t = Type::tcomplex32; goto LabelX;	\
+	case TOKcomplex64: t = Type::tcomplex64; goto LabelX;	\
+	case TOKcomplex80: t = Type::tcomplex80; goto LabelX;	\
+	case TOKbit:	 t = Type::tbit;     goto LabelX;	\
+	case TOKbool:	 t = Type::tbool;    goto LabelX;	\
+	case TOKchar:	 t = Type::tchar;    goto LabelX;	\
+	case TOKwchar:	 t = Type::twchar; goto LabelX;	\
+	case TOKdchar:	 t = Type::tdchar; goto LabelX;	\
+	LabelX
+
+struct Token
+{
+    Token *next;
+    unsigned char *ptr;		// pointer to first character of this token within buffer
+    enum TOK value;
+    unsigned char *blockComment; // doc comment string prior to this token
+    unsigned char *lineComment;	 // doc comment for previous token
+    union
+    {
+	// Integers
+	d_int32 int32value;
+	d_uns32	uns32value;
+	d_int64	int64value;
+	d_uns64	uns64value;
+
+	// Floats
+#ifdef IN_GCC
+	// real_t float80value; // can't use this in a union!
+#else
+	d_float80 float80value;
+#endif
+
+	struct
+	{   unsigned char *ustring;	// UTF8 string
+	    unsigned len;
+	    unsigned char postfix;	// 'c', 'w', 'd'
+	};
+
+	Identifier *ident;
+    };
+#ifdef IN_GCC
+    real_t float80value; // can't use this in a union!
+#endif
+
+    static const char *tochars[TOKMAX];
+    static void *operator new(size_t sz);
+
+    int isKeyword();
+    void print();
+    const char *toChars();
+    static const char *toChars(enum TOK);
+};
+
+struct Lexer
+{
+    static StringTable stringtable;
+    static OutBuffer stringbuffer;
+    static Token *freelist;
+
+    Loc loc;			// for error messages
+
+    unsigned char *base;	// pointer to start of buffer
+    unsigned char *end;		// past end of buffer
+    unsigned char *p;		// current character
+    Token token;
+    Module *mod;
+    int doDocComment;		// collect doc comment information
+    int anyToken;		// !=0 means seen at least one token
+    int commentToken;		// !=0 means comments are TOKcomment's
+
+    Lexer(Module *mod,
+	unsigned char *base, unsigned begoffset, unsigned endoffset,
+	int doDocComment, int commentToken);
+
+    static void initKeywords();
+    static Identifier *idPool(const char *s);
+    static Identifier *uniqueId(const char *s);
+    static Identifier *uniqueId(const char *s, int num);
+
+    TOK nextToken();
+    TOK peekNext();
+    TOK peekNext2();
+    void scan(Token *t);
+    Token *peek(Token *t);
+    Token *peekPastParen(Token *t);
+    unsigned escapeSequence();
+    TOK wysiwygStringConstant(Token *t, int tc);
+    TOK hexStringConstant(Token *t);
+#if DMDV2
+    TOK delimitedStringConstant(Token *t);
+    TOK tokenStringConstant(Token *t);
+#endif
+    TOK escapeStringConstant(Token *t, int wide);
+    TOK charConstant(Token *t, int wide);
+    void stringPostfix(Token *t);
+    unsigned wchar(unsigned u);
+    TOK number(Token *t);
+    TOK inreal(Token *t);
+    void error(const char *format, ...) IS_PRINTF(2);
+    void error(Loc loc, const char *format, ...) IS_PRINTF(3);
+    void pragma();
+    unsigned decodeUTF();
+    void getDocComment(Token *t, unsigned lineComment);
+
+    static int isValidIdentifier(char *p);
+    static unsigned char *combineComments(unsigned char *c1, unsigned char *c2);
+};
+
+#endif /* DMD_LEXER_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd2/lib.h	Mon Jun 01 19:02:20 2009 +0100
@@ -0,0 +1,49 @@
+
+// Compiler implementation of the D programming language
+// Copyright (c) 1999-2008 by Digital Mars
+// All Rights Reserved
+// written by Walter Bright
+// http://www.digitalmars.com
+// License for redistribution is by either the Artistic License
+// in artistic.txt, or the GNU General Public License in gnu.txt.
+// See the included readme.txt for details.
+
+#ifndef DMD_LIB_H
+#define DMD_LIB_H
+
+#ifdef __DMC__
+#pragma once
+#endif /* __DMC__ */
+
+struct ObjModule;
+
+struct ObjSymbol
+{
+    char *name;
+    ObjModule *om;
+};
+
+struct Library
+{
+    File *libfile;
+    Array objmodules;	// ObjModule[]
+    Array objsymbols;	// ObjSymbol[]
+
+    StringTable tab;
+
+    Library();
+    void setFilename(char *dir, char *filename);
+    void addObject(const char *module_name, void *buf, size_t buflen);
+    void addLibrary(void *buf, size_t buflen);
+    void write();
+
+  private:
+    void addSymbol(ObjModule *om, char *name, int pickAny = 0);
+    void scanObjModule(ObjModule *om);
+    unsigned short numDictPages(unsigned padding);
+    int FillDict(unsigned char *bucketsP, unsigned short uNumPages);
+    void WriteLibToBuffer(OutBuffer *libbuf);
+};
+
+#endif /* DMD_LIB_H */
+
--- a/dmd2/link.c.nolink	Mon Jun 01 01:28:18 2009 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,505 +0,0 @@
-
-// 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	<ctype.h>
-#include	<assert.h>
-#include	<stdarg.h>
-#include	<string.h>
-#include	<stdlib.h>
-
-#if _WIN32
-#include	<process.h>
-#endif
-
-#if linux
-#include	<sys/types.h>
-#include	<sys/wait.h>
-#include	<unistd.h>
-#endif
-
-#include	"root.h"
-
-#include	"mars.h"
-
-#include	"mem.h"
-
-int executecmd(char *cmd, char *args, int useenv);
-int executearg0(char *cmd, char *args);
-
-/****************************************
- * Write filename to cmdbuf, quoting if necessary.
- */
-
-void writeFilename(OutBuffer *buf, char *filename, size_t len)
-{
-    /* Loop and see if we need to quote
-     */
-    for (size_t i = 0; i < len; i++)
-    {	char c = filename[i];
-
-	if (isalnum(c) || c == '_')
-	    continue;
-
-	/* Need to quote
-	 */
-	buf->writeByte('"');
-	buf->write(filename, len);
-	buf->writeByte('"');
-	return;
-    }
-
-    /* No quoting necessary
-     */
-    buf->write(filename, len);
-}
-
-void writeFilename(OutBuffer *buf, char *filename)
-{
-    writeFilename(buf, filename, strlen(filename));
-}
-
-/*****************************
- * Run the linker.  Return status of execution.
- */
-
-int runLINK()
-{
-#if _WIN32
-    char *p;
-    int i;
-    int status;
-    OutBuffer cmdbuf;
-
-    global.params.libfiles->push((void *) "user32");
-    global.params.libfiles->push((void *) "kernel32");
-
-    for (i = 0; i < global.params.objfiles->dim; i++)
-    {
-	if (i)
-	    cmdbuf.writeByte('+');
-	p = (char *)global.params.objfiles->data[i];
-	char *ext = FileName::ext(p);
-	if (ext)
-	    // Write name sans extension
-	    writeFilename(&cmdbuf, p, ext - p - 1);
-	else
-	    writeFilename(&cmdbuf, p);
-    }
-    cmdbuf.writeByte(',');
-    if (global.params.exefile)
-	writeFilename(&cmdbuf, global.params.exefile);
-    else
-    {	/* Generate exe file name from first obj name.
-	 * No need to add it to cmdbuf because the linker will default to it.
-	 */
-	char *n = (char *)global.params.objfiles->data[0];
-	n = FileName::name(n);
-	FileName *fn = FileName::forceExt(n, "exe");
-	global.params.exefile = fn->toChars();
-    }
-
-    // Make sure path to exe file exists
-    {	char *p = FileName::path(global.params.exefile);
-	FileName::ensurePathExists(p);
-	mem.free(p);
-    }
-
-    cmdbuf.writeByte(',');
-    if (global.params.run)
-	cmdbuf.writestring("nul");
-//    if (mapfile)
-//	cmdbuf.writestring(output);
-    cmdbuf.writeByte(',');
-
-    for (i = 0; i < global.params.libfiles->dim; i++)
-    {
-	if (i)
-	    cmdbuf.writeByte('+');
-	writeFilename(&cmdbuf, (char *) global.params.libfiles->data[i]);
-    }
-
-    if (global.params.deffile)
-    {
-	cmdbuf.writeByte(',');
-	writeFilename(&cmdbuf, global.params.deffile);
-    }
-
-    /* Eliminate unnecessary trailing commas	*/
-    while (1)
-    {   i = cmdbuf.offset;
-	if (!i || cmdbuf.data[i - 1] != ',')
-	    break;
-	cmdbuf.offset--;
-    }
-
-    if (global.params.resfile)
-    {
-	cmdbuf.writestring("/RC:");
-	writeFilename(&cmdbuf, global.params.resfile);
-    }
-
-#if 0
-    if (mapfile)
-	cmdbuf.writestring("/m");
-    if (debuginfo)
-	cmdbuf.writestring("/li");
-    if (codeview)
-    {
-	cmdbuf.writestring("/co");
-	if (codeview3)
-	    cmdbuf.writestring(":3");
-    }
-#else
-    if (global.params.symdebug)
-	cmdbuf.writestring("/co");
-#endif
-
-    cmdbuf.writestring("/noi");
-    for (i = 0; i < global.params.linkswitches->dim; i++)
-    {
-	cmdbuf.writestring((char *) global.params.linkswitches->data[i]);
-    }
-    cmdbuf.writeByte(';');
-
-    p = cmdbuf.toChars();
-
-    FileName *lnkfilename = NULL;
-    size_t plen = strlen(p);
-    if (plen > 7000)
-    {
-	lnkfilename = FileName::forceExt(global.params.exefile, "lnk");
-	File flnk(lnkfilename);
-	flnk.setbuffer(p, plen);
-	flnk.ref = 1;
-	if (flnk.write())
-	    error("error writing file %s", lnkfilename);
-	if (lnkfilename->len() < plen)
-	    sprintf(p, "@%s", lnkfilename->toChars());
-    }
-
-    char *linkcmd = getenv("LINKCMD");
-    if (!linkcmd)
-	linkcmd = "link";
-    status = executecmd(linkcmd, p, 1);
-    if (lnkfilename)
-    {
-	remove(lnkfilename->toChars());
-	delete lnkfilename;
-    }
-    return status;
-#elif linux
-    pid_t childpid;
-    int i;
-    int status;
-
-    // Build argv[]
-    Array argv;
-
-    const char *cc = getenv("CC");
-    if (!cc)
-	cc = "gcc";
-    argv.push((void *)cc);
-    argv.insert(1, global.params.objfiles);
-
-    // None of that a.out stuff. Use explicit exe file name, or
-    // generate one from name of first source file.
-    argv.push((void *)"-o");
-    if (global.params.exefile)
-    {
-	argv.push(global.params.exefile);
-    }
-    else
-    {	// Generate exe file name from first obj name
-	char *n = (char *)global.params.objfiles->data[0];
-	char *e;
-	char *ex;
-
-	n = FileName::name(n);
-	e = FileName::ext(n);
-	if (e)
-	{
-	    e--;			// back up over '.'
-	    ex = (char *)mem.malloc(e - n + 1);
-	    memcpy(ex, n, e - n);
-	    ex[e - n] = 0;
-	}
-	else
-	    ex = (char *)"a.out";	// no extension, so give up
-	argv.push(ex);
-	global.params.exefile = ex;
-    }
-
-    // Make sure path to exe file exists
-    {	char *p = FileName::path(global.params.exefile);
-	FileName::ensurePathExists(p);
-	mem.free(p);
-    }
-
-    argv.insert(argv.dim, global.params.libfiles);
-
-    if (global.params.symdebug)
-	argv.push((void *)"-g");
-
-    argv.push((void *)"-m32");
-
-    if (0 && global.params.exefile)
-    {
-	/* This switch enables what is known as 'smart linking'
-	 * in the Windows world, where unreferenced sections
-	 * are removed from the executable. It eliminates unreferenced
-	 * functions, essentially making a 'library' out of a module.
-	 * Although it is documented to work with ld version 2.13,
-	 * in practice it does not, but just seems to be ignored.
-	 * Thomas Kuehne has verified that it works with ld 2.16.1.
-	 * BUG: disabled because it causes exception handling to fail
-	 */
-	argv.push((void *)"-Xlinker");
-	argv.push((void *)"--gc-sections");
-    }
-
-    for (i = 0; i < global.params.linkswitches->dim; i++)
-    {	char *p = (char *)global.params.linkswitches->data[i];
-	if (!p || !p[0] || !(p[0] == '-' && p[1] == 'l'))
-	    // Don't need -Xlinker if switch starts with -l
-	    argv.push((void *)"-Xlinker");
-	argv.push((void *) p);
-    }
-
-    /* Standard libraries must go after user specified libraries
-     * passed with -l.
-     */
-    const char *libname = (global.params.symdebug)
-				? global.params.debuglibname
-				: global.params.defaultlibname;
-    char *buf = (char *)malloc(2 + strlen(libname) + 1);
-    strcpy(buf, "-l");
-    strcpy(buf + 2, libname);
-    argv.push((void *)buf);		// turns into /usr/lib/libphobos2.a
-
-    argv.push((void *)"-ldruntime");
-    argv.push((void *)"-lpthread");
-    argv.push((void *)"-lm");
-
-    if (!global.params.quiet || global.params.verbose)
-    {
-	// Print it
-	for (i = 0; i < argv.dim; i++)
-	    printf("%s ", (char *)argv.data[i]);
-	printf("\n");
-	fflush(stdout);
-    }
-
-    argv.push(NULL);
-    childpid = fork();
-    if (childpid == 0)
-    {
-	execvp((char *)argv.data[0], (char **)argv.data);
-	perror((char *)argv.data[0]);		// failed to execute
-	return -1;
-    }
-
-    waitpid(childpid, &status, 0);
-
-    status=WEXITSTATUS(status);
-    if (status)
-	printf("--- errorlevel %d\n", status);
-    return status;
-#else
-    printf ("Linking is not yet supported for this version of DMD.\n");
-    return -1;
-#endif
-}
-
-/**********************************
- * Delete generated EXE file.
- */
-
-void deleteExeFile()
-{
-    if (global.params.exefile)
-    {
-	//printf("deleteExeFile() %s\n", global.params.exefile);
-	remove(global.params.exefile);
-    }
-}
-
-/******************************
- * Execute a rule.  Return the status.
- *	cmd	program to run
- *	args	arguments to cmd, as a string
- *	useenv	if cmd knows about _CMDLINE environment variable
- */
-
-#if _WIN32
-int executecmd(char *cmd, char *args, int useenv)
-{
-    int status;
-    char *buff;
-    size_t len;
-
-    if (!global.params.quiet || global.params.verbose)
-    {
-	printf("%s %s\n", cmd, args);
-	fflush(stdout);
-    }
-
-    if ((len = strlen(args)) > 255)
-    {   char *q;
-	static char envname[] = "@_CMDLINE";
-
-	envname[0] = '@';
-	switch (useenv)
-	{   case 0:	goto L1;
-	    case 2: envname[0] = '%';	break;
-	}
-	q = (char *) alloca(sizeof(envname) + len + 1);
-	sprintf(q,"%s=%s", envname + 1, args);
-	status = putenv(q);
-	if (status == 0)
-	    args = envname;
-	else
-	{
-	L1:
-	    error("command line length of %d is too long",len);
-	}
-    }
-
-    status = executearg0(cmd,args);
-#if _WIN32
-    if (status == -1)
-	status = spawnlp(0,cmd,cmd,args,NULL);
-#endif
-//    if (global.params.verbose)
-//	printf("\n");
-    if (status)
-    {
-	if (status == -1)
-	    printf("Can't run '%s', check PATH\n", cmd);
-	else
-	    printf("--- errorlevel %d\n", status);
-    }
-    return status;
-}
-#endif
-
-/**************************************
- * Attempt to find command to execute by first looking in the directory
- * where DMD was run from.
- * Returns:
- *	-1	did not find command there
- *	!=-1	exit status from command
- */
-
-#if _WIN32
-int executearg0(char *cmd, char *args)
-{
-    char *file;
-    char *argv0 = global.params.argv0;
-
-    //printf("argv0='%s', cmd='%s', args='%s'\n",argv0,cmd,args);
-
-    // If cmd is fully qualified, we don't do this
-    if (FileName::absolute(cmd))
-	return -1;
-
-    file = FileName::replaceName(argv0, cmd);
-
-    //printf("spawning '%s'\n",file);
-#if _WIN32
-    return spawnl(0,file,file,args,NULL);
-#elif linux
-    char *full;
-    int cmdl = strlen(cmd);
-
-    full = (char*) mem.malloc(cmdl + strlen(args) + 2);
-    if (full == NULL)
-	return 1;
-    strcpy(full, cmd);
-    full [cmdl] = ' ';
-    strcpy(full + cmdl + 1, args);
-
-    int result = system(full);
-
-    mem.free(full);
-    return result;
-#else
-    assert(0);
-#endif
-}
-#endif
-
-/***************************************
- * Run the compiled program.
- * Return exit status.
- */
-
-int runProgram()
-{
-    //printf("runProgram()\n");
-    if (global.params.verbose)
-    {
-	printf("%s", global.params.exefile);
-	for (size_t i = 0; i < global.params.runargs_length; i++)
-	    printf(" %s", (char *)global.params.runargs[i]);
-	printf("\n");
-    }
-
-    // Build argv[]
-    Array argv;
-
-    argv.push((void *)global.params.exefile);
-    for (size_t i = 0; i < global.params.runargs_length; i++)
-    {	char *a = global.params.runargs[i];
-
-#if _WIN32
-	// BUG: what about " appearing in the string?
-	if (strchr(a, ' '))
-	{   char *b = (char *)mem.malloc(3 + strlen(a));
-	    sprintf(b, "\"%s\"", a);
-	    a = b;
-	}
-#endif
-	argv.push((void *)a);
-    }
-    argv.push(NULL);
-
-#if _WIN32
-    char *ex = FileName::name(global.params.exefile);
-    if (ex == global.params.exefile)
-	ex = FileName::combine(".", ex);
-    else
-	ex = global.params.exefile;
-    return spawnv(0,ex,(char **)argv.data);
-#elif linux
-    pid_t childpid;
-    int status;
-
-    childpid = fork();
-    if (childpid == 0)
-    {
-	const char *fn = (const char *)argv.data[0];
-	if (!FileName::absolute(fn))
-	{   // Make it "./fn"
-	    fn = FileName::combine(".", fn);
-	}
-	execv(fn, (char **)argv.data);
-	perror(fn);		// failed to execute
-	return -1;
-    }
-
-    waitpid(childpid, &status, 0);
-
-    status = WEXITSTATUS(status);
-    return status;
-#else
-    assert(0);
-#endif
-}
--- a/dmd2/lstring.c	Mon Jun 01 01:28:18 2009 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,63 +0,0 @@
-// lstring.c
-
-// Copyright (c) 1999-2002 by Digital Mars
-// All Rights Reserved
-// written by Walter Bright
-// 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 <stdlib.h>
-
-#include "dchar.h"
-#include "mem.h"
-#include "lstring.h"
-
-#ifdef _MSC_VER // prevent compiler internal crash
-Lstring Lstring::zero;
-#else
-Lstring Lstring::zero = LSTRING_EMPTY();
-#endif
-
-Lstring *Lstring::ctor(const dchar *p, unsigned length)
-{
-    Lstring *s;
-
-    s = alloc(length);
-    memcpy(s->string, p, length * sizeof(dchar));
-    return s;
-}
-
-Lstring *Lstring::alloc(unsigned length)
-{
-    Lstring *s;
-
-    s = (Lstring *)mem.malloc(size(length));
-    s->length = length;
-    s->string[length] = 0;
-    return s;
-}
-
-Lstring *Lstring::append(const Lstring *s)
-{
-    Lstring *t;
-
-    if (!s->length)
-	return this;
-    t = alloc(length + s->length);
-    memcpy(t->string, string, length * sizeof(dchar));
-    memcpy(t->string + length, s->string, s->length * sizeof(dchar));
-    return t;
-}
-
-Lstring *Lstring::substring(int start, int end)
-{
-    Lstring *t;
-
-    if (start == end)
-	return &zero;
-    t = alloc(end - start);
-    memcpy(t->string, string + start, (end - start) * sizeof(dchar));
-    return t;
-}
--- a/dmd2/lstring.h	Mon Jun 01 01:28:18 2009 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,72 +0,0 @@
-
-// lstring.h
-// length-prefixed strings
-
-// Copyright (c) 1999-2002 by Digital Mars
-// All Rights Reserved
-// written by Walter Bright
-// www.digitalmars.com
-// License for redistribution is by either the Artistic License
-// in artistic.txt, or the GNU General Public License in gnu.txt.
-// See the included readme.txt for details.
-
-#ifndef LSTRING_H
-#define LSTRING_H 1
-
-#include "dchar.h"
-
-struct Lstring
-{
-    unsigned length;
-
-    // Disable warning about nonstandard extension
-    #pragma warning (disable : 4200)
-    dchar string[];
-
-    static Lstring zero;	// 0 length string
-
-    // No constructors because we want to be able to statically
-    // initialize Lstring's, and Lstrings are of variable size.
-
-    #if M_UNICODE
-    #define LSTRING(p,length) { length, L##p }
-    #else
-    #define LSTRING(p,length) { length, p }
-    #endif
-
-#if __GNUC__
-    #define LSTRING_EMPTY() { 0 }
-#else
-    #define LSTRING_EMPTY() LSTRING("", 0)
-#endif
-
-    static Lstring *ctor(const dchar *p) { return ctor(p, Dchar::len(p)); }
-    static Lstring *ctor(const dchar *p, unsigned length);
-    static unsigned size(unsigned length) { return sizeof(Lstring) + (length + 1) * sizeof(dchar); }
-    static Lstring *alloc(unsigned length);
-    Lstring *clone();
-
-    unsigned len() { return length; }
-
-    dchar *toDchars() { return string; }
-
-    hash_t hash() { return Dchar::calcHash(string, length); }
-    hash_t ihash() { return Dchar::icalcHash(string, length); }
-
-    static int cmp(const Lstring *s1, const Lstring *s2)
-    {
-	int c = s2->length - s1->length;
-	return c ? c : Dchar::memcmp(s1->string, s2->string, s1->length);
-    }
-
-    static int icmp(const Lstring *s1, const Lstring *s2)
-    {
-	int c = s2->length - s1->length;
-	return c ? c : Dchar::memicmp(s1->string, s2->string, s1->length);
-    }
-
-    Lstring *append(const Lstring *s);
-    Lstring *substring(int start, int end);
-};
-
-#endif
--- a/dmd2/macro.c	Mon Jun 01 01:28:18 2009 +0200
+++ b/dmd2/macro.c	Mon Jun 01 19:02:20 2009 +0100
@@ -16,19 +16,9 @@
 #include <ctype.h>
 #include <assert.h>
 
-#if IN_GCC || IN_LLVM
-#include "mem.h"
-#else
-#if _WIN32
-#include "..\root\mem.h"
-#elif POSIX
-#include "../root/mem.h"
-#else
-#error "fix this"
-#endif
-#endif
+#include "rmem.h"
+#include "root.h"
 
-#include "root.h"
 #include "macro.h"
 
 #define isidstart(c) (isalpha(c) || (c) == '_')
--- a/dmd2/man.c	Mon Jun 01 01:28:18 2009 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,60 +0,0 @@
-
-// Compiler implementation of the D programming language
-// Copyright (c) 2008-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 <string.h>
-#include <stdlib.h>
-#include <assert.h>
-
-#if _WIN32
-
-#include <windows.h>
-
-#pragma comment(lib,"shell32.lib")
-
-void browse(const char *url)
-{
-    ShellExecute(NULL, "open", url, NULL, NULL, SW_SHOWNORMAL);
-}
-
-#endif
-
-#if linux || __APPLE__
-
-#include	<sys/types.h>
-#include	<sys/wait.h>
-#include	<unistd.h>
-
-void browse(const char *url)
-{
-    pid_t childpid;
-    const char *args[3];
-
-    const char *browser = getenv("BROWSER");
-    if (browser)
-	browser = strdup(browser);
-    else
-	browser = "firefox";
-
-    args[0] = browser;
-    args[1] = url;
-    args[2] = NULL;
-
-    childpid = fork();
-    if (childpid == 0)
-    {
-	execvp(args[0], (char**)args);
-	perror(args[0]);		// failed to execute
-	return;
-    }
-}
-
-#endif
-
--- a/dmd2/mangle.c	Mon Jun 01 01:28:18 2009 +0200
+++ b/dmd2/mangle.c	Mon Jun 01 19:02:20 2009 +0100
@@ -1,291 +1,298 @@
-
-// Compiler implementation of the D programming language
-// Copyright (c) 1999-2007 by Digital Mars
-// All Rights Reserved
-// written by Walter Bright
-// http://www.digitalmars.com
-// License for redistribution is by either the Artistic License
-// in artistic.txt, or the GNU General Public License in gnu.txt.
-// See the included readme.txt for details.
-
-#include <stdio.h>
-#include <string.h>
-#include <ctype.h>
-#include <assert.h>
-
-#include "root.h"
-
-#include "init.h"
-#include "declaration.h"
-#include "aggregate.h"
-#include "mtype.h"
-#include "attrib.h"
-#include "template.h"
-#include "id.h"
-#include "module.h"
-
-#if TARGET_LINUX
-char *cpp_mangle(Dsymbol *s);
-#endif
-
-char *mangle(Declaration *sthis)
-{
-    OutBuffer buf;
-    char *id;
-    Dsymbol *s;
-
-    //printf("::mangle(%s)\n", sthis->toChars());
-    s = sthis;
-    do
-    {
-	//printf("mangle: s = %p, '%s', parent = %p\n", s, s->toChars(), s->parent);
-	if (s->ident)
-	{
-	    FuncDeclaration *fd = s->isFuncDeclaration();
-	    if (s != sthis && fd)
-	    {
-		id = mangle(fd);
-		buf.prependstring(id);
-		goto L1;
-	    }
-	    else
-	    {
-		id = s->ident->toChars();
-		int len = strlen(id);
-		char tmp[sizeof(len) * 3 + 1];
-		buf.prependstring(id);
-		sprintf(tmp, "%d", len);
-		buf.prependstring(tmp);
-	    }
-	}
-	else
-	    buf.prependstring("0");
-	s = s->parent;
-    } while (s);
-
-//    buf.prependstring("_D");
-L1:
-    //printf("deco = '%s'\n", sthis->type->deco ? sthis->type->deco : "null");
-    //printf("sthis->type = %s\n", sthis->type->toChars());
-    FuncDeclaration *fd = sthis->isFuncDeclaration();
-    if (fd && (fd->needThis() || fd->isNested()))
-	buf.writeByte(Type::needThisPrefix());
-    if (sthis->type->deco)
-	buf.writestring(sthis->type->deco);
-    else
-    {	assert(fd->inferRetType);
-    }
-
-    id = buf.toChars();
-    buf.data = NULL;
-    return id;
-}
-
-char *Declaration::mangle()
-#if __DMC__
-    __out(result)
-    {
-	int len = strlen(result);
-
-	assert(len > 0);
-	//printf("mangle: '%s' => '%s'\n", toChars(), result);
-	for (int i = 0; i < len; i++)
-	{
-	    assert(result[i] == '_' ||
-		   result[i] == '@' ||
-		   isalnum(result[i]) || result[i] & 0x80);
-	}
-    }
-    __body
-#endif
-    {
-	//printf("Declaration::mangle(this = %p, '%s', parent = '%s', linkage = %d)\n", this, toChars(), parent ? parent->toChars() : "null", linkage);
-	if (!parent || parent->isModule() || linkage == LINKcpp) // if at global scope
-	{
-	    // If it's not a D declaration, no mangling
-	    switch (linkage)
-	    {
-		case LINKd:
-		    break;
-
-        // LDC
-        case LINKintrinsic:
-
-		case LINKc:
-		case LINKwindows:
-		case LINKpascal:
-		    return ident->toChars();
-
-		case LINKcpp:
-#if TARGET_LINUX
-		    return cpp_mangle(this);
-#else
-		    // Windows C++ mangling is done by C++ back end
-		    return ident->toChars();
-#endif
-
-		case LINKdefault:
-		    error("forward declaration");
-		    return ident->toChars();
-
-		default:
-		    fprintf(stdmsg, "'%s', linkage = %d\n", toChars(), linkage);
-		    assert(0);
-	    }
-	}
-	char *p = ::mangle(this);
-	OutBuffer buf;
-	buf.writestring("_D");
-	buf.writestring(p);
-	p = buf.toChars();
-	buf.data = NULL;
-	//printf("Declaration::mangle(this = %p, '%s', parent = '%s', linkage = %d) = %s\n", this, toChars(), parent ? parent->toChars() : "null", linkage, p);
-	return p;
-    }
-
-char *FuncDeclaration::mangle()
-#if __DMC__
-    __out(result)
-    {
-	assert(strlen(result) > 0);
-    }
-    __body
-#endif
-    {
-	if (isMain())
-	    return (char *)"_Dmain";
-
-    if (isWinMain() || isDllMain())
-        return ident->toChars();
-
-    assert(this);
-    return Declaration::mangle();
-    }
-
-
-char *StructDeclaration::mangle()
-{
-    //printf("StructDeclaration::mangle() '%s'\n", toChars());
-    return Dsymbol::mangle();
-}
-
-
-char *TypedefDeclaration::mangle()
-{
-    //printf("TypedefDeclaration::mangle() '%s'\n", toChars());
-    return Dsymbol::mangle();
-}
-
-
-char *ClassDeclaration::mangle()
-{
-    Dsymbol *parentsave = parent;
-
-    //printf("ClassDeclaration::mangle() %s.%s\n", parent->toChars(), toChars());
-
-    /* These are reserved to the compiler, so keep simple
-     * names for them.
-     */
-    if (ident == Id::Exception)
-    {	if (parent->ident == Id::object)
-	    parent = NULL;
-    }
-    else if (ident == Id::TypeInfo   ||
-//	ident == Id::Exception ||
-	ident == Id::TypeInfo_Struct   ||
-	ident == Id::TypeInfo_Class    ||
-	ident == Id::TypeInfo_Typedef  ||
-	ident == Id::TypeInfo_Tuple ||
-	this == object     ||
-	this == classinfo  ||
-	this == Module::moduleinfo ||
-	memcmp(ident->toChars(), "TypeInfo_", 9) == 0
-       )
-	parent = NULL;
-
-    char *id = Dsymbol::mangle();
-    parent = parentsave;
-    return id;
-}
-
-
-char *TemplateInstance::mangle()
-{
-    OutBuffer buf;
-    char *id;
-
-#if 0
-    printf("TemplateInstance::mangle() %s", toChars());
-    if (parent)
-	printf("  parent = %s %s", parent->kind(), parent->toChars());
-    printf("\n");
-#endif
-    id = ident ? ident->toChars() : toChars();
-    if (tempdecl->parent)
-    {
-	char *p = tempdecl->parent->mangle();
-	if (p[0] == '_' && p[1] == 'D')
-	    p += 2;
-	buf.writestring(p);
-    }
-    buf.printf("%"PRIuSIZE"%s", strlen(id), id);
-    id = buf.toChars();
-    buf.data = NULL;
-    //printf("TemplateInstance::mangle() %s = %s\n", toChars(), id);
-    return id;
-}
-
-
-char *TemplateMixin::mangle()
-{
-    OutBuffer buf;
-    char *id;
-
-#if 0
-    printf("TemplateMixin::mangle() %s", toChars());
-    if (parent)
-        printf("  parent = %s %s", parent->kind(), parent->toChars());
-    printf("\n");
-#endif
-    id = ident ? ident->toChars() : toChars();
-    if (parent)
-    {
-	char *p = parent->mangle();
-	if (p[0] == '_' && p[1] == 'D')
-	    p += 2;
-	buf.writestring(p);
-    }
-    buf.printf("%"PRIuSIZE"%s", strlen(id), id);
-    id = buf.toChars();
-    buf.data = NULL;
-    //printf("TemplateMixin::mangle() %s = %s\n", toChars(), id);
-    return id;
-}
-
-char *Dsymbol::mangle()
-{
-    OutBuffer buf;
-    char *id;
-
-#if 0
-    printf("Dsymbol::mangle() '%s'", toChars());
-    if (parent)
-	printf("  parent = %s %s", parent->kind(), parent->toChars());
-    printf("\n");
-#endif
-    id = ident ? ident->toChars() : toChars();
-    if (parent)
-    {
-	char *p = parent->mangle();
-	if (p[0] == '_' && p[1] == 'D')
-	    p += 2;
-	buf.writestring(p);
-    }
-    buf.printf("%"PRIuSIZE"%s", strlen(id), id);
-    id = buf.toChars();
-    buf.data = NULL;
-    //printf("Dsymbol::mangle() %s = %s\n", toChars(), id);
-    return id;
-}
-
-
+
+// Compiler implementation of the D programming language
+// Copyright (c) 1999-2009 by Digital Mars
+// All Rights Reserved
+// written by Walter Bright
+// http://www.digitalmars.com
+// License for redistribution is by either the Artistic License
+// in artistic.txt, or the GNU General Public License in gnu.txt.
+// See the included readme.txt for details.
+
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <assert.h>
+
+#include "root.h"
+
+#include "init.h"
+#include "declaration.h"
+#include "aggregate.h"
+#include "mtype.h"
+#include "attrib.h"
+#include "template.h"
+#include "id.h"
+#include "module.h"
+
+#if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_SOLARIS
+char *cpp_mangle(Dsymbol *s);
+#endif
+
+char *mangle(Declaration *sthis)
+{
+    OutBuffer buf;
+    char *id;
+    Dsymbol *s;
+
+    //printf("::mangle(%s)\n", sthis->toChars());
+    s = sthis;
+    do
+    {
+	//printf("mangle: s = %p, '%s', parent = %p\n", s, s->toChars(), s->parent);
+	if (s->ident)
+	{
+	    FuncDeclaration *fd = s->isFuncDeclaration();
+	    if (s != sthis && fd)
+	    {
+		id = mangle(fd);
+		buf.prependstring(id);
+		goto L1;
+	    }
+	    else
+	    {
+		id = s->ident->toChars();
+		int len = strlen(id);
+		char tmp[sizeof(len) * 3 + 1];
+		buf.prependstring(id);
+		sprintf(tmp, "%d", len);
+		buf.prependstring(tmp);
+	    }
+	}
+	else
+	    buf.prependstring("0");
+	s = s->parent;
+    } while (s);
+
+//    buf.prependstring("_D");
+L1:
+    //printf("deco = '%s'\n", sthis->type->deco ? sthis->type->deco : "null");
+    //printf("sthis->type = %s\n", sthis->type->toChars());
+    FuncDeclaration *fd = sthis->isFuncDeclaration();
+    if (fd && (fd->needThis() || fd->isNested()))
+	buf.writeByte(Type::needThisPrefix());
+    if (sthis->type->deco)
+	buf.writestring(sthis->type->deco);
+    else
+    {
+#ifdef DEBUG
+	if (!fd->inferRetType)
+	    printf("%s\n", fd->toChars());
+#endif
+	assert(fd->inferRetType);
+    }
+
+    id = buf.toChars();
+    buf.data = NULL;
+    return id;
+}
+
+char *Declaration::mangle()
+#if __DMC__
+    __out(result)
+    {
+	int len = strlen(result);
+
+	assert(len > 0);
+	//printf("mangle: '%s' => '%s'\n", toChars(), result);
+	for (int i = 0; i < len; i++)
+	{
+	    assert(result[i] == '_' ||
+		   result[i] == '@' ||
+		   isalnum(result[i]) || result[i] & 0x80);
+	}
+    }
+    __body
+#endif
+    {
+	//printf("Declaration::mangle(this = %p, '%s', parent = '%s', linkage = %d)\n", this, toChars(), parent ? parent->toChars() : "null", linkage);
+	if (!parent || parent->isModule() || linkage == LINKcpp) // if at global scope
+	{
+	    // If it's not a D declaration, no mangling
+	    switch (linkage)
+	    {
+		case LINKd:
+		    break;
+
+        // LDC
+        case LINKintrinsic:
+
+		case LINKc:
+		case LINKwindows:
+		case LINKpascal:
+		    return ident->toChars();
+
+		case LINKcpp:
+#if DMDV2 && (TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_SOLARIS)
+		    return cpp_mangle(this);
+#else
+		    // Windows C++ mangling is done by C++ back end
+		    return ident->toChars();
+#endif
+
+		case LINKdefault:
+		    error("forward declaration");
+		    return ident->toChars();
+
+		default:
+		    fprintf(stdmsg, "'%s', linkage = %d\n", toChars(), linkage);
+		    assert(0);
+	    }
+	}
+	char *p = ::mangle(this);
+	OutBuffer buf;
+	buf.writestring("_D");
+	buf.writestring(p);
+	p = buf.toChars();
+	buf.data = NULL;
+	//printf("Declaration::mangle(this = %p, '%s', parent = '%s', linkage = %d) = %s\n", this, toChars(), parent ? parent->toChars() : "null", linkage, p);
+	return p;
+    }
+
+char *FuncDeclaration::mangle()
+#if __DMC__
+    __out(result)
+    {
+	assert(strlen(result) > 0);
+    }
+    __body
+#endif
+    {
+	if (isMain())
+	    return (char *)"_Dmain";
+
+	if (isWinMain() || isDllMain() || ident == Id::tls_get_addr)
+	    return ident->toChars();
+
+	assert(this);
+	return Declaration::mangle();
+    }
+
+char *StructDeclaration::mangle()
+{
+    //printf("StructDeclaration::mangle() '%s'\n", toChars());
+    return Dsymbol::mangle();
+}
+
+
+char *TypedefDeclaration::mangle()
+{
+    //printf("TypedefDeclaration::mangle() '%s'\n", toChars());
+    return Dsymbol::mangle();
+}
+
+
+char *ClassDeclaration::mangle()
+{
+    Dsymbol *parentsave = parent;
+
+    //printf("ClassDeclaration::mangle() %s.%s\n", parent->toChars(), toChars());
+
+    /* These are reserved to the compiler, so keep simple
+     * names for them.
+     */
+    if (ident == Id::Exception)
+    {	if (parent->ident == Id::object)
+	    parent = NULL;
+    }
+    else if (ident == Id::TypeInfo   ||
+//	ident == Id::Exception ||
+	ident == Id::TypeInfo_Struct   ||
+	ident == Id::TypeInfo_Class    ||
+	ident == Id::TypeInfo_Typedef  ||
+	ident == Id::TypeInfo_Tuple ||
+	this == object     ||
+	this == classinfo  ||
+	this == Module::moduleinfo ||
+	memcmp(ident->toChars(), "TypeInfo_", 9) == 0
+       )
+	parent = NULL;
+
+    char *id = Dsymbol::mangle();
+    parent = parentsave;
+    return id;
+}
+
+
+char *TemplateInstance::mangle()
+{
+    OutBuffer buf;
+    char *id;
+
+#if 0
+    printf("TemplateInstance::mangle() %s", toChars());
+    if (parent)
+	printf("  parent = %s %s", parent->kind(), parent->toChars());
+    printf("\n");
+#endif
+    id = ident ? ident->toChars() : toChars();
+    if (!tempdecl)
+	error("is not defined");
+    else if (tempdecl->parent)
+    {
+	char *p = tempdecl->parent->mangle();
+	if (p[0] == '_' && p[1] == 'D')
+	    p += 2;
+	buf.writestring(p);
+    }
+    buf.printf("%zu%s", strlen(id), id);
+    id = buf.toChars();
+    buf.data = NULL;
+    //printf("TemplateInstance::mangle() %s = %s\n", toChars(), id);
+    return id;
+}
+
+#if IN_LLVM
+char *TemplateMixin::mangle()
+{
+    OutBuffer buf;
+    char *id;
+
+#if 0
+    printf("TemplateMixin::mangle() %s", toChars());
+    if (parent)
+        printf("  parent = %s %s", parent->kind(), parent->toChars());
+    printf("\n");
+#endif
+    id = ident ? ident->toChars() : toChars();
+    if (parent)
+    {
+	char *p = parent->mangle();
+	if (p[0] == '_' && p[1] == 'D')
+	    p += 2;
+	buf.writestring(p);
+    }
+    buf.printf("%zu%s", strlen(id), id);
+    id = buf.toChars();
+    buf.data = NULL;
+    //printf("TemplateMixin::mangle() %s = %s\n", toChars(), id);
+    return id;
+}
+#endif
+
+char *Dsymbol::mangle()
+{
+    OutBuffer buf;
+    char *id;
+
+#if 0
+    printf("Dsymbol::mangle() '%s'", toChars());
+    if (parent)
+	printf("  parent = %s %s", parent->kind(), parent->toChars());
+    printf("\n");
+#endif
+    id = ident ? ident->toChars() : toChars();
+    if (parent)
+    {
+	char *p = parent->mangle();
+	if (p[0] == '_' && p[1] == 'D')
+	    p += 2;
+	buf.writestring(p);
+    }
+    buf.printf("%zu%s", strlen(id), id);
+    id = buf.toChars();
+    buf.data = NULL;
+    //printf("Dsymbol::mangle() %s = %s\n", toChars(), id);
+    return id;
+}
+
+
--- a/dmd2/mars.c	Mon Jun 01 01:28:18 2009 +0200
+++ b/dmd2/mars.c	Mon Jun 01 19:02:20 2009 +0100
@@ -1,278 +1,352 @@
-// Compiler implementation of the D programming language
-// Copyright (c) 1999-2009 by Digital Mars
-// All Rights Reserved
-// written by Walter Bright
-// http://www.digitalmars.com
-// License for redistribution is by either the Artistic License
-// in artistic.txt, or the GNU General Public License in gnu.txt.
-// See the included readme.txt for details.
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <ctype.h>
-#include <assert.h>
-#include <limits.h>
-#include <string>
-#include <cstdarg>
-
-#if __DMC__
-#include <dos.h>
-#endif
-
-#if POSIX
-#include <errno.h>
-#elif _WIN32
-#include <windows.h>
-#endif
-
-#include "mem.h"
-#include "root.h"
-
-#include "mars.h"
-#include "module.h"
-#include "mtype.h"
-#include "id.h"
-#include "cond.h"
-#include "expression.h"
-#include "lexer.h"
-
-#include "revisions.h"
-
-Global global;
-
-Global::Global()
-{
-    mars_ext = "d";
-    sym_ext  = "d";
-    hdr_ext  = "di";
-    doc_ext  = "html";
-    ddoc_ext = "ddoc";
-
-// LDC
-    ll_ext  = "ll";
-    bc_ext  = "bc";
-    s_ext   = "s";
-    obj_ext = "o";
-#if _WIN32
-    obj_ext_alt = "obj";
-#endif
-
-    copyright = "Copyright (c) 1999-2009 by Digital Mars and Tomas Lindquist Olsen";
-    written = "written by Walter Bright and Tomas Lindquist Olsen";
-    version = "v2.021";
-    ldc_version = LDC_REV;
-    llvm_version = LLVM_REV_STR;
-    global.structalign = 8;
-
-    // This should only be used as a global, so the other fields are
-    // automatically initialized to zero when the program is loaded.
-    // In particular, DO NOT zero-initialize .params here (like DMD
-    // does) because command-line options initialize some of those
-    // fields to non-zero defaults, and do so from constructors that
-    // may run before this one.
-}
-
-char *Loc::toChars() const
-{
-    OutBuffer buf;
-
-    if (filename)
-    {
-    buf.printf("%s", filename);
-    }
-
-    if (linnum)
-    buf.printf("(%d)", linnum);
-    buf.writeByte(0);
-    return (char *)buf.extractData();
-}
-
-Loc::Loc(Module *mod, unsigned linnum)
-{
-    this->linnum = linnum;
-    this->filename = mod ? mod->srcfile->toChars() : NULL;
-}
-
-/**************************************
- * Print error message and exit.
- */
-
-void error(Loc loc, const char *format, ...)
-{
-    va_list ap;
-    va_start(ap, format);
-    verror(loc, format, ap);
-    va_end( ap );
-}
-
-void verror(Loc loc, const char *format, va_list ap)
-{
-    if (!global.gag)
-    {
-    char *p = loc.toChars();
-
-    if (*p)
-        fprintf(stdmsg, "%s: ", p);
-    mem.free(p);
-
-    fprintf(stdmsg, "Error: ");
-    vfprintf(stdmsg, format, ap);
-    fprintf(stdmsg, "\n");
-    fflush(stdmsg);
-    }
-    global.errors++;
-}
-
-/***************************************
- * Call this after printing out fatal error messages to clean up and exit
- * the compiler.
- */
-
-void fatal()
-{
-#if 0
-    halt();
-#endif
-    exit(EXIT_FAILURE);
-}
-
-/**************************************
- * Try to stop forgetting to remove the breakpoints from
- * release builds.
- */
-void halt()
-{
-#ifdef DEBUG
-    *(char*)0=0;
-#endif
-}
-
-/***********************************
- * Parse and append contents of environment variable envvar
- * to argc and argv[].
- * The string is separated into arguments, processing \ and ".
- */
-
-void getenv_setargv(const char *envvar, int *pargc, char** *pargv)
-{
-    char *env;
-    char *p;
-    Array *argv;
-    int argc;
-
-    int wildcard;       // do wildcard expansion
-    int instring;
-    int slash;
-    char c;
-    int j;
-
-    env = getenv(envvar);
-    if (!env)
-    return;
-
-    env = mem.strdup(env);  // create our own writable copy
-
-    argc = *pargc;
-    argv = new Array();
-    argv->setDim(argc);
-
-    int argc_left = 0;
-    for (int i = 0; i < argc; i++) {
-        if (!strcmp((*pargv)[i], "-run") || !strcmp((*pargv)[i], "--run")) {
-            // HACK: set flag to indicate we saw '-run' here
-            global.params.run = true;
-            // Don't eat -run yet so the program arguments don't get changed
-            argc_left = argc - i;
-            argc = i;
-            *pargv = &(*pargv)[i];
-            argv->setDim(i);
-            break;
-        } else {
-            argv->data[i] = (void *)(*pargv)[i];
-        }
-    }
-    // HACK to stop required values from command line being drawn from DFLAGS
-    argv->push((char*)"");
-    argc++;
-
-    j = 1;          // leave argv[0] alone
-    while (1)
-    {
-    wildcard = 1;
-    switch (*env)
-    {
-        case ' ':
-        case '\t':
-        env++;
-        break;
-
-        case 0:
-        goto Ldone;
-
-        case '"':
-        wildcard = 0;
-        default:
-        argv->push(env);        // append
-        //argv->insert(j, env);     // insert at position j
-        j++;
-        argc++;
-        p = env;
-        slash = 0;
-        instring = 0;
-        c = 0;
-
-        while (1)
-        {
-            c = *env++;
-            switch (c)
-            {
-            case '"':
-                p -= (slash >> 1);
-                if (slash & 1)
-                {   p--;
-                goto Laddc;
-                }
-                instring ^= 1;
-                slash = 0;
-                continue;
-
-            case ' ':
-            case '\t':
-                if (instring)
-                goto Laddc;
-                *p = 0;
-                //if (wildcard)
-                //wildcardexpand(); // not implemented
-                break;
-
-            case '\\':
-                slash++;
-                *p++ = c;
-                continue;
-
-            case 0:
-                *p = 0;
-                //if (wildcard)
-                //wildcardexpand(); // not implemented
-                goto Ldone;
-
-            default:
-            Laddc:
-                slash = 0;
-                *p++ = c;
-                continue;
-            }
-            break;
-        }
-    }
-    }
-
-Ldone:
-    assert(argc == argv->dim);
-    argv->reserve(argc_left);
-    for (int i = 0; i < argc_left; i++)
-        argv->data[argc++] = (void *)(*pargv)[i];
-
-    *pargc = argc;
-    *pargv = (char **)argv->data;
-}
+
+// Compiler implementation of the D programming language
+// Copyright (c) 1999-2009 by Digital Mars
+// All Rights Reserved
+// written by Walter Bright
+// http://www.digitalmars.com
+// License for redistribution is by either the Artistic License
+// in artistic.txt, or the GNU General Public License in gnu.txt.
+// See the included readme.txt for details.
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <assert.h>
+#include <limits.h>
+#include <string>
+#include <cstdarg>
+
+#if POSIX
+#include <errno.h>
+#elif _WIN32
+#include <windows.h>
+#endif
+
+#include "rmem.h"
+#include "root.h"
+#if !IN_LLVM
+#include "async.h"
+#endif
+
+#include "mars.h"
+#include "module.h"
+#include "mtype.h"
+#include "id.h"
+#include "cond.h"
+#include "expression.h"
+#include "lexer.h"
+#if IN_LLVM
+#include "gen/revisions.h"
+#else
+#include "lib.h"
+
+#if WINDOWS_SEH
+#include <windows.h>
+long __cdecl __ehfilter(LPEXCEPTION_POINTERS ep);
+#endif
+
+
+int response_expand(int *pargc, char ***pargv);
+void browse(const char *url);
+void getenv_setargv(const char *envvar, int *pargc, char** *pargv);
+
+void obj_start(char *srcfile);
+void obj_end(Library *library, File *objfile);
+#endif
+
+Global global;
+
+Global::Global()
+{
+    mars_ext = "d";
+    sym_ext  = "d";
+    hdr_ext  = "di";
+    doc_ext  = "html";
+    ddoc_ext = "ddoc";
+
+#if IN_LLVM
+    ll_ext  = "ll";
+    bc_ext  = "bc";
+    s_ext   = "s";
+    obj_ext = "o";
+#if _WIN32
+    obj_ext_alt = "obj";
+#endif
+#else
+#if TARGET_WINDOS
+    obj_ext  = "obj";
+#elif TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_SOLARIS
+    obj_ext  = "o";
+#elif TARGET_NET
+#else
+#error "fix this"
+#endif
+
+#if TARGET_WINDOS
+    lib_ext  = "lib";
+#elif TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_SOLARIS
+    lib_ext  = "a";
+#elif TARGET_NET
+#else
+#error "fix this"
+#endif
+#endif
+
+    copyright = "Copyright (c) 1999-2009 by Digital Mars";
+    written = "written by Walter Bright"
+#if TARGET_NET
+    "\nMSIL back-end (alpha release) by Cristian L. Vlasceanu and associates.";
+#endif
+    ;
+    version = "v2.030";
+#if IN_LLVM
+    ldc_version = LDC_REV;
+    llvm_version = LLVM_REV_STR;
+#endif
+    global.structalign = 8;
+
+    // This should only be used as a global, so the other fields are
+    // automatically initialized to zero when the program is loaded.
+    // In particular, DO NOT zero-initialize .params here (like DMD
+    // does) because command-line options initialize some of those
+    // fields to non-zero defaults, and do so from constructors that
+    // may run before this one.
+}
+
+char *Loc::toChars()
+{
+    OutBuffer buf;
+
+    if (filename)
+    {
+	buf.printf("%s", filename);
+    }
+
+    if (linnum)
+	buf.printf("(%d)", linnum);
+    buf.writeByte(0);
+    return (char *)buf.extractData();
+}
+
+Loc::Loc(Module *mod, unsigned linnum)
+{
+    this->linnum = linnum;
+    this->filename = mod ? mod->srcfile->toChars() : NULL;
+}
+
+bool Loc::equals(const Loc& loc)
+{
+    return linnum == loc.linnum && FileName::equals(filename, loc.filename);
+}
+
+/**************************************
+ * Print error message and exit.
+ */
+
+void error(Loc loc, const char *format, ...)
+{
+    va_list ap;
+    va_start(ap, format);
+    verror(loc, format, ap);
+    va_end( ap );
+}
+
+void warning(Loc loc, const char *format, ...)
+{
+    if (global.params.warnings && !global.gag)
+    {
+        va_list ap;
+        va_start(ap, format);
+        vwarning(loc, format, ap);
+        va_end( ap );
+    }
+}
+
+void verror(Loc loc, const char *format, va_list ap)
+{
+    if (!global.gag)
+    {
+	char *p = loc.toChars();
+
+	if (*p)
+	    fprintf(stdmsg, "%s: ", p);
+	mem.free(p);
+
+	fprintf(stdmsg, "Error: ");
+	vfprintf(stdmsg, format, ap);
+	fprintf(stdmsg, "\n");
+	fflush(stdmsg);
+    }
+    global.errors++;
+}
+
+void vwarning(Loc loc, const char *format, va_list ap)
+{
+    if (global.params.warnings && !global.gag)
+    {
+        char *p = loc.toChars();
+
+        if (*p)
+            fprintf(stdmsg, "%s: ", p);
+        mem.free(p);
+
+        fprintf(stdmsg, "Warning: ");
+        vfprintf(stdmsg, format, ap);
+        fprintf(stdmsg, "\n");
+        fflush(stdmsg);
+    }
+}
+
+/***************************************
+ * Call this after printing out fatal error messages to clean up and exit
+ * the compiler.
+ */
+
+void fatal()
+{
+#if 0
+    halt();
+#endif
+    exit(EXIT_FAILURE);
+}
+
+/**************************************
+ * Try to stop forgetting to remove the breakpoints from
+ * release builds.
+ */
+void halt()
+{
+#ifdef DEBUG
+    *(char*)0=0;
+#endif
+}
+
+/***********************************
+ * Parse and append contents of environment variable envvar
+ * to argc and argv[].
+ * The string is separated into arguments, processing \ and ".
+ */
+
+void getenv_setargv(const char *envvar, int *pargc, char** *pargv)
+{
+    char *env;
+    char *p;
+    Array *argv;
+    int argc;
+
+    int wildcard;		// do wildcard expansion
+    int instring;
+    int slash;
+    char c;
+    int j;
+
+    env = getenv(envvar);
+    if (!env)
+	return;
+
+    env = mem.strdup(env);	// create our own writable copy
+
+    argc = *pargc;
+    argv = new Array();
+    argv->setDim(argc);
+
+    int argc_left = 0;
+    for (int i = 0; i < argc; i++) {
+        if (!strcmp((*pargv)[i], "-run") || !strcmp((*pargv)[i], "--run")) {
+            // HACK: set flag to indicate we saw '-run' here
+            global.params.run = true;
+            // Don't eat -run yet so the program arguments don't get changed
+            argc_left = argc - i;
+            argc = i;
+            *pargv = &(*pargv)[i];
+            argv->setDim(i);
+            break;
+        } else {
+            argv->data[i] = (void *)(*pargv)[i];
+        }
+    }
+    // HACK to stop required values from command line being drawn from DFLAGS
+    argv->push((char*)"");
+    argc++;
+
+    j = 1;			// leave argv[0] alone
+    while (1)
+    {
+	wildcard = 1;
+	switch (*env)
+	{
+	    case ' ':
+	    case '\t':
+		env++;
+		break;
+
+	    case 0:
+		goto Ldone;
+
+	    case '"':
+		wildcard = 0;
+	    default:
+		argv->push(env);		// append
+		//argv->insert(j, env);		// insert at position j
+		j++;
+		argc++;
+		p = env;
+		slash = 0;
+		instring = 0;
+		c = 0;
+
+		while (1)
+		{
+		    c = *env++;
+		    switch (c)
+		    {
+			case '"':
+			    p -= (slash >> 1);
+			    if (slash & 1)
+			    {	p--;
+				goto Laddc;
+			    }
+			    instring ^= 1;
+			    slash = 0;
+			    continue;
+
+			case ' ':
+			case '\t':
+			    if (instring)
+				goto Laddc;
+			    *p = 0;
+			    //if (wildcard)
+				//wildcardexpand();	// not implemented
+			    break;
+
+			case '\\':
+			    slash++;
+			    *p++ = c;
+			    continue;
+
+			case 0:
+			    *p = 0;
+			    //if (wildcard)
+				//wildcardexpand();	// not implemented
+			    goto Ldone;
+
+			default:
+			Laddc:
+			    slash = 0;
+			    *p++ = c;
+			    continue;
+		    }
+		    break;
+		}
+	}
+    }
+
+Ldone:
+    assert(argc == argv->dim);
+    argv->reserve(argc_left);
+    for (int i = 0; i < argc_left; i++)
+        argv->data[argc++] = (void *)(*pargv)[i];
+
+    *pargc = argc;
+    *pargv = (char **)argv->data;
+}
--- a/dmd2/mars.h	Mon Jun 01 01:28:18 2009 +0200
+++ b/dmd2/mars.h	Mon Jun 01 19:02:20 2009 +0100
@@ -1,353 +1,458 @@
-
-// Compiler implementation of the D programming language
-// Copyright (c) 1999-2007 by Digital Mars
-// All Rights Reserved
-// written by Walter Bright
-// http://www.digitalmars.com
-// License for redistribution is by either the Artistic License
-// in artistic.txt, or the GNU General Public License in gnu.txt.
-// See the included readme.txt for details.
-
-#ifndef DMD_MARS_H
-#define DMD_MARS_H
-
-#ifdef __DMC__
-#pragma once
-#endif /* __DMC__ */
-
-#include <stdint.h>
-#include <stdarg.h>
-#include <stddef.h>
-#define __STDC_FORMAT_MACROS 1
-#include <inttypes.h>
-#include <stdarg.h>
-
-#ifdef __DMC__
-#ifdef DEBUG
-#undef assert
-#define assert(e) (static_cast<void>((e) || (printf("assert %s(%d) %s\n", __FILE__, __LINE__, #e), halt())))
-#endif
-#endif
-
-#ifdef IN_GCC
-/* Changes for the GDC compiler by David Friedman */
-#endif
-
-#define BREAKABI 1  // 0 if not ready to break the ABI just yet
-#define STRUCTTHISREF V2    // if 'this' for struct is a reference, not a pointer
-
-struct Array;
-
-// LDC
-enum ARCH
-{
-    ARCHinvalid,
-    ARCHx86,
-    ARCHx86_64,
-    ARCHppc,
-    ARCHppc_64,
-    ARCHarm,
-    ARCHthumb
-};
-enum OUTPUTFLAG
-{
-    OUTPUTFLAGno,
-    OUTPUTFLAGdefault, // for the .o default
-    OUTPUTFLAGset // for -output
-};
-
-enum OS
-{
-    OSinvalid,
-    OSLinux,
-    OSWindows,
-    OSMacOSX,
-    OSFreeBSD,
-    OSSolaris,
-};
-
-// Put command line switches in here
-struct Param
-{
-    bool obj;           // write object file
-    bool link;          // perform link
-    bool verbose;       // verbose compile
-    char symdebug;  // insert debug symbolic information
-#if !IN_LLVM
-    // LDC uses a different mechanism
-    bool optimize;      // run optimizer
-    char optimizeLevel; // optimization level
-#endif
-    ARCH cpu;       // target CPU
-    OS   os;        // target OS
-    bool is64bit;       // generate 64 bit code
-    bool isLE;          // generate little endian code
-    bool useDeprecated; // allow use of deprecated features
-    bool useAssert;     // generate runtime code for assert()'s
-    bool useInvariants; // generate class invariant checks
-    bool useIn;         // generate precondition checks
-    bool useOut;        // generate postcondition checks
-    bool useArrayBounds; // generate array bounds checks
-    bool useSwitchError; // check for switches without a default
-    bool useUnitTests;  // generate unittest code
-    bool useInline;     // inline expand functions
-    bool warnings;      // enable warnings
-    bool safe;          // enforce safe memory model
-    char Dversion;  // D version number
-
-    char *argv0;    // program name
-    Array *imppath; // array of char*'s of where to look for import modules
-    Array *fileImppath; // array of char*'s of where to look for file import modules
-    char *objdir;   // .obj file output directory
-    char *objname;  // .obj file output name
-
-    bool doDocComments; // process embedded documentation comments
-    char *docdir;   // write documentation file to docdir directory
-    char *docname;  // write documentation file to docname
-    Array *ddocfiles;   // macro include files for Ddoc
-
-    bool doHdrGeneration;       // process embedded documentation comments
-    char *hdrdir;       // write 'header' file to docdir directory
-    char *hdrname;      // write 'header' file to docname
-
-    unsigned debuglevel;    // debug level
-    Array *debugids;        // debug identifiers
-
-    unsigned versionlevel;  // version level
-    Array *versionids;      // version identifiers
-
-    bool dump_source;
-
-    Array *defaultlibnames; // default libraries for non-debug builds
-    Array *debuglibnames;   // default libraries for debug builds
-
-    char *xmlname;      // filename for XML output
-
-    // Hidden debug switches
-    bool debuga;
-    bool debugb;
-    bool debugc;
-    bool debugf;
-    bool debugr;
-    bool debugw;
-    bool debugx;
-    bool debugy;
-
-    bool run;           // run resulting executable
-
-    // Linker stuff
-    Array *objfiles;
-    Array *linkswitches;
-    Array *libfiles;
-    char *deffile;
-    char *resfile;
-    char *exefile;
-
-    // LDC stuff
-    OUTPUTFLAG output_ll;
-    OUTPUTFLAG output_bc;
-    OUTPUTFLAG output_s;
-    OUTPUTFLAG output_o;
-    bool llvmAnnotate;
-    bool useInlineAsm;
-
-    // target stuff
-    const char* llvmArch;
-    const char *targetTriple;
-    const char *dataLayout;
-};
-
-struct Global
-{
-    char *mars_ext;
-    char *sym_ext;
-    char *obj_ext;
-#if _WIN32
-    char *obj_ext_alt;
-#endif
-    char *ll_ext;
-    char *bc_ext;
-    char *s_ext;
-    char *doc_ext;  // for Ddoc generated files
-    char *ddoc_ext; // for Ddoc macro include files
-    char *hdr_ext;  // for D 'header' import files
-    char *copyright;
-    char *written;
-    Array *path;    // Array of char*'s which form the import lookup path
-    Array *filePath;    // Array of char*'s which form the file import lookup path
-    int structalign;
-    char *version;
-    char *ldc_version;
-    char *llvm_version;
-
-    Param params;
-    unsigned errors;    // number of errors reported so far
-    unsigned gag;   // !=0 means gag reporting of errors
-
-    Global();
-};
-
-extern Global global;
-
-/* Set if Windows Structured Exception Handling C extensions are supported.
- * Apparently, VC has dropped support for these?
- */
-#define WINDOWS_SEH (_WIN32 && __DMC__)
-
-
-#if __GNUC__
-//#define memicmp strncasecmp
-//#define stricmp strcasecmp
-#endif
-
-#ifdef __DMC__
- typedef _Complex long double complex_t;
-#else
- #ifndef IN_GCC
-  #include "complex_t.h"
- #endif
- #ifdef __APPLE__
-  //#include "complex.h"//This causes problems with include the c++ <complex> and not the C "complex.h"
-  #define integer_t dmd_integer_t
- #endif
-#endif
-
-// Be careful not to care about sign when using integer_t
-typedef uint64_t integer_t;
-
-// Signed and unsigned variants
-typedef int64_t sinteger_t;
-typedef uint64_t uinteger_t;
-
-typedef int8_t          d_int8;
-typedef uint8_t         d_uns8;
-typedef int16_t         d_int16;
-typedef uint16_t        d_uns16;
-typedef int32_t         d_int32;
-typedef uint32_t        d_uns32;
-typedef int64_t         d_int64;
-typedef uint64_t        d_uns64;
-
-typedef float           d_float32;
-typedef double          d_float64;
-typedef long double     d_float80;
-
-typedef d_uns8          d_char;
-typedef d_uns16         d_wchar;
-typedef d_uns32         d_dchar;
-
-#ifdef IN_GCC
-#include "d-gcc-real.h"
-#else
-typedef long double real_t;
-#endif
-
-// Modify OutBuffer::writewchar to write the correct size of wchar
-#if _WIN32
-#define writewchar writeword
-#else
-// This needs a configuration test...
-#define writewchar write4
-#endif
-
-#ifdef IN_GCC
-#include "d-gcc-complex_t.h"
-#endif
-
-// taken from GDC
-// for handling printf incompatibilities
-#if __MSVCRT__
-#define PRIuSIZE "Iu"
-#define PRIxSIZE "Ix"
-#elif __MINGW32__
-#define PRIuSIZE "u"
-#define PRIxSIZE "x"
-#else
-#define PRIuSIZE "zu"
-#define PRIxSIZE "zx"
-#endif
-
-struct Module;
-
-//typedef unsigned Loc;     // file location
-struct Loc
-{
-    char *filename;
-    unsigned linnum;
-
-    Loc()
-    {
-    linnum = 0;
-    filename = NULL;
-    }
-
-    Loc(int x)
-    {
-    linnum = x;
-    filename = NULL;
-    }
-
-    Loc(Module *mod, unsigned linnum);
-
-    char *toChars() const;
-};
-
-#ifndef GCC_SAFE_DMD
-#define TRUE    1
-#define FALSE   0
-#endif
-
-#define INTERFACE_OFFSET    0   // if 1, put classinfo as first entry
-                    // in interface vtbl[]'s
-#define INTERFACE_VIRTUAL   0   // 1 means if an interface appears
-                    // in the inheritance graph multiple
-                    // times, only one is used
-
-enum LINK
-{
-    LINKdefault,
-    LINKd,
-    LINKc,
-    LINKcpp,
-    LINKwindows,
-    LINKpascal,
-
-    // LDC
-    LINKintrinsic,
-};
-
-enum DYNCAST
-{
-    DYNCAST_OBJECT,
-    DYNCAST_EXPRESSION,
-    DYNCAST_DSYMBOL,
-    DYNCAST_TYPE,
-    DYNCAST_IDENTIFIER,
-    DYNCAST_TUPLE,
-};
-
-enum MATCH
-{
-    MATCHnomatch,   // no match
-    MATCHconvert,   // match with conversions
-#if DMDV2
-    MATCHconst,     // match with conversion to const
-#endif
-    MATCHexact      // exact match
-};
-
-void error(Loc loc, const char *format, ...);
-void verror(Loc loc, const char *format, va_list);
-void fatal();
-void err_nomem();
-void inifile(char *argv0, const char *inifile);
-void halt();
-
-/*** Where to send error messages ***/
-#if IN_GCC || IN_LLVM
-#define stdmsg stderr
-#else
-#define stdmsg stdout
-#endif
-
-#endif /* DMD_MARS_H */
+
+// Compiler implementation of the D programming language
+// Copyright (c) 1999-2009 by Digital Mars
+// All Rights Reserved
+// written by Walter Bright
+// http://www.digitalmars.com
+// License for redistribution is by either the Artistic License
+// in artistic.txt, or the GNU General Public License in gnu.txt.
+// See the included readme.txt for details.
+
+#ifndef DMD_MARS_H
+#define DMD_MARS_H
+
+#ifdef __DMC__
+#pragma once
+#endif
+
+/*
+It is very important to use version control macros correctly - the
+idea is that host and target are independent. If these are done
+correctly, cross compilers can be built.
+The host compiler and host operating system are also different,
+and are predefined by the host compiler. The ones used in
+dmd are:
+
+Macros defined by the compiler, not the code:
+
+    Compiler:
+	__DMC__		Digital Mars compiler
+	_MSC_VER	Microsoft compiler
+	__GNUC__	Gnu compiler
+
+    Host operating system:
+	_WIN32		Microsoft NT, Windows 95, Windows 98, Win32s,
+			Windows 2000, Win XP, Vista
+	_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:
+
+    Target operating system:
+	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
+	TARGET_NET	Covers .Net
+
+    It is expected that the compiler for each platform will be able
+    to generate 32 and 64 bit code from the same compiler binary.
+
+    Target object module format:
+	OMFOBJ		Intel Object Module Format, used on Windows
+	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.
+ */
+
+
+#include <stdio.h>
+#include <stdint.h>
+#include <stdarg.h>
+#include <stddef.h>
+#define __STDC_FORMAT_MACROS 1
+#include <inttypes.h>
+#include <stdarg.h>
+
+#ifdef __DMC__
+#ifdef DEBUG
+#undef assert
+#define assert(e) (static_cast<void>((e) || (printf("assert %s(%d) %s\n", __FILE__, __LINE__, #e), halt())))
+#endif
+#endif
+
+#ifndef IS_PRINTF
+# ifdef __GNUC__
+#  define IS_PRINTF(FMTARG) __attribute((__format__ (__printf__, (FMTARG), (FMTARG)+1) ))
+# else
+#  define IS_PRINTF(FMTARG)
+# endif
+#endif
+
+#ifdef IN_GCC
+/* Changes for the GDC compiler by David Friedman */
+#endif
+
+#define DMDV1	0
+#define DMDV2	1	// Version 2.0 features
+#define BREAKABI 1	// 0 if not ready to break the ABI just yet
+#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, TARGET_OSX, TARGET_FREEBSD and
+ * TARGET_SOLARIS, which are
+ * set on the command line via the compiler makefile.
+ */
+
+#if _WIN32
+#define TARGET_WINDOS 1		// Windows dmd generates Windows targets
+#define OMFOBJ 1
+#endif
+
+#if TARGET_LINUX || TARGET_FREEBSD || TARGET_SOLARIS
+#ifndef ELFOBJ
+#define ELFOBJ 1
+#endif
+#endif
+
+#if TARGET_OSX
+#ifndef MACHOBJ
+#define MACHOBJ 1
+#endif
+#endif
+
+
+struct Array;
+struct OutBuffer;
+
+#if IN_LLVM
+enum ARCH
+{
+    ARCHinvalid,
+    ARCHx86,
+    ARCHx86_64,
+    ARCHppc,
+    ARCHppc_64,
+    ARCHarm,
+    ARCHthumb
+};
+enum OUTPUTFLAG
+{
+    OUTPUTFLAGno,
+    OUTPUTFLAGdefault, // for the .o default
+    OUTPUTFLAGset // for -output
+};
+
+enum OS
+{
+    OSinvalid,
+    OSLinux,
+    OSWindows,
+    OSMacOSX,
+    OSFreeBSD,
+    OSSolaris,
+};
+
+typedef unsigned char ubyte;
+#endif
+
+// Put command line switches in here
+struct Param
+{
+    bool obj;		// write object file
+    bool link;		// perform link
+    bool verbose;	// verbose compile
+    bool vtls;		// identify thread local variables
+    ubyte symdebug;	// insert debug symbolic information
+#if !IN_LLVM
+    // LDC uses a different mechanism
+    bool optimize;      // run optimizer
+    char optimizeLevel; // optimization level
+#endif
+    ARCH cpu;		// target CPU
+    OS   os;
+    bool is64bit;	// generate X86_64 bit code
+    bool isLE;      // generate little endian code
+    bool useDeprecated;	// allow use of deprecated features
+    bool useAssert;	// generate runtime code for assert()'s
+    bool useInvariants;	// generate class invariant checks
+    bool useIn;		// generate precondition checks
+    bool useOut;	// generate postcondition checks
+    bool useArrayBounds; // generate array bounds checks
+    bool useSwitchError; // check for switches without a default
+    bool useUnitTests;	// generate unittest code
+    bool useInline;	// inline expand functions
+    bool warnings;	// enable warnings
+    ubyte Dversion;	// D version number
+    char safe;		// enforce safe memory model
+
+    char *argv0;	// program name
+    Array *imppath;	// array of char*'s of where to look for import modules
+    Array *fileImppath;	// array of char*'s of where to look for file import modules
+    char *objdir;	// .obj file output directory
+    char *objname;	// .obj file output name
+
+    bool doDocComments; // process embedded documentation comments
+    char *docdir;	// write documentation file to docdir directory
+    char *docname;	// write documentation file to docname
+    Array *ddocfiles;	// macro include files for Ddoc
+
+    bool doHdrGeneration;       // process embedded documentation comments
+    char *hdrdir;		// write 'header' file to docdir directory
+    char *hdrname;		// write 'header' file to docname
+
+    unsigned debuglevel;	// debug level
+    Array *debugids;		// debug identifiers
+
+    unsigned versionlevel;	// version level
+    Array *versionids;		// version identifiers
+
+    bool dump_source;
+
+    Array *defaultlibnames;	// default libraries for non-debug builds
+    Array *debuglibnames;	// default libraries for debug builds
+
+    const char *xmlname;	// filename for XML output
+    
+    OutBuffer *moduleDeps;	// buffer and filename for emitting module deps
+    char *moduleDepsFile;
+    
+    // Hidden debug switches
+    bool debuga;
+    bool debugb;
+    bool debugc;
+    bool debugf;
+    bool debugr;
+    bool debugw;
+    bool debugx;
+    bool debugy;
+
+    bool run;           // run resulting executable
+
+    // Linker stuff
+    Array *objfiles;
+    Array *linkswitches;
+    Array *libfiles;
+    char *deffile;
+    char *resfile;
+    char *exefile;
+
+#if IN_LLVM
+    // LDC stuff
+    OUTPUTFLAG output_ll;
+    OUTPUTFLAG output_bc;
+    OUTPUTFLAG output_s;
+    OUTPUTFLAG output_o;
+    bool llvmAnnotate;
+    bool useInlineAsm;
+    bool verbose_cg;
+
+    // target stuff
+    const char* llvmArch;
+    const char *targetTriple;
+    const char *dataLayout;
+#endif
+};
+
+struct Global
+{
+    const char *mars_ext;
+    const char *sym_ext;
+    const char *obj_ext;
+#if IN_LLVM
+#if _WIN32
+    char *obj_ext_alt;
+#endif
+    char *ll_ext;
+    char *bc_ext;
+    char *s_ext;
+#endif
+    const char *lib_ext;
+    const char *doc_ext;	// for Ddoc generated files
+    const char *ddoc_ext;	// for Ddoc macro include files
+    const char *hdr_ext;	// for D 'header' import files
+    const char *copyright;
+    const char *written;
+    Array *path;	// Array of char*'s which form the import lookup path
+    Array *filePath;	// Array of char*'s which form the file import lookup path
+    int structalign;
+    const char *version;
+#if IN_LLVM
+    char *ldc_version;
+    char *llvm_version;
+#endif
+
+    Param params;
+    unsigned errors;	// number of errors reported so far
+    unsigned gag;	// !=0 means gag reporting of errors
+
+    Global();
+};
+
+extern Global global;
+
+/* Set if Windows Structured Exception Handling C extensions are supported.
+ * Apparently, VC has dropped support for these?
+ */
+#define WINDOWS_SEH	(_WIN32 && __DMC__)
+
+
+#ifdef __DMC__
+ typedef _Complex long double complex_t;
+#else
+ #ifndef IN_GCC
+  #include "complex_t.h"
+ #endif
+ #ifdef __APPLE__
+  //#include "complex.h"//This causes problems with include the c++ <complex> and not the C "complex.h"
+ #endif
+#endif
+
+// Be careful not to care about sign when using dinteger_t
+//typedef uint64_t integer_t;
+typedef uint64_t dinteger_t;	// use this instead of integer_t to
+				// avoid conflicts with system #include's
+
+// Signed and unsigned variants
+typedef int64_t sinteger_t;
+typedef uint64_t uinteger_t;
+
+typedef int8_t			d_int8;
+typedef uint8_t			d_uns8;
+typedef int16_t			d_int16;
+typedef uint16_t		d_uns16;
+typedef int32_t			d_int32;
+typedef uint32_t		d_uns32;
+typedef int64_t			d_int64;
+typedef uint64_t		d_uns64;
+
+typedef float			d_float32;
+typedef double			d_float64;
+typedef long double		d_float80;
+
+typedef d_uns8			d_char;
+typedef d_uns16			d_wchar;
+typedef d_uns32			d_dchar;
+
+#ifdef IN_GCC
+#include "d-gcc-real.h"
+#else
+typedef long double real_t;
+#endif
+
+// Modify OutBuffer::writewchar to write the correct size of wchar
+#if _WIN32
+#define writewchar writeword
+#else
+// This needs a configuration test...
+#define writewchar write4
+#endif
+
+#ifdef IN_GCC
+#include "d-gcc-complex_t.h"
+#endif
+
+struct Module;
+
+//typedef unsigned Loc;		// file location
+struct Loc
+{
+    const char *filename;
+    unsigned linnum;
+
+    Loc()
+    {
+	linnum = 0;
+	filename = NULL;
+    }
+
+    Loc(int x)
+    {
+	linnum = x;
+	filename = NULL;
+    }
+
+    Loc(Module *mod, unsigned linnum);
+
+    char *toChars();
+    bool equals(const Loc& loc);
+};
+
+#ifndef GCC_SAFE_DMD
+#define TRUE	1
+#define FALSE	0
+#endif
+
+#define INTERFACE_OFFSET	0	// if 1, put classinfo as first entry
+					// in interface vtbl[]'s
+#define INTERFACE_VIRTUAL	0	// 1 means if an interface appears
+					// in the inheritance graph multiple
+					// times, only one is used
+
+enum LINK
+{
+    LINKdefault,
+    LINKd,
+    LINKc,
+    LINKcpp,
+    LINKwindows,
+    LINKpascal,
+
+#if IN_LLVM
+    LINKintrinsic,
+#endif
+};
+
+enum DYNCAST
+{
+    DYNCAST_OBJECT,
+    DYNCAST_EXPRESSION,
+    DYNCAST_DSYMBOL,
+    DYNCAST_TYPE,
+    DYNCAST_IDENTIFIER,
+    DYNCAST_TUPLE,
+};
+
+enum MATCH
+{
+    MATCHnomatch,	// no match
+    MATCHconvert,	// match with conversions
+#if DMDV2
+    MATCHconst,		// match with conversion to const
+#endif
+    MATCHexact		// exact match
+};
+
+void warning(Loc loc, const char *format, ...) IS_PRINTF(2);
+void vwarning(Loc loc, const char *format, va_list);
+void error(Loc loc, const char *format, ...) IS_PRINTF(2);
+void verror(Loc loc, const char *format, va_list);
+void fatal();
+void err_nomem();
+#if IN_LLVM
+void inifile(char *argv0, const char *inifile);
+#else
+int runLINK();
+void deleteExeFile();
+int runProgram();
+void inifile(const char *argv0, const char *inifile);
+#endif
+void halt();
+#if !IN_LLVM
+void util_progress();
+#endif
+
+/*** Where to send error messages ***/
+#if IN_GCC || IN_LLVM
+#define stdmsg stderr
+#else
+#define stdmsg stdout
+#endif
+
+#if !IN_LLVM
+struct Dsymbol;
+struct Library;
+struct File;
+void obj_start(char *srcfile);
+void obj_end(Library *library, File *objfile);
+void obj_append(Dsymbol *s);
+void obj_write_deferred(Library *library);
+#endif
+
+#endif /* DMD_MARS_H */
--- a/dmd2/mem.c	Mon Jun 01 01:28:18 2009 +0200
+++ b/dmd2/mem.c	Mon Jun 01 19:02:20 2009 +0100
@@ -7,7 +7,7 @@
 #include <cstring>
 #include <cassert>
 
-#include "mem.h"
+#include "rmem.h"
 
 #if USE_BOEHM_GC
     // I needed to perfix the dir after upgrading to gc 7.0
--- a/dmd2/module.c	Mon Jun 01 01:28:18 2009 +0200
+++ b/dmd2/module.c	Mon Jun 01 19:02:20 2009 +0100
@@ -1,992 +1,1163 @@
-
-// Compiler implementation of the D programming language
-// Copyright (c) 1999-2007 by Digital Mars
-// All Rights Reserved
-// written by Walter Bright
-// http://www.digitalmars.com
-// License for redistribution is by either the Artistic License
-// in artistic.txt, or the GNU General Public License in gnu.txt.
-// See the included readme.txt for details.
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <assert.h>
-
-#if _MSC_VER || __MINGW32__
-#include <malloc.h>
-#endif
-
-#if IN_GCC
-#include "gdc_alloca.h"
-#endif
-
-#include "mem.h"
-
-#include "mars.h"
-#include "module.h"
-#include "parse.h"
-#include "scope.h"
-#include "identifier.h"
-#include "id.h"
-#include "import.h"
-#include "dsymbol.h"
-#include "hdrgen.h"
-#include "lexer.h"
-
-#define MARS 1
-#include "html.h"
-
-#ifdef IN_GCC
-#include "d-dmd-gcc.h"
-#endif
-
-
-#include "llvm/Support/CommandLine.h"
-
-static llvm::cl::opt<bool> preservePaths("op",
-    llvm::cl::desc("Do not strip paths from source file"),
-    llvm::cl::ZeroOrMore);
-
-static llvm::cl::opt<bool> fqnNames("oq",
-    llvm::cl::desc("Write object files with fully qualified names"),
-    llvm::cl::ZeroOrMore);
-
-
-
-ClassDeclaration *Module::moduleinfo;
-
-Module *Module::rootModule;
-DsymbolTable *Module::modules;
-Array Module::amodules;
-
-Array Module::deferred;	// deferred Dsymbol's needing semantic() run on them
-unsigned Module::dprogress;
-
-void Module::init()
-{
-    modules = new DsymbolTable();
-}
-
-Module::Module(char *filename, Identifier *ident, int doDocComment, int doHdrGen)
-	: Package(ident)
-{
-    FileName *srcfilename;
-
-//    printf("Module::Module(filename = '%s', ident = '%s')\n", filename, ident->toChars());
-    this->arg = filename;
-    md = NULL;
-    errors = 0;
-    numlines = 0;
-    members = NULL;
-    isHtml = 0;
-    isDocFile = 0;
-    needmoduleinfo = 0;
-#ifdef IN_GCC
-    strictlyneedmoduleinfo = 0;
-#endif
-    insearch = 0;
-    searchCacheIdent = NULL;
-    searchCacheSymbol = NULL;
-    searchCacheFlags = 0;
-    semanticstarted = 0;
-    semanticdone = 0;
-    decldefs = NULL;
-    vmoduleinfo = NULL;
-    massert = NULL;
-    marray = NULL;
-    sictor = NULL;
-    sctor = NULL;
-    sdtor = NULL;
-    stest = NULL;
-    sfilename = NULL;
-    root = 0;
-    importedFrom = NULL;
-    srcfile = NULL;
-    objfile = NULL;
-    docfile = NULL;
-    hdrfile = NULL;
-
-    debuglevel = 0;
-    debugids = NULL;
-    debugidsNot = NULL;
-    versionlevel = 0;
-    versionids = NULL;
-    versionidsNot = NULL;
-
-    macrotable = NULL;
-    escapetable = NULL;
-    safe = FALSE;
-    doppelganger = 0;
-    cov = NULL;
-    covb = NULL;
-
-    srcfilename = FileName::defaultExt(filename, global.mars_ext);
-    if (!srcfilename->equalsExt(global.mars_ext) &&
-        !srcfilename->equalsExt(global.hdr_ext) &&
-        !srcfilename->equalsExt("dd"))
-    {
-	if (srcfilename->equalsExt("html") ||
-	    srcfilename->equalsExt("htm")  ||
-	    srcfilename->equalsExt("xhtml"))
-	{   if (!global.params.useDeprecated)
-		error("html source files is deprecated %s", srcfilename->toChars());
-	    isHtml = 1;
-	}
-	else
-	{   error("source file name '%s' must have .%s extension", srcfilename->toChars(), global.mars_ext);
-	    fatal();
-	}
-    }
-    srcfile = new File(srcfilename);
-
-    // LDC
-    llvmForceLogging = false;
-    this->doDocComment = doDocComment;
-    this->doHdrGen = doHdrGen;
-}
-
-File* Module::buildFilePath(char* forcename, const char* path, const char* ext)
-{
-    char *argobj;
-    if (forcename)
-	argobj = forcename;
-    else
-    {
-	if (preservePaths)
-	    argobj = (char*)this->arg;
-	else
-	    argobj = FileName::name((char*)this->arg);
-
-	if (fqnNames)
-	{
-	    if(md)
-		argobj = FileName::replaceName(argobj, md->toChars());
-	    else
-		argobj = FileName::replaceName(argobj, toChars());
-
-	    // add ext, otherwise forceExt will make nested.module into nested.bc
-	    size_t len = strlen(argobj);
-	    size_t extlen = strlen(ext);
-	    char* s = (char *)alloca(len + 1 + extlen + 1);
-	    memcpy(s, argobj, len);
-	    s[len] = '.';
-	    memcpy(s + len + 1, ext, extlen + 1);
-	    s[len+1+extlen] = 0;
-	    argobj = s;
-	}
-    }
-
-    if (!FileName::absolute(argobj))
-    {
-	argobj = FileName::combine(path, argobj);
-    }
-
-    FileName::ensurePathExists(FileName::path(argobj));
-
-// always append the extension! otherwise hard to make output switches consistent
-//    if (forcename)
-//	return new File(argobj);
-//    else
-    // allow for .o and .obj on windows
-#if _WIN32
-    if (ext == global.params.objdir && FileName::ext(argobj) 
-	    && stricmp(FileName::ext(argobj), global.obj_ext_alt) == 0)
-	return new File(argobj);
-#endif
-    return new File(FileName::forceExt(argobj, ext));
-}
-
-void Module::buildTargetFiles()
-{
-    if(objfile && 
-       (!doDocComment || docfile) && 
-       (!doHdrGen || hdrfile))
-	return;
-
-    if(!objfile)
-	objfile = Module::buildFilePath(global.params.objname, global.params.objdir, global.obj_ext);
-    if(doDocComment && !docfile)
-	docfile = Module::buildFilePath(global.params.docname, global.params.docdir, global.doc_ext);
-    if(doHdrGen && !hdrfile)
-	hdrfile = Module::buildFilePath(global.params.hdrname, global.params.hdrdir, global.hdr_ext);
-
-    // safety check: never allow obj, doc or hdr file to have the source file's name
-    if(stricmp(FileName::name(objfile->name->str), FileName::name((char*)this->arg)) == 0)
-    {
-	error("Output object files with the same name as the source file are forbidden");
-	fatal();
-    }
-    if(docfile && stricmp(FileName::name(docfile->name->str), FileName::name((char*)this->arg)) == 0)
-    {
-	error("Output doc files with the same name as the source file are forbidden");
-	fatal();
-    }
-    if(hdrfile && stricmp(FileName::name(hdrfile->name->str), FileName::name((char*)this->arg)) == 0)
-    {
-	error("Output header files with the same name as the source file are forbidden");
-	fatal();
-    }
-}
-
-void Module::deleteObjFile()
-{
-    if (global.params.obj)
-	objfile->remove();
-    //if (global.params.llvmBC)
-    //bcfile->remove();
-    if (doDocComment && docfile)
-	docfile->remove();
-}
-
-Module::~Module()
-{
-}
-
-const char *Module::kind()
-{
-    return "module";
-}
-
-Module *Module::load(Loc loc, Array *packages, Identifier *ident)
-{   Module *m;
-    char *filename;
-
-    //printf("Module::load(ident = '%s')\n", ident->toChars());
-
-    // Build module filename by turning:
-    //	foo.bar.baz
-    // into:
-    //	foo\bar\baz
-    filename = ident->toChars();
-    if (packages && packages->dim)
-    {
-	OutBuffer buf;
-	int i;
-
-	for (i = 0; i < packages->dim; i++)
-	{   Identifier *pid = (Identifier *)packages->data[i];
-
-	    buf.writestring(pid->toChars());
-#if _WIN32
-	    buf.writeByte('\\');
-#else
-	    buf.writeByte('/');
-#endif
-	}
-	buf.writestring(filename);
-	buf.writeByte(0);
-	filename = (char *)buf.extractData();
-    }
-
-    m = new Module(filename, ident, 0, 0);
-    m->loc = loc;
-
-    /* Search along global.path for .di file, then .d file.
-     */
-    char *result = NULL;
-    FileName *fdi = FileName::forceExt(filename, global.hdr_ext);
-    FileName *fd  = FileName::forceExt(filename, global.mars_ext);
-    char *sdi = fdi->toChars();
-    char *sd  = fd->toChars();
-
-    if (FileName::exists(sdi))
-	result = sdi;
-    else if (FileName::exists(sd))
-	result = sd;
-    else if (FileName::absolute(filename))
-	;
-    else if (!global.path)
-	;
-    else
-    {
-	for (size_t i = 0; i < global.path->dim; i++)
-	{
-	    char *p = (char *)global.path->data[i];
-	    char *n = FileName::combine(p, sdi);
-	    if (FileName::exists(n))
-	    {	result = n;
-		break;
-	    }
-	    mem.free(n);
-	    n = FileName::combine(p, sd);
-	    if (FileName::exists(n))
-	    {	result = n;
-		break;
-	    }
-	    mem.free(n);
-	}
-    }
-    if (result)
-	m->srcfile = new File(result);
-
-    if (global.params.verbose)
-    {
-	printf("import    ");
-	if (packages)
-	{
-	    for (size_t i = 0; i < packages->dim; i++)
-	    {   Identifier *pid = (Identifier *)packages->data[i];
-		printf("%s.", pid->toChars());
-	    }
-	}
-	printf("%s\t(%s)\n", ident->toChars(), m->srcfile->toChars());
-    }
-
-    m->read(loc);
-    m->parse();
-
-#ifdef IN_GCC
-    d_gcc_magic_module(m);
-#endif
-
-    return m;
-}
-
-void Module::read(Loc loc)
-{
-    //printf("Module::read('%s') file '%s'\n", toChars(), srcfile->toChars());
-    if (srcfile->read())
-    {	error(loc, "cannot read file '%s'", srcfile->toChars());
-	fatal();
-    }
-}
-
-inline unsigned readwordLE(unsigned short *p)
-{
-#if __I86__
-    return *p;
-#else
-    return (((unsigned char *)p)[1] << 8) | ((unsigned char *)p)[0];
-#endif
-}
-
-inline unsigned readwordBE(unsigned short *p)
-{
-    return (((unsigned char *)p)[0] << 8) | ((unsigned char *)p)[1];
-}
-
-inline unsigned readlongLE(unsigned *p)
-{
-#if __I86__
-    return *p;
-#else
-    return ((unsigned char *)p)[0] |
-	(((unsigned char *)p)[1] << 8) |
-	(((unsigned char *)p)[2] << 16) |
-	(((unsigned char *)p)[3] << 24);
-#endif
-}
-
-inline unsigned readlongBE(unsigned *p)
-{
-    return ((unsigned char *)p)[3] |
-	(((unsigned char *)p)[2] << 8) |
-	(((unsigned char *)p)[1] << 16) |
-	(((unsigned char *)p)[0] << 24);
-}
-
-#if IN_GCC
-void Module::parse(bool dump_source)
-#else
-void Module::parse()
-#endif
-{   char *srcname;
-    unsigned char *buf;
-    unsigned buflen;
-    unsigned le;
-    unsigned bom;
-
-    //printf("Module::parse()\n");
-
-    srcname = srcfile->name->toChars();
-    //printf("Module::parse(srcname = '%s')\n", srcname);
-
-    buf = srcfile->buffer;
-    buflen = srcfile->len;
-
-    if (buflen >= 2)
-    {
-	/* Convert all non-UTF-8 formats to UTF-8.
-	 * BOM : http://www.unicode.org/faq/utf_bom.html
-	 * 00 00 FE FF	UTF-32BE, big-endian
-	 * FF FE 00 00	UTF-32LE, little-endian
-	 * FE FF	UTF-16BE, big-endian
-	 * FF FE	UTF-16LE, little-endian
-	 * EF BB BF	UTF-8
-	 */
-
-	bom = 1;		// assume there's a BOM
-	if (buf[0] == 0xFF && buf[1] == 0xFE)
-	{
-	    if (buflen >= 4 && buf[2] == 0 && buf[3] == 0)
-	    {	// UTF-32LE
-		le = 1;
-
-	    Lutf32:
-		OutBuffer dbuf;
-		unsigned *pu = (unsigned *)(buf);
-		unsigned *pumax = &pu[buflen / 4];
-
-		if (buflen & 3)
-		{   error("odd length of UTF-32 char source %u", buflen);
-		    fatal();
-		}
-
-		dbuf.reserve(buflen / 4);
-		for (pu += bom; pu < pumax; pu++)
-		{   unsigned u;
-
-		    u = le ? readlongLE(pu) : readlongBE(pu);
-		    if (u & ~0x7F)
-		    {
-			if (u > 0x10FFFF)
-			{   error("UTF-32 value %08x greater than 0x10FFFF", u);
-			    fatal();
-			}
-			dbuf.writeUTF8(u);
-		    }
-		    else
-			dbuf.writeByte(u);
-		}
-		dbuf.writeByte(0);		// add 0 as sentinel for scanner
-		buflen = dbuf.offset - 1;	// don't include sentinel in count
-		buf = (unsigned char *) dbuf.extractData();
-	    }
-	    else
-	    {   // UTF-16LE (X86)
-		// Convert it to UTF-8
-		le = 1;
-
-	    Lutf16:
-		OutBuffer dbuf;
-		unsigned short *pu = (unsigned short *)(buf);
-		unsigned short *pumax = &pu[buflen / 2];
-
-		if (buflen & 1)
-		{   error("odd length of UTF-16 char source %u", buflen);
-		    fatal();
-		}
-
-		dbuf.reserve(buflen / 2);
-		for (pu += bom; pu < pumax; pu++)
-		{   unsigned u;
-
-		    u = le ? readwordLE(pu) : readwordBE(pu);
-		    if (u & ~0x7F)
-		    {	if (u >= 0xD800 && u <= 0xDBFF)
-			{   unsigned u2;
-
-			    if (++pu > pumax)
-			    {   error("surrogate UTF-16 high value %04x at EOF", u);
-				fatal();
-			    }
-			    u2 = le ? readwordLE(pu) : readwordBE(pu);
-			    if (u2 < 0xDC00 || u2 > 0xDFFF)
-			    {   error("surrogate UTF-16 low value %04x out of range", u2);
-				fatal();
-			    }
-			    u = (u - 0xD7C0) << 10;
-			    u |= (u2 - 0xDC00);
-			}
-			else if (u >= 0xDC00 && u <= 0xDFFF)
-			{   error("unpaired surrogate UTF-16 value %04x", u);
-			    fatal();
-			}
-			else if (u == 0xFFFE || u == 0xFFFF)
-			{   error("illegal UTF-16 value %04x", u);
-			    fatal();
-			}
-			dbuf.writeUTF8(u);
-		    }
-		    else
-			dbuf.writeByte(u);
-		}
-		dbuf.writeByte(0);		// add 0 as sentinel for scanner
-		buflen = dbuf.offset - 1;	// don't include sentinel in count
-		buf = (unsigned char *) dbuf.extractData();
-	    }
-	}
-	else if (buf[0] == 0xFE && buf[1] == 0xFF)
-	{   // UTF-16BE
-	    le = 0;
-	    goto Lutf16;
-	}
-	else if (buflen >= 4 && buf[0] == 0 && buf[1] == 0 && buf[2] == 0xFE && buf[3] == 0xFF)
-	{   // UTF-32BE
-	    le = 0;
-	    goto Lutf32;
-	}
-	else if (buflen >= 3 && buf[0] == 0xEF && buf[1] == 0xBB && buf[2] == 0xBF)
-	{   // UTF-8
-
-	    buf += 3;
-	    buflen -= 3;
-	}
-	else
-	{
-	    /* There is no BOM. Make use of Arcane Jill's insight that
-	     * the first char of D source must be ASCII to
-	     * figure out the encoding.
-	     */
-
-	    bom = 0;
-	    if (buflen >= 4)
-	    {   if (buf[1] == 0 && buf[2] == 0 && buf[3] == 0)
-		{   // UTF-32LE
-		    le = 1;
-		    goto Lutf32;
-		}
-		else if (buf[0] == 0 && buf[1] == 0 && buf[2] == 0)
-		{   // UTF-32BE
-		    le = 0;
-		    goto Lutf32;
-		}
-	    }
-	    if (buflen >= 2)
-	    {
-		if (buf[1] == 0)
-		{   // UTF-16LE
-		    le = 1;
-		    goto Lutf16;
-		}
-		else if (buf[0] == 0)
-		{   // UTF-16BE
-		    le = 0;
-		    goto Lutf16;
-		}
-	    }
-
-	    // It's UTF-8
-	    if (buf[0] >= 0x80)
-	    {	error("source file must start with BOM or ASCII character, not \\x%02X", buf[0]);
-		fatal();
-	    }
-	}
-    }
-
-#ifdef IN_GCC
-    // dump utf-8 encoded source
-    if (dump_source)
-    {	// %% srcname could contain a path ...
-	d_gcc_dump_source(srcname, "utf-8", buf, buflen);
-    }
-#endif
-
-    /* If it starts with the string "Ddoc", then it's a documentation
-     * source file.
-     */
-    if (buflen >= 4 && memcmp(buf, "Ddoc", 4) == 0)
-    {
-	comment = buf + 4;
-	isDocFile = 1;
-	return;
-    }
-    if (isHtml)
-    {
-	OutBuffer *dbuf = new OutBuffer();
-	Html h(srcname, buf, buflen);
-	h.extractCode(dbuf);
-	buf = dbuf->data;
-	buflen = dbuf->offset;
-#ifdef IN_GCC
-	// dump extracted source
-	if (dump_source)
-	    d_gcc_dump_source(srcname, "d.utf-8", buf, buflen);
-#endif
-    }
-    Parser p(this, buf, buflen, docfile != NULL);
-    p.nextToken();
-    members = p.parseModule();
-    md = p.md;
-    numlines = p.loc.linnum;
-
-    DsymbolTable *dst;
-
-    if (md)
-    {	this->ident = md->id;
-	this->safe = md->safe;
-	dst = Package::resolve(md->packages, &this->parent, NULL);
-    }
-    else
-    {
-	dst = modules;
-
-	/* Check to see if module name is a valid identifier
-	 */
-	if (!Lexer::isValidIdentifier(this->ident->toChars()))
-	    error("has non-identifier characters in filename, use module declaration instead");
-    }
-
-    // Update global list of modules
-    if (!dst->insert(this))
-    {
-	if (md)
-	    error(loc, "is in multiple packages %s", md->toChars());
-	else
-	    error(loc, "is in multiple defined");
-    }
-    else
-    {
-	amodules.push(this);
-    }
-}
-
-void Module::semantic(Scope* unused_sc)
-{   int i;
-
-    if (semanticstarted)
-	return;
-
-    //printf("+Module::semantic(this = %p, '%s'): parent = %p\n", this, toChars(), parent);
-    semanticstarted = 1;
-
-    // Note that modules get their own scope, from scratch.
-    // This is so regardless of where in the syntax a module
-    // gets imported, it is unaffected by context.
-    Scope *sc = Scope::createGlobal(this);	// create root scope
-
-    //printf("Module = %p, linkage = %d\n", sc->scopesym, sc->linkage);
-
-    // Add import of "object" if this module isn't "object"
-    if (ident != Id::object)
-    {
-	Import *im = new Import(0, NULL, Id::object, NULL, 0);
-	members->shift(im);
-    }
-
-    // Add all symbols into module's symbol table
-    symtab = new DsymbolTable();
-    for (i = 0; i < members->dim; i++)
-    {	Dsymbol *s;
-
-	s = (Dsymbol *)members->data[i];
-	s->addMember(NULL, sc->scopesym, 1);
-    }
-
-    // Pass 1 semantic routines: do public side of the definition
-    for (i = 0; i < members->dim; i++)
-    {	Dsymbol *s;
-
-	s = (Dsymbol *)members->data[i];
-	//printf("\tModule('%s'): '%s'.semantic()\n", toChars(), s->toChars());
-	s->semantic(sc);
-	runDeferredSemantic();
-    }
-
-    sc = sc->pop();
-    sc->pop();
-    semanticdone = semanticstarted;
-    //printf("-Module::semantic(this = %p, '%s'): parent = %p\n", this, toChars(), parent);
-}
-
-void Module::semantic2(Scope* unused_sc)
-{   int i;
-
-    if (deferred.dim)
-    {
-	for (int i = 0; i < deferred.dim; i++)
-	{
-	    Dsymbol *sd = (Dsymbol *)deferred.data[i];
-
-	    sd->error("unable to resolve forward reference in definition");
-	}
-	return;
-    }
-    //printf("Module::semantic2('%s'): parent = %p\n", toChars(), parent);
-    if (semanticstarted >= 2)
-	return;
-    assert(semanticstarted == 1);
-    semanticstarted = 2;
-
-    // Note that modules get their own scope, from scratch.
-    // This is so regardless of where in the syntax a module
-    // gets imported, it is unaffected by context.
-    Scope *sc = Scope::createGlobal(this);	// create root scope
-    //printf("Module = %p\n", sc.scopesym);
-
-    // Pass 2 semantic routines: do initializers and function bodies
-    for (i = 0; i < members->dim; i++)
-    {	Dsymbol *s;
-
-	s = (Dsymbol *)members->data[i];
-	s->semantic2(sc);
-    }
-
-    sc = sc->pop();
-    sc->pop();
-    semanticdone = semanticstarted;
-    //printf("-Module::semantic2('%s'): parent = %p\n", toChars(), parent);
-}
-
-void Module::semantic3(Scope* unused_sc)
-{   int i;
-
-    //printf("Module::semantic3('%s'): parent = %p\n", toChars(), parent);
-    if (semanticstarted >= 3)
-	return;
-    assert(semanticstarted == 2);
-    semanticstarted = 3;
-
-    // Note that modules get their own scope, from scratch.
-    // This is so regardless of where in the syntax a module
-    // gets imported, it is unaffected by context.
-    Scope *sc = Scope::createGlobal(this);	// create root scope
-    //printf("Module = %p\n", sc.scopesym);
-
-    // Pass 3 semantic routines: do initializers and function bodies
-    for (i = 0; i < members->dim; i++)
-    {	Dsymbol *s;
-
-	s = (Dsymbol *)members->data[i];
-	//printf("Module %s: %s.semantic3()\n", toChars(), s->toChars());
-	s->semantic3(sc);
-    }
-
-    sc = sc->pop();
-    sc->pop();
-    semanticdone = semanticstarted;
-}
-
-void Module::inlineScan()
-{   int i;
-
-    if (semanticstarted >= 4)
-	return;
-    assert(semanticstarted == 3);
-    semanticstarted = 4;
-
-    // Note that modules get their own scope, from scratch.
-    // This is so regardless of where in the syntax a module
-    // gets imported, it is unaffected by context.
-    //printf("Module = %p\n", sc.scopesym);
-
-    for (i = 0; i < members->dim; i++)
-    {	Dsymbol *s;
-
-	s = (Dsymbol *)members->data[i];
-	//if (global.params.verbose)
-	    //printf("inline scan symbol %s\n", s->toChars());
-
-	s->inlineScan();
-    }
-    semanticdone = semanticstarted;
-}
-
-/****************************************************
- */
-
-// is this used anywhere?
-/*
-void Module::gensymfile()
-{
-    OutBuffer buf;
-    HdrGenState hgs;
-
-    //printf("Module::gensymfile()\n");
-
-    buf.printf("// Sym file generated from '%s'", srcfile->toChars());
-    buf.writenl();
-
-    for (int i = 0; i < members->dim; i++)
-    {	Dsymbol *s = (Dsymbol *)members->data[i];
-
-	s->toCBuffer(&buf, &hgs);
-    }
-
-    // Transfer image to file
-    symfile->setbuffer(buf.data, buf.offset);
-    buf.data = NULL;
-
-    symfile->writev();
-}*/
-
-/**********************************
- * Determine if we need to generate an instance of ModuleInfo
- * for this Module.
- */
-
-int Module::needModuleInfo()
-{
-    return needmoduleinfo;
-}
-
-Dsymbol *Module::search(Loc loc, Identifier *ident, int flags)
-{
-    /* Since modules can be circularly referenced,
-     * need to stop infinite recursive searches.
-     */
-
-    //printf("%s Module::search('%s', flags = %d) insearch = %d\n", toChars(), ident->toChars(), flags, insearch);
-    Dsymbol *s;
-    if (insearch)
-	s = NULL;
-    else if (searchCacheIdent == ident && searchCacheFlags == flags)
-	s = searchCacheSymbol;
-    else
-    {
-	insearch = 1;
-	s = ScopeDsymbol::search(loc, ident, flags);
-	insearch = 0;
-
-	searchCacheIdent = ident;
-	searchCacheSymbol = s;
-	searchCacheFlags = flags;
-    }
-    return s;
-}
-
-/*******************************************
- * Can't run semantic on s now, try again later.
- */
-
-void Module::addDeferredSemantic(Dsymbol *s)
-{
-    // Don't add it if it is already there
-    for (int i = 0; i < deferred.dim; i++)
-    {
-	Dsymbol *sd = (Dsymbol *)deferred.data[i];
-
-	if (sd == s)
-	    return;
-    }
-
-    //printf("Module::addDeferredSemantic('%s')\n", s->toChars());
-    deferred.push(s);
-}
-
-
-/******************************************
- * Run semantic() on deferred symbols.
- */
-
-void Module::runDeferredSemantic()
-{
-    size_t len;
-
-    static int nested;
-    if (nested)
-	return;
-    //if (deferred.dim) printf("+Module::runDeferredSemantic('%s'), len = %d\n", toChars(), deferred.dim);
-    nested++;
-
-    do
-    {
-	dprogress = 0;
-	len = deferred.dim;
-	if (!len)
-	    break;
-
-	Dsymbol **todo;
-	Dsymbol *tmp;
-	if (len == 1)
-	{
-	    todo = &tmp;
-	}
-	else
-	{
-	    todo = (Dsymbol **)alloca(len * sizeof(Dsymbol *));
-	    assert(todo);
-	}
-	memcpy(todo, deferred.data, len * sizeof(Dsymbol *));
-	deferred.setDim(0);
-
-	for (int i = 0; i < len; i++)
-	{
-	    Dsymbol *s = todo[i];
-
-	    s->semantic(NULL);
-	    //printf("deferred: %s, parent = %s\n", s->toChars(), s->parent->toChars());
-	}
-	//printf("\tdeferred.dim = %d, len = %d, dprogress = %d\n", deferred.dim, len, dprogress);
-    } while (deferred.dim < len || dprogress);	// while making progress
-    nested--;
-    //printf("-Module::runDeferredSemantic('%s'), len = %d\n", toChars(), deferred.dim);
-}
-
-/* =========================== ModuleDeclaration ===================== */
-
-ModuleDeclaration::ModuleDeclaration(Array *packages, Identifier *id, bool safe)
-{
-    this->packages = packages;
-    this->id = id;
-    this->safe = safe;
-}
-
-char *ModuleDeclaration::toChars()
-{
-    OutBuffer buf;
-    int i;
-
-    if (packages && packages->dim)
-    {
-	for (i = 0; i < packages->dim; i++)
-	{   Identifier *pid = (Identifier *)packages->data[i];
-
-	    buf.writestring(pid->toChars());
-	    buf.writeByte('.');
-	}
-    }
-    buf.writestring(id->toChars());
-    buf.writeByte(0);
-    return (char *)buf.extractData();
-}
-
-/* =========================== Package ===================== */
-
-Package::Package(Identifier *ident)
-	: ScopeDsymbol(ident)
-{
-}
-
-
-const char *Package::kind()
-{
-    return "package";
-}
-
-
-DsymbolTable *Package::resolve(Array *packages, Dsymbol **pparent, Package **ppkg)
-{
-    DsymbolTable *dst = Module::modules;
-    Dsymbol *parent = NULL;
-
-    //printf("Package::resolve()\n");
-    if (ppkg)
-	*ppkg = NULL;
-
-    if (packages)
-    {   int i;
-
-	for (i = 0; i < packages->dim; i++)
-	{   Identifier *pid = (Identifier *)packages->data[i];
-	    Dsymbol *p;
-
-	    p = dst->lookup(pid);
-	    if (!p)
-	    {
-		p = new Package(pid);
-		dst->insert(p);
-		p->parent = parent;
-		((ScopeDsymbol *)p)->symtab = new DsymbolTable();
-	    }
-	    else
-	    {
-		assert(p->isPackage());
-		if (p->isModule())
-		{   p->error("module and package have the same name");
-		    fatal();
-		    break;
-		}
-	    }
-	    parent = p;
-	    dst = ((Package *)p)->symtab;
-	    if (ppkg && !*ppkg)
-		*ppkg = (Package *)p;
-	}
-	if (pparent)
-	{
-	    *pparent = parent;
-	}
-    }
-    return dst;
-}
+
+// Compiler implementation of the D programming language
+// Copyright (c) 1999-2009 by Digital Mars
+// All Rights Reserved
+// written by Walter Bright
+// http://www.digitalmars.com
+// License for redistribution is by either the Artistic License
+// in artistic.txt, or the GNU General Public License in gnu.txt.
+// See the included readme.txt for details.
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+
+#if (defined (__SVR4) && defined (__sun))
+#include <alloca.h>
+#endif
+
+#if defined(_MSC_VER) || defined(__MINGW32__)
+#include <malloc.h>
+#endif
+
+#if IN_GCC
+#include "gdc_alloca.h"
+#endif
+
+#include "rmem.h"
+
+#include "mars.h"
+#include "module.h"
+#include "parse.h"
+#include "scope.h"
+#include "identifier.h"
+#include "id.h"
+#include "import.h"
+#include "dsymbol.h"
+#include "hdrgen.h"
+#include "lexer.h"
+
+#define MARS 1
+#include "html.h"
+
+#ifdef IN_GCC
+#include "d-dmd-gcc.h"
+#endif
+
+#if IN_LLVM
+#include "llvm/Support/CommandLine.h"
+
+static llvm::cl::opt<bool> preservePaths("op",
+    llvm::cl::desc("Do not strip paths from source file"),
+    llvm::cl::ZeroOrMore);
+
+static llvm::cl::opt<bool> fqnNames("oq",
+    llvm::cl::desc("Write object files with fully qualified names"),
+    llvm::cl::ZeroOrMore);
+#endif
+
+ClassDeclaration *Module::moduleinfo;
+
+Module *Module::rootModule;
+DsymbolTable *Module::modules;
+Array Module::amodules;
+
+Array Module::deferred;	// deferred Dsymbol's needing semantic() run on them
+unsigned Module::dprogress;
+
+void Module::init()
+{
+    modules = new DsymbolTable();
+}
+
+Module::Module(char *filename, Identifier *ident, int doDocComment, int doHdrGen)
+	: Package(ident)
+{
+    FileName *srcfilename;
+#if IN_DMD
+    FileName *cfilename;
+    FileName *hfilename;
+    FileName *objfilename;
+    FileName *symfilename;
+#endif
+
+//    printf("Module::Module(filename = '%s', ident = '%s')\n", filename, ident->toChars());
+    this->arg = filename;
+    md = NULL;
+    errors = 0;
+    numlines = 0;
+    members = NULL;
+    isHtml = 0;
+    isDocFile = 0;
+    needmoduleinfo = 0;
+#ifdef IN_GCC
+    strictlyneedmoduleinfo = 0;
+#endif
+    selfimports = 0;
+    insearch = 0;
+    searchCacheIdent = NULL;
+    searchCacheSymbol = NULL;
+    searchCacheFlags = 0;
+    semanticstarted = 0;
+    semanticdone = 0;
+    decldefs = NULL;
+    vmoduleinfo = NULL;
+#if IN_DMD
+    massert = NULL;
+    marray = NULL;
+    sictor = NULL;
+    sctor = NULL;
+    sdtor = NULL;
+    stest = NULL;
+    sfilename = NULL;
+#endif
+    root = 0;
+    importedFrom = NULL;
+    srcfile = NULL;
+    objfile = NULL;
+    docfile = NULL;
+    hdrfile = NULL;
+
+    debuglevel = 0;
+    debugids = NULL;
+    debugidsNot = NULL;
+    versionlevel = 0;
+    versionids = NULL;
+    versionidsNot = NULL;
+
+    macrotable = NULL;
+    escapetable = NULL;
+    safe = FALSE;
+#if IN-DMD
+    doppelganger = 0;
+    cov = NULL;
+    covb = NULL;
+#endif
+
+    srcfilename = FileName::defaultExt(filename, global.mars_ext);
+    if (!srcfilename->equalsExt(global.mars_ext) &&
+        !srcfilename->equalsExt(global.hdr_ext) &&
+        !srcfilename->equalsExt("dd"))
+    {
+	if (srcfilename->equalsExt("html") ||
+	    srcfilename->equalsExt("htm")  ||
+	    srcfilename->equalsExt("xhtml"))
+	{   if (!global.params.useDeprecated)
+		error("html source files is deprecated %s", srcfilename->toChars());
+	    isHtml = 1;
+	}
+	else
+	{   error("source file name '%s' must have .%s extension", srcfilename->toChars(), global.mars_ext);
+	    fatal();
+	}
+    }
+#if !IN_LLVM
+    char *argobj;
+    if (global.params.objname)
+	argobj = global.params.objname;
+    else if (global.params.preservePaths)
+	argobj = filename;
+    else
+	argobj = FileName::name(filename);
+    if (!FileName::absolute(argobj))
+    {
+	argobj = FileName::combine(global.params.objdir, argobj);
+    }
+
+    if (global.params.objname)
+	objfilename = new FileName(argobj, 0);
+    else
+	objfilename = FileName::forceExt(argobj, global.obj_ext);
+
+    symfilename = FileName::forceExt(filename, global.sym_ext);
+#endif
+
+    srcfile = new File(srcfilename);
+#if IN_DMD
+    if (doDocComment)
+    {
+	setDocfile();
+    }
+
+    if (doHdrGen)
+    {
+	setHdrfile();
+    }
+
+    objfile = new File(objfilename);
+    symfile = new File(symfilename);
+#endif
+#if IN_LLVM
+    // LDC
+    llvmForceLogging = false;
+    this->doDocComment = doDocComment;
+    this->doHdrGen = doHdrGen;
+#endif
+}
+#if IN_LLVM
+File* Module::buildFilePath(const char* forcename, const char* path, const char* ext)
+{
+    const char *argobj;
+    if (forcename)
+	argobj = forcename;
+    else
+    {
+	if (preservePaths)
+	    argobj = (char*)this->arg;
+	else
+	    argobj = FileName::name((char*)this->arg);
+
+	if (fqnNames)
+	{
+	    if(md)
+		argobj = FileName::replaceName((char*)argobj, md->toChars());
+	    else
+		argobj = FileName::replaceName((char*)argobj, toChars());
+
+	    // add ext, otherwise forceExt will make nested.module into nested.bc
+	    size_t len = strlen(argobj);
+	    size_t extlen = strlen(ext);
+	    char* s = (char *)alloca(len + 1 + extlen + 1);
+	    memcpy(s, argobj, len);
+	    s[len] = '.';
+	    memcpy(s + len + 1, ext, extlen + 1);
+	    s[len+1+extlen] = 0;
+	    argobj = s;
+	}
+    }
+
+    if (!FileName::absolute(argobj))
+    {
+	argobj = FileName::combine(path, argobj);
+    }
+
+    FileName::ensurePathExists(FileName::path(argobj));
+
+// always append the extension! otherwise hard to make output switches consistent
+//    if (forcename)
+//	return new File(argobj);
+//    else
+    // allow for .o and .obj on windows
+#if _WIN32
+    if (ext == global.params.objdir && FileName::ext(argobj) 
+	    && stricmp(FileName::ext(argobj), global.obj_ext_alt) == 0)
+	return new File((char*)argobj);
+#endif
+    return new File(FileName::forceExt(argobj, ext));
+}
+#endif
+#if IN_DMD
+void Module::setDocfile()
+{
+    FileName *docfilename;
+    char *argdoc;
+
+    if (global.params.docname)
+	argdoc = global.params.docname;
+    else if (global.params.preservePaths)
+	argdoc = (char *)arg;
+    else
+	argdoc = FileName::name((char *)arg);
+    if (!FileName::absolute(argdoc))
+    {	//FileName::ensurePathExists(global.params.docdir);
+	argdoc = FileName::combine(global.params.docdir, argdoc);
+    }
+    if (global.params.docname)
+	docfilename = new FileName(argdoc, 0);
+    else
+	docfilename = FileName::forceExt(argdoc, global.doc_ext);
+
+    if (docfilename->equals(srcfile->name))
+    {   error("Source file and documentation file have same name '%s'", srcfile->name->str);
+	fatal();
+    }
+
+    docfile = new File(docfilename);
+}
+
+void Module::setHdrfile()
+{
+    FileName *hdrfilename;
+    char *arghdr;
+
+    if (global.params.hdrname)
+	arghdr = global.params.hdrname;
+    else if (global.params.preservePaths)
+	arghdr = (char *)arg;
+    else
+	arghdr = FileName::name((char *)arg);
+    if (!FileName::absolute(arghdr))
+    {	//FileName::ensurePathExists(global.params.hdrdir);
+	arghdr = FileName::combine(global.params.hdrdir, arghdr);
+    }
+    if (global.params.hdrname)
+	hdrfilename = new FileName(arghdr, 0);
+    else
+	hdrfilename = FileName::forceExt(arghdr, global.hdr_ext);
+
+    if (hdrfilename->equals(srcfile->name))
+    {   error("Source file and 'header' file have same name '%s'", srcfile->name->str);
+	fatal();
+    }
+
+    hdrfile = new File(hdrfilename);
+}
+#endif
+
+#if IN_LLVM
+void Module::buildTargetFiles()
+{
+    if(objfile && 
+       (!doDocComment || docfile) && 
+       (!doHdrGen || hdrfile))
+	return;
+
+    if(!objfile)
+	objfile = Module::buildFilePath(global.params.objname, global.params.objdir, global.obj_ext);
+    if(doDocComment && !docfile)
+	docfile = Module::buildFilePath(global.params.docname, global.params.docdir, global.doc_ext);
+    if(doHdrGen && !hdrfile)
+	hdrfile = Module::buildFilePath(global.params.hdrname, global.params.hdrdir, global.hdr_ext);
+
+    // safety check: never allow obj, doc or hdr file to have the source file's name
+    if(stricmp(FileName::name(objfile->name->str), FileName::name((char*)this->arg)) == 0)
+    {
+	error("Output object files with the same name as the source file are forbidden");
+	fatal();
+    }
+    if(docfile && stricmp(FileName::name(docfile->name->str), FileName::name((char*)this->arg)) == 0)
+    {
+	error("Output doc files with the same name as the source file are forbidden");
+	fatal();
+    }
+    if(hdrfile && stricmp(FileName::name(hdrfile->name->str), FileName::name((char*)this->arg)) == 0)
+    {
+	error("Output header files with the same name as the source file are forbidden");
+	fatal();
+    }
+}
+#endif
+void Module::deleteObjFile()
+{
+    if (global.params.obj)
+	objfile->remove();
+    //if (global.params.llvmBC)
+    //bcfile->remove();
+    if (doDocComment && docfile)
+	docfile->remove();
+}
+
+Module::~Module()
+{
+}
+
+const char *Module::kind()
+{
+    return "module";
+}
+
+Module *Module::load(Loc loc, Array *packages, Identifier *ident)
+{   Module *m;
+    char *filename;
+
+    //printf("Module::load(ident = '%s')\n", ident->toChars());
+
+    // Build module filename by turning:
+    //	foo.bar.baz
+    // into:
+    //	foo\bar\baz
+    filename = ident->toChars();
+    if (packages && packages->dim)
+    {
+	OutBuffer buf;
+	int i;
+
+	for (i = 0; i < packages->dim; i++)
+	{   Identifier *pid = (Identifier *)packages->data[i];
+
+	    buf.writestring(pid->toChars());
+#if _WIN32
+	    buf.writeByte('\\');
+#else
+	    buf.writeByte('/');
+#endif
+	}
+	buf.writestring(filename);
+	buf.writeByte(0);
+	filename = (char *)buf.extractData();
+    }
+
+    m = new Module(filename, ident, 0, 0);
+    m->loc = loc;
+
+    /* Search along global.path for .di file, then .d file.
+     */
+    char *result = NULL;
+    FileName *fdi = FileName::forceExt(filename, global.hdr_ext);
+    FileName *fd  = FileName::forceExt(filename, global.mars_ext);
+    char *sdi = fdi->toChars();
+    char *sd  = fd->toChars();
+
+    if (FileName::exists(sdi))
+	result = sdi;
+    else if (FileName::exists(sd))
+	result = sd;
+    else if (FileName::absolute(filename))
+	;
+    else if (!global.path)
+	;
+    else
+    {
+	for (size_t i = 0; i < global.path->dim; i++)
+	{
+	    char *p = (char *)global.path->data[i];
+	    char *n = FileName::combine(p, sdi);
+	    if (FileName::exists(n))
+	    {	result = n;
+		break;
+	    }
+	    mem.free(n);
+	    n = FileName::combine(p, sd);
+	    if (FileName::exists(n))
+	    {	result = n;
+		break;
+	    }
+	    mem.free(n);
+	}
+    }
+    if (result)
+	m->srcfile = new File(result);
+
+    if (global.params.verbose)
+    {
+	printf("import    ");
+	if (packages)
+	{
+	    for (size_t i = 0; i < packages->dim; i++)
+	    {   Identifier *pid = (Identifier *)packages->data[i];
+		printf("%s.", pid->toChars());
+	    }
+	}
+	printf("%s\t(%s)\n", ident->toChars(), m->srcfile->toChars());
+    }
+
+    m->read(loc);
+    m->parse();
+
+#ifdef IN_GCC
+    d_gcc_magic_module(m);
+#endif
+
+    return m;
+}
+
+void Module::read(Loc loc)
+{
+    //printf("Module::read('%s') file '%s'\n", toChars(), srcfile->toChars());
+    if (srcfile->read())
+    {	error(loc, "cannot read file '%s'", srcfile->toChars());
+	fatal();
+    }
+}
+
+inline unsigned readwordLE(unsigned short *p)
+{
+#if __I86__
+    return *p;
+#else
+    return (((unsigned char *)p)[1] << 8) | ((unsigned char *)p)[0];
+#endif
+}
+
+inline unsigned readwordBE(unsigned short *p)
+{
+    return (((unsigned char *)p)[0] << 8) | ((unsigned char *)p)[1];
+}
+
+inline unsigned readlongLE(unsigned *p)
+{
+#if __I86__
+    return *p;
+#else
+    return ((unsigned char *)p)[0] |
+	(((unsigned char *)p)[1] << 8) |
+	(((unsigned char *)p)[2] << 16) |
+	(((unsigned char *)p)[3] << 24);
+#endif
+}
+
+inline unsigned readlongBE(unsigned *p)
+{
+    return ((unsigned char *)p)[3] |
+	(((unsigned char *)p)[2] << 8) |
+	(((unsigned char *)p)[1] << 16) |
+	(((unsigned char *)p)[0] << 24);
+}
+
+#if IN_GCC
+void Module::parse(bool dump_source)
+#else
+void Module::parse()
+#endif
+{   char *srcname;
+    unsigned char *buf;
+    unsigned buflen;
+    unsigned le;
+    unsigned bom;
+
+    //printf("Module::parse()\n");
+
+    srcname = srcfile->name->toChars();
+    //printf("Module::parse(srcname = '%s')\n", srcname);
+
+    buf = srcfile->buffer;
+    buflen = srcfile->len;
+
+    if (buflen >= 2)
+    {
+	/* Convert all non-UTF-8 formats to UTF-8.
+	 * BOM : http://www.unicode.org/faq/utf_bom.html
+	 * 00 00 FE FF	UTF-32BE, big-endian
+	 * FF FE 00 00	UTF-32LE, little-endian
+	 * FE FF	UTF-16BE, big-endian
+	 * FF FE	UTF-16LE, little-endian
+	 * EF BB BF	UTF-8
+	 */
+
+	bom = 1;		// assume there's a BOM
+	if (buf[0] == 0xFF && buf[1] == 0xFE)
+	{
+	    if (buflen >= 4 && buf[2] == 0 && buf[3] == 0)
+	    {	// UTF-32LE
+		le = 1;
+
+	    Lutf32:
+		OutBuffer dbuf;
+		unsigned *pu = (unsigned *)(buf);
+		unsigned *pumax = &pu[buflen / 4];
+
+		if (buflen & 3)
+		{   error("odd length of UTF-32 char source %u", buflen);
+		    fatal();
+		}
+
+		dbuf.reserve(buflen / 4);
+		for (pu += bom; pu < pumax; pu++)
+		{   unsigned u;
+
+		    u = le ? readlongLE(pu) : readlongBE(pu);
+		    if (u & ~0x7F)
+		    {
+			if (u > 0x10FFFF)
+			{   error("UTF-32 value %08x greater than 0x10FFFF", u);
+			    fatal();
+			}
+			dbuf.writeUTF8(u);
+		    }
+		    else
+			dbuf.writeByte(u);
+		}
+		dbuf.writeByte(0);		// add 0 as sentinel for scanner
+		buflen = dbuf.offset - 1;	// don't include sentinel in count
+		buf = (unsigned char *) dbuf.extractData();
+	    }
+	    else
+	    {   // UTF-16LE (X86)
+		// Convert it to UTF-8
+		le = 1;
+
+	    Lutf16:
+		OutBuffer dbuf;
+		unsigned short *pu = (unsigned short *)(buf);
+		unsigned short *pumax = &pu[buflen / 2];
+
+		if (buflen & 1)
+		{   error("odd length of UTF-16 char source %u", buflen);
+		    fatal();
+		}
+
+		dbuf.reserve(buflen / 2);
+		for (pu += bom; pu < pumax; pu++)
+		{   unsigned u;
+
+		    u = le ? readwordLE(pu) : readwordBE(pu);
+		    if (u & ~0x7F)
+		    {	if (u >= 0xD800 && u <= 0xDBFF)
+			{   unsigned u2;
+
+			    if (++pu > pumax)
+			    {   error("surrogate UTF-16 high value %04x at EOF", u);
+				fatal();
+			    }
+			    u2 = le ? readwordLE(pu) : readwordBE(pu);
+			    if (u2 < 0xDC00 || u2 > 0xDFFF)
+			    {   error("surrogate UTF-16 low value %04x out of range", u2);
+				fatal();
+			    }
+			    u = (u - 0xD7C0) << 10;
+			    u |= (u2 - 0xDC00);
+			}
+			else if (u >= 0xDC00 && u <= 0xDFFF)
+			{   error("unpaired surrogate UTF-16 value %04x", u);
+			    fatal();
+			}
+			else if (u == 0xFFFE || u == 0xFFFF)
+			{   error("illegal UTF-16 value %04x", u);
+			    fatal();
+			}
+			dbuf.writeUTF8(u);
+		    }
+		    else
+			dbuf.writeByte(u);
+		}
+		dbuf.writeByte(0);		// add 0 as sentinel for scanner
+		buflen = dbuf.offset - 1;	// don't include sentinel in count
+		buf = (unsigned char *) dbuf.extractData();
+	    }
+	}
+	else if (buf[0] == 0xFE && buf[1] == 0xFF)
+	{   // UTF-16BE
+	    le = 0;
+	    goto Lutf16;
+	}
+	else if (buflen >= 4 && buf[0] == 0 && buf[1] == 0 && buf[2] == 0xFE && buf[3] == 0xFF)
+	{   // UTF-32BE
+	    le = 0;
+	    goto Lutf32;
+	}
+	else if (buflen >= 3 && buf[0] == 0xEF && buf[1] == 0xBB && buf[2] == 0xBF)
+	{   // UTF-8
+
+	    buf += 3;
+	    buflen -= 3;
+	}
+	else
+	{
+	    /* There is no BOM. Make use of Arcane Jill's insight that
+	     * the first char of D source must be ASCII to
+	     * figure out the encoding.
+	     */
+
+	    bom = 0;
+	    if (buflen >= 4)
+	    {   if (buf[1] == 0 && buf[2] == 0 && buf[3] == 0)
+		{   // UTF-32LE
+		    le = 1;
+		    goto Lutf32;
+		}
+		else if (buf[0] == 0 && buf[1] == 0 && buf[2] == 0)
+		{   // UTF-32BE
+		    le = 0;
+		    goto Lutf32;
+		}
+	    }
+	    if (buflen >= 2)
+	    {
+		if (buf[1] == 0)
+		{   // UTF-16LE
+		    le = 1;
+		    goto Lutf16;
+		}
+		else if (buf[0] == 0)
+		{   // UTF-16BE
+		    le = 0;
+		    goto Lutf16;
+		}
+	    }
+
+	    // It's UTF-8
+	    if (buf[0] >= 0x80)
+	    {	error("source file must start with BOM or ASCII character, not \\x%02X", buf[0]);
+		fatal();
+	    }
+	}
+    }
+
+#ifdef IN_GCC
+    // dump utf-8 encoded source 
+    if (dump_source)
+    {	// %% srcname could contain a path ...
+	d_gcc_dump_source(srcname, "utf-8", buf, buflen);
+    }
+#endif
+
+    /* If it starts with the string "Ddoc", then it's a documentation
+     * source file.
+     */
+    if (buflen >= 4 && memcmp(buf, "Ddoc", 4) == 0)
+    {
+	comment = buf + 4;
+	isDocFile = 1;
+#if IN_DMD
+	if (!docfile)
+	    setDocfile();
+#endif
+	return;
+    }
+    if (isHtml)
+    {
+	OutBuffer *dbuf = new OutBuffer();
+	Html h(srcname, buf, buflen);
+	h.extractCode(dbuf);
+	buf = dbuf->data;
+	buflen = dbuf->offset;
+#ifdef IN_GCC
+	// dump extracted source
+	if (dump_source)
+	    d_gcc_dump_source(srcname, "d.utf-8", buf, buflen);
+#endif
+    }
+    Parser p(this, buf, buflen, docfile != NULL);
+    p.nextToken();
+    members = p.parseModule();
+    md = p.md;
+    numlines = p.loc.linnum;
+
+    DsymbolTable *dst;
+
+    if (md)
+    {	this->ident = md->id;
+	this->safe = md->safe;
+	dst = Package::resolve(md->packages, &this->parent, NULL);
+    }
+    else
+    {
+	dst = modules;
+
+	/* Check to see if module name is a valid identifier
+	 */
+	if (!Lexer::isValidIdentifier(this->ident->toChars()))
+	    error("has non-identifier characters in filename, use module declaration instead");
+    }
+
+    // Update global list of modules
+    if (!dst->insert(this))
+    {
+	if (md)
+	    error(loc, "is in multiple packages %s", md->toChars());
+	else
+	    error(loc, "is in multiple defined");
+    }
+    else
+    {
+	amodules.push(this);
+    }
+}
+
+void Module::semantic(Scope* unused_sc)
+{   int i;
+
+    if (semanticstarted)
+	return;
+
+    //printf("+Module::semantic(this = %p, '%s'): parent = %p\n", this, toChars(), parent);
+    semanticstarted = 1;
+
+    // Note that modules get their own scope, from scratch.
+    // This is so regardless of where in the syntax a module
+    // gets imported, it is unaffected by context.
+    Scope *sc = Scope::createGlobal(this);	// create root scope
+
+    //printf("Module = %p, linkage = %d\n", sc->scopesym, sc->linkage);
+
+    // Add import of "object" if this module isn't "object"
+    if (ident != Id::object)
+    {
+	Import *im = new Import(0, NULL, Id::object, NULL, 0);
+	members->shift(im);
+    }
+
+    // Add all symbols into module's symbol table
+    symtab = new DsymbolTable();
+    for (i = 0; i < members->dim; i++)
+    {	Dsymbol *s;
+
+	s = (Dsymbol *)members->data[i];
+	s->addMember(NULL, sc->scopesym, 1);
+    }
+
+    // Pass 1 semantic routines: do public side of the definition
+    for (i = 0; i < members->dim; i++)
+    {	Dsymbol *s;
+
+	s = (Dsymbol *)members->data[i];
+	//printf("\tModule('%s'): '%s'.semantic()\n", toChars(), s->toChars());
+	s->semantic(sc);
+	runDeferredSemantic();
+    }
+
+    sc = sc->pop();
+    sc->pop();
+    semanticdone = semanticstarted;
+    //printf("-Module::semantic(this = %p, '%s'): parent = %p\n", this, toChars(), parent);
+}
+
+void Module::semantic2(Scope* unused_sc)
+{   int i;
+
+    if (deferred.dim)
+    {
+	for (int i = 0; i < deferred.dim; i++)
+	{
+	    Dsymbol *sd = (Dsymbol *)deferred.data[i];
+
+	    sd->error("unable to resolve forward reference in definition");
+	}
+	return;
+    }
+    //printf("Module::semantic2('%s'): parent = %p\n", toChars(), parent);
+    if (semanticstarted >= 2)
+	return;
+    assert(semanticstarted == 1);
+    semanticstarted = 2;
+
+    // Note that modules get their own scope, from scratch.
+    // This is so regardless of where in the syntax a module
+    // gets imported, it is unaffected by context.
+    Scope *sc = Scope::createGlobal(this);	// create root scope
+    //printf("Module = %p\n", sc.scopesym);
+
+    // Pass 2 semantic routines: do initializers and function bodies
+    for (i = 0; i < members->dim; i++)
+    {	Dsymbol *s;
+
+	s = (Dsymbol *)members->data[i];
+	s->semantic2(sc);
+    }
+
+    sc = sc->pop();
+    sc->pop();
+    semanticdone = semanticstarted;
+    //printf("-Module::semantic2('%s'): parent = %p\n", toChars(), parent);
+}
+
+void Module::semantic3(Scope* unused_sc)
+{   int i;
+
+    //printf("Module::semantic3('%s'): parent = %p\n", toChars(), parent);
+    if (semanticstarted >= 3)
+	return;
+    assert(semanticstarted == 2);
+    semanticstarted = 3;
+
+    // Note that modules get their own scope, from scratch.
+    // This is so regardless of where in the syntax a module
+    // gets imported, it is unaffected by context.
+    Scope *sc = Scope::createGlobal(this);	// create root scope
+    //printf("Module = %p\n", sc.scopesym);
+
+    // Pass 3 semantic routines: do initializers and function bodies
+    for (i = 0; i < members->dim; i++)
+    {	Dsymbol *s;
+
+	s = (Dsymbol *)members->data[i];
+	//printf("Module %s: %s.semantic3()\n", toChars(), s->toChars());
+	s->semantic3(sc);
+    }
+
+    sc = sc->pop();
+    sc->pop();
+    semanticdone = semanticstarted;
+}
+
+void Module::inlineScan()
+{   int i;
+
+    if (semanticstarted >= 4)
+	return;
+    assert(semanticstarted == 3);
+    semanticstarted = 4;
+
+    // Note that modules get their own scope, from scratch.
+    // This is so regardless of where in the syntax a module
+    // gets imported, it is unaffected by context.
+    //printf("Module = %p\n", sc.scopesym);
+
+    for (i = 0; i < members->dim; i++)
+    {	Dsymbol *s;
+
+	s = (Dsymbol *)members->data[i];
+	//if (global.params.verbose)
+	    //printf("inline scan symbol %s\n", s->toChars());
+
+	s->inlineScan();
+    }
+    semanticdone = semanticstarted;
+}
+
+/****************************************************
+ */
+
+// is this used anywhere?
+/*
+void Module::gensymfile()
+{
+    OutBuffer buf;
+    HdrGenState hgs;
+
+    //printf("Module::gensymfile()\n");
+
+    buf.printf("// Sym file generated from '%s'", srcfile->toChars());
+    buf.writenl();
+
+    for (int i = 0; i < members->dim; i++)
+    {	Dsymbol *s = (Dsymbol *)members->data[i];
+
+	s->toCBuffer(&buf, &hgs);
+    }
+
+    // Transfer image to file
+    symfile->setbuffer(buf.data, buf.offset);
+    buf.data = NULL;
+
+    symfile->writev();
+}*/
+
+/**********************************
+ * Determine if we need to generate an instance of ModuleInfo
+ * for this Module.
+ */
+
+int Module::needModuleInfo()
+{
+    return needmoduleinfo;
+}
+
+Dsymbol *Module::search(Loc loc, Identifier *ident, int flags)
+{
+    /* Since modules can be circularly referenced,
+     * need to stop infinite recursive searches.
+     */
+
+    //printf("%s Module::search('%s', flags = %d) insearch = %d\n", toChars(), ident->toChars(), flags, insearch);
+    Dsymbol *s;
+    if (insearch)
+	s = NULL;
+    else if (searchCacheIdent == ident && searchCacheFlags == flags)
+	s = searchCacheSymbol;
+    else
+    {
+	insearch = 1;
+	s = ScopeDsymbol::search(loc, ident, flags);
+	insearch = 0;
+
+	searchCacheIdent = ident;
+	searchCacheSymbol = s;
+	searchCacheFlags = flags;
+    }
+    return s;
+}
+
+/*******************************************
+ * Can't run semantic on s now, try again later.
+ */
+
+void Module::addDeferredSemantic(Dsymbol *s)
+{
+    // Don't add it if it is already there
+    for (int i = 0; i < deferred.dim; i++)
+    {
+	Dsymbol *sd = (Dsymbol *)deferred.data[i];
+
+	if (sd == s)
+	    return;
+    }
+
+    //printf("Module::addDeferredSemantic('%s')\n", s->toChars());
+    deferred.push(s);
+}
+
+
+/******************************************
+ * Run semantic() on deferred symbols.
+ */
+
+void Module::runDeferredSemantic()
+{
+    size_t len;
+
+    static int nested;
+    if (nested)
+	return;
+    //if (deferred.dim) printf("+Module::runDeferredSemantic('%s'), len = %d\n", toChars(), deferred.dim);
+    nested++;
+
+    do
+    {
+	dprogress = 0;
+	len = deferred.dim;
+	if (!len)
+	    break;
+
+	Dsymbol **todo;
+	Dsymbol *tmp;
+	if (len == 1)
+	{
+	    todo = &tmp;
+	}
+	else
+	{
+	    todo = (Dsymbol **)alloca(len * sizeof(Dsymbol *));
+	    assert(todo);
+	}
+	memcpy(todo, deferred.data, len * sizeof(Dsymbol *));
+	deferred.setDim(0);
+
+	for (int i = 0; i < len; i++)
+	{
+	    Dsymbol *s = todo[i];
+
+	    s->semantic(NULL);
+	    //printf("deferred: %s, parent = %s\n", s->toChars(), s->parent->toChars());
+	}
+	//printf("\tdeferred.dim = %d, len = %d, dprogress = %d\n", deferred.dim, len, dprogress);
+    } while (deferred.dim < len || dprogress);	// while making progress
+    nested--;
+    //printf("-Module::runDeferredSemantic('%s'), len = %d\n", toChars(), deferred.dim);
+}
+
+/************************************
+ * Recursively look at every module this module imports,
+ * return TRUE if it imports m.
+ * Can be used to detect circular imports.
+ */
+
+int Module::imports(Module *m)
+{
+    //printf("%s Module::imports(%s)\n", toChars(), m->toChars());
+    int aimports_dim = aimports.dim;
+#if 0
+    for (int i = 0; i < aimports.dim; i++)
+    {	Module *mi = (Module *)aimports.data[i];
+	printf("\t[%d] %s\n", i, mi->toChars());
+    }
+#endif
+    for (int i = 0; i < aimports.dim; i++)
+    {	Module *mi = (Module *)aimports.data[i];
+	if (mi == m)
+	    return TRUE;
+	if (!mi->insearch)
+	{
+	    mi->insearch = 1;
+	    int r = mi->imports(m);
+	    if (r)
+		return r;
+	}
+    }
+    return FALSE;
+}
+
+/*************************************
+ * Return !=0 if module imports itself.
+ */
+
+int Module::selfImports()
+{
+    //printf("Module::selfImports() %s\n", toChars());
+    if (!selfimports)
+    {
+	for (int i = 0; i < amodules.dim; i++)
+	{   Module *mi = (Module *)amodules.data[i];
+	    //printf("\t[%d] %s\n", i, mi->toChars());
+	    mi->insearch = 0;
+	}
+
+	selfimports = imports(this) + 1;
+
+	for (int i = 0; i < amodules.dim; i++)
+	{   Module *mi = (Module *)amodules.data[i];
+	    //printf("\t[%d] %s\n", i, mi->toChars());
+	    mi->insearch = 0;
+	}
+    }
+    return selfimports - 1;
+}
+
+
+/* =========================== ModuleDeclaration ===================== */
+
+ModuleDeclaration::ModuleDeclaration(Array *packages, Identifier *id, bool safe)
+{
+    this->packages = packages;
+    this->id = id;
+    this->safe = safe;
+}
+
+char *ModuleDeclaration::toChars()
+{
+    OutBuffer buf;
+    int i;
+
+    if (packages && packages->dim)
+    {
+	for (i = 0; i < packages->dim; i++)
+	{   Identifier *pid = (Identifier *)packages->data[i];
+
+	    buf.writestring(pid->toChars());
+	    buf.writeByte('.');
+	}
+    }
+    buf.writestring(id->toChars());
+    buf.writeByte(0);
+    return (char *)buf.extractData();
+}
+
+/* =========================== Package ===================== */
+
+Package::Package(Identifier *ident)
+	: ScopeDsymbol(ident)
+{
+}
+
+
+const char *Package::kind()
+{
+    return "package";
+}
+
+
+DsymbolTable *Package::resolve(Array *packages, Dsymbol **pparent, Package **ppkg)
+{
+    DsymbolTable *dst = Module::modules;
+    Dsymbol *parent = NULL;
+
+    //printf("Package::resolve()\n");
+    if (ppkg)
+	*ppkg = NULL;
+
+    if (packages)
+    {   int i;
+
+	for (i = 0; i < packages->dim; i++)
+	{   Identifier *pid = (Identifier *)packages->data[i];
+	    Dsymbol *p;
+
+	    p = dst->lookup(pid);
+	    if (!p)
+	    {
+		p = new Package(pid);
+		dst->insert(p);
+		p->parent = parent;
+		((ScopeDsymbol *)p)->symtab = new DsymbolTable();
+	    }
+	    else
+	    {
+		assert(p->isPackage());
+		if (p->isModule())
+		{   p->error("module and package have the same name");
+		    fatal();
+		    break;
+		}
+	    }
+	    parent = p;
+	    dst = ((Package *)p)->symtab;
+	    if (ppkg && !*ppkg)
+		*ppkg = (Package *)p;
+	}
+	if (pparent)
+	{
+	    *pparent = parent;
+	}
+    }
+    return dst;
+}
--- a/dmd2/module.h	Mon Jun 01 01:28:18 2009 +0200
+++ b/dmd2/module.h	Mon Jun 01 19:02:20 2009 +0100
@@ -1,197 +1,212 @@
-
-// Compiler implementation of the D programming language
-// Copyright (c) 1999-2008 by Digital Mars
-// All Rights Reserved
-// written by Walter Bright
-// http://www.digitalmars.com
-// License for redistribution is by either the Artistic License
-// in artistic.txt, or the GNU General Public License in gnu.txt.
-// See the included readme.txt for details.
-
-#ifndef DMD_MODULE_H
-#define DMD_MODULE_H
-
-#ifdef __DMC__
-#pragma once
-#endif /* __DMC__ */
-
-#include "root.h"
-#include "dsymbol.h"
-
-struct ModuleInfoDeclaration;
-struct ClassDeclaration;
-struct ModuleDeclaration;
-struct Macro;
-struct Escape;
-struct VarDeclaration;
-struct Library;
-
-// Back end
-#if IN_LLVM
-struct DValue;
-typedef DValue elem;
-#else
-#ifdef IN_GCC
-union tree_node; typedef union tree_node elem;
-#else
-struct elem;
-#endif
-#endif
-
-struct Package : ScopeDsymbol
-{
-    Package(Identifier *ident);
-    const char *kind();
-
-    static DsymbolTable *resolve(Array *packages, Dsymbol **pparent, Package **ppkg);
-
-    Package *isPackage() { return this; }
-
-    virtual void semantic(Scope *sc) { }
-};
-
-struct Module : Package
-{
-    static Module *rootModule;
-    static DsymbolTable *modules;	// symbol table of all modules
-    static Array amodules;		// array of all modules
-    static Array deferred;	// deferred Dsymbol's needing semantic() run on them
-    static unsigned dprogress;	// progress resolving the deferred list
-    static void init();
-
-    static ClassDeclaration *moduleinfo;
-
-
-    const char *arg;	// original argument name
-    ModuleDeclaration *md; // if !NULL, the contents of the ModuleDeclaration declaration
-    File *srcfile;	// input source file
-
-    File *objfile; // output object file
-    File *docfile; // output doc file
-    File *hdrfile; // output hdr file
-    
-    unsigned errors;	// if any errors in file
-    unsigned numlines;	// number of lines in source file
-    int isHtml;		// if it is an HTML file
-    int isDocFile;	// if it is a documentation input file, not D source
-    int needmoduleinfo;
-#ifdef IN_GCC
-    int strictlyneedmoduleinfo;
-#endif
-
-    int insearch;
-    Identifier *searchCacheIdent;
-    Dsymbol *searchCacheSymbol;	// cached value of search
-    int searchCacheFlags;	// cached flags
-
-    int semanticstarted;	// has semantic() been started?
-    int semanticdone;		// has semantic() been done?
-    int root;			// != 0 if this is a 'root' module,
-				// i.e. a module that will be taken all the
-				// way to an object file
-    Module *importedFrom;	// module from command line we're imported from,
-				// i.e. a module that will be taken all the
-				// way to an object file
-
-    Array *decldefs;		// top level declarations for this Module
-
-    Array aimports;		// all imported modules
-
-    ModuleInfoDeclaration *vmoduleinfo;
-
-    unsigned debuglevel;	// debug level
-    Array *debugids;		// debug identifiers
-    Array *debugidsNot;		// forward referenced debug identifiers
-
-    unsigned versionlevel;	// version level
-    Array *versionids;		// version identifiers
-    Array *versionidsNot;	// forward referenced version identifiers
-
-    Macro *macrotable;		// document comment macros
-    struct Escape *escapetable;	// document comment escapes
-
-    int doDocComment;		// enable generating doc comments for this module
-    int doHdrGen;		// enable generating header file for this module
-
-    bool safe;
-
-    Module(char *arg, Identifier *ident, int doDocComment, int doHdrGen);
-    ~Module();
-
-    static Module *load(Loc loc, Array *packages, Identifier *ident);
-
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-    const char *kind();
-    void read(Loc loc);	// read file
-#if IN_GCC
-    void parse(bool dump_source = false);	// syntactic parse
-#else
-    void parse();	// syntactic parse
-#endif
-    void semantic(Scope* unused_sc = NULL);	// semantic analysis
-    void semantic2(Scope* unused_sc = NULL);	// pass 2 semantic analysis
-    void semantic3(Scope* unused_sc = NULL);	// pass 3 semantic analysis
-    void inlineScan();	// scan for functions to inline
-#ifdef _DH
-    void genhdrfile();  // generate D import file
-#endif
-    void genobjfile(int multiobj);
-//    void gensymfile();
-    void gendocfile();
-    int needModuleInfo();
-    Dsymbol *search(Loc loc, Identifier *ident, int flags);
-    void deleteObjFile();
-    void addDeferredSemantic(Dsymbol *s);
-    void runDeferredSemantic();
-
-    // Back end
-
-    int doppelganger;		// sub-module
-    Symbol *cov;		// private uint[] __coverage;
-    unsigned *covb;		// bit array of valid code line numbers
-
-    Symbol *sictor;		// module order independent constructor
-    Symbol *sctor;		// module constructor
-    Symbol *sdtor;		// module destructor
-    Symbol *stest;		// module unit test
-
-    Symbol *sfilename;		// symbol for filename
-
-    Symbol *massert;		// module assert function
-    Symbol *toModuleAssert();	// get module assert function
-
-    Symbol *marray;		// module array bounds function
-    Symbol *toModuleArray();	// get module array bounds function
-
-
-    static Symbol *gencritsec();
-    elem *toEfilename();
-    elem *toEmodulename();
-
-    Symbol *toSymbol();
-    void genmoduleinfo();
-
-    // LDC
-    void buildTargetFiles();
-    File* buildFilePath(char* forcename, const char* path, const char* ext);
-    Module *isModule() { return this; }
-    
-    bool llvmForceLogging;
-
-    // array ops emitted in this module already
-    StringTable arrayfuncs;
-};
-
-
-struct ModuleDeclaration
-{
-    Identifier *id;
-    Array *packages;		// array of Identifier's representing packages
-    bool safe;
-
-    ModuleDeclaration(Array *packages, Identifier *id, bool safe);
-
-    char *toChars();
-};
-
-#endif /* DMD_MODULE_H */
+
+// Compiler implementation of the D programming language
+// Copyright (c) 1999-2008 by Digital Mars
+// All Rights Reserved
+// written by Walter Bright
+// http://www.digitalmars.com
+// License for redistribution is by either the Artistic License
+// in artistic.txt, or the GNU General Public License in gnu.txt.
+// See the included readme.txt for details.
+
+#ifndef DMD_MODULE_H
+#define DMD_MODULE_H
+
+#ifdef __DMC__
+#pragma once
+#endif /* __DMC__ */
+
+#include "root.h"
+#include "dsymbol.h"
+
+struct ModuleInfoDeclaration;
+struct ClassDeclaration;
+struct ModuleDeclaration;
+struct Macro;
+struct Escape;
+struct VarDeclaration;
+struct Library;
+
+// Back end
+#if IN_LLVM
+class Ir;
+struct DValue;
+typedef DValue elem;
+namespace llvm { class Module; }
+#else
+
+#ifdef IN_GCC
+union tree_node; typedef union tree_node elem;
+#else
+struct elem;
+#endif
+#endif
+
+struct Package : ScopeDsymbol
+{
+    Package(Identifier *ident);
+    const char *kind();
+
+    static DsymbolTable *resolve(Array *packages, Dsymbol **pparent, Package **ppkg);
+
+    Package *isPackage() { return this; }
+
+    virtual void semantic(Scope *sc) { }
+};
+
+struct Module : Package
+{
+    static Module *rootModule;
+    static DsymbolTable *modules;	// symbol table of all modules
+    static Array amodules;		// array of all modules
+    static Array deferred;	// deferred Dsymbol's needing semantic() run on them
+    static unsigned dprogress;	// progress resolving the deferred list
+    static void init();
+
+    static ClassDeclaration *moduleinfo;
+
+
+    const char *arg;	// original argument name
+    ModuleDeclaration *md; // if !NULL, the contents of the ModuleDeclaration declaration
+    File *srcfile;	// input source file
+
+    File *objfile; // output object file
+    File *docfile; // output doc file
+    File *hdrfile; // output hdr file
+    
+    unsigned errors;	// if any errors in file
+    unsigned numlines;	// number of lines in source file
+    int isHtml;		// if it is an HTML file
+    int isDocFile;	// if it is a documentation input file, not D source
+    int needmoduleinfo;
+#ifdef IN_GCC
+    int strictlyneedmoduleinfo;
+#endif
+
+    int selfimports;		// 0: don't know, 1: does not, 2: does
+    int selfImports();		// returns !=0 if module imports itself
+
+    int insearch;
+    Identifier *searchCacheIdent;
+    Dsymbol *searchCacheSymbol;	// cached value of search
+    int searchCacheFlags;	// cached flags
+
+    int semanticstarted;	// has semantic() been started?
+    int semanticdone;		// has semantic() been done?
+    int root;			// != 0 if this is a 'root' module,
+				// i.e. a module that will be taken all the
+				// way to an object file
+    Module *importedFrom;	// module from command line we're imported from,
+				// i.e. a module that will be taken all the
+				// way to an object file
+
+    Array *decldefs;		// top level declarations for this Module
+
+    Array aimports;		// all imported modules
+
+    ModuleInfoDeclaration *vmoduleinfo;
+
+    unsigned debuglevel;	// debug level
+    Array *debugids;		// debug identifiers
+    Array *debugidsNot;		// forward referenced debug identifiers
+
+    unsigned versionlevel;	// version level
+    Array *versionids;		// version identifiers
+    Array *versionidsNot;	// forward referenced version identifiers
+
+    Macro *macrotable;		// document comment macros
+    Escape *escapetable;	// document comment escapes
+    bool safe;			// TRUE if module is marked as 'safe'
+
+    int doDocComment;		// enable generating doc comments for this module
+    int doHdrGen;		// enable generating header file for this module
+
+    Module(char *arg, Identifier *ident, int doDocComment, int doHdrGen);
+    ~Module();
+
+    static Module *load(Loc loc, Array *packages, Identifier *ident);
+
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+    const char *kind();
+#if !IN_LLVM
+    void setDocfile();	// set docfile member
+#endif
+    void read(Loc loc);	// read file
+#if IN_GCC
+    void parse(bool dump_source = false);	// syntactic parse
+#else
+    void parse();	// syntactic parse
+#endif
+    void semantic(Scope* unused_sc = NULL);	// semantic analysis
+    void semantic2(Scope* unused_sc = NULL);	// pass 2 semantic analysis
+    void semantic3(Scope* unused_sc = NULL);	// pass 3 semantic analysis
+    void inlineScan();	// scan for functions to inline
+#if !IN_LLVM
+    void setHdrfile();	// set hdrfile member
+#endif
+#ifdef _DH
+    void genhdrfile();  // generate D import file
+#endif
+//    void gensymfile();
+    void gendocfile();
+    int needModuleInfo();
+    Dsymbol *search(Loc loc, Identifier *ident, int flags);
+    void deleteObjFile();
+    void addDeferredSemantic(Dsymbol *s);
+    void runDeferredSemantic();
+    int imports(Module *m);
+
+    // Back end
+#if IN_DMD
+    int doppelganger;		// sub-module
+    Symbol *cov;		// private uint[] __coverage;
+    unsigned *covb;		// bit array of valid code line numbers
+
+    Symbol *sictor;		// module order independent constructor
+    Symbol *sctor;		// module constructor
+    Symbol *sdtor;		// module destructor
+    Symbol *stest;		// module unit test
+
+    Symbol *sfilename;		// symbol for filename
+
+    Symbol *massert;		// module assert function
+    Symbol *toModuleAssert();	// get module assert function
+
+    Symbol *marray;		// module array bounds function
+    Symbol *toModuleArray();	// get module array bounds function
+
+
+    static Symbol *gencritsec();
+    elem *toEfilename();
+    elem *toEmodulename();
+
+    Symbol *toSymbol();
+#endif
+    void genmoduleinfo();
+
+#if IN_LLVM
+    // LDC
+    llvm::Module* genLLVMModule(Ir* sir);
+    void buildTargetFiles();
+    File* buildFilePath(const char* forcename, const char* path, const char* ext);
+    Module *isModule() { return this; }
+
+    bool llvmForceLogging;
+
+    // array ops emitted in this module already
+    StringTable arrayfuncs;
+#endif
+};
+
+
+struct ModuleDeclaration
+{
+    Identifier *id;
+    Array *packages;		// array of Identifier's representing packages
+    bool safe;
+
+    ModuleDeclaration(Array *packages, Identifier *id, bool safe);
+
+    char *toChars();
+};
+
+#endif /* DMD_MODULE_H */
--- a/dmd2/mtype.c	Mon Jun 01 01:28:18 2009 +0200
+++ b/dmd2/mtype.c	Mon Jun 01 19:02:20 2009 +0100
@@ -1,6 +1,6 @@
 
 // Compiler implementation of the D programming language
-// Copyright (c) 1999-2008 by Digital Mars
+// Copyright (c) 1999-2009 by Digital Mars
 // All Rights Reserved
 // written by Walter Bright
 // http://www.digitalmars.com
@@ -8,8 +8,13 @@
 // in artistic.txt, or the GNU General Public License in gnu.txt.
 // See the included readme.txt for details.
 
+#define __C99FEATURES__ 1	// Needed on Solaris for NaN and more
 #define __USE_ISOC99 1		// so signbit() gets defined
 
+#if (defined (__SVR4) && defined (__sun))
+#include <alloca.h>
+#endif
+
 #ifdef __DMC__
 #include <math.h>
 #else
@@ -20,10 +25,6 @@
 #include <assert.h>
 #include <float.h>
 
-#ifdef __DMC__
-#include <fp.h>
-#endif
-
 #if _MSC_VER
 #include <malloc.h>
 #include <complex>
@@ -32,19 +33,10 @@
 #include <complex.h>
 #elif __MINGW32__
 #include <malloc.h>
-#else
-//#define signbit 56
 #endif
 
-#if __GNUC__
-#if !(defined (__SVR4) && defined (__sun))
-#include <bits/nan.h>
-#include <bits/mathdef.h>
-#endif
-#endif
-static double zero = 0;
-
-#include "mem.h"
+#include "rmem.h"
+#include "port.h"
 
 #include "dsymbol.h"
 #include "mtype.h"
@@ -60,7 +52,11 @@
 #include "aggregate.h"
 #include "hdrgen.h"
 
-#include "gen/tollvm.h"
+#if IN_LLVM
+//#include "gen/tollvm.h"
+Ir* Type::sir = NULL;
+unsigned GetTypeAlignment(Ir* ir, Type* t);
+#endif
 
 FuncDeclaration *hasThis(Scope *sc);
 
@@ -76,19 +72,34 @@
  */
 
 int PTRSIZE = 4;
-#if IN_LLVM
-int REALSIZE = 8;
-int REALPAD = 0;
-#elif TARGET_LINUX
+
+/* 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 || TARGET_SOLARIS
 int REALSIZE = 12;
 int REALPAD = 2;
+int REALALIGNSIZE = 4;
 #else
 int REALSIZE = 10;
 int REALPAD = 0;
+int REALALIGNSIZE = 2;
 #endif
+
 int Tsize_t = Tuns32;
 int Tptrdiff_t = Tint32;
 
+#if _WIN32 && !defined __MINGW32__
+static double zero = 0;
+double Port::nan = NAN;
+double Port::infinity = 1/zero;
+#endif
+
 /***************************** Type *****************************/
 
 ClassDeclaration *Type::typeinfo;
@@ -106,6 +117,7 @@
 ClassDeclaration *Type::typeinfotypelist;
 ClassDeclaration *Type::typeinfoconst;
 ClassDeclaration *Type::typeinfoinvariant;
+ClassDeclaration *Type::typeinfoshared;
 
 Type *Type::tvoidptr;
 Type *Type::basic[TMAX];
@@ -113,21 +125,34 @@
 unsigned char Type::sizeTy[TMAX];
 StringTable Type::stringtable;
 
-
-Type::Type(TY ty)
+#if IN_LLVM
+StringTable Type::deco_stringtable;
+#endif
+
+
+Type::Type(TY ty/*, Type *next*/)
 {
     this->ty = ty;
     this->mod = 0;
+    //this->next = next;
     this->deco = NULL;
 #if DMDV2
     this->cto = NULL;
     this->ito = NULL;
+    this->sto = NULL;
+    this->scto = NULL;
 #endif
     this->pto = NULL;
     this->rto = NULL;
     this->arrayof = NULL;
     this->vtinfo = NULL;
+#if IN_DMD
     this->ctype = NULL;
+#endif
+
+#if IN_LLVM
+    this->irtype = NULL;
+#endif
 }
 
 Type *Type::syntaxCopy()
@@ -159,7 +184,11 @@
     return 'M';		// name mangling prefix for functions needing 'this'
 }
 
+#if IN_LLVM
+void Type::init(Ir* _sir)
+#else
 void Type::init()
+#endif
 {   int i;
     int j;
 
@@ -256,6 +285,9 @@
 
     tvoidptr = tvoid->pointerTo();
 
+    // LDC
+    sir = _sir;
+
     // set size_t / ptrdiff_t types and pointer size
     if (global.params.is64bit)
     {
@@ -265,6 +297,17 @@
     }
     else
     {
+	PTRSIZE = 4;
+#if TARGET_OSX
+	REALSIZE = 16;
+	REALPAD = 6;
+#elif TARGET_LINUX || TARGET_FREEBSD || TARGET_SOLARIS
+	REALSIZE = 12;
+	REALPAD = 2;
+#else
+	REALSIZE = 10;
+	REALPAD = 0;
+#endif
 	Tsize_t = Tuns32;
 	Tptrdiff_t = Tint32;
 	PTRSIZE = 4;
@@ -309,6 +352,20 @@
     return merge();
 }
 
+Type *Type::trySemantic(Loc loc, Scope *sc)
+{
+    unsigned errors = global.errors;
+    global.gag++;			// suppress printing of error messages
+    Type *t = semantic(loc, sc);
+    global.gag--;
+    if (errors != global.errors)	// if any errors happened
+    {
+	global.errors = errors;
+	t = NULL;
+    }
+    return t;
+}
+
 /*******************************
  * Determine if converting 'this' to 'to' is an identity operation,
  * a conversion to const operation, or the types aren't the same.
@@ -327,8 +384,13 @@
     return MATCHnomatch;
 }
 
+/********************************
+ * Convert to 'const'.
+ */
+
 Type *Type::constOf()
 {
+#if 0
     //printf("Type::constOf() %p %s\n", this, toChars());
     if (isConst())
 	return this;
@@ -342,10 +404,29 @@
     //if (t->nextOf()) assert(t->nextOf()->isConst());
     //printf("-Type::constOf() %p %s\n", t, toChars());
     return t;
-}
+#else
+    //printf("Type::constOf() %p %s\n", this, toChars());
+    if (mod == MODconst)
+	return this;
+    if (cto)
+    {	assert(cto->mod == MODconst);
+	return cto;
+    }
+    Type *t = makeConst();
+    t = t->merge();
+    t->fixTo(this);
+    //printf("-Type::constOf() %p %s\n", t, toChars());
+    return t;
+#endif
+}
+
+/********************************
+ * Convert to 'immutable'.
+ */
 
 Type *Type::invariantOf()
 {
+#if 0
     //printf("Type::invariantOf() %p %s\n", this, toChars());
     if (isInvariant())
     {
@@ -370,10 +451,32 @@
 #endif
     //printf("\t%p\n", t);
     return t;
-}
+#else
+    //printf("Type::invariantOf() %p %s\n", this, toChars());
+    if (isInvariant())
+    {
+	return this;
+    }
+    if (ito)
+    {
+	assert(ito->isInvariant());
+	return ito;
+    }
+    Type *t = makeInvariant();
+    t = t->merge();
+    t->fixTo(this);
+    //printf("\t%p\n", t);
+    return t;
+#endif
+}
+
+/********************************
+ * Make type mutable.
+ */
 
 Type *Type::mutableOf()
 {
+#if 0
     //printf("Type::mutableOf() %p, %s\n", this, toChars());
     Type *t = this;
     if (isConst())
@@ -396,6 +499,8 @@
 	t->rto = NULL;
 	t->cto = NULL;
 	t->ito = NULL;
+	t->sto = NULL;
+	t->scto = NULL;
 	t->vtinfo = NULL;
 	if (ty == Tsarray)
 	{   TypeSArray *ta = (TypeSArray *)t;
@@ -416,6 +521,307 @@
 	}
     }
     return t;
+#else
+    //printf("Type::mutableOf() %p, %s\n", this, toChars());
+    Type *t = this;
+    if (isConst())
+    {	if (isShared())
+	    t = sto;		// shared const => shared
+	else
+	    t = cto;
+	assert(!t || t->isMutable());
+    }
+    else if (isInvariant())
+    {	t = ito;
+	assert(!t || (t->isMutable() && !t->isShared()));
+    }
+    if (!t)
+    {
+	unsigned sz = sizeTy[ty];
+	t = (Type *)mem.malloc(sz);
+	memcpy(t, this, sz);
+	t->mod = 0;
+	t->deco = NULL;
+	t->arrayof = NULL;
+	t->pto = NULL;
+	t->rto = NULL;
+	t->cto = NULL;
+	t->ito = NULL;
+	t->sto = NULL;
+	t->scto = NULL;
+	t->vtinfo = NULL;
+	t = t->merge();
+
+	t->fixTo(this);
+
+	switch (mod)
+	{
+	    case MODconst:
+		t->cto = this;
+		break;
+
+	    case MODinvariant:
+		t->ito = this;
+		break;
+
+	    case MODshared:
+		t->sto = this;
+		break;
+
+	    case MODshared | MODconst:
+		t->scto = this;
+		break;
+
+	    default:
+		assert(0);
+	}
+    }
+    return t;
+#endif
+}
+
+Type *Type::sharedOf()
+{
+    //printf("Type::sharedOf() %p, %s\n", this, toChars());
+    if (mod == MODshared)
+    {
+	return this;
+    }
+    if (sto)
+    {
+	assert(sto->isShared());
+	return sto;
+    }
+    Type *t = makeShared();
+    t = t->merge();
+    t->fixTo(this);
+    //printf("\t%p\n", t);
+    return t;
+}
+
+Type *Type::sharedConstOf()
+{
+    //printf("Type::sharedConstOf() %p, %s\n", this, toChars());
+    if (mod == (MODshared | MODconst))
+    {
+	return this;
+    }
+    if (scto)
+    {
+	assert(scto->mod == (MODshared | MODconst));
+	return scto;
+    }
+    Type *t = makeSharedConst();
+    t = t->merge();
+    t->fixTo(this);
+    //printf("\t%p\n", t);
+    return t;
+}
+
+
+/**********************************
+ * For our new type 'this', which is type-constructed from t,
+ * fill in the cto, ito, sto, scto shortcuts.
+ */
+
+void Type::fixTo(Type *t)
+{
+    ito = t->ito;
+#if 0
+    /* Cannot do these because these are not fully transitive:
+     * there can be a shared ptr to immutable, for example.
+     * Immutable subtypes are always immutable, though.
+     */
+    cto = t->cto;
+    sto = t->sto;
+    scto = t->scto;
+#endif
+
+    assert(mod != t->mod);
+#define X(m, n) (((m) << 3) | (n))
+    switch (X(mod, t->mod))
+    {
+	case X(0, MODconst):
+	    cto = t;
+	    break;
+
+	case X(0, MODinvariant):
+	    ito = t;
+	    break;
+
+	case X(0, MODshared):
+	    sto = t;
+	    break;
+
+	case X(0, MODshared | MODconst):
+	    scto = t;
+	    break;
+
+
+	case X(MODconst, 0):
+	    cto = NULL;
+	    goto L2;
+
+	case X(MODconst, MODinvariant):
+	    ito = t;
+	    goto L2;
+
+	case X(MODconst, MODshared):
+	    sto = t;
+	    goto L2;
+
+	case X(MODconst, MODshared | MODconst):
+	    scto = t;
+	L2:
+	    t->cto = this;
+	    break;
+
+
+	case X(MODinvariant, 0):
+	    ito = NULL;
+	    goto L3;
+
+	case X(MODinvariant, MODconst):
+	    cto = t;
+	    goto L3;
+
+	case X(MODinvariant, MODshared):
+	    sto = t;
+	    goto L3;
+
+	case X(MODinvariant, MODshared | MODconst):
+	    scto = t;
+	L3:
+	    t->ito = this;
+	    if (t->cto) t->cto->ito = this;
+	    if (t->sto) t->sto->ito = this;
+	    if (t->scto) t->scto->ito = this;
+	    break;
+
+
+	case X(MODshared, 0):
+	    sto = NULL;
+	    goto L4;
+
+	case X(MODshared, MODconst):
+	    cto = t;
+	    goto L4;
+
+	case X(MODshared, MODinvariant):
+	    ito = t;
+	    goto L4;
+
+	case X(MODshared, MODshared | MODconst):
+	    scto = t;
+	L4:
+	    t->sto = this;
+	    break;
+
+
+	case X(MODshared | MODconst, 0):
+	    scto = NULL;
+	    break;
+
+	case X(MODshared | MODconst, MODconst):
+	    cto = t;
+	    break;
+
+	case X(MODshared | MODconst, MODinvariant):
+	    ito = t;
+	    break;
+
+	case X(MODshared | MODconst, MODshared):
+	    sto = t;
+	L5:
+	    t->scto = this;
+	    break;
+
+	default:
+	    assert(0);
+    }
+#undef X
+
+    check();
+    t->check();
+    //printf("fixTo: %s, %s\n", toChars(), t->toChars());
+}
+
+/***************************
+ * Look for bugs in constructing types.
+ */
+
+void Type::check()
+{
+    switch (mod)
+    {
+	case 0:
+	    if (cto) assert(cto->mod == MODconst);
+	    if (ito) assert(ito->mod == MODinvariant);
+	    if (sto) assert(sto->mod == MODshared);
+	    if (scto) assert(scto->mod == (MODshared | MODconst));
+	    break;
+
+	case MODconst:
+	    if (cto) assert(cto->mod == 0);
+	    if (ito) assert(ito->mod == MODinvariant);
+	    if (sto) assert(sto->mod == MODshared);
+	    if (scto) assert(scto->mod == (MODshared | MODconst));
+	    break;
+
+	case MODinvariant:
+	    if (cto) assert(cto->mod == MODconst);
+	    if (ito) assert(ito->mod == 0);
+	    if (sto) assert(sto->mod == MODshared);
+	    if (scto) assert(scto->mod == (MODshared | MODconst));
+	    break;
+
+	case MODshared:
+	    if (cto) assert(cto->mod == MODconst);
+	    if (ito) assert(ito->mod == MODinvariant);
+	    if (sto) assert(sto->mod == 0);
+	    if (scto) assert(scto->mod == (MODshared | MODconst));
+	    break;
+
+	case MODshared | MODconst:
+	    if (cto) assert(cto->mod == MODconst);
+	    if (ito) assert(ito->mod == MODinvariant);
+	    if (sto) assert(sto->mod == MODshared);
+	    if (scto) assert(scto->mod == 0);
+	    break;
+
+	default:
+	    assert(0);
+    }
+
+    Type *tn = nextOf();
+    if (tn && ty != Tfunction && ty != Tdelegate)
+    {	// Verify transitivity
+	switch (mod)
+	{
+	    case 0:
+		break;
+
+	    case MODconst:
+		assert(tn->mod & MODinvariant || tn->mod & MODconst);
+		break;
+
+	    case MODinvariant:
+		assert(tn->mod == MODinvariant);
+		break;
+
+	    case MODshared:
+		assert(tn->mod & MODinvariant || tn->mod & MODshared);
+		break;
+
+	    case MODshared | MODconst:
+		assert(tn->mod & MODinvariant || tn->mod & (MODshared | MODconst));
+		break;
+
+	    default:
+		assert(0);
+	}
+	tn->check();
+    }
 }
 
 Type *Type::makeConst()
@@ -433,6 +839,8 @@
     t->rto = NULL;
     t->cto = NULL;
     t->ito = NULL;
+    t->sto = NULL;
+    t->scto = NULL;
     t->vtinfo = NULL;
     //printf("-Type::makeConst() %p, %s\n", t, toChars());
     return t;
@@ -452,10 +860,155 @@
     t->rto = NULL;
     t->cto = NULL;
     t->ito = NULL;
+    t->sto = NULL;
+    t->scto = NULL;
+    t->vtinfo = NULL;
+    return t;
+}
+
+Type *Type::makeShared()
+{
+    if (sto)
+	return sto;
+    unsigned sz = sizeTy[ty];
+    Type *t = (Type *)mem.malloc(sz);
+    memcpy(t, this, sz);
+    t->mod = MODshared;
+    t->deco = NULL;
+    t->arrayof = NULL;
+    t->pto = NULL;
+    t->rto = NULL;
+    t->cto = NULL;
+    t->ito = NULL;
+    t->sto = NULL;
+    t->scto = NULL;
+    t->vtinfo = NULL;
+    return t;
+}
+
+Type *Type::makeSharedConst()
+{
+    if (scto)
+	return scto;
+    unsigned sz = sizeTy[ty];
+    Type *t = (Type *)mem.malloc(sz);
+    memcpy(t, this, sz);
+    t->mod = MODshared | MODconst;
+    t->deco = NULL;
+    t->arrayof = NULL;
+    t->pto = NULL;
+    t->rto = NULL;
+    t->cto = NULL;
+    t->ito = NULL;
+    t->sto = NULL;
+    t->scto = NULL;
     t->vtinfo = NULL;
     return t;
 }
 
+/************************************
+ * Apply MODxxxx bits to existing type.
+ */
+
+Type *Type::castMod(unsigned mod)
+{   Type *t;
+
+    switch (mod)
+    {
+	case 0:
+	    t = mutableOf();
+	    break;
+
+	case MODconst:
+	    t = constOf();
+	    break;
+
+	case MODinvariant:
+	    t = invariantOf();
+	    break;
+
+	case MODshared:
+	    t = sharedOf();
+	    break;
+
+	case MODshared | MODconst:
+	    t = sharedConstOf();
+	    break;
+
+	default:
+	    assert(0);
+    }
+    return t;
+}
+
+/************************************
+ * Add MODxxxx bits to existing type.
+ * We're adding, not replacing, so adding const to
+ * a shared type => "shared const"
+ */
+
+Type *Type::addMod(unsigned mod)
+{   Type *t = this;
+
+    /* Add anything to immutable, and it remains immutable
+     */
+    if (!t->isInvariant())
+    {
+	switch (mod)
+	{
+	    case 0:
+		break;
+
+	    case MODconst:
+		if (isShared())
+		    t = sharedConstOf();
+		else
+		    t = constOf();
+		break;
+
+	    case MODinvariant:
+		t = invariantOf();
+		break;
+
+	    case MODshared:
+		if (isConst())
+		    t = sharedConstOf();
+		else
+		    t = sharedOf();
+		break;
+
+	    case MODshared | MODconst:
+		t = sharedConstOf();
+		break;
+
+	    default:
+		assert(0);
+	}
+    }
+    return t;
+}
+
+/************************************
+ * Add storage class modifiers to type.
+ */
+
+Type *Type::addStorageClass(unsigned stc)
+{
+    /* Just translate to MOD bits and let addMod() do the work
+     */
+    unsigned mod = 0;
+
+    if (stc & STCimmutable)
+	mod = MODinvariant;
+    else
+    {	if (stc & (STCconst | STCin))
+	    mod = MODconst;
+	if (stc & STCshared)
+	    mod |= MODshared;
+    }
+    return addMod(mod);
+}
+
 /**************************
  * Return type with the top level of it being mutable.
  */
@@ -520,7 +1073,7 @@
  *	flag	0x100	do not do const/invariant
  */
 
-void Type::toDecoBuffer(OutBuffer *buf, int flag)
+void Type::toDecoBuffer(OutBuffer *buf, int flag, bool mangle) // Possible conflict from merge
 {
     if (flag != mod && flag != 0x100)
     {
@@ -574,7 +1127,7 @@
     if (mod != this->mod)
     {	const char *p;
 
-	if (mod & MODshared)
+	if (this->mod & MODshared)
 	    buf->writestring("shared(");
 	switch (this->mod & (MODconst | MODinvariant))
 	{
@@ -585,7 +1138,7 @@
 		p = "const(";
 		goto L1;
 	    case MODinvariant:
-		p = "invariant(";
+		p = "immutable(";
 	    L1:	buf->writestring(p);
 		toCBuffer2(buf, hgs, this->mod);
 		buf->writeByte(')');
@@ -593,7 +1146,7 @@
 	    default:
 		assert(0);
 	}
-	if (mod & MODshared)
+	if (this->mod & MODshared)
 	    buf->writeByte(')');
     }
 }
@@ -614,7 +1167,7 @@
 
 	//if (next)
 	    //next = next->merge();
-	toDecoBuffer(&buf);
+	toDecoBuffer(&buf, false);
 	sv = stringtable.update((char *)buf.data, buf.offset);
 	if (sv->ptrvalue)
 	{   t = (Type *) sv->ptrvalue;
@@ -624,13 +1177,51 @@
 	else
 	{
 	    sv->ptrvalue = this;
-	    deco = sv->lstring.string;
+
+            // we still need deco strings to be unique
+            // or Type::equals fails, which breaks a bunch of stuff,
+            // like covariant member function overloads.
+	    OutBuffer mangle;
+	    toDecoBuffer(&mangle, true);
+	    StringValue* sv2 = deco_stringtable.update((char *)mangle.data, mangle.offset);
+	    if (sv2->ptrvalue)
+	    {  Type* t2 = (Type *) sv2->ptrvalue;
+	       assert(t2->deco);
+	       deco = t2->deco;
+	    }
+	    else
+	    {
+	       sv2->ptrvalue = this;
+	       deco = (char *)sv2->lstring.string;
+	    }
 	    //printf("new value, deco = '%s' %p\n", t->deco, t->deco);
 	}
     }
     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::isintegral()
 {
     return FALSE;
@@ -719,7 +1310,7 @@
     return NULL;
 }
 
-int Type::isZeroInit()
+int Type::isZeroInit(Loc loc)
 {
     return 0;		// assume not
 }
@@ -759,7 +1350,7 @@
     else if (ident == Id::size)
     {
 	error(loc, ".size property should be replaced with .sizeof");
-	e = new IntegerExp(loc, size(loc), Type::tsize_t);
+	e = new ErrorExp();
     }
     else if (ident == Id::alignof)
     {
@@ -778,9 +1369,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);
     }
@@ -793,7 +1389,7 @@
     else
     {
 	error(loc, "no property '%s' for type '%s'", ident->toChars(), toChars());
-	e = new IntegerExp(loc, 1, Type::tint32);
+	e = new ErrorExp();
     }
     return e;
 }
@@ -896,6 +1492,17 @@
     va_end( ap );
 }
 
+void Type::warning(Loc loc, const char *format, ...)
+{
+    if (global.params.warnings && !global.gag)
+    {
+	va_list ap;
+	va_start(ap, format);
+	::vwarning(loc, format, ap);
+	va_end( ap );
+    }
+}
+
 Identifier *Type::getTypeInfoIdent(int internal)
 {
     // _init_10TypeInfo_%s
@@ -910,11 +1517,16 @@
 	    buf.writeByte(mangleChar[((TypeArray *)this)->next->ty]);
     }
     else
-	toDecoBuffer(&buf);
+	toDecoBuffer(&buf, true);
     len = buf.offset;
     name = (char *)alloca(19 + sizeof(len) * 3 + len + 1);
     buf.writeByte(0);
+#if TARGET_OSX
+    // The LINKc will prepend the _
+    sprintf(name, "D%dTypeInfo_%s6__initZ", 9 + len, buf.data);
+#else
     sprintf(name, "_D%dTypeInfo_%s6__initZ", 9 + len, buf.data);
+#endif
 // LDC
 // it is not clear where the underscore that's stripped here is added back in
 //    if (global.params.isWindows)
@@ -987,12 +1599,12 @@
     this->next = next;
 }
 
-void TypeNext::toDecoBuffer(OutBuffer *buf, int flag)
-{
-    Type::toDecoBuffer(buf, flag);
+void TypeNext::toDecoBuffer(OutBuffer *buf, int flag, bool mangle)
+{
+    Type::toDecoBuffer(buf, flag, mangle);
     assert(next != this);
     //printf("this = %p, ty = %d, next = %p, ty = %d\n", this, this->ty, next, next->ty);
-    next->toDecoBuffer(buf, (flag & 0x100) ? 0 : mod);
+    next->toDecoBuffer(buf, (flag & 0x100) ? 0 : mod, mangle);
 }
 
 void TypeNext::checkDeprecated(Loc loc, Scope *sc)
@@ -1016,11 +1628,17 @@
 {
     //printf("TypeNext::makeConst() %p, %s\n", this, toChars());
     if (cto)
+    {	assert(cto->mod == MODconst);
 	return cto;
+    }    
     TypeNext *t = (TypeNext *)Type::makeConst();
     if (ty != Tfunction && ty != Tdelegate && next->deco &&
-        !next->isInvariant())
-	t->next = next->constOf();
+        !next->isInvariant() && !next->isConst())
+    {	if (next->isShared())
+	    t->next = next->sharedConstOf();
+	else
+	    t->next = next->constOf();
+    }
     //printf("TypeNext::makeConst() returns %p, %s\n", t, t->toChars());
     return t;
 }
@@ -1033,12 +1651,50 @@
 	return ito;
     }
     TypeNext *t = (TypeNext *)Type::makeInvariant();
-    if (ty != Tfunction && ty != Tdelegate && next->deco)
+    if (ty != Tfunction && ty != Tdelegate && next->deco &&
+	!next->isInvariant())
     {	t->next = next->invariantOf();
     }
     return t;
 }
 
+Type *TypeNext::makeShared()
+{
+    //printf("TypeNext::makeShared() %s\n", toChars());
+    if (sto)
+    {	assert(sto->mod == MODshared);
+	return sto;
+    }    
+    TypeNext *t = (TypeNext *)Type::makeShared();
+    if (ty != Tfunction && ty != Tdelegate && next->deco &&
+        !next->isInvariant() && !next->isShared())
+    {
+	if (next->isConst())
+	    t->next = next->sharedConstOf();
+	else
+	    t->next = next->sharedOf();
+    }
+    //printf("TypeNext::makeShared() returns %p, %s\n", t, t->toChars());
+    return t;
+}
+
+Type *TypeNext::makeSharedConst()
+{
+    //printf("TypeNext::makeSharedConst() %s\n", toChars());
+    if (scto)
+    {	assert(scto->mod == (MODshared | MODconst));
+	return scto;
+    }    
+    TypeNext *t = (TypeNext *)Type::makeSharedConst();
+    if (ty != Tfunction && ty != Tdelegate && next->deco &&
+        !next->isInvariant() && !next->isSharedConst())
+    {
+	t->next = next->sharedConstOf();
+    }
+    //printf("TypeNext::makeSharedConst() returns %p, %s\n", t, t->toChars());
+    return t;
+}
+
 MATCH TypeNext::constConv(Type *to)
 {   MATCH m = Type::constConv(to);
 
@@ -1049,6 +1705,13 @@
 }
 
 
+void TypeNext::transitive()
+{
+    /* Invoke transitivity of type attributes
+     */
+    next = next->addMod(mod);
+}
+
 /* ============================= TypeBasic =========================== */
 
 TypeBasic::TypeBasic(TY ty)
@@ -1234,7 +1897,24 @@
 {
     if (ty == Tvoid)
         return 1;
-    return getABITypeAlign(DtoType(this));
+    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
+#if IN_DMD
+	default:
+	    sz = size(0);
+	    break;
+    }
+    return sz;
+#endif
 }
 
 
@@ -1319,24 +1999,7 @@
 	    case Tfloat64:
 	    case Tfloat80:
 	    {
-#if IN_GCC
-		// mode doesn't matter, will be converted in RealExp anyway
-		fvalue = real_t::getnan(real_t::LongDouble);
-#elif __GNUC__
-		// 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 d_float80 foo;
-		foo = NAN;
-		if (std::signbit(foo))	// signbit sometimes, not always, set
-		    foo = -foo;		// turn off sign bit
-		fvalue = foo;
-#elif _MSC_VER
-		unsigned long nan[2]= { 0xFFFFFFFF, 0x7FFFFFFF };
-		fvalue = *(double*)nan;
-#else
-		fvalue = NAN;
-#endif
+		fvalue = Port::nan;
 		goto Lfvalue;
 	    }
 	}
@@ -1354,15 +2017,7 @@
 	    case Tfloat32:
 	    case Tfloat64:
 	    case Tfloat80:
-#if IN_GCC
-		fvalue = real_t::getinfinity();
-#elif __GNUC__
-		fvalue = 1 / zero;
-#elif _MSC_VER
-		fvalue = std::numeric_limits<long double>::infinity();
-#else
-		fvalue = INFINITY;
-#endif
+		fvalue = Port::infinity;
 		goto Lfvalue;
 	}
     }
@@ -1579,16 +2234,29 @@
 }
 
 Expression *TypeBasic::defaultInit(Loc loc)
-{   integer_t value = 0;
+{   dinteger_t value = 0;
+
+#if SNAN_DEFAULT_INIT
+    /*
+     * Use a payload which is different from the machine NaN,
+     * so that uninitialised variables can be
+     * detected even if exceptions are disabled.
+     */
+    unsigned short snan[8] = { 0, 0, 0, 0xA000, 0x7FFF };
+    /*
+     * Although long doubles are 10 bytes long, some
+     * C ABIs pad them out to 12 or even 16 bytes, so
+     * leave enough space in the snan array.
+     */
+    assert(REALSIZE <= sizeof(snan));
+    d_float80 fvalue = *(long double*)snan;
+#endif
 
 #if LOGDEFAULTINIT
     printf("TypeBasic::defaultInit() '%s'\n", toChars());
 #endif
     switch (ty)
     {
-	case Tvoid:
-	    return new IntegerExp(loc, value, Type::tbool);
-
 	case Tchar:
 	    value = 0xFF;
 	    break;
@@ -1604,15 +2272,33 @@
 	case Tfloat32:
 	case Tfloat64:
 	case Tfloat80:
+#if SNAN_DEFAULT_INIT
+	    return new RealExp(loc, fvalue, this);
+#else
+	    return getProperty(loc, Id::nan);
+#endif
+
 	case Tcomplex32:
 	case Tcomplex64:
 	case Tcomplex80:
+#if SNAN_DEFAULT_INIT
+	{   // Can't use fvalue + I*fvalue (the im part becomes a quiet NaN).
+	    complex_t cvalue;
+	    ((real_t *)&cvalue)[0] = fvalue;
+	    ((real_t *)&cvalue)[1] = fvalue;
+	    return new ComplexExp(loc, cvalue, this);
+	}
+#else
 	    return getProperty(loc, Id::nan);
+#endif
+
+	case Tvoid:
+	    error(loc, "void does not have a default initializer");
     }
     return new IntegerExp(loc, value, this);
 }
 
-int TypeBasic::isZeroInit()
+int TypeBasic::isZeroInit(Loc loc)
 {
     switch (ty)
     {
@@ -1869,7 +2555,7 @@
 	if (ident == Id::idup)
 	{   Type *einv = next->invariantOf();
 	    if (next->implicitConvTo(einv) < MATCHconst)
-		error(e->loc, "cannot implicitly convert element type %s to invariant", next->toChars());
+		error(e->loc, "cannot implicitly convert element type %s to immutable", next->toChars());
 	    e->type = einv->arrayOf();
 	}
 	else
@@ -1909,10 +2595,11 @@
         e = new CastExp(e->loc, e, e->type);
         e->type = Type::tvoid->arrayOf();
     }
-    arguments->push(e);
-
-    arguments->push(n->getTypeInfo(sc));   // LDC, we don't support the getInternalTypeInfo
-                                           // optimization arbitrarily, not yet at least...
+	arguments->push(e);
+
+    if (next->ty != Tbit)
+        arguments->push(n->getTypeInfo(sc));   // LDC, we don't support the getInternalTypeInfo
+                                               // optimization arbitrarily, not yet at least...
 	e = new CallExp(e->loc, ec, arguments);
 	e->type = next->arrayOf();
     }
@@ -1924,7 +2611,6 @@
 }
 
 
-
 /***************************** TypeSArray *****************************/
 
 TypeSArray::TypeSArray(Type *t, Expression *dim)
@@ -1944,13 +2630,13 @@
 }
 
 d_uns64 TypeSArray::size(Loc loc)
-{   integer_t sz;
+{   dinteger_t sz;
 
     if (!dim)
 	return Type::size(loc);
     sz = dim->toInteger();
 
-    {	integer_t n, n2;
+    {	dinteger_t n, n2;
 
 	n = next->size();
 	n2 = n * sz;
@@ -1961,7 +2647,7 @@
     return sz;
 
 Loverflow:
-    error(loc, "index %lld overflow for static array", sz);
+    error(loc, "index %jd overflow for static array", sz);
     return 1;
 }
 
@@ -2028,7 +2714,7 @@
 	    sc = sc->pop();
 
 	    if (d >= td->objects->dim)
-	    {	error(loc, "tuple index %llu exceeds %u", d, td->objects->dim);
+	    {	error(loc, "tuple index %ju exceeds %u", d, td->objects->dim);
 		goto Ldefault;
 	    }
 	    Object *o = (Object *)td->objects->data[(size_t)d];
@@ -2082,7 +2768,7 @@
 	uinteger_t d = dim->toUInteger();
 
 	if (d >= sd->objects->dim)
-	{   error(loc, "tuple index %llu exceeds %u", d, sd->objects->dim);
+	{   error(loc, "tuple index %ju exceeds %u", d, sd->objects->dim);
 	    return Type::terror;
 	}
 	Object *o = (Object *)sd->objects->data[(size_t)d];
@@ -2095,15 +2781,12 @@
     }
 
     next = next->semantic(loc,sc);
-    if (mod == MODconst && !next->isInvariant())
-	next = next->constOf();
-    else if (mod == MODinvariant)
-	next = next->invariantOf();
+    transitive();
 
     Type *tbn = next->toBasetype();
 
     if (dim)
-    {	integer_t n, n2;
+    {	dinteger_t n, n2;
 
 	dim = semanticLength(sc, tbn, dim);
 
@@ -2116,10 +2799,10 @@
 	     */
 	    return this;
 	}
-	integer_t d1 = dim->toInteger();
+	dinteger_t d1 = dim->toInteger();
 	dim = dim->castTo(sc, tsize_t);
 	dim = dim->optimize(WANTvalue);
-	integer_t d2 = dim->toInteger();
+	dinteger_t d2 = dim->toInteger();
 
 	if (d1 != d2)
 	    goto Loverflow;
@@ -2144,7 +2827,7 @@
 	    if (n && n2 / n != d2)
 	    {
 	      Loverflow:
-		error(loc, "index %lld overflow for static array", d1);
+		error(loc, "index %jd overflow for static array", d1);
 		dim = new IntegerExp(0, 1, tsize_t);
 	    }
 	}
@@ -2158,12 +2841,18 @@
 	    uinteger_t d = dim->toUInteger();
 
 	    if (d >= tt->arguments->dim)
-	    {	error(loc, "tuple index %llu exceeds %u", d, tt->arguments->dim);
+	    {	error(loc, "tuple index %ju exceeds %u", d, tt->arguments->dim);
 		return Type::terror;
 	    }
 	    Argument *arg = (Argument *)tt->arguments->data[(size_t)d];
 	    return arg->type;
 	}
+	case Tstruct:
+	{   TypeStruct *ts = (TypeStruct *)tbn;
+	    if (ts->sym->isnested)
+		error(loc, "cannot have array of inner structs %s", ts->toChars());
+	    break;
+	}
 	case Tfunction:
 	case Tnone:
 	    error(loc, "can't have array of %s", tbn->toChars());
@@ -2175,18 +2864,18 @@
     return merge();
 }
 
-void TypeSArray::toDecoBuffer(OutBuffer *buf, int flag)
-{
-    Type::toDecoBuffer(buf, flag);
+void TypeSArray::toDecoBuffer(OutBuffer *buf, int flag, bool mangle)
+{
+    Type::toDecoBuffer(buf, flag, mangle);
     if (dim)
-	buf->printf("%llu", dim->toInteger());
+	buf->printf("%ju", dim->toInteger());
     if (next)
 	/* Note that static arrays are value types, so
 	 * for a parameter, propagate the 0x100 to the next
 	 * level, since for T[4][3], any const should apply to the T,
 	 * not the [4].
 	 */
-	next->toDecoBuffer(buf,  (flag & 0x100) ? flag : mod);
+	next->toDecoBuffer(buf,  (flag & 0x100) ? flag : mod, mangle);
 }
 
 void TypeSArray::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
@@ -2307,9 +2996,9 @@
     return next->defaultInit(loc);
 }
 
-int TypeSArray::isZeroInit()
-{
-    return next->isZeroInit();
+int TypeSArray::isZeroInit(Loc loc)
+{
+    return next->isZeroInit(loc);
 }
 
 
@@ -2375,24 +3064,26 @@
 	    error(loc, "can't have array of %s", tbn->toChars());
 	    tn = next = tint32;
 	    break;
+	case Tstruct:
+	{   TypeStruct *ts = (TypeStruct *)tbn;
+	    if (ts->sym->isnested)
+		error(loc, "cannot have array of inner structs %s", ts->toChars());
+	    break;
+	}
     }
     if (tn->isauto())
 	error(loc, "cannot have array of auto %s", tn->toChars());
 
-    if (mod == MODconst && !tn->isInvariant())
-	tn = tn->constOf();
-    else if (mod == MODinvariant)
-	tn = tn->invariantOf();
-
     next = tn;
+    transitive();
     return merge();
 }
 
-void TypeDArray::toDecoBuffer(OutBuffer *buf, int flag)
-{
-    Type::toDecoBuffer(buf, flag);
+void TypeDArray::toDecoBuffer(OutBuffer *buf, int flag, bool mangle)
+{
+    Type::toDecoBuffer(buf, flag, mangle);
     if (next)
-	next->toDecoBuffer(buf, (flag & 0x100) ? 0 : mod);
+	next->toDecoBuffer(buf, (flag & 0x100) ? 0 : mod, mangle);
 }
 
 void TypeDArray::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
@@ -2511,7 +3202,7 @@
     return e;
 }
 
-int TypeDArray::isZeroInit()
+int TypeDArray::isZeroInit(Loc loc)
 {
     return 1;
 }
@@ -2585,6 +3276,16 @@
     if (index->nextOf() && !index->nextOf()->isInvariant())
     {
 	index = index->constOf()->mutableOf();
+#if 0
+printf("index is %p %s\n", index, index->toChars());
+index->check();
+printf("index->mod = x%x\n", index->mod);
+printf("index->ito = x%x\n", index->ito);
+if (index->ito) {
+printf("index->ito->mod = x%x\n", index->ito->mod);
+printf("index->ito->ito = x%x\n", index->ito->ito);
+}
+#endif
     }
 
     switch (index->toBasetype()->ty)
@@ -2597,10 +3298,7 @@
 	    break;
     }
     next = next->semantic(loc,sc);
-    if (mod == MODconst && !next->isInvariant())
-	next = next->constOf();
-    else if (mod == MODinvariant)
-	next = next->invariantOf();
+    transitive();
 
     switch (next->toBasetype()->ty)
     {
@@ -2666,7 +3364,7 @@
 	arguments = new Expressions();
 	arguments->push(e);
 	e = new CallExp(e->loc, ec, arguments);
-	e->type = ((TypeFunction *)aaLen_fd->type)->next;
+	e->type = aaLen_fd->type->nextOf();
     }
     else if (ident == Id::keys)
     {
@@ -2733,7 +3431,7 @@
 	ec = new VarExp(0, aaRehash_fd);
 	arguments = new Expressions();
 	arguments->push(e->addressOf(sc));
-    arguments->push(index->getInternalTypeInfo(sc));
+	arguments->push(index->getInternalTypeInfo(sc)); // LDC doesn't support getInternalTypeInfo, see above
 	e = new CallExp(e->loc, ec, arguments);
 	e->type = this;
     }
@@ -2744,11 +3442,11 @@
     return e;
 }
 
-void TypeAArray::toDecoBuffer(OutBuffer *buf, int flag)
-{
-    Type::toDecoBuffer(buf, flag);
-    index->toDecoBuffer(buf);
-    next->toDecoBuffer(buf, (flag & 0x100) ? 0 : mod);
+void TypeAArray::toDecoBuffer(OutBuffer *buf, int flag, bool mangle)
+{
+    Type::toDecoBuffer(buf, flag, mangle);
+    index->toDecoBuffer(buf, mangle);
+    next->toDecoBuffer(buf, (flag & 0x100) ? 0 : mod, mangle);
 }
 
 void TypeAArray::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
@@ -2774,7 +3472,7 @@
     return e;
 }
 
-int TypeAArray::isZeroInit()
+int TypeAArray::isZeroInit(Loc loc)
 {
     return TRUE;
 }
@@ -2865,10 +3563,7 @@
     if (n != next)
 	deco = NULL;
     next = n;
-    if (mod == MODconst && !next->isInvariant())
-	next = next->constOf();
-    else if (mod == MODinvariant)
-	next = next->invariantOf();
+    transitive();
     return merge();
 }
 
@@ -2943,7 +3638,7 @@
     return e;
 }
 
-int TypePointer::isZeroInit()
+int TypePointer::isZeroInit(Loc loc)
 {
     return 1;
 }
@@ -2981,10 +3676,7 @@
     if (n != next)
 	deco = NULL;
     next = n;
-    if (mod == MODconst && !next->isInvariant())
-	next = next->constOf();
-    else if (mod == MODinvariant)
-	next = next->invariantOf();
+    transitive();
     return merge();
 }
 
@@ -3024,7 +3716,7 @@
     return e;
 }
 
-int TypeReference::isZeroInit()
+int TypeReference::isZeroInit(Loc loc)
 {
     return 1;
 }
@@ -3046,8 +3738,9 @@
     this->ispure = false;
     this->isref = false;
 
-    // LDC
-    this->fty = NULL;
+#if IN_LLVM
+    this->funcdecl = NULL;
+#endif
 }
 
 Type *TypeFunction::syntaxCopy()
@@ -3077,6 +3770,7 @@
     printf("Type::covariant(t = %s) %s\n", t->toChars(), toChars());
     printf("deco = %p, %p\n", deco, t->deco);
 //    printf("ty = %d\n", next->ty);
+    printf("mod = %x, %x\n", mod, t->mod);
 #endif
 
     int inoutmismatch = 0;
@@ -3154,6 +3848,16 @@
     goto Lnotcovariant;
 
 Lcovariant:
+    /* Can convert mutable to const
+     */
+    if (t1->mod != t2->mod)
+    {
+	if (!(t1->mod & MODconst) && (t2->mod & MODconst))
+	    goto Lnotcovariant;
+	if (!(t1->mod & MODshared) && (t2->mod & MODshared))
+	    goto Lnotcovariant;
+    }
+
     /* Can convert pure to impure, and nothrow to throw
      */
     if (!t1->ispure && t2->ispure)
@@ -3177,7 +3881,7 @@
     return 2;
 }
 
-void TypeFunction::toDecoBuffer(OutBuffer *buf, int flag)
+void TypeFunction::toDecoBuffer(OutBuffer *buf, int flag, bool mangle)
 {   unsigned char mc;
 
     //printf("TypeFunction::toDecoBuffer() this = %p %s\n", this, toChars());
@@ -3210,6 +3914,7 @@
 	    assert(0);
     }
     buf->writeByte(mc);
+// Possible conflict from merge
     if (ispure || isnothrow || isref)
     {
 	if (ispure)
@@ -3220,16 +3925,16 @@
 	    buf->writestring("Nc");
     }
     // Write argument types
-    Argument::argsToDecoBuffer(buf, parameters);
+    Argument::argsToDecoBuffer(buf, parameters, mangle);
     //if (buf->data[buf->offset - 1] == '@') halt();
     buf->writeByte('Z' - varargs);	// mark end of arg list
-    next->toDecoBuffer(buf);
+    next->toDecoBuffer(buf, mangle);
     inuse--;
 }
 
 void TypeFunction::toCBuffer(OutBuffer *buf, Identifier *ident, HdrGenState *hgs)
 {
-    //printf("TypeFunction::toCBuffer() this = %p %s\n", this, toChars());
+    //printf("TypeFunction::toCBuffer() this = %p\n", this);
     const char *p = NULL;
 
     if (inuse)
@@ -3243,7 +3948,7 @@
     if (mod & MODconst)
 	buf->writestring("const ");
     if (mod & MODinvariant)
-	buf->writestring("invariant ");
+	buf->writestring("immutable ");
     if (mod & MODshared)
 	buf->writestring("shared ");
 
@@ -3286,7 +3991,7 @@
 
 void TypeFunction::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
 {
-    //printf("TypeFunction::toCBuffer2() this = %p %s\n", this, toChars());
+    //printf("TypeFunction::toCBuffer2() this = %p, ref = %d\n", this, isref);
     const char *p = NULL;
 
     if (inuse)
@@ -3348,6 +4053,7 @@
 	return this;
     }
     //printf("TypeFunction::semantic() this = %p\n", this);
+    //printf("TypeFunction::semantic() %s, sc->stc = %x\n", toChars(), sc->stc);
 
     TypeFunction *tf = (TypeFunction *)mem.malloc(sizeof(TypeFunction));
     memcpy(tf, this, sizeof(TypeFunction));
@@ -3388,7 +4094,7 @@
 	tf->next = Type::terror;
     }
     if (tf->next->isauto() && !(sc->flags & SCOPEctor))
-	error(loc, "functions cannot return auto %s", tf->next->toChars());
+	error(loc, "functions cannot return scope %s", tf->next->toChars());
 
     if (tf->parameters)
     {	size_t dim = Argument::dim(tf->parameters);
@@ -3400,20 +4106,14 @@
 	    arg->type = arg->type->semantic(loc,sc);
 	    if (tf->inuse == 1) tf->inuse--;
 
-	    if (arg->storageClass & (STCconst | STCin))
-	    {
-		if (!arg->type->isInvariant())
-		    arg->type = arg->type->constOf();
-	    }
-	    else if (arg->storageClass & STCinvariant)
-		arg->type = arg->type->invariantOf();
+	    arg->type = arg->type->addStorageClass(arg->storageClass);
 
 	    if (arg->storageClass & (STCauto | STCalias | STCstatic))
 	    {
 		if (!arg->type)
 		    continue;
 	    }
-
+// Possible merge conflict
 	    Type *t = arg->type->toBasetype();
 
 	    if (arg->storageClass & (STCout | STCref | STClazy))
@@ -3531,7 +4231,7 @@
 	    if (varargs == 2 && u + 1 == nparams)	// if last varargs param
 	    {	Type *tb = p->type->toBasetype();
 		TypeSArray *tsa;
-		integer_t sz;
+		dinteger_t sz;
 
 		switch (tb->ty)
 		{
@@ -3719,7 +4419,7 @@
     return e;
 }
 
-int TypeDelegate::isZeroInit()
+int TypeDelegate::isZeroInit(Loc loc)
 {
     return 1;
 }
@@ -3986,7 +4686,7 @@
 	    }
 	}
 	if (t->ty == Ttuple)
-	    *pt = t->syntaxCopy();
+	    *pt = t;
 	else
 	    *pt = t->merge();
     }
@@ -4015,11 +4715,11 @@
     return t;
 }
 
-void TypeIdentifier::toDecoBuffer(OutBuffer *buf, int flag)
+void TypeIdentifier::toDecoBuffer(OutBuffer *buf, int flag, bool mangle)
 {   unsigned len;
     char *name;
 
-    Type::toDecoBuffer(buf, flag);
+    Type::toDecoBuffer(buf, flag, mangle);
     name = ident->toChars();
     len = strlen(name);
     buf->printf("%d%s", len, name);
@@ -4050,13 +4750,8 @@
     //printf("TypeIdentifier::resolve(sc = %p, idents = '%s')\n", sc, toChars());
     s = sc->search(loc, ident, &scopesym);
     resolveHelper(loc, sc, s, scopesym, pe, pt, ps);
-    if (*pt && mod)
-    {
-	if (mod & MODconst)
-	    *pt = (*pt)->constOf();
-	else if (mod & MODinvariant)
-	    *pt = (*pt)->invariantOf();
-    }
+    if (*pt)
+	(*pt) = (*pt)->addMod(mod);
 }
 
 /*****************************************
@@ -4106,10 +4801,7 @@
 	    if (tt->sym->sem == 1)
 		error(loc, "circular reference of typedef %s", tt->toChars());
 	}
-	if (isConst())
-	    t = t->constOf();
-	else if (isInvariant())
-	    t = t->invariantOf();
+	t = t->addMod(mod);
     }
     else
     {
@@ -4200,13 +4892,8 @@
     if (s)
 	s->semantic(sc);
     resolveHelper(loc, sc, s, NULL, pe, pt, ps);
-    if (*pt && mod)
-    {
-	if (mod & MODconst)
-	    *pt = (*pt)->constOf();
-	else if (mod & MODinvariant)
-	    *pt = (*pt)->invariantOf();
-    }
+    if (*pt)
+	*pt = (*pt)->addMod(mod);
     //printf("pt = '%s'\n", (*pt)->toChars());
 }
 
@@ -4246,6 +4933,34 @@
     return t;
 }
 
+Dsymbol *TypeInstance::toDsymbol(Scope *sc)
+{
+    Type *t;
+    Expression *e;
+    Dsymbol *s;
+
+    //printf("TypeInstance::semantic(%s)\n", toChars());
+
+    if (sc->parameterSpecialization)
+    {
+	unsigned errors = global.errors;
+	global.gag++;
+
+	resolve(loc, sc, &e, &t, &s);
+
+	global.gag--;
+	if (errors != global.errors)
+	{   if (global.gag == 0)
+		global.errors = errors;
+	    return NULL;
+	}
+    }
+    else
+	resolve(loc, sc, &e, &t, &s);
+
+    return s;
+}
+
 
 /***************************** TypeTypeof *****************************/
 
@@ -4257,6 +4972,7 @@
 
 Type *TypeTypeof::syntaxCopy()
 {
+    //printf("TypeTypeof::syntaxCopy() %s\n", toChars());
     TypeTypeof *t;
 
     t = new TypeTypeof(loc, exp->syntaxCopy());
@@ -4363,7 +5079,6 @@
 	 */
 	//t = t->toHeadMutable();
     }
-
     if (idents.dim)
     {
 	Dsymbol *s = t->toDsymbol(sc);
@@ -4374,6 +5089,7 @@
 	    Identifier *id = (Identifier *)idents.data[i];
 	    s = s->searchX(loc, sc, id);
 	}
+
 	if (s)
 	{
 	    t = s->getType();
@@ -4434,11 +5150,7 @@
 	goto Lerr;
     }
     t = sc->func->type->nextOf();
-
-    if (mod & MODinvariant)
-	t = t->invariantOf();
-    else if (mod & MODconst)
-	t = t->constOf();
+    t = t->addMod(mod);
 
     if (idents.dim)
     {
@@ -4548,10 +5260,10 @@
     return sym->memtype->toBasetype();
 }
 
-void TypeEnum::toDecoBuffer(OutBuffer *buf, int flag)
+void TypeEnum::toDecoBuffer(OutBuffer *buf, int flag, bool mangle)
 {
     const char *name = sym->mangle();
-    Type::toDecoBuffer(buf, flag);
+    Type::toDecoBuffer(buf, flag, mangle);
     buf->printf("%s", name);
 }
 
@@ -4572,7 +5284,16 @@
     Dsymbol *s = sym->search(e->loc, ident, 0);
     if (!s)
     {
-	return getProperty(e->loc, ident);
+	if (ident == Id::max ||
+	    ident == Id::min ||
+	    ident == Id::init ||
+	    ident == Id::stringof ||
+	    !sym->memtype
+	   )
+	{
+	    return getProperty(e->loc, ident);
+	}
+	return sym->memtype->dotExp(sc, e, ident);
     }
     EnumMember *m = s->isEnumMember();
     Expression *em = m->value->copy();
@@ -4613,7 +5334,7 @@
 
 Lfwd:
     error(loc, "forward reference of %s.%s", toChars(), ident->toChars());
-    return new IntegerExp(0, 0, this);
+    return new ErrorExp();
 }
 
 int TypeEnum::isintegral()
@@ -4671,13 +5392,21 @@
     if (!sym->defaultval)
     {
 	error(loc, "forward reference of %s.init", toChars());
-	return new IntegerExp(0, 0, this);
+	return new ErrorExp();
     }
     return sym->defaultval;
 }
 
-int TypeEnum::isZeroInit()
-{
+int TypeEnum::isZeroInit(Loc loc)
+{
+    if (!sym->defaultval)
+    {
+#ifdef DEBUG
+	printf("3: ");
+#endif
+	error(loc, "enum %s is forward referenced", sym->toChars());
+	return 0;
+    }
     return sym->defaultval->isBool(FALSE);
 }
 
@@ -4739,9 +5468,9 @@
 	return mutableOf();
 }
 
-void TypeTypedef::toDecoBuffer(OutBuffer *buf, int flag)
-{
-    Type::toDecoBuffer(buf, flag);
+void TypeTypedef::toDecoBuffer(OutBuffer *buf, int flag, bool mangle)
+{
+    Type::toDecoBuffer(buf, flag, mangle);
     const char *name = sym->mangle();
     buf->printf("%s", name);
 }
@@ -4839,10 +5568,7 @@
     sym->inuse = 1;
     Type *t = sym->basetype->toBasetype();
     sym->inuse = 0;
-    if (mod == MODconst && !t->isInvariant())
-	t = t->constOf();
-    else if (mod == MODinvariant)
-	t = t->invariantOf();
+    t = t->addMod(mod);
     return t;
 }
 
@@ -4896,7 +5622,7 @@
     return e;
 }
 
-int TypeTypedef::isZeroInit()
+int TypeTypedef::isZeroInit(Loc loc)
 {
     if (sym->init)
     {
@@ -4913,7 +5639,7 @@
 	sym->basetype = Type::terror;
     }
     sym->inuse = 1;
-    int result = sym->basetype->isZeroInit();
+    int result = sym->basetype->isZeroInit(loc);
     sym->inuse = 0;
     return result;
 }
@@ -4984,11 +5710,11 @@
     return sym;
 }
 
-void TypeStruct::toDecoBuffer(OutBuffer *buf, int flag)
+void TypeStruct::toDecoBuffer(OutBuffer *buf, int flag, bool mangle)
 {
     const char *name = sym->mangle();
     //printf("TypeStruct::toDecoBuffer('%s') = '%s'\n", toChars(), name);
-    Type::toDecoBuffer(buf, flag);
+    Type::toDecoBuffer(buf, flag, mangle);
     buf->printf("%s", name);
 }
 
@@ -5008,7 +5734,6 @@
 Expression *TypeStruct::dotExp(Scope *sc, Expression *e, Identifier *ident)
 {   unsigned offset;
 
-    Expression *b;
     VarDeclaration *v;
     Dsymbol *s;
     DotVarExp *de;
@@ -5020,7 +5745,7 @@
     if (!sym->members)
     {
 	error(e->loc, "struct %s is forward referenced", sym->toChars());
-	return new IntegerExp(e->loc, 0, Type::tint32);
+	return new ErrorExp();
     }
 
     /* If e.tupleof
@@ -5072,6 +5797,17 @@
 	    ident != Id::stringof &&
 	    ident != Id::offsetof)
 	{
+	    /* See if we should forward to the alias this.
+	     */
+	    if (sym->aliasthis)
+	    {	/* Rewrite e.ident as:
+		 *	e.aliasthis.ident
+		 */
+		e = new DotIdExp(e->loc, e, sym->aliasthis->ident);
+		e = new DotIdExp(e->loc, e, ident);
+		return e->semantic(sc);
+	    }
+
 	    /* Look for overloaded opDot() to see if we should forward request
 	     * to it.
 	     */
@@ -5143,6 +5879,33 @@
 	return de;
     }
 
+    Import *timp = s->isImport();
+    if (timp)
+    {
+	e = new DsymbolExp(e->loc, s, 0);
+	e = e->semantic(sc);
+	return e;
+    }
+
+    OverloadSet *o = s->isOverloadSet();
+    if (o)
+    {	/* We really should allow this, triggered by:
+	 *   template c()
+	 *   {
+	 *	void a();
+	 *	void b () { this.a(); }
+	 *   }
+	 *   struct S
+	 *   {
+	 *	mixin c;
+	 *	mixin c;
+	 *  }
+	 *  alias S e;
+	 */
+	error(e->loc, "overload set for %s.%s not allowed in struct declaration", e->toChars(), ident->toChars());
+	return new ErrorExp();
+    }
+
     d = s->isDeclaration();
 #ifdef DEBUG
     if (!d)
@@ -5153,18 +5916,18 @@
     if (e->op == TOKtype)
     {	FuncDeclaration *fd = sc->func;
 
+	if (d->isTupleDeclaration())
+	{
+	    e = new TupleExp(e->loc, d->isTupleDeclaration());
+	    e = e->semantic(sc);
+	    return e;
+	}
 	if (d->needThis() && fd && fd->vthis)
 	{
 	    e = new DotVarExp(e->loc, new ThisExp(e->loc), d);
 	    e = e->semantic(sc);
 	    return e;
 	}
-	if (d->isTupleDeclaration())
-	{
-	    e = new TupleExp(e->loc, d->isTupleDeclaration());
-	    e = e->semantic(sc);
-	    return e;
-	}
 	return new VarExp(e->loc, d, 1);
     }
 
@@ -5187,19 +5950,13 @@
 
 	// *(&e + offset)
 	accessCheck(e->loc, sc, e, d);
-
-// LDC we don't want dot exprs turned into pointer arithmetic. it complicates things for no apparent gain
-#ifndef IN_LLVM
-	b = new AddrExp(e->loc, e);
+#if 0
+	Expression *b = new AddrExp(e->loc, e);
 	b->type = e->type->pointerTo();
 	b = new AddExp(e->loc, b, new IntegerExp(e->loc, v->offset, Type::tint32));
 	b->type = v->type->pointerTo();
 	b = new PtrExp(e->loc, b);
-	b->type = v->type;
-	if (e->type->isConst())
-	    b->type = b->type->constOf();
-	else if (e->type->isInvariant())
-	    b->type = b->type->invariantOf();
+	b->type = v->type->addMod(e->type->mod);
 	return b;
 #endif
     }
@@ -5226,7 +5983,7 @@
     return new VarExp(sym->loc, d);
 }
 
-int TypeStruct::isZeroInit()
+int TypeStruct::isZeroInit(Loc loc)
 {
     return sym->zeroInit;
 }
@@ -5257,7 +6014,8 @@
     for (size_t i = 0; i < s->fields.dim; i++)
     {
 	Dsymbol *sm = (Dsymbol *)s->fields.data[i];
-	if (sm->hasPointers())
+	Declaration *d = sm->isDeclaration();
+	if (d->storage_class & STCref || d->hasPointers())
 	    return TRUE;
     }
     return FALSE;
@@ -5283,20 +6041,10 @@
 		    assert(v && v->storage_class & STCfield);
 
 		    // 'from' type
-		    Type *tvf = v->type;
-		    if (mod == MODconst)
-			tvf = tvf->constOf();
-		    else if (mod == MODinvariant)
-			tvf = tvf->invariantOf();
+		    Type *tvf = v->type->addMod(mod);
 
 		    // 'to' type
-		    Type *tv = v->type;
-		    if (to->mod == 0)
-			tv = tv->mutableOf();
-		    else
-		    {	assert(to->mod == MODinvariant);
-			tv = tv->invariantOf();
-		    }
+		    Type *tv = v->type->castMod(to->mod);
 
 		    //printf("\t%s => %s, match = %d\n", v->type->toChars(), tv->toChars(), tvf->implicitConvTo(tv));
 		    if (tvf->implicitConvTo(tv) < MATCHconst)
@@ -5306,6 +6054,16 @@
 	    }
 	}
     }
+    else if (sym->aliasthis)
+    {
+	m = MATCHnomatch;
+	Declaration *d = sym->aliasthis->isDeclaration();
+	if (d)
+	{   assert(d->type);
+	    Type *t = d->type->addMod(mod);
+	    m = t->implicitConvTo(to);
+	}
+    }
     else
 	m = MATCHnomatch;	// no match
     return m;
@@ -5365,11 +6123,11 @@
     return sym;
 }
 
-void TypeClass::toDecoBuffer(OutBuffer *buf, int flag)
+void TypeClass::toDecoBuffer(OutBuffer *buf, int flag, bool mangle)
 {
     const char *name = sym->mangle();
     //printf("TypeClass::toDecoBuffer('%s' flag=%d mod=%x) = '%s'\n", toChars(), flag, mod, name);
-    Type::toDecoBuffer(buf, flag);
+    Type::toDecoBuffer(buf, flag, mangle);
     buf->printf("%s", name);
 }
 
@@ -5568,6 +6326,17 @@
 		ident != Id::stringof &&
 		ident != Id::offsetof)
 	    {
+		/* See if we should forward to the alias this.
+		 */
+		if (sym->aliasthis)
+		{   /* Rewrite e.ident as:
+		     *	e.aliasthis.ident
+		     */
+		    e = new DotIdExp(e->loc, e, sym->aliasthis->ident);
+		    e = new DotIdExp(e->loc, e, ident);
+		    return e->semantic(sc);
+		}
+
 		/* Look for overloaded opDot() to see if we should forward request
 		 * to it.
 		 */
@@ -5641,11 +6410,19 @@
 	return de;
     }
 
+    OverloadSet *o = s->isOverloadSet();
+    if (o)
+    {	/* We really should allow this
+	 */
+	error(e->loc, "overload set for %s.%s not allowed in struct declaration", e->toChars(), ident->toChars());
+	return new ErrorExp();
+    }
+
     Declaration *d = s->isDeclaration();
     if (!d)
     {
 	e->error("%s.%s is not a declaration", e->toChars(), ident->toChars());
-	return new IntegerExp(e->loc, 1, Type::tint32);
+	return new ErrorExp();
     }
 
     if (e->op == TOKtype)
@@ -5653,7 +6430,13 @@
 	/* It's:
 	 *    Class.d
 	 */
-	if (d->needThis() && (hasThis(sc) || !d->isFuncDeclaration()))
+	if (d->isTupleDeclaration())
+	{
+	    e = new TupleExp(e->loc, d->isTupleDeclaration());
+	    e = e->semantic(sc);
+	    return e;
+	}
+	else if (d->needThis() && (hasThis(sc) || !d->isFuncDeclaration()))
 	{
 	    if (sc->func)
 	    {
@@ -5685,12 +6468,6 @@
 	    e = de->semantic(sc);
 	    return e;
 	}
-	else if (d->isTupleDeclaration())
-	{
-	    e = new TupleExp(e->loc, d->isTupleDeclaration());
-	    e = e->semantic(sc);
-	    return e;
-	}
 	else
 	{
 	    VarExp *ve = new VarExp(e->loc, d, 1);
@@ -5766,7 +6543,18 @@
 	    return MATCHconvert;
     }
 
-    return MATCHnomatch;
+    m = MATCHnomatch;
+    if (sym->aliasthis)
+    {
+	Declaration *d = sym->aliasthis->isDeclaration();
+	if (d)
+	{   assert(d->type);
+	    Type *t = d->type->addMod(mod);
+	    m = t->implicitConvTo(to);
+	}
+    }
+
+    return m;
 }
 
 MATCH TypeClass::constConv(Type *to)
@@ -5795,7 +6583,7 @@
     return e;
 }
 
-int TypeClass::isZeroInit()
+int TypeClass::isZeroInit(Loc loc)
 {
     return 1;
 }
@@ -5939,12 +6727,12 @@
     Argument::argsToCBuffer(buf, hgs, arguments, 0);
 }
 
-void TypeTuple::toDecoBuffer(OutBuffer *buf, int flag)
+void TypeTuple::toDecoBuffer(OutBuffer *buf, int flag, bool mangle)
 {
     //printf("TypeTuple::toDecoBuffer() this = %p, %s\n", this, toChars());
-    Type::toDecoBuffer(buf, flag);
+    Type::toDecoBuffer(buf, flag, mangle);
     OutBuffer buf2;
-    Argument::argsToDecoBuffer(&buf2, arguments);
+    Argument::argsToDecoBuffer(&buf2, arguments, mangle);
     unsigned len = buf2.offset;
     buf->printf("%d%.*s", len, len, (char *)buf2.extractData());
 }
@@ -5962,7 +6750,7 @@
     else
     {
 	error(loc, "no property '%s' for tuple '%s'", ident->toChars(), toChars());
-	e = new IntegerExp(loc, 1, Type::tint32);
+	e = new ErrorExp();
     }
     return e;
 }
@@ -5990,10 +6778,7 @@
 {
     //printf("TypeSlice::semantic() %s\n", toChars());
     next = next->semantic(loc, sc);
-    if (mod == MODconst && !next->isInvariant())
-	next = next->constOf();
-    else if (mod == MODinvariant)
-	next = next->invariantOf();
+    transitive();
     //printf("next: %s\n", next->toChars());
 
     Type *tbn = next->toBasetype();
@@ -6012,7 +6797,7 @@
     uinteger_t i2 = upr->toUInteger();
 
     if (!(i1 <= i2 && i2 <= tt->arguments->dim))
-    {	error(loc, "slice [%llu..%llu] is out of range of [0..%u]", i1, i2, tt->arguments->dim);
+    {	error(loc, "slice [%ju..%ju] is out of range of [0..%u]", i1, i2, tt->arguments->dim);
 	return Type::terror;
     }
 
@@ -6057,7 +6842,7 @@
 	    sc = sc->pop();
 
 	    if (!(i1 <= i2 && i2 <= td->objects->dim))
-	    {   error(loc, "slice [%llu..%llu] is out of range of [0..%u]", i1, i2, td->objects->dim);
+	    {   error(loc, "slice [%ju..%ju] is out of range of [0..%u]", i1, i2, td->objects->dim);
 		goto Ldefault;
 	    }
 
@@ -6198,15 +6983,12 @@
 	    else if (arg->storageClass & STCauto)
 		buf->writestring("auto ");
 
-	    if (arg->storageClass & STCscope)
-		buf->writestring("scope ");
-
-	    if (arg->storageClass & STCconst)
-		buf->writestring("const ");
-	    if (arg->storageClass & STCinvariant)
-		buf->writestring("invariant ");
-	    if (arg->storageClass & STCshared)
-		buf->writestring("shared ");
+	    unsigned stc = arg->storageClass;
+	    if (arg->type && arg->type->mod & MODshared)
+		stc &= ~STCshared;
+
+	    StorageClassDeclaration::stcToCBuffer(buf,
+		stc & (STCconst | STCimmutable | STCshared | STCscope));
 
 	    argbuf.reset();
 	    if (arg->storageClass & STCalias)
@@ -6233,7 +7015,7 @@
 }
 
 
-void Argument::argsToDecoBuffer(OutBuffer *buf, Arguments *arguments)
+void Argument::argsToDecoBuffer(OutBuffer *buf, Arguments *arguments, bool mangle)
 {
     //printf("Argument::argsToDecoBuffer()\n");
 
@@ -6244,7 +7026,7 @@
 	for (size_t i = 0; i < dim; i++)
 	{
 	    Argument *arg = Argument::getNth(arguments, i);
-	    arg->toDecoBuffer(buf);
+	    arg->toDecoBuffer(buf, mangle);
 	}
     }
 }
@@ -6301,7 +7083,7 @@
     return NULL;
 }
 
-void Argument::toDecoBuffer(OutBuffer *buf)
+void Argument::toDecoBuffer(OutBuffer *buf, bool mangle)
 {
     if (storageClass & STCscope)
 	buf->writeByte('M');
@@ -6331,7 +7113,7 @@
     type->toDecoBuffer(buf, mod);
 #else
     //type->toHeadMutable()->toDecoBuffer(buf, 0);
-    type->toDecoBuffer(buf, 0);
+    type->toDecoBuffer(buf, 0, mangle);
 #endif
 }
 
--- a/dmd2/mtype.h	Mon Jun 01 01:28:18 2009 +0200
+++ b/dmd2/mtype.h	Mon Jun 01 19:02:20 2009 +0100
@@ -1,809 +1,896 @@
-
-// Compiler implementation of the D programming language
-// Copyright (c) 1999-2007 by Digital Mars
-// All Rights Reserved
-// written by Walter Bright
-// http://www.digitalmars.com
-// License for redistribution is by either the Artistic License
-// in artistic.txt, or the GNU General Public License in gnu.txt.
-// See the included readme.txt for details.
-
-#ifndef DMD_MTYPE_H
-#define DMD_MTYPE_H
-
-#ifdef __DMC__
-#pragma once
-#endif /* __DMC__ */
-
-#include "root.h"
-#include "stringtable.h"
-
-#include "arraytypes.h"
-#include "expression.h"
-
-// llvm
-#include "../ir/irtype.h"
-namespace llvm { class Type; }
-struct IrFuncTy;
-
-struct Scope;
-struct Identifier;
-struct Expression;
-struct StructDeclaration;
-struct ClassDeclaration;
-struct VarDeclaration;
-struct EnumDeclaration;
-struct TypedefDeclaration;
-struct TypeInfoDeclaration;
-struct Dsymbol;
-struct TemplateInstance;
-struct CppMangleState;
-enum LINK;
-
-struct TypeBasic;
-struct HdrGenState;
-struct Argument;
-
-// Back end
-#if IN_GCC
-union tree_node; typedef union tree_node TYPE;
-typedef TYPE type;
-#else
-typedef struct TYPE type;
-#endif
-struct Symbol;
-
-enum ENUMTY
-{
-    Tarray,		// dynamic array
-    Tsarray,		// static array
-    Taarray,		// associative array
-    Tpointer,
-    Treference,
-    Tfunction,
-    Tident,
-    Tclass,
-    Tstruct,
-    Tenum,
-    Ttypedef,
-    Tdelegate,
-
-    Tnone,
-    Tvoid,
-    Tint8,
-    Tuns8,
-    Tint16,
-    Tuns16,
-    Tint32,
-    Tuns32,
-    Tint64,
-    Tuns64,
-    Tfloat32,
-    Tfloat64,
-    Tfloat80,
-
-    Timaginary32,
-    Timaginary64,
-    Timaginary80,
-
-    Tcomplex32,
-    Tcomplex64,
-    Tcomplex80,
-
-    Tbit,
-    Tbool,
-    Tchar,
-    Twchar,
-    Tdchar,
-
-    Terror,
-    Tinstance,
-    Ttypeof,
-    Ttuple,
-    Tslice,
-    Treturn,
-    TMAX
-};
-typedef unsigned char TY;	// ENUMTY
-
-#define Tascii Tchar
-
-extern int Tsize_t;
-extern int Tptrdiff_t;
-
-
-struct Type : Object
-{
-    TY ty;
-    unsigned char mod;	// modifiers MODxxxx
-	#define MODconst     1	// type is const
-	#define MODinvariant 2	// type is invariant
-	#define MODshared    4	// type is shared
-    char *deco;
-    Type *cto;		// MODconst ? mutable version of this type : const version
-    Type *ito;		// MODinvariant ? mutable version of this type : invariant version
-    Type *pto;		// merged pointer to this type
-    Type *rto;		// reference to this type
-    Type *arrayof;	// array of this type
-    TypeInfoDeclaration *vtinfo;	// TypeInfo object for this Type
-
-    type *ctype;	// for back end
-
-    #define tvoid	basic[Tvoid]
-    #define tint8	basic[Tint8]
-    #define tuns8	basic[Tuns8]
-    #define tint16	basic[Tint16]
-    #define tuns16	basic[Tuns16]
-    #define tint32	basic[Tint32]
-    #define tuns32	basic[Tuns32]
-    #define tint64	basic[Tint64]
-    #define tuns64	basic[Tuns64]
-    #define tfloat32	basic[Tfloat32]
-    #define tfloat64	basic[Tfloat64]
-    #define tfloat80	basic[Tfloat80]
-
-    #define timaginary32 basic[Timaginary32]
-    #define timaginary64 basic[Timaginary64]
-    #define timaginary80 basic[Timaginary80]
-
-    #define tcomplex32	basic[Tcomplex32]
-    #define tcomplex64	basic[Tcomplex64]
-    #define tcomplex80	basic[Tcomplex80]
-
-    #define tbit	basic[Tbit]
-    #define tbool	basic[Tbool]
-    #define tchar	basic[Tchar]
-    #define twchar	basic[Twchar]
-    #define tdchar	basic[Tdchar]
-
-    // Some special types
-    #define tshiftcnt	tint32		// right side of shift expression
-//    #define tboolean	tint32		// result of boolean expression
-    #define tboolean	tbool		// result of boolean expression
-    #define tindex	tint32		// array/ptr index
-    static Type *tvoidptr;		// void*
-    #define terror	basic[Terror]	// for error recovery
-
-    #define tsize_t	basic[Tsize_t]		// matches size_t alias
-    #define tptrdiff_t	basic[Tptrdiff_t]	// matches ptrdiff_t alias
-    #define thash_t	tsize_t			// matches hash_t alias
-
-    static ClassDeclaration *typeinfo;
-    static ClassDeclaration *typeinfoclass;
-    static ClassDeclaration *typeinfointerface;
-    static ClassDeclaration *typeinfostruct;
-    static ClassDeclaration *typeinfotypedef;
-    static ClassDeclaration *typeinfopointer;
-    static ClassDeclaration *typeinfoarray;
-    static ClassDeclaration *typeinfostaticarray;
-    static ClassDeclaration *typeinfoassociativearray;
-    static ClassDeclaration *typeinfoenum;
-    static ClassDeclaration *typeinfofunction;
-    static ClassDeclaration *typeinfodelegate;
-    static ClassDeclaration *typeinfotypelist;
-    static ClassDeclaration *typeinfoconst;
-    static ClassDeclaration *typeinfoinvariant;
-
-    static Type *basic[TMAX];
-    static unsigned char mangleChar[TMAX];
-    static unsigned char sizeTy[TMAX];
-    static StringTable stringtable;
-
-    // These tables are for implicit conversion of binary ops;
-    // the indices are the type of operand one, followed by operand two.
-    static unsigned char impcnvResult[TMAX][TMAX];
-    static unsigned char impcnvType1[TMAX][TMAX];
-    static unsigned char impcnvType2[TMAX][TMAX];
-
-    // If !=0, give warning on implicit conversion
-    static unsigned char impcnvWarn[TMAX][TMAX];
-
-    Type(TY ty);
-    virtual Type *syntaxCopy();
-    int equals(Object *o);
-    int dyncast() { return DYNCAST_TYPE; } // kludge for template.isType()
-    int covariant(Type *t);
-    char *toChars();
-    static char needThisPrefix();
-    static void init();
-    d_uns64 size();
-    virtual d_uns64 size(Loc loc);
-    virtual unsigned alignsize();
-    virtual Type *semantic(Loc loc, Scope *sc);
-    virtual void toDecoBuffer(OutBuffer *buf, int flag = 0);
-    Type *merge();
-    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);
-#if TARGET_LINUX
-    virtual void toCppMangle(OutBuffer *buf, CppMangleState *cms);
-#endif
-    virtual int isintegral();
-    virtual int isfloating();	// real, imaginary, or complex
-    virtual int isreal();
-    virtual int isimaginary();
-    virtual int iscomplex();
-    virtual int isscalar();
-    virtual int isunsigned();
-    virtual int isauto();
-    virtual int isString();
-    virtual int isAssignable();
-    virtual int checkBoolean();	// if can be converted to boolean value
-    virtual void checkDeprecated(Loc loc, Scope *sc);
-    int isConst()	{ return mod & MODconst; }
-    int isInvariant()	{ return mod & MODinvariant; }
-    int isMutable()	{ return !(mod & (MODconst | MODinvariant)); }
-    int isShared()	{ return mod & MODshared; }
-    Type *constOf();
-    Type *invariantOf();
-    Type *mutableOf();
-    Type *pointerTo();
-    Type *referenceTo();
-    Type *arrayOf();
-    virtual Type *makeConst();
-    virtual Type *makeInvariant();
-    virtual Dsymbol *toDsymbol(Scope *sc);
-    virtual Type *toBasetype();
-    virtual Type *toHeadMutable();
-    virtual int isBaseOf(Type *t, int *poffset);
-    virtual MATCH constConv(Type *to);
-    virtual MATCH implicitConvTo(Type *to);
-    virtual ClassDeclaration *isClassHandle();
-    virtual Expression *getProperty(Loc loc, Identifier *ident);
-    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 dt_t **toDt(dt_t **pdt);
-    Identifier *getTypeInfoIdent(int internal);
-    virtual MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes);
-    virtual void resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps);
-    Expression *getInternalTypeInfo(Scope *sc);
-    Expression *getTypeInfo(Scope *sc);
-    virtual TypeInfoDeclaration *getTypeInfoDeclaration();
-    virtual int builtinTypeInfo();
-    virtual Type *reliesOnTident();
-    virtual Expression *toExpression();
-    virtual int hasPointers();
-    virtual Type *nextOf();
-
-    static void error(Loc loc, const char *format, ...);
-
-    // For backend
-    virtual unsigned totym();
-    virtual type *toCtype();
-    virtual type *toCParamtype();
-    virtual Symbol *toSymbol();
-
-    // For eliminating dynamic_cast
-    virtual TypeBasic *isTypeBasic();
-
-    // LDC
-    IrType ir;
-};
-
-struct TypeNext : Type
-{
-    Type *next;
-
-    TypeNext(TY ty, Type *next);
-    void toDecoBuffer(OutBuffer *buf, int flag);
-    void checkDeprecated(Loc loc, Scope *sc);
-    Type *reliesOnTident();
-    Type *nextOf();
-    Type *makeConst();
-    Type *makeInvariant();
-    MATCH constConv(Type *to);
-};
-
-struct TypeBasic : Type
-{
-    const char *dstring;
-    unsigned flags;
-
-    TypeBasic(TY ty);
-    Type *syntaxCopy();
-    d_uns64 size(Loc loc);
-    unsigned alignsize();
-    Expression *getProperty(Loc loc, Identifier *ident);
-    Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
-    char *toChars();
-    void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
-#if TARGET_LINUX
-    void toCppMangle(OutBuffer *buf, CppMangleState *cms);
-#endif
-    int isintegral();
-    int isbit();
-    int isfloating();
-    int isreal();
-    int isimaginary();
-    int iscomplex();
-    int isscalar();
-    int isunsigned();
-    MATCH implicitConvTo(Type *to);
-    Expression *defaultInit(Loc loc);
-    int isZeroInit();
-    int builtinTypeInfo();
-
-    // For eliminating dynamic_cast
-    TypeBasic *isTypeBasic();
-};
-
-struct TypeArray : TypeNext
-{
-    TypeArray(TY ty, Type *next);
-    Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
-};
-
-// Static array, one with a fixed dimension
-struct TypeSArray : TypeArray
-{
-    Expression *dim;
-
-    TypeSArray(Type *t, Expression *dim);
-    Type *syntaxCopy();
-    d_uns64 size(Loc loc);
-    unsigned alignsize();
-    Type *semantic(Loc loc, Scope *sc);
-    void resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps);
-    void toDecoBuffer(OutBuffer *buf, int flag);
-    void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
-    Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
-    int isString();
-    int isZeroInit();
-    unsigned memalign(unsigned salign);
-    MATCH constConv(Type *to);
-    MATCH implicitConvTo(Type *to);
-    Expression *defaultInit(Loc loc);
-    dt_t **toDt(dt_t **pdt);
-    dt_t **toDtElem(dt_t **pdt, Expression *e);
-    MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes);
-    TypeInfoDeclaration *getTypeInfoDeclaration();
-    Expression *toExpression();
-    int hasPointers();
-#if TARGET_LINUX
-    void toCppMangle(OutBuffer *buf, CppMangleState *cms);
-#endif
-
-    type *toCtype();
-    type *toCParamtype();
-};
-
-// Dynamic array, no dimension
-struct TypeDArray : TypeArray
-{
-    TypeDArray(Type *t);
-    Type *syntaxCopy();
-    d_uns64 size(Loc loc);
-    unsigned alignsize();
-    Type *semantic(Loc loc, Scope *sc);
-    void toDecoBuffer(OutBuffer *buf, int flag);
-    void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
-    Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
-    int isString();
-    int isZeroInit();
-    int checkBoolean();
-    MATCH implicitConvTo(Type *to);
-    Expression *defaultInit(Loc loc);
-    int builtinTypeInfo();
-    TypeInfoDeclaration *getTypeInfoDeclaration();
-    int hasPointers();
-#if TARGET_LINUX
-    void toCppMangle(OutBuffer *buf, CppMangleState *cms);
-#endif
-
-    type *toCtype();
-};
-
-struct TypeAArray : TypeArray
-{
-    Type *index;		// key type
-
-    TypeAArray(Type *t, Type *index);
-    Type *syntaxCopy();
-    d_uns64 size(Loc loc);
-    Type *semantic(Loc loc, Scope *sc);
-    void resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps);
-    void toDecoBuffer(OutBuffer *buf, int flag);
-    void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
-    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 checkBoolean();
-    TypeInfoDeclaration *getTypeInfoDeclaration();
-    int hasPointers();
-    MATCH implicitConvTo(Type *to);
-    MATCH constConv(Type *to);
-#if TARGET_LINUX
-    void toCppMangle(OutBuffer *buf, CppMangleState *cms);
-#endif
-
-    // Back end
-    Symbol *aaGetSymbol(const char *func, int flags);
-
-    type *toCtype();
-};
-
-struct TypePointer : TypeNext
-{
-    TypePointer(Type *t);
-    Type *syntaxCopy();
-    Type *semantic(Loc loc, Scope *sc);
-    d_uns64 size(Loc loc);
-    void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
-    MATCH implicitConvTo(Type *to);
-    int isscalar();
-    // LDC: pointers are unsigned
-    int isunsigned() { return TRUE; };
-    Expression *defaultInit(Loc loc);
-    int isZeroInit();
-    TypeInfoDeclaration *getTypeInfoDeclaration();
-    int hasPointers();
-#if TARGET_LINUX
-    void toCppMangle(OutBuffer *buf, CppMangleState *cms);
-#endif
-
-    type *toCtype();
-};
-
-struct TypeReference : TypeNext
-{
-    TypeReference(Type *t);
-    Type *syntaxCopy();
-    Type *semantic(Loc loc, Scope *sc);
-    d_uns64 size(Loc loc);
-    void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
-    Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
-    Expression *defaultInit(Loc loc);
-    int isZeroInit();
-#if TARGET_LINUX
-    void toCppMangle(OutBuffer *buf, CppMangleState *cms);
-#endif
-};
-
-enum RET
-{
-    RETregs	= 1,	// returned in registers
-    RETstack	= 2,	// returned on stack
-};
-
-struct TypeFunction : TypeNext
-{
-    // .next is the return type
-
-    Arguments *parameters;	// function parameters
-    int varargs;	// 1: T t, ...) style for variable number of arguments
-			// 2: T t ...) style for variable number of arguments
-    bool isnothrow;	// true: nothrow
-    bool ispure;	// true: pure
-    bool isref;		// true: returns a reference
-    enum LINK linkage;	// calling convention
-
-    int inuse;
-
-    TypeFunction(Arguments *parameters, Type *treturn, int varargs, enum LINK linkage);
-    Type *syntaxCopy();
-    Type *semantic(Loc loc, Scope *sc);
-    void toDecoBuffer(OutBuffer *buf, int flag);
-    void toCBuffer(OutBuffer *buf, Identifier *ident, HdrGenState *hgs);
-    void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
-    MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes);
-    TypeInfoDeclaration *getTypeInfoDeclaration();
-    Type *reliesOnTident();
-#if TARGET_LINUX
-    void toCppMangle(OutBuffer *buf, CppMangleState *cms);
-#endif
-    bool parameterEscapes(Argument *p);
-
-    int callMatch(Expression *ethis, Expressions *toargs);
-    type *toCtype();
-    enum RET retStyle();
-
-    unsigned totym();
-
-    // LDC
-    IrFuncTy* fty;
-};
-
-struct TypeDelegate : TypeNext
-{
-    // .next is a TypeFunction
-
-    TypeDelegate(Type *t);
-    Type *syntaxCopy();
-    Type *semantic(Loc loc, Scope *sc);
-    d_uns64 size(Loc loc);
-    unsigned alignsize(); // added in LDC
-    void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
-    Expression *defaultInit(Loc loc);
-    int isZeroInit();
-    int checkBoolean();
-    TypeInfoDeclaration *getTypeInfoDeclaration();
-    Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
-    int hasPointers();
-#if TARGET_LINUX
-    void toCppMangle(OutBuffer *buf, CppMangleState *cms);
-#endif
-
-    type *toCtype();
-};
-
-struct TypeQualified : Type
-{
-    Loc loc;
-    Array idents;	// array of Identifier's representing ident.ident.ident etc.
-
-    TypeQualified(TY ty, Loc loc);
-    void syntaxCopyHelper(TypeQualified *t);
-    void addIdent(Identifier *ident);
-    void toCBuffer2Helper(OutBuffer *buf, HdrGenState *hgs);
-    d_uns64 size(Loc loc);
-    void resolveHelper(Loc loc, Scope *sc, Dsymbol *s, Dsymbol *scopesym,
-	Expression **pe, Type **pt, Dsymbol **ps);
-};
-
-struct TypeIdentifier : TypeQualified
-{
-    Identifier *ident;
-
-    TypeIdentifier(Loc loc, Identifier *ident);
-    Type *syntaxCopy();
-    //char *toChars();
-    void toDecoBuffer(OutBuffer *buf, int flag);
-    void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
-    void resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps);
-    Dsymbol *toDsymbol(Scope *sc);
-    Type *semantic(Loc loc, Scope *sc);
-    MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes);
-    Type *reliesOnTident();
-    Expression *toExpression();
-};
-
-/* Similar to TypeIdentifier, but with a TemplateInstance as the root
- */
-struct TypeInstance : TypeQualified
-{
-    TemplateInstance *tempinst;
-
-    TypeInstance(Loc loc, TemplateInstance *tempinst);
-    Type *syntaxCopy();
-    //char *toChars();
-    //void toDecoBuffer(OutBuffer *buf, int flag);
-    void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
-    void resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps);
-    Type *semantic(Loc loc, Scope *sc);
-    MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes);
-};
-
-struct TypeTypeof : TypeQualified
-{
-    Expression *exp;
-
-    TypeTypeof(Loc loc, Expression *exp);
-    Type *syntaxCopy();
-    Dsymbol *toDsymbol(Scope *sc);
-    void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
-    Type *semantic(Loc loc, Scope *sc);
-    d_uns64 size(Loc loc);
-};
-
-struct TypeReturn : TypeQualified
-{
-    TypeReturn(Loc loc);
-    Type *syntaxCopy();
-    Dsymbol *toDsymbol(Scope *sc);
-    Type *semantic(Loc loc, Scope *sc);
-    void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
-};
-
-struct TypeStruct : Type
-{
-    StructDeclaration *sym;
-
-    TypeStruct(StructDeclaration *sym);
-    d_uns64 size(Loc loc);
-    unsigned alignsize();
-    char *toChars();
-    Type *syntaxCopy();
-    Type *semantic(Loc loc, Scope *sc);
-    Dsymbol *toDsymbol(Scope *sc);
-    void toDecoBuffer(OutBuffer *buf, int flag);
-    void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
-    Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
-    unsigned memalign(unsigned salign);
-    Expression *defaultInit(Loc loc);
-    int isZeroInit();
-    int isAssignable();
-    int checkBoolean();
-    dt_t **toDt(dt_t **pdt);
-    MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes);
-    TypeInfoDeclaration *getTypeInfoDeclaration();
-    int hasPointers();
-    MATCH implicitConvTo(Type *to);
-    MATCH constConv(Type *to);
-    Type *toHeadMutable();
-#if TARGET_LINUX
-    void toCppMangle(OutBuffer *buf, CppMangleState *cms);
-#endif
-
-    type *toCtype();
-
-    // LDC
-    // cache the hasUnalignedFields check
-    // 0 = not checked, 1 = aligned, 2 = unaligned
-    int unaligned;
-};
-
-struct TypeEnum : Type
-{
-    EnumDeclaration *sym;
-
-    TypeEnum(EnumDeclaration *sym);
-    d_uns64 size(Loc loc);
-    unsigned alignsize();
-    char *toChars();
-    Type *syntaxCopy();
-    Type *semantic(Loc loc, Scope *sc);
-    Dsymbol *toDsymbol(Scope *sc);
-    void toDecoBuffer(OutBuffer *buf, int flag);
-    void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
-    Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
-    Expression *getProperty(Loc loc, Identifier *ident);
-    int isintegral();
-    int isfloating();
-    int isscalar();
-    int isunsigned();
-    MATCH implicitConvTo(Type *to);
-    MATCH constConv(Type *to);
-    Type *toBasetype();
-    Expression *defaultInit(Loc loc);
-    int isZeroInit();
-    MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes);
-    TypeInfoDeclaration *getTypeInfoDeclaration();
-    int hasPointers();
-#if TARGET_LINUX
-    void toCppMangle(OutBuffer *buf, CppMangleState *cms);
-#endif
-
-    type *toCtype();
-};
-
-struct TypeTypedef : Type
-{
-    TypedefDeclaration *sym;
-
-    TypeTypedef(TypedefDeclaration *sym);
-    Type *syntaxCopy();
-    d_uns64 size(Loc loc);
-    unsigned alignsize();
-    char *toChars();
-    Type *semantic(Loc loc, Scope *sc);
-    Dsymbol *toDsymbol(Scope *sc);
-    void toDecoBuffer(OutBuffer *buf, int flag);
-    void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
-    Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
-    Expression *getProperty(Loc loc, Identifier *ident);
-    int isbit();
-    int isintegral();
-    int isfloating();
-    int isreal();
-    int isimaginary();
-    int iscomplex();
-    int isscalar();
-    int isunsigned();
-    int checkBoolean();
-    int isAssignable();
-    Type *toBasetype();
-    MATCH implicitConvTo(Type *to);
-    MATCH constConv(Type *to);
-    Expression *defaultInit(Loc loc);
-    int isZeroInit();
-    dt_t **toDt(dt_t **pdt);
-    MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes);
-    TypeInfoDeclaration *getTypeInfoDeclaration();
-    int hasPointers();
-    Type *toHeadMutable();
-#if TARGET_LINUX
-    void toCppMangle(OutBuffer *buf, CppMangleState *cms);
-#endif
-
-    type *toCtype();
-    type *toCParamtype();
-};
-
-struct TypeClass : Type
-{
-    ClassDeclaration *sym;
-
-    TypeClass(ClassDeclaration *sym);
-    d_uns64 size(Loc loc);
-    char *toChars();
-    Type *syntaxCopy();
-    Type *semantic(Loc loc, Scope *sc);
-    Dsymbol *toDsymbol(Scope *sc);
-    void toDecoBuffer(OutBuffer *buf, int flag);
-    void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
-    Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
-    ClassDeclaration *isClassHandle();
-    int isBaseOf(Type *t, int *poffset);
-    MATCH implicitConvTo(Type *to);
-    Expression *defaultInit(Loc loc);
-    int isZeroInit();
-    MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes);
-    int isauto();
-    int checkBoolean();
-    TypeInfoDeclaration *getTypeInfoDeclaration();
-    int hasPointers();
-    Type *toHeadMutable();
-    MATCH constConv(Type *to);
-#if TARGET_LINUX
-    void toCppMangle(OutBuffer *buf, CppMangleState *cms);
-#endif
-
-    type *toCtype();
-
-    Symbol *toSymbol();
-};
-
-struct TypeTuple : Type
-{
-    Arguments *arguments;	// types making up the tuple
-
-    TypeTuple(Arguments *arguments);
-    TypeTuple(Expressions *exps);
-    Type *syntaxCopy();
-    Type *semantic(Loc loc, Scope *sc);
-    int equals(Object *o);
-    Type *reliesOnTident();
-    void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
-    void toDecoBuffer(OutBuffer *buf, int flag);
-    Expression *getProperty(Loc loc, Identifier *ident);
-    TypeInfoDeclaration *getTypeInfoDeclaration();
-};
-
-struct TypeSlice : TypeNext
-{
-    Expression *lwr;
-    Expression *upr;
-
-    TypeSlice(Type *next, Expression *lwr, Expression *upr);
-    Type *syntaxCopy();
-    Type *semantic(Loc loc, Scope *sc);
-    void resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps);
-    void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
-};
-
-/**************************************************************/
-
-//enum InOut { None, In, Out, InOut, Lazy };
-
-struct Argument : Object
-{
-    //enum InOut inout;
-    unsigned storageClass;
-    Type *type;
-    Identifier *ident;
-    Expression *defaultArg;
-
-    Argument(unsigned storageClass, Type *type, Identifier *ident, Expression *defaultArg);
-    Argument *syntaxCopy();
-    Type *isLazyArray();
-    void toDecoBuffer(OutBuffer *buf);
-    static Arguments *arraySyntaxCopy(Arguments *args);
-    static char *argsTypesToChars(Arguments *args, int varargs);
-    static void argsCppMangle(OutBuffer *buf, CppMangleState *cms, Arguments *arguments, int varargs);
-    static void argsToCBuffer(OutBuffer *buf, HdrGenState *hgs, Arguments *arguments, int varargs);
-    static void argsToDecoBuffer(OutBuffer *buf, Arguments *arguments);
-    static int isTPL(Arguments *arguments);
-    static size_t dim(Arguments *arguments);
-    static Argument *getNth(Arguments *arguments, size_t nth, size_t *pn = NULL);
-};
-
-extern int PTRSIZE;
-extern int REALSIZE;
-extern int REALPAD;
-extern int Tsize_t;
-extern int Tptrdiff_t;
-
-#endif /* DMD_MTYPE_H */
+
+// Compiler implementation of the D programming language
+// Copyright (c) 1999-2007 by Digital Mars
+// All Rights Reserved
+// written by Walter Bright
+// http://www.digitalmars.com
+// License for redistribution is by either the Artistic License
+// in artistic.txt, or the GNU General Public License in gnu.txt.
+// See the included readme.txt for details.
+
+#ifndef DMD_MTYPE_H
+#define DMD_MTYPE_H
+
+#ifdef __DMC__
+#pragma once
+#endif /* __DMC__ */
+
+#include "root.h"
+#include "stringtable.h"
+
+#include "arraytypes.h"
+#include "expression.h"
+
+#if IN_LLVM
+#include "../ir/irfuncty.h"
+namespace llvm { class Type; }
+class Ir;
+class IrType;
+#endif
+
+struct Scope;
+struct Identifier;
+struct Expression;
+struct StructDeclaration;
+struct ClassDeclaration;
+struct VarDeclaration;
+struct EnumDeclaration;
+struct TypedefDeclaration;
+struct TypeInfoDeclaration;
+struct Dsymbol;
+struct TemplateInstance;
+struct CppMangleState;
+enum LINK;
+
+struct TypeBasic;
+struct HdrGenState;
+struct Argument;
+
+// Back end
+#if IN_GCC
+union tree_node; typedef union tree_node TYPE;
+typedef TYPE type;
+#endif
+
+#if IN_DMD
+typedef struct TYPE type;
+struct Symbol;
+#endif
+
+
+enum ENUMTY
+{
+    Tarray,		// dynamic array
+    Tsarray,		// static array
+    Taarray,		// associative array
+    Tpointer,
+    Treference,
+    Tfunction,
+    Tident,
+    Tclass,
+    Tstruct,
+    Tenum,
+    Ttypedef,
+    Tdelegate,
+
+    Tnone,
+    Tvoid,
+    Tint8,
+    Tuns8,
+    Tint16,
+    Tuns16,
+    Tint32,
+    Tuns32,
+    Tint64,
+    Tuns64,
+    Tfloat32,
+    Tfloat64,
+    Tfloat80,
+
+    Timaginary32,
+    Timaginary64,
+    Timaginary80,
+
+    Tcomplex32,
+    Tcomplex64,
+    Tcomplex80,
+
+    Tbit,
+    Tbool,
+    Tchar,
+    Twchar,
+    Tdchar,
+
+    Terror,
+    Tinstance,
+    Ttypeof,
+    Ttuple,
+    Tslice,
+    Treturn,
+    TMAX
+};
+typedef unsigned char TY;	// ENUMTY
+
+#define Tascii Tchar
+
+extern int Tsize_t;
+extern int Tptrdiff_t;
+
+
+struct Type : Object
+{
+    TY ty;
+    unsigned char mod;	// modifiers MODxxxx
+	/* pick this order of numbers so switch statements work better
+	 */
+	#define MODconst     1	// type is const
+	#define MODinvariant 4	// type is invariant
+	#define MODshared    2	// type is shared
+    char *deco;
+
+    /* Note that there is no "shared immutable", because that is just immutable
+     */
+
+    Type *cto;		// MODconst ? mutable version of this type : const version
+    Type *ito;		// MODinvariant ? mutable version of this type : invariant version
+    Type *sto;		// MODshared ? mutable version of this type : shared mutable version
+    Type *scto;		// MODshared|MODconst ? mutable version of this type : shared const version
+
+    Type *pto;		// merged pointer to this type
+    Type *rto;		// reference to this type
+    Type *arrayof;	// array of this type
+    TypeInfoDeclaration *vtinfo;	// TypeInfo object for this Type
+
+#if IN_DMD
+    type *ctype;	// for back end
+#endif
+
+    #define tvoid	basic[Tvoid]
+    #define tint8	basic[Tint8]
+    #define tuns8	basic[Tuns8]
+    #define tint16	basic[Tint16]
+    #define tuns16	basic[Tuns16]
+    #define tint32	basic[Tint32]
+    #define tuns32	basic[Tuns32]
+    #define tint64	basic[Tint64]
+    #define tuns64	basic[Tuns64]
+    #define tfloat32	basic[Tfloat32]
+    #define tfloat64	basic[Tfloat64]
+    #define tfloat80	basic[Tfloat80]
+
+    #define timaginary32 basic[Timaginary32]
+    #define timaginary64 basic[Timaginary64]
+    #define timaginary80 basic[Timaginary80]
+
+    #define tcomplex32	basic[Tcomplex32]
+    #define tcomplex64	basic[Tcomplex64]
+    #define tcomplex80	basic[Tcomplex80]
+
+    #define tbit	basic[Tbit]
+    #define tbool	basic[Tbool]
+    #define tchar	basic[Tchar]
+    #define twchar	basic[Twchar]
+    #define tdchar	basic[Tdchar]
+
+    // Some special types
+    #define tshiftcnt	tint32		// right side of shift expression
+//    #define tboolean	tint32		// result of boolean expression
+    #define tboolean	tbool		// result of boolean expression
+    #define tindex	tint32		// array/ptr index
+    static Type *tvoidptr;		// void*
+    #define terror	basic[Terror]	// for error recovery
+
+    #define tsize_t	basic[Tsize_t]		// matches size_t alias
+    #define tptrdiff_t	basic[Tptrdiff_t]	// matches ptrdiff_t alias
+    #define thash_t	tsize_t			// matches hash_t alias
+
+    static ClassDeclaration *typeinfo;
+    static ClassDeclaration *typeinfoclass;
+    static ClassDeclaration *typeinfointerface;
+    static ClassDeclaration *typeinfostruct;
+    static ClassDeclaration *typeinfotypedef;
+    static ClassDeclaration *typeinfopointer;
+    static ClassDeclaration *typeinfoarray;
+    static ClassDeclaration *typeinfostaticarray;
+    static ClassDeclaration *typeinfoassociativearray;
+    static ClassDeclaration *typeinfoenum;
+    static ClassDeclaration *typeinfofunction;
+    static ClassDeclaration *typeinfodelegate;
+    static ClassDeclaration *typeinfotypelist;
+    static ClassDeclaration *typeinfoconst;
+    static ClassDeclaration *typeinfoinvariant;
+    static ClassDeclaration *typeinfoshared;
+
+    static Type *basic[TMAX];
+    static unsigned char mangleChar[TMAX];
+    static unsigned char sizeTy[TMAX];
+    static StringTable stringtable;
+#if IN_LLVM
+    static StringTable deco_stringtable;
+#endif
+
+    // These tables are for implicit conversion of binary ops;
+    // the indices are the type of operand one, followed by operand two.
+    static unsigned char impcnvResult[TMAX][TMAX];
+    static unsigned char impcnvType1[TMAX][TMAX];
+    static unsigned char impcnvType2[TMAX][TMAX];
+
+    // If !=0, give warning on implicit conversion
+    static unsigned char impcnvWarn[TMAX][TMAX];
+
+    Type(TY ty);
+    virtual Type *syntaxCopy();
+    int equals(Object *o);
+    int dyncast() { return DYNCAST_TYPE; } // kludge for template.isType()
+    int covariant(Type *t);
+    char *toChars();
+    static char needThisPrefix();
+#if IN_LLVM
+    static void init(Ir*);
+#else
+    static void init();
+#endif
+    d_uns64 size();
+    virtual d_uns64 size(Loc loc);
+    virtual unsigned alignsize();
+    virtual Type *semantic(Loc loc, Scope *sc);
+    Type *trySemantic(Loc loc, Scope *sc);
+    // append the mangleof or a string uniquely identifying this type to buf
+    virtual void toDecoBuffer(OutBuffer *buf, int flag = 0, bool mangle=false);
+    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);
+#if POSIX
+    virtual void toCppMangle(OutBuffer *buf, CppMangleState *cms);
+#endif
+    virtual int isintegral();
+    virtual int isfloating();	// real, imaginary, or complex
+    virtual int isreal();
+    virtual int isimaginary();
+    virtual int iscomplex();
+    virtual int isscalar();
+    virtual int isunsigned();
+    virtual int isauto();
+    virtual int isString();
+    virtual int isAssignable();
+    virtual int checkBoolean();	// if can be converted to boolean value
+    virtual void checkDeprecated(Loc loc, Scope *sc);
+    int isConst()	{ return mod & MODconst; }
+    int isInvariant()	{ return mod & MODinvariant; }
+    int isMutable()	{ return !(mod & (MODconst | MODinvariant)); }
+    int isShared()	{ return mod & MODshared; }
+    int isSharedConst()	{ return mod == (MODshared | MODconst); }
+    Type *constOf();
+    Type *invariantOf();
+    Type *mutableOf();
+    Type *sharedOf();
+    Type *sharedConstOf();
+    void fixTo(Type *t);
+    void check();
+    Type *castMod(unsigned mod);
+    Type *addMod(unsigned mod);
+    Type *addStorageClass(unsigned stc);
+    Type *pointerTo();
+    Type *referenceTo();
+    Type *arrayOf();
+    virtual Type *makeConst();
+    virtual Type *makeInvariant();
+    virtual Type *makeShared();
+    virtual Type *makeSharedConst();
+    virtual Dsymbol *toDsymbol(Scope *sc);
+    virtual Type *toBasetype();
+    virtual Type *toHeadMutable();
+    virtual int isBaseOf(Type *t, int *poffset);
+    virtual MATCH constConv(Type *to);
+    virtual MATCH implicitConvTo(Type *to);
+    virtual ClassDeclaration *isClassHandle();
+    virtual Expression *getProperty(Loc loc, Identifier *ident);
+    virtual Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
+    virtual unsigned memalign(unsigned salign);
+    virtual Expression *defaultInit(Loc loc = 0);
+    virtual int isZeroInit(Loc loc = 0);		// if initializer is 0
+#if IN_DMD
+    virtual dt_t **toDt(dt_t **pdt);
+#endif
+    Identifier *getTypeInfoIdent(int internal);
+    virtual MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes);
+    virtual void resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps);
+    Expression *getInternalTypeInfo(Scope *sc);
+    Expression *getTypeInfo(Scope *sc);
+    virtual TypeInfoDeclaration *getTypeInfoDeclaration();
+    virtual int builtinTypeInfo();
+    virtual Type *reliesOnTident();
+    virtual Expression *toExpression();
+    virtual int hasPointers();
+    //Type *next;
+    virtual Type *nextOf();
+
+    static void error(Loc loc, const char *format, ...) IS_PRINTF(2);
+    static void warning(Loc loc, const char *format, ...) IS_PRINTF(2);
+
+#if IN_DMD
+    // For backend
+    virtual unsigned totym();
+    virtual type *toCtype();
+    virtual type *toCParamtype();
+    virtual Symbol *toSymbol();
+#endif
+
+    // For eliminating dynamic_cast
+    virtual TypeBasic *isTypeBasic();
+
+#if IN_LLVM
+    static Ir* sir;
+    IrType* irtype;
+#endif
+};
+
+struct TypeNext : Type
+{
+    Type *next;
+
+    TypeNext(TY ty, Type *next);
+    void toDecoBuffer(OutBuffer *buf, int flag, bool mangle);
+    void checkDeprecated(Loc loc, Scope *sc);
+    Type *reliesOnTident();
+    Type *nextOf();
+    Type *makeConst();
+    Type *makeInvariant();
+    Type *makeShared();
+    Type *makeSharedConst();
+    MATCH constConv(Type *to);
+    void transitive();
+};
+
+struct TypeBasic : Type
+{
+    const char *dstring;
+    unsigned flags;
+
+    TypeBasic(TY ty);
+    Type *syntaxCopy();
+    d_uns64 size(Loc loc);
+    unsigned alignsize();
+    Expression *getProperty(Loc loc, Identifier *ident);
+    Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
+    char *toChars();
+    void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
+#if POSIX
+    void toCppMangle(OutBuffer *buf, CppMangleState *cms);
+#endif
+    int isintegral();
+    int isbit();
+    int isfloating();
+    int isreal();
+    int isimaginary();
+    int iscomplex();
+    int isscalar();
+    int isunsigned();
+    MATCH implicitConvTo(Type *to);
+    Expression *defaultInit(Loc loc);
+    int isZeroInit(Loc loc);
+    int builtinTypeInfo();
+
+    // For eliminating dynamic_cast
+    TypeBasic *isTypeBasic();
+};
+
+struct TypeArray : TypeNext
+{
+    TypeArray(TY ty, Type *next);
+    Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
+};
+
+// Static array, one with a fixed dimension
+struct TypeSArray : TypeArray
+{
+    Expression *dim;
+
+    TypeSArray(Type *t, Expression *dim);
+    Type *syntaxCopy();
+    d_uns64 size(Loc loc);
+    unsigned alignsize();
+    Type *semantic(Loc loc, Scope *sc);
+    void resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps);
+    void toDecoBuffer(OutBuffer *buf, int flag, bool mangle);
+    void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
+    Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
+    int isString();
+    int isZeroInit(Loc loc);
+    unsigned memalign(unsigned salign);
+    MATCH constConv(Type *to);
+    MATCH implicitConvTo(Type *to);
+    Expression *defaultInit(Loc loc);
+#if IN_DMD
+    dt_t **toDt(dt_t **pdt);
+    dt_t **toDtElem(dt_t **pdt, Expression *e);
+#endif
+    MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes);
+    TypeInfoDeclaration *getTypeInfoDeclaration();
+    Expression *toExpression();
+    int hasPointers();
+#if POSIX
+    void toCppMangle(OutBuffer *buf, CppMangleState *cms);
+#endif
+
+#if IN_DMD
+    type *toCtype();
+    type *toCParamtype();
+#endif
+};
+
+// Dynamic array, no dimension
+struct TypeDArray : TypeArray
+{
+    TypeDArray(Type *t);
+    Type *syntaxCopy();
+    d_uns64 size(Loc loc);
+    unsigned alignsize();
+    Type *semantic(Loc loc, Scope *sc);
+    void toDecoBuffer(OutBuffer *buf, int flag, bool mangle);
+    void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
+    Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
+    int isString();
+    int isZeroInit(Loc loc);
+    int checkBoolean();
+    MATCH implicitConvTo(Type *to);
+    Expression *defaultInit(Loc loc);
+    int builtinTypeInfo();
+    MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes);
+    TypeInfoDeclaration *getTypeInfoDeclaration();
+    int hasPointers();
+#if POSIX
+    void toCppMangle(OutBuffer *buf, CppMangleState *cms);
+#endif
+
+#if IN_DMD
+    type *toCtype();
+#endif
+};
+
+struct TypeAArray : TypeArray
+{
+    Type *index;		// key type
+
+    TypeAArray(Type *t, Type *index);
+    Type *syntaxCopy();
+    d_uns64 size(Loc loc);
+    Type *semantic(Loc loc, Scope *sc);
+    void resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps);
+    void toDecoBuffer(OutBuffer *buf, int flag, bool mangle);
+    void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
+    Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
+    Expression *defaultInit(Loc loc);
+    MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes);
+    int isZeroInit(Loc loc);
+    int checkBoolean();
+    TypeInfoDeclaration *getTypeInfoDeclaration();
+    int hasPointers();
+    MATCH implicitConvTo(Type *to);
+    MATCH constConv(Type *to);
+#if POSIX
+    void toCppMangle(OutBuffer *buf, CppMangleState *cms);
+#endif
+
+#if IN_DMD
+    // Back end
+    Symbol *aaGetSymbol(const char *func, int flags);
+
+    type *toCtype();
+#endif
+};
+
+struct TypePointer : TypeNext
+{
+    TypePointer(Type *t);
+    Type *syntaxCopy();
+    Type *semantic(Loc loc, Scope *sc);
+    d_uns64 size(Loc loc);
+    void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
+    MATCH implicitConvTo(Type *to);
+    int isscalar();
+    // LDC: pointers are unsigned
+    int isunsigned() { return TRUE; };
+    Expression *defaultInit(Loc loc);
+    int isZeroInit(Loc loc);
+    TypeInfoDeclaration *getTypeInfoDeclaration();
+    int hasPointers();
+
+#if POSIX
+    void toCppMangle(OutBuffer *buf, CppMangleState *cms);
+#endif
+
+#if IN_DMD
+    type *toCtype();
+#endif
+};
+
+struct TypeReference : TypeNext
+{
+    TypeReference(Type *t);
+    Type *syntaxCopy();
+    Type *semantic(Loc loc, Scope *sc);
+    d_uns64 size(Loc loc);
+    void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
+    Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
+    Expression *defaultInit(Loc loc);
+    int isZeroInit(Loc loc);
+#if POSIX
+    void toCppMangle(OutBuffer *buf, CppMangleState *cms);
+#endif
+};
+
+enum RET
+{
+    RETregs	= 1,	// returned in registers
+    RETstack	= 2,	// returned on stack
+};
+
+struct TypeFunction : TypeNext
+{
+    // .next is the return type
+
+    Arguments *parameters;	// function parameters
+    int varargs;	// 1: T t, ...) style for variable number of arguments
+			// 2: T t ...) style for variable number of arguments
+    bool isnothrow;	// true: nothrow
+    bool ispure;	// true: pure
+    bool isref;		// true: returns a reference
+    enum LINK linkage;	// calling convention
+
+    int inuse;
+
+    TypeFunction(Arguments *parameters, Type *treturn, int varargs, enum LINK linkage);
+    Type *syntaxCopy();
+    Type *semantic(Loc loc, Scope *sc);
+    void toDecoBuffer(OutBuffer *buf, int flag, bool mangle);
+    void toCBuffer(OutBuffer *buf, Identifier *ident, HdrGenState *hgs);
+    void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
+    MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes);
+    TypeInfoDeclaration *getTypeInfoDeclaration();
+    Type *reliesOnTident();
+#if POSIX
+    void toCppMangle(OutBuffer *buf, CppMangleState *cms);
+#endif
+    bool parameterEscapes(Argument *p);
+
+    int callMatch(Expression *ethis, Expressions *toargs);
+#if IN_DMD
+    type *toCtype();
+#endif
+
+    enum RET retStyle();
+
+#if IN_DMD
+    unsigned totym();
+#elif IN_LLVM
+    // LDC
+    IrFuncTy fty;
+
+    FuncDeclaration* funcdecl;
+#endif
+};
+
+struct TypeDelegate : TypeNext
+{
+    // .next is a TypeFunction
+
+    TypeDelegate(Type *t);
+    Type *syntaxCopy();
+    Type *semantic(Loc loc, Scope *sc);
+    d_uns64 size(Loc loc);
+    unsigned alignsize(); // added in LDC
+    void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
+    Expression *defaultInit(Loc loc);
+    int isZeroInit(Loc loc);
+    int checkBoolean();
+    TypeInfoDeclaration *getTypeInfoDeclaration();
+    Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
+    int hasPointers();
+#if POSIX
+    void toCppMangle(OutBuffer *buf, CppMangleState *cms);
+#endif
+
+#if IN_DMD
+    type *toCtype();
+#endif
+};
+
+struct TypeQualified : Type
+{
+    Loc loc;
+    Array idents;	// array of Identifier's representing ident.ident.ident etc.
+
+    TypeQualified(TY ty, Loc loc);
+    void syntaxCopyHelper(TypeQualified *t);
+    void addIdent(Identifier *ident);
+    void toCBuffer2Helper(OutBuffer *buf, HdrGenState *hgs);
+    d_uns64 size(Loc loc);
+    void resolveHelper(Loc loc, Scope *sc, Dsymbol *s, Dsymbol *scopesym,
+	Expression **pe, Type **pt, Dsymbol **ps);
+};
+
+struct TypeIdentifier : TypeQualified
+{
+    Identifier *ident;
+
+    TypeIdentifier(Loc loc, Identifier *ident);
+    Type *syntaxCopy();
+    //char *toChars();
+    void toDecoBuffer(OutBuffer *buf, int flag, bool mangle);
+    void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
+    void resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps);
+    Dsymbol *toDsymbol(Scope *sc);
+    Type *semantic(Loc loc, Scope *sc);
+    MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes);
+    Type *reliesOnTident();
+    Expression *toExpression();
+};
+
+/* Similar to TypeIdentifier, but with a TemplateInstance as the root
+ */
+struct TypeInstance : TypeQualified
+{
+    TemplateInstance *tempinst;
+
+    TypeInstance(Loc loc, TemplateInstance *tempinst);
+    Type *syntaxCopy();
+    //char *toChars();
+    //void toDecoBuffer(OutBuffer *buf, int flag, bool mangle);
+    void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
+    void resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps);
+    Type *semantic(Loc loc, Scope *sc);
+    Dsymbol *toDsymbol(Scope *sc);
+    MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes);
+};
+
+struct TypeTypeof : TypeQualified
+{
+    Expression *exp;
+
+    TypeTypeof(Loc loc, Expression *exp);
+    Type *syntaxCopy();
+    Dsymbol *toDsymbol(Scope *sc);
+    void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
+    Type *semantic(Loc loc, Scope *sc);
+    d_uns64 size(Loc loc);
+};
+
+struct TypeReturn : TypeQualified
+{
+    TypeReturn(Loc loc);
+    Type *syntaxCopy();
+    Dsymbol *toDsymbol(Scope *sc);
+    Type *semantic(Loc loc, Scope *sc);
+    void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
+};
+
+struct TypeStruct : Type
+{
+    StructDeclaration *sym;
+
+    TypeStruct(StructDeclaration *sym);
+    d_uns64 size(Loc loc);
+    unsigned alignsize();
+    char *toChars();
+    Type *syntaxCopy();
+    Type *semantic(Loc loc, Scope *sc);
+    Dsymbol *toDsymbol(Scope *sc);
+    void toDecoBuffer(OutBuffer *buf, int flag, bool mangle);
+    void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
+    Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
+    unsigned memalign(unsigned salign);
+    Expression *defaultInit(Loc loc);
+    int isZeroInit(Loc loc);
+    int isAssignable();
+    int checkBoolean();
+#if IN_DMD
+    dt_t **toDt(dt_t **pdt);
+#endif
+    MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes);
+    TypeInfoDeclaration *getTypeInfoDeclaration();
+    int hasPointers();
+    MATCH implicitConvTo(Type *to);
+    MATCH constConv(Type *to);
+    Type *toHeadMutable();
+#if POSIX
+    void toCppMangle(OutBuffer *buf, CppMangleState *cms);
+#endif
+
+#if IN_DMD
+    type *toCtype();
+#elif IN_LLVM
+    // LDC
+    // cache the hasUnalignedFields check
+    // 0 = not checked, 1 = aligned, 2 = unaligned
+    int unaligned;
+#endif
+};
+
+struct TypeEnum : Type
+{
+    EnumDeclaration *sym;
+
+    TypeEnum(EnumDeclaration *sym);
+    d_uns64 size(Loc loc);
+    unsigned alignsize();
+    char *toChars();
+    Type *syntaxCopy();
+    Type *semantic(Loc loc, Scope *sc);
+    Dsymbol *toDsymbol(Scope *sc);
+    void toDecoBuffer(OutBuffer *buf, int flag, bool mangle);
+    void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
+    Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
+    Expression *getProperty(Loc loc, Identifier *ident);
+    int isintegral();
+    int isfloating();
+    int isscalar();
+    int isunsigned();
+    MATCH implicitConvTo(Type *to);
+    MATCH constConv(Type *to);
+    Type *toBasetype();
+    Expression *defaultInit(Loc loc);
+    int isZeroInit(Loc loc);
+    MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes);
+    TypeInfoDeclaration *getTypeInfoDeclaration();
+    int hasPointers();
+#if POSIX
+    void toCppMangle(OutBuffer *buf, CppMangleState *cms);
+#endif
+
+#if IN_DMD
+    type *toCtype();
+#endif
+};
+
+struct TypeTypedef : Type
+{
+    TypedefDeclaration *sym;
+
+    TypeTypedef(TypedefDeclaration *sym);
+    Type *syntaxCopy();
+    d_uns64 size(Loc loc);
+    unsigned alignsize();
+    char *toChars();
+    Type *semantic(Loc loc, Scope *sc);
+    Dsymbol *toDsymbol(Scope *sc);
+    void toDecoBuffer(OutBuffer *buf, int flag, bool mangle);
+    void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
+    Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
+    Expression *getProperty(Loc loc, Identifier *ident);
+    int isbit();
+    int isintegral();
+    int isfloating();
+    int isreal();
+    int isimaginary();
+    int iscomplex();
+    int isscalar();
+    int isunsigned();
+    int checkBoolean();
+    int isAssignable();
+    Type *toBasetype();
+    MATCH implicitConvTo(Type *to);
+    MATCH constConv(Type *to);
+    Expression *defaultInit(Loc loc);
+    int isZeroInit(Loc loc);
+#if IN_DMD
+    dt_t **toDt(dt_t **pdt);
+#endif
+    MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes);
+    TypeInfoDeclaration *getTypeInfoDeclaration();
+    int hasPointers();
+    Type *toHeadMutable();
+#if POSIX
+    void toCppMangle(OutBuffer *buf, CppMangleState *cms);
+#endif
+
+#if IN_DMD
+    type *toCtype();
+    type *toCParamtype();
+#endif
+};
+
+struct TypeClass : Type
+{
+    ClassDeclaration *sym;
+
+    TypeClass(ClassDeclaration *sym);
+    d_uns64 size(Loc loc);
+    char *toChars();
+    Type *syntaxCopy();
+    Type *semantic(Loc loc, Scope *sc);
+    Dsymbol *toDsymbol(Scope *sc);
+    void toDecoBuffer(OutBuffer *buf, int flag, bool mangle);
+    void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
+    Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
+    ClassDeclaration *isClassHandle();
+    int isBaseOf(Type *t, int *poffset);
+    MATCH implicitConvTo(Type *to);
+    Expression *defaultInit(Loc loc);
+    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 POSIX
+    void toCppMangle(OutBuffer *buf, CppMangleState *cms);
+#endif
+#endif
+
+#if IN_DMD
+    type *toCtype();
+
+    Symbol *toSymbol();
+#endif
+};
+
+struct TypeTuple : Type
+{
+    Arguments *arguments;	// types making up the tuple
+
+    TypeTuple(Arguments *arguments);
+    TypeTuple(Expressions *exps);
+    Type *syntaxCopy();
+    Type *semantic(Loc loc, Scope *sc);
+    int equals(Object *o);
+    Type *reliesOnTident();
+    void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
+    void toDecoBuffer(OutBuffer *buf, int flag, bool mangle);
+    Expression *getProperty(Loc loc, Identifier *ident);
+    TypeInfoDeclaration *getTypeInfoDeclaration();
+};
+
+struct TypeSlice : TypeNext
+{
+    Expression *lwr;
+    Expression *upr;
+
+    TypeSlice(Type *next, Expression *lwr, Expression *upr);
+    Type *syntaxCopy();
+    Type *semantic(Loc loc, Scope *sc);
+    void resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps);
+    void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
+};
+
+/**************************************************************/
+
+//enum InOut { None, In, Out, InOut, Lazy };
+
+struct Argument : Object
+{
+    //enum InOut inout;
+    unsigned storageClass;
+    Type *type;
+    Identifier *ident;
+    Expression *defaultArg;
+
+    Argument(unsigned storageClass, Type *type, Identifier *ident, Expression *defaultArg);
+    Argument *syntaxCopy();
+    Type *isLazyArray();
+    void toDecoBuffer(OutBuffer *buf, bool mangle);
+    static Arguments *arraySyntaxCopy(Arguments *args);
+    static char *argsTypesToChars(Arguments *args, int varargs);
+    static void argsCppMangle(OutBuffer *buf, CppMangleState *cms, Arguments *arguments, int varargs);
+    static void argsToCBuffer(OutBuffer *buf, HdrGenState *hgs, Arguments *arguments, int varargs);
+    static void argsToDecoBuffer(OutBuffer *buf, Arguments *arguments, bool mangle);
+    static int isTPL(Arguments *arguments);
+    static size_t dim(Arguments *arguments);
+    static Argument *getNth(Arguments *arguments, size_t nth, size_t *pn = NULL);
+};
+
+extern int PTRSIZE;
+extern int REALSIZE;
+extern int REALPAD;
+extern int Tsize_t;
+extern int Tptrdiff_t;
+
+int arrayTypeCompatible(Loc loc, Type *t1, Type *t2);
+
+#endif /* DMD_MTYPE_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd2/objfile.h	Mon Jun 01 19:02:20 2009 +0100
@@ -0,0 +1,61 @@
+
+
+#ifndef OBJFILE_H
+#define OBJFILE_H
+
+#include "root.h"
+
+typedef void *SymHandle;
+typedef unsigned SegOffset;
+
+enum ObjFormat
+{
+	NTCOFF,
+	ELF
+};
+
+struct ObjFile : File
+{
+    ObjFile(FileName *);
+    ~ObjFile();
+
+    ObjFile *init(ObjFormat);
+
+    void comment(const char *);		// insert comment into object file
+    void modulename(const char *);	// set module name
+    void library(const char *);		// add default library
+    void startaddress(SegHandle seg, SegOffset offset);		// set start address
+
+    // Segments
+    enum SegHandle
+    {	code = 1,
+	data, bss
+    };
+
+    SymHandle defineSym(const char *name, SegHandle seg, SegOffset offset);
+    SymHandle externSym(const char *name);
+
+    SegOffset write(SegHandle seg, const void *data, unsigned nbytes);
+    SegOffset writestring(SegHandle seg, char *string);
+    SegOffset write8(SegHandle seg, unsigned b);
+    SegOffset write16(SegHandle seg, unsigned w);
+    SegOffset write32(SegHandle seg, unsigned long v);
+    SegOffset write64(SegHandle seg, unsigned long long v);
+    SegOffset fill0(SegHandle seg, unsigned nbytes);
+    SegOffset align(SegHandle seg, unsigned size);
+    SegOffset writefixup(SegHandle seg, SymHandle sym, unsigned value, int selfrelative);
+
+    // Non-binding hint as to how big seg will grow
+    void reserve(SegHandle seg, SegOffset size);
+
+    // Set actual size
+    void setSize(SegHandle seg, SegOffset size);
+
+    // Get/set offset for subsequent writes
+    void setOffset(SegHandle seg, SegOffset offset);
+    SegOffset getOffset(SegHandle seg);
+
+    SegHandle createSeg(const char *name);
+};
+
+#endif
--- a/dmd2/opover.c	Mon Jun 01 01:28:18 2009 +0200
+++ b/dmd2/opover.c	Mon Jun 01 19:02:20 2009 +0100
@@ -1,750 +1,786 @@
-
-// Compiler implementation of the D programming language
-// Copyright (c) 1999-2007 by Digital Mars
-// All Rights Reserved
-// written by Walter Bright
-// http://www.digitalmars.com
-// License for redistribution is by either the Artistic License
-// in artistic.txt, or the GNU General Public License in gnu.txt.
-// See the included readme.txt for details.
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <ctype.h>
-#include <assert.h>
-#if _MSC_VER
-#include <complex>
-#else
-#endif
-
-#ifdef __APPLE__
-#define integer_t dmd_integer_t
-#endif
-
-#if IN_GCC || IN_LLVM
-#include "mem.h"
-#elif POSIX
-#include "../root/mem.h"
-#elif _WIN32
-#include "..\root\mem.h"
-#endif
-
-//#include "port.h"
-#include "mtype.h"
-#include "init.h"
-#include "expression.h"
-#include "id.h"
-#include "declaration.h"
-#include "aggregate.h"
-#include "template.h"
-
-static void inferApplyArgTypesX(FuncDeclaration *fstart, Arguments *arguments);
-static void inferApplyArgTypesZ(TemplateDeclaration *tstart, Arguments *arguments);
-static int inferApplyArgTypesY(TypeFunction *tf, Arguments *arguments);
-static void templateResolve(Match *m, TemplateDeclaration *td, Scope *sc, Loc loc, Objects *targsi, Expression *ethis, Expressions *arguments);
-
-/******************************** Expression **************************/
-
-
-/***********************************
- * Determine if operands of binary op can be reversed
- * to fit operator overload.
- */
-
-int Expression::isCommutative()
-{
-    return FALSE;	// default is no reverse
-}
-
-/***********************************
- * Get Identifier for operator overload.
- */
-
-Identifier *Expression::opId()
-{
-    assert(0);
-    return NULL;
-}
-
-/***********************************
- * Get Identifier for reverse operator overload,
- * NULL if not supported for this operator.
- */
-
-Identifier *Expression::opId_r()
-{
-    return NULL;
-}
-
-/************************* Operators *****************************/
-
-Identifier *UAddExp::opId()   { return Id::uadd; }
-
-Identifier *NegExp::opId()   { return Id::neg; }
-
-Identifier *ComExp::opId()   { return Id::com; }
-
-Identifier *CastExp::opId()   { return Id::cast; }
-
-Identifier *InExp::opId()     { return Id::opIn; }
-Identifier *InExp::opId_r()     { return Id::opIn_r; }
-
-Identifier *PostExp::opId() { return (op == TOKplusplus)
-				? Id::postinc
-				: Id::postdec; }
-
-int AddExp::isCommutative()  { return TRUE; }
-Identifier *AddExp::opId()   { return Id::add; }
-Identifier *AddExp::opId_r() { return Id::add_r; }
-
-Identifier *MinExp::opId()   { return Id::sub; }
-Identifier *MinExp::opId_r() { return Id::sub_r; }
-
-int MulExp::isCommutative()  { return TRUE; }
-Identifier *MulExp::opId()   { return Id::mul; }
-Identifier *MulExp::opId_r() { return Id::mul_r; }
-
-Identifier *DivExp::opId()   { return Id::div; }
-Identifier *DivExp::opId_r() { return Id::div_r; }
-
-Identifier *ModExp::opId()   { return Id::mod; }
-Identifier *ModExp::opId_r() { return Id::mod_r; }
-
-Identifier *ShlExp::opId()   { return Id::shl; }
-Identifier *ShlExp::opId_r() { return Id::shl_r; }
-
-Identifier *ShrExp::opId()   { return Id::shr; }
-Identifier *ShrExp::opId_r() { return Id::shr_r; }
-
-Identifier *UshrExp::opId()   { return Id::ushr; }
-Identifier *UshrExp::opId_r() { return Id::ushr_r; }
-
-int AndExp::isCommutative()  { return TRUE; }
-Identifier *AndExp::opId()   { return Id::iand; }
-Identifier *AndExp::opId_r() { return Id::iand_r; }
-
-int OrExp::isCommutative()  { return TRUE; }
-Identifier *OrExp::opId()   { return Id::ior; }
-Identifier *OrExp::opId_r() { return Id::ior_r; }
-
-int XorExp::isCommutative()  { return TRUE; }
-Identifier *XorExp::opId()   { return Id::ixor; }
-Identifier *XorExp::opId_r() { return Id::ixor_r; }
-
-Identifier *CatExp::opId()   { return Id::cat; }
-Identifier *CatExp::opId_r() { return Id::cat_r; }
-
-Identifier *    AssignExp::opId()  { return Id::assign;  }
-Identifier * AddAssignExp::opId()  { return Id::addass;  }
-Identifier * MinAssignExp::opId()  { return Id::subass;  }
-Identifier * MulAssignExp::opId()  { return Id::mulass;  }
-Identifier * DivAssignExp::opId()  { return Id::divass;  }
-Identifier * ModAssignExp::opId()  { return Id::modass;  }
-Identifier * AndAssignExp::opId()  { return Id::andass;  }
-Identifier *  OrAssignExp::opId()  { return Id::orass;   }
-Identifier * XorAssignExp::opId()  { return Id::xorass;  }
-Identifier * ShlAssignExp::opId()  { return Id::shlass;  }
-Identifier * ShrAssignExp::opId()  { return Id::shrass;  }
-Identifier *UshrAssignExp::opId()  { return Id::ushrass; }
-Identifier * CatAssignExp::opId()  { return Id::catass;  }
-
-int EqualExp::isCommutative()  { return TRUE; }
-Identifier *EqualExp::opId()   { return Id::eq; }
-
-int CmpExp::isCommutative()  { return TRUE; }
-Identifier *CmpExp::opId()   { return Id::cmp; }
-
-Identifier *ArrayExp::opId()	{ return Id::index; }
-Identifier *PtrExp::opId()	{ return Id::opStar; }
-
-/************************************
- * Operator overload.
- * Check for operator overload, if so, replace
- * with function call.
- * Return NULL if not an operator overload.
- */
-
-Expression *UnaExp::op_overload(Scope *sc)
-{
-    AggregateDeclaration *ad;
-    Dsymbol *fd;
-    Type *t1 = e1->type->toBasetype();
-
-    if (t1->ty == Tclass)
-    {
-	ad = ((TypeClass *)t1)->sym;
-	goto L1;
-    }
-    else if (t1->ty == Tstruct)
-    {
-	ad = ((TypeStruct *)t1)->sym;
-
-    L1:
-	fd = search_function(ad, opId());
-	if (fd)
-	{
-	    if (op == TOKarray)
-	    {
-		Expression *e;
-		ArrayExp *ae = (ArrayExp *)this;
-
-		e = new DotIdExp(loc, e1, fd->ident);
-		e = new CallExp(loc, e, ae->arguments);
-		e = e->semantic(sc);
-		return e;
-	    }
-	    else
-	    {
-		// Rewrite +e1 as e1.add()
-		return build_overload(loc, sc, e1, NULL, fd->ident);
-	    }
-	}
-    }
-    return NULL;
-}
-
-
-Expression *BinExp::op_overload(Scope *sc)
-{
-    //printf("BinExp::op_overload() (%s)\n", toChars());
-
-    AggregateDeclaration *ad;
-    Type *t1 = e1->type->toBasetype();
-    Type *t2 = e2->type->toBasetype();
-    Identifier *id = opId();
-    Identifier *id_r = opId_r();
-
-    Match m;
-    Expressions args1;
-    Expressions args2;
-    int argsset = 0;
-
-    AggregateDeclaration *ad1;
-    if (t1->ty == Tclass)
-	ad1 = ((TypeClass *)t1)->sym;
-    else if (t1->ty == Tstruct)
-	ad1 = ((TypeStruct *)t1)->sym;
-    else
-	ad1 = NULL;
-
-    AggregateDeclaration *ad2;
-    if (t2->ty == Tclass)
-	ad2 = ((TypeClass *)t2)->sym;
-    else if (t2->ty == Tstruct)
-	ad2 = ((TypeStruct *)t2)->sym;
-    else
-	ad2 = NULL;
-
-    Dsymbol *s = NULL;
-    Dsymbol *s_r = NULL;
-    FuncDeclaration *fd = NULL;
-    TemplateDeclaration *td = NULL;
-    if (ad1 && id)
-    {
-	s = search_function(ad1, id);
-    }
-    if (ad2 && id_r)
-    {
-	s_r = search_function(ad2, id_r);
-    }
-
-    if (s || s_r)
-    {
-	/* Try:
-	 *	a.opfunc(b)
-	 *	b.opfunc_r(a)
-	 * and see which is better.
-	 */
-	Expression *e;
-	FuncDeclaration *lastf;
-
-	args1.setDim(1);
-	args1.data[0] = (void*) e1;
-	args2.setDim(1);
-	args2.data[0] = (void*) e2;
-	argsset = 1;
-
-	memset(&m, 0, sizeof(m));
-	m.last = MATCHnomatch;
-
-	if (s)
-	{
-	    fd = s->isFuncDeclaration();
-	    if (fd)
-	    {
-		overloadResolveX(&m, fd, NULL, &args2);
-	    }
-	    else
-	    {   td = s->isTemplateDeclaration();
-		templateResolve(&m, td, sc, loc, NULL, NULL, &args2);
-	    }
-	}
-
-	lastf = m.lastf;
-
-	if (s_r)
-	{
-	    fd = s_r->isFuncDeclaration();
-	    if (fd)
-	    {
-		overloadResolveX(&m, fd, NULL, &args1);
-	    }
-	    else
-	    {   td = s_r->isTemplateDeclaration();
-		templateResolve(&m, td, sc, loc, NULL, NULL, &args1);
-	    }
-	}
-
-	if (m.count > 1)
-	{
-	    // Error, ambiguous
-	    error("overloads %s and %s both match argument list for %s",
-		    m.lastf->type->toChars(),
-		    m.nextf->type->toChars(),
-		    m.lastf->toChars());
-	}
-	else if (m.last == MATCHnomatch)
-	{
-	    m.lastf = m.anyf;
-	}
-
-	if (op == TOKplusplus || op == TOKminusminus)
-	    // Kludge because operator overloading regards e++ and e--
-	    // as unary, but it's implemented as a binary.
-	    // Rewrite (e1 ++ e2) as e1.postinc()
-	    // Rewrite (e1 -- e2) as e1.postdec()
-	    e = build_overload(loc, sc, e1, NULL, id);
-	else if (lastf && m.lastf == lastf || m.last == MATCHnomatch)
-	    // Rewrite (e1 op e2) as e1.opfunc(e2)
-	    e = build_overload(loc, sc, e1, e2, id);
-	else
-	    // Rewrite (e1 op e2) as e2.opfunc_r(e1)
-	    e = build_overload(loc, sc, e2, e1, id_r);
-	return e;
-    }
-
-    if (isCommutative())
-    {
-	s = NULL;
-	s_r = NULL;
-	if (ad1 && id_r)
-	{
-	    s_r = search_function(ad1, id_r);
-	}
-	if (ad2 && id)
-	{
-	    s = search_function(ad2, id);
-	}
-
-	if (s || s_r)
-	{
-	    /* Try:
-	     *	a.opfunc_r(b)
-	     *	b.opfunc(a)
-	     * and see which is better.
-	     */
-	    Expression *e;
-	    FuncDeclaration *lastf;
-
-	    if (!argsset)
-	    {	args1.setDim(1);
-		args1.data[0] = (void*) e1;
-		args2.setDim(1);
-		args2.data[0] = (void*) e2;
-	    }
-
-	    memset(&m, 0, sizeof(m));
-	    m.last = MATCHnomatch;
-
-	    if (s_r)
-	    {
-		fd = s_r->isFuncDeclaration();
-		if (fd)
-		{
-		    overloadResolveX(&m, fd, NULL, &args2);
-		}
-		else
-		{   td = s_r->isTemplateDeclaration();
-		    templateResolve(&m, td, sc, loc, NULL, NULL, &args2);
-		}
-	    }
-	    lastf = m.lastf;
-
-	    if (s)
-	    {
-		fd = s->isFuncDeclaration();
-		if (fd)
-		{
-		    overloadResolveX(&m, fd, NULL, &args1);
-		}
-		else
-		{   td = s->isTemplateDeclaration();
-		    templateResolve(&m, td, sc, loc, NULL, NULL, &args1);
-		}
-	    }
-
-	    if (m.count > 1)
-	    {
-		// Error, ambiguous
-		error("overloads %s and %s both match argument list for %s",
-			m.lastf->type->toChars(),
-			m.nextf->type->toChars(),
-			m.lastf->toChars());
-	    }
-	    else if (m.last == MATCHnomatch)
-	    {
-		m.lastf = m.anyf;
-	    }
-
-	    if (lastf && m.lastf == lastf ||
-		id_r && m.last == MATCHnomatch)
-		// Rewrite (e1 op e2) as e1.opfunc_r(e2)
-		e = build_overload(loc, sc, e1, e2, id_r);
-	    else
-		// Rewrite (e1 op e2) as e2.opfunc(e1)
-		e = build_overload(loc, sc, e2, e1, id);
-
-	    // When reversing operands of comparison operators,
-	    // need to reverse the sense of the op
-	    switch (op)
-	    {
-		case TOKlt:	op = TOKgt;	break;
-		case TOKgt:	op = TOKlt;	break;
-		case TOKle:	op = TOKge;	break;
-		case TOKge:	op = TOKle;	break;
-
-		// Floating point compares
-		case TOKule:	op = TOKuge;	 break;
-		case TOKul:	op = TOKug;	 break;
-		case TOKuge:	op = TOKule;	 break;
-		case TOKug:	op = TOKul;	 break;
-
-		// These are symmetric
-		case TOKunord:
-		case TOKlg:
-		case TOKleg:
-		case TOKue:
-		    break;
-	    }
-
-	    return e;
-	}
-    }
-
-    return NULL;
-}
-
-/***********************************
- * Utility to build a function call out of this reference and argument.
- */
-
-Expression *build_overload(Loc loc, Scope *sc, Expression *ethis, Expression *earg, Identifier *id)
-{
-    Expression *e;
-
-    //printf("build_overload(id = '%s')\n", id->toChars());
-    //earg->print();
-    //earg->type->print();
-    e = new DotIdExp(loc, ethis, id);
-
-    if (earg)
-	e = new CallExp(loc, e, earg);
-    else
-	e = new CallExp(loc, e);
-
-    e = e->semantic(sc);
-    return e;
-}
-
-/***************************************
- * Search for function funcid in aggregate ad.
- */
-
-Dsymbol *search_function(ScopeDsymbol *ad, Identifier *funcid)
-{
-    Dsymbol *s;
-    FuncDeclaration *fd;
-    TemplateDeclaration *td;
-
-    s = ad->search(0, funcid, 0);
-    if (s)
-    {	Dsymbol *s2;
-
-	//printf("search_function: s = '%s'\n", s->kind());
-	s2 = s->toAlias();
-	//printf("search_function: s2 = '%s'\n", s2->kind());
-	fd = s2->isFuncDeclaration();
-	if (fd && fd->type->ty == Tfunction)
-	    return fd;
-
-	td = s2->isTemplateDeclaration();
-	if (td)
-	    return td;
-    }
-    return NULL;
-}
-
-
-/*****************************************
- * Given array of arguments and an aggregate type,
- * if any of the argument types are missing, attempt to infer
- * them from the aggregate type.
- */
-
-void inferApplyArgTypes(enum TOK op, Arguments *arguments, Expression *aggr)
-{
-    if (!arguments || !arguments->dim)
-	return;
-
-    /* Return if no arguments need types.
-     */
-    for (size_t u = 0; 1; u++)
-    {	if (u == arguments->dim)
-	    return;
-	Argument *arg = (Argument *)arguments->data[u];
-	if (!arg->type)
-	    break;
-    }
-
-    AggregateDeclaration *ad;
-
-    Argument *arg = (Argument *)arguments->data[0];
-    Type *taggr = aggr->type;
-    if (!taggr)
-	return;
-    Type *tab = taggr->toBasetype();
-    switch (tab->ty)
-    {
-	case Tarray:
-	case Tsarray:
-	case Ttuple:
-	    if (arguments->dim == 2)
-	    {
-		if (!arg->type)
-		    arg->type = Type::tsize_t;	// key type
-		arg = (Argument *)arguments->data[1];
-	    }
-	    if (!arg->type && tab->ty != Ttuple)
-		arg->type = tab->nextOf();	// value type
-	    break;
-
-	case Taarray:
-	{   TypeAArray *taa = (TypeAArray *)tab;
-
-	    if (arguments->dim == 2)
-	    {
-		if (!arg->type)
-		    arg->type = taa->index;	// key type
-		arg = (Argument *)arguments->data[1];
-	    }
-	    if (!arg->type)
-		arg->type = taa->next;		// value type
-	    break;
-	}
-
-	case Tclass:
-	    ad = ((TypeClass *)tab)->sym;
-	    goto Laggr;
-
-	case Tstruct:
-	    ad = ((TypeStruct *)tab)->sym;
-	    goto Laggr;
-
-	Laggr:
-	    if (arguments->dim == 1)
-	    {
-		if (!arg->type)
-		{
-		    /* Look for a head() or rear() overload
-		     */
-		    Identifier *id = (op == TOKforeach) ? Id::Fhead : Id::Ftoe;
-		    Dsymbol *s = search_function(ad, id);
-		    FuncDeclaration *fd = s ? s->isFuncDeclaration() : NULL;
-		    if (!fd)
-		    {	if (s && s->isTemplateDeclaration())
-			    break;
-			goto Lapply;
-		    }
-		    arg->type = fd->type->nextOf();
-		}
-		break;
-	    }
-
-	Lapply:
-	{   /* Look for an
-	     *	int opApply(int delegate(ref Type [, ...]) dg);
-	     * overload
-	     */
-	    Dsymbol *s = search_function(ad,
-			(op == TOKforeach_reverse) ? Id::applyReverse
-						   : Id::apply);
-	    if (s)
-	    {
-		FuncDeclaration *fd = s->isFuncDeclaration();
-		if (fd)
-		{   inferApplyArgTypesX(fd, arguments);
-		    break;
-		}
-#if 0
-		TemplateDeclaration *td = s->isTemplateDeclaration();
-		if (td)
-		{   inferApplyArgTypesZ(td, arguments);
-		    break;
-		}
-#endif
-	    }
-	    break;
-	}
-
-	case Tdelegate:
-	{
-	    if (0 && aggr->op == TOKdelegate)
-	    {	DelegateExp *de = (DelegateExp *)aggr;
-
-		FuncDeclaration *fd = de->func->isFuncDeclaration();
-		if (fd)
-		    inferApplyArgTypesX(fd, arguments);
-	    }
-	    else
-	    {
-		inferApplyArgTypesY((TypeFunction *)tab->nextOf(), arguments);
-	    }
-	    break;
-	}
-
-	default:
-	    break;		// ignore error, caught later
-    }
-}
-
-/********************************
- * Recursive helper function,
- * analogous to func.overloadResolveX().
- */
-
-int fp3(void *param, FuncDeclaration *f)
-{
-    Arguments *arguments = (Arguments *)param;
-    TypeFunction *tf = (TypeFunction *)f->type;
-    if (inferApplyArgTypesY(tf, arguments) == 1)
-	return 0;
-    if (arguments->dim == 0)
-	return 1;
-    return 0;
-}
-
-static void inferApplyArgTypesX(FuncDeclaration *fstart, Arguments *arguments)
-{
-    overloadApply(fstart, &fp3, arguments);
-}
-
-/******************************
- * Infer arguments from type of function.
- * Returns:
- *	0 match for this function
- *	1 no match for this function
- */
-
-static int inferApplyArgTypesY(TypeFunction *tf, Arguments *arguments)
-{   size_t nparams;
-    Argument *p;
-
-    if (Argument::dim(tf->parameters) != 1)
-	goto Lnomatch;
-    p = Argument::getNth(tf->parameters, 0);
-    if (p->type->ty != Tdelegate)
-	goto Lnomatch;
-    tf = (TypeFunction *)p->type->nextOf();
-    assert(tf->ty == Tfunction);
-
-    /* We now have tf, the type of the delegate. Match it against
-     * the arguments, filling in missing argument types.
-     */
-    nparams = Argument::dim(tf->parameters);
-    if (nparams == 0 || tf->varargs)
-	goto Lnomatch;		// not enough parameters
-    if (arguments->dim != nparams)
-	goto Lnomatch;		// not enough parameters
-
-    for (size_t u = 0; u < nparams; u++)
-    {
-	Argument *arg = (Argument *)arguments->data[u];
-	Argument *param = Argument::getNth(tf->parameters, u);
-	if (arg->type)
-	{   if (!arg->type->equals(param->type))
-	    {
-		/* Cannot resolve argument types. Indicate an
-		 * error by setting the number of arguments to 0.
-		 */
-		arguments->dim = 0;
-		goto Lmatch;
-	    }
-	    continue;
-	}
-	arg->type = param->type;
-    }
-  Lmatch:
-    return 0;
-
-  Lnomatch:
-    return 1;
-}
-
-/*******************************************
- * Infer foreach arg types from a template function opApply which looks like:
- *    int opApply(alias int func(ref uint))() { ... }
- */
-
-#if 0
-void inferApplyArgTypesZ(TemplateDeclaration *tstart, Arguments *arguments)
-{
-    for (TemplateDeclaration *td = tstart; td; td = td->overnext)
-    {
-        if (!td->scope)
-        {
-            error("forward reference to template %s", td->toChars());
-            return;
-        }
-        if (!td->onemember || !td->onemember->toAlias()->isFuncDeclaration())
-        {
-            error("is not a function template");
-            return;
-        }
-	if (!td->parameters || td->parameters->dim != 1)
-	    continue;
-	TemplateParameter *tp = (TemplateParameter *)td->parameters->data[0];
-	TemplateAliasParameter *tap = tp->isTemplateAliasParameter();
-	if (!tap || !tap->specType || tap->specType->ty != Tfunction)
-	    continue;
-	TypeFunction *tf = (TypeFunction *)tap->specType;
-	if (inferApplyArgTypesY(tf, arguments) == 0)	// found it
-	    return;
-    }
-}
-#endif
-
-/**************************************
- */
-
-static void templateResolve(Match *m, TemplateDeclaration *td, Scope *sc, Loc loc, Objects *targsi, Expression *ethis, Expressions *arguments)
-{
-    FuncDeclaration *fd;
-
-    assert(td);
-    fd = td->deduceFunctionTemplate(sc, loc, targsi, ethis, arguments);
-    if (!fd)
-	return;
-    m->anyf = fd;
-    if (m->last >= MATCHexact)
-    {
-	m->nextf = fd;
-	m->count++;
-    }
-    else
-    {
-	m->last = MATCHexact;
-	m->lastf = fd;
-	m->count = 1;
-    }
-}
-
+
+// Compiler implementation of the D programming language
+// Copyright (c) 1999-2009 by Digital Mars
+// All Rights Reserved
+// written by Walter Bright
+// http://www.digitalmars.com
+// License for redistribution is by either the Artistic License
+// in artistic.txt, or the GNU General Public License in gnu.txt.
+// See the included readme.txt for details.
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <assert.h>
+#if _MSC_VER
+#include <complex>
+#else
+#include <complex>
+#endif
+
+#ifdef __APPLE__
+#define integer_t dmd_integer_t
+#endif
+
+#include "rmem.h"
+
+//#include "port.h"
+#include "mtype.h"
+#include "init.h"
+#include "expression.h"
+#include "id.h"
+#include "declaration.h"
+#include "aggregate.h"
+#include "template.h"
+#include "scope.h"
+
+static void inferApplyArgTypesX(Module* from, FuncDeclaration *fstart, Arguments *arguments);
+static void inferApplyArgTypesZ(TemplateDeclaration *tstart, Arguments *arguments);
+static int inferApplyArgTypesY(TypeFunction *tf, Arguments *arguments);
+static void templateResolve(Match *m, TemplateDeclaration *td, Scope *sc, Loc loc, Objects *targsi, Expression *ethis, Expressions *arguments);
+
+/******************************** Expression **************************/
+
+
+/***********************************
+ * Determine if operands of binary op can be reversed
+ * to fit operator overload.
+ */
+
+int Expression::isCommutative()
+{
+    return FALSE;	// default is no reverse
+}
+
+/***********************************
+ * Get Identifier for operator overload.
+ */
+
+Identifier *Expression::opId()
+{
+    assert(0);
+    return NULL;
+}
+
+/***********************************
+ * Get Identifier for reverse operator overload,
+ * NULL if not supported for this operator.
+ */
+
+Identifier *Expression::opId_r()
+{
+    return NULL;
+}
+
+/************************* Operators *****************************/
+
+Identifier *UAddExp::opId()   { return Id::uadd; }
+
+Identifier *NegExp::opId()   { return Id::neg; }
+
+Identifier *ComExp::opId()   { return Id::com; }
+
+Identifier *CastExp::opId()   { return Id::cast; }
+
+Identifier *InExp::opId()     { return Id::opIn; }
+Identifier *InExp::opId_r()     { return Id::opIn_r; }
+
+Identifier *PostExp::opId() { return (op == TOKplusplus)
+				? Id::postinc
+				: Id::postdec; }
+
+int AddExp::isCommutative()  { return TRUE; }
+Identifier *AddExp::opId()   { return Id::add; }
+Identifier *AddExp::opId_r() { return Id::add_r; }
+
+Identifier *MinExp::opId()   { return Id::sub; }
+Identifier *MinExp::opId_r() { return Id::sub_r; }
+
+int MulExp::isCommutative()  { return TRUE; }
+Identifier *MulExp::opId()   { return Id::mul; }
+Identifier *MulExp::opId_r() { return Id::mul_r; }
+
+Identifier *DivExp::opId()   { return Id::div; }
+Identifier *DivExp::opId_r() { return Id::div_r; }
+
+Identifier *ModExp::opId()   { return Id::mod; }
+Identifier *ModExp::opId_r() { return Id::mod_r; }
+
+Identifier *ShlExp::opId()   { return Id::shl; }
+Identifier *ShlExp::opId_r() { return Id::shl_r; }
+
+Identifier *ShrExp::opId()   { return Id::shr; }
+Identifier *ShrExp::opId_r() { return Id::shr_r; }
+
+Identifier *UshrExp::opId()   { return Id::ushr; }
+Identifier *UshrExp::opId_r() { return Id::ushr_r; }
+
+int AndExp::isCommutative()  { return TRUE; }
+Identifier *AndExp::opId()   { return Id::iand; }
+Identifier *AndExp::opId_r() { return Id::iand_r; }
+
+int OrExp::isCommutative()  { return TRUE; }
+Identifier *OrExp::opId()   { return Id::ior; }
+Identifier *OrExp::opId_r() { return Id::ior_r; }
+
+int XorExp::isCommutative()  { return TRUE; }
+Identifier *XorExp::opId()   { return Id::ixor; }
+Identifier *XorExp::opId_r() { return Id::ixor_r; }
+
+Identifier *CatExp::opId()   { return Id::cat; }
+Identifier *CatExp::opId_r() { return Id::cat_r; }
+
+Identifier *    AssignExp::opId()  { return Id::assign;  }
+Identifier * AddAssignExp::opId()  { return Id::addass;  }
+Identifier * MinAssignExp::opId()  { return Id::subass;  }
+Identifier * MulAssignExp::opId()  { return Id::mulass;  }
+Identifier * DivAssignExp::opId()  { return Id::divass;  }
+Identifier * ModAssignExp::opId()  { return Id::modass;  }
+Identifier * AndAssignExp::opId()  { return Id::andass;  }
+Identifier *  OrAssignExp::opId()  { return Id::orass;   }
+Identifier * XorAssignExp::opId()  { return Id::xorass;  }
+Identifier * ShlAssignExp::opId()  { return Id::shlass;  }
+Identifier * ShrAssignExp::opId()  { return Id::shrass;  }
+Identifier *UshrAssignExp::opId()  { return Id::ushrass; }
+Identifier * CatAssignExp::opId()  { return Id::catass;  }
+
+int EqualExp::isCommutative()  { return TRUE; }
+Identifier *EqualExp::opId()   { return Id::eq; }
+
+int CmpExp::isCommutative()  { return TRUE; }
+Identifier *CmpExp::opId()   { return Id::cmp; }
+
+Identifier *ArrayExp::opId()	{ return Id::index; }
+Identifier *PtrExp::opId()	{ return Id::opStar; }
+
+/************************************
+ * Operator overload.
+ * Check for operator overload, if so, replace
+ * with function call.
+ * Return NULL if not an operator overload.
+ */
+
+Expression *UnaExp::op_overload(Scope *sc)
+{
+    //printf("UnaExp::op_overload() (%s)\n", toChars());
+    AggregateDeclaration *ad;
+    Dsymbol *fd;
+    Type *t1 = e1->type->toBasetype();
+
+    if (t1->ty == Tclass)
+    {
+	ad = ((TypeClass *)t1)->sym;
+	goto L1;
+    }
+    else if (t1->ty == Tstruct)
+    {
+	ad = ((TypeStruct *)t1)->sym;
+
+    L1:
+	fd = search_function(ad, opId());
+	if (fd)
+	{
+	    if (op == TOKarray)
+	    {
+		/* Rewrite op e1[arguments] as:
+		 *    e1.fd(arguments)
+		 */
+		Expression *e = new DotIdExp(loc, e1, fd->ident);
+		ArrayExp *ae = (ArrayExp *)this;
+		e = new CallExp(loc, e, ae->arguments);
+		e = e->semantic(sc);
+		return e;
+	    }
+	    else
+	    {
+		// Rewrite +e1 as e1.add()
+		return build_overload(loc, sc, e1, NULL, fd->ident);
+	    }
+	}
+
+	// Didn't find it. Forward to aliasthis
+	if (ad->aliasthis)
+	{
+	    /* Rewrite op(e1) as:
+	     *	op(e1.aliasthis)
+	     */
+	    Expression *e1 = new DotIdExp(loc, this->e1, ad->aliasthis->ident);
+	    Expression *e = copy();
+	    ((UnaExp *)e)->e1 = e1;
+	    e = e->semantic(sc);
+	    return e;
+	}
+    }
+    return NULL;
+}
+
+
+Expression *BinExp::op_overload(Scope *sc)
+{
+    //printf("BinExp::op_overload() (%s)\n", toChars());
+
+    AggregateDeclaration *ad;
+    Type *t1 = e1->type->toBasetype();
+    Type *t2 = e2->type->toBasetype();
+    Identifier *id = opId();
+    Identifier *id_r = opId_r();
+
+    Match m;
+    Expressions args1;
+    Expressions args2;
+    int argsset = 0;
+
+    AggregateDeclaration *ad1;
+    if (t1->ty == Tclass)
+	ad1 = ((TypeClass *)t1)->sym;
+    else if (t1->ty == Tstruct)
+	ad1 = ((TypeStruct *)t1)->sym;
+    else
+	ad1 = NULL;
+
+    AggregateDeclaration *ad2;
+    if (t2->ty == Tclass)
+	ad2 = ((TypeClass *)t2)->sym;
+    else if (t2->ty == Tstruct)
+	ad2 = ((TypeStruct *)t2)->sym;
+    else
+	ad2 = NULL;
+
+    Dsymbol *s = NULL;
+    Dsymbol *s_r = NULL;
+    FuncDeclaration *fd = NULL;
+    TemplateDeclaration *td = NULL;
+    if (ad1 && id)
+    {
+	s = search_function(ad1, id);
+    }
+    if (ad2 && id_r)
+    {
+	s_r = search_function(ad2, id_r);
+    }
+
+    if (s || s_r)
+    {
+	/* Try:
+	 *	a.opfunc(b)
+	 *	b.opfunc_r(a)
+	 * and see which is better.
+	 */
+	Expression *e;
+	FuncDeclaration *lastf;
+
+	args1.setDim(1);
+	args1.data[0] = (void*) e1;
+	args2.setDim(1);
+	args2.data[0] = (void*) e2;
+	argsset = 1;
+
+	memset(&m, 0, sizeof(m));
+	m.last = MATCHnomatch;
+
+	if (s)
+	{
+	    fd = s->isFuncDeclaration();
+	    if (fd)
+	    {
+		overloadResolveX(&m, fd, NULL, &args2, sc->module);
+	    }
+	    else
+	    {   td = s->isTemplateDeclaration();
+		templateResolve(&m, td, sc, loc, NULL, NULL, &args2);
+	    }
+	}
+	
+	lastf = m.lastf;
+
+	if (s_r)
+	{
+	    fd = s_r->isFuncDeclaration();
+	    if (fd)
+	    {
+		overloadResolveX(&m, fd, NULL, &args1, sc->module);
+	    }
+	    else
+	    {   td = s_r->isTemplateDeclaration();
+		templateResolve(&m, td, sc, loc, NULL, NULL, &args1);
+	    }
+	}
+
+	if (m.count > 1)
+	{
+	    // Error, ambiguous
+	    error("overloads %s and %s both match argument list for %s",
+		    m.lastf->type->toChars(),
+		    m.nextf->type->toChars(),
+		    m.lastf->toChars());
+	}
+	else if (m.last == MATCHnomatch)
+	{
+	    m.lastf = m.anyf;
+	}
+
+	if (op == TOKplusplus || op == TOKminusminus)
+	    // Kludge because operator overloading regards e++ and e--
+	    // as unary, but it's implemented as a binary.
+	    // Rewrite (e1 ++ e2) as e1.postinc()
+	    // Rewrite (e1 -- e2) as e1.postdec()
+	    e = build_overload(loc, sc, e1, NULL, id);
+	else if (lastf && m.lastf == lastf || m.last == MATCHnomatch)
+	    // Rewrite (e1 op e2) as e1.opfunc(e2)
+	    e = build_overload(loc, sc, e1, e2, id);
+	else
+	    // Rewrite (e1 op e2) as e2.opfunc_r(e1)
+	    e = build_overload(loc, sc, e2, e1, id_r);
+	return e;
+    }
+
+    if (isCommutative())
+    {
+	s = NULL;
+	s_r = NULL;
+	if (ad1 && id_r)
+	{
+	    s_r = search_function(ad1, id_r);
+	}
+	if (ad2 && id)
+	{
+	    s = search_function(ad2, id);
+	}
+
+	if (s || s_r)
+	{
+	    /* Try:
+	     *	a.opfunc_r(b)
+	     *	b.opfunc(a)
+	     * and see which is better.
+	     */
+
+	    if (!argsset)
+	    {	args1.setDim(1);
+		args1.data[0] = (void*) e1;
+		args2.setDim(1);
+		args2.data[0] = (void*) e2;
+	    }
+
+	    memset(&m, 0, sizeof(m));
+	    m.last = MATCHnomatch;
+
+	    if (s_r)
+	    {
+		fd = s_r->isFuncDeclaration();
+		if (fd)
+		{
+		    overloadResolveX(&m, fd, NULL, &args2, sc->module);
+		}
+		else
+		{   td = s_r->isTemplateDeclaration();
+		    templateResolve(&m, td, sc, loc, NULL, NULL, &args2);
+		}
+	    }
+	    FuncDeclaration *lastf = m.lastf;
+
+	    if (s)
+	    {
+		fd = s->isFuncDeclaration();
+		if (fd)
+		{
+		    overloadResolveX(&m, fd, NULL, &args1, sc->module);
+		}
+		else
+		{   td = s->isTemplateDeclaration();
+		    templateResolve(&m, td, sc, loc, NULL, NULL, &args1);
+		}
+	    }
+
+	    if (m.count > 1)
+	    {
+		// Error, ambiguous
+		error("overloads %s and %s both match argument list for %s",
+			m.lastf->type->toChars(),
+			m.nextf->type->toChars(),
+			m.lastf->toChars());
+	    }
+	    else if (m.last == MATCHnomatch)
+	    {
+		m.lastf = m.anyf;
+	    }
+
+	    Expression *e;
+	    if (lastf && m.lastf == lastf ||
+		id_r && m.last == MATCHnomatch)
+		// Rewrite (e1 op e2) as e1.opfunc_r(e2)
+		e = build_overload(loc, sc, e1, e2, id_r);
+	    else
+		// Rewrite (e1 op e2) as e2.opfunc(e1)
+		e = build_overload(loc, sc, e2, e1, id);
+
+	    // When reversing operands of comparison operators,
+	    // need to reverse the sense of the op
+	    switch (op)
+	    {
+		case TOKlt:	op = TOKgt;	break;
+		case TOKgt:	op = TOKlt;	break;
+		case TOKle:	op = TOKge;	break;
+		case TOKge:	op = TOKle;	break;
+
+		// Floating point compares
+		case TOKule:	op = TOKuge;	 break;
+		case TOKul:	op = TOKug;	 break;
+		case TOKuge:	op = TOKule;	 break;
+		case TOKug:	op = TOKul;	 break;
+
+		// These are symmetric
+		case TOKunord:
+		case TOKlg:
+		case TOKleg:
+		case TOKue:
+		    break;
+	    }
+
+	    return e;
+	}
+    }
+
+    // Try alias this on first operand
+    if (ad1 && ad1->aliasthis)
+    {
+	/* Rewrite (e1 op e2) as:
+	 *	(e1.aliasthis op e2)
+	 */
+	Expression *e1 = new DotIdExp(loc, this->e1, ad1->aliasthis->ident);
+	Expression *e = copy();
+	((BinExp *)e)->e1 = e1;
+	e = e->semantic(sc);
+	return e;
+    }
+
+    // Try alias this on second operand
+    if (ad2 && ad2->aliasthis)
+    {
+	/* Rewrite (e1 op e2) as:
+	 *	(e1 op e2.aliasthis)
+	 */
+	Expression *e2 = new DotIdExp(loc, this->e2, ad2->aliasthis->ident);
+	Expression *e = copy();
+	((BinExp *)e)->e2 = e2;
+	e = e->semantic(sc);
+	return e;
+    }
+
+    return NULL;
+}
+
+/***********************************
+ * Utility to build a function call out of this reference and argument.
+ */
+
+Expression *build_overload(Loc loc, Scope *sc, Expression *ethis, Expression *earg, Identifier *id)
+{
+    Expression *e;
+
+    //printf("build_overload(id = '%s')\n", id->toChars());
+    //earg->print();
+    //earg->type->print();
+    e = new DotIdExp(loc, ethis, id);
+
+    if (earg)
+	e = new CallExp(loc, e, earg);
+    else
+	e = new CallExp(loc, e);
+
+    e = e->semantic(sc);
+    return e;
+}
+
+/***************************************
+ * Search for function funcid in aggregate ad.
+ */
+
+Dsymbol *search_function(ScopeDsymbol *ad, Identifier *funcid)
+{
+    Dsymbol *s;
+    FuncDeclaration *fd;
+    TemplateDeclaration *td;
+
+    s = ad->search(0, funcid, 0);
+    if (s)
+    {	Dsymbol *s2;
+
+	//printf("search_function: s = '%s'\n", s->kind());
+	s2 = s->toAlias();
+	//printf("search_function: s2 = '%s'\n", s2->kind());
+	fd = s2->isFuncDeclaration();
+	if (fd && fd->type->ty == Tfunction)
+	    return fd;
+
+	td = s2->isTemplateDeclaration();
+	if (td)
+	    return td;
+    }
+    return NULL;
+}
+
+
+/*****************************************
+ * Given array of arguments and an aggregate type,
+ * if any of the argument types are missing, attempt to infer
+ * them from the aggregate type.
+ */
+
+void inferApplyArgTypes(enum TOK op, Arguments *arguments, Expression *aggr, Module* from)
+{
+    if (!arguments || !arguments->dim)
+	return;
+
+    /* Return if no arguments need types.
+     */
+    for (size_t u = 0; 1; u++)
+    {	if (u == arguments->dim)
+	    return;
+	Argument *arg = (Argument *)arguments->data[u];
+	if (!arg->type)
+	    break;
+    }
+
+    AggregateDeclaration *ad;
+
+    Argument *arg = (Argument *)arguments->data[0];
+    Type *taggr = aggr->type;
+    if (!taggr)
+	return;
+    Type *tab = taggr->toBasetype();
+    switch (tab->ty)
+    {
+	case Tarray:
+	case Tsarray:
+	case Ttuple:
+	    if (arguments->dim == 2)
+	    {
+		if (!arg->type)
+		    arg->type = Type::tsize_t;	// key type
+		arg = (Argument *)arguments->data[1];
+	    }
+	    if (!arg->type && tab->ty != Ttuple)
+		arg->type = tab->nextOf();	// value type
+	    break;
+
+	case Taarray:
+	{   TypeAArray *taa = (TypeAArray *)tab;
+
+	    if (arguments->dim == 2)
+	    {
+		if (!arg->type)
+		    arg->type = taa->index;	// key type
+		arg = (Argument *)arguments->data[1];
+	    }
+	    if (!arg->type)
+		arg->type = taa->next;		// value type
+	    break;
+	}
+
+	case Tclass:
+	    ad = ((TypeClass *)tab)->sym;
+	    goto Laggr;
+
+	case Tstruct:
+	    ad = ((TypeStruct *)tab)->sym;
+	    goto Laggr;
+
+	Laggr:
+	    if (arguments->dim == 1)
+	    {
+		if (!arg->type)
+		{
+		    /* Look for a head() or rear() overload
+		     */
+		    Identifier *id = (op == TOKforeach) ? Id::Fhead : Id::Ftoe;
+		    Dsymbol *s = search_function(ad, id);
+		    FuncDeclaration *fd = s ? s->isFuncDeclaration() : NULL;
+		    if (!fd)
+		    {	if (s && s->isTemplateDeclaration())
+			    break;
+			goto Lapply;
+		    }
+		    arg->type = fd->type->nextOf();
+		}
+		break;
+	    }
+
+	Lapply:
+	{   /* Look for an
+	     *	int opApply(int delegate(ref Type [, ...]) dg);
+	     * overload
+	     */
+	    Dsymbol *s = search_function(ad,
+			(op == TOKforeach_reverse) ? Id::applyReverse
+						   : Id::apply);
+	    if (s)
+	    {
+		FuncDeclaration *fd = s->isFuncDeclaration();
+		if (fd) 
+		{   inferApplyArgTypesX(from, fd, arguments);
+		    break;
+		}
+#if 0
+		TemplateDeclaration *td = s->isTemplateDeclaration();
+		if (td)
+		{   inferApplyArgTypesZ(td, arguments);
+		    break;
+		}
+#endif
+	    }
+	    break;
+	}
+
+	case Tdelegate:
+	{
+	    if (0 && aggr->op == TOKdelegate)
+	    {	DelegateExp *de = (DelegateExp *)aggr;
+
+		FuncDeclaration *fd = de->func->isFuncDeclaration();
+		if (fd)
+		    inferApplyArgTypesX(from, fd, arguments);
+	    }
+	    else
+	    {
+		inferApplyArgTypesY((TypeFunction *)tab->nextOf(), arguments);
+	    }
+	    break;
+	}
+
+	default:
+	    break;		// ignore error, caught later
+    }
+}
+
+/********************************
+ * Recursive helper function,
+ * analogous to func.overloadResolveX().
+ */
+
+int fp3(void *param, FuncDeclaration *f)
+{
+    Arguments *arguments = (Arguments *)param;
+    TypeFunction *tf = (TypeFunction *)f->type;
+    if (inferApplyArgTypesY(tf, arguments) == 1)
+	return 0;
+    if (arguments->dim == 0)
+	return 1;
+    return 0;
+}
+
+static void inferApplyArgTypesX(Module* from, FuncDeclaration *fstart, Arguments *arguments)
+{
+    overloadApply(from, fstart, &fp3, arguments);
+}
+
+/******************************
+ * Infer arguments from type of function.
+ * Returns:
+ *	0 match for this function
+ *	1 no match for this function
+ */
+
+static int inferApplyArgTypesY(TypeFunction *tf, Arguments *arguments)
+{   size_t nparams;
+    Argument *p;
+
+    if (Argument::dim(tf->parameters) != 1)
+	goto Lnomatch;
+    p = Argument::getNth(tf->parameters, 0);
+    if (p->type->ty != Tdelegate)
+	goto Lnomatch;
+    tf = (TypeFunction *)p->type->nextOf();
+    assert(tf->ty == Tfunction);
+
+    /* We now have tf, the type of the delegate. Match it against
+     * the arguments, filling in missing argument types.
+     */
+    nparams = Argument::dim(tf->parameters);
+    if (nparams == 0 || tf->varargs)
+	goto Lnomatch;		// not enough parameters
+    if (arguments->dim != nparams)
+	goto Lnomatch;		// not enough parameters
+
+    for (size_t u = 0; u < nparams; u++)
+    {
+	Argument *arg = (Argument *)arguments->data[u];
+	Argument *param = Argument::getNth(tf->parameters, u);
+	if (arg->type)
+	{   if (!arg->type->equals(param->type))
+	    {
+		/* Cannot resolve argument types. Indicate an
+		 * error by setting the number of arguments to 0.
+		 */
+		arguments->dim = 0;
+		goto Lmatch;
+	    }
+	    continue;
+	}
+	arg->type = param->type;
+    }
+  Lmatch:
+    return 0;
+
+  Lnomatch:
+    return 1;
+}
+
+/*******************************************
+ * Infer foreach arg types from a template function opApply which looks like:
+ *    int opApply(alias int func(ref uint))() { ... }
+ */
+
+#if 0
+void inferApplyArgTypesZ(TemplateDeclaration *tstart, Arguments *arguments)
+{
+    for (TemplateDeclaration *td = tstart; td; td = td->overnext)
+    {
+        if (!td->scope)
+        {
+            error("forward reference to template %s", td->toChars());
+            return;
+        }
+        if (!td->onemember || !td->onemember->toAlias()->isFuncDeclaration())
+        {
+            error("is not a function template");
+            return;
+        }
+	if (!td->parameters || td->parameters->dim != 1)
+	    continue;
+	TemplateParameter *tp = (TemplateParameter *)td->parameters->data[0];
+	TemplateAliasParameter *tap = tp->isTemplateAliasParameter();
+	if (!tap || !tap->specType || tap->specType->ty != Tfunction)
+	    continue;
+	TypeFunction *tf = (TypeFunction *)tap->specType;
+	if (inferApplyArgTypesY(tf, arguments) == 0)	// found it
+	    return;
+    }
+}
+#endif
+
+/**************************************
+ */
+
+static void templateResolve(Match *m, TemplateDeclaration *td, Scope *sc, Loc loc, Objects *targsi, Expression *ethis, Expressions *arguments)
+{
+    FuncDeclaration *fd;
+
+    assert(td);
+    fd = td->deduceFunctionTemplate(sc, loc, targsi, ethis, arguments);
+    if (!fd)
+	return;
+    m->anyf = fd;
+    if (m->last >= MATCHexact)
+    {
+	m->nextf = fd;
+	m->count++;
+    }
+    else
+    {
+	m->last = MATCHexact;
+	m->lastf = fd;
+	m->count = 1;
+    }
+}
+
--- a/dmd2/optimize.c	Mon Jun 01 01:28:18 2009 +0200
+++ b/dmd2/optimize.c	Mon Jun 01 19:02:20 2009 +0100
@@ -1,914 +1,948 @@
-
-// Compiler implementation of the D programming language
-// Copyright (c) 1999-2007 by Digital Mars
-// All Rights Reserved
-// written by Walter Bright
-// http://www.digitalmars.com
-// License for redistribution is by either the Artistic License
-// in artistic.txt, or the GNU General Public License in gnu.txt.
-// See the included readme.txt for details.
-
-#include <stdio.h>
-#include <ctype.h>
-#include <assert.h>
-#include <math.h>
-
-#if __DMC__
-#include <complex.h>
-#endif
-
-#include "lexer.h"
-#include "mtype.h"
-#include "expression.h"
-#include "declaration.h"
-#include "aggregate.h"
-#include "init.h"
-
-
-#ifdef IN_GCC
-#include "d-gcc-real.h"
-
-/* %% fix? */
-extern "C" bool real_isnan (const real_t *);
-#endif
-
-static real_t zero;	// work around DMC bug for now
-
-
-/*************************************
- * If variable has a const initializer,
- * return that initializer.
- */
-
-Expression *expandVar(int result, VarDeclaration *v)
-{
-    //printf("expandVar(result = %d, v = %s)\n", result, v ? v->toChars() : "null");
-    Expression *e = NULL;
-    if (v && (v->isConst() || v->isInvariant() || v->storage_class & STCmanifest))
-    {
-	Type *tb = v->type->toBasetype();
-	if (result & WANTinterpret ||
-	    v->storage_class & STCmanifest ||
-	    (tb->ty != Tsarray && tb->ty != Tstruct)
-	   )
-	{
-	    if (v->init)
-	    {
-		if (v->inuse)
-		    goto L1;
-		Expression *ei = v->init->toExpression();
-		if (!ei)
-		    goto L1;
-		if (ei->op == TOKconstruct || ei->op == TOKblit)
-		{   AssignExp *ae = (AssignExp *)ei;
-		    ei = ae->e2;
-		    if (ei->isConst() != 1 && ei->op != TOKstring)
-			goto L1;
-		    if (ei->type != v->type)
-			goto L1;
-		}
-		if (v->scope)
-		{
-		    v->inuse++;
-		    e = ei->syntaxCopy();
-		    e = e->semantic(v->scope);
-		    e = e->implicitCastTo(v->scope, v->type);
-		    v->scope = NULL;
-		    v->inuse--;
-		}
-		else if (!ei->type)
-		{
-		    goto L1;
-		}
-		else
-		    // Should remove the copy() operation by
-		    // making all mods to expressions copy-on-write
-		    e = ei->copy();
-	    }
-	    else
-	    {
-#if 1
-		goto L1;
-#else
-		// BUG: what if const is initialized in constructor?
-		e = v->type->defaultInit();
-		e->loc = e1->loc;
-#endif
-	    }
-	    if (e->type != v->type)
-	    {
-		e = e->castTo(NULL, v->type);
-	    }
-	    e = e->optimize(result);
-	}
-    }
-L1:
-    //if (e) printf("\te = %s, e->type = %s\n", e->toChars(), e->type->toChars());
-    return e;
-}
-
-
-Expression *fromConstInitializer(int result, Expression *e1)
-{
-    //printf("fromConstInitializer(result = %x, %s)\n", result, e1->toChars());
-    //static int xx; if (xx++ == 10) assert(0);
-    Expression *e = e1;
-    if (e1->op == TOKvar)
-    {	VarExp *ve = (VarExp *)e1;
-	VarDeclaration *v = ve->var->isVarDeclaration();
-	e = expandVar(result, v);
-	if (e)
-	{   if (e->type != e1->type)
-	    {   // Type 'paint' operation
-		e = e->copy();
-		e->type = e1->type;
-	    }
-	}
-	else
-	    e = e1;
-    }
-    return e;
-}
-
-
-Expression *Expression::optimize(int result)
-{
-    //printf("Expression::optimize(result = x%x) %s\n", result, toChars());
-    return this;
-}
-
-Expression *VarExp::optimize(int result)
-{
-    return fromConstInitializer(result, this);
-}
-
-Expression *TupleExp::optimize(int result)
-{
-    for (size_t i = 0; i < exps->dim; i++)
-    {   Expression *e = (Expression *)exps->data[i];
-
-	e = e->optimize(WANTvalue | (result & WANTinterpret));
-	exps->data[i] = (void *)e;
-    }
-    return this;
-}
-
-Expression *ArrayLiteralExp::optimize(int result)
-{
-    if (elements)
-    {
-	for (size_t i = 0; i < elements->dim; i++)
-	{   Expression *e = (Expression *)elements->data[i];
-
-	    e = e->optimize(WANTvalue | (result & WANTinterpret));
-	    elements->data[i] = (void *)e;
-	}
-    }
-    return this;
-}
-
-Expression *AssocArrayLiteralExp::optimize(int result)
-{
-    assert(keys->dim == values->dim);
-    for (size_t i = 0; i < keys->dim; i++)
-    {   Expression *e = (Expression *)keys->data[i];
-
-	e = e->optimize(WANTvalue | (result & WANTinterpret));
-	keys->data[i] = (void *)e;
-
-	e = (Expression *)values->data[i];
-	e = e->optimize(WANTvalue | (result & WANTinterpret));
-	values->data[i] = (void *)e;
-    }
-    return this;
-}
-
-Expression *StructLiteralExp::optimize(int result)
-{
-    if (elements)
-    {
-	for (size_t i = 0; i < elements->dim; i++)
-	{   Expression *e = (Expression *)elements->data[i];
-	    if (!e)
-		continue;
-	    e = e->optimize(WANTvalue | (result & WANTinterpret));
-	    elements->data[i] = (void *)e;
-	}
-    }
-    return this;
-}
-
-Expression *TypeExp::optimize(int result)
-{
-    return this;
-}
-
-Expression *UnaExp::optimize(int result)
-{
-    e1 = e1->optimize(result);
-    return this;
-}
-
-Expression *NegExp::optimize(int result)
-{   Expression *e;
-
-    e1 = e1->optimize(result);
-    if (e1->isConst() == 1)
-    {
-	e = Neg(type, e1);
-    }
-    else
-	e = this;
-    return e;
-}
-
-Expression *ComExp::optimize(int result)
-{   Expression *e;
-
-    e1 = e1->optimize(result);
-    if (e1->isConst() == 1)
-    {
-	e = Com(type, e1);
-    }
-    else
-	e = this;
-    return e;
-}
-
-Expression *NotExp::optimize(int result)
-{   Expression *e;
-
-    e1 = e1->optimize(result);
-    if (e1->isConst() == 1)
-    {
-	e = Not(type, e1);
-    }
-    else
-	e = this;
-    return e;
-}
-
-Expression *BoolExp::optimize(int result)
-{   Expression *e;
-
-    e1 = e1->optimize(result);
-    if (e1->isConst() == 1)
-    {
-	e = Bool(type, e1);
-    }
-    else
-	e = this;
-    return e;
-}
-
-Expression *AddrExp::optimize(int result)
-{   Expression *e;
-
-    //printf("AddrExp::optimize(result = %d) %s\n", result, toChars());
-
-    /* Rewrite &(a,b) as (a,&b)
-     */
-    if (e1->op == TOKcomma)
-    {	CommaExp *ce = (CommaExp *)e1;
-	AddrExp *ae = new AddrExp(loc, ce->e2);
-	ae->type = type;
-	e = new CommaExp(ce->loc, ce->e1, ae);
-	e->type = type;
-	return e->optimize(result);
-    }
-
-    if (e1->op == TOKvar)
-    {	VarExp *ve = (VarExp *)e1;
-	if (ve->var->storage_class & STCmanifest)
-	    e1 = e1->optimize(result);
-    }
-    else
-	e1 = e1->optimize(result);
-
-    // Convert &*ex to ex
-    if (e1->op == TOKstar)
-    {	Expression *ex;
-
-	ex = ((PtrExp *)e1)->e1;
-	if (type->equals(ex->type))
-	    e = ex;
-	else
-	{
-	    e = ex->copy();
-	    e->type = type;
-	}
-	return e;
-    }
-#if !IN_LLVM
-    if (e1->op == TOKvar)
-    {	VarExp *ve = (VarExp *)e1;
-	if (!ve->var->isOut() && !ve->var->isRef() &&
-	    !ve->var->isImportedSymbol())
-	{
-	    SymOffExp *se = new SymOffExp(loc, ve->var, 0, ve->hasOverloads);
-	    se->type = type;
-	    return se;
-	}
-    }
-    if (e1->op == TOKindex)
-    {	// Convert &array[n] to &array+n
-	IndexExp *ae = (IndexExp *)e1;
-
-	if (ae->e2->op == TOKint64 && ae->e1->op == TOKvar)
-	{
-	    integer_t index = ae->e2->toInteger();
-	    VarExp *ve = (VarExp *)ae->e1;
-	    if (ve->type->ty == Tsarray
-		&& !ve->var->isImportedSymbol())
-	    {
-		TypeSArray *ts = (TypeSArray *)ve->type;
-		integer_t dim = ts->dim->toInteger();
-		if (index < 0 || index >= dim)
-		    error("array index %lld is out of bounds [0..%lld]", index, dim);
-		e = new SymOffExp(loc, ve->var, index * ts->nextOf()->size());
-		e->type = type;
-		return e;
-	    }
-	}
-    }
-#endif
-    return this;
-}
-
-Expression *PtrExp::optimize(int result)
-{
-    //printf("PtrExp::optimize(result = x%x) %s\n", result, toChars());
-    e1 = e1->optimize(result);
-    // Convert *&ex to ex
-    if (e1->op == TOKaddress)
-    {	Expression *e;
-	Expression *ex;
-
-	ex = ((AddrExp *)e1)->e1;
-	if (type->equals(ex->type))
-	    e = ex;
-	else
-	{
-	    e = ex->copy();
-	    e->type = type;
-	}
-	return e;
-    }
-    // Constant fold *(&structliteral + offset)
-    if (e1->op == TOKadd)
-    {
-	Expression *e;
-	e = Ptr(type, e1);
-	if (e != EXP_CANT_INTERPRET)
-	    return e;
-    }
-
-    if (e1->op == TOKsymoff)
-    {	SymOffExp *se = (SymOffExp *)e1;
-	VarDeclaration *v = se->var->isVarDeclaration();
-	Expression *e = expandVar(result, v);
-	if (e && e->op == TOKstructliteral)
-	{   StructLiteralExp *sle = (StructLiteralExp *)e;
-	    e = sle->getField(type, se->offset);
-	    if (e != EXP_CANT_INTERPRET)
-		return e;
-	}
-    }
-    return this;
-}
-
-///////////////////////////////////////////
-// LDC
-Expression *DotVarExp::optimize(int result)
-{
-    e1 = e1->optimize(result);
-
-    // Constant fold structliteral.member
-    if (e1->op == TOKstructliteral)
-    {   StructLiteralExp *se = (StructLiteralExp *)e1;
-
-    VarDeclaration* v;
-    if (v = var->isVarDeclaration())
-    {
-        Expression *e = se->getField(type, v->offset);
-        if (!e)
-        e = EXP_CANT_INTERPRET;
-        return e;
-    }
-    }
-
-    return this;
-}
-///////////////////////////////////////////
-
-Expression *CallExp::optimize(int result)
-{
-    //printf("CallExp::optimize(result = %d) %s\n", result, toChars());
-    Expression *e = this;
-
-    e1 = e1->optimize(result);
-    if (e1->op == TOKvar)
-    {
-	FuncDeclaration *fd = ((VarExp *)e1)->var->isFuncDeclaration();
-	if (fd)
-	{
-	    enum BUILTIN b = fd->isBuiltin();
-	    if (b)
-	    {
-		e = eval_builtin(b, arguments);
-		if (!e)			// failed
-		    e = this;		// evaluate at runtime
-	    }
-	    else if (result & WANTinterpret)
-	    {
-		Expression *eresult = fd->interpret(NULL, arguments);
-		if (eresult && eresult != EXP_VOID_INTERPRET)
-		    e = eresult;
-		else
-		    error("cannot evaluate %s at compile time", toChars());
-	    }
-	}
-    }
-    return e;
-}
-
-
-Expression *CastExp::optimize(int result)
-{
-    //printf("CastExp::optimize(result = %d) %s\n", result, toChars());
-    //printf("from %s to %s\n", type->toChars(), to->toChars());
-    //printf("from %s\n", type->toChars());
-    //printf("e1->type %s\n", e1->type->toChars());
-    //printf("type = %p\n", type);
-    assert(type);
-    enum TOK op1 = e1->op;
-#define X 0
-
-    e1 = e1->optimize(result);
-    e1 = fromConstInitializer(result, e1);
-
-    if ((e1->op == TOKstring || e1->op == TOKarrayliteral) &&
-	(type->ty == Tpointer || type->ty == Tarray) &&
-	e1->type->nextOf()->size() == type->nextOf()->size()
-       )
-    {
-	e1 = e1->castTo(NULL, type);
-	if (X) printf(" returning1 %s\n", e1->toChars());
-	return e1;
-    }
-
-    if (e1->op == TOKstructliteral &&
-	e1->type->implicitConvTo(type) >= MATCHconst)
-    {
-	e1->type = type;
-	if (X) printf(" returning2 %s\n", e1->toChars());
-	return e1;
-    }
-
-    /* The first test here is to prevent infinite loops
-     */
-    if (op1 != TOKarrayliteral && e1->op == TOKarrayliteral)
-	return e1->castTo(NULL, to);
-    if (e1->op == TOKnull &&
-	(type->ty == Tpointer || type->ty == Tclass || type->ty == Tarray))
-    {
-	e1->type = type;
-	if (X) printf(" returning3 %s\n", e1->toChars());
-	return e1;
-    }
-
-    if (result & WANTflags && type->ty == Tclass && e1->type->ty == Tclass)
-    {
-	// See if we can remove an unnecessary cast
-	ClassDeclaration *cdfrom;
-	ClassDeclaration *cdto;
-	int offset;
-
-	cdfrom = e1->type->isClassHandle();
-	cdto   = type->isClassHandle();
-	if (cdto->isBaseOf(cdfrom, &offset) && offset == 0)
-	{
-	    e1->type = type;
-	    if (X) printf(" returning4 %s\n", e1->toChars());
-	    return e1;
-	}
-    }
-
-    // We can convert 'head const' to mutable
-    if (to->constOf()->equals(e1->type->constOf()))
-//    if (to->constConv(e1->type) >= MATCHconst)
-    {
-	e1->type = type;
-	if (X) printf(" returning5 %s\n", e1->toChars());
-	return e1;
-    }
-
-    Expression *e;
-
-    if (e1->isConst())
-    {
-	if (e1->op == TOKsymoff)
-	{
-	    if (type->size() == e1->type->size() &&
-		type->toBasetype()->ty != Tsarray)
-	    {
-		e1->type = type;
-		return e1;
-	    }
-	    return this;
-	}
-	if (to->toBasetype()->ty == Tvoid)
-	    e = this;
-	else
-	    e = Cast(type, to, e1);
-    }
-    else
-	e = this;
-    if (X) printf(" returning6 %s\n", e->toChars());
-    return e;
-#undef X
-}
-
-Expression *BinExp::optimize(int result)
-{
-    //printf("BinExp::optimize(result = %d) %s\n", result, toChars());
-    if (op != TOKconstruct && op != TOKblit)	// don't replace const variable with its initializer
-	e1 = e1->optimize(result);
-    e2 = e2->optimize(result);
-    if (op == TOKshlass || op == TOKshrass || op == TOKushrass)
-    {
-	if (e2->isConst() == 1)
-	{
-	    integer_t i2 = e2->toInteger();
-	    d_uns64 sz = e1->type->size() * 8;
-	    if (i2 < 0 || i2 > sz)
-	    {
-        error("shift assign by %lld is outside the range 0..%"PRIuSIZE, i2, sz);
-		e2 = new IntegerExp(0);
-	    }
-	}
-    }
-    return this;
-}
-
-Expression *AddExp::optimize(int result)
-{   Expression *e;
-
-    //printf("AddExp::optimize(%s)\n", toChars());
-    e1 = e1->optimize(result);
-    e2 = e2->optimize(result);
-    if (e1->isConst() && e2->isConst())
-    {
-	if (e1->op == TOKsymoff && e2->op == TOKsymoff)
-	    return this;
-	e = Add(type, e1, e2);
-    }
-    else
-	e = this;
-    return e;
-}
-
-Expression *MinExp::optimize(int result)
-{   Expression *e;
-
-    e1 = e1->optimize(result);
-    e2 = e2->optimize(result);
-    if (e1->isConst() && e2->isConst())
-    {
-	if (e2->op == TOKsymoff)
-	    return this;
-	e = Min(type, e1, e2);
-    }
-    else
-	e = this;
-    return e;
-}
-
-Expression *MulExp::optimize(int result)
-{   Expression *e;
-
-    //printf("MulExp::optimize(result = %d) %s\n", result, toChars());
-    e1 = e1->optimize(result);
-    e2 = e2->optimize(result);
-    if (e1->isConst() == 1 && e2->isConst() == 1)
-    {
-	e = Mul(type, e1, e2);
-    }
-    else
-	e = this;
-    return e;
-}
-
-Expression *DivExp::optimize(int result)
-{   Expression *e;
-
-    //printf("DivExp::optimize(%s)\n", toChars());
-    e1 = e1->optimize(result);
-    e2 = e2->optimize(result);
-    if (e1->isConst() == 1 && e2->isConst() == 1)
-    {
-	e = Div(type, e1, e2);
-    }
-    else
-	e = this;
-    return e;
-}
-
-Expression *ModExp::optimize(int result)
-{   Expression *e;
-
-    e1 = e1->optimize(result);
-    e2 = e2->optimize(result);
-    if (e1->isConst() == 1 && e2->isConst() == 1)
-    {
-	e = Mod(type, e1, e2);
-    }
-    else
-	e = this;
-    return e;
-}
-
-Expression *shift_optimize(int result, BinExp *e, Expression *(*shift)(Type *, Expression *, Expression *))
-{   Expression *ex = e;
-
-    e->e1 = e->e1->optimize(result);
-    e->e2 = e->e2->optimize(result);
-    if (e->e2->isConst() == 1)
-    {
-	integer_t i2 = e->e2->toInteger();
-	d_uns64 sz = e->e1->type->size() * 8;
-	if (i2 < 0 || i2 > sz)
-	{
-        error("shift by %lld is outside the range 0..%"PRIuSIZE, i2, sz);
-	    e->e2 = new IntegerExp(0);
-	}
-	if (e->e1->isConst() == 1)
-	    ex = (*shift)(e->type, e->e1, e->e2);
-    }
-    return ex;
-}
-
-Expression *ShlExp::optimize(int result)
-{
-    //printf("ShlExp::optimize(result = %d) %s\n", result, toChars());
-    return shift_optimize(result, this, Shl);
-}
-
-Expression *ShrExp::optimize(int result)
-{
-    //printf("ShrExp::optimize(result = %d) %s\n", result, toChars());
-    return shift_optimize(result, this, Shr);
-}
-
-Expression *UshrExp::optimize(int result)
-{
-    //printf("UshrExp::optimize(result = %d) %s\n", result, toChars());
-    return shift_optimize(result, this, Ushr);
-}
-
-Expression *AndExp::optimize(int result)
-{   Expression *e;
-
-    e1 = e1->optimize(result);
-    e2 = e2->optimize(result);
-    if (e1->isConst() == 1 && e2->isConst() == 1)
-	e = And(type, e1, e2);
-    else
-	e = this;
-    return e;
-}
-
-Expression *OrExp::optimize(int result)
-{   Expression *e;
-
-    e1 = e1->optimize(result);
-    e2 = e2->optimize(result);
-    if (e1->isConst() == 1 && e2->isConst() == 1)
-	e = Or(type, e1, e2);
-    else
-	e = this;
-    return e;
-}
-
-Expression *XorExp::optimize(int result)
-{   Expression *e;
-
-    e1 = e1->optimize(result);
-    e2 = e2->optimize(result);
-    if (e1->isConst() == 1 && e2->isConst() == 1)
-	e = Xor(type, e1, e2);
-    else
-	e = this;
-    return e;
-}
-
-Expression *CommaExp::optimize(int result)
-{   Expression *e;
-
-    //printf("CommaExp::optimize(result = %d) %s\n", result, toChars());
-    e1 = e1->optimize(result & WANTinterpret);
-    e2 = e2->optimize(result);
-    if (!e1 || e1->op == TOKint64 || e1->op == TOKfloat64 || !e1->checkSideEffect(2))
-    {
-	e = e2;
-	if (e)
-	    e->type = type;
-    }
-    else
-	e = this;
-    //printf("-CommaExp::optimize(result = %d) %s\n", result, e->toChars());
-    return e;
-}
-
-Expression *ArrayLengthExp::optimize(int result)
-{   Expression *e;
-
-    //printf("ArrayLengthExp::optimize(result = %d) %s\n", result, toChars());
-    e1 = e1->optimize(WANTvalue | (result & WANTinterpret));
-    e = this;
-    if (e1->op == TOKstring || e1->op == TOKarrayliteral || e1->op == TOKassocarrayliteral)
-    {
-	e = ArrayLength(type, e1);
-    }
-    return e;
-}
-
-Expression *EqualExp::optimize(int result)
-{   Expression *e;
-
-    //printf("EqualExp::optimize(result = %x) %s\n", result, toChars());
-    e1 = e1->optimize(WANTvalue | (result & WANTinterpret));
-    e2 = e2->optimize(WANTvalue | (result & WANTinterpret));
-    e = this;
-
-    Expression *e1 = fromConstInitializer(result, this->e1);
-    Expression *e2 = fromConstInitializer(result, this->e2);
-
-    e = Equal(op, type, e1, e2);
-    if (e == EXP_CANT_INTERPRET)
-	e = this;
-    return e;
-}
-
-Expression *IdentityExp::optimize(int result)
-{   Expression *e;
-
-    //printf("IdentityExp::optimize(result = %d) %s\n", result, toChars());
-    e1 = e1->optimize(WANTvalue | (result & WANTinterpret));
-    e2 = e2->optimize(WANTvalue | (result & WANTinterpret));
-    e = this;
-
-    if (this->e1->isConst() && this->e2->isConst())
-    {
-	e = Identity(op, type, this->e1, this->e2);
-    }
-    return e;
-}
-
-Expression *IndexExp::optimize(int result)
-{   Expression *e;
-
-    //printf("IndexExp::optimize(result = %d) %s\n", result, toChars());
-    Expression *e1 = this->e1->optimize(WANTvalue | (result & WANTinterpret));
-    e1 = fromConstInitializer(result, e1);
-    e2 = e2->optimize(WANTvalue | (result & WANTinterpret));
-    e = Index(type, e1, e2);
-    if (e == EXP_CANT_INTERPRET)
-	e = this;
-    return e;
-}
-
-Expression *SliceExp::optimize(int result)
-{   Expression *e;
-
-    //printf("SliceExp::optimize(result = %d) %s\n", result, toChars());
-    e = this;
-    e1 = e1->optimize(WANTvalue | (result & WANTinterpret));
-    if (!lwr)
-    {	if (e1->op == TOKstring)
-	{   // Convert slice of string literal into dynamic array
-	    Type *t = e1->type->toBasetype();
-	    if (t->nextOf())
-		e = e1->castTo(NULL, t->nextOf()->arrayOf());
-	}
-	return e;
-    }
-    e1 = fromConstInitializer(result, e1);
-    lwr = lwr->optimize(WANTvalue | (result & WANTinterpret));
-    upr = upr->optimize(WANTvalue | (result & WANTinterpret));
-    e = Slice(type, e1, lwr, upr);
-    if (e == EXP_CANT_INTERPRET)
-	e = this;
-    //printf("-SliceExp::optimize() %s\n", e->toChars());
-    return e;
-}
-
-Expression *AndAndExp::optimize(int result)
-{   Expression *e;
-
-    //printf("AndAndExp::optimize(%d) %s\n", result, toChars());
-    e1 = e1->optimize(WANTflags | (result & WANTinterpret));
-    e = this;
-    if (e1->isBool(FALSE))
-    {
-	e = new CommaExp(loc, e1, new IntegerExp(loc, 0, type));
-	e->type = type;
-	e = e->optimize(result);
-    }
-    else
-    {
-	e2 = e2->optimize(WANTflags | (result & WANTinterpret));
-	if (result && e2->type->toBasetype()->ty == Tvoid && !global.errors)
-	    error("void has no value");
-	if (e1->isConst())
-	{
-	    if (e2->isConst())
-	    {	int n1 = e1->isBool(1);
-		int n2 = e2->isBool(1);
-
-		e = new IntegerExp(loc, n1 && n2, type);
-	    }
-	    else if (e1->isBool(TRUE))
-		e = new BoolExp(loc, e2, type);
-	}
-    }
-    return e;
-}
-
-Expression *OrOrExp::optimize(int result)
-{   Expression *e;
-
-    e1 = e1->optimize(WANTflags | (result & WANTinterpret));
-    e = this;
-    if (e1->isBool(TRUE))
-    {	// Replace with (e1, 1)
-	e = new CommaExp(loc, e1, new IntegerExp(loc, 1, type));
-	e->type = type;
-	e = e->optimize(result);
-    }
-    else
-    {
-	e2 = e2->optimize(WANTflags | (result & WANTinterpret));
-	if (result && e2->type->toBasetype()->ty == Tvoid && !global.errors)
-	    error("void has no value");
-	if (e1->isConst())
-	{
-	    if (e2->isConst())
-	    {	int n1 = e1->isBool(1);
-		int n2 = e2->isBool(1);
-
-		e = new IntegerExp(loc, n1 || n2, type);
-	    }
-	    else if (e1->isBool(FALSE))
-		e = new BoolExp(loc, e2, type);
-	}
-    }
-    return e;
-}
-
-Expression *CmpExp::optimize(int result)
-{   Expression *e;
-
-    //printf("CmpExp::optimize() %s\n", toChars());
-    e1 = e1->optimize(WANTvalue | (result & WANTinterpret));
-    e2 = e2->optimize(WANTvalue | (result & WANTinterpret));
-
-    Expression *e1 = fromConstInitializer(result, this->e1);
-    Expression *e2 = fromConstInitializer(result, this->e2);
-
-    e = Cmp(op, type, e1, e2);
-    if (e == EXP_CANT_INTERPRET)
-	e = this;
-    return e;
-}
-
-Expression *CatExp::optimize(int result)
-{   Expression *e;
-
-    //printf("CatExp::optimize(%d) %s\n", result, toChars());
-    e1 = e1->optimize(result);
-    e2 = e2->optimize(result);
-    e = Cat(type, e1, e2);
-    if (e == EXP_CANT_INTERPRET)
-	e = this;
-    return e;
-}
-
-
-Expression *CondExp::optimize(int result)
-{   Expression *e;
-
-    econd = econd->optimize(WANTflags | (result & WANTinterpret));
-    if (econd->isBool(TRUE))
-	e = e1->optimize(result);
-    else if (econd->isBool(FALSE))
-	e = e2->optimize(result);
-    else
-    {	e1 = e1->optimize(result);
-	e2 = e2->optimize(result);
-	e = this;
-    }
-    return e;
-}
-
-
+
+// Compiler implementation of the D programming language
+// Copyright (c) 1999-2007 by Digital Mars
+// All Rights Reserved
+// written by Walter Bright
+// http://www.digitalmars.com
+// License for redistribution is by either the Artistic License
+// in artistic.txt, or the GNU General Public License in gnu.txt.
+// See the included readme.txt for details.
+
+#include <stdio.h>
+#include <ctype.h>
+#include <assert.h>
+#include <math.h>
+
+#if __DMC__
+#include <complex.h>
+#endif
+
+#include "lexer.h"
+#include "mtype.h"
+#include "expression.h"
+#include "declaration.h"
+#include "aggregate.h"
+#include "init.h"
+
+
+#ifdef IN_GCC
+#include "d-gcc-real.h"
+
+/* %% fix? */
+extern "C" bool real_isnan (const real_t *);
+#endif
+
+static real_t zero;	// work around DMC bug for now
+
+
+/*************************************
+ * If variable has a const initializer,
+ * return that initializer.
+ */
+
+Expression *expandVar(int result, VarDeclaration *v)
+{
+    //printf("expandVar(result = %d, v = %p, %s)\n", result, v, v ? v->toChars() : "null");
+
+    Expression *e = NULL;
+    if (!v)
+	return e;
+
+    if (v->isConst() || v->isInvariant() || v->storage_class & STCmanifest)
+    {
+	if (!v->type)
+	{
+	    //error("ICE");
+	    return e;
+	}
+
+	Type *tb = v->type->toBasetype();
+	if (result & WANTinterpret ||
+	    v->storage_class & STCmanifest ||
+	    (tb->ty != Tsarray && tb->ty != Tstruct)
+	   )
+	{
+	    if (v->init)
+	    {
+		if (v->inuse)
+		{   if (v->storage_class & STCmanifest)
+			v->error("recursive initialization of constant");
+		    goto L1;
+		}
+		Expression *ei = v->init->toExpression();
+		if (!ei)
+		    goto L1;
+		if (ei->op == TOKconstruct || ei->op == TOKblit)
+		{   AssignExp *ae = (AssignExp *)ei;
+		    ei = ae->e2;
+		    if (ei->isConst() != 1 && ei->op != TOKstring)
+			goto L1;
+		    if (ei->type != v->type)
+			goto L1;
+		}
+		if (v->scope)
+		{
+		    v->inuse++;
+		    e = ei->syntaxCopy();
+		    e = e->semantic(v->scope);
+		    e = e->implicitCastTo(v->scope, v->type);
+		    v->scope = NULL;
+		    v->inuse--;
+		}
+		else if (!ei->type)
+		{
+		    goto L1;
+		}
+		else
+		    // Should remove the copy() operation by
+		    // making all mods to expressions copy-on-write
+		    e = ei->copy();
+	    }
+	    else
+	    {
+#if 1
+		goto L1;
+#else
+		// BUG: what if const is initialized in constructor?
+		e = v->type->defaultInit();
+		e->loc = e1->loc;
+#endif
+	    }
+	    if (e->type != v->type)
+	    {
+		e = e->castTo(NULL, v->type);
+	    }
+	    v->inuse++;
+	    e = e->optimize(result);
+	    v->inuse--;
+	}
+    }
+L1:
+    //if (e) printf("\te = %s, e->type = %s\n", e->toChars(), e->type->toChars());
+    return e;
+}
+
+
+Expression *fromConstInitializer(int result, Expression *e1)
+{
+    //printf("fromConstInitializer(result = %x, %s)\n", result, e1->toChars());
+    //static int xx; if (xx++ == 10) assert(0);
+    Expression *e = e1;
+    if (e1->op == TOKvar)
+    {	VarExp *ve = (VarExp *)e1;
+	VarDeclaration *v = ve->var->isVarDeclaration();
+	e = expandVar(result, v);
+	if (e)
+	{   if (e->type != e1->type)
+	    {   // Type 'paint' operation
+		e = e->copy();
+		e->type = e1->type;
+	    }
+	}
+	else
+	    e = e1;
+    }
+    return e;
+}
+
+
+Expression *Expression::optimize(int result)
+{
+    //printf("Expression::optimize(result = x%x) %s\n", result, toChars());
+    return this;
+}
+
+Expression *VarExp::optimize(int result)
+{
+    return fromConstInitializer(result, this);
+}
+
+Expression *TupleExp::optimize(int result)
+{
+    for (size_t i = 0; i < exps->dim; i++)
+    {   Expression *e = (Expression *)exps->data[i];
+
+	e = e->optimize(WANTvalue | (result & WANTinterpret));
+	exps->data[i] = (void *)e;
+    }
+    return this;
+}
+
+Expression *ArrayLiteralExp::optimize(int result)
+{
+    if (elements)
+    {
+	for (size_t i = 0; i < elements->dim; i++)
+	{   Expression *e = (Expression *)elements->data[i];
+
+	    e = e->optimize(WANTvalue | (result & WANTinterpret));
+	    elements->data[i] = (void *)e;
+	}
+    }
+    return this;
+}
+
+Expression *AssocArrayLiteralExp::optimize(int result)
+{
+    assert(keys->dim == values->dim);
+    for (size_t i = 0; i < keys->dim; i++)
+    {   Expression *e = (Expression *)keys->data[i];
+
+	e = e->optimize(WANTvalue | (result & WANTinterpret));
+	keys->data[i] = (void *)e;
+
+	e = (Expression *)values->data[i];
+	e = e->optimize(WANTvalue | (result & WANTinterpret));
+	values->data[i] = (void *)e;
+    }
+    return this;
+}
+
+Expression *StructLiteralExp::optimize(int result)
+{
+    if (elements)
+    {
+	for (size_t i = 0; i < elements->dim; i++)
+	{   Expression *e = (Expression *)elements->data[i];
+	    if (!e)
+		continue;
+	    e = e->optimize(WANTvalue | (result & WANTinterpret));
+	    elements->data[i] = (void *)e;
+	}
+    }
+    return this;
+}
+
+Expression *TypeExp::optimize(int result)
+{
+    return this;
+}
+
+Expression *UnaExp::optimize(int result)
+{
+    e1 = e1->optimize(result);
+    return this;
+}
+
+Expression *NegExp::optimize(int result)
+{   Expression *e;
+
+    e1 = e1->optimize(result);
+    if (e1->isConst() == 1)
+    {
+	e = Neg(type, e1);
+    }
+    else
+	e = this;
+    return e;
+}
+
+Expression *ComExp::optimize(int result)
+{   Expression *e;
+
+    e1 = e1->optimize(result);
+    if (e1->isConst() == 1)
+    {
+	e = Com(type, e1);
+    }
+    else
+	e = this;
+    return e;
+}
+
+Expression *NotExp::optimize(int result)
+{   Expression *e;
+
+    e1 = e1->optimize(result);
+    if (e1->isConst() == 1)
+    {
+	e = Not(type, e1);
+    }
+    else
+	e = this;
+    return e;
+}
+
+Expression *BoolExp::optimize(int result)
+{   Expression *e;
+
+    e1 = e1->optimize(result);
+    if (e1->isConst() == 1)
+    {
+	e = Bool(type, e1);
+    }
+    else
+	e = this;
+    return e;
+}
+
+Expression *AddrExp::optimize(int result)
+{   Expression *e;
+
+    //printf("AddrExp::optimize(result = %d) %s\n", result, toChars());
+
+    /* Rewrite &(a,b) as (a,&b)
+     */
+    if (e1->op == TOKcomma)
+    {	CommaExp *ce = (CommaExp *)e1;
+	AddrExp *ae = new AddrExp(loc, ce->e2);
+	ae->type = type;
+	e = new CommaExp(ce->loc, ce->e1, ae);
+	e->type = type;
+	return e->optimize(result);
+    }
+
+    if (e1->op == TOKvar)
+    {	VarExp *ve = (VarExp *)e1;
+	if (ve->var->storage_class & STCmanifest)
+	    e1 = e1->optimize(result);
+    }
+    else
+	e1 = e1->optimize(result);
+
+    // Convert &*ex to ex
+    if (e1->op == TOKstar)
+    {	Expression *ex;
+
+	ex = ((PtrExp *)e1)->e1;
+	if (type->equals(ex->type))
+	    e = ex;
+	else
+	{
+	    e = ex->copy();
+	    e->type = type;
+	}
+	return e;
+    }
+#if !IN_LLVM
+    if (e1->op == TOKvar)
+    {	VarExp *ve = (VarExp *)e1;
+	if (!ve->var->isOut() && !ve->var->isRef() &&
+	    !ve->var->isImportedSymbol())
+	{
+	    SymOffExp *se = new SymOffExp(loc, ve->var, 0, ve->hasOverloads);
+	    se->type = type;
+	    return se;
+	}
+    }
+    if (e1->op == TOKindex)
+    {	// Convert &array[n] to &array+n
+	IndexExp *ae = (IndexExp *)e1;
+
+	if (ae->e2->op == TOKint64 && ae->e1->op == TOKvar)
+	{
+	    dinteger_t index = ae->e2->toInteger();
+	    VarExp *ve = (VarExp *)ae->e1;
+	    if (ve->type->ty == Tsarray
+		&& !ve->var->isImportedSymbol())
+	    {
+		TypeSArray *ts = (TypeSArray *)ve->type;
+		dinteger_t dim = ts->dim->toInteger();
+		if (index < 0 || index >= dim)
+		    error("array index %jd is out of bounds [0..%jd]", index, dim);
+		e = new SymOffExp(loc, ve->var, index * ts->nextOf()->size());
+		e->type = type;
+		return e;
+	    }
+	}
+    }
+#endif
+    return this;
+}
+
+Expression *PtrExp::optimize(int result)
+{
+    //printf("PtrExp::optimize(result = x%x) %s\n", result, toChars());
+    e1 = e1->optimize(result);
+    // Convert *&ex to ex
+    if (e1->op == TOKaddress)
+    {	Expression *e;
+	Expression *ex;
+
+	ex = ((AddrExp *)e1)->e1;
+	if (type->equals(ex->type))
+	    e = ex;
+	else
+	{
+	    e = ex->copy();
+	    e->type = type;
+	}
+	return e;
+    }
+    // Constant fold *(&structliteral + offset)
+    if (e1->op == TOKadd)
+    {
+	Expression *e;
+	e = Ptr(type, e1);
+	if (e != EXP_CANT_INTERPRET)
+	    return e;
+    }
+
+    if (e1->op == TOKsymoff)
+    {	SymOffExp *se = (SymOffExp *)e1;
+	VarDeclaration *v = se->var->isVarDeclaration();
+	Expression *e = expandVar(result, v);
+	if (e && e->op == TOKstructliteral)
+	{   StructLiteralExp *sle = (StructLiteralExp *)e;
+	    e = sle->getField(type, se->offset);
+	    if (e && e != EXP_CANT_INTERPRET)
+		return e;
+	}
+    }
+    return this;
+}
+
+Expression *DotVarExp::optimize(int result)
+{
+    //printf("DotVarExp::optimize(result = x%x) %s\n", result, toChars());
+    e1 = e1->optimize(result);
+
+    if (e1->op == TOKvar)
+    {	VarExp *ve = (VarExp *)e1;
+	VarDeclaration *v = ve->var->isVarDeclaration();
+	Expression *e = expandVar(result, v);
+	if (e && e->op == TOKstructliteral)
+	{   StructLiteralExp *sle = (StructLiteralExp *)e;
+	    VarDeclaration *vf = var->isVarDeclaration();
+	    if (vf)
+	    {
+		e = sle->getField(type, vf->offset);
+		if (e && e != EXP_CANT_INTERPRET)
+		    return e;
+	    }
+	}
+    }
+    else if (e1->op == TOKstructliteral)
+    {   StructLiteralExp *sle = (StructLiteralExp *)e1;
+	VarDeclaration *vf = var->isVarDeclaration();
+	if (vf)
+	{
+	    Expression *e = sle->getField(type, vf->offset);
+	    if (e && e != EXP_CANT_INTERPRET)
+		return e;
+	}
+    }
+
+    return this;
+}
+
+Expression *CallExp::optimize(int result)
+{
+    //printf("CallExp::optimize(result = %d) %s\n", result, toChars());
+    Expression *e = this;
+
+    e1 = e1->optimize(result);
+    if (e1->op == TOKvar)
+    {
+	FuncDeclaration *fd = ((VarExp *)e1)->var->isFuncDeclaration();
+	if (fd)
+	{
+	    enum BUILTIN b = fd->isBuiltin();
+	    if (b)
+	    {
+		e = eval_builtin(b, arguments);
+		if (!e)			// failed
+		    e = this;		// evaluate at runtime
+	    }
+	    else if (result & WANTinterpret)
+	    {
+		Expression *eresult = fd->interpret(NULL, arguments);
+		if (eresult && eresult != EXP_VOID_INTERPRET)
+		    e = eresult;
+		else
+		    error("cannot evaluate %s at compile time", toChars());
+	    }
+	}
+    }
+    return e;
+}
+
+
+Expression *CastExp::optimize(int result)
+{
+    //printf("CastExp::optimize(result = %d) %s\n", result, toChars());
+    //printf("from %s to %s\n", type->toChars(), to->toChars());
+    //printf("from %s\n", type->toChars());
+    //printf("e1->type %s\n", e1->type->toChars());
+    //printf("type = %p\n", type);
+    assert(type);
+    enum TOK op1 = e1->op;
+#define X 0
+
+    Expression *e1old = e1;
+    e1 = e1->optimize(result);
+    e1 = fromConstInitializer(result, e1);
+
+    if (e1 == e1old &&
+	e1->op == TOKarrayliteral &&
+	type->toBasetype()->ty == Tpointer &&
+	e1->type->toBasetype()->ty != Tsarray)
+    {
+	// Casting this will result in the same expression, and
+	// infinite loop because of Expression::implicitCastTo()
+	return this;		// no change
+    }
+
+    if ((e1->op == TOKstring || e1->op == TOKarrayliteral) &&
+	(type->ty == Tpointer || type->ty == Tarray) &&
+	e1->type->nextOf()->size() == type->nextOf()->size()
+       )
+    {
+	Expression *e = e1->castTo(NULL, type);
+	if (X) printf(" returning1 %s\n", e->toChars());
+	return e;
+    }
+
+    if (e1->op == TOKstructliteral &&
+	e1->type->implicitConvTo(type) >= MATCHconst)
+    {
+	e1->type = type;
+	if (X) printf(" returning2 %s\n", e1->toChars());
+	return e1;
+    }
+
+    /* The first test here is to prevent infinite loops
+     */
+    if (op1 != TOKarrayliteral && e1->op == TOKarrayliteral)
+	return e1->castTo(NULL, to);
+    if (e1->op == TOKnull &&
+	(type->ty == Tpointer || type->ty == Tclass || type->ty == Tarray))
+    {
+	e1->type = type;
+	if (X) printf(" returning3 %s\n", e1->toChars());
+	return e1;
+    }
+
+    if (result & WANTflags && type->ty == Tclass && e1->type->ty == Tclass)
+    {
+	// See if we can remove an unnecessary cast
+	ClassDeclaration *cdfrom;
+	ClassDeclaration *cdto;
+	int offset;
+
+	cdfrom = e1->type->isClassHandle();
+	cdto   = type->isClassHandle();
+	if (cdto->isBaseOf(cdfrom, &offset) && offset == 0)
+	{
+	    e1->type = type;
+	    if (X) printf(" returning4 %s\n", e1->toChars());
+	    return e1;
+	}
+    }
+
+    // We can convert 'head const' to mutable
+    if (to->constOf()->equals(e1->type->constOf()))
+//    if (to->constConv(e1->type) >= MATCHconst)
+    {
+	e1->type = type;
+	if (X) printf(" returning5 %s\n", e1->toChars());
+	return e1;
+    }
+
+    Expression *e;
+
+    if (e1->isConst())
+    {
+	if (e1->op == TOKsymoff)
+	{
+	    if (type->size() == e1->type->size() &&
+		type->toBasetype()->ty != Tsarray)
+	    {
+		e1->type = type;
+		return e1;
+	    }
+	    return this;
+	}
+	if (to->toBasetype()->ty == Tvoid)
+	    e = this;
+	else
+	    e = Cast(type, to, e1);
+    }
+    else
+	e = this;
+    if (X) printf(" returning6 %s\n", e->toChars());
+    return e;
+#undef X
+}
+
+Expression *BinExp::optimize(int result)
+{
+    //printf("BinExp::optimize(result = %d) %s\n", result, toChars());
+    if (op != TOKconstruct && op != TOKblit)	// don't replace const variable with its initializer
+	e1 = e1->optimize(result);
+    e2 = e2->optimize(result);
+    if (op == TOKshlass || op == TOKshrass || op == TOKushrass)
+    {
+	if (e2->isConst() == 1)
+	{
+	    dinteger_t i2 = e2->toInteger();
+	    d_uns64 sz = e1->type->size() * 8;
+	    if (i2 < 0 || i2 > sz)
+	    {   error("shift assign by %jd is outside the range 0..%zu", i2, sz);
+		e2 = new IntegerExp(0);
+	    }
+	}
+    }
+    return this;
+}
+
+Expression *AddExp::optimize(int result)
+{   Expression *e;
+
+    //printf("AddExp::optimize(%s)\n", toChars());
+    e1 = e1->optimize(result);
+    e2 = e2->optimize(result);
+    if (e1->isConst() && e2->isConst())
+    {
+	if (e1->op == TOKsymoff && e2->op == TOKsymoff)
+	    return this;
+	e = Add(type, e1, e2);
+    }
+    else
+	e = this;
+    return e;
+}
+
+Expression *MinExp::optimize(int result)
+{   Expression *e;
+
+    e1 = e1->optimize(result);
+    e2 = e2->optimize(result);
+    if (e1->isConst() && e2->isConst())
+    {
+	if (e2->op == TOKsymoff)
+	    return this;
+	e = Min(type, e1, e2);
+    }
+    else
+	e = this;
+    return e;
+}
+
+Expression *MulExp::optimize(int result)
+{   Expression *e;
+
+    //printf("MulExp::optimize(result = %d) %s\n", result, toChars());
+    e1 = e1->optimize(result);
+    e2 = e2->optimize(result);
+    if (e1->isConst() == 1 && e2->isConst() == 1)
+    {
+	e = Mul(type, e1, e2);
+    }
+    else
+	e = this;
+    return e;
+}
+
+Expression *DivExp::optimize(int result)
+{   Expression *e;
+
+    //printf("DivExp::optimize(%s)\n", toChars());
+    e1 = e1->optimize(result);
+    e2 = e2->optimize(result);
+    if (e1->isConst() == 1 && e2->isConst() == 1)
+    {
+	e = Div(type, e1, e2);
+    }
+    else
+	e = this;
+    return e;
+}
+
+Expression *ModExp::optimize(int result)
+{   Expression *e;
+
+    e1 = e1->optimize(result);
+    e2 = e2->optimize(result);
+    if (e1->isConst() == 1 && e2->isConst() == 1)
+    {
+	e = Mod(type, e1, e2);
+    }
+    else
+	e = this;
+    return e;
+}
+
+Expression *shift_optimize(int result, BinExp *e, Expression *(*shift)(Type *, Expression *, Expression *))
+{   Expression *ex = e;
+
+    e->e1 = e->e1->optimize(result);
+    e->e2 = e->e2->optimize(result);
+    if (e->e2->isConst() == 1)
+    {
+	dinteger_t i2 = e->e2->toInteger();
+	d_uns64 sz = e->e1->type->size() * 8;
+	if (i2 < 0 || i2 > sz)
+	{   e->error("shift by %jd is outside the range 0..%zu", i2, sz);
+	    e->e2 = new IntegerExp(0);
+	}
+	if (e->e1->isConst() == 1)
+	    ex = (*shift)(e->type, e->e1, e->e2);
+    }
+    return ex;
+}
+
+Expression *ShlExp::optimize(int result)
+{
+    //printf("ShlExp::optimize(result = %d) %s\n", result, toChars());
+    return shift_optimize(result, this, Shl);
+}
+
+Expression *ShrExp::optimize(int result)
+{
+    //printf("ShrExp::optimize(result = %d) %s\n", result, toChars());
+    return shift_optimize(result, this, Shr);
+}
+
+Expression *UshrExp::optimize(int result)
+{
+    //printf("UshrExp::optimize(result = %d) %s\n", result, toChars());
+    return shift_optimize(result, this, Ushr);
+}
+
+Expression *AndExp::optimize(int result)
+{   Expression *e;
+
+    e1 = e1->optimize(result);
+    e2 = e2->optimize(result);
+    if (e1->isConst() == 1 && e2->isConst() == 1)
+	e = And(type, e1, e2);
+    else
+	e = this;
+    return e;
+}
+
+Expression *OrExp::optimize(int result)
+{   Expression *e;
+
+    e1 = e1->optimize(result);
+    e2 = e2->optimize(result);
+    if (e1->isConst() == 1 && e2->isConst() == 1)
+	e = Or(type, e1, e2);
+    else
+	e = this;
+    return e;
+}
+
+Expression *XorExp::optimize(int result)
+{   Expression *e;
+
+    e1 = e1->optimize(result);
+    e2 = e2->optimize(result);
+    if (e1->isConst() == 1 && e2->isConst() == 1)
+	e = Xor(type, e1, e2);
+    else
+	e = this;
+    return e;
+}
+
+Expression *CommaExp::optimize(int result)
+{   Expression *e;
+
+    //printf("CommaExp::optimize(result = %d) %s\n", result, toChars());
+    e1 = e1->optimize(result & WANTinterpret);
+    e2 = e2->optimize(result);
+    if (!e1 || e1->op == TOKint64 || e1->op == TOKfloat64 || !e1->checkSideEffect(2))
+    {
+	e = e2;
+	if (e)
+	    e->type = type;
+    }
+    else
+	e = this;
+    //printf("-CommaExp::optimize(result = %d) %s\n", result, e->toChars());
+    return e;
+}
+
+Expression *ArrayLengthExp::optimize(int result)
+{   Expression *e;
+
+    //printf("ArrayLengthExp::optimize(result = %d) %s\n", result, toChars());
+    e1 = e1->optimize(WANTvalue | (result & WANTinterpret));
+    e = this;
+    if (e1->op == TOKstring || e1->op == TOKarrayliteral || e1->op == TOKassocarrayliteral)
+    {
+	e = ArrayLength(type, e1);
+    }
+    return e;
+}
+
+Expression *EqualExp::optimize(int result)
+{   Expression *e;
+
+    //printf("EqualExp::optimize(result = %x) %s\n", result, toChars());
+    e1 = e1->optimize(WANTvalue | (result & WANTinterpret));
+    e2 = e2->optimize(WANTvalue | (result & WANTinterpret));
+    e = this;
+
+    Expression *e1 = fromConstInitializer(result, this->e1);
+    Expression *e2 = fromConstInitializer(result, this->e2);
+
+    e = Equal(op, type, e1, e2);
+    if (e == EXP_CANT_INTERPRET)
+	e = this;
+    return e;
+}
+
+Expression *IdentityExp::optimize(int result)
+{   Expression *e;
+
+    //printf("IdentityExp::optimize(result = %d) %s\n", result, toChars());
+    e1 = e1->optimize(WANTvalue | (result & WANTinterpret));
+    e2 = e2->optimize(WANTvalue | (result & WANTinterpret));
+    e = this;
+
+    if (this->e1->isConst() && this->e2->isConst())
+    {
+	e = Identity(op, type, this->e1, this->e2);
+    }
+    return e;
+}
+
+Expression *IndexExp::optimize(int result)
+{   Expression *e;
+
+    //printf("IndexExp::optimize(result = %d) %s\n", result, toChars());
+    Expression *e1 = this->e1->optimize(WANTvalue | (result & WANTinterpret));
+    e1 = fromConstInitializer(result, e1);
+    e2 = e2->optimize(WANTvalue | (result & WANTinterpret));
+    e = Index(type, e1, e2);
+    if (e == EXP_CANT_INTERPRET)
+	e = this;
+    return e;
+}
+
+Expression *SliceExp::optimize(int result)
+{   Expression *e;
+
+    //printf("SliceExp::optimize(result = %d) %s\n", result, toChars());
+    e = this;
+    e1 = e1->optimize(WANTvalue | (result & WANTinterpret));
+    if (!lwr)
+    {	if (e1->op == TOKstring)
+	{   // Convert slice of string literal into dynamic array
+	    Type *t = e1->type->toBasetype();
+	    if (t->nextOf())
+		e = e1->castTo(NULL, t->nextOf()->arrayOf());
+	}
+	return e;
+    }
+    e1 = fromConstInitializer(result, e1);
+    lwr = lwr->optimize(WANTvalue | (result & WANTinterpret));
+    upr = upr->optimize(WANTvalue | (result & WANTinterpret));
+    e = Slice(type, e1, lwr, upr);
+    if (e == EXP_CANT_INTERPRET)
+	e = this;
+    //printf("-SliceExp::optimize() %s\n", e->toChars());
+    return e;
+}
+
+Expression *AndAndExp::optimize(int result)
+{   Expression *e;
+
+    //printf("AndAndExp::optimize(%d) %s\n", result, toChars());
+    e1 = e1->optimize(WANTflags | (result & WANTinterpret));
+    e = this;
+    if (e1->isBool(FALSE))
+    {
+	e = new CommaExp(loc, e1, new IntegerExp(loc, 0, type));
+	e->type = type;
+	e = e->optimize(result);
+    }
+    else
+    {
+	e2 = e2->optimize(WANTflags | (result & WANTinterpret));
+	if (result && e2->type->toBasetype()->ty == Tvoid && !global.errors)
+	    error("void has no value");
+	if (e1->isConst())
+	{
+	    if (e2->isConst())
+	    {	int n1 = e1->isBool(1);
+		int n2 = e2->isBool(1);
+
+		e = new IntegerExp(loc, n1 && n2, type);
+	    }
+	    else if (e1->isBool(TRUE))
+		e = new BoolExp(loc, e2, type);
+	}
+    }
+    return e;
+}
+
+Expression *OrOrExp::optimize(int result)
+{   Expression *e;
+
+    e1 = e1->optimize(WANTflags | (result & WANTinterpret));
+    e = this;
+    if (e1->isBool(TRUE))
+    {	// Replace with (e1, 1)
+	e = new CommaExp(loc, e1, new IntegerExp(loc, 1, type));
+	e->type = type;
+	e = e->optimize(result);
+    }
+    else
+    {
+	e2 = e2->optimize(WANTflags | (result & WANTinterpret));
+	if (result && e2->type->toBasetype()->ty == Tvoid && !global.errors)
+	    error("void has no value");
+	if (e1->isConst())
+	{
+	    if (e2->isConst())
+	    {	int n1 = e1->isBool(1);
+		int n2 = e2->isBool(1);
+
+		e = new IntegerExp(loc, n1 || n2, type);
+	    }
+	    else if (e1->isBool(FALSE))
+		e = new BoolExp(loc, e2, type);
+	}
+    }
+    return e;
+}
+
+Expression *CmpExp::optimize(int result)
+{   Expression *e;
+
+    //printf("CmpExp::optimize() %s\n", toChars());
+    e1 = e1->optimize(WANTvalue | (result & WANTinterpret));
+    e2 = e2->optimize(WANTvalue | (result & WANTinterpret));
+
+    Expression *e1 = fromConstInitializer(result, this->e1);
+    Expression *e2 = fromConstInitializer(result, this->e2);
+
+    e = Cmp(op, type, e1, e2);
+    if (e == EXP_CANT_INTERPRET)
+	e = this;
+    return e;
+}
+
+Expression *CatExp::optimize(int result)
+{   Expression *e;
+
+    //printf("CatExp::optimize(%d) %s\n", result, toChars());
+    e1 = e1->optimize(result);
+    e2 = e2->optimize(result);
+    e = Cat(type, e1, e2);
+    if (e == EXP_CANT_INTERPRET)
+	e = this;
+    return e;
+}
+
+
+Expression *CondExp::optimize(int result)
+{   Expression *e;
+
+    econd = econd->optimize(WANTflags | (result & WANTinterpret));
+    if (econd->isBool(TRUE))
+	e = e1->optimize(result);
+    else if (econd->isBool(FALSE))
+	e = e2->optimize(result);
+    else
+    {	e1 = e1->optimize(result);
+	e2 = e2->optimize(result);
+	e = this;
+    }
+    return e;
+}
+
+
--- a/dmd2/parse.c	Mon Jun 01 01:28:18 2009 +0200
+++ b/dmd2/parse.c	Mon Jun 01 19:02:20 2009 +0100
@@ -1,5707 +1,5938 @@
-
-// 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.
-
-// This is the D parser
-
-#include <stdio.h>
-#include <assert.h>
-
-#include "mem.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"
-
-// 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
-
-
-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;
-	bool safe = FALSE;
-
-	nextToken();
-	if (token.value == TOKlparen)
-	{
-	    nextToken();
-	    if (token.value != TOKidentifier)
-	    {	error("module (safe) 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);
-	}
-
-	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, safe);
-
-	    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;
-    enum STC stc;
-    unsigned storageClass;
-    Condition *condition;
-    unsigned char *comment;
-
-    //printf("Parser::parseDeclDefs()\n");
-    decldefs = new Array();
-    do
-    {
-	comment = token.blockComment;
-	storageClass = STCundefined;
-	switch (token.value)
-	{
-	    case TOKenum:
-	    {	/* Determine if this is a manifest constant declaration,
-		 * or a conventional enum.
-		 */
-		Token *t = peek(&token);
-		if (t->value == TOKlcurly || t->value == TOKcolon)
-		    s = parseEnum();
-		else if (t->value != TOKidentifier)
-		    goto Ldeclaration;
-		else
-		{
-		    t = peek(t);
-		    if (t->value == TOKlcurly || t->value == TOKcolon ||
-			t->value == TOKsemicolon)
-			s = parseEnum();
-		    else
-			goto Ldeclaration;
-		}
-		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(STCundefined);
-		decldefs->append(a);
-		continue;
-
-	    case TOKthis:
-		s = parseCtor();
-		break;
-
-	    case TOKassign:
-		s = parsePostBlit();
-		break;
-
-	    case TOKtilde:
-		s = parseDtor();
-		break;
-
-	    case TOKinvariant:
-	    {	Token *t;
-		t = peek(&token);
-		if (t->value == TOKlparen)
-		{
-		    if (peek(t)->value == TOKrparen)
-			// invariant() forms start of class invariant
-			s = parseInvariant();
-		    else
-			// invariant(type)
-			goto Ldeclaration;
-		}
-		else
-		{
-		    stc = STCinvariant;
-		    goto Lstc;
-		}
-		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:
-		if (peek(&token)->value == TOKlparen)
-		    goto Ldeclaration;
-		stc = STCconst;
-		goto Lstc;
-
-	    case TOKimmutable:
-		if (peek(&token)->value == TOKlparen)
-		    goto Ldeclaration;
-		stc = STCinvariant;
-		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 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;
-
-	    Lstc:
-		if (storageClass & stc)
-		    error("redundant storage class %s", Token::toChars(token.value));
-		{
-		unsigned u = storageClass | stc;
-		u &= STCconst | STCinvariant | STCmanifest;
-		if (u & (u - 1))
-		    error("conflicting storage class %s", Token::toChars(token.value));
-		}
-		nextToken();
-	    Lstc2:
-		storageClass |= stc;
-		switch (token.value)
-		{
-		    case TOKconst:
-		    case TOKinvariant:
-		    case TOKimmutable:
-			// If followed by a (, it is not a storage class
-			if (peek(&token)->value == TOKlparen)
-			    break;
-			if (token.value == TOKconst)
-			    stc = STCconst;
-			else
-			    stc = STCinvariant;
-			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 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;
-		    default:
-			break;
-		}
-
-		/* Look for auto initializers:
-		 *	storage_class identifier = initializer;
-		 */
-		if (token.value == TOKidentifier &&
-		    peek(&token)->value == TOKassign)
-		{
-		    a = parseAutoDeclarations(storageClass, comment);
-		    decldefs->append(a);
-		    continue;
-		}
-
-		/* Look for return type inference for template functions.
-		 */
-		Token *tk;
-		if (token.value == TOKidentifier &&
-		    (tk = peek(&token))->value == TOKlparen &&
-		    skipParens(tk, &tk) &&
-		    peek(tk)->value == TOKlparen)
-		{
-		    a = parseDeclarations(storageClass);
-		    decldefs->append(a);
-		    continue;
-		}
-		a = parseBlock();
-		s = new StorageClassDeclaration(storageClass, 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 }
- * or postblit:
- *	this(this) { body }
- * Current token is 'this'.
- */
-
-FuncDeclaration *Parser::parseCtor()
-{
-    Loc loc = this->loc;
-
-    nextToken();
-    if (token.value == TOKlparen && peek(&token)->value == TOKthis)
-    {	// this(this) { ... }
-	nextToken();
-	nextToken();
-	check(TOKrparen);
-	PostBlitDeclaration *f = new PostBlitDeclaration(loc, 0);
-	parseContracts(f);
-	return f;
-    }
-    int varargs;
-    Arguments *arguments = parseParameters(&varargs);
-    CtorDeclaration *f = new CtorDeclaration(loc, 0, arguments, varargs);
-    parseContracts(f);
-    return f;
-}
-
-/*****************************************
- * Parse a postblit definition:
- *	=this() { body }
- * Current token is '='.
- */
-
-PostBlitDeclaration *Parser::parsePostBlit()
-{
-    Loc loc = this->loc;
-
-    nextToken();
-    check(TOKthis);
-    check(TOKlparen);
-    check(TOKrparen);
-
-    PostBlitDeclaration *f = new PostBlitDeclaration(loc, 0);
-    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 = 0;
-	unsigned stc;
-	Expression *ae;
-
-	for (;1; nextToken())
-	{
-	    switch (token.value)
-	    {
-		case TOKrparen:
-		    break;
-
-		case TOKdotdotdot:
-		    varargs = 1;
-		    nextToken();
-		    break;
-
-		case TOKconst:
-		    if (peek(&token)->value == TOKlparen)
-			goto Ldefault;
-		    stc = STCconst;
-		    goto L2;
-
-		case TOKinvariant:
-		case TOKimmutable:
-		    if (peek(&token)->value == TOKlparen)
-			goto Ldefault;
-		    stc = STCinvariant;
-		    goto L2;
-
-		case TOKin:	   stc = STCin;		goto L2;
-		case TOKout:	   stc = STCout;	goto L2;
-		case TOKinout:
-		case TOKref:	   stc = STCref;	goto L2;
-		case TOKlazy:	   stc = STClazy;	goto L2;
-		case TOKscope:	   stc = STCscope;	goto L2;
-		case TOKfinal:	   stc = STCfinal;	goto L2;
-		L2:
-		    if (storageClass & stc ||
-			(storageClass & STCin && stc & (STCconst | STCscope)) ||
-			(stc & STCin && storageClass & (STCconst | STCscope))
-		       )
-			error("redundant storage class %s", Token::toChars(token.value));
-		    storageClass |= stc;
-		    {
-		    unsigned u = storageClass & (STCconst | STCinvariant);
-		    if (u & (u - 1))
-			error("conflicting storage class %s", Token::toChars(token.value));
-		    }
-		    continue;
-
-#if 0
-		case TOKstatic:	   stc = STCstatic;		goto L2;
-		case TOKauto:   storageClass = STCauto;		goto L4;
-		case TOKalias:  storageClass = STCalias;	goto L4;
-		L4:
-		    nextToken();
-		    if (token.value == TOKidentifier)
-		    {	ai = token.ident;
-			nextToken();
-		    }
-		    else
-			ai = NULL;
-		    at = NULL;		// no type
-		    ae = NULL;		// no default argument
-		    if (token.value == TOKassign)	// = defaultArg
-		    {   nextToken();
-			ae = parseDefaultInitExp();
-			hasdefault = 1;
-		    }
-		    else
-		    {   if (hasdefault)
-			    error("default argument expected for alias %s",
-				    ai ? ai->toChars() : "");
-		    }
-		    goto L3;
-#endif
-
-		default:
-		Ldefault:
-		    stc = storageClass & (STCin | STCout | STCref | STClazy);
-		    if (stc & (stc - 1))	// if stc is not a power of 2
-			error("incompatible parameter storage classes");
-		    if ((storageClass & (STCconst | STCout)) == (STCconst | STCout))
-			error("out cannot be const");
-		    if ((storageClass & (STCinvariant | STCout)) == (STCinvariant | STCout))
-			error("out cannot be invariant");
-		    if ((storageClass & STCscope) &&
-			(storageClass & (STCref | STCout)))
-			error("scope cannot be ref or out");
-		    at = parseType(&ai);
-		    ae = NULL;
-		    if (token.value == TOKassign)	// = defaultArg
-		    {   nextToken();
-			ae = parseDefaultInitExp();
-			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;
-		    }
-		L3:
-		    a = new Argument(storageClass, at, ai, ae);
-		    arguments->push(a);
-		    if (token.value == TOKcomma)
-		    {   nextToken();
-			goto L1;
-		    }
-		    break;
-	    }
-	    break;
-	}
-	break;
-
-    L1:	;
-    }
-    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();
-	memtype = parseDeclarator(memtype, NULL, NULL);
-    }
-    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)
-	{
-	    /* Can take the following forms:
-	     *	1. ident
-	     *	2. ident = value
-	     *	3. type ident = value
-	     */
-
-	    loc = this->loc;
-
-	    Type *type = NULL;
-	    Identifier *ident;
-	    Token *tp = peek(&token);
-	    if (token.value == TOKidentifier &&
-		(tp->value == TOKassign || tp->value == TOKcomma || tp->value == TOKrcurly))
-	    {
-		ident = token.ident;
-		type = NULL;
-		nextToken();
-	    }
-	    else
-	    {
-		type = parseType(&ident, NULL);
-		if (id || memtype)
-		    error("type only allowed if anonymous enum and no enum type");
-	    }
-
-	    Expression *value;
-	    if (token.value == TOKassign)
-	    {
-		nextToken();
-		value = parseAssignExp();
-	    }
-	    else
-	    {	value = NULL;
-		if (type)
-		    error("if type, there must be an initializer");
-	    }
-
-	    EnumMember *em = new EnumMember(loc, ident, value, type);
-	    e->members->push(em);
-
-	    if (token.value == TOKrcurly)
-		;
-	    else
-	    {   addComment(em, comment);
-		comment = NULL;
-		check(TOKcomma);
-	    }
-	    addComment(em, comment);
-	    comment = token.blockComment;
-	}
-	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;
-    Expression *constraint = 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();
-	    constraint = parseConstraint();
-	}
-    }
-
-    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)
-    {	// Wrap a template around the aggregate declaration
-
-	Array *decldefs = new Array();
-	decldefs->push(a);
-	TemplateDeclaration *tempdecl =
-		new TemplateDeclaration(loc, id, tpl, constraint, decldefs);
-	return tempdecl;
-    }
-
-    return a;
-}
-
-/*******************************************
- */
-
-BaseClasses *Parser::parseBaseClasses()
-{
-    BaseClasses *baseclasses = new BaseClasses();
-
-    for (; 1; nextToken())
-    {
-	enum PROT protection = PROTpublic;
-	switch (token.value)
-	{
-	    case TOKprivate:
-		protection = PROTprivate;
-		nextToken();
-		break;
-	    case TOKpackage:
-		protection = PROTpackage;
-		nextToken();
-		break;
-	    case TOKprotected:
-		protection = PROTprotected;
-		nextToken();
-		break;
-	    case TOKpublic:
-		protection = PROTpublic;
-		nextToken();
-		break;
-	}
-	if (token.value == TOKidentifier)
-	{
-	    BaseClass *b = new BaseClass(parseBasicType(), protection);
-	    baseclasses->push(b);
-	    if (token.value != TOKcomma)
-		break;
-	}
-	else
-	{
-	    error("base classes expected instead of %s", token.toChars());
-	    return NULL;
-	}
-    }
-    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;
-    Expression *constraint = NULL;
-    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;
-
-    constraint = parseConstraint();
-
-    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, constraint, decldefs);
-    return tempdecl;
-
-Lerr:
-    return NULL;
-}
-
-/******************************************
- * Parse template parameter list.
- * Input:
- *	flag	0: parsing "( list )"
- *		1: parsing non-empty "list )"
- */
-
-TemplateParameters *Parser::parseTemplateParameterList(int flag)
-{
-    TemplateParameters *tpl = new TemplateParameters();
-
-    if (!flag && token.value != TOKlparen)
-    {   error("parenthesized TemplateParameterList expected following TemplateIdentifier");
-	goto Lerr;
-    }
-    nextToken();
-
-    // Get array of TemplateParameters
-    if (flag || 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();
-		Type *spectype = NULL;
-		if (isDeclaration(&token, 2, TOKreserved, NULL))
-		{
-		    spectype = parseType(&tp_ident);
-		}
-		else
-		{
-		    if (token.value != TOKidentifier)
-		    {   error("identifier expected for template alias parameter");
-			goto Lerr;
-		    }
-		    tp_ident = token.ident;
-		    nextToken();
-		}
-		Object *spec = NULL;
-		if (token.value == TOKcolon)	// : Type
-		{
-		    nextToken();
-		    if (isDeclaration(&token, 0, TOKreserved, NULL))
-			spec = parseType();
-		    else
-			spec = parseCondExp();
-		}
-		Object *def = NULL;
-		if (token.value == TOKassign)	// = Type
-		{
-		    nextToken();
-		    if (isDeclaration(&token, 0, TOKreserved, NULL))
-			def = parseType();
-		    else
-			def = parseCondExp();
-		}
-		tp = new TemplateAliasParameter(loc, tp_ident, spectype, spec, def);
-	    }
-	    else if (t->value == TOKcolon || t->value == TOKassign ||
-		     t->value == TOKcomma || t->value == TOKrparen)
-	    {	// TypeParameter
-		if (token.value != TOKidentifier)
-		{   error("identifier expected for template type 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 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 = parseType(&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 = parseDefaultInitExp();
-		}
-		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)
-	{
-	    tqual = parseTypeof();
-	    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();
-	    if (token.value == TOKlparen)
-		tiargs = parseTemplateArgumentList();
-	    else
-		tiargs = parseTemplateArgument();
-	}
-
-	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");
-    if (token.value != TOKlparen && token.value != TOKlcurly)
-    {   error("!(TemplateArgumentList) expected following TemplateIdentifier");
-	return new Objects();
-    }
-    return parseTemplateArgumentList2();
-}
-
-Objects *Parser::parseTemplateArgumentList2()
-{
-    Objects *tiargs = new Objects();
-    enum TOK endtok = TOKrparen;
-    nextToken();
-
-    // Get TemplateArgumentList
-    if (token.value != endtok)
-    {
-	while (1)
-	{
-	    // See if it is an Expression or a Type
-	    if (isDeclaration(&token, 0, TOKreserved, NULL))
-	    {	// Template argument is a type
-		Type *ta = parseType();
-		tiargs->push(ta);
-	    }
-	    else
-	    {	// Template argument is an expression
-		Expression *ea = parseAssignExp();
-		tiargs->push(ea);
-	    }
-	    if (token.value != TOKcomma)
-		break;
-	    nextToken();
-	}
-    }
-    check(endtok, "template argument list");
-    return tiargs;
-}
-
-/*****************************
- * Parse single template argument, to support the syntax:
- *	foo!arg
- * Input:
- *	current token is the arg
- */
-
-Objects *Parser::parseTemplateArgument()
-{
-    //printf("parseTemplateArgument()\n");
-    Objects *tiargs = new Objects();
-    Type *ta;
-    switch (token.value)
-    {
-	case TOKidentifier:
-	    ta = new TypeIdentifier(loc, token.ident);
-	    goto LabelX;
-
-	CASE_BASIC_TYPES_X(ta):
-	    tiargs->push(ta);
-	    nextToken();
-	    break;
-
-	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:
-	case TOKfile:
-	case TOKline:
-	{   // Template argument is an expression
-	    Expression *ea = parsePrimaryExp();
-	    tiargs->push(ea);
-	    break;
-	}
-
-	default:
-	    error("template argument expected following !");
-	    break;
-    }
-    if (token.value == TOKnot)
-	error("multiple ! arguments are not allowed");
-    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, token.ident, 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;
-}
-
-Type *Parser::parseType(Identifier **pident, TemplateParameters **tpl)
-{   Type *t;
-
-    if (token.value == TOKconst && peek(&token)->value != TOKlparen)
-    {
-	nextToken();
-	/* const type
-	 */
-	t = parseType(pident, tpl);
-	t = t->makeConst();
-	return t;
-    }
-    else if ((token.value == TOKinvariant || token.value == TOKimmutable) &&
-             peek(&token)->value != TOKlparen)
-    {
-	nextToken();
-	/* invariant type
-	 */
-	t = parseType(pident, tpl);
-	t = t->makeInvariant();
-	return t;
-    }
-    else
-	t = parseBasicType();
-    t = parseDeclarator(t, pident, tpl);
-    return t;
-}
-
-Type *Parser::parseBasicType()
-{   Type *t;
-    Identifier *id;
-    TypeQualified *tid;
-
-    //printf("parseBasicType()\n");
-    switch (token.value)
-    {
-	CASE_BASIC_TYPES_X(t):
-	    nextToken();
-	    break;
-
-	case TOKidentifier:
-	    id = token.ident;
-	    nextToken();
-	    if (token.value == TOKnot)
-	    {	// ident!(template_arguments)
-		TemplateInstance *tempinst = new TemplateInstance(loc, id);
-		nextToken();
-		if (token.value == TOKlparen)
-		    // ident!(template_arguments)
-		    tempinst->tiargs = parseTemplateArgumentList();
-		else
-		    // ident!template_argument
-		    tempinst->tiargs = parseTemplateArgument();
-		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)
-		{
-		    TemplateInstance *tempinst = new TemplateInstance(loc, id);
-		    nextToken();
-		    if (token.value == TOKlparen)
-			// ident!(template_arguments)
-			tempinst->tiargs = parseTemplateArgumentList();
-		    else
-			// ident!template_argument
-			tempinst->tiargs = parseTemplateArgument();
-		    tid->addIdent((Identifier *)tempinst);
-		}
-		else
-		    tid->addIdent(id);
-	    }
-	    t = tid;
-	    break;
-
-	case TOKdot:
-	    // Leading . as in .foo
-	    id = Id::empty;
-	    goto Lident;
-
-	case TOKtypeof:
-	    // typeof(expression)
-	    tid = parseTypeof();
-	    goto Lident2;
-
-	case TOKconst:
-	    // const(type)
-	    nextToken();
-	    check(TOKlparen);
-	    t = parseType();
-	    check(TOKrparen);
-	    t = t->makeConst();
-	    break;
-
-	case TOKinvariant:
-	case TOKimmutable:
-	    // invariant(type)
-	    nextToken();
-	    check(TOKlparen);
-	    t = parseType();
-	    check(TOKrparen);
-	    t = t->makeInvariant();
-	    break;
-
-	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)
-{
-    //printf("parseBasicType2()\n");
-    while (1)
-    {
-	switch (token.value)
-	{
-	    case TOKmul:
-		t = new TypePointer(t);
-		nextToken();
-		continue;
-
-	    case TOKlbracket:
-		// 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
-
-		    //printf("it's an associative array\n");
-		    Type *index = parseType();		// [ type ]
-		    t = new TypeAArray(t, index);
-		    check(TOKrbracket);
-		}
-		else
-		{
-		    //printf("it's type[expression]\n");
-		    inBrackets++;
-		    Expression *e = parseExpression();		// [ expression ]
-		    if (token.value == TOKslice)
-		    {
-			nextToken();
-			Expression *e2 = parseExpression();	// [ exp .. exp ]
-			t = new TypeSlice(t, e, e2);
-		    }
-		    else
-			t = new TypeSArray(t,e);
-		    inBrackets--;
-		    check(TOKrbracket);
-		}
-		continue;
-
-	    case TOKdelegate:
-	    case TOKfunction:
-	    {	// Handle delegate declaration:
-		//	t delegate(parameter list) nothrow pure
-		//	t function(parameter list) nothrow pure
-		Arguments *arguments;
-		int varargs;
-		bool ispure = false;
-		bool isnothrow = false;
-		enum TOK save = token.value;
-
-		nextToken();
-		arguments = parseParameters(&varargs);
-		while (1)
-		{   // Postfixes of 'pure' or 'nothrow'
-		    if (token.value == TOKpure)
-			ispure = true;
-		    else if (token.value == TOKnothrow)
-			isnothrow = true;
-		    else
-			break;
-		    nextToken();
-		}
-		TypeFunction *tf = new TypeFunction(arguments, t, varargs, linkage);
-		tf->ispure = ispure;
-		tf->isnothrow = isnothrow;
-		if (save == TOKdelegate)
-		    t = new TypeDelegate(tf);
-		else
-		    t = new TypePointer(tf);	// pointer to function
-		continue;
-	    }
-
-	    default:
-		return t;
-	}
-	assert(0);
-    }
-    assert(0);
-    return NULL;
-}
-
-Type *Parser::parseDeclarator(Type *t, Identifier **pident, TemplateParameters **tpl)
-{   Type *ts;
-
-    //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.
-		TypeNext *ta;
-		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
-
-		    //printf("it's an associative array\n");
-		    Type *index = parseType();		// [ type ]
-		    check(TOKrbracket);
-		    ta = new TypeAArray(t, index);
-		}
-		else
-		{
-		    //printf("It's a static array\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 = &((TypeNext*)*pt)->next)
-		    ;
-		*pt = ta;
-		continue;
-	    }
-#endif
-	    case TOKlparen:
-	    {
-		if (tpl)
-		{
-		    /* Look ahead to see if this is (...)(...),
-		     * i.e. a function template declaration
-		     */
-		    if (peekPastParen(&token)->value == TOKlparen)
-		    {
-			//printf("function template declaration\n");
-
-			// Gather template parameter list
-			*tpl = parseTemplateParameterList();
-		    }
-		}
-
-		int varargs;
-		Arguments *arguments = parseParameters(&varargs);
-		Type *tf = new TypeFunction(arguments, t, varargs, linkage);
-
-		/* Parse const/invariant/nothrow/pure postfix
-		 */
-		while (1)
-		{
-		    switch (token.value)
-		    {
-			case TOKconst:
-			    tf = tf->makeConst();
-			    nextToken();
-			    continue;
-
-			case TOKinvariant:
-			case TOKimmutable:
-			    tf = tf->makeInvariant();
-			    nextToken();
-			    continue;
-
-			case TOKnothrow:
-			    ((TypeFunction *)tf)->isnothrow = 1;
-			    nextToken();
-			    continue;
-
-			case TOKpure:
-			    ((TypeFunction *)tf)->ispure = 1;
-			    nextToken();
-			    continue;
-		    }
-		    break;
-		}
-
-		/* Insert tf into
-		 *   ts -> ... -> t
-		 * so that
-		 *   ts -> ... -> tf -> t
-		 */
-		Type **pt;
-		for (pt = &ts; *pt != t; pt = &((TypeNext*)*pt)->next)
-		    ;
-		*pt = tf;
-		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(unsigned 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() %s\n", token.toChars());
-    if (storage_class)
-    {	ts = NULL;		// infer type
-	goto L2;
-    }
-
-    switch (token.value)
-    {
-	case TOKtypedef:
-	case TOKalias:
-	    tok = token.value;
-	    nextToken();
-	    break;
-    }
-
-    storage_class = STCundefined;
-    while (1)
-    {
-	switch (token.value)
-	{
-	    case TOKconst:
-		if (peek(&token)->value == TOKlparen)
-		    break;		// const as type constructor
-		stc = STCconst;		// const as storage class
-		goto L1;
-
-	    case TOKinvariant:
-	    case TOKimmutable:
-		if (peek(&token)->value == TOKlparen)
-		    break;
-		stc = STCinvariant;
-		goto L1;
-
-	    case TOKshared:
-		if (peek(&token)->value == TOKlparen)
-		    break;
-		stc = STCshared;
-		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;
-	    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;
-	    L1:
-		if (storage_class & stc)
-		    error("redundant storage class '%s'", token.toChars());
-		storage_class = (STC) (storage_class | stc);
-		{
-		unsigned u = storage_class;
-		u &= STCconst | STCinvariant | STCmanifest;
-		if (u & (u - 1))
-		    error("conflicting storage class %s", Token::toChars(token.value));
-		}
-		nextToken();
-		continue;
-
-	    case TOKextern:
-		if (peek(&token)->value != TOKlparen)
-		{   stc = STCextern;
-		    goto L1;
-		}
-
-		link = parseLinkage();
-		continue;
-
-	    default:
-		break;
-	}
-	break;
-    }
-
-    /* Look for auto initializers:
-     *	storage_class identifier = initializer;
-     */
-    if (storage_class &&
-	token.value == TOKidentifier &&
-	peek(&token)->value == TOKassign)
-    {
-	return parseAutoDeclarations(storage_class, comment);
-    }
-
-    if (token.value == TOKclass)
-    {
-	AggregateDeclaration *s = (AggregateDeclaration *)parseAggregate();
-	s->storage_class |= storage_class;
-	a = new Array();
-	a->push(s);
-	addComment(s, comment);
-	return a;
-    }
-
-    /* Look for return type inference for template functions.
-     */
-    {
-    Token *tk;
-    if (storage_class &&
-	token.value == TOKidentifier &&
-	(tk = peek(&token))->value == TOKlparen &&
-	skipParens(tk, &tk) &&
-	peek(tk)->value == TOKlparen)
-    {
-	ts = NULL;
-    }
-    else
-    {
-	ts = parseBasicType();
-	ts = parseBasicType2(ts);
-    }
-    }
-
-L2:
-    tfirst = NULL;
-    a = new Array();
-
-    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)
-	{
-	    TypeFunction *tf = (TypeFunction *)t;
-	    Expression *constraint = NULL;
-#if 0
-	    if (Argument::isTPL(tf->parameters))
-	    {
-		if (!tpl)
-		    tpl = new TemplateParameters();
-	    }
-#endif
-	    FuncDeclaration *f =
-		new FuncDeclaration(loc, 0, ident, (enum STC)storage_class, t);
-	    addComment(f, comment);
-	    if (tpl)
-		constraint = parseConstraint();
-	    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);
-	    }
-	    /* A template parameter list means it's a function template
-	     */
-	    if (tpl)
-	    {
-		// Wrap a template around the function declaration
-		Array *decldefs = new Array();
-		decldefs->push(s);
-		TemplateDeclaration *tempdecl =
-		    new TemplateDeclaration(loc, s->ident, tpl, constraint, 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 ';' ',' or '}', 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:
-	case TOKimmutable:
-//	case TOKtypeof:
-	Ldeclaration:
-	{   Array *a;
-
-	    a = parseDeclarations(STCundefined);
-	    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 CompoundStatement(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:
-	{   /* Determine if this is a manifest constant declaration,
-	     * or a conventional enum.
-	     */
-	    Dsymbol *d;
-	    Token *t = peek(&token);
-	    if (t->value == TOKlcurly || t->value == TOKcolon)
-		d = parseEnum();
-	    else if (t->value != TOKidentifier)
-		goto Ldeclaration;
-	    else
-	    {
-		t = peek(t);
-		if (t->value == TOKlcurly || t->value == TOKcolon ||
-		    t->value == TOKsemicolon)
-		    d = parseEnum();
-		else
-		    goto Ldeclaration;
-	    }
-	    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 = 0;
-		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;
-		    }
-		}
-		at = parseType(&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();
-	    if (token.value == TOKslice && arguments->dim == 1)
-	    {
-		Argument *a = (Argument *)arguments->data[0];
-		delete arguments;
-		nextToken();
-		Expression *upr = parseExpression();
-		check(TOKrparen);
-		body = parseStatement(0);
-		s = new ForeachRangeStatement(loc, op, a, aggr, upr, body);
-	    }
-	    else
-	    {
-		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(0, 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 *at;
-		Identifier *ai;
-
-		at = parseType(&ai);
-		check(TOKassign);
-		arg = new Argument(0, 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(0, 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);
-		    id = NULL;
-		    t = parseType(&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 || token.value == TOKimmutable) &&
-	peek(t)->value != TOKlparen)
-    {	/* const type
-	 * invariant type
-	 */
-	t = peek(t);
-    }
-#endif
-
-    if (!isBasicType(&t))
-	goto Lisnot;
-    if (!isDeclarator(&t, &haveId, endtok))
-	goto Lisnot;
-    if ( needId == 1 ||
-	(needId == 0 && !haveId) ||
-	(needId == 2 &&  haveId))
-    {	if (pt)
-	    *pt = t;
-	goto Lis;
-    }
-    else
-	goto Lisnot;
-
-Lis:
-    //printf("\tis declaration\n");
-    return TRUE;
-
-Lisnot:
-    //printf("\tis not declaration\n");
-    return FALSE;
-}
-
-int Parser::isBasicType(Token **pt)
-{
-    // This code parallels parseBasicType()
-    Token *t = *pt;
-    Token *t2;
-    int parens;
-    int haveId = 0;
-
-    switch (t->value)
-    {
-	CASE_BASIC_TYPES:
-	    t = peek(t);
-	    break;
-
-	case TOKidentifier:
-	L5:
-	    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:
-		    /* Seen a !
-		     * Look for:
-		     * !( args ), !identifier, etc.
-		     */
-		    t = peek(t);
-		    switch (t->value)
-		    {	case TOKidentifier:
-			    goto L5;
-			case TOKlparen:
-			    if (!skipParens(t, &t))
-				goto Lfalse;
-			    break;
-			CASE_BASIC_TYPES:
-			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:
-			case TOKfile:
-			case TOKline:
-			    goto L2;
-			default:
-			    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;
-
-	case TOKconst:
-	case TOKinvariant:
-	case TOKimmutable:
-	    // const(type)  or  invariant(type)
-	    t = peek(t);
-	    if (t->value != TOKlparen)
-		goto Lfalse;
-	    t = peek(t);
-	    if (!isDeclaration(t, 0, TOKrparen, &t))
-		goto Lfalse;
-	    t = peek(t);
-	    break;
-
-	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;
-		while (1)
-		{
-		    switch (t->value)
-		    {
-			case TOKconst:
-			case TOKinvariant:
-			case TOKimmutable:
-			case TOKpure:
-			case TOKnothrow:
-			    t = peek(t);
-			    continue;
-			default:
-			    break;
-		    }
-		    break;
-		}
-		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);
-    for (;1; t = peek(t))
-    {
-	switch (t->value)
-	{
-	    case TOKrparen:
-		break;
-
-	    case TOKdotdotdot:
-		t = peek(t);
-		break;
-
-	    case TOKin:
-	    case TOKout:
-	    case TOKinout:
-	    case TOKref:
-	    case TOKlazy:
-	    case TOKconst:
-	    case TOKinvariant:
-	    case TOKimmutable:
-	    case TOKfinal:
-		continue;
-
-#if 0
-	    case TOKstatic:
-		continue;
-	    case TOKauto:
-	    case TOKalias:
-		t = peek(t);
-		if (t->value == TOKidentifier)
-		    t = peek(t);
-		if (t->value == TOKassign)
-		{   t = peek(t);
-		    if (!isExpression(&t))
-			return FALSE;
-		}
-		goto L3;
-#endif
-
-	    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;
-		}
-	    L3:
-		if (t->value == TOKcomma)
-		{
-		    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;
-    int curlynest = 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 TOKlcurly:
-		curlynest++;
-		continue;
-
-	    case TOKrcurly:
-		if (--curlynest >= 0)
-		    continue;
-		return FALSE;
-
-	    case TOKslice:
-		if (brnest)
-		    continue;
-		break;
-
-	    case TOKsemicolon:
-		if (curlynest)
-		    continue;
-		return FALSE;
-
-	    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 && peekNext() != TOKis)
-	    {	// identifier!(template-argument-list)
-		TemplateInstance *tempinst;
-
-		tempinst = new TemplateInstance(loc, id);
-		nextToken();
-		if (token.value == TOKlparen)
-		    // ident!(template_arguments)
-		    tempinst->tiargs = parseTemplateArgumentList();
-		else
-		    // ident!template_argument
-		    tempinst->tiargs = parseTemplateArgument();
-		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, token.int32value, Type::tint32);
-	    nextToken();
-	    break;
-
-	case TOKuns32v:
-	    e = new IntegerExp(loc, token.uns32value, 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, token.uns32value, Type::tchar);
-	    nextToken();
-	    break;
-
-	case TOKwcharv:
-	    e = new IntegerExp(loc, token.uns32value, Type::twchar);
-	    nextToken();
-	    break;
-
-	case TOKdcharv:
-	    e = new IntegerExp(loc, token.uns32value, 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:
-	{
-	    t = parseTypeof();
-	    e = new TypeExp(loc, t);
-	    break;
-	}
-
-	case TOKtypeid:
-	{   Type *t;
-
-	    nextToken();
-	    check(TOKlparen, "typeid");
-	    t = parseType();		// ( 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;
-	    TemplateParameters *tpl = NULL;
-	    Loc loc = this->loc;
-
-	    nextToken();
-	    if (token.value == TOKlparen)
-	    {
-		nextToken();
-		targ = parseType(&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 ||
-			 token.value == TOKconst && peek(&token)->value == TOKrparen ||
-			 token.value == TOKinvariant && peek(&token)->value == TOKrparen ||
-			 token.value == TOKimmutable && peek(&token)->value == TOKrparen ||
-			 token.value == TOKfunction ||
-			 token.value == TOKdelegate ||
-			 token.value == TOKreturn))
-		    {
-			tok2 = token.value;
-			nextToken();
-		    }
-		    else
-		    {
-			tspec = parseType();
-		    }
-		}
-		if (ident && tspec)
-		{
-		    if (token.value == TOKcomma)
-			tpl = parseTemplateParameterList(1);
-		    else
-		    {	tpl = new TemplateParameters();
-			check(TOKrparen);
-		    }
-		    TemplateParameter *tp = new TemplateTypeParameter(loc, ident, NULL, NULL);
-		    tpl->insert(0, tp);
-		}
-		else
-		    check(TOKrparen);
-	    }
-	    else
-	    {   error("(type identifier : specialization) expected following is");
-		goto Lerr;
-	    }
-	    e = new IsExp(loc, targ, ident, tok, tspec, tok2, tpl);
-	    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 } pure nothrow
-	     * delegate type(parameters) { body } pure nothrow
-	     * (parameters) { body }
-	     * { body }
-	     */
-	    Arguments *arguments;
-	    int varargs;
-	    FuncLiteralDeclaration *fd;
-	    Type *t;
-	    bool isnothrow = false;
-	    bool ispure = false;
-
-	    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);
-		while (1)
-		{
-		    if (token.value == TOKpure)
-			ispure = true;
-		    else if (token.value == TOKnothrow)
-			isnothrow = true;
-		    else
-			break;
-		    nextToken();
-		}
-	    }
-	    TypeFunction *tf = new TypeFunction(arguments, t, varargs, linkage);
-	    tf->ispure = ispure;
-	    tf->isnothrow = isnothrow;
-	    fd = new FuncLiteralDeclaration(loc, 0, tf, 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 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 && peekNext() != TOKis)
-		    {   // identifier!(template-argument-list)
-			TemplateInstance *tempinst = new TemplateInstance(loc, id);
-			nextToken();
-			if (token.value == TOKlparen)
-			    // ident!(template_arguments)
-			    tempinst->tiargs = parseTemplateArgumentList();
-			else
-			    // ident!template_argument
-			    tempinst->tiargs = parseTemplateArgument();
-			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);
-	    /* Look for cast(const) and cast(invariant)
-	     */
-	    if ((token.value == TOKconst || token.value == TOKinvariant || token.value == TOKimmutable) &&
-		peek(&token)->value == TOKrparen)
-	    {	enum TOK tok = token.value;
-		nextToken();
-		nextToken();
-		e = parseUnaryExp();
-		e = new CastExp(loc, e, tok);
-	    }
-	    else
-	    {
-		t = parseType();		// ( 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 = parseType();
-			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();
-	    e = parsePostExp(e);
-	    break;
-	}
-	default:
-	    e = parsePrimaryExp();
-	    e = parsePostExp(e);
-	    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;
-    }
-
-    t = parseBasicType();
-    t = parseBasicType2(t);
-    if (t->ty == Taarray)
-    {	TypeAArray *taa = (TypeAArray *)t;
-	Type *index = taa->index;
-
-	Expression *e = index->toExpression();
-	if (e)
-	{   arguments = new Expressions();
-	    arguments->push(e);
-	    t = new TypeDArray(taa->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(tsa->next);
-    }
-    else if (token.value == TOKlparen)
-    {
-	arguments = parseArguments();
-    }
-    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"
+#include "aliasthis.h"
+
+// 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
+
+
+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;
+	bool safe = FALSE;
+
+	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, safe);
+
+	    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;
+    enum STC stc;
+    unsigned storageClass;
+    Condition *condition;
+    unsigned char *comment;
+
+    //printf("Parser::parseDeclDefs()\n");
+    decldefs = new Array();
+    do
+    {
+	comment = token.blockComment;
+	storageClass = STCundefined;
+	switch (token.value)
+	{
+	    case TOKenum:
+	    {	/* Determine if this is a manifest constant declaration,
+		 * or a conventional enum.
+		 */
+		Token *t = peek(&token);
+		if (t->value == TOKlcurly || t->value == TOKcolon)
+		    s = parseEnum();
+		else if (t->value != TOKidentifier)
+		    goto Ldeclaration;
+		else
+		{
+		    t = peek(t);
+		    if (t->value == TOKlcurly || t->value == TOKcolon ||
+			t->value == TOKsemicolon)
+			s = parseEnum();
+		    else
+			goto Ldeclaration;
+		}
+		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(STCundefined);
+		decldefs->append(a);
+		continue;
+
+	    case TOKthis:
+		s = parseCtor();
+		break;
+
+#if 0 // dead end, use this(this){} instead
+	    case TOKassign:
+		s = parsePostBlit();
+		break;
+#endif
+	    case TOKtilde:
+		s = parseDtor();
+		break;
+
+	    case TOKinvariant:
+	    {	Token *t;
+		t = peek(&token);
+		if (t->value == TOKlparen)
+		{
+		    if (peek(t)->value == TOKrparen)
+			// invariant() forms start of class invariant
+			s = parseInvariant();
+		    else
+			// invariant(type)
+			goto Ldeclaration;
+		}
+		else
+		{
+		    stc = STCimmutable;
+		    goto Lstc;
+		}
+		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:
+		if (peek(&token)->value == TOKlparen)
+		    goto Ldeclaration;
+		stc = STCconst;
+		goto Lstc;
+
+	    case TOKimmutable:
+		if (peek(&token)->value == TOKlparen)
+		    goto Ldeclaration;
+		stc = STCimmutable;
+		goto Lstc;
+
+	    case TOKshared:
+		if (peek(&token)->value == TOKlparen)
+		    goto Ldeclaration;
+		stc = STCshared;
+		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 TOKgshared:      stc = STCgshared;	 goto Lstc;
+	    //case TOKmanifest:	  stc = STCmanifest;	 goto Lstc;
+#endif
+
+	    Lstc:
+		if (storageClass & stc)
+		    error("redundant storage class %s", Token::toChars(token.value));
+		composeStorageClass(storageClass | stc);
+		nextToken();
+	    Lstc2:
+		storageClass |= stc;
+		switch (token.value)
+		{
+		    case TOKconst:
+		    case TOKinvariant:
+		    case TOKimmutable:
+		    case TOKshared:
+			// If followed by a (, it is not a storage class
+			if (peek(&token)->value == TOKlparen)
+			    break;
+			if (token.value == TOKconst)
+			    stc = STCconst;
+			else if (token.value == TOKshared)
+			    stc = STCshared;
+			else
+			    stc = STCimmutable;
+			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 TOKnothrow:      stc = STCnothrow;	 goto Lstc;
+		    case TOKpure:         stc = STCpure;	 goto Lstc;
+		    case TOKref:          stc = STCref;          goto Lstc;
+		    case TOKtls:          stc = STCtls;		 goto Lstc;
+		    case TOKgshared:      stc = STCgshared;	 goto Lstc;
+		    //case TOKmanifest:	  stc = STCmanifest;	 goto Lstc;
+		    default:
+			break;
+		}
+
+		/* Look for auto initializers:
+		 *	storage_class identifier = initializer;
+		 */
+		if (token.value == TOKidentifier &&
+		    peek(&token)->value == TOKassign)
+		{
+		    a = parseAutoDeclarations(storageClass, comment);
+		    decldefs->append(a);
+		    continue;
+		}
+
+		/* Look for return type inference for template functions.
+		 */
+		Token *tk;
+		if (token.value == TOKidentifier &&
+		    (tk = peek(&token))->value == TOKlparen &&
+		    skipParens(tk, &tk) &&
+		    (peek(tk)->value == TOKlparen ||
+		     peek(tk)->value == TOKlcurly)
+		   )
+		{
+		    a = parseDeclarations(storageClass);
+		    decldefs->append(a);
+		    continue;
+		}
+		a = parseBlock();
+		s = new StorageClassDeclaration(storageClass, 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;
+}
+
+/*********************************************
+ * Give error on conflicting storage classes.
+ */
+
+void Parser::composeStorageClass(unsigned stc)
+{
+    unsigned u = stc;
+    u &= STCconst | STCimmutable | STCmanifest;
+    if (u & (u - 1))
+	error("conflicting storage class %s", Token::toChars(token.value));
+    u = stc;
+    u &= STCgshared | STCshared | STCtls;
+    if (u & (u - 1))
+	error("conflicting storage class %s", Token::toChars(token.value));
+}
+
+/********************************************
+ * 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(parameters) { body }
+ * or postblit:
+ *	this(this) { body }
+ * or constructor template:
+ *	this(templateparameters)(parameters) { body }
+ * Current token is 'this'.
+ */
+
+Dsymbol *Parser::parseCtor()
+{
+    Loc loc = this->loc;
+
+    nextToken();
+    if (token.value == TOKlparen && peek(&token)->value == TOKthis)
+    {	// this(this) { ... }
+	nextToken();
+	nextToken();
+	check(TOKrparen);
+	PostBlitDeclaration *f = new PostBlitDeclaration(loc, 0);
+	parseContracts(f);
+	return f;
+    }
+
+    /* Look ahead to see if:
+     *   this(...)(...)
+     * which is a constructor template
+     */
+    TemplateParameters *tpl = NULL;
+    if (token.value == TOKlparen && peekPastParen(&token)->value == TOKlparen)
+    {	tpl = parseTemplateParameterList();
+
+	int varargs;
+	Arguments *arguments = parseParameters(&varargs);
+
+	Expression *constraint = NULL;
+	if (tpl)
+	    constraint = parseConstraint();
+
+	CtorDeclaration *f = new CtorDeclaration(loc, 0, arguments, varargs);
+	parseContracts(f);
+
+	// Wrap a template around it
+	Array *decldefs = new Array();
+	decldefs->push(f);
+	TemplateDeclaration *tempdecl =
+	    new TemplateDeclaration(loc, f->ident, tpl, constraint, decldefs);
+	return tempdecl;
+    }
+
+    /* Just a regular constructor
+     */
+    int varargs;
+    Arguments *arguments = parseParameters(&varargs);
+    CtorDeclaration *f = new CtorDeclaration(loc, 0, arguments, varargs);
+    parseContracts(f);
+    return f;
+}
+
+/*****************************************
+ * Parse a postblit definition:
+ *	=this() { body }
+ * Current token is '='.
+ */
+
+PostBlitDeclaration *Parser::parsePostBlit()
+{
+    Loc loc = this->loc;
+
+    nextToken();
+    check(TOKthis);
+    check(TOKlparen);
+    check(TOKrparen);
+
+    PostBlitDeclaration *f = new PostBlitDeclaration(loc, 0);
+    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 = 0;
+	unsigned stc;
+	Expression *ae;
+
+	for (;1; nextToken())
+	{
+	    switch (token.value)
+	    {
+		case TOKrparen:
+		    break;
+
+		case TOKdotdotdot:
+		    varargs = 1;
+		    nextToken();
+		    break;
+
+		case TOKconst:
+		    if (peek(&token)->value == TOKlparen)
+			goto Ldefault;
+		    stc = STCconst;
+		    goto L2;
+
+		case TOKinvariant:
+		case TOKimmutable:
+		    if (peek(&token)->value == TOKlparen)
+			goto Ldefault;
+		    stc = STCimmutable;
+		    goto L2;
+
+		case TOKshared:
+		    if (peek(&token)->value == TOKlparen)
+			goto Ldefault;
+		    stc = STCshared;
+		    goto L2;
+
+		case TOKin:	   stc = STCin;		goto L2;
+		case TOKout:	   stc = STCout;	goto L2;
+		case TOKinout:
+		case TOKref:	   stc = STCref;	goto L2;
+		case TOKlazy:	   stc = STClazy;	goto L2;
+		case TOKscope:	   stc = STCscope;	goto L2;
+		case TOKfinal:	   stc = STCfinal;	goto L2;
+		L2:
+		    if (storageClass & stc ||
+			(storageClass & STCin && stc & (STCconst | STCscope)) ||
+			(stc & STCin && storageClass & (STCconst | STCscope))
+		       )
+			error("redundant storage class %s", Token::toChars(token.value));
+		    storageClass |= stc;
+		    composeStorageClass(storageClass);
+		    continue;
+
+#if 0
+		case TOKstatic:	   stc = STCstatic;		goto L2;
+		case TOKauto:   storageClass = STCauto;		goto L4;
+		case TOKalias:  storageClass = STCalias;	goto L4;
+		L4:
+		    nextToken();
+		    if (token.value == TOKidentifier)
+		    {	ai = token.ident;
+			nextToken();
+		    }
+		    else
+			ai = NULL;
+		    at = NULL;		// no type
+		    ae = NULL;		// no default argument
+		    if (token.value == TOKassign)	// = defaultArg
+		    {   nextToken();
+			ae = parseDefaultInitExp();
+			hasdefault = 1;
+		    }
+		    else
+		    {   if (hasdefault)
+			    error("default argument expected for alias %s",
+				    ai ? ai->toChars() : "");
+		    }
+		    goto L3;
+#endif
+
+		default:
+		Ldefault:
+		    stc = storageClass & (STCin | STCout | STCref | STClazy);
+		    if (stc & (stc - 1))	// if stc is not a power of 2
+			error("incompatible parameter storage classes");
+		    if ((storageClass & (STCconst | STCout)) == (STCconst | STCout))
+			error("out cannot be const");
+		    if ((storageClass & (STCimmutable | STCout)) == (STCimmutable | STCout))
+			error("out cannot be immutable");
+		    if ((storageClass & STCscope) &&
+			(storageClass & (STCref | STCout)))
+			error("scope cannot be ref or out");
+		    at = parseType(&ai);
+		    ae = NULL;
+		    if (token.value == TOKassign)	// = defaultArg
+		    {   nextToken();
+			ae = parseDefaultInitExp();
+			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;
+		    }
+		L3:
+		    a = new Argument(storageClass, at, ai, ae);
+		    arguments->push(a);
+		    if (token.value == TOKcomma)
+		    {   nextToken();
+			goto L1;
+		    }
+		    break;
+	    }
+	    break;
+	}
+	break;
+
+    L1:	;
+    }
+    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();
+	memtype = parseDeclarator(memtype, NULL, NULL);
+    }
+    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)
+	{
+	    /* Can take the following forms:
+	     *	1. ident
+	     *	2. ident = value
+	     *	3. type ident = value
+	     */
+
+	    loc = this->loc;
+
+	    Type *type = NULL;
+	    Identifier *ident;
+	    Token *tp = peek(&token);
+	    if (token.value == TOKidentifier &&
+		(tp->value == TOKassign || tp->value == TOKcomma || tp->value == TOKrcurly))
+	    {
+		ident = token.ident;
+		type = NULL;
+		nextToken();
+	    }
+	    else
+	    {
+		type = parseType(&ident, NULL);
+		if (id || memtype)
+		    error("type only allowed if anonymous enum and no enum type");
+	    }
+
+	    Expression *value;
+	    if (token.value == TOKassign)
+	    {
+		nextToken();
+		value = parseAssignExp();
+	    }
+	    else
+	    {	value = NULL;
+		if (type)
+		    error("if type, there must be an initializer");
+	    }
+
+	    EnumMember *em = new EnumMember(loc, ident, value, type);
+	    e->members->push(em);
+
+	    if (token.value == TOKrcurly)
+		;
+	    else
+	    {   addComment(em, comment);
+		comment = NULL;
+		check(TOKcomma);
+	    }
+	    addComment(em, comment);
+	    comment = token.blockComment;
+	}
+	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;
+    Expression *constraint = 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();
+	    constraint = parseConstraint();
+	}
+    }
+
+    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)
+    {	// Wrap a template around the aggregate declaration
+
+	Array *decldefs = new Array();
+	decldefs->push(a);
+	TemplateDeclaration *tempdecl =
+		new TemplateDeclaration(loc, id, tpl, constraint, decldefs);
+	return tempdecl;
+    }
+
+    return a;
+}
+
+/*******************************************
+ */
+
+BaseClasses *Parser::parseBaseClasses()
+{
+    BaseClasses *baseclasses = new BaseClasses();
+
+    for (; 1; nextToken())
+    {
+	enum PROT protection = PROTpublic;
+	switch (token.value)
+	{
+	    case TOKprivate:
+		protection = PROTprivate;
+		nextToken();
+		break;
+	    case TOKpackage:
+		protection = PROTpackage;
+		nextToken();
+		break;
+	    case TOKprotected:
+		protection = PROTprotected;
+		nextToken();
+		break;
+	    case TOKpublic:
+		protection = PROTpublic;
+		nextToken();
+		break;
+	}
+	if (token.value == TOKidentifier)
+	{
+	    BaseClass *b = new BaseClass(parseBasicType(), protection);
+	    baseclasses->push(b);
+	    if (token.value != TOKcomma)
+		break;
+	}
+	else
+	{
+	    error("base classes expected instead of %s", token.toChars());
+	    return NULL;
+	}
+    }
+    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;
+    Expression *constraint = NULL;
+    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;
+
+    constraint = parseConstraint();
+
+    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, constraint, decldefs);
+    return tempdecl;
+
+Lerr:
+    return NULL;
+}
+
+/******************************************
+ * Parse template parameter list.
+ * Input:
+ *	flag	0: parsing "( list )"
+ *		1: parsing non-empty "list )"
+ */
+
+TemplateParameters *Parser::parseTemplateParameterList(int flag)
+{
+    TemplateParameters *tpl = new TemplateParameters();
+
+    if (!flag && token.value != TOKlparen)
+    {   error("parenthesized TemplateParameterList expected following TemplateIdentifier");
+	goto Lerr;
+    }
+    nextToken();
+
+    // Get array of TemplateParameters
+    if (flag || 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();
+		Type *spectype = NULL;
+		if (isDeclaration(&token, 2, TOKreserved, NULL))
+		{
+		    spectype = parseType(&tp_ident);
+		}
+		else
+		{
+		    if (token.value != TOKidentifier)
+		    {   error("identifier expected for template alias parameter");
+			goto Lerr;
+		    }
+		    tp_ident = token.ident;
+		    nextToken();
+		}
+		Object *spec = NULL;
+		if (token.value == TOKcolon)	// : Type
+		{
+		    nextToken();
+		    if (isDeclaration(&token, 0, TOKreserved, NULL))
+			spec = parseType();
+		    else
+			spec = parseCondExp();
+		}
+		Object *def = NULL;
+		if (token.value == TOKassign)	// = Type
+		{
+		    nextToken();
+		    if (isDeclaration(&token, 0, TOKreserved, NULL))
+			def = parseType();
+		    else
+			def = parseCondExp();
+		}
+		tp = new TemplateAliasParameter(loc, tp_ident, spectype, spec, def);
+	    }
+	    else if (t->value == TOKcolon || t->value == TOKassign ||
+		     t->value == TOKcomma || t->value == TOKrparen)
+	    {	// TypeParameter
+		if (token.value != TOKidentifier)
+		{   error("identifier expected for template type 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 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 = parseType(&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 = parseDefaultInitExp();
+		}
+		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)
+	{
+	    tqual = parseTypeof();
+	    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();
+	    if (token.value == TOKlparen)
+		tiargs = parseTemplateArgumentList();
+	    else
+		tiargs = parseTemplateArgument();
+	}
+
+	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");
+    if (token.value != TOKlparen && token.value != TOKlcurly)
+    {   error("!(TemplateArgumentList) expected following TemplateIdentifier");
+	return new Objects();
+    }
+    return parseTemplateArgumentList2();
+}
+
+Objects *Parser::parseTemplateArgumentList2()
+{
+    //printf("Parser::parseTemplateArgumentList2()\n");
+    Objects *tiargs = new Objects();
+    enum TOK endtok = TOKrparen;
+    nextToken();
+
+    // Get TemplateArgumentList
+    if (token.value != endtok)
+    {
+	while (1)
+	{
+	    // See if it is an Expression or a Type
+	    if (isDeclaration(&token, 0, TOKreserved, NULL))
+	    {	// Template argument is a type
+		Type *ta = parseType();
+		tiargs->push(ta);
+	    }
+	    else
+	    {	// Template argument is an expression
+		Expression *ea = parseAssignExp();
+
+		if (ea->op == TOKfunction)
+		{   FuncLiteralDeclaration *fd = ((FuncExp *)ea)->fd;
+		    if (fd->type->ty == Tfunction)
+		    {
+			TypeFunction *tf = (TypeFunction *)fd->type;
+			/* If there are parameters that consist of only an identifier,
+			 * rather than assuming the identifier is a type, as we would
+			 * for regular function declarations, assume the identifier
+			 * is the parameter name, and we're building a template with
+			 * a deduced type.
+			 */
+			TemplateParameters *tpl = NULL;
+			for (int i = 0; i < tf->parameters->dim; i++)
+			{   Argument *param = (Argument *)tf->parameters->data[i];
+			    if (param->ident == NULL &&
+				param->type &&
+				param->type->ty == Tident &&
+				((TypeIdentifier *)param->type)->idents.dim == 0
+			       )
+			    {
+				/* Switch parameter type to parameter identifier,
+				 * parameterize with template type parameter _T
+				 */
+				TypeIdentifier *pt = (TypeIdentifier *)param->type;
+				param->ident = pt->ident;
+				Identifier *id = Lexer::uniqueId("__T");
+				param->type = new TypeIdentifier(pt->loc, id);
+				TemplateParameter *tp = new TemplateTypeParameter(fd->loc, id, NULL, NULL);
+				if (!tpl)
+				    tpl = new TemplateParameters();
+				tpl->push(tp);
+			    }
+			}
+
+			if (tpl)
+			{   // Wrap a template around function fd
+			    Array *decldefs = new Array();
+			    decldefs->push(fd);
+			    TemplateDeclaration *tempdecl =
+				new TemplateDeclaration(fd->loc, fd->ident, tpl, NULL, decldefs);
+			    tempdecl->literal = 1;	// it's a template 'literal'
+			    tiargs->push(tempdecl);
+			    goto L1;
+			}
+		    }
+		}
+
+		tiargs->push(ea);
+	    }
+	 L1:
+	    if (token.value != TOKcomma)
+		break;
+	    nextToken();
+	}
+    }
+    check(endtok, "template argument list");
+    return tiargs;
+}
+
+/*****************************
+ * Parse single template argument, to support the syntax:
+ *	foo!arg
+ * Input:
+ *	current token is the arg
+ */
+
+Objects *Parser::parseTemplateArgument()
+{
+    //printf("parseTemplateArgument()\n");
+    Objects *tiargs = new Objects();
+    Type *ta;
+    switch (token.value)
+    {
+	case TOKidentifier:
+	    ta = new TypeIdentifier(loc, token.ident);
+	    goto LabelX;
+
+	CASE_BASIC_TYPES_X(ta):
+	    tiargs->push(ta);
+	    nextToken();
+	    break;
+
+	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:
+	case TOKfile:
+	case TOKline:
+	{   // Template argument is an expression
+	    Expression *ea = parsePrimaryExp();
+	    tiargs->push(ea);
+	    break;
+	}
+
+	default:
+	    error("template argument expected following !");
+	    break;
+    }
+    if (token.value == TOKnot)
+	error("multiple ! arguments are not allowed");
+    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;
+
+		nextToken();
+		if (token.value != TOKidentifier)
+		{   error("Identifier expected following :");
+		    break;
+		}
+		Identifier *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;
+
+    //printf("parseBasicType()\n");
+    switch (token.value)
+    {
+	CASE_BASIC_TYPES_X(t):
+	    nextToken();
+	    break;
+
+	case TOKidentifier:
+	    id = token.ident;
+	    nextToken();
+	    if (token.value == TOKnot)
+	    {	// ident!(template_arguments)
+		TemplateInstance *tempinst = new TemplateInstance(loc, id);
+		nextToken();
+		if (token.value == TOKlparen)
+		    // ident!(template_arguments)
+		    tempinst->tiargs = parseTemplateArgumentList();
+		else
+		    // ident!template_argument
+		    tempinst->tiargs = parseTemplateArgument();
+		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)
+		{
+		    TemplateInstance *tempinst = new TemplateInstance(loc, id);
+		    nextToken();
+		    if (token.value == TOKlparen)
+			// ident!(template_arguments)
+			tempinst->tiargs = parseTemplateArgumentList();
+		    else
+			// ident!template_argument
+			tempinst->tiargs = parseTemplateArgument();
+		    tid->addIdent((Identifier *)tempinst);
+		}
+		else
+		    tid->addIdent(id);
+	    }
+	    t = tid;
+	    break;
+
+	case TOKdot:
+	    // Leading . as in .foo
+	    id = Id::empty;
+	    goto Lident;
+
+	case TOKtypeof:
+	    // typeof(expression)
+	    tid = parseTypeof();
+	    goto Lident2;
+
+	case TOKconst:
+	    // const(type)
+	    nextToken();
+	    check(TOKlparen);
+	    t = parseType();
+	    check(TOKrparen);
+	    if (t->isShared())
+		t = t->makeSharedConst();
+	    else
+		t = t->makeConst();
+	    break;
+
+	case TOKinvariant:
+	case TOKimmutable:
+	    // invariant(type)
+	    nextToken();
+	    check(TOKlparen);
+	    t = parseType();
+	    check(TOKrparen);
+	    t = t->makeInvariant();
+	    break;
+
+	case TOKshared:
+	    // shared(type)
+	    nextToken();
+	    check(TOKlparen);
+	    t = parseType();
+	    check(TOKrparen);
+	    if (t->isConst())
+		t = t->makeSharedConst();
+	    else
+		t = t->makeShared();
+	    break;
+
+	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)
+{
+    //printf("parseBasicType2()\n");
+    while (1)
+    {
+	switch (token.value)
+	{
+	    case TOKmul:
+		t = new TypePointer(t);
+		nextToken();
+		continue;
+
+	    case TOKlbracket:
+		// 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
+
+		    //printf("it's an associative array\n");
+		    Type *index = parseType();		// [ type ]
+		    t = new TypeAArray(t, index);
+		    check(TOKrbracket);
+		}
+		else
+		{
+		    //printf("it's type[expression]\n");
+		    inBrackets++;
+		    Expression *e = parseExpression();		// [ expression ]
+		    if (token.value == TOKslice)
+		    {
+			nextToken();
+			Expression *e2 = parseExpression();	// [ exp .. exp ]
+			t = new TypeSlice(t, e, e2);
+		    }
+		    else
+			t = new TypeSArray(t,e);
+		    inBrackets--;
+		    check(TOKrbracket);
+		}
+		continue;
+
+	    case TOKdelegate:
+	    case TOKfunction:
+	    {	// Handle delegate declaration:
+		//	t delegate(parameter list) nothrow pure
+		//	t function(parameter list) nothrow pure
+		Arguments *arguments;
+		int varargs;
+		bool ispure = false;
+		bool isnothrow = false;
+		enum TOK save = token.value;
+
+		nextToken();
+		arguments = parseParameters(&varargs);
+		while (1)
+		{   // Postfixes of 'pure' or 'nothrow'
+		    if (token.value == TOKpure)
+			ispure = true;
+		    else if (token.value == TOKnothrow)
+			isnothrow = true;
+		    else
+			break;
+		    nextToken();
+		}
+		TypeFunction *tf = new TypeFunction(arguments, t, varargs, linkage);
+		tf->ispure = ispure;
+		tf->isnothrow = isnothrow;
+		if (save == TOKdelegate)
+		    t = new TypeDelegate(tf);
+		else
+		    t = new TypePointer(tf);	// pointer to function
+		continue;
+	    }
+
+	    default:
+		return t;
+	}
+	assert(0);
+    }
+    assert(0);
+    return NULL;
+}
+
+Type *Parser::parseDeclarator(Type *t, Identifier **pident, TemplateParameters **tpl)
+{   Type *ts;
+
+    //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.
+		TypeNext *ta;
+		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
+
+		    //printf("it's an associative array\n");
+		    Type *index = parseType();		// [ type ]
+		    check(TOKrbracket);
+		    ta = new TypeAArray(t, index);
+		}
+		else
+		{
+		    //printf("It's a static array\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 = &((TypeNext*)*pt)->next)
+		    ;
+		*pt = ta;
+		continue;
+	    }
+#endif
+	    case TOKlparen:
+	    {
+		if (tpl)
+		{
+		    /* Look ahead to see if this is (...)(...),
+		     * i.e. a function template declaration
+		     */
+		    if (peekPastParen(&token)->value == TOKlparen)
+		    {
+			//printf("function template declaration\n");
+
+			// Gather template parameter list
+			*tpl = parseTemplateParameterList();
+		    }
+		}
+
+		int varargs;
+		Arguments *arguments = parseParameters(&varargs);
+		Type *tf = new TypeFunction(arguments, t, varargs, linkage);
+
+		/* Parse const/invariant/nothrow/pure postfix
+		 */
+		while (1)
+		{
+		    switch (token.value)
+		    {
+			case TOKconst:
+			    if (tf->isShared())
+				tf = tf->makeSharedConst();
+			    else
+				tf = tf->makeConst();
+			    nextToken();
+			    continue;
+
+			case TOKinvariant:
+			case TOKimmutable:
+			    tf = tf->makeInvariant();
+			    nextToken();
+			    continue;
+
+			case TOKshared:
+			    if (tf->isConst())
+				tf = tf->makeSharedConst();
+			    else
+				tf = tf->makeShared();
+			    nextToken();
+			    continue;
+
+			case TOKnothrow:
+			    ((TypeFunction *)tf)->isnothrow = 1;
+			    nextToken();
+			    continue;
+
+			case TOKpure:
+			    ((TypeFunction *)tf)->ispure = 1;
+			    nextToken();
+			    continue;
+		    }
+		    break;
+		}
+
+		/* Insert tf into
+		 *   ts -> ... -> t
+		 * so that
+		 *   ts -> ... -> tf -> t
+		 */
+		Type **pt;
+		for (pt = &ts; *pt != t; pt = &((TypeNext*)*pt)->next)
+		    ;
+		*pt = tf;
+		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(unsigned 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() %s\n", token.toChars());
+    if (storage_class)
+    {	ts = NULL;		// infer type
+	goto L2;
+    }
+
+    switch (token.value)
+    {
+	case TOKalias:
+	    /* Look for:
+	     *   alias identifier this;
+	     */
+	    tok = token.value;
+	    nextToken();
+	    if (token.value == TOKidentifier && peek(&token)->value == TOKthis)
+	    {
+		AliasThis *s = new AliasThis(this->loc, token.ident);
+		nextToken();
+		check(TOKthis);
+		check(TOKsemicolon);
+		a = new Array();
+		a->push(s);
+		addComment(s, comment);
+		return a;
+	    }
+	    break;
+	case TOKtypedef:
+	    tok = token.value;
+	    nextToken();
+	    break;
+    }
+
+    storage_class = STCundefined;
+    while (1)
+    {
+	switch (token.value)
+	{
+	    case TOKconst:
+		if (peek(&token)->value == TOKlparen)
+		    break;		// const as type constructor
+		stc = STCconst;		// const as storage class
+		goto L1;
+
+	    case TOKinvariant:
+	    case TOKimmutable:
+		if (peek(&token)->value == TOKlparen)
+		    break;
+		stc = STCimmutable;
+		goto L1;
+
+	    case TOKshared:
+		if (peek(&token)->value == TOKlparen)
+		    break;
+		stc = STCshared;
+		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 TOKgshared:    stc = STCgshared;	 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);
+		composeStorageClass(storage_class);
+		nextToken();
+		continue;
+
+	    case TOKextern:
+		if (peek(&token)->value != TOKlparen)
+		{   stc = STCextern;
+		    goto L1;
+		}
+
+		link = parseLinkage();
+		continue;
+
+	    default:
+		break;
+	}
+	break;
+    }
+
+    /* Look for auto initializers:
+     *	storage_class identifier = initializer;
+     */
+    if (storage_class &&
+	token.value == TOKidentifier &&
+	peek(&token)->value == TOKassign)
+    {
+	return parseAutoDeclarations(storage_class, comment);
+    }
+
+    if (token.value == TOKclass)
+    {
+	AggregateDeclaration *s = (AggregateDeclaration *)parseAggregate();
+	s->storage_class |= storage_class;
+	a = new Array();
+	a->push(s);
+	addComment(s, comment);
+	return a;
+    }
+
+    /* Look for return type inference for template functions.
+     */
+    {
+    Token *tk;
+    if (storage_class &&
+	token.value == TOKidentifier &&
+	(tk = peek(&token))->value == TOKlparen &&
+	skipParens(tk, &tk) &&
+	peek(tk)->value == TOKlparen)
+    {
+	ts = NULL;
+    }
+    else
+    {
+	ts = parseBasicType();
+	ts = parseBasicType2(ts);
+    }
+    }
+
+L2:
+    tfirst = NULL;
+    a = new Array();
+
+    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)
+	{
+	    TypeFunction *tf = (TypeFunction *)t;
+	    Expression *constraint = NULL;
+#if 0
+	    if (Argument::isTPL(tf->parameters))
+	    {
+		if (!tpl)
+		    tpl = new TemplateParameters();
+	    }
+#endif
+	    FuncDeclaration *f =
+		new FuncDeclaration(loc, 0, ident, (enum STC)storage_class, t);
+	    addComment(f, comment);
+	    if (tpl)
+		constraint = parseConstraint();
+	    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);
+	    }
+	    /* A template parameter list means it's a function template
+	     */
+	    if (tpl)
+	    {
+		// Wrap a template around the function declaration
+		Array *decldefs = new Array();
+		decldefs->push(s);
+		TemplateDeclaration *tempdecl =
+		    new TemplateDeclaration(loc, s->ident, tpl, constraint, 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 ';' ',' or '}', 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:
+	case TOKnothrow:
+	case TOKpure:
+	case TOKtls:
+	case TOKgshared:
+#endif
+//	case TOKtypeof:
+	Ldeclaration:
+	{   Array *a;
+
+	    a = parseDeclarations(STCundefined);
+	    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:
+	{   /* Determine if this is a manifest constant declaration,
+	     * or a conventional enum.
+	     */
+	    Dsymbol *d;
+	    Token *t = peek(&token);
+	    if (t->value == TOKlcurly || t->value == TOKcolon)
+		d = parseEnum();
+	    else if (t->value != TOKidentifier)
+		goto Ldeclaration;
+	    else
+	    {
+		t = peek(t);
+		if (t->value == TOKlcurly || t->value == TOKcolon ||
+		    t->value == TOKsemicolon)
+		    d = parseEnum();
+		else
+		    goto Ldeclaration;
+	    }
+	    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 = 0;
+		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;
+		    }
+		}
+		at = parseType(&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();
+	    if (token.value == TOKslice && arguments->dim == 1)
+	    {
+		Argument *a = (Argument *)arguments->data[0];
+		delete arguments;
+		nextToken();
+		Expression *upr = parseExpression();
+		check(TOKrparen);
+		body = parseStatement(0);
+		s = new ForeachRangeStatement(loc, op, a, aggr, upr, body);
+	    }
+	    else
+	    {
+		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(0, 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 *at;
+		Identifier *ai;
+
+		at = parseType(&ai);
+		check(TOKassign);
+		arg = new Argument(0, 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(0, 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);
+		    id = NULL;
+		    t = parseType(&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 ||
+	 t->value == TOKimmutable ||
+	 t->value == TOKshared) &&
+	peek(t)->value != TOKlparen)
+    {	/* const type
+	 * immutable type
+	 * shared type
+	 */
+	t = peek(t);
+    }
+#endif
+
+    if (!isBasicType(&t))
+    {
+	goto Lisnot;
+    }
+    if (!isDeclarator(&t, &haveId, endtok))
+	goto Lisnot;
+    if ( needId == 1 ||
+	(needId == 0 && !haveId) ||
+	(needId == 2 &&  haveId))
+    {	if (pt)
+	    *pt = t;
+	goto Lis;
+    }
+    else
+	goto Lisnot;
+
+Lis:
+    //printf("\tis declaration\n");
+    return TRUE;
+
+Lisnot:
+    //printf("\tis not declaration\n");
+    return FALSE;
+}
+
+int Parser::isBasicType(Token **pt)
+{
+    // This code parallels parseBasicType()
+    Token *t = *pt;
+    Token *t2;
+    int parens;
+    int haveId = 0;
+
+    switch (t->value)
+    {
+	CASE_BASIC_TYPES:
+	    t = peek(t);
+	    break;
+
+	case TOKidentifier:
+	L5:
+	    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:
+		    /* Seen a !
+		     * Look for:
+		     * !( args ), !identifier, etc.
+		     */
+		    t = peek(t);
+		    switch (t->value)
+		    {	case TOKidentifier:
+			    goto L5;
+			case TOKlparen:
+			    if (!skipParens(t, &t))
+				goto Lfalse;
+			    break;
+			CASE_BASIC_TYPES:
+			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:
+			case TOKfile:
+			case TOKline:
+			    goto L2;
+			default:
+			    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;
+
+	case TOKconst:
+	case TOKinvariant:
+	case TOKimmutable:
+	case TOKshared:
+	    // const(type)  or  immutable(type)  or  shared(type)
+	    t = peek(t);
+	    if (t->value != TOKlparen)
+		goto Lfalse;
+	    t = peek(t);
+	    if (!isDeclaration(t, 0, TOKrparen, &t))
+	    {
+		goto Lfalse;
+	    }
+	    t = peek(t);
+	    break;
+
+	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);
+    for (;1; t = peek(t))
+    {
+	switch (t->value)
+	{
+	    case TOKrparen:
+		break;
+
+	    case TOKdotdotdot:
+		t = peek(t);
+		break;
+
+	    case TOKin:
+	    case TOKout:
+	    case TOKinout:
+	    case TOKref:
+	    case TOKlazy:
+	    case TOKconst:
+	    case TOKinvariant:
+	    case TOKimmutable:
+	    case TOKshared:
+	    case TOKfinal:
+		continue;
+
+#if 0
+	    case TOKstatic:
+		continue;
+	    case TOKauto:
+	    case TOKalias:
+		t = peek(t);
+		if (t->value == TOKidentifier)
+		    t = peek(t);
+		if (t->value == TOKassign)
+		{   t = peek(t);
+		    if (!isExpression(&t))
+			return FALSE;
+		}
+		goto L3;
+#endif
+
+	    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;
+		}
+	    L3:
+		if (t->value == TOKcomma)
+		{
+		    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;
+    int curlynest = 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 TOKlcurly:
+		curlynest++;
+		continue;
+
+	    case TOKrcurly:
+		if (--curlynest >= 0)
+		    continue;
+		return FALSE;
+
+	    case TOKslice:
+		if (brnest)
+		    continue;
+		break;
+
+	    case TOKsemicolon:
+		if (curlynest)
+		    continue;
+		return FALSE;
+
+	    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 && peekNext() != TOKis)
+	    {	// identifier!(template-argument-list)
+		TemplateInstance *tempinst;
+
+		tempinst = new TemplateInstance(loc, id);
+		nextToken();
+		if (token.value == TOKlparen)
+		    // ident!(template_arguments)
+		    tempinst->tiargs = parseTemplateArgumentList();
+		else
+		    // ident!template_argument
+		    tempinst->tiargs = parseTemplateArgument();
+		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:
+	{   const char *s = loc.filename ? loc.filename : mod->ident->toChars();
+	    e = new StringExp(loc, (char *)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:
+	{
+	    t = parseTypeof();
+	    e = new TypeExp(loc, t);
+	    break;
+	}
+
+	case TOKtypeid:
+	{   Type *t;
+
+	    nextToken();
+	    check(TOKlparen, "typeid");
+	    t = parseType();		// ( 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;
+	    TemplateParameters *tpl = NULL;
+	    Loc loc = this->loc;
+
+	    nextToken();
+	    if (token.value == TOKlparen)
+	    {
+		nextToken();
+		targ = parseType(&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 = parseType();
+		    }
+		}
+		if (ident && tspec)
+		{
+		    if (token.value == TOKcomma)
+			tpl = parseTemplateParameterList(1);
+		    else
+		    {	tpl = new TemplateParameters();
+			check(TOKrparen);
+		    }
+		    TemplateParameter *tp = new TemplateTypeParameter(loc, ident, NULL, NULL);
+		    tpl->insert(0, tp);
+		}
+		else
+		    check(TOKrparen);
+	    }
+	    else
+	    {   error("(type identifier : specialization) expected following is");
+		goto Lerr;
+	    }
+	    e = new IsExp(loc, targ, ident, tok, tspec, tok2, tpl);
+	    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 } pure nothrow
+	     * delegate type(parameters) { body } pure nothrow
+	     * (parameters) { body }
+	     * { body }
+	     */
+	    Arguments *arguments;
+	    int varargs;
+	    FuncLiteralDeclaration *fd;
+	    Type *t;
+	    bool isnothrow = false;
+	    bool ispure = false;
+
+	    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);
+		while (1)
+		{
+		    if (token.value == TOKpure)
+			ispure = true;
+		    else if (token.value == TOKnothrow)
+			isnothrow = true;
+		    else
+			break;
+		    nextToken();
+		}
+	    }
+
+	    TypeFunction *tf = new TypeFunction(arguments, t, varargs, linkage);
+	    tf->ispure = ispure;
+	    tf->isnothrow = isnothrow;
+	    fd = new FuncLiteralDeclaration(loc, 0, tf, 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 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 && peekNext() != TOKis)
+		    {   // identifier!(template-argument-list)
+			TemplateInstance *tempinst = new TemplateInstance(loc, id);
+			nextToken();
+			if (token.value == TOKlparen)
+			    // ident!(template_arguments)
+			    tempinst->tiargs = parseTemplateArgumentList();
+			else
+			    // ident!template_argument
+			    tempinst->tiargs = parseTemplateArgument();
+			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
+	{
+	    nextToken();
+	    check(TOKlparen);
+	    /* Look for cast(), cast(const), cast(immutable),
+	     * cast(shared), cast(shared const)
+	     */
+	    unsigned m;
+	    if (token.value == TOKrparen)
+	    {
+		m = 0;
+		goto Lmod1;
+	    }
+	    else if (token.value == TOKconst && peekNext() == TOKrparen)
+	    {
+		m = MODconst;
+		goto Lmod2;
+	    }
+	    else if ((token.value == TOKimmutable || token.value == TOKinvariant) && peekNext() == TOKrparen)
+	    {
+		m = MODinvariant;
+		goto Lmod2;
+	    }
+	    else if (token.value == TOKshared && peekNext() == TOKrparen)
+	    {
+		m = MODshared;
+		goto Lmod2;
+	    }
+	    else if (token.value == TOKconst && peekNext() == TOKshared && peekNext2() == TOKrparen ||
+		     token.value == TOKshared && peekNext() == TOKconst && peekNext2() == TOKrparen)
+	    {
+		m = MODshared | MODconst;
+		nextToken();
+	      Lmod2:
+		nextToken();
+	      Lmod1:
+		nextToken();
+		e = parseUnaryExp();
+		e = new CastExp(loc, e, m);
+	    }
+	    else
+	    {
+		Type *t = parseType();		// ( 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 = parseType();
+			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();
+	    e = parsePostExp(e);
+	    break;
+	}
+	default:
+	    e = parsePrimaryExp();
+	    e = parsePostExp(e);
+	    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;
+    }
+
+    t = parseBasicType();
+    t = parseBasicType2(t);
+    if (t->ty == Taarray)
+    {	TypeAArray *taa = (TypeAArray *)t;
+	Type *index = taa->index;
+
+	Expression *e = index->toExpression();
+	if (e)
+	{   arguments = new Expressions();
+	    arguments->push(e);
+	    t = new TypeDArray(taa->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(tsa->next);
+    }
+    else if (token.value == TOKlparen)
+    {
+	arguments = parseArguments();
+    }
+    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/dmd2/parse.h	Mon Jun 01 01:28:18 2009 +0200
+++ b/dmd2/parse.h	Mon Jun 01 19:02:20 2009 +0100
@@ -1,6 +1,6 @@
 
 // Compiler implementation of the D programming language
-// Copyright (c) 1999-2008 by Digital Mars
+// Copyright (c) 1999-2009 by Digital Mars
 // All Rights Reserved
 // written by Walter Bright
 // http://www.digitalmars.com
@@ -70,6 +70,7 @@
     Array *parseDeclDefs(int once);
     Array *parseAutoDeclarations(unsigned storageClass, unsigned char *comment);
     Array *parseBlock();
+    void composeStorageClass(unsigned stc);
     Expression *parseConstraint();
     TemplateDeclaration *parseTemplateDeclaration();
     TemplateParameters *parseTemplateParameterList(int flag = 0);
@@ -83,7 +84,7 @@
     Condition *parseDebugCondition();
     Condition *parseVersionCondition();
     Condition *parseStaticIfCondition();
-    FuncDeclaration *parseCtor();
+    Dsymbol *parseCtor();
     PostBlitDeclaration *parsePostBlit();
     DtorDeclaration *parseDtor();
     StaticCtorDeclaration *parseStaticCtor();
--- a/dmd2/port.h	Mon Jun 01 01:28:18 2009 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,65 +0,0 @@
-
-// Copyright (c) 1999-2002 by Digital Mars
-// All Rights Reserved
-// written by Walter Bright
-// www.digitalmars.com
-
-#ifndef PORT_H
-#define PORT_H
-
-// Portable wrapper around compiler/system specific things.
-// The idea is to minimize #ifdef's in the app code.
-
-#ifndef TYPEDEFS
-#define TYPEDEFS
-
-#include <wchar.h>
-
-#if _MSC_VER
-typedef __int64 longlong;
-typedef unsigned __int64 ulonglong;
-#else
-typedef long long longlong;
-typedef unsigned long long ulonglong;
-#endif
-
-#endif
-
-typedef double d_time;
-
-struct Port
-{
-    static double nan;
-    static double infinity;
-    static double dbl_max;
-    static double dbl_min;
-
-#if __GNUC__
-    // These conflict with macros in math.h, should rename them
-    #undef isnan
-    #undef isfinite
-    #undef isinfinity
-    #undef signbit
-#endif
-    static int isNan(double);
-    static int isFinite(double);
-    static int isInfinity(double);
-    static int Signbit(double);
-
-    static double floor(double);
-    static double pow(double x, double y);
-
-    static ulonglong strtoull(const char *p, char **pend, int base);
-
-    static char *ull_to_string(char *buffer, ulonglong ull);
-    static wchar_t *ull_to_string(wchar_t *buffer, ulonglong ull);
-
-    // Convert ulonglong to double
-    static double ull_to_double(ulonglong ull);
-
-    // Get locale-dependent list separator
-    static char *list_separator();
-    static wchar_t *wlist_separator();
-};
-
-#endif
--- a/dmd2/readme.txt	Mon Jun 01 01:28:18 2009 +0200
+++ b/dmd2/readme.txt	Mon Jun 01 19:02:20 2009 +0100
@@ -1,26 +1,23 @@
 
 		The D Programming Language
 		Compiler Front End Source
-		Copyright (c) 1999-2002, by Digital Mars
-		www.digitalmars.com
+		Copyright (c) 1999-2009, by Digital Mars
+		http://www.digitalmars.com
 		All Rights Reserved
 
 
 This is the source code to the front end Digital Mars D compiler.
 It covers the lexical analysis, parsing, and semantic analysis
 of the D Programming Language defined in the documents at
-www.digitalmars.com/d/
-
-The optimizer, code generator, and object file generator are not part
-of this source, hence the source does not currently constitute a complete,
-compilable program. However, many people have expressed a strong interested
-in producing a D compiler with the GNU compiler sources. This release should
-enable that.
+http://www.digitalmars.com/d/
 
 These sources are free, they are redistributable and modifiable
 under the terms of the GNU General Public License (attached as gpl.txt),
 or the Artistic License (attached as artistic.txt).
 
+The optimizer and code generator sources are 
+covered under a separate license, backendlicense.txt.
+
 It does not apply to anything else distributed by Digital Mars,
 including D compiler executables.
 
--- a/dmd2/root.c	Mon Jun 01 01:28:18 2009 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1903 +0,0 @@
-
-// Copyright (c) 1999-2006 by Digital Mars
-// All Rights Reserved
-// written by Walter Bright
-// 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 <stdlib.h>
-#include <stdarg.h>
-#include <string.h>
-#include <stdint.h>
-#include <assert.h>
-
-#if _MSC_VER ||__MINGW32__
-#include <malloc.h>
-#include <string>
-#endif
-
-#if _WIN32
-#include <windows.h>
-#include <direct.h>
-#endif
-
-#if POSIX
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <unistd.h>
-#include <utime.h>
-#endif
-
-#include "port.h"
-#include "root.h"
-#include "dchar.h"
-#include "mem.h"
-#include "mars.h"
-
-#if 0 //__SC__ //def DEBUG
-extern "C" void __cdecl _assert(void *e, void *f, unsigned line)
-{
-    printf("Assert('%s','%s',%d)\n",e,f,line);
-    fflush(stdout);
-    *(char *)0 = 0;
-}
-#endif
-
-
-/*************************************
- * Convert wchar string to ascii string.
- */
-
-char *wchar2ascii(wchar_t *us)
-{
-    return wchar2ascii(us, wcslen(us));
-}
-
-char *wchar2ascii(wchar_t *us, unsigned len)
-{
-    unsigned i;
-    char *p;
-
-    p = (char *)mem.malloc(len + 1);
-    for (i = 0; i <= len; i++)
-	p[i] = (char) us[i];
-    return p;
-}
-
-int wcharIsAscii(wchar_t *us)
-{
-    return wcharIsAscii(us, wcslen(us));
-}
-
-int wcharIsAscii(wchar_t *us, unsigned len)
-{
-    unsigned i;
-
-    for (i = 0; i <= len; i++)
-    {
-	if (us[i] & ~0xFF)	// if high bits set
-	    return 0;		// it's not ascii
-    }
-    return 1;
-}
-
-
-/***********************************
- * Compare length-prefixed strings (bstr).
- */
-
-int bstrcmp(unsigned char *b1, unsigned char *b2)
-{
-    return (*b1 == *b2 && memcmp(b1 + 1, b2 + 1, *b2) == 0) ? 0 : 1;
-}
-
-/***************************************
- * Convert bstr into a malloc'd string.
- */
-
-char *bstr2str(unsigned char *b)
-{
-    char *s;
-    unsigned len;
-
-    len = *b;
-    s = (char *) mem.malloc(len + 1);
-    s[len] = 0;
-    return (char *)memcpy(s,b + 1,len);
-}
-
-/**************************************
- * Print error message and exit.
- */
-
-void error(const char *format, ...)
-{
-    va_list ap;
-
-    va_start(ap, format);
-    printf("Error: ");
-    vprintf(format, ap);
-    va_end( ap );
-    printf("\n");
-    fflush(stdout);
-
-    exit(EXIT_FAILURE);
-}
-
-#if M_UNICODE
-void error(const dchar *format, ...)
-{
-    va_list ap;
-
-    va_start(ap, format);
-    printf("Error: ");
-    vwprintf(format, ap);
-    va_end( ap );
-    printf("\n");
-    fflush(stdout);
-
-    exit(EXIT_FAILURE);
-}
-#endif
-
-void error_mem()
-{
-    error("out of memory");
-}
-
-/**************************************
- * Print warning message.
- */
-
-void warning(const char *format, ...)
-{
-    va_list ap;
-
-    va_start(ap, format);
-    printf("Warning: ");
-    vprintf(format, ap);
-    va_end( ap );
-    printf("\n");
-    fflush(stdout);
-}
-
-/****************************** Object ********************************/
-
-int Object::equals(Object *o)
-{
-    return o == this;
-}
-
-hash_t Object::hashCode()
-{
-    return (hash_t) this;
-}
-
-int Object::compare(Object *obj)
-{
-    return this - obj;
-}
-
-void Object::print()
-{
-    printf("%s %p\n", toChars(), this);
-}
-
-char *Object::toChars()
-{
-    return (char *)"Object";
-}
-
-dchar *Object::toDchars()
-{
-#if M_UNICODE
-    return L"Object";
-#else
-    return toChars();
-#endif
-}
-
-int Object::dyncast()
-{
-    return 0;
-}
-
-void Object::toBuffer(OutBuffer *b)
-{
-    b->writestring("Object");
-}
-
-void Object::mark()
-{
-}
-
-/****************************** String ********************************/
-
-String::String(char *str, int ref)
-{
-    this->str = ref ? str : mem.strdup(str);
-    this->ref = ref;
-}
-
-String::~String()
-{
-    mem.free(str);
-}
-
-void String::mark()
-{
-    mem.mark(str);
-}
-
-hash_t String::calcHash(const char *str, size_t len)
-{
-    hash_t hash = 0;
-
-    for (;;)
-    {
-	switch (len)
-	{
-	    case 0:
-		return hash;
-
-	    case 1:
-		hash *= 37;
-		hash += *(uint8_t *)str;
-		return hash;
-
-	    case 2:
-		hash *= 37;
-		hash += *(uint16_t *)str;
-		return hash;
-
-	    case 3:
-		hash *= 37;
-		hash += (*(uint16_t *)str << 8) +
-			((uint8_t *)str)[2];
-		return hash;
-
-	    default:
-		hash *= 37;
-		hash += *(uint32_t *)str;
-		str += 4;
-		len -= 4;
-		break;
-	}
-    }
-}
-
-hash_t String::calcHash(const char *str)
-{
-    return calcHash(str, strlen(str));
-}
-
-hash_t String::hashCode()
-{
-    return calcHash(str, strlen(str));
-}
-
-unsigned String::len()
-{
-    return strlen(str);
-}
-
-int String::equals(Object *obj)
-{
-    return strcmp(str,((String *)obj)->str) == 0;
-}
-
-int String::compare(Object *obj)
-{
-    return strcmp(str,((String *)obj)->str);
-}
-
-char *String::toChars()
-{
-    return str;
-}
-
-void String::print()
-{
-    printf("String '%s'\n",str);
-}
-
-
-/****************************** FileName ********************************/
-
-FileName::FileName(char *str, int ref)
-    : String(str,ref)
-{
-}
-
-char *FileName::combine(const char *path, const char *name)
-{   char *f;
-    size_t pathlen;
-    size_t namelen;
-
-    if (!path || !*path)
-	return (char *)name;
-    pathlen = strlen(path);
-    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
-    )
-    {	f[pathlen] = '/';
-	pathlen++;
-    }
-
-    memcpy(f + pathlen, name, namelen + 1);
-    return f;
-}
-
-FileName::FileName(char *path, char *name)
-    : String(combine(path,name),1)
-{
-}
-
-// Split a path into an Array of paths
-Array *FileName::splitPath(const char *path)
-{
-    char c = 0;				// unnecessary initializer is for VC /W4
-    const char *p;
-    OutBuffer buf;
-    Array *array;
-
-    array = new Array();
-    if (path)
-    {
-	p = path;
-	do
-	{   char instring = 0;
-
-	    while (isspace(*p))		// skip leading whitespace
-		p++;
-	    buf.reserve(strlen(p) + 1);	// guess size of path
-	    for (; ; p++)
-	    {
-		c = *p;
-		switch (c)
-		{
-		    case '"':
-			instring ^= 1;	// toggle inside/outside of string
-			continue;
-
-#if _WIN32
-		    case ';':
-#endif
-#if POSIX
-		    case ':':
-#endif
-			p++;
-			break;		// note that ; cannot appear as part
-					// of a path, quotes won't protect it
-
-		    case 0x1A:		// ^Z means end of file
-		    case 0:
-			break;
-
-		    case '\r':
-			continue;	// ignore carriage returns
-
-#if POSIX
-		    case '~':
-			buf.writestring(getenv("HOME"));
-			continue;
-#endif
-
-		    case ' ':
-		    case '\t':		// tabs in filenames?
-			if (!instring)	// if not in string
-			    break;	// treat as end of path
-		    default:
-			buf.writeByte(c);
-			continue;
-		}
-		break;
-	    }
-	    if (buf.offset)		// if path is not empty
-	    {
-		buf.writeByte(0);	// to asciiz
-		array->push(buf.extractData());
-	    }
-	} while (c);
-    }
-    return array;
-}
-
-hash_t FileName::hashCode()
-{
-#if _WIN32
-    // We need a different hashCode because it must be case-insensitive
-    size_t len = strlen(str);
-    hash_t hash = 0;
-    unsigned char *s = (unsigned char *)str;
-
-    for (;;)
-    {
-	switch (len)
-	{
-	    case 0:
-		return hash;
-
-	    case 1:
-		hash *= 37;
-		hash += *(uint8_t *)s | 0x20;
-		return hash;
-
-	    case 2:
-		hash *= 37;
-		hash += *(uint16_t *)s | 0x2020;
-		return hash;
-
-	    case 3:
-		hash *= 37;
-		hash += ((*(uint16_t *)s << 8) +
-			 ((uint8_t *)s)[2]) | 0x202020;
-		break;
-
-	    default:
-		hash *= 37;
-		hash += *(uint32_t *)s | 0x20202020;
-		s += 4;
-		len -= 4;
-		break;
-	}
-    }
-#else
-    // darwin HFS is case insensitive, though...
-    return String::hashCode();
-#endif
-}
-
-int FileName::compare(Object *obj)
-{
-#if _WIN32
-    return stricmp(str,((FileName *)obj)->str);
-#else
-    return String::compare(obj);
-#endif
-}
-
-int FileName::equals(Object *obj)
-{
-#if _WIN32
-    return stricmp(str,((FileName *)obj)->str) == 0;
-#else
-    return String::equals(obj);
-#endif
-}
-
-/************************************
- * Return !=0 if absolute path name.
- */
-
-int FileName::absolute(const char *name)
-{
-    return
-#if _WIN32
-	(*name == '\\') ||
-	(*name == '/')  ||
-	(*name && name[1] == ':') ||
-#endif
-	(*name == '/');
-}
-
-/********************************
- * Return filename extension (read-only).
- * Points past '.' of extension.
- * If there isn't one, return NULL.
- */
-
-char *FileName::ext(const char *str)
-{
-    char *e;
-    size_t len = strlen(str);
-
-    e = (char *)str + len;
-    for (;;)
-    {
-	switch (*e)
-	{   case '.':
-		return e + 1;
-
-	    case '/':
-	        break;
-
-#if _WIN32
-	    case '\\':
-	    case ':':
-		break;
-#endif
-	    default:
-		if (e == str)
-		    break;
-		e--;
-		continue;
-	}
-	return NULL;
-    }
-}
-
-char *FileName::ext()
-{
-    return ext(str);
-}
-
-/********************************
- * Return mem.malloc'd filename with extension removed.
- */
-
-char *FileName::removeExt(const char *str)
-{
-    const char *e = ext(str);
-    if (e)
-    {	size_t len = (e - str) - 1;
-	char *n = (char *)mem.malloc(len + 1);
-	memcpy(n, str, len);
-	n[len] = 0;
-	return n;
-    }
-    return mem.strdup(str);
-}
-
-/********************************
- * Return filename name excluding path (read-only).
- */
-
-char *FileName::name(const char *str)
-{
-    char *e;
-    size_t len = strlen(str);
-
-    e = (char *)str + len;
-    for (;;)
-    {
-	switch (*e)
-	{
-
-	    case '/':
-	       return e + 1;
-
-#if _WIN32
-	    case '\\':
-	    case ':':
-		return e + 1;
-#endif
-	    default:
-		if (e == str)
-		    break;
-		e--;
-		continue;
-	}
-	return e;
-    }
-}
-
-char *FileName::name()
-{
-    return name(str);
-}
-
-/**************************************
- * Return path portion of str.
- * Path will does not include trailing path separator.
- */
-
-char *FileName::path(const char *str)
-{
-    char *n = name(str);
-    char *path;
-    size_t pathlen;
-
-    if (n > str)
-    {
-
-	if (n[-1] == '/')
-	    n--;
-
-#if _WIN32
-	if (n[-1] == '\\')
-	    n--;
-#endif
-    }
-    pathlen = n - str;
-    path = (char *)mem.malloc(pathlen + 1);
-    memcpy(path, str, pathlen);
-    path[pathlen] = 0;
-    return path;
-}
-
-/**************************************
- * Replace filename portion of path.
- */
-
-char *FileName::replaceName(char *path, char *name)
-{   char *f;
-    char *n;
-    size_t pathlen;
-    size_t namelen;
-
-    if (absolute(name))
-	return name;
-
-    n = FileName::name(path);
-    if (n == path)
-	return name;
-    pathlen = n - path;
-    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
-	)
-    {	f[pathlen] = '/';
-	pathlen++;
-    }
-
-    memcpy(f + pathlen, name, namelen + 1);
-    return f;
-}
-
-/***************************
- */
-
-FileName *FileName::defaultExt(const char *name, const char *ext)
-{
-    char *e;
-    char *s;
-    size_t len;
-    size_t extlen;
-
-    e = FileName::ext(name);
-    if (e)				// if already has an extension
-	return new FileName((char *)name, 0);
-
-    len = strlen(name);
-    extlen = strlen(ext);
-    s = (char *)alloca(len + 1 + extlen + 1);
-    memcpy(s,name,len);
-    s[len] = '.';
-    memcpy(s + len + 1, ext, extlen + 1);
-    return new FileName(s, 0);
-}
-
-/***************************
- */
-
-FileName *FileName::forceExt(const char *name, const char *ext)
-{
-    char *e;
-    char *s;
-    size_t len;
-    size_t extlen;
-
-    e = FileName::ext(name);
-    if (e)				// if already has an extension
-    {
-	len = e - name;
-	extlen = strlen(ext);
-
-	s = (char *)alloca(len + extlen + 1);
-	memcpy(s,name,len);
-	memcpy(s + len, ext, extlen + 1);
-	return new FileName(s, 0);
-    }
-    else
-	return defaultExt(name, ext);	// doesn't have one
-}
-
-/******************************
- * Return !=0 if extensions match.
- */
-
-int FileName::equalsExt(const char *ext)
-{   const char *e;
-
-    e = FileName::ext();
-    if (!e && !ext)
-	return 1;
-    if (!e || !ext)
-	return 0;
-#if POSIX
-    return strcmp(e,ext) == 0;
-#endif
-#if _WIN32
-    return stricmp(e,ext) == 0;
-#endif
-}
-
-/*************************************
- * Copy file from this to to.
- */
-
-void FileName::CopyTo(FileName *to)
-{
-    File file(this);
-
-#if _WIN32
-    file.touchtime = mem.malloc(sizeof(WIN32_FIND_DATAA));	// keep same file time
-#endif
-#if POSIX
-    file.touchtime = mem.malloc(sizeof(struct stat)); // keep same file time
-#endif
-    file.readv();
-    file.name = to;
-    file.writev();
-}
-
-/*************************************
- * Search Path for file.
- * Input:
- *	cwd	if !=0, search current directory before searching path
- */
-
-char *FileName::searchPath(Array *path, const char *name, int cwd)
-{
-    if (absolute(name))
-    {
-	return exists(name) ? (char *)name : NULL;
-    }
-    if (cwd)
-    {
-	if (exists(name))
-	    return (char *)name;
-    }
-    if (path)
-    {	unsigned i;
-
-	for (i = 0; i < path->dim; i++)
-	{
-	    char *p = (char *)path->data[i];
-	    char *n = combine(p, name);
-
-	    if (exists(n))
-		return n;
-	}
-    }
-    return NULL;
-}
-
-int FileName::exists(const char *name)
-{
-#if POSIX
-    struct stat st;
-
-    if (stat(name, &st) < 0)
-	return 0;
-    if (S_ISDIR(st.st_mode))
-	return 2;
-    return 1;
-#endif
-#if _WIN32
-    DWORD dw;
-    int result;
-
-    dw = GetFileAttributesA(name);
-    if (dw == -1L)
-	result = 0;
-    else if (dw & FILE_ATTRIBUTE_DIRECTORY)
-	result = 2;
-    else
-	result = 1;
-    return result;
-#endif
-}
-
-void FileName::ensurePathExists(const char *path)
-{
-    //printf("FileName::ensurePathExists(%s)\n", path ? path : "");
-    if (path && *path)
-    {
-	if (!exists(path))
-	{
-	    char *p = FileName::path(path);
-	    if (*p)
-	    {
-#if _WIN32
-		size_t len = strlen(p);
-		if (len > 2 && p[-1] == ':')
-		{   mem.free(p);
-		    return;
-		}
-#endif
-		ensurePathExists(p);
-		mem.free(p);
-	    }
-#if _WIN32
-	    if (path[strlen(path) - 1] != '\\')
-#endif
-#if POSIX
-	    if (path[strlen(path) - 1] != '\\')
-#endif
-	    {
-		//printf("mkdir(%s)\n", path);
-#if _WIN32
-		if (mkdir(path))
-#endif
-#if POSIX
-		if (mkdir(path, 0777))
-#endif
-		    error("cannot create directory %s", path);
-	    }
-	}
-    }
-}
-
-/****************************** File ********************************/
-
-File::File(FileName *n)
-{
-    ref = 0;
-    buffer = NULL;
-    len = 0;
-    touchtime = NULL;
-    name = n;
-}
-
-File::File(char *n)
-{
-    ref = 0;
-    buffer = NULL;
-    len = 0;
-    touchtime = NULL;
-    name = new FileName(n, 0);
-}
-
-File::~File()
-{
-    if (buffer)
-    {
-	if (ref == 0)
-	    mem.free(buffer);
-#if _WIN32
-	else if (ref == 2)
-	    UnmapViewOfFile(buffer);
-#endif
-    }
-    if (touchtime)
-	mem.free(touchtime);
-}
-
-void File::mark()
-{
-    mem.mark(buffer);
-    mem.mark(touchtime);
-    mem.mark(name);
-}
-
-/*************************************
- */
-
-int File::read()
-{
-#if POSIX
-    off_t size;
-    ssize_t numread;
-    int fd;
-    struct stat buf;
-    int result = 0;
-    char *name;
-
-    name = this->name->toChars();
-    //printf("File::read('%s')\n",name);
-    fd = open(name, O_RDONLY);
-    if (fd == -1)
-    {	result = errno;
-	//printf("\topen error, errno = %d\n",errno);
-	goto err1;
-    }
-
-    if (!ref)
-	mem.free(buffer);
-    ref = 0;       // we own the buffer now
-
-    //printf("\tfile opened\n");
-    if (fstat(fd, &buf))
-    {
-	printf("\tfstat error, errno = %d\n",errno);
-        goto err2;
-    }
-    size = buf.st_size;
-    buffer = (unsigned char *) mem.malloc(size + 2);
-    if (!buffer)
-    {
-	printf("\tmalloc error, errno = %d\n",errno);
-	goto err2;
-    }
-
-    numread = ::read(fd, buffer, size);
-    if (numread != size)
-    {
-	printf("\tread error, errno = %d\n",errno);
-	goto err2;
-    }
-
-    if (touchtime)
-        memcpy(touchtime, &buf, sizeof(buf));
-
-    if (close(fd) == -1)
-    {
-	printf("\tclose error, errno = %d\n",errno);
-	goto err;
-    }
-
-    len = size;
-
-    // Always store a wchar ^Z past end of buffer so scanner has a sentinel
-    buffer[size] = 0;		// ^Z is obsolete, use 0
-    buffer[size + 1] = 0;
-    return 0;
-
-err2:
-    close(fd);
-err:
-    mem.free(buffer);
-    buffer = NULL;
-    len = 0;
-
-err1:
-    result = 1;
-    return result;
-#endif
-#if _WIN32
-    DWORD size;
-    DWORD numread;
-    HANDLE h;
-    int result = 0;
-    char *name;
-
-    name = this->name->toChars();
-    h = CreateFileA(name,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,
-	FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,0);
-    if (h == INVALID_HANDLE_VALUE)
-	goto err1;
-
-    if (!ref)
-	mem.free(buffer);
-    ref = 0;
-
-    size = GetFileSize(h,NULL);
-    buffer = (unsigned char *) mem.malloc(size + 2);
-    if (!buffer)
-	goto err2;
-
-    if (ReadFile(h,buffer,size,&numread,NULL) != TRUE)
-	goto err2;
-
-    if (numread != size)
-	goto err2;
-
-    if (touchtime)
-    {
-	if (!GetFileTime(h, NULL, NULL, &((WIN32_FIND_DATAA *)touchtime)->ftLastWriteTime))
-	    goto err2;
-    }
-
-    if (!CloseHandle(h))
-	goto err;
-
-    len = size;
-
-    // Always store a wchar ^Z past end of buffer so scanner has a sentinel
-    buffer[size] = 0;		// ^Z is obsolete, use 0
-    buffer[size + 1] = 0;
-    return 0;
-
-err2:
-    CloseHandle(h);
-err:
-    mem.free(buffer);
-    buffer = NULL;
-    len = 0;
-
-err1:
-    result = 1;
-    return result;
-#endif
-}
-
-/*****************************
- * Read a file with memory mapped file I/O.
- */
-
-int File::mmread()
-{
-#if POSIX
-    return read();
-#endif
-#if _WIN32
-    HANDLE hFile;
-    HANDLE hFileMap;
-    DWORD size;
-    char *name;
-
-    name = this->name->toChars();
-    hFile = CreateFile(name, GENERIC_READ,
-			FILE_SHARE_READ, NULL,
-			OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
-    if (hFile == INVALID_HANDLE_VALUE)
-	goto Lerr;
-    size = GetFileSize(hFile, NULL);
-    //printf(" file created, size %d\n", size);
-
-    hFileMap = CreateFileMapping(hFile,NULL,PAGE_READONLY,0,size,NULL);
-    if (CloseHandle(hFile) != TRUE)
-	goto Lerr;
-
-    if (hFileMap == NULL)
-	goto Lerr;
-
-    //printf(" mapping created\n");
-
-    if (!ref)
-	mem.free(buffer);
-    ref = 2;
-    buffer = (unsigned char *)MapViewOfFileEx(hFileMap, FILE_MAP_READ,0,0,size,NULL);
-    if (CloseHandle(hFileMap) != TRUE)
-	goto Lerr;
-    if (buffer == NULL)			// mapping view failed
-	goto Lerr;
-
-    len = size;
-    //printf(" buffer = %p\n", buffer);
-
-    return 0;
-
-Lerr:
-    return GetLastError();			// failure
-#endif
-}
-
-/*********************************************
- * Write a file.
- * Returns:
- *	0	success
- */
-
-int File::write()
-{
-#if POSIX
-    int fd;
-    ssize_t numwritten;
-    char *name;
-
-    name = this->name->toChars();
-    fd = open(name, O_CREAT | O_WRONLY | O_TRUNC, 0644);
-    if (fd == -1)
-	goto err;
-
-    numwritten = ::write(fd, buffer, len);
-    if (len != numwritten)
-	goto err2;
-    
-    if (close(fd) == -1)
-	goto err;
-
-    if (touchtime)
-    {   struct utimbuf ubuf;
-
-        ubuf.actime = ((struct stat *)touchtime)->st_atime;
-        ubuf.modtime = ((struct stat *)touchtime)->st_mtime;
-	if (utime(name, &ubuf))
-	    goto err;
-    }
-    return 0;
-
-err2:
-    close(fd);
-    ::remove(name);
-err:
-    return 1;
-#endif
-#if _WIN32
-    HANDLE h;
-    DWORD numwritten;
-    char *name;
-
-    name = this->name->toChars();
-    h = CreateFileA(name,GENERIC_WRITE,0,NULL,CREATE_ALWAYS,
-	FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,NULL);
-    if (h == INVALID_HANDLE_VALUE)
-	goto err;
-
-    if (WriteFile(h,buffer,len,&numwritten,NULL) != TRUE)
-	goto err2;
-
-    if (len != numwritten)
-	goto err2;
-    
-    if (touchtime) {
-        SetFileTime(h, NULL, NULL, &((WIN32_FIND_DATAA *)touchtime)->ftLastWriteTime);
-    }
-    if (!CloseHandle(h))
-	goto err;
-    return 0;
-
-err2:
-    CloseHandle(h);
-    DeleteFileA(name);
-err:
-    return 1;
-#endif
-}
-
-/*********************************************
- * Append to a file.
- * Returns:
- *	0	success
- */
-
-int File::append()
-{
-#if POSIX
-    return 1;
-#endif
-#if _WIN32
-    HANDLE h;
-    DWORD numwritten;
-    char *name;
-
-    name = this->name->toChars();
-    h = CreateFileA(name,GENERIC_WRITE,0,NULL,OPEN_ALWAYS,
-	FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,NULL);
-    if (h == INVALID_HANDLE_VALUE)
-	goto err;
-
-#if 1
-    SetFilePointer(h, 0, NULL, FILE_END);
-#else // INVALID_SET_FILE_POINTER doesn't seem to have a definition
-    if (SetFilePointer(h, 0, NULL, FILE_END) == INVALID_SET_FILE_POINTER)
-	goto err;
-#endif
-
-    if (WriteFile(h,buffer,len,&numwritten,NULL) != TRUE)
-	goto err2;
-
-    if (len != numwritten)
-	goto err2;
-    
-    if (touchtime) {
-        SetFileTime(h, NULL, NULL, &((WIN32_FIND_DATAA *)touchtime)->ftLastWriteTime);
-    }
-    if (!CloseHandle(h))
-	goto err;
-    return 0;
-
-err2:
-    CloseHandle(h);
-err:
-    return 1;
-#endif
-}
-
-/**************************************
- */
-
-void File::readv()
-{
-    if (read())
-	error("Error reading file '%s'\n",name->toChars());
-}
-
-/**************************************
- */
-
-void File::mmreadv()
-{
-    if (mmread())
-	readv();
-}
-
-void File::writev()
-{
-    if (write())
-	error("Error writing file '%s'\n",name->toChars());
-}
-
-void File::appendv()
-{
-    if (write())
-	error("Error appending to file '%s'\n",name->toChars());
-}
-
-/*******************************************
- * Return !=0 if file exists.
- *	0:	file doesn't exist
- *	1:	normal file
- *	2:	directory
- */
-
-int File::exists()
-{
-#if POSIX
-    return 0;
-#endif
-#if _WIN32
-    DWORD dw;
-    int result;
-    char *name;
-
-    name = this->name->toChars();
-    if (touchtime)
-	dw = ((WIN32_FIND_DATAA *)touchtime)->dwFileAttributes;
-    else
-	dw = GetFileAttributesA(name);
-    if (dw == -1L)
-	result = 0;
-    else if (dw & FILE_ATTRIBUTE_DIRECTORY)
-	result = 2;
-    else
-	result = 1;
-    return result;
-#endif
-}
-
-void File::remove()
-{
-#if POSIX
-    ::remove(this->name->toChars());
-#endif
-#if _WIN32
-    DeleteFileA(this->name->toChars());
-#endif
-}
-
-Array *File::match(char *n)
-{
-    return match(new FileName(n, 0));
-}
-
-Array *File::match(FileName *n)
-{
-#if POSIX
-    return NULL;
-#endif
-#if _WIN32
-    HANDLE h;
-    WIN32_FIND_DATAA fileinfo;
-    Array *a;
-    char *c;
-    char *name;
-
-    a = new Array();
-    c = n->toChars();
-    name = n->name();
-    h = FindFirstFileA(c,&fileinfo);
-    if (h != INVALID_HANDLE_VALUE)
-    {
-	do
-	{
-	    // Glue path together with name
-	    char *fn;
-	    File *f;
-
-	    fn = (char *)mem.malloc(name - c + strlen(fileinfo.cFileName) + 1);
-	    memcpy(fn, c, name - c);
-	    strcpy(fn + (name - c), fileinfo.cFileName);
-	    f = new File(fn);
-	    f->touchtime = mem.malloc(sizeof(WIN32_FIND_DATAA));
-	    memcpy(f->touchtime, &fileinfo, sizeof(fileinfo));
-	    a->push(f);
-	} while (FindNextFileA(h,&fileinfo) != FALSE);
-	FindClose(h);
-    }
-    return a;
-#endif
-}
-
-int File::compareTime(File *f)
-{
-#if POSIX
-    return 0;
-#endif
-#if _WIN32
-    if (!touchtime)
-	stat();
-    if (!f->touchtime)
-	f->stat();
-    return CompareFileTime(&((WIN32_FIND_DATAA *)touchtime)->ftLastWriteTime, &((WIN32_FIND_DATAA *)f->touchtime)->ftLastWriteTime);
-#endif
-}
-
-void File::stat()
-{
-#if POSIX
-    if (!touchtime)
-    {
-	touchtime = mem.calloc(1, sizeof(struct stat));
-    }
-#endif
-#if _WIN32
-    HANDLE h;
-
-    if (!touchtime)
-    {
-	touchtime = mem.calloc(1, sizeof(WIN32_FIND_DATAA));
-    }
-    h = FindFirstFileA(name->toChars(),(WIN32_FIND_DATAA *)touchtime);
-    if (h != INVALID_HANDLE_VALUE)
-    {
-	FindClose(h);
-    }
-#endif
-}
-
-void File::checkoffset(size_t offset, size_t nbytes)
-{
-    if (offset > len || offset + nbytes > len)
-	error("Corrupt file '%s': offset x%"PRIxSIZE" off end of file",toChars(),offset);
-}
-
-char *File::toChars()
-{
-    return name->toChars();
-}
-
-
-/************************* OutBuffer *************************/
-
-OutBuffer::OutBuffer()
-{
-    data = NULL;
-    offset = 0;
-    size = 0;
-}
-
-OutBuffer::~OutBuffer()
-{
-    mem.free(data);
-}
-
-void *OutBuffer::extractData()
-{
-    void *p;
-
-    p = (void *)data;
-    data = NULL;
-    offset = 0;
-    size = 0;
-    return p;
-}
-
-void OutBuffer::mark()
-{
-    mem.mark(data);
-}
-
-void OutBuffer::reserve(unsigned nbytes)
-{
-  //printf("OutBuffer::reserve: size = %d, offset = %d, nbytes = %d\n", size, offset, nbytes);
-    if (size - offset < nbytes)
-    {
-#if defined (__x86_64__)
-	size = (offset + nbytes) * 2+2;
-#else
-	size = (offset + nbytes) * 2;
-#endif
-	data = (unsigned char *)mem.realloc(data, size);
-    }
-}
-
-void OutBuffer::reset()
-{
-    offset = 0;
-}
-
-void OutBuffer::setsize(unsigned size)
-{
-    offset = size;
-}
-
-void OutBuffer::write(const void *data, unsigned nbytes)
-{
-    reserve(nbytes);
-    memcpy(this->data + offset, data, nbytes);
-    offset += nbytes;
-}
-
-void OutBuffer::writebstring(unsigned char *string)
-{
-    write(string,*string + 1);
-}
-
-void OutBuffer::writestring(const char *string)
-{
-    write(string,strlen(string));
-}
-
-void OutBuffer::writedstring(const char *string)
-{
-#if M_UNICODE
-    for (; *string; string++)
-    {
-	writedchar(*string);
-    }
-#else
-    write(string,strlen(string));
-#endif
-}
-
-void OutBuffer::writedstring(const wchar_t *string)
-{
-#if M_UNICODE
-    write(string,wcslen(string) * sizeof(wchar_t));
-#else
-    for (; *string; string++)
-    {
-	writedchar(*string);
-    }
-#endif
-}
-
-void OutBuffer::prependstring(const char *string)
-{   unsigned len;
-
-    len = strlen(string);
-    reserve(len);
-    memmove(data + len, data, offset);
-    memcpy(data, string, len);
-    offset += len;
-}
-
-void OutBuffer::writenl()
-{
-#if _WIN32
-#if M_UNICODE
-    write4(0x000A000D);		// newline is CR,LF on Microsoft OS's
-#else
-    writeword(0x0A0D);		// newline is CR,LF on Microsoft OS's
-#endif
-#else
-#if M_UNICODE
-    writeword('\n');
-#else
-    writeByte('\n');
-#endif
-#endif
-}
-
-void OutBuffer::writeByte(unsigned b)
-{
-    reserve(1);
-    this->data[offset] = (unsigned char)b;
-    offset++;
-}
-
-void OutBuffer::writeUTF8(unsigned b)
-{
-    reserve(6);
-    if (b <= 0x7F)
-    {
-	this->data[offset] = (unsigned char)b;
-	offset++;
-    }
-    else if (b <= 0x7FF)
-    {
-	this->data[offset + 0] = (unsigned char)((b >> 6) | 0xC0);
-	this->data[offset + 1] = (unsigned char)((b & 0x3F) | 0x80);
-	offset += 2;
-    }
-    else if (b <= 0xFFFF)
-    {
-	this->data[offset + 0] = (unsigned char)((b >> 12) | 0xE0);
-	this->data[offset + 1] = (unsigned char)(((b >> 6) & 0x3F) | 0x80);
-	this->data[offset + 2] = (unsigned char)((b & 0x3F) | 0x80);
-	offset += 3;
-    }
-    else if (b <= 0x1FFFFF)
-    {
-	this->data[offset + 0] = (unsigned char)((b >> 18) | 0xF0);
-	this->data[offset + 1] = (unsigned char)(((b >> 12) & 0x3F) | 0x80);
-	this->data[offset + 2] = (unsigned char)(((b >> 6) & 0x3F) | 0x80);
-	this->data[offset + 3] = (unsigned char)((b & 0x3F) | 0x80);
-	offset += 4;
-    }
-    else if (b <= 0x3FFFFFF)
-    {
-	this->data[offset + 0] = (unsigned char)((b >> 24) | 0xF8);
-	this->data[offset + 1] = (unsigned char)(((b >> 18) & 0x3F) | 0x80);
-	this->data[offset + 2] = (unsigned char)(((b >> 12) & 0x3F) | 0x80);
-	this->data[offset + 3] = (unsigned char)(((b >> 6) & 0x3F) | 0x80);
-	this->data[offset + 4] = (unsigned char)((b & 0x3F) | 0x80);
-	offset += 5;
-    }
-    else if (b <= 0x7FFFFFFF)
-    {
-	this->data[offset + 0] = (unsigned char)((b >> 30) | 0xFC);
-	this->data[offset + 1] = (unsigned char)(((b >> 24) & 0x3F) | 0x80);
-	this->data[offset + 2] = (unsigned char)(((b >> 18) & 0x3F) | 0x80);
-	this->data[offset + 3] = (unsigned char)(((b >> 12) & 0x3F) | 0x80);
-	this->data[offset + 4] = (unsigned char)(((b >> 6) & 0x3F) | 0x80);
-	this->data[offset + 5] = (unsigned char)((b & 0x3F) | 0x80);
-	offset += 6;
-    }
-    else
-	assert(0);
-}
-
-void OutBuffer::writedchar(unsigned b)
-{
-    reserve(Dchar_mbmax * sizeof(dchar));
-    offset = (unsigned char *)Dchar::put((dchar *)(this->data + offset), (dchar)b) -
-		this->data;
-}
-
-void OutBuffer::prependbyte(unsigned b)
-{
-    reserve(1);
-    memmove(data + 1, data, offset);
-    data[0] = (unsigned char)b;
-    offset++;
-}
-
-void OutBuffer::writeword(unsigned w)
-{
-    reserve(2);
-    *(unsigned short *)(this->data + offset) = (unsigned short)w;
-    offset += 2;
-}
-
-void OutBuffer::writeUTF16(unsigned w)
-{
-    reserve(4);
-    if (w <= 0xFFFF)
-    {
-	*(unsigned short *)(this->data + offset) = (unsigned short)w;
-	offset += 2;
-    }
-    else if (w <= 0x10FFFF)
-    {
-	*(unsigned short *)(this->data + offset) = (unsigned short)((w >> 10) + 0xD7C0);
-	*(unsigned short *)(this->data + offset + 2) = (unsigned short)((w & 0x3FF) | 0xDC00);
-	offset += 4;
-    }
-    else
-	assert(0);
-}
-
-void OutBuffer::write4(unsigned w)
-{
-    reserve(4);
-    *(unsigned long *)(this->data + offset) = w;
-    offset += 4;
-}
-
-void OutBuffer::write(OutBuffer *buf)
-{
-    if (buf)
-    {	reserve(buf->offset);
-	memcpy(data + offset, buf->data, buf->offset);
-	offset += buf->offset;
-    }
-}
-
-void OutBuffer::write(Object *obj)
-{
-    if (obj)
-    {
-	writestring(obj->toChars());
-    }
-}
-
-void OutBuffer::fill0(unsigned nbytes)
-{
-    reserve(nbytes);
-    memset(data + offset,0,nbytes);
-    offset += nbytes;
-}
-
-void OutBuffer::align(unsigned size)
-{   unsigned nbytes;
-
-    nbytes = ((offset + size - 1) & ~(size - 1)) - offset;
-    fill0(nbytes);
-}
-
-
-////////////////////////////////////////////////////////////////
-// The compiler shipped with Visual Studio 2005 (and possible
-// other versions) does not support C99 printf format specfiers
-// such as %z and %j
-#if _MSC_VER || __MINGW32__
-using std::string;
-using std::wstring;
-
-template<typename S>
-inline void 
-search_and_replace(S& str, const S& what, const S& replacement)
-{
-    assert(!what.empty());
-    size_t pos = str.find(what);
-    while (pos != S::npos) 
-    {
-        str.replace(pos, what.size(), replacement);
-        pos = str.find(what, pos + replacement.size());
-    }
-}
-#define WORKAROUND_C99_SPECIFIERS_BUG(S,tmp,f) \
-    S tmp = f;                                 \
-    search_and_replace(fmt, S("%z"), S("%l")); \
-    search_and_replace(fmt, S("%j"), S("%i")); \
-    f = tmp.c_str();
-#else
-#define WORKAROUND_C99_SPECIFIERS_BUG(S,tmp,f)
-#endif
-
-void OutBuffer::vprintf(const char *format, va_list args)
-{
-    char buffer[128];
-    char *p;
-    unsigned psize;
-    int count;
-
-    WORKAROUND_C99_SPECIFIERS_BUG(string, fmt, format);
-
-    p = buffer;
-    psize = sizeof(buffer);
-    for (;;)
-    {
-#if _WIN32
-	count = _vsnprintf(p,psize,format,args);
-	if (count != -1)
-	    break;
-	psize *= 2;
-#elif POSIX
-        va_list va;
-        va_copy(va, args);
-/*
-  The functions vprintf(), vfprintf(), vsprintf(), vsnprintf()
-  are equivalent to the functions printf(), fprintf(), sprintf(),
-  snprintf(), respectively, except that they are called with a
-  va_list instead of a variable number of arguments. These
-  functions do not call the va_end macro. Consequently, the value
-  of ap is undefined after the call. The application should call
-  va_end(ap) itself afterwards.
- */
-	count = vsnprintf(p,psize,format,va);
-        va_end(va);
-	if (count == -1)
-	    psize *= 2;
-	else if (count >= psize)
-	    psize = count + 1;
-	else
-	    break;
-#endif
-	p = (char *) alloca(psize);	// buffer too small, try again with larger size
-    }
-    write(p,count);
-}
-
-#if M_UNICODE
-void OutBuffer::vprintf(const wchar_t *format, va_list args)
-{
-    dchar buffer[128];
-    dchar *p;
-    unsigned psize;
-    int count;
-
-    WORKAROUND_C99_SPECIFIERS_BUG(wstring, fmt, format);
-
-    p = buffer;
-    psize = sizeof(buffer) / sizeof(buffer[0]);
-    for (;;)
-    {
-#if _WIN32
-	count = _vsnwprintf(p,psize,format,args);
-	if (count != -1)
-	    break;
-	psize *= 2;
-#endif
-#if POSIX
-        va_list va;
-        va_copy(va, args);
-	count = vsnwprintf(p,psize,format,va);
-        va_end(va); 
-
-	if (count == -1)
-	    psize *= 2;
-	else if (count >= psize)
-	    psize = count + 1;
-	else
-	    break;
-#endif
-	p = (dchar *) alloca(psize * 2);	// buffer too small, try again with larger size
-    }
-    write(p,count * 2);
-}
-#endif
-
-void OutBuffer::printf(const char *format, ...)
-{
-    va_list ap;
-    va_start(ap, format);
-    vprintf(format,ap);
-    va_end(ap);
-}
-
-#if M_UNICODE
-void OutBuffer::printf(const wchar_t *format, ...)
-{
-    va_list ap;
-    va_start(ap, format);
-    vprintf(format,ap);
-    va_end(ap);
-}
-#endif
-
-void OutBuffer::bracket(char left, char right)
-{
-    reserve(2);
-    memmove(data + 1, data, offset);
-    data[0] = left;
-    data[offset + 1] = right;
-    offset += 2;
-}
-
-/******************
- * Insert left at i, and right at j.
- * Return index just past right.
- */
-
-unsigned OutBuffer::bracket(unsigned i, const char *left, unsigned j, const char *right)
-{
-    size_t leftlen = strlen(left);
-    size_t rightlen = strlen(right);
-    reserve(leftlen + rightlen);
-    insert(i, left, leftlen);
-    insert(j + leftlen, right, rightlen);
-    return j + leftlen + rightlen;
-}
-
-void OutBuffer::spread(unsigned offset, unsigned nbytes)
-{
-    reserve(nbytes);
-    memmove(data + offset + nbytes, data + offset,
-	this->offset - offset);
-    this->offset += nbytes;
-}
-
-/****************************************
- * Returns: offset + nbytes
- */
-
-unsigned OutBuffer::insert(unsigned offset, const void *p, unsigned nbytes)
-{
-    spread(offset, nbytes);
-    memmove(data + offset, p, nbytes);
-    return offset + nbytes;
-}
-
-void OutBuffer::remove(unsigned offset, unsigned nbytes)
-{
-    memmove(data + offset, data + offset + nbytes, this->offset - (offset + nbytes));
-    this->offset -= nbytes;
-}
-
-char *OutBuffer::toChars()
-{
-    writeByte(0);
-    return (char *)data;
-}
-
-/********************************* Bits ****************************/
-
-Bits::Bits()
-{
-    data = NULL;
-    bitdim = 0;
-    allocdim = 0;
-}
-
-Bits::~Bits()
-{
-    mem.free(data);
-}
-
-void Bits::mark()
-{
-    mem.mark(data);
-}
-
-void Bits::resize(unsigned bitdim)
-{
-    unsigned allocdim;
-    unsigned mask;
-
-    allocdim = (bitdim + 31) / 32;
-    data = (unsigned *)mem.realloc(data, allocdim * sizeof(data[0]));
-    if (this->allocdim < allocdim)
-	memset(data + this->allocdim, 0, (allocdim - this->allocdim) * sizeof(data[0]));
-
-    // Clear other bits in last word
-    mask = (1 << (bitdim & 31)) - 1;
-    if (mask)
-	data[allocdim - 1] &= ~mask;
-
-    this->bitdim = bitdim;
-    this->allocdim = allocdim;
-}
-
-void Bits::set(unsigned bitnum)
-{
-    data[bitnum / 32] |= 1 << (bitnum & 31);
-}
-
-void Bits::clear(unsigned bitnum)
-{
-    data[bitnum / 32] &= ~(1 << (bitnum & 31));
-}
-
-int Bits::test(unsigned bitnum)
-{
-    return data[bitnum / 32] & (1 << (bitnum & 31));
-}
-
-void Bits::set()
-{   unsigned mask;
-
-    memset(data, ~0, allocdim * sizeof(data[0]));
-
-    // Clear other bits in last word
-    mask = (1 << (bitdim & 31)) - 1;
-    if (mask)
-	data[allocdim - 1] &= mask;
-}
-
-void Bits::clear()
-{
-    memset(data, 0, allocdim * sizeof(data[0]));
-}
-
-void Bits::copy(Bits *from)
-{
-    assert(bitdim == from->bitdim);
-    memcpy(data, from->data, allocdim * sizeof(data[0]));
-}
-
-Bits *Bits::clone()
-{
-    Bits *b;
-
-    b = new Bits();
-    b->resize(bitdim);
-    b->copy(this);
-    return b;
-}
-
-void Bits::sub(Bits *b)
-{
-    unsigned u;
-
-    for (u = 0; u < allocdim; u++)
-	data[u] &= ~b->data[u];
-}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
--- a/dmd2/root.h	Mon Jun 01 01:28:18 2009 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,356 +0,0 @@
-
-
-// Copyright (c) 1999-2006 by Digital Mars
-// All Rights Reserved
-// written by Walter Bright
-// www.digitalmars.com
-// License for redistribution is by either the Artistic License
-// in artistic.txt, or the GNU General Public License in gnu.txt.
-// See the included readme.txt for details.
-
-#ifndef ROOT_H
-#define ROOT_H
-
-#include <stdlib.h>
-#include <stdarg.h>
-
-#if __DMC__
-#pragma once
-#endif
-
-typedef size_t hash_t;
-
-#include "dchar.h"
-
-char *wchar2ascii(wchar_t *);
-int wcharIsAscii(wchar_t *);
-char *wchar2ascii(wchar_t *, unsigned len);
-int wcharIsAscii(wchar_t *, unsigned len);
-
-int bstrcmp(unsigned char *s1, unsigned char *s2);
-char *bstr2str(unsigned char *b);
-void error(const char *format, ...);
-void error(const wchar_t *format, ...);
-void warning(const char *format, ...);
-
-#ifndef TYPEDEFS
-#define TYPEDEFS
-
-#if _MSC_VER
-#include <malloc.h> // for alloca
-// According to VC 8.0 docs, long double is the same as double
-#define strtold strtod
-#define strtof  strtod
-#define isnan   _isnan
-
-typedef __int64 longlong;
-typedef unsigned __int64 ulonglong;
-#else
-typedef long long longlong;
-typedef unsigned long long ulonglong;
-#endif
-
-#endif
-
-longlong randomx();
-
-/*
- * Root of our class library.
- */
-
-struct OutBuffer;
-struct Array;
-
-struct Object
-{
-    Object() { }
-    virtual ~Object() { }
-
-    virtual int equals(Object *o);
-
-    /**
-     * Returns a hash code, useful for things like building hash tables of Objects.
-     */
-    virtual hash_t hashCode();
-
-    /**
-     * Return <0, ==0, or >0 if this is less than, equal to, or greater than obj.
-     * Useful for sorting Objects.
-     */
-    virtual int compare(Object *obj);
-
-    /**
-     * Pretty-print an Object. Useful for debugging the old-fashioned way.
-     */
-    virtual void print();
-
-    virtual char *toChars();
-    virtual dchar *toDchars();
-    virtual void toBuffer(OutBuffer *buf);
-
-    /**
-     * Used as a replacement for dynamic_cast. Returns a unique number
-     * defined by the library user. For Object, the return value is 0.
-     */
-    virtual int dyncast();
-
-    /**
-     * Marks pointers for garbage collector by calling mem.mark() for all pointers into heap.
-     */
-    /*virtual*/		// not used, disable for now
-	void mark();
-};
-
-struct String : Object
-{
-    int ref;			// != 0 if this is a reference to someone else's string
-    char *str;			// the string itself
-
-    String(char *str, int ref = 1);
-
-    ~String();
-
-    static hash_t calcHash(const char *str, size_t len);
-    static hash_t calcHash(const char *str);
-    hash_t hashCode();
-    unsigned len();
-    int equals(Object *obj);
-    int compare(Object *obj);
-    char *toChars();
-    void print();
-    void mark();
-};
-
-struct FileName : String
-{
-    FileName(char *str, int ref);
-    FileName(char *path, char *name);
-    hash_t hashCode();
-    int equals(Object *obj);
-    int compare(Object *obj);
-    static int absolute(const char *name);
-    static char *ext(const char *);
-    char *ext();
-    static char *removeExt(const char *str);
-    static char *name(const char *);
-    char *name();
-    static char *path(const char *);
-    static char *replaceName(char *path, char *name);
-
-    static char *combine(const char *path, const char *name);
-    static Array *splitPath(const char *path);
-    static FileName *defaultExt(const char *name, const char *ext);
-    static FileName *forceExt(const char *name, const char *ext);
-    int equalsExt(const char *ext);
-
-    void CopyTo(FileName *to);
-    static char *searchPath(Array *path, const char *name, int cwd);
-    static int exists(const char *name);
-    static void ensurePathExists(const char *path);
-};
-
-struct File : Object
-{
-    int ref;			// != 0 if this is a reference to someone else's buffer
-    unsigned char *buffer;	// data for our file
-    unsigned len;		// amount of data in buffer[]
-    void *touchtime;		// system time to use for file
-
-    FileName *name;		// name of our file
-
-    File(char *);
-    File(FileName *);
-    ~File();
-
-    void mark();
-
-    char *toChars();
-
-    /* Read file, return !=0 if error
-     */
-
-    int read();
-
-    /* Write file, either succeed or fail
-     * with error message & exit.
-     */
-
-    void readv();
-
-    /* Read file, return !=0 if error
-     */
-
-    int mmread();
-
-    /* Write file, either succeed or fail
-     * with error message & exit.
-     */
-
-    void mmreadv();
-
-    /* Write file, return !=0 if error
-     */
-
-    int write();
-
-    /* Write file, either succeed or fail
-     * with error message & exit.
-     */
-
-    void writev();
-
-    /* Return !=0 if file exists.
-     *	0:	file doesn't exist
-     *	1:	normal file
-     *	2:	directory
-     */
-
-    /* Append to file, return !=0 if error
-     */
-
-    int append();
-
-    /* Append to file, either succeed or fail
-     * with error message & exit.
-     */
-
-    void appendv();
-
-    /* Return !=0 if file exists.
-     *	0:	file doesn't exist
-     *	1:	normal file
-     *	2:	directory
-     */
-
-    int exists();
-
-    /* Given wildcard filespec, return an array of
-     * matching File's.
-     */
-
-    static Array *match(char *);
-    static Array *match(FileName *);
-
-    // Compare file times.
-    // Return	<0	this < f
-    //		=0	this == f
-    //		>0	this > f
-    int compareTime(File *f);
-
-    // Read system file statistics
-    void stat();
-
-    /* Set buffer
-     */
-
-    void setbuffer(void *buffer, unsigned len)
-    {
-	this->buffer = (unsigned char *)buffer;
-	this->len = len;
-    }
-
-    void checkoffset(size_t offset, size_t nbytes);
-
-    void remove();		// delete file
-};
-
-struct OutBuffer : Object
-{
-    unsigned char *data;
-    unsigned offset;
-    unsigned size;
-
-    OutBuffer();
-    ~OutBuffer();
-    void *extractData();
-    void mark();
-
-    void reserve(unsigned nbytes);
-    void setsize(unsigned size);
-    void reset();
-    void write(const void *data, unsigned nbytes);
-    void writebstring(unsigned char *string);
-    void writestring(const char *string);
-    void writedstring(const char *string);
-    void writedstring(const wchar_t *string);
-    void prependstring(const char *string);
-    void writenl();			// write newline
-    void writeByte(unsigned b);
-    void writebyte(unsigned b) { writeByte(b); }
-    void writeUTF8(unsigned b);
-    void writedchar(unsigned b);
-    void prependbyte(unsigned b);
-    void writeword(unsigned w);
-    void writeUTF16(unsigned w);
-    void write4(unsigned w);
-    void write(OutBuffer *buf);
-    void write(Object *obj);
-    void fill0(unsigned nbytes);
-    void align(unsigned size);
-    void vprintf(const char *format, va_list args);
-    void printf(const char *format, ...);
-#if M_UNICODE
-    void vprintf(const unsigned short *format, va_list args);
-    void printf(const unsigned short *format, ...);
-#endif
-    void bracket(char left, char right);
-    unsigned bracket(unsigned i, const char *left, unsigned j, const char *right);
-    void spread(unsigned offset, unsigned nbytes);
-    unsigned insert(unsigned offset, const void *data, unsigned nbytes);
-    void remove(unsigned offset, unsigned nbytes);
-    char *toChars();
-    char *extractString();
-};
-
-struct Array : Object
-{
-    unsigned dim;
-    unsigned allocdim;
-    void **data;
-
-    Array();
-    ~Array();
-    void mark();
-    char *toChars();
-
-    void reserve(unsigned nentries);
-    void setDim(unsigned newdim);
-    void fixDim();
-    void push(void *ptr);
-    void *pop();
-    void shift(void *ptr);
-    void insert(unsigned index, void *ptr);
-    void insert(unsigned index, Array *a);
-    void append(Array *a);
-    void remove(unsigned i);
-    void zero();
-    void *tos();
-    void sort();
-    Array *copy();
-};
-
-struct Bits : Object
-{
-    unsigned bitdim;
-    unsigned allocdim;
-    unsigned *data;
-
-    Bits();
-    ~Bits();
-    void mark();
-
-    void resize(unsigned bitdim);
-
-    void set(unsigned bitnum);
-    void clear(unsigned bitnum);
-    int test(unsigned bitnum);
-
-    void set();
-    void clear();
-    void copy(Bits *from);
-    Bits *clone();
-
-    void sub(Bits *b);
-};
-
-#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd2/root/array.c	Mon Jun 01 19:02:20 2009 +0100
@@ -0,0 +1,224 @@
+
+// Copyright (c) 1999-2009 by Digital Mars
+// All Rights Reserved
+// written by Walter Bright
+// 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 <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <assert.h>
+
+#if (defined (__SVR4) && defined (__sun)) 
+#include <alloca.h>
+#endif
+
+#if _MSC_VER || __MINGW32__
+#include <malloc.h>
+#endif
+
+#if IN_GCC
+#include "gdc_alloca.h"
+#endif
+
+#if _WIN32
+#include <windows.h>
+#endif
+
+#ifndef _WIN32
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <unistd.h>
+#include <utime.h>
+#endif
+
+#include "port.h"
+#include "root.h"
+#include "dchar.h"
+#include "rmem.h"
+
+
+/********************************* Array ****************************/
+
+Array::Array()
+{
+    data = NULL;
+    dim = 0;
+    allocdim = 0;
+}
+
+Array::~Array()
+{
+    mem.free(data);
+}
+
+void Array::mark()
+{   unsigned u;
+
+    mem.mark(data);
+    for (u = 0; u < dim; u++)
+	mem.mark(data[u]);	// BUG: what if arrays of Object's?
+}
+
+void Array::reserve(unsigned nentries)
+{
+    //printf("Array::reserve: size = %d, offset = %d, nbytes = %d\n", size, offset, nbytes);
+    if (allocdim - dim < nentries)
+    {
+	allocdim = dim + nentries;
+	data = (void **)mem.realloc(data, allocdim * sizeof(*data));
+    }
+}
+
+void Array::setDim(unsigned newdim)
+{
+    if (dim < newdim)
+    {
+	reserve(newdim - dim);
+    }
+    dim = newdim;
+}
+
+void Array::fixDim()
+{
+    if (dim != allocdim)
+    {	data = (void **)mem.realloc(data, dim * sizeof(*data));
+	allocdim = dim;
+    }
+}
+
+void Array::push(void *ptr)
+{
+    reserve(1);
+    data[dim++] = ptr;
+}
+
+void *Array::pop()
+{
+    return data[--dim];
+}
+
+void Array::shift(void *ptr)
+{
+    reserve(1);
+    memmove(data + 1, data, dim * sizeof(*data));
+    data[0] = ptr;
+    dim++;
+}
+
+void Array::insert(unsigned index, void *ptr)
+{
+    reserve(1);
+    memmove(data + index + 1, data + index, (dim - index) * sizeof(*data));
+    data[index] = ptr;
+    dim++;
+}
+
+
+void Array::insert(unsigned index, Array *a)
+{
+    if (a)
+    {	unsigned d;
+
+	d = a->dim;
+	reserve(d);
+	if (dim != index)
+	    memmove(data + index + d, data + index, (dim - index) * sizeof(*data));
+	memcpy(data + index, a->data, d * sizeof(*data));
+	dim += d;
+    }
+}
+
+
+/***********************************
+ * Append array a to this array.
+ */
+
+void Array::append(Array *a)
+{
+    insert(dim, a);
+}
+
+void Array::remove(unsigned i)
+{
+    memmove(data + i, data + i + 1, (dim - i) * sizeof(data[0]));
+    dim--;
+}
+
+char *Array::toChars()
+{
+    unsigned len;
+    unsigned u;
+    char **buf;
+    char *str;
+    char *p;
+
+    buf = (char **)alloca(dim * sizeof(char *));
+    len = 2;
+    for (u = 0; u < dim; u++)
+    {
+	buf[u] = ((Object *)data[u])->toChars();
+	len += strlen(buf[u]) + 1;
+    }
+    str = (char *)mem.malloc(len);
+
+    str[0] = '[';
+    p = str + 1;
+    for (u = 0; u < dim; u++)
+    {
+	if (u)
+	    *p++ = ',';
+	len = strlen(buf[u]);
+	memcpy(p,buf[u],len);
+	p += len;
+    }
+    *p++ = ']';
+    *p = 0;
+    return str;
+}
+
+void Array::zero()
+{
+    memset(data,0,dim * sizeof(data[0]));
+}
+
+void *Array::tos()
+{
+    return dim ? data[dim - 1] : NULL;
+}
+
+int
+#if _WIN32
+  __cdecl
+#endif
+	Array_sort_compare(const void *x, const void *y)
+{
+    Object *ox = *(Object **)x;
+    Object *oy = *(Object **)y;
+
+    return ox->compare(oy);
+}
+
+void Array::sort()
+{
+    if (dim)
+    {
+	qsort(data, dim, sizeof(Object *), Array_sort_compare);
+    }
+}
+
+Array *Array::copy()
+{
+    Array *a = new Array();
+
+    a->setDim(dim);
+    memcpy(a->data, data, dim * sizeof(void *));
+    return a;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd2/root/async.c	Mon Jun 01 19:02:20 2009 +0100
@@ -0,0 +1,177 @@
+
+#define _MT 1
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+
+#if _WIN32
+
+#include <windows.h>
+#include <stdio.h>
+#include <errno.h>
+#include <process.h>
+
+#include "root.h"
+#include "rmem.h"
+
+static unsigned __stdcall startthread(void *p);
+
+struct FileData
+{
+    File *file;
+    int result;
+    HANDLE event;
+};
+
+struct AsyncRead
+{
+    static AsyncRead *create(size_t nfiles);
+    void addFile(File *file);
+    void start();
+    int read(size_t i);
+    static void dispose(AsyncRead *);
+
+    HANDLE hThread;
+
+    size_t filesdim;
+    size_t filesmax;
+    FileData files[1];
+};
+
+
+AsyncRead *AsyncRead::create(size_t nfiles)
+{
+    AsyncRead *aw = (AsyncRead *)mem.calloc(1, sizeof(AsyncRead) +
+				(nfiles - 1) * sizeof(FileData));
+    aw->filesmax = nfiles;
+    return aw;
+}
+
+void AsyncRead::addFile(File *file)
+{
+    //printf("addFile(file = %p)\n", file);
+    //printf("filesdim = %d, filesmax = %d\n", filesdim, filesmax);
+    assert(filesdim < filesmax);
+    files[filesdim].file = file;
+    files[filesdim].event = CreateEvent(NULL, TRUE, FALSE, NULL);
+    ResetEvent(files[filesdim].event);
+    filesdim++;
+}
+
+void AsyncRead::start()
+{
+    unsigned threadaddr;
+    hThread = (HANDLE) _beginthreadex(NULL,
+	0,
+	&startthread,
+	this,
+	0,
+	(unsigned *)&threadaddr);
+
+    if (hThread)
+    {
+	SetThreadPriority(hThread, THREAD_PRIORITY_HIGHEST);
+    }
+    else
+    {
+	assert(0);
+    }
+}
+
+int AsyncRead::read(size_t i)
+{
+    FileData *f = &files[i];
+    WaitForSingleObject(f->event, INFINITE);
+    Sleep(0);			// give up time slice
+    return f->result;
+}
+
+void AsyncRead::dispose(AsyncRead *aw)
+{
+    delete aw;
+}
+
+
+
+unsigned __stdcall startthread(void *p)
+{
+    AsyncRead *aw = (AsyncRead *)p;
+
+    for (size_t i = 0; i < aw->filesdim; i++)
+    {	FileData *f = &aw->files[i];
+
+	f->result = f->file->read();
+	SetEvent(f->event);
+    }
+    _endthreadex(EXIT_SUCCESS);
+    return EXIT_SUCCESS;		// if skidding
+}
+
+#else
+
+#include <stdio.h>
+#include <errno.h>
+
+#include "root.h"
+#include "rmem.h"
+
+struct FileData
+{
+    File *file;
+    int result;
+    //HANDLE event;
+};
+
+struct AsyncRead
+{
+    static AsyncRead *create(size_t nfiles);
+    void addFile(File *file);
+    void start();
+    int read(size_t i);
+    static void dispose(AsyncRead *);
+
+    //HANDLE hThread;
+
+    size_t filesdim;
+    size_t filesmax;
+    FileData files[1];
+};
+
+
+AsyncRead *AsyncRead::create(size_t nfiles)
+{
+    AsyncRead *aw = (AsyncRead *)mem.calloc(1, sizeof(AsyncRead) +
+				(nfiles - 1) * sizeof(FileData));
+    aw->filesmax = nfiles;
+    return aw;
+}
+
+void AsyncRead::addFile(File *file)
+{
+    //printf("addFile(file = %p)\n", file);
+    //printf("filesdim = %d, filesmax = %d\n", filesdim, filesmax);
+    assert(filesdim < filesmax);
+    files[filesdim].file = file;
+    //files[filesdim].event = CreateEvent(NULL, TRUE, FALSE, NULL);
+    //ResetEvent(files[filesdim].event);
+    filesdim++;
+}
+
+void AsyncRead::start()
+{
+}
+
+int AsyncRead::read(size_t i)
+{
+    FileData *f = &files[i];
+    f->result = f->file->read();
+    return f->result;
+}
+
+void AsyncRead::dispose(AsyncRead *aw)
+{
+    delete aw;
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd2/root/async.h	Mon Jun 01 19:02:20 2009 +0100
@@ -0,0 +1,33 @@
+
+// Copyright (c) 2009-2009 by Digital Mars
+// All Rights Reserved
+// written by Walter Bright
+// http://www.digitalmars.com
+// License for redistribution is by either the Artistic License
+// in artistic.txt, or the GNU General Public License in gnu.txt.
+// See the included readme.txt for details.
+
+#ifndef ASYNC_H
+#define ASYNC_H
+
+#if __DMC__
+#pragma once
+#endif
+
+
+/*******************
+ * Simple interface to read files asynchronously in another
+ * thread.
+ */
+
+struct AsyncRead
+{
+    static AsyncRead *create(size_t nfiles);
+    void addFile(File *file);
+    void start();
+    int read(size_t i);
+    static void dispose(AsyncRead *);
+};
+
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd2/root/dchar.c	Mon Jun 01 19:02:20 2009 +0100
@@ -0,0 +1,482 @@
+
+// Copyright (c) 1999-2006 by Digital Mars
+// All Rights Reserved
+// written by Walter Bright
+// 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 <stdlib.h>
+#include <stdint.h>
+#include <assert.h>
+
+#include "dchar.h"
+#include "rmem.h"
+
+#if M_UNICODE
+
+// Converts a char string to Unicode
+
+dchar *Dchar::dup(char *p)
+{
+    dchar *s;
+    size_t len;
+
+    if (!p)
+	return NULL;
+    len = strlen(p);
+    s = (dchar *)mem.malloc((len + 1) * sizeof(dchar));
+    for (unsigned i = 0; i < len; i++)
+    {
+	s[i] = (dchar)(p[i] & 0xFF);
+    }
+    s[len] = 0;
+    return s;
+}
+
+dchar *Dchar::memchr(dchar *p, int c, int count)
+{
+    int u;
+
+    for (u = 0; u < count; u++)
+    {
+	if (p[u] == c)
+	    return p + u;
+    }
+    return NULL;
+}
+
+#if _WIN32 && __DMC__
+__declspec(naked)
+unsigned Dchar::calcHash(const dchar *str, unsigned len)
+{
+    __asm
+    {
+	mov	ECX,4[ESP]
+	mov	EDX,8[ESP]
+	xor	EAX,EAX
+	test	EDX,EDX
+	je	L92
+
+LC8:	cmp	EDX,1
+	je	L98
+	cmp	EDX,2
+	je	LAE
+
+	add	EAX,[ECX]
+//	imul	EAX,EAX,025h
+	lea	EAX,[EAX][EAX*8]
+	add	ECX,4
+	sub	EDX,2
+	jmp	LC8
+
+L98:	mov	DX,[ECX]
+	and	EDX,0FFFFh
+	add	EAX,EDX
+	ret
+
+LAE:	add	EAX,[ECX]
+L92:	ret
+    }
+}
+#else
+hash_t Dchar::calcHash(const dchar *str, size_t len)
+{
+    unsigned hash = 0;
+
+    for (;;)
+    {
+	switch (len)
+	{
+	    case 0:
+		return hash;
+
+	    case 1:
+		hash += *(const uint16_t *)str;
+		return hash;
+
+	    case 2:
+		hash += *(const uint32_t *)str;
+		return hash;
+
+	    default:
+		hash += *(const uint32_t *)str;
+		hash *= 37;
+		str += 2;
+		len -= 2;
+		break;
+	}
+    }
+}
+#endif
+
+hash_t Dchar::icalcHash(const dchar *str, size_t len)
+{
+    hash_t hash = 0;
+
+    for (;;)
+    {
+	switch (len)
+	{
+	    case 0:
+		return hash;
+
+	    case 1:
+		hash += *(const uint16_t *)str | 0x20;
+		return hash;
+
+	    case 2:
+		hash += *(const uint32_t *)str | 0x200020;
+		return hash;
+
+	    default:
+		hash += *(const uint32_t *)str | 0x200020;
+		hash *= 37;
+		str += 2;
+		len -= 2;
+		break;
+	}
+    }
+}
+
+#elif MCBS
+
+hash_t Dchar::calcHash(const dchar *str, size_t len)
+{
+    hash_t hash = 0;
+
+    while (1)
+    {
+	switch (len)
+	{
+	    case 0:
+		return hash;
+
+	    case 1:
+		hash *= 37;
+		hash += *(const uint8_t *)str;
+		return hash;
+
+	    case 2:
+		hash *= 37;
+		hash += *(const uint16_t *)str;
+		return hash;
+
+	    case 3:
+		hash *= 37;
+		hash += (*(const uint16_t *)str << 8) +
+			((const uint8_t *)str)[2];
+		return hash;
+
+	    default:
+		hash *= 37;
+		hash += *(const uint32_t *)str;
+		str += 4;
+		len -= 4;
+		break;
+	}
+    }
+}
+
+#elif UTF8
+
+// Specification is: http://anubis.dkuug.dk/JTC1/SC2/WG2/docs/n1335
+
+char Dchar::mblen[256] =
+{
+    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+    2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
+    2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
+    3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
+    4,4,4,4,4,4,4,4,5,5,5,5,6,6,1,1,
+};
+
+dchar *Dchar::dec(dchar *pstart, dchar *p)
+{
+    while ((p[-1] & 0xC0) == 0x80)
+	p--;
+    return p;
+}
+
+int Dchar::get(dchar *p)
+{
+    unsigned c;
+    unsigned char *q = (unsigned char *)p;
+
+    c = q[0];
+    switch (mblen[c])
+    {
+	case 2:
+	    c = ((c    - 0xC0) << 6) |
+		 (q[1] - 0x80);
+	    break;
+
+	case 3:
+	    c = ((c    - 0xE0) << 12) |
+		((q[1] - 0x80) <<  6) |
+		 (q[2] - 0x80);
+	    break;
+
+	case 4:
+	    c = ((c    - 0xF0) << 18) |
+		((q[1] - 0x80) << 12) |
+		((q[2] - 0x80) <<  6) |
+		 (q[3] - 0x80);
+	    break;
+
+	case 5:
+	    c = ((c    - 0xF8) << 24) |
+		((q[1] - 0x80) << 18) |
+		((q[2] - 0x80) << 12) |
+		((q[3] - 0x80) <<  6) |
+		 (q[4] - 0x80);
+	    break;
+
+	case 6:
+	    c = ((c    - 0xFC) << 30) |
+		((q[1] - 0x80) << 24) |
+		((q[2] - 0x80) << 18) |
+		((q[3] - 0x80) << 12) |
+		((q[4] - 0x80) <<  6) |
+		 (q[5] - 0x80);
+	    break;
+    }
+    return c;
+}
+
+dchar *Dchar::put(dchar *p, unsigned c)
+{
+    if (c <= 0x7F)
+    {
+	*p++ = c;
+    }
+    else if (c <= 0x7FF)
+    {
+	p[0] = 0xC0 + (c >> 6);
+	p[1] = 0x80 + (c & 0x3F);
+	p += 2;
+    }
+    else if (c <= 0xFFFF)
+    {
+	p[0] = 0xE0 + (c >> 12);
+	p[1] = 0x80 + ((c >> 6) & 0x3F);
+	p[2] = 0x80 + (c & 0x3F);
+	p += 3;
+    }
+    else if (c <= 0x1FFFFF)
+    {
+	p[0] = 0xF0 + (c >> 18);
+	p[1] = 0x80 + ((c >> 12) & 0x3F);
+	p[2] = 0x80 + ((c >> 6) & 0x3F);
+	p[3] = 0x80 + (c & 0x3F);
+	p += 4;
+    }
+    else if (c <= 0x3FFFFFF)
+    {
+	p[0] = 0xF8 + (c >> 24);
+	p[1] = 0x80 + ((c >> 18) & 0x3F);
+	p[2] = 0x80 + ((c >> 12) & 0x3F);
+	p[3] = 0x80 + ((c >> 6) & 0x3F);
+	p[4] = 0x80 + (c & 0x3F);
+	p += 5;
+    }
+    else if (c <= 0x7FFFFFFF)
+    {
+	p[0] = 0xFC + (c >> 30);
+	p[1] = 0x80 + ((c >> 24) & 0x3F);
+	p[2] = 0x80 + ((c >> 18) & 0x3F);
+	p[3] = 0x80 + ((c >> 12) & 0x3F);
+	p[4] = 0x80 + ((c >> 6) & 0x3F);
+	p[5] = 0x80 + (c & 0x3F);
+	p += 6;
+    }
+    else
+	assert(0);		// not a UCS-4 character
+    return p;
+}
+
+hash_t Dchar::calcHash(const dchar *str, size_t len)
+{
+    hash_t hash = 0;
+
+    while (1)
+    {
+	switch (len)
+	{
+	    case 0:
+		return hash;
+
+	    case 1:
+		hash *= 37;
+		hash += *(const uint8_t *)str;
+		return hash;
+
+	    case 2:
+		hash *= 37;
+#if __I86__
+		hash += *(const uint16_t *)str;
+#else
+		hash += str[0] * 256 + str[1];
+#endif
+		return hash;
+
+	    case 3:
+		hash *= 37;
+#if __I86__
+		hash += (*(const uint16_t *)str << 8) +
+			((const uint8_t *)str)[2];
+#else
+		hash += (str[0] * 256 + str[1]) * 256 + str[2];
+#endif
+		return hash;
+
+	    default:
+		hash *= 37;
+#if __I86__
+		hash += *(const uint32_t *)str;
+#else
+		hash += ((str[0] * 256 + str[1]) * 256 + str[2]) * 256 + str[3];
+#endif
+
+		str += 4;
+		len -= 4;
+		break;
+	}
+    }
+}
+
+#else // ascii
+
+hash_t Dchar::calcHash(const dchar *str, size_t len)
+{
+    hash_t hash = 0;
+
+    while (1)
+    {
+	switch (len)
+	{
+	    case 0:
+		return hash;
+
+	    case 1:
+		hash *= 37;
+		hash += *(const uint8_t *)str;
+		return hash;
+
+	    case 2:
+		hash *= 37;
+#if __I86__
+		hash += *(const uint16_t *)str;
+#else
+		hash += str[0] * 256 + str[1];
+#endif
+		return hash;
+
+	    case 3:
+		hash *= 37;
+#if __I86__
+		hash += (*(const uint16_t *)str << 8) +
+			((const uint8_t *)str)[2];
+#else
+		hash += (str[0] * 256 + str[1]) * 256 + str[2];
+#endif
+		return hash;
+
+	    default:
+		hash *= 37;
+#if __I86__
+		hash += *(const uint32_t *)str;
+#else
+		hash += ((str[0] * 256 + str[1]) * 256 + str[2]) * 256 + str[3];
+#endif
+		str += 4;
+		len -= 4;
+		break;
+	}
+    }
+}
+
+hash_t Dchar::icalcHash(const dchar *str, size_t len)
+{
+    hash_t hash = 0;
+
+    while (1)
+    {
+	switch (len)
+	{
+	    case 0:
+		return hash;
+
+	    case 1:
+		hash *= 37;
+		hash += *(const uint8_t *)str | 0x20;
+		return hash;
+
+	    case 2:
+		hash *= 37;
+		hash += *(const uint16_t *)str | 0x2020;
+		return hash;
+
+	    case 3:
+		hash *= 37;
+		hash += ((*(const uint16_t *)str << 8) +
+			 ((const uint8_t *)str)[2]) | 0x202020;
+		return hash;
+
+	    default:
+		hash *= 37;
+		hash += *(const uint32_t *)str | 0x20202020;
+		str += 4;
+		len -= 4;
+		break;
+	}
+    }
+}
+
+#endif
+
+#if 0
+#include <stdio.h>
+
+void main()
+{
+    // Print out values to hardcode into Dchar::mblen[]
+    int c;
+    int s;
+
+    for (c = 0; c < 256; c++)
+    {
+	s = 1;
+	if (c >= 0xC0 && c <= 0xDF)
+	    s = 2;
+	if (c >= 0xE0 && c <= 0xEF)
+	    s = 3;
+	if (c >= 0xF0 && c <= 0xF7)
+	    s = 4;
+	if (c >= 0xF8 && c <= 0xFB)
+	    s = 5;
+	if (c >= 0xFC && c <= 0xFD)
+	    s = 6;
+
+	printf("%d", s);
+	if ((c & 15) == 15)
+	    printf(",\n");
+	else
+	    printf(",");
+    }
+}
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd2/root/dchar.h	Mon Jun 01 19:02:20 2009 +0100
@@ -0,0 +1,194 @@
+
+// Copyright (c) 1999-2006 by Digital Mars
+// All Rights Reserved
+// written by Walter Bright
+// www.digitalmars.com
+// License for redistribution is by either the Artistic License
+// in artistic.txt, or the GNU General Public License in gnu.txt.
+// See the included readme.txt for details.
+
+
+#ifndef DCHAR_H
+#define DCHAR_H
+
+#if __GNUC__ && !_WIN32
+#include "gnuc.h"
+#endif
+
+#if _MSC_VER
+    // Disable useless warnings about unreferenced functions
+    #pragma warning (disable : 4514)
+#endif
+
+//#include "root.h"
+typedef size_t hash_t;
+
+#undef TEXT
+
+// NOTE: All functions accepting pointer arguments must not be NULL
+
+#if M_UNICODE
+
+#include <string.h>
+#include <wchar.h>
+
+typedef wchar_t dchar;
+#define TEXT(x)		L##x
+
+#define Dchar_mbmax	1
+
+struct Dchar
+{
+    static dchar *inc(dchar *p) { return p + 1; }
+    static dchar *dec(dchar *pstart, dchar *p) { (void)pstart; return p - 1; }
+    static int len(const dchar *p) { return wcslen(p); }
+    static dchar get(dchar *p) { return *p; }
+    static dchar getprev(dchar *pstart, dchar *p) { (void)pstart; return p[-1]; }
+    static dchar *put(dchar *p, dchar c) { *p = c; return p + 1; }
+    static int cmp(dchar *s1, dchar *s2)
+    {
+#if __DMC__
+	if (!*s1 && !*s2)	// wcscmp is broken
+	    return 0;
+#endif
+	return wcscmp(s1, s2);
+#if 0
+	return (*s1 == *s2)
+	    ? wcscmp(s1, s2)
+	    : ((int)*s1 - (int)*s2);
+#endif
+    }
+    static int memcmp(const dchar *s1, const dchar *s2, int nchars) { return ::memcmp(s1, s2, nchars * sizeof(dchar)); }
+    static int isDigit(dchar c) { return '0' <= c && c <= '9'; }
+    static int isAlpha(dchar c) { return iswalpha(c); }
+    static int isUpper(dchar c) { return iswupper(c); }
+    static int isLower(dchar c) { return iswlower(c); }
+    static int isLocaleUpper(dchar c) { return isUpper(c); }
+    static int isLocaleLower(dchar c) { return isLower(c); }
+    static int toLower(dchar c) { return isUpper(c) ? towlower(c) : c; }
+    static int toLower(dchar *p) { return toLower(*p); }
+    static int toUpper(dchar c) { return isLower(c) ? towupper(c) : c; }
+    static dchar *dup(dchar *p) { return ::_wcsdup(p); }	// BUG: out of memory?
+    static dchar *dup(char *p);
+    static dchar *chr(dchar *p, unsigned c) { return wcschr(p, (dchar)c); }
+    static dchar *rchr(dchar *p, unsigned c) { return wcsrchr(p, (dchar)c); }
+    static dchar *memchr(dchar *p, int c, int count);
+    static dchar *cpy(dchar *s1, dchar *s2) { return wcscpy(s1, s2); }
+    static dchar *str(dchar *s1, dchar *s2) { return wcsstr(s1, s2); }
+    static hash_t calcHash(const dchar *str, size_t len);
+
+    // Case insensitive versions
+    static int icmp(dchar *s1, dchar *s2) { return wcsicmp(s1, s2); }
+    static int memicmp(const dchar *s1, const dchar *s2, int nchars) { return ::wcsnicmp(s1, s2, nchars); }
+    static hash_t icalcHash(const dchar *str, size_t len);
+};
+
+#elif MCBS
+
+#include <limits.h>
+#include <mbstring.h>
+
+typedef char dchar;
+#define TEXT(x)		x
+
+#define Dchar_mbmax	MB_LEN_MAX
+
+#elif UTF8
+
+typedef char dchar;
+#define TEXT(x)		x
+
+#define Dchar_mbmax	6
+
+struct Dchar
+{
+    static char mblen[256];
+
+    static dchar *inc(dchar *p) { return p + mblen[*p & 0xFF]; }
+    static dchar *dec(dchar *pstart, dchar *p);
+    static int len(const dchar *p) { return strlen(p); }
+    static int get(dchar *p);
+    static int getprev(dchar *pstart, dchar *p)
+	{ return *dec(pstart, p) & 0xFF; }
+    static dchar *put(dchar *p, unsigned c);
+    static int cmp(dchar *s1, dchar *s2) { return strcmp(s1, s2); }
+    static int memcmp(const dchar *s1, const dchar *s2, int nchars) { return ::memcmp(s1, s2, nchars); }
+    static int isDigit(dchar c) { return '0' <= c && c <= '9'; }
+    static int isAlpha(dchar c) { return c <= 0x7F ? isalpha(c) : 0; }
+    static int isUpper(dchar c) { return c <= 0x7F ? isupper(c) : 0; }
+    static int isLower(dchar c) { return c <= 0x7F ? islower(c) : 0; }
+    static int isLocaleUpper(dchar c) { return isUpper(c); }
+    static int isLocaleLower(dchar c) { return isLower(c); }
+    static int toLower(dchar c) { return isUpper(c) ? tolower(c) : c; }
+    static int toLower(dchar *p) { return toLower(*p); }
+    static int toUpper(dchar c) { return isLower(c) ? toupper(c) : c; }
+    static dchar *dup(dchar *p) { return ::strdup(p); }	// BUG: out of memory?
+    static dchar *chr(dchar *p, int c) { return strchr(p, c); }
+    static dchar *rchr(dchar *p, int c) { return strrchr(p, c); }
+    static dchar *memchr(dchar *p, int c, int count)
+	{ return (dchar *)::memchr(p, c, count); }
+    static dchar *cpy(dchar *s1, dchar *s2) { return strcpy(s1, s2); }
+    static dchar *str(dchar *s1, dchar *s2) { return strstr(s1, s2); }
+    static hash_t calcHash(const dchar *str, size_t len);
+
+    // Case insensitive versions
+    static int icmp(dchar *s1, dchar *s2) { return _mbsicmp(s1, s2); }
+    static int memicmp(const dchar *s1, const dchar *s2, int nchars) { return ::_mbsnicmp(s1, s2, nchars); }
+};
+
+#else
+
+#include <string.h>
+
+#ifndef GCC_SAFE_DMD
+#include <ctype.h>
+#endif
+
+typedef char dchar;
+#define TEXT(x)		x
+
+#define Dchar_mbmax	1
+
+struct Dchar
+{
+    static dchar *inc(dchar *p) { return p + 1; }
+    static dchar *dec(dchar *pstart, dchar *p) { return p - 1; }
+    static int len(const dchar *p) { return strlen(p); }
+    static int get(dchar *p) { return *p & 0xFF; }
+    static int getprev(dchar *pstart, dchar *p) { return p[-1] & 0xFF; }
+    static dchar *put(dchar *p, unsigned c) { *p = c; return p + 1; }
+    static int cmp(dchar *s1, dchar *s2) { return strcmp(s1, s2); }
+    static int memcmp(const dchar *s1, const dchar *s2, int nchars) { return ::memcmp(s1, s2, nchars); }
+    static int isDigit(dchar c) { return '0' <= c && c <= '9'; }
+#ifndef GCC_SAFE_DMD
+    static int isAlpha(dchar c) { return isalpha(c); }
+    static int isUpper(dchar c) { return isupper(c); }
+    static int isLower(dchar c) { return islower(c); }
+    static int isLocaleUpper(dchar c) { return isupper(c); }
+    static int isLocaleLower(dchar c) { return islower(c); }
+    static int toLower(dchar c) { return isupper(c) ? tolower(c) : c; }
+    static int toLower(dchar *p) { return toLower(*p); }
+    static int toUpper(dchar c) { return islower(c) ? toupper(c) : c; }
+    static dchar *dup(dchar *p) { return ::strdup(p); }	// BUG: out of memory?
+#endif
+    static dchar *chr(dchar *p, int c) { return strchr(p, c); }
+    static dchar *rchr(dchar *p, int c) { return strrchr(p, c); }
+    static dchar *memchr(dchar *p, int c, int count)
+	{ return (dchar *)::memchr(p, c, count); }
+    static dchar *cpy(dchar *s1, dchar *s2) { return strcpy(s1, s2); }
+    static dchar *str(dchar *s1, dchar *s2) { return strstr(s1, s2); }
+    static hash_t calcHash(const dchar *str, size_t len);
+
+    // Case insensitive versions
+#ifdef __GNUC__
+    static int icmp(dchar *s1, dchar *s2) { return strcasecmp(s1, s2); }
+#else
+    static int icmp(dchar *s1, dchar *s2) { return stricmp(s1, s2); }
+#endif
+    static int memicmp(const dchar *s1, const dchar *s2, int nchars) { return ::memicmp(s1, s2, nchars); }
+    static hash_t icalcHash(const dchar *str, size_t len);
+};
+
+#endif
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd2/root/gnuc.c	Mon Jun 01 19:02:20 2009 +0100
@@ -0,0 +1,55 @@
+
+// Put functions in here missing from gnu C
+
+#include "gnuc.h"
+
+int memicmp(const char *s1, const char *s2, int n)
+{
+    int result = 0;
+
+    for (int i = 0; i < n; i++)
+    {	char c1 = s1[i];
+	char c2 = s2[i];
+
+	result = c1 - c2;
+	if (result)
+	{
+	    if ('A' <= c1 && c1 <= 'Z')
+		c1 += 'a' - 'A';
+	    if ('A' <= c2 && c2 <= 'Z')
+		c2 += 'a' - 'A';
+	    result = c1 - c2;
+	    if (result)
+		break;
+	}
+    }
+    return result;
+}
+
+int stricmp(const char *s1, const char *s2)
+{
+    int result = 0;
+
+    for (;;)
+    {	char c1 = *s1;
+	char c2 = *s2;
+
+	result = c1 - c2;
+	if (result)
+	{
+	    if ('A' <= c1 && c1 <= 'Z')
+		c1 += 'a' - 'A';
+	    if ('A' <= c2 && c2 <= 'Z')
+		c2 += 'a' - 'A';
+	    result = c1 - c2;
+	    if (result)
+		break;
+	}
+	if (!c1)
+	    break;
+	s1++;
+	s2++;
+    }
+    return result;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd2/root/gnuc.h	Mon Jun 01 19:02:20 2009 +0100
@@ -0,0 +1,8 @@
+
+#ifndef _GNUC_H
+#define _GNUC_H 1
+
+int memicmp(const char *s1, const char *s2, int n);
+int stricmp(const char *s1, const char *s2);
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd2/root/lstring.c	Mon Jun 01 19:02:20 2009 +0100
@@ -0,0 +1,63 @@
+// lstring.c
+
+// Copyright (c) 1999-2002 by Digital Mars
+// All Rights Reserved
+// written by Walter Bright
+// 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 <stdlib.h>
+
+#include "dchar.h"
+#include "rmem.h"
+#include "lstring.h"
+
+#ifdef _MSC_VER // prevent compiler internal crash
+Lstring Lstring::zero;
+#else
+Lstring Lstring::zero = LSTRING_EMPTY();
+#endif
+
+Lstring *Lstring::ctor(const dchar *p, unsigned length)
+{
+    Lstring *s;
+
+    s = alloc(length);
+    memcpy(s->string, p, length * sizeof(dchar));
+    return s;
+}
+
+Lstring *Lstring::alloc(unsigned length)
+{
+    Lstring *s;
+
+    s = (Lstring *)mem.malloc(size(length));
+    s->length = length;
+    s->string[length] = 0;
+    return s;
+}
+
+Lstring *Lstring::append(const Lstring *s)
+{
+    Lstring *t;
+
+    if (!s->length)
+	return this;
+    t = alloc(length + s->length);
+    memcpy(t->string, string, length * sizeof(dchar));
+    memcpy(t->string + length, s->string, s->length * sizeof(dchar));
+    return t;
+}
+
+Lstring *Lstring::substring(int start, int end)
+{
+    Lstring *t;
+
+    if (start == end)
+	return &zero;
+    t = alloc(end - start);
+    memcpy(t->string, string + start, (end - start) * sizeof(dchar));
+    return t;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd2/root/lstring.h	Mon Jun 01 19:02:20 2009 +0100
@@ -0,0 +1,72 @@
+
+// lstring.h
+// length-prefixed strings
+
+// Copyright (c) 1999-2002 by Digital Mars
+// All Rights Reserved
+// written by Walter Bright
+// www.digitalmars.com
+// License for redistribution is by either the Artistic License
+// in artistic.txt, or the GNU General Public License in gnu.txt.
+// See the included readme.txt for details.
+
+#ifndef LSTRING_H
+#define LSTRING_H 1
+
+#include "dchar.h"
+
+struct Lstring
+{
+    unsigned length;
+
+    // Disable warning about nonstandard extension
+    #pragma warning (disable : 4200)
+    dchar string[];
+
+    static Lstring zero;	// 0 length string
+
+    // No constructors because we want to be able to statically
+    // initialize Lstring's, and Lstrings are of variable size.
+
+    #if M_UNICODE
+    #define LSTRING(p,length) { length, L##p }
+    #else
+    #define LSTRING(p,length) { length, p }
+    #endif
+
+#if __GNUC__
+    #define LSTRING_EMPTY() { 0 }
+#else
+    #define LSTRING_EMPTY() LSTRING("", 0)
+#endif
+
+    static Lstring *ctor(const dchar *p) { return ctor(p, Dchar::len(p)); }
+    static Lstring *ctor(const dchar *p, unsigned length);
+    static unsigned size(unsigned length) { return sizeof(Lstring) + (length + 1) * sizeof(dchar); }
+    static Lstring *alloc(unsigned length);
+    Lstring *clone();
+
+    unsigned len() { return length; }
+
+    dchar *toDchars() { return string; }
+
+    hash_t hash() { return Dchar::calcHash(string, length); }
+    hash_t ihash() { return Dchar::icalcHash(string, length); }
+
+    static int cmp(const Lstring *s1, const Lstring *s2)
+    {
+	int c = s2->length - s1->length;
+	return c ? c : Dchar::memcmp(s1->string, s2->string, s1->length);
+    }
+
+    static int icmp(const Lstring *s1, const Lstring *s2)
+    {
+	int c = s2->length - s1->length;
+	return c ? c : Dchar::memicmp(s1->string, s2->string, s1->length);
+    }
+
+    Lstring *append(const Lstring *s);
+    Lstring *substring(int start, int end);
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd2/root/man.c	Mon Jun 01 19:02:20 2009 +0100
@@ -0,0 +1,100 @@
+
+// Compiler implementation of the D programming language
+// Copyright (c) 2008-2009 by Digital Mars
+// All Rights Reserved
+// written by Walter Bright
+// http://www.digitalmars.com
+// License for redistribution is by either the Artistic License
+// in artistic.txt, or the GNU General Public License in gnu.txt.
+// See the included readme.txt for details.
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <assert.h>
+
+#if _WIN32
+
+#include <windows.h>
+
+#pragma comment(lib,"shell32.lib")
+
+void browse(const char *url)
+{
+    ShellExecute(NULL, "open", url, NULL, NULL, SW_SHOWNORMAL);
+}
+
+#endif
+
+#if linux || __FreeBSD__ || __sun&&__SVR4
+
+#include	<sys/types.h>
+#include	<sys/wait.h>
+#include	<unistd.h>
+
+void browse(const char *url)
+{
+    pid_t childpid;
+    const char *args[3];
+
+    char *browser = getenv("BROWSER");
+    if (browser)
+	browser = strdup(browser);
+    else
+	browser = "x-www-browser";
+
+    args[0] = browser;
+    args[1] = url;
+    args[2] = NULL;
+
+    childpid = fork();
+    if (childpid == 0)
+    {
+	execvp(args[0], (char**)args);
+	perror(args[0]);		// failed to execute
+	return;
+    }
+}
+
+#endif
+
+#if __APPLE__
+
+#include	<sys/types.h>
+#include	<sys/wait.h>
+#include	<unistd.h>
+
+void browse(const char *url)
+{
+    pid_t childpid;
+    const char *args[5];
+
+    char *browser = getenv("BROWSER");
+    if (browser)
+    {	browser = strdup(browser);
+	args[0] = browser;
+	args[1] = url;
+	args[2] = NULL;
+    }
+    else
+    {
+	//browser = "/Applications/Safari.app/Contents/MacOS/Safari";
+	args[0] = "open";
+	args[1] = "-a";
+	args[2] = "/Applications/Safari.app";
+	args[3] = url;
+	args[4] = NULL;
+    }
+
+    childpid = fork();
+    if (childpid == 0)
+    {
+	execvp(args[0], (char**)args);
+	perror(args[0]);		// failed to execute
+	return;
+    }
+}
+
+#endif
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd2/root/port.c	Mon Jun 01 19:02:20 2009 +0100
@@ -0,0 +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;
+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
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd2/root/port.h	Mon Jun 01 19:02:20 2009 +0100
@@ -0,0 +1,78 @@
+
+// Copyright (c) 1999-2009 by Digital Mars
+// All Rights Reserved
+// written by Walter Bright
+// http://www.digitalmars.com
+
+#ifndef PORT_H
+#define PORT_H
+
+// Portable wrapper around compiler/system specific things.
+// The idea is to minimize #ifdef's in the app code.
+
+#ifndef TYPEDEFS
+#define TYPEDEFS
+
+#include <wchar.h>
+
+#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;
+#endif
+
+#endif
+
+typedef double d_time;
+
+struct Port
+{
+    static double nan;
+    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
+    #undef isnan
+    #undef isfinite
+    #undef isinfinity
+    #undef signbit
+#endif
+    static int isNan(double);
+    static int isNan(long double);
+
+    static int isSignallingNan(double);
+    static int isSignallingNan(long double);
+
+    static int isFinite(double);
+    static int isInfinity(double);
+    static int Signbit(double);
+
+    static double floor(double);
+    static double pow(double x, double y);
+
+    static ulonglong strtoull(const char *p, char **pend, int base);
+
+    static char *ull_to_string(char *buffer, ulonglong ull);
+    static wchar_t *ull_to_string(wchar_t *buffer, ulonglong ull);
+
+    // Convert ulonglong to double
+    static double ull_to_double(ulonglong ull);
+
+    // Get locale-dependent list separator
+    static const char *list_separator();
+    static const wchar_t *wlist_separator();
+
+    static char *strupr(char *);
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd2/root/response.c	Mon Jun 01 19:02:20 2009 +0100
@@ -0,0 +1,278 @@
+// Copyright (C) 1990-1998 by Symantec
+// Copyright (C) 2000-2009 by Digital Mars
+// All Rights Reserved
+// http://www.digitalmars.com
+// Written by Walter Bright
+/*
+ * This source file is made available for personal use
+ * only. The license is in /dmd/src/dmd/backendlicense.txt
+ * For any other uses, please contact Digital Mars.
+ */
+
+#include <stdio.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+
+#if !__DMC__
+#include <sys/stat.h>
+#endif
+
+#if _WIN32
+#include <tchar.h>
+#include <io.h>
+#endif
+
+#if linux || __APPLE__ || __FreeBSD__ || __sun&&__SVR4
+#include <sys/types.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <unistd.h>
+#include <utime.h>
+#endif
+
+/*********************************
+ * #include <stdlib.h>
+ * int response_expand(int *pargc,char ***pargv);
+ *
+ * Expand any response files in command line.
+ * Response files are arguments that look like:
+ *   @NAME
+ * The name is first searched for in the environment. If it is not
+ * there, it is searched for as a file name.
+ * Arguments are separated by spaces, tabs, or newlines. These can be
+ * imbedded within arguments by enclosing the argument in '' or "".
+ * Recursively expands nested response files.
+ *
+ * To use, put the line:
+ *   response_expand(&argc,&argv);
+ * as the first executable statement in main(int argc, char **argv).
+ * argc and argv are adjusted to be the new command line arguments
+ * after response file expansion.
+ *
+ * Digital Mars's MAKE program can be notified that a program can accept
+ * long command lines via environment variables by preceding the rule
+ * line for the program with a *.
+ *
+ * Returns:
+ *   0   success
+ *   !=0   failure (argc, argv unchanged)
+ */
+
+struct Narg
+{   
+    int argc;   /* arg count      */
+    int argvmax;   /* dimension of nargv[]   */
+    char **argv;
+};
+
+static int addargp(struct Narg *n, char *p)
+{
+    /* The 2 is to always allow room for a NULL argp at the end   */
+    if (n->argc + 2 >= n->argvmax)
+    {   
+        n->argvmax = n->argc + 2;
+        n->argv = (char **) realloc(n->argv,n->argvmax * sizeof(char *));
+        if (!n->argv)
+            return 1;
+    }
+    n->argv[n->argc++] = p;
+    return 0;
+}
+
+int response_expand(int *pargc, char ***pargv)
+{
+    struct Narg n;
+    int i;
+    char *cp;
+    int recurse = 0;
+
+    n.argc = 0;
+    n.argvmax = 0;      /* dimension of n.argv[]      */
+    n.argv = NULL;
+    for(i=0; i<*pargc; ++i)
+    {
+        cp = (*pargv)[i];
+        if (*cp == '@')
+        {
+            char *buffer;
+            char *bufend;
+            char *p;
+
+            cp++;
+            p = getenv(cp);
+            if (p)
+            {
+                buffer = strdup(p);
+                if (!buffer)
+                    goto noexpand;
+                bufend = buffer + strlen(buffer);
+            }
+            else
+            {   
+                long length;
+                int fd;
+                int nread;
+                size_t len;
+
+#if __DMC__
+                length = filesize(cp);
+#else
+		struct stat statbuf;
+		if (stat(cp, &statbuf))
+		    goto noexpand;
+		length = statbuf.st_size;
+#endif
+                if (length & 0xF0000000)   /* error or file too big */
+                    goto noexpand;
+                len = length;
+                buffer = (char *)malloc(len + 1);
+                if (!buffer)
+                    goto noexpand;
+                bufend = &buffer[len];
+                /* Read file into buffer   */
+#if _WIN32
+                fd = open(cp,O_RDONLY|O_BINARY);
+#else
+                fd = open(cp,O_RDONLY);
+#endif
+                if (fd == -1)
+                    goto noexpand;
+                nread = read(fd,buffer,len);
+                close(fd);
+
+                if (nread != len)
+                    goto noexpand;
+            }
+
+            // The logic of this should match that in setargv()
+
+            for (p = buffer; p < bufend; p++)
+            {   
+                char *d;
+                char c,lastc;
+                unsigned char instring;
+                int num_slashes,non_slashes;
+
+                switch (*p)
+                {   
+                    case 26:      /* ^Z marks end of file      */
+                        goto L2;
+
+                    case 0xD:
+                    case 0:
+                    case ' ':
+                    case '\t':
+                    case '\n':
+                        continue;   // scan to start of argument
+
+                    case '@':
+                        recurse = 1;
+                    default:      /* start of new argument   */
+                        if (addargp(&n,p))
+                            goto noexpand;
+                        instring = 0;
+                        c = 0;
+                        num_slashes = 0;
+                        for (d = p; 1; p++)
+                        {
+                            lastc = c;
+                            if (p >= bufend)
+                                goto Lend;
+                            c = *p;
+                            switch (c)
+                            {
+                                case '"':
+                                    /* 
+                                        Yes this looks strange,but this is so that we are
+                                        MS Compatible, tests have shown that:
+                                        \\\\"foo bar"  gets passed as \\foo bar
+                                        \\\\foo  gets passed as \\\\foo
+                                        \\\"foo gets passed as \"foo  
+                                        and \"foo gets passed as "foo in VC!
+                                     */
+                                    non_slashes = num_slashes % 2; 
+                                    num_slashes = num_slashes / 2;
+                                    for (; num_slashes > 0; num_slashes--)
+                                    {
+                                        d--;
+                                        *d = '\0';
+                                    }
+                                    
+                                    if (non_slashes)
+                                    {
+                                        *(d-1) = c;
+                                    }
+                                    else
+                                    {
+                                        instring ^= 1;
+                                    }
+                                    break;
+                                case 26:
+                            Lend:
+                                    *d = 0;      // terminate argument
+                                    goto L2;
+
+                                case 0xD:      // CR
+                                    c = lastc;
+                                    continue;      // ignore
+
+                                case '@':
+                                    recurse = 1;
+                                    goto Ladd;
+
+                                case ' ':
+                                case '\t':
+                                    if (!instring)
+                                    {
+                                case '\n':
+                                case 0:
+                                        *d = 0;      // terminate argument
+                                        goto Lnextarg;
+                                    }
+                                default:
+                                Ladd:
+                                    if (c == '\\')
+                                        num_slashes++;
+                                    else
+                                        num_slashes = 0;
+                                    *d++ = c;
+                                    break;
+                            }
+#ifdef _MBCS
+                            if (_istlead (c)) {
+                                *d++ = *++p;
+                                if (*(d - 1) == '\0') {
+                                    d--;
+                                    goto Lnextarg;
+                                }
+                            }
+#endif
+                        }
+                    break;
+                }
+            Lnextarg:
+                ;
+            }
+        L2:
+            ;
+        }
+        else if (addargp(&n,(*pargv)[i]))
+            goto noexpand;
+    }
+    n.argv[n.argc] = NULL;
+    if (recurse)
+    {   
+        /* Recursively expand @filename   */
+        if (response_expand(&n.argc,&n.argv))
+            goto noexpand;
+    }
+    *pargc = n.argc;
+    *pargv = n.argv;
+    return 0;            /* success         */
+
+noexpand:            /* error         */
+    free(n.argv);
+    /* BUG: any file buffers are not free'd   */
+    return 1;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd2/root/rmem.h	Mon Jun 01 19:02:20 2009 +0100
@@ -0,0 +1,51 @@
+// Copyright (C) 2000-2001 by Chromium Communications
+// All Rights Reserved
+
+#ifndef ROOT_MEM_H
+#define ROOT_MEM_H
+
+#include <stddef.h>	// for size_t
+
+typedef void (*FINALIZERPROC)(void* pObj, void* pClientData);
+
+struct GC;			// thread specific allocator
+
+struct Mem
+{
+    GC *gc;			// pointer to our thread specific allocator
+    Mem() { gc = NULL; }
+
+    void init();
+
+    // Derive from Mem to get these storage allocators instead of global new/delete
+    void * operator new(size_t m_size);
+    void * operator new(size_t m_size, Mem *mem);
+    void * operator new(size_t m_size, GC *gc);
+    void operator delete(void *p);
+
+    void * operator new[](size_t m_size);
+    void operator delete[](void *p);
+
+    char *strdup(const char *s);
+    void *malloc(size_t size);
+    void *malloc_uncollectable(size_t size);
+    void *calloc(size_t size, size_t n);
+    void *realloc(void *p, size_t size);
+    void free(void *p);
+    void free_uncollectable(void *p);
+    void *mallocdup(void *o, size_t size);
+    void error();
+    void check(void *p);	// validate pointer
+    void fullcollect();		// do full garbage collection
+    void fullcollectNoStack();	// do full garbage collection, no scan stack
+    void mark(void *pointer);
+    void addroots(char* pStart, char* pEnd);
+    void removeroots(char* pStart);
+    void setFinalizer(void* pObj, FINALIZERPROC pFn, void* pClientData);
+    void setStackBottom(void *bottom);
+    GC *getThreadGC();		// get apartment allocator for this thread
+};
+
+extern Mem mem;
+
+#endif /* ROOT_MEM_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd2/root/root.c	Mon Jun 01 19:02:20 2009 +0100
@@ -0,0 +1,1948 @@
+
+// Copyright (c) 1999-2009 by Digital Mars
+// All Rights Reserved
+// written by Walter Bright
+// 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.
+
+#define POSIX (linux || __APPLE__ || __FreeBSD__ || __sun&&__SVR4)
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <stdint.h>
+#include <assert.h>
+
+#if (defined (__SVR4) && defined (__sun))
+#include <alloca.h>
+#endif
+
+#if _MSC_VER ||__MINGW32__
+#include <malloc.h>
+#include <string>
+#endif
+
+#if _WIN32
+#include <windows.h>
+#include <direct.h>
+#endif
+
+#if POSIX
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <unistd.h>
+#include <utime.h>
+#endif
+
+#include "port.h"
+#include "root.h"
+#include "dchar.h"
+#include "rmem.h"
+
+#if 0 //__SC__ //def DEBUG
+extern "C" void __cdecl _assert(void *e, void *f, unsigned line)
+{
+    printf("Assert('%s','%s',%d)\n",e,f,line);
+    fflush(stdout);
+    *(char *)0 = 0;
+}
+#endif
+
+
+/*************************************
+ * Convert wchar string to ascii string.
+ */
+
+char *wchar2ascii(wchar_t *us)
+{
+    return wchar2ascii(us, wcslen(us));
+}
+
+char *wchar2ascii(wchar_t *us, unsigned len)
+{
+    unsigned i;
+    char *p;
+
+    p = (char *)mem.malloc(len + 1);
+    for (i = 0; i <= len; i++)
+	p[i] = (char) us[i];
+    return p;
+}
+
+int wcharIsAscii(wchar_t *us)
+{
+    return wcharIsAscii(us, wcslen(us));
+}
+
+int wcharIsAscii(wchar_t *us, unsigned len)
+{
+    unsigned i;
+
+    for (i = 0; i <= len; i++)
+    {
+	if (us[i] & ~0xFF)	// if high bits set
+	    return 0;		// it's not ascii
+    }
+    return 1;
+}
+
+
+/***********************************
+ * Compare length-prefixed strings (bstr).
+ */
+
+int bstrcmp(unsigned char *b1, unsigned char *b2)
+{
+    return (*b1 == *b2 && memcmp(b1 + 1, b2 + 1, *b2) == 0) ? 0 : 1;
+}
+
+/***************************************
+ * Convert bstr into a malloc'd string.
+ */
+
+char *bstr2str(unsigned char *b)
+{
+    char *s;
+    unsigned len;
+
+    len = *b;
+    s = (char *) mem.malloc(len + 1);
+    s[len] = 0;
+    return (char *)memcpy(s,b + 1,len);
+}
+
+/**************************************
+ * Print error message and exit.
+ */
+
+void error(const char *format, ...)
+{
+    va_list ap;
+
+    va_start(ap, format);
+    printf("Error: ");
+    vprintf(format, ap);
+    va_end( ap );
+    printf("\n");
+    fflush(stdout);
+
+    exit(EXIT_FAILURE);
+}
+
+#if M_UNICODE
+void error(const dchar *format, ...)
+{
+    va_list ap;
+
+    va_start(ap, format);
+    printf("Error: ");
+    vwprintf(format, ap);
+    va_end( ap );
+    printf("\n");
+    fflush(stdout);
+
+    exit(EXIT_FAILURE);
+}
+#endif
+
+void error_mem()
+{
+    error("out of memory");
+}
+
+/**************************************
+ * Print warning message.
+ */
+
+void warning(const char *format, ...)
+{
+    va_list ap;
+
+    va_start(ap, format);
+    printf("Warning: ");
+    vprintf(format, ap);
+    va_end( ap );
+    printf("\n");
+    fflush(stdout);
+}
+
+/****************************** Object ********************************/
+
+int Object::equals(Object *o)
+{
+    return o == this;
+}
+
+hash_t Object::hashCode()
+{
+    return (hash_t) this;
+}
+
+int Object::compare(Object *obj)
+{
+    return this - obj;
+}
+
+void Object::print()
+{
+    printf("%s %p\n", toChars(), this);
+}
+
+char *Object::toChars()
+{
+    return (char *)"Object";
+}
+
+dchar *Object::toDchars()
+{
+#if M_UNICODE
+    return L"Object";
+#else
+    return toChars();
+#endif
+}
+
+int Object::dyncast()
+{
+    return 0;
+}
+
+void Object::toBuffer(OutBuffer *b)
+{
+    b->writestring("Object");
+}
+
+void Object::mark()
+{
+}
+
+/****************************** String ********************************/
+
+String::String(char *str, int ref)
+{
+    this->str = ref ? str : mem.strdup(str);
+    this->ref = ref;
+}
+
+String::~String()
+{
+    mem.free(str);
+}
+
+void String::mark()
+{
+    mem.mark(str);
+}
+
+hash_t String::calcHash(const char *str, size_t len)
+{
+    hash_t hash = 0;
+
+    for (;;)
+    {
+	switch (len)
+	{
+	    case 0:
+		return hash;
+
+	    case 1:
+		hash *= 37;
+		hash += *(uint8_t *)str;
+		return hash;
+
+	    case 2:
+		hash *= 37;
+		hash += *(uint16_t *)str;
+		return hash;
+
+	    case 3:
+		hash *= 37;
+		hash += (*(uint16_t *)str << 8) +
+			((uint8_t *)str)[2];
+		return hash;
+
+	    default:
+		hash *= 37;
+		hash += *(uint32_t *)str;
+		str += 4;
+		len -= 4;
+		break;
+	}
+    }
+}
+
+hash_t String::calcHash(const char *str)
+{
+    return calcHash(str, strlen(str));
+}
+
+hash_t String::hashCode()
+{
+    return calcHash(str, strlen(str));
+}
+
+unsigned String::len()
+{
+    return strlen(str);
+}
+
+int String::equals(Object *obj)
+{
+    return strcmp(str,((String *)obj)->str) == 0;
+}
+
+int String::compare(Object *obj)
+{
+    return strcmp(str,((String *)obj)->str);
+}
+
+char *String::toChars()
+{
+    return str;
+}
+
+void String::print()
+{
+    printf("String '%s'\n",str);
+}
+
+
+/****************************** FileName ********************************/
+
+FileName::FileName(char *str, int ref)
+    : String(str,ref)
+{
+}
+
+char *FileName::combine(const char *path, const char *name)
+{   char *f;
+    size_t pathlen;
+    size_t namelen;
+
+    if (!path || !*path)
+	return (char *)name;
+    pathlen = strlen(path);
+    namelen = strlen(name);
+    f = (char *)mem.malloc(pathlen + 1 + namelen + 1);
+    memcpy(f, path, pathlen);
+#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;
+}
+
+FileName::FileName(char *path, char *name)
+    : String(combine(path,name),1)
+{
+}
+
+// Split a path into an Array of paths
+Array *FileName::splitPath(const char *path)
+{
+    char c = 0;				// unnecessary initializer is for VC /W4
+    const char *p;
+    OutBuffer buf;
+    Array *array;
+
+    array = new Array();
+    if (path)
+    {
+	p = path;
+	do
+	{   char instring = 0;
+
+	    while (isspace(*p))		// skip leading whitespace
+		p++;
+	    buf.reserve(strlen(p) + 1);	// guess size of path
+	    for (; ; p++)
+	    {
+		c = *p;
+		switch (c)
+		{
+		    case '"':
+			instring ^= 1;	// toggle inside/outside of string
+			continue;
+
+#if MACINTOSH
+		    case ',':
+#endif
+#if _WIN32
+		    case ';':
+#endif
+#if POSIX
+		    case ':':
+#endif
+			p++;
+			break;		// note that ; cannot appear as part
+					// of a path, quotes won't protect it
+
+		    case 0x1A:		// ^Z means end of file
+		    case 0:
+			break;
+
+		    case '\r':
+			continue;	// ignore carriage returns
+
+#if POSIX
+		    case '~':
+			buf.writestring(getenv("HOME"));
+			continue;
+#endif
+
+		    case ' ':
+		    case '\t':		// tabs in filenames?
+			if (!instring)	// if not in string
+			    break;	// treat as end of path
+		    default:
+			buf.writeByte(c);
+			continue;
+		}
+		break;
+	    }
+	    if (buf.offset)		// if path is not empty
+	    {
+		buf.writeByte(0);	// to asciiz
+		array->push(buf.extractData());
+	    }
+	} while (c);
+    }
+    return array;
+}
+
+hash_t FileName::hashCode()
+{
+#if _WIN32
+    // We need a different hashCode because it must be case-insensitive
+    size_t len = strlen(str);
+    hash_t hash = 0;
+    unsigned char *s = (unsigned char *)str;
+
+    for (;;)
+    {
+	switch (len)
+	{
+	    case 0:
+		return hash;
+
+	    case 1:
+		hash *= 37;
+		hash += *(uint8_t *)s | 0x20;
+		return hash;
+
+	    case 2:
+		hash *= 37;
+		hash += *(uint16_t *)s | 0x2020;
+		return hash;
+
+	    case 3:
+		hash *= 37;
+		hash += ((*(uint16_t *)s << 8) +
+			 ((uint8_t *)s)[2]) | 0x202020;
+		break;
+
+	    default:
+		hash *= 37;
+		hash += *(uint32_t *)s | 0x20202020;
+		s += 4;
+		len -= 4;
+		break;
+	}
+    }
+#else
+    // darwin HFS is case insensitive, though...
+    return String::hashCode();
+#endif
+}
+
+int FileName::compare(Object *obj)
+{
+    return compare(str, ((FileName *)obj)->str);
+}
+
+int FileName::compare(const char *name1, const char *name2)
+{
+#if _WIN32
+    return stricmp(name1, name2);
+#else
+    return strcmp(name1, name2);
+#endif
+}
+
+int FileName::equals(Object *obj)
+{
+    return compare(obj) == 0;
+}
+
+int FileName::equals(const char *name1, const char *name2)
+{
+    return compare(name1, name2) == 0;
+}
+
+/************************************
+ * Return !=0 if absolute path name.
+ */
+
+int FileName::absolute(const char *name)
+{
+#if _WIN32
+    return (*name == '\\') ||
+	   (*name == '/')  ||
+	   (*name && name[1] == ':');
+#elif POSIX
+    return (*name == '/');
+#else
+    assert(0);
+#endif
+}
+
+/********************************
+ * Return filename extension (read-only).
+ * Points past '.' of extension.
+ * If there isn't one, return NULL.
+ */
+
+char *FileName::ext(const char *str)
+{
+    char *e;
+    size_t len = strlen(str);
+
+    e = (char *)str + len;
+    for (;;)
+    {
+	switch (*e)
+	{   case '.':
+		return e + 1;
+#if POSIX
+	    case '/':
+	        break;
+#endif
+#if _WIN32
+	    case '\\':
+	    case ':':
+	    case '/':
+		break;
+#endif
+	    default:
+		if (e == str)
+		    break;
+		e--;
+		continue;
+	}
+	return NULL;
+    }
+}
+
+char *FileName::ext()
+{
+    return ext(str);
+}
+
+/********************************
+ * Return mem.malloc'd filename with extension removed.
+ */
+
+char *FileName::removeExt(const char *str)
+{
+    const char *e = ext(str);
+    if (e)
+    {	size_t len = (e - str) - 1;
+	char *n = (char *)mem.malloc(len + 1);
+	memcpy(n, str, len);
+	n[len] = 0;
+	return n;
+    }
+    return mem.strdup(str);
+}
+
+/********************************
+ * Return filename name excluding path (read-only).
+ */
+
+char *FileName::name(const char *str)
+{
+    char *e;
+    size_t len = strlen(str);
+
+    e = (char *)str + len;
+    for (;;)
+    {
+	switch (*e)
+	{
+#if POSIX
+	    case '/':
+	       return e + 1;
+#endif
+#if _WIN32
+	    case '/':
+	    case '\\':
+		return e + 1;
+	    case ':':
+		/* The ':' is a drive letter only if it is the second
+		 * character or the last character,
+		 * otherwise it is an ADS (Alternate Data Stream) separator.
+		 * Consider ADS separators as part of the file name.
+		 */
+		if (e == str + 1 || e == str + len - 1)
+		    return e + 1;
+#endif
+	    default:
+		if (e == str)
+		    break;
+		e--;
+		continue;
+	}
+	return e;
+    }
+}
+
+char *FileName::name()
+{
+    return name(str);
+}
+
+/**************************************
+ * Return path portion of str.
+ * Path will does not include trailing path separator.
+ */
+
+char *FileName::path(const char *str)
+{
+    char *n = name(str);
+    char *path;
+    size_t pathlen;
+
+    if (n > str)
+    {
+#if POSIX
+	if (n[-1] == '/')
+	    n--;
+#elif _WIN32
+	if (n[-1] == '\\' || n[-1] == '/')
+	    n--;
+#else
+	assert(0);
+#endif
+    }
+    pathlen = n - str;
+    path = (char *)mem.malloc(pathlen + 1);
+    memcpy(path, str, pathlen);
+    path[pathlen] = 0;
+    return path;
+}
+
+/**************************************
+ * Replace filename portion of path.
+ */
+
+const char *FileName::replaceName(const char *path, const char *name)
+{   char *f;
+    char *n;
+    size_t pathlen;
+    size_t namelen;
+
+    if (absolute(name))
+	return name;
+
+    n = FileName::name(path);
+    if (n == path)
+	return name;
+    pathlen = n - path;
+    namelen = strlen(name);
+    f = (char *)mem.malloc(pathlen + 1 + namelen + 1);
+    memcpy(f, path, pathlen);
+#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;
+}
+
+/***************************
+ */
+
+FileName *FileName::defaultExt(const char *name, const char *ext)
+{
+    char *e;
+    char *s;
+    size_t len;
+    size_t extlen;
+
+    e = FileName::ext(name);
+    if (e)				// if already has an extension
+	return new FileName((char *)name, 0);
+
+    len = strlen(name);
+    extlen = strlen(ext);
+    s = (char *)alloca(len + 1 + extlen + 1);
+    memcpy(s,name,len);
+    s[len] = '.';
+    memcpy(s + len + 1, ext, extlen + 1);
+    return new FileName(s, 0);
+}
+
+/***************************
+ */
+
+FileName *FileName::forceExt(const char *name, const char *ext)
+{
+    char *e;
+    char *s;
+    size_t len;
+    size_t extlen;
+
+    e = FileName::ext(name);
+    if (e)				// if already has an extension
+    {
+	len = e - name;
+	extlen = strlen(ext);
+
+	s = (char *)alloca(len + extlen + 1);
+	memcpy(s,name,len);
+	memcpy(s + len, ext, extlen + 1);
+	return new FileName(s, 0);
+    }
+    else
+	return defaultExt(name, ext);	// doesn't have one
+}
+
+/******************************
+ * Return !=0 if extensions match.
+ */
+
+int FileName::equalsExt(const char *ext)
+{   const char *e;
+
+    e = FileName::ext();
+    if (!e && !ext)
+	return 1;
+    if (!e || !ext)
+	return 0;
+#if POSIX
+    return strcmp(e,ext) == 0;
+#elif _WIN32
+    return stricmp(e,ext) == 0;
+#else
+    assert(0);
+#endif
+}
+
+/*************************************
+ * Copy file from this to to.
+ */
+
+void FileName::CopyTo(FileName *to)
+{
+    File file(this);
+
+#if _WIN32
+    file.touchtime = mem.malloc(sizeof(WIN32_FIND_DATAA));	// keep same file time
+#elif POSIX
+    file.touchtime = mem.malloc(sizeof(struct stat)); // keep same file time
+#else
+    assert(0);
+#endif
+    file.readv();
+    file.name = to;
+    file.writev();
+}
+
+/*************************************
+ * Search Path for file.
+ * Input:
+ *	cwd	if !=0, search current directory before searching path
+ */
+
+char *FileName::searchPath(Array *path, const char *name, int cwd)
+{
+    if (absolute(name))
+    {
+	return exists(name) ? (char *)name : NULL;
+    }
+    if (cwd)
+    {
+	if (exists(name))
+	    return (char *)name;
+    }
+    if (path)
+    {	unsigned i;
+
+	for (i = 0; i < path->dim; i++)
+	{
+	    char *p = (char *)path->data[i];
+	    char *n = combine(p, name);
+
+	    if (exists(n))
+		return n;
+	}
+    }
+    return NULL;
+}
+
+int FileName::exists(const char *name)
+{
+#if POSIX
+    struct stat st;
+
+    if (stat(name, &st) < 0)
+	return 0;
+    if (S_ISDIR(st.st_mode))
+	return 2;
+    return 1;
+#elif _WIN32
+    DWORD dw;
+    int result;
+
+    dw = GetFileAttributesA(name);
+    if (dw == -1L)
+	result = 0;
+    else if (dw & FILE_ATTRIBUTE_DIRECTORY)
+	result = 2;
+    else
+	result = 1;
+    return result;
+#else
+    assert(0);
+#endif
+}
+
+void FileName::ensurePathExists(const char *path)
+{
+    //printf("FileName::ensurePathExists(%s)\n", path ? path : "");
+    if (path && *path)
+    {
+	if (!exists(path))
+	{
+	    char *p = FileName::path(path);
+	    if (*p)
+	    {
+#if _WIN32
+		size_t len = strlen(path);
+		if (len > 2 && p[-1] == ':' && path + 2 == p)
+		{   mem.free(p);
+		    return;
+		}
+#endif
+		ensurePathExists(p);
+		mem.free(p);
+	    }
+#if _WIN32
+	    if (path[strlen(path) - 1] != '\\')
+#endif
+#if POSIX
+	    if (path[strlen(path) - 1] != '\\')
+#endif
+	    {
+		//printf("mkdir(%s)\n", path);
+#if _WIN32
+		if (mkdir(path))
+#endif
+#if POSIX
+		if (mkdir(path, 0777))
+#endif
+		    error("cannot create directory %s", path);
+	    }
+	}
+    }
+}
+
+/****************************** File ********************************/
+
+File::File(FileName *n)
+{
+    ref = 0;
+    buffer = NULL;
+    len = 0;
+    touchtime = NULL;
+    name = n;
+}
+
+File::File(char *n)
+{
+    ref = 0;
+    buffer = NULL;
+    len = 0;
+    touchtime = NULL;
+    name = new FileName(n, 0);
+}
+
+File::~File()
+{
+    if (buffer)
+    {
+	if (ref == 0)
+	    mem.free(buffer);
+#if _WIN32
+	else if (ref == 2)
+	    UnmapViewOfFile(buffer);
+#endif
+    }
+    if (touchtime)
+	mem.free(touchtime);
+}
+
+void File::mark()
+{
+    mem.mark(buffer);
+    mem.mark(touchtime);
+    mem.mark(name);
+}
+
+/*************************************
+ */
+
+int File::read()
+{
+#if POSIX
+    off_t size;
+    ssize_t numread;
+    int fd;
+    struct stat buf;
+    int result = 0;
+    char *name;
+
+    name = this->name->toChars();
+    //printf("File::read('%s')\n",name);
+    fd = open(name, O_RDONLY);
+    if (fd == -1)
+    {	result = errno;
+	//printf("\topen error, errno = %d\n",errno);
+	goto err1;
+    }
+
+    if (!ref)
+	mem.free(buffer);
+    ref = 0;       // we own the buffer now
+
+    //printf("\tfile opened\n");
+    if (fstat(fd, &buf))
+    {
+	printf("\tfstat error, errno = %d\n",errno);
+        goto err2;
+    }
+    size = buf.st_size;
+    buffer = (unsigned char *) mem.malloc(size + 2);
+    if (!buffer)
+    {
+	printf("\tmalloc error, errno = %d\n",errno);
+	goto err2;
+    }
+
+    numread = ::read(fd, buffer, size);
+    if (numread != size)
+    {
+	printf("\tread error, errno = %d\n",errno);
+	goto err2;
+    }
+
+    if (touchtime)
+        memcpy(touchtime, &buf, sizeof(buf));
+
+    if (close(fd) == -1)
+    {
+	printf("\tclose error, errno = %d\n",errno);
+	goto err;
+    }
+
+    len = size;
+
+    // Always store a wchar ^Z past end of buffer so scanner has a sentinel
+    buffer[size] = 0;		// ^Z is obsolete, use 0
+    buffer[size + 1] = 0;
+    return 0;
+
+err2:
+    close(fd);
+err:
+    mem.free(buffer);
+    buffer = NULL;
+    len = 0;
+
+err1:
+    result = 1;
+    return result;
+#elif _WIN32
+    DWORD size;
+    DWORD numread;
+    HANDLE h;
+    int result = 0;
+    char *name;
+
+    name = this->name->toChars();
+    h = CreateFileA(name,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,
+	FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,0);
+    if (h == INVALID_HANDLE_VALUE)
+	goto err1;
+
+    if (!ref)
+	mem.free(buffer);
+    ref = 0;
+
+    size = GetFileSize(h,NULL);
+    buffer = (unsigned char *) mem.malloc(size + 2);
+    if (!buffer)
+	goto err2;
+
+    if (ReadFile(h,buffer,size,&numread,NULL) != TRUE)
+	goto err2;
+
+    if (numread != size)
+	goto err2;
+
+    if (touchtime)
+    {
+	if (!GetFileTime(h, NULL, NULL, &((WIN32_FIND_DATAA *)touchtime)->ftLastWriteTime))
+	    goto err2;
+    }
+
+    if (!CloseHandle(h))
+	goto err;
+
+    len = size;
+
+    // Always store a wchar ^Z past end of buffer so scanner has a sentinel
+    buffer[size] = 0;		// ^Z is obsolete, use 0
+    buffer[size + 1] = 0;
+    return 0;
+
+err2:
+    CloseHandle(h);
+err:
+    mem.free(buffer);
+    buffer = NULL;
+    len = 0;
+
+err1:
+    result = 1;
+    return result;
+#else
+    assert(0);
+#endif
+}
+
+/*****************************
+ * Read a file with memory mapped file I/O.
+ */
+
+int File::mmread()
+{
+#if POSIX
+    return read();
+#elif _WIN32
+    HANDLE hFile;
+    HANDLE hFileMap;
+    DWORD size;
+    char *name;
+
+    name = this->name->toChars();
+    hFile = CreateFile(name, GENERIC_READ,
+			FILE_SHARE_READ, NULL,
+			OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+    if (hFile == INVALID_HANDLE_VALUE)
+	goto Lerr;
+    size = GetFileSize(hFile, NULL);
+    //printf(" file created, size %d\n", size);
+
+    hFileMap = CreateFileMapping(hFile,NULL,PAGE_READONLY,0,size,NULL);
+    if (CloseHandle(hFile) != TRUE)
+	goto Lerr;
+
+    if (hFileMap == NULL)
+	goto Lerr;
+
+    //printf(" mapping created\n");
+
+    if (!ref)
+	mem.free(buffer);
+    ref = 2;
+    buffer = (unsigned char *)MapViewOfFileEx(hFileMap, FILE_MAP_READ,0,0,size,NULL);
+    if (CloseHandle(hFileMap) != TRUE)
+	goto Lerr;
+    if (buffer == NULL)			// mapping view failed
+	goto Lerr;
+
+    len = size;
+    //printf(" buffer = %p\n", buffer);
+
+    return 0;
+
+Lerr:
+    return GetLastError();			// failure
+#else
+    assert(0);
+#endif
+}
+
+/*********************************************
+ * Write a file.
+ * Returns:
+ *	0	success
+ */
+
+int File::write()
+{
+#if POSIX
+    int fd;
+    ssize_t numwritten;
+    char *name;
+
+    name = this->name->toChars();
+    fd = open(name, O_CREAT | O_WRONLY | O_TRUNC, 0644);
+    if (fd == -1)
+	goto err;
+
+    numwritten = ::write(fd, buffer, len);
+    if (len != numwritten)
+	goto err2;
+    
+    if (close(fd) == -1)
+	goto err;
+
+    if (touchtime)
+    {   struct utimbuf ubuf;
+
+        ubuf.actime = ((struct stat *)touchtime)->st_atime;
+        ubuf.modtime = ((struct stat *)touchtime)->st_mtime;
+	if (utime(name, &ubuf))
+	    goto err;
+    }
+    return 0;
+
+err2:
+    close(fd);
+    ::remove(name);
+err:
+    return 1;
+#elif _WIN32
+    HANDLE h;
+    DWORD numwritten;
+    char *name;
+
+    name = this->name->toChars();
+    h = CreateFileA(name,GENERIC_WRITE,0,NULL,CREATE_ALWAYS,
+	FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,NULL);
+    if (h == INVALID_HANDLE_VALUE)
+	goto err;
+
+    if (WriteFile(h,buffer,len,&numwritten,NULL) != TRUE)
+	goto err2;
+
+    if (len != numwritten)
+	goto err2;
+    
+    if (touchtime) {
+        SetFileTime(h, NULL, NULL, &((WIN32_FIND_DATAA *)touchtime)->ftLastWriteTime);
+    }
+    if (!CloseHandle(h))
+	goto err;
+    return 0;
+
+err2:
+    CloseHandle(h);
+    DeleteFileA(name);
+err:
+    return 1;
+#else
+    assert(0);
+#endif
+}
+
+/*********************************************
+ * Append to a file.
+ * Returns:
+ *	0	success
+ */
+
+int File::append()
+{
+#if POSIX
+    return 1;
+#elif _WIN32
+    HANDLE h;
+    DWORD numwritten;
+    char *name;
+
+    name = this->name->toChars();
+    h = CreateFileA(name,GENERIC_WRITE,0,NULL,OPEN_ALWAYS,
+	FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,NULL);
+    if (h == INVALID_HANDLE_VALUE)
+	goto err;
+
+#if 1
+    SetFilePointer(h, 0, NULL, FILE_END);
+#else // INVALID_SET_FILE_POINTER doesn't seem to have a definition
+    if (SetFilePointer(h, 0, NULL, FILE_END) == INVALID_SET_FILE_POINTER)
+	goto err;
+#endif
+
+    if (WriteFile(h,buffer,len,&numwritten,NULL) != TRUE)
+	goto err2;
+
+    if (len != numwritten)
+	goto err2;
+    
+    if (touchtime) {
+        SetFileTime(h, NULL, NULL, &((WIN32_FIND_DATAA *)touchtime)->ftLastWriteTime);
+    }
+    if (!CloseHandle(h))
+	goto err;
+    return 0;
+
+err2:
+    CloseHandle(h);
+err:
+    return 1;
+#else
+    assert(0);
+#endif
+}
+
+/**************************************
+ */
+
+void File::readv()
+{
+    if (read())
+	error("Error reading file '%s'\n",name->toChars());
+}
+
+/**************************************
+ */
+
+void File::mmreadv()
+{
+    if (mmread())
+	readv();
+}
+
+void File::writev()
+{
+    if (write())
+	error("Error writing file '%s'\n",name->toChars());
+}
+
+void File::appendv()
+{
+    if (write())
+	error("Error appending to file '%s'\n",name->toChars());
+}
+
+/*******************************************
+ * Return !=0 if file exists.
+ *	0:	file doesn't exist
+ *	1:	normal file
+ *	2:	directory
+ */
+
+int File::exists()
+{
+#if POSIX
+    return 0;
+#elif _WIN32
+    DWORD dw;
+    int result;
+    char *name;
+
+    name = this->name->toChars();
+    if (touchtime)
+	dw = ((WIN32_FIND_DATAA *)touchtime)->dwFileAttributes;
+    else
+	dw = GetFileAttributesA(name);
+    if (dw == -1L)
+	result = 0;
+    else if (dw & FILE_ATTRIBUTE_DIRECTORY)
+	result = 2;
+    else
+	result = 1;
+    return result;
+#else
+    assert(0);
+#endif
+}
+
+void File::remove()
+{
+#if POSIX
+    ::remove(this->name->toChars());
+#elif _WIN32
+    DeleteFileA(this->name->toChars());
+#else
+    assert(0);
+#endif
+}
+
+Array *File::match(char *n)
+{
+    return match(new FileName(n, 0));
+}
+
+Array *File::match(FileName *n)
+{
+#if POSIX
+    return NULL;
+#elif _WIN32
+    HANDLE h;
+    WIN32_FIND_DATAA fileinfo;
+    Array *a;
+    char *c;
+    char *name;
+
+    a = new Array();
+    c = n->toChars();
+    name = n->name();
+    h = FindFirstFileA(c,&fileinfo);
+    if (h != INVALID_HANDLE_VALUE)
+    {
+	do
+	{
+	    // Glue path together with name
+	    char *fn;
+	    File *f;
+
+	    fn = (char *)mem.malloc(name - c + strlen(fileinfo.cFileName) + 1);
+	    memcpy(fn, c, name - c);
+	    strcpy(fn + (name - c), fileinfo.cFileName);
+	    f = new File(fn);
+	    f->touchtime = mem.malloc(sizeof(WIN32_FIND_DATAA));
+	    memcpy(f->touchtime, &fileinfo, sizeof(fileinfo));
+	    a->push(f);
+	} while (FindNextFileA(h,&fileinfo) != FALSE);
+	FindClose(h);
+    }
+    return a;
+#else
+    assert(0);
+#endif
+}
+
+int File::compareTime(File *f)
+{
+#if POSIX
+    return 0;
+#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
+}
+
+void File::stat()
+{
+#if POSIX
+    if (!touchtime)
+    {
+	touchtime = mem.calloc(1, sizeof(struct stat));
+    }
+#elif _WIN32
+    HANDLE h;
+
+    if (!touchtime)
+    {
+	touchtime = mem.calloc(1, sizeof(WIN32_FIND_DATAA));
+    }
+    h = FindFirstFileA(name->toChars(),(WIN32_FIND_DATAA *)touchtime);
+    if (h != INVALID_HANDLE_VALUE)
+    {
+	FindClose(h);
+    }
+#else
+    assert(0);
+#endif
+}
+
+void File::checkoffset(size_t offset, size_t nbytes)
+{
+    if (offset > len || offset + nbytes > len)
+	error("Corrupt file '%s': offset x%zx off end of file",toChars(),offset);
+}
+
+char *File::toChars()
+{
+    return name->toChars();
+}
+
+
+/************************* OutBuffer *************************/
+
+OutBuffer::OutBuffer()
+{
+    data = NULL;
+    offset = 0;
+    size = 0;
+}
+
+OutBuffer::~OutBuffer()
+{
+    mem.free(data);
+}
+
+void *OutBuffer::extractData()
+{
+    void *p;
+
+    p = (void *)data;
+    data = NULL;
+    offset = 0;
+    size = 0;
+    return p;
+}
+
+void OutBuffer::mark()
+{
+    mem.mark(data);
+}
+
+void OutBuffer::reserve(unsigned nbytes)
+{
+    //printf("OutBuffer::reserve: size = %d, offset = %d, nbytes = %d\n", size, offset, nbytes);
+    if (size - offset < nbytes)
+    {
+	size = (offset + nbytes) * 2;
+	data = (unsigned char *)mem.realloc(data, size);
+    }
+}
+
+void OutBuffer::reset()
+{
+    offset = 0;
+}
+
+void OutBuffer::setsize(unsigned size)
+{
+    offset = size;
+}
+
+void OutBuffer::write(const void *data, unsigned nbytes)
+{
+    reserve(nbytes);
+    memcpy(this->data + offset, data, nbytes);
+    offset += nbytes;
+}
+
+void OutBuffer::writebstring(unsigned char *string)
+{
+    write(string,*string + 1);
+}
+
+void OutBuffer::writestring(const char *string)
+{
+    write(string,strlen(string));
+}
+
+void OutBuffer::writedstring(const char *string)
+{
+#if M_UNICODE
+    for (; *string; string++)
+    {
+	writedchar(*string);
+    }
+#else
+    write(string,strlen(string));
+#endif
+}
+
+void OutBuffer::writedstring(const wchar_t *string)
+{
+#if M_UNICODE
+    write(string,wcslen(string) * sizeof(wchar_t));
+#else
+    for (; *string; string++)
+    {
+	writedchar(*string);
+    }
+#endif
+}
+
+void OutBuffer::prependstring(const char *string)
+{   unsigned len;
+
+    len = strlen(string);
+    reserve(len);
+    memmove(data + len, data, offset);
+    memcpy(data, string, len);
+    offset += len;
+}
+
+void OutBuffer::writenl()
+{
+#if _WIN32
+#if M_UNICODE
+    write4(0x000A000D);		// newline is CR,LF on Microsoft OS's
+#else
+    writeword(0x0A0D);		// newline is CR,LF on Microsoft OS's
+#endif
+#else
+#if M_UNICODE
+    writeword('\n');
+#else
+    writeByte('\n');
+#endif
+#endif
+}
+
+void OutBuffer::writeByte(unsigned b)
+{
+    reserve(1);
+    this->data[offset] = (unsigned char)b;
+    offset++;
+}
+
+void OutBuffer::writeUTF8(unsigned b)
+{
+    reserve(6);
+    if (b <= 0x7F)
+    {
+	this->data[offset] = (unsigned char)b;
+	offset++;
+    }
+    else if (b <= 0x7FF)
+    {
+	this->data[offset + 0] = (unsigned char)((b >> 6) | 0xC0);
+	this->data[offset + 1] = (unsigned char)((b & 0x3F) | 0x80);
+	offset += 2;
+    }
+    else if (b <= 0xFFFF)
+    {
+	this->data[offset + 0] = (unsigned char)((b >> 12) | 0xE0);
+	this->data[offset + 1] = (unsigned char)(((b >> 6) & 0x3F) | 0x80);
+	this->data[offset + 2] = (unsigned char)((b & 0x3F) | 0x80);
+	offset += 3;
+    }
+    else if (b <= 0x1FFFFF)
+    {
+	this->data[offset + 0] = (unsigned char)((b >> 18) | 0xF0);
+	this->data[offset + 1] = (unsigned char)(((b >> 12) & 0x3F) | 0x80);
+	this->data[offset + 2] = (unsigned char)(((b >> 6) & 0x3F) | 0x80);
+	this->data[offset + 3] = (unsigned char)((b & 0x3F) | 0x80);
+	offset += 4;
+    }
+    else if (b <= 0x3FFFFFF)
+    {
+	this->data[offset + 0] = (unsigned char)((b >> 24) | 0xF8);
+	this->data[offset + 1] = (unsigned char)(((b >> 18) & 0x3F) | 0x80);
+	this->data[offset + 2] = (unsigned char)(((b >> 12) & 0x3F) | 0x80);
+	this->data[offset + 3] = (unsigned char)(((b >> 6) & 0x3F) | 0x80);
+	this->data[offset + 4] = (unsigned char)((b & 0x3F) | 0x80);
+	offset += 5;
+    }
+    else if (b <= 0x7FFFFFFF)
+    {
+	this->data[offset + 0] = (unsigned char)((b >> 30) | 0xFC);
+	this->data[offset + 1] = (unsigned char)(((b >> 24) & 0x3F) | 0x80);
+	this->data[offset + 2] = (unsigned char)(((b >> 18) & 0x3F) | 0x80);
+	this->data[offset + 3] = (unsigned char)(((b >> 12) & 0x3F) | 0x80);
+	this->data[offset + 4] = (unsigned char)(((b >> 6) & 0x3F) | 0x80);
+	this->data[offset + 5] = (unsigned char)((b & 0x3F) | 0x80);
+	offset += 6;
+    }
+    else
+	assert(0);
+}
+
+void OutBuffer::writedchar(unsigned b)
+{
+    reserve(Dchar_mbmax * sizeof(dchar));
+    offset = (unsigned char *)Dchar::put((dchar *)(this->data + offset), (dchar)b) -
+		this->data;
+}
+
+void OutBuffer::prependbyte(unsigned b)
+{
+    reserve(1);
+    memmove(data + 1, data, offset);
+    data[0] = (unsigned char)b;
+    offset++;
+}
+
+void OutBuffer::writeword(unsigned w)
+{
+    reserve(2);
+    *(unsigned short *)(this->data + offset) = (unsigned short)w;
+    offset += 2;
+}
+
+void OutBuffer::writeUTF16(unsigned w)
+{
+    reserve(4);
+    if (w <= 0xFFFF)
+    {
+	*(unsigned short *)(this->data + offset) = (unsigned short)w;
+	offset += 2;
+    }
+    else if (w <= 0x10FFFF)
+    {
+	*(unsigned short *)(this->data + offset) = (unsigned short)((w >> 10) + 0xD7C0);
+	*(unsigned short *)(this->data + offset + 2) = (unsigned short)((w & 0x3FF) | 0xDC00);
+	offset += 4;
+    }
+    else
+	assert(0);
+}
+
+void OutBuffer::write4(unsigned w)
+{
+    reserve(4);
+    *(unsigned long *)(this->data + offset) = w;
+    offset += 4;
+}
+
+void OutBuffer::write(OutBuffer *buf)
+{
+    if (buf)
+    {	reserve(buf->offset);
+	memcpy(data + offset, buf->data, buf->offset);
+	offset += buf->offset;
+    }
+}
+
+void OutBuffer::write(Object *obj)
+{
+    if (obj)
+    {
+	writestring(obj->toChars());
+    }
+}
+
+void OutBuffer::fill0(unsigned nbytes)
+{
+    reserve(nbytes);
+    memset(data + offset,0,nbytes);
+    offset += nbytes;
+}
+
+void OutBuffer::align(unsigned size)
+{   unsigned nbytes;
+
+    nbytes = ((offset + size - 1) & ~(size - 1)) - offset;
+    fill0(nbytes);
+}
+
+
+////////////////////////////////////////////////////////////////
+// The compiler shipped with Visual Studio 2005 (and possible
+// other versions) does not support C99 printf format specfiers
+// such as %z and %j
+#if _MSC_VER
+using std::string;
+using std::wstring;
+
+template<typename S>
+inline void 
+search_and_replace(S& str, const S& what, const S& replacement)
+{
+    assert(!what.empty());
+    size_t pos = str.find(what);
+    while (pos != S::npos) 
+    {
+        str.replace(pos, what.size(), replacement);
+        pos = str.find(what, pos + replacement.size());
+    }
+}
+#define WORKAROUND_C99_SPECIFIERS_BUG(S,tmp,f) \
+    S tmp = f;                                 \
+    search_and_replace(fmt, S("%z"), S("%l")); \
+    search_and_replace(fmt, S("%j"), S("%i")); \
+    f = tmp.c_str();
+#else
+#define WORKAROUND_C99_SPECIFIERS_BUG(S,tmp,f)
+#endif
+
+void OutBuffer::vprintf(const char *format, va_list args)
+{
+    char buffer[128];
+    char *p;
+    unsigned psize;
+    int count;
+
+    WORKAROUND_C99_SPECIFIERS_BUG(string, fmt, format);
+
+    p = buffer;
+    psize = sizeof(buffer);
+    for (;;)
+    {
+#if _WIN32
+	count = _vsnprintf(p,psize,format,args);
+	if (count != -1)
+	    break;
+	psize *= 2;
+#elif POSIX
+        va_list va;
+        va_copy(va, args);
+/*
+  The functions vprintf(), vfprintf(), vsprintf(), vsnprintf()
+  are equivalent to the functions printf(), fprintf(), sprintf(),
+  snprintf(), respectively, except that they are called with a
+  va_list instead of a variable number of arguments. These
+  functions do not call the va_end macro. Consequently, the value
+  of ap is undefined after the call. The application should call
+  va_end(ap) itself afterwards.
+ */
+	count = vsnprintf(p,psize,format,va);
+        va_end(va);
+	if (count == -1)
+	    psize *= 2;
+	else if (count >= psize)
+	    psize = count + 1;
+	else
+	    break;
+#else
+    assert(0);
+#endif
+	p = (char *) alloca(psize);	// buffer too small, try again with larger size
+    }
+    write(p,count);
+}
+
+#if M_UNICODE
+void OutBuffer::vprintf(const wchar_t *format, va_list args)
+{
+    dchar buffer[128];
+    dchar *p;
+    unsigned psize;
+    int count;
+
+    WORKAROUND_C99_SPECIFIERS_BUG(wstring, fmt, format);
+
+    p = buffer;
+    psize = sizeof(buffer) / sizeof(buffer[0]);
+    for (;;)
+    {
+#if _WIN32
+	count = _vsnwprintf(p,psize,format,args);
+	if (count != -1)
+	    break;
+	psize *= 2;
+#elif POSIX
+        va_list va;
+        va_copy(va, args);
+	count = vsnwprintf(p,psize,format,va);
+        va_end(va); 
+
+	if (count == -1)
+	    psize *= 2;
+	else if (count >= psize)
+	    psize = count + 1;
+	else
+	    break;
+#else
+    assert(0);
+#endif
+	p = (dchar *) alloca(psize * 2);	// buffer too small, try again with larger size
+    }
+    write(p,count * 2);
+}
+#endif
+
+void OutBuffer::printf(const char *format, ...)
+{
+    va_list ap;
+    va_start(ap, format);
+    vprintf(format,ap);
+    va_end(ap);
+}
+
+#if M_UNICODE
+void OutBuffer::printf(const wchar_t *format, ...)
+{
+    va_list ap;
+    va_start(ap, format);
+    vprintf(format,ap);
+    va_end(ap);
+}
+#endif
+
+void OutBuffer::bracket(char left, char right)
+{
+    reserve(2);
+    memmove(data + 1, data, offset);
+    data[0] = left;
+    data[offset + 1] = right;
+    offset += 2;
+}
+
+/******************
+ * Insert left at i, and right at j.
+ * Return index just past right.
+ */
+
+unsigned OutBuffer::bracket(unsigned i, const char *left, unsigned j, const char *right)
+{
+    size_t leftlen = strlen(left);
+    size_t rightlen = strlen(right);
+    reserve(leftlen + rightlen);
+    insert(i, left, leftlen);
+    insert(j + leftlen, right, rightlen);
+    return j + leftlen + rightlen;
+}
+
+void OutBuffer::spread(unsigned offset, unsigned nbytes)
+{
+    reserve(nbytes);
+    memmove(data + offset + nbytes, data + offset,
+	this->offset - offset);
+    this->offset += nbytes;
+}
+
+/****************************************
+ * Returns: offset + nbytes
+ */
+
+unsigned OutBuffer::insert(unsigned offset, const void *p, unsigned nbytes)
+{
+    spread(offset, nbytes);
+    memmove(data + offset, p, nbytes);
+    return offset + nbytes;
+}
+
+void OutBuffer::remove(unsigned offset, unsigned nbytes)
+{
+    memmove(data + offset, data + offset + nbytes, this->offset - (offset + nbytes));
+    this->offset -= nbytes;
+}
+
+char *OutBuffer::toChars()
+{
+    writeByte(0);
+    return (char *)data;
+}
+
+/********************************* Bits ****************************/
+
+Bits::Bits()
+{
+    data = NULL;
+    bitdim = 0;
+    allocdim = 0;
+}
+
+Bits::~Bits()
+{
+    mem.free(data);
+}
+
+void Bits::mark()
+{
+    mem.mark(data);
+}
+
+void Bits::resize(unsigned bitdim)
+{
+    unsigned allocdim;
+    unsigned mask;
+
+    allocdim = (bitdim + 31) / 32;
+    data = (unsigned *)mem.realloc(data, allocdim * sizeof(data[0]));
+    if (this->allocdim < allocdim)
+	memset(data + this->allocdim, 0, (allocdim - this->allocdim) * sizeof(data[0]));
+
+    // Clear other bits in last word
+    mask = (1 << (bitdim & 31)) - 1;
+    if (mask)
+	data[allocdim - 1] &= ~mask;
+
+    this->bitdim = bitdim;
+    this->allocdim = allocdim;
+}
+
+void Bits::set(unsigned bitnum)
+{
+    data[bitnum / 32] |= 1 << (bitnum & 31);
+}
+
+void Bits::clear(unsigned bitnum)
+{
+    data[bitnum / 32] &= ~(1 << (bitnum & 31));
+}
+
+int Bits::test(unsigned bitnum)
+{
+    return data[bitnum / 32] & (1 << (bitnum & 31));
+}
+
+void Bits::set()
+{   unsigned mask;
+
+    memset(data, ~0, allocdim * sizeof(data[0]));
+
+    // Clear other bits in last word
+    mask = (1 << (bitdim & 31)) - 1;
+    if (mask)
+	data[allocdim - 1] &= mask;
+}
+
+void Bits::clear()
+{
+    memset(data, 0, allocdim * sizeof(data[0]));
+}
+
+void Bits::copy(Bits *from)
+{
+    assert(bitdim == from->bitdim);
+    memcpy(data, from->data, allocdim * sizeof(data[0]));
+}
+
+Bits *Bits::clone()
+{
+    Bits *b;
+
+    b = new Bits();
+    b->resize(bitdim);
+    b->copy(this);
+    return b;
+}
+
+void Bits::sub(Bits *b)
+{
+    unsigned u;
+
+    for (u = 0; u < allocdim; u++)
+	data[u] &= ~b->data[u];
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd2/root/root.h	Mon Jun 01 19:02:20 2009 +0100
@@ -0,0 +1,359 @@
+
+
+// Copyright (c) 1999-2006 by Digital Mars
+// All Rights Reserved
+// written by Walter Bright
+// www.digitalmars.com
+// License for redistribution is by either the Artistic License
+// in artistic.txt, or the GNU General Public License in gnu.txt.
+// See the included readme.txt for details.
+
+#ifndef ROOT_H
+#define ROOT_H
+
+#include <stdlib.h>
+#include <stdarg.h>
+
+#if __DMC__
+#pragma once
+#endif
+
+typedef size_t hash_t;
+
+#include "dchar.h"
+
+char *wchar2ascii(wchar_t *);
+int wcharIsAscii(wchar_t *);
+char *wchar2ascii(wchar_t *, unsigned len);
+int wcharIsAscii(wchar_t *, unsigned len);
+
+int bstrcmp(unsigned char *s1, unsigned char *s2);
+char *bstr2str(unsigned char *b);
+void error(const char *format, ...);
+void error(const wchar_t *format, ...);
+void warning(const char *format, ...);
+
+#ifndef TYPEDEFS
+#define TYPEDEFS
+
+#if _MSC_VER
+#include <float.h>  // for _isnan
+#include <malloc.h> // for alloca
+// According to VC 8.0 docs, long double is the same as double
+#define strtold strtod
+#define strtof  strtod
+#define isnan   _isnan
+
+typedef __int64 longlong;
+typedef unsigned __int64 ulonglong;
+#else
+typedef long long longlong;
+typedef unsigned long long ulonglong;
+#endif
+
+#endif
+
+longlong randomx();
+
+/*
+ * Root of our class library.
+ */
+
+struct OutBuffer;
+struct Array;
+
+struct Object
+{
+    Object() { }
+    virtual ~Object() { }
+
+    virtual int equals(Object *o);
+
+    /**
+     * Returns a hash code, useful for things like building hash tables of Objects.
+     */
+    virtual hash_t hashCode();
+
+    /**
+     * Return <0, ==0, or >0 if this is less than, equal to, or greater than obj.
+     * Useful for sorting Objects.
+     */
+    virtual int compare(Object *obj);
+
+    /**
+     * Pretty-print an Object. Useful for debugging the old-fashioned way.
+     */
+    virtual void print();
+
+    virtual char *toChars();
+    virtual dchar *toDchars();
+    virtual void toBuffer(OutBuffer *buf);
+
+    /**
+     * Used as a replacement for dynamic_cast. Returns a unique number
+     * defined by the library user. For Object, the return value is 0.
+     */
+    virtual int dyncast();
+
+    /**
+     * Marks pointers for garbage collector by calling mem.mark() for all pointers into heap.
+     */
+    /*virtual*/		// not used, disable for now
+	void mark();
+};
+
+struct String : Object
+{
+    int ref;			// != 0 if this is a reference to someone else's string
+    char *str;			// the string itself
+
+    String(char *str, int ref = 1);
+
+    ~String();
+
+    static hash_t calcHash(const char *str, size_t len);
+    static hash_t calcHash(const char *str);
+    hash_t hashCode();
+    unsigned len();
+    int equals(Object *obj);
+    int compare(Object *obj);
+    char *toChars();
+    void print();
+    void mark();
+};
+
+struct FileName : String
+{
+    FileName(char *str, int ref);
+    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();
+    static char *removeExt(const char *str);
+    static char *name(const char *);
+    char *name();
+    static char *path(const char *);
+    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);
+    static FileName *defaultExt(const char *name, const char *ext);
+    static FileName *forceExt(const char *name, const char *ext);
+    int equalsExt(const char *ext);
+
+    void CopyTo(FileName *to);
+    static char *searchPath(Array *path, const char *name, int cwd);
+    static int exists(const char *name);
+    static void ensurePathExists(const char *path);
+};
+
+struct File : Object
+{
+    int ref;			// != 0 if this is a reference to someone else's buffer
+    unsigned char *buffer;	// data for our file
+    unsigned len;		// amount of data in buffer[]
+    void *touchtime;		// system time to use for file
+
+    FileName *name;		// name of our file
+
+    File(char *);
+    File(FileName *);
+    ~File();
+
+    void mark();
+
+    char *toChars();
+
+    /* Read file, return !=0 if error
+     */
+
+    int read();
+
+    /* Write file, either succeed or fail
+     * with error message & exit.
+     */
+
+    void readv();
+
+    /* Read file, return !=0 if error
+     */
+
+    int mmread();
+
+    /* Write file, either succeed or fail
+     * with error message & exit.
+     */
+
+    void mmreadv();
+
+    /* Write file, return !=0 if error
+     */
+
+    int write();
+
+    /* Write file, either succeed or fail
+     * with error message & exit.
+     */
+
+    void writev();
+
+    /* Return !=0 if file exists.
+     *	0:	file doesn't exist
+     *	1:	normal file
+     *	2:	directory
+     */
+
+    /* Append to file, return !=0 if error
+     */
+
+    int append();
+
+    /* Append to file, either succeed or fail
+     * with error message & exit.
+     */
+
+    void appendv();
+
+    /* Return !=0 if file exists.
+     *	0:	file doesn't exist
+     *	1:	normal file
+     *	2:	directory
+     */
+
+    int exists();
+
+    /* Given wildcard filespec, return an array of
+     * matching File's.
+     */
+
+    static Array *match(char *);
+    static Array *match(FileName *);
+
+    // Compare file times.
+    // Return	<0	this < f
+    //		=0	this == f
+    //		>0	this > f
+    int compareTime(File *f);
+
+    // Read system file statistics
+    void stat();
+
+    /* Set buffer
+     */
+
+    void setbuffer(void *buffer, unsigned len)
+    {
+	this->buffer = (unsigned char *)buffer;
+	this->len = len;
+    }
+
+    void checkoffset(size_t offset, size_t nbytes);
+
+    void remove();		// delete file
+};
+
+struct OutBuffer : Object
+{
+    unsigned char *data;
+    unsigned offset;
+    unsigned size;
+
+    OutBuffer();
+    ~OutBuffer();
+    void *extractData();
+    void mark();
+
+    void reserve(unsigned nbytes);
+    void setsize(unsigned size);
+    void reset();
+    void write(const void *data, unsigned nbytes);
+    void writebstring(unsigned char *string);
+    void writestring(const char *string);
+    void writedstring(const char *string);
+    void writedstring(const wchar_t *string);
+    void prependstring(const char *string);
+    void writenl();			// write newline
+    void writeByte(unsigned b);
+    void writebyte(unsigned b) { writeByte(b); }
+    void writeUTF8(unsigned b);
+    void writedchar(unsigned b);
+    void prependbyte(unsigned b);
+    void writeword(unsigned w);
+    void writeUTF16(unsigned w);
+    void write4(unsigned w);
+    void write(OutBuffer *buf);
+    void write(Object *obj);
+    void fill0(unsigned nbytes);
+    void align(unsigned size);
+    void vprintf(const char *format, va_list args);
+    void printf(const char *format, ...);
+#if M_UNICODE
+    void vprintf(const unsigned short *format, va_list args);
+    void printf(const unsigned short *format, ...);
+#endif
+    void bracket(char left, char right);
+    unsigned bracket(unsigned i, const char *left, unsigned j, const char *right);
+    void spread(unsigned offset, unsigned nbytes);
+    unsigned insert(unsigned offset, const void *data, unsigned nbytes);
+    void remove(unsigned offset, unsigned nbytes);
+    char *toChars();
+    char *extractString();
+};
+
+struct Array : Object
+{
+    unsigned dim;
+    unsigned allocdim;
+    void **data;
+
+    Array();
+    ~Array();
+    void mark();
+    char *toChars();
+
+    void reserve(unsigned nentries);
+    void setDim(unsigned newdim);
+    void fixDim();
+    void push(void *ptr);
+    void *pop();
+    void shift(void *ptr);
+    void insert(unsigned index, void *ptr);
+    void insert(unsigned index, Array *a);
+    void append(Array *a);
+    void remove(unsigned i);
+    void zero();
+    void *tos();
+    void sort();
+    Array *copy();
+};
+
+struct Bits : Object
+{
+    unsigned bitdim;
+    unsigned allocdim;
+    unsigned *data;
+
+    Bits();
+    ~Bits();
+    void mark();
+
+    void resize(unsigned bitdim);
+
+    void set(unsigned bitnum);
+    void clear(unsigned bitnum);
+    int test(unsigned bitnum);
+
+    void set();
+    void clear();
+    void copy(Bits *from);
+    Bits *clone();
+
+    void sub(Bits *b);
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd2/root/stringtable.c	Mon Jun 01 19:02:20 2009 +0100
@@ -0,0 +1,139 @@
+
+// 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 <string.h>
+#include <stdlib.h>
+
+#include "root.h"
+#include "rmem.h"
+#include "dchar.h"
+#include "lstring.h"
+#include "stringtable.h"
+
+StringTable::StringTable(unsigned size)
+{
+    table = (void **)mem.calloc(size, sizeof(void *));
+    tabledim = size;
+    count = 0;
+}
+
+StringTable::~StringTable()
+{
+    unsigned i;
+
+    // Zero out dangling pointers to help garbage collector.
+    // Should zero out StringEntry's too.
+    for (i = 0; i < count; i++)
+	table[i] = NULL;
+
+    mem.free(table);
+    table = NULL;
+}
+
+struct StringEntry
+{
+    StringEntry *left;
+    StringEntry *right;
+    hash_t hash;
+
+    StringValue value;
+
+    static StringEntry *alloc(const dchar *s, unsigned len);
+};
+
+StringEntry *StringEntry::alloc(const dchar *s, unsigned len)
+{
+    StringEntry *se;
+
+    se = (StringEntry *) mem.calloc(1,sizeof(StringEntry) - sizeof(Lstring) + Lstring::size(len));
+    se->value.lstring.length = len;
+    se->hash = Dchar::calcHash(s,len);
+    memcpy(se->value.lstring.string, s, len * sizeof(dchar));
+    return se;
+}
+
+void **StringTable::search(const dchar *s, unsigned len)
+{
+    hash_t hash;
+    unsigned u;
+    int cmp;
+    StringEntry **se;
+
+    //printf("StringTable::search(%p,%d)\n",s,len);
+    hash = Dchar::calcHash(s,len);
+    u = hash % tabledim;
+    se = (StringEntry **)&table[u];
+    //printf("\thash = %d, u = %d\n",hash,u);
+    while (*se)
+    {
+	cmp = (*se)->hash - hash;
+	if (cmp == 0)
+	{
+	    cmp = (*se)->value.lstring.len() - len;
+	    if (cmp == 0)
+	    {
+		cmp = Dchar::memcmp(s,(*se)->value.lstring.toDchars(),len);
+		if (cmp == 0)
+		    break;
+	    }
+	}
+	if (cmp < 0)
+	    se = &(*se)->left;
+	else
+	    se = &(*se)->right;
+    }
+    //printf("\treturn %p, %p\n",se, (*se));
+    return (void **)se;
+}
+
+StringValue *StringTable::lookup(const dchar *s, unsigned len)
+{   StringEntry *se;
+
+    se = *(StringEntry **)search(s,len);
+    if (se)
+	return &se->value;
+    else
+	return NULL;
+}
+
+StringValue *StringTable::update(const dchar *s, unsigned len)
+{   StringEntry **pse;
+    StringEntry *se;
+
+    pse = (StringEntry **)search(s,len);
+    se = *pse;
+    if (!se)			// not in table: so create new entry
+    {
+	se = StringEntry::alloc(s, len);
+	*pse = se;
+    }
+    return &se->value;
+}
+
+StringValue *StringTable::insert(const dchar *s, unsigned len)
+{   StringEntry **pse;
+    StringEntry *se;
+
+    pse = (StringEntry **)search(s,len);
+    se = *pse;
+    if (se)
+	return NULL;		// error: already in table
+    else
+    {
+	se = StringEntry::alloc(s, len);
+	*pse = se;
+    }
+    return &se->value;
+}
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd2/root/stringtable.h	Mon Jun 01 19:02:20 2009 +0100
@@ -0,0 +1,48 @@
+// Copyright (c) 1999-2008 by Digital Mars
+// All Rights Reserved
+// written by Walter Bright
+// http://www.digitalmars.com
+// License for redistribution is by either the Artistic License
+// in artistic.txt, or the GNU General Public License in gnu.txt.
+// See the included readme.txt for details.
+
+
+#ifndef STRINGTABLE_H
+#define STRINGTABLE_H
+
+#if __SC__
+#pragma once
+#endif
+
+#include "root.h"
+#include "dchar.h"
+#include "lstring.h"
+
+struct StringValue
+{
+    union
+    {	int intvalue;
+	void *ptrvalue;
+	dchar *string;
+    };
+    Lstring lstring;
+};
+
+struct StringTable : Object
+{
+    void **table;
+    unsigned count;
+    unsigned tabledim;
+
+    StringTable(unsigned size = 37);
+    ~StringTable();
+
+    StringValue *lookup(const dchar *s, unsigned len);
+    StringValue *insert(const dchar *s, unsigned len);
+    StringValue *update(const dchar *s, unsigned len);
+
+private:
+    void **search(const dchar *s, unsigned len);
+};
+
+#endif
--- a/dmd2/scope.c	Mon Jun 01 01:28:18 2009 +0200
+++ b/dmd2/scope.c	Mon Jun 01 19:02:20 2009 +0100
@@ -1,364 +1,361 @@
-
-// Copyright (c) 1999-2005 by Digital Mars
-// All Rights Reserved
-// written by Walter Bright
-// http://www.digitalmars.com
-// License for redistribution is by either the Artistic License
-// in artistic.txt, or the GNU General Public License in gnu.txt.
-// See the included readme.txt for details.
-
-#include <stdio.h>
-#include <assert.h>
-
-#include "root.h"
-
-#include "mars.h"
-#include "init.h"
-#include "identifier.h"
-#include "attrib.h"
-#include "dsymbol.h"
-#include "scope.h"
-#include "declaration.h"
-#include "aggregate.h"
-#include "module.h"
-#include "id.h"
-
-Scope *Scope::freelist = NULL;
-
-void *Scope::operator new(size_t size)
-{
-    if (freelist)
-    {
-	Scope *s = freelist;
-	freelist = s->enclosing;
-	//printf("freelist %p\n", s);
-	assert(s->flags & SCOPEfree);
-	s->flags &= ~SCOPEfree;
-	return s;
-    }
-
-    void *p = ::operator new(size);
-    //printf("new %p\n", p);
-    return p;
-}
-
-Scope::Scope()
-{   // Create root scope
-
-    //printf("Scope::Scope() %p\n", this);
-    this->module = NULL;
-    this->scopesym = NULL;
-    this->sd = NULL;
-    this->enclosing = NULL;
-    this->parent = NULL;
-    this->sw = NULL;
-    this->tf = NULL;
-    this->tfOfTry = NULL;
-    this->tinst = NULL;
-    this->sbreak = NULL;
-    this->scontinue = NULL;
-    this->fes = NULL;
-    this->structalign = global.structalign;
-    this->func = NULL;
-    this->slabel = NULL;
-    this->linkage = LINKd;
-    this->protection = PROTpublic;
-    this->explicitProtection = 0;
-    this->stc = 0;
-    this->offset = 0;
-    this->inunion = 0;
-    this->incontract = 0;
-    this->nofree = 0;
-    this->noctor = 0;
-    this->noaccesscheck = 0;
-    this->intypeof = 0;
-    this->parameterSpecialization = 0;
-    this->callSuper = 0;
-    this->flags = 0;
-    this->anonAgg = NULL;
-    this->lastdc = NULL;
-    this->lastoffset = 0;
-    this->docbuf = NULL;
-}
-
-Scope::Scope(Scope *enclosing)
-{
-    //printf("Scope::Scope(enclosing = %p) %p\n", enclosing, this);
-    assert(!(enclosing->flags & SCOPEfree));
-    this->module = enclosing->module;
-    this->func   = enclosing->func;
-    this->parent = enclosing->parent;
-    this->scopesym = NULL;
-    this->sd = NULL;
-    this->sw = enclosing->sw;
-    this->tf = enclosing->tf;
-    this->tfOfTry = enclosing->tfOfTry;
-    this->tinst = enclosing->tinst;
-    this->sbreak = enclosing->sbreak;
-    this->scontinue = enclosing->scontinue;
-    this->fes = enclosing->fes;
-    this->structalign = enclosing->structalign;
-    this->enclosing = enclosing;
-#ifdef DEBUG
-    if (enclosing->enclosing)
-	assert(!(enclosing->enclosing->flags & SCOPEfree));
-    if (this == enclosing->enclosing)
-    {
-	printf("this = %p, enclosing = %p, enclosing->enclosing = %p\n", this, enclosing, enclosing->enclosing);
-    }
-    assert(this != enclosing->enclosing);
-#endif
-    this->slabel = NULL;
-    this->linkage = enclosing->linkage;
-    this->protection = enclosing->protection;
-    this->explicitProtection = enclosing->explicitProtection;
-    this->stc = enclosing->stc;
-    this->offset = 0;
-    this->inunion = enclosing->inunion;
-    this->incontract = enclosing->incontract;
-    this->nofree = 0;
-    this->noctor = enclosing->noctor;
-    this->noaccesscheck = enclosing->noaccesscheck;
-    this->intypeof = enclosing->intypeof;
-    this->parameterSpecialization = enclosing->parameterSpecialization;
-    this->callSuper = enclosing->callSuper;
-    this->flags = 0;
-    this->anonAgg = NULL;
-    this->lastdc = NULL;
-    this->lastoffset = 0;
-    this->docbuf = enclosing->docbuf;
-    assert(this != enclosing);
-}
-
-Scope *Scope::createGlobal(Module *module)
-{
-    Scope *sc;
-
-    sc = new Scope();
-    sc->module = module;
-    sc->scopesym = new ScopeDsymbol();
-    sc->scopesym->symtab = new DsymbolTable();
-
-    // Add top level package as member of this global scope
-    Dsymbol *m = module;
-    while (m->parent)
-	m = m->parent;
-    m->addMember(NULL, sc->scopesym, 1);
-    m->parent = NULL;			// got changed by addMember()
-
-    // Create the module scope underneath the global scope
-    sc = sc->push(module);
-    sc->parent = module;
-    return sc;
-}
-
-Scope *Scope::push()
-{
-    //printf("Scope::push()\n");
-    Scope *s = new Scope(this);
-    assert(this != s);
-    return s;
-}
-
-Scope *Scope::push(ScopeDsymbol *ss)
-{
-    //printf("Scope::push(%s)\n", ss->toChars());
-    Scope *s = push();
-    s->scopesym = ss;
-    return s;
-}
-
-Scope *Scope::pop()
-{
-    //printf("Scope::pop() %p nofree = %d\n", this, nofree);
-    Scope *enc = enclosing;
-
-    if (enclosing)
-	enclosing->callSuper |= callSuper;
-
-    if (!nofree)
-    {	enclosing = freelist;
-	freelist = this;
-	flags |= SCOPEfree;
-    }
-
-    return enc;
-}
-
-void Scope::mergeCallSuper(Loc loc, unsigned cs)
-{
-    // This does a primitive flow analysis to support the restrictions
-    // regarding when and how constructors can appear.
-    // It merges the results of two paths.
-    // The two paths are callSuper and cs; the result is merged into callSuper.
-
-    if (cs != callSuper)
-    {	int a;
-	int b;
-
-	callSuper |= cs & (CSXany_ctor | CSXlabel);
-	if (cs & CSXreturn)
-	{
-	}
-	else if (callSuper & CSXreturn)
-	{
-	    callSuper = cs | (callSuper & (CSXany_ctor | CSXlabel));
-	}
-	else
-	{
-	    a = (cs        & (CSXthis_ctor | CSXsuper_ctor)) != 0;
-	    b = (callSuper & (CSXthis_ctor | CSXsuper_ctor)) != 0;
-	    if (a != b)
-		error(loc, "one path skips constructor");
-	    callSuper |= cs;
-	}
-    }
-}
-
-Dsymbol *Scope::search(Loc loc, Identifier *ident, Dsymbol **pscopesym)
-{   Dsymbol *s;
-    Scope *sc;
-
-    //printf("Scope::search(%p, '%s')\n", this, ident->toChars());
-    if (ident == Id::empty)
-    {
-	// Look for module scope
-	for (sc = this; sc; sc = sc->enclosing)
-	{
-	    assert(sc != sc->enclosing);
-	    if (sc->scopesym)
-	    {
-		s = sc->scopesym->isModule();
-		if (s)
-		{
-		    //printf("\tfound %s.%s\n", s->parent ? s->parent->toChars() : "", s->toChars());
-		    if (pscopesym)
-			*pscopesym = sc->scopesym;
-		    return s;
-		}
-	    }
-	}
-	return NULL;
-    }
-
-    for (sc = this; sc; sc = sc->enclosing)
-    {
-	assert(sc != sc->enclosing);
-	if (sc->scopesym)
-	{
-	    //printf("\tlooking in scopesym '%s', kind = '%s'\n", sc->scopesym->toChars(), sc->scopesym->kind());
-	    s = sc->scopesym->search(loc, ident, 0);
-	    if (s)
-	    {
-		if ((global.params.warnings ||
-		    global.params.Dversion > 1) &&
-		    ident == Id::length &&
-		    sc->scopesym->isArrayScopeSymbol() &&
-		    sc->enclosing &&
-		    sc->enclosing->search(loc, ident, NULL))
-		{
-            // WTF ?
-		    if (global.params.warnings)
-			fprintf(stdmsg, "warning - ");
-		    error(s->loc, "array 'length' hides other 'length' name in outer scope");
-		}
-
-		//printf("\tfound %s.%s, kind = '%s'\n", s->parent ? s->parent->toChars() : "", s->toChars(), s->kind());
-		if (pscopesym)
-		    *pscopesym = sc->scopesym;
-		return s;
-	    }
-	}
-    }
-
-    return NULL;
-}
-
-Dsymbol *Scope::insert(Dsymbol *s)
-{   Scope *sc;
-
-    for (sc = this; sc; sc = sc->enclosing)
-    {
-	//printf("\tsc = %p\n", sc);
-	if (sc->scopesym)
-	{
-	    //printf("\t\tsc->scopesym = %p\n", sc->scopesym);
-	    if (!sc->scopesym->symtab)
-		sc->scopesym->symtab = new DsymbolTable();
-	    return sc->scopesym->symtab->insert(s);
-	}
-    }
-    assert(0);
-    return NULL;
-}
-
-/********************************************
- * Search enclosing scopes for ClassDeclaration.
- */
-
-ClassDeclaration *Scope::getClassScope()
-{   Scope *sc;
-
-    for (sc = this; sc; sc = sc->enclosing)
-    {
-	ClassDeclaration *cd;
-	
-	if (sc->scopesym)
-	{
-	    cd = sc->scopesym->isClassDeclaration();
-	    if (cd)
-		return cd;
-	}
-    }
-    return NULL;
-}
-
-/********************************************
- * Search enclosing scopes for ClassDeclaration.
- */
-
-AggregateDeclaration *Scope::getStructClassScope()
-{   Scope *sc;
-
-    for (sc = this; sc; sc = sc->enclosing)
-    {
-	AggregateDeclaration *ad;
-	
-	if (sc->scopesym)
-	{
-	    ad = sc->scopesym->isClassDeclaration();
-	    if (ad)
-		return ad;
-	    else
-	    {	ad = sc->scopesym->isStructDeclaration();
-		if (ad)
-		    return ad;
-	    }
-	}
-    }
-    return NULL;
-}
-
-/*******************************************
- * For TemplateDeclarations, we need to remember the Scope
- * where it was declared. So mark the Scope as not
- * to be free'd.
- */
-
-void Scope::setNoFree()
-{   Scope *sc;
-    //int i = 0;
-
-    //printf("Scope::setNoFree(this = %p)\n", this);
-    for (sc = this; sc; sc = sc->enclosing)
-    {
-	//printf("\tsc = %p\n", sc);
-	sc->nofree = 1;
-
-	assert(!(flags & SCOPEfree));
-	//assert(sc != sc->enclosing);
-	//assert(!sc->enclosing || sc != sc->enclosing->enclosing);
-	//if (++i == 10)
-	    //assert(0);
-    }
-}
+
+// Copyright (c) 1999-2005 by Digital Mars
+// All Rights Reserved
+// written by Walter Bright
+// http://www.digitalmars.com
+// License for redistribution is by either the Artistic License
+// in artistic.txt, or the GNU General Public License in gnu.txt.
+// See the included readme.txt for details.
+
+#include <stdio.h>
+#include <assert.h>
+
+#include "root.h"
+
+#include "mars.h"
+#include "init.h"
+#include "identifier.h"
+#include "attrib.h"
+#include "dsymbol.h"
+#include "scope.h"
+#include "declaration.h"
+#include "aggregate.h"
+#include "module.h"
+#include "id.h"
+
+Scope *Scope::freelist = NULL;
+
+void *Scope::operator new(size_t size)
+{
+    if (freelist)
+    {
+	Scope *s = freelist;
+	freelist = s->enclosing;
+	//printf("freelist %p\n", s);
+	assert(s->flags & SCOPEfree);
+	s->flags &= ~SCOPEfree;
+	return s;
+    }
+
+    void *p = ::operator new(size);
+    //printf("new %p\n", p);
+    return p;
+}
+
+Scope::Scope()
+{   // Create root scope
+
+    //printf("Scope::Scope() %p\n", this);
+    this->module = NULL;
+    this->scopesym = NULL;
+    this->sd = NULL;
+    this->enclosing = NULL;
+    this->parent = NULL;
+    this->sw = NULL;
+    this->enclosingFinally = NULL;
+    this->enclosingScopeExit = NULL;
+    this->tinst = NULL;
+    this->sbreak = NULL;
+    this->scontinue = NULL;
+    this->fes = NULL;
+    this->structalign = global.structalign;
+    this->func = NULL;
+    this->slabel = NULL;
+    this->linkage = LINKd;
+    this->protection = PROTpublic;
+    this->explicitProtection = 0;
+    this->stc = 0;
+    this->offset = 0;
+    this->inunion = 0;
+    this->incontract = 0;
+    this->nofree = 0;
+    this->noctor = 0;
+    this->noaccesscheck = 0;
+    this->intypeof = 0;
+    this->parameterSpecialization = 0;
+    this->callSuper = 0;
+    this->flags = 0;
+    this->anonAgg = NULL;
+    this->lastdc = NULL;
+    this->lastoffset = 0;
+    this->docbuf = NULL;
+}
+
+Scope::Scope(Scope *enclosing)
+{
+    //printf("Scope::Scope(enclosing = %p) %p\n", enclosing, this);
+    assert(!(enclosing->flags & SCOPEfree));
+    this->module = enclosing->module;
+    this->func   = enclosing->func;
+    this->parent = enclosing->parent;
+    this->scopesym = NULL;
+    this->sd = NULL;
+    this->sw = enclosing->sw;
+    this->enclosingFinally = enclosing->enclosingFinally;
+    this->enclosingScopeExit = enclosing->enclosingScopeExit;
+    this->tinst = enclosing->tinst;
+    this->sbreak = enclosing->sbreak;
+    this->scontinue = enclosing->scontinue;
+    this->fes = enclosing->fes;
+    this->structalign = enclosing->structalign;
+    this->enclosing = enclosing;
+#ifdef DEBUG
+    if (enclosing->enclosing)
+	assert(!(enclosing->enclosing->flags & SCOPEfree));
+    if (this == enclosing->enclosing)
+    {
+	printf("this = %p, enclosing = %p, enclosing->enclosing = %p\n", this, enclosing, enclosing->enclosing);
+    }
+    assert(this != enclosing->enclosing);
+#endif
+    this->slabel = NULL;
+    this->linkage = enclosing->linkage;
+    this->protection = enclosing->protection;
+    this->explicitProtection = enclosing->explicitProtection;
+    this->stc = enclosing->stc;
+    this->offset = 0;
+    this->inunion = enclosing->inunion;
+    this->incontract = enclosing->incontract;
+    this->nofree = 0;
+    this->noctor = enclosing->noctor;
+    this->noaccesscheck = enclosing->noaccesscheck;
+    this->intypeof = enclosing->intypeof;
+    this->parameterSpecialization = enclosing->parameterSpecialization;
+    this->callSuper = enclosing->callSuper;
+    this->flags = 0;
+    this->anonAgg = NULL;
+    this->lastdc = NULL;
+    this->lastoffset = 0;
+    this->docbuf = enclosing->docbuf;
+    assert(this != enclosing);
+}
+
+Scope *Scope::createGlobal(Module *module)
+{
+    Scope *sc;
+
+    sc = new Scope();
+    sc->module = module;
+    sc->scopesym = new ScopeDsymbol();
+    sc->scopesym->symtab = new DsymbolTable();
+
+    // Add top level package as member of this global scope
+    Dsymbol *m = module;
+    while (m->parent)
+	m = m->parent;
+    m->addMember(NULL, sc->scopesym, 1);
+    m->parent = NULL;			// got changed by addMember()
+
+    // Create the module scope underneath the global scope
+    sc = sc->push(module);
+    sc->parent = module;
+    return sc;
+}
+
+Scope *Scope::push()
+{
+    //printf("Scope::push()\n");
+    Scope *s = new Scope(this);
+    assert(this != s);
+    return s;
+}
+
+Scope *Scope::push(ScopeDsymbol *ss)
+{
+    //printf("Scope::push(%s)\n", ss->toChars());
+    Scope *s = push();
+    s->scopesym = ss;
+    return s;
+}
+
+Scope *Scope::pop()
+{
+    //printf("Scope::pop() %p nofree = %d\n", this, nofree);
+    Scope *enc = enclosing;
+
+    if (enclosing)
+	enclosing->callSuper |= callSuper;
+
+    if (!nofree)
+    {	enclosing = freelist;
+	freelist = this;
+	flags |= SCOPEfree;
+    }
+
+    return enc;
+}
+
+void Scope::mergeCallSuper(Loc loc, unsigned cs)
+{
+    // This does a primitive flow analysis to support the restrictions
+    // regarding when and how constructors can appear.
+    // It merges the results of two paths.
+    // The two paths are callSuper and cs; the result is merged into callSuper.
+
+    if (cs != callSuper)
+    {	int a;
+	int b;
+
+	callSuper |= cs & (CSXany_ctor | CSXlabel);
+	if (cs & CSXreturn)
+	{
+	}
+	else if (callSuper & CSXreturn)
+	{
+	    callSuper = cs | (callSuper & (CSXany_ctor | CSXlabel));
+	}
+	else
+	{
+	    a = (cs        & (CSXthis_ctor | CSXsuper_ctor)) != 0;
+	    b = (callSuper & (CSXthis_ctor | CSXsuper_ctor)) != 0;
+	    if (a != b)
+		error(loc, "one path skips constructor");
+	    callSuper |= cs;
+	}
+    }
+}
+
+Dsymbol *Scope::search(Loc loc, Identifier *ident, Dsymbol **pscopesym)
+{   Dsymbol *s;
+    Scope *sc;
+
+    //printf("Scope::search(%p, '%s')\n", this, ident->toChars());
+    if (ident == Id::empty)
+    {
+	// Look for module scope
+	for (sc = this; sc; sc = sc->enclosing)
+	{
+	    assert(sc != sc->enclosing);
+	    if (sc->scopesym)
+	    {
+		s = sc->scopesym->isModule();
+		if (s)
+		{
+		    //printf("\tfound %s.%s\n", s->parent ? s->parent->toChars() : "", s->toChars());
+		    if (pscopesym)
+			*pscopesym = sc->scopesym;
+		    return s;
+		}
+	    }
+	}
+	return NULL;
+    }
+
+    for (sc = this; sc; sc = sc->enclosing)
+    {
+	assert(sc != sc->enclosing);
+	if (sc->scopesym)
+	{
+	    //printf("\tlooking in scopesym '%s', kind = '%s'\n", sc->scopesym->toChars(), sc->scopesym->kind());
+	    s = sc->scopesym->search(loc, ident, 0);
+	    if (s)
+	    {
+		if ((global.params.warnings ||
+		    global.params.Dversion > 1) &&
+		    ident == Id::length &&
+		    sc->scopesym->isArrayScopeSymbol() &&
+		    sc->enclosing &&
+		    sc->enclosing->search(loc, ident, NULL))
+		{
+		    warning(s->loc, "array 'length' hides other 'length' name in outer scope");
+		}
+
+		//printf("\tfound %s.%s, kind = '%s'\n", s->parent ? s->parent->toChars() : "", s->toChars(), s->kind());
+		if (pscopesym)
+		    *pscopesym = sc->scopesym;
+		return s;
+	    }
+	}
+    }
+
+    return NULL;
+}
+
+Dsymbol *Scope::insert(Dsymbol *s)
+{   Scope *sc;
+
+    for (sc = this; sc; sc = sc->enclosing)
+    {
+	//printf("\tsc = %p\n", sc);
+	if (sc->scopesym)
+	{
+	    //printf("\t\tsc->scopesym = %p\n", sc->scopesym);
+	    if (!sc->scopesym->symtab)
+		sc->scopesym->symtab = new DsymbolTable();
+	    return sc->scopesym->symtab->insert(s);
+	}
+    }
+    assert(0);
+    return NULL;
+}
+
+/********************************************
+ * Search enclosing scopes for ClassDeclaration.
+ */
+
+ClassDeclaration *Scope::getClassScope()
+{   Scope *sc;
+
+    for (sc = this; sc; sc = sc->enclosing)
+    {
+	ClassDeclaration *cd;
+	
+	if (sc->scopesym)
+	{
+	    cd = sc->scopesym->isClassDeclaration();
+	    if (cd)
+		return cd;
+	}
+    }
+    return NULL;
+}
+
+/********************************************
+ * Search enclosing scopes for ClassDeclaration.
+ */
+
+AggregateDeclaration *Scope::getStructClassScope()
+{   Scope *sc;
+
+    for (sc = this; sc; sc = sc->enclosing)
+    {
+	AggregateDeclaration *ad;
+	
+	if (sc->scopesym)
+	{
+	    ad = sc->scopesym->isClassDeclaration();
+	    if (ad)
+		return ad;
+	    else
+	    {	ad = sc->scopesym->isStructDeclaration();
+		if (ad)
+		    return ad;
+	    }
+	}
+    }
+    return NULL;
+}
+
+/*******************************************
+ * For TemplateDeclarations, we need to remember the Scope
+ * where it was declared. So mark the Scope as not
+ * to be free'd.
+ */
+
+void Scope::setNoFree()
+{   Scope *sc;
+    //int i = 0;
+
+    //printf("Scope::setNoFree(this = %p)\n", this);
+    for (sc = this; sc; sc = sc->enclosing)
+    {
+	//printf("\tsc = %p\n", sc);
+	sc->nofree = 1;
+
+	assert(!(flags & SCOPEfree));
+	//assert(sc != sc->enclosing);
+	//assert(!sc->enclosing || sc != sc->enclosing->enclosing);
+	//if (++i == 10)
+	    //assert(0);
+    }
+}
--- a/dmd2/scope.h	Mon Jun 01 01:28:18 2009 +0200
+++ b/dmd2/scope.h	Mon Jun 01 19:02:20 2009 +0100
@@ -1,119 +1,125 @@
-
-// Copyright (c) 1999-2005 by Digital Mars
-// All Rights Reserved
-// written by Walter Bright
-// http://www.digitalmars.com
-// License for redistribution is by either the Artistic License
-// in artistic.txt, or the GNU General Public License in gnu.txt.
-// See the included readme.txt for details.
-
-#ifndef DMD_SCOPE_H
-#define DMD_SCOPE_H
-
-#ifdef __DMC__
-#pragma once
-#endif /* __DMC__ */
-
-struct Dsymbol;
-struct ScopeDsymbol;
-struct Array;
-struct Identifier;
-struct Module;
-struct Statement;
-struct SwitchStatement;
-struct TryFinallyStatement;
-struct LabelStatement;
-struct ForeachStatement;
-struct ClassDeclaration;
-struct AggregateDeclaration;
-struct AnonymousAggregateDeclaration;
-struct FuncDeclaration;
-struct DocComment;
-struct EnclosingHandler;
-struct AnonDeclaration;
-#if __GNUC__
-#include "dsymbol.h"    // PROT
-#include "mars.h"       // LINK
-#else
-enum LINK;
-enum PROT;
-#endif 
-
-struct Scope
-{
-    Scope *enclosing;		// enclosing Scope
-
-    Module *module;		// Root module
-    ScopeDsymbol *scopesym;	// current symbol
-    ScopeDsymbol *sd;		// if in static if, and declaring new symbols,
-				// sd gets the addMember()
-    FuncDeclaration *func;	// function we are in
-    Dsymbol *parent;		// parent to use
-    LabelStatement *slabel;	// enclosing labelled statement
-    SwitchStatement *sw;	// enclosing switch statement
-    TryFinallyStatement *tf;	// enclosing try finally statement; set inside its finally block
-    EnclosingHandler *tfOfTry; // enclosing try-finally, volatile or synchronized statement; set inside its try or body block
-    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
-    unsigned offset;		// next offset to use in aggregate
-    int inunion;		// we're processing members of a union
-    int incontract;		// we're inside contract code
-    int nofree;			// set if shouldn't free it
-    int noctor;			// set if constructor calls aren't allowed
-    int intypeof;		// in typeof(exp)
-    int parameterSpecialization; // if in template parameter specialization
-    int noaccesscheck;		// don't do access checks
-
-    unsigned callSuper;		// primitive flow analysis for constructors
-#define	CSXthis_ctor	1	// called this()
-#define CSXsuper_ctor	2	// called super()
-#define CSXthis		4	// referenced this
-#define CSXsuper	8	// referenced super
-#define CSXlabel	0x10	// seen a label
-#define CSXreturn	0x20	// seen a return statement
-#define CSXany_ctor	0x40	// either this() or super() was called
-
-    unsigned structalign;	// alignment for struct members
-    enum LINK linkage;		// linkage for external functions
-
-    enum PROT protection;	// protection for class members
-    int explicitProtection;	// set if in an explicit protection attribute
-
-    unsigned stc;		// storage class
-
-    unsigned flags;
-#define SCOPEctor	1	// constructor type
-#define SCOPEstaticif	2	// inside static if
-#define SCOPEfree	4	// is on free list
-
-    AnonymousAggregateDeclaration *anonAgg;	// for temporary analysis
-
-    DocComment *lastdc;		// documentation comment for last symbol at this scope
-    unsigned lastoffset;	// offset in docbuf of where to insert next dec
-    OutBuffer *docbuf;		// buffer for documentation output
-
-    static Scope *freelist;
-    static void *operator new(size_t sz);
-    static Scope *createGlobal(Module *module);
-
-    Scope();
-    Scope(Module *module);
-    Scope(Scope *enclosing);
-
-    Scope *push();
-    Scope *push(ScopeDsymbol *ss);
-    Scope *pop();
-
-    void mergeCallSuper(Loc loc, unsigned cs);
-
-    Dsymbol *search(Loc loc, Identifier *ident, Dsymbol **pscopesym);
-    Dsymbol *insert(Dsymbol *s);
-
-    ClassDeclaration *getClassScope();
-    AggregateDeclaration *getStructClassScope();
-    void setNoFree();
-};
-
-#endif /* DMD_SCOPE_H */
+
+// Copyright (c) 1999-2009 by Digital Mars
+// All Rights Reserved
+// written by Walter Bright
+// http://www.digitalmars.com
+// License for redistribution is by either the Artistic License
+// in artistic.txt, or the GNU General Public License in gnu.txt.
+// See the included readme.txt for details.
+
+#ifndef DMD_SCOPE_H
+#define DMD_SCOPE_H
+
+#ifdef __DMC__
+#pragma once
+#endif
+
+struct Dsymbol;
+struct ScopeDsymbol;
+struct Array;
+struct Identifier;
+struct Module;
+struct Statement;
+struct SwitchStatement;
+struct TryFinallyStatement;
+struct LabelStatement;
+struct ForeachStatement;
+struct ClassDeclaration;
+struct AggregateDeclaration;
+struct AnonymousAggregateDeclaration;
+struct FuncDeclaration;
+struct DocComment;
+struct TemplateInstance;
+
+#if IN_LLVM
+struct EnclosingHandler;
+struct AnonDeclaration;
+#endif
+
+#if __GNUC__
+// Requires a full definition for PROT and LINK
+#include "dsymbol.h"    // PROT
+#include "mars.h"       // LINK
+#else
+enum LINK;
+enum PROT;
+#endif 
+
+struct Scope
+{
+    Scope *enclosing;		// enclosing Scope
+
+    Module *module;		// Root module
+    ScopeDsymbol *scopesym;	// current symbol
+    ScopeDsymbol *sd;		// if in static if, and declaring new symbols,
+				// sd gets the addMember()
+    FuncDeclaration *func;	// function we are in
+    Dsymbol *parent;		// parent to use
+    LabelStatement *slabel;	// enclosing labelled statement
+    SwitchStatement *sw;	// enclosing switch statement
+    TryFinallyStatement *enclosingFinally;	// enclosing try finally statement; set inside its finally block
+    TemplateInstance *tinst;    // enclosing template instance
+    Statement *enclosingScopeExit; // enclosing statement that wants to do something on scope exit
+    Statement *sbreak;		// enclosing statement that supports "break"
+    Statement *scontinue;	// enclosing statement that supports "continue"
+    ForeachStatement *fes;	// if nested function for ForeachStatement, this is it
+    unsigned offset;		// next offset to use in aggregate
+    int inunion;		// we're processing members of a union
+    int incontract;		// we're inside contract code
+    int nofree;			// set if shouldn't free it
+    int noctor;			// set if constructor calls aren't allowed
+    int intypeof;		// in typeof(exp)
+    int parameterSpecialization; // if in template parameter specialization
+    int noaccesscheck;		// don't do access checks
+
+    unsigned callSuper;		// primitive flow analysis for constructors
+#define	CSXthis_ctor	1	// called this()
+#define CSXsuper_ctor	2	// called super()
+#define CSXthis		4	// referenced this
+#define CSXsuper	8	// referenced super
+#define CSXlabel	0x10	// seen a label
+#define CSXreturn	0x20	// seen a return statement
+#define CSXany_ctor	0x40	// either this() or super() was called
+
+    unsigned structalign;	// alignment for struct members
+    enum LINK linkage;		// linkage for external functions
+
+    enum PROT protection;	// protection for class members
+    int explicitProtection;	// set if in an explicit protection attribute
+
+    unsigned stc;		// storage class
+
+    unsigned flags;
+#define SCOPEctor	1	// constructor type
+#define SCOPEstaticif	2	// inside static if
+#define SCOPEfree	4	// is on free list
+
+    AnonymousAggregateDeclaration *anonAgg;	// for temporary analysis
+
+    DocComment *lastdc;		// documentation comment for last symbol at this scope
+    unsigned lastoffset;	// offset in docbuf of where to insert next dec
+    OutBuffer *docbuf;		// buffer for documentation output
+
+    static Scope *freelist;
+    static void *operator new(size_t sz);
+    static Scope *createGlobal(Module *module);
+
+    Scope();
+    Scope(Module *module);
+    Scope(Scope *enclosing);
+
+    Scope *push();
+    Scope *push(ScopeDsymbol *ss);
+    Scope *pop();
+
+    void mergeCallSuper(Loc loc, unsigned cs);
+
+    Dsymbol *search(Loc loc, Identifier *ident, Dsymbol **pscopesym);
+    Dsymbol *insert(Dsymbol *s);
+
+    ClassDeclaration *getClassScope();
+    AggregateDeclaration *getStructClassScope();
+    void setNoFree();
+};
+
+#endif /* DMD_SCOPE_H */
--- a/dmd2/statement.c	Mon Jun 01 01:28:18 2009 +0200
+++ b/dmd2/statement.c	Mon Jun 01 19:02:20 2009 +0100
@@ -1,4426 +1,4336 @@
-
-// 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 <stdlib.h>
-#include <assert.h>
-
-#include "mem.h"
-
-#include "statement.h"
-#include "expression.h"
-#include "cond.h"
-#include "init.h"
-#include "staticassert.h"
-#include "mtype.h"
-#include "scope.h"
-#include "declaration.h"
-#include "aggregate.h"
-#include "id.h"
-#include "hdrgen.h"
-#include "parse.h"
-#include "template.h"
-
-/******************************** Statement ***************************/
-
-Statement::Statement(Loc loc)
-    : loc(loc)
-{
-#ifdef _DH
-    // If this is an in{} contract scope statement (skip for determining
-    //  inlineStatus of a function body for header content)
-    incontract = 0;
-#endif
-}
-
-Statement *Statement::syntaxCopy()
-{
-    assert(0);
-    return NULL;
-}
-
-void Statement::print()
-{
-    fprintf(stdmsg, "%s\n", toChars());
-    fflush(stdmsg);
-}
-
-char *Statement::toChars()
-{   OutBuffer *buf;
-    HdrGenState hgs;
-
-    buf = new OutBuffer();
-    toCBuffer(buf, &hgs);
-    return buf->toChars();
-}
-
-void Statement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{
-    buf->printf("Statement::toCBuffer()");
-    buf->writenl();
-}
-
-Statement *Statement::semantic(Scope *sc)
-{
-    return this;
-}
-
-// Same as semantic(), but do create a new scope
-
-Statement *Statement::semanticScope(Scope *sc, Statement *sbreak, Statement *scontinue)
-{   Scope *scd;
-    Statement *s;
-
-    scd = sc->push();
-    if (sbreak)
-	scd->sbreak = sbreak;
-    if (scontinue)
-	scd->scontinue = scontinue;
-    s = semantic(scd);
-    scd->pop();
-    return s;
-}
-
-void Statement::error(const char *format, ...)
-{
-    va_list ap;
-    va_start(ap, format);
-    ::verror(loc, format, ap);
-    va_end( ap );
-}
-
-int Statement::hasBreak()
-{
-    //printf("Statement::hasBreak()\n");
-    return FALSE;
-}
-
-int Statement::hasContinue()
-{
-    return FALSE;
-}
-
-// TRUE if statement uses exception handling
-
-int Statement::usesEH()
-{
-    return FALSE;
-}
-
-/* Only valid after semantic analysis
- */
-int Statement::blockExit()
-{
-    printf("Statement::blockExit(%p)\n", this);
-    printf("%s\n", toChars());
-    assert(0);
-    return BEany;
-}
-
-// TRUE if statement may fall off the end without a throw or return
-
-int Statement::fallOffEnd()
-{
-    return TRUE;
-}
-
-// TRUE if statement 'comes from' somewhere else, like a goto
-
-int Statement::comeFrom()
-{
-    //printf("Statement::comeFrom()\n");
-    return FALSE;
-}
-
-/****************************************
- * If this statement has code that needs to run in a finally clause
- * at the end of the current scope, return that code in the form of
- * a Statement.
- * Output:
- *	*sentry		code executed upon entry to the scope
- *	*sexception	code executed upon exit from the scope via exception
- *	*sfinally	code executed in finally block
- */
-
-void Statement::scopeCode(Scope *sc, Statement **sentry, Statement **sexception, Statement **sfinally)
-{
-    //printf("Statement::scopeCode()\n");
-    //print();
-    *sentry = NULL;
-    *sexception = NULL;
-    *sfinally = NULL;
-}
-
-/*********************************
- * Flatten out the scope by presenting the statement
- * as an array of statements.
- * Returns NULL if no flattening necessary.
- */
-
-Statements *Statement::flatten(Scope *sc)
-{
-    return NULL;
-}
-
-
-/******************************** ExpStatement ***************************/
-
-ExpStatement::ExpStatement(Loc loc, Expression *exp)
-    : Statement(loc)
-{
-    this->exp = exp;
-}
-
-Statement *ExpStatement::syntaxCopy()
-{
-    Expression *e = exp ? exp->syntaxCopy() : NULL;
-    ExpStatement *es = new ExpStatement(loc, e);
-    return es;
-}
-
-void ExpStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{
-    if (exp)
-	exp->toCBuffer(buf, hgs);
-    buf->writeByte(';');
-    if (!hgs->FLinit.init)
-        buf->writenl();
-}
-
-Statement *ExpStatement::semantic(Scope *sc)
-{
-    if (exp)
-    {
-	//printf("ExpStatement::semantic() %s\n", exp->toChars());
-	exp = exp->semantic(sc);
-	exp = resolveProperties(sc, exp);
-	exp->checkSideEffect(0);
-	exp = exp->optimize(0);
-	if (exp->op == TOKdeclaration && !isDeclarationStatement())
-	{   Statement *s = new DeclarationStatement(loc, exp);
-	    return s;
-	}
-	//exp = exp->optimize(isDeclarationStatement() ? WANTvalue : 0);
-    }
-    return this;
-}
-
-int ExpStatement::blockExit()
-{   int result = BEfallthru;
-
-    if (exp)
-    {
-	if (exp->op == TOKhalt)
-	    return BEhalt;
-	if (exp->op == TOKassert)
-	{   AssertExp *a = (AssertExp *)exp;
-
-	    if (a->e1->isBool(FALSE))	// if it's an assert(0)
-		return BEhalt;
-	}
-	if (exp->canThrow())
-	    result |= BEthrow;
-    }
-    return result;
-}
-
-int ExpStatement::fallOffEnd()
-{
-    if (exp)
-    {
-	if (exp->op == TOKassert)
-	{   AssertExp *a = (AssertExp *)exp;
-
-	    if (a->e1->isBool(FALSE))	// if it's an assert(0)
-		return FALSE;
-	}
-	else if (exp->op == TOKhalt)
-	    return FALSE;
-    }
-    return TRUE;
-}
-
-/******************************** CompileStatement ***************************/
-
-CompileStatement::CompileStatement(Loc loc, Expression *exp)
-    : Statement(loc)
-{
-    this->exp = exp;
-}
-
-Statement *CompileStatement::syntaxCopy()
-{
-    Expression *e = exp->syntaxCopy();
-    CompileStatement *es = new CompileStatement(loc, e);
-    return es;
-}
-
-void CompileStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{
-    buf->writestring("mixin(");
-    exp->toCBuffer(buf, hgs);
-    buf->writestring(");");
-    if (!hgs->FLinit.init)
-        buf->writenl();
-}
-
-Statements *CompileStatement::flatten(Scope *sc)
-{
-    //printf("CompileStatement::flatten() %s\n", exp->toChars());
-    exp = exp->semantic(sc);
-    exp = resolveProperties(sc, exp);
-    exp = exp->optimize(WANTvalue | WANTinterpret);
-    if (exp->op != TOKstring)
-    {	error("argument to mixin must be a string, not (%s)", exp->toChars());
-	return NULL;
-    }
-    StringExp *se = (StringExp *)exp;
-    se = se->toUTF8(sc);
-    Parser p(sc->module, (unsigned char *)se->string, se->len, 0);
-    p.loc = loc;
-    p.nextToken();
-
-    Statements *a = new Statements();
-    while (p.token.value != TOKeof)
-    {
-	Statement *s = p.parseStatement(PSsemi | PScurlyscope);
-	a->push(s);
-    }
-    return a;
-}
-
-Statement *CompileStatement::semantic(Scope *sc)
-{
-    //printf("CompileStatement::semantic() %s\n", exp->toChars());
-    Statements *a = flatten(sc);
-    if (!a)
-	return NULL;
-    Statement *s = new CompoundStatement(loc, a);
-    return s->semantic(sc);
-}
-
-
-/******************************** DeclarationStatement ***************************/
-
-DeclarationStatement::DeclarationStatement(Loc loc, Dsymbol *declaration)
-    : ExpStatement(loc, new DeclarationExp(loc, declaration))
-{
-}
-
-DeclarationStatement::DeclarationStatement(Loc loc, Expression *exp)
-    : ExpStatement(loc, exp)
-{
-}
-
-Statement *DeclarationStatement::syntaxCopy()
-{
-    DeclarationStatement *ds = new DeclarationStatement(loc, exp->syntaxCopy());
-    return ds;
-}
-
-void DeclarationStatement::scopeCode(Scope *sc, Statement **sentry, Statement **sexception, Statement **sfinally)
-{
-    //printf("DeclarationStatement::scopeCode()\n");
-    //print();
-
-    *sentry = NULL;
-    *sexception = NULL;
-    *sfinally = NULL;
-
-    if (exp)
-    {
-	if (exp->op == TOKdeclaration)
-	{
-	    DeclarationExp *de = (DeclarationExp *)(exp);
-	    VarDeclaration *v = de->declaration->isVarDeclaration();
-	    if (v)
-	    {	Expression *e;
-
-		e = v->callAutoDtor(sc);
-		if (e)
-		{
-		    //printf("dtor is: "); e->print();
-		    *sfinally = new ExpStatement(loc, e);
-		}
-	    }
-	}
-    }
-}
-
-void DeclarationStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{
-    exp->toCBuffer(buf, hgs);
-}
-
-
-/******************************** CompoundStatement ***************************/
-
-CompoundStatement::CompoundStatement(Loc loc, Statements *s)
-    : Statement(loc)
-{
-    statements = s;
-}
-
-CompoundStatement::CompoundStatement(Loc loc, Statement *s1, Statement *s2)
-    : Statement(loc)
-{
-    statements = new Statements();
-    statements->reserve(2);
-    statements->push(s1);
-    statements->push(s2);
-}
-
-Statement *CompoundStatement::syntaxCopy()
-{
-    Statements *a = new Statements();
-    a->setDim(statements->dim);
-    for (size_t i = 0; i < statements->dim; i++)
-    {	Statement *s = (Statement *)statements->data[i];
-	if (s)
-	    s = s->syntaxCopy();
-	a->data[i] = s;
-    }
-    CompoundStatement *cs = new CompoundStatement(loc, a);
-    return cs;
-}
-
-
-Statement *CompoundStatement::semantic(Scope *sc)
-{   Statement *s;
-
-    //printf("CompoundStatement::semantic(this = %p, sc = %p)\n", this, sc);
-
-    for (size_t i = 0; i < statements->dim; )
-    {
-	s = (Statement *) statements->data[i];
-	if (s)
-	{   Statements *a = s->flatten(sc);
-
-	    if (a)
-	    {
-		statements->remove(i);
-		statements->insert(i, a);
-		continue;
-	    }
-	    s = s->semantic(sc);
-	    statements->data[i] = s;
-	    if (s)
-	    {
-		Statement *sentry;
-		Statement *sexception;
-		Statement *sfinally;
-
-		s->scopeCode(sc, &sentry, &sexception, &sfinally);
-		if (sentry)
-		{
-		    sentry = sentry->semantic(sc);
-		    statements->data[i] = sentry;
-		}
-		if (sexception)
-		{
-		    if (i + 1 == statements->dim && !sfinally)
-		    {
-#if 1
-			sexception = sexception->semantic(sc);
-#else
-			statements->push(sexception);
-			if (sfinally)
-			    // Assume sexception does not throw
-			    statements->push(sfinally);
-#endif
-		    }
-		    else
-		    {
-			/* Rewrite:
-			 *	s; s1; s2;
-			 * As:
-			 *	s;
-			 *	try { s1; s2; }
-			 *	catch (Object __o)
-			 *	{ sexception; throw __o; }
-			 */
-			Statement *body;
-			Statements *a = new Statements();
-
-			for (int j = i + 1; j < statements->dim; j++)
-			{
-			    a->push(statements->data[j]);
-			}
-			body = new CompoundStatement(0, a);
-			body = new ScopeStatement(0, body);
-
-			Identifier *id = Lexer::uniqueId("__o");
-
-			Statement *handler = new ThrowStatement(0, new IdentifierExp(0, id));
-			handler = new CompoundStatement(0, sexception, handler);
-
-			Array *catches = new Array();
-			Catch *ctch = new Catch(0, NULL, id, handler);
-			catches->push(ctch);
-			s = new TryCatchStatement(0, body, catches);
-
-			if (sfinally)
-			    s = new TryFinallyStatement(0, s, sfinally);
-			s = s->semantic(sc);
-			statements->setDim(i + 1);
-			statements->push(s);
-			break;
-		    }
-		}
-		else if (sfinally)
-		{
-		    if (0 && i + 1 == statements->dim)
-		    {
-			statements->push(sfinally);
-		    }
-		    else
-		    {
-			/* Rewrite:
-			 *	s; s1; s2;
-			 * As:
-			 *	s; try { s1; s2; } finally { sfinally; }
-			 */
-			Statement *body;
-			Statements *a = new Statements();
-
-			for (int j = i + 1; j < statements->dim; j++)
-			{
-			    a->push(statements->data[j]);
-			}
-			body = new CompoundStatement(0, a);
-			s = new TryFinallyStatement(0, body, sfinally);
-			s = s->semantic(sc);
-			statements->setDim(i + 1);
-			statements->push(s);
-			break;
-		    }
-		}
-	    }
-	}
-	i++;
-    }
-    if (statements->dim == 1 && !isAsmBlockStatement())
-    {
-	return (Statement *)statements->data[0];
-    }
-    return this;
-}
-
-Statements *CompoundStatement::flatten(Scope *sc)
-{
-    return statements;
-}
-
-ReturnStatement *CompoundStatement::isReturnStatement()
-{
-    ReturnStatement *rs = NULL;
-
-    for (int i = 0; i < statements->dim; i++)
-    {	Statement *s = (Statement *) statements->data[i];
-	if (s)
-	{
-	    rs = s->isReturnStatement();
-	    if (rs)
-		break;
-	}
-    }
-    return rs;
-}
-
-void CompoundStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{
-    for (int i = 0; i < statements->dim; i++)
-    {	Statement *s = (Statement *) statements->data[i];
-	if (s)
-	    s->toCBuffer(buf, hgs);
-    }
-}
-
-int CompoundStatement::usesEH()
-{
-    for (int i = 0; i < statements->dim; i++)
-    {	Statement *s = (Statement *) statements->data[i];
-	if (s && s->usesEH())
-	    return TRUE;
-    }
-    return FALSE;
-}
-
-int CompoundStatement::blockExit()
-{
-    //printf("CompoundStatement::blockExit(%p) %d\n", this, statements->dim);
-    int result = BEfallthru;
-    for (size_t i = 0; i < statements->dim; i++)
-    {	Statement *s = (Statement *) statements->data[i];
-	if (s)
-	{
-//printf("result = x%x\n", result);
-//printf("%s\n", s->toChars());
-	    if (!(result & BEfallthru) && !s->comeFrom())
-	    {
-		if (global.params.warnings)
-		{   fprintf(stdmsg, "warning - ");
-		    s->error("statement is not reachable");
-		}
-	    }
-
-	    result &= ~BEfallthru;
-	    result |= s->blockExit();
-	}
-    }
-    return result;
-}
-
-int CompoundStatement::fallOffEnd()
-{   int falloff = TRUE;
-
-    //printf("CompoundStatement::fallOffEnd() %s\n", toChars());
-    for (int i = 0; i < statements->dim; i++)
-    {	Statement *s = (Statement *)statements->data[i];
-
-	if (!s)
-	    continue;
-
-#if 0
-	if (!falloff && global.params.warnings && !s->comeFrom())
-	{
-	    warning("%s: statement is not reachable", s->loc.toChars());
-	}
-#endif
-	falloff = s->fallOffEnd();
-    }
-    return falloff;
-}
-
-int CompoundStatement::comeFrom()
-{   int comefrom = FALSE;
-
-    //printf("CompoundStatement::comeFrom()\n");
-    for (int i = 0; i < statements->dim; i++)
-    {	Statement *s = (Statement *)statements->data[i];
-
-	if (!s)
-	    continue;
-
-	comefrom |= s->comeFrom();
-    }
-    return comefrom;
-}
-
-
-/**************************** UnrolledLoopStatement ***************************/
-
-UnrolledLoopStatement::UnrolledLoopStatement(Loc loc, Statements *s)
-    : Statement(loc)
-{
-    statements = s;
-    enclosinghandler = NULL;
-}
-
-Statement *UnrolledLoopStatement::syntaxCopy()
-{
-    Statements *a = new Statements();
-    a->setDim(statements->dim);
-    for (size_t i = 0; i < statements->dim; i++)
-    {	Statement *s = (Statement *)statements->data[i];
-	if (s)
-	    s = s->syntaxCopy();
-	a->data[i] = s;
-    }
-    UnrolledLoopStatement *cs = new UnrolledLoopStatement(loc, a);
-    return cs;
-}
-
-
-Statement *UnrolledLoopStatement::semantic(Scope *sc)
-{
-    //printf("UnrolledLoopStatement::semantic(this = %p, sc = %p)\n", this, sc);
-
-    enclosinghandler = sc->tfOfTry;
-
-    sc->noctor++;
-    Scope *scd = sc->push();
-    scd->sbreak = this;
-    scd->scontinue = this;
-
-    for (size_t i = 0; i < statements->dim; i++)
-    {
-	Statement *s = (Statement *) statements->data[i];
-	if (s)
-	{
-	    s = s->semantic(scd);
-	    statements->data[i] = s;
-	}
-    }
-
-    scd->pop();
-    sc->noctor--;
-    return this;
-}
-
-void UnrolledLoopStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{
-    buf->writestring("unrolled {");
-    buf->writenl();
-
-    for (size_t i = 0; i < statements->dim; i++)
-    {	Statement *s;
-
-	s = (Statement *) statements->data[i];
-	if (s)
-	    s->toCBuffer(buf, hgs);
-    }
-
-    buf->writeByte('}');
-    buf->writenl();
-}
-
-int UnrolledLoopStatement::hasBreak()
-{
-    return TRUE;
-}
-
-int UnrolledLoopStatement::hasContinue()
-{
-    return TRUE;
-}
-
-int UnrolledLoopStatement::usesEH()
-{
-    for (size_t i = 0; i < statements->dim; i++)
-    {	Statement *s = (Statement *) statements->data[i];
-	if (s && s->usesEH())
-	    return TRUE;
-    }
-    return FALSE;
-}
-
-int UnrolledLoopStatement::blockExit()
-{
-    int result = BEfallthru;
-    for (size_t i = 0; i < statements->dim; i++)
-    {	Statement *s = (Statement *) statements->data[i];
-	if (s)
-	{
-	    int r = s->blockExit();
-	    result |= r & ~(BEbreak | BEcontinue);
-	}
-    }
-    return result;
-}
-
-int UnrolledLoopStatement::fallOffEnd()
-{
-    //printf("UnrolledLoopStatement::fallOffEnd()\n");
-    for (size_t i = 0; i < statements->dim; i++)
-    {	Statement *s = (Statement *)statements->data[i];
-
-	if (s)
-	    s->fallOffEnd();
-    }
-    return TRUE;
-}
-
-int UnrolledLoopStatement::comeFrom()
-{   int comefrom = FALSE;
-
-    //printf("UnrolledLoopStatement::comeFrom()\n");
-    for (size_t i = 0; i < statements->dim; i++)
-    {	Statement *s = (Statement *)statements->data[i];
-
-	if (!s)
-	    continue;
-
-	comefrom |= s->comeFrom();
-    }
-    return comefrom;
-}
-
-
-/******************************** ScopeStatement ***************************/
-
-ScopeStatement::ScopeStatement(Loc loc, Statement *s)
-    : Statement(loc)
-{
-    this->statement = s;
-}
-
-Statement *ScopeStatement::syntaxCopy()
-{
-    Statement *s;
-
-    s = statement ? statement->syntaxCopy() : NULL;
-    s = new ScopeStatement(loc, s);
-    return s;
-}
-
-
-Statement *ScopeStatement::semantic(Scope *sc)
-{   ScopeDsymbol *sym;
-
-    //printf("ScopeStatement::semantic(sc = %p)\n", sc);
-    if (statement)
-    {	Statements *a;
-
-	sym = new ScopeDsymbol();
-	sym->parent = sc->scopesym;
-	sc = sc->push(sym);
-
-	a = statement->flatten(sc);
-	if (a)
-	{
-	    statement = new CompoundStatement(loc, a);
-	}
-
-	statement = statement->semantic(sc);
-	if (statement)
-	{
-	    Statement *sentry;
-	    Statement *sexception;
-	    Statement *sfinally;
-
-	    statement->scopeCode(sc, &sentry, &sexception, &sfinally);
-	    if (sfinally)
-	    {
-		//printf("adding sfinally\n");
-		statement = new CompoundStatement(loc, statement, sfinally);
-	    }
-	}
-
-	sc->pop();
-    }
-    return this;
-}
-
-int ScopeStatement::hasBreak()
-{
-    //printf("ScopeStatement::hasBreak() %s\n", toChars());
-    return statement ? statement->hasBreak() : FALSE;
-}
-
-int ScopeStatement::hasContinue()
-{
-    return statement ? statement->hasContinue() : FALSE;
-}
-
-int ScopeStatement::usesEH()
-{
-    return statement ? statement->usesEH() : FALSE;
-}
-
-int ScopeStatement::blockExit()
-{
-    //printf("ScopeStatement::blockExit(%p)\n", statement);
-    return statement ? statement->blockExit() : BEfallthru;
-}
-
-int ScopeStatement::fallOffEnd()
-{
-    return statement ? statement->fallOffEnd() : TRUE;
-}
-
-int ScopeStatement::comeFrom()
-{
-    //printf("ScopeStatement::comeFrom()\n");
-    return statement ? statement->comeFrom() : FALSE;
-}
-
-void ScopeStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{
-    buf->writeByte('{');
-    buf->writenl();
-
-    if (statement)
-	statement->toCBuffer(buf, hgs);
-
-    buf->writeByte('}');
-    buf->writenl();
-}
-
-/******************************** WhileStatement ***************************/
-
-WhileStatement::WhileStatement(Loc loc, Expression *c, Statement *b)
-    : Statement(loc)
-{
-    condition = c;
-    body = b;
-    enclosinghandler = NULL;
-}
-
-Statement *WhileStatement::syntaxCopy()
-{
-    WhileStatement *s = new WhileStatement(loc, condition->syntaxCopy(), body ? body->syntaxCopy() : NULL);
-    return s;
-}
-
-
-Statement *WhileStatement::semantic(Scope *sc)
-{
-#if 0
-    if (condition->op == TOKmatch)
-    {
-	/* Rewrite while (condition) body as:
-	 *   if (condition)
-	 *     do
-	 *       body
-	 *     while ((_match = _match.opNext), _match);
-	 */
-
-	Expression *ew = new IdentifierExp(0, Id::_match);
-	ew = new DotIdExp(0, ew, Id::next);
-	ew = new AssignExp(0, new IdentifierExp(0, Id::_match), ew);
-	////ew = new EqualExp(TOKnotequal, 0, ew, new NullExp(0));
-	Expression *ev = new IdentifierExp(0, Id::_match);
-	//ev = new CastExp(0, ev, Type::tvoidptr);
-	ew = new CommaExp(0, ew, ev);
-	Statement *sw = new DoStatement(loc, body, ew);
-	Statement *si = new IfStatement(loc, condition, sw, NULL);
-	return si->semantic(sc);
-    }
-#endif
-
-    enclosinghandler = sc->tfOfTry;
-
-    condition = condition->semantic(sc);
-    condition = resolveProperties(sc, condition);
-    condition = condition->optimize(WANTvalue);
-    condition = condition->checkToBoolean();
-
-    sc->noctor++;
-
-    Scope *scd = sc->push();
-    scd->sbreak = this;
-    scd->scontinue = this;
-    if (body)
-	body = body->semantic(scd);
-    scd->pop();
-
-    sc->noctor--;
-
-    return this;
-}
-
-int WhileStatement::hasBreak()
-{
-    return TRUE;
-}
-
-int WhileStatement::hasContinue()
-{
-    return TRUE;
-}
-
-int WhileStatement::usesEH()
-{
-    return body ? body->usesEH() : 0;
-}
-
-int WhileStatement::blockExit()
-{
-    //printf("WhileStatement::blockExit(%p)\n", this);
-
-    int result = BEnone;
-    if (condition->canThrow())
-	result |= BEthrow;
-    if (condition->isBool(TRUE))
-    {
-	if (body)
-	{   result |= body->blockExit();
-	    if (result & BEbreak)
-		result |= BEfallthru;
-	}
-    }
-    else if (condition->isBool(FALSE))
-    {
-	result |= BEfallthru;
-    }
-    else
-    {
-	if (body)
-	    result |= body->blockExit();
-	result |= BEfallthru;
-    }
-    result &= ~(BEbreak | BEcontinue);
-    return result;
-}
-
-int WhileStatement::fallOffEnd()
-{
-    if (body)
-	body->fallOffEnd();
-    return TRUE;
-}
-
-int WhileStatement::comeFrom()
-{
-    if (body)
-	return body->comeFrom();
-    return FALSE;
-}
-
-void WhileStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{
-    buf->writestring("while (");
-    condition->toCBuffer(buf, hgs);
-    buf->writebyte(')');
-    buf->writenl();
-    if (body)
-	body->toCBuffer(buf, hgs);
-}
-
-/******************************** DoStatement ***************************/
-
-DoStatement::DoStatement(Loc loc, Statement *b, Expression *c)
-    : Statement(loc)
-{
-    body = b;
-    condition = c;
-    enclosinghandler = NULL;
-}
-
-Statement *DoStatement::syntaxCopy()
-{
-    DoStatement *s = new DoStatement(loc, body ? body->syntaxCopy() : NULL, condition->syntaxCopy());
-    return s;
-}
-
-
-Statement *DoStatement::semantic(Scope *sc)
-{
-    enclosinghandler = sc->tfOfTry;
-
-    sc->noctor++;
-    if (body)
-	body = body->semanticScope(sc, this, this);
-    sc->noctor--;
-    condition = condition->semantic(sc);
-    condition = resolveProperties(sc, condition);
-    condition = condition->optimize(WANTvalue);
-
-    condition = condition->checkToBoolean();
-
-    return this;
-}
-
-int DoStatement::hasBreak()
-{
-    return TRUE;
-}
-
-int DoStatement::hasContinue()
-{
-    return TRUE;
-}
-
-int DoStatement::usesEH()
-{
-    return body ? body->usesEH() : 0;
-}
-
-int DoStatement::blockExit()
-{   int result;
-
-    if (body)
-    {	result = body->blockExit();
-	if (result == BEbreak)
-	    return BEfallthru;
-	if (result & BEcontinue)
-	    result |= BEfallthru;
-    }
-    else
-	result = BEfallthru;
-    if (result & BEfallthru)
-    {	if (condition->canThrow())
-	    result |= BEthrow;
-	if (!(result & BEbreak) && condition->isBool(TRUE))
-	    result &= ~BEfallthru;
-    }
-    result &= ~(BEbreak | BEcontinue);
-    return result;
-}
-
-int DoStatement::fallOffEnd()
-{
-    if (body)
-	body->fallOffEnd();
-    return TRUE;
-}
-
-int DoStatement::comeFrom()
-{
-    if (body)
-	return body->comeFrom();
-    return FALSE;
-}
-
-void DoStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{
-    buf->writestring("do");
-    buf->writenl();
-    if (body)
-	body->toCBuffer(buf, hgs);
-    buf->writestring("while (");
-    condition->toCBuffer(buf, hgs);
-    buf->writebyte(')');
-}
-
-/******************************** ForStatement ***************************/
-
-ForStatement::ForStatement(Loc loc, Statement *init, Expression *condition, Expression *increment, Statement *body)
-    : Statement(loc)
-{
-    this->init = init;
-    this->condition = condition;
-    this->increment = increment;
-    this->body = body;
-    this->enclosinghandler = NULL;
-}
-
-Statement *ForStatement::syntaxCopy()
-{
-    Statement *i = NULL;
-    if (init)
-	i = init->syntaxCopy();
-    Expression *c = NULL;
-    if (condition)
-	c = condition->syntaxCopy();
-    Expression *inc = NULL;
-    if (increment)
-	inc = increment->syntaxCopy();
-    ForStatement *s = new ForStatement(loc, i, c, inc, body->syntaxCopy());
-    return s;
-}
-
-Statement *ForStatement::semantic(Scope *sc)
-{
-    enclosinghandler = sc->tfOfTry;
-
-    ScopeDsymbol *sym = new ScopeDsymbol();
-    sym->parent = sc->scopesym;
-    sc = sc->push(sym);
-    if (init)
-	init = init->semantic(sc);
-    sc->noctor++;
-    if (condition)
-    {
-	condition = condition->semantic(sc);
-	condition = resolveProperties(sc, condition);
-	condition = condition->optimize(WANTvalue);
-	condition = condition->checkToBoolean();
-    }
-    if (increment)
-    {	increment = increment->semantic(sc);
-	increment = resolveProperties(sc, increment);
-    }
-
-    sc->sbreak = this;
-    sc->scontinue = this;
-    body = body->semantic(sc);
-    sc->noctor--;
-
-    sc->pop();
-    return this;
-}
-
-void ForStatement::scopeCode(Scope *sc, Statement **sentry, Statement **sexception, Statement **sfinally)
-{
-    //printf("ForStatement::scopeCode()\n");
-    //print();
-    if (init)
-	init->scopeCode(sc, sentry, sexception, sfinally);
-    else
-	Statement::scopeCode(sc, sentry, sexception, sfinally);
-}
-
-int ForStatement::hasBreak()
-{
-    //printf("ForStatement::hasBreak()\n");
-    return TRUE;
-}
-
-int ForStatement::hasContinue()
-{
-    return TRUE;
-}
-
-int ForStatement::usesEH()
-{
-    return (init && init->usesEH()) || body->usesEH();
-}
-
-int ForStatement::blockExit()
-{   int result = BEfallthru;
-
-    if (init)
-    {	result = init->blockExit();
-	if (!(result & BEfallthru))
-	    return result;
-    }
-    if (condition)
-    {	if (condition->canThrow())
-	    result |= BEthrow;
-    }
-    else
-	result &= ~BEfallthru;	// the body must do the exiting
-    if (body)
-    {	int r = body->blockExit();
-	if (r & BEbreak)
-	    result |= BEfallthru;
-	result |= r & ~(BEbreak | BEcontinue);
-    }
-    if (increment && increment->canThrow())
-	result |= BEthrow;
-    return result;
-}
-
-int ForStatement::fallOffEnd()
-{
-    if (body)
-	body->fallOffEnd();
-    return TRUE;
-}
-
-int ForStatement::comeFrom()
-{
-    //printf("ForStatement::comeFrom()\n");
-    if (body)
-    {	int result = body->comeFrom();
-	//printf("result = %d\n", result);
-	return result;
-    }
-    return FALSE;
-}
-
-void ForStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{
-    buf->writestring("for (");
-    if (init)
-    {
-        hgs->FLinit.init++;
-        hgs->FLinit.decl = 0;
-        init->toCBuffer(buf, hgs);
-        if (hgs->FLinit.decl > 0)
-            buf->writebyte(';');
-        hgs->FLinit.decl = 0;
-        hgs->FLinit.init--;
-    }
-    else
-        buf->writebyte(';');
-    if (condition)
-    {   buf->writebyte(' ');
-        condition->toCBuffer(buf, hgs);
-    }
-    buf->writebyte(';');
-    if (increment)
-    {   buf->writebyte(' ');
-        increment->toCBuffer(buf, hgs);
-    }
-    buf->writebyte(')');
-    buf->writenl();
-    buf->writebyte('{');
-    buf->writenl();
-    body->toCBuffer(buf, hgs);
-    buf->writebyte('}');
-    buf->writenl();
-}
-
-/******************************** ForeachStatement ***************************/
-
-ForeachStatement::ForeachStatement(Loc loc, enum TOK op, Arguments *arguments,
-	Expression *aggr, Statement *body)
-    : Statement(loc)
-{
-    this->op = op;
-    this->arguments = arguments;
-    this->aggr = aggr;
-    this->body = body;
-    this->enclosinghandler = NULL;
-
-    this->key = NULL;
-    this->value = NULL;
-
-    this->func = NULL;
-}
-
-Statement *ForeachStatement::syntaxCopy()
-{
-    Arguments *args = Argument::arraySyntaxCopy(arguments);
-    Expression *exp = aggr->syntaxCopy();
-    ForeachStatement *s = new ForeachStatement(loc, op, args, exp,
-	body ? body->syntaxCopy() : NULL);
-    return s;
-}
-
-Statement *ForeachStatement::semantic(Scope *sc)
-{
-    //printf("ForeachStatement::semantic() %p\n", this);
-    ScopeDsymbol *sym;
-    Statement *s = this;
-    size_t dim = arguments->dim;
-    TypeAArray *taa = NULL;
-
-    Type *tn = NULL;
-    Type *tnv = NULL;
-
-    enclosinghandler = sc->tfOfTry;
-
-    func = sc->func;
-    if (func->fes)
-	func = func->fes->func;
-
-    aggr = aggr->semantic(sc);
-    aggr = resolveProperties(sc, aggr);
-    aggr = aggr->optimize(WANTvalue);
-    if (!aggr->type)
-    {
-	error("invalid foreach aggregate %s", aggr->toChars());
-	return this;
-    }
-
-    inferApplyArgTypes(op, arguments, aggr);
-
-    /* Check for inference errors
-     */
-    if (dim != arguments->dim)
-    {
-	//printf("dim = %d, arguments->dim = %d\n", dim, arguments->dim);
-	error("cannot uniquely infer foreach argument types");
-	return this;
-    }
-
-    Type *tab = aggr->type->toBasetype();
-
-    if (tab->ty == Ttuple)	// don't generate new scope for tuple loops
-    {
-	if (dim < 1 || dim > 2)
-	{
-	    error("only one (value) or two (key,value) arguments for tuple foreach");
-	    return s;
-	}
-
-	TypeTuple *tuple = (TypeTuple *)tab;
-	Statements *statements = new Statements();
-	//printf("aggr: op = %d, %s\n", aggr->op, aggr->toChars());
-	size_t n;
-	TupleExp *te = NULL;
-	if (aggr->op == TOKtuple)	// expression tuple
-	{   te = (TupleExp *)aggr;
-	    n = te->exps->dim;
-	}
-	else if (aggr->op == TOKtype)	// type tuple
-	{
-	    n = Argument::dim(tuple->arguments);
-	}
-	else
-	    assert(0);
-	for (size_t j = 0; j < n; j++)
-	{   size_t k = (op == TOKforeach) ? j : n - 1 - j;
-	    Expression *e;
-	    Type *t;
-	    if (te)
-		e = (Expression *)te->exps->data[k];
-	    else
-		t = Argument::getNth(tuple->arguments, k)->type;
-	    Argument *arg = (Argument *)arguments->data[0];
-	    Statements *st = new Statements();
-
-	    if (dim == 2)
-	    {   // Declare key
-		if (arg->storageClass & (STCout | STCref | STClazy))
-		    error("no storage class for key %s", arg->ident->toChars());
-		TY keyty = arg->type->ty;
-        if (global.params.is64bit)
-        {
-            if (keyty != Tint32 && keyty != Tuns32 && keyty != Tint64 && keyty != Tuns64)
-            {
-                error("foreach: key type must be int, uint, long or ulong, not %s", key->type->toChars());
-            }
-        }
-        else if (keyty != Tint32 && keyty != Tuns32)
-        {
-            error("foreach: key type must be int or uint, not %s", key->type->toChars());
-        }
-		Initializer *ie = new ExpInitializer(0, new IntegerExp(k));
-		VarDeclaration *var = new VarDeclaration(loc, arg->type, arg->ident, ie);
-		var->storage_class |= STCmanifest;
-		DeclarationExp *de = new DeclarationExp(loc, var);
-		st->push(new ExpStatement(loc, de));
-		arg = (Argument *)arguments->data[1];	// value
-	    }
-	    // Declare value
-	    if (arg->storageClass & (STCout | STCref | STClazy))
-		error("no storage class for value %s", arg->ident->toChars());
-	    Dsymbol *var;
-	    if (te)
-	    {	Type *tb = e->type->toBasetype();
-		if ((tb->ty == Tfunction || tb->ty == Tsarray) && e->op == TOKvar)
-		{   VarExp *ve = (VarExp *)e;
-		    var = new AliasDeclaration(loc, arg->ident, ve->var);
-		}
-		else
-		{
-		    arg->type = e->type;
-		    Initializer *ie = new ExpInitializer(0, e);
-		    VarDeclaration *v = new VarDeclaration(loc, arg->type, arg->ident, ie);
-		    if (e->isConst())
-			v->storage_class |= STCconst;
-		    var = v;
-		}
-	    }
-	    else
-	    {
-		var = new AliasDeclaration(loc, arg->ident, t);
-	    }
-	    DeclarationExp *de = new DeclarationExp(loc, var);
-	    st->push(new ExpStatement(loc, de));
-
-	    st->push(body->syntaxCopy());
-	    s = new CompoundStatement(loc, st);
-	    s = new ScopeStatement(loc, s);
-	    statements->push(s);
-	}
-
-	s = new UnrolledLoopStatement(loc, statements);
-	s = s->semantic(sc);
-	return s;
-    }
-
-    sym = new ScopeDsymbol();
-    sym->parent = sc->scopesym;
-    sc = sc->push(sym);
-
-    sc->noctor++;
-
-    switch (tab->ty)
-    {
-	case Tarray:
-	case Tsarray:
-	    if (!checkForArgTypes())
-		return this;
-
-	    if (dim < 1 || dim > 2)
-	    {
-		error("only one or two arguments for array foreach");
-		break;
-	    }
-
-	    /* Look for special case of parsing char types out of char type
-	     * array.
-	     */
-	    tn = tab->nextOf()->toBasetype();
-	    if (tn->ty == Tchar || tn->ty == Twchar || tn->ty == Tdchar)
-	    {	Argument *arg;
-
-		int i = (dim == 1) ? 0 : 1;	// index of value
-		arg = (Argument *)arguments->data[i];
-		arg->type = arg->type->semantic(loc, sc);
-		tnv = arg->type->toBasetype();
-		if (tnv->ty != tn->ty &&
-		    (tnv->ty == Tchar || tnv->ty == Twchar || tnv->ty == Tdchar))
-		{
-		    if (arg->storageClass & STCref)
-			error("foreach: value of UTF conversion cannot be ref");
-		    if (dim == 2)
-		    {	arg = (Argument *)arguments->data[0];
-			if (arg->storageClass & STCref)
-			    error("foreach: key cannot be ref");
-		    }
-		    goto Lapply;
-		}
-	    }
-
-	    for (size_t i = 0; i < dim; i++)
-	    {	// Declare args
-		Argument *arg = (Argument *)arguments->data[i];
-		VarDeclaration *var;
-
-		var = new VarDeclaration(loc, arg->type, arg->ident, NULL);
-		var->storage_class |= STCforeach;
-		var->storage_class |= arg->storageClass & (STCin | STCout | STCref | STCconst | STCinvariant);
-		if (dim == 2 && i == 0)
-		{   key = var;
-		    //var->storage_class |= STCfinal;
-		}
-		else
-		{
-		    value = var;
-		    /* Reference to immutable data should be marked as const
-		     */
-		    if (var->storage_class & STCref && !tn->isMutable())
-		    {
-			var->storage_class |= STCconst;
-		    }
-		}
-#if 1
-		DeclarationExp *de = new DeclarationExp(loc, var);
-		de->semantic(sc);
-#else
-		var->semantic(sc);
-		if (!sc->insert(var))
-		    error("%s already defined", var->ident->toChars());
-#endif
-	    }
-
-	    sc->sbreak = this;
-	    sc->scontinue = this;
-	    body = body->semantic(sc);
-
-	    if (tab->nextOf()->implicitConvTo(value->type) < MATCHconst)
-	    {
-		if (aggr->op == TOKstring)
-		    aggr = aggr->implicitCastTo(sc, value->type->arrayOf());
-		else
-		    error("foreach: %s is not an array of %s",
-			tab->toChars(), value->type->toChars());
-	    }
-
-        if (key)
-        {
-            if (global.params.is64bit)
-            {
-                if (key->type->ty != Tint32 && key->type->ty != Tuns32 && key->type->ty != Tint64 && key->type->ty != Tuns64)
-                {
-                    error("foreach: key type must be int, uint, long or ulong, not %s", key->type->toChars());
-                }
-            }
-            else if (key->type->ty != Tint32 && key->type->ty != Tuns32)
-            {
-                error("foreach: key type must be int or uint, not %s", key->type->toChars());
-            }
-        }
-
-	    if (key && key->storage_class & (STCout | STCref))
-		error("foreach: key cannot be out or ref");
-	    break;
-
-	case Taarray:
-	    if (!checkForArgTypes())
-		return this;
-
-	    taa = (TypeAArray *)tab;
-	    if (dim < 1 || dim > 2)
-	    {
-		error("only one or two arguments for associative array foreach");
-		break;
-	    }
-	    if (op == TOKforeach_reverse)
-	    {
-		error("no reverse iteration on associative arrays");
-	    }
-	    goto Lapply;
-
-	case Tclass:
-	case Tstruct:
-#if DMDV2
-	{   /* Look for range iteration, i.e. the properties
-	     * .empty, .next, .retreat, .head and .rear
-	     *    foreach (e; range) { ... }
-	     * translates to:
-	     *    for (auto __r = range; !__r.empty; __r.next)
-	     *    {   auto e = __r.head;
-	     *        ...
-	     *    }
-	     */
-	    if (dim != 1)	// only one argument allowed with ranges
-		goto Lapply;
-	    AggregateDeclaration *ad = (tab->ty == Tclass)
-			? (AggregateDeclaration *)((TypeClass  *)tab)->sym
-			: (AggregateDeclaration *)((TypeStruct *)tab)->sym;
-	    Identifier *idhead;
-	    Identifier *idnext;
-	    if (op == TOKforeach)
-	    {	idhead = Id::Fhead;
-		idnext = Id::Fnext;
-	    }
-	    else
-	    {	idhead = Id::Ftoe;
-		idnext = Id::Fretreat;
-	    }
-	    Dsymbol *shead = search_function(ad, idhead);
-	    if (!shead)
-		goto Lapply;
-
-	    /* Generate a temporary __r and initialize it with the aggregate.
-	     */
-	    Identifier *id = Identifier::generateId("__r");
-	    VarDeclaration *r = new VarDeclaration(loc, NULL, id, new ExpInitializer(loc, aggr));
-	    r->semantic(sc);
-	    Statement *init = new DeclarationStatement(loc, r);
-
-	    // !__r.empty
-	    Expression *e = new VarExp(loc, r);
-	    e = new DotIdExp(loc, e, Id::Fempty);
-	    Expression *condition = new NotExp(loc, e);
-
-	    // __r.next
-	    e = new VarExp(loc, r);
-	    Expression *increment = new DotIdExp(loc, e, idnext);
-
-	    /* Declaration statement for e:
-	     *    auto e = __r.idhead;
-	     */
-	    e = new VarExp(loc, r);
-	    Expression *einit = new DotIdExp(loc, e, idhead);
-	    einit = einit->semantic(sc);
-	    Argument *arg = (Argument *)arguments->data[0];
-	    VarDeclaration *ve = new VarDeclaration(loc, arg->type, arg->ident, new ExpInitializer(loc, einit));
-	    ve->storage_class |= STCforeach;
-	    ve->storage_class |= arg->storageClass & (STCin | STCout | STCref | STCconst | STCinvariant);
-
-	    DeclarationExp *de = new DeclarationExp(loc, ve);
-
-	    Statement *body = new CompoundStatement(loc,
-		new DeclarationStatement(loc, de), this->body);
-
-	    s = new ForStatement(loc, init, condition, increment, body);
-	    s = s->semantic(sc);
-	    break;
-	}
-#endif
-	case Tdelegate:
-	Lapply:
-	{   FuncDeclaration *fdapply;
-	    Arguments *args;
-	    Expression *ec;
-	    Expression *e;
-	    FuncLiteralDeclaration *fld;
-	    Argument *a;
-	    Type *t;
-	    Expression *flde;
-	    Identifier *id;
-	    Type *tret;
-        TypeDelegate* dgty;
-        TypeDelegate* dgty2;
-        TypeDelegate* fldeTy;
-
-	    if (!checkForArgTypes())
-		return this;
-
-	    tret = func->type->nextOf();
-
-	    // Need a variable to hold value from any return statements in body.
-	    if (!sc->func->vresult && tret && tret != Type::tvoid)
-	    {	VarDeclaration *v;
-
-		v = new VarDeclaration(loc, tret, Id::result, NULL);
-		v->noauto = 1;
-		v->semantic(sc);
-		if (!sc->insert(v))
-		    assert(0);
-		v->parent = sc->func;
-		sc->func->vresult = v;
-	    }
-
-	    /* Turn body into the function literal:
-	     *	int delegate(ref T arg) { body }
-	     */
-	    args = new Arguments();
-	    for (size_t i = 0; i < dim; i++)
-	    {	Argument *arg = (Argument *)arguments->data[i];
-
-		arg->type = arg->type->semantic(loc, sc);
-		if (arg->storageClass & STCref)
-		    id = arg->ident;
-		else
-		{   // Make a copy of the ref argument so it isn't
-		    // a reference.
-		    VarDeclaration *v;
-		    Initializer *ie;
-
-		    id = Lexer::uniqueId("__applyArg", i);
-
-		    ie = new ExpInitializer(0, new IdentifierExp(0, id));
-		    v = new VarDeclaration(0, arg->type, arg->ident, ie);
-		    s = new DeclarationStatement(0, v);
-		    body = new CompoundStatement(loc, s, body);
-		}
-		a = new Argument(STCref, arg->type, id, NULL);
-		args->push(a);
-	    }
-	    t = new TypeFunction(args, Type::tint32, 0, LINKd);
-	    fld = new FuncLiteralDeclaration(loc, 0, t, TOKdelegate, this);
-	    fld->fbody = body;
-	    flde = new FuncExp(loc, fld);
-	    flde = flde->semantic(sc);
-	    fld->tookAddressOf = 0;
-
-	    // Resolve any forward referenced goto's
-	    for (int i = 0; i < gotos.dim; i++)
-	    {	CompoundStatement *cs = (CompoundStatement *)gotos.data[i];
-		GotoStatement *gs = (GotoStatement *)cs->statements->data[0];
-
-		if (!gs->label->statement)
-		{   // 'Promote' it to this scope, and replace with a return
-		    cases.push(gs);
-		    s = new ReturnStatement(0, new IntegerExp(cases.dim + 1));
-		    cs->statements->data[0] = (void *)s;
-		}
-	    }
-
-	    if (tab->ty == Taarray)
-	    {
-		// Check types
-		Argument *arg = (Argument *)arguments->data[0];
-		if (dim == 2)
-		{
-		    if (arg->storageClass & STCref)
-			error("foreach: index cannot be ref");
-		    if (!arg->type->equals(taa->index))
-			error("foreach: index must be type %s, not %s", taa->index->toChars(), arg->type->toChars());
-		    arg = (Argument *)arguments->data[1];
-		}
-		if (!arg->type->equals(taa->nextOf()))
-		    error("foreach: value must be type %s, not %s", taa->nextOf()->toChars(), arg->type->toChars());
-
-		/* Call:
-		 *	_aaApply(aggr, keysize, flde)
-		 */
-		//LDC: Build arguments.
-		static FuncDeclaration *aaApply2_fd = NULL;
-        static TypeDelegate* aaApply2_dg;
-		if(!aaApply2_fd) {
-		    Arguments* args = new Arguments;
-		    args->push(new Argument(STCin, Type::tvoid->pointerTo(), NULL, NULL));
-		    args->push(new Argument(STCin, Type::tsize_t, NULL, NULL));
-		    Arguments* dgargs = new Arguments;
-		    dgargs->push(new Argument(STCin, Type::tvoidptr, NULL, NULL));
-		    dgargs->push(new Argument(STCin, Type::tvoidptr, NULL, NULL));
-		    aaApply2_dg = new TypeDelegate(new TypeFunction(dgargs, Type::tindex, 0, LINKd));
-		    args->push(new Argument(STCin, aaApply2_dg, NULL, NULL));
-		    aaApply2_fd = FuncDeclaration::genCfunc(args, Type::tindex, "_aaApply2");
-		}
-		static FuncDeclaration *aaApply_fd = NULL;
-        static TypeDelegate* aaApply_dg;
-		if(!aaApply_fd) {
-		    Arguments* args = new Arguments;
-		    args->push(new Argument(STCin, Type::tvoid->pointerTo(), NULL, NULL));
-		    args->push(new Argument(STCin, Type::tsize_t, NULL, NULL));
-		    Arguments* dgargs = new Arguments;
-		    dgargs->push(new Argument(STCin, Type::tvoidptr, NULL, NULL));
-		    aaApply_dg = new TypeDelegate(new TypeFunction(dgargs, Type::tindex, 0, LINKd));
-		    args->push(new Argument(STCin, aaApply_dg, NULL, NULL));
-		    aaApply_fd = FuncDeclaration::genCfunc(args, Type::tindex, "_aaApply");
-		}
-		if (dim == 2) {
-		    fdapply = aaApply2_fd;
-            fldeTy = aaApply2_dg;
-		} else {
-		    fdapply = aaApply_fd;
-            fldeTy = aaApply_dg;
-		}
-		ec = new VarExp(0, fdapply);
-		Expressions *exps = new Expressions();
-		exps->push(aggr);
-		size_t keysize = taa->index->size();
-		keysize = (keysize + (PTRSIZE-1)) & ~(PTRSIZE-1);
-		exps->push(new IntegerExp(0, keysize, Type::tsize_t));
-
-        // LDC paint delegate argument to the type runtime expects
-        if (!fldeTy->equals(flde->type))
-        {
-            flde = new CastExp(loc, flde, flde->type);
-            flde->type = fldeTy;
-        }
-		exps->push(flde);
-
-		e = new CallExp(loc, ec, exps);
-		e->type = Type::tindex;	// don't run semantic() on e
-	    }
-	    else if (tab->ty == Tarray || tab->ty == Tsarray)
-	    {
-		/* Call:
-		 *	_aApply(aggr, flde)
-		 */
-		static char fntab[9][3] =
-		{ "cc","cw","cd",
-		  "wc","cc","wd",
-		  "dc","dw","dd"
-		};
-		char fdname[7+1+2+ sizeof(dim)*3 + 1];
-		int flag;
-
-		switch (tn->ty)
-		{
-		    case Tchar:		flag = 0; break;
-		    case Twchar:	flag = 3; break;
-		    case Tdchar:	flag = 6; break;
-		    default:		assert(0);
-		}
-		switch (tnv->ty)
-		{
-		    case Tchar:		flag += 0; break;
-		    case Twchar:	flag += 1; break;
-		    case Tdchar:	flag += 2; break;
-		    default:		assert(0);
-		}
-		const char *r = (op == TOKforeach_reverse) ? "R" : "";
-		int j = sprintf(fdname, "_aApply%s%.*s%d", r, 2, fntab[flag], dim);
-		assert(j < sizeof(fdname));
-		//LDC: Build arguments.
-		Arguments* args = new Arguments;
-		args->push(new Argument(STCin, tn->arrayOf(), NULL, NULL));
-		if (dim == 2) {
-		    Arguments* dgargs = new Arguments;
-		    dgargs->push(new Argument(STCin, Type::tvoidptr, NULL, NULL));
-		    dgargs->push(new Argument(STCin, Type::tvoidptr, NULL, NULL));
-		    dgty = new TypeDelegate(new TypeFunction(dgargs, Type::tindex, 0, LINKd));
-		    args->push(new Argument(STCin, dgty, NULL, NULL));
-		    fdapply = FuncDeclaration::genCfunc(args, Type::tindex, fdname);
-		} else {
-		    Arguments* dgargs = new Arguments;
-		    dgargs->push(new Argument(STCin, Type::tvoidptr, NULL, NULL));
-		    dgty = new TypeDelegate(new TypeFunction(dgargs, Type::tindex, 0, LINKd));
-		    args->push(new Argument(STCin, dgty, NULL, NULL));
-		    fdapply = FuncDeclaration::genCfunc(args, Type::tindex, fdname);
-		}
-
-		ec = new VarExp(0, fdapply);
-		Expressions *exps = new Expressions();
-		if (tab->ty == Tsarray)
-		   aggr = aggr->castTo(sc, tn->arrayOf());
-        exps->push(aggr);
-
-        // LDC paint delegate argument to the type runtime expects
-        if (!dgty->equals(flde->type))
-        {
-            flde = new CastExp(loc, flde, flde->type);
-            flde->type = dgty;
-        }
-		exps->push(flde);
-
-		e = new CallExp(loc, ec, exps);
-		e->type = Type::tindex;	// don't run semantic() on e
-	    }
-	    else if (tab->ty == Tdelegate)
-	    {
-		/* Call:
-		 *	aggr(flde)
-		 */
-		Expressions *exps = new Expressions();
-		exps->push(flde);
-		e = new CallExp(loc, aggr, exps);
-		e = e->semantic(sc);
-		if (e->type != Type::tint32)
-		    error("opApply() function for %s must return an int", tab->toChars());
-	    }
-	    else
-	    {
-		assert(tab->ty == Tstruct || tab->ty == Tclass);
-		Identifier *idapply = (op == TOKforeach_reverse)
-				? Id::applyReverse : Id::apply;
-		Dsymbol *sapply = search_function((AggregateDeclaration *)tab->toDsymbol(sc), idapply);
-	        Expressions *exps = new Expressions();
-#if 0
-		TemplateDeclaration *td;
-		if (sapply &&
-		    (td = sapply->isTemplateDeclaration()) != NULL)
-		{   /* Call:
-		     *	aggr.apply!(fld)()
-		     */
-		    TemplateInstance *ti = new TemplateInstance(loc, idapply);
-		    Objects *tiargs = new Objects();
-		    tiargs->push(fld);
-		    ti->tiargs = tiargs;
-		    ec = new DotTemplateInstanceExp(loc, aggr, ti);
-		}
-		else
-#endif
-		{
-		    /* Call:
-		     *	aggr.apply(flde)
-		     */
-		    ec = new DotIdExp(loc, aggr, idapply);
-		    exps->push(flde);
-		}
-		e = new CallExp(loc, ec, exps);
-		e = e->semantic(sc);
-		if (e->type != Type::tint32)
-		    error("opApply() function for %s must return an int", tab->toChars());
-	    }
-
-	    if (!cases.dim)
-		// Easy case, a clean exit from the loop
-		s = new ExpStatement(loc, e);
-	    else
-	    {	// Construct a switch statement around the return value
-		// of the apply function.
-		Statements *a = new Statements();
-
-		// default: break; takes care of cases 0 and 1
-		s = new BreakStatement(0, NULL);
-		s = new DefaultStatement(0, s);
-		a->push(s);
-
-		// cases 2...
-		for (int i = 0; i < cases.dim; i++)
-		{
-		    s = (Statement *)cases.data[i];
-		    s = new CaseStatement(0, new IntegerExp(i + 2), s);
-		    a->push(s);
-		}
-
-		s = new CompoundStatement(loc, a);
-		s = new SwitchStatement(loc, e, s);
-		s = s->semantic(sc);
-	    }
-	    break;
-	}
-
-	default:
-	    error("foreach: %s is not an aggregate type", aggr->type->toChars());
-	    break;
-    }
-    sc->noctor--;
-    sc->pop();
-    return s;
-}
-
-bool ForeachStatement::checkForArgTypes()
-{
-    for (size_t i = 0; i < arguments->dim; i++)
-    {	Argument *arg = (Argument *)arguments->data[i];
-	if (!arg->type)
-	{
-	    error("cannot infer type for %s", arg->ident->toChars());
-	    return FALSE;
-	}
-    }
-    return TRUE;
-}
-
-int ForeachStatement::hasBreak()
-{
-    return TRUE;
-}
-
-int ForeachStatement::hasContinue()
-{
-    return TRUE;
-}
-
-int ForeachStatement::usesEH()
-{
-    return body->usesEH();
-}
-
-int ForeachStatement::blockExit()
-{   int result = BEfallthru;
-
-    if (aggr->canThrow())
-	result |= BEthrow;
-
-    if (body)
-    {
-	result |= body->blockExit() & ~(BEbreak | BEcontinue);
-    }
-    return result;
-}
-
-int ForeachStatement::fallOffEnd()
-{
-    if (body)
-	body->fallOffEnd();
-    return TRUE;
-}
-
-int ForeachStatement::comeFrom()
-{
-    if (body)
-	return body->comeFrom();
-    return FALSE;
-}
-
-void ForeachStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{
-    buf->writestring(Token::toChars(op));
-    buf->writestring(" (");
-    for (int i = 0; i < arguments->dim; i++)
-    {
-	Argument *a = (Argument *)arguments->data[i];
-	if (i)
-	    buf->writestring(", ");
-	if (a->storageClass & STCref)
-	    buf->writestring((global.params.Dversion == 1)
-		? (char*)"inout " : (char*)"ref ");
-	if (a->type)
-	    a->type->toCBuffer(buf, a->ident, hgs);
-	else
-	    buf->writestring(a->ident->toChars());
-    }
-    buf->writestring("; ");
-    aggr->toCBuffer(buf, hgs);
-    buf->writebyte(')');
-    buf->writenl();
-    buf->writebyte('{');
-    buf->writenl();
-    if (body)
-	body->toCBuffer(buf, hgs);
-    buf->writebyte('}');
-    buf->writenl();
-}
-
-/**************************** ForeachRangeStatement ***************************/
-
-#if DMDV2
-
-ForeachRangeStatement::ForeachRangeStatement(Loc loc, enum TOK op, Argument *arg,
-	Expression *lwr, Expression *upr, Statement *body)
-    : Statement(loc)
-{
-    this->op = op;
-    this->arg = arg;
-    this->lwr = lwr;
-    this->upr = upr;
-    this->body = body;
-
-    this->enclosinghandler = NULL;
-
-    this->key = NULL;
-}
-
-Statement *ForeachRangeStatement::syntaxCopy()
-{
-    ForeachRangeStatement *s = new ForeachRangeStatement(loc, op,
-	arg->syntaxCopy(),
-	lwr->syntaxCopy(),
-	upr->syntaxCopy(),
-	body ? body->syntaxCopy() : NULL);
-    return s;
-}
-
-Statement *ForeachRangeStatement::semantic(Scope *sc)
-{
-    //printf("ForeachRangeStatement::semantic() %p\n", this);
-    ScopeDsymbol *sym;
-    Statement *s = this;
-
-    enclosinghandler = sc->tfOfTry;
-
-    lwr = lwr->semantic(sc);
-    lwr = resolveProperties(sc, lwr);
-    lwr = lwr->optimize(WANTvalue);
-    if (!lwr->type)
-    {
-	error("invalid range lower bound %s", lwr->toChars());
-	return this;
-    }
-
-    upr = upr->semantic(sc);
-    upr = resolveProperties(sc, upr);
-    upr = upr->optimize(WANTvalue);
-    if (!upr->type)
-    {
-	error("invalid range upper bound %s", upr->toChars());
-	return this;
-    }
-
-    if (arg->type)
-    {
-	lwr = lwr->implicitCastTo(sc, arg->type);
-	upr = upr->implicitCastTo(sc, arg->type);
-    }
-    else
-    {
-	/* Must infer types from lwr and upr
-	 */
-	AddExp ea(loc, lwr, upr);
-	ea.typeCombine(sc);
-	arg->type = ea.type->mutableOf();
-	lwr = ea.e1;
-	upr = ea.e2;
-    }
-    if (!arg->type->isscalar())
-	error("%s is not a scalar type", arg->type->toChars());
-
-    sym = new ScopeDsymbol();
-    sym->parent = sc->scopesym;
-    sc = sc->push(sym);
-
-    sc->noctor++;
-
-    key = new VarDeclaration(loc, arg->type, arg->ident, NULL);
-    DeclarationExp *de = new DeclarationExp(loc, key);
-    de->semantic(sc);
-
-    if (key->storage_class)
-	error("foreach range: key cannot have storage class");
-
-    sc->sbreak = this;
-    sc->scontinue = this;
-    body = body->semantic(sc);
-
-    sc->noctor--;
-    sc->pop();
-    return s;
-}
-
-int ForeachRangeStatement::hasBreak()
-{
-    return TRUE;
-}
-
-int ForeachRangeStatement::hasContinue()
-{
-    return TRUE;
-}
-
-int ForeachRangeStatement::usesEH()
-{
-    return body->usesEH();
-}
-
-int ForeachRangeStatement::blockExit()
-{   int result = BEfallthru;
-
-    if (lwr && lwr->canThrow())
-	result |= BEthrow;
-    else if (upr && upr->canThrow())
-	result |= BEthrow;
-
-    if (body)
-    {
-	result |= body->blockExit() & ~(BEbreak | BEcontinue);
-    }
-    return result;
-}
-
-int ForeachRangeStatement::fallOffEnd()
-{
-    if (body)
-	body->fallOffEnd();
-    return TRUE;
-}
-
-int ForeachRangeStatement::comeFrom()
-{
-    if (body)
-	return body->comeFrom();
-    return FALSE;
-}
-
-void ForeachRangeStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{
-    buf->writestring(Token::toChars(op));
-    buf->writestring(" (");
-
-    if (arg->type)
-	arg->type->toCBuffer(buf, arg->ident, hgs);
-    else
-	buf->writestring(arg->ident->toChars());
-
-    buf->writestring("; ");
-    lwr->toCBuffer(buf, hgs);
-    buf->writestring(" .. ");
-    upr->toCBuffer(buf, hgs);
-    buf->writebyte(')');
-    buf->writenl();
-    buf->writebyte('{');
-    buf->writenl();
-    if (body)
-	body->toCBuffer(buf, hgs);
-    buf->writebyte('}');
-    buf->writenl();
-}
-
-#endif
-
-/******************************** IfStatement ***************************/
-
-IfStatement::IfStatement(Loc loc, Argument *arg, Expression *condition, Statement *ifbody, Statement *elsebody)
-    : Statement(loc)
-{
-    this->arg = arg;
-    this->condition = condition;
-    this->ifbody = ifbody;
-    this->elsebody = elsebody;
-    this->match = NULL;
-}
-
-Statement *IfStatement::syntaxCopy()
-{
-    Statement *i = NULL;
-    if (ifbody)
-        i = ifbody->syntaxCopy();
-
-    Statement *e = NULL;
-    if (elsebody)
-	e = elsebody->syntaxCopy();
-
-    Argument *a = arg ? arg->syntaxCopy() : NULL;
-    IfStatement *s = new IfStatement(loc, a, condition->syntaxCopy(), i, e);
-    return s;
-}
-
-Statement *IfStatement::semantic(Scope *sc)
-{
-    condition = condition->semantic(sc);
-    condition = resolveProperties(sc, condition);
-    condition = condition->checkToBoolean();
-
-    // If we can short-circuit evaluate the if statement, don't do the
-    // semantic analysis of the skipped code.
-    // This feature allows a limited form of conditional compilation.
-    condition = condition->optimize(WANTflags);
-
-    // Evaluate at runtime
-    unsigned cs0 = sc->callSuper;
-    unsigned cs1;
-
-    Scope *scd;
-    if (arg)
-    {	/* Declare arg, which we will set to be the
-	 * result of condition.
-	 */
-	ScopeDsymbol *sym = new ScopeDsymbol();
-	sym->parent = sc->scopesym;
-	scd = sc->push(sym);
-
-	Type *t = arg->type ? arg->type : condition->type;
-	match = new VarDeclaration(loc, t, arg->ident, NULL);
-	match->noauto = 1;
-	match->semantic(scd);
-	if (!scd->insert(match))
-	    assert(0);
-	match->parent = sc->func;
-
-	/* Generate:
-	 *  (arg = condition)
-	 */
-	VarExp *v = new VarExp(0, match);
-	condition = new AssignExp(loc, v, condition);
-	condition = condition->semantic(scd);
-    }
-
-    else
-	scd = sc->push();
-    ifbody = ifbody->semantic(scd);
-    scd->pop();
-
-    cs1 = sc->callSuper;
-    sc->callSuper = cs0;
-    if (elsebody)
-	elsebody = elsebody->semanticScope(sc, NULL, NULL);
-    sc->mergeCallSuper(loc, cs1);
-
-    return this;
-}
-
-int IfStatement::usesEH()
-{
-    return (ifbody && ifbody->usesEH()) || (elsebody && elsebody->usesEH());
-}
-
-int IfStatement::blockExit()
-{
-    //printf("IfStatement::blockExit(%p)\n", this);
-
-    int result = BEnone;
-    if (condition->canThrow())
-	result |= BEthrow;
-    if (condition->isBool(TRUE))
-    {
-	if (ifbody)
-	    result |= ifbody->blockExit();
-	else
-	    result |= BEfallthru;
-    }
-    else if (condition->isBool(FALSE))
-    {
-	if (elsebody)
-	    result |= elsebody->blockExit();
-	else
-	    result |= BEfallthru;
-    }
-    else
-    {
-	if (ifbody)
-	    result |= ifbody->blockExit();
-	else
-	    result |= BEfallthru;
-	if (elsebody)
-	    result |= elsebody->blockExit();
-	else
-	    result |= BEfallthru;
-    }
-    //printf("IfStatement::blockExit(%p) = x%x\n", this, result);
-    return result;
-}
-
-int IfStatement::fallOffEnd()
-{
-    if (!ifbody || ifbody->fallOffEnd() ||
-	!elsebody || elsebody->fallOffEnd())
-	return TRUE;
-    return FALSE;
-}
-
-
-void IfStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{
-    buf->writestring("if (");
-    if (arg)
-    {
-	if (arg->type)
-	    arg->type->toCBuffer(buf, arg->ident, hgs);
-	else
-	{   buf->writestring("auto ");
-	    buf->writestring(arg->ident->toChars());
-	}
-	buf->writestring(" = ");
-    }
-    condition->toCBuffer(buf, hgs);
-    buf->writebyte(')');
-    buf->writenl();
-    ifbody->toCBuffer(buf, hgs);
-    if (elsebody)
-    {   buf->writestring("else");
-        buf->writenl();
-        elsebody->toCBuffer(buf, hgs);
-    }
-}
-
-/******************************** ConditionalStatement ***************************/
-
-ConditionalStatement::ConditionalStatement(Loc loc, Condition *condition, Statement *ifbody, Statement *elsebody)
-    : Statement(loc)
-{
-    this->condition = condition;
-    this->ifbody = ifbody;
-    this->elsebody = elsebody;
-}
-
-Statement *ConditionalStatement::syntaxCopy()
-{
-    Statement *e = NULL;
-    if (elsebody)
-	e = elsebody->syntaxCopy();
-    ConditionalStatement *s = new ConditionalStatement(loc,
-		condition->syntaxCopy(), ifbody->syntaxCopy(), e);
-    return s;
-}
-
-Statement *ConditionalStatement::semantic(Scope *sc)
-{
-    //printf("ConditionalStatement::semantic()\n");
-
-    // If we can short-circuit evaluate the if statement, don't do the
-    // semantic analysis of the skipped code.
-    // This feature allows a limited form of conditional compilation.
-    if (condition->include(sc, NULL))
-    {
-	ifbody = ifbody->semantic(sc);
-	return ifbody;
-    }
-    else
-    {
-	if (elsebody)
-	    elsebody = elsebody->semantic(sc);
-	return elsebody;
-    }
-}
-
-Statements *ConditionalStatement::flatten(Scope *sc)
-{
-    Statement *s;
-
-    if (condition->include(sc, NULL))
-	s = ifbody;
-    else
-	s = elsebody;
-
-    Statements *a = new Statements();
-    a->push(s);
-    return a;
-}
-
-int ConditionalStatement::usesEH()
-{
-    return (ifbody && ifbody->usesEH()) || (elsebody && elsebody->usesEH());
-}
-
-int ConditionalStatement::blockExit()
-{
-    int result = ifbody->blockExit();
-    if (elsebody)
-	result |= elsebody->blockExit();
-    return result;
-}
-
-void ConditionalStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{
-    condition->toCBuffer(buf, hgs);
-    buf->writenl();
-    buf->writeByte('{');
-    buf->writenl();
-    if (ifbody)
-	ifbody->toCBuffer(buf, hgs);
-    buf->writeByte('}');
-    buf->writenl();
-    if (elsebody)
-    {
-	buf->writestring("else");
-	buf->writenl();
-	buf->writeByte('{');
-	buf->writenl();
-	elsebody->toCBuffer(buf, hgs);
-	buf->writeByte('}');
-	buf->writenl();
-    }
-    buf->writenl();
-}
-
-
-/******************************** PragmaStatement ***************************/
-
-PragmaStatement::PragmaStatement(Loc loc, Identifier *ident, Expressions *args, Statement *body)
-    : Statement(loc)
-{
-    this->ident = ident;
-    this->args = args;
-    this->body = body;
-}
-
-Statement *PragmaStatement::syntaxCopy()
-{
-    Statement *b = NULL;
-    if (body)
-	b = body->syntaxCopy();
-    PragmaStatement *s = new PragmaStatement(loc,
-		ident, Expression::arraySyntaxCopy(args), b);
-    return s;
-}
-
-Statement *PragmaStatement::semantic(Scope *sc)
-{   // Should be merged with PragmaDeclaration
-    //printf("PragmaStatement::semantic() %s\n", toChars());
-    //printf("body = %p\n", body);
-    if (ident == Id::msg)
-    {
-        if (args)
-        {
-            for (size_t i = 0; i < args->dim; i++)
-            {
-                Expression *e = (Expression *)args->data[i];
-
-                e = e->semantic(sc);
-		e = e->optimize(WANTvalue | WANTinterpret);
-                if (e->op == TOKstring)
-                {
-                    StringExp *se = (StringExp *)e;
-                    fprintf(stdmsg, "%.*s", (int)se->len, se->string);
-                }
-                else
-		    error("string expected for message, not '%s'", e->toChars());
-            }
-            fprintf(stdmsg, "\n");
-        }
-    }
-    else if (ident == Id::lib)
-    {
-#if 1
-	/* Should this be allowed?
-	 */
-	error("pragma(lib) not allowed as statement");
-#else
-	if (!args || args->dim != 1)
-	    error("string expected for library name");
-	else
-	{
-	    Expression *e = (Expression *)args->data[0];
-
-	    e = e->semantic(sc);
-	    e = e->optimize(WANTvalue | WANTinterpret);
-	    args->data[0] = (void *)e;
-	    if (e->op != TOKstring)
-		error("string expected for library name, not '%s'", e->toChars());
-	    else if (global.params.verbose)
-	    {
-		StringExp *se = (StringExp *)e;
-		char *name = (char *)mem.malloc(se->len + 1);
-		memcpy(name, se->string, se->len);
-		name[se->len] = 0;
-		printf("library   %s\n", name);
-		mem.free(name);
-	    }
-	}
-#endif
-    }
-    else if (ident == Id::startaddress)
-    {
-	if (!args || args->dim != 1)
-	    error("function name expected for start address");
-	else
-	{
-	    Expression *e = (Expression *)args->data[0];
-	    e = e->semantic(sc);
-	    e = e->optimize(WANTvalue | WANTinterpret);
-	    args->data[0] = (void *)e;
-	    Dsymbol *sa = getDsymbol(e);
-	    if (!sa || !sa->isFuncDeclaration())
-		error("function name expected for start address, not '%s'", e->toChars());
-	    if (body)
-	    {
-		body = body->semantic(sc);
-	    }
-	    return this;
-	}
-    }
-
-    // LDC
-    else if (ident == Id::allow_inline)
-    {
-        sc->func->allowInlining = true;
-    }
-
-    else
-        error("unrecognized pragma(%s)", ident->toChars());
-
-    if (body)
-    {
-	body = body->semantic(sc);
-    }
-    return body;
-}
-
-int PragmaStatement::usesEH()
-{
-    return body && body->usesEH();
-}
-
-int PragmaStatement::blockExit()
-{
-    int result = BEfallthru;
-#if 0 // currently, no code is generated for Pragma's, so it's just fallthru
-    if (arrayExpressionCanThrow(args))
-	result |= BEthrow;
-    if (body)
-	result |= body->blockExit();
-#endif
-    return result;
-}
-
-int PragmaStatement::fallOffEnd()
-{
-    if (body)
-	return body->fallOffEnd();
-    return TRUE;
-}
-
-void PragmaStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{
-    buf->writestring("pragma (");
-    buf->writestring(ident->toChars());
-    if (args && args->dim)
-    {
-	buf->writestring(", ");
-	argsToCBuffer(buf, args, hgs);
-    }
-    buf->writeByte(')');
-    if (body)
-    {
-	buf->writenl();
-	buf->writeByte('{');
-	buf->writenl();
-
-	body->toCBuffer(buf, hgs);
-
-	buf->writeByte('}');
-	buf->writenl();
-    }
-    else
-    {
-	buf->writeByte(';');
-	buf->writenl();
-    }
-}
-
-
-/******************************** StaticAssertStatement ***************************/
-
-StaticAssertStatement::StaticAssertStatement(StaticAssert *sa)
-    : Statement(sa->loc)
-{
-    this->sa = sa;
-}
-
-Statement *StaticAssertStatement::syntaxCopy()
-{
-    StaticAssertStatement *s = new StaticAssertStatement((StaticAssert *)sa->syntaxCopy(NULL));
-    return s;
-}
-
-Statement *StaticAssertStatement::semantic(Scope *sc)
-{
-    sa->semantic2(sc);
-    return NULL;
-}
-
-void StaticAssertStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{
-    sa->toCBuffer(buf, hgs);
-}
-
-
-/******************************** SwitchStatement ***************************/
-
-SwitchStatement::SwitchStatement(Loc loc, Expression *c, Statement *b)
-    : Statement(loc)
-{
-    condition = c;
-    body = b;
-    sdefault = NULL;
-    tf = NULL;
-    cases = NULL;
-    hasNoDefault = 0;
-    hasVars = 0;
-    // LDC
-    enclosinghandler = NULL;
-}
-
-Statement *SwitchStatement::syntaxCopy()
-{
-    SwitchStatement *s = new SwitchStatement(loc,
-	condition->syntaxCopy(), body->syntaxCopy());
-    return s;
-}
-
-Statement *SwitchStatement::semantic(Scope *sc)
-{
-    //printf("SwitchStatement::semantic(%p)\n", this);
-    tf = sc->tf;
-    assert(!cases);		// ensure semantic() is only run once
-
-    enclosinghandler = sc->tfOfTry;
-
-    condition = condition->semantic(sc);
-    condition = resolveProperties(sc, condition);
-    if (condition->type->isString())
-    {
-	// If it's not an array, cast it to one
-	if (condition->type->ty != Tarray)
-	{
-	    condition = condition->implicitCastTo(sc, condition->type->nextOf()->arrayOf());
-	}
-	condition->type = condition->type->constOf();
-    }
-    else
-    {	condition = condition->integralPromotions(sc);
-	condition->checkIntegral();
-    }
-    condition = condition->optimize(WANTvalue);
-
-    sc = sc->push();
-    sc->sbreak = this;
-    sc->sw = this;
-
-    cases = new Array();
-    sc->noctor++;	// BUG: should use Scope::mergeCallSuper() for each case instead
-    body = body->semantic(sc);
-    sc->noctor--;
-
-    // Resolve any goto case's with exp
-    for (int i = 0; i < gotoCases.dim; i++)
-    {
-	GotoCaseStatement *gcs = (GotoCaseStatement *)gotoCases.data[i];
-
-	if (!gcs->exp)
-	{
-	    gcs->error("no case statement following goto case;");
-	    break;
-	}
-
-	for (Scope *scx = sc; scx; scx = scx->enclosing)
-	{
-	    if (!scx->sw)
-		continue;
-	    for (int j = 0; j < scx->sw->cases->dim; j++)
-	    {
-		CaseStatement *cs = (CaseStatement *)scx->sw->cases->data[j];
-
-		if (cs->exp->equals(gcs->exp))
-		{
-		    gcs->cs = cs;
-		    goto Lfoundcase;
-		}
-	    }
-	}
-	gcs->error("case %s not found", gcs->exp->toChars());
-
-     Lfoundcase:
-	;
-    }
-
-    if (!sc->sw->sdefault)
-    {	hasNoDefault = 1;
-
-	if (global.params.warnings)
-	{   warning("%s: switch statement has no default", loc.toChars());
-	}
-
-	// Generate runtime error if the default is hit
-	Statements *a = new Statements();
-	CompoundStatement *cs;
-	Statement *s;
-
-	if (global.params.useSwitchError)
-	    s = new SwitchErrorStatement(loc);
-	else
-	{   Expression *e = new HaltExp(loc);
-	    s = new ExpStatement(loc, e);
-	}
-
-	a->reserve(4);
-	a->push(body);
-	a->push(new BreakStatement(loc, NULL));
-	sc->sw->sdefault = new DefaultStatement(loc, s);
-	a->push(sc->sw->sdefault);
-	cs = new CompoundStatement(loc, a);
-	body = cs;
-    }
-
-    sc->pop();
-    return this;
-}
-
-int SwitchStatement::hasBreak()
-{
-    return TRUE;
-}
-
-int SwitchStatement::usesEH()
-{
-    return body ? body->usesEH() : 0;
-}
-
-int SwitchStatement::blockExit()
-{   int result = BEnone;
-    if (condition->canThrow())
-	result |= BEthrow;
-
-    if (body)
-    {	result |= body->blockExit();
-	if (result & BEbreak)
-	{   result |= BEfallthru;
-	    result &= ~BEbreak;
-	}
-    }
-    else
-	result |= BEfallthru;
-
-    return result;
-}
-
-int SwitchStatement::fallOffEnd()
-{
-    if (body)
-	body->fallOffEnd();
-    return TRUE;	// need to do this better
-}
-
-void SwitchStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{
-    buf->writestring("switch (");
-    condition->toCBuffer(buf, hgs);
-    buf->writebyte(')');
-    buf->writenl();
-    if (body)
-    {
-	if (!body->isScopeStatement())
-        {   buf->writebyte('{');
-            buf->writenl();
-            body->toCBuffer(buf, hgs);
-            buf->writebyte('}');
-            buf->writenl();
-        }
-        else
-        {
-            body->toCBuffer(buf, hgs);
-        }
-    }
-}
-
-/******************************** CaseStatement ***************************/
-
-CaseStatement::CaseStatement(Loc loc, Expression *exp, Statement *s)
-    : Statement(loc)
-{
-    this->exp = exp;
-    this->statement = s;
-    index = 0;
-    cblock = NULL;
-    bodyBB = NULL;
-    llvmIdx = NULL;
-}
-
-Statement *CaseStatement::syntaxCopy()
-{
-    CaseStatement *s = new CaseStatement(loc, exp->syntaxCopy(), statement->syntaxCopy());
-    return s;
-}
-
-Statement *CaseStatement::semantic(Scope *sc)
-{   SwitchStatement *sw = sc->sw;
-
-    //printf("CaseStatement::semantic() %s\n", toChars());
-    exp = exp->semantic(sc);
-    if (sw)
-    {
-	exp = exp->implicitCastTo(sc, sw->condition->type);
-	exp = exp->optimize(WANTvalue | WANTinterpret);
-
-	/* This is where variables are allowed as case expressions.
-	 */
-	if (exp->op == TOKvar)
-	{   VarExp *ve = (VarExp *)exp;
-	    VarDeclaration *v = ve->var->isVarDeclaration();
-	    Type *t = exp->type->toBasetype();
-	    if (v && (t->isintegral() || t->ty == Tclass))
-	    {	/* Flag that we need to do special code generation
-		 * for this, i.e. generate a sequence of if-then-else
-		 */
-		sw->hasVars = 1;
-		goto L1;
-	    }
-	}
-
-	if (exp->op != TOKstring && exp->op != TOKint64)
-	{
-	    error("case must be a string or an integral constant, not %s", exp->toChars());
-	    exp = new IntegerExp(0);
-	}
-
-    L1:
-	for (int i = 0; i < sw->cases->dim; i++)
-	{
-	    CaseStatement *cs = (CaseStatement *)sw->cases->data[i];
-
-	    //printf("comparing '%s' with '%s'\n", exp->toChars(), cs->exp->toChars());
-	    if (cs->exp->equals(exp))
-	    {	error("duplicate case %s in switch statement", exp->toChars());
-		break;
-	    }
-	}
-
-	sw->cases->push(this);
-
-	// Resolve any goto case's with no exp to this case statement
-	for (int i = 0; i < sw->gotoCases.dim; i++)
-	{
-	    GotoCaseStatement *gcs = (GotoCaseStatement *)sw->gotoCases.data[i];
-
-	    if (!gcs->exp)
-	    {
-		gcs->cs = this;
-		sw->gotoCases.remove(i);	// remove from array
-	    }
-	}
-
-	if (sc->sw->tf != sc->tf)
-	    error("switch and case are in different finally blocks");
-    }
-    else
-	error("case not in switch statement");
-    statement = statement->semantic(sc);
-    return this;
-}
-
-int CaseStatement::compare(Object *obj)
-{
-    // Sort cases so we can do an efficient lookup
-    CaseStatement *cs2 = (CaseStatement *)(obj);
-
-    return exp->compare(cs2->exp);
-}
-
-int CaseStatement::usesEH()
-{
-    return statement->usesEH();
-}
-
-int CaseStatement::blockExit()
-{
-    return statement->blockExit();
-}
-
-int CaseStatement::fallOffEnd()
-{
-    return statement->fallOffEnd();
-}
-
-int CaseStatement::comeFrom()
-{
-    return TRUE;
-}
-
-void CaseStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{
-    buf->writestring("case ");
-    exp->toCBuffer(buf, hgs);
-    buf->writebyte(':');
-    buf->writenl();
-    statement->toCBuffer(buf, hgs);
-}
-
-/******************************** DefaultStatement ***************************/
-
-DefaultStatement::DefaultStatement(Loc loc, Statement *s)
-    : Statement(loc)
-{
-    this->statement = s;
-#if IN_GCC
-+    cblock = NULL;
-#endif
-    bodyBB = NULL;
-}
-
-Statement *DefaultStatement::syntaxCopy()
-{
-    DefaultStatement *s = new DefaultStatement(loc, statement->syntaxCopy());
-    return s;
-}
-
-Statement *DefaultStatement::semantic(Scope *sc)
-{
-    //printf("DefaultStatement::semantic()\n");
-    if (sc->sw)
-    {
-	if (sc->sw->sdefault)
-	{
-	    error("switch statement already has a default");
-	}
-	sc->sw->sdefault = this;
-
-	if (sc->sw->tf != sc->tf)
-	    error("switch and default are in different finally blocks");
-    }
-    else
-	error("default not in switch statement");
-    statement = statement->semantic(sc);
-    return this;
-}
-
-int DefaultStatement::usesEH()
-{
-    return statement->usesEH();
-}
-
-int DefaultStatement::blockExit()
-{
-    return statement->blockExit();
-}
-
-int DefaultStatement::fallOffEnd()
-{
-    return statement->fallOffEnd();
-}
-
-int DefaultStatement::comeFrom()
-{
-    return TRUE;
-}
-
-void DefaultStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{
-    buf->writestring("default:\n");
-    statement->toCBuffer(buf, hgs);
-}
-
-/******************************** GotoDefaultStatement ***************************/
-
-GotoDefaultStatement::GotoDefaultStatement(Loc loc)
-    : Statement(loc)
-{
-    sw = NULL;
-    enclosinghandler = NULL;
-}
-
-Statement *GotoDefaultStatement::syntaxCopy()
-{
-    GotoDefaultStatement *s = new GotoDefaultStatement(loc);
-    return s;
-}
-
-Statement *GotoDefaultStatement::semantic(Scope *sc)
-{
-    enclosinghandler = sc->tfOfTry;
-    sw = sc->sw;
-    if (!sw)
-	error("goto default not in switch statement");
-    return this;
-}
-
-int GotoDefaultStatement::blockExit()
-{
-    return BEgoto;
-}
-
-int GotoDefaultStatement::fallOffEnd()
-{
-    return FALSE;
-}
-
-void GotoDefaultStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{
-    buf->writestring("goto default;\n");
-}
-
-/******************************** GotoCaseStatement ***************************/
-
-GotoCaseStatement::GotoCaseStatement(Loc loc, Expression *exp)
-    : Statement(loc)
-{
-    cs = NULL;
-    this->exp = exp;
-    enclosinghandler = NULL;
-    sw = NULL;
-}
-
-Statement *GotoCaseStatement::syntaxCopy()
-{
-    Expression *e = exp ? exp->syntaxCopy() : NULL;
-    GotoCaseStatement *s = new GotoCaseStatement(loc, e);
-    return s;
-}
-
-Statement *GotoCaseStatement::semantic(Scope *sc)
-{
-    enclosinghandler = sc->tfOfTry;
-    if (exp)
-	exp = exp->semantic(sc);
-
-    if (!sc->sw)
-	error("goto case not in switch statement");
-    else
-    {
-	sw = sc->sw;
-	sc->sw->gotoCases.push(this);
-	if (exp)
-	{
-	    exp = exp->implicitCastTo(sc, sc->sw->condition->type);
-	    exp = exp->optimize(WANTvalue);
-	}
-    }
-    return this;
-}
-
-int GotoCaseStatement::blockExit()
-{
-    return BEgoto;
-}
-
-int GotoCaseStatement::fallOffEnd()
-{
-    return FALSE;
-}
-
-void GotoCaseStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{
-    buf->writestring("goto case");
-    if (exp)
-    {   buf->writebyte(' ');
-        exp->toCBuffer(buf, hgs);
-    }
-    buf->writebyte(';');
-    buf->writenl();
-}
-
-/******************************** SwitchErrorStatement ***************************/
-
-SwitchErrorStatement::SwitchErrorStatement(Loc loc)
-    : Statement(loc)
-{
-}
-
-int SwitchErrorStatement::blockExit()
-{
-    return BEthrow;
-}
-
-int SwitchErrorStatement::fallOffEnd()
-{
-    return FALSE;
-}
-
-void SwitchErrorStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{
-    buf->writestring("SwitchErrorStatement::toCBuffer()");
-    buf->writenl();
-}
-
-/******************************** ReturnStatement ***************************/
-
-ReturnStatement::ReturnStatement(Loc loc, Expression *exp)
-    : Statement(loc)
-{
-    this->exp = exp;
-    this->enclosinghandler = NULL;
-}
-
-Statement *ReturnStatement::syntaxCopy()
-{
-    Expression *e = NULL;
-    if (exp)
-	e = exp->syntaxCopy();
-    ReturnStatement *s = new ReturnStatement(loc, e);
-    return s;
-}
-
-Statement *ReturnStatement::semantic(Scope *sc)
-{
-    //printf("ReturnStatement::semantic() %s\n", toChars());
-    this->enclosinghandler = sc->tfOfTry;
-
-    FuncDeclaration *fd = sc->parent->isFuncDeclaration();
-    Scope *scx = sc;
-    int implicit0 = 0;
-
-    if (sc->fes)
-    {
-	// Find scope of function foreach is in
-	for (; 1; scx = scx->enclosing)
-	{
-	    assert(scx);
-	    if (scx->func != fd)
-	    {	fd = scx->func;		// fd is now function enclosing foreach
-		break;
-	    }
-	}
-    }
-
-    Type *tret = fd->type->nextOf();
-    if (fd->tintro)
-	/* We'll be implicitly casting the return expression to tintro
-	 */
-	tret = fd->tintro->nextOf();
-    Type *tbret = NULL;
-
-    if (tret)
-	tbret = tret->toBasetype();
-
-    // main() returns 0, even if it returns void
-    if (!exp && (!tbret || tbret->ty == Tvoid) && fd->isMain())
-    {	implicit0 = 1;
-	exp = new IntegerExp(0);
-    }
-
-    if (sc->incontract || scx->incontract)
-	error("return statements cannot be in contracts");
-    if (sc->tf || scx->tf)
-	error("return statements cannot be in finally, scope(exit) or scope(success) bodies");
-
-    if (fd->isCtorDeclaration())
-    {
-	// Constructors implicitly do:
-	//	return this;
-	if (exp && exp->op != TOKthis)
-	    error("cannot return expression from constructor");
-	exp = new ThisExp(0);
-    }
-
-    if (!exp)
-	fd->nrvo_can = 0;
-
-    if (exp)
-    {
-	fd->hasReturnExp |= 1;
-
-	exp = exp->semantic(sc);
-	exp = resolveProperties(sc, exp);
-	exp = exp->optimize(WANTvalue);
-
-	if (fd->nrvo_can && exp->op == TOKvar)
-	{   VarExp *ve = (VarExp *)exp;
-	    VarDeclaration *v = ve->var->isVarDeclaration();
-
-	    if (((TypeFunction *)fd->type)->isref)
-		// Function returns a reference
-		fd->nrvo_can = 0;
-	    else if (!v || v->isOut() || v->isRef())
-		fd->nrvo_can = 0;
-	    else if (tbret->ty == Tstruct && ((TypeStruct *)tbret)->sym->dtor)
-		// Struct being returned has destructors
-		fd->nrvo_can = 0;
-	    else if (fd->nrvo_var == NULL)
-	    {	if (!v->isDataseg() && !v->isParameter() && v->toParent2() == fd)
-		{   //printf("Setting nrvo to %s\n", v->toChars());
-		    fd->nrvo_var = v;
-		}
-		else
-		    fd->nrvo_can = 0;
-	    }
-	    else if (fd->nrvo_var != v)
-		fd->nrvo_can = 0;
-	}
-	else
-	    fd->nrvo_can = 0;
-
-	if (fd->returnLabel && tbret->ty != Tvoid)
-	{
-	}
-	else if (fd->inferRetType)
-	{
-	    if (fd->type->nextOf())
-	    {
-		if (!exp->type->equals(fd->type->nextOf()))
-		    error("mismatched function return type inference of %s and %s",
-			exp->type->toChars(), fd->type->nextOf()->toChars());
-	    }
-	    else
-	    {
-		((TypeFunction *)fd->type)->next = exp->type;
-		fd->type = fd->type->semantic(loc, sc);
-		if (!fd->tintro)
-		{   tret = fd->type->nextOf();
-		    tbret = tret->toBasetype();
-		}
-	    }
-	}
-	else if (tbret->ty != Tvoid)
-	{
-	    exp = exp->implicitCastTo(sc, tret);
-	}
-    }
-    else if (fd->inferRetType)
-    {
-	if (fd->type->nextOf())
-	{
-	    if (fd->type->nextOf()->ty != Tvoid)
-		error("mismatched function return type inference of void and %s",
-		    fd->type->nextOf()->toChars());
-	}
-	else
-	{
-	    ((TypeFunction *)fd->type)->next = Type::tvoid;
-	    fd->type = fd->type->semantic(loc, sc);
-	    if (!fd->tintro)
-	    {   tret = Type::tvoid;
-		tbret = tret;
-	    }
-	}
-    }
-    else if (tbret->ty != Tvoid)	// if non-void return
-	error("return expression expected");
-
-    if (sc->fes)
-    {
-	Statement *s;
-
-	if (exp && !implicit0)
-	{
-	    exp = exp->implicitCastTo(sc, tret);
-	}
-	if (!exp || exp->op == TOKint64 || exp->op == TOKfloat64 ||
-	    exp->op == TOKimaginary80 || exp->op == TOKcomplex80 ||
-	    exp->op == TOKthis || exp->op == TOKsuper || exp->op == TOKnull ||
-	    exp->op == TOKstring)
-	{
-	    sc->fes->cases.push(this);
-	    // Construct: return cases.dim+1;
-	    s = new ReturnStatement(0, new IntegerExp(sc->fes->cases.dim + 1));
-	}
-	else if (fd->type->nextOf()->toBasetype() == Type::tvoid)
-	{
-	    s = new ReturnStatement(0, NULL);
-	    sc->fes->cases.push(s);
-
-	    // Construct: { exp; return cases.dim + 1; }
-	    Statement *s1 = new ExpStatement(loc, exp);
-	    Statement *s2 = new ReturnStatement(0, new IntegerExp(sc->fes->cases.dim + 1));
-	    s = new CompoundStatement(loc, s1, s2);
-	}
-	else
-	{
-	    // Construct: return vresult;
-	    if (!fd->vresult)
-	    {	// Declare vresult
-		VarDeclaration *v = new VarDeclaration(loc, tret, Id::result, NULL);
-		v->noauto = 1;
-		v->semantic(scx);
-		if (!scx->insert(v))
-		    assert(0);
-		v->parent = fd;
-		fd->vresult = v;
-	    }
-
-	    s = new ReturnStatement(0, new VarExp(0, fd->vresult));
-	    sc->fes->cases.push(s);
-
-	    // Construct: { vresult = exp; return cases.dim + 1; }
-	    exp = new AssignExp(loc, new VarExp(0, fd->vresult), exp);
-	    exp = exp->semantic(sc);
-	    Statement *s1 = new ExpStatement(loc, exp);
-	    Statement *s2 = new ReturnStatement(0, new IntegerExp(sc->fes->cases.dim + 1));
-	    s = new CompoundStatement(loc, s1, s2);
-	}
-	return s;
-    }
-
-    if (exp)
-    {
-	if (fd->returnLabel && tbret->ty != Tvoid)
-	{
-	    assert(fd->vresult);
-	    VarExp *v = new VarExp(0, fd->vresult);
-
-	    exp = new AssignExp(loc, v, exp);
-	    exp = exp->semantic(sc);
-	}
-
-	if (((TypeFunction *)fd->type)->isref)
-	{   // Function returns a reference
-	    if (tbret->isMutable())
-		exp = exp->modifiableLvalue(sc, exp);
-	    else
-		exp = exp->toLvalue(sc, exp);
-
-	    if (exp->op == TOKvar)
-	    {	VarExp *ve = (VarExp *)exp;
-		VarDeclaration *v = ve->var->isVarDeclaration();
-		if (v && !v->isDataseg() && !(v->storage_class & (STCref | STCout)))
-		    error("escaping reference to local variable %s", v->toChars());
-	    }
-	}
-
-	//exp->dump(0);
-	//exp->print();
-	exp->checkEscape();
-    }
-
-    /* BUG: need to issue an error on:
-     *	this
-     *	{   if (x) return;
-     *	    super();
-     *	}
-     */
-
-    if (sc->callSuper & CSXany_ctor &&
-	!(sc->callSuper & (CSXthis_ctor | CSXsuper_ctor)))
-	error("return without calling constructor");
-
-    sc->callSuper |= CSXreturn;
-
-    // See if all returns are instead to be replaced with a goto returnLabel;
-    if (fd->returnLabel)
-    {
-	GotoStatement *gs = new GotoStatement(loc, Id::returnLabel);
-
-	gs->label = fd->returnLabel;
-	if (exp)
-	{   /* Replace: return exp;
-	     * with:    exp; goto returnLabel;
-	     */
-	    Statement *s = new ExpStatement(0, exp);
-	    return new CompoundStatement(loc, s, gs);
-	}
-	return gs;
-    }
-
-    if (exp && tbret->ty == Tvoid && !fd->isMain())
-    {
-	/* Replace:
-	 *	return exp;
-	 * with:
-	 *	exp; return;
-	 */
-	Statement *s = new ExpStatement(loc, exp);
-	loc = 0;
-	exp = NULL;
-	return new CompoundStatement(loc, s, this);
-    }
-
-    return this;
-}
-
-int ReturnStatement::blockExit()
-{   int result = BEreturn;
-
-    if (exp && exp->canThrow())
-	result |= BEthrow;
-    return result;
-}
-
-int ReturnStatement::fallOffEnd()
-{
-    return FALSE;
-}
-
-void ReturnStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{
-    buf->printf("return ");
-    if (exp)
-	exp->toCBuffer(buf, hgs);
-    buf->writeByte(';');
-    buf->writenl();
-}
-
-/******************************** BreakStatement ***************************/
-
-BreakStatement::BreakStatement(Loc loc, Identifier *ident)
-    : Statement(loc)
-{
-    this->ident = ident;
-    this->enclosinghandler = NULL;
-}
-
-Statement *BreakStatement::syntaxCopy()
-{
-    BreakStatement *s = new BreakStatement(loc, ident);
-    return s;
-}
-
-Statement *BreakStatement::semantic(Scope *sc)
-{
-    //printf("BreakStatement::semantic()\n");
-    enclosinghandler = sc->tfOfTry;
-    // If:
-    //	break Identifier;
-    if (ident)
-    {
-	Scope *scx;
-	FuncDeclaration *thisfunc = sc->func;
-
-	for (scx = sc; scx; scx = scx->enclosing)
-	{
-	    LabelStatement *ls;
-
-	    if (scx->func != thisfunc)	// if in enclosing function
-	    {
-		if (sc->fes)		// if this is the body of a foreach
-		{
-		    /* Post this statement to the fes, and replace
-		     * it with a return value that caller will put into
-		     * a switch. Caller will figure out where the break
-		     * label actually is.
-		     * Case numbers start with 2, not 0, as 0 is continue
-		     * and 1 is break.
-		     */
-		    Statement *s;
-		    sc->fes->cases.push(this);
-		    s = new ReturnStatement(0, new IntegerExp(sc->fes->cases.dim + 1));
-		    return s;
-		}
-		break;			// can't break to it
-	    }
-
-	    ls = scx->slabel;
-	    if (ls && ls->ident == ident)
-	    {
-		Statement *s = ls->statement;
-
-		if (!s->hasBreak())
-		    error("label '%s' has no break", ident->toChars());
-		if (ls->tf != sc->tf)
-		    error("cannot break out of finally block");
-		
-		this->target = ls;
-		return this;
-	    }
-	}
-	error("enclosing label '%s' for break not found", ident->toChars());
-    }
-    else if (!sc->sbreak)
-    {
-	if (sc->fes)
-	{   Statement *s;
-
-	    // Replace break; with return 1;
-	    s = new ReturnStatement(0, new IntegerExp(1));
-	    return s;
-	}
-	error("break is not inside a loop or switch");
-    }
-    return this;
-}
-
-int BreakStatement::blockExit()
-{
-    //printf("BreakStatement::blockExit(%p) = x%x\n", this, ident ? BEgoto : BEbreak);
-    return ident ? BEgoto : BEbreak;
-}
-
-int BreakStatement::fallOffEnd()
-{
-    return FALSE;
-}
-
-void BreakStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{
-    buf->writestring("break");
-    if (ident)
-    {   buf->writebyte(' ');
-        buf->writestring(ident->toChars());
-    }
-    buf->writebyte(';');
-    buf->writenl();
-}
-
-/******************************** ContinueStatement ***************************/
-
-ContinueStatement::ContinueStatement(Loc loc, Identifier *ident)
-    : Statement(loc)
-{
-    this->ident = ident;
-    this->enclosinghandler = NULL;
-}
-
-Statement *ContinueStatement::syntaxCopy()
-{
-    ContinueStatement *s = new ContinueStatement(loc, ident);
-    return s;
-}
-
-Statement *ContinueStatement::semantic(Scope *sc)
-{
-    enclosinghandler = sc->tfOfTry;
-    //printf("ContinueStatement::semantic() %p\n", this);
-    if (ident)
-    {
-	Scope *scx;
-	FuncDeclaration *thisfunc = sc->func;
-
-	for (scx = sc; scx; scx = scx->enclosing)
-	{
-	    LabelStatement *ls;
-
-	    if (scx->func != thisfunc)	// if in enclosing function
-	    {
-		if (sc->fes)		// if this is the body of a foreach
-		{
-		    for (; scx; scx = scx->enclosing)
-		    {
-			ls = scx->slabel;
-			if (ls && ls->ident == ident && ls->statement == sc->fes)
-			{
-			    // Replace continue ident; with return 0;
-			    return new ReturnStatement(0, new IntegerExp(0));
-			}
-		    }
-
-		    /* Post this statement to the fes, and replace
-		     * it with a return value that caller will put into
-		     * a switch. Caller will figure out where the break
-		     * label actually is.
-		     * Case numbers start with 2, not 0, as 0 is continue
-		     * and 1 is break.
-		     */
-		    Statement *s;
-		    sc->fes->cases.push(this);
-		    s = new ReturnStatement(0, new IntegerExp(sc->fes->cases.dim + 1));
-		    return s;
-		}
-		break;			// can't continue to it
-	    }
-
-	    ls = scx->slabel;
-	    if (ls && ls->ident == ident)
-	    {
-		Statement *s = ls->statement;
-
-		if (!s->hasContinue())
-		    error("label '%s' has no continue", ident->toChars());
-		if (ls->tf != sc->tf)
-		    error("cannot continue out of finally block");
-		
-		this->target = ls;
-		return this;
-	    }
-	}
-	error("enclosing label '%s' for continue not found", ident->toChars());
-    }
-    else if (!sc->scontinue)
-    {
-	if (sc->fes)
-	{   Statement *s;
-
-	    // Replace continue; with return 0;
-	    s = new ReturnStatement(0, new IntegerExp(0));
-	    return s;
-	}
-	error("continue is not inside a loop");
-    }
-    return this;
-}
-
-int ContinueStatement::blockExit()
-{
-    return ident ? BEgoto : BEcontinue;
-}
-
-int ContinueStatement::fallOffEnd()
-{
-    return FALSE;
-}
-
-void ContinueStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{
-    buf->writestring("continue");
-    if (ident)
-    {   buf->writebyte(' ');
-        buf->writestring(ident->toChars());
-    }
-    buf->writebyte(';');
-    buf->writenl();
-}
-
-/******************************** SynchronizedStatement ***************************/
-
-SynchronizedStatement::SynchronizedStatement(Loc loc, Expression *exp, Statement *body)
-    : Statement(loc)
-{
-    this->exp = exp;
-    this->body = body;
-    this->esync = NULL;
-    this->enclosinghandler = NULL;
-    // LDC
-    this->llsync = NULL;
-}
-
-SynchronizedStatement::SynchronizedStatement(Loc loc, elem *esync, Statement *body)
-    : Statement(loc)
-{
-    this->exp = NULL;
-    this->body = body;
-    this->esync = esync;
-    this->enclosinghandler = NULL;
-    // LDC
-    this->llsync = NULL;
-}
-
-Statement *SynchronizedStatement::syntaxCopy()
-{
-    Expression *e = exp ? exp->syntaxCopy() : NULL;
-    SynchronizedStatement *s = new SynchronizedStatement(loc, e, body ? body->syntaxCopy() : NULL);
-    return s;
-}
-
-Statement *SynchronizedStatement::semantic(Scope *sc)
-{
-    if (exp)
-    {	ClassDeclaration *cd;
-
-	exp = exp->semantic(sc);
-	exp = resolveProperties(sc, exp);
-	cd = exp->type->isClassHandle();
-	if (!cd)
-	    error("can only synchronize on class objects, not '%s'", exp->type->toChars());
-	else if (cd->isInterfaceDeclaration())
-	{   Type *t = new TypeIdentifier(0, Id::Object);
-
-	    t = t->semantic(0, sc);
-	    exp = new CastExp(loc, exp, t);
-	    exp = exp->semantic(sc);
-	}
-    }
-    if (body)
-    {
-        enclosinghandler = sc->tfOfTry;
-        sc->tfOfTry = new EnclosingSynchro(this);
-        body = body->semantic(sc);
-        sc->tfOfTry = enclosinghandler;
-    }
-    return this;
-}
-
-int SynchronizedStatement::hasBreak()
-{
-    return FALSE; //TRUE;
-}
-
-int SynchronizedStatement::hasContinue()
-{
-    return FALSE; //TRUE;
-}
-
-int SynchronizedStatement::usesEH()
-{
-    return TRUE;
-}
-
-int SynchronizedStatement::blockExit()
-{
-    return body ? body->blockExit() : BEfallthru;
-}
-
-int SynchronizedStatement::fallOffEnd()
-{
-    return body ? body->fallOffEnd() : TRUE;
-}
-
-void SynchronizedStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{
-    buf->writestring("synchronized");
-    if (exp)
-    {   buf->writebyte('(');
-	exp->toCBuffer(buf, hgs);
-	buf->writebyte(')');
-    }
-    if (body)
-    {
-	buf->writebyte(' ');
-	body->toCBuffer(buf, hgs);
-    }
-}
-
-/******************************** WithStatement ***************************/
-
-WithStatement::WithStatement(Loc loc, Expression *exp, Statement *body)
-    : Statement(loc)
-{
-    this->exp = exp;
-    this->body = body;
-    wthis = NULL;
-}
-
-Statement *WithStatement::syntaxCopy()
-{
-    WithStatement *s = new WithStatement(loc, exp->syntaxCopy(), body ? body->syntaxCopy() : NULL);
-    return s;
-}
-
-Statement *WithStatement::semantic(Scope *sc)
-{   ScopeDsymbol *sym;
-    Initializer *init;
-
-    //printf("WithStatement::semantic()\n");
-    exp = exp->semantic(sc);
-    exp = resolveProperties(sc, exp);
-    if (exp->op == TOKimport)
-    {	ScopeExp *es = (ScopeExp *)exp;
-
-	sym = es->sds;
-    }
-    else if (exp->op == TOKtype)
-    {	TypeExp *es = (TypeExp *)exp;
-
-	sym = es->type->toDsymbol(sc)->isScopeDsymbol();
-	if (!sym)
-	{   error("%s has no members", es->toChars());
-	    body = body->semantic(sc);
-	    return this;
-	}
-    }
-    else
-    {	Type *t = exp->type;
-
-	assert(t);
-	t = t->toBasetype();
-	if (t->isClassHandle())
-	{
-	    init = new ExpInitializer(loc, exp);
-	    wthis = new VarDeclaration(loc, exp->type, Id::withSym, init);
-	    wthis->semantic(sc);
-
-	    sym = new WithScopeSymbol(this);
-	    sym->parent = sc->scopesym;
-	}
-	else if (t->ty == Tstruct)
-	{
-	    Expression *e = exp->addressOf(sc);
-	    init = new ExpInitializer(loc, e);
-	    wthis = new VarDeclaration(loc, e->type, Id::withSym, init);
-	    wthis->semantic(sc);
-	    sym = new WithScopeSymbol(this);
-	    sym->parent = sc->scopesym;
-	}
-	else
-	{   error("with expressions must be class objects, not '%s'", exp->type->toChars());
-	    return NULL;
-	}
-    }
-    sc = sc->push(sym);
-
-    if (body)
-	body = body->semantic(sc);
-
-    sc->pop();
-
-    return this;
-}
-
-void WithStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{
-    buf->writestring("with (");
-    exp->toCBuffer(buf, hgs);
-    buf->writestring(")\n");
-    if (body)
-	body->toCBuffer(buf, hgs);
-}
-
-int WithStatement::usesEH()
-{
-    return body ? body->usesEH() : 0;
-}
-
-int WithStatement::blockExit()
-{
-    int result = BEnone;
-    if (exp->canThrow())
-	result = BEthrow;
-    if (body)
-	result |= body->blockExit();
-    else
-	result |= BEfallthru;
-    return result;
-}
-
-int WithStatement::fallOffEnd()
-{
-    return body ? body->fallOffEnd() : TRUE;
-}
-
-/******************************** TryCatchStatement ***************************/
-
-TryCatchStatement::TryCatchStatement(Loc loc, Statement *body, Array *catches)
-    : Statement(loc)
-{
-    this->body = body;
-    this->catches = catches;
-}
-
-Statement *TryCatchStatement::syntaxCopy()
-{
-    Array *a = new Array();
-    a->setDim(catches->dim);
-    for (int i = 0; i < a->dim; i++)
-    {   Catch *c;
-
-	c = (Catch *)catches->data[i];
-	c = c->syntaxCopy();
-	a->data[i] = c;
-    }
-    TryCatchStatement *s = new TryCatchStatement(loc, body->syntaxCopy(), a);
-    return s;
-}
-
-Statement *TryCatchStatement::semantic(Scope *sc)
-{
-    body = body->semanticScope(sc, NULL /*this*/, NULL);
-
-    /* Even if body is NULL, still do semantic analysis on catches
-     */
-    for (size_t i = 0; i < catches->dim; i++)
-    {   Catch *c = (Catch *)catches->data[i];
-	c->semantic(sc);
-
-	// Determine if current catch 'hides' any previous catches
-	for (size_t j = 0; j < i; j++)
-	{   Catch *cj = (Catch *)catches->data[j];
-	    char *si = c->loc.toChars();
-	    char *sj = cj->loc.toChars();
-
-	    if (c->type->toBasetype()->implicitConvTo(cj->type->toBasetype()))
-		error("catch at %s hides catch at %s", sj, si);
-	}
-    }
-
-    if (!body)
-	return NULL;
-
-    return this;
-}
-
-int TryCatchStatement::hasBreak()
-{
-    return FALSE; //TRUE;
-}
-
-int TryCatchStatement::usesEH()
-{
-    return TRUE;
-}
-
-int TryCatchStatement::blockExit()
-{   int result;
-
-    assert(body);
-    result = body->blockExit();
-
-    for (size_t i = 0; i < catches->dim; i++)
-    {
-        Catch *c = (Catch *)catches->data[i];
-        result |= c->blockExit();
-    }
-    return result;
-}
-
-int TryCatchStatement::fallOffEnd()
-{
-    int result = FALSE;
-
-    if (body)
-	result = body->fallOffEnd();
-    for (int i = 0; i < catches->dim; i++)
-    {   Catch *c;
-
-	c = (Catch *)catches->data[i];
-	if (c->handler)
-	    result |= c->handler->fallOffEnd();
-    }
-    return result;
-}
-
-void TryCatchStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{
-    buf->writestring("try");
-    buf->writenl();
-    if (body)
-        body->toCBuffer(buf, hgs);
-    for (size_t i = 0; i < catches->dim; i++)
-    {
-        Catch *c = (Catch *)catches->data[i];
-        c->toCBuffer(buf, hgs);
-    }
-}
-
-/******************************** Catch ***************************/
-
-Catch::Catch(Loc loc, Type *t, Identifier *id, Statement *handler)
-{
-    //printf("Catch(%s, loc = %s)\n", id->toChars(), loc.toChars());
-    this->loc = loc;
-    this->type = t;
-    this->ident = id;
-    this->handler = handler;
-    var = NULL;
-}
-
-Catch *Catch::syntaxCopy()
-{
-    Catch *c = new Catch(loc,
-	(type ? type->syntaxCopy() : NULL),
-	ident,
-	(handler ? handler->syntaxCopy() : NULL));
-    return c;
-}
-
-void Catch::semantic(Scope *sc)
-{   ScopeDsymbol *sym;
-
-    //printf("Catch::semantic(%s)\n", ident->toChars());
-
-#ifndef IN_GCC
-    if (sc->tf)
-    {
-	/* This is because the _d_local_unwind() gets the stack munged
-	 * up on this. The workaround is to place any try-catches into
-	 * a separate function, and call that.
-	 * To fix, have the compiler automatically convert the finally
-	 * body into a nested function.
-	 */
-	error(loc, "cannot put catch statement inside finally block");
-    }
-#endif
-
-    sym = new ScopeDsymbol();
-    sym->parent = sc->scopesym;
-    sc = sc->push(sym);
-
-    if (!type)
-	type = new TypeIdentifier(0, Id::Object);
-    type = type->semantic(loc, sc);
-    if (!type->toBasetype()->isClassHandle())
-	error("can only catch class objects, not '%s'", type->toChars());
-    else if (ident)
-    {
-	var = new VarDeclaration(loc, type, ident, NULL);
-	var->parent = sc->parent;
-	sc->insert(var);
-    }
-    handler = handler->semantic(sc);
-
-    sc->pop();
-}
-
-int Catch::blockExit()
-{
-    return handler ? handler->blockExit() : BEfallthru;
-}
-
-void Catch::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{
-    buf->writestring("catch");
-    if (type)
-    {   buf->writebyte('(');
-	type->toCBuffer(buf, ident, hgs);
-        buf->writebyte(')');
-    }
-    buf->writenl();
-    buf->writebyte('{');
-    buf->writenl();
-    if (handler)
-	handler->toCBuffer(buf, hgs);
-    buf->writebyte('}');
-    buf->writenl();
-}
-
-/****************************** TryFinallyStatement ***************************/
-
-TryFinallyStatement::TryFinallyStatement(Loc loc, Statement *body, Statement *finalbody)
-    : Statement(loc)
-{
-    this->body = body;
-    this->finalbody = finalbody;
-    this->enclosinghandler = NULL;
-}
-
-Statement *TryFinallyStatement::syntaxCopy()
-{
-    TryFinallyStatement *s = new TryFinallyStatement(loc,
-	body->syntaxCopy(), finalbody->syntaxCopy());
-    return s;
-}
-
-Statement *TryFinallyStatement::semantic(Scope *sc)
-{
-    //printf("TryFinallyStatement::semantic()\n");
-
-    enclosinghandler = sc->tfOfTry;
-    sc->tfOfTry = new EnclosingTryFinally(this);
-    body = body->semantic(sc);
-    sc->tfOfTry = enclosinghandler;
-
-    sc = sc->push();
-    sc->tf = this;
-    sc->sbreak = NULL;
-    sc->scontinue = NULL;	// no break or continue out of finally block
-    finalbody = finalbody->semantic(sc);
-    sc->pop();
-    if (!body)
-	return finalbody;
-    if (!finalbody)
-	return body;
-    if (body->blockExit() == BEfallthru)
-    {	Statement *s = new CompoundStatement(loc, body, finalbody);
-	return s;
-    }
-    return this;
-}
-
-void TryFinallyStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{
-    buf->printf("try\n{\n");
-    body->toCBuffer(buf, hgs);
-    buf->printf("}\nfinally\n{\n");
-    finalbody->toCBuffer(buf, hgs);
-    buf->writeByte('}');
-    buf->writenl();
-}
-
-int TryFinallyStatement::hasBreak()
-{
-    return FALSE; //TRUE;
-}
-
-int TryFinallyStatement::hasContinue()
-{
-    return FALSE; //TRUE;
-}
-
-int TryFinallyStatement::usesEH()
-{
-    return TRUE;
-}
-
-int TryFinallyStatement::blockExit()
-{
-    int result = body->blockExit();
-    return result;
-}
-
-int TryFinallyStatement::fallOffEnd()
-{   int result;
-
-    result = body->fallOffEnd();
-//    if (finalbody)
-//	result = finalbody->fallOffEnd();
-    return result;
-}
-
-/****************************** OnScopeStatement ***************************/
-
-OnScopeStatement::OnScopeStatement(Loc loc, TOK tok, Statement *statement)
-    : Statement(loc)
-{
-    this->tok = tok;
-    this->statement = statement;
-}
-
-Statement *OnScopeStatement::syntaxCopy()
-{
-    OnScopeStatement *s = new OnScopeStatement(loc,
-	tok, statement->syntaxCopy());
-    return s;
-}
-
-Statement *OnScopeStatement::semantic(Scope *sc)
-{
-    /* semantic is called on results of scopeCode() */
-    return this;
-}
-
-int OnScopeStatement::blockExit()
-{   // At this point, this statement is just an empty placeholder
-    return BEfallthru;
-}
-
-void OnScopeStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{
-    buf->writestring(Token::toChars(tok));
-    buf->writebyte(' ');
-    statement->toCBuffer(buf, hgs);
-}
-
-int OnScopeStatement::usesEH()
-{
-    return 1;
-}
-
-void OnScopeStatement::scopeCode(Scope *sc, Statement **sentry, Statement **sexception, Statement **sfinally)
-{
-    //printf("OnScopeStatement::scopeCode()\n");
-    //print();
-    *sentry = NULL;
-    *sexception = NULL;
-    *sfinally = NULL;
-    switch (tok)
-    {
-	case TOKon_scope_exit:
-	    *sfinally = statement;
-	    break;
-
-	case TOKon_scope_failure:
-	    *sexception = statement;
-	    break;
-
-	case TOKon_scope_success:
-	{
-	    /* Create:
-	     *	sentry:   int x = 0;
-	     *	sexception:    x = 1;
-	     *	sfinally: if (!x) statement;
-	     */
-	    Identifier *id = Lexer::uniqueId("__os");
-
-	    ExpInitializer *ie = new ExpInitializer(loc, new IntegerExp(0));
-	    VarDeclaration *v = new VarDeclaration(loc, Type::tint32, id, ie);
-	    *sentry = new DeclarationStatement(loc, v);
-
-	    Expression *e = new IntegerExp(1);
-	    e = new AssignExp(0, new VarExp(0, v), e);
-	    *sexception = new ExpStatement(0, e);
-
-	    e = new VarExp(0, v);
-	    e = new NotExp(0, e);
-	    *sfinally = new IfStatement(0, NULL, e, statement, NULL);
-
-	    break;
-	}
-
-	default:
-	    assert(0);
-    }
-}
-
-/******************************** ThrowStatement ***************************/
-
-ThrowStatement::ThrowStatement(Loc loc, Expression *exp)
-    : Statement(loc)
-{
-    this->exp = exp;
-}
-
-Statement *ThrowStatement::syntaxCopy()
-{
-    ThrowStatement *s = new ThrowStatement(loc, exp->syntaxCopy());
-    return s;
-}
-
-Statement *ThrowStatement::semantic(Scope *sc)
-{
-    //printf("ThrowStatement::semantic()\n");
-
-    FuncDeclaration *fd = sc->parent->isFuncDeclaration();
-    fd->hasReturnExp |= 2;
-
-    if (sc->incontract)
-	error("Throw statements cannot be in contracts");
-    exp = exp->semantic(sc);
-    exp = resolveProperties(sc, exp);
-    if (!exp->type->toBasetype()->isClassHandle())
-	error("can only throw class objects, not type %s", exp->type->toChars());
-    return this;
-}
-
-int ThrowStatement::blockExit()
-{
-    return BEthrow;  // obviously
-}
-
-int ThrowStatement::fallOffEnd()
-{
-    return FALSE;
-}
-
-void ThrowStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{
-    buf->printf("throw ");
-    exp->toCBuffer(buf, hgs);
-    buf->writeByte(';');
-    buf->writenl();
-}
-
-/******************************** VolatileStatement **************************/
-
-VolatileStatement::VolatileStatement(Loc loc, Statement *statement)
-    : Statement(loc)
-{
-    this->statement = statement;
-    this->enclosinghandler = NULL;
-}
-
-Statement *VolatileStatement::syntaxCopy()
-{
-    VolatileStatement *s = new VolatileStatement(loc,
-		statement ? statement->syntaxCopy() : NULL);
-    return s;
-}
-
-Statement *VolatileStatement::semantic(Scope *sc)
-{
-    if (statement)
-    {
-    enclosinghandler = sc->tfOfTry;
-    sc->tfOfTry = new EnclosingVolatile(this);
-	statement = statement->semantic(sc);
-    sc->tfOfTry = enclosinghandler;
-    }
-    return this;
-}
-
-Statements *VolatileStatement::flatten(Scope *sc)
-{
-    Statements *a;
-
-    a = statement ? statement->flatten(sc) : NULL;
-    if (a)
-    {	for (int i = 0; i < a->dim; i++)
-	{   Statement *s = (Statement *)a->data[i];
-
-	    s = new VolatileStatement(loc, s);
-	    a->data[i] = s;
-	}
-    }
-
-    return a;
-}
-
-int VolatileStatement::blockExit()
-{
-    return statement ? statement->blockExit() : BEfallthru;
-}
-
-int VolatileStatement::fallOffEnd()
-{
-    return statement ? statement->fallOffEnd() : TRUE;
-}
-
-void VolatileStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{
-    buf->writestring("volatile");
-    if (statement)
-    {   if (statement->isScopeStatement())
-            buf->writenl();
-        else
-            buf->writebyte(' ');
-        statement->toCBuffer(buf, hgs);
-    }
-}
-
-
-/******************************** GotoStatement ***************************/
-
-GotoStatement::GotoStatement(Loc loc, Identifier *ident)
-    : Statement(loc)
-{
-    this->ident = ident;
-    this->label = NULL;
-    this->tf = NULL;
-    this->enclosinghandler = NULL;
-}
-
-Statement *GotoStatement::syntaxCopy()
-{
-    GotoStatement *s = new GotoStatement(loc, ident);
-    return s;
-}
-
-Statement *GotoStatement::semantic(Scope *sc)
-{   FuncDeclaration *fd = sc->parent->isFuncDeclaration();
-
-    //printf("GotoStatement::semantic()\n");
-    tf = sc->tf;
-    enclosinghandler = sc->tfOfTry;
-    label = fd->searchLabel(ident);
-    if (!label->statement && sc->fes)
-    {
-	/* Either the goto label is forward referenced or it
-	 * is in the function that the enclosing foreach is in.
-	 * Can't know yet, so wrap the goto in a compound statement
-	 * so we can patch it later, and add it to a 'look at this later'
-	 * list.
-	 */
-	Statements *a = new Statements();
-	Statement *s;
-
-	a->push(this);
-	s = new CompoundStatement(loc, a);
-	sc->fes->gotos.push(s);		// 'look at this later' list
-	return s;
-    }
-    if (label->statement && label->statement->tf != sc->tf)
-	error("cannot goto in or out of finally block");
-    return this;
-}
-
-int GotoStatement::blockExit()
-{
-    //printf("GotoStatement::blockExit(%p)\n", this);
-    return BEgoto;
-}
-
-int GotoStatement::fallOffEnd()
-{
-    return FALSE;
-}
-
-void GotoStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{
-    buf->writestring("goto ");
-    buf->writestring(ident->toChars());
-    buf->writebyte(';');
-    buf->writenl();
-}
-
-/******************************** LabelStatement ***************************/
-
-LabelStatement::LabelStatement(Loc loc, Identifier *ident, Statement *statement)
-    : Statement(loc)
-{
-    this->ident = ident;
-    this->statement = statement;
-    this->tf = NULL;
-    this->enclosinghandler = NULL;
-    this->lblock = NULL;
-    this->isReturnLabel = 0;
-    this->asmLabel = false;
-}
-
-Statement *LabelStatement::syntaxCopy()
-{
-    LabelStatement *s = new LabelStatement(loc, ident, statement->syntaxCopy());
-    return s;
-}
-
-Statement *LabelStatement::semantic(Scope *sc)
-{   LabelDsymbol *ls;
-    FuncDeclaration *fd = sc->parent->isFuncDeclaration();
-
-    //printf("LabelStatement::semantic()\n");
-    ls = fd->searchLabel(ident);
-    if (ls->statement)
-	error("Label '%s' already defined", ls->toChars());
-    else
-	ls->statement = this;
-    tf = sc->tf;
-    enclosinghandler = sc->tfOfTry;
-    sc = sc->push();
-    sc->scopesym = sc->enclosing->scopesym;
-    sc->callSuper |= CSXlabel;
-    sc->slabel = this;
-    if (statement)
-	statement = statement->semantic(sc);
-    sc->pop();
-
-    // LDC put in labmap
-    fd->labmap[ident->toChars()] = this;
-
-    return this;
-}
-
-Statements *LabelStatement::flatten(Scope *sc)
-{
-    Statements *a = NULL;
-
-    if (statement)
-    {
-	a = statement->flatten(sc);
-	if (a)
-	{
-	    if (!a->dim)
-	    {
-		a->push(new ExpStatement(loc, NULL));
-	    }
-	    Statement *s = (Statement *)a->data[0];
-
-	    s = new LabelStatement(loc, ident, s);
-	    a->data[0] = s;
-	}
-    }
-
-    return a;
-}
-
-
-int LabelStatement::usesEH()
-{
-    return statement ? statement->usesEH() : FALSE;
-}
-
-int LabelStatement::blockExit()
-{
-    //printf("LabelStatement::blockExit(%p)\n", this);
-    return statement ? statement->blockExit() : BEfallthru;
-}
-
-int LabelStatement::fallOffEnd()
-{
-    return statement ? statement->fallOffEnd() : TRUE;
-}
-
-int LabelStatement::comeFrom()
-{
-    //printf("LabelStatement::comeFrom()\n");
-    return TRUE;
-}
-
-void LabelStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{
-    buf->writestring(ident->toChars());
-    buf->writebyte(':');
-    buf->writenl();
-    if (statement)
-        statement->toCBuffer(buf, hgs);
-}
-
-
-/******************************** LabelDsymbol ***************************/
-
-LabelDsymbol::LabelDsymbol(Identifier *ident)
-	: Dsymbol(ident)
-{
-    statement = NULL;
-}
-
-LabelDsymbol *LabelDsymbol::isLabel()		// is this a LabelDsymbol()?
-{
-    return this;
-}
-
-
+
+// Compiler implementation of the D programming language
+// Copyright (c) 1999-2009 by Digital Mars
+// All Rights Reserved
+// written by Walter Bright
+// http://www.digitalmars.com
+// License for redistribution is by either the Artistic License
+// in artistic.txt, or the GNU General Public License in gnu.txt.
+// See the included readme.txt for details.
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+
+#include "rmem.h"
+
+#include "statement.h"
+#include "expression.h"
+#include "cond.h"
+#include "init.h"
+#include "staticassert.h"
+#include "mtype.h"
+#include "scope.h"
+#include "declaration.h"
+#include "aggregate.h"
+#include "id.h"
+#include "hdrgen.h"
+#include "parse.h"
+#include "template.h"
+#include "attrib.h"
+
+/******************************** Statement ***************************/
+
+Statement::Statement(Loc loc)
+    : loc(loc)
+{
+#ifdef _DH
+    // If this is an in{} contract scope statement (skip for determining
+    //  inlineStatus of a function body for header content)
+    incontract = 0;
+#endif
+}
+
+Statement *Statement::syntaxCopy()
+{
+    assert(0);
+    return NULL;
+}
+
+void Statement::print()
+{
+    fprintf(stdmsg, "%s\n", toChars());
+    fflush(stdmsg);
+}
+
+char *Statement::toChars()
+{   OutBuffer *buf;
+    HdrGenState hgs;
+
+    buf = new OutBuffer();
+    toCBuffer(buf, &hgs);
+    return buf->toChars();
+}
+
+void Statement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    buf->printf("Statement::toCBuffer()");
+    buf->writenl();
+}
+
+Statement *Statement::semantic(Scope *sc)
+{
+    return this;
+}
+
+// Same as semantic(), but do create a new scope
+
+Statement *Statement::semanticScope(Scope *sc, Statement *sbreak, Statement *scontinue)
+{   Scope *scd;
+    Statement *s;
+
+    scd = sc->push();
+    if (sbreak)
+	scd->sbreak = sbreak;
+    if (scontinue)
+	scd->scontinue = scontinue;
+    s = semantic(scd);
+    scd->pop();
+    return s;
+}
+
+void Statement::error(const char *format, ...)
+{
+    va_list ap;
+    va_start(ap, format);
+    ::verror(loc, format, ap);
+    va_end( ap );
+}
+
+void Statement::warning(const char *format, ...)
+{
+    if (global.params.warnings && !global.gag)
+    {
+	va_list ap;
+	va_start(ap, format);
+	::vwarning(loc, format, ap);
+	va_end( ap );
+    }
+}
+
+int Statement::hasBreak()
+{
+    //printf("Statement::hasBreak()\n");
+    return FALSE;
+}
+
+int Statement::hasContinue()
+{
+    return FALSE;
+}
+
+// TRUE if statement uses exception handling
+
+int Statement::usesEH()
+{
+    return FALSE;
+}
+
+/* Only valid after semantic analysis
+ */
+int Statement::blockExit()
+{
+    printf("Statement::blockExit(%p)\n", this);
+    printf("%s\n", toChars());
+    assert(0);
+    return BEany;
+}
+
+// TRUE if statement 'comes from' somewhere else, like a goto
+
+int Statement::comeFrom()
+{
+    //printf("Statement::comeFrom()\n");
+    return FALSE;
+}
+
+/****************************************
+ * If this statement has code that needs to run in a finally clause
+ * at the end of the current scope, return that code in the form of
+ * a Statement.
+ * Output:
+ *	*sentry		code executed upon entry to the scope
+ *	*sexception	code executed upon exit from the scope via exception
+ *	*sfinally	code executed in finally block
+ */
+
+void Statement::scopeCode(Scope *sc, Statement **sentry, Statement **sexception, Statement **sfinally)
+{
+    //printf("Statement::scopeCode()\n");
+    //print();
+    *sentry = NULL;
+    *sexception = NULL;
+    *sfinally = NULL;
+}
+
+/*********************************
+ * Flatten out the scope by presenting the statement
+ * as an array of statements.
+ * Returns NULL if no flattening necessary.
+ */
+
+Statements *Statement::flatten(Scope *sc)
+{
+    return NULL;
+}
+
+
+/******************************** ExpStatement ***************************/
+
+ExpStatement::ExpStatement(Loc loc, Expression *exp)
+    : Statement(loc)
+{
+    this->exp = exp;
+}
+
+Statement *ExpStatement::syntaxCopy()
+{
+    Expression *e = exp ? exp->syntaxCopy() : NULL;
+    ExpStatement *es = new ExpStatement(loc, e);
+    return es;
+}
+
+void ExpStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    if (exp)
+	exp->toCBuffer(buf, hgs);
+    buf->writeByte(';');
+    if (!hgs->FLinit.init)
+        buf->writenl();
+}
+
+Statement *ExpStatement::semantic(Scope *sc)
+{
+    if (exp)
+    {
+	//printf("ExpStatement::semantic() %s\n", exp->toChars());
+	exp = exp->semantic(sc);
+	exp = resolveProperties(sc, exp);
+	exp->checkSideEffect(0);
+	exp = exp->optimize(0);
+	if (exp->op == TOKdeclaration && !isDeclarationStatement())
+	{   Statement *s = new DeclarationStatement(loc, exp);
+	    return s;
+	}
+	//exp = exp->optimize(isDeclarationStatement() ? WANTvalue : 0);
+    }
+    return this;
+}
+
+int ExpStatement::blockExit()
+{   int result = BEfallthru;
+
+    if (exp)
+    {
+	if (exp->op == TOKhalt)
+	    return BEhalt;
+	if (exp->op == TOKassert)
+	{   AssertExp *a = (AssertExp *)exp;
+
+	    if (a->e1->isBool(FALSE))	// if it's an assert(0)
+		return BEhalt;
+	}
+	if (exp->canThrow())
+	    result |= BEthrow;
+    }
+    return result;
+}
+
+
+/******************************** CompileStatement ***************************/
+
+CompileStatement::CompileStatement(Loc loc, Expression *exp)
+    : Statement(loc)
+{
+    this->exp = exp;
+}
+
+Statement *CompileStatement::syntaxCopy()
+{
+    Expression *e = exp->syntaxCopy();
+    CompileStatement *es = new CompileStatement(loc, e);
+    return es;
+}
+
+void CompileStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    buf->writestring("mixin(");
+    exp->toCBuffer(buf, hgs);
+    buf->writestring(");");
+    if (!hgs->FLinit.init)
+        buf->writenl();
+}
+
+Statements *CompileStatement::flatten(Scope *sc)
+{
+    //printf("CompileStatement::flatten() %s\n", exp->toChars());
+    exp = exp->semantic(sc);
+    exp = resolveProperties(sc, exp);
+    exp = exp->optimize(WANTvalue | WANTinterpret);
+    if (exp->op != TOKstring)
+    {	error("argument to mixin must be a string, not (%s)", exp->toChars());
+	return NULL;
+    }
+    StringExp *se = (StringExp *)exp;
+    se = se->toUTF8(sc);
+    Parser p(sc->module, (unsigned char *)se->string, se->len, 0);
+    p.loc = loc;
+    p.nextToken();
+
+    Statements *a = new Statements();
+    while (p.token.value != TOKeof)
+    {
+	Statement *s = p.parseStatement(PSsemi | PScurlyscope);
+	a->push(s);
+    }
+    return a;
+}
+
+Statement *CompileStatement::semantic(Scope *sc)
+{
+    //printf("CompileStatement::semantic() %s\n", exp->toChars());
+    Statements *a = flatten(sc);
+    if (!a)
+	return NULL;
+    Statement *s = new CompoundStatement(loc, a);
+    return s->semantic(sc);
+}
+
+
+/******************************** DeclarationStatement ***************************/
+
+DeclarationStatement::DeclarationStatement(Loc loc, Dsymbol *declaration)
+    : ExpStatement(loc, new DeclarationExp(loc, declaration))
+{
+}
+
+DeclarationStatement::DeclarationStatement(Loc loc, Expression *exp)
+    : ExpStatement(loc, exp)
+{
+}
+
+Statement *DeclarationStatement::syntaxCopy()
+{
+    DeclarationStatement *ds = new DeclarationStatement(loc, exp->syntaxCopy());
+    return ds;
+}
+
+void DeclarationStatement::scopeCode(Scope *sc, Statement **sentry, Statement **sexception, Statement **sfinally)
+{
+    //printf("DeclarationStatement::scopeCode()\n");
+    //print();
+
+    *sentry = NULL;
+    *sexception = NULL;
+    *sfinally = NULL;
+
+    if (exp)
+    {
+	if (exp->op == TOKdeclaration)
+	{
+	    DeclarationExp *de = (DeclarationExp *)(exp);
+	    VarDeclaration *v = de->declaration->isVarDeclaration();
+	    if (v)
+	    {	Expression *e;
+
+		e = v->callAutoDtor(sc);
+		if (e)
+		{
+		    //printf("dtor is: "); e->print();
+		    *sfinally = new ExpStatement(loc, e);
+		}
+	    }
+	}
+    }
+}
+
+void DeclarationStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    exp->toCBuffer(buf, hgs);
+}
+
+
+/******************************** CompoundStatement ***************************/
+
+CompoundStatement::CompoundStatement(Loc loc, Statements *s)
+    : Statement(loc)
+{
+    statements = s;
+}
+
+CompoundStatement::CompoundStatement(Loc loc, Statement *s1, Statement *s2)
+    : Statement(loc)
+{
+    statements = new Statements();
+    statements->reserve(2);
+    statements->push(s1);
+    statements->push(s2);
+}
+
+Statement *CompoundStatement::syntaxCopy()
+{
+    Statements *a = new Statements();
+    a->setDim(statements->dim);
+    for (size_t i = 0; i < statements->dim; i++)
+    {	Statement *s = (Statement *)statements->data[i];
+	if (s)
+	    s = s->syntaxCopy();
+	a->data[i] = s;
+    }
+    CompoundStatement *cs = new CompoundStatement(loc, a);
+    return cs;
+}
+
+
+Statement *CompoundStatement::semantic(Scope *sc)
+{   Statement *s;
+
+    //printf("CompoundStatement::semantic(this = %p, sc = %p)\n", this, sc);
+
+    for (size_t i = 0; i < statements->dim; )
+    {
+	s = (Statement *) statements->data[i];
+	if (s)
+	{   Statements *a = s->flatten(sc);
+
+	    if (a)
+	    {
+		statements->remove(i);
+		statements->insert(i, a);
+		continue;
+	    }
+	    s = s->semantic(sc);
+	    statements->data[i] = s;
+	    if (s)
+	    {
+		Statement *sentry;
+		Statement *sexception;
+		Statement *sfinally;
+
+		s->scopeCode(sc, &sentry, &sexception, &sfinally);
+		if (sentry)
+		{
+		    sentry = sentry->semantic(sc);
+		    statements->data[i] = sentry;
+		}
+		if (sexception)
+		{
+		    if (i + 1 == statements->dim && !sfinally)
+		    {
+#if 1
+			sexception = sexception->semantic(sc);
+#else
+			statements->push(sexception);
+			if (sfinally)
+			    // Assume sexception does not throw
+			    statements->push(sfinally);
+#endif
+		    }
+		    else
+		    {
+			/* Rewrite:
+			 *	s; s1; s2;
+			 * As:
+			 *	s;
+			 *	try { s1; s2; }
+			 *	catch (Object __o)
+			 *	{ sexception; throw __o; }
+			 */
+			Statement *body;
+			Statements *a = new Statements();
+
+			for (int j = i + 1; j < statements->dim; j++)
+			{
+			    a->push(statements->data[j]);
+			}
+			body = new CompoundStatement(0, a);
+			body = new ScopeStatement(0, body);
+
+			Identifier *id = Lexer::uniqueId("__o");
+
+			Statement *handler = new ThrowStatement(0, new IdentifierExp(0, id));
+			handler = new CompoundStatement(0, sexception, handler);
+
+			Array *catches = new Array();
+			Catch *ctch = new Catch(0, NULL, id, handler);
+			catches->push(ctch);
+			s = new TryCatchStatement(0, body, catches);
+
+			if (sfinally)
+			    s = new TryFinallyStatement(0, s, sfinally);
+			s = s->semantic(sc);
+			statements->setDim(i + 1);
+			statements->push(s);
+			break;
+		    }
+		}
+		else if (sfinally)
+		{
+		    if (0 && i + 1 == statements->dim)
+		    {
+			statements->push(sfinally);
+		    }
+		    else
+		    {
+			/* Rewrite:
+			 *	s; s1; s2;
+			 * As:
+			 *	s; try { s1; s2; } finally { sfinally; }
+			 */
+			Statement *body;
+			Statements *a = new Statements();
+
+			for (int j = i + 1; j < statements->dim; j++)
+			{
+			    a->push(statements->data[j]);
+			}
+			body = new CompoundStatement(0, a);
+			s = new TryFinallyStatement(0, body, sfinally);
+			s = s->semantic(sc);
+			statements->setDim(i + 1);
+			statements->push(s);
+			break;
+		    }
+		}
+	    }
+	}
+	i++;
+    }
+    if (statements->dim == 1 && !isAsmBlockStatement())
+    {
+	return (Statement *)statements->data[0];
+    }
+    return this;
+}
+
+Statements *CompoundStatement::flatten(Scope *sc)
+{
+    return statements;
+}
+
+ReturnStatement *CompoundStatement::isReturnStatement()
+{
+    ReturnStatement *rs = NULL;
+
+    for (int i = 0; i < statements->dim; i++)
+    {	Statement *s = (Statement *) statements->data[i];
+	if (s)
+	{
+	    rs = s->isReturnStatement();
+	    if (rs)
+		break;
+	}
+    }
+    return rs;
+}
+
+void CompoundStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    for (int i = 0; i < statements->dim; i++)
+    {	Statement *s = (Statement *) statements->data[i];
+	if (s)
+	    s->toCBuffer(buf, hgs);
+    }
+}
+
+int CompoundStatement::usesEH()
+{
+    for (int i = 0; i < statements->dim; i++)
+    {	Statement *s = (Statement *) statements->data[i];
+	if (s && s->usesEH())
+	    return TRUE;
+    }
+    return FALSE;
+}
+
+int CompoundStatement::blockExit()
+{
+    //printf("CompoundStatement::blockExit(%p) %d\n", this, statements->dim);
+    int result = BEfallthru;
+    for (size_t i = 0; i < statements->dim; i++)
+    {	Statement *s = (Statement *) statements->data[i];
+	if (s)
+	{
+//printf("result = x%x\n", result);
+//printf("%s\n", s->toChars());
+	    if (!(result & BEfallthru) && !s->comeFrom())
+	    {
+		s->warning("statement is not reachable");
+	    }
+
+	    result &= ~BEfallthru;
+	    result |= s->blockExit();
+	}
+    }
+    return result;
+}
+
+int CompoundStatement::comeFrom()
+{   int comefrom = FALSE;
+
+    //printf("CompoundStatement::comeFrom()\n");
+    for (int i = 0; i < statements->dim; i++)
+    {	Statement *s = (Statement *)statements->data[i];
+
+	if (!s)
+	    continue;
+
+	comefrom |= s->comeFrom();
+    }
+    return comefrom;
+}
+
+
+/******************************** CompoundDeclarationStatement ***************************/
+
+CompoundDeclarationStatement::CompoundDeclarationStatement(Loc loc, Statements *s)
+    : CompoundStatement(loc, s)
+{
+    statements = s;
+}
+
+Statement *CompoundDeclarationStatement::syntaxCopy()
+{
+    Statements *a = new Statements();
+    a->setDim(statements->dim);
+    for (size_t i = 0; i < statements->dim; i++)
+    {	Statement *s = (Statement *)statements->data[i];
+	if (s)
+	    s = s->syntaxCopy();
+	a->data[i] = s;
+    }
+    CompoundDeclarationStatement *cs = new CompoundDeclarationStatement(loc, a);
+    return cs;
+}
+
+void CompoundDeclarationStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    int nwritten = 0;
+    for (int i = 0; i < statements->dim; i++)
+    {	Statement *s = (Statement *) statements->data[i];
+	if (s)
+	{   DeclarationStatement *ds = s->isDeclarationStatement();
+	    assert(ds);
+	    DeclarationExp *de = (DeclarationExp *)ds->exp;
+	    assert(de->op == TOKdeclaration);
+	    Declaration *d = de->declaration->isDeclaration();
+	    assert(d);
+	    VarDeclaration *v = d->isVarDeclaration();
+	    if (v)
+	    {
+		/* This essentially copies the part of VarDeclaration::toCBuffer()
+		 * that does not print the type.
+		 * Should refactor this.
+		 */
+		if (nwritten)
+		{
+		    buf->writeByte(',');
+		    buf->writestring(v->ident->toChars());
+		}
+		else
+		{
+		    StorageClassDeclaration::stcToCBuffer(buf, v->storage_class);
+		    if (v->type)
+			v->type->toCBuffer(buf, v->ident, hgs);
+		    else
+			buf->writestring(v->ident->toChars());
+		}
+
+		if (v->init)
+		{   buf->writestring(" = ");
+#if DMDV2
+		    ExpInitializer *ie = v->init->isExpInitializer();
+		    if (ie && (ie->exp->op == TOKconstruct || ie->exp->op == TOKblit))
+			((AssignExp *)ie->exp)->e2->toCBuffer(buf, hgs);
+		    else
+#endif
+			v->init->toCBuffer(buf, hgs);
+		}
+	    }
+	    else
+		d->toCBuffer(buf, hgs);
+	    nwritten++;
+	}
+    }
+    buf->writeByte(';');
+    if (!hgs->FLinit.init)
+        buf->writenl();
+}
+
+/**************************** UnrolledLoopStatement ***************************/
+
+UnrolledLoopStatement::UnrolledLoopStatement(Loc loc, Statements *s)
+    : Statement(loc)
+{
+    statements = s;
+}
+
+Statement *UnrolledLoopStatement::syntaxCopy()
+{
+    Statements *a = new Statements();
+    a->setDim(statements->dim);
+    for (size_t i = 0; i < statements->dim; i++)
+    {	Statement *s = (Statement *)statements->data[i];
+	if (s)
+	    s = s->syntaxCopy();
+	a->data[i] = s;
+    }
+    UnrolledLoopStatement *cs = new UnrolledLoopStatement(loc, a);
+    return cs;
+}
+
+
+Statement *UnrolledLoopStatement::semantic(Scope *sc)
+{
+    //printf("UnrolledLoopStatement::semantic(this = %p, sc = %p)\n", this, sc);
+
+    sc->noctor++;
+    Scope *scd = sc->push();
+    scd->sbreak = this;
+    scd->scontinue = this;
+
+    for (size_t i = 0; i < statements->dim; i++)
+    {
+	Statement *s = (Statement *) statements->data[i];
+	if (s)
+	{
+	    s = s->semantic(scd);
+	    statements->data[i] = s;
+	}
+    }
+
+    scd->pop();
+    sc->noctor--;
+    return this;
+}
+
+void UnrolledLoopStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    buf->writestring("unrolled {");
+    buf->writenl();
+
+    for (size_t i = 0; i < statements->dim; i++)
+    {	Statement *s;
+
+	s = (Statement *) statements->data[i];
+	if (s)
+	    s->toCBuffer(buf, hgs);
+    }
+
+    buf->writeByte('}');
+    buf->writenl();
+}
+
+int UnrolledLoopStatement::hasBreak()
+{
+    return TRUE;
+}
+
+int UnrolledLoopStatement::hasContinue()
+{
+    return TRUE;
+}
+
+int UnrolledLoopStatement::usesEH()
+{
+    for (size_t i = 0; i < statements->dim; i++)
+    {	Statement *s = (Statement *) statements->data[i];
+	if (s && s->usesEH())
+	    return TRUE;
+    }
+    return FALSE;
+}
+
+int UnrolledLoopStatement::blockExit()
+{
+    int result = BEfallthru;
+    for (size_t i = 0; i < statements->dim; i++)
+    {	Statement *s = (Statement *) statements->data[i];
+	if (s)
+	{
+	    int r = s->blockExit();
+	    result |= r & ~(BEbreak | BEcontinue);
+	}
+    }
+    return result;
+}
+
+
+int UnrolledLoopStatement::comeFrom()
+{   int comefrom = FALSE;
+
+    //printf("UnrolledLoopStatement::comeFrom()\n");
+    for (size_t i = 0; i < statements->dim; i++)
+    {	Statement *s = (Statement *)statements->data[i];
+
+	if (!s)
+	    continue;
+
+	comefrom |= s->comeFrom();
+    }
+    return comefrom;
+}
+
+
+/******************************** ScopeStatement ***************************/
+
+ScopeStatement::ScopeStatement(Loc loc, Statement *s)
+    : Statement(loc)
+{
+    this->statement = s;
+}
+
+Statement *ScopeStatement::syntaxCopy()
+{
+    Statement *s;
+
+    s = statement ? statement->syntaxCopy() : NULL;
+    s = new ScopeStatement(loc, s);
+    return s;
+}
+
+
+Statement *ScopeStatement::semantic(Scope *sc)
+{   ScopeDsymbol *sym;
+
+    //printf("ScopeStatement::semantic(sc = %p)\n", sc);
+    if (statement)
+    {	Statements *a;
+
+	sym = new ScopeDsymbol();
+	sym->parent = sc->scopesym;
+	sc = sc->push(sym);
+
+	a = statement->flatten(sc);
+	if (a)
+	{
+	    statement = new CompoundStatement(loc, a);
+	}
+
+	statement = statement->semantic(sc);
+	if (statement)
+	{
+	    Statement *sentry;
+	    Statement *sexception;
+	    Statement *sfinally;
+
+	    statement->scopeCode(sc, &sentry, &sexception, &sfinally);
+	    if (sfinally)
+	    {
+		//printf("adding sfinally\n");
+		statement = new CompoundStatement(loc, statement, sfinally);
+	    }
+	}
+
+	sc->pop();
+    }
+    return this;
+}
+
+int ScopeStatement::hasBreak()
+{
+    //printf("ScopeStatement::hasBreak() %s\n", toChars());
+    return statement ? statement->hasBreak() : FALSE;
+}
+
+int ScopeStatement::hasContinue()
+{
+    return statement ? statement->hasContinue() : FALSE;
+}
+
+int ScopeStatement::usesEH()
+{
+    return statement ? statement->usesEH() : FALSE;
+}
+
+int ScopeStatement::blockExit()
+{
+    //printf("ScopeStatement::blockExit(%p)\n", statement);
+    return statement ? statement->blockExit() : BEfallthru;
+}
+
+
+int ScopeStatement::comeFrom()
+{
+    //printf("ScopeStatement::comeFrom()\n");
+    return statement ? statement->comeFrom() : FALSE;
+}
+
+void ScopeStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    buf->writeByte('{');
+    buf->writenl();
+
+    if (statement)
+	statement->toCBuffer(buf, hgs);
+
+    buf->writeByte('}');
+    buf->writenl();
+}
+
+/******************************** WhileStatement ***************************/
+
+WhileStatement::WhileStatement(Loc loc, Expression *c, Statement *b)
+    : Statement(loc)
+{
+    condition = c;
+    body = b;
+}
+
+Statement *WhileStatement::syntaxCopy()
+{
+    WhileStatement *s = new WhileStatement(loc, condition->syntaxCopy(), body ? body->syntaxCopy() : NULL);
+    return s;
+}
+
+
+Statement *WhileStatement::semantic(Scope *sc)
+{
+#if 0
+    if (condition->op == TOKmatch)
+    {
+	/* Rewrite while (condition) body as:
+	 *   if (condition)
+	 *     do
+	 *       body
+	 *     while ((_match = _match.opNext), _match);
+	 */
+
+	Expression *ew = new IdentifierExp(0, Id::_match);
+	ew = new DotIdExp(0, ew, Id::next);
+	ew = new AssignExp(0, new IdentifierExp(0, Id::_match), ew);
+	////ew = new EqualExp(TOKnotequal, 0, ew, new NullExp(0));
+	Expression *ev = new IdentifierExp(0, Id::_match);
+	//ev = new CastExp(0, ev, Type::tvoidptr);
+	ew = new CommaExp(0, ew, ev);
+	Statement *sw = new DoStatement(loc, body, ew);
+	Statement *si = new IfStatement(loc, condition, sw, NULL);
+	return si->semantic(sc);
+    }
+#endif
+
+    condition = condition->semantic(sc);
+    condition = resolveProperties(sc, condition);
+    condition = condition->optimize(WANTvalue);
+    condition = condition->checkToBoolean();
+
+    sc->noctor++;
+
+    Scope *scd = sc->push();
+    scd->sbreak = this;
+    scd->scontinue = this;
+    if (body)
+	body = body->semantic(scd);
+    scd->pop();
+
+    sc->noctor--;
+
+    return this;
+}
+
+int WhileStatement::hasBreak()
+{
+    return TRUE;
+}
+
+int WhileStatement::hasContinue()
+{
+    return TRUE;
+}
+
+int WhileStatement::usesEH()
+{
+    return body ? body->usesEH() : 0;
+}
+
+int WhileStatement::blockExit()
+{
+    //printf("WhileStatement::blockExit(%p)\n", this);
+
+    int result = BEnone;
+    if (condition->canThrow())
+	result |= BEthrow;
+    if (condition->isBool(TRUE))
+    {
+	if (body)
+	{   result |= body->blockExit();
+	    if (result & BEbreak)
+		result |= BEfallthru;
+	}
+    }
+    else if (condition->isBool(FALSE))
+    {
+	result |= BEfallthru;
+    }
+    else
+    {
+	if (body)
+	    result |= body->blockExit();
+	result |= BEfallthru;
+    }
+    result &= ~(BEbreak | BEcontinue);
+    return result;
+}
+
+
+int WhileStatement::comeFrom()
+{
+    if (body)
+	return body->comeFrom();
+    return FALSE;
+}
+
+void WhileStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    buf->writestring("while (");
+    condition->toCBuffer(buf, hgs);
+    buf->writebyte(')');
+    buf->writenl();
+    if (body)
+	body->toCBuffer(buf, hgs);
+}
+
+/******************************** DoStatement ***************************/
+
+DoStatement::DoStatement(Loc loc, Statement *b, Expression *c)
+    : Statement(loc)
+{
+    body = b;
+    condition = c;
+}
+
+Statement *DoStatement::syntaxCopy()
+{
+    DoStatement *s = new DoStatement(loc, body ? body->syntaxCopy() : NULL, condition->syntaxCopy());
+    return s;
+}
+
+
+Statement *DoStatement::semantic(Scope *sc)
+{
+    sc->noctor++;
+    if (body)
+	body = body->semanticScope(sc, this, this);
+    sc->noctor--;
+    condition = condition->semantic(sc);
+    condition = resolveProperties(sc, condition);
+    condition = condition->optimize(WANTvalue);
+
+    condition = condition->checkToBoolean();
+
+    return this;
+}
+
+int DoStatement::hasBreak()
+{
+    return TRUE;
+}
+
+int DoStatement::hasContinue()
+{
+    return TRUE;
+}
+
+int DoStatement::usesEH()
+{
+    return body ? body->usesEH() : 0;
+}
+
+int DoStatement::blockExit()
+{   int result;
+
+    if (body)
+    {	result = body->blockExit();
+	if (result == BEbreak)
+	    return BEfallthru;
+	if (result & BEcontinue)
+	    result |= BEfallthru;
+    }
+    else
+	result = BEfallthru;
+    if (result & BEfallthru)
+    {	if (condition->canThrow())
+	    result |= BEthrow;
+	if (!(result & BEbreak) && condition->isBool(TRUE))
+	    result &= ~BEfallthru;
+    }
+    result &= ~(BEbreak | BEcontinue);
+    return result;
+}
+
+
+int DoStatement::comeFrom()
+{
+    if (body)
+	return body->comeFrom();
+    return FALSE;
+}
+
+void DoStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    buf->writestring("do");
+    buf->writenl();
+    if (body)
+	body->toCBuffer(buf, hgs);
+    buf->writestring("while (");
+    condition->toCBuffer(buf, hgs);
+    buf->writebyte(')');
+}
+
+/******************************** ForStatement ***************************/
+
+ForStatement::ForStatement(Loc loc, Statement *init, Expression *condition, Expression *increment, Statement *body)
+    : Statement(loc)
+{
+    this->init = init;
+    this->condition = condition;
+    this->increment = increment;
+    this->body = body;
+}
+
+Statement *ForStatement::syntaxCopy()
+{
+    Statement *i = NULL;
+    if (init)
+	i = init->syntaxCopy();
+    Expression *c = NULL;
+    if (condition)
+	c = condition->syntaxCopy();
+    Expression *inc = NULL;
+    if (increment)
+	inc = increment->syntaxCopy();
+    ForStatement *s = new ForStatement(loc, i, c, inc, body->syntaxCopy());
+    return s;
+}
+
+Statement *ForStatement::semantic(Scope *sc)
+{
+    ScopeDsymbol *sym = new ScopeDsymbol();
+    sym->parent = sc->scopesym;
+    sc = sc->push(sym);
+    if (init)
+	init = init->semantic(sc);
+    sc->noctor++;
+    if (condition)
+    {
+	condition = condition->semantic(sc);
+	condition = resolveProperties(sc, condition);
+	condition = condition->optimize(WANTvalue);
+	condition = condition->checkToBoolean();
+    }
+    if (increment)
+    {	increment = increment->semantic(sc);
+	increment = resolveProperties(sc, increment);
+    }
+
+    sc->sbreak = this;
+    sc->scontinue = this;
+    if (body)
+	body = body->semantic(sc);
+    sc->noctor--;
+
+    sc->pop();
+    return this;
+}
+
+void ForStatement::scopeCode(Scope *sc, Statement **sentry, Statement **sexception, Statement **sfinally)
+{
+    //printf("ForStatement::scopeCode()\n");
+    //print();
+    if (init)
+	init->scopeCode(sc, sentry, sexception, sfinally);
+    else
+	Statement::scopeCode(sc, sentry, sexception, sfinally);
+}
+
+int ForStatement::hasBreak()
+{
+    //printf("ForStatement::hasBreak()\n");
+    return TRUE;
+}
+
+int ForStatement::hasContinue()
+{
+    return TRUE;
+}
+
+int ForStatement::usesEH()
+{
+    return (init && init->usesEH()) || body->usesEH();
+}
+
+int ForStatement::blockExit()
+{   int result = BEfallthru;
+
+    if (init)
+    {	result = init->blockExit();
+	if (!(result & BEfallthru))
+	    return result;
+    }
+    if (condition)
+    {	if (condition->canThrow())
+	    result |= BEthrow;
+    }
+    else
+	result &= ~BEfallthru;	// the body must do the exiting
+    if (body)
+    {	int r = body->blockExit();
+	if (r & (BEbreak | BEgoto))
+	    result |= BEfallthru;
+	result |= r & ~(BEfallthru | BEbreak | BEcontinue);
+    }
+    if (increment && increment->canThrow())
+	result |= BEthrow;
+    return result;
+}
+
+
+int ForStatement::comeFrom()
+{
+    //printf("ForStatement::comeFrom()\n");
+    if (body)
+    {	int result = body->comeFrom();
+	//printf("result = %d\n", result);
+	return result;
+    }
+    return FALSE;
+}
+
+void ForStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    buf->writestring("for (");
+    if (init)
+    {
+        hgs->FLinit.init++;
+        init->toCBuffer(buf, hgs);
+        hgs->FLinit.init--;
+    }
+    else
+        buf->writebyte(';');
+    if (condition)
+    {   buf->writebyte(' ');
+        condition->toCBuffer(buf, hgs);
+    }
+    buf->writebyte(';');
+    if (increment)
+    {   buf->writebyte(' ');
+        increment->toCBuffer(buf, hgs);
+    }
+    buf->writebyte(')');
+    buf->writenl();
+    buf->writebyte('{');
+    buf->writenl();
+    body->toCBuffer(buf, hgs);
+    buf->writebyte('}');
+    buf->writenl();
+}
+
+/******************************** ForeachStatement ***************************/
+
+ForeachStatement::ForeachStatement(Loc loc, enum TOK op, Arguments *arguments,
+	Expression *aggr, Statement *body)
+    : Statement(loc)
+{
+    this->op = op;
+    this->arguments = arguments;
+    this->aggr = aggr;
+    this->body = body;
+
+    this->key = NULL;
+    this->value = NULL;
+
+    this->func = NULL;
+}
+
+Statement *ForeachStatement::syntaxCopy()
+{
+    Arguments *args = Argument::arraySyntaxCopy(arguments);
+    Expression *exp = aggr->syntaxCopy();
+    ForeachStatement *s = new ForeachStatement(loc, op, args, exp,
+	body ? body->syntaxCopy() : NULL);
+    return s;
+}
+
+Statement *ForeachStatement::semantic(Scope *sc)
+{
+    //printf("ForeachStatement::semantic() %p\n", this);
+    ScopeDsymbol *sym;
+    Statement *s = this;
+    size_t dim = arguments->dim;
+    TypeAArray *taa = NULL;
+
+    Type *tn = NULL;
+    Type *tnv = NULL;
+
+    func = sc->func;
+    if (func->fes)
+	func = func->fes->func;
+
+    aggr = aggr->semantic(sc);
+    aggr = resolveProperties(sc, aggr);
+    aggr = aggr->optimize(WANTvalue);
+    if (!aggr->type)
+    {
+	error("invalid foreach aggregate %s", aggr->toChars());
+	return this;
+    }
+
+    inferApplyArgTypes(op, arguments, aggr, sc->module);
+
+    /* Check for inference errors
+     */
+    if (dim != arguments->dim)
+    {
+	//printf("dim = %d, arguments->dim = %d\n", dim, arguments->dim);
+	error("cannot uniquely infer foreach argument types");
+	return this;
+    }
+
+    Type *tab = aggr->type->toBasetype();
+
+    if (tab->ty == Ttuple)	// don't generate new scope for tuple loops
+    {
+	if (dim < 1 || dim > 2)
+	{
+	    error("only one (value) or two (key,value) arguments for tuple foreach");
+	    return s;
+	}
+
+	TypeTuple *tuple = (TypeTuple *)tab;
+	Statements *statements = new Statements();
+	//printf("aggr: op = %d, %s\n", aggr->op, aggr->toChars());
+	size_t n;
+	TupleExp *te = NULL;
+	if (aggr->op == TOKtuple)	// expression tuple
+	{   te = (TupleExp *)aggr;
+	    n = te->exps->dim;
+	}
+	else if (aggr->op == TOKtype)	// type tuple
+	{
+	    n = Argument::dim(tuple->arguments);
+	}
+	else
+	    assert(0);
+	for (size_t j = 0; j < n; j++)
+	{   size_t k = (op == TOKforeach) ? j : n - 1 - j;
+	    Expression *e;
+	    Type *t;
+	    if (te)
+		e = (Expression *)te->exps->data[k];
+	    else
+		t = Argument::getNth(tuple->arguments, k)->type;
+	    Argument *arg = (Argument *)arguments->data[0];
+	    Statements *st = new Statements();
+
+	    if (dim == 2)
+	    {   // Declare key
+		if (arg->storageClass & (STCout | STCref | STClazy))
+		    error("no storage class for key %s", arg->ident->toChars());
+		TY keyty = arg->type->ty;
+		if (keyty != Tint32 && keyty != Tuns32)
+		{
+		    if (global.params.is64bit)
+		    {
+			if (keyty != Tint64 && keyty != Tuns64)
+			    error("foreach: key type must be int or uint, long or ulong, not %s", arg->type->toChars());
+		    }
+		    else
+			error("foreach: key type must be int or uint, not %s", arg->type->toChars());
+		}
+		Initializer *ie = new ExpInitializer(0, new IntegerExp(k));
+		VarDeclaration *var = new VarDeclaration(loc, arg->type, arg->ident, ie);
+		var->storage_class |= STCmanifest;
+		DeclarationExp *de = new DeclarationExp(loc, var);
+		st->push(new ExpStatement(loc, de));
+		arg = (Argument *)arguments->data[1];	// value
+	    }
+	    // Declare value
+	    if (arg->storageClass & (STCout | STCref | STClazy))
+		error("no storage class for value %s", arg->ident->toChars());
+	    Dsymbol *var;
+	    if (te)
+	    {	Type *tb = e->type->toBasetype();
+		if ((tb->ty == Tfunction || tb->ty == Tsarray) && e->op == TOKvar)
+		{   VarExp *ve = (VarExp *)e;
+		    var = new AliasDeclaration(loc, arg->ident, ve->var);
+		}
+		else
+		{
+		    arg->type = e->type;
+		    Initializer *ie = new ExpInitializer(0, e);
+		    VarDeclaration *v = new VarDeclaration(loc, arg->type, arg->ident, ie);
+		    if (e->isConst())
+			v->storage_class |= STCconst;
+		    var = v;
+		}
+	    }
+	    else
+	    {
+		var = new AliasDeclaration(loc, arg->ident, t);
+	    }
+	    DeclarationExp *de = new DeclarationExp(loc, var);
+	    st->push(new ExpStatement(loc, de));
+
+	    st->push(body->syntaxCopy());
+	    s = new CompoundStatement(loc, st);
+	    s = new ScopeStatement(loc, s);
+	    statements->push(s);
+	}
+
+	s = new UnrolledLoopStatement(loc, statements);
+	s = s->semantic(sc);
+	return s;
+    }
+
+    sym = new ScopeDsymbol();
+    sym->parent = sc->scopesym;
+    sc = sc->push(sym);
+
+    sc->noctor++;
+
+    switch (tab->ty)
+    {
+	case Tarray:
+	case Tsarray:
+	    if (!checkForArgTypes())
+		return this;
+
+	    if (dim < 1 || dim > 2)
+	    {
+		error("only one or two arguments for array foreach");
+		break;
+	    }
+
+	    /* Look for special case of parsing char types out of char type
+	     * array.
+	     */
+	    tn = tab->nextOf()->toBasetype();
+	    if (tn->ty == Tchar || tn->ty == Twchar || tn->ty == Tdchar)
+	    {	Argument *arg;
+
+		int i = (dim == 1) ? 0 : 1;	// index of value
+		arg = (Argument *)arguments->data[i];
+		arg->type = arg->type->semantic(loc, sc);
+		tnv = arg->type->toBasetype();
+		if (tnv->ty != tn->ty &&
+		    (tnv->ty == Tchar || tnv->ty == Twchar || tnv->ty == Tdchar))
+		{
+		    if (arg->storageClass & STCref)
+			error("foreach: value of UTF conversion cannot be ref");
+		    if (dim == 2)
+		    {	arg = (Argument *)arguments->data[0];
+			if (arg->storageClass & STCref)
+			    error("foreach: key cannot be ref");
+		    }
+		    goto Lapply;
+		}
+	    }
+
+	    for (size_t i = 0; i < dim; i++)
+	    {	// Declare args
+		Argument *arg = (Argument *)arguments->data[i];
+		VarDeclaration *var;
+
+		var = new VarDeclaration(loc, arg->type, arg->ident, NULL);
+		var->storage_class |= STCforeach;
+		var->storage_class |= arg->storageClass & (STCin | STCout | STCref | STC_TYPECTOR);
+		if (dim == 2 && i == 0)
+		{   key = var;
+		    //var->storage_class |= STCfinal;
+		}
+		else
+		{
+		    value = var;
+		    /* Reference to immutable data should be marked as const
+		     */
+		    if (var->storage_class & STCref && !tn->isMutable())
+		    {
+			var->storage_class |= STCconst;
+		    }
+		}
+#if 1
+		DeclarationExp *de = new DeclarationExp(loc, var);
+		de->semantic(sc);
+#else
+		var->semantic(sc);
+		if (!sc->insert(var))
+		    error("%s already defined", var->ident->toChars());
+#endif
+	    }
+
+	    sc->sbreak = this;
+	    sc->scontinue = this;
+	    body = body->semantic(sc);
+
+	    if (tab->nextOf()->implicitConvTo(value->type) < MATCHconst)
+	    {
+		if (aggr->op == TOKstring)
+		    aggr = aggr->implicitCastTo(sc, value->type->arrayOf());
+		else
+		    error("foreach: %s is not an array of %s",
+			tab->toChars(), value->type->toChars());
+	    }
+
+	    if (key && key->type->ty != Tint32 && key->type->ty != Tuns32)
+	    {
+		if (global.params.is64bit)
+		{
+		    if (key->type->ty != Tint64 && key->type->ty != Tuns64)
+			error("foreach: key type must be int or uint, long or ulong, not %s", key->type->toChars());
+		}
+		else
+		    error("foreach: key type must be int or uint, not %s", key->type->toChars());
+	    }
+
+	    if (key && key->storage_class & (STCout | STCref))
+		error("foreach: key cannot be out or ref");
+	    break;
+
+	case Taarray:
+	    if (!checkForArgTypes())
+		return this;
+
+	    taa = (TypeAArray *)tab;
+	    if (dim < 1 || dim > 2)
+	    {
+		error("only one or two arguments for associative array foreach");
+		break;
+	    }
+	    if (op == TOKforeach_reverse)
+	    {
+		error("no reverse iteration on associative arrays");
+	    }
+	    goto Lapply;
+
+	case Tclass:
+	case Tstruct:
+#if DMDV2
+	{   /* Look for range iteration, i.e. the properties
+	     * .empty, .next, .retreat, .head and .rear
+	     *    foreach (e; aggr) { ... }
+	     * translates to:
+	     *    for (auto __r = aggr[]; !__r.empty; __r.next)
+	     *    {   auto e = __r.head;
+	     *        ...
+	     *    }
+	     */
+	    if (dim != 1)	// only one argument allowed with ranges
+		goto Lapply;
+	    AggregateDeclaration *ad = (tab->ty == Tclass)
+			? (AggregateDeclaration *)((TypeClass  *)tab)->sym
+			: (AggregateDeclaration *)((TypeStruct *)tab)->sym;
+	    Identifier *idhead;
+	    Identifier *idnext;
+	    if (op == TOKforeach)
+	    {	idhead = Id::Fhead;
+		idnext = Id::Fnext;
+	    }
+	    else
+	    {	idhead = Id::Ftoe;
+		idnext = Id::Fretreat;
+	    }
+	    Dsymbol *shead = search_function(ad, idhead);
+	    if (!shead)
+		goto Lapply;
+
+	    /* Generate a temporary __r and initialize it with the aggregate.
+	     */
+	    Identifier *id = Identifier::generateId("__r");
+	    aggr = aggr->semantic(sc);
+	    Expression *rinit = new SliceExp(loc, aggr, NULL, NULL);
+	    rinit = rinit->trySemantic(sc);
+	    if (!rinit)			// if application of [] failed
+		rinit = aggr;
+	    VarDeclaration *r = new VarDeclaration(loc, NULL, id, new ExpInitializer(loc, rinit));
+//	    r->semantic(sc);
+//printf("r: %s, init: %s\n", r->toChars(), r->init->toChars());
+	    Statement *init = new DeclarationStatement(loc, r);
+//printf("init: %s\n", init->toChars());
+
+	    // !__r.empty
+	    Expression *e = new VarExp(loc, r);
+	    e = new DotIdExp(loc, e, Id::Fempty);
+	    Expression *condition = new NotExp(loc, e);
+
+	    // __r.next
+	    e = new VarExp(loc, r);
+	    Expression *increment = new DotIdExp(loc, e, idnext);
+
+	    /* Declaration statement for e:
+	     *    auto e = __r.idhead;
+	     */
+	    e = new VarExp(loc, r);
+	    Expression *einit = new DotIdExp(loc, e, idhead);
+//	    einit = einit->semantic(sc);
+	    Argument *arg = (Argument *)arguments->data[0];
+	    VarDeclaration *ve = new VarDeclaration(loc, arg->type, arg->ident, new ExpInitializer(loc, einit));
+	    ve->storage_class |= STCforeach;
+	    ve->storage_class |= arg->storageClass & (STCin | STCout | STCref | STC_TYPECTOR);
+
+	    DeclarationExp *de = new DeclarationExp(loc, ve);
+
+	    Statement *body = new CompoundStatement(loc,
+		new DeclarationStatement(loc, de), this->body);
+
+	    s = new ForStatement(loc, init, condition, increment, body);
+#if 0
+	    printf("init: %s\n", init->toChars());
+	    printf("condition: %s\n", condition->toChars());
+	    printf("increment: %s\n", increment->toChars());
+	    printf("body: %s\n", body->toChars());
+#endif
+	    s = s->semantic(sc);
+	    break;
+	}
+#endif
+	case Tdelegate:
+	Lapply:
+	{   FuncDeclaration *fdapply;
+	    Arguments *args;
+	    Expression *ec;
+	    Expression *e;
+	    FuncLiteralDeclaration *fld;
+	    Argument *a;
+	    Type *t;
+	    Expression *flde;
+	    Identifier *id;
+	    Type *tret;
+        TypeDelegate* dgty;
+        TypeDelegate* dgty2;
+        TypeDelegate* fldeTy;
+
+	    if (!checkForArgTypes())
+	    {	body = body->semantic(sc);
+		return this;
+	    }
+
+	    tret = func->type->nextOf();
+
+	    // Need a variable to hold value from any return statements in body.
+	    if (!sc->func->vresult && tret && tret != Type::tvoid)
+	    {	VarDeclaration *v;
+
+		v = new VarDeclaration(loc, tret, Id::result, NULL);
+		v->noauto = 1;
+		v->semantic(sc);
+		if (!sc->insert(v))
+		    assert(0);
+		v->parent = sc->func;
+		sc->func->vresult = v;
+	    }
+
+	    /* Turn body into the function literal:
+	     *	int delegate(ref T arg) { body }
+	     */
+	    args = new Arguments();
+	    for (size_t i = 0; i < dim; i++)
+	    {	Argument *arg = (Argument *)arguments->data[i];
+
+		arg->type = arg->type->semantic(loc, sc);
+		if (arg->storageClass & STCref)
+		    id = arg->ident;
+		else
+		{   // Make a copy of the ref argument so it isn't
+		    // a reference.
+		    VarDeclaration *v;
+		    Initializer *ie;
+
+		    id = Lexer::uniqueId("__applyArg", i);
+
+		    ie = new ExpInitializer(0, new IdentifierExp(0, id));
+		    v = new VarDeclaration(0, arg->type, arg->ident, ie);
+		    s = new DeclarationStatement(0, v);
+		    body = new CompoundStatement(loc, s, body);
+		}
+		a = new Argument(STCref, arg->type, id, NULL);
+		args->push(a);
+	    }
+	    t = new TypeFunction(args, Type::tint32, 0, LINKd);
+	    fld = new FuncLiteralDeclaration(loc, 0, t, TOKdelegate, this);
+	    fld->fbody = body;
+	    flde = new FuncExp(loc, fld);
+	    flde = flde->semantic(sc);
+	    fld->tookAddressOf = 0;
+
+	    // Resolve any forward referenced goto's
+	    for (int i = 0; i < gotos.dim; i++)
+	    {	CompoundStatement *cs = (CompoundStatement *)gotos.data[i];
+		GotoStatement *gs = (GotoStatement *)cs->statements->data[0];
+
+		if (!gs->label->statement)
+		{   // 'Promote' it to this scope, and replace with a return
+		    cases.push(gs);
+		    s = new ReturnStatement(0, new IntegerExp(cases.dim + 1));
+		    cs->statements->data[0] = (void *)s;
+		}
+	    }
+
+	    if (tab->ty == Taarray)
+	    {
+		// Check types
+		Argument *arg = (Argument *)arguments->data[0];
+		if (dim == 2)
+		{
+		    if (arg->storageClass & STCref)
+			error("foreach: index cannot be ref");
+		    if (!arg->type->equals(taa->index))
+			error("foreach: index must be type %s, not %s", taa->index->toChars(), arg->type->toChars());
+		    arg = (Argument *)arguments->data[1];
+		}
+		if (!arg->type->equals(taa->nextOf()))
+		    error("foreach: value must be type %s, not %s", taa->nextOf()->toChars(), arg->type->toChars());
+
+		/* Call:
+		 *	_aaApply(aggr, keysize, flde)
+		 */
+		//LDC: Build arguments.
+		static FuncDeclaration *aaApply2_fd = NULL;
+        static TypeDelegate* aaApply2_dg;
+		if(!aaApply2_fd) {
+		    Arguments* args = new Arguments;
+		    args->push(new Argument(STCin, Type::tvoid->pointerTo(), NULL, NULL));
+		    args->push(new Argument(STCin, Type::tsize_t, NULL, NULL));
+		    Arguments* dgargs = new Arguments;
+		    dgargs->push(new Argument(STCin, Type::tvoidptr, NULL, NULL));
+		    dgargs->push(new Argument(STCin, Type::tvoidptr, NULL, NULL));
+		    aaApply2_dg = new TypeDelegate(new TypeFunction(dgargs, Type::tindex, 0, LINKd));
+		    args->push(new Argument(STCin, aaApply2_dg, NULL, NULL));
+		    aaApply2_fd = FuncDeclaration::genCfunc(args, Type::tindex, "_aaApply2");
+		}
+		static FuncDeclaration *aaApply_fd = NULL;
+        static TypeDelegate* aaApply_dg;
+		if(!aaApply_fd) {
+		    Arguments* args = new Arguments;
+		    args->push(new Argument(STCin, Type::tvoid->pointerTo(), NULL, NULL));
+		    args->push(new Argument(STCin, Type::tsize_t, NULL, NULL));
+		    Arguments* dgargs = new Arguments;
+		    dgargs->push(new Argument(STCin, Type::tvoidptr, NULL, NULL));
+		    aaApply_dg = new TypeDelegate(new TypeFunction(dgargs, Type::tindex, 0, LINKd));
+		    args->push(new Argument(STCin, aaApply_dg, NULL, NULL));
+		    aaApply_fd = FuncDeclaration::genCfunc(args, Type::tindex, "_aaApply");
+		}
+		if (dim == 2) {
+		    fdapply = aaApply2_fd;
+            fldeTy = aaApply2_dg;
+		} else {
+		    fdapply = aaApply_fd;
+            fldeTy = aaApply_dg;
+		}
+		ec = new VarExp(0, fdapply);
+		Expressions *exps = new Expressions();
+		exps->push(aggr);
+		size_t keysize = taa->index->size();
+		keysize = (keysize + (PTRSIZE-1)) & ~(PTRSIZE-1);
+		exps->push(new IntegerExp(0, keysize, Type::tsize_t));
+
+        // LDC paint delegate argument to the type runtime expects
+        if (!fldeTy->equals(flde->type))
+        {
+            flde = new CastExp(loc, flde, flde->type);
+            flde->type = fldeTy;
+        }
+		exps->push(flde);
+		e = new CallExp(loc, ec, exps);
+		e->type = Type::tindex;	// don't run semantic() on e
+	    }
+	    else if (tab->ty == Tarray || tab->ty == Tsarray)
+	    {
+		/* Call:
+		 *	_aApply(aggr, flde)
+		 */
+		static char fntab[9][3] =
+		{ "cc","cw","cd",
+		  "wc","cc","wd",
+		  "dc","dw","dd"
+		};
+		char fdname[7+1+2+ sizeof(dim)*3 + 1];
+		int flag;
+
+		switch (tn->ty)
+		{
+		    case Tchar:		flag = 0; break;
+		    case Twchar:	flag = 3; break;
+		    case Tdchar:	flag = 6; break;
+		    default:		assert(0);
+		}
+		switch (tnv->ty)
+		{
+		    case Tchar:		flag += 0; break;
+		    case Twchar:	flag += 1; break;
+		    case Tdchar:	flag += 2; break;
+		    default:		assert(0);
+		}
+		const char *r = (op == TOKforeach_reverse) ? "R" : "";
+#ifdef __MINGW32__
+		int j = sprintf(fdname, "_aApply%s%.*s%lu", r, 2, fntab[flag], dim);
+#else
+		int j = sprintf(fdname, "_aApply%s%.*s%zu", r, 2, fntab[flag], dim);
+#endif
+		assert(j < sizeof(fdname));
+		//LDC: Build arguments.
+		Arguments* args = new Arguments;
+		args->push(new Argument(STCin, tn->arrayOf(), NULL, NULL));
+		if (dim == 2) {
+		    Arguments* dgargs = new Arguments;
+		    dgargs->push(new Argument(STCin, Type::tvoidptr, NULL, NULL));
+		    dgargs->push(new Argument(STCin, Type::tvoidptr, NULL, NULL));
+		    dgty = new TypeDelegate(new TypeFunction(dgargs, Type::tindex, 0, LINKd));
+		    args->push(new Argument(STCin, dgty, NULL, NULL));
+		    fdapply = FuncDeclaration::genCfunc(args, Type::tindex, fdname);
+		} else {
+		    Arguments* dgargs = new Arguments;
+		    dgargs->push(new Argument(STCin, Type::tvoidptr, NULL, NULL));
+		    dgty = new TypeDelegate(new TypeFunction(dgargs, Type::tindex, 0, LINKd));
+		    args->push(new Argument(STCin, dgty, NULL, NULL));
+		    fdapply = FuncDeclaration::genCfunc(args, Type::tindex, fdname);
+		}
+
+		ec = new VarExp(0, fdapply);
+		Expressions *exps = new Expressions();
+		if (tab->ty == Tsarray)
+		   aggr = aggr->castTo(sc, tn->arrayOf());
+        exps->push(aggr);
+
+        // LDC paint delegate argument to the type runtime expects
+        if (!dgty->equals(flde->type))
+        {
+            flde = new CastExp(loc, flde, flde->type);
+            flde->type = dgty;
+        }
+		exps->push(flde);
+		e = new CallExp(loc, ec, exps);
+		e->type = Type::tindex;	// don't run semantic() on e
+	    }
+	    else if (tab->ty == Tdelegate)
+	    {
+		/* Call:
+		 *	aggr(flde)
+		 */
+		Expressions *exps = new Expressions();
+		exps->push(flde);
+		e = new CallExp(loc, aggr, exps);
+		e = e->semantic(sc);
+		if (e->type != Type::tint32)
+		    error("opApply() function for %s must return an int", tab->toChars());
+	    }
+	    else
+	    {
+		assert(tab->ty == Tstruct || tab->ty == Tclass);
+		Identifier *idapply = (op == TOKforeach_reverse)
+				? Id::applyReverse : Id::apply;
+		Dsymbol *sapply = search_function((AggregateDeclaration *)tab->toDsymbol(sc), idapply);
+	        Expressions *exps = new Expressions();
+#if 0
+		TemplateDeclaration *td;
+		if (sapply &&
+		    (td = sapply->isTemplateDeclaration()) != NULL)
+		{   /* Call:
+		     *	aggr.apply!(fld)()
+		     */
+		    TemplateInstance *ti = new TemplateInstance(loc, idapply);
+		    Objects *tiargs = new Objects();
+		    tiargs->push(fld);
+		    ti->tiargs = tiargs;
+		    ec = new DotTemplateInstanceExp(loc, aggr, ti);
+		}
+		else
+#endif
+		{
+		    /* Call:
+		     *	aggr.apply(flde)
+		     */
+		    ec = new DotIdExp(loc, aggr, idapply);
+		    exps->push(flde);
+		}
+		e = new CallExp(loc, ec, exps);
+		e = e->semantic(sc);
+		if (e->type != Type::tint32)
+		    error("opApply() function for %s must return an int", tab->toChars());
+	    }
+
+	    if (!cases.dim)
+		// Easy case, a clean exit from the loop
+		s = new ExpStatement(loc, e);
+	    else
+	    {	// Construct a switch statement around the return value
+		// of the apply function.
+		Statements *a = new Statements();
+
+		// default: break; takes care of cases 0 and 1
+		s = new BreakStatement(0, NULL);
+		s = new DefaultStatement(0, s);
+		a->push(s);
+
+		// cases 2...
+		for (int i = 0; i < cases.dim; i++)
+		{
+		    s = (Statement *)cases.data[i];
+		    s = new CaseStatement(0, new IntegerExp(i + 2), s);
+		    a->push(s);
+		}
+
+		s = new CompoundStatement(loc, a);
+		s = new SwitchStatement(loc, e, s);
+		s = s->semantic(sc);
+	    }
+	    break;
+	}
+
+	default:
+	    error("foreach: %s is not an aggregate type", aggr->type->toChars());
+	    s = NULL;	// error recovery
+	    break;
+    }
+    sc->noctor--;
+    sc->pop();
+    return s;
+}
+
+bool ForeachStatement::checkForArgTypes()
+{   bool result = TRUE;
+
+    for (size_t i = 0; i < arguments->dim; i++)
+    {	Argument *arg = (Argument *)arguments->data[i];
+	if (!arg->type)
+	{
+	    error("cannot infer type for %s", arg->ident->toChars());
+	    arg->type = Type::terror;
+	    result = FALSE;
+	}
+    }
+    return result;
+}
+
+int ForeachStatement::hasBreak()
+{
+    return TRUE;
+}
+
+int ForeachStatement::hasContinue()
+{
+    return TRUE;
+}
+
+int ForeachStatement::usesEH()
+{
+    return body->usesEH();
+}
+
+int ForeachStatement::blockExit()
+{   int result = BEfallthru;
+
+    if (aggr->canThrow())
+	result |= BEthrow;
+
+    if (body)
+    {
+	result |= body->blockExit() & ~(BEbreak | BEcontinue);
+    }
+    return result;
+}
+
+
+int ForeachStatement::comeFrom()
+{
+    if (body)
+	return body->comeFrom();
+    return FALSE;
+}
+
+void ForeachStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    buf->writestring(Token::toChars(op));
+    buf->writestring(" (");
+    for (int i = 0; i < arguments->dim; i++)
+    {
+	Argument *a = (Argument *)arguments->data[i];
+	if (i)
+	    buf->writestring(", ");
+	if (a->storageClass & STCref)
+	    buf->writestring((global.params.Dversion == 1)
+		? (char*)"inout " : (char*)"ref ");
+	if (a->type)
+	    a->type->toCBuffer(buf, a->ident, hgs);
+	else
+	    buf->writestring(a->ident->toChars());
+    }
+    buf->writestring("; ");
+    aggr->toCBuffer(buf, hgs);
+    buf->writebyte(')');
+    buf->writenl();
+    buf->writebyte('{');
+    buf->writenl();
+    if (body)
+	body->toCBuffer(buf, hgs);
+    buf->writebyte('}');
+    buf->writenl();
+}
+
+/**************************** ForeachRangeStatement ***************************/
+
+#if DMDV2
+
+ForeachRangeStatement::ForeachRangeStatement(Loc loc, enum TOK op, Argument *arg,
+	Expression *lwr, Expression *upr, Statement *body)
+    : Statement(loc)
+{
+    this->op = op;
+    this->arg = arg;
+    this->lwr = lwr;
+    this->upr = upr;
+    this->body = body;
+
+    this->key = NULL;
+}
+
+Statement *ForeachRangeStatement::syntaxCopy()
+{
+    ForeachRangeStatement *s = new ForeachRangeStatement(loc, op,
+	arg->syntaxCopy(),
+	lwr->syntaxCopy(),
+	upr->syntaxCopy(),
+	body ? body->syntaxCopy() : NULL);
+    return s;
+}
+
+Statement *ForeachRangeStatement::semantic(Scope *sc)
+{
+    //printf("ForeachRangeStatement::semantic() %p\n", this);
+    ScopeDsymbol *sym;
+    Statement *s = this;
+
+    lwr = lwr->semantic(sc);
+    lwr = resolveProperties(sc, lwr);
+    lwr = lwr->optimize(WANTvalue);
+    if (!lwr->type)
+    {
+	error("invalid range lower bound %s", lwr->toChars());
+	return this;
+    }
+
+    upr = upr->semantic(sc);
+    upr = resolveProperties(sc, upr);
+    upr = upr->optimize(WANTvalue);
+    if (!upr->type)
+    {
+	error("invalid range upper bound %s", upr->toChars());
+	return this;
+    }
+
+    if (arg->type)
+    {
+	arg->type = arg->type->semantic(loc, sc);
+	lwr = lwr->implicitCastTo(sc, arg->type);
+	upr = upr->implicitCastTo(sc, arg->type);
+    }
+    else
+    {
+	/* Must infer types from lwr and upr
+	 */
+	AddExp ea(loc, lwr, upr);
+	ea.typeCombine(sc);
+	arg->type = ea.type->mutableOf();
+	lwr = ea.e1;
+	upr = ea.e2;
+    }
+    if (!arg->type->isscalar())
+	error("%s is not a scalar type", arg->type->toChars());
+
+    sym = new ScopeDsymbol();
+    sym->parent = sc->scopesym;
+    sc = sc->push(sym);
+
+    sc->noctor++;
+
+    key = new VarDeclaration(loc, arg->type, arg->ident, NULL);
+    DeclarationExp *de = new DeclarationExp(loc, key);
+    de->semantic(sc);
+
+    if (key->storage_class)
+	error("foreach range: key cannot have storage class");
+
+    sc->sbreak = this;
+    sc->scontinue = this;
+    body = body->semantic(sc);
+
+    sc->noctor--;
+    sc->pop();
+    return s;
+}
+
+int ForeachRangeStatement::hasBreak()
+{
+    return TRUE;
+}
+
+int ForeachRangeStatement::hasContinue()
+{
+    return TRUE;
+}
+
+int ForeachRangeStatement::usesEH()
+{
+    return body->usesEH();
+}
+
+int ForeachRangeStatement::blockExit()
+{   int result = BEfallthru;
+
+    if (lwr && lwr->canThrow())
+	result |= BEthrow;
+    else if (upr && upr->canThrow())
+	result |= BEthrow;
+
+    if (body)
+    {
+	result |= body->blockExit() & ~(BEbreak | BEcontinue);
+    }
+    return result;
+}
+
+
+int ForeachRangeStatement::comeFrom()
+{
+    if (body)
+	return body->comeFrom();
+    return FALSE;
+}
+
+void ForeachRangeStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    buf->writestring(Token::toChars(op));
+    buf->writestring(" (");
+
+    if (arg->type)
+	arg->type->toCBuffer(buf, arg->ident, hgs);
+    else
+	buf->writestring(arg->ident->toChars());
+
+    buf->writestring("; ");
+    lwr->toCBuffer(buf, hgs);
+    buf->writestring(" .. ");
+    upr->toCBuffer(buf, hgs);
+    buf->writebyte(')');
+    buf->writenl();
+    buf->writebyte('{');
+    buf->writenl();
+    if (body)
+	body->toCBuffer(buf, hgs);
+    buf->writebyte('}');
+    buf->writenl();
+}
+
+#endif
+
+/******************************** IfStatement ***************************/
+
+IfStatement::IfStatement(Loc loc, Argument *arg, Expression *condition, Statement *ifbody, Statement *elsebody)
+    : Statement(loc)
+{
+    this->arg = arg;
+    this->condition = condition;
+    this->ifbody = ifbody;
+    this->elsebody = elsebody;
+    this->match = NULL;
+}
+
+Statement *IfStatement::syntaxCopy()
+{
+    Statement *i = NULL;
+    if (ifbody)
+        i = ifbody->syntaxCopy();
+
+    Statement *e = NULL;
+    if (elsebody)
+	e = elsebody->syntaxCopy();
+
+    Argument *a = arg ? arg->syntaxCopy() : NULL;
+    IfStatement *s = new IfStatement(loc, a, condition->syntaxCopy(), i, e);
+    return s;
+}
+
+Statement *IfStatement::semantic(Scope *sc)
+{
+    condition = condition->semantic(sc);
+    condition = resolveProperties(sc, condition);
+    condition = condition->checkToBoolean();
+
+    // If we can short-circuit evaluate the if statement, don't do the
+    // semantic analysis of the skipped code.
+    // This feature allows a limited form of conditional compilation.
+    condition = condition->optimize(WANTflags);
+
+    // Evaluate at runtime
+    unsigned cs0 = sc->callSuper;
+    unsigned cs1;
+
+    Scope *scd;
+    if (arg)
+    {	/* Declare arg, which we will set to be the
+	 * result of condition.
+	 */
+	ScopeDsymbol *sym = new ScopeDsymbol();
+	sym->parent = sc->scopesym;
+	scd = sc->push(sym);
+
+	Type *t = arg->type ? arg->type : condition->type;
+	match = new VarDeclaration(loc, t, arg->ident, NULL);
+	match->noauto = 1;
+	match->semantic(scd);
+	if (!scd->insert(match))
+	    assert(0);
+	match->parent = sc->func;
+
+	/* Generate:
+	 *  (arg = condition)
+	 */
+	VarExp *v = new VarExp(0, match);
+	condition = new AssignExp(loc, v, condition);
+	condition = condition->semantic(scd);
+    }
+    else
+	scd = sc->push();
+    ifbody = ifbody->semantic(scd);
+    scd->pop();
+
+    cs1 = sc->callSuper;
+    sc->callSuper = cs0;
+    if (elsebody)
+	elsebody = elsebody->semanticScope(sc, NULL, NULL);
+    sc->mergeCallSuper(loc, cs1);
+
+    return this;
+}
+
+int IfStatement::usesEH()
+{
+    return (ifbody && ifbody->usesEH()) || (elsebody && elsebody->usesEH());
+}
+
+int IfStatement::blockExit()
+{
+    //printf("IfStatement::blockExit(%p)\n", this);
+
+    int result = BEnone;
+    if (condition->canThrow())
+	result |= BEthrow;
+    if (condition->isBool(TRUE))
+    {
+	if (ifbody)
+	    result |= ifbody->blockExit();
+	else
+	    result |= BEfallthru;
+    }
+    else if (condition->isBool(FALSE))
+    {
+	if (elsebody)
+	    result |= elsebody->blockExit();
+	else
+	    result |= BEfallthru;
+    }
+    else
+    {
+	if (ifbody)
+	    result |= ifbody->blockExit();
+	else
+	    result |= BEfallthru;
+	if (elsebody)
+	    result |= elsebody->blockExit();
+	else
+	    result |= BEfallthru;
+    }
+    //printf("IfStatement::blockExit(%p) = x%x\n", this, result);
+    return result;
+}
+
+
+void IfStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    buf->writestring("if (");
+    if (arg)
+    {
+	if (arg->type)
+	    arg->type->toCBuffer(buf, arg->ident, hgs);
+	else
+	{   buf->writestring("auto ");
+	    buf->writestring(arg->ident->toChars());
+	}
+	buf->writestring(" = ");
+    }
+    condition->toCBuffer(buf, hgs);
+    buf->writebyte(')');
+    buf->writenl();
+    ifbody->toCBuffer(buf, hgs);
+    if (elsebody)
+    {   buf->writestring("else");
+        buf->writenl();
+        elsebody->toCBuffer(buf, hgs);
+    }
+}
+
+/******************************** ConditionalStatement ***************************/
+
+ConditionalStatement::ConditionalStatement(Loc loc, Condition *condition, Statement *ifbody, Statement *elsebody)
+    : Statement(loc)
+{
+    this->condition = condition;
+    this->ifbody = ifbody;
+    this->elsebody = elsebody;
+}
+
+Statement *ConditionalStatement::syntaxCopy()
+{
+    Statement *e = NULL;
+    if (elsebody)
+	e = elsebody->syntaxCopy();
+    ConditionalStatement *s = new ConditionalStatement(loc,
+		condition->syntaxCopy(), ifbody->syntaxCopy(), e);
+    return s;
+}
+
+Statement *ConditionalStatement::semantic(Scope *sc)
+{
+    //printf("ConditionalStatement::semantic()\n");
+
+    // If we can short-circuit evaluate the if statement, don't do the
+    // semantic analysis of the skipped code.
+    // This feature allows a limited form of conditional compilation.
+    if (condition->include(sc, NULL))
+    {
+	ifbody = ifbody->semantic(sc);
+	return ifbody;
+    }
+    else
+    {
+	if (elsebody)
+	    elsebody = elsebody->semantic(sc);
+	return elsebody;
+    }
+}
+
+Statements *ConditionalStatement::flatten(Scope *sc)
+{
+    Statement *s;
+
+    if (condition->include(sc, NULL))
+	s = ifbody;
+    else
+	s = elsebody;
+
+    Statements *a = new Statements();
+    a->push(s);
+    return a;
+}
+
+int ConditionalStatement::usesEH()
+{
+    return (ifbody && ifbody->usesEH()) || (elsebody && elsebody->usesEH());
+}
+
+int ConditionalStatement::blockExit()
+{
+    int result = ifbody->blockExit();
+    if (elsebody)
+	result |= elsebody->blockExit();
+    return result;
+}
+
+void ConditionalStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    condition->toCBuffer(buf, hgs);
+    buf->writenl();
+    buf->writeByte('{');
+    buf->writenl();
+    if (ifbody)
+	ifbody->toCBuffer(buf, hgs);
+    buf->writeByte('}');
+    buf->writenl();
+    if (elsebody)
+    {
+	buf->writestring("else");
+	buf->writenl();
+	buf->writeByte('{');
+	buf->writenl();
+	elsebody->toCBuffer(buf, hgs);
+	buf->writeByte('}');
+	buf->writenl();
+    }
+    buf->writenl();
+}
+
+
+/******************************** PragmaStatement ***************************/
+
+PragmaStatement::PragmaStatement(Loc loc, Identifier *ident, Expressions *args, Statement *body)
+    : Statement(loc)
+{
+    this->ident = ident;
+    this->args = args;
+    this->body = body;
+}
+
+Statement *PragmaStatement::syntaxCopy()
+{
+    Statement *b = NULL;
+    if (body)
+	b = body->syntaxCopy();
+    PragmaStatement *s = new PragmaStatement(loc,
+		ident, Expression::arraySyntaxCopy(args), b);
+    return s;
+}
+
+Statement *PragmaStatement::semantic(Scope *sc)
+{   // Should be merged with PragmaDeclaration
+    //printf("PragmaStatement::semantic() %s\n", toChars());
+    //printf("body = %p\n", body);
+    if (ident == Id::msg)
+    {
+        if (args)
+        {
+            for (size_t i = 0; i < args->dim; i++)
+            {
+                Expression *e = (Expression *)args->data[i];
+
+                e = e->semantic(sc);
+		e = e->optimize(WANTvalue | WANTinterpret);
+                if (e->op == TOKstring)
+                {
+                    StringExp *se = (StringExp *)e;
+                    fprintf(stdmsg, "%.*s", (int)se->len, (char*)se->string);
+                }
+                else
+		    error("string expected for message, not '%s'", e->toChars());
+            }
+            fprintf(stdmsg, "\n");
+        }
+    }
+    else if (ident == Id::lib)
+    {
+#if 1
+	/* Should this be allowed?
+	 */
+	error("pragma(lib) not allowed as statement");
+#else
+	if (!args || args->dim != 1)
+	    error("string expected for library name");
+	else
+	{
+	    Expression *e = (Expression *)args->data[0];
+
+	    e = e->semantic(sc);
+	    e = e->optimize(WANTvalue | WANTinterpret);
+	    args->data[0] = (void *)e;
+	    if (e->op != TOKstring)
+		error("string expected for library name, not '%s'", e->toChars());
+	    else if (global.params.verbose)
+	    {
+		StringExp *se = (StringExp *)e;
+		char *name = (char *)mem.malloc(se->len + 1);
+		memcpy(name, se->string, se->len);
+		name[se->len] = 0;
+		printf("library   %s\n", name);
+		mem.free(name);
+	    }
+	}
+#endif
+    }
+
+    // LDC
+    else if (ident == Id::allow_inline)
+    {
+        sc->func->allowInlining = true;
+    }
+
+    else if (ident == Id::startaddress)
+    {
+	if (!args || args->dim != 1)
+	    error("function name expected for start address");
+	else
+	{
+	    Expression *e = (Expression *)args->data[0];
+	    e = e->semantic(sc);
+	    e = e->optimize(WANTvalue | WANTinterpret);
+	    args->data[0] = (void *)e;
+	    Dsymbol *sa = getDsymbol(e);
+	    if (!sa || !sa->isFuncDeclaration())
+		error("function name expected for start address, not '%s'", e->toChars());
+	    if (body)
+	    {
+		body = body->semantic(sc);
+	    }
+	    return this;
+	}
+    }
+    else
+        error("unrecognized pragma(%s)", ident->toChars());
+
+    if (body)
+    {
+	body = body->semantic(sc);
+    }
+    return body;
+}
+
+int PragmaStatement::usesEH()
+{
+    return body && body->usesEH();
+}
+
+int PragmaStatement::blockExit()
+{
+    int result = BEfallthru;
+#if 0 // currently, no code is generated for Pragma's, so it's just fallthru
+    if (arrayExpressionCanThrow(args))
+	result |= BEthrow;
+    if (body)
+	result |= body->blockExit();
+#endif
+    return result;
+}
+
+
+void PragmaStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    buf->writestring("pragma (");
+    buf->writestring(ident->toChars());
+    if (args && args->dim)
+    {
+	buf->writestring(", ");
+	argsToCBuffer(buf, args, hgs);
+    }
+    buf->writeByte(')');
+    if (body)
+    {
+	buf->writenl();
+	buf->writeByte('{');
+	buf->writenl();
+
+	body->toCBuffer(buf, hgs);
+
+	buf->writeByte('}');
+	buf->writenl();
+    }
+    else
+    {
+	buf->writeByte(';');
+	buf->writenl();
+    }
+}
+
+
+/******************************** StaticAssertStatement ***************************/
+
+StaticAssertStatement::StaticAssertStatement(StaticAssert *sa)
+    : Statement(sa->loc)
+{
+    this->sa = sa;
+}
+
+Statement *StaticAssertStatement::syntaxCopy()
+{
+    StaticAssertStatement *s = new StaticAssertStatement((StaticAssert *)sa->syntaxCopy(NULL));
+    return s;
+}
+
+Statement *StaticAssertStatement::semantic(Scope *sc)
+{
+    sa->semantic2(sc);
+    return NULL;
+}
+
+void StaticAssertStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    sa->toCBuffer(buf, hgs);
+}
+
+
+/******************************** SwitchStatement ***************************/
+
+SwitchStatement::SwitchStatement(Loc loc, Expression *c, Statement *b)
+    : Statement(loc)
+{
+    condition = c;
+    body = b;
+    sdefault = NULL;
+    cases = NULL;
+    hasNoDefault = 0;
+    hasVars = 0;
+    // LDC
+    enclosingScopeExit = NULL;
+}
+
+Statement *SwitchStatement::syntaxCopy()
+{
+    SwitchStatement *s = new SwitchStatement(loc,
+	condition->syntaxCopy(), body->syntaxCopy());
+    return s;
+}
+
+Statement *SwitchStatement::semantic(Scope *sc)
+{
+    //printf("SwitchStatement::semantic(%p)\n", this);
+    assert(!cases);		// ensure semantic() is only run once
+
+    // LDC
+    enclosingScopeExit = sc->enclosingScopeExit;
+
+    condition = condition->semantic(sc);
+    condition = resolveProperties(sc, condition);
+    if (condition->type->isString())
+    {
+	// If it's not an array, cast it to one
+	if (condition->type->ty != Tarray)
+	{
+	    condition = condition->implicitCastTo(sc, condition->type->nextOf()->arrayOf());
+	}
+	condition->type = condition->type->constOf();
+    }
+    else
+    {	condition = condition->integralPromotions(sc);
+	condition->checkIntegral();
+    }
+    condition = condition->optimize(WANTvalue);
+
+    sc = sc->push();
+    sc->sbreak = this;
+    sc->sw = this;
+
+    cases = new Array();
+    sc->noctor++;	// BUG: should use Scope::mergeCallSuper() for each case instead
+    body = body->semantic(sc);
+    sc->noctor--;
+
+    // Resolve any goto case's with exp
+    for (int i = 0; i < gotoCases.dim; i++)
+    {
+	GotoCaseStatement *gcs = (GotoCaseStatement *)gotoCases.data[i];
+
+	if (!gcs->exp)
+	{
+	    gcs->error("no case statement following goto case;");
+	    break;
+	}
+
+	for (Scope *scx = sc; scx; scx = scx->enclosing)
+	{
+	    if (!scx->sw)
+		continue;
+	    for (int j = 0; j < scx->sw->cases->dim; j++)
+	    {
+		CaseStatement *cs = (CaseStatement *)scx->sw->cases->data[j];
+
+		if (cs->exp->equals(gcs->exp))
+		{
+		    gcs->cs = cs;
+		    goto Lfoundcase;
+		}
+	    }
+	}
+	gcs->error("case %s not found", gcs->exp->toChars());
+
+     Lfoundcase:
+	;
+    }
+
+    if (!sc->sw->sdefault)
+    {	hasNoDefault = 1;
+
+	warning("switch statement has no default");
+
+	// Generate runtime error if the default is hit
+	Statements *a = new Statements();
+	CompoundStatement *cs;
+	Statement *s;
+
+	if (global.params.useSwitchError)
+	    s = new SwitchErrorStatement(loc);
+	else
+	{   Expression *e = new HaltExp(loc);
+	    s = new ExpStatement(loc, e);
+	}
+
+	a->reserve(4);
+	a->push(body);
+
+	// LDC needs semantic to be run on break
+	Statement *breakstmt = new BreakStatement(loc, NULL);
+	breakstmt->semantic(sc);
+	a->push(breakstmt);
+
+	sc->sw->sdefault = new DefaultStatement(loc, s);
+	a->push(sc->sw->sdefault);
+	cs = new CompoundStatement(loc, a);
+	body = cs;
+    }
+
+    sc->pop();
+    return this;
+}
+
+int SwitchStatement::hasBreak()
+{
+    return TRUE;
+}
+
+int SwitchStatement::usesEH()
+{
+    return body ? body->usesEH() : 0;
+}
+
+int SwitchStatement::blockExit()
+{   int result = BEnone;
+    if (condition->canThrow())
+	result |= BEthrow;
+
+    if (body)
+    {	result |= body->blockExit();
+	if (result & BEbreak)
+	{   result |= BEfallthru;
+	    result &= ~BEbreak;
+	}
+    }
+    else
+	result |= BEfallthru;
+
+    return result;
+}
+
+
+void SwitchStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    buf->writestring("switch (");
+    condition->toCBuffer(buf, hgs);
+    buf->writebyte(')');
+    buf->writenl();
+    if (body)
+    {
+	if (!body->isScopeStatement())
+        {   buf->writebyte('{');
+            buf->writenl();
+            body->toCBuffer(buf, hgs);
+            buf->writebyte('}');
+            buf->writenl();
+        }
+        else
+        {
+            body->toCBuffer(buf, hgs);
+        }
+    }
+}
+
+/******************************** CaseStatement ***************************/
+
+CaseStatement::CaseStatement(Loc loc, Expression *exp, Statement *s)
+    : Statement(loc)
+{
+    this->exp = exp;
+    this->statement = s;
+    index = 0;
+    cblock = NULL;
+    bodyBB = NULL;
+    llvmIdx = NULL;
+    // LDC
+    enclosingScopeExit = NULL;
+}
+
+Statement *CaseStatement::syntaxCopy()
+{
+    CaseStatement *s = new CaseStatement(loc, exp->syntaxCopy(), statement->syntaxCopy());
+    return s;
+}
+
+Statement *CaseStatement::semantic(Scope *sc)
+{   SwitchStatement *sw = sc->sw;
+
+    //printf("CaseStatement::semantic() %s\n", toChars());
+    exp = exp->semantic(sc);
+    if (sw)
+    {
+	// LDC
+	enclosingScopeExit = sc->enclosingScopeExit;
+	if (enclosingScopeExit != sw->enclosingScopeExit)
+	{
+	    error("case must be inside the same try, synchronized or volatile level as switch");
+	}
+
+	exp = exp->implicitCastTo(sc, sw->condition->type);
+	exp = exp->optimize(WANTvalue | WANTinterpret);
+
+	/* This is where variables are allowed as case expressions.
+	 */
+	if (exp->op == TOKvar)
+	{   VarExp *ve = (VarExp *)exp;
+	    VarDeclaration *v = ve->var->isVarDeclaration();
+	    Type *t = exp->type->toBasetype();
+	    if (v && (t->isintegral() || t->ty == Tclass))
+	    {	/* Flag that we need to do special code generation
+		 * for this, i.e. generate a sequence of if-then-else
+		 */
+		sw->hasVars = 1;
+		goto L1;
+	    }
+	}
+
+	if (exp->op != TOKstring && exp->op != TOKint64)
+	{
+	    error("case must be a string or an integral constant, not %s", exp->toChars());
+	    exp = new IntegerExp(0);
+	}
+
+    L1:
+	for (int i = 0; i < sw->cases->dim; i++)
+	{
+	    CaseStatement *cs = (CaseStatement *)sw->cases->data[i];
+
+	    //printf("comparing '%s' with '%s'\n", exp->toChars(), cs->exp->toChars());
+	    if (cs->exp->equals(exp))
+	    {	error("duplicate case %s in switch statement", exp->toChars());
+		break;
+	    }
+	}
+
+	sw->cases->push(this);
+
+	// Resolve any goto case's with no exp to this case statement
+	for (int i = 0; i < sw->gotoCases.dim; i++)
+	{
+	    GotoCaseStatement *gcs = (GotoCaseStatement *)sw->gotoCases.data[i];
+
+	    if (!gcs->exp)
+	    {
+		gcs->cs = this;
+		sw->gotoCases.remove(i);	// remove from array
+	    }
+	}
+#if IN_DMD
+	if (sc->sw->tf != sc->tf)
+	    error("switch and case are in different finally blocks");
+#endif
+    }
+    else
+	error("case not in switch statement");
+    statement = statement->semantic(sc);
+    return this;
+}
+
+int CaseStatement::compare(Object *obj)
+{
+    // Sort cases so we can do an efficient lookup
+    CaseStatement *cs2 = (CaseStatement *)(obj);
+
+    return exp->compare(cs2->exp);
+}
+
+int CaseStatement::usesEH()
+{
+    return statement->usesEH();
+}
+
+int CaseStatement::blockExit()
+{
+    return statement->blockExit();
+}
+
+
+int CaseStatement::comeFrom()
+{
+    return TRUE;
+}
+
+void CaseStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    buf->writestring("case ");
+    exp->toCBuffer(buf, hgs);
+    buf->writebyte(':');
+    buf->writenl();
+    statement->toCBuffer(buf, hgs);
+}
+
+/******************************** DefaultStatement ***************************/
+
+DefaultStatement::DefaultStatement(Loc loc, Statement *s)
+    : Statement(loc)
+{
+    this->statement = s;
+#if IN_GCC
++    cblock = NULL;
+#endif
+    bodyBB = NULL;
+    // LDC
+    enclosingScopeExit = NULL;
+}
+
+Statement *DefaultStatement::syntaxCopy()
+{
+    DefaultStatement *s = new DefaultStatement(loc, statement->syntaxCopy());
+    return s;
+}
+
+Statement *DefaultStatement::semantic(Scope *sc)
+{
+    //printf("DefaultStatement::semantic()\n");
+    if (sc->sw)
+    {
+	if (sc->sw->sdefault)
+	{
+	    error("switch statement already has a default");
+	}
+	sc->sw->sdefault = this;
+
+	// LDC
+	enclosingScopeExit = sc->enclosingScopeExit;
+	if (enclosingScopeExit != sc->sw->enclosingScopeExit)
+	{
+	    error("default must be inside the same try, synchronized or volatile level as switch");
+	}
+    }
+    else
+	error("default not in switch statement");
+    statement = statement->semantic(sc);
+    return this;
+}
+
+int DefaultStatement::usesEH()
+{
+    return statement->usesEH();
+}
+
+int DefaultStatement::blockExit()
+{
+    return statement->blockExit();
+}
+
+
+int DefaultStatement::comeFrom()
+{
+    return TRUE;
+}
+
+void DefaultStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    buf->writestring("default:\n");
+    statement->toCBuffer(buf, hgs);
+}
+
+/******************************** GotoDefaultStatement ***************************/
+
+GotoDefaultStatement::GotoDefaultStatement(Loc loc)
+    : Statement(loc)
+{
+    sw = NULL;
+}
+
+Statement *GotoDefaultStatement::syntaxCopy()
+{
+    GotoDefaultStatement *s = new GotoDefaultStatement(loc);
+    return s;
+}
+
+Statement *GotoDefaultStatement::semantic(Scope *sc)
+{
+    sw = sc->sw;
+    if (!sw)
+	error("goto default not in switch statement");
+    return this;
+}
+
+int GotoDefaultStatement::blockExit()
+{
+    return BEgoto;
+}
+
+
+void GotoDefaultStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    buf->writestring("goto default;\n");
+}
+
+/******************************** GotoCaseStatement ***************************/
+
+GotoCaseStatement::GotoCaseStatement(Loc loc, Expression *exp)
+    : Statement(loc)
+{
+    cs = NULL;
+    this->exp = exp;
+    sw = NULL;
+}
+
+Statement *GotoCaseStatement::syntaxCopy()
+{
+    Expression *e = exp ? exp->syntaxCopy() : NULL;
+    GotoCaseStatement *s = new GotoCaseStatement(loc, e);
+    return s;
+}
+
+Statement *GotoCaseStatement::semantic(Scope *sc)
+{
+    if (exp)
+	exp = exp->semantic(sc);
+
+    if (!sc->sw)
+	error("goto case not in switch statement");
+    else
+    {
+	sw = sc->sw;
+	sc->sw->gotoCases.push(this);
+	if (exp)
+	{
+	    exp = exp->implicitCastTo(sc, sc->sw->condition->type);
+	    exp = exp->optimize(WANTvalue);
+	}
+    }
+    return this;
+}
+
+int GotoCaseStatement::blockExit()
+{
+    return BEgoto;
+}
+
+
+void GotoCaseStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    buf->writestring("goto case");
+    if (exp)
+    {   buf->writebyte(' ');
+        exp->toCBuffer(buf, hgs);
+    }
+    buf->writebyte(';');
+    buf->writenl();
+}
+
+/******************************** SwitchErrorStatement ***************************/
+
+SwitchErrorStatement::SwitchErrorStatement(Loc loc)
+    : Statement(loc)
+{
+}
+
+int SwitchErrorStatement::blockExit()
+{
+    return BEthrow;
+}
+
+
+void SwitchErrorStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    buf->writestring("SwitchErrorStatement::toCBuffer()");
+    buf->writenl();
+}
+
+/******************************** ReturnStatement ***************************/
+
+ReturnStatement::ReturnStatement(Loc loc, Expression *exp)
+    : Statement(loc)
+{
+    this->exp = exp;
+}
+
+Statement *ReturnStatement::syntaxCopy()
+{
+    Expression *e = NULL;
+    if (exp)
+	e = exp->syntaxCopy();
+    ReturnStatement *s = new ReturnStatement(loc, e);
+    return s;
+}
+
+Statement *ReturnStatement::semantic(Scope *sc)
+{
+    //printf("ReturnStatement::semantic() %s\n", toChars());
+
+    FuncDeclaration *fd = sc->parent->isFuncDeclaration();
+    Scope *scx = sc;
+    int implicit0 = 0;
+
+    if (sc->fes)
+    {
+	// Find scope of function foreach is in
+	for (; 1; scx = scx->enclosing)
+	{
+	    assert(scx);
+	    if (scx->func != fd)
+	    {	fd = scx->func;		// fd is now function enclosing foreach
+		break;
+	    }
+	}
+    }
+
+    Type *tret = fd->type->nextOf();
+    if (fd->tintro)
+	/* We'll be implicitly casting the return expression to tintro
+	 */
+	tret = fd->tintro->nextOf();
+    Type *tbret = NULL;
+
+    if (tret)
+	tbret = tret->toBasetype();
+
+    // main() returns 0, even if it returns void
+    if (!exp && (!tbret || tbret->ty == Tvoid) && fd->isMain())
+    {	implicit0 = 1;
+	exp = new IntegerExp(0);
+    }
+
+    if (sc->incontract || scx->incontract)
+	error("return statements cannot be in contracts");
+    if (sc->enclosingFinally || scx->enclosingFinally)
+	error("return statements cannot be in finally, scope(exit) or scope(success) bodies");
+
+    if (fd->isCtorDeclaration())
+    {
+	// Constructors implicitly do:
+	//	return this;
+	if (exp && exp->op != TOKthis)
+	    error("cannot return expression from constructor");
+	exp = new ThisExp(0);
+    }
+
+    if (!exp)
+	fd->nrvo_can = 0;
+
+    if (exp)
+    {
+	fd->hasReturnExp |= 1;
+
+	exp = exp->semantic(sc);
+	exp = resolveProperties(sc, exp);
+	exp = exp->optimize(WANTvalue);
+
+	if (fd->nrvo_can && exp->op == TOKvar)
+	{   VarExp *ve = (VarExp *)exp;
+	    VarDeclaration *v = ve->var->isVarDeclaration();
+
+	    if (((TypeFunction *)fd->type)->isref)
+		// Function returns a reference
+		fd->nrvo_can = 0;
+	    else if (!v || v->isOut() || v->isRef())
+		fd->nrvo_can = 0;
+	    else if (tbret->ty == Tstruct && ((TypeStruct *)tbret)->sym->dtor)
+		// Struct being returned has destructors
+		fd->nrvo_can = 0;
+	    else if (fd->nrvo_var == NULL)
+	    {	if (!v->isDataseg() && !v->isParameter() && v->toParent2() == fd)
+		{   //printf("Setting nrvo to %s\n", v->toChars());
+		    fd->nrvo_var = v;
+		}
+		else
+		    fd->nrvo_can = 0;
+	    }
+	    else if (fd->nrvo_var != v)
+		fd->nrvo_can = 0;
+	}
+	else
+	    fd->nrvo_can = 0;
+
+	if (fd->returnLabel && tbret->ty != Tvoid)
+	{
+	}
+	else if (fd->inferRetType)
+	{
+	    if (fd->type->nextOf())
+	    {
+		if (!exp->type->equals(fd->type->nextOf()))
+		    error("mismatched function return type inference of %s and %s",
+			exp->type->toChars(), fd->type->nextOf()->toChars());
+	    }
+	    else
+	    {
+		((TypeFunction *)fd->type)->next = exp->type;
+		fd->type = fd->type->semantic(loc, sc);
+		if (!fd->tintro)
+		{   tret = fd->type->nextOf();
+		    tbret = tret->toBasetype();
+		}
+	    }
+	}
+	else if (tbret->ty != Tvoid)
+	{
+	    exp = exp->implicitCastTo(sc, tret);
+	    exp = exp->optimize(WANTvalue);
+	}
+    }
+    else if (fd->inferRetType)
+    {
+	if (fd->type->nextOf())
+	{
+	    if (fd->type->nextOf()->ty != Tvoid)
+		error("mismatched function return type inference of void and %s",
+		    fd->type->nextOf()->toChars());
+	}
+	else
+	{
+	    ((TypeFunction *)fd->type)->next = Type::tvoid;
+	    fd->type = fd->type->semantic(loc, sc);
+	    if (!fd->tintro)
+	    {   tret = Type::tvoid;
+		tbret = tret;
+	    }
+	}
+    }
+    else if (tbret->ty != Tvoid)	// if non-void return
+	error("return expression expected");
+
+    if (sc->fes)
+    {
+	Statement *s;
+
+	if (exp && !implicit0)
+	{
+	    exp = exp->implicitCastTo(sc, tret);
+	}
+	if (!exp || exp->op == TOKint64 || exp->op == TOKfloat64 ||
+	    exp->op == TOKimaginary80 || exp->op == TOKcomplex80 ||
+	    exp->op == TOKthis || exp->op == TOKsuper || exp->op == TOKnull ||
+	    exp->op == TOKstring)
+	{
+	    sc->fes->cases.push(this);
+	    // Construct: return cases.dim+1;
+	    s = new ReturnStatement(0, new IntegerExp(sc->fes->cases.dim + 1));
+	}
+	else if (fd->type->nextOf()->toBasetype() == Type::tvoid)
+	{
+	    s = new ReturnStatement(0, NULL);
+	    sc->fes->cases.push(s);
+
+	    // Construct: { exp; return cases.dim + 1; }
+	    Statement *s1 = new ExpStatement(loc, exp);
+	    Statement *s2 = new ReturnStatement(0, new IntegerExp(sc->fes->cases.dim + 1));
+	    s = new CompoundStatement(loc, s1, s2);
+	}
+	else
+	{
+	    // Construct: return vresult;
+	    if (!fd->vresult)
+	    {	// Declare vresult
+		VarDeclaration *v = new VarDeclaration(loc, tret, Id::result, NULL);
+		v->noauto = 1;
+		v->semantic(scx);
+		if (!scx->insert(v))
+		    assert(0);
+		v->parent = fd;
+		fd->vresult = v;
+	    }
+
+	    s = new ReturnStatement(0, new VarExp(0, fd->vresult));
+	    sc->fes->cases.push(s);
+
+	    // Construct: { vresult = exp; return cases.dim + 1; }
+	    exp = new AssignExp(loc, new VarExp(0, fd->vresult), exp);
+	    exp = exp->semantic(sc);
+	    Statement *s1 = new ExpStatement(loc, exp);
+	    Statement *s2 = new ReturnStatement(0, new IntegerExp(sc->fes->cases.dim + 1));
+	    s = new CompoundStatement(loc, s1, s2);
+	}
+	return s;
+    }
+
+    if (exp)
+    {
+	if (fd->returnLabel && tbret->ty != Tvoid)
+	{
+	    assert(fd->vresult);
+	    VarExp *v = new VarExp(0, fd->vresult);
+
+	    exp = new AssignExp(loc, v, exp);
+	    exp = exp->semantic(sc);
+	}
+
+	if (((TypeFunction *)fd->type)->isref && !fd->isCtorDeclaration())
+	{   // Function returns a reference
+	    if (tbret->isMutable())
+		exp = exp->modifiableLvalue(sc, exp);
+	    else
+		exp = exp->toLvalue(sc, exp);
+
+	    if (exp->op == TOKvar)
+	    {	VarExp *ve = (VarExp *)exp;
+		VarDeclaration *v = ve->var->isVarDeclaration();
+		if (v && !v->isDataseg() && !(v->storage_class & (STCref | STCout)))
+		    error("escaping reference to local variable %s", v->toChars());
+	    }
+	}
+
+	//exp->dump(0);
+	//exp->print();
+	exp->checkEscape();
+    }
+
+    /* BUG: need to issue an error on:
+     *	this
+     *	{   if (x) return;
+     *	    super();
+     *	}
+     */
+
+    if (sc->callSuper & CSXany_ctor &&
+	!(sc->callSuper & (CSXthis_ctor | CSXsuper_ctor)))
+	error("return without calling constructor");
+
+    sc->callSuper |= CSXreturn;
+
+    // See if all returns are instead to be replaced with a goto returnLabel;
+    if (fd->returnLabel)
+    {
+	GotoStatement *gs = new GotoStatement(loc, Id::returnLabel);
+
+	gs->label = fd->returnLabel;
+	if (exp)
+	{   /* Replace: return exp;
+	     * with:    exp; goto returnLabel;
+	     */
+	    Statement *s = new ExpStatement(0, exp);
+	    return new CompoundStatement(loc, s, gs);
+	}
+	return gs;
+    }
+
+    if (exp && tbret->ty == Tvoid && !fd->isMain())
+    {
+	/* Replace:
+	 *	return exp;
+	 * with:
+	 *	exp; return;
+	 */
+	Statement *s = new ExpStatement(loc, exp);
+	loc = 0;
+	exp = NULL;
+	return new CompoundStatement(loc, s, this);
+    }
+
+    return this;
+}
+
+int ReturnStatement::blockExit()
+{   int result = BEreturn;
+
+    if (exp && exp->canThrow())
+	result |= BEthrow;
+    return result;
+}
+
+
+void ReturnStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    buf->printf("return ");
+    if (exp)
+	exp->toCBuffer(buf, hgs);
+    buf->writeByte(';');
+    buf->writenl();
+}
+
+/******************************** BreakStatement ***************************/
+
+BreakStatement::BreakStatement(Loc loc, Identifier *ident)
+    : Statement(loc)
+{
+    this->ident = ident;
+}
+
+Statement *BreakStatement::syntaxCopy()
+{
+    BreakStatement *s = new BreakStatement(loc, ident);
+    return s;
+}
+
+Statement *BreakStatement::semantic(Scope *sc)
+{
+    //printf("BreakStatement::semantic()\n");
+    // If:
+    //	break Identifier;
+    if (ident)
+    {
+	Scope *scx;
+	FuncDeclaration *thisfunc = sc->func;
+
+	for (scx = sc; scx; scx = scx->enclosing)
+	{
+	    LabelStatement *ls;
+
+	    if (scx->func != thisfunc)	// if in enclosing function
+	    {
+		if (sc->fes)		// if this is the body of a foreach
+		{
+		    /* Post this statement to the fes, and replace
+		     * it with a return value that caller will put into
+		     * a switch. Caller will figure out where the break
+		     * label actually is.
+		     * Case numbers start with 2, not 0, as 0 is continue
+		     * and 1 is break.
+		     */
+		    Statement *s;
+		    sc->fes->cases.push(this);
+		    s = new ReturnStatement(0, new IntegerExp(sc->fes->cases.dim + 1));
+		    return s;
+		}
+		break;			// can't break to it
+	    }
+
+	    ls = scx->slabel;
+	    if (ls && ls->ident == ident)
+	    {
+		Statement *s = ls->statement;
+
+		if (!s->hasBreak())
+		    error("label '%s' has no break", ident->toChars());
+		if (ls->enclosingFinally != sc->enclosingFinally)
+		    error("cannot break out of finally block");
+		
+		this->target = ls;
+		return this;
+	    }
+	}
+	error("enclosing label '%s' for break not found", ident->toChars());
+    }
+    else if (!sc->sbreak)
+    {
+	if (sc->fes)
+	{   Statement *s;
+
+	    // Replace break; with return 1;
+	    s = new ReturnStatement(0, new IntegerExp(1));
+	    return s;
+	}
+	error("break is not inside a loop or switch");
+    }
+    return this;
+}
+
+int BreakStatement::blockExit()
+{
+    //printf("BreakStatement::blockExit(%p) = x%x\n", this, ident ? BEgoto : BEbreak);
+    return ident ? BEgoto : BEbreak;
+}
+
+
+void BreakStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    buf->writestring("break");
+    if (ident)
+    {   buf->writebyte(' ');
+        buf->writestring(ident->toChars());
+    }
+    buf->writebyte(';');
+    buf->writenl();
+}
+
+/******************************** ContinueStatement ***************************/
+
+ContinueStatement::ContinueStatement(Loc loc, Identifier *ident)
+    : Statement(loc)
+{
+    this->ident = ident;
+}
+
+Statement *ContinueStatement::syntaxCopy()
+{
+    ContinueStatement *s = new ContinueStatement(loc, ident);
+    return s;
+}
+
+Statement *ContinueStatement::semantic(Scope *sc)
+{
+    //printf("ContinueStatement::semantic() %p\n", this);
+    if (ident)
+    {
+	Scope *scx;
+	FuncDeclaration *thisfunc = sc->func;
+
+	for (scx = sc; scx; scx = scx->enclosing)
+	{
+	    LabelStatement *ls;
+
+	    if (scx->func != thisfunc)	// if in enclosing function
+	    {
+		if (sc->fes)		// if this is the body of a foreach
+		{
+		    for (; scx; scx = scx->enclosing)
+		    {
+			ls = scx->slabel;
+			if (ls && ls->ident == ident && ls->statement == sc->fes)
+			{
+			    // Replace continue ident; with return 0;
+			    return new ReturnStatement(0, new IntegerExp(0));
+			}
+		    }
+
+		    /* Post this statement to the fes, and replace
+		     * it with a return value that caller will put into
+		     * a switch. Caller will figure out where the break
+		     * label actually is.
+		     * Case numbers start with 2, not 0, as 0 is continue
+		     * and 1 is break.
+		     */
+		    Statement *s;
+		    sc->fes->cases.push(this);
+		    s = new ReturnStatement(0, new IntegerExp(sc->fes->cases.dim + 1));
+		    return s;
+		}
+		break;			// can't continue to it
+	    }
+
+	    ls = scx->slabel;
+	    if (ls && ls->ident == ident)
+	    {
+		Statement *s = ls->statement;
+
+		if (!s->hasContinue())
+		    error("label '%s' has no continue", ident->toChars());
+		if (ls->enclosingFinally != sc->enclosingFinally)
+		    error("cannot continue out of finally block");
+		
+		this->target = ls;
+		return this;
+	    }
+	}
+	error("enclosing label '%s' for continue not found", ident->toChars());
+    }
+    else if (!sc->scontinue)
+    {
+	if (sc->fes)
+	{   Statement *s;
+
+	    // Replace continue; with return 0;
+	    s = new ReturnStatement(0, new IntegerExp(0));
+	    return s;
+	}
+	error("continue is not inside a loop");
+    }
+    return this;
+}
+
+int ContinueStatement::blockExit()
+{
+    return ident ? BEgoto : BEcontinue;
+}
+
+
+void ContinueStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    buf->writestring("continue");
+    if (ident)
+    {   buf->writebyte(' ');
+        buf->writestring(ident->toChars());
+    }
+    buf->writebyte(';');
+    buf->writenl();
+}
+
+/******************************** SynchronizedStatement ***************************/
+
+SynchronizedStatement::SynchronizedStatement(Loc loc, Expression *exp, Statement *body)
+    : Statement(loc)
+{
+    this->exp = exp;
+    this->body = body;
+    this->esync = NULL;
+    // LDC
+    this->llsync = NULL;
+}
+
+SynchronizedStatement::SynchronizedStatement(Loc loc, elem *esync, Statement *body)
+    : Statement(loc)
+{
+    this->exp = NULL;
+    this->body = body;
+    this->esync = esync;
+    // LDC
+    this->llsync = NULL;
+}
+
+Statement *SynchronizedStatement::syntaxCopy()
+{
+    Expression *e = exp ? exp->syntaxCopy() : NULL;
+    SynchronizedStatement *s = new SynchronizedStatement(loc, e, body ? body->syntaxCopy() : NULL);
+    return s;
+}
+
+Statement *SynchronizedStatement::semantic(Scope *sc)
+{
+    if (exp)
+    {	ClassDeclaration *cd;
+
+	exp = exp->semantic(sc);
+	exp = resolveProperties(sc, exp);
+	cd = exp->type->isClassHandle();
+	if (!cd)
+	    error("can only synchronize on class objects, not '%s'", exp->type->toChars());
+	else if (cd->isInterfaceDeclaration())
+	{   Type *t = new TypeIdentifier(0, Id::Object);
+
+	    t = t->semantic(0, sc);
+	    exp = new CastExp(loc, exp, t);
+	    exp = exp->semantic(sc);
+	}
+    }
+    if (body)
+    {
+	Statement* oldScopeExit = sc->enclosingScopeExit;
+	sc->enclosingScopeExit = this;
+	body = body->semantic(sc);
+	sc->enclosingScopeExit = oldScopeExit;
+    }
+    return this;
+}
+
+int SynchronizedStatement::hasBreak()
+{
+    return FALSE; //TRUE;
+}
+
+int SynchronizedStatement::hasContinue()
+{
+    return FALSE; //TRUE;
+}
+
+int SynchronizedStatement::usesEH()
+{
+    return TRUE;
+}
+
+int SynchronizedStatement::blockExit()
+{
+    return body ? body->blockExit() : BEfallthru;
+}
+
+
+void SynchronizedStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    buf->writestring("synchronized");
+    if (exp)
+    {   buf->writebyte('(');
+	exp->toCBuffer(buf, hgs);
+	buf->writebyte(')');
+    }
+    if (body)
+    {
+	buf->writebyte(' ');
+	body->toCBuffer(buf, hgs);
+    }
+}
+
+/******************************** WithStatement ***************************/
+
+WithStatement::WithStatement(Loc loc, Expression *exp, Statement *body)
+    : Statement(loc)
+{
+    this->exp = exp;
+    this->body = body;
+    wthis = NULL;
+}
+
+Statement *WithStatement::syntaxCopy()
+{
+    WithStatement *s = new WithStatement(loc, exp->syntaxCopy(), body ? body->syntaxCopy() : NULL);
+    return s;
+}
+
+Statement *WithStatement::semantic(Scope *sc)
+{   ScopeDsymbol *sym;
+    Initializer *init;
+
+    //printf("WithStatement::semantic()\n");
+    exp = exp->semantic(sc);
+    exp = resolveProperties(sc, exp);
+    if (exp->op == TOKimport)
+    {	ScopeExp *es = (ScopeExp *)exp;
+
+	sym = es->sds;
+    }
+    else if (exp->op == TOKtype)
+    {	TypeExp *es = (TypeExp *)exp;
+
+	sym = es->type->toDsymbol(sc)->isScopeDsymbol();
+	if (!sym)
+	{   error("%s has no members", es->toChars());
+	    body = body->semantic(sc);
+	    return this;
+	}
+    }
+    else
+    {	Type *t = exp->type;
+
+	assert(t);
+	t = t->toBasetype();
+	if (t->isClassHandle())
+	{
+	    init = new ExpInitializer(loc, exp);
+	    wthis = new VarDeclaration(loc, exp->type, Id::withSym, init);
+	    wthis->semantic(sc);
+
+	    sym = new WithScopeSymbol(this);
+	    sym->parent = sc->scopesym;
+	}
+	else if (t->ty == Tstruct)
+	{
+	    Expression *e = exp->addressOf(sc);
+	    init = new ExpInitializer(loc, e);
+	    wthis = new VarDeclaration(loc, e->type, Id::withSym, init);
+	    wthis->semantic(sc);
+	    sym = new WithScopeSymbol(this);
+	    sym->parent = sc->scopesym;
+	}
+	else
+	{   error("with expressions must be class objects, not '%s'", exp->type->toChars());
+	    return NULL;
+	}
+    }
+    sc = sc->push(sym);
+
+    if (body)
+	body = body->semantic(sc);
+
+    sc->pop();
+
+    return this;
+}
+
+void WithStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    buf->writestring("with (");
+    exp->toCBuffer(buf, hgs);
+    buf->writestring(")\n");
+    if (body)
+	body->toCBuffer(buf, hgs);
+}
+
+int WithStatement::usesEH()
+{
+    return body ? body->usesEH() : 0;
+}
+
+int WithStatement::blockExit()
+{
+    int result = BEnone;
+    if (exp->canThrow())
+	result = BEthrow;
+    if (body)
+	result |= body->blockExit();
+    else
+	result |= BEfallthru;
+    return result;
+}
+
+
+/******************************** TryCatchStatement ***************************/
+
+TryCatchStatement::TryCatchStatement(Loc loc, Statement *body, Array *catches)
+    : Statement(loc)
+{
+    this->body = body;
+    this->catches = catches;
+}
+
+Statement *TryCatchStatement::syntaxCopy()
+{
+    Array *a = new Array();
+    a->setDim(catches->dim);
+    for (int i = 0; i < a->dim; i++)
+    {   Catch *c;
+
+	c = (Catch *)catches->data[i];
+	c = c->syntaxCopy();
+	a->data[i] = c;
+    }
+    TryCatchStatement *s = new TryCatchStatement(loc, body->syntaxCopy(), a);
+    return s;
+}
+
+Statement *TryCatchStatement::semantic(Scope *sc)
+{
+    body = body->semanticScope(sc, NULL /*this*/, NULL);
+
+    /* Even if body is NULL, still do semantic analysis on catches
+     */
+    for (size_t i = 0; i < catches->dim; i++)
+    {   Catch *c = (Catch *)catches->data[i];
+	c->semantic(sc);
+
+	// Determine if current catch 'hides' any previous catches
+	for (size_t j = 0; j < i; j++)
+	{   Catch *cj = (Catch *)catches->data[j];
+	    char *si = c->loc.toChars();
+	    char *sj = cj->loc.toChars();
+
+	    if (c->type->toBasetype()->implicitConvTo(cj->type->toBasetype()))
+		error("catch at %s hides catch at %s", sj, si);
+	}
+    }
+
+    if (!body)
+	return NULL;
+
+    return this;
+}
+
+int TryCatchStatement::hasBreak()
+{
+    return FALSE; //TRUE;
+}
+
+int TryCatchStatement::usesEH()
+{
+    return TRUE;
+}
+
+int TryCatchStatement::blockExit()
+{
+    assert(body);
+    int result = body->blockExit();
+
+    int catchresult = 0;
+    for (size_t i = 0; i < catches->dim; i++)
+    {
+        Catch *c = (Catch *)catches->data[i];
+        catchresult |= c->blockExit();
+
+	/* If we're catching Object, then there is no throwing
+	 */
+	Identifier *id = c->type->toBasetype()->isClassHandle()->ident;
+	if (i == 0 &&
+	    (id == Id::Object || id == Id::Throwable || id == Id::Exception))
+	{
+	    result &= ~BEthrow;
+	}
+    }
+    return result | catchresult;
+}
+
+
+void TryCatchStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    buf->writestring("try");
+    buf->writenl();
+    if (body)
+        body->toCBuffer(buf, hgs);
+    for (size_t i = 0; i < catches->dim; i++)
+    {
+        Catch *c = (Catch *)catches->data[i];
+        c->toCBuffer(buf, hgs);
+    }
+}
+
+/******************************** Catch ***************************/
+
+Catch::Catch(Loc loc, Type *t, Identifier *id, Statement *handler)
+{
+    //printf("Catch(%s, loc = %s)\n", id->toChars(), loc.toChars());
+    this->loc = loc;
+    this->type = t;
+    this->ident = id;
+    this->handler = handler;
+    var = NULL;
+}
+
+Catch *Catch::syntaxCopy()
+{
+    Catch *c = new Catch(loc,
+	(type ? type->syntaxCopy() : NULL),
+	ident,
+	(handler ? handler->syntaxCopy() : NULL));
+    return c;
+}
+
+void Catch::semantic(Scope *sc)
+{   ScopeDsymbol *sym;
+
+    //printf("Catch::semantic(%s)\n", ident->toChars());
+
+#ifndef IN_GCC
+    if (sc->enclosingFinally)
+    {
+	/* This is because the _d_local_unwind() gets the stack munged
+	 * up on this. The workaround is to place any try-catches into
+	 * a separate function, and call that.
+	 * To fix, have the compiler automatically convert the finally
+	 * body into a nested function.
+	 */
+	error(loc, "cannot put catch statement inside finally block");
+    }
+#endif
+
+    sym = new ScopeDsymbol();
+    sym->parent = sc->scopesym;
+    sc = sc->push(sym);
+
+    if (!type)
+	type = new TypeIdentifier(0, Id::Object);
+    type = type->semantic(loc, sc);
+    if (!type->toBasetype()->isClassHandle())
+	error("can only catch class objects, not '%s'", type->toChars());
+    else if (ident)
+    {
+	var = new VarDeclaration(loc, type, ident, NULL);
+	var->parent = sc->parent;
+	sc->insert(var);
+    }
+    handler = handler->semantic(sc);
+
+    sc->pop();
+}
+
+int Catch::blockExit()
+{
+    return handler ? handler->blockExit() : BEfallthru;
+}
+
+void Catch::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    buf->writestring("catch");
+    if (type)
+    {   buf->writebyte('(');
+	type->toCBuffer(buf, ident, hgs);
+        buf->writebyte(')');
+    }
+    buf->writenl();
+    buf->writebyte('{');
+    buf->writenl();
+    if (handler)
+	handler->toCBuffer(buf, hgs);
+    buf->writebyte('}');
+    buf->writenl();
+}
+
+/****************************** TryFinallyStatement ***************************/
+
+TryFinallyStatement::TryFinallyStatement(Loc loc, Statement *body, Statement *finalbody)
+    : Statement(loc)
+{
+    this->body = body;
+    this->finalbody = finalbody;
+}
+
+Statement *TryFinallyStatement::syntaxCopy()
+{
+    TryFinallyStatement *s = new TryFinallyStatement(loc,
+	body->syntaxCopy(), finalbody->syntaxCopy());
+    return s;
+}
+
+Statement *TryFinallyStatement::semantic(Scope *sc)
+{
+    //printf("TryFinallyStatement::semantic()\n");
+
+    Statement* oldScopeExit = sc->enclosingScopeExit;
+    sc->enclosingScopeExit = this;
+    body = body->semantic(sc);
+    sc->enclosingScopeExit = oldScopeExit;
+
+    sc = sc->push();
+    sc->enclosingFinally = this;
+    sc->sbreak = NULL;
+    sc->scontinue = NULL;	// no break or continue out of finally block
+    finalbody = finalbody->semantic(sc);
+    sc->pop();
+    if (!body)
+	return finalbody;
+    if (!finalbody)
+	return body;
+    if (body->blockExit() == BEfallthru)
+    {	Statement *s = new CompoundStatement(loc, body, finalbody);
+	return s;
+    }
+    return this;
+}
+
+void TryFinallyStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    buf->printf("try\n{\n");
+    body->toCBuffer(buf, hgs);
+    buf->printf("}\nfinally\n{\n");
+    finalbody->toCBuffer(buf, hgs);
+    buf->writeByte('}');
+    buf->writenl();
+}
+
+int TryFinallyStatement::hasBreak()
+{
+    return FALSE; //TRUE;
+}
+
+int TryFinallyStatement::hasContinue()
+{
+    return FALSE; //TRUE;
+}
+
+int TryFinallyStatement::usesEH()
+{
+    return TRUE;
+}
+
+int TryFinallyStatement::blockExit()
+{
+    if (body)
+	return body->blockExit();
+    return BEfallthru;
+}
+
+
+/****************************** OnScopeStatement ***************************/
+
+OnScopeStatement::OnScopeStatement(Loc loc, TOK tok, Statement *statement)
+    : Statement(loc)
+{
+    this->tok = tok;
+    this->statement = statement;
+}
+
+Statement *OnScopeStatement::syntaxCopy()
+{
+    OnScopeStatement *s = new OnScopeStatement(loc,
+	tok, statement->syntaxCopy());
+    return s;
+}
+
+Statement *OnScopeStatement::semantic(Scope *sc)
+{
+    /* semantic is called on results of scopeCode() */
+    return this;
+}
+
+int OnScopeStatement::blockExit()
+{   // At this point, this statement is just an empty placeholder
+    return BEfallthru;
+}
+
+void OnScopeStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    buf->writestring(Token::toChars(tok));
+    buf->writebyte(' ');
+    statement->toCBuffer(buf, hgs);
+}
+
+int OnScopeStatement::usesEH()
+{
+    return 1;
+}
+
+void OnScopeStatement::scopeCode(Scope *sc, Statement **sentry, Statement **sexception, Statement **sfinally)
+{
+    //printf("OnScopeStatement::scopeCode()\n");
+    //print();
+    *sentry = NULL;
+    *sexception = NULL;
+    *sfinally = NULL;
+    switch (tok)
+    {
+	case TOKon_scope_exit:
+	    *sfinally = statement;
+	    break;
+
+	case TOKon_scope_failure:
+	    *sexception = statement;
+	    break;
+
+	case TOKon_scope_success:
+	{
+	    /* Create:
+	     *	sentry:   int x = 0;
+	     *	sexception:    x = 1;
+	     *	sfinally: if (!x) statement;
+	     */
+	    Identifier *id = Lexer::uniqueId("__os");
+
+	    ExpInitializer *ie = new ExpInitializer(loc, new IntegerExp(0));
+	    VarDeclaration *v = new VarDeclaration(loc, Type::tint32, id, ie);
+	    *sentry = new DeclarationStatement(loc, v);
+
+	    Expression *e = new IntegerExp(1);
+	    e = new AssignExp(0, new VarExp(0, v), e);
+	    *sexception = new ExpStatement(0, e);
+
+	    e = new VarExp(0, v);
+	    e = new NotExp(0, e);
+	    *sfinally = new IfStatement(0, NULL, e, statement, NULL);
+
+	    break;
+	}
+
+	default:
+	    assert(0);
+    }
+}
+
+/******************************** ThrowStatement ***************************/
+
+ThrowStatement::ThrowStatement(Loc loc, Expression *exp)
+    : Statement(loc)
+{
+    this->exp = exp;
+}
+
+Statement *ThrowStatement::syntaxCopy()
+{
+    ThrowStatement *s = new ThrowStatement(loc, exp->syntaxCopy());
+    return s;
+}
+
+Statement *ThrowStatement::semantic(Scope *sc)
+{
+    //printf("ThrowStatement::semantic()\n");
+
+    FuncDeclaration *fd = sc->parent->isFuncDeclaration();
+    fd->hasReturnExp |= 2;
+
+    if (sc->incontract)
+	error("Throw statements cannot be in contracts");
+    exp = exp->semantic(sc);
+    exp = resolveProperties(sc, exp);
+    if (!exp->type->toBasetype()->isClassHandle())
+	error("can only throw class objects, not type %s", exp->type->toChars());
+    return this;
+}
+
+int ThrowStatement::blockExit()
+{
+    return BEthrow;  // obviously
+}
+
+
+void ThrowStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    buf->printf("throw ");
+    exp->toCBuffer(buf, hgs);
+    buf->writeByte(';');
+    buf->writenl();
+}
+
+/******************************** VolatileStatement **************************/
+
+VolatileStatement::VolatileStatement(Loc loc, Statement *statement)
+    : Statement(loc)
+{
+    this->statement = statement;
+}
+
+Statement *VolatileStatement::syntaxCopy()
+{
+    VolatileStatement *s = new VolatileStatement(loc,
+		statement ? statement->syntaxCopy() : NULL);
+    return s;
+}
+
+Statement *VolatileStatement::semantic(Scope *sc)
+{
+    if (statement)
+    {
+	Statement* oldScopeExit = sc->enclosingScopeExit;
+	sc->enclosingScopeExit = this;
+	statement = statement->semantic(sc);
+	sc->enclosingScopeExit = oldScopeExit;
+    }
+    return this;
+}
+
+Statements *VolatileStatement::flatten(Scope *sc)
+{
+    Statements *a;
+
+    a = statement ? statement->flatten(sc) : NULL;
+    if (a)
+    {	for (int i = 0; i < a->dim; i++)
+	{   Statement *s = (Statement *)a->data[i];
+
+	    s = new VolatileStatement(loc, s);
+	    a->data[i] = s;
+	}
+    }
+
+    return a;
+}
+
+int VolatileStatement::blockExit()
+{
+    return statement ? statement->blockExit() : BEfallthru;
+}
+
+
+void VolatileStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    buf->writestring("volatile");
+    if (statement)
+    {   if (statement->isScopeStatement())
+            buf->writenl();
+        else
+            buf->writebyte(' ');
+        statement->toCBuffer(buf, hgs);
+    }
+}
+
+
+/******************************** GotoStatement ***************************/
+
+GotoStatement::GotoStatement(Loc loc, Identifier *ident)
+    : Statement(loc)
+{
+    this->ident = ident;
+    this->label = NULL;
+    this->enclosingFinally = NULL;
+    this->enclosingScopeExit = NULL;
+}
+
+Statement *GotoStatement::syntaxCopy()
+{
+    GotoStatement *s = new GotoStatement(loc, ident);
+    return s;
+}
+
+Statement *GotoStatement::semantic(Scope *sc)
+{   FuncDeclaration *fd = sc->parent->isFuncDeclaration();
+
+    //printf("GotoStatement::semantic()\n");
+    enclosingFinally = sc->enclosingFinally;
+    enclosingScopeExit = sc->enclosingScopeExit;
+
+    label = fd->searchLabel(ident);
+    if (!label->statement && sc->fes)
+    {
+	/* Either the goto label is forward referenced or it
+	 * is in the function that the enclosing foreach is in.
+	 * Can't know yet, so wrap the goto in a compound statement
+	 * so we can patch it later, and add it to a 'look at this later'
+	 * list.
+	 */
+	Statements *a = new Statements();
+	Statement *s;
+
+	a->push(this);
+	s = new CompoundStatement(loc, a);
+	sc->fes->gotos.push(s);		// 'look at this later' list
+	return s;
+    }
+    if (label->statement && label->statement->enclosingFinally != sc->enclosingFinally)
+	error("cannot goto in or out of finally block");
+    return this;
+}
+
+int GotoStatement::blockExit()
+{
+    //printf("GotoStatement::blockExit(%p)\n", this);
+    return BEgoto;
+}
+
+
+void GotoStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    buf->writestring("goto ");
+    buf->writestring(ident->toChars());
+    buf->writebyte(';');
+    buf->writenl();
+}
+
+/******************************** LabelStatement ***************************/
+
+LabelStatement::LabelStatement(Loc loc, Identifier *ident, Statement *statement)
+    : Statement(loc)
+{
+    this->ident = ident;
+    this->statement = statement;
+    this->enclosingFinally = NULL;
+    this->enclosingScopeExit = NULL;
+    this->lblock = NULL;
+    this->isReturnLabel = 0;
+    this->asmLabel = false;
+}
+
+Statement *LabelStatement::syntaxCopy()
+{
+    LabelStatement *s = new LabelStatement(loc, ident, statement->syntaxCopy());
+    return s;
+}
+
+Statement *LabelStatement::semantic(Scope *sc)
+{   LabelDsymbol *ls;
+    FuncDeclaration *fd = sc->parent->isFuncDeclaration();
+
+    //printf("LabelStatement::semantic()\n");
+    ls = fd->searchLabel(ident);
+    if (ls->statement)
+	error("Label '%s' already defined", ls->toChars());
+    else
+	ls->statement = this;
+
+    enclosingFinally = sc->enclosingFinally;
+    enclosingScopeExit = sc->enclosingScopeExit;
+
+    sc = sc->push();
+    sc->scopesym = sc->enclosing->scopesym;
+    sc->callSuper |= CSXlabel;
+    sc->slabel = this;
+    if (statement)
+	statement = statement->semantic(sc);
+    sc->pop();
+
+    // LDC put in labmap
+    fd->labmap[ident->toChars()] = this;
+
+    return this;
+}
+
+Statements *LabelStatement::flatten(Scope *sc)
+{
+    Statements *a = NULL;
+
+    if (statement)
+    {
+	a = statement->flatten(sc);
+	if (a)
+	{
+	    if (!a->dim)
+	    {
+		a->push(new ExpStatement(loc, NULL));
+	    }
+	    Statement *s = (Statement *)a->data[0];
+
+	    s = new LabelStatement(loc, ident, s);
+	    a->data[0] = s;
+	}
+    }
+
+    return a;
+}
+
+
+int LabelStatement::usesEH()
+{
+    return statement ? statement->usesEH() : FALSE;
+}
+
+int LabelStatement::blockExit()
+{
+    //printf("LabelStatement::blockExit(%p)\n", this);
+    return statement ? statement->blockExit() : BEfallthru;
+}
+
+
+int LabelStatement::comeFrom()
+{
+    //printf("LabelStatement::comeFrom()\n");
+    return TRUE;
+}
+
+void LabelStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    buf->writestring(ident->toChars());
+    buf->writebyte(':');
+    buf->writenl();
+    if (statement)
+        statement->toCBuffer(buf, hgs);
+}
+
+
+/******************************** LabelDsymbol ***************************/
+
+LabelDsymbol::LabelDsymbol(Identifier *ident)
+	: Dsymbol(ident)
+{
+    statement = NULL;
+#if IN_GCC
+    asmLabelNum = 0;
+#endif
+}
+
+LabelDsymbol *LabelDsymbol::isLabel()		// is this a LabelDsymbol()?
+{
+    return this;
+}
--- a/dmd2/statement.h	Mon Jun 01 01:28:18 2009 +0200
+++ b/dmd2/statement.h	Mon Jun 01 19:02:20 2009 +0100
@@ -1,951 +1,903 @@
-
-// Compiler implementation of the D programming language
-// Copyright (c) 1999-2008 by Digital Mars
-// All Rights Reserved
-// written by Walter Bright
-// http://www.digitalmars.com
-// License for redistribution is by either the Artistic License
-// in artistic.txt, or the GNU General Public License in gnu.txt.
-// See the included readme.txt for details.
-
-#ifndef DMD_STATEMENT_H
-#define DMD_STATEMENT_H
-
-#ifdef __DMC__
-#pragma once
-#endif /* __DMC__ */
-
-#include "root.h"
-
-#include "arraytypes.h"
-#include "dsymbol.h"
-#include "lexer.h"
-
-struct OutBuffer;
-struct Scope;
-struct Expression;
-struct LabelDsymbol;
-struct Identifier;
-struct IfStatement;
-struct DeclarationStatement;
-struct DefaultStatement;
-struct VarDeclaration;
-struct Condition;
-struct Module;
-struct Token;
-struct InlineCostState;
-struct InlineDoState;
-struct InlineScanState;
-struct ReturnStatement;
-struct CompoundStatement;
-struct Argument;
-struct StaticAssert;
-struct AsmStatement;
-struct AsmBlockStatement;
-struct GotoStatement;
-struct ScopeStatement;
-struct TryCatchStatement;
-struct TryFinallyStatement;
-struct HdrGenState;
-struct InterState;
-struct CaseStatement;
-struct LabelStatement;
-struct VolatileStatement;
-struct SynchronizedStatement;
-
-enum TOK;
-
-namespace llvm
-{
-    class Value;
-    class BasicBlock;
-    class ConstantInt;
-}
-
-// Back end
-struct IRState;
-struct Blockx;
-#if IN_LLVM
-struct DValue;
-typedef DValue elem;
-#endif
-
-#if IN_GCC
-union tree_node; typedef union tree_node block;
-//union tree_node; typedef union tree_node elem;
-#else
-struct block;
-//struct elem;
-#endif
-struct code;
-
-/* How a statement exits
- */
-enum BE
-{
-    BEnone =	 0,
-    BEfallthru = 1,
-    BEthrow =    2,
-    BEreturn =   4,
-    BEgoto =     8,
-    BEhalt =	 0x10,
-    BEbreak =	 0x20,
-    BEcontinue = 0x40,
-    BEany = (BEfallthru | BEthrow | BEreturn | BEgoto | BEhalt),
-};
-
-// LDC this is used for tracking try-finally, synchronized and volatile scopes
-// definitions in gen/llvmhelpers.cpp
-struct EnclosingHandler : Object
-{
-    virtual void emitCode(IRState* p) = 0;
-    virtual EnclosingHandler* getEnclosing() = 0;
-};
-struct EnclosingTryFinally : EnclosingHandler
-{
-    TryFinallyStatement* tf;
-    void emitCode(IRState* p);
-    EnclosingHandler* getEnclosing();
-    EnclosingTryFinally(TryFinallyStatement* _tf) : tf(_tf) {}
-};
-struct EnclosingVolatile : EnclosingHandler
-{
-    VolatileStatement* v;
-    void emitCode(IRState* p);
-    EnclosingHandler* getEnclosing();
-    EnclosingVolatile(VolatileStatement* _tf) : v(_tf) {}
-};
-struct EnclosingSynchro : EnclosingHandler
-{
-    SynchronizedStatement* s;
-    void emitCode(IRState* p);
-    EnclosingHandler* getEnclosing();
-    EnclosingSynchro(SynchronizedStatement* _tf) : s(_tf) {}
-};
-
-struct Statement : Object
-{
-    Loc loc;
-
-    Statement(Loc loc);
-    virtual Statement *syntaxCopy();
-
-    void print();
-    char *toChars();
-
-    void error(const char *format, ...);
-    virtual void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-    virtual TryCatchStatement *isTryCatchStatement() { return NULL; }
-    virtual GotoStatement *isGotoStatement() { return NULL; }
-    virtual AsmStatement *isAsmStatement() { return NULL; }
-    virtual AsmBlockStatement *isAsmBlockStatement() { return NULL; }
-#ifdef _DH
-    int incontract;
-#endif
-    virtual ScopeStatement *isScopeStatement() { return NULL; }
-    virtual Statement *semantic(Scope *sc);
-    Statement *semanticScope(Scope *sc, Statement *sbreak, Statement *scontinue);
-    virtual int hasBreak();
-    virtual int hasContinue();
-    virtual int usesEH();
-    virtual int fallOffEnd();
-    virtual int blockExit();
-    virtual int comeFrom();
-    virtual void scopeCode(Scope *sc, Statement **sentry, Statement **sexit, Statement **sfinally);
-    virtual Statements *flatten(Scope *sc);
-    virtual Expression *interpret(InterState *istate);
-
-    virtual int inlineCost(InlineCostState *ics);
-    virtual Expression *doInline(InlineDoState *ids);
-    virtual Statement *inlineScan(InlineScanState *iss);
-
-    // Back end
-    virtual void toIR(IRState *irs);
-
-    // Avoid dynamic_cast
-    virtual DeclarationStatement *isDeclarationStatement() { return NULL; }
-    virtual CompoundStatement *isCompoundStatement() { return NULL; }
-    virtual ReturnStatement *isReturnStatement() { return NULL; }
-    virtual IfStatement *isIfStatement() { return NULL; }
-    virtual CaseStatement* isCaseStatement() { return NULL; }
-
-    // LDC
-    virtual void toNakedIR(IRState *irs);
-    virtual AsmBlockStatement* endsWithAsm();
-};
-
-struct ExpStatement : Statement
-{
-    Expression *exp;
-
-    ExpStatement(Loc loc, Expression *exp);
-    Statement *syntaxCopy();
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-    Statement *semantic(Scope *sc);
-    Expression *interpret(InterState *istate);
-    int fallOffEnd();
-    int blockExit();
-
-    int inlineCost(InlineCostState *ics);
-    Expression *doInline(InlineDoState *ids);
-    Statement *inlineScan(InlineScanState *iss);
-
-    void toIR(IRState *irs);
-
-    // LDC
-    virtual void toNakedIR(IRState *irs);
-};
-
-struct CompileStatement : Statement
-{
-    Expression *exp;
-
-    CompileStatement(Loc loc, Expression *exp);
-    Statement *syntaxCopy();
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-    Statements *flatten(Scope *sc);
-    Statement *semantic(Scope *sc);
-};
-
-struct DeclarationStatement : ExpStatement
-{
-    // Doing declarations as an expression, rather than a statement,
-    // makes inlining functions much easier.
-
-    DeclarationStatement(Loc loc, Dsymbol *s);
-    DeclarationStatement(Loc loc, Expression *exp);
-    Statement *syntaxCopy();
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-    void scopeCode(Scope *sc, Statement **sentry, Statement **sexit, Statement **sfinally);
-
-    DeclarationStatement *isDeclarationStatement() { return this; }
-};
-
-struct CompoundStatement : Statement
-{
-    Statements *statements;
-
-    CompoundStatement(Loc loc, Statements *s);
-    CompoundStatement(Loc loc, Statement *s1, Statement *s2);
-    virtual Statement *syntaxCopy();
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-    virtual Statement *semantic(Scope *sc);
-    int usesEH();
-    int blockExit();
-    int fallOffEnd();
-    int comeFrom();
-    virtual Statements *flatten(Scope *sc);
-    ReturnStatement *isReturnStatement();
-    Expression *interpret(InterState *istate);
-
-    int inlineCost(InlineCostState *ics);
-    Expression *doInline(InlineDoState *ids);
-    Statement *inlineScan(InlineScanState *iss);
-
-    virtual void toIR(IRState *irs);
-
-    // LDC
-    virtual void toNakedIR(IRState *irs);
-    virtual AsmBlockStatement* endsWithAsm();
-
-    virtual CompoundStatement *isCompoundStatement() { return this; }
-};
-
-/* The purpose of this is so that continue will go to the next
- * of the statements, and break will go to the end of the statements.
- */
-struct UnrolledLoopStatement : Statement
-{
-    Statements *statements;
-    EnclosingHandler* enclosinghandler;
-
-    UnrolledLoopStatement(Loc loc, Statements *statements);
-    Statement *syntaxCopy();
-    Statement *semantic(Scope *sc);
-    int hasBreak();
-    int hasContinue();
-    int usesEH();
-    int blockExit();
-    int fallOffEnd();
-    int comeFrom();
-    Expression *interpret(InterState *istate);
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-
-    int inlineCost(InlineCostState *ics);
-    Expression *doInline(InlineDoState *ids);
-    Statement *inlineScan(InlineScanState *iss);
-
-    void toIR(IRState *irs);
-};
-
-struct ScopeStatement : Statement
-{
-    Statement *statement;
-
-    ScopeStatement(Loc loc, Statement *s);
-    Statement *syntaxCopy();
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-    ScopeStatement *isScopeStatement() { return this; }
-    Statement *semantic(Scope *sc);
-    int hasBreak();
-    int hasContinue();
-    int usesEH();
-    int blockExit();
-    int fallOffEnd();
-    int comeFrom();
-    Expression *interpret(InterState *istate);
-
-    Statement *inlineScan(InlineScanState *iss);
-
-    void toIR(IRState *irs);
-};
-
-struct WhileStatement : Statement
-{
-    Expression *condition;
-    Statement *body;
-    EnclosingHandler* enclosinghandler;
-
-    WhileStatement(Loc loc, Expression *c, Statement *b);
-    Statement *syntaxCopy();
-    Statement *semantic(Scope *sc);
-    int hasBreak();
-    int hasContinue();
-    int usesEH();
-    int blockExit();
-    int fallOffEnd();
-    int comeFrom();
-    Expression *interpret(InterState *istate);
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-
-    Statement *inlineScan(InlineScanState *iss);
-
-    void toIR(IRState *irs);
-};
-
-struct DoStatement : Statement
-{
-    Statement *body;
-    Expression *condition;
-    EnclosingHandler* enclosinghandler;
-
-    DoStatement(Loc loc, Statement *b, Expression *c);
-    Statement *syntaxCopy();
-    Statement *semantic(Scope *sc);
-    int hasBreak();
-    int hasContinue();
-    int usesEH();
-    int blockExit();
-    int fallOffEnd();
-    int comeFrom();
-    Expression *interpret(InterState *istate);
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-
-    Statement *inlineScan(InlineScanState *iss);
-
-    void toIR(IRState *irs);
-};
-
-struct ForStatement : Statement
-{
-    Statement *init;
-    Expression *condition;
-    Expression *increment;
-    Statement *body;
-    EnclosingHandler* enclosinghandler;
-
-    ForStatement(Loc loc, Statement *init, Expression *condition, Expression *increment, Statement *body);
-    Statement *syntaxCopy();
-    Statement *semantic(Scope *sc);
-    void scopeCode(Scope *sc, Statement **sentry, Statement **sexit, Statement **sfinally);
-    int hasBreak();
-    int hasContinue();
-    int usesEH();
-    int blockExit();
-    int fallOffEnd();
-    int comeFrom();
-    Expression *interpret(InterState *istate);
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-
-    Statement *inlineScan(InlineScanState *iss);
-
-    void toIR(IRState *irs);
-};
-
-struct ForeachStatement : Statement
-{
-    enum TOK op;		// TOKforeach or TOKforeach_reverse
-    Arguments *arguments;	// array of Argument*'s
-    Expression *aggr;
-    Statement *body;
-    EnclosingHandler* enclosinghandler;
-
-    VarDeclaration *key;
-    VarDeclaration *value;
-
-    FuncDeclaration *func;	// function we're lexically in
-
-    Array cases;	// put breaks, continues, gotos and returns here
-    Array gotos;	// forward referenced goto's go here
-
-    ForeachStatement(Loc loc, enum TOK op, Arguments *arguments, Expression *aggr, Statement *body);
-    Statement *syntaxCopy();
-    Statement *semantic(Scope *sc);
-    bool checkForArgTypes();
-    int hasBreak();
-    int hasContinue();
-    int usesEH();
-    int blockExit();
-    int fallOffEnd();
-    int comeFrom();
-    Expression *interpret(InterState *istate);
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-
-    Statement *inlineScan(InlineScanState *iss);
-
-    void toIR(IRState *irs);
-};
-
-#if DMDV2
-struct ForeachRangeStatement : Statement
-{
-    enum TOK op;		// TOKforeach or TOKforeach_reverse
-    Argument *arg;		// loop index variable
-    Expression *lwr;
-    Expression *upr;
-    Statement *body;
-    EnclosingHandler* enclosinghandler;
-
-    VarDeclaration *key;
-
-    ForeachRangeStatement(Loc loc, enum TOK op, Argument *arg,
-	Expression *lwr, Expression *upr, Statement *body);
-    Statement *syntaxCopy();
-    Statement *semantic(Scope *sc);
-    int hasBreak();
-    int hasContinue();
-    int usesEH();
-    int blockExit();
-    int fallOffEnd();
-    int comeFrom();
-    Expression *interpret(InterState *istate);
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-
-    Statement *inlineScan(InlineScanState *iss);
-
-    void toIR(IRState *irs);
-};
-#endif
-
-struct IfStatement : Statement
-{
-    Argument *arg;
-    Expression *condition;
-    Statement *ifbody;
-    Statement *elsebody;
-
-    VarDeclaration *match;	// for MatchExpression results
-
-    IfStatement(Loc loc, Argument *arg, Expression *condition, Statement *ifbody, Statement *elsebody);
-    Statement *syntaxCopy();
-    Statement *semantic(Scope *sc);
-    Expression *interpret(InterState *istate);
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-    int usesEH();
-    int blockExit();
-    int fallOffEnd();
-    IfStatement *isIfStatement() { return this; }
-
-    int inlineCost(InlineCostState *ics);
-    Expression *doInline(InlineDoState *ids);
-    Statement *inlineScan(InlineScanState *iss);
-
-    void toIR(IRState *irs);
-};
-
-struct ConditionalStatement : Statement
-{
-    Condition *condition;
-    Statement *ifbody;
-    Statement *elsebody;
-
-    ConditionalStatement(Loc loc, Condition *condition, Statement *ifbody, Statement *elsebody);
-    Statement *syntaxCopy();
-    Statement *semantic(Scope *sc);
-    Statements *flatten(Scope *sc);
-    int usesEH();
-    int blockExit();
-
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-};
-
-struct PragmaStatement : Statement
-{
-    Identifier *ident;
-    Expressions *args;		// array of Expression's
-    Statement *body;
-
-    PragmaStatement(Loc loc, Identifier *ident, Expressions *args, Statement *body);
-    Statement *syntaxCopy();
-    Statement *semantic(Scope *sc);
-    int usesEH();
-    int blockExit();
-    int fallOffEnd();
-
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-
-    void toIR(IRState *irs);
-};
-
-struct StaticAssertStatement : Statement
-{
-    StaticAssert *sa;
-
-    StaticAssertStatement(StaticAssert *sa);
-    Statement *syntaxCopy();
-    Statement *semantic(Scope *sc);
-
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-};
-
-struct SwitchStatement : Statement
-{
-    Expression *condition;
-    Statement *body;
-
-    DefaultStatement *sdefault;
-    TryFinallyStatement *tf;
-    EnclosingHandler* enclosinghandler;
-
-    Array gotoCases;		// array of unresolved GotoCaseStatement's
-    Array *cases;		// array of CaseStatement's
-    int hasNoDefault;		// !=0 if no default statement
-    int hasVars;		// !=0 if has variable case values
-
-    SwitchStatement(Loc loc, Expression *c, Statement *b);
-    Statement *syntaxCopy();
-    Statement *semantic(Scope *sc);
-    int hasBreak();
-    int usesEH();
-    int blockExit();
-    int fallOffEnd();
-    Expression *interpret(InterState *istate);
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-
-    Statement *inlineScan(InlineScanState *iss);
-
-    void toIR(IRState *irs);
-};
-
-struct CaseStatement : Statement
-{
-    Expression *exp;
-    Statement *statement;
-    int index;		// which case it is (since we sort this)
-    block *cblock;	// back end: label for the block
-
-    CaseStatement(Loc loc, Expression *exp, Statement *s);
-    Statement *syntaxCopy();
-    Statement *semantic(Scope *sc);
-    int compare(Object *obj);
-    int usesEH();
-    int blockExit();
-    int fallOffEnd();
-    int comeFrom();
-    Expression *interpret(InterState *istate);
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-
-    Statement *inlineScan(InlineScanState *iss);
-
-    void toIR(IRState *irs);
-
-    CaseStatement* isCaseStatement() { return this; }
-
-    // LDC
-    llvm::BasicBlock* bodyBB;
-    llvm::ConstantInt* llvmIdx;
-};
-
-struct DefaultStatement : Statement
-{
-    Statement *statement;
-#if IN_GCC
-    block *cblock;	// back end: label for the block
-#endif
-
-    DefaultStatement(Loc loc, Statement *s);
-    Statement *syntaxCopy();
-    Statement *semantic(Scope *sc);
-    int usesEH();
-    int blockExit();
-    int fallOffEnd();
-    int comeFrom();
-    Expression *interpret(InterState *istate);
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-
-    Statement *inlineScan(InlineScanState *iss);
-
-    void toIR(IRState *irs);
-
-    // LDC
-    llvm::BasicBlock* bodyBB;
-};
-
-struct GotoDefaultStatement : Statement
-{
-    SwitchStatement *sw;
-    EnclosingHandler* enclosinghandler;
-
-    GotoDefaultStatement(Loc loc);
-    Statement *syntaxCopy();
-    Statement *semantic(Scope *sc);
-    Expression *interpret(InterState *istate);
-    int blockExit();
-    int fallOffEnd();
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-
-    void toIR(IRState *irs);
-};
-
-struct GotoCaseStatement : Statement
-{
-    Expression *exp;		// NULL, or which case to goto
-    CaseStatement *cs;		// case statement it resolves to
-    EnclosingHandler* enclosinghandler;
-    SwitchStatement *sw;
-
-    GotoCaseStatement(Loc loc, Expression *exp);
-    Statement *syntaxCopy();
-    Statement *semantic(Scope *sc);
-    Expression *interpret(InterState *istate);
-    int blockExit();
-    int fallOffEnd();
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-
-    void toIR(IRState *irs);
-};
-
-struct SwitchErrorStatement : Statement
-{
-    SwitchErrorStatement(Loc loc);
-    int blockExit();
-    int fallOffEnd();
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-
-    void toIR(IRState *irs);
-};
-
-struct ReturnStatement : Statement
-{
-    Expression *exp;
-    EnclosingHandler* enclosinghandler;
-
-    ReturnStatement(Loc loc, Expression *exp);
-    Statement *syntaxCopy();
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-    Statement *semantic(Scope *sc);
-    int blockExit();
-    int fallOffEnd();
-    Expression *interpret(InterState *istate);
-
-    int inlineCost(InlineCostState *ics);
-    Expression *doInline(InlineDoState *ids);
-    Statement *inlineScan(InlineScanState *iss);
-
-    void toIR(IRState *irs);
-
-    ReturnStatement *isReturnStatement() { return this; }
-};
-
-struct BreakStatement : Statement
-{
-    Identifier *ident;
-    EnclosingHandler* enclosinghandler;
-
-    BreakStatement(Loc loc, Identifier *ident);
-    Statement *syntaxCopy();
-    Statement *semantic(Scope *sc);
-    Expression *interpret(InterState *istate);
-    int blockExit();
-    int fallOffEnd();
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-
-    void toIR(IRState *irs);
-
-    // LDC: only set if ident is set: label statement to jump to
-    LabelStatement *target;
-};
-
-struct ContinueStatement : Statement
-{
-    Identifier *ident;
-    EnclosingHandler* enclosinghandler;
-
-    ContinueStatement(Loc loc, Identifier *ident);
-    Statement *syntaxCopy();
-    Statement *semantic(Scope *sc);
-    Expression *interpret(InterState *istate);
-    int blockExit();
-    int fallOffEnd();
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-
-    void toIR(IRState *irs);
-
-    // LDC: only set if ident is set: label statement to jump to
-    LabelStatement *target;
-};
-
-struct SynchronizedStatement : Statement
-{
-    Expression *exp;
-    Statement *body;
-    EnclosingHandler* enclosinghandler;
-
-    SynchronizedStatement(Loc loc, Expression *exp, Statement *body);
-    Statement *syntaxCopy();
-    Statement *semantic(Scope *sc);
-    int hasBreak();
-    int hasContinue();
-    int usesEH();
-    int blockExit();
-    int fallOffEnd();
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-
-    Statement *inlineScan(InlineScanState *iss);
-
-// Back end
-    elem *esync;
-    SynchronizedStatement(Loc loc, elem *esync, Statement *body);
-    void toIR(IRState *irs);
-    llvm::Value* llsync;
-};
-
-struct WithStatement : Statement
-{
-    Expression *exp;
-    Statement *body;
-    VarDeclaration *wthis;
-
-    WithStatement(Loc loc, Expression *exp, Statement *body);
-    Statement *syntaxCopy();
-    Statement *semantic(Scope *sc);
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-    int usesEH();
-    int blockExit();
-    int fallOffEnd();
-
-    Statement *inlineScan(InlineScanState *iss);
-
-    void toIR(IRState *irs);
-};
-
-struct TryCatchStatement : Statement
-{
-    Statement *body;
-    Array *catches;
-
-    TryCatchStatement(Loc loc, Statement *body, Array *catches);
-    Statement *syntaxCopy();
-    Statement *semantic(Scope *sc);
-    int hasBreak();
-    int usesEH();
-    int blockExit();
-    int fallOffEnd();
-
-    Statement *inlineScan(InlineScanState *iss);
-
-    void toIR(IRState *irs);
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-    TryCatchStatement *isTryCatchStatement() { return this; }
-};
-
-struct Catch : Object
-{
-    Loc loc;
-    Type *type;
-    Identifier *ident;
-    VarDeclaration *var;
-    Statement *handler;
-
-    Catch(Loc loc, Type *t, Identifier *id, Statement *handler);
-    Catch *syntaxCopy();
-    void semantic(Scope *sc);
-    int blockExit();
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-};
-
-struct TryFinallyStatement : Statement
-{
-    Statement *body;
-    Statement *finalbody;
-    EnclosingHandler* enclosinghandler;
-
-    TryFinallyStatement(Loc loc, Statement *body, Statement *finalbody);
-    Statement *syntaxCopy();
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-    Statement *semantic(Scope *sc);
-    int hasBreak();
-    int hasContinue();
-    int usesEH();
-    int blockExit();
-    int fallOffEnd();
-
-    Statement *inlineScan(InlineScanState *iss);
-
-    void toIR(IRState *irs);
-};
-
-struct OnScopeStatement : Statement
-{
-    TOK tok;
-    Statement *statement;
-
-    OnScopeStatement(Loc loc, TOK tok, Statement *statement);
-    Statement *syntaxCopy();
-    int blockExit();
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-    Statement *semantic(Scope *sc);
-    int usesEH();
-    void scopeCode(Scope *sc, Statement **sentry, Statement **sexit, Statement **sfinally);
-
-    void toIR(IRState *irs);
-};
-
-struct ThrowStatement : Statement
-{
-    Expression *exp;
-
-    ThrowStatement(Loc loc, Expression *exp);
-    Statement *syntaxCopy();
-    Statement *semantic(Scope *sc);
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-    int blockExit();
-    int fallOffEnd();
-
-    Statement *inlineScan(InlineScanState *iss);
-
-    void toIR(IRState *irs);
-};
-
-struct VolatileStatement : Statement
-{
-    Statement *statement;
-    EnclosingHandler* enclosinghandler;
-
-    VolatileStatement(Loc loc, Statement *statement);
-    Statement *syntaxCopy();
-    Statement *semantic(Scope *sc);
-    Statements *flatten(Scope *sc);
-    int blockExit();
-    int fallOffEnd();
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-
-    Statement *inlineScan(InlineScanState *iss);
-
-    void toIR(IRState *irs);
-};
-
-struct GotoStatement : Statement
-{
-    Identifier *ident;
-    LabelDsymbol *label;
-    TryFinallyStatement *tf;
-    EnclosingHandler* enclosinghandler;
-
-    GotoStatement(Loc loc, Identifier *ident);
-    Statement *syntaxCopy();
-    Statement *semantic(Scope *sc);
-    int blockExit();
-    int fallOffEnd();
-    Expression *interpret(InterState *istate);
-
-    void toIR(IRState *irs);
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-    GotoStatement *isGotoStatement() { return this; }
-};
-
-struct LabelStatement : Statement
-{
-    Identifier *ident;
-    Statement *statement;
-    TryFinallyStatement *tf;
-    EnclosingHandler* enclosinghandler;
-    block *lblock;		// back end
-    int isReturnLabel;
-
-    LabelStatement(Loc loc, Identifier *ident, Statement *statement);
-    Statement *syntaxCopy();
-    Statement *semantic(Scope *sc);
-    Statements *flatten(Scope *sc);
-    int usesEH();
-    int blockExit();
-    int fallOffEnd();
-    int comeFrom();
-    Expression *interpret(InterState *istate);
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-
-    Statement *inlineScan(InlineScanState *iss);
-
-    void toIR(IRState *irs);
-
-    // LDC
-    bool asmLabel;       // for labels inside inline assembler
-    virtual void toNakedIR(IRState *irs);
-};
-
-struct LabelDsymbol : Dsymbol
-{
-    LabelStatement *statement;
-
-    LabelDsymbol(Identifier *ident);
-    LabelDsymbol *isLabel();
-};
-
-struct AsmStatement : Statement
-{
-    Token *tokens;
-    code *asmcode;
-    unsigned asmalign;		// alignment of this statement
-    unsigned refparam;		// !=0 if function parameter is referenced
-    unsigned naked;		// !=0 if function is to be naked
-    unsigned regs;		// mask of registers modified
-
-    AsmStatement(Loc loc, Token *tokens);
-    Statement *syntaxCopy();
-    Statement *semantic(Scope *sc);
-    int blockExit();
-    int comeFrom();
-
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-    virtual AsmStatement *isAsmStatement() { return this; }
-
-    void toIR(IRState *irs);
-
-    // LDC
-    // non-zero if this is a branch, contains the target labels identifier
-    Identifier* isBranchToLabel;
-
-    virtual void toNakedIR(IRState *irs);
-};
-
-struct AsmBlockStatement : CompoundStatement
-{
-    EnclosingHandler* enclosinghandler;
-    TryFinallyStatement* tf;
-
-    AsmBlockStatement(Loc loc, Statements *s);
-    Statements *flatten(Scope *sc);
-    Statement *syntaxCopy();
-    Statement *semantic(Scope *sc);
-
-    CompoundStatement *isCompoundStatement() { return NULL; }
-    AsmBlockStatement *isAsmBlockStatement() { return this; }
-
-    void toIR(IRState *irs);
-    virtual void toNakedIR(IRState *irs);
-    AsmBlockStatement* endsWithAsm();
-
-    llvm::Value* abiret;
-};
-
-#endif /* DMD_STATEMENT_H */
+
+// Compiler implementation of the D programming language
+// Copyright (c) 1999-2008 by Digital Mars
+// All Rights Reserved
+// written by Walter Bright
+// http://www.digitalmars.com
+// License for redistribution is by either the Artistic License
+// in artistic.txt, or the GNU General Public License in gnu.txt.
+// See the included readme.txt for details.
+
+#ifndef DMD_STATEMENT_H
+#define DMD_STATEMENT_H
+
+#ifdef __DMC__
+#pragma once
+#endif /* __DMC__ */
+
+#include "root.h"
+
+#include "arraytypes.h"
+#include "dsymbol.h"
+#include "lexer.h"
+
+struct OutBuffer;
+struct Scope;
+struct Expression;
+struct LabelDsymbol;
+struct Identifier;
+struct IfStatement;
+struct DeclarationStatement;
+struct DefaultStatement;
+struct VarDeclaration;
+struct Condition;
+struct Module;
+struct Token;
+struct InlineCostState;
+struct InlineDoState;
+struct InlineScanState;
+struct ReturnStatement;
+struct CompoundStatement;
+struct Argument;
+struct StaticAssert;
+struct AsmStatement;
+#if IN_LLVM
+struct AsmBlockStatement;
+#endif
+struct GotoStatement;
+struct ScopeStatement;
+struct TryCatchStatement;
+struct TryFinallyStatement;
+struct HdrGenState;
+struct InterState;
+#if IN_LLVM
+struct CaseStatement;
+struct LabelStatement;
+struct VolatileStatement;
+struct SynchronizedStatement;
+#endif
+
+enum TOK;
+
+#if IN_LLVM
+namespace llvm
+{
+    class Value;
+    class BasicBlock;
+    class ConstantInt;
+}
+#endif
+
+// Back end
+struct IRState;
+struct Blockx;
+#if IN_LLVM
+struct DValue;
+typedef DValue elem;
+#endif
+
+#if IN_GCC
+union tree_node; typedef union tree_node block;
+//union tree_node; typedef union tree_node elem;
+#else
+struct block;
+//struct elem;
+#endif
+struct code;
+
+/* How a statement exits; this is returned by blockExit()
+ */
+enum BE
+{
+    BEnone =	 0,
+    BEfallthru = 1,
+    BEthrow =    2,
+    BEreturn =   4,
+    BEgoto =     8,
+    BEhalt =	 0x10,
+    BEbreak =	 0x20,
+    BEcontinue = 0x40,
+    BEany = (BEfallthru | BEthrow | BEreturn | BEgoto | BEhalt),
+};
+
+struct Statement : Object
+{
+    Loc loc;
+
+    Statement(Loc loc);
+    virtual Statement *syntaxCopy();
+
+    void print();
+    char *toChars();
+
+    void error(const char *format, ...) IS_PRINTF(2);
+    void warning(const char *format, ...) IS_PRINTF(2);
+    virtual void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+    virtual TryCatchStatement *isTryCatchStatement() { return NULL; }
+    virtual GotoStatement *isGotoStatement() { return NULL; }
+    virtual AsmStatement *isAsmStatement() { return NULL; }
+    virtual AsmBlockStatement *isAsmBlockStatement() { return NULL; }
+#ifdef _DH
+    int incontract;
+#endif
+    virtual ScopeStatement *isScopeStatement() { return NULL; }
+    virtual Statement *semantic(Scope *sc);
+    Statement *semanticScope(Scope *sc, Statement *sbreak, Statement *scontinue);
+    virtual int hasBreak();
+    virtual int hasContinue();
+    virtual int usesEH();
+    virtual int blockExit();
+    virtual int comeFrom();
+    virtual void scopeCode(Scope *sc, Statement **sentry, Statement **sexit, Statement **sfinally);
+    virtual Statements *flatten(Scope *sc);
+    virtual Expression *interpret(InterState *istate);
+
+    virtual int inlineCost(InlineCostState *ics);
+    virtual Expression *doInline(InlineDoState *ids);
+    virtual Statement *inlineScan(InlineScanState *iss);
+
+    // Back end
+    virtual void toIR(IRState *irs);
+
+    // Avoid dynamic_cast
+    virtual DeclarationStatement *isDeclarationStatement() { return NULL; }
+    virtual CompoundStatement *isCompoundStatement() { return NULL; }
+    virtual ReturnStatement *isReturnStatement() { return NULL; }
+    virtual IfStatement *isIfStatement() { return NULL; }
+    virtual CaseStatement* isCaseStatement() { return NULL; }
+
+    // LDC
+    virtual void toNakedIR(IRState *irs);
+    virtual AsmBlockStatement* endsWithAsm();
+};
+
+struct ExpStatement : Statement
+{
+    Expression *exp;
+
+    ExpStatement(Loc loc, Expression *exp);
+    Statement *syntaxCopy();
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+    Statement *semantic(Scope *sc);
+    Expression *interpret(InterState *istate);
+    int blockExit();
+
+    int inlineCost(InlineCostState *ics);
+    Expression *doInline(InlineDoState *ids);
+    Statement *inlineScan(InlineScanState *iss);
+
+    void toIR(IRState *irs);
+
+    // LDC
+    void toNakedIR(IRState *irs);
+};
+
+struct CompileStatement : Statement
+{
+    Expression *exp;
+
+    CompileStatement(Loc loc, Expression *exp);
+    Statement *syntaxCopy();
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+    Statements *flatten(Scope *sc);
+    Statement *semantic(Scope *sc);
+};
+
+struct DeclarationStatement : ExpStatement
+{
+    // Doing declarations as an expression, rather than a statement,
+    // makes inlining functions much easier.
+
+    DeclarationStatement(Loc loc, Dsymbol *s);
+    DeclarationStatement(Loc loc, Expression *exp);
+    Statement *syntaxCopy();
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+    void scopeCode(Scope *sc, Statement **sentry, Statement **sexit, Statement **sfinally);
+
+    DeclarationStatement *isDeclarationStatement() { return this; }
+};
+
+struct CompoundStatement : Statement
+{
+    Statements *statements;
+
+    CompoundStatement(Loc loc, Statements *s);
+    CompoundStatement(Loc loc, Statement *s1, Statement *s2);
+    virtual Statement *syntaxCopy();
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+    virtual Statement *semantic(Scope *sc);
+    int usesEH();
+    int blockExit();
+    int comeFrom();
+    virtual Statements *flatten(Scope *sc);
+    ReturnStatement *isReturnStatement();
+    Expression *interpret(InterState *istate);
+
+    int inlineCost(InlineCostState *ics);
+    Expression *doInline(InlineDoState *ids);
+    Statement *inlineScan(InlineScanState *iss);
+
+    virtual void toIR(IRState *irs);
+
+    // LDC
+    virtual void toNakedIR(IRState *irs);
+    virtual AsmBlockStatement* endsWithAsm();
+
+    virtual CompoundStatement *isCompoundStatement() { return this; }
+};
+
+struct CompoundDeclarationStatement : CompoundStatement
+{
+    CompoundDeclarationStatement(Loc loc, Statements *s);
+    Statement *syntaxCopy();
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+};
+
+/* The purpose of this is so that continue will go to the next
+ * of the statements, and break will go to the end of the statements.
+ */
+struct UnrolledLoopStatement : Statement
+{
+    Statements *statements;
+
+    UnrolledLoopStatement(Loc loc, Statements *statements);
+    Statement *syntaxCopy();
+    Statement *semantic(Scope *sc);
+    int hasBreak();
+    int hasContinue();
+    int usesEH();
+    int blockExit();
+    int comeFrom();
+    Expression *interpret(InterState *istate);
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+
+    int inlineCost(InlineCostState *ics);
+    Expression *doInline(InlineDoState *ids);
+    Statement *inlineScan(InlineScanState *iss);
+
+    void toIR(IRState *irs);
+};
+
+struct ScopeStatement : Statement
+{
+    Statement *statement;
+
+    ScopeStatement(Loc loc, Statement *s);
+    Statement *syntaxCopy();
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+    ScopeStatement *isScopeStatement() { return this; }
+    Statement *semantic(Scope *sc);
+    int hasBreak();
+    int hasContinue();
+    int usesEH();
+    int blockExit();
+    int comeFrom();
+    Expression *interpret(InterState *istate);
+
+    Statement *inlineScan(InlineScanState *iss);
+
+    void toIR(IRState *irs);
+};
+
+struct WhileStatement : Statement
+{
+    Expression *condition;
+    Statement *body;
+
+    WhileStatement(Loc loc, Expression *c, Statement *b);
+    Statement *syntaxCopy();
+    Statement *semantic(Scope *sc);
+    int hasBreak();
+    int hasContinue();
+    int usesEH();
+    int blockExit();
+    int comeFrom();
+    Expression *interpret(InterState *istate);
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+
+    Statement *inlineScan(InlineScanState *iss);
+
+    void toIR(IRState *irs);
+};
+
+struct DoStatement : Statement
+{
+    Statement *body;
+    Expression *condition;
+
+    DoStatement(Loc loc, Statement *b, Expression *c);
+    Statement *syntaxCopy();
+    Statement *semantic(Scope *sc);
+    int hasBreak();
+    int hasContinue();
+    int usesEH();
+    int blockExit();
+    int comeFrom();
+    Expression *interpret(InterState *istate);
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+
+    Statement *inlineScan(InlineScanState *iss);
+
+    void toIR(IRState *irs);
+};
+
+struct ForStatement : Statement
+{
+    Statement *init;
+    Expression *condition;
+    Expression *increment;
+    Statement *body;
+
+    ForStatement(Loc loc, Statement *init, Expression *condition, Expression *increment, Statement *body);
+    Statement *syntaxCopy();
+    Statement *semantic(Scope *sc);
+    void scopeCode(Scope *sc, Statement **sentry, Statement **sexit, Statement **sfinally);
+    int hasBreak();
+    int hasContinue();
+    int usesEH();
+    int blockExit();
+    int comeFrom();
+    Expression *interpret(InterState *istate);
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+
+    Statement *inlineScan(InlineScanState *iss);
+
+    void toIR(IRState *irs);
+};
+
+struct ForeachStatement : Statement
+{
+    enum TOK op;		// TOKforeach or TOKforeach_reverse
+    Arguments *arguments;	// array of Argument*'s
+    Expression *aggr;
+    Statement *body;
+
+    VarDeclaration *key;
+    VarDeclaration *value;
+
+    FuncDeclaration *func;	// function we're lexically in
+
+    Array cases;	// put breaks, continues, gotos and returns here
+    Array gotos;	// forward referenced goto's go here
+
+    ForeachStatement(Loc loc, enum TOK op, Arguments *arguments, Expression *aggr, Statement *body);
+    Statement *syntaxCopy();
+    Statement *semantic(Scope *sc);
+    bool checkForArgTypes();
+    int hasBreak();
+    int hasContinue();
+    int usesEH();
+    int blockExit();
+    int comeFrom();
+    Expression *interpret(InterState *istate);
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+
+    Statement *inlineScan(InlineScanState *iss);
+
+    void toIR(IRState *irs);
+};
+
+#if DMDV2
+struct ForeachRangeStatement : Statement
+{
+    enum TOK op;		// TOKforeach or TOKforeach_reverse
+    Argument *arg;		// loop index variable
+    Expression *lwr;
+    Expression *upr;
+    Statement *body;
+
+    VarDeclaration *key;
+
+    ForeachRangeStatement(Loc loc, enum TOK op, Argument *arg,
+	Expression *lwr, Expression *upr, Statement *body);
+    Statement *syntaxCopy();
+    Statement *semantic(Scope *sc);
+    int hasBreak();
+    int hasContinue();
+    int usesEH();
+    int blockExit();
+    int comeFrom();
+    Expression *interpret(InterState *istate);
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+
+    Statement *inlineScan(InlineScanState *iss);
+
+    void toIR(IRState *irs);
+};
+#endif
+
+struct IfStatement : Statement
+{
+    Argument *arg;
+    Expression *condition;
+    Statement *ifbody;
+    Statement *elsebody;
+
+    VarDeclaration *match;	// for MatchExpression results
+
+    IfStatement(Loc loc, Argument *arg, Expression *condition, Statement *ifbody, Statement *elsebody);
+    Statement *syntaxCopy();
+    Statement *semantic(Scope *sc);
+    Expression *interpret(InterState *istate);
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+    int usesEH();
+    int blockExit();
+    IfStatement *isIfStatement() { return this; }
+
+    int inlineCost(InlineCostState *ics);
+    Expression *doInline(InlineDoState *ids);
+    Statement *inlineScan(InlineScanState *iss);
+
+    void toIR(IRState *irs);
+};
+
+struct ConditionalStatement : Statement
+{
+    Condition *condition;
+    Statement *ifbody;
+    Statement *elsebody;
+
+    ConditionalStatement(Loc loc, Condition *condition, Statement *ifbody, Statement *elsebody);
+    Statement *syntaxCopy();
+    Statement *semantic(Scope *sc);
+    Statements *flatten(Scope *sc);
+    int usesEH();
+    int blockExit();
+
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+};
+
+struct PragmaStatement : Statement
+{
+    Identifier *ident;
+    Expressions *args;		// array of Expression's
+    Statement *body;
+
+    PragmaStatement(Loc loc, Identifier *ident, Expressions *args, Statement *body);
+    Statement *syntaxCopy();
+    Statement *semantic(Scope *sc);
+    int usesEH();
+    int blockExit();
+
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+
+    void toIR(IRState *irs);
+};
+
+struct StaticAssertStatement : Statement
+{
+    StaticAssert *sa;
+
+    StaticAssertStatement(StaticAssert *sa);
+    Statement *syntaxCopy();
+    Statement *semantic(Scope *sc);
+
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+};
+
+struct SwitchStatement : Statement
+{
+    Expression *condition;
+    Statement *body;
+
+    DefaultStatement *sdefault;
+
+    Array gotoCases;		// array of unresolved GotoCaseStatement's
+    Array *cases;		// array of CaseStatement's
+    int hasNoDefault;		// !=0 if no default statement
+    int hasVars;		// !=0 if has variable case values
+
+    // LDC
+    Statement *enclosingScopeExit;
+
+    SwitchStatement(Loc loc, Expression *c, Statement *b);
+    Statement *syntaxCopy();
+    Statement *semantic(Scope *sc);
+    int hasBreak();
+    int usesEH();
+    int blockExit();
+    Expression *interpret(InterState *istate);
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+
+    Statement *inlineScan(InlineScanState *iss);
+
+    void toIR(IRState *irs);
+};
+
+struct CaseStatement : Statement
+{
+    Expression *exp;
+    Statement *statement;
+    int index;		// which case it is (since we sort this)
+    block *cblock;	// back end: label for the block
+
+    // LDC
+    Statement *enclosingScopeExit;
+
+    CaseStatement(Loc loc, Expression *exp, Statement *s);
+    Statement *syntaxCopy();
+    Statement *semantic(Scope *sc);
+    int compare(Object *obj);
+    int usesEH();
+    int blockExit();
+    int comeFrom();
+    Expression *interpret(InterState *istate);
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+
+    Statement *inlineScan(InlineScanState *iss);
+
+    void toIR(IRState *irs);
+
+    CaseStatement* isCaseStatement() { return this; }
+
+    // LDC
+    llvm::BasicBlock* bodyBB;
+    llvm::ConstantInt* llvmIdx;
+};
+
+struct DefaultStatement : Statement
+{
+    Statement *statement;
+#if IN_GCC
+    block *cblock;	// back end: label for the block
+#endif
+
+    // LDC
+    Statement *enclosingScopeExit;
+
+    DefaultStatement(Loc loc, Statement *s);
+    Statement *syntaxCopy();
+    Statement *semantic(Scope *sc);
+    int usesEH();
+    int blockExit();
+    int comeFrom();
+    Expression *interpret(InterState *istate);
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+
+    Statement *inlineScan(InlineScanState *iss);
+
+    void toIR(IRState *irs);
+
+    // LDC
+    llvm::BasicBlock* bodyBB;
+};
+
+struct GotoDefaultStatement : Statement
+{
+    SwitchStatement *sw;
+
+    GotoDefaultStatement(Loc loc);
+    Statement *syntaxCopy();
+    Statement *semantic(Scope *sc);
+    Expression *interpret(InterState *istate);
+    int blockExit();
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+
+    void toIR(IRState *irs);
+};
+
+struct GotoCaseStatement : Statement
+{
+    Expression *exp;		// NULL, or which case to goto
+    CaseStatement *cs;		// case statement it resolves to
+    SwitchStatement *sw;
+
+    GotoCaseStatement(Loc loc, Expression *exp);
+    Statement *syntaxCopy();
+    Statement *semantic(Scope *sc);
+    Expression *interpret(InterState *istate);
+    int blockExit();
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+
+    void toIR(IRState *irs);
+};
+
+struct SwitchErrorStatement : Statement
+{
+    SwitchErrorStatement(Loc loc);
+    int blockExit();
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+
+    void toIR(IRState *irs);
+};
+
+struct ReturnStatement : Statement
+{
+    Expression *exp;
+
+    ReturnStatement(Loc loc, Expression *exp);
+    Statement *syntaxCopy();
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+    Statement *semantic(Scope *sc);
+    int blockExit();
+    Expression *interpret(InterState *istate);
+
+    int inlineCost(InlineCostState *ics);
+    Expression *doInline(InlineDoState *ids);
+    Statement *inlineScan(InlineScanState *iss);
+
+    void toIR(IRState *irs);
+
+    ReturnStatement *isReturnStatement() { return this; }
+};
+
+struct BreakStatement : Statement
+{
+    Identifier *ident;
+
+    BreakStatement(Loc loc, Identifier *ident);
+    Statement *syntaxCopy();
+    Statement *semantic(Scope *sc);
+    Expression *interpret(InterState *istate);
+    int blockExit();
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+
+    void toIR(IRState *irs);
+
+    // LDC: only set if ident is set: label statement to jump to
+    LabelStatement *target;
+};
+
+struct ContinueStatement : Statement
+{
+    Identifier *ident;
+
+    ContinueStatement(Loc loc, Identifier *ident);
+    Statement *syntaxCopy();
+    Statement *semantic(Scope *sc);
+    Expression *interpret(InterState *istate);
+    int blockExit();
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+
+    void toIR(IRState *irs);
+
+    // LDC: only set if ident is set: label statement to jump to
+    LabelStatement *target;
+};
+
+struct SynchronizedStatement : Statement
+{
+    Expression *exp;
+    Statement *body;
+
+    SynchronizedStatement(Loc loc, Expression *exp, Statement *body);
+    Statement *syntaxCopy();
+    Statement *semantic(Scope *sc);
+    int hasBreak();
+    int hasContinue();
+    int usesEH();
+    int blockExit();
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+
+    Statement *inlineScan(InlineScanState *iss);
+
+// Back end
+    elem *esync;
+    SynchronizedStatement(Loc loc, elem *esync, Statement *body);
+    void toIR(IRState *irs);
+    llvm::Value* llsync;
+};
+
+struct WithStatement : Statement
+{
+    Expression *exp;
+    Statement *body;
+    VarDeclaration *wthis;
+
+    WithStatement(Loc loc, Expression *exp, Statement *body);
+    Statement *syntaxCopy();
+    Statement *semantic(Scope *sc);
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+    int usesEH();
+    int blockExit();
+
+    Statement *inlineScan(InlineScanState *iss);
+
+    void toIR(IRState *irs);
+};
+
+struct TryCatchStatement : Statement
+{
+    Statement *body;
+    Array *catches;
+
+    TryCatchStatement(Loc loc, Statement *body, Array *catches);
+    Statement *syntaxCopy();
+    Statement *semantic(Scope *sc);
+    int hasBreak();
+    int usesEH();
+    int blockExit();
+
+    Statement *inlineScan(InlineScanState *iss);
+
+    void toIR(IRState *irs);
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+    TryCatchStatement *isTryCatchStatement() { return this; }
+};
+
+struct Catch : Object
+{
+    Loc loc;
+    Type *type;
+    Identifier *ident;
+    VarDeclaration *var;
+    Statement *handler;
+
+    Catch(Loc loc, Type *t, Identifier *id, Statement *handler);
+    Catch *syntaxCopy();
+    void semantic(Scope *sc);
+    int blockExit();
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+};
+
+struct TryFinallyStatement : Statement
+{
+    Statement *body;
+    Statement *finalbody;
+
+    TryFinallyStatement(Loc loc, Statement *body, Statement *finalbody);
+    Statement *syntaxCopy();
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+    Statement *semantic(Scope *sc);
+    int hasBreak();
+    int hasContinue();
+    int usesEH();
+    int blockExit();
+
+    Statement *inlineScan(InlineScanState *iss);
+
+    void toIR(IRState *irs);
+};
+
+struct OnScopeStatement : Statement
+{
+    TOK tok;
+    Statement *statement;
+
+    OnScopeStatement(Loc loc, TOK tok, Statement *statement);
+    Statement *syntaxCopy();
+    int blockExit();
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+    Statement *semantic(Scope *sc);
+    int usesEH();
+    void scopeCode(Scope *sc, Statement **sentry, Statement **sexit, Statement **sfinally);
+
+    void toIR(IRState *irs);
+};
+
+struct ThrowStatement : Statement
+{
+    Expression *exp;
+
+    ThrowStatement(Loc loc, Expression *exp);
+    Statement *syntaxCopy();
+    Statement *semantic(Scope *sc);
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+    int blockExit();
+
+    Statement *inlineScan(InlineScanState *iss);
+
+    void toIR(IRState *irs);
+};
+
+struct VolatileStatement : Statement
+{
+    Statement *statement;
+
+    VolatileStatement(Loc loc, Statement *statement);
+    Statement *syntaxCopy();
+    Statement *semantic(Scope *sc);
+    Statements *flatten(Scope *sc);
+    int blockExit();
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+
+    Statement *inlineScan(InlineScanState *iss);
+
+    void toIR(IRState *irs);
+};
+
+struct GotoStatement : Statement
+{
+    Identifier *ident;
+    LabelDsymbol *label;
+    TryFinallyStatement *enclosingFinally;
+    Statement* enclosingScopeExit;
+
+    GotoStatement(Loc loc, Identifier *ident);
+    Statement *syntaxCopy();
+    Statement *semantic(Scope *sc);
+    int blockExit();
+    Expression *interpret(InterState *istate);
+
+    void toIR(IRState *irs);
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+    GotoStatement *isGotoStatement() { return this; }
+};
+
+struct LabelStatement : Statement
+{
+    Identifier *ident;
+    Statement *statement;
+    TryFinallyStatement *enclosingFinally;
+    Statement* enclosingScopeExit;
+    block *lblock;		// back end
+    int isReturnLabel;
+
+    LabelStatement(Loc loc, Identifier *ident, Statement *statement);
+    Statement *syntaxCopy();
+    Statement *semantic(Scope *sc);
+    Statements *flatten(Scope *sc);
+    int usesEH();
+    int blockExit();
+    int comeFrom();
+    Expression *interpret(InterState *istate);
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+
+    Statement *inlineScan(InlineScanState *iss);
+
+    void toIR(IRState *irs);
+
+    // LDC
+    bool asmLabel;       // for labels inside inline assembler
+    void toNakedIR(IRState *irs);
+};
+
+struct LabelDsymbol : Dsymbol
+{
+    LabelStatement *statement;
+#if IN_GCC
+    unsigned asmLabelNum;       // GCC-specific
+#endif
+
+    LabelDsymbol(Identifier *ident);
+    LabelDsymbol *isLabel();
+};
+
+struct AsmStatement : Statement
+{
+    Token *tokens;
+    code *asmcode;
+    unsigned asmalign;		// alignment of this statement
+    unsigned refparam;		// !=0 if function parameter is referenced
+    unsigned naked;		// !=0 if function is to be naked
+    unsigned regs;		// mask of registers modified
+
+    AsmStatement(Loc loc, Token *tokens);
+    Statement *syntaxCopy();
+    Statement *semantic(Scope *sc);
+    int blockExit();
+    int comeFrom();
+
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+    virtual AsmStatement *isAsmStatement() { return this; }
+
+    void toIR(IRState *irs);
+
+    // LDC
+    // non-zero if this is a branch, contains the target labels identifier
+    Identifier* isBranchToLabel;
+
+    void toNakedIR(IRState *irs);
+};
+
+struct AsmBlockStatement : CompoundStatement
+{
+    TryFinallyStatement* enclosingFinally;
+    Statement* enclosingScopeExit;
+
+    AsmBlockStatement(Loc loc, Statements *s);
+    Statements *flatten(Scope *sc);
+    Statement *syntaxCopy();
+    Statement *semantic(Scope *sc);
+
+    CompoundStatement *isCompoundStatement() { return NULL; }
+    AsmBlockStatement *isAsmBlockStatement() { return this; }
+
+    void toIR(IRState *irs);
+    void toNakedIR(IRState *irs);
+    AsmBlockStatement* endsWithAsm();
+
+    llvm::Value* abiret;
+};
+
+#endif /* DMD_STATEMENT_H */
--- a/dmd2/staticassert.c	Mon Jun 01 01:28:18 2009 +0200
+++ b/dmd2/staticassert.c	Mon Jun 01 19:02:20 2009 +0100
@@ -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/dmd2/stringtable.c	Mon Jun 01 01:28:18 2009 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,139 +0,0 @@
-
-// 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 <string.h>
-#include <stdlib.h>
-
-#include "root.h"
-#include "mem.h"
-#include "dchar.h"
-#include "lstring.h"
-#include "stringtable.h"
-
-StringTable::StringTable(unsigned size)
-{
-    table = (void **)mem.calloc(size, sizeof(void *));
-    tabledim = size;
-    count = 0;
-}
-
-StringTable::~StringTable()
-{
-    unsigned i;
-
-    // Zero out dangling pointers to help garbage collector.
-    // Should zero out StringEntry's too.
-    for (i = 0; i < count; i++)
-	table[i] = NULL;
-
-    mem.free(table);
-    table = NULL;
-}
-
-struct StringEntry
-{
-    StringEntry *left;
-    StringEntry *right;
-    hash_t hash;
-
-    StringValue value;
-
-    static StringEntry *alloc(const dchar *s, unsigned len);
-};
-
-StringEntry *StringEntry::alloc(const dchar *s, unsigned len)
-{
-    StringEntry *se;
-
-    se = (StringEntry *) mem.calloc(1,sizeof(StringEntry) - sizeof(Lstring) + Lstring::size(len));
-    se->value.lstring.length = len;
-    se->hash = Dchar::calcHash(s,len);
-    memcpy(se->value.lstring.string, s, len * sizeof(dchar));
-    return se;
-}
-
-void **StringTable::search(const dchar *s, unsigned len)
-{
-    hash_t hash;
-    unsigned u;
-    int cmp;
-    StringEntry **se;
-
-    //printf("StringTable::search(%p,%d)\n",s,len);
-    hash = Dchar::calcHash(s,len);
-    u = hash % tabledim;
-    se = (StringEntry **)&table[u];
-    //printf("\thash = %d, u = %d\n",hash,u);
-    while (*se)
-    {
-	cmp = (*se)->hash - hash;
-	if (cmp == 0)
-	{
-	    cmp = (*se)->value.lstring.len() - len;
-	    if (cmp == 0)
-	    {
-		cmp = Dchar::memcmp(s,(*se)->value.lstring.toDchars(),len);
-		if (cmp == 0)
-		    break;
-	    }
-	}
-	if (cmp < 0)
-	    se = &(*se)->left;
-	else
-	    se = &(*se)->right;
-    }
-    //printf("\treturn %p, %p\n",se, (*se));
-    return (void **)se;
-}
-
-StringValue *StringTable::lookup(const dchar *s, unsigned len)
-{   StringEntry *se;
-
-    se = *(StringEntry **)search(s,len);
-    if (se)
-	return &se->value;
-    else
-	return NULL;
-}
-
-StringValue *StringTable::update(const dchar *s, unsigned len)
-{   StringEntry **pse;
-    StringEntry *se;
-
-    pse = (StringEntry **)search(s,len);
-    se = *pse;
-    if (!se)			// not in table: so create new entry
-    {
-	se = StringEntry::alloc(s, len);
-	*pse = se;
-    }
-    return &se->value;
-}
-
-StringValue *StringTable::insert(const dchar *s, unsigned len)
-{   StringEntry **pse;
-    StringEntry *se;
-
-    pse = (StringEntry **)search(s,len);
-    se = *pse;
-    if (se)
-	return NULL;		// error: already in table
-    else
-    {
-	se = StringEntry::alloc(s, len);
-	*pse = se;
-    }
-    return &se->value;
-}
-
-
-
-
--- a/dmd2/stringtable.h	Mon Jun 01 01:28:18 2009 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,48 +0,0 @@
-// Copyright (c) 1999-2008 by Digital Mars
-// All Rights Reserved
-// written by Walter Bright
-// http://www.digitalmars.com
-// License for redistribution is by either the Artistic License
-// in artistic.txt, or the GNU General Public License in gnu.txt.
-// See the included readme.txt for details.
-
-
-#ifndef STRINGTABLE_H
-#define STRINGTABLE_H
-
-#if __SC__
-#pragma once
-#endif
-
-#include "root.h"
-#include "dchar.h"
-#include "lstring.h"
-
-struct StringValue
-{
-    union
-    {	int intvalue;
-	void *ptrvalue;
-	dchar *string;
-    };
-    Lstring lstring;
-};
-
-struct StringTable : Object
-{
-    void **table;
-    unsigned count;
-    unsigned tabledim;
-
-    StringTable(unsigned size = 37);
-    ~StringTable();
-
-    StringValue *lookup(const dchar *s, unsigned len);
-    StringValue *insert(const dchar *s, unsigned len);
-    StringValue *update(const dchar *s, unsigned len);
-
-private:
-    void **search(const dchar *s, unsigned len);
-};
-
-#endif
--- a/dmd2/struct.c	Mon Jun 01 01:28:18 2009 +0200
+++ b/dmd2/struct.c	Mon Jun 01 19:02:20 2009 +0100
@@ -1,6 +1,6 @@
 
 // Compiler implementation of the D programming language
-// Copyright (c) 1999-2008 by Digital Mars
+// Copyright (c) 1999-2009 by Digital Mars
 // All Rights Reserved
 // written by Walter Bright
 // http://www.digitalmars.com
@@ -19,6 +19,7 @@
 #include "module.h"
 #include "id.h"
 #include "statement.h"
+#include "template.h"
 
 /********************************* AggregateDeclaration ****************************/
 
@@ -41,13 +42,20 @@
     aggNew = NULL;
     aggDelete = NULL;
 
+#if IN_DMD
     stag = NULL;
     sinit = NULL;
+#endif
     scope = NULL;
-    dtor = NULL;
+    isnested = 0;
+    vthis = NULL;
 
+#if DMDV2
     ctor = NULL;
     defaultCtor = NULL;
+    aliasthis = NULL;
+#endif
+    dtor = NULL;
 }
 
 enum PROT AggregateDeclaration::prot()
@@ -132,31 +140,21 @@
  * Align sizes of 0, as we may not know array sizes yet.
  */
 
-void AggregateDeclaration::alignmember(unsigned salign, unsigned size, unsigned *poffset)
+void AggregateDeclaration::alignmember(
+	unsigned salign,	// struct alignment that is in effect
+	unsigned size,		// alignment requirement of field
+	unsigned *poffset)
 {
-    //printf("salign = %d, size = %d, offset = %d\n",salign,size,*poffset);
+    //printf("salign = %d, size = %d, offset = %d\n",salign,size,offset);
     if (salign > 1)
-    {	int sa;
-
-	switch (size)
-	{   case 1:
-		break;
-	    case 2:
-	    case_2:
-		*poffset = (*poffset + 1) & ~1;	// align to word
-		break;
-	    case 3:
-	    case 4:
-		if (salign == 2)
-		    goto case_2;
-		*poffset = (*poffset + 3) & ~3;	// align to dword
-		break;
-	    default:
-		*poffset = (*poffset + size - 1) & ~(size - 1);
-		break;
-	}
+    {
+	assert(size != 3);
+	int sa = size;
+	if (sa == 0 || salign < sa)
+	    sa = salign;
+	*poffset = (*poffset + sa - 1) & ~(sa - 1);
     }
-    //printf("result = %d\n",*poffset);
+    //printf("result = %d\n",offset);
 }
 
 
@@ -171,13 +169,18 @@
 
     // Check for forward referenced types which will fail the size() call
     Type *t = v->type->toBasetype();
+    if (v->storage_class & STCref)
+    {	// References are the size of a pointer
+	t = Type::tvoidptr;
+    }
     if (t->ty == Tstruct /*&& isStructDeclaration()*/)
     {	TypeStruct *ts = (TypeStruct *)t;
-
+#if DMDV2
 	if (ts->sym == this)
 	{
 	    error("cannot have field %s with same struct type", v->toChars());
 	}
+#endif
 
 	if (ts->sym->sizeok != 1)
 	{
@@ -191,9 +194,9 @@
 	return;
     }
 
-    memsize = v->type->size(loc);
-    memalignsize = v->type->alignsize();
-    xalign = v->type->memalign(sc->structalign);
+    memsize = t->size(loc);
+    memalignsize = t->alignsize();
+    xalign = t->memalign(sc->structalign);
     alignmember(xalign, memalignsize, &sc->offset);
     v->offset = sc->offset;
     sc->offset += memsize;
@@ -211,15 +214,28 @@
 }
 
 
+/****************************************
+ * Returns !=0 if there's an extra member which is the 'this'
+ * pointer to the enclosing context (enclosing aggregate or function)
+ */
+
+int AggregateDeclaration::isNested()
+{
+    return isnested;
+}
+
+
 /********************************* StructDeclaration ****************************/
 
 StructDeclaration::StructDeclaration(Loc loc, Identifier *id)
     : AggregateDeclaration(loc, id)
 {
     zeroInit = 0;	// assume false until we do semantic processing
+#if DMDV2
     hasIdentityAssign = 0;
     cpctor = NULL;
     postblit = NULL;
+#endif
 
     // For forward references
     type = new TypeStruct(this);
@@ -277,24 +293,64 @@
     assert(!isAnonymous());
     if (sc->stc & STCabstract)
 	error("structs, unions cannot be abstract");
-    if (storage_class & STCinvariant)
+#if DMDV2
+    if (storage_class & STCimmutable)
         type = type->invariantOf();
     else if (storage_class & STCconst)
         type = type->constOf();
+    else if (storage_class & STCshared)
+        type = type->sharedOf();
+#endif
 
     if (sizeok == 0)		// if not already done the addMember step
     {
+	int hasfunctions = 0;
 	for (i = 0; i < members->dim; i++)
 	{
 	    Dsymbol *s = (Dsymbol *)members->data[i];
 	    //printf("adding member '%s' to '%s'\n", s->toChars(), this->toChars());
 	    s->addMember(sc, this, 1);
+	    if (s->isFuncDeclaration())
+		hasfunctions = 1;
 	}
+
+	// If nested struct, add in hidden 'this' pointer to outer scope
+	if (hasfunctions && !(storage_class & STCstatic))
+        {   Dsymbol *s = toParent2();
+            if (s)
+            {
+                AggregateDeclaration *ad = s->isAggregateDeclaration();
+                FuncDeclaration *fd = s->isFuncDeclaration();
+
+		TemplateInstance *ti;
+                if (ad && (ti = ad->parent->isTemplateInstance()) != NULL && ti->isnested || fd)
+                {   isnested = 1;
+                    Type *t;
+                    if (ad)
+                        t = ad->handle;
+                    else if (fd)
+                    {   AggregateDeclaration *ad = fd->isMember2();
+                        if (ad)
+                            t = ad->handle;
+                        else
+			    t = Type::tvoidptr;
+                    }
+                    else
+                        assert(0);
+		    if (t->ty == Tstruct)
+			t = Type::tvoidptr;	// t should not be a ref type
+                    assert(!vthis);
+                    vthis = new ThisDeclaration(loc, t);
+		    //vthis->storage_class |= STCref;
+                    members->push(vthis);
+                }
+            }
+        }
     }
 
     sizeok = 0;
     sc2 = sc->push(this);
-    sc2->stc &= storage_class & (STCconst | STCinvariant);
+    sc2->stc &= storage_class & STC_TYPECTOR;
     sc2->parent = this;
     if (isUnionDeclaration())
 	sc2->inunion = 1;
@@ -314,6 +370,14 @@
 	    break;
 	}
 #endif
+	Type *t;
+	if (s->isDeclaration() &&
+	    (t = s->isDeclaration()->type) != NULL &&
+	    t->toBasetype()->ty == Tstruct)
+	{   StructDeclaration *sd = (StructDeclaration *)t->toDsymbol(sc);
+	    if (sd->isnested)
+		error("inner struct %s cannot be a field", sd->toChars());
+	}
     }
 
     /* The TypeInfo_Struct is expecting an opEquals and opCmp with
@@ -349,9 +413,9 @@
 	Dsymbol *s = search_function(this, id);
 	FuncDeclaration *fdx = s ? s->isFuncDeclaration() : NULL;
 	if (fdx)
-	{   FuncDeclaration *fd = fdx->overloadExactMatch(tfeqptr);
+	{   FuncDeclaration *fd = fdx->overloadExactMatch(tfeqptr, getModule());
 	    if (!fd)
-	    {	fd = fdx->overloadExactMatch(tfeq);
+	    {	fd = fdx->overloadExactMatch(tfeq, getModule());
 		if (fd)
 		{   // Create the thunk, fdptr
 		    FuncDeclaration *fdptr = new FuncDeclaration(loc, loc, fdx->ident, STCundefined, tfeqptr);
@@ -373,11 +437,12 @@
 
 	id = Id::cmp;
     }
-
+#if DMDV2
     dtor = buildDtor(sc2);
     postblit = buildPostBlit(sc2);
     cpctor = buildCpCtor(sc2);
     buildOpAssign(sc2);
+#endif
 
     sc2->pop();
 
@@ -429,7 +494,7 @@
 	    }
 	    else
 	    {
-		if (!vd->type->isZeroInit())
+		if (!vd->type->isZeroInit(loc))
 		{
 		    zeroInit = 0;
 		    break;
@@ -440,7 +505,9 @@
 
     /* Look for special member functions.
      */
-    ctor =   (CtorDeclaration *)search(0, Id::ctor, 0);
+#if DMDV2
+    ctor = search(0, Id::ctor, 0);
+#endif
     inv =    (InvariantDeclaration *)search(0, Id::classInvariant, 0);
     aggNew =       (NewDeclaration *)search(0, Id::classNew,       0);
     aggDelete = (DeleteDeclaration *)search(0, Id::classDelete,    0);
--- a/dmd2/template.c	Mon Jun 01 01:28:18 2009 +0200
+++ b/dmd2/template.c	Mon Jun 01 19:02:20 2009 +0100
@@ -1,4629 +1,4924 @@
-
-// 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.
-
-// Handle template implementation
-
-#include <stdio.h>
-#include <assert.h>
-
-#if !IN_LLVM
-#endif
-#include "root.h"
-#include "mem.h"
-#include "stringtable.h"
-#include "mars.h"
-#include "identifier.h"
-#include "mtype.h"
-#include "template.h"
-#include "init.h"
-#include "expression.h"
-#include "scope.h"
-#include "module.h"
-#include "aggregate.h"
-#include "declaration.h"
-#include "dsymbol.h"
-#include "hdrgen.h"
-
-#if WINDOWS_SEH
-#include <windows.h>
-long __cdecl __ehfilter(LPEXCEPTION_POINTERS ep);
-#endif
-
-#define LOG	0
-
-
-/********************************************
- * These functions substitute for dynamic_cast. dynamic_cast does not work
- * on earlier versions of gcc.
- */
-
-Expression *isExpression(Object *o)
-{
-    //return dynamic_cast<Expression *>(o);
-    if (!o || o->dyncast() != DYNCAST_EXPRESSION)
-	return NULL;
-    return (Expression *)o;
-}
-
-Dsymbol *isDsymbol(Object *o)
-{
-    //return dynamic_cast<Dsymbol *>(o);
-    if (!o || o->dyncast() != DYNCAST_DSYMBOL)
-	return NULL;
-    return (Dsymbol *)o;
-}
-
-Type *isType(Object *o)
-{
-    //return dynamic_cast<Type *>(o);
-    if (!o || o->dyncast() != DYNCAST_TYPE)
-	return NULL;
-    return (Type *)o;
-}
-
-Tuple *isTuple(Object *o)
-{
-    //return dynamic_cast<Tuple *>(o);
-    if (!o || o->dyncast() != DYNCAST_TUPLE)
-	return NULL;
-    return (Tuple *)o;
-}
-
-
-/***********************
- * Try to get arg as a type.
- */
-
-Type *getType(Object *o)
-{
-    Type *t = isType(o);
-    if (!t)
-    {   Expression *e = isExpression(o);
-	if (e)
-	    t = e->type;
-    }
-    return t;
-}
-
-Dsymbol *getDsymbol(Object *oarg)
-{
-    Dsymbol *sa;
-    Expression *ea = isExpression(oarg);
-    if (ea)
-    {   // Try to convert Expression to symbol
-	if (ea->op == TOKvar)
-	    sa = ((VarExp *)ea)->var;
-	else if (ea->op == TOKfunction)
-	    sa = ((FuncExp *)ea)->fd;
-	else
-	    sa = NULL;
-    }
-    else
-    {   // Try to convert Type to symbol
-	Type *ta = isType(oarg);
-	if (ta)
-	    sa = ta->toDsymbol(NULL);
-	else
-	    sa = isDsymbol(oarg);	// if already a symbol
-    }
-    return sa;
-}
-
-/******************************
- * If o1 matches o2, return 1.
- * Else, return 0.
- */
-
-int match(Object *o1, Object *o2, TemplateDeclaration *tempdecl, Scope *sc)
-{
-    Type *t1 = isType(o1);
-    Type *t2 = isType(o2);
-    Expression *e1 = isExpression(o1);
-    Expression *e2 = isExpression(o2);
-    Dsymbol *s1 = isDsymbol(o1);
-    Dsymbol *s2 = isDsymbol(o2);
-    Tuple *v1 = isTuple(o1);
-    Tuple *v2 = isTuple(o2);
-
-    //printf("\t match t1 %p t2 %p, e1 %p e2 %p, s1 %p s2 %p, v1 %p v2 %p\n", t1,t2,e1,e2,s1,s2,v1,v2);
-
-    /* A proper implementation of the various equals() overrides
-     * should make it possible to just do o1->equals(o2), but
-     * we'll do that another day.
-     */
-
-    if (t1)
-    {
-	/* if t1 is an instance of ti, then give error
-	 * about recursive expansions.
-	 */
-	Dsymbol *s = t1->toDsymbol(sc);
-	if (s && s->parent)
-	{   TemplateInstance *ti1 = s->parent->isTemplateInstance();
-	    if (ti1 && ti1->tempdecl == tempdecl)
-	    {
-		for (Scope *sc1 = sc; sc1; sc1 = sc1->enclosing)
-		{
-		    if (sc1->scopesym == ti1)
-		    {
-			error("recursive template expansion for template argument %s", t1->toChars());
-			return 1;	// fake a match
-		    }
-		}
-	    }
-	}
-
-	if (!t2 || !t1->equals(t2))
-	    goto Lnomatch;
-    }
-    else if (e1)
-    {
-#if 0
-	if (e1 && e2)
-	{
-	    printf("match %d\n", e1->equals(e2));
-	    e1->print();
-	    e2->print();
-	    e1->type->print();
-	    e2->type->print();
-	}
-#endif
-	if (!e2)
-	    goto Lnomatch;
-	if (!e1->equals(e2))
-	    goto Lnomatch;
-    }
-    else if (s1)
-    {
-	//printf("%p %s, %p %s\n", s1, s1->toChars(), s2, s2->toChars());
-	if (!s2 || !s1->equals(s2) || s1->parent != s2->parent)
-	{
-	    goto Lnomatch;
-	}
-	VarDeclaration *v1 = s1->isVarDeclaration();
-	VarDeclaration *v2 = s2->isVarDeclaration();
-	if (v1 && v2 && v1->storage_class & v2->storage_class & STCmanifest)
-	{   ExpInitializer *ei1 = v1->init->isExpInitializer();
-	    ExpInitializer *ei2 = v2->init->isExpInitializer();
-	    if (ei1 && ei2 && !ei1->exp->equals(ei2->exp))
-		goto Lnomatch;
-	}
-    }
-    else if (v1)
-    {
-	if (!v2)
-	    goto Lnomatch;
-	if (v1->objects.dim != v2->objects.dim)
-	    goto Lnomatch;
-	for (size_t i = 0; i < v1->objects.dim; i++)
-	{
-	    if (!match((Object *)v1->objects.data[i],
-		       (Object *)v2->objects.data[i],
-		       tempdecl, sc))
-		goto Lnomatch;
-	}
-    }
-    //printf("match\n");
-    return 1;	// match
-Lnomatch:
-    //printf("nomatch\n");
-    return 0;	// nomatch;
-}
-
-/****************************************
- */
-
-void ObjectToCBuffer(OutBuffer *buf, HdrGenState *hgs, Object *oarg)
-{
-    //printf("ObjectToCBuffer()\n");
-    Type *t = isType(oarg);
-    Expression *e = isExpression(oarg);
-    Dsymbol *s = isDsymbol(oarg);
-    Tuple *v = isTuple(oarg);
-    if (t)
-    {	//printf("\tt: %s ty = %d\n", t->toChars(), t->ty);
-	t->toCBuffer(buf, NULL, hgs);
-    }
-    else if (e)
-	e->toCBuffer(buf, hgs);
-    else if (s)
-    {
-	char *p = s->ident ? s->ident->toChars() : s->toChars();
-	buf->writestring(p);
-    }
-    else if (v)
-    {
-	Objects *args = &v->objects;
-	for (size_t i = 0; i < args->dim; i++)
-	{
-	    if (i)
-		buf->writeByte(',');
-	    Object *o = (Object *)args->data[i];
-	    ObjectToCBuffer(buf, hgs, o);
-	}
-    }
-    else if (!oarg)
-    {
-	buf->writestring("NULL");
-    }
-    else
-    {
-#ifdef DEBUG
-	printf("bad Object = %p\n", oarg);
-#endif
-	assert(0);
-    }
-}
-
-Object *objectSyntaxCopy(Object *o)
-{
-    if (!o)
-	return NULL;
-    Type *t = isType(o);
-    if (t)
-	return t->syntaxCopy();
-    Expression *e = isExpression(o);
-    if (e)
-	return e->syntaxCopy();
-    return o;
-}
-
-
-/* ======================== TemplateDeclaration ============================= */
-
-TemplateDeclaration::TemplateDeclaration(Loc loc, Identifier *id,
-	TemplateParameters *parameters, Expression *constraint, Array *decldefs)
-    : ScopeDsymbol(id)
-{
-#if LOG
-    printf("TemplateDeclaration(this = %p, id = '%s')\n", this, id->toChars());
-#endif
-#if 0
-    if (parameters)
-	for (int i = 0; i < parameters->dim; i++)
-	{   TemplateParameter *tp = (TemplateParameter *)parameters->data[i];
-	    //printf("\tparameter[%d] = %p\n", i, tp);
-	    TemplateTypeParameter *ttp = tp->isTemplateTypeParameter();
-
-	    if (ttp)
-	    {
-		printf("\tparameter[%d] = %s : %s\n", i, tp->ident->toChars(), ttp->specType ? ttp->specType->toChars() : "");
-	    }
-	}
-#endif
-    this->loc = loc;
-    this->parameters = parameters;
-    this->origParameters = parameters;
-    this->constraint = constraint;
-    this->members = decldefs;
-    this->overnext = NULL;
-    this->overroot = NULL;
-    this->scope = NULL;
-    this->onemember = NULL;
-}
-
-Dsymbol *TemplateDeclaration::syntaxCopy(Dsymbol *)
-{
-    //printf("TemplateDeclaration::syntaxCopy()\n");
-    TemplateDeclaration *td;
-    TemplateParameters *p;
-    Array *d;
-
-    p = NULL;
-    if (parameters)
-    {
-	p = new TemplateParameters();
-	p->setDim(parameters->dim);
-	for (int i = 0; i < p->dim; i++)
-	{   TemplateParameter *tp = (TemplateParameter *)parameters->data[i];
-	    p->data[i] = (void *)tp->syntaxCopy();
-	}
-    }
-    Expression *e = NULL;
-    if (constraint)
-	e = constraint->syntaxCopy();
-    d = Dsymbol::arraySyntaxCopy(members);
-    td = new TemplateDeclaration(loc, ident, p, e, d);
-    
-    // LDC
-    td->intrinsicName = intrinsicName;
-    
-    return td;
-}
-
-void TemplateDeclaration::semantic(Scope *sc)
-{
-#if LOG
-    printf("TemplateDeclaration::semantic(this = %p, id = '%s')\n", this, ident->toChars());
-#endif
-    if (scope)
-	return;		// semantic() already run
-
-    if (sc->func)
-    {
-//	error("cannot declare template at function scope %s", sc->func->toChars());
-    }
-
-    if (/*global.params.useArrayBounds &&*/ sc->module)
-    {
-	// Generate this function as it may be used
-	// when template is instantiated in other modules
-	sc->module->toModuleArray();
-    }
-
-    if (/*global.params.useAssert &&*/ sc->module)
-    {
-	// Generate this function as it may be used
-	// when template is instantiated in other modules
-	sc->module->toModuleAssert();
-    }
-
-    /* Remember Scope for later instantiations, but make
-     * a copy since attributes can change.
-     */
-    this->scope = new Scope(*sc);
-    this->scope->setNoFree();
-
-    // Set up scope for parameters
-    ScopeDsymbol *paramsym = new ScopeDsymbol();
-    paramsym->parent = sc->parent;
-    Scope *paramscope = sc->push(paramsym);
-    paramscope->parameterSpecialization = 1;
-
-    if (global.params.doDocComments)
-    {
-	origParameters = new TemplateParameters();
-	origParameters->setDim(parameters->dim);
-	for (int i = 0; i < parameters->dim; i++)
-	{
-	    TemplateParameter *tp = (TemplateParameter *)parameters->data[i];
-	    origParameters->data[i] = (void *)tp->syntaxCopy();
-	}
-    }
-
-    for (int i = 0; i < parameters->dim; i++)
-    {
-	TemplateParameter *tp = (TemplateParameter *)parameters->data[i];
-
-	tp->declareParameter(paramscope);
-    }
-
-    for (int i = 0; i < parameters->dim; i++)
-    {
-	TemplateParameter *tp = (TemplateParameter *)parameters->data[i];
-
-	tp->semantic(paramscope);
-	if (i + 1 != parameters->dim && tp->isTemplateTupleParameter())
-	    error("template tuple parameter must be last one");
-    }
-
-    paramscope->pop();
-
-    if (members)
-    {
-	Dsymbol *s;
-	if (Dsymbol::oneMembers(members, &s))
-	{
-	    if (s && s->ident && s->ident->equals(ident))
-	    {
-		onemember = s;
-		s->parent = this;
-	    }
-	}
-    }
-
-    /* BUG: should check:
-     *	o no virtual functions or non-static data members of classes
-     */
-}
-
-const char *TemplateDeclaration::kind()
-{
-    return (onemember && onemember->isAggregateDeclaration())
-		? onemember->kind()
-		: (char *)"template";
-}
-
-/**********************************
- * Overload existing TemplateDeclaration 'this' with the new one 's'.
- * Return !=0 if successful; i.e. no conflict.
- */
-
-int TemplateDeclaration::overloadInsert(Dsymbol *s)
-{
-    TemplateDeclaration **pf;
-    TemplateDeclaration *f;
-
-#if LOG
-    printf("TemplateDeclaration::overloadInsert('%s')\n", s->toChars());
-#endif
-    f = s->isTemplateDeclaration();
-    if (!f)
-	return FALSE;
-    TemplateDeclaration *pthis = this;
-    for (pf = &pthis; *pf; pf = &(*pf)->overnext)
-    {
-#if 0
-	// Conflict if TemplateParameter's match
-	// Will get caught anyway later with TemplateInstance, but
-	// should check it now.
-	TemplateDeclaration *f2 = *pf;
-
-	if (f->parameters->dim != f2->parameters->dim)
-	    goto Lcontinue;
-
-	for (int i = 0; i < f->parameters->dim; i++)
-	{   TemplateParameter *p1 = (TemplateParameter *)f->parameters->data[i];
-	    TemplateParameter *p2 = (TemplateParameter *)f2->parameters->data[i];
-
-	    if (!p1->overloadMatch(p2))
-		goto Lcontinue;
-	}
-
-#if LOG
-	printf("\tfalse: conflict\n");
-#endif
-	return FALSE;
-
-     Lcontinue:
-	;
-#endif
-    }
-
-    f->overroot = this;
-    *pf = f;
-#if LOG
-    printf("\ttrue: no conflict\n");
-#endif
-    return TRUE;
-}
-
-/***************************************
- * Given that ti is an instance of this TemplateDeclaration,
- * deduce the types of the parameters to this, and store
- * those deduced types in dedtypes[].
- * Input:
- *	flag	1: don't do semantic() because of dummy types
- *		2: don't change types in matchArg()
- * Output:
- *	dedtypes	deduced arguments
- * Return match level.
- */
-
-MATCH TemplateDeclaration::matchWithInstance(TemplateInstance *ti,
-	Objects *dedtypes, int flag)
-{   MATCH m;
-    int dedtypes_dim = dedtypes->dim;
-
-#define LOGM 0
-#if LOGM
-    printf("\n+TemplateDeclaration::matchWithInstance(this = %s, ti = %s, flag = %d)\n", toChars(), ti->toChars(), flag);
-#endif
-
-#if 0
-    printf("dedtypes->dim = %d, parameters->dim = %d\n", dedtypes_dim, parameters->dim);
-    if (ti->tiargs->dim)
-	printf("ti->tiargs->dim = %d, [0] = %p\n",
-	    ti->tiargs->dim,
-	    ti->tiargs->data[0]);
-#endif
-    dedtypes->zero();
-
-    int parameters_dim = parameters->dim;
-    int variadic = isVariadic() != NULL;
-
-    // If more arguments than parameters, no match
-    if (ti->tiargs->dim > parameters_dim && !variadic)
-    {
-#if LOGM
-	printf(" no match: more arguments than parameters\n");
-#endif
-	return MATCHnomatch;
-    }
-
-    assert(dedtypes_dim == parameters_dim);
-    assert(dedtypes_dim >= ti->tiargs->dim || variadic);
-
-    // Set up scope for parameters
-    assert((size_t)scope > 0x10000);
-    ScopeDsymbol *paramsym = new ScopeDsymbol();
-    paramsym->parent = scope->parent;
-    Scope *paramscope = scope->push(paramsym);
-
-    // Attempt type deduction
-    m = MATCHexact;
-    for (int i = 0; i < dedtypes_dim; i++)
-    {	MATCH m2;
-	TemplateParameter *tp = (TemplateParameter *)parameters->data[i];
-	Declaration *sparam;
-
-	//printf("\targument [%d]\n", i);
-#if LOGM
-	//printf("\targument [%d] is %s\n", i, oarg ? oarg->toChars() : "null");
-	TemplateTypeParameter *ttp = tp->isTemplateTypeParameter();
-	if (ttp)
-	    printf("\tparameter[%d] is %s : %s\n", i, tp->ident->toChars(), ttp->specType ? ttp->specType->toChars() : "");
-#endif
-
-#if DMDV1
-	m2 = tp->matchArg(paramscope, ti->tiargs, i, parameters, dedtypes, &sparam);
-#else
-	m2 = tp->matchArg(paramscope, ti->tiargs, i, parameters, dedtypes, &sparam, (flag & 2) ? 1 : 0);
-
-#endif
-	//printf("\tm2 = %d\n", m2);
-
-	if (m2 == MATCHnomatch)
-	{
-#if 0
-	    printf("\tmatchArg() for parameter %i failed\n", i);
-#endif
-	    goto Lnomatch;
-	}
-
-	if (m2 < m)
-	    m = m2;
-
-	if (!flag)
-	    sparam->semantic(paramscope);
-	if (!paramscope->insert(sparam))
-	    goto Lnomatch;
-    }
-
-    if (!flag)
-    {
-	/* Any parameter left without a type gets the type of
-	 * its corresponding arg
-	 */
-	for (int i = 0; i < dedtypes_dim; i++)
-	{
-	    if (!dedtypes->data[i])
-	    {   assert(i < ti->tiargs->dim);
-		dedtypes->data[i] = ti->tiargs->data[i];
-	    }
-	}
-    }
-
-    if (m && constraint && !(flag & 1))
-    {	/* Check to see if constraint is satisfied.
-	 */
-	Expression *e = constraint->syntaxCopy();
-	paramscope->flags |= SCOPEstaticif;
-	e = e->semantic(paramscope);
-	e = e->optimize(WANTvalue | WANTinterpret);
-        if (e->isBool(TRUE))
-            ;
-        else if (e->isBool(FALSE))
-            goto Lnomatch;
-        else
-        {
-            e->error("constraint %s is not constant or does not evaluate to a bool", e->toChars());
-        }
-    }
-
-#if LOGM
-    // Print out the results
-    printf("--------------------------\n");
-    printf("template %s\n", toChars());
-    printf("instance %s\n", ti->toChars());
-    if (m)
-    {
-	for (int i = 0; i < dedtypes_dim; i++)
-	{
-	    TemplateParameter *tp = (TemplateParameter *)parameters->data[i];
-	    Object *oarg;
-
-	    printf(" [%d]", i);
-
-	    if (i < ti->tiargs->dim)
-		oarg = (Object *)ti->tiargs->data[i];
-	    else
-		oarg = NULL;
-	    tp->print(oarg, (Object *)dedtypes->data[i]);
-	}
-    }
-    else
-	goto Lnomatch;
-#endif
-
-#if LOGM
-    printf(" match = %d\n", m);
-#endif
-    goto Lret;
-
-Lnomatch:
-#if LOGM
-    printf(" no match\n");
-#endif
-    m = MATCHnomatch;
-
-Lret:
-    paramscope->pop();
-#if LOGM
-    printf("-TemplateDeclaration::matchWithInstance(this = %p, ti = %p) = %d\n", this, ti, m);
-#endif
-    return m;
-}
-
-/********************************************
- * Determine partial specialization order of 'this' vs td2.
- * Returns:
- *	match	this is at least as specialized as td2
- *	0	td2 is more specialized than this
- */
-
-MATCH TemplateDeclaration::leastAsSpecialized(TemplateDeclaration *td2)
-{
-    /* This works by taking the template parameters to this template
-     * declaration and feeding them to td2 as if it were a template
-     * instance.
-     * If it works, then this template is at least as specialized
-     * as td2.
-     */
-
-    TemplateInstance ti(0, ident);	// create dummy template instance
-    Objects dedtypes;
-
-#define LOG_LEASTAS	0
-
-#if LOG_LEASTAS
-    printf("%s.leastAsSpecialized(%s)\n", toChars(), td2->toChars());
-#endif
-
-    // Set type arguments to dummy template instance to be types
-    // generated from the parameters to this template declaration
-    ti.tiargs = new Objects();
-    ti.tiargs->setDim(parameters->dim);
-    for (int i = 0; i < ti.tiargs->dim; i++)
-    {
-	TemplateParameter *tp = (TemplateParameter *)parameters->data[i];
-
-	void *p = tp->dummyArg();
-	if (p)
-	    ti.tiargs->data[i] = p;
-	else
-	    ti.tiargs->setDim(i);
-    }
-
-    // Temporary Array to hold deduced types
-    //dedtypes.setDim(parameters->dim);
-    dedtypes.setDim(td2->parameters->dim);
-
-    // Attempt a type deduction
-    MATCH m = td2->matchWithInstance(&ti, &dedtypes, 1);
-    if (m)
-    {
-	/* A non-variadic template is more specialized than a
-	 * variadic one.
-	 */
-	if (isVariadic() && !td2->isVariadic())
-	    goto L1;
-
-#if LOG_LEASTAS
-	printf("  matches %d, so is least as specialized\n", m);
-#endif
-	return m;
-    }
-  L1:
-#if LOG_LEASTAS
-    printf("  doesn't match, so is not as specialized\n");
-#endif
-    return MATCHnomatch;
-}
-
-
-/*************************************************
- * Match function arguments against a specific template function.
- * Input:
- *	loc		instantiation location
- *	targsi		Expression/Type initial list of template arguments
- *	ethis		'this' argument if !NULL
- *	fargs		arguments to function
- * Output:
- *	dedargs		Expression/Type deduced template arguments
- * Returns:
- *	match level
- */
-
-MATCH TemplateDeclaration::deduceFunctionTemplateMatch(Loc loc, Objects *targsi,
-	Expression *ethis, Expressions *fargs,
-	Objects *dedargs)
-{
-    size_t i;
-    size_t nfparams;
-    size_t nfargs;
-    size_t nargsi;		// array size of targsi
-    int fptupindex = -1;
-    int tuple_dim = 0;
-    MATCH match = MATCHexact;
-    FuncDeclaration *fd = onemember->toAlias()->isFuncDeclaration();
-    TypeFunction *fdtype;		// type of fd
-    TemplateTupleParameter *tp;
-    Objects dedtypes;	// for T:T*, the dedargs is the T*, dedtypes is the T
-
-#if 0
-    printf("\nTemplateDeclaration::deduceFunctionTemplateMatch() %s\n", toChars());
-    for (i = 0; i < fargs->dim; i++)
-    {	Expression *e = (Expression *)fargs->data[i];
-	printf("\tfarg[%d] is %s, type is %s\n", i, e->toChars(), e->type->toChars());
-    }
-#endif
-
-    assert((size_t)scope > 0x10000);
-
-    dedargs->setDim(parameters->dim);
-    dedargs->zero();
-
-    dedtypes.setDim(parameters->dim);
-    dedtypes.zero();
-
-    // Set up scope for parameters
-    ScopeDsymbol *paramsym = new ScopeDsymbol();
-    paramsym->parent = scope->parent;
-    Scope *paramscope = scope->push(paramsym);
-
-    tp = isVariadic();
-
-    nargsi = 0;
-    if (targsi)
-    {	// Set initial template arguments
-
-	nargsi = targsi->dim;
-	if (nargsi > parameters->dim)
-	{   if (!tp)
-		goto Lnomatch;
-	    dedargs->setDim(nargsi);
-	    dedargs->zero();
-	}
-
-	memcpy(dedargs->data, targsi->data, nargsi * sizeof(*dedargs->data));
-
-	for (i = 0; i < nargsi; i++)
-	{   assert(i < parameters->dim);
-	    TemplateParameter *tp = (TemplateParameter *)parameters->data[i];
-	    MATCH m;
-	    Declaration *sparam;
-
-	    m = tp->matchArg(paramscope, dedargs, i, parameters, &dedtypes, &sparam);
-	    //printf("\tdeduceType m = %d\n", m);
-	    if (m == MATCHnomatch)
-		goto Lnomatch;
-	    if (m < match)
-		match = m;
-
-	    sparam->semantic(paramscope);
-	    if (!paramscope->insert(sparam))
-		goto Lnomatch;
-	}
-    }
-
-    assert(fd->type->ty == Tfunction);
-    fdtype = (TypeFunction *)fd->type;
-
-    nfparams = Argument::dim(fdtype->parameters); // number of function parameters
-    nfargs = fargs->dim;		// number of function arguments
-
-    /* Check for match of function arguments with variadic template
-     * parameter, such as:
-     *
-     * template Foo(T, A...) { void Foo(T t, A a); }
-     * void main() { Foo(1,2,3); }
-     */
-    if (tp)				// if variadic
-    {
-	if (nfparams == 0)		// if no function parameters
-	{
-	    Tuple *t = new Tuple();
-	    //printf("t = %p\n", t);
-	    dedargs->data[parameters->dim - 1] = (void *)t;
-	    goto L2;
-	}
-	else if (nfargs < nfparams - 1)
-	    goto L1;
-	else
-	{
-	    /* Figure out which of the function parameters matches
-	     * the tuple template parameter. Do this by matching
-	     * type identifiers.
-	     * Set the index of this function parameter to fptupindex.
-	     */
-	    for (fptupindex = 0; fptupindex < nfparams; fptupindex++)
-	    {
-		Argument *fparam = (Argument *)fdtype->parameters->data[fptupindex];
-		if (fparam->type->ty != Tident)
-		    continue;
-		TypeIdentifier *tid = (TypeIdentifier *)fparam->type;
-		if (!tp->ident->equals(tid->ident) || tid->idents.dim)
-		    continue;
-
-		if (fdtype->varargs)	// variadic function doesn't
-		    goto Lnomatch;	// go with variadic template
-
-		/* The types of the function arguments
-		 * now form the tuple argument.
-		 */
-		Tuple *t = new Tuple();
-		dedargs->data[parameters->dim - 1] = (void *)t;
-
-		tuple_dim = nfargs - (nfparams - 1);
-		t->objects.setDim(tuple_dim);
-		for (i = 0; i < tuple_dim; i++)
-		{   Expression *farg = (Expression *)fargs->data[fptupindex + i];
-		    t->objects.data[i] = (void *)farg->type;
-		}
-		goto L2;
-	    }
-	    fptupindex = -1;
-	}
-    }
-
-L1:
-    if (nfparams == nfargs)
-	;
-    else if (nfargs > nfparams)
-    {
-	if (fdtype->varargs == 0)
-	    goto Lnomatch;		// too many args, no match
-	match = MATCHconvert;		// match ... with a conversion
-    }
-
-L2:
-    // Match 'ethis' to any TemplateThisParameter's
-    if (ethis)
-    {
-	for (size_t i = 0; i < parameters->dim; i++)
-	{   TemplateParameter *tp = (TemplateParameter *)parameters->data[i];
-	    TemplateThisParameter *ttp = tp->isTemplateThisParameter();
-	    if (ttp)
-	    {	MATCH m;
-
-		Type *t = new TypeIdentifier(0, ttp->ident);
-		m = ethis->type->deduceType(scope, t, parameters, &dedtypes);
-		if (!m)
-		    goto Lnomatch;
-		if (m < match)
-		    match = m;		// pick worst match
-	    }
-	}
-    }
-
-    // Loop through the function parameters
-    for (i = 0; i < nfparams; i++)
-    {
-	/* Skip over function parameters which wound up
-	 * as part of a template tuple parameter.
-	 */
-	if (i == fptupindex)
-	{   if (fptupindex == nfparams - 1)
-		break;
-	    i += tuple_dim - 1;
-	    continue;
-	}
-
-	Argument *fparam = Argument::getNth(fdtype->parameters, i);
-
-	if (i >= nfargs)		// if not enough arguments
-	{
-	    if (fparam->defaultArg)
-	    {	/* Default arguments do not participate in template argument
-		 * deduction.
-		 */
-		goto Lmatch;
-	    }
-	}
-	else
-	{   Expression *farg = (Expression *)fargs->data[i];
-#if 0
-	    printf("\tfarg->type   = %s\n", farg->type->toChars());
-	    printf("\tfparam->type = %s\n", fparam->type->toChars());
-#endif
-	    MATCH m;
-	    //m = farg->type->toHeadMutable()->deduceType(scope, fparam->type, parameters, &dedtypes);
-	    m = farg->type->deduceType(scope, fparam->type, parameters, &dedtypes);
-	    //printf("\tdeduceType m = %d\n", m);
-
-	    /* If no match, see if there's a conversion to a delegate
-	     */
-	    if (!m && fparam->type->toBasetype()->ty == Tdelegate)
-	    {
-		TypeDelegate *td = (TypeDelegate *)fparam->type->toBasetype();
-		TypeFunction *tf = (TypeFunction *)td->next;
-
-		if (!tf->varargs && Argument::dim(tf->parameters) == 0)
-		{
-		    m = farg->type->deduceType(scope, tf->next, parameters, &dedtypes);
-		    if (!m && tf->next->toBasetype()->ty == Tvoid)
-			m = MATCHconvert;
-		}
-		//printf("\tm2 = %d\n", m);
-	    }
-
-	    if (m)
-	    {	if (m < match)
-		    match = m;		// pick worst match
-		continue;
-	    }
-	}
-
-	/* The following code for variadic arguments closely
-	 * matches TypeFunction::callMatch()
-	 */
-	if (!(fdtype->varargs == 2 && i + 1 == nfparams))
-	    goto Lnomatch;
-
-	/* Check for match with function parameter T...
-	 */
-	Type *tb = fparam->type->toBasetype();
-	switch (tb->ty)
-	{
-	    // Perhaps we can do better with this, see TypeFunction::callMatch()
-	    case Tsarray:
-	    {	TypeSArray *tsa = (TypeSArray *)tb;
-		integer_t sz = tsa->dim->toInteger();
-		if (sz != nfargs - i)
-		    goto Lnomatch;
-	    }
-	    case Tarray:
-	    {   TypeArray *ta = (TypeArray *)tb;
-		for (; i < nfargs; i++)
-		{
-		    Expression *arg = (Expression *)fargs->data[i];
-		    assert(arg);
-		    MATCH m;
-		    /* If lazy array of delegates,
-		     * convert arg(s) to delegate(s)
-		     */
-		    Type *tret = fparam->isLazyArray();
-		    if (tret)
-		    {
-			if (ta->next->equals(arg->type))
-			{   m = MATCHexact;
-			}
-			else
-			{
-			    m = arg->implicitConvTo(tret);
-			    if (m == MATCHnomatch)
-			    {
-				if (tret->toBasetype()->ty == Tvoid)
-				    m = MATCHconvert;
-			    }
-			}
-		    }
-		    else
-		    {
-			m = arg->type->deduceType(scope, ta->next, parameters, &dedtypes);
-			//m = arg->implicitConvTo(ta->next);
-		    }
-		    if (m == MATCHnomatch)
-			goto Lnomatch;
-		    if (m < match)
-			match = m;
-		}
-		goto Lmatch;
-	    }
-	    case Tclass:
-	    case Tident:
-		goto Lmatch;
-
-	    default:
-		goto Lnomatch;
-	}
-    }
-
-Lmatch:
-
-    /* Fill in any missing arguments with their defaults.
-     */
-    for (i = nargsi; i < dedargs->dim; i++)
-    {
-	TemplateParameter *tp = (TemplateParameter *)parameters->data[i];
-	//printf("tp[%d] = %s\n", i, tp->ident->toChars());
-	/* For T:T*, the dedargs is the T*, dedtypes is the T
-	 * But for function templates, we really need them to match
-	 */
-	Object *oarg = (Object *)dedargs->data[i];
-	Object *oded = (Object *)dedtypes.data[i];
-	//printf("1dedargs[%d] = %p, dedtypes[%d] = %p\n", i, oarg, i, oded);
-	if (!oarg)
-	{
-	    if (oded)
-	    {
-		if (tp->specialization())
-		{   /* The specialization can work as long as afterwards
-		     * the oded == oarg
-		     */
-		    Declaration *sparam;
-		    dedargs->data[i] = (void *)oded;
-		    MATCH m2 = tp->matchArg(paramscope, dedargs, i, parameters, &dedtypes, &sparam, 0);
-		    //printf("m2 = %d\n", m2);
-		    if (!m2)
-			goto Lnomatch;
-		    if (m2 < match)
-			match = m2;		// pick worst match
-		    if (dedtypes.data[i] != oded)
-			error("specialization not allowed for deduced parameter %s", tp->ident->toChars());
-		}
-	    }
-	    else
-	    {	oded = tp->defaultArg(loc, paramscope);
-		if (!oded)
-		    goto Lnomatch;
-	    }
-	    declareParameter(paramscope, tp, oded);
-	    dedargs->data[i] = (void *)oded;
-	}
-    }
-
-    if (constraint)
-    {	/* Check to see if constraint is satisfied.
-	 */
-	Expression *e = constraint->syntaxCopy();
-	paramscope->flags |= SCOPEstaticif;
-	e = e->semantic(paramscope);
-	e = e->optimize(WANTvalue | WANTinterpret);
-        if (e->isBool(TRUE))
-            ;
-        else if (e->isBool(FALSE))
-            goto Lnomatch;
-        else
-        {
-            e->error("constraint %s is not constant or does not evaluate to a bool", e->toChars());
-        }
-    }
-
-
-#if 0
-    for (i = 0; i < dedargs->dim; i++)
-    {	Type *t = (Type *)dedargs->data[i];
-	printf("\tdedargs[%d] = %d, %s\n", i, t->dyncast(), t->toChars());
-    }
-#endif
-
-    paramscope->pop();
-    //printf("\tmatch %d\n", match);
-    return match;
-
-Lnomatch:
-    paramscope->pop();
-    //printf("\tnomatch\n");
-    return MATCHnomatch;
-}
-
-/**************************************************
- * Declare template parameter tp with value o, and install it in the scope sc.
- */
-
-void TemplateDeclaration::declareParameter(Scope *sc, TemplateParameter *tp, Object *o)
-{
-    //printf("TemplateDeclaration::declareParameter('%s', o = %p)\n", tp->ident->toChars(), o);
-
-    Type *targ = isType(o);
-    Expression *ea = isExpression(o);
-    Dsymbol *sa = isDsymbol(o);
-    Tuple *va = isTuple(o);
-
-    Dsymbol *s;
-
-    if (targ)
-    {
-	//printf("type %s\n", targ->toChars());
-	s = new AliasDeclaration(0, tp->ident, targ);
-    }
-    else if (sa)
-    {
-	//printf("Alias %s %s;\n", sa->ident->toChars(), tp->ident->toChars());
-	s = new AliasDeclaration(0, tp->ident, sa);
-    }
-    else if (ea)
-    {
-	// tdtypes.data[i] always matches ea here
-	Initializer *init = new ExpInitializer(loc, ea);
-	TemplateValueParameter *tvp = tp->isTemplateValueParameter();
-
-	Type *t = tvp ? tvp->valType : NULL;
-
-	VarDeclaration *v = new VarDeclaration(loc, t, tp->ident, init);
-	v->storage_class = STCmanifest;
-	s = v;
-    }
-    else if (va)
-    {
-	//printf("\ttuple\n");
-	s = new TupleDeclaration(loc, tp->ident, &va->objects);
-    }
-    else
-    {
-#ifdef DEBUG
-	o->print();
-#endif
-	assert(0);
-    }
-    if (!sc->insert(s))
-	error("declaration %s is already defined", tp->ident->toChars());
-    s->semantic(sc);
-}
-
-/**************************************
- * Determine if TemplateDeclaration is variadic.
- */
-
-TemplateTupleParameter *isVariadic(TemplateParameters *parameters)
-{   size_t dim = parameters->dim;
-    TemplateTupleParameter *tp = NULL;
-
-    if (dim)
-	tp = ((TemplateParameter *)parameters->data[dim - 1])->isTemplateTupleParameter();
-    return tp;
-}
-
-TemplateTupleParameter *TemplateDeclaration::isVariadic()
-{
-    return ::isVariadic(parameters);
-}
-
-/***********************************
- * We can overload templates.
- */
-
-int TemplateDeclaration::isOverloadable()
-{
-    return 1;
-}
-
-/*************************************************
- * Given function arguments, figure out which template function
- * to expand, and return that function.
- * If no match, give error message and return NULL.
- * Input:
- *	sc		instantiation scope
- *	loc		instantiation location
- *	targsi		initial list of template arguments
- *	ethis		if !NULL, the 'this' pointer argument
- *	fargs		arguments to function
- *	flags		1: do not issue error message on no match, just return NULL
- */
-
-FuncDeclaration *TemplateDeclaration::deduceFunctionTemplate(Scope *sc, Loc loc,
-	Objects *targsi, Expression *ethis, Expressions *fargs, int flags)
-{
-    MATCH m_best = MATCHnomatch;
-    TemplateDeclaration *td_ambig = NULL;
-    TemplateDeclaration *td_best = NULL;
-    Objects *tdargs = new Objects();
-    TemplateInstance *ti;
-    FuncDeclaration *fd;
-
-#if 0
-    printf("TemplateDeclaration::deduceFunctionTemplate() %s\n", toChars());
-    printf("    targsi:\n");
-    if (targsi)
-    {	for (int i = 0; i < targsi->dim; i++)
-	{   Object *arg = (Object *)targsi->data[i];
-	    printf("\t%s\n", arg->toChars());
-	}
-    }
-    printf("    fargs:\n");
-    for (int i = 0; i < fargs->dim; i++)
-    {	Expression *arg = (Expression *)fargs->data[i];
-	printf("\t%s %s\n", arg->type->toChars(), arg->toChars());
-	//printf("\tty = %d\n", arg->type->ty);
-    }
-#endif
-
-    for (TemplateDeclaration *td = this; td; td = td->overnext)
-    {
-	if (!td->scope)
-	{
-	    error("forward reference to template %s", td->toChars());
-	    goto Lerror;
-	}
-	if (!td->onemember || !td->onemember->toAlias()->isFuncDeclaration())
-	{
-	    error("is not a function template");
-	    goto Lerror;
-	}
-
-	MATCH m;
-	Objects dedargs;
-
-	m = td->deduceFunctionTemplateMatch(loc, targsi, ethis, fargs, &dedargs);
-	//printf("deduceFunctionTemplateMatch = %d\n", m);
-	if (!m)			// if no match
-	    continue;
-
-	if (m < m_best)
-	    goto Ltd_best;
-	if (m > m_best)
-	    goto Ltd;
-
-	{
-	// Disambiguate by picking the most specialized TemplateDeclaration
-	MATCH c1 = td->leastAsSpecialized(td_best);
-	MATCH c2 = td_best->leastAsSpecialized(td);
-	//printf("c1 = %d, c2 = %d\n", c1, c2);
-
-	if (c1 > c2)
-	    goto Ltd;
-	else if (c1 < c2)
-	    goto Ltd_best;
-	else
-	    goto Lambig;
-	}
-
-      Lambig:		// td_best and td are ambiguous
-	td_ambig = td;
-	continue;
-
-      Ltd_best:		// td_best is the best match so far
-	td_ambig = NULL;
-	continue;
-
-      Ltd:		// td is the new best match
-	td_ambig = NULL;
-	assert((size_t)td->scope > 0x10000);
-	td_best = td;
-	m_best = m;
-	tdargs->setDim(dedargs.dim);
-	memcpy(tdargs->data, dedargs.data, tdargs->dim * sizeof(void *));
-	continue;
-    }
-    if (!td_best)
-    {
-	if (!(flags & 1))
-	    error(loc, "does not match any function template declaration");
-	goto Lerror;
-    }
-    if (td_ambig)
-    {
-	error(loc, "matches more than one function template declaration:\n  %s\nand:\n  %s",
-		td_best->toChars(), td_ambig->toChars());
-    }
-
-    /* The best match is td_best with arguments tdargs.
-     * Now instantiate the template.
-     */
-    assert((size_t)td_best->scope > 0x10000);
-    ti = new TemplateInstance(loc, td_best, tdargs);
-    ti->semantic(sc);
-    fd = ti->toAlias()->isFuncDeclaration();
-    if (!fd)
-	goto Lerror;
-    return fd;
-
-  Lerror:
-    if (!(flags & 1))
-    {
-	HdrGenState hgs;
-
-	OutBuffer bufa;
-	Objects *args = targsi;
-	if (args)
-	{   for (int i = 0; i < args->dim; i++)
-	    {
-		if (i)
-		    bufa.writeByte(',');
-		Object *oarg = (Object *)args->data[i];
-		ObjectToCBuffer(&bufa, &hgs, oarg);
-	    }
-	}
-
-	OutBuffer buf;
-	argExpTypesToCBuffer(&buf, fargs, &hgs);
-
-	error(loc, "cannot deduce template function from argument types !(%s)(%s)",
-		bufa.toChars(), buf.toChars());
-    }
-    return NULL;
-}
-
-void TemplateDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{
-#if 0 // Should handle template functions
-    if (onemember && onemember->isFuncDeclaration())
-	buf->writestring("foo ");
-#endif
-    buf->writestring(kind());
-    buf->writeByte(' ');
-    buf->writestring(ident->toChars());
-    buf->writeByte('(');
-    for (int i = 0; i < parameters->dim; i++)
-    {
-	TemplateParameter *tp = (TemplateParameter *)parameters->data[i];
-	if (hgs->ddoc)
-	    tp = (TemplateParameter *)origParameters->data[i];
-	if (i)
-	    buf->writeByte(',');
-	tp->toCBuffer(buf, hgs);
-    }
-    buf->writeByte(')');
-
-    if (constraint)
-    {	buf->writestring(" if (");
-	constraint->toCBuffer(buf, hgs);
-	buf->writeByte(')');
-    }
-
-    if (hgs->hdrgen)
-    {
-	hgs->tpltMember++;
-	buf->writenl();
-	buf->writebyte('{');
-	buf->writenl();
-	for (int i = 0; i < members->dim; i++)
-	{
-	    Dsymbol *s = (Dsymbol *)members->data[i];
-	    s->toCBuffer(buf, hgs);
-	}
-	buf->writebyte('}');
-	buf->writenl();
-	hgs->tpltMember--;
-    }
-}
-
-
-char *TemplateDeclaration::toChars()
-{   OutBuffer buf;
-    HdrGenState hgs;
-
-    memset(&hgs, 0, sizeof(hgs));
-    buf.writestring(ident->toChars());
-    buf.writeByte('(');
-    for (int i = 0; i < parameters->dim; i++)
-    {
-	TemplateParameter *tp = (TemplateParameter *)parameters->data[i];
-	if (i)
-	    buf.writeByte(',');
-	tp->toCBuffer(&buf, &hgs);
-    }
-    buf.writeByte(')');
-
-    if (constraint)
-    {	buf.writestring(" if (");
-	constraint->toCBuffer(&buf, &hgs);
-	buf.writeByte(')');
-    }
-
-    buf.writeByte(0);
-    return (char *)buf.extractData();
-}
-
-/* ======================== Type ============================================ */
-
-/****
- * Given an identifier, figure out which TemplateParameter it is.
- * Return -1 if not found.
- */
-
-int templateIdentifierLookup(Identifier *id, TemplateParameters *parameters)
-{
-    for (size_t i = 0; i < parameters->dim; i++)
-    {   TemplateParameter *tp = (TemplateParameter *)parameters->data[i];
-
-	if (tp->ident->equals(id))
-	    return i;
-    }
-    return -1;
-}
-
-int templateParameterLookup(Type *tparam, TemplateParameters *parameters)
-{
-    assert(tparam->ty == Tident);
-    TypeIdentifier *tident = (TypeIdentifier *)tparam;
-    //printf("\ttident = '%s'\n", tident->toChars());
-    if (tident->idents.dim == 0)
-    {
-	return templateIdentifierLookup(tident->ident, parameters);
-    }
-    return -1;
-}
-
-/* These form the heart of template argument deduction.
- * Given 'this' being the type argument to the template instance,
- * it is matched against the template declaration parameter specialization
- * 'tparam' to determine the type to be used for the parameter.
- * Example:
- *	template Foo(T:T*)	// template declaration
- *	Foo!(int*)		// template instantiation
- * Input:
- *	this = int*
- *	tparam = T
- *	parameters = [ T:T* ]	// Array of TemplateParameter's
- * Output:
- *	dedtypes = [ int ]	// Array of Expression/Type's
- */
-
-MATCH Type::deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters,
-	Objects *dedtypes)
-{
-#if 0
-    printf("Type::deduceType()\n");
-    printf("\tthis   = %d, ", ty); print();
-    printf("\ttparam = %d, ", tparam->ty); tparam->print();
-#endif
-    if (!tparam)
-	goto Lnomatch;
-
-    if (this == tparam)
-	goto Lexact;
-
-    if (tparam->ty == Tident)
-    {
-	// Determine which parameter tparam is
-	int i = templateParameterLookup(tparam, parameters);
-	if (i == -1)
-	{
-	    if (!sc)
-		goto Lnomatch;
-
-	    /* Need a loc to go with the semantic routine.
-	     */
-	    Loc loc;
-	    if (parameters->dim)
-	    {
-		TemplateParameter *tp = (TemplateParameter *)parameters->data[0];
-		loc = tp->loc;
-	    }
-
-	    /* BUG: what if tparam is a template instance, that
-	     * has as an argument another Tident?
-	     */
-	    tparam = tparam->semantic(loc, sc);
-	    assert(tparam->ty != Tident);
-	    return deduceType(sc, tparam, parameters, dedtypes);
-	}
-
-	TemplateParameter *tp = (TemplateParameter *)parameters->data[i];
-
-	// Found the corresponding parameter tp
-	if (!tp->isTemplateTypeParameter())
-	    goto Lnomatch;
-	Type *tt = this;
-	Type *at = (Type *)dedtypes->data[i];
-
-	// 3*3 == 9 cases
-	if (tparam->isMutable())
-	{   // foo(U:U) T            => T
-	    // foo(U:U) const(T)     => const(T)
-	    // foo(U:U) invariant(T) => invariant(T)
-	    if (!at)
-	    {   dedtypes->data[i] = (void *)this;
-		goto Lexact;
-	    }
-	}
-	else if (mod == tparam->mod)
-	{   // foo(U:const(U))     const(T)     => T
-	    // foo(U:invariant(U)) invariant(T) => T
-	    tt = mutableOf();
-	    if (!at)
-	    {   dedtypes->data[i] = (void *)tt;
-		goto Lexact;
-	    }
-	}
-	else if (tparam->isConst())
-	{   // foo(U:const(U)) T            => T
-	    // foo(U:const(U)) invariant(T) => T
-	    tt = mutableOf();
-	    if (!at)
-	    {   dedtypes->data[i] = (void *)tt;
-		goto Lconst;
-	    }
-	}
-	else
-	{   // foo(U:invariant(U)) T        => nomatch
-	    // foo(U:invariant(U)) const(T) => nomatch
-	    if (!at)
-		goto Lnomatch;
-	}
-
-	if (tt->equals(at))
-	    goto Lexact;
-	else if (tt->ty == Tclass && at->ty == Tclass)
-	{
-	    return tt->implicitConvTo(at);
-	}
-	else if (tt->ty == Tsarray && at->ty == Tarray &&
-	    tt->nextOf()->implicitConvTo(at->nextOf()) >= MATCHconst)
-	{
-	    goto Lexact;
-	}
-	else
-	    goto Lnomatch;
-    }
-
-    if (ty != tparam->ty)
-	return implicitConvTo(tparam);
-//	goto Lnomatch;
-
-    if (nextOf())
-	return nextOf()->deduceType(sc, tparam->nextOf(), parameters, dedtypes);
-
-Lexact:
-    return MATCHexact;
-
-Lnomatch:
-    return MATCHnomatch;
-
-Lconst:
-    return MATCHconst;
-}
-
-MATCH TypeSArray::deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters,
-	Objects *dedtypes)
-{
-#if 0
-    printf("TypeSArray::deduceType()\n");
-    printf("\tthis   = %d, ", ty); print();
-    printf("\ttparam = %d, ", tparam->ty); tparam->print();
-#endif
-
-    // Extra check that array dimensions must match
-    if (tparam)
-    {
-	if (tparam->ty == Tsarray)
-	{
-	    TypeSArray *tp = (TypeSArray *)tparam;
-
-	    if (tp->dim->op == TOKvar &&
-		((VarExp *)tp->dim)->var->storage_class & STCtemplateparameter)
-	    {	int i = templateIdentifierLookup(((VarExp *)tp->dim)->var->ident, parameters);
-		// This code matches code in TypeInstance::deduceType()
-		if (i == -1)
-		    goto Lnomatch;
-		TemplateParameter *tp = (TemplateParameter *)parameters->data[i];
-		TemplateValueParameter *tvp = tp->isTemplateValueParameter();
-		if (!tvp)
-		    goto Lnomatch;
-		Expression *e = (Expression *)dedtypes->data[i];
-		if (e)
-		{
-		    if (!dim->equals(e))
-			goto Lnomatch;
-		}
-		else
-		{   Type *vt = tvp->valType->semantic(0, sc);
-		    MATCH m = (MATCH)dim->implicitConvTo(vt);
-		    if (!m)
-			goto Lnomatch;
-		    dedtypes->data[i] = dim;
-		}
-	    }
-	    else if (dim->toInteger() != tp->dim->toInteger())
-		return MATCHnomatch;
-	}
-	else if (tparam->ty == Taarray)
-	{
-	    TypeAArray *tp = (TypeAArray *)tparam;
-	    if (tp->index->ty == Tident)
-	    {	TypeIdentifier *tident = (TypeIdentifier *)tp->index;
-
-		if (tident->idents.dim == 0)
-		{   Identifier *id = tident->ident;
-
-		    for (size_t i = 0; i < parameters->dim; i++)
-		    {
-			TemplateParameter *tp = (TemplateParameter *)parameters->data[i];
-
-			if (tp->ident->equals(id))
-			{   // Found the corresponding template parameter
-			    TemplateValueParameter *tvp = tp->isTemplateValueParameter();
-			    if (!tvp || !tvp->valType->isintegral())
-				goto Lnomatch;
-
-			    if (dedtypes->data[i])
-			    {
-				if (!dim->equals((Object *)dedtypes->data[i]))
-				    goto Lnomatch;
-			    }
-			    else
-			    {	dedtypes->data[i] = (void *)dim;
-			    }
-			    return next->deduceType(sc, tparam->nextOf(), parameters, dedtypes);
-			}
-		    }
-		}
-	    }
-	}
-	else if (tparam->ty == Tarray)
-	{   MATCH m;
-
-	    m = next->deduceType(sc, tparam->nextOf(), parameters, dedtypes);
-	    if (m == MATCHexact)
-		m = MATCHconvert;
-	    return m;
-	}
-    }
-    return Type::deduceType(sc, tparam, parameters, dedtypes);
-
-  Lnomatch:
-    return MATCHnomatch;
-}
-
-MATCH TypeAArray::deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes)
-{
-#if 0
-    printf("TypeAArray::deduceType()\n");
-    printf("\tthis   = %d, ", ty); print();
-    printf("\ttparam = %d, ", tparam->ty); tparam->print();
-#endif
-
-    // Extra check that index type must match
-    if (tparam && tparam->ty == Taarray)
-    {
-	TypeAArray *tp = (TypeAArray *)tparam;
-	if (!index->deduceType(sc, tp->index, parameters, dedtypes))
-	{
-	    return MATCHnomatch;
-	}
-    }
-    return Type::deduceType(sc, tparam, parameters, dedtypes);
-}
-
-MATCH TypeFunction::deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes)
-{
-    //printf("TypeFunction::deduceType()\n");
-    //printf("\tthis   = %d, ", ty); print();
-    //printf("\ttparam = %d, ", tparam->ty); tparam->print();
-
-    // Extra check that function characteristics must match
-    if (tparam && tparam->ty == Tfunction)
-    {
-	TypeFunction *tp = (TypeFunction *)tparam;
-	if (varargs != tp->varargs ||
-	    linkage != tp->linkage)
-	    return MATCHnomatch;
-
-	size_t nfargs = Argument::dim(this->parameters);
-	size_t nfparams = Argument::dim(tp->parameters);
-
-	/* See if tuple match
-	 */
-	if (nfparams > 0 && nfargs >= nfparams - 1)
-	{
-	    /* 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];
-	    if (fparam->type->ty != Tident)
-		goto L1;
-	    TypeIdentifier *tid = (TypeIdentifier *)fparam->type;
-	    if (tid->idents.dim)
-		goto L1;
-
-	    /* Look through parameters to find tuple matching tid->ident
-	     */
-	    size_t tupi = 0;
-	    for (; 1; tupi++)
-	    {	if (tupi == parameters->dim)
-		    goto L1;
-		TemplateParameter *t = (TemplateParameter *)parameters->data[tupi];
-		TemplateTupleParameter *tup = t->isTemplateTupleParameter();
-		if (tup && tup->ident->equals(tid->ident))
-		    break;
-	    }
-
-	    /* The types of the function arguments [nfparams - 1 .. nfargs]
-	     * now form the tuple argument.
-	     */
-	    int tuple_dim = nfargs - (nfparams - 1);
-
-	    /* See if existing tuple, and whether it matches or not
-	     */
-	    Object *o = (Object *)dedtypes->data[tupi];
-	    if (o)
-	    {	// Existing deduced argument must be a tuple, and must match
-		Tuple *t = isTuple(o);
-		if (!t || t->objects.dim != tuple_dim)
-		    return MATCHnomatch;
-		for (size_t i = 0; i < tuple_dim; i++)
-		{   Argument *arg = Argument::getNth(this->parameters, nfparams - 1 + i);
-		    if (!arg->type->equals((Object *)t->objects.data[i]))
-			return MATCHnomatch;
-		}
-	    }
-	    else
-	    {	// Create new tuple
-		Tuple *t = new Tuple();
-		t->objects.setDim(tuple_dim);
-		for (size_t i = 0; i < tuple_dim; i++)
-		{   Argument *arg = Argument::getNth(this->parameters, nfparams - 1 + i);
-		    t->objects.data[i] = (void *)arg->type;
-		}
-		dedtypes->data[tupi] = (void *)t;
-	    }
-	    nfparams--;	// don't consider the last parameter for type deduction
-	    goto L2;
-	}
-
-    L1:
-	if (nfargs != nfparams)
-	    return MATCHnomatch;
-    L2:
-	for (size_t i = 0; i < nfparams; i++)
-	{
-	    Argument *a = Argument::getNth(this->parameters, i);
-	    Argument *ap = Argument::getNth(tp->parameters, i);
-	    if (a->storageClass != ap->storageClass ||
-		!a->type->deduceType(sc, ap->type, parameters, dedtypes))
-		return MATCHnomatch;
-	}
-    }
-    return Type::deduceType(sc, tparam, parameters, dedtypes);
-}
-
-MATCH TypeIdentifier::deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes)
-{
-    // Extra check
-    if (tparam && tparam->ty == Tident)
-    {
-	TypeIdentifier *tp = (TypeIdentifier *)tparam;
-
-	for (int i = 0; i < idents.dim; i++)
-	{
-	    Identifier *id1 = (Identifier *)idents.data[i];
-	    Identifier *id2 = (Identifier *)tp->idents.data[i];
-
-	    if (!id1->equals(id2))
-		return MATCHnomatch;
-	}
-    }
-    return Type::deduceType(sc, tparam, parameters, dedtypes);
-}
-
-MATCH TypeInstance::deduceType(Scope *sc,
-	Type *tparam, TemplateParameters *parameters,
-	Objects *dedtypes)
-{
-    //printf("TypeInstance::deduceType(tparam = %s) %s\n", tparam->toChars(), toChars());
-    //printf("\ttparam = %d, ", tparam->ty); tparam->print();
-
-    // Extra check
-    if (tparam && tparam->ty == Tinstance)
-    {
-	TypeInstance *tp = (TypeInstance *)tparam;
-
-	//printf("tempinst->tempdecl = %p\n", tempinst->tempdecl);
-	//printf("tp->tempinst->tempdecl = %p\n", tp->tempinst->tempdecl);
-	if (!tp->tempinst->tempdecl)
-	{   //printf("tp->tempinst->name = '%s'\n", tp->tempinst->name->toChars());
-	    if (!tp->tempinst->name->equals(tempinst->name))
-	    {
-		/* Handle case of:
-		 *  template Foo(T : sa!(T), alias sa)
-		 */
-		int i = templateIdentifierLookup(tp->tempinst->name, parameters);
-		if (i == -1)
-		{   /* Didn't find it as a parameter identifier. Try looking
-		     * it up and seeing if is an alias. See Bugzilla 1454
-		     */
-		    Dsymbol *s = tempinst->tempdecl->scope->search(0, tp->tempinst->name, NULL);
-		    if (s)
-		    {
-			s = s->toAlias();
-			TemplateDeclaration *td = s->isTemplateDeclaration();
-			if (td && td == tempinst->tempdecl)
-			    goto L2;
-		    }
-		    goto Lnomatch;
-		}
-		TemplateParameter *tpx = (TemplateParameter *)parameters->data[i];
-		// This logic duplicates tpx->matchArg()
-		TemplateAliasParameter *ta = tpx->isTemplateAliasParameter();
-		if (!ta)
-		    goto Lnomatch;
-		Object *sa = tempinst->tempdecl;
-		if (!sa)
-		    goto Lnomatch;
-		if (ta->specAlias && sa != ta->specAlias)
-		    goto Lnomatch;
-		if (dedtypes->data[i])
-		{   // Must match already deduced symbol
-		    Object *s = (Object *)dedtypes->data[i];
-
-		    if (s != sa)
-			goto Lnomatch;
-		}
-		dedtypes->data[i] = sa;
-	    }
-	}
-	else if (tempinst->tempdecl != tp->tempinst->tempdecl)
-	    goto Lnomatch;
-
-      L2:
-	if (tempinst->tiargs->dim != tp->tempinst->tiargs->dim)
-	    goto Lnomatch;
-
-	for (int i = 0; i < tempinst->tiargs->dim; i++)
-	{
-	    //printf("\ttest: tempinst->tiargs[%d]\n", i);
-	    int j;
-	    Object *o1 = (Object *)tempinst->tiargs->data[i];
-	    Object *o2 = (Object *)tp->tempinst->tiargs->data[i];
-
-	    Type *t1 = isType(o1);
-	    Type *t2 = isType(o2);
-
-	    Expression *e1 = isExpression(o1);
-	    Expression *e2 = isExpression(o2);
-
-#if 0
-	    if (t1)	printf("t1 = %s\n", t1->toChars());
-	    if (t2)	printf("t2 = %s\n", t2->toChars());
-	    if (e1)	printf("e1 = %s\n", e1->toChars());
-	    if (e2)	printf("e2 = %s\n", e2->toChars());
-#endif
-
-	    if (t1 && t2)
-	    {
-		if (!t1->deduceType(sc, t2, parameters, dedtypes))
-		    goto Lnomatch;
-	    }
-	    else if (e1 && e2)
-	    {
-		if (!e1->equals(e2))
-		{   if (e2->op == TOKvar)
-		    {
-			/*
-			 * (T:Number!(e2), int e2)
-			 */
-			j = templateIdentifierLookup(((VarExp *)e2)->var->ident, parameters);
-			goto L1;
-		    }
-		    goto Lnomatch;
-		}
-	    }
-	    else if (e1 && t2 && t2->ty == Tident)
-	    {
-		j = templateParameterLookup(t2, parameters);
-	    L1:
-		if (j == -1)
-		    goto Lnomatch;
-		TemplateParameter *tp = (TemplateParameter *)parameters->data[j];
-		// BUG: use tp->matchArg() instead of the following
-		TemplateValueParameter *tv = tp->isTemplateValueParameter();
-		if (!tv)
-		    goto Lnomatch;
-		Expression *e = (Expression *)dedtypes->data[j];
-		if (e)
-		{
-		    if (!e1->equals(e))
-			goto Lnomatch;
-		}
-		else
-		{   Type *vt = tv->valType->semantic(0, sc);
-		    MATCH m = (MATCH)e1->implicitConvTo(vt);
-		    if (!m)
-			goto Lnomatch;
-		    dedtypes->data[j] = e1;
-		}
-	    }
-	    // BUG: Need to handle alias and tuple parameters
-	    else
-		goto Lnomatch;
-	}
-    }
-    return Type::deduceType(sc, tparam, parameters, dedtypes);
-
-Lnomatch:
-    return MATCHnomatch;
-}
-
-MATCH TypeStruct::deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes)
-{
-    //printf("TypeStruct::deduceType()\n");
-    //printf("\tthis->parent   = %s, ", sym->parent->toChars()); print();
-    //printf("\ttparam = %d, ", tparam->ty); tparam->print();
-
-    /* If this struct is a template struct, and we're matching
-     * it against a template instance, convert the struct type
-     * to a template instance, too, and try again.
-     */
-    TemplateInstance *ti = sym->parent->isTemplateInstance();
-
-    if (tparam && tparam->ty == Tinstance)
-    {
-	if (ti && ti->toAlias() == sym)
-	{
-	    TypeInstance *t = new TypeInstance(0, ti);
-	    return t->deduceType(sc, tparam, parameters, dedtypes);
-	}
-
-	/* Match things like:
-	 *  S!(T).foo
-	 */
-	TypeInstance *tpi = (TypeInstance *)tparam;
-	if (tpi->idents.dim)
-	{   Identifier *id = (Identifier *)tpi->idents.data[tpi->idents.dim - 1];
-	    if (id->dyncast() == DYNCAST_IDENTIFIER && sym->ident->equals(id))
-	    {
-		Type *tparent = sym->parent->getType();
-		if (tparent)
-		{
-		    /* Slice off the .foo in S!(T).foo
-		     */
-		    tpi->idents.dim--;
-		    MATCH m = tparent->deduceType(sc, tpi, parameters, dedtypes);
-		    tpi->idents.dim++;
-		    return m;
-		}
-	    }
-	}
-    }
-
-    // Extra check
-    if (tparam && tparam->ty == Tstruct)
-    {
-	TypeStruct *tp = (TypeStruct *)tparam;
-
-	if (sym != tp->sym)
-	    return MATCHnomatch;
-    }
-    return Type::deduceType(sc, tparam, parameters, dedtypes);
-}
-
-MATCH TypeEnum::deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes)
-{
-    // Extra check
-    if (tparam && tparam->ty == Tenum)
-    {
-	TypeEnum *tp = (TypeEnum *)tparam;
-
-	if (sym != tp->sym)
-	    return MATCHnomatch;
-    }
-    return Type::deduceType(sc, tparam, parameters, dedtypes);
-}
-
-MATCH TypeTypedef::deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes)
-{
-    // Extra check
-    if (tparam && tparam->ty == Ttypedef)
-    {
-	TypeTypedef *tp = (TypeTypedef *)tparam;
-
-	if (sym != tp->sym)
-	    return MATCHnomatch;
-    }
-    return Type::deduceType(sc, tparam, parameters, dedtypes);
-}
-
-MATCH TypeClass::deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes)
-{
-    //printf("TypeClass::deduceType(this = %s)\n", toChars());
-
-    /* If this class is a template class, and we're matching
-     * it against a template instance, convert the class type
-     * to a template instance, too, and try again.
-     */
-    TemplateInstance *ti = sym->parent->isTemplateInstance();
-
-    if (tparam && tparam->ty == Tinstance)
-    {
-	if (ti && ti->toAlias() == sym)
-	{
-	    TypeInstance *t = new TypeInstance(0, ti);
-	    return t->deduceType(sc, tparam, parameters, dedtypes);
-	}
-
-	/* Match things like:
-	 *  S!(T).foo
-	 */
-	TypeInstance *tpi = (TypeInstance *)tparam;
-	if (tpi->idents.dim)
-	{   Identifier *id = (Identifier *)tpi->idents.data[tpi->idents.dim - 1];
-	    if (id->dyncast() == DYNCAST_IDENTIFIER && sym->ident->equals(id))
-	    {
-		Type *tparent = sym->parent->getType();
-		if (tparent)
-		{
-		    /* Slice off the .foo in S!(T).foo
-		     */
-		    tpi->idents.dim--;
-		    MATCH m = tparent->deduceType(sc, tpi, parameters, dedtypes);
-		    tpi->idents.dim++;
-		    return m;
-		}
-	    }
-	}
-    }
-
-    // Extra check
-    if (tparam && tparam->ty == Tclass)
-    {
-	TypeClass *tp = (TypeClass *)tparam;
-
-	//printf("\t%d\n", (MATCH) implicitConvTo(tp));
-	return implicitConvTo(tp);
-    }
-    return Type::deduceType(sc, tparam, parameters, dedtypes);
-}
-
-/* ======================== TemplateParameter =============================== */
-
-TemplateParameter::TemplateParameter(Loc loc, Identifier *ident)
-{
-    this->loc = loc;
-    this->ident = ident;
-    this->sparam = NULL;
-}
-
-TemplateTypeParameter  *TemplateParameter::isTemplateTypeParameter()
-{
-    return NULL;
-}
-
-TemplateValueParameter *TemplateParameter::isTemplateValueParameter()
-{
-    return NULL;
-}
-
-TemplateAliasParameter *TemplateParameter::isTemplateAliasParameter()
-{
-    return NULL;
-}
-
-TemplateTupleParameter *TemplateParameter::isTemplateTupleParameter()
-{
-    return NULL;
-}
-
-#if DMDV2
-TemplateThisParameter  *TemplateParameter::isTemplateThisParameter()
-{
-    return NULL;
-}
-#endif
-
-/* ======================== TemplateTypeParameter =========================== */
-
-// type-parameter
-
-TemplateTypeParameter::TemplateTypeParameter(Loc loc, Identifier *ident, Type *specType,
-	Type *defaultType)
-    : TemplateParameter(loc, ident)
-{
-    this->ident = ident;
-    this->specType = specType;
-    this->defaultType = defaultType;
-}
-
-TemplateTypeParameter  *TemplateTypeParameter::isTemplateTypeParameter()
-{
-    return this;
-}
-
-TemplateParameter *TemplateTypeParameter::syntaxCopy()
-{
-    TemplateTypeParameter *tp = new TemplateTypeParameter(loc, ident, specType, defaultType);
-    if (tp->specType)
-	tp->specType = specType->syntaxCopy();
-    if (defaultType)
-	tp->defaultType = defaultType->syntaxCopy();
-    return tp;
-}
-
-void TemplateTypeParameter::declareParameter(Scope *sc)
-{
-    //printf("TemplateTypeParameter::declareParameter('%s')\n", ident->toChars());
-    TypeIdentifier *ti = new TypeIdentifier(loc, ident);
-    sparam = new AliasDeclaration(loc, ident, ti);
-    if (!sc->insert(sparam))
-	error(loc, "parameter '%s' multiply defined", ident->toChars());
-}
-
-void TemplateTypeParameter::semantic(Scope *sc)
-{
-    //printf("TemplateTypeParameter::semantic('%s')\n", ident->toChars());
-    if (specType)
-    {
-	specType = specType->semantic(loc, sc);
-    }
-#if 0 // Don't do semantic() until instantiation
-    if (defaultType)
-    {
-	defaultType = defaultType->semantic(loc, sc);
-    }
-#endif
-}
-
-/****************************************
- * Determine if two TemplateParameters are the same
- * as far as TemplateDeclaration overloading goes.
- * Returns:
- *	1	match
- *	0	no match
- */
-
-int TemplateTypeParameter::overloadMatch(TemplateParameter *tp)
-{
-    TemplateTypeParameter *ttp = tp->isTemplateTypeParameter();
-
-    if (ttp)
-    {
-	if (specType != ttp->specType)
-	    goto Lnomatch;
-
-	if (specType && !specType->equals(ttp->specType))
-	    goto Lnomatch;
-
-	return 1;			// match
-    }
-
-Lnomatch:
-    return 0;
-}
-
-/*******************************************
- * Match to a particular TemplateParameter.
- * Input:
- *	i		i'th argument
- *	tiargs[]	actual arguments to template instance
- *	parameters[]	template parameters
- *	dedtypes[]	deduced arguments to template instance
- *	*psparam	set to symbol declared and initialized to dedtypes[i]
- *	flags		1: don't do 'toHeadMutable()'
- */
-
-MATCH TemplateTypeParameter::matchArg(Scope *sc, Objects *tiargs,
-	int i, TemplateParameters *parameters, Objects *dedtypes,
-	Declaration **psparam, int flags)
-{
-    //printf("TemplateTypeParameter::matchArg()\n");
-    Type *t;
-    Object *oarg;
-    MATCH m = MATCHexact;
-    Type *ta;
-
-    if (i < tiargs->dim)
-	oarg = (Object *)tiargs->data[i];
-    else
-    {	// Get default argument instead
-	oarg = defaultArg(loc, sc);
-	if (!oarg)
-	{   assert(i < dedtypes->dim);
-	    // It might have already been deduced
-	    oarg = (Object *)dedtypes->data[i];
-	    if (!oarg)
-	    {
-		goto Lnomatch;
-	    }
-	    flags |= 1;		// already deduced, so don't to toHeadMutable()
-	}
-    }
-
-    ta = isType(oarg);
-    if (!ta)
-    {
-	//printf("%s %p %p %p\n", oarg->toChars(), isExpression(oarg), isDsymbol(oarg), isTuple(oarg));
-	goto Lnomatch;
-    }
-    //printf("ta is %s\n", ta->toChars());
-
-    t = (Type *)dedtypes->data[i];
-
-    if (specType)
-    {
-	//printf("\tcalling deduceType(): ta is %s, specType is %s\n", ta->toChars(), specType->toChars());
-	MATCH m2 = ta->deduceType(sc, specType, parameters, dedtypes);
-	if (m2 == MATCHnomatch)
-	{   //printf("\tfailed deduceType\n");
-	    goto Lnomatch;
-	}
-
-	if (m2 < m)
-	    m = m2;
-	t = (Type *)dedtypes->data[i];
-    }
-    else
-    {
-	// So that matches with specializations are better
-	m = MATCHconvert;
-
-	/* This is so that:
-	 *   template Foo(T), Foo!(const int), => ta == int
-	 */
-//	if (!(flags & 1))
-//	    ta = ta->toHeadMutable();
-
-	if (t)
-	{   // Must match already deduced type
-
-	    m = MATCHexact;
-	    if (!t->equals(ta))
-	    {	//printf("t = %s ta = %s\n", t->toChars(), ta->toChars());
-		goto Lnomatch;
-	    }
-	}
-    }
-
-    if (!t)
-    {
-	dedtypes->data[i] = ta;
-	t = ta;
-    }
-    *psparam = new AliasDeclaration(loc, ident, t);
-    //printf("\tm = %d\n", m);
-    return m;
-
-Lnomatch:
-    *psparam = NULL;
-    //printf("\tm = %d\n", MATCHnomatch);
-    return MATCHnomatch;
-}
-
-
-void TemplateTypeParameter::print(Object *oarg, Object *oded)
-{
-    printf(" %s\n", ident->toChars());
-
-    Type *t  = isType(oarg);
-    Type *ta = isType(oded);
-
-    assert(ta);
-
-    if (specType)
-	printf("\tSpecialization: %s\n", specType->toChars());
-    if (defaultType)
-	printf("\tDefault:        %s\n", defaultType->toChars());
-    printf("\tArgument:       %s\n", t ? t->toChars() : "NULL");
-    printf("\tDeduced Type:   %s\n", ta->toChars());
-}
-
-
-void TemplateTypeParameter::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{
-    buf->writestring(ident->toChars());
-    if (specType)
-    {
-	buf->writestring(" : ");
-	specType->toCBuffer(buf, NULL, hgs);
-    }
-    if (defaultType)
-    {
-	buf->writestring(" = ");
-	defaultType->toCBuffer(buf, NULL, hgs);
-    }
-}
-
-
-void *TemplateTypeParameter::dummyArg()
-{   Type *t;
-
-    if (specType)
-	t = specType;
-    else
-    {   // Use this for alias-parameter's too (?)
-	t = new TypeIdentifier(loc, ident);
-    }
-    return (void *)t;
-}
-
-
-Object *TemplateTypeParameter::specialization()
-{
-    return specType;
-}
-
-
-Object *TemplateTypeParameter::defaultArg(Loc loc, Scope *sc)
-{
-    Type *t;
-
-    t = defaultType;
-    if (t)
-    {
-	t = t->syntaxCopy();
-	t = t->semantic(loc, sc);
-    }
-    return t;
-}
-
-/* ======================== TemplateThisParameter =========================== */
-
-#if DMDV2
-// this-parameter
-
-TemplateThisParameter::TemplateThisParameter(Loc loc, Identifier *ident,
-	Type *specType,
-	Type *defaultType)
-    : TemplateTypeParameter(loc, ident, specType, defaultType)
-{
-}
-
-TemplateThisParameter  *TemplateThisParameter::isTemplateThisParameter()
-{
-    return this;
-}
-
-TemplateParameter *TemplateThisParameter::syntaxCopy()
-{
-    TemplateThisParameter *tp = new TemplateThisParameter(loc, ident, specType, defaultType);
-    if (tp->specType)
-	tp->specType = specType->syntaxCopy();
-    if (defaultType)
-	tp->defaultType = defaultType->syntaxCopy();
-    return tp;
-}
-
-void TemplateThisParameter::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{
-    buf->writestring("this ");
-    TemplateTypeParameter::toCBuffer(buf, hgs);
-}
-#endif
-
-/* ======================== TemplateAliasParameter ========================== */
-
-// alias-parameter
-
-Dsymbol *TemplateAliasParameter::sdummy = NULL;
-
-TemplateAliasParameter::TemplateAliasParameter(Loc loc, Identifier *ident,
-	Type *specType, Object *specAlias, Object *defaultAlias)
-    : TemplateParameter(loc, ident)
-{
-    this->ident = ident;
-    this->specType = specType;
-    this->specAlias = specAlias;
-    this->defaultAlias = defaultAlias;
-}
-
-TemplateAliasParameter *TemplateAliasParameter::isTemplateAliasParameter()
-{
-    return this;
-}
-
-TemplateParameter *TemplateAliasParameter::syntaxCopy()
-{
-    TemplateAliasParameter *tp = new TemplateAliasParameter(loc, ident, specType, specAlias, defaultAlias);
-    if (tp->specType)
-	tp->specType = specType->syntaxCopy();
-    tp->specAlias = objectSyntaxCopy(specAlias);
-    tp->defaultAlias = objectSyntaxCopy(defaultAlias);
-    return tp;
-}
-
-void TemplateAliasParameter::declareParameter(Scope *sc)
-{
-    TypeIdentifier *ti = new TypeIdentifier(loc, ident);
-    sparam = new AliasDeclaration(loc, ident, ti);
-    if (!sc->insert(sparam))
-	error(loc, "parameter '%s' multiply defined", ident->toChars());
-}
-
-Object *aliasParameterSemantic(Loc loc, Scope *sc, Object *o)
-{
-    if (o)
-    {
-	Expression *ea = isExpression(o);
-	Type *ta = isType(o);
-	if (ta)
-	{   Dsymbol *s = ta->toDsymbol(sc);
-	    if (s)
-		o = s;
-	    else
-		o = ta->semantic(loc, sc);
-	}
-	else if (ea)
-	{
-	    ea = ea->semantic(sc);
-	    o = ea->optimize(WANTvalue | WANTinterpret);
-	}
-    }
-    return o;
-}
-
-void TemplateAliasParameter::semantic(Scope *sc)
-{
-    if (specType)
-    {
-	specType = specType->semantic(loc, sc);
-    }
-    specAlias = aliasParameterSemantic(loc, sc, specAlias);
-#if 0 // Don't do semantic() until instantiation
-    if (defaultAlias)
-	defaultAlias = defaultAlias->semantic(loc, sc);
-#endif
-}
-
-int TemplateAliasParameter::overloadMatch(TemplateParameter *tp)
-{
-    TemplateAliasParameter *tap = tp->isTemplateAliasParameter();
-
-    if (tap)
-    {
-	if (specAlias != tap->specAlias)
-	    goto Lnomatch;
-
-	return 1;			// match
-    }
-
-Lnomatch:
-    return 0;
-}
-
-MATCH TemplateAliasParameter::matchArg(Scope *sc,
-	Objects *tiargs, int i, TemplateParameters *parameters,
-	Objects *dedtypes,
-	Declaration **psparam, int flags)
-{
-    Object *sa;
-    Object *oarg;
-    Expression *ea;
-    Dsymbol *s;
-
-    //printf("TemplateAliasParameter::matchArg()\n");
-
-    if (i < tiargs->dim)
-	oarg = (Object *)tiargs->data[i];
-    else
-    {	// Get default argument instead
-	oarg = defaultArg(loc, sc);
-	if (!oarg)
-	{   assert(i < dedtypes->dim);
-	    // It might have already been deduced
-	    oarg = (Object *)dedtypes->data[i];
-	    if (!oarg)
-		goto Lnomatch;
-	}
-    }
-
-    sa = getDsymbol(oarg);
-    if (sa)
-    {
-	/* specType means the alias must be a declaration with a type
-	 * that matches specType.
-	 */
-	if (specType)
-	{   Declaration *d = ((Dsymbol *)sa)->isDeclaration();
-	    if (!d)
-		goto Lnomatch;
-	    if (!d->type->equals(specType))
-		goto Lnomatch;
-	}
-    }
-    else
-    {
-	sa = oarg;
-	ea = isExpression(oarg);
-	if (ea)
-	{   if (specType)
-	    {
-		if (!ea->type->equals(specType))
-		    goto Lnomatch;
-	    }
-	}
-	else
-	    goto Lnomatch;
-    }
-
-    if (specAlias)
-    {
-	if (sa == sdummy)
-	    goto Lnomatch;
-	if (sa != specAlias)
-	    goto Lnomatch;
-    }
-    else if (dedtypes->data[i])
-    {   // Must match already deduced symbol
-	Object *s = (Object *)dedtypes->data[i];
-
-	if (!sa || s != sa)
-	    goto Lnomatch;
-    }
-    dedtypes->data[i] = sa;
-
-    s = isDsymbol(sa);
-    if (s)
-	*psparam = new AliasDeclaration(loc, ident, s);
-    else
-    {
-	assert(ea);
-
-        // Declare manifest constant
-        Initializer *init = new ExpInitializer(loc, ea);
-        VarDeclaration *v = new VarDeclaration(loc, NULL, ident, init);
-        v->storage_class = STCmanifest;
-        v->semantic(sc);
-	*psparam = v;
-    }
-    return MATCHexact;
-
-Lnomatch:
-    *psparam = NULL;
-    return MATCHnomatch;
-}
-
-
-void TemplateAliasParameter::print(Object *oarg, Object *oded)
-{
-    printf(" %s\n", ident->toChars());
-
-    Dsymbol *sa = isDsymbol(oded);
-    assert(sa);
-
-    printf("\tArgument alias: %s\n", sa->toChars());
-}
-
-void TemplateAliasParameter::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{
-    buf->writestring("alias ");
-    if (specType)
-    {	HdrGenState hgs;
-	specType->toCBuffer(buf, ident, &hgs);
-    }
-    else
-	buf->writestring(ident->toChars());
-    if (specAlias)
-    {
-	buf->writestring(" : ");
-	ObjectToCBuffer(buf, hgs, specAlias);
-    }
-    if (defaultAlias)
-    {
-	buf->writestring(" = ");
-	ObjectToCBuffer(buf, hgs, defaultAlias);
-    }
-}
-
-
-void *TemplateAliasParameter::dummyArg()
-{   Object *s;
-
-    s = specAlias;
-    if (!s)
-    {
-	if (!sdummy)
-	    sdummy = new Dsymbol();
-	s = sdummy;
-    }
-    return (void*)s;
-}
-
-
-Object *TemplateAliasParameter::specialization()
-{
-    return specAlias;
-}
-
-
-Object *TemplateAliasParameter::defaultArg(Loc loc, Scope *sc)
-{
-    Object *o = aliasParameterSemantic(loc, sc, defaultAlias);
-    return o;
-}
-
-/* ======================== TemplateValueParameter ========================== */
-
-// value-parameter
-
-Expression *TemplateValueParameter::edummy = NULL;
-
-TemplateValueParameter::TemplateValueParameter(Loc loc, Identifier *ident, Type *valType,
-	Expression *specValue, Expression *defaultValue)
-    : TemplateParameter(loc, ident)
-{
-    this->ident = ident;
-    this->valType = valType;
-    this->specValue = specValue;
-    this->defaultValue = defaultValue;
-}
-
-TemplateValueParameter *TemplateValueParameter::isTemplateValueParameter()
-{
-    return this;
-}
-
-TemplateParameter *TemplateValueParameter::syntaxCopy()
-{
-    TemplateValueParameter *tp =
-	new TemplateValueParameter(loc, ident, valType, specValue, defaultValue);
-    tp->valType = valType->syntaxCopy();
-    if (specValue)
-	tp->specValue = specValue->syntaxCopy();
-    if (defaultValue)
-	tp->defaultValue = defaultValue->syntaxCopy();
-    return tp;
-}
-
-void TemplateValueParameter::declareParameter(Scope *sc)
-{
-    VarDeclaration *v = new VarDeclaration(loc, valType, ident, NULL);
-    v->storage_class = STCtemplateparameter;
-    if (!sc->insert(v))
-	error(loc, "parameter '%s' multiply defined", ident->toChars());
-    sparam = v;
-}
-
-void TemplateValueParameter::semantic(Scope *sc)
-{
-    sparam->semantic(sc);
-    valType = valType->semantic(loc, sc);
-    if (!(valType->isintegral() || valType->isfloating() || valType->isString()) &&
-	valType->ty != Tident)
-	error(loc, "arithmetic/string type expected for value-parameter, not %s", valType->toChars());
-
-    if (specValue)
-    {   Expression *e = specValue;
-
-	e = e->semantic(sc);
-	e = e->implicitCastTo(sc, valType);
-	e = e->optimize(WANTvalue | WANTinterpret);
-	if (e->op == TOKint64 || e->op == TOKfloat64 ||
-	    e->op == TOKcomplex80 || e->op == TOKnull || e->op == TOKstring)
-	    specValue = e;
-	//e->toInteger();
-    }
-
-#if 0	// defer semantic analysis to arg match
-    if (defaultValue)
-    {   Expression *e = defaultValue;
-
-	e = e->semantic(sc);
-	e = e->implicitCastTo(sc, valType);
-	e = e->optimize(WANTvalue | WANTinterpret);
-	if (e->op == TOKint64)
-	    defaultValue = e;
-	//e->toInteger();
-    }
-#endif
-}
-
-int TemplateValueParameter::overloadMatch(TemplateParameter *tp)
-{
-    TemplateValueParameter *tvp = tp->isTemplateValueParameter();
-
-    if (tvp)
-    {
-	if (valType != tvp->valType)
-	    goto Lnomatch;
-
-	if (valType && !valType->equals(tvp->valType))
-	    goto Lnomatch;
-
-	if (specValue != tvp->specValue)
-	    goto Lnomatch;
-
-	return 1;			// match
-    }
-
-Lnomatch:
-    return 0;
-}
-
-
-MATCH TemplateValueParameter::matchArg(Scope *sc,
-	Objects *tiargs, int i, TemplateParameters *parameters, Objects *dedtypes,
-	Declaration **psparam, int flags)
-{
-    //printf("TemplateValueParameter::matchArg()\n");
-
-    Initializer *init;
-    Declaration *sparam;
-    MATCH m = MATCHexact;
-    Expression *ei;
-    Object *oarg;
-
-    if (i < tiargs->dim)
-	oarg = (Object *)tiargs->data[i];
-    else
-    {	// Get default argument instead
-	oarg = defaultArg(loc, sc);
-	if (!oarg)
-	{   assert(i < dedtypes->dim);
-	    // It might have already been deduced
-	    oarg = (Object *)dedtypes->data[i];
-	    if (!oarg)
-		goto Lnomatch;
-	}
-    }
-
-    ei = isExpression(oarg);
-    Type *vt;
-
-    if (!ei && oarg)
-	goto Lnomatch;
-
-    if (ei && ei->op == TOKvar)
-    {	// Resolve const variables that we had skipped earlier
-	ei = ei->optimize(WANTvalue | WANTinterpret);
-    }
-
-    if (specValue)
-    {
-	if (!ei || ei == edummy)
-	    goto Lnomatch;
-
-	Expression *e = specValue;
-
-	e = e->semantic(sc);
-	e = e->implicitCastTo(sc, valType);
-	e = e->optimize(WANTvalue | WANTinterpret);
-	//e->type = e->type->toHeadMutable();
-
-	ei = ei->syntaxCopy();
-	ei = ei->semantic(sc);
-	ei = ei->optimize(WANTvalue | WANTinterpret);
-	//ei->type = ei->type->toHeadMutable();
-	//printf("\tei: %s, %s\n", ei->toChars(), ei->type->toChars());
-	//printf("\te : %s, %s\n", e->toChars(), e->type->toChars());
-	if (!ei->equals(e))
-	    goto Lnomatch;
-    }
-    else if (dedtypes->data[i])
-    {   // Must match already deduced value
-	Expression *e = (Expression *)dedtypes->data[i];
-
-	if (!ei || !ei->equals(e))
-	    goto Lnomatch;
-    }
-Lmatch:
-    //printf("\tvalType: %s, ty = %d\n", valType->toChars(), valType->ty);
-    vt = valType->semantic(0, sc);
-    //printf("ei: %s, ei->type: %s\n", ei->toChars(), ei->type->toChars());
-    //printf("vt = %s\n", vt->toChars());
-    if (ei->type)
-    {
-	//ei->type = ei->type->toHeadMutable();
-	m = (MATCH)ei->implicitConvTo(vt);
-	//printf("m: %d\n", m);
-	if (!m)
-	    goto Lnomatch;
-    }
-    dedtypes->data[i] = ei;
-
-    init = new ExpInitializer(loc, ei);
-    sparam = new VarDeclaration(loc, vt, ident, init);
-    sparam->storage_class = STCmanifest;
-    *psparam = sparam;
-    return m;
-
-Lnomatch:
-    //printf("\tno match\n");
-    *psparam = NULL;
-    return MATCHnomatch;
-}
-
-
-void TemplateValueParameter::print(Object *oarg, Object *oded)
-{
-    printf(" %s\n", ident->toChars());
-
-    Expression *ea = isExpression(oded);
-
-    if (specValue)
-	printf("\tSpecialization: %s\n", specValue->toChars());
-    printf("\tArgument Value: %s\n", ea ? ea->toChars() : "NULL");
-}
-
-
-void TemplateValueParameter::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{
-    valType->toCBuffer(buf, ident, hgs);
-    if (specValue)
-    {
-	buf->writestring(" : ");
-	specValue->toCBuffer(buf, hgs);
-    }
-    if (defaultValue)
-    {
-	buf->writestring(" = ");
-	defaultValue->toCBuffer(buf, hgs);
-    }
-}
-
-
-void *TemplateValueParameter::dummyArg()
-{   Expression *e;
-
-    e = specValue;
-    if (!e)
-    {
-	// Create a dummy value
-	if (!edummy)
-	    edummy = valType->defaultInit();
-	e = edummy;
-    }
-    return (void *)e;
-}
-
-
-Object *TemplateValueParameter::specialization()
-{
-    return specValue;
-}
-
-
-Object *TemplateValueParameter::defaultArg(Loc loc, Scope *sc)
-{
-    Expression *e = defaultValue;
-    if (e)
-    {
-	e = e->syntaxCopy();
-	e = e->semantic(sc);
-#if DMDV2
-	if (e->op == TOKdefault)
-	{   DefaultInitExp *de = (DefaultInitExp *)e;
-	    e = de->resolve(loc, sc);
-	}
-#endif
-    }
-    return e;
-}
-
-/* ======================== TemplateTupleParameter ========================== */
-
-// variadic-parameter
-
-TemplateTupleParameter::TemplateTupleParameter(Loc loc, Identifier *ident)
-    : TemplateParameter(loc, ident)
-{
-    this->ident = ident;
-}
-
-TemplateTupleParameter *TemplateTupleParameter::isTemplateTupleParameter()
-{
-    return this;
-}
-
-TemplateParameter *TemplateTupleParameter::syntaxCopy()
-{
-    TemplateTupleParameter *tp = new TemplateTupleParameter(loc, ident);
-    return tp;
-}
-
-void TemplateTupleParameter::declareParameter(Scope *sc)
-{
-    TypeIdentifier *ti = new TypeIdentifier(loc, ident);
-    sparam = new AliasDeclaration(loc, ident, ti);
-    if (!sc->insert(sparam))
-	error(loc, "parameter '%s' multiply defined", ident->toChars());
-}
-
-void TemplateTupleParameter::semantic(Scope *sc)
-{
-}
-
-int TemplateTupleParameter::overloadMatch(TemplateParameter *tp)
-{
-    TemplateTupleParameter *tvp = tp->isTemplateTupleParameter();
-
-    if (tvp)
-    {
-	return 1;			// match
-    }
-
-Lnomatch:
-    return 0;
-}
-
-MATCH TemplateTupleParameter::matchArg(Scope *sc,
-	Objects *tiargs, int i, TemplateParameters *parameters,
-	Objects *dedtypes,
-	Declaration **psparam, int flags)
-{
-    //printf("TemplateTupleParameter::matchArg()\n");
-
-    /* The rest of the actual arguments (tiargs[]) form the match
-     * for the variadic parameter.
-     */
-    assert(i + 1 == dedtypes->dim);	// must be the last one
-    Tuple *ovar;
-    if (i + 1 == tiargs->dim && isTuple((Object *)tiargs->data[i]))
-	ovar = isTuple((Object *)tiargs->data[i]);
-    else
-    {
-	ovar = new Tuple();
-	//printf("ovar = %p\n", ovar);
-	if (i < tiargs->dim)
-	{
-	    //printf("i = %d, tiargs->dim = %d\n", i, tiargs->dim);
-	    ovar->objects.setDim(tiargs->dim - i);
-	    for (size_t j = 0; j < ovar->objects.dim; j++)
-		ovar->objects.data[j] = tiargs->data[i + j];
-	}
-    }
-    *psparam = new TupleDeclaration(loc, ident, &ovar->objects);
-    dedtypes->data[i] = (void *)ovar;
-    return MATCHexact;
-}
-
-
-void TemplateTupleParameter::print(Object *oarg, Object *oded)
-{
-    printf(" %s... [", ident->toChars());
-    Tuple *v = isTuple(oded);
-    assert(v);
-
-    //printf("|%d| ", v->objects.dim);
-    for (int i = 0; i < v->objects.dim; i++)
-    {
-	if (i)
-	    printf(", ");
-
-	Object *o = (Object *)v->objects.data[i];
-
-	Dsymbol *sa = isDsymbol(o);
-	if (sa)
-	    printf("alias: %s", sa->toChars());
-
-	Type *ta = isType(o);
-	if (ta)
-	    printf("type: %s", ta->toChars());
-
-	Expression *ea = isExpression(o);
-	if (ea)
-	    printf("exp: %s", ea->toChars());
-
-	assert(!isTuple(o));		// no nested Tuple arguments
-    }
-
-    printf("]\n");
-}
-
-void TemplateTupleParameter::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{
-    buf->writestring(ident->toChars());
-    buf->writestring("...");
-}
-
-
-void *TemplateTupleParameter::dummyArg()
-{
-    return NULL;
-}
-
-
-Object *TemplateTupleParameter::specialization()
-{
-    return NULL;
-}
-
-
-Object *TemplateTupleParameter::defaultArg(Loc loc, Scope *sc)
-{
-    return NULL;
-}
-
-/* ======================== TemplateInstance ================================ */
-
-TemplateInstance::TemplateInstance(Loc loc, Identifier *ident)
-    : ScopeDsymbol(NULL)
-{
-#if LOG
-    printf("TemplateInstance(this = %p, ident = '%s')\n", this, ident ? ident->toChars() : "null");
-#endif
-    this->loc = loc;
-    this->name = ident;
-    this->tiargs = NULL;
-    this->tempdecl = NULL;
-    this->inst = NULL;
-    this->argsym = NULL;
-    this->aliasdecl = NULL;
-    this->semanticdone = 0;
-    this->semantictiargsdone = 0;
-    this->withsym = NULL;
-    this->nest = 0;
-    this->havetempdecl = 0;
-    this->isnested = NULL;
-    this->errors = 0;
-
-    // LDC
-    this->tinst = NULL;
-    this->tmodule = NULL;
-}
-
-/*****************
- * This constructor is only called when we figured out which function
- * template to instantiate.
- */
-
-TemplateInstance::TemplateInstance(Loc loc, TemplateDeclaration *td, Objects *tiargs)
-    : ScopeDsymbol(NULL)
-{
-#if LOG
-    printf("TemplateInstance(this = %p, tempdecl = '%s')\n", this, td->toChars());
-#endif
-    this->loc = loc;
-    this->name = td->ident;
-    this->tiargs = tiargs;
-    this->tempdecl = td;
-    this->inst = NULL;
-    this->argsym = NULL;
-    this->aliasdecl = NULL;
-    this->semanticdone = 0;
-    this->semantictiargsdone = 1;
-    this->withsym = NULL;
-    this->nest = 0;
-    this->havetempdecl = 1;
-    this->isnested = NULL;
-    this->errors = 0;
-
-    // LDC
-    this->tinst = NULL;
-    this->tmodule = NULL;
-
-    assert((size_t)tempdecl->scope > 0x10000);
-}
-
-
-Objects *TemplateInstance::arraySyntaxCopy(Objects *objs)
-{
-    Objects *a = NULL;
-    if (objs)
-    {	a = new Objects();
-	a->setDim(objs->dim);
-	for (size_t i = 0; i < objs->dim; i++)
-	{
-	    a->data[i] = objectSyntaxCopy((Object *)objs->data[i]);
-	}
-    }
-    return a;
-}
-
-Dsymbol *TemplateInstance::syntaxCopy(Dsymbol *s)
-{
-    TemplateInstance *ti;
-
-    if (s)
-	ti = (TemplateInstance *)s;
-    else
-	ti = new TemplateInstance(loc, name);
-
-    ti->tiargs = arraySyntaxCopy(tiargs);
-
-    ScopeDsymbol::syntaxCopy(ti);
-    return ti;
-}
-
-
-void TemplateInstance::semantic(Scope *sc)
-{
-    if (global.errors)
-    {
-	if (!global.gag)
-	{
-	    /* Trying to soldier on rarely generates useful messages
-	     * at this point.
-	     */
-	    fatal();
-	}
-	return;
-    }
-#if LOG
-    printf("\n+TemplateInstance::semantic('%s', this=%p)\n", toChars(), this);
-#endif
-    if (inst)		// if semantic() was already run
-    {
-#if LOG
-	printf("-TemplateInstance::semantic('%s', this=%p) already run\n", inst->toChars(), inst);
-#endif
-	return;
-    }
-
-    if (semanticdone != 0)
-    {
-	error(loc, "recursive template expansion");
-//	inst = this;
-	return;
-    }
-    semanticdone = 1;
-
-    // get the enclosing template instance from the scope tinst
-    tinst = sc->tinst;
-
-    // get the module of the outermost enclosing instantiation
-    if (tinst)
-    tmodule = tinst->tmodule;
-    else
-    tmodule = sc->module;
-    //printf("%s in %s\n", toChars(), tmodule->toChars());
-
-#if LOG
-    printf("\tdo semantic\n");
-#endif
-    if (havetempdecl)
-    {
-	assert((size_t)tempdecl->scope > 0x10000);
-	// Deduce tdtypes
-	tdtypes.setDim(tempdecl->parameters->dim);
-	if (!tempdecl->matchWithInstance(this, &tdtypes, 2))
-	{
-	    error("incompatible arguments for template instantiation");
-	    inst = this;
-	    return;
-	}
-    }
-    else
-    {
-	/* Run semantic on each argument, place results in tiargs[]
-	 * (if we havetempdecl, then tiargs is already evaluated)
-	 */
-	semanticTiargs(sc);
-
-	tempdecl = findTemplateDeclaration(sc);
-	if (tempdecl)
-	    tempdecl = findBestMatch(sc);
-	if (!tempdecl || global.errors)
-	{   inst = this;
-	    //printf("error return %p, %d\n", tempdecl, global.errors);
-	    return;		// error recovery
-	}
-    }
-
-    isNested(tiargs);
-
-    /* See if there is an existing TemplateInstantiation that already
-     * implements the typeargs. If so, just refer to that one instead.
-     */
-
-    for (size_t i = 0; i < tempdecl->instances.dim; i++)
-    {
-	TemplateInstance *ti = (TemplateInstance *)tempdecl->instances.data[i];
-#if LOG
-	printf("\t%s: checking for match with instance %d (%p): '%s'\n", toChars(), i, ti, ti->toChars());
-#endif
-	assert(tdtypes.dim == ti->tdtypes.dim);
-
-	// Nesting must match
-	if (isnested != ti->isnested)
-	    continue;
-#if 0
-	if (isnested && sc->parent != ti->parent)
-	    continue;
-#endif
-	for (size_t j = 0; j < tdtypes.dim; j++)
-	{   Object *o1 = (Object *)tdtypes.data[j];
-	    Object *o2 = (Object *)ti->tdtypes.data[j];
-	    if (!match(o1, o2, tempdecl, sc))
-		goto L1;
-	}
-
-	// It's a match
-	inst = ti;
-	parent = ti->parent;
-#if LOG
-	printf("\tit's a match with instance %p\n", inst);
-#endif
-	return;
-
-     L1:
-	;
-    }
-
-    /* So, we need to implement 'this' instance.
-     */
-#if LOG
-    printf("\timplement template instance '%s'\n", toChars());
-#endif
-    unsigned errorsave = global.errors;
-    inst = this;
-    int tempdecl_instance_idx = tempdecl->instances.dim;
-    tempdecl->instances.push(this);
-    parent = tempdecl->parent;
-    //printf("parent = '%s'\n", parent->kind());
-
-    ident = genIdent();		// need an identifier for name mangling purposes.
-
-#if 1
-    if (isnested)
-	parent = isnested;
-#endif
-    //printf("parent = '%s'\n", parent->kind());
-
-    // Add 'this' to the enclosing scope's members[] so the semantic routines
-    // will get called on the instance members
-#if 1
-    int dosemantic3 = 0;
-    {	Array *a;
-
-	Scope *scx = sc;
-#if 0
-	for (scx = sc; scx; scx = scx->enclosing)
-	    if (scx->scopesym)
-		break;
-#endif
-
-	//if (scx && scx->scopesym) printf("3: scx is %s %s\n", scx->scopesym->kind(), scx->scopesym->toChars());
-	if (scx && scx->scopesym && scx->scopesym->members && !scx->scopesym->isTemplateMixin())
-	{
-	    //printf("\t1: adding to %s %s\n", scx->scopesym->kind(), scx->scopesym->toChars());
-	    a = scx->scopesym->members;
-	}
-	else
-	{   Module *m = sc->module->importedFrom;
-	    //printf("\t2: adding to module %s instead of module %s\n", m->toChars(), sc->module->toChars());
-	    a = m->members;
-	    if (m->semanticdone >= 3)
-		dosemantic3 = 1;
-	}
-	for (int i = 0; 1; i++)
-	{
-	    if (i == a->dim)
-	    {
-		a->push(this);
-		break;
-	    }
-	    if (this == (Dsymbol *)a->data[i])	// if already in Array
-		break;
-	}
-    }
-#endif
-
-    // Copy the syntax trees from the TemplateDeclaration
-    members = Dsymbol::arraySyntaxCopy(tempdecl->members);
-
-    // Create our own scope for the template parameters
-    Scope *scope = tempdecl->scope;
-    if (!scope)
-    {
-	error("forward reference to template declaration %s\n", tempdecl->toChars());
-	return;
-    }
-
-#if LOG
-    printf("\tcreate scope for template parameters '%s'\n", toChars());
-#endif
-    argsym = new ScopeDsymbol();
-    argsym->parent = scope->parent;
-    scope = scope->push(argsym);
-
-    // Declare each template parameter as an alias for the argument type
-    declareParameters(scope);
-
-    // Add members of template instance to template instance symbol table
-//    parent = scope->scopesym;
-    symtab = new DsymbolTable();
-    int memnum = 0;
-    for (int i = 0; i < members->dim; i++)
-    {
-	Dsymbol *s = (Dsymbol *)members->data[i];
-#if LOG
-	printf("\t[%d] adding member '%s' %p kind %s to '%s', memnum = %d\n", i, s->toChars(), s, s->kind(), this->toChars(), memnum);
-#endif
-	memnum |= s->addMember(scope, this, memnum);
-    }
-#if LOG
-    printf("adding members done\n");
-#endif
-
-    /* See if there is only one member of template instance, and that
-     * member has the same name as the template instance.
-     * If so, this template instance becomes an alias for that member.
-     */
-    //printf("members->dim = %d\n", members->dim);
-    if (members->dim)
-    {
-	Dsymbol *s;
-	if (Dsymbol::oneMembers(members, &s) && s)
-	{
-	    //printf("s->kind = '%s'\n", s->kind());
-	    //s->print();
-	    //printf("'%s', '%s'\n", s->ident->toChars(), tempdecl->ident->toChars());
-	    if (s->ident && s->ident->equals(tempdecl->ident))
-	    {
-		//printf("setting aliasdecl\n");
-		aliasdecl = new AliasDeclaration(loc, s->ident, s);
-	    }
-	}
-    }
-
-    // Do semantic() analysis on template instance members
-#if LOG
-    printf("\tdo semantic() on template instance members '%s'\n", toChars());
-#endif
-    Scope *sc2;
-    sc2 = scope->push(this);
-    //printf("isnested = %d, sc->parent = %s\n", isnested, sc->parent->toChars());
-    sc2->parent = /*isnested ? sc->parent :*/ this;
-    sc2->tinst = this;
-
-#if !IN_LLVM    
-#if WINDOWS_SEH
-  __try
-  {
-#endif
-#endif
-    for (int i = 0; i < members->dim; i++)
-    {
-	Dsymbol *s = (Dsymbol *)members->data[i];
-	//printf("\t[%d] semantic on '%s' %p kind %s in '%s'\n", i, s->toChars(), s, s->kind(), this->toChars());
-	//printf("test: isnested = %d, sc2->parent = %s\n", isnested, sc2->parent->toChars());
-//	if (isnested)
-//	    s->parent = sc->parent;
-	//printf("test3: isnested = %d, s->parent = %s\n", isnested, s->parent->toChars());
-	s->semantic(sc2);
-	//printf("test4: isnested = %d, s->parent = %s\n", isnested, s->parent->toChars());
-	sc2->module->runDeferredSemantic();
-    }
-#if !IN_LLVM    
-#if WINDOWS_SEH
-  }
-  __except (__ehfilter(GetExceptionInformation()))
-  {
-    global.gag = 0;			// ensure error message gets printed
-    error("recursive expansion");
-    fatal();
-  }
-#endif
-#endif
-
-    /* If any of the instantiation members didn't get semantic() run
-     * on them due to forward references, we cannot run semantic2()
-     * or semantic3() yet.
-     */
-    for (size_t i = 0; i < Module::deferred.dim; i++)
-    {	Dsymbol *sd = (Dsymbol *)Module::deferred.data[i];
-
-	if (sd->parent == this)
-	    goto Laftersemantic;
-    }
-
-    /* The problem is when to parse the initializer for a variable.
-     * Perhaps VarDeclaration::semantic() should do it like it does
-     * for initializers inside a function.
-     */
-//    if (sc->parent->isFuncDeclaration())
-
-	/* BUG 782: this has problems if the classes this depends on
-	 * are forward referenced. Find a way to defer semantic()
-	 * on this template.
-	 */
-	semantic2(sc2);
-
-    if (sc->func || dosemantic3)
-    {
-	semantic3(sc2);
-    }
-
-  Laftersemantic:
-    sc2->pop();
-
-    scope->pop();
-
-    // Give additional context info if error occurred during instantiation
-    if (global.errors != errorsave)
-    {
-	error("error instantiating");
-	if(tinst)
-	    tinst->printInstantiationTrace();
-	errors = 1;
-	if (global.gag)
-	    tempdecl->instances.remove(tempdecl_instance_idx);
-    }
-
-#if LOG
-    printf("-TemplateInstance::semantic('%s', this=%p)\n", toChars(), this);
-#endif
-}
-
-
-void TemplateInstance::semanticTiargs(Scope *sc)
-{
-    //printf("+TemplateInstance::semanticTiargs() %s\n", toChars());
-    if (semantictiargsdone)
-	return;
-    semantictiargsdone = 1;
-    semanticTiargs(loc, sc, tiargs, 0);
-}
-
-/**********************************
- * Input:
- *	flags	1: replace const variables with their initializers
- */
-
-void TemplateInstance::semanticTiargs(Loc loc, Scope *sc, Objects *tiargs, int flags)
-{
-    // Run semantic on each argument, place results in tiargs[]
-    //printf("+TemplateInstance::semanticTiargs()\n");
-    if (!tiargs)
-	return;
-    for (size_t j = 0; j < tiargs->dim; j++)
-    {
-	Object *o = (Object *)tiargs->data[j];
-	Type *ta = isType(o);
-	Expression *ea = isExpression(o);
-	Dsymbol *sa = isDsymbol(o);
-
-	//printf("1: tiargs->data[%d] = %p, %p, %p, ea=%p, ta=%p\n", j, o, isDsymbol(o), isTuple(o), ea, ta);
-	if (ta)
-	{
-	    //printf("type %s\n", ta->toChars());
-	    // It might really be an Expression or an Alias
-	    ta->resolve(loc, sc, &ea, &ta, &sa);
-	    if (ea)
-	    {
-		ea = ea->semantic(sc);
-		/* This test is to skip substituting a const var with
-		 * its initializer. The problem is the initializer won't
-		 * match with an 'alias' parameter. Instead, do the
-		 * const substitution in TemplateValueParameter::matchArg().
-		 */
-		if (ea->op != TOKvar || flags & 1)
-		    ea = ea->optimize(WANTvalue | WANTinterpret);
-		tiargs->data[j] = ea;
-	    }
-	    else if (sa)
-	    {	tiargs->data[j] = sa;
-		TupleDeclaration *d = sa->toAlias()->isTupleDeclaration();
-		if (d)
-		{
-		    size_t dim = d->objects->dim;
-		    tiargs->remove(j);
-		    tiargs->insert(j, d->objects);
-		    j--;
-		}
-	    }
-	    else if (ta)
-	    {
-		if (ta->ty == Ttuple)
-		{   // Expand tuple
-		    TypeTuple *tt = (TypeTuple *)ta;
-		    size_t dim = tt->arguments->dim;
-		    tiargs->remove(j);
-		    if (dim)
-		    {	tiargs->reserve(dim);
-			for (size_t i = 0; i < dim; i++)
-			{   Argument *arg = (Argument *)tt->arguments->data[i];
-			    tiargs->insert(j + i, arg->type);
-			}
-		    }
-		    j--;
-		}
-		else
-		    tiargs->data[j] = ta;
-	    }
-	    else
-	    {
-		assert(global.errors);
-		tiargs->data[j] = Type::terror;
-	    }
-	}
-	else if (ea)
-	{
-	    if (!ea)
-	    {	assert(global.errors);
-		ea = new IntegerExp(0);
-	    }
-	    assert(ea);
-	    ea = ea->semantic(sc);
-	    if (ea->op != TOKvar || flags & 1)
-		ea = ea->optimize(WANTvalue | WANTinterpret);
-	    tiargs->data[j] = ea;
-	    if (ea->op == TOKtype)
-		tiargs->data[j] = ea->type;
-	}
-	else if (sa)
-	{
-	}
-	else
-	{
-	    assert(0);
-	}
-	//printf("1: tiargs->data[%d] = %p\n", j, tiargs->data[j]);
-    }
-#if 0
-    printf("-TemplateInstance::semanticTiargs('%s', this=%p)\n", toChars(), this);
-    for (size_t j = 0; j < tiargs->dim; j++)
-    {
-	Object *o = (Object *)tiargs->data[j];
-	Type *ta = isType(o);
-	Expression *ea = isExpression(o);
-	Dsymbol *sa = isDsymbol(o);
-	Tuple *va = isTuple(o);
-
-	printf("\ttiargs[%d] = ta %p, ea %p, sa %p, va %p\n", j, ta, ea, sa, va);
-    }
-#endif
-}
-
-/**********************************************
- * Find template declaration corresponding to template instance.
- */
-
-TemplateDeclaration *TemplateInstance::findTemplateDeclaration(Scope *sc)
-{
-    //printf("TemplateInstance::findTemplateDeclaration() %s\n", toChars());
-    if (!tempdecl)
-    {
-	/* Given:
-	 *    foo!( ... )
-	 * figure out which TemplateDeclaration foo refers to.
-	 */
-	Dsymbol *s;
-	Dsymbol *scopesym;
-	Identifier *id;
-	int i;
-
-	id = name;
-	s = sc->search(loc, id, &scopesym);
-	if (!s)
-	{   error("identifier '%s' is not defined", id->toChars());
-	    return NULL;
-	}
-#if LOG
-	printf("It's an instance of '%s' kind '%s'\n", s->toChars(), s->kind());
-	if (s->parent)
-	    printf("s->parent = '%s'\n", s->parent->toChars());
-#endif
-	withsym = scopesym->isWithScopeSymbol();
-
-	/* We might have found an alias within a template when
-	 * we really want the template.
-	 */
-	TemplateInstance *ti;
-	if (s->parent &&
-	    (ti = s->parent->isTemplateInstance()) != NULL)
-	{
-	    if (
-		(ti->name == id ||
-		 ti->toAlias()->ident == id)
-		&&
-		ti->tempdecl)
-	    {
-		/* This is so that one can refer to the enclosing
-		 * template, even if it has the same name as a member
-		 * of the template, if it has a !(arguments)
-		 */
-		tempdecl = ti->tempdecl;
-		if (tempdecl->overroot)		// if not start of overloaded list of TemplateDeclaration's
-		    tempdecl = tempdecl->overroot; // then get the start
-		s = tempdecl;
-	    }
-	}
-
-	s = s->toAlias();
-
-	/* It should be a TemplateDeclaration, not some other symbol
-	 */
-	tempdecl = s->isTemplateDeclaration();
-	if (!tempdecl)
-	{
-	    if (!s->parent && global.errors)
-		return NULL;
-	    if (!s->parent && s->getType())
-	    {	Dsymbol *s2 = s->getType()->toDsymbol(sc);
-		if (!s2)
-		{
-		    error("%s is not a template declaration, it is a %s", id->toChars(), s->kind());
-		    return NULL;
-		}
-		s = s2;
-	    }
-#ifdef DEBUG
-	    //if (!s->parent) printf("s = %s %s\n", s->kind(), s->toChars());
-#endif
-	    //assert(s->parent);
-	    TemplateInstance *ti = s->parent ? s->parent->isTemplateInstance() : NULL;
-	    if (ti &&
-		(ti->name == id ||
-		 ti->toAlias()->ident == id)
-		&&
-		ti->tempdecl)
-	    {
-		/* This is so that one can refer to the enclosing
-		 * template, even if it has the same name as a member
-		 * of the template, if it has a !(arguments)
-		 */
-		tempdecl = ti->tempdecl;
-		if (tempdecl->overroot)		// if not start of overloaded list of TemplateDeclaration's
-		    tempdecl = tempdecl->overroot; // then get the start
-	    }
-	    else
-	    {
-		error("%s is not a template declaration, it is a %s", id->toChars(), s->kind());
-		return NULL;
-	    }
-	}
-    }
-    else
-	assert(tempdecl->isTemplateDeclaration());
-    return tempdecl;
-}
-
-TemplateDeclaration *TemplateInstance::findBestMatch(Scope *sc)
-{
-    /* Since there can be multiple TemplateDeclaration's with the same
-     * name, look for the best match.
-     */
-    TemplateDeclaration *td_ambig = NULL;
-    TemplateDeclaration *td_best = NULL;
-    MATCH m_best = MATCHnomatch;
-    Objects dedtypes;
-
-#if LOG
-    printf("TemplateInstance::findBestMatch()\n");
-#endif
-    for (TemplateDeclaration *td = tempdecl; td; td = td->overnext)
-    {
-	MATCH m;
-
-//if (tiargs->dim) printf("2: tiargs->dim = %d, data[0] = %p\n", tiargs->dim, tiargs->data[0]);
-
-	// If more arguments than parameters,
-	// then this is no match.
-	if (td->parameters->dim < tiargs->dim)
-	{
-	    if (!td->isVariadic())
-		continue;
-	}
-
-	dedtypes.setDim(td->parameters->dim);
-	dedtypes.zero();
-	if (!td->scope)
-	{
-	    error("forward reference to template declaration %s", td->toChars());
-	    return NULL;
-	}
-	m = td->matchWithInstance(this, &dedtypes, 0);
-	//printf("matchWithInstance = %d\n", m);
-	if (!m)			// no match at all
-	    continue;
-
-	if (m < m_best)
-	    goto Ltd_best;
-	if (m > m_best)
-	    goto Ltd;
-
-	{
-	// Disambiguate by picking the most specialized TemplateDeclaration
-	MATCH c1 = td->leastAsSpecialized(td_best);
-	MATCH c2 = td_best->leastAsSpecialized(td);
-	//printf("c1 = %d, c2 = %d\n", c1, c2);
-
-	if (c1 > c2)
-	    goto Ltd;
-	else if (c1 < c2)
-	    goto Ltd_best;
-	else
-	    goto Lambig;
-	}
-
-      Lambig:		// td_best and td are ambiguous
-	td_ambig = td;
-	continue;
-
-      Ltd_best:		// td_best is the best match so far
-	td_ambig = NULL;
-	continue;
-
-      Ltd:		// td is the new best match
-	td_ambig = NULL;
-	td_best = td;
-	m_best = m;
-	tdtypes.setDim(dedtypes.dim);
-	memcpy(tdtypes.data, dedtypes.data, tdtypes.dim * sizeof(void *));
-	continue;
-    }
-
-    if (!td_best)
-    {
-	if (tempdecl && !tempdecl->overnext)
-	    // Only one template, so we can give better error message
-	    error("%s does not match template declaration %s", toChars(), tempdecl->toChars());
-	else
-	    error("%s does not match any template declaration", toChars());
-	return NULL;
-    }
-    if (td_ambig)
-    {
-	error("%s matches more than one template declaration, %s and %s",
-		toChars(), td_best->toChars(), td_ambig->toChars());
-    }
-
-    /* The best match is td_best
-     */
-    tempdecl = td_best;
-
-#if 0
-    /* Cast any value arguments to be same type as value parameter
-     */
-    for (size_t i = 0; i < tiargs->dim; i++)
-    {	Object *o = (Object *)tiargs->data[i];
-	Expression *ea = isExpression(o);	// value argument
-	TemplateParameter *tp = (TemplateParameter *)tempdecl->parameters->data[i];
-	assert(tp);
-	TemplateValueParameter *tvp = tp->isTemplateValueParameter();
-	if (tvp)
-	{
-	    assert(ea);
-	    ea = ea->castTo(tvp->valType);
-	    ea = ea->optimize(WANTvalue | WANTinterpret);
-	    tiargs->data[i] = (Object *)ea;
-	}
-    }
-#endif
-
-#if LOG
-    printf("\tIt's a match with template declaration '%s'\n", tempdecl->toChars());
-#endif
-    return tempdecl;
-}
-
-
-/*****************************************
- * Determines if a TemplateInstance will need a nested
- * generation of the TemplateDeclaration.
- */
-
-int TemplateInstance::isNested(Objects *args)
-{   int nested = 0;
-    //printf("TemplateInstance::isNested('%s')\n", tempdecl->ident->toChars());
-
-    /* A nested instance happens when an argument references a local
-     * symbol that is on the stack.
-     */
-    for (size_t i = 0; i < args->dim; i++)
-    {   Object *o = (Object *)args->data[i];
-	Expression *ea = isExpression(o);
-	Dsymbol *sa = isDsymbol(o);
-	Tuple *va = isTuple(o);
-	if (ea)
-	{
-	    if (ea->op == TOKvar)
-	    {
-		sa = ((VarExp *)ea)->var;
-		goto Lsa;
-	    }
-	    if (ea->op == TOKfunction)
-	    {
-		sa = ((FuncExp *)ea)->fd;
-		goto Lsa;
-	    }
-	}
-	else if (sa)
-	{
-	  Lsa:
-	    Declaration *d = sa->isDeclaration();
-	    if (d && !d->isDataseg() &&
-#if DMDV2
-		!(d->storage_class & STCmanifest) &&
-#endif
-		(!d->isFuncDeclaration() || d->isFuncDeclaration()->isNested()) &&
-		!isTemplateMixin())
-	    {
-		// if module level template
-		if (tempdecl->toParent()->isModule())
-		{   Dsymbol *dparent = d->toParent();
-		    if (!isnested)
-			isnested = dparent;
-		    else if (isnested != dparent)
-		    {
-			/* Select the more deeply nested of the two.
-			 * Error if one is not nested inside the other.
-			 */
-			for (Dsymbol *p = isnested; p; p = p->parent)
-			{
-			    if (p == dparent)
-				goto L1;	// isnested is most nested
-			}
-			for (Dsymbol *p = dparent; 1; p = p->parent)
-			{
-			    if (p == isnested)
-			    {	isnested = dparent;
-				goto L1;	// dparent is most nested
-			    }
-			}
-			error("is nested in both %s and %s", isnested->toChars(), dparent->toChars());
-		    }
-		  L1:
-		    //printf("\tnested inside %s\n", isnested->toChars());
-		    nested |= 1;
-		}
-		else
-		    error("cannot use local '%s' as parameter to non-global template %s", d->toChars(), tempdecl->toChars());
-	    }
-	}
-	else if (va)
-	{
-	    nested |= isNested(&va->objects);
-	}
-    }
-    return nested;
-}
-
-/****************************************
- * This instance needs an identifier for name mangling purposes.
- * Create one by taking the template declaration name and adding
- * the type signature for it.
- */
-
-Identifier *TemplateInstance::genIdent()
-{   OutBuffer buf;
-    char *id;
-    Objects *args;
-
-    //printf("TemplateInstance::genIdent('%s')\n", tempdecl->ident->toChars());
-    id = tempdecl->ident->toChars();
-    buf.printf("__T%"PRIuSIZE"%s", strlen(id), id);
-    args = tiargs;
-    for (int i = 0; i < args->dim; i++)
-    {   Object *o = (Object *)args->data[i];
-	Type *ta = isType(o);
-	Expression *ea = isExpression(o);
-	Dsymbol *sa = isDsymbol(o);
-	Tuple *va = isTuple(o);
-	//printf("\to %p ta %p ea %p sa %p va %p\n", o, ta, ea, sa, va);
-	if (ta)
-	{
-	    buf.writeByte('T');
-	    if (ta->deco)
-		buf.writestring(ta->deco);
-	    else
-	    {
-#ifdef DEBUG
-		printf("ta = %d, %s\n", ta->ty, ta->toChars());
-#endif
-		assert(global.errors);
-	    }
-	}
-	else if (ea)
-	{
-	  Lea:
-	    sinteger_t v;
-	    real_t r;
-
-	    ea = ea->optimize(WANTvalue | WANTinterpret);
-	    if (ea->op == TOKvar)
-	    {
-		sa = ((VarExp *)ea)->var;
-		ea = NULL;
-		goto Lsa;
-	    }
-	    if (ea->op == TOKfunction)
-	    {
-		sa = ((FuncExp *)ea)->fd;
-		ea = NULL;
-		goto Lsa;
-	    }
-	    buf.writeByte('V');
-	    if (ea->op == TOKtuple)
-	    {	ea->error("tuple is not a valid template value argument");
-		continue;
-	    }
-#if 1
-	    /* Use deco that matches what it would be for a function parameter
-	     */
-	    //buf.writestring(ea->type->toHeadMutable()->deco);
-	    buf.writestring(ea->type->deco);
-#else
-	    // Use type of parameter, not type of argument
-	    TemplateParameter *tp = (TemplateParameter *)tempdecl->parameters->data[i];
-	    assert(tp);
-	    TemplateValueParameter *tvp = tp->isTemplateValueParameter();
-	    assert(tvp);
-	    buf.writestring(tvp->valType->deco);
-#endif
-	    ea->toMangleBuffer(&buf);
-	}
-	else if (sa)
-	{
-	  Lsa:
-	    buf.writeByte('S');
-	    Declaration *d = sa->isDeclaration();
-	    if (d && !d->type->deco)
-	    {	error("forward reference of %s", d->toChars());
-		continue;
-	    }
-#if 0
-	    VarDeclaration *v = sa->isVarDeclaration();
-	    if (v && v->storage_class & STCmanifest)
-	    {	ExpInitializer *ei = v->init->isExpInitializer();
-		if (ei)
-		{
-		    ea = ei->exp;
-		    goto Lea;
-		}
-	    }
-#endif
-	    const char *p = sa->mangle();
-	    buf.printf("%zu%s", strlen(p), p);
-	}
-	else if (va)
-	{
-	    assert(i + 1 == args->dim);		// must be last one
-	    args = &va->objects;
-	    i = -1;
-	}
-	else
-	    assert(0);
-    }
-    buf.writeByte('Z');
-    id = buf.toChars();
-    buf.data = NULL;
-    //printf("\tgenIdent = %s\n", id);
-    return new Identifier(id, TOKidentifier);
-}
-
-
-/****************************************************
- * Declare parameters of template instance, initialize them with the
- * template instance arguments.
- */
-
-void TemplateInstance::declareParameters(Scope *scope)
-{
-    //printf("TemplateInstance::declareParameters()\n");
-    for (int i = 0; i < tdtypes.dim; i++)
-    {
-	TemplateParameter *tp = (TemplateParameter *)tempdecl->parameters->data[i];
-	//Object *o = (Object *)tiargs->data[i];
-	Object *o = (Object *)tdtypes.data[i];		// initializer for tp
-
-	//printf("\ttdtypes[%d] = %p\n", i, o);
-	tempdecl->declareParameter(scope, tp, o);
-    }
-}
-
-
-void TemplateInstance::semantic2(Scope *sc)
-{   int i;
-
-    if (semanticdone >= 2)
-	return;
-    semanticdone = 2;
-#if LOG
-    printf("+TemplateInstance::semantic2('%s')\n", toChars());
-#endif
-    if (!errors && members)
-    {
-	sc = tempdecl->scope;
-	assert(sc);
-	sc = sc->push(argsym);
-	sc = sc->push(this);
-	sc->tinst = this;
-	for (i = 0; i < members->dim; i++)
-	{
-	    Dsymbol *s = (Dsymbol *)members->data[i];
-#if LOG
-printf("\tmember '%s', kind = '%s'\n", s->toChars(), s->kind());
-#endif
-	    s->semantic2(sc);
-	}
-	sc = sc->pop();
-	sc->pop();
-    }
-#if LOG
-    printf("-TemplateInstance::semantic2('%s')\n", toChars());
-#endif
-}
-
-void TemplateInstance::semantic3(Scope *sc)
-{
-#if LOG
-    printf("TemplateInstance::semantic3('%s'), semanticdone = %d\n", toChars(), semanticdone);
-#endif
-//if (toChars()[0] == 'D') *(char*)0=0;
-    if (semanticdone >= 3)
-	return;
-    semanticdone = 3;
-    if (!errors && members)
-    {
-	sc = tempdecl->scope;
-	sc = sc->push(argsym);
-	sc = sc->push(this);
-	sc->tinst = this;
-	for (int i = 0; i < members->dim; i++)
-	{
-	    Dsymbol *s = (Dsymbol *)members->data[i];
-	    s->semantic3(sc);
-	}
-	sc = sc->pop();
-	sc->pop();
-    }
-}
-
-void TemplateInstance::toObjFile(int multiobj)
-{
-#if LOG
-    printf("TemplateInstance::toObjFile('%s', this = %p)\n", toChars(), this);
-#endif
-    if (!errors && members)
-    {
-	if (multiobj)
-	    // Append to list of object files to be written later
-	    //obj_append(this);
-        assert(0 && "multiobj");
-	else
-	{
-	    for (int i = 0; i < members->dim; i++)
-	    {
-		Dsymbol *s = (Dsymbol *)members->data[i];
-		s->toObjFile(multiobj);
-	    }
-	}
-    }
-}
-
-void TemplateInstance::inlineScan()
-{
-#if LOG
-    printf("TemplateInstance::inlineScan('%s')\n", toChars());
-#endif
-    if (!errors && members)
-    {
-	for (int i = 0; i < members->dim; i++)
-	{
-	    Dsymbol *s = (Dsymbol *)members->data[i];
-	    s->inlineScan();
-	}
-    }
-}
-
-void TemplateInstance::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{
-    int i;
-
-    Identifier *id = name;
-    buf->writestring(id->toChars());
-    buf->writestring("!(");
-    if (nest)
-	buf->writestring("...");
-    else
-    {
-	nest++;
-	Objects *args = tiargs;
-	for (i = 0; i < args->dim; i++)
-	{
-	    if (i)
-		buf->writeByte(',');
-	    Object *oarg = (Object *)args->data[i];
-	    ObjectToCBuffer(buf, hgs, oarg);
-	}
-	nest--;
-    }
-    buf->writeByte(')');
-}
-
-
-Dsymbol *TemplateInstance::toAlias()
-{
-#if LOG
-    printf("TemplateInstance::toAlias()\n");
-#endif
-    if (!inst)
-    {	error("cannot resolve forward reference");
-	return this;
-    }
-
-    if (inst != this)
-	return inst->toAlias();
-
-    if (aliasdecl)
-	return aliasdecl->toAlias();
-
-    return inst;
-}
-
-AliasDeclaration *TemplateInstance::isAliasDeclaration()
-{
-    return aliasdecl;
-}
-
-const char *TemplateInstance::kind()
-{
-    return "template instance";
-}
-
-int TemplateInstance::oneMember(Dsymbol **ps)
-{
-    *ps = NULL;
-    return TRUE;
-}
-
-char *TemplateInstance::toChars()
-{
-    OutBuffer buf;
-    HdrGenState hgs;
-    char *s;
-
-    toCBuffer(&buf, &hgs);
-    s = buf.toChars();
-    buf.data = NULL;
-    return s;
-}
-
-void TemplateInstance::printInstantiationTrace()
-{
-    if(global.gag)
-	return;
-
-    const int max_shown = 6;
-
-    // determine instantiation depth
-    int n_instantiations = 1;
-    TemplateInstance* cur = this;
-    while(cur = cur->tinst)
-	++n_instantiations;
-
-    // show full trace only if it's short or verbose is on
-    if(n_instantiations <= max_shown || global.params.verbose)
-    {
-	cur = this;
-	while(cur)
-	{
-	    fprintf(stdmsg,"    instantiatied in %s: %s\n", cur->loc.toChars(), cur->toChars());
-	    cur = cur->tinst;
-	}
-    }
-    else
-    {
-	cur = this;
-	size_t i = 0;
-	for(; i < max_shown/2; ++i, cur = cur->tinst)
-	    fprintf(stdmsg,"    instantiatied in %s: %s\n", cur->loc.toChars(), cur->toChars());
-	fprintf(stdmsg,"    ... (%d instantiations, -v to show) ...\n", n_instantiations - max_shown);
-	for(; i < n_instantiations - max_shown + max_shown/2; ++i, cur = cur->tinst) 
-	{}
-	for(; i < n_instantiations; ++i, cur = cur->tinst) 
-	    fprintf(stdmsg,"    instantiatied in %s: %s\n", cur->loc.toChars(), cur->toChars());
-    }
-}
-
-/* ======================== TemplateMixin ================================ */
-
-TemplateMixin::TemplateMixin(Loc loc, Identifier *ident, Type *tqual,
-	Array *idents, Objects *tiargs)
-	: TemplateInstance(loc, (Identifier *)idents->data[idents->dim - 1])
-{
-    //printf("TemplateMixin(ident = '%s')\n", ident ? ident->toChars() : "");
-    this->ident = ident;
-    this->tqual = tqual;
-    this->idents = idents;
-    this->tiargs = tiargs ? tiargs : new Objects();
-    this->scope = NULL;
-}
-
-Dsymbol *TemplateMixin::syntaxCopy(Dsymbol *s)
-{   TemplateMixin *tm;
-
-    Array *ids = new Array();
-    ids->setDim(idents->dim);
-    for (int i = 0; i < idents->dim; i++)
-    {	// Matches TypeQualified::syntaxCopyHelper()
-        Identifier *id = (Identifier *)idents->data[i];
-        if (id->dyncast() == DYNCAST_DSYMBOL)
-        {
-            TemplateInstance *ti = (TemplateInstance *)id;
-
-            ti = (TemplateInstance *)ti->syntaxCopy(NULL);
-            id = (Identifier *)ti;
-        }
-        ids->data[i] = id;
-    }
-
-    tm = new TemplateMixin(loc, ident,
-		(Type *)(tqual ? tqual->syntaxCopy() : NULL),
-		ids, tiargs);
-    TemplateInstance::syntaxCopy(tm);
-    return tm;
-}
-
-void TemplateMixin::semantic(Scope *sc)
-{
-#if LOG
-    printf("+TemplateMixin::semantic('%s', this=%p)\n", toChars(), this);
-    fflush(stdout);
-#endif
-    if (semanticdone &&
-	// This for when a class/struct contains mixin members, and
-	// is done over because of forward references
-	(!parent || !toParent()->isAggregateDeclaration()))
-    {
-#if LOG
-	printf("\tsemantic done\n");
-#endif
-	return;
-    }
-    if (!semanticdone)
-	semanticdone = 1;
-#if LOG
-    printf("\tdo semantic\n");
-#endif
-
-#if !IN_LLVM
-    // dont know what this is
-    util_progress();
-#endif
-
-    Scope *scx = NULL;
-    if (scope)
-    {	sc = scope;
-	scx = scope;		// save so we don't make redundant copies
-	scope = NULL;
-    }
-
-    // Follow qualifications to find the TemplateDeclaration
-    if (!tempdecl)
-    {	Dsymbol *s;
-	int i;
-	Identifier *id;
-
-	if (tqual)
-	{   s = tqual->toDsymbol(sc);
-	    i = 0;
-	}
-	else
-	{
-	    i = 1;
-	    id = (Identifier *)idents->data[0];
-	    switch (id->dyncast())
-	    {
-		case DYNCAST_IDENTIFIER:
-		    s = sc->search(loc, id, NULL);
-		    break;
-
-		case DYNCAST_DSYMBOL:
-		{
-		    TemplateInstance *ti = (TemplateInstance *)id;
-		    ti->semantic(sc);
-		    s = ti;
-		    break;
-		}
-		default:
-		    assert(0);
-	    }
-	}
-
-	for (; i < idents->dim; i++)
-	{
-	    if (!s)
-		break;
-	    id = (Identifier *)idents->data[i];
-	    s = s->searchX(loc, sc, id);
-	}
-	if (!s)
-	{
-	    error("is not defined");
-	    inst = this;
-	    return;
-	}
-	tempdecl = s->toAlias()->isTemplateDeclaration();
-	if (!tempdecl)
-	{
-	    error("%s isn't a template", s->toChars());
-	    inst = this;
-	    return;
-	}
-    }
-
-    // Look for forward reference
-    assert(tempdecl);
-    for (TemplateDeclaration *td = tempdecl; td; td = td->overnext)
-    {
-	if (!td->scope)
-	{
-	    /* Cannot handle forward references if mixin is a struct member,
-	     * because addField must happen during struct's semantic, not
-	     * during the mixin semantic.
-	     * runDeferred will re-run mixin's semantic outside of the struct's
-	     * semantic.
-	     */
-	    semanticdone = 0;
-	    AggregateDeclaration *ad = toParent()->isAggregateDeclaration();
-	    if (ad)
-		ad->sizeok = 2;
-	    else
-	    {
-		// Forward reference
-		//printf("forward reference - deferring\n");
-		scope = scx ? scx : new Scope(*sc);
-		scope->setNoFree();
-		scope->module->addDeferredSemantic(this);
-	    }
-	    return;
-	}
-    }
-
-    // Run semantic on each argument, place results in tiargs[]
-    semanticTiargs(sc);
-
-    tempdecl = findBestMatch(sc);
-    if (!tempdecl)
-    {	inst = this;
-	return;		// error recovery
-    }
-
-    if (!ident)
-	ident = genIdent();
-
-    inst = this;
-    parent = sc->parent;
-
-    /* Detect recursive mixin instantiations.
-     */
-    for (Dsymbol *s = parent; s; s = s->parent)
-    {
-	//printf("\ts = '%s'\n", s->toChars());
-	TemplateMixin *tm = s->isTemplateMixin();
-	if (!tm || tempdecl != tm->tempdecl)
-	    continue;
-
-	/* Different argument list lengths happen with variadic args
-	 */
-	if (tiargs->dim != tm->tiargs->dim)
-	    continue;
-
-	for (int i = 0; i < tiargs->dim; i++)
-	{   Object *o = (Object *)tiargs->data[i];
-	    Type *ta = isType(o);
-	    Expression *ea = isExpression(o);
-	    Dsymbol *sa = isDsymbol(o);
-	    Object *tmo = (Object *)tm->tiargs->data[i];
-	    if (ta)
-	    {
-		Type *tmta = isType(tmo);
-		if (!tmta)
-		    goto Lcontinue;
-		if (!ta->equals(tmta))
-		    goto Lcontinue;
-	    }
-	    else if (ea)
-	    {	Expression *tme = isExpression(tmo);
-		if (!tme || !ea->equals(tme))
-		    goto Lcontinue;
-	    }
-	    else if (sa)
-	    {
-		Dsymbol *tmsa = isDsymbol(tmo);
-		if (sa != tmsa)
-		    goto Lcontinue;
-	    }
-	    else
-		assert(0);
-	}
-	error("recursive mixin instantiation");
-	return;
-
-    Lcontinue:
-	continue;
-    }
-
-    // Copy the syntax trees from the TemplateDeclaration
-    members = Dsymbol::arraySyntaxCopy(tempdecl->members);
-    if (!members)
-	return;
-
-    symtab = new DsymbolTable();
-
-    for (Scope *sce = sc; 1; sce = sce->enclosing)
-    {
-	ScopeDsymbol *sds = (ScopeDsymbol *)sce->scopesym;
-	if (sds)
-	{
-	    sds->importScope(this, PROTpublic);
-	    break;
-	}
-    }
-
-#if LOG
-    printf("\tcreate scope for template parameters '%s'\n", toChars());
-#endif
-    Scope *scy = sc;
-    scy = sc->push(this);
-    scy->parent = this;
-
-    argsym = new ScopeDsymbol();
-    argsym->parent = scy->parent;
-    Scope *scope = scy->push(argsym);
-
-    unsigned errorsave = global.errors;
-
-    // Declare each template parameter as an alias for the argument type
-    declareParameters(scope);
-
-    // Add members to enclosing scope, as well as this scope
-    for (unsigned i = 0; i < members->dim; i++)
-    {   Dsymbol *s;
-
-	s = (Dsymbol *)members->data[i];
-	s->addMember(scope, this, i);
-	//sc->insert(s);
-	//printf("sc->parent = %p, sc->scopesym = %p\n", sc->parent, sc->scopesym);
-	//printf("s->parent = %s\n", s->parent->toChars());
-    }
-
-    // Do semantic() analysis on template instance members
-#if LOG
-    printf("\tdo semantic() on template instance members '%s'\n", toChars());
-#endif
-    Scope *sc2;
-    sc2 = scope->push(this);
-    sc2->offset = sc->offset;
-    for (int i = 0; i < members->dim; i++)
-    {
-	Dsymbol *s = (Dsymbol *)members->data[i];
-	s->semantic(sc2);
-    }
-    sc->offset = sc2->offset;
-
-    /* The problem is when to parse the initializer for a variable.
-     * Perhaps VarDeclaration::semantic() should do it like it does
-     * for initializers inside a function.
-     */
-//    if (sc->parent->isFuncDeclaration())
-
-	semantic2(sc2);
-
-    if (sc->func)
-    {
-	semantic3(sc2);
-    }
-
-    // Give additional context info if error occurred during instantiation
-    if (global.errors != errorsave)
-    {
-	error("error instantiating");
-    }
-
-    sc2->pop();
-
-    scope->pop();
-
-//    if (!isAnonymous())
-    {
-	scy->pop();
-    }
-#if LOG
-    printf("-TemplateMixin::semantic('%s', this=%p)\n", toChars(), this);
-#endif
-}
-
-void TemplateMixin::semantic2(Scope *sc)
-{   int i;
-
-    if (semanticdone >= 2)
-	return;
-    semanticdone = 2;
-#if LOG
-    printf("+TemplateMixin::semantic2('%s')\n", toChars());
-#endif
-    if (members)
-    {
-	assert(sc);
-	sc = sc->push(argsym);
-	sc = sc->push(this);
-	for (i = 0; i < members->dim; i++)
-	{
-	    Dsymbol *s = (Dsymbol *)members->data[i];
-#if LOG
-	    printf("\tmember '%s', kind = '%s'\n", s->toChars(), s->kind());
-#endif
-	    s->semantic2(sc);
-	}
-	sc = sc->pop();
-	sc->pop();
-    }
-#if LOG
-    printf("-TemplateMixin::semantic2('%s')\n", toChars());
-#endif
-}
-
-void TemplateMixin::semantic3(Scope *sc)
-{   int i;
-
-    if (semanticdone >= 3)
-	return;
-    semanticdone = 3;
-#if LOG
-    printf("TemplateMixin::semantic3('%s')\n", toChars());
-#endif
-    if (members)
-    {
-	sc = sc->push(argsym);
-	sc = sc->push(this);
-	for (i = 0; i < members->dim; i++)
-	{
-	    Dsymbol *s = (Dsymbol *)members->data[i];
-	    s->semantic3(sc);
-	}
-	sc = sc->pop();
-	sc->pop();
-    }
-}
-
-void TemplateMixin::inlineScan()
-{
-    TemplateInstance::inlineScan();
-}
-
-const char *TemplateMixin::kind()
-{
-    return "mixin";
-}
-
-int TemplateMixin::oneMember(Dsymbol **ps)
-{
-    return Dsymbol::oneMember(ps);
-}
-
-int TemplateMixin::hasPointers()
-{
-    //printf("TemplateMixin::hasPointers() %s\n", toChars());
-    for (size_t i = 0; i < members->dim; i++)
-    {
-	Dsymbol *s = (Dsymbol *)members->data[i];
-	//printf(" s = %s %s\n", s->kind(), s->toChars());
-	if (s->hasPointers())
-	{
-	    return 1;
-	}
-    }
-    return 0;
-}
-
-char *TemplateMixin::toChars()
-{
-    OutBuffer buf;
-    HdrGenState hgs;
-    char *s;
-
-    TemplateInstance::toCBuffer(&buf, &hgs);
-    s = buf.toChars();
-    buf.data = NULL;
-    return s;
-}
-
-void TemplateMixin::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{
-    buf->writestring("mixin ");
-
-    for (int i = 0; i < idents->dim; i++)
-    {   Identifier *id = (Identifier *)idents->data[i];
-
-    	if (i)
-	    buf->writeByte('.');
-	buf->writestring(id->toChars());
-    }
-    buf->writestring("!(");
-    if (tiargs)
-    {
-        for (int i = 0; i < tiargs->dim; i++)
-        {   if (i)
-                buf->writebyte(',');
-	    Object *oarg = (Object *)tiargs->data[i];
-	    Type *t = isType(oarg);
-	    Expression *e = isExpression(oarg);
-	    Dsymbol *s = isDsymbol(oarg);
-	    if (t)
-		t->toCBuffer(buf, NULL, hgs);
-	    else if (e)
-		e->toCBuffer(buf, hgs);
-	    else if (s)
-	    {
-		char *p = s->ident ? s->ident->toChars() : s->toChars();
-		buf->writestring(p);
-	    }
-	    else if (!oarg)
-	    {
-		buf->writestring("NULL");
-	    }
-	    else
-	    {
-		assert(0);
-	    }
-        }
-    }
-    buf->writebyte(')');
-    if (ident)
-    {
-	buf->writebyte(' ');
-	buf->writestring(ident->toChars());
-    }
-    buf->writebyte(';');
-    buf->writenl();
-}
-
-
-void TemplateMixin::toObjFile(int multiobj)
-{
-    //printf("TemplateMixin::toObjFile('%s')\n", toChars());
-    TemplateInstance::toObjFile(multiobj);
-}
-
+
+// 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.
+
+// Handle template implementation
+
+#include <stdio.h>
+#include <assert.h>
+
+#include "root.h"
+#include "rmem.h"
+#include "stringtable.h"
+#include "mars.h"
+#include "identifier.h"
+#include "mtype.h"
+#include "template.h"
+#include "init.h"
+#include "expression.h"
+#include "scope.h"
+#include "module.h"
+#include "aggregate.h"
+#include "declaration.h"
+#include "dsymbol.h"
+#include "hdrgen.h"
+
+#if WINDOWS_SEH
+#include <windows.h>
+long __cdecl __ehfilter(LPEXCEPTION_POINTERS ep);
+#endif
+
+#define LOG	0
+
+/********************************************
+ * These functions substitute for dynamic_cast. dynamic_cast does not work
+ * on earlier versions of gcc.
+ */
+
+Expression *isExpression(Object *o)
+{
+    //return dynamic_cast<Expression *>(o);
+    if (!o || o->dyncast() != DYNCAST_EXPRESSION)
+	return NULL;
+    return (Expression *)o;
+}
+
+Dsymbol *isDsymbol(Object *o)
+{
+    //return dynamic_cast<Dsymbol *>(o);
+    if (!o || o->dyncast() != DYNCAST_DSYMBOL)
+	return NULL;
+    return (Dsymbol *)o;
+}
+
+Type *isType(Object *o)
+{
+    //return dynamic_cast<Type *>(o);
+    if (!o || o->dyncast() != DYNCAST_TYPE)
+	return NULL;
+    return (Type *)o;
+}
+
+Tuple *isTuple(Object *o)
+{
+    //return dynamic_cast<Tuple *>(o);
+    if (!o || o->dyncast() != DYNCAST_TUPLE)
+	return NULL;
+    return (Tuple *)o;
+}
+
+
+/***********************
+ * Try to get arg as a type.
+ */
+
+Type *getType(Object *o)
+{
+    Type *t = isType(o);
+    if (!t)
+    {   Expression *e = isExpression(o);
+	if (e)
+	    t = e->type;
+    }
+    return t;
+}
+
+Dsymbol *getDsymbol(Object *oarg)
+{
+    Dsymbol *sa;
+    Expression *ea = isExpression(oarg);
+    if (ea)
+    {   // Try to convert Expression to symbol
+	if (ea->op == TOKvar)
+	    sa = ((VarExp *)ea)->var;
+	else if (ea->op == TOKfunction)
+	    sa = ((FuncExp *)ea)->fd;
+	else
+	    sa = NULL;
+    }
+    else
+    {   // Try to convert Type to symbol
+	Type *ta = isType(oarg);
+	if (ta)
+	    sa = ta->toDsymbol(NULL);
+	else
+	    sa = isDsymbol(oarg);	// if already a symbol
+    }
+    return sa;
+}
+
+/******************************
+ * If o1 matches o2, return 1.
+ * Else, return 0.
+ */
+
+int match(Object *o1, Object *o2, TemplateDeclaration *tempdecl, Scope *sc)
+{
+    Type *t1 = isType(o1);
+    Type *t2 = isType(o2);
+    Expression *e1 = isExpression(o1);
+    Expression *e2 = isExpression(o2);
+    Dsymbol *s1 = isDsymbol(o1);
+    Dsymbol *s2 = isDsymbol(o2);
+    Tuple *v1 = isTuple(o1);
+    Tuple *v2 = isTuple(o2);
+
+    //printf("\t match t1 %p t2 %p, e1 %p e2 %p, s1 %p s2 %p, v1 %p v2 %p\n", t1,t2,e1,e2,s1,s2,v1,v2);
+
+    /* A proper implementation of the various equals() overrides
+     * should make it possible to just do o1->equals(o2), but
+     * we'll do that another day.
+     */
+
+    if (t1)
+    {
+	/* if t1 is an instance of ti, then give error
+	 * about recursive expansions.
+	 */
+	Dsymbol *s = t1->toDsymbol(sc);
+	if (s && s->parent)
+	{   TemplateInstance *ti1 = s->parent->isTemplateInstance();
+	    if (ti1 && ti1->tempdecl == tempdecl)
+	    {
+		for (Scope *sc1 = sc; sc1; sc1 = sc1->enclosing)
+		{
+		    if (sc1->scopesym == ti1)
+		    {
+			error("recursive template expansion for template argument %s", t1->toChars());
+			return 1;	// fake a match
+		    }
+		}
+	    }
+	}
+
+	//printf("t1 = %s\n", t1->toChars());
+	//printf("t2 = %s\n", t2->toChars());
+	if (!t2 || !t1->equals(t2))
+	    goto Lnomatch;
+    }
+    else if (e1)
+    {
+#if 0
+	if (e1 && e2)
+	{
+	    printf("match %d\n", e1->equals(e2));
+	    e1->print();
+	    e2->print();
+	    e1->type->print();
+	    e2->type->print();
+	}
+#endif
+	if (!e2)
+	    goto Lnomatch;
+	if (!e1->equals(e2))
+	    goto Lnomatch;
+    }
+    else if (s1)
+    {
+	//printf("%p %s, %p %s\n", s1, s1->toChars(), s2, s2->toChars());
+	if (!s2 || !s1->equals(s2) || s1->parent != s2->parent)
+	{
+	    goto Lnomatch;
+	}
+#if DMDV2
+	VarDeclaration *v1 = s1->isVarDeclaration();
+	VarDeclaration *v2 = s2->isVarDeclaration();
+	if (v1 && v2 && v1->storage_class & v2->storage_class & STCmanifest)
+	{   ExpInitializer *ei1 = v1->init->isExpInitializer();
+	    ExpInitializer *ei2 = v2->init->isExpInitializer();
+	    if (ei1 && ei2 && !ei1->exp->equals(ei2->exp))
+		goto Lnomatch;
+	}
+#endif
+    }
+    else if (v1)
+    {
+	if (!v2)
+	    goto Lnomatch;
+	if (v1->objects.dim != v2->objects.dim)
+	    goto Lnomatch;
+	for (size_t i = 0; i < v1->objects.dim; i++)
+	{
+	    if (!match((Object *)v1->objects.data[i],
+		       (Object *)v2->objects.data[i],
+		       tempdecl, sc))
+		goto Lnomatch;
+	}
+    }
+    //printf("match\n");
+    return 1;	// match
+Lnomatch:
+    //printf("nomatch\n");
+    return 0;	// nomatch;
+}
+
+/****************************************
+ */
+
+void ObjectToCBuffer(OutBuffer *buf, HdrGenState *hgs, Object *oarg)
+{
+    //printf("ObjectToCBuffer()\n");
+    Type *t = isType(oarg);
+    Expression *e = isExpression(oarg);
+    Dsymbol *s = isDsymbol(oarg);
+    Tuple *v = isTuple(oarg);
+    if (t)
+    {	//printf("\tt: %s ty = %d\n", t->toChars(), t->ty);
+	t->toCBuffer(buf, NULL, hgs);
+    }
+    else if (e)
+	e->toCBuffer(buf, hgs);
+    else if (s)
+    {
+	char *p = s->ident ? s->ident->toChars() : s->toChars();
+	buf->writestring(p);
+    }
+    else if (v)
+    {
+	Objects *args = &v->objects;
+	for (size_t i = 0; i < args->dim; i++)
+	{
+	    if (i)
+		buf->writeByte(',');
+	    Object *o = (Object *)args->data[i];
+	    ObjectToCBuffer(buf, hgs, o);
+	}
+    }
+    else if (!oarg)
+    {
+	buf->writestring("NULL");
+    }
+    else
+    {
+#ifdef DEBUG
+	printf("bad Object = %p\n", oarg);
+#endif
+	assert(0);
+    }
+}
+
+#if DMDV2
+Object *objectSyntaxCopy(Object *o)
+{
+    if (!o)
+	return NULL;
+    Type *t = isType(o);
+    if (t)
+	return t->syntaxCopy();
+    Expression *e = isExpression(o);
+    if (e)
+	return e->syntaxCopy();
+    return o;
+}
+#endif
+
+
+/* ======================== TemplateDeclaration ============================= */
+
+TemplateDeclaration::TemplateDeclaration(Loc loc, Identifier *id,
+	TemplateParameters *parameters, Expression *constraint, Array *decldefs)
+    : ScopeDsymbol(id)
+{
+#if LOG
+    printf("TemplateDeclaration(this = %p, id = '%s')\n", this, id->toChars());
+#endif
+#if 0
+    if (parameters)
+	for (int i = 0; i < parameters->dim; i++)
+	{   TemplateParameter *tp = (TemplateParameter *)parameters->data[i];
+	    //printf("\tparameter[%d] = %p\n", i, tp);
+	    TemplateTypeParameter *ttp = tp->isTemplateTypeParameter();
+
+	    if (ttp)
+	    {
+		printf("\tparameter[%d] = %s : %s\n", i, tp->ident->toChars(), ttp->specType ? ttp->specType->toChars() : "");
+	    }
+	}
+#endif
+    this->loc = loc;
+    this->parameters = parameters;
+    this->origParameters = parameters;
+    this->constraint = constraint;
+    this->members = decldefs;
+    this->overnext = NULL;
+    this->overroot = NULL;
+    this->scope = NULL;
+    this->onemember = NULL;
+    this->literal = 0;
+}
+
+Dsymbol *TemplateDeclaration::syntaxCopy(Dsymbol *)
+{
+    //printf("TemplateDeclaration::syntaxCopy()\n");
+    TemplateDeclaration *td;
+    TemplateParameters *p;
+    Array *d;
+
+    p = NULL;
+    if (parameters)
+    {
+	p = new TemplateParameters();
+	p->setDim(parameters->dim);
+	for (int i = 0; i < p->dim; i++)
+	{   TemplateParameter *tp = (TemplateParameter *)parameters->data[i];
+	    p->data[i] = (void *)tp->syntaxCopy();
+	}
+    }
+    Expression *e = NULL;
+    if (constraint)
+	e = constraint->syntaxCopy();
+    d = Dsymbol::arraySyntaxCopy(members);
+    td = new TemplateDeclaration(loc, ident, p, e, d);
+
+#if IN_LLVM
+    // LDC
+    td->intrinsicName = intrinsicName;
+#endif
+
+    return td;
+}
+
+void TemplateDeclaration::semantic(Scope *sc)
+{
+#if LOG
+    printf("TemplateDeclaration::semantic(this = %p, id = '%s')\n", this, ident->toChars());
+#endif
+    if (scope)
+	return;		// semantic() already run
+
+    if (sc->func)
+    {
+#if DMDV1
+	error("cannot declare template at function scope %s", sc->func->toChars());
+#endif
+    }
+
+    if (/*global.params.useArrayBounds &&*/ sc->module)
+    {
+	// Generate this function as it may be used
+	// when template is instantiated in other modules
+
+	// FIXME: LDC
+	//sc->module->toModuleArray();
+    }
+
+    if (/*global.params.useAssert &&*/ sc->module)
+    {
+	// Generate this function as it may be used
+	// when template is instantiated in other modules
+
+	// FIXME: LDC
+	//sc->module->toModuleAssert();
+    }
+
+    /* Remember Scope for later instantiations, but make
+     * a copy since attributes can change.
+     */
+    this->scope = new Scope(*sc);
+    this->scope->setNoFree();
+
+    // Set up scope for parameters
+    ScopeDsymbol *paramsym = new ScopeDsymbol();
+    paramsym->parent = sc->parent;
+    Scope *paramscope = sc->push(paramsym);
+    paramscope->parameterSpecialization = 1;
+    paramscope->stc = 0;
+
+    if (!parent)
+	parent = sc->parent;
+
+    if (global.params.doDocComments)
+    {
+	origParameters = new TemplateParameters();
+	origParameters->setDim(parameters->dim);
+	for (int i = 0; i < parameters->dim; i++)
+	{
+	    TemplateParameter *tp = (TemplateParameter *)parameters->data[i];
+	    origParameters->data[i] = (void *)tp->syntaxCopy();
+	}
+    }
+
+    for (int i = 0; i < parameters->dim; i++)
+    {
+	TemplateParameter *tp = (TemplateParameter *)parameters->data[i];
+
+	tp->declareParameter(paramscope);
+    }
+
+    for (int i = 0; i < parameters->dim; i++)
+    {
+	TemplateParameter *tp = (TemplateParameter *)parameters->data[i];
+
+	tp->semantic(paramscope);
+	if (i + 1 != parameters->dim && tp->isTemplateTupleParameter())
+	    error("template tuple parameter must be last one");
+    }
+
+    paramscope->pop();
+
+    if (members)
+    {
+	Dsymbol *s;
+	if (Dsymbol::oneMembers(members, &s))
+	{
+	    if (s && s->ident && s->ident->equals(ident))
+	    {
+		onemember = s;
+		s->parent = this;
+	    }
+	}
+    }
+
+    /* BUG: should check:
+     *	o no virtual functions or non-static data members of classes
+     */
+}
+
+const char *TemplateDeclaration::kind()
+{
+    return (onemember && onemember->isAggregateDeclaration())
+		? onemember->kind()
+		: (char *)"template";
+}
+
+/**********************************
+ * Overload existing TemplateDeclaration 'this' with the new one 's'.
+ * Return !=0 if successful; i.e. no conflict.
+ */
+
+int TemplateDeclaration::overloadInsert(Dsymbol *s)
+{
+    TemplateDeclaration **pf;
+    TemplateDeclaration *f;
+
+#if LOG
+    printf("TemplateDeclaration::overloadInsert('%s')\n", s->toChars());
+#endif
+    f = s->isTemplateDeclaration();
+    if (!f)
+	return FALSE;
+    TemplateDeclaration *pthis = this;
+    for (pf = &pthis; *pf; pf = &(*pf)->overnext)
+    {
+#if 0
+	// Conflict if TemplateParameter's match
+	// Will get caught anyway later with TemplateInstance, but
+	// should check it now.
+	TemplateDeclaration *f2 = *pf;
+
+	if (f->parameters->dim != f2->parameters->dim)
+	    goto Lcontinue;
+
+	for (int i = 0; i < f->parameters->dim; i++)
+	{   TemplateParameter *p1 = (TemplateParameter *)f->parameters->data[i];
+	    TemplateParameter *p2 = (TemplateParameter *)f2->parameters->data[i];
+
+	    if (!p1->overloadMatch(p2))
+		goto Lcontinue;
+	}
+
+#if LOG
+	printf("\tfalse: conflict\n");
+#endif
+	return FALSE;
+
+     Lcontinue:
+	;
+#endif
+    }
+
+    f->overroot = this;
+    *pf = f;
+#if LOG
+    printf("\ttrue: no conflict\n");
+#endif
+    return TRUE;
+}
+
+/***************************************
+ * Given that ti is an instance of this TemplateDeclaration,
+ * deduce the types of the parameters to this, and store
+ * those deduced types in dedtypes[].
+ * Input:
+ *	flag	1: don't do semantic() because of dummy types
+ *		2: don't change types in matchArg()
+ * Output:
+ *	dedtypes	deduced arguments
+ * Return match level.
+ */
+
+MATCH TemplateDeclaration::matchWithInstance(TemplateInstance *ti,
+	Objects *dedtypes, int flag)
+{   MATCH m;
+    int dedtypes_dim = dedtypes->dim;
+
+#define LOGM 0
+#if LOGM
+    printf("\n+TemplateDeclaration::matchWithInstance(this = %s, ti = %s, flag = %d)\n", toChars(), ti->toChars(), flag);
+#endif
+
+#if 0
+    printf("dedtypes->dim = %d, parameters->dim = %d\n", dedtypes_dim, parameters->dim);
+    if (ti->tiargs->dim)
+	printf("ti->tiargs->dim = %d, [0] = %p\n",
+	    ti->tiargs->dim,
+	    ti->tiargs->data[0]);
+#endif
+    dedtypes->zero();
+
+    int parameters_dim = parameters->dim;
+    int variadic = isVariadic() != NULL;
+
+    // If more arguments than parameters, no match
+    if (ti->tiargs->dim > parameters_dim && !variadic)
+    {
+#if LOGM
+	printf(" no match: more arguments than parameters\n");
+#endif
+	return MATCHnomatch;
+    }
+
+    assert(dedtypes_dim == parameters_dim);
+    assert(dedtypes_dim >= ti->tiargs->dim || variadic);
+
+    // Set up scope for parameters
+    assert((size_t)scope > 0x10000);
+    ScopeDsymbol *paramsym = new ScopeDsymbol();
+    paramsym->parent = scope->parent;
+    Scope *paramscope = scope->push(paramsym);
+    paramscope->stc = 0;
+
+    // Attempt type deduction
+    m = MATCHexact;
+    for (int i = 0; i < dedtypes_dim; i++)
+    {	MATCH m2;
+	TemplateParameter *tp = (TemplateParameter *)parameters->data[i];
+	Declaration *sparam;
+
+	//printf("\targument [%d]\n", i);
+#if LOGM
+	//printf("\targument [%d] is %s\n", i, oarg ? oarg->toChars() : "null");
+	TemplateTypeParameter *ttp = tp->isTemplateTypeParameter();
+	if (ttp)
+	    printf("\tparameter[%d] is %s : %s\n", i, tp->ident->toChars(), ttp->specType ? ttp->specType->toChars() : "");
+#endif
+
+#if DMDV1
+	m2 = tp->matchArg(paramscope, ti->tiargs, i, parameters, dedtypes, &sparam);
+#else
+	m2 = tp->matchArg(paramscope, ti->tiargs, i, parameters, dedtypes, &sparam, (flag & 2) ? 1 : 0);
+
+#endif
+	//printf("\tm2 = %d\n", m2);
+
+	if (m2 == MATCHnomatch)
+	{
+#if 0
+	    printf("\tmatchArg() for parameter %i failed\n", i);
+#endif
+	    goto Lnomatch;
+	}
+
+	if (m2 < m)
+	    m = m2;
+
+	if (!flag)
+	    sparam->semantic(paramscope);
+	if (!paramscope->insert(sparam))
+	    goto Lnomatch;
+    }
+
+    if (!flag)
+    {
+	/* Any parameter left without a type gets the type of
+	 * its corresponding arg
+	 */
+	for (int i = 0; i < dedtypes_dim; i++)
+	{
+	    if (!dedtypes->data[i])
+	    {   assert(i < ti->tiargs->dim);
+		dedtypes->data[i] = ti->tiargs->data[i];
+	    }
+	}
+    }
+
+#if DMDV2
+    if (m && constraint && !(flag & 1))
+    {	/* Check to see if constraint is satisfied.
+	 */
+	Expression *e = constraint->syntaxCopy();
+	paramscope->flags |= SCOPEstaticif;
+	e = e->semantic(paramscope);
+	e = e->optimize(WANTvalue | WANTinterpret);
+        if (e->isBool(TRUE))
+            ;
+        else if (e->isBool(FALSE))
+            goto Lnomatch;
+        else
+        {
+            e->error("constraint %s is not constant or does not evaluate to a bool", e->toChars());
+        }
+    }
+#endif
+
+#if LOGM
+    // Print out the results
+    printf("--------------------------\n");
+    printf("template %s\n", toChars());
+    printf("instance %s\n", ti->toChars());
+    if (m)
+    {
+	for (int i = 0; i < dedtypes_dim; i++)
+	{
+	    TemplateParameter *tp = (TemplateParameter *)parameters->data[i];
+	    Object *oarg;
+
+	    printf(" [%d]", i);
+
+	    if (i < ti->tiargs->dim)
+		oarg = (Object *)ti->tiargs->data[i];
+	    else
+		oarg = NULL;
+	    tp->print(oarg, (Object *)dedtypes->data[i]);
+	}
+    }
+    else
+	goto Lnomatch;
+#endif
+
+#if LOGM
+    printf(" match = %d\n", m);
+#endif
+    goto Lret;
+
+Lnomatch:
+#if LOGM
+    printf(" no match\n");
+#endif
+    m = MATCHnomatch;
+
+Lret:
+    paramscope->pop();
+#if LOGM
+    printf("-TemplateDeclaration::matchWithInstance(this = %p, ti = %p) = %d\n", this, ti, m);
+#endif
+    return m;
+}
+
+/********************************************
+ * Determine partial specialization order of 'this' vs td2.
+ * Returns:
+ *	match	this is at least as specialized as td2
+ *	0	td2 is more specialized than this
+ */
+
+MATCH TemplateDeclaration::leastAsSpecialized(TemplateDeclaration *td2)
+{
+    /* This works by taking the template parameters to this template
+     * declaration and feeding them to td2 as if it were a template
+     * instance.
+     * If it works, then this template is at least as specialized
+     * as td2.
+     */
+
+    TemplateInstance ti(0, ident);	// create dummy template instance
+    Objects dedtypes;
+
+#define LOG_LEASTAS	0
+
+#if LOG_LEASTAS
+    printf("%s.leastAsSpecialized(%s)\n", toChars(), td2->toChars());
+#endif
+
+    // Set type arguments to dummy template instance to be types
+    // generated from the parameters to this template declaration
+    ti.tiargs = new Objects();
+    ti.tiargs->setDim(parameters->dim);
+    for (int i = 0; i < ti.tiargs->dim; i++)
+    {
+	TemplateParameter *tp = (TemplateParameter *)parameters->data[i];
+
+	void *p = tp->dummyArg();
+	if (p)
+	    ti.tiargs->data[i] = p;
+	else
+	    ti.tiargs->setDim(i);
+    }
+
+    // Temporary Array to hold deduced types
+    //dedtypes.setDim(parameters->dim);
+    dedtypes.setDim(td2->parameters->dim);
+
+    // Attempt a type deduction
+    MATCH m = td2->matchWithInstance(&ti, &dedtypes, 1);
+    if (m)
+    {
+	/* A non-variadic template is more specialized than a
+	 * variadic one.
+	 */
+	if (isVariadic() && !td2->isVariadic())
+	    goto L1;
+
+#if LOG_LEASTAS
+	printf("  matches %d, so is least as specialized\n", m);
+#endif
+	return m;
+    }
+  L1:
+#if LOG_LEASTAS
+    printf("  doesn't match, so is not as specialized\n");
+#endif
+    return MATCHnomatch;
+}
+
+
+/*************************************************
+ * Match function arguments against a specific template function.
+ * Input:
+ *	loc		instantiation location
+ *	targsi		Expression/Type initial list of template arguments
+ *	ethis		'this' argument if !NULL
+ *	fargs		arguments to function
+ * Output:
+ *	dedargs		Expression/Type deduced template arguments
+ * Returns:
+ *	match level
+ */
+
+MATCH TemplateDeclaration::deduceFunctionTemplateMatch(Loc loc, Objects *targsi,
+	Expression *ethis, Expressions *fargs,
+	Objects *dedargs)
+{
+    size_t i;
+    size_t nfparams;
+    size_t nfargs;
+    size_t nargsi;		// array size of targsi
+    int fptupindex = -1;
+    int tuple_dim = 0;
+    MATCH match = MATCHexact;
+    FuncDeclaration *fd = onemember->toAlias()->isFuncDeclaration();
+    Arguments *fparameters;		// function parameter list
+    int fvarargs;			// function varargs
+    Objects dedtypes;	// for T:T*, the dedargs is the T*, dedtypes is the T
+
+#if 0
+    printf("\nTemplateDeclaration::deduceFunctionTemplateMatch() %s\n", toChars());
+    for (i = 0; i < fargs->dim; i++)
+    {	Expression *e = (Expression *)fargs->data[i];
+	printf("\tfarg[%d] is %s, type is %s\n", i, e->toChars(), e->type->toChars());
+    }
+    printf("fd = %s\n", fd->toChars());
+    printf("fd->type = %p\n", fd->type);
+#endif
+
+    assert((size_t)scope > 0x10000);
+
+    dedargs->setDim(parameters->dim);
+    dedargs->zero();
+
+    dedtypes.setDim(parameters->dim);
+    dedtypes.zero();
+
+    // Set up scope for parameters
+    ScopeDsymbol *paramsym = new ScopeDsymbol();
+    paramsym->parent = scope->parent;
+    Scope *paramscope = scope->push(paramsym);
+
+    TemplateTupleParameter *tp = isVariadic();
+
+#if 0
+    for (i = 0; i < dedargs->dim; i++)
+    {
+	printf("\tdedarg[%d] = ", i);
+	Object *oarg = (Object *)dedargs->data[i];
+	if (oarg) printf("%s", oarg->toChars());
+	printf("\n");
+    }
+#endif
+
+
+    nargsi = 0;
+    if (targsi)
+    {	// Set initial template arguments
+	size_t n;
+
+	nargsi = targsi->dim;
+	n = parameters->dim;
+	if (tp)
+	    n--;
+	if (nargsi > n)
+	{   if (!tp)
+		goto Lnomatch;
+
+	    /* The extra initial template arguments
+	     * now form the tuple argument.
+	     */
+	    Tuple *t = new Tuple();
+	    assert(parameters->dim);
+	    dedargs->data[parameters->dim - 1] = (void *)t;
+
+	    tuple_dim = nargsi - n;
+	    t->objects.setDim(tuple_dim);
+	    for (size_t i = 0; i < tuple_dim; i++)
+	    {
+		t->objects.data[i] = (void *)targsi->data[n + i];
+	    }
+	    declareParameter(paramscope, tp, t);
+	}
+	else
+	    n = nargsi;
+
+	memcpy(dedargs->data, targsi->data, n * sizeof(*dedargs->data));
+
+	for (size_t i = 0; i < n; i++)
+	{   assert(i < parameters->dim);
+	    TemplateParameter *tp = (TemplateParameter *)parameters->data[i];
+	    MATCH m;
+	    Declaration *sparam = NULL;
+
+	    m = tp->matchArg(paramscope, dedargs, i, parameters, &dedtypes, &sparam);
+	    //printf("\tdeduceType m = %d\n", m);
+	    if (m == MATCHnomatch)
+		goto Lnomatch;
+	    if (m < match)
+		match = m;
+
+	    sparam->semantic(paramscope);
+	    if (!paramscope->insert(sparam))
+		goto Lnomatch;
+	}
+    }
+#if 0
+    for (i = 0; i < dedargs->dim; i++)
+    {
+	printf("\tdedarg[%d] = ", i);
+	Object *oarg = (Object *)dedargs->data[i];
+	if (oarg) printf("%s", oarg->toChars());
+	printf("\n");
+    }
+#endif
+
+    if (fd->type)
+    {
+	assert(fd->type->ty == Tfunction);
+	TypeFunction *fdtype = (TypeFunction *)fd->type;
+	fparameters = fdtype->parameters;
+	fvarargs = fdtype->varargs;
+    }
+    else
+    {	CtorDeclaration *fctor = fd->isCtorDeclaration();
+	assert(fctor);
+	fparameters = fctor->arguments;
+	fvarargs = fctor->varargs;
+    }
+
+    nfparams = Argument::dim(fparameters); // number of function parameters
+    nfargs = fargs->dim;		// number of function arguments
+
+    /* Check for match of function arguments with variadic template
+     * parameter, such as:
+     *
+     * template Foo(T, A...) { void Foo(T t, A a); }
+     * void main() { Foo(1,2,3); }
+     */
+    if (tp)				// if variadic
+    {
+	if (nfparams == 0)		// if no function parameters
+	{
+	    Tuple *t = new Tuple();
+	    //printf("t = %p\n", t);
+	    dedargs->data[parameters->dim - 1] = (void *)t;
+	    declareParameter(paramscope, tp, t);
+	    goto L2;
+	}
+	else if (nfargs < nfparams - 1)
+	    goto L1;
+	else
+	{
+	    /* Figure out which of the function parameters matches
+	     * the tuple template parameter. Do this by matching
+	     * type identifiers.
+	     * Set the index of this function parameter to fptupindex.
+	     */
+	    for (fptupindex = 0; fptupindex < nfparams; fptupindex++)
+	    {
+		Argument *fparam = (Argument *)fparameters->data[fptupindex];
+		if (fparam->type->ty != Tident)
+		    continue;
+		TypeIdentifier *tid = (TypeIdentifier *)fparam->type;
+		if (!tp->ident->equals(tid->ident) || tid->idents.dim)
+		    continue;
+
+		if (fvarargs)		// variadic function doesn't
+		    goto Lnomatch;	// go with variadic template
+
+		/* The types of the function arguments
+		 * now form the tuple argument.
+		 */
+		Tuple *t = new Tuple();
+		dedargs->data[parameters->dim - 1] = (void *)t;
+
+		tuple_dim = nfargs - (nfparams - 1);
+		t->objects.setDim(tuple_dim);
+		for (i = 0; i < tuple_dim; i++)
+		{   Expression *farg = (Expression *)fargs->data[fptupindex + i];
+		    t->objects.data[i] = (void *)farg->type;
+		}
+		declareParameter(paramscope, tp, t);
+		goto L2;
+	    }
+	    fptupindex = -1;
+	}
+    }
+
+L1:
+    if (nfparams == nfargs)
+	;
+    else if (nfargs > nfparams)
+    {
+	if (fvarargs == 0)
+	    goto Lnomatch;		// too many args, no match
+	match = MATCHconvert;		// match ... with a conversion
+    }
+
+L2:
+#if DMDV2
+    // Match 'ethis' to any TemplateThisParameter's
+    if (ethis)
+    {
+	for (size_t i = 0; i < parameters->dim; i++)
+	{   TemplateParameter *tp = (TemplateParameter *)parameters->data[i];
+	    TemplateThisParameter *ttp = tp->isTemplateThisParameter();
+	    if (ttp)
+	    {	MATCH m;
+
+		Type *t = new TypeIdentifier(0, ttp->ident);
+		m = ethis->type->deduceType(paramscope, t, parameters, &dedtypes);
+		if (!m)
+		    goto Lnomatch;
+		if (m < match)
+		    match = m;		// pick worst match
+	    }
+	}
+    }
+#endif
+
+    // Loop through the function parameters
+    for (i = 0; i < nfparams; i++)
+    {
+	/* Skip over function parameters which wound up
+	 * as part of a template tuple parameter.
+	 */
+	if (i == fptupindex)
+	{   if (fptupindex == nfparams - 1)
+		break;
+	    i += tuple_dim - 1;
+	    continue;
+	}
+
+	Argument *fparam = Argument::getNth(fparameters, i);
+
+	if (i >= nfargs)		// if not enough arguments
+	{
+	    if (fparam->defaultArg)
+	    {	/* Default arguments do not participate in template argument
+		 * deduction.
+		 */
+		goto Lmatch;
+	    }
+	}
+	else
+	{   Expression *farg = (Expression *)fargs->data[i];
+#if 0
+	    printf("\tfarg->type   = %s\n", farg->type->toChars());
+	    printf("\tfparam->type = %s\n", fparam->type->toChars());
+#endif
+	    Type *argtype = farg->type;
+
+#if DMDV2
+	    /* Allow string literals which are type [] to match with [dim]
+	     */
+	    if (farg->op == TOKstring)
+	    {	StringExp *se = (StringExp *)farg;
+		if (!se->committed && argtype->ty == Tarray &&
+		    fparam->type->toBasetype()->ty == Tsarray)
+		{
+		    argtype = new TypeSArray(argtype->nextOf(), new IntegerExp(se->loc, se->len, Type::tindex));
+		    argtype = argtype->semantic(se->loc, NULL);
+		    argtype = argtype->invariantOf();
+		}
+	    }
+#endif
+
+	    MATCH m;
+	    m = argtype->deduceType(paramscope, fparam->type, parameters, &dedtypes);
+	    //printf("\tdeduceType m = %d\n", m);
+
+	    /* If no match, see if there's a conversion to a delegate
+	     */
+	    if (!m && fparam->type->toBasetype()->ty == Tdelegate)
+	    {
+		TypeDelegate *td = (TypeDelegate *)fparam->type->toBasetype();
+		TypeFunction *tf = (TypeFunction *)td->next;
+
+		if (!tf->varargs && Argument::dim(tf->parameters) == 0)
+		{
+		    m = farg->type->deduceType(paramscope, tf->next, parameters, &dedtypes);
+		    if (!m && tf->next->toBasetype()->ty == Tvoid)
+			m = MATCHconvert;
+		}
+		//printf("\tm2 = %d\n", m);
+	    }
+
+	    if (m)
+	    {	if (m < match)
+		    match = m;		// pick worst match
+		continue;
+	    }
+	}
+
+	/* The following code for variadic arguments closely
+	 * matches TypeFunction::callMatch()
+	 */
+	if (!(fvarargs == 2 && i + 1 == nfparams))
+	    goto Lnomatch;
+
+	/* Check for match with function parameter T...
+	 */
+	Type *tb = fparam->type->toBasetype();
+	switch (tb->ty)
+	{
+	    // Perhaps we can do better with this, see TypeFunction::callMatch()
+	    case Tsarray:
+	    {	TypeSArray *tsa = (TypeSArray *)tb;
+		dinteger_t sz = tsa->dim->toInteger();
+		if (sz != nfargs - i)
+		    goto Lnomatch;
+	    }
+	    case Tarray:
+	    {   TypeArray *ta = (TypeArray *)tb;
+		for (; i < nfargs; i++)
+		{
+		    Expression *arg = (Expression *)fargs->data[i];
+		    assert(arg);
+		    MATCH m;
+		    /* If lazy array of delegates,
+		     * convert arg(s) to delegate(s)
+		     */
+		    Type *tret = fparam->isLazyArray();
+		    if (tret)
+		    {
+			if (ta->next->equals(arg->type))
+			{   m = MATCHexact;
+			}
+			else
+			{
+			    m = arg->implicitConvTo(tret);
+			    if (m == MATCHnomatch)
+			    {
+				if (tret->toBasetype()->ty == Tvoid)
+				    m = MATCHconvert;
+			    }
+			}
+		    }
+		    else
+		    {
+			m = arg->type->deduceType(paramscope, ta->next, parameters, &dedtypes);
+			//m = arg->implicitConvTo(ta->next);
+		    }
+		    if (m == MATCHnomatch)
+			goto Lnomatch;
+		    if (m < match)
+			match = m;
+		}
+		goto Lmatch;
+	    }
+	    case Tclass:
+	    case Tident:
+		goto Lmatch;
+
+	    default:
+		goto Lnomatch;
+	}
+    }
+
+Lmatch:
+
+    /* Fill in any missing arguments with their defaults.
+     */
+    for (i = nargsi; i < dedargs->dim; i++)
+    {
+	TemplateParameter *tp = (TemplateParameter *)parameters->data[i];
+	//printf("tp[%d] = %s\n", i, tp->ident->toChars());
+	/* For T:T*, the dedargs is the T*, dedtypes is the T
+	 * But for function templates, we really need them to match
+	 */
+	Object *oarg = (Object *)dedargs->data[i];
+	Object *oded = (Object *)dedtypes.data[i];
+	//printf("1dedargs[%d] = %p, dedtypes[%d] = %p\n", i, oarg, i, oded);
+	//if (oarg) printf("oarg: %s\n", oarg->toChars());
+	//if (oded) printf("oded: %s\n", oded->toChars());
+	if (!oarg)
+	{
+	    if (oded)
+	    {
+		if (tp->specialization())
+		{   /* The specialization can work as long as afterwards
+		     * the oded == oarg
+		     */
+		    Declaration *sparam;
+		    dedargs->data[i] = (void *)oded;
+		    MATCH m2 = tp->matchArg(paramscope, dedargs, i, parameters, &dedtypes, &sparam, 0);
+		    //printf("m2 = %d\n", m2);
+		    if (!m2)
+			goto Lnomatch;
+		    if (m2 < match)
+			match = m2;		// pick worst match
+		    if (dedtypes.data[i] != oded)
+			error("specialization not allowed for deduced parameter %s", tp->ident->toChars());
+		}
+	    }
+	    else
+	    {	oded = tp->defaultArg(loc, paramscope);
+		if (!oded)
+		    goto Lnomatch;
+	    }
+	    declareParameter(paramscope, tp, oded);
+	    dedargs->data[i] = (void *)oded;
+	}
+    }
+
+#if DMDV2
+    if (constraint)
+    {	/* Check to see if constraint is satisfied.
+	 */
+	Expression *e = constraint->syntaxCopy();
+	paramscope->flags |= SCOPEstaticif;
+	e = e->semantic(paramscope);
+	e = e->optimize(WANTvalue | WANTinterpret);
+        if (e->isBool(TRUE))
+            ;
+        else if (e->isBool(FALSE))
+            goto Lnomatch;
+        else
+        {
+            e->error("constraint %s is not constant or does not evaluate to a bool", e->toChars());
+        }
+    }
+#endif
+
+#if 0
+    for (i = 0; i < dedargs->dim; i++)
+    {	Type *t = (Type *)dedargs->data[i];
+	printf("\tdedargs[%d] = %d, %s\n", i, t->dyncast(), t->toChars());
+    }
+#endif
+
+    paramscope->pop();
+    //printf("\tmatch %d\n", match);
+    return match;
+
+Lnomatch:
+    paramscope->pop();
+    //printf("\tnomatch\n");
+    return MATCHnomatch;
+}
+
+/**************************************************
+ * Declare template parameter tp with value o, and install it in the scope sc.
+ */
+
+void TemplateDeclaration::declareParameter(Scope *sc, TemplateParameter *tp, Object *o)
+{
+    //printf("TemplateDeclaration::declareParameter('%s', o = %p)\n", tp->ident->toChars(), o);
+
+    Type *targ = isType(o);
+    Expression *ea = isExpression(o);
+    Dsymbol *sa = isDsymbol(o);
+    Tuple *va = isTuple(o);
+
+    Dsymbol *s;
+
+    // See if tp->ident already exists with a matching definition
+    Dsymbol *scopesym;
+    s = sc->search(loc, tp->ident, &scopesym);
+    if (s && scopesym == sc->scopesym)
+    {
+	TupleDeclaration *td = s->isTupleDeclaration();
+	if (va && td)
+	{   Tuple tup;
+	    tup.objects = *td->objects;
+	    if (match(va, &tup, this, sc))
+	    {
+		return;
+	    }
+	}
+    }
+
+    if (targ)
+    {
+	//printf("type %s\n", targ->toChars());
+	s = new AliasDeclaration(0, tp->ident, targ);
+    }
+    else if (sa)
+    {
+	//printf("Alias %s %s;\n", sa->ident->toChars(), tp->ident->toChars());
+	s = new AliasDeclaration(0, tp->ident, sa);
+    }
+    else if (ea)
+    {
+	// tdtypes.data[i] always matches ea here
+	Initializer *init = new ExpInitializer(loc, ea);
+	TemplateValueParameter *tvp = tp->isTemplateValueParameter();
+
+	Type *t = tvp ? tvp->valType : NULL;
+
+	VarDeclaration *v = new VarDeclaration(loc, t, tp->ident, init);
+	v->storage_class = STCmanifest;
+	s = v;
+    }
+    else if (va)
+    {
+	//printf("\ttuple\n");
+	s = new TupleDeclaration(loc, tp->ident, &va->objects);
+    }
+    else
+    {
+#ifdef DEBUG
+	o->print();
+#endif
+	assert(0);
+    }
+    if (!sc->insert(s))
+	error("declaration %s is already defined", tp->ident->toChars());
+    s->semantic(sc);
+}
+
+/**************************************
+ * Determine if TemplateDeclaration is variadic.
+ */
+
+TemplateTupleParameter *isVariadic(TemplateParameters *parameters)
+{   size_t dim = parameters->dim;
+    TemplateTupleParameter *tp = NULL;
+
+    if (dim)
+	tp = ((TemplateParameter *)parameters->data[dim - 1])->isTemplateTupleParameter();
+    return tp;
+}
+
+TemplateTupleParameter *TemplateDeclaration::isVariadic()
+{
+    return ::isVariadic(parameters);
+}
+
+/***********************************
+ * We can overload templates.
+ */
+
+int TemplateDeclaration::isOverloadable()
+{
+    return 1;
+}
+
+/*************************************************
+ * Given function arguments, figure out which template function
+ * to expand, and return that function.
+ * If no match, give error message and return NULL.
+ * Input:
+ *	sc		instantiation scope
+ *	loc		instantiation location
+ *	targsi		initial list of template arguments
+ *	ethis		if !NULL, the 'this' pointer argument
+ *	fargs		arguments to function
+ *	flags		1: do not issue error message on no match, just return NULL
+ */
+
+FuncDeclaration *TemplateDeclaration::deduceFunctionTemplate(Scope *sc, Loc loc,
+	Objects *targsi, Expression *ethis, Expressions *fargs, int flags)
+{
+    MATCH m_best = MATCHnomatch;
+    TemplateDeclaration *td_ambig = NULL;
+    TemplateDeclaration *td_best = NULL;
+    Objects *tdargs = new Objects();
+    TemplateInstance *ti;
+    FuncDeclaration *fd;
+
+#if 0
+    printf("TemplateDeclaration::deduceFunctionTemplate() %s\n", toChars());
+    printf("    targsi:\n");
+    if (targsi)
+    {	for (int i = 0; i < targsi->dim; i++)
+	{   Object *arg = (Object *)targsi->data[i];
+	    printf("\t%s\n", arg->toChars());
+	}
+    }
+    printf("    fargs:\n");
+    for (int i = 0; i < fargs->dim; i++)
+    {	Expression *arg = (Expression *)fargs->data[i];
+	printf("\t%s %s\n", arg->type->toChars(), arg->toChars());
+	//printf("\tty = %d\n", arg->type->ty);
+    }
+#endif
+
+    for (TemplateDeclaration *td = this; td; td = td->overnext)
+    {
+	if (!td->scope)
+	{
+	    error("forward reference to template %s", td->toChars());
+	    goto Lerror;
+	}
+	if (!td->onemember || !td->onemember->toAlias()->isFuncDeclaration())
+	{
+	    error("is not a function template");
+	    goto Lerror;
+	}
+
+	MATCH m;
+	Objects dedargs;
+
+	m = td->deduceFunctionTemplateMatch(loc, targsi, ethis, fargs, &dedargs);
+	//printf("deduceFunctionTemplateMatch = %d\n", m);
+	if (!m)			// if no match
+	    continue;
+
+	if (m < m_best)
+	    goto Ltd_best;
+	if (m > m_best)
+	    goto Ltd;
+
+	{
+	// Disambiguate by picking the most specialized TemplateDeclaration
+	MATCH c1 = td->leastAsSpecialized(td_best);
+	MATCH c2 = td_best->leastAsSpecialized(td);
+	//printf("c1 = %d, c2 = %d\n", c1, c2);
+
+	if (c1 > c2)
+	    goto Ltd;
+	else if (c1 < c2)
+	    goto Ltd_best;
+	else
+	    goto Lambig;
+	}
+
+      Lambig:		// td_best and td are ambiguous
+	td_ambig = td;
+	continue;
+
+      Ltd_best:		// td_best is the best match so far
+	td_ambig = NULL;
+	continue;
+
+      Ltd:		// td is the new best match
+	td_ambig = NULL;
+	assert((size_t)td->scope > 0x10000);
+	td_best = td;
+	m_best = m;
+	tdargs->setDim(dedargs.dim);
+	memcpy(tdargs->data, dedargs.data, tdargs->dim * sizeof(void *));
+	continue;
+    }
+    if (!td_best)
+    {
+	if (!(flags & 1))
+	    error(loc, "does not match any function template declaration");
+	goto Lerror;
+    }
+    if (td_ambig)
+    {
+	error(loc, "matches more than one function template declaration:\n  %s\nand:\n  %s",
+		td_best->toChars(), td_ambig->toChars());
+    }
+
+    /* The best match is td_best with arguments tdargs.
+     * Now instantiate the template.
+     */
+    assert((size_t)td_best->scope > 0x10000);
+    ti = new TemplateInstance(loc, td_best, tdargs);
+    ti->semantic(sc);
+    fd = ti->toAlias()->isFuncDeclaration();
+    if (!fd)
+	goto Lerror;
+    return fd;
+
+  Lerror:
+#if DMDV2
+    if (!(flags & 1))
+#endif
+    {
+	HdrGenState hgs;
+
+	OutBuffer bufa;
+	Objects *args = targsi;
+	if (args)
+	{   for (int i = 0; i < args->dim; i++)
+	    {
+		if (i)
+		    bufa.writeByte(',');
+		Object *oarg = (Object *)args->data[i];
+		ObjectToCBuffer(&bufa, &hgs, oarg);
+	    }
+	}
+
+	OutBuffer buf;
+	argExpTypesToCBuffer(&buf, fargs, &hgs);
+	error(loc, "cannot deduce template function from argument types !(%s)(%s)",
+		bufa.toChars(), buf.toChars());
+    }
+    return NULL;
+}
+
+void TemplateDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+#if 0 // Should handle template functions
+    if (onemember && onemember->isFuncDeclaration())
+	buf->writestring("foo ");
+#endif
+    buf->writestring(kind());
+    buf->writeByte(' ');
+    buf->writestring(ident->toChars());
+    buf->writeByte('(');
+    for (int i = 0; i < parameters->dim; i++)
+    {
+	TemplateParameter *tp = (TemplateParameter *)parameters->data[i];
+	if (hgs->ddoc)
+	    tp = (TemplateParameter *)origParameters->data[i];
+	if (i)
+	    buf->writeByte(',');
+	tp->toCBuffer(buf, hgs);
+    }
+    buf->writeByte(')');
+#if DMDV2
+    if (constraint)
+    {	buf->writestring(" if (");
+	constraint->toCBuffer(buf, hgs);
+	buf->writeByte(')');
+    }
+#endif
+
+    if (hgs->hdrgen)
+    {
+	hgs->tpltMember++;
+	buf->writenl();
+	buf->writebyte('{');
+	buf->writenl();
+	for (int i = 0; i < members->dim; i++)
+	{
+	    Dsymbol *s = (Dsymbol *)members->data[i];
+	    s->toCBuffer(buf, hgs);
+	}
+	buf->writebyte('}');
+	buf->writenl();
+	hgs->tpltMember--;
+    }
+}
+
+
+char *TemplateDeclaration::toChars()
+{   OutBuffer buf;
+    HdrGenState hgs;
+
+    memset(&hgs, 0, sizeof(hgs));
+    buf.writestring(ident->toChars());
+    buf.writeByte('(');
+    for (int i = 0; i < parameters->dim; i++)
+    {
+	TemplateParameter *tp = (TemplateParameter *)parameters->data[i];
+	if (i)
+	    buf.writeByte(',');
+	tp->toCBuffer(&buf, &hgs);
+    }
+    buf.writeByte(')');
+#if DMDV2
+    if (constraint)
+    {	buf.writestring(" if (");
+	constraint->toCBuffer(&buf, &hgs);
+	buf.writeByte(')');
+    }
+#endif
+    buf.writeByte(0);
+    return (char *)buf.extractData();
+}
+
+/* ======================== Type ============================================ */
+
+/****
+ * Given an identifier, figure out which TemplateParameter it is.
+ * Return -1 if not found.
+ */
+
+int templateIdentifierLookup(Identifier *id, TemplateParameters *parameters)
+{
+    for (size_t i = 0; i < parameters->dim; i++)
+    {   TemplateParameter *tp = (TemplateParameter *)parameters->data[i];
+
+	if (tp->ident->equals(id))
+	    return i;
+    }
+    return -1;
+}
+
+int templateParameterLookup(Type *tparam, TemplateParameters *parameters)
+{
+    assert(tparam->ty == Tident);
+    TypeIdentifier *tident = (TypeIdentifier *)tparam;
+    //printf("\ttident = '%s'\n", tident->toChars());
+    if (tident->idents.dim == 0)
+    {
+	return templateIdentifierLookup(tident->ident, parameters);
+    }
+    return -1;
+}
+
+/* These form the heart of template argument deduction.
+ * Given 'this' being the type argument to the template instance,
+ * it is matched against the template declaration parameter specialization
+ * 'tparam' to determine the type to be used for the parameter.
+ * Example:
+ *	template Foo(T:T*)	// template declaration
+ *	Foo!(int*)		// template instantiation
+ * Input:
+ *	this = int*
+ *	tparam = T
+ *	parameters = [ T:T* ]	// Array of TemplateParameter's
+ * Output:
+ *	dedtypes = [ int ]	// Array of Expression/Type's
+ */
+
+MATCH Type::deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters,
+	Objects *dedtypes)
+{
+#if 0
+    printf("Type::deduceType()\n");
+    printf("\tthis   = %d, ", ty); print();
+    printf("\ttparam = %d, ", tparam->ty); tparam->print();
+#endif
+    if (!tparam)
+	goto Lnomatch;
+
+    if (this == tparam)
+	goto Lexact;
+
+    if (tparam->ty == Tident)
+    {
+	// Determine which parameter tparam is
+	int i = templateParameterLookup(tparam, parameters);
+	if (i == -1)
+	{
+	    if (!sc)
+		goto Lnomatch;
+
+	    /* Need a loc to go with the semantic routine.
+	     */
+	    Loc loc;
+	    if (parameters->dim)
+	    {
+		TemplateParameter *tp = (TemplateParameter *)parameters->data[0];
+		loc = tp->loc;
+	    }
+
+	    /* BUG: what if tparam is a template instance, that
+	     * has as an argument another Tident?
+	     */
+	    tparam = tparam->semantic(loc, sc);
+	    assert(tparam->ty != Tident);
+	    return deduceType(sc, tparam, parameters, dedtypes);
+	}
+
+	TemplateParameter *tp = (TemplateParameter *)parameters->data[i];
+
+	// Found the corresponding parameter tp
+	if (!tp->isTemplateTypeParameter())
+	    goto Lnomatch;
+	Type *tt = this;
+	Type *at = (Type *)dedtypes->data[i];
+
+	// 3*3 == 9 cases
+	if (tparam->isMutable())
+	{   // foo(U:U) T            => T
+	    // foo(U:U) const(T)     => const(T)
+	    // foo(U:U) invariant(T) => invariant(T)
+	    if (!at)
+	    {   dedtypes->data[i] = (void *)this;
+		goto Lexact;
+	    }
+	}
+	else if (mod == tparam->mod)
+	{   // foo(U:const(U))     const(T)     => T
+	    // foo(U:invariant(U)) invariant(T) => T
+	    tt = mutableOf();
+	    if (!at)
+	    {   dedtypes->data[i] = (void *)tt;
+		goto Lexact;
+	    }
+	}
+	else if (tparam->isConst())
+	{   // foo(U:const(U)) T            => T
+	    // foo(U:const(U)) invariant(T) => T
+	    tt = mutableOf();
+	    if (!at)
+	    {   dedtypes->data[i] = (void *)tt;
+		goto Lconst;
+	    }
+	}
+	else
+	{   // foo(U:invariant(U)) T        => nomatch
+	    // foo(U:invariant(U)) const(T) => nomatch
+	    if (!at)
+		goto Lnomatch;
+	}
+
+	if (tt->equals(at))
+	    goto Lexact;
+	else if (tt->ty == Tclass && at->ty == Tclass)
+	{
+	    return tt->implicitConvTo(at);
+	}
+	else if (tt->ty == Tsarray && at->ty == Tarray &&
+	    tt->nextOf()->implicitConvTo(at->nextOf()) >= MATCHconst)
+	{
+	    goto Lexact;
+	}
+	else
+	    goto Lnomatch;
+    }
+
+    if (ty != tparam->ty)
+	return implicitConvTo(tparam);
+//	goto Lnomatch;
+
+    if (nextOf())
+	return nextOf()->deduceType(sc, tparam->nextOf(), parameters, dedtypes);
+
+Lexact:
+    return MATCHexact;
+
+Lnomatch:
+    return MATCHnomatch;
+
+#if DMDV2
+Lconst:
+    return MATCHconst;
+#endif
+}
+
+#if DMDV2
+MATCH TypeDArray::deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters,
+	Objects *dedtypes)
+{
+#if 0
+    printf("TypeDArray::deduceType()\n");
+    printf("\tthis   = %d, ", ty); print();
+    printf("\ttparam = %d, ", tparam->ty); tparam->print();
+#endif
+    return Type::deduceType(sc, tparam, parameters, dedtypes);
+
+  Lnomatch:
+    return MATCHnomatch;
+}
+#endif
+
+MATCH TypeSArray::deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters,
+	Objects *dedtypes)
+{
+#if 0
+    printf("TypeSArray::deduceType()\n");
+    printf("\tthis   = %d, ", ty); print();
+    printf("\ttparam = %d, ", tparam->ty); tparam->print();
+#endif
+
+    // Extra check that array dimensions must match
+    if (tparam)
+    {
+	if (tparam->ty == Tsarray)
+	{
+	    TypeSArray *tp = (TypeSArray *)tparam;
+
+	    if (tp->dim->op == TOKvar &&
+		((VarExp *)tp->dim)->var->storage_class & STCtemplateparameter)
+	    {	int i = templateIdentifierLookup(((VarExp *)tp->dim)->var->ident, parameters);
+		// This code matches code in TypeInstance::deduceType()
+		if (i == -1)
+		    goto Lnomatch;
+		TemplateParameter *tp = (TemplateParameter *)parameters->data[i];
+		TemplateValueParameter *tvp = tp->isTemplateValueParameter();
+		if (!tvp)
+		    goto Lnomatch;
+		Expression *e = (Expression *)dedtypes->data[i];
+		if (e)
+		{
+		    if (!dim->equals(e))
+			goto Lnomatch;
+		}
+		else
+		{   Type *vt = tvp->valType->semantic(0, sc);
+		    MATCH m = (MATCH)dim->implicitConvTo(vt);
+		    if (!m)
+			goto Lnomatch;
+		    dedtypes->data[i] = dim;
+		}
+	    }
+	    else if (dim->toInteger() != tp->dim->toInteger())
+		return MATCHnomatch;
+	}
+	else if (tparam->ty == Taarray)
+	{
+	    TypeAArray *tp = (TypeAArray *)tparam;
+	    if (tp->index->ty == Tident)
+	    {	TypeIdentifier *tident = (TypeIdentifier *)tp->index;
+
+		if (tident->idents.dim == 0)
+		{   Identifier *id = tident->ident;
+
+		    for (size_t i = 0; i < parameters->dim; i++)
+		    {
+			TemplateParameter *tp = (TemplateParameter *)parameters->data[i];
+
+			if (tp->ident->equals(id))
+			{   // Found the corresponding template parameter
+			    TemplateValueParameter *tvp = tp->isTemplateValueParameter();
+			    if (!tvp || !tvp->valType->isintegral())
+				goto Lnomatch;
+
+			    if (dedtypes->data[i])
+			    {
+				if (!dim->equals((Object *)dedtypes->data[i]))
+				    goto Lnomatch;
+			    }
+			    else
+			    {	dedtypes->data[i] = (void *)dim;
+			    }
+			    return next->deduceType(sc, tparam->nextOf(), parameters, dedtypes);
+			}
+		    }
+		}
+	    }
+	}
+	else if (tparam->ty == Tarray)
+	{   MATCH m;
+
+	    m = next->deduceType(sc, tparam->nextOf(), parameters, dedtypes);
+	    if (m == MATCHexact)
+		m = MATCHconvert;
+	    return m;
+	}
+    }
+    return Type::deduceType(sc, tparam, parameters, dedtypes);
+
+  Lnomatch:
+    return MATCHnomatch;
+}
+
+MATCH TypeAArray::deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes)
+{
+#if 0
+    printf("TypeAArray::deduceType()\n");
+    printf("\tthis   = %d, ", ty); print();
+    printf("\ttparam = %d, ", tparam->ty); tparam->print();
+#endif
+
+    // Extra check that index type must match
+    if (tparam && tparam->ty == Taarray)
+    {
+	TypeAArray *tp = (TypeAArray *)tparam;
+	if (!index->deduceType(sc, tp->index, parameters, dedtypes))
+	{
+	    return MATCHnomatch;
+	}
+    }
+    return Type::deduceType(sc, tparam, parameters, dedtypes);
+}
+
+MATCH TypeFunction::deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes)
+{
+    //printf("TypeFunction::deduceType()\n");
+    //printf("\tthis   = %d, ", ty); print();
+    //printf("\ttparam = %d, ", tparam->ty); tparam->print();
+
+    // Extra check that function characteristics must match
+    if (tparam && tparam->ty == Tfunction)
+    {
+	TypeFunction *tp = (TypeFunction *)tparam;
+	if (varargs != tp->varargs ||
+	    linkage != tp->linkage)
+	    return MATCHnomatch;
+
+	size_t nfargs = Argument::dim(this->parameters);
+	size_t nfparams = Argument::dim(tp->parameters);
+
+	/* See if tuple match
+	 */
+	if (nfparams > 0 && nfargs >= nfparams - 1)
+	{
+	    /* See if 'A' of the template parameter matches 'A'
+	     * of the type of the last function parameter.
+	     */
+	    Argument *fparam = Argument::getNth(tp->parameters, nfparams - 1);
+	    assert(fparam);
+	    assert(fparam->type);
+	    if (fparam->type->ty != Tident)
+		goto L1;
+	    TypeIdentifier *tid = (TypeIdentifier *)fparam->type;
+	    if (tid->idents.dim)
+		goto L1;
+
+	    /* Look through parameters to find tuple matching tid->ident
+	     */
+	    size_t tupi = 0;
+	    for (; 1; tupi++)
+	    {	if (tupi == parameters->dim)
+		    goto L1;
+		TemplateParameter *t = (TemplateParameter *)parameters->data[tupi];
+		TemplateTupleParameter *tup = t->isTemplateTupleParameter();
+		if (tup && tup->ident->equals(tid->ident))
+		    break;
+	    }
+
+	    /* The types of the function arguments [nfparams - 1 .. nfargs]
+	     * now form the tuple argument.
+	     */
+	    int tuple_dim = nfargs - (nfparams - 1);
+
+	    /* See if existing tuple, and whether it matches or not
+	     */
+	    Object *o = (Object *)dedtypes->data[tupi];
+	    if (o)
+	    {	// Existing deduced argument must be a tuple, and must match
+		Tuple *t = isTuple(o);
+		if (!t || t->objects.dim != tuple_dim)
+		    return MATCHnomatch;
+		for (size_t i = 0; i < tuple_dim; i++)
+		{   Argument *arg = Argument::getNth(this->parameters, nfparams - 1 + i);
+		    if (!arg->type->equals((Object *)t->objects.data[i]))
+			return MATCHnomatch;
+		}
+	    }
+	    else
+	    {	// Create new tuple
+		Tuple *t = new Tuple();
+		t->objects.setDim(tuple_dim);
+		for (size_t i = 0; i < tuple_dim; i++)
+		{   Argument *arg = Argument::getNth(this->parameters, nfparams - 1 + i);
+		    t->objects.data[i] = (void *)arg->type;
+		}
+		dedtypes->data[tupi] = (void *)t;
+	    }
+	    nfparams--;	// don't consider the last parameter for type deduction
+	    goto L2;
+	}
+
+    L1:
+	if (nfargs != nfparams)
+	    return MATCHnomatch;
+    L2:
+	for (size_t i = 0; i < nfparams; i++)
+	{
+	    Argument *a = Argument::getNth(this->parameters, i);
+	    Argument *ap = Argument::getNth(tp->parameters, i);
+	    if (a->storageClass != ap->storageClass ||
+		!a->type->deduceType(sc, ap->type, parameters, dedtypes))
+		return MATCHnomatch;
+	}
+    }
+    return Type::deduceType(sc, tparam, parameters, dedtypes);
+}
+
+MATCH TypeIdentifier::deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes)
+{
+    // Extra check
+    if (tparam && tparam->ty == Tident)
+    {
+	TypeIdentifier *tp = (TypeIdentifier *)tparam;
+
+	for (int i = 0; i < idents.dim; i++)
+	{
+	    Identifier *id1 = (Identifier *)idents.data[i];
+	    Identifier *id2 = (Identifier *)tp->idents.data[i];
+
+	    if (!id1->equals(id2))
+		return MATCHnomatch;
+	}
+    }
+    return Type::deduceType(sc, tparam, parameters, dedtypes);
+}
+
+MATCH TypeInstance::deduceType(Scope *sc,
+	Type *tparam, TemplateParameters *parameters,
+	Objects *dedtypes)
+{
+#if 0
+    printf("TypeInstance::deduceType()\n");
+    printf("\tthis   = %d, ", ty); print();
+    printf("\ttparam = %d, ", tparam->ty); tparam->print();
+#endif
+
+    // Extra check
+    if (tparam && tparam->ty == Tinstance)
+    {
+	TypeInstance *tp = (TypeInstance *)tparam;
+
+	//printf("tempinst->tempdecl = %p\n", tempinst->tempdecl);
+	//printf("tp->tempinst->tempdecl = %p\n", tp->tempinst->tempdecl);
+	if (!tp->tempinst->tempdecl)
+	{   //printf("tp->tempinst->name = '%s'\n", tp->tempinst->name->toChars());
+	    if (!tp->tempinst->name->equals(tempinst->name))
+	    {
+		/* Handle case of:
+		 *  template Foo(T : sa!(T), alias sa)
+		 */
+		int i = templateIdentifierLookup(tp->tempinst->name, parameters);
+		if (i == -1)
+		{   /* Didn't find it as a parameter identifier. Try looking
+		     * it up and seeing if is an alias. See Bugzilla 1454
+		     */
+		    Dsymbol *s = tempinst->tempdecl->scope->search(0, tp->tempinst->name, NULL);
+		    if (s)
+		    {
+			s = s->toAlias();
+			TemplateDeclaration *td = s->isTemplateDeclaration();
+			if (td && td == tempinst->tempdecl)
+			    goto L2;
+		    }
+		    goto Lnomatch;
+		}
+		TemplateParameter *tpx = (TemplateParameter *)parameters->data[i];
+		// This logic duplicates tpx->matchArg()
+		TemplateAliasParameter *ta = tpx->isTemplateAliasParameter();
+		if (!ta)
+		    goto Lnomatch;
+		Object *sa = tempinst->tempdecl;
+		if (!sa)
+		    goto Lnomatch;
+		if (ta->specAlias && sa != ta->specAlias)
+		    goto Lnomatch;
+		if (dedtypes->data[i])
+		{   // Must match already deduced symbol
+		    Object *s = (Object *)dedtypes->data[i];
+
+		    if (s != sa)
+			goto Lnomatch;
+		}
+		dedtypes->data[i] = sa;
+	    }
+	}
+	else if (tempinst->tempdecl != tp->tempinst->tempdecl)
+	    goto Lnomatch;
+
+      L2:
+
+	for (int i = 0; i < tempinst->tiargs->dim; i++)
+	{
+	    //printf("\ttest: tempinst->tiargs[%d]\n", i);
+	    if (i >= tp->tempinst->tiargs->dim)
+		goto Lnomatch;
+
+	    int j;
+	    Object *o1 = (Object *)tempinst->tiargs->data[i];
+	    Object *o2 = (Object *)tp->tempinst->tiargs->data[i];
+
+	    Type *t1 = isType(o1);
+	    Type *t2 = isType(o2);
+
+	    Expression *e1 = isExpression(o1);
+	    Expression *e2 = isExpression(o2);
+
+	    Dsymbol *s1 = isDsymbol(o1);
+	    Dsymbol *s2 = isDsymbol(o2);
+
+	    Tuple *v1 = isTuple(o1);
+	    Tuple *v2 = isTuple(o2);
+#if 0
+	    if (t1)	printf("t1 = %s\n", t1->toChars());
+	    if (t2)	printf("t2 = %s\n", t2->toChars());
+	    if (e1)	printf("e1 = %s\n", e1->toChars());
+	    if (e2)	printf("e2 = %s\n", e2->toChars());
+	    if (s1)	printf("s1 = %s\n", s1->toChars());
+	    if (s2)	printf("s2 = %s\n", s2->toChars());
+	    if (v1)	printf("v1 = %s\n", v1->toChars());
+	    if (v2)	printf("v2 = %s\n", v2->toChars());
+#endif
+
+	    TemplateTupleParameter *ttp;
+	    if (t2 &&
+		t2->ty == Tident &&
+		i == tp->tempinst->tiargs->dim - 1 &&
+		i == tempinst->tempdecl->parameters->dim - 1 &&
+		(ttp = tempinst->tempdecl->isVariadic()) != NULL)
+	    {
+		/* Given:
+		 *  struct A(B...) {}
+		 *  alias A!(int, float) X;
+		 *  static if (!is(X Y == A!(Z), Z))
+		 * deduce that Z is a tuple(int, float)
+		 */
+
+		j = templateParameterLookup(t2, parameters);
+		if (j == -1)
+		    goto Lnomatch;
+
+		/* Create tuple from remaining args
+		 */
+		Tuple *vt = new Tuple();
+		int vtdim = tempinst->tiargs->dim - i;
+		vt->objects.setDim(vtdim);
+		for (size_t k = 0; k < vtdim; k++)
+		    vt->objects.data[k] = (void *)tempinst->tiargs->data[i + k];
+
+		Tuple *v = (Tuple *)dedtypes->data[j];
+		if (v)
+		{
+		    if (!match(v, vt, tempinst->tempdecl, sc))
+			goto Lnomatch;
+		}
+		else
+		    dedtypes->data[j] = vt;
+		break; //return MATCHexact;
+	    }
+
+	    if (t1 && t2)
+	    {
+		if (!t1->deduceType(sc, t2, parameters, dedtypes))
+		    goto Lnomatch;
+	    }
+	    else if (e1 && e2)
+	    {
+		if (!e1->equals(e2))
+		{   if (e2->op == TOKvar)
+		    {
+			/*
+			 * (T:Number!(e2), int e2)
+			 */
+			j = templateIdentifierLookup(((VarExp *)e2)->var->ident, parameters);
+			goto L1;
+		    }
+		    goto Lnomatch;
+		}
+	    }
+	    else if (e1 && t2 && t2->ty == Tident)
+	    {
+		j = templateParameterLookup(t2, parameters);
+	    L1:
+		if (j == -1)
+		    goto Lnomatch;
+		TemplateParameter *tp = (TemplateParameter *)parameters->data[j];
+		// BUG: use tp->matchArg() instead of the following
+		TemplateValueParameter *tv = tp->isTemplateValueParameter();
+		if (!tv)
+		    goto Lnomatch;
+		Expression *e = (Expression *)dedtypes->data[j];
+		if (e)
+		{
+		    if (!e1->equals(e))
+			goto Lnomatch;
+		}
+		else
+		{   Type *vt = tv->valType->semantic(0, sc);
+		    MATCH m = (MATCH)e1->implicitConvTo(vt);
+		    if (!m)
+			goto Lnomatch;
+		    dedtypes->data[j] = e1;
+		}
+	    }
+	    else if (s1 && t2 && t2->ty == Tident)
+	    {
+		j = templateParameterLookup(t2, parameters);
+		if (j == -1)
+		    goto Lnomatch;
+		TemplateParameter *tp = (TemplateParameter *)parameters->data[j];
+		// BUG: use tp->matchArg() instead of the following
+		TemplateAliasParameter *ta = tp->isTemplateAliasParameter();
+		if (!ta)
+		    goto Lnomatch;
+		Dsymbol *s = (Dsymbol *)dedtypes->data[j];
+		if (s)
+		{
+		    if (!s1->equals(s))
+			goto Lnomatch;
+		}
+		else
+		{
+		    dedtypes->data[j] = s1;
+		}
+	    }
+	    else if (s1 && s2)
+	    {
+		if (!s1->equals(s2))
+		    goto Lnomatch;
+	    }
+	    // BUG: Need to handle tuple parameters
+	    else
+		goto Lnomatch;
+	}
+    }
+    return Type::deduceType(sc, tparam, parameters, dedtypes);
+
+Lnomatch:
+    return MATCHnomatch;
+}
+
+MATCH TypeStruct::deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes)
+{
+    //printf("TypeStruct::deduceType()\n");
+    //printf("\tthis->parent   = %s, ", sym->parent->toChars()); print();
+    //printf("\ttparam = %d, ", tparam->ty); tparam->print();
+
+    /* If this struct is a template struct, and we're matching
+     * it against a template instance, convert the struct type
+     * to a template instance, too, and try again.
+     */
+    TemplateInstance *ti = sym->parent->isTemplateInstance();
+
+    if (tparam && tparam->ty == Tinstance)
+    {
+	if (ti && ti->toAlias() == sym)
+	{
+	    TypeInstance *t = new TypeInstance(0, ti);
+	    return t->deduceType(sc, tparam, parameters, dedtypes);
+	}
+
+	/* Match things like:
+	 *  S!(T).foo
+	 */
+	TypeInstance *tpi = (TypeInstance *)tparam;
+	if (tpi->idents.dim)
+	{   Identifier *id = (Identifier *)tpi->idents.data[tpi->idents.dim - 1];
+	    if (id->dyncast() == DYNCAST_IDENTIFIER && sym->ident->equals(id))
+	    {
+		Type *tparent = sym->parent->getType();
+		if (tparent)
+		{
+		    /* Slice off the .foo in S!(T).foo
+		     */
+		    tpi->idents.dim--;
+		    MATCH m = tparent->deduceType(sc, tpi, parameters, dedtypes);
+		    tpi->idents.dim++;
+		    return m;
+		}
+	    }
+	}
+    }
+
+    // Extra check
+    if (tparam && tparam->ty == Tstruct)
+    {
+	TypeStruct *tp = (TypeStruct *)tparam;
+
+	if (sym != tp->sym)
+	    return MATCHnomatch;
+    }
+    return Type::deduceType(sc, tparam, parameters, dedtypes);
+}
+
+MATCH TypeEnum::deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes)
+{
+    // Extra check
+    if (tparam && tparam->ty == Tenum)
+    {
+	TypeEnum *tp = (TypeEnum *)tparam;
+
+	if (sym != tp->sym)
+	    return MATCHnomatch;
+    }
+    return Type::deduceType(sc, tparam, parameters, dedtypes);
+}
+
+MATCH TypeTypedef::deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes)
+{
+    // Extra check
+    if (tparam && tparam->ty == Ttypedef)
+    {
+	TypeTypedef *tp = (TypeTypedef *)tparam;
+
+	if (sym != tp->sym)
+	    return MATCHnomatch;
+    }
+    return Type::deduceType(sc, tparam, parameters, dedtypes);
+}
+
+MATCH TypeClass::deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes)
+{
+    //printf("TypeClass::deduceType(this = %s)\n", toChars());
+
+    /* If this class is a template class, and we're matching
+     * it against a template instance, convert the class type
+     * to a template instance, too, and try again.
+     */
+    TemplateInstance *ti = sym->parent->isTemplateInstance();
+
+    if (tparam && tparam->ty == Tinstance)
+    {
+	if (ti && ti->toAlias() == sym)
+	{
+	    TypeInstance *t = new TypeInstance(0, ti);
+	    return t->deduceType(sc, tparam, parameters, dedtypes);
+	}
+
+	/* Match things like:
+	 *  S!(T).foo
+	 */
+	TypeInstance *tpi = (TypeInstance *)tparam;
+	if (tpi->idents.dim)
+	{   Identifier *id = (Identifier *)tpi->idents.data[tpi->idents.dim - 1];
+	    if (id->dyncast() == DYNCAST_IDENTIFIER && sym->ident->equals(id))
+	    {
+		Type *tparent = sym->parent->getType();
+		if (tparent)
+		{
+		    /* Slice off the .foo in S!(T).foo
+		     */
+		    tpi->idents.dim--;
+		    MATCH m = tparent->deduceType(sc, tpi, parameters, dedtypes);
+		    tpi->idents.dim++;
+		    return m;
+		}
+	    }
+	}
+    }
+
+    // Extra check
+    if (tparam && tparam->ty == Tclass)
+    {
+	TypeClass *tp = (TypeClass *)tparam;
+
+	//printf("\t%d\n", (MATCH) implicitConvTo(tp));
+	return implicitConvTo(tp);
+    }
+    return Type::deduceType(sc, tparam, parameters, dedtypes);
+}
+
+/* ======================== TemplateParameter =============================== */
+
+TemplateParameter::TemplateParameter(Loc loc, Identifier *ident)
+{
+    this->loc = loc;
+    this->ident = ident;
+    this->sparam = NULL;
+}
+
+TemplateTypeParameter  *TemplateParameter::isTemplateTypeParameter()
+{
+    return NULL;
+}
+
+TemplateValueParameter *TemplateParameter::isTemplateValueParameter()
+{
+    return NULL;
+}
+
+TemplateAliasParameter *TemplateParameter::isTemplateAliasParameter()
+{
+    return NULL;
+}
+
+TemplateTupleParameter *TemplateParameter::isTemplateTupleParameter()
+{
+    return NULL;
+}
+
+#if DMDV2
+TemplateThisParameter  *TemplateParameter::isTemplateThisParameter()
+{
+    return NULL;
+}
+#endif
+
+/* ======================== TemplateTypeParameter =========================== */
+
+// type-parameter
+
+TemplateTypeParameter::TemplateTypeParameter(Loc loc, Identifier *ident, Type *specType,
+	Type *defaultType)
+    : TemplateParameter(loc, ident)
+{
+    this->ident = ident;
+    this->specType = specType;
+    this->defaultType = defaultType;
+}
+
+TemplateTypeParameter  *TemplateTypeParameter::isTemplateTypeParameter()
+{
+    return this;
+}
+
+TemplateParameter *TemplateTypeParameter::syntaxCopy()
+{
+    TemplateTypeParameter *tp = new TemplateTypeParameter(loc, ident, specType, defaultType);
+    if (tp->specType)
+	tp->specType = specType->syntaxCopy();
+    if (defaultType)
+	tp->defaultType = defaultType->syntaxCopy();
+    return tp;
+}
+
+void TemplateTypeParameter::declareParameter(Scope *sc)
+{
+    //printf("TemplateTypeParameter::declareParameter('%s')\n", ident->toChars());
+    TypeIdentifier *ti = new TypeIdentifier(loc, ident);
+    sparam = new AliasDeclaration(loc, ident, ti);
+    if (!sc->insert(sparam))
+	error(loc, "parameter '%s' multiply defined", ident->toChars());
+}
+
+void TemplateTypeParameter::semantic(Scope *sc)
+{
+    //printf("TemplateTypeParameter::semantic('%s')\n", ident->toChars());
+    if (specType)
+    {
+	specType = specType->semantic(loc, sc);
+    }
+#if 0 // Don't do semantic() until instantiation
+    if (defaultType)
+    {
+	defaultType = defaultType->semantic(loc, sc);
+    }
+#endif
+}
+
+/****************************************
+ * Determine if two TemplateParameters are the same
+ * as far as TemplateDeclaration overloading goes.
+ * Returns:
+ *	1	match
+ *	0	no match
+ */
+
+int TemplateTypeParameter::overloadMatch(TemplateParameter *tp)
+{
+    TemplateTypeParameter *ttp = tp->isTemplateTypeParameter();
+
+    if (ttp)
+    {
+	if (specType != ttp->specType)
+	    goto Lnomatch;
+
+	if (specType && !specType->equals(ttp->specType))
+	    goto Lnomatch;
+
+	return 1;			// match
+    }
+
+Lnomatch:
+    return 0;
+}
+
+/*******************************************
+ * Match to a particular TemplateParameter.
+ * Input:
+ *	i		i'th argument
+ *	tiargs[]	actual arguments to template instance
+ *	parameters[]	template parameters
+ *	dedtypes[]	deduced arguments to template instance
+ *	*psparam	set to symbol declared and initialized to dedtypes[i]
+ *	flags		1: don't do 'toHeadMutable()'
+ */
+
+MATCH TemplateTypeParameter::matchArg(Scope *sc, Objects *tiargs,
+	int i, TemplateParameters *parameters, Objects *dedtypes,
+	Declaration **psparam, int flags)
+{
+    //printf("TemplateTypeParameter::matchArg()\n");
+    Type *t;
+    Object *oarg;
+    MATCH m = MATCHexact;
+    Type *ta;
+
+    if (i < tiargs->dim)
+	oarg = (Object *)tiargs->data[i];
+    else
+    {	// Get default argument instead
+	oarg = defaultArg(loc, sc);
+	if (!oarg)
+	{   assert(i < dedtypes->dim);
+	    // It might have already been deduced
+	    oarg = (Object *)dedtypes->data[i];
+	    if (!oarg)
+	    {
+		goto Lnomatch;
+	    }
+	    flags |= 1;		// already deduced, so don't to toHeadMutable()
+	}
+    }
+
+    ta = isType(oarg);
+    if (!ta)
+    {
+	//printf("%s %p %p %p\n", oarg->toChars(), isExpression(oarg), isDsymbol(oarg), isTuple(oarg));
+	goto Lnomatch;
+    }
+    //printf("ta is %s\n", ta->toChars());
+
+    t = (Type *)dedtypes->data[i];
+
+    if (specType)
+    {
+	//printf("\tcalling deduceType(): ta is %s, specType is %s\n", ta->toChars(), specType->toChars());
+	MATCH m2 = ta->deduceType(sc, specType, parameters, dedtypes);
+	if (m2 == MATCHnomatch)
+	{   //printf("\tfailed deduceType\n");
+	    goto Lnomatch;
+	}
+
+	if (m2 < m)
+	    m = m2;
+	t = (Type *)dedtypes->data[i];
+    }
+    else
+    {
+	// So that matches with specializations are better
+	m = MATCHconvert;
+
+	/* This is so that:
+	 *   template Foo(T), Foo!(const int), => ta == int
+	 */
+//	if (!(flags & 1))
+//	    ta = ta->toHeadMutable();
+
+	if (t)
+	{   // Must match already deduced type
+
+	    m = MATCHexact;
+	    if (!t->equals(ta))
+	    {	//printf("t = %s ta = %s\n", t->toChars(), ta->toChars());
+		goto Lnomatch;
+	    }
+	}
+    }
+
+    if (!t)
+    {
+	dedtypes->data[i] = ta;
+	t = ta;
+    }
+    *psparam = new AliasDeclaration(loc, ident, t);
+    //printf("\tm = %d\n", m);
+    return m;
+
+Lnomatch:
+    *psparam = NULL;
+    //printf("\tm = %d\n", MATCHnomatch);
+    return MATCHnomatch;
+}
+
+
+void TemplateTypeParameter::print(Object *oarg, Object *oded)
+{
+    printf(" %s\n", ident->toChars());
+
+    Type *t  = isType(oarg);
+    Type *ta = isType(oded);
+
+    assert(ta);
+
+    if (specType)
+	printf("\tSpecialization: %s\n", specType->toChars());
+    if (defaultType)
+	printf("\tDefault:        %s\n", defaultType->toChars());
+    printf("\tArgument:       %s\n", t ? t->toChars() : "NULL");
+    printf("\tDeduced Type:   %s\n", ta->toChars());
+}
+
+
+void TemplateTypeParameter::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    buf->writestring(ident->toChars());
+    if (specType)
+    {
+	buf->writestring(" : ");
+	specType->toCBuffer(buf, NULL, hgs);
+    }
+    if (defaultType)
+    {
+	buf->writestring(" = ");
+	defaultType->toCBuffer(buf, NULL, hgs);
+    }
+}
+
+
+void *TemplateTypeParameter::dummyArg()
+{   Type *t;
+
+    if (specType)
+	t = specType;
+    else
+    {   // Use this for alias-parameter's too (?)
+	t = new TypeIdentifier(loc, ident);
+    }
+    return (void *)t;
+}
+
+
+Object *TemplateTypeParameter::specialization()
+{
+    return specType;
+}
+
+
+Object *TemplateTypeParameter::defaultArg(Loc loc, Scope *sc)
+{
+    Type *t;
+
+    t = defaultType;
+    if (t)
+    {
+	t = t->syntaxCopy();
+	t = t->semantic(loc, sc);
+    }
+    return t;
+}
+
+/* ======================== TemplateThisParameter =========================== */
+
+#if DMDV2
+// this-parameter
+
+TemplateThisParameter::TemplateThisParameter(Loc loc, Identifier *ident,
+	Type *specType,
+	Type *defaultType)
+    : TemplateTypeParameter(loc, ident, specType, defaultType)
+{
+}
+
+TemplateThisParameter  *TemplateThisParameter::isTemplateThisParameter()
+{
+    return this;
+}
+
+TemplateParameter *TemplateThisParameter::syntaxCopy()
+{
+    TemplateThisParameter *tp = new TemplateThisParameter(loc, ident, specType, defaultType);
+    if (tp->specType)
+	tp->specType = specType->syntaxCopy();
+    if (defaultType)
+	tp->defaultType = defaultType->syntaxCopy();
+    return tp;
+}
+
+void TemplateThisParameter::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    buf->writestring("this ");
+    TemplateTypeParameter::toCBuffer(buf, hgs);
+}
+#endif
+
+/* ======================== TemplateAliasParameter ========================== */
+
+// alias-parameter
+
+Dsymbol *TemplateAliasParameter::sdummy = NULL;
+
+TemplateAliasParameter::TemplateAliasParameter(Loc loc, Identifier *ident,
+	Type *specType, Object *specAlias, Object *defaultAlias)
+    : TemplateParameter(loc, ident)
+{
+    this->ident = ident;
+    this->specType = specType;
+    this->specAlias = specAlias;
+    this->defaultAlias = defaultAlias;
+}
+
+TemplateAliasParameter *TemplateAliasParameter::isTemplateAliasParameter()
+{
+    return this;
+}
+
+TemplateParameter *TemplateAliasParameter::syntaxCopy()
+{
+    TemplateAliasParameter *tp = new TemplateAliasParameter(loc, ident, specType, specAlias, defaultAlias);
+    if (tp->specType)
+	tp->specType = specType->syntaxCopy();
+    tp->specAlias = objectSyntaxCopy(specAlias);
+    tp->defaultAlias = objectSyntaxCopy(defaultAlias);
+    return tp;
+}
+
+void TemplateAliasParameter::declareParameter(Scope *sc)
+{
+    TypeIdentifier *ti = new TypeIdentifier(loc, ident);
+    sparam = new AliasDeclaration(loc, ident, ti);
+    if (!sc->insert(sparam))
+	error(loc, "parameter '%s' multiply defined", ident->toChars());
+}
+
+Object *aliasParameterSemantic(Loc loc, Scope *sc, Object *o)
+{
+    if (o)
+    {
+	Expression *ea = isExpression(o);
+	Type *ta = isType(o);
+	if (ta)
+	{   Dsymbol *s = ta->toDsymbol(sc);
+	    if (s)
+		o = s;
+	    else
+		o = ta->semantic(loc, sc);
+	}
+	else if (ea)
+	{
+	    ea = ea->semantic(sc);
+	    o = ea->optimize(WANTvalue | WANTinterpret);
+	}
+    }
+    return o;
+}
+
+void TemplateAliasParameter::semantic(Scope *sc)
+{
+    if (specType)
+    {
+	specType = specType->semantic(loc, sc);
+    }
+    specAlias = aliasParameterSemantic(loc, sc, specAlias);
+#if 0 // Don't do semantic() until instantiation
+    if (defaultAlias)
+	defaultAlias = defaultAlias->semantic(loc, sc);
+#endif
+}
+
+int TemplateAliasParameter::overloadMatch(TemplateParameter *tp)
+{
+    TemplateAliasParameter *tap = tp->isTemplateAliasParameter();
+
+    if (tap)
+    {
+	if (specAlias != tap->specAlias)
+	    goto Lnomatch;
+
+	return 1;			// match
+    }
+
+Lnomatch:
+    return 0;
+}
+
+MATCH TemplateAliasParameter::matchArg(Scope *sc,
+	Objects *tiargs, int i, TemplateParameters *parameters,
+	Objects *dedtypes,
+	Declaration **psparam, int flags)
+{
+    Object *sa;
+    Object *oarg;
+    Expression *ea;
+    Dsymbol *s;
+
+    //printf("TemplateAliasParameter::matchArg()\n");
+
+    if (i < tiargs->dim)
+	oarg = (Object *)tiargs->data[i];
+    else
+    {	// Get default argument instead
+	oarg = defaultArg(loc, sc);
+	if (!oarg)
+	{   assert(i < dedtypes->dim);
+	    // It might have already been deduced
+	    oarg = (Object *)dedtypes->data[i];
+	    if (!oarg)
+		goto Lnomatch;
+	}
+    }
+
+    sa = getDsymbol(oarg);
+    if (sa)
+    {
+	/* specType means the alias must be a declaration with a type
+	 * that matches specType.
+	 */
+	if (specType)
+	{   Declaration *d = ((Dsymbol *)sa)->isDeclaration();
+	    if (!d)
+		goto Lnomatch;
+	    if (!d->type->equals(specType))
+		goto Lnomatch;
+	}
+    }
+    else
+    {
+	sa = oarg;
+	ea = isExpression(oarg);
+	if (ea)
+	{   if (specType)
+	    {
+		if (!ea->type->equals(specType))
+		    goto Lnomatch;
+	    }
+	}
+	else
+	    goto Lnomatch;
+    }
+
+    if (specAlias)
+    {
+	if (sa == sdummy)
+	    goto Lnomatch;
+	if (sa != specAlias)
+	    goto Lnomatch;
+    }
+    else if (dedtypes->data[i])
+    {   // Must match already deduced symbol
+	Object *s = (Object *)dedtypes->data[i];
+
+	if (!sa || s != sa)
+	    goto Lnomatch;
+    }
+    dedtypes->data[i] = sa;
+
+    s = isDsymbol(sa);
+    if (s)
+	*psparam = new AliasDeclaration(loc, ident, s);
+    else
+    {
+	assert(ea);
+
+        // Declare manifest constant
+        Initializer *init = new ExpInitializer(loc, ea);
+        VarDeclaration *v = new VarDeclaration(loc, NULL, ident, init);
+        v->storage_class = STCmanifest;
+        v->semantic(sc);
+	*psparam = v;
+    }
+    return MATCHexact;
+
+Lnomatch:
+    *psparam = NULL;
+    //printf("\tm = %d\n", MATCHnomatch);
+    return MATCHnomatch;
+}
+
+
+void TemplateAliasParameter::print(Object *oarg, Object *oded)
+{
+    printf(" %s\n", ident->toChars());
+
+    Dsymbol *sa = isDsymbol(oded);
+    assert(sa);
+
+    printf("\tArgument alias: %s\n", sa->toChars());
+}
+
+void TemplateAliasParameter::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    buf->writestring("alias ");
+    if (specType)
+    {	HdrGenState hgs;
+	specType->toCBuffer(buf, ident, &hgs);
+    }
+    else
+	buf->writestring(ident->toChars());
+    if (specAlias)
+    {
+	buf->writestring(" : ");
+	ObjectToCBuffer(buf, hgs, specAlias);
+    }
+    if (defaultAlias)
+    {
+	buf->writestring(" = ");
+	ObjectToCBuffer(buf, hgs, defaultAlias);
+    }
+}
+
+
+void *TemplateAliasParameter::dummyArg()
+{   Object *s;
+
+    s = specAlias;
+    if (!s)
+    {
+	if (!sdummy)
+	    sdummy = new Dsymbol();
+	s = sdummy;
+    }
+    return (void*)s;
+}
+
+
+Object *TemplateAliasParameter::specialization()
+{
+    return specAlias;
+}
+
+
+Object *TemplateAliasParameter::defaultArg(Loc loc, Scope *sc)
+{
+    Object *o = aliasParameterSemantic(loc, sc, defaultAlias);
+    return o;
+}
+
+/* ======================== TemplateValueParameter ========================== */
+
+// value-parameter
+
+Expression *TemplateValueParameter::edummy = NULL;
+
+TemplateValueParameter::TemplateValueParameter(Loc loc, Identifier *ident, Type *valType,
+	Expression *specValue, Expression *defaultValue)
+    : TemplateParameter(loc, ident)
+{
+    this->ident = ident;
+    this->valType = valType;
+    this->specValue = specValue;
+    this->defaultValue = defaultValue;
+}
+
+TemplateValueParameter *TemplateValueParameter::isTemplateValueParameter()
+{
+    return this;
+}
+
+TemplateParameter *TemplateValueParameter::syntaxCopy()
+{
+    TemplateValueParameter *tp =
+	new TemplateValueParameter(loc, ident, valType, specValue, defaultValue);
+    tp->valType = valType->syntaxCopy();
+    if (specValue)
+	tp->specValue = specValue->syntaxCopy();
+    if (defaultValue)
+	tp->defaultValue = defaultValue->syntaxCopy();
+    return tp;
+}
+
+void TemplateValueParameter::declareParameter(Scope *sc)
+{
+    VarDeclaration *v = new VarDeclaration(loc, valType, ident, NULL);
+    v->storage_class = STCtemplateparameter;
+    if (!sc->insert(v))
+	error(loc, "parameter '%s' multiply defined", ident->toChars());
+    sparam = v;
+}
+
+void TemplateValueParameter::semantic(Scope *sc)
+{
+    sparam->semantic(sc);
+    valType = valType->semantic(loc, sc);
+    if (!(valType->isintegral() || valType->isfloating() || valType->isString()) &&
+	valType->ty != Tident)
+	error(loc, "arithmetic/string type expected for value-parameter, not %s", valType->toChars());
+
+    if (specValue)
+    {   Expression *e = specValue;
+
+	e = e->semantic(sc);
+	e = e->implicitCastTo(sc, valType);
+	e = e->optimize(WANTvalue | WANTinterpret);
+	if (e->op == TOKint64 || e->op == TOKfloat64 ||
+	    e->op == TOKcomplex80 || e->op == TOKnull || e->op == TOKstring)
+	    specValue = e;
+	//e->toInteger();
+    }
+
+#if 0	// defer semantic analysis to arg match
+    if (defaultValue)
+    {   Expression *e = defaultValue;
+
+	e = e->semantic(sc);
+	e = e->implicitCastTo(sc, valType);
+	e = e->optimize(WANTvalue | WANTinterpret);
+	if (e->op == TOKint64)
+	    defaultValue = e;
+	//e->toInteger();
+    }
+#endif
+}
+
+int TemplateValueParameter::overloadMatch(TemplateParameter *tp)
+{
+    TemplateValueParameter *tvp = tp->isTemplateValueParameter();
+
+    if (tvp)
+    {
+	if (valType != tvp->valType)
+	    goto Lnomatch;
+
+	if (valType && !valType->equals(tvp->valType))
+	    goto Lnomatch;
+
+	if (specValue != tvp->specValue)
+	    goto Lnomatch;
+
+	return 1;			// match
+    }
+
+Lnomatch:
+    return 0;
+}
+
+
+MATCH TemplateValueParameter::matchArg(Scope *sc,
+	Objects *tiargs, int i, TemplateParameters *parameters, Objects *dedtypes,
+	Declaration **psparam, int flags)
+{
+    //printf("TemplateValueParameter::matchArg()\n");
+
+    Initializer *init;
+    Declaration *sparam;
+    MATCH m = MATCHexact;
+    Expression *ei;
+    Object *oarg;
+
+    if (i < tiargs->dim)
+	oarg = (Object *)tiargs->data[i];
+    else
+    {	// Get default argument instead
+	oarg = defaultArg(loc, sc);
+	if (!oarg)
+	{   assert(i < dedtypes->dim);
+	    // It might have already been deduced
+	    oarg = (Object *)dedtypes->data[i];
+	    if (!oarg)
+		goto Lnomatch;
+	}
+    }
+
+    ei = isExpression(oarg);
+    Type *vt;
+
+    if (!ei && oarg)
+	goto Lnomatch;
+
+    if (ei && ei->op == TOKvar)
+    {	// Resolve const variables that we had skipped earlier
+	ei = ei->optimize(WANTvalue | WANTinterpret);
+    }
+
+    if (specValue)
+    {
+	if (!ei || ei == edummy)
+	    goto Lnomatch;
+
+	Expression *e = specValue;
+
+	e = e->semantic(sc);
+	e = e->implicitCastTo(sc, valType);
+	e = e->optimize(WANTvalue | WANTinterpret);
+	//e->type = e->type->toHeadMutable();
+
+	ei = ei->syntaxCopy();
+	ei = ei->semantic(sc);
+	ei = ei->optimize(WANTvalue | WANTinterpret);
+	//ei->type = ei->type->toHeadMutable();
+	//printf("\tei: %s, %s\n", ei->toChars(), ei->type->toChars());
+	//printf("\te : %s, %s\n", e->toChars(), e->type->toChars());
+	if (!ei->equals(e))
+	    goto Lnomatch;
+    }
+    else if (dedtypes->data[i])
+    {   // Must match already deduced value
+	Expression *e = (Expression *)dedtypes->data[i];
+
+	if (!ei || !ei->equals(e))
+	    goto Lnomatch;
+    }
+Lmatch:
+    //printf("\tvalType: %s, ty = %d\n", valType->toChars(), valType->ty);
+    vt = valType->semantic(0, sc);
+    //printf("ei: %s, ei->type: %s\n", ei->toChars(), ei->type->toChars());
+    //printf("vt = %s\n", vt->toChars());
+    if (ei->type)
+    {
+	m = (MATCH)ei->implicitConvTo(vt);
+	//printf("m: %d\n", m);
+	if (!m)
+	    goto Lnomatch;
+    }
+    dedtypes->data[i] = ei;
+
+    init = new ExpInitializer(loc, ei);
+    sparam = new VarDeclaration(loc, vt, ident, init);
+    sparam->storage_class = STCmanifest;
+    *psparam = sparam;
+    return m;
+
+Lnomatch:
+    //printf("\tno match\n");
+    *psparam = NULL;
+    return MATCHnomatch;
+}
+
+
+void TemplateValueParameter::print(Object *oarg, Object *oded)
+{
+    printf(" %s\n", ident->toChars());
+
+    Expression *ea = isExpression(oded);
+
+    if (specValue)
+	printf("\tSpecialization: %s\n", specValue->toChars());
+    printf("\tArgument Value: %s\n", ea ? ea->toChars() : "NULL");
+}
+
+
+void TemplateValueParameter::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    valType->toCBuffer(buf, ident, hgs);
+    if (specValue)
+    {
+	buf->writestring(" : ");
+	specValue->toCBuffer(buf, hgs);
+    }
+    if (defaultValue)
+    {
+	buf->writestring(" = ");
+	defaultValue->toCBuffer(buf, hgs);
+    }
+}
+
+
+void *TemplateValueParameter::dummyArg()
+{   Expression *e;
+
+    e = specValue;
+    if (!e)
+    {
+	// Create a dummy value
+	if (!edummy)
+	    edummy = valType->defaultInit();
+	e = edummy;
+    }
+    return (void *)e;
+}
+
+
+Object *TemplateValueParameter::specialization()
+{
+    return specValue;
+}
+
+
+Object *TemplateValueParameter::defaultArg(Loc loc, Scope *sc)
+{
+    Expression *e = defaultValue;
+    if (e)
+    {
+	e = e->syntaxCopy();
+	e = e->semantic(sc);
+#if DMDV2
+	if (e->op == TOKdefault)
+	{   DefaultInitExp *de = (DefaultInitExp *)e;
+	    e = de->resolve(loc, sc);
+	}
+#endif
+    }
+    return e;
+}
+
+/* ======================== TemplateTupleParameter ========================== */
+
+// variadic-parameter
+
+TemplateTupleParameter::TemplateTupleParameter(Loc loc, Identifier *ident)
+    : TemplateParameter(loc, ident)
+{
+    this->ident = ident;
+}
+
+TemplateTupleParameter *TemplateTupleParameter::isTemplateTupleParameter()
+{
+    return this;
+}
+
+TemplateParameter *TemplateTupleParameter::syntaxCopy()
+{
+    TemplateTupleParameter *tp = new TemplateTupleParameter(loc, ident);
+    return tp;
+}
+
+void TemplateTupleParameter::declareParameter(Scope *sc)
+{
+    TypeIdentifier *ti = new TypeIdentifier(loc, ident);
+    sparam = new AliasDeclaration(loc, ident, ti);
+    if (!sc->insert(sparam))
+	error(loc, "parameter '%s' multiply defined", ident->toChars());
+}
+
+void TemplateTupleParameter::semantic(Scope *sc)
+{
+}
+
+int TemplateTupleParameter::overloadMatch(TemplateParameter *tp)
+{
+    TemplateTupleParameter *tvp = tp->isTemplateTupleParameter();
+
+    if (tvp)
+    {
+	return 1;			// match
+    }
+
+Lnomatch:
+    return 0;
+}
+
+MATCH TemplateTupleParameter::matchArg(Scope *sc,
+	Objects *tiargs, int i, TemplateParameters *parameters,
+	Objects *dedtypes,
+	Declaration **psparam, int flags)
+{
+    //printf("TemplateTupleParameter::matchArg()\n");
+
+    /* The rest of the actual arguments (tiargs[]) form the match
+     * for the variadic parameter.
+     */
+    assert(i + 1 == dedtypes->dim);	// must be the last one
+    Tuple *ovar;
+    if (i + 1 == tiargs->dim && isTuple((Object *)tiargs->data[i]))
+	ovar = isTuple((Object *)tiargs->data[i]);
+    else
+    {
+	ovar = new Tuple();
+	//printf("ovar = %p\n", ovar);
+	if (i < tiargs->dim)
+	{
+	    //printf("i = %d, tiargs->dim = %d\n", i, tiargs->dim);
+	    ovar->objects.setDim(tiargs->dim - i);
+	    for (size_t j = 0; j < ovar->objects.dim; j++)
+		ovar->objects.data[j] = tiargs->data[i + j];
+	}
+    }
+    *psparam = new TupleDeclaration(loc, ident, &ovar->objects);
+    dedtypes->data[i] = (void *)ovar;
+    return MATCHexact;
+}
+
+
+void TemplateTupleParameter::print(Object *oarg, Object *oded)
+{
+    printf(" %s... [", ident->toChars());
+    Tuple *v = isTuple(oded);
+    assert(v);
+
+    //printf("|%d| ", v->objects.dim);
+    for (int i = 0; i < v->objects.dim; i++)
+    {
+	if (i)
+	    printf(", ");
+
+	Object *o = (Object *)v->objects.data[i];
+
+	Dsymbol *sa = isDsymbol(o);
+	if (sa)
+	    printf("alias: %s", sa->toChars());
+
+	Type *ta = isType(o);
+	if (ta)
+	    printf("type: %s", ta->toChars());
+
+	Expression *ea = isExpression(o);
+	if (ea)
+	    printf("exp: %s", ea->toChars());
+
+	assert(!isTuple(o));		// no nested Tuple arguments
+    }
+
+    printf("]\n");
+}
+
+void TemplateTupleParameter::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    buf->writestring(ident->toChars());
+    buf->writestring("...");
+}
+
+
+void *TemplateTupleParameter::dummyArg()
+{
+    return NULL;
+}
+
+
+Object *TemplateTupleParameter::specialization()
+{
+    return NULL;
+}
+
+
+Object *TemplateTupleParameter::defaultArg(Loc loc, Scope *sc)
+{
+    return NULL;
+}
+
+/* ======================== TemplateInstance ================================ */
+
+TemplateInstance::TemplateInstance(Loc loc, Identifier *ident)
+    : ScopeDsymbol(NULL)
+{
+#if LOG
+    printf("TemplateInstance(this = %p, ident = '%s')\n", this, ident ? ident->toChars() : "null");
+#endif
+    this->loc = loc;
+    this->name = ident;
+    this->tiargs = NULL;
+    this->tempdecl = NULL;
+    this->inst = NULL;
+    this->tinst = NULL;
+    this->argsym = NULL;
+    this->aliasdecl = NULL;
+    this->semanticdone = 0;
+    this->semantictiargsdone = 0;
+    this->withsym = NULL;
+    this->nest = 0;
+    this->havetempdecl = 0;
+    this->isnested = NULL;
+    this->errors = 0;
+
+#if IN_LLVM
+    // LDC
+    this->emittedInModule = NULL;
+    this->tmodule = NULL;
+#endif
+}
+
+/*****************
+ * This constructor is only called when we figured out which function
+ * template to instantiate.
+ */
+
+TemplateInstance::TemplateInstance(Loc loc, TemplateDeclaration *td, Objects *tiargs)
+    : ScopeDsymbol(NULL)
+{
+#if LOG
+    printf("TemplateInstance(this = %p, tempdecl = '%s')\n", this, td->toChars());
+#endif
+    this->loc = loc;
+    this->name = td->ident;
+    this->tiargs = tiargs;
+    this->tempdecl = td;
+    this->inst = NULL;
+    this->tinst = NULL;
+    this->argsym = NULL;
+    this->aliasdecl = NULL;
+    this->semanticdone = 0;
+    this->semantictiargsdone = 1;
+    this->withsym = NULL;
+    this->nest = 0;
+    this->havetempdecl = 1;
+    this->isnested = NULL;
+    this->errors = 0;
+
+#if IN_LLVM
+    // LDC
+    this->tinst = NULL;
+    this->tmodule = NULL;
+#endif
+
+    assert((size_t)tempdecl->scope > 0x10000);
+}
+
+
+Objects *TemplateInstance::arraySyntaxCopy(Objects *objs)
+{
+    Objects *a = NULL;
+    if (objs)
+    {	a = new Objects();
+	a->setDim(objs->dim);
+	for (size_t i = 0; i < objs->dim; i++)
+	{
+	    a->data[i] = objectSyntaxCopy((Object *)objs->data[i]);
+	}
+    }
+    return a;
+}
+
+Dsymbol *TemplateInstance::syntaxCopy(Dsymbol *s)
+{
+    TemplateInstance *ti;
+
+    if (s)
+	ti = (TemplateInstance *)s;
+    else
+	ti = new TemplateInstance(loc, name);
+
+    ti->tiargs = arraySyntaxCopy(tiargs);
+
+    ScopeDsymbol::syntaxCopy(ti);
+    return ti;
+}
+
+
+void TemplateInstance::semantic(Scope *sc)
+{
+    if (global.errors)
+    {
+	if (!global.gag)
+	{
+	    /* Trying to soldier on rarely generates useful messages
+	     * at this point.
+	     */
+	    fatal();
+	}
+	return;
+    }
+#if LOG
+    printf("\n+TemplateInstance::semantic('%s', this=%p)\n", toChars(), this);
+#endif
+    if (inst)		// if semantic() was already run
+    {
+#if LOG
+	printf("-TemplateInstance::semantic('%s', this=%p) already run\n", inst->toChars(), inst);
+#endif
+	return;
+    }
+
+    // get the enclosing template instance from the scope tinst
+    tinst = sc->tinst;
+
+    if (semanticdone != 0)
+    {
+	error(loc, "recursive template expansion");
+//	inst = this;
+	return;
+    }
+    semanticdone = 1;
+#if IN_LLVM
+    // get the enclosing template instance from the scope tinst
+    tinst = sc->tinst;
+
+    // get the module of the outermost enclosing instantiation
+    if (tinst)
+	tmodule = tinst->tmodule;
+    else
+	tmodule = sc->module;
+    //printf("%s in %s\n", toChars(), tmodule->toChars());
+#endif
+
+#if LOG
+    printf("\tdo semantic\n");
+#endif
+    if (havetempdecl)
+    {
+	assert((size_t)tempdecl->scope > 0x10000);
+	// Deduce tdtypes
+	tdtypes.setDim(tempdecl->parameters->dim);
+	if (!tempdecl->matchWithInstance(this, &tdtypes, 2))
+	{
+	    error("incompatible arguments for template instantiation");
+	    inst = this;
+	    return;
+	}
+    }
+    else
+    {
+	/* Run semantic on each argument, place results in tiargs[]
+	 * (if we havetempdecl, then tiargs is already evaluated)
+	 */
+	semanticTiargs(sc);
+
+	tempdecl = findTemplateDeclaration(sc);
+	if (tempdecl)
+	    tempdecl = findBestMatch(sc);
+	if (!tempdecl || global.errors)
+	{   inst = this;
+	    //printf("error return %p, %d\n", tempdecl, global.errors);
+	    return;		// error recovery
+	}
+    }
+
+    hasNestedArgs(tiargs);
+
+    /* See if there is an existing TemplateInstantiation that already
+     * implements the typeargs. If so, just refer to that one instead.
+     */
+
+    for (size_t i = 0; i < tempdecl->instances.dim; i++)
+    {
+	TemplateInstance *ti = (TemplateInstance *)tempdecl->instances.data[i];
+#if LOG
+	printf("\t%s: checking for match with instance %d (%p): '%s'\n", toChars(), i, ti, ti->toChars());
+#endif
+	assert(tdtypes.dim == ti->tdtypes.dim);
+
+	// Nesting must match
+	if (isnested != ti->isnested)
+	{
+	    //printf("test2 isnested %s ti->isnested %s\n", isnested ? isnested->toChars() : "", ti->isnested ? ti->isnested->toChars() : "");
+	    continue;
+	}
+#if 0
+	if (isnested && sc->parent != ti->parent)
+	    continue;
+#endif
+	for (size_t j = 0; j < tdtypes.dim; j++)
+	{   Object *o1 = (Object *)tdtypes.data[j];
+	    Object *o2 = (Object *)ti->tdtypes.data[j];
+	    if (!match(o1, o2, tempdecl, sc))
+	    {
+		goto L1;
+	    }
+	}
+
+	// It's a match
+	inst = ti;
+	parent = ti->parent;
+#if LOG
+	printf("\tit's a match with instance %p\n", inst);
+#endif
+	return;
+
+     L1:
+	;
+    }
+
+    /* So, we need to implement 'this' instance.
+     */
+#if LOG
+    printf("\timplement template instance '%s'\n", toChars());
+#endif
+    unsigned errorsave = global.errors;
+    inst = this;
+    int tempdecl_instance_idx = tempdecl->instances.dim;
+    tempdecl->instances.push(this);
+    parent = tempdecl->parent;
+    //printf("parent = '%s'\n", parent->kind());
+
+    ident = genIdent();		// need an identifier for name mangling purposes.
+
+#if 1
+    if (isnested)
+	parent = isnested;
+#endif
+    //printf("parent = '%s'\n", parent->kind());
+
+    // Add 'this' to the enclosing scope's members[] so the semantic routines
+    // will get called on the instance members
+#if 1
+    int dosemantic3 = 0;
+    {	Array *a;
+
+	Scope *scx = sc;
+#if 0
+	for (scx = sc; scx; scx = scx->enclosing)
+	    if (scx->scopesym)
+		break;
+#endif
+
+	//if (scx && scx->scopesym) printf("3: scx is %s %s\n", scx->scopesym->kind(), scx->scopesym->toChars());
+	if (scx && scx->scopesym &&
+	    scx->scopesym->members && !scx->scopesym->isTemplateMixin()
+#if 0 // removed because it bloated compile times
+	    /* The problem is if A imports B, and B imports A, and both A
+	     * and B instantiate the same template, does the compilation of A
+	     * or the compilation of B do the actual instantiation?
+	     *
+	     * see bugzilla 2500.
+	     */
+	    && !scx->module->selfImports()
+#endif
+	   )
+	{
+	    //printf("\t1: adding to %s %s\n", scx->scopesym->kind(), scx->scopesym->toChars());
+	    a = scx->scopesym->members;
+	}
+	else
+	{   Module *m = sc->module->importedFrom;
+	    //printf("\t2: adding to module %s instead of module %s\n", m->toChars(), sc->module->toChars());
+	    a = m->members;
+	    if (m->semanticdone >= 3)
+		dosemantic3 = 1;
+	}
+	for (int i = 0; 1; i++)
+	{
+	    if (i == a->dim)
+	    {
+		a->push(this);
+		break;
+	    }
+	    if (this == (Dsymbol *)a->data[i])	// if already in Array
+		break;
+	}
+    }
+#endif
+
+    // Copy the syntax trees from the TemplateDeclaration
+    members = Dsymbol::arraySyntaxCopy(tempdecl->members);
+
+    // Create our own scope for the template parameters
+    Scope *scope = tempdecl->scope;
+    if (!scope)
+    {
+	error("forward reference to template declaration %s\n", tempdecl->toChars());
+	return;
+    }
+
+#if LOG
+    printf("\tcreate scope for template parameters '%s'\n", toChars());
+#endif
+    argsym = new ScopeDsymbol();
+    argsym->parent = scope->parent;
+    scope = scope->push(argsym);
+//    scope->stc = 0;
+
+    // Declare each template parameter as an alias for the argument type
+    Scope *paramscope = scope->push();
+    paramscope->stc = 0;
+    declareParameters(paramscope);
+    paramscope->pop();
+
+    // Add members of template instance to template instance symbol table
+//    parent = scope->scopesym;
+    symtab = new DsymbolTable();
+    int memnum = 0;
+    for (int i = 0; i < members->dim; i++)
+    {
+	Dsymbol *s = (Dsymbol *)members->data[i];
+#if LOG
+	printf("\t[%d] adding member '%s' %p kind %s to '%s', memnum = %d\n", i, s->toChars(), s, s->kind(), this->toChars(), memnum);
+#endif
+	memnum |= s->addMember(scope, this, memnum);
+    }
+#if LOG
+    printf("adding members done\n");
+#endif
+
+    /* See if there is only one member of template instance, and that
+     * member has the same name as the template instance.
+     * If so, this template instance becomes an alias for that member.
+     */
+    //printf("members->dim = %d\n", members->dim);
+    if (members->dim)
+    {
+	Dsymbol *s;
+	if (Dsymbol::oneMembers(members, &s) && s)
+	{
+	    //printf("s->kind = '%s'\n", s->kind());
+	    //s->print();
+	    //printf("'%s', '%s'\n", s->ident->toChars(), tempdecl->ident->toChars());
+	    if (s->ident && s->ident->equals(tempdecl->ident))
+	    {
+		//printf("setting aliasdecl\n");
+		aliasdecl = new AliasDeclaration(loc, s->ident, s);
+
+#if IN_LLVM
+                // LDC propagate internal information
+                if (tempdecl->llvmInternal) {
+                    s->llvmInternal = tempdecl->llvmInternal;
+                    if (FuncDeclaration* fd = s->isFuncDeclaration()) {
+                        fd->intrinsicName = tempdecl->intrinsicName;
+                    }
+                }
+#endif
+	    }
+	}
+    }
+
+    // Do semantic() analysis on template instance members
+#if LOG
+    printf("\tdo semantic() on template instance members '%s'\n", toChars());
+#endif
+    Scope *sc2;
+    sc2 = scope->push(this);
+    //printf("isnested = %d, sc->parent = %s\n", isnested, sc->parent->toChars());
+    sc2->parent = /*isnested ? sc->parent :*/ this;
+    sc2->tinst = this;
+
+#if WINDOWS_SEH
+  __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];
+	//printf("\t[%d] semantic on '%s' %p kind %s in '%s'\n", i, s->toChars(), s, s->kind(), this->toChars());
+	//printf("test: isnested = %d, sc2->parent = %s\n", isnested, sc2->parent->toChars());
+//	if (isnested)
+//	    s->parent = sc->parent;
+	//printf("test3: isnested = %d, s->parent = %s\n", isnested, s->parent->toChars());
+	s->semantic(sc2);
+	//printf("test4: isnested = %d, s->parent = %s\n", isnested, s->parent->toChars());
+	sc2->module->runDeferredSemantic();
+    }
+    --nest;
+#if WINDOWS_SEH
+  }
+  __except (__ehfilter(GetExceptionInformation()))
+  {
+    global.gag = 0;			// ensure error message gets printed
+    error("recursive expansion");
+    fatal();
+  }
+#endif
+
+    /* If any of the instantiation members didn't get semantic() run
+     * on them due to forward references, we cannot run semantic2()
+     * or semantic3() yet.
+     */
+    for (size_t i = 0; i < Module::deferred.dim; i++)
+    {	Dsymbol *sd = (Dsymbol *)Module::deferred.data[i];
+
+	if (sd->parent == this)
+	    goto Laftersemantic;
+    }
+
+    /* The problem is when to parse the initializer for a variable.
+     * Perhaps VarDeclaration::semantic() should do it like it does
+     * for initializers inside a function.
+     */
+//    if (sc->parent->isFuncDeclaration())
+
+	/* BUG 782: this has problems if the classes this depends on
+	 * are forward referenced. Find a way to defer semantic()
+	 * on this template.
+	 */
+	semantic2(sc2);
+
+    if (sc->func || dosemantic3)
+    {
+	semantic3(sc2);
+    }
+
+  Laftersemantic:
+    sc2->pop();
+
+    scope->pop();
+
+    // Give additional context info if error occurred during instantiation
+    if (global.errors != errorsave)
+    {
+	error("error instantiating");
+	if (tinst && !global.gag)
+	{   tinst->printInstantiationTrace();
+	    fatal();
+	}
+	errors = 1;
+	if (global.gag)
+	    tempdecl->instances.remove(tempdecl_instance_idx);
+    }
+
+#if LOG
+    printf("-TemplateInstance::semantic('%s', this=%p)\n", toChars(), this);
+#endif
+}
+
+
+void TemplateInstance::semanticTiargs(Scope *sc)
+{
+    //printf("+TemplateInstance::semanticTiargs() %s\n", toChars());
+    if (semantictiargsdone)
+	return;
+    semantictiargsdone = 1;
+    semanticTiargs(loc, sc, tiargs, 0);
+}
+
+/**********************************
+ * Input:
+ *	flags	1: replace const variables with their initializers
+ */
+
+void TemplateInstance::semanticTiargs(Loc loc, Scope *sc, Objects *tiargs, int flags)
+{
+    // Run semantic on each argument, place results in tiargs[]
+    //printf("+TemplateInstance::semanticTiargs() %s\n", toChars());
+    if (!tiargs)
+	return;
+    for (size_t j = 0; j < tiargs->dim; j++)
+    {
+	Object *o = (Object *)tiargs->data[j];
+	Type *ta = isType(o);
+	Expression *ea = isExpression(o);
+	Dsymbol *sa = isDsymbol(o);
+
+	//printf("1: tiargs->data[%d] = %p, %p, %p, ea=%p, ta=%p\n", j, o, isDsymbol(o), isTuple(o), ea, ta);
+	if (ta)
+	{
+	    //printf("type %s\n", ta->toChars());
+	    // It might really be an Expression or an Alias
+	    ta->resolve(loc, sc, &ea, &ta, &sa);
+	    if (ea)
+	    {
+		ea = ea->semantic(sc);
+		/* This test is to skip substituting a const var with
+		 * its initializer. The problem is the initializer won't
+		 * match with an 'alias' parameter. Instead, do the
+		 * const substitution in TemplateValueParameter::matchArg().
+		 */
+		if (ea->op != TOKvar || flags & 1)
+		    ea = ea->optimize(WANTvalue | WANTinterpret);
+		tiargs->data[j] = ea;
+	    }
+	    else if (sa)
+	    {	tiargs->data[j] = sa;
+		TupleDeclaration *d = sa->toAlias()->isTupleDeclaration();
+		if (d)
+		{
+		    size_t dim = d->objects->dim;
+		    tiargs->remove(j);
+		    tiargs->insert(j, d->objects);
+		    j--;
+		}
+	    }
+	    else if (ta)
+	    {
+		if (ta->ty == Ttuple)
+		{   // Expand tuple
+		    TypeTuple *tt = (TypeTuple *)ta;
+		    size_t dim = tt->arguments->dim;
+		    tiargs->remove(j);
+		    if (dim)
+		    {	tiargs->reserve(dim);
+			for (size_t i = 0; i < dim; i++)
+			{   Argument *arg = (Argument *)tt->arguments->data[i];
+			    tiargs->insert(j + i, arg->type);
+			}
+		    }
+		    j--;
+		}
+		else
+		    tiargs->data[j] = ta;
+	    }
+	    else
+	    {
+		assert(global.errors);
+		tiargs->data[j] = Type::terror;
+	    }
+	}
+	else if (ea)
+	{
+	    if (!ea)
+	    {	assert(global.errors);
+		ea = new IntegerExp(0);
+	    }
+	    assert(ea);
+	    ea = ea->semantic(sc);
+	    if (ea->op != TOKvar || flags & 1)
+		ea = ea->optimize(WANTvalue | WANTinterpret);
+	    tiargs->data[j] = ea;
+	    if (ea->op == TOKtype)
+		tiargs->data[j] = ea->type;
+	}
+	else if (sa)
+	{
+	    TemplateDeclaration *td = sa->isTemplateDeclaration();
+	    if (td && !td->scope && td->literal)
+		td->semantic(sc);
+	}
+	else
+	{
+	    assert(0);
+	}
+	//printf("1: tiargs->data[%d] = %p\n", j, tiargs->data[j]);
+    }
+#if 0
+    printf("-TemplateInstance::semanticTiargs('%s', this=%p)\n", toChars(), this);
+    for (size_t j = 0; j < tiargs->dim; j++)
+    {
+	Object *o = (Object *)tiargs->data[j];
+	Type *ta = isType(o);
+	Expression *ea = isExpression(o);
+	Dsymbol *sa = isDsymbol(o);
+	Tuple *va = isTuple(o);
+
+	printf("\ttiargs[%d] = ta %p, ea %p, sa %p, va %p\n", j, ta, ea, sa, va);
+    }
+#endif
+}
+
+/**********************************************
+ * Find template declaration corresponding to template instance.
+ */
+
+TemplateDeclaration *TemplateInstance::findTemplateDeclaration(Scope *sc)
+{
+    //printf("TemplateInstance::findTemplateDeclaration() %s\n", toChars());
+    if (!tempdecl)
+    {
+	/* Given:
+	 *    foo!( ... )
+	 * figure out which TemplateDeclaration foo refers to.
+	 */
+	Dsymbol *s;
+	Dsymbol *scopesym;
+	Identifier *id;
+	int i;
+
+	id = name;
+	s = sc->search(loc, id, &scopesym);
+	if (!s)
+	{   error("identifier '%s' is not defined", id->toChars());
+	    return NULL;
+	}
+#if LOG
+	printf("It's an instance of '%s' kind '%s'\n", s->toChars(), s->kind());
+	if (s->parent)
+	    printf("s->parent = '%s'\n", s->parent->toChars());
+#endif
+	withsym = scopesym->isWithScopeSymbol();
+
+	/* We might have found an alias within a template when
+	 * we really want the template.
+	 */
+	TemplateInstance *ti;
+	if (s->parent &&
+	    (ti = s->parent->isTemplateInstance()) != NULL)
+	{
+	    if (
+		(ti->name == id ||
+		 ti->toAlias()->ident == id)
+		&&
+		ti->tempdecl)
+	    {
+		/* This is so that one can refer to the enclosing
+		 * template, even if it has the same name as a member
+		 * of the template, if it has a !(arguments)
+		 */
+		tempdecl = ti->tempdecl;
+		if (tempdecl->overroot)		// if not start of overloaded list of TemplateDeclaration's
+		    tempdecl = tempdecl->overroot; // then get the start
+		s = tempdecl;
+	    }
+	}
+
+	s = s->toAlias();
+
+	/* It should be a TemplateDeclaration, not some other symbol
+	 */
+	tempdecl = s->isTemplateDeclaration();
+	if (!tempdecl)
+	{
+	    if (!s->parent && global.errors)
+		return NULL;
+	    if (!s->parent && s->getType())
+	    {	Dsymbol *s2 = s->getType()->toDsymbol(sc);
+		if (!s2)
+		{
+		    error("%s is not a template declaration, it is a %s", id->toChars(), s->kind());
+		    return NULL;
+		}
+		s = s2;
+	    }
+#ifdef DEBUG
+	    //if (!s->parent) printf("s = %s %s\n", s->kind(), s->toChars());
+#endif
+	    //assert(s->parent);
+	    TemplateInstance *ti = s->parent ? s->parent->isTemplateInstance() : NULL;
+	    if (ti &&
+		(ti->name == id ||
+		 ti->toAlias()->ident == id)
+		&&
+		ti->tempdecl)
+	    {
+		/* This is so that one can refer to the enclosing
+		 * template, even if it has the same name as a member
+		 * of the template, if it has a !(arguments)
+		 */
+		tempdecl = ti->tempdecl;
+		if (tempdecl->overroot)		// if not start of overloaded list of TemplateDeclaration's
+		    tempdecl = tempdecl->overroot; // then get the start
+	    }
+	    else
+	    {
+		error("%s is not a template declaration, it is a %s", id->toChars(), s->kind());
+		return NULL;
+	    }
+	}
+    }
+    else
+	assert(tempdecl->isTemplateDeclaration());
+    return tempdecl;
+}
+
+TemplateDeclaration *TemplateInstance::findBestMatch(Scope *sc)
+{
+    /* Since there can be multiple TemplateDeclaration's with the same
+     * name, look for the best match.
+     */
+    TemplateDeclaration *td_ambig = NULL;
+    TemplateDeclaration *td_best = NULL;
+    MATCH m_best = MATCHnomatch;
+    Objects dedtypes;
+
+#if LOG
+    printf("TemplateInstance::findBestMatch()\n");
+#endif
+    for (TemplateDeclaration *td = tempdecl; td; td = td->overnext)
+    {
+	MATCH m;
+
+//if (tiargs->dim) printf("2: tiargs->dim = %d, data[0] = %p\n", tiargs->dim, tiargs->data[0]);
+
+	// If more arguments than parameters,
+	// then this is no match.
+	if (td->parameters->dim < tiargs->dim)
+	{
+	    if (!td->isVariadic())
+		continue;
+	}
+
+	dedtypes.setDim(td->parameters->dim);
+	dedtypes.zero();
+	if (!td->scope)
+	{
+	    error("forward reference to template declaration %s", td->toChars());
+	    return NULL;
+	}
+	m = td->matchWithInstance(this, &dedtypes, 0);
+	//printf("matchWithInstance = %d\n", m);
+	if (!m)			// no match at all
+	    continue;
+
+	if (m < m_best)
+	    goto Ltd_best;
+	if (m > m_best)
+	    goto Ltd;
+
+	{
+	// Disambiguate by picking the most specialized TemplateDeclaration
+	MATCH c1 = td->leastAsSpecialized(td_best);
+	MATCH c2 = td_best->leastAsSpecialized(td);
+	//printf("c1 = %d, c2 = %d\n", c1, c2);
+
+	if (c1 > c2)
+	    goto Ltd;
+	else if (c1 < c2)
+	    goto Ltd_best;
+	else
+	    goto Lambig;
+	}
+
+      Lambig:		// td_best and td are ambiguous
+	td_ambig = td;
+	continue;
+
+      Ltd_best:		// td_best is the best match so far
+	td_ambig = NULL;
+	continue;
+
+      Ltd:		// td is the new best match
+	td_ambig = NULL;
+	td_best = td;
+	m_best = m;
+	tdtypes.setDim(dedtypes.dim);
+	memcpy(tdtypes.data, dedtypes.data, tdtypes.dim * sizeof(void *));
+	continue;
+    }
+
+    if (!td_best)
+    {
+	if (tempdecl && !tempdecl->overnext)
+	    // Only one template, so we can give better error message
+	    error("%s does not match template declaration %s", toChars(), tempdecl->toChars());
+	else
+	    error("%s does not match any template declaration", toChars());
+	return NULL;
+    }
+    if (td_ambig)
+    {
+	error("%s matches more than one template declaration, %s and %s",
+		toChars(), td_best->toChars(), td_ambig->toChars());
+    }
+
+    /* The best match is td_best
+     */
+    tempdecl = td_best;
+
+#if 0
+    /* Cast any value arguments to be same type as value parameter
+     */
+    for (size_t i = 0; i < tiargs->dim; i++)
+    {	Object *o = (Object *)tiargs->data[i];
+	Expression *ea = isExpression(o);	// value argument
+	TemplateParameter *tp = (TemplateParameter *)tempdecl->parameters->data[i];
+	assert(tp);
+	TemplateValueParameter *tvp = tp->isTemplateValueParameter();
+	if (tvp)
+	{
+	    assert(ea);
+	    ea = ea->castTo(tvp->valType);
+	    ea = ea->optimize(WANTvalue | WANTinterpret);
+	    tiargs->data[i] = (Object *)ea;
+	}
+    }
+#endif
+
+#if LOG
+    printf("\tIt's a match with template declaration '%s'\n", tempdecl->toChars());
+#endif
+    return tempdecl;
+}
+
+
+/*****************************************
+ * Determines if a TemplateInstance will need a nested
+ * generation of the TemplateDeclaration.
+ */
+
+int TemplateInstance::hasNestedArgs(Objects *args)
+{   int nested = 0;
+    //printf("TemplateInstance::hasNestedArgs('%s')\n", tempdecl->ident->toChars());
+
+    /* A nested instance happens when an argument references a local
+     * symbol that is on the stack.
+     */
+    for (size_t i = 0; i < args->dim; i++)
+    {   Object *o = (Object *)args->data[i];
+	Expression *ea = isExpression(o);
+	Dsymbol *sa = isDsymbol(o);
+	Tuple *va = isTuple(o);
+	if (ea)
+	{
+	    if (ea->op == TOKvar)
+	    {
+		sa = ((VarExp *)ea)->var;
+		goto Lsa;
+	    }
+	    if (ea->op == TOKfunction)
+	    {
+		sa = ((FuncExp *)ea)->fd;
+		goto Lsa;
+	    }
+	}
+	else if (sa)
+	{
+	  Lsa:
+	    Declaration *d = NULL;
+	    TemplateDeclaration *td = sa->isTemplateDeclaration();
+	    if (td && td->literal)
+	    {
+		goto L2;
+	    }
+	    d = sa->isDeclaration();
+	    if (d && !d->isDataseg() &&
+#if DMDV2
+		!(d->storage_class & STCmanifest) &&
+#endif
+		(!d->isFuncDeclaration() || d->isFuncDeclaration()->isNested()) &&
+		!isTemplateMixin())
+	    {
+	     L2:
+		// if module level template
+		if (tempdecl->toParent()->isModule())
+		{   Dsymbol *dparent = sa->toParent();
+		    if (!isnested)
+			isnested = dparent;
+		    else if (isnested != dparent)
+		    {
+			/* Select the more deeply nested of the two.
+			 * Error if one is not nested inside the other.
+			 */
+			for (Dsymbol *p = isnested; p; p = p->parent)
+			{
+			    if (p == dparent)
+				goto L1;	// isnested is most nested
+			}
+			for (Dsymbol *p = dparent; p; p = p->parent)
+			{
+			    if (p == isnested)
+			    {	isnested = dparent;
+				goto L1;	// dparent is most nested
+			    }
+			}
+			error("%s is nested in both %s and %s",
+				toChars(), isnested->toChars(), dparent->toChars());
+		    }
+		  L1:
+		    //printf("\tnested inside %s\n", isnested->toChars());
+		    nested |= 1;
+		}
+		else
+		    error("cannot use local '%s' as parameter to non-global template %s", d->toChars(), tempdecl->toChars());
+	    }
+	}
+	else if (va)
+	{
+	    nested |= hasNestedArgs(&va->objects);
+	}
+    }
+    return nested;
+}
+
+/****************************************
+ * This instance needs an identifier for name mangling purposes.
+ * Create one by taking the template declaration name and adding
+ * the type signature for it.
+ */
+
+Identifier *TemplateInstance::genIdent()
+{   OutBuffer buf;
+    char *id;
+    Objects *args;
+
+    //printf("TemplateInstance::genIdent('%s')\n", tempdecl->ident->toChars());
+    id = tempdecl->ident->toChars();
+    buf.printf("__T%zu%s", strlen(id), id);
+    args = tiargs;
+    for (int i = 0; i < args->dim; i++)
+    {   Object *o = (Object *)args->data[i];
+	Type *ta = isType(o);
+	Expression *ea = isExpression(o);
+	Dsymbol *sa = isDsymbol(o);
+	Tuple *va = isTuple(o);
+	//printf("\to %p ta %p ea %p sa %p va %p\n", o, ta, ea, sa, va);
+	if (ta)
+	{
+	    buf.writeByte('T');
+	    if (ta->deco)
+		buf.writestring(ta->deco);
+	    else
+	    {
+#ifdef DEBUG
+		printf("ta = %d, %s\n", ta->ty, ta->toChars());
+#endif
+		assert(global.errors);
+	    }
+	}
+	else if (ea)
+	{
+	  Lea:
+	    sinteger_t v;
+	    real_t r;
+
+	    ea = ea->optimize(WANTvalue | WANTinterpret);
+	    if (ea->op == TOKvar)
+	    {
+		sa = ((VarExp *)ea)->var;
+		ea = NULL;
+		goto Lsa;
+	    }
+	    if (ea->op == TOKfunction)
+	    {
+		sa = ((FuncExp *)ea)->fd;
+		ea = NULL;
+		goto Lsa;
+	    }
+	    buf.writeByte('V');
+	    if (ea->op == TOKtuple)
+	    {	ea->error("tuple is not a valid template value argument");
+		continue;
+	    }
+#if 1
+	    /* Use deco that matches what it would be for a function parameter
+	     */
+	    buf.writestring(ea->type->deco);
+#else
+	    // Use type of parameter, not type of argument
+	    TemplateParameter *tp = (TemplateParameter *)tempdecl->parameters->data[i];
+	    assert(tp);
+	    TemplateValueParameter *tvp = tp->isTemplateValueParameter();
+	    assert(tvp);
+	    buf.writestring(tvp->valType->deco);
+#endif
+	    ea->toMangleBuffer(&buf);
+	}
+	else if (sa)
+	{
+	  Lsa:
+	    buf.writeByte('S');
+	    Declaration *d = sa->isDeclaration();
+	    if (d && (!d->type || !d->type->deco))
+	    {	error("forward reference of %s", d->toChars());
+		continue;
+	    }
+#if 0
+	    VarDeclaration *v = sa->isVarDeclaration();
+	    if (v && v->storage_class & STCmanifest)
+	    {	ExpInitializer *ei = v->init->isExpInitializer();
+		if (ei)
+		{
+		    ea = ei->exp;
+		    goto Lea;
+		}
+	    }
+#endif
+	    const char *p = sa->mangle();
+	    buf.printf("%zu%s", strlen(p), p);
+	}
+	else if (va)
+	{
+	    assert(i + 1 == args->dim);		// must be last one
+	    args = &va->objects;
+	    i = -1;
+	}
+	else
+	    assert(0);
+    }
+    buf.writeByte('Z');
+    id = buf.toChars();
+    buf.data = NULL;
+    //printf("\tgenIdent = %s\n", id);
+    return new Identifier(id, TOKidentifier);
+}
+
+
+/****************************************************
+ * Declare parameters of template instance, initialize them with the
+ * template instance arguments.
+ */
+
+void TemplateInstance::declareParameters(Scope *scope)
+{
+    //printf("TemplateInstance::declareParameters()\n");
+    for (int i = 0; i < tdtypes.dim; i++)
+    {
+	TemplateParameter *tp = (TemplateParameter *)tempdecl->parameters->data[i];
+	//Object *o = (Object *)tiargs->data[i];
+	Object *o = (Object *)tdtypes.data[i];		// initializer for tp
+
+	//printf("\ttdtypes[%d] = %p\n", i, o);
+	tempdecl->declareParameter(scope, tp, o);
+    }
+}
+
+
+void TemplateInstance::semantic2(Scope *sc)
+{   int i;
+
+    if (semanticdone >= 2)
+	return;
+    semanticdone = 2;
+#if LOG
+    printf("+TemplateInstance::semantic2('%s')\n", toChars());
+#endif
+    if (!errors && members)
+    {
+	sc = tempdecl->scope;
+	assert(sc);
+	sc = sc->push(argsym);
+	sc = sc->push(this);
+	sc->tinst = this;
+	for (i = 0; i < members->dim; i++)
+	{
+	    Dsymbol *s = (Dsymbol *)members->data[i];
+#if LOG
+printf("\tmember '%s', kind = '%s'\n", s->toChars(), s->kind());
+#endif
+	    s->semantic2(sc);
+	}
+	sc = sc->pop();
+	sc->pop();
+    }
+#if LOG
+    printf("-TemplateInstance::semantic2('%s')\n", toChars());
+#endif
+}
+
+void TemplateInstance::semantic3(Scope *sc)
+{
+#if LOG
+    printf("TemplateInstance::semantic3('%s'), semanticdone = %d\n", toChars(), semanticdone);
+#endif
+//if (toChars()[0] == 'D') *(char*)0=0;
+    if (semanticdone >= 3)
+	return;
+    semanticdone = 3;
+    if (!errors && members)
+    {
+	sc = tempdecl->scope;
+	sc = sc->push(argsym);
+	sc = sc->push(this);
+	sc->tinst = this;
+	for (int i = 0; i < members->dim; i++)
+	{
+	    Dsymbol *s = (Dsymbol *)members->data[i];
+	    s->semantic3(sc);
+	}
+	sc = sc->pop();
+	sc->pop();
+    }
+}
+
+#if IN_DMD
+
+void TemplateInstance::printInstantiationTrace()
+{
+    if (global.gag)
+	return;
+}
+
+void TemplateInstance::toObjFile(int multiobj)
+{
+#if LOG
+    printf("TemplateInstance::toObjFile('%s', this = %p)\n", toChars(), this);
+#endif
+    if (!errors && members)
+    {
+	if (multiobj)
+	    // Append to list of object files to be written later
+	    obj_append(this);
+	else
+	{
+	    for (int i = 0; i < members->dim; i++)
+	    {
+		Dsymbol *s = (Dsymbol *)members->data[i];
+		s->toObjFile(multiobj);
+	    }
+	}
+    }
+}
+
+#endif
+
+void TemplateInstance::inlineScan()
+{
+#if LOG
+    printf("TemplateInstance::inlineScan('%s')\n", toChars());
+#endif
+    if (!errors && members)
+    {
+	for (int i = 0; i < members->dim; i++)
+	{
+	    Dsymbol *s = (Dsymbol *)members->data[i];
+	    s->inlineScan();
+	}
+    }
+}
+
+void TemplateInstance::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    int i;
+
+    Identifier *id = name;
+    buf->writestring(id->toChars());
+    buf->writestring("!(");
+    if (nest)
+	buf->writestring("...");
+    else
+    {
+	nest++;
+	Objects *args = tiargs;
+	for (i = 0; i < args->dim; i++)
+	{
+	    if (i)
+		buf->writeByte(',');
+	    Object *oarg = (Object *)args->data[i];
+	    ObjectToCBuffer(buf, hgs, oarg);
+	}
+	nest--;
+    }
+    buf->writeByte(')');
+}
+
+
+Dsymbol *TemplateInstance::toAlias()
+{
+#if LOG
+    printf("TemplateInstance::toAlias()\n");
+#endif
+    if (!inst)
+    {	error("cannot resolve forward reference");
+	return this;
+    }
+
+    if (inst != this)
+	return inst->toAlias();
+
+    if (aliasdecl)
+    {
+	return aliasdecl->toAlias();
+    }
+
+    return inst;
+}
+
+AliasDeclaration *TemplateInstance::isAliasDeclaration()
+{
+    return aliasdecl;
+}
+
+const char *TemplateInstance::kind()
+{
+    return "template instance";
+}
+
+int TemplateInstance::oneMember(Dsymbol **ps)
+{
+    *ps = NULL;
+    return TRUE;
+}
+
+char *TemplateInstance::toChars()
+{
+    OutBuffer buf;
+    HdrGenState hgs;
+    char *s;
+
+    toCBuffer(&buf, &hgs);
+    s = buf.toChars();
+    buf.data = NULL;
+    return s;
+}
+
+#if IN_LLVM
+
+void TemplateInstance::printInstantiationTrace()
+{
+    if(global.gag)
+	return;
+
+    const int max_shown = 6;
+
+    // determine instantiation depth
+    int n_instantiations = 1;
+    TemplateInstance* cur = this;
+    while(cur = cur->tinst)
+	++n_instantiations;
+
+    // show full trace only if it's short or verbose is on
+    if(n_instantiations <= max_shown || global.params.verbose)
+    {
+	cur = this;
+	while(cur)
+	{
+	    fprintf(stdmsg,"    instantiatied in %s: %s\n", cur->loc.toChars(), cur->toChars());
+	    cur = cur->tinst;
+	}
+    }
+    else
+    {
+	cur = this;
+	size_t i = 0;
+	for(; i < max_shown/2; ++i, cur = cur->tinst)
+	    fprintf(stdmsg,"    instantiatied in %s: %s\n", cur->loc.toChars(), cur->toChars());
+	fprintf(stdmsg,"    ... (%d instantiations, -v to show) ...\n", n_instantiations - max_shown);
+	for(; i < n_instantiations - max_shown + max_shown/2; ++i, cur = cur->tinst) 
+	{}
+	for(; i < n_instantiations; ++i, cur = cur->tinst) 
+	    fprintf(stdmsg,"    instantiatied in %s: %s\n", cur->loc.toChars(), cur->toChars());
+    }
+}
+
+#endif
+
+/* ======================== TemplateMixin ================================ */
+
+TemplateMixin::TemplateMixin(Loc loc, Identifier *ident, Type *tqual,
+	Array *idents, Objects *tiargs)
+	: TemplateInstance(loc, (Identifier *)idents->data[idents->dim - 1])
+{
+    //printf("TemplateMixin(ident = '%s')\n", ident ? ident->toChars() : "");
+    this->ident = ident;
+    this->tqual = tqual;
+    this->idents = idents;
+    this->tiargs = tiargs ? tiargs : new Objects();
+    this->scope = NULL;
+}
+
+Dsymbol *TemplateMixin::syntaxCopy(Dsymbol *s)
+{   TemplateMixin *tm;
+
+    Array *ids = new Array();
+    ids->setDim(idents->dim);
+    for (int i = 0; i < idents->dim; i++)
+    {	// Matches TypeQualified::syntaxCopyHelper()
+        Identifier *id = (Identifier *)idents->data[i];
+        if (id->dyncast() == DYNCAST_DSYMBOL)
+        {
+            TemplateInstance *ti = (TemplateInstance *)id;
+
+            ti = (TemplateInstance *)ti->syntaxCopy(NULL);
+            id = (Identifier *)ti;
+        }
+        ids->data[i] = id;
+    }
+
+    tm = new TemplateMixin(loc, ident,
+		(Type *)(tqual ? tqual->syntaxCopy() : NULL),
+		ids, tiargs);
+    TemplateInstance::syntaxCopy(tm);
+    return tm;
+}
+
+void TemplateMixin::semantic(Scope *sc)
+{
+#if LOG
+    printf("+TemplateMixin::semantic('%s', this=%p)\n", toChars(), this);
+    fflush(stdout);
+#endif
+    if (semanticdone &&
+	// This for when a class/struct contains mixin members, and
+	// is done over because of forward references
+	(!parent || !toParent()->isAggregateDeclaration()))
+    {
+#if LOG
+	printf("\tsemantic done\n");
+#endif
+	return;
+    }
+    if (!semanticdone)
+	semanticdone = 1;
+#if LOG
+    printf("\tdo semantic\n");
+#endif
+
+#if !IN_LLVM
+    // dont know what this is
+    util_progress();
+#endif
+
+    Scope *scx = NULL;
+    if (scope)
+    {	sc = scope;
+	scx = scope;		// save so we don't make redundant copies
+	scope = NULL;
+    }
+
+    // Follow qualifications to find the TemplateDeclaration
+    if (!tempdecl)
+    {	Dsymbol *s;
+	int i;
+	Identifier *id;
+
+	if (tqual)
+	{   s = tqual->toDsymbol(sc);
+	    i = 0;
+	}
+	else
+	{
+	    i = 1;
+	    id = (Identifier *)idents->data[0];
+	    switch (id->dyncast())
+	    {
+		case DYNCAST_IDENTIFIER:
+		    s = sc->search(loc, id, NULL);
+		    break;
+
+		case DYNCAST_DSYMBOL:
+		{
+		    TemplateInstance *ti = (TemplateInstance *)id;
+		    ti->semantic(sc);
+		    s = ti;
+		    break;
+		}
+		default:
+		    assert(0);
+	    }
+	}
+
+	for (; i < idents->dim; i++)
+	{
+	    if (!s)
+		break;
+	    id = (Identifier *)idents->data[i];
+	    s = s->searchX(loc, sc, id);
+	}
+	if (!s)
+	{
+	    error("is not defined");
+	    inst = this;
+	    return;
+	}
+	tempdecl = s->toAlias()->isTemplateDeclaration();
+	if (!tempdecl)
+	{
+	    error("%s isn't a template", s->toChars());
+	    inst = this;
+	    return;
+	}
+    }
+
+    // Look for forward reference
+    assert(tempdecl);
+    for (TemplateDeclaration *td = tempdecl; td; td = td->overnext)
+    {
+	if (!td->scope)
+	{
+	    /* Cannot handle forward references if mixin is a struct member,
+	     * because addField must happen during struct's semantic, not
+	     * during the mixin semantic.
+	     * runDeferred will re-run mixin's semantic outside of the struct's
+	     * semantic.
+	     */
+	    semanticdone = 0;
+	    AggregateDeclaration *ad = toParent()->isAggregateDeclaration();
+	    if (ad)
+		ad->sizeok = 2;
+	    else
+	    {
+		// Forward reference
+		//printf("forward reference - deferring\n");
+		scope = scx ? scx : new Scope(*sc);
+		scope->setNoFree();
+		scope->module->addDeferredSemantic(this);
+	    }
+	    return;
+	}
+    }
+
+    // Run semantic on each argument, place results in tiargs[]
+    semanticTiargs(sc);
+
+    tempdecl = findBestMatch(sc);
+    if (!tempdecl)
+    {	inst = this;
+	return;		// error recovery
+    }
+
+    if (!ident)
+	ident = genIdent();
+
+    inst = this;
+    parent = sc->parent;
+
+    /* Detect recursive mixin instantiations.
+     */
+    for (Dsymbol *s = parent; s; s = s->parent)
+    {
+	//printf("\ts = '%s'\n", s->toChars());
+	TemplateMixin *tm = s->isTemplateMixin();
+	if (!tm || tempdecl != tm->tempdecl)
+	    continue;
+
+	/* Different argument list lengths happen with variadic args
+	 */
+	if (tiargs->dim != tm->tiargs->dim)
+	    continue;
+
+	for (int i = 0; i < tiargs->dim; i++)
+	{   Object *o = (Object *)tiargs->data[i];
+	    Type *ta = isType(o);
+	    Expression *ea = isExpression(o);
+	    Dsymbol *sa = isDsymbol(o);
+	    Object *tmo = (Object *)tm->tiargs->data[i];
+	    if (ta)
+	    {
+		Type *tmta = isType(tmo);
+		if (!tmta)
+		    goto Lcontinue;
+		if (!ta->equals(tmta))
+		    goto Lcontinue;
+	    }
+	    else if (ea)
+	    {	Expression *tme = isExpression(tmo);
+		if (!tme || !ea->equals(tme))
+		    goto Lcontinue;
+	    }
+	    else if (sa)
+	    {
+		Dsymbol *tmsa = isDsymbol(tmo);
+		if (sa != tmsa)
+		    goto Lcontinue;
+	    }
+	    else
+		assert(0);
+	}
+	error("recursive mixin instantiation");
+	return;
+
+    Lcontinue:
+	continue;
+    }
+
+    // Copy the syntax trees from the TemplateDeclaration
+    members = Dsymbol::arraySyntaxCopy(tempdecl->members);
+    if (!members)
+	return;
+
+    symtab = new DsymbolTable();
+
+    for (Scope *sce = sc; 1; sce = sce->enclosing)
+    {
+	ScopeDsymbol *sds = (ScopeDsymbol *)sce->scopesym;
+	if (sds)
+	{
+	    sds->importScope(this, PROTpublic);
+	    break;
+	}
+    }
+
+#if LOG
+    printf("\tcreate scope for template parameters '%s'\n", toChars());
+#endif
+    Scope *scy = sc;
+    scy = sc->push(this);
+    scy->parent = this;
+
+    argsym = new ScopeDsymbol();
+    argsym->parent = scy->parent;
+    Scope *scope = scy->push(argsym);
+
+    unsigned errorsave = global.errors;
+
+    // Declare each template parameter as an alias for the argument type
+    declareParameters(scope);
+
+    // Add members to enclosing scope, as well as this scope
+    for (unsigned i = 0; i < members->dim; i++)
+    {   Dsymbol *s;
+
+	s = (Dsymbol *)members->data[i];
+	s->addMember(scope, this, i);
+	//sc->insert(s);
+	//printf("sc->parent = %p, sc->scopesym = %p\n", sc->parent, sc->scopesym);
+	//printf("s->parent = %s\n", s->parent->toChars());
+    }
+
+    // Do semantic() analysis on template instance members
+#if LOG
+    printf("\tdo semantic() on template instance members '%s'\n", toChars());
+#endif
+    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.
+     * Perhaps VarDeclaration::semantic() should do it like it does
+     * for initializers inside a function.
+     */
+//    if (sc->parent->isFuncDeclaration())
+
+	semantic2(sc2);
+
+    if (sc->func)
+    {
+	semantic3(sc2);
+    }
+
+    // Give additional context info if error occurred during instantiation
+    if (global.errors != errorsave)
+    {
+	error("error instantiating");
+    }
+
+    sc2->pop();
+
+    scope->pop();
+
+//    if (!isAnonymous())
+    {
+	scy->pop();
+    }
+#if LOG
+    printf("-TemplateMixin::semantic('%s', this=%p)\n", toChars(), this);
+#endif
+}
+
+void TemplateMixin::semantic2(Scope *sc)
+{   int i;
+
+    if (semanticdone >= 2)
+	return;
+    semanticdone = 2;
+#if LOG
+    printf("+TemplateMixin::semantic2('%s')\n", toChars());
+#endif
+    if (members)
+    {
+	assert(sc);
+	sc = sc->push(argsym);
+	sc = sc->push(this);
+	for (i = 0; i < members->dim; i++)
+	{
+	    Dsymbol *s = (Dsymbol *)members->data[i];
+#if LOG
+	    printf("\tmember '%s', kind = '%s'\n", s->toChars(), s->kind());
+#endif
+	    s->semantic2(sc);
+	}
+	sc = sc->pop();
+	sc->pop();
+    }
+#if LOG
+    printf("-TemplateMixin::semantic2('%s')\n", toChars());
+#endif
+}
+
+void TemplateMixin::semantic3(Scope *sc)
+{   int i;
+
+    if (semanticdone >= 3)
+	return;
+    semanticdone = 3;
+#if LOG
+    printf("TemplateMixin::semantic3('%s')\n", toChars());
+#endif
+    if (members)
+    {
+	sc = sc->push(argsym);
+	sc = sc->push(this);
+	for (i = 0; i < members->dim; i++)
+	{
+	    Dsymbol *s = (Dsymbol *)members->data[i];
+	    s->semantic3(sc);
+	}
+	sc = sc->pop();
+	sc->pop();
+    }
+}
+
+void TemplateMixin::inlineScan()
+{
+    TemplateInstance::inlineScan();
+}
+
+const char *TemplateMixin::kind()
+{
+    return "mixin";
+}
+
+int TemplateMixin::oneMember(Dsymbol **ps)
+{
+    return Dsymbol::oneMember(ps);
+}
+
+int TemplateMixin::hasPointers()
+{
+    //printf("TemplateMixin::hasPointers() %s\n", toChars());
+    for (size_t i = 0; i < members->dim; i++)
+    {
+	Dsymbol *s = (Dsymbol *)members->data[i];
+	//printf(" s = %s %s\n", s->kind(), s->toChars());
+	if (s->hasPointers())
+	{
+	    return 1;
+	}
+    }
+    return 0;
+}
+
+char *TemplateMixin::toChars()
+{
+    OutBuffer buf;
+    HdrGenState hgs;
+    char *s;
+
+    TemplateInstance::toCBuffer(&buf, &hgs);
+    s = buf.toChars();
+    buf.data = NULL;
+    return s;
+}
+
+void TemplateMixin::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    buf->writestring("mixin ");
+
+    for (int i = 0; i < idents->dim; i++)
+    {   Identifier *id = (Identifier *)idents->data[i];
+
+    	if (i)
+	    buf->writeByte('.');
+	buf->writestring(id->toChars());
+    }
+    buf->writestring("!(");
+    if (tiargs)
+    {
+        for (int i = 0; i < tiargs->dim; i++)
+        {   if (i)
+                buf->writebyte(',');
+	    Object *oarg = (Object *)tiargs->data[i];
+	    Type *t = isType(oarg);
+	    Expression *e = isExpression(oarg);
+	    Dsymbol *s = isDsymbol(oarg);
+	    if (t)
+		t->toCBuffer(buf, NULL, hgs);
+	    else if (e)
+		e->toCBuffer(buf, hgs);
+	    else if (s)
+	    {
+		char *p = s->ident ? s->ident->toChars() : s->toChars();
+		buf->writestring(p);
+	    }
+	    else if (!oarg)
+	    {
+		buf->writestring("NULL");
+	    }
+	    else
+	    {
+		assert(0);
+	    }
+        }
+    }
+    buf->writebyte(')');
+    if (ident)
+    {
+	buf->writebyte(' ');
+	buf->writestring(ident->toChars());
+    }
+    buf->writebyte(';');
+    buf->writenl();
+}
+
+
+#if IN_DMD
+void TemplateMixin::toObjFile(int multiobj)
+{
+    //printf("TemplateMixin::toObjFile('%s')\n", toChars());
+    TemplateInstance::toObjFile(multiobj);
+}
+#endif
+
--- a/dmd2/template.h	Mon Jun 01 01:28:18 2009 +0200
+++ b/dmd2/template.h	Mon Jun 01 19:02:20 2009 +0100
@@ -1,363 +1,381 @@
-
-// Compiler implementation of the D programming language
-// Copyright (c) 1999-2008 by Digital Mars
-// All Rights Reserved
-// written by Walter Bright
-// http://www.digitalmars.com
-// License for redistribution is by either the Artistic License
-// in artistic.txt, or the GNU General Public License in gnu.txt.
-// See the included readme.txt for details.
-
-#ifndef DMD_TEMPLATE_H
-#define DMD_TEMPLATE_H
-
-#ifdef __DMC__
-#pragma once
-#endif /* __DMC__ */
-
-#include <string>
-
-#include "root.h"
-#include "arraytypes.h"
-#include "dsymbol.h"
-#include "mtype.h"
-
-
-struct OutBuffer;
-struct Identifier;
-struct TemplateInstance;
-struct TemplateParameter;
-struct TemplateTypeParameter;
-struct TemplateThisParameter;
-struct TemplateValueParameter;
-struct TemplateAliasParameter;
-struct TemplateTupleParameter;
-struct Type;
-struct TypeTypeof;
-struct Scope;
-struct Expression;
-struct AliasDeclaration;
-struct FuncDeclaration;
-struct HdrGenState;
-enum MATCH;
-
-struct Tuple : Object
-{
-    Objects objects;
-
-    int dyncast() { return DYNCAST_TUPLE; } // kludge for template.isType()
-};
-
-
-struct TemplateDeclaration : ScopeDsymbol
-{
-    TemplateParameters *parameters;	// array of TemplateParameter's
-
-    TemplateParameters *origParameters;	// originals for Ddoc
-
-    Expression *constraint;
-
-    Array instances;			// array of TemplateInstance's
-
-    TemplateDeclaration *overnext;	// next overloaded TemplateDeclaration
-    TemplateDeclaration *overroot;	// first in overnext list
-
-    Scope *scope;
-    Dsymbol *onemember;		// if !=NULL then one member of this template
-
-    TemplateDeclaration(Loc loc, Identifier *id, TemplateParameters *parameters,
-	Expression *constraint, Array *decldefs);
-    Dsymbol *syntaxCopy(Dsymbol *);
-    void semantic(Scope *sc);
-    int overloadInsert(Dsymbol *s);
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-    const char *kind();
-    char *toChars();
-
-    void emitComment(Scope *sc);
-//    void toDocBuffer(OutBuffer *buf);
-
-    MATCH matchWithInstance(TemplateInstance *ti, Objects *atypes, int flag);
-    MATCH leastAsSpecialized(TemplateDeclaration *td2);
-
-    MATCH deduceFunctionTemplateMatch(Loc loc, Objects *targsi, Expression *ethis, Expressions *fargs, Objects *dedargs);
-    FuncDeclaration *deduceFunctionTemplate(Scope *sc, Loc loc, Objects *targsi, Expression *ethis, Expressions *fargs, int flags = 0);
-    void declareParameter(Scope *sc, TemplateParameter *tp, Object *o);
-
-    TemplateDeclaration *isTemplateDeclaration() { return this; }
-
-    TemplateTupleParameter *isVariadic();
-    int isOverloadable();
-    
-    // LDC
-    std::string intrinsicName;
-};
-
-struct TemplateParameter
-{
-    /* For type-parameter:
-     *	template Foo(ident)		// specType is set to NULL
-     *	template Foo(ident : specType)
-     * For value-parameter:
-     *	template Foo(valType ident)	// specValue is set to NULL
-     *	template Foo(valType ident : specValue)
-     * For alias-parameter:
-     *	template Foo(alias ident)
-     * For this-parameter:
-     *	template Foo(this ident)
-     */
-
-    Loc loc;
-    Identifier *ident;
-
-    Declaration *sparam;
-
-    TemplateParameter(Loc loc, Identifier *ident);
-
-    virtual TemplateTypeParameter  *isTemplateTypeParameter();
-    virtual TemplateValueParameter *isTemplateValueParameter();
-    virtual TemplateAliasParameter *isTemplateAliasParameter();
-    virtual TemplateThisParameter *isTemplateThisParameter();
-    virtual TemplateTupleParameter *isTemplateTupleParameter();
-
-    virtual TemplateParameter *syntaxCopy() = 0;
-    virtual void declareParameter(Scope *sc) = 0;
-    virtual void semantic(Scope *) = 0;
-    virtual void print(Object *oarg, Object *oded) = 0;
-    virtual void toCBuffer(OutBuffer *buf, HdrGenState *hgs) = 0;
-    virtual Object *specialization() = 0;
-    virtual Object *defaultArg(Loc loc, Scope *sc) = 0;
-
-    /* If TemplateParameter's match as far as overloading goes.
-     */
-    virtual int overloadMatch(TemplateParameter *) = 0;
-
-    /* Match actual argument against parameter.
-     */
-    virtual MATCH matchArg(Scope *sc, Objects *tiargs, int i, TemplateParameters *parameters, Objects *dedtypes, Declaration **psparam, int flags = 0) = 0;
-
-    /* Create dummy argument based on parameter.
-     */
-    virtual void *dummyArg() = 0;
-};
-
-struct TemplateTypeParameter : TemplateParameter
-{
-    /* Syntax:
-     *	ident : specType = defaultType
-     */
-    Type *specType;	// type parameter: if !=NULL, this is the type specialization
-    Type *defaultType;
-
-    TemplateTypeParameter(Loc loc, Identifier *ident, Type *specType, Type *defaultType);
-
-    TemplateTypeParameter *isTemplateTypeParameter();
-    TemplateParameter *syntaxCopy();
-    void declareParameter(Scope *sc);
-    void semantic(Scope *);
-    void print(Object *oarg, Object *oded);
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-    Object *specialization();
-    Object *defaultArg(Loc loc, Scope *sc);
-    int overloadMatch(TemplateParameter *);
-    MATCH matchArg(Scope *sc, Objects *tiargs, int i, TemplateParameters *parameters, Objects *dedtypes, Declaration **psparam, int flags);
-    void *dummyArg();
-};
-
-#if DMDV2
-struct TemplateThisParameter : TemplateTypeParameter
-{
-    /* Syntax:
-     *	this ident : specType = defaultType
-     */
-    Type *specType;	// type parameter: if !=NULL, this is the type specialization
-    Type *defaultType;
-
-    TemplateThisParameter(Loc loc, Identifier *ident, Type *specType, Type *defaultType);
-
-    TemplateThisParameter *isTemplateThisParameter();
-    TemplateParameter *syntaxCopy();
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-};
-#endif
-
-struct TemplateValueParameter : TemplateParameter
-{
-    /* Syntax:
-     *	valType ident : specValue = defaultValue
-     */
-
-    Type *valType;
-    Expression *specValue;
-    Expression *defaultValue;
-
-    static Expression *edummy;
-
-    TemplateValueParameter(Loc loc, Identifier *ident, Type *valType, Expression *specValue, Expression *defaultValue);
-
-    TemplateValueParameter *isTemplateValueParameter();
-    TemplateParameter *syntaxCopy();
-    void declareParameter(Scope *sc);
-    void semantic(Scope *);
-    void print(Object *oarg, Object *oded);
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-    Object *specialization();
-    Object *defaultArg(Loc loc, Scope *sc);
-    int overloadMatch(TemplateParameter *);
-    MATCH matchArg(Scope *sc, Objects *tiargs, int i, TemplateParameters *parameters, Objects *dedtypes, Declaration **psparam, int flags);
-    void *dummyArg();
-};
-
-struct TemplateAliasParameter : TemplateParameter
-{
-    /* Syntax:
-     *	specType ident : specAlias = defaultAlias
-     */
-
-    Type *specType;
-    Object *specAlias;
-    Object *defaultAlias;
-
-    static Dsymbol *sdummy;
-
-    TemplateAliasParameter(Loc loc, Identifier *ident, Type *specType, Object *specAlias, Object *defaultAlias);
-
-    TemplateAliasParameter *isTemplateAliasParameter();
-    TemplateParameter *syntaxCopy();
-    void declareParameter(Scope *sc);
-    void semantic(Scope *);
-    void print(Object *oarg, Object *oded);
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-    Object *specialization();
-    Object *defaultArg(Loc loc, Scope *sc);
-    int overloadMatch(TemplateParameter *);
-    MATCH matchArg(Scope *sc, Objects *tiargs, int i, TemplateParameters *parameters, Objects *dedtypes, Declaration **psparam, int flags);
-    void *dummyArg();
-};
-
-struct TemplateTupleParameter : TemplateParameter
-{
-    /* Syntax:
-     *	ident ...
-     */
-
-    TemplateTupleParameter(Loc loc, Identifier *ident);
-
-    TemplateTupleParameter *isTemplateTupleParameter();
-    TemplateParameter *syntaxCopy();
-    void declareParameter(Scope *sc);
-    void semantic(Scope *);
-    void print(Object *oarg, Object *oded);
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-    Object *specialization();
-    Object *defaultArg(Loc loc, Scope *sc);
-    int overloadMatch(TemplateParameter *);
-    MATCH matchArg(Scope *sc, Objects *tiargs, int i, TemplateParameters *parameters, Objects *dedtypes, Declaration **psparam, int flags);
-    void *dummyArg();
-};
-
-struct TemplateInstance : ScopeDsymbol
-{
-    /* Given:
-     *	foo!(args) =>
-     *	    name = foo
-     *	    tiargs = args
-     */
-    Identifier *name;
-    //Array idents;
-    Objects *tiargs;		// Array of Types/Expressions of template
-				// instance arguments [int*, char, 10*10]
-
-    Objects tdtypes;		// Array of Types/Expressions corresponding
-				// to TemplateDeclaration.parameters
-				// [int, char, 100]
-
-    TemplateDeclaration *tempdecl;	// referenced by foo.bar.abc
-    TemplateInstance *inst;		// refer to existing instance
-    ScopeDsymbol *argsym;		// argument symbol table
-    AliasDeclaration *aliasdecl;	// !=NULL if instance is an alias for its
-					// sole member
-    WithScopeSymbol *withsym;		// if a member of a with statement
-    int semanticdone;	// has semantic() been done?
-    int semantictiargsdone;	// has semanticTiargs() been done?
-    int nest;		// for recursion detection
-    int havetempdecl;	// 1 if used second constructor
-    Dsymbol *isnested;	// if referencing local symbols, this is the context
-    int errors;		// 1 if compiled with errors
-#ifdef IN_GCC
-    /* On some targets, it is necessary to know whether a symbol
-       will be emitted in the output or not before the symbol
-       is used.  This can be different from getModule(). */
-    Module * objFileModule;
-#endif
-
-    TemplateInstance(Loc loc, Identifier *temp_id);
-    TemplateInstance(Loc loc, TemplateDeclaration *tempdecl, Objects *tiargs);
-    static Objects *arraySyntaxCopy(Objects *objs);
-    Dsymbol *syntaxCopy(Dsymbol *);
-    void semantic(Scope *sc);
-    void semantic2(Scope *sc);
-    void semantic3(Scope *sc);
-    void inlineScan();
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-    Dsymbol *toAlias();			// resolve real symbol
-    const char *kind();
-    int oneMember(Dsymbol **ps);
-    char *toChars();
-    char *mangle();
-
-    void toObjFile(int multiobj);			// compile to .obj file
-
-    // Internal
-    static void semanticTiargs(Loc loc, Scope *sc, Objects *tiargs, int flags);
-    void semanticTiargs(Scope *sc);
-    TemplateDeclaration *findTemplateDeclaration(Scope *sc);
-    TemplateDeclaration *findBestMatch(Scope *sc);
-    void declareParameters(Scope *sc);
-    int isNested(Objects *tiargs);
-    Identifier *genIdent();
-
-    TemplateInstance *isTemplateInstance() { return this; }
-    AliasDeclaration *isAliasDeclaration();
-
-    // LDC
-    TemplateInstance *tinst; // enclosing template instance
-    Module* tmodule; // module from outermost enclosing template instantiation
-    void printInstantiationTrace();
-};
-
-struct TemplateMixin : TemplateInstance
-{
-    Array *idents;
-    Type *tqual;
-
-    Scope *scope;		// for forward referencing
-
-    TemplateMixin(Loc loc, Identifier *ident, Type *tqual, Array *idents, Objects *tiargs);
-    Dsymbol *syntaxCopy(Dsymbol *s);
-    void semantic(Scope *sc);
-    void semantic2(Scope *sc);
-    void semantic3(Scope *sc);
-    void inlineScan();
-    const char *kind();
-    int oneMember(Dsymbol **ps);
-    int hasPointers();
-    char *toChars();
-    char *mangle();
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-
-    void toObjFile(int multiobj);			// compile to .obj file
-
-    TemplateMixin *isTemplateMixin() { return this; }
-};
-
-Expression *isExpression(Object *o);
-Dsymbol *isDsymbol(Object *o);
-Type *isType(Object *o);
-Tuple *isTuple(Object *o);
-Type *getType(Object *o);
-Dsymbol *getDsymbol(Object *o);
-
-void ObjectToCBuffer(OutBuffer *buf, HdrGenState *hgs, Object *oarg);
-
-#endif /* DMD_TEMPLATE_H */
+
+// Compiler implementation of the D programming language
+// Copyright (c) 1999-2009 by Digital Mars
+// All Rights Reserved
+// written by Walter Bright
+// http://www.digitalmars.com
+// License for redistribution is by either the Artistic License
+// in artistic.txt, or the GNU General Public License in gnu.txt.
+// See the included readme.txt for details.
+
+#ifndef DMD_TEMPLATE_H
+#define DMD_TEMPLATE_H
+
+#ifdef __DMC__
+#pragma once
+#endif /* __DMC__ */
+#if IN_LLVM
+#include <string>
+#endif
+#include "root.h"
+#include "arraytypes.h"
+#include "dsymbol.h"
+#if IN_LLVM
+#include "mtype.h"
+#endif
+
+struct OutBuffer;
+struct Identifier;
+struct TemplateInstance;
+struct TemplateParameter;
+struct TemplateTypeParameter;
+struct TemplateThisParameter;
+struct TemplateValueParameter;
+struct TemplateAliasParameter;
+struct TemplateTupleParameter;
+struct Type;
+struct TypeTypeof;
+struct Scope;
+struct Expression;
+struct AliasDeclaration;
+struct FuncDeclaration;
+struct HdrGenState;
+enum MATCH;
+
+struct Tuple : Object
+{
+    Objects objects;
+
+    int dyncast() { return DYNCAST_TUPLE; } // kludge for template.isType()
+};
+
+
+struct TemplateDeclaration : ScopeDsymbol
+{
+    TemplateParameters *parameters;	// array of TemplateParameter's
+
+    TemplateParameters *origParameters;	// originals for Ddoc
+    Expression *constraint;
+    Array instances;			// array of TemplateInstance's
+
+    TemplateDeclaration *overnext;	// next overloaded TemplateDeclaration
+    TemplateDeclaration *overroot;	// first in overnext list
+
+    Scope *scope;
+    Dsymbol *onemember;		// if !=NULL then one member of this template
+
+    int literal;		// this template declaration is a literal
+
+    TemplateDeclaration(Loc loc, Identifier *id, TemplateParameters *parameters,
+	Expression *constraint, Array *decldefs);
+    Dsymbol *syntaxCopy(Dsymbol *);
+    void semantic(Scope *sc);
+    int overloadInsert(Dsymbol *s);
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+    const char *kind();
+    char *toChars();
+
+    void emitComment(Scope *sc);
+//    void toDocBuffer(OutBuffer *buf);
+
+    MATCH matchWithInstance(TemplateInstance *ti, Objects *atypes, int flag);
+    MATCH leastAsSpecialized(TemplateDeclaration *td2);
+
+    MATCH deduceFunctionTemplateMatch(Loc loc, Objects *targsi, Expression *ethis, Expressions *fargs, Objects *dedargs);
+    FuncDeclaration *deduceFunctionTemplate(Scope *sc, Loc loc, Objects *targsi, Expression *ethis, Expressions *fargs, int flags = 0);
+    void declareParameter(Scope *sc, TemplateParameter *tp, Object *o);
+
+    TemplateDeclaration *isTemplateDeclaration() { return this; }
+
+    TemplateTupleParameter *isVariadic();
+    int isOverloadable();
+
+#if IN_LLVM
+    // LDC
+    std::string intrinsicName;
+#endif
+};
+
+struct TemplateParameter
+{
+    /* For type-parameter:
+     *	template Foo(ident)		// specType is set to NULL
+     *	template Foo(ident : specType)
+     * For value-parameter:
+     *	template Foo(valType ident)	// specValue is set to NULL
+     *	template Foo(valType ident : specValue)
+     * For alias-parameter:
+     *	template Foo(alias ident)
+     * For this-parameter:
+     *	template Foo(this ident)
+     */
+
+    Loc loc;
+    Identifier *ident;
+
+    Declaration *sparam;
+
+    TemplateParameter(Loc loc, Identifier *ident);
+
+    virtual TemplateTypeParameter  *isTemplateTypeParameter();
+    virtual TemplateValueParameter *isTemplateValueParameter();
+    virtual TemplateAliasParameter *isTemplateAliasParameter();
+#if DMDV2
+    virtual TemplateThisParameter *isTemplateThisParameter();
+#endif
+    virtual TemplateTupleParameter *isTemplateTupleParameter();
+
+    virtual TemplateParameter *syntaxCopy() = 0;
+    virtual void declareParameter(Scope *sc) = 0;
+    virtual void semantic(Scope *) = 0;
+    virtual void print(Object *oarg, Object *oded) = 0;
+    virtual void toCBuffer(OutBuffer *buf, HdrGenState *hgs) = 0;
+    virtual Object *specialization() = 0;
+    virtual Object *defaultArg(Loc loc, Scope *sc) = 0;
+
+    /* If TemplateParameter's match as far as overloading goes.
+     */
+    virtual int overloadMatch(TemplateParameter *) = 0;
+
+    /* Match actual argument against parameter.
+     */
+    virtual MATCH matchArg(Scope *sc, Objects *tiargs, int i, TemplateParameters *parameters, Objects *dedtypes, Declaration **psparam, int flags = 0) = 0;
+
+    /* Create dummy argument based on parameter.
+     */
+    virtual void *dummyArg() = 0;
+};
+
+struct TemplateTypeParameter : TemplateParameter
+{
+    /* Syntax:
+     *	ident : specType = defaultType
+     */
+    Type *specType;	// type parameter: if !=NULL, this is the type specialization
+    Type *defaultType;
+
+    TemplateTypeParameter(Loc loc, Identifier *ident, Type *specType, Type *defaultType);
+
+    TemplateTypeParameter *isTemplateTypeParameter();
+    TemplateParameter *syntaxCopy();
+    void declareParameter(Scope *sc);
+    void semantic(Scope *);
+    void print(Object *oarg, Object *oded);
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+    Object *specialization();
+    Object *defaultArg(Loc loc, Scope *sc);
+    int overloadMatch(TemplateParameter *);
+    MATCH matchArg(Scope *sc, Objects *tiargs, int i, TemplateParameters *parameters, Objects *dedtypes, Declaration **psparam, int flags);
+    void *dummyArg();
+};
+
+#if DMDV2
+struct TemplateThisParameter : TemplateTypeParameter
+{
+    /* Syntax:
+     *	this ident : specType = defaultType
+     */
+    Type *specType;	// type parameter: if !=NULL, this is the type specialization
+    Type *defaultType;
+
+    TemplateThisParameter(Loc loc, Identifier *ident, Type *specType, Type *defaultType);
+
+    TemplateThisParameter *isTemplateThisParameter();
+    TemplateParameter *syntaxCopy();
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+};
+#endif
+
+struct TemplateValueParameter : TemplateParameter
+{
+    /* Syntax:
+     *	valType ident : specValue = defaultValue
+     */
+
+    Type *valType;
+    Expression *specValue;
+    Expression *defaultValue;
+
+    static Expression *edummy;
+
+    TemplateValueParameter(Loc loc, Identifier *ident, Type *valType, Expression *specValue, Expression *defaultValue);
+
+    TemplateValueParameter *isTemplateValueParameter();
+    TemplateParameter *syntaxCopy();
+    void declareParameter(Scope *sc);
+    void semantic(Scope *);
+    void print(Object *oarg, Object *oded);
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+    Object *specialization();
+    Object *defaultArg(Loc loc, Scope *sc);
+    int overloadMatch(TemplateParameter *);
+    MATCH matchArg(Scope *sc, Objects *tiargs, int i, TemplateParameters *parameters, Objects *dedtypes, Declaration **psparam, int flags);
+    void *dummyArg();
+};
+
+struct TemplateAliasParameter : TemplateParameter
+{
+    /* Syntax:
+     *	specType ident : specAlias = defaultAlias
+     */
+
+    Type *specType;
+    Object *specAlias;
+    Object *defaultAlias;
+
+    static Dsymbol *sdummy;
+
+    TemplateAliasParameter(Loc loc, Identifier *ident, Type *specType, Object *specAlias, Object *defaultAlias);
+
+    TemplateAliasParameter *isTemplateAliasParameter();
+    TemplateParameter *syntaxCopy();
+    void declareParameter(Scope *sc);
+    void semantic(Scope *);
+    void print(Object *oarg, Object *oded);
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+    Object *specialization();
+    Object *defaultArg(Loc loc, Scope *sc);
+    int overloadMatch(TemplateParameter *);
+    MATCH matchArg(Scope *sc, Objects *tiargs, int i, TemplateParameters *parameters, Objects *dedtypes, Declaration **psparam, int flags);
+    void *dummyArg();
+};
+
+struct TemplateTupleParameter : TemplateParameter
+{
+    /* Syntax:
+     *	ident ...
+     */
+
+    TemplateTupleParameter(Loc loc, Identifier *ident);
+
+    TemplateTupleParameter *isTemplateTupleParameter();
+    TemplateParameter *syntaxCopy();
+    void declareParameter(Scope *sc);
+    void semantic(Scope *);
+    void print(Object *oarg, Object *oded);
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+    Object *specialization();
+    Object *defaultArg(Loc loc, Scope *sc);
+    int overloadMatch(TemplateParameter *);
+    MATCH matchArg(Scope *sc, Objects *tiargs, int i, TemplateParameters *parameters, Objects *dedtypes, Declaration **psparam, int flags);
+    void *dummyArg();
+};
+
+struct TemplateInstance : ScopeDsymbol
+{
+    /* Given:
+     *	foo!(args) =>
+     *	    name = foo
+     *	    tiargs = args
+     */
+    Identifier *name;
+    //Array idents;
+    Objects *tiargs;		// Array of Types/Expressions of template
+				// instance arguments [int*, char, 10*10]
+
+    Objects tdtypes;		// Array of Types/Expressions corresponding
+				// to TemplateDeclaration.parameters
+				// [int, char, 100]
+
+    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
+    WithScopeSymbol *withsym;		// if a member of a with statement
+    int semanticdone;	// has semantic() been done?
+    int semantictiargsdone;	// has semanticTiargs() been done?
+    int nest;		// for recursion detection
+    int havetempdecl;	// 1 if used second constructor
+    Dsymbol *isnested;	// if referencing local symbols, this is the context
+    int errors;		// 1 if compiled with errors
+#ifdef IN_GCC
+    /* On some targets, it is necessary to know whether a symbol
+       will be emitted in the output or not before the symbol
+       is used.  This can be different from getModule(). */
+    Module * objFileModule;
+#endif
+
+    TemplateInstance(Loc loc, Identifier *temp_id);
+    TemplateInstance(Loc loc, TemplateDeclaration *tempdecl, Objects *tiargs);
+    static Objects *arraySyntaxCopy(Objects *objs);
+    Dsymbol *syntaxCopy(Dsymbol *);
+    void semantic(Scope *sc);
+    void semantic2(Scope *sc);
+    void semantic3(Scope *sc);
+    void inlineScan();
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+    Dsymbol *toAlias();			// resolve real symbol
+    const char *kind();
+    int oneMember(Dsymbol **ps);
+    char *toChars();
+    char *mangle();
+    void printInstantiationTrace();
+
+#if IN_DMD
+    void toObjFile(int multiobj);			// compile to .obj file
+#endif
+
+    // Internal
+    static void semanticTiargs(Loc loc, Scope *sc, Objects *tiargs, int flags);
+    void semanticTiargs(Scope *sc);
+    TemplateDeclaration *findTemplateDeclaration(Scope *sc);
+    TemplateDeclaration *findBestMatch(Scope *sc);
+    void declareParameters(Scope *sc);
+    int hasNestedArgs(Objects *tiargs);
+    Identifier *genIdent();
+
+    TemplateInstance *isTemplateInstance() { return this; }
+    AliasDeclaration *isAliasDeclaration();
+
+#if IN_LLVM
+    // LDC
+    Module* tmodule; // module from outermost enclosing template instantiation
+    Module* emittedInModule; // which module this template instance has been emitted in
+
+    void codegen(Ir*);
+#endif
+};
+
+struct TemplateMixin : TemplateInstance
+{
+    Array *idents;
+    Type *tqual;
+
+    Scope *scope;		// for forward referencing
+
+    TemplateMixin(Loc loc, Identifier *ident, Type *tqual, Array *idents, Objects *tiargs);
+    Dsymbol *syntaxCopy(Dsymbol *s);
+    void semantic(Scope *sc);
+    void semantic2(Scope *sc);
+    void semantic3(Scope *sc);
+    void inlineScan();
+    const char *kind();
+    int oneMember(Dsymbol **ps);
+    int hasPointers();
+    char *toChars();
+    char *mangle();
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+
+#if IN_DMD
+    void toObjFile(int multiobj);			// compile to .obj file
+#endif
+
+    TemplateMixin *isTemplateMixin() { return this; }
+
+#if IN_LLVM
+    void codegen(Ir*);
+#endif
+};
+
+Expression *isExpression(Object *o);
+Dsymbol *isDsymbol(Object *o);
+Type *isType(Object *o);
+Tuple *isTuple(Object *o);
+Type *getType(Object *o);
+Dsymbol *getDsymbol(Object *o);
+
+void ObjectToCBuffer(OutBuffer *buf, HdrGenState *hgs, Object *oarg);
+
+#endif /* DMD_TEMPLATE_H */
--- a/dmd2/total.h	Mon Jun 01 01:28:18 2009 +0200
+++ b/dmd2/total.h	Mon Jun 01 19:02:20 2009 +0100
@@ -41,5 +41,6 @@
 #include "id.h"
 #include "cond.h"
 #include "version.h"
+#include "lib.h"
 
 #endif /* DMD_TOTAL_H */
--- a/dmd2/traits.c	Mon Jun 01 01:28:18 2009 +0200
+++ b/dmd2/traits.c	Mon Jun 01 19:02:20 2009 +0100
@@ -1,6 +1,6 @@
 
 // Compiler implementation of the D programming language
-// Copyright (c) 1999-2007 by Digital Mars
+// Copyright (c) 1999-2009 by Digital Mars
 // All Rights Reserved
 // written by Walter Bright
 // http://www.digitalmars.com
@@ -12,25 +12,9 @@
 #include <stdlib.h>
 #include <ctype.h>
 #include <assert.h>
-#include <complex.h>
 #include <math.h>
 
-#if IN_GCC
-// Issues with using -include total.h (defines integer_t) and then complex.h fails...
-#undef integer_t
-#endif
-
-#ifdef __APPLE__
-#define integer_t dmd_integer_t
-#endif
-
-#if IN_GCC || IN_LLVM
-#include "mem.h"
-#elif _WIN32
-#include "..\root\mem.h"
-#elif linux
-#include "../root/mem.h"
-#endif
+#include "rmem.h"
 
 //#include "port.h"
 #include "mtype.h"
@@ -53,6 +37,8 @@
 
 #define LOGSEMANTIC	0
 
+#if DMDV2
+
 /************************************************
  * Delegate to be passed to overloadApply() that looks
  * for virtual functions.
@@ -197,7 +183,7 @@
 	e = isExpression(o);
 	Dsymbol *s = isDsymbol(o);
 	if (t)
-	    e = new TypeDotIdExp(loc, t, id);
+	    e = typeDotIdExp(loc, t, id);
 	else if (e)
 	    e = new DotIdExp(loc, e, id);
 	else if (s)
@@ -212,13 +198,10 @@
 	if (ident == Id::hasMember)
 	{   /* Take any errors as meaning it wasn't found
 	     */
-	    unsigned errors = global.errors;
-	    global.gag++;
-	    e = e->semantic(sc);
-	    global.gag--;
-	    if (errors != global.errors)
-	    {	if (global.gag == 0)
-		    global.errors = errors;
+	    e = e->trySemantic(sc);
+	    if (!e)
+	    {	if (global.gag)
+		    global.errors++;
 		goto Lfalse;
 	    }
 	    else
@@ -255,7 +238,7 @@
 	    Pvirtuals p;
 	    p.exps = exps;
 	    p.e1 = e;
-	    overloadApply(f, fpvirtuals, &p);
+	    overloadApply(f->getModule(), f, fpvirtuals, &p);
 
 	    TupleExp *tup = new TupleExp(loc, exps);
 	    return tup->semantic(sc);
@@ -340,16 +323,15 @@
 
 	for (size_t i = 0; i < dim; i++)
 	{   Object *o = (Object *)args->data[i];
-	    Type *t;
 	    Expression *e;
-	    Dsymbol *s;
 
 	    unsigned errors = global.errors;
 	    global.gag++;
 
-	    t = isType(o);
+	    Type *t = isType(o);
 	    if (t)
-	    {	t->resolve(loc, sc, &e, &t, &s);
+	    {	Dsymbol *s;
+		t->resolve(loc, sc, &e, &t, &s);
 		if (t)
 		    t->semantic(loc, sc);
 		else if (e)
@@ -438,3 +420,4 @@
 }
 
 
+#endif
--- a/gen/classes.cpp	Mon Jun 01 01:28:18 2009 +0200
+++ b/gen/classes.cpp	Mon Jun 01 19:02:20 2009 +0100
@@ -678,6 +678,8 @@
 //         ClassInfo *base;        // base class
 //         void *destructor;
 //         void *invariant;        // class invariant
+//         version(D_Version2)
+//         	void *xgetMembers; 
 //         uint flags;
 //         void *deallocator;
 //         OffsetTypeInfo[] offTi;
@@ -696,7 +698,11 @@
 
     ClassDeclaration* cinfo = ClassDeclaration::classinfo;
 
+#if DMDV2
+    if (cinfo->fields.dim != 13)
+#else
     if (cinfo->fields.dim != 12)
+#endif
     {
         error("object.d ClassInfo class is incorrect");
         fatal();
--- a/gen/llvmhelpers.cpp	Mon Jun 01 01:28:18 2009 +0200
+++ b/gen/llvmhelpers.cpp	Mon Jun 01 19:02:20 2009 +0100
@@ -1422,8 +1422,13 @@
 {
     t = t->toBasetype();
     if (t->ty == Tsarray) {
+#if DMDV2
+        assert(t->nextOf()->size() % t->nextOf()->alignsize() == 0);
+        return hasUnalignedFields(t->nextOf());
+#else
         assert(t->next->size() % t->next->alignsize() == 0);
         return hasUnalignedFields(t->next);
+#endif
     } else if (t->ty != Tstruct)
         return false;
 
--- a/gen/toobj.cpp	Mon Jun 01 01:28:18 2009 +0200
+++ b/gen/toobj.cpp	Mon Jun 01 19:02:20 2009 +0100
@@ -620,7 +620,11 @@
         fatal();
     }
     // check for patch
+#if DMDV2
+    else if (moduleinfo->fields.dim != 10)
+#else
     else if (moduleinfo->fields.dim != 9)
+#endif
     {
         error("object.d ModuleInfo class is incorrect");
         fatal();
--- a/gen/typinf.cpp	Mon Jun 01 01:28:18 2009 +0200
+++ b/gen/typinf.cpp	Mon Jun 01 19:02:20 2009 +0100
@@ -434,7 +434,11 @@
     else
     {
         const LLType* memty = DtoType(sd->memtype);
+#if DMDV2
+        LLConstant* C = llvm::ConstantInt::get(memty, sd->defaultval->toInteger(), !sd->memtype->isunsigned());
+#else
         LLConstant* C = llvm::ConstantInt::get(memty, sd->defaultval, !sd->memtype->isunsigned());
+#endif
         b.push_void_array(C, sd->memtype, sd);
     }
 
--- a/ir/irclass.cpp	Mon Jun 01 01:28:18 2009 +0200
+++ b/ir/irclass.cpp	Mon Jun 01 19:02:20 2009 +0100
@@ -111,7 +111,11 @@
                     "don't implement any interfaces");
 
     VarDeclarationIter idx(ClassDeclaration::classinfo->fields, 3);
+#if DMDV2
+    const llvm::Type* InterfaceTy = DtoType(idx->type->nextOf());
+#else
     const llvm::Type* InterfaceTy = DtoType(idx->type->next);
+#endif
 
     // create Interface[N]
     const llvm::ArrayType* array_type = llvm::ArrayType::get(InterfaceTy,n);
@@ -174,12 +178,10 @@
     // build the constant struct
     constVtbl = llvm::ConstantStruct::get(constants, false);
 
-    // sanity check
 #if 0
-    IF_LOG Logger::cout() << "constVtbl type: " << *constVtbl->getType() << std::endl;
-    IF_LOG Logger::cout() << "vtbl type: " << *type->irtype->isClass()->getVtbl() << std::endl;
+   IF_LOG Logger::cout() << "constVtbl type: " << *constVtbl->getType() << std::endl;
+   IF_LOG Logger::cout() << "vtbl type: " << *type->irtype->isClass()->getVtbl() << std::endl;
 #endif
-
     assert(constVtbl->getType() == type->irtype->isClass()->getVtbl() &&
         "vtbl initializer type mismatch");
 
@@ -328,7 +330,11 @@
 
     // start with the interface info
     VarDeclarationIter interfaces_idx(ClassDeclaration::classinfo->fields, 3);
+#if DMDV2
+    Type* first = interfaces_idx->type->nextOf()->pointerTo();
+#else
     Type* first = interfaces_idx->type->next->pointerTo();
+#endif
 
     // index into the interfaces array
     llvm::Constant* idxs[2] = {
--- a/ir/irtypeclass.cpp	Mon Jun 01 01:28:18 2009 +0200
+++ b/ir/irtypeclass.cpp	Mon Jun 01 19:02:20 2009 +0100
@@ -171,7 +171,11 @@
         ArrayIter<BaseClass> it2(*base->vtblInterfaces);
 
         VarDeclarationIter interfaces_idx(ClassDeclaration::classinfo->fields, 3);
+#if DMDV2
+	Type* first = interfaces_idx->type->nextOf()->pointerTo();
+#else
         Type* first = interfaces_idx->type->next->pointerTo();
+#endif
 
         // align offset
         offset = (offset + PTRSIZE - 1) & ~(PTRSIZE - 1);