]> granicus.if.org Git - clang/commitdiff
[analyzer] Find ObjC 'self' decl even when block captures local named 'self'.
authorDevin Coughlin <dcoughlin@apple.com>
Tue, 23 Feb 2016 22:26:04 +0000 (22:26 +0000)
committerDevin Coughlin <dcoughlin@apple.com>
Tue, 23 Feb 2016 22:26:04 +0000 (22:26 +0000)
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

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@261703 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Analysis/AnalysisDeclContext.cpp
test/Analysis/blocks.m
test/Analysis/lambdas.mm

index 94f753ed912809815300969448f7caf3859694f0..fe8021b7966c804e51161515db13197fcbc1c727 100644 (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);
   }
 
index 4dbe951720738c8bf4fff688ecad1b17e30ab1bf..0b1c15abb3b3e0bca309111f9cfcb369a3d00824 100644 (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
index 6247f28870fb859219a347a457ec28f7a54b842d..dc1a13e8b69dc2351a37b4cfe7a1d612c5b2ecdb 100644 (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;