On 15 Nov 2013 at 17:50, Antony Polukhin wrote:
I believe that this was a problem for Boost.Move with gcc, which does something similar. It's actually quite common for old C code that casts between different structs to fail with newer compilers. For instance, Python does not work without -fno-strict-aliasing.
Looks like I've got what are you talking about. It's an optimization in GCC, that assumes that if there is a reference to two different types and neither of those types is char, than those types are different in memory (are not aliases):
void foo(int64_t& v1, int32_t& v2) { /* GCC assumes that address of v1 is not a part of v2 adresses*/ v2 = 2; cout << v1; }
int64_t i64 = 1; foo(i64, reinterpret_cast
(i64)); // outputs 1 But this error appears only when we mutate data ( https://svn.boost.org/trac/boost/wiki/Guidelines/WarningsGuidelines search for "strict-aliasing rules")
This isn't really the same thing as Stephen mentioned. The above example is explicitly unrelated types i.e. a int64_t is not a int32_t, and the compiler is permitted to absolutely assume that to be true in the strongest possible way. The strict-aliasing problems in Python and the Linux kernel are due to them casting between unrelated structure types without the proper use of volatile qualification and/or going through void * or char * as the carrying opaque pointer type, such that the compiler's alias optimisation pass will assume that two unrelated type pointers will never refer to the same patch of memory which is permitted by the standard. Using volatile or void * or char * can inhibit that optimisation pass by disabling the ability to assume two pointers cannot refer to the same memory, and therefore inhibit unsafe code being generated. It is of course still undefined behaviour, but it's extremely common in C out of necessity. What TypeIndex does is much safer - it upcasts to a derived and therefore related type, and the compiler knows the types are related (or static_cast would fail). I cannot see how alias optimisation could ever therefore generate unsafe code in this case. Upcasting to a derived type is a very common - if often illegal - idiom in C++, but it is usually safe. It also saves programmers from writing a lot of extra boilerplate, hence its popularity. As I mentioned in the other post, for me it's the incorrectness of the virtual function table which kills this use of UB for me. Not the static upcast. Niall -- Currently unemployed and looking for work. Work Portfolio: http://careers.stackoverflow.com/nialldouglas/