diff options
Diffstat (limited to 'lib/Sema')
-rw-r--r-- | lib/Sema/SemaExpr.cpp | 5 | ||||
-rw-r--r-- | lib/Sema/SemaLambda.cpp | 22 | ||||
-rw-r--r-- | lib/Sema/TreeTransform.h | 51 |
3 files changed, 67 insertions, 11 deletions
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); |