Given these definitions:
typedef void foo_t(void);
static void foo(void) {
}
The following, as expected, does not get optimized away: The pointer is read and the function is indirectly (tail) called:
foo_t volatile *gfoo = foo;
void gtest() {
gfoo();
}
However, if the pointer is declared static
, the read and the function call get completely optimized away:
static foo_t volatile *sfoo = foo;
void stest() {
sfoo();
}
I realize that due to the static
definition, the compiler can see that sfoo
is never written and hence it wants to assume that it always points to the same empty function, which it will inline given the chance. However, my understanding of volatile
is that it should force the read access and not assume anything about the data that is read.
For example, in N1256, the final C99 draft, “6.7.3 Type qualifiers”, it is stated:
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. […]
The related question When can a volatile variable be optimized away completely? and its answers quote the same paragraph, but as the variable in question is read and not just initialized, I think it agrees that sfoo
should not be optimized away.
In case it matters, I read about this in this german blog article about the way openssl tries to use this method to prevent optimizing away dead stores.