[clang-tools-extra] [clang-tidy] Add `readability-redundant-tag` check (PR #210007)
purnima shrivastava via cfe-commits
cfe-commits at lists.llvm.org
Sat Jul 18 09:53:49 PDT 2026
https://github.com/purnima-nlp updated https://github.com/llvm/llvm-project/pull/210007
>From 55f3fea21c6ab55520f0fa31203ff06bb886b128 Mon Sep 17 00:00:00 2001
From: Purnima Shrivastava <purnima.shrivastava at email.com>
Date: Thu, 16 Jul 2026 13:27:32 +0530
Subject: [PATCH 01/14] [clang-tidy] Fix redundant-tag check for hidden tag
declarations
---
.../clang-tidy/readability/CMakeLists.txt | 2 +
.../readability/ReadabilityTidyModule.cpp | 4 +-
.../readability/RedundantTagCheck.cpp | 81 ++++++++++++++
.../readability/RedundantTagCheck.h | 35 ++++++
clang-tools-extra/docs/ReleaseNotes.rst | 6 ++
.../docs/clang-tidy/checks/list.rst | 1 +
.../checks/readability/redundant-tag.rst | 59 +++++++++++
.../checkers/readability/redundant-tag.cpp | 100 ++++++++++++++++++
8 files changed, 287 insertions(+), 1 deletion(-)
create mode 100644 clang-tools-extra/clang-tidy/readability/RedundantTagCheck.cpp
create mode 100644 clang-tools-extra/clang-tidy/readability/RedundantTagCheck.h
create mode 100644 clang-tools-extra/docs/clang-tidy/checks/readability/redundant-tag.rst
create mode 100644 clang-tools-extra/test/clang-tidy/checkers/readability/redundant-tag.cpp
diff --git a/clang-tools-extra/clang-tidy/readability/CMakeLists.txt b/clang-tools-extra/clang-tidy/readability/CMakeLists.txt
index 8a4b5753de890..fbee5f37917b6 100644
--- a/clang-tools-extra/clang-tidy/readability/CMakeLists.txt
+++ b/clang-tools-extra/clang-tidy/readability/CMakeLists.txt
@@ -53,6 +53,7 @@ add_clang_library(clangTidyReadabilityModule STATIC
RedundantSmartptrGetCheck.cpp
RedundantStringCStrCheck.cpp
RedundantStringInitCheck.cpp
+ RedundantTagCheck.cpp
RedundantTypenameCheck.cpp
ReferenceToConstructedTemporaryCheck.cpp
SimplifyBooleanExprCheck.cpp
@@ -69,6 +70,7 @@ add_clang_library(clangTidyReadabilityModule STATIC
UseConcisePreprocessorDirectivesCheck.cpp
UseStdMinMaxCheck.cpp
+
LINK_LIBS
clangTidy
clangTidyUtils
diff --git a/clang-tools-extra/clang-tidy/readability/ReadabilityTidyModule.cpp b/clang-tools-extra/clang-tidy/readability/ReadabilityTidyModule.cpp
index 69b31d6711bcd..098675b376add 100644
--- a/clang-tools-extra/clang-tidy/readability/ReadabilityTidyModule.cpp
+++ b/clang-tools-extra/clang-tidy/readability/ReadabilityTidyModule.cpp
@@ -55,6 +55,7 @@
#include "RedundantSmartptrGetCheck.h"
#include "RedundantStringCStrCheck.h"
#include "RedundantStringInitCheck.h"
+#include "RedundantTagCheck.h"
#include "RedundantTypenameCheck.h"
#include "ReferenceToConstructedTemporaryCheck.h"
#include "SimplifyBooleanExprCheck.h"
@@ -70,7 +71,6 @@
#include "UseAnyOfAllOfCheck.h"
#include "UseConcisePreprocessorDirectivesCheck.h"
#include "UseStdMinMaxCheck.h"
-
namespace clang::tidy {
namespace readability {
namespace {
@@ -202,6 +202,8 @@ class ReadabilityModule : public ClangTidyModule {
"readability-use-concise-preprocessor-directives");
CheckFactories.registerCheck<UseStdMinMaxCheck>(
"readability-use-std-min-max");
+ CheckFactories.registerCheck<RedundantTagCheck>(
+ "readability-redundant-tag");
}
};
diff --git a/clang-tools-extra/clang-tidy/readability/RedundantTagCheck.cpp b/clang-tools-extra/clang-tidy/readability/RedundantTagCheck.cpp
new file mode 100644
index 0000000000000..d98d7d430a080
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/readability/RedundantTagCheck.cpp
@@ -0,0 +1,81 @@
+//===--- RedundantTagCheck.cpp - clang-tidy -------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "RedundantTagCheck.h"
+
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/TypeLoc.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Lex/Lexer.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::readability {
+
+static bool canHideTag(const NamedDecl *D) {
+ D = D->getUnderlyingDecl();
+
+ return isa<VarDecl>(D) || isa<EnumConstantDecl>(D) || isa<FunctionDecl>(D) ||
+ isa<FunctionTemplateDecl>(D) || isa<FieldDecl>(D) ||
+ isa<UnresolvedUsingValueDecl>(D);
+}
+
+void RedundantTagCheck::registerMatchers(MatchFinder *Finder) {
+ Finder->addMatcher(
+ typeLoc(unless(hasAncestor(decl(isInstantiated())))).bind("typeLoc"),
+ this);
+}
+
+void RedundantTagCheck::check(const MatchFinder::MatchResult &Result) {
+ const auto *TL = Result.Nodes.getNodeAs<TypeLoc>("typeLoc");
+ if (!TL)
+ return;
+
+ if (TL->getType()->isInstantiationDependentType())
+ return;
+
+ const auto TagTL = TL->getAs<TagTypeLoc>();
+ if (!TagTL)
+ return;
+
+ const TagDecl *TD = TagTL.getDecl();
+ if (!TD)
+ return;
+
+ auto Lookup = TD->getDeclContext()->lookup(TD->getDeclName());
+
+ for (const NamedDecl *ND : Lookup) {
+ if (declaresSameEntity(ND, TD))
+ continue;
+
+ if (canHideTag(ND))
+ return;
+ }
+
+ const SourceLocation KeywordLoc = TagTL.getElaboratedKeywordLoc();
+ if (KeywordLoc.isInvalid())
+ return;
+
+ Token Tok;
+ if (Lexer::getRawToken(KeywordLoc, Tok, *Result.SourceManager, getLangOpts()))
+ return;
+
+ const llvm::StringRef Keyword = Tok.getRawIdentifier();
+
+ if (Keyword != "struct" && Keyword != "class" && Keyword != "union" &&
+ Keyword != "enum")
+ return;
+
+ diag(KeywordLoc, "redundant '%0' keyword in C++ declaration")
+ << Keyword << FixItHint::CreateRemoval(KeywordLoc);
+}
+
+} // namespace clang::tidy::readability
diff --git a/clang-tools-extra/clang-tidy/readability/RedundantTagCheck.h b/clang-tools-extra/clang-tidy/readability/RedundantTagCheck.h
new file mode 100644
index 0000000000000..70bcdd43b7eba
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/readability/RedundantTagCheck.h
@@ -0,0 +1,35 @@
+//===--- RedundantTagCheck.h - clang-tidy -------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_REDUNDANTTAGCHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_REDUNDANTTAGCHECK_H
+
+#include "../ClangTidyCheck.h"
+
+namespace clang::tidy::readability {
+
+class RedundantTagCheck : public ClangTidyCheck {
+public:
+ RedundantTagCheck(StringRef Name, ClangTidyContext *Context)
+ : ClangTidyCheck(Name, Context) {}
+
+ bool isLanguageVersionSupported(const LangOptions &LangOpts) const override {
+ return LangOpts.CPlusPlus;
+ }
+
+ void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+ void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+
+ std::optional<TraversalKind> getCheckTraversalKind() const override {
+ return TK_IgnoreUnlessSpelledInSource;
+ }
+};
+
+} // namespace clang::tidy::readability
+
+#endif
diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst
index 69c3bcf67b8db..7b971d868383b 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -97,6 +97,12 @@ Improvements to clang-tidy
New checks
^^^^^^^^^^
+- Added the :doc:`readability-redundant-tag
+ <clang-tidy/checks/readability/redundant-tag>` check, which diagnoses
+ redundant ``class``, ``struct``, ``union``, and ``enum`` keywords in C++
+ declarations and provides fix-it hints to remove them when doing so does not
+ change name lookup semantics.
+
New check aliases
^^^^^^^^^^^^^^^^^
diff --git a/clang-tools-extra/docs/clang-tidy/checks/list.rst b/clang-tools-extra/docs/clang-tidy/checks/list.rst
index 2a44dc78fbc89..8026ce4d6aa50 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/list.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/list.rst
@@ -425,6 +425,7 @@ Clang-Tidy Checks
:doc:`readability-redundant-smartptr-get <readability/redundant-smartptr-get>`, "Yes"
:doc:`readability-redundant-string-cstr <readability/redundant-string-cstr>`, "Yes"
:doc:`readability-redundant-string-init <readability/redundant-string-init>`, "Yes"
+ :doc:`readability-redundant-tag <readability/redundant-tag>`, "Yes"
:doc:`readability-redundant-typename <readability/redundant-typename>`, "Yes"
:doc:`readability-reference-to-constructed-temporary <readability/reference-to-constructed-temporary>`,
:doc:`readability-simplify-boolean-expr <readability/simplify-boolean-expr>`, "Yes"
diff --git a/clang-tools-extra/docs/clang-tidy/checks/readability/redundant-tag.rst b/clang-tools-extra/docs/clang-tidy/checks/readability/redundant-tag.rst
new file mode 100644
index 0000000000000..19f868a3a57ce
--- /dev/null
+++ b/clang-tools-extra/docs/clang-tidy/checks/readability/redundant-tag.rst
@@ -0,0 +1,59 @@
+=========================
+readability-redundant-tag
+=========================
+
+Finds redundant uses of the ``class``, ``struct``, ``union``, and ``enum``
+keywords in C++ declarations and provides fix-it hints to remove them.
+
+In C++, elaborated type specifiers are unnecessary when the type name is
+already unambiguous.
+
+For example:
+
+.. code-block:: c++
+
+ struct S {};
+
+ void f() {
+ struct S s;
+ }
+
+becomes:
+
+.. code-block:: c++
+
+ struct S {};
+
+ void f() {
+ S s;
+ }
+
+The check does not diagnose cases where removing the keyword would change name
+lookup semantics. For example:
+
+.. code-block:: c++
+
+ struct Hidden {} Hidden;
+
+ void f() {
+ struct Hidden h;
+ }
+
+Removing ``struct`` would cause ``Hidden`` to refer to the variable rather
+than the type.
+
+Similarly:
+
+.. code-block:: c++
+
+ struct Foo {};
+
+ void Foo();
+
+ void f() {
+ struct Foo x;
+ }
+
+Removing ``struct`` would cause ``Foo`` to refer to the function instead of
+the type.
+
diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-tag.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-tag.cpp
new file mode 100644
index 0000000000000..7b1facdffe39a
--- /dev/null
+++ b/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-tag.cpp
@@ -0,0 +1,100 @@
+// RUN: %check_clang_tidy %s readability-redundant-tag %t -- -- -std=c++20
+
+struct Struct {};
+class Class {};
+union Union {};
+enum Enum {};
+
+void basic() {
+ struct Struct s;
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: redundant 'struct' keyword in C++ declaration
+ // CHECK-FIXES: Struct s;
+
+ class Class c;
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: redundant 'class' keyword in C++ declaration
+ // CHECK-FIXES: Class c;
+
+ union Union u;
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: redundant 'union' keyword in C++ declaration
+ // CHECK-FIXES: Union u;
+
+ enum Enum e;
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: redundant 'enum' keyword in C++ declaration
+ // CHECK-FIXES: Enum e;
+}
+
+// Hidden by variable (GitHub issue)
+struct Hidden {} Hidden;
+
+void hiddenByVariable() {
+ struct Hidden h;
+}
+
+// Forward declaration
+struct Forward;
+
+void forwardDecl() {
+ struct Forward *p;
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: redundant 'struct' keyword in C++ declaration
+ // CHECK-FIXES: Forward *p;
+}
+
+// Namespace-qualified type
+namespace N {
+struct NS {};
+}
+
+void namespaceQualified() {
+ struct N::NS x;
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: redundant 'struct' keyword in C++ declaration
+ // CHECK-FIXES: N::NS x;
+}
+
+// Nested type
+struct Outer {
+ struct Inner {};
+};
+
+void nestedType() {
+ struct Outer::Inner x;
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: redundant 'struct' keyword in C++ declaration
+ // CHECK-FIXES: Outer::Inner x;
+}
+
+// Hidden by function
+struct FuncTag {};
+
+void FuncTag();
+
+void hiddenByFunction() {
+ struct FuncTag x;
+}
+
+// Hidden by enum constant
+struct EnumTag {};
+
+enum { EnumTag };
+
+void hiddenByEnumConstant() {
+ struct EnumTag x;
+}
+
+// Hidden by another variable
+struct A {};
+
+A A;
+
+void anotherHiddenVariable() {
+ struct A x;
+}
+
+// Template argument
+template <typename T>
+void tf();
+
+void templateArgument() {
+ tf<struct Struct>();
+ // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: redundant 'struct' keyword in C++ declaration
+ // CHECK-FIXES: tf<Struct>();
+}
+
>From 92b7db16a0a68cc928f5dd28d76701d9dcd11a52 Mon Sep 17 00:00:00 2001
From: purnima shrivastava <purnimashrivastava05 at gmail.com>
Date: Thu, 16 Jul 2026 23:09:40 +0530
Subject: [PATCH 02/14] Update
clang-tools-extra/docs/clang-tidy/checks/readability/redundant-tag.rst
Co-authored-by: EugeneZelenko <eugene.zelenko at gmail.com>
---
.../docs/clang-tidy/checks/readability/redundant-tag.rst | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/clang-tools-extra/docs/clang-tidy/checks/readability/redundant-tag.rst b/clang-tools-extra/docs/clang-tidy/checks/readability/redundant-tag.rst
index 19f868a3a57ce..2f2352cb37457 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/readability/redundant-tag.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/readability/redundant-tag.rst
@@ -1,4 +1,5 @@
-=========================
+.. title:: clang-tidy - readability-redundant-tag
+
readability-redundant-tag
=========================
>From 80cfcb73b2451b0f9697c05b7e91931f4bd2bc03 Mon Sep 17 00:00:00 2001
From: purnima shrivastava <purnimashrivastava05 at gmail.com>
Date: Thu, 16 Jul 2026 23:10:15 +0530
Subject: [PATCH 03/14] Update
clang-tools-extra/docs/clang-tidy/checks/readability/redundant-tag.rst
Co-authored-by: EugeneZelenko <eugene.zelenko at gmail.com>
---
.../docs/clang-tidy/checks/readability/redundant-tag.rst | 1 -
1 file changed, 1 deletion(-)
diff --git a/clang-tools-extra/docs/clang-tidy/checks/readability/redundant-tag.rst b/clang-tools-extra/docs/clang-tidy/checks/readability/redundant-tag.rst
index 2f2352cb37457..5703340e7f81b 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/readability/redundant-tag.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/readability/redundant-tag.rst
@@ -57,4 +57,3 @@ Similarly:
Removing ``struct`` would cause ``Foo`` to refer to the function instead of
the type.
-
>From c992a8e990b25b4d6fd76aefd5ad8f0fc48475f3 Mon Sep 17 00:00:00 2001
From: purnima shrivastava <purnimashrivastava05 at gmail.com>
Date: Thu, 16 Jul 2026 23:10:49 +0530
Subject: [PATCH 04/14] Update
clang-tools-extra/test/clang-tidy/checkers/readability/redundant-tag.cpp
Co-authored-by: EugeneZelenko <eugene.zelenko at gmail.com>
---
.../test/clang-tidy/checkers/readability/redundant-tag.cpp | 1 -
1 file changed, 1 deletion(-)
diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-tag.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-tag.cpp
index 7b1facdffe39a..6da677e90982b 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-tag.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-tag.cpp
@@ -97,4 +97,3 @@ void templateArgument() {
// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: redundant 'struct' keyword in C++ declaration
// CHECK-FIXES: tf<Struct>();
}
-
>From 239d50a55f302910c69b9e6ecf467e0695e42574 Mon Sep 17 00:00:00 2001
From: purnima shrivastava <purnimashrivastava05 at gmail.com>
Date: Thu, 16 Jul 2026 23:16:18 +0530
Subject: [PATCH 05/14] Update
clang-tools-extra/clang-tidy/readability/CMakeLists.txt
Co-authored-by: EugeneZelenko <eugene.zelenko at gmail.com>
---
clang-tools-extra/clang-tidy/readability/CMakeLists.txt | 1 -
1 file changed, 1 deletion(-)
diff --git a/clang-tools-extra/clang-tidy/readability/CMakeLists.txt b/clang-tools-extra/clang-tidy/readability/CMakeLists.txt
index fbee5f37917b6..b74fbf0390b78 100644
--- a/clang-tools-extra/clang-tidy/readability/CMakeLists.txt
+++ b/clang-tools-extra/clang-tidy/readability/CMakeLists.txt
@@ -70,7 +70,6 @@ add_clang_library(clangTidyReadabilityModule STATIC
UseConcisePreprocessorDirectivesCheck.cpp
UseStdMinMaxCheck.cpp
-
LINK_LIBS
clangTidy
clangTidyUtils
>From 6c517f1c8a8cc086856a6b1c95746a5747dbfe62 Mon Sep 17 00:00:00 2001
From: purnima shrivastava <purnimashrivastava05 at gmail.com>
Date: Thu, 16 Jul 2026 23:16:43 +0530
Subject: [PATCH 06/14] Update
clang-tools-extra/clang-tidy/readability/RedundantTagCheck.cpp
Co-authored-by: EugeneZelenko <eugene.zelenko at gmail.com>
---
clang-tools-extra/clang-tidy/readability/RedundantTagCheck.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/clang-tools-extra/clang-tidy/readability/RedundantTagCheck.cpp b/clang-tools-extra/clang-tidy/readability/RedundantTagCheck.cpp
index d98d7d430a080..802a607351807 100644
--- a/clang-tools-extra/clang-tidy/readability/RedundantTagCheck.cpp
+++ b/clang-tools-extra/clang-tidy/readability/RedundantTagCheck.cpp
@@ -1,4 +1,4 @@
-//===--- RedundantTagCheck.cpp - clang-tidy -------------------------------===//
+//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
>From 54b39d002af1f5225ed980500bf1f834f77abdd1 Mon Sep 17 00:00:00 2001
From: purnima shrivastava <purnimashrivastava05 at gmail.com>
Date: Thu, 16 Jul 2026 23:17:13 +0530
Subject: [PATCH 07/14] Update
clang-tools-extra/clang-tidy/readability/RedundantTagCheck.h
Co-authored-by: EugeneZelenko <eugene.zelenko at gmail.com>
---
clang-tools-extra/clang-tidy/readability/RedundantTagCheck.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/clang-tools-extra/clang-tidy/readability/RedundantTagCheck.h b/clang-tools-extra/clang-tidy/readability/RedundantTagCheck.h
index 70bcdd43b7eba..fd6ed5b3ac214 100644
--- a/clang-tools-extra/clang-tidy/readability/RedundantTagCheck.h
+++ b/clang-tools-extra/clang-tidy/readability/RedundantTagCheck.h
@@ -1,4 +1,4 @@
-//===--- RedundantTagCheck.h - clang-tidy -------------------------------===//
+//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
>From 6f4b56f4279e12eb9f60b8e8518b7dfea4917f97 Mon Sep 17 00:00:00 2001
From: purnima shrivastava <purnimashrivastava05 at gmail.com>
Date: Fri, 17 Jul 2026 08:52:32 +0530
Subject: [PATCH 08/14] Update
clang-tools-extra/test/clang-tidy/checkers/readability/redundant-tag.cpp
Co-authored-by: Zeyi Xu <zeyi2 at nekoarch.cc>
---
.../test/clang-tidy/checkers/readability/redundant-tag.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-tag.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-tag.cpp
index 6da677e90982b..7a2ca8713f5f5 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-tag.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-tag.cpp
@@ -1,4 +1,4 @@
-// RUN: %check_clang_tidy %s readability-redundant-tag %t -- -- -std=c++20
+// RUN: %check_clang_tidy -std=c++20-or-later %s readability-redundant-tag %t
struct Struct {};
class Class {};
>From b346307935e840d8063bc644e14d5f87d5d4d23c Mon Sep 17 00:00:00 2001
From: purnima shrivastava <purnimashrivastava05 at gmail.com>
Date: Fri, 17 Jul 2026 08:53:04 +0530
Subject: [PATCH 09/14] Update
clang-tools-extra/clang-tidy/readability/ReadabilityTidyModule.cpp
Co-authored-by: EugeneZelenko <eugene.zelenko at gmail.com>
---
.../clang-tidy/readability/ReadabilityTidyModule.cpp | 2 ++
1 file changed, 2 insertions(+)
diff --git a/clang-tools-extra/clang-tidy/readability/ReadabilityTidyModule.cpp b/clang-tools-extra/clang-tidy/readability/ReadabilityTidyModule.cpp
index 098675b376add..673fa389bbfd2 100644
--- a/clang-tools-extra/clang-tidy/readability/ReadabilityTidyModule.cpp
+++ b/clang-tools-extra/clang-tidy/readability/ReadabilityTidyModule.cpp
@@ -158,6 +158,8 @@ class ReadabilityModule : public ClangTidyModule {
"readability-redundant-preprocessor");
CheckFactories.registerCheck<RedundantQualifiedAliasCheck>(
"readability-redundant-qualified-alias");
+ CheckFactories.registerCheck<RedundantTagCheck>(
+ "readability-redundant-tag");
CheckFactories.registerCheck<RedundantTypenameCheck>(
"readability-redundant-typename");
CheckFactories.registerCheck<ReferenceToConstructedTemporaryCheck>(
>From 17a3f17a8138c305f7f50a9fa365598bfebf0a0e Mon Sep 17 00:00:00 2001
From: purnima shrivastava <purnimashrivastava05 at gmail.com>
Date: Fri, 17 Jul 2026 08:53:28 +0530
Subject: [PATCH 10/14] Update
clang-tools-extra/clang-tidy/readability/ReadabilityTidyModule.cpp
Co-authored-by: EugeneZelenko <eugene.zelenko at gmail.com>
---
.../readability/ReadabilityTidyModule.cpp | 38 +++++++++----------
clang-tools-extra/docs/ReleaseNotes.rst | 11 +++---
2 files changed, 24 insertions(+), 25 deletions(-)
diff --git a/clang-tools-extra/clang-tidy/readability/ReadabilityTidyModule.cpp b/clang-tools-extra/clang-tidy/readability/ReadabilityTidyModule.cpp
index 673fa389bbfd2..3b9801666e1a7 100644
--- a/clang-tools-extra/clang-tidy/readability/ReadabilityTidyModule.cpp
+++ b/clang-tools-extra/clang-tidy/readability/ReadabilityTidyModule.cpp
@@ -118,16 +118,14 @@ class ReadabilityModule : public ClangTidyModule {
"readability-identifier-naming");
CheckFactories.registerCheck<ImplicitBoolConversionCheck>(
"readability-implicit-bool-conversion");
- CheckFactories.registerCheck<InconsistentIfElseBracesCheck>(
- "readability-inconsistent-ifelse-braces");
- CheckFactories.registerCheck<MathMissingParenthesesCheck>(
- "readability-math-missing-parentheses");
- CheckFactories.registerCheck<RedundantInlineSpecifierCheck>(
- "readability-redundant-inline-specifier");
CheckFactories.registerCheck<InconsistentDeclarationParameterNameCheck>(
"readability-inconsistent-declaration-parameter-name");
+ CheckFactories.registerCheck<InconsistentIfElseBracesCheck>(
+ "readability-inconsistent-ifelse-braces");
CheckFactories.registerCheck<IsolateDeclarationCheck>(
"readability-isolate-declaration");
+ CheckFactories.registerCheck<MathMissingParenthesesCheck>(
+ "readability-math-missing-parentheses");
CheckFactories.registerCheck<MagicNumbersCheck>(
"readability-magic-numbers");
CheckFactories.registerCheck<MakeMemberFunctionConstCheck>(
@@ -136,6 +134,10 @@ class ReadabilityModule : public ClangTidyModule {
"readability-misleading-indentation");
CheckFactories.registerCheck<MisplacedArrayIndexCheck>(
"readability-misplaced-array-index");
+ CheckFactories.registerCheck<readability::NamedParameterCheck>(
+ "readability-named-parameter");
+ CheckFactories.registerCheck<NonConstParameterCheck>(
+ "readability-non-const-parameter");
CheckFactories.registerCheck<OperatorsRepresentationCheck>(
"readability-operators-representation");
CheckFactories.registerCheck<QualifiedAutoCheck>(
@@ -146,6 +148,8 @@ class ReadabilityModule : public ClangTidyModule {
"readability-redundant-casting");
CheckFactories.registerCheck<RedundantFunctionPtrDereferenceCheck>(
"readability-redundant-function-ptr-dereference");
+ CheckFactories.registerCheck<RedundantInlineSpecifierCheck>(
+ "readability-redundant-inline-specifier");
CheckFactories.registerCheck<RedundantLambdaParameterListCheck>(
"readability-redundant-lambda-parameter-list");
CheckFactories.registerCheck<RedundantMemberInitCheck>(
@@ -164,18 +168,6 @@ class ReadabilityModule : public ClangTidyModule {
"readability-redundant-typename");
CheckFactories.registerCheck<ReferenceToConstructedTemporaryCheck>(
"readability-reference-to-constructed-temporary");
- CheckFactories.registerCheck<SimplifySubscriptExprCheck>(
- "readability-simplify-subscript-expr");
- CheckFactories.registerCheck<StaticAccessedThroughInstanceCheck>(
- "readability-static-accessed-through-instance");
- CheckFactories.registerCheck<StaticDefinitionInAnonymousNamespaceCheck>(
- "readability-static-definition-in-anonymous-namespace");
- CheckFactories.registerCheck<StringCompareCheck>(
- "readability-string-compare");
- CheckFactories.registerCheck<readability::NamedParameterCheck>(
- "readability-named-parameter");
- CheckFactories.registerCheck<NonConstParameterCheck>(
- "readability-non-const-parameter");
CheckFactories.registerCheck<RedundantControlFlowCheck>(
"readability-redundant-control-flow");
CheckFactories.registerCheck<RedundantDeclarationCheck>(
@@ -188,6 +180,14 @@ class ReadabilityModule : public ClangTidyModule {
"readability-redundant-string-init");
CheckFactories.registerCheck<SimplifyBooleanExprCheck>(
"readability-simplify-boolean-expr");
+ CheckFactories.registerCheck<SimplifySubscriptExprCheck>(
+ "readability-simplify-subscript-expr");
+ CheckFactories.registerCheck<StaticAccessedThroughInstanceCheck>(
+ "readability-static-accessed-through-instance");
+ CheckFactories.registerCheck<StaticDefinitionInAnonymousNamespaceCheck>(
+ "readability-static-definition-in-anonymous-namespace");
+ CheckFactories.registerCheck<StringCompareCheck>(
+ "readability-string-compare");
CheckFactories.registerCheck<SuspiciousCallArgumentCheck>(
"readability-suspicious-call-argument");
CheckFactories.registerCheck<TrailingCommaCheck>(
@@ -204,8 +204,6 @@ class ReadabilityModule : public ClangTidyModule {
"readability-use-concise-preprocessor-directives");
CheckFactories.registerCheck<UseStdMinMaxCheck>(
"readability-use-std-min-max");
- CheckFactories.registerCheck<RedundantTagCheck>(
- "readability-redundant-tag");
}
};
diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst
index 7b971d868383b..f2dbac0c2c12a 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -97,11 +97,12 @@ Improvements to clang-tidy
New checks
^^^^^^^^^^
-- Added the :doc:`readability-redundant-tag
- <clang-tidy/checks/readability/redundant-tag>` check, which diagnoses
- redundant ``class``, ``struct``, ``union``, and ``enum`` keywords in C++
- declarations and provides fix-it hints to remove them when doing so does not
- change name lookup semantics.
+- New :doc:`readability-redundant-tag
+ <clang-tidy/checks/readability/redundant-tag>` check.
+
+ Finds redundant uses of ``class``, ``struct``, ``union``, and ``enum``
+ keywords in C++ declarations and provides fix-it hints to remove them when
+ doing so does not change name lookup semantics.
New check aliases
^^^^^^^^^^^^^^^^^
>From 144f73cd2716055eebcefee032b6a2da4092e22a Mon Sep 17 00:00:00 2001
From: purnima shrivastava <purnimashrivastava05 at gmail.com>
Date: Fri, 17 Jul 2026 20:34:36 +0530
Subject: [PATCH 11/14] Update
clang-tools-extra/clang-tidy/readability/RedundantTagCheck.h
Co-authored-by: EugeneZelenko <eugene.zelenko at gmail.com>
---
clang-tools-extra/clang-tidy/readability/RedundantTagCheck.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/clang-tools-extra/clang-tidy/readability/RedundantTagCheck.h b/clang-tools-extra/clang-tidy/readability/RedundantTagCheck.h
index fd6ed5b3ac214..7fc10d694dfc9 100644
--- a/clang-tools-extra/clang-tidy/readability/RedundantTagCheck.h
+++ b/clang-tools-extra/clang-tidy/readability/RedundantTagCheck.h
@@ -32,4 +32,4 @@ class RedundantTagCheck : public ClangTidyCheck {
} // namespace clang::tidy::readability
-#endif
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_REDUNDANTTAGCHECK_H
>From 88d5ce84d5ba01a27058338396da80233103c01e Mon Sep 17 00:00:00 2001
From: Purnima Shrivastava <purnima.shrivastava at email.com>
Date: Fri, 17 Jul 2026 21:02:23 +0530
Subject: [PATCH 12/14] [clang-tidy] Address review comments
---
clang-tools-extra/clang-tidy/readability/RedundantTagCheck.h | 4 ++++
clang-tools-extra/docs/ReleaseNotes.rst | 5 ++---
2 files changed, 6 insertions(+), 3 deletions(-)
diff --git a/clang-tools-extra/clang-tidy/readability/RedundantTagCheck.h b/clang-tools-extra/clang-tidy/readability/RedundantTagCheck.h
index 7fc10d694dfc9..4ef6360773e60 100644
--- a/clang-tools-extra/clang-tidy/readability/RedundantTagCheck.h
+++ b/clang-tools-extra/clang-tidy/readability/RedundantTagCheck.h
@@ -13,6 +13,10 @@
namespace clang::tidy::readability {
+/// Finds redundant class, struct, union, and enum tags in C++ declarations.
+///
+/// For the user-facing documentation see:
+/// https://clang.llvm.org/extra/clang-tidy/checks/readability/redundant-tag.html
class RedundantTagCheck : public ClangTidyCheck {
public:
RedundantTagCheck(StringRef Name, ClangTidyContext *Context)
diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst
index f2dbac0c2c12a..b504e9e43bb0a 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -100,9 +100,8 @@ New checks
- New :doc:`readability-redundant-tag
<clang-tidy/checks/readability/redundant-tag>` check.
- Finds redundant uses of ``class``, ``struct``, ``union``, and ``enum``
- keywords in C++ declarations and provides fix-it hints to remove them when
- doing so does not change name lookup semantics.
+ Finds redundant uses of the ``class``, ``struct``, ``union``, and ``enum``
+ keywords in C++ declarations and provides fix-it hints to remove them.
New check aliases
^^^^^^^^^^^^^^^^^
>From bc49f2e337e7a973feb3cb457b56f3fdea9c7935 Mon Sep 17 00:00:00 2001
From: Purnima Shrivastava <purnima.shrivastava at email.com>
Date: Sat, 18 Jul 2026 22:11:19 +0530
Subject: [PATCH 13/14] [clang-tidy] Fix lookup for readability-redundant-tag
---
.../readability/RedundantTagCheck.cpp | 41 +++-
.../checkers/readability/redundant-tag.cpp | 205 ++++++++++++++++++
2 files changed, 241 insertions(+), 5 deletions(-)
diff --git a/clang-tools-extra/clang-tidy/readability/RedundantTagCheck.cpp b/clang-tools-extra/clang-tidy/readability/RedundantTagCheck.cpp
index 802a607351807..84951a25adff1 100644
--- a/clang-tools-extra/clang-tidy/readability/RedundantTagCheck.cpp
+++ b/clang-tools-extra/clang-tidy/readability/RedundantTagCheck.cpp
@@ -50,14 +50,45 @@ void RedundantTagCheck::check(const MatchFinder::MatchResult &Result) {
if (!TD)
return;
- auto Lookup = TD->getDeclContext()->lookup(TD->getDeclName());
+ // Find the declaration enclosing this use of the tag.
+ const Decl *EnclosingDecl = nullptr;
- for (const NamedDecl *ND : Lookup) {
- if (declaresSameEntity(ND, TD))
+ DynTypedNodeList Parents = Result.Context->getParents(*TL);
+
+ while (!Parents.empty()) {
+ if (const auto *D = Parents[0].get<Decl>()) {
+ EnclosingDecl = D;
+ break;
+ }
+ Parents = Result.Context->getParents(Parents[0]);
+ }
+
+ if (!EnclosingDecl)
+ return;
+
+ DeclarationName Name = TD->getDeclName();
+
+ for (const DeclContext *DC = EnclosingDecl->getDeclContext(); DC;
+ DC = DC->getLookupParent()) {
+ auto Lookup = DC->lookup(Name);
+
+ if (Lookup.empty())
continue;
- if (canHideTag(ND))
- return;
+ bool FoundSameEntity = false;
+
+ for (const NamedDecl *ND : Lookup) {
+ if (declaresSameEntity(ND, TD)) {
+ FoundSameEntity = true;
+ continue;
+ }
+
+ if (canHideTag(ND))
+ return;
+ }
+
+ if (FoundSameEntity)
+ break;
}
const SourceLocation KeywordLoc = TagTL.getElaboratedKeywordLoc();
diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-tag.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-tag.cpp
index 7a2ca8713f5f5..6378286748fad 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-tag.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-tag.cpp
@@ -97,3 +97,208 @@ void templateArgument() {
// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: redundant 'struct' keyword in C++ declaration
// CHECK-FIXES: tf<Struct>();
}
+
+//===----------------------------------------------------------------------===//
+// Regression test: using declaration lookup
+//===----------------------------------------------------------------------===//
+
+namespace UsingDeclarationRegression {
+
+namespace NS {
+struct S {};
+} // namespace NS
+
+using NS::S;
+
+using T = struct S;
+// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: redundant 'struct' keyword in C++ declaration
+// CHECK-FIXES: using T = S;
+
+} // namespace UsingDeclarationRegression
+
+//===----------------------------------------------------------------------===//
+// Regression test: hidden in nested namespace scope
+//===----------------------------------------------------------------------===//
+
+namespace HiddenNamespaceRegression {
+
+struct S {};
+
+namespace N1 {
+namespace N2 {
+
+using A = struct S;
+// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: redundant 'struct' keyword in C++ declaration
+// CHECK-FIXES: using A = S;
+
+namespace N3 {
+
+int S;
+
+using B = struct S;
+// CHECK-FIXES: using B = struct S;
+
+void foo() {
+ using C = struct S;
+ // CHECK-FIXES: using C = struct S;
+
+ {
+ using D = struct S;
+ // CHECK-FIXES: using D = struct S;
+ }
+}
+
+} // namespace N3
+
+void bar() {
+ using E = struct S;
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: redundant 'struct' keyword in C++ declaration
+ // CHECK-FIXES: using E = S;
+}
+
+} // namespace N2
+} // namespace N1
+
+} // namespace HiddenNamespaceRegression
+
+//===----------------------------------------------------------------------===//
+// Regression test: deep namespace lookup
+//===----------------------------------------------------------------------===//
+
+namespace DeepLookupRegression {
+
+struct Global {};
+
+namespace N1 {
+
+using ::DeepLookupRegression::Global;
+
+using T1 = struct Global;
+// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: redundant 'struct' keyword in C++ declaration
+// CHECK-FIXES: using T1 = Global;
+
+namespace N2 {
+
+using T2 = struct Global;
+// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: redundant 'struct' keyword in C++ declaration
+// CHECK-FIXES: using T2 = Global;
+
+namespace N3 {
+
+int Global;
+
+using T3 = struct Global;
+// CHECK-FIXES: using T3 = struct Global;
+
+namespace N4 {
+
+using T4 = struct Global;
+// CHECK-FIXES: using T4 = struct Global;
+
+namespace N5 {
+
+using T5 = struct Global;
+// CHECK-FIXES: using T5 = struct Global;
+
+} // namespace N5
+} // namespace N4
+} // namespace N3
+
+using T6 = struct Global;
+// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: redundant 'struct' keyword in C++ declaration
+// CHECK-FIXES: using T6 = Global;
+
+} // namespace N2
+
+using T7 = struct Global;
+// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: redundant 'struct' keyword in C++ declaration
+// CHECK-FIXES: using T7 = Global;
+
+} // namespace N1
+
+} // namespace DeepLookupRegression
+
+//===----------------------------------------------------------------------===//
+// Regression test: deep nested block scopes
+//===----------------------------------------------------------------------===//
+
+namespace DeepBlockRegression {
+
+struct S {};
+
+namespace N1 {
+
+using ::DeepBlockRegression::S;
+
+namespace N2 {
+
+using A = struct S;
+// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: redundant 'struct' keyword in C++ declaration
+// CHECK-FIXES: using A = S;
+
+namespace N3 {
+
+int S;
+
+using B = struct S;
+// CHECK-FIXES: using B = struct S;
+
+void foo() {
+ using C = struct S;
+ // CHECK-FIXES: using C = struct S;
+
+ {
+ using D = struct S;
+ // CHECK-FIXES: using D = struct S;
+
+ {
+ using E = struct S;
+ // CHECK-FIXES: using E = struct S;
+
+ {
+ using F = struct S;
+ // CHECK-FIXES: using F = struct S;
+
+ {
+ using G = struct S;
+ // CHECK-FIXES: using G = struct S;
+ }
+ }
+ }
+ }
+}
+
+} // namespace N3
+
+void bar() {
+ using H = struct S;
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: redundant 'struct' keyword in C++ declaration
+ // CHECK-FIXES: using H = S;
+}
+
+namespace N4 {
+
+using I = struct S;
+// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: redundant 'struct' keyword in C++ declaration
+// CHECK-FIXES: using I = S;
+
+namespace N5 {
+
+void baz() {
+ using J = struct S;
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: redundant 'struct' keyword in C++ declaration
+ // CHECK-FIXES: using J = S;
+
+ {
+ using K = struct S;
+ // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: redundant 'struct' keyword in C++ declaration
+ // CHECK-FIXES: using K = S;
+ }
+}
+
+} // namespace N5
+} // namespace N4
+} // namespace N2
+} // namespace N1
+
+} // namespace DeepBlockRegression
\ No newline at end of file
>From d7f154a6b1c9c0ba7480140cd02f6a292f95eaa8 Mon Sep 17 00:00:00 2001
From: Purnima Shrivastava <purnima.shrivastava at email.com>
Date: Sat, 18 Jul 2026 22:19:43 +0530
Subject: [PATCH 14/14] [clang-tidy] Add regression tests
---
.../test/clang-tidy/checkers/readability/redundant-tag.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-tag.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-tag.cpp
index 6378286748fad..fac9d694e68be 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-tag.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-tag.cpp
@@ -301,4 +301,4 @@ void baz() {
} // namespace N2
} // namespace N1
-} // namespace DeepBlockRegression
\ No newline at end of file
+} // namespace DeepBlockRegression
More information about the cfe-commits
mailing list