%!TEX root = std.tex \rSec0[except]{Exception handling}% \indextext{exception handling|(} %gram: \rSec1[gram.except]{Exception handling} %gram: \indextext{exception object|see{exception handling, exception object}}% \indextext{object, exception|see{exception handling, exception object}} \pnum Exception handling provides a way of transferring control and information from a point in the execution of a thread to an exception handler associated with a point previously passed by the execution. A handler will be invoked only by throwing an exception in code executed in the handler's try block or in functions called from the handler's try block. \indextext{\idxcode{try}}% % \begin{bnf} \nontermdef{try-block}\br \terminal{try} compound-statement handler-seq \end{bnf} \indextext{\idxcode{try}}% % \begin{bnf} \nontermdef{function-try-block}\br \terminal{try} ctor-initializer\opt compound-statement handler-seq \end{bnf} \begin{bnf} \nontermdef{handler-seq}\br handler handler-seq\opt \end{bnf} \indextext{\idxcode{catch}}% % \begin{bnf} \nontermdef{handler}\br \terminal{catch (} exception-declaration \terminal{)} compound-statement \end{bnf} \begin{bnf} \nontermdef{exception-declaration}\br attribute-specifier-seq\opt type-specifier-seq declarator\br attribute-specifier-seq\opt type-specifier-seq abstract-declarator\opt\br \terminal{...} \end{bnf} The optional \grammarterm{attribute-specifier-seq} in an \grammarterm{exception-declaration} appertains to the parameter of the catch clause~(\ref{except.handle}). \pnum \indextext{exception handling!try block}% \indextext{exception handling!handler}% \indextext{try block|see{exception handling, try block}}% \indextext{handler|see{exception handling, handler}}% A \grammarterm{try-block} is a \grammarterm{statement} (Clause~\ref{stmt.stmt}). \enternote Within this Clause ``try block'' is taken to mean both \grammarterm{try-block} and \grammarterm{function-try-block}. \exitnote \pnum \indextext{exception handling!\idxcode{goto}}% \indextext{exception handling!\idxcode{switch}}% \indextext{\idxcode{goto}!and try block}% \indextext{\idxcode{switch}!and try block}% \indextext{\idxcode{goto}!and handler}% \indextext{\idxcode{switch}!and handler}% A \tcode{goto} or \tcode{switch} statement shall not be used to transfer control into a try block or into a handler. \enterexample \begin{codeblock} void f() { goto l1; // Ill-formed goto l2; // Ill-formed try { goto l1; // OK goto l2; // Ill-formed l1: ; } catch (...) { l2: ; goto l1; // Ill-formed goto l2; // OK } } \end{codeblock} \exitexample \indextext{\idxcode{goto}!and try block}% \indextext{\idxcode{switch}!and try block}% \indextext{\idxcode{return}!and try block}% \indextext{\idxcode{continue}!and try block}% \indextext{\idxcode{goto}!and handler}% \indextext{\idxcode{switch}!and handler}% \indextext{\idxcode{return}!and handler}% \indextext{\idxcode{continue}!and handler}% A \tcode{goto}, \tcode{break}, \tcode{return}, or \tcode{continue} statement can be used to transfer control out of a try block or handler. When this happens, each variable declared in the try block will be destroyed in the context that directly contains its declaration. \enterexample \begin{codeblock} lab: try { T1 t1; try { T2 t2; if (@\grammarterm{condition}@) goto lab; } catch(...) { /* @\placeholder{handler 2}@ */ } } catch(...) { /* @\placeholder{handler 1}@ */ } \end{codeblock} Here, executing \tcode{goto lab;} will destroy first \tcode{t2}, then \tcode{t1}, assuming the \grammarterm{condition} does not declare a variable. Any exception raised while destroying \tcode{t2} will result in executing \placeholder{handler 2}; any exception raised while destroying \tcode{t1} will result in executing \placeholder{handler 1}. \exitexample \pnum \indextext{function try block|see{exception handling, function try block}}% \indextext{exception handling!function try block}% A \grammarterm{function-try-block} associates a \grammarterm{handler-seq} with the \grammarterm{ctor-initializer}, if present, and the \grammarterm{compound-statement}. An exception thrown during the execution of the \grammarterm{compound-statement} or, for constructors and destructors, during the initialization or destruction, respectively, of the class's subobjects, transfers control to a handler in a \grammarterm{function-try-block} in the same way as an exception thrown during the execution of a \grammarterm{try-block} transfers control to other handlers. \enterexample \begin{codeblock} int f(int); class C { int i; double d; public: C(int, double); }; C::C(int ii, double id) try : i(f(ii)), d(id) { // constructor statements } catch (...) { // handles exceptions thrown from the ctor-initializer // and from the constructor statements } \end{codeblock} \exitexample \rSec1[except.throw]{Throwing an exception}% \indextext{exception handling!throwing}% \indextext{throwing|see{exception handling, throwing}} \pnum Throwing an exception transfers control to a handler. \enternote An exception can be thrown from one of the following contexts: \grammarterm{throw-expression}{s}~(\ref{expr.throw}), allocation functions~(\ref{basic.stc.dynamic.allocation}), \tcode{dynamic_cast}~(\ref{expr.dynamic.cast}), \tcode{typeid}~(\ref{expr.typeid}), \grammarterm{new-expression}{s}~(\ref{expr.new}), and standard library functions~(\ref{structure.specifications}). \exitnote An object is passed and the type of that object determines which handlers can catch it. \enterexample \begin{codeblock} throw "Help!"; \end{codeblock} can be caught by a \term{handler} of \tcode{const} \tcode{char*} type: \begin{codeblock} try { // ... } catch(const char* p) { // handle character string exceptions here } \end{codeblock} and \begin{codeblock} class Overflow { public: Overflow(char,double,double); }; void f(double x) { throw Overflow('+',x,3.45e107); } \end{codeblock} can be caught by a handler for exceptions of type \tcode{Overflow} \begin{codeblock} try { f(1.2); } catch(Overflow& oo) { // handle exceptions of type \tcode{Overflow} here } \end{codeblock} \exitexample \pnum \indextext{exception handling!throwing}% \indextext{exception handling!handler}% \indextext{exception handling!nearest handler}% When an exception is thrown, control is transferred to the nearest handler with a matching type~(\ref{except.handle}); ``nearest'' means the handler for which the \grammarterm{compound-statement} or \grammarterm{ctor-initializer} following the \tcode{try} keyword was most recently entered by the thread of control and not yet exited. \pnum Throwing an exception copy-initializes~(\ref{dcl.init}, \ref{class.copy}) a temporary object, called the \indextext{exception handling!exception object}\term{exception object}. The temporary is an lvalue and is used to initialize the variable declared in the matching \term{handler}~(\ref{except.handle}). If the type of the exception object would be an incomplete type or a pointer to an incomplete type other than (possibly cv-qualified) \tcode{void} the program is ill-formed. \pnum \indextext{exception handling!memory}% \indextext{exception handling!rethrowing}% \indextext{exception handling!exception object}% The memory for the exception object is allocated in an unspecified way, except as noted in~\ref{basic.stc.dynamic.allocation}. If a handler exits by rethrowing, control is passed to another handler for the same exception. The exception object is destroyed after either the last remaining active handler for the exception exits by any means other than rethrowing, or the last object of type \tcode{std::exception_ptr}~(\ref{propagation}) that refers to the exception object is destroyed, whichever is later. In the former case, the destruction occurs when the handler exits, immediately after the destruction of the object declared in the \grammarterm{exception-declaration} in the handler, if any. In the latter case, the destruction occurs before the destructor of \tcode{std::exception_ptr} returns. The implementation may then deallocate the memory for the exception object; any such deallocation is done in an unspecified way. \enternote a thrown exception does not propagate to other threads unless caught, stored, and rethrown using appropriate library functions; see~\ref{propagation} and~\ref{futures}. \exitnote \pnum \indextext{exception handling!exception object!constructor}% \indextext{exception handling!exception object!destructor}% When the thrown object is a class object, the constructor selected for the copy-initialization and the destructor shall be accessible, even if the copy/move operation is elided~(\ref{class.copy}). \pnum \indextext{exception handling!rethrow}% \indextext{rethrow|see{exception handling, rethrow}}% \indextext{reraise|see{exception handling, rethrow}}% An exception is considered caught when a handler for that exception becomes active~(\ref{except.handle}). \enternote An exception can have active handlers and still be considered uncaught if it is rethrown. \exitnote \pnum \indextext{exception handling!terminate called@\tcode{terminate()} called}% \indextext{\idxcode{terminate()}!called}% If the exception handling mechanism, after completing the initialization of the exception object but before the activation of a handler for the exception, calls a function that exits via an exception, \tcode{std::terminate} is called~(\ref{except.terminate}). \enterexample \begin{codeblock} struct C { C() { } C(const C&) { if (std::uncaught_exceptions()) { throw 0; // throw during copy to handler's \grammarterm{exception-declaration} object~(\ref{except.handle}) } } }; int main() { try { throw C(); // calls \tcode{std::terminate()} if construction of the handler's // \grammarterm{exception-declaration} object is not elided~(\ref{class.copy}) } catch(C) { } } \end{codeblock} \exitexample \rSec1[except.ctor]{Constructors and destructors}% \indextext{exception handling!constructors and destructors}% \indextext{stack unwinding!see exception handling, constructors and destructors}% \indextext{constructor!exception~handling|see{exception handling, constructors and destructors}}% \indextext{destructor!exception~handling|see{exception handling, constructors and destructors}} \pnum \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 section, called \defn{stack unwinding}. If a destructor directly invoked by stack unwinding exits with an exception, \tcode{std::terminate} is called~(\ref{except.terminate}). \enternote Consequently, destructors should generally catch exceptions and not let them propagate out of the destructor. \exitnote \pnum The destructor is invoked for each automatic object of class type constructed since the try block was entered. The automatic objects are destroyed in the reverse order of the completion of their construction. \pnum For an object of class type of any storage duration whose initialization or destruction is terminated by an exception, the destructor is invoked for each of the object's fully constructed subobjects, that is, for each subobject for which the principal constructor~(\ref{class.base.init}) has completed execution and the destructor has not yet begun execution, except that in the case of destruction, the variant members of a union-like class are not destroyed. The subobjects are destroyed in the reverse order of the completion of their construction. Such destruction is sequenced before entering a handler of the \grammarterm{function-try-block} of the constructor or destructor, if any. \pnum Similarly, if the non-delegating constructor for an object has completed execution and a delegating constructor for that object exits with an exception, the object's destructor is invoked. Such destruction is sequenced before entering a handler of the \grammarterm{function-try-block} of a delegating constructor for that object, if any. \pnum \enternote If the object was allocated by a \grammarterm{new-expression}~(\ref{expr.new}), the matching deallocation function~(\ref{basic.stc.dynamic.deallocation}), if any, is called to free the storage occupied by the object. \exitnote \rSec1[except.handle]{Handling an exception} \indextext{exception handling!handler|(}% \pnum The \grammarterm{exception-declaration} in a \term{handler} describes the type(s) of exceptions that can cause that \term{handler} to be entered. \indextext{exception handling!handler!incomplete type in}% \indextext{exception handling!handler!rvalue reference in}% \indextext{exception handling!handler!array in}% \indextext{exception handling!handler!pointer to function in}% The \grammarterm{exception-declaration} shall not denote an incomplete type, an abstract class type, or an rvalue reference type. The \grammarterm{exception-declaration} shall not denote a pointer or reference to an incomplete type, other than \tcode{void*}, \tcode{const} \tcode{void*}, \tcode{volatile} \tcode{void*}, or \tcode{const} \tcode{volatile} \tcode{void*}. \pnum A handler of type ``array of \tcode{T}'' or ``function returning \tcode{T}'' is adjusted to be of type ``pointer to \tcode{T}'' or ``pointer to function returning \tcode{T}'', respectively. \pnum \indextext{exception handling!handler!match|(}% A \term{handler} is a match for an exception object of type \tcode{E} if \begin{itemize} \item% The \term{handler} is of type \cv \tcode{T} or \cv \tcode{T\&} and \tcode{E} and \tcode{T} are the same type (ignoring the top-level \grammarterm{cv-qualifiers}), or \item% the \term{handler} is of type \cv \tcode{T} or \cv \tcode{T\&} and \tcode{T} is an unambiguous public base class of \tcode{E}, or \item% the \term{handler} is of type \cv \tcode{T} or \tcode{const T\&} where \tcode{T} is a pointer type and \tcode{E} is a pointer type that can be converted to \tcode{T} by either or both of \begin{itemize} \item% a standard pointer conversion~(\ref{conv.ptr}) not involving conversions to pointers to private or protected or ambiguous classes \item% a qualification conversion, or \end{itemize} \item the \term{handler} is of type \cv \tcode{T} or \tcode{const T\&} where \tcode{T} is a pointer or pointer to member type and \tcode{E} is \tcode{std::nullptr_t}. \end{itemize} \enternote A \grammarterm{throw-expression} whose operand is an integer literal with value zero does not match a handler of pointer or pointer to member type. \exitnote \enterexample \begin{codeblock} class Matherr { /* ... */ virtual void vf(); }; class Overflow: public Matherr { /* ... */ }; class Underflow: public Matherr { /* ... */ }; class Zerodivide: public Matherr { /* ... */ }; void f() { try { g(); } catch (Overflow oo) { // ... } catch (Matherr mm) { // ... } } \end{codeblock} Here, the \tcode{Overflow} handler will catch exceptions of type \tcode{Overflow} and the \tcode{Matherr} handler will catch exceptions of type \tcode{Matherr} and of all types publicly derived from \tcode{Matherr} including exceptions of type \tcode{Underflow} and \tcode{Zerodivide}. \exitexample \pnum The handlers for a try block are tried in order of appearance. That makes it possible to write handlers that can never be executed, for example by placing a handler for a derived class after a handler for a corresponding base class. \pnum A \tcode{...} in a handler's \grammarterm{exception-declaration} functions similarly to \tcode{...} in a function parameter declaration; it specifies a match for any exception. If present, a \tcode{...} handler shall be the last handler for its try block. \pnum If no match is found among the handlers for a try block, the search for a matching handler continues in a dynamically surrounding try block of the same thread. \pnum A handler is considered active when initialization is complete for the parameter (if any) of the catch clause. \enternote The stack will have been unwound at that point. \exitnote Also, an implicit handler is considered active when \tcode{std::terminate()} or \tcode{std::unexpected()} is entered due to a throw. A handler is no longer considered active when the catch clause exits or when \tcode{std::unexpected()} exits after being entered due to a throw. \pnum The exception with the most recently activated handler that is still active is called the \term{currently handled exception}. \pnum If no matching handler is found, the function \tcode{std::terminate()} is called; whether or not the stack is unwound before this call to \tcode{std::terminate()} is \impldef{stack unwinding before call to \tcode{std::terminate()}}~(\ref{except.terminate}). \pnum Referring to any non-static member or base class of an object in the handler for a \grammarterm{function-try-block} of a constructor or destructor for that object results in undefined behavior. \pnum The scope and lifetime of the parameters of a function or constructor extend into the handlers of a \grammarterm{function-try-block}. \pnum Exceptions thrown in destructors of objects with static storage duration or in constructors of namespace-scope objects with static storage duration are not caught by a \grammarterm{function-try-block} on \tcode{main()}. Exceptions thrown in destructors of objects with thread storage duration or in constructors of namespace-scope objects with thread storage duration are not caught by a \grammarterm{function-try-block} on the initial function of the thread. \pnum If a return statement appears in a handler of the \grammarterm{function-try-block} of a constructor, the program is ill-formed. \pnum The currently handled exception is rethrown if control reaches the end of a handler of the \grammarterm{function-try-block} of a constructor or destructor. Otherwise, a function returns when control reaches the end of a handler for the \grammarterm{function-try-block}~(\ref{stmt.return}). Flowing off the end of a \grammarterm{function-try-block} is equivalent to a \tcode{return} with no value; this results in undefined behavior in a value-returning function~(\ref{stmt.return}). \pnum The variable declared by the \grammarterm{exception-declaration}, of type \cv{} \tcode{T} or \cv{} \tcode{T\&}, is initialized from the exception object, of type \tcode{E}, as follows: \begin{itemize} \item if \tcode{T} is a base class of \tcode{E}, the variable is copy-initialized~(\ref{dcl.init}) from the corresponding base class subobject of the exception object; \item otherwise, the variable is copy-initialized~(\ref{dcl.init}) from the exception object. \end{itemize} The lifetime of the variable ends when the handler exits, after the destruction of any automatic objects initialized within the handler. \pnum When the handler declares an object, any changes to that object will not affect the exception object. When the handler declares a reference to an object, any changes to the referenced object are changes to the exception object and will have effect should that object be rethrown.% \indextext{exception handling!handler!match|)}% \indextext{exception handling!handler|)} \rSec1[except.spec]{Exception specifications}% \indextext{exception specification|(} \pnum \indextext{exception specification!non-throwing}% The \defn{exception specification} of a function is a (possibly empty) set of types, indicating that the function might exit via an exception that matches a handler of one of the types in the set; the (conceptual) set of all types is used to denote that the function might exit via an exception of arbitrary type. If the set is empty, the function is said to have a \defn{non-throwing exception specification}. The exception specification is either defined explicitly by using an \grammarterm{exception-specification} as a suffix of a function declaration's declarator~(\ref{dcl.fct}) or implicitly. \begin{bnf} \nontermdef{exception-specification}\br dynamic-exception-specification\br noexcept-specification \end{bnf} \begin{bnf} \nontermdef{dynamic-exception-specification}\br \terminal{throw (} type-id-list\opt \terminal{)} \end{bnf} \begin{bnf} \nontermdef{type-id-list}\br type-id \terminal{...}\opt\br type-id-list \terminal{,} type-id \terminal{...}\opt \end{bnf} \begin{bnf} \nontermdef{noexcept-specification}\br \terminal{noexcept} \terminal{(} constant-expression \terminal{)}\br \terminal{noexcept} \end{bnf} \indextext{exception specification!noexcept!constant expression and}% In a \grammarterm{noexcept-specification}, the \grammarterm{constant-expression}, if supplied, shall be a constant expression~(\ref{expr.const}) that is contextually converted to \tcode{bool} (Clause~\ref{conv}). A \tcode{(} token that follows \tcode{noexcept} is part of the \grammarterm{noexcept-specification} and does not commence an initializer~(\ref{dcl.init}). \pnum An \grammarterm{exception-specification} shall appear only on a function declarator for a function type, pointer to function type, reference to function type, or pointer to member function type that is the top-level type of a declaration or definition, or on such a type appearing as a parameter or return type in a function declarator. An \grammarterm{exception-specification} shall not appear in a typedef declaration or \grammarterm{alias-declaration}. \enterexample \begin{codeblock} void f() throw(int); // OK void (*fp)() throw (int); // OK void g(void pfa() throw(int)); // OK typedef int (*pf)() throw(int); // ill-formed \end{codeblock} \exitexample \indextext{exception specification!incomplete type and}% A type denoted in a \grammarterm{dynamic-exception-specification} shall not denote an incomplete type or an rvalue reference type. A type denoted in a \grammarterm{dynamic-exception-specification} shall not denote a pointer or reference to an incomplete type, other than ``pointer to \cv\ \tcode{void}''. A type \cv\ \tcode{T}, ``array of \tcode{T}'', or ``function returning \tcode{T}'' denoted in a \grammarterm{dynamic-exception-specification} is adjusted to type \tcode{T}, ``pointer to \tcode{T}'', or ``pointer to function returning \tcode{T}'', respectively. A \grammarterm{dynamic-exception-specification} denotes an exception specification that is the set of adjusted types specified thereby. \pnum The \grammarterm{exception-specification} \tcode{noexcept} or \tcode{noexcept(}\grammarterm{constant-expression}{}\tcode{)}, where the \grammarterm{constant-expression} yields \tcode{true}, denotes an exception specification that is the empty set. The \grammarterm{exception-specification} \tcode{noexcept(}\grammarterm{constant-expression}{}\tcode{)}, where the \grammarterm{constant-expression} yields \tcode{false}, or the absence of an \grammarterm{exception-specification} in a function declarator other than that for a destructor~(\ref{class.dtor}) or a deallocation function~(\ref{basic.stc.dynamic.deallocation}) denotes an exception specification that is the set of all types. \pnum \indextext{exception specification!compatible}% Two \grammarterm{exception-specification}{s} are \defnx{compatible}{compatible|see{exception specification, compatible}} if the sets of types they denote are the same. \pnum If any declaration of a function has an \grammarterm{exception-specification} that is not a \grammarterm{noexcept-specification} allowing all exceptions, all declarations, including the definition and any explicit specialization, of that function shall have a compatible \grammarterm{exception-specification}. If any declaration of a pointer to function, reference to function, or pointer to member function has an \grammarterm{exception-specification}, all occurrences of that declaration shall have a compatible \grammarterm{exception-specification}. If a declaration of a function has an implicit exception specification, other declarations of the function shall not specify an \grammarterm{exception-specification}. In an explicit instantiation an \grammarterm{exception-specification} may be specified, but is not required. If an \grammarterm{exception-specification} is specified in an explicit instantiation directive, it shall be compatible with the \grammarterm{exception-specification}{s} of other declarations of that function. A diagnostic is required only if the \grammarterm{exception-specification}{s} are not compatible within a single translation unit. \pnum \indextext{exception specification!virtual function and}% If a virtual function has an exception specification, all declarations, including the definition, of any function that overrides that virtual function in any derived class shall only allow exceptions that are allowed by the exception specification of the base class virtual function, unless the overriding function is defined as deleted. \enterexample \begin{codeblock} struct B { virtual void f() throw (int, double); virtual void g(); }; struct D: B { void f(); // ill-formed void g() throw (int); // OK }; \end{codeblock} The declaration of \tcode{D::f} is ill-formed because it allows all exceptions, whereas \tcode{B::f} allows only \tcode{int} and \tcode{double}. \exitexample A similar restriction applies to assignment to and initialization of pointers to functions, pointers to member functions, and references to functions: the target entity shall allow at least the exceptions allowed by the source value in the assignment or initialization. \enterexample \begin{codeblock} class A { /* ... */ }; void (*pf1)(); // no exception specification void (*pf2)() throw(A); void f() { pf1 = pf2; // OK: \tcode{pf1} is less restrictive pf2 = pf1; // error: \tcode{pf2} is more restrictive } \end{codeblock} \exitexample \pnum In such an assignment or initialization, \grammarterm{exception-specification}{s} on return types and parameter types shall be compatible. In other assignments or initializations, \grammarterm{exception-specification}{s} shall be compatible. \pnum An \grammarterm{exception-specification} can include the same type more than once and can include classes that are related by inheritance, even though doing so is redundant. \enternote An \grammarterm{exception-specification} can also include the class \tcode{std::bad_exception}~(\ref{bad.exception}). \exitnote \pnum \indextext{allowing an exception|see{exception specification, allowing an exception}}% A function is said to \defnx{allow an exception}{exception specification!allowing an exception} of type \tcode{E} if its exception specification contains a type \tcode{T} for which a handler of type \tcode{T} would be a match~(\ref{except.handle}) for an exception of type \tcode{E}. \indextext{allowing all exceptions|see{exception specification, allowing all exceptions}}% A function is said to \defnx{allow all exceptions}{exception specification!allowing all exceptions} if its exception specification is the set of all types. \pnum \indextext{exception handling!unexpected called@\tcode{unexpected()} called}% \indextext{\idxcode{unexpected()}!called}% Whenever an exception of type \tcode{E} is thrown and the search for a handler~(\ref{except.handle}) encounters the outermost block of a function with an exception specification that does not allow \tcode{E}, then, \begin{itemize} \item if the function definition has a \grammarterm{dynamic-exception-specification}, the function \tcode{std::unexpected()} is called~(\ref{except.unexpected}), \indextext{exception handling!terminate called@\tcode{terminate()} called}% \indextext{\idxcode{terminate()}!called}% \item otherwise, the function \tcode{std::terminate()} is called~(\ref{except.terminate}). \end{itemize} \enterexample \begin{codeblock} class X { }; class Y { }; class Z: public X { }; class W { }; void f() throw (X, Y) { int n = 0; if (n) throw X(); // OK if (n) throw Z(); // also OK throw W(); // will call \tcode{std::unexpected()} } \end{codeblock} \exitexample \enternote A function can have multiple declarations with different non-throwing \grammarterm{exception-specification}{s}; for this purpose, the one on the function definition is used. \exitnote \pnum An implementation shall not reject an expression merely because when executed it throws or might throw an exception that the containing function does not allow. \enterexample \begin{codeblock} extern void f() throw(X, Y); void g() throw(X) { f(); // OK } \end{codeblock} the call to \tcode{f} is well-formed even though when called, \tcode{f} might throw exception \tcode{Y} that \tcode{g} does not allow. \exitexample \pnum \enternote An exception specification is not considered part of a function's type; see~\ref{dcl.fct}. \exitnote \pnum A \defn{potential exception} of a given context is either a type that might be thrown as an exception or a pseudo-type, denoted by ``any'', that represents the situation where an exception of an arbitrary type might be thrown. A subexpression \tcode{e1} of an expression \tcode{e} is an \defn{immediate subexpression} if there is no subexpression \tcode{e2} of \tcode{e} such that \tcode{e1} is a subexpression of \tcode{e2}. \pnum The \defn{set of potential exceptions of a function, function pointer, or member function pointer} \tcode{f} is defined as follows: \begin{itemize} \item If the exception specification of \tcode{f} is the set of all types, the set consists of the pseudo-type ``any''. \item Otherwise, the set consists of every type in the exception specification of \tcode{f}. \end{itemize} \pnum The \defn{set of potential exceptions of an expression} \tcode{e} is empty if \tcode{e} is a core constant expression (\ref{expr.const}). Otherwise, it is the union of the sets of potential exceptions of the immediate subexpressions of \tcode{e}, including default argument expressions used in a function call, combined with a set \placeholder{S} defined by the form of \tcode{e}, as follows: \begin{itemize} \item If \tcode{e} is a function call (\ref{expr.call}): \begin{itemize} \item If its \grammarterm{postfix-expression} is a (possibly parenthesized) \grammarterm{id-expression}~(\ref{expr.prim.general}), class member access (\ref{expr.ref}), or pointer-to-member operation~(\ref{expr.mptr.oper}) whose \grammarterm{cast-expression} is an \grammarterm{id-expression}, \placeholder{S} is the set of potential exceptions of the entity selected by the contained \grammarterm{id-expression} (after overload resolution, if applicable). \item Otherwise, \placeholder{S} contains the pseudo-type ``any''. \end{itemize} \item If \tcode{e} implicitly invokes a function (such as an overloaded operator, an allocation function in a \grammarterm{new-expression}, or a destructor if \tcode{e} is a full-expression~(\ref{intro.execution})), \placeholder{S} is the set of potential exceptions of the function. \item if \tcode{e} is a \grammarterm{throw-expression}~(\ref{expr.throw}), \placeholder{S} consists of the type of the exception object that would be initialized by the operand, if present, or the pseudo-type ``any'' otherwise. \item if \tcode{e} is a \tcode{dynamic_cast} expression that casts to a reference type and requires a run-time check~(\ref{expr.dynamic.cast}), \placeholder{S} consists of the type \tcode{std::bad_cast}. \item if \tcode{e} is a \tcode{typeid} expression applied to a glvalue expression whose type is a polymorphic class type (\ref{expr.typeid}), \placeholder{S} consists of the type \tcode{std::bad_typeid}. \item if \tcode{e} is a \grammarterm{new-expression} with a non-constant \grammarterm{expression} in the \grammarterm{noptr-new-declarator}~(\ref{expr.new}), \placeholder{S} consists of the type \tcode{std::bad_array_new_length}. \end{itemize} \enterexample Given the following declarations \begin{codeblock} void f() throw(int); void g(); struct A { A(); }; struct B { B() noexcept; }; struct D() { D() throw (double); }; \end{codeblock} the set of potential exceptions for some sample expressions is: \begin{itemize} \item for \tcode{f()}, the set consists of \tcode{int}; \item for \tcode{g()}, the set consists of ``any''; \item for \tcode{new A}, the set consists of ``any''; \item for \tcode{B()}, the set is empty; \item for \tcode{new D}, the set consists of ``any'' and \tcode{double}. \end{itemize} \exitexample \pnum Given a member function \tcode{f} of some class \tcode{X}, where \tcode{f} is an inheriting constructor~(\ref{class.inhctor}) or an implicitly-declared special member function, the \defn{set of potential exceptions of the implicitly-declared member function} \tcode{f} consists of all the members from the following sets: \begin{itemize} \item if \tcode{f} is a constructor, \begin{itemize} \item the sets of potential exceptions of the constructor invocations \begin{itemize} \item for \tcode{X}'s non-variant non-static data members, \item for \tcode{X}'s direct base classes, and \item if \tcode{X} is non-abstract (\ref{class.abstract}), for \tcode{X}'s virtual base classes, \end{itemize} (including default argument expressions used in such invocations) as selected by overload resolution for the implicit definition of \tcode{f} (\ref{class.ctor}). \enternote Even though destructors for fully-constructed subobjects are invoked when an exception is thrown during the execution of a constructor (\ref{except.ctor}), their exception specifications do not contribute to the exception specification of the constructor, because an exception thrown from such a destructor could never escape the constructor (\ref{except.throw}, \ref{except.terminate}). \exitnote \item the sets of potential exceptions of the initialization of non-static data members from \grammarterm{brace-or-equal-initializer}{s} that are not ignored (\ref{class.base.init}); \end{itemize} \item if \tcode{f} is an assignment operator, the sets of potential exceptions of the assignment operator invocations for \tcode{X}'s non-variant non-static data members and for \tcode{X}'s direct base classes (including default argument expressions used in such invocations), as selected by overload resolution for the implicit definition of \tcode{f} (\ref{class.copy}); \item if \tcode{f} is a destructor, the sets of potential exceptions of the destructor invocations for \tcode{X}'s non-variant non-static data members and for \tcode{X}'s virtual and direct base classes. \end{itemize} \pnum An inheriting constructor~(\ref{class.inhctor}) and an implicitly-declared special member function (Clause~\ref{special}) are considered to have an implicit exception specification, as follows, where \placeholder{S} is the set of potential exceptions of the implicitly-declared member function: \begin{itemize} \item if \placeholder{S} contains the pseudo-type ``any'', the implicit exception specification is the set of all types; \item otherwise, the implicit exception specification contains all the types in \placeholder{S}. \end{itemize} \enternote An instantiation of an inheriting constructor template has an implied exception specification as if it were a non-template inheriting constructor.\exitnote \enterexample \begin{codeblock} struct A { A(int = (A(5), 0)) noexcept; A(const A&) throw(); A(A&&) throw(); ~A() throw(X); }; struct B { B() throw(); B(const B&) = default; // exception specification contains no types B(B&&, int = (throw Y(), 0)) noexcept; ~B() throw(Y); }; int n = 7; struct D : public A, public B { int * p = new (std::nothrow) int[n]; // exception specification of \tcode{D::D()} contains \tcode{X} and \tcode{std::bad_array_new_length} // exception specification of \tcode{D::D(const D\&)} contains no types // exception specification of \tcode{D::D(D\&\&)} contains \tcode{Y} // exception specification of \tcode{D::\~D()} contains \tcode{X} and \tcode{Y} }; \end{codeblock} Furthermore, if \tcode{A::\~{}A()} or \tcode{B::\~{}B()} were virtual, \tcode{D::\~{}D()} would not be as restrictive as that of \tcode{A::\~{}A}, and the program would be ill-formed since a function that overrides a virtual function from a base class shall have an \grammarterm{exception-specification} at least as restrictive as that in the base class. \exitexample \pnum A deallocation function~(\ref{basic.stc.dynamic.deallocation}) with no explicit \grammarterm{exception-specification} has an exception specification that is the empty set. \pnum An \grammarterm{exception-specification} is considered to be \term{needed} when: \begin{itemize} \item in an expression, the function is the unique lookup result or the selected member of a set of overloaded functions~(\ref{basic.lookup}, \ref{over.match}, \ref{over.over}); \item the function is odr-used~(\ref{basic.def.odr}) or, if it appears in an unevaluated operand, would be odr-used if the expression were potentially-evaluated; \item the \grammarterm{exception-specification} is compared to that of another declaration (e.g., an explicit specialization or an overriding virtual function); \item the function is defined; or \item the \grammarterm{exception-specification} is needed for a defaulted special member function that calls the function. \enternote A defaulted declaration does not require the \grammarterm{exception-specification} of a base member function to be evaluated until the implicit \grammarterm{exception-specification} of the derived function is needed, but an explicit \grammarterm{exception-specification} needs the implicit \grammarterm{exception-specification} to compare against. \exitnote \end{itemize} The \grammarterm{exception-specification} of a defaulted special member function is evaluated as described above only when needed; similarly, the \grammarterm{exception-specification} of a specialization of a function template or member function of a class template is instantiated only when needed. \pnum In a \grammarterm{dynamic-exception-specification}, a \grammarterm{type-id} followed by an ellipsis is a pack expansion~(\ref{temp.variadic}). \pnum \enternote The use of \grammarterm{dynamic-exception-specification}{s} is deprecated (see Annex~\ref{depr}). \exitnote% \indextext{exception specification|)} \rSec1[except.special]{Special functions} \pnum The functions \tcode{std::terminate()}~(\ref{except.terminate}) and \tcode{std::unexpected()}~(\ref{except.unexpected}) are used by the exception handling mechanism for coping with errors related to the exception handling mechanism itself. The function \tcode{std::current_exception()}~(\ref{propagation}) and the class \tcode{std::nested_exception}~(\ref{except.nested}) can be used by a program to capture the currently handled exception. \rSec2[except.terminate]{The \tcode{std::terminate()} function} \pnum \indextext{\idxcode{terminate()}}% In some situations exception handling must be abandoned for less subtle error handling techniques. \enternote These situations are: \indextext{\idxcode{terminate()}!called}% \begin{itemize} \item% when the exception handling mechanism, after completing the initialization of the exception object but before activation of a handler for the exception~(\ref{except.throw}), calls a function that exits via an exception, or \item% when the exception handling mechanism cannot find a handler for a thrown exception~(\ref{except.handle}), or \item when the search for a handler~(\ref{except.handle}) encounters the outermost block of a function with a \grammarterm{noexcept-specification} that does not allow the exception~(\ref{except.spec}), or \item% when the destruction of an object during stack unwinding~(\ref{except.ctor}) terminates by throwing an exception, or \item% when initialization of a non-local variable with static or thread storage duration~(\ref{basic.start.init}) exits via an exception, or \item% when destruction of an object with static or thread storage duration exits via an exception~(\ref{basic.start.term}), or \item% when execution of a function registered with \tcode{std::atexit} or \tcode{std::at_quick_exit} exits via an exception~(\ref{support.start.term}), or \item% when a \grammarterm{throw-expression}~(\ref{expr.throw}) with no operand attempts to rethrow an exception and no exception is being handled~(\ref{except.throw}), or \item% when \tcode{std::unexpected} exits via an exception of a type that is not allowed by the previously violated exception specification, and \tcode{std::bad_exception} is not included in that exception specification~(\ref{except.unexpected}), or \item% when the implementation's default unexpected exception handler is called~(\ref{unexpected.handler}), or \item% when the function \tcode{std::nested_exception::rethrow_nested} is called for an object that has captured no exception~(\ref{except.nested}), or \item% when execution of the initial function of a thread exits via an exception~(\ref{thread.thread.constr}), or \item% when the destructor or the copy assignment operator is invoked on an object of type \tcode{std::thread} that refers to a joinable thread (\ref{thread.thread.destr},~\ref{thread.thread.assign}). \end{itemize} \exitnote \pnum \indextext{\idxcode{terminate()}}% In such cases, \tcode{std::terminate()} is called~(\ref{exception.terminate}). In the situation where no matching handler is found, it is \impldef{stack unwinding before call to \tcode{std::terminate()}} whether or not the stack is unwound before \tcode{std::terminate()} is called. In the situation where the search for a handler~(\ref{except.handle}) encounters the outermost block of a function with a \grammarterm{noexcept-specification} that does not allow the exception~(\ref{except.spec}), it is \impldef{whether stack is unwound before calling \tcode{std::terminate()} when a \tcode{noexcept} specification is violated} whether the stack is unwound, unwound partially, or not unwound at all before \tcode{std::terminate()} is called. In all other situations, the stack shall not be unwound before \tcode{std::terminate()} is called. An implementation is not permitted to finish stack unwinding prematurely based on a determination that the unwind process will eventually cause a call to \tcode{std::terminate()}. \rSec2[except.unexpected]{The \tcode{std::unexpected()} function} \pnum \indextext{\idxcode{unexpected()}}% If a function with a \grammarterm{dynamic-exception-specification} exits via an exception of a type that is not allowed by its exception specification, the function \tcode{std::unexpected()} is called~(\ref{exception.unexpected}) immediately after completing the stack unwinding for the former function. \pnum \enternote By default, \tcode{std::unexpected()} calls \tcode{std::terminate()}, but a program can install its own handler function~(\ref{set.unexpected}). In either case, the constraints in the following paragraph apply. \exitnote \pnum The \tcode{std::unexpected()} function shall not return, but it can throw (or rethrow) an exception. If it throws a new exception which is allowed by the exception specification which previously was violated, then the search for another handler will continue at the call of the function whose exception specification was violated. If it exits via an exception of a type that the \grammarterm{dynamic-exception-specification} does not allow, then the following happens: \indextext{\idxcode{bad_exception}}% If the \grammarterm{dynamic-exception-specification} does not include the class \tcode{std::bad_exception}~(\ref{bad.exception}) then the function \tcode{std::terminate()} is called, otherwise the thrown exception is replaced by an implementation-defined object of type \tcode{std::bad_exception} and the search for another handler will continue at the call of the function whose \grammarterm{dynamic-exception-specification} was violated. \pnum \enternote Thus, a \grammarterm{dynamic-exception-specification} guarantees that a function exits only via an exception of one of the listed types. If the \grammarterm{dynamic-exception-specification} includes the type \tcode{std::bad_exception} then any exception type not on the list may be replaced by \tcode{std\-::\-bad_ex\-cep\-tion} within the function \tcode{std::unexpected()}. \exitnote \rSec2[except.uncaught]{The \tcode{std::uncaught_exceptions()} function}% \indexlibrary{\idxcode{uncaught_exceptions}} \pnum An exception is considered uncaught after completing the initialization of the exception object~(\ref{except.throw}) until completing the activation of a handler for the exception~(\ref{except.handle}). This includes stack unwinding. If the exception is rethrown~(\ref{expr.throw}), it is considered uncaught from the point of rethrow until the rethrown exception is caught again. The function \tcode{std::uncaught_exceptions()}~(\ref{uncaught.exceptions}) returns the number of uncaught exceptions.% \indextext{exception handling|)}