<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  </head>
  <body>
    <p><br>
    </p>
    <div class="moz-cite-prefix">On 8/3/20 8:45 PM, John McCall wrote:<br>
    </div>
    <blockquote type="cite" cite="mid:833CCC19-6042-4889-B081-28EBD258FBB2@apple.com">
      
      <div style="font-family:sans-serif">
        <div style="white-space:normal">
          <p dir="auto">On 31 Jul 2020, at 19:50, Hal Finkel wrote:</p>
        </div>
        <div style="white-space:normal">
          <blockquote style="border-left:2px solid #777; color:#777;
            margin:0 0 5px; padding-left:5px">
            <p dir="auto">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">
              <p dir="auto">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>
                <br>
                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>
                <br>
                Therefore, I believe it's implementation-defined whether
                the following program has undefined behavior.<br>
                <br>
                <a href="https://godbolt.org/z/YT9zsz" style="color:#999" moz-do-not-send="true">https://godbolt.org/z/YT9zsz</a>
                <<a href="https://godbolt.org/z/YT9zsz" style="color:#999" moz-do-not-send="true">https://godbolt.org/z/YT9zsz</a>><br>
                <br>
                #include <assert.h><br>
                <br>
                struct Foo {<br>
                    int x;<br>
                *    // assert fails if you comment out these unused
                fields!<br>
                *    int dummy[4];<br>
                };<br>
                <br>
                struct Bar {<br>
                    Bar() : foo_(CreateFoo()) {}<br>
                <br>
                    Foo CreateFoo() {<br>
                        Foo f;<br>
                        f.x = 55;<br>
                        assert(foo_.x == 55);<br>
                        return f;<br>
                    }<br>
                    Foo foo_;<br>
                };<br>
                <br>
                int main() {<br>
                    Bar b;<br>
                }</p>
            </blockquote>
            <p dir="auto">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">
          <p dir="auto">It does seem hard to argue that this is invalid
            under the specification. To me it seems like it clearly <em>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">noalias</code>,
            so this has immediate significance.</p>
          <p dir="auto">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.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">John.</p>
        </div>
      </div>
    </blockquote>
    <p><br>
    </p>
    <p>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>
    </p>
    <p> -Hal<br>
    </p>
    <p><br>
    </p>
    <blockquote type="cite" cite="mid:833CCC19-6042-4889-B081-28EBD258FBB2@apple.com">
      <div style="font-family:sans-serif">
        <div style="white-space:normal">
        </div>
        <div style="white-space:normal">
          <blockquote style="border-left:2px solid #777; color:#777;
            margin:0 0 5px; padding-left:5px">
            <p dir="auto"> -Hal<br>
              <br>
            </p>
            <blockquote style="border-left:2px solid #777; color:#999;
              margin:0 0 5px; padding-left:5px; border-left-color:#999">
              <p dir="auto">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">mailto:cfe-dev@lists.llvm.org</a>>>
                wrote:<br>
                <br>
                <br>
                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">
                <p dir="auto"> 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">
                  <p dir="auto"> n 31 Jul 2020, at 7:35, Hal Finkel
                    wrote:<br>
                    <br>
                    On 7/29/20 9:00 PM, John McCall via cfe-dev wrote:<br>
                    <br>
                    On 29 Jul 2020, at 17:42, Richard Smith wrote:<br>
                    <br>
                    On Wed, 29 Jul 2020 at 12:52, John McCall<br>
                    <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">mailto:rjmccall@apple.com</a>>
                    wrote:<br>
                    <br>
                    ...<br>
                    <br>
                    I think concretely, the escape hatch doesn't stop
                    things<br>
                    from<br>
                    going wrong,<br>
                    because -- as you note -- even though we *could*
                    have<br>
                    made a copy,<br>
                    it's<br>
                    observable whether or not we *did* make a copy. For
                    example:<br>
                    <br>
                    I would say that it’s observable whether the
                    parameter<br>
                    variable has<br>
                    the same address as the argument. That doesn’t
                    /have/ to<br>
                    be the same<br>
                    question as whether a copy was performed: we could<br>
                    consider there to be<br>
                    a formal copy (or series of copies) that ultimately<br>
                    creates /an/ object<br>
                    at the same address, but it’s not the /same/ object
                    and<br>
                    so pointers<br>
                    to the old object no longer validly pointer to it.
                    But I<br>
                    guess that<br>
                    would probably violate the lifetime rules, because
                    it<br>
                    would make accesses<br>
                    through old pointers UB when in fact they should at<br>
                    worst access a valid<br>
                    object that’s just unrelated to the parameter
                    object.<br>
                    <br>
                    I think that it would be great to be able to do
                    this, but<br>
                    unfortunately, I think that the point that you raise
                    here is<br>
                    a key issue. Whether or not the copy is performed is
                    visible<br>
                    in the model, and so we can't simply act as though
                    there was<br>
                    a copy when optimizing. Someone could easily have
                    code that<br>
                    looks like:<br>
                    <br>
                    Foo DefaultX;<br>
                    <br>
                    ...<br>
                    <br>
                    void something(Foo &A, Foo &B) {<br>
                    <br>
                      if (&A == &B) { ... }<br>
                    <br>
                    }<br>
                    <br>
                    void bar(Foo X) { something(X, DefaultX); }<br>
                    <br>
                    This example isn’t really on point; a call like
                    |bar(DefaultX)|<br>
                    obviously cannot just pass the address of |DefaultX|
                    as a<br>
                    by-value argument without first proving a lot of
                    stuff about how<br>
                    |foo| uses both its parameter and |DefaultX|. I
                    think |noalias|<br>
                    is actually a subset of what would have to be proven
                    there.<br>
                  </p>
                </blockquote>
                <p dir="auto"> Yes, I apologize. You're right: my
                  pseudo-code missed the point.<br>
                  So the record is clear, let me rephrase:<br>
                  <br>
                  Foo *DefaultX = nullptr;<br>
                  ...<br>
                  Foo::Foo() { if (!DefaultX) DefaultX = this; }<br>
                  ...<br>
                  void bar(Foo X) { something(X, *DefaultX); }<br>
                  ...<br>
                  bar(Foo{});<br>
                  <br>
                  I think that's closer to what we're talking about.<br>
                  <br>
                </p>
                <blockquote style="border-left:2px solid #777;
                  color:#BBB; margin:0 0 5px; padding-left:5px;
                  border-left-color:#BBB">
                  <p dir="auto"> In general, the standard is clear that
                    you cannot rely on<br>
                    escaping a pointer to/into a trivially-copyable
                    pr-value<br>
                    argument prior to the call and then rely on that
                    pointer<br>
                    pointing into the corresponding parameter object.<br>
                    Implementations are /allowed/ to introduce copies.
                    But it does<br>
                    seem like the current wording would allow you to
                    rely on that<br>
                    pointer pointing into /some/ valid object, at least
                    until the<br>
                    end of the caller’s full-expression. That means
                    that, if we<br>
                    don’t guarantee to do an actual copy of the
                    argument, we cannot<br>
                    make it UB to access the parameter variable through
                    pointers to<br>
                    the argument temporary, which is what marking the
                    parameter as<br>
                    |noalias| would do.<br>
                    <br>
                    So I guess the remaining questions are:<br>
                    <br>
                    * Is this something we can reasonably change in the
                    standard?<br>
                  </p>
                </blockquote>
                <p dir="auto"> This is the part that I'm unclear about.
                  What change would we make?<br>
                  <br>
                </p>
              </blockquote>
              <p dir="auto"> Also, maybe some extended use of the
                no_unique_address attribute<br>
                would help?<br>
                <br>
                 -Hal<br>
                <br>
              </p>
              <blockquote style="border-left:2px solid #777; color:#BBB;
                margin:0 0 5px; padding-left:5px;
                border-left-color:#BBB">
                <blockquote style="border-left:2px solid #777;
                  color:#BBB; margin:0 0 5px; padding-left:5px;
                  border-left-color:#BBB">
                  <p dir="auto"> * Are we comfortable setting |noalias|
                    in C if the only place<br>
                    that would break is with a C++ caller?<br>
                  </p>
                </blockquote>
                <p dir="auto"> Out of curiosity, if you take C in
                  combination with our<br>
                  statement-expression extension implementation<br>
                  (<a href="https://gcc.gnu.org/onlinedocs/gcc/Statement-Exprs.html" style="color:#BBB" moz-do-not-send="true">https://gcc.gnu.org/onlinedocs/gcc/Statement-Exprs.html</a><br>
                  <<a href="https://gcc.gnu.org/onlinedocs/gcc/Statement-Exprs.html" style="color:#BBB" moz-do-not-send="true">https://gcc.gnu.org/onlinedocs/gcc/Statement-Exprs.html</a>>),
                  and<br>
                  notwithstanding the statement in the GCC manual about
                  returns by<br>
                  value (i.e., the part just before where it says,
                  "Therefore the<br>
                  this pointer observed by Foo is not the address of
                  a."), is there<br>
                  any relationship to this topic?<br>
                  <br>
                  Thanks again,<br>
                  <br>
                  Hal<br>
                  <br>
                </p>
                <blockquote style="border-left:2px solid #777;
                  color:#BBB; margin:0 0 5px; padding-left:5px;
                  border-left-color:#BBB">
                  <p dir="auto"> John.<br>
                    <br>
                    As Richard's example shows, the code doesn't need to<br>
                    explicitly compare the addresses to detect the copy
                    either.<br>
                    Any code that reads/writes to the objects can do it.
                    A<br>
                    perhaps-more-realistic example might be:<br>
                    <br>
                      int Cnt = A.RefCnt; ++A.RefCnt; ++B.RefCnt; if
                    (Cnt + 1 !=<br>
                    A.RefCnt) { /* same object case */ }<br>
                    <br>
                    The best suggestion that I have so far is that we
                    could add<br>
                    an attribute like 'can_copy' indicating that the
                    optimizer<br>
                    can make a formal copy of the argument in the callee
                    and use<br>
                    that instead of the original pointer if that seems
                    useful. I<br>
                    can certainly imagine a transformation such as LICM
                    making<br>
                    use of such a thing (although the cost modeling
                    would<br>
                    probably need to be fairly conservative).<br>
                    <br>
                     -Hal<br>
                    <br>
                    ...<br>
                    <br>
                    John.<br>
                    <br>
                    <br>
                    _______________________________________________<br>
                    cfe-dev mailing list<br>
                    <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">mailto:cfe-dev@lists.llvm.org</a>><br>
                    <a href="https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev" style="color:#BBB" moz-do-not-send="true">https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev</a><br>
                    <<a href="https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev" style="color:#BBB" moz-do-not-send="true">https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev</a>><br>
                    <br>
                    -- <br>
                    Hal Finkel<br>
                    Lead, Compiler Technology and Programming Languages<br>
                    Leadership Computing Facility<br>
                    Argonne National Laboratory<br>
                  </p>
                </blockquote>
                <p dir="auto"> -- <br>
                  Hal Finkel<br>
                  Lead, Compiler Technology and Programming Languages<br>
                  Leadership Computing Facility<br>
                  Argonne National Laboratory</p>
              </blockquote>
              <p dir="auto"> -- <br>
                Hal Finkel<br>
                Lead, Compiler Technology and Programming Languages<br>
                Leadership Computing Facility<br>
                Argonne National Laboratory<br>
                <br>
                _______________________________________________<br>
                cfe-dev mailing list<br>
                <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">mailto:cfe-dev@lists.llvm.org</a>><br>
                <a href="https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev" style="color:#999" moz-do-not-send="true">https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev</a><br>
                <<a href="https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev" style="color:#999" moz-do-not-send="true">https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev</a>><br>
              </p>
            </blockquote>
            <p dir="auto">-- <br>
              Hal Finkel<br>
              Lead, Compiler Technology and Programming Languages<br>
              Leadership Computing Facility<br>
              Argonne National Laboratory</p>
          </blockquote>
        </div>
        <div style="white-space:normal">
        </div>
      </div>
    </blockquote>
    <pre class="moz-signature" cols="72">-- 
Hal Finkel
Lead, Compiler Technology and Programming Languages
Leadership Computing Facility
Argonne National Laboratory</pre>
  </body>
</html>