From c289b74bd6c6837731459ef9620a859fdd158d4d 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 llvm-svn: 261703 --- clang/lib/Analysis/AnalysisDeclContext.cpp | 8 ++++++-- clang/test/Analysis/blocks.m | 22 ++++++++++++++++++++++ clang/test/Analysis/lambdas.mm | 15 ++++++++++++++- 3 files changed, 42 insertions(+), 3 deletions(-) diff --git a/clang/lib/Analysis/AnalysisDeclContext.cpp b/clang/lib/Analysis/AnalysisDeclContext.cpp index 94f753e..fe8021b 100644 --- a/clang/lib/Analysis/AnalysisDeclContext.cpp +++ b/clang/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/clang/test/Analysis/blocks.m b/clang/test/Analysis/blocks.m index 4dbe951..0b1c15a 100644 --- a/clang/test/Analysis/blocks.m +++ b/clang/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/clang/test/Analysis/lambdas.mm b/clang/test/Analysis/lambdas.mm index 6247f28..dc1a13e 100644 --- a/clang/test/Analysis/lambdas.mm +++ b/clang/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.7.4