使用Clang作为库 —— Matching the Clang AST


本文为译文,点击 此处查看原文。

本文档解释了如何使用 Clang 的LibASTMatchers来匹配AST的有趣节点,并执行使用匹配节点的代码。与 LibTooling 相结合,LibASTMatchers可以帮助编写代码到代码的转换工具或查询工具。
我们假设您已经了解了关于 Clang AST 的基本知识,如果您想了解更多关于 AST 结构的信息,请参阅 Clang AST的介绍

1. 介绍

LibASTMatchers提供了一个域特定语言(DSL,domain specific language)来创建 Clang AST 上的谓词(predicates)。这个 DSL 是用C++写的,可以从C++中使用,允许用户编写一个程序来匹配 AST 节点和访问这些节点的C++接口,这些接口提取属性(attributes)、源文件位置(source locations)、或在AST级别提供的其他任何信息。

AST matchers是 AST 中节点上的谓词。Matchers是通过调用creator函数创建的,此函数允许构建一个matchers树,其中使用inner matchers使匹配更加具体。

例如,要创建一个匹配翻译单元的 AST 中的所有 class 或 union 声明的matcher,您可以调用 recordDecl()。要缩小匹配范围,例如查找名称为“Foo”的所有 class 或 union 声明,请插入一个 hasName matcher:调用 recordDecl(hasName(“Foo”))返回一个matcher,它匹配任何 namespace 中名为“Foo”的 class 或 union 。默认情况下,接受多个 inner matchers 的 matchers 使用一个隐式的 allOf()。这允许进一步缩小匹配范围,例如匹配所有派生自“Bar”的类:recordDecl(hasName("Foo"), isDerivedFrom("Bar")

2. 如何创建匹配器

在 Clang AST 中有超过1000个类,当试图找出如何为特定模式创建一个 matcher 时,您可能会很快迷失方向。本节将教会您如何使用严格的分步模式来构建您感兴趣的 matcher。注意,AST 的某些部分总是缺少 matchers。请参阅本文档第4节编写自己的 AST matchers
使用 matchers 的先决条件是了解要匹配的对象的 AST 是什么样子的。Clang AST 的介绍向您介绍了如何将翻译单元的 AST 转储为人类可读的格式。

一般来说,创建正确 matchers 的策略是:

  1. 在您要匹配的 Clang AST 中找到的最外层 class。
  2. 查看 AST Matcher Reference 来查找 matchers,它们要么匹配您感兴趣的节点,要么缩小节点上的属性。
  3. 创建您的外部匹配表达式(outer match expression),验证它是否按预期工作。
  4. 检查 matchers,确定下一个要匹配的内部节点是什么。
  5. 重复这些操作,直到 matcher 完成。

3. 在匹配表达式中绑定节点

Matcher expressions允许您指定 AST 的哪些部分对某个任务感兴趣。然后,您通常希望对匹配的节点做一些事情,比如构建源代码转换
为此,匹配特定 AST 节点的 matchers (所以称为node matchers)是可绑定的;例如,recordDecl(hasName("MyClass")).bind("id")将匹配的recordDecl节点绑定到字符串"id",稍后在匹配回调函数中检索。

4. 编写自己的matchers

根据 matcher 的类型和灵活性,定义一个 matcher 有多种不同的方法。

4.1 VariadicDynCastAllOfMatcher
VariadicDynCastAllOfMatcher<Base, Derived>

如果Base类型的节点可以被动态地转换为Derived,则所有这些节点满足匹配。这些 matchers 的名称都是名词,它们的Derived非常相似。VariadicDynCastAllOfMatchers是 matcher 层次结构的主干。大多数情况下,您的匹配表达式将从其中一个开始,您可以将它们表示的节点绑定ids,以便稍后处理。
VariadicDynCastAllOfMatchers是在 C++03 中建模可变参数模板函数的可调用类。它们取任意数量的Matcher<Derived>,并返回一个Matcher<Base>

4.2 AST_MATCHER_P(Type, Name, ParamType, Param)

大多数 matcher 定义使用matcher creation macros。它们定义了类型Matcher<Type>本身的匹配器,以及一个名为Namematcher-creation函数,该函数接受一个ParamType类型的参数并返回相应的matcher
有多个matcher definition macros处理多态返回值和不同的参数计数。详情参考 ASTMatchersMacros.h

5. Matcher creation函数

Matchers是通过对matcher creation函数的嵌套调用生成的。大多数时候,这些函数要么是使用VariadicDynCastAllOfMatcher创建的,要么是使用matcher creation macros创建的(参见下面)。独立(free-standing)函数表示此 matcher 只是其他 matchers 的组合,例如 callee

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值