]> code.delx.au - gnu-emacs/blobdiff - lib/intprops.h
Prevent bar cursor overwriting next glyph (bug#16856)
[gnu-emacs] / lib / intprops.h
index 4441f1c294e7215db3aabdcf76825016b9406781..e1fce5c96a1e9b7ed215822c98e834552e25dfb7 100644 (file)
@@ -1,10 +1,10 @@
 /* intprops.h -- properties of integer types
 
-   Copyright (C) 2001-2005, 2009-2015 Free Software Foundation, Inc.
+   Copyright (C) 2001-2016 Free Software Foundation, Inc.
 
-   This program is free software: you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 3 of the License, or
+   This program is free software: you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published
+   by the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
 
    This program is distributed in the hope that it will be useful,
@@ -21,9 +21,9 @@
 #define _GL_INTPROPS_H
 
 #include <limits.h>
+#include <verify.h>
 
-/* Return an integer value, converted to the same type as the integer
-   expression E after integer type promotion.  V is the unconverted value.  */
+/* Return a value with the common real type of E and V and the value of V.  */
 #define _GL_INT_CONVERT(e, v) (0 * (e) + (v))
 
 /* Act like _GL_INT_CONVERT (E, -V) but work around a bug in IRIX 6.5 cc; see
    an integer.  */
 #define TYPE_IS_INTEGER(t) ((t) 1.5 == 1)
 
-/* True if negative values of the signed integer type T use two's
-   complement, ones' complement, or signed magnitude representation,
-   respectively.  Much GNU code assumes two's complement, but some
-   people like to be portable to all possible C hosts.  */
-#define TYPE_TWOS_COMPLEMENT(t) ((t) ~ (t) 0 == (t) -1)
-#define TYPE_ONES_COMPLEMENT(t) ((t) ~ (t) 0 == 0)
-#define TYPE_SIGNED_MAGNITUDE(t) ((t) ~ (t) 0 < (t) -1)
-
-/* True if the signed integer expression E uses two's complement.  */
-#define _GL_INT_TWOS_COMPLEMENT(e) (~ _GL_INT_CONVERT (e, 0) == -1)
-
-/* True if the arithmetic type T is signed.  */
+/* True if the real type T is signed.  */
 #define TYPE_SIGNED(t) (! ((t) 0 < (t) -1))
 
-/* Return 1 if the integer expression E, after integer promotion, has
-   a signed type.  */
-#define _GL_INT_SIGNED(e) (_GL_INT_NEGATE_CONVERT (e, 1) < 0)
+/* Return 1 if the real expression E, after promotion, has a
+   signed or floating type.  */
+#define EXPR_SIGNED(e) (_GL_INT_NEGATE_CONVERT (e, 1) < 0)
 
 
-/* Minimum and maximum values for integer types and expressions.  These
-   macros have undefined behavior if T is signed and has padding bits.
-   If this is a problem for you, please let us know how to fix it for
-   your host.  */
+/* Minimum and maximum values for integer types and expressions.  */
 
 /* The maximum and minimum values for the integer type T.  */
-#define TYPE_MINIMUM(t)                                                 \
-  ((t) (! TYPE_SIGNED (t)                                               \
-        ? (t) 0                                                         \
-        : TYPE_SIGNED_MAGNITUDE (t)                                     \
-        ? ~ (t) 0                                                       \
-        : ~ TYPE_MAXIMUM (t)))
+#define TYPE_MINIMUM(t) ((t) ~ TYPE_MAXIMUM (t))
 #define TYPE_MAXIMUM(t)                                                 \
   ((t) (! TYPE_SIGNED (t)                                               \
         ? (t) -1                                                        \
 /* The maximum and minimum values for the type of the expression E,
    after integer promotion.  E should not have side effects.  */
 #define _GL_INT_MINIMUM(e)                                              \
-  (_GL_INT_SIGNED (e)                                                   \
-   ? - _GL_INT_TWOS_COMPLEMENT (e) - _GL_SIGNED_INT_MAXIMUM (e)         \
+  (EXPR_SIGNED (e)                                                      \
+   ? ~ _GL_SIGNED_INT_MAXIMUM (e)                                       \
    : _GL_INT_CONVERT (e, 0))
 #define _GL_INT_MAXIMUM(e)                                              \
-  (_GL_INT_SIGNED (e)                                                   \
+  (EXPR_SIGNED (e)                                                      \
    ? _GL_SIGNED_INT_MAXIMUM (e)                                         \
    : _GL_INT_NEGATE_CONVERT (e, 1))
 #define _GL_SIGNED_INT_MAXIMUM(e)                                       \
   (((_GL_INT_CONVERT (e, 1) << (sizeof ((e) + 0) * CHAR_BIT - 2)) - 1) * 2 + 1)
 
+/* This include file assumes that signed types are two's complement without
+   padding bits; the above macros have undefined behavior otherwise.
+   If this is a problem for you, please let us know how to fix it for your host.
+   As a sanity check, test the assumption for some signed types that
+   <limits.h> bounds.  */
+verify (TYPE_MINIMUM (signed char) == SCHAR_MIN);
+verify (TYPE_MAXIMUM (signed char) == SCHAR_MAX);
+verify (TYPE_MINIMUM (short int) == SHRT_MIN);
+verify (TYPE_MAXIMUM (short int) == SHRT_MAX);
+verify (TYPE_MINIMUM (int) == INT_MIN);
+verify (TYPE_MAXIMUM (int) == INT_MAX);
+verify (TYPE_MINIMUM (long int) == LONG_MIN);
+verify (TYPE_MAXIMUM (long int) == LONG_MAX);
+#ifdef LLONG_MAX
+verify (TYPE_MINIMUM (long long int) == LLONG_MIN);
+verify (TYPE_MAXIMUM (long long int) == LLONG_MAX);
+#endif
 
-/* Return 1 if the __typeof__ keyword works.  This could be done by
+/* Does the __typeof__ keyword work?  This could be done by
    'configure', but for now it's easier to do it by hand.  */
 #if (2 <= __GNUC__ || defined __IBM__TYPEOF__ \
      || (0x5110 <= __SUNPRO_C && !__STDC__))
    ? (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                                     \
 
    The INT_<op>_OVERFLOW macros return 1 if the corresponding C operators
    might not yield numerically correct answers due to arithmetic overflow.
-   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.
-
+   The INT_<op>_WRAPV macros also store the low-order bits of the answer.
    These macros work correctly on all known practical hosts, and do not rely
    on undefined behavior due to signed arithmetic overflow.
 
-   Example usage:
+   Example usage, assuming A and B are long int:
 
-     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");
+     if (INT_MULTIPLY_OVERFLOW (a, b))
+       printf ("result would overflow\n");
+     else
+       printf ("result is %ld (no overflow)\n", a * b);
 
-     enum {
-       INT_PRODUCTS_FIT_IN_LONG
-         = ! INT_CONST_MULTIPLY_OVERFLOW ((long int) INT_MIN, INT_MIN)
-     };
+   Example usage with WRAPV flavor:
+
+     long int result;
+     bool overflow = INT_MULTIPLY_WRAPV (a, b, &result);
+     printf ("result is %ld (%s)\n", result,
+             overflow ? "after overflow" : "no overflow");
 
    Restrictions on these macros:
 
    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.
+   The WRAPV macros are not constant expressions.  They support only
+   +, binary -, and *.  The result type must be signed.
 
    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_CONST_ADD_OVERFLOW(a, b) \
+#define INT_ADD_OVERFLOW(a, b) \
   _GL_BINARY_OP_OVERFLOW (a, b, _GL_ADD_OVERFLOW)
-#define INT_CONST_SUBTRACT_OVERFLOW(a, b) \
+#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))
-#define INT_CONST_MULTIPLY_OVERFLOW(a, b) \
+#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) \
   _GL_BINARY_OP_OVERFLOW (a, b, _GL_DIVIDE_OVERFLOW)
                       _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))
+/* 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)
+#define INT_SUBTRACT_WRAPV(a, b, r) \
+  _GL_INT_OP_WRAPV (a, b, r, -, __builtin_sub_overflow, INT_SUBTRACT_OVERFLOW)
+#define INT_MULTIPLY_WRAPV(a, b, r) \
+  _GL_INT_OP_WRAPV (a, b, r, *, __builtin_mul_overflow, INT_MULTIPLY_OVERFLOW)
+
+#ifndef __has_builtin
+# define __has_builtin(x) 0
+#endif
+
+/* Nonzero if this compiler has GCC bug 68193 or Clang bug 25390.  See:
+   https://gcc.gnu.org/bugzilla/show_bug.cgi?id=68193
+   https://llvm.org/bugs/show_bug.cgi?id=25390
+   For now, assume all versions of GCC-like compilers generate bogus
+   warnings for _Generic.  This matters only for older compilers that
+   lack __builtin_add_overflow.  */
+#if __GNUC__
+# define _GL__GENERIC_BOGUS 1
 #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
+# define _GL__GENERIC_BOGUS 0
+#endif
 
+/* 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
+# define _GL_INT_OP_WRAPV(a, b, r, op, builtin, overflow) \
+   (_Generic \
+    (*(r), \
+     signed char: \
+       _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned char, \
+                        signed char, SCHAR_MIN, SCHAR_MAX), \
+     short int: \
+       _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned short int, \
+                        short int, SHRT_MIN, SHRT_MAX), \
+     int: \
+       _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned int, \
+                        int, INT_MIN, INT_MAX), \
+     long int: \
+       _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned long int, \
+                        long int, LONG_MIN, LONG_MAX), \
+     long long int: \
+       _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned long long int, \
+                        long long int, LLONG_MIN, LLONG_MAX)))
+#else
+# define _GL_INT_OP_WRAPV(a, b, r, op, builtin, overflow) \
+   (sizeof *(r) == sizeof (signed char) \
+    ? _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned char, \
+                       signed char, SCHAR_MIN, SCHAR_MAX) \
+    : sizeof *(r) == sizeof (short int) \
+    ? _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned short int, \
+                       short int, SHRT_MIN, SHRT_MAX) \
+    : sizeof *(r) == sizeof (int) \
+    ? _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned int, \
+                       int, INT_MIN, INT_MAX) \
+    : _GL_INT_OP_WRAPV_LONGISH(a, b, r, op, overflow))
 # 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))
+#  define _GL_INT_OP_WRAPV_LONGISH(a, b, r, op, overflow) \
+    (sizeof *(r) == sizeof (long int) \
+     ? _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned long int, \
+                        long int, LONG_MIN, LONG_MAX) \
+     : _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned long long int, \
+                        long long int, LLONG_MIN, LLONG_MAX))
 # else
-#  define _GL_INT_OP_WRAPV_LONGISH(a, b, op) \
-    _GL_INT_OP_WRAPV_VIA_UNSIGNED (a, b, op, long int)
+#  define _GL_INT_OP_WRAPV_LONGISH(a, b, r, op, overflow) \
+    _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned long int, \
+                     long int, LONG_MIN, LONG_MAX))
 # 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
+/* 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.  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) \
+   : _GL_INT_OP_CALC1 (a, b, r, op, overflow, ut, t, tmin, tmax))
+#define _GL_INT_OP_CALC1(a, b, r, op, overflow, ut, t, tmin, tmax) \
+  ((overflow (a, b) \
+    || (EXPR_SIGNED ((a) op (b)) && ((a) op (b)) < (tmin)) \
+    || (tmax) < ((a) op (b))) \
+   ? (*(r) = _GL_INT_OP_WRAPV_VIA_UNSIGNED (a, b, op, ut, t, tmin, tmax), 1) \
+   : (*(r) = _GL_INT_OP_WRAPV_VIA_UNSIGNED (a, b, op, ut, t, tmin, tmax), 0))
+
+/* Return A <op> B, where the operation is given by OP.  Use the
+   unsigned type UT for calculation to avoid overflow problems.
+   Convert the result to type T without overflow by subtracting TMIN
+   from large values before converting, and adding it afterwards.
+   Compilers can optimize all the operations except OP.  */
+#define _GL_INT_OP_WRAPV_VIA_UNSIGNED(a, b, op, ut, t, tmin, tmax) \
+  (((ut) (a) op (ut) (b)) <= (tmax) \
+   ? (t) ((ut) (a) op (ut) (b)) \
+   : ((t) (((ut) (a) op (ut) (b)) - (tmin)) + (tmin)))
 
 #endif /* _GL_INTPROPS_H */