cogl-flags: Fix iterating flag when the most-significant bit is set

When the flags contain a value that only has the most-significant bit
set then ffsl will return the size of an unsigned long. According to
the C spec it is undefined what happens when shifting by a number
greater than or equal to the size of the left operand. On Intel (and
probably others) this seems to end up being a no-op so the iteration
breaks. To fix this we can split the shift into two separate
shifts. We always need to shift by at least one bit so we can put this
one bit shift into a separate operator.

Reviewed-by: Robert Bragg <robert@linux.intel.com>
This commit is contained in:
Neil Roberts 2011-11-22 15:59:58 +00:00
parent 3e56883c98
commit 61d71c0926

View File

@ -109,7 +109,12 @@ G_BEGIN_DECLS
{ \ { \
int _next_bit = _cogl_util_ffsl (_mask); \ int _next_bit = _cogl_util_ffsl (_mask); \
(bit) += _next_bit; \ (bit) += _next_bit; \
_mask >>= _next_bit; /* This odd two-part shift is to avoid */ \
/* shifting by sizeof (long)*8 which has */ \
/* undefined results according to the */ \
/* C spec (and seems to be a no-op in */ \
/* practice) */ \
_mask = (_mask >> (_next_bit - 1)) >> 1; \
#define COGL_FLAGS_FOREACH_END \ #define COGL_FLAGS_FOREACH_END \
} } } G_STMT_END } } } G_STMT_END