Clang 的应用
通过 Clang 提供的丰富接口功能可以开发出静态分析工具,进而管控代码质量。还可以开发出用于代码增量分析、代码可视化、代码质量报告来保障App质量的系统平台。CodeChecker
什么是 Clang
Clang 是 C、C++、Objective-C 的编译前端,而 Swift 有自己的编译前端。
优势:
- 编译的速度非常快,对内存的使用率非常低,并且兼容 GCC
- 代码诊断,精确的显示出问题所在的行和具体位置,可以确切的说明这个问题的原因,并指出错误类型。
- 对 typedef 的保留和展开也处理的很好
- Fix-it 提示,宏的处理
- 架构是模块化的。其输出的接口可以代码静态分析,开发代码转义、代码生成、代码重构的工具
Clang 是基于 C++ 开发的,源码质量很高。目录清晰、功能解耦做的很好、分类清晰方便组合和复用、代码风格统一而且规范、注释量大便于阅读等。Clang 源码
Clang 做的事
首先,Clang 会对代码进行语法分析,将代码切分成 Token 。
//输入一个命令可以查看代码所有的token
clang -fmodules -E -Xclang -dump-tokens main.m
这个命令的作用是,显示每个 Token 的类型、值以及位置。Token 类型 分为四类:
- 关键字:语法中的关键字
- 标识符:变量名
- 字面量:值、数字、字符串
- 特殊符号:加减乘除等符号
接下来,进行语法分析
将输出的 Token 先按照语法组成语义,生成节点,然后将这些节点按照层级关系构成抽象语法树 (AST)。
//查看语法树
clang -fmodules -fsyntax-only -Xclang -ast-dump main.m
TranslationUnitDecl 0xc75b450 <<invalid sloc>> <invalid sloc>
|-TypedefDecl 0xc75b740 <<invalid sloc>> <invalid sloc> implicit __builtin_va_list ‘char *’
`-FunctionDecl 0xc75b7b0 <test.cpp:1:1, line:7:1> line:1:5 main ‘int (void)’
`-CompoundStmt 0xc75b978 <line:2:1, line:7:1>
|-DeclStmt 0xc75b870 <line:3:2, col:7>
| `-VarDecl 0xc75b840 <col:2, col:6> col:6 used a ‘int’
|-DeclStmt 0xc75b8d8 <line:4:2, col:12>
| `-VarDecl 0xc75b890 <col:2, col:10> col:6 used b ‘int’ cinit
| `-IntegerLiteral 0xc75b8c0 <col:10> ‘int’ 10
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< a = b <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|-BinaryOperator 0xc75b928 <line:5:2, col:6> ‘int’ lvalue ‘=‘
| |-DeclRefExpr 0xc75b8e8 <col:2> ‘int’ lvalue Var 0xc75b840 ‘a’ ‘int’
| `-ImplicitCastExpr 0xc75b918 <col:6> ‘int’ <LValueToRValue>
| `-DeclRefExpr 0xc75b900 <col:6> ‘int’ lvalue Var 0xc75b890 ‘b’ ‘int’
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
`-ReturnStmt 0xc75b968 <line:6:2, col:9>
`-ImplicitCastExpr 0xc75b958 <col:9> ‘int’ <LValueToRValue>
`-DeclRefExpr 0xc75b940 <col:9> ‘int’ lvalue Var 0xc75b840 ‘a’ ‘int
其中 TranslationUnitDecl 是根节点,表示一个编译单元;Decl 表示一个声明;Expr 表示的是表达式;Literal 表示字面量,是一个特殊的 Exper;Stmt 表示陈述。
Clang 还有众多种类的节点类型。节点主要分为 Type 类型、Decl 声明、Stmt 陈述这三种,其他的都是这三种的派生。通过扩展这三类节点,就能够将无限的代码形态用有限的形式表现出来了。
Clang 提供的能力
LibClang
LibClang 提供了一个稳定的高级的C接口,LibClang 可以访问 Clang 的上层高级抽象的能力,比如获取所有 Token、遍历语法树、代码补全等。由于 API 很稳定,Clang 版本更新对其影响不大。但是,LibClang 并不能完全访问到 Clang AST 信息。
使用 LibClang 可以直接使用它的 C API。官方也提供了 Python binding 脚本供你调用。还有开源的 node-js/ruby binding。你要是不熟悉其他语言,还有个第三方开源的 Objective-C 写的 ClangKit 库可供使用。
Clang Plugins
Clang Plugins 可以让你在 AST 上做些操作,这些操作能够集成到编译中,成为编译的一部分。插件是在运行时由编译器加载的动态库,方便集成到构建系统中。
使用 Clang Plugins 一般都是希望能够完全控制 Clang AST,同时能够集成在编译流程中,可以影响编译的过程,进行中断或者提示。
LibTooling
通过LibTooling 能够编写独立运行的语法检查和代码重构工具。与 Clang Plugins 相比,无法影响编译过程,与 LibClang 相比,接口没那么稳定,也无法开箱即用。能够完全控制 Clang AST 和可独立运行。可以做:
- 改变代码:可以改变Clang 生成代码的方式。基于现有代码可以做出大量的修改。还可以进行语言的转换,比如把 OC 语言转成 JavaScript 或者 Swif...
- 做检查:检查命名规范,增加更强的类型检查,还可以按照自己的定义进行代码的检查分析
- 做分析:对源码做任意类型分析,甚至重写程序。
在 LibTooling 的基础之上有个开发人员工具合集Clang tools,Clang tools 作为Clang 项目的一部分,已经提供了一些工具,主要包括:
- 语法检查工具 clang-check;
- 自动修复编译错误工具 clang-fixit;
- 自动代码格式工具 clang-format;
- 新语言和新功能的迁移工具;
- 重构工具。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论