This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Perl_op_lvalue_flags(): skip OPf_WANT_VOID ops.
[perl5.git] / handy.h
diff --git a/handy.h b/handy.h
index cb6da9f..51f79ef 100644 (file)
--- a/handy.h
+++ b/handy.h
@@ -260,7 +260,7 @@ typedef U64TYPE U64;
  * If not, subtracting 1 would leave the uppermost bit set, so the & would
  * yield non-zero */
 #if defined(PERL_CORE) || defined(PERL_EXT)
-#  define isPOWER_OF_2(n) (n && (n & (n-1)) == 0)
+#  define isPOWER_OF_2(n) ((n) && ((n) & ((n)-1)) == 0)
 #endif
 
 /* This is a helper macro to avoid preprocessor issues, replaced by nothing
@@ -1094,11 +1094,27 @@ patched there.  The file as of this writing is cpan/Devel-PPPort/parts/inc/misc
 #define FITS_IN_8_BITS(c) (1)
 #endif
 
-/* Returns true if c is in the range l..u
- * Written with the cast so it only needs one conditional test
- */
-#define inRANGE(c, l, u) (__ASSERT_((u) >= (l))                          \
-    ((WIDEST_UTYPE) (((c) - (l)) | 0) <= ((WIDEST_UTYPE) ((u) - (l)))))
+/* 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
+ * needed.
+ *
+ * This isn't fully general, except for the special cased 'signed char' (which
+ * should be resolved at compile time):  It won't work if 'c' is negative, and
+ * 'l' is larger than the max for that signed type.  Thus if 'c' is a negative
+ * int, and 'l' is larger than INT_MAX, it will fail.  To protect agains this
+ * happening, there is an assert that will generate a warning if c is larger
+ * than e.g.  INT_MAX if it is an 'unsigned int'.  This could be a false
+ * positive, but khw couldn't figure out a way to make it better.  It's good
+ * enough so far */
+#define inRANGE(c, l, u) (__ASSERT_((l) >= 0) __ASSERT_((u) >= (l))            \
+  ((sizeof(c) == 1)                                                            \
+   ? (((WIDEST_UTYPE) ((((U8) (c))|0) - (l))) <= ((WIDEST_UTYPE) ((u) - (l)))) \
+   : (__ASSERT_(   (((WIDEST_UTYPE) 1) <<  (CHARBITS * sizeof(c) - 1) & (c))   \
+                     /* sign bit of c is 0 */                             == 0 \
+                || (((~ ((WIDEST_UTYPE) 1) << ((CHARBITS * sizeof(c) - 1) - 1))\
+                   /* l not larger than largest value in c's signed type */    \
+                                          & ~ ((WIDEST_UTYPE) 0)) & (l)) == 0) \
+      ((WIDEST_UTYPE) (((c) - (l)) | 0) <= ((WIDEST_UTYPE) ((u) - (l)))))))
 
 #ifdef EBCDIC
 #   ifndef _ALL_SOURCE