diff options
-rw-r--r-- | lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp | 6 | ||||
-rw-r--r-- | test/Analysis/retain-release-region-store.m | 7 | ||||
-rw-r--r-- | test/Analysis/retain-release.m | 23 |
3 files changed, 35 insertions, 1 deletions
diff --git a/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp b/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp index 9255796172..a6d33ad2a0 100644 --- a/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp @@ -3341,6 +3341,12 @@ void RetainCountChecker::checkBind(SVal loc, SVal val, const Stmt *S, // the binding). escapes = (state == (state->bindLoc(*regionLoc, val))); } + if (!escapes) { + // Case 4: We do not currently model what happens when a symbol is + // assigned to a struct field, so be conservative here and let the symbol + // go. TODO: This could definitely be improved upon. + escapes = !isa<VarRegion>(regionLoc->getRegion()); + } } // If our store can represent the binding and we aren't storing to something diff --git a/test/Analysis/retain-release-region-store.m b/test/Analysis/retain-release-region-store.m index 1ff31b710d..917381341a 100644 --- a/test/Analysis/retain-release-region-store.m +++ b/test/Analysis/retain-release-region-store.m @@ -100,6 +100,10 @@ struct foo { NSDate* f; }; +// FIXME: We should be warning about a use-after-free here, but we +// temporarily "escape" retain counted objects stored to structs very eagerly +// until we can properly tell whether they have escaped via a return value +// or not. CFAbsoluteTime f4() { struct foo x; @@ -110,7 +114,8 @@ CFAbsoluteTime f4() { CFDateGetAbsoluteTime(date); // no-warning x.f = (NSDate*) date; [((NSDate*) date) release]; - t = CFDateGetAbsoluteTime(date); // expected-warning{{Reference-counted object is used after it is released}} + // FIXME: the following line should warn. + t = CFDateGetAbsoluteTime(date); // no-warning return t; } diff --git a/test/Analysis/retain-release.m b/test/Analysis/retain-release.m index 8b0e7b83a7..fb02427eb4 100644 --- a/test/Analysis/retain-release.m +++ b/test/Analysis/retain-release.m @@ -1668,6 +1668,29 @@ void rdar_10824732() { } //===----------------------------------------------------------------------===// +// Test returning allocated memory in a struct. +// +// We currently don't have a general way to track pointers that "escape". +// Here we test that RetainCountChecker doesn't get excited about returning +// allocated CF objects in struct fields. +//===----------------------------------------------------------------------===// +void *malloc(size_t); +struct rdar11104566 { CFStringRef myStr; }; +struct rdar11104566 test_rdar11104566() { + CFStringRef cf = CFStringCreateWithCString( ((CFAllocatorRef)0), "test", kCFStringEncodingUTF8 ); // no-warning + struct rdar11104566 V; + V.myStr = cf; + return V; // no-warning +} + +struct rdar11104566 *test_2_rdar11104566() { + CFStringRef cf = CFStringCreateWithCString( ((CFAllocatorRef)0), "test", kCFStringEncodingUTF8 ); // no-warning + struct rdar11104566 *V = (struct rdar11104566 *) malloc(sizeof(*V)); + V->myStr = cf; + return V; // no-warning +} + +//===----------------------------------------------------------------------===// // ObjC literals support. //===----------------------------------------------------------------------===// |