Re: r295279 - [cxx1z-constexpr-lambda] Implement captures - thus completing implementation of constexpr lambdas.
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.
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.
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.
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.
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