https://bugs.gentoo.org/969220 https://src.fedoraproject.org/rpms/nano/blob/rawhide/f/nano-8.7-gnulib-c23.patch From c028b6f1804a8fef398d7642d8ccb7d8f73150fb Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Sun, 23 Nov 2025 00:50:40 -0800 Subject: [PATCH] Port to C23 qualifier-generic fns like strchr MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This ports Gnulib to strict C23 platforms that reject code like ‘char *q = strchr (P, 'x');’ when P is a pointer to const, because in C23 strchr is a qualifier-generic function so strchr (P, 'x') returns char const *. This patch does not attempt to do the following two things, which might be useful in the future: 1. When compiling on non-C23 platforms, check user code for portability to platforms that define qualifier-generic functions. 2. Port Gnulib to platforms that have qualifier-generic functions not listed in the C23 standard, e.g., strchrnul. I don’t know of any such platforms. * lib/c++defs.h (_GL_FUNCDECL_SYS_NAME): New macro. * lib/c++defs.h (_GL_FUNCDECL_SYS): * lib/stdlib.in.h (bsearch): Use it, to prevent C23 names like strchr from acting like macros. * lib/string.in.h (memchr, strchr, strpbrk, strrchr): Do not #undef when GNULIB_POSIXCHECK is defined, as this could cause conforming C23 code to fail to conform. It’s not clear why _GL_WARN_ON_USE_CXX; perhaps it was needed but isn’t any more? But for now, limit the removal of #undef to these four functions where #undeffing is clearly undesirable in C23. * lib/wchar.in.h (wmemchr): Parenthesize function name in decl, to prevent it from acting like a macro. Cherry-picked-by: Lukáš Zaoral Upstream-commit: df17f4f37ed3ca373d23ad42eae51122bdb96626 --- lib/c++defs.h | 12 +++++++++++- lib/stdlib.in.h | 6 +++--- lib/string.in.h | 4 ---- lib/wchar.in.h | 2 +- 4 files changed, 15 insertions(+), 9 deletions(-) diff --git a/lib/c++defs.h b/lib/c++defs.h index b77979a..7384457 100644 --- a/lib/c++defs.h +++ b/lib/c++defs.h @@ -127,6 +127,16 @@ #define _GL_FUNCDECL_RPL_1(rpl_func,rettype,parameters,...) \ _GL_EXTERN_C_FUNC __VA_ARGS__ rettype rpl_func parameters +/* _GL_FUNCDECL_SYS_NAME (func) expands to plain func if C++, and to + parenthsized func otherwise. Parenthesization is needed in C23 if + the function is like strchr and so is a qualifier-generic macro + that expands to something more complicated. */ +#ifdef __cplusplus +# define _GL_FUNCDECL_SYS_NAME(func) func +#else +# define _GL_FUNCDECL_SYS_NAME(func) (func) +#endif + /* _GL_FUNCDECL_SYS (func, rettype, parameters, [attributes]); declares the system function, named func, with the given prototype, consisting of return type, parameters, and attributes. @@ -139,7 +149,7 @@ _GL_FUNCDECL_SYS (posix_openpt, int, (int flags), _GL_ATTRIBUTE_NODISCARD); */ #define _GL_FUNCDECL_SYS(func,rettype,parameters,...) \ - _GL_EXTERN_C_FUNC __VA_ARGS__ rettype func parameters + _GL_EXTERN_C_FUNC __VA_ARGS__ rettype _GL_FUNCDECL_SYS_NAME (func) parameters /* _GL_CXXALIAS_RPL (func, rettype, parameters); declares a C++ alias called GNULIB_NAMESPACE::func diff --git a/lib/stdlib.in.h b/lib/stdlib.in.h index bef0aaa..fd0e1e0 100644 --- a/lib/stdlib.in.h +++ b/lib/stdlib.in.h @@ -224,9 +224,9 @@ _GL_INLINE_HEADER_BEGIN /* Declarations for ISO C N3322. */ #if defined __GNUC__ && __GNUC__ >= 15 && !defined __clang__ -_GL_EXTERN_C void *bsearch (const void *__key, - const void *__base, size_t __nmemb, size_t __size, - int (*__compare) (const void *, const void *)) +_GL_EXTERN_C void *_GL_FUNCDECL_SYS_NAME (bsearch) + (const void *__key, const void *__base, size_t __nmemb, size_t __size, + int (*__compare) (const void *, const void *)) _GL_ATTRIBUTE_NONNULL_IF_NONZERO (2, 3) _GL_ARG_NONNULL ((5)); _GL_EXTERN_C void qsort (void *__base, size_t __nmemb, size_t __size, int (*__compare) (const void *, const void *)) diff --git a/lib/string.in.h b/lib/string.in.h index fdcdd21..8b56acf 100644 --- a/lib/string.in.h +++ b/lib/string.in.h @@ -409,7 +409,6 @@ _GL_CXXALIASWARN1 (memchr, void const *, _GL_CXXALIASWARN (memchr); # endif #elif defined GNULIB_POSIXCHECK -# undef memchr /* Assume memchr is always declared. */ _GL_WARN_ON_USE (memchr, "memchr has platform-specific bugs - " "use gnulib module memchr for portability" ); @@ -674,7 +673,6 @@ _GL_WARN_ON_USE (stpncpy, "stpncpy is unportable - " #if defined GNULIB_POSIXCHECK /* strchr() does not work with multibyte strings if the locale encoding is GB18030 and the character to be searched is a digit. */ -# undef strchr /* Assume strchr is always declared. */ _GL_WARN_ON_USE_CXX (strchr, const char *, char *, (const char *, int), @@ -981,7 +979,6 @@ _GL_CXXALIASWARN (strpbrk); Even in this simple case, it does not work with multibyte strings if the locale encoding is GB18030 and one of the characters to be searched is a digit. */ -# undef strpbrk _GL_WARN_ON_USE_CXX (strpbrk, const char *, char *, (const char *, const char *), "strpbrk cannot work correctly on character strings " @@ -1011,7 +1008,6 @@ _GL_WARN_ON_USE (strspn, "strspn cannot work correctly on character strings " #if defined GNULIB_POSIXCHECK /* strrchr() does not work with multibyte strings if the locale encoding is GB18030 and the character to be searched is a digit. */ -# undef strrchr /* Assume strrchr is always declared. */ _GL_WARN_ON_USE_CXX (strrchr, const char *, char *, (const char *, int), diff --git a/lib/wchar.in.h b/lib/wchar.in.h index ab602a2..6be4515 100644 --- a/lib/wchar.in.h +++ b/lib/wchar.in.h @@ -301,7 +301,7 @@ _GL_EXTERN_C int wcsncmp (const wchar_t *__s1, const wchar_t *__s2, size_t __n) _GL_ATTRIBUTE_NONNULL_IF_NONZERO (1, 3) _GL_ATTRIBUTE_NONNULL_IF_NONZERO (2, 3); # ifndef __cplusplus -_GL_EXTERN_C wchar_t *wmemchr (const wchar_t *__s, wchar_t __wc, size_t __n) +_GL_EXTERN_C wchar_t *(wmemchr) (const wchar_t *__s, wchar_t __wc, size_t __n) _GL_ATTRIBUTE_NONNULL_IF_NONZERO (1, 3); # endif _GL_EXTERN_C wchar_t *wmemset (wchar_t *__s, wchar_t __wc, size_t __n) -- 2.52.0