https://github.com/Sirraide created https://github.com/llvm/llvm-project/pull/154276
We have a flag that tracks whether a `CXXThisExpr` refers to a `*this` capture in a lambda with a dependent explicit object parameter; this is to mark it and member accesses involving it as dependent because there is no other way to track that (DREs have a similar flag); when instantiating the lambda, we need to always rebuild the `CXXThisExpr` to potentially clear that flag if the explicit object parameter is no longer dependent. Fixes #154054. >From cd2b97cdd9d6cc3f575d71cee24c8f42f57bdb6a Mon Sep 17 00:00:00 2001 From: Sirraide <aeternalm...@gmail.com> Date: Tue, 19 Aug 2025 08:57:23 +0200 Subject: [PATCH] [Clang] [Sema] Always rebuild 'this' captured by value in a lambda with a dependent explicit object parameter --- clang/docs/ReleaseNotes.rst | 2 ++ clang/lib/Sema/TreeTransform.h | 7 ++++-- clang/test/CodeGenCXX/cxx2b-deducing-this.cpp | 25 +++++++++++++++++++ 3 files changed, 32 insertions(+), 2 deletions(-) diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index b86a9c437ffb1..7eccd6f4d2b92 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -234,6 +234,8 @@ Bug Fixes to C++ Support "intializing multiple members of union" coincide (#GH149985). - Fix a crash when using ``explicit(bool)`` in pre-C++11 language modes. (#GH152729) - Fix the parsing of variadic member functions when the ellipis immediately follows a default argument.(#GH153445) +- Fixed a bug that caused ``this`` captured by value in a lambda with a dependent explicit object parameter to not be + instantiated properly. (#GH154054) Bug Fixes to AST Handling ^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 055d3cd1a8609..485b1fa6f6875 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -14307,7 +14307,9 @@ TreeTransform<Derived>::TransformCXXThisExpr(CXXThisExpr *E) { // for type deduction, so we need to recompute it. // // Always recompute the type if we're in the body of a lambda, and - // 'this' is dependent on a lambda's explicit object parameter. + // 'this' is dependent on a lambda's explicit object parameter; we + // also need to always rebuild the expression in this case to clear + // the flag. QualType T = [&]() { auto &S = getSema(); if (E->isCapturedByCopyInLambdaWithExplicitObjectParameter()) @@ -14317,7 +14319,8 @@ TreeTransform<Derived>::TransformCXXThisExpr(CXXThisExpr *E) { return S.getCurrentThisType(); }(); - if (!getDerived().AlwaysRebuild() && T == E->getType()) { + if (!getDerived().AlwaysRebuild() && T == E->getType() && + !E->isCapturedByCopyInLambdaWithExplicitObjectParameter()) { // Mark it referenced in the new context regardless. // FIXME: this is a bit instantiation-specific. getSema().MarkThisReferenced(E); diff --git a/clang/test/CodeGenCXX/cxx2b-deducing-this.cpp b/clang/test/CodeGenCXX/cxx2b-deducing-this.cpp index 8a78463d3a495..7325121582324 100644 --- a/clang/test/CodeGenCXX/cxx2b-deducing-this.cpp +++ b/clang/test/CodeGenCXX/cxx2b-deducing-this.cpp @@ -264,3 +264,28 @@ void test() { // CHECK: call void @_ZNH5P27971C1cERKS0_ // CHECK: call void @_ZN5P27971C1cEi } + +// This used to crash because we weren’t instantiating a dependent 'this'. +namespace GH154054 { +struct S { + int x; + auto byval() { + return [*this](this auto) { return this->x; }; + } +}; + +void main() { + S s{ 42 }; + + if ( s.byval()() != 42) + __builtin_abort(); +} + +struct s { + auto f() { return [*this](this auto) { return this; }; } +}; + +void f() { + s().f()(); +} +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits