Skip to content

Commit 20bc07a

Browse files
committed
New issue from Jan Schultke: "Undefined behavior in std::bit_cast should be diagnosed during constant evaluation"
1 parent fb82bf3 commit 20bc07a

File tree

1 file changed

+110
-0
lines changed

1 file changed

+110
-0
lines changed

xml/issue4539.xml

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
<?xml version='1.0' encoding='utf-8' standalone='no'?>
2+
<!DOCTYPE issue SYSTEM "lwg-issue.dtd">
3+
4+
<issue num="4539" status="New">
5+
<title>Undefined behavior in `std::bit_cast` should be diagnosed during constant evaluation</title>
6+
<section>
7+
<sref ref="[bit.cast]"/>
8+
</section>
9+
<submitter>Jan Schultke</submitter>
10+
<date>10 Mar 2026</date>
11+
<priority>99</priority>
12+
13+
<discussion>
14+
<p>
15+
Consider the following example with undefined behavior, which assumes that `sizeof(int)` equals `4`:
16+
</p>
17+
<blockquote><pre>
18+
struct alignas(4) E { };
19+
constexpr auto x = std::bit_cast&lt;int&gt;(E{});
20+
</pre></blockquote>
21+
<p>
22+
The example compiles with MSVC without any error or warning, where `x` has the value `0`,
23+
which is valid if the UB is library UB; other compilers reject it.
24+
<p/>
25+
<sref ref="[bit.cast]"/> paragraph 4, bullet 2 explicitly states:
26+
</p>
27+
<blockquote style="border-left: 3px solid #ccc;padding-left: 15px;">
28+
<p>
29+
Otherwise, if <tt><i>b</i></tt> is indeterminate, the behavior is undefined.
30+
</p>
31+
</blockquote>
32+
<p>
33+
The fact that undefined behavior is called out explicitly within library wording suggests that this is
34+
"library UB", not "core UB" that would prevent the initializer from being a constant expression because
35+
it violates the requirement of <sref ref="[expr.const]"/> paragraph 21 bullet 2.3:
36+
</p>
37+
<blockquote style="border-left: 3px solid #ccc;padding-left: 15px;">
38+
<p>
39+
no constituent value of scalar type is an indeterminate or erroneous value (<sref ref="[basic.indet]"/>),
40+
</p>
41+
</blockquote>
42+
<p>
43+
Similarly, <sref ref="[bit.cast]"/> paragraph 4 states that forming a value representation that is not
44+
valid for the type is undefined, which may also be seen as "library UB". This can occur in
45+
<tt>bit_cast&lt;bool&gt;(char{2})</tt> if `2` is not a valid representation of `bool`.
46+
<p/>
47+
During the 2026-03-10 LEWG telecon discussing <paper num="P3969R0"/>, LEWG polled whether this UB
48+
should be diagnosed.
49+
</p>
50+
<blockquote>
51+
<p>
52+
POLL: The undefined behavior in `bit_cast` should be diagnosable during constexpr.<br/>
53+
Attendance: 19<br/>
54+
Authors' opinion: N/A<br/>
55+
Outcome: No objection to unanimous consent.
56+
</p>
57+
</blockquote>
58+
</discussion>
59+
60+
<resolution>
61+
<p>
62+
This wording is relative to <paper num="N5032"/>.
63+
</p>
64+
65+
<ol>
66+
67+
<li><p>Modify <sref ref="[bit.cast]"/> as indicated:</p>
68+
69+
<blockquote>
70+
<pre>
71+
template&lt;class To, class From&gt;
72+
constexpr To bit_cast(const From&amp; from) noexcept;
73+
</pre>
74+
<blockquote>
75+
<p>
76+
-1- <i>Constraints</i>: [&hellip;]
77+
<p/>
78+
-2- <i>Mandates</i>: Neither `To` nor `From` are consteval-only types (<sref ref="[basic.types.general]"/>).
79+
<p/>
80+
-3- <i>Constant When</i>: `To`, `From`, and the types of all subobjects of `To` and `From`
81+
are types `T` such that: [&hellip;]
82+
<p/>
83+
-4- <i>Returns</i>: An object of type `To`. Implicitly creates objects nested within the result
84+
(<sref ref="[intro.object]"/>). Each bit of the value representation of the result is equal to the
85+
corresponding bit in the object representation of from. Padding bits of the result are unspecified.
86+
For the result and each object created within it, if there is no value of the object's type corresponding
87+
to the value representation produced, the behavior is undefined. If there are multiple such values, which
88+
value is produced is unspecified. A bit in the value representation of the result is indeterminate
89+
if it does not correspond to a bit in the value representation of from or corresponds to a bit for
90+
which the smallest enclosing object is not within its lifetime or has an indeterminate value
91+
(<sref ref="[basic.indet]"/>). A bit in the value representation of the result is erroneous if it
92+
corresponds to a bit for which the smallest enclosing object has an erroneous value. For each bit
93+
<tt><i>b</i></tt> in the value representation of the result that is indeterminate or erroneous,
94+
let <tt><i>u</i></tt> be the smallest object containing that bit enclosing <tt><i>b</i></tt>:
95+
<p/>
96+
[&hellip;]
97+
<p/>
98+
The result does not otherwise contain any indeterminate or erroneous values.
99+
<p/>
100+
<ins>-?- <i>Remarks</i>: A function call expression that has undefined or erroneous behavior as
101+
described above is not a core constant expression.</ins>
102+
</p>
103+
</blockquote>
104+
</blockquote>
105+
</li>
106+
107+
</ol>
108+
</resolution>
109+
110+
</issue>

0 commit comments

Comments
 (0)