diff options
Diffstat (limited to 'include/linux/bitfield.h')
| -rw-r--r-- | include/linux/bitfield.h | 19 | 
1 files changed, 18 insertions, 1 deletions
diff --git a/include/linux/bitfield.h b/include/linux/bitfield.h index 4e035aca6f7e..6093fa6db260 100644 --- a/include/linux/bitfield.h +++ b/include/linux/bitfield.h @@ -41,6 +41,22 @@  #define __bf_shf(x) (__builtin_ffsll(x) - 1) +#define __scalar_type_to_unsigned_cases(type)				\ +		unsigned type:	(unsigned type)0,			\ +		signed type:	(unsigned type)0 + +#define __unsigned_scalar_typeof(x) typeof(				\ +		_Generic((x),						\ +			char:	(unsigned char)0,			\ +			__scalar_type_to_unsigned_cases(char),		\ +			__scalar_type_to_unsigned_cases(short),		\ +			__scalar_type_to_unsigned_cases(int),		\ +			__scalar_type_to_unsigned_cases(long),		\ +			__scalar_type_to_unsigned_cases(long long),	\ +			default: (x))) + +#define __bf_cast_unsigned(type, x)	((__unsigned_scalar_typeof(type))(x)) +  #define __BF_FIELD_CHECK(_mask, _reg, _val, _pfx)			\  	({								\  		BUILD_BUG_ON_MSG(!__builtin_constant_p(_mask),		\ @@ -49,7 +65,8 @@  		BUILD_BUG_ON_MSG(__builtin_constant_p(_val) ?		\  				 ~((_mask) >> __bf_shf(_mask)) & (_val) : 0, \  				 _pfx "value too large for the field"); \ -		BUILD_BUG_ON_MSG((_mask) > (typeof(_reg))~0ull,		\ +		BUILD_BUG_ON_MSG(__bf_cast_unsigned(_mask, _mask) >	\ +				 __bf_cast_unsigned(_reg, ~0ull),	\  				 _pfx "type of reg too small for mask"); \  		__BUILD_BUG_ON_NOT_POWER_OF_2((_mask) +			\  					      (1ULL << __bf_shf(_mask))); \  | 
