Sorry for the very late response. It is actually triggered by the bugzilla entry http://gcc.gnu.org/bugzilla/show_bug.cgi?id=22278
The motivating example, abstracted from a misbehaving part of X, is: void test (char *addr) { *((volatile char *) addr); } In this case, the fetch ("access") is required for the hardware to behave. | From: Dale Johannesen <dalej at apple dot com> | Date: Tue, 3 May 2005 10:04:36 -0700 | | On May 3, 2005, at 7:41 AM, Nathan Sidwell wrote: | > Mike Stump wrote: | > > int avail; | > > int main() { | > > while (*(volatile int *)&avail == 0) | > > continue; | > > return 0; | > > } | > > Ok, so, the question is, should gcc produce code that infinitely loops, | > > or should it be obligated to actually fetch from memory? Hint, 3.3 | > > fetched. | > | > I beleive the compiler is so licensed. [5.1.2.3/2] talks about accessing | > a volatile object. If the compiled can determine the actual object | > being accessed through a series of pointer and volatile cast conversions, | > then I see nothing in the std saying it must behave as-if the object | > were volatile when it is not. That turns out not to be the case. See the chain of reasoning later in this message. | This is correct; the standard consistently talks about the type of the object, | not the type of the lvalue, when describing volatile. | | However, as a QOI issue, I believe the compiler should treat the reference as | volatile if either the object or the lvalue is volatile. That is obviously | the | user's intent. It appears to me that standards conformance requires the access to be performed. So GCC4 has a bug. One that is subtle, so the damage it is doing may not be evident. The worst kind. When I asked Henry Spencer to look at this, he gave a convincing argument from chapter and verse of C99. I will quote it here. I added the identical text to the bugzilla entry (comment #43), so there is no need to read the rest of this message if you read that comment. ================ start of Henry's comment There is little room for compiler writers to maneuver here, unless they have announced their intentions in advance in their documentation. Reading C99 carefully: 6.5.3.2: applying `*' to a pointer of type `T *' which points to an object yields an lvalue of type `T' designating that object. So the lvalue in the assignment has a volatile-qualified type. 6.3.2.1: when an object is said to have a particular type, the type is specified by the lvalue used to designate the object. So the lvalue having a volatile-qualified type *means* that the object it designates has a volatile-qualified type; "has type X" and "is designated by an lvalue of type X" are synonymous (!). 6.7.3: any expression referring to an object of volatile-qualified type must be evaluated strictly by the rules of the abstract machine, although precisely what constitutes an "access" to the object is implementation-defined. (Note, "implementation-defined" behavior is required to be well-defined and *documented*.) So if the reference in question is an "access", it must occur where the abstract machine says it should. 5.1.2.3: the abstract machine evaluates all expressions as specified by semantics and all side effects must occur, side effects including "accessing a volatile object"; implementations are allowed to skip part of expression evaluation only if they can deduce that no needed side effects (notably "accessing a volatile object") are therefore skipped. So if the reference is an "access", it must occur, period. I see no useful wiggle room in the difference between "access" and "accessing", or the difference between "volatile object" and "object of volatile-qualified type". These appear to me to be minor accidents of inconsistent terminology, not useful to a sane implementer. 6.7.3 says that to refer to an object "defined with" volatile-qualified type "through use of an lvalue" with non-volatile-qualified type yields undefined behavior. However, the reference here uses a volatile-qualified lvalue, so this is not relevant. A pointer value is not an lvalue; there is no lvalue present until the `*' operator is applied. Surprising though it might seem, I see no express or implied permission to distinguish based on whether the object in question was *defined* with a volatile-qualified type. There are places in the standard where how an object is defined is significant, e.g. the rules for `const' and the part of 6.7.3 noted in the previous paragraph, but none of them is part of the chain of reasoning above. The only loophole is the definition of "access". If GCC wishes to claim standard conformance, GCC is required to document its definition. I'm not aware of any mention of this in the GCC documentation, although I haven't dug hard for it. I see no room for a reasonable definition of "access" which retains some useful meaning for `volatile' and doesn't cover the reference in question. (I agree that you can contrive a definition which contains special-case wording to cover this case, but not that it's reasonable to do so.) If GCC (a) wants to be C99-conforming, and (b) wants to provide useful semantics for `volatile', this is a bug. Henry