From a02dd11cedf26a6484297e5fa345685036672e4c Mon Sep 17 00:00:00 2001 From: Devin Coughlin Date: Tue, 23 Feb 2016 22:26:04 +0000 Subject: [PATCH] [analyzer] Find ObjC 'self' decl even when block captures local named 'self'. When looking up the 'self' decl in block captures, make sure to find the actual self declaration even when the block captures a local variable named 'self'. rdar://problem/24751280 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@261703 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Analysis/AnalysisDeclContext.cpp | 8 ++++++-- test/Analysis/blocks.m | 22 ++++++++++++++++++++++ test/Analysis/lambdas.mm | 15 ++++++++++++++- 3 files changed, 42 insertions(+), 3 deletions(-) diff --git a/lib/Analysis/AnalysisDeclContext.cpp b/lib/Analysis/AnalysisDeclContext.cpp index 94f753ed91..fe8021b796 100644 --- a/lib/Analysis/AnalysisDeclContext.cpp +++ b/lib/Analysis/AnalysisDeclContext.cpp @@ -135,6 +135,10 @@ bool AnalysisDeclContext::isBodyAutosynthesizedFromModelFile() const { return Tmp && Body->getLocStart().isValid(); } +/// Returns true if \param VD is an Objective-C implicit 'self' parameter. +static bool isSelfDecl(const VarDecl *VD) { + return isa(VD) && VD->getName() == "self"; +} const ImplicitParamDecl *AnalysisDeclContext::getSelfDecl() const { if (const ObjCMethodDecl *MD = dyn_cast(D)) @@ -143,7 +147,7 @@ const ImplicitParamDecl *AnalysisDeclContext::getSelfDecl() const { // See if 'self' was captured by the block. for (const auto &I : BD->captures()) { const VarDecl *VD = I.getVariable(); - if (VD->getName() == "self") + if (isSelfDecl(VD)) return dyn_cast(VD); } } @@ -161,7 +165,7 @@ const ImplicitParamDecl *AnalysisDeclContext::getSelfDecl() const { continue; VarDecl *VD = LC.getCapturedVar(); - if (VD->getName() == "self") + if (isSelfDecl(VD)) return dyn_cast(VD); } diff --git a/test/Analysis/blocks.m b/test/Analysis/blocks.m index 4dbe951720..0b1c15abb3 100644 --- a/test/Analysis/blocks.m +++ b/test/Analysis/blocks.m @@ -210,3 +210,25 @@ void testCallContainingWithSignature5() }); } +__attribute__((objc_root_class)) +@interface SuperClass +- (void)someMethod; +@end + +@interface SomeClass : SuperClass +@end + +// Make sure to properly handle super-calls when a block captures +// a local variable named 'self'. +@implementation SomeClass +-(void)foo; { + /*__weak*/ SomeClass *weakSelf = self; + (void)(^(void) { + SomeClass *self = weakSelf; + (void)(^(void) { + (void)self; + [super someMethod]; // no-warning + }); + }); +} +@end diff --git a/test/Analysis/lambdas.mm b/test/Analysis/lambdas.mm index 6247f28870..dc1a13e8b6 100644 --- a/test/Analysis/lambdas.mm +++ b/test/Analysis/lambdas.mm @@ -12,7 +12,6 @@ int clang_analyzer_eval(int); } @end - @implementation Sub - (void)callMethodOnSuperInCXXLambda; { // Explicit capture. @@ -26,6 +25,20 @@ int clang_analyzer_eval(int); }(); } +// Make sure to properly handle super-calls when a block captures +// a local variable named 'self'. +- (void)callMethodOnSuperInCXXLambdaWithRedefinedSelf; { + /*__weak*/ Sub *weakSelf = self; + // Implicit capture. (Sema outlaws explicit capture of a redefined self + // and a call to super [which uses the original self]). + [=]() { + Sub *self = weakSelf; + [=]() { + [super superMethod]; + }(); + }(); +} + - (void)swapIvars { int tmp = _ivar1; _ivar1 = _ivar2; -- 2.40.0