https://bugs.gentoo.org/969219

From 891761bca1aa78336e5b18c121075b6e4696c5d4 Mon Sep 17 00:00:00 2001
From: Paul Eggert <eggert@cs.ucla.edu>
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/mbschr.c (mbschr):
* lib/memchr2.c (memchr2):
Port to C23, where functions like strchr are qualifier-generic.
* 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 <lzaoral@redhat.com>
Upstream-commit: df17f4f37ed3ca373d23ad42eae51122bdb96626
---
 lib/c++defs.h   | 12 +++++++++++-
 lib/mbschr.c    |  2 +-
 lib/memchr2.c   |  2 +-
 lib/stdlib.in.h |  6 +++---
 lib/string.in.h |  4 ----
 lib/wchar.in.h  |  2 +-
 6 files changed, 17 insertions(+), 11 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/mbschr.c b/lib/mbschr.c
index c9e14b5..6582134 100644
--- a/lib/mbschr.c
+++ b/lib/mbschr.c
@@ -65,5 +65,5 @@ mbschr (const char *string, int c)
       return NULL;
     }
   else
-    return strchr (string, c);
+    return (char *) strchr (string, c);
 }
diff --git a/lib/memchr2.c b/lib/memchr2.c
index 7493823..d7724ae 100644
--- a/lib/memchr2.c
+++ b/lib/memchr2.c
@@ -55,7 +55,7 @@ memchr2 (void const *s, int c1_in, int c2_in, size_t n)
   c2 = (unsigned char) c2_in;
 
   if (c1 == c2)
-    return memchr (s, c1, n);
+    return (void *) memchr (s, c1, n);
 
   /* Handle the first few bytes by reading one byte at a time.
      Do this until VOID_PTR is aligned on a longword boundary.  */
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
