首页 > 解决方案 > clang++ 是否以更轻松的方式处理系统标头?

问题描述

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 不支持零长度数组,因此,如果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()
{}

clang++ 背后有什么魔力可以更轻松地处理系统头文件吗?

标签: c++clinuxclangstandards

解决方案


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

是的,如果我们查看在 System Headers 中控制诊断的 clang 文档,它会说:

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

system_headerpragma 可用于将当前文件标记为系统头文件。从同一个文件中编译指示的位置开始不会产生任何警告。

#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指令被视为包含系统头文件。


推荐阅读