diff dmd/template.c @ 561:d4e95db0e62b

Introducing template instantiation traces for static asserts and errors within templates.
author Christian Kamm <kamm incasoftware de>
date Sat, 30 Aug 2008 10:30:57 +0200
parents cecfee2d01a8
children eef8ac26c66c
line wrap: on
line diff
--- a/dmd/template.c	Fri Aug 29 15:01:48 2008 +0200
+++ b/dmd/template.c	Sat Aug 30 10:30:57 2008 +0200
@@ -2775,6 +2775,7 @@
     this->havetempdecl = 0;
     this->isnested = NULL;
     this->errors = 0;
+    this->tinst = NULL;
 }
 
 
@@ -2798,6 +2799,7 @@
     this->havetempdecl = 1;
     this->isnested = NULL;
     this->errors = 0;
+    this->tinst = NULL;
 
     assert((size_t)tempdecl->scope > 0x10000);
 }
@@ -2874,6 +2876,9 @@
     }
     semanticdone = 1;
 
+    // get the enclosing template instance from the scope tinst
+    tinst = sc->tinst;
+
 #if LOG
     printf("\tdo semantic\n");
 #endif
@@ -3062,6 +3067,7 @@
     sc2 = scope->push(this);
     //printf("isnested = %d, sc->parent = %s\n", isnested, sc->parent->toChars());
     sc2->parent = /*isnested ? sc->parent :*/ this;
+    sc2->tinst = this;
 
 #if !IN_LLVM    
 #if _WIN32
@@ -3130,6 +3136,8 @@
     if (global.errors != errorsave)
     {
 	error("error instantiating");
+	if(tinst)
+	    tinst->printInstantiationTrace();
 	errors = 1;
 	if (global.gag)
 	    tempdecl->instances.remove(tempdecl_instance_idx);
@@ -3687,6 +3695,7 @@
 	assert(sc);
 	sc = sc->push(argsym);
 	sc = sc->push(this);
+	sc->tinst = this;
 	for (i = 0; i < members->dim; i++)
 	{
 	    Dsymbol *s = (Dsymbol *)members->data[i];
@@ -3717,6 +3726,7 @@
 	sc = tempdecl->scope;
 	sc = sc->push(argsym);
 	sc = sc->push(this);
+	sc->tinst = this;
 	for (int i = 0; i < members->dim; i++)
 	{
 	    Dsymbol *s = (Dsymbol *)members->data[i];
@@ -3837,6 +3847,43 @@
     return s;
 }
 
+void TemplateInstance::printInstantiationTrace()
+{
+    if(global.gag)
+	return;
+
+    const int max_shown = 6;
+
+    // determine instantiation depth
+    int n_instantiations = 1;
+    TemplateInstance* cur = this;
+    while(cur = cur->tinst)
+	++n_instantiations;
+
+    // show full trace only if it's short or verbose is on
+    if(n_instantiations <= max_shown || global.params.verbose)
+    {
+	cur = this;
+	while(cur)
+	{
+	    fprintf(stdmsg,"    instantiatied in %s: %s\n", cur->loc.toChars(), cur->toChars());
+	    cur = cur->tinst;
+	}
+    }
+    else
+    {
+	cur = this;
+	size_t i = 0;
+	for(; i < max_shown/2; ++i, cur = cur->tinst)
+	    fprintf(stdmsg,"    instantiatied in %s: %s\n", cur->loc.toChars(), cur->toChars());
+	fprintf(stdmsg,"    ... (%d instantiations, -v to show) ...\n", n_instantiations - max_shown);
+	for(; i < n_instantiations - max_shown + max_shown/2; ++i, cur = cur->tinst) 
+	{}
+	for(; i < n_instantiations; ++i, cur = cur->tinst) 
+	    fprintf(stdmsg,"    instantiatied in %s: %s\n", cur->loc.toChars(), cur->toChars());
+    }
+}
+
 /* ======================== TemplateMixin ================================ */
 
 TemplateMixin::TemplateMixin(Loc loc, Identifier *ident, Type *tqual,