diff options
author | Erik Pilkington <erik.pilkington@gmail.com> | 2018-04-05 00:12:05 +0000 |
---|---|---|
committer | Erik Pilkington <erik.pilkington@gmail.com> | 2018-04-05 00:12:05 +0000 |
commit | 11232912b11b15b91e1f10a8e7decd1fa14d21fc (patch) | |
tree | a9a25297e10a2d713e9ae3f3ab386f604533e40e /clang | |
parent | 26c504fe1e066b9a263b8f7d124d0f0d3a30a715 (diff) | |
download | bcm5719-llvm-11232912b11b15b91e1f10a8e7decd1fa14d21fc.tar.gz bcm5719-llvm-11232912b11b15b91e1f10a8e7decd1fa14d21fc.zip |
[AST] Don't track lambda captures when checking a potential constant expression.
Fixes PR36054.
Differential revision: https://reviews.llvm.org/D45194
llvm-svn: 329244
Diffstat (limited to 'clang')
-rw-r--r-- | clang/lib/AST/ExprConstant.cpp | 25 | ||||
-rw-r--r-- | clang/test/SemaCXX/cxx1z-constexpr-lambdas.cpp | 33 |
2 files changed, 52 insertions, 6 deletions
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index 84ac4daeef9..6de55f10dc5 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -4309,9 +4309,15 @@ static bool HandleFunctionCall(SourceLocation CallLoc, This->moveInto(Result); return true; } else if (MD && isLambdaCallOperator(MD)) { - // We're in a lambda; determine the lambda capture field maps. - MD->getParent()->getCaptureFields(Frame.LambdaCaptureFields, - Frame.LambdaThisCaptureField); + // We're in a lambda; determine the lambda capture field maps unless we're + // just constexpr checking a lambda's call operator. constexpr checking is + // done before the captures have been added to the closure object (unless + // we're inferring constexpr-ness), so we don't have access to them in this + // case. But since we don't need the captures to constexpr check, we can + // just ignore them. + if (!Info.checkingPotentialConstantExpression()) + MD->getParent()->getCaptureFields(Frame.LambdaCaptureFields, + Frame.LambdaThisCaptureField); } StmtResult Ret = {Result, ResultSlot}; @@ -5201,10 +5207,17 @@ bool LValueExprEvaluator::VisitVarDecl(const Expr *E, const VarDecl *VD) { // to within 'E' actually represents a lambda-capture that maps to a // data-member/field within the closure object, and if so, evaluate to the // field or what the field refers to. - if (Info.CurrentCall && isLambdaCallOperator(Info.CurrentCall->Callee)) { + if (Info.CurrentCall && isLambdaCallOperator(Info.CurrentCall->Callee) && + isa<DeclRefExpr>(E) && + cast<DeclRefExpr>(E)->refersToEnclosingVariableOrCapture()) { + // We don't always have a complete capture-map when checking or inferring if + // the function call operator meets the requirements of a constexpr function + // - but we don't need to evaluate the captures to determine constexprness + // (dcl.constexpr C++17). + if (Info.checkingPotentialConstantExpression()) + return false; + if (auto *FD = Info.CurrentCall->LambdaCaptureFields.lookup(VD)) { - if (Info.checkingPotentialConstantExpression()) - return false; // Start with 'Result' referring to the complete closure object... Result = *Info.CurrentCall->This; // ... then update it to refer to the field of the closure object diff --git a/clang/test/SemaCXX/cxx1z-constexpr-lambdas.cpp b/clang/test/SemaCXX/cxx1z-constexpr-lambdas.cpp index 4a98a1b06c8..3d5509eedf6 100644 --- a/clang/test/SemaCXX/cxx1z-constexpr-lambdas.cpp +++ b/clang/test/SemaCXX/cxx1z-constexpr-lambdas.cpp @@ -270,4 +270,37 @@ namespace ns1_test_lvalue_type { } // end ns test_lambda_is_cce +namespace PR36054 { +constexpr int fn() { + int Capture = 42; + return [=]() constexpr { return Capture; }(); +} + +static_assert(fn() == 42, ""); + +template <class T> +constexpr int tfn() { + int Capture = 42; + return [=]() constexpr { return Capture; }(); +} + +static_assert(tfn<int>() == 42, ""); + +constexpr int gfn() { + int Capture = 42; + return [=](auto P) constexpr { return Capture + P; }(58); +} + +static_assert(gfn() == 100, ""); + +constexpr bool OtherCaptures() { + int Capture = 42; + constexpr auto Outer = [](auto P) constexpr { return 42 + P; }; + auto Inner = [&](auto O) constexpr { return O(58) + Capture; }; + return Inner(Outer) == 142; +} + +static_assert(OtherCaptures(), ""); +} // namespace PR36054 + #endif // ndef CPP14_AND_EARLIER |