blob: b5d4b52ade22fa91f695bd4d396cb5173dafc8e9 [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());
26 for (unsigned i = 0, e = Bindings.size(); i != e; ++i) {
27 ResultVisitor->visitMatch(BoundNodes(Bindings[i]));
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.
74struct TrueMatcherImpl {
75 TrueMatcherImpl() : Instance(new Impl) {}
76 const IntrusiveRefCntPtr<DynMatcherInterface> Instance;
77
78 class Impl : public DynMatcherInterface {
79 public:
80 bool dynMatches(const ast_type_traits::DynTypedNode &, ASTMatchFinder *,
81 BoundNodesTreeBuilder *) const override {
82 return true;
83 }
84 };
85};
86static llvm::ManagedStatic<TrueMatcherImpl> TrueMatcherInstance;
87
Samuel Benzaquenf28d9972014-10-01 15:08:07 +000088} // namespace
89
90DynTypedMatcher DynTypedMatcher::constructVariadic(
91 VariadicOperatorFunction Func, std::vector<DynTypedMatcher> InnerMatchers) {
92 assert(InnerMatchers.size() > 0 && "Array must not be empty.");
Samuel Benzaquen20099602014-10-13 17:38:12 +000093 assert(std::all_of(InnerMatchers.begin(), InnerMatchers.end(),
94 [&InnerMatchers](const DynTypedMatcher &M) {
95 return InnerMatchers[0].SupportedKind.isSame(M.SupportedKind);
96 }) &&
97 "SupportedKind must match!");
98
99 // We must relax the restrict kind here.
100 // The different operators might deal differently with a mismatch.
101 // Make it the same as SupportedKind, since that is the broadest type we are
102 // allowed to accept.
Samuel Benzaquen193d87f2014-10-13 18:17:11 +0000103 auto SupportedKind = InnerMatchers[0].SupportedKind;
104 return DynTypedMatcher(SupportedKind, SupportedKind,
Samuel Benzaquen20099602014-10-13 17:38:12 +0000105 new VariadicMatcher(Func, std::move(InnerMatchers)));
Samuel Benzaquenf28d9972014-10-01 15:08:07 +0000106}
107
Samuel Benzaquen96039d72014-10-09 19:28:18 +0000108DynTypedMatcher DynTypedMatcher::trueMatcher(
109 ast_type_traits::ASTNodeKind NodeKind) {
110 return DynTypedMatcher(NodeKind, NodeKind, TrueMatcherInstance->Instance);
111}
112
Samuel Benzaquenf28d9972014-10-01 15:08:07 +0000113DynTypedMatcher DynTypedMatcher::dynCastTo(
114 const ast_type_traits::ASTNodeKind Kind) const {
115 auto Copy = *this;
116 Copy.SupportedKind = Kind;
Samuel Benzaquena1170022014-10-06 13:14:30 +0000117 Copy.RestrictKind =
118 ast_type_traits::ASTNodeKind::getMostDerivedType(Kind, RestrictKind);
Samuel Benzaquenf28d9972014-10-01 15:08:07 +0000119 return Copy;
120}
121
122bool DynTypedMatcher::matches(const ast_type_traits::DynTypedNode &DynNode,
123 ASTMatchFinder *Finder,
124 BoundNodesTreeBuilder *Builder) const {
125 if (RestrictKind.isBaseOf(DynNode.getNodeKind()) &&
126 Implementation->dynMatches(DynNode, Finder, Builder)) {
127 return true;
128 }
129 // Delete all bindings when a matcher does not match.
130 // This prevents unexpected exposure of bound nodes in unmatches
131 // branches of the match tree.
132 Builder->removeBindings([](const BoundNodesMap &) { return true; });
133 return false;
134}
135
136llvm::Optional<DynTypedMatcher> DynTypedMatcher::tryBind(StringRef ID) const {
137 if (!AllowBind) return llvm::None;
138 auto Result = *this;
139 Result.Implementation = new IdDynMatcher(ID, Result.Implementation);
140 return Result;
141}
142
Samuel Benzaquenab005ed2014-09-04 14:13:58 +0000143bool DynTypedMatcher::canConvertTo(ast_type_traits::ASTNodeKind To) const {
144 const auto From = getSupportedKind();
145 auto QualKind = ast_type_traits::ASTNodeKind::getFromNodeKind<QualType>();
146 auto TypeKind = ast_type_traits::ASTNodeKind::getFromNodeKind<Type>();
147 /// Mimic the implicit conversions of Matcher<>.
148 /// - From Matcher<Type> to Matcher<QualType>
149 if (From.isSame(TypeKind) && To.isSame(QualKind)) return true;
150 /// - From Matcher<Base> to Matcher<Derived>
151 return From.isBaseOf(To);
152}
153
Manuel Klimeka0c025f2013-06-19 15:42:45 +0000154void BoundNodesTreeBuilder::addMatch(const BoundNodesTreeBuilder &Other) {
155 for (unsigned i = 0, e = Other.Bindings.size(); i != e; ++i) {
156 Bindings.push_back(Other.Bindings[i]);
Daniel Jasper94a56852012-11-16 18:39:22 +0000157 }
Manuel Klimek021d56f2012-08-28 23:26:39 +0000158}
159
Samuel Benzaquen4d058742013-11-22 14:41:48 +0000160bool NotUnaryOperator(const ast_type_traits::DynTypedNode DynNode,
161 ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder,
162 ArrayRef<DynTypedMatcher> InnerMatchers) {
163 if (InnerMatchers.size() != 1)
164 return false;
165
166 // The 'unless' matcher will always discard the result:
167 // If the inner matcher doesn't match, unless returns true,
168 // but the inner matcher cannot have bound anything.
169 // If the inner matcher matches, the result is false, and
170 // any possible binding will be discarded.
171 // We still need to hand in all the bound nodes up to this
172 // point so the inner matcher can depend on bound nodes,
173 // and we need to actively discard the bound nodes, otherwise
174 // the inner matcher will reset the bound nodes if it doesn't
175 // match, but this would be inversed by 'unless'.
176 BoundNodesTreeBuilder Discard(*Builder);
177 return !InnerMatchers[0].matches(DynNode, Finder, &Discard);
178}
179
Samuel Benzaquen85ec25d2013-08-27 15:11:16 +0000180bool AllOfVariadicOperator(const ast_type_traits::DynTypedNode DynNode,
181 ASTMatchFinder *Finder,
182 BoundNodesTreeBuilder *Builder,
Samuel Benzaquenf34ac3e2013-10-29 14:37:15 +0000183 ArrayRef<DynTypedMatcher> InnerMatchers) {
Samuel Benzaquen85ec25d2013-08-27 15:11:16 +0000184 // allOf leads to one matcher for each alternative in the first
185 // matcher combined with each alternative in the second matcher.
186 // Thus, we can reuse the same Builder.
187 for (size_t i = 0, e = InnerMatchers.size(); i != e; ++i) {
Samuel Benzaquenf34ac3e2013-10-29 14:37:15 +0000188 if (!InnerMatchers[i].matches(DynNode, Finder, Builder))
Samuel Benzaquen85ec25d2013-08-27 15:11:16 +0000189 return false;
190 }
191 return true;
192}
193
194bool EachOfVariadicOperator(const ast_type_traits::DynTypedNode DynNode,
195 ASTMatchFinder *Finder,
196 BoundNodesTreeBuilder *Builder,
Samuel Benzaquenf34ac3e2013-10-29 14:37:15 +0000197 ArrayRef<DynTypedMatcher> InnerMatchers) {
Samuel Benzaquen85ec25d2013-08-27 15:11:16 +0000198 BoundNodesTreeBuilder Result;
199 bool Matched = false;
200 for (size_t i = 0, e = InnerMatchers.size(); i != e; ++i) {
201 BoundNodesTreeBuilder BuilderInner(*Builder);
Samuel Benzaquenf34ac3e2013-10-29 14:37:15 +0000202 if (InnerMatchers[i].matches(DynNode, Finder, &BuilderInner)) {
Samuel Benzaquen85ec25d2013-08-27 15:11:16 +0000203 Matched = true;
204 Result.addMatch(BuilderInner);
205 }
206 }
Benjamin Kramerd9c91622014-08-29 11:22:47 +0000207 *Builder = std::move(Result);
Samuel Benzaquen85ec25d2013-08-27 15:11:16 +0000208 return Matched;
209}
210
211bool AnyOfVariadicOperator(const ast_type_traits::DynTypedNode DynNode,
212 ASTMatchFinder *Finder,
213 BoundNodesTreeBuilder *Builder,
Samuel Benzaquenf34ac3e2013-10-29 14:37:15 +0000214 ArrayRef<DynTypedMatcher> InnerMatchers) {
Samuel Benzaquen85ec25d2013-08-27 15:11:16 +0000215 for (size_t i = 0, e = InnerMatchers.size(); i != e; ++i) {
216 BoundNodesTreeBuilder Result = *Builder;
Samuel Benzaquenf34ac3e2013-10-29 14:37:15 +0000217 if (InnerMatchers[i].matches(DynNode, Finder, &Result)) {
Benjamin Kramerd9c91622014-08-29 11:22:47 +0000218 *Builder = std::move(Result);
Samuel Benzaquen85ec25d2013-08-27 15:11:16 +0000219 return true;
220 }
221 }
222 return false;
223}
224
Samuel Benzaquen8513d622014-10-15 14:58:46 +0000225HasNameMatcher::HasNameMatcher(StringRef NameRef)
226 : UseUnqualifiedMatch(NameRef.find("::") == NameRef.npos), Name(NameRef) {
227 assert(!Name.empty());
228}
229
230bool HasNameMatcher::matchesNodeUnqualified(const NamedDecl &Node) const {
231 assert(UseUnqualifiedMatch);
232 if (Node.getIdentifier()) {
233 // Simple name.
234 return Name == Node.getName();
235 } else if (Node.getDeclName()) {
236 // Name needs to be constructed.
237 llvm::SmallString<128> NodeName;
238 llvm::raw_svector_ostream OS(NodeName);
239 Node.printName(OS);
240 return Name == OS.str();
241 } else {
242 return false;
243 }
244}
245
246bool HasNameMatcher::matchesNodeFull(const NamedDecl &Node) const {
247 llvm::SmallString<128> NodeName = StringRef("::");
248 llvm::raw_svector_ostream OS(NodeName);
249 Node.printQualifiedName(OS);
250 const StringRef FullName = OS.str();
251 const StringRef Pattern = Name;
252 if (Pattern.startswith("::")) {
253 return FullName == Pattern;
254 } else {
255 return FullName.endswith(("::" + Pattern).str());
256 }
257}
258
259bool HasNameMatcher::matchesNode(const NamedDecl &Node) const {
260 // FIXME: There is still room for improvement, but it would require copying a
261 // lot of the logic from NamedDecl::printQualifiedName(). The benchmarks do
262 // not show like that extra complexity is needed right now.
263 if (UseUnqualifiedMatch) {
264 assert(matchesNodeUnqualified(Node) == matchesNodeFull(Node));
265 return matchesNodeUnqualified(Node);
266 }
267 return matchesNodeFull(Node);
268}
269
Manuel Klimek04616e42012-07-06 05:48:52 +0000270} // end namespace internal
271} // end namespace ast_matchers
272} // end namespace clang