Wrappres' Studio.

静态分析

字数统计: 1k阅读时长: 4 min
2019/10/26 Share

静态分析工具

SwiftLint,OCLint, Clang, Infer

Clang

Clang 是 C,C++,Objective-C 的编译前端。Swift 有自己的编译前端: SL optimizer。

Clang 会对代码进行词法分析,将代码切分成 Token

用以下命令可以查看:clang -fmodules -E -Xclang -dump-tokens main.m
可以把 Token 分为四类:

  • 关键字:语法中的关键字,比如 if,else,while 等
  • 标识符:变量名
  • 字面值:值,数字,字符串
  • 特殊符号:加减乘除等符号

语法分析

将输出的 Token 按照语法组合语义,生成类似 VarDecl 这样的节点。这些节点按照层次关系生成抽象语法树(AST)。
用以下命令查看:clang -fmodules -fsyntax-only -Xclang -ast-dump main.m
类似的输出有:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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表示字面量,是一个特殊的 Expr。Stmt表示陈述。
节点主要分为三种:Type类型,Decl声明,Stmt陈述,其他都是有这三种派生的。通过扩展三类节点,能够将无限的代码形态用有限的形式表达出来。

提供的能力

Clang 为一些需要分析代码语法,语义信息的工具提供了基础设施。有:LibClang,ClangPlugin 和 LibTooling。

LibClang

LibClang 可以访问 Clang 的上层高级抽象能力,例如:获取所有 Token,遍历语法树,代码补全等。但并不能访问到 Clang AST 信息。

ClangPlugin

ClangPlugin 可以在 AST 上做些操作,这些操作能够集成到编译中,成为编译的一部分。插件是在运行时由编译器加载的动态库,方便集成构建系统中。

LibTooling

LibTooling 是一个 C++ 接口,通过 LibTooling 能够编写独立运行的语法检查和代码重构工具。
LibTooling 有以下优势:

  • 所写工具不依赖构建系统,可以作为一个命令单独使用,比如:clang-check(语法检查工具),clang-fixit(自动修复编译错误工具),clang-format(自动代码格式工具)。
  • 可以完全控制 Clang AST。
  • 能够和 ClangPlugin 共用一份代码。

由于 LibTooling 可以完全控制 AST,所以可以做到很多事:

  • 改变代码:可以改变 Clang 生成代码的方式。基于现有代码可以做大量的修改。还可以进行语言的转换。
  • 做检查:检查命名规范,增加更强的类型检查,还可以按照自己的定义进行代码的检查分析。
  • 做分析:对源码做任意类型分析,甚至重写程序。给 Clang 添加以一些自定义分析,创建自己的重构器,还可以基于工程生成相关的图形或文档进行分析。
CATALOG
  1. 1. 静态分析工具
  2. 2. Clang
    1. 2.1. Clang 会对代码进行词法分析,将代码切分成 Token
    2. 2.2. 语法分析
    3. 2.3. 提供的能力
    4. 2.4. LibClang
    5. 2.5. ClangPlugin
    6. 2.6. LibTooling