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

xml*_*lmx 2 c c++ linux standards clang

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

struct inotify_event
{
    int wd;
    uint32_t mask;
    uint32_t cookie;
    uint32_t len;
    char name __flexarr;
};
Run Code Online (Sandbox Code Playgroud)

请注意最后一个字段name,它是一个零长度数组.C++ 17不支持零长度的阵列,所以,如果使用struct inotify_event以C++ 17项目和与编译它-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()
{}
Run Code Online (Sandbox Code Playgroud)

clang ++背后是否有任何魔术以更轻松的方式处理系统头?

Sha*_*our 5

clang ++背后是否有任何魔术能够以更轻松的方式处理系统定义的头文件?

是的,如果我们查看系统标题中的Controlling Diagnostics的clang 文档,它会说:

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

system_headerpragma可用于将当前文件标记为系统头.在同一文件中,pragma的位置不会产生任何警告.

#if foo
#endif foo // warning: extra tokens at end of #endif directive

#pragma clang system_header

#if foo
#endif foo // no warning
Run Code Online (Sandbox Code Playgroud)

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

例如:

$ clang -Ifoo -isystem bar --system-header-prefix=x/ \
    --no-system-header-prefix=x/y/
Run Code Online (Sandbox Code Playgroud)

在此,#include "x/a.h"被处理为包括一个系统标题,即使头部被发现在foo,并且#include "x/y/b.h"被视为不包括一个系统标题,即使报头在发现bar.

#include指找到相对于当前目录中的文件指令视为包括一个系统标题,如果包括文件被作为系统标题处理.