From e293c94c65d49171c54bb1893c355e36c66806b8 Mon Sep 17 00:00:00 2001 From: Mark H Weaver Date: Tue, 11 Mar 2014 21:27:21 -0400 Subject: [PATCH 1/1] SCM_SRS: Improve fallback implemention to avoid unspecified behavior. * libguile/numbers.h (SCM_SRS): Rewrite preprocessor test to avoid left-shifting negative integers, and to test more comprehensively for the behavior we need. Rewrite fallback implementation to avoid unspecified behavior. --- libguile/numbers.h | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/libguile/numbers.h b/libguile/numbers.h index b4202f26a..a3271ccd5 100644 --- a/libguile/numbers.h +++ b/libguile/numbers.h @@ -49,12 +49,21 @@ typedef scm_t_int32 scm_t_wchar; #define SCM_MOST_POSITIVE_FIXNUM ((SCM_T_SIGNED_BITS_MAX-3)/4) #define SCM_MOST_NEGATIVE_FIXNUM (-SCM_MOST_POSITIVE_FIXNUM-1) -/* SCM_SRS is signed right shift */ -#if (-1 == (((-1) << 2) + 2) >> 2) -# define SCM_SRS(x, y) ((x) >> (y)) +/* SCM_SRS (X, Y) is signed right shift, defined as floor (X / 2^Y), + where Y must be non-negative and less than the width in bits of X. + It's common for >> to do this, but the C standards do not specify + what happens when X is negative. + + NOTE: X must not perform side effects. */ +#if (-1 >> 2 == -1) && (-4 >> 2 == -1) && (-5 >> 2 == -2) && (-8 >> 2 == -2) +# define SCM_SRS(x, y) ((x) >> (y)) #else -# define SCM_SRS(x, y) ((x) < 0 ? ~((~(x)) >> (y)) : ((x) >> (y))) -#endif /* (-1 == (((-1) << 2) + 2) >> 2) */ +# define SCM_SRS(x, y) \ + ((x) < 0 \ + ? -1 - (scm_t_signed_bits) (~(scm_t_bits)(x) >> (y)) \ + : ((x) >> (y))) +#endif + #define SCM_I_INUMP(x) (2 & SCM_UNPACK (x)) -- 2.20.1