|
Date: Wed, 31 May 2023 16:00:25 +0200 From: Jens Gustedt <Jens.Gustedt@...ia.fr> To: musl@...ts.openwall.com Subject: [C23 const 1/2] C23: change bsearch to a macro that respects the const contract 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
Powered by blists - more mailing lists
Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.