From Jason Turner

[except.spec]

Diff to HTML by rtfpessoa

Files changed (1) hide show
  1. tmp/tmpmunk95tt/{from.md → to.md} +140 -208
tmp/tmpmunk95tt/{from.md → to.md} RENAMED
@@ -1,271 +1,203 @@
1
  ## Exception specifications <a id="except.spec">[[except.spec]]</a>
2
 
3
- A function declaration lists exceptions that its function might directly
4
- or indirectly throw by using an *exception-specification* as a suffix of
5
- its declarator.
 
 
 
 
6
 
7
  ``` bnf
8
- exception-specification:
9
- dynamic-exception-specification
10
- noexcept-specification
11
- ```
12
-
13
- ``` bnf
14
- dynamic-exception-specification:
15
- 'throw (' type-id-listₒₚₜ ')'
16
- ```
17
-
18
- ``` bnf
19
- type-id-list:
20
- type-id '...'ₒₚₜ
21
- type-id-list ',' type-id '...'ₒₚₜ
22
- ```
23
-
24
- ``` bnf
25
- noexcept-specification:
26
  'noexcept' '(' constant-expression ')'
27
  'noexcept'
 
28
  ```
29
 
30
- In a *noexcept-specification*, the *constant-expression*, if supplied,
31
- shall be a constant expression ([[expr.const]]) that is contextually
32
- converted to `bool` (Clause  [[conv]]). A *noexcept-specification*
33
- `noexcept` is equivalent to `noexcept(true)`. A `(` token that follows
34
- `noexcept` is part of the *noexcept-specification* and does not commence
35
- an initializer ([[dcl.init]]).
36
-
37
- An *exception-specification* shall appear only on a function declarator
38
- for a function type, pointer to function type, reference to function
39
- type, or pointer to member function type that is the top-level type of a
40
- declaration or definition, or on such a type appearing as a parameter or
41
- return type in a function declarator. An *exception-specification* shall
42
- not appear in a typedef declaration or *alias-declaration*.
43
-
44
- ``` cpp
45
- void f() throw(int); // OK
46
- void (*fp)() throw (int); // OK
47
- void g(void pfa() throw(int)); // OK
48
- typedef int (*pf)() throw(int); // ill-formed
49
- ```
50
-
51
- A type denoted in an *exception-specification* shall not denote an
52
- incomplete type or an rvalue reference type. A type denoted in an
53
- *exception-specification* shall not denote a pointer or reference to an
54
- incomplete type, other than *cv* `void*`. A type cv `T`, “array of `T`”,
55
- or “function returning `T`” denoted in an *exception-specification* is
56
- adjusted to type `T`, “pointer to `T`”, or “pointer to function
57
- returning `T`”, respectively.
58
-
59
- Two *exception-specification*s are *compatible* if:
60
-
61
- - both are non-throwing (see below), regardless of their form,
62
- - both have the form `noexcept(`*constant-expression*`)` and the
63
- *constant-expression*s are equivalent, or
64
- - both are *dynamic-exception-specification*s that have the same set of
65
- adjusted types.
66
-
67
- If any declaration of a function has an *exception-specification* that
68
- is not a *noexcept-specification* allowing all exceptions, all
69
- declarations, including the definition and any explicit specialization,
70
- of that function shall have a compatible *exception-specification*. If
71
- any declaration of a pointer to function, reference to function, or
72
- pointer to member function has an *exception-specification*, all
73
- occurrences of that declaration shall have a compatible
74
- *exception-specification* In an explicit instantiation an
75
- *exception-specification* may be specified, but is not required. If an
76
- *exception-specification* is specified in an explicit instantiation
77
- directive, it shall be compatible with the *exception-specification*s of
78
- other declarations of that function. A diagnostic is required only if
79
- the *exception-specification*s are not compatible within a single
80
- translation unit.
81
-
82
- If a virtual function has an *exception-specification*, all
83
  declarations, including the definition, of any function that overrides
84
- that virtual function in any derived class shall only allow exceptions
85
- that are allowed by the *exception-specification* of the base class
86
- virtual function.
 
 
87
 
88
  ``` cpp
89
  struct B {
90
- virtual void f() throw (int, double);
91
  virtual void g();
 
92
  };
93
 
94
  struct D: B {
95
  void f(); // ill-formed
96
- void g() throw (int); // OK
 
97
  };
98
  ```
99
 
100
- The declaration of `D::f` is ill-formed because it allows all
101
- exceptions, whereas `B::f` allows only `int` and `double`. A similar
102
- restriction applies to assignment to and initialization of pointers to
103
- functions, pointers to member functions, and references to functions:
104
- the target entity shall allow at least the exceptions allowed by the
105
- source value in the assignment or initialization.
106
 
107
- ``` cpp
108
- class A { /* ... */ };
109
- void (*pf1)(); // no exception specification
110
- void (*pf2)() throw(A);
111
-
112
- void f() {
113
- pf1 = pf2; // OK: pf1 is less restrictive
114
- pf2 = pf1; // error: pf2 is more restrictive
115
- }
116
- ```
117
-
118
- In such an assignment or initialization, *exception-specification*s on
119
- return types and parameter types shall be compatible. In other
120
- assignments or initializations, *exception-specification*s shall be
121
- compatible.
122
-
123
- An *exception-specification* can include the same type more than once
124
- and can include classes that are related by inheritance, even though
125
- doing so is redundant. An *exception-specification* can also include the
126
- class `std::bad_exception` ([[bad.exception]]).
127
-
128
- A function is said to *allow* an exception of type `E` if the
129
- *constant-expression* in its *noexcept-specification* evaluates to
130
- `false` or its *dynamic-exception-specification* contains a type `T` for
131
- which a handler of type `T` would be a match ([[except.handle]]) for an
132
- exception of type `E`.
133
 
134
  Whenever an exception is thrown and the search for a handler (
135
- [[except.handle]]) encounters the outermost block of a function with an
136
- *exception-specification* that does not allow the exception, then,
 
137
 
138
- - if the *exception-specification* is a
139
- *dynamic-exception-specification*, the function `std::unexpected()` is
140
- called ([[except.unexpected]]),
141
- - otherwise, the function `std::terminate()` is called (
142
- [[except.terminate]]).
143
 
144
  ``` cpp
145
- class X { };
146
- class Y { };
147
- class Z: public X { };
148
- class W { };
149
 
150
- void f() throw (X, Y) {
151
- int n = 0;
152
- if (n) throw X(); // OK
153
- if (n) throw Z(); // also OK
154
- throw W(); // will call std::unexpected()
155
  }
156
  ```
157
 
158
- A function can have multiple declarations with different non-throwing
159
- *exception-specification*s; for this purpose, the one on the function
160
- definition is used.
161
 
162
- The function `unexpected()` may throw an exception that will satisfy the
163
- *exception-specification* for which it was invoked, and in this case the
164
- search for another handler will continue at the call of the function
165
- with this *exception-specification* (see  [[except.unexpected]]), or it
166
- may call `std::terminate()`.
167
 
168
- An implementation shall not reject an expression merely because when
169
- executed it throws or might throw an exception that the containing
170
- function does not allow.
171
 
172
- ``` cpp
173
- extern void f() throw(X, Y);
 
 
 
 
 
 
 
 
 
 
 
 
 
174
 
175
- void g() throw(X) {
176
- f(); // OK
177
- }
178
- ```
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
179
 
180
- the call to `f` is well-formed even though when called, `f` might throw
181
- exception `Y` that `g` does not allow.
 
 
182
 
183
- A function with no *exception-specification* or with an
184
- *exception-specification* of the form
185
- `noexcept(`*constant-expression*`)` where the *constant-expression*
186
- yields `false` allows all exceptions. An *exception-specification* is
187
- *non-throwing* if it is of the form `throw()`, `noexcept`, or
188
- `noexcept(`*constant-expression*`)` where the *constant-expression*
189
- yields `true`. A function with a non-throwing *exception-specification*
190
- does not allow any exceptions.
191
 
192
- An *exception-specification* is not considered part of a function’s
193
- type.
 
194
 
195
- An inheriting constructor ([[class.inhctor]]) and an implicitly
196
- declared special member function (Clause  [[special]]) have an
197
- *exception-specification*. If `f` is an inheriting constructor or an
198
- implicitly declared default constructor, copy constructor, move
199
- constructor, destructor, copy assignment operator, or move assignment
200
- operator, its implicit *exception-specification* specifies the *type-id*
201
- `T` if and only if `T` is allowed by the *exception-specification* of a
202
- function directly invoked by `f`’s implicit definition; `f` allows all
203
- exceptions if any function it directly invokes allows all exceptions,
204
- and `f` has the *exception-specification* `noexcept(true)` if every
205
- function it directly invokes allows no exceptions. It follows that `f`
206
- has the *exception-specification* `noexcept(true)` if it invokes no
207
- other functions. An instantiation of an inheriting constructor template
208
- has an implied *exception-specification* as if it were a non-template
209
- inheriting constructor.
210
 
211
  ``` cpp
212
  struct A {
213
- A();
214
- A(const A&) throw();
215
- A(A&&) throw();
216
- ~A() throw(X);
217
  };
218
  struct B {
219
  B() throw();
220
- B(const B&) = default; // Declaration of B::B(const B&) noexcept(true)
221
- B(B&&) throw(Y);
222
- ~B() throw(Y);
223
  };
 
224
  struct D : public A, public B {
225
- // Implicit declaration of D::D();
226
- // Implicit declaration of D::D(const D&) noexcept(true);
227
- // Implicit declaration of D::D(D&&) throw(Y);
228
- // Implicit declaration of D::~D() throw(X, Y);
 
229
  };
230
  ```
231
 
232
- Furthermore, if `A::~A()` or `B::~B()` were virtual, `D::~D()` would not
233
- be as restrictive as that of `A::~A`, and the program would be
234
- ill-formed since a function that overrides a virtual function from a
235
- base class shall have an *exception-specification* at least as
236
- restrictive as that in the base class.
237
 
238
- A deallocation function ([[basic.stc.dynamic.deallocation]]) with no
239
- explicit *exception-specification* is treated as if it were specified
240
- with `noexcept(true)`.
241
 
242
- An *exception-specification* is considered to be *needed* when:
243
 
244
  - in an expression, the function is the unique lookup result or the
245
  selected member of a set of overloaded functions ([[basic.lookup]],
246
  [[over.match]], [[over.over]]);
247
  - the function is odr-used ([[basic.def.odr]]) or, if it appears in an
248
  unevaluated operand, would be odr-used if the expression were
249
  potentially-evaluated;
250
- - the *exception-specification* is compared to that of another
251
- declaration (e.g., an explicit specialization or an overriding virtual
252
- function);
253
  - the function is defined; or
254
- - the *exception-specification* is needed for a defaulted special member
255
- function that calls the function. A defaulted declaration does not
256
- require the *exception-specification* of a base member function to be
257
- evaluated until the implicit *exception-specification* of the derived
258
- function is needed, but an explicit *exception-specification* needs
259
- the implicit *exception-specification* to compare against.
 
260
 
261
- The *exception-specification* of a defaulted special member function is
262
  evaluated as described above only when needed; similarly, the
263
- *exception-specification* of a specialization of a function template or
264
  member function of a class template is instantiated only when needed.
265
 
266
- In a *dynamic-exception-specification*, a *type-id* followed by an
267
- ellipsis is a pack expansion ([[temp.variadic]]).
268
-
269
- The use of *dynamic-exception-specification*s is deprecated (see Annex 
270
- [[depr]]).
271
-
 
1
  ## Exception specifications <a id="except.spec">[[except.spec]]</a>
2
 
3
+ The predicate indicating whether a function cannot exit via an exception
4
+ is called the *exception specification* of the function. If the
5
+ predicate is false, the function has a *potentially-throwing exception
6
+ specification*, otherwise it has a *non-throwing exception
7
+ specification*. The exception specification is either defined
8
+ implicitly, or defined explicitly by using a *noexcept-specifier* as a
9
+ suffix of a function declarator ([[dcl.fct]]).
10
 
11
  ``` bnf
12
+ noexcept-specifier:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
13
  'noexcept' '(' constant-expression ')'
14
  'noexcept'
15
+ 'throw' '(' ')'
16
  ```
17
 
18
+ In a *noexcept-specifier*, the *constant-expression*, if supplied, shall
19
+ be a contextually converted constant expression of type `bool` (
20
+ [[expr.const]]); that constant expression is the exception specification
21
+ of the function type in which the *noexcept-specifier* appears. A `(`
22
+ token that follows `noexcept` is part of the *noexcept-specifier* and
23
+ does not commence an initializer ([[dcl.init]]). The
24
+ *noexcept-specifier* `noexcept` without a *constant-expression* is
25
+ equivalent to the *noexcept-specifier* `noexcept(true)`. The
26
+ *noexcept-specifier* `throw()` is deprecated ([[depr.except.spec]]),
27
+ and equivalent to the *noexcept-specifier* `noexcept(true)`.
28
+
29
+ If a declaration of a function does not have a *noexcept-specifier*, the
30
+ declaration has a potentially throwing exception specification unless it
31
+ is a destructor or a deallocation function or is defaulted on its first
32
+ declaration, in which cases the exception specfication is as specified
33
+ below and no other declaration for that function shall have a
34
+ *noexcept-specifier*. In an explicit instantiation ([[temp.explicit]])
35
+ a *noexcept-specifier* may be specified, but is not required. If a
36
+ *noexcept-specifier* is specified in an explicit instantiation
37
+ directive, the exception specification shall be the same as the
38
+ exception specification of all other declarations of that function. A
39
+ diagnostic is required only if the exception specifications are not the
40
+ same within a single translation unit.
41
+
42
+ If a virtual function has a non-throwing exception specification, all
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
43
  declarations, including the definition, of any function that overrides
44
+ that virtual function in any derived class shall have a non-throwing
45
+ exception specification, unless the overriding function is defined as
46
+ deleted.
47
+
48
+ [*Example 1*:
49
 
50
  ``` cpp
51
  struct B {
52
+ virtual void f() noexcept;
53
  virtual void g();
54
+ virtual void h() noexcept = delete;
55
  };
56
 
57
  struct D: B {
58
  void f(); // ill-formed
59
+ void g() noexcept; // OK
60
+ void h() = delete; // OK
61
  };
62
  ```
63
 
64
+ The declaration of `D::f` is ill-formed because it has a
65
+ potentially-throwing exception specification, whereas `B::f` has a
66
+ non-throwing exception specification.
 
 
 
67
 
68
+ *end example*]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
69
 
70
  Whenever an exception is thrown and the search for a handler (
71
+ [[except.handle]]) encounters the outermost block of a function with a
72
+ non-throwing exception specification, the function `std::terminate()` is
73
+ called ([[except.terminate]]).
74
 
75
+ [*Note 1*: An implementation shall not reject an expression merely
76
+ because, when executed, it throws or might throw an exception from a
77
+ function with a non-throwing exception specification. — *end note*]
78
+
79
+ [*Example 2*:
80
 
81
  ``` cpp
82
+ extern void f(); // potentially-throwing
 
 
 
83
 
84
+ void g() noexcept {
85
+ f(); // valid, even if f throws
86
+ throw 42; // valid, effectively a call to std::terminate
 
 
87
  }
88
  ```
89
 
90
+ The call to `f` is well-formed even though, when called, `f` might throw
91
+ an exception.
 
92
 
93
+ *end example*]
 
 
 
 
94
 
95
+ An expression `e` is *potentially-throwing* if
 
 
96
 
97
+ - `e` is a function call ([[expr.call]]) whose *postfix-expression* has
98
+ a function type, or a pointer-to-function type, with a
99
+ potentially-throwing exception specification, or
100
+ - `e` implicitly invokes a function (such as an overloaded operator, an
101
+ allocation function in a *new-expression*, a constructor for a
102
+ function argument, or a destructor if `e` is a full-expression (
103
+ [[intro.execution]])) that is potentially-throwing, or
104
+ - `e` is a *throw-expression* ([[expr.throw]]), or
105
+ - `e` is a `dynamic_cast` expression that casts to a reference type and
106
+ requires a runtime check ([[expr.dynamic.cast]]), or
107
+ - `e` is a `typeid` expression applied to a (possibly parenthesized)
108
+ built-in unary `*` operator applied to a pointer to a polymorphic
109
+ class type ([[expr.typeid]]), or
110
+ - any of the immediate subexpressions ([[intro.execution]]) of `e` is
111
+ potentially-throwing.
112
 
113
+ An implicitly-declared constructor for a class `X`, or a constructor
114
+ without a *noexcept-specifier* that is defaulted on its first
115
+ declaration, has a potentially-throwing exception specification if and
116
+ only if any of the following constructs is potentially-throwing:
117
+
118
+ - a constructor selected by overload resolution in the implicit
119
+ definition of the constructor for class `X` to initialize a
120
+ potentially constructed subobject, or
121
+ - a subexpression of such an initialization, such as a default argument
122
+ expression, or,
123
+ - for a default constructor, a default member initializer.
124
+
125
+ [*Note 2*: Even though destructors for fully-constructed subobjects are
126
+ invoked when an exception is thrown during the execution of a
127
+ constructor ([[except.ctor]]), their exception specifications do not
128
+ contribute to the exception specification of the constructor, because an
129
+ exception thrown from such a destructor would call `std::terminate`
130
+ rather than escape the constructor ([[except.throw]],
131
+ [[except.terminate]]). — *end note*]
132
 
133
+ The exception specification for an implicitly-declared destructor, or a
134
+ destructor without a *noexcept-specifier*, is potentially-throwing if
135
+ and only if any of the destructors for any of its potentially
136
+ constructed subojects is potentially throwing.
137
 
138
+ The exception specification for an implicitly-declared assignment
139
+ operator, or an assignment-operator without a *noexcept-specifier* that
140
+ is defaulted on its first declaration, is potentially-throwing if and
141
+ only if the invocation of any assignment operator in the implicit
142
+ definition is potentially-throwing.
 
 
 
143
 
144
+ A deallocation function ([[basic.stc.dynamic.deallocation]]) with no
145
+ explicit *noexcept-specifier* has a non-throwing exception
146
+ specification.
147
 
148
+ [*Example 3*:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
149
 
150
  ``` cpp
151
  struct A {
152
+ A(int = (A(5), 0)) noexcept;
153
+ A(const A&) noexcept;
154
+ A(A&&) noexcept;
155
+ ~A();
156
  };
157
  struct B {
158
  B() throw();
159
+ B(const B&) = default; // implicit exception specification is noexcept(true)
160
+ B(B&&, int = (throw Y(), 0)) noexcept;
161
+ ~B() noexcept(false);
162
  };
163
+ int n = 7;
164
  struct D : public A, public B {
165
+ int * p = new int[n];
166
+ // D::D() potentially-throwing, as the new operator may throw bad_alloc or bad_array_new_length
167
+ // D::D(const D&) non-throwing
168
+ // D::D(D&&) potentially-throwing, as the default argument for B's constructor may throw
169
+ // D::~D() potentially-throwing
170
  };
171
  ```
172
 
173
+ Furthermore, if `A::~A()` were virtual, the program would be ill-formed
174
+ since a function that overrides a virtual function from a base class
175
+ shall not have a potentially-throwing exception specification if the
176
+ base class function has a non-throwing exception specification.
 
177
 
178
+ *end example*]
 
 
179
 
180
+ An exception specification is considered to be *needed* when:
181
 
182
  - in an expression, the function is the unique lookup result or the
183
  selected member of a set of overloaded functions ([[basic.lookup]],
184
  [[over.match]], [[over.over]]);
185
  - the function is odr-used ([[basic.def.odr]]) or, if it appears in an
186
  unevaluated operand, would be odr-used if the expression were
187
  potentially-evaluated;
188
+ - the exception specification is compared to that of another declaration
189
+ (e.g., an explicit specialization or an overriding virtual function);
 
190
  - the function is defined; or
191
+ - the exception specification is needed for a defaulted special member
192
+ function that calls the function. \[*Note 3*: A defaulted declaration
193
+ does not require the exception specification of a base member function
194
+ to be evaluated until the implicit exception specification of the
195
+ derived function is needed, but an explicit *noexcept-specifier* needs
196
+ the implicit exception specification to compare
197
+ against. — *end note*]
198
 
199
+ The exception specification of a defaulted special member function is
200
  evaluated as described above only when needed; similarly, the
201
+ *noexcept-specifier* of a specialization of a function template or
202
  member function of a class template is instantiated only when needed.
203