>> and I don't have a full copy of it to hand. Can anyone quote
>> exactly what C99 says on this subject. I suspect GCC has done
>> something compliant, but useless.
>
> I'm sure asking on comp.lang.c would get a correct answer.
Actually, comp.std.c sould be the best place. But it's not
necessary; nobody will argue that it's not a bug.
I don't have C99 handy, but C89 says (6.5.3):
# An object that has volatile-qualified type may be modified in ways
# unknown to the implementation or have other unknown side effects.
# Therefore any expression referring to such an object shall be evaluated
# strictly according to the rules of the abstract machine, as described
# in 5.1.2.3. Furthermore, at every sequence point the value last stored
# in the object shall agree with that prescribed by the abstract machine,
# except as modified by the unknown factors described previously.[67]
# What constitutes an access to an object that has volatile-qualified type
# is implementation-defined.
# [67] A volatile declaration may be used to describe an object
# corresponding to a memory-mapped input/output port or an object
# accessed by an asynchronously interrupting function. Actions on
# objects so declared shall not be "optimized out" by an implementation
# except as permitted by the rules for evaluating
# expressions.
The abstract machine rules are a bit intricate, and it's possible to
make a useless choice on the "implementation-defined" escape clause,
but the intention is crystal clear and boils down to "thou shalt access
the underlying object exactly once per literal reference in the C source
code."
The only laxity is that "volatile int a; a += b;" need not use a
single add-to-memory instruction, because many processors don't have
one; it's allowed to convert that to "a = a + b;".
Regardless of weasel-wording, the generated code first tests if the
value is in range, and then fetches it again to index into a jump table.
Without the clearly forbidden assumption that the value in memory doesn't
change between accesses, this can crash the machine. What if it were
4 the first time it was read and 4000 the second time?
swtich (x) {
/* 8 cases */
}
Absolutely MUST jump to one of the cases, or bypass the entire switch
and do nothing. No tenth option is permitted.