diff options
-rw-r--r-- | lib/Analysis/CFRefCount.cpp | 28 | ||||
-rw-r--r-- | test/Analysis/retain-release.m | 2 |
2 files changed, 27 insertions, 3 deletions
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<BlockDataRegion>(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<StopTrackingCallback>(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 |