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

Faisal Vali via cfe-commits cfe-commits at lists.llvm.org
Mon Jan 9 03:44:21 PST 2017


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;


Thanks!


More information about the cfe-commits mailing list