Here's a patch that would allow programs to avoid running afoul of
unexpected gotchas with signed integer overflow when being compiled by
GCC using the default compilation flags.  It also attempts to document
the issue.  Comments?

2006-12-19  Paul Eggert  <[EMAIL PROTECTED]>

        * NEWS: configure now defaults to gcc -g -O2 -fwrapv.  This partly
        attacks the problem reported by Ralf Wildenhues in
        <http://lists.gnu.org/archive/html/bug-gnulib/2006-12/msg00084.html>
        and in <http://gcc.gnu.org/ml/gcc/2006-12/msg00459.html>.
        * doc/autoconf.texi (C Compiler, C++ Compiler):
        (Objective C Compiler): Mention -fwrapv.
        (Loop Induction, Signed Integer Divison): New sections.
        * lib/autoconf/c.m4 (_AC_PROG_CC_G, _AC_PROG_CXX_G):
        (_AC_PROG_OBJC_G): Default to -O2 -fwrapv if GCC, not
        merely to -O2.

Index: NEWS
===================================================================
RCS file: /cvsroot/autoconf/autoconf/NEWS,v
retrieving revision 1.422
diff -u -r1.422 NEWS
--- NEWS        19 Dec 2006 05:41:18 -0000      1.422
+++ NEWS        20 Dec 2006 07:37:11 -0000
@@ -1,5 +1,10 @@
 * Major changes in Autoconf 2.61b (????-??-??)

+** When using GCC, autoconf-generated 'configure' scripts now
+   default to "gcc -g -O2 -fwrapv" instead of to "gcc -g -O2".
+   This better supports the common C idiom where signed integer
+   overflow wraps around.
+
 ** Warnings are now generated by default when an installer invokes
    'configure' with an unknown --enable-* or --with-* option.
    These warnings can be disabled with the new AC_DISABLE_OPTION_CHECKING
Index: doc/autoconf.texi
===================================================================
RCS file: /cvsroot/autoconf/autoconf/doc/autoconf.texi,v
retrieving revision 1.1120
diff -u -r1.1120 autoconf.texi
--- doc/autoconf.texi   18 Dec 2006 20:10:05 -0000      1.1120
+++ doc/autoconf.texi   20 Dec 2006 07:37:12 -0000
@@ -6355,9 +6355,11 @@

 If using the @acronym{GNU} C compiler, set shell variable @code{GCC} to
 @samp{yes}.  If output variable @code{CFLAGS} was not already set, set
-it to @option{-g -O2} for the @acronym{GNU} C compiler (@option{-O2} on systems
-where @acronym{GCC} does not accept @option{-g}), or @option{-g} for
+it to @option{-g -O2 -fwrapv} for the @acronym{GNU} C compiler (omitting
[EMAIL PROTECTED] and @option{-fwrapv} on installations that do not accept these
+options), or @option{-g} for
 other compilers.
[EMAIL PROTECTED] Overflow}, for why @option{-fwrapv} is used here.
 @end defmac

 @defmac AC_PROG_CC_C_O
@@ -6690,9 +6692,11 @@

 If using the @acronym{GNU} C++ compiler, set shell variable @code{GXX} to
 @samp{yes}.  If output variable @code{CXXFLAGS} was not already set, set
-it to @option{-g -O2} for the @acronym{GNU} C++ compiler (@option{-O2} on
-systems where G++ does not accept @option{-g}), or @option{-g} for other
+it to @option{-g -O2 -fwrapv} for the @acronym{GNU} C++ compiler (omitting
[EMAIL PROTECTED] and @option{-fwrapv} on installations that do not accept these
+options), or @option{-g} for other
 compilers.
[EMAIL PROTECTED] Overflow}, for why @option{-fwrapv} is used here.
 @end defmac

 @defmac AC_PROG_CXXCPP
@@ -6744,9 +6748,11 @@

 If using the @acronym{GNU} Objective C compiler, set shell variable
 @code{GOBJC} to @samp{yes}.  If output variable @code{OBJCFLAGS} was not
-already set, set it to @option{-g -O2} for the @acronym{GNU} Objective C
-compiler (@option{-O2} on systems where @command{gcc} does not accept
[EMAIL PROTECTED]), or @option{-g} for other compilers.
+already set, set it to @option{-g -O2 -fwrapv} for the @acronym{GNU}
+Objective C compiler (omitting @option{-g} and @option{-fwrapv} on
+installations that do not accept these options), or @option{-g} for
+other compilers.
[EMAIL PROTECTED] Overflow}, for why @option{-fwrapv} is used here.
 @end defmac

 @defmac AC_PROG_OBJCCPP
@@ -14946,7 +14952,104 @@
 wraps around modulo a power of two, using two's complement arithmetic,
 so long as you cast the resulting value
 to an integer type or store it into an integer variable.  Such programs
-are portable to the vast majority of modern platforms.  However, signed
+are generally portable to the vast majority of modern platforms, if you
+use conservative optimization flags, with one main exception: signed
+integer division.
+
[EMAIL PROTECTED]
+* Loop Induction::             Loops with replaced induction variables
+* Signed Integer Division::    @code{INT_MIN / -1} and @code{INT_MIN % -1}
[EMAIL PROTECTED] menu
+
[EMAIL PROTECTED] Loop Induction
[EMAIL PROTECTED] Loop Induction and Integer Overflow
[EMAIL PROTECTED] loop induction
+
+Compilers sometimes generate code that is incompatible with wraparound
+integer arithmetic.  When this happens, it occurs mostly due to loop
+induction.
+
+For an example of loop induction, consider the following contrived
+function @code{sumc}:
+
[EMAIL PROTECTED]
+int
+sumc (int lo, int hi)
[EMAIL PROTECTED]
+  int sum = 0;
+  int i;
+  for (i = lo; i <= hi; i++)
+    sum ^= i * 100;
+  return sum;
[EMAIL PROTECTED]
[EMAIL PROTECTED] example
+
[EMAIL PROTECTED]
+To avoid multiplying by 100 each time through the loop, an optimizing
+compiler might internally transform @code{sumc} to the equivalent of the
+following:
+
[EMAIL PROTECTED]
+int
+transformed_sumc (int lo, int hi)
[EMAIL PROTECTED]
+  int sum = 0;
+  int hic = hi * 100;
+  int ic;
+  for (ic = lo * 100; ic <= hic; ic += 100)
+    sum ^= ic;
+  return sum;
[EMAIL PROTECTED]
[EMAIL PROTECTED] example
+
[EMAIL PROTECTED]
+If integer overflow is defined to wrap around modulo a power of two,
+this transformation is invalid when @code{INT_MAX / 100 < hi}, because
+then the overflow in computing expressions like @code{hi * 100} causes
+the expression @code{i <= hi} to yield a different value from the
+transformed expression @code{ic <= hic}.
+
+For this reason, compilers that use loop induction and similar
+techniques often do not support reliable wraparound arithmetic when a
+loop induction variable like @code{ic} is involved.  Since loop
+induction variables are generated by the compiler, and are not visible
+in the source code, it is not always trivial to say whether the problem
+affects your code.
+
+Hardly any code actually depends on wraparound arithmetic in cases like
+these, so in practice these loop induction optimizations are often
+useful.  However, @acronym{GCC} currently does not have an easy way to
+enable useful loop induction optimizations without also breaking common
+code that works on traditional C implementations.  For example:
+
[EMAIL PROTECTED]
+int j;
+for (j = 1; 0 < j; j *= 2)
+  test (j);
[EMAIL PROTECTED] example
+
[EMAIL PROTECTED]
+Here, the code is attempting to iterate through all powers of two that
[EMAIL PROTECTED] can represent, but @acronym{GCC}'s loop induction
+optimization can turn this into an infinite loop.
+
+To work around this problem, Autoconf-generated @command{configure}
+scripts by default compile with @option{-O2 -fwrapv} when using
[EMAIL PROTECTED] (assuming @acronym{GCC} is modern enough to support
[EMAIL PROTECTED]).  The @option{-fwrapv} option requires @command{GCC}
+to implement wraparound arithmetic for signed integers.  In some cases
[EMAIL PROTECTED] makes code faster and in some cases slower, but the
+important thing is that it leads to better-defined behavior that matches
+longstanding C tradition, so it is less likely to break existing code.
+
+An installer can override this default by specifying @code{CFLAGS} when
+invoking @command{configure}.
+
[EMAIL PROTECTED] Signed Integer Division
[EMAIL PROTECTED] Signed Integer Division and Integer Overflow
[EMAIL PROTECTED] division, integer
+
+Overflow in signed
 integer division is not always harmless: for example, on CPUs of the
 i386 family, dividing @code{INT_MIN} by @code{-1} yields a SIGFPE signal
 which by default terminates the program.  Worse, taking the remainder
Index: lib/autoconf/c.m4
===================================================================
RCS file: /cvsroot/autoconf/autoconf/lib/autoconf/c.m4,v
retrieving revision 1.242
diff -u -r1.242 c.m4
--- lib/autoconf/c.m4   7 Dec 2006 06:39:40 -0000       1.242
+++ lib/autoconf/c.m4   20 Dec 2006 07:37:12 -0000
@@ -598,15 +598,15 @@
    ac_c_werror_flag=$ac_save_c_werror_flag])
 if test "$ac_test_CFLAGS" = set; then
   CFLAGS=$ac_save_CFLAGS
-elif test $ac_cv_prog_cc_g = yes; then
-  if test "$GCC" = yes; then
-    CFLAGS="-g -O2"
-  else
-    CFLAGS="-g"
-  fi
 else
   if test "$GCC" = yes; then
-    CFLAGS="-O2"
+    CFLAGS='-O2 -fwrapv'
+    _AC_COMPILE_IFELSE([AC_LANG_PROGRAM()], [], [CFLAGS='-O2'])
+    if test $ac_cv_prog_cc_g = yes; then
+      CFLAGS="-g $CFLAGS"
+    fi
+  elif test $ac_cv_prog_cc_g = yes; then
+    CFLAGS='-g'
   else
     CFLAGS=
   fi
@@ -844,6 +844,21 @@
     CXXFLAGS=
   fi
 fi[]dnl
+if test "$ac_test_CXXFLAGS" = set; then
+  CXXFLAGS=$ac_save_CXXFLAGS
+else
+  if test "$GXX" = yes; then
+    CXXFLAGS='-O2 -fwrapv'
+    _AC_COMPILE_IFELSE([AC_LANG_PROGRAM()], [], [CXXFLAGS='-O2'])
+    if test $ac_cv_prog_cxx_g = yes; then
+      CXXFLAGS="-g $CXXFLAGS"
+    fi
+  elif test $ac_cv_prog_cxx_g = yes; then
+    CXXFLAGS='-g'
+  else
+    CXXFLAGS=
+  fi
+fi[]dnl
 ])# _AC_PROG_CXX_G


@@ -1000,15 +1015,15 @@
    ac_objc_werror_flag=$ac_save_objc_werror_flag])
 if test "$ac_test_OBJCFLAGS" = set; then
   OBJCFLAGS=$ac_save_OBJCFLAGS
-elif test $ac_cv_prog_objc_g = yes; then
-  if test "$GOBJC" = yes; then
-    OBJCFLAGS="-g -O2"
-  else
-    OBJCFLAGS="-g"
-  fi
 else
   if test "$GOBJC" = yes; then
-    OBJCFLAGS="-O2"
+    OBJCFLAGS='-O2 -fwrapv'
+    _AC_COMPILE_IFELSE([AC_LANG_PROGRAM()], [], [OBJCFLAGS='-O2'])
+    if test $ac_cv_prog_objc_g = yes; then
+      OBJCFLAGS="-g $OBJCFLAGS"
+    fi
+  elif test $ac_cv_prog_objc_g = yes; then
+    OBJCFLAGS='-g'
   else
     OBJCFLAGS=
   fi


Reply via email to