changeset 16:5c9b78899f5d

Implemented methods for Tuples, fixed some linking issues.
author Robert Clipsham <robert@octarineparrot.com>
date Sun, 04 Apr 2010 22:41:11 +0100
parents da741eed6c00
children ddae60498573
files commands.linux.txt dmd/AggregateDeclaration.d dmd/AliasDeclaration.d dmd/Argument.d dmd/Declaration.d dmd/ExpStatement.d dmd/Expression.d dmd/File.d dmd/FileName.d dmd/Module.d dmd/Token.d dmd/Tuple.d dmd/TupleDeclaration.d dmd/TupleExp.d dmd/Type.d dmd/TypeExp.d dmd/TypeInstance.d dmd/TypeTuple.d dmd/Util.d dmd/VarDeclaration.d dmd/backend/Config.d dmd/backend/Cstate.d dmd/backend/LIST.d dmd/backend/OPER.d dmd/backend/RTLSYM.d dmd/backend/TYM.d dmd/backend/TYPE.d dmd/backend/glue.d dmd/expression/Add.d dmd/expression/Slice.d dmd/expression/Util.d
diffstat 31 files changed, 993 insertions(+), 300 deletions(-) [+]
line wrap: on
line diff
--- a/commands.linux.txt	Sun Apr 04 02:15:33 2010 +0100
+++ b/commands.linux.txt	Sun Apr 04 22:41:11 2010 +0100
@@ -1,4 +1,4 @@
--g
+-gc
 -debug
 -version=Bug3602
 -version=Bug4054
--- a/dmd/AggregateDeclaration.d	Sun Apr 04 02:15:33 2010 +0100
+++ b/dmd/AggregateDeclaration.d	Sun Apr 04 22:41:11 2010 +0100
@@ -640,4 +640,4 @@
 	}
 
     AggregateDeclaration isAggregateDeclaration() { return this; }
-}
\ No newline at end of file
+}
--- a/dmd/AliasDeclaration.d	Sun Apr 04 02:15:33 2010 +0100
+++ b/dmd/AliasDeclaration.d	Sun Apr 04 22:41:11 2010 +0100
@@ -20,49 +20,75 @@
 
 class AliasDeclaration : Declaration
 {
-    Dsymbol aliassym;
-    Dsymbol overnext;		// next in overload list
-    int inSemantic;
+	Dsymbol aliassym;
+	Dsymbol overnext;		// next in overload list
+	int inSemantic;
 
-    this(Loc loc, Identifier ident, Type type)
+	this(Loc loc, Identifier ident, Type type)
 	{
 		super(ident);
-		
+
 		//printf("AliasDeclaration(id = '%s', type = %p)\n", id.toChars(), type);
 		//printf("type = '%s'\n", type.toChars());
 		this.loc = loc;
 		this.type = type;
 		this.aliassym = null;
-	version (_DH) {
-		this.htype = null;
-		this.haliassym = null;
-	}
+		version (_DH) {
+			this.htype = null;
+			this.haliassym = null;
+		}
 
 		assert(type);
 	}
-	
-    this(Loc loc, Identifier id, Dsymbol s)
+
+	this(Loc loc, Identifier id, Dsymbol s)
 	{
 		super(id);
-		
+
 		//printf("AliasDeclaration(id = '%s', s = %p)\n", id->toChars(), s);
 		assert(s !is this);	/// huh?
 		this.loc = loc;
 		this.type = null;
 		this.aliassym = s;
-	version (_DH) {
-		this.htype = null;
-		this.haliassym = null;
-	}
+		version (_DH) {
+			this.htype = null;
+			this.haliassym = null;
+		}
 		assert(s);
 	}
-	
-    Dsymbol syntaxCopy(Dsymbol)
+
+	Dsymbol syntaxCopy(Dsymbol s)
 	{
-		assert(false);
+		//printf("AliasDeclaration::syntaxCopy()\n");
+		assert(!s);
+		AliasDeclaration sa;
+		if (type)
+			sa = new AliasDeclaration(loc, ident, type.syntaxCopy());
+		else
+			sa = new AliasDeclaration(loc, ident, aliassym.syntaxCopy(null));
+version (_DH) {
+		// Syntax copy for header file
+		if (!htype)	    // Don't overwrite original
+		{	if (type)	// Make copy for both old and new instances
+			{   htype = type.syntaxCopy();
+				sa.htype = type.syntaxCopy();
+			}
+		}
+		else			// Make copy of original for new instance
+			sa.htype = htype.syntaxCopy();
+		if (!haliassym)
+		{	if (aliassym)
+			{   haliassym = aliassym.syntaxCopy(s);
+				sa.haliassym = aliassym.syntaxCopy(s);
+			}
+		}
+		else
+			sa.haliassym = haliassym.syntaxCopy(s);
+} // version (_DH)
+		return sa;
 	}
-	
-    void semantic(Scope sc)
+
+	void semantic(Scope sc)
 	{
 		//printf("AliasDeclaration.semantic() %s\n", toChars());
 		if (aliassym)
@@ -100,7 +126,7 @@
 		if (s && ((s.getType() && type.equals(s.getType())) || s.isEnumMember()))
 			goto L2;			// it's a symbolic alias
 
-///version (DMDV2) {
+		///version (DMDV2) {
 		if (storage_class & STC.STCref)
 		{	// For 'ref' to be attached to function types, and picked
 			// up by Type.resolve(), it has to go into sc.
@@ -110,8 +136,8 @@
 			sc = sc.pop();
 		}
 		else
-///	#endif
-		type.resolve(loc, sc, &e, &t, &s);
+			///	#endif
+			type.resolve(loc, sc, &e, &t, &s);
 		if (s)
 		{
 			goto L2;
@@ -135,7 +161,7 @@
 		this.inSemantic = 0;
 		return;
 
-	  L2:
+L2:
 		//printf("alias is a symbol %s %s\n", s.kind(), s.toChars());
 		type = null;
 		VarDeclaration v = s.isVarDeclaration();
@@ -171,8 +197,8 @@
 		aliassym = s;
 		this.inSemantic = 0;
 	}
-	
-    bool overloadInsert(Dsymbol s)
+
+	bool overloadInsert(Dsymbol s)
 	{
 		/* Don't know yet what the aliased symbol is, so assume it can
 		 * be overloaded and check later for correctness.
@@ -189,17 +215,17 @@
 			return overnext.overloadInsert(s);
 		}
 	}
-	
-    string kind()
+
+	string kind()
 	{
 		return "alias";
 	}
-	
-    Type getType()
+
+	Type getType()
 	{
 		return type;
 	}
-    
+
 	Dsymbol toAlias()
 	{
 		//printf("AliasDeclaration::toAlias('%s', this = %p, aliassym = %p, kind = '%s')\n", toChars(), this, aliassym, aliassym ? aliassym->kind() : "");
@@ -214,20 +240,20 @@
 		Dsymbol s = aliassym ? aliassym.toAlias() : this;
 		return s;
 	}
-	
-    void toCBuffer(OutBuffer buf, HdrGenState* hgs)
-	{
-		assert(false);
-	}
-	
-version (_DH) {
-    Type htype;
-    Dsymbol haliassym;
-}
-    void toDocBuffer(OutBuffer buf)
+
+	void toCBuffer(OutBuffer buf, HdrGenState* hgs)
 	{
 		assert(false);
 	}
 
-    AliasDeclaration isAliasDeclaration() { return this; }
-}
\ No newline at end of file
+	version (_DH) {
+		Type htype;
+		Dsymbol haliassym;
+	}
+	void toDocBuffer(OutBuffer buf)
+	{
+		assert(false);
+	}
+
+	AliasDeclaration isAliasDeclaration() { return this; }
+	}
--- a/dmd/Argument.d	Sun Apr 04 02:15:33 2010 +0100
+++ b/dmd/Argument.d	Sun Apr 04 22:41:11 2010 +0100
@@ -107,7 +107,7 @@
 		buf.writeByte('(');
 		if (args)
 		{	
-			OutBuffer argbuf;
+			OutBuffer argbuf = new OutBuffer();
 			HdrGenState hgs;
 
 			for (int i = 0; i < args.dim; i++)
@@ -275,4 +275,4 @@
 
 		return null;
 	}
-}
\ No newline at end of file
+}
--- a/dmd/Declaration.d	Sun Apr 04 02:15:33 2010 +0100
+++ b/dmd/Declaration.d	Sun Apr 04 22:41:11 2010 +0100
@@ -90,7 +90,6 @@
 	
     void semantic(Scope sc)
 	{
-		assert(false);
 	}
 	
     string kind()
--- a/dmd/ExpStatement.d	Sun Apr 04 02:15:33 2010 +0100
+++ b/dmd/ExpStatement.d	Sun Apr 04 22:41:11 2010 +0100
@@ -15,6 +15,7 @@
 import dmd.BE;
 import dmd.TOK;
 import dmd.DeclarationStatement;
+import dmd.Util : printf;
 
 import dmd.backend.Blockx;
 import dmd.backend.Util;
@@ -122,4 +123,4 @@
 		if (exp) 
 			block_appendexp(blx.curblock, exp.toElem(irs));
 	}
-}
\ No newline at end of file
+}
--- a/dmd/Expression.d	Sun Apr 04 02:15:33 2010 +0100
+++ b/dmd/Expression.d	Sun Apr 04 22:41:11 2010 +0100
@@ -906,4 +906,4 @@
 	{
 		assert(false);
 	}
-}
\ No newline at end of file
+}
--- a/dmd/File.d	Sun Apr 04 02:15:33 2010 +0100
+++ b/dmd/File.d	Sun Apr 04 22:41:11 2010 +0100
@@ -86,7 +86,8 @@
 		int fd = open(toStringz(name), O_RDONLY);
 		if (fd == -1) {
 			result = errno;
-			//printf("\topen error, errno = %d\n", errno);
+			printf("file: %s\n", toStringz(name));
+			printf("\topen error, errno = %d\n", errno);
 			goto err1;
 		}
 
--- a/dmd/FileName.d	Sun Apr 04 02:15:33 2010 +0100
+++ b/dmd/FileName.d	Sun Apr 04 22:41:11 2010 +0100
@@ -504,7 +504,32 @@
 		
 		return null;
 	}
-	
+
+	static string searchPath(string[] path, string name, bool cwd)
+	{
+		if (absolute(name)) {
+			return exists(name) ? name : null;
+		}
+		
+		if (cwd) {
+			if (exists(name)) {
+				return name;
+			}
+		}
+		
+		if (path !is null) {
+			foreach (i, p; path)
+			{
+				string n = combine(p, name);
+
+				if (exists(n))
+					return n;
+			}
+		}
+		
+		return null;
+	}
+
     static int exists(string name)
 	{
 version (POSIX) {
--- a/dmd/Module.d	Sun Apr 04 02:15:33 2010 +0100
+++ b/dmd/Module.d	Sun Apr 04 22:41:11 2010 +0100
@@ -456,7 +456,7 @@
 			le = 1;
 
 			Lutf32:
-			OutBuffer dbuf;
+			OutBuffer dbuf = new OutBuffer();
 			uint* pu = cast(uint*)buf;
 			uint* pumax = &pu[buflen / 4];
 
@@ -491,7 +491,7 @@
 				le = 1;
 
 				Lutf16:
-				OutBuffer dbuf;
+				OutBuffer dbuf = new OutBuffer();
 				ushort* pu = cast(ushort*)(buf);
 				ushort *pumax = &pu[buflen / 2];
 
--- a/dmd/Token.d	Sun Apr 04 02:15:33 2010 +0100
+++ b/dmd/Token.d	Sun Apr 04 22:41:11 2010 +0100
@@ -136,7 +136,7 @@
 version (CSTRINGS) {
 			p = string;
 } else {
-		{   OutBuffer buf;
+		{   OutBuffer buf = new OutBuffer();
 
 			buf.writeByte('"');
 			for (size_t i = 0; i < len; )
@@ -212,4 +212,4 @@
 
 		return p;
 	}
-}
\ No newline at end of file
+}
--- a/dmd/Tuple.d	Sun Apr 04 02:15:33 2010 +0100
+++ b/dmd/Tuple.d	Sun Apr 04 22:41:11 2010 +0100
@@ -2,13 +2,18 @@
 
 import dmd.ArrayTypes;
 
-class Tuple
-{
-	Objects objects;
-
-	int dyncast()
-	{
-		assert(false);
-	}
-}
-
+class Tuple
+{
+	Objects objects;
+
+	this()
+	{
+		objects = new Objects;
+	}
+
+	int dyncast()
+	{
+		assert(false);
+	}
+}
+
--- a/dmd/TupleDeclaration.d	Sun Apr 04 02:15:33 2010 +0100
+++ b/dmd/TupleDeclaration.d	Sun Apr 04 22:41:11 2010 +0100
@@ -1,45 +1,113 @@
 module dmd.TupleDeclaration;
 
 import dmd.Declaration;
+import dmd.Argument;
 import dmd.ArrayTypes;
 import dmd.TypeTuple;
 import dmd.Loc;
+import dmd.STC;
+import dmd.TOK;
 import dmd.Identifier;
 import dmd.Dsymbol;
 import dmd.Type;
+import dmd.DYNCAST;
+import dmd.OutBuffer;
+import dmd.Expression;
+import dmd.DsymbolExp;
 
 class TupleDeclaration : Declaration
 {
-    Objects objects;
-    int isexp;			// 1: expression tuple
+	Objects objects;
+	int isexp;			// 1: expression tuple
 
-    TypeTuple tupletype;	// !=NULL if this is a type tuple
+	TypeTuple tupletype;	// !=NULL if this is a type tuple
 
-    this(Loc loc, Identifier ident, Objects objects)
+	this(Loc loc, Identifier ident, Objects objects)
 	{
-		assert(false);
 		super(ident);
+		type = null;
+		this.objects = objects;
+		isexp = 0;
+		tupletype = null;
 	}
 
-    Dsymbol syntaxCopy(Dsymbol)
-	{
-		assert(false);
-	}
-	
-    string kind()
+	Dsymbol syntaxCopy(Dsymbol)
 	{
 		assert(false);
 	}
 
-    Type getType()
+	string kind()
 	{
-		assert(false);
+		return "tuple";
 	}
-	
-    bool needThis()
+
+	Type getType()
 	{
-		assert(false);
+		/* If this tuple represents a type, return that type
+		 */
+
+		//printf("TupleDeclaration::getType() %s\n", toChars());
+		if (isexp)
+			return null;
+		if (!tupletype)
+		{
+			/* It's only a type tuple if all the Object's are types
+			 */
+			for (size_t i = 0; i < objects.dim; i++)
+			{   Dsymbol o = cast(Dsymbol)objects.data[i];
+
+				if (o.dyncast() != DYNCAST.DYNCAST_TYPE)
+				{
+					//printf("\tnot[%d], %p, %d\n", i, o, o->dyncast());
+					return null;
+				}
+			}
+
+			/* We know it's a type tuple, so build the TypeTuple
+			 */
+			Arguments args = new Arguments();
+			args.setDim(objects.dim);
+			OutBuffer buf = new OutBuffer();
+			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) {
+					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 {
+					Argument arg = new Argument(STCundefined, t, null, null);
+				}
+				args.data[i] = cast(void *)arg;
+			}
+
+			tupletype = new TypeTuple(args);
+		}
+
+		return tupletype;
 	}
-	
-    TupleDeclaration isTupleDeclaration() { return this; }
-};
\ No newline at end of file
+
+	bool needThis()
+	{
+		//printf("TupleDeclaration::needThis(%s)\n", toChars());
+		for (size_t i = 0; i < objects.dim; i++)
+		{   Dsymbol o = cast(Dsymbol)objects.data[i];
+			if (o.dyncast() == DYNCAST.DYNCAST_EXPRESSION)
+			{   Expression e = cast(Expression)o;
+				if (e.op == TOKdsymbol)
+				{	DsymbolExp ve = cast(DsymbolExp)e;
+					Declaration d = ve.s.isDeclaration();
+					if (d && d.needThis())
+					{
+						return 1;
+					}
+				}
+			}
+		}
+		return 0;
+	}
+
+	TupleDeclaration isTupleDeclaration() { return this; }
+}
--- a/dmd/TupleExp.d	Sun Apr 04 02:15:33 2010 +0100
+++ b/dmd/TupleExp.d	Sun Apr 04 22:41:11 2010 +0100
@@ -14,97 +14,236 @@
 import dmd.HdrGenState;
 import dmd.InlineScanState;
 import dmd.ArrayTypes;
+import dmd.TypeExp;
+import dmd.TypeTuple;
 import dmd.TOK;
+import dmd.TY;
+import dmd.Dsymbol;
+import dmd.DsymbolExp;
+import dmd.DYNCAST;
+import dmd.expression.Util;
+
+/****************************************
+ * Expand tuples.
+ */
+/+
+void expandTuples(Expressions exps)
+{
+    //printf("expandTuples()\n");
+    if (exps)
+    {
+	for (size_t i = 0; i < exps.dim; i++)
+	{   Expression arg = cast(Expression)exps.data[i];
+	    if (!arg)
+		continue;
+
+	    // Look for tuple with 0 members
+	    if (arg.op == TOKtype)
+	    {	TypeExp e = cast(TypeExp)arg;
+		if (e.type.toBasetype().ty == Ttuple)
+		{   TypeTuple tt = cast(TypeTuple)e.type.toBasetype();
+
+		    if (!tt.arguments || tt.arguments.dim == 0)
+		    {
+			exps.remove(i);
+			if (i == exps.dim)
+			    return;
+			i--;
+			continue;
+		    }
+		}
+	    }
+
+	    // Inline expand all the tuples
+	    while (arg.op == TOKtuple)
+	    {	TupleExp te = cast(TupleExp)arg;
+
+		exps.remove(i);		// remove arg
+		exps.insert(i, te.exps);	// replace with tuple contents
+		if (i == exps.dim)
+		    return;		// empty tuple, no more arguments
+		arg = cast(Expression)exps.data[i];
+	    }
+	}
+    }
+}
++/
+class TupleExp : Expression
+{
+	Expressions exps;
+
+	this(Loc loc, Expressions exps)
+	{
+		super(Loc(0), TOK.init, this.sizeof);
+		this.exps = exps;
+		this.type = null;
+	}
+
+	this(Loc loc, TupleDeclaration tup)
+	{
+		super(Loc(0), TOK.init, this.sizeof);
+		exps = new Expressions();
+		type = null;
 
-class TupleExp : Expression
-{
-	Expressions exps;
-
-	this(Loc loc, Expressions exps)
-	{
-		assert(false);
-		super(Loc(0), TOK.init, 0);
-	}
-
-	this(Loc loc, TupleDeclaration tup)
-	{
+		exps.reserve(tup.objects.dim);
+		for (size_t i = 0; i < tup.objects.dim; i++)
+		{   Dsymbol o = cast(Dsymbol)tup.objects.data[i];
+			if (o.dyncast() == DYNCAST.DYNCAST_EXPRESSION)
+			{
+				Expression e = cast(Expression)o;
+				e = e.syntaxCopy();
+				exps.push(cast(void*)e);
+			}
+			else if (o.dyncast() == DYNCAST.DYNCAST_DSYMBOL)
+			{
+				Dsymbol s = cast(Dsymbol)o;
+				Expression e = new DsymbolExp(loc, s);
+				exps.push(cast(void*)e);
+			}
+			else if (o.dyncast() == DYNCAST.DYNCAST_TYPE)
+			{
+				Type t = cast(Type)o;
+				Expression e = new TypeExp(loc, t);
+				exps.push(cast(void*)e);
+			}
+			else
+			{
+				error("%s is not an expression", o.toChars());
+			}
+		}
+	}
+
+	Expression syntaxCopy()
+	{
+		return new TupleExp(loc, arraySyntaxCopy(exps));
+	}
+
+	int equals(Object o)
+	{
+		TupleExp ne;
+
+		if (this == o)
+			return 1;
+		if ((cast(Expression)o).op == TOKtuple)
+		{
+			TupleExp te = cast(TupleExp)o;
+			if (exps.dim != te.exps.dim)
+				return 0;
+			for (size_t i = 0; i < exps.dim; i++)
+			{   Expression e1 = cast(Expression)exps.data[i];
+				Expression e2 = cast(Expression)te.exps.data[i];
+
+				if (!e1.equals(e2))
+					return 0;
+			}
+			return 1;
+		}
+		return 0;
+	}
+
+	Expression semantic(Scope sc)
+	{
+		version (LOGSEMANTIC) {
+			printf("+TupleExp::semantic(%s)\n", toChars());
+		}
+		if (type)
+			return this;
+
+		// Run semantic() on each argument
+		for (size_t i = 0; i < exps.dim; i++)
+		{	Expression e = cast(Expression)exps.data[i];
+
+			e = e.semantic(sc);
+			if (!e.type)
+			{   error("%s has no value", e.toChars());
+				e.type = Type.terror;
+			}
+			exps.data[i] = cast(void *)e;
+		}
+
+		expandTuples(exps);
+		if (0 && exps.dim == 1)
+		{
+			return cast(Expression)exps.data[0];
+		}
+		type = new TypeTuple(exps);
+		type = type.semantic(loc, sc);
+		//printf("-TupleExp::semantic(%s)\n", toChars());
+		return this;
+	}
+
+	void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		buf.writestring("tuple(");
+		argsToCBuffer(buf, exps, hgs);
+		buf.writeByte(')');
+	}
+
+	void scanForNestedRef(Scope sc)
+	{
 		assert(false);
-		super(Loc(0), TOK.init, 0);
-	}
-
-	Expression syntaxCopy()
-	{
-		assert(false);
-	}
-
-	int equals(Object o)
-	{
-		assert(false);
-	}
-
-	Expression semantic(Scope sc)
-	{
-		assert(false);
-	}
-
-	void toCBuffer(OutBuffer buf, HdrGenState* hgs)
-	{
-		assert(false);
-	}
-
-	void scanForNestedRef(Scope sc)
-	{
-		assert(false);
-	}
-
-	void checkEscape()
-	{
-		assert(false);
-	}
-
-	bool checkSideEffect(int flag)
-	{
-		assert(false);
-	}
-
-	Expression optimize(int result)
-	{
-		assert(false);
-	}
-
-	Expression interpret(InterState* istate)
-	{
-		assert(false);
-	}
-
-	Expression castTo(Scope sc, Type t)
-	{
-		assert(false);
-	}
-
-	elem* toElem(IRState* irs)
-	{
-		assert(false);
-	}
-
-	bool canThrow()
-	{
-		assert(false);
-	}
-
-	int inlineCost(InlineCostState* ics)
-	{
-		assert(false);
-	}
-
-	Expression doInline(InlineDoState ids)
-	{
-		assert(false);
-	}
-
-	Expression inlineScan(InlineScanState* iss)
-	{
-		assert(false);
-	}
-}
-
+	}
+
+	void checkEscape()
+	{
+		for (size_t i = 0; i < exps.dim; i++)
+		{   Expression e = cast(Expression)exps.data[i];
+			e.checkEscape();
+		}
+	}
+
+	bool checkSideEffect(int flag)
+	{
+		bool f = false;
+
+		for (int i = 0; i < exps.dim; i++)
+		{	Expression e = cast(Expression)exps.data[i];
+
+			f |= e.checkSideEffect(2);
+		}
+		if (flag == 0 && f == 0)
+			Expression.checkSideEffect(0);
+		return f;
+	}
+
+	Expression optimize(int result)
+	{
+		assert(false);
+	}
+
+	Expression interpret(InterState* istate)
+	{
+		assert(false);
+	}
+
+	Expression castTo(Scope sc, Type t)
+	{
+		assert(false);
+	}
+
+	elem* toElem(IRState* irs)
+	{
+		assert(false);
+	}
+
+	bool canThrow()
+	{
+		return arrayExpressionCanThrow(exps);
+	}
+
+	int inlineCost(InlineCostState* ics)
+	{
+		assert(false);
+	}
+
+	Expression doInline(InlineDoState ids)
+	{
+		assert(false);
+	}
+
+	Expression inlineScan(InlineScanState* iss)
+	{
+		assert(false);
+	}
+}
+
--- a/dmd/Type.d	Sun Apr 04 02:15:33 2010 +0100
+++ b/dmd/Type.d	Sun Apr 04 22:41:11 2010 +0100
@@ -713,7 +713,7 @@
 	 *	flag	0x100	do not do const/invariant
 	 */
     void toDecoBuffer(OutBuffer buf, int flag = 0)
-	{
+	{ if( buf is null )asm { int 3; }
 		if (flag != mod && flag != 0x100)
 		{
 			if (mod & MOD.MODshared)
--- a/dmd/TypeExp.d	Sun Apr 04 02:15:33 2010 +0100
+++ b/dmd/TypeExp.d	Sun Apr 04 22:41:11 2010 +0100
@@ -46,7 +46,7 @@
 
 	void toCBuffer(OutBuffer buf, HdrGenState* hgs)
 	{
-		assert(false);
+		type.toCBuffer(buf, null, hgs);
 	}
 
 	Expression optimize(int result)
--- a/dmd/TypeInstance.d	Sun Apr 04 02:15:33 2010 +0100
+++ b/dmd/TypeInstance.d	Sun Apr 04 22:41:11 2010 +0100
@@ -1,7 +1,14 @@
 module dmd.TypeInstance;
 
 import dmd.TypeQualified;
+import dmd.TemplateAliasParameter;
+import dmd.TemplateDeclaration;
 import dmd.TemplateInstance;
+import dmd.TemplateParameter;
+import dmd.TemplateValueParameter;
+import dmd.TemplateTupleParameter;
+import dmd.Tuple;
+import dmd.VarExp;
 import dmd.MOD;
 import dmd.MATCH;
 import dmd.Loc;
@@ -13,43 +20,56 @@
 import dmd.Expression;
 import dmd.Scope;
 import dmd.ArrayTypes;
+import dmd.TOK;
 import dmd.TY;
+import dmd.Util : printf;
 
 /* Similar to TypeIdentifier, but with a TemplateInstance as the root
  */
 class TypeInstance : TypeQualified
 {
-    TemplateInstance tempinst;
+	TemplateInstance tempinst;
 
-    this(Loc loc, TemplateInstance tempinst)
+	this(Loc loc, TemplateInstance tempinst)
 	{
 		super(Tinstance, loc);
 		this.tempinst = tempinst;
 	}
-	
-version (DumbClone) {
-} else {
-	Type clone()
-	{
-		assert(false);
+
+	version (DumbClone) {
+	} else {
+		Type clone()
+		{
+			assert(false);
+		}
 	}
-}
-	
-    Type syntaxCopy()
+
+	Type syntaxCopy()
 	{
-		assert(false);
+		//printf("TypeInstance::syntaxCopy() %s, %d\n", toChars(), idents.dim);
+		TypeInstance t;
+
+		t = new TypeInstance(loc, cast(TemplateInstance)tempinst.syntaxCopy(null));
+		t.syntaxCopyHelper(this);
+		t.mod = mod;
+		return t;
 	}
-	
-    //char *toChars();
-	
-    //void toDecoBuffer(OutBuffer *buf, int flag);
-	
-    void toCBuffer2(OutBuffer buf, HdrGenState* hgs, MOD mod)
+
+	//char *toChars();
+
+	//void toDecoBuffer(OutBuffer *buf, int flag);
+
+	void toCBuffer2(OutBuffer buf, HdrGenState* hgs, MOD mod)
 	{
-		assert(false);
+		if (mod != this.mod)
+		{	toCBuffer3(buf, hgs, mod);
+			return;
+		}
+		tempinst.toCBuffer(buf, hgs);
+		toCBuffer2Helper(buf, hgs);
 	}
-	
-    void resolve(Loc loc, Scope sc, Expression* pe, Type* pt, Dsymbol* ps)
+
+	void resolve(Loc loc, Scope sc, Expression* pe, Type* pt, Dsymbol* ps)
 	{
 		// Note close similarity to TypeIdentifier::resolve()
 		Dsymbol s;
@@ -58,13 +78,13 @@
 		*pt = null;
 		*ps = null;
 
-	static if (false) {
-		if (!idents.dim)
-		{
-			error(loc, "template instance '%s' has no identifier", toChars());
-			return;
+		static if (false) {
+			if (!idents.dim)
+			{
+				error(loc, "template instance '%s' has no identifier", toChars());
+				return;
+			}
 		}
-	}
 		//id = (Identifier *)idents.data[0];
 		//printf("TypeInstance::resolve(sc = %p, idents = '%s')\n", sc, id->toChars());
 		s = tempinst;
@@ -75,13 +95,42 @@
 			*pt = (*pt).addMod(mod);
 		//printf("pt = '%s'\n", (*pt)->toChars());
 	}
-	
-    Type semantic(Loc loc, Scope sc)
+
+	Type semantic(Loc loc, Scope sc)
 	{
-		assert(false);
+		Type t;
+		Expression e;
+		Dsymbol s;
+
+		//printf("TypeInstance::semantic(%s)\n", toChars());
+
+		if (sc.parameterSpecialization)
+		{
+			uint errors = global.errors;
+			global.gag++;
+
+			resolve(loc, sc, &e, &t, &s);
+
+			global.gag--;
+			if (errors != global.errors)
+			{   if (global.gag == 0)
+				global.errors = errors;
+				return this;
+			}
+		}
+		else
+			resolve(loc, sc, &e, &t, &s);
+
+		if (!t)
+		{
+			debug printf("2: ");
+			error(loc, "%s is used as a type", toChars());
+			t = tvoid;
+		}
+		return t;
 	}
-	
-    Dsymbol toDsymbol(Scope sc)
+
+	Dsymbol toDsymbol(Scope sc)
 	{
 		Type t;
 		Expression e;
@@ -110,9 +159,225 @@
 
 		return s;
 	}
-	
-    MATCH deduceType(Scope sc, Type tparam, TemplateParameters parameters, Objects dedtypes)
+
+	MATCH deduceType(Scope sc, Type tparam, TemplateParameters parameters, Objects dedtypes)
 	{
-		assert(false);
+static if (0) {
+		printf("TypeInstance::deduceType()\n");
+		printf("\tthis   = %d, ", ty); print();
+		printf("\ttparam = %d, ", tparam.ty); tparam.print();
+}
+
+		// Extra check
+		if (tparam && tparam.ty == Tinstance)
+		{
+			TypeInstance tp = cast(TypeInstance)tparam;
+
+			//printf("tempinst->tempdecl = %p\n", tempinst->tempdecl);
+			//printf("tp->tempinst->tempdecl = %p\n", tp->tempinst->tempdecl);
+			if (!tp.tempinst.tempdecl)
+			{   //printf("tp->tempinst->name = '%s'\n", tp->tempinst->name->toChars());
+				if (!tp.tempinst.name.equals(tempinst.name))
+				{
+					/* Handle case of:
+					 *  template Foo(T : sa!(T), alias sa)
+					 */
+					int i = templateIdentifierLookup(tp.tempinst.name, parameters);
+					if (i == -1)
+					{   /* Didn't find it as a parameter identifier. Try looking
+					     * it up and seeing if is an alias. See Bugzilla 1454
+					     */
+						Dsymbol s = tempinst.tempdecl.scope_.search(Loc(0), tp.tempinst.name, null);
+						if (s)
+						{
+							s = s.toAlias();
+							TemplateDeclaration td = s.isTemplateDeclaration();
+							if (td && td == tempinst.tempdecl)
+								goto L2;
+						}
+						goto Lnomatch;
+					}
+					TemplateParameter tpx = cast(TemplateParameter)parameters.data[i];
+					// This logic duplicates tpx->matchArg()
+					TemplateAliasParameter ta = tpx.isTemplateAliasParameter();
+					if (!ta)
+						goto Lnomatch;
+					Object sa = tempinst.tempdecl;
+					if (!sa)
+						goto Lnomatch;
+					if (ta.specAlias && sa != ta.specAlias)
+						goto Lnomatch;
+					if (dedtypes.data[i])
+					{   // Must match already deduced symbol
+						Object s = cast(Object)dedtypes.data[i];
+
+						if (s != sa)
+							goto Lnomatch;
+					}
+					dedtypes.data[i] = cast(void*)sa;
+				}
+			}
+			else if (tempinst.tempdecl != tp.tempinst.tempdecl)
+				goto Lnomatch;
+
+L2:
+
+			for (int i = 0; 1; i++)
+			{
+				//printf("\ttest: tempinst->tiargs[%d]\n", i);
+				Object o1;
+				if (i < tempinst.tiargs.dim)
+					o1 = cast(Object)tempinst.tiargs.data[i];
+				else if (i < tempinst.tdtypes.dim && i < tp.tempinst.tiargs.dim)
+					// Pick up default arg
+					o1 = cast(Object)tempinst.tdtypes.data[i];
+				else
+					break;
+
+				if (i >= tp.tempinst.tiargs.dim)
+					goto Lnomatch;
+
+				Object o2 = cast(Object)tp.tempinst.tiargs.data[i];
+
+				Type t1 = isType(o1);
+				Type t2 = isType(o2);
+
+				Expression e1 = isExpression(o1);
+				Expression e2 = isExpression(o2);
+
+				Dsymbol s1 = isDsymbol(o1);
+				Dsymbol s2 = isDsymbol(o2);
+
+				Tuple v1 = isTuple(o1);
+				Tuple v2 = isTuple(o2);
+static if (0) {
+				if (t1)	printf("t1 = %s\n", t1.toChars());
+				if (t2)	printf("t2 = %s\n", t2.toChars());
+				if (e1)	printf("e1 = %s\n", e1.toChars());
+				if (e2)	printf("e2 = %s\n", e2.toChars());
+				if (s1)	printf("s1 = %s\n", s1.toChars());
+				if (s2)	printf("s2 = %s\n", s2.toChars());
+				if (v1)	printf("v1 = %s\n", v1.toChars());
+				if (v2)	printf("v2 = %s\n", v2.toChars());
+}
+
+				TemplateTupleParameter ttp;
+				int j;
+				if (t2 &&
+						t2.ty == Tident &&
+						i == tp.tempinst.tiargs.dim - 1 &&
+						i == tempinst.tempdecl.parameters.dim - 1 &&
+						(ttp = tempinst.tempdecl.isVariadic()) !is null)
+				{
+					/* Given:
+					 *  struct A(B...) {}
+					 *  alias A!(int, float) X;
+					 *  static if (!is(X Y == A!(Z), Z))
+					 * deduce that Z is a tuple(int, float)
+					 */
+
+					j = templateParameterLookup(t2, parameters);
+					if (j == -1)
+						goto Lnomatch;
+
+					/* Create tuple from remaining args
+					 */
+					Tuple vt = new Tuple();
+					int vtdim = tempinst.tiargs.dim - i;
+					vt.objects.setDim(vtdim);
+					for (size_t k = 0; k < vtdim; k++)
+						vt.objects.data[k] = cast(void *)tempinst.tiargs.data[i + k];
+
+					Tuple v = cast(Tuple)dedtypes.data[j];
+					if (v)
+					{
+						if (!match(v, vt, tempinst.tempdecl, sc))
+							goto Lnomatch;
+					}
+					else
+						dedtypes.data[j] = cast(void*)vt;
+					break; //return MATCHexact;
+				}
+
+				if (t1 && t2)
+				{
+					if (!t1.deduceType(sc, t2, parameters, dedtypes))
+						goto Lnomatch;
+				}
+				else if (e1 && e2)
+				{
+					if (!e1.equals(e2))
+					{   if (e2.op == TOKvar)
+						{
+							/*
+							 * (T:Number!(e2), int e2)
+							 */
+							j = templateIdentifierLookup((cast(VarExp)e2).var.ident, parameters);
+							goto L1;
+						}
+						goto Lnomatch;
+					}
+				}
+				else if (e1 && t2 && t2.ty == Tident)
+				{
+					j = templateParameterLookup(t2, parameters);
+L1:
+					if (j == -1)
+						goto Lnomatch;
+					TemplateParameter tp_ = cast(TemplateParameter)parameters.data[j];
+					// BUG: use tp->matchArg() instead of the following
+					TemplateValueParameter tv = tp_.isTemplateValueParameter();
+					if (!tv)
+						goto Lnomatch;
+					Expression e = cast(Expression)dedtypes.data[j];
+					if (e)
+					{
+						if (!e1.equals(e))
+							goto Lnomatch;
+					}
+					else
+					{   Type vt = tv.valType.semantic(Loc(0), sc);
+						MATCH m = cast(MATCH)e1.implicitConvTo(vt);
+						if (!m)
+							goto Lnomatch;
+						dedtypes.data[j] = cast(void*)e1;
+					}
+				}
+				else if (s1 && t2 && t2.ty == Tident)
+				{
+					j = templateParameterLookup(t2, parameters);
+					if (j == -1)
+						goto Lnomatch;
+					TemplateParameter tp_ = cast(TemplateParameter)parameters.data[j];
+					// BUG: use tp->matchArg() instead of the following
+					TemplateAliasParameter ta = tp_.isTemplateAliasParameter();
+					if (!ta)
+						goto Lnomatch;
+					Dsymbol s = cast(Dsymbol)dedtypes.data[j];
+					if (s)
+					{
+						if (!s1.equals(s))
+							goto Lnomatch;
+					}
+					else
+					{
+						dedtypes.data[j] = cast(void*)s1;
+					}
+				}
+				else if (s1 && s2)
+				{
+					if (!s1.equals(s2))
+						goto Lnomatch;
+				}
+				// BUG: Need to handle tuple parameters
+				else
+					goto Lnomatch;
+			}
+		}
+		return Type.deduceType(sc, tparam, parameters, dedtypes);
+
+Lnomatch:
+		//printf("no match\n");
+		return MATCHnomatch;
 	}
-}
\ No newline at end of file
+}
--- a/dmd/TypeTuple.d	Sun Apr 04 02:15:33 2010 +0100
+++ b/dmd/TypeTuple.d	Sun Apr 04 22:41:11 2010 +0100
@@ -11,68 +11,165 @@
 import dmd.HdrGenState;
 import dmd.Scope;
 import dmd.TY;
+import dmd.Id;
+import dmd.STC;
+import dmd.Argument;
+import dmd.ErrorExp;
+import dmd.IntegerExp;
 
 class TypeTuple : Type
 {
-    Arguments arguments;	// types making up the tuple
+	Arguments arguments;	// types making up the tuple
+
+	this(Arguments arguments)
+	{
+		super(TY.Ttuple);
+		//printf("TypeTuple(this = %p)\n", this);
+		this.arguments = arguments;
+		//printf("TypeTuple() %s\n", toChars());
+		debug {
+			if (arguments)
+			{
+				for (size_t i = 0; i < arguments.dim; i++)
+				{
+					Argument arg = cast(Argument)arguments.data[i];
+					assert(arg && arg.type);
+				}
+			}
+		}
+	}
+
+	version (DumbClone) {
+	} else {
+		Type clone()
+		{
+			assert(false);
+		}
+	}
 
-    this(Arguments arguments)
+	/****************
+	 * Form TypeTuple from the types of the expressions.
+	 * Assume exps[] is already tuple expanded.
+	 */
+	this(Expressions exps)
+	{
+		super(TY.Ttuple);
+		Arguments arguments = new Arguments;
+		if (exps)
+		{
+			arguments.setDim(exps.dim);
+			for (size_t i = 0; i < exps.dim; i++)
+			{   Expression e = cast(Expression)exps.data[i];
+				if (e.type.ty == Ttuple)
+					e.error("cannot form tuple of tuples");
+				Argument arg = new Argument(STCundefined, e.type, null, null);
+				arguments.data[i] = cast(void *)arg;
+			}
+		}
+		this.arguments = arguments;
+	}
+
+	Type syntaxCopy()
+	{
+		Arguments args = Argument.arraySyntaxCopy(arguments);
+		Type t = new TypeTuple(args);
+		t.mod = mod;
+		return t;
+	}
+
+	Type semantic(Loc loc, Scope sc)
+	{
+		//printf("TypeTuple::semantic(this = %p)\n", this);
+		//printf("TypeTuple::semantic() %s\n", toChars());
+		if (!deco)
+			deco = merge().deco;
+
+		/* Don't return merge(), because a tuple with one type has the
+		 * same deco as that type.
+		 */
+		return this;
+	}
+
+	int equals(Object o)
 	{
-		assert(false);
-		super(TY.init);
+		Type t;
+
+		t = cast(Type)o;
+		//printf("TypeTuple::equals(%s, %s)\n", toChars(), t-cast>toChars());
+		if (this == t)
+		{
+			return 1;
+		}
+		if (t.ty == Ttuple)
+		{	TypeTuple tt = cast(TypeTuple)t;
+
+			if (arguments.dim == tt.arguments.dim)
+			{
+				for (size_t i = 0; i < tt.arguments.dim; i++)
+				{   Argument arg1 = cast(Argument)arguments.data[i];
+					Argument arg2 = cast(Argument)tt.arguments.data[i];
+
+					if (!arg1.type.equals(arg2.type))
+						return 0;
+				}
+				return 1;
+			}
+		}
+		return 0;
 	}
-	
-version (DumbClone) {
-} else {
-	Type clone()
+
+	Type reliesOnTident()
+	{
+		if (arguments)
+		{
+			for (size_t i = 0; i < arguments.dim; i++)
+			{
+				Argument arg = cast(Argument)arguments.data[i];
+				Type t = arg.type.reliesOnTident();
+				if (t)
+					return t;
+			}
+		}
+		return null;
+	}
+
+	void toCBuffer2(OutBuffer buf, HdrGenState* hgs, MOD mod)
+	{
+		Argument.argsToCBuffer(buf, hgs, arguments, 0);
+	}
+
+	void toDecoBuffer(OutBuffer buf, int flag)
+	{
+		//printf("TypeTuple::toDecoBuffer() this = %p, %s\n", this, toChars());
+		Type.toDecoBuffer(buf, flag);
+		OutBuffer buf2 = new OutBuffer();
+		Argument.argsToDecoBuffer(buf2, arguments);
+		uint len = buf2.offset;
+		//buf.printf("%d%.*s", len, len, cast(char *)buf2.extractData());
+		buf.printf("%d%s", len, buf2.extractString());
+	}
+
+	Expression getProperty(Loc loc, Identifier ident)
+	{
+		Expression e;
+
+		version (LOGDOTEXP) {
+			printf("TypeTuple::getProperty(type = '%s', ident = '%s')\n", toChars(), ident.toChars());
+		}
+		if (ident == Id.length)
+		{
+			e = new IntegerExp(loc, arguments.dim, Type.tsize_t);
+		}
+		else
+		{
+			error(loc, "no property '%s' for tuple '%s'", ident.toChars(), toChars());
+			e = new ErrorExp();
+		}
+		return e;
+	}
+
+	TypeInfoDeclaration getTypeInfoDeclaration()
 	{
 		assert(false);
 	}
 }
-	
-    this(Expressions exps)
-	{
-		assert(false);
-		super(TY.init);
-	}
-	
-    Type syntaxCopy()
-	{
-		assert(false);
-	}
-	
-    Type semantic(Loc loc, Scope sc)
-	{
-		assert(false);
-	}
-	
-    int equals(Object *o)
-	{
-		assert(false);
-	}
-	
-    Type reliesOnTident()
-	{
-		assert(false);
-	}
-	
-    void toCBuffer2(OutBuffer buf, HdrGenState* hgs, MOD mod)
-	{
-		assert(false);
-	}
-	
-    void toDecoBuffer(OutBuffer buf, int flag)
-	{
-		assert(false);
-	}
-	
-    Expression getProperty(Loc loc, Identifier ident)
-	{
-		assert(false);
-	}
-	
-    TypeInfoDeclaration getTypeInfoDeclaration()
-	{
-		assert(false);
-	}
-}
\ No newline at end of file
--- a/dmd/Util.d	Sun Apr 04 02:15:33 2010 +0100
+++ b/dmd/Util.d	Sun Apr 04 22:41:11 2010 +0100
@@ -20,16 +20,36 @@
 import core.stdc.stdlib;
 import core.stdc.ctype;
 import core.stdc.stdarg;
-import core.stdc.stdio;
+public import core.stdc.stdio;
 version (Bug4054) import core.memory;
 
 extern(C) int putenv(char*);
+/+version (LOG) 
+{
+	static if( !is(typeof(printf)) )
+		extern (C) int printf(const char*,...);
+}+/
+//version = LOG;
 
-//version = LOG;
+version (TARGET_OSX)
+{
+	version = TARGET_FOS; // FreeBSD, OS X, Solaris
+}
+version (TARGET_FREEBSD)
+{
+	version = TARGET_FOS; // FreeBSD, OS X, Solaris
+}
+version (TARGET_SOLARIS)
+{
+	version = TARGET_FOS; // FreeBSD, OS X, Solaris
+}
 
 version (POSIX)
 {
+	import dmd.Array;
 	import dmd.Gnuc;
+	import core.sys.posix.stdlib;
+	version (TARGET_FOS) import core.stdc.limits;
 }
 
 enum MAX_PATH = 256; ///
@@ -140,20 +160,20 @@
 }
 				filename = FileName.replaceName(argv0, inifile);
 				if (!FileName.exists(filename)) {
-version (XXX) { /// linux || __APPLE__ || __FreeBSD__ || __sun&&__SVR4
-	version (XXX) { /// __GLIBC__ || __APPLE__ || __FreeBSD__ || __sun&&__SVR4   // This fix by Thomas Kuehne
+version (POSIX) { /// linux || __APPLE__ || __FreeBSD__ || __sun&&__SVR4
+	version (POSIX) { /// __GLIBC__ || __APPLE__ || __FreeBSD__ || __sun&&__SVR4   // This fix by Thomas Kuehne
 					/* argv0 might be a symbolic link,
 					* so try again looking past it to the real path
 					*/
-		version (XXX) {/// #if __APPLE__ || __FreeBSD__ || __sun&&__SVR4
+		version (TARGET_FOS) {/// #if __APPLE__ || __FreeBSD__ || __sun&&__SVR4
 					char resolved_name[PATH_MAX + 1];
-					char* real_argv0 = realpath(argv0, resolved_name);
+					char* real_argv0 = realpath(toStringz(argv0), resolved_name);
 		} else {
-					char* real_argv0 = realpath(argv0, null);
+					char* real_argv0 = realpath(toStringz(argv0), null);
 		}
 					//printf("argv0 = %s, real_argv0 = %p\n", argv0, real_argv0);
 					if (real_argv0) {
-						filename = FileName.replaceName(real_argv0, inifile);
+						filename = FileName.replaceName(fromStringz(real_argv0), inifile);
 		version (linux) {
 						///free(real_argv0);
 		}
@@ -166,11 +186,11 @@
 	}
 					if (true) {
 						// Search PATH for argv0
-						const(char)* p = getenv("PATH");
+						const(char)* p = toStringz(getenv("PATH"));
 	version (LOG) {
 						writef("\tPATH='%s'\n", p);
 	}
-						Array paths = FileName.splitPath(p);
+						auto paths = FileName.splitPath(fromStringz(p));
 						filename = FileName.searchPath(paths, argv0, 0);
 						if (!filename) {
 							goto Letc;		// argv0 not found on path
--- a/dmd/VarDeclaration.d	Sun Apr 04 02:15:33 2010 +0100
+++ b/dmd/VarDeclaration.d	Sun Apr 04 22:41:11 2010 +0100
@@ -245,7 +245,7 @@
 		for (size_t i = 0; i < nelems; i++)
 		{   Argument arg = Argument.getNth(tt.arguments, i);
 
-			OutBuffer buf;
+			OutBuffer buf = new OutBuffer();
 			buf.printf("_%s_field_%zu", ident.toChars(), i);
 			buf.writeByte(0);
 			string name = buf.extractString();
@@ -1185,4 +1185,4 @@
 
     // Eliminate need for dynamic_cast
     VarDeclaration isVarDeclaration() { return this; }
-}
\ No newline at end of file
+}
--- a/dmd/backend/Config.d	Sun Apr 04 02:15:33 2010 +0100
+++ b/dmd/backend/Config.d	Sun Apr 04 22:41:11 2010 +0100
@@ -8,7 +8,7 @@
 	void cod3_set386();
 }
 
-debug extern (C) /+extern+/
+debug extern (C) extern
 {
 	__gshared char debuga;		/* cg - watch assignaddr()		*/
 	__gshared char debugb;		/* watch block optimization		*/
@@ -192,7 +192,7 @@
     LINKAGE linkage;	// default function call linkage
 }
 
-extern (C) /+extern+/ __gshared Config config;
+extern (C) extern __gshared Config config;
 
 enum CVNONE = 0;		// No symbolic info
 ///enum CVOLD = 1;		// Codeview 1 symbolic info
--- a/dmd/backend/Cstate.d	Sun Apr 04 02:15:33 2010 +0100
+++ b/dmd/backend/Cstate.d	Sun Apr 04 22:41:11 2010 +0100
@@ -18,4 +18,4 @@
     char* modname;		// module unique identifier
 }
 
-extern (C++) /+extern+/ __gshared Cstate cstate;
+extern (C) extern __gshared Cstate cstate;
--- a/dmd/backend/LIST.d	Sun Apr 04 02:15:33 2010 +0100
+++ b/dmd/backend/LIST.d	Sun Apr 04 22:41:11 2010 +0100
@@ -1,1 +1,26 @@
-module dmd.backend.LIST;

import dmd.backend.Symbol;

struct LIST
{
	/* Do not access items in this struct directly, use the		*/
	/* functions designed for that purpose.				*/
	LIST* next;	/* next element in list			*/
	int count;		/* when 0, element may be deleted	*/

	union
	{
		void *ptr;	/* data pointer				*/
		int data;
	}
}

alias LIST* list_t;			/* pointer to a list entry		*/
alias list_t symlist_t;		/* pointer to a list entry		*/

extern (C++) extern {
	__gshared list_t slist;
	list_t list_prepend(list_t* plist, void* ptr);
	void slist_add(Symbol* s);
}
\ No newline at end of file
+module dmd.backend.LIST;
+
+import dmd.backend.Symbol;
+
+struct LIST
+{
+	/* Do not access items in this struct directly, use the		*/
+	/* functions designed for that purpose.				*/
+	LIST* next;	/* next element in list			*/
+	int count;		/* when 0, element may be deleted	*/
+
+	union
+	{
+		void *ptr;	/* data pointer				*/
+		int data;
+	}
+}
+
+alias LIST* list_t;			/* pointer to a list entry		*/
+alias list_t symlist_t;		/* pointer to a list entry		*/
+
+extern (C++) extern {
+	extern(C) extern __gshared list_t slist;
+	list_t list_prepend(list_t* plist, void* ptr);
+	void slist_add(Symbol* s);
+}
--- a/dmd/backend/OPER.d	Sun Apr 04 02:15:33 2010 +0100
+++ b/dmd/backend/OPER.d	Sun Apr 04 22:41:11 2010 +0100
@@ -291,10 +291,10 @@
 }
 else
 {
-	extern(C++) __gshared const ubyte[OPER.OPMAX] optab1;
-	extern(C++) __gshared const ubyte[OPER.OPMAX] optab2;
-	extern(C++) __gshared const ubyte[OPER.OPMAX] optab3;
-	extern(C++) __gshared const ubyte[OPER.OPMAX] opcost;
+	extern(C) extern __gshared const ubyte[OPER.OPMAX] optab1;
+	extern(C) extern __gshared const ubyte[OPER.OPMAX] optab2;
+	extern(C) extern __gshared const ubyte[OPER.OPMAX] optab3;
+	extern(C) extern __gshared const ubyte[OPER.OPMAX] opcost;
 }
 
 enum _OT
--- a/dmd/backend/RTLSYM.d	Sun Apr 04 02:15:33 2010 +0100
+++ b/dmd/backend/RTLSYM.d	Sun Apr 04 22:41:11 2010 +0100
@@ -99,4 +99,4 @@
 mixin(BringToCurrentScope!(RTLSYM));
 
 //extern(C++) extern __gshared Symbol* rtlsym[RTLSYM.RTLSYM_MAX];
-extern(C++) __gshared Symbol* rtlsym[RTLSYM.RTLSYM_MAX];
+extern(C) extern __gshared Symbol* rtlsym[RTLSYM.RTLSYM_MAX];
--- a/dmd/backend/TYM.d	Sun Apr 04 02:15:33 2010 +0100
+++ b/dmd/backend/TYM.d	Sun Apr 04 22:41:11 2010 +0100
@@ -76,7 +76,7 @@
 ///#endif
 }
 
-extern (C++) /+extern+/ {
+extern (C) extern {
 	__gshared int TYptrdiff, TYsize, TYsize_t;
 }
 
--- a/dmd/backend/TYPE.d	Sun Apr 04 02:15:33 2010 +0100
+++ b/dmd/backend/TYPE.d	Sun Apr 04 22:41:11 2010 +0100
@@ -97,8 +97,8 @@
 
 alias type* typep_t;
 
-extern(C++) /+extern+/ __gshared typep_t tstypes[TYM.TYMAX];
-extern(C++) /+extern+/ __gshared typep_t tsptr2types[TYM.TYMAX];
+extern(C) extern __gshared typep_t tstypes[TYM.TYMAX];
+extern(C) extern __gshared typep_t tsptr2types[TYM.TYMAX];
 
 ref type* tsbool	  () { return tstypes[TYM.TYbool]; }
 ref type* tschar    () { return tstypes[TYM.TYchar]; }
@@ -118,7 +118,7 @@
 ref type* tsdouble  () { return tstypes[TYM.TYdouble]; }
 ref type* tsreal64  () { return tstypes[TYM.TYdouble_alias]; }
 ref type* tsldouble () { return tstypes[TYM.TYldouble]; }
-ref type* tsvoid	() { return tstypes[TYM.TYvoid]; }
+ref type* tsvoid    () { return tstypes[TYM.TYvoid]; }
 ref type* tsifloat   () { return tstypes[TYM.TYifloat]; }
 ref type* tsidouble  () { return tstypes[TYM.TYidouble]; }
 ref type* tsildouble () { return tstypes[TYM.TYildouble]; }
--- a/dmd/backend/glue.d	Sun Apr 04 02:15:33 2010 +0100
+++ b/dmd/backend/glue.d	Sun Apr 04 22:41:11 2010 +0100
@@ -22,7 +22,7 @@
 
 extern (C++) /+extern+/
 {
-	__gshared Outbuffer objbuf;
+	extern(C) extern __gshared Outbuffer objbuf;
 	int go_flag(char* cp);
 	void util_set64();
 	void util_set386();
--- a/dmd/expression/Add.d	Sun Apr 04 02:15:33 2010 +0100
+++ b/dmd/expression/Add.d	Sun Apr 04 22:41:11 2010 +0100
@@ -9,6 +9,7 @@
 import dmd.TOK;
 import dmd.SymOffExp;
 import dmd.Complex;
+import dmd.Util : printf;
 
 Expression Add(Type type, Expression e1, Expression e2)
 {   
@@ -102,4 +103,4 @@
 		e = new IntegerExp(loc, e1.toInteger() + e2.toInteger(), type);
 
     return e;
-}
\ No newline at end of file
+}
--- a/dmd/expression/Slice.d	Sun Apr 04 02:15:33 2010 +0100
+++ b/dmd/expression/Slice.d	Sun Apr 04 22:41:11 2010 +0100
@@ -8,6 +8,7 @@
 import dmd.GlobalExpressions;
 import dmd.ArrayLiteralExp;
 import dmd.ArrayTypes;
+import dmd.Util : printf;
 
 import core.memory;
 
@@ -16,6 +17,7 @@
 
 import std.contracts;
 
+
 /* Also return EXP_CANT_INTERPRET if this fails
  */
 Expression Slice(Type type, Expression e1, Expression lwr, Expression upr)
@@ -78,4 +80,4 @@
 		}
     }
     return e;
-}
\ No newline at end of file
+}
--- a/dmd/expression/Util.d	Sun Apr 04 02:15:33 2010 +0100
+++ b/dmd/expression/Util.d	Sun Apr 04 22:41:11 2010 +0100
@@ -772,6 +772,25 @@
     }
 }
 
+/******************************
+ * Perform canThrow() on an array of Expressions.
+ */
+
+version (DMDV2) {
+bool arrayExpressionCanThrow(Expressions exps)
+{
+    if (exps)
+    {
+	for (size_t i = 0; i < exps.dim; i++)
+	{   Expression e = cast(Expression)exps.data[i];
+	    if (e && e.canThrow())
+		return true;
+	}
+    }
+    return false;
+}
+}
+
 /****************************************
  * Expand tuples.
  */
@@ -1360,4 +1379,4 @@
 			}
 		}
     }
-}
\ No newline at end of file
+}