c++ - 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++ 背后有什么魔力可以更轻松地处理系统头文件吗?
解决方案
clang++ 背后有什么魔力可以更轻松地处理系统定义的标头吗?
是的,如果我们查看在 System Headers 中控制诊断的 clang 文档,它会说:
警告在系统标头中出现时会被抑制。默认情况下,如果在 指定的包含路径中找到包含的文件,则将其视为系统头文件
-isystem
,但这可以通过多种方式覆盖。
system_header
pragma 可用于将当前文件标记为系统头文件。从同一个文件中编译指示的位置开始不会产生任何警告。#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
指令被视为包含系统头文件。