blob: 4cff381f3f4abb3c7e56a40f83002c303a58411a [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"
16
17namespace clang {
18namespace ast_matchers {
19namespace internal {
20
Manuel Klimeka0c025f2013-06-19 15:42:45 +000021void BoundNodesTreeBuilder::visitMatches(Visitor *ResultVisitor) {
22 if (Bindings.empty())
23 Bindings.push_back(BoundNodesMap());
24 for (unsigned i = 0, e = Bindings.size(); i != e; ++i) {
25 ResultVisitor->visitMatch(BoundNodes(Bindings[i]));
Manuel Klimek021d56f2012-08-28 23:26:39 +000026 }
27}
28
Samuel Benzaquenf28d9972014-10-01 15:08:07 +000029namespace {
30
31class VariadicMatcher : public DynMatcherInterface {
32 public:
33 VariadicMatcher(VariadicOperatorFunction Func,
34 std::vector<DynTypedMatcher> InnerMatchers)
35 : Func(Func), InnerMatchers(std::move(InnerMatchers)) {}
36
37 bool dynMatches(const ast_type_traits::DynTypedNode &DynNode,
38 ASTMatchFinder *Finder,
39 BoundNodesTreeBuilder *Builder) const override {
40 return Func(DynNode, Finder, Builder, InnerMatchers);
41 }
42
43 private:
44 VariadicOperatorFunction Func;
45 std::vector<DynTypedMatcher> InnerMatchers;
46};
47
48class IdDynMatcher : public DynMatcherInterface {
49 public:
50 IdDynMatcher(StringRef ID,
51 const IntrusiveRefCntPtr<DynMatcherInterface> &InnerMatcher)
52 : ID(ID), InnerMatcher(InnerMatcher) {}
53
54 bool dynMatches(const ast_type_traits::DynTypedNode &DynNode,
55 ASTMatchFinder *Finder,
56 BoundNodesTreeBuilder *Builder) const override {
57 bool Result = InnerMatcher->dynMatches(DynNode, Finder, Builder);
58 if (Result) Builder->setBinding(ID, DynNode);
59 return Result;
60 }
61
62 private:
63 const std::string ID;
64 const IntrusiveRefCntPtr<DynMatcherInterface> InnerMatcher;
65};
66
67/// \brief Return the most derived type between \p Kind1 and \p Kind2.
68///
69/// Return the null type if they are not related.
70ast_type_traits::ASTNodeKind getMostDerivedType(
71 const ast_type_traits::ASTNodeKind Kind1,
72 const ast_type_traits::ASTNodeKind Kind2) {
73 if (Kind1.isBaseOf(Kind2)) return Kind2;
74 if (Kind2.isBaseOf(Kind1)) return Kind1;
75 return ast_type_traits::ASTNodeKind();
76}
77
78/// \brief Return the least derived type between \p Kind1 and \p Kind2.
79///
80/// Return the null type if they are not related.
81static ast_type_traits::ASTNodeKind getLeastDerivedType(
82 const ast_type_traits::ASTNodeKind Kind1,
83 const ast_type_traits::ASTNodeKind Kind2) {
84 if (Kind1.isBaseOf(Kind2)) return Kind1;
85 if (Kind2.isBaseOf(Kind1)) return Kind2;
86 return ast_type_traits::ASTNodeKind();
87}
88
89} // namespace
90
91DynTypedMatcher DynTypedMatcher::constructVariadic(
92 VariadicOperatorFunction Func, std::vector<DynTypedMatcher> InnerMatchers) {
93 assert(InnerMatchers.size() > 0 && "Array must not be empty.");
94 DynTypedMatcher Result = InnerMatchers[0];
95 // Use the least derived type as the restriction for the wrapper.
96 // This allows mismatches to be resolved on the inner matchers.
97 for (const DynTypedMatcher &M : InnerMatchers) {
98 assert(Result.SupportedKind.isSame(M.SupportedKind) &&
99 "SupportedKind must match!");
100 Result.RestrictKind =
101 getLeastDerivedType(Result.RestrictKind, M.RestrictKind);
102 }
103 Result.Implementation = new VariadicMatcher(Func, std::move(InnerMatchers));
104 return Result;
105}
106
107DynTypedMatcher DynTypedMatcher::dynCastTo(
108 const ast_type_traits::ASTNodeKind Kind) const {
109 auto Copy = *this;
110 Copy.SupportedKind = Kind;
111 Copy.RestrictKind = getMostDerivedType(Kind, RestrictKind);
112 return Copy;
113}
114
115bool DynTypedMatcher::matches(const ast_type_traits::DynTypedNode &DynNode,
116 ASTMatchFinder *Finder,
117 BoundNodesTreeBuilder *Builder) const {
118 if (RestrictKind.isBaseOf(DynNode.getNodeKind()) &&
119 Implementation->dynMatches(DynNode, Finder, Builder)) {
120 return true;
121 }
122 // Delete all bindings when a matcher does not match.
123 // This prevents unexpected exposure of bound nodes in unmatches
124 // branches of the match tree.
125 Builder->removeBindings([](const BoundNodesMap &) { return true; });
126 return false;
127}
128
129llvm::Optional<DynTypedMatcher> DynTypedMatcher::tryBind(StringRef ID) const {
130 if (!AllowBind) return llvm::None;
131 auto Result = *this;
132 Result.Implementation = new IdDynMatcher(ID, Result.Implementation);
133 return Result;
134}
135
Samuel Benzaquenab005ed2014-09-04 14:13:58 +0000136bool DynTypedMatcher::canConvertTo(ast_type_traits::ASTNodeKind To) const {
137 const auto From = getSupportedKind();
138 auto QualKind = ast_type_traits::ASTNodeKind::getFromNodeKind<QualType>();
139 auto TypeKind = ast_type_traits::ASTNodeKind::getFromNodeKind<Type>();
140 /// Mimic the implicit conversions of Matcher<>.
141 /// - From Matcher<Type> to Matcher<QualType>
142 if (From.isSame(TypeKind) && To.isSame(QualKind)) return true;
143 /// - From Matcher<Base> to Matcher<Derived>
144 return From.isBaseOf(To);
145}
146
Manuel Klimeka0c025f2013-06-19 15:42:45 +0000147void BoundNodesTreeBuilder::addMatch(const BoundNodesTreeBuilder &Other) {
148 for (unsigned i = 0, e = Other.Bindings.size(); i != e; ++i) {
149 Bindings.push_back(Other.Bindings[i]);
Daniel Jasper94a56852012-11-16 18:39:22 +0000150 }
Manuel Klimek021d56f2012-08-28 23:26:39 +0000151}
152
Samuel Benzaquen4d058742013-11-22 14:41:48 +0000153bool NotUnaryOperator(const ast_type_traits::DynTypedNode DynNode,
154 ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder,
155 ArrayRef<DynTypedMatcher> InnerMatchers) {
156 if (InnerMatchers.size() != 1)
157 return false;
158
159 // The 'unless' matcher will always discard the result:
160 // If the inner matcher doesn't match, unless returns true,
161 // but the inner matcher cannot have bound anything.
162 // If the inner matcher matches, the result is false, and
163 // any possible binding will be discarded.
164 // We still need to hand in all the bound nodes up to this
165 // point so the inner matcher can depend on bound nodes,
166 // and we need to actively discard the bound nodes, otherwise
167 // the inner matcher will reset the bound nodes if it doesn't
168 // match, but this would be inversed by 'unless'.
169 BoundNodesTreeBuilder Discard(*Builder);
170 return !InnerMatchers[0].matches(DynNode, Finder, &Discard);
171}
172
Samuel Benzaquen85ec25d2013-08-27 15:11:16 +0000173bool AllOfVariadicOperator(const ast_type_traits::DynTypedNode DynNode,
174 ASTMatchFinder *Finder,
175 BoundNodesTreeBuilder *Builder,
Samuel Benzaquenf34ac3e2013-10-29 14:37:15 +0000176 ArrayRef<DynTypedMatcher> InnerMatchers) {
Samuel Benzaquen85ec25d2013-08-27 15:11:16 +0000177 // allOf leads to one matcher for each alternative in the first
178 // matcher combined with each alternative in the second matcher.
179 // Thus, we can reuse the same Builder.
180 for (size_t i = 0, e = InnerMatchers.size(); i != e; ++i) {
Samuel Benzaquenf34ac3e2013-10-29 14:37:15 +0000181 if (!InnerMatchers[i].matches(DynNode, Finder, Builder))
Samuel Benzaquen85ec25d2013-08-27 15:11:16 +0000182 return false;
183 }
184 return true;
185}
186
187bool EachOfVariadicOperator(const ast_type_traits::DynTypedNode DynNode,
188 ASTMatchFinder *Finder,
189 BoundNodesTreeBuilder *Builder,
Samuel Benzaquenf34ac3e2013-10-29 14:37:15 +0000190 ArrayRef<DynTypedMatcher> InnerMatchers) {
Samuel Benzaquen85ec25d2013-08-27 15:11:16 +0000191 BoundNodesTreeBuilder Result;
192 bool Matched = false;
193 for (size_t i = 0, e = InnerMatchers.size(); i != e; ++i) {
194 BoundNodesTreeBuilder BuilderInner(*Builder);
Samuel Benzaquenf34ac3e2013-10-29 14:37:15 +0000195 if (InnerMatchers[i].matches(DynNode, Finder, &BuilderInner)) {
Samuel Benzaquen85ec25d2013-08-27 15:11:16 +0000196 Matched = true;
197 Result.addMatch(BuilderInner);
198 }
199 }
Benjamin Kramerd9c91622014-08-29 11:22:47 +0000200 *Builder = std::move(Result);
Samuel Benzaquen85ec25d2013-08-27 15:11:16 +0000201 return Matched;
202}
203
204bool AnyOfVariadicOperator(const ast_type_traits::DynTypedNode DynNode,
205 ASTMatchFinder *Finder,
206 BoundNodesTreeBuilder *Builder,
Samuel Benzaquenf34ac3e2013-10-29 14:37:15 +0000207 ArrayRef<DynTypedMatcher> InnerMatchers) {
Samuel Benzaquen85ec25d2013-08-27 15:11:16 +0000208 for (size_t i = 0, e = InnerMatchers.size(); i != e; ++i) {
209 BoundNodesTreeBuilder Result = *Builder;
Samuel Benzaquenf34ac3e2013-10-29 14:37:15 +0000210 if (InnerMatchers[i].matches(DynNode, Finder, &Result)) {
Benjamin Kramerd9c91622014-08-29 11:22:47 +0000211 *Builder = std::move(Result);
Samuel Benzaquen85ec25d2013-08-27 15:11:16 +0000212 return true;
213 }
214 }
215 return false;
216}
217
Manuel Klimek04616e42012-07-06 05:48:52 +0000218} // end namespace internal
219} // end namespace ast_matchers
220} // end namespace clang