xref: /minix3/external/bsd/llvm/dist/clang/lib/ASTMatchers/ASTMatchersInternal.cpp (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
1f4a2713aSLionel Sambuc //===--- ASTMatchersInternal.cpp - Structural query framework -------------===//
2f4a2713aSLionel Sambuc //
3f4a2713aSLionel Sambuc //                     The LLVM Compiler Infrastructure
4f4a2713aSLionel Sambuc //
5f4a2713aSLionel Sambuc // This file is distributed under the University of Illinois Open Source
6f4a2713aSLionel Sambuc // License. See LICENSE.TXT for details.
7f4a2713aSLionel Sambuc //
8f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
9f4a2713aSLionel Sambuc //
10f4a2713aSLionel Sambuc //  Implements the base layer of the matcher framework.
11f4a2713aSLionel Sambuc //
12f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
13f4a2713aSLionel Sambuc 
14f4a2713aSLionel Sambuc #include "clang/ASTMatchers/ASTMatchers.h"
15f4a2713aSLionel Sambuc #include "clang/ASTMatchers/ASTMatchersInternal.h"
16*0a6a1f1dSLionel Sambuc #include "llvm/ADT/SmallString.h"
17*0a6a1f1dSLionel Sambuc #include "llvm/Support/ManagedStatic.h"
18f4a2713aSLionel Sambuc 
19f4a2713aSLionel Sambuc namespace clang {
20f4a2713aSLionel Sambuc namespace ast_matchers {
21f4a2713aSLionel Sambuc namespace internal {
22f4a2713aSLionel Sambuc 
23*0a6a1f1dSLionel Sambuc bool NotUnaryOperator(const ast_type_traits::DynTypedNode DynNode,
24*0a6a1f1dSLionel Sambuc                       ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder,
25*0a6a1f1dSLionel Sambuc                       ArrayRef<DynTypedMatcher> InnerMatchers);
26*0a6a1f1dSLionel Sambuc 
27*0a6a1f1dSLionel Sambuc bool AllOfVariadicOperator(const ast_type_traits::DynTypedNode DynNode,
28*0a6a1f1dSLionel Sambuc                            ASTMatchFinder *Finder,
29*0a6a1f1dSLionel Sambuc                            BoundNodesTreeBuilder *Builder,
30*0a6a1f1dSLionel Sambuc                            ArrayRef<DynTypedMatcher> InnerMatchers);
31*0a6a1f1dSLionel Sambuc 
32*0a6a1f1dSLionel Sambuc bool EachOfVariadicOperator(const ast_type_traits::DynTypedNode DynNode,
33*0a6a1f1dSLionel Sambuc                             ASTMatchFinder *Finder,
34*0a6a1f1dSLionel Sambuc                             BoundNodesTreeBuilder *Builder,
35*0a6a1f1dSLionel Sambuc                             ArrayRef<DynTypedMatcher> InnerMatchers);
36*0a6a1f1dSLionel Sambuc 
37*0a6a1f1dSLionel Sambuc bool AnyOfVariadicOperator(const ast_type_traits::DynTypedNode DynNode,
38*0a6a1f1dSLionel Sambuc                            ASTMatchFinder *Finder,
39*0a6a1f1dSLionel Sambuc                            BoundNodesTreeBuilder *Builder,
40*0a6a1f1dSLionel Sambuc                            ArrayRef<DynTypedMatcher> InnerMatchers);
41*0a6a1f1dSLionel Sambuc 
42*0a6a1f1dSLionel Sambuc 
visitMatches(Visitor * ResultVisitor)43f4a2713aSLionel Sambuc void BoundNodesTreeBuilder::visitMatches(Visitor *ResultVisitor) {
44f4a2713aSLionel Sambuc   if (Bindings.empty())
45f4a2713aSLionel Sambuc     Bindings.push_back(BoundNodesMap());
46*0a6a1f1dSLionel Sambuc   for (BoundNodesMap &Binding : Bindings) {
47*0a6a1f1dSLionel Sambuc     ResultVisitor->visitMatch(BoundNodes(Binding));
48f4a2713aSLionel Sambuc   }
49f4a2713aSLionel Sambuc }
50f4a2713aSLionel Sambuc 
51*0a6a1f1dSLionel Sambuc namespace {
52*0a6a1f1dSLionel Sambuc 
53*0a6a1f1dSLionel Sambuc typedef bool (*VariadicOperatorFunction)(
54*0a6a1f1dSLionel Sambuc     const ast_type_traits::DynTypedNode DynNode, ASTMatchFinder *Finder,
55*0a6a1f1dSLionel Sambuc     BoundNodesTreeBuilder *Builder, ArrayRef<DynTypedMatcher> InnerMatchers);
56*0a6a1f1dSLionel Sambuc 
57*0a6a1f1dSLionel Sambuc template <VariadicOperatorFunction Func>
58*0a6a1f1dSLionel Sambuc class VariadicMatcher : public DynMatcherInterface {
59*0a6a1f1dSLionel Sambuc public:
VariadicMatcher(std::vector<DynTypedMatcher> InnerMatchers)60*0a6a1f1dSLionel Sambuc   VariadicMatcher(std::vector<DynTypedMatcher> InnerMatchers)
61*0a6a1f1dSLionel Sambuc       : InnerMatchers(std::move(InnerMatchers)) {}
62*0a6a1f1dSLionel Sambuc 
dynMatches(const ast_type_traits::DynTypedNode & DynNode,ASTMatchFinder * Finder,BoundNodesTreeBuilder * Builder) const63*0a6a1f1dSLionel Sambuc   bool dynMatches(const ast_type_traits::DynTypedNode &DynNode,
64*0a6a1f1dSLionel Sambuc                   ASTMatchFinder *Finder,
65*0a6a1f1dSLionel Sambuc                   BoundNodesTreeBuilder *Builder) const override {
66*0a6a1f1dSLionel Sambuc     return Func(DynNode, Finder, Builder, InnerMatchers);
67*0a6a1f1dSLionel Sambuc   }
68*0a6a1f1dSLionel Sambuc 
69*0a6a1f1dSLionel Sambuc private:
70*0a6a1f1dSLionel Sambuc   std::vector<DynTypedMatcher> InnerMatchers;
71*0a6a1f1dSLionel Sambuc };
72*0a6a1f1dSLionel Sambuc 
73*0a6a1f1dSLionel Sambuc class IdDynMatcher : public DynMatcherInterface {
74*0a6a1f1dSLionel Sambuc  public:
IdDynMatcher(StringRef ID,const IntrusiveRefCntPtr<DynMatcherInterface> & InnerMatcher)75*0a6a1f1dSLionel Sambuc   IdDynMatcher(StringRef ID,
76*0a6a1f1dSLionel Sambuc                const IntrusiveRefCntPtr<DynMatcherInterface> &InnerMatcher)
77*0a6a1f1dSLionel Sambuc       : ID(ID), InnerMatcher(InnerMatcher) {}
78*0a6a1f1dSLionel Sambuc 
dynMatches(const ast_type_traits::DynTypedNode & DynNode,ASTMatchFinder * Finder,BoundNodesTreeBuilder * Builder) const79*0a6a1f1dSLionel Sambuc   bool dynMatches(const ast_type_traits::DynTypedNode &DynNode,
80*0a6a1f1dSLionel Sambuc                   ASTMatchFinder *Finder,
81*0a6a1f1dSLionel Sambuc                   BoundNodesTreeBuilder *Builder) const override {
82*0a6a1f1dSLionel Sambuc     bool Result = InnerMatcher->dynMatches(DynNode, Finder, Builder);
83*0a6a1f1dSLionel Sambuc     if (Result) Builder->setBinding(ID, DynNode);
84*0a6a1f1dSLionel Sambuc     return Result;
85*0a6a1f1dSLionel Sambuc   }
86*0a6a1f1dSLionel Sambuc 
87*0a6a1f1dSLionel Sambuc  private:
88*0a6a1f1dSLionel Sambuc   const std::string ID;
89*0a6a1f1dSLionel Sambuc   const IntrusiveRefCntPtr<DynMatcherInterface> InnerMatcher;
90*0a6a1f1dSLionel Sambuc };
91*0a6a1f1dSLionel Sambuc 
92*0a6a1f1dSLionel Sambuc /// \brief A matcher that always returns true.
93*0a6a1f1dSLionel Sambuc ///
94*0a6a1f1dSLionel Sambuc /// We only ever need one instance of this matcher, so we create a global one
95*0a6a1f1dSLionel Sambuc /// and reuse it to reduce the overhead of the matcher and increase the chance
96*0a6a1f1dSLionel Sambuc /// of cache hits.
97*0a6a1f1dSLionel Sambuc class TrueMatcherImpl : public DynMatcherInterface {
98*0a6a1f1dSLionel Sambuc public:
TrueMatcherImpl()99*0a6a1f1dSLionel Sambuc   TrueMatcherImpl() {
100*0a6a1f1dSLionel Sambuc     Retain(); // Reference count will never become zero.
101*0a6a1f1dSLionel Sambuc   }
dynMatches(const ast_type_traits::DynTypedNode &,ASTMatchFinder *,BoundNodesTreeBuilder *) const102*0a6a1f1dSLionel Sambuc   bool dynMatches(const ast_type_traits::DynTypedNode &, ASTMatchFinder *,
103*0a6a1f1dSLionel Sambuc                   BoundNodesTreeBuilder *) const override {
104*0a6a1f1dSLionel Sambuc     return true;
105*0a6a1f1dSLionel Sambuc   }
106*0a6a1f1dSLionel Sambuc };
107*0a6a1f1dSLionel Sambuc static llvm::ManagedStatic<TrueMatcherImpl> TrueMatcherInstance;
108*0a6a1f1dSLionel Sambuc 
109*0a6a1f1dSLionel Sambuc }  // namespace
110*0a6a1f1dSLionel Sambuc 
constructVariadic(DynTypedMatcher::VariadicOperator Op,std::vector<DynTypedMatcher> InnerMatchers)111*0a6a1f1dSLionel Sambuc DynTypedMatcher DynTypedMatcher::constructVariadic(
112*0a6a1f1dSLionel Sambuc     DynTypedMatcher::VariadicOperator Op,
113*0a6a1f1dSLionel Sambuc     std::vector<DynTypedMatcher> InnerMatchers) {
114*0a6a1f1dSLionel Sambuc   assert(InnerMatchers.size() > 0 && "Array must not be empty.");
115*0a6a1f1dSLionel Sambuc   assert(std::all_of(InnerMatchers.begin(), InnerMatchers.end(),
116*0a6a1f1dSLionel Sambuc                      [&InnerMatchers](const DynTypedMatcher &M) {
117*0a6a1f1dSLionel Sambuc            return InnerMatchers[0].SupportedKind.isSame(M.SupportedKind);
118*0a6a1f1dSLionel Sambuc          }) &&
119*0a6a1f1dSLionel Sambuc          "SupportedKind must match!");
120*0a6a1f1dSLionel Sambuc 
121*0a6a1f1dSLionel Sambuc   auto SupportedKind = InnerMatchers[0].SupportedKind;
122*0a6a1f1dSLionel Sambuc   // We must relax the restrict kind here.
123*0a6a1f1dSLionel Sambuc   // The different operators might deal differently with a mismatch.
124*0a6a1f1dSLionel Sambuc   // Make it the same as SupportedKind, since that is the broadest type we are
125*0a6a1f1dSLionel Sambuc   // allowed to accept.
126*0a6a1f1dSLionel Sambuc   auto RestrictKind = SupportedKind;
127*0a6a1f1dSLionel Sambuc 
128*0a6a1f1dSLionel Sambuc   switch (Op) {
129*0a6a1f1dSLionel Sambuc   case VO_AllOf:
130*0a6a1f1dSLionel Sambuc     // In the case of allOf() we must pass all the checks, so making
131*0a6a1f1dSLionel Sambuc     // RestrictKind the most restrictive can save us time. This way we reject
132*0a6a1f1dSLionel Sambuc     // invalid types earlier and we can elide the kind checks inside the
133*0a6a1f1dSLionel Sambuc     // matcher.
134*0a6a1f1dSLionel Sambuc     for (auto &IM : InnerMatchers) {
135*0a6a1f1dSLionel Sambuc       RestrictKind = ast_type_traits::ASTNodeKind::getMostDerivedType(
136*0a6a1f1dSLionel Sambuc           RestrictKind, IM.RestrictKind);
137*0a6a1f1dSLionel Sambuc     }
138*0a6a1f1dSLionel Sambuc     return DynTypedMatcher(
139*0a6a1f1dSLionel Sambuc         SupportedKind, RestrictKind,
140*0a6a1f1dSLionel Sambuc         new VariadicMatcher<AllOfVariadicOperator>(std::move(InnerMatchers)));
141*0a6a1f1dSLionel Sambuc 
142*0a6a1f1dSLionel Sambuc   case VO_AnyOf:
143*0a6a1f1dSLionel Sambuc     return DynTypedMatcher(
144*0a6a1f1dSLionel Sambuc         SupportedKind, RestrictKind,
145*0a6a1f1dSLionel Sambuc         new VariadicMatcher<AnyOfVariadicOperator>(std::move(InnerMatchers)));
146*0a6a1f1dSLionel Sambuc 
147*0a6a1f1dSLionel Sambuc   case VO_EachOf:
148*0a6a1f1dSLionel Sambuc     return DynTypedMatcher(
149*0a6a1f1dSLionel Sambuc         SupportedKind, RestrictKind,
150*0a6a1f1dSLionel Sambuc         new VariadicMatcher<EachOfVariadicOperator>(std::move(InnerMatchers)));
151*0a6a1f1dSLionel Sambuc 
152*0a6a1f1dSLionel Sambuc   case VO_UnaryNot:
153*0a6a1f1dSLionel Sambuc     // FIXME: Implement the Not operator to take a single matcher instead of a
154*0a6a1f1dSLionel Sambuc     // vector.
155*0a6a1f1dSLionel Sambuc     return DynTypedMatcher(
156*0a6a1f1dSLionel Sambuc         SupportedKind, RestrictKind,
157*0a6a1f1dSLionel Sambuc         new VariadicMatcher<NotUnaryOperator>(std::move(InnerMatchers)));
158*0a6a1f1dSLionel Sambuc   }
159*0a6a1f1dSLionel Sambuc   llvm_unreachable("Invalid Op value.");
160*0a6a1f1dSLionel Sambuc }
161*0a6a1f1dSLionel Sambuc 
trueMatcher(ast_type_traits::ASTNodeKind NodeKind)162*0a6a1f1dSLionel Sambuc DynTypedMatcher DynTypedMatcher::trueMatcher(
163*0a6a1f1dSLionel Sambuc     ast_type_traits::ASTNodeKind NodeKind) {
164*0a6a1f1dSLionel Sambuc   return DynTypedMatcher(NodeKind, NodeKind, &*TrueMatcherInstance);
165*0a6a1f1dSLionel Sambuc }
166*0a6a1f1dSLionel Sambuc 
canMatchNodesOfKind(ast_type_traits::ASTNodeKind Kind) const167*0a6a1f1dSLionel Sambuc bool DynTypedMatcher::canMatchNodesOfKind(
168*0a6a1f1dSLionel Sambuc     ast_type_traits::ASTNodeKind Kind) const {
169*0a6a1f1dSLionel Sambuc   return RestrictKind.isBaseOf(Kind);
170*0a6a1f1dSLionel Sambuc }
171*0a6a1f1dSLionel Sambuc 
dynCastTo(const ast_type_traits::ASTNodeKind Kind) const172*0a6a1f1dSLionel Sambuc DynTypedMatcher DynTypedMatcher::dynCastTo(
173*0a6a1f1dSLionel Sambuc     const ast_type_traits::ASTNodeKind Kind) const {
174*0a6a1f1dSLionel Sambuc   auto Copy = *this;
175*0a6a1f1dSLionel Sambuc   Copy.SupportedKind = Kind;
176*0a6a1f1dSLionel Sambuc   Copy.RestrictKind =
177*0a6a1f1dSLionel Sambuc       ast_type_traits::ASTNodeKind::getMostDerivedType(Kind, RestrictKind);
178*0a6a1f1dSLionel Sambuc   return Copy;
179*0a6a1f1dSLionel Sambuc }
180*0a6a1f1dSLionel Sambuc 
matches(const ast_type_traits::DynTypedNode & DynNode,ASTMatchFinder * Finder,BoundNodesTreeBuilder * Builder) const181*0a6a1f1dSLionel Sambuc bool DynTypedMatcher::matches(const ast_type_traits::DynTypedNode &DynNode,
182*0a6a1f1dSLionel Sambuc                               ASTMatchFinder *Finder,
183*0a6a1f1dSLionel Sambuc                               BoundNodesTreeBuilder *Builder) const {
184*0a6a1f1dSLionel Sambuc   if (RestrictKind.isBaseOf(DynNode.getNodeKind()) &&
185*0a6a1f1dSLionel Sambuc       Implementation->dynMatches(DynNode, Finder, Builder)) {
186*0a6a1f1dSLionel Sambuc     return true;
187*0a6a1f1dSLionel Sambuc   }
188*0a6a1f1dSLionel Sambuc   // Delete all bindings when a matcher does not match.
189*0a6a1f1dSLionel Sambuc   // This prevents unexpected exposure of bound nodes in unmatches
190*0a6a1f1dSLionel Sambuc   // branches of the match tree.
191*0a6a1f1dSLionel Sambuc   Builder->removeBindings([](const BoundNodesMap &) { return true; });
192*0a6a1f1dSLionel Sambuc   return false;
193*0a6a1f1dSLionel Sambuc }
194*0a6a1f1dSLionel Sambuc 
matchesNoKindCheck(const ast_type_traits::DynTypedNode & DynNode,ASTMatchFinder * Finder,BoundNodesTreeBuilder * Builder) const195*0a6a1f1dSLionel Sambuc bool DynTypedMatcher::matchesNoKindCheck(
196*0a6a1f1dSLionel Sambuc     const ast_type_traits::DynTypedNode &DynNode, ASTMatchFinder *Finder,
197*0a6a1f1dSLionel Sambuc     BoundNodesTreeBuilder *Builder) const {
198*0a6a1f1dSLionel Sambuc   assert(RestrictKind.isBaseOf(DynNode.getNodeKind()));
199*0a6a1f1dSLionel Sambuc   if (Implementation->dynMatches(DynNode, Finder, Builder)) {
200*0a6a1f1dSLionel Sambuc     return true;
201*0a6a1f1dSLionel Sambuc   }
202*0a6a1f1dSLionel Sambuc   // Delete all bindings when a matcher does not match.
203*0a6a1f1dSLionel Sambuc   // This prevents unexpected exposure of bound nodes in unmatches
204*0a6a1f1dSLionel Sambuc   // branches of the match tree.
205*0a6a1f1dSLionel Sambuc   Builder->removeBindings([](const BoundNodesMap &) { return true; });
206*0a6a1f1dSLionel Sambuc   return false;
207*0a6a1f1dSLionel Sambuc }
208*0a6a1f1dSLionel Sambuc 
tryBind(StringRef ID) const209*0a6a1f1dSLionel Sambuc llvm::Optional<DynTypedMatcher> DynTypedMatcher::tryBind(StringRef ID) const {
210*0a6a1f1dSLionel Sambuc   if (!AllowBind) return llvm::None;
211*0a6a1f1dSLionel Sambuc   auto Result = *this;
212*0a6a1f1dSLionel Sambuc   Result.Implementation = new IdDynMatcher(ID, Result.Implementation);
213*0a6a1f1dSLionel Sambuc   return Result;
214*0a6a1f1dSLionel Sambuc }
215*0a6a1f1dSLionel Sambuc 
canConvertTo(ast_type_traits::ASTNodeKind To) const216*0a6a1f1dSLionel Sambuc bool DynTypedMatcher::canConvertTo(ast_type_traits::ASTNodeKind To) const {
217*0a6a1f1dSLionel Sambuc   const auto From = getSupportedKind();
218*0a6a1f1dSLionel Sambuc   auto QualKind = ast_type_traits::ASTNodeKind::getFromNodeKind<QualType>();
219*0a6a1f1dSLionel Sambuc   auto TypeKind = ast_type_traits::ASTNodeKind::getFromNodeKind<Type>();
220*0a6a1f1dSLionel Sambuc   /// Mimic the implicit conversions of Matcher<>.
221*0a6a1f1dSLionel Sambuc   /// - From Matcher<Type> to Matcher<QualType>
222*0a6a1f1dSLionel Sambuc   if (From.isSame(TypeKind) && To.isSame(QualKind)) return true;
223*0a6a1f1dSLionel Sambuc   /// - From Matcher<Base> to Matcher<Derived>
224*0a6a1f1dSLionel Sambuc   return From.isBaseOf(To);
225*0a6a1f1dSLionel Sambuc }
226f4a2713aSLionel Sambuc 
addMatch(const BoundNodesTreeBuilder & Other)227f4a2713aSLionel Sambuc void BoundNodesTreeBuilder::addMatch(const BoundNodesTreeBuilder &Other) {
228*0a6a1f1dSLionel Sambuc   Bindings.append(Other.Bindings.begin(), Other.Bindings.end());
229f4a2713aSLionel Sambuc }
230*0a6a1f1dSLionel Sambuc 
NotUnaryOperator(const ast_type_traits::DynTypedNode DynNode,ASTMatchFinder * Finder,BoundNodesTreeBuilder * Builder,ArrayRef<DynTypedMatcher> InnerMatchers)231*0a6a1f1dSLionel Sambuc bool NotUnaryOperator(const ast_type_traits::DynTypedNode DynNode,
232*0a6a1f1dSLionel Sambuc                       ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder,
233*0a6a1f1dSLionel Sambuc                       ArrayRef<DynTypedMatcher> InnerMatchers) {
234*0a6a1f1dSLionel Sambuc   if (InnerMatchers.size() != 1)
235*0a6a1f1dSLionel Sambuc     return false;
236*0a6a1f1dSLionel Sambuc 
237*0a6a1f1dSLionel Sambuc   // The 'unless' matcher will always discard the result:
238*0a6a1f1dSLionel Sambuc   // If the inner matcher doesn't match, unless returns true,
239*0a6a1f1dSLionel Sambuc   // but the inner matcher cannot have bound anything.
240*0a6a1f1dSLionel Sambuc   // If the inner matcher matches, the result is false, and
241*0a6a1f1dSLionel Sambuc   // any possible binding will be discarded.
242*0a6a1f1dSLionel Sambuc   // We still need to hand in all the bound nodes up to this
243*0a6a1f1dSLionel Sambuc   // point so the inner matcher can depend on bound nodes,
244*0a6a1f1dSLionel Sambuc   // and we need to actively discard the bound nodes, otherwise
245*0a6a1f1dSLionel Sambuc   // the inner matcher will reset the bound nodes if it doesn't
246*0a6a1f1dSLionel Sambuc   // match, but this would be inversed by 'unless'.
247*0a6a1f1dSLionel Sambuc   BoundNodesTreeBuilder Discard(*Builder);
248*0a6a1f1dSLionel Sambuc   return !InnerMatchers[0].matches(DynNode, Finder, &Discard);
249f4a2713aSLionel Sambuc }
250f4a2713aSLionel Sambuc 
AllOfVariadicOperator(const ast_type_traits::DynTypedNode DynNode,ASTMatchFinder * Finder,BoundNodesTreeBuilder * Builder,ArrayRef<DynTypedMatcher> InnerMatchers)251f4a2713aSLionel Sambuc bool AllOfVariadicOperator(const ast_type_traits::DynTypedNode DynNode,
252f4a2713aSLionel Sambuc                            ASTMatchFinder *Finder,
253f4a2713aSLionel Sambuc                            BoundNodesTreeBuilder *Builder,
254f4a2713aSLionel Sambuc                            ArrayRef<DynTypedMatcher> InnerMatchers) {
255f4a2713aSLionel Sambuc   // allOf leads to one matcher for each alternative in the first
256f4a2713aSLionel Sambuc   // matcher combined with each alternative in the second matcher.
257f4a2713aSLionel Sambuc   // Thus, we can reuse the same Builder.
258*0a6a1f1dSLionel Sambuc   for (const DynTypedMatcher &InnerMatcher : InnerMatchers) {
259*0a6a1f1dSLionel Sambuc     if (!InnerMatcher.matchesNoKindCheck(DynNode, Finder, Builder))
260f4a2713aSLionel Sambuc       return false;
261f4a2713aSLionel Sambuc   }
262f4a2713aSLionel Sambuc   return true;
263f4a2713aSLionel Sambuc }
264f4a2713aSLionel Sambuc 
EachOfVariadicOperator(const ast_type_traits::DynTypedNode DynNode,ASTMatchFinder * Finder,BoundNodesTreeBuilder * Builder,ArrayRef<DynTypedMatcher> InnerMatchers)265f4a2713aSLionel Sambuc bool EachOfVariadicOperator(const ast_type_traits::DynTypedNode DynNode,
266f4a2713aSLionel Sambuc                             ASTMatchFinder *Finder,
267f4a2713aSLionel Sambuc                             BoundNodesTreeBuilder *Builder,
268f4a2713aSLionel Sambuc                             ArrayRef<DynTypedMatcher> InnerMatchers) {
269f4a2713aSLionel Sambuc   BoundNodesTreeBuilder Result;
270f4a2713aSLionel Sambuc   bool Matched = false;
271*0a6a1f1dSLionel Sambuc   for (const DynTypedMatcher &InnerMatcher : InnerMatchers) {
272f4a2713aSLionel Sambuc     BoundNodesTreeBuilder BuilderInner(*Builder);
273*0a6a1f1dSLionel Sambuc     if (InnerMatcher.matches(DynNode, Finder, &BuilderInner)) {
274f4a2713aSLionel Sambuc       Matched = true;
275f4a2713aSLionel Sambuc       Result.addMatch(BuilderInner);
276f4a2713aSLionel Sambuc     }
277f4a2713aSLionel Sambuc   }
278*0a6a1f1dSLionel Sambuc   *Builder = std::move(Result);
279f4a2713aSLionel Sambuc   return Matched;
280f4a2713aSLionel Sambuc }
281f4a2713aSLionel Sambuc 
AnyOfVariadicOperator(const ast_type_traits::DynTypedNode DynNode,ASTMatchFinder * Finder,BoundNodesTreeBuilder * Builder,ArrayRef<DynTypedMatcher> InnerMatchers)282f4a2713aSLionel Sambuc bool AnyOfVariadicOperator(const ast_type_traits::DynTypedNode DynNode,
283f4a2713aSLionel Sambuc                            ASTMatchFinder *Finder,
284f4a2713aSLionel Sambuc                            BoundNodesTreeBuilder *Builder,
285f4a2713aSLionel Sambuc                            ArrayRef<DynTypedMatcher> InnerMatchers) {
286*0a6a1f1dSLionel Sambuc   for (const DynTypedMatcher &InnerMatcher : InnerMatchers) {
287f4a2713aSLionel Sambuc     BoundNodesTreeBuilder Result = *Builder;
288*0a6a1f1dSLionel Sambuc     if (InnerMatcher.matches(DynNode, Finder, &Result)) {
289*0a6a1f1dSLionel Sambuc       *Builder = std::move(Result);
290f4a2713aSLionel Sambuc       return true;
291f4a2713aSLionel Sambuc     }
292f4a2713aSLionel Sambuc   }
293f4a2713aSLionel Sambuc   return false;
294f4a2713aSLionel Sambuc }
295f4a2713aSLionel Sambuc 
HasNameMatcher(StringRef NameRef)296*0a6a1f1dSLionel Sambuc HasNameMatcher::HasNameMatcher(StringRef NameRef)
297*0a6a1f1dSLionel Sambuc     : UseUnqualifiedMatch(NameRef.find("::") == NameRef.npos), Name(NameRef) {
298*0a6a1f1dSLionel Sambuc   assert(!Name.empty());
299*0a6a1f1dSLionel Sambuc }
300*0a6a1f1dSLionel Sambuc 
matchesNodeUnqualified(const NamedDecl & Node) const301*0a6a1f1dSLionel Sambuc bool HasNameMatcher::matchesNodeUnqualified(const NamedDecl &Node) const {
302*0a6a1f1dSLionel Sambuc   assert(UseUnqualifiedMatch);
303*0a6a1f1dSLionel Sambuc   if (Node.getIdentifier()) {
304*0a6a1f1dSLionel Sambuc     // Simple name.
305*0a6a1f1dSLionel Sambuc     return Name == Node.getName();
306*0a6a1f1dSLionel Sambuc   }
307*0a6a1f1dSLionel Sambuc   if (Node.getDeclName()) {
308*0a6a1f1dSLionel Sambuc     // Name needs to be constructed.
309*0a6a1f1dSLionel Sambuc     llvm::SmallString<128> NodeName;
310*0a6a1f1dSLionel Sambuc     llvm::raw_svector_ostream OS(NodeName);
311*0a6a1f1dSLionel Sambuc     Node.printName(OS);
312*0a6a1f1dSLionel Sambuc     return Name == OS.str();
313*0a6a1f1dSLionel Sambuc   }
314*0a6a1f1dSLionel Sambuc   return false;
315*0a6a1f1dSLionel Sambuc }
316*0a6a1f1dSLionel Sambuc 
matchesNodeFull(const NamedDecl & Node) const317*0a6a1f1dSLionel Sambuc bool HasNameMatcher::matchesNodeFull(const NamedDecl &Node) const {
318*0a6a1f1dSLionel Sambuc   llvm::SmallString<128> NodeName = StringRef("::");
319*0a6a1f1dSLionel Sambuc   llvm::raw_svector_ostream OS(NodeName);
320*0a6a1f1dSLionel Sambuc   Node.printQualifiedName(OS);
321*0a6a1f1dSLionel Sambuc   const StringRef FullName = OS.str();
322*0a6a1f1dSLionel Sambuc   const StringRef Pattern = Name;
323*0a6a1f1dSLionel Sambuc 
324*0a6a1f1dSLionel Sambuc   if (Pattern.startswith("::"))
325*0a6a1f1dSLionel Sambuc     return FullName == Pattern;
326*0a6a1f1dSLionel Sambuc 
327*0a6a1f1dSLionel Sambuc   return FullName.endswith(Pattern) &&
328*0a6a1f1dSLionel Sambuc          FullName.drop_back(Pattern.size()).endswith("::");
329*0a6a1f1dSLionel Sambuc }
330*0a6a1f1dSLionel Sambuc 
matchesNode(const NamedDecl & Node) const331*0a6a1f1dSLionel Sambuc bool HasNameMatcher::matchesNode(const NamedDecl &Node) const {
332*0a6a1f1dSLionel Sambuc   // FIXME: There is still room for improvement, but it would require copying a
333*0a6a1f1dSLionel Sambuc   // lot of the logic from NamedDecl::printQualifiedName(). The benchmarks do
334*0a6a1f1dSLionel Sambuc   // not show like that extra complexity is needed right now.
335*0a6a1f1dSLionel Sambuc   if (UseUnqualifiedMatch) {
336*0a6a1f1dSLionel Sambuc     assert(matchesNodeUnqualified(Node) == matchesNodeFull(Node));
337*0a6a1f1dSLionel Sambuc     return matchesNodeUnqualified(Node);
338*0a6a1f1dSLionel Sambuc   }
339*0a6a1f1dSLionel Sambuc   return matchesNodeFull(Node);
340*0a6a1f1dSLionel Sambuc }
341*0a6a1f1dSLionel Sambuc 
342f4a2713aSLionel Sambuc } // end namespace internal
343f4a2713aSLionel Sambuc } // end namespace ast_matchers
344f4a2713aSLionel Sambuc } // end namespace clang
345