diff --git a/clang/lib/AST/Interp/Function.h b/clang/lib/AST/Interp/Function.h index 0be4564e1e9ec4..92bcd96927912d 100644 --- a/clang/lib/AST/Interp/Function.h +++ b/clang/lib/AST/Interp/Function.h @@ -196,6 +196,12 @@ class Function final { return ArgSize - (align(primSize(PT_Ptr)) * (hasThisPointer() + hasRVO())); } + bool isThisPointerExplicit() const { + if (const auto *MD = dyn_cast(F)) + return MD->isExplicitObjectMemberFunction(); + return false; + } + unsigned getParamOffset(unsigned ParamIndex) const { return ParamOffsets[ParamIndex]; } diff --git a/clang/lib/AST/Interp/Interp.h b/clang/lib/AST/Interp/Interp.h index 784e138e1467d4..1ce92798150c5d 100644 --- a/clang/lib/AST/Interp/Interp.h +++ b/clang/lib/AST/Interp/Interp.h @@ -2442,6 +2442,11 @@ inline bool CallPtr(InterpState &S, CodePtr OpPC, uint32_t ArgSize, assert(ArgSize >= F->getWrittenArgSize()); uint32_t VarArgSize = ArgSize - F->getWrittenArgSize(); + // We need to do this explicitly here since we don't have the necessary + // information to do it automatically. + if (F->isThisPointerExplicit()) + VarArgSize -= align(primSize(PT_Ptr)); + if (F->isVirtual()) return CallVirt(S, OpPC, F, VarArgSize); diff --git a/clang/test/AST/Interp/lambda.cpp b/clang/test/AST/Interp/lambda.cpp index 0eb12643b1b7f4..c4fce283ec45a5 100644 --- a/clang/test/AST/Interp/lambda.cpp +++ b/clang/test/AST/Interp/lambda.cpp @@ -280,3 +280,14 @@ namespace InvalidCapture { } (); } } + +namespace ExplicitInstancePointer { + struct C { + constexpr C(auto) { } + }; + void foo() { + constexpr auto b = [](this C) { return 1; }; + constexpr int (*fp)(C) = b; + static_assert(fp(1) == 1, ""); + } +}