为什么gcc和clang默默地允许标准包含文件重新定义宏?

时间:2017-08-09 22:37:49

标签: gcc clang c-preprocessor

示例代码:

#define PROT_NONE 99
#include <sys/mman.h>

gcc和clang都允许编译上面的代码片段;从sys / mman.h中重新定义PROT_NONE宏,没有任何警告。查看实际的头文件,没有允许重新定义的#undef。

这似乎是一个问题 - 虽然这个案例显然是为了表明问题,但我的代码和系统头文件之间的标识符冲突似乎可以被忽略。 PROT_NONE的系统头定义覆盖了我的定义,甚至没有警告我存在潜在的问题。这似乎是以某种方式特定于系统头文件;如果我自己尝试重新定义,我会得到正确的错误。

我的问题基本上是双重的:

  • 有人知道允许这种行为背后的动机吗?
  • 是否有任何命令行开关会导致在编译阶段失败?

2 个答案:

答案 0 :(得分:3)

发生了什么/动机

在gnu和clang中,警告在系统标题中被抑制。

clang user manual只是声明了这一点:

警告在系统标题中出现时被禁止。

...但gnu c preprocessor manual给出了以下理由:

声明操作系统和运行时库接口的头文件通常不能严格符合C语言。因此,GCC会在系统头文件中给出代码特殊处理。

命令行上的缓解

是否有任何命令行开关会导致它在编译阶段失败?

是。使您的系统标头成为非系统标头。

在clang中,您只能使用 .w3-animate-opacity { animation: opac 0.8s } @keyframes opac { from { opacity: 0 } to { opacity: 1 } } .w3-animate-show { animation: show 0.8s; animation-fill-mode: forwards; } @keyframes show { 0% { opacity: 1 } 100% { opacity: 0 } } 执行此操作,其中x / y / z是从所有系统目录开始匹配的模式。例如,在您的情况下,您可以使用--no-system-header-prefix x/y/z;或者你可以进一步挑选:--no-system-headers sys(通过以mm开头的sys子目录包含的系统目录中的所有文件;它只是一个前缀模式,而不是目录规范)。

在gcc中,这有点过时了。默认情况下,系统头只是系统目录中的标头,并且无法将特定目录排除为系统目录。但是,您可以使用--no-system-headers sys/mm丢弃所有系统目录,并将它们作为常规包含目录添加回来。例如:

-nostdinc

您需要gcc -nostdinc -I/usr/include -I/usr/lib/gcc/x86_64-pc-cygwin/5.4.0/include ... ;进入系统包含路径的-nostdinc路径最终会被忽略。

答案 1 :(得分:2)

默认情况下,

GCC suppresses warnings in system headers。原因是用户通常无法对这些标头生成的警告做任何事情,因为他们无法编辑代码来修复这些警告。您可以使用-Wsystem-headers启用这些警告。

对于您的具体示例,重新定义系统头中未在系统头中定义的宏,GCC应该警告即使-Wno-system-headers(它现在有基础设施来执行此操作)。有人已提交RFE: