[cfe-commits] r171482 - in /cfe/trunk: lib/ARCMigrate/TransRetainReleaseDealloc.cpp test/ARCMT/autoreleases.m test/ARCMT/autoreleases.m.result

Argyrios Kyrtzidis akyrtzi at gmail.com
Fri Jan 4 10:29:59 PST 2013


Author: akirtzidis
Date: Fri Jan  4 12:29:59 2013
New Revision: 171482

URL: http://llvm.org/viewvc/llvm-project?rev=171482&view=rev
Log:
[arcmt] Don't error if an autoreleased variable is returned after the -autorelease.

rdar://12952025

Modified:
    cfe/trunk/lib/ARCMigrate/TransRetainReleaseDealloc.cpp
    cfe/trunk/test/ARCMT/autoreleases.m
    cfe/trunk/test/ARCMT/autoreleases.m.result

Modified: cfe/trunk/lib/ARCMigrate/TransRetainReleaseDealloc.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/ARCMigrate/TransRetainReleaseDealloc.cpp?rev=171482&r1=171481&r2=171482&view=diff
==============================================================================
--- cfe/trunk/lib/ARCMigrate/TransRetainReleaseDealloc.cpp (original)
+++ cfe/trunk/lib/ARCMigrate/TransRetainReleaseDealloc.cpp Fri Jan  4 12:29:59 2013
@@ -162,13 +162,26 @@
 private:
   /// \brief Checks for idioms where an unused -autorelease is common.
   ///
-  /// Currently only returns true for this idiom which is common in property
+  /// Returns true for this idiom which is common in property
   /// setters:
   ///
   ///   [backingValue autorelease];
   ///   backingValue = [newValue retain]; // in general a +1 assign
   ///
+  /// For these as well:
+  ///
+  ///   [[var retain] autorelease];
+  ///   return var;
+  ///
   bool isCommonUnusedAutorelease(ObjCMessageExpr *E) {
+    if (isPlusOneAssignAfterAutorelease(E))
+      return true;
+    if (isReturnedAfterAutorelease(E))
+      return true;
+    return false;
+  }
+
+  bool isReturnedAfterAutorelease(ObjCMessageExpr *E) {
     Expr *Rec = E->getInstanceReceiver();
     if (!Rec)
       return false;
@@ -177,6 +190,46 @@
     if (!RefD)
       return false;
 
+    Stmt *nextStmt = getNextStmt(E);
+    if (!nextStmt)
+      return false;
+
+    // Check for "return <variable>;".
+
+    if (ReturnStmt *RetS = dyn_cast<ReturnStmt>(nextStmt))
+      return RefD == getReferencedDecl(RetS->getRetValue());
+
+    return false;
+  }
+
+  bool isPlusOneAssignAfterAutorelease(ObjCMessageExpr *E) {
+    Expr *Rec = E->getInstanceReceiver();
+    if (!Rec)
+      return false;
+
+    Decl *RefD = getReferencedDecl(Rec);
+    if (!RefD)
+      return false;
+
+    Stmt *nextStmt = getNextStmt(E);
+    if (!nextStmt)
+      return false;
+
+    // Check for "RefD = [+1 retained object];".
+
+    if (BinaryOperator *Bop = dyn_cast<BinaryOperator>(nextStmt)) {
+      if (RefD != getReferencedDecl(Bop->getLHS()))
+        return false;
+      if (isPlusOneAssign(Bop))
+        return true;
+    }
+    return false;
+  }
+
+  Stmt *getNextStmt(Expr *E) {
+    if (!E)
+      return 0;
+
     Stmt *OuterS = E, *InnerS;
     do {
       InnerS = OuterS;
@@ -187,9 +240,7 @@
                       isa<ExprWithCleanups>(OuterS)));
     
     if (!OuterS)
-      return false;
-
-    // Find next statement after the -autorelease.
+      return 0;
 
     Stmt::child_iterator currChildS = OuterS->child_begin();
     Stmt::child_iterator childE = OuterS->child_end();
@@ -198,25 +249,15 @@
         break;
     }
     if (currChildS == childE)
-      return false;
+      return 0;
     ++currChildS;
     if (currChildS == childE)
-      return false;
+      return 0;
 
     Stmt *nextStmt = *currChildS;
     if (!nextStmt)
-      return false;
-    nextStmt = nextStmt->IgnoreImplicit();
-
-    // Check for "RefD = [+1 retained object];".
-    
-    if (BinaryOperator *Bop = dyn_cast<BinaryOperator>(nextStmt)) {
-      if (RefD != getReferencedDecl(Bop->getLHS()))
-        return false;
-      if (isPlusOneAssign(Bop))
-        return true;
-    }
-    return false;
+      return 0;
+    return nextStmt->IgnoreImplicit();
   }
 
   Decl *getReferencedDecl(Expr *E) {
@@ -224,6 +265,17 @@
       return 0;
 
     E = E->IgnoreParenCasts();
+    if (ObjCMessageExpr *ME = dyn_cast<ObjCMessageExpr>(E)) {
+      switch (ME->getMethodFamily()) {
+      case OMF_copy:
+      case OMF_autorelease:
+      case OMF_release:
+      case OMF_retain:
+        return getReferencedDecl(ME->getInstanceReceiver());
+      default:
+        return 0;
+      }
+    }
     if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E))
       return DRE->getDecl();
     if (MemberExpr *ME = dyn_cast<MemberExpr>(E))

Modified: cfe/trunk/test/ARCMT/autoreleases.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/ARCMT/autoreleases.m?rev=171482&r1=171481&r2=171482&view=diff
==============================================================================
--- cfe/trunk/test/ARCMT/autoreleases.m (original)
+++ cfe/trunk/test/ARCMT/autoreleases.m Fri Jan  4 12:29:59 2013
@@ -64,3 +64,8 @@
   [prevVal autorelease];
   prevVal = [newVal retain];
 }
+
+id test2(A* val) {
+  [[val retain] autorelease];
+  return val;
+}

Modified: cfe/trunk/test/ARCMT/autoreleases.m.result
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/ARCMT/autoreleases.m.result?rev=171482&r1=171481&r2=171482&view=diff
==============================================================================
--- cfe/trunk/test/ARCMT/autoreleases.m.result (original)
+++ cfe/trunk/test/ARCMT/autoreleases.m.result Fri Jan  4 12:29:59 2013
@@ -60,3 +60,7 @@
 void test(A *prevVal, A *newVal) {
   prevVal = newVal;
 }
+
+id test2(A* val) {
+  return val;
+}





More information about the cfe-commits mailing list