<HTML>
<HEAD>
<meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
<TITLE>
    Core "ready" Issues
   </TITLE>
<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 }
  SPAN.cmnt { font-family:Times; font-style:italic }
</STYLE>
</HEAD>
<BODY>
<TABLE ALIGN="RIGHT" CELLSPACING="0" CELLPADDING="0">
<TR>
<TD ALIGN="RIGHT">
      Document number:
     </TD>
<TD>
       &#160;P3638R0</TD>
</TR>
<TR>
<TD ALIGN="RIGHT">
      Date:
     </TD>
<TD>
      &#160;2025-02-14</TD>
</TR>
<TR>
<TD ALIGN="RIGHT">
      Project:
     </TD>
<TD>
      &#160;Programming Language C++
     </TD>
</TR>
<TR>
<TD ALIGN="RIGHT">
      Reference:
     </TD>
<TD>
      &#160;ISO/IEC 14882:2024
     </TD>
</TR>
<TR>
<TD ALIGN="RIGHT">
      Reply to:
     </TD>
<TD>
      &#160;Jens Maurer
     </TD>
</TR>
<TR>
<TD></TD>
<TD>
      &#160;<A HREF="mailto://jens.maurer@gmx.net">jens.maurer@gmx.net</A>
</TD>
</TR>
</TABLE>
<BR CLEAR="ALL"><BR><CENTER><H2>
     Core Language Working Group "ready" Issues
     for the
     February, 2025 meeting
    </H2></CENTER>
<BR><P>
    References in this document reflect the section and paragraph
    numbering of document
    <A HREF="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/n5001.pdf">WG21 N5001</A>.
   </P>
<HR>
<A NAME="2549"></A><H4>2549.
  
Implicitly moving the operand of a <I>throw-expression</I> in unevaluated contexts
</H4>
<B>Section: </B>7.5.5.3&#160; [<A href="https://wg21.link/expr.prim.id.qual">expr.prim.id.qual</A>]
 &#160;&#160;&#160;

 <B>Status: </B>ready
 &#160;&#160;&#160;

 <B>Submitter: </B>Richard Smith
 &#160;&#160;&#160;

 <B>Date: </B>2022-03-11


<P>Consider:</P>

<PRE>
  void f() {
    X x;
    //<SPAN CLASS="cmnt"> Is </SPAN>x<SPAN CLASS="cmnt"> an lvalue or an xvalue here?</SPAN>
    void g(int n = (decltype((throw x, 0))()));  //<SPAN CLASS="cmnt"> status quo: </SPAN>x<SPAN CLASS="cmnt"> is move-eligible here</SPAN>
  }

  void f() {
    X x;
    struct A {
      void g() {
        try {
          struct Y {
            //<SPAN CLASS="cmnt"> Is </SPAN>x<SPAN CLASS="cmnt"> an lvalue or an xvalue here?</SPAN>
            void h(int n = (decltype((throw x, 0))()));
          };
        } catch (...) { }
      }
    };
  }
</PRE>

<P>11.9.6 [<A href="https://wg21.link/class.copy.elision#3">class.copy.elision</A>] paragraph 3 specifies:</P>

<BLOCKQUOTE>

An <I>implicitly movable entity</I> is a variable of automatic storage
duration that is either a non-volatile object or an rvalue reference
to a non-volatile object type. In the following copy-initialization
contexts, a move operation is first considered before attempting a
copy operation:

<UL>
<LI>...</LI>

<LI>if the operand of a <I>throw-expression</I>
(7.6.18 [<A href="https://wg21.link/expr.throw">expr.throw</A>]) is a (possibly parenthesized)
<I>id-expression</I> that names an implicitly movable entity that
belongs to a scope that does not contain the <I>compound-statement</I>
of the innermost <I>try-block</I> or <I>function-try-block</I> (if
any) whose <I>compound-statement</I> or <I>ctor-initializer</I>
contains the <I>throw-expression</I>,
</LI>
</UL>

</BLOCKQUOTE>

<P>Thus, in the first example above, <TT>x</TT> is treated as an
xvalue, but it is treated as an lvalue in the second example.  This
outcome is surprising.</P>

<P>(<A HREF="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p2266r2.html">P2266R2</A>
(Simpler implicit move) moved this wording, introduced by
<A HREF="http://open-std.org/JTC1/SC22/WG21/docs/papers/2019/p1825r0.html">P1825R0</A>
(Merged wording for P0527R1 and P1155R3),
from 11.9.6 [<A href="https://wg21.link/class.copy.elision">class.copy.elision</A>] to 7.5.5.2 [<A href="https://wg21.link/expr.prim.id.unqual">expr.prim.id.unqual</A>].)</P>

<P><B>Proposed resolution [SUPERSEDED]:</B></P>

<P>Change in 7.5.5.2 [<A href="https://wg21.link/expr.prim.id.unqual#4">expr.prim.id.unqual</A>] paragraph 4:</P>

<BLOCKQUOTE>

An <I>implicitly movable entity</I> is a variable
<DEL>of</DEL> <INS>with</INS> automatic storage duration that is
either a non-volatile object or an rvalue reference to a non-volatile
object type. <DEL>In the following contexts,
an</DEL> <INS>An</INS> <I>id-expression</I>
is <I>move-eligible</I><DEL>:</DEL>
<INS>if</INS>

<UL>
<LI>
<INS>it names an implicitly movable entity declared in the body
or <I>parameter-declaration-clause</I> of the innermost enclosing
function or <I>lambda-expression</I> and</INS>
</LI>

<LI>
<DEL>If</DEL> the <DEL><I>id-expression</I></DEL> (possibly parenthesized)
<INS><I>id-expression</I></INS> is the operand of

<UL>
<LI>a <TT>return</TT> or <TT>co_return</TT> statement<DEL>, and
names an implicitly movable entity declared in the body
or <I>parameter-declaration-clause</I> of the innermost enclosing
function or <I>lambda-expression</I></DEL> or
</LI>

<LI>
<DEL>if the <I>id-expression</I> (possibly parenthesized) is the
operand of</DEL> a <INS>potentially-evaluated</INS> <I>throw-expression</I>,
<DEL>and names an implicitly movable entity that belongs to a scope
that does not contain the <I>compound-statement</I> of the
innermost <I>lambda-expression</I>, <I>try-block</I>,
or <I>function-try-block</I> (if any) whose <I>compound-statement</I>
or <I>ctor-initializer</I> encloses the <I>throw-expression</I></DEL>
<INS>where
no <I>try-block</I> or <I>function-try-block</I> intervenes between
the declaration of the entity and the innermost enclosing scope of
the <I>throw-expression</I></INS>.
</LI>
</UL>

</LI>
</UL>

</BLOCKQUOTE>

<P><B>Additional notes (December, 2024)</B></P>

<P>Treating potentially-evaluated expressions differently (as opposed
to unevaluated ones) is surprising.</P>



<P><B>Proposed resolution (approved by CWG 2025-02-14):</B></P>

<P>Change in 7.5.5.2 [<A href="https://wg21.link/expr.prim.id.unqual#4">expr.prim.id.unqual</A>] paragraph 4:</P>

<BLOCKQUOTE>

An <I>implicitly movable entity</I> is a variable
<DEL>of</DEL> <INS>with</INS> automatic storage duration that is
either a non-volatile object or an rvalue reference to a non-volatile
object type. <DEL>In the following contexts,
an</DEL> <INS>An</INS> <I>id-expression</I>
is <I>move-eligible</I><DEL>:</DEL>
<INS>if</INS>

<UL>
<LI class="ins">
it names an implicitly movable entity,
</LI>

<LI>
<DEL>If</DEL><INS>it is</INS> the <DEL><I>id-expression</I></DEL> (possibly parenthesized) <DEL>is the</DEL> operand of
a <TT>return</TT> or <TT>co_return</TT> statement<DEL>, and
names an implicitly movable entity declared in the body
or <I>parameter-declaration-clause</I> of the innermost enclosing
function or <I>lambda-expression</I></DEL> or

<DEL>if the <I>id-expression</I> (possibly parenthesized) is the
operand</DEL> of a <I>throw-expression</I>, and
<DEL>names an implicitly movable entity that belongs to a scope
that does not contain the <I>compound-statement</I> of the
innermost <I>lambda-expression</I>, <I>try-block</I>,
or <I>function-try-block</I> (if any) whose <I>compound-statement</I>
or <I>ctor-initializer</I> encloses the <I>throw-expression</I></DEL>
</LI>

<LI class="ins">
each intervening scope between the declaration of the entity and the
innermost enclosing scope of the <I>id-expression</I> is a block scope
and, for a <I>throw-expression</I>, is not the block scope of
a <I>try-block</I> or <I>function-try-block</I>.
</LI>
</UL>

</BLOCKQUOTE>

<BR><BR><HR>
<A NAME="2703"></A><H4>2703.
  
Three-way comparison requiring strong ordering for floating-point types, take 2
</H4>
<B>Section: </B>11.10.3&#160; [<A href="https://wg21.link/class.spaceship">class.spaceship</A>]
 &#160;&#160;&#160;

 <B>Status: </B>ready
 &#160;&#160;&#160;

 <B>Submitter: </B>Richard Smith
 &#160;&#160;&#160;

 <B>Date: </B>2023-02-13




<P>The resolution accepted for issue 2539
does not actually address the example in the issue, because overload
resolution is never performed for expressions involving only built-in
types.</P>

<P><B>Proposed resolution (2025-01-13, approved by CWG 2025-02-14):</B></P>

<P>Change in 11.10.3 [<A href="https://wg21.link/class.spaceship#1">class.spaceship</A>] paragraph 1 as follows:</P>

<BLOCKQUOTE>

The synthesized three-way comparison of type R
(17.11.2 [<A href="https://wg21.link/cmp.categories">cmp.categories</A>]) of glvalues a and b of the same type is
defined as follows:

<UL>

<LI>If a &lt;=&gt; b is usable (11.10.1 [<A href="https://wg21.link/class.compare.default">class.compare.default</A>]) and can
be explicitly converted to R using static_cast,
<TT>static_cast&lt;R&gt;(a &lt;=&gt; b)</TT>.</LI>

<LI>Otherwise, if <INS><TT>a &lt;=&gt; b</TT> is usable or</INS>
overload resolution for <TT>a &lt;=&gt; b</TT> is performed and finds
at least one viable candidate, the synthesized three-way comparison is
not defined.</LI>

<LI>Otherwise, ...</LI>

</UL>

</BLOCKQUOTE>

<BR><BR><HR>
<A NAME="2943"></A><H4>2943.
  
Discarding a void return value
</H4>
<B>Section: </B>9.12.10&#160; [<A href="https://wg21.link/dcl.attr.nodiscard">dcl.attr.nodiscard</A>]
 &#160;&#160;&#160;

 <B>Status: </B>ready
 &#160;&#160;&#160;

 <B>Submitter: </B>Brian Bi
 &#160;&#160;&#160;

 <B>Date: </B>2024-10-24


<P>(From submission
<A HREF="https://github.com/cplusplus/CWG/issues/628">#628</A>.)
</P>

<P>A warning is currently, but ought not to be, encouraged for a call
to a [[nodiscard]] function with a void return type.  Such a situation
may arise for dependent return types.  For example:</P>

<PRE>
  [[nodiscard]] void f();
  template&lt;class T&gt; [[nodiscard]] T g();

  void h() {
    f();                //<SPAN CLASS="cmnt"> suggested change: warning no longer recommended</SPAN>
    (void)f();          //<SPAN CLASS="cmnt"> warning not recommended</SPAN>
    g&lt;int&gt;();           //<SPAN CLASS="cmnt"> warning recommended</SPAN>
    g&lt;void&gt;();          //<SPAN CLASS="cmnt"> suggested change: warning no longer recommended</SPAN>
    (void)g&lt;void&gt;();    //<SPAN CLASS="cmnt"> warning not recommended</SPAN>
  }
</PRE>

<P><B>Proposed resolution (2025-01-21, approved by CWG 2025-02-14):</B></P>

<P>Change in 9.12.10 [<A href="https://wg21.link/dcl.attr.nodiscard#4">dcl.attr.nodiscard</A>] paragraph 4 as follows:</P>

<BLOCKQUOTE>

Recommended practice: Appearance of a nodiscard call as a
potentially-evaluated discarded-value expression
(7.2 [<A href="https://wg21.link/expr.prop">expr.prop</A>]) <INS>of non-void type</INS> is discouraged
unless explicitly cast to void. Implementations should issue a warning
in such cases.  The value of a <I>has-attribute-expression</I> for the
nodiscard attribute should be 0 unless the implementation can issue
such warnings.

</BLOCKQUOTE>

<BR><BR><HR>
<A NAME="2970"></A><H4>2970.
  
Races with <TT>volatile sig_atomic_t</TT> bit-fields
</H4>
<B>Section: </B>6.9.2.2&#160; [<A href="https://wg21.link/intro.races">intro.races</A>]
 &#160;&#160;&#160;

 <B>Status: </B>ready
 &#160;&#160;&#160;

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

 <B>Date: </B>2024-12-17


<P>(From submission
<A HREF="https://github.com/cplusplus/CWG/issues/654">#654</A>.)
</P>

<P>Subclause 6.9.2.2 [<A href="https://wg21.link/intro.races#22">intro.races</A>] paragraph 22 specifies:</P>

<BLOCKQUOTE>

Two accesses to the same object of type <TT>volatile
std::sig_atomic_t</TT> do not result in a data race if both occur in
the same thread, even if one or more occurs in a signal handler. ...

</BLOCKQUOTE>

<P>This provision applies to bit-fields as well, because bit-fields
are objects (6.8.1 [<A href="https://wg21.link/basic.types.general#4">basic.types.general</A>] paragraph 4).  However, in
practice bit-fields are not updated atomically and are subject to
tearing.</P>

<P><B>Proposed resolution (2025-01-20, approved by CWG 2025-02-14):</B></P>

<P>Change in 6.9.2.2 [<A href="https://wg21.link/intro.races#22">intro.races</A>] paragraph 22 as follows:</P>

<BLOCKQUOTE>

Two accesses to the same <INS>non-bit-field</INS> object of
type <TT>volatile std::sig_atomic_t</TT> do not result in a data race
if both occur in the same thread, even if one or more occurs in a
signal handler. ...

</BLOCKQUOTE>

<BR><BR><HR>
<A NAME="2990"></A><H4>2990.
  
Exporting redeclarations of namespaces
</H4>
<B>Section: </B>10.2&#160; [<A href="https://wg21.link/module.interface">module.interface</A>]
 &#160;&#160;&#160;

 <B>Status: </B>ready
 &#160;&#160;&#160;

 <B>Submitter: </B>EWG/CWG
 &#160;&#160;&#160;

 <B>Date: </B>2025-01-10




<P>Issue 2921 fixed the following issue
with namespaces:</P>

<PRE>
  export module M;
  namespace N { //<SPAN CLASS="cmnt"> external linkage, attached to global module, not exported</SPAN>
    void f();
  }
  namespace N { //<SPAN CLASS="cmnt"> error: exported namespace, redeclares non-exported namespace</SPAN>
    export void g();
  }
</PRE>

<P>This is considered a CWG consistency / wording fix.  However, the
change for that issue also allowed:</P>

<PRE>
  module;
  #include "header"
  export module wrap;

  export using ::feature;               // already allowed previously
  export extern "C++" void feature();   // newly allowed by CWG2921
</PRE>

<P>The CWG chair had neglected to run this new feature past EWG prior
to plenary-approving issue 2921 in
Wroclaw.  Subsequent discussion on the EWG reflector surfaced concerns
about missing syntactic differentiation between an intended
export-by-redeclaration and an accidental declaration of a different
entity because of a slight signature mismatch.</P>

<P>This issues seeks to limit the change to namespaces only; any
additional feature in this area should be presented to EWG via a
paper.</P>

<P><B>Proposed resolution (approved by CWG 2025-02-14):</B></P>

<P>Change in 10.2 [<A href="https://wg21.link/module.interface#6">module.interface</A>] paragraph 6 as follows:</P>

<BLOCKQUOTE>

A redeclaration of an entity X is implicitly exported if X was
introduced by an exported declaration; otherwise it shall not be
exported <DEL>if it is attached to a named module</DEL> <INS>unless it
is a namespace</INS>.  [ Example:

<PRE>
  export module M;
  struct S { int n; };
  typedef S S;
  export typedef S S;     //<SPAN CLASS="cmnt"> OK, does not redeclare an entity</SPAN>
  export struct S;        //<SPAN CLASS="cmnt"> error: exported declaration follows non-exported declaration</SPAN>
<INS>  namespace N {           //<SPAN CLASS="cmnt"> external linkage, attached to global module, not exported</SPAN>
    void f();
  }
  namespace N {           //<SPAN CLASS="cmnt"> OK, exported namespace redeclaring non-exported namespace</SPAN>
    export void g();
  }</INS>
</PRE>
-- end example ]
</BLOCKQUOTE>
<BR><BR>
</BODY>
</HTML>
