From: Ted Kremenek Date: Wed, 25 Nov 2009 01:35:18 +0000 (+0000) Subject: Add really basic support for blocks in the retain/release checker. For now, anytime... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=772250ca0b15f9ba74e5cb97773815d3d3beffa4;p=clang 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 --- 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(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(L.getAsRegion())) { + Summ = Summaries.getPersistentStopSummary(); + } + else { + const FunctionDecl* FD = L.getAsFunctionDecl(); + Summ = !FD ? Summaries.getDefaultSummary() : + Summaries.getSummary(const_cast(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); +} +