RegionStore: Use the *default* binding (instead of the *direct* binding) of an Objective-C object
region when doing lazy value retrieval of an ivar.
This fixes: <rdar://problem/7312221>
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@84584 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Analysis/RegionStore.cpp b/lib/Analysis/RegionStore.cpp
index 35eb5b7..780772a 100644
--- a/lib/Analysis/RegionStore.cpp
+++ b/lib/Analysis/RegionStore.cpp
@@ -1244,8 +1244,8 @@
const MemRegion *superR = R->getSuperRegion();
- // Check if the super region has a binding.
- if (Optional<SVal> V = getDirectBinding(B, superR)) {
+ // Check if the super region has a default binding.
+ if (Optional<SVal> V = getDefaultBinding(B, superR)) {
if (SymbolRef parentSym = V->getAsSymbol())
return ValMgr.getDerivedRegionValueSymbolVal(parentSym, R);
@@ -1792,7 +1792,7 @@
void RegionStoreManager::print(Store store, llvm::raw_ostream& OS,
const char* nl, const char *sep) {
RegionBindings B = GetRegionBindings(store);
- OS << "Store (direct bindings):" << nl;
+ OS << "Store (direct and default bindings):" << nl;
for (RegionBindings::iterator I = B.begin(), E = B.end(); I != E; ++I)
OS << ' ' << I.getKey() << " : " << I.getData() << nl;
diff --git a/test/Analysis/misc-ps-region-store.m b/test/Analysis/misc-ps-region-store.m
index e849042..b6fff10 100644
--- a/test/Analysis/misc-ps-region-store.m
+++ b/test/Analysis/misc-ps-region-store.m
@@ -141,9 +141,11 @@
}
}
+//===----------------------------------------------------------------------===//
// Reduced test case from <rdar://problem/7114618>.
// Basically a null check is performed on the field value, which is then
// assigned to a variable and then checked again.
+//===----------------------------------------------------------------------===//
struct s_7114618 { int *p; };
void test_rdar_7114618(struct s_7114618 *s) {
if (s->p) {
@@ -168,9 +170,11 @@
}
}
+//===----------------------------------------------------------------------===//
// <rdar://problem/7185607>
// Bit-fields of a struct should be invalidated when blasting the entire
// struct with an integer constant.
+//===----------------------------------------------------------------------===//
struct test_7185607 {
int x : 10;
int y : 22;
@@ -181,9 +185,11 @@
return s.x; // no-warning
}
+//===----------------------------------------------------------------------===//
// <rdar://problem/7242006> [RegionStore] compound literal assignment with
// floats not honored
// This test case is mirrored in misc-ps.m, but this case is a negative.
+//===----------------------------------------------------------------------===//
typedef float CGFloat;
typedef struct _NSSize {
CGFloat width;
@@ -195,9 +201,11 @@
return y.width; // expected-warning{{garbage}}
}
+//===----------------------------------------------------------------------===//
// <rdar://problem/7249340> - Allow binding of values to symbolic regions.
// This test case shows how RegionStore tracks the value bound to 'x'
// after the assignment.
+//===----------------------------------------------------------------------===//
typedef int* ptr_rdar_7249340;
void rdar_7249340(ptr_rdar_7249340 x) {
*x = 1;
@@ -207,11 +215,13 @@
*p = 0xDEADBEEF; // no-warning
}
+//===----------------------------------------------------------------------===//
// <rdar://problem/7249327> - This test case tests both value tracking of
// array values and that we handle symbolic values that are casted
// between different integer types. Note the assignment 'n = *a++'; here
// 'n' is and 'int' and '*a' is 'unsigned'. Previously we got a false positive
// at 'x += *b++' (undefined value) because we got a false path.
+//===----------------------------------------------------------------------===//
int rdar_7249327_aux(void);
void rdar_7249327(unsigned int A[2*32]) {
@@ -237,8 +247,10 @@
x += *b++; // no-warning
}
+//===----------------------------------------------------------------------===//
// <rdar://problem/6914474> - Check that 'x' is invalidated because its
// address is passed in as a value to a struct.
+//===----------------------------------------------------------------------===//
struct doodad_6914474 { int *v; };
extern void prod_6914474(struct doodad_6914474 *d);
int rdar_6914474(void) {
@@ -278,8 +290,11 @@
return p->z; // no-warning
}
+//===----------------------------------------------------------------------===//
// <rdar://problem/7261075> [RegionStore] crash when
// handling load: '*((unsigned int *)"????")'
+//===----------------------------------------------------------------------===//
+
int rdar_7261075(void) {
unsigned int var = 0;
if (var == *((unsigned int *)"????"))
@@ -287,8 +302,11 @@
return 0;
}
+//===----------------------------------------------------------------------===//
// <rdar://problem/7275774> false path due to limited pointer
// arithmetic constraints
+//===----------------------------------------------------------------------===//
+
void rdar_7275774(void *data, unsigned n) {
if (!(data || n == 0))
return;
@@ -303,3 +321,54 @@
}
}
+//===----------------------------------------------------------------------===//
+// <rdar://problem/7312221>
+//
+// Test that Objective-C instance variables aren't prematurely pruned
+// from the analysis state.
+//===----------------------------------------------------------------------===//
+
+struct rdar_7312221_value { int x; };
+
+@interface RDar7312221
+{
+ struct rdar_7312221_value *y;
+}
+- (void) doSomething_7312221;
+@end
+
+extern struct rdar_7312221_value *rdar_7312221_helper();
+extern int rdar_7312221_helper_2(id o);
+extern void rdar_7312221_helper_3(int z);
+
+@implementation RDar7312221
+- (void) doSomething_7312221 {
+ if (y == 0) {
+ y = rdar_7312221_helper();
+ if (y != 0) {
+ y->x = rdar_7312221_helper_2(self);
+ // The following use of 'y->x' previously triggered a null dereference, as the value of 'y'
+ // before 'y = rdar_7312221_helper()' would be used.
+ rdar_7312221_helper_3(y->x); // no-warning
+ }
+ }
+}
+@end
+
+struct rdar_7312221_container {
+ struct rdar_7312221_value *y;
+};
+
+extern int rdar_7312221_helper_4(struct rdar_7312221_container *s);
+
+// This test case essentially matches the one in [RDar7312221 doSomething_7312221].
+void doSomething_7312221_with_struct(struct rdar_7312221_container *Self) {
+ if (Self->y == 0) {
+ Self->y = rdar_7312221_helper();
+ if (Self->y != 0) {
+ Self->y->x = rdar_7312221_helper_4(Self);
+ rdar_7312221_helper_3(Self->y->x); // no-warning
+ }
+ }
+}
+