16 #include "llvm/ADT/SmallString.h"
17 #include "llvm/Support/ManagedStatic.h"
20 namespace ast_matchers {
43 void BoundNodesTreeBuilder::visitMatches(Visitor *ResultVisitor) {
45 Bindings.push_back(BoundNodesMap());
46 for (BoundNodesMap &Binding : Bindings) {
47 ResultVisitor->visitMatch(
BoundNodes(Binding));
53 typedef bool (*VariadicOperatorFunction)(
54 const ast_type_traits::DynTypedNode &DynNode, ASTMatchFinder *
Finder,
57 template <VariadicOperatorFunction Func>
58 class VariadicMatcher :
public DynMatcherInterface {
61 : InnerMatchers(std::move(InnerMatchers)) {}
63 bool dynMatches(
const ast_type_traits::DynTypedNode &DynNode,
64 ASTMatchFinder *Finder,
65 BoundNodesTreeBuilder *Builder)
const override {
73 class IdDynMatcher :
public DynMatcherInterface {
75 IdDynMatcher(StringRef
ID,
76 const IntrusiveRefCntPtr<DynMatcherInterface> &
InnerMatcher)
79 bool dynMatches(
const ast_type_traits::DynTypedNode &DynNode,
80 ASTMatchFinder *Finder,
81 BoundNodesTreeBuilder *Builder)
const override {
82 bool Result = InnerMatcher->dynMatches(DynNode, Finder, Builder);
83 if (Result) Builder->setBinding(ID, DynNode);
97 class TrueMatcherImpl :
public DynMatcherInterface {
102 bool dynMatches(
const ast_type_traits::DynTypedNode &, ASTMatchFinder *,
103 BoundNodesTreeBuilder *)
const override {
107 static llvm::ManagedStatic<TrueMatcherImpl> TrueMatcherInstance;
111 DynTypedMatcher DynTypedMatcher::constructVariadic(
112 DynTypedMatcher::VariadicOperator Op,
114 assert(InnerMatchers.size() > 0 &&
"Array must not be empty.");
115 assert(std::all_of(InnerMatchers.begin(), InnerMatchers.end(),
117 return InnerMatchers[0].canConvertTo(M.SupportedKind);
119 "SupportedKind must be convertible to a common type!");
121 auto SupportedKind = InnerMatchers[0].SupportedKind;
126 auto RestrictKind = SupportedKind;
134 for (
auto &IM : InnerMatchers) {
136 RestrictKind, IM.RestrictKind);
138 return DynTypedMatcher(
139 SupportedKind, RestrictKind,
140 new VariadicMatcher<AllOfVariadicOperator>(std::move(InnerMatchers)));
143 return DynTypedMatcher(
144 SupportedKind, RestrictKind,
145 new VariadicMatcher<AnyOfVariadicOperator>(std::move(InnerMatchers)));
148 return DynTypedMatcher(
149 SupportedKind, RestrictKind,
150 new VariadicMatcher<EachOfVariadicOperator>(std::move(InnerMatchers)));
155 return DynTypedMatcher(
156 SupportedKind, RestrictKind,
157 new VariadicMatcher<NotUnaryOperator>(std::move(InnerMatchers)));
159 llvm_unreachable(
"Invalid Op value.");
162 DynTypedMatcher DynTypedMatcher::trueMatcher(
163 ast_type_traits::ASTNodeKind NodeKind) {
164 return DynTypedMatcher(NodeKind, NodeKind, &*TrueMatcherInstance);
167 bool DynTypedMatcher::canMatchNodesOfKind(
168 ast_type_traits::ASTNodeKind
Kind)
const {
169 return RestrictKind.isBaseOf(Kind);
172 DynTypedMatcher DynTypedMatcher::dynCastTo(
173 const ast_type_traits::ASTNodeKind Kind)
const {
175 Copy.SupportedKind =
Kind;
182 ASTMatchFinder *Finder,
183 BoundNodesTreeBuilder *Builder)
const {
184 if (RestrictKind.isBaseOf(DynNode.getNodeKind()) &&
185 Implementation->dynMatches(DynNode, Finder, Builder)) {
191 Builder->removeBindings([](
const BoundNodesMap &) {
return true; });
195 bool DynTypedMatcher::matchesNoKindCheck(
196 const ast_type_traits::DynTypedNode &DynNode, ASTMatchFinder *Finder,
197 BoundNodesTreeBuilder *Builder)
const {
198 assert(RestrictKind.isBaseOf(DynNode.getNodeKind()));
199 if (Implementation->dynMatches(DynNode, Finder, Builder)) {
205 Builder->removeBindings([](
const BoundNodesMap &) {
return true; });
212 Result.Implementation =
new IdDynMatcher(ID, Result.Implementation);
216 bool DynTypedMatcher::canConvertTo(ast_type_traits::ASTNodeKind To)
const {
217 const auto From = getSupportedKind();
218 auto QualKind = ast_type_traits::ASTNodeKind::getFromNodeKind<QualType>();
219 auto TypeKind = ast_type_traits::ASTNodeKind::getFromNodeKind<Type>();
222 if (From.isSame(TypeKind) && To.isSame(QualKind))
return true;
224 return From.isBaseOf(To);
227 void BoundNodesTreeBuilder::addMatch(
const BoundNodesTreeBuilder &Other) {
228 Bindings.append(Other.Bindings.begin(), Other.Bindings.end());
232 ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder,
234 if (InnerMatchers.size() != 1)
247 BoundNodesTreeBuilder Discard(*Builder);
248 return !InnerMatchers[0].matches(DynNode, Finder, &Discard);
252 ASTMatchFinder *Finder,
253 BoundNodesTreeBuilder *Builder,
258 for (
const DynTypedMatcher &InnerMatcher : InnerMatchers) {
259 if (!InnerMatcher.matchesNoKindCheck(DynNode, Finder, Builder))
266 ASTMatchFinder *Finder,
267 BoundNodesTreeBuilder *Builder,
269 BoundNodesTreeBuilder Result;
270 bool Matched =
false;
271 for (
const DynTypedMatcher &InnerMatcher : InnerMatchers) {
272 BoundNodesTreeBuilder BuilderInner(*Builder);
273 if (InnerMatcher.matches(DynNode, Finder, &BuilderInner)) {
275 Result.addMatch(BuilderInner);
278 *Builder = std::move(Result);
283 ASTMatchFinder *Finder,
284 BoundNodesTreeBuilder *Builder,
286 for (
const DynTypedMatcher &InnerMatcher : InnerMatchers) {
287 BoundNodesTreeBuilder Result = *
Builder;
288 if (InnerMatcher.matches(DynNode, Finder, &Result)) {
289 *Builder = std::move(Result);
296 HasNameMatcher::HasNameMatcher(StringRef NameRef)
297 : UseUnqualifiedMatch(NameRef.find(
"::") == NameRef.npos), Name(NameRef) {
298 assert(!Name.empty());
301 bool HasNameMatcher::matchesNodeUnqualified(
const NamedDecl &
Node)
const {
302 assert(UseUnqualifiedMatch);
310 llvm::raw_svector_ostream OS(NodeName);
312 return Name == OS.str();
317 bool HasNameMatcher::matchesNodeFull(
const NamedDecl &Node)
const {
319 llvm::raw_svector_ostream OS(NodeName);
320 Node.printQualifiedName(OS);
321 const StringRef FullName = OS.str();
322 const StringRef Pattern = Name;
324 if (Pattern.startswith(
"::"))
325 return FullName == Pattern;
327 return FullName.endswith(Pattern) &&
328 FullName.drop_back(Pattern.size()).endswith(
"::");
331 bool HasNameMatcher::matchesNode(
const NamedDecl &Node)
const {
335 if (UseUnqualifiedMatch) {
336 assert(matchesNodeUnqualified(Node) == matchesNodeFull(Node));
337 return matchesNodeUnqualified(Node);
339 return matchesNodeFull(Node);
StringRef getName() const
IdentifierInfo * getIdentifier() const
bool AnyOfVariadicOperator(const ast_type_traits::DynTypedNode &DynNode, ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder, ArrayRef< DynTypedMatcher > InnerMatchers)
bool NotUnaryOperator(const ast_type_traits::DynTypedNode &DynNode, ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder, ArrayRef< DynTypedMatcher > InnerMatchers)
std::vector< DynTypedMatcher > InnerMatchers
const IntrusiveRefCntPtr< DynMatcherInterface > InnerMatcher
bool EachOfVariadicOperator(const ast_type_traits::DynTypedNode &DynNode, ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder, ArrayRef< DynTypedMatcher > InnerMatchers)
bool AllOfVariadicOperator(const ast_type_traits::DynTypedNode &DynNode, ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder, ArrayRef< DynTypedMatcher > InnerMatchers)
static ASTNodeKind getMostDerivedType(ASTNodeKind Kind1, ASTNodeKind Kind2)
Return the most derived type between Kind1 and Kind2.
DeclarationName getDeclName() const
The result type of a method or function.
ASTMatchFinder *const Finder
void printName(raw_ostream &os) const
BoundNodesTreeBuilder BoundNodes
ast_type_traits::DynTypedNode Node
A dynamically typed AST node container.
BoundNodesTreeBuilder *const Builder
bool matches(const til::SExpr *E1, const til::SExpr *E2)