Author: faisalv Date: Sun Jan 8 21:02:53 2017 New Revision: 291416 URL: http://llvm.org/viewvc/llvm-project?rev=291416&view=rev Log: [cxx1z-constexpr-lambda] Implement constant evaluation of non-capturing lambda expressions.
Add a visitor for lambda expressions to RecordExprEvaluator in ExprConstant.cpp that creates an empty APValue of Struct type to represent the closure object. Additionally, add a LambdaExpr visitor to the TemporaryExprEvaluator that forwards constant evaluation of immediately-called-lambda-expressions to the one in RecordExprEvaluator through VisitConstructExpr. This patch supports: constexpr auto ID = [] (auto a) { return a; }; static_assert(ID(3.14) == 3.14); static_assert([](auto a) { return a + 1; }(10) == 11); Lambda captures are still not supported for constexpr lambdas. Modified: cfe/trunk/lib/AST/ExprConstant.cpp cfe/trunk/lib/Sema/SemaExpr.cpp cfe/trunk/test/SemaCXX/cxx1z-constexpr-lambdas.cpp Modified: cfe/trunk/lib/AST/ExprConstant.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprConstant.cpp?rev=291416&r1=291415&r2=291416&view=diff ============================================================================== --- cfe/trunk/lib/AST/ExprConstant.cpp (original) +++ cfe/trunk/lib/AST/ExprConstant.cpp Sun Jan 8 21:02:53 2017 @@ -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::VisitCXXStdIni 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 Modified: cfe/trunk/lib/Sema/SemaExpr.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=291416&r1=291415&r2=291416&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaExpr.cpp (original) +++ cfe/trunk/lib/Sema/SemaExpr.cpp Sun Jan 8 21:02:53 2017 @@ -13097,8 +13097,10 @@ void Sema::PopExpressionEvaluationContex // 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. Modified: cfe/trunk/test/SemaCXX/cxx1z-constexpr-lambdas.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/cxx1z-constexpr-lambdas.cpp?rev=291416&r1=291415&r2=291416&view=diff ============================================================================== --- cfe/trunk/test/SemaCXX/cxx1z-constexpr-lambdas.cpp (original) +++ cfe/trunk/test/SemaCXX/cxx1z-constexpr-lambdas.cpp Sun Jan 8 21:02:53 2017 @@ -96,4 +96,81 @@ decltype(deduced_return_type(0)) d; //e } // 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 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits