changeset 73:ef02e2e203c2

Updating to dmd2.033
author korDen
date Sat, 28 Aug 2010 19:42:41 +0400
parents 2e2a5c3f943a
children 7e0d548de9e6
files commands.txt dbg/CallStackInfo.d dmd/AddAssignExp.d dmd/ArrayInitializer.d dmd/BinExp.d dmd/CallExp.d dmd/CastExp.d dmd/ClassDeclaration.d dmd/DelegateExp.d dmd/DivAssignExp.d dmd/DotVarExp.d dmd/Dsymbol.d dmd/DsymbolExp.d dmd/ErrorExp.d dmd/ExpInitializer.d dmd/Expression.d dmd/ForeachStatement.d dmd/FuncDeclaration.d dmd/Global.d dmd/Id.d dmd/IdentityExp.d dmd/IndexExp.d dmd/IntegerExp.d dmd/Lexer.d dmd/MinAssignExp.d dmd/ModAssignExp.d dmd/Module.d dmd/MulAssignExp.d dmd/RealExp.d dmd/ReturnStatement.d dmd/SymOffExp.d dmd/SymbolExp.d dmd/TOK.d dmd/Type.d dmd/TypeAArray.d dmd/TypeClass.d dmd/TypeEnum.d dmd/TypeFunction.d dmd/TypeInfoArrayDeclaration.d dmd/TypeInfoAssociativeArrayDeclaration.d dmd/TypeInfoClassDeclaration.d dmd/TypeInfoConstDeclaration.d dmd/TypeInfoDelegateDeclaration.d dmd/TypeInfoEnumDeclaration.d dmd/TypeInfoFunctionDeclaration.d dmd/TypeInfoInterfaceDeclaration.d dmd/TypeInfoInvariantDeclaration.d dmd/TypeInfoPointerDeclaration.d dmd/TypeInfoSharedDeclaration.d dmd/TypeInfoStaticArrayDeclaration.d dmd/TypeInfoStructDeclaration.d dmd/TypeInfoTupleDeclaration.d dmd/TypeInfoTypedefDeclaration.d dmd/TypeQualified.d dmd/TypeStruct.d dmd/TypeTypedef.d dmd/VarDeclaration.d dmd/VarExp.d dmd/backend/F.d dmd/codegen/Util.d dmd/expression/Equal.d dmd/expression/Util.d rt/memory.d
diffstat 63 files changed, 2551 insertions(+), 2056 deletions(-) [+]
line wrap: on
line diff
--- a/commands.txt	Sat Aug 28 16:19:48 2010 +0200
+++ b/commands.txt	Sat Aug 28 19:42:41 2010 +0400
@@ -14,10 +14,10 @@
 -version=SEH
 -version=OMFOBJ
 -version=SNAN_DEFAULT_INIT
--ofbin\dmd.exe
+-ofC:\dmd2.033\windows\bin\dmd.exe
 bridge.obj
 ddmd.def
-dmd.lib
+C:\dmd2.033\src\dmd\dmd.lib
 main.d
 dbg\CallStackInfo.d
 dbg\Debug.d
@@ -333,6 +333,7 @@
 dmd\TypeTypeof.d
 dmd\TypedefDeclaration.d
 dmd\TypeInfoTupleDeclaration
+dmd\TypeInfoFunctionDeclaration
 dmd\UnionDeclaration.d
 dmd\UnitTestDeclaration.d
 dmd\Utf.d
--- a/dbg/CallStackInfo.d	Sat Aug 28 16:19:48 2010 +0200
+++ b/dbg/CallStackInfo.d	Sat Aug 28 19:42:41 2010 +0400
@@ -193,7 +193,7 @@
 alias LONG function(EXCEPTION_POINTERS*) PTOP_LEVEL_EXCEPTION_FILTER;
 extern (Windows) PTOP_LEVEL_EXCEPTION_FILTER SetUnhandledExceptionFilter(PTOP_LEVEL_EXCEPTION_FILTER);
 
-void append(T)(T[] array, ref size_t index, T value)
+void append(T)(ref T[] array, ref size_t index, T value)
 {
 	size_t capacity = array.length;
 	assert(capacity >= index);
@@ -201,8 +201,10 @@
 		if (capacity < 8) {
 			capacity = 8;
 		} else {
-			array.length = capacity * 2;
+			capacity *= 2;
 		}
+		
+		array.length = capacity;
 	}
 	
 	array[index++] = value;
--- a/dmd/AddAssignExp.d	Sat Aug 28 16:19:48 2010 +0200
+++ b/dmd/AddAssignExp.d	Sat Aug 28 19:42:41 2010 +0400
@@ -126,6 +126,7 @@
 				typeCombine(sc);
 				e1.checkArithmetic();
 				e2.checkArithmetic();
+			    checkComplexAddAssign();
 
 				if (type.isreal() || type.isimaginary())
 				{
--- a/dmd/ArrayInitializer.d	Sat Aug 28 16:19:48 2010 +0200
+++ b/dmd/ArrayInitializer.d	Sat Aug 28 19:42:41 2010 +0400
@@ -158,6 +158,7 @@
 
 	/********************************
 	 * If possible, convert array initializer to array literal.
+	  * Otherwise return null.
 	 */	
     override Expression toExpression()
 	{
@@ -238,9 +239,7 @@
 		}
 
 	Lno:
-		delete elements;
-		error(loc, "array initializers as expressions are not allowed");
-		return new ErrorExp();
+	    return null;
 	}
 	
     Initializer toAssocArrayInitializer()
--- a/dmd/BinExp.d	Sat Aug 28 16:19:48 2010 +0200
+++ b/dmd/BinExp.d	Sat Aug 28 19:42:41 2010 +0400
@@ -1328,6 +1328,46 @@
 	{
 		return e1.canThrow() || e2.canThrow();
 	}
+	
+	// generate an error if this is a nonsensical *=,/=, or %=, eg real *= imaginary
+	void checkComplexMulAssign()
+	{
+		// Any multiplication by an imaginary or complex number yields a complex result.
+		// r *= c, i*=c, r*=i, i*=i are all forbidden operations.
+		string opstr = Token.toChars(op);
+		if ( e1.type.isreal() && e2.type.iscomplex())
+		{
+			error("%s %s %s is undefined. Did you mean %s %s %s.re ?",
+				e1.type.toChars(), opstr, e2.type.toChars(), 
+				e1.type.toChars(), opstr, e2.type.toChars());
+		}
+		else if (e1.type.isimaginary() && e2.type.iscomplex())
+		{
+			error("%s %s %s is undefined. Did you mean %s %s %s.im ?",
+				e1.type.toChars(), opstr, e2.type.toChars(),
+				e1.type.toChars(), opstr, e2.type.toChars());
+		}
+		else if ((e1.type.isreal() || e1.type.isimaginary()) && e2.type.isimaginary())
+		{
+			error("%s %s %s is an undefined operation", e1.type.toChars(),
+			opstr, e2.type.toChars());
+		}
+	}
+
+	// generate an error if this is a nonsensical += or -=, eg real += imaginary
+	void checkComplexAddAssign()
+	{
+		// Addition or subtraction of a real and an imaginary is a complex result.
+		// Thus, r+=i, r+=c, i+=r, i+=c are all forbidden operations.
+		if ( (e1.type.isreal() && (e2.type.isimaginary() || e2.type.iscomplex())) ||
+			 (e1.type.isimaginary() && (e2.type.isreal() || e2.type.iscomplex()))        
+			)
+		{
+			error("%s %s %s is undefined (result is complex)",
+			e1.type.toChars(), Token.toChars(op), e2.type.toChars());
+		}
+	}
+
 
 	/***********************************
 	 * Construct the array operation expression.
@@ -1335,6 +1375,13 @@
     Expression arrayOp(Scope sc)
 	{
 		//printf("BinExp.arrayOp() %s\n", toChars());
+		
+		if (type.toBasetype().nextOf().toBasetype().ty == Tvoid)
+		{
+			error("Cannot perform array operations on void[] arrays");
+			return new ErrorExp();
+		}
+			
 		Expressions arguments = new Expressions();
 
 		/* The expression to generate an array operation for is mangled
--- a/dmd/CallExp.d	Sat Aug 28 16:19:48 2010 +0200
+++ b/dmd/CallExp.d	Sat Aug 28 19:42:41 2010 +0400
@@ -93,9 +93,11 @@
 		super(loc, TOK.TOKcall, CallExp.sizeof, e);
 		
 		Expressions arguments = new Expressions();
-		arguments.setDim(1);
-		arguments.data[0] = cast(void*)earg1;
-
+	    if (earg1)
+		{	
+			arguments.setDim(1);
+			arguments.data[0] = cast(void*)earg1;
+		}
 		this.arguments = arguments;
 	}
 
@@ -734,7 +736,7 @@
 			accessCheck(loc, sc, null, f);
 
 			ve.var = f;
-		//	ve.hasOverloads = 0;
+		//	ve.hasOverloads = false;
 			ve.type = f.type;
 			t1 = f.type;
 		}
--- a/dmd/CastExp.d	Sat Aug 28 16:19:48 2010 +0200
+++ b/dmd/CastExp.d	Sat Aug 28 19:42:41 2010 +0400
@@ -3,6 +3,7 @@
 import dmd.Expression;
 import dmd.TY;
 import dmd.TypeStruct;
+import dmd.ErrorExp;
 import dmd.TypeExp;
 import dmd.DotIdExp;
 import dmd.CallExp;
@@ -84,50 +85,63 @@
 		super.semantic(sc);
 		if (e1.type)		// if not a tuple
 		{
-		e1 = resolveProperties(sc, e1);
+			e1 = resolveProperties(sc, e1);
+
+			if (!to)
+			{
+				/* Handle cast(const) and cast(immutable), etc.
+				 */
+				to = e1.type.castMod(mod);
+			}
+			else
+				to = to.semantic(loc, sc);
+
+			if (!to.equals(e1.type))
+			{
+				e = op_overload(sc);
+				if (e)
+				{
+				return e.implicitCastTo(sc, to);
+				}
+			}
 
-		if (!to)
-		{
-			/* Handle cast(const) and cast(immutable), etc.
-			 */
-			to = e1.type.castMod(mod);
-		}
-		else
-			to = to.semantic(loc, sc);
+			Type t1b = e1.type.toBasetype();
+			Type tob = to.toBasetype();
+			if (tob.ty == TY.Tstruct &&
+				!tob.equals(t1b) &&
+				(cast(TypeStruct)tob).sym.search(Loc(0), Id.call, 0)
+			   )
+			{
+				/* Look to replace:
+				 *	cast(S)t
+				 * with:
+				 *	S(t)
+				 */
 
-		if (!to.equals(e1.type))
-		{
-			e = op_overload(sc);
-			if (e)
+				// Rewrite as to.call(e1)
+				e = new TypeExp(loc, to);
+				e = new DotIdExp(loc, e, Id.call);
+				e = new CallExp(loc, e, e1);
+				e = e.semantic(sc);
+				return e;
+			}
+			
+			// Struct casts are possible only when the sizes match
+			if (tob.ty == Tstruct || t1b.ty == Tstruct)
 			{
-			return e.implicitCastTo(sc, to);
+				size_t fromsize = cast(size_t)t1b.size(loc);
+				size_t tosize = cast(size_t)tob.size(loc);
+				if (fromsize != tosize)
+				{
+					error("cannot cast from %s to %s", e1.type.toChars(), to.toChars());
+					return new ErrorExp();
+				}
 			}
 		}
-
-		Type t1b = e1.type.toBasetype();
-		Type tob = to.toBasetype();
-		if (tob.ty == TY.Tstruct &&
-			!tob.equals(t1b) &&
-			(cast(TypeStruct)tob).sym.search(Loc(0), Id.call, 0)
-		   )
-		{
-			/* Look to replace:
-			 *	cast(S)t
-			 * with:
-			 *	S(t)
-			 */
-
-			// Rewrite as to.call(e1)
-			e = new TypeExp(loc, to);
-			e = new DotIdExp(loc, e, Id.call);
-			e = new CallExp(loc, e, e1);
-			e = e.semantic(sc);
-			return e;
-		}
-		}
 		else if (!to)
-		{	error("cannot cast tuple");
-		to = Type.terror;
+		{	
+			error("cannot cast tuple");
+			to = Type.terror;
 		}
 
 		if (global.params.safe && !sc.module_.safe && !sc.intypeof)
@@ -212,9 +226,14 @@
 			break;
 		default:
 		}
-		ir.imin &= type.sizemask();
-		ir.imax &= type.sizemask();
-	//printf("CastExp: imin = x%llx, imax = x%llx\n", ir.imin, ir.imax);
+		
+		if (type.isintegral())
+		{
+			ir.imin &= type.sizemask();
+			ir.imax &= type.sizemask();
+		}
+
+		//printf("CastExp: imin = x%llx, imax = x%llx\n", ir.imin, ir.imax);
 		return ir;
 	}
 
--- a/dmd/ClassDeclaration.d	Sat Aug 28 16:19:48 2010 +0200
+++ b/dmd/ClassDeclaration.d	Sat Aug 28 19:42:41 2010 +0400
@@ -1,1904 +1,1936 @@
-module dmd.ClassDeclaration;
-
-import dmd.AggregateDeclaration;
-import dmd.InterfaceDeclaration;
-import dmd.ThisDeclaration;
-import dmd.CompoundStatement;
-import dmd.DeleteDeclaration;
-import dmd.NewDeclaration;
-import dmd.CtorDeclaration;
-import dmd.TypeIdentifier;
-import dmd.STC;
-import dmd.Argument;
-import dmd.TypeTuple;
-import dmd.TY;
-import dmd.LINK;
-import dmd.DsymbolTable;
-import dmd.FuncDeclaration;
-import dmd.Array;
-import dmd.TypeClass;
-import dmd.Module;
-import dmd.Id;
-import dmd.Type;
-import dmd.OverloadSet;
-import dmd.ArrayTypes;
-import dmd.BaseClass;
-import dmd.ClassInfoDeclaration;
-import dmd.Loc;
-import dmd.Identifier;
-import dmd.Dsymbol;
-import dmd.Scope;
-import dmd.TypeFunction;
-import dmd.OutBuffer;
-import dmd.HdrGenState;
-import dmd.VarDeclaration;
-import dmd.Initializer;
-import dmd.ExpInitializer;
-import dmd.TypeSArray;
-import dmd.ScopeDsymbol;
-import dmd.PROT;
-import dmd.Util;
-import dmd.Global;
-
-import dmd.expression.Util;
-
-import dmd.backend.Symbol;
-import dmd.backend.dt_t;
-import dmd.backend.TYPE;
-import dmd.backend.FL;
-import dmd.backend.SFL;
-import dmd.backend.mTY;
-import dmd.backend.SC;
-import dmd.backend.mTYman;
-import dmd.backend.Util;
-import dmd.backend.TYM;
-import dmd.backend.Classsym;
-import dmd.backend.glue;
-import dmd.backend.RTLSYM;
-import dmd.backend.LIST;
-
-import dmd.codegen.Util;
-
-import std.string;
-
-version (DMDV2) {
-	enum CLASSINFO_SIZE = (0x3C+16+4);	// value of ClassInfo.size
-} else {
-	enum CLASSINFO_SIZE = (0x3C+12+4);	// value of ClassInfo.size
-}
-
-enum OFFSET_RUNTIME = 0x76543210;
-
-struct Param
-{
-	int isf(void*, FuncDeclaration fd2)
-	{
-		//printf("param = %p, fd = %p %s\n", param, fd, fd.toChars());
-		return fd is fd2;
-	}
-	
-	FuncDeclaration fd;
-}
-
-class ClassDeclaration : AggregateDeclaration
-{
-    static __gshared ClassDeclaration object;
-    static __gshared ClassDeclaration classinfo;
-
-    ClassDeclaration baseClass;	// null only if this is Object
-    FuncDeclaration staticCtor;
-    FuncDeclaration staticDtor;
-    Array vtbl;				// Array of FuncDeclaration's making up the vtbl[]
-    Array vtblFinal;			// More FuncDeclaration's that aren't in vtbl[]
-
-    BaseClasses baseclasses;		// Array of BaseClass's; first is super,
-					// rest are Interface's
-
-    int interfaces_dim;
-    BaseClass* interfaces;		// interfaces[interfaces_dim] for this class
-					// (does not include baseClass)
-
-    BaseClasses vtblInterfaces;	// array of base interfaces that have
-					// their own vtbl[]
-
-    ClassInfoDeclaration vclassinfo;	// the ClassInfo object for this ClassDeclaration
-    bool com;				// true if this is a COM class (meaning
-					// it derives from IUnknown)
-    bool isauto;				// true if this is an auto class
-    bool isabstract;			// true if abstract class
-
-    int inuse;				// to prevent recursive attempts
-
-    this(Loc loc, Identifier id, BaseClasses baseclasses)
-	{
-		super(loc, id);
-		
-		vtbl = new Array();
-		vtblFinal = new Array();
-		
-		enum msg = "only object.d can define this reserved class name";
-
-		if (baseclasses) {
-			this.baseclasses = baseclasses;
-		} else {
-			this.baseclasses = new BaseClasses();
-		}
-
-		//printf("ClassDeclaration(%s), dim = %d\n", id.toChars(), this.baseclasses.dim);
-
-		// For forward references
-		type = new TypeClass(this);
-
-		if (id)
-		{
-			// Look for special class names
-
-			if (id is Id.__sizeof || id is Id.alignof_ || id is Id.mangleof_)
-				error("illegal class name");
-
-			// BUG: What if this is the wrong TypeInfo, i.e. it is nested?
-			if (id.toChars()[0] == 'T')
-			{
-				if (id is Id.TypeInfo)
-				{	
-					if (Type.typeinfo)
-						Type.typeinfo.error("%s", msg);
-					Type.typeinfo = this;
-				}
-
-				if (id is Id.TypeInfo_Class)
-				{	
-					if (Type.typeinfoclass)
-						Type.typeinfoclass.error("%s", msg);
-					Type.typeinfoclass = this;
-				}
-
-				if (id is Id.TypeInfo_Interface)
-				{	
-					if (Type.typeinfointerface)
-						Type.typeinfointerface.error("%s", msg);
-					Type.typeinfointerface = this;
-				}
-
-				if (id is Id.TypeInfo_Struct)
-				{	
-					if (Type.typeinfostruct)
-						Type.typeinfostruct.error("%s", msg);
-					Type.typeinfostruct = this;
-				}
-
-				if (id is Id.TypeInfo_Typedef)
-				{	
-					if (Type.typeinfotypedef)
-						Type.typeinfotypedef.error("%s", msg);
-					Type.typeinfotypedef = this;
-				}
-
-				if (id is Id.TypeInfo_Pointer)
-				{	
-					if (Type.typeinfopointer)
-						Type.typeinfopointer.error("%s", msg);
-					Type.typeinfopointer = this;
-				}
-
-				if (id is Id.TypeInfo_Array)
-				{	
-					if (Type.typeinfoarray)
-						Type.typeinfoarray.error("%s", msg);
-					Type.typeinfoarray = this;
-				}
-
-				if (id is Id.TypeInfo_StaticArray)
-				{	//if (Type.typeinfostaticarray)
-					//Type.typeinfostaticarray.error("%s", msg);
-					Type.typeinfostaticarray = this;
-				}
-
-				if (id is Id.TypeInfo_AssociativeArray)
-				{	
-					if (Type.typeinfoassociativearray)
-						Type.typeinfoassociativearray.error("%s", msg);
-					Type.typeinfoassociativearray = this;
-				}
-
-				if (id is Id.TypeInfo_Enum)
-				{	
-					if (Type.typeinfoenum)
-						Type.typeinfoenum.error("%s", msg);
-					Type.typeinfoenum = this;
-				}
-
-				if (id is Id.TypeInfo_Function)
-				{	
-					if (Type.typeinfofunction)
-						Type.typeinfofunction.error("%s", msg);
-					Type.typeinfofunction = this;
-				}
-
-				if (id is Id.TypeInfo_Delegate)
-				{	
-					if (Type.typeinfodelegate)
-						Type.typeinfodelegate.error("%s", msg);
-					Type.typeinfodelegate = this;
-				}
-
-				if (id is Id.TypeInfo_Tuple)
-				{	
-					if (Type.typeinfotypelist)
-						Type.typeinfotypelist.error("%s", msg);
-					Type.typeinfotypelist = this;
-				}
-
-	version (DMDV2) {
-				if (id is Id.TypeInfo_Const)
-				{	
-					if (Type.typeinfoconst)
-						Type.typeinfoconst.error("%s", msg);
-					Type.typeinfoconst = this;
-				}
-
-				if (id is Id.TypeInfo_Invariant)
-				{	
-					if (Type.typeinfoinvariant)
-						Type.typeinfoinvariant.error("%s", msg);
-					Type.typeinfoinvariant = this;
-				}
-
-				if (id is Id.TypeInfo_Shared)
-				{	
-					if (Type.typeinfoshared)
-						Type.typeinfoshared.error("%s", msg);
-					Type.typeinfoshared = this;
-				}
-	}
-			}
-
-			if (id is Id.Object_)
-			{   
-				if (object)
-					object.error("%s", msg);
-				object = this;
-			}
-
-			if (id is Id.ClassInfo)
-			{   
-				if (classinfo)
-					classinfo.error("%s", msg);
-				classinfo = this;
-			}
-
-			if (id is Id.ModuleInfo)
-			{   
-				if (Module.moduleinfo)
-					Module.moduleinfo.error("%s", msg);
-				Module.moduleinfo = this;
-			}
-		}
-
-		com = 0;
-		isauto = false;
-		isabstract = false;
-		inuse = 0;
-	}
-	
-    override Dsymbol syntaxCopy(Dsymbol s)
-	{
-		ClassDeclaration cd;
-
-		//printf("ClassDeclaration.syntaxCopy('%s')\n", toChars());
-		if (s)
-			cd = cast(ClassDeclaration)s;
-		else
-		cd = new ClassDeclaration(loc, ident, null);
-
-		cd.storage_class |= storage_class;
-
-		cd.baseclasses.setDim(this.baseclasses.dim);
-		for (int i = 0; i < cd.baseclasses.dim; i++)
-		{
-			BaseClass b = cast(BaseClass)this.baseclasses.data[i];
-			BaseClass b2 = new BaseClass(b.type.syntaxCopy(), b.protection);
-			cd.baseclasses.data[i] = cast(void*)b2;
-		}
-
-		ScopeDsymbol.syntaxCopy(cd);
-		return cd;
-	}
-	
-    override void semantic(Scope sc)
-	{
-		int i;
-		uint offset;
-
-		//printf("ClassDeclaration.semantic(%s), type = %p, sizeok = %d, this = %p\n", toChars(), type, sizeok, this);
-		//printf("\tparent = %p, '%s'\n", sc.parent, sc.parent ? sc.parent.toChars() : "");
-		//printf("sc.stc = %x\n", sc.stc);
-
-		//{ static int n;  if (++n == 20) *(char*)0=0; }
-
-		if (!ident)		// if anonymous class
-		{	
-			string id = "__anonclass";
-			ident = Identifier.generateId(id);
-		}
-
-		if (!sc)
-			sc = scope_;
-
-		if (!parent && sc.parent && !sc.parent.isModule())
-			parent = sc.parent;
-
-		type = type.semantic(loc, sc);
-		handle = type;
-
-		if (!members)			// if forward reference
-		{	
-			//printf("\tclass '%s' is forward referenced\n", toChars());
-			return;
-		}
-		if (symtab)
-		{	if (!scope_)
-		{   //printf("\tsemantic for '%s' is already completed\n", toChars());
-			return;		// semantic() already completed
-		}
-		}
-		else
-		symtab = new DsymbolTable();
-
-		Scope scx = null;
-		if (scope_)
-		{	sc = scope_;
-			scx = scope_;		// save so we don't make redundant copies
-		scope_ = null;
-		}
-version (IN_GCC) {
-		methods.setDim(0);
-}
-
-		if (sc.stc & STC.STCdeprecated)
-		{
-		isdeprecated = 1;
-		}
-
-		if (sc.linkage == LINK.LINKcpp)
-		error("cannot create C++ classes");
-
-		// Expand any tuples in baseclasses[]
-		for (i = 0; i < baseclasses.dim; )
-		{	
-			BaseClass b = cast(BaseClass)baseclasses.data[i];
-		//printf("test1 %s %s\n", toChars(), b.type.toChars());
-			b.type = b.type.semantic(loc, sc);
-		//printf("test2\n");
-			Type tb = b.type.toBasetype();
-
-			if (tb.ty == TY.Ttuple)
-			{   
-				TypeTuple tup = cast(TypeTuple)tb;
-				enum PROT protection = b.protection;
-				baseclasses.remove(i);
-				size_t dim = Argument.dim(tup.arguments);
-				for (size_t j = 0; j < dim; j++)
-				{	
-					Argument arg = Argument.getNth(tup.arguments, j);
-					b = new BaseClass(arg.type, protection);
-					baseclasses.insert(i + j, cast(void*)b);
-				}
-			}
-			else
-				i++;
-		}
-
-		// See if there's a base class as first in baseclasses[]
-		if (baseclasses.dim)
-		{	
-			TypeClass tc;
-			BaseClass b;
-			Type tb;
-
-			b = cast(BaseClass)baseclasses.data[0];
-			//b.type = b.type.semantic(loc, sc);
-			tb = b.type.toBasetype();
-			if (tb.ty != TY.Tclass)
-			{   error("base type must be class or interface, not %s", b.type.toChars());
-				baseclasses.remove(0);
-			}
-			else
-			{
-				tc = cast(TypeClass)(tb);
-
-				if (tc.sym.isDeprecated())
-				{
-				if (!isDeprecated())
-				{
-					// Deriving from deprecated class makes this one deprecated too
-					isdeprecated = 1;
-
-					tc.checkDeprecated(loc, sc);
-				}
-				}
-
-				if (tc.sym.isInterfaceDeclaration()) {
-					;
-				} else {
-					for (ClassDeclaration cdb = tc.sym; cdb; cdb = cdb.baseClass)
-					{
-						if (cdb == this)
-						{
-							error("circular inheritance");
-							baseclasses.remove(0);
-							goto L7;
-						}
-					}
-					if (!tc.sym.symtab || tc.sym.sizeok == 0)
-					{   // Try to resolve forward reference
-						if (sc.mustsemantic && tc.sym.scope_)
-						tc.sym.semantic(null);
-					}
-					if (!tc.sym.symtab || tc.sym.scope_ || tc.sym.sizeok == 0)
-					{
-						//printf("%s: forward reference of base class %s\n", toChars(), tc.sym.toChars());
-						//error("forward reference of base class %s", baseClass.toChars());
-						// Forward reference of base class, try again later
-						//printf("\ttry later, forward reference of base class %s\n", tc.sym.toChars());
-						scope_ = scx ? scx : new Scope(sc);
-						scope_.setNoFree();
-						if (tc.sym.scope_)
-							tc.sym.scope_.module_.addDeferredSemantic(tc.sym);
-						scope_.module_.addDeferredSemantic(this);
-						return;
-					}
-					else
-					{   baseClass = tc.sym;
-						b.base = baseClass;
-					}
-				 L7: ;
-				}
-			}
-		}
-
-		// Treat the remaining entries in baseclasses as interfaces
-		// Check for errors, handle forward references
-		for (i = (baseClass ? 1 : 0); i < baseclasses.dim; )
-		{	TypeClass tc;
-		BaseClass b;
-		Type tb;
-
-		b = cast(BaseClass)baseclasses.data[i];
-		b.type = b.type.semantic(loc, sc);
-		tb = b.type.toBasetype();
-		if (tb.ty == TY.Tclass)
-			tc = cast(TypeClass)tb;
-		else
-			tc = null;
-		if (!tc || !tc.sym.isInterfaceDeclaration())
-		{
-			error("base type must be interface, not %s", b.type.toChars());
-			baseclasses.remove(i);
-			continue;
-		}
-		else
-		{
-			if (tc.sym.isDeprecated())
-			{
-			if (!isDeprecated())
-			{
-				// Deriving from deprecated class makes this one deprecated too
-				isdeprecated = 1;
-
-				tc.checkDeprecated(loc, sc);
-			}
-			}
-
-			// Check for duplicate interfaces
-			for (size_t j = (baseClass ? 1 : 0); j < i; j++)
-			{
-			BaseClass b2 = cast(BaseClass)baseclasses.data[j];
-			if (b2.base == tc.sym)
-				error("inherits from duplicate interface %s", b2.base.toChars());
-			}
-
-			if (!tc.sym.symtab)
-			{   // Try to resolve forward reference
-			if (sc.mustsemantic && tc.sym.scope_)
-				tc.sym.semantic(null);
-			}
-
-			b.base = tc.sym;
-			if (!b.base.symtab || b.base.scope_)
-			{
-			//error("forward reference of base class %s", baseClass.toChars());
-			// Forward reference of base, try again later
-			//printf("\ttry later, forward reference of base %s\n", baseClass.toChars());
-			scope_ = scx ? scx : new Scope(sc);
-			scope_.setNoFree();
-			if (tc.sym.scope_)
-				tc.sym.scope_.module_.addDeferredSemantic(tc.sym);
-			scope_.module_.addDeferredSemantic(this);
-			return;
-			}
-		}
-		i++;
-		}
-
-
-		// If no base class, and this is not an Object, use Object as base class
-		if (!baseClass && ident !is Id.Object_)
-		{
-			// BUG: what if Object is redefined in an inner scope?
-			Type tbase = new TypeIdentifier(Loc(0), Id.Object_);
-			BaseClass b;
-			TypeClass tc;
-			Type bt;
-
-			if (!object)
-			{
-				error("missing or corrupt object.d");
-				fatal();
-			}
-			bt = tbase.semantic(loc, sc).toBasetype();
-			b = new BaseClass(bt, PROT.PROTpublic);
-			baseclasses.shift(cast(void*)b);
-			assert(b.type.ty == TY.Tclass);
-			tc = cast(TypeClass)(b.type);
-			baseClass = tc.sym;
-			assert(!baseClass.isInterfaceDeclaration());
-			b.base = baseClass;
-		}
-
-		interfaces_dim = baseclasses.dim;
-		interfaces = cast(BaseClass*)baseclasses.data;
-
-		if (baseClass)
-		{
-			if (baseClass.storage_class & STC.STCfinal)
-				error("cannot inherit from final class %s", baseClass.toChars());
-
-			interfaces_dim--;
-			interfaces++;
-
-			// Copy vtbl[] from base class
-			vtbl.setDim(baseClass.vtbl.dim);
-			memcpy(vtbl.data, baseClass.vtbl.data, (void*).sizeof * vtbl.dim);
-
-			// Inherit properties from base class
-			com = baseClass.isCOMclass();
-			isauto = baseClass.isauto;
-			vthis = baseClass.vthis;
-			storage_class |= baseClass.storage_class & STC.STC_TYPECTOR;
-		}
-		else
-		{
-			// No base class, so this is the root of the class hierarchy
-			vtbl.setDim(0);
-			vtbl.push(cast(void*)this);		// leave room for classinfo as first member
-		}
-
-		protection = sc.protection;
-		storage_class |= sc.stc;
-
-		if (sizeok == 0)
-		{
-		interfaceSemantic(sc);
-
-		for (i = 0; i < members.dim; i++)
-		{
-			Dsymbol s = cast(Dsymbol)members.data[i];
-			s.addMember(sc, this, true);
-		}
-
-		/* If this is a nested class, add the hidden 'this'
-		 * member which is a pointer to the enclosing scope.
-		 */
-		if (vthis)		// if inheriting from nested class
-		{   // Use the base class's 'this' member
-			isnested = true;
-			if (storage_class & STC.STCstatic)
-			error("static class cannot inherit from nested class %s", baseClass.toChars());
-			if (toParent2() != baseClass.toParent2())
-			{
-			if (toParent2())
-			{
-				error("is nested within %s, but super class %s is nested within %s",
-				toParent2().toChars(),
-				baseClass.toChars(),
-				baseClass.toParent2().toChars());
-			}
-			else
-			{
-				error("is not nested, but super class %s is nested within %s",
-				baseClass.toChars(),
-				baseClass.toParent2().toChars());
-			}
-			isnested = false;
-			}
-		}
-		else if (!(storage_class & STC.STCstatic))
-		{   
-			Dsymbol s = toParent2();
-			if (s)
-			{
-				AggregateDeclaration ad = s.isClassDeclaration();
-				FuncDeclaration fd = s.isFuncDeclaration();
-
-				if (ad || fd)
-				{   isnested = true;
-					Type t;
-					if (ad)
-						t = ad.handle;
-					else if (fd)
-					{	
-						AggregateDeclaration ad2 = fd.isMember2();
-						if (ad2)
-							t = ad2.handle;
-						else
-						{
-							t = Type.tvoidptr;
-						}
-					}
-					else
-						assert(0);
-					if (t.ty == TY.Tstruct)	// ref to struct
-						t = Type.tvoidptr;
-					assert(!vthis);
-					vthis = new ThisDeclaration(loc, t);
-					members.push(cast(void*)vthis);
-				}
-			}
-		}
-		}
-
-		if (storage_class & (STC.STCauto | STC.STCscope))
-			isauto = true;
-		if (storage_class & STC.STCabstract)
-			isabstract = true;
-		if (storage_class & STC.STCimmutable)
-			type = type.invariantOf();
-		else if (storage_class & STC.STCconst)
-			type = type.constOf();
-		else if (storage_class & STC.STCshared)
-			type = type.sharedOf();
-
-		sc = sc.push(this);
-		sc.stc &= ~(STC.STCfinal | STC.STCauto | STC.STCscope | STC.STCstatic |
-			 STC.STCabstract | STC.STCdeprecated | STC.STC_TYPECTOR | STC.STCtls | STC.STCgshared);
-		sc.stc |= storage_class & STC.STC_TYPECTOR;
-		sc.parent = this;
-		sc.inunion = 0;
-
-		if (isCOMclass())
-		{
-version (_WIN32) {
-		sc.linkage = LINK.LINKwindows;
-} else {
-		/* This enables us to use COM objects under Linux and
-		 * work with things like XPCOM
-		 */
-		sc.linkage = LINK.LINKc;
-}
-		}
-		sc.protection = PROT.PROTpublic;
-		sc.explicitProtection = 0;
-		sc.structalign = 8;
-		structalign = sc.structalign;
-		if (baseClass)
-		{	sc.offset = baseClass.structsize;
-		alignsize = baseClass.alignsize;
-	//	if (isnested)
-	//	    sc.offset += PTRSIZE;	// room for uplevel context pointer
-		}
-		else
-		{	sc.offset = PTRSIZE * 2;	// allow room for __vptr and __monitor
-		alignsize = PTRSIZE;
-		}
-		structsize = sc.offset;
-		Scope scsave = sc;	/// a copy must be created?
-		int members_dim = members.dim;
-		sizeok = 0;
-		for (i = 0; i < members_dim; i++)
-		{
-			Dsymbol s = cast(Dsymbol)members.data[i];
-			s.semantic(sc);
-		}
-
-		if (sizeok == 2)
-		{	// semantic() failed because of forward references.
-		// Unwind what we did, and defer it for later
-		fields.setDim(0);
-		structsize = 0;
-		alignsize = 0;
-		structalign = 0;
-
-		sc = sc.pop();
-
-		scope_ = scx ? scx : new Scope(sc);
-		scope_.setNoFree();
-		scope_.module_.addDeferredSemantic(this);
-
-		//printf("\tsemantic('%s') failed due to forward references\n", toChars());
-		return;
-		}
-
-		//printf("\tsemantic('%s') successful\n", toChars());
-
-		structsize = sc.offset;
-		//members.print();
-
-		/* Look for special member functions.
-		 * They must be in this class, not in a base class.
-		 */
-		ctor = cast(CtorDeclaration)search(Loc(0), Id.ctor, 0);
-		if (ctor && (ctor.toParent() != this || !ctor.isCtorDeclaration()))
-		ctor = null;
-
-	//    dtor = (DtorDeclaration *)search(Id.dtor, 0);
-	//    if (dtor && dtor.toParent() != this)
-	//	dtor = null;
-
-	//    inv = (InvariantDeclaration *)search(Id.classInvariant, 0);
-	//    if (inv && inv.toParent() != this)
-	//	inv = null;
-
-		// Can be in base class
-		aggNew = cast(NewDeclaration)search(Loc(0), Id.classNew, 0);
-		aggDelete = cast(DeleteDeclaration)search(Loc(0), Id.classDelete, 0);
-
-		// If this class has no constructor, but base class does, create
-		// a constructor:
-		//    this() { }
-		if (!ctor && baseClass && baseClass.ctor)
-		{
-		//printf("Creating default this(){} for class %s\n", toChars());
-		CtorDeclaration ctor = new CtorDeclaration(loc, Loc(0), null, 0);
-		ctor.fbody = new CompoundStatement(Loc(0), new Statements());
-		members.push(cast(void*)ctor);
-		ctor.addMember(sc, this, true);
-		sc = scsave;	// why? What about sc.nofree?	///
-		sc.offset = structsize;
-		ctor.semantic(sc);
-		this.ctor = ctor;
-		defaultCtor = ctor;
-		}
-
-static if (false) {
-		if (baseClass)
-		{	if (!aggDelete)
-			aggDelete = baseClass.aggDelete;
-		if (!aggNew)
-			aggNew = baseClass.aggNew;
-		}
-}
-
-		// Allocate instance of each new interface
-		for (i = 0; i < vtblInterfaces.dim; i++)
-		{
-			BaseClass b = cast(BaseClass)vtblInterfaces.data[i];
-			uint thissize = PTRSIZE;
-
-			alignmember(structalign, thissize, &sc.offset);
-			assert(b.offset == 0);
-			b.offset = sc.offset;
-
-			// Take care of single inheritance offsets
-			while (b.baseInterfaces.length)
-			{
-				b = b.baseInterfaces[0];
-				b.offset = sc.offset;
-			}
-
-			sc.offset += thissize;
-			if (alignsize < thissize)
-				alignsize = thissize;
-		}
-		structsize = sc.offset;
-		sizeok = 1;
-		Module.dprogress++;
-
-		dtor = buildDtor(sc);
-
-		sc.pop();
-
-static if (false) { // Do not call until toObjfile() because of forward references
-		// Fill in base class vtbl[]s
-		for (i = 0; i < vtblInterfaces.dim; i++)
-		{
-			BaseClass b = cast(BaseClass)vtblInterfaces.data[i];
-
-		//b.fillVtbl(this, &b.vtbl, 1);
-		}
-}
-		//printf("-ClassDeclaration.semantic(%s), type = %p\n", toChars(), type);
-	}
-	
-    override void toCBuffer(OutBuffer buf, HdrGenState* hgs)
-	{
-		assert(false);
-	}
-	
-	/*********************************************
-	 * Determine if 'this' is a base class of cd.
-	 * This is used to detect circular inheritance only.
-	 */
-    int isBaseOf2(ClassDeclaration cd)
-	{
-		if (!cd)
-			return 0;
-		//printf("ClassDeclaration::isBaseOf2(this = '%s', cd = '%s')\n", toChars(), cd.toChars());
-		for (int i = 0; i < cd.baseclasses.dim; i++)
-		{	
-			BaseClass b = cast(BaseClass)cd.baseclasses.data[i];
-
-			if (b.base is this || isBaseOf2(b.base))
-				return 1;
-		}
-		return 0;
-	}
-
-	/*******************************************
-	 * Determine if 'this' is a base class of cd.
-	 */
-///    #define OFFSET_RUNTIME 0x76543210
-    bool isBaseOf(ClassDeclaration cd, int* poffset)
-	{
-		if (!cd)
-			return 0;
-		//printf("ClassDeclaration::isBaseOf2(this = '%s', cd = '%s')\n", toChars(), cd.toChars());
-		for (int i = 0; i < cd.baseclasses.dim; i++)
-		{	
-			BaseClass b = cast(BaseClass)cd.baseclasses.data[i];
-
-			if (b.base == this || isBaseOf2(b.base))
-				return 1;
-		}
-
-		return 0;
-	}
-
-    override Dsymbol search(Loc, Identifier ident, int flags)
-	{
-		Dsymbol s;
-		//printf("%s.ClassDeclaration.search('%s')\n", toChars(), ident.toChars());
-
-		if (scope_)
-		{
-			Scope sc = scope_;
-			sc.mustsemantic++;
-			semantic(sc);
-			sc.mustsemantic--;
-		}
-
-		if (!members || !symtab || scope_)
-		{
-			error("is forward referenced when looking for '%s'", ident.toChars());
-			//*(char*)0=0;
-			return null;
-		}
-
-		s = ScopeDsymbol.search(loc, ident, flags);
-		if (!s)
-		{
-			// Search bases classes in depth-first, left to right order
-
-			int i;
-
-			for (i = 0; i < baseclasses.dim; i++)
-			{
-				BaseClass b = cast(BaseClass)baseclasses.data[i];
-
-				if (b.base)
-				{
-					if (!b.base.symtab)
-						error("base %s is forward referenced", b.base.ident.toChars());
-					else
-					{
-						s = b.base.search(loc, ident, flags);
-						if (s is this)	// happens if s is nested in this and derives from this
-							s = null;
-						else if (s)
-							break;
-					}
-				}
-			}
-		}
-		return s;
-	}
-	
-version (DMDV2) {
-    bool isFuncHidden(FuncDeclaration fd)
-	{
-		//printf("ClassDeclaration::isFuncHidden(class = %s, fd = %s)\n", toChars(), fd.toChars());
-		Dsymbol s = search(Loc(0), fd.ident, 4|2);
-		if (!s)
-		{	
-			//printf("not found\n");
-			/* Because, due to a hack, if there are multiple definitions
-			 * of fd.ident, null is returned.
-			 */
-			return false;
-		}
-		
-		Param p; p.fd = fd;
-
-		s = s.toAlias();
-		OverloadSet os = s.isOverloadSet();	
-		if (os)
-		{
-			for (int i = 0; i < os.a.dim; i++)
-			{   
-				Dsymbol s2 = cast(Dsymbol)os.a.data[i];
-				FuncDeclaration f2 = s2.isFuncDeclaration();
-				if (f2 && overloadApply(f2, &p.isf, &p))
-					return false;
-			}
-			return true;
-		}
-		else
-		{
-			FuncDeclaration fdstart = s.isFuncDeclaration();
-			//printf("%s fdstart = %p\n", s.kind(), fdstart);
-			return !overloadApply(fdstart, &p.isf, &p);
-		}
-	}
-}
-    FuncDeclaration findFunc(Identifier ident, TypeFunction tf)
-	{
-		//printf("ClassDeclaration.findFunc(%s, %s) %s\n", ident.toChars(), tf.toChars(), toChars());
-
-		ClassDeclaration cd = this;
-		Array vtbl = cd.vtbl;
-		while (true)
-		{
-			for (size_t i = 0; i < vtbl.dim; i++)
-			{
-				FuncDeclaration fd = (cast(Dsymbol)vtbl.data[i]).isFuncDeclaration();
-				if (!fd)
-					continue;		// the first entry might be a ClassInfo
-
-				//printf("\t[%d] = %s\n", i, fd.toChars());
-				if (ident == fd.ident &&
-					//tf.equals(fd.type)
-					fd.type.covariant(tf) == 1
-				   )
-				{   //printf("\t\tfound\n");
-					return fd;
-				}
-				//else printf("\t\t%d\n", fd.type.covariant(tf));
-			}
-			if (!cd)
-				break;
-
-			vtbl = cd.vtblFinal;
-			cd = cd.baseClass;
-		}
-
-		return null;
-	}
-
-    void interfaceSemantic(Scope sc)
-	{
-		InterfaceDeclaration id = isInterfaceDeclaration();
-
-		vtblInterfaces = new BaseClasses();
-		vtblInterfaces.reserve(interfaces_dim);
-
-		for (size_t i = 0; i < interfaces_dim; i++)
-		{
-			BaseClass b = interfaces[i];
-
-			// If this is an interface, and it derives from a COM interface,
-			// then this is a COM interface too.
-			if (b.base.isCOMinterface())
-				com = 1;
-
-			if (b.base.isCPPinterface() && id)
-				id.cpp = 1;
-
-			vtblInterfaces.push(cast(void*)b);
-			b.copyBaseInterfaces(vtblInterfaces);
-		}
-	}
-
-    bool isCOMclass()
-	{
-		return com;
-	}
-	
-    bool isCOMinterface()
-	{
-		return false;
-	}
-
-version (DMDV2) {
-    bool isCPPinterface()
-	{
-		return false;
-	}
-}
-    bool isAbstract()
-	{
-		if (isabstract)
-			return true;
-
-		for (int i = 1; i < vtbl.dim; i++)
-		{
-			FuncDeclaration fd = (cast(Dsymbol)vtbl.data[i]).isFuncDeclaration();
-
-			//printf("\tvtbl[%d] = %p\n", i, fd);
-			if (!fd || fd.isAbstract())
-			{
-				isabstract = true;
-				return true;
-			}
-		}
-
-		return false;
-	}
-	
-    int vtblOffset()
-	{
-		assert(false);
-	}
-	
-    override string kind()
-	{
-		return "class";
-	}
-	
-    override string mangle()
-	{
-		Dsymbol parentsave = parent;
-
-		//printf("ClassDeclaration.mangle() %s.%s\n", parent.toChars(), toChars());
-
-		/* These are reserved to the compiler, so keep simple
-		 * names for them.
-		 */
-		if (ident is Id.Exception)
-		{	
-			if (parent.ident is Id.object)
-				parent = null;
-		}
-		else if (ident is Id.TypeInfo   ||
-		//	ident is Id.Exception ||
-			ident is Id.TypeInfo_Struct   ||
-			ident is Id.TypeInfo_Class    ||
-			ident is Id.TypeInfo_Typedef  ||
-			ident is Id.TypeInfo_Tuple ||
-			this is object     ||
-			this is classinfo  ||
-			this is Module.moduleinfo ||
-			ident.toChars().startsWith("TypeInfo_")
-		   )
-		{
-			parent = null;
-		}
-
-		string id = Dsymbol.mangle();
-		parent = parentsave;
-		return id;
-	}
-	
-    override void toDocBuffer(OutBuffer buf)
-	{
-		assert(false);
-	}
-
-    override PROT getAccess(Dsymbol smember)	// determine access to smember
-	{
-		PROT access_ret = PROT.PROTnone;
-
-	version (LOG) {
-		printf("+ClassDeclaration::getAccess(this = '%s', smember = '%s')\n",
-			toChars(), smember.toChars());
-	}
-		if (smember.toParent() is this)
-		{
-			access_ret = smember.prot();
-		}
-		else
-		{
-			PROT access;
-			int i;
-
-			if (smember.isDeclaration().isStatic())
-			{
-				access_ret = smember.prot();
-			}
-
-			for (i = 0; i < baseclasses.dim; i++)
-			{   
-				BaseClass b = cast(BaseClass)baseclasses.data[i];
-
-				access = b.base.getAccess(smember);
-				switch (access)
-				{
-					case PROT.PROTnone:
-						break;
-
-					case PROT.PROTprivate:
-						access = PROT.PROTnone;	// private members of base class not accessible
-						break;
-
-					case PROT.PROTpackage:
-					case PROT.PROTprotected:
-					case PROT.PROTpublic:
-					case PROT.PROTexport:
-						// If access is to be tightened
-						if (b.protection < access)
-							access = b.protection;
-
-						// Pick path with loosest access
-						if (access > access_ret)
-							access_ret = access;
-						break;
-
-					default:
-						assert(0);
-				}
-			}
-		}
-
-	version (LOG) {
-		printf("-ClassDeclaration::getAccess(this = '%s', smember = '%s') = %d\n",
-			toChars(), smember.toChars(), access_ret);
-	}
-
-		return access_ret;
-	}
-
-    override void addLocalClass(ClassDeclarations aclasses)
-	{
-		aclasses.push(cast(void*)this);
-	}
-
-    // Back end
-    override void toObjFile(int multiobj)			// compile to .obj file
-	{
-		uint i;
-		uint offset;
-		Symbol* sinit;
-		enum_SC scclass;
-
-		//printf("ClassDeclaration.toObjFile('%s')\n", toChars());
-
-		if (!members)
-			return;
-
-		if (multiobj)
-		{	
-			obj_append(this);
-			return;
-		}
-
-		if (global.params.symdebug)
-			toDebug();
-
-		assert(!scope_);	// semantic() should have been run to completion
-
-		scclass = SCglobal;
-		if (inTemplateInstance())
-			scclass = SCcomdat;
-
-		// Put out the members
-		for (i = 0; i < members.dim; i++)
-		{
-			Dsymbol member;
-
-			member = cast(Dsymbol)members.data[i];
-			member.toObjFile(0);
-		}
-
-static if (false) {
-		// Build destructor by aggregating dtors[]
-		Symbol* sdtor;
-		switch (dtors.dim)
-		{	
-			case 0:
-				// No destructors for this class
-				sdtor = null;
-				break;
-
-			case 1:
-				// One destructor, just use it directly
-				sdtor = (cast(DtorDeclaration)dtors.data[0]).toSymbol();
-				break;
-
-			default:
-			{   
-				/* Build a destructor that calls all the
-				 * other destructors in dtors[].
-				 */
-
-				elem* edtor = null;
-
-				// Declare 'this' pointer for our new destructor
-				Symbol* sthis = symbol_calloc("this");
-				sthis.Stype = type_fake(TYnptr);
-				sthis.Stype.Tcount++;
-				sthis.Sclass = SCfastpar;
-				sthis.Spreg = AX;
-				sthis.Sfl = FLauto;
-
-				// Call each of the destructors in dtors[]
-				// in reverse order
-				for (i = 0; i < dtors.dim; i++)
-				{	
-					DtorDeclaration d = cast(DtorDeclaration)dtors.data[i];
-					Symbol* s = d.toSymbol();
-					elem* e = el_bin(OPcall, TYvoid, el_var(s), el_var(sthis));
-					edtor = el_combine(e, edtor);
-				}
-
-				// Create type for the function
-				.type* t = type_alloc(TYjfunc);
-				t.Tflags |= TFprototype | TFfixed;
-				t.Tmangle = mTYman_d;
-				t.Tnext = tsvoid;
-				tsvoid.Tcount++;
-
-				// Create the function, sdtor, and write it out
-				localgot = null;
-				sdtor = toSymbolX("__dtor", SCglobal, t, "FZv");
-				block* b = block_calloc();
-				b.BC = BCret;
-				b.Belem = edtor;
-				sdtor.Sfunc.Fstartblock = b;
-				cstate.CSpsymtab = &sdtor.Sfunc.Flocsym;
-				symbol_add(sthis);
-				writefunc(sdtor);
-			}
-		}
-}
-
-		// Generate C symbols
-		toSymbol();
-		toVtblSymbol();
-		sinit = toInitializer();
-
-		//////////////////////////////////////////////
-
-		// Generate static initializer
-		sinit.Sclass = scclass;
-		sinit.Sfl = FLdata;
-	version (ELFOBJ) { // Burton
-		sinit.Sseg = Segment.CDATA;
-	}
-	version (MACHOBJ) {
-		sinit.Sseg = Segment.DATA;
-	}
-		toDt(&sinit.Sdt);
-		outdata(sinit);
-
-		//////////////////////////////////////////////
-
-		// Put out the TypeInfo
-		type.getTypeInfo(null);
-		type.vtinfo.toObjFile(multiobj);
-
-		//////////////////////////////////////////////
-
-		// Put out the ClassInfo
-		csym.Sclass = scclass;
-		csym.Sfl = FLdata;
-
-		/* The layout is:
-		   {
-			void **vptr;
-			monitor_t monitor;
-			byte[] initializer;		// static initialization data
-			char[] name;		// class name
-			void *[] vtbl;
-			Interface[] interfaces;
-			ClassInfo *base;		// base class
-			void *destructor;
-			void *invariant;		// class invariant
-			uint flags;
-			void *deallocator;
-			OffsetTypeInfo[] offTi;
-			void *defaultConstructor;
-			const(MemberInfo[]) function(string) xgetMembers;	// module getMembers() function
-			TypeInfo typeinfo;
-		   }
-		 */
-		dt_t* dt = null;
-		offset = CLASSINFO_SIZE;			// must be ClassInfo.size
-		if (classinfo)
-		{
-			if (classinfo.structsize != CLASSINFO_SIZE)
-				error("D compiler and phobos' object.d are mismatched");
-		}
-
-		if (classinfo)
-			dtxoff(&dt, classinfo.toVtblSymbol(), 0, TYnptr); // vtbl for ClassInfo
-		else
-			dtdword(&dt, 0);		// BUG: should be an assert()
-
-		dtdword(&dt, 0);			// monitor
-
-		// initializer[]
-		assert(structsize >= 8);
-		dtdword(&dt, structsize);		// size
-		dtxoff(&dt, sinit, 0, TYnptr);	// initializer
-
-		// name[]
-		string name = ident.toChars();
-		size_t namelen = name.length;
-		if (!(namelen > 9 && name[0..9] == "TypeInfo_"))
-		{	
-			name = toPrettyChars();
-			namelen = name.length;
-		}
-		dtdword(&dt, namelen);
-		dtabytes(&dt, TYnptr, 0, namelen + 1, toStringz(name));
-
-		// vtbl[]
-		dtdword(&dt, vtbl.dim);
-		dtxoff(&dt, vtblsym, 0, TYnptr);
-
-		// interfaces[]
-		dtdword(&dt, vtblInterfaces.dim);
-		if (vtblInterfaces.dim)
-			dtxoff(&dt, csym, offset, TYnptr);	// (*)
-		else
-			dtdword(&dt, 0);
-
-		// base
-		if (baseClass)
-			dtxoff(&dt, baseClass.toSymbol(), 0, TYnptr);
-		else
-			dtdword(&dt, 0);
-
-		// destructor
-		if (dtor)
-			dtxoff(&dt, dtor.toSymbol(), 0, TYnptr);
-		else
-			dtdword(&dt, 0);
-
-		// invariant
-		if (inv)
-			dtxoff(&dt, inv.toSymbol(), 0, TYnptr);
-		else
-			dtdword(&dt, 0);
-
-		// flags
-		int flags = 4 | isCOMclass();
-	version (DMDV2) {
-		flags |= 16;
-	}
-		flags |= 32;
-
-		if (ctor)
-			flags |= 8;
-		for (ClassDeclaration cd = this; cd; cd = cd.baseClass)
-		{
-			if (cd.members)
-			{
-				for (size_t j = 0; j < cd.members.dim; j++)
-				{
-					Dsymbol sm = cast(Dsymbol)cd.members.data[j];
-					//printf("sm = %s %s\n", sm.kind(), sm.toChars());
-					if (sm.hasPointers())
-						goto L2;
-				}
-			}
-		}
-		flags |= 2;			// no pointers
-	  L2:
-		dtdword(&dt, flags);
-
-
-		// deallocator
-		if (aggDelete)
-			dtxoff(&dt, aggDelete.toSymbol(), 0, TYnptr);
-		else
-			dtdword(&dt, 0);
-
-		// offTi[]
-		dtdword(&dt, 0);
-		dtdword(&dt, 0);		// null for now, fix later
-
-		// defaultConstructor
-		if (defaultCtor)
-			dtxoff(&dt, defaultCtor.toSymbol(), 0, TYnptr);
-		else
-			dtdword(&dt, 0);
-
-	version (DMDV2) {
-		FuncDeclaration sgetmembers = findGetMembers();
-		if (sgetmembers)
-			dtxoff(&dt, sgetmembers.toSymbol(), 0, TYnptr);
-		else
-			dtdword(&dt, 0);	// module getMembers() function
-	}
-
-		dtxoff(&dt, type.vtinfo.toSymbol(), 0, TYnptr);	// typeinfo
-		//dtdword(&dt, 0);
-
-		//////////////////////////////////////////////
-
-		// Put out vtblInterfaces.data[]. Must immediately follow csym, because
-		// of the fixup (*)
-
-		offset += vtblInterfaces.dim * (4 * PTRSIZE);
-		for (i = 0; i < vtblInterfaces.dim; i++)
-		{	
-			BaseClass b = cast(BaseClass)vtblInterfaces.data[i];
-			ClassDeclaration id = b.base;
-
-			/* The layout is:
-			 *  {
-			 *	ClassInfo *interface;
-			 *	void *[] vtbl;
-			 *	unsigned offset;
-			 *  }
-			 */
-
-			// Fill in vtbl[]
-			b.fillVtbl(this, b.vtbl, 1);
-
-			dtxoff(&dt, id.toSymbol(), 0, TYnptr);		// ClassInfo
-
-			// vtbl[]
-			dtdword(&dt, id.vtbl.dim);
-			dtxoff(&dt, csym, offset, TYnptr);
-
-			dtdword(&dt, b.offset);			// this offset
-
-			offset += id.vtbl.dim * PTRSIZE;
-		}
-
-		// Put out the vtblInterfaces.data[].vtbl[]
-		// This must be mirrored with ClassDeclaration.baseVtblOffset()
-		//printf("putting out %d interface vtbl[]s for '%s'\n", vtblInterfaces.dim, toChars());
-		for (i = 0; i < vtblInterfaces.dim; i++)
-		{	
-			BaseClass b = cast(BaseClass)vtblInterfaces.data[i];
-			ClassDeclaration id = b.base;
-			int j;
-
-			//printf("    interface[%d] is '%s'\n", i, id.toChars());
-			j = 0;
-			if (id.vtblOffset())
-			{
-				// First entry is ClassInfo reference
-				//dtxoff(&dt, id.toSymbol(), 0, TYnptr);
-
-				// First entry is struct Interface reference
-				dtxoff(&dt, csym, CLASSINFO_SIZE + i * (4 * PTRSIZE), TYnptr);
-				j = 1;
-			}
-			
-			assert(id.vtbl.dim == b.vtbl.dim);
-			for (; j < id.vtbl.dim; j++)
-			{
-				FuncDeclaration fd;
-
-				assert(j < b.vtbl.dim);
-		static if (false) {
-				Object o = cast(Object)b.vtbl.data[j];
-				if (o)
-				{
-					printf("o = %p\n", o);
-					assert(o.dyncast() == DYNCAST_DSYMBOL);
-					Dsymbol s = cast(Dsymbol)o;
-					printf("s.kind() = '%s'\n", s.kind());
-				}
-		}
-				fd = cast(FuncDeclaration)b.vtbl.data[j];
-				if (fd)
-					dtxoff(&dt, fd.toThunkSymbol(b.offset), 0, TYnptr);
-				else
-					dtdword(&dt, 0);
-			}
-		}
-
-	static if (true) {
-		// Put out the overriding interface vtbl[]s.
-		// This must be mirrored with ClassDeclaration.baseVtblOffset()
-		//printf("putting out overriding interface vtbl[]s for '%s' at offset x%x\n", toChars(), offset);
-		ClassDeclaration cd;
-		scope Array bvtbl = new Array();
-
-		for (cd = this.baseClass; cd; cd = cd.baseClass)
-		{
-			for (int k = 0; k < cd.vtblInterfaces.dim; k++)
-			{   
-				BaseClass bs = cast(BaseClass)cd.vtblInterfaces.data[k];
-
-				if (bs.fillVtbl(this, bvtbl, 0))
-				{
-					//printf("\toverriding vtbl[] for %s\n", bs.base.toChars());
-					ClassDeclaration id = bs.base;
-					int j;
-
-					j = 0;
-					if (id.vtblOffset())
-					{
-						// First entry is ClassInfo reference
-						//dtxoff(&dt, id.toSymbol(), 0, TYnptr);
-
-						// First entry is struct Interface reference
-						dtxoff(&dt, cd.toSymbol(), CLASSINFO_SIZE + k * (4 * PTRSIZE), TYnptr);
-						j = 1;
-					}
-
-					for (; j < id.vtbl.dim; j++)
-					{
-						assert(j < bvtbl.dim);
-						FuncDeclaration fd = cast(FuncDeclaration)bvtbl.data[j];
-						if (fd)
-							dtxoff(&dt, fd.toThunkSymbol(bs.offset), 0, TYnptr);
-						else
-							dtdword(&dt, 0);
-					}
-				}
-			}
-		}
-	}
-	
-	version (INTERFACE_VIRTUAL) {
-		// Put out the overriding interface vtbl[]s.
-		// This must be mirrored with ClassDeclaration.baseVtblOffset()
-		//printf("putting out overriding interface vtbl[]s for '%s' at offset x%x\n", toChars(), offset);
-		for (i = 0; i < vtblInterfaces.dim; i++)
-		{	
-			BaseClass b = cast(BaseClass)vtblInterfaces.data[i];
-			ClassDeclaration cd;
-
-			for (cd = this.baseClass; cd; cd = cd.baseClass)
-			{
-				for (int k = 0; k < cd.vtblInterfaces.dim; k++)
-				{	
-					BaseClass bs = cast(BaseClass)cd.vtblInterfaces.data[k];
-
-					if (b.base == bs.base)
-					{
-						//printf("\toverriding vtbl[] for %s\n", b.base.toChars());
-						ClassDeclaration id = b.base;
-						int j;
-
-						j = 0;
-						if (id.vtblOffset())
-						{
-							// First entry is ClassInfo reference
-							//dtxoff(&dt, id.toSymbol(), 0, TYnptr);
-
-							// First entry is struct Interface reference
-							dtxoff(&dt, cd.toSymbol(), CLASSINFO_SIZE + k * (4 * PTRSIZE), TYnptr);
-							j = 1;
-						}
-
-						for (; j < id.vtbl.dim; j++)
-						{
-							assert(j < b.vtbl.dim);
-							FuncDeclaration fd = cast(FuncDeclaration)b.vtbl.data[j];
-							if (fd)
-								dtxoff(&dt, fd.toThunkSymbol(bs.offset), 0, TYnptr);
-							else
-								dtdword(&dt, 0);
-						}
-					}
-				}
-			}
-		}
-	}
-
-
-		csym.Sdt = dt;
-	version (ELFOBJ_OR_MACHOBJ) { // Burton
-		// ClassInfo cannot be const data, because we use the monitor on it
-		csym.Sseg = Segment.DATA;
-	}
-		outdata(csym);
-		if (isExport())
-			obj_export(csym,0);
-
-		//////////////////////////////////////////////
-
-		// Put out the vtbl[]
-		//printf("putting out %s.vtbl[]\n", toChars());
-		dt = null;
-		if (0)
-			i = 0;
-		else
-		{	
-			dtxoff(&dt, csym, 0, TYnptr);		// first entry is ClassInfo reference
-			i = 1;
-		}
-		for (; i < vtbl.dim; i++)
-		{
-			FuncDeclaration fd = (cast(Dsymbol)vtbl.data[i]).isFuncDeclaration();
-
-			//printf("\tvtbl[%d] = %p\n", i, fd);
-			if (fd && (fd.fbody || !isAbstract()))
-			{   
-				Symbol* s = fd.toSymbol();
-
-		version (DMDV2) {
-				if (isFuncHidden(fd))
-				{	
-					/* fd is hidden from the view of this class.
-					 * If fd overlaps with any function in the vtbl[], then
-					 * issue 'hidden' error.
-					 */
-					for (int j = 1; j < vtbl.dim; j++)
-					{   
-						if (j == i)
-							continue;
-						FuncDeclaration fd2 = (cast(Dsymbol)vtbl.data[j]).isFuncDeclaration();
-						if (!fd2.ident.equals(fd.ident))
-							continue;
-						if (fd.leastAsSpecialized(fd2) || fd2.leastAsSpecialized(fd))
-						{
-							if (global.params.warnings)
-							{
-								TypeFunction tf = cast(TypeFunction)fd.type;
-								if (tf.ty == Tfunction)
-									warning("%s%s is hidden by %s\n", fd.toPrettyChars(), Argument.argsTypesToChars(tf.parameters, tf.varargs), toChars());
-								else
-									warning("%s is hidden by %s\n", fd.toPrettyChars(), toChars());
-							}
-							s = rtlsym[RTLSYM_DHIDDENFUNC];
-							break;
-						}
-					}
-				}
-		}
-				dtxoff(&dt, s, 0, TYnptr);
-			}
-			else
-				dtdword(&dt, 0);
-		}
-
-		vtblsym.Sdt = dt;
-		vtblsym.Sclass = scclass;
-		vtblsym.Sfl = FLdata;
-	version (ELFOBJ) {
-		vtblsym.Sseg = Segment.CDATA;
-	}
-	version (MACHOBJ) {
-		vtblsym.Sseg = Segment.DATA;
-	}
-		outdata(vtblsym);
-		if (isExport())
-			obj_export(vtblsym,0);
-	}
-	
-    void toDebug()
-	{
-		assert(false);
-	}
-	
-	/******************************************
-	 * Get offset of base class's vtbl[] initializer from start of csym.
-	 * Returns ~0 if not this csym.
-	 */
-    uint baseVtblOffset(BaseClass bc)
-	{
-		uint csymoffset;
-		int i;
-
-		//printf("ClassDeclaration.baseVtblOffset('%s', bc = %p)\n", toChars(), bc);
-		csymoffset = CLASSINFO_SIZE;
-		csymoffset += vtblInterfaces.dim * (4 * PTRSIZE);
-
-		for (i = 0; i < vtblInterfaces.dim; i++)
-		{
-			BaseClass b = cast(BaseClass)vtblInterfaces.data[i];
-
-			if (b == bc)
-				return csymoffset;
-			csymoffset += b.base.vtbl.dim * PTRSIZE;
-		}
-
-	static if (true) {
-		// Put out the overriding interface vtbl[]s.
-		// This must be mirrored with ClassDeclaration.baseVtblOffset()
-		//printf("putting out overriding interface vtbl[]s for '%s' at offset x%x\n", toChars(), offset);
-		ClassDeclaration cd;
-		Array bvtbl;
-
-		for (cd = this.baseClass; cd; cd = cd.baseClass)
-		{
-			for (int k = 0; k < cd.vtblInterfaces.dim; k++)
-			{   
-				BaseClass bs = cast(BaseClass)cd.vtblInterfaces.data[k];
-
-				if (bs.fillVtbl(this, null, 0))
-				{
-					if (bc == bs)
-					{   
-						//printf("\tcsymoffset = x%x\n", csymoffset);
-						return csymoffset;
-					}
-					csymoffset += bs.base.vtbl.dim * PTRSIZE;
-				}
-			}
-		}
-	}
-	version (INTERFACE_VIRTUAL) {
-		for (i = 0; i < vtblInterfaces.dim; i++)
-		{	
-			BaseClass b = cast(BaseClass)vtblInterfaces.data[i];
-			ClassDeclaration cd;
-
-			for (cd = this.baseClass; cd; cd = cd.baseClass)
-			{
-				//printf("\tbase class %s\n", cd.toChars());
-				for (int k = 0; k < cd.vtblInterfaces.dim; k++)
-				{	
-					BaseClass bs = cast(BaseClass)cd.vtblInterfaces.data[k];
-
-					if (bc == bs)
-					{   
-						//printf("\tcsymoffset = x%x\n", csymoffset);
-						return csymoffset;
-					}
-					if (b.base == bs.base)
-						csymoffset += bs.base.vtbl.dim * PTRSIZE;
-				}
-			}
-		}
-	}
-
-		return ~0;
-	}
-	
-	static private __gshared Classsym* scc;
-
-	/*************************************
-	 * Create the "ClassInfo" symbol
-	 */
-    override Symbol* toSymbol()
-	{
-		if (!csym)
-		{
-			Symbol* s;
-
-			if (!scc)
-				scc = fake_classsym(Id.ClassInfo);
-
-			s = toSymbolX("__Class", SC.SCextern, scc.Stype, "Z");
-			s.Sfl = FL.FLextern;
-			s.Sflags |= SFL.SFLnodebug;
-			csym = s;
-			slist_add(s);
-		}
-
-		return csym;
-	}
-
-	/*************************************
-	 * This is accessible via the ClassData, but since it is frequently
-	 * needed directly (like for rtti comparisons), make it directly accessible.
-	 */
-    Symbol* toVtblSymbol()
-	{
-		if (!vtblsym)
-		{
-			if (!csym)
-				toSymbol();
-
-			TYPE* t = type_alloc(TYM.TYnptr | mTY.mTYconst);
-			t.Tnext = tsvoid;
-			t.Tnext.Tcount++;
-			t.Tmangle = mTYman.mTYman_d;
-
-			Symbol* s = toSymbolX("__vtbl", SC.SCextern, t, "Z");
-			s.Sflags |= SFL.SFLnodebug;
-			s.Sfl = FL.FLextern;
-			vtblsym = s;
-			slist_add(s);
-		}
-		return vtblsym;
-	}
-	
-	// Generate the data for the static initializer.
-    void toDt(dt_t **pdt)
-	{
-		//printf("ClassDeclaration.toDt(this = '%s')\n", toChars());
-
-		// Put in first two members, the vtbl[] and the monitor
-		dtxoff(pdt, toVtblSymbol(), 0, TYnptr);
-		dtdword(pdt, 0);			// monitor
-
-		// Put in the rest
-		toDt2(pdt, this);
-
-		//printf("-ClassDeclaration.toDt(this = '%s')\n", toChars());
-	}
-	
-    void toDt2(dt_t** pdt, ClassDeclaration cd)
-	{
-		uint offset;
-		uint i;
-		dt_t* dt;
-		uint csymoffset;
-
-	version (LOG) {
-		printf("ClassDeclaration.toDt2(this = '%s', cd = '%s')\n", toChars(), cd.toChars());
-	}
-		if (baseClass)
-		{
-			baseClass.toDt2(pdt, cd);
-			offset = baseClass.structsize;
-		}
-		else
-		{
-			offset = 8;
-		}
-
-		// Note equivalence of this loop to struct's
-		for (i = 0; i < fields.dim; i++)
-		{
-			VarDeclaration v = cast(VarDeclaration)fields.data[i];
-			Initializer init;
-
-			//printf("\t\tv = '%s' v.offset = %2d, offset = %2d\n", v.toChars(), v.offset, offset);
-			dt = null;
-			init = v.init;
-			if (init)
-			{   
-				//printf("\t\t%s has initializer %s\n", v.toChars(), init.toChars());
-				ExpInitializer ei = init.isExpInitializer();
-				Type tb = v.type.toBasetype();
-				if (ei && tb.ty == Tsarray)
-					(cast(TypeSArray)tb).toDtElem(&dt, ei.exp);
-				else
-					dt = init.toDt();
-			}
-			else if (v.offset >= offset)
-			{   //printf("\t\tdefault initializer\n");
-				v.type.toDt(&dt);
-			}
-			if (dt)
-			{
-				if (v.offset < offset)
-					error("duplicated union initialization for %s", v.toChars());
-				else
-				{
-					if (offset < v.offset)
-						dtnzeros(pdt, v.offset - offset);
-					dtcat(pdt, dt);
-					offset = v.offset + cast(uint)v.type.size();
-				}
-			}
-		}
-
-		// Interface vptr initializations
-		toSymbol();						// define csym
-
-		for (i = 0; i < vtblInterfaces.dim; i++)
-		{	
-			BaseClass b = cast(BaseClass)vtblInterfaces.data[i];
-
-///		version (1 || INTERFACE_VIRTUAL) {
-			for (ClassDeclaration cd2 = cd; 1; cd2 = cd2.baseClass)
-			{
-				assert(cd2);
-				csymoffset = cd2.baseVtblOffset(b);
-				if (csymoffset != ~0)
-				{
-					if (offset < b.offset)
-						dtnzeros(pdt, b.offset - offset);
-					dtxoff(pdt, cd2.toSymbol(), csymoffset, TYnptr);
-					break;
-				}
-			}
-///		} else {
-///			csymoffset = baseVtblOffset(b);
-///			assert(csymoffset != ~0);
-///			dtxoff(pdt, csym, csymoffset, TYnptr);
-///		}
-			offset = b.offset + 4;
-		}
-
-		if (offset < structsize)
-			dtnzeros(pdt, structsize - offset);
-	}
-
-    Symbol* vtblsym;
-
-    ///ClassDeclaration isClassDeclaration() { return cast(ClassDeclaration)this; }	/// huh?
-    override ClassDeclaration isClassDeclaration() { return this; }
-}
+module dmd.ClassDeclaration;
+
+import dmd.AggregateDeclaration;
+import dmd.InterfaceDeclaration;
+import dmd.ThisDeclaration;
+import dmd.CompoundStatement;
+import dmd.DeleteDeclaration;
+import dmd.NewDeclaration;
+import dmd.CtorDeclaration;
+import dmd.TypeIdentifier;
+import dmd.STC;
+import dmd.Argument;
+import dmd.TypeTuple;
+import dmd.TY;
+import dmd.LINK;
+import dmd.DsymbolTable;
+import dmd.FuncDeclaration;
+import dmd.Array;
+import dmd.TypeClass;
+import dmd.Module;
+import dmd.Id;
+import dmd.Type;
+import dmd.OverloadSet;
+import dmd.ArrayTypes;
+import dmd.BaseClass;
+import dmd.ClassInfoDeclaration;
+import dmd.Loc;
+import dmd.Identifier;
+import dmd.Dsymbol;
+import dmd.Scope;
+import dmd.TypeFunction;
+import dmd.OutBuffer;
+import dmd.HdrGenState;
+import dmd.VarDeclaration;
+import dmd.Initializer;
+import dmd.ExpInitializer;
+import dmd.TypeSArray;
+import dmd.ScopeDsymbol;
+import dmd.PROT;
+import dmd.Util;
+import dmd.Global;
+
+import dmd.expression.Util;
+
+import dmd.backend.Symbol;
+import dmd.backend.dt_t;
+import dmd.backend.TYPE;
+import dmd.backend.FL;
+import dmd.backend.SFL;
+import dmd.backend.mTY;
+import dmd.backend.SC;
+import dmd.backend.mTYman;
+import dmd.backend.Util;
+import dmd.backend.TYM;
+import dmd.backend.Classsym;
+import dmd.backend.glue;
+import dmd.backend.RTLSYM;
+import dmd.backend.LIST;
+
+import dmd.codegen.Util;
+
+import std.string;
+
+version (DMDV2) {
+	enum CLASSINFO_SIZE = (0x3C+16+4);	// value of ClassInfo.size
+} else {
+	enum CLASSINFO_SIZE = (0x3C+12+4);	// value of ClassInfo.size
+}
+
+enum OFFSET_RUNTIME = 0x76543210;
+
+struct Param
+{
+	int isf(void*, FuncDeclaration fd2)
+	{
+		//printf("param = %p, fd = %p %s\n", param, fd, fd.toChars());
+		return fd is fd2;
+	}
+	
+	FuncDeclaration fd;
+}
+
+class ClassDeclaration : AggregateDeclaration
+{
+    static __gshared ClassDeclaration object;
+    static __gshared ClassDeclaration classinfo;
+
+    ClassDeclaration baseClass;	// null only if this is Object
+    FuncDeclaration staticCtor;
+    FuncDeclaration staticDtor;
+    Array vtbl;				// Array of FuncDeclaration's making up the vtbl[]
+    Array vtblFinal;			// More FuncDeclaration's that aren't in vtbl[]
+
+    BaseClasses baseclasses;		// Array of BaseClass's; first is super,
+					// rest are Interface's
+
+    int interfaces_dim;
+    BaseClass* interfaces;		// interfaces[interfaces_dim] for this class
+					// (does not include baseClass)
+
+    BaseClasses vtblInterfaces;	// array of base interfaces that have
+					// their own vtbl[]
+
+    ClassInfoDeclaration vclassinfo;	// the ClassInfo object for this ClassDeclaration
+    bool com;				// true if this is a COM class (meaning
+					// it derives from IUnknown)
+    bool isauto;				// true if this is an auto class
+    bool isabstract;			// true if abstract class
+
+    int inuse;				// to prevent recursive attempts
+
+    this(Loc loc, Identifier id, BaseClasses baseclasses)
+	{
+		super(loc, id);
+		
+		vtbl = new Array();
+		vtblFinal = new Array();
+		
+		enum msg = "only object.d can define this reserved class name";
+
+		if (baseclasses) {
+			this.baseclasses = baseclasses;
+		} else {
+			this.baseclasses = new BaseClasses();
+		}
+
+		//printf("ClassDeclaration(%s), dim = %d\n", id.toChars(), this.baseclasses.dim);
+
+		// For forward references
+		type = new TypeClass(this);
+
+		if (id)
+		{
+			// Look for special class names
+
+			if (id is Id.__sizeof || id is Id.alignof_ || id is Id.mangleof_)
+				error("illegal class name");
+
+			// BUG: What if this is the wrong TypeInfo, i.e. it is nested?
+			if (id.toChars()[0] == 'T')
+			{
+				if (id is Id.TypeInfo)
+				{	
+					if (Type.typeinfo)
+						Type.typeinfo.error("%s", msg);
+					Type.typeinfo = this;
+				}
+
+				if (id is Id.TypeInfo_Class)
+				{	
+					if (Type.typeinfoclass)
+						Type.typeinfoclass.error("%s", msg);
+					Type.typeinfoclass = this;
+				}
+
+				if (id is Id.TypeInfo_Interface)
+				{	
+					if (Type.typeinfointerface)
+						Type.typeinfointerface.error("%s", msg);
+					Type.typeinfointerface = this;
+				}
+
+				if (id is Id.TypeInfo_Struct)
+				{	
+					if (Type.typeinfostruct)
+						Type.typeinfostruct.error("%s", msg);
+					Type.typeinfostruct = this;
+				}
+
+				if (id is Id.TypeInfo_Typedef)
+				{	
+					if (Type.typeinfotypedef)
+						Type.typeinfotypedef.error("%s", msg);
+					Type.typeinfotypedef = this;
+				}
+
+				if (id is Id.TypeInfo_Pointer)
+				{	
+					if (Type.typeinfopointer)
+						Type.typeinfopointer.error("%s", msg);
+					Type.typeinfopointer = this;
+				}
+
+				if (id is Id.TypeInfo_Array)
+				{	
+					if (Type.typeinfoarray)
+						Type.typeinfoarray.error("%s", msg);
+					Type.typeinfoarray = this;
+				}
+
+				if (id is Id.TypeInfo_StaticArray)
+				{	//if (Type.typeinfostaticarray)
+					//Type.typeinfostaticarray.error("%s", msg);
+					Type.typeinfostaticarray = this;
+				}
+
+				if (id is Id.TypeInfo_AssociativeArray)
+				{	
+					if (Type.typeinfoassociativearray)
+						Type.typeinfoassociativearray.error("%s", msg);
+					Type.typeinfoassociativearray = this;
+				}
+
+				if (id is Id.TypeInfo_Enum)
+				{	
+					if (Type.typeinfoenum)
+						Type.typeinfoenum.error("%s", msg);
+					Type.typeinfoenum = this;
+				}
+
+				if (id is Id.TypeInfo_Function)
+				{	
+					if (Type.typeinfofunction)
+						Type.typeinfofunction.error("%s", msg);
+					Type.typeinfofunction = this;
+				}
+
+				if (id is Id.TypeInfo_Delegate)
+				{	
+					if (Type.typeinfodelegate)
+						Type.typeinfodelegate.error("%s", msg);
+					Type.typeinfodelegate = this;
+				}
+
+				if (id is Id.TypeInfo_Tuple)
+				{	
+					if (Type.typeinfotypelist)
+						Type.typeinfotypelist.error("%s", msg);
+					Type.typeinfotypelist = this;
+				}
+
+	version (DMDV2) {
+				if (id is Id.TypeInfo_Const)
+				{	
+					if (Type.typeinfoconst)
+						Type.typeinfoconst.error("%s", msg);
+					Type.typeinfoconst = this;
+				}
+
+				if (id is Id.TypeInfo_Invariant)
+				{	
+					if (Type.typeinfoinvariant)
+						Type.typeinfoinvariant.error("%s", msg);
+					Type.typeinfoinvariant = this;
+				}
+
+				if (id is Id.TypeInfo_Shared)
+				{	
+					if (Type.typeinfoshared)
+						Type.typeinfoshared.error("%s", msg);
+					Type.typeinfoshared = this;
+				}
+	}
+			}
+
+			if (id is Id.Object_)
+			{   
+				if (object)
+					object.error("%s", msg);
+				object = this;
+			}
+
+			if (id is Id.ClassInfo)
+			{   
+				if (classinfo)
+					classinfo.error("%s", msg);
+				classinfo = this;
+			}
+
+			if (id is Id.ModuleInfo)
+			{   
+				if (Module.moduleinfo)
+					Module.moduleinfo.error("%s", msg);
+				Module.moduleinfo = this;
+			}
+		}
+
+		com = 0;
+		isauto = false;
+		isabstract = false;
+		inuse = 0;
+	}
+	
+    override Dsymbol syntaxCopy(Dsymbol s)
+	{
+		ClassDeclaration cd;
+
+		//printf("ClassDeclaration.syntaxCopy('%s')\n", toChars());
+		if (s)
+			cd = cast(ClassDeclaration)s;
+		else
+		cd = new ClassDeclaration(loc, ident, null);
+
+		cd.storage_class |= storage_class;
+
+		cd.baseclasses.setDim(this.baseclasses.dim);
+		for (int i = 0; i < cd.baseclasses.dim; i++)
+		{
+			BaseClass b = cast(BaseClass)this.baseclasses.data[i];
+			BaseClass b2 = new BaseClass(b.type.syntaxCopy(), b.protection);
+			cd.baseclasses.data[i] = cast(void*)b2;
+		}
+
+		ScopeDsymbol.syntaxCopy(cd);
+		return cd;
+	}
+	
+    override void semantic(Scope sc)
+	{
+		int i;
+		uint offset;
+
+		//printf("ClassDeclaration.semantic(%s), type = %p, sizeok = %d, this = %p\n", toChars(), type, sizeok, this);
+		//printf("\tparent = %p, '%s'\n", sc.parent, sc.parent ? sc.parent.toChars() : "");
+		//printf("sc.stc = %x\n", sc.stc);
+
+		//{ static int n;  if (++n == 20) *(char*)0=0; }
+
+		if (!ident)		// if anonymous class
+		{	
+			string id = "__anonclass";
+			ident = Identifier.generateId(id);
+		}
+
+		if (!sc)
+			sc = scope_;
+
+		if (!parent && sc.parent && !sc.parent.isModule())
+			parent = sc.parent;
+
+		type = type.semantic(loc, sc);
+		handle = type;
+
+		if (!members)			// if forward reference
+		{	
+			//printf("\tclass '%s' is forward referenced\n", toChars());
+			return;
+		}
+		if (symtab)
+		{	if (!scope_)
+		{   //printf("\tsemantic for '%s' is already completed\n", toChars());
+			return;		// semantic() already completed
+		}
+		}
+		else
+		symtab = new DsymbolTable();
+
+		Scope scx = null;
+		if (scope_)
+		{	sc = scope_;
+			scx = scope_;		// save so we don't make redundant copies
+		scope_ = null;
+		}
+version (IN_GCC) {
+		methods.setDim(0);
+}
+
+		if (sc.stc & STC.STCdeprecated)
+		{
+		isdeprecated = 1;
+		}
+
+		if (sc.linkage == LINK.LINKcpp)
+		error("cannot create C++ classes");
+
+		// Expand any tuples in baseclasses[]
+		for (i = 0; i < baseclasses.dim; )
+		{	
+			BaseClass b = cast(BaseClass)baseclasses.data[i];
+		//printf("test1 %s %s\n", toChars(), b.type.toChars());
+			b.type = b.type.semantic(loc, sc);
+		//printf("test2\n");
+			Type tb = b.type.toBasetype();
+
+			if (tb.ty == TY.Ttuple)
+			{   
+				TypeTuple tup = cast(TypeTuple)tb;
+				enum PROT protection = b.protection;
+				baseclasses.remove(i);
+				size_t dim = Argument.dim(tup.arguments);
+				for (size_t j = 0; j < dim; j++)
+				{	
+					Argument arg = Argument.getNth(tup.arguments, j);
+					b = new BaseClass(arg.type, protection);
+					baseclasses.insert(i + j, cast(void*)b);
+				}
+			}
+			else
+				i++;
+		}
+
+		// See if there's a base class as first in baseclasses[]
+		if (baseclasses.dim)
+		{	
+			TypeClass tc;
+			BaseClass b;
+			Type tb;
+
+			b = cast(BaseClass)baseclasses.data[0];
+			//b.type = b.type.semantic(loc, sc);
+			tb = b.type.toBasetype();
+			if (tb.ty != TY.Tclass)
+			{   error("base type must be class or interface, not %s", b.type.toChars());
+				baseclasses.remove(0);
+			}
+			else
+			{
+				tc = cast(TypeClass)(tb);
+
+				if (tc.sym.isDeprecated())
+				{
+				if (!isDeprecated())
+				{
+					// Deriving from deprecated class makes this one deprecated too
+					isdeprecated = 1;
+
+					tc.checkDeprecated(loc, sc);
+				}
+				}
+
+				if (tc.sym.isInterfaceDeclaration()) {
+					;
+				} else {
+					for (ClassDeclaration cdb = tc.sym; cdb; cdb = cdb.baseClass)
+					{
+						if (cdb == this)
+						{
+							error("circular inheritance");
+							baseclasses.remove(0);
+							goto L7;
+						}
+					}
+					if (!tc.sym.symtab || tc.sym.sizeok == 0)
+					{   // Try to resolve forward reference
+						if (sc.mustsemantic && tc.sym.scope_)
+						tc.sym.semantic(null);
+					}
+					if (!tc.sym.symtab || tc.sym.scope_ || tc.sym.sizeok == 0)
+					{
+						//printf("%s: forward reference of base class %s\n", toChars(), tc.sym.toChars());
+						//error("forward reference of base class %s", baseClass.toChars());
+						// Forward reference of base class, try again later
+						//printf("\ttry later, forward reference of base class %s\n", tc.sym.toChars());
+						scope_ = scx ? scx : new Scope(sc);
+						scope_.setNoFree();
+						if (tc.sym.scope_)
+							tc.sym.scope_.module_.addDeferredSemantic(tc.sym);
+						scope_.module_.addDeferredSemantic(this);
+						return;
+					}
+					else
+					{   baseClass = tc.sym;
+						b.base = baseClass;
+					}
+				 L7: ;
+				}
+			}
+		}
+
+		// Treat the remaining entries in baseclasses as interfaces
+		// Check for errors, handle forward references
+		for (i = (baseClass ? 1 : 0); i < baseclasses.dim; )
+		{	TypeClass tc;
+		BaseClass b;
+		Type tb;
+
+		b = cast(BaseClass)baseclasses.data[i];
+		b.type = b.type.semantic(loc, sc);
+		tb = b.type.toBasetype();
+		if (tb.ty == TY.Tclass)
+			tc = cast(TypeClass)tb;
+		else
+			tc = null;
+		if (!tc || !tc.sym.isInterfaceDeclaration())
+		{
+			error("base type must be interface, not %s", b.type.toChars());
+			baseclasses.remove(i);
+			continue;
+		}
+		else
+		{
+			if (tc.sym.isDeprecated())
+			{
+			if (!isDeprecated())
+			{
+				// Deriving from deprecated class makes this one deprecated too
+				isdeprecated = 1;
+
+				tc.checkDeprecated(loc, sc);
+			}
+			}
+
+			// Check for duplicate interfaces
+			for (size_t j = (baseClass ? 1 : 0); j < i; j++)
+			{
+			BaseClass b2 = cast(BaseClass)baseclasses.data[j];
+			if (b2.base == tc.sym)
+				error("inherits from duplicate interface %s", b2.base.toChars());
+			}
+
+			if (!tc.sym.symtab)
+			{   // Try to resolve forward reference
+			if (sc.mustsemantic && tc.sym.scope_)
+				tc.sym.semantic(null);
+			}
+
+			b.base = tc.sym;
+			if (!b.base.symtab || b.base.scope_)
+			{
+			//error("forward reference of base class %s", baseClass.toChars());
+			// Forward reference of base, try again later
+			//printf("\ttry later, forward reference of base %s\n", baseClass.toChars());
+			scope_ = scx ? scx : new Scope(sc);
+			scope_.setNoFree();
+			if (tc.sym.scope_)
+				tc.sym.scope_.module_.addDeferredSemantic(tc.sym);
+			scope_.module_.addDeferredSemantic(this);
+			return;
+			}
+		}
+		i++;
+		}
+
+
+		// If no base class, and this is not an Object, use Object as base class
+		if (!baseClass && ident !is Id.Object_)
+		{
+			// BUG: what if Object is redefined in an inner scope?
+			Type tbase = new TypeIdentifier(Loc(0), Id.Object_);
+			BaseClass b;
+			TypeClass tc;
+			Type bt;
+
+			if (!object)
+			{
+				error("missing or corrupt object.d");
+				fatal();
+			}
+			bt = tbase.semantic(loc, sc).toBasetype();
+			b = new BaseClass(bt, PROT.PROTpublic);
+			baseclasses.shift(cast(void*)b);
+			assert(b.type.ty == TY.Tclass);
+			tc = cast(TypeClass)(b.type);
+			baseClass = tc.sym;
+			assert(!baseClass.isInterfaceDeclaration());
+			b.base = baseClass;
+		}
+
+		interfaces_dim = baseclasses.dim;
+		interfaces = cast(BaseClass*)baseclasses.data;
+
+		if (baseClass)
+		{
+			if (baseClass.storage_class & STC.STCfinal)
+				error("cannot inherit from final class %s", baseClass.toChars());
+
+			interfaces_dim--;
+			interfaces++;
+
+			// Copy vtbl[] from base class
+			vtbl.setDim(baseClass.vtbl.dim);
+			memcpy(vtbl.data, baseClass.vtbl.data, (void*).sizeof * vtbl.dim);
+
+			// Inherit properties from base class
+			com = baseClass.isCOMclass();
+			isauto = baseClass.isauto;
+			vthis = baseClass.vthis;
+			storage_class |= baseClass.storage_class & STC.STC_TYPECTOR;
+		}
+		else
+		{
+			// No base class, so this is the root of the class hierarchy
+			vtbl.setDim(0);
+			vtbl.push(cast(void*)this);		// leave room for classinfo as first member
+		}
+
+		protection = sc.protection;
+		storage_class |= sc.stc;
+
+		if (sizeok == 0)
+		{
+		interfaceSemantic(sc);
+
+		for (i = 0; i < members.dim; i++)
+		{
+			Dsymbol s = cast(Dsymbol)members.data[i];
+			s.addMember(sc, this, true);
+		}
+
+		/* If this is a nested class, add the hidden 'this'
+		 * member which is a pointer to the enclosing scope.
+		 */
+		if (vthis)		// if inheriting from nested class
+		{   // Use the base class's 'this' member
+			isnested = true;
+			if (storage_class & STC.STCstatic)
+			error("static class cannot inherit from nested class %s", baseClass.toChars());
+			if (toParent2() != baseClass.toParent2())
+			{
+			if (toParent2())
+			{
+				error("is nested within %s, but super class %s is nested within %s",
+				toParent2().toChars(),
+				baseClass.toChars(),
+				baseClass.toParent2().toChars());
+			}
+			else
+			{
+				error("is not nested, but super class %s is nested within %s",
+				baseClass.toChars(),
+				baseClass.toParent2().toChars());
+			}
+			isnested = false;
+			}
+		}
+		else if (!(storage_class & STC.STCstatic))
+		{   
+			Dsymbol s = toParent2();
+			if (s)
+			{
+				AggregateDeclaration ad = s.isClassDeclaration();
+				FuncDeclaration fd = s.isFuncDeclaration();
+
+				if (ad || fd)
+				{   isnested = true;
+					Type t;
+					if (ad)
+						t = ad.handle;
+					else if (fd)
+					{	
+						AggregateDeclaration ad2 = fd.isMember2();
+						if (ad2)
+							t = ad2.handle;
+						else
+						{
+							t = Type.tvoidptr;
+						}
+					}
+					else
+						assert(0);
+					if (t.ty == TY.Tstruct)	// ref to struct
+						t = Type.tvoidptr;
+					assert(!vthis);
+					vthis = new ThisDeclaration(loc, t);
+					members.push(cast(void*)vthis);
+				}
+			}
+		}
+		}
+
+		if (storage_class & (STC.STCauto | STC.STCscope))
+			isauto = true;
+		if (storage_class & STC.STCabstract)
+			isabstract = true;
+		if (storage_class & STC.STCimmutable)
+			type = type.invariantOf();
+		else if (storage_class & STC.STCconst)
+			type = type.constOf();
+		else if (storage_class & STC.STCshared)
+			type = type.sharedOf();
+
+		sc = sc.push(this);
+		sc.stc &= ~(STC.STCfinal | STC.STCauto | STC.STCscope | STC.STCstatic |
+			 STC.STCabstract | STC.STCdeprecated | STC.STC_TYPECTOR | STC.STCtls | STC.STCgshared);
+		sc.stc |= storage_class & STC.STC_TYPECTOR;
+		sc.parent = this;
+		sc.inunion = 0;
+
+		if (isCOMclass())
+		{
+version (_WIN32) {
+		sc.linkage = LINK.LINKwindows;
+} else {
+		/* This enables us to use COM objects under Linux and
+		 * work with things like XPCOM
+		 */
+		sc.linkage = LINK.LINKc;
+}
+		}
+		sc.protection = PROT.PROTpublic;
+		sc.explicitProtection = 0;
+		sc.structalign = 8;
+		structalign = sc.structalign;
+		if (baseClass)
+		{	sc.offset = baseClass.structsize;
+		alignsize = baseClass.alignsize;
+	//	if (isnested)
+	//	    sc.offset += PTRSIZE;	// room for uplevel context pointer
+		}
+		else
+		{	sc.offset = PTRSIZE * 2;	// allow room for __vptr and __monitor
+		alignsize = PTRSIZE;
+		}
+		structsize = sc.offset;
+		Scope scsave = sc;	/// a copy must be created?
+		int members_dim = members.dim;
+		sizeok = 0;
+		for (i = 0; i < members_dim; i++)
+		{
+			Dsymbol s = cast(Dsymbol)members.data[i];
+			s.semantic(sc);
+		}
+
+		if (sizeok == 2)
+		{	// semantic() failed because of forward references.
+		// Unwind what we did, and defer it for later
+		fields.setDim(0);
+		structsize = 0;
+		alignsize = 0;
+		structalign = 0;
+
+		sc = sc.pop();
+
+		scope_ = scx ? scx : new Scope(sc);
+		scope_.setNoFree();
+		scope_.module_.addDeferredSemantic(this);
+
+		//printf("\tsemantic('%s') failed due to forward references\n", toChars());
+		return;
+		}
+
+		//printf("\tsemantic('%s') successful\n", toChars());
+
+		structsize = sc.offset;
+		//members.print();
+
+		/* Look for special member functions.
+		 * They must be in this class, not in a base class.
+		 */
+		ctor = cast(CtorDeclaration)search(Loc(0), Id.ctor, 0);
+		if (ctor && (ctor.toParent() != this || !ctor.isCtorDeclaration()))
+		ctor = null;
+
+	//    dtor = (DtorDeclaration *)search(Id.dtor, 0);
+	//    if (dtor && dtor.toParent() != this)
+	//	dtor = null;
+
+	//    inv = (InvariantDeclaration *)search(Id.classInvariant, 0);
+	//    if (inv && inv.toParent() != this)
+	//	inv = null;
+
+		// Can be in base class
+		aggNew = cast(NewDeclaration)search(Loc(0), Id.classNew, 0);
+		aggDelete = cast(DeleteDeclaration)search(Loc(0), Id.classDelete, 0);
+
+		// If this class has no constructor, but base class does, create
+		// a constructor:
+		//    this() { }
+		if (!ctor && baseClass && baseClass.ctor)
+		{
+		//printf("Creating default this(){} for class %s\n", toChars());
+		CtorDeclaration ctor = new CtorDeclaration(loc, Loc(0), null, 0);
+		ctor.fbody = new CompoundStatement(Loc(0), new Statements());
+		members.push(cast(void*)ctor);
+		ctor.addMember(sc, this, true);
+		sc = scsave;	// why? What about sc.nofree?	///
+		sc.offset = structsize;
+		ctor.semantic(sc);
+		this.ctor = ctor;
+		defaultCtor = ctor;
+		}
+
+static if (false) {
+		if (baseClass)
+		{	if (!aggDelete)
+			aggDelete = baseClass.aggDelete;
+		if (!aggNew)
+			aggNew = baseClass.aggNew;
+		}
+}
+
+		// Allocate instance of each new interface
+		for (i = 0; i < vtblInterfaces.dim; i++)
+		{
+			BaseClass b = cast(BaseClass)vtblInterfaces.data[i];
+			uint thissize = PTRSIZE;
+
+			alignmember(structalign, thissize, &sc.offset);
+			assert(b.offset == 0);
+			b.offset = sc.offset;
+
+			// Take care of single inheritance offsets
+			while (b.baseInterfaces.length)
+			{
+				b = b.baseInterfaces[0];
+				b.offset = sc.offset;
+			}
+
+			sc.offset += thissize;
+			if (alignsize < thissize)
+				alignsize = thissize;
+		}
+		structsize = sc.offset;
+		sizeok = 1;
+		Module.dprogress++;
+
+		dtor = buildDtor(sc);
+
+		sc.pop();
+
+static if (false) { // Do not call until toObjfile() because of forward references
+		// Fill in base class vtbl[]s
+		for (i = 0; i < vtblInterfaces.dim; i++)
+		{
+			BaseClass b = cast(BaseClass)vtblInterfaces.data[i];
+
+		//b.fillVtbl(this, &b.vtbl, 1);
+		}
+}
+		//printf("-ClassDeclaration.semantic(%s), type = %p\n", toChars(), type);
+	}
+	
+    override void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		if (!isAnonymous())
+		{
+			buf.printf("%s ", kind());
+			buf.writestring(toChars());
+			if (baseclasses.dim)
+				buf.writestring(" : ");
+		}
+		for (int i = 0; i < baseclasses.dim; i++)
+		{
+			BaseClass b = cast(BaseClass)baseclasses.data[i];
+
+			if (i)
+				buf.writeByte(',');
+			//buf.writestring(b.base.ident.toChars());
+			b.type.toCBuffer(buf, null, hgs);
+		}
+		if (members)
+		{
+			buf.writenl();
+			buf.writeByte('{');
+			buf.writenl();
+			for (int i = 0; i < members.dim; i++)
+			{
+				Dsymbol s = cast(Dsymbol)members.data[i];
+
+				buf.writestring("    ");
+				s.toCBuffer(buf, hgs);
+			}
+			buf.writestring("}");
+		}
+		else
+			buf.writeByte(';');
+		buf.writenl();
+	}
+	
+	/*********************************************
+	 * Determine if 'this' is a base class of cd.
+	 * This is used to detect circular inheritance only.
+	 */
+    int isBaseOf2(ClassDeclaration cd)
+	{
+		if (!cd)
+			return 0;
+		//printf("ClassDeclaration::isBaseOf2(this = '%s', cd = '%s')\n", toChars(), cd.toChars());
+		for (int i = 0; i < cd.baseclasses.dim; i++)
+		{	
+			BaseClass b = cast(BaseClass)cd.baseclasses.data[i];
+
+			if (b.base is this || isBaseOf2(b.base))
+				return 1;
+		}
+		return 0;
+	}
+
+	/*******************************************
+	 * Determine if 'this' is a base class of cd.
+	 */
+///    #define OFFSET_RUNTIME 0x76543210
+    bool isBaseOf(ClassDeclaration cd, int* poffset)
+	{
+		if (!cd)
+			return 0;
+		//printf("ClassDeclaration::isBaseOf2(this = '%s', cd = '%s')\n", toChars(), cd.toChars());
+		for (int i = 0; i < cd.baseclasses.dim; i++)
+		{	
+			BaseClass b = cast(BaseClass)cd.baseclasses.data[i];
+
+			if (b.base == this || isBaseOf2(b.base))
+				return 1;
+		}
+
+		return 0;
+	}
+
+    override Dsymbol search(Loc, Identifier ident, int flags)
+	{
+		Dsymbol s;
+		//printf("%s.ClassDeclaration.search('%s')\n", toChars(), ident.toChars());
+
+		if (scope_)
+		{
+			Scope sc = scope_;
+			sc.mustsemantic++;
+			semantic(sc);
+			sc.mustsemantic--;
+		}
+
+		if (!members || !symtab || scope_)
+		{
+			error("is forward referenced when looking for '%s'", ident.toChars());
+			//*(char*)0=0;
+			return null;
+		}
+
+		s = ScopeDsymbol.search(loc, ident, flags);
+		if (!s)
+		{
+			// Search bases classes in depth-first, left to right order
+
+			int i;
+
+			for (i = 0; i < baseclasses.dim; i++)
+			{
+				BaseClass b = cast(BaseClass)baseclasses.data[i];
+
+				if (b.base)
+				{
+					if (!b.base.symtab)
+						error("base %s is forward referenced", b.base.ident.toChars());
+					else
+					{
+						s = b.base.search(loc, ident, flags);
+						if (s is this)	// happens if s is nested in this and derives from this
+							s = null;
+						else if (s)
+							break;
+					}
+				}
+			}
+		}
+		return s;
+	}
+	
+version (DMDV2) {
+    bool isFuncHidden(FuncDeclaration fd)
+	{
+		//printf("ClassDeclaration::isFuncHidden(class = %s, fd = %s)\n", toChars(), fd.toChars());
+		Dsymbol s = search(Loc(0), fd.ident, 4|2);
+		if (!s)
+		{	
+			//printf("not found\n");
+			/* Because, due to a hack, if there are multiple definitions
+			 * of fd.ident, null is returned.
+			 */
+			return false;
+		}
+		
+		Param p; p.fd = fd;
+
+		s = s.toAlias();
+		OverloadSet os = s.isOverloadSet();	
+		if (os)
+		{
+			for (int i = 0; i < os.a.dim; i++)
+			{   
+				Dsymbol s2 = cast(Dsymbol)os.a.data[i];
+				FuncDeclaration f2 = s2.isFuncDeclaration();
+				if (f2 && overloadApply(f2, &p.isf, &p))
+					return false;
+			}
+			return true;
+		}
+		else
+		{
+			FuncDeclaration fdstart = s.isFuncDeclaration();
+			//printf("%s fdstart = %p\n", s.kind(), fdstart);
+			return !overloadApply(fdstart, &p.isf, &p);
+		}
+	}
+}
+    FuncDeclaration findFunc(Identifier ident, TypeFunction tf)
+	{
+		//printf("ClassDeclaration.findFunc(%s, %s) %s\n", ident.toChars(), tf.toChars(), toChars());
+
+		ClassDeclaration cd = this;
+		Array vtbl = cd.vtbl;
+		while (true)
+		{
+			for (size_t i = 0; i < vtbl.dim; i++)
+			{
+				FuncDeclaration fd = (cast(Dsymbol)vtbl.data[i]).isFuncDeclaration();
+				if (!fd)
+					continue;		// the first entry might be a ClassInfo
+
+				//printf("\t[%d] = %s\n", i, fd.toChars());
+				if (ident == fd.ident &&
+					//tf.equals(fd.type)
+					fd.type.covariant(tf) == 1
+				   )
+				{   //printf("\t\tfound\n");
+					return fd;
+				}
+				//else printf("\t\t%d\n", fd.type.covariant(tf));
+			}
+			if (!cd)
+				break;
+
+			vtbl = cd.vtblFinal;
+			cd = cd.baseClass;
+		}
+
+		return null;
+	}
+
+    void interfaceSemantic(Scope sc)
+	{
+		InterfaceDeclaration id = isInterfaceDeclaration();
+
+		vtblInterfaces = new BaseClasses();
+		vtblInterfaces.reserve(interfaces_dim);
+
+		for (size_t i = 0; i < interfaces_dim; i++)
+		{
+			BaseClass b = interfaces[i];
+
+			// If this is an interface, and it derives from a COM interface,
+			// then this is a COM interface too.
+			if (b.base.isCOMinterface())
+				com = 1;
+
+			if (b.base.isCPPinterface() && id)
+				id.cpp = 1;
+
+			vtblInterfaces.push(cast(void*)b);
+			b.copyBaseInterfaces(vtblInterfaces);
+		}
+	}
+
+    bool isCOMclass()
+	{
+		return com;
+	}
+	
+    bool isCOMinterface()
+	{
+		return false;
+	}
+
+version (DMDV2) {
+    bool isCPPinterface()
+	{
+		return false;
+	}
+}
+    bool isAbstract()
+	{
+		if (isabstract)
+			return true;
+
+		for (int i = 1; i < vtbl.dim; i++)
+		{
+			FuncDeclaration fd = (cast(Dsymbol)vtbl.data[i]).isFuncDeclaration();
+
+			//printf("\tvtbl[%d] = %p\n", i, fd);
+			if (!fd || fd.isAbstract())
+			{
+				isabstract = true;
+				return true;
+			}
+		}
+
+		return false;
+	}
+	
+    int vtblOffset()
+	{
+		assert(false);
+	}
+	
+    override string kind()
+	{
+		return "class";
+	}
+	
+    override string mangle()
+	{
+		Dsymbol parentsave = parent;
+
+		//printf("ClassDeclaration.mangle() %s.%s\n", parent.toChars(), toChars());
+
+		/* These are reserved to the compiler, so keep simple
+		 * names for them.
+		 */
+		if (ident is Id.Exception)
+		{	
+			if (parent.ident is Id.object)
+				parent = null;
+		}
+		else if (ident is Id.TypeInfo   ||
+		//	ident is Id.Exception ||
+			ident is Id.TypeInfo_Struct   ||
+			ident is Id.TypeInfo_Class    ||
+			ident is Id.TypeInfo_Typedef  ||
+			ident is Id.TypeInfo_Tuple ||
+			this is object     ||
+			this is classinfo  ||
+			this is Module.moduleinfo ||
+			ident.toChars().startsWith("TypeInfo_")
+		   )
+		{
+			parent = null;
+		}
+
+		string id = Dsymbol.mangle();
+		parent = parentsave;
+		return id;
+	}
+	
+    override void toDocBuffer(OutBuffer buf)
+	{
+		assert(false);
+	}
+
+    override PROT getAccess(Dsymbol smember)	// determine access to smember
+	{
+		PROT access_ret = PROT.PROTnone;
+
+	version (LOG) {
+		printf("+ClassDeclaration::getAccess(this = '%s', smember = '%s')\n",
+			toChars(), smember.toChars());
+	}
+		if (smember.toParent() is this)
+		{
+			access_ret = smember.prot();
+		}
+		else
+		{
+			PROT access;
+			int i;
+
+			if (smember.isDeclaration().isStatic())
+			{
+				access_ret = smember.prot();
+			}
+
+			for (i = 0; i < baseclasses.dim; i++)
+			{   
+				BaseClass b = cast(BaseClass)baseclasses.data[i];
+
+				access = b.base.getAccess(smember);
+				switch (access)
+				{
+					case PROT.PROTnone:
+						break;
+
+					case PROT.PROTprivate:
+						access = PROT.PROTnone;	// private members of base class not accessible
+						break;
+
+					case PROT.PROTpackage:
+					case PROT.PROTprotected:
+					case PROT.PROTpublic:
+					case PROT.PROTexport:
+						// If access is to be tightened
+						if (b.protection < access)
+							access = b.protection;
+
+						// Pick path with loosest access
+						if (access > access_ret)
+							access_ret = access;
+						break;
+
+					default:
+						assert(0);
+				}
+			}
+		}
+
+	version (LOG) {
+		printf("-ClassDeclaration::getAccess(this = '%s', smember = '%s') = %d\n",
+			toChars(), smember.toChars(), access_ret);
+	}
+
+		return access_ret;
+	}
+
+    override void addLocalClass(ClassDeclarations aclasses)
+	{
+		aclasses.push(cast(void*)this);
+	}
+
+    // Back end
+    override void toObjFile(int multiobj)			// compile to .obj file
+	{
+		uint i;
+		uint offset;
+		Symbol* sinit;
+		enum_SC scclass;
+
+		//printf("ClassDeclaration.toObjFile('%s')\n", toChars());
+
+		if (!members)
+			return;
+
+		if (multiobj)
+		{	
+			obj_append(this);
+			return;
+		}
+
+		if (global.params.symdebug)
+			toDebug();
+
+		assert(!scope_);	// semantic() should have been run to completion
+
+		scclass = SCglobal;
+		if (inTemplateInstance())
+			scclass = SCcomdat;
+
+		// Put out the members
+		for (i = 0; i < members.dim; i++)
+		{
+			Dsymbol member;
+
+			member = cast(Dsymbol)members.data[i];
+			member.toObjFile(0);
+		}
+
+static if (false) {
+		// Build destructor by aggregating dtors[]
+		Symbol* sdtor;
+		switch (dtors.dim)
+		{	
+			case 0:
+				// No destructors for this class
+				sdtor = null;
+				break;
+
+			case 1:
+				// One destructor, just use it directly
+				sdtor = (cast(DtorDeclaration)dtors.data[0]).toSymbol();
+				break;
+
+			default:
+			{   
+				/* Build a destructor that calls all the
+				 * other destructors in dtors[].
+				 */
+
+				elem* edtor = null;
+
+				// Declare 'this' pointer for our new destructor
+				Symbol* sthis = symbol_calloc("this");
+				sthis.Stype = type_fake(TYnptr);
+				sthis.Stype.Tcount++;
+				sthis.Sclass = SCfastpar;
+				sthis.Spreg = AX;
+				sthis.Sfl = FLauto;
+
+				// Call each of the destructors in dtors[]
+				// in reverse order
+				for (i = 0; i < dtors.dim; i++)
+				{	
+					DtorDeclaration d = cast(DtorDeclaration)dtors.data[i];
+					Symbol* s = d.toSymbol();
+					elem* e = el_bin(OPcall, TYvoid, el_var(s), el_var(sthis));
+					edtor = el_combine(e, edtor);
+				}
+
+				// Create type for the function
+				.type* t = type_alloc(TYjfunc);
+				t.Tflags |= TFprototype | TFfixed;
+				t.Tmangle = mTYman_d;
+				t.Tnext = tsvoid;
+				tsvoid.Tcount++;
+
+				// Create the function, sdtor, and write it out
+				localgot = null;
+				sdtor = toSymbolX("__dtor", SCglobal, t, "FZv");
+				block* b = block_calloc();
+				b.BC = BCret;
+				b.Belem = edtor;
+				sdtor.Sfunc.Fstartblock = b;
+				cstate.CSpsymtab = &sdtor.Sfunc.Flocsym;
+				symbol_add(sthis);
+				writefunc(sdtor);
+			}
+		}
+}
+
+		// Generate C symbols
+		toSymbol();
+		toVtblSymbol();
+		sinit = toInitializer();
+
+		//////////////////////////////////////////////
+
+		// Generate static initializer
+		sinit.Sclass = scclass;
+		sinit.Sfl = FLdata;
+	version (ELFOBJ) { // Burton
+		sinit.Sseg = Segment.CDATA;
+	}
+	version (MACHOBJ) {
+		sinit.Sseg = Segment.DATA;
+	}
+		toDt(&sinit.Sdt);
+		outdata(sinit);
+
+		//////////////////////////////////////////////
+
+		// Put out the TypeInfo
+		type.getTypeInfo(null);
+		type.vtinfo.toObjFile(multiobj);
+
+		//////////////////////////////////////////////
+
+		// Put out the ClassInfo
+		csym.Sclass = scclass;
+		csym.Sfl = FLdata;
+
+		/* The layout is:
+		   {
+			void **vptr;
+			monitor_t monitor;
+			byte[] initializer;		// static initialization data
+			char[] name;		// class name
+			void *[] vtbl;
+			Interface[] interfaces;
+			ClassInfo *base;		// base class
+			void *destructor;
+			void *invariant;		// class invariant
+			uint flags;
+			void *deallocator;
+			OffsetTypeInfo[] offTi;
+			void *defaultConstructor;
+			const(MemberInfo[]) function(string) xgetMembers;	// module getMembers() function
+			TypeInfo typeinfo;
+		   }
+		 */
+		dt_t* dt = null;
+		offset = CLASSINFO_SIZE;			// must be ClassInfo.size
+		if (classinfo)
+		{
+			if (classinfo.structsize != CLASSINFO_SIZE)
+				error("D compiler and phobos' object.d are mismatched");
+		}
+
+		if (classinfo)
+			dtxoff(&dt, classinfo.toVtblSymbol(), 0, TYnptr); // vtbl for ClassInfo
+		else
+			dtdword(&dt, 0);		// BUG: should be an assert()
+
+		dtdword(&dt, 0);			// monitor
+
+		// initializer[]
+		assert(structsize >= 8);
+		dtdword(&dt, structsize);		// size
+		dtxoff(&dt, sinit, 0, TYnptr);	// initializer
+
+		// name[]
+		string name = ident.toChars();
+		size_t namelen = name.length;
+		if (!(namelen > 9 && name[0..9] == "TypeInfo_"))
+		{	
+			name = toPrettyChars();
+			namelen = name.length;
+		}
+		dtdword(&dt, namelen);
+		dtabytes(&dt, TYnptr, 0, namelen + 1, toStringz(name));
+
+		// vtbl[]
+		dtdword(&dt, vtbl.dim);
+		dtxoff(&dt, vtblsym, 0, TYnptr);
+
+		// interfaces[]
+		dtdword(&dt, vtblInterfaces.dim);
+		if (vtblInterfaces.dim)
+			dtxoff(&dt, csym, offset, TYnptr);	// (*)
+		else
+			dtdword(&dt, 0);
+
+		// base
+		if (baseClass)
+			dtxoff(&dt, baseClass.toSymbol(), 0, TYnptr);
+		else
+			dtdword(&dt, 0);
+
+		// destructor
+		if (dtor)
+			dtxoff(&dt, dtor.toSymbol(), 0, TYnptr);
+		else
+			dtdword(&dt, 0);
+
+		// invariant
+		if (inv)
+			dtxoff(&dt, inv.toSymbol(), 0, TYnptr);
+		else
+			dtdword(&dt, 0);
+
+		// flags
+		int flags = 4 | isCOMclass();
+	version (DMDV2) {
+		flags |= 16;
+	}
+		flags |= 32;
+
+		if (ctor)
+			flags |= 8;
+		for (ClassDeclaration cd = this; cd; cd = cd.baseClass)
+		{
+			if (cd.members)
+			{
+				for (size_t j = 0; j < cd.members.dim; j++)
+				{
+					Dsymbol sm = cast(Dsymbol)cd.members.data[j];
+					//printf("sm = %s %s\n", sm.kind(), sm.toChars());
+					if (sm.hasPointers())
+						goto L2;
+				}
+			}
+		}
+		flags |= 2;			// no pointers
+	  L2:
+		dtdword(&dt, flags);
+
+
+		// deallocator
+		if (aggDelete)
+			dtxoff(&dt, aggDelete.toSymbol(), 0, TYnptr);
+		else
+			dtdword(&dt, 0);
+
+		// offTi[]
+		dtdword(&dt, 0);
+		dtdword(&dt, 0);		// null for now, fix later
+
+		// defaultConstructor
+		if (defaultCtor)
+			dtxoff(&dt, defaultCtor.toSymbol(), 0, TYnptr);
+		else
+			dtdword(&dt, 0);
+
+	version (DMDV2) {
+		FuncDeclaration sgetmembers = findGetMembers();
+		if (sgetmembers)
+			dtxoff(&dt, sgetmembers.toSymbol(), 0, TYnptr);
+		else
+			dtdword(&dt, 0);	// module getMembers() function
+	}
+
+		dtxoff(&dt, type.vtinfo.toSymbol(), 0, TYnptr);	// typeinfo
+		//dtdword(&dt, 0);
+
+		//////////////////////////////////////////////
+
+		// Put out vtblInterfaces.data[]. Must immediately follow csym, because
+		// of the fixup (*)
+
+		offset += vtblInterfaces.dim * (4 * PTRSIZE);
+		for (i = 0; i < vtblInterfaces.dim; i++)
+		{	
+			BaseClass b = cast(BaseClass)vtblInterfaces.data[i];
+			ClassDeclaration id = b.base;
+
+			/* The layout is:
+			 *  {
+			 *	ClassInfo *interface;
+			 *	void *[] vtbl;
+			 *	unsigned offset;
+			 *  }
+			 */
+
+			// Fill in vtbl[]
+			b.fillVtbl(this, b.vtbl, 1);
+
+			dtxoff(&dt, id.toSymbol(), 0, TYnptr);		// ClassInfo
+
+			// vtbl[]
+			dtdword(&dt, id.vtbl.dim);
+			dtxoff(&dt, csym, offset, TYnptr);
+
+			dtdword(&dt, b.offset);			// this offset
+
+			offset += id.vtbl.dim * PTRSIZE;
+		}
+
+		// Put out the vtblInterfaces.data[].vtbl[]
+		// This must be mirrored with ClassDeclaration.baseVtblOffset()
+		//printf("putting out %d interface vtbl[]s for '%s'\n", vtblInterfaces.dim, toChars());
+		for (i = 0; i < vtblInterfaces.dim; i++)
+		{	
+			BaseClass b = cast(BaseClass)vtblInterfaces.data[i];
+			ClassDeclaration id = b.base;
+			int j;
+
+			//printf("    interface[%d] is '%s'\n", i, id.toChars());
+			j = 0;
+			if (id.vtblOffset())
+			{
+				// First entry is ClassInfo reference
+				//dtxoff(&dt, id.toSymbol(), 0, TYnptr);
+
+				// First entry is struct Interface reference
+				dtxoff(&dt, csym, CLASSINFO_SIZE + i * (4 * PTRSIZE), TYnptr);
+				j = 1;
+			}
+			
+			assert(id.vtbl.dim == b.vtbl.dim);
+			for (; j < id.vtbl.dim; j++)
+			{
+				FuncDeclaration fd;
+
+				assert(j < b.vtbl.dim);
+		static if (false) {
+				Object o = cast(Object)b.vtbl.data[j];
+				if (o)
+				{
+					printf("o = %p\n", o);
+					assert(o.dyncast() == DYNCAST_DSYMBOL);
+					Dsymbol s = cast(Dsymbol)o;
+					printf("s.kind() = '%s'\n", s.kind());
+				}
+		}
+				fd = cast(FuncDeclaration)b.vtbl.data[j];
+				if (fd)
+					dtxoff(&dt, fd.toThunkSymbol(b.offset), 0, TYnptr);
+				else
+					dtdword(&dt, 0);
+			}
+		}
+
+	static if (true) {
+		// Put out the overriding interface vtbl[]s.
+		// This must be mirrored with ClassDeclaration.baseVtblOffset()
+		//printf("putting out overriding interface vtbl[]s for '%s' at offset x%x\n", toChars(), offset);
+		ClassDeclaration cd;
+		scope Array bvtbl = new Array();
+
+		for (cd = this.baseClass; cd; cd = cd.baseClass)
+		{
+			for (int k = 0; k < cd.vtblInterfaces.dim; k++)
+			{   
+				BaseClass bs = cast(BaseClass)cd.vtblInterfaces.data[k];
+
+				if (bs.fillVtbl(this, bvtbl, 0))
+				{
+					//printf("\toverriding vtbl[] for %s\n", bs.base.toChars());
+					ClassDeclaration id = bs.base;
+					int j;
+
+					j = 0;
+					if (id.vtblOffset())
+					{
+						// First entry is ClassInfo reference
+						//dtxoff(&dt, id.toSymbol(), 0, TYnptr);
+
+						// First entry is struct Interface reference
+						dtxoff(&dt, cd.toSymbol(), CLASSINFO_SIZE + k * (4 * PTRSIZE), TYnptr);
+						j = 1;
+					}
+
+					for (; j < id.vtbl.dim; j++)
+					{
+						assert(j < bvtbl.dim);
+						FuncDeclaration fd = cast(FuncDeclaration)bvtbl.data[j];
+						if (fd)
+							dtxoff(&dt, fd.toThunkSymbol(bs.offset), 0, TYnptr);
+						else
+							dtdword(&dt, 0);
+					}
+				}
+			}
+		}
+	}
+	
+	version (INTERFACE_VIRTUAL) {
+		// Put out the overriding interface vtbl[]s.
+		// This must be mirrored with ClassDeclaration.baseVtblOffset()
+		//printf("putting out overriding interface vtbl[]s for '%s' at offset x%x\n", toChars(), offset);
+		for (i = 0; i < vtblInterfaces.dim; i++)
+		{	
+			BaseClass b = cast(BaseClass)vtblInterfaces.data[i];
+			ClassDeclaration cd;
+
+			for (cd = this.baseClass; cd; cd = cd.baseClass)
+			{
+				for (int k = 0; k < cd.vtblInterfaces.dim; k++)
+				{	
+					BaseClass bs = cast(BaseClass)cd.vtblInterfaces.data[k];
+
+					if (b.base == bs.base)
+					{
+						//printf("\toverriding vtbl[] for %s\n", b.base.toChars());
+						ClassDeclaration id = b.base;
+						int j;
+
+						j = 0;
+						if (id.vtblOffset())
+						{
+							// First entry is ClassInfo reference
+							//dtxoff(&dt, id.toSymbol(), 0, TYnptr);
+
+							// First entry is struct Interface reference
+							dtxoff(&dt, cd.toSymbol(), CLASSINFO_SIZE + k * (4 * PTRSIZE), TYnptr);
+							j = 1;
+						}
+
+						for (; j < id.vtbl.dim; j++)
+						{
+							assert(j < b.vtbl.dim);
+							FuncDeclaration fd = cast(FuncDeclaration)b.vtbl.data[j];
+							if (fd)
+								dtxoff(&dt, fd.toThunkSymbol(bs.offset), 0, TYnptr);
+							else
+								dtdword(&dt, 0);
+						}
+					}
+				}
+			}
+		}
+	}
+
+
+		csym.Sdt = dt;
+	version (ELFOBJ_OR_MACHOBJ) { // Burton
+		// ClassInfo cannot be const data, because we use the monitor on it
+		csym.Sseg = Segment.DATA;
+	}
+		outdata(csym);
+		if (isExport())
+			obj_export(csym,0);
+
+		//////////////////////////////////////////////
+
+		// Put out the vtbl[]
+		//printf("putting out %s.vtbl[]\n", toChars());
+		dt = null;
+		if (0)
+			i = 0;
+		else
+		{	
+			dtxoff(&dt, csym, 0, TYnptr);		// first entry is ClassInfo reference
+			i = 1;
+		}
+		for (; i < vtbl.dim; i++)
+		{
+			FuncDeclaration fd = (cast(Dsymbol)vtbl.data[i]).isFuncDeclaration();
+
+			//printf("\tvtbl[%d] = %p\n", i, fd);
+			if (fd && (fd.fbody || !isAbstract()))
+			{   
+				Symbol* s = fd.toSymbol();
+
+		version (DMDV2) {
+				if (isFuncHidden(fd))
+				{	
+					/* fd is hidden from the view of this class.
+					 * If fd overlaps with any function in the vtbl[], then
+					 * issue 'hidden' error.
+					 */
+					for (int j = 1; j < vtbl.dim; j++)
+					{   
+						if (j == i)
+							continue;
+						FuncDeclaration fd2 = (cast(Dsymbol)vtbl.data[j]).isFuncDeclaration();
+						if (!fd2.ident.equals(fd.ident))
+							continue;
+						if (fd.leastAsSpecialized(fd2) || fd2.leastAsSpecialized(fd))
+						{
+							if (global.params.warnings)
+							{
+								TypeFunction tf = cast(TypeFunction)fd.type;
+								if (tf.ty == Tfunction)
+									warning("%s%s is hidden by %s\n", fd.toPrettyChars(), Argument.argsTypesToChars(tf.parameters, tf.varargs), toChars());
+								else
+									warning("%s is hidden by %s\n", fd.toPrettyChars(), toChars());
+							}
+							s = rtlsym[RTLSYM_DHIDDENFUNC];
+							break;
+						}
+					}
+				}
+		}
+				dtxoff(&dt, s, 0, TYnptr);
+			}
+			else
+				dtdword(&dt, 0);
+		}
+
+		vtblsym.Sdt = dt;
+		vtblsym.Sclass = scclass;
+		vtblsym.Sfl = FLdata;
+	version (ELFOBJ) {
+		vtblsym.Sseg = Segment.CDATA;
+	}
+	version (MACHOBJ) {
+		vtblsym.Sseg = Segment.DATA;
+	}
+		outdata(vtblsym);
+		if (isExport())
+			obj_export(vtblsym,0);
+	}
+	
+    void toDebug()
+	{
+		assert(false);
+	}
+	
+	/******************************************
+	 * Get offset of base class's vtbl[] initializer from start of csym.
+	 * Returns ~0 if not this csym.
+	 */
+    uint baseVtblOffset(BaseClass bc)
+	{
+		uint csymoffset;
+		int i;
+
+		//printf("ClassDeclaration.baseVtblOffset('%s', bc = %p)\n", toChars(), bc);
+		csymoffset = CLASSINFO_SIZE;
+		csymoffset += vtblInterfaces.dim * (4 * PTRSIZE);
+
+		for (i = 0; i < vtblInterfaces.dim; i++)
+		{
+			BaseClass b = cast(BaseClass)vtblInterfaces.data[i];
+
+			if (b == bc)
+				return csymoffset;
+			csymoffset += b.base.vtbl.dim * PTRSIZE;
+		}
+
+	static if (true) {
+		// Put out the overriding interface vtbl[]s.
+		// This must be mirrored with ClassDeclaration.baseVtblOffset()
+		//printf("putting out overriding interface vtbl[]s for '%s' at offset x%x\n", toChars(), offset);
+		ClassDeclaration cd;
+		Array bvtbl;
+
+		for (cd = this.baseClass; cd; cd = cd.baseClass)
+		{
+			for (int k = 0; k < cd.vtblInterfaces.dim; k++)
+			{   
+				BaseClass bs = cast(BaseClass)cd.vtblInterfaces.data[k];
+
+				if (bs.fillVtbl(this, null, 0))
+				{
+					if (bc == bs)
+					{   
+						//printf("\tcsymoffset = x%x\n", csymoffset);
+						return csymoffset;
+					}
+					csymoffset += bs.base.vtbl.dim * PTRSIZE;
+				}
+			}
+		}
+	}
+	version (INTERFACE_VIRTUAL) {
+		for (i = 0; i < vtblInterfaces.dim; i++)
+		{	
+			BaseClass b = cast(BaseClass)vtblInterfaces.data[i];
+			ClassDeclaration cd;
+
+			for (cd = this.baseClass; cd; cd = cd.baseClass)
+			{
+				//printf("\tbase class %s\n", cd.toChars());
+				for (int k = 0; k < cd.vtblInterfaces.dim; k++)
+				{	
+					BaseClass bs = cast(BaseClass)cd.vtblInterfaces.data[k];
+
+					if (bc == bs)
+					{   
+						//printf("\tcsymoffset = x%x\n", csymoffset);
+						return csymoffset;
+					}
+					if (b.base == bs.base)
+						csymoffset += bs.base.vtbl.dim * PTRSIZE;
+				}
+			}
+		}
+	}
+
+		return ~0;
+	}
+	
+	static private __gshared Classsym* scc;
+
+	/*************************************
+	 * Create the "ClassInfo" symbol
+	 */
+    override Symbol* toSymbol()
+	{
+		if (!csym)
+		{
+			Symbol* s;
+
+			if (!scc)
+				scc = fake_classsym(Id.ClassInfo);
+
+			s = toSymbolX("__Class", SC.SCextern, scc.Stype, "Z");
+			s.Sfl = FL.FLextern;
+			s.Sflags |= SFL.SFLnodebug;
+			csym = s;
+			slist_add(s);
+		}
+
+		return csym;
+	}
+
+	/*************************************
+	 * This is accessible via the ClassData, but since it is frequently
+	 * needed directly (like for rtti comparisons), make it directly accessible.
+	 */
+    Symbol* toVtblSymbol()
+	{
+		if (!vtblsym)
+		{
+			if (!csym)
+				toSymbol();
+
+			TYPE* t = type_alloc(TYM.TYnptr | mTY.mTYconst);
+			t.Tnext = tsvoid;
+			t.Tnext.Tcount++;
+			t.Tmangle = mTYman.mTYman_d;
+
+			Symbol* s = toSymbolX("__vtbl", SC.SCextern, t, "Z");
+			s.Sflags |= SFL.SFLnodebug;
+			s.Sfl = FL.FLextern;
+			vtblsym = s;
+			slist_add(s);
+		}
+		return vtblsym;
+	}
+	
+	// Generate the data for the static initializer.
+    void toDt(dt_t **pdt)
+	{
+		//printf("ClassDeclaration.toDt(this = '%s')\n", toChars());
+
+		// Put in first two members, the vtbl[] and the monitor
+		dtxoff(pdt, toVtblSymbol(), 0, TYnptr);
+		dtdword(pdt, 0);			// monitor
+
+		// Put in the rest
+		toDt2(pdt, this);
+
+		//printf("-ClassDeclaration.toDt(this = '%s')\n", toChars());
+	}
+	
+    void toDt2(dt_t** pdt, ClassDeclaration cd)
+	{
+		uint offset;
+		uint i;
+		dt_t* dt;
+		uint csymoffset;
+
+	version (LOG) {
+		printf("ClassDeclaration.toDt2(this = '%s', cd = '%s')\n", toChars(), cd.toChars());
+	}
+		if (baseClass)
+		{
+			baseClass.toDt2(pdt, cd);
+			offset = baseClass.structsize;
+		}
+		else
+		{
+			offset = 8;
+		}
+
+		// Note equivalence of this loop to struct's
+		for (i = 0; i < fields.dim; i++)
+		{
+			VarDeclaration v = cast(VarDeclaration)fields.data[i];
+			Initializer init;
+
+			//printf("\t\tv = '%s' v.offset = %2d, offset = %2d\n", v.toChars(), v.offset, offset);
+			dt = null;
+			init = v.init;
+			if (init)
+			{   
+				//printf("\t\t%s has initializer %s\n", v.toChars(), init.toChars());
+				ExpInitializer ei = init.isExpInitializer();
+				Type tb = v.type.toBasetype();
+				if (ei && tb.ty == Tsarray)
+					(cast(TypeSArray)tb).toDtElem(&dt, ei.exp);
+				else
+					dt = init.toDt();
+			}
+			else if (v.offset >= offset)
+			{   //printf("\t\tdefault initializer\n");
+				v.type.toDt(&dt);
+			}
+			if (dt)
+			{
+				if (v.offset < offset)
+					error("duplicated union initialization for %s", v.toChars());
+				else
+				{
+					if (offset < v.offset)
+						dtnzeros(pdt, v.offset - offset);
+					dtcat(pdt, dt);
+					offset = v.offset + cast(uint)v.type.size();
+				}
+			}
+		}
+
+		// Interface vptr initializations
+		toSymbol();						// define csym
+
+		for (i = 0; i < vtblInterfaces.dim; i++)
+		{	
+			BaseClass b = cast(BaseClass)vtblInterfaces.data[i];
+
+///		version (1 || INTERFACE_VIRTUAL) {
+			for (ClassDeclaration cd2 = cd; 1; cd2 = cd2.baseClass)
+			{
+				assert(cd2);
+				csymoffset = cd2.baseVtblOffset(b);
+				if (csymoffset != ~0)
+				{
+					if (offset < b.offset)
+						dtnzeros(pdt, b.offset - offset);
+					dtxoff(pdt, cd2.toSymbol(), csymoffset, TYnptr);
+					break;
+				}
+			}
+///		} else {
+///			csymoffset = baseVtblOffset(b);
+///			assert(csymoffset != ~0);
+///			dtxoff(pdt, csym, csymoffset, TYnptr);
+///		}
+			offset = b.offset + 4;
+		}
+
+		if (offset < structsize)
+			dtnzeros(pdt, structsize - offset);
+	}
+
+    Symbol* vtblsym;
+
+    ///ClassDeclaration isClassDeclaration() { return cast(ClassDeclaration)this; }	/// huh?
+    override ClassDeclaration isClassDeclaration() { return this; }
+}
--- a/dmd/DelegateExp.d	Sat Aug 28 16:19:48 2010 +0200
+++ b/dmd/DelegateExp.d	Sat Aug 28 19:42:41 2010 +0400
@@ -28,9 +28,9 @@
 class DelegateExp : UnaExp
 {
 	FuncDeclaration func;
-	int hasOverloads;
+	bool hasOverloads;
 
-	this(Loc loc, Expression e, FuncDeclaration f, int hasOverloads = 0)
+	this(Loc loc, Expression e, FuncDeclaration f, bool hasOverloads = false)
 	{
 		super(loc, TOK.TOKdelegate, DelegateExp.sizeof, e);
 		this.func = f;
--- a/dmd/DivAssignExp.d	Sat Aug 28 16:19:48 2010 +0200
+++ b/dmd/DivAssignExp.d	Sat Aug 28 19:42:41 2010 +0400
@@ -54,6 +54,7 @@
 		typeCombine(sc);
 		e1.checkArithmetic();
 		e2.checkArithmetic();
+	    checkComplexMulAssign();
 		if (e2.type.isimaginary())
 		{	
 			Type t1;
--- a/dmd/DotVarExp.d	Sat Aug 28 16:19:48 2010 +0200
+++ b/dmd/DotVarExp.d	Sat Aug 28 19:42:41 2010 +0400
@@ -41,9 +41,9 @@
 {
 	Declaration var;
 
-	int hasOverloads;
+	bool hasOverloads;
 
-	this(Loc loc, Expression e, Declaration var, int hasOverloads = 0)
+	this(Loc loc, Expression e, Declaration var, bool hasOverloads = false)
 	{
 		super(loc, TOK.TOKdotvar, DotVarExp.sizeof, e);
 		//printf("DotVarExp()\n");
--- a/dmd/Dsymbol.d	Sat Aug 28 16:19:48 2010 +0200
+++ b/dmd/Dsymbol.d	Sat Aug 28 19:42:41 2010 +0400
@@ -843,7 +843,7 @@
 		id = cast(char*) GC.malloc(2 + nlen + size_t.sizeof * 3 + prefix.length + suffix.length + 1);
 		else
 		id = cast(char*) alloca(2 + nlen + size_t.sizeof * 3 + prefix.length + suffix.length + 1);
-		sprintf(id, "_D%.*s%lu%.*s%.*s", n, prefix.length, prefix, suffix);
+	    sprintf(id, "_D%.*s%zu%.*s%.*s", n, prefix.length, prefix, suffix);
 		
 	static if (false) {
 		if (global.params.isWindows && (type_mangle(t) == mTYman.mTYman_c || type_mangle(t) == mTYman.mTYman_std))
--- a/dmd/DsymbolExp.d	Sat Aug 28 16:19:48 2010 +0200
+++ b/dmd/DsymbolExp.d	Sat Aug 28 19:42:41 2010 +0400
@@ -36,9 +36,9 @@
 class DsymbolExp : Expression
 {
 	Dsymbol s;
-	int hasOverloads;
+	bool hasOverloads;
 
-	this(Loc loc, Dsymbol s, int hasOverloads = 0)
+	this(Loc loc, Dsymbol s, bool hasOverloads = false)
 	{
 		super(loc, TOK.TOKdsymbol, DsymbolExp.sizeof);
 		this.s = s;
--- a/dmd/ErrorExp.d	Sat Aug 28 16:19:48 2010 +0200
+++ b/dmd/ErrorExp.d	Sat Aug 28 19:42:41 2010 +0400
@@ -3,6 +3,7 @@
 import dmd.OutBuffer;
 import dmd.IntegerExp;
 import dmd.Loc;
+import dmd.TOK;
 import dmd.HdrGenState;
 import dmd.Type;
 
@@ -15,6 +16,7 @@
 	this()
 	{
 		super(Loc(0), 0, Type.terror);
+	    op = TOKerror;
 	}
 
 	override void toCBuffer(OutBuffer buf, HdrGenState* hgs)
--- a/dmd/ExpInitializer.d	Sat Aug 28 16:19:48 2010 +0200
+++ b/dmd/ExpInitializer.d	Sat Aug 28 19:42:41 2010 +0400
@@ -1,6 +1,7 @@
 module dmd.ExpInitializer;
 
 import dmd.Initializer;
+import dmd.DelegateExp;
 import dmd.Loc;
 import dmd.Scope;
 import dmd.Type;
@@ -83,6 +84,15 @@
 			if (se.hasOverloads && !se.var.isFuncDeclaration().isUnique())
 				exp.error("cannot infer type from overloaded function symbol %s", exp.toChars());
 		}
+		
+	    // Give error for overloaded function addresses
+		if (exp.op == TOKdelegate)
+		{   
+			DelegateExp se = cast(DelegateExp)exp;
+			if (se.func.isFuncDeclaration() && !se.func.isFuncDeclaration().isUnique())
+				exp.error("cannot infer type from overloaded function symbol %s", exp.toChars());
+		}
+
 
 		Type t = exp.type;
 		if (!t)
--- a/dmd/Expression.d	Sat Aug 28 16:19:48 2010 +0200
+++ b/dmd/Expression.d	Sat Aug 28 19:42:41 2010 +0400
@@ -530,7 +530,11 @@
 	{
 		IntRange ir;
 		ir.imin = 0;
-		ir.imax = type.sizemask();
+	    if (type.isintegral())
+			ir.imax = type.sizemask();
+		else
+			ir.imax = 0xFFFFFFFFFFFFFFFFUL; // assume the worst
+
 		return ir;
 	}
 	
@@ -741,8 +745,9 @@
     Expression deref()
 	{
 		//printf("Expression::deref()\n");
-		if (type.ty == TY.Treference)
-		{	
+	    // type could be null if forward referencing an 'auto' variable
+		if (type && type.ty == Treference)
+		{
 			Expression e = new PtrExp(loc, this);
 			e.type = (cast(TypeReference)type).next;
 			return e;
@@ -863,7 +868,11 @@
 	{
 		if (flag == 0)
 		{	
-			if (op == TOKimport)
+			if (op == TOKerror)
+			{
+				// Error should have already been printed
+			}
+			else if (op == TOKimport)
 				error("%s has no effect", toChars());
 			else
 				error("%s has no effect in expression (%s)",
--- a/dmd/ForeachStatement.d	Sat Aug 28 16:19:48 2010 +0200
+++ b/dmd/ForeachStatement.d	Sat Aug 28 19:42:41 2010 +0400
@@ -659,7 +659,7 @@
 						case TY.Tdchar:	flag += 2; break;
 					}
 					string r = (op == TOK.TOKforeach_reverse) ? "R" : "";
-					int j = sprintf(fdname.ptr, "_aApply%.*s%.*s%ld".ptr, r, 2, fntab[flag].ptr, dim);
+					int j = sprintf(fdname.ptr, "_aApply%.*s%.*s%zd".ptr, r, 2, fntab[flag].ptr, dim);
 					assert(j < fdname.sizeof);
 					fdapply = FuncDeclaration.genCfunc(Type.tindex, fdname[0..j].idup);
 
--- a/dmd/FuncDeclaration.d	Sat Aug 28 16:19:48 2010 +0200
+++ b/dmd/FuncDeclaration.d	Sat Aug 28 19:42:41 2010 +0400
@@ -4,6 +4,9 @@
 import dmd.DotIdExp;
 import dmd.AddrExp;
 import dmd.TryFinallyStatement;
+import dmd.TryCatchStatement;
+import dmd.Catch;
+import dmd.DeclarationStatement;
 import dmd.StaticDtorDeclaration;
 import dmd.GlobalExpressions;
 import dmd.PeelStatement;
@@ -80,7 +83,6 @@
 import dmd.Util;
 import dmd.BaseClass;
 import dmd.Module;
-import dmd.ILS;
 import dmd.InlineCostState;
 
 import dmd.expression.Util;
@@ -126,6 +128,10 @@
     Statement frequire;
     Statement fensure;
     Statement fbody;
+	
+    FuncDeclarations foverrides;	// functions this function overrides
+    FuncDeclaration fdrequire;		// function that does the in contract
+    FuncDeclaration fdensure;		// function that does the out contract
 
     Identifier outId;			// identifier for out statement
     VarDeclaration vresult;		// variable corresponding to outId
@@ -142,10 +148,10 @@
     DsymbolTable labtab;		// statement label symbol table
     Declaration overnext;		// next in overload list
     Loc endloc;				// location of closing curly bracket
-    int vtblIndex = -1;			// for member functions, index into vtbl[]
+    int vtblIndex;			// for member functions, index into vtbl[]
     int naked;				// !=0 if naked
     int inlineAsm;			// !=0 if has inline assembler
-    ILS inlineStatus = ILS.ILSuninitialized;
+    ILS inlineStatus;
     int inlineNest;			// !=0 if nested inline
     int cantInterpret;			// !=0 if cannot interpret function
     int semanticRun;			// 1 semantic() run
@@ -196,17 +202,52 @@
 		this.type = type;
 		this.loc = loc;
 		this.endloc = endloc;
-
+		fthrows = null;
+		frequire = null;
+		fdrequire = null;
+		fdensure = null;
+		outId = null;
+		vresult = null;
+		returnLabel = null;
+		fensure = null;
+		fbody = null;
+		localsymtab = null;
+		vthis = null;
+		v_arguments = null;
+version (IN_GCC) {
+		v_argptr = null;
+}
+		parameters = null;
+		labtab = null;
+		overnext = null;
+		vtblIndex = -1;
+		hasReturnExp = 0;
+		naked = 0;
+		inlineStatus = ILS.ILSuninitialized;
+		inlineNest = 0;
+		inlineAsm = 0;
+		cantInterpret = 0;
+		semanticRun = 0;
+version (DMDV1) {
+		nestedFrameRef = 0;
+}
+		fes = null;
+		introducing = 0;
+		tintro = null;
 		/* The type given for "infer the return type" is a TypeFunction with
 		 * null for the return type.
 		 */
 		inferRetType = (type && type.nextOf() is null);
-
+		hasReturnExp = 0;
+		nrvo_can = 1;
+		nrvo_var = null;
+		shidden = null;
+version (DMDV2) {
+		builtin = BUILTINunknown;
+		tookAddressOf = 0;
+}
+		foverrides = new FuncDeclarations();
 		closureVars = new Dsymbols();
-
-version (DMDV2) {
-		builtin = BUILTIN.BUILTINunknown;
-}
 	}
 	
     override Dsymbol syntaxCopy(Dsymbol s)
@@ -551,6 +592,10 @@
 			}
 			cd.vtbl.data[vi] = cast(void*)this;
 			vtblIndex = vi;
+			
+			/* Remember which functions this overrides
+			 */
+			foverrides.push(cast(void*)fdv);
 
 			/* This works by whenever this function is called,
 			 * it actually returns tintro, which gets dynamically
@@ -597,9 +642,13 @@
 			default:
 			{   FuncDeclaration fdv = cast(FuncDeclaration)b.base.vtbl.data[vi];
 				Type ti = null;
+				
+				/* Remember which functions this overrides
+				 */
+				foverrides.push(cast(void*)fdv);
 
 				if (fdv.tintro)
-				ti = fdv.tintro;
+					ti = fdv.tintro;
 				else if (!type.equals(fdv.type))
 				{
 				/* Only need to have a tintro if the vptr
@@ -727,6 +776,61 @@
 			}
 		}
 		}
+		
+		if (isVirtual())
+		{
+			/* Rewrite contracts as nested functions, then call them.
+			 * Doing it as nested functions means that overriding functions
+			 * can call them.
+			 */
+			if (frequire)
+			{   
+				/*   in { ... }
+				 * becomes:
+				 *   void __require() { ... }
+				 *   __require();
+				 */
+				Loc loc = frequire.loc;
+				TypeFunction tf = new TypeFunction(null, Type.tvoid, 0, LINKd);
+				FuncDeclaration fd = new FuncDeclaration(loc, loc, Id.require, STCundefined, tf);
+				fd.fbody = frequire;
+				Statement s1 = new DeclarationStatement(loc, fd);
+				Expression e = new CallExp(loc, new VarExp(loc, fd, 0), cast(Expressions)null);
+				Statement s2 = new ExpStatement(loc, e);
+				frequire = new CompoundStatement(loc, s1, s2);
+				fdrequire = fd;
+			}
+
+			if (fensure)
+			{   /*   out (result) { ... }
+				 * becomes:
+				 *   tret __ensure(ref tret result) { ... }
+				 *   __ensure(result);
+				 */
+				if (!outId && f.nextOf().toBasetype().ty != Tvoid)
+					outId = Id.result;	// provide a default
+
+				Loc loc = fensure.loc;
+				Arguments arguments = new Arguments();
+				Argument a = null;
+				if (outId)
+				{	
+					a = new Argument(STCref, f.nextOf(), outId, null);
+					arguments.push(cast(void*)a);
+				}
+				TypeFunction tf = new TypeFunction(arguments, Type.tvoid, 0, LINKd);
+				FuncDeclaration fd = new FuncDeclaration(loc, loc, Id.ensure, STCundefined, tf);
+				fd.fbody = fensure;
+				Statement s1 = new DeclarationStatement(loc, fd);
+				Expression eresult = null;
+				if (outId)
+					eresult = new IdentifierExp(loc, outId);
+				Expression e = new CallExp(loc, new VarExp(loc, fd, 0), eresult);
+				Statement s2 = new ExpStatement(loc, e);
+				fensure = new CompoundStatement(loc, s1, s2);
+				fdensure = fd;
+			}
+		}
 
 	Ldone:
 		/* Save scope for possible later use (if we need the
@@ -790,6 +894,9 @@
 			error("can only throw classes, not %s", t.toChars());
 		}
 		}
+		
+	    frequire = mergeFrequire(frequire);
+		fensure = mergeFensure(fensure);
 
 		if (fbody || frequire)
 		{
@@ -1328,27 +1435,29 @@
 			if (argptr)
 			{	// Initialize _argptr to point past non-variadic arg
 version (IN_GCC) {
-			// Handled in FuncDeclaration.toObjFile
-			v_argptr = argptr;
-			v_argptr.init = new VoidInitializer(loc);
+				// Handled in FuncDeclaration.toObjFile
+				v_argptr = argptr;
+				v_argptr.init = new VoidInitializer(loc);
 } else {
-			Expression e1;
-			Expression e;
-			Type t = argptr.type;
-			VarDeclaration p;
-			uint offset;
-
-			e1 = new VarExp(Loc(0), argptr);
-			if (parameters && parameters.dim)
-				p = cast(VarDeclaration)parameters.data[parameters.dim - 1];
-			else
-				p = v_arguments;		// last parameter is _arguments[]
-			offset = cast(uint)p.type.size();	///
-			offset = (offset + 3) & ~3;	// assume stack aligns on 4
-			e = new SymOffExp(Loc(0), p, offset);
-			e = new AssignExp(Loc(0), e1, e);
-			e.type = t;
-			a.push(cast(void*)new ExpStatement(Loc(0), e));
+				Type t = argptr.type;
+				VarDeclaration p;
+				uint offset;
+
+				Expression e1 = new VarExp(Loc(0), argptr);
+				if (parameters && parameters.dim)
+					p = cast(VarDeclaration)parameters.data[parameters.dim - 1];
+				else
+					p = v_arguments;		// last parameter is _arguments[]
+				if (p.storage_class & STClazy)
+					// If the last parameter is lazy, it's the size of a delegate
+					offset = PTRSIZE * 2;
+				else
+					offset = cast(size_t)p.type.size();
+				offset = (offset + 3) & ~3;	// assume stack aligns on 4
+				Expression e = new SymOffExp(Loc(0), p, offset);
+				e = new AssignExp(Loc(0), e1, e);
+				e.type = t;
+				a.push(cast(void*)new ExpStatement(Loc(0), e));
 }
 			}
 
@@ -2767,6 +2876,99 @@
 		return true;
 	}
 	
+    /****************************************************
+	 * Merge into this function the 'in' contracts of all it overrides.
+	 * 'in's are OR'd together, i.e. only one of them needs to pass.
+	 */
+
+	Statement mergeFrequire(Statement sf)
+	{
+		/* Implementing this is done by having the overriding function call
+		 * nested functions (the fdrequire functions) nested inside the overridden
+		 * function. This requires that the stack layout of the calling function's
+		 * parameters and 'this' pointer be in the same place (as the nested
+		 * function refers to them).
+		 * This is easy for the parameters, as they are all on the stack in the same
+		 * place by definition, since it's an overriding function. The problem is
+		 * getting the 'this' pointer in the same place, since it is a local variable.
+		 * We did some hacks in the code generator to make this happen:
+		 *	1. always generate exception handler frame, or at least leave space for it
+		 *     in the frame (Windows 32 SEH only)
+		 *	2. always generate an EBP style frame
+		 *  3. since 'this' is passed in a register that is subsequently copied into
+		 *     a stack local, allocate that local immediately following the exception
+		 *     handler block, so it is always at the same offset from EBP.
+		 */
+		for (int i = 0; i < foverrides.dim; i++)
+		{
+			FuncDeclaration fdv = cast(FuncDeclaration)foverrides.data[i];
+			sf = fdv.mergeFrequire(sf);
+			if (fdv.frequire)
+			{
+				//printf("fdv.frequire: %s\n", fdv.frequire.toChars());
+				/* Make the call:
+				 *   try { __require(); }
+				 *   catch { frequire; }
+				 */
+				Expression eresult = null;
+				Expression e = new CallExp(loc, new VarExp(loc, fdv.fdrequire, 0), eresult);
+				Statement s2 = new ExpStatement(loc, e);
+
+				if (sf)
+				{	
+					Catch c = new Catch(loc, null, null, sf);
+					Array catches = new Array();
+					catches.push(cast(void*)c);
+					sf = new TryCatchStatement(loc, s2, catches);
+				}
+				else
+					sf = s2;
+			}
+		}
+		return sf;
+	}
+
+    /****************************************************
+	 * Merge into this function the 'out' contracts of all it overrides.
+	 * 'out's are AND'd together, i.e. all of them need to pass.
+	 */
+
+	Statement mergeFensure(Statement sf)
+	{
+		/* Same comments as for mergeFrequire(), except that we take care
+		 * of generating a consistent reference to the 'result' local by
+		 * explicitly passing 'result' to the nested function as a reference
+		 * argument.
+		 * This won't work for the 'this' parameter as it would require changing
+		 * the semantic code for the nested function so that it looks on the parameter
+		 * list for the 'this' pointer, something that would need an unknown amount
+		 * of tweaking of various parts of the compiler that I'd rather leave alone.
+		 */
+		for (int i = 0; i < foverrides.dim; i++)
+		{
+			FuncDeclaration fdv = cast(FuncDeclaration)foverrides.data[i];
+			sf = fdv.mergeFensure(sf);
+			if (fdv.fensure)
+			{
+				//printf("fdv.fensure: %s\n", fdv.fensure.toChars());
+				// Make the call: __ensure(result)
+				Expression eresult = null;
+				if (outId)
+					eresult = new IdentifierExp(loc, outId);
+				Expression e = new CallExp(loc, new VarExp(loc, fdv.fdensure, 0), eresult);
+				Statement s2 = new ExpStatement(loc, e);
+
+				if (sf)
+				{
+					sf = new CompoundStatement(fensure.loc, s2, sf);
+				}
+				else
+					sf = s2;
+			}
+		}
+		return sf;
+	}
+	
     static FuncDeclaration genCfunc(Type treturn, string name)
 	{
 		return genCfunc(treturn, Lexer.idPool(name));
@@ -2991,6 +3193,16 @@
 
 		s = func.toSymbol();
 		f = s.Sfunc;
+		
+version (TARGET_WINDOS) {
+    /* This is done so that the 'this' pointer on the stack is the same
+     * distance away from the function parameters, so that an overriding
+     * function can call the nested fdensure or fdrequire of its overridden function
+     * and the stack offsets are the same.
+     */
+    if (isVirtual() && (fensure || frequire))
+		f.Fflags3 |= F3.Ffakeeh;
+}
 
 version (TARGET_OSX) {
 		s.Sclass = SC.SCcomdat;
--- a/dmd/Global.d	Sat Aug 28 16:19:48 2010 +0200
+++ b/dmd/Global.d	Sat Aug 28 19:42:41 2010 +0400
@@ -37,7 +37,7 @@
     string[] path;	// Array of char*'s which form the import lookup path
     string[] filePath;	// Array of char*'s which form the file import lookup path
     int structalign = 8;
-    string version_ = "v2.032";
+    string version_ = "v2.033";
 
     Param params;
     uint errors;	// number of errors reported so far
--- a/dmd/Id.d	Sat Aug 28 16:19:48 2010 +0200
+++ b/dmd/Id.d	Sat Aug 28 19:42:41 2010 +0400
@@ -17,6 +17,8 @@
     static Identifier _postblit;
     static Identifier classInvariant;
     static Identifier unitTest;
+    static Identifier require;
+    static Identifier ensure;
     static Identifier init_;
     static Identifier size;
     static Identifier __sizeof;
@@ -242,6 +244,8 @@
 		_postblit = Lexer.idPool("__postblit");
 		classInvariant = Lexer.idPool("__invariant");
 		unitTest = Lexer.idPool("__unitTest");
+		require = Lexer.idPool("__require");
+		ensure = Lexer.idPool("__ensure");
 		init_ = Lexer.idPool("init");
 		size = Lexer.idPool("size");
 		__sizeof = Lexer.idPool("sizeof");
--- a/dmd/IdentityExp.d	Sat Aug 28 16:19:48 2010 +0200
+++ b/dmd/IdentityExp.d	Sat Aug 28 19:42:41 2010 +0400
@@ -10,6 +10,7 @@
 import dmd.Type;
 import dmd.WANT;
 import dmd.TY;
+import dmd.GlobalExpressions;
 import dmd.expression.Identity;
 
 import dmd.backend.elem;
@@ -61,6 +62,8 @@
 		if ((this.e1.isConst() && this.e2.isConst()) || (this.e1.op == TOK.TOKnull && this.e2.op == TOK.TOKnull))
 		{
 			e = Identity(op, type, this.e1, this.e2);
+			if (e is EXP_CANT_INTERPRET)
+				e = this;
 		}
 
 		return e;
--- a/dmd/IndexExp.d	Sat Aug 28 16:19:48 2010 +0200
+++ b/dmd/IndexExp.d	Sat Aug 28 19:42:41 2010 +0400
@@ -43,6 +43,9 @@
 import dmd.backend.TYM;
 
 import core.stdc.string;
+import core.stdc.stdio;
+
+extern (C) extern void exit(int);
 
 class IndexExp : BinExp
 {
@@ -147,6 +150,9 @@
 				TupleExp te;
 				TypeTuple tup;
 
+				printf("e1.op: %d\n", e1.op);
+				exit(-1);
+				
 				if (e1.op == TOKtuple)
 				{	
 					te = cast(TupleExp)e1;
--- a/dmd/IntegerExp.d	Sat Aug 28 16:19:48 2010 +0200
+++ b/dmd/IntegerExp.d	Sat Aug 28 19:42:41 2010 +0400
@@ -22,6 +22,7 @@
 import dmd.backend.Util;
 
 import core.stdc.ctype : isprint;
+import std.stdio;
 
 class IntegerExp : Expression
 {
@@ -166,11 +167,16 @@
 					 * the type is painted on like in fromConstInitializer().
 					 */
 					if (!global.errors)
-					{   
+					{
+						printf("ty = %d, %d\n", type.ty, t.ty);
+						if (type.ty == Tenum) {
+							printf("test1\n");
+						}
 						///type.print();
 						assert(0);
 					}
 					break;
+
 			}
 			break;
 		}
--- a/dmd/Lexer.d	Sat Aug 28 16:19:48 2010 +0200
+++ b/dmd/Lexer.d	Sat Aug 28 19:42:41 2010 +0400
@@ -498,6 +498,7 @@
 		Token.tochars[TOK.TOKat]		= "@";
 
 		 // For debugging
+		Token.tochars[TOKerror]		= "error";
 		Token.tochars[TOK.TOKdotexp]		= "dotexp";
 		Token.tochars[TOK.TOKdotti]		= "dotti";
 		Token.tochars[TOK.TOKdotvar]		= "dotvar";
--- a/dmd/MinAssignExp.d	Sat Aug 28 16:19:48 2010 +0200
+++ b/dmd/MinAssignExp.d	Sat Aug 28 19:42:41 2010 +0400
@@ -54,6 +54,7 @@
 		{
 			e1 = e1.checkArithmetic();
 			e2 = e2.checkArithmetic();
+			checkComplexAddAssign();
 			type = e1.type;
 			typeCombine(sc);
 			if (type.isreal() || type.isimaginary())
--- a/dmd/ModAssignExp.d	Sat Aug 28 16:19:48 2010 +0200
+++ b/dmd/ModAssignExp.d	Sat Aug 28 19:42:41 2010 +0400
@@ -24,7 +24,9 @@
 	
     override Expression semantic(Scope sc)
 	{
-    		return commonSemanticAssign(sc);
+	    BinExp.semantic(sc);
+		checkComplexMulAssign();
+   		return commonSemanticAssign(sc);
 	}
 	
     override Expression interpret(InterState istate)
--- a/dmd/Module.d	Sat Aug 28 16:19:48 2010 +0200
+++ b/dmd/Module.d	Sat Aug 28 19:42:41 2010 +0400
@@ -1164,8 +1164,11 @@
 		Dsymbol s;
 		if (insearch)
 			s = null;
-		else if (searchCacheIdent is ident && searchCacheFlags == flags)
+	    else if (searchCacheIdent == ident && searchCacheFlags == flags && searchCacheSymbol)
+		{
 			s = searchCacheSymbol;
+			//printf("%s Module.search('%s', flags = %d) insearch = %d searchCacheSymbol = %s\n", toChars(), ident.toChars(), flags, insearch, searchCacheSymbol ? searchCacheSymbol.toChars() : "null");
+		}
 		else
 		{
 			insearch = 1;
--- a/dmd/MulAssignExp.d	Sat Aug 28 16:19:48 2010 +0200
+++ b/dmd/MulAssignExp.d	Sat Aug 28 19:42:41 2010 +0400
@@ -50,6 +50,7 @@
 		typeCombine(sc);
 		e1.checkArithmetic();
 		e2.checkArithmetic();
+	    checkComplexMulAssign();
 		if (e2.type.isfloating())
 		{	
 			Type t1;
--- a/dmd/RealExp.d	Sat Aug 28 16:19:48 2010 +0200
+++ b/dmd/RealExp.d	Sat Aug 28 19:42:41 2010 +0400
@@ -21,6 +21,8 @@
 
 import dmd.Complex;
 
+import std.stdio;
+
 class RealExp : Expression
 {
 	real value;
@@ -158,7 +160,7 @@
 				print();
 				///type.print();
 				///type.toBasetype().print();
-				writef("ty = %d, tym = %x\n", type.ty, ty);
+	    	    printf("ty = %d, tym = %lx\n", type.ty, ty);
 				assert(0);
 		}
 		return el_const(ty, &c);
--- a/dmd/ReturnStatement.d	Sat Aug 28 16:19:48 2010 +0200
+++ b/dmd/ReturnStatement.d	Sat Aug 28 19:42:41 2010 +0400
@@ -330,16 +330,22 @@
 			return gs;
 		}
 
-		if (exp && tbret.ty == TY.Tvoid && !fd.isMain())
+		if (exp && tbret.ty == Tvoid && !implicit0)
 		{
 			/* Replace:
 			 *	return exp;
 			 * with:
 			 *	exp; return;
+			 * or, if main():
+			 *	exp; return 0;
 			 */
 			Statement s = new ExpStatement(loc, exp);
+			//s = s.semantic(sc);
 			loc = Loc(0);
-			exp = null;
+			if (fd.isMain())
+				exp = new IntegerExp(0);
+			else
+				exp = null;
 			return new CompoundStatement(loc, s, this);
 		}
 
--- a/dmd/SymOffExp.d	Sat Aug 28 16:19:48 2010 +0200
+++ b/dmd/SymOffExp.d	Sat Aug 28 19:42:41 2010 +0400
@@ -28,7 +28,7 @@
 {
 	uint offset;
 
-	this(Loc loc, Declaration var, uint offset, int hasOverloads = 0)
+	this(Loc loc, Declaration var, uint offset, bool hasOverloads = false)
 	{
 		super(loc, TOK.TOKsymoff, SymOffExp.sizeof, var, hasOverloads);
 		
@@ -136,7 +136,7 @@
 	static if (false) {
 		printf("SymOffExp::castTo(this=%s, type=%s, t=%s)\n", toChars(), type.toChars(), t.toChars());
 	}
-		if (type == t && hasOverloads == 0)
+		if (type == t && !hasOverloads)
 			return this;
 
 		Expression e;
@@ -199,7 +199,7 @@
 		{	
 			e = copy();
 			e.type = t;
-			(cast(SymOffExp)e).hasOverloads = 0;
+			(cast(SymOffExp)e).hasOverloads = false;
 		}
 		return e;
 	}
--- a/dmd/SymbolExp.d	Sat Aug 28 16:19:48 2010 +0200
+++ b/dmd/SymbolExp.d	Sat Aug 28 19:42:41 2010 +0400
@@ -23,9 +23,9 @@
 {
 	Declaration var;
 
-	int hasOverloads;
+	bool hasOverloads;
 
-	this(Loc loc, TOK op, int size, Declaration var, int hasOverloads)
+	this(Loc loc, TOK op, int size, Declaration var, bool hasOverloads)
 	{
 		super(loc, op, size);
 		assert(var);
--- a/dmd/TOK.d	Sat Aug 28 16:19:48 2010 +0200
+++ b/dmd/TOK.d	Sat Aug 28 19:42:41 2010 +0400
@@ -74,6 +74,7 @@
 		TOKidentifier,	TOKstring,
 		TOKthis,	TOKsuper,
 		TOKhalt,	TOKtuple,
+		TOKerror,
 
 		// Basic types
 		TOKvoid,
@@ -202,6 +203,7 @@
 		TOKidentifier,	TOKstring,
 		TOKthis,	TOKsuper,
 		TOKhalt,	TOKtuple,
+		TOKerror,
 
 		// Basic types
 		TOKvoid,
--- a/dmd/Type.d	Sat Aug 28 16:19:48 2010 +0200
+++ b/dmd/Type.d	Sat Aug 28 19:42:41 2010 +0400
@@ -906,7 +906,7 @@
 	 *	a = b;
 	 * ?
 	 */
-    int isAssignable()
+    bool isAssignable()
 	{
 		return true;
 	}
--- a/dmd/TypeAArray.d	Sat Aug 28 16:19:48 2010 +0200
+++ b/dmd/TypeAArray.d	Sat Aug 28 19:42:41 2010 +0400
@@ -124,6 +124,7 @@
 			case Tfunction:
 			case Tvoid:
 			case Tnone:
+			case Ttuple:
 				error(loc, "can't have associative array key of %s", index.toBasetype().toChars());
 				break;
 			default:
--- a/dmd/TypeClass.d	Sat Aug 28 16:19:48 2010 +0200
+++ b/dmd/TypeClass.d	Sat Aug 28 19:42:41 2010 +0400
@@ -398,7 +398,7 @@
 				e = e.semantic(sc);
 				return e;
 			}
-			else if (d.needThis() && (hasThis(sc) || !d.isFuncDeclaration()))
+			else if (d.needThis() && (hasThis(sc) || !(sc.intypeof || d.isFuncDeclaration())))
 			{
 				if (sc.func)
 				{
--- a/dmd/TypeEnum.d	Sat Aug 28 16:19:48 2010 +0200
+++ b/dmd/TypeEnum.d	Sat Aug 28 19:42:41 2010 +0400
@@ -129,18 +129,42 @@
 	
     override bool isintegral()
 	{
-		return true;
+	    return sym.memtype.isintegral();
 	}
 	
     override bool isfloating()
 	{
-		return false;
+	    return sym.memtype.isfloating();
+	}
+	
+    bool isreal()
+	{
+		return sym.memtype.isreal();
+	}
+	
+    bool isimaginary()
+	{
+		return sym.memtype.isimaginary();
+	}
+	
+    bool iscomplex()
+	{
+		return sym.memtype.iscomplex();
+	}
+	
+    bool checkBoolean()
+	{
+		return sym.memtype.checkBoolean();
+	}
+	
+    bool isAssignable()
+	{
+		return sym.memtype.isAssignable();
 	}
 	
     override bool isscalar()
 	{
-		return true;
-		//return sym.memtype.isscalar();
+	    return sym.memtype.isscalar();
 	}
 	
     override bool isunsigned()
--- a/dmd/TypeFunction.d	Sat Aug 28 16:19:48 2010 +0200
+++ b/dmd/TypeFunction.d	Sat Aug 28 19:42:41 2010 +0400
@@ -10,6 +10,7 @@
 import dmd.Global;
 import dmd.STC;
 import dmd.MOD;
+import dmd.PROT;
 import dmd.Type;
 import dmd.Loc;
 import dmd.Scope;
@@ -158,13 +159,20 @@
 		}
 
 		if (tf.parameters)
-		{	size_t dim = Argument.dim(tf.parameters);
+		{	
+			/* Create a scope for evaluating the default arguments for the parameters
+			 */
+			Scope argsc = sc.push();
+			argsc.stc = STCundefined;			// don't inherit storage class
+			argsc.protection = PROT.PROTpublic;
+
+			size_t dim = Argument.dim(tf.parameters);
 
 			for (size_t i = 0; i < dim; i++)
 			{   Argument arg = Argument.getNth(tf.parameters, i);
 
 				tf.inuse++;
-				arg.type = arg.type.semantic(loc,sc);
+				arg.type = arg.type.semantic(loc, argsc);
 				if (tf.inuse == 1) tf.inuse--;
 
 				arg.type = arg.type.addStorageClass(arg.storageClass);
@@ -189,9 +197,9 @@
 
 				if (arg.defaultArg)
 				{
-					arg.defaultArg = arg.defaultArg.semantic(sc);
-					arg.defaultArg = resolveProperties(sc, arg.defaultArg);
-					arg.defaultArg = arg.defaultArg.implicitCastTo(sc, arg.type);
+					arg.defaultArg = arg.defaultArg.semantic(argsc);
+					arg.defaultArg = resolveProperties(argsc, arg.defaultArg);
+					arg.defaultArg = arg.defaultArg.implicitCastTo(argsc, arg.type);
 				}
 
 				/* If arg turns out to be a tuple, the number of parameters may
@@ -202,6 +210,7 @@
 					i--;
 				}
 			}
+			argsc.pop();
 		}
 		if (tf.next)
 		tf.deco = tf.merge().deco;
@@ -307,10 +316,10 @@
 			switch (linkage)
 			{
 				case LINKd:		p = null;	break;
-				case LINKc:		p = "C ";	break;
-				case LINKwindows:	p = "Windows ";	break;
-				case LINKpascal:	p = "Pascal ";	break;
-				case LINKcpp:	p = "C++ ";	break;
+				case LINKc:		p = " C";	break;
+				case LINKwindows:	p = " Windows";	break;
+				case LINKpascal:	p = " Pascal";	break;
+				case LINKcpp:	p = " C++";	break;
 				default:
 				assert(0);
 			}
--- a/dmd/TypeInfoArrayDeclaration.d	Sat Aug 28 16:19:48 2010 +0200
+++ b/dmd/TypeInfoArrayDeclaration.d	Sat Aug 28 19:42:41 2010 +0400
@@ -15,6 +15,7 @@
 	this(Type tinfo)
 	{
 		super(tinfo, 0);
+	    type = Type.typeinfoarray.type;
 	}
 
 	override void toDt(dt_t** pdt)
--- a/dmd/TypeInfoAssociativeArrayDeclaration.d	Sat Aug 28 16:19:48 2010 +0200
+++ b/dmd/TypeInfoAssociativeArrayDeclaration.d	Sat Aug 28 19:42:41 2010 +0400
@@ -13,6 +13,7 @@
 	this(Type tinfo)
 	{
 		super(tinfo, 0);
+	    type = Type.typeinfoassociativearray.type;
 	}
 
 	override void toDt(dt_t** pdt)
--- a/dmd/TypeInfoClassDeclaration.d	Sat Aug 28 16:19:48 2010 +0200
+++ b/dmd/TypeInfoClassDeclaration.d	Sat Aug 28 19:42:41 2010 +0400
@@ -16,6 +16,7 @@
 	this(Type tinfo)
 	{
 		super(tinfo, 0);
+	    type = Type.typeinfostruct.type;
 	}
 
 	override void toDt(dt_t** pdt)
--- a/dmd/TypeInfoConstDeclaration.d	Sat Aug 28 16:19:48 2010 +0200
+++ b/dmd/TypeInfoConstDeclaration.d	Sat Aug 28 19:42:41 2010 +0400
@@ -12,6 +12,7 @@
 	this(Type tinfo)
 	{
 		super(tinfo, 0);
+	    type = Type.typeinfoconst.type;
 	}
 
 	override void toDt(dt_t** pdt)
--- a/dmd/TypeInfoDelegateDeclaration.d	Sat Aug 28 16:19:48 2010 +0200
+++ b/dmd/TypeInfoDelegateDeclaration.d	Sat Aug 28 19:42:41 2010 +0400
@@ -14,6 +14,7 @@
 	this(Type tinfo)
 	{
 		super(tinfo, 0);
+	    type = Type.typeinfodelegate.type;
 	}
 
 	override void toDt(dt_t** pdt)
--- a/dmd/TypeInfoEnumDeclaration.d	Sat Aug 28 16:19:48 2010 +0200
+++ b/dmd/TypeInfoEnumDeclaration.d	Sat Aug 28 19:42:41 2010 +0400
@@ -17,6 +17,7 @@
 	this(Type tinfo)
 	{
 		super(tinfo, 0);
+	    type = Type.typeinfoenum.type;
 	}
 
 	override void toDt(dt_t** pdt)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/TypeInfoFunctionDeclaration.d	Sat Aug 28 19:42:41 2010 +0400
@@ -0,0 +1,20 @@
+module dmd.TypeInfoFunctionDeclaration;
+
+import dmd.Type;
+import dmd.TypeInfoDeclaration;
+import dmd.backend.dt_t;
+
+class TypeInfoFunctionDeclaration : TypeInfoDeclaration
+{
+	this(Type tinfo)
+	{
+		super(tinfo, 0);
+        type = Type.typeinfofunction.type;
+	}
+
+	void toDt(dt_t** pdt)
+	{
+		assert(false);
+	}
+}
+
--- a/dmd/TypeInfoInterfaceDeclaration.d	Sat Aug 28 16:19:48 2010 +0200
+++ b/dmd/TypeInfoInterfaceDeclaration.d	Sat Aug 28 19:42:41 2010 +0400
@@ -16,6 +16,7 @@
 	this(Type tinfo)
 	{
 		super(tinfo, 0);
+	    type = Type.typeinfointerface.type;
 	}
 
 	override void toDt(dt_t** pdt)
--- a/dmd/TypeInfoInvariantDeclaration.d	Sat Aug 28 16:19:48 2010 +0200
+++ b/dmd/TypeInfoInvariantDeclaration.d	Sat Aug 28 19:42:41 2010 +0400
@@ -11,6 +11,7 @@
 	this(Type tinfo)
 	{
 		super(tinfo, 0);
+	    type = Type.typeinfoinvariant.type;
 	}
 
 	override void toDt(dt_t** pdt)
--- a/dmd/TypeInfoPointerDeclaration.d	Sat Aug 28 16:19:48 2010 +0200
+++ b/dmd/TypeInfoPointerDeclaration.d	Sat Aug 28 19:42:41 2010 +0400
@@ -13,6 +13,7 @@
 	this(Type tinfo)
 	{
 		super(tinfo, 0);
+	    type = Type.typeinfopointer.type;
 	}
 
 	override void toDt(dt_t** pdt)
--- a/dmd/TypeInfoSharedDeclaration.d	Sat Aug 28 16:19:48 2010 +0200
+++ b/dmd/TypeInfoSharedDeclaration.d	Sat Aug 28 19:42:41 2010 +0400
@@ -8,8 +8,8 @@
 {
 	this(Type tinfo)
 	{
-		assert(false);
 		super(tinfo, 0);
+	    type = Type.typeinfoshared.type;
 	}
 
 	override void toDt(dt_t** pdt)
--- a/dmd/TypeInfoStaticArrayDeclaration.d	Sat Aug 28 16:19:48 2010 +0200
+++ b/dmd/TypeInfoStaticArrayDeclaration.d	Sat Aug 28 19:42:41 2010 +0400
@@ -14,6 +14,7 @@
     this(Type tinfo)
 	{
 		super(tinfo, 0);
+	    type = Type.typeinfostaticarray.type;
 	}
 
     override void toDt(dt_t** pdt)
--- a/dmd/TypeInfoStructDeclaration.d	Sat Aug 28 16:19:48 2010 +0200
+++ b/dmd/TypeInfoStructDeclaration.d	Sat Aug 28 19:42:41 2010 +0400
@@ -28,6 +28,7 @@
 	this(Type tinfo)
 	{
 		super(tinfo, 0);
+	    type = Type.typeinfostruct.type;
 	}
 
 	override void toDt(dt_t** pdt)
--- a/dmd/TypeInfoTupleDeclaration.d	Sat Aug 28 16:19:48 2010 +0200
+++ b/dmd/TypeInfoTupleDeclaration.d	Sat Aug 28 19:42:41 2010 +0400
@@ -18,6 +18,7 @@
     this(Type tinfo)
 	{
 		super(tinfo, 0);
+	    type = Type.typeinfotypelist.type;
 	}
 
     override void toDt(dt_t **pdt)
--- a/dmd/TypeInfoTypedefDeclaration.d	Sat Aug 28 16:19:48 2010 +0200
+++ b/dmd/TypeInfoTypedefDeclaration.d	Sat Aug 28 19:42:41 2010 +0400
@@ -17,6 +17,7 @@
 	this(Type tinfo)
 	{
 		super(tinfo, 0);
+	    type = Type.typeinfotypedef.type;
 	}
 
 	override void toDt(dt_t** pdt)
--- a/dmd/TypeQualified.d	Sat Aug 28 16:19:48 2010 +0200
+++ b/dmd/TypeQualified.d	Sat Aug 28 19:42:41 2010 +0400
@@ -2,6 +2,7 @@
 
 import dmd.Type;
 import dmd.Import;
+import dmd.DsymbolExp;
 import dmd.TypeExp;
 import dmd.DotIdExp;
 import dmd.VarDeclaration;
@@ -139,6 +140,19 @@
 						goto Lerror;
 						goto L3;
 					}
+					else if (v && id == Id.stringof_)
+					{
+						e = new DsymbolExp(loc, s, 0);
+						do
+						{
+							id = cast(Identifier)idents.data[i];
+							e = new DotIdExp(loc, e, id);
+						} while (++i < idents.dim);
+						e = e.semantic(sc);
+						*pe = e;
+						return;
+					}
+					
 					t = s.getType();
 					if (!t && s.isDeclaration())
 						t = s.isDeclaration().type;
@@ -242,20 +256,29 @@
 			{
 				if (t.reliesOnTident())
 				{
-					Scope scx;
-
-					for (scx = sc; 1; scx = scx.enclosing)
+					if (s.scope_)
+						t = t.semantic(loc, s.scope_);
+					else
 					{
-						if (!scx)
-						{   
-							error(loc, "forward reference to '%s'", t.toChars());
-							return;
+						/* Attempt to find correct scope in which to evaluate t.
+						 * Not sure if this is right or not, or if we should just
+						 * give forward reference error if s.scope is not set.
+						 */
+						for (Scope scx = sc; 1; scx = scx.enclosing)
+						{
+							if (!scx)
+							{   
+								error(loc, "forward reference to '%s'", t.toChars());
+								return;
+							}
+							if (scx.scopesym == scopesym)
+							{
+								t = t.semantic(loc, scx);
+								break;
+							}
 						}
-						if (scx.scopesym == scopesym)
-							break;
 					}
-					t = t.semantic(loc, scx);
-					//((TypeIdentifier *)t).resolve(loc, scx, pe, &t, ps);
+
 				}
 			}
 			if (t.ty == TY.Ttuple)
--- a/dmd/TypeStruct.d	Sat Aug 28 16:19:48 2010 +0200
+++ b/dmd/TypeStruct.d	Sat Aug 28 19:42:41 2010 +0400
@@ -428,7 +428,7 @@
 		return sym.zeroInit;
 	}
 	
-    override int isAssignable()
+    override bool isAssignable()
 	{
 		/* If any of the fields are const or invariant,
 		 * then one cannot assign this struct.
--- a/dmd/TypeTypedef.d	Sat Aug 28 16:19:48 2010 +0200
+++ b/dmd/TypeTypedef.d	Sat Aug 28 19:42:41 2010 +0400
@@ -163,7 +163,7 @@
 		return sym.basetype.checkBoolean();
 	}
 	
-    override int isAssignable()
+    override bool isAssignable()
 	{
 		return sym.basetype.isAssignable();
 	}
--- a/dmd/VarDeclaration.d	Sat Aug 28 16:19:48 2010 +0200
+++ b/dmd/VarDeclaration.d	Sat Aug 28 19:42:41 2010 +0400
@@ -51,6 +51,7 @@
 import dmd.OutBuffer;
 import dmd.HdrGenState;
 import dmd.PROT;
+import dmd.expression.Util;
 
 import dmd.backend.Symbol;
 import dmd.backend.TYM;
@@ -559,10 +560,20 @@
 				}
 }
 				if (!ei.exp.implicitConvTo(type))
-				{	Type ti = ei.exp.type.toBasetype();
-				// Don't cast away invariant or mutability in initializer
-				if (!(ti.ty == TY.Tstruct && t.toDsymbol(sc) == ti.toDsymbol(sc)))
-					ei.exp = new CastExp(loc, ei.exp, type);
+				{
+					/* Look for opCall
+					 * See bugzilla 2702 for more discussion
+					 */
+					Type ti = ei.exp.type.toBasetype();
+					// Don't cast away invariant or mutability in initializer
+					if (search_function(sd, Id.call) &&
+						/* Initializing with the same type is done differently
+						 */
+						!(ti.ty == Tstruct && t.toDsymbol(sc) == ti.toDsymbol(sc)))
+					{   // Rewrite as e1.call(arguments)
+						Expression eCall = new DotIdExp(loc, e1, Id.call);
+						ei.exp = new CallExp(loc, eCall, ei.exp);
+					}
 				}
 			}
 			ei.exp = new AssignExp(loc, e1, ei.exp);
--- a/dmd/VarExp.d	Sat Aug 28 16:19:48 2010 +0200
+++ b/dmd/VarExp.d	Sat Aug 28 19:42:41 2010 +0400
@@ -26,7 +26,7 @@
 
 class VarExp : SymbolExp
 {
-	this(Loc loc, Declaration var, int hasOverloads = 0)
+	this(Loc loc, Declaration var, bool hasOverloads = false)
 	{
 		super(loc, TOK.TOKvar, VarExp.sizeof, var, hasOverloads);
 		
--- a/dmd/backend/F.d	Sat Aug 28 16:19:48 2010 +0200
+++ b/dmd/backend/F.d	Sat Aug 28 19:42:41 2010 +0400
@@ -57,4 +57,5 @@
 	Fnested	= 0x1000,	// D nested function with 'this'
 	Fmember	= 0x2000,	// D member function with 'this'
 	Fnotailrecursion = 0x4000,	// no tail recursion optimizations
+	Ffakeeh = 0x8000,	// allocate space for NT EH context sym anyway
 }
\ No newline at end of file
--- a/dmd/codegen/Util.d	Sat Aug 28 16:19:48 2010 +0200
+++ b/dmd/codegen/Util.d	Sat Aug 28 19:42:41 2010 +0400
@@ -1,6 +1,7 @@
 module dmd.codegen.Util;
 
 import dmd.Loc;
+import dmd.Id;
 import dmd.IRState;
 import dmd.Type;
 import dmd.Array;
@@ -351,7 +352,12 @@
     Dsymbol fdparent = fd.toParent2();
 
     //printf("getEthis(thisfd = '%s', fd = '%s', fdparent = '%s')\n", thisfd.toChars(), fd.toChars(), fdparent.toChars());
-    if (fdparent == thisfd)
+    if (fdparent == thisfd ||
+		/* These two are compiler generated functions for the in and out contracts,
+		 * and are called from an overriding function, not just the one they're
+		 * nested inside, so this hack is so they'll pass
+		 */
+		fd.ident == Id.require || fd.ident == Id.ensure)
     {	
 		/* Going down one nesting level, i.e. we're calling
 		 * a nested function from its enclosing function.
@@ -405,6 +411,8 @@
 				ethis.Eoper = OPER.OPframeptr;
 			}
 		}
+		
+		//if (fdparent != thisfd) ethis = el_bin(OPadd, TYnptr, ethis, el_long(TYint, 0x18));
     }
     else
     {
--- a/dmd/expression/Equal.d	Sat Aug 28 16:19:48 2010 +0200
+++ b/dmd/expression/Equal.d	Sat Aug 28 19:42:41 2010 +0400
@@ -3,6 +3,7 @@
 import dmd.Expression;
 import dmd.Type;
 import dmd.TOK;
+import dmd.TY;
 import dmd.Loc;
 import dmd.StringExp;
 import dmd.GlobalExpressions;
@@ -194,7 +195,7 @@
     {
 		cmp = (e1.toComplex() == e2.toComplex());
     }
-    else if (e1.type.isintegral())
+    else if (e1.type.isintegral() || e1.type.ty == Tpointer)
     {
 		cmp = (e1.toInteger() == e2.toInteger());
     }
--- a/dmd/expression/Util.d	Sat Aug 28 16:19:48 2010 +0200
+++ b/dmd/expression/Util.d	Sat Aug 28 19:42:41 2010 +0400
@@ -745,21 +745,28 @@
 				}
 			}
 version (DMDV2) {
-			if (tb.ty == TY.Tstruct)
+			if (tb.ty == Tstruct)
 			{
 				arg = callCpCtor(loc, sc, arg);
 			}
+}
 
-			// Give error for overloaded function addresses
-			if (arg.op == TOK.TOKsymoff)
-			{	
-				SymOffExp se = cast(SymOffExp)arg;
-				if (se.hasOverloads && !se.var.isFuncDeclaration().isUnique())
-					arg.error("function %s is overloaded", arg.toChars());
-			}
+	    // Give error for overloaded function addresses
+	    if (arg.op == TOKsymoff)
+	    {	
+			SymOffExp se = cast(SymOffExp)arg;
+version (DMDV2) {
+			bool aux = (se.hasOverloads != 0);
+} else {
+			bool aux = true;
 }
-			arg.rvalue();
-		}
+		if (aux && !se.var.isFuncDeclaration().isUnique())
+		    arg.error("function %s is overloaded", arg.toChars());
+	    }
+
+	    arg.rvalue();
+	}
+
 		arg = arg.optimize(WANT.WANTvalue);
 		arguments.data[i] = cast(void*) arg;
 		if (done)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rt/memory.d	Sat Aug 28 19:42:41 2010 +0400
@@ -0,0 +1,3 @@
+module rt.memory;
+
+extern(D) void initStaticDataGC();
\ No newline at end of file