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 b15e712aea433545950342747c3f5625a0459896..d6c2be3715a4ae9f2469f53cf2be1a3255ecf254 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 d8ae286512af5e746f13f90c0bc3922cb09d46ad..bb7be99e7d23a3c0d3d79cd5bfae576e2d495b70 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 686691c21e07f239ea9f936d6cef57a91a2ef4c9..e7596957d82a827538b3e37727cc38db98ba8ecd 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 66e72a7d0ad7aaf2ce771039bc98b8dbc53a2121..ce5673e087cd82bf0791bcfda0558aa064bc4a14 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 1f476feb510cfe10a188cce5d6533783e0ab8311..d87b121e885a9d2e61ad0000d059b32071466342 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" } } */