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