[Clang] Fix constant evaluating a captured variable in a lambda (#68090)

with an explicit parameter.

We tried to read a pointer to a non-existent `This` APValue when
constant-evaluating an explicit object lambda call operator (the `this`
pointer is never set in explicit object member functions)

Fixes #68070
This commit is contained in:
cor3ntin 2023-10-05 10:17:50 +02:00 committed by GitHub
parent b74cfc139a
commit 49666ec038
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 25 additions and 1 deletions

View File

@ -8370,7 +8370,13 @@ bool LValueExprEvaluator::VisitVarDecl(const Expr *E, const VarDecl *VD) {
if (auto *FD = Info.CurrentCall->LambdaCaptureFields.lookup(VD)) {
// Start with 'Result' referring to the complete closure object...
Result = *Info.CurrentCall->This;
if (auto *MD = cast<CXXMethodDecl>(Info.CurrentCall->Callee);
MD->isExplicitObjectMemberFunction()) {
APValue *RefValue =
Info.getParamSlot(Info.CurrentCall->Arguments, MD->getParamDecl(0));
Result.setFrom(Info.Ctx, *RefValue);
} else
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))

View File

@ -54,3 +54,21 @@ consteval void test() {
static_assert(*s == 42);
static_assert((s << 11) == 31);
}
namespace GH68070 {
constexpr auto f = [x = 3]<typename Self>(this Self&& self) {
return x;
};
auto g = [x = 3]<typename Self>(this Self&& self) {
return x;
};
int test() {
constexpr int a = f();
static_assert(a == 3);
return f() + g();
}
}