Projects
Mega:24.03:SP1:Everything
clang
_service:tar_scm:0010-Backport-clang-Avoid-Wsha...
Sign Up
Log In
Username
Password
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File _service:tar_scm:0010-Backport-clang-Avoid-Wshadow-warning-when-init-capture-named.patch of Package clang
From 6804a15df7959a14b97d41dd8c069d2d695392e4 Mon Sep 17 00:00:00 2001 From: Mariya Podchishchaeva <mariya.podchishchaeva@intel.com> Date: Mon, 12 Feb 2024 12:44:20 +0300 Subject: [PATCH] [clang] Avoid -Wshadow warning when init-capture named same as class field (#74512) Shadowing warning doesn't make much sense since field is not available in lambda's body without capturing this. Fixes https://github.com/llvm/llvm-project/issues/71976 (cherry picked from commit c13b7485b87909fcf739f62cfa382b55407433c0) --- clang/docs/ReleaseNotes.rst | 3 + clang/include/clang/Sema/ScopeInfo.h | 4 +- clang/lib/Sema/SemaDecl.cpp | 73 +++++++++------ clang/test/SemaCXX/warn-shadow-in-lambdas.cpp | 92 ++++++++++++++++++- 4 files changed, 141 insertions(+), 31 deletions(-) diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index a1143e14562e..5086a56eb496 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -730,6 +730,9 @@ Bug Fixes in This Version ``thread_local`` instead of ``_Thread_local``. Fixes (`#70068 <https://github.com/llvm/llvm-project/issues/70068>`_) and (`#69167 <https://github.com/llvm/llvm-project/issues/69167>`_) +- Clang's ``-Wshadow`` no longer warns when an init-capture is named the same as + a class field unless the lambda can capture this. + Fixes (`#71976 <https://github.com/llvm/llvm-project/issues/71976>`_) Bug Fixes to Compiler Builtins ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/include/clang/Sema/ScopeInfo.h b/clang/include/clang/Sema/ScopeInfo.h index 26c0387dfc44..f4e1dba4e20d 100644 --- a/clang/include/clang/Sema/ScopeInfo.h +++ b/clang/include/clang/Sema/ScopeInfo.h @@ -915,8 +915,8 @@ public: /// that were defined in parent contexts. Used to avoid warnings when the /// shadowed variables are uncaptured by this lambda. struct ShadowedOuterDecl { - const VarDecl *VD; - const VarDecl *ShadowedDecl; + const NamedDecl *VD; + const NamedDecl *ShadowedDecl; }; llvm::SmallVector<ShadowedOuterDecl, 4> ShadowingDecls; diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 21b5781a71cd..5481bbd22c66 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -8269,28 +8269,40 @@ void Sema::CheckShadow(NamedDecl *D, NamedDecl *ShadowedDecl, unsigned WarningDiag = diag::warn_decl_shadow; SourceLocation CaptureLoc; - if (isa<VarDecl>(D) && isa<VarDecl>(ShadowedDecl) && NewDC && - isa<CXXMethodDecl>(NewDC)) { + if (isa<VarDecl>(D) && NewDC && isa<CXXMethodDecl>(NewDC)) { if (const auto *RD = dyn_cast<CXXRecordDecl>(NewDC->getParent())) { if (RD->isLambda() && OldDC->Encloses(NewDC->getLexicalParent())) { - if (RD->getLambdaCaptureDefault() == LCD_None) { - // Try to avoid warnings for lambdas with an explicit capture list. + if (const auto *VD = dyn_cast<VarDecl>(ShadowedDecl)) { const auto *LSI = cast<LambdaScopeInfo>(getCurFunction()); - // Warn only when the lambda captures the shadowed decl explicitly. - CaptureLoc = getCaptureLocation(LSI, cast<VarDecl>(ShadowedDecl)); - if (CaptureLoc.isInvalid()) - WarningDiag = diag::warn_decl_shadow_uncaptured_local; - } else { - // Remember that this was shadowed so we can avoid the warning if the - // shadowed decl isn't captured and the warning settings allow it. + if (RD->getLambdaCaptureDefault() == LCD_None) { + // Try to avoid warnings for lambdas with an explicit capture + // list. Warn only when the lambda captures the shadowed decl + // explicitly. + CaptureLoc = getCaptureLocation(LSI, VD); + if (CaptureLoc.isInvalid()) + WarningDiag = diag::warn_decl_shadow_uncaptured_local; + } else { + // Remember that this was shadowed so we can avoid the warning if + // the shadowed decl isn't captured and the warning settings allow + // it. + cast<LambdaScopeInfo>(getCurFunction()) + ->ShadowingDecls.push_back({D, VD}); + return; + } + } + if (isa<FieldDecl>(ShadowedDecl)) { + // If lambda can capture this, then emit default shadowing warning, + // Otherwise it is not really a shadowing case since field is not + // available in lambda's body. + // At this point we don't know that lambda can capture this, so + // remember that this was shadowed and delay until we know. cast<LambdaScopeInfo>(getCurFunction()) - ->ShadowingDecls.push_back( - {cast<VarDecl>(D), cast<VarDecl>(ShadowedDecl)}); + ->ShadowingDecls.push_back({D, ShadowedDecl}); return; } } - - if (cast<VarDecl>(ShadowedDecl)->hasLocalStorage()) { + if (const auto *VD = dyn_cast<VarDecl>(ShadowedDecl); + VD && VD->hasLocalStorage()) { // A variable can't shadow a local variable in an enclosing scope, if // they are separated by a non-capturing declaration context. for (DeclContext *ParentDC = NewDC; @@ -8337,19 +8349,28 @@ void Sema::CheckShadow(NamedDecl *D, NamedDecl *ShadowedDecl, /// when these variables are captured by the lambda. void Sema::DiagnoseShadowingLambdaDecls(const LambdaScopeInfo *LSI) { for (const auto &Shadow : LSI->ShadowingDecls) { - const VarDecl *ShadowedDecl = Shadow.ShadowedDecl; + const NamedDecl *ShadowedDecl = Shadow.ShadowedDecl; // Try to avoid the warning when the shadowed decl isn't captured. - SourceLocation CaptureLoc = getCaptureLocation(LSI, ShadowedDecl); const DeclContext *OldDC = ShadowedDecl->getDeclContext(); - Diag(Shadow.VD->getLocation(), CaptureLoc.isInvalid() - ? diag::warn_decl_shadow_uncaptured_local - : diag::warn_decl_shadow) - << Shadow.VD->getDeclName() - << computeShadowedDeclKind(ShadowedDecl, OldDC) << OldDC; - if (!CaptureLoc.isInvalid()) - Diag(CaptureLoc, diag::note_var_explicitly_captured_here) - << Shadow.VD->getDeclName() << /*explicitly*/ 0; - Diag(ShadowedDecl->getLocation(), diag::note_previous_declaration); + if (const auto *VD = dyn_cast<VarDecl>(ShadowedDecl)) { + SourceLocation CaptureLoc = getCaptureLocation(LSI, VD); + Diag(Shadow.VD->getLocation(), + CaptureLoc.isInvalid() ? diag::warn_decl_shadow_uncaptured_local + : diag::warn_decl_shadow) + << Shadow.VD->getDeclName() + << computeShadowedDeclKind(ShadowedDecl, OldDC) << OldDC; + if (CaptureLoc.isValid()) + Diag(CaptureLoc, diag::note_var_explicitly_captured_here) + << Shadow.VD->getDeclName() << /*explicitly*/ 0; + Diag(ShadowedDecl->getLocation(), diag::note_previous_declaration); + } else if (isa<FieldDecl>(ShadowedDecl)) { + Diag(Shadow.VD->getLocation(), + LSI->isCXXThisCaptured() ? diag::warn_decl_shadow + : diag::warn_decl_shadow_uncaptured_local) + << Shadow.VD->getDeclName() + << computeShadowedDeclKind(ShadowedDecl, OldDC) << OldDC; + Diag(ShadowedDecl->getLocation(), diag::note_previous_declaration); + } } } diff --git a/clang/test/SemaCXX/warn-shadow-in-lambdas.cpp b/clang/test/SemaCXX/warn-shadow-in-lambdas.cpp index bda6a65c0216..d54b394df4eb 100644 --- a/clang/test/SemaCXX/warn-shadow-in-lambdas.cpp +++ b/clang/test/SemaCXX/warn-shadow-in-lambdas.cpp @@ -1,6 +1,6 @@ -// RUN: %clang_cc1 -std=c++14 -verify -fsyntax-only -Wshadow -D AVOID %s -// RUN: %clang_cc1 -std=c++14 -verify -fsyntax-only -Wshadow -Wshadow-uncaptured-local %s -// RUN: %clang_cc1 -std=c++14 -verify -fsyntax-only -Wshadow-all %s +// RUN: %clang_cc1 -std=c++14 -verify=expected,cxx14 -fsyntax-only -Wshadow -D AVOID %s +// RUN: %clang_cc1 -std=c++14 -verify=expected,cxx14 -fsyntax-only -Wshadow -Wshadow-uncaptured-local %s +// RUN: %clang_cc1 -std=c++14 -verify=expected,cxx14 -fsyntax-only -Wshadow-all %s // RUN: %clang_cc1 -std=c++17 -verify -fsyntax-only -Wshadow-all %s // RUN: %clang_cc1 -std=c++20 -verify -fsyntax-only -Wshadow-all %s @@ -179,3 +179,89 @@ void f() { #endif } } + +namespace GH71976 { +#ifdef AVOID +struct A { + int b = 5; + int foo() { + return [b = b]() { return b; }(); // no -Wshadow diagnostic, init-capture does not shadow b due to not capturing this + } +}; + +struct B { + int a; + void foo() { + auto b = [a = this->a] {}; // no -Wshadow diagnostic, init-capture does not shadow a due to not capturing his + } +}; + +struct C { + int b = 5; + int foo() { + return [a = b]() { + return [=, b = a]() { // no -Wshadow diagnostic, init-capture does not shadow b due to outer lambda + return b; + }(); + }(); + } +}; + +#else +struct A { + int b = 5; // expected-note {{previous}} + int foo() { + return [b = b]() { return b; }(); // expected-warning {{declaration shadows a field}} + } +}; + +struct B { + int a; // expected-note {{previous}} + void foo() { + auto b = [a = this->a] {}; // expected-warning {{declaration shadows a field}} + } +}; + +struct C { + int b = 5; // expected-note {{previous}} + int foo() { + return [a = b]() { + return [=, b = a]() { // expected-warning {{declaration shadows a field}} + return b; + }(); + }(); + } +}; + +struct D { + int b = 5; // expected-note {{previous}} + int foo() { + return [b = b, this]() { return b; }(); // expected-warning {{declaration shadows a field}} + } +}; + +struct E { + int b = 5; + int foo() { + return [a = b]() { // expected-note {{previous}} + return [=, a = a]() { // expected-warning {{shadows a local}} + return a; + }(); + }(); + } +}; + +#endif + +struct S { + int a ; +}; + +int foo() { + auto [a] = S{0}; // expected-note {{previous}} \ + // cxx14-warning {{decomposition declarations are a C++17 extension}} + [a = a] () { // expected-warning {{declaration shadows a structured binding}} + }(); +} + +} -- 2.33.0
Locations
Projects
Search
Status Monitor
Help
Open Build Service
OBS Manuals
API Documentation
OBS Portal
Reporting a Bug
Contact
Mailing List
Forums
Chat (IRC)
Twitter
Open Build Service (OBS)
is an
openSUSE project
.
浙ICP备2022010568号-2