<html>
<head>
<title>N4285: 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>
N4285<br/>
revision of N4133<br/>
Jens Maurer &lt;Jens.Maurer@gmx.net><br>
2014-11-07

<h1>N4285: 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 5.3.7 expr.unary.noexcept paragraph 3:

<blockquote>

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

<li>a potentially-evaluated <em>throw-expression</em> (<del>15.1
except.throw</del> <ins>5.17 expr.throw</ins>),</li>

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

</blockquote>

Change in 5.16 expr.cond paragraph 2:

<blockquote>
<ul>

<li>The second or the third operand (but not both) is a (possibly
parenthesized) <em>throw-expression</em> (<del>15.1 except.throw</del>
<ins>5.17 expr.throw</ins>); the result is of the type and value
category of the other.</li>

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

</blockquote>


Change in 5.19 expr.const paragraph 2:

<blockquote>
<ul>
<li>...</li>

<li>a <em>throw-expression</em> (<del>15.1 except.throw</del>
<ins>5.17 expr.throw</ins>).</li>

</ul>
</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.8 class.copy paragraph 31:

<blockquote>

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


<li>in a <em>throw-expression</em> <ins>(5.17 expr.throw)</ins>, when
the operand is the name of a non-volatile automatic object (other than
a function or catch-clause parameter) whose scope does not extend
beyond the end of the innermost enclosing try-block (if there is one),
the copy/move operation from the operand to the exception object (15.1
except.throw) can be omitted by constructing the automatic object
directly into the exception object</li>

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

</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 <ins>(15.1 except.throw)</ins>; 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<del>;
therefore, the value of <code>std::uncaught_exception()</code>
will again be true</del>.  [ 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>, 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) 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>

Change in 15.4 except.spec paragraph 5:

<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 <ins>of type E</ins> 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 <del>the
exception</del> <ins>E</ins>, 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>

Remove 15.4 except.spec paragraph 10:

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

</blockquote>

Remove 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 <ins>of a type</ins> 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.1 except.terminate paragraph 1:

<blockquote>

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

<li>when a <em>throw-expression</em> <ins>(5.17 expr.throw)</ins> with
no operand attempts to rethrow an exception and no exception is being
handled (15.1 except.throw), or</li>

<li>...</li>

</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 <ins>of a
type</ins> 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 <ins>of a type</ins> that the
<em>dynamic-exception-specification</em> does not allow<ins>,</ins>
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 an exception
of one of the listed types</ins> <del>the listed exceptions ill be
thrown</del>. If the <em>dynamic-exception-specification</em> includes
the type <code>std::bad_exception</code> then any exception
<ins>type</ins> 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>
