https://gcc.gnu.org/bugzilla/show_bug.cgi?id=68120

            Bug ID: 68120
           Summary: can't easily deal with integer overflow at compile
                    time
           Product: gcc
           Version: unknown
            Status: UNCONFIRMED
          Severity: enhancement
          Priority: P3
         Component: c
          Assignee: unassigned at gcc dot gnu.org
          Reporter: eggert at gnu dot org
  Target Milestone: ---

This is a followup to Bug#61129, which asked for integer-overflow-detecting
arithmetic intrinsics. We have them now (thanks!) but I'm running into some
problems using them.

The Gnulib intprops module defines macros to check for integer overflow, e.g.,
INT_ADD_OVERFLOW (a, b) returns 1 if the C expression A+B would overflow. These
macros are implemented in portable C. I'm trying to use GCC 5's new
__builtin_add_overflow etc. functions to speed up their runtime execution. This
turns out to be a pain because these macros are used in integer constant
expressions, where __builtin_add_overflow etc. cannot be used.

I am working around the problem with macro definitions like this:

 # define INT_ADD_OVERFLOW(a, b) \
   (__builtin_constant_p ((a) == (b)) \
    ? _GL_INT_ADD_OVERFLOW (a, b) \
    : __builtin_add_overflow (a, b, &(__typeof__ ((a) + (b))) {0}))

where _GL_INT_ADD_OVERFLOW is a complex macro implemented in Standard C and is
a constant expression when its arguments are constant expressions. Although I
think this will work, it is ugly, and the macro _GL_INT_ADD_OVERFLOW is
complicated.

To simplify use of __builtin_add_overflow etc., I suggest extending these
builtins as follows.

First, allow the 3rd argument to be a null pointer constant of type
pointer-to-integer, meaning that the caller only wants to know if the overflow
occurred and does not want the low-order bits of the result. E.g.,
__builtin_add_overflow (a, b, (int *) 0) returns 1 if the mathematical value of
A + B does not fit in 'int'.  This would allow the above macro to be simplified
to:

 # define INT_ADD_OVERFLOW(a, b) \
   __builtin_add_overflow (a, b, (__typeof__ ((a) + (b)) *) 0)

Second, allow the 3rd argument to be omitted, as a shorthand for a null pointer
to the integer type of A+B. This further simplification would allow the above
macro to be simplified to:

  # define INT_ADD_OVERFLOW(a, b) __builtin_add_overflow (a, b)

Third, add a function __builtin_add_wrapv (a, b, c) that acts like
__builtin_add_overflow (a, b, c) except that it returns the value that would be
stored if C were a non-null pointer.  The 3rd argument C is optional here too,
with the same semantics as for __builtin_add_overflow.  This will let the user
get the bottom-order bits of an overflowed value in a constant expression,
something that can't be done with the current primitives.

The basic idea here is that we need intrinsics that deal with values and that
do not require non-null addresses, so that we can use these intrinsics in
constant expressions.

Reply via email to