有没有一种优雅的方式来遍历 Clang AST 语句

Is there an elegant way to traverse Clang AST Statements?

本文关键字:方式 遍历 Clang 语句 AST 一种 有没有      更新时间:2023-10-16

我正在尝试遍历所有函数定义并从中提取信息。我必须遍历函数体中的所有语句,并根据类型执行特定函数。

目前我有一个丑陋的if-else块。有没有更优雅的方法可以做到这一点?

void FunctionMatcher::processStatement(const clang::Stmt *statement) {
    string type = statement->getStmtClassName();
    if (type == "ReturnStmt") {
        auto rs = dyn_cast<const ReturnStmt *>(statement);
        processReturnStmt(rs);
    } else if (type == "WhileStmt") {
        auto ws = dyn_cast<WhileStmt>(statement);
        processWhileStmt(ws);
    } else if (type == "ForStmt") {
        auto fs = dyn_cast<const ForStmt *>(statement);
        processForStmt(fs);
    } else if (type == "IfStmt") {
        auto is = dyn_cast<const IfStmt *>(statement);
        processIfStmt(is);
    } else if (type == "SwitchStmt") {
        auto ss = dyn_cast<const SwitchStmt *>(statement);
        processSwitchStmt(ss);
    } else if (type == "CompoundStmt") {
        auto cs = dyn_cast<const CompoundStmt *>(statement);
        for (auto child : cs->children())
            processStatement(child);
    } else {
      // ...
    }

通过浏览 clang::TextNodeDumper 的代码,我找到了一个解决方案。显然,Clang有自己的访客来发表声明,声明等...简单的例子:

class StatementVisitor : public ConstStmtVisitor<StatementVisitor> {
public:
    StatementVisitor();
    void Visit(const Stmt *Node) {
        ConstStmtVisitor<StatementVisitor>::Visit(Node);
    }
    void VisitIfStmt(const IfStmt *Node) {
        llvm::outs() << " An if statement yay!n";
    }
    void VisitWhileStmt(const WhileStmt *Node) {
        llvm::outs() << " A While statement yay!n";
    }
};

您可以使用RecursiveASTVisitor

它递归遍历给定代码中的所有语句

class MyASTVisitor : public RecursiveASTVisitor<MyASTVisitor>
{
    public:
    bool VisitFunctionDecl(FunctionDecl* f)
    {
        ...
    }
    bool VisitIfStmt(IfStmt* IF)
    {
        ...
    }
    bool VisitForStmt(ForStmt* FS)
    {
        ...
    }
    bool VisitWhileStmt(WhileStmt* WS)
    {
        ...
    }
}