-
Notifications
You must be signed in to change notification settings - Fork 15.2k
[clang] fix code synthesis context depth limit logic #161103
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[clang] fix code synthesis context depth limit logic #161103
Conversation
This makes the instantation depth limit be checked whenever the code synthesis context is pushed, not only when creating a InstantiatingTemplate RAII object. Also fix the note suggesting the user increases `-ftemplate-depth` so it is printed even in a SFINAE context.
@llvm/pr-subscribers-clang Author: Matheus Izvekov (mizvekov) ChangesThis makes the instantation depth limit be checked whenever the code synthesis context is pushed, not only when creating a InstantiatingTemplate RAII object. Also fix the note suggesting the user increases Full diff: https://github.com/llvm/llvm-project/pull/161103.diff 6 Files Affected:
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index dc4c6d3de27c1..fa202fba29370 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -5770,8 +5770,10 @@ def err_template_recursion_depth_exceeded : Error<
def err_constraint_depends_on_self
: Error<"satisfaction of constraint %0 depends on itself">,
NoSFINAE;
-def note_template_recursion_depth : Note<
- "use -ftemplate-depth=N to increase recursive template instantiation depth">;
+def note_template_recursion_depth
+ : Note<"use -ftemplate-depth=N to increase recursive template "
+ "instantiation depth">,
+ NoSFINAE;
def err_template_instantiate_within_definition : Error<
"%select{implicit|explicit}0 instantiation of template %1 within its"
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 2bd6be2a32cd5..f53aafdeb4f36 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -13335,8 +13335,6 @@ class Sema final : public SemaBase {
Sema &SemaRef;
bool Invalid;
bool AlreadyInstantiating;
- bool CheckInstantiationDepth(SourceLocation PointOfInstantiation,
- SourceRange InstantiationRange);
InstantiatingTemplate(Sema &SemaRef,
CodeSynthesisContext::SynthesisKind Kind,
@@ -13529,7 +13527,7 @@ class Sema final : public SemaBase {
~ArgPackSubstIndexRAII() { Self.ArgPackSubstIndex = OldSubstIndex; }
};
- void pushCodeSynthesisContext(CodeSynthesisContext Ctx);
+ bool pushCodeSynthesisContext(CodeSynthesisContext Ctx);
void popCodeSynthesisContext();
void PrintContextStack(InstantiationContextDiagFuncRef DiagFunc) {
diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp
index 1ff94d7ae397f..f1c9c5c868159 100644
--- a/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -616,29 +616,30 @@ Sema::InstantiatingTemplate::InstantiatingTemplate(
Invalid = true;
return;
}
- Invalid = CheckInstantiationDepth(PointOfInstantiation, InstantiationRange);
+
+ CodeSynthesisContext Inst;
+ Inst.Kind = Kind;
+ Inst.PointOfInstantiation = PointOfInstantiation;
+ Inst.Entity = Entity;
+ Inst.Template = Template;
+ Inst.TemplateArgs = TemplateArgs.data();
+ Inst.NumTemplateArgs = TemplateArgs.size();
+ Inst.DeductionInfo = DeductionInfo;
+ Inst.InstantiationRange = InstantiationRange;
+ Inst.InConstraintSubstitution =
+ Inst.Kind == CodeSynthesisContext::ConstraintSubstitution;
+ if (!SemaRef.CodeSynthesisContexts.empty())
+ Inst.InConstraintSubstitution |=
+ SemaRef.CodeSynthesisContexts.back().InConstraintSubstitution;
+
+ Invalid = SemaRef.pushCodeSynthesisContext(Inst);
if (!Invalid) {
- CodeSynthesisContext Inst;
- Inst.Kind = Kind;
- Inst.PointOfInstantiation = PointOfInstantiation;
- Inst.Entity = Entity;
- Inst.Template = Template;
- Inst.TemplateArgs = TemplateArgs.data();
- Inst.NumTemplateArgs = TemplateArgs.size();
- Inst.DeductionInfo = DeductionInfo;
- Inst.InstantiationRange = InstantiationRange;
- Inst.InConstraintSubstitution =
- Inst.Kind == CodeSynthesisContext::ConstraintSubstitution;
- if (!SemaRef.CodeSynthesisContexts.empty())
- Inst.InConstraintSubstitution |=
- SemaRef.CodeSynthesisContexts.back().InConstraintSubstitution;
-
- SemaRef.pushCodeSynthesisContext(Inst);
-
- AlreadyInstantiating = !Inst.Entity ? false :
- !SemaRef.InstantiatingSpecializations
- .insert({Inst.Entity->getCanonicalDecl(), Inst.Kind})
- .second;
+ AlreadyInstantiating =
+ !Inst.Entity
+ ? false
+ : !SemaRef.InstantiatingSpecializations
+ .insert({Inst.Entity->getCanonicalDecl(), Inst.Kind})
+ .second;
atTemplateBegin(SemaRef.TemplateInstCallbacks, SemaRef, Inst);
}
}
@@ -834,18 +835,34 @@ Sema::InstantiatingTemplate::InstantiatingTemplate(
: InstantiatingTemplate(SemaRef, CodeSynthesisContext::PartialOrderingTTP,
ArgLoc, InstantiationRange, PArg) {}
-void Sema::pushCodeSynthesisContext(CodeSynthesisContext Ctx) {
+bool Sema::pushCodeSynthesisContext(CodeSynthesisContext Ctx) {
Ctx.SavedInNonInstantiationSFINAEContext = InNonInstantiationSFINAEContext;
InNonInstantiationSFINAEContext = false;
- CodeSynthesisContexts.push_back(Ctx);
-
- if (!Ctx.isInstantiationRecord())
+ if (!Ctx.isInstantiationRecord()) {
++NonInstantiationEntries;
+ } else {
+ assert(SemaRef.NonInstantiationEntries <=
+ SemaRef.CodeSynthesisContexts.size());
+ if ((SemaRef.CodeSynthesisContexts.size() -
+ SemaRef.NonInstantiationEntries) >
+ SemaRef.getLangOpts().InstantiationDepth) {
+ SemaRef.Diag(Ctx.PointOfInstantiation,
+ diag::err_template_recursion_depth_exceeded)
+ << SemaRef.getLangOpts().InstantiationDepth << Ctx.InstantiationRange;
+ SemaRef.Diag(Ctx.PointOfInstantiation,
+ diag::note_template_recursion_depth)
+ << SemaRef.getLangOpts().InstantiationDepth;
+ return true;
+ }
+ }
+
+ CodeSynthesisContexts.push_back(Ctx);
// Check to see if we're low on stack space. We can't do anything about this
// from here, but we can at least warn the user.
StackHandler.warnOnStackNearlyExhausted(Ctx.PointOfInstantiation);
+ return false;
}
void Sema::popCodeSynthesisContext() {
@@ -907,25 +924,6 @@ static std::string convertCallArgsToString(Sema &S,
return Result;
}
-bool Sema::InstantiatingTemplate::CheckInstantiationDepth(
- SourceLocation PointOfInstantiation,
- SourceRange InstantiationRange) {
- assert(SemaRef.NonInstantiationEntries <=
- SemaRef.CodeSynthesisContexts.size());
- if ((SemaRef.CodeSynthesisContexts.size() -
- SemaRef.NonInstantiationEntries)
- <= SemaRef.getLangOpts().InstantiationDepth)
- return false;
-
- SemaRef.Diag(PointOfInstantiation,
- diag::err_template_recursion_depth_exceeded)
- << SemaRef.getLangOpts().InstantiationDepth
- << InstantiationRange;
- SemaRef.Diag(PointOfInstantiation, diag::note_template_recursion_depth)
- << SemaRef.getLangOpts().InstantiationDepth;
- return true;
-}
-
void Sema::PrintInstantiationStack(InstantiationContextDiagFuncRef DiagFunc) {
// Determine which template instantiations to skip, if any.
unsigned SkipStart = CodeSynthesisContexts.size(), SkipEnd = SkipStart;
diff --git a/clang/test/SemaCXX/invalid-requirement-requires-expr.cpp b/clang/test/SemaCXX/invalid-requirement-requires-expr.cpp
index 097ada3caa135..436dfb9aac0a7 100644
--- a/clang/test/SemaCXX/invalid-requirement-requires-expr.cpp
+++ b/clang/test/SemaCXX/invalid-requirement-requires-expr.cpp
@@ -17,8 +17,7 @@ constexpr bool A<x>::far() {
b.data_member;
requires A<x-1>::far(); // #Invalid
// expected-error@#Invalid {{recursive template instantiation exceeded maximum depth}}
- // expected-note@#Invalid {{in instantiation}}
- // expected-note@#Invalid 2 {{while}}
+ // expected-note@#Invalid 3 {{while}}
// expected-note@#Invalid {{contexts in backtrace}}
// expected-note@#Invalid {{increase recursive template instantiation depth}}
};
diff --git a/clang/test/SemaTemplate/instantiation-depth-subst-2.cpp b/clang/test/SemaTemplate/instantiation-depth-subst-2.cpp
index 2b519e974a907..66fd1af0d1429 100644
--- a/clang/test/SemaTemplate/instantiation-depth-subst-2.cpp
+++ b/clang/test/SemaTemplate/instantiation-depth-subst-2.cpp
@@ -2,5 +2,6 @@
template<int N> struct S { };
template<typename T> S<T() + T()> operator+(T, T); // expected-error {{instantiation exceeded maximum depth}} expected-note 2{{while substituting}}
+// expected-note@-1 {{use -ftemplate-depth=N to increase recursive template instantiation depth}}
S<0> s;
int k = s + s; // expected-note {{while substituting}}
diff --git a/clang/test/SemaTemplate/instantiation-depth-subst.cpp b/clang/test/SemaTemplate/instantiation-depth-subst.cpp
index 062a8ed08bb64..17944bc3aaa40 100644
--- a/clang/test/SemaTemplate/instantiation-depth-subst.cpp
+++ b/clang/test/SemaTemplate/instantiation-depth-subst.cpp
@@ -3,7 +3,8 @@
// PR9793
template<typename T> auto f(T t) -> decltype(f(t)); // \
// expected-error {{recursive template instantiation exceeded maximum depth of 2}} \
-// expected-note 2 {{while substituting}}
+// expected-note 2 {{while substituting}} \
+// expected-note {{use -ftemplate-depth=N to increase recursive template instantiation depth}}
struct S {};
int k = f(S{}); // expected-note {{while substituting}}
|
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/163/builds/27261 Here is the relevant piece of the build log for the reference
|
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/27/builds/16727 Here is the relevant piece of the build log for the reference
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems reasonable, 1 nit, else i'm ok with this.
} | ||
Invalid = CheckInstantiationDepth(PointOfInstantiation, InstantiationRange); | ||
|
||
CodeSynthesisContext Inst; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems in desperate need of a constructor here :)
This makes the instantation depth limit be checked whenever the code synthesis context is pushed, not only when creating a InstantiatingTemplate RAII object. Also fix the note suggesting the user increases `-ftemplate-depth` so it is printed even in a SFINAE context.
This makes the instantation depth limit be checked whenever the code synthesis context is pushed, not only when creating a InstantiatingTemplate RAII object.
Also fix the note suggesting the user increases
-ftemplate-depth
so it is printed even in a SFINAE context.