diff dmd/CallExp.d @ 72:2e2a5c3f943a

reduced warnings by adding override to the methods think this also normalizes different line endings used all over the place
author Trass3r
date Sat, 28 Aug 2010 16:19:48 +0200
parents efb1e5bdf63c
children ef02e2e203c2
line wrap: on
line diff
--- a/dmd/CallExp.d	Sat Aug 28 16:14:07 2010 +0200
+++ b/dmd/CallExp.d	Sat Aug 28 16:19:48 2010 +0200
@@ -1,85 +1,85 @@
-module dmd.CallExp;
-
-import dmd.Expression;
-import dmd.Cast;
-import dmd.WANT;
-import dmd.BUILTIN;
-import dmd.TypeFunction;
-import dmd.ScopeDsymbol;
-import dmd.CastExp;
-import dmd.GlobalExpressions;
-import dmd.TypePointer;
-import dmd.ThisExp;
-import dmd.OverExp;
-import dmd.Dsymbol;
-import dmd.CSX;
-import dmd.AggregateDeclaration;
-import dmd.TypeDelegate;
-import dmd.ClassDeclaration;
-import dmd.DsymbolExp;
-import dmd.DotExp;
-import dmd.TemplateExp;
-import dmd.TypeStruct;
-import dmd.TypeClass;
-import dmd.Identifier;
-import dmd.Lexer;
-import dmd.VarDeclaration;
-import dmd.DeclarationExp;
-import dmd.CtorDeclaration;
-import dmd.PtrExp;
-import dmd.TemplateDeclaration;
-import dmd.StructLiteralExp;
-import dmd.StructDeclaration;
-import dmd.DotTemplateExp;
-import dmd.CommaExp;
-import dmd.AggregateDeclaration;
-import dmd.FuncDeclaration;
-import dmd.Type;
-import dmd.ScopeExp;
-import dmd.VarExp;
-import dmd.STC;
-import dmd.LINK;
-import dmd.Global;
-import dmd.DotTemplateInstanceExp;
-import dmd.TemplateInstance;
-import dmd.DelegateExp;
-import dmd.IdentifierExp;
-import dmd.DotVarExp;
-import dmd.DotIdExp;
-import dmd.TY;
-import dmd.Id;
-import dmd.TypeAArray;
-import dmd.RemoveExp;
-import dmd.backend.elem;
-import dmd.UnaExp;
-import dmd.InterState;
-import dmd.OutBuffer;
-import dmd.Loc;
-import dmd.Scope;
-import dmd.InlineCostState;
-import dmd.IRState;
-import dmd.InlineDoState;
-import dmd.HdrGenState;
-import dmd.InlineScanState;
-import dmd.ArrayTypes;
-import dmd.TOK;
-import dmd.PREC;
-import dmd.expression.Util;
-import dmd.backend.Symbol;
-import dmd.backend.TYPE;
-import dmd.backend.Util;
-import dmd.backend.TYM;
-import dmd.codegen.Util;
-
-import std.stdio;
-
+module dmd.CallExp;
+
+import dmd.Expression;
+import dmd.Cast;
+import dmd.WANT;
+import dmd.BUILTIN;
+import dmd.TypeFunction;
+import dmd.ScopeDsymbol;
+import dmd.CastExp;
+import dmd.GlobalExpressions;
+import dmd.TypePointer;
+import dmd.ThisExp;
+import dmd.OverExp;
+import dmd.Dsymbol;
+import dmd.CSX;
+import dmd.AggregateDeclaration;
+import dmd.TypeDelegate;
+import dmd.ClassDeclaration;
+import dmd.DsymbolExp;
+import dmd.DotExp;
+import dmd.TemplateExp;
+import dmd.TypeStruct;
+import dmd.TypeClass;
+import dmd.Identifier;
+import dmd.Lexer;
+import dmd.VarDeclaration;
+import dmd.DeclarationExp;
+import dmd.CtorDeclaration;
+import dmd.PtrExp;
+import dmd.TemplateDeclaration;
+import dmd.StructLiteralExp;
+import dmd.StructDeclaration;
+import dmd.DotTemplateExp;
+import dmd.CommaExp;
+import dmd.AggregateDeclaration;
+import dmd.FuncDeclaration;
+import dmd.Type;
+import dmd.ScopeExp;
+import dmd.VarExp;
+import dmd.STC;
+import dmd.LINK;
+import dmd.Global;
+import dmd.DotTemplateInstanceExp;
+import dmd.TemplateInstance;
+import dmd.DelegateExp;
+import dmd.IdentifierExp;
+import dmd.DotVarExp;
+import dmd.DotIdExp;
+import dmd.TY;
+import dmd.Id;
+import dmd.TypeAArray;
+import dmd.RemoveExp;
+import dmd.backend.elem;
+import dmd.UnaExp;
+import dmd.InterState;
+import dmd.OutBuffer;
+import dmd.Loc;
+import dmd.Scope;
+import dmd.InlineCostState;
+import dmd.IRState;
+import dmd.InlineDoState;
+import dmd.HdrGenState;
+import dmd.InlineScanState;
+import dmd.ArrayTypes;
+import dmd.TOK;
+import dmd.PREC;
+import dmd.expression.Util;
+import dmd.backend.Symbol;
+import dmd.backend.TYPE;
+import dmd.backend.Util;
+import dmd.backend.TYM;
+import dmd.codegen.Util;
+
+import std.stdio;
+
 class CallExp : UnaExp
 {
 	Expressions arguments;
 
 	this(Loc loc, Expression e, Expressions exps)
 	{
-		super(loc, TOK.TOKcall, CallExp.sizeof, e);
+		super(loc, TOK.TOKcall, CallExp.sizeof, e);
 		this.arguments = exps;
 	}
 
@@ -90,1051 +90,1051 @@
 
 	this(Loc loc, Expression e, Expression earg1)
 	{
-		super(loc, TOK.TOKcall, CallExp.sizeof, e);
-		
-		Expressions arguments = new Expressions();
-		arguments.setDim(1);
-		arguments.data[0] = cast(void*)earg1;
-
+		super(loc, TOK.TOKcall, CallExp.sizeof, e);
+		
+		Expressions arguments = new Expressions();
+		arguments.setDim(1);
+		arguments.data[0] = cast(void*)earg1;
+
 		this.arguments = arguments;
 	}
 
 	this(Loc loc, Expression e, Expression earg1, Expression earg2)
-	{
-		super(loc, TOK.TOKcall, CallExp.sizeof, e);
+	{
+		super(loc, TOK.TOKcall, CallExp.sizeof, e);
 		
-		Expressions arguments = new Expressions();
-		arguments.setDim(2);
-		arguments.data[0] = cast(void*)earg1;
-		arguments.data[1] = cast(void*)earg2;
-
+		Expressions arguments = new Expressions();
+		arguments.setDim(2);
+		arguments.data[0] = cast(void*)earg1;
+		arguments.data[1] = cast(void*)earg2;
+
 		this.arguments = arguments;
 	}
 
-	Expression syntaxCopy()
+	override Expression syntaxCopy()
 	{
 		return new CallExp(loc, e1.syntaxCopy(), arraySyntaxCopy(arguments));
 	}
 
-	Expression semantic(Scope sc)
-	{
-		TypeFunction tf;
-		FuncDeclaration f;
-		int i;
-		Type t1;
-		int istemp;
-		Objects targsi;	// initial list of template arguments
-		TemplateInstance tierror;
-
-version (LOGSEMANTIC) {
-		printf("CallExp.semantic() %s\n", toChars());
-}
-		if (type)
-			return this;		// semantic() already run
-
-static if (false) {
-		if (arguments && arguments.dim)
-		{
-			Expression earg = cast(Expression)arguments.data[0];
-			earg.print();
-			if (earg.type) earg.type.print();
-		}
-}
-
-		if (e1.op == TOK.TOKdelegate)
-		{	
-			DelegateExp de = cast(DelegateExp)e1;
-
-			e1 = new DotVarExp(de.loc, de.e1, de.func);
-			return semantic(sc);
-		}
-
-		/* Transform:
-		 *	array.id(args) into .id(array,args)
-		 *	aa.remove(arg) into delete aa[arg]
-		 */
-		if (e1.op == TOK.TOKdot)
-		{
-			// BUG: we should handle array.a.b.c.e(args) too
-
-			DotIdExp dotid = cast(DotIdExp)(e1);
-			dotid.e1 = dotid.e1.semantic(sc);
-			assert(dotid.e1);
-			if (dotid.e1.type)
-			{
-				TY e1ty = dotid.e1.type.toBasetype().ty;
-				if (e1ty == TY.Taarray && dotid.ident == Id.remove)
-				{
-					if (!arguments || arguments.dim != 1)
-					{  
-						error("expected key as argument to aa.remove()");
-						goto Lagain;
-					}
-					Expression key = cast(Expression)arguments.data[0];
-					key = key.semantic(sc);
-					key = resolveProperties(sc, key);
-					key.rvalue();
-
-					TypeAArray taa = cast(TypeAArray)dotid.e1.type.toBasetype();
-					key = key.implicitCastTo(sc, taa.index);
-
-					return new RemoveExp(loc, dotid.e1, key);
-				}
-				else if (e1ty == TY.Tarray || e1ty == TY.Tsarray || e1ty == TY.Taarray)
-				{
-					if (!arguments)
-						arguments = new Expressions();
-					arguments.shift(cast(void*)dotid.e1);
-version (DMDV2) {
-					e1 = new DotIdExp(dotid.loc, new IdentifierExp(dotid.loc, Id.empty), dotid.ident);
-} else {
-					e1 = new IdentifierExp(dotid.loc, dotid.ident);
-}
-				}
-			}
-		}
-
-static if (true) {
-		/* This recognizes:
-		 *	foo!(tiargs)(funcargs)
-		 */
-		if (e1.op == TOK.TOKimport && !e1.type)
-		{	
-			ScopeExp se = cast(ScopeExp)e1;
-			TemplateInstance ti = se.sds.isTemplateInstance();
-			if (ti && !ti.semanticRun)
-			{
-				/* Attempt to instantiate ti. If that works, go with it.
-				 * If not, go with partial explicit specialization.
-				 */
-				ti.semanticTiargs(sc);
-				uint errors = global.errors;
-				global.gag++;
-				ti.semantic(sc);
-				global.gag--;
-				if (errors != global.errors)
-				{
-					/* Didn't work, go with partial explicit specialization
-					 */
-					global.errors = errors;
-					targsi = ti.tiargs;
-					tierror = ti;			// for error reporting
-					e1 = new IdentifierExp(loc, ti.name);
-				}
-			}
-		}
-
-		/* This recognizes:
-		 *	expr.foo!(tiargs)(funcargs)
-		 */
-		if (e1.op == TOK.TOKdotti && !e1.type)
-		{	
-			DotTemplateInstanceExp se = cast(DotTemplateInstanceExp)e1;
-			TemplateInstance ti = se.ti;
-			if (!ti.semanticRun)
-			{
-				/* Attempt to instantiate ti. If that works, go with it.
-				 * If not, go with partial explicit specialization.
-				 */
-				ti.semanticTiargs(sc);
-				Expression etmp = e1.trySemantic(sc);
-				if (etmp)
-					e1 = etmp;	// it worked
-				else		// didn't work
-				{
-					targsi = ti.tiargs;
-					tierror = ti;		// for error reporting
-					e1 = new DotIdExp(loc, se.e1, ti.name);
-				}
-			}
-		}
-}
-
-		istemp = 0;
-	Lagain:
-		//printf("Lagain: %s\n", toChars());
-		f = null;
-		if (e1.op == TOK.TOKthis || e1.op == TOK.TOKsuper)
-		{
-			// semantic() run later for these
-		}
-		else
-		{
-			UnaExp.semantic(sc);
-
-			/* Look for e1 being a lazy parameter
-			 */
-			if (e1.op == TOK.TOKvar)
-			{   
-				VarExp ve = cast(VarExp)e1;
-
-				if (ve.var.storage_class & STC.STClazy)
-				{
-					TypeFunction tff = new TypeFunction(null, ve.var.type, 0, LINK.LINKd);
-					TypeDelegate t = new TypeDelegate(tff);
-					ve.type = t.semantic(loc, sc);
-				}
-			}
-
-			if (e1.op == TOK.TOKimport)
-			{   
-				// Perhaps this should be moved to ScopeExp.semantic()
-				ScopeExp se = cast(ScopeExp)e1;
-				e1 = new DsymbolExp(loc, se.sds);
-				e1 = e1.semantic(sc);
-			}
-///static if (true) {	// patch for #540 by Oskar Linde
-			else if (e1.op == TOK.TOKdotexp)
-			{
-				DotExp de = cast(DotExp)e1;
-
-				if (de.e2.op == TOK.TOKimport)
-				{   
-					// This should *really* be moved to ScopeExp.semantic()
-					ScopeExp se = cast(ScopeExp)de.e2;
-					de.e2 = new DsymbolExp(loc, se.sds);
-					de.e2 = de.e2.semantic(sc);
-				}
-
-				if (de.e2.op == TOK.TOKtemplate)
-				{   
-					TemplateExp te = cast(TemplateExp)de.e2;
-					e1 = new DotTemplateExp(loc,de.e1,te.td);
-				}
-			}
-///}
-		}
-
-		if (e1.op == TOK.TOKcomma)
-		{
-			CommaExp ce = cast(CommaExp)e1;
-
-			e1 = ce.e2;
-			e1.type = ce.type;
-			ce.e2 = this;
-			ce.type = null;
-			return ce.semantic(sc);
-		}
-
-		t1 = null;
-		if (e1.type)
-		t1 = e1.type.toBasetype();
-
-		// Check for call operator overload
-		if (t1)
-		{	
-			AggregateDeclaration ad;
-
-			if (t1.ty == TY.Tstruct)
-			{
-				ad = (cast(TypeStruct)t1).sym;
-version (DMDV2) {
-				// First look for constructor
-				if (ad.ctor && arguments && arguments.dim)
-				{
-					// Create variable that will get constructed
-					Identifier idtmp = Lexer.uniqueId("__ctmp");
-					VarDeclaration tmp = new VarDeclaration(loc, t1, idtmp, null);
-					Expression av = new DeclarationExp(loc, tmp);
-					av = new CommaExp(loc, av, new VarExp(loc, tmp));
-
-					Expression e;
-					CtorDeclaration cf = ad.ctor.isCtorDeclaration();
-					if (cf)
-						e = new DotVarExp(loc, av, cf, 1);
-					else
-					{   
-						TemplateDeclaration td = ad.ctor.isTemplateDeclaration();
-						assert(td);
-						e = new DotTemplateExp(loc, av, td);
-					}
-					e = new CallExp(loc, e, arguments);
-			version (STRUCTTHISREF) {
-			} else {
-					/* Constructors return a pointer to the instance
-					 */
-					e = new PtrExp(loc, e);
-			}
-					e = e.semantic(sc);
-					return e;
-				}
-}
-				// No constructor, look for overload of opCall
-				if (search_function(ad, Id.call))
-					goto L1;	// overload of opCall, therefore it's a call
-
-				if (e1.op != TOK.TOKtype)
-					error("%s %s does not overload ()", ad.kind(), ad.toChars());
-				
-				/* It's a struct literal
-				 */
-				Expression e = new StructLiteralExp(loc, cast(StructDeclaration)ad, arguments);
-				e = e.semantic(sc);
-				e.type = e1.type;		// in case e1.type was a typedef
-				return e;
-			}
-			else if (t1.ty == TY.Tclass)
-			{
-				ad = (cast(TypeClass)t1).sym;
-				goto L1;
-			L1:
-				// Rewrite as e1.call(arguments)
-				Expression e = new DotIdExp(loc, e1, Id.call);
-				e = new CallExp(loc, e, arguments);
-				e = e.semantic(sc);
-				return e;
-			}
-		}
-
-		arrayExpressionSemantic(arguments, sc);
-		preFunctionArguments(loc, sc, arguments);
-
-		if (e1.op == TOK.TOKdotvar && t1.ty == TY.Tfunction ||
-			e1.op == TOK.TOKdottd)
-		{
-			DotVarExp dve;
-			DotTemplateExp dte;
-			AggregateDeclaration ad;
-			UnaExp ue = cast(UnaExp)e1;
-
-			if (e1.op == TOK.TOKdotvar)
-			{   
-				// Do overload resolution
-				dve = cast(DotVarExp)e1;
-
-				f = dve.var.isFuncDeclaration();
-				assert(f);
-				f = f.overloadResolve(loc, ue.e1, arguments);
-
-				ad = f.toParent().isAggregateDeclaration();
-			}
-			else
-			{   
-				dte = cast(DotTemplateExp)e1;
-				TemplateDeclaration td = dte.td;
-				assert(td);
-
-				if (!arguments)
-					// Should fix deduceFunctionTemplate() so it works on null argument
-					arguments = new Expressions();
-
-				f = td.deduceFunctionTemplate(sc, loc, targsi, ue.e1, arguments);
-				if (!f)
-				{	
-					type = Type.terror;
-					return this;
-				}
-				ad = td.toParent().isAggregateDeclaration();
-			}
-
-			if (f.needThis())
-			{
-				ue.e1 = getRightThis(loc, sc, ad, ue.e1, f);
-			}
-
-			/* Cannot call public functions from inside invariant
-			 * (because then the invariant would have infinite recursion)
-			 */
-			if (sc.func && sc.func.isInvariantDeclaration() &&
-				ue.e1.op == TOK.TOKthis && f.addPostInvariant())
-			{
-				error("cannot call public/export function %s from invariant", f.toChars());
-			}
-
-			checkDeprecated(sc, f);
-	version (DMDV2) {
-			checkPurity(sc, f);
-	}
-			accessCheck(loc, sc, ue.e1, f);
-			if (!f.needThis())
-			{
-				VarExp ve = new VarExp(loc, f);
-				e1 = new CommaExp(loc, ue.e1, ve);
-				e1.type = f.type;
-			}
-			else
-			{
-				if (e1.op == TOK.TOKdotvar)		
-					dve.var = f;
-				else
-					e1 = new DotVarExp(loc, dte.e1, f);
-
-				e1.type = f.type;
-static if (false) {
-				printf("ue.e1 = %s\n", ue.e1.toChars());
-				printf("f = %s\n", f.toChars());
-				printf("t = %s\n", t.toChars());
-				printf("e1 = %s\n", e1.toChars());
-				printf("e1.type = %s\n", e1.type.toChars());
-}
-				// Const member function can take const/immutable/mutable this
-				if (!(f.type.isConst()))
-				{
-					// Check for const/immutable compatibility
-					Type tthis = ue.e1.type.toBasetype();
-					if (tthis.ty == TY.Tpointer)
-						tthis = tthis.nextOf().toBasetype();
-
-	static if (false) {	// this checking should have been already done
-					if (f.type.isInvariant())
-					{
-						if (tthis.mod != MOD.MODinvariant)
-							error("%s can only be called with an immutable object", e1.toChars());
-					}
-					else if (f.type.isShared())
-					{
-						if (tthis.mod != MOD.MODinvariant && tthis.mod != MOD.MODshared && tthis.mod != (MOD.MODshared | MOD.MODconst))
-							error("shared %s can only be called with a shared or immutable object", e1.toChars());
-					}
-					else
-					{
-						if (tthis.mod != MOD.MODundefined)
-						{	
-							//printf("mod = %x\n", tthis.mod);
-							error("%s can only be called with a mutable object, not %s", e1.toChars(), tthis.toChars());
-						}
-					}
-	}
-					/* Cannot call mutable method on a final struct
-					 */
-					if (tthis.ty == TY.Tstruct &&
-						ue.e1.op == TOK.TOKvar)
-					{
-						VarExp v = cast(VarExp)ue.e1;
-						if (v.var.storage_class & STC.STCfinal)
-							error("cannot call mutable method on final struct");
-					}
-				}
-
-				// See if we need to adjust the 'this' pointer
-				AggregateDeclaration add = f.isThis();
-				ClassDeclaration cd = ue.e1.type.isClassHandle();
-				if (add && cd && add.isClassDeclaration() && add != cd && ue.e1.op != TOK.TOKsuper)
-				{
-					ue.e1 = ue.e1.castTo(sc, add.type); //new CastExp(loc, ue.e1, add.type);
-					ue.e1 = ue.e1.semantic(sc);
-				}
-			}
-			t1 = e1.type;
-		}
-		else if (e1.op == TOK.TOKsuper)
-		{
-			// Base class constructor call
-			ClassDeclaration cd = null;
-
-			if (sc.func)
-				cd = sc.func.toParent().isClassDeclaration();
-			if (!cd || !cd.baseClass || !sc.func.isCtorDeclaration())
-			{
-				error("super class constructor call must be in a constructor");
-				type = Type.terror;
-				return this;
-			}
-			else
-			{
-				if (!cd.baseClass.ctor)
-				{	
-					error("no super class constructor for %s", cd.baseClass.toChars());
-					type = Type.terror;
-					return this;
-				}
-				else
-				{
-					if (!sc.intypeof)
-					{
-static if (false) {
-						if (sc.callSuper & (CSX.CSXthis | CSX.CSXsuper))
-							error("reference to this before super()");
-}
-						if (sc.noctor || sc.callSuper & CSX.CSXlabel)
-							error("constructor calls not allowed in loops or after labels");
-						if (sc.callSuper & (CSX.CSXsuper_ctor | CSX.CSXthis_ctor))
-							error("multiple constructor calls");
-						sc.callSuper |= CSX.CSXany_ctor | CSX.CSXsuper_ctor;
-					}
-
-					f = resolveFuncCall(sc, loc, cd.baseClass.ctor, null, null, arguments, 0);
-					checkDeprecated(sc, f);
-version (DMDV2) {
-					checkPurity(sc, f);
-}
-					e1 = new DotVarExp(e1.loc, e1, f);
-					e1 = e1.semantic(sc);
-					t1 = e1.type;
-				}
-			}
-		}
-		else if (e1.op == TOK.TOKthis)
-		{
-			// same class constructor call
-			AggregateDeclaration cd = null;
-
-			if (sc.func)
-				cd = sc.func.toParent().isAggregateDeclaration();
-			if (!cd || !sc.func.isCtorDeclaration())
-			{
-				error("constructor call must be in a constructor");
-				type = Type.terror;
-				return this;
-			}
-			else
-			{
-				if (!sc.intypeof)
-				{
-static if (false) {
-					if (sc.callSuper & (CSXthis | CSXsuper))
-						error("reference to this before super()");
-}
-					if (sc.noctor || sc.callSuper & CSX.CSXlabel)
-						error("constructor calls not allowed in loops or after labels");
-					if (sc.callSuper & (CSX.CSXsuper_ctor | CSX.CSXthis_ctor))
-						error("multiple constructor calls");
-					sc.callSuper |= CSX.CSXany_ctor | CSX.CSXthis_ctor;
-				}
-
-				f = resolveFuncCall(sc, loc, cd.ctor, null, null, arguments, 0);
-				checkDeprecated(sc, f);
-version (DMDV2) {
-				checkPurity(sc, f);
-}
-				e1 = new DotVarExp(e1.loc, e1, f);
-				e1 = e1.semantic(sc);
-				t1 = e1.type;
-
-				// BUG: this should really be done by checking the static
-				// call graph
-				if (f == sc.func)
-					error("cyclic constructor call");
-			}
-		}
-		else if (e1.op == TOK.TOKoverloadset)
-		{
-			OverExp eo = cast(OverExp)e1;
-			FuncDeclaration ff = null;
-			for (int j = 0; j < eo.vars.a.dim; j++)
-			{   
-				Dsymbol s = cast(Dsymbol)eo.vars.a.data[j];
-				FuncDeclaration f2 = s.isFuncDeclaration();
-				if (f2)
-				{
-					f2 = f2.overloadResolve(loc, null, arguments, 1);
-				}
-				else
-				{	
-					TemplateDeclaration td = s.isTemplateDeclaration();
-					assert(td);
-					f2 = td.deduceFunctionTemplate(sc, loc, targsi, null, arguments, 1);
-				}
-				if (f2)
-				{	
-					if (ff)
-						/* Error if match in more than one overload set,
-						 * even if one is a 'better' match than the other.
-						 */
-						ScopeDsymbol.multiplyDefined(loc, ff, f2);
-					else
-						ff = f2;
-				}
-			}
-			if (!ff)
-			{   
-				/* No overload matches, just set ff and rely on error
-				 * message being generated later.
-				 */
-				ff = cast(FuncDeclaration)eo.vars.a.data[0];
-			}
-			e1 = new VarExp(loc, ff);
-			goto Lagain;
-		}
-		else if (!t1)
-		{
-			error("function expected before (), not '%s'", e1.toChars());
-			type = Type.terror;
-			return this;
-		}
-		else if (t1.ty != TY.Tfunction)
-		{
-			if (t1.ty == TY.Tdelegate)
-			{   
-				TypeDelegate td = cast(TypeDelegate)t1;
-				assert(td.next.ty == TY.Tfunction);
-				tf = cast(TypeFunction)(td.next);
-				if (sc.func && sc.func.isPure() && !tf.ispure)
-				{
-					error("pure function '%s' cannot call impure delegate '%s'", sc.func.toChars(), e1.toChars());
-				}
-				goto Lcheckargs;
-			}
-			else if (t1.ty == TY.Tpointer && (cast(TypePointer)t1).next.ty == TY.Tfunction)
-			{   
-				Expression e = new PtrExp(loc, e1);
-				t1 = (cast(TypePointer)t1).next;
-				if (sc.func && sc.func.isPure() && !(cast(TypeFunction)t1).ispure)
-				{
-					error("pure function '%s' cannot call impure function pointer '%s'", sc.func.toChars(), e1.toChars());
-				}
-				e.type = t1;
-				e1 = e;
-			}
-			else if (e1.op == TOK.TOKtemplate)
-			{
-				TemplateExp te = cast(TemplateExp)e1;
-				f = te.td.deduceFunctionTemplate(sc, loc, targsi, null, arguments);
-				if (!f)
-				{	
-					if (tierror)
-						tierror.error("errors instantiating template");	// give better error message
-					type = Type.terror;
-					return this;
-				}
-				if (f.needThis() && hasThis(sc))
-				{
-					// Supply an implicit 'this', as in
-					//	  this.ident
-
-					e1 = new DotTemplateExp(loc, (new ThisExp(loc)).semantic(sc), te.td);
-					goto Lagain;
-				}
-
-				e1 = new VarExp(loc, f);
-				goto Lagain;
-			}
-			else
-			{   
-				error("function expected before (), not %s of type %s", e1.toChars(), e1.type.toChars());
-				type = Type.terror;
-				return this;
-			}
-		}
-		else if (e1.op == TOK.TOKvar)
-		{
-			// Do overload resolution
-			VarExp ve = cast(VarExp)e1;
-
-			f = ve.var.isFuncDeclaration();
-			assert(f);
-
-			if (ve.hasOverloads)
-				f = f.overloadResolve(loc, null, arguments);
-
-			checkDeprecated(sc, f);
-version (DMDV2) {
-			checkPurity(sc, f);
-}
-
-			if (f.needThis() && hasThis(sc))
-			{
-				// Supply an implicit 'this', as in
-				//	  this.ident
-
-				e1 = new DotVarExp(loc, new ThisExp(loc), f);
-				goto Lagain;
-			}
-
-			accessCheck(loc, sc, null, f);
-
-			ve.var = f;
-		//	ve.hasOverloads = 0;
-			ve.type = f.type;
-			t1 = f.type;
-		}
-		assert(t1.ty == TY.Tfunction);
-		tf = cast(TypeFunction)t1;
-
-	Lcheckargs:
-		assert(tf.ty == TY.Tfunction);
-		type = tf.next;
-
-		if (!arguments)
-			arguments = new Expressions();
-
-		functionArguments(loc, sc, tf, arguments);
-
-		if (!type)
-		{
-			error("forward reference to inferred return type of function call %s", toChars());
-			type = Type.terror;
-		}
-
-		if (f && f.tintro)
-		{
-			Type t = type;
-			int offset = 0;
-			TypeFunction tff = cast(TypeFunction)f.tintro;
-
-			if (tff.next.isBaseOf(t, &offset) && offset)
-			{
-				type = tff.next;
-				return castTo(sc, t);
-			}
-		}
-
-		return this;
+	override Expression semantic(Scope sc)
+	{
+		TypeFunction tf;
+		FuncDeclaration f;
+		int i;
+		Type t1;
+		int istemp;
+		Objects targsi;	// initial list of template arguments
+		TemplateInstance tierror;
+
+version (LOGSEMANTIC) {
+		printf("CallExp.semantic() %s\n", toChars());
+}
+		if (type)
+			return this;		// semantic() already run
+
+static if (false) {
+		if (arguments && arguments.dim)
+		{
+			Expression earg = cast(Expression)arguments.data[0];
+			earg.print();
+			if (earg.type) earg.type.print();
+		}
+}
+
+		if (e1.op == TOK.TOKdelegate)
+		{	
+			DelegateExp de = cast(DelegateExp)e1;
+
+			e1 = new DotVarExp(de.loc, de.e1, de.func);
+			return semantic(sc);
+		}
+
+		/* Transform:
+		 *	array.id(args) into .id(array,args)
+		 *	aa.remove(arg) into delete aa[arg]
+		 */
+		if (e1.op == TOK.TOKdot)
+		{
+			// BUG: we should handle array.a.b.c.e(args) too
+
+			DotIdExp dotid = cast(DotIdExp)(e1);
+			dotid.e1 = dotid.e1.semantic(sc);
+			assert(dotid.e1);
+			if (dotid.e1.type)
+			{
+				TY e1ty = dotid.e1.type.toBasetype().ty;
+				if (e1ty == TY.Taarray && dotid.ident == Id.remove)
+				{
+					if (!arguments || arguments.dim != 1)
+					{  
+						error("expected key as argument to aa.remove()");
+						goto Lagain;
+					}
+					Expression key = cast(Expression)arguments.data[0];
+					key = key.semantic(sc);
+					key = resolveProperties(sc, key);
+					key.rvalue();
+
+					TypeAArray taa = cast(TypeAArray)dotid.e1.type.toBasetype();
+					key = key.implicitCastTo(sc, taa.index);
+
+					return new RemoveExp(loc, dotid.e1, key);
+				}
+				else if (e1ty == TY.Tarray || e1ty == TY.Tsarray || e1ty == TY.Taarray)
+				{
+					if (!arguments)
+						arguments = new Expressions();
+					arguments.shift(cast(void*)dotid.e1);
+version (DMDV2) {
+					e1 = new DotIdExp(dotid.loc, new IdentifierExp(dotid.loc, Id.empty), dotid.ident);
+} else {
+					e1 = new IdentifierExp(dotid.loc, dotid.ident);
+}
+				}
+			}
+		}
+
+static if (true) {
+		/* This recognizes:
+		 *	foo!(tiargs)(funcargs)
+		 */
+		if (e1.op == TOK.TOKimport && !e1.type)
+		{	
+			ScopeExp se = cast(ScopeExp)e1;
+			TemplateInstance ti = se.sds.isTemplateInstance();
+			if (ti && !ti.semanticRun)
+			{
+				/* Attempt to instantiate ti. If that works, go with it.
+				 * If not, go with partial explicit specialization.
+				 */
+				ti.semanticTiargs(sc);
+				uint errors = global.errors;
+				global.gag++;
+				ti.semantic(sc);
+				global.gag--;
+				if (errors != global.errors)
+				{
+					/* Didn't work, go with partial explicit specialization
+					 */
+					global.errors = errors;
+					targsi = ti.tiargs;
+					tierror = ti;			// for error reporting
+					e1 = new IdentifierExp(loc, ti.name);
+				}
+			}
+		}
+
+		/* This recognizes:
+		 *	expr.foo!(tiargs)(funcargs)
+		 */
+		if (e1.op == TOK.TOKdotti && !e1.type)
+		{	
+			DotTemplateInstanceExp se = cast(DotTemplateInstanceExp)e1;
+			TemplateInstance ti = se.ti;
+			if (!ti.semanticRun)
+			{
+				/* Attempt to instantiate ti. If that works, go with it.
+				 * If not, go with partial explicit specialization.
+				 */
+				ti.semanticTiargs(sc);
+				Expression etmp = e1.trySemantic(sc);
+				if (etmp)
+					e1 = etmp;	// it worked
+				else		// didn't work
+				{
+					targsi = ti.tiargs;
+					tierror = ti;		// for error reporting
+					e1 = new DotIdExp(loc, se.e1, ti.name);
+				}
+			}
+		}
+}
+
+		istemp = 0;
+	Lagain:
+		//printf("Lagain: %s\n", toChars());
+		f = null;
+		if (e1.op == TOK.TOKthis || e1.op == TOK.TOKsuper)
+		{
+			// semantic() run later for these
+		}
+		else
+		{
+			UnaExp.semantic(sc);
+
+			/* Look for e1 being a lazy parameter
+			 */
+			if (e1.op == TOK.TOKvar)
+			{   
+				VarExp ve = cast(VarExp)e1;
+
+				if (ve.var.storage_class & STC.STClazy)
+				{
+					TypeFunction tff = new TypeFunction(null, ve.var.type, 0, LINK.LINKd);
+					TypeDelegate t = new TypeDelegate(tff);
+					ve.type = t.semantic(loc, sc);
+				}
+			}
+
+			if (e1.op == TOK.TOKimport)
+			{   
+				// Perhaps this should be moved to ScopeExp.semantic()
+				ScopeExp se = cast(ScopeExp)e1;
+				e1 = new DsymbolExp(loc, se.sds);
+				e1 = e1.semantic(sc);
+			}
+///static if (true) {	// patch for #540 by Oskar Linde
+			else if (e1.op == TOK.TOKdotexp)
+			{
+				DotExp de = cast(DotExp)e1;
+
+				if (de.e2.op == TOK.TOKimport)
+				{   
+					// This should *really* be moved to ScopeExp.semantic()
+					ScopeExp se = cast(ScopeExp)de.e2;
+					de.e2 = new DsymbolExp(loc, se.sds);
+					de.e2 = de.e2.semantic(sc);
+				}
+
+				if (de.e2.op == TOK.TOKtemplate)
+				{   
+					TemplateExp te = cast(TemplateExp)de.e2;
+					e1 = new DotTemplateExp(loc,de.e1,te.td);
+				}
+			}
+///}
+		}
+
+		if (e1.op == TOK.TOKcomma)
+		{
+			CommaExp ce = cast(CommaExp)e1;
+
+			e1 = ce.e2;
+			e1.type = ce.type;
+			ce.e2 = this;
+			ce.type = null;
+			return ce.semantic(sc);
+		}
+
+		t1 = null;
+		if (e1.type)
+		t1 = e1.type.toBasetype();
+
+		// Check for call operator overload
+		if (t1)
+		{	
+			AggregateDeclaration ad;
+
+			if (t1.ty == TY.Tstruct)
+			{
+				ad = (cast(TypeStruct)t1).sym;
+version (DMDV2) {
+				// First look for constructor
+				if (ad.ctor && arguments && arguments.dim)
+				{
+					// Create variable that will get constructed
+					Identifier idtmp = Lexer.uniqueId("__ctmp");
+					VarDeclaration tmp = new VarDeclaration(loc, t1, idtmp, null);
+					Expression av = new DeclarationExp(loc, tmp);
+					av = new CommaExp(loc, av, new VarExp(loc, tmp));
+
+					Expression e;
+					CtorDeclaration cf = ad.ctor.isCtorDeclaration();
+					if (cf)
+						e = new DotVarExp(loc, av, cf, 1);
+					else
+					{   
+						TemplateDeclaration td = ad.ctor.isTemplateDeclaration();
+						assert(td);
+						e = new DotTemplateExp(loc, av, td);
+					}
+					e = new CallExp(loc, e, arguments);
+			version (STRUCTTHISREF) {
+			} else {
+					/* Constructors return a pointer to the instance
+					 */
+					e = new PtrExp(loc, e);
+			}
+					e = e.semantic(sc);
+					return e;
+				}
+}
+				// No constructor, look for overload of opCall
+				if (search_function(ad, Id.call))
+					goto L1;	// overload of opCall, therefore it's a call
+
+				if (e1.op != TOK.TOKtype)
+					error("%s %s does not overload ()", ad.kind(), ad.toChars());
+				
+				/* It's a struct literal
+				 */
+				Expression e = new StructLiteralExp(loc, cast(StructDeclaration)ad, arguments);
+				e = e.semantic(sc);
+				e.type = e1.type;		// in case e1.type was a typedef
+				return e;
+			}
+			else if (t1.ty == TY.Tclass)
+			{
+				ad = (cast(TypeClass)t1).sym;
+				goto L1;
+			L1:
+				// Rewrite as e1.call(arguments)
+				Expression e = new DotIdExp(loc, e1, Id.call);
+				e = new CallExp(loc, e, arguments);
+				e = e.semantic(sc);
+				return e;
+			}
+		}
+
+		arrayExpressionSemantic(arguments, sc);
+		preFunctionArguments(loc, sc, arguments);
+
+		if (e1.op == TOK.TOKdotvar && t1.ty == TY.Tfunction ||
+			e1.op == TOK.TOKdottd)
+		{
+			DotVarExp dve;
+			DotTemplateExp dte;
+			AggregateDeclaration ad;
+			UnaExp ue = cast(UnaExp)e1;
+
+			if (e1.op == TOK.TOKdotvar)
+			{   
+				// Do overload resolution
+				dve = cast(DotVarExp)e1;
+
+				f = dve.var.isFuncDeclaration();
+				assert(f);
+				f = f.overloadResolve(loc, ue.e1, arguments);
+
+				ad = f.toParent().isAggregateDeclaration();
+			}
+			else
+			{   
+				dte = cast(DotTemplateExp)e1;
+				TemplateDeclaration td = dte.td;
+				assert(td);
+
+				if (!arguments)
+					// Should fix deduceFunctionTemplate() so it works on null argument
+					arguments = new Expressions();
+
+				f = td.deduceFunctionTemplate(sc, loc, targsi, ue.e1, arguments);
+				if (!f)
+				{	
+					type = Type.terror;
+					return this;
+				}
+				ad = td.toParent().isAggregateDeclaration();
+			}
+
+			if (f.needThis())
+			{
+				ue.e1 = getRightThis(loc, sc, ad, ue.e1, f);
+			}
+
+			/* Cannot call public functions from inside invariant
+			 * (because then the invariant would have infinite recursion)
+			 */
+			if (sc.func && sc.func.isInvariantDeclaration() &&
+				ue.e1.op == TOK.TOKthis && f.addPostInvariant())
+			{
+				error("cannot call public/export function %s from invariant", f.toChars());
+			}
+
+			checkDeprecated(sc, f);
+	version (DMDV2) {
+			checkPurity(sc, f);
+	}
+			accessCheck(loc, sc, ue.e1, f);
+			if (!f.needThis())
+			{
+				VarExp ve = new VarExp(loc, f);
+				e1 = new CommaExp(loc, ue.e1, ve);
+				e1.type = f.type;
+			}
+			else
+			{
+				if (e1.op == TOK.TOKdotvar)		
+					dve.var = f;
+				else
+					e1 = new DotVarExp(loc, dte.e1, f);
+
+				e1.type = f.type;
+static if (false) {
+				printf("ue.e1 = %s\n", ue.e1.toChars());
+				printf("f = %s\n", f.toChars());
+				printf("t = %s\n", t.toChars());
+				printf("e1 = %s\n", e1.toChars());
+				printf("e1.type = %s\n", e1.type.toChars());
+}
+				// Const member function can take const/immutable/mutable this
+				if (!(f.type.isConst()))
+				{
+					// Check for const/immutable compatibility
+					Type tthis = ue.e1.type.toBasetype();
+					if (tthis.ty == TY.Tpointer)
+						tthis = tthis.nextOf().toBasetype();
+
+	static if (false) {	// this checking should have been already done
+					if (f.type.isInvariant())
+					{
+						if (tthis.mod != MOD.MODinvariant)
+							error("%s can only be called with an immutable object", e1.toChars());
+					}
+					else if (f.type.isShared())
+					{
+						if (tthis.mod != MOD.MODinvariant && tthis.mod != MOD.MODshared && tthis.mod != (MOD.MODshared | MOD.MODconst))
+							error("shared %s can only be called with a shared or immutable object", e1.toChars());
+					}
+					else
+					{
+						if (tthis.mod != MOD.MODundefined)
+						{	
+							//printf("mod = %x\n", tthis.mod);
+							error("%s can only be called with a mutable object, not %s", e1.toChars(), tthis.toChars());
+						}
+					}
+	}
+					/* Cannot call mutable method on a final struct
+					 */
+					if (tthis.ty == TY.Tstruct &&
+						ue.e1.op == TOK.TOKvar)
+					{
+						VarExp v = cast(VarExp)ue.e1;
+						if (v.var.storage_class & STC.STCfinal)
+							error("cannot call mutable method on final struct");
+					}
+				}
+
+				// See if we need to adjust the 'this' pointer
+				AggregateDeclaration add = f.isThis();
+				ClassDeclaration cd = ue.e1.type.isClassHandle();
+				if (add && cd && add.isClassDeclaration() && add != cd && ue.e1.op != TOK.TOKsuper)
+				{
+					ue.e1 = ue.e1.castTo(sc, add.type); //new CastExp(loc, ue.e1, add.type);
+					ue.e1 = ue.e1.semantic(sc);
+				}
+			}
+			t1 = e1.type;
+		}
+		else if (e1.op == TOK.TOKsuper)
+		{
+			// Base class constructor call
+			ClassDeclaration cd = null;
+
+			if (sc.func)
+				cd = sc.func.toParent().isClassDeclaration();
+			if (!cd || !cd.baseClass || !sc.func.isCtorDeclaration())
+			{
+				error("super class constructor call must be in a constructor");
+				type = Type.terror;
+				return this;
+			}
+			else
+			{
+				if (!cd.baseClass.ctor)
+				{	
+					error("no super class constructor for %s", cd.baseClass.toChars());
+					type = Type.terror;
+					return this;
+				}
+				else
+				{
+					if (!sc.intypeof)
+					{
+static if (false) {
+						if (sc.callSuper & (CSX.CSXthis | CSX.CSXsuper))
+							error("reference to this before super()");
+}
+						if (sc.noctor || sc.callSuper & CSX.CSXlabel)
+							error("constructor calls not allowed in loops or after labels");
+						if (sc.callSuper & (CSX.CSXsuper_ctor | CSX.CSXthis_ctor))
+							error("multiple constructor calls");
+						sc.callSuper |= CSX.CSXany_ctor | CSX.CSXsuper_ctor;
+					}
+
+					f = resolveFuncCall(sc, loc, cd.baseClass.ctor, null, null, arguments, 0);
+					checkDeprecated(sc, f);
+version (DMDV2) {
+					checkPurity(sc, f);
+}
+					e1 = new DotVarExp(e1.loc, e1, f);
+					e1 = e1.semantic(sc);
+					t1 = e1.type;
+				}
+			}
+		}
+		else if (e1.op == TOK.TOKthis)
+		{
+			// same class constructor call
+			AggregateDeclaration cd = null;
+
+			if (sc.func)
+				cd = sc.func.toParent().isAggregateDeclaration();
+			if (!cd || !sc.func.isCtorDeclaration())
+			{
+				error("constructor call must be in a constructor");
+				type = Type.terror;
+				return this;
+			}
+			else
+			{
+				if (!sc.intypeof)
+				{
+static if (false) {
+					if (sc.callSuper & (CSXthis | CSXsuper))
+						error("reference to this before super()");
+}
+					if (sc.noctor || sc.callSuper & CSX.CSXlabel)
+						error("constructor calls not allowed in loops or after labels");
+					if (sc.callSuper & (CSX.CSXsuper_ctor | CSX.CSXthis_ctor))
+						error("multiple constructor calls");
+					sc.callSuper |= CSX.CSXany_ctor | CSX.CSXthis_ctor;
+				}
+
+				f = resolveFuncCall(sc, loc, cd.ctor, null, null, arguments, 0);
+				checkDeprecated(sc, f);
+version (DMDV2) {
+				checkPurity(sc, f);
+}
+				e1 = new DotVarExp(e1.loc, e1, f);
+				e1 = e1.semantic(sc);
+				t1 = e1.type;
+
+				// BUG: this should really be done by checking the static
+				// call graph
+				if (f == sc.func)
+					error("cyclic constructor call");
+			}
+		}
+		else if (e1.op == TOK.TOKoverloadset)
+		{
+			OverExp eo = cast(OverExp)e1;
+			FuncDeclaration ff = null;
+			for (int j = 0; j < eo.vars.a.dim; j++)
+			{   
+				Dsymbol s = cast(Dsymbol)eo.vars.a.data[j];
+				FuncDeclaration f2 = s.isFuncDeclaration();
+				if (f2)
+				{
+					f2 = f2.overloadResolve(loc, null, arguments, 1);
+				}
+				else
+				{	
+					TemplateDeclaration td = s.isTemplateDeclaration();
+					assert(td);
+					f2 = td.deduceFunctionTemplate(sc, loc, targsi, null, arguments, 1);
+				}
+				if (f2)
+				{	
+					if (ff)
+						/* Error if match in more than one overload set,
+						 * even if one is a 'better' match than the other.
+						 */
+						ScopeDsymbol.multiplyDefined(loc, ff, f2);
+					else
+						ff = f2;
+				}
+			}
+			if (!ff)
+			{   
+				/* No overload matches, just set ff and rely on error
+				 * message being generated later.
+				 */
+				ff = cast(FuncDeclaration)eo.vars.a.data[0];
+			}
+			e1 = new VarExp(loc, ff);
+			goto Lagain;
+		}
+		else if (!t1)
+		{
+			error("function expected before (), not '%s'", e1.toChars());
+			type = Type.terror;
+			return this;
+		}
+		else if (t1.ty != TY.Tfunction)
+		{
+			if (t1.ty == TY.Tdelegate)
+			{   
+				TypeDelegate td = cast(TypeDelegate)t1;
+				assert(td.next.ty == TY.Tfunction);
+				tf = cast(TypeFunction)(td.next);
+				if (sc.func && sc.func.isPure() && !tf.ispure)
+				{
+					error("pure function '%s' cannot call impure delegate '%s'", sc.func.toChars(), e1.toChars());
+				}
+				goto Lcheckargs;
+			}
+			else if (t1.ty == TY.Tpointer && (cast(TypePointer)t1).next.ty == TY.Tfunction)
+			{   
+				Expression e = new PtrExp(loc, e1);
+				t1 = (cast(TypePointer)t1).next;
+				if (sc.func && sc.func.isPure() && !(cast(TypeFunction)t1).ispure)
+				{
+					error("pure function '%s' cannot call impure function pointer '%s'", sc.func.toChars(), e1.toChars());
+				}
+				e.type = t1;
+				e1 = e;
+			}
+			else if (e1.op == TOK.TOKtemplate)
+			{
+				TemplateExp te = cast(TemplateExp)e1;
+				f = te.td.deduceFunctionTemplate(sc, loc, targsi, null, arguments);
+				if (!f)
+				{	
+					if (tierror)
+						tierror.error("errors instantiating template");	// give better error message
+					type = Type.terror;
+					return this;
+				}
+				if (f.needThis() && hasThis(sc))
+				{
+					// Supply an implicit 'this', as in
+					//	  this.ident
+
+					e1 = new DotTemplateExp(loc, (new ThisExp(loc)).semantic(sc), te.td);
+					goto Lagain;
+				}
+
+				e1 = new VarExp(loc, f);
+				goto Lagain;
+			}
+			else
+			{   
+				error("function expected before (), not %s of type %s", e1.toChars(), e1.type.toChars());
+				type = Type.terror;
+				return this;
+			}
+		}
+		else if (e1.op == TOK.TOKvar)
+		{
+			// Do overload resolution
+			VarExp ve = cast(VarExp)e1;
+
+			f = ve.var.isFuncDeclaration();
+			assert(f);
+
+			if (ve.hasOverloads)
+				f = f.overloadResolve(loc, null, arguments);
+
+			checkDeprecated(sc, f);
+version (DMDV2) {
+			checkPurity(sc, f);
+}
+
+			if (f.needThis() && hasThis(sc))
+			{
+				// Supply an implicit 'this', as in
+				//	  this.ident
+
+				e1 = new DotVarExp(loc, new ThisExp(loc), f);
+				goto Lagain;
+			}
+
+			accessCheck(loc, sc, null, f);
+
+			ve.var = f;
+		//	ve.hasOverloads = 0;
+			ve.type = f.type;
+			t1 = f.type;
+		}
+		assert(t1.ty == TY.Tfunction);
+		tf = cast(TypeFunction)t1;
+
+	Lcheckargs:
+		assert(tf.ty == TY.Tfunction);
+		type = tf.next;
+
+		if (!arguments)
+			arguments = new Expressions();
+
+		functionArguments(loc, sc, tf, arguments);
+
+		if (!type)
+		{
+			error("forward reference to inferred return type of function call %s", toChars());
+			type = Type.terror;
+		}
+
+		if (f && f.tintro)
+		{
+			Type t = type;
+			int offset = 0;
+			TypeFunction tff = cast(TypeFunction)f.tintro;
+
+			if (tff.next.isBaseOf(t, &offset) && offset)
+			{
+				type = tff.next;
+				return castTo(sc, t);
+			}
+		}
+
+		return this;
 	}
 
-	Expression optimize(int result)
+	override Expression optimize(int result)
 	{
-		//printf("CallExp::optimize(result = %d) %s\n", result, toChars());
-		Expression e = this;
-
-		// Optimize parameters
-		if (arguments)
-		{
-			for (size_t i = 0; i < arguments.dim; i++)
-			{   
-				Expression ee = cast(Expression)arguments.data[i];
-
-				ee = ee.optimize(WANT.WANTvalue);
-				arguments.data[i] = cast(void*)ee;
-			}
-		}
-
-		e1 = e1.optimize(result);
-		if (e1.op == TOK.TOKvar)
-		{
-			FuncDeclaration fd = (cast(VarExp)e1).var.isFuncDeclaration();
-			if (fd)
-			{
-				BUILTIN b = fd.isBuiltin();
-				if (b)
-				{
-					e = eval_builtin(b, arguments);
-					if (!e)			// failed
-						e = this;		// evaluate at runtime
-				}
-				else if (result & WANT.WANTinterpret)
-				{
-					Expression eresult = fd.interpret(null, arguments);
-					if (eresult && eresult !is EXP_VOID_INTERPRET)
-						e = eresult;
-					else
-						error("cannot evaluate %s at compile time", toChars());
-				}
-			}
-		}
-
+		//printf("CallExp::optimize(result = %d) %s\n", result, toChars());
+		Expression e = this;
+
+		// Optimize parameters
+		if (arguments)
+		{
+			for (size_t i = 0; i < arguments.dim; i++)
+			{   
+				Expression ee = cast(Expression)arguments.data[i];
+
+				ee = ee.optimize(WANT.WANTvalue);
+				arguments.data[i] = cast(void*)ee;
+			}
+		}
+
+		e1 = e1.optimize(result);
+		if (e1.op == TOK.TOKvar)
+		{
+			FuncDeclaration fd = (cast(VarExp)e1).var.isFuncDeclaration();
+			if (fd)
+			{
+				BUILTIN b = fd.isBuiltin();
+				if (b)
+				{
+					e = eval_builtin(b, arguments);
+					if (!e)			// failed
+						e = this;		// evaluate at runtime
+				}
+				else if (result & WANT.WANTinterpret)
+				{
+					Expression eresult = fd.interpret(null, arguments);
+					if (eresult && eresult !is EXP_VOID_INTERPRET)
+						e = eresult;
+					else
+						error("cannot evaluate %s at compile time", toChars());
+				}
+			}
+		}
+
 		return e;
 	}
 
-	Expression interpret(InterState istate)
+	override Expression interpret(InterState istate)
 	{
-		Expression e = EXP_CANT_INTERPRET;
-
-version (LOG) {
-		printf("CallExp.interpret() %.*s\n", toChars());
-}
-		if (e1.op == TOKdotvar)
-		{
-			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);
-				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++)
-					{
-						Expression earg = cast(Expression)arguments.data[i];
-						earg = earg.interpret(istate);
-						if (earg == EXP_CANT_INTERPRET)
-							return earg;
-						args.data[i] = cast(void*)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 = cast(Expression)arguments.data[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());
-				}
-			}
-		}
+		Expression e = EXP_CANT_INTERPRET;
+
+version (LOG) {
+		printf("CallExp.interpret() %.*s\n", toChars());
+}
+		if (e1.op == TOKdotvar)
+		{
+			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);
+				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++)
+					{
+						Expression earg = cast(Expression)arguments.data[i];
+						earg = earg.interpret(istate);
+						if (earg == EXP_CANT_INTERPRET)
+							return earg;
+						args.data[i] = cast(void*)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 = cast(Expression)arguments.data[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;
 	}
 
-	bool checkSideEffect(int flag)
+	override bool checkSideEffect(int flag)
 	{
-version (DMDV2) {
-		if (flag != 2)
-			return true;
-
-		if (e1.checkSideEffect(2))
-			return true;
-
-		/* If any of the arguments have side effects, this expression does
-		 */
-		for (size_t i = 0; i < arguments.dim; i++)
-		{   
-			Expression e = cast(Expression)arguments.data[i];
-
-			if (e.checkSideEffect(2))
-				return true;
-		}
-
-		/* If calling a function or delegate that is typed as pure,
-		 * then this expression has no side effects.
-		 */
-		Type t = e1.type.toBasetype();
-		if (t.ty == TY.Tfunction && (cast(TypeFunction)t).ispure)
-			return false;
-		if (t.ty == TY.Tdelegate && (cast(TypeFunction)(cast(TypeDelegate)t).next).ispure)
-			return false;
-}
+version (DMDV2) {
+		if (flag != 2)
+			return true;
+
+		if (e1.checkSideEffect(2))
+			return true;
+
+		/* If any of the arguments have side effects, this expression does
+		 */
+		for (size_t i = 0; i < arguments.dim; i++)
+		{   
+			Expression e = cast(Expression)arguments.data[i];
+
+			if (e.checkSideEffect(2))
+				return true;
+		}
+
+		/* If calling a function or delegate that is typed as pure,
+		 * then this expression has no side effects.
+		 */
+		Type t = e1.type.toBasetype();
+		if (t.ty == TY.Tfunction && (cast(TypeFunction)t).ispure)
+			return false;
+		if (t.ty == TY.Tdelegate && (cast(TypeFunction)(cast(TypeDelegate)t).next).ispure)
+			return false;
+}
 		return true;
 	}
 
-	void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	override void toCBuffer(OutBuffer buf, HdrGenState* hgs)
 	{
-		int i;
-		expToCBuffer(buf, hgs, e1, precedence[op]);
-		buf.writeByte('(');
-		argsToCBuffer(buf, arguments, hgs);
+		int i;
+		expToCBuffer(buf, hgs, e1, precedence[op]);
+		buf.writeByte('(');
+		argsToCBuffer(buf, arguments, hgs);
 		buf.writeByte(')');
 	}
 
-	void dump(int indent)
+	override void dump(int indent)
 	{
 		assert(false);
 	}
 
-	elem* toElem(IRState* irs)
+	override elem* toElem(IRState* irs)
 	{
-		//printf("CallExp::toElem('%s')\n", toChars());
-		assert(e1.type);
-		elem* ec;
-		int directcall;
-		FuncDeclaration fd;
-		Type t1 = e1.type.toBasetype();
-		Type ectype = t1;
-
-		elem* ehidden = irs.ehidden;
-		irs.ehidden = null;
-
-		directcall = 0;
-		fd = null;
-		if (e1.op == TOK.TOKdotvar && t1.ty != TY.Tdelegate)
-		{	
-			DotVarExp dve = cast(DotVarExp)e1;
-
-			fd = dve.var.isFuncDeclaration();
-			Expression ex = dve.e1;
-			while (1)
-			{
-				switch (ex.op)
-				{
-				case TOK.TOKsuper:		// super.member() calls directly
-				case TOK.TOKdottype:	// type.member() calls directly
-					directcall = 1;
-					break;
-
-				case TOK.TOKcast:
-					ex = (cast(CastExp)ex).e1;
-					continue;
-
-				default:
-					//ex.dump(0);
-					break;
-				}
-				break;
-			}
-			ec = dve.e1.toElem(irs);
-			ectype = dve.e1.type.toBasetype();
-		}
-		else if (e1.op == TOK.TOKvar)
-		{
-			fd = (cast(VarExp)e1).var.isFuncDeclaration();
-
-			if (fd && fd.ident == Id.alloca && !fd.fbody && fd.linkage == LINK.LINKc && arguments && arguments.dim == 1)
-			{   
-				Expression arg = cast(Expression)arguments.data[0];
-				arg = arg.optimize(WANT.WANTvalue);
-				if (arg.isConst() && arg.type.isintegral())
-				{	
-					long sz = arg.toInteger();
-					if (sz > 0 && sz < 0x40000)
-					{
-						// It's an alloca(sz) of a fixed amount.
-						// Replace with an array allocated on the stack
-						// of the same size: char[sz] tmp;
-
-						Symbol* stmp;
-						.type* t;
-
-						assert(!ehidden);
-						t = type_allocn(TYM.TYarray, tschar);
-						t.Tdim = cast(uint)sz;
-						stmp = symbol_genauto(t);
-						ec = el_ptr(stmp);
-						el_setLoc(ec,loc);
-						return ec;
-					}
-				}
-			}
-
-			ec = e1.toElem(irs);
-		}
-		else
-		{
-			ec = e1.toElem(irs);
-		}
-		ec = callfunc(loc, irs, directcall, type, ec, ectype, fd, t1, ehidden, arguments);
-		el_setLoc(ec,loc);
+		//printf("CallExp::toElem('%s')\n", toChars());
+		assert(e1.type);
+		elem* ec;
+		int directcall;
+		FuncDeclaration fd;
+		Type t1 = e1.type.toBasetype();
+		Type ectype = t1;
+
+		elem* ehidden = irs.ehidden;
+		irs.ehidden = null;
+
+		directcall = 0;
+		fd = null;
+		if (e1.op == TOK.TOKdotvar && t1.ty != TY.Tdelegate)
+		{	
+			DotVarExp dve = cast(DotVarExp)e1;
+
+			fd = dve.var.isFuncDeclaration();
+			Expression ex = dve.e1;
+			while (1)
+			{
+				switch (ex.op)
+				{
+				case TOK.TOKsuper:		// super.member() calls directly
+				case TOK.TOKdottype:	// type.member() calls directly
+					directcall = 1;
+					break;
+
+				case TOK.TOKcast:
+					ex = (cast(CastExp)ex).e1;
+					continue;
+
+				default:
+					//ex.dump(0);
+					break;
+				}
+				break;
+			}
+			ec = dve.e1.toElem(irs);
+			ectype = dve.e1.type.toBasetype();
+		}
+		else if (e1.op == TOK.TOKvar)
+		{
+			fd = (cast(VarExp)e1).var.isFuncDeclaration();
+
+			if (fd && fd.ident == Id.alloca && !fd.fbody && fd.linkage == LINK.LINKc && arguments && arguments.dim == 1)
+			{   
+				Expression arg = cast(Expression)arguments.data[0];
+				arg = arg.optimize(WANT.WANTvalue);
+				if (arg.isConst() && arg.type.isintegral())
+				{	
+					long sz = arg.toInteger();
+					if (sz > 0 && sz < 0x40000)
+					{
+						// It's an alloca(sz) of a fixed amount.
+						// Replace with an array allocated on the stack
+						// of the same size: char[sz] tmp;
+
+						Symbol* stmp;
+						.type* t;
+
+						assert(!ehidden);
+						t = type_allocn(TYM.TYarray, tschar);
+						t.Tdim = cast(uint)sz;
+						stmp = symbol_genauto(t);
+						ec = el_ptr(stmp);
+						el_setLoc(ec,loc);
+						return ec;
+					}
+				}
+			}
+
+			ec = e1.toElem(irs);
+		}
+		else
+		{
+			ec = e1.toElem(irs);
+		}
+		ec = callfunc(loc, irs, directcall, type, ec, ectype, fd, t1, ehidden, arguments);
+		el_setLoc(ec,loc);
 		return ec;
 	}
 
-	void scanForNestedRef(Scope sc)
+	override void scanForNestedRef(Scope sc)
 	{
-		//printf("CallExp.scanForNestedRef(Scope *sc): %s\n", toChars());
-		e1.scanForNestedRef(sc);
+		//printf("CallExp.scanForNestedRef(Scope *sc): %s\n", toChars());
+		e1.scanForNestedRef(sc);
 		arrayExpressionScanForNestedRef(sc, arguments);
-	}
+	}
 	
 version (DMDV2) {
-	int isLvalue()
+	override int isLvalue()
 	{
-		//    if (type.toBasetype().ty == Tstruct)
-		//	return 1;
-		Type tb = e1.type.toBasetype();
-		if (tb.ty == Tfunction && (cast(TypeFunction)tb).isref)
-			return 1;		// function returns a reference
+		//    if (type.toBasetype().ty == Tstruct)
+		//	return 1;
+		Type tb = e1.type.toBasetype();
+		if (tb.ty == Tfunction && (cast(TypeFunction)tb).isref)
+			return 1;		// function returns a reference
 		return 0;
 	}
 }
-	Expression toLvalue(Scope sc, Expression e)
+	override Expression toLvalue(Scope sc, Expression e)
 	{
-		if (isLvalue())
-			return this;
+		if (isLvalue())
+			return this;
 		return Expression.toLvalue(sc, e);
-	}
+	}
 
 version (DMDV2) {
-	bool canThrow()
+	override bool canThrow()
 	{
-		//printf("CallExp::canThrow() %s\n", toChars());
-		if (e1.canThrow())
-			return true;
-
-		/* If any of the arguments can throw, then this expression can throw
-		 */
-		for (size_t i = 0; i < arguments.dim; i++)
-		{   
-			Expression e = cast(Expression)arguments.data[i];
-
-			if (e && e.canThrow())
-				return true;
-		}
-
-		if (global.errors && !e1.type)
-			return false;			// error recovery
-
-		/* If calling a function or delegate that is typed as nothrow,
-		 * then this expression cannot throw.
-		 * Note that pure functions can throw.
-		 */
-		Type t = e1.type.toBasetype();
-		if (t.ty == TY.Tfunction && (cast(TypeFunction)t).isnothrow)
-			return false;
-		if (t.ty == TY.Tdelegate && (cast(TypeFunction)(cast(TypeDelegate)t).next).isnothrow)
-			return false;
-
+		//printf("CallExp::canThrow() %s\n", toChars());
+		if (e1.canThrow())
+			return true;
+
+		/* If any of the arguments can throw, then this expression can throw
+		 */
+		for (size_t i = 0; i < arguments.dim; i++)
+		{   
+			Expression e = cast(Expression)arguments.data[i];
+
+			if (e && e.canThrow())
+				return true;
+		}
+
+		if (global.errors && !e1.type)
+			return false;			// error recovery
+
+		/* If calling a function or delegate that is typed as nothrow,
+		 * then this expression cannot throw.
+		 * Note that pure functions can throw.
+		 */
+		Type t = e1.type.toBasetype();
+		if (t.ty == TY.Tfunction && (cast(TypeFunction)t).isnothrow)
+			return false;
+		if (t.ty == TY.Tdelegate && (cast(TypeFunction)(cast(TypeDelegate)t).next).isnothrow)
+			return false;
+
 		return true;
 	}
 }
-	int inlineCost(InlineCostState* ics)
+	override int inlineCost(InlineCostState* ics)
 	{
 		return 1 + e1.inlineCost(ics) + arrayInlineCost(ics, arguments);
 	}
 
-	Expression doInline(InlineDoState ids)
+	override Expression doInline(InlineDoState ids)
 	{
-		CallExp ce = cast(CallExp)copy();
-		ce.e1 = e1.doInline(ids);
-		ce.arguments = arrayExpressiondoInline(arguments, ids);
+		CallExp ce = cast(CallExp)copy();
+		ce.e1 = e1.doInline(ids);
+		ce.arguments = arrayExpressiondoInline(arguments, ids);
 		return ce;
 	}
 
-	Expression inlineScan(InlineScanState* iss)
+	override Expression inlineScan(InlineScanState* iss)
 	{
-		Expression e = this;
-
-		//printf("CallExp.inlineScan()\n");
-		e1 = e1.inlineScan(iss);
-		arrayInlineScan(iss, arguments);
-
-		if (e1.op == TOKvar)
-		{
-			VarExp ve = cast(VarExp)e1;
-			FuncDeclaration fd = ve.var.isFuncDeclaration();
-
-			if (fd && fd != iss.fd && fd.canInline(0))
-			{
-				e = fd.doInline(iss, null, arguments);
-			}
-		}
-		else if (e1.op == TOKdotvar)
-		{
-			DotVarExp dve = cast(DotVarExp)e1;
-			FuncDeclaration fd = dve.var.isFuncDeclaration();
-
-			if (fd && fd != iss.fd && fd.canInline(1))
-			{
-				if (dve.e1.op == TOKcall &&
-					dve.e1.type.toBasetype().ty == Tstruct)
-				{
-					/* To create ethis, we'll need to take the address
-					 * of dve.e1, but this won't work if dve.e1 is
-					 * a function call.
-					 */
-					;
-				}
-				else
-					e = fd.doInline(iss, dve.e1, arguments);
-			}
-		}
-
+		Expression e = this;
+
+		//printf("CallExp.inlineScan()\n");
+		e1 = e1.inlineScan(iss);
+		arrayInlineScan(iss, arguments);
+
+		if (e1.op == TOKvar)
+		{
+			VarExp ve = cast(VarExp)e1;
+			FuncDeclaration fd = ve.var.isFuncDeclaration();
+
+			if (fd && fd != iss.fd && fd.canInline(0))
+			{
+				e = fd.doInline(iss, null, arguments);
+			}
+		}
+		else if (e1.op == TOKdotvar)
+		{
+			DotVarExp dve = cast(DotVarExp)e1;
+			FuncDeclaration fd = dve.var.isFuncDeclaration();
+
+			if (fd && fd != iss.fd && fd.canInline(1))
+			{
+				if (dve.e1.op == TOKcall &&
+					dve.e1.type.toBasetype().ty == Tstruct)
+				{
+					/* To create ethis, we'll need to take the address
+					 * of dve.e1, but this won't work if dve.e1 is
+					 * a function call.
+					 */
+					;
+				}
+				else
+					e = fd.doInline(iss, dve.e1, arguments);
+			}
+		}
+
 		return e;
 	}
 }