|  | //===--- Matchers.h - 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 | 
|  | // | 
|  | //===----------------------------------------------------------------------===// | 
|  |  | 
|  | #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_UTILS_MATCHERS_H | 
|  | #define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_UTILS_MATCHERS_H | 
|  |  | 
|  | #include "TypeTraits.h" | 
|  | #include "clang/ASTMatchers/ASTMatchers.h" | 
|  |  | 
|  | namespace clang { | 
|  | namespace tidy { | 
|  | namespace matchers { | 
|  |  | 
|  | AST_MATCHER(BinaryOperator, isRelationalOperator) { | 
|  | return Node.isRelationalOp(); | 
|  | } | 
|  |  | 
|  | AST_MATCHER(BinaryOperator, isEqualityOperator) { return Node.isEqualityOp(); } | 
|  |  | 
|  | AST_MATCHER(QualType, isExpensiveToCopy) { | 
|  | llvm::Optional<bool> IsExpensive = | 
|  | utils::type_traits::isExpensiveToCopy(Node, Finder->getASTContext()); | 
|  | return IsExpensive && *IsExpensive; | 
|  | } | 
|  |  | 
|  | AST_MATCHER(RecordDecl, isTriviallyDefaultConstructible) { | 
|  | return utils::type_traits::recordIsTriviallyDefaultConstructible( | 
|  | Node, Finder->getASTContext()); | 
|  | } | 
|  |  | 
|  | AST_MATCHER(QualType, isTriviallyDestructible) { | 
|  | return utils::type_traits::isTriviallyDestructible(Node); | 
|  | } | 
|  |  | 
|  | // Returns QualType matcher for references to const. | 
|  | AST_MATCHER_FUNCTION(ast_matchers::TypeMatcher, isReferenceToConst) { | 
|  | using namespace ast_matchers; | 
|  | return referenceType(pointee(qualType(isConstQualified()))); | 
|  | } | 
|  |  | 
|  | // Returns QualType matcher for pointers to const. | 
|  | AST_MATCHER_FUNCTION(ast_matchers::TypeMatcher, isPointerToConst) { | 
|  | using namespace ast_matchers; | 
|  | return pointerType(pointee(qualType(isConstQualified()))); | 
|  | } | 
|  |  | 
|  | // A matcher implementation that matches a list of type name regular expressions | 
|  | // against a NamedDecl. If a regular expression contains the substring "::" | 
|  | // matching will occur against the qualified name, otherwise only the typename. | 
|  | class MatchesAnyListedNameMatcher | 
|  | : public ast_matchers::internal::MatcherInterface<NamedDecl> { | 
|  | public: | 
|  | explicit MatchesAnyListedNameMatcher(llvm::ArrayRef<std::string> NameList) { | 
|  | std::transform( | 
|  | NameList.begin(), NameList.end(), std::back_inserter(NameMatchers), | 
|  | [](const llvm::StringRef Name) { return NameMatcher(Name); }); | 
|  | } | 
|  | bool matches( | 
|  | const NamedDecl &Node, ast_matchers::internal::ASTMatchFinder *Finder, | 
|  | ast_matchers::internal::BoundNodesTreeBuilder *Builder) const override { | 
|  | return llvm::any_of(NameMatchers, [&Node](const NameMatcher &NM) { | 
|  | return NM.match(Node); | 
|  | }); | 
|  | } | 
|  |  | 
|  | private: | 
|  | class NameMatcher { | 
|  | llvm::Regex Regex; | 
|  | enum class MatchMode { | 
|  | // Match against the unqualified name because the regular expression | 
|  | // does not contain ":". | 
|  | MatchUnqualified, | 
|  | // Match against the qualified name because the regular expression | 
|  | // contains ":" suggesting name and namespace should be matched. | 
|  | MatchQualified, | 
|  | // Match against the fully qualified name because the regular expression | 
|  | // starts with ":". | 
|  | MatchFullyQualified, | 
|  | }; | 
|  | MatchMode Mode; | 
|  |  | 
|  | public: | 
|  | NameMatcher(const llvm::StringRef Regex) | 
|  | : Regex(Regex), Mode(determineMatchMode(Regex)) {} | 
|  |  | 
|  | bool match(const NamedDecl &ND) const { | 
|  | switch (Mode) { | 
|  | case MatchMode::MatchQualified: | 
|  | return Regex.match(ND.getQualifiedNameAsString()); | 
|  | case MatchMode::MatchFullyQualified: | 
|  | return Regex.match("::" + ND.getQualifiedNameAsString()); | 
|  | default: | 
|  | return Regex.match(ND.getName()); | 
|  | } | 
|  | } | 
|  |  | 
|  | private: | 
|  | MatchMode determineMatchMode(llvm::StringRef Regex) { | 
|  | if (Regex.startswith(":") || Regex.startswith("^:")) { | 
|  | return MatchMode::MatchFullyQualified; | 
|  | } | 
|  | return Regex.contains(":") ? MatchMode::MatchQualified | 
|  | : MatchMode::MatchUnqualified; | 
|  | } | 
|  | }; | 
|  |  | 
|  | std::vector<NameMatcher> NameMatchers; | 
|  | }; | 
|  |  | 
|  | // Returns a matcher that matches NamedDecl's against a list of provided regular | 
|  | // expressions. If a regular expression contains starts ':' the NamedDecl's | 
|  | // qualified name will be used for matching, otherwise its name will be used. | 
|  | inline ::clang::ast_matchers::internal::Matcher<NamedDecl> | 
|  | matchesAnyListedName(llvm::ArrayRef<std::string> NameList) { | 
|  | return ::clang::ast_matchers::internal::makeMatcher( | 
|  | new MatchesAnyListedNameMatcher(NameList)); | 
|  | } | 
|  |  | 
|  | } // namespace matchers | 
|  | } // namespace tidy | 
|  | } // namespace clang | 
|  |  | 
|  | #endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_UTILS_MATCHERS_H |