]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
flags.h (POINTER_TYPE_OVERFLOW_UNDEFINED): Define. prereleases/gcc-4.2.4-rc1
authorIan Lance Taylor <iant@google.com>
Mon, 12 May 2008 18:04:51 +0000 (18:04 +0000)
committerIan Lance Taylor <ian@gcc.gnu.org>
Mon, 12 May 2008 18:04:51 +0000 (18:04 +0000)
./: * flags.h (POINTER_TYPE_OVERFLOW_UNDEFINED): Define.
* fold-const.c (fold_overflow_warning): Remove assertion.
(pointer_may_wrap_p): New static function.
(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.
testsuite/:
* gcc.dg/strict-overflow-6.c: New.
* gcc.dg/no-strict-overflow-7.c: New.
* gcc.dg/Wstrict-overflow-22.c: New.
* gcc.c-torture/compile/20080419-1.c: New.
* gcc.dg/tree-ssa/loop-17.c: Use -O2.

From-SVN: r135222

gcc/ChangeLog
gcc/doc/invoke.texi
gcc/flags.h
gcc/fold-const.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.c-torture/compile/20080419-1.c [new file with mode: 0644]
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]
gcc/testsuite/gcc.dg/tree-ssa/loop-17.c

index 6970062441116f1b4fe04c78e7ef91952a20eafa..5487418a5152434fc39a38999ad0468973e6ba12 100644 (file)
@@ -1,3 +1,15 @@
+2008-05-12  Ian Lance Taylor  <iant@google.com>
+
+       * flags.h (POINTER_TYPE_OVERFLOW_UNDEFINED): Define.
+       * fold-const.c (fold_overflow_warning): Remove assertion.
+       (pointer_may_wrap_p): New static function.
+       (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-05-02  Ralf Wildenhues  <Ralf.Wildenhues@gmx.de>
 
        PR bootstrap/35169
index 5514943da30fb8e5a0e73797ec14fb58028c2c94..7f5b38faa0921fbcdaf474403d4b298f0fe7d603 100644 (file)
@@ -5490,13 +5490,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 5d5f0798b2d1ef5ef764c05e7deb1d675740e210..a6d5b24f62a93bf5458640ebb21a99f25b9d5c3d 100644 (file)
@@ -1,6 +1,6 @@
 /* Compilation switch flag definitions for GCC.
    Copyright (C) 1987, 1988, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2002,
-   2003, 2004, 2005, 2006, 2007
+   2003, 2004, 2005, 2006, 2007, 2008
    Free Software Foundation, Inc.
 
 This file is part of GCC.
@@ -303,6 +303,9 @@ extern const char *flag_random_seed;
 #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 dde8f88720a06262d8c4682e3884b06338457583..4a1cc2c97217d0b67bb4b281377c09d2404e63c5 100644 (file)
@@ -1,6 +1,6 @@
 /* Fold a constant sub-tree into a single node for C-compiler
    Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
-   2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
+   2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
    Free Software Foundation, Inc.
 
 This file is part of GCC.
@@ -980,7 +980,6 @@ fold_deferring_overflow_warnings_p (void)
 static void
 fold_overflow_warning (const char* gmsgid, enum warn_strict_overflow_code wc)
 {
-  gcc_assert (!flag_wrapv && !flag_trapv);
   if (fold_deferring_overflow_warnings > 0)
     {
       if (fold_deferred_overflow_warning == NULL
@@ -7969,6 +7968,46 @@ fold_minmax (enum tree_code code, tree type, tree op0, tree op1)
   return NULL_TREE;
 }
 
+/* Return whether BASE + OFFSET may wrap around the address space.
+   This is used to avoid issuing overflow warnings for expressions
+   like &p->x which can not wrap.  */
+
+static bool
+pointer_may_wrap_p (tree base, tree offset)
+{
+  unsigned HOST_WIDE_INT offset_low;
+  HOST_WIDE_INT size, offset_high;
+
+  if (!POINTER_TYPE_P (TREE_TYPE (base))
+      && TREE_CODE (TREE_TYPE (base)) != ARRAY_TYPE)
+    return true;
+
+  if (offset == NULL_TREE)
+    {
+      offset_low = 0;
+      offset_high = 0;
+    }
+  else if (TREE_CODE (offset) != INTEGER_CST || TREE_OVERFLOW (offset))
+    return true;
+  else
+    {
+      offset_low = TREE_INT_CST_LOW (offset);
+      offset_high = TREE_INT_CST_HIGH (offset);
+
+      if (offset_high != 0)
+       return true;
+    }
+
+  if (POINTER_TYPE_P (TREE_TYPE (base)))
+    size = int_size_in_bytes (TREE_TYPE (TREE_TYPE (base)));
+  else
+    size = int_size_in_bytes (TREE_TYPE (base));
+  if (size <= 0)
+    return true;
+
+  return offset_low > (unsigned HOST_WIDE_INT) size;
+}
+
 /* Subroutine of fold_binary.  This routine performs all of the
    transformations that are common to the equality/inequality
    operators (EQ_EXPR and NE_EXPR) and the ordering operators
@@ -8037,7 +8076,10 @@ fold_comparison (enum tree_code code, tree type, tree op0, tree op1)
      not here.  */
   if (POINTER_TYPE_P (TREE_TYPE (arg0))
       && !flag_wrapv
-      && !TYPE_OVERFLOW_TRAPS (TREE_TYPE (arg0)))
+      && !TYPE_OVERFLOW_TRAPS (TREE_TYPE (arg0))
+      && (code == EQ_EXPR
+         || code == NE_EXPR
+         || POINTER_TYPE_OVERFLOW_UNDEFINED))
     {
       tree base0, offset0, base1, offset1;
 
@@ -8062,6 +8104,16 @@ 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
+             && !operand_equal_p (offset0, offset1, 0)
+             && (pointer_may_wrap_p (base0, offset0)
+                 || pointer_may_wrap_p (base1, offset1)))
+           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);
        }
     }
@@ -8876,7 +8928,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_UNSIGNED (type) || flag_wrapv)))
              && var0 && var1)
index b5ddb3870b97b1ca525d579c73fae37b9fa0406a..6ef2644572f8db2e19555b4c90745fe7b697fce6 100644 (file)
@@ -1,3 +1,11 @@
+2008-05-12  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.
+       * gcc.c-torture/compile/20080419-1.c: New.
+       * gcc.dg/tree-ssa/loop-17.c: Use -O2.
+
 2008-05-11  Volker Reichelt  <v.reichelt@netcologne.de>
 
        PR c++/35578
diff --git a/gcc/testsuite/gcc.c-torture/compile/20080419-1.c b/gcc/testsuite/gcc.c-torture/compile/20080419-1.c
new file mode 100644 (file)
index 0000000..b257fea
--- /dev/null
@@ -0,0 +1,6 @@
+extern void *f();
+void dmi_scan_machine(void) {
+  char *p = f(), *q;
+  for (q = p; q < p + 10; q++)
+    ;
+}
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" } } */
index 26e49862091972e8215c584dbf951986687402d3..6db543c44df069f359a1e17694d32200d3971242 100644 (file)
@@ -1,5 +1,5 @@
 /* { dg-do compile } */
-/* { dg-options "-O -fdump-tree-sccp-details" } */
+/* { dg-options "-O2 -fdump-tree-sccp-details" } */
 
 /* To determine the number of iterations in this loop we need to fold
    p_4 + 4B > p_4 + 8B to false.  This transformation has caused