xref: /aosp_15_r20/external/clang/lib/ASTMatchers/ASTMatchersInternal.cpp (revision 67e74705e28f6214e480b399dd47ea732279e315)
1*67e74705SXin Li //===--- ASTMatchersInternal.cpp - Structural query framework -------------===//
2*67e74705SXin Li //
3*67e74705SXin Li //                     The LLVM Compiler Infrastructure
4*67e74705SXin Li //
5*67e74705SXin Li // This file is distributed under the University of Illinois Open Source
6*67e74705SXin Li // License. See LICENSE.TXT for details.
7*67e74705SXin Li //
8*67e74705SXin Li //===----------------------------------------------------------------------===//
9*67e74705SXin Li //
10*67e74705SXin Li //  Implements the base layer of the matcher framework.
11*67e74705SXin Li //
12*67e74705SXin Li //===----------------------------------------------------------------------===//
13*67e74705SXin Li 
14*67e74705SXin Li #include "clang/ASTMatchers/ASTMatchers.h"
15*67e74705SXin Li #include "clang/ASTMatchers/ASTMatchersInternal.h"
16*67e74705SXin Li #include "llvm/ADT/SmallString.h"
17*67e74705SXin Li #include "llvm/ADT/SmallVector.h"
18*67e74705SXin Li #include "llvm/Support/ManagedStatic.h"
19*67e74705SXin Li 
20*67e74705SXin Li namespace clang {
21*67e74705SXin Li namespace ast_matchers {
22*67e74705SXin Li namespace internal {
23*67e74705SXin Li 
24*67e74705SXin Li bool NotUnaryOperator(const ast_type_traits::DynTypedNode &DynNode,
25*67e74705SXin Li                       ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder,
26*67e74705SXin Li                       ArrayRef<DynTypedMatcher> InnerMatchers);
27*67e74705SXin Li 
28*67e74705SXin Li bool AllOfVariadicOperator(const ast_type_traits::DynTypedNode &DynNode,
29*67e74705SXin Li                            ASTMatchFinder *Finder,
30*67e74705SXin Li                            BoundNodesTreeBuilder *Builder,
31*67e74705SXin Li                            ArrayRef<DynTypedMatcher> InnerMatchers);
32*67e74705SXin Li 
33*67e74705SXin Li bool EachOfVariadicOperator(const ast_type_traits::DynTypedNode &DynNode,
34*67e74705SXin Li                             ASTMatchFinder *Finder,
35*67e74705SXin Li                             BoundNodesTreeBuilder *Builder,
36*67e74705SXin Li                             ArrayRef<DynTypedMatcher> InnerMatchers);
37*67e74705SXin Li 
38*67e74705SXin Li bool AnyOfVariadicOperator(const ast_type_traits::DynTypedNode &DynNode,
39*67e74705SXin Li                            ASTMatchFinder *Finder,
40*67e74705SXin Li                            BoundNodesTreeBuilder *Builder,
41*67e74705SXin Li                            ArrayRef<DynTypedMatcher> InnerMatchers);
42*67e74705SXin Li 
43*67e74705SXin Li 
visitMatches(Visitor * ResultVisitor)44*67e74705SXin Li void BoundNodesTreeBuilder::visitMatches(Visitor *ResultVisitor) {
45*67e74705SXin Li   if (Bindings.empty())
46*67e74705SXin Li     Bindings.push_back(BoundNodesMap());
47*67e74705SXin Li   for (BoundNodesMap &Binding : Bindings) {
48*67e74705SXin Li     ResultVisitor->visitMatch(BoundNodes(Binding));
49*67e74705SXin Li   }
50*67e74705SXin Li }
51*67e74705SXin Li 
52*67e74705SXin Li namespace {
53*67e74705SXin Li 
54*67e74705SXin Li typedef bool (*VariadicOperatorFunction)(
55*67e74705SXin Li     const ast_type_traits::DynTypedNode &DynNode, ASTMatchFinder *Finder,
56*67e74705SXin Li     BoundNodesTreeBuilder *Builder, ArrayRef<DynTypedMatcher> InnerMatchers);
57*67e74705SXin Li 
58*67e74705SXin Li template <VariadicOperatorFunction Func>
59*67e74705SXin Li class VariadicMatcher : public DynMatcherInterface {
60*67e74705SXin Li public:
VariadicMatcher(std::vector<DynTypedMatcher> InnerMatchers)61*67e74705SXin Li   VariadicMatcher(std::vector<DynTypedMatcher> InnerMatchers)
62*67e74705SXin Li       : InnerMatchers(std::move(InnerMatchers)) {}
63*67e74705SXin Li 
dynMatches(const ast_type_traits::DynTypedNode & DynNode,ASTMatchFinder * Finder,BoundNodesTreeBuilder * Builder) const64*67e74705SXin Li   bool dynMatches(const ast_type_traits::DynTypedNode &DynNode,
65*67e74705SXin Li                   ASTMatchFinder *Finder,
66*67e74705SXin Li                   BoundNodesTreeBuilder *Builder) const override {
67*67e74705SXin Li     return Func(DynNode, Finder, Builder, InnerMatchers);
68*67e74705SXin Li   }
69*67e74705SXin Li 
70*67e74705SXin Li private:
71*67e74705SXin Li   std::vector<DynTypedMatcher> InnerMatchers;
72*67e74705SXin Li };
73*67e74705SXin Li 
74*67e74705SXin Li class IdDynMatcher : public DynMatcherInterface {
75*67e74705SXin Li  public:
IdDynMatcher(StringRef ID,const IntrusiveRefCntPtr<DynMatcherInterface> & InnerMatcher)76*67e74705SXin Li   IdDynMatcher(StringRef ID,
77*67e74705SXin Li                const IntrusiveRefCntPtr<DynMatcherInterface> &InnerMatcher)
78*67e74705SXin Li       : ID(ID), InnerMatcher(InnerMatcher) {}
79*67e74705SXin Li 
dynMatches(const ast_type_traits::DynTypedNode & DynNode,ASTMatchFinder * Finder,BoundNodesTreeBuilder * Builder) const80*67e74705SXin Li   bool dynMatches(const ast_type_traits::DynTypedNode &DynNode,
81*67e74705SXin Li                   ASTMatchFinder *Finder,
82*67e74705SXin Li                   BoundNodesTreeBuilder *Builder) const override {
83*67e74705SXin Li     bool Result = InnerMatcher->dynMatches(DynNode, Finder, Builder);
84*67e74705SXin Li     if (Result) Builder->setBinding(ID, DynNode);
85*67e74705SXin Li     return Result;
86*67e74705SXin Li   }
87*67e74705SXin Li 
88*67e74705SXin Li  private:
89*67e74705SXin Li   const std::string ID;
90*67e74705SXin Li   const IntrusiveRefCntPtr<DynMatcherInterface> InnerMatcher;
91*67e74705SXin Li };
92*67e74705SXin Li 
93*67e74705SXin Li /// \brief A matcher that always returns true.
94*67e74705SXin Li ///
95*67e74705SXin Li /// We only ever need one instance of this matcher, so we create a global one
96*67e74705SXin Li /// and reuse it to reduce the overhead of the matcher and increase the chance
97*67e74705SXin Li /// of cache hits.
98*67e74705SXin Li class TrueMatcherImpl : public DynMatcherInterface {
99*67e74705SXin Li public:
TrueMatcherImpl()100*67e74705SXin Li   TrueMatcherImpl() {
101*67e74705SXin Li     Retain(); // Reference count will never become zero.
102*67e74705SXin Li   }
dynMatches(const ast_type_traits::DynTypedNode &,ASTMatchFinder *,BoundNodesTreeBuilder *) const103*67e74705SXin Li   bool dynMatches(const ast_type_traits::DynTypedNode &, ASTMatchFinder *,
104*67e74705SXin Li                   BoundNodesTreeBuilder *) const override {
105*67e74705SXin Li     return true;
106*67e74705SXin Li   }
107*67e74705SXin Li };
108*67e74705SXin Li static llvm::ManagedStatic<TrueMatcherImpl> TrueMatcherInstance;
109*67e74705SXin Li 
110*67e74705SXin Li }  // namespace
111*67e74705SXin Li 
constructVariadic(DynTypedMatcher::VariadicOperator Op,ast_type_traits::ASTNodeKind SupportedKind,std::vector<DynTypedMatcher> InnerMatchers)112*67e74705SXin Li DynTypedMatcher DynTypedMatcher::constructVariadic(
113*67e74705SXin Li     DynTypedMatcher::VariadicOperator Op,
114*67e74705SXin Li     ast_type_traits::ASTNodeKind SupportedKind,
115*67e74705SXin Li     std::vector<DynTypedMatcher> InnerMatchers) {
116*67e74705SXin Li   assert(InnerMatchers.size() > 0 && "Array must not be empty.");
117*67e74705SXin Li   assert(std::all_of(InnerMatchers.begin(), InnerMatchers.end(),
118*67e74705SXin Li                      [SupportedKind](const DynTypedMatcher &M) {
119*67e74705SXin Li                        return M.canConvertTo(SupportedKind);
120*67e74705SXin Li                      }) &&
121*67e74705SXin Li          "InnerMatchers must be convertible to SupportedKind!");
122*67e74705SXin Li 
123*67e74705SXin Li   // We must relax the restrict kind here.
124*67e74705SXin Li   // The different operators might deal differently with a mismatch.
125*67e74705SXin Li   // Make it the same as SupportedKind, since that is the broadest type we are
126*67e74705SXin Li   // allowed to accept.
127*67e74705SXin Li   auto RestrictKind = SupportedKind;
128*67e74705SXin Li 
129*67e74705SXin Li   switch (Op) {
130*67e74705SXin Li   case VO_AllOf:
131*67e74705SXin Li     // In the case of allOf() we must pass all the checks, so making
132*67e74705SXin Li     // RestrictKind the most restrictive can save us time. This way we reject
133*67e74705SXin Li     // invalid types earlier and we can elide the kind checks inside the
134*67e74705SXin Li     // matcher.
135*67e74705SXin Li     for (auto &IM : InnerMatchers) {
136*67e74705SXin Li       RestrictKind = ast_type_traits::ASTNodeKind::getMostDerivedType(
137*67e74705SXin Li           RestrictKind, IM.RestrictKind);
138*67e74705SXin Li     }
139*67e74705SXin Li     return DynTypedMatcher(
140*67e74705SXin Li         SupportedKind, RestrictKind,
141*67e74705SXin Li         new VariadicMatcher<AllOfVariadicOperator>(std::move(InnerMatchers)));
142*67e74705SXin Li 
143*67e74705SXin Li   case VO_AnyOf:
144*67e74705SXin Li     return DynTypedMatcher(
145*67e74705SXin Li         SupportedKind, RestrictKind,
146*67e74705SXin Li         new VariadicMatcher<AnyOfVariadicOperator>(std::move(InnerMatchers)));
147*67e74705SXin Li 
148*67e74705SXin Li   case VO_EachOf:
149*67e74705SXin Li     return DynTypedMatcher(
150*67e74705SXin Li         SupportedKind, RestrictKind,
151*67e74705SXin Li         new VariadicMatcher<EachOfVariadicOperator>(std::move(InnerMatchers)));
152*67e74705SXin Li 
153*67e74705SXin Li   case VO_UnaryNot:
154*67e74705SXin Li     // FIXME: Implement the Not operator to take a single matcher instead of a
155*67e74705SXin Li     // vector.
156*67e74705SXin Li     return DynTypedMatcher(
157*67e74705SXin Li         SupportedKind, RestrictKind,
158*67e74705SXin Li         new VariadicMatcher<NotUnaryOperator>(std::move(InnerMatchers)));
159*67e74705SXin Li   }
160*67e74705SXin Li   llvm_unreachable("Invalid Op value.");
161*67e74705SXin Li }
162*67e74705SXin Li 
trueMatcher(ast_type_traits::ASTNodeKind NodeKind)163*67e74705SXin Li DynTypedMatcher DynTypedMatcher::trueMatcher(
164*67e74705SXin Li     ast_type_traits::ASTNodeKind NodeKind) {
165*67e74705SXin Li   return DynTypedMatcher(NodeKind, NodeKind, &*TrueMatcherInstance);
166*67e74705SXin Li }
167*67e74705SXin Li 
canMatchNodesOfKind(ast_type_traits::ASTNodeKind Kind) const168*67e74705SXin Li bool DynTypedMatcher::canMatchNodesOfKind(
169*67e74705SXin Li     ast_type_traits::ASTNodeKind Kind) const {
170*67e74705SXin Li   return RestrictKind.isBaseOf(Kind);
171*67e74705SXin Li }
172*67e74705SXin Li 
dynCastTo(const ast_type_traits::ASTNodeKind Kind) const173*67e74705SXin Li DynTypedMatcher DynTypedMatcher::dynCastTo(
174*67e74705SXin Li     const ast_type_traits::ASTNodeKind Kind) const {
175*67e74705SXin Li   auto Copy = *this;
176*67e74705SXin Li   Copy.SupportedKind = Kind;
177*67e74705SXin Li   Copy.RestrictKind =
178*67e74705SXin Li       ast_type_traits::ASTNodeKind::getMostDerivedType(Kind, RestrictKind);
179*67e74705SXin Li   return Copy;
180*67e74705SXin Li }
181*67e74705SXin Li 
matches(const ast_type_traits::DynTypedNode & DynNode,ASTMatchFinder * Finder,BoundNodesTreeBuilder * Builder) const182*67e74705SXin Li bool DynTypedMatcher::matches(const ast_type_traits::DynTypedNode &DynNode,
183*67e74705SXin Li                               ASTMatchFinder *Finder,
184*67e74705SXin Li                               BoundNodesTreeBuilder *Builder) const {
185*67e74705SXin Li   if (RestrictKind.isBaseOf(DynNode.getNodeKind()) &&
186*67e74705SXin Li       Implementation->dynMatches(DynNode, Finder, Builder)) {
187*67e74705SXin Li     return true;
188*67e74705SXin Li   }
189*67e74705SXin Li   // Delete all bindings when a matcher does not match.
190*67e74705SXin Li   // This prevents unexpected exposure of bound nodes in unmatches
191*67e74705SXin Li   // branches of the match tree.
192*67e74705SXin Li   Builder->removeBindings([](const BoundNodesMap &) { return true; });
193*67e74705SXin Li   return false;
194*67e74705SXin Li }
195*67e74705SXin Li 
matchesNoKindCheck(const ast_type_traits::DynTypedNode & DynNode,ASTMatchFinder * Finder,BoundNodesTreeBuilder * Builder) const196*67e74705SXin Li bool DynTypedMatcher::matchesNoKindCheck(
197*67e74705SXin Li     const ast_type_traits::DynTypedNode &DynNode, ASTMatchFinder *Finder,
198*67e74705SXin Li     BoundNodesTreeBuilder *Builder) const {
199*67e74705SXin Li   assert(RestrictKind.isBaseOf(DynNode.getNodeKind()));
200*67e74705SXin Li   if (Implementation->dynMatches(DynNode, Finder, Builder)) {
201*67e74705SXin Li     return true;
202*67e74705SXin Li   }
203*67e74705SXin Li   // Delete all bindings when a matcher does not match.
204*67e74705SXin Li   // This prevents unexpected exposure of bound nodes in unmatches
205*67e74705SXin Li   // branches of the match tree.
206*67e74705SXin Li   Builder->removeBindings([](const BoundNodesMap &) { return true; });
207*67e74705SXin Li   return false;
208*67e74705SXin Li }
209*67e74705SXin Li 
tryBind(StringRef ID) const210*67e74705SXin Li llvm::Optional<DynTypedMatcher> DynTypedMatcher::tryBind(StringRef ID) const {
211*67e74705SXin Li   if (!AllowBind) return llvm::None;
212*67e74705SXin Li   auto Result = *this;
213*67e74705SXin Li   Result.Implementation = new IdDynMatcher(ID, Result.Implementation);
214*67e74705SXin Li   return Result;
215*67e74705SXin Li }
216*67e74705SXin Li 
canConvertTo(ast_type_traits::ASTNodeKind To) const217*67e74705SXin Li bool DynTypedMatcher::canConvertTo(ast_type_traits::ASTNodeKind To) const {
218*67e74705SXin Li   const auto From = getSupportedKind();
219*67e74705SXin Li   auto QualKind = ast_type_traits::ASTNodeKind::getFromNodeKind<QualType>();
220*67e74705SXin Li   auto TypeKind = ast_type_traits::ASTNodeKind::getFromNodeKind<Type>();
221*67e74705SXin Li   /// Mimic the implicit conversions of Matcher<>.
222*67e74705SXin Li   /// - From Matcher<Type> to Matcher<QualType>
223*67e74705SXin Li   if (From.isSame(TypeKind) && To.isSame(QualKind)) return true;
224*67e74705SXin Li   /// - From Matcher<Base> to Matcher<Derived>
225*67e74705SXin Li   return From.isBaseOf(To);
226*67e74705SXin Li }
227*67e74705SXin Li 
addMatch(const BoundNodesTreeBuilder & Other)228*67e74705SXin Li void BoundNodesTreeBuilder::addMatch(const BoundNodesTreeBuilder &Other) {
229*67e74705SXin Li   Bindings.append(Other.Bindings.begin(), Other.Bindings.end());
230*67e74705SXin Li }
231*67e74705SXin Li 
NotUnaryOperator(const ast_type_traits::DynTypedNode & DynNode,ASTMatchFinder * Finder,BoundNodesTreeBuilder * Builder,ArrayRef<DynTypedMatcher> InnerMatchers)232*67e74705SXin Li bool NotUnaryOperator(const ast_type_traits::DynTypedNode &DynNode,
233*67e74705SXin Li                       ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder,
234*67e74705SXin Li                       ArrayRef<DynTypedMatcher> InnerMatchers) {
235*67e74705SXin Li   if (InnerMatchers.size() != 1)
236*67e74705SXin Li     return false;
237*67e74705SXin Li 
238*67e74705SXin Li   // The 'unless' matcher will always discard the result:
239*67e74705SXin Li   // If the inner matcher doesn't match, unless returns true,
240*67e74705SXin Li   // but the inner matcher cannot have bound anything.
241*67e74705SXin Li   // If the inner matcher matches, the result is false, and
242*67e74705SXin Li   // any possible binding will be discarded.
243*67e74705SXin Li   // We still need to hand in all the bound nodes up to this
244*67e74705SXin Li   // point so the inner matcher can depend on bound nodes,
245*67e74705SXin Li   // and we need to actively discard the bound nodes, otherwise
246*67e74705SXin Li   // the inner matcher will reset the bound nodes if it doesn't
247*67e74705SXin Li   // match, but this would be inversed by 'unless'.
248*67e74705SXin Li   BoundNodesTreeBuilder Discard(*Builder);
249*67e74705SXin Li   return !InnerMatchers[0].matches(DynNode, Finder, &Discard);
250*67e74705SXin Li }
251*67e74705SXin Li 
AllOfVariadicOperator(const ast_type_traits::DynTypedNode & DynNode,ASTMatchFinder * Finder,BoundNodesTreeBuilder * Builder,ArrayRef<DynTypedMatcher> InnerMatchers)252*67e74705SXin Li bool AllOfVariadicOperator(const ast_type_traits::DynTypedNode &DynNode,
253*67e74705SXin Li                            ASTMatchFinder *Finder,
254*67e74705SXin Li                            BoundNodesTreeBuilder *Builder,
255*67e74705SXin Li                            ArrayRef<DynTypedMatcher> InnerMatchers) {
256*67e74705SXin Li   // allOf leads to one matcher for each alternative in the first
257*67e74705SXin Li   // matcher combined with each alternative in the second matcher.
258*67e74705SXin Li   // Thus, we can reuse the same Builder.
259*67e74705SXin Li   for (const DynTypedMatcher &InnerMatcher : InnerMatchers) {
260*67e74705SXin Li     if (!InnerMatcher.matchesNoKindCheck(DynNode, Finder, Builder))
261*67e74705SXin Li       return false;
262*67e74705SXin Li   }
263*67e74705SXin Li   return true;
264*67e74705SXin Li }
265*67e74705SXin Li 
EachOfVariadicOperator(const ast_type_traits::DynTypedNode & DynNode,ASTMatchFinder * Finder,BoundNodesTreeBuilder * Builder,ArrayRef<DynTypedMatcher> InnerMatchers)266*67e74705SXin Li bool EachOfVariadicOperator(const ast_type_traits::DynTypedNode &DynNode,
267*67e74705SXin Li                             ASTMatchFinder *Finder,
268*67e74705SXin Li                             BoundNodesTreeBuilder *Builder,
269*67e74705SXin Li                             ArrayRef<DynTypedMatcher> InnerMatchers) {
270*67e74705SXin Li   BoundNodesTreeBuilder Result;
271*67e74705SXin Li   bool Matched = false;
272*67e74705SXin Li   for (const DynTypedMatcher &InnerMatcher : InnerMatchers) {
273*67e74705SXin Li     BoundNodesTreeBuilder BuilderInner(*Builder);
274*67e74705SXin Li     if (InnerMatcher.matches(DynNode, Finder, &BuilderInner)) {
275*67e74705SXin Li       Matched = true;
276*67e74705SXin Li       Result.addMatch(BuilderInner);
277*67e74705SXin Li     }
278*67e74705SXin Li   }
279*67e74705SXin Li   *Builder = std::move(Result);
280*67e74705SXin Li   return Matched;
281*67e74705SXin Li }
282*67e74705SXin Li 
AnyOfVariadicOperator(const ast_type_traits::DynTypedNode & DynNode,ASTMatchFinder * Finder,BoundNodesTreeBuilder * Builder,ArrayRef<DynTypedMatcher> InnerMatchers)283*67e74705SXin Li bool AnyOfVariadicOperator(const ast_type_traits::DynTypedNode &DynNode,
284*67e74705SXin Li                            ASTMatchFinder *Finder,
285*67e74705SXin Li                            BoundNodesTreeBuilder *Builder,
286*67e74705SXin Li                            ArrayRef<DynTypedMatcher> InnerMatchers) {
287*67e74705SXin Li   for (const DynTypedMatcher &InnerMatcher : InnerMatchers) {
288*67e74705SXin Li     BoundNodesTreeBuilder Result = *Builder;
289*67e74705SXin Li     if (InnerMatcher.matches(DynNode, Finder, &Result)) {
290*67e74705SXin Li       *Builder = std::move(Result);
291*67e74705SXin Li       return true;
292*67e74705SXin Li     }
293*67e74705SXin Li   }
294*67e74705SXin Li   return false;
295*67e74705SXin Li }
296*67e74705SXin Li 
hasAnyNameFunc(ArrayRef<const StringRef * > NameRefs)297*67e74705SXin Li Matcher<NamedDecl> hasAnyNameFunc(ArrayRef<const StringRef *> NameRefs) {
298*67e74705SXin Li   std::vector<std::string> Names;
299*67e74705SXin Li   for (auto *Name : NameRefs)
300*67e74705SXin Li     Names.emplace_back(*Name);
301*67e74705SXin Li   return internal::Matcher<NamedDecl>(
302*67e74705SXin Li       new internal::HasNameMatcher(std::move(Names)));
303*67e74705SXin Li }
304*67e74705SXin Li 
HasNameMatcher(std::vector<std::string> N)305*67e74705SXin Li HasNameMatcher::HasNameMatcher(std::vector<std::string> N)
306*67e74705SXin Li     : UseUnqualifiedMatch(std::all_of(
307*67e74705SXin Li           N.begin(), N.end(),
308*67e74705SXin Li           [](StringRef Name) { return Name.find("::") == Name.npos; })),
309*67e74705SXin Li       Names(std::move(N)) {
310*67e74705SXin Li #ifndef NDEBUG
311*67e74705SXin Li   for (StringRef Name : Names)
312*67e74705SXin Li     assert(!Name.empty());
313*67e74705SXin Li #endif
314*67e74705SXin Li }
315*67e74705SXin Li 
316*67e74705SXin Li namespace {
317*67e74705SXin Li 
consumeNameSuffix(StringRef & FullName,StringRef Suffix)318*67e74705SXin Li bool consumeNameSuffix(StringRef &FullName, StringRef Suffix) {
319*67e74705SXin Li   StringRef Name = FullName;
320*67e74705SXin Li   if (!Name.endswith(Suffix))
321*67e74705SXin Li     return false;
322*67e74705SXin Li   Name = Name.drop_back(Suffix.size());
323*67e74705SXin Li   if (!Name.empty()) {
324*67e74705SXin Li     if (!Name.endswith("::"))
325*67e74705SXin Li       return false;
326*67e74705SXin Li     Name = Name.drop_back(2);
327*67e74705SXin Li   }
328*67e74705SXin Li   FullName = Name;
329*67e74705SXin Li   return true;
330*67e74705SXin Li }
331*67e74705SXin Li 
getNodeName(const NamedDecl & Node,llvm::SmallString<128> & Scratch)332*67e74705SXin Li StringRef getNodeName(const NamedDecl &Node, llvm::SmallString<128> &Scratch) {
333*67e74705SXin Li   // Simple name.
334*67e74705SXin Li   if (Node.getIdentifier())
335*67e74705SXin Li     return Node.getName();
336*67e74705SXin Li 
337*67e74705SXin Li   if (Node.getDeclName()) {
338*67e74705SXin Li     // Name needs to be constructed.
339*67e74705SXin Li     Scratch.clear();
340*67e74705SXin Li     llvm::raw_svector_ostream OS(Scratch);
341*67e74705SXin Li     Node.printName(OS);
342*67e74705SXin Li     return OS.str();
343*67e74705SXin Li   }
344*67e74705SXin Li 
345*67e74705SXin Li   return "(anonymous)";
346*67e74705SXin Li }
347*67e74705SXin Li 
getNodeName(const RecordDecl & Node,llvm::SmallString<128> & Scratch)348*67e74705SXin Li StringRef getNodeName(const RecordDecl &Node, llvm::SmallString<128> &Scratch) {
349*67e74705SXin Li   if (Node.getIdentifier()) {
350*67e74705SXin Li     return Node.getName();
351*67e74705SXin Li   }
352*67e74705SXin Li   Scratch.clear();
353*67e74705SXin Li   return ("(anonymous " + Node.getKindName() + ")").toStringRef(Scratch);
354*67e74705SXin Li }
355*67e74705SXin Li 
getNodeName(const NamespaceDecl & Node,llvm::SmallString<128> & Scratch)356*67e74705SXin Li StringRef getNodeName(const NamespaceDecl &Node,
357*67e74705SXin Li                       llvm::SmallString<128> &Scratch) {
358*67e74705SXin Li   return Node.isAnonymousNamespace() ? "(anonymous namespace)" : Node.getName();
359*67e74705SXin Li }
360*67e74705SXin Li 
361*67e74705SXin Li 
362*67e74705SXin Li class PatternSet {
363*67e74705SXin Li public:
PatternSet(ArrayRef<std::string> Names)364*67e74705SXin Li   PatternSet(ArrayRef<std::string> Names) {
365*67e74705SXin Li     for (StringRef Name : Names)
366*67e74705SXin Li       Patterns.push_back({Name, Name.startswith("::")});
367*67e74705SXin Li   }
368*67e74705SXin Li 
369*67e74705SXin Li   /// Consumes the name suffix from each pattern in the set and removes the ones
370*67e74705SXin Li   /// that didn't match.
371*67e74705SXin Li   /// Return true if there are still any patterns left.
consumeNameSuffix(StringRef NodeName,bool CanSkip)372*67e74705SXin Li   bool consumeNameSuffix(StringRef NodeName, bool CanSkip) {
373*67e74705SXin Li     for (size_t I = 0; I < Patterns.size();) {
374*67e74705SXin Li       if (internal::consumeNameSuffix(Patterns[I].P, NodeName) ||
375*67e74705SXin Li           CanSkip) {
376*67e74705SXin Li         ++I;
377*67e74705SXin Li       } else {
378*67e74705SXin Li         Patterns.erase(Patterns.begin() + I);
379*67e74705SXin Li       }
380*67e74705SXin Li     }
381*67e74705SXin Li     return !Patterns.empty();
382*67e74705SXin Li   }
383*67e74705SXin Li 
384*67e74705SXin Li   /// Check if any of the patterns are a match.
385*67e74705SXin Li   /// A match will be a pattern that was fully consumed, that also matches the
386*67e74705SXin Li   /// 'fully qualified' requirement.
foundMatch(bool AllowFullyQualified) const387*67e74705SXin Li   bool foundMatch(bool AllowFullyQualified) const {
388*67e74705SXin Li     for (auto& P: Patterns)
389*67e74705SXin Li       if (P.P.empty() && (AllowFullyQualified || !P.IsFullyQualified))
390*67e74705SXin Li         return true;
391*67e74705SXin Li     return false;
392*67e74705SXin Li   }
393*67e74705SXin Li 
394*67e74705SXin Li private:
395*67e74705SXin Li   struct Pattern {
396*67e74705SXin Li     StringRef P;
397*67e74705SXin Li     bool IsFullyQualified;
398*67e74705SXin Li   };
399*67e74705SXin Li   llvm::SmallVector<Pattern, 8> Patterns;
400*67e74705SXin Li };
401*67e74705SXin Li 
402*67e74705SXin Li }  // namespace
403*67e74705SXin Li 
matchesNodeUnqualified(const NamedDecl & Node) const404*67e74705SXin Li bool HasNameMatcher::matchesNodeUnqualified(const NamedDecl &Node) const {
405*67e74705SXin Li   assert(UseUnqualifiedMatch);
406*67e74705SXin Li   llvm::SmallString<128> Scratch;
407*67e74705SXin Li   StringRef NodeName = getNodeName(Node, Scratch);
408*67e74705SXin Li   return std::any_of(Names.begin(), Names.end(), [&](StringRef Name) {
409*67e74705SXin Li     return consumeNameSuffix(Name, NodeName) && Name.empty();
410*67e74705SXin Li   });
411*67e74705SXin Li }
412*67e74705SXin Li 
matchesNodeFullFast(const NamedDecl & Node) const413*67e74705SXin Li bool HasNameMatcher::matchesNodeFullFast(const NamedDecl &Node) const {
414*67e74705SXin Li   PatternSet Patterns(Names);
415*67e74705SXin Li   llvm::SmallString<128> Scratch;
416*67e74705SXin Li 
417*67e74705SXin Li   // This function is copied and adapted from NamedDecl::printQualifiedName()
418*67e74705SXin Li   // By matching each part individually we optimize in a couple of ways:
419*67e74705SXin Li   //  - We can exit early on the first failure.
420*67e74705SXin Li   //  - We can skip inline/anonymous namespaces without another pass.
421*67e74705SXin Li   //  - We print one name at a time, reducing the chance of overflowing the
422*67e74705SXin Li   //    inlined space of the SmallString.
423*67e74705SXin Li 
424*67e74705SXin Li   // First, match the name.
425*67e74705SXin Li   if (!Patterns.consumeNameSuffix(getNodeName(Node, Scratch),
426*67e74705SXin Li                                   /*CanSkip=*/false))
427*67e74705SXin Li     return false;
428*67e74705SXin Li 
429*67e74705SXin Li   // Try to match each declaration context.
430*67e74705SXin Li   // We are allowed to skip anonymous and inline namespaces if they don't match.
431*67e74705SXin Li   const DeclContext *Ctx = Node.getDeclContext();
432*67e74705SXin Li 
433*67e74705SXin Li   if (Ctx->isFunctionOrMethod())
434*67e74705SXin Li     return Patterns.foundMatch(/*AllowFullyQualified=*/false);
435*67e74705SXin Li 
436*67e74705SXin Li   for (; Ctx && isa<NamedDecl>(Ctx); Ctx = Ctx->getParent()) {
437*67e74705SXin Li     if (Patterns.foundMatch(/*AllowFullyQualified=*/false))
438*67e74705SXin Li       return true;
439*67e74705SXin Li 
440*67e74705SXin Li     if (const auto *ND = dyn_cast<NamespaceDecl>(Ctx)) {
441*67e74705SXin Li       // If it matches (or we can skip it), continue.
442*67e74705SXin Li       if (Patterns.consumeNameSuffix(getNodeName(*ND, Scratch),
443*67e74705SXin Li                                      /*CanSkip=*/ND->isAnonymousNamespace() ||
444*67e74705SXin Li                                          ND->isInline()))
445*67e74705SXin Li         continue;
446*67e74705SXin Li       return false;
447*67e74705SXin Li     }
448*67e74705SXin Li     if (const auto *RD = dyn_cast<RecordDecl>(Ctx)) {
449*67e74705SXin Li       if (!isa<ClassTemplateSpecializationDecl>(Ctx)) {
450*67e74705SXin Li         if (Patterns.consumeNameSuffix(getNodeName(*RD, Scratch),
451*67e74705SXin Li                                        /*CanSkip=*/false))
452*67e74705SXin Li           continue;
453*67e74705SXin Li 
454*67e74705SXin Li         return false;
455*67e74705SXin Li       }
456*67e74705SXin Li     }
457*67e74705SXin Li 
458*67e74705SXin Li     // We don't know how to deal with this DeclContext.
459*67e74705SXin Li     // Fallback to the slow version of the code.
460*67e74705SXin Li     return matchesNodeFullSlow(Node);
461*67e74705SXin Li   }
462*67e74705SXin Li 
463*67e74705SXin Li   return Patterns.foundMatch(/*AllowFullyQualified=*/true);
464*67e74705SXin Li }
465*67e74705SXin Li 
matchesNodeFullSlow(const NamedDecl & Node) const466*67e74705SXin Li bool HasNameMatcher::matchesNodeFullSlow(const NamedDecl &Node) const {
467*67e74705SXin Li   const bool SkipUnwrittenCases[] = {false, true};
468*67e74705SXin Li   for (bool SkipUnwritten : SkipUnwrittenCases) {
469*67e74705SXin Li     llvm::SmallString<128> NodeName = StringRef("::");
470*67e74705SXin Li     llvm::raw_svector_ostream OS(NodeName);
471*67e74705SXin Li 
472*67e74705SXin Li     if (SkipUnwritten) {
473*67e74705SXin Li       PrintingPolicy Policy = Node.getASTContext().getPrintingPolicy();
474*67e74705SXin Li       Policy.SuppressUnwrittenScope = true;
475*67e74705SXin Li       Node.printQualifiedName(OS, Policy);
476*67e74705SXin Li     } else {
477*67e74705SXin Li       Node.printQualifiedName(OS);
478*67e74705SXin Li     }
479*67e74705SXin Li 
480*67e74705SXin Li     const StringRef FullName = OS.str();
481*67e74705SXin Li 
482*67e74705SXin Li     for (const StringRef Pattern : Names) {
483*67e74705SXin Li       if (Pattern.startswith("::")) {
484*67e74705SXin Li         if (FullName == Pattern)
485*67e74705SXin Li           return true;
486*67e74705SXin Li       } else if (FullName.endswith(Pattern) &&
487*67e74705SXin Li                  FullName.drop_back(Pattern.size()).endswith("::")) {
488*67e74705SXin Li         return true;
489*67e74705SXin Li       }
490*67e74705SXin Li     }
491*67e74705SXin Li   }
492*67e74705SXin Li 
493*67e74705SXin Li   return false;
494*67e74705SXin Li }
495*67e74705SXin Li 
matchesNode(const NamedDecl & Node) const496*67e74705SXin Li bool HasNameMatcher::matchesNode(const NamedDecl &Node) const {
497*67e74705SXin Li   assert(matchesNodeFullFast(Node) == matchesNodeFullSlow(Node));
498*67e74705SXin Li   if (UseUnqualifiedMatch) {
499*67e74705SXin Li     assert(matchesNodeUnqualified(Node) == matchesNodeFullFast(Node));
500*67e74705SXin Li     return matchesNodeUnqualified(Node);
501*67e74705SXin Li   }
502*67e74705SXin Li   return matchesNodeFullFast(Node);
503*67e74705SXin Li }
504*67e74705SXin Li 
505*67e74705SXin Li } // end namespace internal
506*67e74705SXin Li } // end namespace ast_matchers
507*67e74705SXin Li } // end namespace clang
508