diff options
Diffstat (limited to 'clang/lib/Sema/SemaLambda.cpp')
-rw-r--r-- | clang/lib/Sema/SemaLambda.cpp | 70 |
1 files changed, 55 insertions, 15 deletions
diff --git a/clang/lib/Sema/SemaLambda.cpp b/clang/lib/Sema/SemaLambda.cpp index f6c9dee2a08..6d487cc8325 100644 --- a/clang/lib/Sema/SemaLambda.cpp +++ b/clang/lib/Sema/SemaLambda.cpp @@ -843,19 +843,10 @@ VarDecl *Sema::createLambdaInitCaptureVarDecl(SourceLocation Loc, return NewVD; } -FieldDecl *Sema::buildInitCaptureField(LambdaScopeInfo *LSI, VarDecl *Var) { - FieldDecl *Field = FieldDecl::Create( - Context, LSI->Lambda, Var->getLocation(), Var->getLocation(), - nullptr, Var->getType(), Var->getTypeSourceInfo(), nullptr, false, - ICIS_NoInit); - Field->setImplicit(true); - Field->setAccess(AS_private); - LSI->Lambda->addDecl(Field); - +void Sema::addInitCapture(LambdaScopeInfo *LSI, VarDecl *Var) { LSI->addCapture(Var, /*isBlock*/false, Var->getType()->isReferenceType(), /*isNested*/false, Var->getLocation(), SourceLocation(), Var->getType(), Var->getInit(), /*Invalid*/false); - return Field; } void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro, @@ -1182,7 +1173,7 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro, } if (C->Init.isUsable()) { - buildInitCaptureField(LSI, Var); + addInitCapture(LSI, Var); } else { TryCaptureKind Kind = C->Kind == LCK_ByRef ? TryCapture_ExplicitByRef : TryCapture_ExplicitByVal; @@ -1539,6 +1530,54 @@ bool Sema::DiagnoseUnusedLambdaCapture(SourceRange CaptureRange, return true; } +/// Create a field within the lambda class or captured statement record for the +/// given capture. +FieldDecl *Sema::BuildCaptureField(RecordDecl *RD, + const sema::Capture &Capture) { + SourceLocation Loc = Capture.getLocation(); + QualType FieldType = Capture.getCaptureType(); + + TypeSourceInfo *TSI = nullptr; + if (Capture.isVariableCapture()) { + auto *Var = Capture.getVariable(); + if (Var->isInitCapture()) + TSI = Capture.getVariable()->getTypeSourceInfo(); + } + + // FIXME: Should we really be doing this? A null TypeSourceInfo seems more + // appropriate, at least for an implicit capture. + if (!TSI) + TSI = Context.getTrivialTypeSourceInfo(FieldType, Loc); + + // Build the non-static data member. + FieldDecl *Field = + FieldDecl::Create(Context, RD, Loc, Loc, nullptr, FieldType, TSI, nullptr, + false, ICIS_NoInit); + // If the variable being captured has an invalid type, mark the class as + // invalid as well. + if (!FieldType->isDependentType()) { + if (RequireCompleteType(Loc, FieldType, diag::err_field_incomplete)) { + RD->setInvalidDecl(); + Field->setInvalidDecl(); + } else { + NamedDecl *Def; + FieldType->isIncompleteType(&Def); + if (Def && Def->isInvalidDecl()) { + RD->setInvalidDecl(); + Field->setInvalidDecl(); + } + } + } + Field->setImplicit(true); + Field->setAccess(AS_private); + RD->addDecl(Field); + + if (Capture.isVLATypeCapture()) + Field->setCapturedVLAType(Capture.getCapturedVLAType()); + + return Field; +} + ExprResult Sema::BuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc, LambdaScopeInfo *LSI) { // Collect information from the lambda scope. @@ -1576,14 +1615,12 @@ ExprResult Sema::BuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc, PopExpressionEvaluationContext(); - // Translate captures. - auto CurField = Class->field_begin(); // True if the current capture has a used capture or default before it. bool CurHasPreviousCapture = CaptureDefault != LCD_None; SourceLocation PrevCaptureLoc = CurHasPreviousCapture ? CaptureDefaultLoc : IntroducerRange.getBegin(); - for (unsigned I = 0, N = LSI->Captures.size(); I != N; ++I, ++CurField) { + for (unsigned I = 0, N = LSI->Captures.size(); I != N; ++I) { const Capture &From = LSI->Captures[I]; if (From.isInvalid()) @@ -1626,6 +1663,9 @@ 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, @@ -1659,7 +1699,7 @@ ExprResult Sema::BuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc, Expr *Init = From.getInitExpr(); if (!Init) { auto InitResult = performLambdaVarCaptureInitialization( - *this, From, *CurField, CaptureDefaultLoc, IsImplicit); + *this, From, Field, CaptureDefaultLoc, IsImplicit); if (InitResult.isInvalid()) return ExprError(); Init = InitResult.get(); |