[clang] 890f11d - [Clang] Realize generic lambda call operators are dependent sooner
Corentin Jabot via cfe-commits
cfe-commits at lists.llvm.org
Fri Sep 1 23:05:55 PDT 2023
Author: Corentin Jabot
Date: 2023-09-02T08:05:49+02:00
New Revision: 890f11d60feffed4207afa58229da7bfaaff276e
URL: https://github.com/llvm/llvm-project/commit/890f11d60feffed4207afa58229da7bfaaff276e
DIFF: https://github.com/llvm/llvm-project/commit/890f11d60feffed4207afa58229da7bfaaff276e.diff
LOG: [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 #64689
Reviewed By: erichkeane
Differential Revision: https://reviews.llvm.org/D159358
Added:
Modified:
clang/docs/ReleaseNotes.rst
clang/include/clang/Sema/Sema.h
clang/lib/Sema/SemaLambda.cpp
clang/lib/Sema/TreeTransform.h
clang/test/SemaCXX/cxx2a-template-lambdas.cpp
Removed:
################################################################################
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 51a04735bfd665..30fc9c43543d52 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -257,6 +257,9 @@ Bug Fixes to C++ Support
(`#64172 <https://github.com/llvm/llvm-project/issues/64172>`_) and
(`#64723 <https://github.com/llvm/llvm-project/issues/64723>`_).
+ Fix crash when parsing the requires clause of some generic lambdas.
+ (`#64689 <https://github.com/llvm/llvm-project/issues/64689>`_`)
+
Bug Fixes to AST Handling
^^^^^^^^^^^^^^^^^^^^^^^^^
- Fixed an import failure of recursive friend class template.
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 1980571e6656f9..35ee253831fc93 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -7216,6 +7216,11 @@ class Sema final {
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
index 26d3a66d553192..5256d91a19a0d0 100644
--- a/clang/lib/Sema/SemaLambda.cpp
+++ b/clang/lib/Sema/SemaLambda.cpp
@@ -912,6 +912,17 @@ CXXMethodDecl *Sema::CreateLambdaCallOperator(SourceRange IntroducerRange,
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 @@ void Sema::CompleteLambdaCallOperator(
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,6 +1273,17 @@ void Sema::ActOnLambdaClosureParameters(
PushOnScopeChains(Param, LambdaScope, false);
}
+ // 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
index a08a0177db0a67..cfcd19e57cf169 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -13558,6 +13558,9 @@ TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) {
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
index cc50292dbff487..7ac48136989146 100644
--- a/clang/test/SemaCXX/cxx2a-template-lambdas.cpp
+++ b/clang/test/SemaCXX/cxx2a-template-lambdas.cpp
@@ -70,3 +70,20 @@ static_assert(B<>(42) == 42);
}
}
+
+namespace GH64689 {
+void f();
+void foo() {
+ []<typename T>(int)
+ noexcept(requires(int t) { f(); })
+ -> decltype(requires(int t) { f(); })
+ requires requires(int t) { f(); }
+ {return {};}.operator()<int>(0);
+ [](auto)
+ noexcept(requires(int t) { f(); })
+ -> decltype(requires(int t) { f(); })
+ requires requires(int t) { f(); }
+ {return {};}(1);
+}
+
+}
More information about the cfe-commits
mailing list