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

Richard Smith via cfe-commits cfe-commits at lists.llvm.org
Mon Jan 9 13:02:05 PST 2017


On 9 January 2017 at 03:44, Faisal Vali <faisalv at gmail.com> wrote:

> On Mon, Jan 9, 2017 at 12:13 AM, Richard Smith <richard at metafoo.co.uk>
> wrote:
> > 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).
> >
>
> Yes - I'll add those restrictions back (I suppose we'll need to check
> whether the nearest enclosing non-lambda context is a valid one [while
> still allowing them in default function arguments]) - but then we'll
> need to relax some of them when we implement P0315 in post-C++-17
> right?
>
> For e.g. these would be ok w P0315 right?
>
> template<int N = []{ return 5; }()> struct X { };
>
> X<[](auto a){ return a; }(10)> x;


Who can say... P0315's direction is not finalized as far as I'm aware, and
I don't expect it to apply retroactively, so we'll need the DR1607 rules
anyway.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20170109/ce13c0ca/attachment.html>


More information about the cfe-commits mailing list