Essentially, if s is a structure, and foo(const void *) is evaluated conservatively, then foo(&s) does not invalidate s, but foo(&(s.x)) invalidates the whole s, because the store only looks at traits of base regions (inside binding keys), and s.x is a field region.
This patch represents the idea that only whole base regions should carry the TK_PreserveContents trait. This also makes a bit of sense, because no matter what pointer arithmetic we do with a const pointer, it's still a const pointer. There's an extra complication with mutable fields in C++ classes, which i neither added nor fixed here.
In CallEvent.cpp below the changed code there's a FIXME comment, but i'm not sure what it means; if anybody thinks it means exactly what this patch is about, then i'd have to update it :)
What i don't like about the approach this patch implements, is that it makes the core rely on an implementation detail of RegionStoreManager ("only base regions are relevant" is such implementation detail). Instead, i also tried to add a few extra virtual methods into the StoreManager to avoid this problem, but it made the patch much heavier. I can post that, unless anybody else thinks that it's a natural thing (rather than implementation detail) to propagate this trait to base regions.
Instead, it should be possible to auto-replace the region with a base region inside setTrait() and hasTrait() methods.