forked from OSchip/llvm-project
[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:
parent
f9c0a5c377
commit
c289b74bd6
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue