<HTML>
<HEAD>
<META http-equiv="Content-Type" content="text/html; charset=us-ascii">
<TITLE>
    Core "tentatively ready" Issues
   </TITLE>
</HEAD>
<BODY>
<TABLE ALIGN="RIGHT" CELLSPACING="0" CELLPADDING="0">
<TR>
<TD ALIGN="RIGHT">
      Document number:
     </TD>
<TD>
       &#160;P1510R0</TD>
</TR>
<TR>
<TD ALIGN="RIGHT">
      Date:
     </TD>
<TD>
      &#160;2019-07-19</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 IS 14882:2017
     </TD>
</TR>
<TR>
<TD ALIGN="RIGHT">
      Reply to:
     </TD>
<TD>
      &#160;William M. Miller
     </TD>
</TR>
<TR>
<TD></TD>
<TD>
      &#160;Edison Design Group, Inc.
     </TD>
</TR>
<TR>
<TD></TD>
<TD>
      &#160;<A HREF="mailto://wmm@edg.com">wmm@edg.com</A></TD>
</TR>
</TABLE><BR CLEAR="ALL"><BR><CENTER>
<H2>
     Core Language Working Group "tentatively ready" Issues
     for the
     July, 2019 (Cologne) 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/2019/n4810.pdf">WG21 N4810</A>.
   </P>
<HR><A NAME="682"></A><H4>682.
  
Missing description of lookup of template aliases
</H4><B>Section: </B>6.4.5&#160; [basic.lookup.classref]
 &#160;&#160;&#160;

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

 <B>Submitter: </B>Daveed Vandevoorde
 &#160;&#160;&#160;

 <B>Date: </B>1 March, 2008


<P>6.4.5 [basic.lookup.classref] does not mention template aliases as the
possible result of the lookup but should do so.</P>

<P><B>Proposed resolution, June, 2019:</B></P>

<P>Change 6.4.5 [basic.lookup.classref] paragraph 1 as follows:</P>

<BLOCKQUOTE>

In a class member access expression
(7.6.1.4 [expr.ref]), if the <TT>.</TT>
or <TT>-&gt;</TT> token is immediately followed by an
<I>identifier</I> followed by a <TT>&lt;</TT>, the
identifier must be looked up to determine whether
the <TT>&lt;</TT> is the beginning of a template argument
list (13.2 [temp.names]) or a less-than
operator. The identifier is first looked up in the class of
the object expression (11.7 [class.member.lookup]). If the
identifier is not found, it is then looked up in the context
of the entire <I>postfix-expression</I> and shall name a
<SPAN style="text-decoration:line-through;background-color:#FFA0A0">class</SPAN> template <SPAN style="font-weight:bold;background-color:#A0FFA0">whose specializations are
types</SPAN>.

</BLOCKQUOTE>

<BR><BR><HR><A NAME="2207"></A><H4>2207.
  
Alignment of allocation function return value
</H4><B>Section: </B>6.6.5.4.1&#160; [basic.stc.dynamic.allocation]
 &#160;&#160;&#160;

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

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

 <B>Date: </B>2015-12-02




<P>According to 6.6.5.4.1 [basic.stc.dynamic.allocation] paragraph 2,</P>

<BLOCKQUOTE>

For an allocation function other than a reserved placement allocation
function (17.6.2.3 [new.delete.placement]), the pointer returned is suitably
aligned so that it can be converted to a pointer to any suitable complete
object type (17.6.2.1 [new.delete.single]) and then used to access the
object or array in the storage allocated (until the storage is explicitly
deallocated by a call to a corresponding deallocation function).

</BLOCKQUOTE>

<P>This requirement seems excessive, as it appears to require
the strictest fundamental alignment even for objects that are
too small to require such an alignment.</P>

<P><B>Proposed resolution (March, 2019):</B></P>

<OL><LI><P>Change 6.6.5.4.1 [basic.stc.dynamic.allocation] paragraph 2 as
follows:</P></LI>

<BLOCKQUOTE>

...The order, contiguity, and initial value of storage
allocated by successive calls to an allocation function are
unspecified. <SPAN style="text-decoration:line-through;background-color:#FFA0A0">For an allocation function other than a
reserved placement allocation function
(17.6.2.3 [new.delete.placement]), the pointer returned is
suitably aligned so that it can be converted to a pointer to
any suitable complete object type
(17.6.2.1 [new.delete.single]) and then used to access the
object or array in the storage allocated (until the storage
is explicitly deallocated by a call to a corresponding
deallocation function).</SPAN> Even if the size of the space
requested...

</BLOCKQUOTE>

<LI><P>Add the following as a new paragraph to
6.6.5.4.1 [basic.stc.dynamic.allocation] after the existing paragraph 2:</P></LI>

<BLOCKQUOTE><P><SPAN style="font-weight:bold;background-color:#A0FFA0">For an allocation function other than a
reserved placement allocation function
(17.6.2.3 [new.delete.placement]), the pointer returned on a
successful call shall represent the address of storage that
is aligned as follows:</SPAN></P>

<UL><LI><P><SPAN style="font-weight:bold;background-color:#A0FFA0">If the allocation function takes an argument
of type <TT>std::align_val_t</TT>, then the storage will
have the alignment specified by the value of this
argument.</SPAN></P></LI>

<LI><P><SPAN style="font-weight:bold;background-color:#A0FFA0">Otherwise, if the allocation function is
named <TT>operator new[]</TT>, then the storage is aligned
for any object that does not have new-extended alignment
(6.6.6 [basic.align]) and is no loarger than the
requested size.</SPAN></P></LI>

<LI><P><SPAN style="font-weight:bold;background-color:#A0FFA0">Otherwise, the storage is aligned for any object that does not have new-extended alignment and is of the requested size.</SPAN></P></LI>

</UL>

</BLOCKQUOTE>

<LI><P>Change 17.6.2.1 [new.delete.single] paragraph 1 as follows:</P></LI>

<BLOCKQUOTE>

<I>Effects:</I> The allocation functions
(6.6.5.4.1 [basic.stc.dynamic.allocation]) called by
a <I>new-expression</I> (7.6.2.5 [expr.new]) to
allocate <TT>size</TT> bytes of storage. The second form is
called for a type with new-extended alignment,
and <SPAN style="text-decoration:line-through;background-color:#FFA0A0">allocates storage with the specified
alignment. The</SPAN> <SPAN style="font-weight:bold;background-color:#A0FFA0">the</SPAN> first form is called
otherwise<SPAN style="text-decoration:line-through;background-color:#FFA0A0">, and allocates storage suitably aligned to
represent any object of that size provided the object's type
does not have new-extended alignment</SPAN>.

</BLOCKQUOTE>

<LI><P>Change 17.6.2.2 [new.delete.array] paragraph 1 as follows:</P></LI>

<BLOCKQUOTE>

<I>Effects:</I> The allocation functions
(6.6.5.4.1 [basic.stc.dynamic.allocation]) called by the array form of
a <I>new-expression</I> (7.6.2.5 [expr.new]) to
allocate <TT>size</TT> bytes of storage. The second form is
called for a type with new-extended alignment, and <SPAN style="text-decoration:line-through;background-color:#FFA0A0">allocates
storage with the specified alignment. The</SPAN>
<SPAN style="font-weight:bold;background-color:#A0FFA0">the</SPAN> first form is called otherwise<SPAN style="text-decoration:line-through;background-color:#FFA0A0">, and
allocates storage suitably aligned to represent any array
object of that size or smaller, provided the object's type
does not have new-extended alignment</SPAN>.<SUP>218</SUP>

</BLOCKQUOTE>

</OL>

<BR><BR><HR><A NAME="2300"></A><H4>2300.
  
Lambdas in multiple definitions
</H4><B>Section: </B>6.2&#160; [basic.def.odr]
 &#160;&#160;&#160;

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

 <B>Submitter: </B>Robert Haberlach
 &#160;&#160;&#160;

 <B>Date: </B>2016-04-11


<P>A lambda expression in two translation units has distinct closure
types, because each such expression's type is unique within the program.
This results in an issue with the ODR, which requires that the definitions
of an entity are identical. For example, if</P>

<PRE>
  template &lt;int&gt; void f() {std::function&lt;void()&gt; f = []{};}
</PRE>

<P>appears in two translation units, different specializations of
<TT>function</TT>'s constructor template are called, which violates
6.2 [basic.def.odr] bullet 6.4.</P>

<P>Issue 765 dealt with a similar problem
for inline functions, but the issue still remains for templates.</P>



<P><B>Proposed resolution, April, 2019:</B></P>

<P>Change 6.2 [basic.def.odr] paragraph 12 as follows:</P>

<BLOCKQUOTE>

<P>...Given such an entity named <TT>D</TT> defined in more
than one translation unit, then</P>

<UL><LI><P>each definition of <TT>D</TT> shall consist of
the same sequence of tokens<SPAN style="font-weight:bold;background-color:#A0FFA0">, for which the definition
of a closure type is considered to consist of the sequence
of tokens of the corresponding <I>lambda-expression</I></SPAN>;
and</P></LI>

<LI><P>in each definition of <TT>D</TT>, corresponding
names, looked up according to 6.4 [basic.lookup],
<SPAN style="text-decoration:line-through;background-color:#FFA0A0">shall refer to an entity defined within the definition
of <TT>D</TT>, or</SPAN> shall refer to the same entity,
after overload resolution (12.3 [over.match]) and
after matching of partial template specialization
(13.9.3 [temp.over]), except that a name can refer
to</P></LI>

<UL><LI><P>a non-volatile const object with internal or no
linkage if the object</P></LI>

<UL><LI><P>has the same literal type in all definitions
of <TT>D</TT>,</P></LI>

<LI><P>is initialized with a constant expression
(7.7 [expr.const]),</P></LI>

<LI><P>is not odr-used in any definition of <TT>D</TT>, and</P></LI>

<LI><P>has the same value in all definitions of <TT>D</TT>,</P></LI>

</UL>

<P>or</P>

<LI><P>a reference with internal or no linkage initialized
with a constant expression such that the reference refers to
the same entity in all definitions of <TT>D</TT>;</P></LI>

</UL>

<P>and</P>

<LI><P><SPAN style="font-weight:bold;background-color:#A0FFA0">in each definition of <TT>D</TT>, except within
the default arguments and default template arguments of
<TT>D</TT>, corresponding <I>lambda-expression</I>s shall
have the same closure type (see below), and</SPAN></P></LI>

<LI><P>in each definition of <TT>D</TT>, corresponding
entities shall have the same language linkage; and</P></LI>

<LI><P>in each definition of <TT>D</TT>, the overloaded
operators referred to, the implicit calls to conversion
functions, constructors, operator new functions and operator
delete functions, shall refer to the same function<SPAN style="text-decoration:line-through;background-color:#FFA0A0">, or to a
function defined within the definition of <TT>D</TT></SPAN>;
and</P></LI>

<LI><P>in each definition of <TT>D</TT>, a default argument used by an
(implicit or explicit) function call <SPAN style="font-weight:bold;background-color:#A0FFA0">or a default
template argument used by an (implicit or explicit)
<I>template-id</I> or <I>simple-template-id</I></SPAN> is
treated as if its token sequence were present in the
definition of <TT>D</TT>; that is, the default
argument <SPAN style="font-weight:bold;background-color:#A0FFA0">or default template argument</SPAN> is subject
to the requirements described in this paragraph (<SPAN style="text-decoration:line-through;background-color:#FFA0A0">and,
if the default argument has subexpressions with default
arguments, this requirement applies</SPAN>
recursively) <SPAN style="text-decoration:line-through;background-color:#FFA0A0">[<I>Footnote:</I> 9.2.3.6 [dcl.fct.default]
describes how default argument names are looked up.
&#8212;<I>end footnote</I>]</SPAN>; and</P></LI>

<LI><P>...</P></LI>

</UL>

<P>If <TT>D</TT> is a template and is defined in more than
one translation unit, then the preceding requirements shall
apply both to names from the template's enclosing scope used
in the template definition (13.7.3 [temp.nondep]),
and also to dependent names at the point of instantiation
(13.7.2 [temp.dep]). <SPAN style="text-decoration:line-through;background-color:#FFA0A0">If the definitions
of <TT>D</TT> satisfy all these requirements, then the
behavior is as if there were a single definition
of <TT>D</TT>.</SPAN> <SPAN style="font-weight:bold;background-color:#A0FFA0">These requirements also apply to
corresponding entities defined within each definition of
<TT>D</TT> (including the closure types
of <I>lambda-expression</I>s, but excluding entities defined
within default arguments or defualt template arguments of
either <TT>D</TT> or an entity not defined within
<TT>D</TT>). For each such entity and for <TT>D</TT> itself,
the behavior is as if there is a single entity with a single
definition, including in the application of these
requirements to other entities.</SPAN> [<I>Note:</I> The
entity is still declared in multiple translation units, and
6.5 [basic.link] still applies to these
declarations. In particular, <I>lambda-expression</I>s
(7.5.5 [expr.prim.lambda]) appearing in the type
of <TT>D</TT> may result in the different declarations
having distinct types<SPAN style="font-weight:bold;background-color:#A0FFA0">, and <I>lambda-expression</I>s
appearng in a default argument of <TT>D</TT> may still
denote different types in different translation
units</SPAN>. &#8212;<I>end note</I>] If the definitions
of <TT>D</TT> do not satisfy these requirements, then the
<SPAN style="text-decoration:line-through;background-color:#FFA0A0">behavior is undefined.</SPAN>
<SPAN style="font-weight:bold;background-color:#A0FFA0">program is ill-formed, no diagnostic required.
[<I>Example:</I></SPAN></P>

<PRE>
<SPAN style="font-weight:bold;background-color:#A0FFA0">  inline void f(bool cond, void (*p)()) {
    if (cond) f(false, []{});
  }
  inline void g(bool cond, void (*p)() = []{}) {
    if (cond) g(false);
  }
  struct X {
    void h(bool cond, void (*p)() = []{}) {
      if (cond) h(false);
    }
  }</SPAN>
</PRE>

<P><SPAN style="font-weight:bold;background-color:#A0FFA0">If the definition of <TT>f</TT> appears in multiple
translation units, the behavior of the program is as if there
is only one definition of <TT>f</TT>. If the definition of
<TT>g</TT> appears in multiple translation units, the program
is ill-formed (no diagnostic required) because each such
definition uses a default argument that refers to a distinct
<I>lambda-expression</I> closure type. The definition of <TT>X</TT>
can sppear in multiple translation units of a valid program; the
<I>lambda-expression</I>s defined within the default argumeht of
<TT>X::h</TT> within the definition of <TT>X</TT> denote the
same closure type in each translation unit. &#8212;<I>end
example</I>]</SPAN></P>

</BLOCKQUOTE>

<BR><BR><HR><A NAME="2366"></A><H4>2366.
  
Can default initialization be constant initialization?
</H4><B>Section: </B>6.8.3.2&#160; [basic.start.static]
 &#160;&#160;&#160;

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

 <B>Submitter: </B>Geoffrey Romer
 &#160;&#160;&#160;

 <B>Date: </B>2017-11-01


<P>According to 6.8.3.2 [basic.start.static] paragraph 2,</P>

<BLOCKQUOTE>

<I>Constant initialization</I>
is performed if a variable or temporary object with
static or thread storage duration is initialized by a constant initializer
for the entity. If constant initialization is not performed, a variable
with static storage duration (6.6.5.1 [basic.stc.static]) or thread storage
duration (6.6.5.2 [basic.stc.thread]) is zero-initialized
(9.3 [dcl.init]). Together, zero-initialization and constant
initialization are called static initialization; all other initialization
is <I>dynamic initialization</I>.

</BLOCKQUOTE>

<P>This appears to require an explicit initializer for constant
initialization and would preclude examples like:</P>

<PRE>
  struct S {
    int i = 1;
  };
  static constexpr S s;
</PRE>

<P>where there is no initializer.</P>

<P><B>Notes from the October, 2018 teleconference:</B></P>

<P>CWG agreed that the example should be well-formed.</P>

<P><B>Proposed resolution, June, 2019:</B></P>

<OL><LI><P>Change 6.8.3.2 [basic.start.static] paragraph 2 as follows:</P></LI>

<BLOCKQUOTE>

<I>Constant initialization</I>
is performed if a variable or
temporary object with static or thread storage duration is
<SPAN style="font-weight:bold;background-color:#A0FFA0">constant-</SPAN>initialized <SPAN style="text-decoration:line-through;background-color:#FFA0A0">by a constant initializer</SPAN>
(7.7 [expr.const]) <SPAN style="text-decoration:line-through;background-color:#FFA0A0">for the entity</SPAN>. If constant
initialization is not performed, a variable with static
storage duration (6.6.5.1 [basic.stc.static]) or thread
storage duration (6.6.5.2 [basic.stc.thread]) is
zero-initialized (9.3 [dcl.init]). Together,
zero-initialization and constant initialization...

</BLOCKQUOTE>

<LI><P>Change 7.7 [expr.const] paragraph 2 as follows:</P></LI>

<BLOCKQUOTE>

<P>A <SPAN style="text-decoration:line-through;background-color:#FFA0A0"><I>constant initializer</I> for a</SPAN> variable or
temporary object <TT>o</TT> is <SPAN style="text-decoration:line-through;background-color:#FFA0A0">an initializer for which
interpreting its full-expression as
a <I>constant-expression</I> results in a constant
expression</SPAN> <SPAN style="font-weight:bold;background-color:#A0FFA0"><I>constant-initialized</I> if</SPAN></P>

<UL>

<LI><P><SPAN style="font-weight:bold;background-color:#A0FFA0">either it has an initializer or its
default-initialization results in some initialization being
performed, and</SPAN></P></LI>

<LI><P><SPAN style="font-weight:bold;background-color:#A0FFA0">its initialization full-expression is a constant
expression when interpreted as
a <I>constant-expression</I></SPAN>, except that
if <TT>o</TT> is an object, <SPAN style="text-decoration:line-through;background-color:#FFA0A0">such an initializer</SPAN>
<SPAN style="font-weight:bold;background-color:#A0FFA0">the initialization full-expression</SPAN> may also
invoke constexpr constructors for <TT>o</TT> and its
subobjects even if those objects are of non-literal class
types. [<I>Note:</I> Such a class may have a non-trivial
destructor. Within this
evaluation, <TT>std::is_constant_evaluated()</TT>
(20.15.10 [meta.const.eval])
returns <TT>true</TT>. &#8212;<I>end note</I>]</P></LI>

</UL>

</BLOCKQUOTE>

<LI><P>Change 7.7 [expr.const] paragraph 3 as follows:</P></LI>

<BLOCKQUOTE>

A variable is <I>usable in constant expressions</I> after
its initializing declaration is encountered if it is a
constexpr variable, or it is <SPAN style="font-weight:bold;background-color:#A0FFA0">a constant-initialized
variable</SPAN> of reference type or of const-qualified
integral or enumeration type<SPAN style="text-decoration:line-through;background-color:#FFA0A0">, and its initializer is a
constant initializer</SPAN>.

</BLOCKQUOTE>

<LI><P>Change 9.1.5 [dcl.constexpr] paragraph 5 as follows:</P></LI>

<BLOCKQUOTE>

For a constexpr function or constexpr constructor that is
neither defaulted nor a template, if no argument values
exist such that an invocation of the function or constructor
could be an evaluated subexpression of a core constant
expression (7.7 [expr.const]), or, for a
constructor, <SPAN style="text-decoration:line-through;background-color:#FFA0A0">a constant initializer for</SPAN>
<SPAN style="font-weight:bold;background-color:#A0FFA0">an evaluated subexpression of the initialization
full-expression of</SPAN>
some <SPAN style="font-weight:bold;background-color:#A0FFA0">constant-initialized</SPAN> object
(6.8.3.2 [basic.start.static]), the program is ill-formed,
no diagnostic required. [<I>Example:</I>...

</BLOCKQUOTE>

</OL>

<BR><BR><HR><A NAME="2376"></A><H4>2376.
  
Class template argument deduction with array declarator
</H4><B>Section: </B>12.3.1.8&#160; [over.match.class.deduct]
 &#160;&#160;&#160;

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

 <B>Submitter: </B>Mike Miller
 &#160;&#160;&#160;

 <B>Date: </B>2018-03-01


<P>An example like</P>

<PRE>
   template &lt;class ...T&gt; struct A {
     A(T...) {}
   };
   A x[29]{};

</PRE>

<P>Appears to be permitted by the current wording of the Standard,
but existing implementations reject it. Should this usage be
supported (in which case some mention of it in the wording would
be useful) or prohibited?</P>

<P><B>Notes from the November, 2018 meeting:</B></P>

<P>The example is intended to be ill-formed; the intent is
that declarator operators are not permitted, as
with <TT>decltype(auto).</TT></P>

<P><B>Proposed resolution, March, 2019:</B></P>

<P>Change 9.1.7.6 [dcl.type.class.deduct] paragraph 1 as follows:</P>

<BLOCKQUOTE>

<P>If a placeholder for a deduced class type appears as
a <I>decl-specifier</I> in the <I>decl-specifier-seq</I> of
an initializing declaration (9.3 [dcl.init]) of a
variable, the <SPAN style="font-weight:bold;background-color:#A0FFA0">declared type of the variable shall be
<I>cv</I> <TT>T</TT>, where <TT>T</TT> is the placeholder.
[<I>Example:</I></SPAN></P>

<PRE>
<SPAN style="font-weight:bold;background-color:#A0FFA0">  template &lt;class ...T&gt; struct A {
    A(T...) {}
  };
  A x[29]{};    //<SPAN style="font-family:Times;font-style:italic"> error: no declarator operators allowed</SPAN>
  const A&amp; y{}; //<SPAN style="font-family:Times;font-style:italic"> error: no declarator operators allowed</SPAN></SPAN>
</PRE>

<P><SPAN style="font-weight:bold;background-color:#A0FFA0">&#8212;<I>end example</I>] The</SPAN>
placeholder is replaced by the return type of
the function selected by overload resolution for class
template deduction (12.3.1.8 [over.match.class.deduct]). If
the <I>decl-specifier-seq</I> is followed by
an <I>init-declarator-list</I>
or <I>member-declarator-list</I> containing more than one
declarator, the type that replaces the placeholder shall be
the same in each deduction.</P>

</BLOCKQUOTE>

<BR><BR><HR><A NAME="2390"></A><H4>2390.
  
Is the argument of <TT>__has_cpp_attribute</TT> macro-expanded?
</H4><B>Section: </B>15.1&#160; [cpp.cond]
 &#160;&#160;&#160;

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

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

 <B>Date: </B>2018-11-14


<P>The Standard does not specify whether the argument of
<TT>__has_cpp_attribute</TT> is macro-expanded before being tested
to see if it names an attribute or not, and there is implementation
divergence.</P>

<P><B>Notes from the February, 2019 meeting:</B></P>

<P>CWG observed that a use of an attribute would be macro-expanded,
so it seemed reasonable to expect to be able to specify the same
macro as the argument to <TT>__has_cpp_attribute</TT> and get the
corresponding result.</P>

<P><B>Proposed resolution (June, 2019):</B></P>

<OL><LI><P>Change 15.1 [cpp.cond] paragraph 5 as follows:</P></LI>

<BLOCKQUOTE>

Each <I>has-attribute-expression</I> is replaced by a
non-zero <I>pp-number</I> matching the form of
an <I>integer-literal</I> if the implementation supports an
attribute with the name specified by interpreting
the <I>pp-token</I>s<SPAN style="font-weight:bold;background-color:#A0FFA0">, after macro expansion,</SPAN>
as an <I>attribute-token</I>, and by <TT>0</TT>
otherwise. The program is ill-formed if the <I>pp-token</I>s
do not match the form of an <I>attribute-token</I>.

</BLOCKQUOTE>

<LI><P>Change 15.1 [cpp.cond] paragraph 11 as follows:</P></LI>

<BLOCKQUOTE>

After all replacements due to macro expansion and
evaluations of <I>defined-macro-expression</I>s<SPAN style="font-weight:bold;background-color:#A0FFA0">,</SPAN>
<SPAN style="text-decoration:line-through;background-color:#FFA0A0">and</SPAN> <I>has-include-expression</I>s<SPAN style="font-weight:bold;background-color:#A0FFA0">,
and <I>has_attribute_expression</I>s</SPAN> have been
performed, all remaining identifiers and keywords, except
for <TT>true</TT> and <TT>false</TT>, are replaced with
the <I>pp-number</I> <TT>0</TT>, and then each preprocessing
token is converted into a token. [<I>Note:</I> An
alternative token (5.5 [lex.digraph]) is not an
identifier, even when its spelling consists entirely of
letters and underscores.  Therefore it is not subject to
this replacement. &#8212;<I>end note</I>]

</BLOCKQUOTE>

</OL>

<BR><BR><HR><A NAME="2400"></A><H4>2400.
  
Constexpr virtual functions and temporary objects
</H4><B>Section: </B>7.7&#160; [expr.const]
 &#160;&#160;&#160;

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

 <B>Submitter: </B>Daveed Vandevoorde
 &#160;&#160;&#160;

 <B>Date: </B>2019-02-08


<P>Consider an example like the following:</P>

<PRE>
  struct A {
    constexpr virtual int f() const {
      return 1;
    }
  };

  struct B : A {
    constexpr virtual int f() const {
      return 2;
    }
  };

  constexpr B b{};
  constexpr A&amp;&amp; ref = (B)b;

  static_assert(ref.f() == 2, "");
</PRE>

<P>Since the temporary bound to <TT>ref</TT> is non-const,
it can be re-newed to something else, which would make the
invocation <TT>ref.f()</TT> undefined behavior, which the
interpreter is required to catch.</P>

<P>Presumably, <TT>ref.f()</TT> should not be a constant
expression, and 7.7 [expr.const] paragraph 2 should
have a bullet for invoking a virtual function of a non-const
object unless its lifetime began within the evaluation of
the constant expression.</P>

<P><B>Proposed resolution (March, 2019):</B></P>

<P>Add the following as a new bullet following 7.7 [expr.const]
bullet 4.4:</P>

<BLOCKQUOTE>

<P>An expression <TT>e</TT> is a <I>core constant
expression</I> unless the evaluation of <TT>e</TT>,
following the rules of the abstract machine
(6.8.1 [intro.execution]), would evaluate one of the
following expressions:</P>

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

<LI><P>an invocation of an instantiated constexpr function or
constexpr constructor that fails to satisfy the requirements
for a constexpr function or constexpr constructor
(9.1.5 [dcl.constexpr]);</P></LI>

<LI><P><SPAN style="font-weight:bold;background-color:#A0FFA0">an invocation of a virtual function
(11.6.2 [class.virtual]) for an object unless</SPAN></P></LI>

<UL><LI><P><SPAN style="font-weight:bold;background-color:#A0FFA0">the object is usable in constant expressions
or</SPAN></P></LI>

<LI><P><SPAN style="font-weight:bold;background-color:#A0FFA0">its lifetime began within the evaluation of
<TT>e</TT>;</SPAN></P></LI>

</UL>

<LI><P>an expression that would exceed the
implementation-defined limits (see
Annex B [implimits]);</P></LI>

<LI><P>...</P></LI>

</UL>

</BLOCKQUOTE>

<BR><BR><HR><A NAME="2404"></A><H4>2404.
  
<TT>[[no_unique_address]]</TT> and allocation order
</H4><B>Section: </B>11.3&#160; [class.mem]
 &#160;&#160;&#160;

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

 <B>Submitter: </B>Daveed Vandevoorde
 &#160;&#160;&#160;

 <B>Date: </B>2018-12-13


<P>According to 11.3 [class.mem] paragraph 19,</P>

<BLOCKQUOTE>

Non-static data members of a (non-union) class with the same
access control (11.8 [class.access]) are allocated so
that later members have higher addresses within a class
object.

</BLOCKQUOTE>

<P>With the advent of the <TT>[[no_unique_address]]</TT>
attribute, &#8220;higher addresses&#8221; is no longer
strictly accurate. According to the FAQ in
<A HREF="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0840r2.html">
P0840R2</A>, next-to-last question:</P>

<BLOCKQUOTE>

<P>Q: Suppose I have members <TT>a</TT>, <TT>b</TT>, <TT>c</TT>
(in that order, with the
same access). Today we guarantee that <TT>&amp;a
&lt; &amp;b
&lt; &amp;c</TT>. What happens if <TT>b</TT>
has the attribute? </P>

<P>Two cases:</P>

<OL><LI><P>If the type of <TT>b</TT> is empty, then there is
no guarantee about the address of <TT>b</TT> (other than that
it is somewhere within the containing object).</P></LI>

<LI><P>If the type of <TT>b</TT>
is nonempty, then we still guarantee that
<TT>&amp;a &lt; &amp;b &lt; &amp;c</TT>.</P></LI>

</OL>

</BLOCKQUOTE>

<P>Presumably the wording in 11.3 [class.mem]
paragraph 19 needs to be changed to reflect that intent.</P>

<P><B>Proposed resolution, March, 2019:</B></P>

<P>Change 11.3 [class.mem] paragraph 19 as follows:</P>

<BLOCKQUOTE>

<SPAN style="font-weight:bold;background-color:#A0FFA0">[<I>Note:</I></SPAN> Non-static data members of a
(non-union) class with the same access control
(11.8 [class.access]) <SPAN style="font-weight:bold;background-color:#A0FFA0">and non-zero size
(6.6.2 [intro.object])</SPAN> are allocated so that
later members have higher addresses within a class
object. The order of allocation of non-static data members
with different access control is unspecified
<SPAN style="text-decoration:line-through;background-color:#FFA0A0">(11.8 [class.access])</SPAN>. Implementation alignment
requirements might cause two adjacent members not to be
allocated immediately after each other; so might
requirements for space for managing virtual functions
(11.6.2 [class.virtual]) and virtual base classes
(11.6.1 [class.mi]). <SPAN style="font-weight:bold;background-color:#A0FFA0">&#8212;<I>end note</I>]</SPAN>

</BLOCKQUOTE>

<BR><BR><HR><A NAME="2406"></A><H4>2406.
  
<TT>[[fallthrough]]</TT> attribute and iteration statements
</H4><B>Section: </B>9.11.6&#160; [dcl.attr.fallthrough]
 &#160;&#160;&#160;

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

 <B>Submitter: </B>Mike Miller
 &#160;&#160;&#160;

 <B>Date: </B>2019-03-08


<P>According to 9.11.6 [dcl.attr.fallthrough] paragraph 1,</P>

<BLOCKQUOTE>

A fallthrough statement may only appear within an enclosing
<TT>switch</TT> statement (8.4.2 [stmt.switch]). The
next statement that would be executed after a fallthrough
statement shall be a labeled statement whose label is a case
label or default label for the same <TT>switch</TT>
statement.

</BLOCKQUOTE>

<P>The meaning of &#8220;next statement that would be
executed&#8221; is unclear with respect to the controlled
substatement of an iteration statement. There is
implementation divergence on an example like:</P>

<PRE>
  void f(int n) {
    switch (n) {
      case 0:
        while (true)
          [[fallthrough]]; //<SPAN style="font-family:Times;font-style:italic"> Well-formed?</SPAN>
      case 1:
        break;
    }
  }
</PRE>

<P><B>Proposed resolution, April, 2019:</B></P>

<OL><LI><P>Change 9.11.6 [dcl.attr.fallthrough] paragraph 1 as follows:</P></LI>

<BLOCKQUOTE>

The <I>attribute-token</I> <TT>fallthrough</TT> may be
applied to a null statement (8.2 [stmt.expr]); such
a statement is a fallthrough
statement. The <I>attribute-token</I> <TT>fallthrough</TT>
shall appear at most once in each <I>attribute-list</I> and
no <I>attribute-argument-clause</I> shall be present. A
fallthrough statement may only appear within an enclosing
<TT>switch</TT> statement (8.4.2 [stmt.switch]). The
next statement that would be executed after a fallthrough
statement shall be a labeled statement whose label is a case
label or default label for the same <TT>switch</TT>
statement <SPAN style="font-weight:bold;background-color:#A0FFA0">and, if the fallthrough statement is
contained in an iteration statement, the next statement
shall be part of the same execution of the substatement of
the innermost enclosing iteration statement</SPAN>. The
program is ill-formed if there is no such statement.

</BLOCKQUOTE>

<LI><P>Change the example in 9.11.6 [dcl.attr.fallthrough] paragraph
3 as follows:</P></LI>

<BLOCKQUOTE>

<P>[<I>Example:</I></P>

<PRE>
  void f(int n) {
    void g(), h(), i();
    switch (n) {
    case 1:
    case 2:
      g();
      [[fallthrough]];
    case 3:              //<SPAN style="font-family:Times;font-style:italic"> warning on fallthrough discouraged</SPAN>
<SPAN style="font-weight:bold;background-color:#A0FFA0">      do {
        [[fallthrough]]; //<SPAN style="font-family:Times;font-style:italic"> error: next statement is not part of the same substatement execution</SPAN>
      } while (false);
    case 6:
      do {
        [[fallthrough]]; //<SPAN style="font-family:Times;font-style:italic"> error: next statement is not part of the same substatement execution</SPAN>
      } while (n--);
    case 7:
      while (false) {
        [[fallthrough]]; //<SPAN style="font-family:Times;font-style:italic"> error: next statement is not part of the same substatement execution</SPAN>
      }
    case 5:</SPAN>
      h();
    case 4:              //<SPAN style="font-family:Times;font-style:italic"> implementation may warn on fallthrough</SPAN>
      i();
      [[fallthrough]];   //<SPAN style="font-family:Times;font-style:italic"> ill-formed</SPAN>
    }
  }
</PRE>

<P>&#8212;<I>end example</I>]</P>

</BLOCKQUOTE>

</OL>

<BR><BR><HR><A NAME="2418"></A><H4>2418.
  
Missing cases in definition of &#8220;usable in constant expressions&#8221;
</H4><B>Section: </B>7.7&#160; [expr.const]
 &#160;&#160;&#160;

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

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

 <B>Date: </B>2018-11-25




<P>The term &#8220;usable in constant expressions&#8221;
(7.7 [expr.const] paragraph 3) is only defined for
variables:</P>

<BLOCKQUOTE>

A variable is <I>usable in constant expressions</I> after
its initializing declaration is encountered if it is a
constexpr variable, or it is of reference type or of
const-qualified integral or enumeration type, and its
initializer is a constant initializer.

</BLOCKQUOTE>

<P>However, uses of the term assume that it applies more
widely. For example, 7.7 [expr.const] bullet 4.7.1
mentions &#8220;a non-volatile glvalue that refers to an
object that is usable in constant expressions&#8221; (not
all objects are variables), and bullet 4.10.1 speaks of a
&#8220;data member of reference type&#8221; (also not a
variable) that is usable in constant expressions.</P>

<P><B>Proposed resolution, June, 2019:</B></P>

<P>Change 7.7 [expr.const] paragraph 3 as follows:</P>

<BLOCKQUOTE>

<P>A variable is usable in constant expressions after its
initializing declaration is encountered if it is a constexpr
variable, or it is of reference type or of const-qualified
integral or enumeration type, and its initializer is a
constant initializer. <SPAN style="font-weight:bold;background-color:#A0FFA0">An object or reference is
<I>usable in constant expressions</I> if it is</SPAN></P>

<UL><LI><P><SPAN style="font-weight:bold;background-color:#A0FFA0">a variable that is usable in constant
expressions, or</SPAN></P></LI>

<LI><P><SPAN style="font-weight:bold;background-color:#A0FFA0">a template parameter object
(13.1 [temp.param]), or</SPAN></P></LI>

<LI><P><SPAN style="font-weight:bold;background-color:#A0FFA0">a string literal object
(5.13.5 [lex.string]), or</SPAN></P></LI>

<LI><P><SPAN style="font-weight:bold;background-color:#A0FFA0">a non-mutable subobject or reference member
of any of the above, or</SPAN></P></LI>

<LI><P><SPAN style="font-weight:bold;background-color:#A0FFA0">a complete temporary object of non-volatile
const-qualified integral or enumeration type that is
initialized with a constant expression.</SPAN></P></LI>

</UL>

</BLOCKQUOTE>

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