diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2019-06-02 04:00:43 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2019-06-02 04:00:43 +0000 |
commit | e518235aca345ad5dd708dd26c632e06122ffb09 (patch) | |
tree | 6e8ffbe189029c8380731691813c1dba048094ea /clang/lib/Sema/SemaLambda.cpp | |
parent | 2e2c02c0cdd45a59faf81bd5c87688b21a5a0d9a (diff) | |
download | bcm5719-llvm-e518235aca345ad5dd708dd26c632e06122ffb09.tar.gz bcm5719-llvm-e518235aca345ad5dd708dd26c632e06122ffb09.zip |
Factor out commonality between variable capture initialization and
'this' capture initialization.
llvm-svn: 362317
Diffstat (limited to 'clang/lib/Sema/SemaLambda.cpp')
-rw-r--r-- | clang/lib/Sema/SemaLambda.cpp | 153 |
1 files changed, 83 insertions, 70 deletions
diff --git a/clang/lib/Sema/SemaLambda.cpp b/clang/lib/Sema/SemaLambda.cpp index d3f3b60926f..4b832f56530 100644 --- a/clang/lib/Sema/SemaLambda.cpp +++ b/clang/lib/Sema/SemaLambda.cpp @@ -1431,32 +1431,22 @@ static void addBlockPointerConversion(Sema &S, Class->addDecl(Conversion); } -ExprResult Sema::performThisCaptureInitialization(const Capture &Cap, - bool IsImplicit) { - QualType ThisTy = getCurrentThisType(); - SourceLocation Loc = Cap.getLocation(); - Expr *This = BuildCXXThisExpr(Loc, ThisTy, IsImplicit); - if (Cap.isReferenceCapture()) - return This; - - // Capture (by copy) of '*this'. - Expr *StarThis = CreateBuiltinUnaryOp(Loc, UO_Deref, This).get(); - InitializedEntity Entity = InitializedEntity::InitializeLambdaCapture( - nullptr, Cap.getCaptureType(), Loc); - InitializationKind InitKind = - InitializationKind::CreateDirect(Loc, Loc, Loc); - InitializationSequence Init(*this, Entity, InitKind, StarThis); - return Init.Perform(*this, Entity, InitKind, StarThis); -} - -static ExprResult performLambdaVarCaptureInitialization( - Sema &S, const Capture &Capture, FieldDecl *Field, - SourceLocation ImplicitCaptureLoc, bool IsImplicitCapture) { - assert(Capture.isVariableCapture() && "not a variable capture"); - - auto *Var = Capture.getVariable(); +ExprResult Sema::BuildCaptureInit(const Capture &Cap, + SourceLocation ImplicitCaptureLoc, + bool IsOpenMPMapping) { + // VLA captures don't have a stored initialization expression. + if (Cap.isVLATypeCapture()) + return ExprResult(); + + // An init-capture is initialized directly from its stored initializer. + if (Cap.isInitCapture()) + return Cap.getVariable()->getInit(); + + // For anything else, build an initialization expression. For an implicit + // capture, the capture notionally happens at the capture-default, so use + // that location here. SourceLocation Loc = - IsImplicitCapture ? ImplicitCaptureLoc : Capture.getLocation(); + ImplicitCaptureLoc.isValid() ? ImplicitCaptureLoc : Cap.getLocation(); // C++11 [expr.prim.lambda]p21: // When the lambda-expression is evaluated, the entities that @@ -1470,17 +1460,39 @@ static ExprResult performLambdaVarCaptureInitialization( // C++ [expr.prim.lambda]p12: // An entity captured by a lambda-expression is odr-used (3.2) in // the scope containing the lambda-expression. - ExprResult RefResult = S.BuildDeclarationNameExpr( + ExprResult Init; + IdentifierInfo *Name = nullptr; + if (Cap.isThisCapture()) { + QualType ThisTy = getCurrentThisType(); + Expr *This = BuildCXXThisExpr(Loc, ThisTy, ImplicitCaptureLoc.isValid()); + if (Cap.isCopyCapture()) + Init = CreateBuiltinUnaryOp(Loc, UO_Deref, This); + else + Init = This; + } else { + assert(Cap.isVariableCapture() && "unknown kind of capture"); + VarDecl *Var = Cap.getVariable(); + Name = Var->getIdentifier(); + Init = BuildDeclarationNameExpr( CXXScopeSpec(), DeclarationNameInfo(Var->getDeclName(), Loc), Var); - if (RefResult.isInvalid()) + } + + // In OpenMP, the capture kind doesn't actually describe how to capture: + // variables are "mapped" onto the device in a process that does not formally + // make a copy, even for a "copy capture". + if (IsOpenMPMapping) + return Init; + + if (Init.isInvalid()) return ExprError(); - Expr *Ref = RefResult.get(); - auto Entity = InitializedEntity::InitializeLambdaCapture( - Var->getIdentifier(), Field->getType(), Loc); - InitializationKind InitKind = InitializationKind::CreateDirect(Loc, Loc, Loc); - InitializationSequence Init(S, Entity, InitKind, Ref); - return Init.Perform(S, Entity, InitKind, Ref); + Expr *InitExpr = Init.get(); + InitializedEntity Entity = InitializedEntity::InitializeLambdaCapture( + Name, Cap.getCaptureType(), Loc); + InitializationKind InitKind = + InitializationKind::CreateDirect(Loc, Loc, Loc); + InitializationSequence InitSeq(*this, Entity, InitKind, InitExpr); + return InitSeq.Perform(*this, Entity, InitKind, InitExpr); } ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc, Stmt *Body, @@ -1647,14 +1659,18 @@ ExprResult Sema::BuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc, assert(!From.isBlockCapture() && "Cannot capture __block variables"); bool IsImplicit = I >= LSI->NumExplicitCaptures; + SourceLocation ImplicitCaptureLoc = + IsImplicit ? CaptureDefaultLoc : SourceLocation(); // Use source ranges of explicit captures for fixits where available. SourceRange CaptureRange = LSI->ExplicitCaptureRanges[I]; // Warn about unused explicit captures. bool IsCaptureUsed = true; - if (!CurContext->isDependentContext() && !IsImplicit && !From.isODRUsed()) { + if (!CurContext->isDependentContext() && !IsImplicit && + !From.isODRUsed()) { // Initialized captures that are non-ODR used may not be eliminated. + // FIXME: Where did the IsGenericLambda here come from? bool NonODRUsedInitCapture = IsGenericLambda && From.isNonODRUsed() && From.isInitCapture(); if (!NonODRUsedInitCapture) { @@ -1682,46 +1698,43 @@ ExprResult Sema::BuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc, PrevCaptureLoc = CaptureRange.getEnd(); } - // Add a FieldDecl for the capture. - FieldDecl *Field = BuildCaptureField(Class, From); - - // Handle 'this' capture. - if (From.isThisCapture()) { - // Capturing 'this' implicitly with a default of '[=]' is deprecated, - // because it results in a reference capture. Don't warn prior to - // C++2a; there's nothing that can be done about it before then. - if (getLangOpts().CPlusPlus2a && IsImplicit && - CaptureDefault == LCD_ByCopy) { - Diag(From.getLocation(), diag::warn_deprecated_this_capture); - Diag(CaptureDefaultLoc, diag::note_deprecated_this_capture) - << FixItHint::CreateInsertion( - getLocForEndOfToken(CaptureDefaultLoc), ", this"); + // Map the capture to our AST representation. + LambdaCapture Capture = [&] { + if (From.isThisCapture()) { + // Capturing 'this' implicitly with a default of '[=]' is deprecated, + // because it results in a reference capture. Don't warn prior to + // C++2a; there's nothing that can be done about it before then. + if (getLangOpts().CPlusPlus2a && IsImplicit && + CaptureDefault == LCD_ByCopy) { + Diag(From.getLocation(), diag::warn_deprecated_this_capture); + Diag(CaptureDefaultLoc, diag::note_deprecated_this_capture) + << FixItHint::CreateInsertion( + getLocForEndOfToken(CaptureDefaultLoc), ", this"); + } + return LambdaCapture(From.getLocation(), IsImplicit, + From.isCopyCapture() ? LCK_StarThis : LCK_This); + } else if (From.isVLATypeCapture()) { + return LambdaCapture(From.getLocation(), IsImplicit, LCK_VLAType); + } else { + assert(From.isVariableCapture() && "unknown kind of capture"); + VarDecl *Var = From.getVariable(); + LambdaCaptureKind Kind = + From.isCopyCapture() ? LCK_ByCopy : LCK_ByRef; + return LambdaCapture(From.getLocation(), IsImplicit, Kind, Var, + From.getEllipsisLoc()); } + }(); - ExprResult Init = performThisCaptureInitialization(From, IsImplicit); - Captures.push_back( - LambdaCapture(From.getLocation(), IsImplicit, - From.isCopyCapture() ? LCK_StarThis : LCK_This)); - CaptureInits.push_back(Init.get()); - continue; - } - if (From.isVLATypeCapture()) { - Captures.push_back( - LambdaCapture(From.getLocation(), IsImplicit, LCK_VLAType)); - CaptureInits.push_back(nullptr); - continue; - } + // Form the initializer for the capture field. + ExprResult Init = BuildCaptureInit(From, ImplicitCaptureLoc); - VarDecl *Var = From.getVariable(); - LambdaCaptureKind Kind = From.isCopyCapture() ? LCK_ByCopy : LCK_ByRef; - Captures.push_back(LambdaCapture(From.getLocation(), IsImplicit, Kind, - Var, From.getEllipsisLoc())); + // FIXME: Skip this capture if the capture is not used, the initializer + // has no side-effects, the type of the capture is trivial, and the + // lambda is not externally visible. - ExprResult Init = - From.isInitCapture() - ? Var->getInit() - : performLambdaVarCaptureInitialization( - *this, From, Field, CaptureDefaultLoc, IsImplicit); + // Add a FieldDecl for the capture and form its initializer. + BuildCaptureField(Class, From); + Captures.push_back(Capture); CaptureInits.push_back(Init.get()); } |