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