[cfe-dev] [AST Matcher API] How to match against a subtree?
Gábor Márton via cfe-dev
cfe-dev at lists.llvm.org
Wed Jul 25 08:50:59 PDT 2018
Hi,
I'd like to do a traversal on a subtree rooted on a specific node, but
not on the whole tree rooted at the TranslataionUnitDecl. My
understanding is this is not possible today, or is it? I wonder why
this was not missing for anybody.
We can match **one** node against a matcher, but we will not traverse
into the children (this is MatchFinder::match).
Or we can traverse through the whole tree rooted at the TUDecl (this
is MatchFinder::matchAST).
Below, the short draft of my idea how could we support this, what do you think?
Thanks,
Gabor
diff --git a/include/clang/ASTMatchers/ASTMatchFinder.h
b/include/clang/ASTMatchers/ASTMatchFinder.h
index 389af1b..7610074 100644
--- a/include/clang/ASTMatchers/ASTMatchFinder.h
+++ b/include/clang/ASTMatchers/ASTMatchFinder.h
@@ -189,6 +189,15 @@ public:
ASTContext &Context);
/// @}
+ /// \brief Finds all matches in the given subtree rooted at \p Node
+ /// @{
+ template <typename T> void matchSubtree(const T &Node, ASTContext &Context) {
+ matchSubtree(clang::ast_type_traits::DynTypedNode::create(Node), Context);
+ }
+ void matchSubtree(const clang::ast_type_traits::DynTypedNode &Node,
+ ASTContext &Context);
+ /// @}
+
/// \brief Finds all matches in the given AST.
void matchAST(ASTContext &Context);
diff --git a/lib/ASTMatchers/ASTMatchFinder.cpp
b/lib/ASTMatchers/ASTMatchFinder.cpp
index 02aee4b..ec37e95 100644
--- a/lib/ASTMatchers/ASTMatchFinder.cpp
+++ b/lib/ASTMatchers/ASTMatchFinder.cpp
@@ -1018,6 +1018,31 @@ void MatchFinder::matchAST(ASTContext &Context) {
Visitor.onEndOfTranslationUnit();
}
+void MatchFinder::matchSubtree(const
clang::ast_type_traits::DynTypedNode &Node,
+ ASTContext &Context) {
+ internal::MatchASTVisitor Visitor(&Matchers, Options);
+ Visitor.set_active_ast_context(&Context);
+ Visitor.onStartOfTranslationUnit(); // Is it needed ???
+ Visitor.TraverseDecl(Context.getTranslationUnitDecl());
+ // FIXME: Improve this with a switch or a visitor pattern.
+ if (auto *N = Node.get<Decl>()) {
+ Visitor.TraverseDecl(const_cast<Decl*>(N));
+ } else if (auto *N = Node.get<Stmt>()) {
+ Visitor.TraverseStmt(const_cast<Stmt*>(N));
+ } else if (auto *N = Node.get<QualType>()) {
+ Visitor.TraverseType(*N);
+ } else if (auto *N = Node.get<TypeLoc>()) {
+ Visitor.TraverseTypeLoc(*N);
+ } else if (auto *N = Node.get<NestedNameSpecifier>()) {
+ Visitor.TraverseNestedNameSpecifier(const_cast<NestedNameSpecifier*>(N));
+ } else if (auto *N = Node.get<NestedNameSpecifierLoc>()) {
+ Visitor.TraverseNestedNameSpecifierLoc(*N);
+ } else if (auto *N = Node.get<CXXCtorInitializer>()) {
+ Visitor.TraverseConstructorInitializer(const_cast<CXXCtorInitializer*>(N));
+ }
+ Visitor.onEndOfTranslationUnit(); // Is it needed ???
+}
+
More information about the cfe-dev
mailing list