This is an unofficial snapshot of the ISO/IEC JTC1 SC22 WG21 Core Issues List revision 113d. See http://www.open-std.org/jtc1/sc22/wg21/ for the official list.

2024-03-20


1431. Exceptions from other than throw-expressions

Section: Clause 14  [except]     Status: CD3     Submitter: Nikolay Ivchenkov     Date: 2011-12-16

[Moved to DR at the October, 2012 meeting.]

There are a number of places in the Standard that appear to assume that exceptions are only thrown by throw-expressions. Various other constructs, such as dynamic_casts, typeid, new-expressions, etc., can also throw exceptions, so a more general term should be coined and applied in place of throw-expression wherever necessary.

Proposed resolution (February, 2012):

  1. Change 6.7.5.5.2 [basic.stc.dynamic.allocation] paragraph 3 as follows:

  2. ...Any other allocation function that fails to allocate storage shall indicate failure only by throwing an exception (14.2 [except.throw]) of a type that would match a handler (14.4 [except.handle]) of type std::bad_alloc (17.6.4.1 [bad.alloc]).
  3. Change 6.7.5.5.2 [basic.stc.dynamic.allocation] paragraph 4 as follows:

  4. ...[Note: In particular, a global allocation function is not called to allocate storage for objects with static storage duration (6.7.5.2 [basic.stc.static]), for objects or references with thread storage duration (6.7.5.3 [basic.stc.thread]), for objects of type std::type_info (7.6.1.8 [expr.typeid]), or for the copy of an object thrown by a throw expression an exception object (14.2 [except.throw]). —end note]
  5. Change 7.6.1.7 [expr.dynamic.cast] paragraph 9 as follows:

  6. The value of a failed cast to pointer type is the null pointer value of the required result type. A failed cast to reference type throws an exception (14.2 [except.throw]) of a type that would match a handler (14.4 [except.handle]) of type std::bad_cast (17.7.4 [bad.cast]).
  7. Change 7.6.1.8 [expr.typeid] paragraph 2 as follows:

  8. ...If the glvalue expression is obtained by applying the unary * operator to a pointer68 and the pointer is a null pointer value (7.3.12 [conv.ptr]), the typeid expression throws the an exception (14.2 [except.throw]) of a type that would match a handler of type std::bad_typeid exception (17.7.5 [bad.typeid]).
  9. Change 7.6.2.8 [expr.new] paragraph 7 as follows:

  10. When the value of the expression in a noptr-new-declarator is zero, the allocation function is called to allocate an array with no elements. If the value of that expression is less than zero or such that the size of the allocated object would exceed the implementation-defined limit, or if the new-initializer is a braced-init-list for which the number of initializer-clauses exceeds the number of elements to initialize, no storage is obtained and the new-expression terminates by throwing throws an exception (14.2 [except.throw]) of a type that would match a handler (14.4 [except.handle]) of type std::bad_array_new_length (17.6.4.2 [new.badlength]).
  11. Change Clause 14 [except] paragraph 1 as follows:

  12. ...A handler will be invoked only by a throw-expression invoked throwing an exception in code executed in the handler's try block or in functions called from the handler's try block ...
  13. Change Clause 14 [except] paragraph 2 as follows:

  14. A try-block is a statement (Clause 8 [stmt.stmt]). A throw-expression is of type void. Code that executes a throw-expression is said to “throw an exception;” code that subsequently gets control is called a “handler.” [Note:...
  15. Change 14.2 [except.throw] paragraph 1 as follows:

  16. Throwing an exception transfers control to a handler. [Note: An exception can be thrown from one of the following contexts: throw-expression (see below), allocation functions (6.7.5.5.2 [basic.stc.dynamic.allocation]), dynamic_cast (7.6.1.7 [expr.dynamic.cast]), typeid (7.6.1.8 [expr.typeid]), new-expression (7.6.2.8 [expr.new]), and standard library functions (16.3.2.4 [structure.specifications]). —end note] An object is passed and the type of that object determines which handlers can catch it. [Example:...
  17. Change 14.2 [except.throw] paragraph 3 as follows:

  18. A throw-expression Throwing an exception copy-initializes (9.4 [dcl.init], 11.4.5.3 [class.copy.ctor]) a temporary object, called the exception object, the type of which is determined by removing any top-level cv-qualifiers from the static type of the operand of throw and adjusting the type from “array of T” or “function returning T” to “pointer to T” or “pointer to function returning T”, respectively. The temporary is an lvalue and is used to initialize the variable named in the matching handler (14.4 [except.handle]). If the type of the exception object would be an incomplete type or a pointer to an incomplete type other than (possibly cv-qualified) void the program is ill-formed. Except for these restrictions and the restrictions on type matching mentioned in 14.4 [except.handle], the operand of throw is treated exactly as a function argument in a call (7.6.1.3 [expr.call]) or the operand of a return statement. Evaluating a throw-expression 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.
  19. Change 14.2 [except.throw] paragraph 4 as follows:

  20. ...[Note: an a thrown exception thrown by a throw-expression does not propagate to other threads unless caught, stored, and rethrown using appropriate library functions; see 17.9.7 [propagation] and 33.10 [futures]. —end note]
  21. Change 14.2 [except.throw] paragraph 8 as follows:

  22. A throw-expression with no operand rethrows the currently handled exception (14.4 [except.handle]). The exception is reactivated with the existing temporary exception object; no new temporary exception object is created. The exception is no longer considered to be caught; therefore, the value of std::uncaught_exception() will again be true. [Example:...
  23. Change 14.3 [except.ctor] paragraph 1 as follows:

  24. As control passes from a throw-expression the point where an exception is thrown to a handler, destructors are invoked for all automatic objects constructed since the try block was entered...
  25. Change 14.3 [except.ctor] paragraph 3 as follows:

  26. The process of calling destructors for automatic objects constructed on the path from a try block to a throw-expression the point where an exception is thrown is called “stack unwinding.” If a destructor...
  27. Change 14.4 [except.handle] paragraph 17 as follows:

  28. When the handler declares a non-constant an object, any changes to that object will not affect the temporary object that was initialized by execution of the throw-expression exception object. When the handler declares a reference to a non-constant an object, any changes to the referenced object are changes to the temporary object initialized when the throw-expression was executed exception object and will have effect should that object be rethrown.
  29. Change 17.9.5.4 [terminate] paragraph 1 as follows:

  30. Remarks: Called by the implementation when exception handling must be abandoned for any of several reasons (14.6.2 [except.terminate]), in effect immediately after evaluating the throw-expression (17.9.5.1 [terminate.handler]) throwing the exception. May also be called directly by the program.