The following struct is defined in the Linux system header file /usr/include/sys/inotify.h
:
struct inotify_event
{
int wd;
uint32_t mask;
uint32_t cookie;
uint32_t len;
char name __flexarr;
};
Please note the last field name
, which is a zero-length array. C++17 does not support zero-length array, so, if using struct inotify_event
in a C++17 project and compiling it with -pedantic
, a compiler warning should be raised.
However, the following code doesn't raise any warning for struct inotify_event
. More weird, if I define a struct using zero-length array the same way, the warning is raised as expected.
Compiler options: 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()
{}
Is there any magic behind clang++ that treats system headers in a more relaxed way?
Is there any magic behind clang++ that treats system-defined headers in a more relaxed way?
Yes, if we look at the clang documentation for Controlling Diagnostics in System Headers it says:
Warnings are suppressed when they occur in system headers. By default, an included file is treated as a system header if it is found in an include path specified by
-isystem
, but this can be overridden in several ways.The
system_header
pragma can be used to mark the current file as being a system header. No warnings will be produced from the location of the pragma onwards within the same file.#if foo #endif foo // warning: extra tokens at end of #endif directive #pragma clang system_header #if foo #endif foo // no warning
The
–system-header-prefix=
and–no-system-header-prefix=
command-line arguments can be used to override whether subsets of an include path are treated as system headers. When the name in a#include
directive is found within a header search path and starts with a system prefix, the header is treated as a system header. The last prefix on the command-line which matches the specified header name takes precedence.For instance:
$ clang -Ifoo -isystem bar --system-header-prefix=x/ \ --no-system-header-prefix=x/y/
Here,
#include "x/a.h"
is treated as including a system header, even if the header is found infoo
, and#include "x/y/b.h"
is treated as not including a system header, even if the header is found inbar
.A
#include
directive which finds a file relative to the current directory is treated as including a system header if the including file is treated as a system header.