changeset 1630:44b145be2ef5

Merge dmd 1.056.
author Robert Clipsham <robert@octarineparrot.com>
date Sat, 06 Feb 2010 15:53:52 +0000
parents b07d683ba4d0
children e16ea850ff81
files dmd/access.c dmd/aggregate.h dmd/arrayop.c dmd/attrib.c dmd/class.c dmd/cond.c dmd/declaration.c dmd/declaration.h dmd/dsymbol.c dmd/dsymbol.h dmd/enum.c dmd/expression.c dmd/expression.h dmd/func.c dmd/identifier.h dmd/inline.c dmd/interpret.c dmd/mangle.c dmd/mars.c dmd/mars.h dmd/module.c dmd/module.h dmd/mtype.c dmd/optimize.c dmd/statement.c dmd/statement.h dmd/struct.c dmd/template.c tests/mini/bug372.d
diffstat 29 files changed, 638 insertions(+), 285 deletions(-) [+]
line wrap: on
line diff
--- a/dmd/access.c	Wed Jan 06 19:53:35 2010 +0100
+++ b/dmd/access.c	Sat Feb 06 15:53:52 2010 +0000
@@ -392,12 +392,11 @@
 #endif
     if (!e)
     {
-	if (d->getModule() != sc->module)
-	    if (d->prot() == PROTprivate ||
-		d->prot() == PROTpackage && !hasPackageAccess(sc, d))
+	if (d->prot() == PROTprivate && d->getModule() != sc->module ||
+	    d->prot() == PROTpackage && !hasPackageAccess(sc, d))
 
-		error(loc, "%s %s.%s is not accessible from %s",
-		    d->kind(), d->getModule()->toChars(), d->toChars(), sc->module->toChars());
+	    error(loc, "%s %s.%s is not accessible from %s",
+		d->kind(), d->getModule()->toChars(), d->toChars(), sc->module->toChars());
     }
     else if (e->type->ty == Tclass)
     {   // Do access check
--- a/dmd/aggregate.h	Wed Jan 06 19:53:35 2010 +0100
+++ b/dmd/aggregate.h	Sat Feb 06 15:53:52 2010 +0000
@@ -19,9 +19,11 @@
 
 #include "dsymbol.h"
 
+#if IN_LLVM
 #include <vector>
 #include <set>
 #include <map>
+#endif
 
 struct Identifier;
 struct Type;
@@ -38,6 +40,7 @@
 struct VarDeclaration;
 struct dt_t;
 
+#if IN_LLVM
 namespace llvm
 {
     class Type;
@@ -46,6 +49,7 @@
     class ConstantStruct;
     class GlobalVariable;
 }
+#endif
 
 struct AggregateDeclaration : ScopeDsymbol
 {
--- a/dmd/arrayop.c	Wed Jan 06 19:53:35 2010 +0100
+++ b/dmd/arrayop.c	Sat Feb 06 15:53:52 2010 +0000
@@ -24,6 +24,15 @@
 #include "module.h"
 #include "init.h"
 
+#if IN_DMD
+extern int binary(const char *p , const char **tab, int high);
+
+/**************************************
+ * Hash table of array op functions already generated or known about.
+ */
+
+StringTable arrayfuncs;
+#endif
 
 /***********************************
  * Construct the array operation expression.
--- a/dmd/attrib.c	Wed Jan 06 19:53:35 2010 +0100
+++ b/dmd/attrib.c	Sat Feb 06 15:53:52 2010 +0000
@@ -392,6 +392,8 @@
 	    scstc &= ~(STCconst | STCimmutable | STCmanifest);
 	if (stc & (STCgshared | STCshared | STCtls))
 	    scstc &= ~(STCgshared | STCshared | STCtls);
+	if (stc & (STCsafe | STCtrusted | STCsystem))
+	    scstc &= ~(STCsafe | STCtrusted | STCsystem);
 	scstc |= stc;
 
 	setScopeNewSc(sc, scstc, sc->linkage, sc->protection, sc->explicitProtection, sc->structalign);
@@ -415,6 +417,8 @@
 	    scstc &= ~(STCconst | STCimmutable | STCmanifest);
 	if (stc & (STCgshared | STCshared | STCtls))
 	    scstc &= ~(STCgshared | STCshared | STCtls);
+	if (stc & (STCsafe | STCtrusted | STCsystem))
+	    scstc &= ~(STCsafe | STCtrusted | STCsystem);
 	scstc |= stc;
 
 	semanticNewSc(sc, scstc, sc->linkage, sc->protection, sc->explicitProtection, sc->structalign);
@@ -453,6 +457,10 @@
 	{ STCref,          TOKref },
 	{ STCtls,          TOKtls },
 	{ STCgshared,      TOKgshared },
+	{ STCproperty,     TOKat },
+	{ STCsafe,         TOKat },
+	{ STCtrusted,      TOKat },
+	{ STCdisable,       TOKat },
 #endif
     };
 
@@ -714,6 +722,8 @@
 	scope = NULL;
     }
 
+    unsigned dprogress_save = Module::dprogress;
+
     assert(sc->parent);
 
     Dsymbol *parent = sc->parent->pastMixin();
@@ -743,7 +753,7 @@
 
 	sc = sc->push();
 	sc->anonAgg = &aad;
-	sc->stc &= ~(STCauto | STCscope | STCstatic | STCtls);
+	sc->stc &= ~(STCauto | STCscope | STCstatic | STCtls | STCgshared);
 	sc->inunion = isunion;
 	sc->offset = 0;
 	sc->flags = 0;
@@ -775,6 +785,7 @@
 		scope->setNoFree();
 		scope->module->addDeferredSemantic(this);
 	    }
+	    Module::dprogress = dprogress_save;
 	    //printf("\tforward reference %p\n", this);
 	    return;
 	}
@@ -805,15 +816,15 @@
 	{
 	    VarDeclaration *v = (VarDeclaration *)aad.fields.data[i];
 
-        // LDC
+#if IN_LLVM
         v->offset2 = sc->offset;
-
+#endif
 	    v->offset += sc->offset;
 
-        // LDC
+#if IN_LLVM
         if (!v->anonDecl)
             v->anonDecl = this;
-
+#endif
 	    ad->fields.push(v);
 	}
 
@@ -1369,7 +1380,21 @@
 	char *name = (char *)mem.malloc(se->len + 1);
 	memcpy(name, se->string, se->len);
 	name[se->len] = 0;
+#if OMFOBJ
+	/* The OMF format allows library names to be inserted
+	 * into the object file. The linker will then automatically
+	 * search that library, too.
+	 */
 	obj_includelib(name);
+#elif ELFOBJ || MACHOBJ
+	/* The format does not allow embedded library names,
+	 * so instead append the library name to the list to be passed
+	 * to the linker.
+	 */
+	global.params.libfiles->push((void *) name);
+#else
+	error("pragma lib not supported");
+#endif
     }
 #if DMDV2
     else if (ident == Id::startaddress)
--- a/dmd/class.c	Wed Jan 06 19:53:35 2010 +0100
+++ b/dmd/class.c	Sat Feb 06 15:53:52 2010 +0000
@@ -264,6 +264,7 @@
 	scx = scope;		// save so we don't make redundant copies
 	scope = NULL;
     }
+    unsigned dprogress_save = Module::dprogress;
 #ifdef IN_GCC
     methods.setDim(0);
 #endif
@@ -628,6 +629,8 @@
 	scope->setNoFree();
 	scope->module->addDeferredSemantic(this);
 
+	Module::dprogress = dprogress_save;
+
 	//printf("\tsemantic('%s') failed due to forward references\n", toChars());
 	return;
     }
--- a/dmd/cond.c	Wed Jan 06 19:53:35 2010 +0100
+++ b/dmd/cond.c	Sat Feb 06 15:53:52 2010 +0000
@@ -142,10 +142,11 @@
 	"all",
 	"none",
 
-    // LDC
+#if IN_LLVM
     "LLVM", "LDC", "LLVM64",
     "PPC", "PPC64",
     "darwin","solaris","freebsd"
+#endif
     };
 
     for (unsigned i = 0; i < sizeof(reserved) / sizeof(reserved[0]); i++)
--- a/dmd/declaration.c	Wed Jan 06 19:53:35 2010 +0100
+++ b/dmd/declaration.c	Sat Feb 06 15:53:52 2010 +0000
@@ -835,7 +835,7 @@
 	    //printf("declaring field %s of type %s\n", v->toChars(), v->type->toChars());
 	    v->semantic(sc);
             
-/*
+#if !IN_LLVM
 // removed for LDC since TupleDeclaration::toObj already creates the fields;
 // adding them to the scope again leads to duplicates
 	    if (sc->scopesym)
@@ -843,7 +843,8 @@
 		if (sc->scopesym->members)
 		    sc->scopesym->members->push(v);
 	    }
-*/
+#endif
+
 	    Expression *e = new DsymbolExp(loc, v);
 	    exps->data[i] = e;
 	}
@@ -1490,9 +1491,10 @@
 void TypeInfoDeclaration::semantic(Scope *sc)
 {
     assert(linkage == LINKc);
-    // LDC
+#if IN_LLVM
     if (!global.params.useAvailableExternally)
         availableExternally = false;
+#endif
 }
 
 /***************************** TypeInfoConstDeclaration **********************/
--- a/dmd/declaration.h	Wed Jan 06 19:53:35 2010 +0100
+++ b/dmd/declaration.h	Sat Feb 06 15:53:52 2010 +0000
@@ -15,9 +15,11 @@
 #pragma once
 #endif /* __DMC__ */
 
+#if IN_LLVM
 #include <set>
 #include <map>
 #include <string>
+#endif
 
 #include "dsymbol.h"
 #include "lexer.h"
--- a/dmd/dsymbol.c	Wed Jan 06 19:53:35 2010 +0100
+++ b/dmd/dsymbol.c	Sat Feb 06 15:53:52 2010 +0000
@@ -29,7 +29,9 @@
 #include "import.h"
 #include "template.h"
 #include "attrib.h"
+#if IN_LLVM
 #include "../gen/enums.h"
+#endif
 
 /****************************** Dsymbol ******************************/
 
--- a/dmd/dsymbol.h	Wed Jan 06 19:53:35 2010 +0100
+++ b/dmd/dsymbol.h	Sat Feb 06 15:53:52 2010 +0000
@@ -21,8 +21,9 @@
 #include "mars.h"
 #include "arraytypes.h"
 
-// llvm
+#if IN_LLVM
 #include "../ir/irdsymbol.h"
+#endif
 
 struct Identifier;
 struct Scope;
@@ -51,6 +52,9 @@
 struct NewDeclaration;
 struct VarDeclaration;
 struct AttribDeclaration;
+#if IN_DMD
+struct Symbol;
+#endif
 struct Package;
 struct Module;
 struct Import;
@@ -76,9 +80,6 @@
 #if TARGET_NET
 struct PragmaScope;
 #endif
-#if IN_DMD
-struct Symbol;
-#endif
 #if IN_GCC
 union tree_node;
 typedef union tree_node TYPE;
@@ -109,6 +110,18 @@
     PROTexport,
 };
 
+/* State of symbol in winding its way through the passes of the compiler
+ */
+enum PASS
+{
+    PASSinit,		// initial state
+    PASSsemantic,	// semantic() started
+    PASSsemanticdone,	// semantic() done
+    PASSsemantic2,	// semantic2() run
+    PASSsemantic3,	// semantic3() started
+    PASSsemantic3done,	// semantic3() done
+    PASSobj,		// toObjFile() run
+};
 
 struct Dsymbol : Object
 {
--- a/dmd/enum.c	Wed Jan 06 19:53:35 2010 +0100
+++ b/dmd/enum.c	Sat Feb 06 15:53:52 2010 +0000
@@ -1,5 +1,5 @@
 
-// Copyright (c) 1999-2009 by Digital Mars
+// Copyright (c) 1999-2010 by Digital Mars
 // All Rights Reserved
 // written by Walter Bright
 // http://www.digitalmars.com
@@ -14,6 +14,7 @@
 #include "enum.h"
 #include "mtype.h"
 #include "scope.h"
+#include "module.h"
 #include "declaration.h"
 
 /********************************* EnumDeclaration ****************************/
@@ -74,6 +75,8 @@
         scope = NULL;
     }
 
+    unsigned dprogress_save = Module::dprogress;
+
     if (sc->stc & STCdeprecated)
 	isdeprecated = 1;
 
@@ -97,6 +100,7 @@
     }
 
     isdone = 1;
+    Module::dprogress++;
 
     t = isAnonymous() ? memtype : type;
     symtab = new DsymbolTable();
--- a/dmd/expression.c	Wed Jan 06 19:53:35 2010 +0100
+++ b/dmd/expression.c	Sat Feb 06 15:53:52 2010 +0000
@@ -1,6 +1,6 @@
 
 // Compiler implementation of the D programming language
-// Copyright (c) 1999-2009 by Digital Mars
+// Copyright (c) 1999-2010 by Digital Mars
 // All Rights Reserved
 // written by Walter Bright
 // http://www.digitalmars.com
@@ -3710,7 +3710,6 @@
 			break;
 		    }
 		}
-		
 	    }
 	}
 	else if (thisexp)
@@ -8777,8 +8776,11 @@
     typeCombine(sc);
     e1->checkIntegral();
     e2 = e2->checkIntegral();
-    //e2 = e2->castTo(sc, Type::tshiftcnt);
-    e2 = e2->castTo(sc, e1->type); // LDC
+#if !IN_LLVM
+    e2 = e2->castTo(sc, Type::tshiftcnt);
+#else
+    e2 = e2->castTo(sc, e1->type);
+#endif
     return this;
 }
 
@@ -8806,8 +8808,11 @@
     typeCombine(sc);
     e1->checkIntegral();
     e2 = e2->checkIntegral();
-    //e2 = e2->castTo(sc, Type::tshiftcnt);
-    e2 = e2->castTo(sc, e1->type); // LDC
+#if !IN_LLVM
+    e2 = e2->castTo(sc, Type::tshiftcnt);
+#else
+    e2 = e2->castTo(sc, e1->type);
+#endif
     return this;
 }
 
@@ -8835,8 +8840,11 @@
     typeCombine(sc);
     e1->checkIntegral();
     e2 = e2->checkIntegral();
-    //e2 = e2->castTo(sc, Type::tshiftcnt);
-    e2 = e2->castTo(sc, e1->type); // LDC
+#if !IN_LLVM
+    e2 = e2->castTo(sc, Type::tshiftcnt);
+#else
+    e2 = e2->castTo(sc, e1->type);
+#endif
     return this;
 }
 
@@ -9323,8 +9331,11 @@
 	e1 = e1->checkIntegral();
 	e2 = e2->checkIntegral();
 	e1 = e1->integralPromotions(sc);
-	//e2 = e2->castTo(sc, Type::tshiftcnt);
-    e2 = e2->castTo(sc, e1->type); // LDC
+#if !IN_LLVM
+	e2 = e2->castTo(sc, Type::tshiftcnt);
+#else
+    e2 = e2->castTo(sc, e1->type);
+#endif
 	type = e1->type;
     }
     return this;
@@ -9348,8 +9359,11 @@
 	e1 = e1->checkIntegral();
 	e2 = e2->checkIntegral();
 	e1 = e1->integralPromotions(sc);
-	//e2 = e2->castTo(sc, Type::tshiftcnt);
-    e2 = e2->castTo(sc, e1->type); // LDC
+#if !IN_LLVM
+	e2 = e2->castTo(sc, Type::tshiftcnt);
+#else
+    e2 = e2->castTo(sc, e1->type);
+#endif
 	type = e1->type;
     }
     return this;
@@ -9373,8 +9387,11 @@
 	e1 = e1->checkIntegral();
 	e2 = e2->checkIntegral();
 	e1 = e1->integralPromotions(sc);
-	//e2 = e2->castTo(sc, Type::tshiftcnt);
-    e2 = e2->castTo(sc, e1->type); // LDC
+#if !IN_LLVM
+	e2 = e2->castTo(sc, Type::tshiftcnt);
+#else
+    e2 = e2->castTo(sc, e1->type);
+#endif
 	type = e1->type;
     }
     return this;
--- a/dmd/expression.h	Wed Jan 06 19:53:35 2010 +0100
+++ b/dmd/expression.h	Sat Feb 06 15:53:52 2010 +0000
@@ -1,6 +1,6 @@
 
 // Compiler implementation of the D programming language
-// Copyright (c) 1999-2009 by Digital Mars
+// Copyright (c) 1999-2010 by Digital Mars
 // All Rights Reserved
 // written by Walter Bright
 // http://www.digitalmars.com
@@ -645,6 +645,7 @@
 
     SymOffExp(Loc loc, Declaration *var, unsigned offset);
     Expression *semantic(Scope *sc);
+    Expression *interpret(InterState *istate);
     void checkEscape();
     void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
     int isConst();
@@ -722,6 +723,7 @@
     FuncExp(Loc loc, FuncLiteralDeclaration *fd);
     Expression *syntaxCopy();
     Expression *semantic(Scope *sc);
+    Expression *interpret(InterState *istate);
     void scanForNestedRef(Scope *sc);
     char *toChars();
     void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
@@ -985,6 +987,7 @@
 
     DelegateExp(Loc loc, Expression *e, FuncDeclaration *func);
     Expression *semantic(Scope *sc);
+    Expression *interpret(InterState *istate);
     MATCH implicitConvTo(Type *t);
     Expression *castTo(Scope *sc, Type *t);
     void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
--- a/dmd/func.c	Wed Jan 06 19:53:35 2010 +0100
+++ b/dmd/func.c	Sat Feb 06 15:53:52 2010 +0000
@@ -1,5 +1,5 @@
 // Compiler implementation of the D programming language
-// Copyright (c) 1999-2009 by Digital Mars
+// Copyright (c) 1999-2010 by Digital Mars
 // All Rights Reserved
 // written by Walter Bright
 // http://www.digitalmars.com
@@ -65,7 +65,7 @@
     inlineNest = 0;
     inlineAsm = 0;
     cantInterpret = 0;
-    semanticRun = 0;
+    semanticRun = PASSinit;
 #if DMDV1
     nestedFrameRef = 0;
 #endif
@@ -131,8 +131,9 @@
     f->fbody    = fbody    ? fbody->syntaxCopy()    : NULL;
     assert(!fthrows); // deprecated
 
-    // LDC
+#if IN_LLVM
     f->intrinsicName = intrinsicName;
+#endif
 
     return f;
 }
@@ -155,7 +156,7 @@
     printf("type: %p, %s\n", type, type->toChars());
 #endif
 
-    if (semanticRun && isFuncLiteralDeclaration())
+    if (semanticRun != PASSinit && isFuncLiteralDeclaration())
     {
 	/* Member functions that have return types that are
 	 * forward references can have semantic() run more than
@@ -164,8 +165,24 @@
 	 */
 	return;
     }
-    assert(semanticRun <= 1);
-    semanticRun = 1;
+    parent = sc->parent;
+    Dsymbol *parent = toParent();
+
+    if (semanticRun == PASSsemanticdone)
+    {
+	if (!parent->isClassDeclaration())
+	    return;
+	// need to re-run semantic() in order to set the class's vtbl[]
+    }
+    else
+    {
+	assert(semanticRun <= PASSsemantic);
+	semanticRun = PASSsemantic;
+    }
+
+    unsigned dprogress_save = Module::dprogress;
+
+    foverrides.setDim(0);	// reset in case semantic() is being retried for this function
 
     if (!type->deco)
     {
@@ -181,15 +198,9 @@
     size_t nparams = Parameter::dim(f->parameters);
 
     linkage = sc->linkage;
-//    if (!parent)
-    {
-	//parent = sc->scopesym;
-	parent = sc->parent;
-    }
     protection = sc->protection;
     storage_class |= sc->stc;
     //printf("function storage_class = x%x\n", storage_class);
-    Dsymbol *parent = toParent();
 
     if (ident == Id::ctor && !isCtorDeclaration())
 	error("_ctor is reserved for constructors");
@@ -267,7 +278,7 @@
 	    isInvariantDeclaration() ||
 	    isUnitTestDeclaration() || isNewDeclaration() || isDelete())
 	    error("special function not allowed in interface %s", id->toChars());
-	if (fbody)
+	if (fbody && isVirtual())
 	    error("function body is not abstract in interface %s", id->toChars());
     }
 
@@ -337,8 +348,12 @@
 	    goto Ldone;
 	}
 
-	// Find index of existing function in vtbl[] to override
-	vi = findVtblIndex(&cd->vtbl, cd->baseClass ? cd->baseClass->vtbl.dim : 0);
+	/* Find index of existing function in base class's vtbl[] to override
+	 * (the index will be the same as in cd's current vtbl[])
+	 */
+	vi = cd->baseClass ? findVtblIndex(&cd->baseClass->vtbl, cd->baseClass->vtbl.dim)
+			   : -1;
+
 	switch (vi)
 	{
 	    case -1:
@@ -378,10 +393,11 @@
 
 	    case -2:	// can't determine because of fwd refs
 		cd->sizeok = 2;	// can't finish due to forward reference
+		Module::dprogress = dprogress_save;
 		return;
 
 	    default:
-	    {   FuncDeclaration *fdv = (FuncDeclaration *)cd->vtbl.data[vi];
+	    {   FuncDeclaration *fdv = (FuncDeclaration *)cd->baseClass->vtbl.data[vi];
 		// This function is covariant with fdv
 		if (fdv->isFinal())
 		    error("cannot override final function %s", fdv->toPrettyChars());
@@ -455,6 +471,7 @@
 
 		case -2:
 		    cd->sizeok = 2;	// can't finish due to forward reference
+		    Module::dprogress = dprogress_save;
 		    return;
 
 		default:
@@ -472,19 +489,22 @@
 			/* Only need to have a tintro if the vptr
 			 * offsets differ
 			 */
+			unsigned errors = global.errors;
+			global.gag++;            // suppress printing of error messages
 			int offset;
-			if (fdv->type->nextOf()->isBaseOf(type->nextOf(), &offset))
+			int baseOf = fdv->type->nextOf()->isBaseOf(type->nextOf(), &offset);
+			global.gag--;            // suppress printing of error messages
+			if (errors != global.errors)
+			{
+			    // any error in isBaseOf() is a forward reference error, so we bail out
+			    global.errors = errors;
+			    cd->sizeok = 2;    // can't finish due to forward reference
+			    Module::dprogress = dprogress_save;
+			    return;
+			}
+			if (baseOf)
 			{
 			    ti = fdv->type;
-#if 0
-			    if (offset)
-				ti = fdv->type;
-			    else if (type->nextOf()->ty == Tclass)
-			    {   ClassDeclaration *cdn = ((TypeClass *)type->nextOf())->sym;
-				if (cdn && cdn->sizeok != 1)
-				    ti = fdv->type;
-			    }
-#endif
 			}
 		    }
 		    if (ti)
@@ -596,7 +616,7 @@
 	}
     }
 
-    if (isVirtual())
+    if (isVirtual() && semanticRun != PASSsemanticdone)
     {
 	/* Rewrite contracts as nested functions, then call them.
 	 * Doing it as nested functions means that overriding functions
@@ -652,6 +672,9 @@
     }
 
 Ldone:
+    Module::dprogress++;
+    semanticRun = PASSsemanticdone;
+
     /* Save scope for possible later use (if we need the
      * function internals)
      */
@@ -688,14 +711,14 @@
     //printf("\tlinkage = %d\n", sc->linkage);
 
     //printf(" sc->incontract = %d\n", sc->incontract);
-    if (semanticRun >= 3)
+    if (semanticRun >= PASSsemantic3)
 	return;
-    semanticRun = 3;
-
-    // LDC
+    semanticRun = PASSsemantic3;
+
+#if IN_LLVM
     if (!global.params.useAvailableExternally)
         availableExternally = false;
-
+#endif
     if (!type || type->ty != Tfunction)
 	return;
     f = (TypeFunction *)(type);
@@ -1466,7 +1489,7 @@
 	sc2->callSuper = 0;
 	sc2->pop();
     }
-    semanticRun = 4;
+    semanticRun = PASSsemantic3done;
 }
 
 void FuncDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
@@ -1638,6 +1661,7 @@
 /*************************************************
  * Find index of function in vtbl[0..dim] that
  * this function overrides.
+ * Prefer an exact match to a covariant one.
  * Returns:
  *	-1	didn't find one
  *	-2	can't determine because of forward references
@@ -1645,11 +1669,16 @@
 
 int FuncDeclaration::findVtblIndex(Array *vtbl, int dim)
 {
+    FuncDeclaration *mismatch = NULL;
+    int bestvi = -1;
     for (int vi = 0; vi < dim; vi++)
     {
 	FuncDeclaration *fdv = ((Dsymbol *)vtbl->data[vi])->isFuncDeclaration();
 	if (fdv && fdv->ident == ident)
 	{
+	    if (type->equals(fdv->type))	// if exact match
+	        return vi;			// no need to look further
+
 	    int cov = type->covariant(fdv->type);
 	    //printf("\tbaseclass cov = %d\n", cov);
 	    switch (cov)
@@ -1658,15 +1687,12 @@
 		    break;
 
 		case 1:
-		    return vi;
+	            bestvi = vi;	// covariant, but not identical
+	            break;		// keep looking for an exact match
 
 		case 2:
-		    //type->print();
-		    //fdv->type->print();
-		    //printf("%s %s\n", type->deco, fdv->type->deco);
-		    error("of type %s overrides but is not covariant with %s of type %s",
-			type->toChars(), fdv->toPrettyChars(), fdv->type->toChars());
-		    break;
+		    mismatch = fdv;	// overrides, but is not covariant
+		    break;		// keep looking for an exact match
 
 		case 3:
 		    return -2;	// forward references
@@ -1676,7 +1702,15 @@
 	    }
 	}
     }
-    return -1;
+    if (bestvi == -1 && mismatch)
+    {
+	//type->print();
+	//mismatch->type->print();
+	//printf("%s %s\n", type->deco, mismatch->type->deco);
+	error("of type %s overrides but is not covariant with %s of type %s",
+	    type->toChars(), mismatch->toPrettyChars(), mismatch->type->toChars());
+    }
+    return bestvi;
 }
 
 /****************************************************
@@ -2554,7 +2588,7 @@
 	id = "__dgliteral";
     else
 	id = "__funcliteral";
-    this->ident = Identifier::generateId(id);
+    this->ident = Lexer::uniqueId(id);
     this->tok = tok;
     this->fes = fes;
     //printf("FuncLiteralDeclaration() id = '%s', type = '%s'\n", this->ident->toChars(), type->toChars());
@@ -2568,7 +2602,9 @@
     if (s)
 	f = (FuncLiteralDeclaration *)s;
     else
-	f = new FuncLiteralDeclaration(loc, endloc, type->syntaxCopy(), tok, fes);
+    {	f = new FuncLiteralDeclaration(loc, endloc, type->syntaxCopy(), tok, fes);
+	f->ident = ident;		// keep old identifier
+    }
     FuncDeclaration::syntaxCopy(f);
     return f;
 }
@@ -2634,19 +2670,14 @@
 
 void CtorDeclaration::semantic(Scope *sc)
 {
-    ClassDeclaration *cd;
-    Type *tret;
-
-    //printf("CtorDeclaration::semantic()\n");
-    if (type)
-	return;
-
+    //printf("CtorDeclaration::semantic() %s\n", toChars());
     sc = sc->push();
     sc->stc &= ~STCstatic;		// not a static constructor
 
     parent = sc->parent;
     Dsymbol *parent = toParent();
-    cd = parent->isClassDeclaration();
+    Type *tret;
+    ClassDeclaration *cd = parent->isClassDeclaration();
     if (!cd)
     {
 	error("constructors are only for class definitions");
@@ -2655,7 +2686,8 @@
     }
     else
 	tret = cd->type; //->referenceTo();
-    type = new TypeFunction(arguments, tret, varargs, LINKd);
+    if (!type)
+	type = new TypeFunction(arguments, tret, varargs, LINKd);
 #if STRUCTTHISREF
     if (ad && ad->isStructDeclaration())
 	((TypeFunction *)type)->isref = 1;
@@ -2670,7 +2702,7 @@
     // Append:
     //	return this;
     // to the function body
-    if (fbody)
+    if (fbody && semanticRun < PASSsemantic)
     {
 	Expression *e = new ThisExp(loc);
 	Statement *s = new ReturnStatement(loc, e);
@@ -2744,6 +2776,7 @@
 {
     //printf("PostBlitDeclaration::semantic() %s\n", toChars());
     //printf("ident: %s, %s, %p, %p\n", ident->toChars(), Id::dtor->toChars(), ident, Id::dtor);
+    //printf("stc = x%llx\n", sc->stc);
     parent = sc->parent;
     Dsymbol *parent = toParent();
     StructDeclaration *ad = parent->isStructDeclaration();
@@ -2751,9 +2784,11 @@
     {
 	error("post blits are only for struct/union definitions, not %s %s", parent->kind(), parent->toChars());
     }
-    else if (ident == Id::_postblit)
+    else if (ident == Id::_postblit && semanticRun < PASSsemantic)
 	ad->postblits.push(this);
-    type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd);
+
+    if (!type)
+	type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd);
 
     sc = sc->push();
     sc->stc &= ~STCstatic;		// not static
@@ -2786,9 +2821,7 @@
 
 void PostBlitDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
 {
-    if (hgs->hdrgen)
-	return;
-    buf->writestring("=this()");
+    buf->writestring("this(this)");
     bodyToCBuffer(buf, hgs);
 }
 #endif
@@ -2825,9 +2858,11 @@
 	error("destructors are only for class/struct/union definitions, not %s %s", parent->kind(), parent->toChars());
 	fatal();
     }
-    else
+    else if (semanticRun < PASSsemantic)
 	cd->dtors.push(this);
-    type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd);
+
+    if (!type)
+	type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd);
 
     sc = sc->push();
     sc->stc &= ~STCstatic;		// not a static destructor
@@ -2893,10 +2928,8 @@
 
 Dsymbol *StaticCtorDeclaration::syntaxCopy(Dsymbol *s)
 {
-    StaticCtorDeclaration *scd;
-
     assert(!s);
-    scd = new StaticCtorDeclaration(loc, endloc);
+    StaticCtorDeclaration *scd = new StaticCtorDeclaration(loc, endloc);
     return FuncDeclaration::syntaxCopy(scd);
 }
 
@@ -2905,13 +2938,14 @@
 {
     //printf("StaticCtorDeclaration::semantic()\n");
 
-    type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd);
+    if (!type)
+	type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd);
 
     /* If the static ctor appears within a template instantiation,
      * it could get called multiple times by the module constructors
      * for different modules. Thus, protect it with a gate.
      */
-    if (inTemplateInstance())
+    if (inTemplateInstance() && semanticRun < PASSsemantic)
     {
 	/* Add this prefix to the function:
 	 *	static int gate;
@@ -2943,6 +2977,7 @@
 	m = sc->module;
     if (m)
     {	m->needmoduleinfo = 1;
+	//printf("module1 %s needs moduleinfo\n", m->toChars());
 #ifdef IN_GCC
 	m->strictlyneedmoduleinfo = 1;
 #endif
@@ -3005,20 +3040,16 @@
 
 void StaticDtorDeclaration::semantic(Scope *sc)
 {
-    ClassDeclaration *cd;
-    Type *tret;
-
-    cd = sc->scopesym->isClassDeclaration();
-    if (!cd)
-    {
-    }
-    type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd);
+    ClassDeclaration *cd = sc->scopesym->isClassDeclaration();
+
+    if (!type)
+	type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd);
 
     /* If the static ctor appears within a template instantiation,
      * it could get called multiple times by the module constructors
      * for different modules. Thus, protect it with a gate.
      */
-    if (inTemplateInstance())
+    if (inTemplateInstance() && semanticRun < PASSsemantic)
     {
 	/* Add this prefix to the function:
 	 *	static int gate;
@@ -3112,23 +3143,21 @@
 
 void InvariantDeclaration::semantic(Scope *sc)
 {
-    AggregateDeclaration *ad;
-    Type *tret;
-
     parent = sc->parent;
     Dsymbol *parent = toParent();
-    ad = parent->isAggregateDeclaration();
+    AggregateDeclaration *ad = parent->isAggregateDeclaration();
     if (!ad)
     {
 	error("invariants are only for struct/union/class definitions");
 	return;
     }
-    else if (ad->inv && ad->inv != this)
+    else if (ad->inv && ad->inv != this && semanticRun < PASSsemantic)
     {
 	error("more than one invariant for %s", ad->toChars());
     }
     ad->inv = this;
-    type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd);
+    if (!type)
+	type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd);
 
     sc = sc->push();
     sc->stc &= ~STCstatic;		// not a static invariant
@@ -3195,7 +3224,8 @@
 {
     if (global.params.useUnitTests)
     {
-	type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd);
+	if (!type)
+	    type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd);
 	Scope *sc2 = sc->push();
 	sc2->linkage = LINKd;
 	FuncDeclaration::semantic(sc2);
@@ -3271,20 +3301,18 @@
 
 void NewDeclaration::semantic(Scope *sc)
 {
-    ClassDeclaration *cd;
-    Type *tret;
-
     //printf("NewDeclaration::semantic()\n");
 
     parent = sc->parent;
     Dsymbol *parent = toParent();
-    cd = parent->isClassDeclaration();
+    ClassDeclaration *cd = parent->isClassDeclaration();
     if (!cd && !parent->isStructDeclaration())
     {
 	error("new allocators only are for class or struct definitions");
     }
-    tret = Type::tvoid->pointerTo();
-    type = new TypeFunction(arguments, tret, varargs, LINKd);
+    Type *tret = Type::tvoid->pointerTo();
+    if (!type)
+	type = new TypeFunction(arguments, tret, varargs, LINKd);
 
     type = type->semantic(loc, sc);
     assert(type->ty == Tfunction);
@@ -3357,18 +3385,17 @@
 
 void DeleteDeclaration::semantic(Scope *sc)
 {
-    ClassDeclaration *cd;
-
     //printf("DeleteDeclaration::semantic()\n");
 
     parent = sc->parent;
     Dsymbol *parent = toParent();
-    cd = parent->isClassDeclaration();
+    ClassDeclaration *cd = parent->isClassDeclaration();
     if (!cd && !parent->isStructDeclaration())
     {
 	error("new allocators only are for class or struct definitions");
     }
-    type = new TypeFunction(arguments, Type::tvoid, 0, LINKd);
+    if (!type)
+	type = new TypeFunction(arguments, Type::tvoid, 0, LINKd);
 
     type = type->semantic(loc, sc);
     assert(type->ty == Tfunction);
--- a/dmd/identifier.h	Wed Jan 06 19:53:35 2010 +0100
+++ b/dmd/identifier.h	Sat Feb 06 15:53:52 2010 +0000
@@ -16,11 +16,12 @@
 #endif /* __DMC__ */
 
 #include "root.h"
-
+#if IN_LLVM
 namespace llvm
 {
     class Value;
 }
+#endif
 
 struct Identifier : Object
 {
--- a/dmd/inline.c	Wed Jan 06 19:53:35 2010 +0100
+++ b/dmd/inline.c	Sat Feb 06 15:53:52 2010 +0000
@@ -1281,7 +1281,7 @@
     if (needThis() && !hasthis)
 	return 0;
 
-    if (inlineNest || (semanticRun < 3 && !hdrscan))
+    if (inlineNest || (semanticRun < PASSsemantic3 && !hdrscan))
     {
 #if CANINLINE_LOG
 	printf("\t1: no, inlineNest = %d, semanticRun = %d\n", inlineNest, semanticRun);
--- a/dmd/interpret.c	Wed Jan 06 19:53:35 2010 +0100
+++ b/dmd/interpret.c	Sat Feb 06 15:53:52 2010 +0000
@@ -1,6 +1,6 @@
 
 // Compiler implementation of the D programming language
-// Copyright (c) 1999-2009 by Digital Mars
+// Copyright (c) 1999-2010 by Digital Mars
 // All Rights Reserved
 // written by Walter Bright
 // http://www.digitalmars.com
@@ -52,6 +52,8 @@
 Expression *interpret_keys(InterState *istate, Expression *earg, FuncDeclaration *fd);
 Expression *interpret_values(InterState *istate, Expression *earg, FuncDeclaration *fd);
 
+ArrayLiteralExp *createBlockDuplicatedArrayLiteral(Type *type, Expression *elem, size_t dim);
+
 /*************************************
  * Attempt to interpret a function given the arguments.
  * Input:
@@ -92,7 +94,7 @@
     }
 #endif
 
-    if (cantInterpret || semanticRun == 3)
+    if (cantInterpret || semanticRun == PASSsemantic3)
 	return NULL;
 
     if (!fbody)
@@ -100,13 +102,13 @@
 	return NULL;
     }
 
-    if (semanticRun < 3 && scope)
+    if (semanticRun < PASSsemantic3 && scope)
     {
 	semantic3(scope);
 	if (global.errors)	// if errors compiling this function
 	    return NULL;
     }
-    if (semanticRun < 4)
+    if (semanticRun < PASSsemantic3done)
 	return NULL;
 
     Type *tb = type->toBasetype();
@@ -160,7 +162,7 @@
 	{   Expression *earg = (Expression *)arguments->data[i];
 	    Parameter *arg = Parameter::getNth(tf->parameters, i);
 
-	    if (arg->storageClass & (STCout | STCref))
+	    if (arg->storageClass & (STCout | STCref | STClazy))
 	    {
 	    }
 	    else
@@ -1005,6 +1007,35 @@
     return this;
 }
 
+Expression *FuncExp::interpret(InterState *istate)
+{
+#if LOG
+    printf("FuncExp::interpret() %s\n", toChars());
+#endif
+    return this;
+}
+
+Expression *SymOffExp::interpret(InterState *istate)
+{
+#if LOG
+    printf("SymOffExp::interpret() %s\n", toChars());
+#endif
+    if (var->isFuncDeclaration() && offset == 0)
+    {
+	return this;
+    }
+    error("Cannot interpret %s at compile time", toChars());
+    return EXP_CANT_INTERPRET;
+}
+
+Expression *DelegateExp::interpret(InterState *istate)
+{
+#if LOG
+    printf("DelegateExp::interpret() %s\n", toChars());
+#endif
+    return this;
+}
+
 Expression *getVarExp(Loc loc, InterState *istate, Declaration *d)
 {
     Expression *e = EXP_CANT_INTERPRET;
@@ -1013,6 +1044,11 @@
     if (v)
     {
 #if DMDV2
+	/* Magic variable __ctfe always returns true when interpreting
+	 */
+	if (v->ident == Id::ctfe)
+	    return new IntegerExp(loc, 1, Type::tbool);
+
 	if ((v->isConst() || v->isImmutable() || v->storage_class & STCmanifest) && v->init && !v->value)
 #else
 	if (v->isConst() && v->init)
@@ -1021,6 +1057,16 @@
 	    if (e && !e->type)
 		e->type = v->type;
 	}
+	else if (v->isCTFE() && !v->value)
+	{
+	    if (v->init)
+	    {
+		e = v->init->toExpression();
+		e = e->interpret(istate);
+	    }
+	    else // This should never happen
+		e = v->type->defaultInitLiteral();
+	}
 	else
 	{   e = v->value;
 	    if (!v->isCTFE())
@@ -1482,7 +1528,7 @@
 }
 
 /***************************************
- * Returns oldelems[0..insertpoint] ~ newelems ~ oldelems[insertpoint..$]
+ * Returns oldelems[0..insertpoint] ~ newelems ~ oldelems[insertpoint+newelems.length..$]
  */
 Expressions *spliceElements(Expressions *oldelems,
 	Expressions *newelems, size_t insertpoint)
@@ -1499,6 +1545,26 @@
     return expsx;
 }
 
+/***************************************
+ * Returns oldstr[0..insertpoint] ~ newstr ~ oldstr[insertpoint+newlen..$]
+ */
+StringExp *spliceStringExp(StringExp *oldstr, StringExp *newstr, size_t insertpoint)
+{
+    assert(oldstr->sz==newstr->sz);
+    unsigned char *s;
+    size_t oldlen = oldstr->len;
+    size_t newlen = newstr->len;
+    size_t sz = oldstr->sz;
+    s = (unsigned char *)mem.calloc(oldlen + 1, sz);
+    memcpy(s, oldstr->string, oldlen * sz);
+    memcpy(s + insertpoint * sz, newstr->string, newlen * sz);
+    StringExp *se2 = new StringExp(oldstr->loc, s, oldlen);
+    se2->committed = oldstr->committed;
+    se2->postfix = oldstr->postfix;
+    se2->type = oldstr->type;
+    return se2;
+}
+
 /******************************
  * Create an array literal consisting of 'elem' duplicated 'dim' times.
  */
@@ -1514,6 +1580,28 @@
     return ae;
 }
 
+/******************************
+ * Create a string literal consisting of 'value' duplicated 'dim' times.
+ */
+StringExp *createBlockDuplicatedStringLiteral(Type *type,
+	unsigned value, size_t dim, int sz)
+{
+    unsigned char *s;
+    s = (unsigned char *)mem.calloc(dim + 1, sz);
+    for (int elemi=0; elemi<dim; ++elemi)
+    {
+    	switch (sz)
+	{
+	    case 1:	s[elemi] = value; break;
+	    case 2:	((unsigned short *)s)[elemi] = value; break;
+	    case 4:	((unsigned *)s)[elemi] = value; break;
+	    default:    assert(0);
+	}
+    }
+    StringExp *se = new StringExp(0, s, dim);
+    se->type = type;
+    return se;
+}
 
 /********************************
  *  Add v to the istate list, unless it already exists there.
@@ -1582,13 +1670,16 @@
     // To reduce code complexity of handling dotvar expressions,
     // extract the aggregate now.
     Expression *aggregate;
-    if (e1->op == TOKdotvar) {
+    if (e1->op == TOKdotvar)
+    {
         aggregate = ((DotVarExp *)e1)->e1;
 	// Get rid of 'this'.
         if (aggregate->op == TOKthis && istate->localThis)
-            aggregate = istate->localThis;	
+            aggregate = istate->localThis;
     }
-    
+    if (e1->op == TOKthis && istate->localThis)
+	e1 = istate->localThis;
+
     /* Assignment to variable of the form:
      *	v = e2
      */
@@ -1623,7 +1714,8 @@
 	    if (e2 == EXP_CANT_INTERPRET)
 		return e2;
 
-	    addVarToInterstate(istate, v);
+	    if (istate)
+		addVarToInterstate(istate, v);
 	    v->value = e2;
 	    e = Cast(type, type, post ? ev : e2);
 	}
@@ -1668,16 +1760,21 @@
 	     * on the void value - to do that we'd need a VoidExp.
 	     * That's probably a good enhancement idea.
 	     */
-	    v->value = v->type->defaultInit();
+	    v->value = v->type->defaultInitLiteral();
 	}
 	Expression *vie = v->value;
+	assert(vie != EXP_CANT_INTERPRET);
+
 	if (vie->op == TOKvar)
 	{
 	    Declaration *d = ((VarExp *)vie)->var;
 	    vie = getVarExp(e1->loc, istate, d);
 	}
 	if (vie->op != TOKstructliteral)
+	{
+	    error("Cannot assign %s=%s in CTFE", v->toChars(), vie->toChars());
 	    return EXP_CANT_INTERPRET;
+	}
 	StructLiteralExp *se = (StructLiteralExp *)vie;
 	VarDeclaration *vf = ((DotVarExp *)e1)->var->isVarDeclaration();
 	if (!vf)
@@ -2015,19 +2112,19 @@
 	    error("%s cannot be modified at compile time", v->toChars());
 	    return EXP_CANT_INTERPRET;
 	}
-	    // Chase down rebinding of out and ref
-	    if (v->value && v->value->op == TOKvar)
-	    {
-		VarExp *ve2 = (VarExp *)v->value;
-		if (ve2->var->isStaticStructInitDeclaration())
-		{	// This can happen if v is a struct initialized to
-			// 0 using an __initZ SymbolDeclaration from
-			// TypeStruct::defaultInit()
-		}
-		else
-		    v = ve2->var->isVarDeclaration();
-		assert(v);
+       // Chase down rebinding of out and ref
+        if (v->value && v->value->op == TOKvar)
+        {
+	    VarExp *ve2 = (VarExp *)v->value;
+	    if (ve2->var->isStaticStructInitDeclaration())
+	    {	// This can happen if v is a struct initialized to
+		// 0 using an __initZ SymbolDeclaration from
+		// TypeStruct::defaultInit()
 	    }
+	    else
+		v = ve2->var->isVarDeclaration();
+	    assert(v);
+	}
 	/* Set the $ variable
 	 */
 	Expression *ee = v->value ? ArrayLength(Type::tsize_t, v->value)
@@ -2062,10 +2159,7 @@
 	    if (v->value->op == TOKarrayliteral)
 		dim = ((ArrayLiteralExp *)v->value)->elements->dim;
 	    else if (v->value->op ==TOKstring)
-	    {
-		error("String slice assignment is not yet supported in CTFE");
-		return EXP_CANT_INTERPRET;
-	    }
+	       dim = ((StringExp *)v->value)->len;
 	}
 	else
 	{
@@ -2075,69 +2169,89 @@
 	int upperbound = upper ? upper->toInteger() : dim;
 	int lowerbound = lower ? lower->toInteger() : 0;
 
-	ArrayLiteralExp *existing;
 	if (((int)lowerbound < 0) || (upperbound > dim))
 	{
-	    error("Array bounds [0..%d] exceeded in slice [%d..%d]", dim, lowerbound, upperbound);
+	    error("Array bounds [0..%d] exceeded in slice [%d..%d]",
+		dim, lowerbound, upperbound);
 	    return EXP_CANT_INTERPRET;
 	}
-	if (upperbound-lowerbound != dim)
+	// Could either be slice assignment (v[] = e[]), 
+	// or block assignment (v[] = val). 
+	// For the former, we check that the lengths match.
+	bool isSliceAssignment = (e2->op == TOKarrayliteral)
+	    || (e2->op == TOKstring);
+	size_t srclen = 0;
+	if (e2->op == TOKarrayliteral)
+	    srclen = ((ArrayLiteralExp *)e2)->elements->dim;
+	else if (e2->op == TOKstring)
+	    srclen = ((StringExp *)e2)->len;
+	if (isSliceAssignment && srclen != (upperbound - lowerbound))
 	{
-	    // Only modifying part of the array. Must create a new array literal.
-	    // If the existing array is uninitialized (this can only happen
-	    // with static arrays), create it.
-	    if (v->value && v->value->op == TOKarrayliteral)
-		    existing = (ArrayLiteralExp *)v->value;
-	    else
-	    {
-		// this can only happen with static arrays
-		existing = createBlockDuplicatedArrayLiteral(v->type, v->type->defaultInit(), dim);
-	    }
+	    error("Array length mismatch assigning [0..%d] to [%d..%d]", srclen, lowerbound, upperbound);
+	    return e;
 	}
-
 	if (e2->op == TOKarrayliteral)
 	{
 	    // Static array assignment from literal
 	    ArrayLiteralExp *ae = (ArrayLiteralExp *)e2;				
-	    if (ae->elements->dim != (upperbound - lowerbound))
-	    {
-		error("Array length mismatch assigning [0..%d] to [%d..%d]", ae->elements->dim, lowerbound, upperbound);
-		return e;
-	    }
 	    if (upperbound - lowerbound == dim)
 		v->value = ae;
 	    else
 	    {
+		ArrayLiteralExp *existing;
+		// Only modifying part of the array. Must create a new array literal.
+		// If the existing array is uninitialized (this can only happen
+		// with static arrays), create it.
+		if (v->value && v->value->op == TOKarrayliteral)
+		    existing = (ArrayLiteralExp *)v->value;
+		else // this can only happen with static arrays
+		    existing = createBlockDuplicatedArrayLiteral(v->type, v->type->defaultInit(), dim);
 		// value[] = value[0..lower] ~ ae ~ value[upper..$]
 		existing->elements = spliceElements(existing->elements, ae->elements, lowerbound);
 		v->value = existing;
 	    }
 	    return e2;
 	}
+	else if (e2->op == TOKstring)
+	{
+	    StringExp *se = (StringExp *)e2;
+	    if (upperbound-lowerbound == dim)
+	        v->value = e2;		
+	    else
+	    {
+		if (!v->value)
+		    v->value = createBlockDuplicatedStringLiteral(se->type,
+			se->type->defaultInit()->toInteger(), dim, se->sz);
+		if (v->value->op==TOKstring)
+	            v->value = spliceStringExp((StringExp *)v->value, se, lowerbound);
+		else
+	            error("String slice assignment is not yet supported in CTFE");
+	    }
+	    return e2;
+	}
 	else if (t->nextOf()->ty == e2->type->ty)
 	{
-	     // Static array block assignment
-	    if (upperbound-lowerbound ==dim)
+	    // Static array block assignment
+	    if (upperbound - lowerbound == dim)
 		v->value = createBlockDuplicatedArrayLiteral(v->type, e2, dim);
 	    else
 	    {
+		ArrayLiteralExp *existing;
+		// Only modifying part of the array. Must create a new array literal.
+		// If the existing array is uninitialized (this can only happen
+		// with static arrays), create it.
+		if (v->value && v->value->op == TOKarrayliteral)
+		    existing = (ArrayLiteralExp *)v->value;
+		else // this can only happen with static arrays
+		    existing = createBlockDuplicatedArrayLiteral(v->type, v->type->defaultInit(), dim);
 		// value[] = value[0..lower] ~ ae ~ value[upper..$]
-		existing->elements = spliceElements(existing->elements, createBlockDuplicatedArrayLiteral(v->type, e2, upperbound-lowerbound)->elements, lowerbound);
+		existing->elements = spliceElements(existing->elements,
+			createBlockDuplicatedArrayLiteral(v->type, e2, upperbound-lowerbound)->elements,
+			lowerbound);
 		v->value = existing;
 	    }				
 	    return e2;
 	}
-	else if (e2->op == TOKstring)
-	{
-	    StringExp *se = (StringExp *)e2;
-	    // This is problematic. char[8] should be storing
-	    // values as a string literal, not
-	    // as an array literal. Then, for static arrays, we
-	    // could do modifications
-	    // in-place, with a dramatic memory and speed improvement.
-	    error("String slice assignment is not yet supported in CTFE");
-	    return e2;
-	}
 	else
 	{
 	    error("Slice operation %s cannot be evaluated at compile time", toChars());
@@ -2260,74 +2374,118 @@
 #if LOG
     printf("CallExp::interpret() %s\n", toChars());
 #endif
-    if (e1->op == TOKdotvar)
+
+    Expression * pthis = NULL; 
+    FuncDeclaration *fd = NULL;
+    Expression *ecall = e1;
+    if (ecall->op == TOKindex)
+        ecall = e1->interpret(istate);
+    if (ecall->op == TOKdotvar && !((DotVarExp*)ecall)->var->isFuncDeclaration())
+        ecall = e1->interpret(istate);
+   
+    if (ecall->op == TOKdotvar)
+    {   // Calling a member function    
+        pthis = ((DotVarExp*)e1)->e1;
+	fd = ((DotVarExp*)e1)->var->isFuncDeclaration();
+    }
+    else if (ecall->op == TOKvar)
     {
-        Expression * pthis = ((DotVarExp*)e1)->e1;
-	FuncDeclaration *fd = ((DotVarExp*)e1)->var->isFuncDeclaration();
-	TypeFunction *tf = fd ? (TypeFunction *)(fd->type) : NULL;
-	if (tf)
-	{   // Member function call
-	    if(pthis->op == TOKthis)
-		pthis = istate->localThis;	    
-	    Expression *eresult = fd->interpret(istate, arguments, pthis);
+        VarDeclaration *vd = ((VarExp *)ecall)->var->isVarDeclaration();
+	if (vd && vd->value) 
+	    ecall = vd->value;
+	else // Calling a function
+	    fd = ((VarExp *)e1)->var->isFuncDeclaration();
+    }    
+    if (ecall->op == TOKdelegate)
+    {   // Calling a delegate
+	fd = ((DelegateExp *)ecall)->func;
+	pthis = ((DelegateExp *)ecall)->e1;
+    }
+    else if (ecall->op == TOKfunction)
+    {	// Calling a delegate literal
+        fd = ((FuncExp*)ecall)->fd;
+    }
+    else if (ecall->op == TOKstar && ((PtrExp*)ecall)->e1->op==TOKfunction)
+    {	// Calling a function literal
+        fd = ((FuncExp*)((PtrExp*)ecall)->e1)->fd;
+    }	
+    else if (ecall->op == TOKstar && ((PtrExp*)ecall)->e1->op==TOKvar)
+    {	// Calling a function pointer
+        VarDeclaration *vd = ((VarExp *)((PtrExp*)ecall)->e1)->var->isVarDeclaration();
+	if (vd && vd->value && vd->value->op==TOKsymoff) 
+	    fd = ((SymOffExp *)vd->value)->var->isFuncDeclaration();
+    }
+    
+    TypeFunction *tf = fd ? (TypeFunction *)(fd->type) : NULL;
+    if (!tf)
+    {   // DAC: I'm not sure if this ever happens
+	//printf("ecall=%s %d %d\n", ecall->toChars(), ecall->op, TOKcall);
+	error("cannot evaluate %s at compile time", toChars());
+	return EXP_CANT_INTERPRET;
+    }
+    if (pthis && fd)
+    {   // Member function call
+	if (pthis->op == TOKthis)
+	    pthis = istate->localThis;
+	else if (pthis->op == TOKcomma)
+	    pthis = pthis->interpret(istate);
+	Expression *eresult = fd->interpret(istate, arguments, pthis);
+	if (eresult)
+	    e = eresult;
+	else if (fd->type->toBasetype()->nextOf()->ty == Tvoid && !global.errors)
+	    e = EXP_VOID_INTERPRET;
+	else
+	    error("cannot evaluate %s at compile time", toChars());
+	return e;
+    }
+    else if (fd)
+    {    // function call
+#if DMDV2
+	enum BUILTIN b = fd->isBuiltin();
+	if (b)
+	{   Expressions args;
+	    args.setDim(arguments->dim);
+	    for (size_t i = 0; i < args.dim; i++)
+	    {
+		Expression *earg = (Expression *)arguments->data[i];
+		earg = earg->interpret(istate);
+		if (earg == EXP_CANT_INTERPRET)
+		    return earg;
+		args.data[i] = (void *)earg;
+	    }
+	    e = eval_builtin(b, &args);
+	    if (!e)
+		e = EXP_CANT_INTERPRET;
+	}
+	else
+#endif
+	// Inline .dup
+	if (fd->ident == Id::adDup && arguments && arguments->dim == 2)
+	{
+	    e = (Expression *)arguments->data[1];
+	    e = e->interpret(istate);
+	    if (e != EXP_CANT_INTERPRET)
+	    {
+		e = expType(type, e);
+	    }
+	}
+	else
+	{
+	    Expression *eresult = fd->interpret(istate, arguments);
 	    if (eresult)
 		e = eresult;
 	    else if (fd->type->toBasetype()->nextOf()->ty == Tvoid && !global.errors)
 		e = EXP_VOID_INTERPRET;
 	    else
 		error("cannot evaluate %s at compile time", toChars());
-	    return e;
-	} 
+	}
+    }
+    else
+    {
 	error("cannot evaluate %s at compile time", toChars());
         return EXP_CANT_INTERPRET;
     }
-    if (e1->op == TOKvar)
-    {
-	FuncDeclaration *fd = ((VarExp *)e1)->var->isFuncDeclaration();
-	if (fd)
-	{
-#if DMDV2
-	    enum BUILTIN b = fd->isBuiltin();
-	    if (b)
-	    {	Expressions args;
-		args.setDim(arguments->dim);
-		for (size_t i = 0; i < args.dim; i++)
-		{
-		    Expression *earg = (Expression *)arguments->data[i];
-		    earg = earg->interpret(istate);
-		    if (earg == EXP_CANT_INTERPRET)
-			return earg;
-		    args.data[i] = (void *)earg;
-		}
-		e = eval_builtin(b, &args);
-		if (!e)
-		    e = EXP_CANT_INTERPRET;
-	    }
-	    else
-#endif
-	    // Inline .dup
-	    if (fd->ident == Id::adDup && arguments && arguments->dim == 2)
-	    {
-		e = (Expression *)arguments->data[1];
-		e = e->interpret(istate);
-		if (e != EXP_CANT_INTERPRET)
-		{
-		    e = expType(type, e);
-		}
-	    }
-	    else
-	    {
-		Expression *eresult = fd->interpret(istate, arguments);
-		if (eresult)
-		    e = eresult;
-		else if (fd->type->toBasetype()->nextOf()->ty == Tvoid && !global.errors)
-		    e = EXP_VOID_INTERPRET;
-		else
-		    error("cannot evaluate %s at compile time", toChars());
-	    }
-	}
-    }
-    return e;
+    return e; 
 }
 
 Expression *CommaExp::interpret(InterState *istate)
@@ -2335,6 +2493,21 @@
 #if LOG
     printf("CommaExp::interpret() %s\n", toChars());
 #endif
+    // If the comma returns a temporary variable, it needs to be an lvalue
+    // (this is particularly important for struct constructors)
+    if (e1->op == TOKdeclaration && e2->op == TOKvar 
+       && ((DeclarationExp *)e1)->declaration == ((VarExp*)e2)->var)
+    {
+	VarExp* ve = (VarExp *)e2;
+	VarDeclaration *v = ve->var->isVarDeclaration();
+	if (!v->init && !v->value)
+	    v->value = v->type->defaultInitLiteral();
+	if (!v->value)
+	    v->value = v->init->toExpression();
+	v->value = v->value->interpret(istate);	
+	return e2;
+    }
+
     Expression *e = e1->interpret(istate);
     if (e != EXP_CANT_INTERPRET)
 	e = e2->interpret(istate);
@@ -2516,14 +2689,18 @@
     if( this->e1->op == TOKaddress)
     {   // Special case: deal with compiler-inserted assert(&this, "null this") 
 	AddrExp *ade = (AddrExp *)this->e1;
-	if(ade->e1->op == TOKthis && istate->localThis)   	
-	return istate->localThis->interpret(istate);
+	if (ade->e1->op == TOKthis && istate->localThis)
+	    if (ade->e1->op == TOKdotvar
+	        && ((DotVarExp *)(istate->localThis))->e1->op == TOKthis)
+	        return getVarExp(loc, istate, ((DotVarExp*)(istate->localThis))->var);
+	    else
+	        return istate->localThis->interpret(istate);
     }
-if (this->e1->op == TOKthis)
-{
-	if(istate->localThis)   	
-	return istate->localThis->interpret(istate);
-}    
+    if (this->e1->op == TOKthis)
+    {
+	if (istate->localThis)
+	    return istate->localThis->interpret(istate);
+    }
     e1 = this->e1->interpret(istate);
     if (e1 == EXP_CANT_INTERPRET)
 	goto Lcant;
--- a/dmd/mangle.c	Wed Jan 06 19:53:35 2010 +0100
+++ b/dmd/mangle.c	Sat Feb 06 15:53:52 2010 +0000
@@ -113,9 +113,9 @@
 		case LINKd:
 		    break;
 
-        // LDC
+#if IN_LLVM
         case LINKintrinsic:
-
+#endif
 		case LINKc:
 		case LINKwindows:
 		case LINKpascal:
--- a/dmd/mars.c	Wed Jan 06 19:53:35 2010 +0100
+++ b/dmd/mars.c	Sat Feb 06 15:53:52 2010 +0000
@@ -1,6 +1,6 @@
 
 // Compiler implementation of the D programming language
-// Copyright (c) 1999-2009 by Digital Mars
+// Copyright (c) 1999-2010 by Digital Mars
 // All Rights Reserved
 // written by Walter Bright
 // http://www.digitalmars.com
@@ -13,8 +13,10 @@
 #include <ctype.h>
 #include <assert.h>
 #include <limits.h>
+#if IN_LLVM
 #include <string>
 #include <cstdarg>
+#endif
 
 #if POSIX
 #include <errno.h>
@@ -34,7 +36,9 @@
 #include "lexer.h"
 #include "json.h"
 
+#if IN_LLVM
 #include "gen/revisions.h"
+#endif
 
 Global global;
 
@@ -46,6 +50,7 @@
     doc_ext  = "html";
     ddoc_ext = "ddoc";
     json_ext = "json";
+    map_ext  = "map";
 
 // LDC
     ll_ext  = "ll";
@@ -58,7 +63,7 @@
 
     copyright = "Copyright (c) 1999-2009 by Digital Mars and Tomas Lindquist Olsen";
     written = "written by Walter Bright and Tomas Lindquist Olsen";
-    version = "v1.055";
+    version = "v1.056";
     ldc_version = LDC_REV;
     llvm_version = LLVM_REV_STR;
     global.structalign = 8;
--- a/dmd/mars.h	Wed Jan 06 19:53:35 2010 +0100
+++ b/dmd/mars.h	Sat Feb 06 15:53:52 2010 +0000
@@ -1,6 +1,6 @@
 
 // Compiler implementation of the D programming language
-// Copyright (c) 1999-2009 by Digital Mars
+// Copyright (c) 1999-2010 by Digital Mars
 // All Rights Reserved
 // written by Walter Bright
 // http://www.digitalmars.com
@@ -235,7 +235,9 @@
     char *deffile;
     char *resfile;
     char *exefile;
+    char *mapfile;
 
+#if IN_LLVM
     // LDC stuff
     OUTPUTFLAG output_ll;
     OUTPUTFLAG output_bc;
@@ -250,6 +252,7 @@
     const char* llvmArch;
     const char *targetTriple;
     const char *dataLayout;
+#endif
 };
 
 struct Global
@@ -268,6 +271,7 @@
     const char *ddoc_ext;	// for Ddoc macro include files
     const char *hdr_ext;	// for D 'header' import files
     const char *json_ext;	// for JSON files
+    const char *map_ext;	// for .map files
     const char *copyright;
     const char *written;
     Array *path;	// Array of char*'s which form the import lookup path
@@ -393,8 +397,9 @@
     LINKwindows,
     LINKpascal,
 
-    // LDC
+#if IN_LLVM
     LINKintrinsic,
+#endif
 };
 
 enum DYNCAST
--- a/dmd/module.c	Wed Jan 06 19:53:35 2010 +0100
+++ b/dmd/module.c	Sat Feb 06 15:53:52 2010 +0000
@@ -1,6 +1,6 @@
 
 // Compiler implementation of the D programming language
-// Copyright (c) 1999-2009 by Digital Mars
+// Copyright (c) 1999-2010 by Digital Mars
 // All Rights Reserved
 // written by Walter Bright
 // http://www.digitalmars.com
@@ -44,7 +44,7 @@
 #include "d-dmd-gcc.h"
 #endif
 
-
+#if IN_LLVM
 #include "llvm/Support/CommandLine.h"
 #include <map>
 
@@ -55,8 +55,7 @@
 static llvm::cl::opt<bool> fqnNames("oq",
     llvm::cl::desc("Write object files with fully qualified names"),
     llvm::cl::ZeroOrMore);
-
-
+#endif
 
 ClassDeclaration *Module::moduleinfo;
 
@@ -971,7 +970,8 @@
 
 void Module::runDeferredSemantic()
 {
-    size_t len;
+    if (dprogress == 0)
+	return;
 
     static int nested;
     if (nested)
@@ -979,6 +979,7 @@
     //if (deferred.dim) printf("+Module::runDeferredSemantic('%s'), len = %d\n", toChars(), deferred.dim);
     nested++;
 
+    size_t len;
     do
     {
 	dprogress = 0;
--- a/dmd/module.h	Wed Jan 06 19:53:35 2010 +0100
+++ b/dmd/module.h	Sat Feb 06 15:53:52 2010 +0000
@@ -153,7 +153,7 @@
     Dsymbol *symtabInsert(Dsymbol *s);
     void deleteObjFile();
     void addDeferredSemantic(Dsymbol *s);
-    void runDeferredSemantic();
+    static void runDeferredSemantic();
     int imports(Module *m);
 
     // Back end
--- a/dmd/mtype.c	Wed Jan 06 19:53:35 2010 +0100
+++ b/dmd/mtype.c	Sat Feb 06 15:53:52 2010 +0000
@@ -4061,8 +4061,15 @@
 Type *TypeEnum::toBasetype()
 {
     if (sym->scope)
-    {
-	sym->semantic(NULL);	// attempt to resolve forward reference
+    {	// Enum is forward referenced. We don't need to resolve the whole thing,
+	// just the base type
+	if (sym->memtype)
+	{   sym->memtype = sym->memtype->semantic(sym->loc, sym->scope);
+	}
+	else
+	{   if (!sym->isAnonymous())
+		sym->memtype = Type::tint32;
+	}
     }
     if (!sym->memtype)
     {
--- a/dmd/optimize.c	Wed Jan 06 19:53:35 2010 +0100
+++ b/dmd/optimize.c	Sat Feb 06 15:53:52 2010 +0000
@@ -1,6 +1,6 @@
 
 // Compiler implementation of the D programming language
-// Copyright (c) 1999-2009 by Digital Mars
+// Copyright (c) 1999-2010 by Digital Mars
 // All Rights Reserved
 // written by Walter Bright
 // http://www.digitalmars.com
@@ -344,7 +344,9 @@
 }
 
 Expression *CallExp::optimize(int result)
-{   Expression *e = this;
+{
+    //printf("CallExp::optimize(result = %d) %s\n", result, toChars());
+    Expression *e = this;
 
     // Optimize parameters
     if (arguments)
@@ -358,17 +360,15 @@
     }
 
     e1 = e1->optimize(result);
-    if (e1->op == TOKvar && result & WANTinterpret)
+    if (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());
-	}
+        Expression *eresult = interpret(NULL);
+	if (eresult == EXP_CANT_INTERPRET)
+	    return e;
+	if (eresult && eresult != EXP_VOID_INTERPRET)
+	    e = eresult;
+	else
+	    error("cannot evaluate %s at compile time", toChars());
     }
     return e;
 }
@@ -624,6 +624,22 @@
 {   Expression *e;
 
     //printf("CommaExp::optimize(result = %d) %s\n", result, toChars());
+    // Comma needs special treatment, because it may
+    // contain compiler-generated declarations. We can interpret them, but
+    // otherwise we must NOT attempt to constant-fold them.
+    // In particular, if the comma returns a temporary variable, it needs
+    // to be an lvalue (this is particularly important for struct constructors)
+
+    if (result & WANTinterpret)
+    {   // Interpreting comma needs special treatment, because it may
+        // contain compiler-generated declarations.
+	e = interpret(NULL);
+	return (e == EXP_CANT_INTERPRET) ?  this : e;
+    }
+    // Don't constant fold if it is a compiler-generated temporary.
+    if (e1->op == TOKdeclaration)
+       return this;
+
     e1 = e1->optimize(result & WANTinterpret);
     e2 = e2->optimize(result);
     if (!e1 || e1->op == TOKint64 || e1->op == TOKfloat64 || !e1->checkSideEffect(2))
@@ -709,8 +725,8 @@
     {	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());
+	    if (t->nextOf())
+		e = e1->castTo(NULL, t->nextOf()->arrayOf());
 	}
 	return e;
     }
--- a/dmd/statement.c	Wed Jan 06 19:53:35 2010 +0100
+++ b/dmd/statement.c	Sat Feb 06 15:53:52 2010 +0000
@@ -2483,7 +2483,14 @@
                 Expression *e = (Expression *)args->data[i];
 
                 e = e->semantic(sc);
+#if 1
 		e = e->optimize(WANTvalue | WANTinterpret);
+#else
+	        e = e->interpret(NULL);
+		if (e == EXP_CANT_INTERPRET)
+		    fprintf(stdmsg, ((Expression *)args->data[i])->toChars());
+                else
+#endif
                 if (e->op == TOKstring)
                 {
                     StringExp *se = (StringExp *)e;
--- a/dmd/statement.h	Wed Jan 06 19:53:35 2010 +0100
+++ b/dmd/statement.h	Sat Feb 06 15:53:52 2010 +0000
@@ -54,13 +54,14 @@
 struct SynchronizedStatement;
 
 enum TOK;
-
+#if IN_LLVM
 namespace llvm
 {
     class Value;
     class BasicBlock;
     class ConstantInt;
 }
+#endif
 
 // Back end
 struct IRState;
@@ -141,9 +142,10 @@
     virtual IfStatement *isIfStatement() { return NULL; }
     virtual CaseStatement* isCaseStatement() { return NULL; }
 
-    // LDC
+#if IN_LLVM
     virtual void toNakedIR(IRState *irs);
     virtual AsmBlockStatement* endsWithAsm();
+#endif
 };
 
 struct PeelStatement : Statement
@@ -172,8 +174,9 @@
 
     void toIR(IRState *irs);
 
-    // LDC
+#if IN_LLVM
     void toNakedIR(IRState *irs);
+#endif
 };
 
 struct CompileStatement : Statement
--- a/dmd/struct.c	Wed Jan 06 19:53:35 2010 +0100
+++ b/dmd/struct.c	Sat Feb 06 15:53:52 2010 +0000
@@ -19,6 +19,7 @@
 #include "module.h"
 #include "id.h"
 #include "statement.h"
+#include "template.h"
 
 /********************************* AggregateDeclaration ****************************/
 
@@ -269,6 +270,8 @@
         scope = NULL;
     }
 
+    unsigned dprogress_save = Module::dprogress;
+
     parent = sc->parent;
     type = type->semantic(loc, sc);
 #if STRUCTTHISREF
@@ -417,6 +420,8 @@
 	scope = scx ? scx : new Scope(*sc);
 	scope->setNoFree();
 	scope->module->addDeferredSemantic(this);
+
+	Module::dprogress = dprogress_save;
 	//printf("\tdeferring %s\n", toChars());
 	return;
     }
--- a/dmd/template.c	Wed Jan 06 19:53:35 2010 +0100
+++ b/dmd/template.c	Sat Feb 06 15:53:52 2010 +0000
@@ -1,6 +1,6 @@
 
 // Compiler implementation of the D programming language
-// Copyright (c) 1999-2009 by Digital Mars
+// Copyright (c) 1999-2010 by Digital Mars
 // All Rights Reserved
 // written by Walter Bright
 // http://www.digitalmars.com
@@ -3539,7 +3539,8 @@
 	error("error instantiating");
 	if (tinst)
 	{   tinst->printInstantiationTrace();
-	    fatal();
+	    if (!global.gag)
+		fatal();
 	}
 	errors = 1;
 	if (global.gag)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/mini/bug372.d	Sat Feb 06 15:53:52 2010 +0000
@@ -0,0 +1,14 @@
+class A {
+    class B {
+    }
+}
+
+class C : A {
+    void test () {
+        B foo = new B();
+    }
+}
+
+int main () {
+    return 0;
+}