diff --git a/clang/lib/AST/Interp/ByteCodeEmitter.h b/clang/lib/AST/Interp/ByteCodeEmitter.h --- a/clang/lib/AST/Interp/ByteCodeEmitter.h +++ b/clang/lib/AST/Interp/ByteCodeEmitter.h @@ -67,7 +67,8 @@ llvm::DenseMap Params; /// Lambda captures. llvm::DenseMap LambdaCaptures; - unsigned LambdaThisCapture; + /// Offset of the This parameter in a lambda record. + unsigned LambdaThisCapture = 0; /// Local descriptors. llvm::SmallVector, 2> Descriptors; diff --git a/clang/lib/AST/Interp/ByteCodeEmitter.cpp b/clang/lib/AST/Interp/ByteCodeEmitter.cpp --- a/clang/lib/AST/Interp/ByteCodeEmitter.cpp +++ b/clang/lib/AST/Interp/ByteCodeEmitter.cpp @@ -64,8 +64,8 @@ this->LambdaCaptures[Cap.first] = { Offset, Cap.second->getType()->isReferenceType()}; } - // FIXME: LambdaThisCapture - (void)LTC; + if (LTC) + this->LambdaThisCapture = R->getField(LTC)->Offset; } } diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.cpp b/clang/lib/AST/Interp/ByteCodeExprGen.cpp --- a/clang/lib/AST/Interp/ByteCodeExprGen.cpp +++ b/clang/lib/AST/Interp/ByteCodeExprGen.cpp @@ -2305,6 +2305,10 @@ bool ByteCodeExprGen::VisitCXXThisExpr(const CXXThisExpr *E) { if (DiscardResult) return true; + + if (this->LambdaThisCapture > 0) + return this->emitGetThisFieldPtr(this->LambdaThisCapture, E); + return this->emitThis(E); } diff --git a/clang/lib/AST/Interp/EvalEmitter.h b/clang/lib/AST/Interp/EvalEmitter.h --- a/clang/lib/AST/Interp/EvalEmitter.h +++ b/clang/lib/AST/Interp/EvalEmitter.h @@ -73,7 +73,8 @@ llvm::DenseMap Params; /// Lambda captures. llvm::DenseMap LambdaCaptures; - unsigned LambdaThisCapture; + /// Offset of the This parameter in a lambda record. + unsigned LambdaThisCapture = 0; /// Local descriptors. llvm::SmallVector, 2> Descriptors; diff --git a/clang/test/AST/Interp/lambda.cpp b/clang/test/AST/Interp/lambda.cpp --- a/clang/test/AST/Interp/lambda.cpp +++ b/clang/test/AST/Interp/lambda.cpp @@ -179,3 +179,24 @@ } static_assert(heh() == 1.0); } + +namespace ThisCapture { + class Foo { + public: + int b = 32; + int a; + + constexpr Foo() : a([this](){ return b + 1;}()) {} + + constexpr int Aplus2() const { + auto F = [this]() { + return a + 2; + }; + + return F(); + } + }; + constexpr Foo F; + static_assert(F.a == 33, ""); + static_assert(F.Aplus2() == (33 + 2), ""); +}