diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index f1cc205c4a430..4387f9b3145be 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -507,6 +507,8 @@ Bug Fixes to C++ Support (`#114 `_) - Fix parsing of `auto(x)`, when it is surrounded by parentheses. (`#62494 `_) +- Fix handling of generic lambda used as template arguments. + (`#62611 `_) Bug Fixes to AST Handling ^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/lib/Parse/ParseTemplate.cpp b/clang/lib/Parse/ParseTemplate.cpp index 964d985b6b6e6..79f4ab683281e 100644 --- a/clang/lib/Parse/ParseTemplate.cpp +++ b/clang/lib/Parse/ParseTemplate.cpp @@ -841,10 +841,17 @@ NamedDecl *Parser::ParseTypeParameter(unsigned Depth, unsigned Position) { // we introduce the type parameter into the local scope. SourceLocation EqualLoc; ParsedType DefaultArg; - if (TryConsumeToken(tok::equal, EqualLoc)) + if (TryConsumeToken(tok::equal, EqualLoc)) { + // The default argument may declare template parameters, notably + // if it contains a generic lambda, so we need to increase + // the template depth as these parameters would not be instantiated + // at the current level. + TemplateParameterDepthRAII CurTemplateDepthTracker(TemplateParameterDepth); + ++CurTemplateDepthTracker; DefaultArg = ParseTypeName(/*Range=*/nullptr, DeclaratorContext::TemplateTypeArg) .get(); + } NamedDecl *NewDecl = Actions.ActOnTypeParameter(getCurScope(), TypenameKeyword, EllipsisLoc, @@ -1030,6 +1037,14 @@ Parser::ParseNonTypeTemplateParameter(unsigned Depth, unsigned Position) { // end of the template-parameter-list rather than a greater-than // operator. GreaterThanIsOperatorScope G(GreaterThanIsOperator, false); + + // The default argument may declare template parameters, notably + // if it contains a generic lambda, so we need to increase + // the template depth as these parameters would not be instantiated + // at the current level. + TemplateParameterDepthRAII CurTemplateDepthTracker( + TemplateParameterDepth); + ++CurTemplateDepthTracker; EnterExpressionEvaluationContext ConstantEvaluated( Actions, Sema::ExpressionEvaluationContext::ConstantEvaluated); DefaultArg = diff --git a/clang/test/SemaCXX/cxx2a-template-lambdas.cpp b/clang/test/SemaCXX/cxx2a-template-lambdas.cpp index 65baf29718f06..cc50292dbff48 100644 --- a/clang/test/SemaCXX/cxx2a-template-lambdas.cpp +++ b/clang/test/SemaCXX/cxx2a-template-lambdas.cpp @@ -43,3 +43,30 @@ constexpr T outer() { } static_assert(outer() == 123); template int *outer(); // expected-note {{in instantiation}} + + +namespace GH62611 { +template +struct C { + static constexpr auto B = A; +}; + +int test() { + C<>::B(42); +} + +namespace AutoParam +{ +template +auto B = A; +static_assert(B<>(42) == 42); +} + +namespace TypeParam +{ +template +auto B = T{}; +static_assert(B<>(42) == 42); +} + +}