faisalv created this revision. faisalv added reviewers: rsmith, hubert.reinterpretcast, aaron.ballman, erik.pilkington. faisalv added a subscriber: cfe-commits. faisalv set the repository for this revision to rL LLVM. faisalv added a project: clang-c.
Add a visitor for lambda expressions to RecordExprEvaluator in ExprConstant.cpp that creates an empty APValue Struct - thus supporting the following code: constexpr auto ID = [] (auto a) { return a; }; static_assert(ID(3.14) == 3.14); Repository: rL LLVM https://reviews.llvm.org/D22996 Files: lib/AST/ExprConstant.cpp test/SemaCXX/cxx1z-constexpr-lambdas.cpp
Index: test/SemaCXX/cxx1z-constexpr-lambdas.cpp =================================================================== --- test/SemaCXX/cxx1z-constexpr-lambdas.cpp +++ test/SemaCXX/cxx1z-constexpr-lambdas.cpp @@ -2,6 +2,16 @@ // RUN: %clang_cc1 -std=c++1z -verify -fsyntax-only -fblocks -fdelayed-template-parsing %s // RUN: %clang_cc1 -std=c++14 -verify -fsyntax-only -fblocks %s -DCPP14_AND_EARLIER +namespace test_lambda_is_literal { +#ifdef CPP14_AND_EARLIER +//expected-error@+4{{not a literal type}} +//expected-note@+2{{not an aggregate and has no constexpr constructors}} +#endif +auto L = [] { }; +constexpr int foo(decltype(L) l) { return 0; } +} + + #ifndef CPP14_AND_EARLIER namespace test_constexpr_checking { @@ -35,14 +45,73 @@ } // end ns test_constexpr_call -#endif -namespace test_lambda_is_literal { -#ifdef CPP14_AND_EARLIER -//expected-error@+4{{not a literal type}} -//expected-note@+2{{not an aggregate and has no constexpr constructors}} -#endif -auto L = [] { }; -constexpr int foo(decltype(L) l) { return 0; } +namespace test_lambda_is_cce { +namespace ns1_simple_lambda { -} \ No newline at end of file +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 Index: lib/AST/ExprConstant.cpp =================================================================== --- lib/AST/ExprConstant.cpp +++ lib/AST/ExprConstant.cpp @@ -5433,6 +5433,7 @@ 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); @@ -5764,6 +5765,21 @@ 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() &&
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits