summaryrefslogtreecommitdiffstats
path: root/clang/lib/Sema/SemaExpr.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/Sema/SemaExpr.cpp')
-rw-r--r--clang/lib/Sema/SemaExpr.cpp153
1 files changed, 23 insertions, 130 deletions
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index d18aeab57a0..493ebe78269 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -12534,13 +12534,11 @@ static bool captureInCapturedRegion(CapturedRegionScopeInfo *RSI,
}
/// \brief Create a field within the lambda class for the variable
-/// being captured. Handle Array captures.
-static ExprResult addAsFieldToClosureType(Sema &S,
- LambdaScopeInfo *LSI,
- VarDecl *Var, QualType FieldType,
- QualType DeclRefType,
- SourceLocation Loc,
- bool RefersToCapturedVariable) {
+/// being captured.
+static void addAsFieldToClosureType(Sema &S, LambdaScopeInfo *LSI, VarDecl *Var,
+ QualType FieldType, QualType DeclRefType,
+ SourceLocation Loc,
+ bool RefersToCapturedVariable) {
CXXRecordDecl *Lambda = LSI->Lambda;
// Build the non-static data member.
@@ -12551,111 +12549,8 @@ static ExprResult addAsFieldToClosureType(Sema &S,
Field->setImplicit(true);
Field->setAccess(AS_private);
Lambda->addDecl(Field);
-
- // C++11 [expr.prim.lambda]p21:
- // When the lambda-expression is evaluated, the entities that
- // are captured by copy are used to direct-initialize each
- // corresponding non-static data member of the resulting closure
- // object. (For array members, the array elements are
- // direct-initialized in increasing subscript order.) These
- // initializations are performed in the (unspecified) order in
- // which the non-static data members are declared.
-
- // Introduce a new evaluation context for the initialization, so
- // that temporaries introduced as part of the capture are retained
- // to be re-"exported" from the lambda expression itself.
- EnterExpressionEvaluationContext scope(S, Sema::PotentiallyEvaluated);
-
- // C++ [expr.prim.labda]p12:
- // An entity captured by a lambda-expression is odr-used (3.2) in
- // the scope containing the lambda-expression.
- Expr *Ref = new (S.Context) DeclRefExpr(Var, RefersToCapturedVariable,
- DeclRefType, VK_LValue, Loc);
- Var->setReferenced(true);
- Var->markUsed(S.Context);
-
- // When the field has array type, create index variables for each
- // dimension of the array. We use these index variables to subscript
- // the source array, and other clients (e.g., CodeGen) will perform
- // the necessary iteration with these index variables.
- SmallVector<VarDecl *, 4> IndexVariables;
- QualType BaseType = FieldType;
- QualType SizeType = S.Context.getSizeType();
- LSI->ArrayIndexStarts.push_back(LSI->ArrayIndexVars.size());
- while (const ConstantArrayType *Array
- = S.Context.getAsConstantArrayType(BaseType)) {
- // Create the iteration variable for this array index.
- IdentifierInfo *IterationVarName = nullptr;
- {
- SmallString<8> Str;
- llvm::raw_svector_ostream OS(Str);
- OS << "__i" << IndexVariables.size();
- IterationVarName = &S.Context.Idents.get(OS.str());
- }
- VarDecl *IterationVar
- = VarDecl::Create(S.Context, S.CurContext, Loc, Loc,
- IterationVarName, SizeType,
- S.Context.getTrivialTypeSourceInfo(SizeType, Loc),
- SC_None);
- IndexVariables.push_back(IterationVar);
- LSI->ArrayIndexVars.push_back(IterationVar);
-
- // Create a reference to the iteration variable.
- ExprResult IterationVarRef
- = S.BuildDeclRefExpr(IterationVar, SizeType, VK_LValue, Loc);
- assert(!IterationVarRef.isInvalid() &&
- "Reference to invented variable cannot fail!");
- IterationVarRef = S.DefaultLvalueConversion(IterationVarRef.get());
- assert(!IterationVarRef.isInvalid() &&
- "Conversion of invented variable cannot fail!");
-
- // Subscript the array with this iteration variable.
- ExprResult Subscript = S.CreateBuiltinArraySubscriptExpr(
- Ref, Loc, IterationVarRef.get(), Loc);
- if (Subscript.isInvalid()) {
- S.CleanupVarDeclMarking();
- S.DiscardCleanupsInEvaluationContext();
- return ExprError();
- }
-
- Ref = Subscript.get();
- BaseType = Array->getElementType();
- }
-
- // Construct the entity that we will be initializing. For an array, this
- // will be first element in the array, which may require several levels
- // of array-subscript entities.
- SmallVector<InitializedEntity, 4> Entities;
- Entities.reserve(1 + IndexVariables.size());
- Entities.push_back(
- InitializedEntity::InitializeLambdaCapture(Var->getIdentifier(),
- Field->getType(), Loc));
- for (unsigned I = 0, N = IndexVariables.size(); I != N; ++I)
- Entities.push_back(InitializedEntity::InitializeElement(S.Context,
- 0,
- Entities.back()));
-
- InitializationKind InitKind
- = InitializationKind::CreateDirect(Loc, Loc, Loc);
- InitializationSequence Init(S, Entities.back(), InitKind, Ref);
- ExprResult Result(true);
- if (!Init.Diagnose(S, Entities.back(), InitKind, Ref))
- Result = Init.Perform(S, Entities.back(), InitKind, Ref);
-
- // If this initialization requires any cleanups (e.g., due to a
- // default argument to a copy constructor), note that for the
- // lambda.
- if (S.ExprNeedsCleanups)
- LSI->ExprNeedsCleanups = true;
-
- // Exit the expression evaluation context used for the capture.
- S.CleanupVarDeclMarking();
- S.DiscardCleanupsInEvaluationContext();
- return Result;
}
-
-
/// \brief Capture the given variable in the lambda.
static bool captureInLambda(LambdaScopeInfo *LSI,
VarDecl *Var,
@@ -12733,14 +12628,9 @@ static bool captureInLambda(LambdaScopeInfo *LSI,
}
// Capture this variable in the lambda.
- Expr *CopyExpr = nullptr;
- if (BuildAndDiagnose) {
- ExprResult Result = addAsFieldToClosureType(S, LSI, Var,
- CaptureType, DeclRefType, Loc,
- RefersToCapturedVariable);
- if (!Result.isInvalid())
- CopyExpr = Result.get();
- }
+ if (BuildAndDiagnose)
+ addAsFieldToClosureType(S, LSI, Var, CaptureType, DeclRefType, Loc,
+ RefersToCapturedVariable);
// Compute the type of a reference to this captured variable.
if (ByRef)
@@ -12759,18 +12649,20 @@ static bool captureInLambda(LambdaScopeInfo *LSI,
// Add the capture.
if (BuildAndDiagnose)
LSI->addCapture(Var, /*IsBlock=*/false, ByRef, RefersToCapturedVariable,
- Loc, EllipsisLoc, CaptureType, CopyExpr);
+ Loc, EllipsisLoc, CaptureType, /*CopyExpr=*/nullptr);
return true;
}
-bool Sema::tryCaptureVariable(VarDecl *Var, SourceLocation ExprLoc,
- TryCaptureKind Kind, SourceLocation EllipsisLoc,
- bool BuildAndDiagnose,
- QualType &CaptureType,
- QualType &DeclRefType,
- const unsigned *const FunctionScopeIndexToStopAt) {
- bool Nested = Var->isInitCapture();
+bool Sema::tryCaptureVariable(
+ VarDecl *Var, SourceLocation ExprLoc, TryCaptureKind Kind,
+ SourceLocation EllipsisLoc, bool BuildAndDiagnose, QualType &CaptureType,
+ QualType &DeclRefType, const unsigned *const FunctionScopeIndexToStopAt) {
+ // An init-capture is notionally from the context surrounding its
+ // declaration, but its parent DC is the lambda class.
+ DeclContext *VarDC = Var->getDeclContext();
+ if (Var->isInitCapture())
+ VarDC = VarDC->getParent();
DeclContext *DC = CurContext;
const unsigned MaxFunctionScopesIndex = FunctionScopeIndexToStopAt
@@ -12786,9 +12678,9 @@ bool Sema::tryCaptureVariable(VarDecl *Var, SourceLocation ExprLoc,
}
- // If the variable is declared in the current context (and is not an
- // init-capture), there is no need to capture it.
- if (!Nested && Var->getDeclContext() == DC) return true;
+ // If the variable is declared in the current context, there is no need to
+ // capture it.
+ if (VarDC == DC) return true;
// Capture global variables if it is required to use private copy of this
// variable.
@@ -12806,6 +12698,7 @@ bool Sema::tryCaptureVariable(VarDecl *Var, SourceLocation ExprLoc,
// the variable.
CaptureType = Var->getType();
DeclRefType = CaptureType.getNonReferenceType();
+ bool Nested = false;
bool Explicit = (Kind != TryCapture_Implicit);
unsigned FunctionScopesIndex = MaxFunctionScopesIndex;
do {
@@ -13006,7 +12899,7 @@ bool Sema::tryCaptureVariable(VarDecl *Var, SourceLocation ExprLoc,
FunctionScopesIndex--;
DC = ParentDC;
Explicit = false;
- } while (!Var->getDeclContext()->Equals(DC));
+ } while (!VarDC->Equals(DC));
// Walk back down the scope stack, (e.g. from outer lambda to inner lambda)
// computing the type of the capture at each step, checking type-specific
OpenPOWER on IntegriCloud