aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTed Kremenek <kremenek@apple.com>2009-11-25 01:35:18 +0000
committerTed Kremenek <kremenek@apple.com>2009-11-25 01:35:18 +0000
commit772250ca0b15f9ba74e5cb97773815d3d3beffa4 (patch)
tree5c1ef04fe63f4839ab7b02b6938b8d344752984c
parent721903eca33f6115296083aed17685eaa73d3e8c (diff)
Add really basic support for blocks in the retain/release checker. For now, anytime we pass a tracked object to a block call we stop tracking it.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@89831 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Analysis/CFRefCount.cpp17
-rw-r--r--test/Analysis/retain-release.m37
2 files changed, 49 insertions, 5 deletions
diff --git a/lib/Analysis/CFRefCount.cpp b/lib/Analysis/CFRefCount.cpp
index 433e350acc..c0d306d57c 100644
--- a/lib/Analysis/CFRefCount.cpp
+++ b/lib/Analysis/CFRefCount.cpp
@@ -3052,9 +3052,20 @@ void CFRefCount::EvalCall(ExplodedNodeSet& Dst,
GRStmtNodeBuilder& Builder,
CallExpr* CE, SVal L,
ExplodedNode* Pred) {
- const FunctionDecl* FD = L.getAsFunctionDecl();
- RetainSummary* Summ = !FD ? Summaries.getDefaultSummary()
- : Summaries.getSummary(const_cast<FunctionDecl*>(FD));
+
+ RetainSummary *Summ = 0;
+
+ // FIXME: Better support for blocks. For now we stop tracking anything
+ // that is passed to blocks.
+ // FIXME: Need to handle variables that are "captured" by the block.
+ if (dyn_cast_or_null<BlockTextRegion>(L.getAsRegion())) {
+ Summ = Summaries.getPersistentStopSummary();
+ }
+ else {
+ const FunctionDecl* FD = L.getAsFunctionDecl();
+ Summ = !FD ? Summaries.getDefaultSummary() :
+ Summaries.getSummary(const_cast<FunctionDecl*>(FD));
+ }
assert(Summ);
EvalSummary(Dst, Eng, Builder, CE, 0, *Summ,
diff --git a/test/Analysis/retain-release.m b/test/Analysis/retain-release.m
index 76149bc021..8c3fda27cc 100644
--- a/test/Analysis/retain-release.m
+++ b/test/Analysis/retain-release.m
@@ -1,5 +1,5 @@
-// RUN: clang-cc -triple x86_64-apple-darwin10 -analyze -checker-cfref -analyzer-store=basic -verify %s
-// RUN: clang-cc -triple x86_64-apple-darwin10 -analyze -checker-cfref -analyzer-store=region -verify %s
+// RUN: clang-cc -triple x86_64-apple-darwin10 -analyze -checker-cfref -analyzer-store=basic -fblocks -verify %s
+// RUN: clang-cc -triple x86_64-apple-darwin10 -analyze -checker-cfref -analyzer-store=region -fblocks -verify %s
#if __has_feature(attribute_ns_returns_retained)
#define NS_RETURNS_RETAINED __attribute__((ns_returns_retained))
@@ -1272,3 +1272,36 @@ void test_panic_pos_2(int x) {
panic();
}
+//===----------------------------------------------------------------------===//
+// Test uses of blocks (closures)
+//===----------------------------------------------------------------------===//
+
+void test_blocks_1_pos(void) {
+ NSNumber *number = [[NSNumber alloc] initWithInt:5]; // expected-warning{{leak}}
+ ^{}();
+}
+
+#if 0
+void test_blocks_1_indirect_release(void) {
+ NSNumber *number = [[NSNumber alloc] initWithInt:5]; // no-warning
+ ^{ [number release]; }();
+}
+
+void test_blocks_1_indirect_retain(void) {
+ // Eventually this should be reported as a leak.
+ NSNumber *number = [[NSNumber alloc] initWithInt:5]; // no-warning
+ ^{ [number retain]; }();
+}
+#endif
+
+void test_blocks_1_indirect_release_via_call(void) {
+ NSNumber *number = [[NSNumber alloc] initWithInt:5]; // no-warning
+ ^(NSObject *o){ [o release]; }(number);
+}
+
+void test_blocks_1_indirect_retain_via_call(void) {
+ // Eventually this should be reported as a leak.
+ NSNumber *number = [[NSNumber alloc] initWithInt:5]; // no-warning
+ ^(NSObject *o){ [o retain]; }(number);
+}
+