[PATCH] D49840: [AST] Add MatchFinder::matchSubtree

Gabor Marton via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Fri Jul 27 01:39:49 PDT 2018


martong added a comment.

> MatchFinder::match allows you to match a node. Wrapping your matcher code with:
>  auto m = <my cool matcher>;
>  ast_matchers::match(anyOf(m, hashDescendant(m)), node, context);

Okay, I understand and accept that.
However, I consider that a different level of abstraction. `ast_matchers::match` uses `internal::CollectMatchesCallback` in its implementation. If I already have my own custom MatchCallback implemented then there is no way to achieve the desired behavior.

For example, in `ASTImporter` tests we use the following customized callback class:

  enum class DeclMatcherKind { First, Last };
  
  // Matcher class to retrieve the first/last matched node under a given AST.
  template <typename NodeType, DeclMatcherKind MatcherKind>
  class DeclMatcher : public MatchFinder::MatchCallback {
    NodeType *Node = nullptr;
    void run(const MatchFinder::MatchResult &Result) override {
      if ((MatcherKind == DeclMatcherKind::First && Node == nullptr) ||
          MatcherKind == DeclMatcherKind::Last) {
        Node = const_cast<NodeType *>(Result.Nodes.getNodeAs<NodeType>(""));
      }
    }
  public:
    // Returns the first/last matched node under the tree rooted in `D`.
    template <typename MatcherType>
    NodeType *match(const Decl *D, const MatcherType &AMatcher) {
      MatchFinder Finder;
      Finder.addMatcher(AMatcher.bind(""), this);
      Finder.matchAST(D->getASTContext());
      assert(Node);
      return Node;
    }
  };
  template <typename NodeType>
  using LastDeclMatcher = DeclMatcher<NodeType, DeclMatcherKind::Last>;
  template <typename NodeType>
  using FirstDeclMatcher = DeclMatcher<NodeType, DeclMatcherKind::First>;

And this is how we use it in the tests:

  Decl *FromTU = getTuDecl("void f(); void f(); void f();", Lang_CXX);
  auto Pattern = functionDecl(hasName("f"));
  auto *D0 = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
  auto *D2 = LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);

At this point we would like to extend this `DeclMatcher` to be able to match a subtree, and be able to start the traverse from a specific `Decl`, something like this :

  auto *DV = FirsDeclMatcher<VarDecl>().match(D2, SomeOtherPattern);

Currently, I don't see how we could do this extension without the proposed `matchSubtree`. 
(Perhaps, we could refactor our `DeclMatcher` to not use a customized MatchCallback, rather use `ast_matchers::match`, but that sounds like a bad workaround to me.)

Hope this makes the the goal of this patch cleaner.


Repository:
  rC Clang

https://reviews.llvm.org/D49840





More information about the cfe-commits mailing list