cplusplus / CWG

Core Working Group
23 stars 7 forks source link

CWG2822 [basic.stc.general] Side-effect-free pointer zap #457

Closed opensdh closed 5 months ago

opensdh commented 11 months ago

Reference (section label): [basic.stc.general]

Link to reflector thread (if any): main proposal

Issue description:

[basic.stc.general]/4 seems to suggest that the end of the duration of a region of storage causes modifications to pointer objects, raising questions about data races (in the abstract machine) and complicating ongoing discussions about the compatibility of the standard with certain concurrent algorithms.

Suggested resolution:

Per reflector discussion, separate inherently invalid pointer values (as from reinterpret_cast of arbitrary integers) from circumstantially invalid pointer usage (that does not happen before the destruction of the relevant storage), by making the wording changes below.

Change in [basic.stc.general]/4:

[Note: When After the end of the duration of a region of storage is reached, the values of all pointers representing the address of any part of that region of storage become behave as if they were invalid pointer values ([basic.compound]). — end note]

Indirection through an invalid pointer value and passing an invalid pointer value to a deallocation function have undefined behavior. Any other use of an invalid pointer value has implementation-defined behavior.[…]

Change in [basic.compound]/3:

[…] Every value of pointer type is one of the following:

  • a pointer to an object or function (the pointer is said to point to the object or function), or
  • a pointer past the end of an object ([expr.add]), or
  • the null pointer value for that type, or
  • an invalid pointer value.

A value of a pointer type that is a pointer to or past the end of an object represents the address of the first byte in memory ([intro.memory]) occupied by the object[…] or the first byte in memory after the end of the storage occupied by the object, respectively.

[Note: A pointer past the end of an object ([expr.add]) is not considered to point to an unrelated object of the object's type, even if the unrelated object is located at that address. A pointer value becomes invalid when the storage it denotes reaches the end of its storage duration; see [basic.stc]. — end note]

[…]

Insert a new paragraph after /3, including the deleted text from [basic.stc.general]/4:

A pointer value P is valid in the context of an evaluation E if P is a null pointer value, or if it is a pointer to or past the end of an object O and E happens before the end of the duration of the region of storage for O. If a pointer value P is used in an evaluation E and P is not valid in the context of E, then the behavior is undefined if E is an indirection or an invocation of a deallocation function, and implementation-defined otherwise.[…]

[Note: P can be valid in the context of E even if it points to a type unrelated to that of O or if O is not within its lifetime, although further restrictions apply to such pointer values ([basic.lval], [expr.add], [basic.life]). — end note]

For clarity, add cross reference in [expr.static.cast]/14:

A prvalue of type "pointer to cv1 void" can be converted to a prvalue of type "pointer to cv2 T", where T is an object type and cv2 is the same cv-qualification as, or greater cv-qualification than, cv1. If the original pointer value represents the address A of a byte in memory and A does not satisfy the alignment requirement of T, then the resulting pointer value ([basic.compound]) is unspecified.

[…]

and similarly in [expr.reinterpret.cast]/5:

A value of integral type or enumeration type can be explicitly converted to a pointer. A pointer converted to an integer of sufficient size (if any such exists on the implementation) and back to the same pointer type will have its original value ([basic.compound]); mappings between pointers and integers are otherwise implementation-defined.

jensmaurer commented 11 months ago

CWG2822