Skip to content

Commit

Permalink
[Clang] Correctly handle generic lambda used as default template argu…
Browse files Browse the repository at this point in the history
…ment.

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
  • Loading branch information
cor3ntin committed May 26, 2023
1 parent 0c18379 commit 75cd8cd
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 1 deletion.
2 changes: 2 additions & 0 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -507,6 +507,8 @@ Bug Fixes to C++ Support
(`#114 <https://github.com/llvm/llvm-project/issues/114>`_)
- Fix parsing of `auto(x)`, when it is surrounded by parentheses.
(`#62494 <https://github.com/llvm/llvm-project/issues/62494>`_)
- Fix handling of generic lambda used as template arguments.
(`#62611 <https://github.com/llvm/llvm-project/issues/62611>`_)

Bug Fixes to AST Handling
^^^^^^^^^^^^^^^^^^^^^^^^^
Expand Down
17 changes: 16 additions & 1 deletion clang/lib/Parse/ParseTemplate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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 =
Expand Down
27 changes: 27 additions & 0 deletions clang/test/SemaCXX/cxx2a-template-lambdas.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,30 @@ constexpr T outer() {
}
static_assert(outer<int>() == 123);
template int *outer<int *>(); // expected-note {{in instantiation}}


namespace GH62611 {
template <auto A = [](auto x){}>
struct C {
static constexpr auto B = A;
};

int test() {
C<>::B(42);
}

namespace AutoParam
{
template <auto A = [](auto x) { return x;}>
auto B = A;
static_assert(B<>(42) == 42);
}

namespace TypeParam
{
template <typename T = decltype([](auto x) {return x;})>
auto B = T{};
static_assert(B<>(42) == 42);
}

}

0 comments on commit 75cd8cd

Please sign in to comment.