blob: 06ec76753bdf2a9e81a4e0ec20aa88d0006c6a14 [file] [log] [blame]
Manuel Klimek04616e42012-07-06 05:48:52 +00001//===--- ASTMatchersInternal.cpp - Structural query framework -------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// Implements the base layer of the matcher framework.
11//
12//===----------------------------------------------------------------------===//
13
14#include "clang/ASTMatchers/ASTMatchers.h"
15#include "clang/ASTMatchers/ASTMatchersInternal.h"
Samuel Benzaquen8513d622014-10-15 14:58:46 +000016#include "llvm/ADT/SmallString.h"
Samuel Benzaquen96039d72014-10-09 19:28:18 +000017#include "llvm/Support/ManagedStatic.h"
Manuel Klimek04616e42012-07-06 05:48:52 +000018
19namespace clang {
20namespace ast_matchers {
21namespace internal {
22
Manuel Klimeka0c025f2013-06-19 15:42:45 +000023void BoundNodesTreeBuilder::visitMatches(Visitor *ResultVisitor) {
24 if (Bindings.empty())
25 Bindings.push_back(BoundNodesMap());
Benjamin Kramer79f15902014-10-24 13:29:15 +000026 for (BoundNodesMap &Binding : Bindings) {
27 ResultVisitor->visitMatch(BoundNodes(Binding));
Manuel Klimek021d56f2012-08-28 23:26:39 +000028 }
29}
30
Samuel Benzaquenf28d9972014-10-01 15:08:07 +000031namespace {
32
33class VariadicMatcher : public DynMatcherInterface {
34 public:
35 VariadicMatcher(VariadicOperatorFunction Func,
36 std::vector<DynTypedMatcher> InnerMatchers)
37 : Func(Func), InnerMatchers(std::move(InnerMatchers)) {}
38
39 bool dynMatches(const ast_type_traits::DynTypedNode &DynNode,
40 ASTMatchFinder *Finder,
41 BoundNodesTreeBuilder *Builder) const override {
42 return Func(DynNode, Finder, Builder, InnerMatchers);
43 }
44
45 private:
46 VariadicOperatorFunction Func;
47 std::vector<DynTypedMatcher> InnerMatchers;
48};
49
50class IdDynMatcher : public DynMatcherInterface {
51 public:
52 IdDynMatcher(StringRef ID,
53 const IntrusiveRefCntPtr<DynMatcherInterface> &InnerMatcher)
54 : ID(ID), InnerMatcher(InnerMatcher) {}
55
56 bool dynMatches(const ast_type_traits::DynTypedNode &DynNode,
57 ASTMatchFinder *Finder,
58 BoundNodesTreeBuilder *Builder) const override {
59 bool Result = InnerMatcher->dynMatches(DynNode, Finder, Builder);
60 if (Result) Builder->setBinding(ID, DynNode);
61 return Result;
62 }
63
64 private:
65 const std::string ID;
66 const IntrusiveRefCntPtr<DynMatcherInterface> InnerMatcher;
67};
68
Samuel Benzaquen96039d72014-10-09 19:28:18 +000069/// \brief A matcher that always returns true.
70///
71/// We only ever need one instance of this matcher, so we create a global one
72/// and reuse it to reduce the overhead of the matcher and increase the chance
73/// of cache hits.
Benjamin Kramer967c0792014-10-24 13:29:21 +000074class TrueMatcherImpl : public DynMatcherInterface {
75public:
76 TrueMatcherImpl() {
77 Retain(); // Reference count will never become zero.
78 }
79 bool dynMatches(const ast_type_traits::DynTypedNode &, ASTMatchFinder *,
80 BoundNodesTreeBuilder *) const override {
81 return true;
82 }
Samuel Benzaquen96039d72014-10-09 19:28:18 +000083};
84static llvm::ManagedStatic<TrueMatcherImpl> TrueMatcherInstance;
85
Samuel Benzaquenf28d9972014-10-01 15:08:07 +000086} // namespace
87
88DynTypedMatcher DynTypedMatcher::constructVariadic(
89 VariadicOperatorFunction Func, std::vector<DynTypedMatcher> InnerMatchers) {
90 assert(InnerMatchers.size() > 0 && "Array must not be empty.");
Samuel Benzaquen20099602014-10-13 17:38:12 +000091 assert(std::all_of(InnerMatchers.begin(), InnerMatchers.end(),
92 [&InnerMatchers](const DynTypedMatcher &M) {
93 return InnerMatchers[0].SupportedKind.isSame(M.SupportedKind);
94 }) &&
95 "SupportedKind must match!");
96
97 // We must relax the restrict kind here.
98 // The different operators might deal differently with a mismatch.
99 // Make it the same as SupportedKind, since that is the broadest type we are
100 // allowed to accept.
Samuel Benzaquen193d87f2014-10-13 18:17:11 +0000101 auto SupportedKind = InnerMatchers[0].SupportedKind;
102 return DynTypedMatcher(SupportedKind, SupportedKind,
Samuel Benzaquen20099602014-10-13 17:38:12 +0000103 new VariadicMatcher(Func, std::move(InnerMatchers)));
Samuel Benzaquenf28d9972014-10-01 15:08:07 +0000104}
105
Samuel Benzaquen96039d72014-10-09 19:28:18 +0000106DynTypedMatcher DynTypedMatcher::trueMatcher(
107 ast_type_traits::ASTNodeKind NodeKind) {
Benjamin Kramer967c0792014-10-24 13:29:21 +0000108 return DynTypedMatcher(NodeKind, NodeKind, &*TrueMatcherInstance);
Samuel Benzaquen96039d72014-10-09 19:28:18 +0000109}
110
Samuel Benzaquenf28d9972014-10-01 15:08:07 +0000111DynTypedMatcher DynTypedMatcher::dynCastTo(
112 const ast_type_traits::ASTNodeKind Kind) const {
113 auto Copy = *this;
114 Copy.SupportedKind = Kind;
Samuel Benzaquena1170022014-10-06 13:14:30 +0000115 Copy.RestrictKind =
116 ast_type_traits::ASTNodeKind::getMostDerivedType(Kind, RestrictKind);
Samuel Benzaquenf28d9972014-10-01 15:08:07 +0000117 return Copy;
118}
119
120bool DynTypedMatcher::matches(const ast_type_traits::DynTypedNode &DynNode,
121 ASTMatchFinder *Finder,
122 BoundNodesTreeBuilder *Builder) const {
123 if (RestrictKind.isBaseOf(DynNode.getNodeKind()) &&
124 Implementation->dynMatches(DynNode, Finder, Builder)) {
125 return true;
126 }
127 // Delete all bindings when a matcher does not match.
128 // This prevents unexpected exposure of bound nodes in unmatches
129 // branches of the match tree.
130 Builder->removeBindings([](const BoundNodesMap &) { return true; });
131 return false;
132}
133
134llvm::Optional<DynTypedMatcher> DynTypedMatcher::tryBind(StringRef ID) const {
135 if (!AllowBind) return llvm::None;
136 auto Result = *this;
137 Result.Implementation = new IdDynMatcher(ID, Result.Implementation);
138 return Result;
139}
140
Samuel Benzaquenab005ed2014-09-04 14:13:58 +0000141bool DynTypedMatcher::canConvertTo(ast_type_traits::ASTNodeKind To) const {
142 const auto From = getSupportedKind();
143 auto QualKind = ast_type_traits::ASTNodeKind::getFromNodeKind<QualType>();
144 auto TypeKind = ast_type_traits::ASTNodeKind::getFromNodeKind<Type>();
145 /// Mimic the implicit conversions of Matcher<>.
146 /// - From Matcher<Type> to Matcher<QualType>
147 if (From.isSame(TypeKind) && To.isSame(QualKind)) return true;
148 /// - From Matcher<Base> to Matcher<Derived>
149 return From.isBaseOf(To);
150}
151
Manuel Klimeka0c025f2013-06-19 15:42:45 +0000152void BoundNodesTreeBuilder::addMatch(const BoundNodesTreeBuilder &Other) {
Benjamin Kramer79f15902014-10-24 13:29:15 +0000153 Bindings.append(Other.Bindings.begin(), Other.Bindings.end());
Manuel Klimek021d56f2012-08-28 23:26:39 +0000154}
155
Samuel Benzaquen4d058742013-11-22 14:41:48 +0000156bool NotUnaryOperator(const ast_type_traits::DynTypedNode DynNode,
157 ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder,
158 ArrayRef<DynTypedMatcher> InnerMatchers) {
159 if (InnerMatchers.size() != 1)
160 return false;
161
162 // The 'unless' matcher will always discard the result:
163 // If the inner matcher doesn't match, unless returns true,
164 // but the inner matcher cannot have bound anything.
165 // If the inner matcher matches, the result is false, and
166 // any possible binding will be discarded.
167 // We still need to hand in all the bound nodes up to this
168 // point so the inner matcher can depend on bound nodes,
169 // and we need to actively discard the bound nodes, otherwise
170 // the inner matcher will reset the bound nodes if it doesn't
171 // match, but this would be inversed by 'unless'.
172 BoundNodesTreeBuilder Discard(*Builder);
173 return !InnerMatchers[0].matches(DynNode, Finder, &Discard);
174}
175
Samuel Benzaquen85ec25d2013-08-27 15:11:16 +0000176bool AllOfVariadicOperator(const ast_type_traits::DynTypedNode DynNode,
177 ASTMatchFinder *Finder,
178 BoundNodesTreeBuilder *Builder,
Samuel Benzaquenf34ac3e2013-10-29 14:37:15 +0000179 ArrayRef<DynTypedMatcher> InnerMatchers) {
Samuel Benzaquen85ec25d2013-08-27 15:11:16 +0000180 // allOf leads to one matcher for each alternative in the first
181 // matcher combined with each alternative in the second matcher.
182 // Thus, we can reuse the same Builder.
Benjamin Kramer79f15902014-10-24 13:29:15 +0000183 for (const DynTypedMatcher &InnerMatcher : InnerMatchers) {
184 if (!InnerMatcher.matches(DynNode, Finder, Builder))
Samuel Benzaquen85ec25d2013-08-27 15:11:16 +0000185 return false;
186 }
187 return true;
188}
189
190bool EachOfVariadicOperator(const ast_type_traits::DynTypedNode DynNode,
191 ASTMatchFinder *Finder,
192 BoundNodesTreeBuilder *Builder,
Samuel Benzaquenf34ac3e2013-10-29 14:37:15 +0000193 ArrayRef<DynTypedMatcher> InnerMatchers) {
Samuel Benzaquen85ec25d2013-08-27 15:11:16 +0000194 BoundNodesTreeBuilder Result;
195 bool Matched = false;
Benjamin Kramer79f15902014-10-24 13:29:15 +0000196 for (const DynTypedMatcher &InnerMatcher : InnerMatchers) {
Samuel Benzaquen85ec25d2013-08-27 15:11:16 +0000197 BoundNodesTreeBuilder BuilderInner(*Builder);
Benjamin Kramer79f15902014-10-24 13:29:15 +0000198 if (InnerMatcher.matches(DynNode, Finder, &BuilderInner)) {
Samuel Benzaquen85ec25d2013-08-27 15:11:16 +0000199 Matched = true;
200 Result.addMatch(BuilderInner);
201 }
202 }
Benjamin Kramerd9c91622014-08-29 11:22:47 +0000203 *Builder = std::move(Result);
Samuel Benzaquen85ec25d2013-08-27 15:11:16 +0000204 return Matched;
205}
206
207bool AnyOfVariadicOperator(const ast_type_traits::DynTypedNode DynNode,
208 ASTMatchFinder *Finder,
209 BoundNodesTreeBuilder *Builder,
Samuel Benzaquenf34ac3e2013-10-29 14:37:15 +0000210 ArrayRef<DynTypedMatcher> InnerMatchers) {
Benjamin Kramer79f15902014-10-24 13:29:15 +0000211 for (const DynTypedMatcher &InnerMatcher : InnerMatchers) {
Samuel Benzaquen85ec25d2013-08-27 15:11:16 +0000212 BoundNodesTreeBuilder Result = *Builder;
Benjamin Kramer79f15902014-10-24 13:29:15 +0000213 if (InnerMatcher.matches(DynNode, Finder, &Result)) {
Benjamin Kramerd9c91622014-08-29 11:22:47 +0000214 *Builder = std::move(Result);
Samuel Benzaquen85ec25d2013-08-27 15:11:16 +0000215 return true;
216 }
217 }
218 return false;
219}
220
Samuel Benzaquen8513d622014-10-15 14:58:46 +0000221HasNameMatcher::HasNameMatcher(StringRef NameRef)
222 : UseUnqualifiedMatch(NameRef.find("::") == NameRef.npos), Name(NameRef) {
223 assert(!Name.empty());
224}
225
226bool HasNameMatcher::matchesNodeUnqualified(const NamedDecl &Node) const {
227 assert(UseUnqualifiedMatch);
228 if (Node.getIdentifier()) {
229 // Simple name.
230 return Name == Node.getName();
Samuel Benzaquenb6f73bc2014-10-16 17:50:19 +0000231 }
232 if (Node.getDeclName()) {
Samuel Benzaquen8513d622014-10-15 14:58:46 +0000233 // Name needs to be constructed.
234 llvm::SmallString<128> NodeName;
235 llvm::raw_svector_ostream OS(NodeName);
236 Node.printName(OS);
237 return Name == OS.str();
Samuel Benzaquen8513d622014-10-15 14:58:46 +0000238 }
Samuel Benzaquenb6f73bc2014-10-16 17:50:19 +0000239 return false;
Samuel Benzaquen8513d622014-10-15 14:58:46 +0000240}
241
242bool HasNameMatcher::matchesNodeFull(const NamedDecl &Node) const {
243 llvm::SmallString<128> NodeName = StringRef("::");
244 llvm::raw_svector_ostream OS(NodeName);
245 Node.printQualifiedName(OS);
246 const StringRef FullName = OS.str();
247 const StringRef Pattern = Name;
Samuel Benzaquenb6f73bc2014-10-16 17:50:19 +0000248
249 if (Pattern.startswith("::"))
Samuel Benzaquen8513d622014-10-15 14:58:46 +0000250 return FullName == Pattern;
Samuel Benzaquenb6f73bc2014-10-16 17:50:19 +0000251
252 return FullName.endswith(Pattern) &&
253 FullName.drop_back(Pattern.size()).endswith("::");
Samuel Benzaquen8513d622014-10-15 14:58:46 +0000254}
255
256bool HasNameMatcher::matchesNode(const NamedDecl &Node) const {
257 // FIXME: There is still room for improvement, but it would require copying a
258 // lot of the logic from NamedDecl::printQualifiedName(). The benchmarks do
259 // not show like that extra complexity is needed right now.
260 if (UseUnqualifiedMatch) {
261 assert(matchesNodeUnqualified(Node) == matchesNodeFull(Node));
262 return matchesNodeUnqualified(Node);
263 }
264 return matchesNodeFull(Node);
265}
266
Manuel Klimek04616e42012-07-06 05:48:52 +0000267} // end namespace internal
268} // end namespace ast_matchers
269} // end namespace clang