Index: scope.c
===================================================================
--- scope.c	(revision 22)
+++ scope.c	(working copy)
@@ -53,6 +53,7 @@
     this->parent = NULL;
     this->sw = NULL;
     this->tf = NULL;
+	this->tinst = NULL;
     this->sbreak = NULL;
     this->scontinue = NULL;
     this->fes = NULL;
@@ -90,6 +91,7 @@
     this->sd = NULL;
     this->sw = enclosing->sw;
     this->tf = enclosing->tf;
+	this->tinst = enclosing->tinst;
     this->sbreak = enclosing->sbreak;
     this->scontinue = enclosing->scontinue;
     this->fes = enclosing->fes;
Index: scope.h
===================================================================
--- scope.h	(revision 22)
+++ scope.h	(working copy)
@@ -29,6 +29,7 @@
 struct AnonymousAggregateDeclaration;
 struct FuncDeclaration;
 struct DocComment;
+struct TemplateInstance;
 
 #if __GNUC__
 // Requires a full definition for PROT and LINK
@@ -52,6 +53,7 @@
     LabelStatement *slabel;	// enclosing labelled statement
     SwitchStatement *sw;	// enclosing switch statement
     TryFinallyStatement *tf;	// enclosing try finally statement
+    TemplateInstance *tinst;    // enclosing template instance
     Statement *sbreak;		// enclosing statement that supports "break"
     Statement *scontinue;	// enclosing statement that supports "continue"
     ForeachStatement *fes;	// if nested function for ForeachStatement, this is it
Index: staticassert.c
===================================================================
--- staticassert.c	(revision 23)
+++ staticassert.c	(working copy)
@@ -16,7 +16,10 @@
 #include "expression.h"
 #include "id.h"
 #include "hdrgen.h"
+#include "scope.h"
+#include "template.h"
 
+
 /********************************* AttribDeclaration ****************************/
 
 StaticAssert::StaticAssert(Loc loc, Expression *exp, Expression *msg)
@@ -45,6 +48,10 @@
 {
 }
 
+#include "scope.h"
+#include "template.h"
+#include "declaration.h"
+
 void StaticAssert::semantic2(Scope *sc)
 {
     Expression *e;
@@ -66,8 +73,11 @@
 	}
 	else
 	    error("(%s) is false", exp->toChars());
-//	if (!global.gag)
-//	    fatal();
+		if(sc->tinst)
+	    sc->tinst->printInstantiationTrace();
+	  if (!global.gag) {
+	      fatal();
+	  }
     }
     else if (!e->isBool(TRUE))
     {
Index: template.c
===================================================================
--- template.c	(revision 22)
+++ template.c	(working copy)
@@ -3198,6 +3198,7 @@
     this->tiargs = NULL;
     this->tempdecl = NULL;
     this->inst = NULL;
+	this->tinst = NULL;
     this->argsym = NULL;
     this->aliasdecl = NULL;
     this->semanticdone = 0;
@@ -3225,6 +3226,7 @@
     this->tiargs = tiargs;
     this->tempdecl = td;
     this->inst = NULL;
+	this->tinst = NULL;
     this->argsym = NULL;
     this->aliasdecl = NULL;
     this->semanticdone = 0;
@@ -3293,6 +3295,9 @@
 	return;
     }
 
+    // get the enclosing template instance from the scope tinst
+    tinst = sc->tinst;
+
     if (semanticdone != 0)
     {
 	error(loc, "recursive template expansion");
@@ -3513,6 +3518,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 WINDOWS_SEH
   __try
@@ -3577,6 +3583,8 @@
     if (global.errors != errorsave)
     {
 	error("error instantiating");
+	if (tinst)
+	    tinst->printInstantiationTrace();
 	errors = 1;
 	if (global.gag)
 	    tempdecl->instances.remove(tempdecl_instance_idx);
@@ -4161,6 +4169,8 @@
 	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];
@@ -4191,6 +4201,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];
@@ -4201,6 +4212,87 @@
     }
 }
 
+bool sameLocation(Loc a, Loc b)
+{
+	if (a.linnum != b.linnum) return false;
+	if (a.filename && b.filename) {
+		return !strcmp(a.filename, b.filename);
+	}
+	return false;
+}
+
+void TemplateInstance::printInstantiationTrace()
+{
+    if(global.gag)
+	return;
+
+    const int max_shown = 6;
+
+    // determine instantiation depth and number of recursive instantiations
+    int n_instantiations = 1;
+	int n_totalrecursions = 0;
+    TemplateInstance* cur = this;
+	while(cur) {
+	++n_instantiations;
+	// If two instantiations use the same declaration, they are recursive.
+	// (this works even if they are instantiated from different places in the
+	// same template).
+	// In principle, we could also check for multiple-template recursion, but it's
+	// probably not worthwhile.
+	if (cur->tinst && cur->tempdecl && cur->tinst->tempdecl
+			&& sameLocation(cur->tempdecl->loc, cur->tinst->tempdecl->loc))
+			++n_totalrecursions;
+	cur = cur->tinst;
+	}
+
+    // 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,"%s:        instantiatied from here: %s\n", cur->loc.toChars(), cur->toChars());
+	    cur = cur->tinst;
+	}
+    }
+	else if (n_instantiations-n_totalrecursions <= max_shown)
+	{
+		// By collapsing recursive instantiations into a single line, we can stay under
+		// the limit.
+	cur = this;
+	int recursionDepth=0;
+	while (cur) {	    
+		if (cur->tinst && cur->tempdecl && cur->tinst->tempdecl
+			&& sameLocation(cur->tempdecl->loc, cur->tinst->tempdecl->loc)) {
+				++recursionDepth;
+			} else {
+				if (recursionDepth)
+					fprintf(stdmsg,"%s:        %d recursive instantiations from here: %s\n", cur->loc.toChars(), recursionDepth+2, cur->toChars());
+				else 
+		            fprintf(stdmsg,"%s:        instantiatied from here: %s\n", cur->loc.toChars(), cur->toChars());
+				recursionDepth = 0;
+			}
+			cur = cur->tinst;
+	}
+	}
+	else
+    {
+		// Even after collapsing the recursions, the depth is too deep.
+		// Just display the first few and last few instantiations.
+	cur = this;
+	size_t i = 0;
+	for(; i < max_shown/2; ++i, cur = cur->tinst) {
+		fprintf(stdmsg,"%s:        instantiatied from here: %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,"%s:        instantiatied from here: %s\n", cur->loc.toChars(), cur->toChars());
+    }
+}
+
+
 void TemplateInstance::toObjFile(int multiobj)
 {
 #if LOG
Index: template.h
===================================================================
--- template.h	(revision 22)
+++ template.h	(working copy)
@@ -268,6 +268,7 @@
 
     TemplateDeclaration *tempdecl;	// referenced by foo.bar.abc
     TemplateInstance *inst;		// refer to existing instance
+	TemplateInstance *tinst;    // enclosing template instance
     ScopeDsymbol *argsym;		// argument symbol table
     AliasDeclaration *aliasdecl;	// !=NULL if instance is an alias for its
 					// sole member
@@ -299,6 +300,7 @@
     int oneMember(Dsymbol **ps);
     char *toChars();
     char *mangle();
+	void printInstantiationTrace();
 
     void toObjFile(int multiobj);			// compile to .obj file
 
