2015-11-10 Paul Eggert <eggert@cs.ucla.edu>
+ intprops: new public macro EXPR_SIGNED
+ Emacs can use this macro, so make it public.
+ * doc/intprops.texi (Arithmetic Type Properties): Rename from
+ 'Integer Type Determination', since some of these macros apply
+ to non-integer types. Clarify what kinds of constant expressions
+ these macros return. Say when the arguments can be non-integers.
+ Mention newly published macro EXPR_SIGNED.
+ * lib/intprops.h (EXPR_SIGNED): Rename from _GL_INT_SIGNED, to
+ make it public. All uses changed.
+
intprops: fix typo in clang port
* lib/intprops.h (_GL_INT_OP_WRAPV): Fix misspelling of
'__builtin_add_overflow' that is not caught by compiler.
and straightforward portable implementation.
@menu
-* Integer Type Determination:: Whether a type has integer properties.
+* Arithmetic Type Properties:: Determining properties of arithmetic types.
* Integer Bounds:: Bounds on integer values and representations.
* Wraparound Arithmetic:: Well-defined behavior on signed overflow.
* Integer Type Overflow:: General integer overflow checking.
* Integer Range Overflow:: Integer overflow checking if bounds are known.
@end menu
-@node Integer Type Determination
-@subsection Integer Type Determination
+@node Arithmetic Type Properties
+@subsection Arithmetic Type Properties
@findex TYPE_IS_INTEGER
-@code{TYPE_IS_INTEGER (@var{t})} is a constant
+@code{TYPE_IS_INTEGER (@var{t})} is an arithmetic constant
expression that is 1 if the arithmetic type @var{t} is an integer type.
@code{_Bool} counts as an integer type.
@findex TYPE_SIGNED
-@code{TYPE_SIGNED (@var{t})} is a constant expression
-that is 1 if the arithmetic type @var{t} is a signed integer type or a
+@code{TYPE_SIGNED (@var{t})} is an arithmetic constant expression
+that is 1 if the real type @var{t} is a signed integer type or a
floating type. If @var{t} is an integer type, @code{TYPE_SIGNED (@var{t})}
is an integer constant expression.
+@findex EXPR_SIGNED
+@code{EXPR_SIGNED (@var{e})} is 1 if the real expression @var{e}
+has a signed integer type or a floating type. If @var{e} is an
+integer constant expression or an arithmetic constant expression,
+@code{EXPR_SIGNED (@var{e})} is likewise. Although @var{e} is
+evaluated, if @var{e} is free of side effects then @code{EXPR_SIGNED
+(@var{e})} is typically optimized to a constant.
+
Example usage:
@example
#include <intprops.h>
#include <time.h>
+
enum
@{
time_t_is_signed_integer =
TYPE_IS_INTEGER (time_t) && TYPE_SIGNED (time_t)
@};
+
+int
+CLOCKS_PER_SEC_is_signed (void)
+@{
+ return EXPR_SIGNED (CLOCKS_PER_SEC);
+@}
@end example
@node Integer Bounds
#include <limits.h>
-/* Return an integer value, converted to the same type as the integer
- expression E after integer type promotion. V is the unconverted value. */
+/* Return a value with the common real type of E and V and the value of V. */
#define _GL_INT_CONVERT(e, v) (0 * (e) + (v))
/* Act like _GL_INT_CONVERT (E, -V) but work around a bug in IRIX 6.5 cc; see
/* 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 arithmetic type T is signed. */
+/* True if the real type T is signed. */
#define TYPE_SIGNED(t) (! ((t) 0 < (t) -1))
-/* Return 1 if the integer expression E, after integer promotion, has
- a signed type. */
-#define _GL_INT_SIGNED(e) (_GL_INT_NEGATE_CONVERT (e, 1) < 0)
+/* Return 1 if the real expression E, after promotion, has a
+ signed or floating type. */
+#define EXPR_SIGNED(e) (_GL_INT_NEGATE_CONVERT (e, 1) < 0)
/* Minimum and maximum values for integer types and expressions. These
/* The maximum and minimum values for the type of the expression E,
after integer promotion. E should not have side effects. */
#define _GL_INT_MINIMUM(e) \
- (_GL_INT_SIGNED (e) \
+ (EXPR_SIGNED (e) \
? - _GL_INT_TWOS_COMPLEMENT (e) - _GL_SIGNED_INT_MAXIMUM (e) \
: _GL_INT_CONVERT (e, 0))
#define _GL_INT_MAXIMUM(e) \
- (_GL_INT_SIGNED (e) \
+ (EXPR_SIGNED (e) \
? _GL_SIGNED_INT_MAXIMUM (e) \
: _GL_INT_NEGATE_CONVERT (e, 1))
#define _GL_SIGNED_INT_MAXIMUM(e) \
: _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) \
- || (_GL_INT_SIGNED ((a) op (b)) && ((a) op (b)) < (tmin)) \
+ || (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))