Skip to content

Commit e567f41

Browse files
momo773510Lancern
andauthored
feat: migrate cpp/language/exceptions (#90)
* update preprocessor documentation * feat: migrate cpp/templates cpp/exceptions from cppref * fix preprocessor doc * feat: migrate cpp/language/exceptions * fixed broken indentation fixed the broken indentation caused by wrong auto formatting * Fix formatting of exception handling details * Update src/content/docs/cpp/language/exceptions/catch.mdx fixed indented problem Co-authored-by: Sirui Mu <msrlancern@gmail.com> --------- Co-authored-by: Sirui Mu <msrlancern@gmail.com>
1 parent 1880cea commit e567f41

File tree

6 files changed

+1052
-18
lines changed

6 files changed

+1052
-18
lines changed

src/content/docs/cpp/language/exceptions.mdx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
---
2-
title: Exceptions
2+
title: Overview
3+
sidebar:
4+
order: 1
35
---
46

57
import { Decl, DeclDoc } from "@components/decl-doc";
Lines changed: 326 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,326 @@
1+
---
2+
title: Handling exceptions
3+
sidebar:
4+
order: 4
5+
---
6+
7+
import { Decl, DeclDoc } from "@components/decl-doc";
8+
import { Desc, DescList, DocLink } from '@components/index';
9+
import { Revision, RevisionBlock } from "@components/revision";
10+
import { DR, DRList } from "@components/defect-report";
11+
import { ParamDoc, ParamDocList } from "@components/param-doc";
12+
13+
An <DocLink dest="/cpp/language/exceptions">exception</DocLink> can be handled by a handler.
14+
15+
### Handler
16+
17+
<DeclDoc id={1}>
18+
<Decl slot="decl">
19+
```cpp cxx-mark
20+
catch ( /*$s:attr*//*$opt*/ /*$s:type-specifier-seq*/ /*$s:declarator*/ ) /*$s:compound-statement*/
21+
```
22+
</Decl>
23+
A handler with a named parameter.
24+
</DeclDoc>
25+
<DeclDoc id={2}>
26+
<Decl slot="decl">
27+
```cpp cxx-mark
28+
catch ( /*$s:attr*//*$opt*/ /*$s:type-specifier-seq*/ /*$s:abstract-declarator*//*$opt*/ ) /*$s:compound-statement*/
29+
```
30+
</Decl>
31+
A handler with an unnamed parameter.
32+
</DeclDoc>
33+
<DeclDoc id={3}>
34+
<Decl slot="decl">
35+
```cpp cxx-mark
36+
catch ( ... ) /*$s:compound-statement*/
37+
```
38+
</Decl>
39+
A handler matching all kinds of exceptions.
40+
</DeclDoc>
41+
42+
<ParamDocList>
43+
<ParamDoc name="attr">
44+
<Revision since="C++11"></Revision> any number of <DocLink dest="/cpp/language/attributes">attributes</DocLink>, applies to the parameter
45+
</ParamDoc>
46+
<ParamDoc name="type-specifier-seq">
47+
part of a formal parameter declaration, same as in a function <DocLink dest="/cpp/language/functions/function#Parameter_list">parameter list</DocLink>
48+
</ParamDoc>
49+
<ParamDoc name="declarator">
50+
part of a parameter declaration, same as in a function <DocLink dest="/cpp/language/functions/function#Parameter_list">parameter list</DocLink>
51+
</ParamDoc>
52+
<ParamDoc name="abstract-declarator">
53+
part of an unnamed parameter declaration, same as in function <DocLink dest="/cpp/language/functions/function#Parameter_list">parameter list</DocLink>
54+
</ParamDoc>
55+
<ParamDoc name="compound-statement">
56+
a <DocLink dest="/cpp/language/statements#Compound_statements">compound statement</DocLink>
57+
</ParamDoc>
58+
</ParamDocList>
59+
60+
The parameter declaration in a handler describes the type(s) of exceptions that can cause that handler to be entered.
61+
62+
If the parameter is declared to have one of the following types, the program is ill-formed:
63+
64+
- an <DocLink dest="/cpp/language/basic_concepts/definition#Incomplete_type">incomplete type</DocLink>
65+
- an <DocLink dest="/cpp/language/classes#Abstract_classes">abstract class type</DocLink>
66+
- an <DocLink dest="/cpp/language/reference#Rvalue_reference"><Revision since="C++11">rvalue reference type</Revision></DocLink>
67+
- a pointer to an incomplete type other than (possibly cv-qualified) `void`
68+
- an lvalue reference to an incomplete type
69+
70+
If the parameter is declared to have type “array of `T`” or function type `T`, the type is adjusted to “pointer to `T`”.
71+
72+
A handler with parameter type `T` can be abbreviated as “a handler of type `T`”.
73+
74+
### Matching exceptions
75+
76+
Each `try` block associates with a number of handlers, these handlers form a handler sequence. When an exception is thrown from a `try` block, the handlers in the sequence are tried in order of appearance to match the exception.
77+
78+
A handler is a match for an <DocLink dest="/cpp/language/exceptions/throwing_exceptions#Exception_object">exception object</DocLink> of type `E` if any of the following conditions is satisfied:
79+
80+
- The handler is of type “possibly cv-qualified `T`” or “lvalue reference to possibly cv-qualified `T`”, and any of the following conditions is satisfied:
81+
- `E` and `T` are the same type (ignoring the top-level cv-qualifiers).
82+
- `T` is an unambiguous public base class of `E`.
83+
- The handler is of type “possibly cv-qualified `T`” or `const T&` where `T` is a pointer or pointer-to-member type, and any of the following conditions is satisfied:
84+
- `E` is a pointer or pointer-to-member type that can be converted to `T` by at least one of the following conversions:
85+
- A <DocLink dest="/cpp/language/implicit_cast#Pointer_conversions">standard pointer conversion</DocLink> not involving conversions to pointers to private or protected or ambiguous classes.
86+
- <Revision since="C++17">A <DocLink dest="/cpp/language/implicit_cast#Function_pointer_conversions">function pointer conversion.</DocLink></Revision>
87+
- A <DocLink dest="/cpp/language/implicit_cast#Qualification_conversions">qualification conversion</DocLink>.
88+
- <Revision since="C++11">`E` is <DocLink dest="/cpp/types/nullptr_t">std::nullptr_t</DocLink>.</Revision>
89+
90+
The `catch (...)` handler matches exceptions of any type. If present, it can only be the last handler in a handler sequence. This handler may be used to ensure that no uncaught exceptions can possibly escape from a function that offers <DocLink dest="/cpp/language/exceptions">nothrow exception guarantee</DocLink>.
91+
```cpp
92+
try
93+
{
94+
f();
95+
}
96+
catch (const std::overflow_error& e)
97+
{} // this executes if f() throws std::overflow_error (same type rule)
98+
catch (const std::runtime_error& e)
99+
{} // this executes if f() throws std::underflow_error (base class rule)
100+
catch (const std::exception& e)
101+
{} // this executes if f() throws std::logic_error (base class rule)
102+
catch (...)
103+
{} // this executes if f() throws std::string or int or any other unrelated type
104+
```
105+
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<Revision since="C++11"> of the same thread</Revision>.
106+
107+
If no matching handler is found, <DocLink dest="/cpp/error/terminate">std::terminate</DocLink> is invoked; whether or not the stack is <DocLink dest="/cpp/language/exceptions/throwing_exceptions#Stack_unwinding">unwound</DocLink> before this invocation of <DocLink dest="/cpp/error/terminate">std::terminate</DocLink> is implementation-defined.
108+
109+
### Handling exceptions
110+
111+
When an exception is thrown, control is transferred to the nearest handler with a matching type; “nearest” means the handler for which the compound statement or the member initializer list (if present) following the `try` keyword was most recently entered by the thread of control and not yet exited.
112+
113+
#### Initializing the handler parameter
114+
115+
The parameter declared in the parameter list (if any), of type “possibly cv-qualified `T`” or “lvalue reference to possibly cv-qualified `T`”, is initialized from the <DocLink dest="/cpp/language/exceptions/throwing_exceptions#Exception_object">exception object</DocLink>, of type `E`, as follows:
116+
117+
- If `T` is a base class of `E`, the parameter is <DocLink dest="/cpp/language/copy_initialization">copy-initialized</DocLink> from an lvalue of type `T` designating the corresponding base class subobject of the exception object.
118+
- Otherwise, the parameter is copy-initialized from an lvalue of type `E` designating the exception object.
119+
120+
The lifetime of the parameter ends when the handler exits, after the destruction of any objects with automatic <DocLink dest="/cpp/language/storage_duration">storage duration</DocLink> initialized within the handler.
121+
122+
When the parameter is declared as an object, any changes to that object will not affect the exception object.
123+
124+
When the parameter is declared as 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.
125+
126+
#### Activating the handler
127+
128+
A handler is considered _active_ when initialization is complete for the parameter (if any) of the handler.
129+
130+
Also, an implicit handler is considered active when <DocLink dest="/cpp/error/terminate">std::terminate</DocLink> is entered due to a throw.
131+
132+
A handler is no longer considered active when the handler exits.
133+
134+
The exception with the most recently activated handler that is still active is called the _currently handled exception_. Such an exception can be <DocLink dest="/cpp/language/exceptions/throwing_exceptions#throw_expressions">rethrown</DocLink>.
135+
136+
### Control flow
137+
138+
The `compound-statement` of a handler is a <DocLink dest="/cpp/language/statements#Control-flow-limited_statements">control-flow-limited statement</DocLink>:
139+
140+
```cpp
141+
void f()
142+
{
143+
goto label; // error
144+
try
145+
{
146+
goto label; // error
147+
}
148+
catch (...)
149+
{
150+
goto label: // OK
151+
label: ;
152+
}
153+
}
154+
```
155+
156+
### Notes
157+
158+
<DocLink dest="/cpp/language/exceptions/throwing_exceptions#Stack_unwinding">Stack unwinding</DocLink> occurs while control is transferring to a handler. When a handler becomes active, stack unwinding is already completed.
159+
160+
The exception thrown by the `throw` expression `throw 0` does not match a handler of pointer or pointer-to-member type.
161+
162+
- <Revision since="C++11">`throw nullptr` can be used instead to throw a null pointer that matches such handlers.</Revision>
163+
164+
<DocLink dest="/cpp/language/exceptions/throwing_exceptions#Exception_object">Exception objects</DocLink> can never have array or function types, therefore a handler of reference to array or function type is never a match for any exception object.
165+
166+
It is 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:
167+
168+
```cpp
169+
try
170+
{
171+
f();
172+
}
173+
catch (const std::exception& e)
174+
{} // will be executed if f() throws std::runtime_error
175+
catch (const std::runtime_error& e)
176+
{} // dead code!
177+
```
178+
179+
Many implementations overly extend the resolution of <DocLink dest="https://cplusplus.github.io/CWG/issues/388.html">CWG issue 388</DocLink> to handlers of reference to non-const pointer types:
180+
181+
```cpp
182+
int i;
183+
try
184+
{
185+
try
186+
{
187+
throw static_cast<float*>(nullptr);
188+
}
189+
catch (void*& pv)
190+
{
191+
pv = &i;
192+
throw;
193+
}
194+
}
195+
catch (const float* pf)
196+
{
197+
assert(pf == nullptr); // should pass, but fails on MSVC and Clang
198+
}
199+
```
200+
201+
### Keywords
202+
203+
- <DocLink dest="/cpp/keyword/catch">`catch`</DocLink>
204+
205+
### Example
206+
207+
The following example demonstrates several usage cases of the handlers:
208+
209+
```cpp
210+
#include <iostream>
211+
#include <vector>
212+
213+
int main()
214+
{
215+
try
216+
{
217+
std::cout << "Throwing an integer exception...\n";
218+
throw 42;
219+
}
220+
catch (int i)
221+
{
222+
std::cout << " the integer exception was caught, with value: " << i << '\n';
223+
}
224+
225+
try
226+
{
227+
std::cout << "Creating a vector of size 5... \n";
228+
std::vector<int> v(5);
229+
std::cout << "Accessing the 11th element of the vector...\n";
230+
std::cout << v.at(10); // vector::at() throws std::out_of_range
231+
}
232+
catch (const std::exception& e) // caught by reference to base
233+
{
234+
std::cout << " a standard exception was caught, with message: '"
235+
<< e.what() << "'\n";
236+
}
237+
}
238+
```
239+
240+
Possible output:
241+
242+
```text
243+
Throwing an integer exception...
244+
the integer exception was caught, with value: 42
245+
Creating a vector of size 5...
246+
Accessing the 11th element of the vector...
247+
a standard exception was caught, with message: 'out_of_range'
248+
```
249+
250+
### Defect reports
251+
252+
The following behavior-changing defect reports were applied retroactively to previously published C++ standards.
253+
254+
<DRList>
255+
<DR kind="cwg" id={98} std="C++98">
256+
<Fragment slot="behavior-published">
257+
a `switch` statement can transfer control into a handler
258+
</Fragment>
259+
<Fragment slot="correct-behavior">
260+
prohibited
261+
</Fragment>
262+
</DR>
263+
<DR kind="cwg" id={210} std="C++98">
264+
<Fragment slot="behavior-published">
265+
`throw` expressions were matched against the handlers
266+
</Fragment>
267+
<Fragment slot="correct-behavior">
268+
exception objects are matched against the handlers
269+
</Fragment>
270+
</DR>
271+
<DR kind="cwg" id={388} std="C++98">
272+
<Fragment slot="behavior-published">
273+
an exception of pointer or pointer to member type could not be matched by a const reference to a different type
274+
</Fragment>
275+
<Fragment slot="correct-behavior">
276+
made matchable when convertible
277+
</Fragment>
278+
</DR>
279+
<DR kind="cwg" id={1166} std="C++98">
280+
<Fragment slot="behavior-published">
281+
the behavior was unspecified when a handler whose type is a reference to an abstract class type is matched
282+
</Fragment>
283+
<Fragment slot="correct-behavior">
284+
abstract class types are not allowed for handlers
285+
</Fragment>
286+
</DR>
287+
<DR kind="cwg" id={1769} std="C++98">
288+
<Fragment slot="behavior-published">
289+
when the type of the handler is a base of the type of the exception object, a converting constructor might be used for the initialization of the handler parameter
290+
</Fragment>
291+
<Fragment slot="correct-behavior">
292+
the parameter is copy-initialized from the corresponding base class subobject of the exception object
293+
</Fragment>
294+
</DR>
295+
<DR kind="cwg" id={2093} std="C++98">
296+
<Fragment slot="behavior-published">
297+
an exception object of pointer to object type could not match a handler of pointer to object type through qualification conversion
298+
</Fragment>
299+
<Fragment slot="correct-behavior">
300+
allowed
301+
</Fragment>
302+
</DR>
303+
</DRList>
304+
305+
### References
306+
307+
- C++23 standard (ISO/IEC 14882:2024):
308+
- 14.4 Handling an exception [except.handle]
309+
- C++20 standard (ISO/IEC 14882:2020):
310+
- 14.4 Handling an exception [except.handle]
311+
- C++17 standard (ISO/IEC 14882:2017):
312+
- 18.3 Handling an exception [except.handle]
313+
- C++14 standard (ISO/IEC 14882:2014):
314+
- 15.3 Handling an exception [except.handle]
315+
- C++11 standard (ISO/IEC 14882:2011):
316+
- 15.3 Handling an exception [except.handle]
317+
- C++03 standard (ISO/IEC 14882:2003):
318+
- 15.3 Handling an exception [except.handle]
319+
- C++98 standard (ISO/IEC 14882:1998):
320+
- 15.3 Handling an exception [except.handle]
321+
322+
### See also
323+
324+
- <DocLink dest="/cpp/language/exceptions/try">`try` block</DocLink>
325+
- <DocLink dest="/cpp/language/exceptions/throw">Throwing exceptions</DocLink>
326+
- <DocLink dest="/cpp/error">Exception handling</DocLink>

0 commit comments

Comments
 (0)