blob: c7d98b8a3a9659fe191402afbd83c934d4241d25 [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 Benzaquenf28d9972014-10-01 15:08:07 +0000152DynTypedMatcher DynTypedMatcher::dynCastTo(
153 const ast_type_traits::ASTNodeKind Kind) const {
154 auto Copy = *this;
155 Copy.SupportedKind = Kind;
Samuel Benzaquena1170022014-10-06 13:14:30 +0000156 Copy.RestrictKind =
157 ast_type_traits::ASTNodeKind::getMostDerivedType(Kind, RestrictKind);
Samuel Benzaquenf28d9972014-10-01 15:08:07 +0000158 return Copy;
159}
160
161bool DynTypedMatcher::matches(const ast_type_traits::DynTypedNode &DynNode,
162 ASTMatchFinder *Finder,
163 BoundNodesTreeBuilder *Builder) const {
164 if (RestrictKind.isBaseOf(DynNode.getNodeKind()) &&
165 Implementation->dynMatches(DynNode, Finder, Builder)) {
166 return true;
167 }
168 // Delete all bindings when a matcher does not match.
169 // This prevents unexpected exposure of bound nodes in unmatches
170 // branches of the match tree.
171 Builder->removeBindings([](const BoundNodesMap &) { return true; });
172 return false;
173}
174
175llvm::Optional<DynTypedMatcher> DynTypedMatcher::tryBind(StringRef ID) const {
176 if (!AllowBind) return llvm::None;
177 auto Result = *this;
178 Result.Implementation = new IdDynMatcher(ID, Result.Implementation);
179 return Result;
180}
181
Samuel Benzaquenab005ed2014-09-04 14:13:58 +0000182bool DynTypedMatcher::canConvertTo(ast_type_traits::ASTNodeKind To) const {
183 const auto From = getSupportedKind();
184 auto QualKind = ast_type_traits::ASTNodeKind::getFromNodeKind<QualType>();
185 auto TypeKind = ast_type_traits::ASTNodeKind::getFromNodeKind<Type>();
186 /// Mimic the implicit conversions of Matcher<>.
187 /// - From Matcher<Type> to Matcher<QualType>
188 if (From.isSame(TypeKind) && To.isSame(QualKind)) return true;
189 /// - From Matcher<Base> to Matcher<Derived>
190 return From.isBaseOf(To);
191}
192
Manuel Klimeka0c025f2013-06-19 15:42:45 +0000193void BoundNodesTreeBuilder::addMatch(const BoundNodesTreeBuilder &Other) {
Benjamin Kramer79f15902014-10-24 13:29:15 +0000194 Bindings.append(Other.Bindings.begin(), Other.Bindings.end());
Manuel Klimek021d56f2012-08-28 23:26:39 +0000195}
196
Samuel Benzaquen4d058742013-11-22 14:41:48 +0000197bool NotUnaryOperator(const ast_type_traits::DynTypedNode DynNode,
198 ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder,
199 ArrayRef<DynTypedMatcher> InnerMatchers) {
200 if (InnerMatchers.size() != 1)
201 return false;
202
203 // The 'unless' matcher will always discard the result:
204 // If the inner matcher doesn't match, unless returns true,
205 // but the inner matcher cannot have bound anything.
206 // If the inner matcher matches, the result is false, and
207 // any possible binding will be discarded.
208 // We still need to hand in all the bound nodes up to this
209 // point so the inner matcher can depend on bound nodes,
210 // and we need to actively discard the bound nodes, otherwise
211 // the inner matcher will reset the bound nodes if it doesn't
212 // match, but this would be inversed by 'unless'.
213 BoundNodesTreeBuilder Discard(*Builder);
214 return !InnerMatchers[0].matches(DynNode, Finder, &Discard);
215}
216
Samuel Benzaquen85ec25d2013-08-27 15:11:16 +0000217bool AllOfVariadicOperator(const ast_type_traits::DynTypedNode DynNode,
218 ASTMatchFinder *Finder,
219 BoundNodesTreeBuilder *Builder,
Samuel Benzaquenf34ac3e2013-10-29 14:37:15 +0000220 ArrayRef<DynTypedMatcher> InnerMatchers) {
Samuel Benzaquen85ec25d2013-08-27 15:11:16 +0000221 // allOf leads to one matcher for each alternative in the first
222 // matcher combined with each alternative in the second matcher.
223 // Thus, we can reuse the same Builder.
Benjamin Kramer79f15902014-10-24 13:29:15 +0000224 for (const DynTypedMatcher &InnerMatcher : InnerMatchers) {
225 if (!InnerMatcher.matches(DynNode, Finder, Builder))
Samuel Benzaquen85ec25d2013-08-27 15:11:16 +0000226 return false;
227 }
228 return true;
229}
230
231bool EachOfVariadicOperator(const ast_type_traits::DynTypedNode DynNode,
232 ASTMatchFinder *Finder,
233 BoundNodesTreeBuilder *Builder,
Samuel Benzaquenf34ac3e2013-10-29 14:37:15 +0000234 ArrayRef<DynTypedMatcher> InnerMatchers) {
Samuel Benzaquen85ec25d2013-08-27 15:11:16 +0000235 BoundNodesTreeBuilder Result;
236 bool Matched = false;
Benjamin Kramer79f15902014-10-24 13:29:15 +0000237 for (const DynTypedMatcher &InnerMatcher : InnerMatchers) {
Samuel Benzaquen85ec25d2013-08-27 15:11:16 +0000238 BoundNodesTreeBuilder BuilderInner(*Builder);
Benjamin Kramer79f15902014-10-24 13:29:15 +0000239 if (InnerMatcher.matches(DynNode, Finder, &BuilderInner)) {
Samuel Benzaquen85ec25d2013-08-27 15:11:16 +0000240 Matched = true;
241 Result.addMatch(BuilderInner);
242 }
243 }
Benjamin Kramerd9c91622014-08-29 11:22:47 +0000244 *Builder = std::move(Result);
Samuel Benzaquen85ec25d2013-08-27 15:11:16 +0000245 return Matched;
246}
247
248bool AnyOfVariadicOperator(const ast_type_traits::DynTypedNode DynNode,
249 ASTMatchFinder *Finder,
250 BoundNodesTreeBuilder *Builder,
Samuel Benzaquenf34ac3e2013-10-29 14:37:15 +0000251 ArrayRef<DynTypedMatcher> InnerMatchers) {
Benjamin Kramer79f15902014-10-24 13:29:15 +0000252 for (const DynTypedMatcher &InnerMatcher : InnerMatchers) {
Samuel Benzaquen85ec25d2013-08-27 15:11:16 +0000253 BoundNodesTreeBuilder Result = *Builder;
Benjamin Kramer79f15902014-10-24 13:29:15 +0000254 if (InnerMatcher.matches(DynNode, Finder, &Result)) {
Benjamin Kramerd9c91622014-08-29 11:22:47 +0000255 *Builder = std::move(Result);
Samuel Benzaquen85ec25d2013-08-27 15:11:16 +0000256 return true;
257 }
258 }
259 return false;
260}
261
Samuel Benzaquen8513d622014-10-15 14:58:46 +0000262HasNameMatcher::HasNameMatcher(StringRef NameRef)
263 : UseUnqualifiedMatch(NameRef.find("::") == NameRef.npos), Name(NameRef) {
264 assert(!Name.empty());
265}
266
267bool HasNameMatcher::matchesNodeUnqualified(const NamedDecl &Node) const {
268 assert(UseUnqualifiedMatch);
269 if (Node.getIdentifier()) {
270 // Simple name.
271 return Name == Node.getName();
Samuel Benzaquenb6f73bc2014-10-16 17:50:19 +0000272 }
273 if (Node.getDeclName()) {
Samuel Benzaquen8513d622014-10-15 14:58:46 +0000274 // Name needs to be constructed.
275 llvm::SmallString<128> NodeName;
276 llvm::raw_svector_ostream OS(NodeName);
277 Node.printName(OS);
278 return Name == OS.str();
Samuel Benzaquen8513d622014-10-15 14:58:46 +0000279 }
Samuel Benzaquenb6f73bc2014-10-16 17:50:19 +0000280 return false;
Samuel Benzaquen8513d622014-10-15 14:58:46 +0000281}
282
283bool HasNameMatcher::matchesNodeFull(const NamedDecl &Node) const {
284 llvm::SmallString<128> NodeName = StringRef("::");
285 llvm::raw_svector_ostream OS(NodeName);
286 Node.printQualifiedName(OS);
287 const StringRef FullName = OS.str();
288 const StringRef Pattern = Name;
Samuel Benzaquenb6f73bc2014-10-16 17:50:19 +0000289
290 if (Pattern.startswith("::"))
Samuel Benzaquen8513d622014-10-15 14:58:46 +0000291 return FullName == Pattern;
Samuel Benzaquenb6f73bc2014-10-16 17:50:19 +0000292
293 return FullName.endswith(Pattern) &&
294 FullName.drop_back(Pattern.size()).endswith("::");
Samuel Benzaquen8513d622014-10-15 14:58:46 +0000295}
296
297bool HasNameMatcher::matchesNode(const NamedDecl &Node) const {
298 // FIXME: There is still room for improvement, but it would require copying a
299 // lot of the logic from NamedDecl::printQualifiedName(). The benchmarks do
300 // not show like that extra complexity is needed right now.
301 if (UseUnqualifiedMatch) {
302 assert(matchesNodeUnqualified(Node) == matchesNodeFull(Node));
303 return matchesNodeUnqualified(Node);
304 }
305 return matchesNodeFull(Node);
306}
307
Manuel Klimek04616e42012-07-06 05:48:52 +0000308} // end namespace internal
309} // end namespace ast_matchers
310} // end namespace clang