diff options
author | Akira Hatanaka <ahatanaka@apple.com> | 2019-04-17 23:14:44 +0000 |
---|---|---|
committer | Akira Hatanaka <ahatanaka@apple.com> | 2019-04-17 23:14:44 +0000 |
commit | ac57af32843f0670b00eea5cf9f993241907f5ce (patch) | |
tree | 1dd7dcc16bdfc6db2e43e3c63db57466b41265ef /clang/lib/Sema/SemaDecl.cpp | |
parent | 0b19f5aef94c734f45d91b20b48e98b257692792 (diff) | |
download | bcm5719-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.cpp | 31 |
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. |