I expect the following program to return 0 all of the time. However with Visual Studio 2013 (Update 4), the program exits 1 in release builds. I\'m not sure if this is a bug
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**) 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.
No, this optimization does not conform to the C++ standard. The declaration of uniqueMemLoc
defines a unique object for each instance of the template, and each object has its own address.
(If you had used a string literal, it would be a different story. The optimization would be valid in that case.)