emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Emacs-diffs] master aa1411b: Update from Gnulib


From: Paul Eggert
Subject: [Emacs-diffs] master aa1411b: Update from Gnulib
Date: Wed, 14 Aug 2019 21:14:00 -0400 (EDT)

branch: master
commit aa1411b20fba73ca6fde90fc9ce62cc8a854bf20
Author: Paul Eggert <address@hidden>
Commit: Paul Eggert <address@hidden>

    Update from Gnulib
    
    This incorporates:
    2019-08-14 intprops: pacify picky GCC
    2019-08-14 intprops: support unsigned *_WRAPV results
    2019-08-12 verify: improve diagnostic quality in recent GCC
    * lib/intprops.h, lib/verify.h:     Copy from Gnulib.
---
 lib/intprops.h | 156 ++++++++++++++++++++++++++++++++++++++++++++++-----------
 lib/verify.h   |  33 ++++++------
 2 files changed, 147 insertions(+), 42 deletions(-)

diff --git a/lib/intprops.h b/lib/intprops.h
index 1a44ae5..d1785ac 100644
--- a/lib/intprops.h
+++ b/lib/intprops.h
@@ -111,8 +111,8 @@
    Subtract 1 for the sign bit if T is signed, and then add 1 more for
    a minus sign if needed.
 
-   Because _GL_SIGNED_TYPE_OR_EXPR sometimes returns 0 when its argument is
-   signed, this macro may overestimate the true bound by one byte when
+   Because _GL_SIGNED_TYPE_OR_EXPR sometimes returns 1 when its argument is
+   unsigned, this macro may overestimate the true bound by one byte when
    applied to unsigned types of size 2, 4, 16, ... bytes.  */
 #define INT_STRLEN_BOUND(t)                                     \
   (INT_BITS_STRLEN_BOUND (TYPE_WIDTH (t) - _GL_SIGNED_TYPE_OR_EXPR (t)) \
@@ -281,7 +281,9 @@
 
    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 also store the low-order bits of the answer.
+   The INT_<op>_WRAPV macros compute the low-order bits of the sum,
+   difference, and product of two C integers, and return 1 if these
+   low-order bits are not numerically correct.
    These macros work correctly on all known practical hosts, and do not rely
    on undefined behavior due to signed arithmetic overflow.
 
@@ -309,9 +311,12 @@
    arguments should not have side effects.
 
    The WRAPV macros are not constant expressions.  They support only
-   +, binary -, and *.  The result type must be signed.
+   +, 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.
 
-   These macros are tuned for their last argument being a constant.
+   These macros are tuned for their last input 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.  */
@@ -348,11 +353,21 @@
 /* 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)
+  _GL_INT_OP_WRAPV (a, b, r, +, __builtin_add_overflow, \
+                    _GL_INT_ADD_RANGE_OVERFLOW)
 #define INT_SUBTRACT_WRAPV(a, b, r) \
-  _GL_INT_OP_WRAPV (a, b, r, -, __builtin_sub_overflow, INT_SUBTRACT_OVERFLOW)
+  _GL_INT_OP_WRAPV (a, b, r, -, __builtin_sub_overflow, \
+                    _GL_INT_SUBTRACT_RANGE_OVERFLOW)
 #define INT_MULTIPLY_WRAPV(a, b, r) \
-  _GL_INT_OP_WRAPV (a, b, r, *, __builtin_mul_overflow, INT_MULTIPLY_OVERFLOW)
+   _GL_INT_OP_WRAPV (a, b, r, *, _GL_BUILTIN_MUL_OVERFLOW, \
+                     _GL_INT_MULTIPLY_RANGE_OVERFLOW)
+
+/* Like __builtin_mul_overflow, but work around GCC bug 91450.  */
+#define _GL_BUILTIN_MUL_OVERFLOW(a, b, r) \
+  ((!_GL_SIGNED_TYPE_OR_EXPR (*(r)) && EXPR_SIGNED (a) && EXPR_SIGNED (b) \
+    && _GL_INT_MULTIPLY_RANGE_OVERFLOW (a, b, 0, (__typeof__ (*(r))) -1)) \
+   ? ((void) __builtin_mul_overflow (a, b, r), 1) \
+   : __builtin_mul_overflow (a, b, r))
 
 /* Nonzero if this compiler has GCC bug 68193 or Clang bug 25390.  See:
    https://gcc.gnu.org/bugzilla/show_bug.cgi?id=68193
@@ -379,41 +394,79 @@
      signed char: \
        _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned int, \
                         signed char, SCHAR_MIN, SCHAR_MAX), \
+     unsigned char: \
+       _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned int, \
+                        unsigned char, 0, UCHAR_MAX), \
      short int: \
        _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned int, \
                         short int, SHRT_MIN, SHRT_MAX), \
+     unsigned short int: \
+       _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned int, \
+                        unsigned short int, 0, USHRT_MAX), \
      int: \
        _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned int, \
                         int, INT_MIN, INT_MAX), \
+     unsigned int: \
+       _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned int, \
+                        unsigned int, 0, UINT_MAX), \
      long int: \
        _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned long int, \
                         long int, LONG_MIN, LONG_MAX), \
+     unsigned long int: \
+       _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned long int, \
+                        unsigned long int, 0, ULONG_MAX), \
      long long int: \
        _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned long long int, \
-                        long long int, LLONG_MIN, LLONG_MAX)))
+                        long long int, LLONG_MIN, LLONG_MAX),
+     unsigned long long int: \
+       _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.  */
 # 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 int, \
-                       signed char, SCHAR_MIN, SCHAR_MAX) \
+    ? (_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)) \
     : sizeof *(r) == sizeof (short int) \
-    ? _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned int, \
-                       short int, SHRT_MIN, SHRT_MAX) \
+    ? (_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)) \
     : sizeof *(r) == sizeof (int) \
-    ? _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned int, \
-                       int, INT_MIN, INT_MAX) \
+    ? (EXPR_SIGNED (*(r)) \
+       ? _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned int, \
+                          int, INT_MIN, INT_MAX) \
+       : _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned int, \
+                          unsigned int, 0, UINT_MAX)) \
     : _GL_INT_OP_WRAPV_LONGISH(a, b, r, op, overflow))
 # ifdef LLONG_MAX
 #  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))
+     ? (EXPR_SIGNED (*(r)) \
+        ? _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 int, \
+                           unsigned long int, 0, ULONG_MAX)) \
+     : (EXPR_SIGNED (*(r)) \
+        ? _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned long long int, \
+                           long long int, LLONG_MIN, LLONG_MAX) \
+        : _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned long long int, \
+                           unsigned long long int, 0, ULLONG_MAX)))
 # else
 #  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)
+    (EXPR_SIGNED (*(r)) \
+     ? _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 int, \
+                        unsigned long int, 0, ULONG_MAX))
 # endif
 #endif
 
@@ -422,13 +475,7 @@
    overflow problems.  *R's type is T, with extrema 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))) \
+  (overflow (a, b, tmin, tmax) \
    ? (*(r) = _GL_INT_OP_WRAPV_VIA_UNSIGNED (a, b, op, ut, t), 1) \
    : (*(r) = _GL_INT_OP_WRAPV_VIA_UNSIGNED (a, b, op, ut, t), 0))
 
@@ -452,4 +499,57 @@
 #define _GL_INT_OP_WRAPV_VIA_UNSIGNED(a, b, op, ut, t) \
   ((t) ((ut) (a) op (ut) (b)))
 
+/* Return true if the numeric values A + B, A - B, A * B fall outside
+   the range TMIN..TMAX.  Arguments should be integer expressions
+   without side effects.  TMIN should be signed and nonpositive.
+   TMAX should be positive, and should be signed unless TMIN is zero.  */
+#define _GL_INT_ADD_RANGE_OVERFLOW(a, b, tmin, tmax) \
+  ((b) < 0 \
+   ? (((tmin) \
+       ? ((EXPR_SIGNED (_GL_INT_CONVERT (a, (tmin) - (b))) || (b) < (tmin)) \
+          && (a) < (tmin) - (b)) \
+       : (a) <= -1 - (b)) \
+      || ((EXPR_SIGNED (a) ? 0 <= (a) : (tmax) < (a)) && (tmax) < (a) + (b))) \
+   : (a) < 0 \
+   ? (((tmin) \
+       ? ((EXPR_SIGNED (_GL_INT_CONVERT (b, (tmin) - (a))) || (a) < (tmin)) \
+          && (b) < (tmin) - (a)) \
+       : (b) <= -1 - (a)) \
+      || ((EXPR_SIGNED (_GL_INT_CONVERT (a, b)) || (tmax) < (b)) \
+          && (tmax) < (a) + (b))) \
+   : (tmax) < (b) || (tmax) - (b) < (a))
+#define _GL_INT_SUBTRACT_RANGE_OVERFLOW(a, b, tmin, tmax) \
+  (((a) < 0) == ((b) < 0) \
+   ? ((a) < (b) \
+      ? !(tmin) || -1 - (tmin) < (b) - (a) - 1 \
+      : (tmax) < (a) - (b)) \
+   : (a) < 0 \
+   ? ((!EXPR_SIGNED (_GL_INT_CONVERT ((a) - (tmin), b)) && (a) - (tmin) < 0) \
+      || (a) - (tmin) < (b)) \
+   : ((! (EXPR_SIGNED (_GL_INT_CONVERT (tmax, b)) \
+          && EXPR_SIGNED (_GL_INT_CONVERT ((tmax) + (b), a))) \
+       && (tmax) <= -1 - (b)) \
+      || (tmax) + (b) < (a)))
+#define _GL_INT_MULTIPLY_RANGE_OVERFLOW(a, b, tmin, tmax) \
+  ((b) < 0 \
+   ? ((a) < 0 \
+      ? (EXPR_SIGNED (_GL_INT_CONVERT (tmax, b)) \
+         ? (a) < (tmax) / (b) \
+         : ((INT_NEGATE_OVERFLOW (b) \
+             ? _GL_INT_CONVERT (b, tmax) >> (TYPE_WIDTH (b) - 1) \
+             : (tmax) / -(b)) \
+            <= -1 - (a))) \
+      : INT_NEGATE_OVERFLOW (_GL_INT_CONVERT (b, tmin)) && (b) == -1 \
+      ? (EXPR_SIGNED (a) \
+        ? 0 < (a) + (tmin) \
+        : 0 < (a) && -1 - (tmin) < (a) - 1) \
+      : (tmin) / (b) < (a)) \
+   : (b) == 0 \
+   ? 0 \
+   : ((a) < 0 \
+      ? (INT_NEGATE_OVERFLOW (_GL_INT_CONVERT (a, tmin)) && (a) == -1 \
+         ? (EXPR_SIGNED (b) ? 0 < (b) + (tmin) : -1 - (tmin) < (b) - 1) \
+         : (tmin) / (a) < (b)) \
+      : (tmax) / (b) < (a)))
+
 #endif /* _GL_INTPROPS_H */
diff --git a/lib/verify.h b/lib/verify.h
index 9b8e1ed..afdc1ad 100644
--- a/lib/verify.h
+++ b/lib/verify.h
@@ -175,9 +175,11 @@
 #define _GL_GENSYM(prefix) _GL_CONCAT (prefix, _GL_COUNTER)
 
 /* Verify requirement R at compile-time, as an integer constant expression
-   that returns 1.  If R is false, fail at compile-time.  */
+   that returns 1.  If R is false, fail at compile-time, preferably
+   with a diagnostic that includes the string-literal DIAGNOSTIC.  */
 
-#define _GL_VERIFY_TRUE(R) (!!sizeof (_GL_VERIFY_TYPE (R)))
+#define _GL_VERIFY_TRUE(R, DIAGNOSTIC) \
+   (!!sizeof (_GL_VERIFY_TYPE (R, DIAGNOSTIC)))
 
 #ifdef __cplusplus
 # if !GNULIB_defined_struct__gl_verify_type
@@ -187,15 +189,16 @@ template <int w>
   };
 #  define GNULIB_defined_struct__gl_verify_type 1
 # endif
-# define _GL_VERIFY_TYPE(R) _gl_verify_type<(R) ? 1 : -1>
-#elif defined _GL_HAVE__STATIC_ASSERT1
-# define _GL_VERIFY_TYPE(R) \
+# define _GL_VERIFY_TYPE(R, DIAGNOSTIC) \
+    _gl_verify_type<(R) ? 1 : -1>
+#elif defined _GL_HAVE__STATIC_ASSERT
+# define _GL_VERIFY_TYPE(R, DIAGNOSTIC) \
     struct {                                   \
-      _Static_assert (R); \
+      _Static_assert (R, DIAGNOSTIC);          \
       int _gl_dummy;                          \
     }
 #else
-# define _GL_VERIFY_TYPE(R)                                             \
+# define _GL_VERIFY_TYPE(R, DIAGNOSTIC) \
     struct { unsigned int _gl_verify_error_if_negative: (R) ? 1 : -1; }
 #endif
 
@@ -214,7 +217,7 @@ template <int w>
 #else
 # define _GL_VERIFY(R, DIAGNOSTIC, ...)                                \
     extern int (*_GL_GENSYM (_gl_verify_function) (void))             \
-      [_GL_VERIFY_TRUE (R)]
+      [_GL_VERIFY_TRUE (R, DIAGNOSTIC)]
 #endif
 
 /* _GL_STATIC_ASSERT_H is defined if this code is copied into assert.h.  */
@@ -242,17 +245,19 @@ template <int w>
 /* Verify requirement R at compile-time.  Return the value of the
    expression E.  */
 
-#define verify_expr(R, E) (_GL_VERIFY_TRUE (R) ? (E) : (E))
+#define verify_expr(R, E) \
+   (_GL_VERIFY_TRUE (R, "verify_expr (" #R ", " #E ")") ? (E) : (E))
 
 /* Verify requirement R at compile-time, as a declaration without a
    trailing ';'.  verify (R) acts like static_assert (R) except that
-   it is portable to C11/C++14 and earlier, and its name is shorter
-   and may be more convenient.  */
+   it is portable to C11/C++14 and earlier, it can issue better
+   diagnostics, and its name is shorter and may be more convenient.  */
 
-#ifdef _GL_HAVE__STATIC_ASSERT1
-# define verify(R) _Static_assert (R)
-#else
+#ifdef __PGI
+/* PGI barfs if R is long.  */
 # define verify(R) _GL_VERIFY (R, "verify (...)", -)
+#else
+# define verify(R) _GL_VERIFY (R, "verify (" #R ")", -)
 #endif
 
 #ifndef __has_builtin



reply via email to

[Prev in Thread] Current Thread [Next in Thread]