diff options
author | Douglas Gregor <dgregor@apple.com> | 2012-02-09 08:14:43 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2012-02-09 08:14:43 +0000 |
commit | e2c5913c48f66bfec9e58a8ad1d90e5eeffad586 (patch) | |
tree | af3426a28595a628dcd322a29f51ab9b22a322d8 /lib/Sema/SemaExpr.cpp | |
parent | 621fc4b47f11585120e3d2eed32d1f46e2063c62 (diff) |
Implement C++ [expr.prim.lambda]p2, which bans lambda expressions in
unevaluated operands. Be certain that we're marking everything
referenced within a capture initializer as odr-used.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@150163 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaExpr.cpp')
-rw-r--r-- | lib/Sema/SemaExpr.cpp | 36 |
1 files changed, 34 insertions, 2 deletions
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 36bbae03f8..de70ad4cba 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -9282,6 +9282,12 @@ namespace { return BaseTransform::TransformUnaryOperator(E); } + /// \brief Transform the capture expressions in the lambda + /// expression. + ExprResult TransformLambdaExpr(LambdaExpr *E) { + // Lambdas never need to be transformed. + return E; + } }; } @@ -9307,6 +9313,29 @@ Sema::PushExpressionEvaluationContext(ExpressionEvaluationContext NewContext) { void Sema::PopExpressionEvaluationContext() { ExpressionEvaluationContextRecord& Rec = ExprEvalContexts.back(); + if (!Rec.Lambdas.empty()) { + if (Rec.Context == Unevaluated) { + // C++11 [expr.prim.lambda]p2: + // A lambda-expression shall not appear in an unevaluated operand + // (Clause 5). + for (unsigned I = 0, N = Rec.Lambdas.size(); I != N; ++I) + Diag(Rec.Lambdas[I]->getLocStart(), + diag::err_lambda_unevaluated_operand); + } else { + // Mark the capture expressions odr-used. This was deferred + // during lambda expression creation. + for (unsigned I = 0, N = Rec.Lambdas.size(); I != N; ++I) { + LambdaExpr *Lambda = Rec.Lambdas[I]; + for (LambdaExpr::capture_init_iterator + C = Lambda->capture_init_begin(), + CEnd = Lambda->capture_init_end(); + C != CEnd; ++C) { + MarkDeclarationsReferencedInExpr(*C); + } + } + } + } + // When are coming out of an unevaluated context, clear out any // temporaries that we may have created as part of the evaluation of // the expression in that context: they aren't relevant because they @@ -9318,6 +9347,8 @@ void Sema::PopExpressionEvaluationContext() { CleanupVarDeclMarking(); std::swap(MaybeODRUseExprs, Rec.SavedMaybeODRUseExprs); + if (Rec.Context == Unevaluated) { + } // Otherwise, merge the contexts together. } else { ExprNeedsCleanups |= Rec.ParentNeedsCleanups; @@ -9589,8 +9620,9 @@ static ExprResult captureInLambda(Sema &S, LambdaScopeInfo *LSI, // // FIXME: Introduce an initialization entity for lambda captures. - // Introduce a new evaluation context for the initialization, so that - // temporaries introduced as part of the capture + // 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. S.PushExpressionEvaluationContext(Sema::PotentiallyEvaluated); Expr *Ref = new (S.Context) DeclRefExpr(Var, Type.getNonReferenceType(), |