mirror of
https://gcc.gnu.org/git/gcc.git
synced 2026-02-22 03:46:53 -05:00
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:
committed by
Ian Lance Taylor
parent
b757d0317c
commit
fd37b08228
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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. */
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
6
gcc/testsuite/gcc.c-torture/compile/20080419-1.c
Normal file
6
gcc/testsuite/gcc.c-torture/compile/20080419-1.c
Normal file
@@ -0,0 +1,6 @@
|
||||
extern void *f();
|
||||
void dmi_scan_machine(void) {
|
||||
char *p = f(), *q;
|
||||
for (q = p; q < p + 10; q++)
|
||||
;
|
||||
}
|
||||
13
gcc/testsuite/gcc.dg/Wstrict-overflow-22.c
Normal file
13
gcc/testsuite/gcc.dg/Wstrict-overflow-22.c
Normal 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" } */
|
||||
}
|
||||
16
gcc/testsuite/gcc.dg/no-strict-overflow-7.c
Normal file
16
gcc/testsuite/gcc.dg/no-strict-overflow-7.c
Normal 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" } } */
|
||||
16
gcc/testsuite/gcc.dg/strict-overflow-6.c
Normal file
16
gcc/testsuite/gcc.dg/strict-overflow-6.c
Normal 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" } } */
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user