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
This commit is contained in:
Ian Lance Taylor
2008-05-12 18:04:51 +00:00
committed by Ian Lance Taylor
parent b757d0317c
commit 08c9b67abb
10 changed files with 146 additions and 11 deletions

View 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

View 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

View 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. */

View 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)

View 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

View File

@@ -0,0 +1,6 @@
extern void *f();
void dmi_scan_machine(void) {
char *p = f(), *q;
for (q = p; q < p + 10; q++)
;
}

View File

@@ -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" } */
}

View File

@@ -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" } } */

View File

@@ -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" } } */

View 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