Francisco Jerez <curroje...@riseup.net> writes:

> Erik Faye-Lund <kusmab...@gmail.com> writes:
>
>> On Fri, Jun 26, 2015 at 4:01 PM, Francisco Jerez <curroje...@riseup.net> 
>> wrote:
>>> Davin McCall <dav...@davmac.org> writes:
>>>
>>>> On 26/06/15 14:31, Eirik Byrkjeflot Anonsen wrote:
>>>>> Erik Faye-Lund <kusmab...@gmail.com> writes:
>>>>>
>>>>>> On Fri, Jun 26, 2015 at 1:23 PM, Davin McCall <dav...@davmac.org> wrote:
>>>>>>> On 26/06/15 12:03, Davin McCall wrote:
>>>>>>>> ... The stored value of 'n' is not accessed by any other type than the
>>>>>>>> type of n itself. This value is then cast to a different pointer type. 
>>>>>>>> You
>>>>>>>> are mistaken if you think that the cast accesses the stored value of 
>>>>>>>> n. The
>>>>>>>> other "stored value" access that it occurs in that expression is to the
>>>>>>>> object pointed at by the result of the cast. [...]:
>>>>>>>
>>>>>>> I'm sorry, I think that was phrased somewhat abrasively, which I did not
>>>>>>> intend. Let me try this part again. If we by break up the expression in
>>>>>>> order of evaluation:
>>>>>>>
>>>>>>> From:
>>>>>>>     return ((const struct exec_node **)n)[0]
>>>>>>>
>>>>>>> In order of evaluation:
>>>>>>>
>>>>>>> n
>>>>>>> - which accesses the stored value of n, i.e. a value of type 'struct 
>>>>>>> exec
>>>>>>> node *', via n, which is obviously of that type.
>>>>>>>
>>>>>>> (const struct exec_node **)n
>>>>>>>   - which casts that value, after it has been retrieved, to another 
>>>>>>> type. If
>>>>>>> this were an aliasing violation, then casting any pointer variable to
>>>>>>> another type would be an aliasing violation; this is clearly not the 
>>>>>>> case.
>>>>>>>
>>>>>>> ((const struct exec_node **)n)[0]
>>>>>>> - which de-references the result of the above cast, thereby accessing a
>>>>>>> stored value of type 'exec node *' using a glvalue of type 'exec node 
>>>>>>> *'.
>>>>>> I think breaking this up is a mistake, because the strict-aliasing
>>>>>> rules is explicitly about the *combination* of these two things.
>>>>>>
>>>>>> You *are* accessing the underlying memory of 'n' through a different
>>>>>> type, and this is what strict aliasing is all about. But it takes two
>>>>>> steps, a single step isn't enough to do so.
>>>>>>
>>>>>> Those other spec-quotes doesn't undo the strict-aliasing definitions;
>>>>>> knowing how things are laid out in memory doesn't mean the compiler
>>>>>> cannot assume two differently typed variables doesn't overlap.
>>>>> So basically, you're saying that e.g.:
>>>>>
>>>>>     p->next = a;
>>>>>     q = exec_node_get_next_const(p);
>>>>>
>>>>> is equivalent to:
>>>>>
>>>>>     exec_node * p1 = p;
>>>>>     exec_node ** p2 = (exec_node**)p;
>>>>>     p1->next = a;
>>>>>     q = p2[0];
>>>>
>>>> It is, once the patch is applied (or if strict aliasing is disabled).
>>>>
>>>>> And at this point p1 and p2 are different types, so the compiler can
>>>>> freely assume that p1 and p2 are non-overlapping.
>>>>
>>>> p1 and p2 are two separate variables and of course they are
>>>> non-overlapping, but *p1 and **p2 are the same type and so may overlap.
>>>>
>>> Also note that even *p1 and *p2 are allowed to overlap even though they
>>> are of different types because of section 6.5 of C99:
>>>
>>> | 7 An object shall have its stored value accessed only by an lvalue
>>> |   expression that has one of the following types:
>>> |[...]
>>> |    - an aggregate or union type that includes one of the aforementioned
>>> |      types among its members (including, recursively, a member of a
>>> |      subaggregate or contained union)[...]
>>
>> I don't see how this wording legitimates the code above. There's no
>> unions involved, so that part is irrelevant.
>
> Yeah, only the "aggregate" part is relevant.
>
>> And "n" isn't an aggregate type, it's a pointer type that happens to
>> point to an aggregate type, no? But even if it were, it needs to
>> include one of the "aforementioned" types among its members, which I
>> cannot see that it does either.
>>
>> Care to explain?
>
> In the example this was replying to, *p1 was an lvalue of aggregate type
> (struct exec_node), and *p2 (or equivalently p2[0]) was an lvalue of
> type "struct exec_node *".  The latter is "a type compatible with the
> effective type of the object", the object being the "next" member of an
> aggregate object of type "struct exec_node", hence the text quoted above
> applies and *p1 and *p2 may legitimately alias the same object.

The argument makes sense. As I said, I haven't been carefully thinking
about aliasing issues, and I have a feeling that there is "obviously
correct code" that probably requires this to work. If my example was
broken, it would probably break stuff that shouldn't break.

eirik
_______________________________________________
mesa-dev mailing list
mesa-dev@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/mesa-dev

Reply via email to