diff options
author | Douglas Gregor <dgregor@apple.com> | 2012-02-09 00:47:04 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2012-02-09 00:47:04 +0000 |
commit | 503384f731b5abcbf870b0a5224eb920e631db0a (patch) | |
tree | 0af31e2390158648077180f89fe1f0e19f4eed6f /lib/Sema | |
parent | 91c2a1192cdd4e7b2b4ac7838c5aceef200ea251 (diff) |
Various interrelated cleanups for lambdas:
- Complete the lambda class when we finish the lambda expression
(previously, it was left in the "being completed" state)
- Actually return the LambdaExpr object and bind to the resulting
temporary when needed.
- Detect when cleanups are needed while capturing a variable into a
lambda (e.g., due to default arguments in the copy constructor), and
make sure those cleanups apply for the whole of the lambda
expression.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@150123 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema')
-rw-r--r-- | lib/Sema/SemaChecking.cpp | 5 | ||||
-rw-r--r-- | lib/Sema/SemaExpr.cpp | 19 | ||||
-rw-r--r-- | lib/Sema/SemaLambda.cpp | 28 |
3 files changed, 41 insertions, 11 deletions
diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp index 378930a0e5..69731e45ef 100644 --- a/lib/Sema/SemaChecking.cpp +++ b/lib/Sema/SemaChecking.cpp @@ -4185,7 +4185,10 @@ void AnalyzeImplicitConversions(Sema &S, Expr *OrigE, SourceLocation CC) { BinaryOperator *BO = dyn_cast<BinaryOperator>(E); bool IsLogicalOperator = BO && BO->isLogicalOp(); for (Stmt::child_range I = E->children(); I; ++I) { - Expr *ChildExpr = cast<Expr>(*I); + Expr *ChildExpr = dyn_cast<Expr>(*I); + if (!ChildExpr) + continue; + if (IsLogicalOperator && isa<StringLiteral>(ChildExpr->IgnoreParenImpCasts())) // Ignore checking string literals that are in logical operators. diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index accf85171e..aed6eaf4e3 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -9652,7 +9652,8 @@ void Sema::TryCaptureVar(VarDecl *var, SourceLocation loc, Expr *copyExpr = 0; const RecordType *rtype; if (isLambda) { - CXXRecordDecl *Lambda = cast<LambdaScopeInfo>(CSI)->Lambda; + LambdaScopeInfo *LSI = cast<LambdaScopeInfo>(CSI); + CXXRecordDecl *Lambda = LSI->Lambda; QualType FieldType; if (byRef) { // C++11 [expr.prim.lambda]p15: @@ -9704,6 +9705,11 @@ void Sema::TryCaptureVar(VarDecl *var, SourceLocation loc, // // FIXME: Introduce an initialization entity for lambda captures. // FIXME: Totally broken for arrays. + + // Introduce a new evaluation context for the initialization, so that + // temporaries introduced as part of the capture + PushExpressionEvaluationContext(PotentiallyEvaluated); + Expr *Ref = new (Context) DeclRefExpr(var, type.getNonReferenceType(), VK_LValue, loc); InitializedEntity InitEntity @@ -9717,6 +9723,17 @@ void Sema::TryCaptureVar(VarDecl *var, SourceLocation loc, if (!Result.isInvalid()) copyExpr = Result.take(); } + + // If this initialization requires any cleanups (e.g., due to a + // default argument to a copy constructor), note that for the + // lambda. + if (ExprNeedsCleanups) + LSI->ExprNeedsCleanups = true; + + // Exit the expression evaluation context used for the capture. + CleanupVarDeclMarking(); + DiscardCleanupsInEvaluationContext(); + PopExpressionEvaluationContext(); } else if (!byRef && getLangOptions().CPlusPlus && (rtype = type.getNonReferenceType()->getAs<RecordType>())) { // The capture logic needs the destructor, so make sure we mark it. diff --git a/lib/Sema/SemaLambda.cpp b/lib/Sema/SemaLambda.cpp index 3e9e210244..b90f5e3d63 100644 --- a/lib/Sema/SemaLambda.cpp +++ b/lib/Sema/SemaLambda.cpp @@ -103,13 +103,11 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro, Method->setAccess(AS_public); Class->addDecl(Method); Method->setLexicalDeclContext(DC); // FIXME: Minor hack. - + + // Attributes on the lambda apply to the method. ProcessDeclAttributes(CurScope, Method, ParamInfo); - // Enter a new evaluation context to insulate the block from any - // cleanups from the enclosing full-expression. - PushExpressionEvaluationContext(PotentiallyEvaluated); - + // Introduce the function call operator as the current declaration context. PushDeclContext(CurScope, Method); // Introduce the lambda scope. @@ -255,6 +253,9 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro, // FIXME: Check return type is complete, !isObjCObjectType + // Enter a new evaluation context to insulate the block from any + // cleanups from the enclosing full-expression. + PushExpressionEvaluationContext(PotentiallyEvaluated); } void Sema::ActOnLambdaError(SourceLocation StartLoc, Scope *CurScope) { @@ -273,8 +274,6 @@ ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc, DiscardCleanupsInEvaluationContext(); PopExpressionEvaluationContext(); - // FIXME: End-of-lambda checking - // Collect information from the lambda scope. llvm::SmallVector<LambdaExpr::Capture, 4> Captures; llvm::SmallVector<Expr *, 4> CaptureInits; @@ -282,11 +281,13 @@ ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc, CXXRecordDecl *Class; SourceRange IntroducerRange; bool ExplicitParams; + bool LambdaExprNeedsCleanups; { LambdaScopeInfo *LSI = getCurLambda(); Class = LSI->Lambda; IntroducerRange = LSI->IntroducerRange; ExplicitParams = LSI->ExplicitParams; + LambdaExprNeedsCleanups = LSI->ExprNeedsCleanups; // Translate captures. for (unsigned I = 0, N = LSI->Captures.size(); I != N; ++I) { @@ -331,16 +332,25 @@ ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc, break; } + // Finalize the lambda class. + SmallVector<Decl*, 4> Fields(Class->field_begin(), Class->field_end()); + ActOnFields(0, Class->getLocation(), Class, Fields, + SourceLocation(), SourceLocation(), 0); + CheckCompletedCXXClass(Class); + // C++ [expr.prim.lambda]p7: // The lambda-expression's compound-statement yields the // function-body (8.4) of the function call operator [...]. ActOnFinishFunctionBody(LSI->CallOperator, Body, /*IsInstantation=*/false); } + if (LambdaExprNeedsCleanups) + ExprNeedsCleanups = true; + Expr *Lambda = LambdaExpr::Create(Context, Class, IntroducerRange, CaptureDefault, Captures, ExplicitParams, CaptureInits, Body->getLocEnd()); - (void)Lambda; Diag(StartLoc, diag::err_lambda_unsupported); - return ExprError(); + + return MaybeBindToTemporary(Lambda); } |