<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class=""><br class=""><div><br class=""><blockquote type="cite" class=""><div class="">On Aug 3, 2020, at 11:28 PM, Hal Finkel via cfe-dev <<a href="mailto:cfe-dev@lists.llvm.org" class="">cfe-dev@lists.llvm.org</a>> wrote:</div><br class="Apple-interchange-newline"><div class="">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" class="">
  
  <div class=""><p class=""><br class="">
    </p>
    <div class="moz-cite-prefix">On 8/3/20 8:45 PM, John McCall wrote:<br class="">
    </div>
    <blockquote type="cite" cite="mid:833CCC19-6042-4889-B081-28EBD258FBB2@apple.com" class="">
      
      <div style="font-family:sans-serif" class="">
        <div style="white-space:normal" class=""><p dir="auto" class="">On 31 Jul 2020, at 19:50, Hal Finkel wrote:</p>
        </div>
        <div style="white-space:normal" class="">
          <blockquote style="border-left:2px solid #777; color:#777;
            margin:0 0 5px; padding-left:5px" class=""><p dir="auto" class="">On 7/31/20 5:59 PM, James Y Knight wrote:</p>
            <blockquote style="border-left:2px solid #777; color:#999;
              margin:0 0 5px; padding-left:5px; border-left-color:#999" class=""><p dir="auto" class="">This discussion reminds me of an example I
                ran into a couple weeks ago, where the execution of the
                program is dependent precisely upon whether the ABI
                calls for the object to be passed indirectly, or in a
                register<br class="">
                <br class="">
                In the case where NVRO is triggered, the class member
                foo_ is fully-constructed on the first line of CreateFoo
                (despite appearing as if that's only constructing a
                local variable). In the case where the struct is small
                enough to fit in a register, NVRO does not apply, and in
                that case, foo_ isn't constructed until after CreateFoo
                returns.<br class="">
                <br class="">
                Therefore, I believe it's implementation-defined whether
                the following program has undefined behavior.<br class="">
                <br class="">
                <a href="https://godbolt.org/z/YT9zsz" style="color:#999" moz-do-not-send="true" class="">https://godbolt.org/z/YT9zsz</a>
                <<a href="https://godbolt.org/z/YT9zsz" style="color:#999" moz-do-not-send="true" class="">https://godbolt.org/z/YT9zsz</a>><br class="">
                <br class="">
                #include <assert.h><br class="">
                <br class="">
                struct Foo {<br class="">
                    int x;<br class="">
                *    // assert fails if you comment out these unused
                fields!<br class="">
                *    int dummy[4];<br class="">
                };<br class="">
                <br class="">
                struct Bar {<br class="">
                    Bar() : foo_(CreateFoo()) {}<br class="">
                <br class="">
                    Foo CreateFoo() {<br class="">
                        Foo f;<br class="">
                        f.x = 55;<br class="">
                        assert(foo_.x == 55);<br class="">
                        return f;<br class="">
                    }<br class="">
                    Foo foo_;<br class="">
                };<br class="">
                <br class="">
                int main() {<br class="">
                    Bar b;<br class="">
                }</p>
            </blockquote><p dir="auto" class="">Looks that way to me too. The example in
              11.10.5p2 sort of makes this point as well (by pointing
              out that you can directly initialize a global this way).</p>
          </blockquote>
        </div>
        <div style="white-space:normal" class=""><p dir="auto" class="">It does seem hard to argue that this is invalid
            under the specification. To me it seems like it clearly <em class="">ought</em>
            to be invalid, though. Note that Clang has always emitted
            return address arguments as <code style="background-color:#F7F7F7; border-radius:3px;
              margin:0; padding:0 0.4em" bgcolor="#F7F7F7" class="">noalias</code>,
            so this has immediate significance.</p><p dir="auto" class="">If I were writing the specification, I would
            rewrite the restriction in <code style="background-color:#F7F7F7; border-radius:3px;
              margin:0; padding:0 0.4em" bgcolor="#F7F7F7" class="">[class.cdtor]p2</code>
            to say that pointers derived by naming a
            returned/constructed object do not formally point to the
            object until the function actually returns, even if the copy
            is elided. That would make James’s example undefined
            behavior.</p><p dir="auto" class="">John.</p>
        </div>
      </div>
    </blockquote><p class=""><br class="">
    </p><p class="">I agree. It seems like we should be able to make a sanitizer
      detect this kind of mistake as well (although the general case
      will require some msan-like propagation scheme).<br class="">
    </p><p class=""> -Hal<br class=""></p></div></div></blockquote><div><br class=""></div><div>On second thought I agree as well — i.e. allow both the NRVO and the noalias optimizations to be applied as they currently are, and adjust the standard so that any code which would break due to those optimizations should be considered undefined.  </div><div><br class=""></div><div>That would be consistent with the proposal of making escaping pointers within a constructor of a trivially-copyable class undefined behavior.</div><div><br class=""></div><div>And more generally: if there are <i class="">any</i> other instances in which the compiler is currently forced to be pessimistic, just to handle a few weird usages which are technically allowed, I think by all means we should ask the standard to explicitly address those, via the same approach: the typical, more-optimizable cases should be allowed to fully optimize, by making the rare, less-optimizable cases undefined behavior.  </div><div><br class=""></div><div>But in tandem, the standard should also introduce attributes that allow advanced users to explicitly opt out of those optimizations (e.g. "forcecopy" or "maybealias" or whatever) to allow their weird cases to remain standard compliant.  Nobody loses.</div><div><br class=""></div><div>People write C and C++ because they want the fastest possible compiled code — the standard should get out of the way wherever it is obstructing optimization.</div><div><br class=""></div><div>Dave</div><blockquote type="cite" class=""><div class=""><div class=""><p class="">
    </p><p class=""><br class="">
    </p>
    <blockquote type="cite" cite="mid:833CCC19-6042-4889-B081-28EBD258FBB2@apple.com" class="">
      <div style="font-family:sans-serif" class="">
        <div style="white-space:normal" class="">
        </div>
        <div style="white-space:normal" class="">
          <blockquote style="border-left:2px solid #777; color:#777;
            margin:0 0 5px; padding-left:5px" class=""><p dir="auto" class=""> -Hal<br class="">
              <br class="">
            </p>
            <blockquote style="border-left:2px solid #777; color:#999;
              margin:0 0 5px; padding-left:5px; border-left-color:#999" class=""><p dir="auto" class="">On Fri, Jul 31, 2020 at 2:27 PM Hal Finkel
                via cfe-dev <<a class="moz-txt-link-abbreviated" href="mailto:cfe-dev@lists.llvm.org">cfe-dev@lists.llvm.org</a> <<a href="mailto:cfe-dev@lists.llvm.org" style="color:#999" moz-do-not-send="true" class="">mailto:cfe-dev@lists.llvm.org</a>>>
                wrote:<br class="">
                <br class="">
                <br class="">
                On 7/31/20 1:24 PM, Hal Finkel wrote:</p>
              <blockquote style="border-left:2px solid #777; color:#BBB;
                margin:0 0 5px; padding-left:5px;
                border-left-color:#BBB" class=""><p dir="auto" class=""> On 7/31/20 12:43 PM, John McCall wrote:</p>
                <blockquote style="border-left:2px solid #777;
                  color:#BBB; margin:0 0 5px; padding-left:5px;
                  border-left-color:#BBB" class=""><p dir="auto" class=""> n 31 Jul 2020, at 7:35, Hal Finkel
                    wrote:<br class="">
                    <br class="">
                    On 7/29/20 9:00 PM, John McCall via cfe-dev wrote:<br class="">
                    <br class="">
                    On 29 Jul 2020, at 17:42, Richard Smith wrote:<br class="">
                    <br class="">
                    On Wed, 29 Jul 2020 at 12:52, John McCall<br class="">
                    <a class="moz-txt-link-rfc2396E" href="mailto:rjmccall@apple.com"><rjmccall@apple.com></a> <<a href="mailto:rjmccall@apple.com" style="color:#BBB" moz-do-not-send="true" class="">mailto:rjmccall@apple.com</a>>
                    wrote:<br class="">
                    <br class="">
                    ...<br class="">
                    <br class="">
                    I think concretely, the escape hatch doesn't stop
                    things<br class="">
                    from<br class="">
                    going wrong,<br class="">
                    because -- as you note -- even though we *could*
                    have<br class="">
                    made a copy,<br class="">
                    it's<br class="">
                    observable whether or not we *did* make a copy. For
                    example:<br class="">
                    <br class="">
                    I would say that it’s observable whether the
                    parameter<br class="">
                    variable has<br class="">
                    the same address as the argument. That doesn’t
                    /have/ to<br class="">
                    be the same<br class="">
                    question as whether a copy was performed: we could<br class="">
                    consider there to be<br class="">
                    a formal copy (or series of copies) that ultimately<br class="">
                    creates /an/ object<br class="">
                    at the same address, but it’s not the /same/ object
                    and<br class="">
                    so pointers<br class="">
                    to the old object no longer validly pointer to it.
                    But I<br class="">
                    guess that<br class="">
                    would probably violate the lifetime rules, because
                    it<br class="">
                    would make accesses<br class="">
                    through old pointers UB when in fact they should at<br class="">
                    worst access a valid<br class="">
                    object that’s just unrelated to the parameter
                    object.<br class="">
                    <br class="">
                    I think that it would be great to be able to do
                    this, but<br class="">
                    unfortunately, I think that the point that you raise
                    here is<br class="">
                    a key issue. Whether or not the copy is performed is
                    visible<br class="">
                    in the model, and so we can't simply act as though
                    there was<br class="">
                    a copy when optimizing. Someone could easily have
                    code that<br class="">
                    looks like:<br class="">
                    <br class="">
                    Foo DefaultX;<br class="">
                    <br class="">
                    ...<br class="">
                    <br class="">
                    void something(Foo &A, Foo &B) {<br class="">
                    <br class="">
                      if (&A == &B) { ... }<br class="">
                    <br class="">
                    }<br class="">
                    <br class="">
                    void bar(Foo X) { something(X, DefaultX); }<br class="">
                    <br class="">
                    This example isn’t really on point; a call like
                    |bar(DefaultX)|<br class="">
                    obviously cannot just pass the address of |DefaultX|
                    as a<br class="">
                    by-value argument without first proving a lot of
                    stuff about how<br class="">
                    |foo| uses both its parameter and |DefaultX|. I
                    think |noalias|<br class="">
                    is actually a subset of what would have to be proven
                    there.<br class="">
                  </p>
                </blockquote><p dir="auto" class=""> Yes, I apologize. You're right: my
                  pseudo-code missed the point.<br class="">
                  So the record is clear, let me rephrase:<br class="">
                  <br class="">
                  Foo *DefaultX = nullptr;<br class="">
                  ...<br class="">
                  Foo::Foo() { if (!DefaultX) DefaultX = this; }<br class="">
                  ...<br class="">
                  void bar(Foo X) { something(X, *DefaultX); }<br class="">
                  ...<br class="">
                  bar(Foo{});<br class="">
                  <br class="">
                  I think that's closer to what we're talking about.<br class="">
                  <br class="">
                </p>
                <blockquote style="border-left:2px solid #777;
                  color:#BBB; margin:0 0 5px; padding-left:5px;
                  border-left-color:#BBB" class=""><p dir="auto" class=""> In general, the standard is clear that
                    you cannot rely on<br class="">
                    escaping a pointer to/into a trivially-copyable
                    pr-value<br class="">
                    argument prior to the call and then rely on that
                    pointer<br class="">
                    pointing into the corresponding parameter object.<br class="">
                    Implementations are /allowed/ to introduce copies.
                    But it does<br class="">
                    seem like the current wording would allow you to
                    rely on that<br class="">
                    pointer pointing into /some/ valid object, at least
                    until the<br class="">
                    end of the caller’s full-expression. That means
                    that, if we<br class="">
                    don’t guarantee to do an actual copy of the
                    argument, we cannot<br class="">
                    make it UB to access the parameter variable through
                    pointers to<br class="">
                    the argument temporary, which is what marking the
                    parameter as<br class="">
                    |noalias| would do.<br class="">
                    <br class="">
                    So I guess the remaining questions are:<br class="">
                    <br class="">
                    * Is this something we can reasonably change in the
                    standard?<br class="">
                  </p>
                </blockquote><p dir="auto" class=""> This is the part that I'm unclear about.
                  What change would we make?<br class="">
                  <br class="">
                </p>
              </blockquote><p dir="auto" class=""> Also, maybe some extended use of the
                no_unique_address attribute<br class="">
                would help?<br class="">
                <br class="">
                 -Hal<br class="">
                <br class="">
              </p>
              <blockquote style="border-left:2px solid #777; color:#BBB;
                margin:0 0 5px; padding-left:5px;
                border-left-color:#BBB" class="">
                <blockquote style="border-left:2px solid #777;
                  color:#BBB; margin:0 0 5px; padding-left:5px;
                  border-left-color:#BBB" class=""><p dir="auto" class=""> * Are we comfortable setting |noalias|
                    in C if the only place<br class="">
                    that would break is with a C++ caller?<br class="">
                  </p>
                </blockquote><p dir="auto" class=""> Out of curiosity, if you take C in
                  combination with our<br class="">
                  statement-expression extension implementation<br class="">
                  (<a href="https://gcc.gnu.org/onlinedocs/gcc/Statement-Exprs.html" style="color:#BBB" moz-do-not-send="true" class="">https://gcc.gnu.org/onlinedocs/gcc/Statement-Exprs.html</a><br class="">
                  <<a href="https://gcc.gnu.org/onlinedocs/gcc/Statement-Exprs.html" style="color:#BBB" moz-do-not-send="true" class="">https://gcc.gnu.org/onlinedocs/gcc/Statement-Exprs.html</a>>),
                  and<br class="">
                  notwithstanding the statement in the GCC manual about
                  returns by<br class="">
                  value (i.e., the part just before where it says,
                  "Therefore the<br class="">
                  this pointer observed by Foo is not the address of
                  a."), is there<br class="">
                  any relationship to this topic?<br class="">
                  <br class="">
                  Thanks again,<br class="">
                  <br class="">
                  Hal<br class="">
                  <br class="">
                </p>
                <blockquote style="border-left:2px solid #777;
                  color:#BBB; margin:0 0 5px; padding-left:5px;
                  border-left-color:#BBB" class=""><p dir="auto" class=""> John.<br class="">
                    <br class="">
                    As Richard's example shows, the code doesn't need to<br class="">
                    explicitly compare the addresses to detect the copy
                    either.<br class="">
                    Any code that reads/writes to the objects can do it.
                    A<br class="">
                    perhaps-more-realistic example might be:<br class="">
                    <br class="">
                      int Cnt = A.RefCnt; ++A.RefCnt; ++B.RefCnt; if
                    (Cnt + 1 !=<br class="">
                    A.RefCnt) { /* same object case */ }<br class="">
                    <br class="">
                    The best suggestion that I have so far is that we
                    could add<br class="">
                    an attribute like 'can_copy' indicating that the
                    optimizer<br class="">
                    can make a formal copy of the argument in the callee
                    and use<br class="">
                    that instead of the original pointer if that seems
                    useful. I<br class="">
                    can certainly imagine a transformation such as LICM
                    making<br class="">
                    use of such a thing (although the cost modeling
                    would<br class="">
                    probably need to be fairly conservative).<br class="">
                    <br class="">
                     -Hal<br class="">
                    <br class="">
                    ...<br class="">
                    <br class="">
                    John.<br class="">
                    <br class="">
                    <br class="">
                    _______________________________________________<br class="">
                    cfe-dev mailing list<br class="">
                    <a class="moz-txt-link-abbreviated" href="mailto:cfe-dev@lists.llvm.org">cfe-dev@lists.llvm.org</a> <<a href="mailto:cfe-dev@lists.llvm.org" style="color:#BBB" moz-do-not-send="true" class="">mailto:cfe-dev@lists.llvm.org</a>><br class="">
                    <a href="https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev" style="color:#BBB" moz-do-not-send="true" class="">https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev</a><br class="">
                    <<a href="https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev" style="color:#BBB" moz-do-not-send="true" class="">https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev</a>><br class="">
                    <br class="">
                    -- <br class="">
                    Hal Finkel<br class="">
                    Lead, Compiler Technology and Programming Languages<br class="">
                    Leadership Computing Facility<br class="">
                    Argonne National Laboratory<br class="">
                  </p>
                </blockquote><p dir="auto" class=""> -- <br class="">
                  Hal Finkel<br class="">
                  Lead, Compiler Technology and Programming Languages<br class="">
                  Leadership Computing Facility<br class="">
                  Argonne National Laboratory</p>
              </blockquote><p dir="auto" class=""> -- <br class="">
                Hal Finkel<br class="">
                Lead, Compiler Technology and Programming Languages<br class="">
                Leadership Computing Facility<br class="">
                Argonne National Laboratory<br class="">
                <br class="">
                _______________________________________________<br class="">
                cfe-dev mailing list<br class="">
                <a class="moz-txt-link-abbreviated" href="mailto:cfe-dev@lists.llvm.org">cfe-dev@lists.llvm.org</a> <<a href="mailto:cfe-dev@lists.llvm.org" style="color:#999" moz-do-not-send="true" class="">mailto:cfe-dev@lists.llvm.org</a>><br class="">
                <a href="https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev" style="color:#999" moz-do-not-send="true" class="">https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev</a><br class="">
                <<a href="https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev" style="color:#999" moz-do-not-send="true" class="">https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev</a>><br class="">
              </p>
            </blockquote><p dir="auto" class="">-- <br class="">
              Hal Finkel<br class="">
              Lead, Compiler Technology and Programming Languages<br class="">
              Leadership Computing Facility<br class="">
              Argonne National Laboratory</p>
          </blockquote>
        </div>
        <div style="white-space:normal" class="">
        </div>
      </div>
    </blockquote>
    <pre class="moz-signature" cols="72">-- 
Hal Finkel
Lead, Compiler Technology and Programming Languages
Leadership Computing Facility
Argonne National Laboratory</pre>
  </div>

_______________________________________________<br class="">cfe-dev mailing list<br class=""><a href="mailto:cfe-dev@lists.llvm.org" class="">cfe-dev@lists.llvm.org</a><br class="">https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev<br class=""></div></blockquote></div><br class=""></body></html>