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


496. Is a volatile-qualified type really a POD?

Section: 6.8  [basic.types]     Status: CD3     Submitter: John Maddock     Date: 30 Dec 2004

[Moved to DR at the April, 2013 meeting.]

In 6.8 [basic.types] paragraph 10, the standard makes it quite clear that volatile qualified types are PODs:

Arithmetic types (6.8.2 [basic.fundamental]), enumeration types, pointer types, and pointer to member types (6.8.4 [basic.compound]), and cv-qualified versions of these types (6.8.5 [basic.type.qualifier]) are collectively called scalar types. Scalar types, POD-struct types, POD-union types (Clause 11 [class]), arrays of such types and cv-qualified versions of these types (6.8.5 [basic.type.qualifier]) are collectively called POD types.

However in 6.8 [basic.types] paragraph 3, the standard makes it clear that PODs can be copied “as if” they were a collection of bytes by memcpy:

For any POD type T, if two pointers to T point to distinct T objects obj1 and obj2, where neither obj1 nor obj2 is a base-class subobject, if the value of obj1 is copied into obj2, using the std::memcpy library function, obj2 shall subsequently hold the same value as obj1.

The problem with this is that a volatile qualified type may need to be copied in a specific way (by copying using only atomic operations on multithreaded platforms, for example) in order to avoid the “memory tearing” that may occur with a byte-by-byte copy.

I realise that the standard says very little about volatile qualified types, and nothing at all (yet) about multithreaded platforms, but nonetheless this is a real issue, for the following reason:

The forthcoming TR1 will define a series of traits that provide information about the properties of a type, including whether a type is a POD and/or has trivial construct/copy/assign operations. Libraries can use this information to optimise their code as appropriate, for example an array of type T might be copied with a memcpy rather than an element-by-element copy if T is a POD. This was one of the main motivations behind the type traits chapter of the TR1. However it's not clear how volatile types (or POD's which have a volatile type as a member) should be handled in these cases.

Notes from the April, 2005 meeting:

It is not clear whether the volatile qualifier actually guarantees atomicity in this way. Also, the work on the memory model for multithreading being done by the Evolution Working Group seems at this point likely to specify additional semantics for volatile data, and that work would need to be considered before resolving this issue.

(See also issue 1746.)

Proposed resolution, October, 2012:

  1. Change 6.8 [basic.types] paragraph 9 as follows:

  2. ...Scalar types, trivially copyable class types (Clause 11 [class]), arrays of such types, and cv-qualified non-volatile const-qualified versions of these types (6.8.5 [basic.type.qualifier]) are collectively called trivially copyable types. Scalar types, trivial class types...
  3. Change 9.2.9.2 [dcl.type.cv] paragraphs 6-7 as follows:

  4. What constitutes an access to an object that has volatile-qualified type is implementation-defined. If an attempt is made to refer to an object defined with a volatile-qualified type through the use of a glvalue with a non-volatile-qualified type, the program behavior is undefined.

    [Note: volatile is a hint to the implementation to avoid aggressive optimization involving the object because the value of the object might be changed by means undetectable by an implementation. Furthermore, for some implementations, volatile might indicate that special hardware instructions are required to access the object. See 6.9.1 [intro.execution] for detailed semantics. In general, the semantics of volatile are intended to be the same in C++ as they are in C. —end note]

  5. Change 11.4.5.3 [class.copy.ctor] paragraph 12 as follows:

  6. A copy/move constructor for class X is trivial if it is not user-provided, its declared parameter type is the same as if it had been implicitly declared, and if

  7. Change 11.4.5.3 [class.copy.ctor] paragraph 25 as follows:

  8. A copy/move assignment operator for class X is trivial if it is not user-provided, its declared parameter type is the same as if it had been implicitly declared, and if

Notes from the June, 2016 meeting:

The resolution of issue 2094 revert the changes above revert the changes of volatile qualification on trivial copyability.