diff options
-rw-r--r-- | include/clang/Sema/ScopeInfo.h | 42 | ||||
-rw-r--r-- | include/clang/Sema/Sema.h | 7 | ||||
-rw-r--r-- | lib/Sema/ScopeInfo.cpp | 14 | ||||
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 8 | ||||
-rw-r--r-- | lib/Sema/SemaExpr.cpp | 81 | ||||
-rw-r--r-- | lib/Sema/SemaExprCXX.cpp | 63 | ||||
-rw-r--r-- | lib/Sema/SemaLambda.cpp | 70 | ||||
-rw-r--r-- | lib/Sema/SemaStmt.cpp | 15 | ||||
-rw-r--r-- | lib/Sema/TreeTransform.h | 2 | ||||
-rw-r--r-- | test/AST/ast-dump-expr.cpp | 14 |
10 files changed, 142 insertions, 174 deletions
diff --git a/include/clang/Sema/ScopeInfo.h b/include/clang/Sema/ScopeInfo.h index 9b4d9638d2..375d93111a 100644 --- a/include/clang/Sema/ScopeInfo.h +++ b/include/clang/Sema/ScopeInfo.h @@ -507,8 +507,13 @@ class Capture { Cap_ByCopy, Cap_ByRef, Cap_Block, Cap_VLA }; - /// If !CapturesThis, the captured variable. - VarDecl *CapturedVar = nullptr; + union { + /// If Kind == Cap_VLA, the captured type. + const VariableArrayType *CapturedVLA; + + /// Otherwise, the captured variable (if any). + VarDecl *CapturedVar; + }; /// Expression to initialize a field of the given type. This is only required /// if we are capturing ByVal and the variable's type has a non-trivial copy @@ -553,8 +558,7 @@ public: Expr *Cpy, bool Invalid) : CapturedVar(Var), InitExpr(Cpy), Loc(Loc), EllipsisLoc(EllipsisLoc), CaptureType(CaptureType), - Kind(!Var ? Cap_VLA - : Block ? Cap_Block : ByRef ? Cap_ByRef : Cap_ByCopy), + Kind(Block ? Cap_Block : ByRef ? Cap_ByRef : Cap_ByCopy), Nested(IsNested), CapturesThis(false), ODRUsed(false), NonODRUsed(false), Invalid(Invalid) {} @@ -566,6 +570,13 @@ public: CapturesThis(true), ODRUsed(false), NonODRUsed(false), Invalid(Invalid) {} + enum IsVLACapture { VLACapture }; + Capture(IsVLACapture, const VariableArrayType *VLA, bool IsNested, + SourceLocation Loc, QualType CaptureType) + : CapturedVLA(VLA), Loc(Loc), CaptureType(CaptureType), Kind(Cap_VLA), + Nested(IsNested), CapturesThis(false), ODRUsed(false), + NonODRUsed(false), Invalid(false) {} + bool isThisCapture() const { return CapturesThis; } bool isVariableCapture() const { return !isThisCapture() && !isVLATypeCapture(); @@ -594,6 +605,11 @@ public: return CapturedVar; } + const VariableArrayType *getCapturedVLAType() const { + assert(isVLATypeCapture()); + return CapturedVLA; + } + /// Retrieve the location at which this variable was captured. SourceLocation getLocation() const { return Loc; } @@ -653,17 +669,13 @@ public: CaptureMap[Var] = Captures.size(); } - void addVLATypeCapture(SourceLocation Loc, QualType CaptureType) { - Captures.push_back(Capture(/*Var*/ nullptr, /*isBlock*/ false, - /*isByref*/ false, /*isNested*/ false, Loc, - /*EllipsisLoc*/ SourceLocation(), CaptureType, - /*Cpy*/ nullptr, /*Invalid*/ false)); + void addVLATypeCapture(SourceLocation Loc, const VariableArrayType *VLAType, + QualType CaptureType) { + Captures.push_back(Capture(Capture::VLACapture, VLAType, + /*FIXME: IsNested*/ false, Loc, CaptureType)); } - // Note, we do not need to add the type of 'this' since that is always - // retrievable from Sema::getCurrentThisType - and is also encoded within the - // type of the corresponding FieldDecl. - void addThisCapture(bool isNested, SourceLocation Loc, + void addThisCapture(bool isNested, SourceLocation Loc, QualType CaptureType, Expr *Cpy, bool ByCopy); /// Determine whether the C++ 'this' is captured. @@ -1010,9 +1022,9 @@ void FunctionScopeInfo::recordUseOfWeak(const ExprT *E, bool IsRead) { inline void CapturingScopeInfo::addThisCapture(bool isNested, SourceLocation Loc, - Expr *Cpy, + QualType CaptureType, Expr *Cpy, const bool ByCopy) { - Captures.push_back(Capture(Capture::ThisCapture, isNested, Loc, QualType(), + Captures.push_back(Capture(Capture::ThisCapture, isNested, Loc, CaptureType, Cpy, ByCopy, /*Invalid*/ false)); CXXThisCaptureIndex = Captures.size(); } diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index db6435461e..d7486ec1c2 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -5739,8 +5739,8 @@ public: IdentifierInfo *Id, unsigned InitStyle, Expr *Init); - /// Build the implicit field for an init-capture. - FieldDecl *buildInitCaptureField(sema::LambdaScopeInfo *LSI, VarDecl *Var); + /// Add an init-capture to a lambda scope. + void addInitCapture(sema::LambdaScopeInfo *LSI, VarDecl *Var); /// Note that we have finished the explicit captures for the /// given lambda. @@ -5786,6 +5786,9 @@ public: bool DiagnoseUnusedLambdaCapture(SourceRange CaptureRange, const sema::Capture &From); + /// Build a FieldDecl suitable to hold the given capture. + FieldDecl *BuildCaptureField(RecordDecl *RD, const sema::Capture &Capture); + /// Complete a lambda-expression having processed and attached the /// lambda body. ExprResult BuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc, diff --git a/lib/Sema/ScopeInfo.cpp b/lib/Sema/ScopeInfo.cpp index 1003d2639c..dd309a2811 100644 --- a/lib/Sema/ScopeInfo.cpp +++ b/lib/Sema/ScopeInfo.cpp @@ -113,17 +113,9 @@ FunctionScopeInfo::WeakObjectProfileTy::getBaseInfo(const Expr *E) { } bool CapturingScopeInfo::isVLATypeCaptured(const VariableArrayType *VAT) const { - RecordDecl *RD = nullptr; - if (auto *LSI = dyn_cast<LambdaScopeInfo>(this)) - RD = LSI->Lambda; - else if (auto CRSI = dyn_cast<CapturedRegionScopeInfo>(this)) - RD = CRSI->TheRecordDecl; - - if (RD) - for (auto *FD : RD->fields()) { - if (FD->hasCapturedVLAType() && FD->getCapturedVLAType() == VAT) - return true; - } + for (auto &Cap : Captures) + if (Cap.isVLATypeCapture() && Cap.getCapturedVLAType() == VAT) + return true; return false; } diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 188e801b4c..fbc410f014 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -12942,11 +12942,11 @@ static void RebuildLambdaScopeInfo(CXXMethodDecl *CallOperator, CaptureType, /*Expr*/ nullptr, /*Invalid*/false); } else if (C.capturesThis()) { - LSI->addThisCapture(/*Nested*/ false, C.getLocation(), - /*Expr*/ nullptr, - C.getCaptureKind() == LCK_StarThis); + LSI->addThisCapture(/*Nested*/ false, C.getLocation(), I->getType(), + /*Expr*/ nullptr, C.getCaptureKind() == LCK_StarThis); } else { - LSI->addVLATypeCapture(C.getLocation(), I->getType()); + LSI->addVLATypeCapture(C.getLocation(), I->getCapturedVLAType(), + I->getType()); } ++I; } diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 95be7af8b6..8eccb4b0c5 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -4050,32 +4050,11 @@ static void captureVariablyModifiedType(ASTContext &Context, QualType T, // Unknown size indication requires no size computation. // Otherwise, evaluate and record it. - if (auto Size = VAT->getSizeExpr()) { - if (!CSI->isVLATypeCaptured(VAT)) { - RecordDecl *CapRecord = nullptr; - if (auto LSI = dyn_cast<LambdaScopeInfo>(CSI)) { - CapRecord = LSI->Lambda; - } else if (auto CRSI = dyn_cast<CapturedRegionScopeInfo>(CSI)) { - CapRecord = CRSI->TheRecordDecl; - } - if (CapRecord) { - auto ExprLoc = Size->getExprLoc(); - auto SizeType = Context.getSizeType(); - // Build the non-static data member. - auto Field = - FieldDecl::Create(Context, CapRecord, ExprLoc, ExprLoc, - /*Id*/ nullptr, SizeType, /*TInfo*/ nullptr, - /*BW*/ nullptr, /*Mutable*/ false, - /*InitStyle*/ ICIS_NoInit); - Field->setImplicit(true); - Field->setAccess(AS_private); - Field->setCapturedVLAType(VAT); - CapRecord->addDecl(Field); - - CSI->addVLATypeCapture(ExprLoc, SizeType); - } - } - } + auto Size = VAT->getSizeExpr(); + if (Size && !CSI->isVLATypeCaptured(VAT) && + (isa<CapturedRegionScopeInfo>(CSI) || isa<LambdaScopeInfo>(CSI))) + CSI->addVLATypeCapture(Size->getExprLoc(), VAT, Context.getSizeType()); + T = VAT->getElementType(); break; } @@ -15367,18 +15346,6 @@ static bool captureInCapturedRegion(CapturedRegionScopeInfo *RSI, // The current implementation assumes that all variables are captured // by references. Since there is no capture by copy, no expression // evaluation will be needed. - RecordDecl *RD = RSI->TheRecordDecl; - - FieldDecl *Field - = FieldDecl::Create(S.Context, RD, Loc, Loc, nullptr, CaptureType, - S.Context.getTrivialTypeSourceInfo(CaptureType, Loc), - nullptr, false, ICIS_NoInit); - Field->setImplicit(true); - Field->setAccess(AS_private); - RD->addDecl(Field); - if (S.getLangOpts().OpenMP && RSI->CapRegionKind == CR_OpenMP) - S.setOpenMPCaptureKind(Field, Var, RSI->OpenMPLevel); - CopyExpr = new (S.Context) DeclRefExpr( S.Context, Var, RefersToCapturedVariable, DeclRefType, VK_LValue, Loc); Var->setReferenced(true); @@ -15394,39 +15361,6 @@ static bool captureInCapturedRegion(CapturedRegionScopeInfo *RSI, return !Invalid; } -/// Create a field within the lambda class for the variable -/// being captured. -static void addAsFieldToClosureType(Sema &S, LambdaScopeInfo *LSI, - QualType FieldType, QualType DeclRefType, - SourceLocation Loc, - bool RefersToCapturedVariable) { - CXXRecordDecl *Lambda = LSI->Lambda; - - // Build the non-static data member. - FieldDecl *Field - = FieldDecl::Create(S.Context, Lambda, Loc, Loc, nullptr, FieldType, - S.Context.getTrivialTypeSourceInfo(FieldType, Loc), - nullptr, false, ICIS_NoInit); - // If the variable being captured has an invalid type, mark the lambda class - // as invalid as well. - if (!FieldType->isDependentType()) { - if (S.RequireCompleteType(Loc, FieldType, diag::err_field_incomplete)) { - Lambda->setInvalidDecl(); - Field->setInvalidDecl(); - } else { - NamedDecl *Def; - FieldType->isIncompleteType(&Def); - if (Def && Def->isInvalidDecl()) { - Lambda->setInvalidDecl(); - Field->setInvalidDecl(); - } - } - } - Field->setImplicit(true); - Field->setAccess(AS_private); - Lambda->addDecl(Field); -} - /// Capture the given variable in the lambda. static bool captureInLambda(LambdaScopeInfo *LSI, VarDecl *Var, @@ -15504,11 +15438,6 @@ static bool captureInLambda(LambdaScopeInfo *LSI, } } - // Capture this variable in the lambda. - if (BuildAndDiagnose && !Invalid) - addAsFieldToClosureType(S, LSI, CaptureType, DeclRefType, Loc, - RefersToCapturedVariable); - // Compute the type of a reference to this captured variable. if (ByRef) DeclRefType = CaptureType.getNonReferenceType(); diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index ef27fc2d71..00b158debc 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -1135,39 +1135,15 @@ Sema::CXXThisScopeRAII::~CXXThisScopeRAII() { } static Expr *captureThis(Sema &S, ASTContext &Context, RecordDecl *RD, - QualType ThisTy, SourceLocation Loc, - const bool ByCopy) { - - QualType AdjustedThisTy = ThisTy; - // The type of the corresponding data member (not a 'this' pointer if 'by - // copy'). - QualType CaptureThisFieldTy = ThisTy; - if (ByCopy) { - // If we are capturing the object referred to by '*this' by copy, ignore any - // cv qualifiers inherited from the type of the member function for the type - // of the closure-type's corresponding data member and any use of 'this'. - CaptureThisFieldTy = ThisTy->getPointeeType(); - CaptureThisFieldTy.removeLocalCVRQualifiers(Qualifiers::CVRMask); - AdjustedThisTy = Context.getPointerType(CaptureThisFieldTy); - } - - FieldDecl *Field = FieldDecl::Create( - Context, RD, Loc, Loc, nullptr, CaptureThisFieldTy, - Context.getTrivialTypeSourceInfo(CaptureThisFieldTy, Loc), nullptr, false, - ICIS_NoInit); - - Field->setImplicit(true); - Field->setAccess(AS_private); - RD->addDecl(Field); - Expr *This = - new (Context) CXXThisExpr(Loc, ThisTy, /*isImplicit*/ true); + QualType ThisTy, QualType CaptureType, + SourceLocation Loc, const bool ByCopy) { + Expr *This = new (Context) CXXThisExpr(Loc, ThisTy, /*isImplicit*/ true); if (ByCopy) { - Expr *StarThis = S.CreateBuiltinUnaryOp(Loc, - UO_Deref, - This).get(); - InitializedEntity Entity = InitializedEntity::InitializeLambdaCapture( - nullptr, CaptureThisFieldTy, Loc); - InitializationKind InitKind = InitializationKind::CreateDirect(Loc, Loc, Loc); + Expr *StarThis = S.CreateBuiltinUnaryOp(Loc, UO_Deref, This).get(); + InitializedEntity Entity = + InitializedEntity::InitializeLambdaCapture(nullptr, CaptureType, Loc); + InitializationKind InitKind = + InitializationKind::CreateDirect(Loc, Loc, Loc); InitializationSequence Init(S, Entity, InitKind, StarThis); ExprResult ER = Init.Perform(S, Entity, InitKind, StarThis); if (ER.isInvalid()) return nullptr; @@ -1273,21 +1249,32 @@ bool Sema::CheckCXXThisCapture(SourceLocation Loc, const bool Explicit, CapturingScopeInfo *CSI = cast<CapturingScopeInfo>(FunctionScopes[idx]); Expr *ThisExpr = nullptr; + // The type of the corresponding data member (not a 'this' pointer if 'by + // copy'). + QualType CaptureType = ThisTy; + if (ByCopy) { + // If we are capturing the object referred to by '*this' by copy, ignore + // any cv qualifiers inherited from the type of the member function for + // the type of the closure-type's corresponding data member and any use + // of 'this'. + CaptureType = ThisTy->getPointeeType(); + CaptureType.removeLocalCVRQualifiers(Qualifiers::CVRMask); + } + if (LambdaScopeInfo *LSI = dyn_cast<LambdaScopeInfo>(CSI)) { // For lambda expressions, build a field and an initializing expression, // and capture the *enclosing object* by copy only if this is the first // iteration. - ThisExpr = captureThis(*this, Context, LSI->Lambda, ThisTy, Loc, - ByCopy && idx == MaxFunctionScopesIndex); + ThisExpr = captureThis(*this, Context, LSI->Lambda, ThisTy, CaptureType, + Loc, ByCopy && idx == MaxFunctionScopesIndex); } else if (CapturedRegionScopeInfo *RSI = dyn_cast<CapturedRegionScopeInfo>(FunctionScopes[idx])) - ThisExpr = - captureThis(*this, Context, RSI->TheRecordDecl, ThisTy, Loc, - false/*ByCopy*/); + ThisExpr = captureThis(*this, Context, RSI->TheRecordDecl, ThisTy, + CaptureType, Loc, false /*ByCopy*/); bool isNested = NumCapturingClosures > 1; - CSI->addThisCapture(isNested, Loc, ThisExpr, ByCopy); + CSI->addThisCapture(isNested, Loc, CaptureType, ThisExpr, ByCopy); } return false; } diff --git a/lib/Sema/SemaLambda.cpp b/lib/Sema/SemaLambda.cpp index f6c9dee2a0..6d487cc832 100644 --- a/lib/Sema/SemaLambda.cpp +++ b/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(); diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp index 51a72c618b..357e257abe 100644 --- a/lib/Sema/SemaStmt.cpp +++ b/lib/Sema/SemaStmt.cpp @@ -4224,13 +4224,16 @@ Sema::CreateCapturedStmtRecordDecl(CapturedDecl *&CD, SourceLocation Loc, } static void -buildCapturedStmtCaptureList(SmallVectorImpl<CapturedStmt::Capture> &Captures, - SmallVectorImpl<Expr *> &CaptureInits, - ArrayRef<sema::Capture> Candidates) { - for (const sema::Capture &Cap : Candidates) { +buildCapturedStmtCaptureList(Sema &S, CapturedRegionScopeInfo *RSI, + SmallVectorImpl<CapturedStmt::Capture> &Captures, + SmallVectorImpl<Expr *> &CaptureInits) { + for (const sema::Capture &Cap : RSI->Captures) { if (Cap.isInvalid()) continue; + // Create a field for this capture. + FieldDecl *Field = S.BuildCaptureField(RSI->TheRecordDecl, Cap); + if (Cap.isThisCapture()) { Captures.push_back(CapturedStmt::Capture(Cap.getLocation(), CapturedStmt::VCK_This)); @@ -4243,6 +4246,8 @@ buildCapturedStmtCaptureList(SmallVectorImpl<CapturedStmt::Capture> &Captures, continue; } + if (S.getLangOpts().OpenMP && RSI->CapRegionKind == CR_OpenMP) + S.setOpenMPCaptureKind(Field, Cap.getVariable(), RSI->OpenMPLevel); Captures.push_back(CapturedStmt::Capture(Cap.getLocation(), Cap.isReferenceCapture() ? CapturedStmt::VCK_ByRef @@ -4360,7 +4365,7 @@ StmtResult Sema::ActOnCapturedRegionEnd(Stmt *S) { SmallVector<CapturedStmt::Capture, 4> Captures; SmallVector<Expr *, 4> CaptureInits; - buildCapturedStmtCaptureList(Captures, CaptureInits, RSI->Captures); + buildCapturedStmtCaptureList(*this, RSI, Captures, CaptureInits); CapturedDecl *CD = RSI->TheCapturedDecl; RecordDecl *RD = RSI->TheRecordDecl; diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h index b5114eeef3..6620885f23 100644 --- a/lib/Sema/TreeTransform.h +++ b/lib/Sema/TreeTransform.h @@ -11382,7 +11382,7 @@ TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) { break; } NewVDs.push_back(NewVD); - getSema().buildInitCaptureField(LSI, NewVD); + getSema().addInitCapture(LSI, NewVD); } if (Invalid) diff --git a/test/AST/ast-dump-expr.cpp b/test/AST/ast-dump-expr.cpp index 96d3df34cb..693dd57307 100644 --- a/test/AST/ast-dump-expr.cpp +++ b/test/AST/ast-dump-expr.cpp @@ -252,9 +252,9 @@ void PrimaryExpressions(Ts... a) { // CHECK-NEXT: CopyAssignment // CHECK-NEXT: MoveAssignment // CHECK-NEXT: Destructor - // CHECK-NEXT: FieldDecl 0x{{[^ ]*}} <col:8> col:8 implicit 'V *' // CHECK-NEXT: CXXMethodDecl // CHECK-NEXT: CompoundStmt + // CHECK-NEXT: FieldDecl 0x{{[^ ]*}} <col:8> col:8 implicit 'V *' // CHECK-NEXT: CXXThisExpr 0x{{[^ ]*}} <col:8> 'V *' implicit this [*this]{}; @@ -267,9 +267,9 @@ void PrimaryExpressions(Ts... a) { // CHECK-NEXT: CopyAssignment // CHECK-NEXT: MoveAssignment // CHECK-NEXT: Destructor - // CHECK-NEXT: FieldDecl 0x{{[^ ]*}} <col:8> col:8 implicit 'V' // CHECK-NEXT: CXXMethodDecl // CHECK-NEXT: CompoundStmt + // CHECK-NEXT: FieldDecl 0x{{[^ ]*}} <col:8> col:8 implicit 'V' // CHECK-NEXT: ParenListExpr 0x{{[^ ]*}} <col:8> 'NULL TYPE' // CHECK-NEXT: UnaryOperator 0x{{[^ ]*}} <col:8> '<dependent type>' prefix '*' cannot overflow // CHECK-NEXT: CXXThisExpr 0x{{[^ ]*}} <col:8> 'V *' implicit this @@ -322,9 +322,9 @@ void PrimaryExpressions(Ts... a) { // CHECK-NEXT: CopyAssignment // CHECK-NEXT: MoveAssignment // CHECK-NEXT: Destructor - // CHECK-NEXT: FieldDecl 0x{{[^ ]*}} <col:4> col:4 implicit 'Ts...' // CHECK-NEXT: CXXMethodDecl 0x{{[^ ]*}} <col:8, col:10> col:3 operator() 'auto () const -> auto' inline // CHECK-NEXT: CompoundStmt + // CHECK-NEXT: FieldDecl 0x{{[^ ]*}} <col:4> col:4 implicit 'Ts...' // CHECK-NEXT: ParenListExpr 0x{{[^ ]*}} <col:4> 'NULL TYPE' // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:4> 'Ts...' lvalue ParmVar 0x{{[^ ]*}} 'a' 'Ts...' // CHECK-NEXT: CompoundStmt 0x{{[^ ]*}} <col:9, col:10> @@ -403,8 +403,6 @@ void PrimaryExpressions(Ts... a) { // CHECK-NEXT: CopyAssignment // CHECK-NEXT: MoveAssignment // CHECK-NEXT: Destructor - // CHECK-NEXT: FieldDecl 0x{{[^ ]*}} <col:4> col:4 implicit 'int' - // CHECK-NEXT: FieldDecl 0x{{[^ ]*}} <col:8> col:8 implicit 'int &' // CHECK-NEXT: CXXMethodDecl 0x{{[^ ]*}} <col:9, col:26> col:3 operator() 'auto () const -> auto' inline // CHECK-NEXT: CompoundStmt // CHECK-NEXT: ReturnStmt 0x{{[^ ]*}} <col:12, col:23> @@ -413,6 +411,8 @@ void PrimaryExpressions(Ts... a) { // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:19> 'const int' lvalue Var 0x{{[^ ]*}} 'b' 'int' // CHECK-NEXT: ImplicitCastExpr // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:23> 'int' lvalue Var 0x{{[^ ]*}} 'c' 'int' + // CHECK-NEXT: FieldDecl 0x{{[^ ]*}} <col:4> col:4 implicit 'int' + // CHECK-NEXT: FieldDecl 0x{{[^ ]*}} <col:8> col:8 implicit 'int &' // CHECK-NEXT: ImplicitCastExpr // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:4> 'int' lvalue Var 0x{{[^ ]*}} 'b' 'int' // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:8> 'int' lvalue Var 0x{{[^ ]*}} 'c' 'int' @@ -434,10 +434,10 @@ void PrimaryExpressions(Ts... a) { // CHECK-NEXT: CopyAssignment // CHECK-NEXT: MoveAssignment // CHECK-NEXT: Destructor - // CHECK-NEXT: FieldDecl 0x{{[^ ]*}} <col:4> col:4 implicit 'Ts...' - // CHECK-NEXT: FieldDecl 0x{{[^ ]*}} <col:10> col:10 implicit 'int':'int' // CHECK-NEXT: CXXMethodDecl 0x{{[^ ]*}} <col:16, col:18> col:3 operator() 'auto () const -> auto' inline // CHECK-NEXT: CompoundStmt + // CHECK-NEXT: FieldDecl 0x{{[^ ]*}} <col:4> col:4 implicit 'Ts...' + // CHECK-NEXT: FieldDecl 0x{{[^ ]*}} <col:10> col:10 implicit 'int':'int' // CHECK-NEXT: ParenListExpr 0x{{[^ ]*}} <col:4> 'NULL TYPE' // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:4> 'Ts...' lvalue ParmVar 0x{{[^ ]*}} 'a' 'Ts...' // CHECK-NEXT: IntegerLiteral 0x{{[^ ]*}} <col:14> 'int' 12 |