Skip to content
  • Michal Nazarewicz's avatar
    include/linux/kernel.h: change abs() macro so it uses consistent return type · 8f57e4d9
    Michal Nazarewicz authored
    
    
    Rewrite abs() so that its return type does not depend on the
    architecture and no unexpected type conversion happen inside of it.  The
    only conversion is from unsigned to signed type.  char is left as a
    return type but treated as a signed type regradless of it's actual
    signedness.
    
    With the old version, int arguments were promoted to long and depending
    on architecture a long argument might result in s64 or long return type
    (which may or may not be the same).
    
    This came after some back and forth with Nicolas.  The current macro has
    different return type (for the same input type) depending on
    architecture which might be midly iritating.
    
    An alternative version would promote to int like so:
    
    	#define abs(x)	__abs_choose_expr(x, long long,			\
    			__abs_choose_expr(x, long,			\
    			__builtin_choose_expr(				\
    				sizeof(x) <= sizeof(int),		\
    				({ int __x = (x); __x<0?-__x:__x; }),	\
    				((void)0))))
    
    I have no preference but imagine Linus might.  :] Nicolas argument against
    is that promoting to int causes iconsistent behaviour:
    
    	int main(void) {
    		unsigned short a = 0, b = 1, c = a - b;
    		unsigned short d = abs(a - b);
    		unsigned short e = abs(c);
    		printf("%u %u\n", d, e);  // prints: 1 65535
    	}
    
    Then again, no sane person expects consistent behaviour from C integer
    arithmetic.  ;)
    
    Note:
    
      __builtin_types_compatible_p(unsigned char, char) is always false, and
      __builtin_types_compatible_p(signed char, char) is also always false.
    
    Signed-off-by: default avatarMichal Nazarewicz <mina86@mina86.com>
    Reviewed-by: default avatarNicolas Pitre <nico@linaro.org>
    Cc: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
    Cc: Wey-Yi Guy <wey-yi.w.guy@intel.com>
    Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
    Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
    8f57e4d9