From 29dc47a9eeeb2e080170109e3e2fb3cd5aad58d2 Mon Sep 17 00:00:00 2001 From: Takuya Shimizu Date: Wed, 24 May 2023 21:11:56 +0900 Subject: [PATCH] [clang][Sema] `-Wshadow` warns about shadowings by static local variables This patch makes `-Wshadow` warn about the shadowings by static local variables. Fixes https://github.com/llvm/llvm-project/issues/62850 Differential Revision: https://reviews.llvm.org/D151214 --- clang/docs/ReleaseNotes.rst | 2 ++ clang/lib/Sema/SemaDecl.cpp | 2 +- clang/test/Sema/warn-shadow.c | 30 ++++++++++++++++++++++++++- clang/test/SemaCXX/warn-shadow-in-lambdas.cpp | 13 ++++++++++++ clang/test/SemaCXX/warn-shadow.cpp | 7 +++++-- 5 files changed, 50 insertions(+), 4 deletions(-) diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 0c369a7..92fe909 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -299,6 +299,8 @@ Improvements to Clang's diagnostics - Clang constexpr evaluator now prints subobject's name instead of its type in notes when a constexpr variable has uninitialized subobjects after its constructor call. (`#58601 `_) +- Clang's `-Wshadow` warning now warns about shadowings by static local variables + (`#62850: `_). Bug Fixes in This Version ------------------------- diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 8592247..aac5719 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -8150,7 +8150,7 @@ NamedDecl *Sema::getShadowedDeclaration(const VarDecl *D, return nullptr; // Don't diagnose declarations at file scope. - if (D->hasGlobalStorage()) + if (D->hasGlobalStorage() && !D->isStaticLocal()) return nullptr; NamedDecl *ShadowedDecl = R.getFoundDecl(); diff --git a/clang/test/Sema/warn-shadow.c b/clang/test/Sema/warn-shadow.c index b4b0620..212ca88 100644 --- a/clang/test/Sema/warn-shadow.c +++ b/clang/test/Sema/warn-shadow.c @@ -1,18 +1,24 @@ // RUN: %clang_cc1 -verify -fsyntax-only -fblocks -Wshadow %s -int i; // expected-note 3 {{previous declaration is here}} +int i; // expected-note 4 {{previous declaration is here}} +static int s; // expected-note 2 {{previous declaration is here}} void foo(void) { int pass1; int i; // expected-warning {{declaration shadows a variable in the global scope}} \ // expected-note {{previous declaration is here}} + int s; // expected-warning {{declaration shadows a variable in the global scope}} \ + // expected-note {{previous declaration is here}} { int pass2; int i; // expected-warning {{declaration shadows a local variable}} \ // expected-note {{previous declaration is here}} + int s; // expected-warning {{declaration shadows a local variable}} \ + // expected-note {{previous declaration is here}} { int pass3; int i; // expected-warning {{declaration shadows a local variable}} + int s; // expected-warning {{declaration shadows a local variable}} } } @@ -71,3 +77,25 @@ struct PR24718_4 { PR24718_3 // Does not shadow a type. }; }; + +void static_locals() { + static int i; // expected-warning {{declaration shadows a variable in the global scope}} + // expected-note@-1 {{previous definition is here}} + // expected-note@-2 {{previous declaration is here}} + int i; // expected-error {{non-static declaration of 'i' follows static declaration}} + static int foo; // expected-note {{previous declaration is here}} + static int hoge; // expected-note {{previous declaration is here}} + int s; // expected-warning {{declaration shadows a variable in the global scope}} + { + static int foo; // expected-warning {{declaration shadows a local variable}} + // expected-note@-1 {{previous declaration is here}} + static int i; // expected-warning {{declaration shadows a local variable}} + // expected-note@-1 {{previous declaration is here}} + int hoge; // expected-warning {{declaration shadows a local variable}} + { + static int foo; // expected-warning {{declaration shadows a local variable}} + int i; // expected-warning {{declaration shadows a local variable}} + extern int hoge; + } + } +} diff --git a/clang/test/SemaCXX/warn-shadow-in-lambdas.cpp b/clang/test/SemaCXX/warn-shadow-in-lambdas.cpp index e5d4c69..bda6a65 100644 --- a/clang/test/SemaCXX/warn-shadow-in-lambdas.cpp +++ b/clang/test/SemaCXX/warn-shadow-in-lambdas.cpp @@ -14,11 +14,15 @@ void foo(int param) { // expected-note 1+ {{previous declaration is here}} auto f2 = [&] { int var = 2; }; // no warning auto f3 = [=] (int param) { ; }; // no warning auto f4 = [&] (int param) { ; }; // no warning + auto f5 = [=] { static int var = 1; }; // no warning + auto f6 = [&] { static int var = 2; }; // no warning #else auto f1 = [=] { int var = 1; }; // expected-warning {{declaration shadows a local variable}} auto f2 = [&] { int var = 2; }; // expected-warning {{declaration shadows a local variable}} auto f3 = [=] (int param) { ; }; // expected-warning {{declaration shadows a local variable}} auto f4 = [&] (int param) { ; }; // expected-warning {{declaration shadows a local variable}} + auto f5 = [=] { static int var = 1; }; // expected-warning {{declaration shadows a local variable}} + auto f6 = [&] { static int var = 2; }; // expected-warning {{declaration shadows a local variable}} #endif } @@ -67,11 +71,15 @@ void foo(int param) { // expected-note 1+ {{previous declaration is here}} auto f2 = [] (int param) { ; }; // no warning auto f3 = [param] () { int var = 1; }; // no warning auto f4 = [var] (int param) { ; }; // no warning + auto f5 = [param] () { static int var = 1; }; // no warning + auto f6 = [] { static int var = 1; }; // no warning #else auto f1 = [] { int var = 1; }; // expected-warning {{declaration shadows a local variable}} auto f2 = [] (int param) { ; }; // expected-warning {{declaration shadows a local variable}} auto f3 = [param] () { int var = 1; }; // expected-warning {{declaration shadows a local variable}} auto f4 = [var] (int param) { ; }; // expected-warning {{declaration shadows a local variable}} + auto f5 = [param] () { static int var = 1; }; // expected-warning {{declaration shadows a local variable}} + auto f6 = [] { static int var = 1; }; // expected-warning {{declaration shadows a local variable}} #endif }; @@ -127,6 +135,11 @@ void foo(int param) { // expected-note 1+ {{previous declaration is here}} int param = 0; // expected-warning {{declaration shadows a local variable}} }; }; + auto l7 = [&] { + auto f1 = [param] { // expected-note {{variable 'param' is explicitly captured here}} + static int param = 0; // expected-warning {{declaration shadows a local variable}} + }; + }; // Generic lambda arguments should work. #ifdef AVOID diff --git a/clang/test/SemaCXX/warn-shadow.cpp b/clang/test/SemaCXX/warn-shadow.cpp index 4e1a3c3..de0db21 100644 --- a/clang/test/SemaCXX/warn-shadow.cpp +++ b/clang/test/SemaCXX/warn-shadow.cpp @@ -2,6 +2,7 @@ namespace { int i; // expected-note {{previous declaration is here}} + static int s; // expected-note {{previous declaration is here}} } namespace one { @@ -31,6 +32,7 @@ using namespace yy; void foo() { int i; // expected-warning {{declaration shadows a variable in namespace '(anonymous)'}} int j; // expected-warning {{declaration shadows a variable in namespace 'one::two'}} + static int s; // expected-warning {{declaration shadows a variable in namespace '(anonymous)'}} int m; int mm; int mmm; @@ -40,7 +42,7 @@ class A { static int data; // expected-note 1 {{previous declaration}} // expected-note@+1 1 {{previous declaration}} int field; - int f1, f2, f3, f4; // expected-note 8 {{previous declaration is here}} + int f1, f2, f3, f4; // expected-note 9 {{previous declaration is here}} typedef int a1; // expected-note 2 {{previous declaration}} using a2=int; // expected-note 2 {{previous declaration}} @@ -66,6 +68,7 @@ class A { char *a2; // no warning char *jj; // no warning char *jjj; // no warning + static char *f1; // expected-warning {{declaration shadows a field of 'A'}} } void test2() { @@ -305,4 +308,4 @@ void test4() { } } -}; // namespace structured_binding_tests \ No newline at end of file +}; // namespace structured_binding_tests -- 2.7.4