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/lib/AST/ExprConstant.cpp | |
parent | 26c504fe1e066b9a263b8f7d124d0f0d3a30a715 (diff) | |
download | llvm-11232912b11b15b91e1f10a8e7decd1fa14d21fc.zip llvm-11232912b11b15b91e1f10a8e7decd1fa14d21fc.tar.gz llvm-11232912b11b15b91e1f10a8e7decd1fa14d21fc.tar.bz2 |
[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/lib/AST/ExprConstant.cpp')
-rw-r--r-- | clang/lib/AST/ExprConstant.cpp | 25 |
1 files changed, 19 insertions, 6 deletions
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index 84ac4da..6de55f1 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 |