diff options
-rw-r--r-- | lib/StaticAnalyzer/RegionStore.cpp | 29 | ||||
-rw-r--r-- | test/Analysis/misc-ps-region-store.m | 14 |
2 files changed, 41 insertions, 2 deletions
diff --git a/lib/StaticAnalyzer/RegionStore.cpp b/lib/StaticAnalyzer/RegionStore.cpp index def1b43f34..e47a77e6fc 100644 --- a/lib/StaticAnalyzer/RegionStore.cpp +++ b/lib/StaticAnalyzer/RegionStore.cpp @@ -1572,13 +1572,38 @@ Store RegionStoreManager::BindStruct(Store store, const TypedRegion* R, Store RegionStoreManager::KillStruct(Store store, const TypedRegion* R, SVal DefaultVal) { + + BindingKey key = BindingKey::Make(R, BindingKey::Default); + + // The BindingKey may be "invalid" if we cannot handle the region binding + // explicitly. One example is something like array[index], where index + // is a symbolic value. In such cases, we want to invalidate the entire + // array, as the index assignment could have been to any element. In + // the case of nested symbolic indices, we need to march up the region + // hierarchy untile we reach a region whose binding we can reason about. + const SubRegion *subReg = R; + + while (!key.isValid()) { + if (const SubRegion *tmp = dyn_cast<SubRegion>(subReg->getSuperRegion())) { + subReg = tmp; + key = BindingKey::Make(tmp, BindingKey::Default); + } + else + break; + } + + // Remove the old bindings, using 'subReg' as the root of all regions + // we will invalidate. RegionBindings B = GetRegionBindings(store); llvm::OwningPtr<RegionStoreSubRegionMap> SubRegions(getRegionStoreSubRegionMap(store)); - RemoveSubRegionBindings(B, R, *SubRegions); + RemoveSubRegionBindings(B, subReg, *SubRegions); // Set the default value of the struct region to "unknown". - return addBinding(B, R, BindingKey::Default, DefaultVal).getRoot(); + if (!key.isValid()) + return B.getRoot(); + + return addBinding(B, key, DefaultVal).getRoot(); } Store RegionStoreManager::CopyLazyBindings(nonloc::LazyCompoundVal V, diff --git a/test/Analysis/misc-ps-region-store.m b/test/Analysis/misc-ps-region-store.m index 0a6884be06..13a2c1fbe9 100644 --- a/test/Analysis/misc-ps-region-store.m +++ b/test/Analysis/misc-ps-region-store.m @@ -1203,3 +1203,17 @@ void rdar_8642434_funcB(struct rdar_8642434_typeA *x, struct rdar_8642434_typeA rdar_8642434_funcA(y); // expected-warning{{Null pointer passed as an argument to a 'nonnull' parameter}} } +// <rdar://problem/8848957> - Handle loads and stores from a symbolic index +// into array without warning about an uninitialized value being returned. +// While RegionStore can't fully reason about this example, it shouldn't +// warn here either. +typedef struct s_test_rdar8848957 { + int x, y, z; +} s_test_rdar8848957; + +s_test_rdar8848957 foo_rdar8848957(); +int rdar8848957(int index) { + s_test_rdar8848957 vals[10]; + vals[index] = foo_rdar8848957(); + return vals[index].x; // no-warning +} |