summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang/Sema/ScopeInfo.h42
-rw-r--r--include/clang/Sema/Sema.h7
-rw-r--r--lib/Sema/ScopeInfo.cpp14
-rw-r--r--lib/Sema/SemaDecl.cpp8
-rw-r--r--lib/Sema/SemaExpr.cpp81
-rw-r--r--lib/Sema/SemaExprCXX.cpp63
-rw-r--r--lib/Sema/SemaLambda.cpp70
-rw-r--r--lib/Sema/SemaStmt.cpp15
-rw-r--r--lib/Sema/TreeTransform.h2
-rw-r--r--test/AST/ast-dump-expr.cpp14
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