changeset 510:6aee82889553

Merged DMD 1.034, array operations are not yet implemented ;)
author Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
date Thu, 14 Aug 2008 06:55:41 +0200
parents 337554fd34f1
children a0b0676e787d
files dmd/arrayop.c dmd/cast.c dmd/doc.c dmd/expression.c dmd/expression.h dmd/func.c dmd/identifier.c dmd/identifier.h dmd/mars.c dmd/module.c dmd/statement.c dmd/statement.h llvmdc.kdevelop.filelist
diffstat 13 files changed, 1151 insertions(+), 175 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/arrayop.c	Thu Aug 14 06:55:41 2008 +0200
@@ -0,0 +1,505 @@
+
+// Copyright (c) 1999-2008 by Digital Mars
+// All Rights Reserved
+// written by Walter Bright
+// http://www.digitalmars.com
+// License for redistribution is by either the Artistic License
+// in artistic.txt, or the GNU General Public License in gnu.txt.
+// See the included readme.txt for details.
+
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+
+#if _WIN32 || IN_GCC  || IN_LLVM
+#include "mem.h"
+#else
+#include "../root/mem.h"
+#endif
+
+#include "stringtable.h"
+
+#include "expression.h"
+#include "statement.h"
+#include "mtype.h"
+#include "declaration.h"
+#include "scope.h"
+#include "id.h"
+#include "module.h"
+#include "init.h"
+
+// FIXME
+int binary(const char *p , const char **tab, int high)
+{
+    assert(0);
+}
+
+/**************************************
+ * Hash table of array op functions already generated or known about.
+ */
+
+StringTable arrayfuncs;
+
+/***********************************
+ * Construct the array operation expression.
+ */
+
+Expression *BinExp::arrayOp(Scope *sc)
+{
+    // FIXME
+    error("array operations not yet implemented");
+    fatal();
+
+    Expressions *arguments = new Expressions();
+
+    /* The expression to generate an array operation for is mangled
+     * into a name to use as the array operation function name.
+     * Mangle in the operands and operators in RPN order, and type.
+     */
+    OutBuffer buf;
+    buf.writestring("_array");
+    buildArrayIdent(&buf, arguments);
+    buf.writeByte('_');
+
+    /* Append deco of array element type
+     */
+#if DMDV2
+    buf.writestring(type->toBasetype()->nextOf()->toBasetype()->mutableOf()->deco);
+#else
+    buf.writestring(type->toBasetype()->nextOf()->toBasetype()->deco);
+#endif
+
+    size_t namelen = buf.offset;
+    buf.writeByte(0);
+    char *name = (char *)buf.extractData();
+
+    /* Look up name in hash table
+     */
+    StringValue *sv = arrayfuncs.update(name, namelen);
+    FuncDeclaration *fd = (FuncDeclaration *)sv->ptrvalue;
+    if (!fd)
+    {
+	/* Some of the array op functions are written as library functions,
+	 * presumably to optimize them with special CPU vector instructions.
+	 * List those library functions here, in alpha order.
+	 */
+	static const char *libArrayopFuncs[] =
+	{
+	    "_arrayExpSliceAddass_a",
+	    "_arrayExpSliceAddass_d",		// T[]+=T
+	    "_arrayExpSliceAddass_f",		// T[]+=T
+	    "_arrayExpSliceAddass_g",
+	    "_arrayExpSliceAddass_h",
+	    "_arrayExpSliceAddass_i",
+	    "_arrayExpSliceAddass_k",
+	    "_arrayExpSliceAddass_s",
+	    "_arrayExpSliceAddass_t",
+	    "_arrayExpSliceAddass_u",
+	    "_arrayExpSliceAddass_w",
+
+	    "_arrayExpSliceDivass_d",		// T[]/=T
+	    "_arrayExpSliceDivass_f",		// T[]/=T
+
+	    "_arrayExpSliceMinSliceAssign_a",
+	    "_arrayExpSliceMinSliceAssign_d",	// T[]=T-T[]
+	    "_arrayExpSliceMinSliceAssign_f",	// T[]=T-T[]
+	    "_arrayExpSliceMinSliceAssign_g",
+	    "_arrayExpSliceMinSliceAssign_h",
+	    "_arrayExpSliceMinSliceAssign_i",
+	    "_arrayExpSliceMinSliceAssign_k",
+	    "_arrayExpSliceMinSliceAssign_s",
+	    "_arrayExpSliceMinSliceAssign_t",
+	    "_arrayExpSliceMinSliceAssign_u",
+	    "_arrayExpSliceMinSliceAssign_w",
+
+	    "_arrayExpSliceMinass_a",
+	    "_arrayExpSliceMinass_d",		// T[]-=T
+	    "_arrayExpSliceMinass_f",		// T[]-=T
+	    "_arrayExpSliceMinass_g",
+	    "_arrayExpSliceMinass_h",
+	    "_arrayExpSliceMinass_i",
+	    "_arrayExpSliceMinass_k",
+	    "_arrayExpSliceMinass_s",
+	    "_arrayExpSliceMinass_t",
+	    "_arrayExpSliceMinass_u",
+	    "_arrayExpSliceMinass_w",
+
+	    "_arrayExpSliceMulass_d",		// T[]*=T
+	    "_arrayExpSliceMulass_f",		// T[]*=T
+	    "_arrayExpSliceMulass_i",
+	    "_arrayExpSliceMulass_k",
+	    "_arrayExpSliceMulass_s",
+	    "_arrayExpSliceMulass_t",
+	    "_arrayExpSliceMulass_u",
+	    "_arrayExpSliceMulass_w",
+
+	    "_arraySliceExpAddSliceAssign_a",
+	    "_arraySliceExpAddSliceAssign_d",	// T[]=T[]+T
+	    "_arraySliceExpAddSliceAssign_f",	// T[]=T[]+T
+	    "_arraySliceExpAddSliceAssign_g",
+	    "_arraySliceExpAddSliceAssign_h",
+	    "_arraySliceExpAddSliceAssign_i",
+	    "_arraySliceExpAddSliceAssign_k",
+	    "_arraySliceExpAddSliceAssign_s",
+	    "_arraySliceExpAddSliceAssign_t",
+	    "_arraySliceExpAddSliceAssign_u",
+	    "_arraySliceExpAddSliceAssign_w",
+
+	    "_arraySliceExpDivSliceAssign_d",	// T[]=T[]/T
+	    "_arraySliceExpDivSliceAssign_f",	// T[]=T[]/T
+
+	    "_arraySliceExpMinSliceAssign_a",
+	    "_arraySliceExpMinSliceAssign_d",	// T[]=T[]-T
+	    "_arraySliceExpMinSliceAssign_f",	// T[]=T[]-T
+	    "_arraySliceExpMinSliceAssign_g",
+	    "_arraySliceExpMinSliceAssign_h",
+	    "_arraySliceExpMinSliceAssign_i",
+	    "_arraySliceExpMinSliceAssign_k",
+	    "_arraySliceExpMinSliceAssign_s",
+	    "_arraySliceExpMinSliceAssign_t",
+	    "_arraySliceExpMinSliceAssign_u",
+	    "_arraySliceExpMinSliceAssign_w",
+
+	    "_arraySliceExpMulSliceAddass_d",	// T[] += T[]*T
+	    "_arraySliceExpMulSliceAddass_f",
+	    "_arraySliceExpMulSliceAddass_r",
+
+	    "_arraySliceExpMulSliceAssign_d",	// T[]=T[]*T
+	    "_arraySliceExpMulSliceAssign_f",	// T[]=T[]*T
+	    "_arraySliceExpMulSliceAssign_i",
+	    "_arraySliceExpMulSliceAssign_k",
+	    "_arraySliceExpMulSliceAssign_s",
+	    "_arraySliceExpMulSliceAssign_t",
+	    "_arraySliceExpMulSliceAssign_u",
+	    "_arraySliceExpMulSliceAssign_w",
+
+	    "_arraySliceExpMulSliceMinass_d",	// T[] -= T[]*T
+	    "_arraySliceExpMulSliceMinass_f",
+	    "_arraySliceExpMulSliceMinass_r",
+
+	    "_arraySliceSliceAddSliceAssign_a",
+	    "_arraySliceSliceAddSliceAssign_d",	// T[]=T[]+T[]
+	    "_arraySliceSliceAddSliceAssign_f",	// T[]=T[]+T[]
+	    "_arraySliceSliceAddSliceAssign_g",
+	    "_arraySliceSliceAddSliceAssign_h",
+	    "_arraySliceSliceAddSliceAssign_i",
+	    "_arraySliceSliceAddSliceAssign_k",
+	    "_arraySliceSliceAddSliceAssign_r",	// T[]=T[]+T[]
+	    "_arraySliceSliceAddSliceAssign_s",
+	    "_arraySliceSliceAddSliceAssign_t",
+	    "_arraySliceSliceAddSliceAssign_u",
+	    "_arraySliceSliceAddSliceAssign_w",
+
+	    "_arraySliceSliceAddass_a",
+	    "_arraySliceSliceAddass_d",		// T[]+=T[]
+	    "_arraySliceSliceAddass_f",		// T[]+=T[]
+	    "_arraySliceSliceAddass_g",
+	    "_arraySliceSliceAddass_h",
+	    "_arraySliceSliceAddass_i",
+	    "_arraySliceSliceAddass_k",
+	    "_arraySliceSliceAddass_s",
+	    "_arraySliceSliceAddass_t",
+	    "_arraySliceSliceAddass_u",
+	    "_arraySliceSliceAddass_w",
+
+	    "_arraySliceSliceMinSliceAssign_a",
+	    "_arraySliceSliceMinSliceAssign_d",	// T[]=T[]-T[]
+	    "_arraySliceSliceMinSliceAssign_f",	// T[]=T[]-T[]
+	    "_arraySliceSliceMinSliceAssign_g",
+	    "_arraySliceSliceMinSliceAssign_h",
+	    "_arraySliceSliceMinSliceAssign_i",
+	    "_arraySliceSliceMinSliceAssign_k",
+	    "_arraySliceSliceMinSliceAssign_r",	// T[]=T[]-T[]
+	    "_arraySliceSliceMinSliceAssign_s",
+	    "_arraySliceSliceMinSliceAssign_t",
+	    "_arraySliceSliceMinSliceAssign_u",
+	    "_arraySliceSliceMinSliceAssign_w",
+
+	    "_arraySliceSliceMinass_a",
+	    "_arraySliceSliceMinass_d",		// T[]-=T[]
+	    "_arraySliceSliceMinass_f",		// T[]-=T[]
+	    "_arraySliceSliceMinass_g",
+	    "_arraySliceSliceMinass_h",
+	    "_arraySliceSliceMinass_i",
+	    "_arraySliceSliceMinass_k",
+	    "_arraySliceSliceMinass_s",
+	    "_arraySliceSliceMinass_t",
+	    "_arraySliceSliceMinass_u",
+	    "_arraySliceSliceMinass_w",
+
+	    "_arraySliceSliceMulSliceAssign_d",	// T[]=T[]*T[]
+	    "_arraySliceSliceMulSliceAssign_f",	// T[]=T[]*T[]
+	    "_arraySliceSliceMulSliceAssign_i",
+	    "_arraySliceSliceMulSliceAssign_k",
+	    "_arraySliceSliceMulSliceAssign_s",
+	    "_arraySliceSliceMulSliceAssign_t",
+	    "_arraySliceSliceMulSliceAssign_u",
+	    "_arraySliceSliceMulSliceAssign_w",
+
+	    "_arraySliceSliceMulass_d",		// T[]*=T[]
+	    "_arraySliceSliceMulass_f",		// T[]*=T[]
+	    "_arraySliceSliceMulass_i",
+	    "_arraySliceSliceMulass_k",
+	    "_arraySliceSliceMulass_s",
+	    "_arraySliceSliceMulass_t",
+	    "_arraySliceSliceMulass_u",
+	    "_arraySliceSliceMulass_w",
+	};
+
+	int i = binary(name, libArrayopFuncs, sizeof(libArrayopFuncs) / sizeof(char *));
+	if (i == -1)
+	{
+#ifdef DEBUG	// Make sure our array is alphabetized
+	    for (i = 0; i < sizeof(libArrayopFuncs) / sizeof(char *); i++)
+	    {
+		if (strcmp(name, libArrayopFuncs[i]) == 0)
+		    assert(0);
+	    }
+#endif
+	    /* Not in library, so generate it.
+	     * Construct the function body:
+	     *	foreach (i; 0 .. p.length)    for (size_t i = 0; i < p.length; i++)
+	     *	    loopbody;
+	     *	return p;
+	     */
+
+	    Arguments *fparams = new Arguments();
+	    Expression *loopbody = buildArrayLoop(fparams);
+	    Argument *p = (Argument *)fparams->data[0 /*fparams->dim - 1*/];
+#if DMDV1
+	    // for (size_t i = 0; i < p.length; i++)
+	    Initializer *init = new ExpInitializer(0, new IntegerExp(0, 0, Type::tsize_t));
+	    Dsymbol *d = new VarDeclaration(0, Type::tsize_t, Id::p, init);
+	    Statement *s1 = new ForStatement(0,
+		new DeclarationStatement(0, d),
+		new CmpExp(TOKlt, 0, new IdentifierExp(0, Id::p), new ArrayLengthExp(0, new IdentifierExp(0, p->ident))),
+		new PostExp(TOKplusplus, 0, new IdentifierExp(0, Id::p)),
+		new ExpStatement(0, loopbody));
+#else
+	    // foreach (i; 0 .. p.length)
+	    Statement *s1 = new ForeachRangeStatement(0, TOKforeach,
+		new Argument(0, NULL, Id::p, NULL),
+		new IntegerExp(0, 0, Type::tint32),
+		new ArrayLengthExp(0, new IdentifierExp(0, p->ident)),
+		new ExpStatement(0, loopbody));
+#endif
+	    Statement *s2 = new ReturnStatement(0, new IdentifierExp(0, p->ident));
+	    //printf("s2: %s\n", s2->toChars());
+	    Statement *fbody = new CompoundStatement(0, s1, s2);
+
+	    /* Construct the function
+	     */
+	    TypeFunction *ftype = new TypeFunction(fparams, type, 0, LINKc);
+	    //printf("ftype: %s\n", ftype->toChars());
+	    fd = new FuncDeclaration(0, 0, Lexer::idPool(name), STCundefined, ftype);
+	    fd->fbody = fbody;
+	    fd->protection = PROTpublic;
+	    fd->linkage = LINKc;
+
+	    sc->module->importedFrom->members->push(fd);
+
+	    sc = sc->push();
+	    sc->parent = sc->module->importedFrom;
+	    sc->stc = 0;
+	    sc->linkage = LINKc;
+	    fd->semantic(sc);
+	    sc->pop();
+	}
+	else
+	{   /* In library, refer to it.
+	     */
+        // LLVMDC FIXME   
+	    fd = FuncDeclaration::genCfunc(NULL, type, name);
+	}
+	sv->ptrvalue = fd;	// cache symbol in hash table
+    }
+
+    /* Call the function fd(arguments)
+     */
+    Expression *ec = new VarExp(0, fd);
+    Expression *e = new CallExp(loc, ec, arguments);
+    e->type = type;
+    return e;
+}
+
+/******************************************
+ * Construct the identifier for the array operation function,
+ * and build the argument list to pass to it.
+ */
+
+void Expression::buildArrayIdent(OutBuffer *buf, Expressions *arguments)
+{
+    buf->writestring("Exp");
+    arguments->shift(this);
+}
+
+void SliceExp::buildArrayIdent(OutBuffer *buf, Expressions *arguments)
+{
+    buf->writestring("Slice");
+    arguments->shift(this);
+}
+
+void AssignExp::buildArrayIdent(OutBuffer *buf, Expressions *arguments)
+{
+    /* Evaluate assign expressions right to left
+     */
+    e2->buildArrayIdent(buf, arguments);
+    e1->buildArrayIdent(buf, arguments);
+    buf->writestring("Assign");
+}
+
+#define X(Str) \
+void Str##AssignExp::buildArrayIdent(OutBuffer *buf, Expressions *arguments) \
+{							\
+    /* Evaluate assign expressions right to left	\
+     */							\
+    e2->buildArrayIdent(buf, arguments);		\
+    e1->buildArrayIdent(buf, arguments);		\
+    buf->writestring(#Str);				\
+    buf->writestring("ass");				\
+}
+
+X(Add)
+X(Min)
+X(Mul)
+X(Div)
+X(Mod)
+X(Xor)
+X(And)
+X(Or)
+
+#undef X
+
+void NegExp::buildArrayIdent(OutBuffer *buf, Expressions *arguments)
+{
+    e1->buildArrayIdent(buf, arguments);
+    buf->writestring("Neg");
+}
+
+void ComExp::buildArrayIdent(OutBuffer *buf, Expressions *arguments)
+{
+    e1->buildArrayIdent(buf, arguments);
+    buf->writestring("Com");
+}
+
+#define X(Str) \
+void Str##Exp::buildArrayIdent(OutBuffer *buf, Expressions *arguments)	\
+{									\
+    /* Evaluate assign expressions left to right			\
+     */									\
+    e1->buildArrayIdent(buf, arguments);				\
+    e2->buildArrayIdent(buf, arguments);				\
+    buf->writestring(#Str);						\
+}
+
+X(Add)
+X(Min)
+X(Mul)
+X(Div)
+X(Mod)
+X(Xor)
+X(And)
+X(Or)
+
+#undef X
+
+/******************************************
+ * Construct the inner loop for the array operation function,
+ * and build the parameter list.
+ */
+
+Expression *Expression::buildArrayLoop(Arguments *fparams)
+{
+    Identifier *id = Identifier::generateId("c", fparams->dim);
+    Argument *param = new Argument(0, type, id, NULL);
+    fparams->shift(param);
+    Expression *e = new IdentifierExp(0, id);
+    return e;
+}
+
+Expression *SliceExp::buildArrayLoop(Arguments *fparams)
+{
+    Identifier *id = Identifier::generateId("p", fparams->dim);
+    Argument *param = new Argument(STCconst, type, id, NULL);
+    fparams->shift(param);
+    Expression *e = new IdentifierExp(0, id);
+    Expressions *arguments = new Expressions();
+    Expression *index = new IdentifierExp(0, Id::p);
+    arguments->push(index);
+    e = new ArrayExp(0, e, arguments);
+    return e;
+}
+
+Expression *AssignExp::buildArrayLoop(Arguments *fparams)
+{
+    /* Evaluate assign expressions right to left
+     */
+    Expression *ex2 = e2->buildArrayLoop(fparams);
+    Expression *ex1 = e1->buildArrayLoop(fparams);
+    Argument *param = (Argument *)fparams->data[0];
+    param->storageClass = 0;
+    Expression *e = new AssignExp(0, ex1, ex2);
+    return e;
+}
+
+#define X(Str) \
+Expression *Str##AssignExp::buildArrayLoop(Arguments *fparams)	\
+{								\
+    /* Evaluate assign expressions right to left		\
+     */								\
+    Expression *ex2 = e2->buildArrayLoop(fparams);		\
+    Expression *ex1 = e1->buildArrayLoop(fparams);		\
+    Argument *param = (Argument *)fparams->data[0];		\
+    param->storageClass = 0;					\
+    Expression *e = new Str##AssignExp(0, ex1, ex2);		\
+    return e;							\
+}
+
+X(Add)
+X(Min)
+X(Mul)
+X(Div)
+X(Mod)
+X(Xor)
+X(And)
+X(Or)
+
+#undef X
+
+Expression *NegExp::buildArrayLoop(Arguments *fparams)
+{
+    Expression *ex1 = e1->buildArrayLoop(fparams);
+    Expression *e = new NegExp(0, ex1);
+    return e;
+}
+
+Expression *ComExp::buildArrayLoop(Arguments *fparams)
+{
+    Expression *ex1 = e1->buildArrayLoop(fparams);
+    Expression *e = new ComExp(0, ex1);
+    return e;
+}
+
+#define X(Str) \
+Expression *Str##Exp::buildArrayLoop(Arguments *fparams)	\
+{								\
+    /* Evaluate assign expressions left to right		\
+     */								\
+    Expression *ex1 = e1->buildArrayLoop(fparams);		\
+    Expression *ex2 = e2->buildArrayLoop(fparams);		\
+    Expression *e = new Str##Exp(0, ex1, ex2);			\
+    return e;							\
+}
+
+X(Add)
+X(Min)
+X(Mul)
+X(Div)
+X(Mod)
+X(Xor)
+X(And)
+X(Or)
+
+#undef X
+
+
--- a/dmd/cast.c	Thu Aug 14 03:09:26 2008 +0200
+++ b/dmd/cast.c	Thu Aug 14 06:55:41 2008 +0200
@@ -46,6 +46,14 @@
 	    warning("%s: implicit conversion of expression (%s) of type %s to %s can cause loss of data",
 		loc.toChars(), toChars(), type->toChars(), t->toChars());
 	}
+#if DMDV2
+	if (match == MATCHconst && t == type->constOf())
+	{
+	    Expression *e = copy();
+	    e->type = t;
+	    return e;
+	}
+#endif
 	return castTo(sc, t);
     }
 
@@ -54,12 +62,13 @@
 	return e->implicitCastTo(sc, t);
 
 #if 0
+printf("ty = %d\n", type->ty);
 print();
 type->print();
 printf("to:\n");
 t->print();
 printf("%p %p type: %s to: %s\n", type->deco, t->deco, type->deco, t->deco);
-//printf("%p %p %p\n", type->next->arrayOf(), type, t);
+//printf("%p %p %p\n", type->nextOf()->arrayOf(), type, t);
 fflush(stdout);
 #endif
     if (!t->deco)
@@ -92,6 +101,7 @@
     printf("Expression::implicitConvTo(this=%s, type=%s, t=%s)\n",
 	toChars(), type->toChars(), t->toChars());
 #endif
+    //static int nest; if (++nest == 10) halt();
     if (!type)
     {	error("%s is not an expression", toChars());
 	type = Type::terror;
@@ -110,16 +120,16 @@
     Type *tb = t->toBasetype();
     if (tb->ty == Tdelegate)
     {	TypeDelegate *td = (TypeDelegate *)tb;
-	TypeFunction *tf = (TypeFunction *)td->next;
+	TypeFunction *tf = (TypeFunction *)td->nextOf();
 
 	if (!tf->varargs &&
 	    !(tf->arguments && tf->arguments->dim)
 	   )
 	{
-	    match = type->implicitConvTo(tf->next);
+	    match = type->implicitConvTo(tf->nextOf());
 	    if (match)
 		return match;
-	    if (tf->next->toBasetype()->ty == Tvoid)
+	    if (tf->nextOf()->toBasetype()->ty == Tvoid)
 		return MATCHconvert;
 	}
     }
@@ -332,6 +342,39 @@
     return Expression::implicitConvTo(t);
 }
 
+#if DMDV2
+MATCH StructLiteralExp::implicitConvTo(Type *t)
+{
+#if 0
+    printf("StructLiteralExp::implicitConvTo(this=%s, type=%s, t=%s)\n",
+	toChars(), type->toChars(), t->toChars());
+#endif
+    MATCH m = Expression::implicitConvTo(t);
+    if (m != MATCHnomatch)
+	return m;
+    if (type->ty == t->ty && type->ty == Tstruct &&
+	((TypeStruct *)type)->sym == ((TypeStruct *)t)->sym)
+    {
+	m = MATCHconst;
+	for (int i = 0; i < elements->dim; i++)
+	{   Expression *e = (Expression *)elements->data[i];
+	    Type *te = e->type;
+	    if (t->mod == 0)
+		te = te->mutableOf();
+	    else
+	    {	assert(t->mod == MODinvariant);
+		te = te->invariantOf();
+	    }
+	    MATCH m2 = e->implicitConvTo(te);
+	    //printf("\t%s => %s, match = %d\n", e->toChars(), te->toChars(), m2);
+	    if (m2 < m)
+		m = m2;
+	}
+    }
+    return m;
+}
+#endif
+
 MATCH StringExp::implicitConvTo(Type *t)
 {   MATCH m;
 
@@ -387,6 +430,10 @@
 MATCH ArrayLiteralExp::implicitConvTo(Type *t)
 {   MATCH result = MATCHexact;
 
+#if 0
+    printf("ArrayLiteralExp::implicitConvTo(this=%s, type=%s, t=%s)\n",
+	toChars(), type->toChars(), t->toChars());
+#endif
     Type *typeb = type->toBasetype();
     Type *tb = t->toBasetype();
     if ((tb->ty == Tarray || tb->ty == Tsarray) &&
@@ -400,7 +447,7 @@
 
 	for (int i = 0; i < elements->dim; i++)
 	{   Expression *e = (Expression *)elements->data[i];
-	    MATCH m = (MATCH)e->implicitConvTo(tb->next);
+	    MATCH m = (MATCH)e->implicitConvTo(tb->nextOf());
 	    if (m < result)
 		result = m;			// remember worst match
 	    if (result == MATCHnomatch)
@@ -427,7 +474,7 @@
 	    if (result == MATCHnomatch)
 		break;				// no need to check for worse
 	    e = (Expression *)values->data[i];
-	    m = (MATCH)e->implicitConvTo(tb->next);
+	    m = (MATCH)e->implicitConvTo(tb->nextOf());
 	    if (m < result)
 		result = m;			// remember worst match
 	    if (result == MATCHnomatch)
@@ -516,10 +563,10 @@
 	FuncDeclaration *f;
 
 	t = t->toBasetype();
-	if (type->ty == Tdelegate && type->next->ty == Tfunction &&
-	    t->ty == Tdelegate && t->next->ty == Tfunction)
+	if (type->ty == Tdelegate && type->nextOf()->ty == Tfunction &&
+	    t->ty == Tdelegate && t->nextOf()->ty == Tfunction)
 	{
-	    if (func && func->overloadExactMatch(t->next))
+	    if (func && func->overloadExactMatch(t->nextOf()))
 		result = MATCHexact;
 	}
     }
@@ -948,7 +995,7 @@
 Expression *ArrayLiteralExp::castTo(Scope *sc, Type *t)
 {
 #if 0
-    printf("ArrayLiteralExp::castTo(this=%s, type=%s, t=%s)\n",
+    printf("ArrayLiteralExp::castTo(this=%s, type=%s, => %s)\n",
 	toChars(), type->toChars(), t->toChars());
 #endif
     if (type == t)
@@ -1016,7 +1063,6 @@
     return e->Expression::castTo(sc, t);
 }
 
-
 Expression *SymOffExp::castTo(Scope *sc, Type *t)
 {
     Type *tb;
@@ -1134,7 +1180,7 @@
 	// Replace (ptr + int) with (ptr + (int * stride))
 	Type *t = Type::tptrdiff_t;
 
-	stride = t1b->next->size();
+	stride = t1b->nextOf()->size(loc);
 	if (!t->equals(t2b))
 	    e2 = e2->castTo(sc, t);
     // LLVMDC: llvm uses typesafe pointer arithmetic
@@ -1156,7 +1202,7 @@
 	Type *t = Type::tptrdiff_t;
 	Expression *e;
 
-	stride = t2b->next->size();
+	stride = t2b->nextOf()->size(loc);
 	if (!t->equals(t1b))
 	    e = e1->castTo(sc, t);
 	else
@@ -1327,13 +1373,17 @@
 	    goto Lincompatible;
     }
     else if ((t1->ty == Tsarray || t1->ty == Tarray) &&
-	     e2->op == TOKnull && t2->ty == Tpointer && t2->next->ty == Tvoid)
-    {
+	     e2->op == TOKnull && t2->ty == Tpointer && t2->nextOf()->ty == Tvoid)
+    {	/*  (T[n] op void*)
+	 *  (T[] op void*)
+	 */
 	goto Lx1;
     }
     else if ((t2->ty == Tsarray || t2->ty == Tarray) &&
-	     e1->op == TOKnull && t1->ty == Tpointer && t1->next->ty == Tvoid)
-    {
+	     e1->op == TOKnull && t1->ty == Tpointer && t1->nextOf()->ty == Tvoid)
+    {	/*  (void* op T[n])
+	 *  (void* op T[])
+	 */
 	goto Lx2;
     }
     else if ((t1->ty == Tsarray || t1->ty == Tarray) && t1->implicitConvTo(t2))
@@ -1375,7 +1425,7 @@
 		/* Pick 'tightest' type
 		 */
 		ClassDeclaration *cd1 = tc1->sym->baseClass;
-		ClassDeclaration *cd2 = tc1->sym->baseClass;
+		ClassDeclaration *cd2 = tc2->sym->baseClass;
 
 		if (cd1 && cd2)
 		{   t1 = cd1->type;
@@ -1402,21 +1452,48 @@
 	goto Lt1;
     }
     else if (t1->ty == Tsarray && t2->ty == Tsarray &&
-	     e2->implicitConvTo(t1->next->arrayOf()))
+	     e2->implicitConvTo(t1->nextOf()->arrayOf()))
     {
      Lx1:
-	t = t1->next->arrayOf();
+	t = t1->nextOf()->arrayOf();
 	e1 = e1->castTo(sc, t);
 	e2 = e2->castTo(sc, t);
     }
     else if (t1->ty == Tsarray && t2->ty == Tsarray &&
-	     e1->implicitConvTo(t2->next->arrayOf()))
+	     e1->implicitConvTo(t2->nextOf()->arrayOf()))
     {
      Lx2:
-	t = t2->next->arrayOf();
+	t = t2->nextOf()->arrayOf();
 	e1 = e1->castTo(sc, t);
 	e2 = e2->castTo(sc, t);
     }
+    else if (t1->isintegral() && t2->isintegral())
+    {
+	assert(0);
+    }
+    else if (e1->op == TOKslice && t1->ty == Tarray &&
+	     e2->implicitConvTo(t1->nextOf()))
+    {	// T[] op T
+	e2 = e2->castTo(sc, t1->nextOf());
+	t = t1->nextOf()->arrayOf();
+    }
+    else if (e2->op == TOKslice && t2->ty == Tarray &&
+	     e1->implicitConvTo(t2->nextOf()))
+    {	// T op T[]
+	e1 = e1->castTo(sc, t2->nextOf());
+	t = t2->nextOf()->arrayOf();
+
+	//printf("test %s\n", e->toChars());
+	e1 = e1->optimize(WANTvalue);
+	if (isCommutative() && e1->isConst())
+	{   /* Swap operands to minimize number of functions generated
+	     */
+	    //printf("swap %s\n", e->toChars());
+	    Expression *tmp = e1;
+	    e1 = e2;
+	    e2 = tmp;
+	}
+    }
     else
     {
      Lincompatible:
@@ -1446,9 +1523,10 @@
  */
 
 Expression *Expression::integralPromotions(Scope *sc)
-{   Expression *e;
+{
+    Expression *e = this;
 
-    e = this;
+    //printf("integralPromotions %s %s\n", e->toChars(), e->type->toChars());
     switch (type->toBasetype()->ty)
     {
 	case Tvoid:
--- a/dmd/doc.c	Thu Aug 14 03:09:26 2008 +0200
+++ b/dmd/doc.c	Thu Aug 14 06:55:41 2008 +0200
@@ -775,7 +775,7 @@
 	    {
 		TemplateParameter *tp = (TemplateParameter *)td->origParameters->data[i];
 		if (i)
-		    buf->writeByte(',');
+		    buf->writestring(", ");
 		tp->toCBuffer(buf, &hgs);
 	    }
 	    buf->writeByte(')');
--- a/dmd/expression.c	Thu Aug 14 03:09:26 2008 +0200
+++ b/dmd/expression.c	Thu Aug 14 06:55:41 2008 +0200
@@ -368,6 +368,7 @@
 	{
 	    e->error("expression has no value");
 	}
+
     }
     return e;
 }
@@ -389,6 +390,26 @@
     }
 }
 
+
+/******************************
+ * Perform canThrow() on an array of Expressions.
+ */
+
+#if DMDV2
+int arrayExpressionCanThrow(Expressions *exps)
+{
+    if (exps)
+    {
+	for (size_t i = 0; i < exps->dim; i++)
+	{   Expression *e = (Expression *)exps->data[i];
+	    if (e && e->canThrow())
+		return 1;
+	}
+    }
+    return 0;
+}
+#endif
+
 /****************************************
  * Expand tuples.
  */
@@ -503,10 +524,10 @@
 /****************************************
  * Now that we know the exact type of the function we're calling,
  * the arguments[] need to be adjusted:
- *	1) implicitly convert argument to the corresponding parameter type
- *	2) add default arguments for any missing arguments
- *	3) do default promotions on arguments corresponding to ...
- *	4) add hidden _arguments[] argument
+ *	1. implicitly convert argument to the corresponding parameter type
+ *	2. add default arguments for any missing arguments
+ *	3. do default promotions on arguments corresponding to ...
+ *	4. add hidden _arguments[] argument
  */
 
 void functionArguments(Loc loc, Scope *sc, TypeFunction *tf, Expressions *arguments)
@@ -802,6 +823,7 @@
 Expression::Expression(Loc loc, enum TOK op, int size)
     : loc(loc)
 {
+    //printf("Expression::Expression(op = %d) this = %p\n", op, this);
     this->loc = loc;
     this->op = op;
     this->size = size;
@@ -832,6 +854,7 @@
 	assert(0);
     }
     e = (Expression *)mem.malloc(size);
+    //printf("Expression::copy(op = %d) e = %p\n", op, e);
     return (Expression *)memcpy(e, this, size);
 }
 
@@ -965,6 +988,8 @@
 
 Expression *Expression::modifiableLvalue(Scope *sc, Expression *e)
 {
+    //printf("Expression::modifiableLvalue() %s, type = %s\n", toChars(), type->toChars());
+
     // See if this expression is a modifiable lvalue (i.e. not const)
     return toLvalue(sc, e);
 }
@@ -1300,7 +1325,8 @@
 	    type = Type::tint32;
     }
     else
-    {	type = type->semantic(loc, sc);
+    {	if (!type->deco)
+	    type = type->semantic(loc, sc);
     }
     return this;
 }
@@ -1785,7 +1811,8 @@
     {	Expression *e;
 	WithScopeSymbol *withsym;
 
-	// See if it was a with class
+	/* See if the symbol was a member of an enclosing 'with'
+	 */
 	withsym = scopesym->isWithScopeSymbol();
 	if (withsym)
 	{
@@ -1800,7 +1827,7 @@
 	    else
 	    {	Type *t = withsym->withstate->wthis->type;
 		if (t->ty == Tpointer)
-		    t = t->next;
+		    t = ((TypePointer *)t)->next;
 		e = new TypeDotIdExp(loc, t, ident);
 	    }
 	}
@@ -2161,8 +2188,8 @@
     return this;
 
 Lerr:
-    error("'this' is only allowed in non-static member functions, not %s", sc->parent->toChars());
-    type = Type::tint32;
+    error("'this' is only defined in non-static member functions, not %s", sc->parent->toChars());
+    type = Type::terror;
     return this;
 }
 
@@ -2695,7 +2722,7 @@
 	    // Convert any static arrays to dynamic arrays
 	    if (t0->ty == Tsarray)
 	    {
-		t0 = t0->next->arrayOf();
+		t0 = ((TypeSArray *)t0)->next->arrayOf();
 		e = e->implicitCastTo(sc, t0);
 	    }
 	}
@@ -2906,6 +2933,8 @@
 #if LOGSEMANTIC
     printf("StructLiteralExp::semantic('%s')\n", toChars());
 #endif
+    if (type)
+	return this;
 
     // Run semantic() on each element
     for (size_t i = 0; i < elements->dim; i++)
@@ -2986,11 +3015,17 @@
  */
 
 Expression *StructLiteralExp::getField(Type *type, unsigned offset)
-{   Expression *e = NULL;
+{
+    //printf("StructLiteralExp::getField(this = %s, type = %s, offset = %u)\n",
+//	/*toChars()*/"", type->toChars(), offset);
+    Expression *e = NULL;
     int i = getFieldIndex(type, offset);
 
     if (i != -1)
-    {   e = (Expression *)elements->data[i];
+    {
+	//printf("\ti = %d\n", i);
+	assert(i < elements->dim);
+	e = (Expression *)elements->data[i];
 	if (e)
 	{
 	    e = e->copy();
@@ -3330,7 +3365,7 @@
 	    Dsymbol *s = cd->toParent2();
 	    ClassDeclaration *cdn = s->isClassDeclaration();
 
-	    //printf("isNested, cdn = %s\n", cdn ? cdn->toChars() : "null");
+	    //printf("cd isNested, cdn = %s\n", cdn ? cdn->toChars() : "null");
 	    if (cdn)
 	    {
 		if (!cdthis)
@@ -3485,7 +3520,7 @@
 	    if (arg->op == TOKint64 && (long long)arg->toInteger() < 0)
 		error("negative array index %s", arg->toChars());
 	    arguments->data[i] = (void *) arg;
-	    tb = tb->next->toBasetype();
+	    tb = ((TypeDArray *)tb)->next->toBasetype();
 	}
     }
     else if (tb->isscalar())
@@ -3822,6 +3857,29 @@
 }
 
 
+/******************************** OverExp **************************/
+
+#if DMDV2
+OverExp::OverExp(OverloadSet *s)
+	: Expression(loc, TOKoverloadset, sizeof(OverExp))
+{
+    //printf("OverExp(this = %p, '%s')\n", this, var->toChars());
+    vars = s;
+    type = Type::tvoid;
+}
+
+int OverExp::isLvalue()
+{
+    return 1;
+}
+
+Expression *OverExp::toLvalue(Scope *sc, Expression *e)
+{
+    return this;
+}
+#endif
+
+
 /******************************** TupleExp **************************/
 
 TupleExp::TupleExp(Loc loc, Expressions *exps)
@@ -4158,6 +4216,43 @@
     buf->writeByte(')');
 }
 
+/************************ TraitsExp ************************************/
+#if DMDV2
+/*
+ *	__traits(identifier, args...)
+ */
+
+TraitsExp::TraitsExp(Loc loc, Identifier *ident, Objects *args)
+    : Expression(loc, TOKtraits, sizeof(TraitsExp))
+{
+    this->ident = ident;
+    this->args = args;
+}
+
+
+Expression *TraitsExp::syntaxCopy()
+{
+    return new TraitsExp(loc, ident, TemplateInstance::arraySyntaxCopy(args));
+}
+
+
+void TraitsExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    buf->writestring("__traits(");
+    buf->writestring(ident->toChars());
+    if (args)
+    {
+	for (int i = 0; i < args->dim; i++)
+	{
+	    buf->writeByte(',');
+	    Object *oarg = (Object *)args->data[i];
+	    ObjectToCBuffer(buf, hgs, oarg);
+	}
+    }
+    buf->writeByte(')');
+}
+#endif
+
 /************************************************************/
 
 HaltExp::HaltExp(Loc loc)
@@ -4210,7 +4305,11 @@
 Expression *IsExp::semantic(Scope *sc)
 {   Type *tded;
 
-    //printf("IsExp::semantic()\n");
+    /* is(targ id tok tspec)
+     * is(targ id == tok2)
+     */
+
+    //printf("IsExp::semantic(%s)\n", toChars());
     if (id && !(sc->flags & SCOPEstaticif))
 	error("can only declare type aliases within static if conditionals");
 
@@ -4267,6 +4366,19 @@
 		    goto Lno;
 		tded = targ;
 		break;
+#if DMDV2
+	    case TOKconst:
+		if (!targ->isConst())
+		    goto Lno;
+		tded = targ;
+		break;
+
+	    case TOKinvariant:
+		if (!targ->isInvariant())
+		    goto Lno;
+		tded = targ;
+		break;
+#endif
 
 	    case TOKsuper:
 		// If class or interface, get the base class and interfaces
@@ -4293,11 +4405,12 @@
 	    case TOKdelegate:
 		if (targ->ty != Tdelegate)
 		    goto Lno;
-		tded = targ->next;	// the underlying function type
+		tded = ((TypeDelegate *)targ)->next;	// the underlying function type
 		break;
 
 	    case TOKfunction:
-	    {	if (targ->ty != Tfunction)
+	    {
+		if (targ->ty != Tfunction)
 		    goto Lno;
 		tded = targ;
 
@@ -4321,7 +4434,7 @@
 		 * delegate, or pointer to function.
 		 */
 		if (targ->ty == Tfunction)
-		    tded = targ->next;
+		    tded = ((TypeFunction *)targ)->next;
 		else if (targ->ty == Tdelegate)
 		    tded = targ->next->next;
 		else if (targ->ty == Tpointer && targ->next->ty == Tfunction)
@@ -4537,6 +4650,13 @@
 	if (e)
 	    return e;
 
+	if (e1->op == TOKslice)
+	{   // T[] op= ...
+	    typeCombine(sc);
+	    type = e1->type;
+	    return arrayOp(sc);
+	}
+
 	e1 = e1->modifiableLvalue(sc, e1);
 	e1->checkScalar();
 	type = e1->type;
@@ -4568,6 +4688,13 @@
 	if (e)
 	    return e;
 
+	if (e1->op == TOKslice)
+	{   // T[] op= ...
+	    typeCombine(sc);
+	    type = e1->type;
+	    return arrayOp(sc);
+	}
+
 	e1 = e1->modifiableLvalue(sc, e1);
 	e1->checkScalar();
 	type = e1->type;
@@ -4888,6 +5015,24 @@
 	eleft = NULL;
 	eright = e1;
     }
+#if DMDV2
+    if (e1->op == TOKtuple && ident == Id::offsetof)
+    {	/* 'distribute' the .offsetof to each of the tuple elements.
+	 */
+	TupleExp *te = (TupleExp *)e1;
+	Expressions *exps = new Expressions();
+	exps->setDim(te->exps->dim);
+	for (int i = 0; i < exps->dim; i++)
+	{   Expression *e = (Expression *)te->exps->data[i];
+	    e = e->semantic(sc);
+	    e = new DotIdExp(e->loc, e, Id::offsetof);
+	    exps->data[i] = (void *)e;
+	}
+	e = new TupleExp(loc, exps);
+	e = e->semantic(sc);
+	return e;
+    }
+#endif
 
     if (e1->op == TOKtuple && ident == Id::length)
     {
@@ -5048,7 +5193,7 @@
 	     ident != Id::mangleof && ident != Id::stringof)
     {
 	e = new PtrExp(loc, e1);
-	e->type = e1->type->next;
+	e->type = ((TypePointer *)e1->type)->next;
 	return e->type->dotExp(sc, e, ident);
     }
     else
@@ -5176,7 +5321,11 @@
 
 Expression *DotVarExp::modifiableLvalue(Scope *sc, Expression *e)
 {
-    //printf("DotVarExp::modifiableLvalue(%s)\n", toChars());
+#if 0
+    printf("DotVarExp::modifiableLvalue(%s)\n", toChars());
+    printf("e1->type = %s\n", e1->type->toChars());
+    printf("var->type = %s\n", var->type->toChars());
+#endif
 
     if (var->isCtorinit())
     {	// It's only modifiable if inside the right constructor
@@ -5265,6 +5414,12 @@
     if (t1)
 	t1 = t1->toBasetype();
     //t1->print();
+
+    /* Extract the following from e1:
+     *	s: the symbol which ti should be a member of
+     *	eleft: if not NULL, it is the 'this' pointer for ti
+     */
+
     if (e1->op == TOKdotexp)
     {	DotExp *de = (DotExp *)e1;
 	eleft = de->e1;
@@ -5295,7 +5450,7 @@
     }
     else if (t1 && t1->ty == Tpointer)
     {
-	t1 = t1->next->toBasetype();
+	t1 = ((TypePointer *)t1)->next->toBasetype();
 	if (t1->ty != Tstruct)
 	    goto L1;
 	s = t1->toDsymbol(sc);
@@ -5471,6 +5626,7 @@
     int i;
     Type *t1;
     int istemp;
+    Objects *targsi = NULL;	// initial list of template arguments
 
 #if LOGSEMANTIC
     printf("CallExp::semantic() %s\n", toChars());
@@ -5534,8 +5690,66 @@
 	}
     }
 
+#if DMDV2
+    /* This recognizes:
+     *	foo!(tiargs)(funcargs)
+     */
+    if (e1->op == TOKimport && !e1->type)
+    {	ScopeExp *se = (ScopeExp *)e1;
+	TemplateInstance *ti = se->sds->isTemplateInstance();
+	if (ti && !ti->semanticdone)
+	{
+	    /* Attempt to instantiate ti. If that works, go with it.
+	     * If not, go with partial explicit specialization.
+	     */
+	    ti->semanticTiargs(sc);
+	    unsigned errors = global.errors;
+	    global.gag++;
+	    ti->semantic(sc);
+	    global.gag--;
+	    if (errors != global.errors)
+	    {
+		/* Didn't work, go with partial explicit specialization
+		 */
+		global.errors = errors;
+		targsi = ti->tiargs;
+		e1 = new IdentifierExp(loc, ti->name);
+	    }
+	}
+    }
+
+    /* This recognizes:
+     *	expr.foo!(tiargs)(funcargs)
+     */
+    if (e1->op == TOKdotti && !e1->type)
+    {	DotTemplateInstanceExp *se = (DotTemplateInstanceExp *)e1;
+	TemplateInstance *ti = se->ti;
+	if (!ti->semanticdone)
+	{
+	    /* Attempt to instantiate ti. If that works, go with it.
+	     * If not, go with partial explicit specialization.
+	     */
+	    ti->semanticTiargs(sc);
+	    Expression *etmp;
+	    unsigned errors = global.errors;
+	    global.gag++;
+	    etmp = e1->semantic(sc);
+	    global.gag--;
+	    if (errors != global.errors)
+	    {
+		global.errors = errors;
+		targsi = ti->tiargs;
+		e1 = new DotIdExp(loc, se->e1, ti->name);
+	    }
+	    else
+		e1 = etmp;
+	}
+    }
+#endif
+
     istemp = 0;
 Lagain:
+    //printf("Lagain: %s\n", toChars());
     f = NULL;
     if (e1->op == TOKthis || e1->op == TOKsuper)
     {
@@ -5804,16 +6018,16 @@
     else if (t1->ty != Tfunction)
     {
 	if (t1->ty == Tdelegate)
-	{
-	    assert(t1->next->ty == Tfunction);
-	    tf = (TypeFunction *)(t1->next);
+	{   TypeDelegate *td = (TypeDelegate *)t1;
+	    assert(td->next->ty == Tfunction);
+	    tf = (TypeFunction *)(td->next);
 	    goto Lcheckargs;
 	}
-	else if (t1->ty == Tpointer && t1->next->ty == Tfunction)
+	else if (t1->ty == Tpointer && ((TypePointer *)t1)->next->ty == Tfunction)
 	{   Expression *e;
 
 	    e = new PtrExp(loc, e1);
-	    t1 = t1->next;
+	    t1 = ((TypePointer *)t1)->next;
 	    e->type = t1;
 	    e1 = e;
 	}
@@ -5909,10 +6123,11 @@
     {
 	Type *t = type;
 	int offset = 0;
-
-	if (f->tintro->next->isBaseOf(t, &offset) && offset)
-	{
-	    type = f->tintro->next;
+	TypeFunction *tf = (TypeFunction *)f->tintro;
+
+	if (tf->next->isBaseOf(t, &offset) && offset)
+	{
+	    type = tf->next;
 	    return castTo(sc, t);
 	}
     }
@@ -5974,9 +6189,7 @@
 	    FuncDeclaration *f = dve->var->isFuncDeclaration();
 
 	    if (f)
-	    {	Expression *e;
-
-		e = new DelegateExp(loc, dve->e1, f);
+	    {	Expression *e = new DelegateExp(loc, dve->e1, f);
 		e = e->semantic(sc);
 		return e;
 	    }
@@ -6018,7 +6231,7 @@
 	: UnaExp(loc, TOKstar, sizeof(PtrExp), e)
 {
     if (e->type)
-	type = e->type->next;
+	type = ((TypePointer *)e->type)->next;
 }
 
 PtrExp::PtrExp(Loc loc, Expression *e, Type *t)
@@ -6108,7 +6321,8 @@
 	    return e;
 
 	e1->checkNoBool();
-	e1->checkArithmetic();
+	if (e1->op != TOKslice)
+	    e1->checkArithmetic();
 	type = e1->type;
     }
     return this;
@@ -6157,7 +6371,8 @@
 	    return e;
 
 	e1->checkNoBool();
-	e1 = e1->checkIntegral();
+	if (e1->op != TOKslice)
+	    e1 = e1->checkIntegral();
 	type = e1->type;
     }
     return this;
@@ -6238,7 +6453,7 @@
 	    break;
 	}
 	case Tpointer:
-	    tb = tb->next->toBasetype();
+	    tb = ((TypePointer *)tb)->next->toBasetype();
 	    if (tb->ty == Tstruct)
 	    {
 		TypeStruct *ts = (TypeStruct *)tb;
@@ -6569,7 +6784,7 @@
 	return e;
     }
 
-    type = t->next->arrayOf();
+    type = t->nextOf()->arrayOf();
     return e;
 
 Lerror:
@@ -6878,7 +7093,7 @@
 			    index, length);
 	    }
 #endif
-	    e->type = t1->next;
+	    e->type = t1->nextOf();
 	    break;
 	}
 
@@ -7199,6 +7414,20 @@
     {
 	e2 = e2->implicitCastTo(sc, e1->type);
     }
+
+    /* Look for array operations
+     */
+    if (e1->op == TOKslice && !ismemset &&
+	(e2->op == TOKadd || e2->op == TOKmin ||
+	 e2->op == TOKmul || e2->op == TOKdiv ||
+	 e2->op == TOKmod || e2->op == TOKxor ||
+	 e2->op == TOKand || e2->op == TOKor  ||
+	 e2->op == TOKtilde || e2->op == TOKneg))
+    {
+	type = e1->type;
+	return arrayOp(sc);
+    }
+
     type = e1->type;
     assert(type);
     return this;
@@ -7234,14 +7463,23 @@
     if (e)
 	return e;
 
-    e1 = e1->modifiableLvalue(sc, e1);
-
     Type *tb1 = e1->type->toBasetype();
     Type *tb2 = e2->type->toBasetype();
 
+    if (e1->op == TOKslice)
+    {
+	typeCombine(sc);
+	type = e1->type;
+	return arrayOp(sc);
+    }
+    else
+    {
+	e1 = e1->modifiableLvalue(sc, e1);
+    }
+
     if ((tb1->ty == Tarray || tb1->ty == Tsarray) &&
 	(tb2->ty == Tarray || tb2->ty == Tsarray) &&
-	tb1->next->equals(tb2->next)
+	tb1->nextOf()->equals(tb2->nextOf())
        )
     {
 	type = e1->type;
@@ -7263,11 +7501,7 @@
 		Expression *ea;
 		Expression *ex;
 
-		char name[6+6+1];
-		Identifier *id;
-		static int idn;
-		sprintf(name, "__name%d", ++idn);
-		id = Lexer::idPool(name);
+		Identifier *id = Lexer::uniqueId("__name");
 
 		v = new VarDeclaration(loc, tb1->pointerTo(), id, NULL);
 		v->semantic(sc);
@@ -7334,6 +7568,13 @@
     if (e)
 	return e;
 
+    if (e1->op == TOKslice)
+    {	// T[] -= ...
+	typeCombine(sc);
+	type = e1->type;
+	return arrayOp(sc);
+    }
+
     e1 = e1->modifiableLvalue(sc, e1);
     e1->checkScalar();
     e1->checkNoBool();
@@ -7397,10 +7638,10 @@
 	e = this;
     }
     else if ((tb1->ty == Tarray) &&
-	e2->implicitConvTo(tb1->next)
+	e2->implicitConvTo(tb1->nextOf())
        )
     {	// Append element
-	e2 = e2->castTo(sc, tb1->next);
+	e2 = e2->castTo(sc, tb1->nextOf());
 	type = e1->type;
 	e = this;
     }
@@ -7430,6 +7671,13 @@
     if (e)
 	return e;
 
+    if (e1->op == TOKslice)
+    {	// T[] -= ...
+	typeCombine(sc);
+	type = e1->type;
+	return arrayOp(sc);
+    }
+
     e1 = e1->modifiableLvalue(sc, e1);
     e1->checkScalar();
     e1->checkNoBool();
@@ -7486,6 +7734,13 @@
     if (e)
 	return e;
 
+    if (e1->op == TOKslice)
+    {	// T[] -= ...
+	typeCombine(sc);
+	type = e1->type;
+	return arrayOp(sc);
+    }
+
     e1 = e1->modifiableLvalue(sc, e1);
     e1->checkScalar();
     e1->checkNoBool();
@@ -7690,7 +7945,7 @@
 
         if ((tb1->ty == Tarray || tb1->ty == Tsarray) &&
             (tb2->ty == Tarray || tb2->ty == Tsarray) &&
-            tb1->next->equals(tb2->next)
+            tb1->nextOf()->equals(tb2->nextOf())
            )
         {
             type = e1->type;
@@ -7776,17 +8031,22 @@
 
 	    typeCombine(sc);		// make sure pointer types are compatible
 	    type = Type::tptrdiff_t;
-	    stride = t2->next->size();
-        if (!stride)
-            return new IntegerExp(0, 0, Type::tptrdiff_t);
-	    e = new DivExp(loc, this, new IntegerExp(0, stride, Type::tptrdiff_t));
-	    e->type = Type::tptrdiff_t;
+	    stride = t2->nextOf()->size();
+	    if (stride == 0)
+	    {
+		e = new IntegerExp(loc, 0, Type::tptrdiff_t);
+	    }
+	    else
+	    {
+		e = new DivExp(loc, this, new IntegerExp(0, stride, Type::tptrdiff_t));
+		e->type = Type::tptrdiff_t;
+	    }
 	    return e;
 	}
 	else if (t2->isintegral())
 	    e = scaleFactor(sc);
 	else
-	{   error("incompatible types for -");
+	{   error("incompatible types for minus");
 	    return new IntegerExp(0);
 	}
     }
@@ -7864,7 +8124,7 @@
 	if ((tb1->ty == Tsarray || tb1->ty == Tarray) &&
 	    e2->type->equals(tb1->next))
 	{
-	    type = tb1->next->arrayOf();
+	    type = tb1->nextOf()->arrayOf();
 	    if (tb2->ty == Tarray)
 	    {	// Make e2 into [e2]
 		e2 = new ArrayLiteralExp(e2->loc, e2);
@@ -7875,7 +8135,7 @@
 	else if ((tb2->ty == Tsarray || tb2->ty == Tarray) &&
 	    e1->type->equals(tb2->next))
 	{
-	    type = tb2->next->arrayOf();
+	    type = tb2->nextOf()->arrayOf();
 	    if (tb1->ty == Tarray)
 	    {	// Make e1 into [e1]
 		e1 = new ArrayLiteralExp(e1->loc, e1);
@@ -7904,6 +8164,7 @@
 	}
 	else
 	{
+	    //printf("(%s) ~ (%s)\n", e1->toChars(), e2->toChars());
 	    error("Can only concatenate arrays, not (%s ~ %s)",
 		e1->type->toChars(), e2->type->toChars());
 	    type = Type::tint32;
@@ -7939,8 +8200,10 @@
 	return e;
 
     typeCombine(sc);
-    e1->checkArithmetic();
-    e2->checkArithmetic();
+    if (e1->op != TOKslice && e2->op != TOKslice)
+    {	e1->checkArithmetic();
+	e2->checkArithmetic();
+    }
     if (type->isfloating())
     {	Type *t1 = e1->type;
 	Type *t2 = e2->type;
@@ -8003,8 +8266,10 @@
 	return e;
 
     typeCombine(sc);
-    e1->checkArithmetic();
-    e2->checkArithmetic();
+    if (e1->op != TOKslice && e2->op != TOKslice)
+    {	e1->checkArithmetic();
+	e2->checkArithmetic();
+    }
     if (type->isfloating())
     {	Type *t1 = e1->type;
 	Type *t2 = e2->type;
@@ -8068,8 +8333,10 @@
 	return e;
 
     typeCombine(sc);
-    e1->checkArithmetic();
-    e2->checkArithmetic();
+    if (e1->op != TOKslice && e2->op != TOKslice)
+    {	e1->checkArithmetic();
+	e2->checkArithmetic();
+    }
     if (type->isfloating())
     {	type = e1->type;
 	if (e2->type->iscomplex())
@@ -8180,8 +8447,10 @@
 	else
 	{
 	    typeCombine(sc);
-	    e1->checkIntegral();
-	    e2->checkIntegral();
+	    if (e1->op != TOKslice && e2->op != TOKslice)
+	    {   e1->checkIntegral();
+		e2->checkIntegral();
+	    }
 	}
     }
     return this;
@@ -8211,8 +8480,10 @@
 	else
 	{
 	    typeCombine(sc);
-	    e1->checkIntegral();
-	    e2->checkIntegral();
+	    if (e1->op != TOKslice && e2->op != TOKslice)
+	    {   e1->checkIntegral();
+		e2->checkIntegral();
+	    }
 	}
     }
     return this;
@@ -8242,8 +8513,10 @@
 	else
 	{
 	    typeCombine(sc);
-	    e1->checkIntegral();
-	    e2->checkIntegral();
+	    if (e1->op != TOKslice && e2->op != TOKslice)
+	    {   e1->checkIntegral();
+		e2->checkIntegral();
+	    }
 	}
     }
     return this;
@@ -8414,7 +8687,7 @@
 	e1 = e1->implicitCastTo(sc, ta->index);
 
 	// Return type is pointer to value
-	type = ta->next->pointerTo();
+	type = ta->nextOf()->pointerTo();
     }
     return this;
 }
@@ -8501,6 +8774,7 @@
 #endif
     else
 	e = this;
+    //printf("CmpExp: %s\n", e->toChars());
     return e;
 }
 
--- a/dmd/expression.h	Thu Aug 14 03:09:26 2008 +0200
+++ b/dmd/expression.h	Thu Aug 14 06:55:41 2008 +0200
@@ -43,7 +43,7 @@
 struct BinExp;
 struct InterState;
 struct Symbol;		// back end symbol
-
+struct OverloadSet;
 namespace llvm
 {
     class Constant;
@@ -151,6 +151,10 @@
     virtual Identifier *opId();
     virtual Identifier *opId_r();
 
+    // For array ops
+    virtual void buildArrayIdent(OutBuffer *buf, Expressions *arguments);
+    virtual Expression *buildArrayLoop(Arguments *fparams);
+
     // Back end
     virtual elem *toElem(IRState *irs);
     virtual dt_t **toDt(dt_t **pdt);
@@ -594,6 +598,19 @@
     virtual llvm::Constant *toConstElem(IRState *irs);
 };
 
+#if DMDV2
+// Overload Set
+
+struct OverExp : Expression
+{
+    OverloadSet *vars;
+
+    OverExp(OverloadSet *s);
+    int isLvalue();
+    Expression *toLvalue(Scope *sc, Expression *e);
+};
+#endif
+
 // Function/Delegate literal
 
 struct FuncExp : Expression
@@ -643,6 +660,19 @@
     void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
 };
 
+#if DMDV2
+struct TraitsExp : Expression
+{
+    Identifier *ident;
+    Objects *args;
+
+    TraitsExp(Loc loc, Identifier *ident, Objects *args);
+    Expression *syntaxCopy();
+    Expression *semantic(Scope *sc);
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+};
+#endif
+
 struct HaltExp : Expression
 {
     HaltExp(Loc loc);
@@ -715,6 +745,7 @@
     Expression *interpretCommon(InterState *istate, Expression *(*fp)(Type *, Expression *, Expression *));
     Expression *interpretCommon2(InterState *istate, Expression *(*fp)(TOK, Type *, Expression *, Expression *));
     Expression *interpretAssignCommon(InterState *istate, Expression *(*fp)(Type *, Expression *, Expression *), int post = 0);
+    Expression *arrayOp(Scope *sc);
 
     int inlineCost(InlineCostState *ics);
     Expression *doInline(InlineDoState *ids);
@@ -887,6 +918,8 @@
     Expression *semantic(Scope *sc);
     Expression *optimize(int result);
     Expression *interpret(InterState *istate);
+    void buildArrayIdent(OutBuffer *buf, Expressions *arguments);
+    Expression *buildArrayLoop(Arguments *fparams);
 
     // For operator overloading
     Identifier *opId();
@@ -909,6 +942,8 @@
     Expression *semantic(Scope *sc);
     Expression *optimize(int result);
     Expression *interpret(InterState *istate);
+    void buildArrayIdent(OutBuffer *buf, Expressions *arguments);
+    Expression *buildArrayLoop(Arguments *fparams);
 
     // For operator overloading
     Identifier *opId();
@@ -984,6 +1019,8 @@
     void dump(int indent);
     elem *toElem(IRState *irs);
     void scanForNestedRef(Scope *sc);
+    void buildArrayIdent(OutBuffer *buf, Expressions *arguments);
+    Expression *buildArrayLoop(Arguments *fparams);
 
     int inlineCost(InlineCostState *ics);
     Expression *doInline(InlineDoState *ids);
@@ -1081,6 +1118,8 @@
     Expression *checkToBoolean();
     Expression *interpret(InterState *istate);
     Identifier *opId();    // For operator overloading
+    void buildArrayIdent(OutBuffer *buf, Expressions *arguments);
+    Expression *buildArrayLoop(Arguments *fparams);
     elem *toElem(IRState *irs);
 };
 
@@ -1090,25 +1129,33 @@
     op##AssignExp(Loc loc, Expression *e1, Expression *e2);	\
     Expression *semantic(Scope *sc);				\
     Expression *interpret(InterState *istate);			\
+    X(void buildArrayIdent(OutBuffer *buf, Expressions *arguments);) \
+    X(Expression *buildArrayLoop(Arguments *fparams);)		\
 								\
     Identifier *opId();    /* For operator overloading */	\
 								\
     elem *toElem(IRState *irs);					\
 };
 
+#define X(a) a
 ASSIGNEXP(Add)
 ASSIGNEXP(Min)
-ASSIGNEXP(Cat)
 ASSIGNEXP(Mul)
 ASSIGNEXP(Div)
 ASSIGNEXP(Mod)
+ASSIGNEXP(And)
+ASSIGNEXP(Or)
+ASSIGNEXP(Xor)
+#undef X
+
+#define X(a)
+
 ASSIGNEXP(Shl)
 ASSIGNEXP(Shr)
 ASSIGNEXP(Ushr)
-ASSIGNEXP(And)
-ASSIGNEXP(Or)
-ASSIGNEXP(Xor)
+ASSIGNEXP(Cat)
 
+#undef X
 #undef ASSIGNEXP
 
 struct AddExp : BinExp
@@ -1117,6 +1164,8 @@
     Expression *semantic(Scope *sc);
     Expression *optimize(int result);
     Expression *interpret(InterState *istate);
+    void buildArrayIdent(OutBuffer *buf, Expressions *arguments);
+    Expression *buildArrayLoop(Arguments *fparams);
 
     // For operator overloading
     int isCommutative();
@@ -1135,6 +1184,8 @@
     Expression *semantic(Scope *sc);
     Expression *optimize(int result);
     Expression *interpret(InterState *istate);
+    void buildArrayIdent(OutBuffer *buf, Expressions *arguments);
+    Expression *buildArrayLoop(Arguments *fparams);
 
     // For operator overloading
     Identifier *opId();
@@ -1163,6 +1214,8 @@
     Expression *semantic(Scope *sc);
     Expression *optimize(int result);
     Expression *interpret(InterState *istate);
+    void buildArrayIdent(OutBuffer *buf, Expressions *arguments);
+    Expression *buildArrayLoop(Arguments *fparams);
 
     // For operator overloading
     int isCommutative();
@@ -1178,6 +1231,8 @@
     Expression *semantic(Scope *sc);
     Expression *optimize(int result);
     Expression *interpret(InterState *istate);
+    void buildArrayIdent(OutBuffer *buf, Expressions *arguments);
+    Expression *buildArrayLoop(Arguments *fparams);
 
     // For operator overloading
     Identifier *opId();
@@ -1192,6 +1247,8 @@
     Expression *semantic(Scope *sc);
     Expression *optimize(int result);
     Expression *interpret(InterState *istate);
+    void buildArrayIdent(OutBuffer *buf, Expressions *arguments);
+    Expression *buildArrayLoop(Arguments *fparams);
 
     // For operator overloading
     Identifier *opId();
@@ -1248,6 +1305,8 @@
     Expression *semantic(Scope *sc);
     Expression *optimize(int result);
     Expression *interpret(InterState *istate);
+    void buildArrayIdent(OutBuffer *buf, Expressions *arguments);
+    Expression *buildArrayLoop(Arguments *fparams);
 
     // For operator overloading
     int isCommutative();
@@ -1263,6 +1322,8 @@
     Expression *semantic(Scope *sc);
     Expression *optimize(int result);
     Expression *interpret(InterState *istate);
+    void buildArrayIdent(OutBuffer *buf, Expressions *arguments);
+    Expression *buildArrayLoop(Arguments *fparams);
 
     // For operator overloading
     int isCommutative();
@@ -1278,6 +1339,8 @@
     Expression *semantic(Scope *sc);
     Expression *optimize(int result);
     Expression *interpret(InterState *istate);
+    void buildArrayIdent(OutBuffer *buf, Expressions *arguments);
+    Expression *buildArrayLoop(Arguments *fparams);
 
     // For operator overloading
     int isCommutative();
@@ -1402,6 +1465,32 @@
     elem *toElem(IRState *irs);
 };
 
+#if DMDV2
+/****************************************************************/
+
+struct DefaultInitExp : Expression
+{
+    enum TOK subop;		// which of the derived classes this is
+
+    DefaultInitExp(Loc loc, enum TOK subop, int size);
+    virtual Expression *resolve(Loc loc, Scope *sc) = 0;
+    void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+};
+
+struct FileInitExp : DefaultInitExp
+{
+    FileInitExp(Loc loc);
+    Expression *semantic(Scope *sc);
+    Expression *resolve(Loc loc, Scope *sc);
+};
+
+struct LineInitExp : DefaultInitExp
+{
+    LineInitExp(Loc loc);
+    Expression *semantic(Scope *sc);
+    Expression *resolve(Loc loc, Scope *sc);
+};
+#endif
 
 /****************************************************************/
 
--- a/dmd/func.c	Thu Aug 14 03:09:26 2008 +0200
+++ b/dmd/func.c	Thu Aug 14 06:55:41 2008 +0200
@@ -68,6 +68,9 @@
     fes = NULL;
     introducing = 0;
     tintro = NULL;
+    /* The type given for "infer the return type" is a TypeFunction with
+     * NULL for the return type.
+     */
     inferRetType = (type && type->nextOf() == NULL);
     scope = NULL;
     hasReturnExp = 0;
@@ -112,7 +115,7 @@
     if (isFuncLiteralDeclaration())
 	printf("\tFuncLiteralDeclaration()\n");
     printf("sc->parent = %s\n", sc->parent->toChars());
-    printf("type: %s\n", type->toChars());
+    printf("type: %p, %s\n", type, type->toChars());
 #endif
 
     if (type->nextOf())
@@ -281,8 +284,11 @@
 	vi = findVtblIndex(&cd->vtbl, cd->baseClass ? cd->baseClass->vtbl.dim : 0);
 	switch (vi)
 	{
-	    case -1:	// didn't find one
-		// This is an 'introducing' function.
+	    case -1:
+		/* Didn't find one, so
+		 * This is an 'introducing' function which gets a new
+		 * slot in the vtbl[].
+		 */
 
 		// Verify this doesn't override previous final function
 		if (cd->baseClass)
@@ -632,9 +638,8 @@
 
     // Check the 'throws' clause
     if (fthrows)
-    {	int i;
-
-	for (i = 0; i < fthrows->dim; i++)
+    {
+	for (int i = 0; i < fthrows->dim; i++)
 	{
 	    Type *t = (Type *)fthrows->data[i];
 
@@ -696,9 +701,11 @@
 	}
 	else if (isNested())
 	{
-	    VarDeclaration *v;
-
-	    v = new ThisDeclaration(Type::tvoid->pointerTo());
+	    /* The 'this' for a nested function is the link to the
+	     * enclosing function's stack frame.
+	     * Note that nested functions and member functions are disjoint.
+	     */
+	    VarDeclaration *v = new ThisDeclaration(Type::tvoid->pointerTo());
 	    v->storage_class |= STCparameter | STCin;
 	    v->semantic(sc2);
 	    if (!sc2->insert(v))
@@ -781,11 +788,7 @@
 		    /* Generate identifier for un-named parameter,
 		     * because we need it later on.
 		     */
-		    OutBuffer buf;
-            buf.printf("_param_%"PRIuSIZE, i);
-		    char *name = (char *)buf.extractData();
-		    id = new Identifier(name, TOKidentifier);
-		    arg->ident = id;
+		    arg->ident = id = Identifier::generateId("_param_", i);
 		}
 		VarDeclaration *v = new VarDeclaration(loc, arg->type, id, NULL);
 		//printf("declaring parameter %s of type %s\n", v->toChars(), v->type->toChars());
@@ -824,11 +827,11 @@
 			assert(narg->ident);
 			VarDeclaration *v = sc2->search(0, narg->ident, NULL)->isVarDeclaration();
 			assert(v);
-			Expression *e = new VarExp(0, v);
+			Expression *e = new VarExp(v->loc, v);
 			exps->data[j] = (void *)e;
 		    }
 		    assert(arg->ident);
-		    TupleDeclaration *v = new TupleDeclaration(0, arg->ident, exps);
+		    TupleDeclaration *v = new TupleDeclaration(loc, arg->ident, exps);
 		    //printf("declaring tuple %s\n", v->toChars());
 		    v->isexp = 1;
 		    if (!sc2->insert(v))
@@ -1569,10 +1572,8 @@
 
     if (f != m->lastf)		// skip duplicates
     {
-	TypeFunction *tf;
-
 	m->anyf = f;
-	tf = (TypeFunction *)f->type;
+	TypeFunction *tf = (TypeFunction *)f->type;
 	match = (MATCH) tf->callMatch(arguments);
 	//printf("match = %d\n", match);
 	if (match != MATCHnomatch)
@@ -1910,8 +1911,16 @@
 
 int FuncDeclaration::isWinMain()
 {
+    //printf("FuncDeclaration::isWinMain() %s\n", toChars());
+#if 0
+    int x = ident == Id::WinMain &&
+	linkage != LINKc && !isMember();
+    printf("%s\n", x ? "yes" : "no");
+    return x;
+#else
     return ident == Id::WinMain &&
 	linkage != LINKc && !isMember();
+#endif
 }
 
 int FuncDeclaration::isDllMain()
@@ -2090,7 +2099,7 @@
 		goto Lyes;	// assume f escapes this function's scope
 
 	    // Look to see if any parents of f that are below this escape
-	    for (Dsymbol *s = f->parent; s != this; s = s->parent)
+	    for (Dsymbol *s = f->parent; s && s != this; s = s->parent)
 	    {
 		f = s->isFuncDeclaration();
 		if (f && (f->isThis() || f->tookAddressOf))
@@ -2196,7 +2205,7 @@
 {
     this->arguments = arguments;
     this->varargs = varargs;
-    //printf("CtorDeclaration() %s\n", toChars());
+    //printf("CtorDeclaration(loc = %s) %s\n", loc.toChars(), toChars());
 }
 
 Dsymbol *CtorDeclaration::syntaxCopy(Dsymbol *s)
--- a/dmd/identifier.c	Thu Aug 14 03:09:26 2008 +0200
+++ b/dmd/identifier.c	Thu Aug 14 06:55:41 2008 +0200
@@ -81,15 +81,21 @@
     return DYNCAST_IDENTIFIER;
 }
 
-Identifier *Identifier::generateId(char *prefix)
+
+Identifier *Identifier::generateId(const char *prefix)
+{
+    static size_t i;
+
+    return generateId(prefix, ++i);
+}
+
+Identifier *Identifier::generateId(const char *prefix, size_t i)
 {   OutBuffer buf;
-    char *id;
-    static unsigned i;
 
     buf.writestring(prefix);
-    buf.printf("%u", ++i);
+    buf.printf("%zu", i);
 
-    id = buf.toChars();
+    char *id = buf.toChars();
     buf.data = NULL;
-    return new Identifier(id, TOKidentifier);
+    return Lexer::idPool(id);
 }
--- a/dmd/identifier.h	Thu Aug 14 03:09:26 2008 +0200
+++ b/dmd/identifier.h	Thu Aug 14 06:55:41 2008 +0200
@@ -1,46 +1,47 @@
-
-// Compiler implementation of the D programming language
-// Copyright (c) 1999-2006 by Digital Mars
-// All Rights Reserved
-// written by Walter Bright
-// http://www.digitalmars.com
-// License for redistribution is by either the Artistic License
-// in artistic.txt, or the GNU General Public License in gnu.txt.
-// See the included readme.txt for details.
-
-#ifndef DMD_IDENTIFIER_H
-#define DMD_IDENTIFIER_H
-
-#ifdef __DMC__
-#pragma once
-#endif /* __DMC__ */
-
-#include "root.h"
-
-namespace llvm
-{
-    class Value;
-}
-
-struct Identifier : Object
-{
-    int value;
-    const char *string;
-    unsigned len;
-
-    Identifier(const char *string, int value);
-    int equals(Object *o);
-    hash_t hashCode();
-    int compare(Object *o);
-    void print();
-    char *toChars();
-#ifdef _DH
-    char *toHChars();
-#endif
-    char *toHChars2();
-    int dyncast();
-
-    static Identifier *generateId(char *prefix);
-};
-
-#endif /* DMD_IDENTIFIER_H */
+
+// Compiler implementation of the D programming language
+// Copyright (c) 1999-2006 by Digital Mars
+// All Rights Reserved
+// written by Walter Bright
+// http://www.digitalmars.com
+// License for redistribution is by either the Artistic License
+// in artistic.txt, or the GNU General Public License in gnu.txt.
+// See the included readme.txt for details.
+
+#ifndef DMD_IDENTIFIER_H
+#define DMD_IDENTIFIER_H
+
+#ifdef __DMC__
+#pragma once
+#endif /* __DMC__ */
+
+#include "root.h"
+
+namespace llvm
+{
+    class Value;
+}
+
+struct Identifier : Object
+{
+    int value;
+    const char *string;
+    unsigned len;
+
+    Identifier(const char *string, int value);
+    int equals(Object *o);
+    hash_t hashCode();
+    int compare(Object *o);
+    void print();
+    char *toChars();
+#ifdef _DH
+    char *toHChars();
+#endif
+    char *toHChars2();
+    int dyncast();
+
+    static Identifier *generateId(const char *prefix);
+    static Identifier *generateId(const char *prefix, size_t i);
+};
+
+#endif /* DMD_IDENTIFIER_H */
--- a/dmd/mars.c	Thu Aug 14 03:09:26 2008 +0200
+++ b/dmd/mars.c	Thu Aug 14 06:55:41 2008 +0200
@@ -865,6 +865,7 @@
 #endif
 
 	    if (stricmp(ext, global.mars_ext) == 0 ||
+        stricmp(ext, global.hdr_ext) == 0 ||
 		stricmp(ext, "htm") == 0 ||
 		stricmp(ext, "html") == 0 ||
 		stricmp(ext, "xhtml") == 0)
--- a/dmd/module.c	Thu Aug 14 03:09:26 2008 +0200
+++ b/dmd/module.c	Thu Aug 14 06:55:41 2008 +0200
@@ -112,6 +112,7 @@
 
     srcfilename = FileName::defaultExt(filename, global.mars_ext);
     if (!srcfilename->equalsExt(global.mars_ext) &&
+        !srcfilename->equalsExt(global.hdr_ext) &&
         !srcfilename->equalsExt("dd"))
     {
 	if (srcfilename->equalsExt("html") ||
--- a/dmd/statement.c	Thu Aug 14 03:09:26 2008 +0200
+++ b/dmd/statement.c	Thu Aug 14 06:55:41 2008 +0200
@@ -1968,8 +1968,10 @@
 	if (arg->type)
 	    arg->type->toCBuffer(buf, arg->ident, hgs);
 	else
+	{   buf->writestring("auto ");
 	    buf->writestring(arg->ident->toChars());
-	buf->writebyte(';');
+	}
+	buf->writestring(" = ");
     }
     condition->toCBuffer(buf, hgs);
     buf->writebyte(')');
@@ -2041,6 +2043,14 @@
     return (ifbody && ifbody->usesEH()) || (elsebody && elsebody->usesEH());
 }
 
+int ConditionalStatement::blockExit()
+{
+    int result = ifbody->blockExit();
+    if (elsebody)
+	result |= elsebody->blockExit();
+    return result;
+}
+
 void ConditionalStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
 {
     condition->toCBuffer(buf, hgs);
--- a/dmd/statement.h	Thu Aug 14 03:09:26 2008 +0200
+++ b/dmd/statement.h	Thu Aug 14 06:55:41 2008 +0200
@@ -461,6 +461,7 @@
     Statement *semantic(Scope *sc);
     Statements *flatten(Scope *sc);
     int usesEH();
+    int blockExit();
 
     void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
 };
--- a/llvmdc.kdevelop.filelist	Thu Aug 14 03:09:26 2008 +0200
+++ b/llvmdc.kdevelop.filelist	Thu Aug 14 06:55:41 2008 +0200
@@ -3,6 +3,7 @@
 dmd/access.c
 dmd/aggregate.h
 dmd/array.c
+dmd/arrayop.c
 dmd/arraytypes.h
 dmd/attrib.c
 dmd/attrib.h