diff options
Diffstat (limited to 'include/assert.h')
| -rw-r--r-- | include/assert.h | 47 |
1 files changed, 39 insertions, 8 deletions
diff --git a/include/assert.h b/include/assert.h index a3dbe933e18f..f1dcf2bb180c 100644 --- a/include/assert.h +++ b/include/assert.h @@ -52,17 +52,44 @@ #define __assert_unreachable() __unreachable() #endif /* __BSD_VISIBLE */ #else -#define _assert(e) assert(e) - -#define assert(e) ((e) ? (void)0 : __assert(__func__, __FILE__, \ - __LINE__, #e)) +#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 */ +#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__, \ + __LINE__, #__VA_ARGS__)) +#define _assert(...) assert(__VA_ARGS__) #if __BSD_VISIBLE #define __assert_unreachable() assert(0 && "unreachable segment reached") #endif /* __BSD_VISIBLE */ #endif /* NDEBUG */ -#ifndef _ASSERT_H_ -#define _ASSERT_H_ +#ifndef __STDC_VERSION_ASSERT_H__ +#define __STDC_VERSION_ASSERT_H__ 202311L /* * Static assertions. In principle we could define static_assert for @@ -72,8 +99,12 @@ * C++ template parameters may contain commas, even if not enclosed in * parentheses, causing the _Static_assert macro to be invoked with more * than two parameters. + * + * C23 defines static_assert and its obsolescent alternative spelling, + * _Static_assert, as keywords. */ -#if __ISO_C_VISIBLE >= 2011 && !defined(__cplusplus) +#if __ISO_C_VISIBLE >= 2011 && !defined(__cplusplus) && \ + __STDC_VERSION__ < 202311L #define static_assert _Static_assert #endif @@ -81,4 +112,4 @@ __BEGIN_DECLS void __assert(const char *, const char *, int, const char *) __dead2; __END_DECLS -#endif /* !_ASSERT_H_ */ +#endif /* !__STDC_VERSION_ASSERT_H__ */ |
