diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp index e6569d4a784fde..f3641afbbf8a01 100644 --- a/clang/lib/Sema/SemaTemplateDeduction.cpp +++ b/clang/lib/Sema/SemaTemplateDeduction.cpp @@ -3041,8 +3041,13 @@ Sema::DeduceTemplateArguments(ClassTemplatePartialSpecializationDecl *Partial, if (Trap.hasErrorOccurred()) return Sema::TDK_SubstitutionFailure; - return ::FinishTemplateArgumentDeduction( - *this, Partial, /*IsPartialOrdering=*/false, TemplateArgs, Deduced, Info); + TemplateDeductionResult Result; + runWithSufficientStackSpace(Info.getLocation(), [&] { + Result = ::FinishTemplateArgumentDeduction(*this, Partial, + /*IsPartialOrdering=*/false, + TemplateArgs, Deduced, Info); + }); + return Result; } /// Perform template argument deduction to determine whether @@ -3082,8 +3087,13 @@ Sema::DeduceTemplateArguments(VarTemplatePartialSpecializationDecl *Partial, if (Trap.hasErrorOccurred()) return Sema::TDK_SubstitutionFailure; - return ::FinishTemplateArgumentDeduction( - *this, Partial, /*IsPartialOrdering=*/false, TemplateArgs, Deduced, Info); + TemplateDeductionResult Result; + runWithSufficientStackSpace(Info.getLocation(), [&] { + Result = ::FinishTemplateArgumentDeduction(*this, Partial, + /*IsPartialOrdering=*/false, + TemplateArgs, Deduced, Info); + }); + return Result; } /// Determine whether the given type T is a simple-template-id type. @@ -4032,13 +4042,12 @@ Sema::TemplateDeductionResult Sema::DeduceTemplateArguments( SmallVector ParamTypes; unsigned NumExplicitlySpecified = 0; if (ExplicitTemplateArgs) { - TemplateDeductionResult Result = - SubstituteExplicitTemplateArguments(FunctionTemplate, - *ExplicitTemplateArgs, - Deduced, - ParamTypes, - nullptr, - Info); + TemplateDeductionResult Result; + runWithSufficientStackSpace(Info.getLocation(), [&] { + Result = SubstituteExplicitTemplateArguments( + FunctionTemplate, *ExplicitTemplateArgs, Deduced, ParamTypes, nullptr, + Info); + }); if (Result) return Result; @@ -4140,12 +4149,16 @@ Sema::TemplateDeductionResult Sema::DeduceTemplateArguments( // that is needed when the accessibility of template arguments is checked. DeclContext *CallingCtx = CurContext; - return FinishTemplateArgumentDeduction( - FunctionTemplate, Deduced, NumExplicitlySpecified, Specialization, Info, - &OriginalCallArgs, PartialOverloading, [&, CallingCtx]() { - ContextRAII SavedContext(*this, CallingCtx); - return CheckNonDependent(ParamTypesForArgChecking); - }); + TemplateDeductionResult Result; + runWithSufficientStackSpace(Info.getLocation(), [&] { + Result = FinishTemplateArgumentDeduction( + FunctionTemplate, Deduced, NumExplicitlySpecified, Specialization, Info, + &OriginalCallArgs, PartialOverloading, [&, CallingCtx]() { + ContextRAII SavedContext(*this, CallingCtx); + return CheckNonDependent(ParamTypesForArgChecking); + }); + }); + return Result; } QualType Sema::adjustCCAndNoReturn(QualType ArgFunctionType, @@ -4231,11 +4244,13 @@ Sema::TemplateDeductionResult Sema::DeduceTemplateArguments( unsigned NumExplicitlySpecified = 0; SmallVector ParamTypes; if (ExplicitTemplateArgs) { - if (TemplateDeductionResult Result - = SubstituteExplicitTemplateArguments(FunctionTemplate, - *ExplicitTemplateArgs, - Deduced, ParamTypes, - &FunctionType, Info)) + TemplateDeductionResult Result; + runWithSufficientStackSpace(Info.getLocation(), [&] { + Result = SubstituteExplicitTemplateArguments( + FunctionTemplate, *ExplicitTemplateArgs, Deduced, ParamTypes, + &FunctionType, Info); + }); + if (Result) return Result; NumExplicitlySpecified = Deduced.size(); @@ -4277,10 +4292,13 @@ Sema::TemplateDeductionResult Sema::DeduceTemplateArguments( return Result; } - if (TemplateDeductionResult Result - = FinishTemplateArgumentDeduction(FunctionTemplate, Deduced, - NumExplicitlySpecified, - Specialization, Info)) + TemplateDeductionResult Result; + runWithSufficientStackSpace(Info.getLocation(), [&] { + Result = FinishTemplateArgumentDeduction(FunctionTemplate, Deduced, + NumExplicitlySpecified, + Specialization, Info); + }); + if (Result) return Result; // If the function has a deduced return type, deduce it now, so we can check @@ -4437,9 +4455,11 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *ConversionTemplate, LocalInstantiationScope InstScope(*this); // Finish template argument deduction. FunctionDecl *ConversionSpecialized = nullptr; - TemplateDeductionResult Result - = FinishTemplateArgumentDeduction(ConversionTemplate, Deduced, 0, - ConversionSpecialized, Info); + TemplateDeductionResult Result; + runWithSufficientStackSpace(Info.getLocation(), [&] { + Result = FinishTemplateArgumentDeduction(ConversionTemplate, Deduced, 0, + ConversionSpecialized, Info); + }); Specialization = cast_or_null(ConversionSpecialized); return Result; } @@ -5379,14 +5399,15 @@ static bool isAtLeastAsSpecializedAs(Sema &S, QualType T1, QualType T2, Sema::InstantiatingTemplate Inst(S, Info.getLocation(), P2, DeducedArgs, Info); auto *TST1 = T1->castAs(); - if (FinishTemplateArgumentDeduction( - S, P2, /*IsPartialOrdering=*/true, - TemplateArgumentList(TemplateArgumentList::OnStack, - TST1->template_arguments()), - Deduced, Info)) - return false; - - return true; + bool AtLeastAsSpecialized; + S.runWithSufficientStackSpace(Info.getLocation(), [&] { + AtLeastAsSpecialized = !FinishTemplateArgumentDeduction( + S, P2, /*IsPartialOrdering=*/true, + TemplateArgumentList(TemplateArgumentList::OnStack, + TST1->template_arguments()), + Deduced, Info); + }); + return AtLeastAsSpecialized; } /// Returns the more specialized class template partial specialization diff --git a/clang/test/SemaTemplate/stack-exhaustion.cpp b/clang/test/SemaTemplate/stack-exhaustion.cpp index 7f76212d2a4923..1eb1b474ffa580 100644 --- a/clang/test/SemaTemplate/stack-exhaustion.cpp +++ b/clang/test/SemaTemplate/stack-exhaustion.cpp @@ -1,4 +1,6 @@ -// RUN: %clang_cc1 -verify %s +// RUN: %clang_cc1 -verify %s -DTEST=1 +// RUN: %clang_cc1 -verify %s -DTEST=2 +// RUN: %clang_cc1 -verify %s -DTEST=3 // REQUIRES: thread_support // FIXME: Detection of, or recovery from, stack exhaustion does not work on @@ -9,6 +11,8 @@ // expected-warning@* 0-1{{stack nearly exhausted}} // expected-note@* 0+{{}} +#if TEST == 1 + template struct X : X {}; template<> struct X<0> {}; X<1000> x; @@ -21,3 +25,38 @@ int f(X<0>); template auto f(X) -> f(X()); int k = f(X<1000>()); + +#elif TEST == 2 + +namespace template_argument_recursion { + struct ostream; + template T &&declval(); + + namespace mlir { + template() << declval())> + ostream &operator<<(ostream& os, const T& obj); // expected-error {{exceeded maximum depth}} + struct Value; + } + + void printFunctionalType(ostream &os, mlir::Value &v) { os << v; } +} + +#elif TEST == 3 + +namespace template_parameter_type_recursion { + struct ostream; + template T &&declval(); + template struct enable_if { using type = T; }; + + namespace mlir { + template() << declval(), void*>::type = nullptr> + ostream &operator<<(ostream& os, const T& obj); // expected-error {{exceeded maximum depth}} + struct Value; + } + + void printFunctionalType(ostream &os, mlir::Value &v) { os << v; } +} + +#else +#error unknown test +#endif