From 75cd8cdbde45d07800d5cefa6f7a213271245e4a Mon Sep 17 00:00:00 2001 From: Corentin Jabot Date: Wed, 24 May 2023 18:11:40 +0200 Subject: [PATCH] [Clang] Correctly handle generic lambda used as default template argument. Adjust the template pparameter depth when parsing default template arguments as they may introduce generic lambda whose parameters are not substituted at the same depth. Fixes #62611 Reviewed By: erichkeane, #clang-language-wg Differential Revision: https://reviews.llvm.org/D151342 --- clang/docs/ReleaseNotes.rst | 2 ++ clang/lib/Parse/ParseTemplate.cpp | 17 ++++++++++++++++- clang/test/SemaCXX/cxx2a-template-lambdas.cpp | 27 +++++++++++++++++++++++++++ 3 files changed, 45 insertions(+), 1 deletion(-) diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index f1cc205..4387f9b 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 964d985..79f4ab6 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 65baf29..cc50292 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); +} + +} -- 2.7.4