From d3c5351c0bddd0bf9cd743471beafbf18bbab77c Mon Sep 17 00:00:00 2001 From: Corentin Jabot Date: Tue, 3 Oct 2023 13:19:50 +0200 Subject: [PATCH 1/2] [Clang] Fix constant evaluating a captured variable in a lambda with an explicit parameter. Fixes #68070 --- clang/lib/AST/ExprConstant.cpp | 8 +++++++- .../SemaCXX/cxx2b-deducing-this-constexpr.cpp | 18 ++++++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index a142ea7c47a47..e8bf037c879c6 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -8366,8 +8366,14 @@ bool LValueExprEvaluator::VisitVarDecl(const Expr *E, const VarDecl *VD) { return false; if (auto *FD = Info.CurrentCall->LambdaCaptureFields.lookup(VD)) { + auto *MD = cast(Info.CurrentCall->Callee); // Start with 'Result' referring to the complete closure object... - Result = *Info.CurrentCall->This; + if (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)) diff --git a/clang/test/SemaCXX/cxx2b-deducing-this-constexpr.cpp b/clang/test/SemaCXX/cxx2b-deducing-this-constexpr.cpp index 44de0d711674b..9dbea17dd2cae 100644 --- a/clang/test/SemaCXX/cxx2b-deducing-this-constexpr.cpp +++ b/clang/test/SemaCXX/cxx2b-deducing-this-constexpr.cpp @@ -54,3 +54,21 @@ consteval void test() { static_assert(*s == 42); static_assert((s << 11) == 31); } + +namespace GH68070 { + +constexpr auto f = [x = 3](this Self&& self) { + return x; +}; + +auto g = [x = 3](this Self&& self) { + return x; +}; + +int test() { + constexpr int a = f(); + static_assert(a == 3); + return f() + g(); +} + +} From 535fda1ccf5804f2c350b58ced8ee5e98c6583bd Mon Sep 17 00:00:00 2001 From: Corentin Jabot Date: Tue, 3 Oct 2023 14:17:54 +0200 Subject: [PATCH 2/2] Address Timm's feedback --- clang/lib/AST/ExprConstant.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index e8bf037c879c6..d77597d063eb2 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -8366,9 +8366,9 @@ bool LValueExprEvaluator::VisitVarDecl(const Expr *E, const VarDecl *VD) { return false; if (auto *FD = Info.CurrentCall->LambdaCaptureFields.lookup(VD)) { - auto *MD = cast(Info.CurrentCall->Callee); // Start with 'Result' referring to the complete closure object... - if (MD->isExplicitObjectMemberFunction()) { + if (auto *MD = cast(Info.CurrentCall->Callee); + MD->isExplicitObjectMemberFunction()) { APValue *RefValue = Info.getParamSlot(Info.CurrentCall->Arguments, MD->getParamDecl(0)); Result.setFrom(Info.Ctx, *RefValue);