diff options
author | Jordan Rose <jordan_rose@apple.com> | 2012-09-17 17:54:30 +0000 |
---|---|---|
committer | Jordan Rose <jordan_rose@apple.com> | 2012-09-17 17:54:30 +0000 |
commit | 1fac58a2ff3c56a18765b2c7395ed91ac7b80544 (patch) | |
tree | 87ee0680f6b772ab093aa353dd530e9adb68af42 /lib/Sema/SemaChecking.cpp | |
parent | 8f411c39283caf2a403739b0c5dd398a6df511dc (diff) |
-Warc-retain-cycles: look through [^{...} copy] and Block_copy(^{...})
Retain cycles happen in the case where a block is persisted past its
life on the stack, and the way that occurs is by copying the block.
We should thus look through any explicit copies we see.
Note that Block_copy is actually a type-safe wrapper for _Block_copy,
which does all the real work.
<rdar://problem/12219663>
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@164039 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaChecking.cpp')
-rw-r--r-- | lib/Sema/SemaChecking.cpp | 18 |
1 files changed, 18 insertions, 0 deletions
diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp index 6d8d7f2c04..4c8418a533 100644 --- a/lib/Sema/SemaChecking.cpp +++ b/lib/Sema/SemaChecking.cpp @@ -5429,6 +5429,24 @@ static Expr *findCapturingExpr(Sema &S, Expr *e, RetainCycleOwner &owner) { assert(owner.Variable && owner.Loc.isValid()); e = e->IgnoreParenCasts(); + + // Look through [^{...} copy] and Block_copy(^{...}). + if (ObjCMessageExpr *ME = dyn_cast<ObjCMessageExpr>(e)) { + Selector Cmd = ME->getSelector(); + if (Cmd.isUnarySelector() && Cmd.getNameForSlot(0) == "copy") { + e = ME->getInstanceReceiver(); + if (!e) + return 0; + e = e->IgnoreParenCasts(); + } + } else if (CallExpr *CE = dyn_cast<CallExpr>(e)) { + if (CE->getNumArgs() == 1) { + FunctionDecl *Fn = dyn_cast_or_null<FunctionDecl>(CE->getCalleeDecl()); + if (Fn && Fn->getIdentifier()->isStr("_Block_copy")) + e = CE->getArg(0)->IgnoreParenCasts(); + } + } + BlockExpr *block = dyn_cast<BlockExpr>(e); if (!block || !block->getBlockDecl()->capturesVariable(owner.Variable)) return 0; |