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

Richard Smith via cfe-commits cfe-commits at lists.llvm.org
Sun Jan 8 22:13:18 PST 2017


On 8 January 2017 at 19:02, Faisal Vali via cfe-commits <
cfe-commits at lists.llvm.org> wrote:

> 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);
>

We'll need an implementation of DR1607 before we're done here, since it
looks like this has removed the last restriction on lambda-expressions in
function template signatures in some contexts (array bounds, template
arguments).

     } 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 at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20170108/45ef6878/attachment.html>


More information about the cfe-commits mailing list