diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -225,6 +225,9 @@ - Fix an issue about ``decltype`` in the members of class templates derived from templates with related parameters. (`#58674 `_) +- Stop stripping CV qualifiers from the type of ``this`` when capturing it by value in + a lambda. + (`#50866 `_) Bug Fixes to AST Handling ^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -1135,8 +1135,7 @@ auto C = CurLSI->getCXXThisCapture(); if (C.isCopyCapture()) { - ClassType.removeLocalCVRQualifiers(Qualifiers::CVRMask); - if (!CurLSI->Mutable) + if (!CurLSI->Mutable) ClassType.addConst(); return ASTCtx.getPointerType(ClassType); } @@ -1175,7 +1174,6 @@ while (Closure && IsThisCaptured(Closure, IsByCopyCapture, IsConstCapture)) { if (IsByCopyCapture) { - ClassType.removeLocalCVRQualifiers(Qualifiers::CVRMask); if (IsConstCapture) ClassType.addConst(); return ASTCtx.getPointerType(ClassType); @@ -1362,15 +1360,7 @@ // The type of the corresponding data member (not a 'this' pointer if 'by // copy'). - QualType CaptureType = ThisTy; - if (ByCopy) { - // If we are capturing the object referred to by '*this' by copy, ignore - // any cv qualifiers inherited from the type of the member function for - // the type of the closure-type's corresponding data member and any use - // of 'this'. - CaptureType = ThisTy->getPointeeType(); - CaptureType.removeLocalCVRQualifiers(Qualifiers::CVRMask); - } + QualType CaptureType = ByCopy ? ThisTy->getPointeeType() : ThisTy; bool isNested = NumCapturingClosures > 1; CSI->addThisCapture(isNested, Loc, CaptureType, ByCopy); diff --git a/clang/test/SemaCXX/cxx1z-lambda-star-this.cpp b/clang/test/SemaCXX/cxx1z-lambda-star-this.cpp --- a/clang/test/SemaCXX/cxx1z-lambda-star-this.cpp +++ b/clang/test/SemaCXX/cxx1z-lambda-star-this.cpp @@ -88,13 +88,11 @@ void foo() const { //expected-note{{const}} auto L = [*this]() mutable { - static_assert(is_same); - ++d; + static_assert(is_same); auto M = [this] { - static_assert(is_same); - ++d; + static_assert(is_same); auto N = [] { - static_assert(is_same); + static_assert(is_same); }; }; }; @@ -108,9 +106,9 @@ }; }; auto M2 = [*this]() mutable { - static_assert(is_same); + static_assert(is_same); auto N = [] { - static_assert(is_same); + static_assert(is_same); }; }; }; @@ -126,9 +124,9 @@ }; auto M2 = [*this](auto a) mutable { - static_assert(is_same); + static_assert(is_same); auto N = [](auto b) { - static_assert(is_same); + static_assert(is_same); }; return N; }; @@ -143,13 +141,11 @@ ++d; //expected-error{{cannot assign}} }; auto GL = [*this](auto a) mutable { - static_assert(is_same); - ++d; + static_assert(is_same); auto M = [this](auto b) { - static_assert(is_same); - ++d; + static_assert(is_same); auto N = [](auto c) { - static_assert(is_same); + static_assert(is_same); }; N(3.14); }; @@ -161,21 +157,21 @@ auto L = [this]() { static_assert(is_same); auto M = [*this]() mutable { - static_assert(is_same); + static_assert(is_same); auto N = [this] { - static_assert(is_same); + static_assert(is_same); auto M = [] { - static_assert(is_same); + static_assert(is_same); }; }; auto N2 = [*this] { - static_assert(is_same); + static_assert(is_same); }; }; auto M2 = [*this]() { - static_assert(is_same); + static_assert(is_same); auto N = [this] { - static_assert(is_same); + static_assert(is_same); }; }; }; @@ -190,14 +186,13 @@ auto L = [*this]() mutable { auto M = [=](auto a) { auto N = [this] { - ++d; - static_assert(is_same); + static_assert(is_same); auto O = [*this] { static_assert(is_same); }; }; N(); - static_assert(is_same); + static_assert(is_same); }; return M; }; @@ -308,3 +303,22 @@ z(id,3); } } // namespace PR45881 + + +namespace GH50866 { +struct S; + +void f(S *) = delete; // expected-note {{would lose const qualifier}} +void f(const S *) = delete; // expected-note {{candidate function has been explicitly deleted}} + +struct S { + void g() const { + [*this]() mutable { f(this); }(); // expected-error {{call to deleted function}} + } +}; + +void g() { + S s{}; + s.g(); +} +}