r210823 - Objective-C ARC. Blocks that strongly capture themselves

Fariborz Jahanian fjahanian at apple.com
Thu Jun 12 13:57:14 PDT 2014


Author: fjahanian
Date: Thu Jun 12 15:57:14 2014
New Revision: 210823

URL: http://llvm.org/viewvc/llvm-project?rev=210823&view=rev
Log:
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

Modified:
    cfe/trunk/lib/Sema/SemaChecking.cpp
    cfe/trunk/test/SemaObjC/warn-retain-cycle.m

Modified: cfe/trunk/lib/Sema/SemaChecking.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaChecking.cpp?rev=210823&r1=210822&r2=210823&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaChecking.cpp (original)
+++ cfe/trunk/lib/Sema/SemaChecking.cpp Thu Jun 12 15:57:14 2014
@@ -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,
 
   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,

Modified: cfe/trunk/test/SemaObjC/warn-retain-cycle.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/warn-retain-cycle.m?rev=210823&r1=210822&r2=210823&view=diff
==============================================================================
--- cfe/trunk/test/SemaObjC/warn-retain-cycle.m (original)
+++ cfe/trunk/test/SemaObjC/warn-retain-cycle.m Thu Jun 12 15:57:14 2014
@@ -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);
+        }
+   };
+
+}





More information about the cfe-commits mailing list