[clang-tools-extra] [clang-tidy] new check readability-mark-static (PR #90830)

Congcong Cai via cfe-commits cfe-commits at lists.llvm.org
Fri May 3 00:33:31 PDT 2024


https://github.com/HerrCai0907 updated https://github.com/llvm/llvm-project/pull/90830

>From ec7ddff8aedaa9d42796b5f952ff7ca77465dfd1 Mon Sep 17 00:00:00 2001
From: Congcong Cai <congcongcai0907 at 163.com>
Date: Thu, 2 May 2024 15:44:45 +0800
Subject: [PATCH 1/4] [clang-tidy] new check readability-mark-static

Add new check readability-mark-static to dectect variable and function can be marked as static.
---
 .../clang-tidy/readability/CMakeLists.txt     |  1 +
 .../readability/MarkStaticCheck.cpp           | 65 +++++++++++++++++++
 .../clang-tidy/readability/MarkStaticCheck.h  | 33 ++++++++++
 .../readability/ReadabilityTidyModule.cpp     |  2 +
 clang-tools-extra/docs/ReleaseNotes.rst       |  5 ++
 .../docs/clang-tidy/checks/list.rst           |  1 +
 .../checks/readability/mark-static.rst        | 26 ++++++++
 .../readability/Inputs/mark-static-var/func.h |  3 +
 .../readability/Inputs/mark-static-var/var.h  |  3 +
 .../checkers/readability/mark-static-func.cpp | 24 +++++++
 .../checkers/readability/mark-static-var.cpp  | 34 ++++++++++
 11 files changed, 197 insertions(+)
 create mode 100644 clang-tools-extra/clang-tidy/readability/MarkStaticCheck.cpp
 create mode 100644 clang-tools-extra/clang-tidy/readability/MarkStaticCheck.h
 create mode 100644 clang-tools-extra/docs/clang-tidy/checks/readability/mark-static.rst
 create mode 100644 clang-tools-extra/test/clang-tidy/checkers/readability/Inputs/mark-static-var/func.h
 create mode 100644 clang-tools-extra/test/clang-tidy/checkers/readability/Inputs/mark-static-var/var.h
 create mode 100644 clang-tools-extra/test/clang-tidy/checkers/readability/mark-static-func.cpp
 create mode 100644 clang-tools-extra/test/clang-tidy/checkers/readability/mark-static-var.cpp

diff --git a/clang-tools-extra/clang-tidy/readability/CMakeLists.txt b/clang-tools-extra/clang-tidy/readability/CMakeLists.txt
index 41065fc8e87859..3e0cbc4d943274 100644
--- a/clang-tools-extra/clang-tidy/readability/CMakeLists.txt
+++ b/clang-tools-extra/clang-tidy/readability/CMakeLists.txt
@@ -23,6 +23,7 @@ add_clang_library(clangTidyReadabilityModule
   IdentifierLengthCheck.cpp
   IdentifierNamingCheck.cpp
   ImplicitBoolConversionCheck.cpp
+  MarkStaticCheck.cpp
   RedundantInlineSpecifierCheck.cpp
   InconsistentDeclarationParameterNameCheck.cpp
   IsolateDeclarationCheck.cpp
diff --git a/clang-tools-extra/clang-tidy/readability/MarkStaticCheck.cpp b/clang-tools-extra/clang-tidy/readability/MarkStaticCheck.cpp
new file mode 100644
index 00000000000000..c8881963071de8
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/readability/MarkStaticCheck.cpp
@@ -0,0 +1,65 @@
+//===--- MarkStaticCheck.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 "MarkStaticCheck.h"
+#include "clang/AST/Decl.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+#include "clang/ASTMatchers/ASTMatchersMacros.h"
+#include "clang/Basic/Specifiers.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::readability {
+
+namespace {
+
+AST_POLYMORPHIC_MATCHER(isFirstDecl,
+                        AST_POLYMORPHIC_SUPPORTED_TYPES(FunctionDecl,
+                                                        VarDecl)) {
+  return Node.isFirstDecl();
+}
+
+AST_MATCHER(Decl, isInMainFile) {
+  return Finder->getASTContext().getSourceManager().isInMainFile(
+      Node.getLocation());
+}
+
+AST_POLYMORPHIC_MATCHER(isExternStorageClass,
+                        AST_POLYMORPHIC_SUPPORTED_TYPES(FunctionDecl,
+                                                        VarDecl)) {
+  return Node.getStorageClass() == SC_Extern;
+}
+
+} // namespace
+
+void MarkStaticCheck::registerMatchers(MatchFinder *Finder) {
+  auto Common =
+      allOf(isFirstDecl(), isInMainFile(),
+            unless(anyOf(isStaticStorageClass(), isExternStorageClass(),
+                         isInAnonymousNamespace())));
+  Finder->addMatcher(
+      functionDecl(Common, unless(cxxMethodDecl()), unless(isMain()))
+          .bind("fn"),
+      this);
+  Finder->addMatcher(varDecl(Common, hasGlobalStorage()).bind("var"), this);
+}
+
+void MarkStaticCheck::check(const MatchFinder::MatchResult &Result) {
+  if (const auto *FD = Result.Nodes.getNodeAs<FunctionDecl>("fn")) {
+    diag(FD->getLocation(), "function %0 can be static") << FD;
+    return;
+  }
+  if (const auto *VD = Result.Nodes.getNodeAs<VarDecl>("var")) {
+    diag(VD->getLocation(), "variable %0 can be static") << VD;
+    return;
+  }
+  llvm_unreachable("");
+}
+
+} // namespace clang::tidy::readability
diff --git a/clang-tools-extra/clang-tidy/readability/MarkStaticCheck.h b/clang-tools-extra/clang-tidy/readability/MarkStaticCheck.h
new file mode 100644
index 00000000000000..0af6788d3e3d85
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/readability/MarkStaticCheck.h
@@ -0,0 +1,33 @@
+//===--- MarkStaticCheck.h - clang-tidy -------------------------*- C++ -*-===//
+//
+// 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_MARKSTATICCHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_MARKSTATICCHECK_H
+
+#include "../ClangTidyCheck.h"
+
+namespace clang::tidy::readability {
+
+/// Detects variable and function can be marked as static.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/readability/mark-static.html
+class MarkStaticCheck : public ClangTidyCheck {
+public:
+  MarkStaticCheck(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context) {}
+  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 // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_MARKSTATICCHECK_H
diff --git a/clang-tools-extra/clang-tidy/readability/ReadabilityTidyModule.cpp b/clang-tools-extra/clang-tidy/readability/ReadabilityTidyModule.cpp
index d61c0ba39658e5..5c04426818b5f7 100644
--- a/clang-tools-extra/clang-tidy/readability/ReadabilityTidyModule.cpp
+++ b/clang-tools-extra/clang-tidy/readability/ReadabilityTidyModule.cpp
@@ -32,6 +32,7 @@
 #include "IsolateDeclarationCheck.h"
 #include "MagicNumbersCheck.h"
 #include "MakeMemberFunctionConstCheck.h"
+#include "MarkStaticCheck.h"
 #include "MathMissingParenthesesCheck.h"
 #include "MisleadingIndentationCheck.h"
 #include "MisplacedArrayIndexCheck.h"
@@ -106,6 +107,7 @@ class ReadabilityModule : public ClangTidyModule {
         "readability-identifier-naming");
     CheckFactories.registerCheck<ImplicitBoolConversionCheck>(
         "readability-implicit-bool-conversion");
+    CheckFactories.registerCheck<MarkStaticCheck>("readability-mark-static");
     CheckFactories.registerCheck<MathMissingParenthesesCheck>(
         "readability-math-missing-parentheses");
     CheckFactories.registerCheck<RedundantInlineSpecifierCheck>(
diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst
index 5956ccb925485c..35e4d7e722f1de 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -151,6 +151,11 @@ New checks
   Enforces consistent style for enumerators' initialization, covering three
   styles: none, first only, or all initialized explicitly.
 
+- New :doc:`readability-mark-static
+  <clang-tidy/checks/readability/mark-static>` check.
+
+  Detects variable and function can be marked as static.
+
 - New :doc:`readability-math-missing-parentheses
   <clang-tidy/checks/readability/math-missing-parentheses>` check.
 
diff --git a/clang-tools-extra/docs/clang-tidy/checks/list.rst b/clang-tools-extra/docs/clang-tidy/checks/list.rst
index 5cdaf9e35b6acd..4f473e13eb9480 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/list.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/list.rst
@@ -364,6 +364,7 @@ Clang-Tidy Checks
    :doc:`readability-isolate-declaration <readability/isolate-declaration>`, "Yes"
    :doc:`readability-magic-numbers <readability/magic-numbers>`,
    :doc:`readability-make-member-function-const <readability/make-member-function-const>`, "Yes"
+   :doc:`readability-mark-static <readability/mark-static>`,
    :doc:`readability-math-missing-parentheses <readability/math-missing-parentheses>`, "Yes"
    :doc:`readability-misleading-indentation <readability/misleading-indentation>`,
    :doc:`readability-misplaced-array-index <readability/misplaced-array-index>`, "Yes"
diff --git a/clang-tools-extra/docs/clang-tidy/checks/readability/mark-static.rst b/clang-tools-extra/docs/clang-tidy/checks/readability/mark-static.rst
new file mode 100644
index 00000000000000..24ba06acef261b
--- /dev/null
+++ b/clang-tools-extra/docs/clang-tidy/checks/readability/mark-static.rst
@@ -0,0 +1,26 @@
+.. title:: clang-tidy - readability-mark-static
+
+readability-mark-static
+=======================
+
+Detects variable and function can be marked as static.
+
+Static functions and variables are scoped to a single file. Marking functions
+and variables as static helps to better remove dead code. In addition, it gives
+the compiler more information and can help compiler make more aggressive
+optimizations.
+
+Example:
+
+.. code-block:: c++
+  int v1; // can be marked as static
+
+  void fn1(); // can be marked as static
+
+  namespace {
+    // already in anonymous namespace
+    int v2;
+    void fn2();
+  }
+  // already declared as extern
+  extern int v2;
diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/Inputs/mark-static-var/func.h b/clang-tools-extra/test/clang-tidy/checkers/readability/Inputs/mark-static-var/func.h
new file mode 100644
index 00000000000000..31c68e9ad0cd92
--- /dev/null
+++ b/clang-tools-extra/test/clang-tidy/checkers/readability/Inputs/mark-static-var/func.h
@@ -0,0 +1,3 @@
+#pragma once
+
+void func_header();
diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/Inputs/mark-static-var/var.h b/clang-tools-extra/test/clang-tidy/checkers/readability/Inputs/mark-static-var/var.h
new file mode 100644
index 00000000000000..37e4cfbafff146
--- /dev/null
+++ b/clang-tools-extra/test/clang-tidy/checkers/readability/Inputs/mark-static-var/var.h
@@ -0,0 +1,3 @@
+#pragma once
+
+extern int gloabl_header;
diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/mark-static-func.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability/mark-static-func.cpp
new file mode 100644
index 00000000000000..c9adcc70b8c5cb
--- /dev/null
+++ b/clang-tools-extra/test/clang-tidy/checkers/readability/mark-static-func.cpp
@@ -0,0 +1,24 @@
+// RUN: %check_clang_tidy %s readability-mark-static %t -- -- -I%S/Inputs/mark-static-var
+
+#include "func.h"
+
+void func() {}
+// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: function 'func'
+
+template<class T>
+void func_template() {}
+// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: function 'func_template'
+
+struct S {
+  void method();
+};
+void S::method() {}
+
+void func_header();
+extern void func_extern();
+static void func_static();
+namespace {
+void func_anonymous_ns();
+} // namespace
+
+int main(int argc, const char*argv[]) {}
diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/mark-static-var.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability/mark-static-var.cpp
new file mode 100644
index 00000000000000..f0b0486dd38c63
--- /dev/null
+++ b/clang-tools-extra/test/clang-tidy/checkers/readability/mark-static-var.cpp
@@ -0,0 +1,34 @@
+// RUN: %check_clang_tidy %s readability-mark-static %t -- -- -I%S/Inputs/mark-static-var
+
+#include "var.h"
+
+int global;
+// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: variable 'global'
+
+template<class T>
+T global_template;
+// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: variable 'global_template'
+
+int gloabl_header;
+
+extern int global_extern;
+
+static int global_static;
+
+namespace {
+static int global_anonymous_ns;
+namespace NS {
+static int global_anonymous_ns;
+}
+}
+
+static void f(int para) {
+  int local;
+  static int local_static;
+}
+
+struct S {
+  int m1;
+  static int m2;
+};
+int S::m2;

>From aea346161bf7390e044c825c734ab6624ed35ecc Mon Sep 17 00:00:00 2001
From: Congcong Cai <congcongcai0907 at 163.com>
Date: Fri, 3 May 2024 14:33:37 +0800
Subject: [PATCH 2/4] rename

---
 .../clang-tidy/readability/CMakeLists.txt          |  2 +-
 .../readability/ReadabilityTidyModule.cpp          |  4 ++--
 ...eck.cpp => UnnecessaryExternalLinkageCheck.cpp} | 10 ++++++----
 ...icCheck.h => UnnecessaryExternalLinkageCheck.h} | 14 +++++++-------
 clang-tools-extra/docs/ReleaseNotes.rst            |  4 ++--
 clang-tools-extra/docs/clang-tidy/checks/list.rst  |  2 +-
 ...static.rst => unnecessary-external-linkage.rst} |  6 +++---
 ...c.cpp => unnecessary-external-linkage-func.cpp} |  2 +-
 ...ar.cpp => unnecessary-external-linkage-var.cpp} |  2 +-
 9 files changed, 24 insertions(+), 22 deletions(-)
 rename clang-tools-extra/clang-tidy/readability/{MarkStaticCheck.cpp => UnnecessaryExternalLinkageCheck.cpp} (86%)
 rename clang-tools-extra/clang-tidy/readability/{MarkStaticCheck.h => UnnecessaryExternalLinkageCheck.h} (59%)
 rename clang-tools-extra/docs/clang-tidy/checks/readability/{mark-static.rst => unnecessary-external-linkage.rst} (78%)
 rename clang-tools-extra/test/clang-tidy/checkers/readability/{mark-static-func.cpp => unnecessary-external-linkage-func.cpp} (80%)
 rename clang-tools-extra/test/clang-tidy/checkers/readability/{mark-static-var.cpp => unnecessary-external-linkage-var.cpp} (82%)

diff --git a/clang-tools-extra/clang-tidy/readability/CMakeLists.txt b/clang-tools-extra/clang-tidy/readability/CMakeLists.txt
index 3e0cbc4d943274..8f58d9f24ba491 100644
--- a/clang-tools-extra/clang-tidy/readability/CMakeLists.txt
+++ b/clang-tools-extra/clang-tidy/readability/CMakeLists.txt
@@ -23,7 +23,7 @@ add_clang_library(clangTidyReadabilityModule
   IdentifierLengthCheck.cpp
   IdentifierNamingCheck.cpp
   ImplicitBoolConversionCheck.cpp
-  MarkStaticCheck.cpp
+  UnnecessaryExternalLinkageCheck.cpp
   RedundantInlineSpecifierCheck.cpp
   InconsistentDeclarationParameterNameCheck.cpp
   IsolateDeclarationCheck.cpp
diff --git a/clang-tools-extra/clang-tidy/readability/ReadabilityTidyModule.cpp b/clang-tools-extra/clang-tidy/readability/ReadabilityTidyModule.cpp
index 5c04426818b5f7..baa4eec704bde4 100644
--- a/clang-tools-extra/clang-tidy/readability/ReadabilityTidyModule.cpp
+++ b/clang-tools-extra/clang-tidy/readability/ReadabilityTidyModule.cpp
@@ -32,7 +32,7 @@
 #include "IsolateDeclarationCheck.h"
 #include "MagicNumbersCheck.h"
 #include "MakeMemberFunctionConstCheck.h"
-#include "MarkStaticCheck.h"
+#include "UnnecessaryExternalLinkageCheck.h"
 #include "MathMissingParenthesesCheck.h"
 #include "MisleadingIndentationCheck.h"
 #include "MisplacedArrayIndexCheck.h"
@@ -107,7 +107,7 @@ class ReadabilityModule : public ClangTidyModule {
         "readability-identifier-naming");
     CheckFactories.registerCheck<ImplicitBoolConversionCheck>(
         "readability-implicit-bool-conversion");
-    CheckFactories.registerCheck<MarkStaticCheck>("readability-mark-static");
+    CheckFactories.registerCheck<UnnecessaryExternalLinkageCheck>("readability-unnecessary-external-linkage");
     CheckFactories.registerCheck<MathMissingParenthesesCheck>(
         "readability-math-missing-parentheses");
     CheckFactories.registerCheck<RedundantInlineSpecifierCheck>(
diff --git a/clang-tools-extra/clang-tidy/readability/MarkStaticCheck.cpp b/clang-tools-extra/clang-tidy/readability/UnnecessaryExternalLinkageCheck.cpp
similarity index 86%
rename from clang-tools-extra/clang-tidy/readability/MarkStaticCheck.cpp
rename to clang-tools-extra/clang-tidy/readability/UnnecessaryExternalLinkageCheck.cpp
index c8881963071de8..013f67697da1b8 100644
--- a/clang-tools-extra/clang-tidy/readability/MarkStaticCheck.cpp
+++ b/clang-tools-extra/clang-tidy/readability/UnnecessaryExternalLinkageCheck.cpp
@@ -1,4 +1,4 @@
-//===--- MarkStaticCheck.cpp - clang-tidy ---------------------------------===//
+//===--- UnnecessaryExternalLinkageCheck.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.
@@ -6,7 +6,7 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include "MarkStaticCheck.h"
+#include "UnnecessaryExternalLinkageCheck.h"
 #include "clang/AST/Decl.h"
 #include "clang/ASTMatchers/ASTMatchFinder.h"
 #include "clang/ASTMatchers/ASTMatchers.h"
@@ -38,7 +38,7 @@ AST_POLYMORPHIC_MATCHER(isExternStorageClass,
 
 } // namespace
 
-void MarkStaticCheck::registerMatchers(MatchFinder *Finder) {
+void UnnecessaryExternalLinkageCheck::registerMatchers(MatchFinder *Finder) {
   auto Common =
       allOf(isFirstDecl(), isInMainFile(),
             unless(anyOf(isStaticStorageClass(), isExternStorageClass(),
@@ -50,7 +50,9 @@ void MarkStaticCheck::registerMatchers(MatchFinder *Finder) {
   Finder->addMatcher(varDecl(Common, hasGlobalStorage()).bind("var"), this);
 }
 
-void MarkStaticCheck::check(const MatchFinder::MatchResult &Result) {
+
+
+void UnnecessaryExternalLinkageCheck::check(const MatchFinder::MatchResult &Result) {
   if (const auto *FD = Result.Nodes.getNodeAs<FunctionDecl>("fn")) {
     diag(FD->getLocation(), "function %0 can be static") << FD;
     return;
diff --git a/clang-tools-extra/clang-tidy/readability/MarkStaticCheck.h b/clang-tools-extra/clang-tidy/readability/UnnecessaryExternalLinkageCheck.h
similarity index 59%
rename from clang-tools-extra/clang-tidy/readability/MarkStaticCheck.h
rename to clang-tools-extra/clang-tidy/readability/UnnecessaryExternalLinkageCheck.h
index 0af6788d3e3d85..523e271ef20626 100644
--- a/clang-tools-extra/clang-tidy/readability/MarkStaticCheck.h
+++ b/clang-tools-extra/clang-tidy/readability/UnnecessaryExternalLinkageCheck.h
@@ -1,4 +1,4 @@
-//===--- MarkStaticCheck.h - clang-tidy -------------------------*- C++ -*-===//
+//===--- UnnecessaryExternalLinkageCheck.h - clang-tidy ---------*- C++ -*-===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
@@ -6,8 +6,8 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_MARKSTATICCHECK_H
-#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_MARKSTATICCHECK_H
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_UNNECESSARYEXTERNALLINKAGECHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_UNNECESSARYEXTERNALLINKAGECHECK_H
 
 #include "../ClangTidyCheck.h"
 
@@ -16,10 +16,10 @@ namespace clang::tidy::readability {
 /// Detects variable and function can be marked as static.
 ///
 /// For the user-facing documentation see:
-/// http://clang.llvm.org/extra/clang-tidy/checks/readability/mark-static.html
-class MarkStaticCheck : public ClangTidyCheck {
+/// http://clang.llvm.org/extra/clang-tidy/checks/readability/unnecessary-external-linkage.html
+class UnnecessaryExternalLinkageCheck : public ClangTidyCheck {
 public:
-  MarkStaticCheck(StringRef Name, ClangTidyContext *Context)
+  UnnecessaryExternalLinkageCheck(StringRef Name, ClangTidyContext *Context)
       : ClangTidyCheck(Name, Context) {}
   void registerMatchers(ast_matchers::MatchFinder *Finder) override;
   void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
@@ -30,4 +30,4 @@ class MarkStaticCheck : public ClangTidyCheck {
 
 } // namespace clang::tidy::readability
 
-#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_MARKSTATICCHECK_H
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_UNNECESSARYEXTERNALLINKAGECHECK_H
diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst
index 35e4d7e722f1de..6269393eb02b8b 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -151,8 +151,8 @@ New checks
   Enforces consistent style for enumerators' initialization, covering three
   styles: none, first only, or all initialized explicitly.
 
-- New :doc:`readability-mark-static
-  <clang-tidy/checks/readability/mark-static>` check.
+- New :doc:`readability-unnecessary-external-linkage
+  <clang-tidy/checks/readability/unnecessary-external-linkage>` check.
 
   Detects variable and function can be marked as static.
 
diff --git a/clang-tools-extra/docs/clang-tidy/checks/list.rst b/clang-tools-extra/docs/clang-tidy/checks/list.rst
index 4f473e13eb9480..c50ed21a07abb9 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/list.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/list.rst
@@ -364,7 +364,6 @@ Clang-Tidy Checks
    :doc:`readability-isolate-declaration <readability/isolate-declaration>`, "Yes"
    :doc:`readability-magic-numbers <readability/magic-numbers>`,
    :doc:`readability-make-member-function-const <readability/make-member-function-const>`, "Yes"
-   :doc:`readability-mark-static <readability/mark-static>`,
    :doc:`readability-math-missing-parentheses <readability/math-missing-parentheses>`, "Yes"
    :doc:`readability-misleading-indentation <readability/misleading-indentation>`,
    :doc:`readability-misplaced-array-index <readability/misplaced-array-index>`, "Yes"
@@ -391,6 +390,7 @@ Clang-Tidy Checks
    :doc:`readability-string-compare <readability/string-compare>`, "Yes"
    :doc:`readability-suspicious-call-argument <readability/suspicious-call-argument>`,
    :doc:`readability-uniqueptr-delete-release <readability/uniqueptr-delete-release>`, "Yes"
+   :doc:`readability-unnecessary-external-linkage <readability/unnecessary-external-linkage>`,
    :doc:`readability-uppercase-literal-suffix <readability/uppercase-literal-suffix>`, "Yes"
    :doc:`readability-use-anyofallof <readability/use-anyofallof>`,
    :doc:`readability-use-std-min-max <readability/use-std-min-max>`, "Yes"
diff --git a/clang-tools-extra/docs/clang-tidy/checks/readability/mark-static.rst b/clang-tools-extra/docs/clang-tidy/checks/readability/unnecessary-external-linkage.rst
similarity index 78%
rename from clang-tools-extra/docs/clang-tidy/checks/readability/mark-static.rst
rename to clang-tools-extra/docs/clang-tidy/checks/readability/unnecessary-external-linkage.rst
index 24ba06acef261b..f25c7197cd0da1 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/readability/mark-static.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/readability/unnecessary-external-linkage.rst
@@ -1,7 +1,7 @@
-.. title:: clang-tidy - readability-mark-static
+.. title:: clang-tidy - readability-unnecessary-external-linkage
 
-readability-mark-static
-=======================
+readability-unnecessary-external-linkage
+========================================
 
 Detects variable and function can be marked as static.
 
diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/mark-static-func.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability/unnecessary-external-linkage-func.cpp
similarity index 80%
rename from clang-tools-extra/test/clang-tidy/checkers/readability/mark-static-func.cpp
rename to clang-tools-extra/test/clang-tidy/checkers/readability/unnecessary-external-linkage-func.cpp
index c9adcc70b8c5cb..ccc0013b360a81 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/readability/mark-static-func.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/readability/unnecessary-external-linkage-func.cpp
@@ -1,4 +1,4 @@
-// RUN: %check_clang_tidy %s readability-mark-static %t -- -- -I%S/Inputs/mark-static-var
+// RUN: %check_clang_tidy %s readability-unnecessary-external-linkage %t -- -- -I%S/Inputs/mark-static-var
 
 #include "func.h"
 
diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/mark-static-var.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability/unnecessary-external-linkage-var.cpp
similarity index 82%
rename from clang-tools-extra/test/clang-tidy/checkers/readability/mark-static-var.cpp
rename to clang-tools-extra/test/clang-tidy/checkers/readability/unnecessary-external-linkage-var.cpp
index f0b0486dd38c63..30dee9f8660946 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/readability/mark-static-var.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/readability/unnecessary-external-linkage-var.cpp
@@ -1,4 +1,4 @@
-// RUN: %check_clang_tidy %s readability-mark-static %t -- -- -I%S/Inputs/mark-static-var
+// RUN: %check_clang_tidy %s readability-unnecessary-external-linkage %t -- -- -I%S/Inputs/mark-static-var
 
 #include "var.h"
 

>From 0d821c495efb270f186507f6976cb4c3c43f180e Mon Sep 17 00:00:00 2001
From: Congcong Cai <congcongcai0907 at 163.com>
Date: Fri, 3 May 2024 14:39:53 +0800
Subject: [PATCH 3/4] fix

---
 .../readability/UnnecessaryExternalLinkageCheck.cpp      | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/clang-tools-extra/clang-tidy/readability/UnnecessaryExternalLinkageCheck.cpp b/clang-tools-extra/clang-tidy/readability/UnnecessaryExternalLinkageCheck.cpp
index 013f67697da1b8..e4f5dc0c6f4a88 100644
--- a/clang-tools-extra/clang-tidy/readability/UnnecessaryExternalLinkageCheck.cpp
+++ b/clang-tools-extra/clang-tidy/readability/UnnecessaryExternalLinkageCheck.cpp
@@ -50,15 +50,18 @@ void UnnecessaryExternalLinkageCheck::registerMatchers(MatchFinder *Finder) {
   Finder->addMatcher(varDecl(Common, hasGlobalStorage()).bind("var"), this);
 }
 
-
+static constexpr StringRef Message =
+    "%0 %1 can be internal linkage, "
+    "marking as static or using anonymous namespace can avoid external "
+    "linkage.";
 
 void UnnecessaryExternalLinkageCheck::check(const MatchFinder::MatchResult &Result) {
   if (const auto *FD = Result.Nodes.getNodeAs<FunctionDecl>("fn")) {
-    diag(FD->getLocation(), "function %0 can be static") << FD;
+    diag(FD->getLocation(), Message) << "function" << FD;
     return;
   }
   if (const auto *VD = Result.Nodes.getNodeAs<VarDecl>("var")) {
-    diag(VD->getLocation(), "variable %0 can be static") << VD;
+    diag(VD->getLocation(), Message) << "variable" << VD;
     return;
   }
   llvm_unreachable("");

>From 1bb5ed2ebd9e1b40fe581b719181681f71f78fa2 Mon Sep 17 00:00:00 2001
From: Congcong Cai <congcongcai0907 at 163.com>
Date: Fri, 3 May 2024 15:33:16 +0800
Subject: [PATCH 4/4] fix

---
 .../UnnecessaryExternalLinkageCheck.cpp       | 22 ++++++++++++++-----
 .../unnecessary-external-linkage-func.cpp     |  6 +++++
 .../unnecessary-external-linkage-var.cpp      |  6 +++++
 3 files changed, 28 insertions(+), 6 deletions(-)

diff --git a/clang-tools-extra/clang-tidy/readability/UnnecessaryExternalLinkageCheck.cpp b/clang-tools-extra/clang-tidy/readability/UnnecessaryExternalLinkageCheck.cpp
index e4f5dc0c6f4a88..fd302f5ab154b5 100644
--- a/clang-tools-extra/clang-tidy/readability/UnnecessaryExternalLinkageCheck.cpp
+++ b/clang-tools-extra/clang-tidy/readability/UnnecessaryExternalLinkageCheck.cpp
@@ -26,8 +26,11 @@ AST_POLYMORPHIC_MATCHER(isFirstDecl,
 }
 
 AST_MATCHER(Decl, isInMainFile) {
-  return Finder->getASTContext().getSourceManager().isInMainFile(
-      Node.getLocation());
+  for (const Decl *D : Node.redecls())
+    if (!Finder->getASTContext().getSourceManager().isInMainFile(
+            D->getLocation()))
+      return false;
+  return true;
 }
 
 AST_POLYMORPHIC_MATCHER(isExternStorageClass,
@@ -39,10 +42,17 @@ AST_POLYMORPHIC_MATCHER(isExternStorageClass,
 } // namespace
 
 void UnnecessaryExternalLinkageCheck::registerMatchers(MatchFinder *Finder) {
-  auto Common =
-      allOf(isFirstDecl(), isInMainFile(),
-            unless(anyOf(isStaticStorageClass(), isExternStorageClass(),
-                         isInAnonymousNamespace())));
+  auto Common = allOf(isFirstDecl(), isInMainFile(),
+                      unless(anyOf(
+                          // 1. internal linkage
+                          isStaticStorageClass(), isInAnonymousNamespace(),
+                          // 2. explicit external linkage
+                          isExternStorageClass(), isExternC(),
+                          // 3. template
+                          isExplicitTemplateSpecialization(),
+                          clang::ast_matchers::isTemplateInstantiation(),
+                          // 4. friend
+                          hasAncestor(friendDecl()))));
   Finder->addMatcher(
       functionDecl(Common, unless(cxxMethodDecl()), unless(isMain()))
           .bind("fn"),
diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/unnecessary-external-linkage-func.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability/unnecessary-external-linkage-func.cpp
index ccc0013b360a81..362def250d68c5 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/readability/unnecessary-external-linkage-func.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/readability/unnecessary-external-linkage-func.cpp
@@ -22,3 +22,9 @@ void func_anonymous_ns();
 } // namespace
 
 int main(int argc, const char*argv[]) {}
+
+extern "C" {
+void func_extern_c_1() {}
+}
+
+extern "C" void func_extern_c_2() {}
diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/unnecessary-external-linkage-var.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability/unnecessary-external-linkage-var.cpp
index 30dee9f8660946..68981e04fa5dc8 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/readability/unnecessary-external-linkage-var.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/readability/unnecessary-external-linkage-var.cpp
@@ -32,3 +32,9 @@ struct S {
   static int m2;
 };
 int S::m2;
+
+extern "C" {
+int global_in_extern_c_1;
+}
+
+extern "C" int global_in_extern_c_2;



More information about the cfe-commits mailing list