<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/xhtml; charset=utf-8">
</head>
<body>
<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">https://godbolt.org/z/YT9zsz</a> <<a href="https://godbolt.org/z/YT9zsz" style="color:#999">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 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 <cfe-dev@lists.llvm.org <<a href="mailto:cfe-dev@lists.llvm.org" style="color:#999">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>
            <rjmccall@apple.com> <<a href="mailto:rjmccall@apple.com" style="color:#BBB">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">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">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>
            cfe-dev@lists.llvm.org <<a href="mailto:cfe-dev@lists.llvm.org" style="color:#BBB">mailto:cfe-dev@lists.llvm.org</a>><br>
            <a href="https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev" style="color:#BBB">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">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>
    cfe-dev@lists.llvm.org <<a href="mailto:cfe-dev@lists.llvm.org" style="color:#999">mailto:cfe-dev@lists.llvm.org</a>><br>
    <a href="https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev" style="color:#999">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">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>
</body>
</html>