diff --git a/source/basic.tex b/source/basic.tex index 8a8c9961dd..74122bc3b8 100644 --- a/source/basic.tex +++ b/source/basic.tex @@ -2802,15 +2802,17 @@ \indextext{object lifetime|(}% The \defn{lifetime} of an object or reference is a runtime property of the object or reference. -An object is said to have \defnadj{non-vacuous}{initialization} if it is of a class or -array type and it or one of its subobjects is initialized by a constructor -other than a trivial default constructor. \begin{note} Initialization by a -trivial copy/move constructor is non-vacuous initialization. \end{note} +\indextext{initialization!vacuous}% +A variable is said to have \defn{vacuous initialization} +if it is default-initialized and, +if it is of class type or a (possibly multi-dimensional) array thereof, +that class type has a trivial default constructor. The lifetime of an object of type \tcode{T} begins when: \begin{itemize} -\item storage with the proper alignment and size for type \tcode{T} is -obtained, and -\item if the object has non-vacuous initialization, its initialization is complete, +\item storage with the proper alignment and size + for type \tcode{T} is obtained, and +\item its initialization (if any) is complete + (including vacuous initialization)\iref{dcl.init}, \end{itemize} except that if the object is a union member or subobject thereof, its lifetime only begins if that union member is the @@ -2818,8 +2820,8 @@ or as described in \ref{class.union}. The lifetime of an object \placeholder{o} of type \tcode{T} ends when: \begin{itemize} -\item if \tcode{T} is a class type with a non-trivial -destructor\iref{class.dtor}, the destructor call starts, or +\item if \tcode{T} is a non-class type, the object is destroyed, or +\item if \tcode{T} is a class type, the destructor call starts, or \item the storage which the object occupies is released, or is reused by an object that is not nested within \placeholder{o}\iref{intro.object}. \end{itemize} @@ -5974,26 +5976,25 @@ \indextext{program!termination|(}% \indextext{object!destructor static}% \indextext{\idxcode{main} function!return from}% -Destructors\iref{class.dtor} for initialized objects -(that is, objects whose lifetime\iref{basic.life} has begun) -with static storage duration, -and functions registered with \tcode{std::atexit}, +Constructed objects\iref{dcl.init} +with static storage duration are destroyed +and functions registered with \tcode{std::atexit} are called as part of a call to \indextext{\idxcode{exit}}% \indexlibrary{\idxcode{exit}}% \tcode{std::exit}\iref{support.start.term}. The call to \tcode{std::exit} is sequenced before -the invocations of the destructors and the registered functions. +the destructions and the registered functions. \begin{note} Returning from \tcode{main} invokes \tcode{std::exit}\iref{basic.start.main}. \end{note} \pnum -Destructors for initialized objects with thread storage duration within a given thread -are called as a result of returning from the initial function of that thread and as a +Constructed objects with thread storage duration within a given thread +are destroyed as a result of returning from the initial function of that thread and as a result of that thread calling \tcode{std::exit}. -The completions of the destructors for all initialized objects with thread storage -duration within that thread strongly happen before the initiation of the destructors of +The destruction of all constructed objects with thread storage +duration within that thread strongly happens before destroying any object with static storage duration. \pnum diff --git a/source/classes.tex b/source/classes.tex index efbb440557..7008d06b61 100644 --- a/source/classes.tex +++ b/source/classes.tex @@ -2120,7 +2120,6 @@ \tcode{virtual}. \pnum -A destructor is used to destroy objects of its class type. \indextext{restriction!destructor}% The address of a destructor shall not be taken. \indextext{\idxcode{const}!destructor and}% @@ -6506,12 +6505,12 @@ \begin{note} There cannot be a move from the exception object because it is always an lvalue. \end{note} \end{itemize} -Copy elision is required +Copy elision is not permitted where an expression is evaluated in a context requiring a constant expression\iref{expr.const} and in constant initialization\iref{basic.start.static}. \begin{note} -Copy elision might not be performed +Copy elision might be performed if the same expression is evaluated in another context. \end{note} diff --git a/source/declarations.tex b/source/declarations.tex index 591d7c5c4d..f4cbd195af 100644 --- a/source/declarations.tex +++ b/source/declarations.tex @@ -810,7 +810,7 @@ each of its parameter types shall be a literal type; \item -its \grammarterm{function-body} shall not contain +its \grammarterm{function-body} shall not enclose\iref{stmt.stmt} \begin{itemize} \item an \grammarterm{asm-definition}, \item a \tcode{goto} statement, @@ -822,7 +822,7 @@ \end{itemize} \begin{note} A \grammarterm{function-body} that is \tcode{= delete} or \tcode{= default} -contains none of the above. +encloses none of the above. \end{note} \end{itemize} @@ -955,7 +955,7 @@ a call to a constexpr function can appear in a constant expression\iref{expr.const} and \item -copy elision is mandatory in a constant expression\iref{class.copy.elision}. +copy elision is not performed in a constant expression\iref{class.copy.elision}. \end{itemize} \pnum @@ -1310,8 +1310,11 @@ \opt{\tcode{typename}} \opt{\grammarterm{nested-name-specifier}} \grammarterm{template-name} is a placeholder for a deduced class type\iref{dcl.type.class.deduct}. -The \grammarterm{template-name} shall name a class template -that is not an injected-class-name. +The \grammarterm{template-name} shall name a class template. +\begin{note} +An injected-class-name is never interpreted as a \grammarterm{template-name} +in contexts where class template argument deduction would be performed\iref{temp.local}. +\end{note} The other \grammarterm{simple-type-specifier}{s} specify either a previously-declared type, a type determined from an @@ -4469,13 +4472,18 @@ \pnum An object whose initialization has completed is deemed to be constructed, -even if no constructor of the object's class +even if the object is of non-class type or +no constructor of the object's class is invoked for the initialization. \begin{note} Such an object might have been value-initialized or initialized by aggregate initialization\iref{dcl.init.aggr} or by an inherited constructor\iref{class.inhctor.init}. \end{note} +Destroying an object of class type invokes the destructor of the class. +Destroying a scalar type has no effect other than +ending the lifetime of the object\iref{basic.life}. +Destroying an array destroys each element in reverse subscript order. \pnum A declaration that specifies the initialization of a variable, @@ -4804,7 +4812,7 @@ \end{example} \pnum -If a reference member is initialized from its default member initializer +If a member has a default member initializer and a potentially-evaluated subexpression thereof is an aggregate initialization that would use that default member initializer, the program is ill-formed. @@ -4817,6 +4825,10 @@ const A& a2 { A{} }; // error }; A a{a,a}; // OK + + struct B { + int n = B{}.n; // error + }; \end{codeblock} \end{example} @@ -5166,29 +5178,17 @@ Given types ``\cvqual{cv1} \tcode{T1}'' and ``\cvqual{cv2} \tcode{T2}'', ``\cvqual{cv1} \tcode{T1}'' is \defn{reference-related} to ``\cvqual{cv2} \tcode{T2}'' if -\tcode{T1} is the same type as \tcode{T2}, or +\tcode{T1} is similar\iref{conv.qual} to \tcode{T2}, or \tcode{T1} is a base class of \tcode{T2}. ``\cvqual{cv1} \tcode{T1}'' is \defn{reference-compatible} with ``\cvqual{cv2} \tcode{T2}'' if -\begin{itemize} -\item \tcode{T1} is reference-related to \tcode{T2}, or -\item \tcode{T2} is ``\tcode{noexcept} function'' and \tcode{T1} is ``function'', -where the function types are otherwise the same, -\end{itemize} -and -\cvqual{cv1} -is the same cv-qualification as, or greater cv-qualification than, -\cvqual{cv2}. -In all cases where the reference-related or reference-compatible relationship -of two types is used to establish the validity of a reference binding, and -\tcode{T1} -is a base class of -\tcode{T2}, -a program that necessitates such a binding is ill-formed if -\tcode{T1} -is an inaccessible\iref{class.access} or ambiguous\iref{class.member.lookup} -base class of -\tcode{T2}. +a prvalue of type ``pointer to \cvqual{cv2} \tcode{T2}'' can be converted to +the type ``pointer to \cvqual{cv1} \tcode{T1}'' +via a standard conversion sequence\iref{conv}. +In all cases where the reference-compatible relationship +of two types is used to establish the validity of a reference binding and +the standard conversion sequence would be ill-formed, +a program that necessitates such a binding is ill-formed. \pnum A reference to type ``\cvqual{cv1} \tcode{T1}'' is initialized by @@ -5586,9 +5586,7 @@ \item Otherwise, if \tcode{T} is a reference type, a prvalue of the type referenced by \tcode{T} is generated. -The prvalue initializes its result object by -copy-list-initialization or direct-list-initialization, -depending on the kind of initialization for the reference. +The prvalue initializes its result object by copy-list-initialization. The prvalue is then used to direct-initialize the reference. \begin{note} As usual, the binding will fail and the program is ill-formed if the reference type is an lvalue reference to a non-const type. \end{note} @@ -5606,6 +5604,10 @@ const int& i1 = { 1 }; // OK const int& i2 = { 1.1 }; // error: narrowing const int (&iar)[2] = { 1, 2 }; // OK: \tcode{iar} is bound to temporary array + +struct A { } a; +struct B { explicit B(const A&); }; +const B &b2{a}; // error: cannot copy-list-initialize \tcode{B} temporary from \tcode{A} \end{codeblock} \end{example} @@ -8780,15 +8782,19 @@ \pnum The attribute may be applied to the declaration of a class, -a \grammarterm{typedef-name}, a variable, a non-static data member, +a \grammarterm{typedef-name}, +a variable (including a structured binding declaration), +a non-static data member, a function, an enumeration, or an enumerator. \pnum -\begin{note} -For an entity marked \tcode{maybe_unused}, implementations -should not emit a warning that the entity is unused, or -that the entity is used despite the presence of the attribute. -\end{note} +For an entity marked \tcode{maybe_unused}, +implementations should not emit a warning +that the entity or its structured bindings (if any) +are used or unused. +For a structured binding declaration not marked \tcode{maybe_unused}, +implementations should not emit such a warning unless +all of its structured bindings are unused. \pnum A name or entity declared without the \tcode{maybe_unused} attribute diff --git a/source/exceptions.tex b/source/exceptions.tex index 22947b9438..438b4fbb0f 100644 --- a/source/exceptions.tex +++ b/source/exceptions.tex @@ -365,12 +365,12 @@ \indextext{unwinding!stack}% As control passes from the point where an exception is thrown to a handler, -destructors are invoked by a process, specified in this subclause, called -\defn{stack unwinding}. +objects with automatic storage duration are destroyed by a process, +specified in this subclause, called \defn{stack unwinding}. \pnum -The destructor is invoked for each automatic object of class type constructed, -but not yet destroyed, +Each object with automatic storage duration is destroyed if it has been +constructed, but not yet destroyed, since the try block was entered. If an exception is thrown during the destruction of temporaries or local variables for a \tcode{return} statement\iref{stmt.return}, @@ -882,7 +882,9 @@ is potentially-throwing if and only if any of the destructors for any of its potentially constructed subobjects -is potentially throwing. +is potentially-throwing or +the destructor is virtual and the destructor of any virtual base class +is potentially-throwing. \pnum The exception specification for an implicitly-declared assignment operator, diff --git a/source/expressions.tex b/source/expressions.tex index c0c1807a22..3e369e9ca1 100644 --- a/source/expressions.tex +++ b/source/expressions.tex @@ -973,7 +973,7 @@ \pnum A prvalue of type ``pointer to \cv{} \tcode{D}'', where \tcode{D} -is a class type, can be converted to a prvalue of type ``pointer to +is a complete class type, can be converted to a prvalue of type ``pointer to \cv{} \tcode{B}'', where \tcode{B} is a base class\iref{class.derived} of \tcode{D}. If \tcode{B} is an inaccessible\iref{class.access} or @@ -1005,8 +1005,8 @@ A prvalue of type ``pointer to member of \tcode{B} of type \cv{} \tcode{T}'', where \tcode{B} is a class type, can be converted to a prvalue of type ``pointer to member of \tcode{D} of type \cv{} -\tcode{T}'', where \tcode{D} is a derived class\iref{class.derived} -of \tcode{B}. If \tcode{B} is an +\tcode{T}'', where \tcode{D} is a complete class derived\iref{class.derived} +from \tcode{B}. If \tcode{B} is an inaccessible\iref{class.access}, ambiguous\iref{class.member.lookup}, or virtual\iref{class.mi} base class of \tcode{D}, or a base class of a virtual base class of @@ -2201,7 +2201,11 @@ \pnum A \grammarterm{lambda-expression} appearing in a default argument shall not -implicitly or explicitly capture any entity. +implicitly or explicitly capture any entity, +except for an \grammarterm{init-capture} for which +any full-expression in its \grammarterm{initializer} +satisfies the constraints of an expression appearing in +a default argument\iref{dcl.fct.default}. \begin{example} \begin{codeblock} void f2() { @@ -2211,6 +2215,8 @@ void g3(int = ([=]{ return i; })()); // ill-formed void g4(int = ([=]{ return 0; })()); // OK void g5(int = ([]{ return sizeof i; })()); // OK + void g6(int = ([x=1]{ return x; })(); // OK + void g7(int = ([x=i]{ return x; })(); // ill-formed } \end{codeblock} \end{example} @@ -3713,7 +3719,8 @@ \indextext{cast!derived class}% A prvalue of type ``pointer to \cvqual{cv1} \tcode{B}'', where \tcode{B} is a class type, can be converted to a prvalue of type ``pointer to -\cvqual{cv2} \tcode{D}'', where \tcode{D} is a class derived\iref{class.derived} +\cvqual{cv2} \tcode{D}'', +where \tcode{D} is a complete class derived\iref{class.derived} from \tcode{B}, if \cvqual{cv2} is the same cv-qualification as, or greater cv-qualification than, \cvqual{cv1}. @@ -3732,8 +3739,9 @@ \indextext{cast!pointer-to-member}% A prvalue of type ``pointer to member of \tcode{D} of type \cvqual{cv1} \tcode{T}'' can be converted to a prvalue of type ``pointer to member of -\tcode{B} of type \cvqual{cv2} \tcode{T}'', where \tcode{B} is a base -class\iref{class.derived} of \tcode{D}, +\tcode{B} of type \cvqual{cv2} \tcode{T}'', where +\tcode{D} is a complete class type and +\tcode{B} is a base class\iref{class.derived} of \tcode{D}, if \cvqual{cv2} is the same cv-qualification as, or greater cv-qualification than, \cvqual{cv1}.\footnote{Function types (including those used in pointer-to-member-function @@ -6505,7 +6513,7 @@ requirements as detailed in this subclause; other contexts have different semantics depending on whether or not an expression satisfies these requirements. Expressions that satisfy these requirements, -assuming that copy elision is performed, +assuming that copy elision\iref{class.copy.elision} is not performed, are called \indexdefn{expression!constant}% \defnx{constant expressions}{constant expression}. \begin{note} Constant expressions can be evaluated diff --git a/source/overloading.tex b/source/overloading.tex index 0602fc540a..2e1b9b2e32 100644 --- a/source/overloading.tex +++ b/source/overloading.tex @@ -1406,9 +1406,11 @@ with ``\cvqual{cv2} \tcode{T2}'', are candidate functions. For direct-initialization, those explicit conversion functions that are not hidden within \tcode{S} and yield -type ``lvalue reference to \cvqual{cv2} \tcode{T2}'' or ``\cvqual{cv2} -\tcode{T2}'' or ``rvalue reference to \cvqual{cv2} \tcode{T2}'', -respectively, where \tcode{T2} is the same type as \tcode{T} or can be +type ``lvalue reference to \cvqual{cv2} \tcode{T2}'' +(when initializing an lvalue reference or an rvalue reference to function) +or ``rvalue reference to \cvqual{cv2} \tcode{T2}'' +(when initializing an rvalue reference or an lvalue reference to function), +where \tcode{T2} is the same type as \tcode{T} or can be converted to type \tcode{T} with a qualification conversion\iref{conv.qual}, are also candidate functions. diff --git a/source/statements.tex b/source/statements.tex index 6a18726066..e065fced45 100644 --- a/source/statements.tex +++ b/source/statements.tex @@ -31,6 +31,43 @@ The optional \grammarterm{attribute-specifier-seq} appertains to the respective statement. +\pnum +A \defn{substatement} of a \grammarterm{statement} is one of the following: +\begin{itemize} +\item + for a \grammarterm{labeled-statement}, its contained \grammarterm{statement}, +\item + for a \grammarterm{compound-statement}, any \grammarterm{statement} of its \grammarterm{statement-seq}, +\item + for a \grammarterm{selection-statement}, any of its \grammarterm{statement}{s} (but not its \grammarterm{init-statement}), or +\item + for an \grammarterm{iteration-statement}, its contained \grammarterm{statement} (but not an \grammarterm{init-statement}). +\end{itemize} +\begin{note} +The \grammarterm{compound-statement} of a \grammarterm{lambda-expression} +is not a substatement of the \grammarterm{statement} (if any) +in which the \grammarterm{lambda-expression} lexically appears. +\end{note} + +\pnum +A \grammarterm{statement} \tcode{S1} \defnx{encloses}{enclosing statement} +a \grammarterm{statement} \tcode{S2} if +\begin{itemize} +\item + \tcode{S2} is a substatement of \tcode{S1}\iref{dcl.dcl}, +\item + \tcode{S1} is a \grammarterm{selection-statement} or + \grammarterm{iteration-statement} and + \tcode{S2} is the \grammarterm{init-statement} of \tcode{S1}, +\item + \tcode{S1} is a \grammarterm{try-block} and \tcode{S2} + is its \grammarterm{compound-statement} or + any of the \grammarterm{compound-statement}{s} of + its \grammarterm{handler}{s}, or +\item + \tcode{S1} encloses a statement \tcode{S3} and \tcode{S3} encloses \tcode{S2}. +\end{itemize} + \pnum \indextext{\idxgram{condition}{s}!rules for}% The rules for \grammarterm{condition}{s} apply both to @@ -208,9 +245,8 @@ \begin{note} An \grammarterm{init-statement} ends with a semicolon. \end{note} -In \ref{stmt.stmt}, the term \term{substatement} refers to -the contained \grammarterm{statement} or \grammarterm{statement}{s} that appear -in the syntax notation. + +\pnum \indextext{scope!\idxgram{selection-statement}}% The substatement in a \grammarterm{selection-statement} (each substatement, in the \tcode{else} form of the \tcode{if} statement) implicitly defines @@ -714,7 +750,7 @@ \indextext{\idxcode{abort}}% \indexlibrary{\idxcode{abort}}% \tcode{std::abort()}\iref{support.start.term}, for example) without -destroying class objects with automatic storage duration. +destroying objects with automatic storage duration. \end{note} \rSec2[stmt.break]{The \tcode{break} statement}% @@ -876,9 +912,10 @@ A program that jumps\footnote{The transfer from the condition of a \tcode{switch} statement to a \tcode{case} label is considered a jump in this respect.} from a point where a variable with automatic storage duration is -not in scope to a point where it is in scope is ill-formed unless the -variable has scalar type, class type with a trivial default constructor and a trivial destructor, a cv-qualified version of one of these types, or an array of one of the preceding types and is declared without an -\grammarterm{initializer}\iref{dcl.init}. +not in scope to a point where it is in scope is ill-formed unless +the variable has vacuous initialization\iref{dcl.init}. +In such a case, the variables with vacuous initialization +are constructed in the order of their declaration. \begin{example} \begin{codeblock} @@ -929,8 +966,8 @@ \pnum \indextext{\idxcode{static}!destruction of local}% -The destructor for a block-scope object with static or thread storage duration will be -executed if and only if it was constructed. +A block-scope object with static or thread storage duration will be +destroyed if and only if it was constructed. \begin{note} \ref{basic.start.term} describes the order in which block-scope objects with static and thread storage duration are destroyed. diff --git a/source/templates.tex b/source/templates.tex index 3a38870f84..c9008923a7 100644 --- a/source/templates.tex +++ b/source/templates.tex @@ -4379,8 +4379,10 @@ as a \grammarterm{template-argument} for a template \grammarterm{template-parameter}, or as the final identifier in the \grammarterm{elaborated-type-specifier} of a friend class template declaration, -it refers to the -class template itself. Otherwise, it is equivalent to the \grammarterm{template-name} +it is a \grammarterm{template-name} that refers to the +class template itself. +Otherwise, it is a \grammarterm{type-name} +equivalent to the \grammarterm{template-name} followed by the \grammarterm{template-parameter}{s} of the class template enclosed in \tcode{<>}. @@ -5467,7 +5469,8 @@ \pnum \indextext{specialization!template}% -The act of instantiating a function, a class, a member of a class template or +The act of instantiating a function, a variable, +a class, a member of a class template, or a member template is referred to as \defn{template instantiation}. @@ -5490,12 +5493,14 @@ \pnum An explicit specialization may be declared for a function template, -a class template, a member of a class template or a member template. +a variable template, a class template, a member of a class template, or +a member template. An explicit specialization declaration is introduced by \tcode{template<>}. -In an explicit specialization declaration for a class template, +In an explicit specialization declaration for +a variable template, a class template, a member of a class template or a class member template, -the name of the class that is explicitly specialized shall be a +the name of the variable or class that is explicitly specialized shall be a \grammarterm{simple-template-id}. In the explicit specialization declaration for a function template or a member function template, @@ -5527,7 +5532,7 @@ An instantiated template specialization can be either implicitly instantiated\iref{temp.inst} for a given argument list or be explicitly instantiated\iref{temp.explicit}. -A specialization is a class, function, or class member that is either +A specialization is a class, variable, function, or class member that is either instantiated or explicitly specialized\iref{temp.expl.spec}. \pnum @@ -7335,14 +7340,15 @@ \tcode{A}) as described below. If removing references and cv-qualifiers from \tcode{P} gives -\tcode{std::initializer_list} -or \tcode{P$'$[N]} -for some \tcode{P$'$} and \tcode{N} and the +\tcode{std::initializer_list} +or $\tcode{P}'\tcode{[N]}$ +for some $\tcode{P}'$ and \tcode{N} and the argument is a non-empty initializer list\iref{dcl.init.list}, then deduction is -performed instead for each element of the initializer list, taking -\tcode{P$'$} as a function template parameter type and the initializer -element as its argument, -and in the \tcode{P$'$[N]} case, if \tcode{N} is a non-type template parameter, +performed instead for each element of the initializer list independently, +taking $\tcode{P}'$ +as separate function template parameter types $\tcode{P}'_i$ +and the $i^\text{th}$ initializer element as the corresponding argument. +In the $\tcode{P}'\tcode{[N]}$ case, if \tcode{N} is a non-type template parameter, \tcode{N} is deduced from the length of the initializer list. Otherwise, an initializer list argument causes the parameter to be considered a non-deduced context\iref{temp.deduct.type}. @@ -7371,6 +7377,14 @@ template void n(T const(&)[N], T); n({{1},{2},{3}},Aggr()); // OK, \tcode{T} is \tcode{Aggr}, \tcode{N} is \tcode{3} + +template void o(T (* const (&)[N])(T)) { } +int f1(int); +int f4(int); +char f4(char); +o({ &f1, &f4 }); // OK, \tcode{T} deduced as \tcode{int} from first element, nothing + // deduced from second element, \tcode{N} deduced as \tcode{2} +o({ &f1, static_cast(&f4) }); // error: conflicting deductions for \tcode{T} \end{codeblock} \end{example} For a function parameter pack that occurs at the end @@ -7524,7 +7538,7 @@ \grammarterm{simple-template-id}, then the transformed \tcode{A} -can be a derived class of the +can be a derived class \tcode{D} of the deduced \tcode{A}. Likewise, if @@ -7533,8 +7547,28 @@ \grammarterm{simple-template-id}, the transformed \tcode{A} can be a pointer to a -derived class pointed to by the deduced +derived class \tcode{D} pointed to by the deduced \tcode{A}. +However, if there is a class \tcode{C} that is +a (direct or indirect) base class of \tcode{D} and +derived (directly or indirectly) from a class \tcode{B} and +that would be a valid deduced \tcode{A}, +the deduced \tcode{A} cannot be \tcode{B} or pointer to \tcode{B}, +respectively. +\begin{example} +\begin{codeblock} +template struct X; +template <> struct X<> {}; +template + struct X : X {}; +struct D : X {}; + +template +int f(const X&); +int x = f(D()); // calls \tcode{f}, not \tcode{f<>} + // \tcode{B} is \tcode{X<>}, \tcode{C} is \tcode{X} +\end{codeblock} +\end{example} \end{itemize} \pnum