c-family: Use TYPE_OVERFLOW_UNDEFINED instead of !TYPE_UNSIGNED in pointer_sum [PR95903]
For lp64 targets and int off ... ptr[off + 1] is lowered in pointer_sum to *(ptr + ((sizetype) off + (sizetype) 1)). That is fine when signed integer wrapping is undefined (and is not done already if off has unsigned type), but changes behavior for -fwrapv, where overflow is well defined. Runtime test could be: int main () { char *p = __builtin_malloc (0x100000000UL); if (!p) return 0; char *q = p + 0x80000000UL; int o = __INT_MAX__; q[o + 1] = 1; if (q[-__INT_MAX__ - 1] != 1) __builtin_abort (); return 0; } with -fwrapv or so, not included in the testsuite because it requires 4GB allocation (with some other test it would be enough to have something slightly above 2GB, but still...). 2020-06-27 Jakub Jelinek <jakub@redhat.com> PR middle-end/95903 gcc/c-family/ * c-common.c (pointer_int_sum): Use TYPE_OVERFLOW_UNDEFINED instead of !TYPE_UNSIGNED check to see if we can apply distributive law and handle smaller precision intop operands separately. gcc/testsuite/ * c-c++-common/pr95903.c: New test.
This commit is contained in:
parent
daaed0199e
commit
3799596098
@ -3141,7 +3141,7 @@ pointer_int_sum (location_t loc, enum tree_code resultcode,
|
||||
/* If the constant is unsigned, and smaller than the pointer size,
|
||||
then we must skip this optimization. This is because it could cause
|
||||
an overflow error if the constant is negative but INTOP is not. */
|
||||
&& (!TYPE_UNSIGNED (TREE_TYPE (intop))
|
||||
&& (TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (intop))
|
||||
|| (TYPE_PRECISION (TREE_TYPE (intop))
|
||||
== TYPE_PRECISION (TREE_TYPE (ptrop)))))
|
||||
{
|
||||
|
19
gcc/testsuite/c-c++-common/pr95903.c
Normal file
19
gcc/testsuite/c-c++-common/pr95903.c
Normal file
@ -0,0 +1,19 @@
|
||||
/* PR middle-end/95903 */
|
||||
/* { dg-do compile { target lp64 } } */
|
||||
/* { dg-options "-O2 -fwrapv -fdump-tree-optimized" } */
|
||||
/* Verify that for -fwrapv the + 1 addition is performed in the parameter's
|
||||
type before sign extending it. */
|
||||
/* { dg-final { scan-tree-dump-times "off_\[0-9]+\\\(D\\\) \\+ 1" 2 "optimized" } } */
|
||||
|
||||
char
|
||||
foo (const char *ptr, int off)
|
||||
{
|
||||
off += 1;
|
||||
return ptr[off];
|
||||
}
|
||||
|
||||
char
|
||||
bar (const char *ptr, int off)
|
||||
{
|
||||
return ptr[off + 1];
|
||||
}
|
Loading…
Reference in New Issue
Block a user