[clang-tools-extra] [clang-tidy] Use lexical anon-ns matcher in llvm-prefer-static-over-anonymous-namespace (PR #148357)
Baranov Victor via cfe-commits
cfe-commits at lists.llvm.org
Sat Jul 12 04:24:47 PDT 2025
https://github.com/vbvictor updated https://github.com/llvm/llvm-project/pull/148357
>From 82bee931621536e7e59910f1833289510909ce23 Mon Sep 17 00:00:00 2001
From: Victor Baranov <bar.victor.2002 at gmail.com>
Date: Sat, 12 Jul 2025 14:24:31 +0300
Subject: [PATCH] [clang-tidy] Use lexical anon-ns matcher in
llvm-prefer-static-over-anonymous-namespace
---
...referStaticOverAnonymousNamespaceCheck.cpp | 17 +++-
...prefer-static-over-anonymous-namespace.cpp | 89 +++++++++++++++++++
2 files changed, 103 insertions(+), 3 deletions(-)
diff --git a/clang-tools-extra/clang-tidy/llvm/PreferStaticOverAnonymousNamespaceCheck.cpp b/clang-tools-extra/clang-tidy/llvm/PreferStaticOverAnonymousNamespaceCheck.cpp
index 592f0986292f2..ea79bfaef8876 100644
--- a/clang-tools-extra/clang-tidy/llvm/PreferStaticOverAnonymousNamespaceCheck.cpp
+++ b/clang-tools-extra/clang-tidy/llvm/PreferStaticOverAnonymousNamespaceCheck.cpp
@@ -21,6 +21,17 @@ AST_MATCHER(NamedDecl, isInMacro) {
AST_MATCHER(VarDecl, isLocalVariable) { return Node.isLocalVarDecl(); }
+AST_MATCHER(Decl, isLexicallyInAnonymousNamespace) {
+ for (const DeclContext *DC = Node.getLexicalDeclContext(); DC != nullptr;
+ DC = DC->getLexicalParent()) {
+ if (const auto *ND = dyn_cast<NamespaceDecl>(DC))
+ if (ND->isAnonymousNamespace())
+ return true;
+ }
+
+ return false;
+}
+
} // namespace
PreferStaticOverAnonymousNamespaceCheck::
@@ -40,9 +51,9 @@ void PreferStaticOverAnonymousNamespaceCheck::storeOptions(
void PreferStaticOverAnonymousNamespaceCheck::registerMatchers(
MatchFinder *Finder) {
- const auto IsDefinitionInAnonymousNamespace =
- allOf(unless(isExpansionInSystemHeader()), isInAnonymousNamespace(),
- unless(isInMacro()), isDefinition());
+ const auto IsDefinitionInAnonymousNamespace = allOf(
+ unless(isExpansionInSystemHeader()), isLexicallyInAnonymousNamespace(),
+ unless(isInMacro()), isDefinition());
if (AllowMemberFunctionsInClass) {
Finder->addMatcher(
diff --git a/clang-tools-extra/test/clang-tidy/checkers/llvm/prefer-static-over-anonymous-namespace.cpp b/clang-tools-extra/test/clang-tidy/checkers/llvm/prefer-static-over-anonymous-namespace.cpp
index f0ffafcf18e67..71dce6ea4f01c 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/llvm/prefer-static-over-anonymous-namespace.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/llvm/prefer-static-over-anonymous-namespace.cpp
@@ -178,6 +178,95 @@ void OuterClass::NestedClass::nestedMemberFunc() {}
} // namespace
+namespace {
+
+class MyClassOutOfAnon {
+public:
+ MyClassOutOfAnon();
+ MyClassOutOfAnon(const MyClassOutOfAnon&) {}
+ // CHECK-MESSAGES-MEM: :[[@LINE-1]]:3: warning: place definition of method 'MyClassOutOfAnon' outside of an anonymous namespace
+ MyClassOutOfAnon(MyClassOutOfAnon&&) = default;
+ // CHECK-MESSAGES-MEM: :[[@LINE-1]]:3: warning: place definition of method 'MyClassOutOfAnon' outside of an anonymous namespace
+ MyClassOutOfAnon& operator=(const MyClassOutOfAnon&);
+ MyClassOutOfAnon& operator=(MyClassOutOfAnon&&);
+ bool operator<(const MyClassOutOfAnon&) const;
+ void memberFunction();
+ static void staticMemberFunction();
+ void memberDefinedInClass() {}
+ // CHECK-MESSAGES-MEM: :[[@LINE-1]]:8: warning: place definition of method 'memberDefinedInClass' outside of an anonymous namespace
+ static void staticMemberDefinedInClass() {}
+ // CHECK-MESSAGES-MEM: :[[@LINE-1]]:15: warning: place definition of method 'staticMemberDefinedInClass' outside of an anonymous namespace
+ template <typename T>
+ void templateFunction();
+ template <typename T>
+ void templateFunctionInClass() {}
+ // CHECK-MESSAGES-MEM: :[[@LINE-1]]:8: warning: place definition of method 'templateFunctionInClass' outside of an anonymous namespace
+};
+
+} // namespace
+
+MyClassOutOfAnon::MyClassOutOfAnon() {}
+
+MyClassOutOfAnon& MyClassOutOfAnon::operator=(const MyClassOutOfAnon&) { return *this; }
+
+MyClassOutOfAnon& MyClassOutOfAnon::operator=(MyClassOutOfAnon&&) = default;
+
+bool MyClassOutOfAnon::operator<(const MyClassOutOfAnon&) const { return true; }
+
+void MyClassOutOfAnon::memberFunction() {}
+
+void MyClassOutOfAnon::staticMemberFunction() {}
+
+template <typename T>
+void MyClassOutOfAnon::templateFunction() {}
+
+namespace {
+
+template<typename T>
+class TemplateClassOutOfAnon {
+ public:
+ TemplateClassOutOfAnon();
+ TemplateClassOutOfAnon(const TemplateClassOutOfAnon&) {}
+ // CHECK-MESSAGES-MEM: :[[@LINE-1]]:3: warning: place definition of method 'TemplateClassOutOfAnon<T>' outside of an anonymous namespace
+ TemplateClassOutOfAnon(TemplateClassOutOfAnon&&) = default;
+ // CHECK-MESSAGES-MEM: :[[@LINE-1]]:3: warning: place definition of method 'TemplateClassOutOfAnon<T>' outside of an anonymous namespace
+ TemplateClassOutOfAnon& operator=(const TemplateClassOutOfAnon&);
+ TemplateClassOutOfAnon& operator=(TemplateClassOutOfAnon&&);
+ bool operator<(const TemplateClassOutOfAnon&) const;
+ void memberFunc();
+ T getValue() const;
+ void memberDefinedInClass() {}
+ // CHECK-MESSAGES-MEM: :[[@LINE-1]]:8: warning: place definition of method 'memberDefinedInClass' outside of an anonymous namespace
+ static void staticMemberDefinedInClass() {}
+ // CHECK-MESSAGES-MEM: :[[@LINE-1]]:15: warning: place definition of method 'staticMemberDefinedInClass' outside of an anonymous namespace
+ template <typename U>
+ void templateMethodInTemplateClass() {}
+ // CHECK-MESSAGES-MEM: :[[@LINE-1]]:8: warning: place definition of method 'templateMethodInTemplateClass' outside of an anonymous namespace
+ private:
+ T Value;
+};
+
+} // namespace
+
+template<typename T>
+TemplateClassOutOfAnon<T>::TemplateClassOutOfAnon() {}
+
+template<typename T>
+TemplateClassOutOfAnon<T>& TemplateClassOutOfAnon<T>::operator=(const TemplateClassOutOfAnon&) { return *this; }
+
+template<typename T>
+TemplateClassOutOfAnon<T>& TemplateClassOutOfAnon<T>::operator=(TemplateClassOutOfAnon&&) = default;
+
+template<typename T>
+bool TemplateClassOutOfAnon<T>::operator<(const TemplateClassOutOfAnon&) const { return true; }
+
+template<typename T>
+void TemplateClassOutOfAnon<T>::memberFunc() {}
+
+template<typename T>
+T TemplateClassOutOfAnon<T>::getValue() const { return Value; }
+
+
#define DEFINE_FUNCTION(name) \
namespace { \
void name() {} \
More information about the cfe-commits
mailing list