diff options
Diffstat (limited to 'clang/lib/Sema/SemaExpr.cpp')
-rw-r--r-- | clang/lib/Sema/SemaExpr.cpp | 153 |
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 |