Limit the template instantiation depth to some user-configurable value
(default: 99). Beyond this limit, produce an error and consider the
current template instantiation a failure.

The stack we're building to track the instantiations will, eventually,
be used to produce instantiation backtraces from diagnostics within
template instantiation. However, we're not quite there yet.

This adds a new Clang driver option -ftemplate-depth=NNN, which should
eventually be generated from the GCC command-line operation
-ftemplate-depth-NNN (note the '-' rather than the '='!). I did not
make the driver changes to do this mapping.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@66513 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp
index 71bba49..0990057 100644
--- a/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/lib/Sema/SemaTemplateInstantiate.cpp
@@ -21,6 +21,35 @@
 
 using namespace clang;
 
+Sema::InstantiatingTemplate::
+InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
+                      ClassTemplateSpecializationDecl *Entity,
+                      SourceRange InstantiationRange)
+  :  SemaRef(SemaRef) {
+  if (SemaRef.ActiveTemplateInstantiations.size() 
+        > SemaRef.getLangOptions().InstantiationDepth) {
+    SemaRef.Diag(PointOfInstantiation, 
+                 diag::err_template_recursion_depth_exceeded)
+      << SemaRef.getLangOptions().InstantiationDepth
+      << InstantiationRange;
+    SemaRef.Diag(PointOfInstantiation, diag::note_template_recursion_depth)
+      << SemaRef.getLangOptions().InstantiationDepth;
+    Invalid = true;
+  } else {
+    ActiveTemplateInstantiation Inst;
+    Inst.PointOfInstantiation = PointOfInstantiation;
+    Inst.Entity = Entity;
+    Inst.InstantiationRange = InstantiationRange;
+    SemaRef.ActiveTemplateInstantiations.push_back(Inst);
+    Invalid = false;
+  }
+}
+
+Sema::InstantiatingTemplate::~InstantiatingTemplate() {
+  if (!Invalid)
+    SemaRef.ActiveTemplateInstantiations.pop_back();
+}
+
 //===----------------------------------------------------------------------===/
 // Template Instantiation for Types
 //===----------------------------------------------------------------------===/
@@ -526,6 +555,11 @@
 
   bool Invalid = false;
   
+  InstantiatingTemplate Inst(*this, ClassTemplateSpec->getLocation(),
+                             ClassTemplateSpec);
+  if (Inst)
+    return true;
+
   // Enter the scope of this instantiation. We don't use
   // PushDeclContext because we don't have a scope.
   DeclContext *PreviousContext = CurContext;