blob: af6f0abfb9bb3f0ce80c88d05b8aac864d0e6b33 [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());
Benjamin Kramer79f15902014-10-24 13:29:15 +000026 for (BoundNodesMap &Binding : Bindings) {
27 ResultVisitor->visitMatch(BoundNodes(Binding));
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:
Samuel Benzaquen9743c9d2014-11-17 14:55:49 +000035 VariadicMatcher(DynTypedMatcher::VariadicOperatorFunction Func,
Samuel Benzaquenf28d9972014-10-01 15:08:07 +000036 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:
Samuel Benzaquen9743c9d2014-11-17 14:55:49 +000046 DynTypedMatcher::VariadicOperatorFunction Func;
Samuel Benzaquenf28d9972014-10-01 15:08:07 +000047 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.
Benjamin Kramer967c0792014-10-24 13:29:21 +000074class TrueMatcherImpl : public DynMatcherInterface {
75public:
76 TrueMatcherImpl() {
77 Retain(); // Reference count will never become zero.
78 }
79 bool dynMatches(const ast_type_traits::DynTypedNode &, ASTMatchFinder *,
80 BoundNodesTreeBuilder *) const override {
81 return true;
82 }
Samuel Benzaquen96039d72014-10-09 19:28:18 +000083};
84static llvm::ManagedStatic<TrueMatcherImpl> TrueMatcherInstance;
85
Samuel Benzaquenf28d9972014-10-01 15:08:07 +000086} // namespace
87
88DynTypedMatcher DynTypedMatcher::constructVariadic(
Samuel Benzaquen9743c9d2014-11-17 14:55:49 +000089 DynTypedMatcher::VariadicOperatorFunction Func,
90 std::vector<DynTypedMatcher> InnerMatchers) {
Samuel Benzaquenf28d9972014-10-01 15:08:07 +000091 assert(InnerMatchers.size() > 0 && "Array must not be empty.");
Samuel Benzaquen20099602014-10-13 17:38:12 +000092 assert(std::all_of(InnerMatchers.begin(), InnerMatchers.end(),
93 [&InnerMatchers](const DynTypedMatcher &M) {
94 return InnerMatchers[0].SupportedKind.isSame(M.SupportedKind);
95 }) &&
96 "SupportedKind must match!");
97
98 // We must relax the restrict kind here.
99 // The different operators might deal differently with a mismatch.
100 // Make it the same as SupportedKind, since that is the broadest type we are
101 // allowed to accept.
Samuel Benzaquen193d87f2014-10-13 18:17:11 +0000102 auto SupportedKind = InnerMatchers[0].SupportedKind;
103 return DynTypedMatcher(SupportedKind, SupportedKind,
Samuel Benzaquen20099602014-10-13 17:38:12 +0000104 new VariadicMatcher(Func, std::move(InnerMatchers)));
Samuel Benzaquenf28d9972014-10-01 15:08:07 +0000105}
106
Samuel Benzaquen96039d72014-10-09 19:28:18 +0000107DynTypedMatcher DynTypedMatcher::trueMatcher(
108 ast_type_traits::ASTNodeKind NodeKind) {
Benjamin Kramer967c0792014-10-24 13:29:21 +0000109 return DynTypedMatcher(NodeKind, NodeKind, &*TrueMatcherInstance);
Samuel Benzaquen96039d72014-10-09 19:28:18 +0000110}
111
Samuel Benzaquenf28d9972014-10-01 15:08:07 +0000112DynTypedMatcher DynTypedMatcher::dynCastTo(
113 const ast_type_traits::ASTNodeKind Kind) const {
114 auto Copy = *this;
115 Copy.SupportedKind = Kind;
Samuel Benzaquena1170022014-10-06 13:14:30 +0000116 Copy.RestrictKind =
117 ast_type_traits::ASTNodeKind::getMostDerivedType(Kind, RestrictKind);
Samuel Benzaquenf28d9972014-10-01 15:08:07 +0000118 return Copy;
119}
120
121bool DynTypedMatcher::matches(const ast_type_traits::DynTypedNode &DynNode,
122 ASTMatchFinder *Finder,
123 BoundNodesTreeBuilder *Builder) const {
124 if (RestrictKind.isBaseOf(DynNode.getNodeKind()) &&
125 Implementation->dynMatches(DynNode, Finder, Builder)) {
126 return true;
127 }
128 // Delete all bindings when a matcher does not match.
129 // This prevents unexpected exposure of bound nodes in unmatches
130 // branches of the match tree.
131 Builder->removeBindings([](const BoundNodesMap &) { return true; });
132 return false;
133}
134
135llvm::Optional<DynTypedMatcher> DynTypedMatcher::tryBind(StringRef ID) const {
136 if (!AllowBind) return llvm::None;
137 auto Result = *this;
138 Result.Implementation = new IdDynMatcher(ID, Result.Implementation);
139 return Result;
140}
141
Samuel Benzaquenab005ed2014-09-04 14:13:58 +0000142bool DynTypedMatcher::canConvertTo(ast_type_traits::ASTNodeKind To) const {
143 const auto From = getSupportedKind();
144 auto QualKind = ast_type_traits::ASTNodeKind::getFromNodeKind<QualType>();
145 auto TypeKind = ast_type_traits::ASTNodeKind::getFromNodeKind<Type>();
146 /// Mimic the implicit conversions of Matcher<>.
147 /// - From Matcher<Type> to Matcher<QualType>
148 if (From.isSame(TypeKind) && To.isSame(QualKind)) return true;
149 /// - From Matcher<Base> to Matcher<Derived>
150 return From.isBaseOf(To);
151}
152
Manuel Klimeka0c025f2013-06-19 15:42:45 +0000153void BoundNodesTreeBuilder::addMatch(const BoundNodesTreeBuilder &Other) {
Benjamin Kramer79f15902014-10-24 13:29:15 +0000154 Bindings.append(Other.Bindings.begin(), Other.Bindings.end());
Manuel Klimek021d56f2012-08-28 23:26:39 +0000155}
156
Samuel Benzaquen4d058742013-11-22 14:41:48 +0000157bool NotUnaryOperator(const ast_type_traits::DynTypedNode DynNode,
158 ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder,
159 ArrayRef<DynTypedMatcher> InnerMatchers) {
160 if (InnerMatchers.size() != 1)
161 return false;
162
163 // The 'unless' matcher will always discard the result:
164 // If the inner matcher doesn't match, unless returns true,
165 // but the inner matcher cannot have bound anything.
166 // If the inner matcher matches, the result is false, and
167 // any possible binding will be discarded.
168 // We still need to hand in all the bound nodes up to this
169 // point so the inner matcher can depend on bound nodes,
170 // and we need to actively discard the bound nodes, otherwise
171 // the inner matcher will reset the bound nodes if it doesn't
172 // match, but this would be inversed by 'unless'.
173 BoundNodesTreeBuilder Discard(*Builder);
174 return !InnerMatchers[0].matches(DynNode, Finder, &Discard);
175}
176
Samuel Benzaquen85ec25d2013-08-27 15:11:16 +0000177bool AllOfVariadicOperator(const ast_type_traits::DynTypedNode DynNode,
178 ASTMatchFinder *Finder,
179 BoundNodesTreeBuilder *Builder,
Samuel Benzaquenf34ac3e2013-10-29 14:37:15 +0000180 ArrayRef<DynTypedMatcher> InnerMatchers) {
Samuel Benzaquen85ec25d2013-08-27 15:11:16 +0000181 // allOf leads to one matcher for each alternative in the first
182 // matcher combined with each alternative in the second matcher.
183 // Thus, we can reuse the same Builder.
Benjamin Kramer79f15902014-10-24 13:29:15 +0000184 for (const DynTypedMatcher &InnerMatcher : InnerMatchers) {
185 if (!InnerMatcher.matches(DynNode, Finder, Builder))
Samuel Benzaquen85ec25d2013-08-27 15:11:16 +0000186 return false;
187 }
188 return true;
189}
190
191bool EachOfVariadicOperator(const ast_type_traits::DynTypedNode DynNode,
192 ASTMatchFinder *Finder,
193 BoundNodesTreeBuilder *Builder,
Samuel Benzaquenf34ac3e2013-10-29 14:37:15 +0000194 ArrayRef<DynTypedMatcher> InnerMatchers) {
Samuel Benzaquen85ec25d2013-08-27 15:11:16 +0000195 BoundNodesTreeBuilder Result;
196 bool Matched = false;
Benjamin Kramer79f15902014-10-24 13:29:15 +0000197 for (const DynTypedMatcher &InnerMatcher : InnerMatchers) {
Samuel Benzaquen85ec25d2013-08-27 15:11:16 +0000198 BoundNodesTreeBuilder BuilderInner(*Builder);
Benjamin Kramer79f15902014-10-24 13:29:15 +0000199 if (InnerMatcher.matches(DynNode, Finder, &BuilderInner)) {
Samuel Benzaquen85ec25d2013-08-27 15:11:16 +0000200 Matched = true;
201 Result.addMatch(BuilderInner);
202 }
203 }
Benjamin Kramerd9c91622014-08-29 11:22:47 +0000204 *Builder = std::move(Result);
Samuel Benzaquen85ec25d2013-08-27 15:11:16 +0000205 return Matched;
206}
207
208bool AnyOfVariadicOperator(const ast_type_traits::DynTypedNode DynNode,
209 ASTMatchFinder *Finder,
210 BoundNodesTreeBuilder *Builder,
Samuel Benzaquenf34ac3e2013-10-29 14:37:15 +0000211 ArrayRef<DynTypedMatcher> InnerMatchers) {
Benjamin Kramer79f15902014-10-24 13:29:15 +0000212 for (const DynTypedMatcher &InnerMatcher : InnerMatchers) {
Samuel Benzaquen85ec25d2013-08-27 15:11:16 +0000213 BoundNodesTreeBuilder Result = *Builder;
Benjamin Kramer79f15902014-10-24 13:29:15 +0000214 if (InnerMatcher.matches(DynNode, Finder, &Result)) {
Benjamin Kramerd9c91622014-08-29 11:22:47 +0000215 *Builder = std::move(Result);
Samuel Benzaquen85ec25d2013-08-27 15:11:16 +0000216 return true;
217 }
218 }
219 return false;
220}
221
Samuel Benzaquen8513d622014-10-15 14:58:46 +0000222HasNameMatcher::HasNameMatcher(StringRef NameRef)
223 : UseUnqualifiedMatch(NameRef.find("::") == NameRef.npos), Name(NameRef) {
224 assert(!Name.empty());
225}
226
227bool HasNameMatcher::matchesNodeUnqualified(const NamedDecl &Node) const {
228 assert(UseUnqualifiedMatch);
229 if (Node.getIdentifier()) {
230 // Simple name.
231 return Name == Node.getName();
Samuel Benzaquenb6f73bc2014-10-16 17:50:19 +0000232 }
233 if (Node.getDeclName()) {
Samuel Benzaquen8513d622014-10-15 14:58:46 +0000234 // Name needs to be constructed.
235 llvm::SmallString<128> NodeName;
236 llvm::raw_svector_ostream OS(NodeName);
237 Node.printName(OS);
238 return Name == OS.str();
Samuel Benzaquen8513d622014-10-15 14:58:46 +0000239 }
Samuel Benzaquenb6f73bc2014-10-16 17:50:19 +0000240 return false;
Samuel Benzaquen8513d622014-10-15 14:58:46 +0000241}
242
243bool HasNameMatcher::matchesNodeFull(const NamedDecl &Node) const {
244 llvm::SmallString<128> NodeName = StringRef("::");
245 llvm::raw_svector_ostream OS(NodeName);
246 Node.printQualifiedName(OS);
247 const StringRef FullName = OS.str();
248 const StringRef Pattern = Name;
Samuel Benzaquenb6f73bc2014-10-16 17:50:19 +0000249
250 if (Pattern.startswith("::"))
Samuel Benzaquen8513d622014-10-15 14:58:46 +0000251 return FullName == Pattern;
Samuel Benzaquenb6f73bc2014-10-16 17:50:19 +0000252
253 return FullName.endswith(Pattern) &&
254 FullName.drop_back(Pattern.size()).endswith("::");
Samuel Benzaquen8513d622014-10-15 14:58:46 +0000255}
256
257bool HasNameMatcher::matchesNode(const NamedDecl &Node) const {
258 // FIXME: There is still room for improvement, but it would require copying a
259 // lot of the logic from NamedDecl::printQualifiedName(). The benchmarks do
260 // not show like that extra complexity is needed right now.
261 if (UseUnqualifiedMatch) {
262 assert(matchesNodeUnqualified(Node) == matchesNodeFull(Node));
263 return matchesNodeUnqualified(Node);
264 }
265 return matchesNodeFull(Node);
266}
267
Manuel Klimek04616e42012-07-06 05:48:52 +0000268} // end namespace internal
269} // end namespace ast_matchers
270} // end namespace clang