+2016-04-13 Paul Eggert <eggert@cs.ucla.edu>
+
+ intprops, mktime, strtol: assume two's complement
+ These macros were not portable to every conforming C11 ones'
+ complement platform. It's not worth the hassle of porting to some
+ platforms that use ones' complement or signed magnitude, as such
+ platforms are almost purely theoretical nowadays and porting even
+ to some of them makes the code harder to review for little
+ practical benefit. Problem reported by Florian Weimer in:
+ https://sourceware.org/ml/libc-alpha/2016-04/msg00295.html
+ * lib/intprops.h (TYPE_TWOS_COMPLEMENT, TYPE_ONES_COMPLEMENT)
+ (TYPE_SIGNED_MAGNITUDE, _GL_INT_TWOS_COMPLEMENT):
+ * lib/mktime.c (TYPE_TWOS_COMPLEMENT):
+ * lib/strtol.c (TYPE_TWOS_COMPLEMENT, TYPE_ONES_COMPLEMENT)
+ (TYPE_SIGNED_MAGNITUDE):
+ Remove. All uses rewritten to assume two's complement, which is
+ all we can reasonably test nowadays anyway.
+ * top/maint.mk (_intprops_names): Remove the removed macros.
+
2016-04-11 Paul Eggert <eggert@cs.ucla.edu>
stdint: port to strict C11 left shift
Date Modules Changes
+2016-04-12 intprops The following macros were removed:
+ TYPE_TWOS_COMPLEMENT TYPE_ONES_COMPLEMENT
+ TYPE_SIGNED_MAGNITUDE
+
2015-09-25 c-ctype The following macros were removed:
C_CTYPE_CONSECUTIVE_DIGITS
C_CTYPE_CONSECUTIVE_LOWERCASE
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 real type T is signed. */
#define TYPE_SIGNED(t) (! ((t) 0 < (t) -1))
#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.
+ These macros have undefined behavior for signed types that either
+ have padding bits or do not use two's complement. If this is a
+ problem for you, please let us know how to fix it for your host. */
/* 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 \
after integer promotion. E should not have side effects. */
#define _GL_INT_MINIMUM(e) \
(EXPR_SIGNED (e) \
- ? - _GL_INT_TWOS_COMPLEMENT (e) - _GL_SIGNED_INT_MAXIMUM (e) \
+ ? ~ _GL_SIGNED_INT_MAXIMUM (e) \
: _GL_INT_CONVERT (e, 0))
#define _GL_INT_MAXIMUM(e) \
(EXPR_SIGNED (e) \
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, or if T is an unsigned integer type. */
-#define TYPE_TWOS_COMPLEMENT(t) ((t) ~ (t) 0 == (t) -1)
-
/* True if the arithmetic type T is signed. */
#define TYPE_SIGNED(t) (! ((t) 0 < (t) -1))
-/* The maximum and minimum values for the integer type T. 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. */
-#define TYPE_MINIMUM(t) \
- ((t) (! TYPE_SIGNED (t) \
- ? (t) 0 \
- : ~ TYPE_MAXIMUM (t)))
-#define TYPE_MAXIMUM(t) \
- ((t) (! TYPE_SIGNED (t) \
- ? (t) -1 \
- : ((((t) 1 << (sizeof (t) * CHAR_BIT - 2)) - 1) * 2 + 1)))
+/* Minimum and maximum values for integer types.
+ These macros have undefined behavior for signed types that either
+ have padding bits or do not use two's complement. If this is a
+ problem for you, please let us know how to fix it for your host. */
+
+/* The maximum and minimum values for the integer type T. */
+#define TYPE_MINIMUM(t) ((t) ~ TYPE_MAXIMUM (t))
+#define TYPE_MAXIMUM(t) \
+ ((t) (! TYPE_SIGNED (t) \
+ ? (t) -1 \
+ : ((((t) 1 << (sizeof (t) * CHAR_BIT - 2)) - 1) * 2 + 1)))
#ifndef TIME_T_MIN
# define TIME_T_MIN TYPE_MINIMUM (time_t)
#define TIME_T_MIDPOINT (SHR (TIME_T_MIN + TIME_T_MAX, 1) + 1)
verify (time_t_is_integer, TYPE_IS_INTEGER (time_t));
-verify (twos_complement_arithmetic,
- (TYPE_TWOS_COMPLEMENT (int)
- && TYPE_TWOS_COMPLEMENT (long_int)
- && TYPE_TWOS_COMPLEMENT (time_t)));
#define EPOCH_YEAR 1970
#define TM_YEAR_BASE 1900
/* The extra casts in the following macros work around compiler bugs,
e.g., in Cray C 5.0.3.0. */
-/* 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 arithmetic type T is signed. */
# define TYPE_SIGNED(t) (! ((t) 0 < (t) -1))
-/* The maximum and minimum values for the integer type T. 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. */
-# define TYPE_MINIMUM(t) \
- ((t) (! TYPE_SIGNED (t) \
- ? (t) 0 \
- : TYPE_SIGNED_MAGNITUDE (t) \
- ? ~ (t) 0 \
- : ~ TYPE_MAXIMUM (t)))
-# define TYPE_MAXIMUM(t) \
- ((t) (! TYPE_SIGNED (t) \
- ? (t) -1 \
+/* Minimum and maximum values for integer types.
+ These macros have undefined behavior for signed types that either
+ have padding bits or do not use two's complement. If this is a
+ problem for you, please let us know how to fix it for your host. */
+
+/* The maximum and minimum values for the integer type T. */
+# define TYPE_MINIMUM(t) ((t) ~ TYPE_MAXIMUM (t))
+# define TYPE_MAXIMUM(t) \
+ ((t) (! TYPE_SIGNED (t) \
+ ? (t) -1 \
: ((((t) 1 << (sizeof (t) * CHAR_BIT - 2)) - 1) * 2 + 1)))
# ifndef ULLONG_MAX
time_t might be unsigned. */
verify (TYPE_IS_INTEGER (time_t));
- verify (TYPE_TWOS_COMPLEMENT (int));
/* Destination and source time stamps. */
time_t dst_s = dst_stat->st_mtime;
ASSERT (TYPE_SIGNED (double));
ASSERT (TYPE_SIGNED (long double));
- /* Integer representation. */
- VERIFY (INT_MIN + INT_MAX < 0
- ? (TYPE_TWOS_COMPLEMENT (int)
- && ! TYPE_ONES_COMPLEMENT (int) && ! TYPE_SIGNED_MAGNITUDE (int))
- : (! TYPE_TWOS_COMPLEMENT (int)
- && (TYPE_ONES_COMPLEMENT (int) || TYPE_SIGNED_MAGNITUDE (int))));
+ /* Integer representation. Check that it is two's complement. */
+ VERIFY (INT_MIN + INT_MAX < 0);
/* TYPE_MINIMUM, TYPE_MAXIMUM. */
VERIFY (TYPE_MINIMUM (char) == CHAR_MIN);
{ \
t result; \
ASSERT (INT_##opname##_WRAPV (a, b, &result) == (v)); \
- ASSERT (result == ((v) ? (vres) : ((a) op (b))) \
- || ((v) && !TYPE_TWOS_COMPLEMENT (t))); \
+ ASSERT (result == ((v) ? (vres) : ((a) op (b)))); \
}
#define CHECK_UNOP(op, opname, a, t, v) \
VERIFY (INT_##opname##_RANGE_OVERFLOW (a, TYPE_MINIMUM (t), \
CHECK_BINOP (-, SUBTRACT, UINT_MAX, 1u, unsigned int, false, UINT_MAX - 1u);
CHECK_BINOP (-, SUBTRACT, 0u, 1u, unsigned int, true, 0u - 1u);
- CHECK_UNOP (-, NEGATE, INT_MIN, int, TYPE_TWOS_COMPLEMENT (int));
+ CHECK_UNOP (-, NEGATE, INT_MIN, int, true);
CHECK_UNOP (-, NEGATE, 0, int, false);
CHECK_UNOP (-, NEGATE, INT_MAX, int, false);
CHECK_UNOP (-, NEGATE, 0u, unsigned int, false);
{ \
t result; \
ASSERT (INT_ADD_WRAPV (a, b, &result) == (v)); \
- ASSERT (result == ((v) ? (vres) : ((a) + (b))) \
- || ((v) && !TYPE_TWOS_COMPLEMENT (t))); \
+ ASSERT (result == ((v) ? (vres) : ((a) + (b)))); \
}
CHECK_SSUM (-1, LONG_MIN, long int, true, LONG_MAX);
CHECK_SUM (-1, UINT_MAX, unsigned int, false, DONTCARE);
{ \
t result; \
ASSERT (INT_SUBTRACT_WRAPV (a, b, &result) == (v)); \
- ASSERT (result == ((v) ? (vres) : ((a) - (b))) \
- || ((v) && !TYPE_TWOS_COMPLEMENT (t))); \
+ ASSERT (result == ((v) ? (vres) : ((a) - (b)))); \
}
CHECK_DIFFERENCE (INT_MAX, 1u, unsigned int, UINT_MAX < INT_MAX - 1,
INT_MAX - 1u);
{ \
t result; \
ASSERT (INT_MULTIPLY_WRAPV (a, b, &result) == (v)); \
- ASSERT (result == ((v) ? (vres) : ((a) * (b))) \
- || ((v) && !TYPE_TWOS_COMPLEMENT (t))); \
+ ASSERT (result == ((v) ? (vres) : ((a) * (b)))); \
}
CHECK_PRODUCT (-1, 1u, unsigned int, true, -1 * 1u);
CHECK_SPRODUCT (-1, INT_MIN, int, INT_NEGATE_OVERFLOW (INT_MIN), INT_MIN);
#define CHECK_QUOTIENT(a, b, v) VERIFY (INT_DIVIDE_OVERFLOW (a, b) == (v))
- CHECK_QUOTIENT (INT_MIN, -1L,
- TYPE_TWOS_COMPLEMENT (long int) && INT_MIN == LONG_MIN);
+ CHECK_QUOTIENT (INT_MIN, -1L, INT_MIN == LONG_MIN);
CHECK_QUOTIENT (INT_MIN, UINT_MAX, false);
CHECK_QUOTIENT (INTMAX_MIN, UINTMAX_MAX, false);
CHECK_QUOTIENT (INTMAX_MIN, UINT_MAX, false);
#define CHECK_REMAINDER(a, b, v) VERIFY (INT_REMAINDER_OVERFLOW (a, b) == (v))
- CHECK_REMAINDER (INT_MIN, -1L,
- TYPE_TWOS_COMPLEMENT (long int) && INT_MIN == LONG_MIN);
+ CHECK_REMAINDER (INT_MIN, -1L, INT_MIN == LONG_MIN);
CHECK_REMAINDER (-1, UINT_MAX, true);
CHECK_REMAINDER ((intmax_t) -1, UINTMAX_MAX, true);
CHECK_REMAINDER (INTMAX_MIN, UINT_MAX,
# Get the list of symbol names with this:
# perl -lne '/^# *define ([A-Z]\w+)\(/ and print $1' lib/intprops.h|fmt
_intprops_names = \
- TYPE_IS_INTEGER TYPE_TWOS_COMPLEMENT TYPE_ONES_COMPLEMENT \
- TYPE_SIGNED_MAGNITUDE TYPE_SIGNED TYPE_MINIMUM TYPE_MAXIMUM \
+ TYPE_IS_INTEGER TYPE_SIGNED TYPE_MINIMUM TYPE_MAXIMUM \
INT_BITS_STRLEN_BOUND INT_STRLEN_BOUND INT_BUFSIZE_BOUND \
INT_ADD_RANGE_OVERFLOW INT_SUBTRACT_RANGE_OVERFLOW \
INT_NEGATE_RANGE_OVERFLOW INT_MULTIPLY_RANGE_OVERFLOW \