Skip to content
Advertisement

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

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?

Advertisement

Answer

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 in foo, and #include "x/y/b.h" is treated as not including a system header, even if the header is found in bar.

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.

Advertisement