cor3ntin updated this revision to Diff 423657.
cor3ntin added a comment.
More cleanups and formatting.
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D124012/new/
https://reviews.llvm.org/D124012
Files:
clang/include/clang/Sema/Sema.h
clang/lib/Sema/SemaLambda.cpp
clang/lib/Sema/TreeTransform.h
clang/test/SemaCXX/lambda-capture-type-deduction.cpp
Index: clang/test/SemaCXX/lambda-capture-type-deduction.cpp
===================================================================
--- clang/test/SemaCXX/lambda-capture-type-deduction.cpp
+++ clang/test/SemaCXX/lambda-capture-type-deduction.cpp
@@ -163,6 +163,35 @@
[&]() requires is_same<decltype(u), T> {}();
}
+template <typename T>
+void dependent_init_capture(T x = 0) {
+ [ y = x + 1, x ]() mutable -> decltype(y + x) requires(is_same<decltype((y)), int &> && is_same<decltype((x)), int &>) {
+ return y;
+ }
+ ();
+ [ y = x + 1, x ]() -> decltype(y + x) requires(is_same<decltype((y)), const int &> && is_same<decltype((x)), const int &>) {
+ return y;
+ }
+ ();
+}
+
+template <typename T, typename...>
+struct extract_type {
+ using type = T;
+};
+
+template <typename... T>
+void dependent_variadic_capture(T... x) {
+ [... y = x, x... ](auto...) mutable -> typename extract_type<decltype(y)...>::type requires((is_same<decltype((y)), int &> && ...) && (is_same<decltype((x)), int &> && ...)) {
+ return 0;
+ }
+ (x...);
+ [... y = x, x... ](auto...) -> typename extract_type<decltype(y)...>::type requires((is_same<decltype((y)), const int &> && ...) && (is_same<decltype((x)), const int &> && ...)) {
+ return 0;
+ }
+ (x...);
+}
+
void test_dependent() {
int v = 0;
int & r = v;
@@ -170,6 +199,8 @@
dependent<int&>(v);
dependent<int&>(r);
dependent<const int&>(cr);
+ dependent_init_capture(0);
+ dependent_variadic_capture(1, 2, 3, 4);
}
void test_CWG2569_tpl(auto a) {
Index: clang/lib/Sema/TreeTransform.h
===================================================================
--- clang/lib/Sema/TreeTransform.h
+++ clang/lib/Sema/TreeTransform.h
@@ -12966,44 +12966,6 @@
LambdaScopeInfo *LSI = getSema().PushLambdaScope();
Sema::FunctionScopeRAII FuncScopeCleanup(getSema());
- // Transform the template parameters, and add them to the current
- // instantiation scope. The null case is handled correctly.
- auto TPL = getDerived().TransformTemplateParameterList(
- E->getTemplateParameterList());
- LSI->GLTemplateParameterList = TPL;
-
- // Transform the type of the original lambda's call operator.
- // The transformation MUST be done in the CurrentInstantiationScope since
- // it introduces a mapping of the original to the newly created
- // transformed parameters.
- TypeSourceInfo *NewCallOpTSI = nullptr;
- {
- TypeSourceInfo *OldCallOpTSI = E->getCallOperator()->getTypeSourceInfo();
- FunctionProtoTypeLoc OldCallOpFPTL =
- OldCallOpTSI->getTypeLoc().getAs<FunctionProtoTypeLoc>();
-
- TypeLocBuilder NewCallOpTLBuilder;
- SmallVector<QualType, 4> ExceptionStorage;
- TreeTransform *This = this; // Work around gcc.gnu.org/PR56135.
- QualType NewCallOpType = TransformFunctionProtoType(
- NewCallOpTLBuilder, OldCallOpFPTL, nullptr, Qualifiers(),
- [&](FunctionProtoType::ExceptionSpecInfo &ESI, bool &Changed) {
- return This->TransformExceptionSpec(OldCallOpFPTL.getBeginLoc(), ESI,
- ExceptionStorage, Changed);
- });
- if (NewCallOpType.isNull())
- return ExprError();
- NewCallOpTSI = NewCallOpTLBuilder.getTypeSourceInfo(getSema().Context,
- NewCallOpType);
- }
-
- // Transform the trailing requires clause
- ExprResult NewTrailingRequiresClause;
- if (Expr *TRC = E->getCallOperator()->getTrailingRequiresClause())
- // FIXME: Concepts: Substitution into requires clause should only happen
- // when checking satisfaction.
- NewTrailingRequiresClause = getDerived().TransformExpr(TRC);
-
// Create the local class that will describe the lambda.
// FIXME: DependencyKind below is wrong when substituting inside a templated
@@ -13019,10 +12981,8 @@
DependencyKind = CXXRecordDecl::LDK_NeverDependent;
CXXRecordDecl *OldClass = E->getLambdaClass();
- CXXRecordDecl *Class =
- getSema().createLambdaClosureType(E->getIntroducerRange(), NewCallOpTSI,
- DependencyKind, E->getCaptureDefault());
-
+ CXXRecordDecl *Class = getSema().createLambdaClosureType(
+ E->getIntroducerRange(), nullptr, DependencyKind, E->getCaptureDefault());
getDerived().transformedLocalDecl(OldClass, {Class});
Optional<std::tuple<bool, unsigned, unsigned, Decl *>> Mangling;
@@ -13032,35 +12992,19 @@
OldClass->getDeviceLambdaManglingNumber(),
OldClass->getLambdaContextDecl());
- // Build the call operator.
- CXXMethodDecl *NewCallOperator = getSema().startLambdaDefinition(
- Class, E->getIntroducerRange(), NewCallOpTSI,
- E->getCallOperator()->getEndLoc(),
- NewCallOpTSI->getTypeLoc().castAs<FunctionProtoTypeLoc>().getParams(),
- E->getCallOperator()->getConstexprKind(),
- NewTrailingRequiresClause.get());
-
- LSI->CallOperator = NewCallOperator;
+ CXXMethodDecl *NewCallOperator =
+ getSema().CreateLambdaCallOperator(E->getIntroducerRange(), Class);
+ NewCallOperator->setLexicalDeclContext(getSema().CurContext);
- getDerived().transformAttrs(E->getCallOperator(), NewCallOperator);
- getDerived().transformedLocalDecl(E->getCallOperator(), {NewCallOperator});
-
- // Number the lambda for linkage purposes if necessary.
- getSema().handleLambdaNumbering(Class, NewCallOperator, Mangling);
+ // Enter the scope of the lambda.
+ getSema().buildLambdaScope(LSI, NewCallOperator, E->getIntroducerRange(),
+ E->getCaptureDefault(), E->getCaptureDefaultLoc(),
+ E->hasExplicitParameters(), E->isMutable());
// Introduce the context of the call operator.
Sema::ContextRAII SavedContext(getSema(), NewCallOperator,
/*NewThisContext*/false);
- // Enter the scope of the lambda.
- getSema().buildLambdaScope(LSI, NewCallOperator,
- E->getIntroducerRange(),
- E->getCaptureDefault(),
- E->getCaptureDefaultLoc(),
- E->hasExplicitParameters(),
- E->hasExplicitResultType(),
- E->isMutable());
-
bool Invalid = false;
// Transform captures.
@@ -13182,6 +13126,60 @@
}
getSema().finishLambdaExplicitCaptures(LSI);
+ // Transform the template parameters, and add them to the current
+ // instantiation scope. The null case is handled correctly.
+ auto TPL = getDerived().TransformTemplateParameterList(
+ E->getTemplateParameterList());
+ LSI->GLTemplateParameterList = TPL;
+
+ // Transform the type of the original lambda's call operator.
+ // The transformation MUST be done in the CurrentInstantiationScope since
+ // it introduces a mapping of the original to the newly created
+ // transformed parameters.
+ TypeSourceInfo *NewCallOpTSI = nullptr;
+ {
+ TypeSourceInfo *OldCallOpTSI = E->getCallOperator()->getTypeSourceInfo();
+ FunctionProtoTypeLoc OldCallOpFPTL =
+ OldCallOpTSI->getTypeLoc().getAs<FunctionProtoTypeLoc>();
+
+ TypeLocBuilder NewCallOpTLBuilder;
+ SmallVector<QualType, 4> ExceptionStorage;
+ TreeTransform *This = this; // Work around gcc.gnu.org/PR56135.
+ QualType NewCallOpType = TransformFunctionProtoType(
+ NewCallOpTLBuilder, OldCallOpFPTL, nullptr, Qualifiers(),
+ [&](FunctionProtoType::ExceptionSpecInfo &ESI, bool &Changed) {
+ return This->TransformExceptionSpec(OldCallOpFPTL.getBeginLoc(), ESI,
+ ExceptionStorage, Changed);
+ });
+ if (NewCallOpType.isNull())
+ return ExprError();
+ NewCallOpTSI =
+ NewCallOpTLBuilder.getTypeSourceInfo(getSema().Context, NewCallOpType);
+ }
+
+ // Transform the trailing requires clause
+ ExprResult NewTrailingRequiresClause;
+ if (Expr *TRC = E->getCallOperator()->getTrailingRequiresClause())
+ // FIXME: Concepts: Substitution into requires clause should only happen
+ // when checking satisfaction.
+ NewTrailingRequiresClause = getDerived().TransformExpr(TRC);
+
+ getSema().CompleteLambdaCallOperator(
+ NewCallOperator, E->getCallOperator()->getLocation(),
+ NewTrailingRequiresClause.get(), NewCallOpTSI,
+ E->getCallOperator()->getConstexprKind(),
+ NewCallOpTSI->getTypeLoc().castAs<FunctionProtoTypeLoc>().getParams(),
+ E->hasExplicitResultType());
+
+ getDerived().transformAttrs(E->getCallOperator(), NewCallOperator);
+ getDerived().transformedLocalDecl(E->getCallOperator(), {NewCallOperator});
+
+ {
+ // Number the lambda for linkage purposes if necessary.
+ Sema::ContextRAII ManglingContext(getSema(), Class->getDeclContext());
+ getSema().handleLambdaNumbering(Class, NewCallOperator, Mangling);
+ }
+
// FIXME: Sema's lambda-building mechanism expects us to push an expression
// evaluation context even if we're not transforming the function body.
getSema().PushExpressionEvaluationContext(
Index: clang/lib/Sema/SemaLambda.cpp
===================================================================
--- clang/lib/Sema/SemaLambda.cpp
+++ clang/lib/Sema/SemaLambda.cpp
@@ -540,11 +540,9 @@
SourceRange IntroducerRange,
LambdaCaptureDefault CaptureDefault,
SourceLocation CaptureDefaultLoc,
- bool ExplicitParams, bool ExplicitResultType,
- bool Mutable) {
+ bool ExplicitParams, bool Mutable) {
buildLambdaScopeCaptures(LSI, CallOperator, IntroducerRange, CaptureDefault,
CaptureDefaultLoc, ExplicitParams, Mutable);
- buildLambdaScopeReturnType(*this, LSI, CallOperator, ExplicitResultType);
}
void Sema::finishLambdaExplicitCaptures(LambdaScopeInfo *LSI) {
@@ -953,28 +951,76 @@
return MethodTyInfo;
}
-static CXXMethodDecl *CreateMethod(Sema &S, SourceRange IntroducerRange,
- CXXRecordDecl *Class) {
+CXXMethodDecl *Sema::CreateLambdaCallOperator(SourceRange IntroducerRange,
+ CXXRecordDecl *Class) {
+
// C++11 [expr.prim.lambda]p5:
// The closure type for a lambda-expression has a public inline function
// call operator (13.5.4) whose parameters and return type are described
// by the lambda-expression's parameter-declaration-clause and
// trailing-return-type respectively.
DeclarationName MethodName =
- S.Context.DeclarationNames.getCXXOperatorName(OO_Call);
+ Context.DeclarationNames.getCXXOperatorName(OO_Call);
DeclarationNameLoc MethodNameLoc =
DeclarationNameLoc::makeCXXOperatorNameLoc(IntroducerRange.getBegin());
CXXMethodDecl *Method = CXXMethodDecl::Create(
- S.Context, Class, SourceLocation(),
+ Context, Class, SourceLocation(),
DeclarationNameInfo(MethodName, IntroducerRange.getBegin(),
MethodNameLoc),
- QualType(), nullptr, SC_None, S.getCurFPFeatures().isFPConstrained(),
+ QualType(), nullptr, SC_None, getCurFPFeatures().isFPConstrained(),
/*isInline=*/true, ConstexprSpecKind::Unspecified, SourceLocation(),
nullptr);
Method->setAccess(AS_public);
return Method;
}
+void Sema::CompleteLambdaCallOperator(CXXMethodDecl *Method, SourceLocation Loc,
+ Expr *TrailingRequiresClause,
+ TypeSourceInfo *MethodTyInfo,
+ ConstexprSpecKind ConstexprKind,
+ ArrayRef<ParmVarDecl *> Params,
+ bool HasExplicitResultType) {
+
+ LambdaScopeInfo *const LSI = getCurrentLambdaScopeUnsafe(*this);
+
+ if (TrailingRequiresClause)
+ Method->setTrailingRequiresClause(TrailingRequiresClause);
+
+ TemplateParameterList *TemplateParams =
+ getGenericLambdaTemplateParameterList(LSI, *this);
+
+ auto DC = Method->getLexicalDeclContext();
+ Method->setLexicalDeclContext(LSI->Lambda);
+ if (TemplateParams) {
+ FunctionTemplateDecl *const TemplateMethod = FunctionTemplateDecl::Create(
+ Context, LSI->Lambda, Method->getLocation(), Method->getDeclName(),
+ TemplateParams, Method);
+ TemplateMethod->setAccess(AS_public);
+ Method->setDescribedFunctionTemplate(TemplateMethod);
+ LSI->Lambda->addDecl(TemplateMethod);
+ TemplateMethod->setLexicalDeclContext(DC);
+ } else {
+ LSI->Lambda->addDecl(Method);
+ }
+ LSI->Lambda->setLambdaIsGeneric(TemplateParams);
+ LSI->Lambda->setLambdaTypeInfo(MethodTyInfo);
+
+ Method->setLexicalDeclContext(DC);
+ Method->setLocation(Loc);
+ Method->setTypeSourceInfo(MethodTyInfo);
+ Method->setType(buildTypeForLambdaCallOperator(*this, LSI->Lambda,
+ TemplateParams, MethodTyInfo));
+ Method->setConstexprKind(ConstexprKind);
+ if (!Params.empty()) {
+ CheckParmsForFunctionDef(Params, /*CheckParameterNames=*/false);
+ Method->setParams(Params);
+ for (auto P : Method->parameters())
+ P->setOwningFunction(Method);
+ }
+
+ buildLambdaScopeReturnType(*this, LSI, Method, HasExplicitResultType);
+}
+
void Sema::ActOnLambdaIntroducer(LambdaIntroducer &Intro, Scope *CurrentScope) {
LambdaScopeInfo *const LSI = getCurLambda();
@@ -1016,7 +1062,7 @@
// by the lambda-expression's parameter-declaration-clause and
// trailing-return-type respectively.
- CXXMethodDecl *Method = CreateMethod(*this, Intro.Range, Class);
+ CXXMethodDecl *Method = CreateLambdaCallOperator(Intro.Range, Class);
LSI->CallOperator = Method;
Method->setLexicalDeclContext(CurContext);
@@ -1312,40 +1358,9 @@
CXXRecordDecl *Class = LSI->Lambda;
CXXMethodDecl *Method = LSI->CallOperator;
- if (auto *C = ParamInfo.getTrailingRequiresClause())
- Method->setTrailingRequiresClause(C);
-
- TemplateParameterList *TemplateParams =
- getGenericLambdaTemplateParameterList(LSI, *this);
-
- auto DC = Method->getLexicalDeclContext();
- Method->setLexicalDeclContext(Class);
- if (TemplateParams) {
- FunctionTemplateDecl *const TemplateMethod = FunctionTemplateDecl::Create(
- Context, Class, Method->getLocation(), Method->getDeclName(),
- TemplateParams, Method);
- TemplateMethod->setAccess(AS_public);
- Method->setDescribedFunctionTemplate(TemplateMethod);
- Class->addDecl(TemplateMethod);
- TemplateMethod->setLexicalDeclContext(DC);
- } else {
- Class->addDecl(Method);
- }
- Method->setLexicalDeclContext(DC);
- Class->setLambdaIsGeneric(TemplateParams);
-
TypeSourceInfo *MethodTyInfo = getLambdaType(
*this, Intro, ParamInfo, getCurScope(), TypeLoc, ExplicitResultType);
- Class->setLambdaTypeInfo(MethodTyInfo);
- Method->setInnerLocStart(LambdaLoc);
- Method->setLocation(Intro.Range.getBegin());
- Method->setTypeSourceInfo(MethodTyInfo);
- Method->setType(buildTypeForLambdaCallOperator(*this, Class, TemplateParams,
- MethodTyInfo));
- Method->setConstexprKind(ParamInfo.getDeclSpec().getConstexprSpecifier());
- buildLambdaScopeReturnType(*this, LSI, Method, ExplicitResultType);
-
LSI->ExplicitParams = ParamInfo.getNumTypeObjects() != 0;
if (ParamInfo.isFunctionDeclarator() != 0 &&
@@ -1359,14 +1374,15 @@
}
}
- ContextRAII ManglingContext(*this, Class->getDeclContext());
+ Method->setInnerLocStart(LambdaLoc);
+ CompleteLambdaCallOperator(
+ Method, Intro.Range.getBegin(), ParamInfo.getTrailingRequiresClause(),
+ MethodTyInfo, ParamInfo.getDeclSpec().getConstexprSpecifier(), Params,
+ ExplicitResultType);
- CheckParmsForFunctionDef(Params, /*CheckParameterNames=*/false);
+ ContextRAII ManglingContext(*this, Class->getDeclContext());
- if (LSI->ExplicitParams) {
- Method->setParams(Params);
- CheckCXXDefaultArguments(Method);
- }
+ CheckCXXDefaultArguments(Method);
// This represents the function body for the lambda function, check if we
// have to apply optnone due to a pragma.
Index: clang/include/clang/Sema/Sema.h
===================================================================
--- clang/include/clang/Sema/Sema.h
+++ clang/include/clang/Sema/Sema.h
@@ -6849,9 +6849,17 @@
LambdaCaptureDefault CaptureDefault,
SourceLocation CaptureDefaultLoc,
bool ExplicitParams,
- bool ExplicitResultType,
bool Mutable);
+ CXXMethodDecl *CreateLambdaCallOperator(SourceRange IntroducerRange,
+ CXXRecordDecl *Class);
+ void CompleteLambdaCallOperator(CXXMethodDecl *Method, SourceLocation Loc,
+ Expr *TrailingRequiresClause,
+ TypeSourceInfo *MethodTyInfo,
+ ConstexprSpecKind ConstexprKind,
+ ArrayRef<ParmVarDecl *> Params,
+ bool HasExplicitResultType);
+
/// Perform initialization analysis of the init-capture and perform
/// any implicit conversions such as an lvalue-to-rvalue conversion if
/// not being used to initialize a reference.
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits