使用 RecursiveASTVisitor 访问 Clang AST 时确定 Stmt 的父函数节点

Posted

技术标签:

【中文标题】使用 RecursiveASTVisitor 访问 Clang AST 时确定 Stmt 的父函数节点【英文标题】:Determine parent function node of a Stmt when visiting Clang AST using RecursiveASTVisitor 【发布时间】:2014-08-20 17:35:25 【问题描述】:

我正在学习如何使用 clanglibtooling 构建解析 C 的工具。

我正在使用RecursiveASTVisitor-inherited 类,因此它的所有遍历和访问方法都可用。 我想知道在覆盖方法VisitStmt(Stmt *s)时是否可以确定语句的父函数节点。例如这里,我可以从s 获得FunctionDecl* 吗?

谢谢。

【问题讨论】:

【参考方案1】:

我没有clang方面的专业知识,但你不能只存储你在上次VisitDecl调用中收到的值吗?

喜欢:

class FooVisitor : public RecursiveASTVisitor<FooVisitor> 
 public:
  explicit FooVisitor(ASTContext* context)
    : context_(context), current_func_(nullptr) 

  bool VisitDecl(Decl *decl) 
     if (decl->isFunctionOrFunctionTemplate())
        current_func_ = decl->getAsFunction();
     return true;
  

  bool VisitStmt(Stmt* stmt) 
     do_something(current_func_, stmt);
     return true;
  
 private:
  ASTContext* context_;
  FunctionDecl* current_func_;
;

我还没有编译它,所以可能需要一些修正,但它应该能说明这个概念。

【讨论】:

谢谢,这可能是个主意。我只想知道 Clang AST 是如何连接的。 @TrúcNguyễnLâm:“Clang AST 的连接程度”是什么意思?【参考方案2】:

由于你持有 ASTContext,我认为你可以通过 ASTContext::getParent() 访问 Node 的父母。

【讨论】:

【参考方案3】:

我认为这段代码是你想要的:

    const Stmt* ST = str;

    while (true) 
        //get parents
        const auto& parents = pContext->getParents(*ST);
        if ( parents.empty() ) 
            llvm::errs() << "Can not find parent\n";
            return false;
        
        llvm::errs() << "find parent size=" << parents.size() << "\n";
        ST = parents[0].get<Stmt>();
        if (!ST)
            return false;
        ST->dump();
        if (isa<CompoundStmt>(ST))
            break;
     

【讨论】:

【参考方案4】:

可能有点晚了。 如果您将 decls 和 Stmts 的解析添加到@xawi2000,那么我想您会到达顶部节点。 例如,你可能有

函数声明

compoundStmt

变量声明

Stmt

在这种情况下,您需要通过 stmt 进行解析,然后通过 decl 来获取 functionDecl。 只解析过stmts,可能不会给出这种情况

【讨论】:

以上是关于使用 RecursiveASTVisitor 访问 Clang AST 时确定 Stmt 的父函数节点的主要内容,如果未能解决你的问题,请参考以下文章

将 json 库添加到 clang libtooling 项目

禁用在 clang 前端查找预编译的头文件

使用可访问性标识符访问标签文本

Groovy集合声明与访问 ( 使用 [] 创建 ArrayList 和 LinkedList 集合 | 集合赋初值 | 使用下标访问集合 | 使用 IntRange 作为下标访问集合 )

GroovyGroovy 方法调用 ( 使用 对象名.成员名 访问 Groovy 类的成员 | 使用 对象名.‘成员名‘ 访问类的成员 | 使用 对象名[‘成员名‘] 访问类成员 )

我应该如何使用人工访问令牌来访问 npm repo