UseAnonymousNamespaceCheck.cpp 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475
  1. //===--- UseAnonymousNamespaceCheck.cpp - clang-tidy ----------------------===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. #include "UseAnonymousNamespaceCheck.h"
  9. #include "clang/AST/ASTContext.h"
  10. #include "clang/ASTMatchers/ASTMatchFinder.h"
  11. using namespace clang::ast_matchers;
  12. namespace clang::tidy::misc {
  13. namespace {
  14. AST_POLYMORPHIC_MATCHER_P(isInHeaderFile,
  15. AST_POLYMORPHIC_SUPPORTED_TYPES(FunctionDecl,
  16. VarDecl),
  17. utils::FileExtensionsSet, HeaderFileExtensions) {
  18. return utils::isExpansionLocInHeaderFile(
  19. Node.getBeginLoc(), Finder->getASTContext().getSourceManager(),
  20. HeaderFileExtensions);
  21. }
  22. AST_MATCHER(FunctionDecl, isMemberFunction) {
  23. return llvm::isa<CXXMethodDecl>(&Node);
  24. }
  25. AST_MATCHER(VarDecl, isStaticDataMember) { return Node.isStaticDataMember(); }
  26. } // namespace
  27. UseAnonymousNamespaceCheck::UseAnonymousNamespaceCheck(
  28. StringRef Name, ClangTidyContext *Context)
  29. : ClangTidyCheck(Name, Context),
  30. RawStringHeaderFileExtensions(Options.getLocalOrGlobal(
  31. "HeaderFileExtensions", utils::defaultHeaderFileExtensions())) {
  32. if (!utils::parseFileExtensions(RawStringHeaderFileExtensions,
  33. HeaderFileExtensions,
  34. utils::defaultFileExtensionDelimiters())) {
  35. this->configurationDiag("Invalid header file extension: '%0'")
  36. << RawStringHeaderFileExtensions;
  37. }
  38. }
  39. void UseAnonymousNamespaceCheck::storeOptions(
  40. ClangTidyOptions::OptionMap &Opts) {
  41. Options.store(Opts, "HeaderFileExtensions", RawStringHeaderFileExtensions);
  42. }
  43. void UseAnonymousNamespaceCheck::registerMatchers(MatchFinder *Finder) {
  44. Finder->addMatcher(
  45. functionDecl(isStaticStorageClass(),
  46. unless(anyOf(isInHeaderFile(HeaderFileExtensions),
  47. isInAnonymousNamespace(), isMemberFunction())))
  48. .bind("x"),
  49. this);
  50. Finder->addMatcher(
  51. varDecl(isStaticStorageClass(),
  52. unless(anyOf(isInHeaderFile(HeaderFileExtensions),
  53. isInAnonymousNamespace(), isStaticLocal(),
  54. isStaticDataMember(), hasType(isConstQualified()))))
  55. .bind("x"),
  56. this);
  57. }
  58. void UseAnonymousNamespaceCheck::check(const MatchFinder::MatchResult &Result) {
  59. if (const auto *MatchedDecl = Result.Nodes.getNodeAs<NamedDecl>("x")) {
  60. StringRef Type = llvm::isa<VarDecl>(MatchedDecl) ? "variable" : "function";
  61. diag(MatchedDecl->getLocation(),
  62. "%0 %1 declared 'static', move to anonymous namespace instead")
  63. << Type << MatchedDecl;
  64. }
  65. }
  66. } // namespace clang::tidy::misc