https://github.com/localspook updated 
https://github.com/llvm/llvm-project/pull/173196

>From 34c52f3abe4786aaedecf30c916713b365691952 Mon Sep 17 00:00:00 2001
From: Victor Chernyakin <[email protected]>
Date: Sun, 21 Dec 2025 10:05:40 -0700
Subject: [PATCH 1/2] [clang-tidy] Add first-class C support to
 `misc-use-internal-linkage`

---
 .../misc/UseInternalLinkageCheck.cpp          |  6 ++--
 .../checks/misc/use-internal-linkage.rst      | 17 ++++++----
 .../misc/use-internal-linkage-consteval.cpp   |  2 +-
 .../use-internal-linkage-fix-mode-none.cpp    |  4 +--
 .../misc/use-internal-linkage-func.cpp        | 24 +++++++-------
 .../misc/use-internal-linkage-var.cpp         | 10 +++---
 .../checkers/misc/use-internal-linkage.c      | 33 +++++++++++++++++++
 7 files changed, 66 insertions(+), 30 deletions(-)
 create mode 100644 
clang-tools-extra/test/clang-tidy/checkers/misc/use-internal-linkage.c

diff --git a/clang-tools-extra/clang-tidy/misc/UseInternalLinkageCheck.cpp 
b/clang-tools-extra/clang-tidy/misc/UseInternalLinkageCheck.cpp
index bad51c600f1cb..254de05e5e464 100644
--- a/clang-tools-extra/clang-tidy/misc/UseInternalLinkageCheck.cpp
+++ b/clang-tools-extra/clang-tidy/misc/UseInternalLinkageCheck.cpp
@@ -137,13 +137,13 @@ void 
UseInternalLinkageCheck::registerMatchers(MatchFinder *Finder) {
 }
 
 static constexpr StringRef Message =
-    "%0 %1 can be made static or moved into an anonymous namespace "
+    "%0 %1 can be made static %select{|or moved into an anonymous namespace }2"
     "to enforce internal linkage";
 
 void UseInternalLinkageCheck::check(const MatchFinder::MatchResult &Result) {
   if (const auto *FD = Result.Nodes.getNodeAs<FunctionDecl>("fn")) {
     const DiagnosticBuilder DB = diag(FD->getLocation(), Message)
-                                 << "function" << FD;
+                                 << "function" << FD << 
getLangOpts().CPlusPlus;
     const SourceLocation FixLoc = FD->getInnerLocStart();
     if (FixLoc.isInvalid() || FixLoc.isMacroID())
       return;
@@ -159,7 +159,7 @@ void UseInternalLinkageCheck::check(const 
MatchFinder::MatchResult &Result) {
       return;
 
     const DiagnosticBuilder DB = diag(VD->getLocation(), Message)
-                                 << "variable" << VD;
+                                 << "variable" << VD << 
getLangOpts().CPlusPlus;
     const SourceLocation FixLoc = VD->getInnerLocStart();
     if (FixLoc.isInvalid() || FixLoc.isMacroID())
       return;
diff --git 
a/clang-tools-extra/docs/clang-tidy/checks/misc/use-internal-linkage.rst 
b/clang-tools-extra/docs/clang-tidy/checks/misc/use-internal-linkage.rst
index 224ad21ecc5c3..9e08e0c12d644 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/misc/use-internal-linkage.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/misc/use-internal-linkage.rst
@@ -3,8 +3,8 @@
 misc-use-internal-linkage
 =========================
 
-Detects variables and functions that can be marked as static or moved into
-an anonymous namespace to enforce internal linkage.
+Detects variables and functions that can be marked as static or (in C++)
+moved into an anonymous namespace to enforce internal linkage.
 
 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
@@ -18,17 +18,20 @@ Example:
 
   void fn1() {} // can be marked as static
 
-  namespace {
-    // already in anonymous namespace
-    int v2;
-    void fn2();
-  }
   // already declared as extern
   extern int v2;
 
   void fn3(); // without function body in all declaration, maybe external 
linkage
   void fn3();
 
+  // === C++-specific ===
+
+  namespace {
+    // already in anonymous namespace
+    int v2;
+    void fn2();
+  }
+
   // export declarations
   export void fn4() {}
   export namespace t { void fn5() {} }
diff --git 
a/clang-tools-extra/test/clang-tidy/checkers/misc/use-internal-linkage-consteval.cpp
 
b/clang-tools-extra/test/clang-tidy/checkers/misc/use-internal-linkage-consteval.cpp
index 62c9818e07c4f..b63e87da25cea 100644
--- 
a/clang-tools-extra/test/clang-tidy/checkers/misc/use-internal-linkage-consteval.cpp
+++ 
b/clang-tools-extra/test/clang-tidy/checkers/misc/use-internal-linkage-consteval.cpp
@@ -3,5 +3,5 @@
 consteval void gh122096() {}
 
 constexpr void cxf() {}
-// CHECK-MESSAGES: :[[@LINE-1]]:16: warning: function 'cxf'
+// CHECK-MESSAGES: :[[@LINE-1]]:16: warning: function 'cxf' can be made static 
or moved into an anonymous namespace to enforce internal linkage
 // CHECK-FIXES: static constexpr void cxf() {}
diff --git 
a/clang-tools-extra/test/clang-tidy/checkers/misc/use-internal-linkage-fix-mode-none.cpp
 
b/clang-tools-extra/test/clang-tidy/checkers/misc/use-internal-linkage-fix-mode-none.cpp
index 3f2f5897bf718..8eb4a40d2d7d6 100644
--- 
a/clang-tools-extra/test/clang-tidy/checkers/misc/use-internal-linkage-fix-mode-none.cpp
+++ 
b/clang-tools-extra/test/clang-tidy/checkers/misc/use-internal-linkage-fix-mode-none.cpp
@@ -2,9 +2,9 @@
 // RUN:   -config="{CheckOptions: {misc-use-internal-linkage.FixMode: 
'None'}}"  -- -I%S/Inputs/use-internal-linkage
 
 void func() {}
-// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: function 'func'
+// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: function 'func' can be made static 
or moved into an anonymous namespace to enforce internal linkage
 // CHECK-FIXES-NOT: static void func() {}
 
 int global;
-// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: variable 'global'
+// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: variable 'global' can be made 
static or moved into an anonymous namespace to enforce internal linkage
 // CHECK-FIXES-NOT: static int global;
diff --git 
a/clang-tools-extra/test/clang-tidy/checkers/misc/use-internal-linkage-func.cpp 
b/clang-tools-extra/test/clang-tidy/checkers/misc/use-internal-linkage-func.cpp
index abf95b857c192..9ec851b8ac0d6 100644
--- 
a/clang-tools-extra/test/clang-tidy/checkers/misc/use-internal-linkage-func.cpp
+++ 
b/clang-tools-extra/test/clang-tidy/checkers/misc/use-internal-linkage-func.cpp
@@ -5,51 +5,51 @@
 #include "func.h"
 
 void func() {}
-// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: function 'func'
+// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: function 'func' can be made static 
or moved into an anonymous namespace to enforce internal linkage
 // CHECK-FIXES: static void func() {}
 
 template<class T>
 void func_template() {}
-// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: function 'func_template'
+// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: function 'func_template' can be 
made static or moved into an anonymous namespace to enforce internal linkage
 // CHECK-FIXES: static void func_template() {}
 
 void func_cpp_inc() {}
-// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: function 'func_cpp_inc'
+// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: function 'func_cpp_inc' can be 
made static or moved into an anonymous namespace to enforce internal linkage
 // CHECK-FIXES: static void func_cpp_inc() {}
 
 int* func_cpp_inc_return_ptr() { return nullptr; }
-// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: function 'func_cpp_inc_return_ptr'
+// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: function 'func_cpp_inc_return_ptr' 
can be made static or moved into an anonymous namespace to enforce internal 
linkage
 // CHECK-FIXES: static int* func_cpp_inc_return_ptr() { return nullptr; }
 
 const int* func_cpp_inc_return_const_ptr() { return nullptr; }
-// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: function 
'func_cpp_inc_return_const_ptr'
+// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: function 
'func_cpp_inc_return_const_ptr' can be made static or moved into an anonymous 
namespace to enforce internal linkage
 // CHECK-FIXES: static const int* func_cpp_inc_return_const_ptr() { return 
nullptr; }
 
 int const* func_cpp_inc_return_ptr_const() { return nullptr; }
-// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: function 
'func_cpp_inc_return_ptr_const'
+// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: function 
'func_cpp_inc_return_ptr_const' can be made static or moved into an anonymous 
namespace to enforce internal linkage
 // CHECK-FIXES: static int const* func_cpp_inc_return_ptr_const() { return 
nullptr; }
 
 int * const func_cpp_inc_return_const() { return nullptr; }
-// CHECK-MESSAGES: :[[@LINE-1]]:13: warning: function 
'func_cpp_inc_return_const'
+// CHECK-MESSAGES: :[[@LINE-1]]:13: warning: function 
'func_cpp_inc_return_const' can be made static or moved into an anonymous 
namespace to enforce internal linkage
 // CHECK-FIXES: static int * const func_cpp_inc_return_const() { return 
nullptr; }
 
 volatile const int* func_cpp_inc_return_volatile_const_ptr() { return nullptr; 
}
-// CHECK-MESSAGES: :[[@LINE-1]]:21: warning: function 
'func_cpp_inc_return_volatile_const_ptr'
+// CHECK-MESSAGES: :[[@LINE-1]]:21: warning: function 
'func_cpp_inc_return_volatile_const_ptr' can be made static or moved into an 
anonymous namespace to enforce internal linkage
 // CHECK-FIXES: static volatile const int* 
func_cpp_inc_return_volatile_const_ptr() { return nullptr; }
 
 [[nodiscard]] void func_nodiscard() {}
-// CHECK-MESSAGES: :[[@LINE-1]]:20: warning: function 'func_nodiscard'
+// CHECK-MESSAGES: :[[@LINE-1]]:20: warning: function 'func_nodiscard' can be 
made static or moved into an anonymous namespace to enforce internal linkage
 // CHECK-FIXES: {{\[\[nodiscard\]\]}} static void func_nodiscard() {}
 
 #define NDS [[nodiscard]]
 #define NNDS
 
 NDS void func_nds() {}
-// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: function 'func_nds'
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: function 'func_nds' can be made 
static or moved into an anonymous namespace to enforce internal linkage
 // CHECK-FIXES: NDS static void func_nds() {}
 
 NNDS void func_nnds() {}
-// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: function 'func_nnds'
+// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: function 'func_nnds' can be made 
static or moved into an anonymous namespace to enforce internal linkage
 // CHECK-FIXES: NNDS static void func_nnds() {}
 
 #include "func_cpp.inc"
@@ -78,7 +78,7 @@ extern "C" void func_extern_c_2() {}
 
 namespace gh117488 {
 void func_with_body();
-// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: function 'func_with_body'
+// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: function 'func_with_body' can be 
made static or moved into an anonymous namespace to enforce internal linkage
 // CHECK-FIXES: static void func_with_body();
 void func_with_body() {}
 
diff --git 
a/clang-tools-extra/test/clang-tidy/checkers/misc/use-internal-linkage-var.cpp 
b/clang-tools-extra/test/clang-tidy/checkers/misc/use-internal-linkage-var.cpp
index 3da05c71dd94f..548f585fcbd31 100644
--- 
a/clang-tools-extra/test/clang-tidy/checkers/misc/use-internal-linkage-var.cpp
+++ 
b/clang-tools-extra/test/clang-tidy/checkers/misc/use-internal-linkage-var.cpp
@@ -5,24 +5,24 @@
 #include "var.h"
 
 int global;
-// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: variable 'global'
+// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: variable 'global' can be made 
static or moved into an anonymous namespace to enforce internal linkage
 // CHECK-FIXES: static int global;
 
 template<class T>
 T global_template;
-// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: variable 'global_template'
+// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: variable 'global_template' can be 
made static or moved into an anonymous namespace to enforce internal linkage
 // CHECK-FIXES: static T global_template;
 
 int const* ptr_const_star;
-// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: variable 'ptr_const_star'
+// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: variable 'ptr_const_star' can be 
made static or moved into an anonymous namespace to enforce internal linkage
 // CHECK-FIXES: static int const* ptr_const_star;
 
 const int* const_ptr_star;
-// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: variable 'const_ptr_star'
+// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: variable 'const_ptr_star' can be 
made static or moved into an anonymous namespace to enforce internal linkage
 // CHECK-FIXES: static const int* const_ptr_star;
 
 const volatile int* const_volatile_ptr_star;
-// CHECK-MESSAGES: :[[@LINE-1]]:21: warning: variable 'const_volatile_ptr_star'
+// CHECK-MESSAGES: :[[@LINE-1]]:21: warning: variable 
'const_volatile_ptr_star' can be made static or moved into an anonymous 
namespace to enforce internal linkage
 // CHECK-FIXES: static const volatile int* const_volatile_ptr_star;
 
 int gloabl_header;
diff --git 
a/clang-tools-extra/test/clang-tidy/checkers/misc/use-internal-linkage.c 
b/clang-tools-extra/test/clang-tidy/checkers/misc/use-internal-linkage.c
new file mode 100644
index 0000000000000..a1b431e1bb28a
--- /dev/null
+++ b/clang-tools-extra/test/clang-tidy/checkers/misc/use-internal-linkage.c
@@ -0,0 +1,33 @@
+// RUN: %check_clang_tidy %s misc-use-internal-linkage %t -- -- 
-I%S/Inputs/use-internal-linkage
+// RUN: %check_clang_tidy %s misc-use-internal-linkage %t -- \
+// RUN:   -config="{CheckOptions: {misc-use-internal-linkage.FixMode: 
'UseStatic'}}"  -- -I%S/Inputs/use-internal-linkage
+
+#include "func.h"
+
+void func() {}
+// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: function 'func' can be made static 
to enforce internal linkage
+// CHECK-FIXES: static void func() {}
+
+void func_header() {}
+extern void func_extern() {}
+static void func_static() {}
+
+int main() {}
+
+
+#include "var.h"
+
+int global;
+// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: variable 'global' can be made 
static to enforce internal linkage
+// CHECK-FIXES: static int global;
+
+const int const_global = 123;
+// CHECK-MESSAGES: :[[@LINE-1]]:21: warning: variable 'const_global' can be 
made static to enforce internal linkage
+// CHECK-FIXES: static const int const_global = 123;
+
+int gloabl_header;
+extern int global_extern;
+static int global_static;
+#if __STDC_VERSION__ >= 201112L
+_Thread_local int global_thread_local;
+#endif

>From a6d4b2cba3c75a45b4ff13bec625e19b10edd921 Mon Sep 17 00:00:00 2001
From: Victor Chernyakin <[email protected]>
Date: Sun, 21 Dec 2025 11:53:27 -0700
Subject: [PATCH 2/2] TMP

---
 .../clang-tidy/misc/UseInternalLinkageCheck.cpp            | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/clang-tools-extra/clang-tidy/misc/UseInternalLinkageCheck.cpp 
b/clang-tools-extra/clang-tidy/misc/UseInternalLinkageCheck.cpp
index 254de05e5e464..3fb13c8597324 100644
--- a/clang-tools-extra/clang-tidy/misc/UseInternalLinkageCheck.cpp
+++ b/clang-tools-extra/clang-tidy/misc/UseInternalLinkageCheck.cpp
@@ -20,6 +20,7 @@
 #include "llvm/ADT/SmallVector.h"
 
 using namespace clang::ast_matchers;
+using namespace clang::ast_matchers::internal;
 
 namespace clang::tidy {
 
@@ -115,7 +116,7 @@ void UseInternalLinkageCheck::registerMatchers(MatchFinder 
*Finder) {
                 // 1. internal linkage
                 isStaticStorageClass(), isInAnonymousNamespace(),
                 // 2. explicit external linkage
-                isExternStorageClass(), isExternC(),
+                isExternStorageClass(),
                 // 3. template
                 isExplicitTemplateSpecialization(),
                 hasAncestor(decl(anyOf(
@@ -142,6 +143,8 @@ static constexpr StringRef Message =
 
 void UseInternalLinkageCheck::check(const MatchFinder::MatchResult &Result) {
   if (const auto *FD = Result.Nodes.getNodeAs<FunctionDecl>("fn")) {
+    if (getLangOpts.CPlusPlus && FD.isExternC())
+      return;
     const DiagnosticBuilder DB = diag(FD->getLocation(), Message)
                                  << "function" << FD << 
getLangOpts().CPlusPlus;
     const SourceLocation FixLoc = FD->getInnerLocStart();
@@ -152,6 +155,8 @@ void UseInternalLinkageCheck::check(const 
MatchFinder::MatchResult &Result) {
     return;
   }
   if (const auto *VD = Result.Nodes.getNodeAs<VarDecl>("var")) {
+    if (getLangOpts.CPlusPlus && FD.isExternC())
+      return;
     // In C++, const variables at file scope have implicit internal linkage,
     // so we should not warn there. This is not the case in C.
     // https://eel.is/c++draft/diff#basic-3

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to