【问题标题】:Is there an elegant way to traverse Clang AST Statements?有没有一种优雅的方式来遍历 Clang AST 语句?
【发布时间】:2019-07-24 10:07:02
【问题描述】:

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

目前我有一个丑陋的 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 {
      // ...
    }

【问题讨论】:

  • @KostasRim 这就是我用来提取函数的东西。现在我想遍历正文中的语句并处理它们。
  • 看起来像 visitor pattern 的经典用例,不是吗?
  • @G.M.我需要用 accept 方法扩展 Stmt 类,不是吗?这些是库类。

标签: c++ clang abstract-syntax-tree clang++


【解决方案1】:

通过浏览 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";
    }
};

【讨论】:

    【解决方案2】:

    你可以使用RecursiveASTVisitor

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

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

    【讨论】:

      猜你喜欢
      • 2020-01-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-09-18
      • 2019-11-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多