With one exception, the relevant details aren't really compiler-specific, and C++20 keeps the relevant parts... if you perform two operations on volatile values, the operations can't be reordered, because the spec says so.
> Accesses through volatile glvalues are evaluated strictly according to the rules of the abstract machine.
Not the best, clearest, most useful part of the C++ spec but the core concept is there... if you perform operation A on a volatile object, then perform operation B on a volatile object, the emitted code must perform A before B. To my knowledge, this part of the C++ standard hasn't even changed wording in C++20, and isn't deprecated either.
The compiler-specific parts are things like:
1. Is this a compiler fence? (If no, the buffer in a ring buffer must also be volatile.)
2. Is this a memory fence?
3. Is there some platform-specific way in which operations on volatile objects are different?
The part you do need to know is if the operation will tear.
You can find the C++ draft by searching for "n4861", if you're not the kind of person who wants to pay for (or has institutional access to) the final version of the spec.
The draft lists ++ / += of volatile deprecated, lists volatile function parameters and return types as deprecated, but does not mention deprecation of volatile member functions (or I didn't find it).
Keep in mind that the standard does change between draft and finalization, and I've been bitten by this before (one draft of C is missing library functions present in the final standard).
> the standard does change between draft and finalization
Interesting. This topic turned up 2 months ago [0] and I was assured that the differences between the last draft and the final document were guaranteed to be insubstantial things like formatting tweaks. You're saying this is definitely not the case in practice?
> Accesses through volatile glvalues are evaluated strictly according to the rules of the abstract machine.
Not the best, clearest, most useful part of the C++ spec but the core concept is there... if you perform operation A on a volatile object, then perform operation B on a volatile object, the emitted code must perform A before B. To my knowledge, this part of the C++ standard hasn't even changed wording in C++20, and isn't deprecated either.
The compiler-specific parts are things like:
1. Is this a compiler fence? (If no, the buffer in a ring buffer must also be volatile.)
2. Is this a memory fence?
3. Is there some platform-specific way in which operations on volatile objects are different?
The part you do need to know is if the operation will tear.