Skip to content

Commit bff8c38

Browse files
author
Peter Zijlstra
committed
bitfield.h: Fix "type of reg too small for mask" test
The test: 'mask > (typeof(_reg))~0ull' only works correctly when both sides are unsigned, consider: - 0xff000000 vs (int)~0ull - 0x000000ff vs (int)~0ull Signed-off-by: Peter Zijlstra (Intel) <[email protected]> Reviewed-by: Josh Poimboeuf <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent e463a09 commit bff8c38

File tree

1 file changed

+18
-1
lines changed

1 file changed

+18
-1
lines changed

include/linux/bitfield.h

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,22 @@
4141

4242
#define __bf_shf(x) (__builtin_ffsll(x) - 1)
4343

44+
#define __scalar_type_to_unsigned_cases(type) \
45+
unsigned type: (unsigned type)0, \
46+
signed type: (unsigned type)0
47+
48+
#define __unsigned_scalar_typeof(x) typeof( \
49+
_Generic((x), \
50+
char: (unsigned char)0, \
51+
__scalar_type_to_unsigned_cases(char), \
52+
__scalar_type_to_unsigned_cases(short), \
53+
__scalar_type_to_unsigned_cases(int), \
54+
__scalar_type_to_unsigned_cases(long), \
55+
__scalar_type_to_unsigned_cases(long long), \
56+
default: (x)))
57+
58+
#define __bf_cast_unsigned(type, x) ((__unsigned_scalar_typeof(type))(x))
59+
4460
#define __BF_FIELD_CHECK(_mask, _reg, _val, _pfx) \
4561
({ \
4662
BUILD_BUG_ON_MSG(!__builtin_constant_p(_mask), \
@@ -49,7 +65,8 @@
4965
BUILD_BUG_ON_MSG(__builtin_constant_p(_val) ? \
5066
~((_mask) >> __bf_shf(_mask)) & (_val) : 0, \
5167
_pfx "value too large for the field"); \
52-
BUILD_BUG_ON_MSG((_mask) > (typeof(_reg))~0ull, \
68+
BUILD_BUG_ON_MSG(__bf_cast_unsigned(_mask, _mask) > \
69+
__bf_cast_unsigned(_reg, ~0ull), \
5370
_pfx "type of reg too small for mask"); \
5471
__BUILD_BUG_ON_NOT_POWER_OF_2((_mask) + \
5572
(1ULL << __bf_shf(_mask))); \

0 commit comments

Comments
 (0)