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 <[email protected]> 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 <[email protected]> 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 <[email protected]> --- .../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 <[email protected]> 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 <[email protected]> --- .../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 <[email protected]> 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 <[email protected]> --- .../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 <[email protected]> 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 <[email protected]> --- 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 <[email protected]> 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 <[email protected]> --- 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 <[email protected]> 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 <[email protected]> --- 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 <[email protected]> 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 <[email protected]> --- .../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 <[email protected]> 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 <[email protected]> --- .../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 <[email protected]> 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 <[email protected]> --- .../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 <[email protected]> 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 <[email protected]> --- 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 <[email protected]> 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 <[email protected]> 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 <[email protected]> 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 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
