aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/AST/ExprConstant.cpp
diff options
context:
space:
mode:
authorErik Pilkington <erik.pilkington@gmail.com>2018-04-05 00:12:05 +0000
committerErik Pilkington <erik.pilkington@gmail.com>2018-04-05 00:12:05 +0000
commit11232912b11b15b91e1f10a8e7decd1fa14d21fc (patch)
treea9a25297e10a2d713e9ae3f3ab386f604533e40e /clang/lib/AST/ExprConstant.cpp
parent26c504fe1e066b9a263b8f7d124d0f0d3a30a715 (diff)
downloadllvm-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.cpp25
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