changeset 98:5c859d5fbe27

and more
author Trass3r
date Tue, 31 Aug 2010 03:53:49 +0200
parents acd69f84627e
children 903b95002d4e
files dmd/AliasDeclaration.d dmd/BinExp.d dmd/DtorDeclaration.d dmd/FuncDeclaration.d dmd/Import.d dmd/PostBlitDeclaration.d dmd/StaticCtorDeclaration.d dmd/StaticDtorDeclaration.d dmd/StringExp.d dmd/TupleDeclaration.d dmd/Type.d dmd/UnitTestDeclaration.d dmd/VarDeclaration.d dmd/expression/Util.d
diffstat 14 files changed, 354 insertions(+), 236 deletions(-) [+]
line wrap: on
line diff
--- a/dmd/AliasDeclaration.d	Tue Aug 31 02:12:15 2010 +0200
+++ b/dmd/AliasDeclaration.d	Tue Aug 31 03:53:49 2010 +0200
@@ -126,17 +126,17 @@
 		if (s && ((s.getType() && type.equals(s.getType())) || s.isEnumMember()))
 			goto L2;			// it's a symbolic alias
 
-		///version (DMDV2) {
-		if (storage_class & STC.STCref)
+///version (DMDV2) {
+		if (storage_class & (STC.STCref | STCnothrow | STCpure))
 		{	// 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 |= STC.STCref;
+			sc.stc |= storage_class & (STCref | STCnothrow | STCpure);
 			type.resolve(loc, sc, &e, &t, &s);
 			sc = sc.pop();
 		}
 		else
-			///	#endif
+///	#endif
 			type.resolve(loc, sc, &e, &t, &s);
 		if (s)
 		{
--- a/dmd/BinExp.d	Tue Aug 31 02:12:15 2010 +0200
+++ b/dmd/BinExp.d	Tue Aug 31 03:53:49 2010 +0200
@@ -328,13 +328,13 @@
     {
 		assert(0);
     }
-    else if (e1.op == TOK.TOKslice && t1.ty == TY.Tarray &&
+    else if (e1.isArrayOperand() && t1.ty == TY.Tarray &&
 	     e2.implicitConvTo(t1.nextOf()))
     {	// T[] op T
 		e2 = e2.castTo(sc, t1.nextOf());
 		t = t1.nextOf().arrayOf();
     }
-    else if (e2.op == TOK.TOKslice && t2.ty == TY.Tarray &&
+    else if (e2.isArrayOperand() && t2.ty == TY.Tarray &&
 	     e1.implicitConvTo(t2.nextOf()))
     {	// T op T[]
 		e1 = e1.castTo(sc, t2.nextOf());
--- a/dmd/DtorDeclaration.d	Tue Aug 31 02:12:15 2010 +0200
+++ b/dmd/DtorDeclaration.d	Tue Aug 31 03:53:49 2010 +0200
@@ -17,23 +17,24 @@
 
 class DtorDeclaration : FuncDeclaration
 {
-    this(Loc loc, Loc endloc)
+	this(Loc loc, Loc endloc)
 	{
 		super(loc, endloc, Id.dtor, STCundefined, null);
 	}
 
-    this(Loc loc, Loc endloc, Identifier id)
+	this(Loc loc, Loc endloc, Identifier id)
 	{
-		assert(false);
-		super(loc, endloc, null, STC.init, null);
+		super(loc, endloc, id, STCundefined, null);
 	}
 
-    override Dsymbol syntaxCopy(Dsymbol)
+	override Dsymbol syntaxCopy(Dsymbol s)
 	{
-		assert(false);
+		assert(!s);
+		DtorDeclaration dd = new DtorDeclaration(loc, endloc, ident);
+		return super.syntaxCopy(dd);
 	}
 	
-    override void semantic(Scope sc)
+	override void semantic(Scope sc)
 	{
 		//printf("DtorDeclaration::semantic() %s\n", toChars());
 		//printf("ident: %s, %s, %p, %p\n", ident.toChars(), Id::dtor.toChars(), ident, Id::dtor);
@@ -53,31 +54,33 @@
 		sc.stc &= ~STCstatic;		// not a static destructor
 		sc.linkage = LINK.LINKd;
 
-		FuncDeclaration.semantic(sc);
+		super.semantic(sc);
 
 		sc.pop();
 	}
 	
-    override void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	override void toCBuffer(OutBuffer buf, HdrGenState* hgs)
 	{
-		assert(false);
+		buf.writestring("~this()");
+		bodyToCBuffer(buf, hgs);
 	}
-    
+	
 	override void toJsonBuffer(OutBuffer buf)
 	{
+		// intentionally empty
 	}
 	
-    override string kind()
+	override string kind()
 	{
-		assert(false);
+		return "destructor";
 	}
 	
-    override string toChars()
+	override string toChars()
 	{
 		return "~this";
 	}
 	
-    override bool isVirtual()
+	override bool isVirtual()
 	{
 		/* This should be FALSE so that dtor's don't get put into the vtbl[],
 		 * but doing so will require recompiling everything.
@@ -85,29 +88,29 @@
 	version (BREAKABI) {
 		return false;
 	} else {
-		return FuncDeclaration.isVirtual();
+		return super.isVirtual();
 	}
 	}
 	
-    override bool addPreInvariant()
+	override bool addPreInvariant()
 	{
 		return (isThis() && vthis && global.params.useInvariants);
 	}
 	
-    override bool addPostInvariant()
+	override bool addPostInvariant()
 	{
 		return false;
 	}
 	
-    override bool overloadInsert(Dsymbol s)
+	override bool overloadInsert(Dsymbol s)
 	{
-		assert(false);
+		return false;	   // cannot overload destructors
 	}
 	
-    override void emitComment(Scope sc)
+	override void emitComment(Scope sc)
 	{
-		assert(false);
+		// intentionally empty
 	}
 
-    override DtorDeclaration isDtorDeclaration() { return this; }
+	override DtorDeclaration isDtorDeclaration() { return this; }
 }
--- a/dmd/FuncDeclaration.d	Tue Aug 31 02:12:15 2010 +0200
+++ b/dmd/FuncDeclaration.d	Tue Aug 31 03:53:49 2010 +0200
@@ -1473,6 +1473,7 @@
 				e = new AssignExp(Loc(0), e1, e);
 				e.type = t;
 				a.push(cast(void*)new ExpStatement(Loc(0), e));
+				p.isargptr = true;
 }
 			}
 
@@ -2962,7 +2963,7 @@
 		foreach(FuncDeclaration fdv; foverrides) //(int i = 0; i < foverrides.dim; i++)
 		{
 			sf = fdv.mergeFrequire(sf);
-			if (fdv.frequire)
+			if (fdv.fdrequire)
 			{
 				//printf("fdv.frequire: %s\n", fdv.frequire.toChars());
 				/* Make the call:
@@ -3006,7 +3007,7 @@
 		foreach (FuncDeclaration fdv; foverrides)
 		{
 			sf = fdv.mergeFensure(sf);
-			if (fdv.fensure)
+			if (fdv.fdensure)
 			{
 				//printf("fdv.fensure: %s\n", fdv.fensure.toChars());
 				// Make the call: __ensure(result)
@@ -3214,7 +3215,8 @@
 		int has_arguments;
 
 		//printf("FuncDeclaration.toObjFile(%p, %s.%s)\n", func, parent.toChars(), func.toChars());
-static if (false) {
+static if (false)
+{
 		//printf("line = %d\n",func.getWhere() / LINEINC);
 		EEcontext ee = env.getEEcontext();
 		if (ee.EEcompile == 2)
@@ -3252,7 +3254,8 @@
 		s = func.toSymbol();
 		f = s.Sfunc;
 		
-version (TARGET_WINDOS) {
+version (TARGET_WINDOS)
+{
     /* This is done so that the 'this' pointer on the stack is the same
      * distance away from the function parameters, so that an overriding
      * function can call the nested fdensure or fdrequire of its overridden function
@@ -3407,11 +3410,12 @@
 			for ( ; i < parameters.dim; ++i)
 			{   
 				auto v = cast(VarDeclaration)parameters[i];
-debug {
+
 				if (v.csym)
-					writef("parameter '%s'\n", v.toChars());
-}
-				assert(!v.csym);
+				{
+					error("compiler error, parameter '%s', bugzilla 2962?", v.toChars());
+					assert(false);
+				}
 				params[pi + i] = v.toSymbol();
 			}
 			pi += i;
--- a/dmd/Import.d	Tue Aug 31 02:12:15 2010 +0200
+++ b/dmd/Import.d	Tue Aug 31 03:53:49 2010 +0200
@@ -198,7 +198,10 @@
 			mod.semantic();
 
 			if (mod.needmoduleinfo)
+			{
+				// writef("module4 %s because of %s\n", sc.module.toChars(), mod.toChars());
 				sc.module_.needmoduleinfo = 1;
+			}
 
 			sc = sc.push(mod);
 			for (size_t i = 0; i < aliasdecls.dim; i++)
@@ -291,7 +294,10 @@
 		//printf("Import::semantic2('%s')\n", toChars());
 		mod.semantic2();
 		if (mod.needmoduleinfo)
+		{
+			// writef("module5 %s because of %s\n", sc.module.toChars(), mod.toChars());
 			sc.module_.needmoduleinfo = 1;
+		}
 	}
 	
 	override Dsymbol toAlias()
--- a/dmd/PostBlitDeclaration.d	Tue Aug 31 02:12:15 2010 +0200
+++ b/dmd/PostBlitDeclaration.d	Tue Aug 31 03:53:49 2010 +0200
@@ -1,72 +1,103 @@
 module dmd.PostBlitDeclaration;
 
 import dmd.FuncDeclaration;
+import dmd.Global;
+import dmd.LINK;
+import dmd.LinkDeclaration;
 import dmd.Loc;
 import dmd.Identifier;
 import dmd.Dsymbol;
 import dmd.Scope;
+import dmd.StructDeclaration;
 import dmd.OutBuffer;
 import dmd.HdrGenState;
 import dmd.STC;
+import dmd.Type;
+import dmd.TypeFunction;
 import dmd.Id;
 
+version(DMDV2)
 class PostBlitDeclaration : FuncDeclaration
 {
-    this(Loc loc, Loc endloc)
+	this(Loc loc, Loc endloc)
 	{
 		super(loc, endloc, Id._postblit, STCundefined, null);
 	}
 	
-    this(Loc loc, Loc endloc, Identifier id)
+	this(Loc loc, Loc endloc, Identifier id)
 	{
-		assert(false);
-		super(loc, loc, null, STC.init, null);
+		super(loc, loc, id, STCundefined, null);
 	}
 	
-    override Dsymbol syntaxCopy(Dsymbol)
+	override Dsymbol syntaxCopy(Dsymbol s)
 	{
-		assert(false);
+		assert(!s);
+		PostBlitDeclaration dd = new PostBlitDeclaration(loc, endloc, ident);
+		return super.syntaxCopy(dd);
 	}
 	
-    override void semantic(Scope sc)
+	override void semantic(Scope sc)
 	{
-		assert(false);
+		//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);
+		parent = sc.parent;
+		Dsymbol parent = toParent();
+		StructDeclaration ad = parent.isStructDeclaration();
+		if (!ad)
+		{
+			error("post blits are only for struct/union definitions, not %s %s", parent.kind(), parent.toChars());
+		}
+		else if (ident == Id._postblit && semanticRun < PASSsemantic)
+			ad.postblits.push(this);
+
+		if (!type)
+			type = new TypeFunction(null, Type.tvoid, false, LINKd);
+
+		sc = sc.push();
+		sc.stc &= ~STCstatic;			  // not static
+		sc.linkage = LINKd;
+
+		FuncDeclaration.semantic(sc);
+
+		sc.pop();
 	}
 	
-    override void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	override void toCBuffer(OutBuffer buf, HdrGenState* hgs)
 	{
-		assert(false);
+		buf.writestring("this(this)");
+		bodyToCBuffer(buf, hgs);
 	}
 	
-    version(DMDV2)
 	override void toJsonBuffer(OutBuffer buf)
 	{
+		// intentionally empty
 	}
 
-    override bool isVirtual()
+	override bool isVirtual()
 	{
-		assert(false);
+		return false;
 	}
 	
-    override bool addPreInvariant()
+	override bool addPreInvariant()
 	{
-		assert(false);
+		return false;
 	}
 	
-    override bool addPostInvariant()
+	override bool addPostInvariant()
 	{
-		assert(false);
+		return (isThis() && vthis && global.params.useInvariants);
 	}
 	
-    override bool overloadInsert(Dsymbol s)
+	override bool overloadInsert(Dsymbol s)
 	{
-		assert(false);
+		return false;	   // cannot overload postblits
 	}
 	
-    override void emitComment(Scope sc)
+	override void emitComment(Scope sc)
 	{
-		assert(false);
+		// intentionally empty
 	}
 
-    override PostBlitDeclaration isPostBlitDeclaration() { return this; }
-}
+	override PostBlitDeclaration isPostBlitDeclaration() { return this; }
+}
\ No newline at end of file
--- a/dmd/StaticCtorDeclaration.d	Tue Aug 31 02:12:15 2010 +0200
+++ b/dmd/StaticCtorDeclaration.d	Tue Aug 31 03:53:49 2010 +0200
@@ -30,17 +30,19 @@
 
 class StaticCtorDeclaration : FuncDeclaration
 {
-    this(Loc loc, Loc endloc)
+	this(Loc loc, Loc endloc)
 	{
 		super(loc, endloc, Identifier.generateId("_staticCtor"), STCstatic, null);
 	}
 	
-    override Dsymbol syntaxCopy(Dsymbol)
+	override Dsymbol syntaxCopy(Dsymbol s)
 	{
-		assert(false);
+		assert(!s);
+		StaticCtorDeclaration scd = new StaticCtorDeclaration(loc, endloc);
+		return FuncDeclaration.syntaxCopy(scd);
 	}
 	
-    override void semantic(Scope sc)
+	override void semantic(Scope sc)
 	{
 		//printf("StaticCtorDeclaration.semantic()\n");
 
@@ -84,45 +86,51 @@
 		if (m)
 		{	
 			m.needmoduleinfo = 1;
+			// writef("module1 %s needs moduleinfo\n", m.toChars());
 	version (IN_GCC) {
 			m.strictlyneedmoduleinfo = 1;
 	}
 		}
 	}
 	
-    override AggregateDeclaration isThis()
+	override AggregateDeclaration isThis()
 	{
 		return null;
 	}
 	
-    override bool isStaticConstructor()
+	override bool isStaticConstructor()
 	{
 		return true;
 	}
 	
-    override bool isVirtual()
+	override bool isVirtual()
 	{
 		return false;
 	}
 	
-    override bool addPreInvariant()
+	override bool addPreInvariant()
+	{
+		return false;
+	}
+	
+	override bool addPostInvariant()
 	{
 		return false;
 	}
 	
-    override bool addPostInvariant()
+	override void emitComment(Scope sc)
 	{
-		return false;
 	}
 	
-    override void emitComment(Scope sc)
+	override void toCBuffer(OutBuffer buf, HdrGenState* hgs)
 	{
-		assert(false);
-	}
-	
-    override void toCBuffer(OutBuffer buf, HdrGenState* hgs)
-	{
-		assert(false);
+		if (hgs.hdrgen)
+		{
+			buf.writestring("static this();\n");
+			return;
+		}
+		buf.writestring("static this()");
+		bodyToCBuffer(buf, hgs);
 	}
 
 	override void toJsonBuffer(OutBuffer buf)
--- a/dmd/StaticDtorDeclaration.d	Tue Aug 31 02:12:15 2010 +0200
+++ b/dmd/StaticDtorDeclaration.d	Tue Aug 31 03:53:49 2010 +0200
@@ -33,17 +33,19 @@
 {
 	VarDeclaration vgate;	// 'gate' variable
 
-    this(Loc loc, Loc endloc)
+	this(Loc loc, Loc endloc)
 	{
 		super(loc, endloc, Identifier.generateId("_staticDtor"), STCstatic, null);
 	}
 	
-    override Dsymbol syntaxCopy(Dsymbol)
+	override Dsymbol syntaxCopy(Dsymbol)
 	{
-		assert(false);
+		assert(!s);
+		StaticDtorDeclaration sdd = new StaticDtorDeclaration(loc, endloc);
+		return FuncDeclaration.syntaxCopy(sdd);
 	}
 	
-    override void semantic(Scope sc)
+	override void semantic(Scope sc)
 	{
 		ClassDeclaration cd;
 		Type tret;
@@ -93,50 +95,53 @@
 		if (m)
 		{	
 			m.needmoduleinfo = 1;
+			// writef("module2 %s needs moduleinfo\n", m.toChars());
 	version (IN_GCC) {
 			m.strictlyneedmoduleinfo = 1;
 	}
 		}
 	}
 	
-    override AggregateDeclaration isThis()
+	override AggregateDeclaration isThis()
 	{
 		return null;
 	}
 	
-    override bool isStaticDestructor()
+	override bool isStaticDestructor()
 	{
 		return true;
 	}
 	
-    override bool isVirtual()
+	override bool isVirtual()
 	{
 		return false;
 	}
 	
-    override bool addPreInvariant()
+	override bool addPreInvariant()
+	{
+		return false;
+	}
+	
+	override bool addPostInvariant()
 	{
 		return false;
 	}
 	
-    override bool addPostInvariant()
+	override void emitComment(Scope sc)
 	{
-		return false;
 	}
 	
-    override void emitComment(Scope sc)
+	override void toCBuffer(OutBuffer buf, HdrGenState* hgs)
 	{
-		assert(false);
-	}
-	
-    override void toCBuffer(OutBuffer buf, HdrGenState* hgs)
-	{
-		assert(false);
+		if (hgs.hdrgen)
+			return;
+		buf.writestring("static ~this()");
+		bodyToCBuffer(buf, hgs);
 	}
 
 	override void toJsonBuffer(OutBuffer buf)
 	{
 	}
 
-    override StaticDtorDeclaration isStaticDtorDeclaration() { return this; }
+	override StaticDtorDeclaration isStaticDtorDeclaration() { return this; }
 }
--- a/dmd/StringExp.d	Tue Aug 31 02:12:15 2010 +0200
+++ b/dmd/StringExp.d	Tue Aug 31 03:53:49 2010 +0200
@@ -344,8 +344,6 @@
 		 * will result in a copy.
 		 * The this.string member is considered immutable.
 		 */
-		StringExp se;
-		Type tb;
 		int copied = 0;
 
 		//printf("StringExp.castTo(t = %s), '%s' committed = %d\n", t.toChars(), toChars(), committed);
@@ -355,7 +353,7 @@
 			error("cannot convert string literal to void*");
 		}
 
-		se = this;
+		StringExp se = this;
 		if (!committed)
 		{   
 			se = cast(StringExp)copy();
@@ -368,7 +366,7 @@
 			return se;
 		}
 
-		tb = t.toBasetype();
+		Type tb = t.toBasetype();
 		//printf("\ttype = %s\n", type.toChars());
 		if (tb.ty == TY.Tdelegate && type.toBasetype().ty != TY.Tdelegate)
 			return Expression.castTo(sc, t);
--- a/dmd/TupleDeclaration.d	Tue Aug 31 02:12:15 2010 +0200
+++ b/dmd/TupleDeclaration.d	Tue Aug 31 03:53:49 2010 +0200
@@ -69,22 +69,28 @@
 			Arguments args = new Arguments();
 			args.setDim(objects.dim);
 			OutBuffer buf = new OutBuffer();
+			bool hasdeco = 1;
 			for (size_t i = 0; i < objects.dim; i++)
 			{   Type t = cast(Type)objects.data[i];
 
 				//printf("type = %s\n", t->toChars());
-				static if (0) {
+static if (false)
+{
 					buf.printf("_%s_%d", ident.toChars(), i);
 					char *name = cast(char *)buf.extractData();
 					Identifier id = new Identifier(name, TOKidentifier);
 					Argument arg = new Argument(STCin, t, id, null);
-				} else {
+} else {
 					Argument arg = new Argument(STCundefined, t, null, null);
-				}
+}
 				args.data[i] = cast(void *)arg;
+				if (!t.deco)
+					hasdeco = false;
 			}
 
 			tupletype = new TypeTuple(args);
+			if (hasdeco)
+				return tupletype.semantic(0, null);
 		}
 
 		return tupletype;
--- a/dmd/Type.d	Tue Aug 31 02:12:15 2010 +0200
+++ b/dmd/Type.d	Tue Aug 31 03:53:49 2010 +0200
@@ -397,6 +397,7 @@
     DYNCAST dyncast() { return DYNCAST.DYNCAST_TYPE; } // kludge for template.isType()
 
 	/*******************************
+	 * Covariant means that 'this' can substitute for 't'.
 	 * Returns:
 	 *	0	types are distinct
 	 *	1	this is covariant with t
@@ -446,6 +447,7 @@
 				{
 ///static if (false) {
 ///				// turn on this for contravariant argument types, see bugzilla 3075
+///				// BUG: cannot convert ref to const to ref to immutable
 ///				// We can add const, but not subtract it
 ///				if (arg2.type.implicitConvTo(arg1.type) < MATCH.MATCHconst)
 ///}
@@ -649,6 +651,7 @@
 		basic[TY.Terror] = basic[TY.Tint32];
 
 		tvoidptr = tvoid.pointerTo();
+		tstring = tchar.invariantOf().arrayOf();
 
 		if (global.params.isX86_64) {
 			PTRSIZE = 8;
@@ -946,21 +949,6 @@
 	 */
 	Type constOf()
 	{
-static if (false) {
-		//printf("Type.constOf() %p %s\n", this, toChars());
-		if (isConst())
-			return this;
-		if (cto)
-			return cto;
-		Type t = makeConst();
-		t = t.merge();
-		cto = t;
-		if (ito)
-			ito.cto = t;
-		//if (t.nextOf()) assert(t.nextOf().isConst());
-		//printf("-Type.constOf() %p %s\n", t, toChars());
-		return t;
-} else {
 		//printf("Type.constOf() %p %s\n", this, toChars());
 		if (mod == MOD.MODconst)
 			return this;
@@ -974,7 +962,6 @@
 		t.fixTo(this);
 		//printf("-Type.constOf() %p %s\n", t, toChars());
 		return t;
-}
 	}
 
 	/********************************
@@ -982,32 +969,6 @@
 	 */
     Type invariantOf()
 	{	
-static if (false) {
-		//printf("Type.invariantOf() %p %s\n", this, toChars());
-		if (isInvariant())
-		{
-			return this;
-		}
-		if (ito)
-		{
-			//if (!ito.isInvariant()) printf("\tito is %p %s\n", ito, ito.toChars());
-			assert(ito.isInvariant());
-			return ito;
-		}
-		Type t = makeInvariant();
-		t = t.merge();
-		ito = t;
-		if (cto)
-			cto.ito = t;
-static if (false) {// fails for function types
-		if (t.nextOf() && !t.nextOf().isInvariant())
-		{
-			assert(0);
-		}
-}
-		//printf("\t%p\n", t);
-		return t;
-} else {
 		//printf("Type.invariantOf() %p %s\n", this, toChars());
 		if (isInvariant())
 		{
@@ -1023,60 +984,10 @@
 		t.fixTo(this);
 		//printf("\t%p\n", t);
 		return t;
-}
 	}
 
     Type mutableOf()
 	{
-	static if (false) {
-		//printf("Type.mutableOf() %p, %s\n", this, toChars());
-		Type t = this;
-		if (isConst())
-		{	
-			t = cto;
-			assert(!t || t.isMutable());
-		}
-		else if (isInvariant())
-		{	
-			t = ito;
-			assert(!t || t.isMutable());
-		}
-		if (!t)
-		{
-			uint sz = this.classinfo.init.length;
-			t = cast(Type)GC.malloc(sz);
-			memcpy(cast(void*)t, cast(void*)this, sz);
-			t.mod = 0;
-			t.deco = null;
-			t.arrayof = null;
-			t.pto = null;
-			t.rto = null;
-			t.cto = null;
-			t.ito = null;
-			t.sto = null;
-			t.scto = null;
-			t.vtinfo = null;
-			if (ty == Tsarray)
-			{   
-				TypeSArray ta = cast(TypeSArray)t;
-				//ta.next = ta.next.mutableOf();
-			}
-			t = t.merge();
-			if (isConst())
-			{   cto = t;
-				t.cto = this;
-				if (ito)
-					ito.cto = this;
-			}
-			else if (isInvariant())
-			{   ito = t;
-				t.ito = this;
-				if (cto)
-					cto.ito = this;
-			}
-		}
-		return t;
-	} else {
 		//printf("Type.mutableOf() %p, %s\n", this, toChars());
 		Type t = this;
 		if (isConst())
@@ -1097,7 +1008,7 @@
 			uint sz = this.classinfo.init.length;
 			t = cast(Type)GC.malloc(sz);
 			memcpy(cast(void*)t, cast(void*)this, sz);
-			t.mod = MODundefined;
+			t.mod = mod & MODshared;
 			t.deco = null;
 			t.arrayof = null;
 			t.pto = null;
@@ -1121,10 +1032,6 @@
 					t.ito = this;
 					break;
 
-				case MODshared:
-					t.sto = this;
-					break;
-
 				case MODshared | MODconst:
 					t.scto = this;
 					break;
@@ -1135,7 +1042,6 @@
 		}
 		return t;
 	}
-	}
 
     Type sharedOf()
 	{
@@ -1178,7 +1084,61 @@
 
 		return t;
 	}
+
+	/********************************
+	 * Make type unshared.
+	 */
+	Type unSharedOf()
+	{
+		//writef("Type::unSharedOf() %p, %s\n", this, toChars());
+		Type t = this;
+
+		if (isShared())
+		{
+			if (isConst())
+				t = cto;	// shared const => const
+			else
+				t = sto;
+			assert(!t || !t.isShared());
+		}
+
+		if (!t)
+		{
+			uint sz = this.classinfo.init.length;
+			t = cast(Type)GC.malloc(sz);
+			memcpy(cast(void*)t, cast(void*)this, sz);
+			t.mod = mod & ~MODshared;
+			t.deco = null;
+			t.arrayof = null;
+			t.pto = null;
+			t.rto = null;
+			t.cto = null;
+			t.ito = null;
+			t.sto = null;
+			t.scto = null;
+			t.vtinfo = null;
+			t = t.merge();
 	
+			t.fixTo(this);
+	
+			switch (mod)
+			{
+				case MODshared:
+				t.sto = this;
+				break;
+	
+				case MODshared | MODconst:
+				t.scto = this;
+				break;
+	
+				default:
+				assert(0);
+			}
+		}
+		assert(!t.isShared());
+		return t;
+	}
+
 	static uint X(MOD m, MOD n)
 	{
 		return (((m) << 3) | (n));
@@ -1906,7 +1866,8 @@
 	 */
     MATCH deduceType(Scope sc, Type tparam, TemplateParameters parameters, Objects dedtypes)
 	{
-	static if (false) {
+	static if (false)
+	{
 		printf("Type.deduceType()\n");
 		printf("\tthis   = %d, ", ty); print();
 		printf("\ttparam = %d, ", tparam.ty); tparam.print();
@@ -1951,42 +1912,94 @@
 			Type tt = this;
 			Type at = cast(Type)dedtypes.data[i];
 
-			// 3*3 == 9 cases
-			if (tparam.isMutable())
-			{   // foo(U:U) T            => T
-				// foo(U:U) const(T)     => const(T)
-				// foo(U:U) invariant(T) => invariant(T)
+			// 5*5 == 25 cases
+			static pure int X(int U, int T) { return ((U << 3) | T); }
+			
+			switch (X(tparam.mod, mod))
+			{
+				case X(0, 0):
+				case X(0, MODconst):
+				case X(0, MODinvariant):
+				case X(0, MODshared):
+				case X(0, MODconst | MODshared):
+				// foo(U:U) T  							=> T
+				// foo(U:U) const(T)					=> const(T)
+				// foo(U:U) immutable(T)				=> immutable(T)
+				// foo(U:U) shared(T)					=> shared(T)
+				// foo(U:U) const(shared(T))			=> const(shared(T))
 				if (!at)
-				{   
-					dedtypes.data[i] = cast(void*)this;
+				{   dedtypes.data[i] = cast(void *)tt;
 					goto Lexact;
 				}
-			}
-			else if (mod == tparam.mod)
-			{   // foo(U:const(U))     const(T)     => T
-				// foo(U:invariant(U)) invariant(T) => T
+				break;
+
+				case X(MODconst, MODconst):
+				case X(MODinvariant, MODinvariant):
+				case X(MODshared, MODshared):
+				case X(MODconst | MODshared, MODconst | MODshared):
+				// foo(U:const(U))			const(T)		=> T
+				// foo(U:immutable(U))		immutable(T)	=> T
+				// foo(U:shared(U))			shared(T)		=> T
+				// foo(U:const(shared(U))	const(shared(T))=> T
+				tt = mutableOf().unSharedOf();
+				if (!at)
+				{   dedtypes.data[i] = cast(void *)tt;
+					goto Lexact;
+				}
+				break;
+
+				case X(MODconst, 0):
+				case X(MODconst, MODimmutable):
+				case X(MODconst, MODconst | MODshared):
+				case X(MODconst | MODshared, MODimmutable):
+				// foo(U:const(U))			T					=> T
+				// foo(U:const(U))			immutable(T)		=> T
+				// foo(U:const(U))			const(shared(T))	=> shared(T)
+				// foo(U:const(shared(U))	immutable(T)		=> T
 				tt = mutableOf();
 				if (!at)
-				{   
-					dedtypes.data[i] = cast(void*)tt;
-					goto Lexact;
+				{   dedtypes.data[i] = cast(void *)tt;
+					goto Lconst;
 				}
-			}
-			else if (tparam.isConst())
-			{   // foo(U:const(U)) T            => T
-				// foo(U:const(U)) invariant(T) => T
-				tt = mutableOf();
+				break;
+
+				case X(MODshared, MODconst | MODshared):
+				case X(MODconst | MODshared, MODshared):
+				// foo(U:shared(U))			const(shared(T))	=> const(T)
+				// foo(U:const(shared(U))	shared(T)			=> T
+				tt = unSharedOf();
 				if (!at)
-				{   
-					dedtypes.data[i] = cast(void*)tt;
+				{   dedtypes.data[i] = cast(void *)tt;
 					goto Lconst;
 				}
-			}
-			else
-			{   // foo(U:invariant(U)) T        => nomatch
-				// foo(U:invariant(U)) const(T) => nomatch
-				if (!at)
+				break;
+
+				case X(MODimmutable,		 0):
+				case X(MODimmutable,		 MODconst):
+				case X(MODimmutable,		 MODshared):
+				case X(MODimmutable,		 MODconst | MODshared):
+				case X(MODconst,			 MODshared):
+				case X(MODshared,			0):
+				case X(MODshared,			MODconst):
+				case X(MODshared,			MODimmutable):
+				case X(MODconst | MODshared, 0):
+				case X(MODconst | MODshared, MODconst):
+				// foo(U:immutable(U)) T				   => nomatch
+				// foo(U:immutable(U)) const(T)			=> nomatch
+				// foo(U:immutable(U)) shared(T)		   => nomatch
+				// foo(U:immutable(U)) const(shared(T))	=> nomatch
+				// foo(U:const(U)) shared(T)			   => nomatch
+				// foo(U:shared(U)) T					  => nomatch
+				// foo(U:shared(U)) const(T)			   => nomatch
+				// foo(U:shared(U)) immutable(T)		   => nomatch
+				// foo(U:const(shared(U)) T				=> nomatch
+				// foo(U:const(shared(U)) const(T)		 => nomatch
+				//if (!at)
 					goto Lnomatch;
+				break;
+
+				default:
+				assert(0);
 			}
 
 			if (tt.equals(at))
@@ -2272,7 +2285,10 @@
 		case TY.Tpointer:	t = TYM.TYnptr;	break;
 		case TY.Tdelegate:	t = TYM.TYdelegate;	break;
 		case TY.Tarray:	t = TYM.TYdarray;	break;
-		case TY.Tsarray:	t = TYM.TYarray;	break;
+version(SARRAYVALUE)
+{		case TY.Tsarray:	t = TYstruct;	break;}
+else
+{		case TY.Tsarray:	t = TYM.TYarray;	break;}
 		case TY.Tstruct:	t = TYM.TYstruct;	break;
 
 		case TY.Tenum:
@@ -2485,7 +2501,8 @@
 	}
 	
     static Type tvoidptr;		// void*
-    
+    static Type tstring;		// immutable(char)[]
+
 	static Type terror()
 	{
 		return basic[TY.Terror];	// for error recovery
--- a/dmd/UnitTestDeclaration.d	Tue Aug 31 02:12:15 2010 +0200
+++ b/dmd/UnitTestDeclaration.d	Tue Aug 31 03:53:49 2010 +0200
@@ -53,14 +53,21 @@
 			sc2.pop();
 		}
 
+static if (false)
+{
 		// We're going to need ModuleInfo even if the unit tests are not
 		// compiled in, because other modules may import this module and refer
 		// to this ModuleInfo.
+		// (This doesn't make sense to me?)
 		Module m = getModule();
 		if (!m)
 			m = sc.module_;
 		if (m)
+		{
+			// writef("module3 %s needs moduleinfo\n", m.toChars());
 			m.needmoduleinfo = 1;
+		}
+}
 	}
 
     override AggregateDeclaration isThis()
--- a/dmd/VarDeclaration.d	Tue Aug 31 02:12:15 2010 +0200
+++ b/dmd/VarDeclaration.d	Tue Aug 31 03:53:49 2010 +0200
@@ -74,7 +74,8 @@
     uint offset;
     bool noauto;			// no auto semantics
 version (DMDV2) {
-    FuncDeclarations nestedrefs; // referenced by these lexically nested functions
+	FuncDeclarations nestedrefs; // referenced by these lexically nested functions
+	bool isargptr = false;		// if parameter that _argptr points to
 } else {
     int nestedref;		// referenced by a lexically nested function
 }
@@ -95,7 +96,8 @@
 	{
 		super(id);
 		
-debug {
+debug
+{
 		if (!type && !init)
 		{
 			writef("VarDeclaration('%s')\n", id.toChars());
@@ -105,8 +107,24 @@
 		assert(type || init);
 		this.type = type;
 		this.init = init;
+version(_DH)
+{
+		this.htype = null;
+		this.hinit = null;
+}
 		this.loc = loc;
 		
+		/* TODO:
+		#if DMDV1
+    	nestedref = 0;
+		#endif
+		ctorinit = 0;
+		aliassym = NULL;
+		onstack = 0;
+		canassign = 0;
+		value = NULL;
+		rundtor = NULL;
+		 */
 		nestedrefs = new FuncDeclarations();
 	}
 
@@ -521,10 +539,12 @@
 			else if (t.ty == TY.Tstruct)
 			{
 				ei.exp = ei.exp.semantic(sc);
-version (DMDV2) {
+				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
 				 */
-				StructDeclaration sd = (cast(TypeStruct)t).sym;
 				if (sd.ctor &&		// there are constructors
 				ei.exp.type.ty == TY.Tstruct &&	// rvalue is the same struct
 				(cast(TypeStruct)ei.exp.type).sym == sd &&
@@ -562,10 +582,22 @@
 }
 				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
 					 */
-					Type ti = ei.exp.type.toBasetype();
+
 					// Don't cast away invariant or mutability in initializer
 					if (search_function(sd, Id.call) &&
 						/* Initializing with the same type is done differently
@@ -590,7 +622,8 @@
 			}
 		}
 		else if (storage_class & (STC.STCconst | STC.STCimmutable | STC.STCmanifest) ||
-			 type.isConst() || type.isInvariant())
+			type.isConst() || type.isInvariant() ||
+			parent.isAggregateDeclaration())
 		{
 			/* Because we may need the results of a const declaration in a
 			 * subsequent type, such as an array dimension, before semantic2()
--- a/dmd/expression/Util.d	Tue Aug 31 02:12:15 2010 +0200
+++ b/dmd/expression/Util.d	Tue Aug 31 03:53:49 2010 +0200
@@ -196,7 +196,7 @@
 			m.anyf = f;
 			TypeFunction tf = cast(TypeFunction)f.type;
 			match = tf.callMatch(f.needThis() ? ethis : null, arguments);
-			//printf("match = %d\n", match);
+			//printf("test: match = %d\n", match);
 			if (match != MATCH.MATCHnomatch)
 			{
 				if (match > m.last)