summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTed Kremenek <kremenek@apple.com>2011-01-13 06:58:15 +0000
committerTed Kremenek <kremenek@apple.com>2011-01-13 06:58:15 +0000
commit304b6e4aa11126919a1bf5c8ab1c5b7a334573c4 (patch)
tree7c887e2b755c6420f7d7a7b7c850099bb0cbe507
parentda2d2f4d1f960f40f62fdbf011eae8fef8c83496 (diff)
downloadbcm5719-llvm-304b6e4aa11126919a1bf5c8ab1c5b7a334573c4.tar.gz
bcm5719-llvm-304b6e4aa11126919a1bf5c8ab1c5b7a334573c4.zip
Fix a corner case in RegionStore where we assign
a struct value to a symbolic index into array. RegionStore can't actually reason about this, so we were getting bogus warnings about loading uninitialized values from the array. The solution is invalidate the entire array when we cannot represent the binding explicitly. Fixes <rdar://problem/8848957> llvm-svn: 123368
-rw-r--r--clang/lib/StaticAnalyzer/RegionStore.cpp29
-rw-r--r--clang/test/Analysis/misc-ps-region-store.m14
2 files changed, 41 insertions, 2 deletions
diff --git a/clang/lib/StaticAnalyzer/RegionStore.cpp b/clang/lib/StaticAnalyzer/RegionStore.cpp
index def1b43f345..e47a77e6fc8 100644
--- a/clang/lib/StaticAnalyzer/RegionStore.cpp
+++ b/clang/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/clang/test/Analysis/misc-ps-region-store.m b/clang/test/Analysis/misc-ps-region-store.m
index 0a6884be063..13a2c1fbe9a 100644
--- a/clang/test/Analysis/misc-ps-region-store.m
+++ b/clang/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
+}
OpenPOWER on IntegriCloud