[Mesa-dev] [PATCH v2] glsls: Modify exec_list to avoid strict-aliasing violations
Erik Faye-Lund
kusmabite at gmail.com
Fri Jun 26 08:44:30 PDT 2015
On Fri, Jun 26, 2015 at 5:32 PM, Davin McCall <davmac at davmac.org> wrote:
> On 26/06/15 15:29, Erik Faye-Lund wrote:
>
> On Fri, Jun 26, 2015 at 4:16 PM, Davin McCall <davmac at davmac.org> wrote:
>
> On 26/06/15 14:53, Erik Faye-Lund wrote:
>
> On Fri, Jun 26, 2015 at 3:05 PM, Davin McCall <davmac at davmac.org> wrote:
>
> [...]
>
> It is. In fact, it's not even possible to violate strict-aliasing
> without doing at least two operations. You cannot validate operations
> in a vacuum, because that's not how strict-aliasing is defined.
>
> Any pointer dereference can violate strict aliasing - that's one operation.
> If you mean that it's first necessary to construct a pointer value in such a
> way that de-referencing it will be an aliasing violation, then yes, I agree
> with this statement.
>
> Yes, I mean exactly the latter. You cannot look at one operation in
> isolation, you need to look at the whole program.
>
> As I have pointed out, with your reading,
> pretty much any pointer cast constitutes an aliasing violation.
>
> No, only those violating the strict aliasing rules I posted before.
>
> ... which would only allow changing const/volatile qualifiers, not the
> pointed-to type.
>
> You can change the pointed to type in terms of signedness, you can
> cast it to a compatible type, you can cast a void-pointer or
> char-pointer to any type. But you need to make sure you don't violate
> the strict-aliasing rules in some other way while doing the latter.
>
>
> A cast by itself simply can't cause an aliasing violation, because it
> doesn't "access the stored value of an object". The aliasing violation has
> to happen either before or after the cast.
>
>
> Aliasing *is* hard. But let's not go shopping for that reason.
>
>
> Agreed, though maybe this is getting to the point where we should take it
> off-list.
>
>
> Your reading also disallows casting an 'int' variable to type 'long',
> because that isn't on the list.
>
> The strict aliasing rules specify what kind of reference you can use to
> access an object of a particular type. They say nothing about how that
> reference is obtained.
>
> Which means that it applies regardless of how you obtain it.
>
> Yes.
>
> "If a program attempts to access the stored value of an object through
> a glvalue of other than one of the following types the behavior is
> undefined"
>
> It says "if a *program* attempts", not "if a *statement* attempts" or
> "if an *opreation* attempts". This is a whole-program deal, not
> limited to one operation in isolation.
>
> The key part of the wording is "through a glvalue":
>
> "If a program attempts to access the stored value of an object *through
> a glvalue* of other than one of the following types ..."
>
> This is exactly what makes this invalid AFAICT, see below.
>
> Going back to the original example:
>
> return ((const struct exec_node **)n)[0]
>
> The glvalue used to access the object in n is n itself. (I do not think that
> '(const struct exec_node **)n' is even a glvalue).
>
> Bur 'n' *is* an lvalue, which also makes it an glvalue (for reference,
> a glvalue is a "generalized lvalue", which means that it's either an
> lvalue or an xvalue).
>
>
> 'n' is an lvalue, yes. Its type is 'struct exec node *' (disregarding const
> for now). So when the object that is in 'n' is accessed, it is accessed via
> an appropriate type. The cast does not itself cause an access and the cast
> expression as a whole is not an lvalue.
>
> The fact that n is an lvalue does not mean that it can appear anywhere on
> the left-hand-side of an assignment expression; the entire left-hand-side
> expression must be an lvalue. So when you then say:
>
> You can write stuff like:
>
> "((const struct exec_node **)n)[0] = foo;"
>
> ...so it can appear on the left-hand side of an assignment, which
> makes it an lvalue.
>
>
> ... it is not quite correct. The fact that you could put n itself on the
> left-hand side of an assignment (eg "n = NULL") makes it an lvalue, not the
> fact that it appears *within* a larger expression that is on the left-hand
> side of an assignment.
>
> In fact, the whole of '((const struct exec_node **)n)[0]' is an lvalue.
> However, '(const struct exec_node **)n' is not an lvalue.
>
> I do believe you have some sort of misconception, and I'm trying hard to
> understand the nature of this misconception.
I think Francisco managed to clear it up. Yeah, you're right, I had
the misconception that "(const struct exec_node **)n" was an lvalue.
But it's not, and that makes my whole line of arguing invalid. So
yeah, I no longer think the proposed code violates the strict-aliasing
rules. Sorry for the noise.
More information about the mesa-dev
mailing list