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 | 8c50e7c5e380d93f784582579c3e3f1bc157bf12 (patch) | |
| tree | d6556ee13f1264af6738a39fd7c043365bfeb166 /clang/lib | |
| parent | f542675ae34943a85ffcdb9d07c69b181c3d869f (diff) | |
| download | bcm5719-llvm-8c50e7c5e380d93f784582579c3e3f1bc157bf12.tar.gz bcm5719-llvm-8c50e7c5e380d93f784582579c3e3f1bc157bf12.zip | |
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.
llvm-svn: 150123
Diffstat (limited to 'clang/lib')
| -rw-r--r-- | clang/lib/Sema/SemaChecking.cpp | 5 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaExpr.cpp | 19 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaLambda.cpp | 28 |
3 files changed, 41 insertions, 11 deletions
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index 378930a0e5b..69731e45eff 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/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/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index accf85171ee..aed6eaf4e3e 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/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/clang/lib/Sema/SemaLambda.cpp b/clang/lib/Sema/SemaLambda.cpp index 3e9e2102448..b90f5e3d639 100644 --- a/clang/lib/Sema/SemaLambda.cpp +++ b/clang/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); } |

