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
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index fc87b23..9f7a8bf 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -7286,10 +7286,12 @@
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 @@
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 @@
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,