blob: 2c482e38dc08121ad6f13f0a2f286c3e9a73e9c7 [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
Samuel Benzaquen2c15e8c2014-11-20 15:45:53 +000023bool NotUnaryOperator(const ast_type_traits::DynTypedNode DynNode,
24 ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder,
25 ArrayRef<DynTypedMatcher> InnerMatchers);
26
27bool AllOfVariadicOperator(const ast_type_traits::DynTypedNode DynNode,
28 ASTMatchFinder *Finder,
29 BoundNodesTreeBuilder *Builder,
30 ArrayRef<DynTypedMatcher> InnerMatchers);
31
32bool EachOfVariadicOperator(const ast_type_traits::DynTypedNode DynNode,
33 ASTMatchFinder *Finder,
34 BoundNodesTreeBuilder *Builder,
35 ArrayRef<DynTypedMatcher> InnerMatchers);
36
37bool AnyOfVariadicOperator(const ast_type_traits::DynTypedNode DynNode,
38 ASTMatchFinder *Finder,
39 BoundNodesTreeBuilder *Builder,
40 ArrayRef<DynTypedMatcher> InnerMatchers);
41
42
Manuel Klimeka0c025f2013-06-19 15:42:45 +000043void BoundNodesTreeBuilder::visitMatches(Visitor *ResultVisitor) {
44 if (Bindings.empty())
45 Bindings.push_back(BoundNodesMap());
Benjamin Kramer79f15902014-10-24 13:29:15 +000046 for (BoundNodesMap &Binding : Bindings) {
47 ResultVisitor->visitMatch(BoundNodes(Binding));
Manuel Klimek021d56f2012-08-28 23:26:39 +000048 }
49}
50
Samuel Benzaquenf28d9972014-10-01 15:08:07 +000051namespace {
52
Samuel Benzaquen95636e52014-12-01 14:46:14 +000053typedef bool (*VariadicOperatorFunction)(
54 const ast_type_traits::DynTypedNode DynNode, ASTMatchFinder *Finder,
55 BoundNodesTreeBuilder *Builder, ArrayRef<DynTypedMatcher> InnerMatchers);
56
57template <VariadicOperatorFunction Func>
Samuel Benzaquenf28d9972014-10-01 15:08:07 +000058class VariadicMatcher : public DynMatcherInterface {
Samuel Benzaquen2c15e8c2014-11-20 15:45:53 +000059public:
Samuel Benzaquen95636e52014-12-01 14:46:14 +000060 VariadicMatcher(std::vector<DynTypedMatcher> InnerMatchers)
61 : InnerMatchers(std::move(InnerMatchers)) {}
Samuel Benzaquenf28d9972014-10-01 15:08:07 +000062
63 bool dynMatches(const ast_type_traits::DynTypedNode &DynNode,
64 ASTMatchFinder *Finder,
65 BoundNodesTreeBuilder *Builder) const override {
66 return Func(DynNode, Finder, Builder, InnerMatchers);
67 }
68
Samuel Benzaquen2c15e8c2014-11-20 15:45:53 +000069private:
Samuel Benzaquenf28d9972014-10-01 15:08:07 +000070 std::vector<DynTypedMatcher> InnerMatchers;
71};
72
73class IdDynMatcher : public DynMatcherInterface {
74 public:
75 IdDynMatcher(StringRef ID,
76 const IntrusiveRefCntPtr<DynMatcherInterface> &InnerMatcher)
77 : ID(ID), InnerMatcher(InnerMatcher) {}
78
79 bool dynMatches(const ast_type_traits::DynTypedNode &DynNode,
80 ASTMatchFinder *Finder,
81 BoundNodesTreeBuilder *Builder) const override {
82 bool Result = InnerMatcher->dynMatches(DynNode, Finder, Builder);
83 if (Result) Builder->setBinding(ID, DynNode);
84 return Result;
85 }
86
87 private:
88 const std::string ID;
89 const IntrusiveRefCntPtr<DynMatcherInterface> InnerMatcher;
90};
91
Samuel Benzaquen96039d72014-10-09 19:28:18 +000092/// \brief A matcher that always returns true.
93///
94/// We only ever need one instance of this matcher, so we create a global one
95/// and reuse it to reduce the overhead of the matcher and increase the chance
96/// of cache hits.
Benjamin Kramer967c0792014-10-24 13:29:21 +000097class TrueMatcherImpl : public DynMatcherInterface {
98public:
99 TrueMatcherImpl() {
100 Retain(); // Reference count will never become zero.
101 }
102 bool dynMatches(const ast_type_traits::DynTypedNode &, ASTMatchFinder *,
103 BoundNodesTreeBuilder *) const override {
104 return true;
105 }
Samuel Benzaquen96039d72014-10-09 19:28:18 +0000106};
107static llvm::ManagedStatic<TrueMatcherImpl> TrueMatcherInstance;
108
Samuel Benzaquenf28d9972014-10-01 15:08:07 +0000109} // namespace
110
111DynTypedMatcher DynTypedMatcher::constructVariadic(
Samuel Benzaquen2c15e8c2014-11-20 15:45:53 +0000112 DynTypedMatcher::VariadicOperator Op,
Samuel Benzaquen9743c9d2014-11-17 14:55:49 +0000113 std::vector<DynTypedMatcher> InnerMatchers) {
Samuel Benzaquenf28d9972014-10-01 15:08:07 +0000114 assert(InnerMatchers.size() > 0 && "Array must not be empty.");
Samuel Benzaquen20099602014-10-13 17:38:12 +0000115 assert(std::all_of(InnerMatchers.begin(), InnerMatchers.end(),
116 [&InnerMatchers](const DynTypedMatcher &M) {
117 return InnerMatchers[0].SupportedKind.isSame(M.SupportedKind);
118 }) &&
119 "SupportedKind must match!");
120
Samuel Benzaquen95636e52014-12-01 14:46:14 +0000121 auto SupportedKind = InnerMatchers[0].SupportedKind;
Samuel Benzaquen20099602014-10-13 17:38:12 +0000122 // We must relax the restrict kind here.
123 // The different operators might deal differently with a mismatch.
124 // Make it the same as SupportedKind, since that is the broadest type we are
125 // allowed to accept.
Samuel Benzaquen95636e52014-12-01 14:46:14 +0000126 auto RestrictKind = SupportedKind;
127
Samuel Benzaquen2c15e8c2014-11-20 15:45:53 +0000128 switch (Op) {
129 case VO_AllOf:
Samuel Benzaquen95636e52014-12-01 14:46:14 +0000130 // In the case of allOf() we must pass all the checks, so making
131 // RestrictKind the most restrictive can save us time. This way we reject
132 // invalid types earlier and we can elide the kind checks inside the
133 // matcher.
134 for (auto &IM : InnerMatchers) {
135 RestrictKind = ast_type_traits::ASTNodeKind::getMostDerivedType(
136 RestrictKind, IM.RestrictKind);
137 }
138 return DynTypedMatcher(
139 SupportedKind, RestrictKind,
140 new VariadicMatcher<AllOfVariadicOperator>(std::move(InnerMatchers)));
Samuel Benzaquen2c15e8c2014-11-20 15:45:53 +0000141
Samuel Benzaquen95636e52014-12-01 14:46:14 +0000142 case VO_AnyOf:
143 return DynTypedMatcher(
144 SupportedKind, RestrictKind,
145 new VariadicMatcher<AnyOfVariadicOperator>(std::move(InnerMatchers)));
146
147 case VO_EachOf:
148 return DynTypedMatcher(
149 SupportedKind, RestrictKind,
150 new VariadicMatcher<EachOfVariadicOperator>(std::move(InnerMatchers)));
151
152 case VO_UnaryNot:
153 // FIXME: Implement the Not operator to take a single matcher instead of a
154 // vector.
155 return DynTypedMatcher(
156 SupportedKind, RestrictKind,
157 new VariadicMatcher<NotUnaryOperator>(std::move(InnerMatchers)));
158 }
159 llvm_unreachable("Invalid Op value.");
Samuel Benzaquenf28d9972014-10-01 15:08:07 +0000160}
161
Samuel Benzaquen96039d72014-10-09 19:28:18 +0000162DynTypedMatcher DynTypedMatcher::trueMatcher(
163 ast_type_traits::ASTNodeKind NodeKind) {
Benjamin Kramer967c0792014-10-24 13:29:21 +0000164 return DynTypedMatcher(NodeKind, NodeKind, &*TrueMatcherInstance);
Samuel Benzaquen96039d72014-10-09 19:28:18 +0000165}
166
Samuel Benzaquen074bbb62014-11-24 21:21:09 +0000167bool DynTypedMatcher::canMatchNodesOfKind(
168 ast_type_traits::ASTNodeKind Kind) const {
169 return RestrictKind.isBaseOf(Kind);
170}
171
Samuel Benzaquenf28d9972014-10-01 15:08:07 +0000172DynTypedMatcher DynTypedMatcher::dynCastTo(
173 const ast_type_traits::ASTNodeKind Kind) const {
174 auto Copy = *this;
175 Copy.SupportedKind = Kind;
Samuel Benzaquena1170022014-10-06 13:14:30 +0000176 Copy.RestrictKind =
177 ast_type_traits::ASTNodeKind::getMostDerivedType(Kind, RestrictKind);
Samuel Benzaquenf28d9972014-10-01 15:08:07 +0000178 return Copy;
179}
180
181bool DynTypedMatcher::matches(const ast_type_traits::DynTypedNode &DynNode,
182 ASTMatchFinder *Finder,
183 BoundNodesTreeBuilder *Builder) const {
184 if (RestrictKind.isBaseOf(DynNode.getNodeKind()) &&
185 Implementation->dynMatches(DynNode, Finder, Builder)) {
186 return true;
187 }
188 // Delete all bindings when a matcher does not match.
189 // This prevents unexpected exposure of bound nodes in unmatches
190 // branches of the match tree.
191 Builder->removeBindings([](const BoundNodesMap &) { return true; });
192 return false;
193}
194
Samuel Benzaquen074bbb62014-11-24 21:21:09 +0000195bool DynTypedMatcher::matchesNoKindCheck(
196 const ast_type_traits::DynTypedNode &DynNode, ASTMatchFinder *Finder,
197 BoundNodesTreeBuilder *Builder) const {
198 assert(RestrictKind.isBaseOf(DynNode.getNodeKind()));
199 if (Implementation->dynMatches(DynNode, Finder, Builder)) {
200 return true;
201 }
202 // Delete all bindings when a matcher does not match.
203 // This prevents unexpected exposure of bound nodes in unmatches
204 // branches of the match tree.
205 Builder->removeBindings([](const BoundNodesMap &) { return true; });
206 return false;
207}
208
Samuel Benzaquenf28d9972014-10-01 15:08:07 +0000209llvm::Optional<DynTypedMatcher> DynTypedMatcher::tryBind(StringRef ID) const {
210 if (!AllowBind) return llvm::None;
211 auto Result = *this;
212 Result.Implementation = new IdDynMatcher(ID, Result.Implementation);
213 return Result;
214}
215
Samuel Benzaquenab005ed2014-09-04 14:13:58 +0000216bool DynTypedMatcher::canConvertTo(ast_type_traits::ASTNodeKind To) const {
217 const auto From = getSupportedKind();
218 auto QualKind = ast_type_traits::ASTNodeKind::getFromNodeKind<QualType>();
219 auto TypeKind = ast_type_traits::ASTNodeKind::getFromNodeKind<Type>();
220 /// Mimic the implicit conversions of Matcher<>.
221 /// - From Matcher<Type> to Matcher<QualType>
222 if (From.isSame(TypeKind) && To.isSame(QualKind)) return true;
223 /// - From Matcher<Base> to Matcher<Derived>
224 return From.isBaseOf(To);
225}
226
Manuel Klimeka0c025f2013-06-19 15:42:45 +0000227void BoundNodesTreeBuilder::addMatch(const BoundNodesTreeBuilder &Other) {
Benjamin Kramer79f15902014-10-24 13:29:15 +0000228 Bindings.append(Other.Bindings.begin(), Other.Bindings.end());
Manuel Klimek021d56f2012-08-28 23:26:39 +0000229}
230
Samuel Benzaquen4d058742013-11-22 14:41:48 +0000231bool NotUnaryOperator(const ast_type_traits::DynTypedNode DynNode,
232 ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder,
233 ArrayRef<DynTypedMatcher> InnerMatchers) {
234 if (InnerMatchers.size() != 1)
235 return false;
236
237 // The 'unless' matcher will always discard the result:
238 // If the inner matcher doesn't match, unless returns true,
239 // but the inner matcher cannot have bound anything.
240 // If the inner matcher matches, the result is false, and
241 // any possible binding will be discarded.
242 // We still need to hand in all the bound nodes up to this
243 // point so the inner matcher can depend on bound nodes,
244 // and we need to actively discard the bound nodes, otherwise
245 // the inner matcher will reset the bound nodes if it doesn't
246 // match, but this would be inversed by 'unless'.
247 BoundNodesTreeBuilder Discard(*Builder);
248 return !InnerMatchers[0].matches(DynNode, Finder, &Discard);
249}
250
Samuel Benzaquen85ec25d2013-08-27 15:11:16 +0000251bool AllOfVariadicOperator(const ast_type_traits::DynTypedNode DynNode,
252 ASTMatchFinder *Finder,
253 BoundNodesTreeBuilder *Builder,
Samuel Benzaquenf34ac3e2013-10-29 14:37:15 +0000254 ArrayRef<DynTypedMatcher> InnerMatchers) {
Samuel Benzaquen85ec25d2013-08-27 15:11:16 +0000255 // allOf leads to one matcher for each alternative in the first
256 // matcher combined with each alternative in the second matcher.
257 // Thus, we can reuse the same Builder.
Benjamin Kramer79f15902014-10-24 13:29:15 +0000258 for (const DynTypedMatcher &InnerMatcher : InnerMatchers) {
Samuel Benzaquen95636e52014-12-01 14:46:14 +0000259 if (!InnerMatcher.matchesNoKindCheck(DynNode, Finder, Builder))
Samuel Benzaquen85ec25d2013-08-27 15:11:16 +0000260 return false;
261 }
262 return true;
263}
264
265bool EachOfVariadicOperator(const ast_type_traits::DynTypedNode DynNode,
266 ASTMatchFinder *Finder,
267 BoundNodesTreeBuilder *Builder,
Samuel Benzaquenf34ac3e2013-10-29 14:37:15 +0000268 ArrayRef<DynTypedMatcher> InnerMatchers) {
Samuel Benzaquen85ec25d2013-08-27 15:11:16 +0000269 BoundNodesTreeBuilder Result;
270 bool Matched = false;
Benjamin Kramer79f15902014-10-24 13:29:15 +0000271 for (const DynTypedMatcher &InnerMatcher : InnerMatchers) {
Samuel Benzaquen85ec25d2013-08-27 15:11:16 +0000272 BoundNodesTreeBuilder BuilderInner(*Builder);
Benjamin Kramer79f15902014-10-24 13:29:15 +0000273 if (InnerMatcher.matches(DynNode, Finder, &BuilderInner)) {
Samuel Benzaquen85ec25d2013-08-27 15:11:16 +0000274 Matched = true;
275 Result.addMatch(BuilderInner);
276 }
277 }
Benjamin Kramerd9c91622014-08-29 11:22:47 +0000278 *Builder = std::move(Result);
Samuel Benzaquen85ec25d2013-08-27 15:11:16 +0000279 return Matched;
280}
281
282bool AnyOfVariadicOperator(const ast_type_traits::DynTypedNode DynNode,
283 ASTMatchFinder *Finder,
284 BoundNodesTreeBuilder *Builder,
Samuel Benzaquenf34ac3e2013-10-29 14:37:15 +0000285 ArrayRef<DynTypedMatcher> InnerMatchers) {
Benjamin Kramer79f15902014-10-24 13:29:15 +0000286 for (const DynTypedMatcher &InnerMatcher : InnerMatchers) {
Samuel Benzaquen85ec25d2013-08-27 15:11:16 +0000287 BoundNodesTreeBuilder Result = *Builder;
Benjamin Kramer79f15902014-10-24 13:29:15 +0000288 if (InnerMatcher.matches(DynNode, Finder, &Result)) {
Benjamin Kramerd9c91622014-08-29 11:22:47 +0000289 *Builder = std::move(Result);
Samuel Benzaquen85ec25d2013-08-27 15:11:16 +0000290 return true;
291 }
292 }
293 return false;
294}
295
Samuel Benzaquen8513d622014-10-15 14:58:46 +0000296HasNameMatcher::HasNameMatcher(StringRef NameRef)
297 : UseUnqualifiedMatch(NameRef.find("::") == NameRef.npos), Name(NameRef) {
298 assert(!Name.empty());
299}
300
301bool HasNameMatcher::matchesNodeUnqualified(const NamedDecl &Node) const {
302 assert(UseUnqualifiedMatch);
303 if (Node.getIdentifier()) {
304 // Simple name.
305 return Name == Node.getName();
Samuel Benzaquenb6f73bc2014-10-16 17:50:19 +0000306 }
307 if (Node.getDeclName()) {
Samuel Benzaquen8513d622014-10-15 14:58:46 +0000308 // Name needs to be constructed.
309 llvm::SmallString<128> NodeName;
310 llvm::raw_svector_ostream OS(NodeName);
311 Node.printName(OS);
312 return Name == OS.str();
Samuel Benzaquen8513d622014-10-15 14:58:46 +0000313 }
Samuel Benzaquenb6f73bc2014-10-16 17:50:19 +0000314 return false;
Samuel Benzaquen8513d622014-10-15 14:58:46 +0000315}
316
317bool HasNameMatcher::matchesNodeFull(const NamedDecl &Node) const {
318 llvm::SmallString<128> NodeName = StringRef("::");
319 llvm::raw_svector_ostream OS(NodeName);
320 Node.printQualifiedName(OS);
321 const StringRef FullName = OS.str();
322 const StringRef Pattern = Name;
Samuel Benzaquenb6f73bc2014-10-16 17:50:19 +0000323
324 if (Pattern.startswith("::"))
Samuel Benzaquen8513d622014-10-15 14:58:46 +0000325 return FullName == Pattern;
Samuel Benzaquenb6f73bc2014-10-16 17:50:19 +0000326
327 return FullName.endswith(Pattern) &&
328 FullName.drop_back(Pattern.size()).endswith("::");
Samuel Benzaquen8513d622014-10-15 14:58:46 +0000329}
330
331bool HasNameMatcher::matchesNode(const NamedDecl &Node) const {
332 // FIXME: There is still room for improvement, but it would require copying a
333 // lot of the logic from NamedDecl::printQualifiedName(). The benchmarks do
334 // not show like that extra complexity is needed right now.
335 if (UseUnqualifiedMatch) {
336 assert(matchesNodeUnqualified(Node) == matchesNodeFull(Node));
337 return matchesNodeUnqualified(Node);
338 }
339 return matchesNodeFull(Node);
340}
341
Manuel Klimek04616e42012-07-06 05:48:52 +0000342} // end namespace internal
343} // end namespace ast_matchers
344} // end namespace clang