From: Ted Kremenek Date: Thu, 26 Nov 2009 02:38:19 +0000 (+0000) Subject: Add a PostVisitBlockExpr() method to RetainReleaseChecker to query for X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=38cc6bca5c172e2888c86fb0bef6883db0692cf6;p=clang Add a PostVisitBlockExpr() method to RetainReleaseChecker to query for the set of variables "captured" by a block. Until the analysis gets more sophisticated, for now we stop the retain count tracking of any objects (transitively) referenced by these variables. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@89929 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Analysis/CFRefCount.cpp b/lib/Analysis/CFRefCount.cpp index 06aa6bd279..17a69a2b5a 100644 --- a/lib/Analysis/CFRefCount.cpp +++ b/lib/Analysis/CFRefCount.cpp @@ -24,6 +24,7 @@ #include "clang/Analysis/PathSensitive/GRTransferFuncs.h" #include "clang/Analysis/PathSensitive/CheckerVisitor.h" #include "clang/AST/DeclObjC.h" +#include "clang/AST/StmtVisitor.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/ImmutableMap.h" @@ -3646,10 +3647,35 @@ class VISIBILITY_HIDDEN RetainReleaseChecker CFRefCount *TF; public: RetainReleaseChecker(CFRefCount *tf) : TF(tf) {} - static void* getTag() { static int x = 0; return &x; } + static void* getTag() { static int x = 0; return &x; } + + void PostVisitBlockExpr(CheckerContext &C, const BlockExpr *BE); }; } // end anonymous namespace + +void RetainReleaseChecker::PostVisitBlockExpr(CheckerContext &C, + const BlockExpr *BE) { + + // Scan the BlockDecRefExprs for any object the retain/release checker + // may be tracking. + if (!BE->hasBlockDeclRefExprs()) + return; + + const GRState *state = C.getState(); + const BlockDataRegion *R = + cast(state->getSVal(BE).getAsRegion()); + + BlockDataRegion::referenced_vars_iterator I = R->referenced_vars_begin(), + E = R->referenced_vars_end(); + + if (I == E) + return; + + state = state->scanReachableSymbols(I, E).getState(); + C.addTransition(state); +} + //===----------------------------------------------------------------------===// // Transfer function creation for external clients. //===----------------------------------------------------------------------===// diff --git a/test/Analysis/retain-release.m b/test/Analysis/retain-release.m index 8c3fda27cc..bc9f0b7ef4 100644 --- a/test/Analysis/retain-release.m +++ b/test/Analysis/retain-release.m @@ -1281,7 +1281,6 @@ void test_blocks_1_pos(void) { ^{}(); } -#if 0 void test_blocks_1_indirect_release(void) { NSNumber *number = [[NSNumber alloc] initWithInt:5]; // no-warning ^{ [number release]; }(); @@ -1292,7 +1291,6 @@ void test_blocks_1_indirect_retain(void) { 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