[clang] [Clang] skip shadow warnings for enum constants in distinct class scopes (PR #115656)

Oleksandr T. via cfe-commits cfe-commits at lists.llvm.org
Sun Nov 10 05:12:34 PST 2024


https://github.com/a-tarasyuk created https://github.com/llvm/llvm-project/pull/115656

Fixes #62588

>From e13774913ecba7d66652f10f9a3468a55acb3b42 Mon Sep 17 00:00:00 2001
From: Oleksandr T <oleksandr.tarasiuk at outlook.com>
Date: Sun, 10 Nov 2024 15:11:39 +0200
Subject: [PATCH] [Clang] skip shadow warnings for enum constants in distinct
 class scopes

---
 clang/docs/ReleaseNotes.rst        |  2 ++
 clang/include/clang/Sema/Sema.h    |  2 +-
 clang/lib/Sema/SemaDecl.cpp        | 15 ++++++++++-----
 clang/lib/Sema/SemaDeclCXX.cpp     |  2 +-
 clang/test/SemaCXX/warn-shadow.cpp | 14 ++++++++++++++
 5 files changed, 28 insertions(+), 7 deletions(-)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index c3424e0e6f34c9..f8005c57ea865c 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -527,6 +527,8 @@ Improvements to Clang's diagnostics
 
 - Clang now diagnoses ``[[deprecated]]`` attribute usage on local variables (#GH90073).
 
+- Clang now omits shadow warnings for enum constants in separate class scopes (#GH62588).
+
 Improvements to Clang's time-trace
 ----------------------------------
 
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index fad446a05e782f..8e8097e86764c6 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -3453,7 +3453,7 @@ class Sema final : public SemaBase {
   ///
   /// \param ShadowedDecl the declaration that is shadowed by the given variable
   /// \param R the lookup of the name
-  void CheckShadow(NamedDecl *D, NamedDecl *ShadowedDecl,
+  void CheckShadow(Scope *S, NamedDecl *D, NamedDecl *ShadowedDecl,
                    const LookupResult &R);
 
   /// Check -Wshadow without the advantage of a previous lookup.
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 61c29e320d5c73..7bf7a19de1c6a6 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -6732,7 +6732,7 @@ Sema::ActOnTypedefNameDecl(Scope *S, DeclContext *DC, TypedefNameDecl *NewTD,
   }
 
   if (ShadowedDecl && !Redeclaration)
-    CheckShadow(NewTD, ShadowedDecl, Previous);
+    CheckShadow(S, NewTD, ShadowedDecl, Previous);
 
   // If this is the C FILE type, notify the AST context.
   if (IdentifierInfo *II = NewTD->getIdentifier())
@@ -8092,7 +8092,7 @@ NamedDecl *Sema::ActOnVariableDeclarator(
 
   // Diagnose shadowed variables iff this isn't a redeclaration.
   if (!IsPlaceholderVariable && ShadowedDecl && !D.isRedeclaration())
-    CheckShadow(NewVD, ShadowedDecl, Previous);
+    CheckShadow(S, NewVD, ShadowedDecl, Previous);
 
   ProcessPragmaWeak(S, NewVD);
 
@@ -8237,7 +8237,7 @@ NamedDecl *Sema::getShadowedDeclaration(const BindingDecl *D,
                                                             : nullptr;
 }
 
-void Sema::CheckShadow(NamedDecl *D, NamedDecl *ShadowedDecl,
+void Sema::CheckShadow(Scope *S, NamedDecl *D, NamedDecl *ShadowedDecl,
                        const LookupResult &R) {
   DeclContext *NewDC = D->getDeclContext();
 
@@ -8341,6 +8341,11 @@ void Sema::CheckShadow(NamedDecl *D, NamedDecl *ShadowedDecl,
     // shadowing context, but that's just a false negative.
   }
 
+  // Skip shadowing check if we're in a class scope, dealing with an enum
+  // constant in a different context.
+  if (S->isClassScope() && isa<EnumConstantDecl>(D) &&
+      !OldDC->Equals(NewDC->getRedeclContext()))
+    return;
 
   DeclarationName Name = R.getLookupName();
 
@@ -8389,7 +8394,7 @@ void Sema::CheckShadow(Scope *S, VarDecl *D) {
                  RedeclarationKind::ForVisibleRedeclaration);
   LookupName(R, S);
   if (NamedDecl *ShadowedDecl = getShadowedDeclaration(D, R))
-    CheckShadow(D, ShadowedDecl, R);
+    CheckShadow(S, D, ShadowedDecl, R);
 }
 
 /// Check if 'E', which is an expression that is about to be modified, refers
@@ -19736,7 +19741,7 @@ Decl *Sema::ActOnEnumConstant(Scope *S, Decl *theEnumDecl, Decl *lastEnumConst,
   if (PrevDecl) {
     if (!TheEnumDecl->isScoped() && isa<ValueDecl>(PrevDecl)) {
       // Check for other kinds of shadowing not already handled.
-      CheckShadow(New, PrevDecl, R);
+      CheckShadow(S, New, PrevDecl, R);
     }
 
     // When in C++, we may get a TagDecl with the same name; in this case the
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 8d76a35b2d2557..ad8df19485d9da 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -924,7 +924,7 @@ Sema::ActOnDecompositionDeclarator(Scope *S, Declarator &D,
         Diag(Old->getLocation(), diag::note_previous_definition);
       }
     } else if (ShadowedDecl && !D.isRedeclaration()) {
-      CheckShadow(BD, ShadowedDecl, Previous);
+      CheckShadow(S, BD, ShadowedDecl, Previous);
     }
     PushOnScopeChains(BD, S, true);
     Bindings.push_back(BD);
diff --git a/clang/test/SemaCXX/warn-shadow.cpp b/clang/test/SemaCXX/warn-shadow.cpp
index 2969bd39fed41e..98a235a73c7e52 100644
--- a/clang/test/SemaCXX/warn-shadow.cpp
+++ b/clang/test/SemaCXX/warn-shadow.cpp
@@ -307,3 +307,17 @@ void test4() {
 }
 
 }; // namespace structured_binding_tests
+
+namespace GH62588 {
+class Outer {
+public:
+  char *foo();          // expected-note {{previous declaration is here}} \
+                        // expected-note {{previous definition is here}}
+  enum Outer_E { foo }; // expected-error {{redefinition of 'foo'}} \
+                        // expected-warning {{declaration shadows a static data member of 'GH62588::Outer'}}
+  class Inner {
+  public:
+    enum Inner_E { foo }; // ok
+  };
+};
+} // namespace GH62588



More information about the cfe-commits mailing list