summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Eggert <eggert@cs.ucla.edu>2019-08-14 22:24:49 -0700
committerPaul Eggert <eggert@cs.ucla.edu>2019-08-14 22:25:29 -0700
commit45cb2a14a68a519bfa57abfa1751cde6150b6f81 (patch)
tree32eaf5c285b7338f31662b0ad2fefb35cdfa0604
parent96b8849e0203df4bd08610b6d58b3cfa7a2c72b5 (diff)
downloadgnulib-45cb2a14a68a519bfa57abfa1751cde6150b6f81.tar.gz
intprops: support uchar, ushort _WRAPV dests
* lib/intprops.h (_GL_INT_OP_WRAPV_SMALLISH): New macro, defined when __builtin_add_overflow etc. and _Generic are not used. (_GL_INT_OP_WRAPV): Use it to support destinations that are unsigned char or unsigned short, even in compilers that lack __typeof__ and are not C11-compatible.
-rw-r--r--ChangeLog7
-rw-r--r--lib/intprops.h53
2 files changed, 39 insertions, 21 deletions
diff --git a/ChangeLog b/ChangeLog
index 4b752fb06c..74ab30f9f1 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,12 @@
2019-08-14 Paul Eggert <eggert@cs.ucla.edu>
+ intprops: support uchar, ushort _WRAPV dests
+ * lib/intprops.h (_GL_INT_OP_WRAPV_SMALLISH): New macro, defined
+ when __builtin_add_overflow etc. and _Generic are not used.
+ (_GL_INT_OP_WRAPV): Use it to support destinations that
+ are unsigned char or unsigned short, even in compilers
+ that lack __typeof__ and are not C11-compatible.
+
intprops: pacify picky GCC
* lib/intprops.h (_GL_BUILTIN_MUL_OVERFLOW):
Pacify GCC’s complaints about ignoring __builtin_mul_overflow’s
diff --git a/lib/intprops.h b/lib/intprops.h
index 54012874df..f1b2943eaf 100644
--- a/lib/intprops.h
+++ b/lib/intprops.h
@@ -311,10 +311,9 @@
arguments should not have side effects.
The WRAPV macros are not constant expressions. They support only
- +, binary -, and *. The result type must be either signed, or an
- unsigned type that is 'unsigned int' or wider. Because the WRAPV
- macros convert the result, the report overflow in different
- circumstances than the OVERFLOW macros do.
+ +, binary -, and *. Because the WRAPV macros convert the result,
+ they report overflow in different circumstances than the OVERFLOW
+ macros do.
These macros are tuned for their last input argument being a constant.
@@ -422,24 +421,36 @@
_GL_INT_OP_CALC (a, b, r, op, overflow, unsigned long long int, \
unsigned long long int, ULLONG_MIN, ULLONG_MAX)))
#else
-/* This fallback implementation uses _GL_SIGNED_TYPE_OR_EXPR, and so
- may guess wrong on some non-GNU pre-C11 compilers when the type of
- *R is unsigned char or unsigned short. This is why the
- documentation for INT_ADD_WRAPV says that the result type, if
- unsigned, should be unsigned int or wider. */
+/* Store the low-order bits of A <op> B into *R, where OP specifies
+ the operation and OVERFLOW the overflow predicate. If *R is
+ signed, its type is ST with bounds SMIN..SMAX; otherwise its type
+ is UT with bounds U..UMAX. ST and UT are narrower than int.
+ Return 1 if the result overflows. See above for restrictions. */
+# if _GL_HAVE___TYPEOF__
+# define _GL_INT_OP_WRAPV_SMALLISH(a,b,r,op,overflow,st,smin,smax,ut,umax) \
+ (TYPE_SIGNED (__typeof__ (*(r))) \
+ ? _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned int, st, smin, smax) \
+ : _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned int, ut, 0, umax))
+# else
+# define _GL_INT_OP_WRAPV_SMALLISH(a,b,r,op,overflow,st,smin,smax,ut,umax) \
+ (overflow (a, b, smin, smax) \
+ ? (overflow (a, b, 0, umax) \
+ ? (*(r) = _GL_INT_OP_WRAPV_VIA_UNSIGNED (a,b,op,unsigned,st), 1) \
+ : (*(r) = _GL_INT_OP_WRAPV_VIA_UNSIGNED (a,b,op,unsigned,st)) < 0) \
+ : (overflow (a, b, 0, umax) \
+ ? (*(r) = _GL_INT_OP_WRAPV_VIA_UNSIGNED (a,b,op,unsigned,st)) >= 0 \
+ : (*(r) = _GL_INT_OP_WRAPV_VIA_UNSIGNED (a,b,op,unsigned,st), 0)))
+# endif
+
# define _GL_INT_OP_WRAPV(a, b, r, op, builtin, overflow) \
(sizeof *(r) == sizeof (signed char) \
- ? (_GL_SIGNED_TYPE_OR_EXPR (*(r)) \
- ? _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned int, \
- signed char, SCHAR_MIN, SCHAR_MAX) \
- : _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned int, \
- unsigned char, 0, UCHAR_MAX)) \
+ ? _GL_INT_OP_WRAPV_SMALLISH (a, b, r, op, overflow, \
+ signed char, SCHAR_MIN, SCHAR_MAX, \
+ unsigned char, UCHAR_MAX) \
: sizeof *(r) == sizeof (short int) \
- ? (_GL_SIGNED_TYPE_OR_EXPR (*(r)) \
- ? _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned int, \
- short int, SHRT_MIN, SHRT_MAX) \
- : _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned int, \
- unsigned short int, 0, USHRT_MAX)) \
+ ? _GL_INT_OP_WRAPV_SMALLISH (a, b, r, op, overflow, \
+ short int, SHRT_MIN, SHRT_MAX, \
+ unsigned short int, USHRT_MAX) \
: sizeof *(r) == sizeof (int) \
? (EXPR_SIGNED (*(r)) \
? _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned int, \
@@ -541,8 +552,8 @@
<= -1 - (a))) \
: INT_NEGATE_OVERFLOW (_GL_INT_CONVERT (b, tmin)) && (b) == -1 \
? (EXPR_SIGNED (a) \
- ? 0 < (a) + (tmin) \
- : 0 < (a) && -1 - (tmin) < (a) - 1) \
+ ? 0 < (a) + (tmin) \
+ : 0 < (a) && -1 - (tmin) < (a) - 1) \
: (tmin) / (b) < (a)) \
: (b) == 0 \
? 0 \