aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorJens Wiklander <jens.wiklander@linaro.org>2018-05-14 17:17:30 +0200
committerJérôme Forissier <jerome.forissier@linaro.org>2018-05-15 17:15:23 +0200
commitecdedc94e72049d79afda94488b8d67974eb7583 (patch)
tree925364539b334dc2f81e5a32c4d770dc95b117b3 /lib
parent9a8117de1263a61702d2b1cd81a9339fd77624cb (diff)
util: update fallback SUB_OVERFLOW() macro
Updates the fallback SUB_OVERFLOW() macro to better support mixed types in the arguments. Acked-by: Etienne Carriere <etienne.carriere@linaro.org> Acked-by: Jerome Forissier <jerome.forissier@linaro.org> Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>
Diffstat (limited to 'lib')
-rw-r--r--lib/libutils/ext/include/compiler.h42
1 files changed, 27 insertions, 15 deletions
diff --git a/lib/libutils/ext/include/compiler.h b/lib/libutils/ext/include/compiler.h
index eb1842fe..d86be9d7 100644
--- a/lib/libutils/ext/include/compiler.h
+++ b/lib/libutils/ext/include/compiler.h
@@ -150,23 +150,35 @@
#define __INTOF_SUB(c, a, b) (__extension__({ \
typeof(a) __intofs_a = a; \
typeof(b) __intofs_b = b; \
- int __infos_b_signed = !!__INTOF_MIN(typeof(b)); \
- int __infos_c_signed = !!__INTOF_MIN(typeof(c)); \
+ intmax_t __intofs_a_signed = __intofs_a; \
+ uintmax_t __intofs_a_unsigned = __intofs_a; \
+ intmax_t __intofs_b_signed = __intofs_b; \
+ uintmax_t __intofs_b_unsigned = __intofs_b; \
\
__intofs_b < 1 ? \
- ((__INTOF_MAX(typeof(c)) + __intofs_b >= __intofs_a) ? \
- __INTOF_ASSIGN((c), __intofs_a - __intofs_b) : 1) : \
- /* \
- * First deal with special case where c is signed and b is \
- * unsigned, and __INTOF_MIN(typeof(c)) + __intofs_b would \
- * have been a negative number if the expression wasn't \
- * promoted to an unsigned type. \
- */ \
- (((__infos_c_signed && !__infos_b_signed && \
- ((uintmax_t)__INTOF_MAX_SIGNED(typeof(c)) >= \
- (uintmax_t)__intofs_b)) || \
- (__INTOF_MIN(typeof(c)) + __intofs_b <= __intofs_a)) ? \
- __INTOF_ASSIGN((c), __intofs_a - __intofs_b) : 1); \
+ __intofs_a < 1 ? \
+ ((INTMAX_MAX + __intofs_b >= __intofs_a) ? \
+ __INTOF_ASSIGN((c), __intofs_a_signed - \
+ __intofs_b_signed) : 1) \
+ : \
+ (((uintmax_t)(UINTMAX_MAX + __intofs_b_signed) >= \
+ __intofs_a_unsigned) ? \
+ __INTOF_ASSIGN((c), __intofs_a - \
+ __intofs_b) : 1) \
+ : \
+ __intofs_a < 1 ? \
+ (((INTMAX_MIN + __intofs_b <= __intofs_a)) ? \
+ __INTOF_ASSIGN((c), \
+ (intmax_t)(__intofs_a_signed - \
+ __intofs_b_unsigned)) : 1) \
+ : \
+ ((__intofs_b_unsigned <= __intofs_a_unsigned) ? \
+ __INTOF_ASSIGN((c), __intofs_a_unsigned - \
+ __intofs_b_unsigned) \
+ : \
+ __INTOF_ASSIGN((c), \
+ (intmax_t)(__intofs_a_unsigned - \
+ __intofs_b_unsigned))); \
}))
/*