From 1e29a7e66b28777692a27e9b9828188147842ec0 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Tue, 22 Jun 2021 22:43:12 +0200 Subject: std-aux: rework NM_STATIC_ASSERT_EXPR() macro Replace NM_STATIC_ASSERT_EXPR() by NM_STATIC_ASSERT_EXPR_1() and NM_STATIC_ASSERT_EXPR_VOID(). NM_STATIC_ASSERT_EXPR_VOID() can be used as an expression that returns void (that is, a simple statement). On the other hand, NM_STATIC_ASSERT_EXPR_1() itself retuns a compile time constant of int value 1. The latter is useful, because we can use the 1 to combine static assertions in expressions that are themself compile time constants, like #define STATIC_CHECK_AND_GET(cond, value) \ (NM_STATIC_ASSERT_EXPR_1(cond) ? (value) : (value)) This is itself a compile time constant if value is a compile time constant. Also, it does the compile time check that "cond" is true. --- src/libnm-glib-aux/tests/test-shared-general.c | 26 ++++++++++++++++++++++++++ src/libnm-std-aux/nm-std-aux.h | 9 ++++----- 2 files changed, 30 insertions(+), 5 deletions(-) diff --git a/src/libnm-glib-aux/tests/test-shared-general.c b/src/libnm-glib-aux/tests/test-shared-general.c index 6c7ab4882f..593b8c42a1 100644 --- a/src/libnm-glib-aux/tests/test-shared-general.c +++ b/src/libnm-glib-aux/tests/test-shared-general.c @@ -30,6 +30,31 @@ G_STATIC_ASSERT(4 == _nm_alignof(NMIPAddr)); /*****************************************************************************/ +static void +test_nm_static_assert(void) +{ + int v1[NM_STATIC_ASSERT_EXPR_1(1)]; + typeof(NM_STATIC_ASSERT_EXPR_1(1)) v_int; + int * p_int; + + G_STATIC_ASSERT(sizeof(v1) == sizeof(int)); + G_STATIC_ASSERT(NM_STATIC_ASSERT_EXPR_1(1) == 1); + G_STATIC_ASSERT(NM_STATIC_ASSERT_EXPR_1(NM_STATIC_ASSERT_EXPR_1(1)) == 1); + G_STATIC_ASSERT(NM_STATIC_ASSERT_EXPR_1(NM_STATIC_ASSERT_EXPR_1(NM_STATIC_ASSERT_EXPR_1(1))) + == 1); + + g_assert(NM_STATIC_ASSERT_EXPR_1(2) == 1); + + p_int = &v_int; + g_assert(&v_int == p_int); + + (void) NM_STATIC_ASSERT_EXPR_1(2 > 1); + + NM_STATIC_ASSERT_EXPR_VOID(2 > 1); +} + +/*****************************************************************************/ + static void test_gpid(void) { @@ -1352,6 +1377,7 @@ main(int argc, char **argv) { nmtst_init(&argc, &argv, TRUE); + g_test_add_func("/general/test_nm_static_assert", test_nm_static_assert); g_test_add_func("/general/test_gpid", test_gpid); g_test_add_func("/general/test_monotonic_timestamp", test_monotonic_timestamp); g_test_add_func("/general/test_nmhash", test_nmhash); diff --git a/src/libnm-std-aux/nm-std-aux.h b/src/libnm-std-aux/nm-std-aux.h index 1e341157fc..49ec8aab0c 100644 --- a/src/libnm-std-aux/nm-std-aux.h +++ b/src/libnm-std-aux/nm-std-aux.h @@ -182,11 +182,10 @@ typedef uint64_t _nm_bitwise nm_be64_t; }) #define NM_STATIC_ASSERT(cond) static_assert(cond, "") -#define NM_STATIC_ASSERT_EXPR(cond) \ - ({ \ - NM_STATIC_ASSERT(cond); \ - 1; \ - }) +#define NM_STATIC_ASSERT_EXPR_1(cond) \ + (sizeof(struct { char __static_assert_expr_1[(cond) ? 1 : -1]; }) == 1) +#define NM_STATIC_ASSERT_EXPR_VOID(cond) \ + ((void) (sizeof(struct { char __static_assert_expr_void[(cond) ? 1 : -1]; }) == 1)) /*****************************************************************************/ -- cgit v1.2.3 From 895b7dd95a3e083a984455c4c2059c867f0abd60 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Tue, 22 Jun 2021 22:50:13 +0200 Subject: glib-aux: rework NM_HASH_COMBINE_BOOLS() macro to avoid expression statement clang 3.4.2-9.el7 dislikes expressions in the form int v; struct { typeof(({ v; })) _field; } x; error: statement expression not allowed at file scope typeof( ({ v; }) ) _field; ^ That is, if the argument to typeof() is an expression statement. But this is what nm_hash_update_val(&h, ..., NM_HASH_COMBINE_BOOLS(...)) expands to. Rework NM_HASH_COMBINE_BOOLS() to avoid the expression statement. We still have the static assertion for the size of the return type. We no longer have the _nm_hash_combine_bools_type typedef. It really wasn't needed, and the current variant is always safe without it. Fixes: 23adeed24463 ('glib-aux: use NM_VA_ARGS_FOREACH() to implement NM_HASH_COMBINE_BOOLS()') --- src/libnm-core-impl/tests/test-general.c | 2 ++ src/libnm-glib-aux/nm-hash-utils.h | 18 ++++++------------ 2 files changed, 8 insertions(+), 12 deletions(-) diff --git a/src/libnm-core-impl/tests/test-general.c b/src/libnm-core-impl/tests/test-general.c index 51411b6feb..172cf15224 100644 --- a/src/libnm-core-impl/tests/test-general.c +++ b/src/libnm-core-impl/tests/test-general.c @@ -508,6 +508,8 @@ test_nm_hash(void) g_assert(((typeof(x)) -1) > 0); } #endif + + NM_STATIC_ASSERT_EXPR_VOID(NM_HASH_COMBINE_BOOLS(int, 1, 0, 1) == 5); } /*****************************************************************************/ diff --git a/src/libnm-glib-aux/nm-hash-utils.h b/src/libnm-glib-aux/nm-hash-utils.h index 52e3430503..0a68bde685 100644 --- a/src/libnm-glib-aux/nm-hash-utils.h +++ b/src/libnm-glib-aux/nm-hash-utils.h @@ -122,18 +122,12 @@ nm_hash_update_bool(NMHashState *state, bool val) nm_hash_update(state, &val, sizeof(val)); } -#define _NM_HASH_COMBINE_BOOLS_OP(x, n) \ - ((x) ? ((_nm_hash_combine_bools_type) NM_BIT((n))) : ((_nm_hash_combine_bools_type) 0)) - -#define NM_HASH_COMBINE_BOOLS(type, ...) \ - ({ \ - typedef type _nm_hash_combine_bools_type; \ - \ - G_STATIC_ASSERT(NM_NARG(__VA_ARGS__) <= 8 * sizeof(_nm_hash_combine_bools_type)); \ - \ - (_nm_hash_combine_bools_type)( \ - NM_VA_ARGS_FOREACH(, , |, _NM_HASH_COMBINE_BOOLS_OP, __VA_ARGS__)); \ - }) +#define _NM_HASH_COMBINE_BOOLS_OP(x, n) ((x) ? NM_BIT((n)) : 0u) + +#define NM_HASH_COMBINE_BOOLS(type, ...) \ + ((type) (NM_STATIC_ASSERT_EXPR_1(NM_NARG(__VA_ARGS__) <= 8 * sizeof(type)) \ + ? (NM_VA_ARGS_FOREACH(, , |, _NM_HASH_COMBINE_BOOLS_OP, __VA_ARGS__)) \ + : 0)) #define nm_hash_update_bools(state, ...) \ nm_hash_update_val(state, NM_HASH_COMBINE_BOOLS(guint8, __VA_ARGS__)) -- cgit v1.2.3