blob: ca58d330d803d09eca8d7fe035e505c292ae6755 [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
53class VariadicMatcher : public DynMatcherInterface {
Samuel Benzaquen2c15e8c2014-11-20 15:45:53 +000054public:
55 typedef bool (*VariadicOperatorFunction)(
56 const ast_type_traits::DynTypedNode DynNode, ASTMatchFinder *Finder,
57 BoundNodesTreeBuilder *Builder, ArrayRef<DynTypedMatcher> InnerMatchers);
58
59 VariadicMatcher(VariadicOperatorFunction Func,
Samuel Benzaquenf28d9972014-10-01 15:08:07 +000060 std::vector<DynTypedMatcher> InnerMatchers)
61 : Func(Func), InnerMatchers(std::move(InnerMatchers)) {}
62
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:
70 VariadicOperatorFunction Func;
Samuel Benzaquenf28d9972014-10-01 15:08:07 +000071 std::vector<DynTypedMatcher> InnerMatchers;
72};
73
74class IdDynMatcher : public DynMatcherInterface {
75 public:
76 IdDynMatcher(StringRef ID,
77 const IntrusiveRefCntPtr<DynMatcherInterface> &InnerMatcher)
78 : ID(ID), InnerMatcher(InnerMatcher) {}
79
80 bool dynMatches(const ast_type_traits::DynTypedNode &DynNode,
81 ASTMatchFinder *Finder,
82 BoundNodesTreeBuilder *Builder) const override {
83 bool Result = InnerMatcher->dynMatches(DynNode, Finder, Builder);
84 if (Result) Builder->setBinding(ID, DynNode);
85 return Result;
86 }
87
88 private:
89 const std::string ID;
90 const IntrusiveRefCntPtr<DynMatcherInterface> InnerMatcher;
91};
92
Samuel Benzaquen96039d72014-10-09 19:28:18 +000093/// \brief A matcher that always returns true.
94///
95/// We only ever need one instance of this matcher, so we create a global one
96/// and reuse it to reduce the overhead of the matcher and increase the chance
97/// of cache hits.
Benjamin Kramer967c0792014-10-24 13:29:21 +000098class TrueMatcherImpl : public DynMatcherInterface {
99public:
100 TrueMatcherImpl() {
101 Retain(); // Reference count will never become zero.
102 }
103 bool dynMatches(const ast_type_traits::DynTypedNode &, ASTMatchFinder *,
104 BoundNodesTreeBuilder *) const override {
105 return true;
106 }
Samuel Benzaquen96039d72014-10-09 19:28:18 +0000107};
108static llvm::ManagedStatic<TrueMatcherImpl> TrueMatcherInstance;
109
Samuel Benzaquenf28d9972014-10-01 15:08:07 +0000110} // namespace
111
112DynTypedMatcher DynTypedMatcher::constructVariadic(
Samuel Benzaquen2c15e8c2014-11-20 15:45:53 +0000113 DynTypedMatcher::VariadicOperator Op,
Samuel Benzaquen9743c9d2014-11-17 14:55:49 +0000114 std::vector<DynTypedMatcher> InnerMatchers) {
Samuel Benzaquenf28d9972014-10-01 15:08:07 +0000115 assert(InnerMatchers.size() > 0 && "Array must not be empty.");
Samuel Benzaquen20099602014-10-13 17:38:12 +0000116 assert(std::all_of(InnerMatchers.begin(), InnerMatchers.end(),
117 [&InnerMatchers](const DynTypedMatcher &M) {
118 return InnerMatchers[0].SupportedKind.isSame(M.SupportedKind);
119 }) &&
120 "SupportedKind must match!");
121
122 // 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 Benzaquen193d87f2014-10-13 18:17:11 +0000126 auto SupportedKind = InnerMatchers[0].SupportedKind;
Samuel Benzaquen2c15e8c2014-11-20 15:45:53 +0000127 VariadicMatcher::VariadicOperatorFunction Func;
128 switch (Op) {
129 case VO_AllOf:
130 Func = AllOfVariadicOperator;
131 break;
132 case VO_AnyOf:
133 Func = AnyOfVariadicOperator;
134 break;
135 case VO_EachOf:
136 Func = EachOfVariadicOperator;
137 break;
138 case VO_UnaryNot:
139 Func = NotUnaryOperator;
140 break;
141 }
142
Samuel Benzaquen193d87f2014-10-13 18:17:11 +0000143 return DynTypedMatcher(SupportedKind, SupportedKind,
Samuel Benzaquen20099602014-10-13 17:38:12 +0000144 new VariadicMatcher(Func, std::move(InnerMatchers)));
Samuel Benzaquenf28d9972014-10-01 15:08:07 +0000145}
146
Samuel Benzaquen96039d72014-10-09 19:28:18 +0000147DynTypedMatcher DynTypedMatcher::trueMatcher(
148 ast_type_traits::ASTNodeKind NodeKind) {
Benjamin Kramer967c0792014-10-24 13:29:21 +0000149 return DynTypedMatcher(NodeKind, NodeKind, &*TrueMatcherInstance);
Samuel Benzaquen96039d72014-10-09 19:28:18 +0000150}
151
Samuel Benzaquen074bbb62014-11-24 21:21:09 +0000152bool DynTypedMatcher::canMatchNodesOfKind(
153 ast_type_traits::ASTNodeKind Kind) const {
154 return RestrictKind.isBaseOf(Kind);
155}
156
Samuel Benzaquenf28d9972014-10-01 15:08:07 +0000157DynTypedMatcher DynTypedMatcher::dynCastTo(
158 const ast_type_traits::ASTNodeKind Kind) const {
159 auto Copy = *this;
160 Copy.SupportedKind = Kind;
Samuel Benzaquena1170022014-10-06 13:14:30 +0000161 Copy.RestrictKind =
162 ast_type_traits::ASTNodeKind::getMostDerivedType(Kind, RestrictKind);
Samuel Benzaquenf28d9972014-10-01 15:08:07 +0000163 return Copy;
164}
165
166bool DynTypedMatcher::matches(const ast_type_traits::DynTypedNode &DynNode,
167 ASTMatchFinder *Finder,
168 BoundNodesTreeBuilder *Builder) const {
169 if (RestrictKind.isBaseOf(DynNode.getNodeKind()) &&
170 Implementation->dynMatches(DynNode, Finder, Builder)) {
171 return true;
172 }
173 // Delete all bindings when a matcher does not match.
174 // This prevents unexpected exposure of bound nodes in unmatches
175 // branches of the match tree.
176 Builder->removeBindings([](const BoundNodesMap &) { return true; });
177 return false;
178}
179
Samuel Benzaquen074bbb62014-11-24 21:21:09 +0000180bool DynTypedMatcher::matchesNoKindCheck(
181 const ast_type_traits::DynTypedNode &DynNode, ASTMatchFinder *Finder,
182 BoundNodesTreeBuilder *Builder) const {
183 assert(RestrictKind.isBaseOf(DynNode.getNodeKind()));
184 if (Implementation->dynMatches(DynNode, Finder, Builder)) {
185 return true;
186 }
187 // Delete all bindings when a matcher does not match.
188 // This prevents unexpected exposure of bound nodes in unmatches
189 // branches of the match tree.
190 Builder->removeBindings([](const BoundNodesMap &) { return true; });
191 return false;
192}
193
Samuel Benzaquenf28d9972014-10-01 15:08:07 +0000194llvm::Optional<DynTypedMatcher> DynTypedMatcher::tryBind(StringRef ID) const {
195 if (!AllowBind) return llvm::None;
196 auto Result = *this;
197 Result.Implementation = new IdDynMatcher(ID, Result.Implementation);
198 return Result;
199}
200
Samuel Benzaquenab005ed2014-09-04 14:13:58 +0000201bool DynTypedMatcher::canConvertTo(ast_type_traits::ASTNodeKind To) const {
202 const auto From = getSupportedKind();
203 auto QualKind = ast_type_traits::ASTNodeKind::getFromNodeKind<QualType>();
204 auto TypeKind = ast_type_traits::ASTNodeKind::getFromNodeKind<Type>();
205 /// Mimic the implicit conversions of Matcher<>.
206 /// - From Matcher<Type> to Matcher<QualType>
207 if (From.isSame(TypeKind) && To.isSame(QualKind)) return true;
208 /// - From Matcher<Base> to Matcher<Derived>
209 return From.isBaseOf(To);
210}
211
Manuel Klimeka0c025f2013-06-19 15:42:45 +0000212void BoundNodesTreeBuilder::addMatch(const BoundNodesTreeBuilder &Other) {
Benjamin Kramer79f15902014-10-24 13:29:15 +0000213 Bindings.append(Other.Bindings.begin(), Other.Bindings.end());
Manuel Klimek021d56f2012-08-28 23:26:39 +0000214}
215
Samuel Benzaquen4d058742013-11-22 14:41:48 +0000216bool NotUnaryOperator(const ast_type_traits::DynTypedNode DynNode,
217 ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder,
218 ArrayRef<DynTypedMatcher> InnerMatchers) {
219 if (InnerMatchers.size() != 1)
220 return false;
221
222 // The 'unless' matcher will always discard the result:
223 // If the inner matcher doesn't match, unless returns true,
224 // but the inner matcher cannot have bound anything.
225 // If the inner matcher matches, the result is false, and
226 // any possible binding will be discarded.
227 // We still need to hand in all the bound nodes up to this
228 // point so the inner matcher can depend on bound nodes,
229 // and we need to actively discard the bound nodes, otherwise
230 // the inner matcher will reset the bound nodes if it doesn't
231 // match, but this would be inversed by 'unless'.
232 BoundNodesTreeBuilder Discard(*Builder);
233 return !InnerMatchers[0].matches(DynNode, Finder, &Discard);
234}
235
Samuel Benzaquen85ec25d2013-08-27 15:11:16 +0000236bool AllOfVariadicOperator(const ast_type_traits::DynTypedNode DynNode,
237 ASTMatchFinder *Finder,
238 BoundNodesTreeBuilder *Builder,
Samuel Benzaquenf34ac3e2013-10-29 14:37:15 +0000239 ArrayRef<DynTypedMatcher> InnerMatchers) {
Samuel Benzaquen85ec25d2013-08-27 15:11:16 +0000240 // allOf leads to one matcher for each alternative in the first
241 // matcher combined with each alternative in the second matcher.
242 // Thus, we can reuse the same Builder.
Benjamin Kramer79f15902014-10-24 13:29:15 +0000243 for (const DynTypedMatcher &InnerMatcher : InnerMatchers) {
244 if (!InnerMatcher.matches(DynNode, Finder, Builder))
Samuel Benzaquen85ec25d2013-08-27 15:11:16 +0000245 return false;
246 }
247 return true;
248}
249
250bool EachOfVariadicOperator(const ast_type_traits::DynTypedNode DynNode,
251 ASTMatchFinder *Finder,
252 BoundNodesTreeBuilder *Builder,
Samuel Benzaquenf34ac3e2013-10-29 14:37:15 +0000253 ArrayRef<DynTypedMatcher> InnerMatchers) {
Samuel Benzaquen85ec25d2013-08-27 15:11:16 +0000254 BoundNodesTreeBuilder Result;
255 bool Matched = false;
Benjamin Kramer79f15902014-10-24 13:29:15 +0000256 for (const DynTypedMatcher &InnerMatcher : InnerMatchers) {
Samuel Benzaquen85ec25d2013-08-27 15:11:16 +0000257 BoundNodesTreeBuilder BuilderInner(*Builder);
Benjamin Kramer79f15902014-10-24 13:29:15 +0000258 if (InnerMatcher.matches(DynNode, Finder, &BuilderInner)) {
Samuel Benzaquen85ec25d2013-08-27 15:11:16 +0000259 Matched = true;
260 Result.addMatch(BuilderInner);
261 }
262 }
Benjamin Kramerd9c91622014-08-29 11:22:47 +0000263 *Builder = std::move(Result);
Samuel Benzaquen85ec25d2013-08-27 15:11:16 +0000264 return Matched;
265}
266
267bool AnyOfVariadicOperator(const ast_type_traits::DynTypedNode DynNode,
268 ASTMatchFinder *Finder,
269 BoundNodesTreeBuilder *Builder,
Samuel Benzaquenf34ac3e2013-10-29 14:37:15 +0000270 ArrayRef<DynTypedMatcher> InnerMatchers) {
Benjamin Kramer79f15902014-10-24 13:29:15 +0000271 for (const DynTypedMatcher &InnerMatcher : InnerMatchers) {
Samuel Benzaquen85ec25d2013-08-27 15:11:16 +0000272 BoundNodesTreeBuilder Result = *Builder;
Benjamin Kramer79f15902014-10-24 13:29:15 +0000273 if (InnerMatcher.matches(DynNode, Finder, &Result)) {
Benjamin Kramerd9c91622014-08-29 11:22:47 +0000274 *Builder = std::move(Result);
Samuel Benzaquen85ec25d2013-08-27 15:11:16 +0000275 return true;
276 }
277 }
278 return false;
279}
280
Samuel Benzaquen8513d622014-10-15 14:58:46 +0000281HasNameMatcher::HasNameMatcher(StringRef NameRef)
282 : UseUnqualifiedMatch(NameRef.find("::") == NameRef.npos), Name(NameRef) {
283 assert(!Name.empty());
284}
285
286bool HasNameMatcher::matchesNodeUnqualified(const NamedDecl &Node) const {
287 assert(UseUnqualifiedMatch);
288 if (Node.getIdentifier()) {
289 // Simple name.
290 return Name == Node.getName();
Samuel Benzaquenb6f73bc2014-10-16 17:50:19 +0000291 }
292 if (Node.getDeclName()) {
Samuel Benzaquen8513d622014-10-15 14:58:46 +0000293 // Name needs to be constructed.
294 llvm::SmallString<128> NodeName;
295 llvm::raw_svector_ostream OS(NodeName);
296 Node.printName(OS);
297 return Name == OS.str();
Samuel Benzaquen8513d622014-10-15 14:58:46 +0000298 }
Samuel Benzaquenb6f73bc2014-10-16 17:50:19 +0000299 return false;
Samuel Benzaquen8513d622014-10-15 14:58:46 +0000300}
301
302bool HasNameMatcher::matchesNodeFull(const NamedDecl &Node) const {
303 llvm::SmallString<128> NodeName = StringRef("::");
304 llvm::raw_svector_ostream OS(NodeName);
305 Node.printQualifiedName(OS);
306 const StringRef FullName = OS.str();
307 const StringRef Pattern = Name;
Samuel Benzaquenb6f73bc2014-10-16 17:50:19 +0000308
309 if (Pattern.startswith("::"))
Samuel Benzaquen8513d622014-10-15 14:58:46 +0000310 return FullName == Pattern;
Samuel Benzaquenb6f73bc2014-10-16 17:50:19 +0000311
312 return FullName.endswith(Pattern) &&
313 FullName.drop_back(Pattern.size()).endswith("::");
Samuel Benzaquen8513d622014-10-15 14:58:46 +0000314}
315
316bool HasNameMatcher::matchesNode(const NamedDecl &Node) const {
317 // FIXME: There is still room for improvement, but it would require copying a
318 // lot of the logic from NamedDecl::printQualifiedName(). The benchmarks do
319 // not show like that extra complexity is needed right now.
320 if (UseUnqualifiedMatch) {
321 assert(matchesNodeUnqualified(Node) == matchesNodeFull(Node));
322 return matchesNodeUnqualified(Node);
323 }
324 return matchesNodeFull(Node);
325}
326
Manuel Klimek04616e42012-07-06 05:48:52 +0000327} // end namespace internal
328} // end namespace ast_matchers
329} // end namespace clang