[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