flags.h (POINTER_TYPE_OVERFLOW_UNDEFINED): Define.

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
This commit is contained in:
Ian Lance Taylor 2008-04-14 19:18:31 +00:00 committed by Ian Lance Taylor
parent 3a5a8be120
commit 4c9db6e07a
8 changed files with 88 additions and 7 deletions

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

View 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

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

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

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

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