From 2b9ad0f1609fa7926448451750eccfcfa080b520 Mon Sep 17 00:00:00 2001 From: Oleksandr Tarasiuk Date: Fri, 31 Oct 2025 22:54:53 +0200 Subject: [PATCH 1/4] [Clang] fix false-positive lambda shadow diagnostics in explicit-object member functions --- clang/docs/ReleaseNotes.rst | 1 + clang/lib/Sema/SemaDecl.cpp | 4 ++-- clang/test/SemaCXX/cxx2b-warn-shadow.cpp | 26 ++++++++++++++++++++++++ 3 files changed, 29 insertions(+), 2 deletions(-) diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 92fc9381a5868..593e117777314 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -432,6 +432,7 @@ Bug Fixes in This Version - Fixed a failed assertion with empty filename arguments in ``__has_embed``. (#GH159898) - Fixed a failed assertion with empty filename in ``#embed`` directive. (#GH162951) - Fixed a crash triggered by unterminated ``__has_embed``. (#GH162953) +- Fixed false-positive shadow diagnostics for lambdas in explicit object member functions. (#GH163731) Bug Fixes to Compiler Builtins ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index fc3aabf5741ca..47423adf38612 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -8492,12 +8492,12 @@ void Sema::CheckShadow(NamedDecl *D, NamedDecl *ShadowedDecl, DeclContext *NewDC = D->getDeclContext(); if (FieldDecl *FD = dyn_cast(ShadowedDecl)) { - if (CXXMethodDecl *MD = dyn_cast(NewDC)) { + if (CXXMethodDecl *MD = dyn_cast(getFunctionLevelDeclContext())) { // Fields are not shadowed by variables in C++ static methods. if (MD->isStatic()) return; - if (!MD->getParent()->isLambda() && MD->isExplicitObjectMemberFunction()) + if (MD->isExplicitObjectMemberFunction()) return; } // Fields shadowed by constructor parameters are a special case. Usually diff --git a/clang/test/SemaCXX/cxx2b-warn-shadow.cpp b/clang/test/SemaCXX/cxx2b-warn-shadow.cpp index 76866c4269474..9ce0c5a7434f5 100644 --- a/clang/test/SemaCXX/cxx2b-warn-shadow.cpp +++ b/clang/test/SemaCXX/cxx2b-warn-shadow.cpp @@ -11,3 +11,29 @@ struct Foo { } }; } // namespace GH95707 + +namespace GH163731 { +struct S1 { + int a; + void m(this S1 &self) { + auto lambda = [](int a) { return a; }; + } +}; + +struct S2 { + int a; + void m(this S2 &self) { + int a = 1; // expected-note {{previous declaration is here}} + auto lambda = [](int a) { // expected-warning {{declaration shadows a local variable}} + return a; + }; + } +}; + +struct S3 { + int a; + void m(this S3 &self) { + auto lambda = [self](int a) { return a + self.a; }; + } +}; +} From e1ecc29b7e6ba070c58bc58b7f809f4d18e97e4c Mon Sep 17 00:00:00 2001 From: Oleksandr Tarasiuk Date: Sat, 1 Nov 2025 16:12:25 +0200 Subject: [PATCH 2/4] fix formatting --- clang/lib/Sema/SemaDecl.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 47423adf38612..25de881bcfce2 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -8492,7 +8492,8 @@ void Sema::CheckShadow(NamedDecl *D, NamedDecl *ShadowedDecl, DeclContext *NewDC = D->getDeclContext(); if (FieldDecl *FD = dyn_cast(ShadowedDecl)) { - if (CXXMethodDecl *MD = dyn_cast(getFunctionLevelDeclContext())) { + if (CXXMethodDecl *MD = + dyn_cast(getFunctionLevelDeclContext())) { // Fields are not shadowed by variables in C++ static methods. if (MD->isStatic()) return; From bcc1fb6b610c2f634657dd30f7f4bf57c6b01954 Mon Sep 17 00:00:00 2001 From: Oleksandr Tarasiuk Date: Sat, 1 Nov 2025 21:31:16 +0200 Subject: [PATCH 3/4] eliminate redundant if condition --- clang/lib/Sema/SemaDecl.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 25de881bcfce2..2e9a6215a8834 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -8494,11 +8494,9 @@ void Sema::CheckShadow(NamedDecl *D, NamedDecl *ShadowedDecl, if (FieldDecl *FD = dyn_cast(ShadowedDecl)) { if (CXXMethodDecl *MD = dyn_cast(getFunctionLevelDeclContext())) { - // Fields are not shadowed by variables in C++ static methods. - if (MD->isStatic()) - return; - - if (MD->isExplicitObjectMemberFunction()) + // Fields aren't shadowed in C++ static members or in member functions + // with an explicit object parameter. + if (MD->isStatic() || MD->isExplicitObjectMemberFunction()) return; } // Fields shadowed by constructor parameters are a special case. Usually From 219b61ca731b40facf67aae87e75c0dd0aaf08c5 Mon Sep 17 00:00:00 2001 From: Oleksandr Tarasiuk Date: Thu, 6 Nov 2025 19:01:01 +0200 Subject: [PATCH 4/4] use auto instead of explicit type --- clang/lib/Sema/SemaDecl.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 2e9a6215a8834..086dd8ba1c670 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -8492,7 +8492,7 @@ void Sema::CheckShadow(NamedDecl *D, NamedDecl *ShadowedDecl, DeclContext *NewDC = D->getDeclContext(); if (FieldDecl *FD = dyn_cast(ShadowedDecl)) { - if (CXXMethodDecl *MD = + if (const auto *MD = dyn_cast(getFunctionLevelDeclContext())) { // Fields aren't shadowed in C++ static members or in member functions // with an explicit object parameter.