我需要一个工具来自动标记未使用的结构成员在 C 代码库中。我对“未使用”的定义很简单 - 如果从代码中删除结构成员定义,并且代码编译成功,则该结构成员被声明为未使用。问题是 - 如何以自动化方式完成此操作? (由于代码库很小,速度并不是太重要)。
关于该主题的现有堆栈溢出文章似乎暗示目前还没有现有的静态分析工具可以做到这一点。另一方面,考虑到 Clang 的模块化,我认为这应该可以通过 AST 操作来实现。我们以单个文件为例。我想做的是以下(这可以稍后推广到代码库中的一组源文件):
- 从 C 代码生成 AST。
- Recursively visit all structure field defintions and remove them one-by-one. We can keep a "seen" dictionary to ensure we don't remove already seen field definition nodes.
- 过滤出字段定义,仅保留要分析的代码库中存在的字段定义(例如,避免标准库中的定义)。
- 编译代码。
- 如果代码编译成功,则相应的字段声明未使用并被标记。
- 继续#1。
上面的关键字是remove。我怎么能够remove字段定义?使用 Clang 似乎有两种方法。
- 在源代码级别,我们可以使用 Clang Rewriter 删除字段声明(有一个“RemoveText(SourceRange)”选项)。但是,我不知道这是否会一直有效(例如:结构是使用宏扩展自动生成的)。
- 从 AST 中删除字段声明节点,然后“重新编译”AST(无论这意味着什么)。
在上述两个选项中,#1 似乎很 hacky - 您需要创建源文件的副本,在删除字段定义后重新编写它,然后重新编译修改后的源文件。而且,我不确定当涉及生成结构字段定义的复杂宏时它的工作效果如何。
#2 看起来很干净,但从谷歌搜索来看,似乎没有“删除 AST 节点”这样的东西(它是不可变的)。如果我错了,请纠正我。即使我成功了,我如何从现在开始重新评估 AST 是否缺少对结构字段的引用? (“编译”步骤)。
任何建议表示赞赏(提前致谢!)。我已经通过上面的#1 方法取得了一些初步的成功,但我觉得这不是正确的方向。
cppcheck可以做到这一点。例如:
// test.cpp
struct Struct
{
int used;
int unused;
};
int main()
{
Struct s;
s.used = 0;
return s.used;
}
$ cppcheck test.cpp --enable=all
Checking test.cpp ...
test.cpp:5:9: style: struct member 'Struct::unused' is never used. [unusedStructMember]
int unused;
^
虽然我在示例中使用了 C++ 代码,但它的行为与 C 相同。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)