diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index bb0b8ba5c8bc..18206e5e0eeb 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -5868,6 +5868,7 @@ namespace { bool VisitCXXConstructExpr(const CXXConstructExpr *E) { return VisitCXXConstructExpr(E, E->getType()); } + bool VisitLambdaExpr(const LambdaExpr *E); bool VisitCXXInheritedCtorInitExpr(const CXXInheritedCtorInitExpr *E); bool VisitCXXConstructExpr(const CXXConstructExpr *E, QualType T); bool VisitCXXStdInitializerListExpr(const CXXStdInitializerListExpr *E); @@ -6202,6 +6203,21 @@ bool RecordExprEvaluator::VisitCXXStdInitializerListExpr( return true; } +bool RecordExprEvaluator::VisitLambdaExpr(const LambdaExpr *E) { + const CXXRecordDecl *ClosureClass = E->getLambdaClass(); + if (ClosureClass->isInvalidDecl()) return false; + + if (Info.checkingPotentialConstantExpression()) return true; + if (E->capture_size()) { + Info.FFDiag(E, diag::note_unimplemented_constexpr_lambda_feature_ast) + << "can not evaluate lambda expressions with captures"; + return false; + } + // FIXME: Implement captures. + Result = APValue(APValue::UninitStruct(), /*NumBases*/0, /*NumFields*/0); + return true; +} + static bool EvaluateRecord(const Expr *E, const LValue &This, APValue &Result, EvalInfo &Info) { assert(E->isRValue() && E->getType()->isRecordType() && @@ -6251,6 +6267,9 @@ public: bool VisitCXXStdInitializerListExpr(const CXXStdInitializerListExpr *E) { return VisitConstructExpr(E); } + bool VisitLambdaExpr(const LambdaExpr *E) { + return VisitConstructExpr(E); + } }; } // end anonymous namespace diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 023d6f678d5b..65e8236952f4 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -13097,8 +13097,10 @@ void Sema::PopExpressionEvaluationContext() { // evaluate [...] a lambda-expression. D = diag::err_lambda_in_constant_expression; } - for (const auto *L : Rec.Lambdas) - Diag(L->getLocStart(), D); + // C++1z allows lambda expressions as core constant expressions. + if (Rec.Context != ConstantEvaluated || !getLangOpts().CPlusPlus1z) + for (const auto *L : Rec.Lambdas) + Diag(L->getLocStart(), D); } else { // Mark the capture expressions odr-used. This was deferred // during lambda expression creation. diff --git a/clang/test/SemaCXX/cxx1z-constexpr-lambdas.cpp b/clang/test/SemaCXX/cxx1z-constexpr-lambdas.cpp index f1f4cfe66c25..16d5730d3d4c 100644 --- a/clang/test/SemaCXX/cxx1z-constexpr-lambdas.cpp +++ b/clang/test/SemaCXX/cxx1z-constexpr-lambdas.cpp @@ -96,4 +96,81 @@ decltype(deduced_return_type(0)) d; //expected-note{{requested here}} } // end ns test_conversion_function_for_non_capturing_lambdas +namespace test_lambda_is_cce { +namespace ns1_simple_lambda { + +namespace ns0 { +constexpr int I = [](auto a) { return a; }(10); + +static_assert(I == 10); +static_assert(10 == [](auto a) { return a; }(10)); +static_assert(3.14 == [](auto a) { return a; }(3.14)); + +} //end ns0 + +namespace ns1 { +constexpr auto f(int i) { + double d = 3.14; + auto L = [=](auto a) { + int Isz = sizeof(i); + return sizeof(i) + sizeof(a) + sizeof(d); + }; + int I = L("abc") + L(nullptr); + return L; +} +constexpr auto L = f(3); +constexpr auto M = L("abc") + L(nullptr); + +static_assert(M == sizeof(int) * 2 + sizeof(double) * 2 + sizeof(nullptr) + sizeof(const char*)); + +} // end ns1 + +namespace ns2 { +constexpr auto f(int i) { + auto L = [](auto a) { return a + a; }; + return L; +} +constexpr auto L = f(3); +constexpr int I = L(6); +static_assert(I == 12); +} // end ns2 + +namespace contained_lambdas_call_operator_is_not_constexpr { +constexpr auto f(int i) { + double d = 3.14; + auto L = [=](auto a) { //expected-note{{declared here}} + int Isz = sizeof(i); + asm("hello"); + return sizeof(i) + sizeof(a) + sizeof(d); + }; + return L; +} + +constexpr auto L = f(3); + +constexpr auto M = // expected-error{{must be initialized by}} + L("abc"); //expected-note{{non-constexpr function}} + +} // end ns contained_lambdas_call_operator_is_not_constexpr + + + +} // end ns1_simple_lambda + +namespace ns1_unimplemented { +namespace ns1_captures { +constexpr auto f(int i) { + double d = 3.14; + auto L = [=](auto a) { //expected-note{{coming soon}} + int Isz = i + d; + return sizeof(i) + sizeof(a) + sizeof(d); + }; + return L; +} +constexpr auto M = f(3); //expected-error{{constant expression}} expected-note{{in call to}} +} // end ns1_captures +} // end ns1_unimplemented + +} // end ns test_lambda_is_cce + #endif // ndef CPP14_AND_EARLIER