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