<html>
  <head>
    <meta content="text/html; charset=utf-8" http-equiv="Content-Type">
  </head>
  <body bgcolor="#FFFFFF" text="#000000">
    <div class="moz-cite-prefix">On 26/06/15 15:29, Erik Faye-Lund
      wrote:<br>
    </div>
    <blockquote
cite="mid:CABPQNSYZ-0MNaYb3bF3BxmgES3zYrdC-kAROeTu73r836YZ=Vg@mail.gmail.com"
      type="cite">
      <pre wrap="">On Fri, Jun 26, 2015 at 4:16 PM, Davin McCall <a class="moz-txt-link-rfc2396E" href="mailto:davmac@davmac.org"><davmac@davmac.org></a> wrote:
</pre>
      <blockquote type="cite">
        <pre wrap="">On 26/06/15 14:53, Erik Faye-Lund wrote:
</pre>
        <blockquote type="cite">
          <pre wrap="">
On Fri, Jun 26, 2015 at 3:05 PM, Davin McCall <a class="moz-txt-link-rfc2396E" href="mailto:davmac@davmac.org"><davmac@davmac.org></a> wrote:
</pre>
          <blockquote type="cite">
            <pre wrap="">[...]
</pre>
          </blockquote>
          <pre wrap="">
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.
</pre>
        </blockquote>
        <pre wrap="">

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.

</pre>
      </blockquote>
      <pre wrap="">
Yes, I mean exactly the latter. You cannot look at one operation in
isolation, you need to look at the whole program.

</pre>
      <blockquote type="cite">
        <blockquote type="cite">
          <pre wrap="">
</pre>
          <blockquote type="cite">
            <pre wrap="">As I have pointed out, with your reading,
pretty much any pointer cast constitutes an aliasing violation.

</pre>
          </blockquote>
          <pre wrap="">No, only those violating the strict aliasing rules I posted before.
</pre>
        </blockquote>
        <pre wrap="">

... which would only allow changing const/volatile qualifiers, not the
pointed-to type.

</pre>
      </blockquote>
      <pre wrap="">
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.</pre>
    </blockquote>
    <br>
    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.<br>
    <br>
    <blockquote
cite="mid:CABPQNSYZ-0MNaYb3bF3BxmgES3zYrdC-kAROeTu73r836YZ=Vg@mail.gmail.com"
      type="cite">
      <pre wrap="">

Aliasing *is* hard. But let's not go shopping for that reason.</pre>
    </blockquote>
    <br>
    Agreed, though maybe this is getting to the point where we should
    take it off-list.<br>
    <br>
    <blockquote
cite="mid:CABPQNSYZ-0MNaYb3bF3BxmgES3zYrdC-kAROeTu73r836YZ=Vg@mail.gmail.com"
      type="cite">
      <pre wrap="">

</pre>
      <blockquote type="cite">
        <pre wrap="">Your reading also disallows casting an 'int' variable to type 'long',
because that isn't on the list.

</pre>
        <blockquote type="cite">
          <pre wrap="">
</pre>
          <blockquote type="cite">
            <pre wrap="">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.
</pre>
          </blockquote>
          <pre wrap="">
Which means that it applies regardless of how you obtain it.
</pre>
        </blockquote>
        <pre wrap="">

Yes.

</pre>
        <blockquote type="cite">
          <pre wrap="">"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.
</pre>
        </blockquote>
        <pre wrap="">

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 ..."
</pre>
      </blockquote>
      <pre wrap="">
This is exactly what makes this invalid AFAICT, see below.

</pre>
      <blockquote type="cite">
        <pre wrap="">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).
</pre>
      </blockquote>
      <pre wrap="">
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).</pre>
    </blockquote>
    <br>
    '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.<br>
    <br>
    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:<br>
    <br>
    <blockquote type="cite">
      <pre wrap="">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.</pre>
    </blockquote>
    <br>
    ... 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.<br>
    <br>
    In fact, the whole of '((const struct exec_node **)n)[0]' is an
    lvalue. However, '(const struct exec_node **)n' is not an lvalue.<br>
    <br>
    I do believe you have some sort of misconception, and I'm trying
    hard to understand the nature of this misconception. Let's start
    with some stuff that I hope we can agree on (ignore the 'const' for
    now as it doesn't make much difference, unless you disagree?).
    Assume that the type of the variable 'n' is 'struct exec_node *'.<br>
    <br>
    1. The expression '((struct exec_node **)n)[0] = foo' accesses two
    objects - one is that represented by the variable 'n', and another
    that is pointed-to by the pointer value in 'n'.<br>
    2. In (1), the first access is a read, the other is due to the
    assignment operator.<br>
    3. The object represented by the variable 'n' is not modified by the
    expression (unless 'n' has been made to point to itself).<br>
    4. The type of the 'n' object is 'struct exec_node *'<br>
    5. The type of the sub-expression 'n' is also 'struct exec_node *'.<br>
    6. The type of the sub-expression '(struct exec_node **)n' is
    'struct exec_node **'.<br>
    7. The type of the whole expression, '((struct exec_node **)n)[0] =
    foo', is 'struct exec_node *'.<br>
    <br>
    I think you would say the following (though I'd disagree):<br>
    8. The expression '((struct exec_node **)n)[0] = foo' necessarily
    causes an aliasing violation, assuming it doesn't cause undefined
    behavior for any other reason (i.e. assuming n is not null and is a
    valid pointer etc).<br>
    9. The statement 'return ((struct exec_node **)n)[0];' necessarily
    causes an aliasing violation, assuming it doesn't cause undefined
    behavior for any other reason.<br>
    10. The reason that (6) and (7) cause an aliasing violation is
    essentially the same.<br>
    <br>
    Now if you do indeed believe (6) is true, the difficulty I'm having
    is understanding why. So, some questions:<br>
    <br>
    Do you also believe the following would violate strict aliasing (and
    if so, on which line)?<br>
    <br>
    <blockquote>struct exec_node ** m = (struct exec_node *) n;<br>
      return m[0];<br>
    </blockquote>
    <br>
    How about this (and on which line)?<br>
    <br>
    <blockquote>struct exec_node ** m = (struct exec_node *) n;<br>
      n = NULL;<br>
      return m[0];<br>
    </blockquote>
    <br>
    Davin<br>
    <br>
  </body>
</html>