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

Gabor Marton via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Fri Jul 27 03:43:54 PDT 2018


martong added a comment.

> Finder.match also has an overload that takes the node. Can you wrap "Pattern" above in the anyOf(hasDescendant(...), ...) and match on the node instead of the full AST?

Ok, I changed and wrapped the pattern:

  template <typename MatcherType>
  NodeType *match(const Decl *D, const MatcherType &AMatcher) {
    MatchFinder Finder;
    auto WrappedMatcher = anyOf(AMatcher.bind(""), hasDescendant(AMatcher.bind("")));
    Finder.addMatcher(WrappedMatcher, this);
    // ...
  }

But this results in an ambigous call of `addMatcher` because the compiler cannot choose the appropriate overload:

  ../../git/llvm/tools/clang/unittests/AST/DeclMatcher.h:36:12: error: call to member function 'addMatcher' is ambiguous
      Finder.addMatcher(WrappedMatcher, this);
      ~~~~~~~^~~~~~~~~~
  ...
  ../../git/llvm/tools/clang/include/clang/ASTMatchers/ASTMatchFinder.h:149:8: note: candidate function
    void addMatcher(const DeclarationMatcher &NodeMatch,
         ^
  ../../git/llvm/tools/clang/include/clang/ASTMatchers/ASTMatchFinder.h:151:8: note: candidate function
    void addMatcher(const TypeMatcher &NodeMatch,
         ^
  ../../git/llvm/tools/clang/include/clang/ASTMatchers/ASTMatchFinder.h:153:8: note: candidate function
    void addMatcher(const StatementMatcher &NodeMatch,
         ^
  ../../git/llvm/tools/clang/include/clang/ASTMatchers/ASTMatchFinder.h:155:8: note: candidate function
    void addMatcher(const NestedNameSpecifierMatcher &NodeMatch,
         ^
  ../../git/llvm/tools/clang/include/clang/ASTMatchers/ASTMatchFinder.h:157:8: note: candidate function
    void addMatcher(const NestedNameSpecifierLocMatcher &NodeMatch,
         ^
  ../../git/llvm/tools/clang/include/clang/ASTMatchers/ASTMatchFinder.h:159:8: note: candidate function
    void addMatcher(const TypeLocMatcher &NodeMatch,
         ^
  ../../git/llvm/tools/clang/include/clang/ASTMatchers/ASTMatchFinder.h:161:8: note: candidate function
    void addMatcher(const CXXCtorInitializerMatcher &NodeMatch,
         ^

This seems quite logical to me, since `anyOf` wraps many matchers, which could refer to Nodes with different type.
So, I went on and specified which overload to call (note, from this point this is getting hacky and would not consider such an API easy to use):

  And then I gave up.
    template <typename MatcherType>
    NodeType *match(const Decl *D, const MatcherType &AMatcher) {
      MatchFinder Finder;
      auto WrappedMatcher = anyOf(AMatcher.bind(""), hasDescendant(AMatcher.bind("")));
      auto PtrToMemFun = static_cast<void (MatchFinder::*)(
          const DeclarationMatcher&, MatchCallback*)>(&MatchFinder::addMatcher);
      (Finder.*PtrToMemFun)(WrappedMatcher, this);

This time it turned out that we can't just add a matcker like this because `getMatchers` in `anyOf` would call the private ctor of `Matcher`:

  ../../git/llvm/tools/clang/include/clang/ASTMatchers/ASTMatchersInternal.h:1339:13: error: calling a private constructor of class 'clang::ast_matchers::internal::Matcher<clang::Decl>'
      return {Matcher<T>(std::get<Is>(Params))...};
              ^
  ../../git/llvm/tools/clang/include/clang/ASTMatchers/ASTMatchersInternal.h:1331:16: note: in instantiation of function template specialization 'clang::ast_matchers::internal::VariadicOperatorMatcher<clang::ast_matchers::internal::Matcher<clang::Stmt>, clang::ast_matchers::internal::ArgumentAdaptingMatcherFunc<internal::HasDescendantMatcher, clang::ast_matchers::internal::TypeList<clang::Decl, clang::Stmt, clang::NestedNameSpecifier, clang::NestedNameSpecifierLoc, clang::QualType, clang::Type, clang::TypeLoc, clang::CXXCtorInitializer>, clang::ast_matchers::internal::TypeList<clang::Decl, clang::Stmt, clang::NestedNameSpecifier, clang::NestedNameSpecifierLoc, clang::TypeLoc, clang::QualType> >::Adaptor<clang::Stmt> >::getMatchers<clang::Decl, 0, 1>' requested here
                 getMatchers<T>(llvm::index_sequence_for<Ps...>()))
                 ^

As an alternative, I tried to call addDynamicMatcher, which resulted in a conversion error:

  template <typename MatcherType>
  NodeType *match(const Decl *D, const MatcherType &AMatcher) {
    MatchFinder Finder;
    auto WrappedMatcher = anyOf(AMatcher.bind(""), hasDescendant(AMatcher.bind("")));
    Finder.addDynamicMatcher(WrappedMatcher, this);

  ../../git/llvm/tools/clang/unittests/AST/DeclMatcher.h:40:30: error: no viable conversion from 'clang::ast_matchers::internal::VariadicOperatorMatcher<clang::ast_matchers::internal::Matcher<clang::Decl>, clang::ast_matchers::internal::ArgumentAdaptingMatcherFunc<internal::HasDescendantMatcher, clang::ast_matchers::internal::TypeList<clang::Decl, clang::Stmt, clang::NestedNameSpecifier, clang::NestedNameSpecifierLoc, clang::QualType, clang::Type, clang::TypeLoc, clang::CXXCtorInitializer>, clang::ast_matchers::internal::TypeList<clang::Decl, clang::Stmt, clang::NestedNameSpecifier, clang::NestedNameSpecifierLoc, clang::TypeLoc, clang::QualType> >::Adaptor<clang::Decl> >' to 'const internal::DynTypedMatcher'
      Finder.addDynamicMatcher(WrappedMatcher, this);
                               ^~~~~~~~~~~~~~

Perhaps I am doing something wrong because I really could not find a way to add the wrapped matcher.
These results motivated me to double check your original idea of using `ast_matchers::match`:

  Decl *FromTU = getTuDecl("void f();", Lang_CXX);
  auto Pattern = functionDecl(hasName("f"));
  match(anyOf(Pattern, hasDescendant(Pattern)), FromTU, FromTU->getASTContext());

This resulted an ambigous call again, but this time the compiler could not resolve the call inside `ast_matchers::match`:

  ../../git/llvm/tools/clang/include/clang/ASTMatchers/ASTMatchFinder.h:301:10: error: call to member function 'addMatcher' is ambiguous
    Finder.addMatcher(Matcher, &Callback);
    ~~~~~~~^~~~~~~~~~


Repository:
  rC Clang

https://reviews.llvm.org/D49840





More information about the cfe-commits mailing list