快速构建静态分析工具的C语言编译前端——Psyche-C
Psyche-C 是一个独特的C语言编译器前端,特别为实现静态分析工具而设计。它的创新之处在于:
- 清晰地分隔了语法和语义编译阶段。
- 利用算法和启发式方法进行语法歧义消除。
- 缺失
struct
,union
,enum
,和typedef
类型推断,即使在#include
失败时也能“恢复”和宽容处理。 - API灵感来源于 Roslyn .NET compiler 。
- AST(抽象语法树)类似于 LLVM's Clang frontend 。
库与API
Psyche-C 实现为一个库,其原生API是C++(其他语言的API正在开发中,Issue #112)。以下是简单的API示例:
void analyse(const SourceText& srcText, const FileInfo& fi)
{
// 设置解析选项
ParseOptions parseOpts;
parseOpts.setTreatmentOfAmbiguities(ParseOptions::TreatmentOfAmbiguities::DisambiguateAlgorithmically);
// 解析源代码
auto tree = SyntaxTree::parseText(srcText,
TextPreprocessingState::Preprocessed,
TextCompleteness::Fragment,
parseOpts,
fi.fileName());
// 创建编译上下文
auto compilation = Compilation::create("code-analysis");
compilation->addSyntaxTree(tree.get());
// 运行分析
AnalysisVisitor analysis(tree.get(), compilation->semanticModel(tree.get()));
analysis.run(tree->translationUnitRoot());
}
你可以在函数定义等节点上编写自定义的访问器,以执行特定的分析任务。
SyntaxVisitor::Action AnalysisVisitor::visitFunctionDefinition(const FunctionDefinitionSyntax* node) override
{
const sym = semaModel->declaredSymbol(node);
if (sym->kind() == SymbolKind::Function) {
const FunctionSymbol* funSym = sym->asFunction();
// ...
}
return Action::Skip;
}
cnippet 驱动程序
Psyche-C 提供了一个名为cnippet的驱动程序,使其可以作为一个普通的C语言解析器使用。例如:
void f()
{
int ;
}
使用cnippet运行上述代码将得到与GCC或Clang类似的错误诊断。
~ cnip test.c
test.c:4:4 error: declaration does not declare anything
int ;
^
请注意,目前的语义分析功能还不完全。
类型推断
Psyche-C 能够对代码片段(不完整程序)中的缺失类型进行推断,这在很多场景下非常有用:
- 允许在不完整的源码上实现那些依赖完全类型信息的静态分析技术。
- 可以编译部分代码(如从bug跟踪器获取的代码片段),用于对象代码检查。
- 对于孤立的函数,生成测试输入数据,无需考虑其依赖关系。
- 在快速原型设计算法时,无须显式声明类型。
类型推断功能当前仅在原始分支中可用。
文档和资源
构建与测试
除类型推断部分使用Haskell外,Psyche-C 使用C++17编写,而cnippet使用Python 3编写。构建和测试过程如下:
cmake CMakeLists.txt && make -j 4
./test-suite
相关出版物
-
Type Inference for C: Applications to the Static Analysis of Incomplete Programs
ACM Transactions on Programming Languages and Systems — TOPLAS,Volume 42, Issue 3, Article No. 15,2020年12月。 -
Inference of static semantics for incomplete C programs
Proceedings of the ACM on Programming Languages,Volume 2, Issue POPL,2018年1月,Article No. 29。 -
AnghaBench: 一百万可编译C基准测试套件,用于代码大小优化
IEEE/ACM International Symposium on Code Generation and Optimization — CGO,2021。 -
内存不安全语言中数组的边界内输入生成
IEEE/ACM International Symposium on Code Generation and Optimization — CGO,2019年2月,p. 136-148。 -
结构化代码中的自动任务注解
国际并行架构与编译技术会议 — PACT,2018年11月,Article No. 31。