mirror of
https://github.com/freebsd/freebsd-src.git
synced 2026-10-28 11:25:21 +01:00
libc: Implement qualifier-preserving standard library functions
Several standard library functions are specified to return an unqualified pointer while accepting a pointer to a potentially const-qualified object. N3020 addresses this behaviour, discarding qualifiers due to incompatible pointer types, by introducing qualifier-preserving macros for the affected set of standard library functions. Add `__qualsel()` helper to `<sys/cdefs.h>`, implemented using the generic selection, and define qualifier-preserving macros for that set of functions in `<string.h>`, `<wchar.h>`, and `<stdlib.h>`. Macros are gated on `_STDC_VERSION__ >= 202311L && !__cplusplus`, therefore there is no behavioural change for earlier C modes or C++ translation units. The kernel is likewise unaffected, as it does not include userland headers. As function-like macros, they are transparent except at a call site where the address-of operator is applied, the macro is suppressed via `#undef`, or the identifier appears in parenthesised form; all of which cause the underlying function designator to be used instead. Reviewed by: fuz Approved by: fuz (mentor) MFC after: 1 month Pull Request: https://github.com/freebsd/freebsd-src/pull/2288
This commit is contained in:
13 files changed
+187
-33
No files matched your search
@@ -418,4 +418,16 @@ errno_t qsort_s(void *, rsize_t, rsize_t,
|
||||
__END_DECLS
|
||||
__NULLABILITY_PRAGMA_POP
|
||||
|
||||
#if defined(__qualsel) && !defined(__cplusplus) && \
|
||||
defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202311L
|
||||
#define bsearch(key, base, nmemb, size, compar) __qualsel((base), \
|
||||
(const void *)(bsearch)((key), (base), (nmemb), (size), (compar)), \
|
||||
(bsearch)((key), (base), (nmemb), (size), (compar)))
|
||||
#ifdef __BLOCKS__
|
||||
#define bsearch_b(key, base, nmemb, size, compar) __qualsel((base), \
|
||||
(const void *)(bsearch_b)((key), (base), (nmemb), (size), (compar)), \
|
||||
(bsearch_b)((key), (base), (nmemb), (size), (compar)))
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif /* !_STDLIB_H_ */
|
||||
@@ -205,4 +205,32 @@ errno_t memset_s(void *, rsize_t, int, rsize_t);
|
||||
#endif /* __EXT1_VISIBLE */
|
||||
__END_DECLS
|
||||
|
||||
#if defined(__qualsel) && !defined(__cplusplus) && \
|
||||
defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202311L
|
||||
#define memchr(b, c, n) __qualsel((b), \
|
||||
(const void *)(memchr)((b), (c), (n)), (memchr)((b), (c), (n)))
|
||||
#define strchr(s, c) __qualsel((s), \
|
||||
(const char *)(strchr)((s), (c)), (strchr)((s), (c)))
|
||||
#define strpbrk(s, charset) __qualsel((s), \
|
||||
(const char *)(strpbrk)((s), (charset)), (strpbrk)((s), (charset)))
|
||||
#define strrchr(s, c) __qualsel((s), \
|
||||
(const char *)(strrchr)((s), (c)), (strrchr)((s), (c)))
|
||||
#define strstr(s, find) __qualsel((s), \
|
||||
(const char *)(strstr)((s), (find)), (strstr)((s), (find)))
|
||||
#if __BSD_VISIBLE
|
||||
#define memmem(b, blen, pat, plen) __qualsel((b), \
|
||||
(const void *)(memmem)((b), (blen), (pat), (plen)), \
|
||||
(memmem)((b), (blen), (pat), (plen)))
|
||||
#define memrchr(b, c, n) __qualsel((b), \
|
||||
(const void *)(memrchr)((b), (c), (n)), (memrchr)((b), (c), (n)))
|
||||
#define strcasestr(s, find) __qualsel((s), \
|
||||
(const char *)(strcasestr)((s), (find)), (strcasestr)((s), (find)))
|
||||
#define strchrnul(s, c) __qualsel((s), \
|
||||
(const char *)(strchrnul)((s), (c)), (strchrnul)((s), (c)))
|
||||
#define strnstr(s, find, slen) __qualsel((s), \
|
||||
(const char *)(strnstr)((s), (find), (slen)), \
|
||||
(strnstr)((s), (find), (slen)))
|
||||
#endif /* __BSD_VISIBLE */
|
||||
#endif
|
||||
|
||||
#endif /* _STRING_H_ */
|
||||
@@ -246,4 +246,18 @@ size_t wcslcpy(wchar_t *, const wchar_t *, size_t);
|
||||
#endif
|
||||
__END_DECLS
|
||||
|
||||
#if defined(__qualsel) && !defined(__cplusplus) && \
|
||||
defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202311L
|
||||
#define wcschr(s, c) __qualsel((s), \
|
||||
(const wchar_t *)(wcschr)((s), (c)), (wcschr)((s), (c)))
|
||||
#define wcspbrk(s, set) __qualsel((s), \
|
||||
(const wchar_t *)(wcspbrk)((s), (set)), (wcspbrk)((s), (set)))
|
||||
#define wcsrchr(s, c) __qualsel((s), \
|
||||
(const wchar_t *)(wcsrchr)((s), (c)), (wcsrchr)((s), (c)))
|
||||
#define wcsstr(s, find) __qualsel((s), \
|
||||
(const wchar_t *)(wcsstr)((s), (find)), (wcsstr)((s), (find)))
|
||||
#define wmemchr(s, c, n) __qualsel((s), \
|
||||
(const wchar_t *)(wmemchr)((s), (c), (n)), (wmemchr)((s), (c), (n)))
|
||||
#endif
|
||||
|
||||
#endif /* !_WCHAR_H_ */
|
||||
@@ -29,7 +29,7 @@
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.Dd July 17, 2019
|
||||
.Dd June 21, 2026
|
||||
.Dt BSEARCH 3
|
||||
.Os
|
||||
.Sh NAME
|
||||
@@ -153,4 +153,5 @@ main(void)
|
||||
The
|
||||
.Fn bsearch
|
||||
function conforms to
|
||||
.St -isoC .
|
||||
.St -isoC-2023 ,
|
||||
where it is specified as a qualifier-preserving function.
|
||||
@@ -27,7 +27,7 @@
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.Dd December 5, 2023
|
||||
.Dd June 21, 2026
|
||||
.Dt BSTRING 3
|
||||
.Os
|
||||
.Sh NAME
|
||||
@@ -88,7 +88,6 @@ See the specific manual pages for more information.
|
||||
.Xr memset 3
|
||||
.Sh STANDARDS
|
||||
The functions
|
||||
.Fn memchr ,
|
||||
.Fn memcmp ,
|
||||
.Fn memcpy ,
|
||||
.Fn memmove ,
|
||||
@@ -96,6 +95,12 @@ and
|
||||
.Fn memset
|
||||
conform to
|
||||
.St -isoC .
|
||||
.Pp
|
||||
The
|
||||
.Fn memchr
|
||||
function conforms to
|
||||
.St -isoC-2023 ,
|
||||
where it is specified as a qualifier-preserving function.
|
||||
.Sh HISTORY
|
||||
The functions
|
||||
.Fn bzero
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.Dd April 9, 2008
|
||||
.Dd June 21, 2026
|
||||
.Dt MEMCHR 3
|
||||
.Os
|
||||
.Sh NAME
|
||||
@@ -92,13 +92,18 @@ bytes.
|
||||
.Sh STANDARDS
|
||||
The
|
||||
.Fn memchr
|
||||
function
|
||||
conforms to
|
||||
.St -isoC .
|
||||
function conforms to
|
||||
.St -isoC-2023 ,
|
||||
where it is specified as a qualifier-preserving function.
|
||||
.Pp
|
||||
The
|
||||
.Fn memrchr
|
||||
function is a GNU extension and conforms to no standard.
|
||||
Like the qualifier-preserving functions in
|
||||
.St -isoC-2023 ,
|
||||
.Fx implements
|
||||
.Fn memrchr
|
||||
as qualifier-preserving as well.
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Fn memrchr
|
||||
|
||||
@@ -71,6 +71,11 @@ is returned.
|
||||
.Fn memmem
|
||||
conforms to
|
||||
.St -p1003.1-2024 .
|
||||
Like the qualifier-preserving functions in
|
||||
.St -isoC-2023 ,
|
||||
.Fx implements
|
||||
.Fn memmem
|
||||
as qualifier-preserving as well.
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Fn memmem
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.Dd February 13, 2013
|
||||
.Dd June 21, 2026
|
||||
.Dt STRCHR 3
|
||||
.Os
|
||||
.Sh NAME
|
||||
@@ -109,12 +109,20 @@ The functions
|
||||
and
|
||||
.Fn strrchr
|
||||
conform to
|
||||
.St -isoC .
|
||||
.St -isoC-2023 ,
|
||||
where they are specified as qualifier-preserving functions.
|
||||
.Pp
|
||||
The function
|
||||
.Fn strchrnul
|
||||
is a
|
||||
.Tn GNU
|
||||
extension.
|
||||
Like the qualifier-preserving functions in
|
||||
.St -isoC-2023 ,
|
||||
.Fx
|
||||
implements
|
||||
.Fn strchrnul
|
||||
as qualifier-preserving as well.
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Fn strchrnul
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.Dd September 2, 2023
|
||||
.Dd June 21, 2026
|
||||
.Dt STRING 3
|
||||
.Os
|
||||
.Sh NAME
|
||||
@@ -136,20 +136,26 @@ for size limitations.
|
||||
The
|
||||
.Fn strcat ,
|
||||
.Fn strncat ,
|
||||
.Fn strchr ,
|
||||
.Fn strrchr ,
|
||||
.Fn strcmp ,
|
||||
.Fn strncmp ,
|
||||
.Fn strcpy ,
|
||||
.Fn strncpy ,
|
||||
.Fn strerror ,
|
||||
.Fn strlen ,
|
||||
.Fn strpbrk ,
|
||||
.Fn strspn ,
|
||||
.Fn strcspn ,
|
||||
.Fn strstr ,
|
||||
and
|
||||
.Fn strtok
|
||||
functions
|
||||
conform to
|
||||
.St -isoC .
|
||||
.Pp
|
||||
The
|
||||
.Fn strchr ,
|
||||
.Fn strrchr ,
|
||||
.Fn strpbrk ,
|
||||
and
|
||||
.Fn strstr
|
||||
functions conform to
|
||||
.St -isoC-2023 ,
|
||||
where they are specified as qualifier-preserving functions.
|
||||
@@ -29,7 +29,7 @@
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.Dd June 4, 1993
|
||||
.Dd June 21, 2026
|
||||
.Dt STRPBRK 3
|
||||
.Os
|
||||
.Sh NAME
|
||||
@@ -69,6 +69,6 @@ returns NULL.
|
||||
.Sh STANDARDS
|
||||
The
|
||||
.Fn strpbrk
|
||||
function
|
||||
conforms to
|
||||
.St -isoC .
|
||||
function conforms to
|
||||
.St -isoC-2023 ,
|
||||
where it is specified as a qualifier-preserving function.
|
||||
@@ -30,7 +30,7 @@
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.Dd October 11, 2001
|
||||
.Dd June 21, 2026
|
||||
.Dt STRSTR 3
|
||||
.Os
|
||||
.Sh NAME
|
||||
@@ -147,9 +147,22 @@ ptr = strnstr(largestring, smallstring, 4);
|
||||
.Sh STANDARDS
|
||||
The
|
||||
.Fn strstr
|
||||
function
|
||||
conforms to
|
||||
.St -isoC .
|
||||
function conforms to
|
||||
.St -isoC-2023 ,
|
||||
where it is specified as a qualifier-preserving function.
|
||||
.Pp
|
||||
The
|
||||
.Fn strcasestr
|
||||
function is a
|
||||
.Tn GNU
|
||||
extension, and the
|
||||
.Fn strnstr
|
||||
function is a
|
||||
.Bx
|
||||
extension.
|
||||
Like the qualifier-preserving functions in
|
||||
.St -isoC-2023 ,
|
||||
.Fx implements them as qualifier-preserving as well.
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Fn strnstr
|
||||
|
||||
+46
-10
@@ -154,21 +154,57 @@ counterpart, such as
|
||||
.Xr strspn 3 ,
|
||||
.Xr strstr 3
|
||||
.Sh STANDARDS
|
||||
These functions conform to
|
||||
.St -isoC-99 ,
|
||||
with the exception of
|
||||
Functions
|
||||
.Fn wmemcmp ,
|
||||
.Fn wmemcpy ,
|
||||
.Fn wmemmove ,
|
||||
.Fn wmemset ,
|
||||
.Fn wcscat ,
|
||||
.Fn wcscmp ,
|
||||
.Fn wcscpy ,
|
||||
.Fn wcscspn ,
|
||||
.Fn wcslen ,
|
||||
.Fn wcsncat ,
|
||||
.Fn wcsncmp ,
|
||||
.Fn wcsncpy ,
|
||||
and
|
||||
.Fn wcsspn
|
||||
conform to
|
||||
.St -isoC-99 .
|
||||
.Pp
|
||||
Functions
|
||||
.Fn wmemchr ,
|
||||
.Fn wcschr ,
|
||||
.Fn wcspbrk ,
|
||||
.Fn wcsrchr ,
|
||||
and
|
||||
.Fn wcsstr
|
||||
conform to
|
||||
.St -isoC-2023 ,
|
||||
where they are specified as qualifier-preserving functions.
|
||||
.Pp
|
||||
Functions
|
||||
.Fn wcpcpy ,
|
||||
.Fn wcpncpy ,
|
||||
.Fn wcscasecmp ,
|
||||
.Fn wcsdup ,
|
||||
.Fn wcsncasecmp ,
|
||||
and
|
||||
.Fn wcsnlen ,
|
||||
which conform to
|
||||
.St -p1003.1-2008 ;
|
||||
.Fn wcsnlen
|
||||
conform to
|
||||
.St -p1003.1-2008 ,
|
||||
and functions
|
||||
.Fn wcslcat
|
||||
and
|
||||
.Fn wcslcat ,
|
||||
.Fn wcslcpy ,
|
||||
and
|
||||
.Fn wmempcpy ,
|
||||
which are extensions.
|
||||
first introduced by
|
||||
.Ox ,
|
||||
conform to
|
||||
.St -p1003.1-2024 .
|
||||
.Pp
|
||||
Function
|
||||
.Fn wmempcpy
|
||||
is a
|
||||
.Tn GNU
|
||||
extensions.
|
||||
|
||||
@@ -227,6 +227,27 @@
|
||||
__typeof(((void)0, (expr))), t), yes, no)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* __qualsel() is the building block for C23 qualifier-preserving macros
|
||||
* as proposed in N3020: it selects cexpr when the pointer expression p
|
||||
* references a const-qualified object, and expr otherwise.
|
||||
*
|
||||
* The conditional operator's composite-type rule collapses every
|
||||
* pointer-to-const-object type onto the single "const void *"" association,
|
||||
* so callers passing any such pointer are matched even though _Generic()
|
||||
* otherwise compares types exactly.
|
||||
*
|
||||
* The (__uintptr_t) round-trip only suppresses -Wcast-qual on the throwaway
|
||||
* second operand.
|
||||
*/
|
||||
#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L) || \
|
||||
__has_extension(c_generic_selections)
|
||||
#define __qualsel(p, cexpr, expr) \
|
||||
_Generic(1 ? (p) : (void *)(__uintptr_t)(p), \
|
||||
const void *: (cexpr), \
|
||||
default: (expr))
|
||||
#endif
|
||||
|
||||
/*
|
||||
* C99 Static array indices in function parameter declarations. Syntax such as:
|
||||
* void bar(int myArray[static 10]);
|
||||
|
||||
Reference in new issue
Block a user