[Mesa-dev] [PATCH v2] glsls: Modify exec_list to avoid strict-aliasing violations

Erik Faye-Lund kusmabite at gmail.com
Fri Jun 26 08:05:46 PDT 2015

On Fri, Jun 26, 2015 at 4:01 PM, Francisco Jerez <currojerez at riseup.net> wrote:
> Davin McCall <davmac at davmac.org> writes:
>> On 26/06/15 14:31, Eirik Byrkjeflot Anonsen wrote:
>>> Erik Faye-Lund <kusmabite at gmail.com> writes:
>>>> On Fri, Jun 26, 2015 at 1:23 PM, Davin McCall <davmac at 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. 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?

More information about the mesa-dev mailing list