diff options
author | Paul Eggert <eggert@cs.ucla.edu> | 2016-06-24 13:49:32 +0200 |
---|---|---|
committer | Paul Eggert <eggert@cs.ucla.edu> | 2016-06-24 13:51:08 +0200 |
commit | 63457dcfe0fe101d3db131c4b05823e8280b6bff (patch) | |
tree | 61011da009c5e0bb342d3c5a01e516cd08d97254 /lib | |
parent | dc49db725e2d1648cbf1f94cef6131d42b13237b (diff) |
Update from gnulib
This incorporates:
2016-06-24 intprops: port better to GCC 7
2016-06-13 xalloc-oversized: port to GCC 7; fewer warnings
* doc/misc/texinfo.tex, lib/xalloc-oversized.h, lib/intprops.h:
Copy from gnulib.
Diffstat (limited to 'lib')
-rw-r--r-- | lib/intprops.h | 57 | ||||
-rw-r--r-- | lib/xalloc-oversized.h | 42 |
2 files changed, 70 insertions, 29 deletions
diff --git a/lib/intprops.h b/lib/intprops.h index 31521395e2..e1fce5c96a 100644 --- a/lib/intprops.h +++ b/lib/intprops.h @@ -222,24 +222,35 @@ verify (TYPE_MAXIMUM (long long int) == LLONG_MAX); ? (a) < (min) >> (b) \ : (max) >> (b) < (a)) +/* True if __builtin_add_overflow (A, B, P) works when P is null. */ +#define _GL_HAS_BUILTIN_OVERFLOW_WITH_NULL (7 <= __GNUC__) /* The _GL*_OVERFLOW macros have the same restrictions as the *_RANGE_OVERFLOW macros, except that they do not assume that operands (e.g., A and B) have the same type as MIN and MAX. Instead, they assume that the result (e.g., A + B) has that type. */ -#define _GL_ADD_OVERFLOW(a, b, min, max) \ - ((min) < 0 ? INT_ADD_RANGE_OVERFLOW (a, b, min, max) \ - : (a) < 0 ? (b) <= (a) + (b) \ - : (b) < 0 ? (a) <= (a) + (b) \ - : (a) + (b) < (b)) -#define _GL_SUBTRACT_OVERFLOW(a, b, min, max) \ - ((min) < 0 ? INT_SUBTRACT_RANGE_OVERFLOW (a, b, min, max) \ - : (a) < 0 ? 1 \ - : (b) < 0 ? (a) - (b) <= (a) \ - : (a) < (b)) -#define _GL_MULTIPLY_OVERFLOW(a, b, min, max) \ - (((min) == 0 && (((a) < 0 && 0 < (b)) || ((b) < 0 && 0 < (a)))) \ - || INT_MULTIPLY_RANGE_OVERFLOW (a, b, min, max)) +#if _GL_HAS_BUILTIN_OVERFLOW_WITH_NULL +# define _GL_ADD_OVERFLOW(a, b, min, max) + __builtin_add_overflow (a, b, (__typeof__ ((a) + (b)) *) 0) +# define _GL_SUBTRACT_OVERFLOW(a, b, min, max) + __builtin_sub_overflow (a, b, (__typeof__ ((a) - (b)) *) 0) +# define _GL_MULTIPLY_OVERFLOW(a, b, min, max) + __builtin_mul_overflow (a, b, (__typeof__ ((a) * (b)) *) 0) +#else +# define _GL_ADD_OVERFLOW(a, b, min, max) \ + ((min) < 0 ? INT_ADD_RANGE_OVERFLOW (a, b, min, max) \ + : (a) < 0 ? (b) <= (a) + (b) \ + : (b) < 0 ? (a) <= (a) + (b) \ + : (a) + (b) < (b)) +# define _GL_SUBTRACT_OVERFLOW(a, b, min, max) \ + ((min) < 0 ? INT_SUBTRACT_RANGE_OVERFLOW (a, b, min, max) \ + : (a) < 0 ? 1 \ + : (b) < 0 ? (a) - (b) <= (a) \ + : (a) < (b)) +# define _GL_MULTIPLY_OVERFLOW(a, b, min, max) \ + (((min) == 0 && (((a) < 0 && 0 < (b)) || ((b) < 0 && 0 < (a)))) \ + || INT_MULTIPLY_RANGE_OVERFLOW (a, b, min, max)) +#endif #define _GL_DIVIDE_OVERFLOW(a, b, min, max) \ ((min) < 0 ? (b) == _GL_INT_NEGATE_CONVERT (min, 1) && (a) < - (max) \ : (a) < 0 ? (b) <= (a) + (b) - 1 \ @@ -304,8 +315,12 @@ verify (TYPE_MAXIMUM (long long int) == LLONG_MAX); _GL_BINARY_OP_OVERFLOW (a, b, _GL_ADD_OVERFLOW) #define INT_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)) +#if _GL_HAS_BUILTIN_OVERFLOW_WITH_NULL +# define INT_NEGATE_OVERFLOW(a) INT_SUBTRACT_OVERFLOW (0, a) +#else +# define INT_NEGATE_OVERFLOW(a) \ + INT_NEGATE_RANGE_OVERFLOW (a, _GL_INT_MINIMUM (a), _GL_INT_MAXIMUM (a)) +#endif #define INT_MULTIPLY_OVERFLOW(a, b) \ _GL_BINARY_OP_OVERFLOW (a, b, _GL_MULTIPLY_OVERFLOW) #define INT_DIVIDE_OVERFLOW(a, b) \ @@ -325,7 +340,7 @@ verify (TYPE_MAXIMUM (long long int) == LLONG_MAX); _GL_INT_MINIMUM (0 * (b) + (a)), \ _GL_INT_MAXIMUM (0 * (b) + (a))) -/* Compute A + B, A - B, A * B, respectively, storing the result into *R. +/* Store the low-order bits of A + B, A - B, A * B, respectively, into *R. Return 1 if the result overflows. See above for restrictions. */ #define INT_ADD_WRAPV(a, b, r) \ _GL_INT_OP_WRAPV (a, b, r, +, __builtin_add_overflow, INT_ADD_OVERFLOW) @@ -350,9 +365,10 @@ verify (TYPE_MAXIMUM (long long int) == LLONG_MAX); # define _GL__GENERIC_BOGUS 0 #endif -/* Store A <op> B into *R, where OP specifies the operation. - BUILTIN is the builtin operation, and OVERFLOW the overflow predicate. - See above for restrictions. */ +/* Store the low-order bits of A <op> B into *R, where OP specifies + the operation. BUILTIN is the builtin operation, and OVERFLOW the + overflow predicate. Return 1 if the result overflows. See above + for restrictions. */ #if 5 <= __GNUC__ || __has_builtin (__builtin_add_overflow) # define _GL_INT_OP_WRAPV(a, b, r, op, builtin, overflow) builtin (a, b, r) #elif 201112 <= __STDC_VERSION__ && !_GL__GENERIC_BOGUS @@ -403,7 +419,8 @@ verify (TYPE_MAXIMUM (long long int) == LLONG_MAX); /* Store the low-order bits of A <op> B into *R, where the operation is given by OP. Use the unsigned type UT for calculation to avoid overflow problems. *R's type is T, with extremal values TMIN and - TMAX. T must be a signed integer type. */ + TMAX. T must be a signed integer type. Return 1 if the result + overflows. */ #define _GL_INT_OP_CALC(a, b, r, op, overflow, ut, t, tmin, tmax) \ (sizeof ((a) op (b)) < sizeof (t) \ ? _GL_INT_OP_CALC1 ((t) (a), (t) (b), r, op, overflow, ut, t, tmin, tmax) \ diff --git a/lib/xalloc-oversized.h b/lib/xalloc-oversized.h index d81a8471d3..44f16441c7 100644 --- a/lib/xalloc-oversized.h +++ b/lib/xalloc-oversized.h @@ -20,15 +20,13 @@ #include <stddef.h> +/* Default for (non-Clang) compilers that lack __has_builtin. */ #ifndef __has_builtin # define __has_builtin(x) 0 #endif -/* Return 1 if an array of N objects, each of size S, cannot exist due - to size arithmetic overflow. S must be positive and N must be - nonnegative. This is a macro, not a function, so that it - works correctly even when SIZE_MAX < N. - +/* True if N * S would overflow in a size calculation. + This expands to a constant expression if N and S are both constants. By gnulib convention, SIZE_MAX represents overflow in size calculations, so the conservative dividend to use here is SIZE_MAX - 1, since SIZE_MAX might represent an overflowed value. @@ -36,12 +34,38 @@ sizeof (ptrdiff_t) <= sizeof (size_t), so do not bother to test for exactly-SIZE_MAX allocations on such hosts; this avoids a test and branch when S is known to be 1. */ -#if 5 <= __GNUC__ || __has_builtin (__builtin_mul_overflow) +#define __xalloc_oversized(n, s) \ + ((size_t) (sizeof (ptrdiff_t) <= sizeof (size_t) ? -1 : -2) / (s) < (n)) + + +/* Return 1 if an array of N objects, each of size S, cannot exist due + to size arithmetic overflow. S must be positive and N must be + nonnegative. This is a macro, not a function, so that it + works correctly even when SIZE_MAX < N. */ + +/* GCC 7 __builtin_mul_overflow should easily compute this. See: + https://gcc.gnu.org/bugzilla/show_bug.cgi?id=68120 */ +#if 7 <= __GNUC__ +# define xalloc_oversized(n, s) __builtin_mul_overflow (n, s, (size_t *) NULL) + +/* GCC 5 and Clang __builtin_mul_overflow needs a temporary, and + should be used only for non-constant operands, so that + xalloc_oversized is a constant expression if both arguments are. + Do not use this if pedantic, since pedantic GCC issues a diagnostic + for ({ ... }). */ +#elif ((5 <= __GNUC__ \ + || (__has_builtin (__builtin_mul_overflow) \ + && __has_builtin (__builtin_constant_p))) \ + && !__STRICT_ANSI__) # define xalloc_oversized(n, s) \ - ({ size_t __xalloc_size; __builtin_mul_overflow (n, s, &__xalloc_size); }) + (__builtin_constant_p (n) && __builtin_constant_p (s) \ + ? __xalloc_oversized (n, s) \ + : ({ size_t __xalloc_size; __builtin_mul_overflow (n, s, &__xalloc_size); })) + +/* Other compilers use integer division; this may be slower but is + more portable. */ #else -# define xalloc_oversized(n, s) \ - ((size_t) (sizeof (ptrdiff_t) <= sizeof (size_t) ? -1 : -2) / (s) < (n)) +# define xalloc_oversized(n, s) __xalloc_oversized (n, s) #endif #endif /* !XALLOC_OVERSIZED_H_ */ |