<div dir="ltr"><br><div class="gmail_extra"><br><div class="gmail_quote">On Mon, May 1, 2017 at 12:16 PM, Hal Finkel <span dir="ltr"><<a href="mailto:hfinkel@anl.gov" target="_blank">hfinkel@anl.gov</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
  
    
  
  <div bgcolor="#FFFFFF"><div><div class="gmail-h5">
    <br>
    <div class="gmail-m_-2119143275366730840moz-cite-prefix">On 05/01/2017 12:49 PM, Daniel Berlin
      wrote:<br>
    </div>
    <blockquote type="cite">
      
      <div dir="ltr"><br>
        <div class="gmail_extra"><br>
          <div class="gmail_quote">On Fri, Apr 21, 2017 at 4:03 AM, Hal
            Finkel via Phabricator <span dir="ltr"><<a href="mailto:reviews@reviews.llvm.org" target="_blank">reviews@reviews.llvm.org</a>></span>
            wrote:<br>
            <blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">hfinkel added a
              comment.<br>
              <span class="gmail-m_-2119143275366730840gmail-"><br>
                In <a href="https://reviews.llvm.org/D32199#732737" rel="noreferrer" target="_blank">https://reviews.llvm.org/D3219<wbr>9#732737</a>,
                @rsmith wrote:<br>
                <br>
                > In <a href="https://reviews.llvm.org/D32199#732189" rel="noreferrer" target="_blank">https://reviews.llvm.org/D3219<wbr>9#732189</a>,
                @hfinkel wrote:<br>
                ><br>
                > > In <a href="https://reviews.llvm.org/D32199#731472" rel="noreferrer" target="_blank">https://reviews.llvm.org/D3219<wbr>9#731472</a>,
                @rsmith wrote:<br>
                > ><br>
                > > > 1. C's "effective type" rule allows
                writes to set the type pretty much unconditionally,
                unless the storage is for a variable with a declared
                type<br>
                > ><br>
                > ><br>
                > > To come back to this point: We don't really
                implement these rules now, and it is not clear that we
                will. The problem here is that, if we take the
                specification literally, then we can't use our current
                TBAA at all. The problem is that if we have:<br>
                > ><br>
                > >   write x, !tbaa "int"<br>
                > >   read x, !tbaa "int"<br>
                > >   write x, !tbaa "float"<br>
                > ><br>
                > ><br>
                > > TBAA will currently tell us that the "float"
                write aliases with neither the preceding read nor the
                preceding write.<br>
                ><br>
                ><br>
                > Right, C's TBAA rules do not (in general) permit a
                store to be reordered before a memory operation of a
                different type, they only allow loads to be moved before
                stores. (Put another way, they do not tell you that
                pointers point to distinct memory locations, just that a
                stored value cannot be observed by a load of a different
                type.) You get the more general "distinct memory
                locations" result only for objects of a declared type.<br>
                ><br>
                > C++ is similar, except that (because object
                lifetimes do not currently begin magically due to a
                store) you /can/ reorder stores past a memory operation
                of a different type if you know no object's lifetime
                began in between. (But currently we do not record all
                lifetime events in IR, so we can't do that today. Also,
                we may be about to lose the property that you can
                statically determine a small number of places that might
                start an object lifetime.)<br>
                ><br>
                > > Also, a strict reading of C's access rules
                seems to rule out the premise underlying our struct-path
                TBAA entirely. So long as I'm accessing a value using a
                struct that has some member, including recursively, with
                that type, then it's fine. The matching of the relative
                offsets is a sufficient, but not necessary, condition
                for well-defined access. C++ has essentially the same
                language (and, thus, potentially the same problem).<br>
                ><br>
                > I agree this rule is garbage, but it's not as
                permissive as I think you're suggesting. The rule says
                that you can use an lvalue of struct type to access
                memory of struct field type. In C this happens during
                struct assignment, for instance. It does *not* permit
                using an lvalue of struct field type to access unrelated
                fields of the same struct. So C appears to allow this
                nonsense:<br>
                ><br>
                >   char *p = malloc(8);<br>
                >   *(int*)p = 0;<br>
                >   *(int*)(p + 4) = 0;<br>
                >   struct S {int n; float f;} s = *(struct S*)p; //
                use lvalue of type `struct S` to access object of
                effective type `int`, to initialize a `float`<br>
                ><br>
                ><br>
                > but not this nonsense:<br>
                ><br>
                >   float q = ((struct S*)p)->f; // ub, cannot use
                lvalue of type `float` to access object of effective
                type `int`<br>
                ><br>
                ><br>
                > ... which just means that we can't make much use of
                TBAA when emitting struct copies in C.<br>
                ><br>
                > In C++, on the other hand, the rule is even more
                garbage, since there is no way to perform a memory
                access with a glvalue of class type. (The closest you
                get is that a defaulted union construction/assignment
                copies the object representation, but that's expressed
                in terms of copying a sequence of unsigned chars, and in
                any case those are member functions and so already
                require an object of the correct type to exist.) See
                wg21.link/cwg2051<br>
                <br>
                <br>
              </span>Our struct-path TBAA does the following:<br>
              <br>
                struct X { int a, b; };<br>
                X x { 50, 100 };<br>
                X *o = (X*) (((int*) &x) + 1);<br>
              <br>
                int a_is_b = o->a; // This is UB (or so we say)?<br>
            </blockquote>
            <div><br>
            </div>
            <div>This is UB.</div>
            <div>A good resource for this stuff is <a href="http://www.cl.cam.ac.uk/%7Epes20/cerberus/" target="_blank">http://www.cl.cam.ac.uk/~<wbr>pes20/cerberus/</a>
              which has a long document where they exlpore all of these
              and what various compilers do, along with what the
              standard seems to say.</div>
          </div>
        </div>
      </div>
    </blockquote>
    <br>
    </div></div><a class="gmail-m_-2119143275366730840moz-txt-link-freetext" href="http://www.cl.cam.ac.uk/~pes20/cerberus/notes30-full.pdf" target="_blank">http://www.cl.cam.ac.uk/~<wbr>pes20/cerberus/notes30-full.<wbr>pdf</a> is 172
    pages, and so I may have missed it, but I don't see this case. </div></blockquote><div><br></div><div>Let me find it for you. it may only be in one of the other versions.</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div bgcolor="#FFFFFF">Also,
    I'd really like to see where the standard says this is UB. I don't
    see it.<br>
    <br></div></blockquote><div><br></div><div>So you believe that you can index into an object randomly by pointer arithmetic and pull out a different field?<br><br></div><div>For starters, this is  illegal because you don't know where the padding bytes are.</div><div>You cannot assume that X.a + 1 == X.b</div><div>"Implementation alignment requirements might
cause two adjacent members not to be allocated immediately after each other;"</div><div><br></div><div>See 9.2.14</div><div><br></div><div><br></div><div><br></div></div></div></div>