<HTML>
<HEAD>
<meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
<TITLE>
    CWG Issue 2658</TITLE>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<STYLE TYPE="text/css">
  INS { text-decoration:none; font-weight:bold; background-color:#A0FFA0 }
  .INS { text-decoration:none; background-color:#D0FFD0 }
  DEL { text-decoration:line-through; background-color:#FFA0A0 }
  .DEL { text-decoration:line-through; background-color: #FFD0D0 }
  @media (prefers-color-scheme: dark) {
    HTML { background-color:#202020; color:#f0f0f0; }
    A { color:#5bc0ff; }
    A:visited { color:#c6a8ff; }
    A:hover, a:focus { color:#afd7ff; }
    INS { background-color:#033a16; color:#aff5b4; }
    .INS { background-color: #033a16; }
    DEL { background-color:#67060c; color:#ffdcd7; }
    .DEL { background-color:#67060c; }
  }
  SPAN.cmnt { font-family:Times; font-style:italic }
</STYLE>
</HEAD>
<BODY>
<P><EM>This is an unofficial snapshot of the ISO/IEC JTC1 SC22 WG21
  Core Issues List revision 118b.
  See http://www.open-std.org/jtc1/sc22/wg21/ for the official
  list.</EM></P>
<P>2025-09-28</P>
<HR>
<A NAME="2658"></A><H4>2658.
  
Trivial copying of unions in core constant expressions
</H4>
<B>Section: </B>7.7&#160; [<A href="https://wg21.link/expr.const">expr.const</A>]
 &#160;&#160;&#160;

 <B>Status: </B>C++23
 &#160;&#160;&#160;

 <B>Submitter: </B>Hubert Tong
 &#160;&#160;&#160;

 <B>Date: </B>2022-12-04<BR>


<P>[Accepted as a DR at the February, 2023 meeting.]</P>

<P>Consider:</P>

<PRE>
  struct A { char c; int x; };
  union U { A a; };
  constexpr int f() {
    U u;
    u.a.c = 1;
    u.a.x = 2;
    U v = u; //<SPAN CLASS="cmnt"> indeterminate padding bytes read!</SPAN>
    return u.a.x;
  }
  extern constexpr int x = f();
</PRE>

<P>
Subclause 7.7 [<A href="https://wg21.link/expr.const#5.11">expr.const</A>] bullet 5.11 added by
P1331R2 prohibits lvalue-to-rvalue conversion of objects having
indeterminate value during evaluation of a core constant
expression. Trivial copy constructors of unions copy the object
representation (not just the active member). The new prohibition
causes cases where bytes not involved in the value presentation of the
active member and having indeterminate values would prevent a union
from being copied by a trivial copy constructor (for example, the
padding bytes in the above case).</P>

<P>
Note: The source of a union copy is never a prvalue within the
evaluation of a trivial copy constructor because the reference
parameter is bound to a glvalue.</P>

<P><B>Proposed resolution (January, 2023):</B></P>

<P>Add a new paragraph after 7.7 [<A href="https://wg21.link/expr.const#6">expr.const</A>] paragraph 6 as follows:</P>

<BLOCKQUOTE>

<P>... to an object whose lifetime began within the evaluation of E.</P>

<P class="ins">
For the purposes of determining whether <I>E</I> is a core constant
expression, lvalue-to-rvalue conversion of an object of indeterminate
value during the evaluation of a call to a trivial copy/move
constructor or copy/move assignment operator of a union does not
disqualify <I>E</I> from being a core constant expression unless the
active member of the source union object contains a subobject of
indeterminate value.
</P>

</BLOCKQUOTE>

<P><B>Proposed resolution (approved by CWG 2023-02-07):</B></P>

<P>Add a new paragraph after 7.7 [<A href="https://wg21.link/expr.const#6">expr.const</A>] paragraph 6 as follows:</P>

<BLOCKQUOTE>

<P>... to an object whose lifetime began within the evaluation of E.</P>

<P class="ins">
For the purposes of determining whether <I>E</I> is a core constant
expression, the evaluation of a call to a trivial copy/move
constructor or copy/move assignment operator of a union is considered
to copy/move the active member of the union, if any.
[ Note: The copy/move of the active member is trivial. -- end note ]</P>

</BLOCKQUOTE>

<BR><BR>
</BODY>
</HTML>
