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};
// 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
} // 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