<div dir="ltr"><div dir="ltr">On Fri, Jun 21, 2019 at 5:46 PM Gabriel Dos Reis <<a href="mailto:gdr@microsoft.com">gdr@microsoft.com</a>> wrote:<br></div><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<div dir="auto">
<div dir="ltr"></div>
<div dir="ltr">On Jun 20, 2019, at 6:51 PM, Richard Smith <<a href="mailto:richardsmith@google.com" target="_blank">richardsmith@google.com</a>> wrote:<br></div><div dir="ltr">
<br>
</div>
<blockquote type="cite">
<div dir="ltr">
<div dir="ltr">
<div dir="ltr">On Thu, Jun 20, 2019 at 2:22 PM Richard Smith <<a href="mailto:richardsmith@google.com" target="_blank">richardsmith@google.com</a>> wrote:<br>
</div>
<div class="gmail_quote">
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<div dir="ltr">
<div>As currently specified, bit_cast from an indeterminate value produces an unspecified value rather than an indeterminate value. That means this can't be implemented by a simple load on some implementations, and instead will require some kind of removing-the-taint-of-an-uninitialized-value
operation to be performed. (A similar concern applies to reading from padding bits.)</div>
<div><br>
</div>
<div>Is that the intent?</div>
</div>
</blockquote>
<div><br>
</div>
<div>I chatted with JF about this. The intent is as follows:</div>
<div><br>
</div>
<div> * bits of the input that don't have defined values result in the corresponding bit of the output being "bad"</div>
<div> * if any part of a scalar object is "bad", that object has an indeterminate value</div>
<div><br>
</div>
<div>Some examples:</div>
<div><br>
</div>
<div><br>
</div>
<div>struct A { char c; /* char padding : 8; */ short s; };</div>
<div>struct B { char x[4]; };</div>
<div><br>
</div>
<div>B one() {</div>
<div> A a = {1, 2};</div>
<div> return std::bit_cast<B>(a);</div>
<div>}</div>
<div><br>
</div>
<div>In one(), the second byte of the object representation of a is bad. That means that the second byte of the produced B object is bad, so x[1] in the produced B object is an indeterminate value. The above function, if declared constexpr, would be usable
in constant expressions so long as you don't look at one().x[1].</div>
<div><br>
</div>
<div><br>
</div>
<div>A two() {</div>
<div> B b;</div>
<div> b.x[0] = 'a';</div>
<div> b.x[2] = 1;</div>
<div> b.x[3] = 2;</div>
<div> return std::bit_cast<A>(b);</div>
<div>}</div>
<div><br>
</div>
<div>In two(), the second byte of the object representation of b is bad. But a bit_cast to A doesn't care because it never looks at that byte. The above function returns an A with a fully-defined value. If declared constexpr, it would produce a normal, fully-initialized
value.</div>
<div><br>
</div>
<div><br>
</div>
<div>int three() {</div>
<div> int n;</div>
<div> return std::bit_cast<int>(n);</div>
<div>}</div>
<div class="gmail_quote"><br>
</div>
In three(), the entirety of n is bad. A bit_cast from it produces an int whose value is indeterminate. And because we have an expression of non-byte-like type that produced an indeterminate value, the behavior is undefined.</div>
</div>
</div>
</blockquote>
<div><br>
</div>
<div>Hmmm, isn’t it the lvalue-to-rvalue conversion that provokes the UB? I am asking a question regarding the actual cause of the UB.</div></div></blockquote><div><br></div><div>This doesn't naturally fall out of the wording, because std::bit_cast takes an lvalue and returns an rvalue, and is specified in terms of poking at an object representation directly without formally performing an lvalue-to-rvalue conversion or hitting the [basic.indet] cases where the undefined value is "observed".</div><div><br></div><div>And I think that's actually in some ways a good thing: it shouldn't matter if some part of the input to bit_cast is uninitialized so long as the destination type has only padding in the uninitialized region.</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="auto"><blockquote type="cite">
<div dir="ltr">
<div dir="ltr">
<div class="gmail_quote">B four() {</div>
<div class="gmail_quote"> int n;</div>
<div class="gmail_quote"> return std::bit_cast<B>(n);</div>
<div class="gmail_quote">}</div>
<div class="gmail_quote"><br>
</div>
<div class="gmail_quote">In four(), just like three(), the entirety of n is bad, so the scalar subobjects of B are bad too. But because they're of byte-like type, that's OK: we can copy them about and produce them from prvalue expressions.</div>
<div class="gmail_quote"><br>
</div>
<div class="gmail_quote">
<div><br>
</div>
<div>I think the above is captured by the following wording change:</div>
<div><br>
</div>
<div>Change in [bit.cast]p1:</div>
<div><br>
</div>
<div>"""</div>
<div>Returns: An object of type To. Each bit of the value representation of the result is equal to the<br>
corresponding bit in the object representation of from. Padding bits of the To object are unspecified.<br>
<div></div>
</div>
<div>If there is no value of type To corresponding to the value representation produced, the behavior is<br>
undefined. If there are multiple such values, which value is produced is unspecified.</div>
<div><ins>A bit in the value representation of the result is indeterminate if does not correspond to a bit in the value</div>
<div>
<div>representation of <font face="courier new, monospace">from</font> or corresponds to a bit of an object that is not within its lifetime or has an indeterminate value ([basic.indet]).</div>
</div>
<div>For each bit in the value representation of the result that is indeterminate,</div>
<div>the smallest object containing that bit has an indeterminate value;</div>
<div>the behavior is undefined unless that object is of unsigned ordinary character type or std::byte type.</div>
<div>The result does not otherwise contain any indeterminate values.</ins><br>
</div>
<div>"""</div>
</div>
</div>
</div>
</blockquote>
<blockquote type="cite">
<div dir="ltr"><span>_______________________________________________</span><br>
<span>ub mailing list</span><br>
<span><a href="mailto:ub@isocpp.open-std.org" target="_blank">ub@isocpp.open-std.org</a></span><br>
<span><a href="http://www.open-std.org/mailman/listinfo/ub" target="_blank">http://www.open-std.org/mailman/listinfo/ub</a></span><br>
</div>
</blockquote>
</div>
_______________________________________________<br>
ub mailing list<br>
<a href="mailto:ub@isocpp.open-std.org" target="_blank">ub@isocpp.open-std.org</a><br>
<a href="http://www.open-std.org/mailman/listinfo/ub" rel="noreferrer" target="_blank">http://www.open-std.org/mailman/listinfo/ub</a><br>
</blockquote></div></div>