-pedantic warnings in system headers?

The assert.h in glibc 2.25 defines assert as a GNU-extension "statement expression", see <sourceware.org Git - glibc.git/commit; "assert.h: allow gcc to detect assert(a = 1) errors":

/* When possible, define assert so that it does not add extra
   parentheses around EXPR. Otherwise, those added parentheses would
   suppress warnings we'd expect to be detected by gcc's -Wparentheses. */
# if !defined __GNUC__ || defined __STRICT_ANSI__
# define assert(expr) \
    ((expr) \
     ? __ASSERT_VOID_CAST (0) \
     : __assert_fail (#expr, __FILE__, __LINE__, __ASSERT_FUNCTION))
# else
# define assert(expr) \
    ({ \
      if (expr) \
        ; /* empty */ \
      else \
        __assert_fail (#expr, __FILE__, __LINE__, __ASSERT_FUNCTION); \
    })
# endif

A simple program

$ cat test.c
#include <assert.h>
int main() {
    assert(1);
}

causes no issues when compiled with GCC (some random "gcc (GCC) 7.1.1 20170622 (Red Hat 7.1.1-3)"),

$ gcc -pedantic test.c

but emits a diagnostic when compiled with Clang (at least recent trunk),

$ /data/llvm/inst/bin/clang -pedantic test.c
test.c:3:5: warning: use of GNU statement expression extension [-Wgnu-statement-expression]
    assert(1);
    ^
/usr/include/assert.h:95:6: note: expanded from macro 'assert'
    ({ \
     ^
1 warning generated.

From a quick look at the code of both GCC and Clang, I assume the difference is due to GCC implicitly assuming /usr/include/assert.h to be a system header (so it suppresses the pedantic warning there), while Clang does not. (Curiously, while many of the libstdc++ files in /usr/include/c++/... have

#pragma GCC system_header

near the top, none of the files from glibc in /usr/include/ do.)

Anybody got any further information, whether the difference in behavior is by accident or by design?

It should, but you can check that assumption easily by using -isystem
/usr/include.

Joerg

I believe that this is a known issue, where the warning suppression for macros happens based on the instantiation location, not on the declaration location. You are getting the warning because the file in which you instantiate the macro is not a system header, even though the macro is defined in a system header.

David

From a quick look at the code of both GCC and Clang, I assume the difference is due to GCC implicitly assuming /usr/include/assert.h to be a system header (so it suppresses the pedantic warning there), while Clang does not. (Curiously, while many of the libstdc++ files in /usr/include/c++/… have

I believe that this is a known issue, where the warning suppression for macros happens based on the instantiation location, not on the declaration location. You are getting the warning because the file in which you instantiate the macro is not a system header, even though the macro is defined in a system header.

Not always the case - Clang looks at where a macro is defined in many cases, I think - though I could be wrong. Maybe this one hasn’t been adjusted yet.

I've come up with <https://reviews.llvm.org/D35564&gt; "Suppress -pedantic warnings about GNU extension StmtExpr in glibc's assert macro". Reviews welcome.