diff options
author | Douglas Gregor <dgregor@apple.com> | 2012-02-14 19:27:52 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2012-02-14 19:27:52 +0000 |
commit | a73652465bcc4c0f6cb7d933ad84e002b527a643 (patch) | |
tree | 04ea4a96da25afda7a6dc6353d0ad0bbee083894 /lib | |
parent | 63aae82bb12bbbe9028e597fb77e40fa8d348c12 (diff) |
Implement support for lambda capture pack expansions, e.g.,
[&values...] { print(values...); }
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@150497 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Parse/ParseExprCXX.cpp | 8 | ||||
-rw-r--r-- | lib/Sema/SemaExpr.cpp | 5 | ||||
-rw-r--r-- | lib/Sema/SemaLambda.cpp | 22 | ||||
-rw-r--r-- | lib/Sema/TreeTransform.h | 51 |
4 files changed, 73 insertions, 13 deletions
diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp index fe212f4ebc..380237082b 100644 --- a/lib/Parse/ParseExprCXX.cpp +++ b/lib/Parse/ParseExprCXX.cpp @@ -651,7 +651,8 @@ llvm::Optional<unsigned> Parser::ParseLambdaIntroducer(LambdaIntroducer &Intro) LambdaCaptureKind Kind = LCK_ByCopy; SourceLocation Loc; IdentifierInfo* Id = 0; - + SourceLocation EllipsisLoc; + if (Tok.is(tok::kw_this)) { Kind = LCK_This; Loc = ConsumeToken(); @@ -664,6 +665,9 @@ llvm::Optional<unsigned> Parser::ParseLambdaIntroducer(LambdaIntroducer &Intro) if (Tok.is(tok::identifier)) { Id = Tok.getIdentifierInfo(); Loc = ConsumeToken(); + + if (Tok.is(tok::ellipsis)) + EllipsisLoc = ConsumeToken(); } else if (Tok.is(tok::kw_this)) { // FIXME: If we want to suggest a fixit here, will need to return more // than just DiagnosticID. Perhaps full DiagnosticBuilder that can be @@ -674,7 +678,7 @@ llvm::Optional<unsigned> Parser::ParseLambdaIntroducer(LambdaIntroducer &Intro) } } - Intro.addCapture(Kind, Loc, Id); + Intro.addCapture(Kind, Loc, Id, EllipsisLoc); } T.consumeClose(); diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 4dc8a7bedd..371a4e39eb 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -9831,7 +9831,7 @@ bool Sema::canCaptureVariable(VarDecl *Var, SourceLocation Loc, bool Explicit, // Check if the variable needs to be captured; if so, try to perform // the capture. void Sema::TryCaptureVar(VarDecl *var, SourceLocation loc, - TryCaptureKind Kind) { + TryCaptureKind Kind, SourceLocation EllipsisLoc) { QualType type; unsigned functionScopesIndex; bool Nested; @@ -9909,7 +9909,8 @@ void Sema::TryCaptureVar(VarDecl *var, SourceLocation loc, } } - CSI->AddCapture(var, hasBlocksAttr, byRef, Nested, loc, copyExpr); + CSI->AddCapture(var, hasBlocksAttr, byRef, Nested, loc, EllipsisLoc, + copyExpr); Nested = true; if (shouldAddConstForScope(CSI, var)) diff --git a/lib/Sema/SemaLambda.cpp b/lib/Sema/SemaLambda.cpp index 0ce1c74163..c75c3c5b7d 100644 --- a/lib/Sema/SemaLambda.cpp +++ b/lib/Sema/SemaLambda.cpp @@ -291,9 +291,26 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro, continue; } + // C++11 [expr.prim.lambda]p23: + // A capture followed by an ellipsis is a pack expansion (14.5.3). + SourceLocation EllipsisLoc; + if (C->EllipsisLoc.isValid()) { + if (Var->isParameterPack()) { + EllipsisLoc = C->EllipsisLoc; + } else { + Diag(C->EllipsisLoc, diag::err_pack_expansion_without_parameter_packs) + << SourceRange(C->Loc); + + // Just ignore the ellipsis. + } + } else if (Var->isParameterPack()) { + Diag(C->Loc, diag::err_lambda_unexpanded_pack); + continue; + } + TryCaptureKind Kind = C->Kind == LCK_ByRef ? TryCapture_ExplicitByRef : TryCapture_ExplicitByVal; - TryCaptureVar(Var, C->Loc, Kind); + TryCaptureVar(Var, C->Loc, Kind, EllipsisLoc); } finishLambdaExplicitCaptures(LSI); @@ -380,10 +397,9 @@ ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc, Stmt *Body, } VarDecl *Var = From.getVariable(); - // FIXME: Handle pack expansions. LambdaCaptureKind Kind = From.isCopyCapture()? LCK_ByCopy : LCK_ByRef; Captures.push_back(LambdaExpr::Capture(From.getLocation(), IsImplicit, - Kind, Var)); + Kind, Var, From.getEllipsisLoc())); CaptureInits.push_back(From.getCopyExpr()); } diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h index a63b9c804a..71037b6b3e 100644 --- a/lib/Sema/TreeTransform.h +++ b/lib/Sema/TreeTransform.h @@ -7706,6 +7706,49 @@ TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) { continue; } + // Determine the capture kind for Sema. + Sema::TryCaptureKind Kind + = C->isImplicit()? Sema::TryCapture_Implicit + : C->getCaptureKind() == LCK_ByCopy + ? Sema::TryCapture_ExplicitByVal + : Sema::TryCapture_ExplicitByRef; + SourceLocation EllipsisLoc; + if (C->isPackExpansion()) { + UnexpandedParameterPack Unexpanded(C->getCapturedVar(), C->getLocation()); + bool ShouldExpand = false; + bool RetainExpansion = false; + llvm::Optional<unsigned> NumExpansions; + if (getDerived().TryExpandParameterPacks(C->getEllipsisLoc(), + C->getLocation(), + Unexpanded, + ShouldExpand, RetainExpansion, + NumExpansions)) + return ExprError(); + + if (ShouldExpand) { + // The transform has determined that we should perform an expansion; + // transform and capture each of the arguments. + // expansion of the pattern. Do so. + VarDecl *Pack = C->getCapturedVar(); + for (unsigned I = 0; I != *NumExpansions; ++I) { + Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(getSema(), I); + VarDecl *CapturedVar + = cast_or_null<VarDecl>(getDerived().TransformDecl(C->getLocation(), + Pack)); + if (!CapturedVar) { + Invalid = true; + continue; + } + + // Capture the transformed variable. + getSema().TryCaptureVar(CapturedVar, C->getLocation(), Kind); + } + continue; + } + + EllipsisLoc = C->getEllipsisLoc(); + } + // Transform the captured variable. VarDecl *CapturedVar = cast_or_null<VarDecl>(getDerived().TransformDecl(C->getLocation(), @@ -7714,13 +7757,9 @@ TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) { Invalid = true; continue; } - + // Capture the transformed variable. - getSema().TryCaptureVar(CapturedVar, C->getLocation(), - C->isImplicit()? Sema::TryCapture_Implicit - : C->getCaptureKind() == LCK_ByCopy - ? Sema::TryCapture_ExplicitByVal - : Sema::TryCapture_ExplicitByRef); + getSema().TryCaptureVar(CapturedVar, C->getLocation(), Kind); } if (!FinishedExplicitCaptures) getSema().finishLambdaExplicitCaptures(LSI); |