<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">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><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">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"><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">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">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">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">cfe-dev@lists.llvm.org</a><br>
<a href="https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev" rel="noreferrer" target="_blank">https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev</a><br>
</blockquote></div>