On December 15, 2017 4:58:14 PM GMT+01:00, Martin Sebor <mse...@gmail.com> 
wrote:
>On 12/15/2017 01:48 AM, Richard Biener wrote:
>> On Thu, Dec 14, 2017 at 5:01 PM, Martin Sebor <mse...@gmail.com>
>wrote:
>>> On 12/14/2017 03:43 AM, Richard Biener wrote:
>>>>
>>>> On Wed, Dec 13, 2017 at 4:47 AM, Martin Sebor <mse...@gmail.com>
>wrote:
>>>>>
>>>>> On 12/12/2017 05:35 PM, Jeff Law wrote:
>>>>>>
>>>>>>
>>>>>> On 12/12/2017 01:15 PM, Martin Sebor wrote:
>>>>>>>
>>>>>>>
>>>>>>> Bug 83373 - False positive reported by -Wstringop-overflow, is
>>>>>>> another example of warning triggered by a missed optimization
>>>>>>> opportunity, this time in the strlen pass.  The optimization
>>>>>>> is discussed in pr78450 - strlen(s) return value can be assumed
>>>>>>> to be less than the size of s.  The gist of it is that the
>result
>>>>>>> of strlen(array) can be assumed to be less than the size of
>>>>>>> the array (except in the corner case of last struct members).
>>>>>>>
>>>>>>> To avoid the false positive the attached patch adds this
>>>>>>> optimization to the strlen pass.  Although the patch passes
>>>>>>> bootstrap and regression tests for all front-ends I'm not sure
>>>>>>> the way it determines the upper bound of the range is 100%
>>>>>>> correct for languages with arrays with a non-zero lower bound.
>>>>>>> Maybe it's just not as tight as it could be.
>>>>>>
>>>>>>
>>>>>> What about something hideous like
>>>>>>
>>>>>> struct fu {
>>>>>>   char x1[10];
>>>>>>   char x2[10];
>>>>>>   int avoid_trailing_array;
>>>>>> }
>>>>>>
>>>>>> Where objects stored in x1 are not null terminated.  Are we in
>the realm
>>>>>> of undefined behavior at that point (I hope so)?
>>>>>
>>>>>
>>>>>
>>>>> Yes, this is undefined.  Pointer arithmetic (either direct or
>>>>> via standard library functions) is only defined for pointers
>>>>> to the same object or subobject.  So even something like
>>>>>
>>>>>  memcpy (pfu->x1, pfu->x1 + 10, 10);
>>>>>
>>>>> is undefined.
>>>>
>>>>
>>>> There's nothing undefined here - computing the pointer pointing
>>>> to one-after-the-last element of an array is valid (you are just
>>>> not allowed to dereference it).
>>>
>>>
>>> Right, and memcpy dereferences it, so it's undefined.
>>
>> That's interpretation of the standard that I don't share.
>
>It's not an interpretation.  It's a basic rule of the languages
>that the standards are explicit about.  In C11 you will find
>this specified in detail in 6.5.6, paragraph 7 and 8 (of
>particular relevance to your question below is p7: "a pointer
>to an object that is not an element of an array behaves the same
>as a pointer to the first element of an array of length one.")

I know. 

>> Also, if I have struct f { int i; int j; };  and a int * that points
>> to the j member you say I have no standard conforming way
>> to get at a pointer to the i member from this, right?
>
>Correct.  See above.
>
>> Because
>> the pointer points to an 'int' object.  But it also points within
>> a struct f object!  So at least maybe (int *)((char *)p - offsetof
>> (struct f, j))
>> should be valid?
>
>No, not really.  It works in practice but it's not well-defined.
>It doesn't matter how you get at the result.  What matters is
>what you start with.  As Jeff said, to derive a pointer to
>distinct suobjects of a larger object you need to start with
>a pointer to the larger object and treat it as an array of
>chars.

That's obviously not constraints people use C and C++ with so I see no way to 
enforce this within gimple.

>> This means that pfu->x1 + 10 is a valid pointer
>> into *pfu no matter what you say and you can dereference it.
>
>No.
>
>As another hopefully more convincing example consider a multi-
>dimensional array A[2][2].  The value of the offset of A[i][j]
>is sizeof A[i] + j.  With that, the offset of A[1][0] is
>sizeof A[1] + 0, and so would be the offset of A[0][2]. But
>that doesn't make A[0][2] a valid reference to an element of
>A (because A[0] has only two elements, A[0][0] and A[0][1]),
>or &A[0] + 2 a derefernceable pointer.  It's a pointer that
>points just past the last element of the array A[0].  That
>there's another array right after A[0] (namely A[1]) is
>immaterial, same as in the struct f example above.

I know. Dependence analysis relies on this. We've had bugs in the past with gcc 
itself introducing such bogus references. 

Richard. 

>
>Martin

Reply via email to