changeset 1195:e961851fb8be

Merged DMD 1.042.
author Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
date Fri, 03 Apr 2009 17:59:34 +0200
parents 1853dcd9b944
children 6c31351af0c5
files dmd/attrib.c dmd/attrib.h dmd/cast.c dmd/class.c dmd/cond.c dmd/constfold.c dmd/declaration.c dmd/declaration.h dmd/enum.c dmd/enum.h dmd/expression.c dmd/expression.h dmd/func.c dmd/identifier.c dmd/identifier.h dmd/lexer.c dmd/lexer.h dmd/mangle.c dmd/mars.c dmd/mars.h dmd/module.c dmd/mtype.c dmd/opover.c dmd/optimize.c dmd/parse.c dmd/parse.h dmd/root/array.c dmd/root/async.c dmd/root/async.h dmd/root/port.c dmd/root/port.h dmd/root/root.c dmd/scope.h dmd/statement.c dmd/statement.h dmd/struct.c dmd/template.c dmd/template.h
diffstat 38 files changed, 6507 insertions(+), 5235 deletions(-) [+]
line wrap: on
line diff
--- a/dmd/attrib.c	Fri Apr 03 17:02:52 2009 +0200
+++ b/dmd/attrib.c	Fri Apr 03 17:59:34 2009 +0200
@@ -1,6 +1,6 @@
 
 // Compiler implementation of the D programming language
-// Copyright (c) 1999-2008 by Digital Mars
+// Copyright (c) 1999-2009 by Digital Mars
 // All Rights Reserved
 // written by Walter Bright
 // http://www.digitalmars.com
@@ -322,7 +322,7 @@
 	sc->stc = stc;
 }
 
-void StorageClassDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+void StorageClassDeclaration::stcToCBuffer(OutBuffer *buf, int stc)
 {
     struct SCstring
     {
@@ -350,18 +350,19 @@
 //	{ 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));
+	    buf->writeByte(' ');
 	}
     }
+}
 
+void StorageClassDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    stcToCBuffer(buf, stc);
     AttribDeclaration::toCBuffer(buf, hgs);
 }
 
@@ -1193,6 +1194,18 @@
 	name[se->len] = 0;
 	obj_includelib(name);
     }
+#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
--- a/dmd/attrib.h	Fri Apr 03 17:02:52 2009 +0200
+++ b/dmd/attrib.h	Fri Apr 03 17:59:34 2009 +0200
@@ -68,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
--- a/dmd/cast.c	Fri Apr 03 17:02:52 2009 +0200
+++ b/dmd/cast.c	Fri Apr 03 17:59:34 2009 +0200
@@ -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
@@ -228,7 +228,7 @@
 
 	case Tchar:
 	case Tuns8:
-	    //printf("value = %llu %llu\n", (integer_t)(unsigned char)value, value);
+	    //printf("value = %llu %llu\n", (dinteger_t)(unsigned char)value, value);
 	    if ((unsigned char)value != value)
 		goto Lno;
 	    goto Lyes;
--- a/dmd/class.c	Fri Apr 03 17:02:52 2009 +0200
+++ b/dmd/class.c	Fri Apr 03 17:59:34 2009 +0200
@@ -562,7 +562,7 @@
 //	    sc->offset += PTRSIZE;	// room for uplevel context pointer
     }
     else
-    {	sc->offset = 2*PTRSIZE;		// allow room for vptr[] and monitor
+    {	sc->offset = PTRSIZE * 2;	// allow room for vptr[] and monitor
 	alignsize = PTRSIZE;
     }
     structsize = sc->offset;
@@ -1152,7 +1152,7 @@
 	sc->linkage = LINKwindows;
     sc->structalign = 8;
     structalign = sc->structalign;
-    sc->offset = 2*PTRSIZE;
+    sc->offset = PTRSIZE * 2;
     inuse++;
     for (i = 0; i < members->dim; i++)
     {
--- a/dmd/cond.c	Fri Apr 03 17:02:52 2009 +0200
+++ b/dmd/cond.c	Fri Apr 03 17:59:34 2009 +0200
@@ -129,7 +129,14 @@
     {
 	"DigitalMars", "X86", "X86_64",
 	"Windows", "Win32", "Win64",
-	"linux", "Posix", "OSX", "FreeBSD",
+	"linux",
+#if DMDV2
+	/* Although Posix is predefined by D1, disallowing its
+	 * redefinition breaks makefiles and older builds.
+	 */
+	"Posix",
+#endif
+	"OSX", "FreeBSD",
 	"LittleEndian", "BigEndian",
 	"all",
 	"none",
--- a/dmd/constfold.c	Fri Apr 03 17:02:52 2009 +0200
+++ b/dmd/constfold.c	Fri Apr 03 17:59:34 2009 +0200
@@ -1,6 +1,6 @@
 
 // Compiler implementation of the D programming language
-// Copyright (c) 1999-2007 by Digital Mars
+// Copyright (c) 1999-2009 by Digital Mars
 // All Rights Reserved
 // written by Walter Bright
 // http://www.digitalmars.com
@@ -555,7 +555,7 @@
 {   Expression *e;
     Loc loc = e1->loc;
     unsigned count;
-    integer_t value;
+    dinteger_t value;
 
     value = e1->toInteger();
     count = e2->toInteger();
@@ -604,7 +604,7 @@
 {   Expression *e;
     Loc loc = e1->loc;
     unsigned count;
-    integer_t value;
+    dinteger_t value;
 
     value = e1->toInteger();
     count = e2->toInteger();
@@ -887,7 +887,7 @@
 Expression *Cmp(enum TOK op, Type *type, Expression *e1, Expression *e2)
 {   Expression *e;
     Loc loc = e1->loc;
-    integer_t n;
+    dinteger_t n;
     real_t r1;
     real_t r2;
 
@@ -1058,7 +1058,7 @@
     else if (type->isintegral())
     {
 	if (e1->type->isfloating())
-	{   integer_t result;
+	{   dinteger_t result;
 	    real_t r = e1->toReal();
 
 	    switch (type->toBasetype()->ty)
@@ -1251,7 +1251,7 @@
 	if (iupr > es1->len || ilwr > iupr)
 	    e1->error("string slice [%ju .. %ju] is out of bounds", ilwr, iupr);
 	else
-	{   integer_t value;
+	{   dinteger_t value;
 	    void *s;
 	    size_t len = iupr - ilwr;
 	    int sz = es1->sz;
@@ -1317,7 +1317,7 @@
 	    StringExp *es;
 	    size_t len = 1;
 	    int sz = tn->size();
-	    integer_t v = e->toInteger();
+	    dinteger_t v = e->toInteger();
 
 	    s = mem.malloc((len + 1) * sz);
 	    memcpy((unsigned char *)s, &v, sz);
@@ -1384,7 +1384,7 @@
 	Type *t;
 	size_t len = es1->len + 1;
 	int sz = es1->sz;
-	integer_t v = e2->toInteger();
+	dinteger_t v = e2->toInteger();
 
 	s = mem.malloc((len + 1) * sz);
 	memcpy(s, es1->string, es1->len * sz);
@@ -1409,7 +1409,7 @@
 	Type *t;
 	size_t len = 1 + es2->len;
 	int sz = es2->sz;
-	integer_t v = e1->toInteger();
+	dinteger_t v = e1->toInteger();
 
 	s = mem.malloc((len + 1) * sz);
 	memcpy((unsigned char *)s, &v, sz);
--- a/dmd/declaration.c	Fri Apr 03 17:02:52 2009 +0200
+++ b/dmd/declaration.c	Fri Apr 03 17:59:34 2009 +0200
@@ -1,1426 +1,1416 @@
-
-// 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)
-	{
-	    char *p = NULL;
-	    if (isConst())
-		p = "const";
-	    else if (isInvariant())
-		p = "invariant";
-	    else if (storage_class & STCmanifest)
-		p = "manifest constant";
-	    else if (!t->isAssignable())
-		p = "struct with immutable members";
-	    if (p)
-	    {	error(loc, "cannot modify %s", p);
-		halt();
-	    }
-	}
-    }
-}
-#endif
-
-
-/********************************* TupleDeclaration ****************************/
-
-TupleDeclaration::TupleDeclaration(Loc loc, Identifier *id, Objects *objects)
-    : Declaration(id)
-{
-    this->type = NULL;
-    this->objects = objects;
-    this->isexp = 0;
-    this->tupletype = NULL;
-}
-
-Dsymbol *TupleDeclaration::syntaxCopy(Dsymbol *s)
-{
-    assert(0);
-    return NULL;
-}
-
-const char *TupleDeclaration::kind()
-{
-    return "tuple";
-}
-
-Type *TupleDeclaration::getType()
-{
-    /* If this tuple represents a type, return that type
-     */
-
-    //printf("TupleDeclaration::getType() %s\n", toChars());
-    if (isexp)
-	return NULL;
-    if (!tupletype)
-    {
-	/* It's only a type tuple if all the Object's are types
-	 */
-	for (size_t i = 0; i < objects->dim; i++)
-	{   Object *o = (Object *)objects->data[i];
-
-	    if (o->dyncast() != DYNCAST_TYPE)
-	    {
-		//printf("\tnot[%d], %p, %d\n", i, o, o->dyncast());
-		return NULL;
-	    }
-	}
-
-	/* We know it's a type tuple, so build the TypeTuple
-	 */
-	Arguments *args = new Arguments();
-	args->setDim(objects->dim);
-	OutBuffer buf;
-	for (size_t i = 0; i < objects->dim; i++)
-	{   Type *t = (Type *)objects->data[i];
-
-	    //printf("type = %s\n", t->toChars());
-#if 0
-	    buf.printf("_%s_%d", ident->toChars(), i);
-	    char *name = (char *)buf.extractData();
-	    Identifier *id = new Identifier(name, TOKidentifier);
-	    Argument *arg = new Argument(STCin, t, id, NULL);
-#else
-	    Argument *arg = new Argument(STCin, t, NULL, NULL);
-#endif
-	    args->data[i] = (void *)arg;
-	}
-
-	tupletype = new TypeTuple(args);
-    }
-
-    return tupletype;
-}
-
-int TupleDeclaration::needThis()
-{
-    //printf("TupleDeclaration::needThis(%s)\n", toChars());
-    for (size_t i = 0; i < objects->dim; i++)
-    {   Object *o = (Object *)objects->data[i];
-	if (o->dyncast() == DYNCAST_EXPRESSION)
-	{   Expression *e = (Expression *)o;
-	    if (e->op == TOKdsymbol)
-	    {	DsymbolExp *ve = (DsymbolExp *)e;
-		Declaration *d = ve->s->isDeclaration();
-		if (d && d->needThis())
-		{
-		    return 1;
-		}
-	    }
-	}
-    }
-    return 0;
-}
-
-/********************************* TypedefDeclaration ****************************/
-
-TypedefDeclaration::TypedefDeclaration(Loc loc, Identifier *id, Type *basetype, Initializer *init)
-    : Declaration(id)
-{
-    this->type = new TypeTypedef(this);
-    this->basetype = basetype->toBasetype();
-    this->init = init;
-#ifdef _DH
-    this->htype = NULL;
-    this->hbasetype = NULL;
-#endif
-    this->sem = 0;
-    this->inuse = 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;
-    assert(type);
-}
-
-AliasDeclaration::AliasDeclaration(Loc loc, Identifier *id, Dsymbol *s)
-    : Declaration(id)
-{
-    //printf("AliasDeclaration(id = '%s', s = %p)\n", id->toChars(), s);
-    assert(s != this);
-    this->loc = loc;
-    this->type = NULL;
-    this->aliassym = s;
-#ifdef _DH
-    this->htype = NULL;
-    this->haliassym = NULL;
-#endif
-    this->overnext = NULL;
-    this->inSemantic = 0;
-    assert(s);
-}
-
-Dsymbol *AliasDeclaration::syntaxCopy(Dsymbol *s)
-{
-    //printf("AliasDeclaration::syntaxCopy()\n");
-    assert(!s);
-    AliasDeclaration *sa;
-    if (type)
-	sa = new AliasDeclaration(loc, ident, type->syntaxCopy());
-    else
-	sa = new AliasDeclaration(loc, ident, aliassym->syntaxCopy(NULL));
-#ifdef _DH
-    // Syntax copy for header file
-    if (!htype)	    // Don't overwrite original
-    {	if (type)	// Make copy for both old and new instances
-	{   htype = type->syntaxCopy();
-	    sa->htype = type->syntaxCopy();
-	}
-    }
-    else			// Make copy of original for new instance
-	sa->htype = htype->syntaxCopy();
-    if (!haliassym)
-    {	if (aliassym)
-	{   haliassym = aliassym->syntaxCopy(s);
-	    sa->haliassym = aliassym->syntaxCopy(s);
-	}
-    }
-    else
-	sa->haliassym = haliassym->syntaxCopy(s);
-#endif
-    return sa;
-}
-
-void AliasDeclaration::semantic(Scope *sc)
-{
-    //printf("AliasDeclaration::semantic() %s\n", toChars());
-    if (aliassym)
-    {
-	if (aliassym->isTemplateInstance())
-	    aliassym->semantic(sc);
-	return;
-    }
-    this->inSemantic = 1;
-
-    if (storage_class & STCconst)
-	error("cannot be const");
-
-    storage_class |= sc->stc & STCdeprecated;
-
-    // Given:
-    //	alias foo.bar.abc def;
-    // it is not knowable from the syntax whether this is an alias
-    // for a type or an alias for a symbol. It is up to the semantic()
-    // pass to distinguish.
-    // If it is a type, then type is set and getType() will return that
-    // type. If it is a symbol, then aliassym is set and type is NULL -
-    // toAlias() will return aliasssym.
-
-    Dsymbol *s;
-    Type *t;
-    Expression *e;
-
-    /* This section is needed because resolve() will:
-     *   const x = 3;
-     *   alias x y;
-     * try to alias y to 3.
-     */
-    s = type->toDsymbol(sc);
-    if (s)
-	goto L2;			// it's a symbolic alias
-
-    //printf("alias type is %s\n", type->toChars());
-    type->resolve(loc, sc, &e, &t, &s);
-    if (s)
-    {
-	goto L2;
-    }
-    else if (e)
-    {
-	// Try to convert Expression to Dsymbol
-        if (e->op == TOKvar)
-	{   s = ((VarExp *)e)->var;
-	    goto L2;
-	}
-        else if (e->op == TOKfunction)
-	{   s = ((FuncExp *)e)->fd;
-	    goto L2;
-	}
-        else
-	{   error("cannot alias an expression %s", e->toChars());
-	    t = e->type;
-	}
-    }
-    else if (t)
-	type = t;
-    if (overnext)
-	ScopeDsymbol::multiplyDefined(0, this, overnext);
-    this->inSemantic = 0;
-    return;
-
-  L2:
-    //printf("alias is a symbol %s %s\n", s->kind(), s->toChars());
-    type = NULL;
-    VarDeclaration *v = s->isVarDeclaration();
-    if (v && v->linkage == LINKdefault)
-    {
-	error("forward reference of %s", v->toChars());
-	s = NULL;
-    }
-    else
-    {
-	FuncDeclaration *f = s->toAlias()->isFuncDeclaration();
-	if (f)
-	{
-	    if (overnext)
-	    {
-		FuncAliasDeclaration *fa = new FuncAliasDeclaration(f);
-		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;
-    nestedref = 0;
-    inuse = 0;
-    ctorinit = 0;
-    aliassym = NULL;
-    onstack = 0;
-    canassign = 0;
-    value = 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)
-{
-    //printf("VarDeclaration::semantic('%s', parent = '%s')\n", toChars(), sc->parent->toChars());
-    //printf(" type = %s\n", type ? type->toChars() : "null");
-    //printf(" stc = x%x\n", sc->stc);
-    //printf(" storage_class = x%x\n", storage_class);
-    //printf("linkage = %d\n", sc->linkage);
-    //if (strcmp(toChars(), "mul") == 0) halt();
-
-    storage_class |= sc->stc;
-    if (storage_class & STCextern && init)
-	error("extern symbols cannot have initializers");
-
-    /* If auto type inference, do the inference
-     */
-    int inferred = 0;
-    if (!type)
-    {	inuse++;
-	type = init->inferType(sc);
-	inuse--;
-	inferred = 1;
-
-	/* This is a kludge to support the existing syntax for RAII
-	 * declarations.
-	 */
-	storage_class &= ~STCauto;
-	originalType = type;
-    }
-    else
-    {	if (!originalType)
-	    originalType = type;
-	type = type->semantic(loc, sc);
-    }
-    //printf(" semantic type = %s\n", type ? type->toChars() : "null");
-
-    type->checkDeprecated(loc, sc);
-    linkage = sc->linkage;
-    this->parent = sc->parent;
-    //printf("this = %p, parent = %p, '%s'\n", this, parent, parent->toChars());
-    protection = sc->protection;
-    //printf("sc->stc = %x\n", sc->stc);
-    //printf("storage_class = x%x\n", storage_class);
-
-    Dsymbol *parent = toParent();
-    FuncDeclaration *fd = parent->isFuncDeclaration();
-
-    Type *tb = type->toBasetype();
-    if (tb->ty == Tvoid && !(storage_class & STClazy))
-    {	error("voids have no value");
-	type = Type::terror;
-	tb = type;
-    }
-    if (tb->ty == Tfunction)
-    {	error("cannot be declared to be a function");
-	type = Type::terror;
-	tb = type;
-    }
-    if (tb->ty == Tstruct)
-    {	TypeStruct *ts = (TypeStruct *)tb;
-
-	if (!ts->sym->members)
-	{
-	    error("no definition of struct %s", ts->toChars());
-	}
-    }
-
-    if (tb->ty == Ttuple)
-    {   /* Instead, declare variables for each of the tuple elements
-	 * and add those.
-	 */
-	TypeTuple *tt = (TypeTuple *)tb;
-	size_t nelems = Argument::dim(tt->arguments);
-	Objects *exps = new Objects();
-	exps->setDim(nelems);
-	Expression *ie = init ? init->toExpression() : NULL;
-
-	for (size_t i = 0; i < nelems; i++)
-	{   Argument *arg = Argument::getNth(tt->arguments, i);
-
-	    OutBuffer buf;
-	    buf.printf("_%s_field_%zu", ident->toChars(), i);
-	    buf.writeByte(0);
-	    char *name = (char *)buf.extractData();
-	    Identifier *id = new Identifier(name, TOKidentifier);
-
-	    Expression *einit = ie;
-	    if (ie && ie->op == TOKtuple)
-	    {	einit = (Expression *)((TupleExp *)ie)->exps->data[i];
-	    }
-	    Initializer *ti = init;
-	    if (einit)
-	    {	ti = new ExpInitializer(einit->loc, einit);
-	    }
-
-	    VarDeclaration *v = new VarDeclaration(loc, arg->type, id, ti);
-	    //printf("declaring field %s of type %s\n", v->toChars(), v->type->toChars());
-	    v->semantic(sc);
-            
-/*
-// removed for LDC since TupleDeclaration::toObj already creates the fields;
-// adding them to the scope again leads to duplicates
-	    if (sc->scopesym)
-	    {	//printf("adding %s to %s\n", v->toChars(), sc->scopesym->toChars());
-		if (sc->scopesym->members)
-		    sc->scopesym->members->push(v);
-	    }
-*/
-	    Expression *e = new DsymbolExp(loc, v);
-	    exps->data[i] = e;
-	}
-	TupleDeclaration *v2 = new TupleDeclaration(loc, ident, exps);
-	v2->isexp = 1;
-	aliassym = v2;
-	return;
-    }
-
-    if (storage_class & STCconst && !init && !fd)
-	// Initialize by constructor only
-	storage_class = (storage_class & ~STCconst) | STCctorinit;
-
-    if (isConst())
-    {
-    }
-    else if (isStatic())
-    {
-    }
-    else if (isSynchronized())
-    {
-	error("variable %s cannot be synchronized", toChars());
-    }
-    else if (isOverride())
-    {
-	error("override cannot be applied to variable");
-    }
-    else if (isAbstract())
-    {
-	error("abstract cannot be applied to variable");
-    }
-    else if (storage_class & STCtemplateparameter)
-    {
-    }
-    else
-    {
-	AggregateDeclaration *aad = sc->anonAgg;
-	if (!aad)
-	    aad = parent->isAggregateDeclaration();
-	if (aad)
-	{
-	    aad->addField(sc, this);
-	}
-
-	InterfaceDeclaration *id = parent->isInterfaceDeclaration();
-	if (id)
-	{
-	    error("field not allowed in interface");
-	}
-
-	/* Templates cannot add fields to aggregates
-	 */
-	TemplateInstance *ti = parent->isTemplateInstance();
-	if (ti)
-	{
-	    // Take care of nested templates
-	    while (1)
-	    {
-		TemplateInstance *ti2 = ti->tempdecl->parent->isTemplateInstance();
-		if (!ti2)
-		    break;
-		ti = ti2;
-	    }
-
-	    // If it's a member template
-	    AggregateDeclaration *ad = ti->tempdecl->isMember();
-	    if (ad && storage_class != STCundefined)
-	    {
-		error("cannot use template to add field to aggregate '%s'", ad->toChars());
-	    }
-	}
-    }
-
-    if (type->isauto() && !noauto)
-    {
-	if (storage_class & (STCfield | STCout | STCref | STCstatic) || !fd)
-	{
-	    error("globals, statics, fields, 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 (!init && !sc->inunion && !isStatic() && !isConst() && fd &&
-	!(storage_class & (STCfield | STCin | STCforeach)) &&
-	type->size() != 0)
-    {
-	// Provide a default initializer
-	//printf("Providing default initializer for '%s'\n", toChars());
-	if (type->ty == Tstruct &&
-	    ((TypeStruct *)type)->sym->zeroInit == 1)
-	{   /* If a struct is all zeros, as a special case
-	     * set it's initializer to the integer 0.
-	     * In AssignExp::toElem(), we check for this and issue
-	     * a memset() to initialize the struct.
-	     * Must do same check in interpreter.
-	     */
-	    Expression *e = new IntegerExp(loc, 0, Type::tint32);
-	    Expression *e1;
-	    e1 = new VarExp(loc, this);
-	    e = new AssignExp(loc, e1, e);
-	    e->type = e1->type;
-	    init = new ExpInitializer(loc, e/*->type->defaultInit()*/);
-	    return;
-	}
-	else if (type->ty == Ttypedef)
-	{   TypeTypedef *td = (TypeTypedef *)type;
-	    if (td->sym->init)
-	    {	init = td->sym->init;
-		ExpInitializer *ie = init->isExpInitializer();
-		if (ie)
-		    // Make copy so we can modify it
-		    init = new ExpInitializer(ie->loc, ie->exp);
-	    }
-	    else
-		init = getExpInitializer();
-	}
-	else
-	{
-	    init = getExpInitializer();
-	}
-    }
-
-    if (init)
-    {
-	sc = sc->push();
-	sc->stc &= ~(STCconst | STCinvariant | STCpure);
-
-	ArrayInitializer *ai = init->isArrayInitializer();
-	if (ai && tb->ty == Taarray)
-	{
-	    init = ai->toAssocArrayInitializer();
-	}
-
-	StructInitializer *si = init->isStructInitializer();
-	ExpInitializer *ei = init->isExpInitializer();
-
-	// See if we can allocate on the stack
-	if (ei && isScope() && ei->exp->op == TOKnew)
-	{   NewExp *ne = (NewExp *)ei->exp;
-	    if (!(ne->newargs && ne->newargs->dim))
-	    {	ne->onstack = 1;
-		onstack = 1;
-		if (type->isBaseOf(ne->newtype->semantic(loc, sc), NULL))
-		    onstack = 2;
-	    }
-	}
-
-	// If inside function, there is no semantic3() call
-	if (sc->func)
-	{
-	    // If local variable, use AssignExp to handle all the various
-	    // possibilities.
-	    if (fd && !isStatic() && !isConst() && !init->isVoidInitializer())
-	    {
-		//printf("fd = '%s', var = '%s'\n", fd->toChars(), toChars());
-		if (!ei)
-		{
-		    Expression *e = init->toExpression();
-		    if (!e)
-		    {
-			init = init->semantic(sc, type);
-			e = init->toExpression();
-			if (!e)
-			{   error("is not a static and cannot have static initializer");
-			    return;
-			}
-		    }
-		    ei = new ExpInitializer(init->loc, e);
-		    init = ei;
-		}
-
-		Expression *e1 = new VarExp(loc, this);
-
-		Type *t = type->toBasetype();
-		if (t->ty == Tsarray)
-		{
-		    ei->exp = ei->exp->semantic(sc);
-		    if (!ei->exp->implicitConvTo(type))
-		    {
-			int dim = ((TypeSArray *)t)->dim->toInteger();
-			// If multidimensional static array, treat as one large array
-			while (1)
-			{
-			    t = t->nextOf()->toBasetype();
-			    if (t->ty != Tsarray)
-				break;
-			    dim *= ((TypeSArray *)t)->dim->toInteger();
-			    e1->type = new TypeSArray(t->nextOf(), new IntegerExp(0, dim, Type::tindex));
-			}
-		    }
-		    e1 = new SliceExp(loc, e1, NULL, NULL);
-		}
-		else if (t->ty == Tstruct)
-		{
-		    ei->exp = ei->exp->semantic(sc);
-		    if (!ei->exp->implicitConvTo(type))
-			ei->exp = new CastExp(loc, ei->exp, type);
-		}
-		ei->exp = new AssignExp(loc, e1, ei->exp);
-		ei->exp->op = TOKconstruct;
-		canassign++;
-		ei->exp = ei->exp->semantic(sc);
-		canassign--;
-		ei->exp->optimize(WANTvalue);
-	    }
-	    else
-	    {
-		init = init->semantic(sc, type);
-		if (fd && isConst() && !isStatic())
-		{   // Make it static
-		    storage_class |= STCstatic;
-		}
-	    }
-	}
-	else if (isConst() || isFinal())
-	{
-	    /* Because we may need the results of a const declaration in a
-	     * subsequent type, such as an array dimension, before semantic2()
-	     * gets ordinarily run, try to run semantic2() now.
-	     * Ignore failure.
-	     */
-
-	    if (!global.errors && !inferred)
-	    {
-		unsigned errors = global.errors;
-		global.gag++;
-		//printf("+gag\n");
-		Expression *e;
-		Initializer *i2 = init;
-		inuse++;
-		if (ei)
-		{
-		    e = ei->exp->syntaxCopy();
-		    e = e->semantic(sc);
-		    e = e->implicitCastTo(sc, type);
-		}
-		else if (si || ai)
-		{   i2 = init->syntaxCopy();
-		    i2 = i2->semantic(sc, type);
-		}
-		inuse--;
-		global.gag--;
-		//printf("-gag\n");
-		if (errors != global.errors)	// if errors happened
-		{
-		    if (global.gag == 0)
-			global.errors = errors;	// act as if nothing happened
-		}
-		else if (ei)
-		{
-		    e = e->optimize(WANTvalue | WANTinterpret);
-		    if (e->op == TOKint64 || e->op == TOKstring)
-		    {
-			ei->exp = e;		// no errors, keep result
-		    }
-		}
-		else
-		    init = i2;		// no errors, keep result
-	    }
-	}
-	sc = sc->pop();
-    }
-}
-
-ExpInitializer *VarDeclaration::getExpInitializer()
-{
-    ExpInitializer *ei;
-
-    if (init)
-	ei = init->isExpInitializer();
-    else
-    {
-	Expression *e = type->defaultInit(loc);
-	if (e)
-	    ei = new ExpInitializer(loc, e);
-	else
-	    ei = NULL;
-    }
-    return ei;
-}
-
-void VarDeclaration::semantic2(Scope *sc)
-{
-    //printf("VarDeclaration::semantic2('%s')\n", toChars());
-    if (init && !toParent()->isFuncDeclaration())
-    {	inuse++;
-#if 0
-	ExpInitializer *ei = init->isExpInitializer();
-	if (ei)
-	{
-	    ei->exp->dump(0);
-	    printf("type = %p\n", ei->exp->type);
-	}
-#endif
-	init = init->semantic(sc, type);
-	inuse--;
-    }
-}
-
-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(" = ");
-	init->toCBuffer(buf, hgs);
-    }
-    buf->writeByte(';');
-    buf->writenl();
-}
-
-int VarDeclaration::needThis()
-{
-    //printf("VarDeclaration::needThis(%s, x%x)\n", toChars(), storage_class);
-    return storage_class & STCfield;
-}
-
-int VarDeclaration::isImportedSymbol()
-{
-    if (protection == PROTexport && !init && (isStatic() || isConst() || parent->isModule()))
-	return TRUE;
-    return FALSE;
-}
-
-void VarDeclaration::checkCtorConstInit()
-{
-    if (ctorinit == 0 && isCtorinit() && !(storage_class & STCfield))
-	error("missing initializer in static constructor for const variable");
-}
-
-/************************************
- * Check to see if this variable is actually in an enclosing function
- * rather than the current one.
- */
-
-void VarDeclaration::checkNestedReference(Scope *sc, Loc loc)
-{
-    //printf("VarDeclaration::checkNestedReference() %s\n", toChars());
-    if (parent && !isDataseg() && parent != sc->parent)
-    {
-	// The function that this variable is in
-	FuncDeclaration *fdv = toParent()->isFuncDeclaration();
-	// The current function
-	FuncDeclaration *fdthis = sc->parent->isFuncDeclaration();
-
-	if (fdv && fdthis)
-	{
-	    if (loc.filename)
-		fdthis->getLevel(loc, fdv);
-	    nestedref = 1;
-	    fdv->nestedFrameRef = 1;
-        fdv->nestedVars.insert(this);
-	    //printf("var %s in function %s is nested ref\n", toChars(), fdv->toChars());
-	}
-    }
-}
-
-/*******************************
- * Does symbol go into data segment?
- * Includes extern variables.
- */
-
-int VarDeclaration::isDataseg()
-{
-#if 0
-    printf("VarDeclaration::isDataseg(%p, '%s')\n", this, toChars());
-    printf("%x, %p, %p\n", storage_class & (STCstatic | STCconst), parent->isModule(), parent->isTemplateInstance());
-    printf("parent = '%s'\n", parent->toChars());
-#endif
-    Dsymbol *parent = this->toParent();
-    if (!parent && !(storage_class & (STCstatic | STCconst)))
-    {	error("forward referenced");
-	type = Type::terror;
-	return 0;
-    }
-    return (storage_class & (STCstatic | STCconst) ||
-	   parent->isModule() ||
-	   parent->isTemplateInstance());
-}
-
-int VarDeclaration::hasPointers()
-{
-    return (!isDataseg() && type->hasPointers());
-}
-
-/******************************************
- * If a variable has an auto destructor call, return call for it.
- * Otherwise, return NULL.
- */
-
-Expression *VarDeclaration::callAutoDtor()
-{   Expression *e = NULL;
-
-    //printf("VarDeclaration::callAutoDtor() %s\n", toChars());
-    if (storage_class & (STCauto | STCscope) && !noauto)
-    {
-	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;
+}
+
+void Declaration::semantic(Scope *sc)
+{
+}
+
+const char *Declaration::kind()
+{
+    return "declaration";
+}
+
+unsigned Declaration::size(Loc loc)
+{
+    assert(type);
+    return type->size();
+}
+
+int Declaration::isStaticConstructor()
+{
+    return FALSE;
+}
+
+int Declaration::isStaticDestructor()
+{
+    return FALSE;
+}
+
+int Declaration::isDelete()
+{
+    return FALSE;
+}
+
+int Declaration::isDataseg()
+{
+    return FALSE;
+}
+
+int Declaration::isCodeseg()
+{
+    return FALSE;
+}
+
+enum PROT Declaration::prot()
+{
+    return protection;
+}
+
+/*************************************
+ * Check to see if declaration can be modified in this context (sc).
+ * Issue error if not.
+ */
+
+#if DMDV2
+void Declaration::checkModify(Loc loc, Scope *sc, Type *t)
+{
+    if (sc->incontract && isParameter())
+	error(loc, "cannot modify parameter '%s' in contract", toChars());
+
+    if (isCtorinit())
+    {	// It's only modifiable if inside the right constructor
+	Dsymbol *s = sc->func;
+	while (1)
+	{
+	    FuncDeclaration *fd = NULL;
+	    if (s)
+		fd = s->isFuncDeclaration();
+	    if (fd &&
+		((fd->isCtorDeclaration() && storage_class & STCfield) ||
+		 (fd->isStaticCtorDeclaration() && !(storage_class & STCfield))) &&
+		fd->toParent() == toParent()
+	       )
+	    {
+		VarDeclaration *v = isVarDeclaration();
+		assert(v);
+		v->ctorinit = 1;
+		//printf("setting ctorinit\n");
+	    }
+	    else
+	    {
+		if (s)
+		{   s = s->toParent2();
+		    continue;
+		}
+		else
+		{
+		    const char *p = isStatic() ? "static " : "";
+		    error(loc, "can only initialize %sconst %s inside %sconstructor",
+			p, toChars(), p);
+		}
+	    }
+	    break;
+	}
+    }
+    else
+    {
+	VarDeclaration *v = isVarDeclaration();
+	if (v && v->canassign == 0)
+	{
+	    char *p = NULL;
+	    if (isConst())
+		p = "const";
+	    else if (isInvariant())
+		p = "invariant";
+	    else if (storage_class & STCmanifest)
+		p = "manifest constant";
+	    else if (!t->isAssignable())
+		p = "struct with immutable members";
+	    if (p)
+	    {	error(loc, "cannot modify %s", p);
+		halt();
+	    }
+	}
+    }
+}
+#endif
+
+
+/********************************* TupleDeclaration ****************************/
+
+TupleDeclaration::TupleDeclaration(Loc loc, Identifier *id, Objects *objects)
+    : Declaration(id)
+{
+    this->type = NULL;
+    this->objects = objects;
+    this->isexp = 0;
+    this->tupletype = NULL;
+}
+
+Dsymbol *TupleDeclaration::syntaxCopy(Dsymbol *s)
+{
+    assert(0);
+    return NULL;
+}
+
+const char *TupleDeclaration::kind()
+{
+    return "tuple";
+}
+
+Type *TupleDeclaration::getType()
+{
+    /* If this tuple represents a type, return that type
+     */
+
+    //printf("TupleDeclaration::getType() %s\n", toChars());
+    if (isexp)
+	return NULL;
+    if (!tupletype)
+    {
+	/* It's only a type tuple if all the Object's are types
+	 */
+	for (size_t i = 0; i < objects->dim; i++)
+	{   Object *o = (Object *)objects->data[i];
+
+	    if (o->dyncast() != DYNCAST_TYPE)
+	    {
+		//printf("\tnot[%d], %p, %d\n", i, o, o->dyncast());
+		return NULL;
+	    }
+	}
+
+	/* We know it's a type tuple, so build the TypeTuple
+	 */
+	Arguments *args = new Arguments();
+	args->setDim(objects->dim);
+	OutBuffer buf;
+	for (size_t i = 0; i < objects->dim; i++)
+	{   Type *t = (Type *)objects->data[i];
+
+	    //printf("type = %s\n", t->toChars());
+#if 0
+	    buf.printf("_%s_%d", ident->toChars(), i);
+	    char *name = (char *)buf.extractData();
+	    Identifier *id = new Identifier(name, TOKidentifier);
+	    Argument *arg = new Argument(STCin, t, id, NULL);
+#else
+	    Argument *arg = new Argument(STCin, t, NULL, NULL);
+#endif
+	    args->data[i] = (void *)arg;
+	}
+
+	tupletype = new TypeTuple(args);
+    }
+
+    return tupletype;
+}
+
+int TupleDeclaration::needThis()
+{
+    //printf("TupleDeclaration::needThis(%s)\n", toChars());
+    for (size_t i = 0; i < objects->dim; i++)
+    {   Object *o = (Object *)objects->data[i];
+	if (o->dyncast() == DYNCAST_EXPRESSION)
+	{   Expression *e = (Expression *)o;
+	    if (e->op == TOKdsymbol)
+	    {	DsymbolExp *ve = (DsymbolExp *)e;
+		Declaration *d = ve->s->isDeclaration();
+		if (d && d->needThis())
+		{
+		    return 1;
+		}
+	    }
+	}
+    }
+    return 0;
+}
+
+/********************************* TypedefDeclaration ****************************/
+
+TypedefDeclaration::TypedefDeclaration(Loc loc, Identifier *id, Type *basetype, Initializer *init)
+    : Declaration(id)
+{
+    this->type = new TypeTypedef(this);
+    this->basetype = basetype->toBasetype();
+    this->init = init;
+#ifdef _DH
+    this->htype = NULL;
+    this->hbasetype = NULL;
+#endif
+    this->sem = 0;
+    this->inuse = 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;
+    assert(type);
+}
+
+AliasDeclaration::AliasDeclaration(Loc loc, Identifier *id, Dsymbol *s)
+    : Declaration(id)
+{
+    //printf("AliasDeclaration(id = '%s', s = %p)\n", id->toChars(), s);
+    assert(s != this);
+    this->loc = loc;
+    this->type = NULL;
+    this->aliassym = s;
+#ifdef _DH
+    this->htype = NULL;
+    this->haliassym = NULL;
+#endif
+    this->overnext = NULL;
+    this->inSemantic = 0;
+    assert(s);
+}
+
+Dsymbol *AliasDeclaration::syntaxCopy(Dsymbol *s)
+{
+    //printf("AliasDeclaration::syntaxCopy()\n");
+    assert(!s);
+    AliasDeclaration *sa;
+    if (type)
+	sa = new AliasDeclaration(loc, ident, type->syntaxCopy());
+    else
+	sa = new AliasDeclaration(loc, ident, aliassym->syntaxCopy(NULL));
+#ifdef _DH
+    // Syntax copy for header file
+    if (!htype)	    // Don't overwrite original
+    {	if (type)	// Make copy for both old and new instances
+	{   htype = type->syntaxCopy();
+	    sa->htype = type->syntaxCopy();
+	}
+    }
+    else			// Make copy of original for new instance
+	sa->htype = htype->syntaxCopy();
+    if (!haliassym)
+    {	if (aliassym)
+	{   haliassym = aliassym->syntaxCopy(s);
+	    sa->haliassym = aliassym->syntaxCopy(s);
+	}
+    }
+    else
+	sa->haliassym = haliassym->syntaxCopy(s);
+#endif
+    return sa;
+}
+
+void AliasDeclaration::semantic(Scope *sc)
+{
+    //printf("AliasDeclaration::semantic() %s\n", toChars());
+    if (aliassym)
+    {
+	if (aliassym->isTemplateInstance())
+	    aliassym->semantic(sc);
+	return;
+    }
+    this->inSemantic = 1;
+
+    if (storage_class & STCconst)
+	error("cannot be const");
+
+    storage_class |= sc->stc & STCdeprecated;
+
+    // Given:
+    //	alias foo.bar.abc def;
+    // it is not knowable from the syntax whether this is an alias
+    // for a type or an alias for a symbol. It is up to the semantic()
+    // pass to distinguish.
+    // If it is a type, then type is set and getType() will return that
+    // type. If it is a symbol, then aliassym is set and type is NULL -
+    // toAlias() will return aliasssym.
+
+    Dsymbol *s;
+    Type *t;
+    Expression *e;
+
+    /* This section is needed because resolve() will:
+     *   const x = 3;
+     *   alias x y;
+     * try to alias y to 3.
+     */
+    s = type->toDsymbol(sc);
+    if (s)
+	goto L2;			// it's a symbolic alias
+
+    //printf("alias type is %s\n", type->toChars());
+    type->resolve(loc, sc, &e, &t, &s);
+    if (s)
+    {
+	goto L2;
+    }
+    else if (e)
+    {
+	// Try to convert Expression to Dsymbol
+        if (e->op == TOKvar)
+	{   s = ((VarExp *)e)->var;
+	    goto L2;
+	}
+        else if (e->op == TOKfunction)
+	{   s = ((FuncExp *)e)->fd;
+	    goto L2;
+	}
+        else
+	{   error("cannot alias an expression %s", e->toChars());
+	    t = e->type;
+	}
+    }
+    else if (t)
+	type = t;
+    if (overnext)
+	ScopeDsymbol::multiplyDefined(0, this, overnext);
+    this->inSemantic = 0;
+    return;
+
+  L2:
+    //printf("alias is a symbol %s %s\n", s->kind(), s->toChars());
+    type = NULL;
+    VarDeclaration *v = s->isVarDeclaration();
+    if (v && v->linkage == LINKdefault)
+    {
+	error("forward reference of %s", v->toChars());
+	s = NULL;
+    }
+    else
+    {
+	FuncDeclaration *f = s->toAlias()->isFuncDeclaration();
+	if (f)
+	{
+	    if (overnext)
+	    {
+		FuncAliasDeclaration *fa = new FuncAliasDeclaration(f);
+		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;
+    nestedref = 0;
+    inuse = 0;
+    ctorinit = 0;
+    aliassym = NULL;
+    onstack = 0;
+    canassign = 0;
+    value = 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)
+{
+    //printf("VarDeclaration::semantic('%s', parent = '%s')\n", toChars(), sc->parent->toChars());
+    //printf(" type = %s\n", type ? type->toChars() : "null");
+    //printf(" stc = x%x\n", sc->stc);
+    //printf(" storage_class = x%x\n", storage_class);
+    //printf("linkage = %d\n", sc->linkage);
+    //if (strcmp(toChars(), "mul") == 0) halt();
+
+    storage_class |= sc->stc;
+    if (storage_class & STCextern && init)
+	error("extern symbols cannot have initializers");
+
+    /* If auto type inference, do the inference
+     */
+    int inferred = 0;
+    if (!type)
+    {	inuse++;
+	type = init->inferType(sc);
+	inuse--;
+	inferred = 1;
+
+	/* This is a kludge to support the existing syntax for RAII
+	 * declarations.
+	 */
+	storage_class &= ~STCauto;
+	originalType = type;
+    }
+    else
+    {	if (!originalType)
+	    originalType = type;
+	type = type->semantic(loc, sc);
+    }
+    //printf(" semantic type = %s\n", type ? type->toChars() : "null");
+
+    type->checkDeprecated(loc, sc);
+    linkage = sc->linkage;
+    this->parent = sc->parent;
+    //printf("this = %p, parent = %p, '%s'\n", this, parent, parent->toChars());
+    protection = sc->protection;
+    //printf("sc->stc = %x\n", sc->stc);
+    //printf("storage_class = x%x\n", storage_class);
+
+    Dsymbol *parent = toParent();
+    FuncDeclaration *fd = parent->isFuncDeclaration();
+
+    Type *tb = type->toBasetype();
+    if (tb->ty == Tvoid && !(storage_class & STClazy))
+    {	error("voids have no value");
+	type = Type::terror;
+	tb = type;
+    }
+    if (tb->ty == Tfunction)
+    {	error("cannot be declared to be a function");
+	type = Type::terror;
+	tb = type;
+    }
+    if (tb->ty == Tstruct)
+    {	TypeStruct *ts = (TypeStruct *)tb;
+
+	if (!ts->sym->members)
+	{
+	    error("no definition of struct %s", ts->toChars());
+	}
+    }
+
+    if (tb->ty == Ttuple)
+    {   /* Instead, declare variables for each of the tuple elements
+	 * and add those.
+	 */
+	TypeTuple *tt = (TypeTuple *)tb;
+	size_t nelems = Argument::dim(tt->arguments);
+	Objects *exps = new Objects();
+	exps->setDim(nelems);
+	Expression *ie = init ? init->toExpression() : NULL;
+
+	for (size_t i = 0; i < nelems; i++)
+	{   Argument *arg = Argument::getNth(tt->arguments, i);
+
+	    OutBuffer buf;
+	    buf.printf("_%s_field_%zu", ident->toChars(), i);
+	    buf.writeByte(0);
+	    char *name = (char *)buf.extractData();
+	    Identifier *id = new Identifier(name, TOKidentifier);
+
+	    Expression *einit = ie;
+	    if (ie && ie->op == TOKtuple)
+	    {	einit = (Expression *)((TupleExp *)ie)->exps->data[i];
+	    }
+	    Initializer *ti = init;
+	    if (einit)
+	    {	ti = new ExpInitializer(einit->loc, einit);
+	    }
+
+	    VarDeclaration *v = new VarDeclaration(loc, arg->type, id, ti);
+	    //printf("declaring field %s of type %s\n", v->toChars(), v->type->toChars());
+	    v->semantic(sc);
+            
+/*
+// removed for LDC since TupleDeclaration::toObj already creates the fields;
+// adding them to the scope again leads to duplicates
+	    if (sc->scopesym)
+	    {	//printf("adding %s to %s\n", v->toChars(), sc->scopesym->toChars());
+		if (sc->scopesym->members)
+		    sc->scopesym->members->push(v);
+	    }
+*/
+	    Expression *e = new DsymbolExp(loc, v);
+	    exps->data[i] = e;
+	}
+	TupleDeclaration *v2 = new TupleDeclaration(loc, ident, exps);
+	v2->isexp = 1;
+	aliassym = v2;
+	return;
+    }
+
+    if (storage_class & STCconst && !init && !fd)
+	// Initialize by constructor only
+	storage_class = (storage_class & ~STCconst) | STCctorinit;
+
+    if (isConst())
+    {
+    }
+    else if (isStatic())
+    {
+    }
+    else if (isSynchronized())
+    {
+	error("variable %s cannot be synchronized", toChars());
+    }
+    else if (isOverride())
+    {
+	error("override cannot be applied to variable");
+    }
+    else if (isAbstract())
+    {
+	error("abstract cannot be applied to variable");
+    }
+    else if (storage_class & STCtemplateparameter)
+    {
+    }
+    else
+    {
+	AggregateDeclaration *aad = sc->anonAgg;
+	if (!aad)
+	    aad = parent->isAggregateDeclaration();
+	if (aad)
+	{
+	    aad->addField(sc, this);
+	}
+
+	InterfaceDeclaration *id = parent->isInterfaceDeclaration();
+	if (id)
+	{
+	    error("field not allowed in interface");
+	}
+
+	/* Templates cannot add fields to aggregates
+	 */
+	TemplateInstance *ti = parent->isTemplateInstance();
+	if (ti)
+	{
+	    // Take care of nested templates
+	    while (1)
+	    {
+		TemplateInstance *ti2 = ti->tempdecl->parent->isTemplateInstance();
+		if (!ti2)
+		    break;
+		ti = ti2;
+	    }
+
+	    // If it's a member template
+	    AggregateDeclaration *ad = ti->tempdecl->isMember();
+	    if (ad && storage_class != STCundefined)
+	    {
+		error("cannot use template to add field to aggregate '%s'", ad->toChars());
+	    }
+	}
+    }
+
+    if (type->isauto() && !noauto)
+    {
+	if (storage_class & (STCfield | STCout | STCref | STCstatic) || !fd)
+	{
+	    error("globals, statics, fields, 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 (!init && !sc->inunion && !isStatic() && !isConst() && fd &&
+	!(storage_class & (STCfield | STCin | STCforeach)) &&
+	type->size() != 0)
+    {
+	// Provide a default initializer
+	//printf("Providing default initializer for '%s'\n", toChars());
+	if (type->ty == Tstruct &&
+	    ((TypeStruct *)type)->sym->zeroInit == 1)
+	{   /* If a struct is all zeros, as a special case
+	     * set it's initializer to the integer 0.
+	     * In AssignExp::toElem(), we check for this and issue
+	     * a memset() to initialize the struct.
+	     * Must do same check in interpreter.
+	     */
+	    Expression *e = new IntegerExp(loc, 0, Type::tint32);
+	    Expression *e1;
+	    e1 = new VarExp(loc, this);
+	    e = new AssignExp(loc, e1, e);
+	    e->type = e1->type;
+	    init = new ExpInitializer(loc, e/*->type->defaultInit()*/);
+	    return;
+	}
+	else if (type->ty == Ttypedef)
+	{   TypeTypedef *td = (TypeTypedef *)type;
+	    if (td->sym->init)
+	    {	init = td->sym->init;
+		ExpInitializer *ie = init->isExpInitializer();
+		if (ie)
+		    // Make copy so we can modify it
+		    init = new ExpInitializer(ie->loc, ie->exp);
+	    }
+	    else
+		init = getExpInitializer();
+	}
+	else
+	{
+	    init = getExpInitializer();
+	}
+    }
+
+    if (init)
+    {
+	sc = sc->push();
+	sc->stc &= ~(STCconst | STCinvariant | STCpure);
+
+	ArrayInitializer *ai = init->isArrayInitializer();
+	if (ai && tb->ty == Taarray)
+	{
+	    init = ai->toAssocArrayInitializer();
+	}
+
+	StructInitializer *si = init->isStructInitializer();
+	ExpInitializer *ei = init->isExpInitializer();
+
+	// See if we can allocate on the stack
+	if (ei && isScope() && ei->exp->op == TOKnew)
+	{   NewExp *ne = (NewExp *)ei->exp;
+	    if (!(ne->newargs && ne->newargs->dim))
+	    {	ne->onstack = 1;
+		onstack = 1;
+		if (type->isBaseOf(ne->newtype->semantic(loc, sc), NULL))
+		    onstack = 2;
+	    }
+	}
+
+	// If inside function, there is no semantic3() call
+	if (sc->func)
+	{
+	    // If local variable, use AssignExp to handle all the various
+	    // possibilities.
+	    if (fd && !isStatic() && !isConst() && !init->isVoidInitializer())
+	    {
+		//printf("fd = '%s', var = '%s'\n", fd->toChars(), toChars());
+		if (!ei)
+		{
+		    Expression *e = init->toExpression();
+		    if (!e)
+		    {
+			init = init->semantic(sc, type);
+			e = init->toExpression();
+			if (!e)
+			{   error("is not a static and cannot have static initializer");
+			    return;
+			}
+		    }
+		    ei = new ExpInitializer(init->loc, e);
+		    init = ei;
+		}
+
+		Expression *e1 = new VarExp(loc, this);
+
+		Type *t = type->toBasetype();
+		if (t->ty == Tsarray)
+		{
+		    ei->exp = ei->exp->semantic(sc);
+		    if (!ei->exp->implicitConvTo(type))
+		    {
+			int dim = ((TypeSArray *)t)->dim->toInteger();
+			// If multidimensional static array, treat as one large array
+			while (1)
+			{
+			    t = t->nextOf()->toBasetype();
+			    if (t->ty != Tsarray)
+				break;
+			    dim *= ((TypeSArray *)t)->dim->toInteger();
+			    e1->type = new TypeSArray(t->nextOf(), new IntegerExp(0, dim, Type::tindex));
+			}
+		    }
+		    e1 = new SliceExp(loc, e1, NULL, NULL);
+		}
+		else if (t->ty == Tstruct)
+		{
+		    ei->exp = ei->exp->semantic(sc);
+		    if (!ei->exp->implicitConvTo(type))
+			ei->exp = new CastExp(loc, ei->exp, type);
+		}
+		ei->exp = new AssignExp(loc, e1, ei->exp);
+		ei->exp->op = TOKconstruct;
+		canassign++;
+		ei->exp = ei->exp->semantic(sc);
+		canassign--;
+		ei->exp->optimize(WANTvalue);
+	    }
+	    else
+	    {
+		init = init->semantic(sc, type);
+		if (fd && isConst() && !isStatic())
+		{   // Make it static
+		    storage_class |= STCstatic;
+		}
+	    }
+	}
+	else if (isConst() || isFinal())
+	{
+	    /* Because we may need the results of a const declaration in a
+	     * subsequent type, such as an array dimension, before semantic2()
+	     * gets ordinarily run, try to run semantic2() now.
+	     * Ignore failure.
+	     */
+
+	    if (!global.errors && !inferred)
+	    {
+		unsigned errors = global.errors;
+		global.gag++;
+		//printf("+gag\n");
+		Expression *e;
+		Initializer *i2 = init;
+		inuse++;
+		if (ei)
+		{
+		    e = ei->exp->syntaxCopy();
+		    e = e->semantic(sc);
+		    e = e->implicitCastTo(sc, type);
+		}
+		else if (si || ai)
+		{   i2 = init->syntaxCopy();
+		    i2 = i2->semantic(sc, type);
+		}
+		inuse--;
+		global.gag--;
+		//printf("-gag\n");
+		if (errors != global.errors)	// if errors happened
+		{
+		    if (global.gag == 0)
+			global.errors = errors;	// act as if nothing happened
+		}
+		else if (ei)
+		{
+		    e = e->optimize(WANTvalue | WANTinterpret);
+		    if (e->op == TOKint64 || e->op == TOKstring)
+		    {
+			ei->exp = e;		// no errors, keep result
+		    }
+		}
+		else
+		    init = i2;		// no errors, keep result
+	    }
+	}
+	sc = sc->pop();
+    }
+}
+
+ExpInitializer *VarDeclaration::getExpInitializer()
+{
+    ExpInitializer *ei;
+
+    if (init)
+	ei = init->isExpInitializer();
+    else
+    {
+	Expression *e = type->defaultInit(loc);
+	if (e)
+	    ei = new ExpInitializer(loc, e);
+	else
+	    ei = NULL;
+    }
+    return ei;
+}
+
+void VarDeclaration::semantic2(Scope *sc)
+{
+    //printf("VarDeclaration::semantic2('%s')\n", toChars());
+    if (init && !toParent()->isFuncDeclaration())
+    {	inuse++;
+#if 0
+	ExpInitializer *ei = init->isExpInitializer();
+	if (ei)
+	{
+	    ei->exp->dump(0);
+	    printf("type = %p\n", ei->exp->type);
+	}
+#endif
+	init = init->semantic(sc, type);
+	inuse--;
+    }
+}
+
+const char *VarDeclaration::kind()
+{
+    return "variable";
+}
+
+Dsymbol *VarDeclaration::toAlias()
+{
+    //printf("VarDeclaration::toAlias('%s', this = %p, aliassym = %p)\n", toChars(), this, aliassym);
+    assert(this != aliassym);
+    Dsymbol *s = aliassym ? aliassym->toAlias() : this;
+    return s;
+}
+
+void VarDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    StorageClassDeclaration::stcToCBuffer(buf, storage_class);
+
+    /* If changing, be sure and fix CompoundDeclarationStatement::toCBuffer()
+     * too.
+     */
+    if (type)
+	type->toCBuffer(buf, ident, hgs);
+    else
+	buf->writestring(ident->toChars());
+    if (init)
+    {	buf->writestring(" = ");
+	init->toCBuffer(buf, hgs);
+    }
+    buf->writeByte(';');
+    buf->writenl();
+}
+
+int VarDeclaration::needThis()
+{
+    //printf("VarDeclaration::needThis(%s, x%x)\n", toChars(), storage_class);
+    return storage_class & STCfield;
+}
+
+int VarDeclaration::isImportedSymbol()
+{
+    if (protection == PROTexport && !init && (isStatic() || isConst() || parent->isModule()))
+	return TRUE;
+    return FALSE;
+}
+
+void VarDeclaration::checkCtorConstInit()
+{
+    if (ctorinit == 0 && isCtorinit() && !(storage_class & STCfield))
+	error("missing initializer in static constructor for const variable");
+}
+
+/************************************
+ * Check to see if this variable is actually in an enclosing function
+ * rather than the current one.
+ */
+
+void VarDeclaration::checkNestedReference(Scope *sc, Loc loc)
+{
+    //printf("VarDeclaration::checkNestedReference() %s\n", toChars());
+    if (parent && !isDataseg() && parent != sc->parent)
+    {
+	// The function that this variable is in
+	FuncDeclaration *fdv = toParent()->isFuncDeclaration();
+	// The current function
+	FuncDeclaration *fdthis = sc->parent->isFuncDeclaration();
+
+	if (fdv && fdthis)
+	{
+	    if (loc.filename)
+		fdthis->getLevel(loc, fdv);
+	    nestedref = 1;
+	    fdv->nestedFrameRef = 1;
+        fdv->nestedVars.insert(this);
+	    //printf("var %s in function %s is nested ref\n", toChars(), fdv->toChars());
+	}
+    }
+}
+
+/*******************************
+ * Does symbol go into data segment?
+ * Includes extern variables.
+ */
+
+int VarDeclaration::isDataseg()
+{
+#if 0
+    printf("VarDeclaration::isDataseg(%p, '%s')\n", this, toChars());
+    printf("%x, %p, %p\n", storage_class & (STCstatic | STCconst), parent->isModule(), parent->isTemplateInstance());
+    printf("parent = '%s'\n", parent->toChars());
+#endif
+    Dsymbol *parent = this->toParent();
+    if (!parent && !(storage_class & (STCstatic | STCconst)))
+    {	error("forward referenced");
+	type = Type::terror;
+	return 0;
+    }
+    return (storage_class & (STCstatic | STCconst) ||
+	   parent->isModule() ||
+	   parent->isTemplateInstance());
+}
+
+int VarDeclaration::hasPointers()
+{
+    return (!isDataseg() && type->hasPointers());
+}
+
+/******************************************
+ * If a variable has an auto destructor call, return call for it.
+ * Otherwise, return NULL.
+ */
+
+Expression *VarDeclaration::callAutoDtor()
+{   Expression *e = NULL;
+
+    //printf("VarDeclaration::callAutoDtor() %s\n", toChars());
+    if (storage_class & (STCauto | STCscope) && !noauto)
+    {
+	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;
+}
+
--- a/dmd/declaration.h	Fri Apr 03 17:02:52 2009 +0200
+++ b/dmd/declaration.h	Fri Apr 03 17:59:34 2009 +0200
@@ -1,914 +1,914 @@
-
-// 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
-};
-
-struct Match
-{
-    int count;			// number of matches found
-    MATCH last;			// match level of lastf
-    FuncDeclaration *lastf;	// last matching function we found
-    FuncDeclaration *nextf;	// current matching function
-    FuncDeclaration *anyf;	// pick a func, any func, to use for error recovery
-};
-
-void overloadResolveX(Match *m, FuncDeclaration *f, Expressions *arguments);
-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 0; }
-    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
-    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);
-
-#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;
-
-    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
-    int nestedref;		// referenced by a lexically nested function
-    int inuse;
-    int ctorinit;		// it has been initialized in a ctor
-    int onstack;		// 1: it has been allocated on the stack
-				// 2: on stack, run destructor anyway
-    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)
-
-    VarDeclaration(Loc loc, Type *t, Identifier *id, Initializer *init);
-    Dsymbol *syntaxCopy(Dsymbol *);
-    void semantic(Scope *sc);
-    void semantic2(Scope *sc);
-    const char *kind();
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-#ifdef _DH
-    Type *htype;
-    Initializer *hinit;
-#endif
-    int needThis();
-    int isImportedSymbol();
-    int isDataseg();
-    int hasPointers();
-    Expression *callAutoDtor();
-    ExpInitializer *getExpInitializer();
-    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);
-
-    // LDC
-    AnonDeclaration* anonDecl;
-    unsigned offset2;
-    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
-};
-#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
-#if IN_DMD
-    Symbol *shidden;			// hidden pointer passed to function
-#endif
-
-#if DMDV2
-    enum BUILTIN builtin;		// set if this is a known, builtin
-					// function we can evaluate at compile
-					// time
-
-    int tookAddressOf;			// set if someone took the address of
-					// this function
-    Dsymbols closureVars;		// local variables in this function
-					// which are referenced by nested
-					// functions
-#else
-    int nestedFrameRef;			// !=0 if nested variables referenced
-#endif
-
-    FuncDeclaration(Loc loc, Loc endloc, Identifier *id, enum STC storage_class, Type *type);
-    Dsymbol *syntaxCopy(Dsymbol *);
-    void semantic(Scope *sc);
-    void semantic2(Scope *sc);
-    void semantic3(Scope *sc);
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-    void bodyToCBuffer(OutBuffer *buf, HdrGenState *hgs);
-    int overrides(FuncDeclaration *fd);
-    int findVtblIndex(Array *vtbl, int dim);
-    int overloadInsert(Dsymbol *s);
-    FuncDeclaration *overloadExactMatch(Type *t);
-    FuncDeclaration *overloadResolve(Loc loc, Expressions *arguments);
-    LabelDsymbol *searchLabel(Identifier *ident);
-    AggregateDeclaration *isThis();
-    AggregateDeclaration *isMember2();
-    int getLevel(Loc loc, FuncDeclaration *fd);	// lexical nesting level difference
-    void appendExp(Expression *e);
-    void appendState(Statement *s);
-    char *mangle();
-    int isMain();
-    int isWinMain();
-    int isDllMain();
-    int isExport();
-    int isImportedSymbol();
-    int isAbstract();
-    int isCodeseg();
-    virtual int isNested();
-    int needThis();
-    virtual int isVirtual();
-    virtual int isFinal();
-    virtual int addPreInvariant();
-    virtual int addPostInvariant();
-    Expression *interpret(InterState *istate, Expressions *arguments);
-    void inlineScan();
-    int canInline(int hasthis, int hdrscan = 0);
-    Expression *doInline(InlineScanState *iss, Expression *ethis, Array *arguments);
-    const char *kind();
-    void toDocBuffer(OutBuffer *buf);
-
-// LDC: give argument types to runtime functions
-    static FuncDeclaration *genCfunc(Arguments *args, Type *treturn, const char *name);
-    static FuncDeclaration *genCfunc(Arguments *args, Type *treturn, Identifier *id);
-
-#if IN_DMD
-    Symbol *toSymbol();
-    Symbol *toThunkSymbol(int offset);	// thunk version
-    void toObjFile(int multiobj);			// compile to .obj file
-    int cvMember(unsigned char *p);
-#endif
-
-    FuncDeclaration *isFuncDeclaration() { return this; }
-
-#if IN_LLVM
-    // LDC stuff
-
-    /// Codegen traversal
-    void codegen(Ir* ir);
-
-    // vars declared in this function that nested funcs reference
-    // is this is not empty, nestedFrameRef is set and these VarDecls
-    // probably have nestedref set too, see VarDeclaration::checkNestedReference
-    std::set<VarDeclaration*> nestedVars;
-
-    std::string intrinsicName;
-
-    bool isIntrinsic();
-    bool isVaIntrinsic();
-
-    // we keep our own table of label statements as LabelDsymbolS
-    // don't always carry their corresponding statement along ...
-    typedef std::map<const char*, LabelStatement*> LabelMap;
-    LabelMap labmap;
-
-    // if this is an array operation it gets a little special attention
-    bool isArrayOp;
-
-    // true if overridden with the pragma(allow_inline); stmt
-    bool allowInlining;
-#endif
-};
-
-struct FuncAliasDeclaration : FuncDeclaration
-{
-    FuncDeclaration *funcalias;
-
-    FuncAliasDeclaration(FuncDeclaration *funcalias);
-
-    FuncAliasDeclaration *isFuncAliasDeclaration() { return this; }
-    const char *kind();
-#if IN_DMD
-    Symbol *toSymbol();
-#endif
-};
-
-struct FuncLiteralDeclaration : FuncDeclaration
-{
-    enum TOK tok;			// TOKfunction or TOKdelegate
-
-    FuncLiteralDeclaration(Loc loc, Loc endloc, Type *type, enum TOK tok,
-	ForeachStatement *fes);
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-    Dsymbol *syntaxCopy(Dsymbol *);
-    int isNested();
-    int isVirtual();
-
-    FuncLiteralDeclaration *isFuncLiteralDeclaration() { return this; }
-    const char *kind();
-};
-
-struct CtorDeclaration : FuncDeclaration
-{   Arguments *arguments;
-    int varargs;
-
-    CtorDeclaration(Loc loc, Loc endloc, Arguments *arguments, int varargs);
-    Dsymbol *syntaxCopy(Dsymbol *);
-    void semantic(Scope *sc);
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-    const char *kind();
-    char *toChars();
-    int isVirtual();
-    int addPreInvariant();
-    int addPostInvariant();
-    void toDocBuffer(OutBuffer *buf);
-
-    CtorDeclaration *isCtorDeclaration() { return this; }
-};
-
-#if DMDV2
-struct PostBlitDeclaration : FuncDeclaration
-{
-    PostBlitDeclaration(Loc loc, Loc endloc);
-    PostBlitDeclaration(Loc loc, Loc endloc, Identifier *id);
-    Dsymbol *syntaxCopy(Dsymbol *);
-    void semantic(Scope *sc);
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-    int isVirtual();
-    int addPreInvariant();
-    int addPostInvariant();
-    int overloadInsert(Dsymbol *s);
-    void emitComment(Scope *sc);
-
-    PostBlitDeclaration *isPostBlitDeclaration() { return this; }
-};
-#endif
-
-struct DtorDeclaration : FuncDeclaration
-{
-    DtorDeclaration(Loc loc, Loc endloc);
-    DtorDeclaration(Loc loc, Loc endloc, Identifier *id);
-    Dsymbol *syntaxCopy(Dsymbol *);
-    void semantic(Scope *sc);
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-    int isVirtual();
-    int addPreInvariant();
-    int addPostInvariant();
-    int overloadInsert(Dsymbol *s);
-    void emitComment(Scope *sc);
-
-    DtorDeclaration *isDtorDeclaration() { return this; }
-};
-
-struct StaticCtorDeclaration : FuncDeclaration
-{
-    StaticCtorDeclaration(Loc loc, Loc endloc);
-    Dsymbol *syntaxCopy(Dsymbol *);
-    void semantic(Scope *sc);
-    AggregateDeclaration *isThis();
-    int isStaticConstructor();
-    int isVirtual();
-    int addPreInvariant();
-    int addPostInvariant();
-    void emitComment(Scope *sc);
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-
-    StaticCtorDeclaration *isStaticCtorDeclaration() { return this; }
-};
-
-struct StaticDtorDeclaration : FuncDeclaration
-{   VarDeclaration *vgate;	// 'gate' variable
-
-    StaticDtorDeclaration(Loc loc, Loc endloc);
-    Dsymbol *syntaxCopy(Dsymbol *);
-    void semantic(Scope *sc);
-    AggregateDeclaration *isThis();
-    int isStaticDestructor();
-    int isVirtual();
-    int addPreInvariant();
-    int addPostInvariant();
-    void emitComment(Scope *sc);
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-
-    StaticDtorDeclaration *isStaticDtorDeclaration() { return this; }
-};
-
-struct InvariantDeclaration : FuncDeclaration
-{
-    InvariantDeclaration(Loc loc, Loc endloc);
-    Dsymbol *syntaxCopy(Dsymbol *);
-    void semantic(Scope *sc);
-    int isVirtual();
-    int addPreInvariant();
-    int addPostInvariant();
-    void emitComment(Scope *sc);
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-
-    InvariantDeclaration *isInvariantDeclaration() { return this; }
-};
-
-
-struct UnitTestDeclaration : FuncDeclaration
-{
-    UnitTestDeclaration(Loc loc, Loc endloc);
-    Dsymbol *syntaxCopy(Dsymbol *);
-    void semantic(Scope *sc);
-    AggregateDeclaration *isThis();
-    int isVirtual();
-    int addPreInvariant();
-    int addPostInvariant();
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-
-    UnitTestDeclaration *isUnitTestDeclaration() { return this; }
-};
-
-struct NewDeclaration : FuncDeclaration
-{   Arguments *arguments;
-    int varargs;
-
-    NewDeclaration(Loc loc, Loc endloc, Arguments *arguments, int varargs);
-    Dsymbol *syntaxCopy(Dsymbol *);
-    void semantic(Scope *sc);
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-    const char *kind();
-    int isVirtual();
-    int addPreInvariant();
-    int addPostInvariant();
-
-    NewDeclaration *isNewDeclaration() { return this; }
-};
-
-
-struct DeleteDeclaration : FuncDeclaration
-{   Arguments *arguments;
-
-    DeleteDeclaration(Loc loc, Loc endloc, Arguments *arguments);
-    Dsymbol *syntaxCopy(Dsymbol *);
-    void semantic(Scope *sc);
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-    const char *kind();
-    int isDelete();
-    int isVirtual();
-    int addPreInvariant();
-    int addPostInvariant();
-#ifdef _DH
-    DeleteDeclaration *isDeleteDeclaration() { return this; }
-#endif
-};
-
-#endif /* DMD_DECLARATION_H */
+
+// Compiler implementation of the D programming language
+// Copyright (c) 1999-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
+};
+
+struct Match
+{
+    int count;			// number of matches found
+    MATCH last;			// match level of lastf
+    FuncDeclaration *lastf;	// last matching function we found
+    FuncDeclaration *nextf;	// current matching function
+    FuncDeclaration *anyf;	// pick a func, any func, to use for error recovery
+};
+
+void overloadResolveX(Match *m, FuncDeclaration *f, Expressions *arguments);
+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 0; }
+    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
+    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);
+
+#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;
+
+    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
+    int nestedref;		// referenced by a lexically nested function
+    int inuse;
+    int ctorinit;		// it has been initialized in a ctor
+    int onstack;		// 1: it has been allocated on the stack
+				// 2: on stack, run destructor anyway
+    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)
+
+    VarDeclaration(Loc loc, Type *t, Identifier *id, Initializer *init);
+    Dsymbol *syntaxCopy(Dsymbol *);
+    void semantic(Scope *sc);
+    void semantic2(Scope *sc);
+    const char *kind();
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+#ifdef _DH
+    Type *htype;
+    Initializer *hinit;
+#endif
+    int needThis();
+    int isImportedSymbol();
+    int isDataseg();
+    int hasPointers();
+    Expression *callAutoDtor();
+    ExpInitializer *getExpInitializer();
+    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);
+
+    // LDC
+    AnonDeclaration* anonDecl;
+    unsigned offset2;
+    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
+};
+#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
+#if IN_DMD
+    Symbol *shidden;			// hidden pointer passed to function
+#endif
+
+#if DMDV2
+    enum BUILTIN builtin;		// set if this is a known, builtin
+					// function we can evaluate at compile
+					// time
+
+    int tookAddressOf;			// set if someone took the address of
+					// this function
+    Dsymbols closureVars;		// local variables in this function
+					// which are referenced by nested
+					// functions
+#else
+    int nestedFrameRef;			// !=0 if nested variables referenced
+#endif
+
+    FuncDeclaration(Loc loc, Loc endloc, Identifier *id, enum STC storage_class, Type *type);
+    Dsymbol *syntaxCopy(Dsymbol *);
+    void semantic(Scope *sc);
+    void semantic2(Scope *sc);
+    void semantic3(Scope *sc);
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+    void bodyToCBuffer(OutBuffer *buf, HdrGenState *hgs);
+    int overrides(FuncDeclaration *fd);
+    int findVtblIndex(Array *vtbl, int dim);
+    int overloadInsert(Dsymbol *s);
+    FuncDeclaration *overloadExactMatch(Type *t);
+    FuncDeclaration *overloadResolve(Loc loc, Expressions *arguments);
+    LabelDsymbol *searchLabel(Identifier *ident);
+    AggregateDeclaration *isThis();
+    AggregateDeclaration *isMember2();
+    int getLevel(Loc loc, FuncDeclaration *fd);	// lexical nesting level difference
+    void appendExp(Expression *e);
+    void appendState(Statement *s);
+    char *mangle();
+    int isMain();
+    int isWinMain();
+    int isDllMain();
+    int isExport();
+    int isImportedSymbol();
+    int isAbstract();
+    int isCodeseg();
+    virtual int isNested();
+    int needThis();
+    virtual int isVirtual();
+    virtual int isFinal();
+    virtual int addPreInvariant();
+    virtual int addPostInvariant();
+    Expression *interpret(InterState *istate, Expressions *arguments);
+    void inlineScan();
+    int canInline(int hasthis, int hdrscan = 0);
+    Expression *doInline(InlineScanState *iss, Expression *ethis, Array *arguments);
+    const char *kind();
+    void toDocBuffer(OutBuffer *buf);
+
+// LDC: give argument types to runtime functions
+    static FuncDeclaration *genCfunc(Arguments *args, Type *treturn, const char *name);
+    static FuncDeclaration *genCfunc(Arguments *args, Type *treturn, Identifier *id);
+
+#if IN_DMD
+    Symbol *toSymbol();
+    Symbol *toThunkSymbol(int offset);	// thunk version
+    void toObjFile(int multiobj);			// compile to .obj file
+    int cvMember(unsigned char *p);
+#endif
+
+    FuncDeclaration *isFuncDeclaration() { return this; }
+
+#if IN_LLVM
+    // LDC stuff
+
+    /// Codegen traversal
+    void codegen(Ir* ir);
+
+    // vars declared in this function that nested funcs reference
+    // is this is not empty, nestedFrameRef is set and these VarDecls
+    // probably have nestedref set too, see VarDeclaration::checkNestedReference
+    std::set<VarDeclaration*> nestedVars;
+
+    std::string intrinsicName;
+
+    bool isIntrinsic();
+    bool isVaIntrinsic();
+
+    // we keep our own table of label statements as LabelDsymbolS
+    // don't always carry their corresponding statement along ...
+    typedef std::map<const char*, LabelStatement*> LabelMap;
+    LabelMap labmap;
+
+    // if this is an array operation it gets a little special attention
+    bool isArrayOp;
+
+    // true if overridden with the pragma(allow_inline); stmt
+    bool allowInlining;
+#endif
+};
+
+struct FuncAliasDeclaration : FuncDeclaration
+{
+    FuncDeclaration *funcalias;
+
+    FuncAliasDeclaration(FuncDeclaration *funcalias);
+
+    FuncAliasDeclaration *isFuncAliasDeclaration() { return this; }
+    const char *kind();
+#if IN_DMD
+    Symbol *toSymbol();
+#endif
+};
+
+struct FuncLiteralDeclaration : FuncDeclaration
+{
+    enum TOK tok;			// TOKfunction or TOKdelegate
+
+    FuncLiteralDeclaration(Loc loc, Loc endloc, Type *type, enum TOK tok,
+	ForeachStatement *fes);
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+    Dsymbol *syntaxCopy(Dsymbol *);
+    int isNested();
+    int isVirtual();
+
+    FuncLiteralDeclaration *isFuncLiteralDeclaration() { return this; }
+    const char *kind();
+};
+
+struct CtorDeclaration : FuncDeclaration
+{   Arguments *arguments;
+    int varargs;
+
+    CtorDeclaration(Loc loc, Loc endloc, Arguments *arguments, int varargs);
+    Dsymbol *syntaxCopy(Dsymbol *);
+    void semantic(Scope *sc);
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+    const char *kind();
+    char *toChars();
+    int isVirtual();
+    int addPreInvariant();
+    int addPostInvariant();
+    void toDocBuffer(OutBuffer *buf);
+
+    CtorDeclaration *isCtorDeclaration() { return this; }
+};
+
+#if DMDV2
+struct PostBlitDeclaration : FuncDeclaration
+{
+    PostBlitDeclaration(Loc loc, Loc endloc);
+    PostBlitDeclaration(Loc loc, Loc endloc, Identifier *id);
+    Dsymbol *syntaxCopy(Dsymbol *);
+    void semantic(Scope *sc);
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+    int isVirtual();
+    int addPreInvariant();
+    int addPostInvariant();
+    int overloadInsert(Dsymbol *s);
+    void emitComment(Scope *sc);
+
+    PostBlitDeclaration *isPostBlitDeclaration() { return this; }
+};
+#endif
+
+struct DtorDeclaration : FuncDeclaration
+{
+    DtorDeclaration(Loc loc, Loc endloc);
+    DtorDeclaration(Loc loc, Loc endloc, Identifier *id);
+    Dsymbol *syntaxCopy(Dsymbol *);
+    void semantic(Scope *sc);
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+    int isVirtual();
+    int addPreInvariant();
+    int addPostInvariant();
+    int overloadInsert(Dsymbol *s);
+    void emitComment(Scope *sc);
+
+    DtorDeclaration *isDtorDeclaration() { return this; }
+};
+
+struct StaticCtorDeclaration : FuncDeclaration
+{
+    StaticCtorDeclaration(Loc loc, Loc endloc);
+    Dsymbol *syntaxCopy(Dsymbol *);
+    void semantic(Scope *sc);
+    AggregateDeclaration *isThis();
+    int isStaticConstructor();
+    int isVirtual();
+    int addPreInvariant();
+    int addPostInvariant();
+    void emitComment(Scope *sc);
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+
+    StaticCtorDeclaration *isStaticCtorDeclaration() { return this; }
+};
+
+struct StaticDtorDeclaration : FuncDeclaration
+{   VarDeclaration *vgate;	// 'gate' variable
+
+    StaticDtorDeclaration(Loc loc, Loc endloc);
+    Dsymbol *syntaxCopy(Dsymbol *);
+    void semantic(Scope *sc);
+    AggregateDeclaration *isThis();
+    int isStaticDestructor();
+    int isVirtual();
+    int addPreInvariant();
+    int addPostInvariant();
+    void emitComment(Scope *sc);
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+
+    StaticDtorDeclaration *isStaticDtorDeclaration() { return this; }
+};
+
+struct InvariantDeclaration : FuncDeclaration
+{
+    InvariantDeclaration(Loc loc, Loc endloc);
+    Dsymbol *syntaxCopy(Dsymbol *);
+    void semantic(Scope *sc);
+    int isVirtual();
+    int addPreInvariant();
+    int addPostInvariant();
+    void emitComment(Scope *sc);
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+
+    InvariantDeclaration *isInvariantDeclaration() { return this; }
+};
+
+
+struct UnitTestDeclaration : FuncDeclaration
+{
+    UnitTestDeclaration(Loc loc, Loc endloc);
+    Dsymbol *syntaxCopy(Dsymbol *);
+    void semantic(Scope *sc);
+    AggregateDeclaration *isThis();
+    int isVirtual();
+    int addPreInvariant();
+    int addPostInvariant();
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+
+    UnitTestDeclaration *isUnitTestDeclaration() { return this; }
+};
+
+struct NewDeclaration : FuncDeclaration
+{   Arguments *arguments;
+    int varargs;
+
+    NewDeclaration(Loc loc, Loc endloc, Arguments *arguments, int varargs);
+    Dsymbol *syntaxCopy(Dsymbol *);
+    void semantic(Scope *sc);
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+    const char *kind();
+    int isVirtual();
+    int addPreInvariant();
+    int addPostInvariant();
+
+    NewDeclaration *isNewDeclaration() { return this; }
+};
+
+
+struct DeleteDeclaration : FuncDeclaration
+{   Arguments *arguments;
+
+    DeleteDeclaration(Loc loc, Loc endloc, Arguments *arguments);
+    Dsymbol *syntaxCopy(Dsymbol *);
+    void semantic(Scope *sc);
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+    const char *kind();
+    int isDelete();
+    int isVirtual();
+    int addPreInvariant();
+    int addPostInvariant();
+#ifdef _DH
+    DeleteDeclaration *isDeleteDeclaration() { return this; }
+#endif
+};
+
+#endif /* DMD_DECLARATION_H */
--- a/dmd/enum.c	Fri Apr 03 17:02:52 2009 +0200
+++ b/dmd/enum.c	Fri Apr 03 17:59:34 2009 +0200
@@ -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/dmd/enum.h	Fri Apr 03 17:02:52 2009 +0200
+++ b/dmd/enum.h	Fri Apr 03 17:59:34 2009 +0200
@@ -32,9 +32,9 @@
     Type *memtype;		// type of the members
 
 #if DMDV1
-    integer_t maxval;
-    integer_t minval;
-    integer_t defaultval;	// default initializer
+    dinteger_t maxval;
+    dinteger_t minval;
+    dinteger_t defaultval;	// default initializer
 #else
     Expression *maxval;
     Expression *minval;
--- a/dmd/expression.c	Fri Apr 03 17:02:52 2009 +0200
+++ b/dmd/expression.c	Fri Apr 03 17:59:34 2009 +0200
@@ -34,15 +34,6 @@
 #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
-
 #include "rmem.h"
 
 //#include "port.h"
@@ -700,7 +691,6 @@
 		arg = arg->checkToPointer();
 	    }
 #endif
-
 #if DMDV2
 	    if (tb->ty == Tstruct && !(p->storageClass & (STCref | STCout)))
 	    {
@@ -1000,7 +990,7 @@
     return e1;
 }
 
-integer_t Expression::toInteger()
+dinteger_t Expression::toInteger()
 {
     //printf("Expression %s\n", Token::toChars(op));
     error("Integer constant expression expected instead of %s", toChars());
@@ -1289,7 +1279,7 @@
 
 /******************************** IntegerExp **************************/
 
-IntegerExp::IntegerExp(Loc loc, integer_t value, Type *type)
+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() : "");
@@ -1303,7 +1293,7 @@
     this->value = value;
 }
 
-IntegerExp::IntegerExp(integer_t value)
+IntegerExp::IntegerExp(dinteger_t value)
 	: Expression(0, TOKint64, sizeof(IntegerExp))
 {
     this->type = Type::tint32;
@@ -1333,7 +1323,7 @@
 #endif
 }
 
-integer_t IntegerExp::toInteger()
+dinteger_t IntegerExp::toInteger()
 {   Type *t;
 
     t = type;
@@ -1355,11 +1345,12 @@
 	    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
+                else if (PTRSIZE == 8)
                     value = (d_uns64) value;
+		else
+		    assert(0);
                 break;
 
 	    case Tenum:
@@ -1423,7 +1414,7 @@
     if (!type)
     {
 	// Determine what the type of this number is
-	integer_t number = value;
+	dinteger_t number = value;
 
 	if (number & 0x8000000000000000LL)
 	    type = Type::tuns64;
@@ -1451,7 +1442,7 @@
 
 void IntegerExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
 {
-    integer_t v = toInteger();
+    dinteger_t v = toInteger();
 
     if (type)
     {	Type *t = type;
@@ -1520,7 +1511,7 @@
 		break;
 
 	    case Tuns64:
-            L4:
+	    L4:
 		buf->printf("%juLU", v);
 		break;
 
@@ -1533,11 +1524,12 @@
 		buf->writestring("cast(");
 		buf->writestring(t->toChars());
 		buf->writeByte(')');
-                // FIXME: Other pointer widths than 32 and 64?
                 if (PTRSIZE == 4)
                     goto L3;
-                else
+                else if (PTRSIZE == 8)
                     goto L4;
+		else
+		    assert(0);
 
 	    default:
 		/* This can happen if errors, such as
@@ -1592,7 +1584,7 @@
     return mem.strdup(buffer);
 }
 
-integer_t RealExp::toInteger()
+dinteger_t RealExp::toInteger()
 {
 #ifdef IN_GCC
     return toReal().toInt();
@@ -1817,7 +1809,7 @@
     return mem.strdup(buffer);
 }
 
-integer_t ComplexExp::toInteger()
+dinteger_t ComplexExp::toInteger()
 {
 #ifdef IN_GCC
     return (sinteger_t) toReal().toInt();
@@ -2163,9 +2155,11 @@
     imp = s->isImport();
     if (imp)
     {
-	ScopeExp *ie;
-
-	ie = new ScopeExp(loc, imp->pkg);
+	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();
@@ -3650,7 +3644,7 @@
 
 	if (cd->aggNew)
 	{
-	    // Prepend the size_t size argument to newargs[]
+	    // Prepend the size argument to newargs[]
 	    Expression *e = new IntegerExp(loc, cd->size(loc), Type::tsize_t);
 	    if (!newargs)
 		newargs = new Expressions();
@@ -4319,7 +4313,8 @@
 
 void FuncExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
 {
-    buf->writestring(fd->toChars());
+    fd->toCBuffer(buf, hgs);
+    //buf->writestring(fd->toChars());
 }
 
 
@@ -7593,8 +7588,8 @@
 	    e2 = e2->optimize(WANTvalue);
 	    if (e2->op == TOKint64)
 	    {
-		integer_t index = e2->toInteger();
-		integer_t length = tsa->dim->toInteger();
+		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);
--- a/dmd/expression.h	Fri Apr 03 17:02:52 2009 +0200
+++ b/dmd/expression.h	Fri Apr 03 17:59:34 2009 +0200
@@ -1,6 +1,6 @@
 
 // Compiler implementation of the D programming language
-// Copyright (c) 1999-2008 by Digital Mars
+// Copyright (c) 1999-2009 by Digital Mars
 // All Rights Reserved
 // written by Walter Bright
 // http://www.digitalmars.com
@@ -105,7 +105,7 @@
     static Expression *combine(Expression *e1, Expression *e2);
     static Expressions *arraySyntaxCopy(Expressions *exps);
 
-    virtual integer_t toInteger();
+    virtual dinteger_t toInteger();
     virtual uinteger_t toUInteger();
     virtual real_t toReal();
     virtual real_t toImaginary();
@@ -175,16 +175,16 @@
 
 struct IntegerExp : Expression
 {
-    integer_t value;
+    dinteger_t value;
 
-    IntegerExp(Loc loc, integer_t value, Type *type);
-    IntegerExp(integer_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);
-    integer_t toInteger();
+    dinteger_t toInteger();
     real_t toReal();
     real_t toImaginary();
     complex_t toComplex();
@@ -212,7 +212,7 @@
     Expression *semantic(Scope *sc);
     Expression *interpret(InterState *istate);
     char *toChars();
-    integer_t toInteger();
+    dinteger_t toInteger();
     uinteger_t toUInteger();
     real_t toReal();
     real_t toImaginary();
@@ -240,7 +240,7 @@
     Expression *semantic(Scope *sc);
     Expression *interpret(InterState *istate);
     char *toChars();
-    integer_t toInteger();
+    dinteger_t toInteger();
     uinteger_t toUInteger();
     real_t toReal();
     real_t toImaginary();
--- a/dmd/func.c	Fri Apr 03 17:02:52 2009 +0200
+++ b/dmd/func.c	Fri Apr 03 17:59:34 2009 +0200
@@ -1237,7 +1237,7 @@
 		{   // Call invariant virtually
 		    ThisExp *v = new ThisExp(0);
 		    v->type = vthis->type;
-		    Expression *se = new StringExp(0, "null this");
+		    Expression *se = new StringExp(0, (char *)"null this");
 		    se = se->semantic(sc);
 		    se->type = Type::tchar->arrayOf();
 		    e = new AssertExp(loc, v, se);
@@ -2878,7 +2878,7 @@
     type = type->semantic(loc, sc);
     assert(type->ty == Tfunction);
 
-    // Check that there is at least one argument of type uint
+    // Check that there is at least one argument of type size_t
     TypeFunction *tf = (TypeFunction *)type;
     if (Argument::dim(tf->parameters) < 1)
     {
--- a/dmd/identifier.c	Fri Apr 03 17:02:52 2009 +0200
+++ b/dmd/identifier.c	Fri Apr 03 17:59:34 2009 +0200
@@ -45,9 +45,9 @@
     return (char *)string;
 }
 
-char *Identifier::toHChars2()
+const char *Identifier::toHChars2()
 {
-    char *p = NULL;
+    const char *p = NULL;
 
     if (this == Id::ctor) p = "this";
     else if (this == Id::dtor) p = "~this";
--- a/dmd/identifier.h	Fri Apr 03 17:02:52 2009 +0200
+++ b/dmd/identifier.h	Fri Apr 03 17:59:34 2009 +0200
@@ -37,7 +37,7 @@
 #ifdef _DH
     char *toHChars();
 #endif
-    char *toHChars2();
+    const char *toHChars2();
     int dyncast();
 
     static Identifier *generateId(const char *prefix);
--- a/dmd/lexer.c	Fri Apr 03 17:02:52 2009 +0200
+++ b/dmd/lexer.c	Fri Apr 03 17:59:34 2009 +0200
@@ -1,6 +1,6 @@
 
 // Compiler implementation of the D programming language
-// Copyright (c) 1999-2008 by Digital Mars
+// Copyright (c) 1999-2009 by Digital Mars
 // All Rights Reserved
 // written by Walter Bright
 // http://www.digitalmars.com
@@ -8,7 +8,7 @@
 // in artistic.txt, or the GNU General Public License in gnu.txt.
 // See the included readme.txt for details.
 
-#define __C99FEATURES__ 1
+#include <cmath>
 
 /* Lexical Analyzer */
 
@@ -20,19 +20,7 @@
 #include <wchar.h>
 #include <stdlib.h>
 #include <assert.h>
-#include <math.h>
-
-#if _MSC_VER
-#include <time.h>
-#else
-#include <sys/time.h>
-#endif
-
-#ifdef IN_GCC
-#include <time.h>
-#elif __GNUC__
-#include <time.h>
-#endif
+#include <time.h>	// for time() and ctime()
 
 #include "rmem.h"
 
@@ -49,10 +37,6 @@
 extern "C" char * __cdecl __locale_decpoint;
 #endif
 
-#if _MSC_VER // workaround VC++ bug, labels and types should be in separate namespaces
-#define Lstring Lstr
-#endif
-
 extern int HtmlNamedEntity(unsigned char *p, int length);
 
 #define LS 0x2028	// UTF line separator
@@ -682,7 +666,7 @@
 		    if (mod && id == Id::FILE)
 		    {
 			t->ustring = (unsigned char *)(loc.filename ? loc.filename : mod->ident->toChars());
-			goto Lstring;
+			goto Lstr;
 		    }
 		    else if (mod && id == Id::LINE)
 		    {
@@ -694,22 +678,22 @@
 		    if (id == Id::DATE)
 		    {
 			t->ustring = (unsigned char *)date;
-			goto Lstring;
+			goto Lstr;
 		    }
 		    else if (id == Id::TIME)
 		    {
 			t->ustring = (unsigned char *)time;
-			goto Lstring;
+			goto Lstr;
 		    }
 		    else if (id == Id::VENDOR)
 		    {
 			t->ustring = (unsigned char *)"LDC";
-			goto Lstring;
+			goto Lstr;
 		    }
 		    else if (id == Id::TIMESTAMP)
 		    {
 			t->ustring = (unsigned char *)timestamp;
-		     Lstring:
+		     Lstr:
 			t->value = TOKstring;
 		     Llen:
 			t->postfix = 0;
@@ -3097,4 +3081,6 @@
     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/dmd/lexer.h	Fri Apr 03 17:02:52 2009 +0200
+++ b/dmd/lexer.h	Fri Apr 03 17:59:34 2009 +0200
@@ -1,305 +1,305 @@
-
-// 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,
-
-	// Statements
-	TOKif, TOKelse, TOKwhile, TOKfor, TOKdo, TOKswitch,
-	TOKcase, TOKdefault, TOKbreak, TOKcontinue, TOKwith,
-	TOKsynchronized, TOKreturn, TOKgoto, TOKtry, TOKcatch, TOKfinally,
-	TOKasm, TOKforeach, TOKforeach_reverse,
-	TOKscope,
-	TOKon_scope_exit, TOKon_scope_failure, TOKon_scope_success,
-
-	// Contracts
-	TOKbody, TOKinvariant,
-
-	// Testing
-	TOKunittest,
-
-	// Added after 1.0
-	TOKref,
-	TOKmacro,
-#if DMDV2
-	TOKtraits,
-	TOKoverloadset,
-	TOKpure,
-	TOKnothrow,
-	TOKtls,
-	TOKline,
-	TOKfile,
-    TOKshared,
-#endif
-
-// LDC specific
-#if IN_LLVM
-    TOKgep,
-#endif
-
-	TOKMAX
-};
-
-#define CASE_BASIC_TYPES			\
-	case TOKwchar: case TOKdchar:		\
-	case TOKbit: case TOKbool: case TOKchar:	\
-	case TOKint8: case TOKuns8:		\
-	case TOKint16: case TOKuns16:		\
-	case TOKint32: case TOKuns32:		\
-	case TOKint64: case TOKuns64:		\
-	case TOKfloat32: case TOKfloat64: case TOKfloat80:		\
-	case TOKimaginary32: case TOKimaginary64: case TOKimaginary80:	\
-	case TOKcomplex32: case TOKcomplex64: case TOKcomplex80:	\
-	case TOKvoid
-
-#define CASE_BASIC_TYPES_X(t)					\
-	case TOKvoid:	 t = Type::tvoid;  goto LabelX;		\
-	case TOKint8:	 t = Type::tint8;  goto LabelX;		\
-	case TOKuns8:	 t = Type::tuns8;  goto LabelX;		\
-	case TOKint16:	 t = Type::tint16; goto LabelX;		\
-	case TOKuns16:	 t = Type::tuns16; goto LabelX;		\
-	case TOKint32:	 t = Type::tint32; goto LabelX;		\
-	case TOKuns32:	 t = Type::tuns32; goto LabelX;		\
-	case TOKint64:	 t = Type::tint64; goto LabelX;		\
-	case TOKuns64:	 t = Type::tuns64; goto LabelX;		\
-	case TOKfloat32: t = Type::tfloat32; goto LabelX;	\
-	case TOKfloat64: t = Type::tfloat64; goto LabelX;	\
-	case TOKfloat80: t = Type::tfloat80; goto LabelX;	\
-	case TOKimaginary32: t = Type::timaginary32; goto LabelX;	\
-	case TOKimaginary64: t = Type::timaginary64; goto LabelX;	\
-	case TOKimaginary80: t = Type::timaginary80; goto LabelX;	\
-	case TOKcomplex32: t = Type::tcomplex32; goto LabelX;	\
-	case TOKcomplex64: t = Type::tcomplex64; goto LabelX;	\
-	case TOKcomplex80: t = Type::tcomplex80; goto LabelX;	\
-	case TOKbit:	 t = Type::tbit;     goto LabelX;	\
-	case TOKbool:	 t = Type::tbool;    goto LabelX;	\
-	case TOKchar:	 t = Type::tchar;    goto LabelX;	\
-	case TOKwchar:	 t = Type::twchar; goto LabelX;	\
-	case TOKdchar:	 t = Type::tdchar; goto LabelX;	\
-	LabelX
-
-struct Token
-{
-    Token *next;
-    unsigned char *ptr;		// pointer to first character of this token within buffer
-    enum TOK value;
-    unsigned char *blockComment; // doc comment string prior to this token
-    unsigned char *lineComment;	 // doc comment for previous token
-    union
-    {
-	// Integers
-	d_int64	int64value;
-	d_uns64	uns64value;
-
-	// Floats
-#ifdef IN_GCC
-	// real_t float80value; // can't use this in a union!
-#else
-	d_float80 float80value;
-#endif
-
-	struct
-	{   unsigned char *ustring;	// UTF8 string
-	    unsigned len;
-	    unsigned char postfix;	// 'c', 'w', 'd'
-	};
-
-	Identifier *ident;
-    };
-#ifdef IN_GCC
-    real_t float80value; // can't use this in a union!
-#endif
-
-    static const char *tochars[TOKMAX];
-    static void *operator new(size_t sz);
-
-    int isKeyword();
-    void print();
-    const char *toChars();
-    static const char *toChars(enum TOK);
-};
-
-struct Lexer
-{
-    static StringTable stringtable;
-    static OutBuffer stringbuffer;
-    static Token *freelist;
-
-    Loc loc;			// for error messages
-
-    unsigned char *base;	// pointer to start of buffer
-    unsigned char *end;		// past end of buffer
-    unsigned char *p;		// current character
-    Token token;
-    Module *mod;
-    int doDocComment;		// collect doc comment information
-    int anyToken;		// !=0 means seen at least one token
-    int commentToken;		// !=0 means comments are TOKcomment's
-
-    Lexer(Module *mod,
-	unsigned char *base, unsigned begoffset, unsigned endoffset,
-	int doDocComment, int commentToken);
-
-    static void initKeywords();
-    static Identifier *idPool(const char *s);
-    static Identifier *uniqueId(const char *s);
-    static Identifier *uniqueId(const char *s, int num);
-
-    TOK nextToken();
-    TOK peekNext();
-    void scan(Token *t);
-    Token *peek(Token *t);
-    Token *peekPastParen(Token *t);
-    unsigned escapeSequence();
-    TOK wysiwygStringConstant(Token *t, int tc);
-    TOK hexStringConstant(Token *t);
-#if DMDV2
-    TOK delimitedStringConstant(Token *t);
-    TOK tokenStringConstant(Token *t);
-#endif
-    TOK escapeStringConstant(Token *t, int wide);
-    TOK charConstant(Token *t, int wide);
-    void stringPostfix(Token *t);
-    unsigned wchar(unsigned u);
-    TOK number(Token *t);
-    TOK inreal(Token *t);
-    void error(const char *format, ...);
-    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,	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,
+
+	// Statements
+	TOKif, TOKelse, TOKwhile, TOKfor, TOKdo, TOKswitch,
+	TOKcase, TOKdefault, TOKbreak, TOKcontinue, TOKwith,
+	TOKsynchronized, TOKreturn, TOKgoto, TOKtry, TOKcatch, TOKfinally,
+	TOKasm, TOKforeach, TOKforeach_reverse,
+	TOKscope,
+	TOKon_scope_exit, TOKon_scope_failure, TOKon_scope_success,
+
+	// Contracts
+	TOKbody, TOKinvariant,
+
+	// Testing
+	TOKunittest,
+
+	// Added after 1.0
+	TOKref,
+	TOKmacro,
+#if DMDV2
+	TOKtraits,
+	TOKoverloadset,
+	TOKpure,
+	TOKnothrow,
+	TOKtls,
+	TOKline,
+	TOKfile,
+    TOKshared,
+#endif
+
+// LDC specific
+#if IN_LLVM
+    TOKgep,
+#endif
+
+	TOKMAX
+};
+
+#define CASE_BASIC_TYPES			\
+	case TOKwchar: case TOKdchar:		\
+	case TOKbit: case TOKbool: case TOKchar:	\
+	case TOKint8: case TOKuns8:		\
+	case TOKint16: case TOKuns16:		\
+	case TOKint32: case TOKuns32:		\
+	case TOKint64: case TOKuns64:		\
+	case TOKfloat32: case TOKfloat64: case TOKfloat80:		\
+	case TOKimaginary32: case TOKimaginary64: case TOKimaginary80:	\
+	case TOKcomplex32: case TOKcomplex64: case TOKcomplex80:	\
+	case TOKvoid
+
+#define CASE_BASIC_TYPES_X(t)					\
+	case TOKvoid:	 t = Type::tvoid;  goto LabelX;		\
+	case TOKint8:	 t = Type::tint8;  goto LabelX;		\
+	case TOKuns8:	 t = Type::tuns8;  goto LabelX;		\
+	case TOKint16:	 t = Type::tint16; goto LabelX;		\
+	case TOKuns16:	 t = Type::tuns16; goto LabelX;		\
+	case TOKint32:	 t = Type::tint32; goto LabelX;		\
+	case TOKuns32:	 t = Type::tuns32; goto LabelX;		\
+	case TOKint64:	 t = Type::tint64; goto LabelX;		\
+	case TOKuns64:	 t = Type::tuns64; goto LabelX;		\
+	case TOKfloat32: t = Type::tfloat32; goto LabelX;	\
+	case TOKfloat64: t = Type::tfloat64; goto LabelX;	\
+	case TOKfloat80: t = Type::tfloat80; goto LabelX;	\
+	case TOKimaginary32: t = Type::timaginary32; goto LabelX;	\
+	case TOKimaginary64: t = Type::timaginary64; goto LabelX;	\
+	case TOKimaginary80: t = Type::timaginary80; goto LabelX;	\
+	case TOKcomplex32: t = Type::tcomplex32; goto LabelX;	\
+	case TOKcomplex64: t = Type::tcomplex64; goto LabelX;	\
+	case TOKcomplex80: t = Type::tcomplex80; goto LabelX;	\
+	case TOKbit:	 t = Type::tbit;     goto LabelX;	\
+	case TOKbool:	 t = Type::tbool;    goto LabelX;	\
+	case TOKchar:	 t = Type::tchar;    goto LabelX;	\
+	case TOKwchar:	 t = Type::twchar; goto LabelX;	\
+	case TOKdchar:	 t = Type::tdchar; goto LabelX;	\
+	LabelX
+
+struct Token
+{
+    Token *next;
+    unsigned char *ptr;		// pointer to first character of this token within buffer
+    enum TOK value;
+    unsigned char *blockComment; // doc comment string prior to this token
+    unsigned char *lineComment;	 // doc comment for previous token
+    union
+    {
+	// Integers
+	d_int64	int64value;
+	d_uns64	uns64value;
+
+	// Floats
+#ifdef IN_GCC
+	// real_t float80value; // can't use this in a union!
+#else
+	d_float80 float80value;
+#endif
+
+	struct
+	{   unsigned char *ustring;	// UTF8 string
+	    unsigned len;
+	    unsigned char postfix;	// 'c', 'w', 'd'
+	};
+
+	Identifier *ident;
+    };
+#ifdef IN_GCC
+    real_t float80value; // can't use this in a union!
+#endif
+
+    static const char *tochars[TOKMAX];
+    static void *operator new(size_t sz);
+
+    int isKeyword();
+    void print();
+    const char *toChars();
+    static const char *toChars(enum TOK);
+};
+
+struct Lexer
+{
+    static StringTable stringtable;
+    static OutBuffer stringbuffer;
+    static Token *freelist;
+
+    Loc loc;			// for error messages
+
+    unsigned char *base;	// pointer to start of buffer
+    unsigned char *end;		// past end of buffer
+    unsigned char *p;		// current character
+    Token token;
+    Module *mod;
+    int doDocComment;		// collect doc comment information
+    int anyToken;		// !=0 means seen at least one token
+    int commentToken;		// !=0 means comments are TOKcomment's
+
+    Lexer(Module *mod,
+	unsigned char *base, unsigned begoffset, unsigned endoffset,
+	int doDocComment, int commentToken);
+
+    static void initKeywords();
+    static Identifier *idPool(const char *s);
+    static Identifier *uniqueId(const char *s);
+    static Identifier *uniqueId(const char *s, int num);
+
+    TOK nextToken();
+    TOK peekNext();
+    void scan(Token *t);
+    Token *peek(Token *t);
+    Token *peekPastParen(Token *t);
+    unsigned escapeSequence();
+    TOK wysiwygStringConstant(Token *t, int tc);
+    TOK hexStringConstant(Token *t);
+#if DMDV2
+    TOK delimitedStringConstant(Token *t);
+    TOK tokenStringConstant(Token *t);
+#endif
+    TOK escapeStringConstant(Token *t, int wide);
+    TOK charConstant(Token *t, int wide);
+    void stringPostfix(Token *t);
+    unsigned wchar(unsigned u);
+    TOK number(Token *t);
+    TOK inreal(Token *t);
+    void error(const char *format, ...);
+    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 */
--- a/dmd/mangle.c	Fri Apr 03 17:02:52 2009 +0200
+++ b/dmd/mangle.c	Fri Apr 03 17:59:34 2009 +0200
@@ -117,7 +117,7 @@
 		    return ident->toChars();
 
 		case LINKcpp:
-#if V2 && (TARGET_LINUX || TARGET_OSX)
+#if DMDV2 && (TARGET_LINUX || TARGET_OSX)
 		    return cpp_mangle(this);
 #else
 		    // Windows C++ mangling is done by C++ back end
--- a/dmd/mars.c	Fri Apr 03 17:02:52 2009 +0200
+++ b/dmd/mars.c	Fri Apr 03 17:59:34 2009 +0200
@@ -1,3 +1,4 @@
+
 // Compiler implementation of the D programming language
 // Copyright (c) 1999-2009 by Digital Mars
 // All Rights Reserved
@@ -15,10 +16,6 @@
 #include <string>
 #include <cstdarg>
 
-#if __DMC__
-#include <dos.h>
-#endif
-
 #if POSIX
 #include <errno.h>
 #elif _WIN32
@@ -59,7 +56,7 @@
 
     copyright = "Copyright (c) 1999-2009 by Digital Mars and Tomas Lindquist Olsen";
     written = "written by Walter Bright and Tomas Lindquist Olsen";
-    version = "v1.041";
+    version = "v1.042";
     ldc_version = LDC_REV;
     llvm_version = LLVM_REV_STR;
     global.structalign = 8;
--- a/dmd/mars.h	Fri Apr 03 17:02:52 2009 +0200
+++ b/dmd/mars.h	Fri Apr 03 17:59:34 2009 +0200
@@ -57,6 +57,7 @@
  */
 
 
+#include <stdio.h>
 #include <stdint.h>
 #include <stdarg.h>
 #include <stddef.h>
@@ -77,7 +78,8 @@
 
 #define DMDV2	0	// Version 2.0 features
 #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
+#define STRUCTTHISREF DMDV2	// if 'this' for struct is a reference, not a pointer
+#define SNAN_DEFAULT_INIT DMDV2	// if floats are default initialized to signalling NaN
 
 /* Other targets are TARGET_LINUX and TARGET_OSX, which are
  * set on the command line via the compiler makefile.
@@ -261,11 +263,6 @@
 #define WINDOWS_SEH	(_WIN32 && __DMC__)
 
 
-#if __GNUC__
-//#define memicmp strncasecmp
-//#define stricmp strcasecmp
-#endif
-
 #ifdef __DMC__
  typedef _Complex long double complex_t;
 #else
@@ -274,12 +271,13 @@
  #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;
+// 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;
--- a/dmd/module.c	Fri Apr 03 17:02:52 2009 +0200
+++ b/dmd/module.c	Fri Apr 03 17:59:34 2009 +0200
@@ -1,6 +1,6 @@
 
 // Compiler implementation of the D programming language
-// Copyright (c) 1999-2007 by Digital Mars
+// Copyright (c) 1999-2009 by Digital Mars
 // All Rights Reserved
 // written by Walter Bright
 // http://www.digitalmars.com
--- a/dmd/mtype.c	Fri Apr 03 17:02:52 2009 +0200
+++ b/dmd/mtype.c	Fri Apr 03 17:59:34 2009 +0200
@@ -25,10 +25,6 @@
 #include <assert.h>
 #include <float.h>
 
-#ifdef __DMC__
-#include <fp.h>
-#endif
-
 #if _MSC_VER
 #include <malloc.h>
 #include <complex>
@@ -37,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 "rmem.h"
+#include "port.h"
 
 #include "dsymbol.h"
 #include "mtype.h"
@@ -85,15 +72,18 @@
  */
 
 int PTRSIZE = 4;
-#if IN_LLVM
-int REALSIZE = 8;
-int REALPAD = 0;
-#elif TARGET_LINUX
+#if TARGET_OSX
+int REALSIZE = 16;
+int REALPAD = 6;
+int REALALIGNSIZE = 16;
+#elif TARGET_LINUX || TARGET_FREEBSD
 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;
@@ -1119,24 +1109,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;
 	    }
 	}
@@ -1154,15 +1127,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;
 	}
     }
@@ -1378,7 +1343,7 @@
 }
 
 Expression *TypeBasic::defaultInit(Loc loc)
-{   integer_t value = 0;
+{   dinteger_t value = 0;
 
 #if LOGDEFAULTINIT
     printf("TypeBasic::defaultInit() '%s'\n", toChars());
@@ -1735,7 +1700,7 @@
 }
 
 d_uns64 TypeSArray::size(Loc loc)
-{   integer_t sz;
+{   dinteger_t sz;
 
     if (!dim)
 	return Type::size(loc);
@@ -1747,7 +1712,7 @@
 	sz = ((sz + 31) & ~31) / 8;	// size in bytes, rounded up to 32 bit dwords
     }
     else
-    {	integer_t n, n2;
+    {	dinteger_t n, n2;
 
 	n = next->size();
 	n2 = n * sz;
@@ -1896,7 +1861,7 @@
     Type *tbn = next->toBasetype();
 
     if (dim)
-    {	integer_t n, n2;
+    {	dinteger_t n, n2;
 
 	dim = semanticLength(sc, tbn, dim);
 
@@ -1909,10 +1874,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;
@@ -3052,7 +3017,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)
 		{
--- a/dmd/opover.c	Fri Apr 03 17:02:52 2009 +0200
+++ b/dmd/opover.c	Fri Apr 03 17:59:34 2009 +0200
@@ -18,10 +18,6 @@
 #include <complex>
 #endif
 
-#ifdef __APPLE__
-#define integer_t dmd_integer_t
-#endif
-
 #include "rmem.h"
 
 //#include "port.h"
--- a/dmd/optimize.c	Fri Apr 03 17:02:52 2009 +0200
+++ b/dmd/optimize.c	Fri Apr 03 17:59:34 2009 +0200
@@ -1,791 +1,791 @@
-
-// 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 expression is a variable with a const initializer,
- * return that initializer.
- */
-
-Expression *fromConstInitializer(Expression *e1)
-{
-    //printf("fromConstInitializer(%s)\n", e1->toChars());
-    if (e1->op == TOKvar)
-    {	VarExp *ve = (VarExp *)e1;
-	VarDeclaration *v = ve->var->isVarDeclaration();
-	if (v && v->isConst() && v->init)
-	{   Expression *ei = v->init->toExpression();
-	    if (ei && ei->type)
-		e1 = ei;
-	}
-    }
-    return e1;
-}
-
-
-Expression *Expression::optimize(int result)
-{
-    //printf("Expression::optimize(result = x%x) %s\n", result, toChars());
-    return this;
-}
-
-Expression *VarExp::optimize(int result)
-{
-    if (result & WANTinterpret)
-    {
-	return fromConstInitializer(this);
-    }
-    return this;
-}
-
-Expression *TupleExp::optimize(int result)
-{
-    for (size_t i = 0; i < exps->dim; i++)
-    {   Expression *e = (Expression *)exps->data[i];
-
-	e = e->optimize(WANTvalue | (result & WANTinterpret));
-	exps->data[i] = (void *)e;
-    }
-    return this;
-}
-
-Expression *ArrayLiteralExp::optimize(int result)
-{
-    if (elements)
-    {
-	for (size_t i = 0; i < elements->dim; i++)
-	{   Expression *e = (Expression *)elements->data[i];
-
-	    e = e->optimize(WANTvalue | (result & WANTinterpret));
-	    elements->data[i] = (void *)e;
-	}
-    }
-    return this;
-}
-
-Expression *AssocArrayLiteralExp::optimize(int result)
-{
-    assert(keys->dim == values->dim);
-    for (size_t i = 0; i < keys->dim; i++)
-    {   Expression *e = (Expression *)keys->data[i];
-
-	e = e->optimize(WANTvalue | (result & WANTinterpret));
-	keys->data[i] = (void *)e;
-
-	e = (Expression *)values->data[i];
-	e = e->optimize(WANTvalue | (result & WANTinterpret));
-	values->data[i] = (void *)e;
-    }
-    return this;
-}
-
-Expression *StructLiteralExp::optimize(int result)
-{
-    if (elements)
-    {
-	for (size_t i = 0; i < elements->dim; i++)
-	{   Expression *e = (Expression *)elements->data[i];
-	    if (!e)
-		continue;
-	    e = e->optimize(WANTvalue | (result & WANTinterpret));
-	    elements->data[i] = (void *)e;
-	}
-    }
-    return this;
-}
-
-Expression *TypeExp::optimize(int result)
-{
-    return this;
-}
-
-Expression *UnaExp::optimize(int result)
-{
-    e1 = e1->optimize(result);
-    return this;
-}
-
-Expression *NegExp::optimize(int result)
-{   Expression *e;
-
-    e1 = e1->optimize(result);
-    if (e1->isConst() == 1)
-    {
-	e = Neg(type, e1);
-    }
-    else
-	e = this;
-    return e;
-}
-
-Expression *ComExp::optimize(int result)
-{   Expression *e;
-
-    e1 = e1->optimize(result);
-    if (e1->isConst() == 1)
-    {
-	e = Com(type, e1);
-    }
-    else
-	e = this;
-    return e;
-}
-
-Expression *NotExp::optimize(int result)
-{   Expression *e;
-
-    e1 = e1->optimize(result);
-    if (e1->isConst() == 1)
-    {
-	e = Not(type, e1);
-    }
-    else
-	e = this;
-    return e;
-}
-
-Expression *BoolExp::optimize(int result)
-{   Expression *e;
-
-    e1 = e1->optimize(result);
-    if (e1->isConst() == 1)
-    {
-	e = Bool(type, e1);
-    }
-    else
-	e = this;
-    return e;
-}
-
-Expression *AddrExp::optimize(int result)
-{   Expression *e;
-
-    //printf("AddrExp::optimize(result = %d) %s\n", result, toChars());
-    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())
-	{
-	    e = new SymOffExp(loc, ve->var, 0);
-	    e->type = type;
-	    return e;
-	}
-    }
-    if (e1->op == TOKindex)
-    {	// Convert &array[n] to &array+n
-	IndexExp *ae = (IndexExp *)e1;
-
-	if (ae->e2->op == TOKint64 && ae->e1->op == TOKvar)
-	{
-	    integer_t index = ae->e2->toInteger();
-	    VarExp *ve = (VarExp *)ae->e1;
-	    if (ve->type->ty == Tsarray && ve->type->next->ty != Tbit
-		&& !ve->var->isImportedSymbol())
-	    {
-		TypeSArray *ts = (TypeSArray *)ve->type;
-		integer_t dim = ts->dim->toInteger();
-		if (index < 0 || index >= dim)
-		    error("array index %jd is out of bounds [0..%jd]", index, dim);
-		e = new SymOffExp(loc, ve->var, index * ts->next->size());
-		e->type = type;
-		return e;
-	    }
-	}
-    }
-#endif
-    return this;
-}
-
-Expression *PtrExp::optimize(int result)
-{
-    //printf("PtrExp::optimize(result = x%x) %s\n", result, toChars());
-    e1 = e1->optimize(result);
-    // Convert *&ex to ex
-    if (e1->op == TOKaddress)
-    {	Expression *e;
-	Expression *ex;
-
-	ex = ((AddrExp *)e1)->e1;
-	if (type->equals(ex->type))
-	    e = ex;
-	else
-	{
-	    e = ex->copy();
-	    e->type = type;
-	}
-	return e;
-    }
-    // Constant fold *(&structliteral + offset)
-    if (e1->op == TOKadd)
-    {
-	Expression *e;
-	e = Ptr(type, e1);
-	if (e != EXP_CANT_INTERPRET)
-	    return e;
-    }
-
-    return this;
-}
-
-Expression *DotVarExp::optimize(int result)
-{
-    //printf("DotVarExp::optimize(result = x%x) %s\n", result, toChars());
-    e1 = e1->optimize(result);
-
-#if DMDV2
-    if (e1->op == TOKvar)
-    {	VarExp *ve = (VarExp *)e1;
-	VarDeclaration *v = ve->var->isVarDeclaration();
-	Expression *e = expandVar(result, v);
-	if (e && e->op == TOKstructliteral)
-	{   StructLiteralExp *sle = (StructLiteralExp *)e;
-	    VarDeclaration *vf = var->isVarDeclaration();
-	    if (vf)
-	    {
-		e = sle->getField(type, vf->offset);
-		if (e != EXP_CANT_INTERPRET)
-		    return e;
-	    }
-	}
-    }
-    else
-#endif
-    if (e1->op == TOKstructliteral)
-    {   StructLiteralExp *sle = (StructLiteralExp *)e1;
-	VarDeclaration *vf = var->isVarDeclaration();
-	if (vf)
-	{
-	    Expression *e = sle->getField(type, vf->offset);
-	    if (e != EXP_CANT_INTERPRET)
-		return e;
-	}
-    }
-
-    return this;
-}
-
-Expression *CallExp::optimize(int result)
-{   Expression *e = this;
-
-    e1 = e1->optimize(result);
-    if (e1->op == TOKvar && result & WANTinterpret)
-    {
-	FuncDeclaration *fd = ((VarExp *)e1)->var->isFuncDeclaration();
-	if (fd)
-	{
-	    Expression *eresult = fd->interpret(NULL, arguments);
-	    if (eresult && eresult != EXP_VOID_INTERPRET)
-		e = eresult;
-	    else if (result & WANTinterpret)
-		error("cannot evaluate %s at compile time", toChars());
-	}
-    }
-    return e;
-}
-
-
-Expression *CastExp::optimize(int result)
-{
-    //printf("CastExp::optimize(result = %d) %s\n", result, toChars());
-    //printf("from %s to %s\n", type->toChars(), to->toChars());
-    //printf("from %s\n", type->toChars());
-    //printf("e1->type %s\n", e1->type->toChars());
-    //printf("type = %p\n", type);
-    assert(type);
-    enum TOK op1 = e1->op;
-
-    e1 = e1->optimize(result);
-    if (result & WANTinterpret)
-	e1 = fromConstInitializer(e1);
-
-    if ((e1->op == TOKstring || e1->op == TOKarrayliteral) &&
-	(type->ty == Tpointer || type->ty == Tarray) &&
-	type->next->equals(e1->type->next)
-       )
-    {
-	// make a copy before adjusting type to avoid
-	// messing up the type of an existing initializer
-	e1 = e1->syntaxCopy();
-	e1->type = type;
-	return e1;
-    }
-    /* The first test here is to prevent infinite loops
-     */
-    if (op1 != TOKarrayliteral && e1->op == TOKarrayliteral)
-	return e1->castTo(NULL, to);
-    if (e1->op == TOKnull &&
-	(type->ty == Tpointer || type->ty == Tclass))
-    {
-	e1->type = type;
-	return e1;
-    }
-
-    if (result & WANTflags && type->ty == Tclass && e1->type->ty == Tclass)
-    {
-	// See if we can remove an unnecessary cast
-	ClassDeclaration *cdfrom;
-	ClassDeclaration *cdto;
-	int offset;
-
-	cdfrom = e1->type->isClassHandle();
-	cdto   = type->isClassHandle();
-	if (cdto->isBaseOf(cdfrom, &offset) && offset == 0)
-	{
-	    e1->type = type;
-	    return e1;
-	}
-    }
-
-    Expression *e;
-
-    if (e1->isConst())
-    {
-	if (e1->op == TOKsymoff)
-	{
-	    if (type->size() == e1->type->size() &&
-		type->toBasetype()->ty != Tsarray)
-	    {
-		e1->type = type;
-		return e1;
-	    }
-	    return this;
-	}
-	if (to->toBasetype()->ty == Tvoid)
-	    e = this;
-	else
-	    e = Cast(type, to, e1);
-    }
-    else
-	e = this;
-    return e;
-}
-
-Expression *BinExp::optimize(int result)
-{
-    //printf("BinExp::optimize(result = %d) %s\n", result, toChars());
-    e1 = e1->optimize(result);
-    e2 = e2->optimize(result);
-    if (op == TOKshlass || op == TOKshrass || op == TOKushrass)
-    {
-	if (e2->isConst() == 1)
-	{
-	    integer_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)
-    {
-	integer_t i2 = e->e2->toInteger();
-	d_uns64 sz = e->e1->type->size() * 8;
-	if (i2 < 0 || i2 > sz)
-	{   e->error("shift by %jd is outside the range 0..%zu", i2, sz);
-	    e->e2 = new IntegerExp(0);
-	}
-	if (e->e1->isConst() == 1)
-	    ex = (*shift)(e->type, e->e1, e->e2);
-    }
-    return ex;
-}
-
-Expression *ShlExp::optimize(int result)
-{
-    //printf("ShlExp::optimize(result = %d) %s\n", result, toChars());
-    return shift_optimize(result, this, Shl);
-}
-
-Expression *ShrExp::optimize(int result)
-{
-    //printf("ShrExp::optimize(result = %d) %s\n", result, toChars());
-    return shift_optimize(result, this, Shr);
-}
-
-Expression *UshrExp::optimize(int result)
-{
-    //printf("UshrExp::optimize(result = %d) %s\n", result, toChars());
-    return shift_optimize(result, this, Ushr);
-}
-
-Expression *AndExp::optimize(int result)
-{   Expression *e;
-
-    e1 = e1->optimize(result);
-    e2 = e2->optimize(result);
-    if (e1->isConst() == 1 && e2->isConst() == 1)
-	e = And(type, e1, e2);
-    else
-	e = this;
-    return e;
-}
-
-Expression *OrExp::optimize(int result)
-{   Expression *e;
-
-    e1 = e1->optimize(result);
-    e2 = e2->optimize(result);
-    if (e1->isConst() == 1 && e2->isConst() == 1)
-	e = Or(type, e1, e2);
-    else
-	e = this;
-    return e;
-}
-
-Expression *XorExp::optimize(int result)
-{   Expression *e;
-
-    e1 = e1->optimize(result);
-    e2 = e2->optimize(result);
-    if (e1->isConst() == 1 && e2->isConst() == 1)
-	e = Xor(type, e1, e2);
-    else
-	e = this;
-    return e;
-}
-
-Expression *CommaExp::optimize(int result)
-{   Expression *e;
-
-    //printf("CommaExp::optimize(result = %d) %s\n", result, toChars());
-    e1 = e1->optimize(result & WANTinterpret);
-    e2 = e2->optimize(result);
-    if (!e1 || e1->op == TOKint64 || e1->op == TOKfloat64 || !e1->checkSideEffect(2))
-    {
-	e = e2;
-	if (e)
-	    e->type = type;
-    }
-    else
-	e = this;
-    //printf("-CommaExp::optimize(result = %d) %s\n", result, e->toChars());
-    return e;
-}
-
-Expression *ArrayLengthExp::optimize(int result)
-{   Expression *e;
-
-    //printf("ArrayLengthExp::optimize(result = %d) %s\n", result, toChars());
-    e1 = e1->optimize(WANTvalue | (result & WANTinterpret));
-    e = this;
-    if (e1->op == TOKstring || e1->op == TOKarrayliteral || e1->op == TOKassocarrayliteral)
-    {
-	e = ArrayLength(type, e1);
-    }
-    return e;
-}
-
-Expression *EqualExp::optimize(int result)
-{   Expression *e;
-
-    //printf("EqualExp::optimize(result = %x) %s\n", result, toChars());
-    e1 = e1->optimize(WANTvalue | (result & WANTinterpret));
-    e2 = e2->optimize(WANTvalue | (result & WANTinterpret));
-    e = this;
-
-    Expression *e1 = fromConstInitializer(this->e1);
-    Expression *e2 = fromConstInitializer(this->e2);
-
-    e = Equal(op, type, e1, e2);
-    if (e == EXP_CANT_INTERPRET)
-	e = this;
-    return e;
-}
-
-Expression *IdentityExp::optimize(int result)
-{   Expression *e;
-
-    //printf("IdentityExp::optimize(result = %d) %s\n", result, toChars());
-    e1 = e1->optimize(WANTvalue | (result & WANTinterpret));
-    e2 = e2->optimize(WANTvalue | (result & WANTinterpret));
-    e = this;
-
-    if (this->e1->isConst() && this->e2->isConst())
-    {
-	e = Identity(op, type, this->e1, this->e2);
-    }
-    return e;
-}
-
-Expression *IndexExp::optimize(int result)
-{   Expression *e;
-
-    //printf("IndexExp::optimize(result = %d) %s\n", result, toChars());
-    Expression *e1 = this->e1->optimize(WANTvalue | (result & WANTinterpret));
-    if (result & WANTinterpret)
-	e1 = fromConstInitializer(e1);
-    e2 = e2->optimize(WANTvalue | (result & WANTinterpret));
-    e = Index(type, e1, e2);
-    if (e == EXP_CANT_INTERPRET)
-	e = this;
-    return e;
-}
-
-Expression *SliceExp::optimize(int result)
-{   Expression *e;
-
-    //printf("SliceExp::optimize(result = %d) %s\n", result, toChars());
-    e = this;
-    e1 = e1->optimize(WANTvalue | (result & WANTinterpret));
-    if (!lwr)
-    {	if (e1->op == TOKstring)
-	{   // Convert slice of string literal into dynamic array
-	    Type *t = e1->type->toBasetype();
-	    if (t->next)
-		e = e1->castTo(NULL, t->next->arrayOf());
-	}
-	return e;
-    }
-    if (result & WANTinterpret)
-	e1 = fromConstInitializer(e1);
-    lwr = lwr->optimize(WANTvalue | (result & WANTinterpret));
-    upr = upr->optimize(WANTvalue | (result & WANTinterpret));
-    e = Slice(type, e1, lwr, upr);
-    if (e == EXP_CANT_INTERPRET)
-	e = this;
-    return e;
-}
-
-Expression *AndAndExp::optimize(int result)
-{   Expression *e;
-
-    //printf("AndAndExp::optimize(%d) %s\n", result, toChars());
-    e1 = e1->optimize(WANTflags | (result & WANTinterpret));
-    e = this;
-    if (e1->isBool(FALSE))
-    {
-	e = new CommaExp(loc, e1, new IntegerExp(loc, 0, type));
-	e->type = type;
-	e = e->optimize(result);
-    }
-    else
-    {
-	e2 = e2->optimize(WANTflags | (result & WANTinterpret));
-	if (result && e2->type->toBasetype()->ty == Tvoid && !global.errors)
-	    error("void has no value");
-	if (e1->isConst())
-	{
-	    if (e2->isConst())
-	    {	int n1 = e1->isBool(1);
-		int n2 = e2->isBool(1);
-
-		e = new IntegerExp(loc, n1 && n2, type);
-	    }
-	    else if (e1->isBool(TRUE))
-		e = new BoolExp(loc, e2, type);
-	}
-    }
-    return e;
-}
-
-Expression *OrOrExp::optimize(int result)
-{   Expression *e;
-
-    e1 = e1->optimize(WANTflags | (result & WANTinterpret));
-    e = this;
-    if (e1->isBool(TRUE))
-    {	// Replace with (e1, 1)
-	e = new CommaExp(loc, e1, new IntegerExp(loc, 1, type));
-	e->type = type;
-	e = e->optimize(result);
-    }
-    else
-    {
-	e2 = e2->optimize(WANTflags | (result & WANTinterpret));
-	if (result && e2->type->toBasetype()->ty == Tvoid && !global.errors)
-	    error("void has no value");
-	if (e1->isConst())
-	{
-	    if (e2->isConst())
-	    {	int n1 = e1->isBool(1);
-		int n2 = e2->isBool(1);
-
-		e = new IntegerExp(loc, n1 || n2, type);
-	    }
-	    else if (e1->isBool(FALSE))
-		e = new BoolExp(loc, e2, type);
-	}
-    }
-    return e;
-}
-
-Expression *CmpExp::optimize(int result)
-{   Expression *e;
-
-    //printf("CmpExp::optimize() %s\n", toChars());
-    e1 = e1->optimize(result);
-    e2 = e2->optimize(result);
-    if (e1->isConst() == 1 && e2->isConst() == 1)
-    {
-	e = Cmp(op, type, this->e1, this->e2);
-    }
-    else
-	e = this;
-    return e;
-}
-
-Expression *CatExp::optimize(int result)
-{   Expression *e;
-
-    //printf("CatExp::optimize(%d) %s\n", result, toChars());
-    e1 = e1->optimize(result);
-    e2 = e2->optimize(result);
-    e = Cat(type, e1, e2);
-    if (e == EXP_CANT_INTERPRET)
-	e = this;
-    return e;
-}
-
-
-Expression *CondExp::optimize(int result)
-{   Expression *e;
-
-    econd = econd->optimize(WANTflags | (result & WANTinterpret));
-    if (econd->isBool(TRUE))
-	e = e1->optimize(result);
-    else if (econd->isBool(FALSE))
-	e = e2->optimize(result);
-    else
-    {	e1 = e1->optimize(result);
-	e2 = e2->optimize(result);
-	e = this;
-    }
-    return e;
-}
-
-
+
+// Compiler implementation of the D programming language
+// Copyright (c) 1999-2009 by Digital Mars
+// All Rights Reserved
+// written by Walter Bright
+// http://www.digitalmars.com
+// License for redistribution is by either the Artistic License
+// in artistic.txt, or the GNU General Public License in gnu.txt.
+// See the included readme.txt for details.
+
+#include <stdio.h>
+#include <ctype.h>
+#include <assert.h>
+#include <math.h>
+
+#if __DMC__
+#include <complex.h>
+#endif
+
+#include "lexer.h"
+#include "mtype.h"
+#include "expression.h"
+#include "declaration.h"
+#include "aggregate.h"
+#include "init.h"
+
+
+#ifdef IN_GCC
+#include "d-gcc-real.h"
+
+/* %% fix? */
+extern "C" bool real_isnan (const real_t *);
+#endif
+
+static real_t zero;	// work around DMC bug for now
+
+
+/*************************************
+ * If expression is a variable with a const initializer,
+ * return that initializer.
+ */
+
+Expression *fromConstInitializer(Expression *e1)
+{
+    //printf("fromConstInitializer(%s)\n", e1->toChars());
+    if (e1->op == TOKvar)
+    {	VarExp *ve = (VarExp *)e1;
+	VarDeclaration *v = ve->var->isVarDeclaration();
+	if (v && v->isConst() && v->init)
+	{   Expression *ei = v->init->toExpression();
+	    if (ei && ei->type)
+		e1 = ei;
+	}
+    }
+    return e1;
+}
+
+
+Expression *Expression::optimize(int result)
+{
+    //printf("Expression::optimize(result = x%x) %s\n", result, toChars());
+    return this;
+}
+
+Expression *VarExp::optimize(int result)
+{
+    if (result & WANTinterpret)
+    {
+	return fromConstInitializer(this);
+    }
+    return this;
+}
+
+Expression *TupleExp::optimize(int result)
+{
+    for (size_t i = 0; i < exps->dim; i++)
+    {   Expression *e = (Expression *)exps->data[i];
+
+	e = e->optimize(WANTvalue | (result & WANTinterpret));
+	exps->data[i] = (void *)e;
+    }
+    return this;
+}
+
+Expression *ArrayLiteralExp::optimize(int result)
+{
+    if (elements)
+    {
+	for (size_t i = 0; i < elements->dim; i++)
+	{   Expression *e = (Expression *)elements->data[i];
+
+	    e = e->optimize(WANTvalue | (result & WANTinterpret));
+	    elements->data[i] = (void *)e;
+	}
+    }
+    return this;
+}
+
+Expression *AssocArrayLiteralExp::optimize(int result)
+{
+    assert(keys->dim == values->dim);
+    for (size_t i = 0; i < keys->dim; i++)
+    {   Expression *e = (Expression *)keys->data[i];
+
+	e = e->optimize(WANTvalue | (result & WANTinterpret));
+	keys->data[i] = (void *)e;
+
+	e = (Expression *)values->data[i];
+	e = e->optimize(WANTvalue | (result & WANTinterpret));
+	values->data[i] = (void *)e;
+    }
+    return this;
+}
+
+Expression *StructLiteralExp::optimize(int result)
+{
+    if (elements)
+    {
+	for (size_t i = 0; i < elements->dim; i++)
+	{   Expression *e = (Expression *)elements->data[i];
+	    if (!e)
+		continue;
+	    e = e->optimize(WANTvalue | (result & WANTinterpret));
+	    elements->data[i] = (void *)e;
+	}
+    }
+    return this;
+}
+
+Expression *TypeExp::optimize(int result)
+{
+    return this;
+}
+
+Expression *UnaExp::optimize(int result)
+{
+    e1 = e1->optimize(result);
+    return this;
+}
+
+Expression *NegExp::optimize(int result)
+{   Expression *e;
+
+    e1 = e1->optimize(result);
+    if (e1->isConst() == 1)
+    {
+	e = Neg(type, e1);
+    }
+    else
+	e = this;
+    return e;
+}
+
+Expression *ComExp::optimize(int result)
+{   Expression *e;
+
+    e1 = e1->optimize(result);
+    if (e1->isConst() == 1)
+    {
+	e = Com(type, e1);
+    }
+    else
+	e = this;
+    return e;
+}
+
+Expression *NotExp::optimize(int result)
+{   Expression *e;
+
+    e1 = e1->optimize(result);
+    if (e1->isConst() == 1)
+    {
+	e = Not(type, e1);
+    }
+    else
+	e = this;
+    return e;
+}
+
+Expression *BoolExp::optimize(int result)
+{   Expression *e;
+
+    e1 = e1->optimize(result);
+    if (e1->isConst() == 1)
+    {
+	e = Bool(type, e1);
+    }
+    else
+	e = this;
+    return e;
+}
+
+Expression *AddrExp::optimize(int result)
+{   Expression *e;
+
+    //printf("AddrExp::optimize(result = %d) %s\n", result, toChars());
+    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())
+	{
+	    e = new SymOffExp(loc, ve->var, 0);
+	    e->type = type;
+	    return e;
+	}
+    }
+    if (e1->op == TOKindex)
+    {	// Convert &array[n] to &array+n
+	IndexExp *ae = (IndexExp *)e1;
+
+	if (ae->e2->op == TOKint64 && ae->e1->op == TOKvar)
+	{
+	    dinteger_t index = ae->e2->toInteger();
+	    VarExp *ve = (VarExp *)ae->e1;
+	    if (ve->type->ty == Tsarray && ve->type->next->ty != Tbit
+		&& !ve->var->isImportedSymbol())
+	    {
+		TypeSArray *ts = (TypeSArray *)ve->type;
+		dinteger_t dim = ts->dim->toInteger();
+		if (index < 0 || index >= dim)
+		    error("array index %jd is out of bounds [0..%jd]", index, dim);
+		e = new SymOffExp(loc, ve->var, index * ts->next->size());
+		e->type = type;
+		return e;
+	    }
+	}
+    }
+#endif
+    return this;
+}
+
+Expression *PtrExp::optimize(int result)
+{
+    //printf("PtrExp::optimize(result = x%x) %s\n", result, toChars());
+    e1 = e1->optimize(result);
+    // Convert *&ex to ex
+    if (e1->op == TOKaddress)
+    {	Expression *e;
+	Expression *ex;
+
+	ex = ((AddrExp *)e1)->e1;
+	if (type->equals(ex->type))
+	    e = ex;
+	else
+	{
+	    e = ex->copy();
+	    e->type = type;
+	}
+	return e;
+    }
+    // Constant fold *(&structliteral + offset)
+    if (e1->op == TOKadd)
+    {
+	Expression *e;
+	e = Ptr(type, e1);
+	if (e != EXP_CANT_INTERPRET)
+	    return e;
+    }
+
+    return this;
+}
+
+Expression *DotVarExp::optimize(int result)
+{
+    //printf("DotVarExp::optimize(result = x%x) %s\n", result, toChars());
+    e1 = e1->optimize(result);
+
+#if DMDV2
+    if (e1->op == TOKvar)
+    {	VarExp *ve = (VarExp *)e1;
+	VarDeclaration *v = ve->var->isVarDeclaration();
+	Expression *e = expandVar(result, v);
+	if (e && e->op == TOKstructliteral)
+	{   StructLiteralExp *sle = (StructLiteralExp *)e;
+	    VarDeclaration *vf = var->isVarDeclaration();
+	    if (vf)
+	    {
+		e = sle->getField(type, vf->offset);
+		if (e != EXP_CANT_INTERPRET)
+		    return e;
+	    }
+	}
+    }
+    else
+#endif
+    if (e1->op == TOKstructliteral)
+    {   StructLiteralExp *sle = (StructLiteralExp *)e1;
+	VarDeclaration *vf = var->isVarDeclaration();
+	if (vf)
+	{
+	    Expression *e = sle->getField(type, vf->offset);
+	    if (e != EXP_CANT_INTERPRET)
+		return e;
+	}
+    }
+
+    return this;
+}
+
+Expression *CallExp::optimize(int result)
+{   Expression *e = this;
+
+    e1 = e1->optimize(result);
+    if (e1->op == TOKvar && result & WANTinterpret)
+    {
+	FuncDeclaration *fd = ((VarExp *)e1)->var->isFuncDeclaration();
+	if (fd)
+	{
+	    Expression *eresult = fd->interpret(NULL, arguments);
+	    if (eresult && eresult != EXP_VOID_INTERPRET)
+		e = eresult;
+	    else if (result & WANTinterpret)
+		error("cannot evaluate %s at compile time", toChars());
+	}
+    }
+    return e;
+}
+
+
+Expression *CastExp::optimize(int result)
+{
+    //printf("CastExp::optimize(result = %d) %s\n", result, toChars());
+    //printf("from %s to %s\n", type->toChars(), to->toChars());
+    //printf("from %s\n", type->toChars());
+    //printf("e1->type %s\n", e1->type->toChars());
+    //printf("type = %p\n", type);
+    assert(type);
+    enum TOK op1 = e1->op;
+
+    e1 = e1->optimize(result);
+    if (result & WANTinterpret)
+	e1 = fromConstInitializer(e1);
+
+    if ((e1->op == TOKstring || e1->op == TOKarrayliteral) &&
+	(type->ty == Tpointer || type->ty == Tarray) &&
+	type->next->equals(e1->type->next)
+       )
+    {
+	// make a copy before adjusting type to avoid
+	// messing up the type of an existing initializer
+	e1 = e1->syntaxCopy();
+	e1->type = type;
+	return e1;
+    }
+    /* The first test here is to prevent infinite loops
+     */
+    if (op1 != TOKarrayliteral && e1->op == TOKarrayliteral)
+	return e1->castTo(NULL, to);
+    if (e1->op == TOKnull &&
+	(type->ty == Tpointer || type->ty == Tclass))
+    {
+	e1->type = type;
+	return e1;
+    }
+
+    if (result & WANTflags && type->ty == Tclass && e1->type->ty == Tclass)
+    {
+	// See if we can remove an unnecessary cast
+	ClassDeclaration *cdfrom;
+	ClassDeclaration *cdto;
+	int offset;
+
+	cdfrom = e1->type->isClassHandle();
+	cdto   = type->isClassHandle();
+	if (cdto->isBaseOf(cdfrom, &offset) && offset == 0)
+	{
+	    e1->type = type;
+	    return e1;
+	}
+    }
+
+    Expression *e;
+
+    if (e1->isConst())
+    {
+	if (e1->op == TOKsymoff)
+	{
+	    if (type->size() == e1->type->size() &&
+		type->toBasetype()->ty != Tsarray)
+	    {
+		e1->type = type;
+		return e1;
+	    }
+	    return this;
+	}
+	if (to->toBasetype()->ty == Tvoid)
+	    e = this;
+	else
+	    e = Cast(type, to, e1);
+    }
+    else
+	e = this;
+    return e;
+}
+
+Expression *BinExp::optimize(int result)
+{
+    //printf("BinExp::optimize(result = %d) %s\n", result, toChars());
+    e1 = e1->optimize(result);
+    e2 = e2->optimize(result);
+    if (op == TOKshlass || op == TOKshrass || op == TOKushrass)
+    {
+	if (e2->isConst() == 1)
+	{
+	    dinteger_t i2 = e2->toInteger();
+	    d_uns64 sz = e1->type->size() * 8;
+	    if (i2 < 0 || i2 > sz)
+	    {   error("shift assign by %jd is outside the range 0..%zu", i2, sz);
+		e2 = new IntegerExp(0);
+	    }
+	}
+    }
+    return this;
+}
+
+Expression *AddExp::optimize(int result)
+{   Expression *e;
+
+    //printf("AddExp::optimize(%s)\n", toChars());
+    e1 = e1->optimize(result);
+    e2 = e2->optimize(result);
+    if (e1->isConst() && e2->isConst())
+    {
+	if (e1->op == TOKsymoff && e2->op == TOKsymoff)
+	    return this;
+	e = Add(type, e1, e2);
+    }
+    else
+	e = this;
+    return e;
+}
+
+Expression *MinExp::optimize(int result)
+{   Expression *e;
+
+    e1 = e1->optimize(result);
+    e2 = e2->optimize(result);
+    if (e1->isConst() && e2->isConst())
+    {
+	if (e2->op == TOKsymoff)
+	    return this;
+	e = Min(type, e1, e2);
+    }
+    else
+	e = this;
+    return e;
+}
+
+Expression *MulExp::optimize(int result)
+{   Expression *e;
+
+    //printf("MulExp::optimize(result = %d) %s\n", result, toChars());
+    e1 = e1->optimize(result);
+    e2 = e2->optimize(result);
+    if (e1->isConst() == 1 && e2->isConst() == 1)
+    {
+	e = Mul(type, e1, e2);
+    }
+    else
+	e = this;
+    return e;
+}
+
+Expression *DivExp::optimize(int result)
+{   Expression *e;
+
+    //printf("DivExp::optimize(%s)\n", toChars());
+    e1 = e1->optimize(result);
+    e2 = e2->optimize(result);
+    if (e1->isConst() == 1 && e2->isConst() == 1)
+    {
+	e = Div(type, e1, e2);
+    }
+    else
+	e = this;
+    return e;
+}
+
+Expression *ModExp::optimize(int result)
+{   Expression *e;
+
+    e1 = e1->optimize(result);
+    e2 = e2->optimize(result);
+    if (e1->isConst() == 1 && e2->isConst() == 1)
+    {
+	e = Mod(type, e1, e2);
+    }
+    else
+	e = this;
+    return e;
+}
+
+Expression *shift_optimize(int result, BinExp *e, Expression *(*shift)(Type *, Expression *, Expression *))
+{   Expression *ex = e;
+
+    e->e1 = e->e1->optimize(result);
+    e->e2 = e->e2->optimize(result);
+    if (e->e2->isConst() == 1)
+    {
+	dinteger_t i2 = e->e2->toInteger();
+	d_uns64 sz = e->e1->type->size() * 8;
+	if (i2 < 0 || i2 > sz)
+	{   e->error("shift by %jd is outside the range 0..%zu", i2, sz);
+	    e->e2 = new IntegerExp(0);
+	}
+	if (e->e1->isConst() == 1)
+	    ex = (*shift)(e->type, e->e1, e->e2);
+    }
+    return ex;
+}
+
+Expression *ShlExp::optimize(int result)
+{
+    //printf("ShlExp::optimize(result = %d) %s\n", result, toChars());
+    return shift_optimize(result, this, Shl);
+}
+
+Expression *ShrExp::optimize(int result)
+{
+    //printf("ShrExp::optimize(result = %d) %s\n", result, toChars());
+    return shift_optimize(result, this, Shr);
+}
+
+Expression *UshrExp::optimize(int result)
+{
+    //printf("UshrExp::optimize(result = %d) %s\n", result, toChars());
+    return shift_optimize(result, this, Ushr);
+}
+
+Expression *AndExp::optimize(int result)
+{   Expression *e;
+
+    e1 = e1->optimize(result);
+    e2 = e2->optimize(result);
+    if (e1->isConst() == 1 && e2->isConst() == 1)
+	e = And(type, e1, e2);
+    else
+	e = this;
+    return e;
+}
+
+Expression *OrExp::optimize(int result)
+{   Expression *e;
+
+    e1 = e1->optimize(result);
+    e2 = e2->optimize(result);
+    if (e1->isConst() == 1 && e2->isConst() == 1)
+	e = Or(type, e1, e2);
+    else
+	e = this;
+    return e;
+}
+
+Expression *XorExp::optimize(int result)
+{   Expression *e;
+
+    e1 = e1->optimize(result);
+    e2 = e2->optimize(result);
+    if (e1->isConst() == 1 && e2->isConst() == 1)
+	e = Xor(type, e1, e2);
+    else
+	e = this;
+    return e;
+}
+
+Expression *CommaExp::optimize(int result)
+{   Expression *e;
+
+    //printf("CommaExp::optimize(result = %d) %s\n", result, toChars());
+    e1 = e1->optimize(result & WANTinterpret);
+    e2 = e2->optimize(result);
+    if (!e1 || e1->op == TOKint64 || e1->op == TOKfloat64 || !e1->checkSideEffect(2))
+    {
+	e = e2;
+	if (e)
+	    e->type = type;
+    }
+    else
+	e = this;
+    //printf("-CommaExp::optimize(result = %d) %s\n", result, e->toChars());
+    return e;
+}
+
+Expression *ArrayLengthExp::optimize(int result)
+{   Expression *e;
+
+    //printf("ArrayLengthExp::optimize(result = %d) %s\n", result, toChars());
+    e1 = e1->optimize(WANTvalue | (result & WANTinterpret));
+    e = this;
+    if (e1->op == TOKstring || e1->op == TOKarrayliteral || e1->op == TOKassocarrayliteral)
+    {
+	e = ArrayLength(type, e1);
+    }
+    return e;
+}
+
+Expression *EqualExp::optimize(int result)
+{   Expression *e;
+
+    //printf("EqualExp::optimize(result = %x) %s\n", result, toChars());
+    e1 = e1->optimize(WANTvalue | (result & WANTinterpret));
+    e2 = e2->optimize(WANTvalue | (result & WANTinterpret));
+    e = this;
+
+    Expression *e1 = fromConstInitializer(this->e1);
+    Expression *e2 = fromConstInitializer(this->e2);
+
+    e = Equal(op, type, e1, e2);
+    if (e == EXP_CANT_INTERPRET)
+	e = this;
+    return e;
+}
+
+Expression *IdentityExp::optimize(int result)
+{   Expression *e;
+
+    //printf("IdentityExp::optimize(result = %d) %s\n", result, toChars());
+    e1 = e1->optimize(WANTvalue | (result & WANTinterpret));
+    e2 = e2->optimize(WANTvalue | (result & WANTinterpret));
+    e = this;
+
+    if (this->e1->isConst() && this->e2->isConst())
+    {
+	e = Identity(op, type, this->e1, this->e2);
+    }
+    return e;
+}
+
+Expression *IndexExp::optimize(int result)
+{   Expression *e;
+
+    //printf("IndexExp::optimize(result = %d) %s\n", result, toChars());
+    Expression *e1 = this->e1->optimize(WANTvalue | (result & WANTinterpret));
+    if (result & WANTinterpret)
+	e1 = fromConstInitializer(e1);
+    e2 = e2->optimize(WANTvalue | (result & WANTinterpret));
+    e = Index(type, e1, e2);
+    if (e == EXP_CANT_INTERPRET)
+	e = this;
+    return e;
+}
+
+Expression *SliceExp::optimize(int result)
+{   Expression *e;
+
+    //printf("SliceExp::optimize(result = %d) %s\n", result, toChars());
+    e = this;
+    e1 = e1->optimize(WANTvalue | (result & WANTinterpret));
+    if (!lwr)
+    {	if (e1->op == TOKstring)
+	{   // Convert slice of string literal into dynamic array
+	    Type *t = e1->type->toBasetype();
+	    if (t->next)
+		e = e1->castTo(NULL, t->next->arrayOf());
+	}
+	return e;
+    }
+    if (result & WANTinterpret)
+	e1 = fromConstInitializer(e1);
+    lwr = lwr->optimize(WANTvalue | (result & WANTinterpret));
+    upr = upr->optimize(WANTvalue | (result & WANTinterpret));
+    e = Slice(type, e1, lwr, upr);
+    if (e == EXP_CANT_INTERPRET)
+	e = this;
+    return e;
+}
+
+Expression *AndAndExp::optimize(int result)
+{   Expression *e;
+
+    //printf("AndAndExp::optimize(%d) %s\n", result, toChars());
+    e1 = e1->optimize(WANTflags | (result & WANTinterpret));
+    e = this;
+    if (e1->isBool(FALSE))
+    {
+	e = new CommaExp(loc, e1, new IntegerExp(loc, 0, type));
+	e->type = type;
+	e = e->optimize(result);
+    }
+    else
+    {
+	e2 = e2->optimize(WANTflags | (result & WANTinterpret));
+	if (result && e2->type->toBasetype()->ty == Tvoid && !global.errors)
+	    error("void has no value");
+	if (e1->isConst())
+	{
+	    if (e2->isConst())
+	    {	int n1 = e1->isBool(1);
+		int n2 = e2->isBool(1);
+
+		e = new IntegerExp(loc, n1 && n2, type);
+	    }
+	    else if (e1->isBool(TRUE))
+		e = new BoolExp(loc, e2, type);
+	}
+    }
+    return e;
+}
+
+Expression *OrOrExp::optimize(int result)
+{   Expression *e;
+
+    e1 = e1->optimize(WANTflags | (result & WANTinterpret));
+    e = this;
+    if (e1->isBool(TRUE))
+    {	// Replace with (e1, 1)
+	e = new CommaExp(loc, e1, new IntegerExp(loc, 1, type));
+	e->type = type;
+	e = e->optimize(result);
+    }
+    else
+    {
+	e2 = e2->optimize(WANTflags | (result & WANTinterpret));
+	if (result && e2->type->toBasetype()->ty == Tvoid && !global.errors)
+	    error("void has no value");
+	if (e1->isConst())
+	{
+	    if (e2->isConst())
+	    {	int n1 = e1->isBool(1);
+		int n2 = e2->isBool(1);
+
+		e = new IntegerExp(loc, n1 || n2, type);
+	    }
+	    else if (e1->isBool(FALSE))
+		e = new BoolExp(loc, e2, type);
+	}
+    }
+    return e;
+}
+
+Expression *CmpExp::optimize(int result)
+{   Expression *e;
+
+    //printf("CmpExp::optimize() %s\n", toChars());
+    e1 = e1->optimize(result);
+    e2 = e2->optimize(result);
+    if (e1->isConst() == 1 && e2->isConst() == 1)
+    {
+	e = Cmp(op, type, this->e1, this->e2);
+    }
+    else
+	e = this;
+    return e;
+}
+
+Expression *CatExp::optimize(int result)
+{   Expression *e;
+
+    //printf("CatExp::optimize(%d) %s\n", result, toChars());
+    e1 = e1->optimize(result);
+    e2 = e2->optimize(result);
+    e = Cat(type, e1, e2);
+    if (e == EXP_CANT_INTERPRET)
+	e = this;
+    return e;
+}
+
+
+Expression *CondExp::optimize(int result)
+{   Expression *e;
+
+    econd = econd->optimize(WANTflags | (result & WANTinterpret));
+    if (econd->isBool(TRUE))
+	e = e1->optimize(result);
+    else if (econd->isBool(FALSE))
+	e = e2->optimize(result);
+    else
+    {	e1 = e1->optimize(result);
+	e2 = e2->optimize(result);
+	e = this;
+    }
+    return e;
+}
+
+
--- a/dmd/parse.c	Fri Apr 03 17:02:52 2009 +0200
+++ b/dmd/parse.c	Fri Apr 03 17:59:34 2009 +0200
@@ -1,6 +1,6 @@
 
 // Compiler implementation of the D programming language
-// Copyright (c) 1999-2008 by Digital Mars
+// Copyright (c) 1999-2009 by Digital Mars
 // All Rights Reserved
 // written by Walter Bright
 // http://www.digitalmars.com
@@ -32,6 +32,9 @@
 #include "enum.h"
 #include "id.h"
 #include "version.h"
+#if DMDV2
+#include "aliasthis.h"
+#endif
 
 // How multiple declarations are parsed.
 // If 1, treat as C.
@@ -75,6 +78,25 @@
 	unsigned char *comment = token.blockComment;
 
 	nextToken();
+#if DMDV2
+	if (token.value == TOKlparen)
+	{
+	    nextToken();
+	    if (token.value != TOKidentifier)
+	    {	error("module (system) identifier expected");
+		goto Lerr;
+	    }
+	    Identifier *id = token.ident;
+
+	    if (id == Id::system)
+		safe = TRUE;
+	    else
+		error("(safe) expected, not %s", id->toChars());
+	    nextToken();
+	    check(TOKrparen);
+	}
+#endif
+
 	if (token.value != TOKidentifier)
 	{   error("Identifier expected following module");
 	    goto Lerr;
@@ -259,6 +281,13 @@
 	    case TOKabstract:	  stc = STCabstract;	 goto Lstc;
 	    case TOKsynchronized: stc = STCsynchronized; goto Lstc;
 	    case TOKdeprecated:   stc = STCdeprecated;	 goto Lstc;
+#if DMDV2
+	    case TOKnothrow:      stc = STCnothrow;	 goto Lstc;
+	    case TOKpure:         stc = STCpure;	 goto Lstc;
+	    case TOKref:          stc = STCref;          goto Lstc;
+	    case TOKtls:          stc = STCtls;		 goto Lstc;
+	    //case TOKmanifest:	  stc = STCmanifest;	 goto Lstc;
+#endif
 
 	    Lstc:
 		nextToken();
@@ -342,6 +371,16 @@
 
 	    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;
@@ -802,7 +841,7 @@
 
 /*****************************************
  * Parse an invariant definition:
- *	invariant { body }
+ *	invariant() { body }
  * Current token is 'invariant'.
  */
 
@@ -987,7 +1026,7 @@
 EnumDeclaration *Parser::parseEnum()
 {   EnumDeclaration *e;
     Identifier *id;
-    Type *t;
+    Type *memtype;
     Loc loc = this->loc;
 
     //printf("Parser::parseEnum()\n");
@@ -1002,12 +1041,12 @@
     if (token.value == TOKcolon)
     {
 	nextToken();
-	t = parseBasicType();
+	memtype = parseBasicType();
     }
     else
-	t = NULL;
-
-    e = new EnumDeclaration(loc, id, t);
+	memtype = NULL;
+
+    e = new EnumDeclaration(loc, id, memtype);
     if (token.value == TOKsemicolon && id)
  	nextToken();
     else if (token.value == TOKlcurly)
@@ -1058,6 +1097,10 @@
     return e;
 }
 
+/********************************
+ * Parse struct, union, interface, class.
+ */
+
 Dsymbol *Parser::parseAggregate()
 {   AggregateDeclaration *a = NULL;
     int anon = 0;
@@ -1160,7 +1203,7 @@
 	// Wrap a template around the aggregate declaration
 	decldefs = new Array();
 	decldefs->push(a);
-	tempdecl = new TemplateDeclaration(loc, id, tpl, decldefs);
+	tempdecl = new TemplateDeclaration(loc, id, tpl, NULL, decldefs);
 	return tempdecl;
     }
 
@@ -1265,7 +1308,7 @@
 	nextToken();
     }
 
-    tempdecl = new TemplateDeclaration(loc, id, tpl, decldefs);
+    tempdecl = new TemplateDeclaration(loc, id, tpl, NULL, decldefs);
     return tempdecl;
 
 Lerr:
@@ -1650,6 +1693,60 @@
     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;
@@ -1889,6 +1986,7 @@
 	    break;
     }
 
+    // parse DeclaratorSuffixes
     while (1)
     {
 	switch (token.value)
@@ -1924,6 +2022,7 @@
 		    ta = new TypeSArray(t, e);
 		    check(TOKrbracket);
 		}
+
 		/* Insert ta into
 		 *   ts -> ... -> t
 		 * so that
@@ -1986,7 +2085,7 @@
     Type *tfirst;
     Identifier *ident;
     Array *a;
-    enum TOK tok;
+    enum TOK tok = TOKreserved;
     unsigned char *comment = token.blockComment;
     enum LINK link = linkage;
 
@@ -2018,6 +2117,13 @@
 	    case TOKabstract:	stc = STCabstract;	 goto L1;
 	    case TOKsynchronized: stc = STCsynchronized; goto L1;
 	    case TOKdeprecated: stc = STCdeprecated;	 goto L1;
+#if DMDV2
+	    case TOKnothrow:    stc = STCnothrow;	 goto L1;
+	    case TOKpure:       stc = STCpure;		 goto L1;
+	    case TOKref:        stc = STCref;            goto L1;
+	    case TOKtls:        stc = STCtls;		 goto L1;
+	    case TOKenum:	stc = STCmanifest;	 goto L1;
+#endif
 	    L1:
 		if (storage_class & stc)
 		    error("redundant storage class '%s'", token.toChars());
@@ -2108,9 +2214,8 @@
 
 	if (tok == TOKtypedef || tok == TOKalias)
 	{   Declaration *v;
-	    Initializer *init;
-
-	    init = NULL;
+	    Initializer *init = NULL;
+
 	    if (token.value == TOKassign)
 	    {
 		nextToken();
@@ -2150,13 +2255,12 @@
 	    }
 	}
 	else if (t->ty == Tfunction)
-	{   FuncDeclaration *f;
-	    Dsymbol *s;
-
-	    f = new FuncDeclaration(loc, 0, ident, storage_class, t);
+	{   FuncDeclaration *f =
+		new FuncDeclaration(loc, 0, ident, storage_class, t);
 	    addComment(f, comment);
 	    parseContracts(f);
 	    addComment(f, NULL);
+	    Dsymbol *s;
 	    if (link == linkage)
 	    {
 		s = f;
@@ -2174,23 +2278,22 @@
 		// Wrap a template around the aggregate declaration
 		decldefs = new Array();
 		decldefs->push(s);
-		tempdecl = new TemplateDeclaration(loc, s->ident, tpl, decldefs);
+		tempdecl = new TemplateDeclaration(loc, s->ident, tpl, NULL, decldefs);
 		s = tempdecl;
 	    }
 	    addComment(s, comment);
 	    a->push(s);
 	}
 	else
-	{   VarDeclaration *v;
-	    Initializer *init;
-
-	    init = NULL;
+	{
+	    Initializer *init = NULL;
 	    if (token.value == TOKassign)
 	    {
 		nextToken();
 		init = parseInitializer();
 	    }
-	    v = new VarDeclaration(loc, t, ident, init);
+
+	    VarDeclaration *v = new VarDeclaration(loc, t, ident, init);
 	    v->storage_class = storage_class;
 	    if (link == linkage)
 		a->push(v);
@@ -2363,6 +2466,7 @@
 }
 
 /*****************************************
+ * Parse initializer for variable declaration.
  */
 
 Initializer *Parser::parseInitializer()
@@ -2620,13 +2724,14 @@
     switch (token.value)
     {
 	case TOKidentifier:
-	    // Need to look ahead to see if it is a declaration, label, or expression
+	    /* 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;
-
-		ident = token.ident;
+
+		Identifier *ident = token.ident;
 		nextToken();
 		nextToken();
 		s = parseStatement(PSsemi);
@@ -2718,6 +2823,10 @@
 	case TOKextern:
 	case TOKfinal:
 	case TOKinvariant:
+#if DMDV2
+	case TOKimmutable:
+	case TOKshared:
+#endif
 //	case TOKtypeof:
 	Ldeclaration:
 	{   Array *a;
@@ -2733,7 +2842,7 @@
 		    s = new DeclarationStatement(loc, d);
 		    as->push(s);
 		}
-		s = new CompoundStatement(loc, as);
+		s = new CompoundDeclarationStatement(loc, as);
 	    }
 	    else if (a->dim == 1)
 	    {
@@ -3443,7 +3552,7 @@
     nextToken();
 }
 
-void Parser::check(enum TOK value, char *string)
+void Parser::check(enum TOK value, const char *string)
 {
     if (token.value != value)
 	error("found '%s' when expecting '%s' following '%s'",
@@ -3461,6 +3570,7 @@
 
 int Parser::isDeclaration(Token *t, int needId, enum TOK endtok, Token **pt)
 {
+    //printf("isDeclaration(needId = %d)\n", needId);
     int haveId = 0;
 
 #if DMDV2
@@ -3551,9 +3661,11 @@
 	    goto Lfalse;
     }
     *pt = t;
+    //printf("is\n");
     return TRUE;
 
 Lfalse:
+    //printf("is not\n");
     return FALSE;
 }
 
@@ -3678,6 +3790,25 @@
 		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
@@ -4203,6 +4334,12 @@
 			 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))
--- a/dmd/parse.h	Fri Apr 03 17:02:52 2009 +0200
+++ b/dmd/parse.h	Fri Apr 03 17:59:34 2009 +0200
@@ -1,6 +1,6 @@
 
 // Compiler implementation of the D programming language
-// Copyright (c) 1999-2008 by Digital Mars
+// Copyright (c) 1999-2009 by Digital Mars
 // All Rights Reserved
 // written by Walter Bright
 // http://www.digitalmars.com
@@ -100,7 +100,7 @@
     Initializer *parseInitializer();
     void check(Loc loc, enum TOK value);
     void check(enum TOK value);
-    void check(enum TOK value, char *string);
+    void check(enum TOK value, const char *string);
     int isDeclaration(Token *t, int needId, enum TOK endtok, Token **pt);
     int isBasicType(Token **pt);
     int isDeclarator(Token **pt, int *haveId, enum TOK endtok);
--- a/dmd/root/array.c	Fri Apr 03 17:02:52 2009 +0200
+++ b/dmd/root/array.c	Fri Apr 03 17:59:34 2009 +0200
@@ -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
 // www.digitalmars.com
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/root/async.c	Fri Apr 03 17:59:34 2009 +0200
@@ -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/dmd/root/async.h	Fri Apr 03 17:59:34 2009 +0200
@@ -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/dmd/root/port.c	Fri Apr 03 17:59:34 2009 +0200
@@ -0,0 +1,754 @@
+
+// Copyright (c) 1999-2009 by Digital Mars
+// All Rights Reserved
+// written by Walter Bright
+// http://www.digitalmars.com
+
+#include "port.h"
+
+#if __DMC__
+#include <math.h>
+#include <float.h>
+#include <fp.h>
+#include <time.h>
+#include <stdlib.h>
+#include <string.h>
+
+double Port::nan = NAN;
+double Port::infinity = INFINITY;
+double Port::dbl_max = DBL_MAX;
+double Port::dbl_min = DBL_MIN;
+
+int Port::isNan(double r)
+{
+    return ::isnan(r);
+}
+
+int Port::isNan(long double r)
+{
+    return ::isnan(r);
+}
+
+int Port::isSignallingNan(double r)
+{
+    /* A signalling NaN is a NaN with 0 as the most significant bit of
+     * its significand, which is bit 51 of 0..63 for 64 bit doubles.
+     */
+    return isNan(r) && !((((unsigned char*)&r)[6]) & 8);
+}
+
+int Port::isSignallingNan(long double r)
+{
+    /* A signalling NaN is a NaN with 0 as the most significant bit of
+     * its significand, which is bit 62 of 0..79 for 80 bit reals.
+     */
+    return isNan(r) && !((((unsigned char*)&r)[7]) & 0x40);
+}
+
+int Port::isFinite(double r)
+{
+    return ::isfinite(r);
+}
+
+int Port::isInfinity(double r)
+{
+    return (::fpclassify(r) == FP_INFINITE);
+}
+
+int Port::Signbit(double r)
+{
+    return ::signbit(r);
+}
+
+double Port::floor(double d)
+{
+    return ::floor(d);
+}
+
+double Port::pow(double x, double y)
+{
+    return ::pow(x, y);
+}
+
+unsigned long long Port::strtoull(const char *p, char **pend, int base)
+{
+    return ::strtoull(p, pend, base);
+}
+
+char *Port::ull_to_string(char *buffer, ulonglong ull)
+{
+    sprintf(buffer, "%llu", ull);
+    return buffer;
+}
+
+wchar_t *Port::ull_to_string(wchar_t *buffer, ulonglong ull)
+{
+    swprintf(buffer, sizeof(ulonglong) * 3 + 1, L"%llu", ull);
+    return buffer;
+}
+
+double Port::ull_to_double(ulonglong ull)
+{
+    return (double) ull;
+}
+
+const char *Port::list_separator()
+{
+    // LOCALE_SLIST for Windows
+    return ",";
+}
+
+const wchar_t *Port::wlist_separator()
+{
+    // LOCALE_SLIST for Windows
+    return L",";
+}
+
+char *Port::strupr(char *s)
+{
+    return ::strupr(s);
+}
+
+#endif
+
+#if _MSC_VER
+
+// Disable useless warnings about unreferenced functions
+#pragma warning (disable : 4514)
+
+#include <math.h>
+#include <float.h>
+#include <time.h>
+#include <errno.h>
+#include <string.h>
+#include <ctype.h>
+#include <stdlib.h>
+
+static unsigned long nanarray[2]= { 0xFFFFFFFF, 0x7FFFFFFF };
+//static unsigned long nanarray[2] = {0,0x7FF80000 };
+double Port::nan = (*(double *)nanarray);
+
+//static unsigned long infinityarray[2] = {0,0x7FF00000 };
+static double zero = 0;
+double Port::infinity = 1 / zero;
+
+double Port::dbl_max = DBL_MAX;
+double Port::dbl_min = DBL_MIN;
+
+struct PortInitializer
+{
+    PortInitializer();
+};
+
+static PortInitializer portinitializer;
+
+PortInitializer::PortInitializer()
+{
+    Port::infinity = std::numeric_limits<long double>::infinity();
+}
+
+int Port::isNan(double r)
+{
+    return ::_isnan(r);
+}
+
+int Port::isNan(long double r)
+{
+    return ::_isnan(r);
+}
+
+int Port::isSignallingNan(double r)
+{
+    /* A signalling NaN is a NaN with 0 as the most significant bit of
+     * its significand, which is bit 51 of 0..63 for 64 bit doubles.
+     */
+    return isNan(r) && !((((unsigned char*)&r)[6]) & 8);
+}
+
+int Port::isSignallingNan(long double r)
+{
+    /* MSVC doesn't have 80 bit long doubles
+     */
+    return isSignallingNan((double) r);
+}
+
+int Port::isFinite(double r)
+{
+    return ::_finite(r);
+}
+
+int Port::isInfinity(double r)
+{
+    return (::_fpclass(r) & (_FPCLASS_NINF | _FPCLASS_PINF));
+}
+
+int Port::Signbit(double r)
+{
+    return (long)(((long *)&(r))[1] & 0x80000000);
+}
+
+double Port::floor(double d)
+{
+    return ::floor(d);
+}
+
+double Port::pow(double x, double y)
+{
+    if (y == 0)
+	return 1;		// even if x is NAN
+    return ::pow(x, y);
+}
+
+unsigned _int64 Port::strtoull(const char *p, char **pend, int base)
+{
+    unsigned _int64 number = 0;
+    int c;
+    int error;
+    #define ULLONG_MAX ((unsigned _int64)~0I64)
+
+    while (isspace(*p))		/* skip leading white space	*/
+	p++;
+    if (*p == '+')
+	p++;
+    switch (base)
+    {   case 0:
+	    base = 10;		/* assume decimal base		*/
+	    if (*p == '0')
+	    {   base = 8;	/* could be octal		*/
+		    p++;
+		    switch (*p)
+		    {   case 'x':
+			case 'X':
+			    base = 16;	/* hex			*/
+			    p++;
+			    break;
+#if BINARY
+			case 'b':
+			case 'B':
+			    base = 2;	/* binary		*/
+			    p++;
+			    break;
+#endif
+		    }
+	    }
+	    break;
+	case 16:			/* skip over '0x' and '0X'	*/
+	    if (*p == '0' && (p[1] == 'x' || p[1] == 'X'))
+		    p += 2;
+	    break;
+#if BINARY
+	case 2:			/* skip over '0b' and '0B'	*/
+	    if (*p == '0' && (p[1] == 'b' || p[1] == 'B'))
+		    p += 2;
+	    break;
+#endif
+    }
+    error = 0;
+    for (;;)
+    {   c = *p;
+	if (isdigit(c))
+		c -= '0';
+	else if (isalpha(c))
+		c = (c & ~0x20) - ('A' - 10);
+	else			/* unrecognized character	*/
+		break;
+	if (c >= base)		/* not in number base		*/
+		break;
+	if ((ULLONG_MAX - c) / base < number)
+		error = 1;
+	number = number * base + c;
+	p++;
+    }
+    if (pend)
+	*pend = (char *)p;
+    if (error)
+    {   number = ULLONG_MAX;
+	errno = ERANGE;
+    }
+    return number;
+}
+
+char *Port::ull_to_string(char *buffer, ulonglong ull)
+{
+    _ui64toa(ull, buffer, 10);
+    return buffer;
+}
+
+wchar_t *Port::ull_to_string(wchar_t *buffer, ulonglong ull)
+{
+    _ui64tow(ull, buffer, 10);
+    return buffer;
+}
+
+double Port::ull_to_double(ulonglong ull)
+{   double d;
+
+    if ((__int64) ull < 0)
+    {
+	// MSVC doesn't implement the conversion
+	d = (double) (__int64)(ull -  0x8000000000000000i64);
+	d += (double)(signed __int64)(0x7FFFFFFFFFFFFFFFi64) + 1.0;
+    }
+    else
+	d = (double)(__int64)ull;
+    return d;
+}
+
+const char *Port::list_separator()
+{
+    // LOCALE_SLIST for Windows
+    return ",";
+}
+
+const wchar_t *Port::wlist_separator()
+{
+    // LOCALE_SLIST for Windows
+    return L",";
+}
+
+char *Port::strupr(char *s)
+{
+    return ::strupr(s);
+}
+
+#endif
+
+#if linux || __APPLE__ || __FreeBSD__
+
+#include <math.h>
+#if linux
+#include <bits/nan.h>
+#include <bits/mathdef.h>
+#endif
+#include <time.h>
+#include <sys/time.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+
+static double zero = 0;
+double Port::nan = NAN;
+double Port::infinity = 1 / zero;
+double Port::dbl_max = 1.7976931348623157e308;
+double Port::dbl_min = 5e-324;
+
+struct PortInitializer
+{
+    PortInitializer();
+};
+
+static PortInitializer portinitializer;
+
+PortInitializer::PortInitializer()
+{
+    // gcc nan's have the sign bit set by default, so turn it off
+    // Need the volatile to prevent gcc from doing incorrect
+    // constant folding.
+    volatile long double foo;
+    foo = NAN;
+    if (signbit(foo))	// signbit sometimes, not always, set
+	foo = -foo;	// turn off sign bit
+    Port::nan = foo;
+}
+
+#undef isnan
+int Port::isNan(double r)
+{
+#if __APPLE__
+    return __inline_isnan(r);
+#else
+    return ::isnan(r);
+#endif
+}
+
+int Port::isNan(long double r)
+{
+#if __APPLE__
+    return __inline_isnan(r);
+#else
+    return ::isnan(r);
+#endif
+}
+
+int Port::isSignallingNan(double r)
+{
+    /* A signalling NaN is a NaN with 0 as the most significant bit of
+     * its significand, which is bit 51 of 0..63 for 64 bit doubles.
+     */
+    return isNan(r) && !((((unsigned char*)&r)[6]) & 8);
+}
+
+int Port::isSignallingNan(long double r)
+{
+    /* A signalling NaN is a NaN with 0 as the most significant bit of
+     * its significand, which is bit 62 of 0..79 for 80 bit reals.
+     */
+    return isNan(r) && !((((unsigned char*)&r)[7]) & 0x40);
+}
+
+#undef isfinite
+int Port::isFinite(double r)
+{
+    return ::finite(r);
+}
+
+#undef isinf
+int Port::isInfinity(double r)
+{
+#if __APPLE__
+    return fpclassify(r) == FP_INFINITE;
+#else
+    return ::isinf(r);
+#endif
+}
+
+#undef signbit
+int Port::Signbit(double r)
+{
+    return (long)(((long *)&r)[1] & 0x80000000);
+}
+
+double Port::floor(double d)
+{
+    return ::floor(d);
+}
+
+double Port::pow(double x, double y)
+{
+    return ::pow(x, y);
+}
+
+unsigned long long Port::strtoull(const char *p, char **pend, int base)
+{
+    return ::strtoull(p, pend, base);
+}
+
+char *Port::ull_to_string(char *buffer, ulonglong ull)
+{
+    sprintf(buffer, "%llu", ull);
+    return buffer;
+}
+
+wchar_t *Port::ull_to_string(wchar_t *buffer, ulonglong ull)
+{
+    swprintf(buffer, sizeof(ulonglong) * 3 + 1, L"%llu", ull);
+    return buffer;
+}
+
+double Port::ull_to_double(ulonglong ull)
+{
+    return (double) ull;
+}
+
+const char *Port::list_separator()
+{
+    return ",";
+}
+
+const wchar_t *Port::wlist_separator()
+{
+    return L",";
+}
+
+char *Port::strupr(char *s)
+{
+    char *t = s;
+    
+    while (*s)
+    {
+	*s = toupper(*s);
+	s++;
+    }
+
+    return t;
+}
+
+#endif
+
+#if defined (__SVR4) && defined (__sun)
+
+#define __C99FEATURES__ 1	// Needed on Solaris for NaN and more
+#include <math.h>
+#include <time.h>
+#include <sys/time.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+
+static double zero = 0;
+double Port::nan = NAN;
+double Port::infinity = 1 / zero;
+double Port::dbl_max = 1.7976931348623157e308;
+double Port::dbl_min = 5e-324;
+
+struct PortInitializer
+{
+    PortInitializer();
+};
+
+static PortInitializer portinitializer;
+
+PortInitializer::PortInitializer()
+{
+    // gcc nan's have the sign bit set by default, so turn it off
+    // Need the volatile to prevent gcc from doing incorrect
+    // constant folding.
+    volatile long double foo;
+    foo = NAN;
+    if (signbit(foo))	// signbit sometimes, not always, set
+	foo = -foo;	// turn off sign bit
+    Port::nan = foo;
+}
+
+#undef isnan
+int Port::isNan(double r)
+{
+#if __APPLE__
+    return __inline_isnan(r);
+#else
+    return ::isnan(r);
+#endif
+}
+
+int Port::isNan(long double r)
+{
+#if __APPLE__
+    return __inline_isnan(r);
+#else
+    return ::isnan(r);
+#endif
+}
+
+int Port::isSignallingNan(double r)
+{
+    /* A signalling NaN is a NaN with 0 as the most significant bit of
+     * its significand, which is bit 51 of 0..63 for 64 bit doubles.
+     */
+    return isNan(r) && !((((unsigned char*)&r)[6]) & 8);
+}
+
+int Port::isSignallingNan(long double r)
+{
+    /* A signalling NaN is a NaN with 0 as the most significant bit of
+     * its significand, which is bit 62 of 0..79 for 80 bit reals.
+     */
+    return isNan(r) && !((((unsigned char*)&r)[7]) & 0x40);
+}
+
+#undef isfinite
+int Port::isFinite(double r)
+{
+    return ::finite(r);
+}
+
+#undef isinf
+int Port::isInfinity(double r)
+{
+    return ::isinf(r);
+}
+
+#undef signbit
+int Port::Signbit(double r)
+{
+    return (long)(((long *)&r)[1] & 0x80000000);
+}
+
+double Port::floor(double d)
+{
+    return ::floor(d);
+}
+
+double Port::pow(double x, double y)
+{
+    return ::pow(x, y);
+}
+
+unsigned long long Port::strtoull(const char *p, char **pend, int base)
+{
+    return ::strtoull(p, pend, base);
+}
+
+char *Port::ull_to_string(char *buffer, ulonglong ull)
+{
+    sprintf(buffer, "%llu", ull);
+    return buffer;
+}
+
+wchar_t *Port::ull_to_string(wchar_t *buffer, ulonglong ull)
+{
+    swprintf(buffer, sizeof(ulonglong) * 3 + 1, L"%llu", ull);
+    return buffer;
+}
+
+double Port::ull_to_double(ulonglong ull)
+{
+    return (double) ull;
+}
+
+const char *Port::list_separator()
+{
+    return ",";
+}
+
+const wchar_t *Port::wlist_separator()
+{
+    return L",";
+}
+
+char *Port::strupr(char *s)
+{
+    char *t = s;
+    
+    while (*s)
+    {
+	*s = toupper(*s);
+	s++;
+    }
+
+    return t;
+}
+
+#endif
+
+#if IN_GCC
+
+#include <math.h>
+#include <bits/nan.h>
+#include <bits/mathdef.h>
+#include <time.h>
+#include <sys/time.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+
+static double zero = 0;
+double Port::nan = NAN;
+double Port::infinity = 1 / zero;
+double Port::dbl_max = 1.7976931348623157e308;
+double Port::dbl_min = 5e-324;
+
+#include "d-gcc-real.h"
+extern "C" bool real_isnan (const real_t *);
+
+struct PortInitializer
+{
+    PortInitializer();
+};
+
+static PortInitializer portinitializer;
+
+PortInitializer::PortInitializer()
+{
+    Port::infinity = real_t::getinfinity();
+    Port::nan = real_t::getnan(real_t::LongDouble);
+}
+
+#undef isnan
+int Port::isNan(double r)
+{
+#if __APPLE__
+    return __inline_isnan(r);
+#else
+    return ::isnan(r);
+#endif
+}
+
+int Port::isNan(long double r)
+{
+    return real_isnan(&r);
+}
+
+int Port::isSignallingNan(double r)
+{
+    /* A signalling NaN is a NaN with 0 as the most significant bit of
+     * its significand, which is bit 51 of 0..63 for 64 bit doubles.
+     */
+    return isNan(r) && !((((unsigned char*)&r)[6]) & 8);
+}
+
+int Port::isSignallingNan(long double r)
+{
+    /* A signalling NaN is a NaN with 0 as the most significant bit of
+     * its significand, which is bit 62 of 0..79 for 80 bit reals.
+     */
+    return isNan(r) && !((((unsigned char*)&r)[7]) & 0x40);
+}
+
+#undef isfinite
+int Port::isFinite(double r)
+{
+    return ::finite(r);
+}
+
+#undef isinf
+int Port::isInfinity(double r)
+{
+    return ::isinf(r);
+}
+
+#undef signbit
+int Port::Signbit(double r)
+{
+    return (long)(((long *)&r)[1] & 0x80000000);
+}
+
+double Port::floor(double d)
+{
+    return ::floor(d);
+}
+
+double Port::pow(double x, double y)
+{
+    return ::pow(x, y);
+}
+
+unsigned long long Port::strtoull(const char *p, char **pend, int base)
+{
+    return ::strtoull(p, pend, base);
+}
+
+char *Port::ull_to_string(char *buffer, ulonglong ull)
+{
+    sprintf(buffer, "%llu", ull);
+    return buffer;
+}
+
+wchar_t *Port::ull_to_string(wchar_t *buffer, ulonglong ull)
+{
+    swprintf(buffer, L"%llu", ull);
+    return buffer;
+}
+
+double Port::ull_to_double(ulonglong ull)
+{
+    return (double) ull;
+}
+
+const char *Port::list_separator()
+{
+    return ",";
+}
+
+const wchar_t *Port::wlist_separator()
+{
+    return L",";
+}
+
+char *Port::strupr(char *s)
+{
+    char *t = s;
+    
+    while (*s)
+    {
+	*s = toupper(*s);
+	s++;
+    }
+
+    return t;
+}
+
+#endif
+
--- a/dmd/root/port.h	Fri Apr 03 17:02:52 2009 +0200
+++ b/dmd/root/port.h	Fri Apr 03 17:59:34 2009 +0200
@@ -1,8 +1,8 @@
 
-// Copyright (c) 1999-2002 by Digital Mars
+// Copyright (c) 1999-2009 by Digital Mars
 // All Rights Reserved
 // written by Walter Bright
-// www.digitalmars.com
+// http://www.digitalmars.com
 
 #ifndef PORT_H
 #define PORT_H
@@ -42,6 +42,11 @@
     #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);
@@ -58,8 +63,10 @@
     static double ull_to_double(ulonglong ull);
 
     // Get locale-dependent list separator
-    static char *list_separator();
-    static wchar_t *wlist_separator();
+    static const char *list_separator();
+    static const wchar_t *wlist_separator();
+
+    static char *strupr(char *);
 };
 
 #endif
--- a/dmd/root/root.c	Fri Apr 03 17:02:52 2009 +0200
+++ b/dmd/root/root.c	Fri Apr 03 17:59:34 2009 +0200
@@ -583,9 +583,17 @@
 	       return e + 1;
 
 #if _WIN32
+	    case '/':
 	    case '\\':
+		return e + 1;
 	    case ':':
-		return e + 1;
+		/* 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)
@@ -620,7 +628,7 @@
 	    n--;
 
 #if _WIN32
-	if (n[-1] == '\\')
+	if (n[-1] == '\\' || n[-1] == '/')
 	    n--;
 #endif
     }
@@ -822,8 +830,8 @@
 	    if (*p)
 	    {
 #if _WIN32
-		size_t len = strlen(p);
-		if (len > 2 && p[-1] == ':')
+		size_t len = strlen(path);
+		if (len > 2 && p[-1] == ':' && path + 2 == p)
 		{   mem.free(p);
 		    return;
 		}
--- a/dmd/scope.h	Fri Apr 03 17:02:52 2009 +0200
+++ b/dmd/scope.h	Fri Apr 03 17:59:34 2009 +0200
@@ -1,114 +1,120 @@
-
-// 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;
-enum LINK;
-enum PROT;
-
-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
-    Statement *enclosingScopeExit; // enclosing statement that wants to do something on scope exit
-    TemplateInstance *tinst;	// enclosing template instance
-    Statement *sbreak;		// enclosing statement that supports "break"
-    Statement *scontinue;	// enclosing statement that supports "continue"
-    ForeachStatement *fes;	// if nested function for ForeachStatement, this is it
-    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 /* __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 *enclosingFinally;	// enclosing try finally statement; set inside its finally block
+    Statement *enclosingScopeExit; // enclosing statement that wants to do something on scope exit
+    TemplateInstance *tinst;	// enclosing template instance
+    Statement *sbreak;		// enclosing statement that supports "break"
+    Statement *scontinue;	// enclosing statement that supports "continue"
+    ForeachStatement *fes;	// if nested function for ForeachStatement, this is it
+    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/dmd/statement.c	Fri Apr 03 17:02:52 2009 +0200
+++ b/dmd/statement.c	Fri Apr 03 17:59:34 2009 +0200
@@ -27,6 +27,7 @@
 #include "hdrgen.h"
 #include "parse.h"
 #include "template.h"
+#include "attrib.h"
 
 /******************************** Statement ***************************/
 
@@ -207,6 +208,10 @@
 	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;
@@ -576,6 +581,82 @@
 }
 
 
+/******************************** 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)
@@ -889,6 +970,7 @@
     return result;
 }
 
+
 int WhileStatement::comeFrom()
 {
     if (body)
@@ -974,6 +1056,7 @@
     return result;
 }
 
+
 int DoStatement::comeFrom()
 {
     if (body)
@@ -1103,6 +1186,7 @@
     return result;
 }
 
+
 int ForStatement::comeFrom()
 {
     //printf("ForStatement::comeFrom()\n");
@@ -1120,11 +1204,7 @@
     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
@@ -1249,17 +1329,16 @@
 		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());
-        }
+		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 |= STCconst;
@@ -1391,20 +1470,16 @@
 			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->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");
--- a/dmd/statement.h	Fri Apr 03 17:02:52 2009 +0200
+++ b/dmd/statement.h	Fri Apr 03 17:59:34 2009 +0200
@@ -1,882 +1,889 @@
-
-// Compiler implementation of the D programming language
-// Copyright (c) 1999-2008 by Digital Mars
-// All Rights Reserved
-// written by Walter Bright
-// http://www.digitalmars.com
-// License for redistribution is by either the Artistic License
-// in artistic.txt, or the GNU General Public License in gnu.txt.
-// See the included readme.txt for details.
-
-#ifndef DMD_STATEMENT_H
-#define DMD_STATEMENT_H
-
-#ifdef __DMC__
-#pragma once
-#endif /* __DMC__ */
-
-#include "root.h"
-
-#include "arraytypes.h"
-#include "dsymbol.h"
-#include "lexer.h"
-
-struct OutBuffer;
-struct Scope;
-struct Expression;
-struct LabelDsymbol;
-struct Identifier;
-struct IfStatement;
-struct DeclarationStatement;
-struct DefaultStatement;
-struct VarDeclaration;
-struct Condition;
-struct Module;
-struct Token;
-struct InlineCostState;
-struct InlineDoState;
-struct InlineScanState;
-struct ReturnStatement;
-struct CompoundStatement;
-struct Argument;
-struct StaticAssert;
-struct AsmStatement;
-struct AsmBlockStatement;
-struct GotoStatement;
-struct ScopeStatement;
-struct TryCatchStatement;
-struct TryFinallyStatement;
-struct HdrGenState;
-struct InterState;
-struct CaseStatement;
-struct LabelStatement;
-struct VolatileStatement;
-struct SynchronizedStatement;
-
-enum TOK;
-
-namespace llvm
-{
-    class Value;
-    class BasicBlock;
-    class ConstantInt;
-}
-
-// Back end
-struct IRState;
-struct Blockx;
-#if IN_LLVM
-struct DValue;
-typedef DValue elem;
-#endif
-
-#if IN_GCC
-union tree_node; typedef union tree_node block;
-//union tree_node; typedef union tree_node elem;
-#else
-struct block;
-//struct elem;
-#endif
-struct code;
-
-/* How a statement exits; this is returned by blockExit()
- */
-enum BE
-{
-    BEnone =	 0,
-    BEfallthru = 1,
-    BEthrow =    2,
-    BEreturn =   4,
-    BEgoto =     8,
-    BEhalt =	 0x10,
-    BEbreak =	 0x20,
-    BEcontinue = 0x40,
-    BEany = (BEfallthru | BEthrow | BEreturn | BEgoto | BEhalt),
-};
-
-struct Statement : Object
-{
-    Loc loc;
-
-    Statement(Loc loc);
-    virtual Statement *syntaxCopy();
-
-    void print();
-    char *toChars();
-
-    void error(const char *format, ...);
-    void warning(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 blockExit();
-    virtual int comeFrom();
-    virtual void scopeCode(Statement **sentry, Statement **sexit, Statement **sfinally);
-    virtual Statements *flatten(Scope *sc);
-    virtual Expression *interpret(InterState *istate);
-
-    virtual int inlineCost(InlineCostState *ics);
-    virtual Expression *doInline(InlineDoState *ids);
-    virtual Statement *inlineScan(InlineScanState *iss);
-
-    // Back end
-    virtual void toIR(IRState *irs);
-
-    // Avoid dynamic_cast
-    virtual DeclarationStatement *isDeclarationStatement() { return NULL; }
-    virtual CompoundStatement *isCompoundStatement() { return NULL; }
-    virtual ReturnStatement *isReturnStatement() { return NULL; }
-    virtual IfStatement *isIfStatement() { return NULL; }
-    virtual CaseStatement* isCaseStatement() { return NULL; }
-
-    // LDC
-    virtual void toNakedIR(IRState *irs);
-    virtual AsmBlockStatement* endsWithAsm();
-};
-
-struct ExpStatement : Statement
-{
-    Expression *exp;
-
-    ExpStatement(Loc loc, Expression *exp);
-    Statement *syntaxCopy();
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-    Statement *semantic(Scope *sc);
-    Expression *interpret(InterState *istate);
-    int blockExit();
-
-    int inlineCost(InlineCostState *ics);
-    Expression *doInline(InlineDoState *ids);
-    Statement *inlineScan(InlineScanState *iss);
-
-    void toIR(IRState *irs);
-
-    // LDC
-    void toNakedIR(IRState *irs);
-};
-
-struct CompileStatement : Statement
-{
-    Expression *exp;
-
-    CompileStatement(Loc loc, Expression *exp);
-    Statement *syntaxCopy();
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-    Statements *flatten(Scope *sc);
-    Statement *semantic(Scope *sc);
-};
-
-struct DeclarationStatement : ExpStatement
-{
-    // Doing declarations as an expression, rather than a statement,
-    // makes inlining functions much easier.
-
-    DeclarationStatement(Loc loc, Dsymbol *s);
-    DeclarationStatement(Loc loc, Expression *exp);
-    Statement *syntaxCopy();
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-    void scopeCode(Statement **sentry, Statement **sexit, Statement **sfinally);
-
-    DeclarationStatement *isDeclarationStatement() { return this; }
-};
-
-struct CompoundStatement : Statement
-{
-    Statements *statements;
-
-    CompoundStatement(Loc loc, Statements *s);
-    CompoundStatement(Loc loc, Statement *s1, Statement *s2);
-    virtual Statement *syntaxCopy();
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-    virtual Statement *semantic(Scope *sc);
-    int usesEH();
-    int blockExit();
-    int comeFrom();
-    virtual Statements *flatten(Scope *sc);
-    ReturnStatement *isReturnStatement();
-    Expression *interpret(InterState *istate);
-
-    int inlineCost(InlineCostState *ics);
-    Expression *doInline(InlineDoState *ids);
-    Statement *inlineScan(InlineScanState *iss);
-
-    virtual void toIR(IRState *irs);
-
-    // LDC
-    virtual void toNakedIR(IRState *irs);
-    virtual AsmBlockStatement* endsWithAsm();
-
-    virtual CompoundStatement *isCompoundStatement() { return this; }
-};
-
-/* The purpose of this is so that continue will go to the next
- * of the statements, and break will go to the end of the statements.
- */
-struct UnrolledLoopStatement : Statement
-{
-    Statements *statements;
-
-    UnrolledLoopStatement(Loc loc, Statements *statements);
-    Statement *syntaxCopy();
-    Statement *semantic(Scope *sc);
-    int hasBreak();
-    int hasContinue();
-    int usesEH();
-    int blockExit();
-    int comeFrom();
-    Expression *interpret(InterState *istate);
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-
-    int inlineCost(InlineCostState *ics);
-    Expression *doInline(InlineDoState *ids);
-    Statement *inlineScan(InlineScanState *iss);
-
-    void toIR(IRState *irs);
-};
-
-struct ScopeStatement : Statement
-{
-    Statement *statement;
-
-    ScopeStatement(Loc loc, Statement *s);
-    Statement *syntaxCopy();
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-    ScopeStatement *isScopeStatement() { return this; }
-    Statement *semantic(Scope *sc);
-    int hasBreak();
-    int hasContinue();
-    int usesEH();
-    int blockExit();
-    int comeFrom();
-    Expression *interpret(InterState *istate);
-
-    Statement *inlineScan(InlineScanState *iss);
-
-    void toIR(IRState *irs);
-};
-
-struct WhileStatement : Statement
-{
-    Expression *condition;
-    Statement *body;
-
-    WhileStatement(Loc loc, Expression *c, Statement *b);
-    Statement *syntaxCopy();
-    Statement *semantic(Scope *sc);
-    int hasBreak();
-    int hasContinue();
-    int usesEH();
-    int blockExit();
-    int comeFrom();
-    Expression *interpret(InterState *istate);
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-
-    Statement *inlineScan(InlineScanState *iss);
-
-    void toIR(IRState *irs);
-};
-
-struct DoStatement : Statement
-{
-    Statement *body;
-    Expression *condition;
-
-    DoStatement(Loc loc, Statement *b, Expression *c);
-    Statement *syntaxCopy();
-    Statement *semantic(Scope *sc);
-    int hasBreak();
-    int hasContinue();
-    int usesEH();
-    int blockExit();
-    int comeFrom();
-    Expression *interpret(InterState *istate);
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-
-    Statement *inlineScan(InlineScanState *iss);
-
-    void toIR(IRState *irs);
-};
-
-struct ForStatement : Statement
-{
-    Statement *init;
-    Expression *condition;
-    Expression *increment;
-    Statement *body;
-
-    ForStatement(Loc loc, Statement *init, Expression *condition, Expression *increment, Statement *body);
-    Statement *syntaxCopy();
-    Statement *semantic(Scope *sc);
-    void scopeCode(Statement **sentry, Statement **sexit, Statement **sfinally);
-    int hasBreak();
-    int hasContinue();
-    int usesEH();
-    int blockExit();
-    int comeFrom();
-    Expression *interpret(InterState *istate);
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-
-    Statement *inlineScan(InlineScanState *iss);
-
-    void toIR(IRState *irs);
-};
-
-struct ForeachStatement : Statement
-{
-    enum TOK op;		// TOKforeach or TOKforeach_reverse
-    Arguments *arguments;	// array of Argument*'s
-    Expression *aggr;
-    Statement *body;
-
-    VarDeclaration *key;
-    VarDeclaration *value;
-
-    FuncDeclaration *func;	// function we're lexically in
-
-    Array cases;	// put breaks, continues, gotos and returns here
-    Array gotos;	// forward referenced goto's go here
-
-    ForeachStatement(Loc loc, enum TOK op, Arguments *arguments, Expression *aggr, Statement *body);
-    Statement *syntaxCopy();
-    Statement *semantic(Scope *sc);
-    int hasBreak();
-    int hasContinue();
-    int usesEH();
-    int blockExit();
-    int comeFrom();
-    Expression *interpret(InterState *istate);
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-
-    Statement *inlineScan(InlineScanState *iss);
-
-    void toIR(IRState *irs);
-};
-
-#if DMDV2
-struct ForeachRangeStatement : Statement
-{
-    enum TOK op;		// TOKforeach or TOKforeach_reverse
-    Argument *arg;		// loop index variable
-    Expression *lwr;
-    Expression *upr;
-    Statement *body;
-
-    VarDeclaration *key;
-
-    ForeachRangeStatement(Loc loc, enum TOK op, Argument *arg,
-	Expression *lwr, Expression *upr, Statement *body);
-    Statement *syntaxCopy();
-    Statement *semantic(Scope *sc);
-    int hasBreak();
-    int hasContinue();
-    int usesEH();
-    int blockExit();
-    int comeFrom();
-    Expression *interpret(InterState *istate);
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-
-    Statement *inlineScan(InlineScanState *iss);
-
-    void toIR(IRState *irs);
-};
-#endif
-
-struct IfStatement : Statement
-{
-    Argument *arg;
-    Expression *condition;
-    Statement *ifbody;
-    Statement *elsebody;
-
-    VarDeclaration *match;	// for MatchExpression results
-
-    IfStatement(Loc loc, Argument *arg, Expression *condition, Statement *ifbody, Statement *elsebody);
-    Statement *syntaxCopy();
-    Statement *semantic(Scope *sc);
-    Expression *interpret(InterState *istate);
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-    int usesEH();
-    int blockExit();
-    IfStatement *isIfStatement() { return this; }
-
-    int inlineCost(InlineCostState *ics);
-    Expression *doInline(InlineDoState *ids);
-    Statement *inlineScan(InlineScanState *iss);
-
-    void toIR(IRState *irs);
-};
-
-struct ConditionalStatement : Statement
-{
-    Condition *condition;
-    Statement *ifbody;
-    Statement *elsebody;
-
-    ConditionalStatement(Loc loc, Condition *condition, Statement *ifbody, Statement *elsebody);
-    Statement *syntaxCopy();
-    Statement *semantic(Scope *sc);
-    Statements *flatten(Scope *sc);
-    int usesEH();
-    int blockExit();
-
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-};
-
-struct PragmaStatement : Statement
-{
-    Identifier *ident;
-    Expressions *args;		// array of Expression's
-    Statement *body;
-
-    PragmaStatement(Loc loc, Identifier *ident, Expressions *args, Statement *body);
-    Statement *syntaxCopy();
-    Statement *semantic(Scope *sc);
-    int usesEH();
-    int blockExit();
-
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-};
-
-struct StaticAssertStatement : Statement
-{
-    StaticAssert *sa;
-
-    StaticAssertStatement(StaticAssert *sa);
-    Statement *syntaxCopy();
-    Statement *semantic(Scope *sc);
-
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-};
-
-struct SwitchStatement : Statement
-{
-    Expression *condition;
-    Statement *body;
-
-    DefaultStatement *sdefault;
-
-    Array gotoCases;		// array of unresolved GotoCaseStatement's
-    Array *cases;		// array of CaseStatement's
-    int hasNoDefault;		// !=0 if no default statement
-    
-    // LDC
-    Statement *enclosingScopeExit;
-
-    SwitchStatement(Loc loc, Expression *c, Statement *b);
-    Statement *syntaxCopy();
-    Statement *semantic(Scope *sc);
-    int hasBreak();
-    int usesEH();
-    int blockExit();
-    Expression *interpret(InterState *istate);
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-
-    Statement *inlineScan(InlineScanState *iss);
-
-    void toIR(IRState *irs);
-};
-
-struct CaseStatement : Statement
-{
-    Expression *exp;
-    Statement *statement;
-    int index;		// which case it is (since we sort this)
-    block *cblock;	// back end: label for the block
-
-    // LDC
-    Statement *enclosingScopeExit;
-
-    CaseStatement(Loc loc, Expression *exp, Statement *s);
-    Statement *syntaxCopy();
-    Statement *semantic(Scope *sc);
-    int compare(Object *obj);
-    int usesEH();
-    int blockExit();
-    int comeFrom();
-    Expression *interpret(InterState *istate);
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-
-    Statement *inlineScan(InlineScanState *iss);
-
-    void toIR(IRState *irs);
-
-    CaseStatement* isCaseStatement() { return this; }
-
-    // LDC
-    llvm::BasicBlock* bodyBB;
-    llvm::ConstantInt* llvmIdx;
-};
-
-struct DefaultStatement : Statement
-{
-    Statement *statement;
-#if IN_GCC
-    block *cblock;	// back end: label for the block
-#endif
-
-    // LDC
-    Statement *enclosingScopeExit;
-
-    DefaultStatement(Loc loc, Statement *s);
-    Statement *syntaxCopy();
-    Statement *semantic(Scope *sc);
-    int usesEH();
-    int blockExit();
-    int comeFrom();
-    Expression *interpret(InterState *istate);
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-
-    Statement *inlineScan(InlineScanState *iss);
-
-    void toIR(IRState *irs);
-
-    // LDC
-    llvm::BasicBlock* bodyBB;
-};
-
-struct GotoDefaultStatement : Statement
-{
-    SwitchStatement *sw;
-
-    GotoDefaultStatement(Loc loc);
-    Statement *syntaxCopy();
-    Statement *semantic(Scope *sc);
-    Expression *interpret(InterState *istate);
-    int blockExit();
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-
-    void toIR(IRState *irs);
-};
-
-struct GotoCaseStatement : Statement
-{
-    Expression *exp;		// NULL, or which case to goto
-    CaseStatement *cs;		// case statement it resolves to
-    SwitchStatement *sw;
-
-    GotoCaseStatement(Loc loc, Expression *exp);
-    Statement *syntaxCopy();
-    Statement *semantic(Scope *sc);
-    Expression *interpret(InterState *istate);
-    int blockExit();
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-
-    void toIR(IRState *irs);
-};
-
-struct SwitchErrorStatement : Statement
-{
-    SwitchErrorStatement(Loc loc);
-    int blockExit();
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-
-    void toIR(IRState *irs);
-};
-
-struct ReturnStatement : Statement
-{
-    Expression *exp;
-
-    ReturnStatement(Loc loc, Expression *exp);
-    Statement *syntaxCopy();
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-    Statement *semantic(Scope *sc);
-    int blockExit();
-    Expression *interpret(InterState *istate);
-
-    int inlineCost(InlineCostState *ics);
-    Expression *doInline(InlineDoState *ids);
-    Statement *inlineScan(InlineScanState *iss);
-
-    void toIR(IRState *irs);
-
-    ReturnStatement *isReturnStatement() { return this; }
-};
-
-struct BreakStatement : Statement
-{
-    Identifier *ident;
-
-    BreakStatement(Loc loc, Identifier *ident);
-    Statement *syntaxCopy();
-    Statement *semantic(Scope *sc);
-    Expression *interpret(InterState *istate);
-    int blockExit();
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-
-    void toIR(IRState *irs);
-
-    // LDC: only set if ident is set: label statement to jump to
-    LabelStatement *target;
-};
-
-struct ContinueStatement : Statement
-{
-    Identifier *ident;
-
-    ContinueStatement(Loc loc, Identifier *ident);
-    Statement *syntaxCopy();
-    Statement *semantic(Scope *sc);
-    Expression *interpret(InterState *istate);
-    int blockExit();
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-
-    void toIR(IRState *irs);
-
-    // LDC: only set if ident is set: label statement to jump to
-    LabelStatement *target;
-};
-
-struct SynchronizedStatement : Statement
-{
-    Expression *exp;
-    Statement *body;
-
-    SynchronizedStatement(Loc loc, Expression *exp, Statement *body);
-    Statement *syntaxCopy();
-    Statement *semantic(Scope *sc);
-    int hasBreak();
-    int hasContinue();
-    int usesEH();
-    int blockExit();
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-
-    Statement *inlineScan(InlineScanState *iss);
-
-// Back end
-    elem *esync;
-    SynchronizedStatement(Loc loc, elem *esync, Statement *body);
-    void toIR(IRState *irs);
-    llvm::Value* llsync;
-};
-
-struct WithStatement : Statement
-{
-    Expression *exp;
-    Statement *body;
-    VarDeclaration *wthis;
-
-    WithStatement(Loc loc, Expression *exp, Statement *body);
-    Statement *syntaxCopy();
-    Statement *semantic(Scope *sc);
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-    int usesEH();
-    int blockExit();
-
-    Statement *inlineScan(InlineScanState *iss);
-
-    void toIR(IRState *irs);
-};
-
-struct TryCatchStatement : Statement
-{
-    Statement *body;
-    Array *catches;
-
-    TryCatchStatement(Loc loc, Statement *body, Array *catches);
-    Statement *syntaxCopy();
-    Statement *semantic(Scope *sc);
-    int hasBreak();
-    int usesEH();
-    int blockExit();
-
-    Statement *inlineScan(InlineScanState *iss);
-
-    void toIR(IRState *irs);
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-    TryCatchStatement *isTryCatchStatement() { return this; }
-};
-
-struct Catch : Object
-{
-    Loc loc;
-    Type *type;
-    Identifier *ident;
-    VarDeclaration *var;
-    Statement *handler;
-
-    Catch(Loc loc, Type *t, Identifier *id, Statement *handler);
-    Catch *syntaxCopy();
-    void semantic(Scope *sc);
-    int blockExit();
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-};
-
-struct TryFinallyStatement : Statement
-{
-    Statement *body;
-    Statement *finalbody;
-
-    TryFinallyStatement(Loc loc, Statement *body, Statement *finalbody);
-    Statement *syntaxCopy();
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-    Statement *semantic(Scope *sc);
-    int hasBreak();
-    int hasContinue();
-    int usesEH();
-    int blockExit();
-
-    Statement *inlineScan(InlineScanState *iss);
-
-    void toIR(IRState *irs);
-};
-
-struct OnScopeStatement : Statement
-{
-    TOK tok;
-    Statement *statement;
-
-    OnScopeStatement(Loc loc, TOK tok, Statement *statement);
-    Statement *syntaxCopy();
-    int blockExit();
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-    Statement *semantic(Scope *sc);
-    int usesEH();
-    void scopeCode(Statement **sentry, Statement **sexit, Statement **sfinally);
-
-    void toIR(IRState *irs);
-};
-
-struct ThrowStatement : Statement
-{
-    Expression *exp;
-
-    ThrowStatement(Loc loc, Expression *exp);
-    Statement *syntaxCopy();
-    Statement *semantic(Scope *sc);
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-    int blockExit();
-
-    Statement *inlineScan(InlineScanState *iss);
-
-    void toIR(IRState *irs);
-};
-
-struct VolatileStatement : Statement
-{
-    Statement *statement;
-
-    VolatileStatement(Loc loc, Statement *statement);
-    Statement *syntaxCopy();
-    Statement *semantic(Scope *sc);
-    Statements *flatten(Scope *sc);
-    int blockExit();
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-
-    Statement *inlineScan(InlineScanState *iss);
-
-    void toIR(IRState *irs);
-};
-
-struct GotoStatement : Statement
-{
-    Identifier *ident;
-    LabelDsymbol *label;
-    TryFinallyStatement *enclosingFinally;
-    Statement* enclosingScopeExit;
-
-    GotoStatement(Loc loc, Identifier *ident);
-    Statement *syntaxCopy();
-    Statement *semantic(Scope *sc);
-    int blockExit();
-    Expression *interpret(InterState *istate);
-
-    void toIR(IRState *irs);
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-    GotoStatement *isGotoStatement() { return this; }
-};
-
-struct LabelStatement : Statement
-{
-    Identifier *ident;
-    Statement *statement;
-    TryFinallyStatement *enclosingFinally;
-    Statement* enclosingScopeExit;
-    block *lblock;		// back end
-    int isReturnLabel;
-
-    LabelStatement(Loc loc, Identifier *ident, Statement *statement);
-    Statement *syntaxCopy();
-    Statement *semantic(Scope *sc);
-    Statements *flatten(Scope *sc);
-    int usesEH();
-    int blockExit();
-    int comeFrom();
-    Expression *interpret(InterState *istate);
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-
-    Statement *inlineScan(InlineScanState *iss);
-
-    void toIR(IRState *irs);
-
-    // LDC
-    bool asmLabel;       // for labels inside inline assembler
-    void toNakedIR(IRState *irs);
-};
-
-struct LabelDsymbol : Dsymbol
-{
-    LabelStatement *statement;
-
-    LabelDsymbol(Identifier *ident);
-    LabelDsymbol *isLabel();
-};
-
-struct AsmStatement : Statement
-{
-    Token *tokens;
-    code *asmcode;
-    unsigned asmalign;		// alignment of this statement
-    unsigned refparam;		// !=0 if function parameter is referenced
-    unsigned naked;		// !=0 if function is to be naked
-
-    AsmStatement(Loc loc, Token *tokens);
-    Statement *syntaxCopy();
-    Statement *semantic(Scope *sc);
-    int blockExit();
-    int comeFrom();
-
-    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-    virtual AsmStatement *isAsmStatement() { return this; }
-
-    void toIR(IRState *irs);
-
-    // LDC
-    // non-zero if this is a branch, contains the target labels identifier
-    Identifier* isBranchToLabel;
-
-    void toNakedIR(IRState *irs);
-};
-
-struct AsmBlockStatement : CompoundStatement
-{
-    TryFinallyStatement* enclosingFinally;
-    Statement* enclosingScopeExit;
-
-    AsmBlockStatement(Loc loc, Statements *s);
-    Statements *flatten(Scope *sc);
-    Statement *syntaxCopy();
-    Statement *semantic(Scope *sc);
-
-    CompoundStatement *isCompoundStatement() { return NULL; }
-    AsmBlockStatement *isAsmBlockStatement() { return this; }
-
-    void toIR(IRState *irs);
-    void toNakedIR(IRState *irs);
-    AsmBlockStatement* endsWithAsm();
-
-    llvm::Value* abiret;
-};
-
-#endif /* DMD_STATEMENT_H */
+
+// Compiler implementation of the D programming language
+// Copyright (c) 1999-2008 by Digital Mars
+// All Rights Reserved
+// written by Walter Bright
+// http://www.digitalmars.com
+// License for redistribution is by either the Artistic License
+// in artistic.txt, or the GNU General Public License in gnu.txt.
+// See the included readme.txt for details.
+
+#ifndef DMD_STATEMENT_H
+#define DMD_STATEMENT_H
+
+#ifdef __DMC__
+#pragma once
+#endif /* __DMC__ */
+
+#include "root.h"
+
+#include "arraytypes.h"
+#include "dsymbol.h"
+#include "lexer.h"
+
+struct OutBuffer;
+struct Scope;
+struct Expression;
+struct LabelDsymbol;
+struct Identifier;
+struct IfStatement;
+struct DeclarationStatement;
+struct DefaultStatement;
+struct VarDeclaration;
+struct Condition;
+struct Module;
+struct Token;
+struct InlineCostState;
+struct InlineDoState;
+struct InlineScanState;
+struct ReturnStatement;
+struct CompoundStatement;
+struct Argument;
+struct StaticAssert;
+struct AsmStatement;
+struct AsmBlockStatement;
+struct GotoStatement;
+struct ScopeStatement;
+struct TryCatchStatement;
+struct TryFinallyStatement;
+struct HdrGenState;
+struct InterState;
+struct CaseStatement;
+struct LabelStatement;
+struct VolatileStatement;
+struct SynchronizedStatement;
+
+enum TOK;
+
+namespace llvm
+{
+    class Value;
+    class BasicBlock;
+    class ConstantInt;
+}
+
+// Back end
+struct IRState;
+struct Blockx;
+#if IN_LLVM
+struct DValue;
+typedef DValue elem;
+#endif
+
+#if IN_GCC
+union tree_node; typedef union tree_node block;
+//union tree_node; typedef union tree_node elem;
+#else
+struct block;
+//struct elem;
+#endif
+struct code;
+
+/* How a statement exits; this is returned by blockExit()
+ */
+enum BE
+{
+    BEnone =	 0,
+    BEfallthru = 1,
+    BEthrow =    2,
+    BEreturn =   4,
+    BEgoto =     8,
+    BEhalt =	 0x10,
+    BEbreak =	 0x20,
+    BEcontinue = 0x40,
+    BEany = (BEfallthru | BEthrow | BEreturn | BEgoto | BEhalt),
+};
+
+struct Statement : Object
+{
+    Loc loc;
+
+    Statement(Loc loc);
+    virtual Statement *syntaxCopy();
+
+    void print();
+    char *toChars();
+
+    void error(const char *format, ...);
+    void warning(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 blockExit();
+    virtual int comeFrom();
+    virtual void scopeCode(Statement **sentry, Statement **sexit, Statement **sfinally);
+    virtual Statements *flatten(Scope *sc);
+    virtual Expression *interpret(InterState *istate);
+
+    virtual int inlineCost(InlineCostState *ics);
+    virtual Expression *doInline(InlineDoState *ids);
+    virtual Statement *inlineScan(InlineScanState *iss);
+
+    // Back end
+    virtual void toIR(IRState *irs);
+
+    // Avoid dynamic_cast
+    virtual DeclarationStatement *isDeclarationStatement() { return NULL; }
+    virtual CompoundStatement *isCompoundStatement() { return NULL; }
+    virtual ReturnStatement *isReturnStatement() { return NULL; }
+    virtual IfStatement *isIfStatement() { return NULL; }
+    virtual CaseStatement* isCaseStatement() { return NULL; }
+
+    // LDC
+    virtual void toNakedIR(IRState *irs);
+    virtual AsmBlockStatement* endsWithAsm();
+};
+
+struct ExpStatement : Statement
+{
+    Expression *exp;
+
+    ExpStatement(Loc loc, Expression *exp);
+    Statement *syntaxCopy();
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+    Statement *semantic(Scope *sc);
+    Expression *interpret(InterState *istate);
+    int blockExit();
+
+    int inlineCost(InlineCostState *ics);
+    Expression *doInline(InlineDoState *ids);
+    Statement *inlineScan(InlineScanState *iss);
+
+    void toIR(IRState *irs);
+
+    // LDC
+    void toNakedIR(IRState *irs);
+};
+
+struct CompileStatement : Statement
+{
+    Expression *exp;
+
+    CompileStatement(Loc loc, Expression *exp);
+    Statement *syntaxCopy();
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+    Statements *flatten(Scope *sc);
+    Statement *semantic(Scope *sc);
+};
+
+struct DeclarationStatement : ExpStatement
+{
+    // Doing declarations as an expression, rather than a statement,
+    // makes inlining functions much easier.
+
+    DeclarationStatement(Loc loc, Dsymbol *s);
+    DeclarationStatement(Loc loc, Expression *exp);
+    Statement *syntaxCopy();
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+    void scopeCode(Statement **sentry, Statement **sexit, Statement **sfinally);
+
+    DeclarationStatement *isDeclarationStatement() { return this; }
+};
+
+struct CompoundStatement : Statement
+{
+    Statements *statements;
+
+    CompoundStatement(Loc loc, Statements *s);
+    CompoundStatement(Loc loc, Statement *s1, Statement *s2);
+    virtual Statement *syntaxCopy();
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+    virtual Statement *semantic(Scope *sc);
+    int usesEH();
+    int blockExit();
+    int comeFrom();
+    virtual Statements *flatten(Scope *sc);
+    ReturnStatement *isReturnStatement();
+    Expression *interpret(InterState *istate);
+
+    int inlineCost(InlineCostState *ics);
+    Expression *doInline(InlineDoState *ids);
+    Statement *inlineScan(InlineScanState *iss);
+
+    virtual void toIR(IRState *irs);
+
+    // LDC
+    virtual void toNakedIR(IRState *irs);
+    virtual AsmBlockStatement* endsWithAsm();
+
+    virtual CompoundStatement *isCompoundStatement() { return this; }
+};
+
+struct CompoundDeclarationStatement : CompoundStatement
+{
+    CompoundDeclarationStatement(Loc loc, Statements *s);
+    Statement *syntaxCopy();
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+};
+
+/* The purpose of this is so that continue will go to the next
+ * of the statements, and break will go to the end of the statements.
+ */
+struct UnrolledLoopStatement : Statement
+{
+    Statements *statements;
+
+    UnrolledLoopStatement(Loc loc, Statements *statements);
+    Statement *syntaxCopy();
+    Statement *semantic(Scope *sc);
+    int hasBreak();
+    int hasContinue();
+    int usesEH();
+    int blockExit();
+    int comeFrom();
+    Expression *interpret(InterState *istate);
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+
+    int inlineCost(InlineCostState *ics);
+    Expression *doInline(InlineDoState *ids);
+    Statement *inlineScan(InlineScanState *iss);
+
+    void toIR(IRState *irs);
+};
+
+struct ScopeStatement : Statement
+{
+    Statement *statement;
+
+    ScopeStatement(Loc loc, Statement *s);
+    Statement *syntaxCopy();
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+    ScopeStatement *isScopeStatement() { return this; }
+    Statement *semantic(Scope *sc);
+    int hasBreak();
+    int hasContinue();
+    int usesEH();
+    int blockExit();
+    int comeFrom();
+    Expression *interpret(InterState *istate);
+
+    Statement *inlineScan(InlineScanState *iss);
+
+    void toIR(IRState *irs);
+};
+
+struct WhileStatement : Statement
+{
+    Expression *condition;
+    Statement *body;
+
+    WhileStatement(Loc loc, Expression *c, Statement *b);
+    Statement *syntaxCopy();
+    Statement *semantic(Scope *sc);
+    int hasBreak();
+    int hasContinue();
+    int usesEH();
+    int blockExit();
+    int comeFrom();
+    Expression *interpret(InterState *istate);
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+
+    Statement *inlineScan(InlineScanState *iss);
+
+    void toIR(IRState *irs);
+};
+
+struct DoStatement : Statement
+{
+    Statement *body;
+    Expression *condition;
+
+    DoStatement(Loc loc, Statement *b, Expression *c);
+    Statement *syntaxCopy();
+    Statement *semantic(Scope *sc);
+    int hasBreak();
+    int hasContinue();
+    int usesEH();
+    int blockExit();
+    int comeFrom();
+    Expression *interpret(InterState *istate);
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+
+    Statement *inlineScan(InlineScanState *iss);
+
+    void toIR(IRState *irs);
+};
+
+struct ForStatement : Statement
+{
+    Statement *init;
+    Expression *condition;
+    Expression *increment;
+    Statement *body;
+
+    ForStatement(Loc loc, Statement *init, Expression *condition, Expression *increment, Statement *body);
+    Statement *syntaxCopy();
+    Statement *semantic(Scope *sc);
+    void scopeCode(Statement **sentry, Statement **sexit, Statement **sfinally);
+    int hasBreak();
+    int hasContinue();
+    int usesEH();
+    int blockExit();
+    int comeFrom();
+    Expression *interpret(InterState *istate);
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+
+    Statement *inlineScan(InlineScanState *iss);
+
+    void toIR(IRState *irs);
+};
+
+struct ForeachStatement : Statement
+{
+    enum TOK op;		// TOKforeach or TOKforeach_reverse
+    Arguments *arguments;	// array of Argument*'s
+    Expression *aggr;
+    Statement *body;
+
+    VarDeclaration *key;
+    VarDeclaration *value;
+
+    FuncDeclaration *func;	// function we're lexically in
+
+    Array cases;	// put breaks, continues, gotos and returns here
+    Array gotos;	// forward referenced goto's go here
+
+    ForeachStatement(Loc loc, enum TOK op, Arguments *arguments, Expression *aggr, Statement *body);
+    Statement *syntaxCopy();
+    Statement *semantic(Scope *sc);
+    int hasBreak();
+    int hasContinue();
+    int usesEH();
+    int blockExit();
+    int comeFrom();
+    Expression *interpret(InterState *istate);
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+
+    Statement *inlineScan(InlineScanState *iss);
+
+    void toIR(IRState *irs);
+};
+
+#if DMDV2
+struct ForeachRangeStatement : Statement
+{
+    enum TOK op;		// TOKforeach or TOKforeach_reverse
+    Argument *arg;		// loop index variable
+    Expression *lwr;
+    Expression *upr;
+    Statement *body;
+
+    VarDeclaration *key;
+
+    ForeachRangeStatement(Loc loc, enum TOK op, Argument *arg,
+	Expression *lwr, Expression *upr, Statement *body);
+    Statement *syntaxCopy();
+    Statement *semantic(Scope *sc);
+    int hasBreak();
+    int hasContinue();
+    int usesEH();
+    int blockExit();
+    int comeFrom();
+    Expression *interpret(InterState *istate);
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+
+    Statement *inlineScan(InlineScanState *iss);
+
+    void toIR(IRState *irs);
+};
+#endif
+
+struct IfStatement : Statement
+{
+    Argument *arg;
+    Expression *condition;
+    Statement *ifbody;
+    Statement *elsebody;
+
+    VarDeclaration *match;	// for MatchExpression results
+
+    IfStatement(Loc loc, Argument *arg, Expression *condition, Statement *ifbody, Statement *elsebody);
+    Statement *syntaxCopy();
+    Statement *semantic(Scope *sc);
+    Expression *interpret(InterState *istate);
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+    int usesEH();
+    int blockExit();
+    IfStatement *isIfStatement() { return this; }
+
+    int inlineCost(InlineCostState *ics);
+    Expression *doInline(InlineDoState *ids);
+    Statement *inlineScan(InlineScanState *iss);
+
+    void toIR(IRState *irs);
+};
+
+struct ConditionalStatement : Statement
+{
+    Condition *condition;
+    Statement *ifbody;
+    Statement *elsebody;
+
+    ConditionalStatement(Loc loc, Condition *condition, Statement *ifbody, Statement *elsebody);
+    Statement *syntaxCopy();
+    Statement *semantic(Scope *sc);
+    Statements *flatten(Scope *sc);
+    int usesEH();
+    int blockExit();
+
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+};
+
+struct PragmaStatement : Statement
+{
+    Identifier *ident;
+    Expressions *args;		// array of Expression's
+    Statement *body;
+
+    PragmaStatement(Loc loc, Identifier *ident, Expressions *args, Statement *body);
+    Statement *syntaxCopy();
+    Statement *semantic(Scope *sc);
+    int usesEH();
+    int blockExit();
+
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+};
+
+struct StaticAssertStatement : Statement
+{
+    StaticAssert *sa;
+
+    StaticAssertStatement(StaticAssert *sa);
+    Statement *syntaxCopy();
+    Statement *semantic(Scope *sc);
+
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+};
+
+struct SwitchStatement : Statement
+{
+    Expression *condition;
+    Statement *body;
+
+    DefaultStatement *sdefault;
+
+    Array gotoCases;		// array of unresolved GotoCaseStatement's
+    Array *cases;		// array of CaseStatement's
+    int hasNoDefault;		// !=0 if no default statement
+    
+    // LDC
+    Statement *enclosingScopeExit;
+
+    SwitchStatement(Loc loc, Expression *c, Statement *b);
+    Statement *syntaxCopy();
+    Statement *semantic(Scope *sc);
+    int hasBreak();
+    int usesEH();
+    int blockExit();
+    Expression *interpret(InterState *istate);
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+
+    Statement *inlineScan(InlineScanState *iss);
+
+    void toIR(IRState *irs);
+};
+
+struct CaseStatement : Statement
+{
+    Expression *exp;
+    Statement *statement;
+    int index;		// which case it is (since we sort this)
+    block *cblock;	// back end: label for the block
+
+    // LDC
+    Statement *enclosingScopeExit;
+
+    CaseStatement(Loc loc, Expression *exp, Statement *s);
+    Statement *syntaxCopy();
+    Statement *semantic(Scope *sc);
+    int compare(Object *obj);
+    int usesEH();
+    int blockExit();
+    int comeFrom();
+    Expression *interpret(InterState *istate);
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+
+    Statement *inlineScan(InlineScanState *iss);
+
+    void toIR(IRState *irs);
+
+    CaseStatement* isCaseStatement() { return this; }
+
+    // LDC
+    llvm::BasicBlock* bodyBB;
+    llvm::ConstantInt* llvmIdx;
+};
+
+struct DefaultStatement : Statement
+{
+    Statement *statement;
+#if IN_GCC
+    block *cblock;	// back end: label for the block
+#endif
+
+    // LDC
+    Statement *enclosingScopeExit;
+
+    DefaultStatement(Loc loc, Statement *s);
+    Statement *syntaxCopy();
+    Statement *semantic(Scope *sc);
+    int usesEH();
+    int blockExit();
+    int comeFrom();
+    Expression *interpret(InterState *istate);
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+
+    Statement *inlineScan(InlineScanState *iss);
+
+    void toIR(IRState *irs);
+
+    // LDC
+    llvm::BasicBlock* bodyBB;
+};
+
+struct GotoDefaultStatement : Statement
+{
+    SwitchStatement *sw;
+
+    GotoDefaultStatement(Loc loc);
+    Statement *syntaxCopy();
+    Statement *semantic(Scope *sc);
+    Expression *interpret(InterState *istate);
+    int blockExit();
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+
+    void toIR(IRState *irs);
+};
+
+struct GotoCaseStatement : Statement
+{
+    Expression *exp;		// NULL, or which case to goto
+    CaseStatement *cs;		// case statement it resolves to
+    SwitchStatement *sw;
+
+    GotoCaseStatement(Loc loc, Expression *exp);
+    Statement *syntaxCopy();
+    Statement *semantic(Scope *sc);
+    Expression *interpret(InterState *istate);
+    int blockExit();
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+
+    void toIR(IRState *irs);
+};
+
+struct SwitchErrorStatement : Statement
+{
+    SwitchErrorStatement(Loc loc);
+    int blockExit();
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+
+    void toIR(IRState *irs);
+};
+
+struct ReturnStatement : Statement
+{
+    Expression *exp;
+
+    ReturnStatement(Loc loc, Expression *exp);
+    Statement *syntaxCopy();
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+    Statement *semantic(Scope *sc);
+    int blockExit();
+    Expression *interpret(InterState *istate);
+
+    int inlineCost(InlineCostState *ics);
+    Expression *doInline(InlineDoState *ids);
+    Statement *inlineScan(InlineScanState *iss);
+
+    void toIR(IRState *irs);
+
+    ReturnStatement *isReturnStatement() { return this; }
+};
+
+struct BreakStatement : Statement
+{
+    Identifier *ident;
+
+    BreakStatement(Loc loc, Identifier *ident);
+    Statement *syntaxCopy();
+    Statement *semantic(Scope *sc);
+    Expression *interpret(InterState *istate);
+    int blockExit();
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+
+    void toIR(IRState *irs);
+
+    // LDC: only set if ident is set: label statement to jump to
+    LabelStatement *target;
+};
+
+struct ContinueStatement : Statement
+{
+    Identifier *ident;
+
+    ContinueStatement(Loc loc, Identifier *ident);
+    Statement *syntaxCopy();
+    Statement *semantic(Scope *sc);
+    Expression *interpret(InterState *istate);
+    int blockExit();
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+
+    void toIR(IRState *irs);
+
+    // LDC: only set if ident is set: label statement to jump to
+    LabelStatement *target;
+};
+
+struct SynchronizedStatement : Statement
+{
+    Expression *exp;
+    Statement *body;
+
+    SynchronizedStatement(Loc loc, Expression *exp, Statement *body);
+    Statement *syntaxCopy();
+    Statement *semantic(Scope *sc);
+    int hasBreak();
+    int hasContinue();
+    int usesEH();
+    int blockExit();
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+
+    Statement *inlineScan(InlineScanState *iss);
+
+// Back end
+    elem *esync;
+    SynchronizedStatement(Loc loc, elem *esync, Statement *body);
+    void toIR(IRState *irs);
+    llvm::Value* llsync;
+};
+
+struct WithStatement : Statement
+{
+    Expression *exp;
+    Statement *body;
+    VarDeclaration *wthis;
+
+    WithStatement(Loc loc, Expression *exp, Statement *body);
+    Statement *syntaxCopy();
+    Statement *semantic(Scope *sc);
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+    int usesEH();
+    int blockExit();
+
+    Statement *inlineScan(InlineScanState *iss);
+
+    void toIR(IRState *irs);
+};
+
+struct TryCatchStatement : Statement
+{
+    Statement *body;
+    Array *catches;
+
+    TryCatchStatement(Loc loc, Statement *body, Array *catches);
+    Statement *syntaxCopy();
+    Statement *semantic(Scope *sc);
+    int hasBreak();
+    int usesEH();
+    int blockExit();
+
+    Statement *inlineScan(InlineScanState *iss);
+
+    void toIR(IRState *irs);
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+    TryCatchStatement *isTryCatchStatement() { return this; }
+};
+
+struct Catch : Object
+{
+    Loc loc;
+    Type *type;
+    Identifier *ident;
+    VarDeclaration *var;
+    Statement *handler;
+
+    Catch(Loc loc, Type *t, Identifier *id, Statement *handler);
+    Catch *syntaxCopy();
+    void semantic(Scope *sc);
+    int blockExit();
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+};
+
+struct TryFinallyStatement : Statement
+{
+    Statement *body;
+    Statement *finalbody;
+
+    TryFinallyStatement(Loc loc, Statement *body, Statement *finalbody);
+    Statement *syntaxCopy();
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+    Statement *semantic(Scope *sc);
+    int hasBreak();
+    int hasContinue();
+    int usesEH();
+    int blockExit();
+
+    Statement *inlineScan(InlineScanState *iss);
+
+    void toIR(IRState *irs);
+};
+
+struct OnScopeStatement : Statement
+{
+    TOK tok;
+    Statement *statement;
+
+    OnScopeStatement(Loc loc, TOK tok, Statement *statement);
+    Statement *syntaxCopy();
+    int blockExit();
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+    Statement *semantic(Scope *sc);
+    int usesEH();
+    void scopeCode(Statement **sentry, Statement **sexit, Statement **sfinally);
+
+    void toIR(IRState *irs);
+};
+
+struct ThrowStatement : Statement
+{
+    Expression *exp;
+
+    ThrowStatement(Loc loc, Expression *exp);
+    Statement *syntaxCopy();
+    Statement *semantic(Scope *sc);
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+    int blockExit();
+
+    Statement *inlineScan(InlineScanState *iss);
+
+    void toIR(IRState *irs);
+};
+
+struct VolatileStatement : Statement
+{
+    Statement *statement;
+
+    VolatileStatement(Loc loc, Statement *statement);
+    Statement *syntaxCopy();
+    Statement *semantic(Scope *sc);
+    Statements *flatten(Scope *sc);
+    int blockExit();
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+
+    Statement *inlineScan(InlineScanState *iss);
+
+    void toIR(IRState *irs);
+};
+
+struct GotoStatement : Statement
+{
+    Identifier *ident;
+    LabelDsymbol *label;
+    TryFinallyStatement *enclosingFinally;
+    Statement* enclosingScopeExit;
+
+    GotoStatement(Loc loc, Identifier *ident);
+    Statement *syntaxCopy();
+    Statement *semantic(Scope *sc);
+    int blockExit();
+    Expression *interpret(InterState *istate);
+
+    void toIR(IRState *irs);
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+    GotoStatement *isGotoStatement() { return this; }
+};
+
+struct LabelStatement : Statement
+{
+    Identifier *ident;
+    Statement *statement;
+    TryFinallyStatement *enclosingFinally;
+    Statement* enclosingScopeExit;
+    block *lblock;		// back end
+    int isReturnLabel;
+
+    LabelStatement(Loc loc, Identifier *ident, Statement *statement);
+    Statement *syntaxCopy();
+    Statement *semantic(Scope *sc);
+    Statements *flatten(Scope *sc);
+    int usesEH();
+    int blockExit();
+    int comeFrom();
+    Expression *interpret(InterState *istate);
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+
+    Statement *inlineScan(InlineScanState *iss);
+
+    void toIR(IRState *irs);
+
+    // LDC
+    bool asmLabel;       // for labels inside inline assembler
+    void toNakedIR(IRState *irs);
+};
+
+struct LabelDsymbol : Dsymbol
+{
+    LabelStatement *statement;
+
+    LabelDsymbol(Identifier *ident);
+    LabelDsymbol *isLabel();
+};
+
+struct AsmStatement : Statement
+{
+    Token *tokens;
+    code *asmcode;
+    unsigned asmalign;		// alignment of this statement
+    unsigned refparam;		// !=0 if function parameter is referenced
+    unsigned naked;		// !=0 if function is to be naked
+
+    AsmStatement(Loc loc, Token *tokens);
+    Statement *syntaxCopy();
+    Statement *semantic(Scope *sc);
+    int blockExit();
+    int comeFrom();
+
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+    virtual AsmStatement *isAsmStatement() { return this; }
+
+    void toIR(IRState *irs);
+
+    // LDC
+    // non-zero if this is a branch, contains the target labels identifier
+    Identifier* isBranchToLabel;
+
+    void toNakedIR(IRState *irs);
+};
+
+struct AsmBlockStatement : CompoundStatement
+{
+    TryFinallyStatement* enclosingFinally;
+    Statement* enclosingScopeExit;
+
+    AsmBlockStatement(Loc loc, Statements *s);
+    Statements *flatten(Scope *sc);
+    Statement *syntaxCopy();
+    Statement *semantic(Scope *sc);
+
+    CompoundStatement *isCompoundStatement() { return NULL; }
+    AsmBlockStatement *isAsmBlockStatement() { return this; }
+
+    void toIR(IRState *irs);
+    void toNakedIR(IRState *irs);
+    AsmBlockStatement* endsWithAsm();
+
+    llvm::Value* abiret;
+};
+
+#endif /* DMD_STATEMENT_H */
--- a/dmd/struct.c	Fri Apr 03 17:02:52 2009 +0200
+++ b/dmd/struct.c	Fri Apr 03 17:59:34 2009 +0200
@@ -1,512 +1,512 @@
-
-// Compiler implementation of the D programming language
-// Copyright (c) 1999-2009 by Digital Mars
-// All Rights Reserved
-// written by Walter Bright
-// http://www.digitalmars.com
-// License for redistribution is by either the Artistic License
-// in artistic.txt, or the GNU General Public License in gnu.txt.
-// See the included readme.txt for details.
-
-#include <stdio.h>
-#include <assert.h>
-
-#include "root.h"
-#include "aggregate.h"
-#include "scope.h"
-#include "mtype.h"
-#include "declaration.h"
-#include "module.h"
-#include "id.h"
-#include "statement.h"
-
-/********************************* AggregateDeclaration ****************************/
-
-AggregateDeclaration::AggregateDeclaration(Loc loc, Identifier *id)
-    : ScopeDsymbol(id)
-{
-    this->loc = loc;
-
-    storage_class = 0;
-    protection = PROTpublic;
-    type = NULL;
-    handle = NULL;
-    structsize = 0;		// size of struct
-    alignsize = 0;		// size of struct for alignment purposes
-    structalign = 0;		// struct member alignment in effect
-    hasUnions = 0;
-    sizeok = 0;			// size not determined yet
-    isdeprecated = 0;
-    inv = NULL;
-    aggNew = NULL;
-    aggDelete = NULL;
-
-#if IN_DMD
-    stag = NULL;
-    sinit = NULL;
-#endif
-    scope = NULL;
-#if V2
-    dtor = NULL;
-
-    ctor = NULL;
-    defaultCtor = NULL;
-#endif
-}
-
-enum PROT AggregateDeclaration::prot()
-{
-    return protection;
-}
-
-void AggregateDeclaration::semantic2(Scope *sc)
-{
-    //printf("AggregateDeclaration::semantic2(%s)\n", toChars());
-    if (scope)
-    {	error("has forward references");
-	return;
-    }
-    if (members)
-    {
-	sc = sc->push(this);
-	for (size_t i = 0; i < members->dim; i++)
-	{
-	    Dsymbol *s = (Dsymbol *)members->data[i];
-	    s->semantic2(sc);
-	}
-	sc->pop();
-    }
-}
-
-void AggregateDeclaration::semantic3(Scope *sc)
-{   int i;
-
-    //printf("AggregateDeclaration::semantic3(%s)\n", toChars());
-    if (members)
-    {
-	sc = sc->push(this);
-	for (i = 0; i < members->dim; i++)
-	{
-	    Dsymbol *s = (Dsymbol *)members->data[i];
-	    s->semantic3(sc);
-	}
-	sc->pop();
-    }
-}
-
-void AggregateDeclaration::inlineScan()
-{   int i;
-
-    //printf("AggregateDeclaration::inlineScan(%s)\n", toChars());
-    if (members)
-    {
-	for (i = 0; i < members->dim; i++)
-	{
-	    Dsymbol *s = (Dsymbol *)members->data[i];
-	    //printf("inline scan aggregate symbol '%s'\n", s->toChars());
-	    s->inlineScan();
-	}
-    }
-}
-
-unsigned AggregateDeclaration::size(Loc loc)
-{
-    //printf("AggregateDeclaration::size() = %d\n", structsize);
-    if (!members)
-	error(loc, "unknown size");
-    if (sizeok != 1)
-    {	error(loc, "no size yet for forward reference");
-	//*(char*)0=0;
-    }
-    return structsize;
-}
-
-Type *AggregateDeclaration::getType()
-{
-    return type;
-}
-
-int AggregateDeclaration::isDeprecated()
-{
-    return isdeprecated;
-}
-
-/****************************
- * Do byte or word alignment as necessary.
- * Align sizes of 0, as we may not know array sizes yet.
- */
-
-void AggregateDeclaration::alignmember(
-	unsigned salign,	// struct alignment that is in effect
-	unsigned size,		// alignment requirement of field
-	unsigned *poffset)
-{
-    //printf("salign = %d, size = %d, offset = %d\n",salign,size,offset);
-    if (salign > 1)
-    {
-	assert(size != 3);
-	int sa = size;
-	if (sa == 0 || salign < sa)
-	    sa = salign;
-	*poffset = (*poffset + sa - 1) & ~(sa - 1);
-    }
-    //printf("result = %d\n",offset);
-}
-
-
-void AggregateDeclaration::addField(Scope *sc, VarDeclaration *v)
-{
-    unsigned memsize;		// size of member
-    unsigned memalignsize;	// size of member for alignment purposes
-    unsigned xalign;		// alignment boundaries
-
-    //printf("AggregateDeclaration::addField('%s') %s\n", v->toChars(), toChars());
-
-    // Check for forward referenced types which will fail the size() call
-    Type *t = v->type->toBasetype();
-    if (t->ty == Tstruct /*&& isStructDeclaration()*/)
-    {	TypeStruct *ts = (TypeStruct *)t;
-#if V2
-	if (ts->sym == this)
-	{
-	    error("cannot have field %s with same struct type", v->toChars());
-	}
-#endif
-
-	if (ts->sym->sizeok != 1)
-	{
-	    sizeok = 2;		// cannot finish; flag as forward referenced
-	    return;
-	}
-    }
-    if (t->ty == Tident)
-    {
-	sizeok = 2;		// cannot finish; flag as forward referenced
-	return;
-    }
-
-    memsize = v->type->size(loc);
-    memalignsize = v->type->alignsize();
-    xalign = v->type->memalign(sc->structalign);
-    alignmember(xalign, memalignsize, &sc->offset);
-    v->offset = sc->offset;
-    sc->offset += memsize;
-    if (sc->offset > structsize)
-	structsize = sc->offset;
-    if (sc->structalign < memalignsize)
-	memalignsize = sc->structalign;
-    if (alignsize < memalignsize)
-	alignsize = memalignsize;
-    //printf("\talignsize = %d\n", alignsize);
-
-    v->storage_class |= STCfield;
-    //printf(" addField '%s' to '%s' at offset %d, size = %d\n", v->toChars(), toChars(), v->offset, memsize);
-    fields.push(v);
-}
-
-
-/********************************* StructDeclaration ****************************/
-
-StructDeclaration::StructDeclaration(Loc loc, Identifier *id)
-    : AggregateDeclaration(loc, id)
-{
-    zeroInit = 0;	// assume false until we do semantic processing
-#if V2
-    hasIdentityAssign = 0;
-    cpctor = NULL;
-    postblit = NULL;
-#endif
-
-    // For forward references
-    type = new TypeStruct(this);
-}
-
-Dsymbol *StructDeclaration::syntaxCopy(Dsymbol *s)
-{
-    StructDeclaration *sd;
-
-    if (s)
-	sd = (StructDeclaration *)s;
-    else
-	sd = new StructDeclaration(loc, ident);
-    ScopeDsymbol::syntaxCopy(sd);
-    return sd;
-}
-
-void StructDeclaration::semantic(Scope *sc)
-{   int i;
-    Scope *sc2;
-
-    //printf("+StructDeclaration::semantic(this=%p, '%s')\n", this, toChars());
-
-    //static int count; if (++count == 20) *(char*)0=0;
-
-    assert(type);
-    if (!members)			// if forward reference
-	return;
-
-    if (symtab)
-    {   if (!scope)
-            return;             // semantic() already completed
-    }
-    else
-        symtab = new DsymbolTable();
-
-    Scope *scx = NULL;
-    if (scope)
-    {   sc = scope;
-        scx = scope;            // save so we don't make redundant copies
-        scope = NULL;
-    }
-
-    parent = sc->parent;
-#if STRUCTTHISREF
-    handle = type;
-#else
-    handle = type->pointerTo();
-#endif
-    structalign = sc->structalign;
-    protection = sc->protection;
-    if (sc->stc & STCdeprecated)
-	isdeprecated = 1;
-    assert(!isAnonymous());
-    if (sc->stc & STCabstract)
-	error("structs, unions cannot be abstract");
-#if V2
-    if (storage_class & STCinvariant)
-        type = type->invariantOf();
-    else if (storage_class & STCconst)
-        type = type->constOf();
-#endif
-
-    if (sizeok == 0)		// if not already done the addMember step
-    {
-	for (i = 0; i < members->dim; i++)
-	{
-	    Dsymbol *s = (Dsymbol *)members->data[i];
-	    //printf("adding member '%s' to '%s'\n", s->toChars(), this->toChars());
-	    s->addMember(sc, this, 1);
-	}
-    }
-
-    sizeok = 0;
-    sc2 = sc->push(this);
-    sc2->stc = 0;
-    sc2->parent = this;
-    if (isUnionDeclaration())
-	sc2->inunion = 1;
-    sc2->protection = PROTpublic;
-    sc2->explicitProtection = 0;
-
-    int members_dim = members->dim;
-    for (i = 0; i < members_dim; i++)
-    {
-	Dsymbol *s = (Dsymbol *)members->data[i];
-	s->semantic(sc2);
-	if (isUnionDeclaration())
-	    sc2->offset = 0;
-#if 0
-	if (sizeok == 2)
-	{   //printf("forward reference\n");
-	    break;
-	}
-#endif
-    }
-
-    /* The TypeInfo_Struct is expecting an opEquals and opCmp with
-     * a parameter that is a pointer to the struct. But if there
-     * isn't one, but is an opEquals or opCmp with a value, write
-     * another that is a shell around the value:
-     *	int opCmp(struct *p) { return opCmp(*p); }
-     */
-
-    TypeFunction *tfeqptr;
-    {
-	Arguments *arguments = new Arguments;
-	Argument *arg = new Argument(STCin, handle, Id::p, NULL);
-
-	arguments->push(arg);
-	tfeqptr = new TypeFunction(arguments, Type::tint32, 0, LINKd);
-	tfeqptr = (TypeFunction *)tfeqptr->semantic(0, sc);
-    }
-
-    TypeFunction *tfeq;
-    {
-	Arguments *arguments = new Arguments;
-	Argument *arg = new Argument(STCin, type, NULL, NULL);
-
-	arguments->push(arg);
-	tfeq = new TypeFunction(arguments, Type::tint32, 0, LINKd);
-	tfeq = (TypeFunction *)tfeq->semantic(0, sc);
-    }
-
-    Identifier *id = Id::eq;
-    for (int i = 0; i < 2; i++)
-    {
-	Dsymbol *s = search_function(this, id);
-	FuncDeclaration *fdx = s ? s->isFuncDeclaration() : NULL;
-	if (fdx)
-	{   FuncDeclaration *fd = fdx->overloadExactMatch(tfeqptr);
-	    if (!fd)
-	    {	fd = fdx->overloadExactMatch(tfeq);
-		if (fd)
-		{   // Create the thunk, fdptr
-		    FuncDeclaration *fdptr = new FuncDeclaration(loc, loc, fdx->ident, STCundefined, tfeqptr);
-		    Expression *e = new IdentifierExp(loc, Id::p);
-		    e = new PtrExp(loc, e);
-		    Expressions *args = new Expressions();
-		    args->push(e);
-		    e = new IdentifierExp(loc, id);
-		    e = new CallExp(loc, e, args);
-		    fdptr->fbody = new ReturnStatement(loc, e);
-		    ScopeDsymbol *s = fdx->parent->isScopeDsymbol();
-		    assert(s);
-		    s->members->push(fdptr);
-		    fdptr->addMember(sc, s, 1);
-		    fdptr->semantic(sc2);
-		}
-	    }
-	}
-
-	id = Id::cmp;
-    }
-#if V2
-    dtor = buildDtor(sc2);
-    postblit = buildPostBlit(sc2);
-    cpctor = buildCpCtor(sc2);
-    buildOpAssign(sc2);
-#endif
-
-    sc2->pop();
-
-    if (sizeok == 2)
-    {	// semantic() failed because of forward references.
-	// Unwind what we did, and defer it for later
-	fields.setDim(0);
-	structsize = 0;
-	alignsize = 0;
-	structalign = 0;
-
-	scope = scx ? scx : new Scope(*sc);
-	scope->setNoFree();
-	scope->module->addDeferredSemantic(this);
-	//printf("\tdeferring %s\n", toChars());
-	return;
-    }
-
-    // 0 sized struct's are set to 1 byte
-    if (structsize == 0)
-    {
-	structsize = 1;
-	alignsize = 1;
-    }
-
-    // Round struct size up to next alignsize boundary.
-    // This will ensure that arrays of structs will get their internals
-    // aligned properly.
-    structsize = (structsize + alignsize - 1) & ~(alignsize - 1);
-
-    sizeok = 1;
-    Module::dprogress++;
-
-    //printf("-StructDeclaration::semantic(this=%p, '%s')\n", this, toChars());
-
-    // Determine if struct is all zeros or not
-    zeroInit = 1;
-    for (i = 0; i < fields.dim; i++)
-    {
-	Dsymbol *s = (Dsymbol *)fields.data[i];
-	VarDeclaration *vd = s->isVarDeclaration();
-	if (vd && !vd->isDataseg())
-	{
-	    if (vd->init)
-	    {
-		// Should examine init to see if it is really all 0's
-		zeroInit = 0;
-		break;
-	    }
-	    else
-	    {
-		if (!vd->type->isZeroInit())
-		{
-		    zeroInit = 0;
-		    break;
-		}
-	    }
-	}
-    }
-
-    /* Look for special member functions.
-     */
-#if V2
-    ctor =   (CtorDeclaration *)search(0, Id::ctor, 0);
-#endif
-    inv =    (InvariantDeclaration *)search(0, Id::classInvariant, 0);
-    aggNew =       (NewDeclaration *)search(0, Id::classNew,       0);
-    aggDelete = (DeleteDeclaration *)search(0, Id::classDelete,    0);
-
-    if (sc->func)
-    {
-	semantic2(sc);
-	semantic3(sc);
-    }
-}
-
-void StructDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{   int i;
-
-    buf->printf("%s ", kind());
-    if (!isAnonymous())
-	buf->writestring(toChars());
-    if (!members)
-    {
-	buf->writeByte(';');
-	buf->writenl();
-	return;
-    }
-    buf->writenl();
-    buf->writeByte('{');
-    buf->writenl();
-    for (i = 0; i < members->dim; i++)
-    {
-	Dsymbol *s = (Dsymbol *)members->data[i];
-
-	buf->writestring("    ");
-	s->toCBuffer(buf, hgs);
-    }
-    buf->writeByte('}');
-    buf->writenl();
-}
-
-
-const char *StructDeclaration::kind()
-{
-    return "struct";
-}
-
-/********************************* UnionDeclaration ****************************/
-
-UnionDeclaration::UnionDeclaration(Loc loc, Identifier *id)
-    : StructDeclaration(loc, id)
-{
-}
-
-Dsymbol *UnionDeclaration::syntaxCopy(Dsymbol *s)
-{
-    UnionDeclaration *ud;
-
-    if (s)
-	ud = (UnionDeclaration *)s;
-    else
-	ud = new UnionDeclaration(loc, ident);
-    StructDeclaration::syntaxCopy(ud);
-    return ud;
-}
-
-
-const char *UnionDeclaration::kind()
-{
-    return "union";
-}
-
-
+
+// Compiler implementation of the D programming language
+// Copyright (c) 1999-2009 by Digital Mars
+// All Rights Reserved
+// written by Walter Bright
+// http://www.digitalmars.com
+// License for redistribution is by either the Artistic License
+// in artistic.txt, or the GNU General Public License in gnu.txt.
+// See the included readme.txt for details.
+
+#include <stdio.h>
+#include <assert.h>
+
+#include "root.h"
+#include "aggregate.h"
+#include "scope.h"
+#include "mtype.h"
+#include "declaration.h"
+#include "module.h"
+#include "id.h"
+#include "statement.h"
+
+/********************************* AggregateDeclaration ****************************/
+
+AggregateDeclaration::AggregateDeclaration(Loc loc, Identifier *id)
+    : ScopeDsymbol(id)
+{
+    this->loc = loc;
+
+    storage_class = 0;
+    protection = PROTpublic;
+    type = NULL;
+    handle = NULL;
+    structsize = 0;		// size of struct
+    alignsize = 0;		// size of struct for alignment purposes
+    structalign = 0;		// struct member alignment in effect
+    hasUnions = 0;
+    sizeok = 0;			// size not determined yet
+    isdeprecated = 0;
+    inv = NULL;
+    aggNew = NULL;
+    aggDelete = NULL;
+
+#if IN_DMD
+    stag = NULL;
+    sinit = NULL;
+#endif
+    scope = NULL;
+#if DMDV2
+    dtor = NULL;
+
+    ctor = NULL;
+    defaultCtor = NULL;
+#endif
+}
+
+enum PROT AggregateDeclaration::prot()
+{
+    return protection;
+}
+
+void AggregateDeclaration::semantic2(Scope *sc)
+{
+    //printf("AggregateDeclaration::semantic2(%s)\n", toChars());
+    if (scope)
+    {	error("has forward references");
+	return;
+    }
+    if (members)
+    {
+	sc = sc->push(this);
+	for (size_t i = 0; i < members->dim; i++)
+	{
+	    Dsymbol *s = (Dsymbol *)members->data[i];
+	    s->semantic2(sc);
+	}
+	sc->pop();
+    }
+}
+
+void AggregateDeclaration::semantic3(Scope *sc)
+{   int i;
+
+    //printf("AggregateDeclaration::semantic3(%s)\n", toChars());
+    if (members)
+    {
+	sc = sc->push(this);
+	for (i = 0; i < members->dim; i++)
+	{
+	    Dsymbol *s = (Dsymbol *)members->data[i];
+	    s->semantic3(sc);
+	}
+	sc->pop();
+    }
+}
+
+void AggregateDeclaration::inlineScan()
+{   int i;
+
+    //printf("AggregateDeclaration::inlineScan(%s)\n", toChars());
+    if (members)
+    {
+	for (i = 0; i < members->dim; i++)
+	{
+	    Dsymbol *s = (Dsymbol *)members->data[i];
+	    //printf("inline scan aggregate symbol '%s'\n", s->toChars());
+	    s->inlineScan();
+	}
+    }
+}
+
+unsigned AggregateDeclaration::size(Loc loc)
+{
+    //printf("AggregateDeclaration::size() = %d\n", structsize);
+    if (!members)
+	error(loc, "unknown size");
+    if (sizeok != 1)
+    {	error(loc, "no size yet for forward reference");
+	//*(char*)0=0;
+    }
+    return structsize;
+}
+
+Type *AggregateDeclaration::getType()
+{
+    return type;
+}
+
+int AggregateDeclaration::isDeprecated()
+{
+    return isdeprecated;
+}
+
+/****************************
+ * Do byte or word alignment as necessary.
+ * Align sizes of 0, as we may not know array sizes yet.
+ */
+
+void AggregateDeclaration::alignmember(
+	unsigned salign,	// struct alignment that is in effect
+	unsigned size,		// alignment requirement of field
+	unsigned *poffset)
+{
+    //printf("salign = %d, size = %d, offset = %d\n",salign,size,offset);
+    if (salign > 1)
+    {
+	assert(size != 3);
+	int sa = size;
+	if (sa == 0 || salign < sa)
+	    sa = salign;
+	*poffset = (*poffset + sa - 1) & ~(sa - 1);
+    }
+    //printf("result = %d\n",offset);
+}
+
+
+void AggregateDeclaration::addField(Scope *sc, VarDeclaration *v)
+{
+    unsigned memsize;		// size of member
+    unsigned memalignsize;	// size of member for alignment purposes
+    unsigned xalign;		// alignment boundaries
+
+    //printf("AggregateDeclaration::addField('%s') %s\n", v->toChars(), toChars());
+
+    // Check for forward referenced types which will fail the size() call
+    Type *t = v->type->toBasetype();
+    if (t->ty == Tstruct /*&& isStructDeclaration()*/)
+    {	TypeStruct *ts = (TypeStruct *)t;
+#if DMDV2
+	if (ts->sym == this)
+	{
+	    error("cannot have field %s with same struct type", v->toChars());
+	}
+#endif
+
+	if (ts->sym->sizeok != 1)
+	{
+	    sizeok = 2;		// cannot finish; flag as forward referenced
+	    return;
+	}
+    }
+    if (t->ty == Tident)
+    {
+	sizeok = 2;		// cannot finish; flag as forward referenced
+	return;
+    }
+
+    memsize = v->type->size(loc);
+    memalignsize = v->type->alignsize();
+    xalign = v->type->memalign(sc->structalign);
+    alignmember(xalign, memalignsize, &sc->offset);
+    v->offset = sc->offset;
+    sc->offset += memsize;
+    if (sc->offset > structsize)
+	structsize = sc->offset;
+    if (sc->structalign < memalignsize)
+	memalignsize = sc->structalign;
+    if (alignsize < memalignsize)
+	alignsize = memalignsize;
+    //printf("\talignsize = %d\n", alignsize);
+
+    v->storage_class |= STCfield;
+    //printf(" addField '%s' to '%s' at offset %d, size = %d\n", v->toChars(), toChars(), v->offset, memsize);
+    fields.push(v);
+}
+
+
+/********************************* StructDeclaration ****************************/
+
+StructDeclaration::StructDeclaration(Loc loc, Identifier *id)
+    : AggregateDeclaration(loc, id)
+{
+    zeroInit = 0;	// assume false until we do semantic processing
+#if DMDV2
+    hasIdentityAssign = 0;
+    cpctor = NULL;
+    postblit = NULL;
+#endif
+
+    // For forward references
+    type = new TypeStruct(this);
+}
+
+Dsymbol *StructDeclaration::syntaxCopy(Dsymbol *s)
+{
+    StructDeclaration *sd;
+
+    if (s)
+	sd = (StructDeclaration *)s;
+    else
+	sd = new StructDeclaration(loc, ident);
+    ScopeDsymbol::syntaxCopy(sd);
+    return sd;
+}
+
+void StructDeclaration::semantic(Scope *sc)
+{   int i;
+    Scope *sc2;
+
+    //printf("+StructDeclaration::semantic(this=%p, '%s')\n", this, toChars());
+
+    //static int count; if (++count == 20) *(char*)0=0;
+
+    assert(type);
+    if (!members)			// if forward reference
+	return;
+
+    if (symtab)
+    {   if (!scope)
+            return;             // semantic() already completed
+    }
+    else
+        symtab = new DsymbolTable();
+
+    Scope *scx = NULL;
+    if (scope)
+    {   sc = scope;
+        scx = scope;            // save so we don't make redundant copies
+        scope = NULL;
+    }
+
+    parent = sc->parent;
+#if STRUCTTHISREF
+    handle = type;
+#else
+    handle = type->pointerTo();
+#endif
+    structalign = sc->structalign;
+    protection = sc->protection;
+    if (sc->stc & STCdeprecated)
+	isdeprecated = 1;
+    assert(!isAnonymous());
+    if (sc->stc & STCabstract)
+	error("structs, unions cannot be abstract");
+#if DMDV2
+    if (storage_class & STCinvariant)
+        type = type->invariantOf();
+    else if (storage_class & STCconst)
+        type = type->constOf();
+#endif
+
+    if (sizeok == 0)		// if not already done the addMember step
+    {
+	for (i = 0; i < members->dim; i++)
+	{
+	    Dsymbol *s = (Dsymbol *)members->data[i];
+	    //printf("adding member '%s' to '%s'\n", s->toChars(), this->toChars());
+	    s->addMember(sc, this, 1);
+	}
+    }
+
+    sizeok = 0;
+    sc2 = sc->push(this);
+    sc2->stc = 0;
+    sc2->parent = this;
+    if (isUnionDeclaration())
+	sc2->inunion = 1;
+    sc2->protection = PROTpublic;
+    sc2->explicitProtection = 0;
+
+    int members_dim = members->dim;
+    for (i = 0; i < members_dim; i++)
+    {
+	Dsymbol *s = (Dsymbol *)members->data[i];
+	s->semantic(sc2);
+	if (isUnionDeclaration())
+	    sc2->offset = 0;
+#if 0
+	if (sizeok == 2)
+	{   //printf("forward reference\n");
+	    break;
+	}
+#endif
+    }
+
+    /* The TypeInfo_Struct is expecting an opEquals and opCmp with
+     * a parameter that is a pointer to the struct. But if there
+     * isn't one, but is an opEquals or opCmp with a value, write
+     * another that is a shell around the value:
+     *	int opCmp(struct *p) { return opCmp(*p); }
+     */
+
+    TypeFunction *tfeqptr;
+    {
+	Arguments *arguments = new Arguments;
+	Argument *arg = new Argument(STCin, handle, Id::p, NULL);
+
+	arguments->push(arg);
+	tfeqptr = new TypeFunction(arguments, Type::tint32, 0, LINKd);
+	tfeqptr = (TypeFunction *)tfeqptr->semantic(0, sc);
+    }
+
+    TypeFunction *tfeq;
+    {
+	Arguments *arguments = new Arguments;
+	Argument *arg = new Argument(STCin, type, NULL, NULL);
+
+	arguments->push(arg);
+	tfeq = new TypeFunction(arguments, Type::tint32, 0, LINKd);
+	tfeq = (TypeFunction *)tfeq->semantic(0, sc);
+    }
+
+    Identifier *id = Id::eq;
+    for (int i = 0; i < 2; i++)
+    {
+	Dsymbol *s = search_function(this, id);
+	FuncDeclaration *fdx = s ? s->isFuncDeclaration() : NULL;
+	if (fdx)
+	{   FuncDeclaration *fd = fdx->overloadExactMatch(tfeqptr);
+	    if (!fd)
+	    {	fd = fdx->overloadExactMatch(tfeq);
+		if (fd)
+		{   // Create the thunk, fdptr
+		    FuncDeclaration *fdptr = new FuncDeclaration(loc, loc, fdx->ident, STCundefined, tfeqptr);
+		    Expression *e = new IdentifierExp(loc, Id::p);
+		    e = new PtrExp(loc, e);
+		    Expressions *args = new Expressions();
+		    args->push(e);
+		    e = new IdentifierExp(loc, id);
+		    e = new CallExp(loc, e, args);
+		    fdptr->fbody = new ReturnStatement(loc, e);
+		    ScopeDsymbol *s = fdx->parent->isScopeDsymbol();
+		    assert(s);
+		    s->members->push(fdptr);
+		    fdptr->addMember(sc, s, 1);
+		    fdptr->semantic(sc2);
+		}
+	    }
+	}
+
+	id = Id::cmp;
+    }
+#if DMDV2
+    dtor = buildDtor(sc2);
+    postblit = buildPostBlit(sc2);
+    cpctor = buildCpCtor(sc2);
+    buildOpAssign(sc2);
+#endif
+
+    sc2->pop();
+
+    if (sizeok == 2)
+    {	// semantic() failed because of forward references.
+	// Unwind what we did, and defer it for later
+	fields.setDim(0);
+	structsize = 0;
+	alignsize = 0;
+	structalign = 0;
+
+	scope = scx ? scx : new Scope(*sc);
+	scope->setNoFree();
+	scope->module->addDeferredSemantic(this);
+	//printf("\tdeferring %s\n", toChars());
+	return;
+    }
+
+    // 0 sized struct's are set to 1 byte
+    if (structsize == 0)
+    {
+	structsize = 1;
+	alignsize = 1;
+    }
+
+    // Round struct size up to next alignsize boundary.
+    // This will ensure that arrays of structs will get their internals
+    // aligned properly.
+    structsize = (structsize + alignsize - 1) & ~(alignsize - 1);
+
+    sizeok = 1;
+    Module::dprogress++;
+
+    //printf("-StructDeclaration::semantic(this=%p, '%s')\n", this, toChars());
+
+    // Determine if struct is all zeros or not
+    zeroInit = 1;
+    for (i = 0; i < fields.dim; i++)
+    {
+	Dsymbol *s = (Dsymbol *)fields.data[i];
+	VarDeclaration *vd = s->isVarDeclaration();
+	if (vd && !vd->isDataseg())
+	{
+	    if (vd->init)
+	    {
+		// Should examine init to see if it is really all 0's
+		zeroInit = 0;
+		break;
+	    }
+	    else
+	    {
+		if (!vd->type->isZeroInit())
+		{
+		    zeroInit = 0;
+		    break;
+		}
+	    }
+	}
+    }
+
+    /* Look for special member functions.
+     */
+#if DMDV2
+    ctor =   (CtorDeclaration *)search(0, Id::ctor, 0);
+#endif
+    inv =    (InvariantDeclaration *)search(0, Id::classInvariant, 0);
+    aggNew =       (NewDeclaration *)search(0, Id::classNew,       0);
+    aggDelete = (DeleteDeclaration *)search(0, Id::classDelete,    0);
+
+    if (sc->func)
+    {
+	semantic2(sc);
+	semantic3(sc);
+    }
+}
+
+void StructDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{   int i;
+
+    buf->printf("%s ", kind());
+    if (!isAnonymous())
+	buf->writestring(toChars());
+    if (!members)
+    {
+	buf->writeByte(';');
+	buf->writenl();
+	return;
+    }
+    buf->writenl();
+    buf->writeByte('{');
+    buf->writenl();
+    for (i = 0; i < members->dim; i++)
+    {
+	Dsymbol *s = (Dsymbol *)members->data[i];
+
+	buf->writestring("    ");
+	s->toCBuffer(buf, hgs);
+    }
+    buf->writeByte('}');
+    buf->writenl();
+}
+
+
+const char *StructDeclaration::kind()
+{
+    return "struct";
+}
+
+/********************************* UnionDeclaration ****************************/
+
+UnionDeclaration::UnionDeclaration(Loc loc, Identifier *id)
+    : StructDeclaration(loc, id)
+{
+}
+
+Dsymbol *UnionDeclaration::syntaxCopy(Dsymbol *s)
+{
+    UnionDeclaration *ud;
+
+    if (s)
+	ud = (UnionDeclaration *)s;
+    else
+	ud = new UnionDeclaration(loc, ident);
+    StructDeclaration::syntaxCopy(ud);
+    return ud;
+}
+
+
+const char *UnionDeclaration::kind()
+{
+    return "union";
+}
+
+
--- a/dmd/template.c	Fri Apr 03 17:02:52 2009 +0200
+++ b/dmd/template.c	Fri Apr 03 17:59:34 2009 +0200
@@ -14,12 +14,7 @@
 #include <assert.h>
 
 #if !IN_LLVM
-#if _WIN32
-#include <windows.h>
-long __cdecl __ehfilter(LPEXCEPTION_POINTERS ep);
 #endif
-#endif
-
 #include "root.h"
 #include "rmem.h"
 #include "stringtable.h"
@@ -36,6 +31,11 @@
 #include "dsymbol.h"
 #include "hdrgen.h"
 
+#if WINDOWS_SEH
+#include <windows.h>
+long __cdecl __ehfilter(LPEXCEPTION_POINTERS ep);
+#endif
+
 #define LOG	0
 
 /********************************************
@@ -159,6 +159,8 @@
 	    }
 	}
 
+	//printf("t1 = %s\n", t1->toChars());
+	//printf("t2 = %s\n", t2->toChars());
 	if (!t2 || !t1->equals(t2))
 	    goto Lnomatch;
     }
@@ -186,7 +188,7 @@
 	{
 	    goto Lnomatch;
 	}
-#if V2
+#if DMDV2
 	VarDeclaration *v1 = s1->isVarDeclaration();
 	VarDeclaration *v2 = s2->isVarDeclaration();
 	if (v1 && v2 && v1->storage_class & v2->storage_class & STCmanifest)
@@ -263,7 +265,7 @@
     }
 }
 
-#if V2
+#if DMDV2
 Object *objectSyntaxCopy(Object *o)
 {
     if (!o)
@@ -281,7 +283,8 @@
 
 /* ======================== TemplateDeclaration ============================= */
 
-TemplateDeclaration::TemplateDeclaration(Loc loc, Identifier *id, TemplateParameters *parameters, Array *decldefs)
+TemplateDeclaration::TemplateDeclaration(Loc loc, Identifier *id,
+	TemplateParameters *parameters, Expression *constraint, Array *decldefs)
     : ScopeDsymbol(id)
 {
 #if LOG
@@ -303,9 +306,7 @@
     this->loc = loc;
     this->parameters = parameters;
     this->origParameters = parameters;
-#if V2
     this->constraint = constraint;
-#endif
     this->members = decldefs;
     this->overnext = NULL;
     this->overroot = NULL;
@@ -330,13 +331,11 @@
 	    p->data[i] = (void *)tp->syntaxCopy();
 	}
     }
-#if V2
     Expression *e = NULL;
     if (constraint)
 	e = constraint->syntaxCopy();
-#endif
     d = Dsymbol::arraySyntaxCopy(members);
-    td = new TemplateDeclaration(loc, ident, p, d);
+    td = new TemplateDeclaration(loc, ident, p, e, d);
 
 #if IN_LLVM
     // LDC
@@ -673,11 +672,11 @@
 /********************************************
  * Determine partial specialization order of 'this' vs td2.
  * Returns:
- *	1	this is at least as specialized as td2
+ *	match	this is at least as specialized as td2
  *	0	td2 is more specialized than this
  */
 
-int TemplateDeclaration::leastAsSpecialized(TemplateDeclaration *td2)
+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
@@ -715,7 +714,8 @@
     dedtypes.setDim(td2->parameters->dim);
 
     // Attempt a type deduction
-    if (td2->matchWithInstance(&ti, &dedtypes, 1))
+    MATCH m = td2->matchWithInstance(&ti, &dedtypes, 1);
+    if (m)
     {
 	/* A non-variadic template is more specialized than a
 	 * variadic one.
@@ -724,15 +724,15 @@
 	    goto L1;
 
 #if LOG_LEASTAS
-	printf("  matches, so is least as specialized\n");
+	printf("  matches %d, so is least as specialized\n", m);
 #endif
-	return 1;
+	return m;
     }
   L1:
 #if LOG_LEASTAS
     printf("  doesn't match, so is not as specialized\n");
 #endif
-    return 0;
+    return MATCHnomatch;
 }
 
 
@@ -762,7 +762,6 @@
     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
@@ -786,7 +785,18 @@
     paramsym->parent = scope->parent;
     Scope *paramscope = scope->push(paramsym);
 
-    tp = isVariadic();
+    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)
@@ -802,11 +812,11 @@
 
 	memcpy(dedargs->data, targsi->data, nargsi * sizeof(*dedargs->data));
 
-	for (i = 0; i < nargsi; i++)
+	for (size_t i = 0; i < nargsi; i++)
 	{   assert(i < parameters->dim);
 	    TemplateParameter *tp = (TemplateParameter *)parameters->data[i];
 	    MATCH m;
-	    Declaration *sparam;
+	    Declaration *sparam = NULL;
 
 	    m = tp->matchArg(paramscope, dedargs, i, parameters, &dedtypes, &sparam);
 	    //printf("\tdeduceType m = %d\n", m);
@@ -820,6 +830,15 @@
 		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
 
     assert(fd->type->ty == Tfunction);
     fdtype = (TypeFunction *)fd->type;
@@ -833,7 +852,6 @@
      * template Foo(T, A...) { void Foo(T t, A a); }
      * void main() { Foo(1,2,3); }
      */
-    tp = isVariadic();
     if (tp)				// if variadic
     {
 	if (nfparams == 0)		// if no function parameters
@@ -906,7 +924,7 @@
 	    {	MATCH m;
 
 		Type *t = new TypeIdentifier(0, ttp->ident);
-		m = ethis->type->deduceType(scope, t, parameters, &dedtypes);
+		m = ethis->type->deduceType(paramscope, t, parameters, &dedtypes);
 		if (!m)
 		    goto Lnomatch;
 		if (m < match)
@@ -946,9 +964,25 @@
 	    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 = farg->type->deduceType(scope, fparam->type, parameters, &dedtypes);
+	    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
@@ -960,7 +994,7 @@
 
 		if (!tf->varargs && Argument::dim(tf->parameters) == 0)
 		{
-		    m = farg->type->deduceType(scope, tf->next, parameters, &dedtypes);
+		    m = farg->type->deduceType(paramscope, tf->next, parameters, &dedtypes);
 		    if (!m && tf->next->toBasetype()->ty == Tvoid)
 			m = MATCHconvert;
 		}
@@ -988,7 +1022,7 @@
 	    // Perhaps we can do better with this, see TypeFunction::callMatch()
 	    case Tsarray:
 	    {	TypeSArray *tsa = (TypeSArray *)tb;
-		integer_t sz = tsa->dim->toInteger();
+		dinteger_t sz = tsa->dim->toInteger();
 		if (sz != nfargs - i)
 		    goto Lnomatch;
 	    }
@@ -1020,7 +1054,7 @@
 		    }
 		    else
 		    {
-			m = arg->type->deduceType(scope, ta->next, parameters, &dedtypes);
+			m = arg->type->deduceType(paramscope, ta->next, parameters, &dedtypes);
 			//m = arg->implicitConvTo(ta->next);
 		    }
 		    if (m == MATCHnomatch)
@@ -1053,6 +1087,8 @@
 	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)
@@ -1134,6 +1170,22 @@
 
     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());
@@ -1267,8 +1319,8 @@
 
 	{
 	// Disambiguate by picking the most specialized TemplateDeclaration
-	int c1 = td->leastAsSpecialized(td_best);
-	int c2 = td_best->leastAsSpecialized(td);
+	MATCH c1 = td->leastAsSpecialized(td_best);
+	MATCH c2 = td_best->leastAsSpecialized(td);
 	//printf("c1 = %d, c2 = %d\n", c1, c2);
 
 	if (c1 > c2)
@@ -1298,7 +1350,7 @@
     }
     if (!td_best)
     {
-	error(loc, "does not match any template declaration");
+	error(loc, "does not match any function template declaration");
 	goto Lerror;
     }
     if (td_ambig)
@@ -1319,6 +1371,9 @@
     return fd;
 
   Lerror:
+#if DMDV2
+    if (!(flags & 1))
+#endif
     {
 	HdrGenState hgs;
 
@@ -1537,8 +1592,29 @@
 
 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)
 {
@@ -1765,8 +1841,11 @@
 	Type *tparam, TemplateParameters *parameters,
 	Objects *dedtypes)
 {
-    //printf("TypeInstance::deduceType(tparam = %s) %s\n", tparam->toChars(), toChars());
-    //printf("\ttparam = %d, ", tparam->ty); tparam->print();
+#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)
@@ -1802,14 +1881,14 @@
 		TemplateAliasParameter *ta = tpx->isTemplateAliasParameter();
 		if (!ta)
 		    goto Lnomatch;
-		Dsymbol *sa = tempinst->tempdecl;
+		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
-		    Dsymbol *s = (Dsymbol *)dedtypes->data[i];
+		    Object *s = (Object *)dedtypes->data[i];
 
 		    if (s != sa)
 			goto Lnomatch;
@@ -1821,12 +1900,13 @@
 	    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);
+	    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];
@@ -1853,6 +1933,43 @@
 	    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))
@@ -3299,12 +3416,10 @@
     sc2->parent = /*isnested ? sc->parent :*/ this;
     sc2->tinst = this;
 
-#if !IN_LLVM    
-#if _WIN32
+#if WINDOWS_SEH
   __try
   {
 #endif
-#endif
     for (int i = 0; i < members->dim; i++)
     {
 	Dsymbol *s = (Dsymbol *)members->data[i];
@@ -3317,8 +3432,7 @@
 	//printf("test4: isnested = %d, s->parent = %s\n", isnested, s->parent->toChars());
 	sc2->module->runDeferredSemantic();
     }
-#if !IN_LLVM    
-#if _WIN32
+#if WINDOWS_SEH
   }
   __except (__ehfilter(GetExceptionInformation()))
   {
@@ -3327,7 +3441,6 @@
     fatal();
   }
 #endif
-#endif
 
     /* If any of the instantiation members didn't get semantic() run
      * on them due to forward references, we cannot run semantic2()
@@ -3385,10 +3498,15 @@
     if (semantictiargsdone)
 	return;
     semantictiargsdone = 1;
-    semanticTiargs(loc, sc, tiargs);
+    semanticTiargs(loc, sc, tiargs, 0);
 }
 
-void TemplateInstance::semanticTiargs(Loc loc, Scope *sc, Objects *tiargs)
+/**********************************
+ * 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());
@@ -3636,8 +3754,8 @@
 
 	{
 	// Disambiguate by picking the most specialized TemplateDeclaration
-	int c1 = td->leastAsSpecialized(td_best);
-	int c2 = td_best->leastAsSpecialized(td);
+	MATCH c1 = td->leastAsSpecialized(td_best);
+	MATCH c2 = td_best->leastAsSpecialized(td);
 	//printf("c1 = %d, c2 = %d\n", c1, c2);
 
 	if (c1 > c2)
@@ -3667,7 +3785,11 @@
 
     if (!td_best)
     {
-	error("%s does not match any template declaration", toChars());
+	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)
@@ -3777,7 +3899,7 @@
 		    nested |= 1;
 		}
 		else
-		    error("cannot use local '%s' as template parameter", d->toChars());
+		    error("cannot use local '%s' as parameter to non-global template %s", d->toChars(), tempdecl->toChars());
 	    }
 	}
 	else if (va)
--- a/dmd/template.h	Fri Apr 03 17:02:52 2009 +0200
+++ b/dmd/template.h	Fri Apr 03 17:59:34 2009 +0200
@@ -54,9 +54,7 @@
     TemplateParameters *parameters;	// array of TemplateParameter's
 
     TemplateParameters *origParameters;	// originals for Ddoc
-#if DMDV2
     Expression *constraint;
-#endif
     Array instances;			// array of TemplateInstance's
 
     TemplateDeclaration *overnext;	// next overloaded TemplateDeclaration
@@ -66,10 +64,7 @@
     Dsymbol *onemember;		// if !=NULL then one member of this template
 
     TemplateDeclaration(Loc loc, Identifier *id, TemplateParameters *parameters,
-#if DMDV2
-	Expression *constraint,
-#endif
-	Array *decldefs);
+	Expression *constraint, Array *decldefs);
     Dsymbol *syntaxCopy(Dsymbol *);
     void semantic(Scope *sc);
     int overloadInsert(Dsymbol *s);
@@ -81,7 +76,7 @@
 //    void toDocBuffer(OutBuffer *buf);
 
     MATCH matchWithInstance(TemplateInstance *ti, Objects *atypes, int flag);
-    int leastAsSpecialized(TemplateDeclaration *td2);
+    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);
@@ -108,6 +103,8 @@
      *	template Foo(valType ident : specValue)
      * For alias-parameter:
      *	template Foo(alias ident)
+     * For this-parameter:
+     *	template Foo(this ident)
      */
 
     Loc loc;
@@ -216,7 +213,7 @@
 struct TemplateAliasParameter : TemplateParameter
 {
     /* Syntax:
-     *	ident : specAlias = defaultAlias
+     *	specType ident : specAlias = defaultAlias
      */
 
     Type *specAliasT;
@@ -317,7 +314,7 @@
 #endif
 
     // Internal
-    static void semanticTiargs(Loc loc, Scope *sc, Objects *tiargs);
+    static void semanticTiargs(Loc loc, Scope *sc, Objects *tiargs, int flags);
     void semanticTiargs(Scope *sc);
     TemplateDeclaration *findTemplateDeclaration(Scope *sc);
     TemplateDeclaration *findBestMatch(Scope *sc);