Matchers.h 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. //===--- Matchers.h - 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. #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_UTILS_MATCHERS_H
  9. #define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_UTILS_MATCHERS_H
  10. #include "TypeTraits.h"
  11. #include "clang/ASTMatchers/ASTMatchers.h"
  12. #include <optional>
  13. namespace clang::tidy::matchers {
  14. AST_MATCHER(BinaryOperator, isRelationalOperator) {
  15. return Node.isRelationalOp();
  16. }
  17. AST_MATCHER(BinaryOperator, isEqualityOperator) { return Node.isEqualityOp(); }
  18. AST_MATCHER(QualType, isExpensiveToCopy) {
  19. std::optional<bool> IsExpensive =
  20. utils::type_traits::isExpensiveToCopy(Node, Finder->getASTContext());
  21. return IsExpensive && *IsExpensive;
  22. }
  23. AST_MATCHER(RecordDecl, isTriviallyDefaultConstructible) {
  24. return utils::type_traits::recordIsTriviallyDefaultConstructible(
  25. Node, Finder->getASTContext());
  26. }
  27. AST_MATCHER(QualType, isTriviallyDestructible) {
  28. return utils::type_traits::isTriviallyDestructible(Node);
  29. }
  30. // Returns QualType matcher for references to const.
  31. AST_MATCHER_FUNCTION(ast_matchers::TypeMatcher, isReferenceToConst) {
  32. using namespace ast_matchers;
  33. return referenceType(pointee(qualType(isConstQualified())));
  34. }
  35. // Returns QualType matcher for pointers to const.
  36. AST_MATCHER_FUNCTION(ast_matchers::TypeMatcher, isPointerToConst) {
  37. using namespace ast_matchers;
  38. return pointerType(pointee(qualType(isConstQualified())));
  39. }
  40. // A matcher implementation that matches a list of type name regular expressions
  41. // against a NamedDecl. If a regular expression contains the substring "::"
  42. // matching will occur against the qualified name, otherwise only the typename.
  43. class MatchesAnyListedNameMatcher
  44. : public ast_matchers::internal::MatcherInterface<NamedDecl> {
  45. public:
  46. explicit MatchesAnyListedNameMatcher(llvm::ArrayRef<StringRef> NameList) {
  47. std::transform(
  48. NameList.begin(), NameList.end(), std::back_inserter(NameMatchers),
  49. [](const llvm::StringRef Name) { return NameMatcher(Name); });
  50. }
  51. bool matches(
  52. const NamedDecl &Node, ast_matchers::internal::ASTMatchFinder *Finder,
  53. ast_matchers::internal::BoundNodesTreeBuilder *Builder) const override {
  54. return llvm::any_of(NameMatchers, [&Node](const NameMatcher &NM) {
  55. return NM.match(Node);
  56. });
  57. }
  58. private:
  59. class NameMatcher {
  60. llvm::Regex Regex;
  61. enum class MatchMode {
  62. // Match against the unqualified name because the regular expression
  63. // does not contain ":".
  64. MatchUnqualified,
  65. // Match against the qualified name because the regular expression
  66. // contains ":" suggesting name and namespace should be matched.
  67. MatchQualified,
  68. // Match against the fully qualified name because the regular expression
  69. // starts with ":".
  70. MatchFullyQualified,
  71. };
  72. MatchMode Mode;
  73. public:
  74. NameMatcher(const llvm::StringRef Regex)
  75. : Regex(Regex), Mode(determineMatchMode(Regex)) {}
  76. bool match(const NamedDecl &ND) const {
  77. switch (Mode) {
  78. case MatchMode::MatchQualified:
  79. return Regex.match(ND.getQualifiedNameAsString());
  80. case MatchMode::MatchFullyQualified:
  81. return Regex.match("::" + ND.getQualifiedNameAsString());
  82. default:
  83. return Regex.match(ND.getName());
  84. }
  85. }
  86. private:
  87. MatchMode determineMatchMode(llvm::StringRef Regex) {
  88. if (Regex.startswith(":") || Regex.startswith("^:")) {
  89. return MatchMode::MatchFullyQualified;
  90. }
  91. return Regex.contains(":") ? MatchMode::MatchQualified
  92. : MatchMode::MatchUnqualified;
  93. }
  94. };
  95. std::vector<NameMatcher> NameMatchers;
  96. };
  97. // Returns a matcher that matches NamedDecl's against a list of provided regular
  98. // expressions. If a regular expression contains starts ':' the NamedDecl's
  99. // qualified name will be used for matching, otherwise its name will be used.
  100. inline ::clang::ast_matchers::internal::Matcher<NamedDecl>
  101. matchesAnyListedName(llvm::ArrayRef<StringRef> NameList) {
  102. return ::clang::ast_matchers::internal::makeMatcher(
  103. new MatchesAnyListedNameMatcher(NameList));
  104. }
  105. } // namespace clang::tidy::matchers
  106. #endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_UTILS_MATCHERS_H