-
Notifications
You must be signed in to change notification settings - Fork 13.6k
[clang-tidy] Add new check llvm-prefer-static-over-anonymous-namespace
#142839
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
@llvm/pr-subscribers-clang-tools-extra @llvm/pr-subscribers-clang-tidy Author: Baranov Victor (vbvictor) ChangesFinds function and variable declarations inside anonymous namespace and suggests replacing them with The check will enforce that restrict-visibility rule in LLVM Coding Standards is followed correctly (by adding The check has additional levels of "strictness" represented by Options. Patch is 23.08 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/142839.diff 10 Files Affected:
diff --git a/clang-tools-extra/clang-tidy/llvm/CMakeLists.txt b/clang-tools-extra/clang-tidy/llvm/CMakeLists.txt
index 79c58a19aedac..3232f6e2cafe5 100644
--- a/clang-tools-extra/clang-tidy/llvm/CMakeLists.txt
+++ b/clang-tools-extra/clang-tidy/llvm/CMakeLists.txt
@@ -9,6 +9,7 @@ add_clang_library(clangTidyLLVMModule STATIC
LLVMTidyModule.cpp
PreferIsaOrDynCastInConditionalsCheck.cpp
PreferRegisterOverUnsignedCheck.cpp
+ PreferStaticOverAnonymousNamespaceCheck.cpp
TwineLocalCheck.cpp
LINK_LIBS
diff --git a/clang-tools-extra/clang-tidy/llvm/LLVMTidyModule.cpp b/clang-tools-extra/clang-tidy/llvm/LLVMTidyModule.cpp
index e749163699b34..854e32b5ec514 100644
--- a/clang-tools-extra/clang-tidy/llvm/LLVMTidyModule.cpp
+++ b/clang-tools-extra/clang-tidy/llvm/LLVMTidyModule.cpp
@@ -16,6 +16,7 @@
#include "IncludeOrderCheck.h"
#include "PreferIsaOrDynCastInConditionalsCheck.h"
#include "PreferRegisterOverUnsignedCheck.h"
+#include "PreferStaticOverAnonymousNamespaceCheck.h"
#include "TwineLocalCheck.h"
namespace clang::tidy {
@@ -34,6 +35,8 @@ class LLVMModule : public ClangTidyModule {
"llvm-prefer-isa-or-dyn-cast-in-conditionals");
CheckFactories.registerCheck<PreferRegisterOverUnsignedCheck>(
"llvm-prefer-register-over-unsigned");
+ CheckFactories.registerCheck<PreferStaticOverAnonymousNamespaceCheck>(
+ "llvm-prefer-static-over-anonymous-namespace");
CheckFactories.registerCheck<readability::QualifiedAutoCheck>(
"llvm-qualified-auto");
CheckFactories.registerCheck<TwineLocalCheck>("llvm-twine-local");
diff --git a/clang-tools-extra/clang-tidy/llvm/PreferStaticOverAnonymousNamespaceCheck.cpp b/clang-tools-extra/clang-tidy/llvm/PreferStaticOverAnonymousNamespaceCheck.cpp
new file mode 100644
index 0000000000000..f24504619b458
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/llvm/PreferStaticOverAnonymousNamespaceCheck.cpp
@@ -0,0 +1,96 @@
+//===--- PreferStaticOverAnonymousNamespaceCheck.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 "PreferStaticOverAnonymousNamespaceCheck.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::llvm_check {
+
+namespace {
+
+AST_MATCHER(NamedDecl, isInMacro) {
+ return Node.getBeginLoc().isMacroID() || Node.getEndLoc().isMacroID();
+}
+
+AST_MATCHER(VarDecl, isLocalVariable) { return Node.isLocalVarDecl(); }
+
+} // namespace
+
+PreferStaticOverAnonymousNamespaceCheck::
+ PreferStaticOverAnonymousNamespaceCheck(StringRef Name,
+ ClangTidyContext *Context)
+ : ClangTidyCheck(Name, Context),
+ AllowVariableDeclarations(Options.get("AllowVariableDeclarations", true)),
+ AllowMemberFunctionsInClass(
+ Options.get("AllowMemberFunctionsInClass", true)) {}
+
+void PreferStaticOverAnonymousNamespaceCheck::storeOptions(
+ ClangTidyOptions::OptionMap &Opts) {
+ Options.store(Opts, "AllowVariableDeclarations", AllowVariableDeclarations);
+ Options.store(Opts, "AllowMemberFunctionsInClass",
+ AllowMemberFunctionsInClass);
+}
+
+void PreferStaticOverAnonymousNamespaceCheck::registerMatchers(
+ MatchFinder *Finder) {
+ const auto IsDefinitionInAnonymousNamespace =
+ allOf(unless(isExpansionInSystemHeader()), isInAnonymousNamespace(),
+ unless(isInMacro()), isDefinition());
+
+ if (AllowMemberFunctionsInClass) {
+ Finder->addMatcher(functionDecl(IsDefinitionInAnonymousNamespace,
+ unless(hasParent(cxxRecordDecl())))
+ .bind("function"),
+ this);
+ } else
+ Finder->addMatcher(
+ functionDecl(IsDefinitionInAnonymousNamespace).bind("function"), this);
+
+ if (!AllowVariableDeclarations)
+ Finder->addMatcher(varDecl(IsDefinitionInAnonymousNamespace,
+ unless(isLocalVariable()), unless(parmVarDecl()))
+ .bind("var"),
+ this);
+}
+
+void PreferStaticOverAnonymousNamespaceCheck::check(
+ const MatchFinder::MatchResult &Result) {
+
+ if (const auto *Func = Result.Nodes.getNodeAs<FunctionDecl>("function")) {
+ if (Func->isCXXClassMember())
+ diag(Func->getLocation(),
+ "place definition of method %0 outside of an anonymous namespace")
+ << Func;
+ else if (Func->isStatic())
+ diag(Func->getLocation(),
+ "place static function %0 outside of an anonymous namespace")
+ << Func;
+ else
+ diag(Func->getLocation(),
+ "function %0 is declared in an anonymous namespace; "
+ "prefer using 'static' for restricting visibility")
+ << Func;
+ return;
+ }
+
+ if (const auto *Var = Result.Nodes.getNodeAs<VarDecl>("var")) {
+ if (Var->getStorageClass() == SC_Static)
+ diag(Var->getLocation(),
+ "place static variable %0 outside of an anonymous namespace")
+ << Var;
+ else
+ diag(Var->getLocation(),
+ "variable %0 is declared in an anonymous namespace; "
+ "prefer using 'static' for restricting visibility")
+ << Var;
+ }
+}
+
+} // namespace clang::tidy::llvm_check
diff --git a/clang-tools-extra/clang-tidy/llvm/PreferStaticOverAnonymousNamespaceCheck.h b/clang-tools-extra/clang-tidy/llvm/PreferStaticOverAnonymousNamespaceCheck.h
new file mode 100644
index 0000000000000..ca0245e1d3031
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/llvm/PreferStaticOverAnonymousNamespaceCheck.h
@@ -0,0 +1,42 @@
+//===--- PreferStaticOverAnonymousNamespaceCheck.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_LLVM_PREFERSTATICOVERANONYMOUSNAMESPACECHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_LLVM_PREFERSTATICOVERANONYMOUSNAMESPACECHECK_H
+
+#include "../ClangTidyCheck.h"
+
+namespace clang::tidy::llvm_check {
+
+/// Finds function and variable declarations inside anonymous namespace and
+/// suggests replacing them with ``static`` declarations.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/llvm/prefer-static-over-anonymous-namespace.html
+class PreferStaticOverAnonymousNamespaceCheck : public ClangTidyCheck {
+public:
+ PreferStaticOverAnonymousNamespaceCheck(StringRef Name,
+ ClangTidyContext *Context);
+ void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+ void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+ void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
+ bool isLanguageVersionSupported(const LangOptions &LangOpts) const override {
+ return LangOpts.CPlusPlus;
+ }
+ std::optional<TraversalKind> getCheckTraversalKind() const override {
+ return TK_IgnoreUnlessSpelledInSource;
+ }
+
+private:
+ const bool AllowVariableDeclarations;
+ const bool AllowMemberFunctionsInClass;
+};
+
+} // namespace clang::tidy::llvm_check
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_LLVM_PREFERSTATICOVERANONYMOUSNAMESPACECHECK_H
diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst
index e0f81a032c38d..17142b5a0eaec 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -136,6 +136,12 @@ New checks
Finds unintended character output from ``unsigned char`` and ``signed char``
to an ``ostream``.
+- New :doc:`llvm-prefer-static-over-anonymous-namespace
+ <clang-tidy/checks/llvm/prefer-static-over-anonymous-namespace>` check.
+
+ Finds function and variable declarations inside anonymous namespace and
+ suggests replacing them with ``static`` declarations.
+
- New :doc:`portability-avoid-pragma-once
<clang-tidy/checks/portability/avoid-pragma-once>` check.
diff --git a/clang-tools-extra/docs/clang-tidy/checks/list.rst b/clang-tools-extra/docs/clang-tidy/checks/list.rst
index 5a79d61b1fd7e..7f6564af08fff 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/list.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/list.rst
@@ -249,6 +249,7 @@ Clang-Tidy Checks
:doc:`llvm-namespace-comment <llvm/namespace-comment>`,
:doc:`llvm-prefer-isa-or-dyn-cast-in-conditionals <llvm/prefer-isa-or-dyn-cast-in-conditionals>`, "Yes"
:doc:`llvm-prefer-register-over-unsigned <llvm/prefer-register-over-unsigned>`, "Yes"
+ :doc:`llvm-prefer-static-over-anonymous-namespace <llvm/prefer-static-over-anonymous-namespace>`,
:doc:`llvm-twine-local <llvm/twine-local>`, "Yes"
:doc:`llvmlibc-callee-namespace <llvmlibc/callee-namespace>`,
:doc:`llvmlibc-implementation-in-namespace <llvmlibc/implementation-in-namespace>`,
diff --git a/clang-tools-extra/docs/clang-tidy/checks/llvm/prefer-static-over-anonymous-namespace.rst b/clang-tools-extra/docs/clang-tidy/checks/llvm/prefer-static-over-anonymous-namespace.rst
new file mode 100644
index 0000000000000..21ba161189548
--- /dev/null
+++ b/clang-tools-extra/docs/clang-tidy/checks/llvm/prefer-static-over-anonymous-namespace.rst
@@ -0,0 +1,73 @@
+.. title:: clang-tidy - llvm-prefer-static-over-anonymous-namespace
+
+llvm-prefer-static-over-anonymous-namespace
+===========================================
+
+Finds function and variable declarations inside anonymous namespace and
+suggests replacing them with ``static`` declarations.
+
+The `LLVM Coding Standards <https://llvm.org/docs/CodingStandards.html#restrict-visibility>`_
+recommend keeping anonymous namespaces as small as possible and only use them
+for class declarations. For functions and variables, ``static`` specifier
+should be preferred for restricting visibility.
+
+For example non-compliant code:
+
+.. code-block:: c++
+
+ namespace {
+
+ class StringSort {
+ public:
+ StringSort(...)
+ bool operator<(const char *RHS) const;
+ };
+
+ // warning: place method definition outside of an anonymous namespace
+ bool StringSort::operator<(const char *RHS) const {}
+
+ // warning: prefer using 'static' for restricting visibility
+ void runHelper() {}
+
+ // warning: prefer using 'static' for restricting visibility
+ int myVariable = 42;
+
+ }
+
+Should become:
+
+.. code-block:: c++
+
+ // Small anonymous namespace for class declaration
+ namespace {
+
+ class StringSort {
+ public:
+ StringSort(...)
+ bool operator<(const char *RHS) const;
+ };
+
+ }
+
+ // placed method definition outside of the anonymous namespace
+ bool StringSort::operator<(const char *RHS) const {}
+
+ // used 'static' instead of an anonymous namespace
+ static void runHelper() {}
+
+ // used 'static' instead of an anonymous namespace
+ static int myVariable = 42;
+
+
+Options
+-------
+
+.. option:: AllowVariableDeclarations
+
+ When `true`, allow variable declarations to be in anonymous namespace.
+ Default value is `true`.
+
+.. option:: AllowMemberFunctionsInClass
+
+ When `true`, only methods defined in anonymous namespace outside of the
+ corresponding class will be warned. Default value is `true`.
\ No newline at end of file
diff --git a/clang-tools-extra/test/clang-tidy/checkers/llvm/prefer-static-over-anonymous-namespace-allow-member-functions.cpp b/clang-tools-extra/test/clang-tidy/checkers/llvm/prefer-static-over-anonymous-namespace-allow-member-functions.cpp
new file mode 100644
index 0000000000000..d31f56c603631
--- /dev/null
+++ b/clang-tools-extra/test/clang-tidy/checkers/llvm/prefer-static-over-anonymous-namespace-allow-member-functions.cpp
@@ -0,0 +1,65 @@
+// RUN: %check_clang_tidy %s llvm-prefer-static-over-anonymous-namespace %t -- \
+// RUN: -config="{CheckOptions: { \
+// RUN: llvm-prefer-static-over-anonymous-namespace.AllowMemberFunctionsInClass: false }, \
+// RUN: }" -- -fno-delayed-template-parsing
+
+namespace {
+
+class MyClass {
+public:
+ MyClass() {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: place definition of method 'MyClass' outside of an anonymous namespace
+ MyClass(const MyClass&) = default;
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: place definition of method 'MyClass' outside of an anonymous namespace
+ MyClass& operator=(const MyClass&) = default;
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: place definition of method 'operator=' outside of an anonymous namespace
+ MyClass& operator=(MyClass&&) { return *this; };
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: place definition of method 'operator=' outside of an anonymous namespace
+ bool operator<(const MyClass&) const { return true; };
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: place definition of method 'operator<' outside of an anonymous namespace
+ void memberFunction();
+ void memberDefinedInClass() {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: place definition of method 'memberDefinedInClass' outside of an anonymous namespace
+};
+
+void MyClass::memberFunction() {}
+// CHECK-MESSAGES: :[[@LINE-1]]:15: warning: place definition of method 'memberFunction' outside of an anonymous namespace
+
+template<typename T>
+class TemplateClass {
+public:
+ TemplateClass() {};
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: place definition of method 'TemplateClass<T>' outside of an anonymous namespace
+ TemplateClass(const TemplateClass&) = default;
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: place definition of method 'TemplateClass<T>' outside of an anonymous namespace
+ TemplateClass& operator=(const TemplateClass&) = default;
+ // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: place definition of method 'operator=' outside of an anonymous namespace
+ TemplateClass& operator=(TemplateClass&&) { return *this; };
+ // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: place definition of method 'operator=' outside of an anonymous namespace
+ bool operator<(const TemplateClass&) const { return true; };
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: place definition of method 'operator<' outside of an anonymous namespace
+ void memberFunc();
+ T getValue() const { return {}; };
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: place definition of method 'getValue' outside of an anonymous namespace
+ void memberDefinedInClass() {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: place definition of method 'memberDefinedInClass' outside of an anonymous namespace
+};
+
+template<typename T>
+void TemplateClass<T>::memberFunc() {}
+// CHECK-MESSAGES: :[[@LINE-1]]:24: warning: place definition of method 'memberFunc' outside of an anonymous namespace
+
+class OuterClass {
+public:
+ class NestedClass {
+ public:
+ void nestedMemberFunc();
+ void nestedMemberDefinedInClass() {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: place definition of method 'nestedMemberDefinedInClass' outside of an anonymous namespace
+ };
+};
+
+void OuterClass::NestedClass::nestedMemberFunc() {}
+// CHECK-MESSAGES: :[[@LINE-1]]:31: warning: place definition of method 'nestedMemberFunc' outside of an anonymous namespace
+
+} // namespace
diff --git a/clang-tools-extra/test/clang-tidy/checkers/llvm/prefer-static-over-anonymous-namespace-allow-variables.cpp b/clang-tools-extra/test/clang-tidy/checkers/llvm/prefer-static-over-anonymous-namespace-allow-variables.cpp
new file mode 100644
index 0000000000000..7efd872bcf352
--- /dev/null
+++ b/clang-tools-extra/test/clang-tidy/checkers/llvm/prefer-static-over-anonymous-namespace-allow-variables.cpp
@@ -0,0 +1,60 @@
+// RUN: %check_clang_tidy %s llvm-prefer-static-over-anonymous-namespace %t -- \
+// RUN: -config="{CheckOptions: { \
+// RUN: llvm-prefer-static-over-anonymous-namespace.AllowVariableDeclarations: false }, \
+// RUN: }" -- -fno-delayed-template-parsing
+
+namespace {
+
+void regularFunction(int param) {
+// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: function 'regularFunction' is declared in an anonymous namespace;
+
+ int Variable = 42;
+ auto Lambda = []() { return 42; };
+ static int StaticVariable = 42;
+}
+
+int globalVariable = 42;
+// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: variable 'globalVariable' is declared in an anonymous namespace;
+
+static int staticVariable = 42;
+// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: place static variable 'staticVariable' outside of an anonymous namespace
+
+typedef int MyInt;
+const MyInt myGlobalVariable = 42;
+// CHECK-MESSAGES: :[[@LINE-1]]:13: warning: variable 'myGlobalVariable' is declared in an anonymous namespace;
+
+template<typename T>
+constexpr T Pi = T(3.1415926);
+// CHECK-MESSAGES: :[[@LINE-1]]:13: warning: variable 'Pi' is declared in an anonymous namespace;
+
+void (*funcPtr)() = nullptr;
+// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: variable 'funcPtr' is declared in an anonymous namespace;
+
+auto lambda = []() { return 42; };
+// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: variable 'lambda' is declared in an anonymous namespace;
+
+class MyClass {
+ int member;
+};
+
+MyClass instance;
+// CHECK-MESSAGES: :[[@LINE-1]]:9: warning: variable 'instance' is declared in an anonymous namespace;
+
+MyClass* instancePtr = nullptr;
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: variable 'instancePtr' is declared in an anonymous namespace;
+
+MyClass& instanceRef = instance;
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: variable 'instanceRef' is declared in an anonymous namespace;
+
+class OtherClass{
+ void method() {
+ MyClass instance;
+ MyClass* instancePtr = nullptr;
+ MyClass& instanceRef = instance;
+ }
+ MyClass member;
+ MyClass* memberPtr = nullptr;
+ MyClass& memberRef = member;
+};
+
+} // namespace
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
new file mode 100644
index 0000000000000..2dfa82717b5f7
--- /dev/null
+++ b/clang-tools-extra/test/clang-tidy/checkers/llvm/prefer-static-over-anonymous-namespace.cpp
@@ -0,0 +1,146 @@
+// RUN: %check_clang_tidy %s llvm-prefer-static-over-anonymous-namespace %t -- -- -fno-delayed-template-parsing
+
+namespace {
+
+void regularFunction() {}
+// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: function 'regularFunction' is declared in an anonymous namespace; prefer using 'static' for restricting visibility [llvm-prefer-static-over-anonymous-namespace]
+
+void declaredFunction();
+
+static void staticFunction() {}
+// CHECK-MESSAGES: :[[@LINE-1]]:13: warning: place static function 'staticFunction' outside of an anonymous namespace
+
+int globalVariable = 42;
+
+static int staticVariable = 42;
+
+class MyClass {
+public:
+ MyClass();
+ MyClass(const MyClass&) {}
+ MyClass(MyClass&&) = default;
+ MyClass& operator=(const MyClass&);
+ MyClass& operator=(MyClass&&);
+ bool operator<(const MyClass&) const;
+ void memberFunction();
+ static void staticMemberFunction();
+ void memberDefinedInClass() {}
+ static void staticMemberDefinedInClass() {}
+};
+
+MyClass::MyClass() {}
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: place definition of method 'MyClass' outside of an anonymous namespace
+
+MyClass& MyClass::operator=(const MyClass&) { return *this; }
+// CHECK-MESSAGES: :[[@LINE-1]]:19: warning: place definition of method 'operator=' outside of an anonymous namespace
+
+MyClass& MyClass::operator=(MyClass&&) = default;
+// CHECK-MESSAGES: :[[@LINE-1]]:19: warning: place definition of method 'operator=' outside of an anonymous namespace
+
+bool MyClass::operator<(const MyClass&) const { return true; }
+// CHECK-MESSAGES: :[[@LINE-1]]:15: warning: place definition of method 'operator<' outside of an anonymous namespace
+
+void MyClass::memberFunction() {}
+// CHECK-MESSAGES: :[[@LINE-1]]:15: warning: place definition of method 'memberFunction' outside of an anonymous namespace
+
+void MyClass::staticMemberFunction() {}
+// CHECK-MESSAGES: :[[@LINE-1]]:15: warning: place definition of method 'staticMemberFunction' outside of an anonymous namespace
+
+template<typename ...
[truncated]
|
@AaronBallman, may you give some feedback on how good/bad this check would play on LLVM project in general. |
I think that having such a check is a reasonable idea, but yeah, I doubt we could turn it on in CI without limiting to just new code. But it would be a handy tool when writing new code, so I think it's probably worth it. |
Finds function and variable declarations inside anonymous namespace and suggests replacing them with
static
declarations.The check will enforce that restrict-visibility rule in LLVM Coding Standards is followed correctly (by adding
static
to functions instead of putting them in anonimous namespace).The check has additional levels of "strictness" represented by Options.
By default, the check works in the most relaxed way by giving warning only for methods and functions defined in anonymous namespaces. Also, It finds
static
functions that are placed inside anonymous namespace - there is no point in keeping them inside.