r291416 - [cxx1z-constexpr-lambda] Implement constant evaluation of non-capturing lambda expressions.

Faisal Vali via cfe-commits cfe-commits at lists.llvm.org
Sun Jan 8 19:02:54 PST 2017


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




More information about the cfe-commits mailing list