>From 3c20784ac87d0f0748a86f3bc6f06e18694658da Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Fri, 14 Apr 2017 17:38:58 -0700 Subject: [PATCH 1/2] intprops: port to Oracle Studio 12.3 x86 Problem reported by Gavin Smith in: http://lists.gnu.org/archive/html/bug-gnulib/2017-04/msg00049.html * lib/intprops.h (_GL_INT_OP_WRAPV_VIA_UNSIGNED): Convert unsigned to signed via the usual rather than the standard way, to avoid a compiler bug in Oracle Studio 12.3 x86. --- ChangeLog | 9 +++++++++ lib/intprops.h | 41 +++++++++++++++++++++++++++++------------ 2 files changed, 38 insertions(+), 12 deletions(-) diff --git a/ChangeLog b/ChangeLog index ae1a8bd..97d1e59 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2017-04-14 Paul Eggert + + intprops: port to Oracle Studio 12.3 x86 + Problem reported by Gavin Smith in: + http://lists.gnu.org/archive/html/bug-gnulib/2017-04/msg00049.html + * lib/intprops.h (_GL_INT_OP_WRAPV_VIA_UNSIGNED): + Convert unsigned to signed via the usual rather than the standard way, + to avoid a compiler bug in Oracle Studio 12.3 x86. + 2017-04-08 Paul Eggert getopt: prefer - to _ in new file names diff --git a/lib/intprops.h b/lib/intprops.h index eb06b69..220b509 100644 --- a/lib/intprops.h +++ b/lib/intprops.h @@ -442,17 +442,34 @@ verify (TYPE_WIDTH (unsigned int) == UINT_WIDTH); ((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 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))) + ? (*(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)) + +/* Return A B, where the operation is given by OP. Return the + low-order bits of the mathematically-correct answer. Use the + unsigned type UT for calculation to avoid undefined behavior on + signed integer overflow. Assume that conversion to the result type + T yields the low-order bits in the usual way. UT and T are the + same width, T is two's complement, and there is no padding or trap + representations. + + According to the C standard, converting UT to T yields an + implementation-defined result or signal for values outside T's range. + So, the standard way to convert UT to T is to subtract TMIN from + greater-than-TMAX values before converting them to T, and to add + TMIN afterwards, where TMIN and TMAX are T's extrema. + However, in practice there is no need to subtract and add TMIN. + E.g., GCC converts to signed integers in the usual way; see: + https://gcc.gnu.org/onlinedocs/gcc/Integers-implementation.html + All other known C compilers are similar to GCC in this respect. + Furthermore, Oracle Studio Studio 12.3 x86 has a bug when + implementing the standard way; see: + http://lists.gnu.org/archive/html/bug-gnulib/2017-04/msg00049.html + + So, implement this operation in the usual way rather than in + the standard way. */ + +#define _GL_INT_OP_WRAPV_VIA_UNSIGNED(a, b, op, ut, t) \ + ((t) ((ut) (a) op (ut) (b))) #endif /* _GL_INTPROPS_H */ -- 2.9.3