It is expected to have the same object (memory region) treated as if it has different types in different program points. Like, the object may be a union or contain a union, or a pointer to it can be reinterpreted as a pointer to a different type. The correct behavior for RegionStore when an object is stored as an object of type T1 but loaded as an object of type T2 is to store the object as if it has type T1 but cast it to T2 during load. This is what CastRetrievedVal is responsible for.
Note that the cast here is some sort of a "reinterpret_cast" (even in C). For instance, if you store a float and load an integer, you won't have your float rounded to an integer; instead, you will have garbage.
Therefore i propose to admit that we cannot perform the cast as long as types we're dealing with are non-trivial (neither integers, nor pointers). Our modeling would still be weird in this case when dealing with integer casts, but so is support for integer casts in general.
Of course, if the cast is not necessary (eg, T1 == T2), we can still load the value just fine. This trivial observation in fact improves our behavior on tests and addresses some old FIXMEs: previously we would have tried to perform the cast and fail. We should probably also teach SValBuilder to perform casts in this case.
This is entirely incorrect. The whole point of this function is to handle the case when R->getValueType() has nothing to do with the original type of V.
Unfortunately, "type of an SVal" is not a thing, so it's going to be a bit more verbose.