16 #include "llvm/ADT/SmallString.h"
17 #include "llvm/ADT/SmallVector.h"
18 #include "llvm/Support/ManagedStatic.h"
21 namespace ast_matchers {
44 void BoundNodesTreeBuilder::visitMatches(Visitor *ResultVisitor) {
46 Bindings.push_back(BoundNodesMap());
47 for (BoundNodesMap &Binding : Bindings) {
48 ResultVisitor->visitMatch(
BoundNodes(Binding));
54 typedef bool (*VariadicOperatorFunction)(
55 const ast_type_traits::DynTypedNode &DynNode, ASTMatchFinder *
Finder,
58 template <VariadicOperatorFunction Func>
59 class VariadicMatcher :
public DynMatcherInterface {
62 : InnerMatchers(std::move(InnerMatchers)) {}
64 bool dynMatches(
const ast_type_traits::DynTypedNode &DynNode,
65 ASTMatchFinder *Finder,
66 BoundNodesTreeBuilder *Builder)
const override {
74 class IdDynMatcher :
public DynMatcherInterface {
76 IdDynMatcher(StringRef
ID,
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);
98 class TrueMatcherImpl :
public DynMatcherInterface {
103 bool dynMatches(
const ast_type_traits::DynTypedNode &, ASTMatchFinder *,
104 BoundNodesTreeBuilder *)
const override {
108 static llvm::ManagedStatic<TrueMatcherImpl> TrueMatcherInstance;
112 DynTypedMatcher DynTypedMatcher::constructVariadic(
113 DynTypedMatcher::VariadicOperator Op,
114 ast_type_traits::ASTNodeKind SupportedKind,
116 assert(InnerMatchers.size() > 0 &&
"Array must not be empty.");
117 assert(std::all_of(InnerMatchers.begin(), InnerMatchers.end(),
118 [SupportedKind](
const DynTypedMatcher &M) {
119 return M.canConvertTo(SupportedKind);
121 "InnerMatchers must be convertible to SupportedKind!");
127 auto RestrictKind = SupportedKind;
135 for (
auto &IM : InnerMatchers) {
137 RestrictKind, IM.RestrictKind);
139 return DynTypedMatcher(
140 SupportedKind, RestrictKind,
141 new VariadicMatcher<AllOfVariadicOperator>(std::move(InnerMatchers)));
144 return DynTypedMatcher(
145 SupportedKind, RestrictKind,
146 new VariadicMatcher<AnyOfVariadicOperator>(std::move(InnerMatchers)));
149 return DynTypedMatcher(
150 SupportedKind, RestrictKind,
151 new VariadicMatcher<EachOfVariadicOperator>(std::move(InnerMatchers)));
156 return DynTypedMatcher(
157 SupportedKind, RestrictKind,
158 new VariadicMatcher<NotUnaryOperator>(std::move(InnerMatchers)));
160 llvm_unreachable(
"Invalid Op value.");
163 DynTypedMatcher DynTypedMatcher::trueMatcher(
164 ast_type_traits::ASTNodeKind NodeKind) {
165 return DynTypedMatcher(NodeKind, NodeKind, &*TrueMatcherInstance);
168 bool DynTypedMatcher::canMatchNodesOfKind(
169 ast_type_traits::ASTNodeKind
Kind)
const {
170 return RestrictKind.isBaseOf(Kind);
173 DynTypedMatcher DynTypedMatcher::dynCastTo(
174 const ast_type_traits::ASTNodeKind Kind)
const {
176 Copy.SupportedKind =
Kind;
183 ASTMatchFinder *Finder,
184 BoundNodesTreeBuilder *Builder)
const {
185 if (RestrictKind.isBaseOf(DynNode.getNodeKind()) &&
186 Implementation->dynMatches(DynNode, Finder, Builder)) {
192 Builder->removeBindings([](
const BoundNodesMap &) {
return true; });
196 bool DynTypedMatcher::matchesNoKindCheck(
197 const ast_type_traits::DynTypedNode &DynNode, ASTMatchFinder *Finder,
198 BoundNodesTreeBuilder *Builder)
const {
199 assert(RestrictKind.isBaseOf(DynNode.getNodeKind()));
200 if (Implementation->dynMatches(DynNode, Finder, Builder)) {
206 Builder->removeBindings([](
const BoundNodesMap &) {
return true; });
213 Result.Implementation =
214 new IdDynMatcher(ID, std::move(Result.Implementation));
215 return std::move(Result);
218 bool DynTypedMatcher::canConvertTo(ast_type_traits::ASTNodeKind To)
const {
219 const auto From = getSupportedKind();
220 auto QualKind = ast_type_traits::ASTNodeKind::getFromNodeKind<QualType>();
221 auto TypeKind = ast_type_traits::ASTNodeKind::getFromNodeKind<Type>();
224 if (From.isSame(TypeKind) && To.isSame(QualKind))
return true;
226 return From.isBaseOf(To);
229 void BoundNodesTreeBuilder::addMatch(
const BoundNodesTreeBuilder &Other) {
230 Bindings.append(Other.Bindings.begin(), Other.Bindings.end());
234 ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder,
236 if (InnerMatchers.size() != 1)
249 BoundNodesTreeBuilder Discard(*Builder);
250 return !InnerMatchers[0].matches(DynNode, Finder, &Discard);
254 ASTMatchFinder *Finder,
255 BoundNodesTreeBuilder *Builder,
260 for (
const DynTypedMatcher &InnerMatcher : InnerMatchers) {
261 if (!InnerMatcher.matchesNoKindCheck(DynNode, Finder, Builder))
268 ASTMatchFinder *Finder,
269 BoundNodesTreeBuilder *Builder,
271 BoundNodesTreeBuilder Result;
272 bool Matched =
false;
273 for (
const DynTypedMatcher &InnerMatcher : InnerMatchers) {
274 BoundNodesTreeBuilder BuilderInner(*Builder);
275 if (InnerMatcher.matches(DynNode, Finder, &BuilderInner)) {
277 Result.addMatch(BuilderInner);
280 *Builder = std::move(Result);
285 ASTMatchFinder *Finder,
286 BoundNodesTreeBuilder *Builder,
288 for (
const DynTypedMatcher &InnerMatcher : InnerMatchers) {
289 BoundNodesTreeBuilder Result = *
Builder;
290 if (InnerMatcher.matches(DynNode, Finder, &Result)) {
291 *Builder = std::move(Result);
299 std::vector<std::string>
Names;
300 for (
auto *
Name : NameRefs)
301 Names.emplace_back(*
Name);
302 return internal::Matcher<NamedDecl>(
303 new internal::HasNameMatcher(std::move(Names)));
306 HasNameMatcher::HasNameMatcher(std::vector<std::string> N)
307 : UseUnqualifiedMatch(std::all_of(
309 [](StringRef
Name) {
return Name.find(
"::") ==
Name.npos; })),
313 assert(!
Name.empty());
319 bool consumeNameSuffix(StringRef &FullName, StringRef Suffix) {
320 StringRef
Name = FullName;
321 if (!Name.endswith(Suffix))
323 Name = Name.drop_back(Suffix.size());
325 if (!Name.endswith(
"::"))
327 Name = Name.drop_back(2);
335 if (Node.getIdentifier())
336 return Node.getName();
338 if (Node.getDeclName()) {
341 llvm::raw_svector_ostream OS(Scratch);
346 return "(anonymous)";
350 if (Node.getIdentifier()) {
351 return Node.getName();
354 return (
"(anonymous " + Node.getKindName() +
")").toStringRef(Scratch);
357 StringRef getNodeName(
const NamespaceDecl &Node,
359 return Node.isAnonymousNamespace() ?
"(anonymous namespace)" : Node.getName();
365 PatternSet(ArrayRef<std::string>
Names) {
366 for (StringRef Name : Names)
373 bool consumeNameSuffix(StringRef NodeName,
bool CanSkip) {
375 if (internal::consumeNameSuffix(
Patterns[
I].
P, NodeName) ||
388 bool foundMatch(
bool AllowFullyQualified)
const {
390 if (P.P.empty() && (AllowFullyQualified || !P.IsFullyQualified))
405 bool HasNameMatcher::matchesNodeUnqualified(
const NamedDecl &Node)
const {
406 assert(UseUnqualifiedMatch);
408 StringRef NodeName = getNodeName(Node, Scratch);
409 return std::any_of(Names.begin(), Names.end(), [&](StringRef
Name) {
410 return consumeNameSuffix(Name, NodeName) && Name.empty();
414 bool HasNameMatcher::matchesNodeFullFast(
const NamedDecl &Node)
const {
426 if (!
Patterns.consumeNameSuffix(getNodeName(Node, Scratch),
432 const DeclContext *Ctx = Node.getDeclContext();
434 if (Ctx->isFunctionOrMethod())
437 for (; Ctx && isa<NamedDecl>(Ctx); Ctx = Ctx->getParent()) {
441 if (
const auto *ND = dyn_cast<NamespaceDecl>(Ctx)) {
443 if (
Patterns.consumeNameSuffix(getNodeName(*ND, Scratch),
444 ND->isAnonymousNamespace() ||
449 if (
const auto *RD = dyn_cast<RecordDecl>(Ctx)) {
450 if (!isa<ClassTemplateSpecializationDecl>(Ctx)) {
451 if (
Patterns.consumeNameSuffix(getNodeName(*RD, Scratch),
461 return matchesNodeFullSlow(Node);
467 bool HasNameMatcher::matchesNodeFullSlow(
const NamedDecl &Node)
const {
468 const bool SkipUnwrittenCases[] = {
false,
true};
469 for (
bool SkipUnwritten : SkipUnwrittenCases) {
471 llvm::raw_svector_ostream OS(NodeName);
474 PrintingPolicy Policy = Node.getASTContext().getPrintingPolicy();
475 Policy.SuppressUnwrittenScope =
true;
476 Node.printQualifiedName(OS, Policy);
478 Node.printQualifiedName(OS);
481 const StringRef FullName = OS.str();
483 for (
const StringRef Pattern : Names) {
484 if (Pattern.startswith(
"::")) {
485 if (FullName == Pattern)
487 }
else if (FullName.endswith(Pattern) &&
488 FullName.drop_back(Pattern.size()).endswith(
"::")) {
497 bool HasNameMatcher::matchesNode(
const NamedDecl &Node)
const {
498 assert(matchesNodeFullFast(Node) == matchesNodeFullSlow(Node));
499 if (UseUnqualifiedMatch) {
500 assert(matchesNodeUnqualified(Node) == matchesNodeFullFast(Node));
501 return matchesNodeUnqualified(Node);
503 return matchesNodeFullFast(Node);
bool AnyOfVariadicOperator(const ast_type_traits::DynTypedNode &DynNode, ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder, ArrayRef< DynTypedMatcher > InnerMatchers)
llvm::SmallVector< Pattern, 8 > Patterns
bool NotUnaryOperator(const ast_type_traits::DynTypedNode &DynNode, ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder, ArrayRef< DynTypedMatcher > InnerMatchers)
std::vector< DynTypedMatcher > InnerMatchers
const IntrusiveRefCntPtr< DynMatcherInterface > InnerMatcher
bool EachOfVariadicOperator(const ast_type_traits::DynTypedNode &DynNode, ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder, ArrayRef< DynTypedMatcher > InnerMatchers)
detail::InMemoryDirectory::const_iterator I
bool AllOfVariadicOperator(const ast_type_traits::DynTypedNode &DynNode, ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder, ArrayRef< DynTypedMatcher > InnerMatchers)
Matcher< NamedDecl > hasAnyNameFunc(ArrayRef< const StringRef * > NameRefs)
static ASTNodeKind getMostDerivedType(ASTNodeKind Kind1, ASTNodeKind Kind2)
Return the most derived type between Kind1 and Kind2.
ASTMatchFinder *const Finder
BoundNodesTreeBuilder BoundNodes
ast_type_traits::DynTypedNode Node
A dynamically typed AST node container.
BoundNodesTreeBuilder *const Builder
bool matches(const til::SExpr *E1, const til::SExpr *E2)