Not an answer
This is just an issue with the wording of the question and the answers. The problem arises due to the inability to convert pointers to volatile objects into void pointers, not volatile pointers.
The difference, which is rather important, is what memory element is the one that is volatile. In the question, the pointer is not volatile (it can be cached, and it does not have to be flushed to memory when it is changed), but rather the pointed memory:
int volatile * p = f();
p++; // this does not affect the perceived state of the c++ memory model
++p;
*p = 5; // this changes the perceived state
The reason why it is important is that with a volatile pointer to memory, the pointer itself is the one that has special treatment.
void foo( int * );
int * volatile p = f(); // 1
foo(p); // 2
int volatile * q = f();
//foo(q); // error, cannot convert pointer to volatile to pointer to non-volatile
*q = 5; // 3
q = 0; // 4
In the code above, the operations marked as 1 and 2 make it all the way to memory. The assignment in [1] must be dumped to memory. Even if the value of p
is in a register, it will be loaded from memory at [2]. The operation marked [3] modifies the value pointed by q
which is volatile
and will make all the way to main memory, while the operation [4] only affects the pointer, which is not volatile
itself, and as such is not part of the c++ memory model perceivable state and can be performed in registers (note that a compiler can optimize away q
and perform the operations in a register, while p
cannot be optimized.