This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
handy.h: Avoid compiler warnings for withinCOUNT()
authorKarl Williamson <khw@cpan.org>
Thu, 26 Sep 2019 04:23:55 +0000 (22:23 -0600)
committerKarl Williamson <khw@cpan.org>
Thu, 26 Sep 2019 04:30:43 +0000 (22:30 -0600)
If a parameter to this function is unsigned, gcc, at least, generates a
comparison-always-true warning for the asserts on the parameters.
Silence these by casting to an NV.  Any extra machine instructions will
be gone from non-DEBUGGING builds.  The value in an NV won't necessarily
be exact, but all the assertions care about is the sign, which is
guaranteed by C11 standard 6.3.1.4 item 2.

This technique was the idea of Tomasz Konojacki.

handy.h

diff --git a/handy.h b/handy.h
index e584efd..26547fb 100644 (file)
--- a/handy.h
+++ b/handy.h
@@ -1319,9 +1319,12 @@ or casts
 
 /* Returns true if l <= c <= (l + n), where 'l' and 'n' are non-negative
  * Written this way so that after optimization, only one conditional test is
- * needed. */
-#define withinCOUNT(c, l, n) (__ASSERT_((l) >= 0) __ASSERT_((n) >= (0))        \
-   (((WIDEST_UTYPE) (((c) | 0) - ((l) | 0))) <= (((WIDEST_UTYPE) ((n) | 0)))))
+ * needed.  (The NV casts stop any warnings about comparison always being true
+ * if called with an unsigned.  The cast preserves the sign, which is all we
+ * care about.) */
+#define withinCOUNT(c, l, n) (__ASSERT_((NV) (l) >= 0)                         \
+                              __ASSERT_((NV) (n) >= 0)                         \
+   (((WIDEST_UTYPE) (((c)) - ((l) | 0))) <= (((WIDEST_UTYPE) ((n) | 0)))))
 
 /* Returns true if c is in the range l..u, where 'l' is non-negative
  * Written this way so that after optimization, only one conditional test is