diff options
author | Carlos Galvez <carlosgalvezp@gmail.com> | 2022-11-03 11:04:10 +0000 |
---|---|---|
committer | Carlos Galvez <carlosgalvezp@gmail.com> | 2022-12-01 07:19:30 +0000 |
commit | 65d6d67fc9a9aa818d3ae41bd52bd9f64b95c06e (patch) | |
tree | 0da66b9724fc66d4a2d84893a38d794f7e9fa596 /clang-tools-extra/clang-tidy/misc/UseAnonymousNamespaceCheck.cpp | |
parent | df43ec30ab66f5af7bbf87e121e0fe26aad478b4 (diff) | |
download | llvm-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.cpp | 72 |
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 |