1//===--- ASTMatchersInternal.cpp - Structural query framework -------------===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10//  Implements the base layer of the matcher framework.
11//
12//===----------------------------------------------------------------------===//
13
14#include "clang/ASTMatchers/ASTMatchers.h"
15#include "clang/ASTMatchers/ASTMatchersInternal.h"
16
17namespace clang {
18namespace ast_matchers {
19namespace internal {
20
21void BoundNodesTreeBuilder::visitMatches(Visitor *ResultVisitor) {
22  if (Bindings.empty())
23    Bindings.push_back(BoundNodesMap());
24  for (unsigned i = 0, e = Bindings.size(); i != e; ++i) {
25    ResultVisitor->visitMatch(BoundNodes(Bindings[i]));
26  }
27}
28
29DynTypedMatcher::MatcherStorage::~MatcherStorage() {}
30
31void BoundNodesTreeBuilder::addMatch(const BoundNodesTreeBuilder &Other) {
32  for (unsigned i = 0, e = Other.Bindings.size(); i != e; ++i) {
33    Bindings.push_back(Other.Bindings[i]);
34  }
35}
36
37bool NotUnaryOperator(const ast_type_traits::DynTypedNode DynNode,
38                      ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder,
39                      ArrayRef<DynTypedMatcher> InnerMatchers) {
40  if (InnerMatchers.size() != 1)
41    return false;
42
43  // The 'unless' matcher will always discard the result:
44  // If the inner matcher doesn't match, unless returns true,
45  // but the inner matcher cannot have bound anything.
46  // If the inner matcher matches, the result is false, and
47  // any possible binding will be discarded.
48  // We still need to hand in all the bound nodes up to this
49  // point so the inner matcher can depend on bound nodes,
50  // and we need to actively discard the bound nodes, otherwise
51  // the inner matcher will reset the bound nodes if it doesn't
52  // match, but this would be inversed by 'unless'.
53  BoundNodesTreeBuilder Discard(*Builder);
54  return !InnerMatchers[0].matches(DynNode, Finder, &Discard);
55}
56
57bool AllOfVariadicOperator(const ast_type_traits::DynTypedNode DynNode,
58                           ASTMatchFinder *Finder,
59                           BoundNodesTreeBuilder *Builder,
60                           ArrayRef<DynTypedMatcher> InnerMatchers) {
61  // allOf leads to one matcher for each alternative in the first
62  // matcher combined with each alternative in the second matcher.
63  // Thus, we can reuse the same Builder.
64  for (size_t i = 0, e = InnerMatchers.size(); i != e; ++i) {
65    if (!InnerMatchers[i].matches(DynNode, Finder, Builder))
66      return false;
67  }
68  return true;
69}
70
71bool EachOfVariadicOperator(const ast_type_traits::DynTypedNode DynNode,
72                            ASTMatchFinder *Finder,
73                            BoundNodesTreeBuilder *Builder,
74                            ArrayRef<DynTypedMatcher> InnerMatchers) {
75  BoundNodesTreeBuilder Result;
76  bool Matched = false;
77  for (size_t i = 0, e = InnerMatchers.size(); i != e; ++i) {
78    BoundNodesTreeBuilder BuilderInner(*Builder);
79    if (InnerMatchers[i].matches(DynNode, Finder, &BuilderInner)) {
80      Matched = true;
81      Result.addMatch(BuilderInner);
82    }
83  }
84  *Builder = Result;
85  return Matched;
86}
87
88bool AnyOfVariadicOperator(const ast_type_traits::DynTypedNode DynNode,
89                           ASTMatchFinder *Finder,
90                           BoundNodesTreeBuilder *Builder,
91                           ArrayRef<DynTypedMatcher> InnerMatchers) {
92  for (size_t i = 0, e = InnerMatchers.size(); i != e; ++i) {
93    BoundNodesTreeBuilder Result = *Builder;
94    if (InnerMatchers[i].matches(DynNode, Finder, &Result)) {
95      *Builder = Result;
96      return true;
97    }
98  }
99  return false;
100}
101
102} // end namespace internal
103} // end namespace ast_matchers
104} // end namespace clang
105