new __attribute_nonnull__(params) conflicts with third-party (Staring with a summary, then following with details.) I am fully aware that leading _ and leading __ and any __ are reserved in C indentifiers. This bug report suggests a patch to hopefully reduce breakage caused by the introduction of __attribute_nonnull__. ``` diff --git a/misc/sys/cdefs.h b/misc/sys/cdefs.h index 4dac9d264d..70d6ef37f4 100644 --- a/misc/sys/cdefs.h +++ b/misc/sys/cdefs.h @@ -329,7 +329,7 @@ # endif #endif #ifndef __nonnull -# define __nonnull(params) __attribute_nonnull__ (params) +# define __nonnull(params) __attribute__ ((__nonnull__ params)) #endif /* The returns_nonnull function attribute marks the return type of the function ``` Details __attribute_xxxxx__ is a useful idiom that I and others have used for 20+ years in software ported to multiple platforms, including alternative libc libraries. Using __attribute_xxxxx__ in code allows for `#define __attribute_xxxxx__ /*nothing*/` in environments without support for __attribute__ ((__xxxxx__)). For example: https://github.com/gstrauss/plasma/blob/master/plasma_attr.h#L213 ``` #ifndef __attribute_nonnull__ #if __has_attribute(nonnull) \ || __GNUC_PREREQ(3,3) #define __attribute_nonnull__ __attribute__((__nonnull__)) #else #define __attribute_nonnull__ #endif #endif ``` I have used the above for some 20+ years with compilers including gcc, clang, Sun Studio cc, IBM xlc, HP acc on Linux, *BSD, Solaris, AIX, HPUX Code can be annotated with __attribute_nonull__ and the attribute is defined for compilers which support it, and defined to a no-op for those which do not. I have the same code in the lighttpd web server https://github.com/lighttpd/lighttpd1.4/blob/master/src/first.h#L246 Unfortunately, there is a limitation in C in how macros are handled with and without arguments. In glibc 2.35 development, __attribute_nonnull__(params) has been introduced. https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=0b5ca7c3e551e5502f3be3b06453324fe8604e82 https://sourceware.org/git/?p=glibc.git;a=blobdiff;f=misc/sys/cdefs.h;h=4dac9d264d28d6ddf8d3ccd99a9d91a3ca410338;hp=e490fc1aebeadc3dc19b83e18d875d0827b9d695;hb=0b5ca7c3e551e5502f3be3b06453324fe8604e82;hpb=f3e664563361dc17530113b3205998d1f19dc4d9 This breaks pre-existing usage of the idiom __attribute_nonnull__ if used *without params* Some gcc attributes take an *optional* argument, e.g. __nonnull__, __deprecated__, __sentinel__ In https://github.com/gstrauss/plasma, I differentiated with macros __attribute_nonnull__ and __attribute_nonnull_x__(params) I am not saying this is the only solution, but it does differentiate. Unfortunately, the new macro in glibc for __attribute_nonnull__(params) breaks historical usage of __attribute_nonnull__ without params. As I mentioned above, I recognize that leading __ names are reserved for the system libraries, and it is glibc's prerogative to define the macro for __attribute_nonnull__ however glibc developers please. There is already macro __nonnull(params) in gcc and clang #define __nonnull(params) __attribute__ ((__nonnull__ params)) ==> For greatest compatibility, I kindly request that glibc 2.35 *not define* __attribute_nonull__ at all and instead continue to use __nonnull(params) If not, then please consider the patch at the top of this post which continues to define __nonnull(params) directly to #define __nonnull(params) __attribute__ ((__nonnull__ params)) so that others who may have used the __attribute_nonnull__ idiom do not have to track down weird compiler errors from system headers using __nonnull(params) in addition to the application code which uses __attribute_nonnull__ without params. The impetus for this bug report is that lighttpd 1.4.60 release breaks in Fedora Rawhide (which is using glibc 2.34.9000), due to both lighttpd and glibc 2.34.9000 having different definitions for __attribute_nonnull__. lighttpd usage of __attribute_nonull__ does not expect __attribute_nonnull__(params) to require parameters, leading to compiler errors where lighttpd headers uses __attribute_nonnull__ without params. Thank you. Glenn
In order to match glibc 2.35 development, I have modified lighttpd to define __attribute_nonnull__(params) with an argument for params, and I have modified lighttpd usage from __attribute_nonnull__ to __attribute_nonnull__(). (This is also extensible to filling in params, e.g. __attribute_nonnull((1,2,3)), as is recommended by gcc for passing a single arg or no arg to attributes.) lighttpd patch (not glibc): ``` #ifndef __attribute_nonnull__ #if __has_attribute(nonnull) \ || __GNUC_PREREQ(3,3) -#define __attribute_nonnull__ __attribute__((__nonnull__)) +#define __attribute_nonnull__(params) __attribute__((__nonnull__ params)) #else -#define __attribute_nonnull__ +#define __attribute_nonnull__(params) #endif #endif ``` (In hindsight, that is probably how I should have defined macros for attributes which take an optional single argument as parenthesized set of 0 or more arguments.)