aboutsummaryrefslogtreecommitdiff
path: root/include/assert.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/assert.h')
-rw-r--r--include/assert.h47
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__ */