Bug 28425 - new __attribute_nonnull__(params) conflicts with third-party
Summary: new __attribute_nonnull__(params) conflicts with third-party
Status: UNCONFIRMED
Alias: None
Product: glibc
Classification: Unclassified
Component: libc (show other bugs)
Version: 2.35
: P2 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2021-10-05 20:58 UTC by gstrauss
Modified: 2021-10-05 23:26 UTC (History)
2 users (show)

See Also:
Host:
Target:
Build:
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description gstrauss 2021-10-05 20:58:38 UTC
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
Comment 1 gstrauss 2021-10-05 23:26:44 UTC
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.)