diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 0c369a7f45057..92fe909e5e8a6 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 859224780befa..aac57196012aa 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 b4b0620395cf7..212ca8803b6fb 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 e5d4c69dcee06..bda6a65c02168 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 4e1a3c393a9db..de0db219cb9b7 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