【问题标题】:Add #include's to the headers of a program using llvm clang使用 llvm clang 将#include 添加到程序的标题中
【发布时间】:2017-12-09 22:48:34
【问题描述】:

我需要通过使用 LLVM 和 Clang 对其进行转换,将标头添加到已经存在的程序中。

我已经使用clang的重写器在更改函数名称和参数等方面完成了类似的事情。

但是头文件不存在于 clang 的 AST 中。我已经知道我们需要使用 PPCallbacks (https://clang.llvm.org/doxygen/classclang_1_1PPCallbacks.html),但如果可能的话,我急需一些关于如何使其与重写器一起工作的示例。

或者,在第一个之前添加#include 语句

using namespace <namespace>; 

也有效。我也想知道一个例子。

任何帮助将不胜感激。

【问题讨论】:

  • 为什么不能在正版源文件(原*.cc*.cpp文件)中添加#include指令?您不需要 Clang (即使您当然可以使用复杂的静态分析技术,使用 Clang 和/或 LLVM 来确定要包含的 哪些 头文件)。我的意思是,在一些源代码的开头添加一些预处理器指令非常简单(可以使用sed 完成),问题是要知道要包含的哪个头文件!
  • 这是我项目的一部分。我不允许手动更改文件。而且我确切地知道要包含哪个头文件!
  • 但您可以自动更改文件。如果不允许更改它们,则不是添加头文件的问题,而是在翻译单元中添加声明和定义。添加的东西甚至可能不存在于任何头文件中。然后,您应该在预处理器阶段之外工作(因此头文件不再重要)
  • 只是头文件的顺序很重要。所以我想在其余的头文件已经到位之后放置新的头文件。我想办法把它放在开头。
  • 不,您需要并希望使用 preprocessed 形式的代码,此时头文件不再存在。或者您需要更改物理源文件,然后添加一些 #include 行非常简单(并且可以自动完成,一旦您知道应该添加哪些预处理器指令以及在什么位置添加)。

标签: clang llvm header-files


【解决方案1】:

你的问题有点混乱。您需要详细了解preprocessor 的工作原理。请注意,大多数 C++ 编译发生在预处理阶段之后(因此大多数 C++ 静态分析器在该阶段之后工作)。

换句话说,C++ 规范(以及 C 规范)首先定义什么是预处理,然后定义预处理形式的语法和语义。

换句话说,在编译 foo.cc 时,您的编译器会看到您可以使用 clang++ -C -E foo.cc &gt; foo.ii 获得的预处理形式 foo.ii

在 1980 年代,预处理器 /lib/cpp 是一个由编译器分叉的独立程序(一些临时的 foo.ii 位于磁盘上并在编译结束时被删除)。今天,出于性能原因,它是在编译器内部完成的一些初始处理。但你可以推理为它仍然是分开的。

您想要更改 Clang 编译器,它(与所有其他 C++ 编译器或 C++ 静态分析器一样)主要处理 预处理 形式。然后你不想添加新的#include-s,但是你想改变给编译器的AST的流(在预处理之后),这是一个不同的问题:然后你想在它们之间添加一些AST现有的 AST 元素(独立于任何预处理器指令)。

或者您想自动更改 C++ 源代码。困难的部分是确定你想要改变什么以及在什么地方。我想您已经使用复杂的东西来确定必须在文件foo.cc 的第 34 行之后插入#include &lt;vector&gt;。一旦你获得了这些信息(并且获得它是一件困难的事情),进行插入就非常简单了。例如,您可以阅读每个 C++ 源代码行,并在您阅读足够多的行时插入您的行。

【讨论】:

  • 我有许多彼此不同的源文件。我不会编译任何东西(即没有“clang++”命令)。我正在运行 ninja 命令在 bin/ 中创建可执行文件。我将我的文件提供给它,我可以看到我重写的代码作为输出(如果我愿意,还可以看到 AST 转储)。知道这一切都是在 llvm 构建工具的帮助下完成的,这可能会有所帮助。
  • 您需要进行预处理,即使您只是分析(而不是编译)C++ 代码。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-03-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多