diff --git a/clang/lib/Analysis/AnalysisDeclContext.cpp b/clang/lib/Analysis/AnalysisDeclContext.cpp index 94f753ed9128..fe8021b7966c 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 4dbe95172073..0b1c15abb3b3 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 6247f28870fb..dc1a13e8b69d 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;