From patchwork Thu Oct 31 18:25:26 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Adhemerval Zanella X-Patchwork-Id: 178216 Delivered-To: patch@linaro.org Received: by 2002:a92:409a:0:0:0:0:0 with SMTP id d26csp3227461ill; Thu, 31 Oct 2019 11:25:56 -0700 (PDT) X-Google-Smtp-Source: APXvYqyG4tPhEYt5RR7PK51juHjYxaH6ocz7NUqCW72ubFF6a8+8hM785x5oo/m+pbC/YBbig+Qf X-Received: by 2002:aa7:db82:: with SMTP id u2mr7751582edt.256.1572546356179; Thu, 31 Oct 2019 11:25:56 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1572546356; cv=none; d=google.com; s=arc-20160816; b=J5+0h+rCfZNZXu9b+KBNtiF3cHuqWSRnGEPVIQKv9+++4aun2D2rBOpQ86DDa7pAfA zu9a6PJrTsZWMDdNmkiArIfs4EGHXokyariB6SYUHYPVsiaBx0XM7dv7auf32FElN22y kpHXCmLfYV9IKb0qqoWE7fUfbOIt7FbhycI84ASIFSHDe4s/q8/G1VQa4LfVoLZ4Gk1r fPfB9y4NfaaEfQZnPU+SWkNR57pUYjObPba2USp/AUkGltBdOCnuQdbFLA2yNgA7nl4G kwdypvxjdn56/V2Z+QBq3laY8kyT5DqBG9YN9rOu6mWtvKjoUnji5AHw32c4wozaWXTt uftQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=message-id:date:subject:to:from:dkim-signature:delivered-to:sender :list-help:list-post:list-archive:list-subscribe:list-unsubscribe :list-id:precedence:mailing-list:dkim-signature:domainkey-signature; bh=iYqUYwHhvtQVAzmzk+QTHnvBT6txVmXOjmBnDRD5TK0=; b=x9aKQN4Lk6tLeMVnDJDfyC5SXTXOCbG3qbN2tvKenyeNCC8ZAgIO4/mNJilBNeMzu3 fXbC3q21wlXV1oIavJVOKKe0GrZE5k3WNA4G+fXIxWndsSl4fEnkOiaw+3CvKIxzSGz9 D7U/PdH265xvVNyjOk++HohSWJFwzVC9mQNjx3xtKb+ZX30Ey+GNwJMhHXJc/3kCAQwg qZvb0cL/9iN7FT13t9vECcvZZdED3/jO/i+6p5sWLP+jsTBqMN90VQk9JBkmDuN57cZq XP94Idwmyp7DU3FWEHP3XPwRBfrpaHeH1lRkHz/IemLsI8+pwTJsve/XOJlOWZ6lpOmL j7Yg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@sourceware.org header.s=default header.b=M20WNH5P; dkim=pass header.i=@linaro.org header.s=google header.b=wR8KWKk3; spf=pass (google.com: domain of libc-alpha-return-106507-patch=linaro.org@sourceware.org designates 209.132.180.131 as permitted sender) smtp.mailfrom="libc-alpha-return-106507-patch=linaro.org@sourceware.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from sourceware.org (server1.sourceware.org. [209.132.180.131]) by mx.google.com with ESMTPS id l20si4512474ejz.355.2019.10.31.11.25.55 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 31 Oct 2019 11:25:56 -0700 (PDT) Received-SPF: pass (google.com: domain of libc-alpha-return-106507-patch=linaro.org@sourceware.org designates 209.132.180.131 as permitted sender) client-ip=209.132.180.131; Authentication-Results: mx.google.com; dkim=pass header.i=@sourceware.org header.s=default header.b=M20WNH5P; dkim=pass header.i=@linaro.org header.s=google header.b=wR8KWKk3; spf=pass (google.com: domain of libc-alpha-return-106507-patch=linaro.org@sourceware.org designates 209.132.180.131 as permitted sender) smtp.mailfrom="libc-alpha-return-106507-patch=linaro.org@sourceware.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org DomainKey-Signature: a=rsa-sha1; c=nofws; d=sourceware.org; h=list-id :list-unsubscribe:list-subscribe:list-archive:list-post :list-help:sender:from:to:subject:date:message-id; q=dns; s= default; b=LZkHkkUKOQN6QtWl4zLt0/Zr/boA+8dmxowV9YdKNUDQClK6hdPrr lR58/LrShd4ZmNgJhpI7SzI4NO7s/5KQSe3XqQrPVxC3fyD+lEB64DhZexwX4S3Q H95WCJgnb0f779RQPgdIP31hmk/2MZPMIRmmwBeiZ0XgLB3GjixhPs= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=sourceware.org; h=list-id :list-unsubscribe:list-subscribe:list-archive:list-post :list-help:sender:from:to:subject:date:message-id; s=default; bh=QPFJ+yZ+YDK7ekMRbMP6no3cSyg=; b=M20WNH5PNlQXpKeiSn576aRCYi0O 2EPYKbbaM3KF9Sb5urVXJpfszkejxPEE5/S0YOnOVWvK7Qidj2KcIfwQzjukoqeQ j/2HKwSbjr6FFa6ab4GhWTXMnk0lMwhR/18wMDoCyPGCOKMPE1xslcR+0OK3VbcT MUj0Jh47ZRme7sE= Received: (qmail 25672 invoked by alias); 31 Oct 2019 18:25:38 -0000 Mailing-List: contact libc-alpha-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: libc-alpha-owner@sourceware.org Delivered-To: mailing list libc-alpha@sourceware.org Received: (qmail 25605 invoked by uid 89); 31 Oct 2019 18:25:38 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-21.6 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, KAM_SHORT, RCVD_IN_DNSWL_NONE, SPF_PASS autolearn=ham version=3.3.1 spammy= X-HELO: mail-qk1-f194.google.com DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:subject:date:message-id; bh=iYqUYwHhvtQVAzmzk+QTHnvBT6txVmXOjmBnDRD5TK0=; b=wR8KWKk3PjqXN+gAMiG1QaefzU5xR/yesnDACkue6fJxaiFIManAJ4RnCwTXmCb6xg W5JX+bt6VCkHEA4lhXqeVcktCQaCYL4cygzb4C6/L1zN/Pww5RhZK9U76EMRDg+yWlkH O+w3FockA9U9iO4BzVarih33f+5aWU6eK5msVBmMA71PKEzqpYPZNf6oO0k855aHLUu2 JHC1AE8GclBkFuYOohSW8P41S2hDgM4kQ+ClO1JjpYYK5b9cwWbh/c8z0zx7Y40eKkZg +a4Gii/f3Tr+2A6b5me3K0wE1atvUY7Rx/ovZYlOLMXHWpcteJNHhFS10bNFioQFkYlU F49w== Return-Path: From: Adhemerval Zanella To: libc-alpha@sourceware.org Subject: [PATCH 1/2] Sync intprops.h with gnulib Date: Thu, 31 Oct 2019 15:25:26 -0300 Message-Id: <20191031182527.26933-1-adhemerval.zanella@linaro.org> It sync with gnulib commit f5756b919addb9e8ce03f4e61a10e4fcff14874a. --- include/intprops.h | 214 +++++++++++++++++++++++++++++++++++---------- 1 file changed, 169 insertions(+), 45 deletions(-) -- 2.17.1 diff --git a/include/intprops.h b/include/intprops.h index 140f6d2a4b..bc7e950a0e 100644 --- a/include/intprops.h +++ b/include/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)) \ @@ -220,14 +220,26 @@ ? (a) < (min) >> (b) \ : (max) >> (b) < (a)) -/* True if __builtin_add_overflow (A, B, P) works when P is non-null. */ +/* True if __builtin_add_overflow (A, B, P) and __builtin_sub_overflow + (A, B, P) work when P is non-null. */ #if 5 <= __GNUC__ && !defined __ICC -# define _GL_HAS_BUILTIN_OVERFLOW 1 +# define _GL_HAS_BUILTIN_ADD_OVERFLOW 1 +#elif defined __has_builtin +# define _GL_HAS_BUILTIN_ADD_OVERFLOW __has_builtin (__builtin_add_overflow) #else -# define _GL_HAS_BUILTIN_OVERFLOW 0 +# define _GL_HAS_BUILTIN_ADD_OVERFLOW 0 #endif -/* True if __builtin_add_overflow_p (A, B, C) works. */ +/* True if __builtin_mul_overflow (A, B, P) works when P is non-null. */ +#ifdef __clang__ +/* Work around Clang bug . */ +# define _GL_HAS_BUILTIN_MUL_OVERFLOW 0 +#else +# define _GL_HAS_BUILTIN_MUL_OVERFLOW _GL_HAS_BUILTIN_ADD_OVERFLOW +#endif + +/* True if __builtin_add_overflow_p (A, B, C) works, and similarly for + __builtin_mul_overflow_p and __builtin_mul_overflow_p. */ #define _GL_HAS_BUILTIN_OVERFLOW_P (7 <= __GNUC__) /* The _GL*_OVERFLOW macros have the same restrictions as the @@ -281,7 +293,9 @@ The INT__OVERFLOW macros return 1 if the corresponding C operators might not yield numerically correct answers due to arithmetic overflow. - The INT__WRAPV macros also store the low-order bits of the answer. + The INT__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 +323,11 @@ 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 *. 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 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. */ @@ -347,19 +363,33 @@ /* 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) +#if _GL_HAS_BUILTIN_ADD_OVERFLOW +# define INT_ADD_WRAPV(a, b, r) __builtin_add_overflow (a, b, r) +# define INT_SUBTRACT_WRAPV(a, b, r) __builtin_sub_overflow (a, b, r) +#else +# define INT_ADD_WRAPV(a, b, r) \ + _GL_INT_OP_WRAPV (a, b, r, +, _GL_INT_ADD_RANGE_OVERFLOW) +# define INT_SUBTRACT_WRAPV(a, b, r) \ + _GL_INT_OP_WRAPV (a, b, r, -, _GL_INT_SUBTRACT_RANGE_OVERFLOW) +#endif +#if _GL_HAS_BUILTIN_MUL_OVERFLOW +/* Work around GCC bug 91450. */ +# define INT_MULTIPLY_WRAPV(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)) +#else +# define INT_MULTIPLY_WRAPV(a, b, r) \ + _GL_INT_OP_WRAPV (a, b, r, *, _GL_INT_MULTIPLY_RANGE_OVERFLOW) +#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. */ + warnings for _Generic. This matters only for compilers that + lack relevant builtins. */ #if __GNUC__ # define _GL__GENERIC_BOGUS 1 #else @@ -367,53 +397,100 @@ #endif /* Store the low-order bits of A 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 _GL_HAS_BUILTIN_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) \ + the operation and OVERFLOW the overflow predicate. Return 1 if the + result overflows. See above for restrictions. */ +#if 201112 <= __STDC_VERSION__ && !_GL__GENERIC_BOGUS +# define _GL_INT_OP_WRAPV(a, b, r, op, overflow) \ (_Generic \ (*(r), \ 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, 0, ULLONG_MAX))) #else -# define _GL_INT_OP_WRAPV(a, b, r, op, builtin, overflow) \ +/* Store the low-order bits of A 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, overflow) \ (sizeof *(r) == sizeof (signed char) \ - ? _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned int, \ - signed char, SCHAR_MIN, SCHAR_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_INT_OP_CALC (a, b, r, op, overflow, unsigned int, \ - short int, SHRT_MIN, SHRT_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) \ - ? _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 +499,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 +523,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 */