aboutsummaryrefslogtreecommitdiff
path: root/clang-tools-extra/clang-tidy/misc/UseAnonymousNamespaceCheck.cpp
diff options
context:
space:
mode:
authorCarlos Galvez <carlosgalvezp@gmail.com>2022-11-03 11:04:10 +0000
committerCarlos Galvez <carlosgalvezp@gmail.com>2022-12-01 07:19:30 +0000
commit65d6d67fc9a9aa818d3ae41bd52bd9f64b95c06e (patch)
tree0da66b9724fc66d4a2d84893a38d794f7e9fa596 /clang-tools-extra/clang-tidy/misc/UseAnonymousNamespaceCheck.cpp
parentdf43ec30ab66f5af7bbf87e121e0fe26aad478b4 (diff)
downloadllvm-65d6d67fc9a9aa818d3ae41bd52bd9f64b95c06e.zip
llvm-65d6d67fc9a9aa818d3ae41bd52bd9f64b95c06e.tar.gz
llvm-65d6d67fc9a9aa818d3ae41bd52bd9f64b95c06e.tar.bz2
[clang-tidy] Add misc-use-anonymous-namespace check
Differential Revision: https://reviews.llvm.org/D137340
Diffstat (limited to 'clang-tools-extra/clang-tidy/misc/UseAnonymousNamespaceCheck.cpp')
-rw-r--r--clang-tools-extra/clang-tidy/misc/UseAnonymousNamespaceCheck.cpp72
1 files changed, 72 insertions, 0 deletions
diff --git a/clang-tools-extra/clang-tidy/misc/UseAnonymousNamespaceCheck.cpp b/clang-tools-extra/clang-tidy/misc/UseAnonymousNamespaceCheck.cpp
new file mode 100644
index 0000000..5632347
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/misc/UseAnonymousNamespaceCheck.cpp
@@ -0,0 +1,72 @@
+//===--- UseAnonymousNamespaceCheck.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 "UseAnonymousNamespaceCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace misc {
+namespace {
+AST_POLYMORPHIC_MATCHER(isStatic, AST_POLYMORPHIC_SUPPORTED_TYPES(FunctionDecl,
+ VarDecl)) {
+ return Node.getStorageClass() == SC_Static;
+}
+
+AST_MATCHER(FunctionDecl, isMemberFunction) {
+ return llvm::isa<CXXMethodDecl>(&Node);
+}
+AST_MATCHER(VarDecl, isStaticDataMember) { return Node.isStaticDataMember(); }
+} // namespace
+
+static bool isInAnonymousNamespace(const Decl *Decl) {
+ const DeclContext *DC = Decl->getDeclContext();
+ if (DC && DC->isNamespace()) {
+ const auto *ND = llvm::cast<NamespaceDecl>(DC);
+ if (ND && ND->isAnonymousNamespace())
+ return true;
+ }
+ return false;
+}
+
+template <typename T>
+void UseAnonymousNamespaceCheck::processMatch(const T *MatchedDecl) {
+ StringRef Type = llvm::isa<VarDecl>(MatchedDecl) ? "variable" : "function";
+ if (isInAnonymousNamespace(MatchedDecl))
+ diag(MatchedDecl->getLocation(), "%0 %1 declared 'static' in "
+ "anonymous namespace, remove 'static'")
+ << Type << MatchedDecl;
+ else
+ diag(MatchedDecl->getLocation(),
+ "%0 %1 declared 'static', move to anonymous namespace instead")
+ << Type << MatchedDecl;
+}
+
+void UseAnonymousNamespaceCheck::registerMatchers(MatchFinder *Finder) {
+ Finder->addMatcher(
+ functionDecl(isStatic(), unless(isMemberFunction())).bind("func"), this);
+ Finder->addMatcher(
+ varDecl(isStatic(), unless(anyOf(isStaticLocal(), isStaticDataMember())))
+ .bind("var"),
+ this);
+}
+
+void UseAnonymousNamespaceCheck::check(const MatchFinder::MatchResult &Result) {
+ if (const auto *MatchedDecl = Result.Nodes.getNodeAs<FunctionDecl>("func"))
+ processMatch(MatchedDecl);
+
+ if (const auto *MatchedDecl = Result.Nodes.getNodeAs<VarDecl>("var"))
+ processMatch(MatchedDecl);
+}
+
+} // namespace misc
+} // namespace tidy
+} // namespace clang