Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions clang/include/clang/Basic/DiagnosticSemaKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
4 changes: 1 addition & 3 deletions clang/include/clang/Sema/Sema.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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) {
Expand Down
88 changes: 43 additions & 45 deletions clang/lib/Sema/SemaTemplateInstantiate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -616,29 +616,30 @@ Sema::InstantiatingTemplate::InstantiatingTemplate(
Invalid = true;
return;
}
Invalid = CheckInstantiationDepth(PointOfInstantiation, InstantiationRange);

CodeSynthesisContext Inst;
Copy link
Collaborator

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 :)

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);
}
}
Expand Down Expand Up @@ -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() {
Expand Down Expand Up @@ -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;
Expand Down
3 changes: 1 addition & 2 deletions clang/test/SemaCXX/invalid-requirement-requires-expr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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}}
};
Expand Down
1 change: 1 addition & 0 deletions clang/test/SemaTemplate/instantiation-depth-subst-2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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}}
3 changes: 2 additions & 1 deletion clang/test/SemaTemplate/instantiation-depth-subst.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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}}