PR9793: Treat substitution as an instantiation step for the purpose of the
-ftemplate-depth limit.  There are various ways to get an infinite (or merely
huge) stack of substitutions with no intervening instantiations. This is also
consistent with gcc's behavior.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@159907 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index cfc55e5..6dbf704 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -3383,6 +3383,8 @@
       = ArgList.getInnermost();
     InstantiatingTemplate Inst(*this, CallLoc, Param, Innermost.first,
                                Innermost.second);
+    if (Inst)
+      return ExprError();
 
     ExprResult Result;
     {
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp
index 77695c1..4605e01 100644
--- a/lib/Sema/SemaTemplate.cpp
+++ b/lib/Sema/SemaTemplate.cpp
@@ -1990,6 +1990,8 @@
       TemplateArgLists.addOuterTemplateArguments(0, 0);
 
     InstantiatingTemplate Inst(*this, TemplateLoc, Template);
+    if (Inst)
+      return QualType();
     CanonType = SubstType(Pattern->getUnderlyingType(),
                           TemplateArgLists, AliasTemplate->getLocation(),
                           AliasTemplate->getDeclName());
@@ -2550,6 +2552,8 @@
                                      Template, Converted.data(),
                                      Converted.size(),
                                      SourceRange(TemplateLoc, RAngleLoc));
+    if (Inst)
+      return 0;
 
     Sema::ContextRAII SavedContext(SemaRef, Template->getDeclContext());
     ArgType = SemaRef.SubstType(ArgType, AllTemplateArgs,
@@ -2599,6 +2603,8 @@
                                    Template, Converted.data(),
                                    Converted.size(),
                                    SourceRange(TemplateLoc, RAngleLoc));
+  if (Inst)
+    return ExprError();
 
   Sema::ContextRAII SavedContext(SemaRef, Template->getDeclContext());
   EnterExpressionEvaluationContext Unevaluated(SemaRef, Sema::Unevaluated);
@@ -2648,6 +2654,8 @@
                                    Template, Converted.data(),
                                    Converted.size(),
                                    SourceRange(TemplateLoc, RAngleLoc));
+  if (Inst)
+    return TemplateName();
 
   Sema::ContextRAII SavedContext(SemaRef, Template->getDeclContext());
   // Substitute into the nested-name-specifier first, 
@@ -2781,6 +2789,8 @@
       InstantiatingTemplate Inst(*this, TemplateLoc, Template,
                                  NTTP, Converted.data(), Converted.size(),
                                  SourceRange(TemplateLoc, RAngleLoc));
+      if (Inst)
+        return true;
 
       TemplateArgumentList TemplateArgs(TemplateArgumentList::OnStack,
                                         Converted.data(), Converted.size());
@@ -2913,6 +2923,8 @@
     InstantiatingTemplate Inst(*this, TemplateLoc, Template,
                                TempParm, Converted.data(), Converted.size(),
                                SourceRange(TemplateLoc, RAngleLoc));
+    if (Inst)
+      return true;
 
     TemplateArgumentList TemplateArgs(TemplateArgumentList::OnStack,
                                       Converted.data(), Converted.size());
@@ -3144,6 +3156,8 @@
     InstantiatingTemplate Instantiating(*this, RAngleLoc, Template, *Param,
                                         Converted.data(), Converted.size(),
                                         SourceRange(TemplateLoc, RAngleLoc));
+    if (Instantiating)
+      return true;
 
     // Check the default template argument.
     if (CheckTemplateArgument(*Param, Arg, Template, TemplateLoc,
diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp
index 8973916..7416d12 100644
--- a/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/lib/Sema/SemaTemplateInstantiate.cpp
@@ -156,11 +156,11 @@
   case ExceptionSpecInstantiation:
   case DefaultTemplateArgumentInstantiation:
   case DefaultFunctionArgumentInstantiation:
-    return true;
-      
   case ExplicitTemplateArgumentSubstitution:
   case DeducedTemplateArgumentSubstitution:
   case PriorTemplateArgumentSubstitution:
+    return true;
+
   case DefaultTemplateArgumentChecking:
     return false;
   }
@@ -252,8 +252,7 @@
     SavedInNonInstantiationSFINAEContext(
                                      SemaRef.InNonInstantiationSFINAEContext)
 {
-  Invalid = CheckInstantiationDepth(PointOfInstantiation,
-                                    InstantiationRange);
+  Invalid = CheckInstantiationDepth(PointOfInstantiation, InstantiationRange);
   if (!Invalid) {
     ActiveTemplateInstantiation Inst;
     Inst.Kind = Kind;
@@ -282,21 +281,19 @@
     SavedInNonInstantiationSFINAEContext(
                                      SemaRef.InNonInstantiationSFINAEContext)
 {
-  Invalid = false;
-    
-  ActiveTemplateInstantiation Inst;
-  Inst.Kind = ActiveTemplateInstantiation::DeducedTemplateArgumentSubstitution;
-  Inst.PointOfInstantiation = PointOfInstantiation;
-  Inst.Entity = reinterpret_cast<uintptr_t>(PartialSpec);
-  Inst.TemplateArgs = TemplateArgs;
-  Inst.NumTemplateArgs = NumTemplateArgs;
-  Inst.DeductionInfo = &DeductionInfo;
-  Inst.InstantiationRange = InstantiationRange;
-  SemaRef.InNonInstantiationSFINAEContext = false;
-  SemaRef.ActiveTemplateInstantiations.push_back(Inst);
-      
-  assert(!Inst.isInstantiationRecord());
-  ++SemaRef.NonInstantiationEntries;
+  Invalid = CheckInstantiationDepth(PointOfInstantiation, InstantiationRange);
+  if (!Invalid) {
+    ActiveTemplateInstantiation Inst;
+    Inst.Kind = ActiveTemplateInstantiation::DeducedTemplateArgumentSubstitution;
+    Inst.PointOfInstantiation = PointOfInstantiation;
+    Inst.Entity = reinterpret_cast<uintptr_t>(PartialSpec);
+    Inst.TemplateArgs = TemplateArgs;
+    Inst.NumTemplateArgs = NumTemplateArgs;
+    Inst.DeductionInfo = &DeductionInfo;
+    Inst.InstantiationRange = InstantiationRange;
+    SemaRef.InNonInstantiationSFINAEContext = false;
+    SemaRef.ActiveTemplateInstantiations.push_back(Inst);
+  }
 }
 
 Sema::InstantiatingTemplate::InstantiatingTemplate(Sema &SemaRef,
@@ -310,7 +307,6 @@
                                      SemaRef.InNonInstantiationSFINAEContext)
 {
   Invalid = CheckInstantiationDepth(PointOfInstantiation, InstantiationRange);
-
   if (!Invalid) {
     ActiveTemplateInstantiation Inst;
     Inst.Kind
@@ -336,21 +332,19 @@
     SavedInNonInstantiationSFINAEContext(
                                      SemaRef.InNonInstantiationSFINAEContext)
 {
-  Invalid = false;
-  
-  ActiveTemplateInstantiation Inst;
-  Inst.Kind = ActiveTemplateInstantiation::PriorTemplateArgumentSubstitution;
-  Inst.PointOfInstantiation = PointOfInstantiation;
-  Inst.Template = Template;
-  Inst.Entity = reinterpret_cast<uintptr_t>(Param);
-  Inst.TemplateArgs = TemplateArgs;
-  Inst.NumTemplateArgs = NumTemplateArgs;
-  Inst.InstantiationRange = InstantiationRange;
-  SemaRef.InNonInstantiationSFINAEContext = false;
-  SemaRef.ActiveTemplateInstantiations.push_back(Inst);
-  
-  assert(!Inst.isInstantiationRecord());
-  ++SemaRef.NonInstantiationEntries;
+  Invalid = CheckInstantiationDepth(PointOfInstantiation, InstantiationRange);
+  if (!Invalid) {
+    ActiveTemplateInstantiation Inst;
+    Inst.Kind = ActiveTemplateInstantiation::PriorTemplateArgumentSubstitution;
+    Inst.PointOfInstantiation = PointOfInstantiation;
+    Inst.Template = Template;
+    Inst.Entity = reinterpret_cast<uintptr_t>(Param);
+    Inst.TemplateArgs = TemplateArgs;
+    Inst.NumTemplateArgs = NumTemplateArgs;
+    Inst.InstantiationRange = InstantiationRange;
+    SemaRef.InNonInstantiationSFINAEContext = false;
+    SemaRef.ActiveTemplateInstantiations.push_back(Inst);
+  }
 }
 
 Sema::InstantiatingTemplate::
@@ -364,20 +358,19 @@
     SavedInNonInstantiationSFINAEContext(
                                      SemaRef.InNonInstantiationSFINAEContext)
 {
-  Invalid = false;
-  ActiveTemplateInstantiation Inst;
-  Inst.Kind = ActiveTemplateInstantiation::PriorTemplateArgumentSubstitution;
-  Inst.PointOfInstantiation = PointOfInstantiation;
-  Inst.Template = Template;
-  Inst.Entity = reinterpret_cast<uintptr_t>(Param);
-  Inst.TemplateArgs = TemplateArgs;
-  Inst.NumTemplateArgs = NumTemplateArgs;
-  Inst.InstantiationRange = InstantiationRange;
-  SemaRef.InNonInstantiationSFINAEContext = false;
-  SemaRef.ActiveTemplateInstantiations.push_back(Inst);
-  
-  assert(!Inst.isInstantiationRecord());
-  ++SemaRef.NonInstantiationEntries;
+  Invalid = CheckInstantiationDepth(PointOfInstantiation, InstantiationRange);
+  if (!Invalid) {
+    ActiveTemplateInstantiation Inst;
+    Inst.Kind = ActiveTemplateInstantiation::PriorTemplateArgumentSubstitution;
+    Inst.PointOfInstantiation = PointOfInstantiation;
+    Inst.Template = Template;
+    Inst.Entity = reinterpret_cast<uintptr_t>(Param);
+    Inst.TemplateArgs = TemplateArgs;
+    Inst.NumTemplateArgs = NumTemplateArgs;
+    Inst.InstantiationRange = InstantiationRange;
+    SemaRef.InNonInstantiationSFINAEContext = false;
+    SemaRef.ActiveTemplateInstantiations.push_back(Inst);
+  }
 }
 
 Sema::InstantiatingTemplate::
diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp
index bbf8f50..cce0b0d 100644
--- a/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -2446,7 +2446,6 @@
       (void) FunTmpl;
       ActiveInst.Kind = ActiveInstType::TemplateInstantiation;
       ActiveInst.Entity = reinterpret_cast<uintptr_t>(New);
-      --SemaRef.NonInstantiationEntries;
     }
   }
 
diff --git a/test/SemaTemplate/instantiation-depth-defarg.cpp b/test/SemaTemplate/instantiation-depth-defarg.cpp
new file mode 100644
index 0000000..d66c71b
--- /dev/null
+++ b/test/SemaTemplate/instantiation-depth-defarg.cpp
@@ -0,0 +1,28 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -ftemplate-depth 512 -ftemplate-backtrace-limit 4 %s
+
+template<int N> struct S {
+  typedef typename S<N-1>::type type;
+  static int f(int n = S<N-1>::f()); // \
+// expected-error{{recursive template instantiation exceeded maximum depth of 512}} \
+// expected-note 3 {{instantiation of default function argument}} \
+// expected-note {{skipping 509 contexts in backtrace}} \
+// expected-note {{use -ftemplate-depth=N to increase recursive template instantiation depth}}
+
+};
+template<> struct S<0> {
+  typedef int type;
+};
+
+// Incrementally instantiate up to S<2048>.
+template struct S<256>;
+template struct S<512>;
+template struct S<768>;
+template struct S<1024>;
+template struct S<1280>;
+template struct S<1536>;
+template struct S<1792>;
+template struct S<2048>;
+
+// Check that we actually bail out when we hit the instantiation depth limit for
+// the default arguments.
+void g() { S<2048>::f(); } // expected-note {{required here}}
diff --git a/test/SemaTemplate/instantiation-depth-subst-2.cpp b/test/SemaTemplate/instantiation-depth-subst-2.cpp
new file mode 100644
index 0000000..a29d6b5
--- /dev/null
+++ b/test/SemaTemplate/instantiation-depth-subst-2.cpp
@@ -0,0 +1,9 @@
+// RUN: %clang_cc1 -verify %s -ftemplate-depth 2
+
+template<int N> struct S { };
+// FIXME: We produce the same 'instantiation depth' error here many times
+// (2^(depth+1) in total), due to additional lookups performed as part of
+// error recovery in DiagnoseTwoPhaseOperatorLookup.
+template<typename T> S<T() + T()> operator+(T, T); // expected-error 8{{}} expected-note 10{{}}
+S<0> s;
+int k = s + s; // expected-error {{invalid operands to binary expression}}
diff --git a/test/SemaTemplate/instantiation-depth-subst.cpp b/test/SemaTemplate/instantiation-depth-subst.cpp
new file mode 100644
index 0000000..58e6374
--- /dev/null
+++ b/test/SemaTemplate/instantiation-depth-subst.cpp
@@ -0,0 +1,9 @@
+// RUN: %clang_cc1 -std=c++11 -verify %s -ftemplate-depth 2
+
+// PR9793
+template<typename T> auto f(T t) -> decltype(f(t)); // \
+// expected-error {{recursive template instantiation exceeded maximum depth of 2}} \
+// expected-note 3 {{while substituting}} \
+// expected-note {{candidate}}
+
+int k = f(0); // expected-error {{no matching function for call to 'f'}}