0

我想知道是否可以使用 GCC 强制执行直接 #include 要求。假设我有这些文件:

abc.h:

typedef struct {
   int useful;
} str;

文件1.h:

#include <abc.h>
#ifndef GUARD
#define GUARD

#include <deh.h>

typedef struct {
   int useful;
} str2;

#endif

文件2.h:

#ifndef GUARD2
#define GUARD2
#include <file1.h>

void a_function (str*  my_str);
void a_function2(str2* my_str);

#endif

问题是“file2.h”正在使用“abc.h”中定义的“str”。假设“file1.h”是由某些 Linux 系统上的系统提供的。我无法控制“file1.h”的内容。如果可能包括也可能不包括,它可能会或可能不会在内部包括警卫,它可能会或可能不会随着时间而改变。

问题在于支持多个发行版和系统。如果 file2.h 不小心使用了 "str" 而没有 include ,它可能会在大多数系统上编译,但在其他系统上可能会失败,或者将来当 "file1.h" 更改时。

有没有办法强制 GCC(或 LLVM)只使用 file2.h 中直接定义的类型?我知道“#include”只是包含,所以编译器内部可能不会在预处理器阶段之后意识到这些问题,但是,我想知道这目前是否可行,如果可以,如何?

我在使用“普通”Linux 发行版时遇到过几次这个问题,但在早期的 Android NDK 版本中情况更糟。

4

2 回答 2

2

不,#include指示编译器将其他文件的内容视为放置在#include指令中 - 您要求以某种方式对其他文件的内容进行不同的处理。

在这种情况下,您最好的希望是使用执行依赖关系分析的静态分析工具,并检查通过间接(嵌套)包含获得的类型(或函数或对象)是否没有直接依赖关系。

免费的doxygen文档工具提取有关包含和依赖关系的信息,并以 XML 格式提供。当然,就重载解析和模板处理而言,它不如真正的编译器准确。我确信有付费工具会更准确(用户 Ira Baxter 不时弹出提及他的公司销售的商业产品、DMS Toolkit 或类似的东西,听起来它会得到这些信息)。但我猜 doxygen 将为您提供大多数“正常”代码的正确结果。

于 2013-09-30T18:57:26.997 回答
1

C++ 语言中没有任何东西可以验证是否正确包含所有标头。但是,有基于clang的 include-what-you-use。我还没有尝试过使用它,但它似乎是你正在寻找的方向。对于 C,实现一个分析器检测依赖关系并报告缺少的直接包含似乎是相当简单的。由于需要检测模板实例化的依赖关系,在 C++ 中尝试相同的事情会变得有些困难。

根据上周 C++ 委员会会议上的讨论,重构源代码和标头以正确包含实际使用的内容可能有助于 C++ 中未来的模块支持

于 2013-09-30T18:58:36.140 回答