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