<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>