Skip to content

Commit 5721c68

Browse files
mizvekovmahesh-attarde
authored andcommitted
[clang] fix code synthesis context depth limit logic (llvm#161103)
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.
1 parent 013fce1 commit 5721c68

File tree

6 files changed

+52
-53
lines changed

6 files changed

+52
-53
lines changed

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5770,8 +5770,10 @@ def err_template_recursion_depth_exceeded : Error<
57705770
def err_constraint_depends_on_self
57715771
: Error<"satisfaction of constraint %0 depends on itself">,
57725772
NoSFINAE;
5773-
def note_template_recursion_depth : Note<
5774-
"use -ftemplate-depth=N to increase recursive template instantiation depth">;
5773+
def note_template_recursion_depth
5774+
: Note<"use -ftemplate-depth=N to increase recursive template "
5775+
"instantiation depth">,
5776+
NoSFINAE;
57755777

57765778
def err_template_instantiate_within_definition : Error<
57775779
"%select{implicit|explicit}0 instantiation of template %1 within its"

clang/include/clang/Sema/Sema.h

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13335,8 +13335,6 @@ class Sema final : public SemaBase {
1333513335
Sema &SemaRef;
1333613336
bool Invalid;
1333713337
bool AlreadyInstantiating;
13338-
bool CheckInstantiationDepth(SourceLocation PointOfInstantiation,
13339-
SourceRange InstantiationRange);
1334013338

1334113339
InstantiatingTemplate(Sema &SemaRef,
1334213340
CodeSynthesisContext::SynthesisKind Kind,
@@ -13529,7 +13527,7 @@ class Sema final : public SemaBase {
1352913527
~ArgPackSubstIndexRAII() { Self.ArgPackSubstIndex = OldSubstIndex; }
1353013528
};
1353113529

13532-
void pushCodeSynthesisContext(CodeSynthesisContext Ctx);
13530+
bool pushCodeSynthesisContext(CodeSynthesisContext Ctx);
1353313531
void popCodeSynthesisContext();
1353413532

1353513533
void PrintContextStack(InstantiationContextDiagFuncRef DiagFunc) {

clang/lib/Sema/SemaTemplateInstantiate.cpp

Lines changed: 43 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -616,29 +616,30 @@ Sema::InstantiatingTemplate::InstantiatingTemplate(
616616
Invalid = true;
617617
return;
618618
}
619-
Invalid = CheckInstantiationDepth(PointOfInstantiation, InstantiationRange);
619+
620+
CodeSynthesisContext Inst;
621+
Inst.Kind = Kind;
622+
Inst.PointOfInstantiation = PointOfInstantiation;
623+
Inst.Entity = Entity;
624+
Inst.Template = Template;
625+
Inst.TemplateArgs = TemplateArgs.data();
626+
Inst.NumTemplateArgs = TemplateArgs.size();
627+
Inst.DeductionInfo = DeductionInfo;
628+
Inst.InstantiationRange = InstantiationRange;
629+
Inst.InConstraintSubstitution =
630+
Inst.Kind == CodeSynthesisContext::ConstraintSubstitution;
631+
if (!SemaRef.CodeSynthesisContexts.empty())
632+
Inst.InConstraintSubstitution |=
633+
SemaRef.CodeSynthesisContexts.back().InConstraintSubstitution;
634+
635+
Invalid = SemaRef.pushCodeSynthesisContext(Inst);
620636
if (!Invalid) {
621-
CodeSynthesisContext Inst;
622-
Inst.Kind = Kind;
623-
Inst.PointOfInstantiation = PointOfInstantiation;
624-
Inst.Entity = Entity;
625-
Inst.Template = Template;
626-
Inst.TemplateArgs = TemplateArgs.data();
627-
Inst.NumTemplateArgs = TemplateArgs.size();
628-
Inst.DeductionInfo = DeductionInfo;
629-
Inst.InstantiationRange = InstantiationRange;
630-
Inst.InConstraintSubstitution =
631-
Inst.Kind == CodeSynthesisContext::ConstraintSubstitution;
632-
if (!SemaRef.CodeSynthesisContexts.empty())
633-
Inst.InConstraintSubstitution |=
634-
SemaRef.CodeSynthesisContexts.back().InConstraintSubstitution;
635-
636-
SemaRef.pushCodeSynthesisContext(Inst);
637-
638-
AlreadyInstantiating = !Inst.Entity ? false :
639-
!SemaRef.InstantiatingSpecializations
640-
.insert({Inst.Entity->getCanonicalDecl(), Inst.Kind})
641-
.second;
637+
AlreadyInstantiating =
638+
!Inst.Entity
639+
? false
640+
: !SemaRef.InstantiatingSpecializations
641+
.insert({Inst.Entity->getCanonicalDecl(), Inst.Kind})
642+
.second;
642643
atTemplateBegin(SemaRef.TemplateInstCallbacks, SemaRef, Inst);
643644
}
644645
}
@@ -834,18 +835,34 @@ Sema::InstantiatingTemplate::InstantiatingTemplate(
834835
: InstantiatingTemplate(SemaRef, CodeSynthesisContext::PartialOrderingTTP,
835836
ArgLoc, InstantiationRange, PArg) {}
836837

837-
void Sema::pushCodeSynthesisContext(CodeSynthesisContext Ctx) {
838+
bool Sema::pushCodeSynthesisContext(CodeSynthesisContext Ctx) {
838839
Ctx.SavedInNonInstantiationSFINAEContext = InNonInstantiationSFINAEContext;
839840
InNonInstantiationSFINAEContext = false;
840841

841-
CodeSynthesisContexts.push_back(Ctx);
842-
843-
if (!Ctx.isInstantiationRecord())
842+
if (!Ctx.isInstantiationRecord()) {
844843
++NonInstantiationEntries;
844+
} else {
845+
assert(SemaRef.NonInstantiationEntries <=
846+
SemaRef.CodeSynthesisContexts.size());
847+
if ((SemaRef.CodeSynthesisContexts.size() -
848+
SemaRef.NonInstantiationEntries) >
849+
SemaRef.getLangOpts().InstantiationDepth) {
850+
SemaRef.Diag(Ctx.PointOfInstantiation,
851+
diag::err_template_recursion_depth_exceeded)
852+
<< SemaRef.getLangOpts().InstantiationDepth << Ctx.InstantiationRange;
853+
SemaRef.Diag(Ctx.PointOfInstantiation,
854+
diag::note_template_recursion_depth)
855+
<< SemaRef.getLangOpts().InstantiationDepth;
856+
return true;
857+
}
858+
}
859+
860+
CodeSynthesisContexts.push_back(Ctx);
845861

846862
// Check to see if we're low on stack space. We can't do anything about this
847863
// from here, but we can at least warn the user.
848864
StackHandler.warnOnStackNearlyExhausted(Ctx.PointOfInstantiation);
865+
return false;
849866
}
850867

851868
void Sema::popCodeSynthesisContext() {
@@ -907,25 +924,6 @@ static std::string convertCallArgsToString(Sema &S,
907924
return Result;
908925
}
909926

910-
bool Sema::InstantiatingTemplate::CheckInstantiationDepth(
911-
SourceLocation PointOfInstantiation,
912-
SourceRange InstantiationRange) {
913-
assert(SemaRef.NonInstantiationEntries <=
914-
SemaRef.CodeSynthesisContexts.size());
915-
if ((SemaRef.CodeSynthesisContexts.size() -
916-
SemaRef.NonInstantiationEntries)
917-
<= SemaRef.getLangOpts().InstantiationDepth)
918-
return false;
919-
920-
SemaRef.Diag(PointOfInstantiation,
921-
diag::err_template_recursion_depth_exceeded)
922-
<< SemaRef.getLangOpts().InstantiationDepth
923-
<< InstantiationRange;
924-
SemaRef.Diag(PointOfInstantiation, diag::note_template_recursion_depth)
925-
<< SemaRef.getLangOpts().InstantiationDepth;
926-
return true;
927-
}
928-
929927
void Sema::PrintInstantiationStack(InstantiationContextDiagFuncRef DiagFunc) {
930928
// Determine which template instantiations to skip, if any.
931929
unsigned SkipStart = CodeSynthesisContexts.size(), SkipEnd = SkipStart;

clang/test/SemaCXX/invalid-requirement-requires-expr.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,7 @@ constexpr bool A<x>::far() {
1717
b.data_member;
1818
requires A<x-1>::far(); // #Invalid
1919
// expected-error@#Invalid {{recursive template instantiation exceeded maximum depth}}
20-
// expected-note@#Invalid {{in instantiation}}
21-
// expected-note@#Invalid 2 {{while}}
20+
// expected-note@#Invalid 3 {{while}}
2221
// expected-note@#Invalid {{contexts in backtrace}}
2322
// expected-note@#Invalid {{increase recursive template instantiation depth}}
2423
};

clang/test/SemaTemplate/instantiation-depth-subst-2.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,6 @@
22

33
template<int N> struct S { };
44
template<typename T> S<T() + T()> operator+(T, T); // expected-error {{instantiation exceeded maximum depth}} expected-note 2{{while substituting}}
5+
// expected-note@-1 {{use -ftemplate-depth=N to increase recursive template instantiation depth}}
56
S<0> s;
67
int k = s + s; // expected-note {{while substituting}}

clang/test/SemaTemplate/instantiation-depth-subst.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@
33
// PR9793
44
template<typename T> auto f(T t) -> decltype(f(t)); // \
55
// expected-error {{recursive template instantiation exceeded maximum depth of 2}} \
6-
// expected-note 2 {{while substituting}}
6+
// expected-note 2 {{while substituting}} \
7+
// expected-note {{use -ftemplate-depth=N to increase recursive template instantiation depth}}
78

89
struct S {};
910
int k = f(S{}); // expected-note {{while substituting}}

0 commit comments

Comments
 (0)