169 lines
7 KiB
Diff
169 lines
7 KiB
Diff
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
|
||
|