git: 48d20fd1cf90 - main - libc: Fix assert() sanitiser for C++ contextual bool conversion

From: Robert Clausecker <fuz_at_FreeBSD.org>
Date: Wed, 10 Jun 2026 17:58:17 UTC
The branch main has been updated by fuz:

URL: https://cgit.FreeBSD.org/src/commit/?id=48d20fd1cf90179e778c6155900cbed2be140273

commit 48d20fd1cf90179e778c6155900cbed2be140273
Author:     Faraz Vahedi <kfv@kfv.io>
AuthorDate: 2026-06-06 11:38:47 +0000
Commit:     Robert Clausecker <fuz@FreeBSD.org>
CommitDate: 2026-06-10 16:14:32 +0000

    libc: Fix assert() sanitiser for C++ contextual bool conversion
    
    Replace the `(bool(*)(bool))` probe in `__assert_sanitize()` with an unevaluated
    conditional expression, so types with `explicit operator bool()` that require a
    contextually converted constant expression of type `bool` are handled correctly.
    
    Ergo, arity check is now performed separately via `__assert_sanitize_arity()`, a
    unary template whose parameter pack must bind to exactly on argument after
    `__VA_ARGS__` is substituted into the call.
    
    Also align NDEBUG with C23 requirements.
    
    Reported by:    dim, aokblast
    Signed-off-by:  Faraz Vahedi <kfv@kfv.io>
    Reviewed by:    aokblast, fuz
    MFC after:      1 week
    Fixes:          867b51452ea78ece0b312a387e63fdbc2a11056a
    Pull Request:   https://github.com/freebsd/freebsd-src/pull/2265
---
 include/assert.h | 38 +++++++++-----------------------------
 1 file changed, 9 insertions(+), 29 deletions(-)

diff --git a/include/assert.h b/include/assert.h
index d4c9627bf3ea..afbf2c1092e0 100644
--- a/include/assert.h
+++ b/include/assert.h
@@ -46,42 +46,22 @@
 #undef __assert_unreachable
 
 #ifdef NDEBUG
-#define assert(e)	((void)0)
-#define _assert(e)	((void)0)
+#define assert(...)	((void)0)
+#define _assert(...)	((void)0)
 #if __BSD_VISIBLE
 #define __assert_unreachable()	__unreachable()
 #endif /* __BSD_VISIBLE */
 #else
 #ifdef __cplusplus
-#if __cplusplus < 202002L
-/*
- * C++ modes prior to C++20 cannot simultaneously satisfy all three
- * desirable properties of the sanitiser:
- *
- *   Approach                       No double-eval  Lambda support  Arity check
- *   -----------------------------  --------------  --------------  -----------
- *   sizeof(cast(expression))       yes             no              yes
- *   static_cast<bool>(expression)  no              yes             no
- *   (void)bool(expression)         no              yes             no
- *
- *   NOTE: C++20 introduced lambdas in unevaluated contexts; see P0315R4.
- *
- * Since no approach satisfies all three below C++20, the least harmful
- * choice is to forgo the check entirely rather than silently break one
- * of the remaining guarantees.
- *
- */
-#define __assert_sanitize(...)	((void)0)
-#else
-#define __assert_sanitize(...)	(void)sizeof(((bool(*)(bool))0)(__VA_ARGS__))
-#endif /* __cplusplus < 202002L */
+#define assert(...)	((void)(bool(__VA_ARGS__) ? ((void)0) :           \
+			    __assert(__func__, __FILE__, __LINE__,        \
+			    #__VA_ARGS__)))
 #else
-#define __assert_sanitize(...)	(void)sizeof(((_Bool(*)(_Bool))0)(__VA_ARGS__))
-#endif /* __cplusplus */
-#define assert(...)	(__assert_sanitize(__VA_ARGS__),       \
-			    (__VA_ARGS__) ? (void)0 :          \
-			    __assert(__func__, __FILE__,       \
+#define assert(...)	((void)sizeof(((_Bool(*)(_Bool))0)(__VA_ARGS__)), \
+			    (__VA_ARGS__) ? (void)0 :                     \
+			    __assert(__func__, __FILE__,                  \
 			    __LINE__, #__VA_ARGS__))
+#endif /* __cplusplus */
 #define _assert(...)	assert(__VA_ARGS__)
 #if __BSD_VISIBLE
 #define __assert_unreachable()	assert(0 && "unreachable segment reached")