Paul Eggert wrote: >+ libc-config: avoid Clang’s __diagnose_if__ >+ * lib/cdefs.h (__warndecl, __warnattr, __errordecl): >+ For now, do not use __diagnose_if__ here, as this fails >+ on Fedora 31 with Clang 9.0.1, with diagnostic >+ "/usr/include/bits/stdio2.h:263:9: error: fgets called with bigger >+ size than length of destination buffer >+ [-Werror,-Wuser-defined-warnings]". I guess Clang 9 warns even >+ for functions that are not called? I can reproduce the redundant warnings, on Fedora 31 with Clang 9.0.1, when applying the change to gnulib/lib/cdefs.h also to /usr/include/sys/cdefs.h. With the attached program foo.c I get warnings for each of these inline functions that conditionally invokes a *_chk_warn function. Apparently, clang - unlike GCC - processes the body of the inline function also when the inline function is never referenced. It would be possible to silence these warnings by adding a gnulib module as attached (clang-warnings.tar.gz). BUT since the macros __warndecl and __warnattr are ONLY used by Fortify inline functions - there are no other uses in the glibc headers, nor in gnulib - and most of these uses produce redundant warnings, this is all pointless. What matters for user code is that gnulib's "attribute.h" defines ATTRIBUTE_WARNING and ATTRIBUTE_ERROR in a way that works with clang. In order to use the clang __diagnose_if__ primitive, the Fortify inline functions would need to be written in a different way. This has been done in the Android header files. For example, here is the fgets function in glibc - tailored for GCC -: extern char *__REDIRECT (__fgets_chk_warn, (char *__restrict __s, size_t __size, int __n, FILE *__restrict __stream), __fgets_chk) __wur __warnattr ("fgets called with bigger size than length " "of destination buffer"); __fortify_function __wur char * fgets (char *__restrict __s, int __n, FILE *__restrict __stream) { if (__bos (__s) != (size_t) -1) { if (!__builtin_constant_p (__n) || __n <= 0) return __fgets_chk (__s, __bos (__s), __n, __stream); if ((size_t) __n > __bos (__s)) return __fgets_chk_warn (__s, __bos (__s), __n, __stream); // <=== line 263 } return __fgets_alias (__s, __n, __stream); } and here it is in Android - tailored for clang -: __BIONIC_FORTIFY_INLINE char* fgets(char* const __pass_object_size dest, int size, FILE* stream) __overloadable __clang_error_if(size < 0, "in call to 'fgets', size should not be negative") __clang_error_if(size > __bos(dest), "in call to 'fgets', size is larger than the destination buffer") { size_t bos = __bos(dest); if (bos == __BIONIC_FORTIFY_UNKNOWN_SIZE) { return __call_bypassing_fortify(fgets)(dest, size, stream); } return __fgets_chk(dest, size, stream, bos); } 2020-08-23 Bruno Haible libc-config: Improve comments. * lib/cdefs.h (__warndecl, __warnattr, __errordecl): Explain why we cannot use clang's __diagnose_if__ here. diff --git a/lib/cdefs.h b/lib/cdefs.h index 32a2c40..1ae9ffc 100644 --- a/lib/cdefs.h +++ b/lib/cdefs.h @@ -148,7 +148,11 @@ # define __warnattr(msg) __attribute__((__warning__ (msg))) # define __errordecl(name, msg) \ extern void name (void) __attribute__((__error__ (msg))) -#elif __glibc_clang_has_attribute (__diagnose_if__) && 0 /* fails on Fedora 31 with Clang 9. */ +#elif __glibc_clang_has_attribute (__diagnose_if__) && 0 +/* These definitions are not enabled, because they produce bogus warnings + in the glibc Fortify functions. These functions are written in a style + that works with GCC. In order to work with clang, these functions would + need to be modified. */ # define __warndecl(name, msg) \ extern void name (void) __attribute__((__diagnose_if__ (1, msg, "warning"))) # define __warnattr(msg) __attribute__((__diagnose_if__ (1, msg, "warning")))