summaryrefslogtreecommitdiffstats
path: root/clang/lib/StaticAnalyzer/Core/RegionStore.cpp
diff options
context:
space:
mode:
authorJordan Rose <jordan_rose@apple.com>2013-09-11 16:46:50 +0000
committerJordan Rose <jordan_rose@apple.com>2013-09-11 16:46:50 +0000
commit9519ff59ec0accfeee3bc43ce5c01dd7cbd94850 (patch)
treed00500b7ef1b8cb79d3841d36e1dbe9ff0f63b3b /clang/lib/StaticAnalyzer/Core/RegionStore.cpp
parentd9ad0681fad9a98f43d9baddb95d505b37153c48 (diff)
downloadbcm5719-llvm-9519ff59ec0accfeee3bc43ce5c01dd7cbd94850.tar.gz
bcm5719-llvm-9519ff59ec0accfeee3bc43ce5c01dd7cbd94850.zip
[analyzer] Handle zeroing constructors for fields of structs with empty bases.
RegionStore tries to protect against accidentally initializing the same region twice, but it doesn't take subregions into account very well. If the outer region being initialized is a struct with an empty base class, the offset of the first field in the struct will be 0. When we initialize the base class, we may invalidate the contents of the struct by providing a default value of Unknown (or some new symbol). We then go to initialize the member with a zeroing constructor, only to find that the region at that offset in the struct already has a value. The best we can do here is to invalidate that value and continue; neither the old default value nor the new 0 is correct for the entire struct after the member constructor call. The correct solution for this is to track region extents in the store. <rdar://problem/14914316> llvm-svn: 190530
Diffstat (limited to 'clang/lib/StaticAnalyzer/Core/RegionStore.cpp')
-rw-r--r--clang/lib/StaticAnalyzer/Core/RegionStore.cpp17
1 files changed, 13 insertions, 4 deletions
diff --git a/clang/lib/StaticAnalyzer/Core/RegionStore.cpp b/clang/lib/StaticAnalyzer/Core/RegionStore.cpp
index dd416f63666..50186fbaa5a 100644
--- a/clang/lib/StaticAnalyzer/Core/RegionStore.cpp
+++ b/clang/lib/StaticAnalyzer/Core/RegionStore.cpp
@@ -422,11 +422,20 @@ public: // Part of public interface to class.
// BindDefault is only used to initialize a region with a default value.
StoreRef BindDefault(Store store, const MemRegion *R, SVal V) {
RegionBindingsRef B = getRegionBindings(store);
- assert(!B.lookup(R, BindingKey::Default));
assert(!B.lookup(R, BindingKey::Direct));
- return StoreRef(B.addBinding(R, BindingKey::Default, V)
- .asImmutableMap()
- .getRootWithoutRetain(), *this);
+
+ BindingKey Key = BindingKey::Make(R, BindingKey::Default);
+ if (B.lookup(Key)) {
+ const SubRegion *SR = cast<SubRegion>(R);
+ assert(SR->getAsOffset().getOffset() ==
+ SR->getSuperRegion()->getAsOffset().getOffset() &&
+ "A default value must come from a super-region");
+ B = removeSubRegionBindings(B, SR);
+ } else {
+ B = B.addBinding(Key, V);
+ }
+
+ return StoreRef(B.asImmutableMap().getRootWithoutRetain(), *this);
}
/// Attempt to extract the fields of \p LCV and bind them to the struct region
OpenPOWER on IntegriCloud