diff dmd/func.c @ 1630:44b145be2ef5

Merge dmd 1.056.
author Robert Clipsham <robert@octarineparrot.com>
date Sat, 06 Feb 2010 15:53:52 +0000
parents 6820110de311
children 9bf06e02070b
line wrap: on
line diff
--- a/dmd/func.c	Wed Jan 06 19:53:35 2010 +0100
+++ b/dmd/func.c	Sat Feb 06 15:53:52 2010 +0000
@@ -1,5 +1,5 @@
 // Compiler implementation of the D programming language
-// Copyright (c) 1999-2009 by Digital Mars
+// Copyright (c) 1999-2010 by Digital Mars
 // All Rights Reserved
 // written by Walter Bright
 // http://www.digitalmars.com
@@ -65,7 +65,7 @@
     inlineNest = 0;
     inlineAsm = 0;
     cantInterpret = 0;
-    semanticRun = 0;
+    semanticRun = PASSinit;
 #if DMDV1
     nestedFrameRef = 0;
 #endif
@@ -131,8 +131,9 @@
     f->fbody    = fbody    ? fbody->syntaxCopy()    : NULL;
     assert(!fthrows); // deprecated
 
-    // LDC
+#if IN_LLVM
     f->intrinsicName = intrinsicName;
+#endif
 
     return f;
 }
@@ -155,7 +156,7 @@
     printf("type: %p, %s\n", type, type->toChars());
 #endif
 
-    if (semanticRun && isFuncLiteralDeclaration())
+    if (semanticRun != PASSinit && isFuncLiteralDeclaration())
     {
 	/* Member functions that have return types that are
 	 * forward references can have semantic() run more than
@@ -164,8 +165,24 @@
 	 */
 	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;
+    }
+
+    unsigned dprogress_save = Module::dprogress;
+
+    foverrides.setDim(0);	// reset in case semantic() is being retried for this function
 
     if (!type->deco)
     {
@@ -181,15 +198,9 @@
     size_t nparams = Parameter::dim(f->parameters);
 
     linkage = sc->linkage;
-//    if (!parent)
-    {
-	//parent = sc->scopesym;
-	parent = sc->parent;
-    }
     protection = sc->protection;
     storage_class |= sc->stc;
     //printf("function storage_class = x%x\n", storage_class);
-    Dsymbol *parent = toParent();
 
     if (ident == Id::ctor && !isCtorDeclaration())
 	error("_ctor is reserved for constructors");
@@ -267,7 +278,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());
     }
 
@@ -337,8 +348,12 @@
 	    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:
@@ -378,10 +393,11 @@
 
 	    case -2:	// can't determine because of fwd refs
 		cd->sizeok = 2;	// can't finish due to forward reference
+		Module::dprogress = dprogress_save;
 		return;
 
 	    default:
-	    {   FuncDeclaration *fdv = (FuncDeclaration *)cd->vtbl.data[vi];
+	    {   FuncDeclaration *fdv = (FuncDeclaration *)cd->baseClass->vtbl.data[vi];
 		// This function is covariant with fdv
 		if (fdv->isFinal())
 		    error("cannot override final function %s", fdv->toPrettyChars());
@@ -455,6 +471,7 @@
 
 		case -2:
 		    cd->sizeok = 2;	// can't finish due to forward reference
+		    Module::dprogress = dprogress_save;
 		    return;
 
 		default:
@@ -472,19 +489,22 @@
 			/* Only need to have a tintro if the vptr
 			 * offsets differ
 			 */
+			unsigned errors = global.errors;
+			global.gag++;            // suppress printing of error messages
 			int offset;
-			if (fdv->type->nextOf()->isBaseOf(type->nextOf(), &offset))
+			int baseOf = fdv->type->nextOf()->isBaseOf(type->nextOf(), &offset);
+			global.gag--;            // suppress printing of error messages
+			if (errors != global.errors)
+			{
+			    // 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
+			    Module::dprogress = dprogress_save;
+			    return;
+			}
+			if (baseOf)
 			{
 			    ti = fdv->type;
-#if 0
-			    if (offset)
-				ti = fdv->type;
-			    else if (type->nextOf()->ty == Tclass)
-			    {   ClassDeclaration *cdn = ((TypeClass *)type->nextOf())->sym;
-				if (cdn && cdn->sizeok != 1)
-				    ti = fdv->type;
-			    }
-#endif
 			}
 		    }
 		    if (ti)
@@ -596,7 +616,7 @@
 	}
     }
 
-    if (isVirtual())
+    if (isVirtual() && semanticRun != PASSsemanticdone)
     {
 	/* Rewrite contracts as nested functions, then call them.
 	 * Doing it as nested functions means that overriding functions
@@ -652,6 +672,9 @@
     }
 
 Ldone:
+    Module::dprogress++;
+    semanticRun = PASSsemanticdone;
+
     /* Save scope for possible later use (if we need the
      * function internals)
      */
@@ -688,14 +711,14 @@
     //printf("\tlinkage = %d\n", sc->linkage);
 
     //printf(" sc->incontract = %d\n", sc->incontract);
-    if (semanticRun >= 3)
+    if (semanticRun >= PASSsemantic3)
 	return;
-    semanticRun = 3;
-
-    // LDC
+    semanticRun = PASSsemantic3;
+
+#if IN_LLVM
     if (!global.params.useAvailableExternally)
         availableExternally = false;
-
+#endif
     if (!type || type->ty != Tfunction)
 	return;
     f = (TypeFunction *)(type);
@@ -1466,7 +1489,7 @@
 	sc2->callSuper = 0;
 	sc2->pop();
     }
-    semanticRun = 4;
+    semanticRun = PASSsemantic3done;
 }
 
 void FuncDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
@@ -1638,6 +1661,7 @@
 /*************************************************
  * 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
@@ -1645,11 +1669,16 @@
 
 int FuncDeclaration::findVtblIndex(Array *vtbl, int dim)
 {
+    FuncDeclaration *mismatch = NULL;
+    int bestvi = -1;
     for (int vi = 0; vi < dim; vi++)
     {
 	FuncDeclaration *fdv = ((Dsymbol *)vtbl->data[vi])->isFuncDeclaration();
 	if (fdv && fdv->ident == 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)
@@ -1658,15 +1687,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
@@ -1676,7 +1702,15 @@
 	    }
 	}
     }
-    return -1;
+    if (bestvi == -1 && mismatch)
+    {
+	//type->print();
+	//mismatch->type->print();
+	//printf("%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;
 }
 
 /****************************************************
@@ -2554,7 +2588,7 @@
 	id = "__dgliteral";
     else
 	id = "__funcliteral";
-    this->ident = Identifier::generateId(id);
+    this->ident = Lexer::uniqueId(id);
     this->tok = tok;
     this->fes = fes;
     //printf("FuncLiteralDeclaration() id = '%s', type = '%s'\n", this->ident->toChars(), type->toChars());
@@ -2568,7 +2602,9 @@
     if (s)
 	f = (FuncLiteralDeclaration *)s;
     else
-	f = new FuncLiteralDeclaration(loc, endloc, type->syntaxCopy(), tok, fes);
+    {	f = new FuncLiteralDeclaration(loc, endloc, type->syntaxCopy(), tok, fes);
+	f->ident = ident;		// keep old identifier
+    }
     FuncDeclaration::syntaxCopy(f);
     return f;
 }
@@ -2634,19 +2670,14 @@
 
 void CtorDeclaration::semantic(Scope *sc)
 {
-    ClassDeclaration *cd;
-    Type *tret;
-
-    //printf("CtorDeclaration::semantic()\n");
-    if (type)
-	return;
-
+    //printf("CtorDeclaration::semantic() %s\n", toChars());
     sc = sc->push();
     sc->stc &= ~STCstatic;		// not a static constructor
 
     parent = sc->parent;
     Dsymbol *parent = toParent();
-    cd = parent->isClassDeclaration();
+    Type *tret;
+    ClassDeclaration *cd = parent->isClassDeclaration();
     if (!cd)
     {
 	error("constructors are only for class definitions");
@@ -2655,7 +2686,8 @@
     }
     else
 	tret = cd->type; //->referenceTo();
-    type = new TypeFunction(arguments, tret, varargs, LINKd);
+    if (!type)
+	type = new TypeFunction(arguments, tret, varargs, LINKd);
 #if STRUCTTHISREF
     if (ad && ad->isStructDeclaration())
 	((TypeFunction *)type)->isref = 1;
@@ -2670,7 +2702,7 @@
     // Append:
     //	return this;
     // to the function body
-    if (fbody)
+    if (fbody && semanticRun < PASSsemantic)
     {
 	Expression *e = new ThisExp(loc);
 	Statement *s = new ReturnStatement(loc, e);
@@ -2744,6 +2776,7 @@
 {
     //printf("PostBlitDeclaration::semantic() %s\n", toChars());
     //printf("ident: %s, %s, %p, %p\n", ident->toChars(), Id::dtor->toChars(), ident, Id::dtor);
+    //printf("stc = x%llx\n", sc->stc);
     parent = sc->parent;
     Dsymbol *parent = toParent();
     StructDeclaration *ad = parent->isStructDeclaration();
@@ -2751,9 +2784,11 @@
     {
 	error("post blits are only for struct/union definitions, not %s %s", parent->kind(), parent->toChars());
     }
-    else if (ident == Id::_postblit)
+    else if (ident == Id::_postblit && semanticRun < PASSsemantic)
 	ad->postblits.push(this);
-    type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd);
+
+    if (!type)
+	type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd);
 
     sc = sc->push();
     sc->stc &= ~STCstatic;		// not static
@@ -2786,9 +2821,7 @@
 
 void PostBlitDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
 {
-    if (hgs->hdrgen)
-	return;
-    buf->writestring("=this()");
+    buf->writestring("this(this)");
     bodyToCBuffer(buf, hgs);
 }
 #endif
@@ -2825,9 +2858,11 @@
 	error("destructors are only for class/struct/union definitions, not %s %s", parent->kind(), parent->toChars());
 	fatal();
     }
-    else
+    else if (semanticRun < PASSsemantic)
 	cd->dtors.push(this);
-    type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd);
+
+    if (!type)
+	type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd);
 
     sc = sc->push();
     sc->stc &= ~STCstatic;		// not a static destructor
@@ -2893,10 +2928,8 @@
 
 Dsymbol *StaticCtorDeclaration::syntaxCopy(Dsymbol *s)
 {
-    StaticCtorDeclaration *scd;
-
     assert(!s);
-    scd = new StaticCtorDeclaration(loc, endloc);
+    StaticCtorDeclaration *scd = new StaticCtorDeclaration(loc, endloc);
     return FuncDeclaration::syntaxCopy(scd);
 }
 
@@ -2905,13 +2938,14 @@
 {
     //printf("StaticCtorDeclaration::semantic()\n");
 
-    type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd);
+    if (!type)
+	type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd);
 
     /* If the static ctor appears within a template instantiation,
      * it could get called multiple times by the module constructors
      * for different modules. Thus, protect it with a gate.
      */
-    if (inTemplateInstance())
+    if (inTemplateInstance() && semanticRun < PASSsemantic)
     {
 	/* Add this prefix to the function:
 	 *	static int gate;
@@ -2943,6 +2977,7 @@
 	m = sc->module;
     if (m)
     {	m->needmoduleinfo = 1;
+	//printf("module1 %s needs moduleinfo\n", m->toChars());
 #ifdef IN_GCC
 	m->strictlyneedmoduleinfo = 1;
 #endif
@@ -3005,20 +3040,16 @@
 
 void StaticDtorDeclaration::semantic(Scope *sc)
 {
-    ClassDeclaration *cd;
-    Type *tret;
-
-    cd = sc->scopesym->isClassDeclaration();
-    if (!cd)
-    {
-    }
-    type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd);
+    ClassDeclaration *cd = sc->scopesym->isClassDeclaration();
+
+    if (!type)
+	type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd);
 
     /* If the static ctor appears within a template instantiation,
      * it could get called multiple times by the module constructors
      * for different modules. Thus, protect it with a gate.
      */
-    if (inTemplateInstance())
+    if (inTemplateInstance() && semanticRun < PASSsemantic)
     {
 	/* Add this prefix to the function:
 	 *	static int gate;
@@ -3112,23 +3143,21 @@
 
 void InvariantDeclaration::semantic(Scope *sc)
 {
-    AggregateDeclaration *ad;
-    Type *tret;
-
     parent = sc->parent;
     Dsymbol *parent = toParent();
-    ad = parent->isAggregateDeclaration();
+    AggregateDeclaration *ad = parent->isAggregateDeclaration();
     if (!ad)
     {
 	error("invariants are only for struct/union/class definitions");
 	return;
     }
-    else if (ad->inv && ad->inv != this)
+    else if (ad->inv && ad->inv != this && semanticRun < PASSsemantic)
     {
 	error("more than one invariant for %s", ad->toChars());
     }
     ad->inv = this;
-    type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd);
+    if (!type)
+	type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd);
 
     sc = sc->push();
     sc->stc &= ~STCstatic;		// not a static invariant
@@ -3195,7 +3224,8 @@
 {
     if (global.params.useUnitTests)
     {
-	type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd);
+	if (!type)
+	    type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd);
 	Scope *sc2 = sc->push();
 	sc2->linkage = LINKd;
 	FuncDeclaration::semantic(sc2);
@@ -3271,20 +3301,18 @@
 
 void NewDeclaration::semantic(Scope *sc)
 {
-    ClassDeclaration *cd;
-    Type *tret;
-
     //printf("NewDeclaration::semantic()\n");
 
     parent = sc->parent;
     Dsymbol *parent = toParent();
-    cd = parent->isClassDeclaration();
+    ClassDeclaration *cd = parent->isClassDeclaration();
     if (!cd && !parent->isStructDeclaration())
     {
 	error("new allocators only are for class or struct definitions");
     }
-    tret = Type::tvoid->pointerTo();
-    type = new TypeFunction(arguments, tret, varargs, LINKd);
+    Type *tret = Type::tvoid->pointerTo();
+    if (!type)
+	type = new TypeFunction(arguments, tret, varargs, LINKd);
 
     type = type->semantic(loc, sc);
     assert(type->ty == Tfunction);
@@ -3357,18 +3385,17 @@
 
 void DeleteDeclaration::semantic(Scope *sc)
 {
-    ClassDeclaration *cd;
-
     //printf("DeleteDeclaration::semantic()\n");
 
     parent = sc->parent;
     Dsymbol *parent = toParent();
-    cd = parent->isClassDeclaration();
+    ClassDeclaration *cd = parent->isClassDeclaration();
     if (!cd && !parent->isStructDeclaration())
     {
 	error("new allocators only are for class or struct definitions");
     }
-    type = new TypeFunction(arguments, Type::tvoid, 0, LINKd);
+    if (!type)
+	type = new TypeFunction(arguments, Type::tvoid, 0, LINKd);
 
     type = type->semantic(loc, sc);
     assert(type->ty == Tfunction);