WIP: Make reinterpreting from Variant safer
I ran into some bizarre behavior with code generated with GCC in optimized mode. I think the problem was that the optimizer was being aggressive in removing computation after reinterpreting pointers.
The C++ standard states that if two pointers or references point to different types of data, they can be considered to point to different memory locations. This often allows the compiler to make much faster code. But it also means that if you pun the data (make the data look like two different things at once) you get undefined behavior.
The commonly accepted solution to the problem is to use std::memcpy to move the data to a pointer of a new type. However, this only works for trivial types, and we need to support non-trivial types.
The solution used here is to allow the data to be punned, but to use std::memmove to alert the compiler that there is a dependence between the two types. The pointers to the memmove are the same, so the compiler should remove any actual work but still record the data dependence. It should also be safe for non-trivial types since you are not actually moving any data.
Technically, this solution still is classified as undefined
behavior. However, the only issue you should run into is that
changes to the punned data won't reflect each other. This should
be addressed in CastAndCall
, which does a second memmove after
the functor is called in case the object is changed. For the
same reason, writing to the value using Get
has been disabled
to prevent those writes from being out of order.