clang++ 是否以更轻松的方式处理系统标头?

Does clang++ treat system headers in a more relaxed way?

本文关键字:处理系统 方式 是否 clang++      更新时间:2023-10-16

以下结构在 Linux 系统头文件/usr/include/sys/inotify.h中定义:

struct inotify_event
{
int wd;
uint32_t mask;
uint32_t cookie;
uint32_t len;
char name __flexarr;
};

请注意最后一个字段name,它是一个零长度数组。C++17 不支持零长度数组,因此,如果在 C++17 项目中使用struct inotify_event并使用-pedantic编译它,则应引发编译器警告。

但是,以下代码不会引发任何警告struct inotify_event。更奇怪的是,如果我以相同的方式使用零长度数组定义结构,则会按预期引发警告。

编译器选项:clang++ -std=c++17 -pedantic main.cpp

#include <sys/inotify.h>
struct inotify_event* p = nullptr; // no warning
struct A
{
int x;
char name __flexarr; // warning: flexible array members are a C99 feature
};
int main()
{}

clang++ 背后是否有任何魔力可以更轻松地处理系统标头?

clang++ 背后有什么魔力可以更轻松地处理系统定义的标头吗?

是的,如果我们查看"控制系统标头中的诊断"的 clang 文档,它说:

当警告出现在系统标头中时,将禁止显示警告。默认情况下,如果在-isystem指定的包含路径中找到包含的文件,则该文件将被视为系统标头,但这可以通过多种方式覆盖。

system_header杂注可用于将当前文件标记为系统标头。从杂注的位置开始,不会在同一文件中生成警告。

#if foo
#endif foo // warning: extra tokens at end of #endif directive
#pragma clang system_header
#if foo
#endif foo // no warning

–system-header-prefix=–no-system-header-prefix=命令行参数可用于覆盖是否将包含路径的子集视为系统标头。当#include指令中的名称在标头搜索路径中找到并以系统前缀开头时,该标头将被视为系统标头。命令行上与指定标头名称匹配的最后一个前缀优先。

例如:

$ clang -Ifoo -isystem bar --system-header-prefix=x/ 
--no-system-header-prefix=x/y/

在这里,#include "x/a.h"被视为包含系统标头,即使在foo中找到标头,#include "x/y/b.h"也被视为不包含系统标头,即使在bar中找到标头也是如此。

如果将包含文件视为系统头,则查找相对于当前目录的文件的#include指令将被视为包含系统头。