diff dmd/func.c @ 1602:a413ae7329bf

Merge DMD r243: some harmonization with D2 dmd --- dmd/aggregate.h | 24 ++++- dmd/attrib.c | 63 ++++++---- dmd/attrib.h | 10 +- dmd/declaration.h | 5 +- dmd/func.c | 337 ++++++++++++++++++++++------------------------------- dmd/mars.c | 2 +- dmd/mars.h | 7 + dmd/mtype.h | 13 ++- dmd/parse.c | 32 ++++- dmd/parse.h | 14 ++- dmd/scope.h | 2 +- 11 files changed, 263 insertions(+), 246 deletions(-)
author Leandro Lucarella <llucax@gmail.com>
date Wed, 06 Jan 2010 15:18:19 -0300
parents def7a1d494fd
children 207a8a438dea
line wrap: on
line diff
--- a/dmd/func.c	Mon Dec 28 02:23:54 2009 +0000
+++ b/dmd/func.c	Wed Jan 06 15:18:19 2010 -0300
@@ -31,7 +31,7 @@
 
 /********************************* FuncDeclaration ****************************/
 
-FuncDeclaration::FuncDeclaration(Loc loc, Loc endloc, Identifier *id, enum STC storage_class, Type *type)
+FuncDeclaration::FuncDeclaration(Loc loc, Loc endloc, Identifier *id, StorageClass storage_class, Type *type)
     : Declaration(id)
 {
     //printf("FuncDeclaration(id = '%s', type = %p)\n", id->toChars(), type);
@@ -124,7 +124,7 @@
     if (s)
 	f = (FuncDeclaration *)s;
     else
-	f = new FuncDeclaration(loc, endloc, ident, (enum STC) storage_class, type->syntaxCopy());
+	f = new FuncDeclaration(loc, endloc, ident, storage_class, type->syntaxCopy());
     f->outId = outId;
     f->frequire = frequire ? frequire->syntaxCopy() : NULL;
     f->fensure  = fensure  ? fensure->syntaxCopy()  : NULL;
@@ -446,7 +446,6 @@
 	 */
 	for (int i = 0; i < cd->interfaces_dim; i++)
 	{
-#if 1
 	    BaseClass *b = cd->interfaces[i];
 	    vi = findVtblIndex(&b->base->vtbl, b->base->vtbl.dim);
 	    switch (vi)
@@ -499,68 +498,6 @@
 		    goto L2;
 		}
 	    }
-#else
-	    BaseClass *b = cd->interfaces[i];
-	    for (vi = 0; vi < b->base->vtbl.dim; vi++)
-	    {
-		Dsymbol *s = (Dsymbol *)b->base->vtbl.data[vi];
-		//printf("interface %d vtbl[%d] %p %s\n", i, vi, s, s->toChars());
-		FuncDeclaration *fdv = s->isFuncDeclaration();
-		if (fdv && fdv->ident == ident)
-		{
-		    int cov = type->covariant(fdv->type);
-		    //printf("\tcov = %d\n", cov);
-		    if (cov == 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());
-		    }
-		    if (cov == 1)
-		    {	Type *ti = NULL;
-
-			if (fdv->tintro)
-			    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;
-#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)
-			{
-			    if (tintro && !tintro->equals(ti))
-			    {
-				error("incompatible covariant types %s and %s", tintro->toChars(), ti->toChars());
-			    }
-			    tintro = ti;
-			}
-			goto L2;
-		    }
-		    if (cov == 3)
-		    {
-			cd->sizeok = 2;	// can't finish due to forward reference
-			return;
-		    }
-		}
-	    }
-#endif
 	}
 
 	if (introducing && isOverride())
@@ -1312,13 +1249,11 @@
 		v_argptr = argptr;
 		v_argptr->init = new VoidInitializer(loc);
 #else
-		Expression *e1;
-		Expression *e;
 		Type *t = argptr->type;
 		VarDeclaration *p;
 		unsigned offset;
 
-		e1 = new VarExp(0, argptr);
+		Expression *e1 = new VarExp(0, argptr);
 		if (parameters && parameters->dim)
 		    p = (VarDeclaration *)parameters->data[parameters->dim - 1];
 		else
@@ -1329,7 +1264,7 @@
 		else
 		    offset = p->type->size();
 		offset = (offset + 3) & ~3;	// assume stack aligns on 4
-		e = new SymOffExp(0, p, offset);
+		Expression *e = new SymOffExp(0, p, offset);
 		e = new AssignExp(0, e1, e);
 		e->type = t;
 		a->push(new ExpStatement(0, e));
@@ -1918,48 +1853,6 @@
     return p.f;
 }
 
-#if 0
-FuncDeclaration *FuncDeclaration::overloadExactMatch(Type *t)
-{
-    FuncDeclaration *f;
-    Declaration *d;
-    Declaration *next;
-
-    for (d = this; d; d = next)
-    {	FuncAliasDeclaration *fa = d->isFuncAliasDeclaration();
-
-	if (fa)
-	{
-	    FuncDeclaration *f2 = fa->funcalias->overloadExactMatch(t);
-	    if (f2)
-		return f2;
-	    next = fa->overnext;
-	}
-	else
-	{
-	    AliasDeclaration *a = d->isAliasDeclaration();
-
-	    if (a)
-	    {
-		Dsymbol *s = a->toAlias();
-		next = s->isDeclaration();
-		if (next == a)
-		    break;
-	    }
-	    else
-	    {
-		f = d->isFuncDeclaration();
-		if (!f)
-		    break;		// BUG: should print error message?
-		if (t->equals(d->type))
-		    return f;
-		next = f->overnext;
-	    }
-	}
-    }
-    return NULL;
-}
-#endif
 
 /********************************************
  * Decide which function matches the arguments best.
@@ -1968,6 +1861,9 @@
 struct Param2
 {
     Match *m;
+#if DMDV2
+    Expression *ethis;
+#endif
     Expressions *arguments;
 };
 
@@ -1998,6 +1894,22 @@
 	    else if (f->overrides(m->lastf))
 		goto LfIsBetter;
 
+#if DMDV2
+	    /* Try to disambiguate using template-style partial ordering rules.
+	     * In essence, if f() and g() are ambiguous, if f() can call g(),
+	     * but g() cannot call f(), then pick f().
+	     * This is because f() is "more specialized."
+	     */
+	    {
+	    MATCH c1 = f->leastAsSpecialized(m->lastf);
+	    MATCH c2 = m->lastf->leastAsSpecialized(f);
+	    //printf("c1 = %d, c2 = %d\n", c1, c2);
+	    if (c1 > c2)
+		goto LfIsBetter;
+	    if (c1 < c2)
+		goto LlastIsBetter;
+	    }
+#endif
 	Lambiguous:
 	    m->nextf = f;
 	    m->count++;
@@ -2026,87 +1938,6 @@
     overloadApply(from, fstart, &fp2, &p);
 }
 
-#if 0
-// Recursive helper function
-
-void overloadResolveX(Match *m, FuncDeclaration *fstart, Expressions *arguments)
-{
-    MATCH match;
-    Declaration *d;
-    Declaration *next;
-
-    for (d = fstart; d; d = next)
-    {
-	FuncDeclaration *f;
-	FuncAliasDeclaration *fa;
-	AliasDeclaration *a;
-
-	fa = d->isFuncAliasDeclaration();
-	if (fa)
-	{
-	    overloadResolveX(m, fa->funcalias, NULL, arguments);
-	    next = fa->overnext;
-	}
-	else if ((f = d->isFuncDeclaration()) != NULL)
-	{
-	    next = f->overnext;
-	    if (f == m->lastf)
-		continue;			// skip duplicates
-	    else
-	    {
-		TypeFunction *tf;
-
-		m->anyf = f;
-		tf = (TypeFunction *)f->type;
-		match = (MATCH) tf->callMatch(arguments);
-		//printf("2match = %d\n", match);
-		if (match != MATCHnomatch)
-		{
-		    if (match > m->last)
-			goto LfIsBetter;
-
-		    if (match < m->last)
-			goto LlastIsBetter;
-
-		    /* See if one of the matches overrides the other.
-		     */
-		    if (m->lastf->overrides(f))
-			goto LlastIsBetter;
-		    else if (f->overrides(m->lastf))
-			goto LfIsBetter;
-
-		Lambiguous:
-		    m->nextf = f;
-		    m->count++;
-		    continue;
-
-		LfIsBetter:
-		    m->last = match;
-		    m->lastf = f;
-		    m->count = 1;
-		    continue;
-
-		LlastIsBetter:
-		    continue;
-		}
-	    }
-	}
-	else if ((a = d->isAliasDeclaration()) != NULL)
-	{
-	    Dsymbol *s = a->toAlias();
-	    next = s->isDeclaration();
-	    if (next == a)
-		break;
-	    if (next == fstart)
-		break;
-	}
-	else
-	{   d->error("is aliased to a function");
-	    break;
-	}
-    }
-}
-#endif
 
 FuncDeclaration *FuncDeclaration::overloadResolve(Loc loc, Expression *ethis, Expressions *arguments, Module *from, int flags)
 {
@@ -2179,6 +2010,118 @@
     }
 }
 
+/*************************************
+ * Determine partial specialization order of 'this' vs g.
+ * This is very similar to TemplateDeclaration::leastAsSpecialized().
+ * Returns:
+ *	match	'this' is at least as specialized as g
+ *	0	g is more specialized than 'this'
+ */
+
+#if DMDV2
+MATCH FuncDeclaration::leastAsSpecialized(FuncDeclaration *g)
+{
+#define LOG_LEASTAS     0
+
+#if LOG_LEASTAS
+    printf("%s.leastAsSpecialized(%s)\n", toChars(), g->toChars());
+#endif
+
+    /* This works by calling g() with f()'s parameters, and
+     * if that is possible, then f() is at least as specialized
+     * as g() is.
+     */
+
+    TypeFunction *tf = (TypeFunction *)type;
+    TypeFunction *tg = (TypeFunction *)g->type;
+    size_t nfparams = Argument::dim(tf->parameters);
+    size_t ngparams = Argument::dim(tg->parameters);
+    MATCH match = MATCHexact;
+
+    /* If both functions have a 'this' pointer, and the mods are not
+     * the same and g's is not const, then this is less specialized.
+     */
+    if (needThis() && g->needThis())
+    {
+	if (tf->mod != tg->mod)
+	{
+	    if (tg->mod == MODconst)
+		match = MATCHconst;
+	    else
+		return MATCHnomatch;
+	}
+    }
+
+    /* Create a dummy array of arguments out of the parameters to f()
+     */
+    Expressions args;
+    args.setDim(nfparams);
+    for (int u = 0; u < nfparams; u++)
+    {
+	Argument *p = Argument::getNth(tf->parameters, u);
+	Expression *e;
+	if (p->storageClass & (STCref | STCout))
+	{
+	    e = new IdentifierExp(0, p->ident);
+	    e->type = p->type;
+	}
+	else
+	    e = p->type->defaultInit();
+	args.data[u] = e;
+    }
+
+    MATCH m = (MATCH) tg->callMatch(NULL, &args);
+    if (m)
+    {
+        /* A variadic parameter list is less specialized than a
+         * non-variadic one.
+         */
+        if (tf->varargs && !tg->varargs)
+            goto L1;	// less specialized
+
+#if LOG_LEASTAS
+        printf("  matches %d, so is least as specialized\n", m);
+#endif
+        return m;
+    }
+  L1:
+#if LOG_LEASTAS
+    printf("  doesn't match, so is not as specialized\n");
+#endif
+    return MATCHnomatch;
+}
+
+/*******************************************
+ * Given a symbol that could be either a FuncDeclaration or
+ * a function template, resolve it to a function symbol.
+ *	sc		instantiation scope
+ *	loc		instantiation location
+ *	targsi		initial list of template arguments
+ *	ethis		if !NULL, the 'this' pointer argument
+ *	fargs		arguments to function
+ *	flags		1: do not issue error message on no match, just return NULL
+ */
+
+FuncDeclaration *resolveFuncCall(Scope *sc, Loc loc, Dsymbol *s,
+	Objects *tiargs,
+	Expression *ethis,
+	Expressions *arguments,
+	int flags)
+{
+    if (!s)
+	return NULL;			// no match
+    FuncDeclaration *f = s->isFuncDeclaration();
+    if (f)
+	f = f->overloadResolve(loc, ethis, arguments);
+    else
+    {	TemplateDeclaration *td = s->isTemplateDeclaration();
+	assert(td);
+	f = td->deduceFunctionTemplate(sc, loc, tiargs, NULL, arguments, flags);
+    }
+    return f;
+}
+#endif
+
 /********************************
  * Labels are in a separate scope, one per function.
  */
@@ -2298,15 +2241,14 @@
 }
 
 void FuncDeclaration::appendState(Statement *s)
-{   CompoundStatement *cs;
-
+{
     if (!fbody)
     {	Statements *a;
 
 	a = new Statements();
 	fbody = new CompoundStatement(0, a);
     }
-    cs = fbody->isCompoundStatement();
+    CompoundStatement *cs = fbody->isCompoundStatement();
     cs->statements->push(s);
 }
 
@@ -2362,7 +2304,7 @@
 {
 #if 0
     printf("FuncDeclaration::isVirtual(%s)\n", toChars());
-    printf("%p %d %d %d %d\n", isMember(), isStatic(), protection == PROTprivate, isCtorDeclaration(), linkage != LINKd);
+    printf("isMember:%p isStatic:%d private:%d ctor:%d !Dlinkage:%d\n", isMember(), isStatic(), protection == PROTprivate, isCtorDeclaration(), linkage != LINKd);
     printf("result is %d\n",
 	isMember() &&
 	!(isStatic() || protection == PROTprivate || protection == PROTpackage) &&
@@ -2407,7 +2349,7 @@
 {
     //if (!toParent())
 	//printf("FuncDeclaration::isNested('%s') parent=%p\n", toChars(), parent);
-    //printf("\ttoParent() = '%s'\n", toParent()->toChars());
+    //printf("\ttoParent2() = '%s'\n", toParent2()->toChars());
     return ((storage_class & STCstatic) == 0) && toParent2() &&
 	   (toParent2()->isFuncDeclaration() != NULL);
 }
@@ -3078,6 +3020,7 @@
 	m = sc->module;
     if (m)
     {	m->needmoduleinfo = 1;
+	//printf("module2 %s needs moduleinfo\n", m->toChars());
 #ifdef IN_GCC
 	m->strictlyneedmoduleinfo = 1;
 #endif