diff mbox

[PR,c/71699] Handle pointer arithmetic in nonzero tree checks

Message ID CAFOnWk=xveuB-LNHHz4rE9+8vZK5yNfRPCTt5DUQs4ALdPKdtQ@mail.gmail.com
State New
Headers show

Commit Message

Manish Goregaokar June 30, 2016, 11:17 a.m. UTC
gcc/ChangeLog:
    PR c/71699
    * fold-const.c (tree_binary_nonzero_warnv_p): Allow
    pointer addition to also be considered nonzero.
---
 gcc/fold-const.c | 20 +++++++++++++-------
 1 file changed, 13 insertions(+), 7 deletions(-)

Comments

Richard Biener June 30, 2016, 11:55 a.m. UTC | #1
On Thu, Jun 30, 2016 at 1:17 PM, Manish Goregaokar <manish@mozilla.com> wrote:
> gcc/ChangeLog:
>     PR c/71699
>     * fold-const.c (tree_binary_nonzero_warnv_p): Allow
>     pointer addition to also be considered nonzero.
> ---
>  gcc/fold-const.c | 20 +++++++++++++-------
>  1 file changed, 13 insertions(+), 7 deletions(-)
>
> diff --git a/gcc/fold-const.c b/gcc/fold-const.c
> index 3b9500d..eda713e 100644
> --- a/gcc/fold-const.c
> +++ b/gcc/fold-const.c
> @@ -13200,16 +13200,22 @@ tree_binary_nonzero_warnv_p (enum tree_code code,
>      {
>      case POINTER_PLUS_EXPR:
>      case PLUS_EXPR:
> -      if (ANY_INTEGRAL_TYPE_P (type) && TYPE_OVERFLOW_UNDEFINED (type))
> +      if ((ANY_INTEGRAL_TYPE_P (type) && TYPE_OVERFLOW_UNDEFINED (type))
> +          || POINTER_TYPE_P (type))
>      {
> +      /* Pointers are always nonnegative, check integers.  */
> +      if (ANY_INTEGRAL_TYPE_P (type))
> +      {
> +          sub_strict_overflow_p = false;
> +          if (!tree_expr_nonnegative_warnv_p (op0,
> +                              &sub_strict_overflow_p)
> +              || !tree_expr_nonnegative_warnv_p (op1,
> +                             &sub_strict_overflow_p))
> +            return false;
> +      }
>        /* With the presence of negative values it is hard
>           to say something.  */
> -      sub_strict_overflow_p = false;
> -      if (!tree_expr_nonnegative_warnv_p (op0,
> -                          &sub_strict_overflow_p)
> -          || !tree_expr_nonnegative_warnv_p (op1,
> -                         &sub_strict_overflow_p))
> -        return false;
> +

Hmm, note that op1 of POINTER_PLUS_EXPR _is_ an integer that needs to be treated
as signed.

POINTER_PLUS_EXPR is special in other ways in that iff
flag_delete_null_pointer_checks
is set we can assume that ptr + non-zero is never zero.  Thus simply do

   case POINTER_PLUS_EXPR:
      return flag_delete_null_pointer_checks
               && (tree_expr_nonzero_warnv_p (op0, strict_overflow_p)
                     || tree_expr_nonzero_warnv_p (op1, strict_overflow_p));

OTOH ptr + -(uintptr_t)ptr is valid from a POINTER_PLUS_EXPR
perspective as GCC does
not have a special tree code for pointer subtraction (but IIRC it uses
MINUS_EXPR on integers
for this).

Richard.


>        /* One of operands must be positive and the other non-negative.  */
>        /* We don't set *STRICT_OVERFLOW_P here: even if this value
>           overflows, on a twos-complement machine the sum of two
> --
> 2.8.3
Manish Goregaokar June 30, 2016, 12:03 p.m. UTC | #2
What about ptr + intptr_t? I guess we should check nonnegative for op1 then?
-Manish


On Thu, Jun 30, 2016 at 5:25 PM, Richard Biener
<richard.guenther@gmail.com> wrote:
> On Thu, Jun 30, 2016 at 1:17 PM, Manish Goregaokar <manish@mozilla.com> wrote:
>> gcc/ChangeLog:
>>     PR c/71699
>>     * fold-const.c (tree_binary_nonzero_warnv_p): Allow
>>     pointer addition to also be considered nonzero.
>> ---
>>  gcc/fold-const.c | 20 +++++++++++++-------
>>  1 file changed, 13 insertions(+), 7 deletions(-)
>>
>> diff --git a/gcc/fold-const.c b/gcc/fold-const.c
>> index 3b9500d..eda713e 100644
>> --- a/gcc/fold-const.c
>> +++ b/gcc/fold-const.c
>> @@ -13200,16 +13200,22 @@ tree_binary_nonzero_warnv_p (enum tree_code code,
>>      {
>>      case POINTER_PLUS_EXPR:
>>      case PLUS_EXPR:
>> -      if (ANY_INTEGRAL_TYPE_P (type) && TYPE_OVERFLOW_UNDEFINED (type))
>> +      if ((ANY_INTEGRAL_TYPE_P (type) && TYPE_OVERFLOW_UNDEFINED (type))
>> +          || POINTER_TYPE_P (type))
>>      {
>> +      /* Pointers are always nonnegative, check integers.  */
>> +      if (ANY_INTEGRAL_TYPE_P (type))
>> +      {
>> +          sub_strict_overflow_p = false;
>> +          if (!tree_expr_nonnegative_warnv_p (op0,
>> +                              &sub_strict_overflow_p)
>> +              || !tree_expr_nonnegative_warnv_p (op1,
>> +                             &sub_strict_overflow_p))
>> +            return false;
>> +      }
>>        /* With the presence of negative values it is hard
>>           to say something.  */
>> -      sub_strict_overflow_p = false;
>> -      if (!tree_expr_nonnegative_warnv_p (op0,
>> -                          &sub_strict_overflow_p)
>> -          || !tree_expr_nonnegative_warnv_p (op1,
>> -                         &sub_strict_overflow_p))
>> -        return false;
>> +
>
> Hmm, note that op1 of POINTER_PLUS_EXPR _is_ an integer that needs to be treated
> as signed.
>
> POINTER_PLUS_EXPR is special in other ways in that iff
> flag_delete_null_pointer_checks
> is set we can assume that ptr + non-zero is never zero.  Thus simply do
>
>    case POINTER_PLUS_EXPR:
>       return flag_delete_null_pointer_checks
>                && (tree_expr_nonzero_warnv_p (op0, strict_overflow_p)
>                      || tree_expr_nonzero_warnv_p (op1, strict_overflow_p));
>
> OTOH ptr + -(uintptr_t)ptr is valid from a POINTER_PLUS_EXPR
> perspective as GCC does
> not have a special tree code for pointer subtraction (but IIRC it uses
> MINUS_EXPR on integers
> for this).
>
> Richard.
>
>
>>        /* One of operands must be positive and the other non-negative.  */
>>        /* We don't set *STRICT_OVERFLOW_P here: even if this value
>>           overflows, on a twos-complement machine the sum of two
>> --
>> 2.8.3
Richard Biener June 30, 2016, 1:15 p.m. UTC | #3
On Thu, Jun 30, 2016 at 2:03 PM, Manish Goregaokar <manish@mozilla.com> wrote:
> What about ptr + intptr_t? I guess we should check nonnegative for op1 then?

op1 will always be nonnegative as it is forced to sizetype type (which
is unsigned).

Richard.

> -Manish
>
>
> On Thu, Jun 30, 2016 at 5:25 PM, Richard Biener
> <richard.guenther@gmail.com> wrote:
>> On Thu, Jun 30, 2016 at 1:17 PM, Manish Goregaokar <manish@mozilla.com> wrote:
>>> gcc/ChangeLog:
>>>     PR c/71699
>>>     * fold-const.c (tree_binary_nonzero_warnv_p): Allow
>>>     pointer addition to also be considered nonzero.
>>> ---
>>>  gcc/fold-const.c | 20 +++++++++++++-------
>>>  1 file changed, 13 insertions(+), 7 deletions(-)
>>>
>>> diff --git a/gcc/fold-const.c b/gcc/fold-const.c
>>> index 3b9500d..eda713e 100644
>>> --- a/gcc/fold-const.c
>>> +++ b/gcc/fold-const.c
>>> @@ -13200,16 +13200,22 @@ tree_binary_nonzero_warnv_p (enum tree_code code,
>>>      {
>>>      case POINTER_PLUS_EXPR:
>>>      case PLUS_EXPR:
>>> -      if (ANY_INTEGRAL_TYPE_P (type) && TYPE_OVERFLOW_UNDEFINED (type))
>>> +      if ((ANY_INTEGRAL_TYPE_P (type) && TYPE_OVERFLOW_UNDEFINED (type))
>>> +          || POINTER_TYPE_P (type))
>>>      {
>>> +      /* Pointers are always nonnegative, check integers.  */
>>> +      if (ANY_INTEGRAL_TYPE_P (type))
>>> +      {
>>> +          sub_strict_overflow_p = false;
>>> +          if (!tree_expr_nonnegative_warnv_p (op0,
>>> +                              &sub_strict_overflow_p)
>>> +              || !tree_expr_nonnegative_warnv_p (op1,
>>> +                             &sub_strict_overflow_p))
>>> +            return false;
>>> +      }
>>>        /* With the presence of negative values it is hard
>>>           to say something.  */
>>> -      sub_strict_overflow_p = false;
>>> -      if (!tree_expr_nonnegative_warnv_p (op0,
>>> -                          &sub_strict_overflow_p)
>>> -          || !tree_expr_nonnegative_warnv_p (op1,
>>> -                         &sub_strict_overflow_p))
>>> -        return false;
>>> +
>>
>> Hmm, note that op1 of POINTER_PLUS_EXPR _is_ an integer that needs to be treated
>> as signed.
>>
>> POINTER_PLUS_EXPR is special in other ways in that iff
>> flag_delete_null_pointer_checks
>> is set we can assume that ptr + non-zero is never zero.  Thus simply do
>>
>>    case POINTER_PLUS_EXPR:
>>       return flag_delete_null_pointer_checks
>>                && (tree_expr_nonzero_warnv_p (op0, strict_overflow_p)
>>                      || tree_expr_nonzero_warnv_p (op1, strict_overflow_p));
>>
>> OTOH ptr + -(uintptr_t)ptr is valid from a POINTER_PLUS_EXPR
>> perspective as GCC does
>> not have a special tree code for pointer subtraction (but IIRC it uses
>> MINUS_EXPR on integers
>> for this).
>>
>> Richard.
>>
>>
>>>        /* One of operands must be positive and the other non-negative.  */
>>>        /* We don't set *STRICT_OVERFLOW_P here: even if this value
>>>           overflows, on a twos-complement machine the sum of two
>>> --
>>> 2.8.3
diff mbox

Patch

diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index 3b9500d..eda713e 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -13200,16 +13200,22 @@  tree_binary_nonzero_warnv_p (enum tree_code code,
     {
     case POINTER_PLUS_EXPR:
     case PLUS_EXPR:
-      if (ANY_INTEGRAL_TYPE_P (type) && TYPE_OVERFLOW_UNDEFINED (type))
+      if ((ANY_INTEGRAL_TYPE_P (type) && TYPE_OVERFLOW_UNDEFINED (type))
+          || POINTER_TYPE_P (type))
     {
+      /* Pointers are always nonnegative, check integers.  */
+      if (ANY_INTEGRAL_TYPE_P (type))
+      {
+          sub_strict_overflow_p = false;
+          if (!tree_expr_nonnegative_warnv_p (op0,
+                              &sub_strict_overflow_p)
+              || !tree_expr_nonnegative_warnv_p (op1,
+                             &sub_strict_overflow_p))
+            return false;
+      }
       /* With the presence of negative values it is hard
          to say something.  */
-      sub_strict_overflow_p = false;
-      if (!tree_expr_nonnegative_warnv_p (op0,
-                          &sub_strict_overflow_p)
-          || !tree_expr_nonnegative_warnv_p (op1,
-                         &sub_strict_overflow_p))
-        return false;
+
       /* One of operands must be positive and the other non-negative.  */
       /* We don't set *STRICT_OVERFLOW_P here: even if this value
          overflows, on a twos-complement machine the sum of two