This does not seem like a valid optimization according to the draft C++11 standard section 14.8
[temp.fct.spec] says (emphasis mine going forward):
Each function template specialization instantiated from a template has
its own copy of any static variable. [ Example:
template<class T> void f(T* p) {
static T s;
};
void g(int a, char* b) {
f(&a); // calls f<int>(int*)
f(&b); // calls f<char*>(char**)
}
Here f(int*) has a static variable s of type int and
f<char*>(char**) has a static variable s of type char*. —end example ]
Since your taking the address of the variable folding them effects observable behavior which would violate the as-if rule.
T.C. points out that /opt:noicf
prevents the non-conforming behavior.
Matt McNabb points out that the /OPT (Optimizations) documentation contains the following note:
Because /OPT:ICF can cause the same address to be assigned to
different functions or read-only data members (const variables
compiled by using /Gy), it can break a program that depends on unique
addresses for functions or read-only data members. For more
information, see /Gy (Enable Function-Level Linking).
Which suggests this could be intentional non-conforming behavior. Ben Voigt says in a comment now moved to chat that this indeed means the optimizations can be non-conforming but this points is debatable.
User usr linked to an MS blog post: Introducing ‘/Gw’ Compiler Switch and it says:
Please note, the ICF optimization will only be applied for identical
COMDATs where their address is not taken, and they are read only. If a
data is not address taken, then breaking address uniqueness by ICF
won't lead to any observable difference, thus it is valid and
conformant to the standard.
and a later comment says:
Even though it's on it's own completely standards complaint, when
combined with /Gy potentially breaking behavior can result.
From what I can tell in order for /Gy
to effect const variables __declspec(selectany) has to be used but it could be clearer in the documentation.
At minimum we can see that /Gw
should not introduce non-conforming behavior but /Gy
in combination with /Gw
may.
/opt:noicf
fixes it. – Volition/Za
to avoid the broken behavior, regardless of whether it sets/OPT:NOICF
(which is only important is/OPT:REF
is specified, otherwise the default of no/OPT
options will have folding disabled as well). – MillenniumPlease note, the ICF optimization will only be applied for identical COMDATs where their address is not taken
which indicates it does not apply to this case. – Biak