<html>
<head>
<title>N4133: Cleanup for exception-specification and throw-expression</title>

<style type="text/css">
  ins { text-decoration:underline; font-weight:bold; background-color:#A0FFA0 }
  .new { text-decoration:none; font-weight:bold; background-color:#D0FFD0 }
  del { text-decoration:line-through; background-color:#FFA0A0 }
  strong { font-weight: inherit; color: #2020ff }
</style>

</head>

<body>
N4133<br/>
Jens Maurer<br>
2014-09-10

<h1>N4133: Cleanup for <em>exception-specification</em> and <em>throw-expression</em></h1>

<h2>Introduction</h2>

This paper proposes to adjust the wording for exceptions to achieve
the following goals:

<ul>

<li>Exception specifications as a semantic concept are separated from
the grammar term <em>exception-specification</em></li>

<li>The description of <em>throw-expression</em> is integrated into
clause 5.</li>

</ul>

<p>
The changes are intended to be editorial only, not changing
semantics. Due to the size of the changes, it seems prudent to have a
full CWG review for these instead of leaving the issue to the project
editor alone.
</p>


<h2>Miscellaneous</h2>

Change in 3.7.4.1 basic.stc.dynamic.allocation paragraph 3:

<blockquote>
... If an allocation function <del>declared with</del> <ins>that
has</ins> a non-throwing <del><em>exception-specification</em></del>
<ins>exception specification</ins> (15.4 except.spec) fails to
allocate storage, it shall return a null pointer. Any other allocation
function that fails to allocate storage shall indicate failure only by
throwing an exception (15.1 except.throw) of a type that would match a
handler (15.3) of type <code>std::bad_alloc</code> (18.6.2.1).

</blockquote>

Change in 5.3.4 expr.new paragraph 15:

<blockquote>
[ Note: unless an allocation function <del>is declared with</del>
<ins>has</ins> a non-throwing
<del><em>exception-specification</em></del> <ins>exception
specification</ins> (15.4 except.spec), it indicates failure to
allocate storage by throwing a <code>std::bad_alloc</code> exception
(<ins>3.7.4.1 basic.stc.dynamic.allocation,</ins> Clause 15 except,
18.6.2.1); it returns a non-null pointer otherwise. If the allocation
function <del>is declared with</del> <ins>has</ins> a non-throwing
<del><em>exception-specification</em></del> <ins>exception
specification</ins>, it returns null to indicate failure to allocate
storage and a non-null pointer otherwise. -- end note ] If the
allocation function returns null, initialization shall not be done,
the deallocation function shall not be called, and the value of the
new-expression shall be null.

</blockquote>

Change in 8.4.2 dcl.fct.def.default paragraph 2:

<blockqouote>
<ul>
<li>...</li>

<li>it <del>is implicitly considered to have the same
<em>exception-specification</em></del> <ins>has the same exception
specification</ins> as if it had been implicitly declared (15.4
except.spec).</li>

</ul>

</blockquote>

Change in 8.4.2 dcl.fct.def.default paragraph 3:

<blockquote>
If a function that is explicitly defaulted <del>has an explicit
<em>exception-specification</em></del> <ins>is declared with an
exception specification</ins> that is not compatible (15.4
except.spec) with the <del><em>exception-specification</em></del>
<ins>exception specification</ins> on the implicit declaration, then
...

</blockquote>

Change in 12.1 class.ctor paragraph 5:

<blockquote>

... [ Note: An implicitly-declared default constructor has an
<del><em>exception-specification</em></del> <ins>exception
specification</ins> (15.4 except.spec). An explicitly-defaulted
definition might have an implicit
<del><em>exception-specification</em></del> <ins>exception
specification</ins>, see 8.4 dcl.fct.def. -- end note ]

</blockquote>

Change in 12.4 class.dtor paragraph 3:

<blockquote>
A declaration of a destructor that does not have an
<em>exception-specification</em> <del>is implicitly considered to have
the same exception-specification as an implicit declaration</del>
<ins>has the same exception specification as if had been implicitly
declared</ins> (15.4 except.spec).

</blockquote>

Change in 12.5 class.free paragraph:

<blockquote>
[ Note: If a deallocation function has no explicit
<em>exception-specification</em>, it <del>is treated as if it were
specified with <code>noexcept(true)</code></del> <ins>has a
non-throwing exception specification</ins> (15.4 except.spec). --
end note ]

</blockquote>

Change in 12.8 class.copy paragarph 14:

<blockquote>
... [ Note: An implicitly-declared copy/move constructor has an
<del><em>exception-specification</em></del> <ins>implied exception
specification</ins> (15.4 except.spec). -- end note ]

</blockquote>

Change in 12.9 class.inhctor paragraph 3:

<blockquote>
[ Note: Default arguments are not inherited. An
<del><em>exception-specification</em></del> <ins>exception
specification</ins> is implied as specified in 15.4 except.spec. --
end note ]


</blockquote>


<h2>5.17 Throwing an exception [expr.throw]</h2>

<p>
Insert the section immediately before 5.17 [expr.ass], renumbering the
sections that follow.
</p>

Move the following grammar production from 15 except paragraph 1:
<blockquote class="new">
<pre>
<em>throw-expression</em>:
      <code>throw</code> <em>assignment-expression</em><sub>opt</sub>
</pre>
</blockquote>

Move the following from 15 except paragraph 2:

<blockquote class="new">
A <em>throw-expression</em> is of type <code>void</code>.
</blockquote>

Move the following sentence from 15.1 except.throw paragraph 3:

<blockquote class="new">
Evaluating a <em>throw-expression</em> with an operand throws an
exception; the type of the exception object is determined by removing
any top-level cv-qualifiers from the static type of the operand and
adjusting the type from "array of T" or "function returning T" to
"pointer to T" or "pointer to function returning T," respectively.

</blockquote>

Move from 15.1 except.throw paragraphs 8 and 9, changing the highlighted parts::

<blockquote class="new">
<p>
A <em>throw-expression</em> with no operand rethrows the currently
handled exception (15.3 except.handle). The exception is reactivated
with the existing exception object; no new exception object is
created. The exception is no longer considered to be caught;
therefore, the value of <code>std::uncaught_exception()</code>
<ins>(15.5.3 except.uncaught)</ins> will again be true.  [ Example:
code that must be executed because of an exception yet cannot
completely handle the exception can be written like this:

<pre>
   try {
       // ...
   } catch (...) {        // catch all exceptions
     // respond (partially) to exception
     throw;               // pass the exception to some
                          // other handler
   }
</pre>
 -- end example ]

<p>
If no exception is presently being handled, <del>executing</del>
<ins>evaluating</ins> a <em>throw-expression</em> with no operand
calls <code>std:: terminate()</code> (15.5.1 except.terminate).
</p>

</blockquote>


<h2>Clause 15  Exceptions</h2>

Remove from 15 except paragraph 1:

<blockquote>
<pre>
<del><em>throw-expression</em>:
      throw <em>assignment-expression</em><sub>opt</sub>
</del>
</pre>
</blockquote>

Remove from 15 except paragraph 2:

<blockquote>
A <em>try-block</em> is a statement (Clause 6 stmt). <del>A
<em>throw-expression</em> is of type void.</del> [ Note: Within this
Clause "try block" is taken to mean both try-block and
function-try-block. -- end note ]

</blockquote>

Change in 15.1 except.throw paragraph 1:

<blockquote>
Throwing an exception transfers control to a handler. [ Note: An
exception can be thrown from one of the following contexts:
<em>throw-expression</em> (<del>see below</del><ins>5.17
expr.throw</ins>), allocation functions (3.7.4.1),
<code>dynamic_cast</code> (5.2.7), <code>typeid</code> (5.2.8),
<em>new-expression</em> (5.3.4), and standard library functions
(17.5.1.4). -- end note ] ...

</blockquote>

Remove from 15.1 expr.throw paragraph 3:

<blockquote>
... <del>Evaluating a <em>throw-expression</em> with an operand ...,
respectively.</del>

</blockquote>


Remove from 15.1 except throw paragraphs 8 and 9:

<blockquote>
<p>
<del>A <em>throw-expression</em> with no operand ...</del>
</p>

<p>
<del>If no exception is presently...</el>
</p>

</blockquote>


Change in 15.4 except.spec paragraph 1:

<blockquote>
<ins>The <em>exception specification</em> of a function is a (possibly
empty) set of types, indicating that the function might exit via an
exception that matches a handler of one of the types in the set; the
(conceptual) set of all types is used to denote that the function
might exit via an exception of arbitrary type. If the set is empty,
the function is said to have a <em>non-throwing exception
specification</em>. The exception specification is either defined
explicitly </ins>

<del>A function declaration lists exceptions that its function might
directly or indirectly throw</del> by using an
<em>exception-specification</em> as a suffix of <del>its</del> <ins>a
function declaration's</ins> declarator<ins> (8.3.5 dcl.fct) or
implicitly</ins>. ...

<del>A <em>noexcept-specification</em> <code>noexcept</code> is
equivalent to <code>noexcept(true)</code>.</del>

</blockquote>

Replace 15.4 except.spec paragraph 2:

<blockquote>
... A type denoted in <del>an <em>exception-specification</em></del>
<ins>a <em>dynamic-exception-specification</em></ins> shall not denote
an incomplete type or an rvalue reference type. A type denoted in
<del>an <em>exception-specification</em></del>
<ins>a <em>dynamic-exception-specification</em></ins> shall not denote a
pointer or reference to an incomplete type, other than
<del><var>cv</var> void*</del> <ins>"pointer to <var>cv</var>
<code>void</code>"</ins>. A type <var>cv</var> T, "array of T", or
"function returning T" denoted in <del>an
<em>exception-specification</em></del> <ins>a
<em>dynamic-exception-specification</em></ins> is adjusted to type T,
"pointer to T", or "pointer to function returning T",
respectively. <ins>A <em>dynamic-exception-specification</em> denotes
an exception specification that is the set of adjusted types specified
thereby.</ins>

</blockquote>


Change in 15.4 except.spec paragraph 3:

<blockquote>
<ins>The <em>exception-specification</em> <code>noexcept</code> or
<code>noexcept(<em>constant-expression</em>)</code>, where the
<em>constant-expression</em> yields <code>true</code>, denotes an
exception specification that is the empty set.  The
<em>exception-specification</em>
<code>noexcept(<em>constant-expression</em>)</code>, where the
<em>constant-expression</em> yields <code>false</code>, <strong>or the
absence of an <em>exception-specification</em> in a function
declarator other than that for a destructor (12.4 class.dtor) or a
deallocation function (3.7.4.2
basic.stc.dynamic.deallocation)</strong> denotes an exception
specification that is the set of all types.</ins>

<p>

Two <em>exception-specification</em>s are <em>compatible</em>
if<del>:</del> <ins>the sets of types they denote are the same.</ins>

<ul>

<li><del>both are non-throwing (see below), regardless of their
form,</del></li>

<li><del>both have the form noexcept(constant-expression) and the
constant-expressions are equivalent, or</del></li>

<li><del>both are <em>dynamic-exception-specification</em>s that have
the same set of adjusted types.</del></li>
</ul>

</blockquote>

<strong>Change in 15.4 except.spec paragraph 5:</strong>

<blockquote>
If a virtual function has an
<del><em>exception-specification</em></del> <ins>exception
specification</ins>, all declarations, including the definition, of
any function that overrides that virtual function in any derived class
shall only allow exceptions that are allowed by the
<del><em>exception-specification</em></del> <ins>exception
specification</ins> of the base class virtual function. [ Example:
... ]

</blockquote>


Change in 15.4 except.spec paragraph 8:

<blockquote>
A function is said to allow an exception of type <code>E</code> if
<del>the <em>constant-expression</em> in its
<em>noexcept-specification</em> evaluates to false or its
<em>dynamic-exception-specification</em></del> <ins>its exception
specification</ins> contains a type T for which a handler of type T
would be a match (15.3 except.handle) for an exception of type
<code>E</code>.  <ins>A function is said to allow all exceptions if
its exception specification is the set of all types.</ins>

</blockquote>

Change in 15.4 except.spec paragraph 9:

<blockquote>
Whenever an exception is thrown and the search for a handler (15.3
except.handle) encounters the outermost block of a function with an
<del><em>exception-specification</em></del> <ins>exception
specification</ins> that does not allow the exception, then,
<ul>

<li>if the <ins>function definition has</ins>
<del><em>exception-specification</em> is</del> a
<em>dynamic-exception-specification</em>, the function
<code>std::unexpected()</code> is called (15.5.2),</li>

<li>otherwise, the function <code>std::terminate()</code> is called
(15.5.1).</li>

</ul>

...

[ Note: A function can have multiple declarations with different
non-throwing <em>exception-specifications</em>; for this purpose, the
one on the function definition is used. -- end note ]

</blockquote>

Change in 15.4 except.spec paragraph 10:

<blockquote>
The function <code><ins>std::</ins>unexpected()</code> may throw an
exception that <del>will satisfy the
<em>exception-specification</em></del> <ins>is allowed by the
exception specification of the function</ins> for which it was
invoked, and in this case the search for another handler will continue
at the call of <del>the</del> <ins>that</ins> function <del>with this
<em>exception-specification</em></del> (see 15.5.2), or it may call
<code>std::terminate()</code>.

</blockquote>

Change in 15.4 except.spec paragraph 12:

<blockquote>
<del>A function with no <em>exception-specification</em> or with an
<em>exception-specification</em> of the form
<code>noexcept(<em>constant-expression</em> )</code> where the
<em>constant-expression</em> yields false allows all exceptions. An
<em>exception-specification</em> is non-throwing if it is of the form
<code>throw()</code>, <code>noexcept</code>, or
<code>noexcept(<em>constant-expression</em> )</code> where the
<em>constant-expression</em> yields true. A function with a
non-throwing <em>exception-specification</em> does not allow any
exceptions.</del>

</blockquote>

Change in 15.4 except.spec paragraph 13:

<blockquote>
<ins>[ Note:</ins> An <del><em>exception-specification</em></del>
<ins>exception specification</ins> is not considered part of a
function's type<ins>; see 8.3.5 dcl.fct. -- end note ]</ins>

</blockquote>

Change in 15.4 except.spec paragraph 15:

<blockquote>
A deallocation function (3.7.4.2) with no explicit
<em>exception-specification</em> <ins>has an exception specification
that is the empty set</ins> <del>is treated as if it were specified
with <code>noexcept(true)</code></del>.

</blockquote>

Change in 15.5.1 except.terminate paragraph 1:

<blockquote>
<ul>

<li>...</li>

<li>when <code>std::unexpected</code> <del>throws</del> <ins>exits
via</ins> an exception which is not allowed by the previously violated
<del><em>dynamic-exception-specification</em></del> <ins>exception
specification</ins>, and <code>std::bad_exception</code> is not
included in that <del><em>dynamic-exception-specification</em></del>
<ins>exception specification</ins> (15.5.2 except.unexpected), or</li>

<li>...</li>

</ul>

</blockquote>

Change in 15.5.2 except.unexpected paragraph 1:

<blockquote>
If a function with a <em>dynamic-exception-specification</em>
<del>throws</del> <ins>exits via</ins> an exception that is not
<del>listed in the <em>dynamic-exception-specification</em></del>
<ins>allowed by its exception specification</ins>, the function
<code>std::unexpected()</code> is called (D.11) immediately after
completing the stack unwinding for the former function.

</blockquote>

Change in 15.5.2 except.unexpected paragraph 3:

<blockquote>
.... If it <del>throws or rethrows</del> <ins>exits via</ins> an
exception that the <em>dynamic-exception-specification</em> does not
allow then the following happens: If the
<em>dynamic-exception-specification</em> does not include the class
<code>std::bad_exception</code> (18.8.2) then the function
<code>std::terminate()</code> is called, otherwise the thrown
exception is replaced by an implementation-defined object of
<del>the</del> type <code>std::bad_exception</code> and the search for
another handler will continue at the call of the function whose
<em>dynamic-exception-specification</em> was violated.

<p>

<ins> [ Note:</ins> Thus, a <em>dynamic-exception-specification</em>
guarantees that <ins>a function exits</ins> only <ins>via</ins> the
listed exceptions <del>will be thrown</del>. If the
<em>dynamic-exception-specification</em> includes the type
<code>std::bad_exception</code> then any exception not on the list may
be replaced by <code>std::bad_exception</code> within the function
<code>std::unexpected()</code>.<ins> -- end note ]</ins>

</blockquote>


Change in 17.6.5.12 res.on.exception.handling paragraph 1:

<blockquote>
Any of the functions defined in the C++ standard library can report a
failure by throwing an exception of a type described in its
<b>Throws:</b> paragraph. An implementation may strengthen the
<del><em>exception-specification</em></del> <ins>exception
specification</ins> for a non-virtual function by adding a
non-throwing <em>noexcept-specification</em>.


</body>
</html>
