在使用Clang LibTooling的RecursiveASTVisitor时,如何告诉库中止当前访问的AST节点下的子树扫描?

RecursiveASTVisitor在AST上使用深度优先遍历,可以很容易地中止某些子树并继续遍历。

例如(请阅读代码中的注释):

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 ***方法返回false会达到这个目标,但是它确实告诉lib一起结束遍历,而不是跳过子树。

由于目标只是标题中所述的目标,因此不考虑使用ASTMatchers。

最佳答案

实际上,从false函数之一返回VisitXXX将终止整个遍历。

要跳过AST节点,您可以覆盖TraverseXXX并有选择地回退到父类(super class)型(即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

09-11 04:55