On August 7, 2018 4:24:42 AM GMT+02:00, Martin Sebor <mse...@gmail.com> wrote:
>On 07/26/2018 02:55 AM, Richard Biener wrote:
>> On Wed, 25 Jul 2018, Martin Sebor wrote:
>>
>>>> BUT - for the string_constant and c_strlen functions we are,
>>>> in all cases we return something interesting, able to look
>>>> at an initializer which then determines that type.  Hopefully.
>>>> I think the strlen() folding code when it sets SSA ranges
>>>> now looks at types ...?
>>>>
>>>> Consider
>>>>
>>>> struct X { int i; char c[4]; int j;};
>>>> struct Y { char c[16]; };
>>>>
>>>> void foo (struct X *p, struct Y *q)
>>>> {
>>>>   memcpy (p, q, sizeof (struct Y));
>>>>   if (strlen ((char *)(struct Y *)p + 4) < 7)
>>>>     abort ();
>>>> }
>>>>
>>>> here the GIMPLE IL looks like
>>>>
>>>>   const char * _1;
>>>>
>>>>   <bb 2> [local count: 1073741825]:
>>>>   _5 = MEM[(char * {ref-all})q_4(D)];
>>>>   MEM[(char * {ref-all})p_6(D)] = _5;
>>>>   _1 = p_6(D) + 4;
>>>>   _2 = __builtin_strlen (_1);
>>>>
>>>> and I guess Martin would argue that since p is of type struct X
>>>> + 4 gets you to c[4] and thus strlen of that cannot be larger
>>>> than 3.  But of course the middle-end doesn't work like that
>>>> and luckily we do not try to draw such conclusions or we
>>>> are somehow lucky that for the testcase as written above we do not
>>>> (I'm not sure whether Martins changes in this area would derive
>>>> such conclusions in principle).
>>>
>>> Only if the strlen argument were p->c.
>>>
>>>> NOTE - we do not know the dynamic type here since we do not know
>>>> the dynamic type of the memory pointed-to by q!  We can only
>>>> derive that at q+4 there must be some object that we can
>>>> validly call strlen on (where Martin again thinks strlen
>>>> imposes constrains that memchr does not - sth I do not agree
>>>> with from a QOI perspective)
>>>
>>> The dynamic type is a murky area.
>>
>> It's well-specified in the middle-end.  A store changes the
>> dynamic type of the stored-to object.  If that type is
>> compatible with the surrounding objects dynamic type that one
>> is not affected, if not then the surrounding objects dynamic
>> type becomes unspecified.  There is TYPE_TYPELESS_STORAGE
>> to somewhat control "compatibility" of subobjects.
>
>I never responded to this.  Using a dynamic (effective) type as
>you describe it would invalidate the aggressive loop optimization
>in the following:
>
>   void foo (struct X *p)
>   {
>       struct Y y = { "12345678" };
>       memcpy (p, &y, sizeof (struct Y));
>
>       // *p effective type is now struct Y
>
>       int n = 0;
>       while (p->c[n])
>         ++n;
>
>       if (n < 7)
>         abort ();
>   }
>
>GCC unconditionally aborts, just as it does with strlen(p->c).
>Why is that not wrong (in either case)?
>
>Because the code is invalid either way, for two reasons:

No, because the storage has only 4 non-null characters starting at offset 4?

>1) it accesses an object of (effective) type struct Y via
>    an lvalue of type struct X (specifically via (*p).c)
>2) it relies on p->c
>
>The loop optimization relies on the exact same requirement
>as the strlen one.  Either they are both valid or neither is.
>
>Martin

Reply via email to