1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
|
//===--- 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"
#include <optional>
namespace clang::tidy::matchers {
AST_MATCHER(BinaryOperator, isRelationalOperator) {
return Node.isRelationalOp();
}
AST_MATCHER(BinaryOperator, isEqualityOperator) { return Node.isEqualityOp(); }
AST_MATCHER(QualType, isExpensiveToCopy) {
std::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<StringRef> 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<StringRef> NameList) {
return ::clang::ast_matchers::internal::makeMatcher(
new MatchesAnyListedNameMatcher(NameList));
}
} // namespace clang::tidy::matchers
#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_UTILS_MATCHERS_H
|