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
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))
// 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);
}
}
continue;
VarDecl *VD = LC.getCapturedVar();
- if (VD->getName() == "self")
+ if (isSelfDecl(VD))
return dyn_cast<ImplicitParamDecl>(VD);
}
});
}
+__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
}
@end
-
@implementation Sub
- (void)callMethodOnSuperInCXXLambda; {
// Explicit capture.
}();
}
+// 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;