如何让 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