]> granicus.if.org Git - clang/commitdiff
PR9793: Treat substitution as an instantiation step for the purpose of the
authorRichard Smith <richard-llvm@metafoo.co.uk>
Sun, 8 Jul 2012 02:38:24 +0000 (02:38 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Sun, 8 Jul 2012 02:38:24 +0000 (02:38 +0000)
-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

lib/Sema/SemaExpr.cpp
lib/Sema/SemaTemplate.cpp
lib/Sema/SemaTemplateInstantiate.cpp
lib/Sema/SemaTemplateInstantiateDecl.cpp
test/SemaTemplate/instantiation-depth-defarg.cpp [new file with mode: 0644]
test/SemaTemplate/instantiation-depth-subst-2.cpp [new file with mode: 0644]
test/SemaTemplate/instantiation-depth-subst.cpp [new file with mode: 0644]

index cfc55e5715c061e39613b9901902201274f6367a..6dbf70476582e5a8f04fa741cfcfb484267e25f5 100644 (file)
@@ -3383,6 +3383,8 @@ ExprResult Sema::BuildCXXDefaultArgExpr(SourceLocation CallLoc,
       = ArgList.getInnermost();
     InstantiatingTemplate Inst(*this, CallLoc, Param, Innermost.first,
                                Innermost.second);
+    if (Inst)
+      return ExprError();
 
     ExprResult Result;
     {
index 77695c199d5f1879a8bf388936b6af652ee1272c..4605e01fa25433a3bcd8e5b23ac302e8260d57e7 100644 (file)
@@ -1990,6 +1990,8 @@ QualType Sema::CheckTemplateIdType(TemplateName Name,
       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 @@ SubstDefaultTemplateArgument(Sema &SemaRef,
                                      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 @@ SubstDefaultTemplateArgument(Sema &SemaRef,
                                    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 @@ SubstDefaultTemplateArgument(Sema &SemaRef,
                                    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 @@ bool Sema::CheckTemplateArgument(NamedDecl *Param,
       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 @@ bool Sema::CheckTemplateArgument(NamedDecl *Param,
     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 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,
     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,
index 8973916f371102bf09ec828e2ea560da11a0ddf6..7416d1230178e0387e01bd857193a43aa00b1305 100644 (file)
@@ -156,11 +156,11 @@ bool Sema::ActiveTemplateInstantiation::isInstantiationRecord() const {
   case ExceptionSpecInstantiation:
   case DefaultTemplateArgumentInstantiation:
   case DefaultFunctionArgumentInstantiation:
-    return true;
-      
   case ExplicitTemplateArgumentSubstitution:
   case DeducedTemplateArgumentSubstitution:
   case PriorTemplateArgumentSubstitution:
+    return true;
+
   case DefaultTemplateArgumentChecking:
     return false;
   }
@@ -252,8 +252,7 @@ Sema::InstantiatingTemplate::InstantiatingTemplate(Sema &SemaRef,
     SavedInNonInstantiationSFINAEContext(
                                      SemaRef.InNonInstantiationSFINAEContext)
 {
-  Invalid = CheckInstantiationDepth(PointOfInstantiation,
-                                    InstantiationRange);
+  Invalid = CheckInstantiationDepth(PointOfInstantiation, InstantiationRange);
   if (!Invalid) {
     ActiveTemplateInstantiation Inst;
     Inst.Kind = Kind;
@@ -282,21 +281,19 @@ Sema::InstantiatingTemplate::InstantiatingTemplate(Sema &SemaRef,
     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 @@ Sema::InstantiatingTemplate::InstantiatingTemplate(Sema &SemaRef,
                                      SemaRef.InNonInstantiationSFINAEContext)
 {
   Invalid = CheckInstantiationDepth(PointOfInstantiation, InstantiationRange);
-
   if (!Invalid) {
     ActiveTemplateInstantiation Inst;
     Inst.Kind
@@ -336,21 +332,19 @@ InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
     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 @@ InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
     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::
index bbf8f50a3c774b2c53933064a812e355c0420c25..cce0b0d0930a6a30ded40065b1ed125c7cb46979 100644 (file)
@@ -2446,7 +2446,6 @@ TemplateDeclInstantiator::InitFunctionInstantiation(FunctionDecl *New,
       (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 (file)
index 0000000..d66c71b
--- /dev/null
@@ -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 (file)
index 0000000..a29d6b5
--- /dev/null
@@ -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 (file)
index 0000000..58e6374
--- /dev/null
@@ -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'}}