[PATCH] D97784: [ASTMatchers] Always create a "binding" for the node being matched on.

2021-03-09 Thread Stephen Kelly via Phabricator via cfe-commits
steveire added a comment.

Can you add some tests for this?


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D97784/new/

https://reviews.llvm.org/D97784

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D97784: [ASTMatchers] Always create a "binding" for the node being matched on.

2021-03-02 Thread Nathan James via Phabricator via cfe-commits
njames93 created this revision.
njames93 added reviewers: klimek, aaron.ballman, steveire.
njames93 published this revision for review.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

Most often when using matchers, there is a need to get the root node that the 
matcher matched on.
Currently the only way to do this is to manually create a binding the the root 
matcher, however this has some drawbacks.
It can be prone to typos and there is no universal agreed name to give the root 
node, so an API that accepts a DynTypedMatcher wont be able to figure out what 
the root actually is.

By altering the infrastructure to always provide access to the node being 
matched on, that isn't dependent on names, it can simplify workflow a lot.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D97784

Files:
  clang/include/clang/ASTMatchers/ASTMatchFinder.h
  clang/include/clang/ASTMatchers/ASTMatchers.h
  clang/include/clang/ASTMatchers/ASTMatchersInternal.h
  clang/lib/ASTMatchers/ASTMatchFinder.cpp
  clang/lib/ASTMatchers/ASTMatchersInternal.cpp

Index: clang/lib/ASTMatchers/ASTMatchersInternal.cpp
===
--- clang/lib/ASTMatchers/ASTMatchersInternal.cpp
+++ clang/lib/ASTMatchers/ASTMatchersInternal.cpp
@@ -98,11 +98,12 @@
 /*LookupInDependent =*/true);
 }
 
-void BoundNodesTreeBuilder::visitMatches(Visitor *ResultVisitor) {
+void BoundNodesTreeBuilder::visitMatches(Visitor *ResultVisitor,
+ const DynTypedNode ) {
   if (Bindings.empty())
 Bindings.push_back(BoundNodesMap());
   for (BoundNodesMap  : Bindings) {
-ResultVisitor->visitMatch(BoundNodes(Binding));
+ResultVisitor->visitMatch(BoundNodes(Binding, RootNode));
   }
 }
 
Index: clang/lib/ASTMatchers/ASTMatchFinder.cpp
===
--- clang/lib/ASTMatchers/ASTMatchFinder.cpp
+++ clang/lib/ASTMatchers/ASTMatchFinder.cpp
@@ -815,7 +815,7 @@
   BoundNodesTreeBuilder Builder;
   if (MP.first.matches(Node, this, )) {
 MatchVisitor Visitor(ActiveASTContext, MP.second);
-Builder.visitMatches();
+Builder.visitMatches(, DynTypedNode::create(Node));
   }
 }
   }
@@ -847,7 +847,7 @@
 
   if (MP.first.matches(DynNode, this, )) {
 MatchVisitor Visitor(ActiveASTContext, MP.second);
-Builder.visitMatches();
+Builder.visitMatches(, DynNode);
   }
 }
   }
Index: clang/include/clang/ASTMatchers/ASTMatchersInternal.h
===
--- clang/include/clang/ASTMatchers/ASTMatchersInternal.h
+++ clang/include/clang/ASTMatchers/ASTMatchersInternal.h
@@ -248,7 +248,7 @@
   /// Visits all matches that this BoundNodesTree represents.
   ///
   /// The ownership of 'ResultVisitor' remains at the caller.
-  void visitMatches(Visitor* ResultVisitor);
+  void visitMatches(Visitor *ResultVisitor, const DynTypedNode );
 
   template 
   bool removeBindings(const ExcludePredicate ) {
Index: clang/include/clang/ASTMatchers/ASTMatchers.h
===
--- clang/include/clang/ASTMatchers/ASTMatchers.h
+++ clang/include/clang/ASTMatchers/ASTMatchers.h
@@ -125,14 +125,21 @@
 return MyBoundNodes.getMap();
   }
 
+  template  const T *getRootAs() const { return RootNode.get(); }
+
+  const DynTypedNode () const { return RootNode; }
+
 private:
   friend class internal::BoundNodesTreeBuilder;
 
   /// Create BoundNodes from a pre-filled map of bindings.
-  BoundNodes(internal::BoundNodesMap )
-  : MyBoundNodes(MyBoundNodes) {}
+  BoundNodes(internal::BoundNodesMap ,
+ const DynTypedNode )
+  : MyBoundNodes(MyBoundNodes), RootNode(RootNode) {}
 
   internal::BoundNodesMap MyBoundNodes;
+
+  DynTypedNode RootNode;
 };
 
 /// Types of matchers for the top-level classes in the AST class
Index: clang/include/clang/ASTMatchers/ASTMatchFinder.h
===
--- clang/include/clang/ASTMatchers/ASTMatchFinder.h
+++ clang/include/clang/ASTMatchers/ASTMatchFinder.h
@@ -280,6 +280,24 @@
   return nullptr;
 }
 
+/// Returns the first result of type \c NodeT bound to the root match result.
+///
+/// Returns \c NULL if there is no match, or if the matching node cannot be
+/// casted to \c NodeT.
+///
+/// This is useful in combanation with \c match():
+/// \code
+///   const Decl *D = selectFirst(match(DeclMatcher, Node, Context));
+/// \endcode
+template 
+const NodeT *selectFirst(const SmallVectorImpl ) {
+  for (const BoundNodes  : Results) {
+if (const NodeT *Node = N.getRootAs())
+  return Node;
+  }
+  return nullptr;
+}
+
 namespace internal {
 class CollectMatchesCallback : public MatchFinder::MatchCallback {
 public:
___
cfe-commits mailing list