diff --git a/source/basic.tex b/source/basic.tex index ca9e4df559..9274dcd517 100644 --- a/source/basic.tex +++ b/source/basic.tex @@ -6760,7 +6760,14 @@ \indextext{atomic!operation|)}% \indextext{threads!multiple|)} -\rSec2[except.throw]{Throwing an exception}% +\rSec2[except.flow]{Exceptional control flow} + +\rSec3[except.general]{General} +\pnum +In this Clause, ``before'' and ``after'' refer to the +``sequenced before'' relation\iref{intro.execution}. + +\rSec3[except.throw]{Throwing an exception}% \indextext{exception handling!throwing}% \indextext{throwing|see{exception handling, throwing}} @@ -6951,7 +6958,7 @@ \tcode{std::terminate} is invoked. \end{note} -\rSec2[except.ctor]{Stack unwinding}% +\rSec3[except.ctor]{Stack unwinding}% \indextext{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}} @@ -7066,6 +7073,260 @@ if any, is called to free the storage occupied by the object. \end{note} +\rSec3[except.handle]{Handling an exception} +\indextext{exception handling!handler|(}% + +\pnum +The +\grammarterm{exception-declaration} +in a +\grammarterm{handler} +describes the type(s) of exceptions that can cause +that +\grammarterm{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 ``pointer to \cv{}~\keyword{void}''. + +\pnum +A handler of type +\indextext{array!handler of type}% +``array of \tcode{T}'' or +\indextext{function!handler of type}% +function type \tcode{T} +is adjusted to be of type +``pointer to \tcode{T}''. + +\pnum +\indextext{exception handling!handler!match|(}% +A +\grammarterm{handler} +is a match for +an exception object +of type +\tcode{E} +if +\begin{itemize} +\item% +The \grammarterm{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-qualifier}{s}), or +\item% +the \grammarterm{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 \grammarterm{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 a pointer or pointer-to-member type +that can be converted to \tcode{T} by one or more of +\begin{itemize} + +\item% +a standard pointer conversion\iref{conv.ptr} not involving conversions +to pointers to private or protected or ambiguous classes +\item% +a function pointer conversion\iref{conv.fctptr} +\item% +a qualification conversion\iref{conv.qual}, or + +\end{itemize} + +\item +the \grammarterm{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} + +\begin{note} +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. +A handler of reference to array or function type +is never a match for any exception object\iref{expr.throw}. +\end{note} + +\begin{example} +\begin{codeblock} +class Matherr { @\commentellip@ virtual void vf(); }; +class Overflow: public Matherr { @\commentellip@ }; +class Underflow: public Matherr { @\commentellip@ }; +class Zerodivide: public Matherr { @\commentellip@ }; + +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}. +\end{example} + +\pnum +The handlers for a try block are tried in order of appearance. +\begin{note} +This makes it possible to write handlers that can never be +executed, for example by placing a handler for a final derived class after +a handler for a corresponding unambiguous public base class. +\end{note} + +\pnum +A +\tcode{...} +in a handler's +\grammarterm{exception-declaration} +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 +\indextext{exception handling!terminate called@\tcode{terminate} called}% +\indextext{\idxcode{terminate}!called}% +If the search for a handler +encounters the outermost block of a function with a +non-throwing exception specification, +the function \tcode{std::terminate}\iref{except.terminate} is invoked. +\begin{note} +An implementation is not permitted to reject an expression merely because, when +executed, it throws or might +throw an exception from a function with a non-throwing exception specification. +\end{note} +\begin{example} +\begin{codeblock} +extern void f(); // potentially-throwing + +void g() noexcept { + f(); // valid, even if \tcode{f} throws + throw 42; // valid, effectively a call to \tcode{std::terminate} +} +\end{codeblock} +The call to +\tcode{f} +is well-formed despite the possibility for it to throw an exception. +\end{example} + +\pnum +If no matching handler is found, +the function \tcode{std::terminate} is invoked; +whether or not the stack is unwound before this invocation of +\tcode{std::terminate} is +\impldef{whether stack is unwound before invoking the function \tcode{std::terminate} +when no matching handler is found}\iref{except.terminate} + +\pnum +A handler is considered \defnx{active}{exception handling!handler!active} when +initialization is complete for the parameter (if any) of the catch clause. +\begin{note} +The stack will have been unwound at that point. +\end{note} +Also, an implicit handler is considered active when +the function \tcode{std::terminate} +is entered due to a throw. A handler is no longer considered active when the +catch clause exits. + +\pnum +\indextext{currently handled exception|see{exception handling, currently handled exception}}% +The exception with the most recently activated handler that is +still active is called the +\defnx{currently handled exception}{exception handling!currently handled exception}. + +\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 +Exceptions thrown in destructors of objects with static storage duration or in +constructors of objects associated with non-block variables with static storage duration are not caught by a +\grammarterm{function-try-block} +on +the \tcode{main} function\iref{basic.start.main}. +Exceptions thrown in destructors of objects with thread storage duration or in constructors of objects associated with non-block variables with thread storage duration are not caught by a +\grammarterm{function-try-block} +on the initial function of the thread. + +\pnum +If a \keyword{return} statement\iref{stmt.return} 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, flowing off the end of +the \grammarterm{compound-statement} +of a \grammarterm{handler} +of a \grammarterm{function-try-block} +is equivalent to flowing off the end of +the \grammarterm{compound-statement} +of that function (see \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\iref{dcl.init} +from an lvalue of type \tcode{T} designating the corresponding base class subobject +of the exception object; +\item otherwise, the variable is copy-initialized\iref{dcl.init} +from an lvalue of type \tcode{E} designating the exception object. +\end{itemize} + +The lifetime of the variable ends +when the handler exits, after the +destruction of any objects with automatic storage duration 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|)} + \rSec2[basic.start]{Start and termination} \rSec3[basic.start.main]{\tcode{main} function} @@ -7603,9 +7864,9 @@ \pnum \indextext{\idxcode{terminate}}% In the situation where no matching handler is found, it is -\impldef{stack unwinding before invocation of \tcode{std::terminate}} -whether or not the stack is unwound -before \tcode{std::terminate} is invoked. +\impldef{whether stack is unwound before invoking the function \tcode{std::terminate} +when no matching handler is found} +whether or not the stack is unwound before \tcode{std::terminate} is invoked. In the situation where the search for a handler\iref{except.handle} encounters the outermost block of a function with a non-throwing exception specification\iref{except.spec}, it is diff --git a/source/compatibility.tex b/source/compatibility.tex index 93baac8554..9bc289e8c1 100644 --- a/source/compatibility.tex +++ b/source/compatibility.tex @@ -951,6 +951,25 @@ \end{codeblock} \end{example} +\diffref{except.spec} +\change +Remove \tcode{throw()} exception specification. +\rationale +Removal of obsolete feature that has been replaced by \keyword{noexcept}. +\effect +A valid \CppXVII{} function declaration, member function declaration, function +pointer declaration, or function reference declaration that uses \tcode{throw()} +for its exception specification will be rejected as ill-formed in this +revision of \Cpp{}. It should simply be replaced with \keyword{noexcept} for no +change of meaning since \CppXVII{}. +\begin{note} +There is no way to write a function declaration +that is non-throwing in this revision of \Cpp{} +and is also non-throwing in \CppIII{} +except by using the preprocessor to generate +a different token sequence in each case. +\end{note} + \rSec2[diff.cpp17.class]{\ref{class}: classes} \diffref{class.ctor,class.conv.fct} @@ -1134,27 +1153,6 @@ \end{codeblock} \end{example} -\rSec2[diff.cpp17.except]{\ref{except}: exception handling} - -\diffref{except.spec} -\change -Remove \tcode{throw()} exception specification. -\rationale -Removal of obsolete feature that has been replaced by \keyword{noexcept}. -\effect -A valid \CppXVII{} function declaration, member function declaration, function -pointer declaration, or function reference declaration that uses \tcode{throw()} -for its exception specification will be rejected as ill-formed in this -revision of \Cpp{}. It should simply be replaced with \keyword{noexcept} for no -change of meaning since \CppXVII{}. -\begin{note} -There is no way to write a function declaration -that is non-throwing in this revision of \Cpp{} -and is also non-throwing in \CppIII{} -except by using the preprocessor to generate -a different token sequence in each case. -\end{note} - \rSec2[diff.cpp17.library]{\ref{library}: library introduction} \diffref{headers} @@ -1560,6 +1558,27 @@ \end{codeblock} \end{example} +\diffref{except.spec} +\change +Remove dynamic exception specifications. +\rationale +Dynamic exception specifications were a deprecated feature +that was complex and brittle in use. +They interacted badly with the type system, +which became a more significant issue in this revision of \Cpp{} +where (non-dynamic) exception specifications are part of the function type. +\effect +A valid \CppXIV{} function declaration, +member function declaration, +function pointer declaration, +or function reference declaration, +if it has a potentially throwing dynamic exception specification, +is rejected as ill-formed in this revision of \Cpp{}. +Violating a non-throwing dynamic exception specification +calls \tcode{terminate} rather than \tcode{unexpected}, +and it is unspecified whether stack unwinding is performed +prior to such a call. + \rSec2[diff.cpp14.class]{\ref{class}: classes} \diffref{class.inhctor.init} @@ -1613,29 +1632,6 @@ \end{codeblock} \end{example} -\rSec2[diff.cpp14.except]{\ref{except}: exception handling} - -\diffref{except.spec} -\change -Remove dynamic exception specifications. -\rationale -Dynamic exception specifications were a deprecated feature -that was complex and brittle in use. -They interacted badly with the type system, -which became a more significant issue in this revision of \Cpp{} -where (non-dynamic) exception specifications are part of the function type. -\effect -A valid \CppXIV{} function declaration, -member function declaration, -function pointer declaration, -or function reference declaration, -if it has a potentially throwing dynamic exception specification, -is rejected as ill-formed in this revision of \Cpp{}. -Violating a non-throwing dynamic exception specification -calls \tcode{terminate} rather than \tcode{unexpected}, -and it is unspecified whether stack unwinding is performed -prior to such a call. - \rSec2[diff.cpp14.library]{\ref{library}: library introduction} \diffref{headers} diff --git a/source/exceptions.tex b/source/exceptions.tex index c6a6d3bb71..459445c51d 100644 --- a/source/exceptions.tex +++ b/source/exceptions.tex @@ -7,436 +7,5 @@ \indextext{exception object|see{exception handling, exception object}}% \indextext{object!exception|see{exception handling, exception object}} -\rSec1[except.pre]{Preamble} -\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 - \keyword{try} compound-statement handler-seq -\end{bnf} - -\indextext{\idxcode{try}}% -% -\begin{bnf} -\nontermdef{function-try-block}\br - \keyword{try} \opt{ctor-initializer} compound-statement handler-seq -\end{bnf} - -\begin{bnf} -\nontermdef{handler-seq}\br - handler \opt{handler-seq} -\end{bnf} - -\indextext{\idxcode{catch}}% -% -\begin{bnf} -\nontermdef{handler}\br - \keyword{catch} \terminal{(} exception-declaration \terminal{)} compound-statement -\end{bnf} - -\begin{bnf} -\nontermdef{exception-declaration}\br - \opt{attribute-specifier-seq} type-specifier-seq declarator\br - \opt{attribute-specifier-seq} type-specifier-seq \opt{abstract-declarator}\br - \terminal{...} -\end{bnf} - -The optional \grammarterm{attribute-specifier-seq} in an \grammarterm{exception-declaration} -appertains to the parameter of the catch clause\iref{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}\iref{stmt.pre}. -\begin{note} -Within this Clause -``try block'' is taken to mean both \grammarterm{try-block} and -\grammarterm{function-try-block}. -\end{note} - -\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}% -The \grammarterm{compound-statement} of a try block or of a handler is a -control-flow-limited statement\iref{stmt.label}. -\begin{example} -\begin{codeblock} -void f() { - goto l1; // error - goto l2; // error - try { - goto l1; // OK - goto l2; // error - l1: ; - } catch (...) { - l2: ; - goto l1; // error - goto l2; // OK - } -} - -\end{codeblock} -\end{example} -\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 -\keyword{goto}, -\keyword{break}, -\keyword{return}, -or -\keyword{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. -\begin{example} -\begin{codeblock} -lab: try { - T1 t1; - try { - T2 t2; - if (@\grammarterm{condition}@) - goto lab; - } catch(...) { @\tcode{/* handler 2 */}@ } - } catch(...) { @\tcode{/* 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 thrown while destroying -\tcode{t2} -will result in executing -\tcode{handler 2}; -any exception thrown while destroying -\tcode{t1} -will result in executing -\tcode{handler 1}. -\end{example} - -\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. -\begin{example} -\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} -\end{example} - -\pnum -In this Clause, ``before'' and ``after'' refer to the -``sequenced before'' relation\iref{intro.execution}. - -\rSec1[except.handle]{Handling an exception} -\indextext{exception handling!handler|(}% - -\pnum -The -\grammarterm{exception-declaration} -in a -\grammarterm{handler} -describes the type(s) of exceptions that can cause -that -\grammarterm{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 ``pointer to \cv{}~\keyword{void}''. - -\pnum -A handler of type -\indextext{array!handler of type}% -``array of \tcode{T}'' or -\indextext{function!handler of type}% -function type \tcode{T} -is adjusted to be of type -``pointer to \tcode{T}''. - -\pnum -\indextext{exception handling!handler!match|(}% -A -\grammarterm{handler} -is a match for -an exception object -of type -\tcode{E} -if -\begin{itemize} -\item% -The \grammarterm{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-qualifier}{s}), or -\item% -the \grammarterm{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 \grammarterm{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 a pointer or pointer-to-member type -that can be converted to \tcode{T} by one or more of -\begin{itemize} - -\item% -a standard pointer conversion\iref{conv.ptr} not involving conversions -to pointers to private or protected or ambiguous classes -\item% -a function pointer conversion\iref{conv.fctptr} -\item% -a qualification conversion\iref{conv.qual}, or - -\end{itemize} - -\item -the \grammarterm{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} - -\begin{note} -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. -A handler of reference to array or function type -is never a match for any exception object\iref{expr.throw}. -\end{note} - -\begin{example} -\begin{codeblock} -class Matherr { @\commentellip@ virtual void vf(); }; -class Overflow: public Matherr { @\commentellip@ }; -class Underflow: public Matherr { @\commentellip@ }; -class Zerodivide: public Matherr { @\commentellip@ }; - -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}. -\end{example} - -\pnum -The handlers for a try block are tried in order of appearance. -\begin{note} -This makes it possible to write handlers that can never be -executed, for example by placing a handler for a final derived class after -a handler for a corresponding unambiguous public base class. -\end{note} - -\pnum -A -\tcode{...} -in a handler's -\grammarterm{exception-declaration} -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 -\indextext{exception handling!terminate called@\tcode{terminate} called}% -\indextext{\idxcode{terminate}!called}% -If the search for a handler -encounters the outermost block of a function with a -non-throwing exception specification, -the function \tcode{std::terminate}\iref{except.terminate} is invoked. -\begin{note} -An implementation is not permitted to reject an expression merely because, when -executed, it throws or might -throw an exception from a function with a non-throwing exception specification. -\end{note} -\begin{example} -\begin{codeblock} -extern void f(); // potentially-throwing - -void g() noexcept { - f(); // valid, even if \tcode{f} throws - throw 42; // valid, effectively a call to \tcode{std::terminate} -} -\end{codeblock} -The call to -\tcode{f} -is well-formed despite the possibility for it to throw an exception. -\end{example} - -\pnum -If no matching handler is found, -the function \tcode{std::terminate} is invoked; -whether or not the stack is unwound before this invocation of -\tcode{std::terminate} -is \impldef{stack unwinding before invocation of -\tcode{std::terminate}}\iref{except.terminate}. - -\pnum -A handler is considered \defnx{active}{exception handling!handler!active} when -initialization is complete for the parameter (if any) of the catch clause. -\begin{note} -The stack will have been unwound at that point. -\end{note} -Also, an implicit handler is considered active when -the function \tcode{std::terminate} -is entered due to a throw. A handler is no longer considered active when the -catch clause exits. - -\pnum -\indextext{currently handled exception|see{exception handling, currently handled exception}}% -The exception with the most recently activated handler that is -still active is called the -\defnx{currently handled exception}{exception handling!currently handled exception}. - -\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 -Exceptions thrown in destructors of objects with static storage duration or in -constructors of objects associated with non-block variables with static storage duration are not caught by a -\grammarterm{function-try-block} -on -the \tcode{main} function\iref{basic.start.main}. -Exceptions thrown in destructors of objects with thread storage duration or in constructors of objects associated with non-block variables with thread storage duration are not caught by a -\grammarterm{function-try-block} -on the initial function of the thread. - -\pnum -If a \keyword{return} statement\iref{stmt.return} 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, flowing off the end of -the \grammarterm{compound-statement} -of a \grammarterm{handler} -of a \grammarterm{function-try-block} -is equivalent to flowing off the end of -the \grammarterm{compound-statement} -of that function (see \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\iref{dcl.init} -from an lvalue of type \tcode{T} designating the corresponding base class subobject -of the exception object; -\item otherwise, the variable is copy-initialized\iref{dcl.init} -from an lvalue of type \tcode{E} designating the exception object. -\end{itemize} - -The lifetime of the variable ends -when the handler exits, after the -destruction of any objects with automatic storage duration 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|)} \indextext{exception handling|)} diff --git a/source/expressions.tex b/source/expressions.tex index 54e40c91a9..6d74239ecb 100644 --- a/source/expressions.tex +++ b/source/expressions.tex @@ -5643,7 +5643,7 @@ \indextext{\idxcode{bad_alloc}}% \indexlibraryglobal{bad_alloc}% \tcode{std::bad_alloc} -exception\iref{basic.stc.dynamic.allocation,except,bad.alloc}; +exception\iref{basic.stc.dynamic.allocation,except.throw,bad.alloc}; it returns a non-null pointer otherwise. If the allocation function has a non-throwing exception specification, it returns null to indicate failure to allocate storage diff --git a/source/lib-intro.tex b/source/lib-intro.tex index d608fa2067..55581f1d7f 100644 --- a/source/lib-intro.tex +++ b/source/lib-intro.tex @@ -53,7 +53,7 @@ The language support library\iref{support} provides components that are required by certain parts of the \Cpp{} language, such as memory allocation\iref{expr.new,expr.delete} and -exception processing\iref{except}. +exception processing\iref{support.exception.general}. \pnum The concepts library\iref{concepts} describes library components that \Cpp{} diff --git a/source/statements.tex b/source/statements.tex index 9940ee28de..4fd6aee9d3 100644 --- a/source/statements.tex +++ b/source/statements.tex @@ -1033,6 +1033,181 @@ \indextext{label}% label\iref{stmt.label} located in the current function. +\rSec1[except.pre]{\keyword{try} blocks} + +\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 + \keyword{try} compound-statement handler-seq +\end{bnf} + +\indextext{\idxcode{try}}% +% +\begin{bnf} +\nontermdef{function-try-block}\br + \keyword{try} \opt{ctor-initializer} compound-statement handler-seq +\end{bnf} + +\begin{bnf} +\nontermdef{handler-seq}\br + handler \opt{handler-seq} +\end{bnf} + +\indextext{\idxcode{catch}}% +% +\begin{bnf} +\nontermdef{handler}\br + \keyword{catch} \terminal{(} exception-declaration \terminal{)} compound-statement +\end{bnf} + +\begin{bnf} +\nontermdef{exception-declaration}\br + \opt{attribute-specifier-seq} type-specifier-seq declarator\br + \opt{attribute-specifier-seq} type-specifier-seq \opt{abstract-declarator}\br + \terminal{...} +\end{bnf} + +The optional \grammarterm{attribute-specifier-seq} in an \grammarterm{exception-declaration} +appertains to the parameter of the catch clause\iref{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}\iref{stmt.pre}. +\begin{note} +Within this Clause +``try block'' is taken to mean both \grammarterm{try-block} and +\grammarterm{function-try-block}. +\end{note} + +\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}% +The \grammarterm{compound-statement} of a try block or of a handler is a +control-flow-limited statement\iref{stmt.label}. +\begin{example} +\begin{codeblock} +void f() { + goto l1; // error + goto l2; // error + try { + goto l1; // OK + goto l2; // error + l1: ; + } catch (...) { + l2: ; + goto l1; // error + goto l2; // OK + } +} + +\end{codeblock} +\end{example} +\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 +\keyword{goto}, +\keyword{break}, +\keyword{return}, +or +\keyword{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. +\begin{example} +\begin{codeblock} +lab: try { + T1 t1; + try { + T2 t2; + if (@\grammarterm{condition}@) + goto lab; + } catch(...) { @\tcode{/* handler 2 */}@ } + } catch(...) { @\tcode{/* 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 thrown while destroying +\tcode{t2} +will result in executing +\tcode{handler 2}; +any exception thrown while destroying +\tcode{t1} +will result in executing +\tcode{handler 1}. +\end{example} + +\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. +\begin{example} +\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} +\end{example} + \rSec1[stmt.dcl]{Declaration statement}% \indextext{statement!declaration} diff --git a/source/std.tex b/source/std.tex index fea8f0a37c..3a5132f9f8 100644 --- a/source/std.tex +++ b/source/std.tex @@ -120,7 +120,6 @@ \include{classes} \include{overloading} \include{templates} -\include{exceptions} \include{preprocessor} \include{lib-intro} \include{support} diff --git a/source/xrefdelta.tex b/source/xrefdelta.tex index 38e3895f08..688ec44f56 100644 --- a/source/xrefdelta.tex +++ b/source/xrefdelta.tex @@ -74,8 +74,12 @@ \removedxref{type.index.hash} % Dissolving [except] +\removedxref{diff.cpp14.except} +\removedxref{diff.cpp17.except} +\removedxref{except} \removedxref{except.special} \removedxref{except.special.general} +\removedxref{gram.except} %%% Renamed sections. %%% Examples: