From 899807f467b1650b4b4bc46d2073f7cc80547b62 Mon Sep 17 00:00:00 2001 From: Phil Carmody Date: Fri, 11 May 2018 09:19:21 +0300 Subject: [PATCH] lib: bits - macros to simplify expressions when using -Wstrict-bool To be strict-bool compliant, your expressions need to be a bit verbose, these might simplify things. There are presently over 400 instances matching HAS_NO_BITS(), and nearly 1300 instances matching HAS_ANY_BITS(), so it's a very common pattern. Signed-off-by: Phil Carmody --- src/lib/bits.h | 11 +++++++++++ src/lib/test-bits.c | 30 ++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+) diff --git a/src/lib/bits.h b/src/lib/bits.h index d3b9a7d907..430ae8ec3f 100644 --- a/src/lib/bits.h +++ b/src/lib/bits.h @@ -6,6 +6,17 @@ #define BIT(n) (1u << (n)) +/* These expressions make it easy to ensure that bit test expressions + are boolean in order to satisfy the in-house -Wstrict-bool. */ +/* ((val & bits) == 0) is very common */ +#define HAS_NO_BITS(val,bits) (((val) & (bits)) == 0) +/* ((val & bits) != 0) is even more common */ +/* Note - illogical behaviour if bits==0, fixing that requires potential + multiple evaluation, but it's a corner case that should never occur. */ +#define HAS_ANY_BITS(val,bits) (((val) & (bits)) != 0) +/* ((val & bits) == bits) is uncommon */ +#define HAS_ALL_BITS(val,bits) ((~(val) & (bits)) == 0) + /* Returns x, such that x is the smallest power of 2 >= num. */ size_t nearest_power(size_t num) ATTR_CONST; diff --git a/src/lib/test-bits.c b/src/lib/test-bits.c index 72216ef6ce..e80a0d5d48 100644 --- a/src/lib/test-bits.c +++ b/src/lib/test-bits.c @@ -190,6 +190,35 @@ static void test_bits_rotr64(void) test_end(); } +static void test_bit_tests(void) +{ + test_begin("HAS_..._BITS() macro tests"); + + test_assert(HAS_NO_BITS(1,0)); + test_assert(HAS_NO_BITS(2,~2)); + test_assert(!HAS_NO_BITS(2,2)); + + /* OUCH - this vacuously true expression fails. However, if you are + dumb enough to use 0 as bits, then it will also fail in the verbose + case that this macro replaces, it's not a regression. */ + /* test_assert(HAS_ANY_BITS(6,0)); */ + test_assert(HAS_ANY_BITS(3,1)); + test_assert(HAS_ANY_BITS(2,3)); + test_assert(!HAS_ANY_BITS(7,~(7|128))); + + test_assert(HAS_ALL_BITS(0,0)); + test_assert(HAS_ALL_BITS(30,14)); + test_assert(!HAS_ALL_BITS(~1,~0)); + + /* Trap double-evaluation */ + unsigned int v=10,b=2; + test_assert(!HAS_NO_BITS(v++, b++) && v==11 && b==3); + test_assert(HAS_ANY_BITS(v++, b++) && v==12 && b==4); + test_assert(HAS_ALL_BITS(v++, b++) && v==13 && b==5); + + test_end(); +} + void test_bits(void) { test_nearest_power(); @@ -202,4 +231,5 @@ void test_bits(void) test_bits_rotl64(); test_bits_rotr64(); test_sum_overflows(); + test_bit_tests(); }