Clang 的应用 - 文章教程

Clang 的应用

发布于 2021-03-22 字数 5466 浏览 1068 评论 0

通过 Clang 提供的丰富接口功能可以开发出静态分析工具,进而管控代码质量。还可以开发出用于代码增量分析、代码可视化、代码质量报告来保障App质量的系统平台。CodeChecker

什么是 Clang

Clang 是 C、C++、Objective-C 的编译前端,而 Swift 有自己的编译前端。

优势:

  1. 编译的速度非常快,对内存的使用率非常低,并且兼容 GCC
  2. 代码诊断,精确的显示出问题所在的行和具体位置,可以确切的说明这个问题的原因,并指出错误类型。
  3. 对 typedef 的保留和展开也处理的很好
  4. Fix-it 提示,宏的处理
  5. 架构是模块化的。其输出的接口可以代码静态分析,开发代码转义、代码生成、代码重构的工具

Clang 是基于 C++ 开发的,源码质量很高。目录清晰、功能解耦做的很好、分类清晰方便组合和复用、代码风格统一而且规范、注释量大便于阅读等。Clang 源码

Clang 做的事

首先,Clang 会对代码进行语法分析,将代码切分成 Token 。

//输入一个命令可以查看代码所有的token
clang -fmodules -E -Xclang -dump-tokens main.m

这个命令的作用是,显示每个 Token 的类型、值以及位置。Token 类型 分为四类:

  1. 关键字:语法中的关键字
  2. 标识符:变量名
  3. 字面量:值、数字、字符串
  4. 特殊符号:加减乘除等符号

接下来,进行语法分析

将输出的 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 和可独立运行。可以做:

  1. 改变代码:可以改变Clang 生成代码的方式。基于现有代码可以做出大量的修改。还可以进行语言的转换,比如把 OC 语言转成 JavaScript 或者 Swif…
  2. 做检查:检查命名规范,增加更强的类型检查,还可以按照自己的定义进行代码的检查分析
  3. 做分析:对源码做任意类型分析,甚至重写程序。

在 LibTooling 的基础之上有个开发人员工具合集Clang tools,Clang tools 作为Clang 项目的一部分,已经提供了一些工具,主要包括:

  • 语法检查工具 clang-check;
  • 自动修复编译错误工具 clang-fixit;
  • 自动代码格式工具 clang-format;
  • 新语言和新功能的迁移工具;
  • 重构工具。

如果你对这篇文章有疑问,欢迎到本站 社区 发帖提问或使用手Q扫描下方二维码加群参与讨论,获取更多帮助。

扫码加入群聊

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

目前还没有任何评论,快来抢沙发吧!

关于作者

JSmiles

生命进入颠沛而奔忙的本质状态,并将以不断告别和相遇的陈旧方式继续下去。

2583 文章
29 评论
84935 人气
更多

推荐作者

Jay

文章 0 评论 0

guowei007

文章 0 评论 0

2668157715

文章 0 评论 0

HY阳

文章 0 评论 0

想挽留

文章 30 评论 3