clang-tools 20.0.0git
clang-tidy/utils/Matchers.h
Go to the documentation of this file.
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
9#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_UTILS_MATCHERS_H
10#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_UTILS_MATCHERS_H
11
12#include "TypeTraits.h"
13#include "clang/AST/ExprConcepts.h"
14#include "clang/ASTMatchers/ASTMatchers.h"
15#include <optional>
16
17namespace clang::tidy::matchers {
18
19AST_MATCHER(BinaryOperator, isRelationalOperator) {
20 return Node.isRelationalOp();
21}
22
23AST_MATCHER(BinaryOperator, isEqualityOperator) { return Node.isEqualityOp(); }
24
25AST_MATCHER(QualType, isExpensiveToCopy) {
26 std::optional<bool> IsExpensive =
27 utils::type_traits::isExpensiveToCopy(Node, Finder->getASTContext());
28 return IsExpensive && *IsExpensive;
29}
30
31AST_MATCHER(RecordDecl, isTriviallyDefaultConstructible) {
33 Node, Finder->getASTContext());
34}
35
36AST_MATCHER(QualType, isTriviallyDestructible) {
38}
39
40// Returns QualType matcher for references to const.
41AST_MATCHER_FUNCTION(ast_matchers::TypeMatcher, isReferenceToConst) {
42 using namespace ast_matchers;
43 return referenceType(pointee(qualType(isConstQualified())));
44}
45
46// Returns QualType matcher for pointers to const.
47AST_MATCHER_FUNCTION(ast_matchers::TypeMatcher, isPointerToConst) {
48 using namespace ast_matchers;
49 return pointerType(pointee(qualType(isConstQualified())));
50}
51
52// Returns QualType matcher for target char type only.
53AST_MATCHER(QualType, isSimpleChar) {
54 const auto ActualType = Node.getTypePtr();
55 return ActualType &&
56 (ActualType->isSpecificBuiltinType(BuiltinType::Char_S) ||
57 ActualType->isSpecificBuiltinType(BuiltinType::Char_U));
58}
59
60AST_MATCHER(Expr, hasUnevaluatedContext) {
61 if (isa<CXXNoexceptExpr>(Node) || isa<RequiresExpr>(Node))
62 return true;
63 if (const auto *UnaryExpr = dyn_cast<UnaryExprOrTypeTraitExpr>(&Node)) {
64 switch (UnaryExpr->getKind()) {
65 case UETT_SizeOf:
66 case UETT_AlignOf:
67 return true;
68 default:
69 return false;
70 }
71 }
72 if (const auto *TypeIDExpr = dyn_cast<CXXTypeidExpr>(&Node))
73 return !TypeIDExpr->isPotentiallyEvaluated();
74 return false;
75}
76
77// A matcher implementation that matches a list of type name regular expressions
78// against a NamedDecl. If a regular expression contains the substring "::"
79// matching will occur against the qualified name, otherwise only the typename.
82public:
83 explicit MatchesAnyListedNameMatcher(llvm::ArrayRef<StringRef> NameList) {
84 std::transform(
85 NameList.begin(), NameList.end(), std::back_inserter(NameMatchers),
86 [](const llvm::StringRef Name) { return NameMatcher(Name); });
87 }
88 bool matches(
89 const NamedDecl &Node, ast_matchers::internal::ASTMatchFinder *Finder,
90 ast_matchers::internal::BoundNodesTreeBuilder *Builder) const override {
91 return llvm::any_of(NameMatchers, [&Node](const NameMatcher &NM) {
92 return NM.match(Node);
93 });
94 }
95
96private:
97 class NameMatcher {
98 llvm::Regex Regex;
99 enum class MatchMode {
100 // Match against the unqualified name because the regular expression
101 // does not contain ":".
102 MatchUnqualified,
103 // Match against the qualified name because the regular expression
104 // contains ":" suggesting name and namespace should be matched.
105 MatchQualified,
106 // Match against the fully qualified name because the regular expression
107 // starts with ":".
108 MatchFullyQualified,
109 };
110 MatchMode Mode;
111
112 public:
113 NameMatcher(const llvm::StringRef Regex)
114 : Regex(Regex), Mode(determineMatchMode(Regex)) {}
115
116 bool match(const NamedDecl &ND) const {
117 switch (Mode) {
118 case MatchMode::MatchQualified:
119 return Regex.match(ND.getQualifiedNameAsString());
120 case MatchMode::MatchFullyQualified:
121 return Regex.match("::" + ND.getQualifiedNameAsString());
122 default:
123 if (const IdentifierInfo *II = ND.getIdentifier())
124 return Regex.match(II->getName());
125 return false;
126 }
127 }
128
129 private:
130 MatchMode determineMatchMode(llvm::StringRef Regex) {
131 if (Regex.starts_with(":") || Regex.starts_with("^:")) {
132 return MatchMode::MatchFullyQualified;
133 }
134 return Regex.contains(":") ? MatchMode::MatchQualified
135 : MatchMode::MatchUnqualified;
136 }
137 };
138
139 std::vector<NameMatcher> NameMatchers;
140};
141
142// Returns a matcher that matches NamedDecl's against a list of provided regular
143// expressions. If a regular expression contains starts ':' the NamedDecl's
144// qualified name will be used for matching, otherwise its name will be used.
145inline ::clang::ast_matchers::internal::Matcher<NamedDecl>
146matchesAnyListedName(llvm::ArrayRef<StringRef> NameList) {
147 return ::clang::ast_matchers::internal::makeMatcher(
148 new MatchesAnyListedNameMatcher(NameList));
149}
150
151// Predicate that verify if statement is not identical to one bound to ID node.
153 bool
154 operator()(const clang::ast_matchers::internal::BoundNodesMap &Nodes) const;
155
156 std::string ID;
157 ::clang::DynTypedNode Node;
158 ASTContext *Context;
159};
160
161// Checks if statement is identical (utils::areStatementsIdentical) to one bound
162// to ID node.
163AST_MATCHER_P(Stmt, isStatementIdenticalToBoundNode, std::string, ID) {
165 ID, ::clang::DynTypedNode::create(Node), &(Finder->getASTContext())};
166 return Builder->removeBindings(Predicate);
167}
168
169// A matcher implementation that matches a list of type name regular expressions
170// against a QualType.
173public:
174 explicit MatchesAnyListedTypeNameMatcher(llvm::ArrayRef<StringRef> NameList);
176 bool matches(
177 const QualType &Node, ast_matchers::internal::ASTMatchFinder *Finder,
178 ast_matchers::internal::BoundNodesTreeBuilder *Builder) const override;
179
180private:
181 std::vector<llvm::Regex> NameMatchers;
182};
183
184// Returns a matcher that matches QualType against a list of provided regular.
185inline ::clang::ast_matchers::internal::Matcher<QualType>
186matchesAnyListedTypeName(llvm::ArrayRef<StringRef> NameList) {
187 return ::clang::ast_matchers::internal::makeMatcher(
188 new MatchesAnyListedTypeNameMatcher(NameList));
189}
190
191} // namespace clang::tidy::matchers
192
193#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_UTILS_MATCHERS_H
llvm::SmallString< 256U > Name
CodeCompletionBuilder Builder
::clang::DynTypedNode Node
MatchesAnyListedNameMatcher(llvm::ArrayRef< StringRef > NameList)
bool matches(const NamedDecl &Node, ast_matchers::internal::ASTMatchFinder *Finder, ast_matchers::internal::BoundNodesTreeBuilder *Builder) const override
bool matches(const QualType &Node, ast_matchers::internal::ASTMatchFinder *Finder, ast_matchers::internal::BoundNodesTreeBuilder *Builder) const override
Definition: Matchers.cpp:26
AST_MATCHER_P(Stmt, isStatementIdenticalToBoundNode, std::string, ID)
AST_MATCHER(BinaryOperator, isRelationalOperator)
AST_MATCHER_FUNCTION(ast_matchers::TypeMatcher, isReferenceToConst)
inline ::clang::ast_matchers::internal::Matcher< NamedDecl > matchesAnyListedName(llvm::ArrayRef< StringRef > NameList)
inline ::clang::ast_matchers::internal::Matcher< QualType > matchesAnyListedTypeName(llvm::ArrayRef< StringRef > NameList)
bool recordIsTriviallyDefaultConstructible(const RecordDecl &RecordDecl, const ASTContext &Context)
Returns true if RecordDecl is trivially default constructible.
Definition: TypeTraits.cpp:49
std::optional< bool > isExpensiveToCopy(QualType Type, const ASTContext &Context)
Returns true if Type is expensive to copy.
Definition: TypeTraits.cpp:39
bool isTriviallyDestructible(QualType Type)
Returns true if Type is trivially destructible.
Definition: TypeTraits.cpp:137
bool operator()(const clang::ast_matchers::internal::BoundNodesMap &Nodes) const
Definition: Matchers.cpp:14