Skip to content

[except.throw] Non-copyable exception object types can be conditionally-supported #35

@frederick-vs-ja

Description

@frederick-vs-ja

Full name of submitter (unless configured in github; will be published with the issue): Jiang An

Reference (section label): [except.throw], [except.handle], [propagation]

Link to reflector thread (if any):

Issue description: CWG1863 clarified that the type of an exception object must be copyable. However, such restriction seems overly strict. Some (but not all) mainstream implementations (perhaps all implementations using Itanium C++ ABI) can correctly support move-only exception objects, given the operand of throw-expression is an rvalue and the exception is caught by reference, because exception objects are allocated on the heap, and no exception_ptr-related mechanism needs to copy exception objects. On the other hand, CWG1863 predated the acception of P0135R1 (guaranteed RVO since C++17), and the aforementioned implementations seem even support non-movable exception objects in C++17 and later modes.

This issue is related LWG3688. For implementations supporting move-only exception objects, std::bad_expection_access<MoveOnly> can be thrown correctly, see gcc bug 105146.

I think move-only exception object type should be made conditionally-supported to legitimize such existing implementation strategy. The term "thrown object" may be wrong or denote different objects (see editiorial issue 5238), perhaps it should be reworded.

Suggested resolution:

Change [except.throw]/5 as indicated:

When the thrown object is a class object, the constructor selected for the copy-initialization as well as the constructor selected for a copy-initialization considering the thrown object as an lvalue shall be non-deleted and accessible, even if the copy/move operation is elided (11.9.6 [class.copy.elision]). The copy-initialization of the exception object from the operand of the throw-expression shall be well-formed in the context of the throw-expression. T When the operand is of a class type, the destructor is potentially invoked (11.4.7 [class.dtor]). If the copy-initialization of an object of the same type of the exception object from an lvalue of that type would be ill-formed in any context, the throw-expression is conditionally-supported.

Add a bullet after [except.handle]/3:

If the handler is of type cv T, where T is an object type, the copy-initialization of an object of type T from an lvalue of type T shall be well-formed in every possible context.

Change [propagation]/8 as indicated:

... If it is possible to copy the exception object, Iit is unspecified whether the return values of two successive calls to current_exception refer to the same exception object.

Change [propagation]/10 as indicated:

... If it is possible to copy the exception object, Iit is unspecified whether a copy is made, and memory for the copy is allocated in an unspecified way. ...

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions