背景
Clang Static Analyzer是开源编译器前端clang中内置的针对C,C++和Objective-C源代码的静态分析工具,能提供普通warning之外的检查,涵盖内存操作,安全等方面。这部分功能可通过clang --analyze命令或者库文件等方式调用。
结构和使用
整体来看clang static analyzer分为两部分,分析引擎(analyzer core)和checkers,所有checker的运行都建立在底层分析引擎的基础之上。增加新的检查,大多是使用分析引擎提供的功能编写新的checker。
大部分checker的运行都建立在分析引擎基于源代码的符号模拟执行结果上,分析引擎会遍历代码并通过ExplodedGraph对象来表现模拟执行后的每一个片段。每个ExplodedGraph对象由ProgramPoint和ProgramState组成。ProgramPoint用来表现CFG上的节点位置,同时也包含一些该节点创建相关的其他信息。而ProgramState用来表现这段代码相关联的虚拟状态,例如Environment是源码中表达式到符号变量的映射关系,而Store是内存地址到符号变量的映射关系等。
用户可以通过clang --analyze -Xclang -analyzer-checker-help来列举当前clang版本下所有包含的checker列表,这些checker按类型被分组。默认情况下alpha分组的不会被执行,要明确包含某个分组可通过-analyzer-checker参数指定,例如调用alpha分组checker,需要执行:
clang --analyze -Xclang -analyzer-checker=alpha <file>
详细的checker列表和简要的说明可以在http://clang-analyzer.llvm.org/available_checks.html中找到。
除了正常功能的checker,debug分组的checker可以帮助开发者了解分析引擎在处理源代码过程中的逻辑,例如以下一些checker:

Checker代码实例
Clang/llvm项目编译方面的步骤可参看官方文档。关于checker的编写,clang项目下StaticAnalyzer/Checkers目录中有不少实例可以参考。这里用一个最简单的例子来熟悉checker的创建:FixedAddressChecker,这个checker将检查出所有直接向指针赋值常量的操作并报警,该checker甚至没有涉及使用模拟执行的部分。
准备工作:

所有自定义的checker类都需要继承Checker模板类,并通过实现不同的事件注册函数来挂钩analyzer core分析过程,所有支持的事件类型可以在CheckerDocumentation.cpp中查阅。FixedAddressCheck类通过实现checkPreStmt函数捕捉代码中的赋值操作,下面是加上注释的代码:

这就完成了一个简单checker的实现,通过测试用例test.c,运行该checker可以看到相应的输出结果:

看了FixedAddressChecker例子之后,可继续查看其他的一些实例,参考文档[3]以官方StreamChecker为例,给出了针对文件流操作checker的整个设计和编写过程,当然目前StreamChecker和2012年PPT中所描述的相比有所变化,但大体思路没有变。
后话
clang static analyzer通过建立分析引擎和checkers所组成的这种架构,将编写自定义checker的难度有所简化,方便二次开发。当然要编写出低误报,低漏报的checker还需更深入的了解分析引擎本身和熟悉其提供的各类接口。
Reference
[2] clang-analyzer.llvm.org/checker_dev…
[4] blog.trailofbits.com/2014/04/27/…