Skip to content

Commit 890f11d

Browse files
committed
[Clang] Realize generic lambda call operators are dependent sooner
When parsing a trailing return type / noexcept / constraint of a generic lambda, we need to know that we are in a dependent context. We currently don't because we only create a TemplateDecl for the call operator one its fully parsed. This patch attach a template decl to the call operator as soon as the parameter declaration clause is parsed - the point at which we have collected all template parameters Fixes llvm#64689 Reviewed By: erichkeane Differential Revision: https://reviews.llvm.org/D159358
1 parent f4f40c6 commit 890f11d

File tree

5 files changed

+55
-5
lines changed

5 files changed

+55
-5
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,9 @@ Bug Fixes to C++ Support
257257
(`#64172 <https://github.com/llvm/llvm-project/issues/64172>`_) and
258258
(`#64723 <https://github.com/llvm/llvm-project/issues/64723>`_).
259259

260+
Fix crash when parsing the requires clause of some generic lambdas.
261+
(`#64689 <https://github.com/llvm/llvm-project/issues/64689>`_`)
262+
260263
Bug Fixes to AST Handling
261264
^^^^^^^^^^^^^^^^^^^^^^^^^
262265
- Fixed an import failure of recursive friend class template.

clang/include/clang/Sema/Sema.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7216,6 +7216,11 @@ class Sema final {
72167216

72177217
CXXMethodDecl *CreateLambdaCallOperator(SourceRange IntroducerRange,
72187218
CXXRecordDecl *Class);
7219+
7220+
void AddTemplateParametersToLambdaCallOperator(
7221+
CXXMethodDecl *CallOperator, CXXRecordDecl *Class,
7222+
TemplateParameterList *TemplateParams);
7223+
72197224
void CompleteLambdaCallOperator(
72207225
CXXMethodDecl *Method, SourceLocation LambdaLoc,
72217226
SourceLocation CallOperatorLoc, Expr *TrailingRequiresClause,

clang/lib/Sema/SemaLambda.cpp

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -912,6 +912,17 @@ CXXMethodDecl *Sema::CreateLambdaCallOperator(SourceRange IntroducerRange,
912912
return Method;
913913
}
914914

915+
void Sema::AddTemplateParametersToLambdaCallOperator(
916+
CXXMethodDecl *CallOperator, CXXRecordDecl *Class,
917+
TemplateParameterList *TemplateParams) {
918+
assert(TemplateParams && "no template parameters");
919+
FunctionTemplateDecl *TemplateMethod = FunctionTemplateDecl::Create(
920+
Context, Class, CallOperator->getLocation(), CallOperator->getDeclName(),
921+
TemplateParams, CallOperator);
922+
TemplateMethod->setAccess(AS_public);
923+
CallOperator->setDescribedFunctionTemplate(TemplateMethod);
924+
}
925+
915926
void Sema::CompleteLambdaCallOperator(
916927
CXXMethodDecl *Method, SourceLocation LambdaLoc,
917928
SourceLocation CallOperatorLoc, Expr *TrailingRequiresClause,
@@ -930,11 +941,11 @@ void Sema::CompleteLambdaCallOperator(
930941
DeclContext *DC = Method->getLexicalDeclContext();
931942
Method->setLexicalDeclContext(LSI->Lambda);
932943
if (TemplateParams) {
933-
FunctionTemplateDecl *TemplateMethod = FunctionTemplateDecl::Create(
934-
Context, LSI->Lambda, Method->getLocation(), Method->getDeclName(),
935-
TemplateParams, Method);
936-
TemplateMethod->setAccess(AS_public);
937-
Method->setDescribedFunctionTemplate(TemplateMethod);
944+
FunctionTemplateDecl *TemplateMethod =
945+
Method->getDescribedFunctionTemplate();
946+
assert(TemplateMethod &&
947+
"AddTemplateParametersToLambdaCallOperator should have been called");
948+
938949
LSI->Lambda->addDecl(TemplateMethod);
939950
TemplateMethod->setLexicalDeclContext(DC);
940951
} else {
@@ -1262,6 +1273,17 @@ void Sema::ActOnLambdaClosureParameters(
12621273
PushOnScopeChains(Param, LambdaScope, false);
12631274
}
12641275

1276+
// After the parameter list, we may parse a noexcept/requires/trailing return
1277+
// type which need to know whether the call operator constiture a dependent
1278+
// context, so we need to setup the FunctionTemplateDecl of generic lambdas
1279+
// now.
1280+
TemplateParameterList *TemplateParams =
1281+
getGenericLambdaTemplateParameterList(LSI, *this);
1282+
if (TemplateParams) {
1283+
AddTemplateParametersToLambdaCallOperator(LSI->CallOperator, LSI->Lambda,
1284+
TemplateParams);
1285+
LSI->Lambda->setLambdaIsGeneric(true);
1286+
}
12651287
LSI->AfterParameterList = true;
12661288
}
12671289

clang/lib/Sema/TreeTransform.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13558,6 +13558,9 @@ TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) {
1355813558
auto TPL = getDerived().TransformTemplateParameterList(
1355913559
E->getTemplateParameterList());
1356013560
LSI->GLTemplateParameterList = TPL;
13561+
if (TPL)
13562+
getSema().AddTemplateParametersToLambdaCallOperator(NewCallOperator, Class,
13563+
TPL);
1356113564

1356213565
// Transform the type of the original lambda's call operator.
1356313566
// The transformation MUST be done in the CurrentInstantiationScope since

clang/test/SemaCXX/cxx2a-template-lambdas.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,3 +70,20 @@ static_assert(B<>(42) == 42);
7070
}
7171

7272
}
73+
74+
namespace GH64689 {
75+
void f();
76+
void foo() {
77+
[]<typename T>(int)
78+
noexcept(requires(int t) { f(); })
79+
-> decltype(requires(int t) { f(); })
80+
requires requires(int t) { f(); }
81+
{return {};}.operator()<int>(0);
82+
[](auto)
83+
noexcept(requires(int t) { f(); })
84+
-> decltype(requires(int t) { f(); })
85+
requires requires(int t) { f(); }
86+
{return {};}(1);
87+
}
88+
89+
}

0 commit comments

Comments
 (0)