diff dmd/template.c @ 1587:def7a1d494fd

Merge DMD 1.051
author Christian Kamm <kamm incasoftware de>
date Fri, 06 Nov 2009 23:58:01 +0100
parents 4dca8ed9d8b7
children 207a8a438dea
line wrap: on
line diff
--- a/dmd/template.c	Fri Nov 06 21:51:41 2009 +0100
+++ b/dmd/template.c	Fri Nov 06 23:58:01 2009 +0100
@@ -310,7 +310,7 @@
     this->members = decldefs;
     this->overnext = NULL;
     this->overroot = NULL;
-    this->scope = NULL;
+    this->semanticRun = 0;
     this->onemember = NULL;
 }
 
@@ -350,8 +350,9 @@
 #if LOG
     printf("TemplateDeclaration::semantic(this = %p, id = '%s')\n", this, ident->toChars());
 #endif
-    if (scope)
+    if (semanticRun)
 	return;		// semantic() already run
+    semanticRun = 1;
 
     if (sc->func)
     {
@@ -803,16 +804,19 @@
     {	// Set initial template arguments
 
 	nargsi = targsi->dim;
-	if (nargsi > parameters->dim)
+	size_t n = parameters->dim;
+	if (nargsi > n)
 	{   if (!tp)
 		goto Lnomatch;
 	    dedargs->setDim(nargsi);
 	    dedargs->zero();
 	}
-
-	memcpy(dedargs->data, targsi->data, nargsi * sizeof(*dedargs->data));
-
-	for (size_t i = 0; i < nargsi; i++)
+	else
+	    n = nargsi;
+
+	memcpy(dedargs->data, targsi->data, n * sizeof(*dedargs->data));
+
+	for (size_t i = 0; i < n; i++)
 	{   assert(i < parameters->dim);
 	    TemplateParameter *tp = (TemplateParameter *)parameters->data[i];
 	    MATCH m;
@@ -844,7 +848,7 @@
     fdtype = (TypeFunction *)fd->type;
 
     nfparams = Argument::dim(fdtype->parameters); // number of function parameters
-    nfargs = fargs->dim;		// number of function arguments
+    nfargs = fargs ? fargs->dim : 0;		// number of function arguments
 
     /* Check for match of function arguments with variadic template
      * parameter, such as:
@@ -854,7 +858,7 @@
      */
     if (tp)				// if variadic
     {
-	if (nfparams == 0)		// if no function parameters
+	if (nfparams == 0 && nfargs != 0)		// if no function parameters
 	{
 	    Tuple *t = new Tuple();
 	    //printf("t = %p\n", t);
@@ -1293,7 +1297,7 @@
 
     for (TemplateDeclaration *td = this; td; td = td->overnext)
     {
-	if (!td->scope)
+	if (!td->semanticRun)
 	{
 	    error("forward reference to template %s", td->toChars());
 	    goto Lerror;
@@ -1901,14 +1905,21 @@
 
       L2:
 
-	for (int i = 0; i < tempinst->tiargs->dim; i++)
+	for (int i = 0; 1; i++)
 	{
 	    //printf("\ttest: tempinst->tiargs[%d]\n", i);
+	    Object *o1;
+	    if (i < tempinst->tiargs->dim)
+		o1 = (Object *)tempinst->tiargs->data[i];
+	    else if (i < tempinst->tdtypes.dim && i < tp->tempinst->tiargs->dim)
+		// Pick up default arg
+		o1 = (Object *)tempinst->tdtypes.data[i];
+	    else
+		break;
+
 	    if (i >= tp->tempinst->tiargs->dim)
 		goto Lnomatch;
 
-	    int j;
-	    Object *o1 = (Object *)tempinst->tiargs->data[i];
 	    Object *o2 = (Object *)tp->tempinst->tiargs->data[i];
 
 	    Type *t1 = isType(o1);
@@ -1934,6 +1945,7 @@
 #endif
 
 	    TemplateTupleParameter *ttp;
+	    int j;
 	    if (t2 &&
 		t2->ty == Tident &&
 		i == tp->tempinst->tiargs->dim - 1 &&
@@ -3062,7 +3074,7 @@
     this->tinst = NULL;
     this->argsym = NULL;
     this->aliasdecl = NULL;
-    this->semanticdone = 0;
+    this->semanticRun = 0;
     this->semantictiargsdone = 0;
     this->withsym = NULL;
     this->nest = 0;
@@ -3096,7 +3108,7 @@
     this->tinst = NULL;
     this->argsym = NULL;
     this->aliasdecl = NULL;
-    this->semanticdone = 0;
+    this->semanticRun = 0;
     this->semantictiargsdone = 1;
     this->withsym = NULL;
     this->nest = 0;
@@ -3179,13 +3191,13 @@
     // get the enclosing template instance from the scope tinst
     tinst = sc->tinst;
 
-    if (semanticdone != 0)
+    if (semanticRun != 0)
     {
 	error(loc, "recursive template expansion");
 //	inst = this;
 	return;
     }
-    semanticdone = 1;
+    semanticRun = 1;
 
     // get the enclosing template instance from the scope tinst
     tinst = sc->tinst;
@@ -3323,7 +3335,7 @@
 	{   Module *m = sc->module->importedFrom;
 	    //printf("\t2: adding to module %s instead of module %s\n", m->toChars(), sc->module->toChars());
 	    a = m->members;
-	    if (m->semanticdone >= 3)
+	    if (m->semanticRun >= 3)
 		dosemantic3 = 1;
 	}
 	for (int i = 0; 1; i++)
@@ -3344,9 +3356,9 @@
 
     // Create our own scope for the template parameters
     Scope *scope = tempdecl->scope;
-    if (!scope)
+    if (!tempdecl->semanticRun)
     {
-	error("forward reference to template declaration %s\n", tempdecl->toChars());
+	error("template instantiation %s forward references template declaration %s\n", toChars(), tempdecl->toChars());
 	return;
     }
 
@@ -3559,6 +3571,7 @@
 	    }
 	    else if (ta)
 	    {
+	      Ltype:
 		if (ta->ty == Ttuple)
 		{   // Expand tuple
 		    TypeTuple *tt = (TypeTuple *)ta;
@@ -3593,7 +3606,21 @@
 	    ea = ea->optimize(WANTvalue | WANTinterpret);
 	    tiargs->data[j] = ea;
 	    if (ea->op == TOKtype)
-		tiargs->data[j] = ea->type;
+	    {	ta = ea->type;
+		goto Ltype;
+	    }
+	    if (ea->op == TOKtuple)
+	    {   // Expand tuple
+		TupleExp *te = (TupleExp *)ea;
+		size_t dim = te->exps->dim;
+		tiargs->remove(j);
+		if (dim)
+		{   tiargs->reserve(dim);
+		    for (size_t i = 0; i < dim; i++)
+			tiargs->insert(j + i, te->exps->data[i]);
+		}
+		j--;
+	    }
 	}
 	else if (sa)
 	{
@@ -3736,6 +3763,23 @@
 #if LOG
     printf("TemplateInstance::findBestMatch()\n");
 #endif
+    // First look for forward references
+    for (TemplateDeclaration *td = tempdecl; td; td = td->overnext)
+    {
+	if (!td->semanticRun)
+	{
+	    if (td->scope)
+	    {	// Try to fix forward reference
+		td->semantic(td->scope);
+	    }
+	    if (!td->semanticRun)
+	    {
+		error("%s forward references template declaration %s\n", toChars(), td->toChars());
+		return NULL;
+	    }
+	}
+    }
+
     for (TemplateDeclaration *td = tempdecl; td; td = td->overnext)
     {
 	MATCH m;
@@ -3752,11 +3796,7 @@
 
 	dedtypes.setDim(td->parameters->dim);
 	dedtypes.zero();
-	if (!td->scope)
-	{
-	    error("forward reference to template declaration %s", td->toChars());
-	    return NULL;
-	}
+	assert(td->semanticRun);
 	m = td->matchWithInstance(this, &dedtypes, 0);
 	//printf("matchWithInstance = %d\n", m);
 	if (!m)			// no match at all
@@ -3964,6 +4004,7 @@
 	{   sinteger_t v;
 	    real_t r;
 
+	    ea = ea->optimize(WANTvalue | WANTinterpret);
 	    if (ea->op == TOKvar)
 	    {
 		sa = ((VarExp *)ea)->var;
@@ -4030,7 +4071,7 @@
  * template instance arguments.
  */
 
-void TemplateInstance::declareParameters(Scope *scope)
+void TemplateInstance::declareParameters(Scope *sc)
 {
     //printf("TemplateInstance::declareParameters()\n");
     for (int i = 0; i < tdtypes.dim; i++)
@@ -4040,7 +4081,7 @@
 	Object *o = (Object *)tdtypes.data[i];		// initializer for tp
 
 	//printf("\ttdtypes[%d] = %p\n", i, o);
-	tempdecl->declareParameter(scope, tp, o);
+	tempdecl->declareParameter(sc, tp, o);
     }
 }
 
@@ -4048,9 +4089,9 @@
 void TemplateInstance::semantic2(Scope *sc)
 {   int i;
 
-    if (semanticdone >= 2)
+    if (semanticRun >= 2)
 	return;
-    semanticdone = 2;
+    semanticRun = 2;
 #if LOG
     printf("+TemplateInstance::semantic2('%s')\n", toChars());
 #endif
@@ -4080,12 +4121,12 @@
 void TemplateInstance::semantic3(Scope *sc)
 {
 #if LOG
-    printf("TemplateInstance::semantic3('%s'), semanticdone = %d\n", toChars(), semanticdone);
+    printf("TemplateInstance::semantic3('%s'), semanticRun = %d\n", toChars(), semanticRun);
 #endif
 //if (toChars()[0] == 'D') *(char*)0=0;
-    if (semanticdone >= 3)
+    if (semanticRun >= 3)
 	return;
-    semanticdone = 3;
+    semanticRun = 3;
     if (!errors && members)
     {
 	sc = tempdecl->scope;
@@ -4182,6 +4223,7 @@
 #endif
     if (!inst)
     {	error("cannot resolve forward reference");
+	errors = 1;
 	return this;
     }
 
@@ -4274,7 +4316,6 @@
     this->tqual = tqual;
     this->idents = idents;
     this->tiargs = tiargs ? tiargs : new Objects();
-    this->scope = NULL;
 }
 
 Dsymbol *TemplateMixin::syntaxCopy(Dsymbol *s)
@@ -4308,18 +4349,22 @@
     printf("+TemplateMixin::semantic('%s', this=%p)\n", toChars(), this);
     fflush(stdout);
 #endif
-    if (semanticdone &&
+    if (semanticRun)
+    {
 	// This for when a class/struct contains mixin members, and
 	// is done over because of forward references
-	(!parent || !toParent()->isAggregateDeclaration()))
-    {
+	if (parent && toParent()->isAggregateDeclaration())
+	    semanticRun = 1;		// do over
+	else
+	{
 #if LOG
-	printf("\tsemantic done\n");
+	    printf("\tsemantic done\n");
 #endif
-	return;
+	    return;
+	}
     }
-    if (!semanticdone)
-	semanticdone = 1;
+    if (!semanticRun)
+	semanticRun = 1;
 #if LOG
     printf("\tdo semantic\n");
 #endif
@@ -4394,7 +4439,7 @@
     assert(tempdecl);
     for (TemplateDeclaration *td = tempdecl; td; td = td->overnext)
     {
-	if (!td->scope)
+	if (!td->semanticRun)
 	{
 	    /* Cannot handle forward references if mixin is a struct member,
 	     * because addField must happen during struct's semantic, not
@@ -4402,7 +4447,7 @@
 	     * runDeferred will re-run mixin's semantic outside of the struct's
 	     * semantic.
 	     */
-	    semanticdone = 0;
+	    semanticRun = 0;
 	    AggregateDeclaration *ad = toParent()->isAggregateDeclaration();
 	    if (ad)
 		ad->sizeok = 2;
@@ -4420,6 +4465,8 @@
 
     // Run semantic on each argument, place results in tiargs[]
     semanticTiargs(sc);
+    if (errors)
+	return;
 
     tempdecl = findBestMatch(sc);
     if (!tempdecl)
@@ -4508,19 +4555,19 @@
 
     argsym = new ScopeDsymbol();
     argsym->parent = scy->parent;
-    Scope *scope = scy->push(argsym);
+    Scope *argscope = scy->push(argsym);
 
     unsigned errorsave = global.errors;
 
     // Declare each template parameter as an alias for the argument type
-    declareParameters(scope);
+    declareParameters(argscope);
 
     // Add members to enclosing scope, as well as this scope
     for (unsigned i = 0; i < members->dim; i++)
     {   Dsymbol *s;
 
 	s = (Dsymbol *)members->data[i];
-	s->addMember(scope, this, i);
+	s->addMember(argscope, this, i);
 	//sc->insert(s);
 	//printf("sc->parent = %p, sc->scopesym = %p\n", sc->parent, sc->scopesym);
 	//printf("s->parent = %s\n", s->parent->toChars());
@@ -4531,7 +4578,7 @@
     printf("\tdo semantic() on template instance members '%s'\n", toChars());
 #endif
     Scope *sc2;
-    sc2 = scope->push(this);
+    sc2 = argscope->push(this);
     sc2->offset = sc->offset;
 
     static int nest;
@@ -4574,7 +4621,7 @@
 
     sc2->pop();
 
-    scope->pop();
+    argscope->pop();
 
 //    if (!isAnonymous())
     {
@@ -4588,9 +4635,9 @@
 void TemplateMixin::semantic2(Scope *sc)
 {   int i;
 
-    if (semanticdone >= 2)
+    if (semanticRun >= 2)
 	return;
-    semanticdone = 2;
+    semanticRun = 2;
 #if LOG
     printf("+TemplateMixin::semantic2('%s')\n", toChars());
 #endif
@@ -4618,9 +4665,9 @@
 void TemplateMixin::semantic3(Scope *sc)
 {   int i;
 
-    if (semanticdone >= 3)
+    if (semanticRun >= 3)
 	return;
-    semanticdone = 3;
+    semanticRun = 3;
 #if LOG
     printf("TemplateMixin::semantic3('%s')\n", toChars());
 #endif