<!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 29 Jul 2020, at 17:42, Richard Smith 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 Wed, 29 Jul 2020 at 12:52, John McCall <rjmccall@apple.com> wrote:<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">Clang IRGen currently doesn’t mark indirect parameters as noalias.<br>
Considerations:<br>
<br>
   -<br>
<br>
   A lot of targets don’t pass struct arguments indirectly outside of<br>
   C++, but some do, notably AArch64.<br>
   -<br>
<br>
   In a pure C world, we would always be able to mark such parameters<br>
   noalias, because arguments are r-values and there’s no way to have a<br>
   pointer to an r-value.<br>
   -<br>
<br>
   ObjC __weak references can have pointers to them from the ObjC<br>
   runtime. You can’t pass a weak reference immediately as an argument because<br>
   __weak is a qualifier and qualifiers are ignored in calls, but you can<br>
   put one in a struct and pass that, and that struct has to be passed<br>
   indirectly. Arguably such a parameter cannot be noalias because of the<br>
   pointer from the runtime, but then again, ObjC code isn’t allowed to<br>
   directly access the weak reference (it has to call the runtime), which<br>
   means that no accesses that LLVM can actually see violate the noalias<br>
   restriction.<br>
   -<br>
<br>
   C++ parameters of non-trivially-copyable class type cannot be marked<br>
   noalias: it is absolutely permitted to escape a pointer to this within<br>
   a constructor and to replace that pointer whenever the object is moved.<br>
   This is both well-defined and sometimes useful.<br>
   -<br>
<br>
   It’s actually possible to escape a pointer to *any* C++ object within<br>
   its constructor, and that pointer remains valid for the duration of the<br>
   object’s lifetime. And you can do this with NRVO, too, so you don’t even<br>
   need to have a type with non-trivial constructors, as long as the object<br>
   isn’t copied. Note that this even messes up the C case, which is really<br>
   unfortunate: arguably we need to pessimize C code because of the<br>
   possibility it might interoperate with C++.<br>
   -<br>
<br>
   But I think there’s an escape hatch here. C++ has a rule which is<br>
   intended to give implementation extra leeway with passing and returning<br>
   trivial types, e.g. to pass them in registers. This rule is C++<br>
   [class.temporary]p3, which says that implementations can create an extra<br>
   temporary object to pass an object of type X as long as “each copy<br>
   constructor, move constructor, and destructor of X is either trivial or<br>
   deleted, and X has at least one non-deleted copy or move constructor”. This<br>
   object is created by (trivially) copy/move-initializing from the<br>
   argument/return object. Arguably we can consider any type that satisfies<br>
   this condition to be *formally* copied into a new object as part of<br>
   passing or returning it. We don’t need to *actually* do the copy, I<br>
   think, we just need to consider a copy to have been done in order to<br>
   formally disrupt any existing pointers to the object. (Although arguably<br>
   you aren’t allowed to copy an object into a new object at the original<br>
   object’s current address; it would be an unfortunate consequence of this<br>
   wording if we had to either forgo optimization or do an unnecessary copy<br>
   here.)<br>
<br>
Thoughts?<br>
</p>
</blockquote><p dir="auto">From a high level: I think the C++ language semantics *should* permit us to<br>
assume that objects passed by value to functions, and objects returned by<br>
value from functions (in which category I include *this in a constructor),<br>
are noalias.</p>
</blockquote></div>
<div style="white-space:normal">

<p dir="auto">I agree that this should be the goal for trivial types.  If nothing<br>
else, it seems unfortunate that whether something is UB would depend<br>
on a type’s ABI treatment in a specific situation.  Guarantees should<br>
be based on well-defined type properties, and implementations should<br>
have to conform.</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">I think concretely, the escape hatch doesn't stop things from going wrong,<br>
because -- as you note -- even though we *could* have made a copy, it's<br>
observable whether or not we *did* make a copy. For example:</p>
</blockquote></div>
<div style="white-space:normal">

<p dir="auto">I would say that it’s observable whether the parameter variable has<br>
the same address as the argument.  That doesn’t <em>have</em> 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 <em>an</em> object<br>
at the same address, but it’s not the <em>same</em> 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.</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">As it happens, we do actually make a redundant copy here when performing<br>
the call to `f`, which seems wasteful.</p>
</blockquote></div>
<div style="white-space:normal">

<p dir="auto">You’re probably looking at x86_64 code generation.  The x86_64 ABI passes<br>
this argument on the stack, which means that LLVM forces Clang to use an<br>
IR pattern (<code style="background-color:#F7F7F7; border-radius:3px; margin:0; padding:0 0.4em" bgcolor="#F7F7F7">byval</code>) that it’s hard for LLVM to reliably optimize.</p>

<p dir="auto">I agree that, because in practice we only elide the copy of a <code style="background-color:#F7F7F7; border-radius:3px; margin:0; padding:0 0.4em" bgcolor="#F7F7F7">byval</code><br>
argument in the caller in very specific situations, it is currently safe<br>
to mark <code style="background-color:#F7F7F7; border-radius:3px; margin:0; padding:0 0.4em" bgcolor="#F7F7F7">byval</code> arguments as <code style="background-color:#F7F7F7; border-radius:3px; margin:0; padding:0 0.4em" bgcolor="#F7F7F7">noalias</code> in Clang.  But arguably we shouldn’t<br>
start expressing that assumption when it wouldn’t be true in the general<br>
case because it would break if we made the compiler smarter.</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">And so do GCC and ICC, which means<br>
the 'noalias' would actually be correct here considering only the behavior<br>
of those compilers. So in principle we could address this in the ABI by<br>
saying that the copy is mandatory. But I don't think we should -- I think<br>
the above code should have undefined behavior because it accesses a<br>
function parameter through an access path not derived from the name of the<br>
function parameter.<br>
<br>
We do have some wording in the standard that tries to give aliasing<br>
guarantees in some of these cases, but does so in a way that's not really<br>
useful. Specifically, [class.cdtor]p2: "During the construction of an<br>
object, if the value of the object or any of its subobjects is accessed<br>
through a glvalue that is not obtained, directly or indirectly, from the<br>
constructor’s this pointer, the value of the object or subobject thus<br>
obtained is unspecified." (I mean, thanks for trying, but that's not all<br>
the cases, and "the value is unspecified" is not enough permission.)</p>
</blockquote></div>
<div style="white-space:normal">

<p dir="auto">Yeah, I think this rule is fixable if it’s updated to use the<br>
same object model that the standard is now using elsewhere.<br>
Basically, things like pointers to unconstructed objects should<br>
only get “forwarded” to become pointers to the object when<br>
construction is complete.  But I don’t think you can run this<br>
rule in reverse to restrict how you can use pointers derived<br>
from <code style="background-color:#F7F7F7; border-radius:3px; margin:0; padding:0 0.4em" bgcolor="#F7F7F7">this</code>.</p>

<p dir="auto">(I also don’t know how to make this work with the ubiquitous<br>
placement-new pattern.  It feels like the language wants the<br>
rule to be that you have to use the result of the <code style="background-color:#F7F7F7; border-radius:3px; margin:0; padding:0 0.4em" bgcolor="#F7F7F7">new</code><br>
expression, but (1) approximately nobody writes code that<br>
complies with that and (2) doing so would be a significant<br>
regression for a lot of code that would suddenly have to pass<br>
around a pointer to the constructed object just to satisfy<br>
a formal model when it already knows exactly where it’s stored.)</p>

<p dir="auto">John.</p>
</div>
</div>
</body>
</html>