aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/StaticAnalyzer/Core/RegionStore.cpp25
-rw-r--r--test/Analysis/misc-ps-region-store.m16
2 files changed, 34 insertions, 7 deletions
diff --git a/lib/StaticAnalyzer/Core/RegionStore.cpp b/lib/StaticAnalyzer/Core/RegionStore.cpp
index 4cafddc08a..1619e6bc64 100644
--- a/lib/StaticAnalyzer/Core/RegionStore.cpp
+++ b/lib/StaticAnalyzer/Core/RegionStore.cpp
@@ -1194,14 +1194,23 @@ SVal RegionStoreManager::getBindingForFieldOrElementCommon(Store store,
// At this point we have already checked in either getBindingForElement or
// getBindingForField if 'R' has a direct binding.
-
RegionBindings B = GetRegionBindings(store);
+
+ // Record whether or not we see a symbolic index. That can completely
+ // be out of scope of our lookup.
+ bool hasSymbolicIndex = false;
while (superR) {
if (const Optional<SVal> &D =
getBindingForDerivedDefaultValue(B, superR, R, Ty))
return *D;
+ if (const ElementRegion *ER = dyn_cast<ElementRegion>(superR)) {
+ NonLoc index = ER->getIndex();
+ if (!index.isConstant())
+ hasSymbolicIndex = true;
+ }
+
// If our super region is a field or element itself, walk up the region
// hierarchy to see if there is a default value installed in an ancestor.
if (const SubRegion *SR = dyn_cast<SubRegion>(superR)) {
@@ -1220,7 +1229,7 @@ SVal RegionStoreManager::getBindingForFieldOrElementCommon(Store store,
return getLazyBinding(lazyBindingRegion, lazyBindingStore);
if (R->hasStackNonParametersStorage()) {
- if (const ElementRegion *ER = dyn_cast<ElementRegion>(R)) {
+ if (isa<ElementRegion>(R)) {
// Currently we don't reason specially about Clang-style vectors. Check
// if superR is a vector and if so return Unknown.
if (const TypedValueRegion *typedSuperR =
@@ -1228,13 +1237,15 @@ SVal RegionStoreManager::getBindingForFieldOrElementCommon(Store store,
if (typedSuperR->getValueType()->isVectorType())
return UnknownVal();
}
-
- // FIXME: We also need to take ElementRegions with symbolic indexes into
- // account.
- if (!ER->getIndex().isConstant())
- return UnknownVal();
}
+ // FIXME: We also need to take ElementRegions with symbolic indexes into
+ // account. This case handles both directly accessing an ElementRegion
+ // with a symbolic offset, but also fields within an element with
+ // a symbolic offset.
+ if (hasSymbolicIndex)
+ return UnknownVal();
+
return UndefinedVal();
}
diff --git a/test/Analysis/misc-ps-region-store.m b/test/Analysis/misc-ps-region-store.m
index 7268c909be..1c5b0b29dd 100644
--- a/test/Analysis/misc-ps-region-store.m
+++ b/test/Analysis/misc-ps-region-store.m
@@ -1325,3 +1325,19 @@ void rdar9444714() {
*dst = '\0';
}
+// Test handling symbolic elements with field accesses.
+// <rdar://problem/11127008>
+typedef struct {
+ unsigned value;
+} RDar11127008;
+
+signed rdar_11127008_index();
+
+static unsigned rdar_11127008(void) {
+ RDar11127008 values[] = {{.value = 0}, {.value = 1}};
+ signed index = rdar_11127008_index();
+ if (index < 0) return 0;
+ if (index >= 2) return 0;
+ return values[index].value;
+}
+