From 455a8429f01ee5f98161bd8710c50ba0bdec61f2 Mon Sep 17 00:00:00 2001 From: Olivier Dion Date: Fri, 18 Aug 2023 16:16:23 -0400 Subject: [PATCH] urcu/compiler: Add urcu_static_assert Static assertion macros copied from LTTng-ust ust-compiler.h for compatibility with compilers that do not support static assertion. Change-Id: I5dfa8ba565041b522a1d5c226c7a9369979a3a02 Signed-off-by: Olivier Dion Signed-off-by: Mathieu Desnoyers --- include/urcu/compiler.h | 32 ++++++++++++++++++++++++++++++++ include/urcu/uatomic.h | 17 +++++++---------- 2 files changed, 39 insertions(+), 10 deletions(-) diff --git a/include/urcu/compiler.h b/include/urcu/compiler.h index 887d9be..197656c 100644 --- a/include/urcu/compiler.h +++ b/include/urcu/compiler.h @@ -193,4 +193,36 @@ volatile T cmm_cast_volatile(T t) }) #endif +/* + * Compile time assertion. + * - predicate: boolean expression to evaluate, + * - msg: string to print to the user on failure when `static_assert()` is + * supported, + * - c_identifier_msg: message to be included in the typedef to emulate a + * static assertion. This parameter must be a valid C identifier as it will + * be used as a typedef name. + */ +#ifdef __cplusplus +#define urcu_static_assert(predicate, msg, c_identifier_msg) \ + static_assert(predicate, msg) +#elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) +#define urcu_static_assert(predicate, msg, c_identifier_msg) \ + _Static_assert(predicate, msg) +#else +/* + * Evaluates the predicate and emit a compilation error on failure. + * + * If the predicate evaluates to true, this macro emits a function + * prototype with an argument type which is an array of size 0. + * + * If the predicate evaluates to false, this macro emits a function + * prototype with an argument type which is an array of negative size + * which is invalid in C and forces a compiler error. The + * c_identifier_msg parameter is used as the argument identifier so it + * is printed to the user when the error is reported. + */ +#define urcu_static_assert(predicate, msg, c_identifier_msg) \ + void urcu_static_assert_proto(char c_identifier_msg[2*!!(predicate)-1]) +#endif + #endif /* _URCU_COMPILER_H */ diff --git a/include/urcu/uatomic.h b/include/urcu/uatomic.h index 5365f1f..aca9a63 100644 --- a/include/urcu/uatomic.h +++ b/include/urcu/uatomic.h @@ -5,9 +5,8 @@ #ifndef _URCU_UATOMIC_H #define _URCU_UATOMIC_H -#include - #include +#include #include enum cmm_memorder { @@ -25,14 +24,12 @@ enum cmm_memorder { /* * Make sure that CMM_SEQ_CST_FENCE is not equivalent to other memory orders. */ -# ifdef static_assert -static_assert(CMM_RELAXED == __ATOMIC_RELAXED, ""); -static_assert(CMM_CONSUME == __ATOMIC_CONSUME, ""); -static_assert(CMM_ACQUIRE == __ATOMIC_ACQUIRE, ""); -static_assert(CMM_RELEASE == __ATOMIC_RELEASE, ""); -static_assert(CMM_ACQ_REL == __ATOMIC_ACQ_REL, ""); -static_assert(CMM_SEQ_CST == __ATOMIC_SEQ_CST, ""); -# endif +urcu_static_assert(CMM_RELAXED == __ATOMIC_RELAXED, "", cmm_relaxed); +urcu_static_assert(CMM_CONSUME == __ATOMIC_CONSUME, "", cmm_consume); +urcu_static_assert(CMM_ACQUIRE == __ATOMIC_ACQUIRE, "", cmm_acquire); +urcu_static_assert(CMM_RELEASE == __ATOMIC_RELEASE, "", cmm_release); +urcu_static_assert(CMM_ACQ_REL == __ATOMIC_ACQ_REL, "", cmm_acq_rel); +urcu_static_assert(CMM_SEQ_CST == __ATOMIC_SEQ_CST, "", cmm_seq_cst); /* * This is not part of the public API. It it used internally to implement the -- 2.34.1