Re: r295279 - [cxx1z-constexpr-lambda] Implement captures - thus completing implementation of constexpr lambdas.

2017-02-21 Thread Richard Smith via cfe-commits
Timeout -- committed r295791 on your behalf.

On 16 February 2017 at 05:04, Faisal Vali  wrote:

> Of course Richard - I'll be happy to bump that value for C++1z
> hopefully later today.
> Thanks!
> Faisal Vali
>
>
>
> On Wed, Feb 15, 2017 at 10:30 PM, Richard Smith 
> wrote:
> > On 15 February 2017 at 20:12, Faisal Vali via cfe-commits
> >  wrote:
> >>
> >> Author: faisalv
> >> Date: Wed Feb 15 22:12:21 2017
> >> New Revision: 295279
> >>
> >> URL: http://llvm.org/viewvc/llvm-project?rev=295279&view=rev
> >> Log:
> >> [cxx1z-constexpr-lambda] Implement captures - thus completing
> >> implementation of constexpr lambdas.
> >>
> >> Enable evaluation of captures within constexpr lambdas by using a
> strategy
> >> similar to that used in CodeGen:
> >>   - when starting evaluation of a lambda's call operator, create a map
> >> from VarDecl's to a closure's FieldDecls
> >>   - every time a VarDecl (or '*this) that represents a capture is
> >> encountered while evaluating the expression via the expression evaluator
> >> (specifically the LValueEvaluator) in ExprConstant.cpp - it is replaced
> by
> >> the corresponding FieldDecl LValue (an Lvalue-to-Rvalue conversion on
> this
> >> LValue representation then determines the right rvalue when needed).
> >>
> >> Thanks to Richard Smith and Hubert Tong for their review and feedback!
> >
> >
> > Awesome, thanks Faisal!
> >
> > Want to bump our value for __cpp_constexpr to 201603 in C++1z mode to
> > advertise support for this?
> >
> >>
> >> https://reviews.llvm.org/D29748
> >>
> >>
> >> Modified:
> >> cfe/trunk/lib/AST/ExprConstant.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=295279&r1=295278&r2=295279&view=diff
> >>
> >> 
> ==
> >> --- cfe/trunk/lib/AST/ExprConstant.cpp (original)
> >> +++ cfe/trunk/lib/AST/ExprConstant.cpp Wed Feb 15 22:12:21 2017
> >> @@ -425,6 +425,17 @@ namespace {
> >>  /// Index - The call index of this call.
> >>  unsigned Index;
> >>
> >> +// FIXME: Adding this to every 'CallStackFrame' may have a
> nontrivial
> >> impact
> >> +// on the overall stack usage of deeply-recursing constexpr
> >> evaluataions.
> >> +// (We should cache this map rather than recomputing it
> repeatedly.)
> >> +// But let's try this and see how it goes; we can look into caching
> >> the map
> >> +// as a later change.
> >> +
> >> +/// LambdaCaptureFields - Mapping from captured variables/this to
> >> +/// corresponding data members in the closure class.
> >> +llvm::DenseMap LambdaCaptureFields;
> >> +FieldDecl *LambdaThisCaptureField;
> >> +
> >>  CallStackFrame(EvalInfo &Info, SourceLocation CallLoc,
> >> const FunctionDecl *Callee, const LValue *This,
> >> APValue *Arguments);
> >> @@ -2279,6 +2290,10 @@ static bool HandleLValueComplexElement(E
> >>return true;
> >>  }
> >>
> >> +static bool handleLValueToRValueConversion(EvalInfo &Info, const Expr
> >> *Conv,
> >> +   QualType Type, const LValue
> >> &LVal,
> >> +   APValue &RVal);
> >> +
> >>  /// Try to evaluate the initializer for a variable declaration.
> >>  ///
> >>  /// \param Info   Information about the ongoing evaluation.
> >> @@ -2290,6 +2305,7 @@ static bool HandleLValueComplexElement(E
> >>  static bool evaluateVarDeclInit(EvalInfo &Info, const Expr *E,
> >>  const VarDecl *VD, CallStackFrame
> *Frame,
> >>  APValue *&Result) {
> >> +
> >>// If this is a parameter to an active constexpr function call,
> perform
> >>// argument substitution.
> >>if (const ParmVarDecl *PVD = dyn_cast(VD)) {
> >> @@ -4180,6 +4196,10 @@ static bool HandleFunctionCall(SourceLoc
> >>return false;
> >>  This->moveInto(Result);
> >>  return true;
> >> +  } else if (MD && isLambdaCallOperator(MD)) {
> >> +// We're in a lambda; determine the lambda capture field maps.
> >> +MD->getParent()->getCaptureFields(Frame.LambdaCaptureFields,
> >> +  Frame.LambdaThisCaptureField);
> >>}
> >>
> >>StmtResult Ret = {Result, ResultSlot};
> >> @@ -5041,6 +5061,33 @@ bool LValueExprEvaluator::VisitDeclRefEx
> >>
> >>
> >>  bool LValueExprEvaluator::VisitVarDecl(const Expr *E, const VarDecl
> *VD)
> >> {
> >> +
> >> +  // If we are within a lambda's call operator, check whether the 'VD'
> >> referred
> >> +  // to within 'E' actually represents a lambda-capture that maps to a
> >> +  // data-member/field within the closure object, and if so, evaluate
> to
> >> the
> >> +  // field or what the field refers to.
> >> +  if (Info.CurrentCall && isLambdaCallOperator(Info.
> CurrentCall->Callee))

Re: r295279 - [cxx1z-constexpr-lambda] Implement captures - thus completing implementation of constexpr lambdas.

2017-02-16 Thread Faisal Vali via cfe-commits
Of course Richard - I'll be happy to bump that value for C++1z
hopefully later today.
Thanks!
Faisal Vali



On Wed, Feb 15, 2017 at 10:30 PM, Richard Smith  wrote:
> On 15 February 2017 at 20:12, Faisal Vali via cfe-commits
>  wrote:
>>
>> Author: faisalv
>> Date: Wed Feb 15 22:12:21 2017
>> New Revision: 295279
>>
>> URL: http://llvm.org/viewvc/llvm-project?rev=295279&view=rev
>> Log:
>> [cxx1z-constexpr-lambda] Implement captures - thus completing
>> implementation of constexpr lambdas.
>>
>> Enable evaluation of captures within constexpr lambdas by using a strategy
>> similar to that used in CodeGen:
>>   - when starting evaluation of a lambda's call operator, create a map
>> from VarDecl's to a closure's FieldDecls
>>   - every time a VarDecl (or '*this) that represents a capture is
>> encountered while evaluating the expression via the expression evaluator
>> (specifically the LValueEvaluator) in ExprConstant.cpp - it is replaced by
>> the corresponding FieldDecl LValue (an Lvalue-to-Rvalue conversion on this
>> LValue representation then determines the right rvalue when needed).
>>
>> Thanks to Richard Smith and Hubert Tong for their review and feedback!
>
>
> Awesome, thanks Faisal!
>
> Want to bump our value for __cpp_constexpr to 201603 in C++1z mode to
> advertise support for this?
>
>>
>> https://reviews.llvm.org/D29748
>>
>>
>> Modified:
>> cfe/trunk/lib/AST/ExprConstant.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=295279&r1=295278&r2=295279&view=diff
>>
>> ==
>> --- cfe/trunk/lib/AST/ExprConstant.cpp (original)
>> +++ cfe/trunk/lib/AST/ExprConstant.cpp Wed Feb 15 22:12:21 2017
>> @@ -425,6 +425,17 @@ namespace {
>>  /// Index - The call index of this call.
>>  unsigned Index;
>>
>> +// FIXME: Adding this to every 'CallStackFrame' may have a nontrivial
>> impact
>> +// on the overall stack usage of deeply-recursing constexpr
>> evaluataions.
>> +// (We should cache this map rather than recomputing it repeatedly.)
>> +// But let's try this and see how it goes; we can look into caching
>> the map
>> +// as a later change.
>> +
>> +/// LambdaCaptureFields - Mapping from captured variables/this to
>> +/// corresponding data members in the closure class.
>> +llvm::DenseMap LambdaCaptureFields;
>> +FieldDecl *LambdaThisCaptureField;
>> +
>>  CallStackFrame(EvalInfo &Info, SourceLocation CallLoc,
>> const FunctionDecl *Callee, const LValue *This,
>> APValue *Arguments);
>> @@ -2279,6 +2290,10 @@ static bool HandleLValueComplexElement(E
>>return true;
>>  }
>>
>> +static bool handleLValueToRValueConversion(EvalInfo &Info, const Expr
>> *Conv,
>> +   QualType Type, const LValue
>> &LVal,
>> +   APValue &RVal);
>> +
>>  /// Try to evaluate the initializer for a variable declaration.
>>  ///
>>  /// \param Info   Information about the ongoing evaluation.
>> @@ -2290,6 +2305,7 @@ static bool HandleLValueComplexElement(E
>>  static bool evaluateVarDeclInit(EvalInfo &Info, const Expr *E,
>>  const VarDecl *VD, CallStackFrame *Frame,
>>  APValue *&Result) {
>> +
>>// If this is a parameter to an active constexpr function call, perform
>>// argument substitution.
>>if (const ParmVarDecl *PVD = dyn_cast(VD)) {
>> @@ -4180,6 +4196,10 @@ static bool HandleFunctionCall(SourceLoc
>>return false;
>>  This->moveInto(Result);
>>  return true;
>> +  } else if (MD && isLambdaCallOperator(MD)) {
>> +// We're in a lambda; determine the lambda capture field maps.
>> +MD->getParent()->getCaptureFields(Frame.LambdaCaptureFields,
>> +  Frame.LambdaThisCaptureField);
>>}
>>
>>StmtResult Ret = {Result, ResultSlot};
>> @@ -5041,6 +5061,33 @@ bool LValueExprEvaluator::VisitDeclRefEx
>>
>>
>>  bool LValueExprEvaluator::VisitVarDecl(const Expr *E, const VarDecl *VD)
>> {
>> +
>> +  // If we are within a lambda's call operator, check whether the 'VD'
>> referred
>> +  // to within 'E' actually represents a lambda-capture that maps to a
>> +  // data-member/field within the closure object, and if so, evaluate to
>> the
>> +  // field or what the field refers to.
>> +  if (Info.CurrentCall && isLambdaCallOperator(Info.CurrentCall->Callee))
>> {
>> +if (auto *FD = Info.CurrentCall->LambdaCaptureFields.lookup(VD)) {
>> +  if (Info.checkingPotentialConstantExpression())
>> +return false;
>> +  // Start with 'Result' referring to the complete closure object...
>> +  Result = *Info.CurrentCall->This;
>> +  // ... then update it to refer to the field of the closure object

Re: r295279 - [cxx1z-constexpr-lambda] Implement captures - thus completing implementation of constexpr lambdas.

2017-02-15 Thread Craig Topper via cfe-commits
The assert below is throwing a -Wsign-compare warning because std::distance
returns a signed type.

+  const size_t NumFields =
+  std::distance(ClosureClass->field_begin(),
ClosureClass->field_end());
+
+  assert(NumFields ==
+std::distance(E->capture_init_begin(), E->capture_init_end()) &&
+"The number of lambda capture initializers should equal the number of "
+"fields within the closure type");

~Craig

On Wed, Feb 15, 2017 at 8:12 PM, Faisal Vali via cfe-commits <
cfe-commits@lists.llvm.org> wrote:

> Author: faisalv
> Date: Wed Feb 15 22:12:21 2017
> New Revision: 295279
>
> URL: http://llvm.org/viewvc/llvm-project?rev=295279&view=rev
> Log:
> [cxx1z-constexpr-lambda] Implement captures - thus completing
> implementation of constexpr lambdas.
>
> Enable evaluation of captures within constexpr lambdas by using a strategy
> similar to that used in CodeGen:
>   - when starting evaluation of a lambda's call operator, create a map
> from VarDecl's to a closure's FieldDecls
>   - every time a VarDecl (or '*this) that represents a capture is
> encountered while evaluating the expression via the expression evaluator
> (specifically the LValueEvaluator) in ExprConstant.cpp - it is replaced by
> the corresponding FieldDecl LValue (an Lvalue-to-Rvalue conversion on this
> LValue representation then determines the right rvalue when needed).
>
> Thanks to Richard Smith and Hubert Tong for their review and feedback!
>
> https://reviews.llvm.org/D29748
>
>
> Modified:
> cfe/trunk/lib/AST/ExprConstant.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=295279&r1=295278&r2=295279&view=diff
> 
> ==
> --- cfe/trunk/lib/AST/ExprConstant.cpp (original)
> +++ cfe/trunk/lib/AST/ExprConstant.cpp Wed Feb 15 22:12:21 2017
> @@ -425,6 +425,17 @@ namespace {
>  /// Index - The call index of this call.
>  unsigned Index;
>
> +// FIXME: Adding this to every 'CallStackFrame' may have a nontrivial
> impact
> +// on the overall stack usage of deeply-recursing constexpr
> evaluataions.
> +// (We should cache this map rather than recomputing it repeatedly.)
> +// But let's try this and see how it goes; we can look into caching
> the map
> +// as a later change.
> +
> +/// LambdaCaptureFields - Mapping from captured variables/this to
> +/// corresponding data members in the closure class.
> +llvm::DenseMap LambdaCaptureFields;
> +FieldDecl *LambdaThisCaptureField;
> +
>  CallStackFrame(EvalInfo &Info, SourceLocation CallLoc,
> const FunctionDecl *Callee, const LValue *This,
> APValue *Arguments);
> @@ -2279,6 +2290,10 @@ static bool HandleLValueComplexElement(E
>return true;
>  }
>
> +static bool handleLValueToRValueConversion(EvalInfo &Info, const Expr
> *Conv,
> +   QualType Type, const LValue
> &LVal,
> +   APValue &RVal);
> +
>  /// Try to evaluate the initializer for a variable declaration.
>  ///
>  /// \param Info   Information about the ongoing evaluation.
> @@ -2290,6 +2305,7 @@ static bool HandleLValueComplexElement(E
>  static bool evaluateVarDeclInit(EvalInfo &Info, const Expr *E,
>  const VarDecl *VD, CallStackFrame *Frame,
>  APValue *&Result) {
> +
>// If this is a parameter to an active constexpr function call, perform
>// argument substitution.
>if (const ParmVarDecl *PVD = dyn_cast(VD)) {
> @@ -4180,6 +4196,10 @@ static bool HandleFunctionCall(SourceLoc
>return false;
>  This->moveInto(Result);
>  return true;
> +  } else if (MD && isLambdaCallOperator(MD)) {
> +// We're in a lambda; determine the lambda capture field maps.
> +MD->getParent()->getCaptureFields(Frame.LambdaCaptureFields,
> +  Frame.LambdaThisCaptureField);
>}
>
>StmtResult Ret = {Result, ResultSlot};
> @@ -5041,6 +5061,33 @@ bool LValueExprEvaluator::VisitDeclRefEx
>
>
>  bool LValueExprEvaluator::VisitVarDecl(const Expr *E, const VarDecl *VD)
> {
> +
> +  // If we are within a lambda's call operator, check whether the 'VD'
> referred
> +  // to within 'E' actually represents a lambda-capture that maps to a
> +  // data-member/field within the closure object, and if so, evaluate to
> the
> +  // field or what the field refers to.
> +  if (Info.CurrentCall && isLambdaCallOperator(Info.CurrentCall->Callee))
> {
> +if (auto *FD = Info.CurrentCall->LambdaCaptureFields.lookup(VD)) {
> +  if (Info.checkingPotentialConstantExpression())
> +return false;
> +  // Start with 'Result' referring to the complete closure object...
> +  Result = *Info.CurrentCall->This;
> +  // ... then update i

Re: r295279 - [cxx1z-constexpr-lambda] Implement captures - thus completing implementation of constexpr lambdas.

2017-02-15 Thread Richard Smith via cfe-commits
On 15 February 2017 at 20:12, Faisal Vali via cfe-commits <
cfe-commits@lists.llvm.org> wrote:

> Author: faisalv
> Date: Wed Feb 15 22:12:21 2017
> New Revision: 295279
>
> URL: http://llvm.org/viewvc/llvm-project?rev=295279&view=rev
> Log:
> [cxx1z-constexpr-lambda] Implement captures - thus completing
> implementation of constexpr lambdas.
>
> Enable evaluation of captures within constexpr lambdas by using a strategy
> similar to that used in CodeGen:
>   - when starting evaluation of a lambda's call operator, create a map
> from VarDecl's to a closure's FieldDecls
>   - every time a VarDecl (or '*this) that represents a capture is
> encountered while evaluating the expression via the expression evaluator
> (specifically the LValueEvaluator) in ExprConstant.cpp - it is replaced by
> the corresponding FieldDecl LValue (an Lvalue-to-Rvalue conversion on this
> LValue representation then determines the right rvalue when needed).
>
> Thanks to Richard Smith and Hubert Tong for their review and feedback!
>

Awesome, thanks Faisal!

Want to bump our value for __cpp_constexpr to 201603 in C++1z mode to
advertise support for this?


> https://reviews.llvm.org/D29748
>
>
> Modified:
> cfe/trunk/lib/AST/ExprConstant.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/ExprCo
> nstant.cpp?rev=295279&r1=295278&r2=295279&view=diff
> 
> ==
> --- cfe/trunk/lib/AST/ExprConstant.cpp (original)
> +++ cfe/trunk/lib/AST/ExprConstant.cpp Wed Feb 15 22:12:21 2017
> @@ -425,6 +425,17 @@ namespace {
>  /// Index - The call index of this call.
>  unsigned Index;
>
> +// FIXME: Adding this to every 'CallStackFrame' may have a nontrivial
> impact
> +// on the overall stack usage of deeply-recursing constexpr
> evaluataions.
> +// (We should cache this map rather than recomputing it repeatedly.)
> +// But let's try this and see how it goes; we can look into caching
> the map
> +// as a later change.
> +
> +/// LambdaCaptureFields - Mapping from captured variables/this to
> +/// corresponding data members in the closure class.
> +llvm::DenseMap LambdaCaptureFields;
> +FieldDecl *LambdaThisCaptureField;
> +
>  CallStackFrame(EvalInfo &Info, SourceLocation CallLoc,
> const FunctionDecl *Callee, const LValue *This,
> APValue *Arguments);
> @@ -2279,6 +2290,10 @@ static bool HandleLValueComplexElement(E
>return true;
>  }
>
> +static bool handleLValueToRValueConversion(EvalInfo &Info, const Expr
> *Conv,
> +   QualType Type, const LValue
> &LVal,
> +   APValue &RVal);
> +
>  /// Try to evaluate the initializer for a variable declaration.
>  ///
>  /// \param Info   Information about the ongoing evaluation.
> @@ -2290,6 +2305,7 @@ static bool HandleLValueComplexElement(E
>  static bool evaluateVarDeclInit(EvalInfo &Info, const Expr *E,
>  const VarDecl *VD, CallStackFrame *Frame,
>  APValue *&Result) {
> +
>// If this is a parameter to an active constexpr function call, perform
>// argument substitution.
>if (const ParmVarDecl *PVD = dyn_cast(VD)) {
> @@ -4180,6 +4196,10 @@ static bool HandleFunctionCall(SourceLoc
>return false;
>  This->moveInto(Result);
>  return true;
> +  } else if (MD && isLambdaCallOperator(MD)) {
> +// We're in a lambda; determine the lambda capture field maps.
> +MD->getParent()->getCaptureFields(Frame.LambdaCaptureFields,
> +  Frame.LambdaThisCaptureField);
>}
>
>StmtResult Ret = {Result, ResultSlot};
> @@ -5041,6 +5061,33 @@ bool LValueExprEvaluator::VisitDeclRefEx
>
>
>  bool LValueExprEvaluator::VisitVarDecl(const Expr *E, const VarDecl *VD)
> {
> +
> +  // If we are within a lambda's call operator, check whether the 'VD'
> referred
> +  // to within 'E' actually represents a lambda-capture that maps to a
> +  // data-member/field within the closure object, and if so, evaluate to
> the
> +  // field or what the field refers to.
> +  if (Info.CurrentCall && isLambdaCallOperator(Info.CurrentCall->Callee))
> {
> +if (auto *FD = Info.CurrentCall->LambdaCaptureFields.lookup(VD)) {
> +  if (Info.checkingPotentialConstantExpression())
> +return false;
> +  // Start with 'Result' referring to the complete closure object...
> +  Result = *Info.CurrentCall->This;
> +  // ... then update it to refer to the field of the closure object
> +  // that represents the capture.
> +  if (!HandleLValueMember(Info, E, Result, FD))
> +return false;
> +  // And if the field is of reference type, update 'Result' to refer
> to what
> +  // the field refers to.
> +  if (FD->g

r295279 - [cxx1z-constexpr-lambda] Implement captures - thus completing implementation of constexpr lambdas.

2017-02-15 Thread Faisal Vali via cfe-commits
Author: faisalv
Date: Wed Feb 15 22:12:21 2017
New Revision: 295279

URL: http://llvm.org/viewvc/llvm-project?rev=295279&view=rev
Log:
[cxx1z-constexpr-lambda] Implement captures - thus completing implementation of 
constexpr lambdas.

Enable evaluation of captures within constexpr lambdas by using a strategy 
similar to that used in CodeGen:
  - when starting evaluation of a lambda's call operator, create a map from 
VarDecl's to a closure's FieldDecls
  - every time a VarDecl (or '*this) that represents a capture is encountered 
while evaluating the expression via the expression evaluator (specifically the 
LValueEvaluator) in ExprConstant.cpp - it is replaced by the corresponding 
FieldDecl LValue (an Lvalue-to-Rvalue conversion on this LValue representation 
then determines the right rvalue when needed).

Thanks to Richard Smith and Hubert Tong for their review and feedback!

https://reviews.llvm.org/D29748


Modified:
cfe/trunk/lib/AST/ExprConstant.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=295279&r1=295278&r2=295279&view=diff
==
--- cfe/trunk/lib/AST/ExprConstant.cpp (original)
+++ cfe/trunk/lib/AST/ExprConstant.cpp Wed Feb 15 22:12:21 2017
@@ -425,6 +425,17 @@ namespace {
 /// Index - The call index of this call.
 unsigned Index;
 
+// FIXME: Adding this to every 'CallStackFrame' may have a nontrivial 
impact
+// on the overall stack usage of deeply-recursing constexpr evaluataions.
+// (We should cache this map rather than recomputing it repeatedly.)
+// But let's try this and see how it goes; we can look into caching the map
+// as a later change.
+
+/// LambdaCaptureFields - Mapping from captured variables/this to
+/// corresponding data members in the closure class.
+llvm::DenseMap LambdaCaptureFields;
+FieldDecl *LambdaThisCaptureField;
+
 CallStackFrame(EvalInfo &Info, SourceLocation CallLoc,
const FunctionDecl *Callee, const LValue *This,
APValue *Arguments);
@@ -2279,6 +2290,10 @@ static bool HandleLValueComplexElement(E
   return true;
 }
 
+static bool handleLValueToRValueConversion(EvalInfo &Info, const Expr *Conv,
+   QualType Type, const LValue &LVal,
+   APValue &RVal);
+
 /// Try to evaluate the initializer for a variable declaration.
 ///
 /// \param Info   Information about the ongoing evaluation.
@@ -2290,6 +2305,7 @@ static bool HandleLValueComplexElement(E
 static bool evaluateVarDeclInit(EvalInfo &Info, const Expr *E,
 const VarDecl *VD, CallStackFrame *Frame,
 APValue *&Result) {
+
   // If this is a parameter to an active constexpr function call, perform
   // argument substitution.
   if (const ParmVarDecl *PVD = dyn_cast(VD)) {
@@ -4180,6 +4196,10 @@ static bool HandleFunctionCall(SourceLoc
   return false;
 This->moveInto(Result);
 return true;
+  } else if (MD && isLambdaCallOperator(MD)) {
+// We're in a lambda; determine the lambda capture field maps.
+MD->getParent()->getCaptureFields(Frame.LambdaCaptureFields,
+  Frame.LambdaThisCaptureField);
   }
 
   StmtResult Ret = {Result, ResultSlot};
@@ -5041,6 +5061,33 @@ bool LValueExprEvaluator::VisitDeclRefEx
 
 
 bool LValueExprEvaluator::VisitVarDecl(const Expr *E, const VarDecl *VD) {
+
+  // If we are within a lambda's call operator, check whether the 'VD' referred
+  // to within 'E' actually represents a lambda-capture that maps to a
+  // data-member/field within the closure object, and if so, evaluate to the
+  // field or what the field refers to.
+  if (Info.CurrentCall && isLambdaCallOperator(Info.CurrentCall->Callee)) {
+if (auto *FD = Info.CurrentCall->LambdaCaptureFields.lookup(VD)) {
+  if (Info.checkingPotentialConstantExpression())
+return false;
+  // Start with 'Result' referring to the complete closure object...
+  Result = *Info.CurrentCall->This;
+  // ... then update it to refer to the field of the closure object
+  // that represents the capture.
+  if (!HandleLValueMember(Info, E, Result, FD))
+return false;
+  // And if the field is of reference type, update 'Result' to refer to 
what
+  // the field refers to.
+  if (FD->getType()->isReferenceType()) {
+APValue RVal;
+if (!handleLValueToRValueConversion(Info, E, FD->getType(), Result,
+RVal))
+  return false;
+Result.setFrom(Info.Ctx, RVal);
+  }
+  return true;
+}
+  }
   CallStackFrame *Frame = nullptr;
   if (VD->hasLocalStorage() && Info.CurrentCall->Index > 1) {
 // Only if a local variable was d