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]; And at this point p1 and p2 are different types, so the compiler can freely assume that p1 and p2 are non-overlapping. Thus the two assignments can be "safely" reordered. Sounds plausible to me. And note that casting via void* won't help. "p == (void*)p" compares a variable of type "exec_node*" to a variable of type "void*", and thus there's no strict-aliasing problem. But "p == (exec_node**)(void*)p" compares an "exec_node*" to an "exec_node**" and thus the compiler can assume that they are not the same. eirik _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev