2

在使用 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。

4

1 回答 1

3

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

要跳过 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
于 2020-01-25T08:41:24.483 回答