如何使用 clang 从源文件中提取标头?

How to extract headers from source file using clang?

本文关键字:提取 源文件 何使用 clang      更新时间:2023-10-16

我正在使用clang ast匹配器从源文件中提取一些信息。现在,我还想知道源文件正在使用的标头和依赖项标头的列表。例如,源文件 abc.c 具有以下标头:

#include <def.h>
//#include <def_private.h>

在 clang 匹配器期间,我需要确保 clang 知道 def.h,它位于同一目录中。def.h 包括以下标头:

#include <iostream.h>
#include <string.h>
#include <float.h>
#include <math.h>
/*#include <boost>
* #inclde <fstream>*/

我做 ast 匹配器从 abc.c 中提取或识别信息。现在,我想提取所有标题或包含。这应该包括所有这些:

#include <def.h>
#include <iostream.h>
#include <string.h>
#include <float.h>
#include <math.h>

我做了一些在线研究来做到这一点,不幸的是,所有这些都涉及正则表达式(从c文件中提取头名的正则表达式(或如何在Visual Studio中执行(在Visual Studio中显示C++文件的 #include 层次结构(。

我想知道是否可以使用叮当声。另外,请让我知道是否有任何其他方法可以以编程方式提取标头,而不仅仅是使用正则表达式。

OP 说任何其他以编程方式提取标头的方法,而不仅仅是使用正则表达式。没有叮当是可以的。

我们都同意正则表达式根本无法做到这一点。 您需要将源文本解析为树,并在树中显式显示 #include 指令。

我不是叮当专家。 我怀疑它的内部树反映了预处理的源代码,因此 #include 结构已经消失。 那么问题就在于坚持对源文本进行预处理以解析它。

我们的 DMS 软件再造工具包及其支持 C++17 的解析器可以在不扩展指令的情况下处理此类解析。 它可以通过两种方式做到这一点:a(预处理器指令相对于源代码"结构良好",可以将C++前端配置为捕获解析树,并将指令解析为树在适当的位置;这在实践中非常有效,但代价是有时必须手动修补一个特别丑陋的条件或宏调用以使其"结构良好,或 b( 解析捕获以(几乎(任意方式放置的预处理器指令;这有时以自动复制小段代码为代价捕获指令,本质上导致案例 A 喜欢的良好重组(。

无论哪种情况,#include 指令现在都显式出现在 AST 中,包含的文件几乎构建为表示包含文件的辅助树。 这样的树节点很容易通过树行走来寻找这样的显式包含节点。 DMS的ASTInterface提供了ScanTree来遍历节点,并在某些提供的谓词对节点成立时采取行动;检查 #include 节点很容易。 值得注意的是,条件指令也被保留,通过从 #include onr 向上走,可以构造实际包含该包含文件的条件。

当然,头文件本身也会被解析,从而生成一棵树。 它的任何包含都出现在其树体中。 必须在这些树中的每一个上运行ScanTree才能收集所有包含的内容。

OP没有说他想用 #includes 做什么。 DMS 提供了许多解析之外的功能来帮助 OP 实现她的目的,包括符号表构造、控制和数据流分析、树模式匹配、以源语言 (C++( 语法表示的树到树转换,最后从修改后的语法树生成源代码(重新(。