使用 clang-query

clang-query 是一个工具,允许您快速迭代和开发匹配器中最困难的部分。一旦匹配器的设计完成,它就可以转移到一个 C++ clang-tidy 插件中,类似于 mozilla-central 中的那些

clang-query 选项

设置遍历

遍历模式 指定了 AST 匹配器将如何遍历抽象语法树中的节点。有两个值

AsIs

此模式记录 AST 中的所有节点,即使它们在源代码中没有明确说明。这将包括您从未见过的并且可能不会立即理解的节点,例如 ExprWithCleanupsMaterializeTemporaryExpr。在此模式下,有必要编写明确匹配或以其他方式遍历这些潜在的意外节点的匹配器。

IgnoreUnlessSpelledInSource

此模式跳过由于隐式转换或其他通常是低级语言细节而创建的“隐式”节点。这通常更用户友好。**通常您会想要使用** set traversal IgnoreUnlessSpelledInSource

更多示例可在文档中找到,但这里有一个简单的示例

B func1() {
  return 42;
}

/*
  AST Dump in 'Asis' mode for C++17/C++20 dialect:

  FunctionDecl
  `-CompoundStmt
    `-ReturnStmt
      `-ImplicitCastExpr
        `-CXXConstructExpr
          `-IntegerLiteral 'int' 42

  AST Dump in 'IgnoreUnlessSpelledInSource' mode for all dialects:

  FunctionDecl
  `-CompoundStmt
    `-ReturnStmt
      `-IntegerLiteral 'int' 42
*/

设置绑定根

如果您正在匹配对象并为以后使用分配名称,则此选项可能相关。如果您正在调试单个匹配器并且没有使用任何 .bind(),则它无关紧要。

考虑 match functionDecl().bind("x") 的输出

clang-query> match functionDecl().bind("x")

Match #1:

testfile.cpp:1:1: note: "root" binds here
int addTwo(int num)
^~~~~~~~~~~~~~~~~~~
testfile.cpp:1:1: note: "x" binds here
int addTwo(int num)
^~~~~~~~~~~~~~~~~~~

Match #2:

testfile.cpp:6:1: note: "root" binds here
int main(int, char**)
^~~~~~~~~~~~~~~~~~~~~
testfile.cpp:6:1: note: "x" binds here
int main(int, char**)
^~~~~~~~~~~~~~~~~~~~~
2 matches.

clang-query 自动将 root 绑定到匹配项,但我们也已将名称 x 绑定到该匹配项。该 root 是冗余的。如果 set bind-root false 则输出噪音较小

clang-query> set bind-root false
clang-query> m functionDecl().bind("x")

Match #1:

testfile.cpp:1:1: note: "x" binds here
int addtwo(int num)
^~~~~~~~~~~~~~~~~~~

Match #2:

testfile.cpp:6:1: note: "x" binds here
int main(int, char**)
^~~~~~~~~~~~~~~~~~~~~
2 matches.

设置打印匹配器

set print-matcher true 将打印以下形式的标题行“Matcher: <foo>”,其中 foo 是您编写的匹配器。在同时调试多个匹配器时很有帮助,否则不会造成任何不便。

启用/禁用/设置输出 <foo>

这些命令将控制您从 clang-query 获取的输出类型。选项有

打印

向您显示正在匹配的节点的 C++ 形式。这通常没有用。

诊断

向您显示正在匹配的单个节点。

dump (别名:detailed-ast)

向您显示正在匹配的节点以及该节点的整个子树

默认情况下,您会获得 diag 输出。您可以通过选择 set output 来更改输出。您可以使用 enable output 添加输出。您可以使用 disable output 禁用输出,但这通常不需要。

因此,如果您想获得所有三种输出格式,您可以执行以下操作

# diag output happens automatically because you did not override with 'set'
enable output print
enable output dump

补丁

本节跟踪一些补丁;它们目前未使用,但我们将来可能需要它们。

  • 功能

  • 匹配器更改

  • 管道