[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
This commit is contained in:
Devin Coughlin 2016-02-23 22:26:04 +00:00
parent f9c0a5c377
commit c289b74bd6
3 changed files with 42 additions and 3 deletions

View File

@ -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<ImplicitParamDecl>(VD) && VD->getName() == "self";
}
const ImplicitParamDecl *AnalysisDeclContext::getSelfDecl() const {
if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(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<ImplicitParamDecl>(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<ImplicitParamDecl>(VD);
}

View File

@ -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

View File

@ -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;