the latest gcc "volatile" keyword(I can not understand)

The C++ standard differs from the C standard in its treatment of volatile objects. It fails to specify what constitutes a volatile access, except to say that C++ should behave in a similar manner to C with respect to volatiles, where possible. However, the different lvalueness of expressions between C and C++ complicate the behavior. G++ behaves the same as GCC for volatile access, See Volatiles, for a description of GCC's behavior.

The C and C++ language specifications differ when an object is accessed in a void context:
volatile int *src = somevalue;
*src;


The C++ standard specifies that such expressions do not undergo lvalue to rvalue conversion, and that the type of the dereferenced object may be incomplete. The C++ standard does not specify explicitly that it is lvalue to rvalue conversion that is responsible for causing an access. There is reason to believe that it is, because otherwise certain simple expressions become undefined. However, because it would surprise most programmers, G++ treats dereferencing a pointer to volatile object of complete type as GCC would do for an equivalent type in C. When the object has incomplete type, G++ issues a warning; if you wish to force an error, you must force a conversion to rvalue with, for instance, a static cast.

When using a reference to volatile, G++ does not treat equivalent expressions as accesses to volatiles, but instead issues a warning that no volatile is accessed. The rationale for this is that otherwise it becomes difficult to determine where volatile access occur, and not possible to ignore the return value from functions returning volatile references. Again, if you wish to force a read, cast the reference to an rvalue.

G++ implements the same behavior as GCC does when assigning to a volatile object—there is no reread of the assigned-to object, the assigned rvalue is reused. Note that in C++ assignment expressions are lvalues, and if used as an lvalue, the volatile object is referred to. For instance, vref refers to vobj, as expected, in the following example:
volatile int vobj;
volatile int &vref = vobj = something;
'Volatile', in particular, is a frill for esoteric applications, and much better expressed by other means.
Its chief virtue is that nearly everyone can forget about it.
- Dennis Ritchie, March 1988 http://www.lysator.liu.se/c/dmr-on-noalias.html (emphasis added)


Even more true, after the languages (C11, C++11) became concurrency aware.
Last edited on
In my experience, 'volatile' is to avoid to read from 'memory' directly with 'register'.
Accessing a volatile object is deemed to be part of the observable behaviour of the program.

The least requirements on a conforming implementation are:

— Access to volatile objects are evaluated strictly according to the rules of the abstract machine.
— ... <data written to files> ...
— ... <i/o on interactive devices> ....

These collectively are referred to as the observable behaviour of the program - IS


Annotation by cppreference:
Every access (read or write operation, member function call, etc.) on the volatile object is treated as a visible side-effect for the purposes of optimization (that is, within a single thread of execution, volatile accesses cannot be optimized out or reordered with another visible side effect that is sequenced-before or sequenced-after the volatile access. This makes volatile objects suitable for communication with a signal handler, but not with another thread of execution, see std::memory_order). Any attempt to refer to a volatile object through a non-volatile glvalue (e.g. through a reference or pointer to non-volatile type) results in undefined behavior.
http://en.cppreference.com/w/cpp/language/cv


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
void foo( int& a )
{
    int b = 7 ;
    a = b++ ;
    /*
        movl  $7, (%rdi)
        ret
    */
    // "as-if" rule, generate code as-if void foo( int& a ) { a = 7 ; }
}

void bar( int& a )
{
    volatile int b = 7 ;
    a = b++ ;
    /*
        movl $7, -4(%rsp)
        movl -4(%rsp), %eax
        leal 1(%rax), %edx
        movl %eax, (%rdi)
        movl %edx, -4(%rsp)
        ret
    */
    // "as-if" rule does not apply to volatile objects, generate code for
    // void bar( int& a )
    // {
    //     int b = 7 ;
    //     int anonymous_temporary = b ; // The value computation of the built-in post-increment operator 
    //     b = b + 1 ; // is sequenced before its side-effect. http://en.cppreference.com/w/cpp/language/eval_order
    //     a = anonymous_temporary ;
    // }
    // strictly, according to the rules of the abstract machine
}

http://coliru.stacked-crooked.com/a/ca388765d61672a5
Interesting it's being brought up; the C++ committee was just discussing C's wg14 DR 476, which pointed out that C++ spec isn't precise enough to allow the intended use of volatile, such as
volatile short *ttyport = (volatile short*)TTYPORT_ADDR;
That line JLBorges quoted might eventually change to "Access to volatile objects and access through volatile-qualified lvalues are evaluated strictly according to the rules of the abstract machine". although compiler vendors, such as GCC in the OP quote, understand the intent even if the wording is flawed.

Last edited on
Topic archived. No new replies allowed.