>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