summaryrefslogtreecommitdiffstats
path: root/clang
diff options
context:
space:
mode:
authorFariborz Jahanian <fjahanian@apple.com>2014-06-12 20:57:14 +0000
committerFariborz Jahanian <fjahanian@apple.com>2014-06-12 20:57:14 +0000
commit8df9e2438bee1289183b7cbf76b521d4c66237d3 (patch)
tree26411864f3ae3fcede78432a0d4b2c85b53926ea /clang
parentd104c31fc0b62dca30debb8a4647aea44eb79ec9 (diff)
downloadbcm5719-llvm-8df9e2438bee1289183b7cbf76b521d4c66237d3.tar.gz
bcm5719-llvm-8df9e2438bee1289183b7cbf76b521d4c66237d3.zip
Objective-C ARC. Blocks that strongly capture themselves
to call themselves will get the warning: "Capturing <itself> strongly in this block is likely to lead to a retain cycle". Cut down on the amount of noise by noticing that user at some point sets the captured variable to null in order to release it (and break the cycle). // rdar://16944538 llvm-svn: 210823
Diffstat (limited to 'clang')
-rw-r--r--clang/lib/Sema/SemaChecking.cpp23
-rw-r--r--clang/test/SemaObjC/warn-retain-cycle.m18
2 files changed, 36 insertions, 5 deletions
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index fc87b231d64..9f7a8bf7b38 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -7286,10 +7286,12 @@ namespace {
struct FindCaptureVisitor : EvaluatedExprVisitor<FindCaptureVisitor> {
FindCaptureVisitor(ASTContext &Context, VarDecl *variable)
: EvaluatedExprVisitor<FindCaptureVisitor>(Context),
- Variable(variable), Capturer(nullptr) {}
-
+ Context(Context), Variable(variable), Capturer(nullptr),
+ VarWillBeReased(false) {}
+ ASTContext &Context;
VarDecl *Variable;
Expr *Capturer;
+ bool VarWillBeReased;
void VisitDeclRefExpr(DeclRefExpr *ref) {
if (ref->getDecl() == Variable && !Capturer)
@@ -7314,6 +7316,21 @@ namespace {
if (OVE->getSourceExpr())
Visit(OVE->getSourceExpr());
}
+ void VisitBinaryOperator(BinaryOperator *BinOp) {
+ if (!Variable || VarWillBeReased || BinOp->getOpcode() != BO_Assign)
+ return;
+ Expr *LHS = BinOp->getLHS();
+ if (const DeclRefExpr *DRE = dyn_cast_or_null<DeclRefExpr>(LHS)) {
+ if (DRE->getDecl() != Variable)
+ return;
+ if (Expr *RHS = BinOp->getRHS()) {
+ RHS = RHS->IgnoreParenCasts();
+ llvm::APSInt Value;
+ VarWillBeReased =
+ (RHS && RHS->isIntegerConstantExpr(Value, Context) && Value == 0);
+ }
+ }
+ }
};
}
@@ -7351,7 +7368,7 @@ static Expr *findCapturingExpr(Sema &S, Expr *e, RetainCycleOwner &owner) {
FindCaptureVisitor visitor(S.Context, owner.Variable);
visitor.Visit(block->getBlockDecl()->getBody());
- return visitor.Capturer;
+ return visitor.VarWillBeReased ? nullptr : visitor.Capturer;
}
static void diagnoseRetainCycle(Sema &S, Expr *capturer,
diff --git a/clang/test/SemaObjC/warn-retain-cycle.m b/clang/test/SemaObjC/warn-retain-cycle.m
index eb4e966c772..4398d29e4a8 100644
--- a/clang/test/SemaObjC/warn-retain-cycle.m
+++ b/clang/test/SemaObjC/warn-retain-cycle.m
@@ -122,8 +122,8 @@ void doSomething(unsigned v);
// Sanity check that we are really whitelisting 'addOperationWithBlock:' and not doing
// something funny.
[myOperationQueue addSomethingElse:^() { // expected-note {{block will be retained by an object strongly retained by the captured object}}
- if (count > 20) { // expected-warning {{capturing 'self' strongly in this block is likely to lead to a retain cycle}}
- doSomething(count);
+ if (count > 20) {
+ doSomething(count); // expected-warning {{capturing 'self' strongly in this block is likely to lead to a retain cycle}}
}
}];
}
@@ -184,3 +184,17 @@ void testCopying(Test0 *obj) {
})];
}
+// rdar://16944538
+void func(int someCondition) {
+
+__block void(^myBlock)(void) = ^{
+ if (someCondition) {
+ doSomething(1);
+ myBlock();
+ }
+ else {
+ myBlock = ((void*)0);
+ }
+ };
+
+}
OpenPOWER on IntegriCloud