diff options
author | Paul Eggert <eggert@cs.ucla.edu> | 2015-10-30 19:21:29 -0700 |
---|---|---|
committer | Paul Eggert <eggert@cs.ucla.edu> | 2015-10-30 19:21:51 -0700 |
commit | b059c6b584e964296d425667642650f42972c238 (patch) | |
tree | 6fb75417015f334689101115595ebad2e0d38ca1 /lib | |
parent | e11aaee266da52937a3a031cb108fe13f68958c3 (diff) |
Merge from gnulib.
This incorporates:
2015-10-30 intprops: add WRAPV and const flavors for GCC 5
2015-10-25 stdalign: port to Sun C 5.9
* doc/misc/texinfo.tex, lib/intprops.h, lib/stdalign.in.h:
Copy from gnulib.
Diffstat (limited to 'lib')
-rw-r--r-- | lib/intprops.h | 141 | ||||
-rw-r--r-- | lib/stdalign.in.h | 2 |
2 files changed, 130 insertions, 13 deletions
diff --git a/lib/intprops.h b/lib/intprops.h index f85ccade4e..4441f1c294 100644 --- a/lib/intprops.h +++ b/lib/intprops.h @@ -263,22 +263,31 @@ : (a) % - (b)) \ == 0) - -/* Integer overflow checks. +/* Check for integer overflow, and report low order bits of answer. The INT_<op>_OVERFLOW macros return 1 if the corresponding C operators might not yield numerically correct answers due to arithmetic overflow. - They work correctly on all known practical hosts, and do not rely + The INT_<op>_WRAPV macros return the low-order bits of the answer. + For example, INT_ADD_WRAPV (INT_MAX, 1) returns INT_MIN on a two's + complement host, even if INT_MAX + 1 would trap. + + These macros work correctly on all known practical hosts, and do not rely on undefined behavior due to signed arithmetic overflow. Example usage: - long int i = ...; - long int j = ...; - if (INT_MULTIPLY_OVERFLOW (i, j)) - printf ("multiply would overflow"); - else - printf ("product is %ld", i * j); + long int a = ...; + long int b = ...; + long int result = INT_MULTIPLY_WRAPV (a, b); + printf ("result is %ld (%s)\n", result, + INT_MULTIPLY_OVERFLOW (a, b) ? "after overflow" : "no overflow"); + + enum { + INT_PRODUCTS_FIT_IN_LONG + = ! INT_CONST_MULTIPLY_OVERFLOW ((long int) INT_MIN, INT_MIN) + }; + + Restrictions on these macros: These macros do not check for all possible numerical problems or undefined or unspecified behavior: they do not check for division @@ -287,18 +296,35 @@ These macros may evaluate their arguments zero or multiple times, so the arguments should not have side effects. + On non-GCC-compatible compilers that do not support C11, the type + of INT_<op>_WRAPV (A, B) might differ from the native type of (A op + B), so it is wise to convert the result to the native type. Such a + conversion is safe and cannot trap. + + For runtime efficiency GCC 5 and later has builtin functions for +, + -, * when doing integer overflow checking or wraparound arithmetic. + Unfortunately, these builtins require nonnull pointer arguments and + so cannot be used in constant expressions; see GCC bug 68120 + <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=68120>. In constant + expressions, use the macros INT_CONST_ADD_OVERFLOW and + INT_CONST_ADD_WRAPV instead, and similarly for SUBTRACT and + MULTIPLY; these macros avoid the builtins and are slower in + non-constant expressions. Perhaps someday GCC's API for overflow + checking will be improved and we can remove the need for the + INT_CONST_ variants. + These macros are tuned for their last argument being a constant. Return 1 if the integer expressions A * B, A - B, -A, A * B, A / B, A % B, and A << B would overflow, respectively. */ -#define INT_ADD_OVERFLOW(a, b) \ +#define INT_CONST_ADD_OVERFLOW(a, b) \ _GL_BINARY_OP_OVERFLOW (a, b, _GL_ADD_OVERFLOW) -#define INT_SUBTRACT_OVERFLOW(a, b) \ +#define INT_CONST_SUBTRACT_OVERFLOW(a, b) \ _GL_BINARY_OP_OVERFLOW (a, b, _GL_SUBTRACT_OVERFLOW) #define INT_NEGATE_OVERFLOW(a) \ INT_NEGATE_RANGE_OVERFLOW (a, _GL_INT_MINIMUM (a), _GL_INT_MAXIMUM (a)) -#define INT_MULTIPLY_OVERFLOW(a, b) \ +#define INT_CONST_MULTIPLY_OVERFLOW(a, b) \ _GL_BINARY_OP_OVERFLOW (a, b, _GL_MULTIPLY_OVERFLOW) #define INT_DIVIDE_OVERFLOW(a, b) \ _GL_BINARY_OP_OVERFLOW (a, b, _GL_DIVIDE_OVERFLOW) @@ -317,4 +343,95 @@ _GL_INT_MINIMUM (0 * (b) + (a)), \ _GL_INT_MAXIMUM (0 * (b) + (a))) +/* Return the low order bits of the integer expressions + A * B, A - B, -A, A * B, A / B, A % B, and A << B, respectively. + See above for restrictions. */ +#define INT_CONST_ADD_WRAPV(a, b) _GL_INT_OP_WRAPV (a, b, +) +#define INT_CONST_SUBTRACT_WRAPV(a, b) _GL_INT_OP_WRAPV (a, b, -) +#define INT_NEGATE_WRAPV(a) INT_CONST_SUBTRACT_WRAPV (0, a) +#define INT_CONST_MULTIPLY_WRAPV(a, b) _GL_INT_OP_WRAPV (a, b, *) +#define INT_DIVIDE_WRAPV(a, b) \ + (INT_DIVIDE_OVERFLOW(a, b) ? INT_NEGATE_WRAPV (a) : (a) / (b)) +#define INT_REMAINDER_WRAPV(a, b) \ + (INT_REMAINDER_OVERFLOW(a, b) ? 0 : (a) % (b)) +#define INT_LEFT_SHIFT_WRAPV(a, b) _GL_INT_OP_WRAPV (a, b, <<) + +/* Return the low order bits of A <op> B, where OP specifies the operation. + See above for restrictions. */ +#if !_GL_HAVE___TYPEOF__ && 201112 <= __STDC_VERSION__ +# define _GL_INT_OP_WRAPV(a, b, op) \ + _Generic ((a) op (b), \ + int: _GL_INT_OP_WRAPV_VIA_UNSIGNED (a, b, op, int), \ + long int: _GL_INT_OP_WRAPV_VIA_UNSIGNED (a, b, op, long int), \ + long long int: _GL_INT_OP_WRAPV_VIA_UNSIGNED (a, b, op, \ + long long int), \ + default: (a) op (b)) +#else +# define _GL_INT_OP_WRAPV(a, b, op) \ + (! _GL_INT_SIGNED ((0 * (a)) op (0 * (b))) \ + ? ((a) op (b)) \ + : _GL_EXPR_CAST ((a) op (b), \ + (sizeof ((a) op (b)) <= sizeof (int) \ + ? _GL_INT_OP_WRAPV_VIA_UNSIGNED (a, b, op, int) \ + : _GL_INT_OP_WRAPV_LONGISH (a, b, op)))) + +/* Cast to E's type the value of V if possible. Yield V as-is otherwise. */ +# if _GL_HAVE___TYPEOF__ +# define _GL_EXPR_CAST(e, v) ((__typeof__ (e)) (v)) +# else +# define _GL_EXPR_CAST(e, v) (v) +# endif + +# ifdef LLONG_MAX +# define _GL_INT_OP_WRAPV_LONGISH(a, b, op) \ + (sizeof ((a) op (b)) <= sizeof (long int) \ + ? _GL_INT_OP_WRAPV_VIA_UNSIGNED (a, b, op, long int) \ + : _GL_INT_OP_WRAPV_VIA_UNSIGNED (a, b, op, long long int)) +# else +# define _GL_INT_OP_WRAPV_LONGISH(a, b, op) \ + _GL_INT_OP_WRAPV_VIA_UNSIGNED (a, b, op, long int) +# endif +#endif + +/* Return A <op> B, where the operation is given by OP and the result + type is T. T is a signed integer type that is at least as wide as int. + Do arithmetic using 'unsigned T' to avoid signed integer overflow. + Subtract TYPE_MINIMUM (T) before converting back to T, and add it + back afterwards, to avoid signed overflow during conversion. */ +#define _GL_INT_OP_WRAPV_VIA_UNSIGNED(a, b, op, t) \ + ((unsigned t) (a) op (unsigned t) (b) <= TYPE_MAXIMUM (t) \ + ? (t) ((unsigned t) (a) op (unsigned t) (b)) \ + : ((t) ((unsigned t) (a) op (unsigned t) (b) - TYPE_MINIMUM (t)) \ + + TYPE_MINIMUM (t))) + +/* Calls to the INT_<op>_<result> macros are like their INT_CONST_<op>_<result> + counterparts, except they are faster with GCC 5 or later, and they + are not constant expressions due to limitations in the GNU C API. */ + +#define INT_ADD_OVERFLOW(a, b) \ + _GL_OP_OVERFLOW (a, b, INT_CONST_ADD_OVERFLOW, __builtin_add_overflow) +#define INT_SUBTRACT_OVERFLOW(a, b) \ + _GL_OP_OVERFLOW (a, b, INT_CONST_SUBTRACT_OVERFLOW, __builtin_sub_overflow) +#define INT_MULTIPLY_OVERFLOW(a, b) \ + _GL_OP_OVERFLOW (a, b, INT_CONST_MULTIPLY_OVERFLOW, __builtin_mul_overflow) + +#define INT_ADD_WRAPV(a, b) \ + _GL_OP_WRAPV (a, b, INT_CONST_ADD_WRAPV, __builtin_add_overflow) +#define INT_SUBTRACT_WRAPV(a, b) \ + _GL_OP_WRAPV (a, b, INT_CONST_SUBTRACT_WRAPV, __builtin_sub_overflow) +#define INT_MULTIPLY_WRAPV(a, b) \ + _GL_OP_WRAPV (a, b, INT_CONST_MULTIPLY_WRAPV, __builtin_mul_overflow) + +#if __GNUC__ < 5 +# define _GL_OP_OVERFLOW(a, b, portable, builtin) portable (a, b) +# define _GL_OP_WRAPV(a, b, portable, builtin) portable (a, b) +#else +# define _GL_OP_OVERFLOW(a, b, portable, builtin) \ + builtin (a, b, &(__typeof__ ((a) + (b))) {0}) +# define _GL_OP_WRAPV(a, b, portable, builtin) \ + _GL_OP_WRAPV_GENSYM(a, b, builtin, __gl_wrapv##__COUNTER__) +# define _GL_OP_WRAPV_GENSYM(a, b, builtin, r) \ + ({__typeof__ ((a) + (b)) r; builtin (a, b, &r); r; }) +#endif + #endif /* _GL_INTPROPS_H */ diff --git a/lib/stdalign.in.h b/lib/stdalign.in.h index ce1e793e27..b16ccc8699 100644 --- a/lib/stdalign.in.h +++ b/lib/stdalign.in.h @@ -104,7 +104,7 @@ ? 4 < __GNUC__ + (1 <= __GNUC_MINOR__) \ : __GNUC__) \ || __HP_cc || __HP_aCC || __IBMC__ || __IBMCPP__ \ - || __ICC || 0x5110 <= __SUNPRO_C) + || __ICC || 0x590 <= __SUNPRO_C) # define _Alignas(a) __attribute__ ((__aligned__ (a))) # elif 1300 <= _MSC_VER # define _Alignas(a) __declspec (align (a)) |