[PR middle-end/79123] cast false positive in -Walloca-larger-than=

Martin Sebor msebor@gmail.com
Mon Jan 23 15:56:00 GMT 2017


>> Yes, I see that.  But when I change size_t to unsigned int (in LP64)
>> like so:
>>
>>   void g (int *p, int *q)
>>   {
>>     unsigned n = (unsigned)(p - q);
>>
>>     if (n < 10)
>>       f (__builtin_alloca (n));
>>   }
>>
>> -Walloca-larger-than=100 still complains:
>>
>>   warning: argument to ‘alloca’ may be too large
>>   note: limit is 100 bytes, but argument may be as large as 4294967295
>>
>> and the VRP dump shows
>>
>>   _5: [0, 4294967295]
>>   _14: [0, 4294967295]
>>   ...
>>     _3 = p.0_1 - q.1_2;
>>     _4 = _3 /[ex] 4;
>>     n_10 = (unsigned int) _4;
>>     if (n_10 <= 9)
>>       goto <bb 3>; [36.64%]
>>     else
>>       goto <bb 4>; [63.36%]
>>
>>     <bb 3> [36.64%]:
>>     _14 = _4 & 4294967295;
>>     _5 = (long unsigned int) _14;
>>     _6 = __builtin_alloca (_5);
>>
>> so it seems that even in VRP itself the range information isn't
>> quite good enough to avoid false positives.  (Perhaps that's one
>> the missed cases you mention below?)
>
> Well, you see that there's no obvious way to use the n_10 <= 9 conditional
> here.  VRP would need to register a [0, 9] range for the lower half of n_10
> and then figure after seeing
>
>>     _14 = _4 & 4294967295;
>
> that _14 is now [0, 9].
>
> That's a neat trick VRP cannot handle at the moment (there's no way the
> lattice can encode a range for a sub-set of all bits of a SSA name).

Sure.  My point is just that it looks like there will be some false
positives whether the warnings are implemented as part of the VRP
pass or elsewhere.  (I admit I haven't studied the implementation
of the VRP pass to understand whether these false positives are
avoidable and I'm happy to take your word if if you say they can.)

> Your source is bogus in the way that (unsigned)(p - q) might truncate
> the pointer difference.

The problem is independent of the pointer difference and can be
reproduced by any conversion from a wider type to a narrower
unsigned type (even the safe ones), as the test case in bug 79191
I opened for it shows:

   void f (unsigned long n)
   {
     if (n > 3)
       __builtin_abort ();
   }

   void h (unsigned long m)
   {
     unsigned n = m;

     if (n < 3)
       f (n);
   }

Martin



More information about the Gcc-patches mailing list