flags.h (POINTER_TYPE_OVERFLOW_UNDEFINED): Define.
authorIan Lance Taylor <iant@google.com>
Mon, 14 Apr 2008 19:18:31 +0000 (19:18 +0000)
committerIan Lance Taylor <ian@gcc.gnu.org>
Mon, 14 Apr 2008 19:18:31 +0000 (19:18 +0000)
gcc/:
* flags.h (POINTER_TYPE_OVERFLOW_UNDEFINED): Define.
* fold-const.c (fold_comparison): If appropriate, test
POINTER_TYPE_OVERFLOW_UNDEFINED, and issue an overflow warning.
(fold_binary): Test POINTER_TYPE_OVERFLOW_UNDEFINED when
reassociating a pointer type.
* doc/invoke.texi (Optimize Options): Document that
-fstrict-overflow applies to pointer wraparound.
gcc/testsuite/:
* gcc.dg/strict-overflow-6.c: New.
* gcc.dg/no-strict-overflow-7.c: New.
* gcc.dg/Wstrict-overflow-22.c: New.

From-SVN: r134287

gcc/ChangeLog
gcc/doc/invoke.texi
gcc/flags.h
gcc/fold-const.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/Wstrict-overflow-22.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/no-strict-overflow-7.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/strict-overflow-6.c [new file with mode: 0644]

index b15e712..d6c2be3 100644 (file)
@@ -1,3 +1,13 @@
+2008-04-14  Ian Lance Taylor  <iant@google.com>
+
+       * flags.h (POINTER_TYPE_OVERFLOW_UNDEFINED): Define.
+       * fold-const.c (fold_comparison): If appropriate, test
+       POINTER_TYPE_OVERFLOW_UNDEFINED, and issue an overflow warning.
+       (fold_binary): Test POINTER_TYPE_OVERFLOW_UNDEFINED when
+       reassociating a pointer type.
+       * doc/invoke.texi (Optimize Options): Document that
+       -fstrict-overflow applies to pointer wraparound.
+
 2008-04-13  Jan Hubicka  <jh@suse.cz>
 
        * m32.c (m32c_pushm_popm): Use crtl->retrun_rtx.
index d8ae286..bb7be99 100644 (file)
@@ -6161,13 +6161,22 @@ using twos complement arithmetic.  When this option is in effect any
 attempt to determine whether an operation on signed numbers will
 overflow must be written carefully to not actually involve overflow.
 
+This option also allows the compiler to assume strict pointer
+semantics: given a pointer to an object, if adding an offset to that
+pointer does not produce a pointer to the same object, the addition is
+undefined.  This permits the compiler to conclude that @code{p + u >
+p} is always true for a pointer @code{p} and unsigned integer
+@code{u}.  This assumption is only valid because pointer wraparound is
+undefined, as the expression is false if @code{p + u} overflows using
+twos complement arithmetic.
+
 See also the @option{-fwrapv} option.  Using @option{-fwrapv} means
-that signed overflow is fully defined: it wraps.  When
+that integer signed overflow is fully defined: it wraps.  When
 @option{-fwrapv} is used, there is no difference between
-@option{-fstrict-overflow} and @option{-fno-strict-overflow}.  With
-@option{-fwrapv} certain types of overflow are permitted.  For
-example, if the compiler gets an overflow when doing arithmetic on
-constants, the overflowed value can still be used with
+@option{-fstrict-overflow} and @option{-fno-strict-overflow} for
+integers.  With @option{-fwrapv} certain types of overflow are
+permitted.  For example, if the compiler gets an overflow when doing
+arithmetic on constants, the overflowed value can still be used with
 @option{-fwrapv}, but not otherwise.
 
 The @option{-fstrict-overflow} option is enabled at levels
index 686691c..e759695 100644 (file)
@@ -332,6 +332,9 @@ extern bool flag_instrument_functions_exclude_p (tree fndecl);
 #define TYPE_OVERFLOW_TRAPS(TYPE) \
   (!TYPE_UNSIGNED (TYPE) && flag_trapv)
 
+/* True if pointer types have undefined overflow.  */
+#define POINTER_TYPE_OVERFLOW_UNDEFINED (flag_strict_overflow)
+
 /* Names for the different levels of -Wstrict-overflow=N.  The numeric
    values here correspond to N.  */
 
index 66e72a7..ce5673e 100644 (file)
@@ -8568,7 +8568,9 @@ fold_comparison (enum tree_code code, tree type, tree op0, tree op1)
             because pointer arithmetic is restricted to retain within an
             object and overflow on pointer differences is undefined as of
             6.5.6/8 and /9 with respect to the signed ptrdiff_t.  */
-         else if (bitpos0 == bitpos1)
+         else if (bitpos0 == bitpos1
+                  && ((code == EQ_EXPR || code == NE_EXPR)
+                      || POINTER_TYPE_OVERFLOW_UNDEFINED))
            {
              tree signed_size_type_node;
              signed_size_type_node = signed_type_for (size_type_node);
@@ -8587,6 +8589,12 @@ fold_comparison (enum tree_code code, tree type, tree op0, tree op1)
              else
                offset1 = fold_convert (signed_size_type_node, offset1);
 
+             if (code != EQ_EXPR && code != NE_EXPR)
+               fold_overflow_warning (("assuming pointer wraparound does not "
+                                       "occur when comparing P +- C1 with "
+                                       "P +- C2"),
+                                      WARN_STRICT_OVERFLOW_COMPARISON);
+
              return fold_build2 (code, type, offset0, offset1);
            }
        }
@@ -9711,7 +9719,7 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
 
          /* With undefined overflow we can only associate constants
             with one variable.  */
-         if ((POINTER_TYPE_P (type)
+         if (((POINTER_TYPE_P (type) && POINTER_TYPE_OVERFLOW_UNDEFINED)
               || (INTEGRAL_TYPE_P (type) && !TYPE_OVERFLOW_WRAPS (type)))
              && var0 && var1)
            {
index 1f476fe..d87b121 100644 (file)
@@ -1,3 +1,9 @@
+2008-04-14  Ian Lance Taylor  <iant@google.com>
+
+       * gcc.dg/strict-overflow-6.c: New.
+       * gcc.dg/no-strict-overflow-7.c: New.
+       * gcc.dg/Wstrict-overflow-22.c: New.
+
 2008-04-14  Samuel Tardieu  <sam@rfc1149.net>
 
        * gnat.dg/specs/storage.ads: Fix expected error message.
diff --git a/gcc/testsuite/gcc.dg/Wstrict-overflow-22.c b/gcc/testsuite/gcc.dg/Wstrict-overflow-22.c
new file mode 100644 (file)
index 0000000..4b84387
--- /dev/null
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-options "-fstrict-overflow -O2 -Wstrict-overflow=3" } */
+
+/* Source: Ian Lance Taylor.  Based on strict-overflow-6.c.  */
+
+/* We can only simplify the conditional when using strict overflow
+   semantics.  */
+
+int
+foo (char* p)
+{
+  return p + 1000 < p; /* { dg-warning "assuming pointer wraparound does not occur" "correct warning" } */
+}
diff --git a/gcc/testsuite/gcc.dg/no-strict-overflow-7.c b/gcc/testsuite/gcc.dg/no-strict-overflow-7.c
new file mode 100644 (file)
index 0000000..07ad27b
--- /dev/null
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-options "-fno-strict-overflow -O2 -fdump-tree-final_cleanup" } */
+
+/* Source: Ian Lance Taylor.  Dual of strict-overflow-6.c.  */
+
+/* We can only simplify the conditional when using strict overflow
+   semantics.  */
+
+int
+foo (char* p)
+{
+  return p + 1000 < p;
+}
+
+/* { dg-final { scan-tree-dump "\[+\]\[ \]*1000" "final_cleanup" } } */
+/* { dg-final { cleanup-tree-dump "final_cleanup" } } */
diff --git a/gcc/testsuite/gcc.dg/strict-overflow-6.c b/gcc/testsuite/gcc.dg/strict-overflow-6.c
new file mode 100644 (file)
index 0000000..ec1266d
--- /dev/null
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-options "-fstrict-overflow -O2 -fdump-tree-final_cleanup" } */
+
+/* Source: Ian Lance Taylor.  Dual of no-strict-overflow-7.c.  */
+
+/* We can only simplify the conditional when using strict overflow
+   semantics.  */
+
+int
+foo (char* p)
+{
+  return p + 1000 < p;
+}
+
+/* { dg-final { scan-tree-dump-not "\[+\]\[ \]*1000" "final_cleanup" } } */
+/* { dg-final { cleanup-tree-dump "final_cleanup" } } */