Description
Full name of submitter (unless configured in github; will be published with the issue): Jiang An
Reference (section label): [except.throw]
Link to reflector thread (if any):
Issue description:
The wording in [except.throw] p5 is out of sync. It predated P0135R1 which made the thrown operand of a class type not necessarily an object, and P0848R3 which made the selected constructor for a copy-initialization possibly non-existent. Some of its contents will be covered by CWG2711.
It seems that all mainstream implementations lack the checking required by CWG1863.
Additionally, it's unclear in which context the access checking is performed when the checking is needed for a constructor. It might be better to clarify that the exception object is always of a cv-unqualified object type, even if it is generated by the implementation in a way other than a throw-expression.
Suggested resolution:
Change [except.throw] p3 as indicated:
Throwing an exception copy-initializes ([dcl.init], [class.copy.ctor]) a temporary object of a cv-unqualified type, called the exception object. Let
T
denote the type of the exception object. Ifthe type of the exception objectT
would be an incomplete type, an abstract class type ([class.abstract]), or a pointer to an incomplete type other than cvvoid
the program is ill-formed. Copy-initialization of an object of the typeT
from an lvalue of typeT
, where the access checking for the selected constructor (if any) is performed in a context unrelated to any class, shall be well-formed. WhenT
is a class type, the destructor forT
is potentially invoked ([class.dtor]).
[Note ?: Copyability of the exception object may be needed for standard library functionscurrent_exception
andrethrow_exception
([propagation]). — end note]
Delete the whole [except.throw] p5 (the contents are moved to p3, modulo CWG2711).
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 ([class.copy.elision]). The destructor is potentially invoked ([class.dtor]).
Add a paragraph after [propagation] p8:
?. Remarks: If the exception object is copied, the source is treated as a cv-unqualified lvalue and copy-initialization is performed.
Add a paragraph after [propagation] p10:
?. Remarks: If the referred-to object is copied, the source is treated as a cv-unqualified lvalue and copy-initialization is performed.
Drafting notes: It's not clear to me whether access checking is wanted. Also, given LWG3843 requires is_copy_constructible_v<E>
to be true
, perhaps we should consider the source as const-qualified instead of cv-unqualified.