mailing list of musl libc
 help / color / mirror / code / Atom feed
* [musl] [C23 const 1/2] C23: change bsearch to a macro that respects the const contract
       [not found] <cover.1685541439.git.Jens.Gustedt@inria.fr>
@ 2023-05-31 14:00 ` Jens Gustedt
  2023-05-31 14:00 ` [musl] [C23 const 2/2] C23: change string.h and wchar.h interfaces to macros " Jens Gustedt
  1 sibling, 0 replies; 3+ messages in thread
From: Jens Gustedt @ 2023-05-31 14:00 UTC (permalink / raw)
  To: musl

This adds a macro interface to stdlib that has an additional cast of
the return value to `void const*` for the case that the argument to
the call was also const-qualified. Nothing changes for the function
itself, only the identifier has to be protected with (), such that the
macro does not expand for the function declaration or definition.

The implementation of this macro might be a bit unusual for musl. It
serves the purpose of better error tracking if users call the macro
with the wrong argument.

(0) Programming _Generic is hard. It needs that all choices are
syntactically and semantically valid. Otherwise the users drowns in
warnings and errors.

(1) Compilers nowadays track on which line in a macro definition an
error appears. For _Generic it helps a lot if the compiler presents
the exact choice which leads to a diagnostic.

(2) All object pointer values with unqualified or const-qualified
target are valid. Therefore we use a trick that maps all
const-qualified targets to void const*.

(3) The case of a wrongly qualified pointer argument would lead to a
misleading diagnostic without the cast.
---
 include/stdlib.h     | 12 +++++++++++-
 src/include/stdlib.h |  2 ++
 src/stdlib/bsearch.c |  2 +-
 3 files changed, 14 insertions(+), 2 deletions(-)

diff --git a/include/stdlib.h b/include/stdlib.h
index 72522cd6..b7abf8c4 100644
--- a/include/stdlib.h
+++ b/include/stdlib.h
@@ -60,7 +60,17 @@ char *getenv (const char *);
 
 int system (const char *);
 
-void *bsearch (const void *, const void *, size_t, size_t, int (*)(const void *, const void *));
+void * (bsearch) (const void *, const void *, size_t, size_t, int (*)(const void *, const void *));
+#if __STDC_VERSION__ > 201112L
+# define bsearch(K, B, N, S, C)                                         \
+	_Generic(                                                       \
+		/* ensure conversion to a void pointer */               \
+		1 ? (B) : (void*)1,                                     \
+		void const*: (void const*)bsearch((K), (void const*)(B), (N), (S), (C)), \
+		/* volatile qualification of *B is an error for this call */ \
+		default:     bsearch((K), (B), (N), (S), (C))           \
+)
+#endif
 void qsort (void *, size_t, size_t, int (*)(const void *, const void *));
 
 int abs (int);
diff --git a/src/include/stdlib.h b/src/include/stdlib.h
index 812b04de..f0b03df9 100644
--- a/src/include/stdlib.h
+++ b/src/include/stdlib.h
@@ -16,4 +16,6 @@ hidden void *__libc_calloc(size_t, size_t);
 hidden void *__libc_realloc(void *, size_t);
 hidden void __libc_free(void *);
 
+#undef bsearch
+
 #endif
diff --git a/src/stdlib/bsearch.c b/src/stdlib/bsearch.c
index fe050ea3..4f62ea37 100644
--- a/src/stdlib/bsearch.c
+++ b/src/stdlib/bsearch.c
@@ -1,6 +1,6 @@
 #include <stdlib.h>
 
-void *bsearch(const void *key, const void *base, size_t nel, size_t width, int (*cmp)(const void *, const void *))
+void *(bsearch)(const void *key, const void *base, size_t nel, size_t width, int (*cmp)(const void *, const void *))
 {
 	void *try;
 	int sign;
-- 
2.34.1


^ permalink raw reply	[flat|nested] 3+ messages in thread

* [musl] [C23 const 2/2] C23: change string.h and wchar.h interfaces to macros that respects the const contract
       [not found] <cover.1685541439.git.Jens.Gustedt@inria.fr>
  2023-05-31 14:00 ` [musl] [C23 const 1/2] C23: change bsearch to a macro that respects the const contract Jens Gustedt
@ 2023-05-31 14:00 ` Jens Gustedt
  1 sibling, 0 replies; 3+ messages in thread
From: Jens Gustedt @ 2023-05-31 14:00 UTC (permalink / raw)
  To: musl

This adds a macro interfaces to those string functions that search for
a string position. This has an additional cast of the return value to
`void const*` for the case that the argument to the call was also
const-qualified. Nothing changes for the correspondin function itself,
only the identifier has to be protected with (), such that the macro
does not expand for the function declaration or definition.

The implementation of this macro might be a bit unusual for musl. It
serves the purpose of better error tracking if users call the macro
with the wrong argument.

(0) Programming _Generic is hard. It needs that all choices are
syntactically and semantically valid. Otherwise the users drowns in
warnings and errors.

(1) Compilers nowadays track on which line in a macro definition an
error appears. For _Generic it helps a lot if the compiler presents
the exact choice which leads to a diagnostic.

(2) All object pointer values with unqualified or const-qualified
target are valid for the memchr function. Therefore we use a trick
that maps all const-qualified targets to void const*.

(3) All other functions have to accept either pointers to character
types (char or wchar_t) or pointers to void (where there is an
implicit conversion to the character pointer). Therefore we cannot use
the trick in (2), this would map any const-qualified pointer to that
case. Instead, we list the two possible const-qualifed cases
explicitly.

(4) The case of wrongly qualified pointer arguments would lead to a
misleading diagnostic without the casts.
---
 include/string.h     | 54 ++++++++++++++++++++++++++++++++++++++-----
 include/wchar.h      | 55 +++++++++++++++++++++++++++++++++++++++-----
 src/include/string.h |  6 +++++
 src/include/wchar.h  |  6 +++++
 src/string/memchr.c  |  2 +-
 src/string/strchr.c  |  2 +-
 src/string/strpbrk.c |  2 +-
 src/string/strrchr.c |  2 +-
 src/string/strstr.c  |  2 +-
 src/string/wcschr.c  |  2 +-
 src/string/wcspbrk.c |  2 +-
 src/string/wcsrchr.c |  2 +-
 src/string/wcsstr.c  |  2 +-
 src/string/wmemchr.c |  2 +-
 14 files changed, 119 insertions(+), 22 deletions(-)

diff --git a/include/string.h b/include/string.h
index 7df7a402..61768cf7 100644
--- a/include/string.h
+++ b/include/string.h
@@ -28,7 +28,54 @@ void *memcpy (void *__restrict, const void *__restrict, size_t);
 void *memmove (void *, const void *, size_t);
 void *memset (void *, int, size_t);
 int memcmp (const void *, const void *, size_t);
-void *memchr (const void *, int, size_t);
+
+void *(memchr) (const void *, int, size_t);
+char *(strchr) (const char *, int);
+char *(strrchr) (const char *, int);
+char *(strpbrk) (const char *, const char *);
+char *(strstr) (const char *, const char *);
+#if __STDC_VERSION__ > 201112L
+# define memchr(S, C, N)                                                \
+  _Generic(                                                             \
+           /* ensure conversion to a void pointer */                    \
+           1 ? (S) : (void*)1,                                          \
+           void const*: (void const*)memchr((void const*)(S), (C), (N)), \
+           /* volatile qualification of *S is an error for this call */ \
+           default:     memchr((S), (C), (N))                           \
+)
+# define strchr(S, C)                                                   \
+  _Generic(                                                             \
+           (S),                                                         \
+           void const*: (char const*)strchr((char const*)(S), (C)),     \
+           char const*: (char const*)strchr((char const*)(S), (C)),     \
+           /* volatile qualification of *S is an error for this call */ \
+           default:     strchr((S), (C))                                \
+)
+# define strrchr(S, C)                                                  \
+  _Generic(                                                             \
+           (S),                                                         \
+           void const*: (char const*)strrchr((char const*)(S), (C)),    \
+           char const*: (char const*)strrchr((char const*)(S), (C)),    \
+           /* volatile qualification of *S is an error for this call */ \
+           default:     strrchr((S), (C))                               \
+)
+# define strpbrk(S, A)                                                  \
+  _Generic(                                                             \
+           (S),                                                         \
+           void const*: (char const*)strpbrk((char const*)(S), (A)),    \
+           char const*: (char const*)strpbrk((char const*)(S), (A)),    \
+           /* volatile qualification of *S is an error for this call */ \
+           default:     strpbrk((S), (A))                               \
+)
+# define strstr(H, N)                                                   \
+  _Generic(                                                             \
+           (H),                                                         \
+           void const*: (char const*)strstr((char const*)(H), (N)),     \
+           char const*: (char const*)strstr((char const*)(H), (N)),     \
+           /* volatile qualification of *S is an error for this call */ \
+           default:     strstr((H), (N))                                \
+)
+#endif
 
 char *strcpy (char *__restrict, const char *__restrict);
 char *strncpy (char *__restrict, const char *__restrict, size_t);
@@ -42,13 +89,8 @@ int strncmp (const char *, const char *, size_t);
 int strcoll (const char *, const char *);
 size_t strxfrm (char *__restrict, const char *__restrict, size_t);
 
-char *strchr (const char *, int);
-char *strrchr (const char *, int);
-
 size_t strcspn (const char *, const char *);
 size_t strspn (const char *, const char *);
-char *strpbrk (const char *, const char *);
-char *strstr (const char *, const char *);
 char *strtok (char *__restrict, const char *__restrict);
 
 size_t strlen (const char *);
diff --git a/include/wchar.h b/include/wchar.h
index ed5d774d..194f7f8f 100644
--- a/include/wchar.h
+++ b/include/wchar.h
@@ -61,21 +61,64 @@ int wcsncmp (const wchar_t *, const wchar_t *, size_t);
 int wcscoll(const wchar_t *, const wchar_t *);
 size_t wcsxfrm (wchar_t *__restrict, const wchar_t *__restrict, size_t);
 
-wchar_t *wcschr (const wchar_t *, wchar_t);
-wchar_t *wcsrchr (const wchar_t *, wchar_t);
-
 size_t wcscspn (const wchar_t *, const wchar_t *);
 size_t wcsspn (const wchar_t *, const wchar_t *);
-wchar_t *wcspbrk (const wchar_t *, const wchar_t *);
 
 wchar_t *wcstok (wchar_t *__restrict, const wchar_t *__restrict, wchar_t **__restrict);
 
 size_t wcslen (const wchar_t *);
 
-wchar_t *wcsstr (const wchar_t *__restrict, const wchar_t *__restrict);
 wchar_t *wcswcs (const wchar_t *, const wchar_t *);
 
-wchar_t *wmemchr (const wchar_t *, wchar_t, size_t);
+wchar_t *(wmemchr) (const wchar_t *, wchar_t, size_t);
+wchar_t *(wcschr) (const wchar_t *, wchar_t);
+wchar_t *(wcsrchr) (const wchar_t *, wchar_t);
+wchar_t *(wcspbrk) (const wchar_t *, const wchar_t *);
+wchar_t *(wcsstr) (const wchar_t *__restrict, const wchar_t *__restrict);
+#if __STDC_VERSION__ > 201112L
+# define wmemchr(S, C, N)                                               \
+  _Generic(                                                             \
+           (S),                                                         \
+           void const*: (wchar_t const*)wmemchr((wchar_t const*)(S), (C), (N)), \
+           wchar_t const*: (wchar_t const*)wmemchr((wchar_t const*)(S), (C), (N)), \
+           /* volatile qualification of *S is an error for this call */ \
+           default:     wmemchr((S), (C), (N))                          \
+)
+# define wcschr(S, C)                                                   \
+  _Generic(                                                             \
+           (S),                                                         \
+           void const*: (wchar_t const*)wcschr((wchar_t const*)(S), (C)), \
+           wchar_t const*: (wchar_t const*)wcschr((wchar_t const*)(S), (C)), \
+           /* volatile qualification of *S is an error for this call */ \
+           default:     wcschr((S), (C))                                \
+)
+# define wcsrchr(S, C)                                                  \
+  _Generic(                                                             \
+           (S),                                                         \
+           void const*: (wchar_t const*)wcsrchr((wchar_t const*)(S), (C)), \
+           wchar_t const*: (wchar_t const*)wcsrchr((wchar_t const*)(S), (C)), \
+           /* volatile qualification of *S is an error for this call */ \
+           default:     wcsrchr((S), (C))                               \
+)
+# define wcspbrk(S, A)                                                  \
+  _Generic(                                                             \
+           (S),                                                         \
+           void const*: (wchar_t const*)wcspbrk((wchar_t const*)(S), (A)), \
+           wchar_t const*: (wchar_t const*)wcspbrk((wchar_t const*)(S), (A)), \
+           /* volatile qualification of *S is an error for this call */ \
+           default:     wcspbrk((S), (A))                               \
+)
+# define wcsstr(H, N)                                                   \
+  _Generic(                                                             \
+           (H),                                                         \
+           void const*: (wchar_t const*)wcsstr((wchar_t const*)(H), (N)), \
+           wchar_t const*: (wchar_t const*)wcsstr((wchar_t const*)(H), (N)), \
+           /* volatile qualification of *S is an error for this call */ \
+           default:     wcsstr((H), (N))                                \
+)
+#endif
+
+
 int wmemcmp (const wchar_t *, const wchar_t *, size_t);
 wchar_t *wmemcpy (wchar_t *__restrict, const wchar_t *__restrict, size_t);
 wchar_t *wmemmove (wchar_t *, const wchar_t *, size_t);
diff --git a/src/include/string.h b/src/include/string.h
index 2133b5c1..f536c26b 100644
--- a/src/include/string.h
+++ b/src/include/string.h
@@ -8,4 +8,10 @@ hidden char *__stpcpy(char *, const char *);
 hidden char *__stpncpy(char *, const char *, size_t);
 hidden char *__strchrnul(const char *, int);
 
+#undef memchr
+#undef strchr
+#undef strrchr
+#undef strpbrk
+#undef strstr
+
 #endif
diff --git a/src/include/wchar.h b/src/include/wchar.h
index 79f5d0e7..dcd1cce1 100644
--- a/src/include/wchar.h
+++ b/src/include/wchar.h
@@ -5,5 +5,11 @@
 
 #include "../../include/wchar.h"
 
+#undef wmemchr
+#undef wcschr
+#undef wcsrchr
+#undef wcspbrk
+#undef wcsstr
+
 #endif
 
diff --git a/src/string/memchr.c b/src/string/memchr.c
index 65f0d789..f11c0573 100644
--- a/src/string/memchr.c
+++ b/src/string/memchr.c
@@ -8,7 +8,7 @@
 #define HIGHS (ONES * (UCHAR_MAX/2+1))
 #define HASZERO(x) ((x)-ONES & ~(x) & HIGHS)
 
-void *memchr(const void *src, int c, size_t n)
+void *(memchr)(const void *src, int c, size_t n)
 {
 	const unsigned char *s = src;
 	c = (unsigned char)c;
diff --git a/src/string/strchr.c b/src/string/strchr.c
index 3cbc828b..3a86beeb 100644
--- a/src/string/strchr.c
+++ b/src/string/strchr.c
@@ -1,6 +1,6 @@
 #include <string.h>
 
-char *strchr(const char *s, int c)
+char *(strchr)(const char *s, int c)
 {
 	char *r = __strchrnul(s, c);
 	return *(unsigned char *)r == (unsigned char)c ? r : 0;
diff --git a/src/string/strpbrk.c b/src/string/strpbrk.c
index 55947c64..0941fc51 100644
--- a/src/string/strpbrk.c
+++ b/src/string/strpbrk.c
@@ -1,6 +1,6 @@
 #include <string.h>
 
-char *strpbrk(const char *s, const char *b)
+char *(strpbrk)(const char *s, const char *b)
 {
 	s += strcspn(s, b);
 	return *s ? (char *)s : 0;
diff --git a/src/string/strrchr.c b/src/string/strrchr.c
index 98ad1b04..908fd8d4 100644
--- a/src/string/strrchr.c
+++ b/src/string/strrchr.c
@@ -1,6 +1,6 @@
 #include <string.h>
 
-char *strrchr(const char *s, int c)
+char *(strrchr)(const char *s, int c)
 {
 	return __memrchr(s, c, strlen(s) + 1);
 }
diff --git a/src/string/strstr.c b/src/string/strstr.c
index 96657bc2..5c622a82 100644
--- a/src/string/strstr.c
+++ b/src/string/strstr.c
@@ -135,7 +135,7 @@ static char *twoway_strstr(const unsigned char *h, const unsigned char *n)
 	}
 }
 
-char *strstr(const char *h, const char *n)
+char *(strstr)(const char *h, const char *n)
 {
 	/* Return immediately on empty needle */
 	if (!n[0]) return (char *)h;
diff --git a/src/string/wcschr.c b/src/string/wcschr.c
index 8dfc2f31..2bf7a111 100644
--- a/src/string/wcschr.c
+++ b/src/string/wcschr.c
@@ -1,6 +1,6 @@
 #include <wchar.h>
 
-wchar_t *wcschr(const wchar_t *s, wchar_t c)
+wchar_t *(wcschr)(const wchar_t *s, wchar_t c)
 {
 	if (!c) return (wchar_t *)s + wcslen(s);
 	for (; *s && *s != c; s++);
diff --git a/src/string/wcspbrk.c b/src/string/wcspbrk.c
index 0c72c197..eb76b5ff 100644
--- a/src/string/wcspbrk.c
+++ b/src/string/wcspbrk.c
@@ -1,6 +1,6 @@
 #include <wchar.h>
 
-wchar_t *wcspbrk(const wchar_t *s, const wchar_t *b)
+wchar_t *(wcspbrk)(const wchar_t *s, const wchar_t *b)
 {
 	s += wcscspn(s, b);
 	return *s ? (wchar_t *)s : NULL;
diff --git a/src/string/wcsrchr.c b/src/string/wcsrchr.c
index 8961b9e2..889303f3 100644
--- a/src/string/wcsrchr.c
+++ b/src/string/wcsrchr.c
@@ -1,6 +1,6 @@
 #include <wchar.h>
 
-wchar_t *wcsrchr(const wchar_t *s, wchar_t c)
+wchar_t *(wcsrchr)(const wchar_t *s, wchar_t c)
 {
 	const wchar_t *p;
 	for (p=s+wcslen(s); p>=s && *p!=c; p--);
diff --git a/src/string/wcsstr.c b/src/string/wcsstr.c
index 4caaef3c..8f27dbea 100644
--- a/src/string/wcsstr.c
+++ b/src/string/wcsstr.c
@@ -90,7 +90,7 @@ static wchar_t *twoway_wcsstr(const wchar_t *h, const wchar_t *n)
 	}
 }
 
-wchar_t *wcsstr(const wchar_t *restrict h, const wchar_t *restrict n)
+wchar_t *(wcsstr)(const wchar_t *restrict h, const wchar_t *restrict n)
 {
 	/* Return immediately on empty needle or haystack */
 	if (!n[0]) return (wchar_t *)h;
diff --git a/src/string/wmemchr.c b/src/string/wmemchr.c
index 2bc2c270..3d761488 100644
--- a/src/string/wmemchr.c
+++ b/src/string/wmemchr.c
@@ -1,6 +1,6 @@
 #include <wchar.h>
 
-wchar_t *wmemchr(const wchar_t *s, wchar_t c, size_t n)
+wchar_t *(wmemchr)(const wchar_t *s, wchar_t c, size_t n)
 {
 	for (; n && *s != c; n--, s++);
 	return n ? (wchar_t *)s : 0;
-- 
2.34.1


^ permalink raw reply	[flat|nested] 3+ messages in thread

* [musl] [C23 const 2/2] C23: change string.h and wchar.h interfaces to macros that respects the const contract
  2023-05-25 14:44 [musl] [C23 const 0/2] some interfaces become type-generic Jens Gustedt
@ 2023-05-25 14:45 ` Jens Gustedt
  0 siblings, 0 replies; 3+ messages in thread
From: Jens Gustedt @ 2023-05-25 14:45 UTC (permalink / raw)
  To: musl

This adds a macro interfaces to those string functions that search for
a string position. This has an additional cast of the return value to
`void const*` for the case that the argument to the call was also
const-qualified. Nothing changes for the correspondin function itself,
only the identifier has to be protected with (), such that the macro
does not expand for the function declaration or definition.
---
 include/string.h     | 54 ++++++++++++++++++++++++++++++++++++++-----
 include/wchar.h      | 55 +++++++++++++++++++++++++++++++++++++++-----
 src/include/string.h |  6 +++++
 src/include/wchar.h  |  6 +++++
 src/string/memchr.c  |  2 +-
 src/string/strchr.c  |  2 +-
 src/string/strpbrk.c |  2 +-
 src/string/strrchr.c |  2 +-
 src/string/strstr.c  |  2 +-
 src/string/wcschr.c  |  2 +-
 src/string/wcspbrk.c |  2 +-
 src/string/wcsrchr.c |  2 +-
 src/string/wcsstr.c  |  2 +-
 src/string/wmemchr.c |  2 +-
 14 files changed, 119 insertions(+), 22 deletions(-)

diff --git a/include/string.h b/include/string.h
index 7df7a402..05019c03 100644
--- a/include/string.h
+++ b/include/string.h
@@ -28,7 +28,54 @@ void *memcpy (void *__restrict, const void *__restrict, size_t);
 void *memmove (void *, const void *, size_t);
 void *memset (void *, int, size_t);
 int memcmp (const void *, const void *, size_t);
-void *memchr (const void *, int, size_t);
+
+void *(memchr) (const void *, int, size_t);
+char *(strchr) (const char *, int);
+char *(strrchr) (const char *, int);
+char *(strpbrk) (const char *, const char *);
+char *(strstr) (const char *, const char *);
+#if __STDC_VERSION__ > 201112L
+# define memchr(S, C, N)                                                \
+	_Generic(                                                       \
+		/* ensure conversion to a void pointer */               \
+		1 ? (S) : (void*)1,                                     \
+		void const*: (void const*)memchr((void const*)(S), (C), (N)), \
+		/* volatile qualification of *S is an error for this call */ \
+		default:     memchr((S), (C), (N))                      \
+)
+# define strchr(S, C)                                                   \
+	_Generic(                                                       \
+		/* ensure conversion to a void pointer */               \
+		1 ? (S) : (void*)1,                                     \
+		void const*: (char const*)strchr((char const*){ (S) }, (C)), \
+		/* volatile qualification of *S is an error for this call */ \
+		default:     strchr((S), (C))                           \
+)
+# define strrchr(S, C)                                                   \
+	_Generic(                                                       \
+		/* ensure conversion to a void pointer */               \
+		1 ? (S) : (void*)1,                                     \
+		void const*: (char const*)strrchr((char const*){ (S) }, (C)), \
+		/* volatile qualification of *S is an error for this call */ \
+		default:     strrchr((S), (C))                           \
+)
+# define strpbrk(S, A)                                                  \
+	_Generic(                                                       \
+		/* ensure conversion to a void pointer */               \
+		1 ? (S) : (void*)1,                                     \
+		void const*: (char const*)strpbrk((char const*){ (S) }, (A)), \
+		/* volatile qualification of *S is an error for this call */ \
+		default:     strpbrk((S), (A))                          \
+)
+# define strstr(H, N)                                                   \
+	_Generic(                                                       \
+		/* ensure conversion to a void pointer */               \
+		1 ? (H) : (void*)1,                                     \
+		void const*: (char const*)strstr((char const*){ (H) }, (N)), \
+		/* volatile qualification of *S is an error for this call */ \
+		default:     strstr((H), (N))                           \
+)
+#endif
 
 char *strcpy (char *__restrict, const char *__restrict);
 char *strncpy (char *__restrict, const char *__restrict, size_t);
@@ -42,13 +89,8 @@ int strncmp (const char *, const char *, size_t);
 int strcoll (const char *, const char *);
 size_t strxfrm (char *__restrict, const char *__restrict, size_t);
 
-char *strchr (const char *, int);
-char *strrchr (const char *, int);
-
 size_t strcspn (const char *, const char *);
 size_t strspn (const char *, const char *);
-char *strpbrk (const char *, const char *);
-char *strstr (const char *, const char *);
 char *strtok (char *__restrict, const char *__restrict);
 
 size_t strlen (const char *);
diff --git a/include/wchar.h b/include/wchar.h
index ed5d774d..3816a7cd 100644
--- a/include/wchar.h
+++ b/include/wchar.h
@@ -61,21 +61,64 @@ int wcsncmp (const wchar_t *, const wchar_t *, size_t);
 int wcscoll(const wchar_t *, const wchar_t *);
 size_t wcsxfrm (wchar_t *__restrict, const wchar_t *__restrict, size_t);
 
-wchar_t *wcschr (const wchar_t *, wchar_t);
-wchar_t *wcsrchr (const wchar_t *, wchar_t);
-
 size_t wcscspn (const wchar_t *, const wchar_t *);
 size_t wcsspn (const wchar_t *, const wchar_t *);
-wchar_t *wcspbrk (const wchar_t *, const wchar_t *);
 
 wchar_t *wcstok (wchar_t *__restrict, const wchar_t *__restrict, wchar_t **__restrict);
 
 size_t wcslen (const wchar_t *);
 
-wchar_t *wcsstr (const wchar_t *__restrict, const wchar_t *__restrict);
 wchar_t *wcswcs (const wchar_t *, const wchar_t *);
 
-wchar_t *wmemchr (const wchar_t *, wchar_t, size_t);
+wchar_t *(wmemchr) (const wchar_t *, wchar_t, size_t);
+wchar_t *(wcschr) (const wchar_t *, wchar_t);
+wchar_t *(wcsrchr) (const wchar_t *, wchar_t);
+wchar_t *(wcspbrk) (const wchar_t *, const wchar_t *);
+wchar_t *(wcsstr) (const wchar_t *__restrict, const wchar_t *__restrict);
+#if __STDC_VERSION__ > 201112L
+# define wmemchr(S, C, N)                                               \
+	_Generic(                                                       \
+		/* ensure conversion to a void pointer */               \
+		1 ? (S) : (void*)1,                                     \
+		void const*: (wchar_t const*)wmemchr((wchar_t const*){ (S) }, (C), (N)), \
+		/* volatile qualification of *S is an error for this call */ \
+		default:     wmemchr((S), (C), (N))                     \
+)
+# define wcschr(S, C)                                                   \
+	_Generic(                                                       \
+		/* ensure conversion to a void pointer */               \
+		1 ? (S) : (void*)1,                                     \
+		void const*: (wchar_t const*)wcschr((wchar_t const*){ (S) }, (C)), \
+		/* volatile qualification of *S is an error for this call */ \
+		default:     wcschr((S), (C))                           \
+)
+# define wcsrchr(S, C)                                                  \
+	_Generic(                                                       \
+		/* ensure conversion to a void pointer */               \
+		1 ? (S) : (void*)1,                                     \
+		void const*: (wchar_t const*)wcsrchr((wchar_t const*){ (S) }, (C)), \
+		/* volatile qualification of *S is an error for this call */ \
+		default:     wcsrchr((S), (C))                          \
+)
+# define wcspbrk(S, A)                                                  \
+	_Generic(                                                       \
+		/* ensure conversion to a void pointer */               \
+		1 ? (S) : (void*)1,                                     \
+		void const*: (wchar_t const*)wcspbrk((wchar_t const*){ (S) }, (A)), \
+		/* volatile qualification of *S is an error for this call */ \
+		default:     wcspbrk((S), (A))                          \
+)
+# define wcsstr(H, N)                                                   \
+	_Generic(                                                       \
+		/* ensure conversion to a void pointer */               \
+		1 ? (H) : (void*)1,                                     \
+		void const*: (wchar_t const*)wcsstr((wchar_t const*){ (H) }, (N)), \
+		/* volatile qualification of *S is an error for this call */ \
+		default:     wcsstr((H), (N))                           \
+)
+#endif
+
+
 int wmemcmp (const wchar_t *, const wchar_t *, size_t);
 wchar_t *wmemcpy (wchar_t *__restrict, const wchar_t *__restrict, size_t);
 wchar_t *wmemmove (wchar_t *, const wchar_t *, size_t);
diff --git a/src/include/string.h b/src/include/string.h
index 2133b5c1..f536c26b 100644
--- a/src/include/string.h
+++ b/src/include/string.h
@@ -8,4 +8,10 @@ hidden char *__stpcpy(char *, const char *);
 hidden char *__stpncpy(char *, const char *, size_t);
 hidden char *__strchrnul(const char *, int);
 
+#undef memchr
+#undef strchr
+#undef strrchr
+#undef strpbrk
+#undef strstr
+
 #endif
diff --git a/src/include/wchar.h b/src/include/wchar.h
index 79f5d0e7..dcd1cce1 100644
--- a/src/include/wchar.h
+++ b/src/include/wchar.h
@@ -5,5 +5,11 @@
 
 #include "../../include/wchar.h"
 
+#undef wmemchr
+#undef wcschr
+#undef wcsrchr
+#undef wcspbrk
+#undef wcsstr
+
 #endif
 
diff --git a/src/string/memchr.c b/src/string/memchr.c
index 65f0d789..f11c0573 100644
--- a/src/string/memchr.c
+++ b/src/string/memchr.c
@@ -8,7 +8,7 @@
 #define HIGHS (ONES * (UCHAR_MAX/2+1))
 #define HASZERO(x) ((x)-ONES & ~(x) & HIGHS)
 
-void *memchr(const void *src, int c, size_t n)
+void *(memchr)(const void *src, int c, size_t n)
 {
 	const unsigned char *s = src;
 	c = (unsigned char)c;
diff --git a/src/string/strchr.c b/src/string/strchr.c
index 3cbc828b..3a86beeb 100644
--- a/src/string/strchr.c
+++ b/src/string/strchr.c
@@ -1,6 +1,6 @@
 #include <string.h>
 
-char *strchr(const char *s, int c)
+char *(strchr)(const char *s, int c)
 {
 	char *r = __strchrnul(s, c);
 	return *(unsigned char *)r == (unsigned char)c ? r : 0;
diff --git a/src/string/strpbrk.c b/src/string/strpbrk.c
index 55947c64..0941fc51 100644
--- a/src/string/strpbrk.c
+++ b/src/string/strpbrk.c
@@ -1,6 +1,6 @@
 #include <string.h>
 
-char *strpbrk(const char *s, const char *b)
+char *(strpbrk)(const char *s, const char *b)
 {
 	s += strcspn(s, b);
 	return *s ? (char *)s : 0;
diff --git a/src/string/strrchr.c b/src/string/strrchr.c
index 98ad1b04..908fd8d4 100644
--- a/src/string/strrchr.c
+++ b/src/string/strrchr.c
@@ -1,6 +1,6 @@
 #include <string.h>
 
-char *strrchr(const char *s, int c)
+char *(strrchr)(const char *s, int c)
 {
 	return __memrchr(s, c, strlen(s) + 1);
 }
diff --git a/src/string/strstr.c b/src/string/strstr.c
index 96657bc2..5c622a82 100644
--- a/src/string/strstr.c
+++ b/src/string/strstr.c
@@ -135,7 +135,7 @@ static char *twoway_strstr(const unsigned char *h, const unsigned char *n)
 	}
 }
 
-char *strstr(const char *h, const char *n)
+char *(strstr)(const char *h, const char *n)
 {
 	/* Return immediately on empty needle */
 	if (!n[0]) return (char *)h;
diff --git a/src/string/wcschr.c b/src/string/wcschr.c
index 8dfc2f31..2bf7a111 100644
--- a/src/string/wcschr.c
+++ b/src/string/wcschr.c
@@ -1,6 +1,6 @@
 #include <wchar.h>
 
-wchar_t *wcschr(const wchar_t *s, wchar_t c)
+wchar_t *(wcschr)(const wchar_t *s, wchar_t c)
 {
 	if (!c) return (wchar_t *)s + wcslen(s);
 	for (; *s && *s != c; s++);
diff --git a/src/string/wcspbrk.c b/src/string/wcspbrk.c
index 0c72c197..eb76b5ff 100644
--- a/src/string/wcspbrk.c
+++ b/src/string/wcspbrk.c
@@ -1,6 +1,6 @@
 #include <wchar.h>
 
-wchar_t *wcspbrk(const wchar_t *s, const wchar_t *b)
+wchar_t *(wcspbrk)(const wchar_t *s, const wchar_t *b)
 {
 	s += wcscspn(s, b);
 	return *s ? (wchar_t *)s : NULL;
diff --git a/src/string/wcsrchr.c b/src/string/wcsrchr.c
index 8961b9e2..889303f3 100644
--- a/src/string/wcsrchr.c
+++ b/src/string/wcsrchr.c
@@ -1,6 +1,6 @@
 #include <wchar.h>
 
-wchar_t *wcsrchr(const wchar_t *s, wchar_t c)
+wchar_t *(wcsrchr)(const wchar_t *s, wchar_t c)
 {
 	const wchar_t *p;
 	for (p=s+wcslen(s); p>=s && *p!=c; p--);
diff --git a/src/string/wcsstr.c b/src/string/wcsstr.c
index 4caaef3c..8f27dbea 100644
--- a/src/string/wcsstr.c
+++ b/src/string/wcsstr.c
@@ -90,7 +90,7 @@ static wchar_t *twoway_wcsstr(const wchar_t *h, const wchar_t *n)
 	}
 }
 
-wchar_t *wcsstr(const wchar_t *restrict h, const wchar_t *restrict n)
+wchar_t *(wcsstr)(const wchar_t *restrict h, const wchar_t *restrict n)
 {
 	/* Return immediately on empty needle or haystack */
 	if (!n[0]) return (wchar_t *)h;
diff --git a/src/string/wmemchr.c b/src/string/wmemchr.c
index 2bc2c270..3d761488 100644
--- a/src/string/wmemchr.c
+++ b/src/string/wmemchr.c
@@ -1,6 +1,6 @@
 #include <wchar.h>
 
-wchar_t *wmemchr(const wchar_t *s, wchar_t c, size_t n)
+wchar_t *(wmemchr)(const wchar_t *s, wchar_t c, size_t n)
 {
 	for (; n && *s != c; n--, s++);
 	return n ? (wchar_t *)s : 0;
-- 
2.34.1


^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2023-05-31 14:01 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <cover.1685541439.git.Jens.Gustedt@inria.fr>
2023-05-31 14:00 ` [musl] [C23 const 1/2] C23: change bsearch to a macro that respects the const contract Jens Gustedt
2023-05-31 14:00 ` [musl] [C23 const 2/2] C23: change string.h and wchar.h interfaces to macros " Jens Gustedt
2023-05-25 14:44 [musl] [C23 const 0/2] some interfaces become type-generic Jens Gustedt
2023-05-25 14:45 ` [musl] [C23 const 2/2] C23: change string.h and wchar.h interfaces to macros that respects the const contract Jens Gustedt

Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/musl/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).