forked from OSchip/llvm-project
[AST] Don't track lambda captures when checking a potential constant expression.
Fixes PR36054. Differential revision: https://reviews.llvm.org/D45194 llvm-svn: 329244
This commit is contained in:
parent
26c504fe1e
commit
11232912b1
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue