diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -250,6 +250,9 @@ (`#64962 `_) and (`#28679 `_). +- Fix crash when parsing the requires clause of some generic lambdas. + (`#64689 `_`) + Bug Fixes to AST Handling ^^^^^^^^^^^^^^^^^^^^^^^^^ - Fixed an import failure of recursive friend class template. diff --git a/clang/include/clang/AST/DeclCXX.h b/clang/include/clang/AST/DeclCXX.h --- a/clang/include/clang/AST/DeclCXX.h +++ b/clang/include/clang/AST/DeclCXX.h @@ -1864,8 +1864,6 @@ "setting lambda property of non-lambda class"); auto &DL = static_cast(*DefinitionData); DL.IsGenericLambda = IsGeneric; - if(IsGeneric) - DL.DependencyKind = true; } // Determine whether this type is an Interface Like type for diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -7229,6 +7229,11 @@ CXXMethodDecl *CreateLambdaCallOperator(SourceRange IntroducerRange, CXXRecordDecl *Class); + + void AddTemplateParametersToLambdaCallOperator( + CXXMethodDecl *CallOperator, CXXRecordDecl *Class, + TemplateParameterList *TemplateParams); + void CompleteLambdaCallOperator( CXXMethodDecl *Method, SourceLocation LambdaLoc, SourceLocation CallOperatorLoc, Expr *TrailingRequiresClause, diff --git a/clang/lib/Sema/SemaLambda.cpp b/clang/lib/Sema/SemaLambda.cpp --- a/clang/lib/Sema/SemaLambda.cpp +++ b/clang/lib/Sema/SemaLambda.cpp @@ -912,6 +912,17 @@ return Method; } +void Sema::AddTemplateParametersToLambdaCallOperator( + CXXMethodDecl *CallOperator, CXXRecordDecl *Class, + TemplateParameterList *TemplateParams) { + assert(TemplateParams && "no template parameters"); + FunctionTemplateDecl *TemplateMethod = FunctionTemplateDecl::Create( + Context, Class, CallOperator->getLocation(), CallOperator->getDeclName(), + TemplateParams, CallOperator); + TemplateMethod->setAccess(AS_public); + CallOperator->setDescribedFunctionTemplate(TemplateMethod); +} + void Sema::CompleteLambdaCallOperator( CXXMethodDecl *Method, SourceLocation LambdaLoc, SourceLocation CallOperatorLoc, Expr *TrailingRequiresClause, @@ -930,11 +941,11 @@ DeclContext *DC = Method->getLexicalDeclContext(); Method->setLexicalDeclContext(LSI->Lambda); if (TemplateParams) { - FunctionTemplateDecl *TemplateMethod = FunctionTemplateDecl::Create( - Context, LSI->Lambda, Method->getLocation(), Method->getDeclName(), - TemplateParams, Method); - TemplateMethod->setAccess(AS_public); - Method->setDescribedFunctionTemplate(TemplateMethod); + FunctionTemplateDecl *TemplateMethod = + Method->getDescribedFunctionTemplate(); + assert(TemplateMethod && + "AddTemplateParametersToLambdaCallOperator should have been called"); + LSI->Lambda->addDecl(TemplateMethod); TemplateMethod->setLexicalDeclContext(DC); } else { @@ -1262,10 +1273,17 @@ PushOnScopeChains(Param, LambdaScope, false); } - bool IsGenericLambda = getGenericLambdaTemplateParameterList(LSI, *this); - LSI->Lambda->setLambdaIsGeneric(IsGenericLambda); - - + // After the parameter list, we may parse a noexcept/requires/trailing return + // type which need to know whether the call operator constiture a dependent + // context, so we need to setup the FunctionTemplateDecl of generic lambdas + // now. + TemplateParameterList *TemplateParams = + getGenericLambdaTemplateParameterList(LSI, *this); + if (TemplateParams) { + AddTemplateParametersToLambdaCallOperator(LSI->CallOperator, LSI->Lambda, + TemplateParams); + LSI->Lambda->setLambdaIsGeneric(true); + } LSI->AfterParameterList = true; } diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -13554,6 +13554,9 @@ auto TPL = getDerived().TransformTemplateParameterList( E->getTemplateParameterList()); LSI->GLTemplateParameterList = TPL; + if (TPL) + getSema().AddTemplateParametersToLambdaCallOperator(NewCallOperator, Class, + TPL); // Transform the type of the original lambda's call operator. // The transformation MUST be done in the CurrentInstantiationScope since diff --git a/clang/test/SemaCXX/cxx2a-template-lambdas.cpp b/clang/test/SemaCXX/cxx2a-template-lambdas.cpp --- a/clang/test/SemaCXX/cxx2a-template-lambdas.cpp +++ b/clang/test/SemaCXX/cxx2a-template-lambdas.cpp @@ -70,3 +70,22 @@ } } + +namespace GH64689 { +void f(); +void foo() { + [](int) + noexcept(requires(int t) { f(); }) + -> decltype(requires(int t) { f(); }) + requires requires(int t) { f(); } + {return {};}.operator()(0); + [](auto) + noexcept(requires(int t) { f(); }) + -> decltype(requires(int t) { f(); }) + requires requires(int t) { f(); } + {return {};}(1); +} + +} + +}