<div dir="ltr"><div dir="ltr">On Thu, Jun 20, 2019 at 2:22 PM Richard Smith &lt;<a href="mailto:richardsmith@google.com">richardsmith@google.com</a>&gt; 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&#39;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&#39;t have defined values result in the corresponding bit of the output being &quot;bad&quot;</div><div> * if any part of a scalar object is &quot;bad&quot;, 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&lt;B&gt;(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&#39;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] = &#39;a&#39;;</div><div>  b.x[2] = 1;</div><div>  b.x[3] = 2;</div><div>  return std::bit_cast&lt;A&gt;(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&#39;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&lt;int&gt;(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 class="gmail_quote"><br></div><div class="gmail_quote"><br></div><div class="gmail_quote">B four() {</div><div class="gmail_quote">  int n;</div><div class="gmail_quote">  return std::bit_cast&lt;B&gt;(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&#39;re of byte-like type, that&#39;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>&quot;&quot;&quot;</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>&lt;ins&gt;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.&lt;/ins&gt;<br></div><div>&quot;&quot;&quot;</div></div></div>