changeset 179:cd48cb899aee

Updated to dmd2.040
author korDen
date Sun, 17 Oct 2010 20:56:07 +0400
parents e3afd1303184
children 0622fff7810a
files commands.linux.txt commands.txt dmd/AliasDeclaration.d dmd/AnonDeclaration.d dmd/AssertExp.d dmd/BinExp.d dmd/CallExp.d dmd/ClassDeclaration.d dmd/CommaExp.d dmd/CtorDeclaration.d dmd/Declaration.d dmd/DelegateExp.d dmd/DeleteDeclaration.d dmd/Dsymbol.d dmd/DsymbolExp.d dmd/DtorDeclaration.d dmd/EnumDeclaration.d dmd/Expression.d dmd/ForeachStatement.d dmd/FuncDeclaration.d dmd/FuncExp.d dmd/Global.d dmd/Id.d dmd/IdentifierExp.d dmd/InvariantDeclaration.d dmd/Module.d dmd/NewDeclaration.d dmd/NewExp.d dmd/Param.d dmd/Parser.d dmd/PostBlitDeclaration.d dmd/PowExp.d dmd/STC.d dmd/SharedStaticCtorDeclaration.d dmd/SharedStaticDtorDeclaration.d dmd/StaticCtorDeclaration.d dmd/StaticDtorDeclaration.d dmd/StorageClassDeclaration.d dmd/StructDeclaration.d dmd/SymOffExp.d dmd/SymbolExp.d dmd/TemplateDeclaration.d dmd/TraitsExp.d dmd/TypeAArray.d dmd/TypeEnum.d dmd/UnitTestDeclaration.d dmd/Util.d dmd/VarDeclaration.d dmd/backend/glue.d dmd/expression/Util.d dmd/interpret/Util.d main.d
diffstat 52 files changed, 1560 insertions(+), 759 deletions(-) [+]
line wrap: on
line diff
--- a/commands.linux.txt	Sun Oct 17 07:42:00 2010 +0400
+++ b/commands.linux.txt	Sun Oct 17 20:56:07 2010 +0400
@@ -16,6 +16,7 @@
 -version=BREAKABI
 -version=SNAN_DEFAULT_INIT
 -version=SARRAYVALUE
+-version=MODULEINFO_IS_STRUCT
 -ofbin/ddmd
 
 bridge.o
@@ -299,6 +300,8 @@
 dmd/SwitchStatement.d
 dmd/SymbolDeclaration.d
 dmd/SynchronizedStatement.d
+dmd/SharedStaticCtorDeclaration.d
+dmd/SharedStaticDtorDeclaration.d
 dmd/TOK.d
 dmd/TRUST.d
 dmd/TY.d
--- a/commands.txt	Sun Oct 17 07:42:00 2010 +0400
+++ b/commands.txt	Sun Oct 17 20:56:07 2010 +0400
@@ -13,6 +13,7 @@
 -version=OMFOBJ
 -version=SNAN_DEFAULT_INIT
 -version=SARRAYVALUE
+-version=MODULEINFO_IS_STRUCT
 -ofbin\ddmd.exe
 bridge.obj
 ddmd.def
@@ -294,6 +295,8 @@
 dmd\SwitchStatement.d
 dmd\SymbolDeclaration.d
 dmd\SynchronizedStatement.d
+dmd\SharedStaticCtorDeclaration.d
+dmd\SharedStaticDtorDeclaration.d
 dmd\TOK.d
 dmd\TRUST.d
 dmd\TY.d
--- a/dmd/AliasDeclaration.d	Sun Oct 17 07:42:00 2010 +0400
+++ b/dmd/AliasDeclaration.d	Sun Oct 17 20:56:07 2010 +0400
@@ -132,11 +132,11 @@
 
 ///version (DMDV2) {
         type = type.addStorageClass(storage_class);
-		if (storage_class & (STC.STCref | STCnothrow | STCpure))
+		if (storage_class & (STC.STCref | STCnothrow | STCpure | STCdisable))
 		{	// For 'ref' to be attached to function types, and picked
 			// up by Type.resolve(), it has to go into sc.
 			sc = sc.push();
-		    sc.stc |= storage_class & (STCref | STCnothrow | STCpure | STCshared);
+		    sc.stc |= storage_class & (STCref | STCnothrow | STCpure | STCshared | STCdisable);
 			type.resolve(loc, sc, &e, &t, &s);
 			sc = sc.pop();
 		}
--- a/dmd/AnonDeclaration.d	Sun Oct 17 07:42:00 2010 +0400
+++ b/dmd/AnonDeclaration.d	Sun Oct 17 20:56:07 2010 +0400
@@ -48,6 +48,8 @@
 			scx = scope_;
 			scope_ = null;
 		}
+		
+	    uint dprogress_save = global.dprogress;
 
 		assert(sc.parent);
 
@@ -107,6 +109,7 @@
 					scope_.setNoFree();
 					scope_.module_.addDeferredSemantic(this);
 				}
+				global.dprogress = dprogress_save;
 				//printf("\tforward reference %p\n", this);
 				return;
 			}
--- a/dmd/AssertExp.d	Sun Oct 17 07:42:00 2010 +0400
+++ b/dmd/AssertExp.d	Sun Oct 17 20:56:07 2010 +0400
@@ -18,8 +18,11 @@
 import dmd.InvariantDeclaration;
 import dmd.TOK;
 import dmd.PREC;
+import dmd.AddrExp;
+import dmd.DotVarExp;
 import dmd.TY;
 import dmd.TypeClass;
+import dmd.GlobalExpressions;
 import dmd.Module;
 import dmd.WANT;
 import dmd.FuncDeclaration;
@@ -36,6 +39,7 @@
 import dmd.backend.FL;
 
 import dmd.expression.Util;
+import dmd.interpret.Util;
 
 import core.stdc.string;
 import std.string : toStringz;
@@ -97,8 +101,54 @@
 	}
 
 	override Expression interpret(InterState istate)
-	{
-		assert(false);
+	{   
+		Expression e;
+		Expression e1;
+
+version (LOG) {
+		writef("AssertExp::interpret() %s\n", toChars());
+}
+		if (this.e1.op == TOKaddress)
+		{   
+			// Special case: deal with compiler-inserted assert(&this, "null this") 
+			AddrExp ade = cast(AddrExp)this.e1;
+			if (ade.e1.op == TOKthis && istate.localThis)
+				if (ade.e1.op == TOKdotvar
+					&& (cast(DotVarExp)(istate.localThis)).e1.op == TOKthis)
+					return getVarExp(loc, istate, (cast(DotVarExp)(istate.localThis)).var);
+				else
+					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 is EXP_CANT_INTERPRET)
+			goto Lcant;
+		if (e1.isBool(true))
+		{
+		}
+		else if (e1.isBool(false))
+		{
+			if (msg)
+			{
+				e = msg.interpret(istate);
+				if (e is EXP_CANT_INTERPRET)
+					goto Lcant;
+				error("%s", e.toChars());
+			}
+			else
+				error("%s failed", toChars());
+			goto Lcant;
+		}
+		else
+			goto Lcant;
+		return e1;
+
+	Lcant:
+		return EXP_CANT_INTERPRET;
 	}
 
 	override bool checkSideEffect(int flag)
--- a/dmd/BinExp.d	Sun Oct 17 07:42:00 2010 +0400
+++ b/dmd/BinExp.d	Sun Oct 17 20:56:07 2010 +0400
@@ -787,7 +787,7 @@
 			return e2;
 
 		// Chase down rebinding of out and ref.
-		if (e1.op == TOKvar)
+		if (e1.op == TOKvar) 
 		{
 			VarExp ve = cast(VarExp)e1;
 			VarDeclaration v = ve.var.isVarDeclaration();
@@ -813,12 +813,15 @@
 		// To reduce code complexity of handling dotvar expressions,
 		// extract the aggregate now.
 		Expression aggregate;
-		if (e1.op == TOKdotvar) {
+		if (e1.op == TOKdotvar)
+		{
 			aggregate = (cast(DotVarExp)e1).e1;
 		// Get rid of 'this'.
 			if (aggregate.op == TOKthis && istate.localThis)
 				aggregate = istate.localThis;
 		}
+	    if (e1.op == TOKthis && istate.localThis)
+			e1 = istate.localThis;
 
 		/* Assignment to variable of the form:
 		 *	v = e2
@@ -857,7 +860,8 @@
 				if (e2 is EXP_CANT_INTERPRET)
 					return e2;
 
-				addVarToInterstate(istate, v);
+			    if (istate)
+					addVarToInterstate(istate, v);
 				v.value = e2;
 				e = Cast(type, type, post ? ev : e2);
 			}
@@ -908,16 +912,20 @@
 				 * on the void value - to do that we'd need a VoidExp.
 				 * That's probably a good enhancement idea.
 				 */
-				v.value = v.type.defaultInit(Loc(0));
+			    v.value = v.type.defaultInitLiteral(Loc(0));
 			}
 			Expression vie = v.value;
+			assert(vie !is EXP_CANT_INTERPRET);
 			if (vie.op == TOKvar)
 			{
 				Declaration d = (cast(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 = cast(StructLiteralExp)vie;
 			VarDeclaration vf = (cast(DotVarExp)e1).var.isVarDeclaration();
 			if (!vf)
@@ -1311,10 +1319,7 @@
 				if (v.value.op == TOKarrayliteral)
 					dim = (cast(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 = (cast(StringExp)v.value).len;
 			}
 			else
 			{
@@ -1324,67 +1329,87 @@
 			int upperbound = upper ? cast(int)upper.toInteger() : dim;
 			int lowerbound = lower ? cast(int)lower.toInteger() : 0;
 
-			ArrayLiteralExp existing;
 			if ((cast(int)lowerbound < 0) || (upperbound > dim))
 			{
 				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 = (cast(ArrayLiteralExp)e2).elements.dim;
+			else if (e2.op == TOKstring)
+				srclen = (cast(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 = cast(ArrayLiteralExp)v.value;
-				else
-				{
-					// this can only happen with static arrays
-					existing = createBlockDuplicatedArrayLiteral(v.type, v.type.defaultInit(Loc(0)), 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 = cast(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 = cast(ArrayLiteralExp)v.value;
+					else // this can only happen with static arrays
+						existing = createBlockDuplicatedArrayLiteral(v.type, v.type.defaultInit(Loc(0)), dim);
+
 					// value[] = value[0..lower] ~ ae ~ value[upper..$]
 					existing.elements = spliceElements(existing.elements, ae.elements, lowerbound);
 					v.value = existing;
 				}
 				return e2;
 			}
-			else if (t.nextOf().ty == e2.type.ty)
-			{
-				 // Static array block assignment
-				if (upperbound-lowerbound ==dim)
-					v.value = createBlockDuplicatedArrayLiteral(v.type, e2, dim);
-				else
-				{
-					// value[] = value[0..lower] ~ ae ~ value[upper..$]
-					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 = cast(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");
+				if (upperbound-lowerbound == dim)
+					v.value = e2;		
+				else
+				{
+					if (!v.value)
+						v.value = createBlockDuplicatedStringLiteral(se.type, cast(dchar)se.type.defaultInit(Loc(0)).toInteger(), dim, se.sz);
+					if (v.value.op==TOKstring)
+						v.value = spliceStringExp(cast(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)
+					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 = cast(ArrayLiteralExp)v.value;
+					else // this can only happen with static arrays
+						existing = createBlockDuplicatedArrayLiteral(v.type, v.type.defaultInit(Loc(0)), dim);
+					// value[] = value[0..lower] ~ ae ~ value[upper..$]
+					existing.elements = spliceElements(existing.elements, 
+						createBlockDuplicatedArrayLiteral(v.type, e2, upperbound-lowerbound).elements,
+						lowerbound);
+					v.value = existing;
+				}				
+
 				return e2;
 			}
 			else
--- a/dmd/CallExp.d	Sun Oct 17 07:42:00 2010 +0400
+++ b/dmd/CallExp.d	Sun Oct 17 20:56:07 2010 +0400
@@ -9,6 +9,8 @@
 import dmd.TypeFunction;
 import dmd.ScopeDsymbol;
 import dmd.CastExp;
+import dmd.FuncExp;
+import dmd.SymOffExp;
 import dmd.GlobalExpressions;
 import dmd.TypePointer;
 import dmd.ThisExp;
@@ -383,6 +385,7 @@
 					// Create variable that will get constructed
 					Identifier idtmp = Lexer.uniqueId("__ctmp");
 					VarDeclaration tmp = new VarDeclaration(loc, t1, idtmp, null);
+					tmp.storage_class |= STCctfe;		
 					Expression av = new DeclarationExp(loc, tmp);
 					av = new CommaExp(loc, av, new VarExp(loc, tmp));
 
@@ -845,6 +848,18 @@
 		}
 
 		e1 = e1.optimize(result);
+static if (true) {
+		if (result & WANTinterpret)
+		{
+			Expression eresult = interpret(null);
+			if (eresult is EXP_CANT_INTERPRET)
+				return e;
+			if (eresult && eresult !is EXP_VOID_INTERPRET)
+				e = eresult;
+			else
+				error("cannot evaluate %s at compile time", toChars());
+		}
+} else {
 		if (e1.op == TOK.TOKvar)
 		{
 			FuncDeclaration fd = (cast(VarExp)e1).var.isFuncDeclaration();
@@ -880,7 +895,7 @@
 					error("cannot evaluate %s at compile time", toChars());
 			}
 		}
-
+}
 		return e;
 	}
 
@@ -891,75 +906,122 @@
 version (LOG) {
 		printf("CallExp.interpret() %.*s\n", toChars());
 }
-		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 && !(cast(DotVarExp)ecall).var.isFuncDeclaration())
+			ecall = e1.interpret(istate);
+	   
+		if (ecall.op == TOKdotvar)
+		{   // Calling a member function    
+			pthis = (cast(DotVarExp)e1).e1;
+			fd = (cast(DotVarExp)e1).var.isFuncDeclaration();
+		}
+		else if (ecall.op == TOKvar)
 		{
-			Expression pthis = (cast(DotVarExp)e1).e1;
-			FuncDeclaration fd = (cast(DotVarExp)e1).var.isFuncDeclaration();
-			TypeFunction tf = fd ? cast(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 = (cast(VarExp)ecall).var.isVarDeclaration();
+			if (vd && vd.value) 
+				ecall = vd.value;
+			else // Calling a function
+				fd = (cast(VarExp)e1).var.isFuncDeclaration();
+		}    
+		if (ecall.op == TOKdelegate)
+		{   
+			// Calling a delegate
+			fd = (cast(DelegateExp)ecall).func;
+			pthis = (cast(DelegateExp)ecall).e1;
+		}
+		else if (ecall.op == TOKfunction)
+		{	// Calling a delegate literal
+			fd = (cast(FuncExp)ecall).fd;
+		}
+		else if (ecall.op == TOKstar && (cast(PtrExp)ecall).e1.op == TOKfunction)
+		{	// Calling a function literal
+			fd = (cast(FuncExp)(cast(PtrExp)ecall).e1).fd;
+		}	
+		else if (ecall.op == TOKstar && (cast(PtrExp*)ecall).e1.op==TOKvar)
+		{	// Calling a function pointer
+			VarDeclaration vd = (cast(VarExp)(cast(PtrExp*)ecall).e1).var.isVarDeclaration();
+			if (vd && vd.value && vd.value.op == TOKsymoff) 
+				fd = (cast(SymOffExp)vd.value).var.isFuncDeclaration();
+		}
+
+		TypeFunction tf = fd ? cast(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
+
+///version (DMDV2) {
+			BUILTIN b = fd.isBuiltin();
+			if (b)
+			{	
+				scope Expressions args = new Expressions();
+				args.setDim(arguments.dim);
+				for (size_t i = 0; i < args.dim; i++)
+				{
+					auto earg = arguments[i];
+					earg = earg.interpret(istate);
+					if (earg == EXP_CANT_INTERPRET)
+						return earg;
+					args[i] = earg;
+				}
+				e = eval_builtin(b, args);
+				if (!e)
+					e = EXP_CANT_INTERPRET;
+			}
+			else
+///}
+			// Inline .dup
+			if (fd.ident == Id.adDup && arguments && arguments.dim == 2)
+			{
+				e = arguments[1];
+				e = e.interpret(istate);
+				if (e !is 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;
-			} 
-			error("cannot evaluate %s at compile time", toChars());
-				return EXP_CANT_INTERPRET;
-		}
-		if (e1.op == TOKvar)
-		{
-			FuncDeclaration fd = (cast(VarExp)e1).var.isFuncDeclaration();
-			if (fd)
-			{
-///version (DMDV2) {
-				BUILTIN b = fd.isBuiltin();
-				if (b)
-				{	
-					scope Expressions args = new Expressions();
-					args.setDim(arguments.dim);
-					for (size_t i = 0; i < args.dim; i++)
-					{
-						auto earg = arguments[i];
-						earg = earg.interpret(istate);
-						if (earg == EXP_CANT_INTERPRET)
-							return earg;
-						args[i] = earg;
-					}
-					e = eval_builtin(b, args);
-					if (!e)
-						e = EXP_CANT_INTERPRET;
-				}
-				else
-///}
-				// Inline .dup
-				if (fd.ident == Id.adDup && arguments && arguments.dim == 2)
-				{
-					e = arguments[1];
-					e = e.interpret(istate);
-					if (e !is 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());
-				}
 			}
 		}
+		else
+		{
+			error("cannot evaluate %s at compile time", toChars());
+			return EXP_CANT_INTERPRET;
+		}
+
 		return e;
 	}
 
--- a/dmd/ClassDeclaration.d	Sun Oct 17 07:42:00 2010 +0400
+++ b/dmd/ClassDeclaration.d	Sun Oct 17 20:56:07 2010 +0400
@@ -363,10 +363,12 @@
 
 		Scope scx = null;
 		if (scope_)
-		{	sc = scope_;
+		{	
+			sc = scope_;
 			scx = scope_;		// save so we don't make redundant copies
-		scope_ = null;
+			scope_ = null;
 		}
+	    uint dprogress_save = global.dprogress;
 version (IN_GCC) {
 		methods.setDim(0);
 }
@@ -728,21 +730,24 @@
 		}
 
 		if (sizeok == 2)
-		{	// semantic() failed because of forward references.
-		// Unwind what we did, and defer it for later
-		fields.setDim(0);
-		structsize = 0;
-		alignsize = 0;
-		structalign = 0;
+		{	
+			// semantic() failed because of forward references.
+			// Unwind what we did, and defer it for later
+			fields.setDim(0);
+			structsize = 0;
+			alignsize = 0;
+			structalign = 0;
 
-		sc = sc.pop();
+			sc = sc.pop();
 
-		scope_ = scx ? scx : sc.clone();
-		scope_.setNoFree();
-		scope_.module_.addDeferredSemantic(this);
+			scope_ = scx ? scx : sc.clone();
+			scope_.setNoFree();
+			scope_.module_.addDeferredSemantic(this);
+			
+			global.dprogress = dprogress_save;
 
-		//printf("\tsemantic('%s') failed due to forward references\n", toChars());
-		return;
+			//printf("\tsemantic('%s') failed due to forward references\n", toChars());
+			return;
 		}
 
 		//printf("\tsemantic('%s') successful\n", toChars());
@@ -755,7 +760,7 @@
 		 */
 		ctor = cast(CtorDeclaration)search(Loc(0), Id.ctor, 0);
 		if (ctor && (ctor.toParent() != this || !ctor.isCtorDeclaration()))
-		ctor = null;
+			ctor = null;
 
 	//    dtor = (DtorDeclaration *)search(Id.dtor, 0);
 	//    if (dtor && dtor.toParent() != this)
@@ -774,24 +779,25 @@
 		//    this() { }
 		if (!ctor && baseClass && baseClass.ctor)
 		{
-		//printf("Creating default this(){} for class %s\n", toChars());
-		CtorDeclaration ctor = new CtorDeclaration(loc, Loc(0), null, 0);
-		ctor.fbody = new CompoundStatement(Loc(0), new Statements());
-		members.push(ctor);
-		ctor.addMember(sc, this, true);
-		sc = scsave;	// why? What about sc.nofree?	///
-		sc.offset = structsize;
-		ctor.semantic(sc);
-		this.ctor = ctor;
-		defaultCtor = ctor;
+			//printf("Creating default this(){} for class %s\n", toChars());
+			CtorDeclaration ctor = new CtorDeclaration(loc, Loc(0), null, 0);
+			ctor.fbody = new CompoundStatement(Loc(0), new Statements());
+			members.push(ctor);
+			ctor.addMember(sc, this, true);
+			sc = scsave;	// why? What about sc.nofree?	///
+			sc.offset = structsize;
+			ctor.semantic(sc);
+			this.ctor = ctor;
+			defaultCtor = ctor;
 		}
 
 static if (false) {
 		if (baseClass)
-		{	if (!aggDelete)
-			aggDelete = baseClass.aggDelete;
-		if (!aggNew)
-			aggNew = baseClass.aggNew;
+		{	
+			if (!aggDelete)
+				aggDelete = baseClass.aggDelete;
+			if (!aggNew)
+				aggNew = baseClass.aggNew;
 		}
 }
 
--- a/dmd/CommaExp.d	Sun Oct 17 07:42:00 2010 +0400
+++ b/dmd/CommaExp.d	Sun Oct 17 20:56:07 2010 +0400
@@ -6,6 +6,9 @@
 import dmd.IRState;
 import dmd.Scope;
 import dmd.IntRange;
+import dmd.DeclarationExp;
+import dmd.VarExp;
+import dmd.VarDeclaration;
 import dmd.Expression;
 import dmd.GlobalExpressions;
 import dmd.MATCH;
@@ -113,6 +116,23 @@
 		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 is 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))
@@ -132,6 +152,21 @@
 version (LOG) {
 		printf("CommaExp.interpret() %.*s\n", toChars());
 }
+		// 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 
+		   && (cast(DeclarationExp)e1).declaration == (cast(VarExp)e2).var)
+		{
+			VarExp ve = cast(VarExp)e2;
+			VarDeclaration v = ve.var.isVarDeclaration();
+			if (!v.init && !v.value)
+				v.value = v.type.defaultInitLiteral(Loc(0));
+			if (!v.value)
+				v.value = v.init.toExpression();
+			v.value = v.value.interpret(istate);	
+			return e2;
+		}
+
 		Expression e = e1.interpret(istate);
 		if (e !is EXP_CANT_INTERPRET)
 			e = e2.interpret(istate);
--- a/dmd/CtorDeclaration.d	Sun Oct 17 07:42:00 2010 +0400
+++ b/dmd/CtorDeclaration.d	Sun Oct 17 20:56:07 2010 +0400
@@ -53,19 +53,14 @@
 	
     override void semantic(Scope sc)
 	{
-		AggregateDeclaration ad;
-		Type tret;
-
 		//printf("CtorDeclaration.semantic() %s\n", toChars());
-		if (type)
-			return;
-
 		sc = sc.push();
 		sc.stc &= ~STCstatic;		// not a static constructor
 
 		parent = sc.parent;
 		Dsymbol parent = toParent2();
-		ad = parent.isAggregateDeclaration();
+	    Type tret;
+		AggregateDeclaration ad = parent.isAggregateDeclaration();
 		if (!ad || parent.isUnionDeclaration())
 		{
 			error("constructors are only for class or struct definitions");
@@ -76,7 +71,8 @@
 			tret = ad.handle;
 			assert(tret);
 		}
-		type = new TypeFunction(arguments, tret, varargs, LINKd);
+	    if (!type)
+			type = new TypeFunction(arguments, tret, varargs, LINKd);
 
 version (STRUCTTHISREF) {
 		if (ad && ad.isStructDeclaration())
@@ -92,7 +88,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);
--- a/dmd/Declaration.d	Sun Oct 17 07:42:00 2010 +0400
+++ b/dmd/Declaration.d	Sun Oct 17 20:56:07 2010 +0400
@@ -274,16 +274,6 @@
 	
     bool isStatic() { return (storage_class & STC.STCstatic) != 0; }
 	
-    bool isStaticConstructor()
-	{
-		return false;
-	}
-	
-    bool isStaticDestructor()
-	{
-		return false;
-	}
-	
     bool isDelete()
 	{
 		return false;
--- a/dmd/DelegateExp.d	Sun Oct 17 07:42:00 2010 +0400
+++ b/dmd/DelegateExp.d	Sun Oct 17 20:56:07 2010 +0400
@@ -7,6 +7,7 @@
 import dmd.UnaExp;
 import dmd.TypeDelegate;
 import dmd.FuncDeclaration;
+import dmd.InterState;
 import dmd.MATCH;
 import dmd.Type;
 import dmd.OutBuffer;
@@ -55,6 +56,14 @@
 		}
 		return this;
 	}
+	
+    Expression interpret(InterState istate)
+	{
+version (LOG) {
+		printf("DelegateExp::interpret() %s\n", toChars());
+}
+		return this;
+	}
 
 	override MATCH implicitConvTo(Type t)
 	{
--- a/dmd/DeleteDeclaration.d	Sun Oct 17 07:42:00 2010 +0400
+++ b/dmd/DeleteDeclaration.d	Sun Oct 17 20:56:07 2010 +0400
@@ -43,18 +43,17 @@
 	
     override void 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/Dsymbol.d	Sun Oct 17 07:42:00 2010 +0400
+++ b/dmd/Dsymbol.d	Sun Oct 17 20:56:07 2010 +0400
@@ -12,6 +12,8 @@
 import dmd.Id;
 import dmd.Identifier;
 import dmd.TemplateInstance;
+import dmd.SharedStaticCtorDeclaration;
+import dmd.SharedStaticDtorDeclaration;
 import dmd.HdrGenState;
 import dmd.AggregateDeclaration;
 import dmd.ClassDeclaration;
@@ -250,21 +252,34 @@
 			for (Dsymbol sp = sc.parent; sp; sp = sp.parent)
 			{   
 				if (sp.isDeprecated())
-					return;
+					goto L1;
 			}
 
 			for (; sc; sc = sc.enclosing)
 			{
 				if (sc.scopesym && sc.scopesym.isDeprecated())
-					return;
+					goto L1;
 
 				// If inside a StorageClassDeclaration that is deprecated
 				if (sc.stc & STC.STCdeprecated)
-					return;
+					goto L1;
 			}
 
 			error(loc, "is deprecated");
 		}
+		
+	L1:
+		Declaration d = isDeclaration();
+		if (d && d.storage_class & STCdisable)
+		{
+			if (!(sc.func && sc.func.storage_class & STCdisable))
+			{
+				if (d.ident == Id.cpctor && d.toParent())
+					d.toParent().error(loc, "is not copyable");
+				else
+					error(loc, "is not callable");
+			}
+		}
 	}
 	
     Module getModule()
@@ -896,6 +911,8 @@
     DtorDeclaration isDtorDeclaration() { return null; }
     StaticCtorDeclaration isStaticCtorDeclaration() { return null; }
     StaticDtorDeclaration isStaticDtorDeclaration() { return null; }
+    SharedStaticCtorDeclaration isSharedStaticCtorDeclaration() { return null; }
+    SharedStaticDtorDeclaration isSharedStaticDtorDeclaration() { return null; }
     InvariantDeclaration isInvariantDeclaration() { return null; }
     UnitTestDeclaration isUnitTestDeclaration() { return null; }
     NewDeclaration isNewDeclaration() { return null; }
--- a/dmd/DsymbolExp.d	Sun Oct 17 07:42:00 2010 +0400
+++ b/dmd/DsymbolExp.d	Sun Oct 17 20:56:07 2010 +0400
@@ -127,7 +127,12 @@
 			if ((v.storage_class & STC.STCmanifest) && v.init)
 			{
 				e = v.init.toExpression();
-				e.semantic(sc);
+	            if (!e)
+				{   
+					error("cannot make expression out of initializer for %s", v.toChars());
+					e = new ErrorExp();
+				}
+				e = e.semantic(sc);
 				return e;
 			}
 
--- a/dmd/DtorDeclaration.d	Sun Oct 17 07:42:00 2010 +0400
+++ b/dmd/DtorDeclaration.d	Sun Oct 17 20:56:07 2010 +0400
@@ -48,10 +48,11 @@
 		{
 			error("destructors are only for class/struct/union definitions, not %s %s", parent.kind(), parent.toChars());
 		}
-		else if (ident == Id.dtor)
+	    else if (ident == Id.dtor && semanticRun < PASSsemantic)
 			ad.dtors.push(this);
 
-		type = new TypeFunction(null, Type.tvoid, false, LINK.LINKd);
+	    if (!type)
+			type = new TypeFunction(null, Type.tvoid, false, LINK.LINKd);
 
 		sc = sc.push();
 		sc.stc &= ~STCstatic;		// not a static destructor
--- a/dmd/EnumDeclaration.d	Sun Oct 17 07:42:00 2010 +0400
+++ b/dmd/EnumDeclaration.d	Sun Oct 17 20:56:07 2010 +0400
@@ -118,6 +118,8 @@
 			scx = scope_;            // save so we don't make redundant copies
 			scope_ = null;
 		}
+		
+	    uint dprogress_save = global.dprogress;
 
 		if (sc.stc & STC.STCdeprecated)
 			isdeprecated = true;
@@ -145,7 +147,8 @@
 					scope_ = scx ? scx : sc.clone();
 					scope_.setNoFree();
 					scope_.module_.addDeferredSemantic(this);
-					writef("\tdeferring %s\n", toChars());
+					global.dprogress = dprogress_save;
+					//writef("\tdeferring %s\n", toChars());
 					return;
 				}
 			}
@@ -160,6 +163,7 @@
 		}
 
 		isdone = true;
+	    global.dprogress++;
 
 		type = type.semantic(loc, sc);
 		if (isAnonymous())
--- a/dmd/Expression.d	Sun Oct 17 07:42:00 2010 +0400
+++ b/dmd/Expression.d	Sun Oct 17 20:56:07 2010 +0400
@@ -323,7 +323,8 @@
 			{   
 				auto e = exps[i];
 
-				e = e.syntaxCopy();
+			    if (e)
+					e = e.syntaxCopy();
 				a[i] = e;
 			}
 		}
--- a/dmd/ForeachStatement.d	Sun Oct 17 07:42:00 2010 +0400
+++ b/dmd/ForeachStatement.d	Sun Oct 17 20:56:07 2010 +0400
@@ -346,7 +346,7 @@
 				  */
 				Identifier id = Lexer.uniqueId("__aggr");
 				ExpInitializer ie = new ExpInitializer(loc, new SliceExp(loc, aggr, null, null));
-				VarDeclaration tmp = new VarDeclaration(loc, aggr.type.nextOf().arrayOf(), id, ie);
+				VarDeclaration tmp = new VarDeclaration(loc, tab.nextOf().arrayOf(), id, ie);
 
 				Expression tmp_length = new DotIdExp(loc, new VarExp(loc, tmp), Id.length);
 
--- a/dmd/FuncDeclaration.d	Sun Oct 17 07:42:00 2010 +0400
+++ b/dmd/FuncDeclaration.d	Sun Oct 17 20:56:07 2010 +0400
@@ -6,6 +6,7 @@
 import dmd.AddrExp;
 import dmd.TryFinallyStatement;
 import dmd.TryCatchStatement;
+import dmd.SharedStaticDtorDeclaration;
 import dmd.Catch;
 import dmd.DeclarationStatement;
 import dmd.StaticDtorDeclaration;
@@ -20,6 +21,7 @@
 import dmd.Id;
 import dmd.StorageClassDeclaration;
 import dmd.StringExp;
+import dmd.PASS;
 import dmd.DsymbolExp;
 import dmd.HaltExp;
 import dmd.CommaExp;
@@ -27,6 +29,7 @@
 import dmd.IntegerExp;
 import dmd.ExpStatement;
 import dmd.CSX;
+import dmd.PROT;
 import dmd.CompoundStatement;
 import dmd.LabelStatement;
 import dmd.ThisExp;
@@ -150,19 +153,15 @@
     Dsymbols parameters;		// Array of VarDeclaration's for parameters
     DsymbolTable labtab;		// statement label symbol table
     Declaration overnext;		// next in overload list
-    Loc endloc;				// location of closing curly bracket
-    int vtblIndex;			// for member functions, index into vtbl[]
-    int naked;				// !=0 if naked
-    int inlineAsm;			// !=0 if has inline assembler
+    Loc endloc;					// location of closing curly bracket
+    int vtblIndex;				// for member functions, index into vtbl[]
+    int naked;					// !=0 if naked
+    int inlineAsm;				// !=0 if has inline assembler
     ILS inlineStatus;
-    int inlineNest;			// !=0 if nested inline
+    int inlineNest;				// !=0 if nested inline
     int cantInterpret;			// !=0 if cannot interpret function
-    int semanticRun;			// 1 semantic() run
-					// 2 semantic2() run
-					// 3 semantic3() started
-					// 4 semantic3() done
-					// 5 toObjFile() run
-					// this function's frame ptr
+    PASS semanticRun;
+								// this function's frame ptr
     ForeachStatement fes;		// if foreach body, this is the foreach
     int introducing;			// !=0 if 'introducing' function
     Type tintro;			// if !=null, then this is the type
@@ -231,7 +230,7 @@
 		inlineNest = 0;
 		inlineAsm = 0;
 		cantInterpret = 0;
-		semanticRun = 0;
+		semanticRun = PASSinit;
 version (DMDV1) {
 		nestedFrameRef = 0;
 }
@@ -291,7 +290,7 @@
 		printf("type: %p, %s\n", type, type.toChars());
 }
 
-		if (semanticRun && isFuncLiteralDeclaration())
+		if (semanticRun != PASSinit && isFuncLiteralDeclaration())
 		{
 			/* Member functions that have return types that are
 			 * forward references can have semantic() run more than
@@ -300,18 +299,35 @@
 			 */
 			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;
+		}
+
+		uint dprogress_save = global.dprogress;
+
+		foverrides.setDim(0);	// reset in case semantic() is being retried for this function
 
 		storage_class |= sc.stc & ~STC.STCref;
-		//printf("function storage_class = x%x\n", storage_class);
+	    //printf("function storage_class = x%llx, sc->stc = x%llx\n", storage_class, sc->stc);
 
 		if (!originalType)
 			originalType = type;
 		if (!type.deco)
 		{
     	    sc = sc.push();
-	        sc.stc |= storage_class & STC.STCref;	// forward refness to function type
+        	sc.stc |= storage_class & STCref;	// forward to function type
 	        type = type.semantic(loc, sc);
 	        sc = sc.pop();
 
@@ -387,13 +403,7 @@
 		size_t nparams = Parameter.dim(f.parameters);
 
 		linkage = sc.linkage;
-	//    if (!parent)
-		{
-		//parent = sc.scopesym;
-		parent = sc.parent;
-		}
 		protection = sc.protection;
-		Dsymbol parent = toParent();
 
 		if (storage_class & STC.STCscope)
 		error("functions cannot be scope");
@@ -434,7 +444,7 @@
 		{
 		if (isCtorDeclaration())
 		{
-			return;
+			goto Ldone;
 		}
 static if (false) {
 		// Verify no constructors, destructors, etc.
@@ -475,7 +485,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());
 		}
 
@@ -545,8 +555,10 @@
 			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:
@@ -586,12 +598,14 @@
 			break;
 
 			case -2:	// can't determine because of fwd refs
-			cd.sizeok = 2;	// can't finish due to forward reference
-			return;
+				cd.sizeok = 2;	// can't finish due to forward reference
+				global.dprogress = dprogress_save;
+				return;
 
 			default:
 			{
-				FuncDeclaration fdv = cast(FuncDeclaration)cd.vtbl.data[vi];
+			FuncDeclaration fdv = cast(FuncDeclaration)cd.baseClass.vtbl.data[vi];
+
 			// This function is covariant with fdv
 			if (fdv.isFinal())
 				error("cannot override final function %s", fdv.toPrettyChars());
@@ -665,6 +679,7 @@
 
 			case -2:
 				cd.sizeok = 2;	// can't finish due to forward reference
+			    global.dprogress = dprogress_save;
 				return;
 
 			default:
@@ -679,23 +694,25 @@
 					ti = fdv.tintro;
 				else if (!type.equals(fdv.type))
 				{
-				/* Only need to have a tintro if the vptr
-				 * offsets differ
-				 */
-				int offset;
-				if (fdv.type.nextOf().isBaseOf(type.nextOf(), &offset))
-				{
-					ti = fdv.type;
-static if (false) {
-					if (offset)
-					ti = fdv.type;
-					else if (type.nextOf().ty == Tclass)
+					/* Only need to have a tintro if the vptr
+					 * offsets differ
+					 */
+					uint errors = global.errors;
+					global.gag++;            // suppress printing of error messages
+					int offset;
+					int baseOf = fdv.type.nextOf().isBaseOf(type.nextOf(), &offset);
+					global.gag--;            // suppress printing of error messages
+					if (errors != global.errors)
 					{
-						ClassDeclaration cdn = (cast(TypeClass)type.nextOf()).sym;
-						if (cdn && cdn.sizeok != 1)
-							ti = fdv.type;
-						}
-}
+						// 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
+						global.dprogress = dprogress_save;
+						return;
+					}
+					if (baseOf)
+					{
+						ti = fdv.type;
 					}
 				}
 				if (ti)
@@ -717,6 +734,27 @@
 		}
 
 		L2: ;
+			/* Go through all the interface bases.
+			 * Disallow overriding any final functions in the interface(s).
+			 */
+			for (int i = 0; i < cd.interfaces_dim; i++)
+			{
+				BaseClass b = cd.interfaces[i];
+				if (b.base)
+				{
+					Dsymbol s = search_function(b.base, ident);
+					if (s)
+					{
+						FuncDeclaration f_ = s.isFuncDeclaration();
+						if (f_)
+						{
+							f_ = f_.overloadExactMatch(type);
+							if (f_ && f_.isFinal() && f_.prot() != PROT.PROTprivate)
+								error("cannot override final function %s.%s", b.base.toChars(), f_.toPrettyChars());
+						}
+					}
+				}
+			}
 		}
 		else if (isOverride() && !parent.isTemplateInstance())
 		error("override only applies to class member functions");
@@ -807,7 +845,7 @@
 		}
 		}
 
-		if (isVirtual())
+	    if (isVirtual() && semanticRun != PASSsemanticdone)
 		{
 			/* Rewrite contracts as nested functions, then call them.
 			 * Doing it as nested functions means that overriding functions
@@ -863,6 +901,9 @@
 		}
 
 	Ldone:
+	    global.dprogress++;
+		semanticRun = PASSsemanticdone;
+
 		/* Save scope for possible later use (if we need the
 		 * function internals)
 		 */
@@ -904,9 +945,9 @@
 		//printf("\tlinkage = %d\n", sc.linkage);
 
 		//printf(" sc.incontract = %d\n", sc.incontract);
-		if (semanticRun >= 3)
-		return;
-		semanticRun = 3;
+	    if (semanticRun >= PASSsemantic3)
+			return;
+		semanticRun = PASSsemantic3;
 
 		if (!type || type.ty != TY.Tfunction)
 		return;
@@ -1671,7 +1712,8 @@
 		sc2.callSuper = 0;
 		sc2.pop();
 		}
-		semanticRun = 4;
+		
+	    semanticRun = PASSsemantic3done;
 	}
 
     // called from semantic3
@@ -1763,17 +1805,22 @@
 	/*************************************************
 	 * 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
 	 */
     int findVtblIndex(Array vtbl, int dim)
 	{
+	    FuncDeclaration mismatch = null;
+		int bestvi = -1;
 		for (int vi = 0; vi < dim; vi++)
 		{
 			FuncDeclaration fdv = (cast(Dsymbol)vtbl.data[vi]).isFuncDeclaration();
 			if (fdv && fdv.ident is 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)
@@ -1782,15 +1829,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
@@ -1801,7 +1845,15 @@
 				}
 			}
 		}
-		return -1;
+	    if (bestvi == -1 && mismatch)
+		{
+			//type.print();
+			//mismatch.type.print();
+			//writef("%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;
 	}
 
 	/****************************************************
@@ -2328,7 +2380,11 @@
 		printf("result is %d\n",
 		isMember() && !(isStatic() || protection == PROT.PROTprivate || protection == PROT.PROTpackage) && toParent().isClassDeclaration());
 }
-		return isMember() && !(isStatic() || protection == PROT.PROTprivate || protection == PROT.PROTpackage) && toParent().isClassDeclaration();
+	    Dsymbol p = toParent();
+	    return isMember() &&
+			!(isStatic() || protection == PROT.PROTprivate || protection == PROT.PROTpackage) &&
+			p.isClassDeclaration() &&
+			!(p.isInterfaceDeclaration() && isFinal());
 	}
 
     override bool isFinal()
@@ -2404,7 +2460,7 @@
 		}
 }
 
-		if (cantInterpret || semanticRun == 3)
+	    if (cantInterpret || semanticRun == PASSsemantic3)
 			return null;
 
 		if (!fbody)
@@ -2413,13 +2469,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();
@@ -2433,21 +2489,6 @@
 			return null;
 		}
 
-		// Ensure there are no lazy parameters
-		if (tf.parameters)
-		{
-			size_t dim = Parameter.dim(tf.parameters);
-			for (size_t i = 0; i < dim; i++)
-			{
-				auto arg = Parameter.getNth(tf.parameters, i);
-				if (arg.storageClass & STClazy)
-				{
-					cantInterpret = 1;
-					return null;
-				}
-			}
-		}
-
 		scope InterState istatex = new InterState();
 		istatex.caller = istate;
 		istatex.fd = this;
@@ -2479,7 +2520,7 @@
 				Expression earg = arguments[i];
 				auto arg = Parameter.getNth(tf.parameters, i);
 
-				if (arg.storageClass & (STCout | STCref))
+			    if (arg.storageClass & (STCout | STCref | STClazy))
 				{
 				}
 				else
@@ -2686,7 +2727,7 @@
 		if (needThis() && !hasthis)
 			return 0;
 
-		if (inlineNest || (semanticRun < 3 && !hdrscan))
+	    if (inlineNest || (semanticRun < PASSsemantic3 && !hdrscan))
 		{
 	version (CANINLINE_LOG) {
 			printf("\t1: no, inlineNest = %d, semanticRun = %d\n", inlineNest, semanticRun);
@@ -3292,10 +3333,9 @@
 			return;
 		}
 
-		if (semanticRun >= 5)	// if toObjFile() already run
+		if (semanticRun >= PASSobj)	// if toObjFile() already run
 			return;
-			
-		semanticRun = 5;
+		semanticRun = PASSobj;
 
 		if (!func.fbody)
 		{
@@ -3349,18 +3389,25 @@
 
 			// Pull in RTL startup code
 			if (func.isMain())
-			{   objextdef("_main");
+			{   
+				objextdef("_main");
 version (POSIX) { ///TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_SOLARIS
 				obj_ehsections();	// initialize exception handling sections
-} else {
+}
+version (TARGET_WINDOS) {
 				objextdef("__acrtused_con");
 }
 				obj_includelib(libname);
 				s.Sclass = SC.SCglobal;
 			}
 			else if (strcmp(s.Sident.ptr, "main".ptr) == 0 && linkage == LINK.LINKc)
-				s.Sclass = SC.SCglobal;
-
+			{
+version (TARGET_WINDOS) {
+				objextdef("__acrtused_con");	// bring in C startup code
+				obj_includelib("snn.lib");		// bring in C runtime library
+}
+				s.Sclass = SCglobal;
+			}
 			else if (func.isWinMain())
 			{
 				objextdef("__acrtused");
@@ -3640,32 +3687,54 @@
 		}
 
 		// If static constructor
-		if (isStaticConstructor())
+		if (isSharedStaticCtorDeclaration())	// must come first because it derives from StaticCtorDeclaration
 		{
-			elem* e = el_una(OPER.OPucall, TYM.TYvoid, el_var(s));
+			elem* e = el_una(OPucall, TYvoid, el_var(s));
+			global.esharedctor = el_combine(global.esharedctor, e);
+		}
+		else if (isStaticCtorDeclaration())
+		{
+			elem* e = el_una(OPucall, TYvoid, el_var(s));
 			global.ector = el_combine(global.ector, e);
 		}
 
 		// If static destructor
-		if (isStaticDestructor())
+		if (auto f_ = isSharedStaticDtorDeclaration())	// must come first because it derives from StaticDtorDeclaration
 		{
 			elem* e;
 
 version (STATICCTOR) {
-			e = el_bin(OPER.OPcall, TYM.TYvoid, el_var(rtlsym[RTLSYM.RTLSYM_FATEXIT]), el_ptr(s));
-			ector = el_combine(ector, e);
+			e = el_bin(OPcall, TYvoid, el_var(rtlsym[RTLSYM_FATEXIT]), el_ptr(s));
+			esharedctor = el_combine(esharedctor, e);
+			shareddtorcount++;
+} else {
+			if (f_.vgate)
+			{   
+				/* Increment destructor's vgate at construction time
+				 */
+				global.esharedctorgates.push(cast(void*)f_);
+			}
+
+			e = el_una(OPucall, TYvoid, el_var(s));
+			global.eshareddtor = el_combine(e, global.eshareddtor);
+}
+		}
+		else if (auto f_ = isStaticDtorDeclaration())
+		{
+			elem* e;
+
+version (STATICCTOR) {
+			e = el_bin(OPcall, TYvoid, el_var(rtlsym[RTLSYM_FATEXIT]), el_ptr(s));
+			global.ector = el_combine(ector, e);
 			dtorcount++;
 } else {
-			StaticDtorDeclaration f2 = isStaticDtorDeclaration();
-			assert(f2);
-			if (f2.vgate)
-			{
-				/* Increment destructor's vgate at construction time
+			if (f_.vgate)
+			{   /* Increment destructor's vgate at construction time
 				 */
-				global.ectorgates.push(cast(void*)f2);
+				global.ectorgates.push(cast(void*)f_);
 			}
 
-			e = el_una(OPER.OPucall, TYM.TYvoid, el_var(s));
+			e = el_una(OPucall, TYvoid, el_var(s));
 			global.edtor = el_combine(e, global.edtor);
 }
 		}
--- a/dmd/FuncExp.d	Sun Oct 17 07:42:00 2010 +0400
+++ b/dmd/FuncExp.d	Sun Oct 17 20:56:07 2010 +0400
@@ -7,6 +7,7 @@
 import dmd.Loc;
 import dmd.Scope;
 import dmd.InlineCostState;
+import dmd.InterState;
 import dmd.IRState;
 import dmd.HdrGenState;
 import dmd.FuncLiteralDeclaration;
@@ -85,6 +86,15 @@
 
 		return this;
 	}
+	
+    Expression interpret(InterState istate)
+	{
+version (LOG) {
+		writef("FuncExp::interpret() %s\n", toChars());
+}
+		return this;
+
+	}
 
 	override void scanForNestedRef(Scope sc)
 	{
--- a/dmd/Global.d	Sun Oct 17 07:42:00 2010 +0400
+++ b/dmd/Global.d	Sun Oct 17 20:56:07 2010 +0400
@@ -60,6 +60,7 @@
     string doc_ext	= "html";	// for Ddoc generated files
     string ddoc_ext	= "ddoc";	// for Ddoc macro include files
     string json_ext = "json";
+    string map_ext = "map";	// for .map files
     string hdr_ext	= "di";	// for D 'header' import files
     string copyright= "Copyright (c) 1999-2009 by Digital Mars";
     string written	= "written by Walter Bright, ported to D by community";
@@ -70,7 +71,7 @@
     string[] path;	// Array of char*'s which form the import lookup path
     string[] filePath;	// Array of char*'s which form the file import lookup path
     int structalign = 8;
-    string version_ = "v2.039";
+    string version_ = "v2.040";
 
     Param params;
     uint errors;	// number of errors reported so far
@@ -166,6 +167,10 @@
 	Outbuffer objbuf;
 	string lastmname;
 	int count;
+	elem* esharedctor;
+	Array esharedctorgates;
+	elem* eshareddtor;
+	int shareddtorcount;
 
 	// Used in backend.iasm
 	ASM_STATE asmstate;
@@ -208,6 +213,7 @@
 		obj_symbols_towrite = new Array();
 
 		ectorgates = new Array();
+		esharedctorgates = new Array();
 
 		sdummy = new Dsymbol();
 		edummy = new Expression(Loc(0), TOK.init, 0);
--- a/dmd/Id.d	Sun Oct 17 07:42:00 2010 +0400
+++ b/dmd/Id.d	Sun Oct 17 20:56:07 2010 +0400
@@ -59,6 +59,7 @@
 		ID( "ptr" ),
 		ID( "funcptr" ),
 		ID( "dollar", "__dollar" ),
+		ID( "ctfe", "__ctfe" ),
 		ID( "offset" ),
 		ID( "offsetof" ),
 		ID( "ModuleInfo" ),
@@ -150,6 +151,7 @@
         ID( "safe" ),
         ID( "trusted" ),
         ID( "system" ),
+        ID( "disable" ),
 
 		// For inline assembler
 		ID( "___out", "out" ),
@@ -296,11 +298,14 @@
 		ID( "isVirtualFunction" ),
 		ID( "isAbstractFunction" ),
 		ID( "isFinalFunction" ),
+		ID( "isStaticFunction" ),
         ID( "isRef" ),
         ID( "isOut" ),
         ID( "isLazy" ),
 		ID( "hasMember" ),
+		ID( "identifier" ),
 		ID( "getMember" ),
+		ID( "getOverloads" ),
 		ID( "getVirtualFunctions" ),
 		ID( "classInstanceSize" ),
 		ID( "allMembers" ),
--- a/dmd/IdentifierExp.d	Sun Oct 17 07:42:00 2010 +0400
+++ b/dmd/IdentifierExp.d	Sun Oct 17 20:56:07 2010 +0400
@@ -7,6 +7,8 @@
 import dmd.TypePointer;
 import dmd.FuncDeclaration;
 import dmd.TemplateInstance;
+import dmd.Id;
+import dmd.VarDeclaration;
 import dmd.TemplateDeclaration;
 import dmd.TemplateExp;
 import dmd.DsymbolExp;
@@ -132,6 +134,15 @@
 
 			return e.semantic(sc);
 		}
+		
+		if (ident == Id.ctfe)
+		{  
+			// Create the magic __ctfe bool variable
+		   VarDeclaration vd = new VarDeclaration(loc, Type.tbool, Id.ctfe, null);
+		   Expression e = new VarExp(loc, vd);
+		   e = e.semantic(sc);
+		   return e;
+		}
 
 		error("undefined identifier %s", ident.toChars());
 		type = Type.terror;
--- a/dmd/InvariantDeclaration.d	Sun Oct 17 07:42:00 2010 +0400
+++ b/dmd/InvariantDeclaration.d	Sun Oct 17 20:56:07 2010 +0400
@@ -32,23 +32,21 @@
 
     override void 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
--- a/dmd/Module.d	Sun Oct 17 07:42:00 2010 +0400
+++ b/dmd/Module.d	Sun Oct 17 20:56:07 2010 +0400
@@ -8,6 +8,8 @@
 import dmd.StaticDtorDeclaration;
 import dmd.Scope;
 import dmd.Id;
+import dmd.SharedStaticCtorDeclaration;
+import dmd.SharedStaticDtorDeclaration;
 import dmd.Import;
 import dmd.ClassDeclaration;
 import dmd.ModuleDeclaration;
@@ -951,8 +953,12 @@
 		global.ector = null;
 		global.ectorgates.setDim(0);
 		global.edtor = null;
+	    global.esharedctor = null;
+		global.esharedctorgates.setDim(0);
+		global.eshareddtor = null;
 		global.etest = null;
 		global.dtorcount = 0;
+	    global.shareddtorcount = 0;
 
 		if (doppelganger)
 		{
@@ -961,7 +967,7 @@
 			 */
 			Module m = cast(Module)aimports.data[0];
 			assert(m);
-			if (m.sictor || m.sctor || m.sdtor)
+			if (m.sictor || m.sctor || m.sdtor || m.ssharedctor || m.sshareddtor)
 			{
 				Symbol* s = m.toSymbol();
 				//objextern(s);
@@ -1057,7 +1063,7 @@
 		}
 
 		// If coverage / static constructor / destructor / unittest calls
-		if (global.eictor || global.ector || global.ectorgates.dim || global.edtor || global.etest)
+	    if (global.eictor || global.ector || global.ectorgates.dim || global.edtor || global.esharedctor || global.esharedctorgates.dim || global.eshareddtor || global.etest)
 		{
 			/* t will be the type of the functions generated:
 			 *	extern (C) void func();
@@ -1118,6 +1124,45 @@
 				sdtor.Sfunc.Fstartblock = b;
 				writefunc(sdtor);
 			}
+			
+			if (global.esharedctor || global.esharedctorgates.dim)
+			{
+				global.localgot = null;
+				ssharedctor = toSymbolX("__modsharedctor", SCglobal, t, moddeco);
+				cstate.CSpsymtab = &ssharedctor.Sfunc.Flocsym;
+
+				for (int i = 0; i < global.esharedctorgates.dim; i++)
+				{	
+					SharedStaticDtorDeclaration f = cast(SharedStaticDtorDeclaration)global.esharedctorgates.data[i];
+
+					Symbol* s = f.vgate.toSymbol();
+					elem* e = el_var(s);
+					e = el_bin(OPaddass, TYint, e, el_long(TYint, 1));
+					global.esharedctor = el_combine(global.esharedctor, e);
+				}
+
+				block* b = block_calloc();
+				b.BC = BCret;
+				b.Belem = global.esharedctor;
+				ssharedctor.Sfunc.Fstartblock = b;
+				writefunc(ssharedctor);
+version (STATICCTOR) {
+				obj_staticctor(ssharedctor, shareddtorcount, 1);
+}
+			}
+
+			if (global.eshareddtor)
+			{
+				global.localgot = null;
+				sshareddtor = toSymbolX("__modshareddtor", SCglobal, t, moddeco);
+
+				block *b = block_calloc();
+				b.BC = BCret;
+				b.Belem = global.eshareddtor;
+				sshareddtor.Sfunc.Fstartblock = b;
+				writefunc(sshareddtor);
+			}
+
 
 			if (global.etest)
 			{
@@ -1292,17 +1337,19 @@
 	 * Run semantic() on deferred symbols.
 	 */
 
-    void runDeferredSemantic()
+    static void runDeferredSemantic()
 	{
+		if (global.dprogress == 0)
+			return;
+	
 		if (global.nested)
 			return;
 		//if (deferred.dim) printf("+Module.runDeferredSemantic('%s'), len = %d\n", toChars(), deferred.dim);
 		global.nested++;
 
-		size_t len;
-
 		auto deferred = global.deferred;
 
+		size_t len;
 		do
 		{
 			global.dprogress = 0;
@@ -1380,6 +1427,8 @@
     Symbol* sictor;		// module order independent constructor
     Symbol* sctor;		// module constructor
     Symbol* sdtor;		// module destructor
+    Symbol* ssharedctor;	// module shared constructor
+    Symbol* sshareddtor;	// module shared destructor
     Symbol* stest;		// module unit test
 
     Symbol* sfilename;		// symbol for filename
@@ -1526,10 +1575,15 @@
 
 		uint offset;
 	version (DMDV2) {
-		uint sizeof_ModuleInfo = 18 * PTRSIZE;
+		uint sizeof_ModuleInfo = 16 * PTRSIZE;
 	} else {
 		uint sizeof_ModuleInfo = 14 * PTRSIZE;
 	}
+	
+		version (MODULEINFO_IS_STRUCT) {} else {
+			sizeof_ModuleInfo -= 2 * PTRSIZE;
+		}
+		//printf("moduleinfo size = x%x\n", sizeof_ModuleInfo);
 
 		//////////////////////////////////////////////
 
@@ -1550,11 +1604,14 @@
 			void *unitTest;
 			const(MemberInfo[]) function(string) xgetMembers;	// module getMembers() function
 			void *ictor;
-			void*[4] reserved;
+		    void *sharedctor;
+			void *shareddtor;
+			uint index;
+			void*[1] reserved;
 		   }
 		 */
 		dt_t* dt = null;
-
+version (MODULEINFO_IS_STRUCT) {} else {
 		if (global.moduleinfo)
 			dtxoff(&dt, global.moduleinfo.toVtblSymbol(), 0, TYM.TYnptr); // vtbl for ModuleInfo
 		else
@@ -1563,7 +1620,7 @@
 			dtdword(&dt, 0);		// BUG: should be an assert()
 		}
 		dtdword(&dt, 0);			// monitor
-
+}
 		// name[]
 		string name = toPrettyChars();
 		size_t namelen = name.length;
@@ -1606,13 +1663,13 @@
 		else
 			dtdword(&dt, 8|4);		// flags (4 means MIstandalone)
 
-		if (sctor)
-			dtxoff(&dt, sctor, 0, TYM.TYnptr);
+		if (ssharedctor)
+			dtxoff(&dt, ssharedctor, 0, TYnptr);
 		else
 			dtdword(&dt, 0);
 
-		if (sdtor)
-			dtxoff(&dt, sdtor, 0, TYM.TYnptr);
+		if (sshareddtor)
+			dtxoff(&dt, sshareddtor, 0, TYnptr);
 		else
 			dtdword(&dt, 0);
 
@@ -1635,10 +1692,19 @@
 			dtdword(&dt, 0);
 
 	version (DMDV2) {
-		// void*[4] reserved;
-		dtdword(&dt, 0);
-		dtdword(&dt, 0);
-		dtdword(&dt, 0);
+		if (sctor)
+			dtxoff(&dt, sctor, 0, TYnptr);
+		else
+			dtdword(&dt, 0);
+
+		if (sdtor)
+			dtxoff(&dt, sdtor, 0, TYnptr);
+		else
+			dtdword(&dt, 0);
+
+		dtdword(&dt, 0);				// index
+
+		// void*[1] reserved;
 		dtdword(&dt, 0);
 	}
 		//////////////////////////////////////////////
--- a/dmd/NewDeclaration.d	Sun Oct 17 07:42:00 2010 +0400
+++ b/dmd/NewDeclaration.d	Sun Oct 17 20:56:07 2010 +0400
@@ -45,20 +45,18 @@
 
     override void 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);
--- a/dmd/NewExp.d	Sun Oct 17 07:42:00 2010 +0400
+++ b/dmd/NewExp.d	Sun Oct 17 20:56:07 2010 +0400
@@ -2,9 +2,11 @@
 
 import dmd.common;
 import dmd.Expression;
+import dmd.GlobalExpressions;
 import dmd.NewDeclaration;
 import dmd.CtorDeclaration;
 import dmd.ClassDeclaration;
+import dmd.InterState;
 import dmd.Type;
 import dmd.OutBuffer;
 import dmd.PREC;
@@ -31,6 +33,9 @@
 import dmd.IntegerExp;
 import dmd.TypePointer;
 
+import dmd.interpret.Util;
+import dmd.expression.Util;
+
 import dmd.backend.elem;
 import dmd.backend.TYM;
 import dmd.backend.SC;
@@ -41,7 +46,6 @@
 import dmd.backend.Util;
 import dmd.backend.OPER;
 import dmd.backend.RTLSYM;
-import dmd.expression.Util;
 import dmd.codegen.Util;
 
 import std.string : toStringz;
@@ -378,6 +382,23 @@
 
 		return this;
 	}
+	
+    Expression interpret(InterState istate)
+	{
+version (LOG) {
+		writef("NewExp::interpret() %s\n", toChars());
+}
+		if (newtype.ty == Tarray && arguments && arguments.dim == 1)
+		{
+			Expression lenExpr = arguments[0].interpret(istate);
+			if (lenExpr is EXP_CANT_INTERPRET)
+				return EXP_CANT_INTERPRET;
+			return createBlockDuplicatedArrayLiteral(newtype, newtype.defaultInitLiteral(Loc(0)), cast(uint)lenExpr.toInteger());
+		}
+		error("Cannot interpret %s at compile time", toChars());
+		return EXP_CANT_INTERPRET;
+
+	}
 
 	override Expression optimize(int result)
 	{
--- a/dmd/Param.d	Sun Oct 17 07:42:00 2010 +0400
+++ b/dmd/Param.d	Sun Oct 17 20:56:07 2010 +0400
@@ -18,6 +18,7 @@
     bool vtls;		// identify thread local variables
     byte symdebug;	// insert debug symbolic information
     bool optimize;	// run optimizer
+    bool map;		// generate linker .map file
     bool cpu;		// target CPU
     bool isX86_64;	// generate X86_64 bit code
     bool isLinux;	// generate code for linux
@@ -101,4 +102,5 @@
     string deffile;
     string resfile;
     string exefile;
+    string mapfile;
 }
--- a/dmd/Parser.d	Sun Oct 17 07:42:00 2010 +0400
+++ b/dmd/Parser.d	Sun Oct 17 20:56:07 2010 +0400
@@ -5,6 +5,8 @@
 import dmd.PostBlitDeclaration;
 import dmd.FileInitExp;
 import dmd.LineInitExp;
+import dmd.SharedStaticCtorDeclaration;
+import dmd.SharedStaticDtorDeclaration;
 import dmd.EnumMember;
 import dmd.CtorDeclaration;
 import dmd.ShlAssignExp;
@@ -481,25 +483,42 @@
 			break;
 
 			case TOK.TOKconst:
-			if (peek(&token).value == TOK.TOKlparen)
+			if (peekNext() == TOKlparen)
 				goto Ldeclaration;
 			stc = STC.STCconst;
 			goto Lstc;
 
 			case TOK.TOKimmutable:
-			if (peek(&token).value == TOK.TOKlparen)
+			if (peekNext() == TOKlparen)
 				goto Ldeclaration;
 			stc = STC.STCimmutable;
 			goto Lstc;
 
 			case TOK.TOKshared:
-			if (peek(&token).value == TOK.TOKlparen)
-				goto Ldeclaration;
-			stc = STC.STCshared;
-			goto Lstc;
-
-	        case TOKwild:
-		    if (peek(&token).value == TOK.TOKlparen)
+			{
+				TOK next = peekNext();
+				if (next == TOKlparen)
+					goto Ldeclaration;
+				if (next == TOKstatic)
+				{   
+					TOK next2 = peekNext2();
+					if (next2 == TOKthis)
+					{	
+						s = parseSharedStaticCtor();
+						break;
+					}
+					if (next2 == TOKtilde)
+					{	
+						s = parseSharedStaticDtor();
+						break;
+					}
+				}
+				stc = STCshared;
+				goto Lstc;
+			}
+
+			case TOKwild:
+			if (peekNext() == TOKlparen)
 		        goto Ldeclaration;
 		    stc = STCwild;
 		    goto Lstc;
@@ -892,8 +911,11 @@
 	        stc = STCtrusted;
         else if (token.ident == Id.system)
 	        stc = STCsystem;
-        else
-	        error("valid attribute identifiers are @property, @safe, @trusted, @system, not @%s", token.toChars());
+        else if (token.ident == Id.disable)
+			stc = STCdisable;
+		else
+			error("valid attribute identifiers are @property, @safe, @trusted, @system, @disable not @%s", token.toChars());
+
         return stc;
     }
 }
@@ -1694,14 +1716,13 @@
 	 */
     StaticCtorDeclaration parseStaticCtor()
 	{
-		StaticCtorDeclaration f;
 		Loc loc = this.loc;
 
 		nextToken();
 		check(TOKlparen);
 		check(TOKrparen);
 
-		f = new StaticCtorDeclaration(loc, Loc(0));
+		StaticCtorDeclaration f = new StaticCtorDeclaration(loc, Loc(0));
 		parseContracts(f);
 		return f;
 	}
@@ -1713,7 +1734,6 @@
 	 */
     StaticDtorDeclaration parseStaticDtor()
 	{
-		StaticDtorDeclaration f;
 		Loc loc = this.loc;
 
 		nextToken();
@@ -1721,7 +1741,49 @@
 		check(TOKlparen);
 		check(TOKrparen);
 
-		f = new StaticDtorDeclaration(loc, Loc(0));
+		StaticDtorDeclaration f = new StaticDtorDeclaration(loc, Loc(0));
+		parseContracts(f);
+		return f;
+
+	}
+	
+	/*****************************************
+	 * Parse a shared static constructor definition:
+	 *	shared static this() { body }
+	 * Current token is 'shared'.
+	 */
+    SharedStaticCtorDeclaration parseSharedStaticCtor()
+	{
+		Loc loc = this.loc;
+
+		nextToken();
+		nextToken();
+		nextToken();
+		check(TOKlparen);
+		check(TOKrparen);
+
+		SharedStaticCtorDeclaration f = new SharedStaticCtorDeclaration(loc, Loc(0));
+		parseContracts(f);
+		return f;
+	}
+	
+	/*****************************************
+	 * Parse a shared static destructor definition:
+	 *	shared static ~this() { body }
+	 * Current token is 'shared'.
+	 */
+    SharedStaticDtorDeclaration parseSharedStaticDtor()
+	{
+	    Loc loc = this.loc;
+
+		nextToken();
+		nextToken();
+		nextToken();
+		check(TOKthis);
+		check(TOKlparen);
+		check(TOKrparen);
+
+		SharedStaticDtorDeclaration f = new SharedStaticDtorDeclaration(loc, Loc(0));
 		parseContracts(f);
 		return f;
 	}
--- a/dmd/PostBlitDeclaration.d	Sun Oct 17 07:42:00 2010 +0400
+++ b/dmd/PostBlitDeclaration.d	Sun Oct 17 20:56:07 2010 +0400
@@ -43,7 +43,7 @@
 	{
 		//writef("PostBlitDeclaration.semantic() %s\n", toChars());
 		//writef("ident: %s, %s, %p, %p\n", ident.toChars(), Id.dtor.toChars(), ident, Id.dtor);
-		//writef("stc = x%llx\n", sc.stc);
+	    //writef("stc = x%llx\n", sc.stc);
 		parent = sc.parent;
 		Dsymbol parent = toParent();
 		StructDeclaration ad = parent.isStructDeclaration();
--- a/dmd/PowExp.d	Sun Oct 17 07:42:00 2010 +0400
+++ b/dmd/PowExp.d	Sun Oct 17 20:56:07 2010 +0400
@@ -18,6 +18,7 @@
 import dmd.Global;
 import dmd.IntegerExp;
 import dmd.Type;
+import dmd.STC;
 import dmd.Lexer;
 import dmd.VarDeclaration;
 import dmd.ExpInitializer;
@@ -86,25 +87,30 @@
 		        e1.type.toBasetype().toChars(), e1.toChars(), e2.toChars());
 	            return new ErrorExp();
 	        }
+			
+			// Determine if we're raising to an integer power.
+			long intpow = 0;
+			if (e2.op == TOKint64 && (cast(long)e2.toInteger() == 2 || cast(long)e2.toInteger() == 3))
+				intpow = e2.toInteger();
+			else if (e2.op == TOKfloat64 && (e2.toReal() == cast(long)(e2.toReal())))
+				intpow = cast(long)(e2.toReal());
 	
 	        // Deal with x^^2, x^^3 immediately, since they are of practical importance.
-	        // Don't bother if x is a literal, since it will be constant-folded anyway.
-	        if ( (  (e2.op == TOK.TOKint64 && (e2.toInteger() == 2 || e2.toInteger() == 3)) 
-	             ||	(e2.op == TOK.TOKfloat64 && (e2.toReal() == 2.0 || e2.toReal() == 3.0))
-	             ) && (e1.op == TOK.TOKint64 || e1.op == TOK.TOKfloat64)
-	           )
+        	if (intpow == 2 || intpow == 3)
 	        {
 	            typeCombine(sc);
 	            // Replace x^^2 with (tmp = x, tmp*tmp)
 	            // Replace x^^3 with (tmp = x, tmp*tmp*tmp) 
 	            Identifier idtmp = Lexer.uniqueId("__tmp");
 	            VarDeclaration tmp = new VarDeclaration(loc, e1.type.toBasetype(), idtmp, new ExpInitializer(Loc(0), e1));
-	            VarExp ve = new VarExp(loc, tmp);
+	            tmp.storage_class = STC.STCctfe;
+				Expression ve = new VarExp(loc, tmp);
 	            Expression ae = new DeclarationExp(loc, tmp);
+				/* Note that we're reusing ve. This should be ok.
+				*/
 	            Expression me = new MulExp(loc, ve, ve);
-	            if ( (e2.op == TOK.TOKint64 && e2.toInteger() == 3) 
-	              || (e2.op == TOK.TOKfloat64 && e2.toReal() == 3.0))
-		        me = new MulExp(loc, me, ve);
+           	    if (intpow == 3)
+					me = new MulExp(loc, me, ve);
 	            e = new CommaExp(loc, ae, me);
 	            e = e.semantic(sc);
 	            return e;
@@ -143,6 +149,10 @@
 	            // integer powers are treated specially by std.math.pow).
 	            if (!e2.type.isintegral())
 		            typeCombine(sc);
+			    // In fact, if it *could* have been an integer, make it one.
+				if (e2.op == TOKfloat64 && intpow != 0)
+					e2 = new IntegerExp(loc, intpow, Type.tint64);
+
 	            e = new CallExp(loc, new DotIdExp(loc, e, Id._pow), e1, e2);	
  	        }	
  	        e = e.semantic(sc);
--- a/dmd/STC.d	Sun Oct 17 07:42:00 2010 +0400
+++ b/dmd/STC.d	Sun Oct 17 20:56:07 2010 +0400
@@ -44,7 +44,9 @@
 	STCtrusted		= 0x400000000,
 	STCsystem		= 0x800000000,
 	STCctfe			= 0x1000000000,	// can be used in CTFE, even if it is static
+	STCdisable      = 0x2000000000,	// for functions that are not callable
 }
+
 alias STC StorageClass;
 
 import dmd.EnumUtils;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/SharedStaticCtorDeclaration.d	Sun Oct 17 20:56:07 2010 +0400
@@ -0,0 +1,31 @@
+module dmd.SharedStaticCtorDeclaration;
+
+import dmd.StaticCtorDeclaration;
+import dmd.Loc;
+import dmd.Dsymbol;
+import dmd.OutBuffer;
+import dmd.HdrGenState;
+import dmd.FuncDeclaration;
+
+class SharedStaticCtorDeclaration : StaticCtorDeclaration
+{
+    this(Loc loc, Loc endloc)
+	{
+		super(loc, endloc, "_sharedStaticCtor");
+	}
+	
+    Dsymbol syntaxCopy(Dsymbol s)
+	{
+		assert(!s);
+		SharedStaticCtorDeclaration scd = new SharedStaticCtorDeclaration(loc, endloc);
+		return FuncDeclaration.syntaxCopy(scd);
+	}
+	
+    void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		buf.writestring("shared ");
+		StaticCtorDeclaration.toCBuffer(buf, hgs);
+	}
+
+    SharedStaticCtorDeclaration isSharedStaticCtorDeclaration() { return this; }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/SharedStaticDtorDeclaration.d	Sun Oct 17 20:56:07 2010 +0400
@@ -0,0 +1,34 @@
+module dmd.SharedStaticDtorDeclaration;
+
+import dmd.StaticDtorDeclaration;
+import dmd.Loc;
+import dmd.Dsymbol;
+import dmd.OutBuffer;
+import dmd.HdrGenState;
+import dmd.FuncDeclaration;
+
+class SharedStaticDtorDeclaration : StaticDtorDeclaration
+{
+    this(Loc loc, Loc endloc)
+	{
+	    super(loc, endloc, "_sharedStaticDtor");
+	}
+	
+    Dsymbol syntaxCopy(Dsymbol s)
+	{
+		assert(!s);
+		SharedStaticDtorDeclaration sdd = new SharedStaticDtorDeclaration(loc, endloc);
+		return FuncDeclaration.syntaxCopy(sdd);
+	}
+	
+    void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+	    if (!hgs.hdrgen)
+		{
+			buf.writestring("shared ");
+			StaticDtorDeclaration.toCBuffer(buf, hgs);
+		}
+	}
+
+    SharedStaticDtorDeclaration isSharedStaticDtorDeclaration() { return this; }
+}
\ No newline at end of file
--- a/dmd/StaticCtorDeclaration.d	Sun Oct 17 07:42:00 2010 +0400
+++ b/dmd/StaticCtorDeclaration.d	Sun Oct 17 20:56:07 2010 +0400
@@ -31,12 +31,12 @@
 
 class StaticCtorDeclaration : FuncDeclaration
 {
-	this(Loc loc, Loc endloc)
+    this(Loc loc, Loc endloc, string name = "_staticCtor")
 	{
 		register();
 		super(loc, endloc, Identifier.generateId("_staticCtor"), STCstatic, null);
 	}
-	
+
 	override Dsymbol syntaxCopy(Dsymbol s)
 	{
 		assert(!s);
@@ -48,13 +48,14 @@
 	{
 		//printf("StaticCtorDeclaration.semantic()\n");
 
-		type = new TypeFunction(null, Type.tvoid, false, LINK.LINKd);
+	    if (!type)
+			type = new TypeFunction(null, Type.tvoid, false, LINK.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;
@@ -64,7 +65,7 @@
 			 */
 			Identifier id = Lexer.idPool("__gate");
 			VarDeclaration v = new VarDeclaration(Loc(0), Type.tint32, id, null);
-			v.storage_class = STCstatic;
+			v.storage_class = isSharedStaticCtorDeclaration() ? STCstatic : STCtls;
 			Statements sa = new Statements();
 			Statement s = new DeclarationStatement(Loc(0), v);
 			sa.push(s);
@@ -100,11 +101,6 @@
 		return null;
 	}
 	
-	override bool isStaticConstructor()
-	{
-		return true;
-	}
-	
 	override bool isVirtual()
 	{
 		return false;
--- a/dmd/StaticDtorDeclaration.d	Sun Oct 17 07:42:00 2010 +0400
+++ b/dmd/StaticDtorDeclaration.d	Sun Oct 17 20:56:07 2010 +0400
@@ -34,10 +34,11 @@
 {
 	VarDeclaration vgate;	// 'gate' variable
 
-	this(Loc loc, Loc endloc)
+    this(Loc loc, Loc endloc, string name = "_staticDtor")
 	{
 		register();
-		super(loc, endloc, Identifier.generateId("_staticDtor"), STCstatic, null);
+		super(loc, endloc, Identifier.generateId(name), STCstatic, null);
+	    vgate = null;
 	}
 	
 	override Dsymbol syntaxCopy(Dsymbol s)
@@ -49,20 +50,15 @@
 	
 	override void semantic(Scope sc)
 	{
-		ClassDeclaration cd;
-		Type tret;
-
-		cd = sc.scopesym.isClassDeclaration();
-		if (!cd)
-		{
-		}
-		type = new TypeFunction(null, Type.tvoid, false, LINK.LINKd);
+	    ClassDeclaration cd = sc.scopesym.isClassDeclaration();
+		if (!type)
+			type = new TypeFunction(null, Type.tvoid, false, LINK.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;
@@ -73,7 +69,7 @@
 			 */
 			Identifier id = Lexer.idPool("__gate");
 			VarDeclaration v = new VarDeclaration(Loc(0), Type.tint32, id, null);
-			v.storage_class = STCstatic;
+			v.storage_class = isSharedStaticDtorDeclaration() ? STCstatic : STCtls;
 			auto sa = new Statements();
 			Statement s = new DeclarationStatement(Loc(0), v);
 			sa.push(s);
@@ -109,11 +105,6 @@
 		return null;
 	}
 	
-	override bool isStaticDestructor()
-	{
-		return true;
-	}
-	
 	override bool isVirtual()
 	{
 		return false;
--- a/dmd/StorageClassDeclaration.d	Sun Oct 17 07:42:00 2010 +0400
+++ b/dmd/StorageClassDeclaration.d	Sun Oct 17 20:56:07 2010 +0400
@@ -113,18 +113,19 @@
 			{ STCalias,        TOKalias },
 			{ STCout,          TOKout },
 			{ STCin,           TOKin },
-///		version (DMDV2) {
-///			{ STCimmutable,    TOKimmutable },
-///			{ STCshared,       TOKshared },
-///			{ STCnothrow,      TOKnothrow },
-///			{ STCpure,         TOKpure },
-///			{ STCref,          TOKref },
-///			{ STCtls,          TOKtls },
-///			{ STCgshared,      TOKgshared },
-///			{ STCproperty,     TOKat },
-///			{ STCsafe,         TOKat },
-///			{ STCtrusted,      TOKat },
-///		}
+///version (DMDV2) {
+			{ STCimmutable,    TOKimmutable },
+			{ STCshared,       TOKshared },
+			{ STCnothrow,      TOKnothrow },
+			{ STCpure,         TOKpure },
+			{ STCref,          TOKref },
+			{ STCtls,          TOKtls },
+			{ STCgshared,      TOKgshared },
+			{ STCproperty,     TOKat },
+			{ STCsafe,         TOKat },
+			{ STCtrusted,      TOKat },
+			{ STCdisable,      TOKat },
+///}
 		];
 
 		for (int i = 0; i < table.length; i++)
@@ -141,6 +142,8 @@
 						id = Id.safe;
 					else if (stc & STCtrusted)
 						id = Id.trusted;
+					else if (stc & STCdisable)
+						id = Id.disable;
 					else
 						assert(0);
 					buf.writestring(id.toChars());
--- a/dmd/StructDeclaration.d	Sun Oct 17 07:42:00 2010 +0400
+++ b/dmd/StructDeclaration.d	Sun Oct 17 20:56:07 2010 +0400
@@ -133,6 +133,8 @@
 			scx = scope_;            // save so we don't make redundant copies
 			scope_ = null;
 		}
+		
+	    uint dprogress_save = global.dprogress;
 
 		parent = sc.parent;
 		type = type.semantic(loc, sc);
@@ -363,25 +365,28 @@
 		sc2.pop();
 
 		if (sizeok == 2)
-		{	// semantic() failed because of forward references.
-		// Unwind what we did, and defer it for later
-		fields.setDim(0);
-		structsize = 0;
-		alignsize = 0;
-		structalign = 0;
+		{	
+			// semantic() failed because of forward references.
+			// Unwind what we did, and defer it for later
+			fields.setDim(0);
+			structsize = 0;
+			alignsize = 0;
+			structalign = 0;
 
-		scope_ = scx ? scx : sc.clone();
-		scope_.setNoFree();
-		scope_.module_.addDeferredSemantic(this);
-		writef("\tdeferring %s\n", toChars());
-		return;
+			scope_ = scx ? scx : sc.clone();
+			scope_.setNoFree();
+			scope_.module_.addDeferredSemantic(this);
+			
+			global.dprogress = dprogress_save;
+			//printf("\tdeferring %s\n", toChars());
+			return;
 		}
 
 		// 0 sized struct's are set to 1 byte
 		if (structsize == 0)
 		{
-		structsize = 1;
-		alignsize = 1;
+			structsize = 1;
+			alignsize = 1;
 		}
 
 		// Round struct size up to next alignsize boundary.
@@ -600,6 +605,7 @@
 		{
 			tmp = new VarDeclaration(Loc(0), type, idtmp, new VoidInitializer(Loc(0)));
 			tmp.noauto = true;
+		    tmp.storage_class |= STCctfe;
 			e = new DeclarationExp(Loc(0), tmp);
 
 			Expression e2;
@@ -750,6 +756,7 @@
 	{
 		//printf("StructDeclaration.buildPostBlit() %s\n", toChars());
 		Expression e = null;
+	    StorageClass stc = STCundefined;
 
 		foreach (VarDeclaration v; fields)
 		{
@@ -759,37 +766,42 @@
 			Type tv = v.type.toBasetype();
 			size_t dim = 1;
 			while (tv.ty == TY.Tsarray)
-			{   TypeSArray ta = cast(TypeSArray)tv;
+			{   
+				TypeSArray ta = cast(TypeSArray)tv;
 				dim *= (cast(TypeSArray)tv).dim.toInteger();
 				tv = tv.nextOf().toBasetype();
 			}
 			if (tv.ty == TY.Tstruct)
-			{   TypeStruct ts = cast(TypeStruct)tv;
+			{   
+				TypeStruct ts = cast(TypeStruct)tv;
 				StructDeclaration sd = ts.sym;
 				if (sd.postblit)
-				{	Expression ex;
+				{	
+					Expression ex;
+					
+					stc |= sd.postblit.storage_class & STCdisable;
 
-				// this.v
-				ex = new ThisExp(Loc(0));
-				ex = new DotVarExp(Loc(0), ex, v, 0);
+					// this.v
+					ex = new ThisExp(Loc(0));
+					ex = new DotVarExp(Loc(0), ex, v, 0);
 
-				if (dim == 1)
-				{   // this.v.postblit()
-					ex = new DotVarExp(Loc(0), ex, sd.postblit, 0);
-					ex = new CallExp(Loc(0), ex);
-				}
-				else
-				{
-					// Typeinfo.postblit(cast(void*)&this.v);
-					Expression ea = new AddrExp(Loc(0), ex);
-					ea = new CastExp(Loc(0), ea, Type.tvoid.pointerTo());
+					if (dim == 1)
+					{   // this.v.postblit()
+						ex = new DotVarExp(Loc(0), ex, sd.postblit, 0);
+						ex = new CallExp(Loc(0), ex);
+					}
+					else
+					{
+						// Typeinfo.postblit(cast(void*)&this.v);
+						Expression ea = new AddrExp(Loc(0), ex);
+						ea = new CastExp(Loc(0), ea, Type.tvoid.pointerTo());
 
-					Expression et = v.type.getTypeInfo(sc);
-					et = new DotIdExp(Loc(0), et, Id._postblit);
+						Expression et = v.type.getTypeInfo(sc);
+						et = new DotIdExp(Loc(0), et, Id._postblit);
 
-					ex = new CallExp(Loc(0), et, ea);
-				}
-				e = Expression.combine(e, ex);	// combine in forward order
+						ex = new CallExp(Loc(0), et, ea);
+					}
+					e = Expression.combine(e, ex);	// combine in forward order
 				}
 			}
 		}
@@ -797,12 +809,14 @@
 		/* Build our own "postblit" which executes e
 		 */
 		if (e)
-		{	//printf("Building __fieldPostBlit()\n");
-		auto dd = new PostBlitDeclaration(Loc(0), Loc(0), Lexer.idPool("__fieldPostBlit"));
-		dd.fbody = new ExpStatement(Loc(0), e);
-		postblits.shift(dd);
-		members.push(dd);
-		dd.semantic(sc);
+		{	
+			//printf("Building __fieldPostBlit()\n");
+			auto dd = new PostBlitDeclaration(Loc(0), Loc(0), Lexer.idPool("__fieldPostBlit"));
+			dd.storage_class |= stc;
+			dd.fbody = new ExpStatement(Loc(0), e);
+			postblits.shift(dd);
+			members.push(dd);
+			dd.semantic(sc);
 		}
 
 		switch (postblits.dim)
@@ -817,12 +831,14 @@
 			e = null;
 			foreach(FuncDeclaration fd; postblits)
 			{
-			Expression ex = new ThisExp(Loc(0));
-			ex = new DotVarExp(Loc(0), ex, fd, 0);
-			ex = new CallExp(Loc(0), ex);
-			e = Expression.combine(e, ex);
+				Expression ex = new ThisExp(Loc(0));
+				stc |= fd.storage_class & STCdisable;
+				ex = new DotVarExp(Loc(0), ex, fd, 0);
+				ex = new CallExp(Loc(0), ex);
+				e = Expression.combine(e, ex);
 			}
 			auto dd = new PostBlitDeclaration(Loc(0), Loc(0), Lexer.idPool("__aggrPostBlit"));
+		    dd.storage_class |= stc;
 			dd.fbody = new ExpStatement(Loc(0), e);
 			members.push(dd);
 			dd.semantic(sc);
@@ -864,6 +880,7 @@
 			Type ftype = new TypeFunction(fparams, Type.tvoid, false, LINK.LINKd);
 
 			fcp = new FuncDeclaration(Loc(0), Loc(0), Id.cpctor, STC.STCundefined, ftype);
+			fcp.storage_class |= postblit.storage_class & STCdisable;
 
 			// Build *this = p;
 			Expression e = new ThisExp(Loc(0));
--- a/dmd/SymOffExp.d	Sun Oct 17 07:42:00 2010 +0400
+++ b/dmd/SymOffExp.d	Sun Oct 17 20:56:07 2010 +0400
@@ -2,9 +2,11 @@
 
 import dmd.common;
 import dmd.Expression;
+import dmd.GlobalExpressions;
 import dmd.Declaration;
 import dmd.MATCH;
 import dmd.Type;
+import dmd.InterState;
 import dmd.OutBuffer;
 import dmd.Loc;
 import dmd.Scope;
@@ -54,6 +56,20 @@
 			v.checkNestedReference(sc, loc);
 		return this;
 	}
+	
+    Expression interpret(InterState istate)
+	{
+version (LOG) {
+		writef("SymOffExp::interpret() %s\n", toChars());
+}
+		if (var.isFuncDeclaration() && offset == 0)
+		{
+			return this;
+		}
+		error("Cannot interpret %s at compile time", toChars());
+		return EXP_CANT_INTERPRET;
+
+	}
 
 	override void checkEscape()
 	{
--- a/dmd/SymbolExp.d	Sun Oct 17 07:42:00 2010 +0400
+++ b/dmd/SymbolExp.d	Sun Oct 17 20:56:07 2010 +0400
@@ -8,6 +8,7 @@
 import dmd.TOK;
 import dmd.TY;
 import dmd.Type;
+import dmd.Id;
 import dmd.SymOffExp;
 import dmd.FuncDeclaration;
 import dmd.VarDeclaration;
@@ -53,6 +54,12 @@
 			error("need 'this' to access member %s", toChars());
 			return el_long(TYM.TYint, 0);
 		}
+		
+	    /* The magic variable __ctfe is always false at runtime
+		 */
+		if (op == TOKvar && v && v.ident == Id.ctfe)
+			return el_long(type.totym(), 0);
+
 		s = var.toSymbol();
 		fd = null;
 		if (var.toParent2())
--- a/dmd/TemplateDeclaration.d	Sun Oct 17 07:42:00 2010 +0400
+++ b/dmd/TemplateDeclaration.d	Sun Oct 17 20:56:07 2010 +0400
@@ -183,7 +183,8 @@
 	override void semantic(Scope sc)
 	{
 	version (LOG) {
-		printf("TemplateDeclaration.semantic(this = %p, id = '%s')\n", this, ident.toChars());
+		writef("TemplateDeclaration.semantic(this = %p, id = '%s')\n", this, ident.toChars());
+	    writef("sc.stc = %llx\n", sc.stc);
 	}
 		if (semanticRun)
 			return;		// semantic() already run
@@ -703,7 +704,9 @@
 			printf("\tfarg[%d] is %s, type is %s\n", i, e.toChars(), e.type.toChars());
 		}
 		printf("fd = %s\n", fd.toChars());
-		printf("fd.type = %p\n", fd.type);
+	    printf("fd.type = %s\n", fd.type.toChars());
+		if (ethis)
+			printf("ethis.type = %s\n", ethis.type.toChars());
 	}
 
 		assert(cast(size_t)cast(void*)scope_ > 0x10000);
@@ -875,9 +878,9 @@
 
 	L2:
 	version (DMDV2) {
-		// Match 'ethis' to any TemplateThisParameter's
 		if (ethis)
 		{
+			// Match 'ethis' to any TemplateThisParameter's
 			for (size_t i = 0; i < parameters.dim; i++)
 			{   
 				auto tp2 = parameters[i];
@@ -894,6 +897,35 @@
 						match = m;		// pick worst match
 				}
 			}
+			
+			// Match attributes of ethis against attributes of fd
+			if (fd.type)
+			{
+				Type tthis = ethis.type;
+				MOD mod = fd.type.mod;
+				StorageClass stc = scope_.stc;
+				if (stc & (STCshared | STCsynchronized))
+					mod |= MODshared;
+				if (stc & STCimmutable)
+					mod |= MODimmutable;
+				if (stc & STCconst)
+					mod |= MODconst;
+				if (stc & STCwild)
+					mod |= MODwild;
+				// Fix mod
+				if (mod & MODimmutable)
+					mod = MODimmutable;
+				if (mod & MODconst)
+					mod &= ~STCwild;
+				if (tthis.mod != mod)
+				{
+					if (!MODimplicitConv(tthis.mod, mod))
+						goto Lnomatch;
+					if (MATCHconst < match)
+						match = MATCHconst;
+				}
+			}
+
 		}
 	}
 
@@ -1050,8 +1082,8 @@
 		 */
 		for (size_t i = nargsi; i < dedargs.dim; i++)
 		{
-			auto tp2 = parameters[i];
-			//printf("tp2[%d] = %s\n", i, tp2.ident.toChars());
+			auto tparam = parameters[i];
+			//printf("tparam[%d] = %s\n", i, tparam.ident.toChars());
 			/* For T:T*, the dedargs is the T*, dedtypes is the T
 			 * But for function templates, we really need them to match
 			 */
@@ -1064,30 +1096,39 @@
 			{
 				if (oded)
 				{
-					if (tp2.specialization())
+					if (tparam.specialization())
 					{   
 						/* The specialization can work as long as afterwards
 						 * the oded == oarg
 						 */
 						Declaration sparam;
 						dedargs[i] = oded;
-						MATCH m2 = tp2.matchArg(paramscope, dedargs, i, parameters, dedtypes, &sparam, 0);
+						MATCH m2 = tparam.matchArg(paramscope, dedargs, i, parameters, dedtypes, &sparam, 0);
 						//printf("m2 = %d\n", m2);
 						if (!m2)
 							goto Lnomatch;
 						if (m2 < match)
 							match = m2;		// pick worst match
 						if (dedtypes[i] !is oded)
-							error("specialization not allowed for deduced parameter %s", tp2.ident.toChars());
+							error("specialization not allowed for deduced parameter %s", tparam.ident.toChars());
 					}
 				}
 				else
 				{	
-					oded = tp2.defaultArg(loc, paramscope);
 					if (!oded)
-						goto Lnomatch;
+					{
+						if (tp &&						// if tuple parameter and
+							fptupindex < 0 &&			// tuple parameter was not in function parameter list and
+							nargsi == dedargs.dim - 1)	// we're one argument short (i.e. no tuple argument)
+						{   
+							// make tuple argument an empty tuple
+							oded = new Tuple();
+						}
+						else
+							goto Lnomatch;
+					}
 				}
-				declareParameter(paramscope, tp2, oded);
+				declareParameter(paramscope, tparam, oded);
 				dedargs[i] = oded;
 			}
 		}
@@ -1169,6 +1210,7 @@
 			printf("\t%s %s\n", arg.type.toChars(), arg.toChars());
 			//printf("\tty = %d\n", arg.type.ty);
 		}
+	    printf("stc = %llx\n", scope_.stc);
 	}
 
 		for (TemplateDeclaration td = this; td; td = td.overnext)
--- a/dmd/TraitsExp.d	Sun Oct 17 07:42:00 2010 +0400
+++ b/dmd/TraitsExp.d	Sun Oct 17 20:56:07 2010 +0400
@@ -39,37 +39,35 @@
 
 /************************************************
  * Delegate to be passed to overloadApply() that looks
- * for virtual functions.
+ * for functions matching a trait.
  */
 
-struct Pvirtuals
+struct Ptrait
 {
 	Expression e1;
-	Expressions exps;
+	Expressions exps;		// collected results
+	Identifier ident;		// which trait we're looking for
 	
 	bool visit(FuncDeclaration f)
 	{
-		Pvirtuals* p = &this;
+		if (ident == Id.getVirtualFunctions && !f.isVirtual())
+			return false;
 
-		if (f.isVirtual())
-		{	
-			Expression e;
+		Expression e;
 
-			if (p.e1.op == TOKdotvar)
-			{   
-				DotVarExp dve = cast(DotVarExp)p.e1;
-				e = new DotVarExp(Loc(0), dve.e1, f);
-			}
-			else
-				e = new DsymbolExp(Loc(0), f);
-			p.exps.push(e);
+		if (e1.op == TOKdotvar)
+		{   
+			DotVarExp dve = cast(DotVarExp)e1;
+			e = new DotVarExp(Loc(0), dve.e1, f);
 		}
+		else
+			e = new DsymbolExp(Loc(0), f);
+		exps.push(e);
+
 		return false;
 	}
 }
 
-
-
 class TraitsExp : Expression
 {
 	Identifier ident;
@@ -97,7 +95,6 @@
 		if (ident != Id.compiles && ident != Id.isSame)
 			TemplateInstance.semanticTiargs(loc, sc, args, 1);
 		size_t dim = args ? args.dim : 0;
-		Object o;
         Declaration d;
 		FuncDeclaration f;
 
@@ -180,6 +177,10 @@
 			mixin(ISDSYMBOL(q{(f = s.isFuncDeclaration()) !is null && f.isFinal()}));
 		}
 //version(DMDV2) {
+	    else if (ident == Id.isStaticFunction)
+		{
+			mixin(ISDSYMBOL(q{(f = s.isFuncDeclaration()) !is null && !f.needThis()}));
+		}
         else if (ident == Id.isRef)
         {
 	        mixin(ISDSYMBOL(q{(d = s.isDeclaration()) !is null && d.isRef()}));
@@ -192,14 +193,30 @@
         {
 	        mixin(ISDSYMBOL(q{(d = s.isDeclaration()) !is null && d.storage_class & STClazy}));
         }
+		else if (ident == Id.identifier)
+		{	
+			// Get identifier for symbol as a string literal
+			if (dim != 1)
+				goto Ldimerror;
+			auto o = args[0];
+			Dsymbol s = getDsymbol(o);
+			if (!s || !s.ident)
+			{
+				error("argument %s has no identifier", ident.toChars());	///< CHANGED o to ident!!!
+				goto Lfalse;
+			}
+			StringExp se = new StringExp(loc, s.ident.toChars());
+			return se.semantic(sc);
+		}
 //}
 		else if (ident == Id.hasMember ||
 				ident == Id.getMember ||
+			    ident == Id.getOverloads ||
 				ident == Id.getVirtualFunctions)
 		{
 			if (dim != 2)
 				goto Ldimerror;
-			auto o_ = args[0];
+			auto o = args[0];
 			Expression e = isExpression(args[1]);
 			if (!e)
 			{   error("expression expected as second argument of __traits %s", ident.toChars());
@@ -218,9 +235,9 @@
 			}
 			Identifier id = Lexer.idPool(fromStringz(cast(char*)se.string_));
 
-			Type t = isType(o_);
-			e = isExpression(o_);
-			Dsymbol s = isDsymbol(o_);
+			Type t = isType(o);
+			e = isExpression(o);
+			Dsymbol s = isDsymbol(o);
 			if (t)
 				e = typeDotIdExp(loc, t, id);
 			else if (e)
@@ -251,7 +268,7 @@
 				e = e.semantic(sc);
 				return e;
 			}
-			else if (ident == Id.getVirtualFunctions)
+			else if (ident == Id.getVirtualFunctions || ident == Id.getOverloads)
 			{
 				uint errors = global.errors;
 				Expression ex = e;
@@ -259,7 +276,7 @@
 				if (errors < global.errors)
 					error("%s cannot be resolved", ex.toChars());
 
-				/* Create tuple of virtual function overloads of e
+			    /* Create tuple of virtual function overloads of e
 				 */
 				//e.dump(0);
 				Expressions exps = new Expressions();
@@ -277,9 +294,10 @@
 				else
 					f_ = null;
 					
-				Pvirtuals p;
+			    Ptrait p;
 				p.exps = exps;
 				p.e1 = e;
+				p.ident = ident;
 				overloadApply(f_, p);
 
 				TupleExp tup = new TupleExp(loc, exps);
@@ -292,8 +310,8 @@
 		{
 			if (dim != 1)
 				goto Ldimerror;
-			Object o_ = args[0];
-			Dsymbol s = getDsymbol(o_);
+			Object o = args[0];
+			Dsymbol s = getDsymbol(o);
 			ClassDeclaration cd;
 			if (!s || (cd = s.isClassDeclaration()) is null)
 			{
@@ -306,8 +324,8 @@
 		{
 			if (dim != 1)
 				goto Ldimerror;
-			Object o_ = args[0];
-			Dsymbol s = getDsymbol(o_);
+			Object o = args[0];
+			Dsymbol s = getDsymbol(o);
 			ScopeDsymbol sd;
 			if (!s)
 			{
@@ -364,13 +382,13 @@
 				goto Lfalse;
 
 			for (size_t i = 0; i < dim; i++)
-			{   Object o_ = args[i];
+			{   Object o = args[i];
 				Expression e;
 
 				uint errors = global.errors;
 				global.gag++;
 
-				Type t = isType(o_);
+				Type t = isType(o);
 				if (t)
 				{	Dsymbol s;
 					t.resolve(loc, sc, &e, &t, &s);
@@ -441,15 +459,17 @@
 				goto Lfalse;
 		}
 		else
-		{	error("unrecognized trait %s", ident.toChars());
+		{
+			error("unrecognized trait %s", ident.toChars());
 			goto Lfalse;
 		}
 
 		return null;
 
-Lnottype:
-		error("%s is not a type", o/*.toChars()*/); // BUG: o is Object, no member toChars()
-		goto Lfalse;
+// Not used
+//Lnottype:
+//		error("%s is not a type", o.toChars());
+//		goto Lfalse;
 
 Ldimerror:
 		error("wrong number of arguments %d", dim);
--- a/dmd/TypeAArray.d	Sun Oct 17 07:42:00 2010 +0400
+++ b/dmd/TypeAArray.d	Sun Oct 17 20:56:07 2010 +0400
@@ -10,6 +10,8 @@
 import dmd.Scope;
 import dmd.StructDeclaration;
 import dmd.Loc;
+import dmd.DotTemplateInstanceExp;
+import dmd.IdentifierExp;
 import dmd.Global;
 import dmd.Dsymbol;
 import dmd.Type;
@@ -169,12 +171,18 @@
 				 * But the instantiation can fail if it is a template specialization field
 				 * which has Tident's instead of real types.
 				 */
-				TemplateInstance ti = new TemplateInstance(loc, Id.AssociativeArray);
 				Objects tiargs = new Objects();
 				tiargs.push(index);
 				tiargs.push(next);
-				ti.tiargs = tiargs;
-	
+
+			    // Create .AssociativeArray!(index, next)
+				DotTemplateInstanceExp dti = new DotTemplateInstanceExp(loc,
+					new IdentifierExp(loc, Id.empty),
+					Id.AssociativeArray,
+					tiargs);
+				dti.semantic(sc);
+				TemplateInstance ti = dti.ti;
+				
 				ti.semantic(sc);
 				ti.semantic2(sc);
 				ti.semantic3(sc);
--- a/dmd/TypeEnum.d	Sun Oct 17 07:42:00 2010 +0400
+++ b/dmd/TypeEnum.d	Sun Oct 17 20:56:07 2010 +0400
@@ -242,7 +242,17 @@
 	{
         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/UnitTestDeclaration.d	Sun Oct 17 07:42:00 2010 +0400
+++ b/dmd/UnitTestDeclaration.d	Sun Oct 17 20:56:07 2010 +0400
@@ -48,7 +48,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 = LINK.LINKd;
 			FuncDeclaration.semantic(sc2);
--- a/dmd/Util.d	Sun Oct 17 07:42:00 2010 +0400
+++ b/dmd/Util.d	Sun Oct 17 20:56:07 2010 +0400
@@ -559,6 +559,7 @@
 "  -Llinkerflag   pass linkerflag to link\n"
 "  -lib           generate library rather than object files\n"
 "  -man           open web browser on manual page\n"
+"  -map           generate linker .map file\n"
 "  -noboundscheck turns off array bounds checking for all functions\n"
 "  -nofloat       do not emit reference to floating point\n"
 "  -O             optimize\n"
@@ -758,11 +759,12 @@
     }
 
     cmdbuf.writeByte(',');
-    if (global.params.run)
+
+    if (global.params.mapfile)
+		cmdbuf.writestring(global.params.mapfile);
+    else if (global.params.run)
 		cmdbuf.writestring("nul");
 
-//    if (mapfile)
-//	cmdbuf.writestring(output);
     cmdbuf.writeByte(',');
 
     for (i = 0; i < global.params.libfiles.dim; i++)
@@ -793,9 +795,10 @@
 		writeFilename(cmdbuf, global.params.resfile);
     }
 
+    if (global.params.map || global.params.mapfile)
+		cmdbuf.writestring("/m");
+	
 static if (false) {
-    if (mapfile)
-		cmdbuf.writestring("/m");
     if (debuginfo)
 		cmdbuf.writestring("/li");
     if (codeview)
@@ -867,53 +870,81 @@
     argv.push(cast(void *)cast(char*)"-o");
     if (global.params.exefile)
     {
-	argv.push(cast(void*)toStringz(global.params.exefile));
+		argv.push(cast(void*)toStringz(global.params.exefile));
     }
     else
-    {	// Generate exe file name from first obj name
-	string n = (cast(String)global.params.objfiles.data[0]).str;
-	n = FileName.name(n);
-	string e = FileName.ext(n);
-	string ex = e ? n[0..$-(e.length+1)] : "a.out";
+    {	
+		// Generate exe file name from first obj name
+		string n = (cast(String)global.params.objfiles.data[0]).str;
+		n = FileName.name(n);
+		string e = FileName.ext(n);
+		string ex = e ? n[0..$-(e.length+1)] : "a.out";
 
-	argv.push(cast(void*)toStringz(ex));
-	global.params.exefile = ex;
+		argv.push(cast(void*)toStringz(ex));
+		global.params.exefile = ex;
     }
 
     // Make sure path to exe file exists
-    {	string p = FileName.path(global.params.exefile);
-	FileName.ensurePathExists(p);
+    {	
+		string p = FileName.path(global.params.exefile);
+		FileName.ensurePathExists(p);
     }
 
     if (global.params.symdebug)
-	argv.push(cast(void *)cast(char*)"-g");
+		argv.push(cast(void*)"-g".ptr);
 
     if (global.params.isX86_64)
-	argv.push(cast(void *)cast(char*)"-m64");
+		argv.push(cast(void*)"-m64".ptr);
     else
-	argv.push(cast(void *)cast(char*)"-m32");
+		argv.push(cast(void*)"-m32".ptr);
+	
+	if (global.params.map || global.params.mapfile)
+    {
+		argv.push(cast(void*)"-Xlinker".ptr);
+version (__APPLE__) {
+		argv.push(cast(void*)"-map".ptr);
+} else {
+		argv.push(cast(void *)"-Map".ptr);
+}
+		if (!global.params.mapfile)
+		{
+			size_t elen = global.params.exefile.length;
+			size_t extlen = global.map_ext.length;
+			size_t mlen = elen + 1 + extlen;
+			char* m = cast(char*)GC.malloc(mlen + 1);
+			memcpy(m, global.params.exefile.ptr, elen);
+			m[elen] = '.';
+			memcpy(m + elen + 1, global.map_ext.ptr, extlen);
+			m[mlen] = 0;
+			global.params.mapfile = cast(string)m[0..mlen];
+		}
+		argv.push(cast(void*)"-Xlinker".ptr);
+		argv.push(global.params.mapfile.ptr);
+    }
 
     if (0 && global.params.exefile)
     {
-	/* This switch enables what is known as 'smart linking'
-	 * in the Windows world, where unreferenced sections
-	 * are removed from the executable. It eliminates unreferenced
-	 * functions, essentially making a 'library' out of a module.
-	 * Although it is documented to work with ld version 2.13,
-	 * in practice it does not, but just seems to be ignored.
-	 * Thomas Kuehne has verified that it works with ld 2.16.1.
-	 * BUG: disabled because it causes exception handling to fail
-	 */
-	argv.push(cast(void *)cast(char*)"-Xlinker");
-	argv.push(cast(void *)cast(char*)"--gc-sections");
+		/* This switch enables what is known as 'smart linking'
+		 * in the Windows world, where unreferenced sections
+		 * are removed from the executable. It eliminates unreferenced
+		 * functions, essentially making a 'library' out of a module.
+		 * Although it is documented to work with ld version 2.13,
+		 * in practice it does not, but just seems to be ignored.
+		 * Thomas Kuehne has verified that it works with ld 2.16.1.
+		 * BUG: disabled because it causes exception handling to fail
+		 * because EH sections are "unreferenced" and elided
+		 */
+		argv.push(cast(void *)"-Xlinker".ptr);
+		argv.push(cast(void *)"--gc-sections".ptr);
     }
 
     for (i = 0; i < global.params.linkswitches.dim; i++)
-    {	char *p = cast(char *)global.params.linkswitches.data[i];
-	if (!p || !p[0] || !(p[0] == '-' && p[1] == 'l'))
-	    // Don't need -Xlinker if switch starts with -l
-	    argv.push(cast(void *)cast(char*)"-Xlinker");
-	argv.push(cast(void *) p);
+    {	
+		char* p = cast(char*)global.params.linkswitches.data[i];
+		if (!p || !p[0] || !(p[0] == '-' && p[1] == 'l'))
+			// Don't need -Xlinker if switch starts with -l
+			argv.push(cast(void *)"-Xlinker".ptr);
+		argv.push(cast(void*)p);
     }
 
     /* Add each library, prefixing it with "-l".
@@ -925,58 +956,59 @@
      *  4. standard libraries.
      */
     for (i = 0; i < global.params.libfiles.dim; i++)
-    {	char *p = cast(char *)global.params.libfiles.data[i];
-	size_t plen = strlen(p);
-	if (plen > 2 && p[plen - 2] == '.' && p[plen -1] == 'a')
-	    argv.push(cast(void *)p);
-	else
-	{
-	    char *s = cast(char *)GC.malloc(plen + 3);
-	    s[0] = '-';
-	    s[1] = 'l';
-	    memcpy(s + 2, p, plen + 1);
-	    argv.push(cast(void *)s);
-	}
+    {	
+		char* p = cast(char*)global.params.libfiles.data[i];
+		size_t plen = strlen(p);
+		if (plen > 2 && p[plen - 2] == '.' && p[plen -1] == 'a')
+			argv.push(cast(void *)p);
+		else
+		{
+			char *s = cast(char *)GC.malloc(plen + 3);
+			s[0] = '-';
+			s[1] = 'l';
+			memcpy(s + 2, p, plen + 1);
+			argv.push(cast(void *)s);
+		}
     }
 
     /* Standard libraries must go after user specified libraries
      * passed with -l.
      */
-    const char *libname = (global.params.symdebug)
+    const char* libname = (global.params.symdebug)
 				? global.params.debuglibname
 				: global.params.defaultlibname;
-    char *buf = cast(char *)GC.malloc(2 + strlen(libname) + 1);
+    char* buf = cast(char*)GC.malloc(2 + strlen(libname) + 1);
     strcpy(buf, "-l");
     strcpy(buf + 2, libname);
     argv.push(cast(void *)buf);		// turns into /usr/lib/libphobos2.a
 
 //    argv.push((void *)"-ldruntime");
-    argv.push(cast(void *)cast(char*)"-lpthread");
-    argv.push(cast(void *)cast(char*)"-lm");
+    argv.push(cast(void *)"-lpthread".ptr);
+    argv.push(cast(void *)"-lm".ptr);
 
     if (!global.params.quiet || global.params.verbose)
     {
-	// Print it
-	for (i = 0; i < argv.dim; i++)
-	    printf("%s ", cast(char *)argv.data[i]);
-	printf("\n");
-	fflush(stdout);
+		// Print it
+		for (i = 0; i < argv.dim; i++)
+			printf("%s ", cast(char *)argv.data[i]);
+		printf("\n");
+		fflush(stdout);
     }
 
     argv.push(null);
     childpid = fork();
     if (childpid == 0)
     {
-	execvp(cast(char *)argv.data[0], cast(char **)argv.data);
-	perror(cast(char *)argv.data[0]);		// failed to execute
-	return -1;
+		execvp(cast(char *)argv.data[0], cast(char **)argv.data);
+		perror(cast(char *)argv.data[0]);		// failed to execute
+		return -1;
     }
 
     waitpid(childpid, &status, 0);
 
     status=WEXITSTATUS(status);
     if (status)
-	printf("--- errorlevel %d\n", status);
+		printf("--- errorlevel %d\n", status);
     return status;
 
 } else {
--- a/dmd/VarDeclaration.d	Sun Oct 17 07:42:00 2010 +0400
+++ b/dmd/VarDeclaration.d	Sun Oct 17 20:56:07 2010 +0400
@@ -464,272 +464,320 @@
 		(!(storage_class & (STC.STCfield | STC.STCin | STC.STCforeach | STC.STCparameter)) || (storage_class & STC.STCout)) &&
 		type.size() != 0)
 		{
-		// Provide a default initializer
-		//printf("Providing default initializer for '%s'\n", toChars());
-		if (type.ty == TY.Tstruct &&
-			(cast(TypeStruct)type).sym.zeroInit)
-		{   /* If a struct is all zeros, as a special case
-			 * set it's initializer to the integer 0.
-			 * In AssignExp.toElem(), we check for this and issue
-			 * a memset() to initialize the struct.
-			 * Must do same check in interpreter.
-			 */
-			Expression e = new IntegerExp(loc, 0, Type.tint32);
-			Expression e1;
-			e1 = new VarExp(loc, this);
-			e = new AssignExp(loc, e1, e);
-			e.op = TOK.TOKconstruct;
-			e.type = e1.type;		// don't type check this, it would fail
-			init = new ExpInitializer(loc, e);
-			return;
-		}
-		else if (type.ty == TY.Ttypedef)
-		{   TypeTypedef td = cast(TypeTypedef)type;
-			if (td.sym.init)
-			{	init = td.sym.init;
-			ExpInitializer ie = init.isExpInitializer();
-			if (ie)
-				// Make copy so we can modify it
-				init = new ExpInitializer(ie.loc, ie.exp);
+			// Provide a default initializer
+			//printf("Providing default initializer for '%s'\n", toChars());
+			if (type.ty == TY.Tstruct &&
+				(cast(TypeStruct)type).sym.zeroInit)
+			{   /* If a struct is all zeros, as a special case
+				 * set it's initializer to the integer 0.
+				 * In AssignExp.toElem(), we check for this and issue
+				 * a memset() to initialize the struct.
+				 * Must do same check in interpreter.
+				 */
+				Expression e = new IntegerExp(loc, 0, Type.tint32);
+				Expression e1;
+				e1 = new VarExp(loc, this);
+				e = new AssignExp(loc, e1, e);
+				e.op = TOK.TOKconstruct;
+				e.type = e1.type;		// don't type check this, it would fail
+				init = new ExpInitializer(loc, e);
+				return;
+			}
+			else if (type.ty == TY.Ttypedef)
+			{   
+				TypeTypedef td = cast(TypeTypedef)type;
+				if (td.sym.init)
+				{	
+					init = td.sym.init;
+					ExpInitializer ie = init.isExpInitializer();
+					if (ie)
+						// Make copy so we can modify it
+						init = new ExpInitializer(ie.loc, ie.exp);
+				}
+				else
+					init = getExpInitializer();
 			}
 			else
-			init = getExpInitializer();
-		}
-		else
-		{
-			init = getExpInitializer();
-		}
-		// Default initializer is always a blit
-		op = TOK.TOKblit;
+			{
+				init = getExpInitializer();
+			}
+			// Default initializer is always a blit
+			op = TOK.TOKblit;
 		}
 
 		if (init)
 		{
-		sc = sc.push();
-		sc.stc &= ~(STC.STC_TYPECTOR | STC.STCpure | STC.STCnothrow | STC.STCref);
-
-		ArrayInitializer ai = init.isArrayInitializer();
-		if (ai && tb.ty == TY.Taarray)
-		{
-			Expression e = ai.toAssocArrayLiteral();
-			init = new ExpInitializer(e.loc, e);
-		}
-
-		StructInitializer si = init.isStructInitializer();
-		ExpInitializer ei = init.isExpInitializer();
-
-		// See if initializer is a NewExp that can be allocated on the stack
-		if (ei && isScope() && ei.exp.op == TOK.TOKnew)
-		{   NewExp ne = cast(NewExp)ei.exp;
-			if (!(ne.newargs && ne.newargs.dim))
-			{	ne.onstack = 1;
-			onstack = 1;
-			if (type.isBaseOf(ne.newtype.semantic(loc, sc), null))
-				onstack = 2;
-			}
-		}
+			sc = sc.push();
+			sc.stc &= ~(STC.STC_TYPECTOR | STC.STCpure | STC.STCnothrow | STC.STCref | STCdisable);
 
-		// If inside function, there is no semantic3() call
-		if (sc.func)
-		{
-			// If local variable, use AssignExp to handle all the various
-			// possibilities.
-			if (fd &&
-			!(storage_class & (STC.STCmanifest | STC.STCstatic | STC.STCtls | STC.STCgshared | STC.STCextern)) &&
-			!init.isVoidInitializer())
-			{
-			//printf("fd = '%s', var = '%s'\n", fd.toChars(), toChars());
-			if (!ei)
+			ArrayInitializer ai = init.isArrayInitializer();
+			if (ai && tb.ty == TY.Taarray)
 			{
-				Expression e = init.toExpression();
-				if (!e)
-				{
-				init = init.semantic(sc, type);
-				e = init.toExpression();
-				if (!e)
-				{   error("is not a static and cannot have static initializer");
-					return;
-				}
-				}
-				ei = new ExpInitializer(init.loc, e);
-				init = ei;
+				Expression e = ai.toAssocArrayLiteral();
+				init = new ExpInitializer(e.loc, e);
 			}
 
-			Expression e1 = new VarExp(loc, this);
+			StructInitializer si = init.isStructInitializer();
+			ExpInitializer ei = init.isExpInitializer();
 
-			Type t = type.toBasetype();
-			if (t.ty == TY.Tsarray && !(storage_class & (STC.STCref | STC.STCout)))
-			{
-				ei.exp = ei.exp.semantic(sc);
-				if (!ei.exp.implicitConvTo(type))
-				{
-				int dim = cast(int)(cast(TypeSArray)t).dim.toInteger();	///
-				// If multidimensional static array, treat as one large array
-				while (1)
-				{
-					t = t.nextOf().toBasetype();
-					if (t.ty != TY.Tsarray)
-						break;
-					dim *= (cast(TypeSArray)t).dim.toInteger();
-					e1.type = new TypeSArray(t.nextOf(), new IntegerExp(Loc(0), dim, Type.tindex));
+			// See if initializer is a NewExp that can be allocated on the stack
+			if (ei && isScope() && ei.exp.op == TOK.TOKnew)
+			{   NewExp ne = cast(NewExp)ei.exp;
+				if (!(ne.newargs && ne.newargs.dim))
+				{	ne.onstack = 1;
+				onstack = 1;
+				if (type.isBaseOf(ne.newtype.semantic(loc, sc), null))
+					onstack = 2;
 				}
-				}
-				e1 = new SliceExp(loc, e1, null, null);
 			}
-			else if (t.ty == TY.Tstruct)
+
+			// If inside function, there is no semantic3() call
+			if (sc.func)
 			{
-				ei.exp = ei.exp.semantic(sc);
-				ei.exp = resolveProperties(sc, ei.exp);
-				StructDeclaration sd = (cast(TypeStruct)t).sym;
-version (DMDV2)
-{
-				/* Look to see if initializer is a call to the constructor
-				 */
-				if (sd.ctor &&		// there are constructors
-				ei.exp.type.ty == TY.Tstruct &&	// rvalue is the same struct
-				(cast(TypeStruct)ei.exp.type).sym == sd &&
-				ei.exp.op == TOK.TOKstar)
+				// If local variable, use AssignExp to handle all the various
+				// possibilities.
+				if (fd &&
+				!(storage_class & (STC.STCmanifest | STC.STCstatic | STC.STCtls | STC.STCgshared | STC.STCextern)) &&
+				!init.isVoidInitializer())
 				{
-				/* Look for form of constructor call which is:
-				 *    *__ctmp.ctor(arguments...)
-				 */
-				PtrExp pe = cast(PtrExp)ei.exp;
-				if (pe.e1.op == TOK.TOKcall)
-				{   CallExp ce = cast(CallExp)pe.e1;
-					if (ce.e1.op == TOK.TOKdotvar)
-					{	DotVarExp dve = cast(DotVarExp)ce.e1;
-					if (dve.var.isCtorDeclaration())
-					{   /* It's a constructor call, currently constructing
-						 * a temporary __ctmp.
-						 */
-						/* Before calling the constructor, initialize
-						 * variable with a bit copy of the default
-						 * initializer
-						 */
-						Expression e = new AssignExp(loc, new VarExp(loc, this), t.defaultInit(loc));
-						e.op = TOK.TOKblit;
-						e.type = t;
-						ei.exp = new CommaExp(loc, e, ei.exp);
-
-						/* Replace __ctmp being constructed with e1
-						 */
-						dve.e1 = e1;
+				//printf("fd = '%s', var = '%s'\n", fd.toChars(), toChars());
+				if (!ei)
+				{
+					Expression e = init.toExpression();
+					if (!e)
+					{
+					init = init.semantic(sc, type);
+					e = init.toExpression();
+					if (!e)
+					{   error("is not a static and cannot have static initializer");
 						return;
 					}
 					}
-				}
+					ei = new ExpInitializer(init.loc, e);
+					init = ei;
 				}
-}
-				if (!ei.exp.implicitConvTo(type))
+
+				Expression e1 = new VarExp(loc, this);
+
+				Type t = type.toBasetype();
+				if (t.ty == TY.Tsarray && !(storage_class & (STC.STCref | STC.STCout)))
 				{
-					Type ti = ei.exp.type.toBasetype();
-					// Look for constructor first
-					if (sd.ctor &&
-					    /* Initializing with the same type is done differently
-					     */
-					    !(ti.ty == Tstruct && t.toDsymbol(sc) == ti.toDsymbol(sc)))
+					ei.exp = ei.exp.semantic(sc);
+					if (!ei.exp.implicitConvTo(type))
+					{
+					int dim = cast(int)(cast(TypeSArray)t).dim.toInteger();	///
+					// If multidimensional static array, treat as one large array
+					while (1)
+					{
+						t = t.nextOf().toBasetype();
+						if (t.ty != TY.Tsarray)
+							break;
+						dim *= (cast(TypeSArray)t).dim.toInteger();
+						e1.type = new TypeSArray(t.nextOf(), new IntegerExp(Loc(0), dim, Type.tindex));
+					}
+					}
+					e1 = new SliceExp(loc, e1, null, null);
+				}
+				else if (t.ty == TY.Tstruct)
+				{
+					ei.exp = ei.exp.semantic(sc);
+					ei.exp = resolveProperties(sc, ei.exp);
+					StructDeclaration sd = (cast(TypeStruct)t).sym;
+	version (DMDV2)
+	{
+					/* Look to see if initializer is a call to the constructor
+					 */
+					if (sd.ctor &&		// there are constructors
+					ei.exp.type.ty == TY.Tstruct &&	// rvalue is the same struct
+					(cast(TypeStruct)ei.exp.type).sym == sd &&
+					ei.exp.op == TOK.TOKstar)
 					{
-					   // Rewrite as e1.ctor(arguments)
-					    Expression ector = new DotIdExp(loc, e1, Id.ctor);
-					    ei.exp = new CallExp(loc, ector, ei.exp);
-					} 
-					else
-					/* Look for opCall
-					 * See bugzilla 2702 for more discussion
+					/* Look for form of constructor call which is:
+					 *    *__ctmp.ctor(arguments...)
 					 */
+					PtrExp pe = cast(PtrExp)ei.exp;
+					if (pe.e1.op == TOK.TOKcall)
+					{   CallExp ce = cast(CallExp)pe.e1;
+						if (ce.e1.op == TOK.TOKdotvar)
+						{	DotVarExp dve = cast(DotVarExp)ce.e1;
+						if (dve.var.isCtorDeclaration())
+						{   /* It's a constructor call, currently constructing
+							 * a temporary __ctmp.
+							 */
+							/* Before calling the constructor, initialize
+							 * variable with a bit copy of the default
+							 * initializer
+							 */
+							Expression e = new AssignExp(loc, new VarExp(loc, this), t.defaultInit(loc));
+							e.op = TOK.TOKblit;
+							e.type = t;
+							ei.exp = new CommaExp(loc, e, ei.exp);
 
-					// Don't cast away invariant or mutability in initializer
-					if (search_function(sd, Id.call) &&
-						/* Initializing with the same type is done differently
+							/* Replace __ctmp being constructed with e1
+							 */
+							dve.e1 = e1;
+							return;
+						}
+						}
+					}
+					}
+	}
+					if (!ei.exp.implicitConvTo(type))
+					{
+						Type ti = ei.exp.type.toBasetype();
+						// Look for constructor first
+						if (sd.ctor &&
+							/* Initializing with the same type is done differently
+							 */
+							!(ti.ty == Tstruct && t.toDsymbol(sc) == ti.toDsymbol(sc)))
+						{
+						   // Rewrite as e1.ctor(arguments)
+							Expression ector = new DotIdExp(loc, e1, Id.ctor);
+							ei.exp = new CallExp(loc, ector, ei.exp);
+						} 
+						else
+						/* Look for opCall
+						 * See bugzilla 2702 for more discussion
 						 */
-						!(ti.ty == Tstruct && t.toDsymbol(sc) == ti.toDsymbol(sc)))
-					{   // Rewrite as e1.call(arguments)
-						Expression eCall = new DotIdExp(loc, e1, Id.call);
-						ei.exp = new CallExp(loc, eCall, ei.exp);
+
+						// Don't cast away invariant or mutability in initializer
+						if (search_function(sd, Id.call) &&
+							/* Initializing with the same type is done differently
+							 */
+							!(ti.ty == Tstruct && t.toDsymbol(sc) == ti.toDsymbol(sc)))
+						{   // Rewrite as e1.call(arguments)
+							Expression eCall = new DotIdExp(loc, e1, Id.call);
+							ei.exp = new CallExp(loc, eCall, ei.exp);
+						}
 					}
 				}
+				ei.exp = new AssignExp(loc, e1, ei.exp);
+				ei.exp.op = op;
+				canassign++;
+				ei.exp = ei.exp.semantic(sc);
+				canassign--;
+				ei.exp.optimize(WANT.WANTvalue);
+				}
+				else
+				{
+				init = init.semantic(sc, type);
+				}
 			}
-			ei.exp = new AssignExp(loc, e1, ei.exp);
-			ei.exp.op = op;
-			canassign++;
-			ei.exp = ei.exp.semantic(sc);
-			canassign--;
-			ei.exp.optimize(WANT.WANTvalue);
-			}
-			else
+			else if (storage_class & (STC.STCconst | STC.STCimmutable | STC.STCmanifest) ||
+				type.isConst() || type.isImmutable() ||
+				parent.isAggregateDeclaration())
 			{
-			init = init.semantic(sc, type);
-			}
-		}
-		else if (storage_class & (STC.STCconst | STC.STCimmutable | STC.STCmanifest) ||
-			type.isConst() || type.isImmutable() ||
-			parent.isAggregateDeclaration())
-		{
-			/* Because we may need the results of a const declaration in a
-			 * subsequent type, such as an array dimension, before semantic2()
-			 * gets ordinarily run, try to run semantic2() now.
-			 * Ignore failure.
-			 */
+				/* Because we may need the results of a const declaration in a
+				 * subsequent type, such as an array dimension, before semantic2()
+				 * gets ordinarily run, try to run semantic2() now.
+				 * Ignore failure.
+				 */
+
+				if (!global.errors && !inferred)
+				{
+					uint errors = global.errors;
+					global.gag++;
+					//printf("+gag\n");
+					Expression e;
+					Initializer i2 = init;
+					inuse++;
+					if (ei)
+					{
+						e = ei.exp.syntaxCopy();
+						e = e.semantic(sc);
+						e = resolveProperties(sc, e);
+version (DMDV2) {
+					/* The problem is the following code:
+					 *	struct CopyTest {
+					 *	   double x;
+					 *	   this(double a) { x = a * 10.0;}
+					 *	   this(this) { x += 2.0; }
+					 *	}
+					 *	const CopyTest z = CopyTest(5.3);  // ok
+					 *	const CopyTest w = z;              // not ok, postblit not run
+					 *	static assert(w.x == 55.0);
+					 * because the postblit doesn't get run on the initialization of w.
+					 */
 
-			if (!global.errors && !inferred)
-			{
-			uint errors = global.errors;
-			global.gag++;
-			//printf("+gag\n");
-			Expression e;
-			Initializer i2 = init;
-			inuse++;
-			if (ei)
-			{
-				e = ei.exp.syntaxCopy();
-				e = e.semantic(sc);
-				e = e.implicitCastTo(sc, type);
-			}
-			else if (si || ai)
-			{   i2 = init.syntaxCopy();
-				i2 = i2.semantic(sc, type);
+					Type tb_ = e.type.toBasetype();
+					if (tb_.ty == Tstruct)
+					{	
+						StructDeclaration sd = (cast(TypeStruct)tb_).sym;
+						Type typeb = type.toBasetype();
+						/* Look to see if initializer involves a copy constructor
+						 * (which implies a postblit)
+						 */
+						if (sd.cpctor &&		// there is a copy constructor
+							typeb.equals(tb_))		// rvalue is the same struct
+						{
+							// The only allowable initializer is a (non-copy) constructor
+							if (e.op == TOKcall)
+							{
+							CallExp ce = cast(CallExp)e;
+							if (ce.e1.op == TOKdotvar)
+							{
+								DotVarExp dve = cast(DotVarExp)ce.e1;
+								if (dve.var.isCtorDeclaration())
+									goto LNoCopyConstruction;
+							}
+							}
+							global.gag--;
+							error("of type struct %s uses this(this), which is not allowed in static initialization", typeb.toChars());
+							global.gag++;
+
+						  LNoCopyConstruction:
+							;
+						}
+					}
+}
+						e = e.implicitCastTo(sc, type);
+					}
+					else if (si || ai)
+					{   
+						i2 = init.syntaxCopy();
+						i2 = i2.semantic(sc, type);
+					}
+					inuse--;
+					global.gag--;
+					//printf("-gag\n");
+					if (errors != global.errors)	// if errors happened
+					{
+						if (global.gag == 0)
+							global.errors = errors;	// act as if nothing happened
+version (DMDV2) {
+						/* Save scope for later use, to try again
+						 */
+						scope_ = sc.clone();
+						scope_.setNoFree();
+}
+					}
+					else if (ei)
+					{
+						if (isDataseg())
+							/* static const/invariant does CTFE
+							 */
+							e = e.optimize(WANT.WANTvalue | WANT.WANTinterpret);
+						else
+							e = e.optimize(WANT.WANTvalue);
+						if (e.op == TOK.TOKint64 || e.op == TOK.TOKstring || e.op == TOK.TOKfloat64)
+						{
+							ei.exp = e;		// no errors, keep result
+						}
+///version (DMDV2) {
+						else
+						{
+							/* Save scope for later use, to try again
+							 */
+							scope_ = sc.clone();
+							scope_.setNoFree();
+						}
+///}
+					}
+					else
+						init = i2;		// no errors, keep result
+				}
 			}
-			inuse--;
-			global.gag--;
-			//printf("-gag\n");
-			if (errors != global.errors)	// if errors happened
-			{
-				if (global.gag == 0)
-				global.errors = errors;	// act as if nothing happened
-version (DMDV2) {
-				/* Save scope for later use, to try again
-				 */
-				scope_ = sc.clone();
-				scope_.setNoFree();
-}
-			}
-			else if (ei)
-			{
-				if (isDataseg())
-					/* static const/invariant does CTFE
-					 */
-					e = e.optimize(WANT.WANTvalue | WANT.WANTinterpret);
-				else
-					e = e.optimize(WANT.WANTvalue);
-				if (e.op == TOK.TOKint64 || e.op == TOK.TOKstring || e.op == TOK.TOKfloat64)
-				{
-					ei.exp = e;		// no errors, keep result
-				}
-///version (DMDV2) {
-				else
-				{
-				/* Save scope for later use, to try again
-				 */
-				scope_ = sc.clone();
-				scope_.setNoFree();
-				}
-///}
-			}
-			else
-				init = i2;		// no errors, keep result
-			}
-		}
-		sc = sc.pop();
+			sc = sc.pop();
 		}
 	}
 
--- a/dmd/backend/glue.d	Sun Oct 17 07:42:00 2010 +0400
+++ b/dmd/backend/glue.d	Sun Oct 17 20:56:07 2010 +0400
@@ -14,6 +14,7 @@
 import dmd.Global;
 import dmd.Param;
 import dmd.backend.Config;
+import dmd.backend.elem;
 import dmd.backend.Configv;
 import dmd.backend.StringTab;
 
--- a/dmd/expression/Util.d	Sun Oct 17 07:42:00 2010 +0400
+++ b/dmd/expression/Util.d	Sun Oct 17 20:56:07 2010 +0400
@@ -1115,6 +1115,7 @@
 			 */
 			Identifier idtmp = Lexer.uniqueId("__tmp");
 			VarDeclaration tmp = new VarDeclaration(loc, tb, idtmp, new ExpInitializer(Loc(0), e));
+			tmp.storage_class |= STCctfe;
 			Expression ae = new DeclarationExp(loc, tmp);
 			e = new CommaExp(loc, ae, new VarExp(loc, tmp));
 			e = e.semantic(sc);
--- a/dmd/interpret/Util.d	Sun Oct 17 07:42:00 2010 +0400
+++ b/dmd/interpret/Util.d	Sun Oct 17 20:56:07 2010 +0400
@@ -6,10 +6,12 @@
 import dmd.FuncDeclaration;
 import dmd.InterState;
 import dmd.ArrayTypes;
+import dmd.StringExp;
 import dmd.GlobalExpressions;
 import dmd.TOK;
 import dmd.AssocArrayLiteralExp;
 import dmd.IntegerExp;
+import dmd.Id;
 import dmd.Type;
 import dmd.Declaration;
 import dmd.Loc;
@@ -24,6 +26,9 @@
 import dmd.VarDeclaration;
 import dmd.Util;
 
+import core.memory;
+import core.stdc.string;
+
 version(DMDV1)
 {
 Expression interpret_aaLen(InterState istate, Expressions arguments)
@@ -140,6 +145,11 @@
 	if (v)
 	{
 ///version (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)
@@ -149,6 +159,17 @@
 			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(Loc(0));
+		}
+
 		else
 		{
 			e = v.value;
@@ -198,7 +219,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)
 {
@@ -214,6 +235,48 @@
 	return expsx;
 }
 
+/***************************************
+ * Returns oldstr[0..insertpoint] ~ newstr ~ oldstr[insertpoint+newlen..$]
+ */
+StringExp spliceStringExp(StringExp oldstr, StringExp newstr, size_t insertpoint)
+{
+    assert(oldstr.sz==newstr.sz);
+    char* s;
+    size_t oldlen = oldstr.len;
+    size_t newlen = newstr.len;
+    size_t sz = oldstr.sz;
+    s = cast(char*)GC.calloc(oldlen + 1, sz);
+    memcpy(s, oldstr.string_, oldlen * sz);
+    memcpy(s + insertpoint * sz, newstr.string_, newlen * sz);
+    StringExp se2 = new StringExp(oldstr.loc, cast(string)s[0..oldlen]);
+    se2.committed = oldstr.committed;
+    se2.postfix = oldstr.postfix;
+    se2.type = oldstr.type;
+    return se2;
+}
+
+/******************************
+ * Create a string literal consisting of 'value' duplicated 'dim' times.
+ */
+StringExp createBlockDuplicatedStringLiteral(Type type, dchar value, size_t dim, int sz)
+{
+    char* s;
+    s = cast(char*)GC.calloc(dim + 1, sz);
+    for (int elemi = 0; elemi < dim; ++elemi)
+    {
+    	switch (sz)
+		{
+			case 1:	s[elemi] = cast(char)value; break;
+			case 2:	(cast(wchar*)s)[elemi] = cast(wchar)value; break;
+			case 4:	(cast(dchar*)s)[elemi] = value; break;
+			default:    assert(0);
+		}
+    }
+    StringExp se = new StringExp(Loc(0), cast(string)s[0..dim]);
+    se.type = type;
+    return se;
+}
+
 /******************************
  * Create an array literal consisting of 'elem' duplicated 'dim' times.
  */
--- a/main.d	Sun Oct 17 07:42:00 2010 +0400
+++ b/main.d	Sun Oct 17 20:56:07 2010 +0400
@@ -337,6 +337,8 @@
 ///            else if (arg == "fPIC")
 ///                global.params.pic = 1;
 ///}
+			else if (arg == "map")
+				global.params.map = 1;
             else if (arg == "multiobj")
                 global.params.multiobj = 1;
             else if (arg == "g")
@@ -860,7 +862,13 @@
 			if (FileName.equals(ext, global.json_ext))
 			{
 				global.params.doXGeneration = 1;
-				global.params.xfilename = (cast(immutable(char)*)files.data[i])[0..0];
+				global.params.xfilename = (cast(String)files.data[i]).str;
+				continue;
+			}
+			
+		    if (FileName.equals(ext, global.map_ext))
+			{
+				global.params.mapfile = (cast(String)files.data[i]).str;
 				continue;
 			}
 
@@ -868,13 +876,13 @@
 {
             if (FileName.equals(ext, "res"))
             {
-                global.params.resfile = (cast(immutable(char)*)files.data[i])[0..0];		/// !!!
+                global.params.resfile = (cast(String)files.data[i]).str;
                 continue;
             }
 
             if (FileName.equals(ext, "def"))
             {
-                global.params.deffile = (cast(immutable(char)*)files.data[i])[0..0];
+                global.params.deffile = (cast(String)files.data[i]).str;
                 continue;
             }
 
@@ -1053,6 +1061,9 @@
     if (global.errors)
         fatal();
 	
+    global.dprogress = 1;
+    Module.runDeferredSemantic();
+	
     // Do pass 2 semantic analysis
     for (int i = 0; i < modules.dim; i++)
     {