diff options
author | Paul Eggert <eggert@cs.ucla.edu> | 2015-11-04 08:27:57 -0800 |
---|---|---|
committer | Paul Eggert <eggert@cs.ucla.edu> | 2015-11-04 08:29:17 -0800 |
commit | 8780c1786db440a0ef1c0776dfff68134602fcea (patch) | |
tree | 05e23c1e030b92154c7a60acddc90abf2a0b6b38 /doc/intprops.texi | |
parent | 24fb386f25ce0800577ac64f2d2303822e9e615c (diff) | |
download | gnulib-8780c1786db440a0ef1c0776dfff68134602fcea.tar.gz |
intprops: revise _WRAPV macros, revert _OVERFLOW
The incompatible changes to the _OVERFLOW macros were too much of
a hassle in practice, so revert them. Instead, change the new
_WRAPV macros to make them closer in behavior to GCC 5's new
builtin_add_overflow etc. functions. No other software was using
these newly-added macros yet, so this should be OK.
* NEWS: Revert previous change, since the incompatible change
has been reverted, and nobody used the incompatible version.
* doc/intprops.texi (Wraparound Arithmetic, Integer Type Overflow):
Document revised behavior.
(Integer Range Overflow): Adjust example to match above revisions.
* lib/intprops.h (INT_ADD_OVERFLOW, INT_SUBTRACT_OVERFLOW)
(INT_MULTIPLY_OVERFLOW): Revert previous change, so that
these can be used in integer constant expressions again.
(INT_CONST_ADD_OVERFLOW, INT_CONST_SUBTRACT_OVERFLOW)
(INT_CONST_MULTIPLY_OVERFLOW): Remove, as these are no longer
needed.
(INT_CONST_ADD_WRAPV, INT_CONST_SUBTRACT_WRAPV)
(INT_NEGATE_WRAPV, INT_CONST_MULTIPLY_WRAPV, INT_DIVIDE_WRAPV)
(INT_REMAINDER_WRAPV, INT_LEFT_SHIFT_WRAPV):
Remove, as they did not seem that useful.
(INT_ADD_WRAPV, INT_SUBTRACT_WRAPV, INT_MULTIPLY_WRAPV)
(_GL_INT_OP_WRAPV, _GL_INT_OP_WRAPV_LONGISH)
(_GL_INT_OP_WRAPV_VIA_UNSIGNED):
Support new semantics.
(__has_builtin): New macro, if not alreay defined.
(_GL__GENERIC_BOGUS, _GL_INT_OP_CALC, _GL_INT_OP_CALC1): New macros.
* tests/test-intprops.c (INT_CONST_DIVIDE_OVERFLOW)
(INT_CONST_REMAINDER_OVERFLOW, INT_CONST_LEFT_SHIFT_OVERFLOW)
(INT_CONST_DIVIDE_WRAPV, INT_CONST_REMAINDER_WRAPV)
(INT_CONST_LEFT_SHIFT_WRAPV): Remove.
(CHECK_SBINOP, CHECK_SSUM, CHECK_SUM1, CHECK_SSUM1)
(CHECK_SDIFFERENCE, CHECK_SPRODUCT, CHECK_PRODUCT1, CHECK_SPRODUCT1):
New macros.
(CHECK_BINOP, CHECK_UNOP, main, CHECK_SUM): Test new behavior.
Diffstat (limited to 'doc/intprops.texi')
-rw-r--r-- | doc/intprops.texi | 196 |
1 files changed, 83 insertions, 113 deletions
diff --git a/doc/intprops.texi b/doc/intprops.texi index 489bcb934e..55e60e99a6 100644 --- a/doc/intprops.texi +++ b/doc/intprops.texi @@ -147,97 +147,77 @@ necessarily yield @code{INT_MIN}, because the compiler may do calculations with a 64-bit register, or may generate code that traps on signed integer overflow. -The following macros work around this problem by yielding the -wraparound value, i.e., the low-order bits of the correct answer. For -example, @code{INT_ADD_WRAPV (INT_MAX, 1)} reliably yields -@code{INT_MIN} on a two's complement machine. You can also use -overflow-checking macros to check whether wraparound occurred. -@xref{Integer Type Overflow}. +The following macros work around this problem by storing the +wraparound value, i.e., the low-order bits of the correct answer, and +by returning an overflow indication. For example, if @code{i} is of +type @code{int}, @code{INT_ADD_WRAPV (INT_MAX, 1, &i)} sets @code{i} +to @code{INT_MIN} and returns 1 on a two's complement machine. On +newer platforms, these macros are typically more efficient than the +overflow-checking macros. @xref{Integer Type Overflow}. + +Example usage: + +@example +#include <intprops.h> +#include <stdio.h> + +/* Print the low order bits of A * B, + reporting whether overflow occurred. */ +void +print_product (long int a, long int b) +@{ + long int r; + int overflow = INT_MULTIPLY_WRAPV (a, b, &r); + printf ("result is %ld (%s)\n", r, + (overflow + ? "after overflow" + : "no overflow")); +@} +@end example @noindent These macros have the following restrictions: @itemize @bullet @item -Their arguments must be integer expressions. +Their first two arguments must be integer expressions. + +@item +Their last argument must be a non-null pointer to a signed integer. +To calculate a wraparound unsigned integer you can use ordinary C +arithmetic; to tell whether it overflowed, you can use the +overflow-checking macros. @item They may evaluate their arguments zero or multiple times, so the arguments should not have side effects. @item -On non-GCC-compatible compilers that do not support C11, the type of -@code{INT_ADD_WRAPV (@var{a}, @var{b})} might differ from the native -type of @code{@var{a} + @var{b}}, so it is wise to convert the result -to the native type. Such a conversion is safe and cannot trap. This -issue applies to all the @code{_WRAP} macros. +They are not necessarily constant expressions, even if all their +arguments are constant expressions. @end itemize -These macros are tuned for their last argument being a constant. - @table @code -@item INT_ADD_WRAP (@var{a}, @var{b}) -@findex INT_ADD_WRAP -Return the low-order bits of @code{@var{a} + @var{b}}. See above for +@item INT_ADD_WRAPV (@var{a}, @var{b}, @var{r}) +@findex INT_ADD_WRAPV +Store the low-order bits of the sum of @var{a} and @var{b} into +@code{*@var{r}}. Return true if overflow occurred, false if the +low-order bits are the mathematically-correct sum. See above for restrictions. -@item INT_CONST_ADD_WRAP (@var{a}, @var{b}) -@findex INT_CONST_ADD_WRAP -Return the low-order bits of @code{@var{a} + @var{b}}. See above for -restrictions. This macro differs from @code{INT_ADD_WRAP} in that -although its implementation is typically slower, it is an integer -constant expression if its arguments are. - -@item INT_SUBTRACT_WRAP (@var{a}, @var{b}) -@findex INT_SUBTRACT_WRAP -Return the low-order bits of @code{@var{a} - @var{b}}. See above for +@item INT_SUBTRACT_WRAPV (@var{a}, @var{b}, @var{r}) +@findex INT_SUBTRACT_WRAPV +Store the low-order bits of the difference between @var{a} and @var{b} +into @code{*@var{r}}. Return true if overflow occurred, false if the +low-order bits are the mathematically-correct difference. See above +for restrictions. + +@item INT_MULTIPLY_WRAPV (@var{a}, @var{b}, @var{r}) +@findex INT_MULTIPLY_WRAPV +Store the low-order bits of the product of @var{a} and @var{b} into +@code{*@var{r}}. Return true if overflow occurred, false if the +low-order bits are the mathematically-correct product. See above for restrictions. - -@item INT_CONST_SUBTRACT_WRAP (@var{a}, @var{b}) -@findex INT_CONST_SUBTRACT_WRAP -Return the low-order bits of @code{@var{a} - @var{b}}. See above for -restrictions. This macro differs from @code{INT_SUBTRACT_WRAP} in -that although its implementation is typically slower, it is an integer -constant expression if its arguments are. - -@item INT_NEGATE_WRAP (@var{a}) -@findex INT_NEGATE_WRAP -Return the low-order bits of @code{-@var{a}}. See above for restrictions. -This macro is an integer constant expression if its arguments are. - -@item INT_MULTIPLY_WRAP (@var{a}, @var{b}) -@findex INT_MULTIPLY_WRAP -Return the low-order bits of @code{@var{a} * @var{b}}. See above for -restrictions. - -@item INT_CONST_MULTIPLY_WRAP (@var{a}, @var{b}) -@findex INT_CONST_MULTIPLY_WRAP -Return the low-order bits of @code{@var{a} * @var{b}}. See above for -restrictions. This macro differs from @code{INT_MULTIPLY_WRAP} in -that although its implementation is typically slower, it is an integer -constant expression if its arguments are. - -@item INT_DIVIDE_WRAP (@var{a}, @var{b}) -@findex INT_DIVIDE_WRAP -Return the low-order bits of @code{@var{a} / @var{b}}. See above for -restrictions. This macro does not check for division by zero. This -macro is an integer constant expression if its arguments are. - -@item INT_REMAINDER_WRAP (@var{a}, @var{b}) -@findex INT_REMAINDER_WRAP -Return the low-order bits of @code{@var{a} % @var{b}}. See above for -restrictions. This macro does not check for division by zero. This -macro is an integer constant expression if its arguments are. - -@item INT_LEFT_SHIFT_WRAP (@var{a}, @var{b}) -@findex INT_LEFT_SHIFT_WRAP -Return the low-order bits of @code{@var{a} << @var{b}}. See above for -restrictions. The C standard says that behavior is undefined for -shifts unless 0@leq{}@var{b}<@var{w} where @var{w} is @var{a}'s word -width, and that when @var{a} is negative then @code{@var{a} << -@var{b}} has undefined behavior, but this macro does not check these -other restrictions. This macro is an integer constant expression if -its arguments are. @end table @node Integer Type Overflow @@ -262,34 +242,35 @@ These macros yield 1 if the corresponding C operators might not yield numerically correct answers due to arithmetic overflow of an integer type. They work correctly on all known practical hosts, and do not rely on undefined behavior due to signed arithmetic overflow. They +are integer constant expressions if their arguments are. They are typically easier to use than the integer range overflow macros -(@pxref{Integer Range Overflow}). +(@pxref{Integer Range Overflow}), and they support more operations and +evaluation contexts than the wraparound macros (@pxref{Wraparound +Arithmetic}). -Example usages: +Example usage: @example #include <intprops.h> #include <limits.h> +#include <stdio.h> -/* Print the low order bits of A * B, - reporting whether overflow occurred. - When optimized this code typically - multiplies A and B only once. */ +/* Print A * B if in range, an overflow + indicator otherwise. */ void print_product (long int a, long int b) @{ - long int result = INT_MULTIPLY_WRAPV (a, b); - printf ("result is %ld (%s)\n", result, - (INT_MULTIPLY_OVERFLOW (a, b) - ? "after overflow" - : "no overflow")); + if (INT_MULTIPLY_OVERFLOW (a, b)) + printf ("multiply would overflow"); + else + printf ("product is %ld", a * b); @} /* Does the product of two ints always fit in a long int? */ enum @{ INT_PRODUCTS_FIT_IN_LONG - = ! (INT_CONST_MULTIPLY_OVERFLOW + = ! (INT_MULTIPLY_OVERFLOW ((long int) INT_MIN, INT_MIN)) @}; @end example @@ -306,6 +287,7 @@ They may evaluate their arguments zero or multiple times, so the arguments should not have side effects. @end itemize +@noindent These macros are tuned for their last argument being a constant. @table @code @@ -314,49 +296,26 @@ These macros are tuned for their last argument being a constant. Yield 1 if @code{@var{a} + @var{b}} would overflow. See above for restrictions. -@item INT_CONST_ADD_OVERFLOW (@var{a}, @var{b}) -@findex INT_CONST_ADD_OVERFLOW -Yield 1 if @code{@var{a} + @var{b}} would overflow. See above for -restrictions. This macro differs from @code{INT_ADD_OVERFLOW} in that -although its implementation is typically slower, it is an integer -constant expression if its arguments are. - @item INT_SUBTRACT_OVERFLOW (@var{a}, @var{b}) @findex INT_SUBTRACT_OVERFLOW Yield 1 if @code{@var{a} - @var{b}} would overflow. See above for restrictions. -@item INT_CONST_SUBTRACT_OVERFLOW (@var{a}, @var{b}) -@findex INT_CONST_SUBTRACT_OVERFLOW -Yield 1 if @code{@var{a} - @var{b}} would overflow. See above for -restrictions. This macro differs from @code{INT_SUBTRACT_OVERFLOW} in -that although its implementation is typically slower, it is an integer -constant expression if its arguments are. - @item INT_NEGATE_OVERFLOW (@var{a}) @findex INT_NEGATE_OVERFLOW Yields 1 if @code{-@var{a}} would overflow. See above for restrictions. -This macro is an integer constant expression if its arguments are. @item INT_MULTIPLY_OVERFLOW (@var{a}, @var{b}) @findex INT_MULTIPLY_OVERFLOW Yield 1 if @code{@var{a} * @var{b}} would overflow. See above for restrictions. -@item INT_CONST_MULTIPLY_OVERFLOW (@var{a}, @var{b}) -@findex INT_CONST_MULTIPLY_OVERFLOW -Yield 1 if @code{@var{a} * @var{b}} would overflow. See above for -restrictions. This macro differs from @code{INT_SUBTRACT_OVERFLOW} in -that although its implementation is typically slower, it is an integer -constant expression if its arguments are. - @item INT_DIVIDE_OVERFLOW (@var{a}, @var{b}) @findex INT_DIVIDE_OVERFLOW Yields 1 if @code{@var{a} / @var{b}} would overflow. See above for restrictions. Division overflow can happen on two's complement hosts when dividing the most negative integer by @minus{}1. This macro does -not check for division by zero. This macro is an integer constant -expression if its arguments are. +not check for division by zero. @item INT_REMAINDER_OVERFLOW (@var{a}, @var{b}) @findex INT_REMAINDER_OVERFLOW @@ -365,8 +324,7 @@ restrictions. Remainder overflow can happen on two's complement hosts when dividing the most negative integer by @minus{}1; although the mathematical result is always 0, in practice some implementations trap, so this counts as an overflow. This macro does not check for -division by zero. This macro is an integer constant expression if its -arguments are. +division by zero. @item INT_LEFT_SHIFT_OVERFLOW (@var{a}, @var{b}) @findex INT_LEFT_SHIFT_OVERFLOW @@ -375,8 +333,7 @@ restrictions. The C standard says that behavior is undefined for shifts unless 0@leq{}@var{b}<@var{w} where @var{w} is @var{a}'s word width, and that when @var{a} is negative then @code{@var{a} << @var{b}} has undefined behavior, but this macro does not check these -other restrictions. This macro is an integer constant expression if -its arguments are. +other restrictions. @end table @node Integer Range Overflow @@ -407,6 +364,9 @@ Example usage: @example #include <intprops.h> +#include <limits.h> +#include <stdio.h> + void print_product (long int a, long int b) @{ @@ -415,6 +375,15 @@ print_product (long int a, long int b) else printf ("product is %ld", a * b); @} + +/* Does the product of two ints always fit + in a long int? */ +enum @{ + INT_PRODUCTS_FIT_IN_LONG + = ! (INT_MULTIPLY_RANGE_OVERFLOW + ((long int) INT_MIN, (long int) INT_MIN, + LONG_MIN, LONG_MAX)) +@}; @end example @noindent @@ -436,6 +405,7 @@ maximum @var{max}. Unsigned values should use a zero @var{min} of the proper type, for example, @code{(unsigned int) 0}. @end itemize +@noindent These macros are tuned for constant @var{min} and @var{max}. For commutative operations such as @code{@var{a} + @var{b}}, they are also tuned for constant @var{b}. |