changeset 17:ddae60498573

Implemented mixin statements, DefaultInitExps, FileInitExps, LineInitExps and __traits.
author Robert Clipsham <robert@octarineparrot.com>
date Mon, 05 Apr 2010 03:24:08 +0100
parents 5c9b78899f5d
children f2413c9183d1
files dmd/ClassDeclaration.d dmd/CompileStatement.d dmd/DefaultInitExp.d dmd/Dsymbol.d dmd/FileInitExp.d dmd/FuncDeclaration.d dmd/LineInitExp.d dmd/TraitsExp.d dmd/expression/Util.d
diffstat 9 files changed, 593 insertions(+), 114 deletions(-) [+]
line wrap: on
line diff
--- a/dmd/ClassDeclaration.d	Sun Apr 04 22:41:11 2010 +0100
+++ b/dmd/ClassDeclaration.d	Mon Apr 05 03:24:08 2010 +0100
@@ -71,7 +71,7 @@
 
 struct Param
 {
-	int isf(FuncDeclaration fd2)
+	int isf(void*, FuncDeclaration fd2)
 	{
 		//printf("param = %p, fd = %p %s\n", param, fd, fd.toChars());
 		return fd is fd2;
@@ -908,7 +908,7 @@
 			{   
 				Dsymbol s2 = cast(Dsymbol)os.a.data[i];
 				FuncDeclaration f2 = s2.isFuncDeclaration();
-				if (f2 && overloadApply(f2, &p.isf))
+				if (f2 && overloadApply(f2, &p.isf, &p))
 					return false;
 			}
 			return true;
@@ -917,7 +917,7 @@
 		{
 			FuncDeclaration fdstart = s.isFuncDeclaration();
 			//printf("%s fdstart = %p\n", s.kind(), fdstart);
-			return !overloadApply(fdstart, &p.isf);
+			return !overloadApply(fdstart, &p.isf, &p);
 		}
 	}
 }
@@ -1882,4 +1882,4 @@
 
     ///ClassDeclaration isClassDeclaration() { return cast(ClassDeclaration)this; }	/// huh?
     ClassDeclaration isClassDeclaration() { return this; }
-}
\ No newline at end of file
+}
--- a/dmd/CompileStatement.d	Sun Apr 04 22:41:11 2010 +0100
+++ b/dmd/CompileStatement.d	Mon Apr 05 03:24:08 2010 +0100
@@ -7,34 +7,71 @@
 import dmd.OutBuffer;
 import dmd.HdrGenState;
 import dmd.ArrayTypes;
+import dmd.TOK;
+import dmd.WANT;
+import dmd.ParseStatementFlags;
+import dmd.Parser;
+import dmd.CompoundStatement;
+import dmd.StringExp;
 
 class CompileStatement : Statement
 {
-    Expression exp;
+	Expression exp;
 
-    this(Loc loc, Expression exp)
+	this(Loc loc, Expression exp)
 	{
-		assert(false);
 		super(loc);
+		this.exp = exp;
 	}
 
-    Statement syntaxCopy()
+	Statement syntaxCopy()
 	{
-		assert(false);
+		Expression e = exp.syntaxCopy();
+		CompileStatement es = new CompileStatement(loc, e);
+		return es;
+	}
+
+	void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		buf.writestring("mixin(");
+		exp.toCBuffer(buf, hgs);
+		buf.writestring(");");
+		if (!hgs.FLinit.init)
+			buf.writenl();
 	}
 
-    void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	Statements flatten(Scope sc)
 	{
-		assert(false);
+		//printf("CompileStatement::flatten() %s\n", exp->toChars());
+		exp = exp.semantic(sc);
+		exp = resolveProperties(sc, exp);
+		exp = exp.optimize(WANT.WANTvalue | WANT.WANTinterpret);
+		if (exp.op != TOK.TOKstring)
+		{	error("argument to mixin must be a string, not (%s)", exp.toChars());
+			return null;
+		}
+		StringExp se = cast(StringExp)exp;
+		se = se.toUTF8(sc);
+		Parser p = new Parser(sc.module_, cast(ubyte *)se.string_, se.len, 0);
+		p.loc = loc;
+		p.nextToken();
+
+		Statements a = new Statements();
+		while (p.token.value != TOK.TOKeof)
+		{
+			Statement s = p.parseStatement(ParseStatementFlags.PSsemi | ParseStatementFlags.PScurlyscope);
+			a.push(cast(void*)s);
+		}
+		return a;
 	}
 
-    Statements flatten(Scope sc)
+	Statement semantic(Scope sc)
 	{
-		assert(false);
+		//printf("CompileStatement::semantic() %s\n", exp->toChars());
+		Statements a = flatten(sc);
+		if (!a)
+			return null;
+		Statement s = new CompoundStatement(loc, a);
+		return s.semantic(sc);
 	}
-
-    Statement semantic(Scope sc)
-	{
-		assert(false);
-	}
-}
\ No newline at end of file
+}
--- a/dmd/DefaultInitExp.d	Sun Apr 04 22:41:11 2010 +0100
+++ b/dmd/DefaultInitExp.d	Mon Apr 05 03:24:08 2010 +0100
@@ -6,25 +6,23 @@
 import dmd.Scope;
 import dmd.HdrGenState;
 import dmd.TOK;
+import dmd.Token;
 
-class DefaultInitExp : Expression
-{
-	TOK subop;
-
-	this(Loc loc, TOK subop, int size)
-	{
-		assert(false);
-		super(loc, subop, size);
-	}
-
-	Expression resolve(Loc loc, Scope sc)
-	{
-		assert(false);
-	}
-
-	void toCBuffer(OutBuffer buf, HdrGenState* hgs)
-	{
-		assert(false);
-	}
-}
-
+class DefaultInitExp : Expression
+{
+	TOK subop;
+
+	this(Loc loc, TOK subop, int size)
+	{
+		super(loc, subop, size);
+		this.subop = subop;
+	}
+
+	abstract Expression resolve(Loc loc, Scope sc);
+
+	void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		buf.writestring(Token.toChars(subop));
+	}
+}
+
--- a/dmd/Dsymbol.d	Sun Apr 04 22:41:11 2010 +0100
+++ b/dmd/Dsymbol.d	Mon Apr 05 03:24:08 2010 +0100
@@ -90,6 +90,22 @@
     return cast(Type)o;
 }
 
+/***********************
+ * Try to get arg as a type.
+ */
+
+Type getType(Object o)
+{
+    Type t = isType(o);
+    if (!t)
+    {   Expression e = isExpression(o);
+	if (e)
+	    t = e.type;
+    }
+    return t;
+}
+
+
 Dsymbol getDsymbol(Object oarg)
 {
 	Dsymbol sa;
--- a/dmd/FileInitExp.d	Sun Apr 04 22:41:11 2010 +0100
+++ b/dmd/FileInitExp.d	Mon Apr 05 03:24:08 2010 +0100
@@ -4,24 +4,32 @@
 import dmd.Loc;
 import dmd.Scope;
 import dmd.DefaultInitExp;
+import dmd.StringExp;
 import dmd.TOK;
+import dmd.Util;
+import dmd.Type;
+
+class FileInitExp : DefaultInitExp
+{
+	this(Loc loc)
+	{
+		super(loc, TOK.TOKfile, this.sizeof);
+	}
 
-class FileInitExp : DefaultInitExp
-{
-	this(Loc loc)
-	{
-		assert(false);
-		super(loc, TOK.init, 0);
-	}
-
-	Expression semantic(Scope sc)
-	{
-		assert(false);
-	}
-
-	Expression resolve(Loc loc, Scope sc)
-	{
-		assert(false);
-	}
-}
-
+	Expression semantic(Scope sc)
+	{
+		type = Type.tchar.invariantOf().arrayOf();
+		return this;
+	}
+
+	Expression resolve(Loc loc, Scope sc)
+	{
+		//printf("FileInitExp::resolve() %s\n", toChars());
+		string s = loc.filename ? loc.filename : sc.module_.ident.toChars();
+		Expression e = new StringExp(loc, s);
+		e = e.semantic(sc);
+		e = e.castTo(sc, type);
+		return e;
+	}
+}
+
--- a/dmd/FuncDeclaration.d	Sun Apr 04 22:41:11 2010 +0100
+++ b/dmd/FuncDeclaration.d	Mon Apr 05 03:24:08 2010 +0100
@@ -1659,7 +1659,7 @@
 		Param1 p;
 		p.t = t;
 		p.f = null;
-		overloadApply(this, &p.fp1);
+		overloadApply(this, &p.fp1, &p);
 		return p.f;
 	}
 	
--- a/dmd/LineInitExp.d	Sun Apr 04 22:41:11 2010 +0100
+++ b/dmd/LineInitExp.d	Mon Apr 05 03:24:08 2010 +0100
@@ -4,23 +4,27 @@
 import dmd.Loc;
 import dmd.Scope;
 import dmd.DefaultInitExp;
+import dmd.IntegerExp;
 import dmd.TOK;
+import dmd.Type;
+
+class LineInitExp : DefaultInitExp
+{
+	this(Loc loc)
+	{
+		super(loc, TOK.TOKline, this.sizeof);
+	}
 
-class LineInitExp : DefaultInitExp
-{
-	this(Loc loc)
-	{
-		assert(false);
-		super(loc, TOK.init, 0);
-	}
-
-	Expression semantic(Scope sc)
-	{
-		assert(false);
-	}
-
-	Expression resolve(Loc loc, Scope sc)
-	{
-		assert(false);
-	}
-}
\ No newline at end of file
+	Expression semantic(Scope sc)
+	{
+		type = Type.tint32;
+		return this;
+	}
+
+	Expression resolve(Loc loc, Scope sc)
+	{
+		Expression e = new IntegerExp(loc, loc.linnum, Type.tint32);
+		e = e.castTo(sc, type);
+		return e;
+	}
+}
--- a/dmd/TraitsExp.d	Sun Apr 04 22:41:11 2010 +0100
+++ b/dmd/TraitsExp.d	Mon Apr 05 03:24:08 2010 +0100
@@ -8,32 +8,448 @@
 import dmd.Scope;
 import dmd.HdrGenState;
 import dmd.TOK;
+import dmd.TY;
+import dmd.STC;
+import dmd.WANT;
+import dmd.Id;
+import dmd.Global;
+import dmd.Lexer;
+import dmd.ArrayLiteralExp;
+import dmd.VarExp;
+import dmd.StringExp;
+import dmd.DotIdExp;
+import dmd.DotVarExp;
+import dmd.IntegerExp;
+import dmd.TupleExp;
+import dmd.Type;
+import dmd.Dsymbol;
+import dmd.DsymbolExp;
+import dmd.ScopeDsymbol;
+import dmd.FuncDeclaration;
+import dmd.ClassDeclaration;
+import dmd.TemplateDeclaration;
+import dmd.TemplateInstance;
+import dmd.TypeClass;
+import dmd.Util;
+import dmd.expression.Util;
 
-class TraitsExp : Expression
-{
-	Identifier ident;
-
-	Objects args;
-
-	this(Loc loc, Identifier ident, Objects args)
-	{
-		assert(false);
-		super(loc, TOK.init, 0);
-	}
-
-	Expression syntaxCopy()
-	{
-		assert(false);
-	}
-
-	Expression semantic(Scope sc)
-	{
-		assert(false);
-	}
-
-	void toCBuffer(OutBuffer buf, HdrGenState* hgs)
-	{
-		assert(false);
-	}
-}
-
+import core.stdc.string : strcmp;
+
+/************************************************
+ * Delegate to be passed to overloadApply() that looks
+ * for virtual functions.
+ */
+
+struct Pvirtuals
+{
+	Expression e1;
+	Expressions exps;
+	int fpvirtuals(void* param, FuncDeclaration f)
+	{   Pvirtuals p = *cast(Pvirtuals*)param;
+
+		if (f.isVirtual())
+		{	Expression e;
+
+			if (p.e1.op == TOK.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(cast(void*)e);
+		}
+		return 0;
+	}
+}
+
+
+
+class TraitsExp : Expression
+{
+	Identifier ident;
+
+	Objects args;
+
+	this(Loc loc, Identifier ident, Objects args)
+	{
+		super(loc, TOK.TOKtraits, this.sizeof);
+		this.ident = ident;
+		this.args = args;
+	}
+
+	Expression syntaxCopy()
+	{
+		return new TraitsExp(loc, ident, TemplateInstance.arraySyntaxCopy(args));
+	}
+
+	Expression semantic(Scope sc)
+	{
+		version (LOGSEMANTIC) {
+			printf("TraitsExp.semantic() %s\n", toChars());
+		}
+		if (ident != Id.compiles && ident != Id.isSame)
+			TemplateInstance.semanticTiargs(loc, sc, args, 1);
+		size_t dim = args ? args.dim : 0;
+		Object o;
+		FuncDeclaration f;
+
+		string ISTYPE(string cond)
+		{
+			return `
+				for (size_t i = 0; i < dim; i++)
+				{   Type t = getType(cast(Object)args.data[i]);
+					if (!t)
+						goto Lfalse;
+					if (!(`~cond~`))
+						goto Lfalse;
+				}
+			if (!dim)
+				goto Lfalse;
+			goto Ltrue;
+			`;
+		}
+
+		string ISDSYMBOL(string cond)
+		{
+			return `for (size_t i = 0; i < dim; i++)
+			{   Dsymbol s = getDsymbol(cast(Object)args.data[i]);
+				if (!s)
+					goto Lfalse;
+				if (!(`~cond~`))
+					goto Lfalse;
+			}
+			if (!dim)
+				goto Lfalse;
+			goto Ltrue;`;
+		}
+
+		if (ident == Id.isArithmetic)
+		{
+			mixin(ISTYPE(`t.isintegral() || t.isfloating()`));
+		}
+		else if (ident == Id.isFloating)
+		{
+			mixin(ISTYPE(q{t.isfloating()}));
+		}
+		else if (ident == Id.isIntegral)
+		{
+			mixin(ISTYPE(q{t.isintegral()}));
+		}
+		else if (ident == Id.isScalar)
+		{
+			mixin(ISTYPE(q{t.isscalar()}));
+		}
+		else if (ident == Id.isUnsigned)
+		{
+			mixin(ISTYPE(q{t.isunsigned()}));
+		}
+		else if (ident == Id.isAssociativeArray)
+		{
+			mixin(ISTYPE(q{t.toBasetype().ty == TY.Taarray}));
+		}
+		else if (ident == Id.isStaticArray)
+		{
+			mixin(ISTYPE(q{t.toBasetype().ty == TY.Tsarray}));
+		}
+		else if (ident == Id.isAbstractClass)
+		{
+			mixin(ISTYPE(q{t.toBasetype().ty == TY.Tclass && (cast(TypeClass)t.toBasetype()).sym.isAbstract()}));
+		}
+		else if (ident == Id.isFinalClass)
+		{
+			mixin(ISTYPE(q{t.toBasetype().ty == TY.Tclass && (cast(TypeClass)t.toBasetype()).sym.storage_class & STC.STCfinal}));
+		}
+		else if (ident == Id.isAbstractFunction)
+		{
+			mixin(ISDSYMBOL(q{(f = s.isFuncDeclaration()) !is null && f.isAbstract()}));
+		}
+		else if (ident == Id.isVirtualFunction)
+		{
+			mixin(ISDSYMBOL(q{(f = s.isFuncDeclaration()) !is null && f.isVirtual()}));
+		}
+		else if (ident == Id.isFinalFunction)
+		{
+			mixin(ISDSYMBOL(q{(f = s.isFuncDeclaration()) !is null && f.isFinal()}));
+		}
+		else if (ident == Id.hasMember ||
+				ident == Id.getMember ||
+				ident == Id.getVirtualFunctions)
+		{
+			if (dim != 2)
+				goto Ldimerror;
+			Object o_ = cast(Object)args.data[0];
+			Expression e = isExpression(cast(Object)args.data[1]);
+			if (!e)
+			{   error("expression expected as second argument of __traits %s", ident.toChars());
+				goto Lfalse;
+			}
+			e = e.optimize(WANT.WANTvalue | WANT.WANTinterpret);
+			if (e.op != TOKstring)
+			{   error("string expected as second argument of __traits %s instead of %s", ident.toChars(), e.toChars());
+				goto Lfalse;
+			}
+			StringExp se = cast(StringExp)e;
+			se = se.toUTF8(sc);
+			if (se.sz != 1)
+			{   error("string must be chars");
+				goto Lfalse;
+			}
+			Identifier id = Lexer.idPool(fromStringz(cast(char*)se.string_));
+
+			Type t = isType(o_);
+			e = isExpression(o_);
+			Dsymbol s = isDsymbol(o_);
+			if (t)
+				e = typeDotIdExp(loc, t, id);
+			else if (e)
+				e = new DotIdExp(loc, e, id);
+			else if (s)
+			{   e = new DsymbolExp(loc, s);
+				e = new DotIdExp(loc, e, id);
+			}
+			else
+			{   error("invalid first argument");
+				goto Lfalse;
+			}
+
+			if (ident == Id.hasMember)
+			{   /* Take any errors as meaning it wasn't found
+			     */
+				e = e.trySemantic(sc);
+				if (!e)
+				{	if (global.gag)
+					global.errors++;
+					goto Lfalse;
+				}
+				else
+					goto Ltrue;
+			}
+			else if (ident == Id.getMember)
+			{
+				e = e.semantic(sc);
+				return e;
+			}
+			else if (ident == Id.getVirtualFunctions)
+			{
+				uint errors = global.errors;
+				Expression ex = e;
+				e = e.semantic(sc);
+				if (errors < global.errors)
+					error("%s cannot be resolved", ex.toChars());
+
+				/* Create tuple of virtual function overloads of e
+				 */
+				//e.dump(0);
+				Expressions exps = new Expressions();
+				FuncDeclaration f_;
+				if (e.op == TOKvar)
+				{	VarExp ve = cast(VarExp)e;
+					f_ = ve.var.isFuncDeclaration();
+				}
+				else if (e.op == TOKdotvar)
+				{	DotVarExp dve = cast(DotVarExp)e;
+					f_ = dve.var.isFuncDeclaration();
+				}
+				else
+					f_ = null;
+				Pvirtuals p;
+				p.exps = exps;
+				p.e1 = e;
+				overloadApply(f_, &p.fpvirtuals, &p);
+
+				TupleExp tup = new TupleExp(loc, exps);
+				return tup.semantic(sc);
+			}
+			else
+				assert(0);
+		}
+		else if (ident == Id.classInstanceSize)
+		{
+			if (dim != 1)
+				goto Ldimerror;
+			Object o_ = cast(Object)args.data[0];
+			Dsymbol s = getDsymbol(o_);
+			ClassDeclaration cd;
+			if (!s || (cd = s.isClassDeclaration()) is null)
+			{
+				error("first argument is not a class");
+				goto Lfalse;
+			}
+			return new IntegerExp(loc, cd.structsize, Type.tsize_t);
+		}
+		else if (ident == Id.allMembers || ident == Id.derivedMembers)
+		{
+			if (dim != 1)
+				goto Ldimerror;
+			Object o_ = cast(Object)args.data[0];
+			Dsymbol s = getDsymbol(o_);
+			ScopeDsymbol sd;
+			if (!s)
+			{
+				error("argument has no members");
+				goto Lfalse;
+			}
+			if ((sd = s.isScopeDsymbol()) is null)
+			{
+				error("%s %s has no members", s.kind(), s.toChars());
+				goto Lfalse;
+			}
+			Expressions exps = new Expressions;
+			while (1)
+			{   size_t dim_ = ScopeDsymbol.dim(sd.members);
+				for (size_t i = 0; i < dim_; i++)
+				{
+					Dsymbol sm = ScopeDsymbol.getNth(sd.members, i);
+					//printf("\t[%i] %s %s\n", i, sm.kind(), sm.toChars());
+					if (sm.ident)
+					{
+						//printf("\t%s\n", sm.ident.toChars());
+						auto str = sm.ident.toChars();
+
+						/* Skip if already present in exps[]
+						 */
+						for (size_t j = 0; j < exps.dim; j++)
+						{   StringExp se2 = cast(StringExp)exps.data[j];
+							if (strcmp(toStringz(str), cast(char*)se2.string_) == 0)
+								goto Lnext;
+						}
+
+						StringExp se = new StringExp(loc, str);
+						exps.push(cast(void*)se);
+					}
+Lnext:
+					;
+				}
+				ClassDeclaration cd = sd.isClassDeclaration();
+				if (cd && cd.baseClass && ident == Id.allMembers)
+					sd = cd.baseClass;	// do again with base class
+				else
+					break;
+			}
+			Expression e = new ArrayLiteralExp(loc, exps);
+			e = e.semantic(sc);
+			return e;
+		}
+		else if (ident == Id.compiles)
+		{
+			/* Determine if all the objects - types, expressions, or symbols -
+			 * compile without error
+			 */
+			if (!dim)
+				goto Lfalse;
+
+			for (size_t i = 0; i < dim; i++)
+			{   Object o_ = cast(Object)args.data[i];
+				Expression e;
+
+				uint errors = global.errors;
+				global.gag++;
+
+				Type t = isType(o_);
+				if (t)
+				{	Dsymbol s;
+					t.resolve(loc, sc, &e, &t, &s);
+					if (t)
+						t.semantic(loc, sc);
+					else if (e)
+						e.semantic(sc);
+				}
+				else
+				{	e = isExpression(o);
+					if (e)
+						e.semantic(sc);
+				}
+
+				global.gag--;
+				if (errors != global.errors)
+				{   if (global.gag == 0)
+					global.errors = errors;
+					goto Lfalse;
+				}
+			}
+			goto Ltrue;
+		}
+		else if (ident == Id.isSame)
+		{	/* Determine if two symbols are the same
+			 */
+			if (dim != 2)
+				goto Ldimerror;
+			TemplateInstance.semanticTiargs(loc, sc, args, 0);
+			Object o1 = cast(Object)args.data[0];
+			Object o2 = cast(Object)args.data[1];
+			Dsymbol s1 = getDsymbol(o1);
+			Dsymbol s2 = getDsymbol(o2);
+
+			static if (0) {
+				printf("o1: %p\n", o1);
+				printf("o2: %p\n", o2);
+				if (!s1)
+				{   Expression ea = isExpression(o1);
+					if (ea)
+						printf("%s\n", ea.toChars());
+					Type ta = isType(o1);
+					if (ta)
+						printf("%s\n", ta.toChars());
+					goto Lfalse;
+				}
+				else
+					printf("%s %s\n", s1.kind(), s1.toChars());
+			}
+			if (!s1 && !s2)
+			{   Expression ea1 = isExpression(o1);
+				Expression ea2 = isExpression(o2);
+				if (ea1 && ea2 && ea1.equals(ea2))
+					goto Ltrue;
+			}
+
+			if (!s1 || !s2)
+				goto Lfalse;
+
+			s1 = s1.toAlias();
+			s2 = s2.toAlias();
+
+			if (s1 == s2)
+				goto Ltrue;
+			else
+				goto Lfalse;
+		}
+		else
+		{	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;
+
+Ldimerror:
+		error("wrong number of arguments %d", dim);
+		goto Lfalse;
+
+
+Lfalse:
+		return new IntegerExp(loc, 0, Type.tbool);
+
+Ltrue:
+		return new IntegerExp(loc, 1, Type.tbool);
+	}
+
+	void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		buf.writestring("__traits(");
+		buf.writestring(ident.toChars());
+		if (args)
+		{
+			for (int i = 0; i < args.dim; i++)
+			{
+				buf.writeByte(',');
+				Object oarg = cast(Object)args.data[i];
+				ObjectToCBuffer(buf, hgs, oarg);
+			}
+		}
+		buf.writeByte(')');
+	}
+}
+
--- a/dmd/expression/Util.d	Sun Apr 04 22:41:11 2010 +0100
+++ b/dmd/expression/Util.d	Mon Apr 05 03:24:08 2010 +0100
@@ -129,7 +129,7 @@
  *	1	done
  */
 
-int overloadApply(FuncDeclaration fstart, int delegate(FuncDeclaration) dg)
+int overloadApply(FuncDeclaration fstart, int delegate(void*, FuncDeclaration) dg, void* param)
 {
     FuncDeclaration f;
     Declaration d;
@@ -141,7 +141,7 @@
 
 		if (fa)
 		{
-			if (overloadApply(fa.funcalias, dg))
+			if (overloadApply(fa.funcalias, dg, param))
 				return 1;
 			next = fa.overnext;
 		}
@@ -166,7 +166,7 @@
 					d.error("is aliased to a function");
 					break;		// BUG: should print error message?
 				}
-				if (dg(f))
+				if (dg(param, f))
 					return 1;
 
 				next = f.overnext;
@@ -186,7 +186,7 @@
     Expression ethis;
     Expressions arguments;
 	
-	int fp2(FuncDeclaration f)
+	int fp2(void*, FuncDeclaration f)
 	{   
 		MATCH match;
 
@@ -250,7 +250,7 @@
     Type t;		// type to match
     FuncDeclaration f;	// return value
 	
-	int fp1(FuncDeclaration f)
+	int fp1(void*, FuncDeclaration f)
 	{   
 		if (t.equals(f.type))
 		{	
@@ -283,7 +283,7 @@
     p.m = m;
     p.ethis = ethis;
     p.arguments = arguments;
-    overloadApply(fstart, &p.fp2);
+    overloadApply(fstart, &p.fp2, &p);
 }
 
 void templateResolve(Match* m, TemplateDeclaration td, Scope sc, Loc loc, Objects targsi, Expression ethis, Expressions arguments)
@@ -1258,7 +1258,7 @@
 	 * analogous to func.overloadResolveX().
 	 */
 
-	int fp3(FuncDeclaration f)
+	int fp3(void*, FuncDeclaration f)
 	{
 		TypeFunction tf = cast(TypeFunction)f.type;
 		if (inferApplyArgTypesY(tf, arguments) == 1)
@@ -1277,7 +1277,7 @@
 {
 	Param3 p3;
 	p3.arguments = arguments;
-    overloadApply(fstart, &p3.fp3);
+    overloadApply(fstart, &p3.fp3, cast(void*)arguments);
 }
 
 /******************************