238 lines
11 KiB
Markdown
238 lines
11 KiB
Markdown
[except.handle]
|
||
|
||
# 14 Exception handling [[except]](./#except)
|
||
|
||
## 14.4 Handling an exception [except.handle]
|
||
|
||
[1](#1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exceptions.tex#L500)
|
||
|
||
The[*exception-declaration*](except.pre#nt:exception-declaration "14.1 Preamble [except.pre]") in a[*handler*](except.pre#nt:handler "14.1 Preamble [except.pre]") describes the type(s) of exceptions that can cause
|
||
that[*handler*](except.pre#nt:handler "14.1 Preamble [except.pre]") to be entered[.](#1.sentence-1)
|
||
|
||
The[*exception-declaration*](except.pre#nt:exception-declaration "14.1 Preamble [except.pre]") shall not denote an incomplete type, an abstract class type, or an rvalue reference type[.](#1.sentence-2)
|
||
|
||
The[*exception-declaration*](except.pre#nt:exception-declaration "14.1 Preamble [except.pre]") shall not denote a pointer or reference to an
|
||
incomplete type, other than âpointer to cv voidâ[.](#1.sentence-3)
|
||
|
||
[2](#2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exceptions.tex#L521)
|
||
|
||
A handler of typeâarray of Tâ orfunction type T is adjusted to be of type
|
||
âpointer to Tâ[.](#2.sentence-1)
|
||
|
||
[3](#3)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exceptions.tex#L530)
|
||
|
||
A[*handler*](except.pre#nt:handler "14.1 Preamble [except.pre]") is a match for
|
||
an exception object
|
||
of typeE if
|
||
|
||
- [(3.1)](#3.1)
|
||
|
||
The [*handler*](except.pre#nt:handler "14.1 Preamble [except.pre]") is of type cv T orcv T& andE and T are the same type (ignoring the top-level [*cv-qualifier*](dcl.decl.general#nt:cv-qualifier "9.3.1 General [dcl.decl.general]")*s*), or
|
||
|
||
- [(3.2)](#3.2)
|
||
|
||
the [*handler*](except.pre#nt:handler "14.1 Preamble [except.pre]") is of type cv T orcv T& andT is an unambiguous public base class of E, or
|
||
|
||
- [(3.3)](#3.3)
|
||
|
||
the [*handler*](except.pre#nt:handler "14.1 Preamble [except.pre]") is of type cv T or const T& where T is a pointer or pointer-to-member type andE is a pointer or pointer-to-member type
|
||
that can be converted to T by one or more of
|
||
* [(3.3.1)](#3.3.1)
|
||
|
||
a standard [pointer conversion](conv.ptr "7.3.12 Pointer conversions [conv.ptr]") not involving conversions
|
||
to pointers to private or protected or ambiguous classes
|
||
|
||
* [(3.3.2)](#3.3.2)
|
||
|
||
a [function pointer conversion](conv.fctptr "7.3.14 Function pointer conversions [conv.fctptr]")
|
||
|
||
* [(3.3.3)](#3.3.3)
|
||
|
||
a [qualification conversion](conv.qual "7.3.6 Qualification conversions [conv.qual]"), or
|
||
|
||
- [(3.4)](#3.4)
|
||
|
||
the [*handler*](except.pre#nt:handler "14.1 Preamble [except.pre]") is of type cv T or const T& where T is a pointer or pointer-to-member type and E is std::nullptr_t[.](#3.sentence-1)
|
||
|
||
[*Note [1](#note-1)*:
|
||
|
||
A[*throw-expression*](expr.throw#nt:throw-expression "7.6.18 Throwing an exception [expr.throw]") whose operand is an integer literal with value zero does not match a handler of
|
||
pointer or pointer-to-member type[.](#3.sentence-2)
|
||
|
||
A handler of reference to array or function type
|
||
is never a match for any exception object ([[expr.throw]](expr.throw "7.6.18 Throwing an exception"))[.](#3.sentence-3)
|
||
|
||
â *end note*]
|
||
|
||
[*Example [1](#example-1)*: 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) {// ...}}
|
||
|
||
Here, theOverflow handler will catch exceptions of typeOverflow and theMatherr handler will catch exceptions of typeMatherr and of all types publicly derived fromMatherr including exceptions of typeUnderflow andZerodivide[.](#3.sentence-4)
|
||
|
||
â *end example*]
|
||
|
||
[4](#4)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exceptions.tex#L611)
|
||
|
||
The handlers for a try block are tried in order of appearance[.](#4.sentence-1)
|
||
|
||
[*Note [2](#note-2)*:
|
||
|
||
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[.](#4.sentence-2)
|
||
|
||
â *end note*]
|
||
|
||
[5](#5)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exceptions.tex#L619)
|
||
|
||
A... in a handler's[*exception-declaration*](except.pre#nt:exception-declaration "14.1 Preamble [except.pre]") specifies a match for any exception[.](#5.sentence-1)
|
||
|
||
If present, a... handler shall be the last handler for its try block[.](#5.sentence-2)
|
||
|
||
[6](#6)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exceptions.tex#L629)
|
||
|
||
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[.](#6.sentence-1)
|
||
|
||
[7](#7)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exceptions.tex#L635)
|
||
|
||
If the search for a handler
|
||
exits the function body of a function with a
|
||
non-throwing exception specification,
|
||
the function std::terminate ([[except.terminate]](except.terminate "14.6.2 The std::terminate function")) is invoked[.](#7.sentence-1)
|
||
|
||
[*Note [3](#note-3)*:
|
||
|
||
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[.](#7.sentence-2)
|
||
|
||
â *end note*]
|
||
|
||
[*Example [2](#example-2)*: extern void f(); // potentially-throwingvoid g() noexcept { f(); // valid, even if f throwsthrow 42; // valid, effectively a call to std::terminate}
|
||
|
||
The call tof is well-formed despite the possibility for it to throw an exception[.](#7.sentence-3)
|
||
|
||
â *end example*]
|
||
|
||
[8](#8)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exceptions.tex#L661)
|
||
|
||
If no matching handler is found,
|
||
the function std::terminate is invoked;
|
||
whether or not the stack is unwound before this invocation ofstd::terminate is implementation-defined ([[except.terminate]](except.terminate "14.6.2 The std::terminate function"))[.](#8.sentence-1)
|
||
|
||
[9](#9)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exceptions.tex#L669)
|
||
|
||
A handler is considered [*active*](#def:exception_handling,handler,active "14.4 Handling an exception [except.handle]") when
|
||
initialization is complete for the parameter (if any) of the catch clause[.](#9.sentence-1)
|
||
|
||
[*Note [4](#note-4)*:
|
||
|
||
The stack will have been unwound at that point[.](#9.sentence-2)
|
||
|
||
â *end note*]
|
||
|
||
Also, an implicit handler is considered active when
|
||
the function std::terminate is entered due to a throw[.](#9.sentence-3)
|
||
|
||
A handler is no longer considered active when the
|
||
catch clause exits[.](#9.sentence-4)
|
||
|
||
[10](#10)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exceptions.tex#L680)
|
||
|
||
The exception with the most recently activated handler that is
|
||
still active is called the[*currently handled exception*](#def:exception_handling,currently_handled_exception "14.4 Handling an exception [except.handle]")[.](#10.sentence-1)
|
||
|
||
[11](#11)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exceptions.tex#L686)
|
||
|
||
Referring to any non-static member or base class of an object
|
||
in the handler for a[*function-try-block*](except.pre#nt:function-try-block "14.1 Preamble [except.pre]") of a constructor or destructor for that object results in undefined behavior[.](#11.sentence-1)
|
||
|
||
[12](#12)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exceptions.tex#L692)
|
||
|
||
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[*function-try-block*](except.pre#nt:function-try-block "14.1 Preamble [except.pre]") on
|
||
the [main function](basic.start.main "6.10.3.1 main function [basic.start.main]")[.](#12.sentence-1)
|
||
|
||
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[*function-try-block*](except.pre#nt:function-try-block "14.1 Preamble [except.pre]") on the initial function of the thread[.](#12.sentence-2)
|
||
|
||
[13](#13)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exceptions.tex#L702)
|
||
|
||
If a return statement ([[stmt.return]](stmt.return "8.8.4 The return statement")) appears in a handler of the[*function-try-block*](except.pre#nt:function-try-block "14.1 Preamble [except.pre]") of a
|
||
constructor, the program is ill-formed[.](#13.sentence-1)
|
||
|
||
[14](#14)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exceptions.tex#L708)
|
||
|
||
The currently handled exception
|
||
is rethrown if control reaches the end of a handler of the[*function-try-block*](except.pre#nt:function-try-block "14.1 Preamble [except.pre]") of a constructor or destructor[.](#14.sentence-1)
|
||
|
||
Otherwise, flowing off the end of
|
||
the [*compound-statement*](stmt.block#nt:compound-statement "8.4 Compound statement or block [stmt.block]") of a [*handler*](except.pre#nt:handler "14.1 Preamble [except.pre]") of a [*function-try-block*](except.pre#nt:function-try-block "14.1 Preamble [except.pre]") is equivalent to flowing off the end of
|
||
the [*compound-statement*](stmt.block#nt:compound-statement "8.4 Compound statement or block [stmt.block]") of that function (see [[stmt.return]](stmt.return "8.8.4 The return statement"))[.](#14.sentence-2)
|
||
|
||
[15](#15)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exceptions.tex#L721)
|
||
|
||
The variable declared by the [*exception-declaration*](except.pre#nt:exception-declaration "14.1 Preamble [except.pre]"), of typecv T or cv T&, is initialized from the exception object,
|
||
of type E, as follows:
|
||
|
||
- [(15.1)](#15.1)
|
||
|
||
if T is a base class of E,
|
||
the variable is copy-initialized ([[dcl.init]](dcl.init "9.5 Initializers"))
|
||
from an lvalue of type T designating the corresponding base class subobject
|
||
of the exception object;
|
||
|
||
- [(15.2)](#15.2)
|
||
|
||
otherwise, the variable is copy-initialized ([[dcl.init]](dcl.init "9.5 Initializers"))
|
||
from an lvalue of type E designating the exception object[.](#15.sentence-1)
|
||
|
||
The lifetime of the variable ends
|
||
when the handler exits, after the
|
||
destruction of any objects with automatic storage duration initialized
|
||
within the handler[.](#15.sentence-2)
|
||
|
||
[16](#16)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exceptions.tex#L740)
|
||
|
||
When the handler declares an object,
|
||
any changes to that object will not affect the exception object[.](#16.sentence-1)
|
||
|
||
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[.](#16.sentence-2)
|