|
6760 | 6760 | \indextext{atomic!operation|)}%
|
6761 | 6761 | \indextext{threads!multiple|)}
|
6762 | 6762 |
|
6763 |
| -\rSec2[except.throw]{Throwing an exception}% |
| 6763 | +\rSec2[except.flow]{Exceptional control flow} |
| 6764 | + |
| 6765 | +\rSec3[except.general]{General} |
| 6766 | +\pnum |
| 6767 | +In this Clause, ``before'' and ``after'' refer to the |
| 6768 | +``sequenced before'' relation\iref{intro.execution}. |
| 6769 | + |
| 6770 | +\rSec3[except.throw]{Throwing an exception}% |
6764 | 6771 | \indextext{exception handling!throwing}%
|
6765 | 6772 | \indextext{throwing|see{exception handling, throwing}}
|
6766 | 6773 |
|
|
6951 | 6958 | \tcode{std::terminate} is invoked.
|
6952 | 6959 | \end{note}
|
6953 | 6960 |
|
6954 |
| -\rSec2[except.ctor]{Stack unwinding}% |
| 6961 | +\rSec3[except.ctor]{Stack unwinding}% |
6955 | 6962 | \indextext{exception handling!constructors and destructors}%
|
6956 | 6963 | \indextext{constructor!exception handling|see{exception handling, constructors and destructors}}%
|
6957 | 6964 | \indextext{destructor!exception handling|see{exception handling, constructors and destructors}}
|
|
7066 | 7073 | if any, is called to free the storage occupied by the object.
|
7067 | 7074 | \end{note}
|
7068 | 7075 |
|
| 7076 | +\rSec3[except.handle]{Handling an exception} |
| 7077 | +\indextext{exception handling!handler|(}% |
| 7078 | + |
| 7079 | +\pnum |
| 7080 | +The |
| 7081 | +\grammarterm{exception-declaration} |
| 7082 | +in a |
| 7083 | +\grammarterm{handler} |
| 7084 | +describes the type(s) of exceptions that can cause |
| 7085 | +that |
| 7086 | +\grammarterm{handler} |
| 7087 | +to be entered. |
| 7088 | +\indextext{exception handling!handler!incomplete type in}% |
| 7089 | +\indextext{exception handling!handler!rvalue reference in}% |
| 7090 | +\indextext{exception handling!handler!array in}% |
| 7091 | +\indextext{exception handling!handler!pointer to function in}% |
| 7092 | +The |
| 7093 | +\grammarterm{exception-declaration} |
| 7094 | +shall not denote an incomplete type, an abstract class type, or an rvalue reference type. |
| 7095 | +The |
| 7096 | +\grammarterm{exception-declaration} |
| 7097 | +shall not denote a pointer or reference to an |
| 7098 | +incomplete type, other than ``pointer to \cv{}~\keyword{void}''. |
| 7099 | + |
| 7100 | +\pnum |
| 7101 | +A handler of type |
| 7102 | +\indextext{array!handler of type}% |
| 7103 | +``array of \tcode{T}'' or |
| 7104 | +\indextext{function!handler of type}% |
| 7105 | +function type \tcode{T} |
| 7106 | +is adjusted to be of type |
| 7107 | +``pointer to \tcode{T}''. |
| 7108 | + |
| 7109 | +\pnum |
| 7110 | +\indextext{exception handling!handler!match|(}% |
| 7111 | +A |
| 7112 | +\grammarterm{handler} |
| 7113 | +is a match for |
| 7114 | +an exception object |
| 7115 | +of type |
| 7116 | +\tcode{E} |
| 7117 | +if |
| 7118 | +\begin{itemize} |
| 7119 | +\item% |
| 7120 | +The \grammarterm{handler} is of type \cv{}~\tcode{T} or |
| 7121 | +\cv{}~\tcode{T\&} and |
| 7122 | +\tcode{E} and \tcode{T} |
| 7123 | +are the same type (ignoring the top-level \grammarterm{cv-qualifier}{s}), or |
| 7124 | +\item% |
| 7125 | +the \grammarterm{handler} is of type \cv{}~\tcode{T} or |
| 7126 | +\cv{}~\tcode{T\&} and |
| 7127 | +\tcode{T} is an unambiguous public base class of \tcode{E}, or |
| 7128 | +\item% |
| 7129 | +the \grammarterm{handler} is of type \cv{}~\tcode{T} or \tcode{const T\&} |
| 7130 | +where \tcode{T} is a pointer or pointer-to-member type and |
| 7131 | +\tcode{E} is a pointer or pointer-to-member type |
| 7132 | +that can be converted to \tcode{T} by one or more of |
| 7133 | +\begin{itemize} |
| 7134 | + |
| 7135 | +\item% |
| 7136 | +a standard pointer conversion\iref{conv.ptr} not involving conversions |
| 7137 | +to pointers to private or protected or ambiguous classes |
| 7138 | +\item% |
| 7139 | +a function pointer conversion\iref{conv.fctptr} |
| 7140 | +\item% |
| 7141 | +a qualification conversion\iref{conv.qual}, or |
| 7142 | + |
| 7143 | +\end{itemize} |
| 7144 | + |
| 7145 | +\item |
| 7146 | +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}. |
| 7147 | + |
| 7148 | +\end{itemize} |
| 7149 | + |
| 7150 | +\begin{note} |
| 7151 | +A |
| 7152 | +\grammarterm{throw-expression} |
| 7153 | +whose operand is an integer literal with value zero does not match a handler of |
| 7154 | +pointer or pointer-to-member type. |
| 7155 | +A handler of reference to array or function type |
| 7156 | +is never a match for any exception object\iref{expr.throw}. |
| 7157 | +\end{note} |
| 7158 | + |
| 7159 | +\begin{example} |
| 7160 | +\begin{codeblock} |
| 7161 | +class Matherr { @\commentellip@ virtual void vf(); }; |
| 7162 | +class Overflow: public Matherr { @\commentellip@ }; |
| 7163 | +class Underflow: public Matherr { @\commentellip@ }; |
| 7164 | +class Zerodivide: public Matherr { @\commentellip@ }; |
| 7165 | + |
| 7166 | +void f() { |
| 7167 | + try { |
| 7168 | + g(); |
| 7169 | + } catch (Overflow oo) { |
| 7170 | + // ... |
| 7171 | + } catch (Matherr mm) { |
| 7172 | + // ... |
| 7173 | + } |
| 7174 | +} |
| 7175 | +\end{codeblock} |
| 7176 | +Here, the |
| 7177 | +\tcode{Overflow} |
| 7178 | +handler will catch exceptions of type |
| 7179 | +\tcode{Overflow} |
| 7180 | +and the |
| 7181 | +\tcode{Matherr} |
| 7182 | +handler will catch exceptions of type |
| 7183 | +\tcode{Matherr} |
| 7184 | +and of all types publicly derived from |
| 7185 | +\tcode{Matherr} |
| 7186 | +including exceptions of type |
| 7187 | +\tcode{Underflow} |
| 7188 | +and |
| 7189 | +\tcode{Zerodivide}. |
| 7190 | +\end{example} |
| 7191 | + |
| 7192 | +\pnum |
| 7193 | +The handlers for a try block are tried in order of appearance. |
| 7194 | +\begin{note} |
| 7195 | +This makes it possible to write handlers that can never be |
| 7196 | +executed, for example by placing a handler for a final derived class after |
| 7197 | +a handler for a corresponding unambiguous public base class. |
| 7198 | +\end{note} |
| 7199 | + |
| 7200 | +\pnum |
| 7201 | +A |
| 7202 | +\tcode{...} |
| 7203 | +in a handler's |
| 7204 | +\grammarterm{exception-declaration} |
| 7205 | +specifies a match for any exception. |
| 7206 | +If present, a |
| 7207 | +\tcode{...} |
| 7208 | +handler shall be the last handler for its try block. |
| 7209 | + |
| 7210 | +\pnum |
| 7211 | +If no match is found among the handlers for a try block, |
| 7212 | +the search for a matching |
| 7213 | +handler continues in a dynamically surrounding try block |
| 7214 | +of the same thread. |
| 7215 | + |
| 7216 | +\pnum |
| 7217 | +\indextext{exception handling!terminate called@\tcode{terminate} called}% |
| 7218 | +\indextext{\idxcode{terminate}!called}% |
| 7219 | +If the search for a handler |
| 7220 | +encounters the outermost block of a function with a |
| 7221 | +non-throwing exception specification, |
| 7222 | +the function \tcode{std::terminate}\iref{except.terminate} is invoked. |
| 7223 | +\begin{note} |
| 7224 | +An implementation is not permitted to reject an expression merely because, when |
| 7225 | +executed, it throws or might |
| 7226 | +throw an exception from a function with a non-throwing exception specification. |
| 7227 | +\end{note} |
| 7228 | +\begin{example} |
| 7229 | +\begin{codeblock} |
| 7230 | +extern void f(); // potentially-throwing |
| 7231 | + |
| 7232 | +void g() noexcept { |
| 7233 | + f(); // valid, even if \tcode{f} throws |
| 7234 | + throw 42; // valid, effectively a call to \tcode{std::terminate} |
| 7235 | +} |
| 7236 | +\end{codeblock} |
| 7237 | +The call to |
| 7238 | +\tcode{f} |
| 7239 | +is well-formed despite the possibility for it to throw an exception. |
| 7240 | +\end{example} |
| 7241 | + |
| 7242 | +\pnum |
| 7243 | +If no matching handler is found, |
| 7244 | +the function \tcode{std::terminate} is invoked; |
| 7245 | +whether or not the stack is unwound before this invocation of |
| 7246 | +\tcode{std::terminate} is |
| 7247 | +\impldef{whether stack is unwound before invoking the function \tcode{std::terminate} |
| 7248 | +when no matching handler is found}\iref{except.terminate} |
| 7249 | + |
| 7250 | +\pnum |
| 7251 | +A handler is considered \defnx{active}{exception handling!handler!active} when |
| 7252 | +initialization is complete for the parameter (if any) of the catch clause. |
| 7253 | +\begin{note} |
| 7254 | +The stack will have been unwound at that point. |
| 7255 | +\end{note} |
| 7256 | +Also, an implicit handler is considered active when |
| 7257 | +the function \tcode{std::terminate} |
| 7258 | +is entered due to a throw. A handler is no longer considered active when the |
| 7259 | +catch clause exits. |
| 7260 | + |
| 7261 | +\pnum |
| 7262 | +\indextext{currently handled exception|see{exception handling, currently handled exception}}% |
| 7263 | +The exception with the most recently activated handler that is |
| 7264 | +still active is called the |
| 7265 | +\defnx{currently handled exception}{exception handling!currently handled exception}. |
| 7266 | + |
| 7267 | +\pnum |
| 7268 | +Referring to any non-static member or base class of an object |
| 7269 | +in the handler for a |
| 7270 | +\grammarterm{function-try-block} |
| 7271 | +of a constructor or destructor for that object results in undefined behavior. |
| 7272 | + |
| 7273 | +\pnum |
| 7274 | +Exceptions thrown in destructors of objects with static storage duration or in |
| 7275 | +constructors of objects associated with non-block variables with static storage duration are not caught by a |
| 7276 | +\grammarterm{function-try-block} |
| 7277 | +on |
| 7278 | +the \tcode{main} function\iref{basic.start.main}. |
| 7279 | +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 |
| 7280 | +\grammarterm{function-try-block} |
| 7281 | +on the initial function of the thread. |
| 7282 | + |
| 7283 | +\pnum |
| 7284 | +If a \keyword{return} statement\iref{stmt.return} appears in a handler of the |
| 7285 | +\grammarterm{function-try-block} |
| 7286 | +of a |
| 7287 | +constructor, the program is ill-formed. |
| 7288 | + |
| 7289 | +\pnum |
| 7290 | +The currently handled exception |
| 7291 | +is rethrown if control reaches the end of a handler of the |
| 7292 | +\grammarterm{function-try-block} |
| 7293 | +of a constructor or destructor. |
| 7294 | +Otherwise, flowing off the end of |
| 7295 | +the \grammarterm{compound-statement} |
| 7296 | +of a \grammarterm{handler} |
| 7297 | +of a \grammarterm{function-try-block} |
| 7298 | +is equivalent to flowing off the end of |
| 7299 | +the \grammarterm{compound-statement} |
| 7300 | +of that function (see \ref{stmt.return}). |
| 7301 | + |
| 7302 | +\pnum |
| 7303 | +The variable declared by the \grammarterm{exception-declaration}, of type |
| 7304 | +\cv{}~\tcode{T} or \cv{}~\tcode{T\&}, is initialized from the exception object, |
| 7305 | +of type \tcode{E}, as follows: |
| 7306 | +\begin{itemize} |
| 7307 | +\item |
| 7308 | +if \tcode{T} is a base class of \tcode{E}, |
| 7309 | +the variable is copy-initialized\iref{dcl.init} |
| 7310 | +from an lvalue of type \tcode{T} designating the corresponding base class subobject |
| 7311 | +of the exception object; |
| 7312 | +\item otherwise, the variable is copy-initialized\iref{dcl.init} |
| 7313 | +from an lvalue of type \tcode{E} designating the exception object. |
| 7314 | +\end{itemize} |
| 7315 | + |
| 7316 | +The lifetime of the variable ends |
| 7317 | +when the handler exits, after the |
| 7318 | +destruction of any objects with automatic storage duration initialized |
| 7319 | +within the handler. |
| 7320 | + |
| 7321 | +\pnum |
| 7322 | +When the handler declares an object, |
| 7323 | +any changes to that object will not affect the exception object. |
| 7324 | +When the handler declares a reference to an object, |
| 7325 | +any changes to the referenced object are changes to the |
| 7326 | +exception object and will have effect should that object be rethrown.% |
| 7327 | +\indextext{exception handling!handler!match|)}% |
| 7328 | +\indextext{exception handling!handler|)} |
| 7329 | + |
7069 | 7330 | \rSec2[basic.start]{Start and termination}
|
7070 | 7331 |
|
7071 | 7332 | \rSec3[basic.start.main]{\tcode{main} function}
|
|
7603 | 7864 | \pnum
|
7604 | 7865 | \indextext{\idxcode{terminate}}%
|
7605 | 7866 | In the situation where no matching handler is found, it is
|
7606 |
| -\impldef{stack unwinding before invocation of \tcode{std::terminate}} |
7607 |
| -whether or not the stack is unwound |
7608 |
| -before \tcode{std::terminate} is invoked. |
| 7867 | +\impldef{whether stack is unwound before invoking the function \tcode{std::terminate} |
| 7868 | +when no matching handler is found} |
| 7869 | +whether or not the stack is unwound before \tcode{std::terminate} is invoked. |
7609 | 7870 | In the situation where the search for a handler\iref{except.handle} encounters the
|
7610 | 7871 | outermost block of a function
|
7611 | 7872 | with a non-throwing exception specification\iref{except.spec}, it is
|
|
0 commit comments