c++ 是否可以使用RecursiveASTVisitor只遍历AST的子树

wecizke3  于 11个月前  发布在  其他
关注(0)|答案(1)|浏览(152)

我想用clang的RecursiveASTVisitor遍历一个拥有巨大AST的项目。当我指定遍历整个AST时(如下所示),这需要花费大量时间:

void MyVisitor::HandleTranslationUnit(clang::ASTContext& context)
{
  TraverseDecl(context.getTranslationUnitDecl());
}

字符串
出于这个原因,我想使用AST匹配器将AST缩小到我想要遍历的代码的相关部分。假设我只想遍历某些函数声明,那么我有沿着行的东西:

void MyVisitor::HandleTranslationUnit(clang::ASTContext& context)
{
    auto decl = context.getTranslationUnitDecl();
    auto relevantNodes = match(findAll(functionDecl(/* any matcher */).bind("function")), *decl, context);
    for(auto &relevantNode : relevantNodes)
    {
      const clang::FunctionDecl *relevantFunctionDecl = relevantNode.getNodeAs<clang::FunctionDecl>("function");
      if(relevantFunctionDecl)
      {
        TraverseDecl(relevantFunctionDecl);
        //----------^ cannot pass const clang::FunctionDecl* to function accepting clang::Decl*
      }
    }
}


在我的代码中,getNodeAs<>方法返回一个常量指针,但是TraverseDecl接受非常量指针,即编译失败。
有没有办法只穿越AST的某些部分?
提前感谢!

sulc1iza

sulc1iza1#

是的,可以访问子树。只需按照代码片段中所示的操作,除了添加const_cast以允许从匹配器获得的指针传递给RecursiveASTVisitor。C未定义行为没有问题,因为所有AST对象最初都是在没有const限定符的情况下创建的。
一般来说,Clang API在常量方面有点不一致。许多API,比如matchers,处理const指针,因为它们本身不修改AST。但是,虽然RecursiveASTVisitor也是如此,但使用修改AST的指针编写transformer是很常见的,所以它的API不使用const
参见Clang Discourse讨论Is it safe to cast-away constness to use Clang static analysis?,了解Clang开发人员的类似问题和评论。
(As另外,我认为这部分源于C
没有“const polymorphism”的概念,如果它存在的话,可能会允许API在客户端的请求下选择性地统一处理const或非const指针。由于语言强制做出选择,API设计者必须选择更适合通用用法的指针,因此客户端必须在某些边界处插入const_cast)。

相关问题