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