flags.h (POINTER_TYPE_OVERFLOW_UNDEFINED): Define.

./:	* 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
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 6970062..5487418 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 5514943..7f5b38f 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -5490,13 +5490,22 @@
 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
diff --git a/gcc/flags.h b/gcc/flags.h
index 5d5f079..a6d5b24 100644
--- a/gcc/flags.h
+++ b/gcc/flags.h
@@ -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 @@
 #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.  */
 
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index dde8f88..4a1cc2c 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -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 @@
 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 @@
   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 @@
      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 @@
 	  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 @@
 
 	  /* 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)
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index b5ddb38..6ef2644 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
index 0000000..b257fea
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/compile/20080419-1.c
@@ -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
index 0000000..4b84387
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Wstrict-overflow-22.c
@@ -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
index 0000000..07ad27b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/no-strict-overflow-7.c
@@ -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
index 0000000..ec1266d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/strict-overflow-6.c
@@ -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" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/loop-17.c b/gcc/testsuite/gcc.dg/tree-ssa/loop-17.c
index 26e4986..6db543c 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/loop-17.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/loop-17.c
@@ -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