summaryrefslogtreecommitdiffstats
path: root/clang/lib/Sema/SemaDecl.cpp
diff options
context:
space:
mode:
authorAkira Hatanaka <ahatanaka@apple.com>2019-04-17 23:14:44 +0000
committerAkira Hatanaka <ahatanaka@apple.com>2019-04-17 23:14:44 +0000
commitac57af32843f0670b00eea5cf9f993241907f5ce (patch)
tree1dd7dcc16bdfc6db2e43e3c63db57466b41265ef /clang/lib/Sema/SemaDecl.cpp
parent0b19f5aef94c734f45d91b20b48e98b257692792 (diff)
downloadbcm5719-llvm-ac57af32843f0670b00eea5cf9f993241907f5ce.tar.gz
bcm5719-llvm-ac57af32843f0670b00eea5cf9f993241907f5ce.zip
[Sema][ObjC] Don't warn about an implicitly retained self if the
retaining block and all of the enclosing blocks are non-escaping. If the block implicitly retaining self doesn't escape, there is no risk of creating retain cycles, so clang shouldn't diagnose it and force users to add self-> to silence the diagnostic. Also, fix a bug where clang was failing to diagnose an implicitly retained self inside a c++ lambda nested inside a block. rdar://problem/25059955 Differential Revision: https://reviews.llvm.org/D60736 llvm-svn: 358624
Diffstat (limited to 'clang/lib/Sema/SemaDecl.cpp')
-rw-r--r--clang/lib/Sema/SemaDecl.cpp31
1 files changed, 31 insertions, 0 deletions
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index fbe258bb1d5..8e0badf444a 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -13150,6 +13150,35 @@ private:
bool IsLambda = false;
};
+static void diagnoseImplicitlyRetainedSelf(Sema &S) {
+ llvm::DenseMap<const BlockDecl *, bool> EscapeInfo;
+
+ auto IsOrNestedInEscapingBlock = [&](const BlockDecl *BD) {
+ if (EscapeInfo.count(BD))
+ return EscapeInfo[BD];
+
+ bool R = false;
+ const BlockDecl *CurBD = BD;
+
+ do {
+ R = !CurBD->doesNotEscape();
+ if (R)
+ break;
+ CurBD = CurBD->getParent()->getInnermostBlockDecl();
+ } while (CurBD);
+
+ return EscapeInfo[BD] = R;
+ };
+
+ // If the location where 'self' is implicitly retained is inside a escaping
+ // block, emit a diagnostic.
+ for (const std::pair<SourceLocation, const BlockDecl *> &P :
+ S.ImplicitlyRetainedSelfLocs)
+ if (IsOrNestedInEscapingBlock(P.second))
+ S.Diag(P.first, diag::warn_implicitly_retains_self)
+ << FixItHint::CreateInsertion(P.first, "self->");
+}
+
Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body,
bool IsInstantiation) {
FunctionDecl *FD = dcl ? dcl->getAsFunction() : nullptr;
@@ -13361,6 +13390,8 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body,
diag::warn_objc_secondary_init_missing_init_call);
getCurFunction()->ObjCWarnForNoInitDelegation = false;
}
+
+ diagnoseImplicitlyRetainedSelf(*this);
} else {
// Parsing the function declaration failed in some way. Pop the fake scope
// we pushed on.
OpenPOWER on IntegriCloud