]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib: bits - macros to simplify expressions when using -Wstrict-bool
authorPhil Carmody <phil@dovecot.fi>
Fri, 11 May 2018 06:19:21 +0000 (09:19 +0300)
committerAki Tuomi <aki.tuomi@open-xchange.com>
Sun, 20 May 2018 08:51:40 +0000 (08:51 +0000)
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 <phil@dovecot.fi>
src/lib/bits.h
src/lib/test-bits.c

index d3b9a7d907ef091a015807a25b14d416e19f693c..430ae8ec3f1462f5b775a137955bd11acd15159f 100644 (file)
@@ -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;
 
index 72216ef6ce2aa4cf31e38b0bd8112938f9da0cf1..e80a0d5d48c6a80b41900aee80cdf33017376bf8 100644 (file)
@@ -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();
 }