diff dmd/FuncDeclaration.d @ 179:cd48cb899aee

Updated to dmd2.040
author korDen
date Sun, 17 Oct 2010 20:56:07 +0400
parents e3afd1303184
children b0d41ff5e0df
line wrap: on
line diff
--- a/dmd/FuncDeclaration.d	Sun Oct 17 07:42:00 2010 +0400
+++ b/dmd/FuncDeclaration.d	Sun Oct 17 20:56:07 2010 +0400
@@ -6,6 +6,7 @@
 import dmd.AddrExp;
 import dmd.TryFinallyStatement;
 import dmd.TryCatchStatement;
+import dmd.SharedStaticDtorDeclaration;
 import dmd.Catch;
 import dmd.DeclarationStatement;
 import dmd.StaticDtorDeclaration;
@@ -20,6 +21,7 @@
 import dmd.Id;
 import dmd.StorageClassDeclaration;
 import dmd.StringExp;
+import dmd.PASS;
 import dmd.DsymbolExp;
 import dmd.HaltExp;
 import dmd.CommaExp;
@@ -27,6 +29,7 @@
 import dmd.IntegerExp;
 import dmd.ExpStatement;
 import dmd.CSX;
+import dmd.PROT;
 import dmd.CompoundStatement;
 import dmd.LabelStatement;
 import dmd.ThisExp;
@@ -150,19 +153,15 @@
     Dsymbols parameters;		// Array of VarDeclaration's for parameters
     DsymbolTable labtab;		// statement label symbol table
     Declaration overnext;		// next in overload list
-    Loc endloc;				// location of closing curly bracket
-    int vtblIndex;			// for member functions, index into vtbl[]
-    int naked;				// !=0 if naked
-    int inlineAsm;			// !=0 if has inline assembler
+    Loc endloc;					// location of closing curly bracket
+    int vtblIndex;				// for member functions, index into vtbl[]
+    int naked;					// !=0 if naked
+    int inlineAsm;				// !=0 if has inline assembler
     ILS inlineStatus;
-    int inlineNest;			// !=0 if nested inline
+    int inlineNest;				// !=0 if nested inline
     int cantInterpret;			// !=0 if cannot interpret function
-    int semanticRun;			// 1 semantic() run
-					// 2 semantic2() run
-					// 3 semantic3() started
-					// 4 semantic3() done
-					// 5 toObjFile() run
-					// this function's frame ptr
+    PASS semanticRun;
+								// this function's frame ptr
     ForeachStatement fes;		// if foreach body, this is the foreach
     int introducing;			// !=0 if 'introducing' function
     Type tintro;			// if !=null, then this is the type
@@ -231,7 +230,7 @@
 		inlineNest = 0;
 		inlineAsm = 0;
 		cantInterpret = 0;
-		semanticRun = 0;
+		semanticRun = PASSinit;
 version (DMDV1) {
 		nestedFrameRef = 0;
 }
@@ -291,7 +290,7 @@
 		printf("type: %p, %s\n", type, type.toChars());
 }
 
-		if (semanticRun && isFuncLiteralDeclaration())
+		if (semanticRun != PASSinit && isFuncLiteralDeclaration())
 		{
 			/* Member functions that have return types that are
 			 * forward references can have semantic() run more than
@@ -300,18 +299,35 @@
 			 */
 			return;
 		}
-		assert(semanticRun <= 1);
-		semanticRun = 1;
+		
+		parent = sc.parent;
+		Dsymbol parent = toParent();
+		
+		if (semanticRun == PASSsemanticdone)
+		{
+			if (!parent.isClassDeclaration())
+				return;
+			// need to re-run semantic() in order to set the class's vtbl[]
+		}
+		else
+		{
+			assert(semanticRun <= PASSsemantic);
+			semanticRun = PASSsemantic;
+		}
+
+		uint dprogress_save = global.dprogress;
+
+		foverrides.setDim(0);	// reset in case semantic() is being retried for this function
 
 		storage_class |= sc.stc & ~STC.STCref;
-		//printf("function storage_class = x%x\n", storage_class);
+	    //printf("function storage_class = x%llx, sc->stc = x%llx\n", storage_class, sc->stc);
 
 		if (!originalType)
 			originalType = type;
 		if (!type.deco)
 		{
     	    sc = sc.push();
-	        sc.stc |= storage_class & STC.STCref;	// forward refness to function type
+        	sc.stc |= storage_class & STCref;	// forward to function type
 	        type = type.semantic(loc, sc);
 	        sc = sc.pop();
 
@@ -387,13 +403,7 @@
 		size_t nparams = Parameter.dim(f.parameters);
 
 		linkage = sc.linkage;
-	//    if (!parent)
-		{
-		//parent = sc.scopesym;
-		parent = sc.parent;
-		}
 		protection = sc.protection;
-		Dsymbol parent = toParent();
 
 		if (storage_class & STC.STCscope)
 		error("functions cannot be scope");
@@ -434,7 +444,7 @@
 		{
 		if (isCtorDeclaration())
 		{
-			return;
+			goto Ldone;
 		}
 static if (false) {
 		// Verify no constructors, destructors, etc.
@@ -475,7 +485,7 @@
 			isInvariantDeclaration() ||
 			isUnitTestDeclaration() || isNewDeclaration() || isDelete())
 			error("special function not allowed in interface %s", id.toChars());
-		if (fbody)
+		if (fbody && isVirtual())
 			error("function body is not abstract in interface %s", id.toChars());
 		}
 
@@ -545,8 +555,10 @@
 			goto Ldone;
 		}
 
-		// Find index of existing function in vtbl[] to override
-		vi = findVtblIndex(cd.vtbl, cd.baseClass ? cd.baseClass.vtbl.dim : 0);
+		/* Find index of existing function in base class's vtbl[] to override
+		 * (the index will be the same as in cd's current vtbl[])
+		 */
+		vi = cd.baseClass ? findVtblIndex(cd.baseClass.vtbl, cd.baseClass.vtbl.dim) : -1;
 		switch (vi)
 		{
 			case -1:
@@ -586,12 +598,14 @@
 			break;
 
 			case -2:	// can't determine because of fwd refs
-			cd.sizeok = 2;	// can't finish due to forward reference
-			return;
+				cd.sizeok = 2;	// can't finish due to forward reference
+				global.dprogress = dprogress_save;
+				return;
 
 			default:
 			{
-				FuncDeclaration fdv = cast(FuncDeclaration)cd.vtbl.data[vi];
+			FuncDeclaration fdv = cast(FuncDeclaration)cd.baseClass.vtbl.data[vi];
+
 			// This function is covariant with fdv
 			if (fdv.isFinal())
 				error("cannot override final function %s", fdv.toPrettyChars());
@@ -665,6 +679,7 @@
 
 			case -2:
 				cd.sizeok = 2;	// can't finish due to forward reference
+			    global.dprogress = dprogress_save;
 				return;
 
 			default:
@@ -679,23 +694,25 @@
 					ti = fdv.tintro;
 				else if (!type.equals(fdv.type))
 				{
-				/* Only need to have a tintro if the vptr
-				 * offsets differ
-				 */
-				int offset;
-				if (fdv.type.nextOf().isBaseOf(type.nextOf(), &offset))
-				{
-					ti = fdv.type;
-static if (false) {
-					if (offset)
-					ti = fdv.type;
-					else if (type.nextOf().ty == Tclass)
+					/* Only need to have a tintro if the vptr
+					 * offsets differ
+					 */
+					uint errors = global.errors;
+					global.gag++;            // suppress printing of error messages
+					int offset;
+					int baseOf = fdv.type.nextOf().isBaseOf(type.nextOf(), &offset);
+					global.gag--;            // suppress printing of error messages
+					if (errors != global.errors)
 					{
-						ClassDeclaration cdn = (cast(TypeClass)type.nextOf()).sym;
-						if (cdn && cdn.sizeok != 1)
-							ti = fdv.type;
-						}
-}
+						// any error in isBaseOf() is a forward reference error, so we bail out
+						global.errors = errors;
+						cd.sizeok = 2;    // can't finish due to forward reference
+						global.dprogress = dprogress_save;
+						return;
+					}
+					if (baseOf)
+					{
+						ti = fdv.type;
 					}
 				}
 				if (ti)
@@ -717,6 +734,27 @@
 		}
 
 		L2: ;
+			/* Go through all the interface bases.
+			 * Disallow overriding any final functions in the interface(s).
+			 */
+			for (int i = 0; i < cd.interfaces_dim; i++)
+			{
+				BaseClass b = cd.interfaces[i];
+				if (b.base)
+				{
+					Dsymbol s = search_function(b.base, ident);
+					if (s)
+					{
+						FuncDeclaration f_ = s.isFuncDeclaration();
+						if (f_)
+						{
+							f_ = f_.overloadExactMatch(type);
+							if (f_ && f_.isFinal() && f_.prot() != PROT.PROTprivate)
+								error("cannot override final function %s.%s", b.base.toChars(), f_.toPrettyChars());
+						}
+					}
+				}
+			}
 		}
 		else if (isOverride() && !parent.isTemplateInstance())
 		error("override only applies to class member functions");
@@ -807,7 +845,7 @@
 		}
 		}
 
-		if (isVirtual())
+	    if (isVirtual() && semanticRun != PASSsemanticdone)
 		{
 			/* Rewrite contracts as nested functions, then call them.
 			 * Doing it as nested functions means that overriding functions
@@ -863,6 +901,9 @@
 		}
 
 	Ldone:
+	    global.dprogress++;
+		semanticRun = PASSsemanticdone;
+
 		/* Save scope for possible later use (if we need the
 		 * function internals)
 		 */
@@ -904,9 +945,9 @@
 		//printf("\tlinkage = %d\n", sc.linkage);
 
 		//printf(" sc.incontract = %d\n", sc.incontract);
-		if (semanticRun >= 3)
-		return;
-		semanticRun = 3;
+	    if (semanticRun >= PASSsemantic3)
+			return;
+		semanticRun = PASSsemantic3;
 
 		if (!type || type.ty != TY.Tfunction)
 		return;
@@ -1671,7 +1712,8 @@
 		sc2.callSuper = 0;
 		sc2.pop();
 		}
-		semanticRun = 4;
+		
+	    semanticRun = PASSsemantic3done;
 	}
 
     // called from semantic3
@@ -1763,17 +1805,22 @@
 	/*************************************************
 	 * Find index of function in vtbl[0..dim] that
 	 * this function overrides.
+	 * Prefer an exact match to a covariant one.
 	 * Returns:
 	 *	-1	didn't find one
 	 *	-2	can't determine because of forward references
 	 */
     int findVtblIndex(Array vtbl, int dim)
 	{
+	    FuncDeclaration mismatch = null;
+		int bestvi = -1;
 		for (int vi = 0; vi < dim; vi++)
 		{
 			FuncDeclaration fdv = (cast(Dsymbol)vtbl.data[vi]).isFuncDeclaration();
 			if (fdv && fdv.ident is ident)
 			{
+			    if (type.equals(fdv.type))	// if exact match
+					return vi;				// no need to look further
 				int cov = type.covariant(fdv.type);
 				//printf("\tbaseclass cov = %d\n", cov);
 				switch (cov)
@@ -1782,15 +1829,12 @@
 						break;
 
 					case 1:
-						return vi;
+			            bestvi = vi;	// covariant, but not identical
+						break;			// keep looking for an exact match
 
 					case 2:
-						//type.print();
-						//fdv.type.print();
-						//printf("%s %s\n", type.deco, fdv.type.deco);
-						error("of type %s overrides but is not covariant with %s of type %s",
-						type.toChars(), fdv.toPrettyChars(), fdv.type.toChars());
-						break;
+						mismatch = fdv;	// overrides, but is not covariant
+						break;			// keep looking for an exact match
 
 					case 3:
 						return -2;	// forward references
@@ -1801,7 +1845,15 @@
 				}
 			}
 		}
-		return -1;
+	    if (bestvi == -1 && mismatch)
+		{
+			//type.print();
+			//mismatch.type.print();
+			//writef("%s %s\n", type.deco, mismatch.type.deco);
+			error("of type %s overrides but is not covariant with %s of type %s",
+				type.toChars(), mismatch.toPrettyChars(), mismatch.type.toChars());
+		}
+		return bestvi;
 	}
 
 	/****************************************************
@@ -2328,7 +2380,11 @@
 		printf("result is %d\n",
 		isMember() && !(isStatic() || protection == PROT.PROTprivate || protection == PROT.PROTpackage) && toParent().isClassDeclaration());
 }
-		return isMember() && !(isStatic() || protection == PROT.PROTprivate || protection == PROT.PROTpackage) && toParent().isClassDeclaration();
+	    Dsymbol p = toParent();
+	    return isMember() &&
+			!(isStatic() || protection == PROT.PROTprivate || protection == PROT.PROTpackage) &&
+			p.isClassDeclaration() &&
+			!(p.isInterfaceDeclaration() && isFinal());
 	}
 
     override bool isFinal()
@@ -2404,7 +2460,7 @@
 		}
 }
 
-		if (cantInterpret || semanticRun == 3)
+	    if (cantInterpret || semanticRun == PASSsemantic3)
 			return null;
 
 		if (!fbody)
@@ -2413,13 +2469,13 @@
 			return null;
 		}
 
-		if (semanticRun < 3 && scope_)
+		if (semanticRun < PASSsemantic3 && scope_)
 		{
 			semantic3(scope_);
 			if (global.errors)	// if errors compiling this function
 				return null;
 		}
-		if (semanticRun < 4)
+		if (semanticRun < PASSsemantic3done)
 			return null;
 
 		Type tb = type.toBasetype();
@@ -2433,21 +2489,6 @@
 			return null;
 		}
 
-		// Ensure there are no lazy parameters
-		if (tf.parameters)
-		{
-			size_t dim = Parameter.dim(tf.parameters);
-			for (size_t i = 0; i < dim; i++)
-			{
-				auto arg = Parameter.getNth(tf.parameters, i);
-				if (arg.storageClass & STClazy)
-				{
-					cantInterpret = 1;
-					return null;
-				}
-			}
-		}
-
 		scope InterState istatex = new InterState();
 		istatex.caller = istate;
 		istatex.fd = this;
@@ -2479,7 +2520,7 @@
 				Expression earg = arguments[i];
 				auto arg = Parameter.getNth(tf.parameters, i);
 
-				if (arg.storageClass & (STCout | STCref))
+			    if (arg.storageClass & (STCout | STCref | STClazy))
 				{
 				}
 				else
@@ -2686,7 +2727,7 @@
 		if (needThis() && !hasthis)
 			return 0;
 
-		if (inlineNest || (semanticRun < 3 && !hdrscan))
+	    if (inlineNest || (semanticRun < PASSsemantic3 && !hdrscan))
 		{
 	version (CANINLINE_LOG) {
 			printf("\t1: no, inlineNest = %d, semanticRun = %d\n", inlineNest, semanticRun);
@@ -3292,10 +3333,9 @@
 			return;
 		}
 
-		if (semanticRun >= 5)	// if toObjFile() already run
+		if (semanticRun >= PASSobj)	// if toObjFile() already run
 			return;
-			
-		semanticRun = 5;
+		semanticRun = PASSobj;
 
 		if (!func.fbody)
 		{
@@ -3349,18 +3389,25 @@
 
 			// Pull in RTL startup code
 			if (func.isMain())
-			{   objextdef("_main");
+			{   
+				objextdef("_main");
 version (POSIX) { ///TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_SOLARIS
 				obj_ehsections();	// initialize exception handling sections
-} else {
+}
+version (TARGET_WINDOS) {
 				objextdef("__acrtused_con");
 }
 				obj_includelib(libname);
 				s.Sclass = SC.SCglobal;
 			}
 			else if (strcmp(s.Sident.ptr, "main".ptr) == 0 && linkage == LINK.LINKc)
-				s.Sclass = SC.SCglobal;
-
+			{
+version (TARGET_WINDOS) {
+				objextdef("__acrtused_con");	// bring in C startup code
+				obj_includelib("snn.lib");		// bring in C runtime library
+}
+				s.Sclass = SCglobal;
+			}
 			else if (func.isWinMain())
 			{
 				objextdef("__acrtused");
@@ -3640,32 +3687,54 @@
 		}
 
 		// If static constructor
-		if (isStaticConstructor())
+		if (isSharedStaticCtorDeclaration())	// must come first because it derives from StaticCtorDeclaration
 		{
-			elem* e = el_una(OPER.OPucall, TYM.TYvoid, el_var(s));
+			elem* e = el_una(OPucall, TYvoid, el_var(s));
+			global.esharedctor = el_combine(global.esharedctor, e);
+		}
+		else if (isStaticCtorDeclaration())
+		{
+			elem* e = el_una(OPucall, TYvoid, el_var(s));
 			global.ector = el_combine(global.ector, e);
 		}
 
 		// If static destructor
-		if (isStaticDestructor())
+		if (auto f_ = isSharedStaticDtorDeclaration())	// must come first because it derives from StaticDtorDeclaration
 		{
 			elem* e;
 
 version (STATICCTOR) {
-			e = el_bin(OPER.OPcall, TYM.TYvoid, el_var(rtlsym[RTLSYM.RTLSYM_FATEXIT]), el_ptr(s));
-			ector = el_combine(ector, e);
+			e = el_bin(OPcall, TYvoid, el_var(rtlsym[RTLSYM_FATEXIT]), el_ptr(s));
+			esharedctor = el_combine(esharedctor, e);
+			shareddtorcount++;
+} else {
+			if (f_.vgate)
+			{   
+				/* Increment destructor's vgate at construction time
+				 */
+				global.esharedctorgates.push(cast(void*)f_);
+			}
+
+			e = el_una(OPucall, TYvoid, el_var(s));
+			global.eshareddtor = el_combine(e, global.eshareddtor);
+}
+		}
+		else if (auto f_ = isStaticDtorDeclaration())
+		{
+			elem* e;
+
+version (STATICCTOR) {
+			e = el_bin(OPcall, TYvoid, el_var(rtlsym[RTLSYM_FATEXIT]), el_ptr(s));
+			global.ector = el_combine(ector, e);
 			dtorcount++;
 } else {
-			StaticDtorDeclaration f2 = isStaticDtorDeclaration();
-			assert(f2);
-			if (f2.vgate)
-			{
-				/* Increment destructor's vgate at construction time
+			if (f_.vgate)
+			{   /* Increment destructor's vgate at construction time
 				 */
-				global.ectorgates.push(cast(void*)f2);
+				global.ectorgates.push(cast(void*)f_);
 			}
 
-			e = el_una(OPER.OPucall, TYM.TYvoid, el_var(s));
+			e = el_una(OPucall, TYvoid, el_var(s));
 			global.edtor = el_combine(e, global.edtor);
 }
 		}