From nobody Tue Sep 22 19:01:32 2026 X-Original-To: dev-commits-src-branches@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4hq8b06ZFhz6svv4 for ; Tue, 22 Sep 2026 19:01:32 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange x25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "YR2" (not verified)) by mx1.freebsd.org (Postfix) with ESMTPS id 4hq8b05tDgz4Rgx for ; Tue, 22 Sep 2026 19:01:32 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1790103692; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=nSgTGXkPdiNs1LuQzWZrqMQzyrrr4EyVO+S/BOwr8kY=; b=W+6aEY3tiPpj2i8vniTDO825ziDg7W/BW+O2bvPTS4iOysy3/k1O4CK1w0Tvpr049sk3gh f1N+jP7YOsRZubR6b6gO1il88aAidyUnO2WbOAmwkj4Dnf2e27Y4qO7CxAkXYZIGtX+I3q 0nWMhKb+6nGGdHwEMLSNZQaSFQVUYMwFy9Klai2CuMmEHQbLmyoYj+oAA260NBXt30oZpU 1bk9u5pWQj410gGeJEjqnrbrbcvvzNnbNqxEWQ3kUEJDrYKtMQ3XixjRjzEHD4JXh1K1D4 44vqys+WxbNb7zUG2EJ0KpcI6zlOxoku6PC8+ZbvyXMf7RUoanV4qLF8/IXGqA== ARC-Seal: i=1; a=rsa-sha256; d=freebsd.org; s=dkim; cv=none; t=1790103692; b=Bke5k/m+Imt+tt7fXyJqjgsdF3IKrpuc68dPdpnCoyQ23Q3ibEfsgs5yB0uq5piDg5yM+d moE8+HFKp/57dlmrc0ugfWuLx3uDLe1l/WM9GTf78qFBKBxiSodadqcGbexwcUDKAqSW7/ dLX+/X4ppqNwarG8MUhxE6PLOZUL1F6ubwm40oVarBBMwh9c5e3F/UlOr9Yez4s2LtQZaC AHFypJgPEUFH8TFz3rlj+EALJNbhU44WpLGcD03rXOQ2MIEXtS1Ssm7Qf1jue5zFpaRWq+ +s0RwZ1pmlhQrHHuEXPvSCSMdEueeygfOc+BGZ+DDvZI+gqwiHO0HYr0QHoUSA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1790103692; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=nSgTGXkPdiNs1LuQzWZrqMQzyrrr4EyVO+S/BOwr8kY=; b=fqx1LQGPIYOaguI6Fh17yN5HxPkO+0FVxlfy5hXkzPfYViGZvTfIE1KPbdImKBHbokHrl4 1xRr6E9MNkQHdVRxhOusCc2Oab8EETsM077tISkWhrLdy49Om1kTDxlZssOj6Yo2D9g4iH h5GI8/uoGI6XuTGwQUwXL+5NKHaylEzTkY/ZeSFIyCARiXTVEcR0m1rNg9EO8vB8B0c7fb iDz2eGqRMilHKLxRMERhGcCPECLtTOaolHyX8A1mox3k4qjcC8qUv9SpvLxES4WswMNOus 8Hz8kiZTX65+cUWnjTsQ8XloUzC7A5JHBdKlkCEycftS0kksvgLKY77YLoY4GA== ARC-Authentication-Results: i=1; mx1.freebsd.org; none Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4hq8b04nDhzJt6 for ; Tue, 22 Sep 2026 19:01:32 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 18c76 by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Tue, 22 Sep 2026 19:01:32 +0000 To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org From: Faraz Vahedi Subject: git: 4bdbd68e6b76 - stable/15 - libc: Implement qualifier-preserving standard library functions List-Id: Commits to the stable branches of the FreeBSD src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-branches List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-branches@freebsd.org Sender: owner-dev-commits-src-branches@FreeBSD.org List-Id: List-Post: List-Help: List-Subscribe: List-Unsubscribe: List-Owner: Precedence: list MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: kfv X-Git-Repository: src X-Git-Refname: refs/heads/stable/15 X-Git-Reftype: branch X-Git-Commit: 4bdbd68e6b76c4621c3e0d6d51fa81530caaa5a0 Auto-Submitted: auto-generated Date: Tue, 22 Sep 2026 19:01:32 +0000 Message-Id: <6ab2d08c.18c76.2dc39e7c@gitrepo.freebsd.org> The branch stable/15 has been updated by kfv: URL: https://cgit.FreeBSD.org/src/commit/?id=4bdbd68e6b76c4621c3e0d6d51fa81530caaa5a0 commit 4bdbd68e6b76c4621c3e0d6d51fa81530caaa5a0 Author: Faraz Vahedi AuthorDate: 2026-06-19 21:50:20 +0000 Commit: Faraz Vahedi CommitDate: 2026-09-22 17:12:01 +0000 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 ``, implemented using the generic selection, and define qualifier-preserving macros for that set of functions in ``, ``, and ``. 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 (cherry picked from commit d08296c7ab0d7bb259bf7b8cdf9ffb819c1929ab) --- include/stdlib.h | 12 ++++++++++ include/string.h | 28 ++++++++++++++++++++++++ include/wchar.h | 14 ++++++++++++ lib/libc/stdlib/bsearch.3 | 5 +++-- lib/libc/string/bstring.3 | 9 ++++++-- lib/libc/string/memchr.3 | 13 +++++++---- lib/libc/string/memmem.3 | 5 +++++ lib/libc/string/strchr.3 | 12 ++++++++-- lib/libc/string/string.3 | 16 +++++++++----- lib/libc/string/strpbrk.3 | 8 +++---- lib/libc/string/strstr.3 | 21 ++++++++++++++---- lib/libc/string/wmemchr.3 | 56 ++++++++++++++++++++++++++++++++++++++--------- sys/sys/cdefs.h | 21 ++++++++++++++++++ 13 files changed, 187 insertions(+), 33 deletions(-) diff --git a/include/stdlib.h b/include/stdlib.h index 7960a70ae9c2..01a56b32116a 100644 --- a/include/stdlib.h +++ b/include/stdlib.h @@ -416,4 +416,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_ */ diff --git a/include/string.h b/include/string.h index e9aa1b55281a..98a0a6396848 100644 --- a/include/string.h +++ b/include/string.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_ */ diff --git a/include/wchar.h b/include/wchar.h index bf07062935d5..1447d083a889 100644 --- a/include/wchar.h +++ b/include/wchar.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_ */ diff --git a/lib/libc/stdlib/bsearch.3 b/lib/libc/stdlib/bsearch.3 index 712be0f98381..68c0cae5154a 100644 --- a/lib/libc/stdlib/bsearch.3 +++ b/lib/libc/stdlib/bsearch.3 @@ -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. diff --git a/lib/libc/string/bstring.3 b/lib/libc/string/bstring.3 index dd89af44fc4a..25168404029b 100644 --- a/lib/libc/string/bstring.3 +++ b/lib/libc/string/bstring.3 @@ -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 diff --git a/lib/libc/string/memchr.3 b/lib/libc/string/memchr.3 index c50e932d3382..da96256e976d 100644 --- a/lib/libc/string/memchr.3 +++ b/lib/libc/string/memchr.3 @@ -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 diff --git a/lib/libc/string/memmem.3 b/lib/libc/string/memmem.3 index e301a0bd1e0f..96dc899844ee 100644 --- a/lib/libc/string/memmem.3 +++ b/lib/libc/string/memmem.3 @@ -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 diff --git a/lib/libc/string/strchr.3 b/lib/libc/string/strchr.3 index 45179a0001fc..a2f5b32c32c9 100644 --- a/lib/libc/string/strchr.3 +++ b/lib/libc/string/strchr.3 @@ -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 diff --git a/lib/libc/string/string.3 b/lib/libc/string/string.3 index 3ffea6ce0369..c91f6317b5db 100644 --- a/lib/libc/string/string.3 +++ b/lib/libc/string/string.3 @@ -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. diff --git a/lib/libc/string/strpbrk.3 b/lib/libc/string/strpbrk.3 index cdccf0da957f..fd63aacfa965 100644 --- a/lib/libc/string/strpbrk.3 +++ b/lib/libc/string/strpbrk.3 @@ -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. diff --git a/lib/libc/string/strstr.3 b/lib/libc/string/strstr.3 index 8957388db535..e04e882eec6a 100644 --- a/lib/libc/string/strstr.3 +++ b/lib/libc/string/strstr.3 @@ -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 diff --git a/lib/libc/string/wmemchr.3 b/lib/libc/string/wmemchr.3 index c1701facb7d5..fddb59a1f49f 100644 --- a/lib/libc/string/wmemchr.3 +++ b/lib/libc/string/wmemchr.3 @@ -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. + diff --git a/sys/sys/cdefs.h b/sys/sys/cdefs.h index d0a34f1bdfc0..22e2888d80af 100644 --- a/sys/sys/cdefs.h +++ b/sys/sys/cdefs.h @@ -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]);