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



commit 61d71c0926bf5bf7c78bc27e4da726e0e0084a36
Author: Neil Roberts <neil linux intel com>
Date:   Tue Nov 22 15:59:58 2011 +0000

    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>

 cogl/cogl-flags.h |    7 ++++++-
 1 files changed, 6 insertions(+), 1 deletions(-)
---
diff --git a/cogl/cogl-flags.h b/cogl/cogl-flags.h
index bf5eadd..d62294a 100644
--- a/cogl/cogl-flags.h
+++ b/cogl/cogl-flags.h
@@ -109,7 +109,12 @@ G_BEGIN_DECLS
         {                                               \
           int _next_bit = _cogl_util_ffsl (_mask);      \
           (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 \
   } } } G_STMT_END



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]