提问人:Mike van Dyke 提问时间:11/13/2023 更新时间:11/14/2023 访问量:44
是否可以使用 RecursiveASTVisitor 仅遍历 AST 的子树
Is it possible to traverse only a subtree of the AST with RecursiveASTVisitor
问:
我想用 clang 的 .当我指定应该遍历整个 AST 时(如下所示),这需要花费大量时间:RecursiveASTVisitor
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*
}
}
}
在我的代码中,该方法返回一个 const 指针,但接受非常量指针,即编译失败。getNodeAs<>
TraverseDecl
有没有办法只遍历 AST 的某些部分?
提前致谢!
答:
1赞
Scott McPeak
11/14/2023
#1
是的,可以访问子树。只需按照代码片段中所示的操作即可,但添加以允许将从匹配器获取的指针传递给 。C++ 未定义行为没有问题,因为所有 AST 对象最初都是在没有限定符的情况下创建的。const_cast
RecursiveASTVisitor
const
一般来说,Clang API 在恒定性方面有点不一致。许多 API(如匹配器)处理指针,因为它们本身不会修改 AST。但是,虽然 也是如此,但使用修改 AST 的转换器编写转换器有些常见,因此其 API 不使用 .const
RecursiveASTVisitor
const
请参阅 Clang Discourse 讨论 使用 Clang 静态分析是否安全? 对于类似的问题和 Clang 开发人员的评论。
(顺便说一句,我认为这部分源于这样一个事实,即 C++ 没有“常量多态性”的概念,如果它存在,它可能允许 API 选择性地统一处理或非指针。由于语言强制做出选择,因此 API 设计人员必须选择更适合常见用法的,因此客户端必须在某些边界处插入。const
const
const_cast
评论