如何让 RecursiveASTVisitor 中止当前子树
How to let RecursiveASTVisitor abort current subtree
在使用Clang LibTooling的RecursiveASTVisitor时,如何让库中止扫描当前访问的AST节点下的子树?
RecursiveASTVisitor 在 AST 上使用 depth-first 遍历,可以很容易地中止某些子树并继续遍历。
例如(请阅读代码中的注释):
virtual bool VisitCXXRecordDecl(CXXRecordDecl *decl) {
//some code to tell the lib not to traverse the subtree
//under the currently visited node i.e. decl
//but still continue the traversal
//so that the scan process will skip all AST nodes under any
//CXXRecordDecl in the AST
}
我认为从 Visit*** 方法中 return false 会达到这个目标,但它确实告诉 lib 一起结束遍历,而不是跳过子树。
不考虑 ASTMatchers,因为目标只是标题中描述的目标。
确实,从 VisitXXX
函数之一返回 false
将终止整个遍历。
要跳过 AST 节点,您可以覆盖 TraverseXXX
并有选择地回退到超类型(即 RecursiveASTVisitor
)实现:
class ASTVisitor : public RecursiveASTVisitor<ASTVisitor> {
public:
bool TraverseCXXRecordDecl(CXXRecordDecl *decl) {
// Don't traverse skip_me
if (auto name = decl->getName(); name.equals("skip_me")) {
std::cout << "Skipping " << name.str() << '\n';
// Return true to continue AST traversal,
// but don't visit the node
return true;
}
// Call RecursiveASTVisitor's implementation to visit this node
return RecursiveASTVisitor::TraverseCXXRecordDecl(decl);
}
bool VisitFieldDecl(FieldDecl *decl) {
std::cout << "Visited field " << decl->getName().str() << '\n';
return true;
}
};
在此翻译单元上测试此访问者:
struct skip_me {
int skipped;
};
struct dont_skip_me {
int not_skipped;
};
产生以下输出:
Skipping skip_me
Visited field not_skipped
在使用Clang LibTooling的RecursiveASTVisitor时,如何让库中止扫描当前访问的AST节点下的子树?
RecursiveASTVisitor 在 AST 上使用 depth-first 遍历,可以很容易地中止某些子树并继续遍历。
例如(请阅读代码中的注释):
virtual bool VisitCXXRecordDecl(CXXRecordDecl *decl) {
//some code to tell the lib not to traverse the subtree
//under the currently visited node i.e. decl
//but still continue the traversal
//so that the scan process will skip all AST nodes under any
//CXXRecordDecl in the AST
}
我认为从 Visit*** 方法中 return false 会达到这个目标,但它确实告诉 lib 一起结束遍历,而不是跳过子树。
不考虑 ASTMatchers,因为目标只是标题中描述的目标。
确实,从 VisitXXX
函数之一返回 false
将终止整个遍历。
要跳过 AST 节点,您可以覆盖 TraverseXXX
并有选择地回退到超类型(即 RecursiveASTVisitor
)实现:
class ASTVisitor : public RecursiveASTVisitor<ASTVisitor> {
public:
bool TraverseCXXRecordDecl(CXXRecordDecl *decl) {
// Don't traverse skip_me
if (auto name = decl->getName(); name.equals("skip_me")) {
std::cout << "Skipping " << name.str() << '\n';
// Return true to continue AST traversal,
// but don't visit the node
return true;
}
// Call RecursiveASTVisitor's implementation to visit this node
return RecursiveASTVisitor::TraverseCXXRecordDecl(decl);
}
bool VisitFieldDecl(FieldDecl *decl) {
std::cout << "Visited field " << decl->getName().str() << '\n';
return true;
}
};
在此翻译单元上测试此访问者:
struct skip_me {
int skipped;
};
struct dont_skip_me {
int not_skipped;
};
产生以下输出:
Skipping skip_me
Visited field not_skipped