1 //===--- Matchers.h - clang-tidy-------------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_UTILS_MATCHERS_H
10 #define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_UTILS_MATCHERS_H
12 #include "TypeTraits.h"
13 #include "clang/AST/ExprConcepts.h"
14 #include "clang/ASTMatchers/ASTMatchers.h"
17 namespace clang::tidy::matchers
{
19 AST_MATCHER(BinaryOperator
, isRelationalOperator
) {
20 return Node
.isRelationalOp();
23 AST_MATCHER(BinaryOperator
, isEqualityOperator
) { return Node
.isEqualityOp(); }
25 AST_MATCHER(QualType
, isExpensiveToCopy
) {
26 std::optional
<bool> IsExpensive
=
27 utils::type_traits::isExpensiveToCopy(Node
, Finder
->getASTContext());
28 return IsExpensive
&& *IsExpensive
;
31 AST_MATCHER(RecordDecl
, isTriviallyDefaultConstructible
) {
32 return utils::type_traits::recordIsTriviallyDefaultConstructible(
33 Node
, Finder
->getASTContext());
36 AST_MATCHER(QualType
, isTriviallyDestructible
) {
37 return utils::type_traits::isTriviallyDestructible(Node
);
40 // Returns QualType matcher for references to const.
41 AST_MATCHER_FUNCTION(ast_matchers::TypeMatcher
, isReferenceToConst
) {
42 using namespace ast_matchers
;
43 return referenceType(pointee(qualType(isConstQualified())));
46 // Returns QualType matcher for pointers to const.
47 AST_MATCHER_FUNCTION(ast_matchers::TypeMatcher
, isPointerToConst
) {
48 using namespace ast_matchers
;
49 return pointerType(pointee(qualType(isConstQualified())));
52 AST_MATCHER(Expr
, hasUnevaluatedContext
) {
53 if (isa
<CXXNoexceptExpr
>(Node
) || isa
<RequiresExpr
>(Node
))
55 if (const auto *UnaryExpr
= dyn_cast
<UnaryExprOrTypeTraitExpr
>(&Node
)) {
56 switch (UnaryExpr
->getKind()) {
64 if (const auto *TypeIDExpr
= dyn_cast
<CXXTypeidExpr
>(&Node
))
65 return !TypeIDExpr
->isPotentiallyEvaluated();
69 // A matcher implementation that matches a list of type name regular expressions
70 // against a NamedDecl. If a regular expression contains the substring "::"
71 // matching will occur against the qualified name, otherwise only the typename.
72 class MatchesAnyListedNameMatcher
73 : public ast_matchers::internal::MatcherInterface
<NamedDecl
> {
75 explicit MatchesAnyListedNameMatcher(llvm::ArrayRef
<StringRef
> NameList
) {
77 NameList
.begin(), NameList
.end(), std::back_inserter(NameMatchers
),
78 [](const llvm::StringRef Name
) { return NameMatcher(Name
); });
81 const NamedDecl
&Node
, ast_matchers::internal::ASTMatchFinder
*Finder
,
82 ast_matchers::internal::BoundNodesTreeBuilder
*Builder
) const override
{
83 return llvm::any_of(NameMatchers
, [&Node
](const NameMatcher
&NM
) {
84 return NM
.match(Node
);
91 enum class MatchMode
{
92 // Match against the unqualified name because the regular expression
93 // does not contain ":".
95 // Match against the qualified name because the regular expression
96 // contains ":" suggesting name and namespace should be matched.
98 // Match against the fully qualified name because the regular expression
105 NameMatcher(const llvm::StringRef Regex
)
106 : Regex(Regex
), Mode(determineMatchMode(Regex
)) {}
108 bool match(const NamedDecl
&ND
) const {
110 case MatchMode::MatchQualified
:
111 return Regex
.match(ND
.getQualifiedNameAsString());
112 case MatchMode::MatchFullyQualified
:
113 return Regex
.match("::" + ND
.getQualifiedNameAsString());
115 if (const IdentifierInfo
*II
= ND
.getIdentifier())
116 return Regex
.match(II
->getName());
122 MatchMode
determineMatchMode(llvm::StringRef Regex
) {
123 if (Regex
.startswith(":") || Regex
.startswith("^:")) {
124 return MatchMode::MatchFullyQualified
;
126 return Regex
.contains(":") ? MatchMode::MatchQualified
127 : MatchMode::MatchUnqualified
;
131 std::vector
<NameMatcher
> NameMatchers
;
134 // Returns a matcher that matches NamedDecl's against a list of provided regular
135 // expressions. If a regular expression contains starts ':' the NamedDecl's
136 // qualified name will be used for matching, otherwise its name will be used.
137 inline ::clang::ast_matchers::internal::Matcher
<NamedDecl
>
138 matchesAnyListedName(llvm::ArrayRef
<StringRef
> NameList
) {
139 return ::clang::ast_matchers::internal::makeMatcher(
140 new MatchesAnyListedNameMatcher(NameList
));
143 } // namespace clang::tidy::matchers
145 #endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_UTILS_MATCHERS_H