1accaf19bc1129c0273ec50dba52318e60bc29103Benjamin Kramer//===--- TransAutoreleasePool.cpp - Transformations to ARC mode -----------===//
27196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis//
37196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis//                     The LLVM Compiler Infrastructure
47196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis//
57196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis// This file is distributed under the University of Illinois Open Source
67196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis// License. See LICENSE.TXT for details.
77196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis//
87196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis//===----------------------------------------------------------------------===//
97196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis//
107196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis// rewriteAutoreleasePool:
117196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis//
127196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis// Calls to NSAutoreleasePools will be rewritten as an @autorelease scope.
137196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis//
147196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis//  NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
157196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis//  ...
167196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis//  [pool release];
177196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis// ---->
187196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis//  @autorelease {
197196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis//  ...
207196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis//  }
217196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis//
227196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis// An NSAutoreleasePool will not be touched if:
237196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis// - There is not a corresponding -release/-drain in the same scope
247196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis// - Not all references of the NSAutoreleasePool variable can be removed
257196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis// - There is a variable that is declared inside the intended @autorelease scope
267196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis//   which is also used outside it.
277196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis//
287196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis//===----------------------------------------------------------------------===//
297196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
307196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis#include "Transforms.h"
317196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis#include "Internals.h"
32471c8b49982d1132f30b0b0da27fef94fd6e4f67Benjamin Kramer#include "clang/AST/ASTContext.h"
337196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis#include "clang/Basic/SourceManager.h"
3455fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/Sema/SemaDiagnostic.h"
357196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis#include <map>
367196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
377196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidisusing namespace clang;
387196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidisusing namespace arcmt;
397196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidisusing namespace trans;
407196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
417196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidisnamespace {
427196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
437196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidisclass ReleaseCollector : public RecursiveASTVisitor<ReleaseCollector> {
447196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  Decl *Dcl;
455f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner  SmallVectorImpl<ObjCMessageExpr *> &Releases;
467196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
477196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidispublic:
485f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner  ReleaseCollector(Decl *D, SmallVectorImpl<ObjCMessageExpr *> &releases)
497196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    : Dcl(D), Releases(releases) { }
507196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
517196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  bool VisitObjCMessageExpr(ObjCMessageExpr *E) {
527196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    if (!E->isInstanceMessage())
537196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis      return true;
547196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    if (E->getMethodFamily() != OMF_release)
557196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis      return true;
567196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    Expr *instance = E->getInstanceReceiver()->IgnoreParenCasts();
577196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    if (DeclRefExpr *DE = dyn_cast<DeclRefExpr>(instance)) {
587196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis      if (DE->getDecl() == Dcl)
597196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis        Releases.push_back(E);
607196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    }
617196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    return true;
627196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  }
637196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis};
647196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
657196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis}
667196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
677196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidisnamespace {
687196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
697196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidisclass AutoreleasePoolRewriter
707196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis                         : public RecursiveASTVisitor<AutoreleasePoolRewriter> {
717196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidispublic:
72b1094a0621c3bf91141f7cd9684ca80b357ae61eArgyrios Kyrtzidis  AutoreleasePoolRewriter(MigrationPass &pass)
736bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    : Body(nullptr), Pass(pass) {
747196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    PoolII = &pass.Ctx.Idents.get("NSAutoreleasePool");
757196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    DrainSel = pass.Ctx.Selectors.getNullarySelector(
767196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis                                                 &pass.Ctx.Idents.get("drain"));
777196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  }
787196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
7976a5245d7fb558625453ebe2281ee0bc9c93c245Argyrios Kyrtzidis  void transformBody(Stmt *body, Decl *ParentD) {
807196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    Body = body;
817196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    TraverseStmt(body);
827196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  }
837196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
847196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  ~AutoreleasePoolRewriter() {
855f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner    SmallVector<VarDecl *, 8> VarsToHandle;
867196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
877196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    for (std::map<VarDecl *, PoolVarInfo>::iterator
887196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis           I = PoolVars.begin(), E = PoolVars.end(); I != E; ++I) {
897196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis      VarDecl *var = I->first;
907196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis      PoolVarInfo &info = I->second;
917196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
927196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis      // Check that we can handle/rewrite all references of the pool.
937196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
947196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis      clearRefsIn(info.Dcl, info.Refs);
955f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner      for (SmallVectorImpl<PoolScope>::iterator
967196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis             scpI = info.Scopes.begin(),
977196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis             scpE = info.Scopes.end(); scpI != scpE; ++scpI) {
987196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis        PoolScope &scope = *scpI;
997196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis        clearRefsIn(*scope.Begin, info.Refs);
1007196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis        clearRefsIn(*scope.End, info.Refs);
1017196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis        clearRefsIn(scope.Releases.begin(), scope.Releases.end(), info.Refs);
1027196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis      }
1037196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
1047196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis      // Even if one reference is not handled we will not do anything about that
1057196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis      // pool variable.
1067196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis      if (info.Refs.empty())
1077196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis        VarsToHandle.push_back(var);
1087196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    }
1097196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
1107196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    for (unsigned i = 0, e = VarsToHandle.size(); i != e; ++i) {
1117196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis      PoolVarInfo &info = PoolVars[VarsToHandle[i]];
1127196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
1137196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis      Transaction Trans(Pass.TA);
1147196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
1157196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis      clearUnavailableDiags(info.Dcl);
1167196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis      Pass.TA.removeStmt(info.Dcl);
1177196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
1187196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis      // Add "@autoreleasepool { }"
1195f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner      for (SmallVectorImpl<PoolScope>::iterator
1207196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis             scpI = info.Scopes.begin(),
1217196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis             scpE = info.Scopes.end(); scpI != scpE; ++scpI) {
1227196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis        PoolScope &scope = *scpI;
1237196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis        clearUnavailableDiags(*scope.Begin);
1247196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis        clearUnavailableDiags(*scope.End);
1257196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis        if (scope.IsFollowedBySimpleReturnStmt) {
1267196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis          // Include the return in the scope.
1277196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis          Pass.TA.replaceStmt(*scope.Begin, "@autoreleasepool {");
1287196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis          Pass.TA.removeStmt(*scope.End);
1297196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis          Stmt::child_iterator retI = scope.End;
1307196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis          ++retI;
1317196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis          SourceLocation afterSemi = findLocationAfterSemi((*retI)->getLocEnd(),
1327196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis                                                           Pass.Ctx);
1337196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis          assert(afterSemi.isValid() &&
1347196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis                 "Didn't we check before setting IsFollowedBySimpleReturnStmt "
1357196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis                 "to true?");
1367196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis          Pass.TA.insertAfterToken(afterSemi, "\n}");
1377196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis          Pass.TA.increaseIndentation(
1387196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis                                SourceRange(scope.getIndentedRange().getBegin(),
1397196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis                                            (*retI)->getLocEnd()),
1407196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis                                      scope.CompoundParent->getLocStart());
1417196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis        } else {
1427196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis          Pass.TA.replaceStmt(*scope.Begin, "@autoreleasepool {");
1437196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis          Pass.TA.replaceStmt(*scope.End, "}");
1447196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis          Pass.TA.increaseIndentation(scope.getIndentedRange(),
1457196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis                                      scope.CompoundParent->getLocStart());
1467196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis        }
1477196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis      }
1487196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
1497196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis      // Remove rest of pool var references.
1505f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner      for (SmallVectorImpl<PoolScope>::iterator
1517196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis             scpI = info.Scopes.begin(),
1527196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis             scpE = info.Scopes.end(); scpI != scpE; ++scpI) {
1537196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis        PoolScope &scope = *scpI;
1545f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner        for (SmallVectorImpl<ObjCMessageExpr *>::iterator
1557196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis               relI = scope.Releases.begin(),
1567196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis               relE = scope.Releases.end(); relI != relE; ++relI) {
1577196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis          clearUnavailableDiags(*relI);
1587196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis          Pass.TA.removeStmt(*relI);
1597196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis        }
1607196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis      }
1617196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    }
1627196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  }
1637196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
1647196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  bool VisitCompoundStmt(CompoundStmt *S) {
1655f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner    SmallVector<PoolScope, 4> Scopes;
1667196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
1677196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    for (Stmt::child_iterator
1687196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis           I = S->body_begin(), E = S->body_end(); I != E; ++I) {
1697196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis      Stmt *child = getEssential(*I);
1707196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis      if (DeclStmt *DclS = dyn_cast<DeclStmt>(child)) {
1717196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis        if (DclS->isSingleDecl()) {
1727196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis          if (VarDecl *VD = dyn_cast<VarDecl>(DclS->getSingleDecl())) {
1737196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis            if (isNSAutoreleasePool(VD->getType())) {
1747196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis              PoolVarInfo &info = PoolVars[VD];
1757196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis              info.Dcl = DclS;
1767196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis              collectRefs(VD, S, info.Refs);
1777196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis              // Does this statement follow the pattern:
1787196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis              // NSAutoreleasePool * pool = [NSAutoreleasePool  new];
1797196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis              if (isPoolCreation(VD->getInit())) {
1807196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis                Scopes.push_back(PoolScope());
1817196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis                Scopes.back().PoolVar = VD;
1827196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis                Scopes.back().CompoundParent = S;
1837196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis                Scopes.back().Begin = I;
1847196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis              }
1857196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis            }
1867196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis          }
1877196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis        }
1887196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis      } else if (BinaryOperator *bop = dyn_cast<BinaryOperator>(child)) {
1897196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis        if (DeclRefExpr *dref = dyn_cast<DeclRefExpr>(bop->getLHS())) {
1907196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis          if (VarDecl *VD = dyn_cast<VarDecl>(dref->getDecl())) {
1917196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis            // Does this statement follow the pattern:
1927196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis            // pool = [NSAutoreleasePool  new];
1937196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis            if (isNSAutoreleasePool(VD->getType()) &&
1947196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis                isPoolCreation(bop->getRHS())) {
1957196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis              Scopes.push_back(PoolScope());
1967196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis              Scopes.back().PoolVar = VD;
1977196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis              Scopes.back().CompoundParent = S;
1987196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis              Scopes.back().Begin = I;
1997196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis            }
2007196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis          }
2017196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis        }
2027196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis      }
2037196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
2047196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis      if (Scopes.empty())
2057196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis        continue;
2067196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
2077196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis      if (isPoolDrain(Scopes.back().PoolVar, child)) {
2087196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis        PoolScope &scope = Scopes.back();
2097196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis        scope.End = I;
2107196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis        handlePoolScope(scope, S);
2117196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis        Scopes.pop_back();
2127196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis      }
2137196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    }
2147196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    return true;
2157196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  }
2167196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
2177196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidisprivate:
2187196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  void clearUnavailableDiags(Stmt *S) {
2197196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    if (S)
2207196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis      Pass.TA.clearDiagnostic(diag::err_unavailable,
2217196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis                              diag::err_unavailable_message,
2227196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis                              S->getSourceRange());
2237196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  }
2247196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
2257196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  struct PoolScope {
2267196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    VarDecl *PoolVar;
2277196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    CompoundStmt *CompoundParent;
2287196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    Stmt::child_iterator Begin;
2297196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    Stmt::child_iterator End;
2307196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    bool IsFollowedBySimpleReturnStmt;
2315f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner    SmallVector<ObjCMessageExpr *, 4> Releases;
2327196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
2336bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    PoolScope() : PoolVar(nullptr), CompoundParent(nullptr), Begin(), End(),
2347196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis                  IsFollowedBySimpleReturnStmt(false) { }
2357196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
2367196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    SourceRange getIndentedRange() const {
2377196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis      Stmt::child_iterator rangeS = Begin;
2387196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis      ++rangeS;
2397196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis      if (rangeS == End)
2407196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis        return SourceRange();
2417196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis      Stmt::child_iterator rangeE = Begin;
2427196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis      for (Stmt::child_iterator I = rangeS; I != End; ++I)
2437196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis        ++rangeE;
2447196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis      return SourceRange((*rangeS)->getLocStart(), (*rangeE)->getLocEnd());
2457196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    }
2467196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  };
2477196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
2487196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  class NameReferenceChecker : public RecursiveASTVisitor<NameReferenceChecker>{
2497196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    ASTContext &Ctx;
2507196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    SourceRange ScopeRange;
2517196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    SourceLocation &referenceLoc, &declarationLoc;
2527196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
2537196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  public:
2547196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    NameReferenceChecker(ASTContext &ctx, PoolScope &scope,
2557196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis                         SourceLocation &referenceLoc,
2567196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis                         SourceLocation &declarationLoc)
2577196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis      : Ctx(ctx), referenceLoc(referenceLoc),
2587196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis        declarationLoc(declarationLoc) {
2597196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis      ScopeRange = SourceRange((*scope.Begin)->getLocStart(),
2607196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis                               (*scope.End)->getLocStart());
2617196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    }
2627196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
2637196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    bool VisitDeclRefExpr(DeclRefExpr *E) {
2647196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis      return checkRef(E->getLocation(), E->getDecl()->getLocation());
2657196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    }
2667196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
2677196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    bool VisitTypedefTypeLoc(TypedefTypeLoc TL) {
2687196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis      return checkRef(TL.getBeginLoc(), TL.getTypedefNameDecl()->getLocation());
2697196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    }
2707196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
2717196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    bool VisitTagTypeLoc(TagTypeLoc TL) {
2727196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis      return checkRef(TL.getBeginLoc(), TL.getDecl()->getLocation());
2737196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    }
2747196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
2757196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  private:
2767196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    bool checkRef(SourceLocation refLoc, SourceLocation declLoc) {
2777196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis      if (isInScope(declLoc)) {
2787196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis        referenceLoc = refLoc;
2797196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis        declarationLoc = declLoc;
2807196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis        return false;
2817196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis      }
2827196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis      return true;
2837196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    }
2847196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
2857196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    bool isInScope(SourceLocation loc) {
28618fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis      if (loc.isInvalid())
28718fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis        return false;
28818fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis
2897196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis      SourceManager &SM = Ctx.getSourceManager();
2907196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis      if (SM.isBeforeInTranslationUnit(loc, ScopeRange.getBegin()))
2917196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis        return false;
2927196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis      return SM.isBeforeInTranslationUnit(loc, ScopeRange.getEnd());
2937196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    }
2947196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  };
2957196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
2967196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  void handlePoolScope(PoolScope &scope, CompoundStmt *compoundS) {
2977196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    // Check that all names declared inside the scope are not used
2987196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    // outside the scope.
2997196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    {
3007196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis      bool nameUsedOutsideScope = false;
3017196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis      SourceLocation referenceLoc, declarationLoc;
3027196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis      Stmt::child_iterator SI = scope.End, SE = compoundS->body_end();
3037196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis      ++SI;
3047196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis      // Check if the autoreleasepool scope is followed by a simple return
3057196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis      // statement, in which case we will include the return in the scope.
3067196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis      if (SI != SE)
3077196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis        if (ReturnStmt *retS = dyn_cast<ReturnStmt>(*SI))
3086bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines          if ((retS->getRetValue() == nullptr ||
3097196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis               isa<DeclRefExpr>(retS->getRetValue()->IgnoreParenCasts())) &&
3107196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis              findLocationAfterSemi(retS->getLocEnd(), Pass.Ctx).isValid()) {
3117196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis            scope.IsFollowedBySimpleReturnStmt = true;
3127196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis            ++SI; // the return will be included in scope, don't check it.
3137196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis          }
3147196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
3157196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis      for (; SI != SE; ++SI) {
3167196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis        nameUsedOutsideScope = !NameReferenceChecker(Pass.Ctx, scope,
3177196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis                                                     referenceLoc,
3187196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis                                              declarationLoc).TraverseStmt(*SI);
3197196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis        if (nameUsedOutsideScope)
3207196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis          break;
3217196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis      }
3227196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
3237196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis      // If not all references were cleared it means some variables/typenames/etc
3247196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis      // declared inside the pool scope are used outside of it.
3257196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis      // We won't try to rewrite the pool.
3267196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis      if (nameUsedOutsideScope) {
3277196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis        Pass.TA.reportError("a name is referenced outside the "
3287196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis            "NSAutoreleasePool scope that it was declared in", referenceLoc);
3297196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis        Pass.TA.reportNote("name declared here", declarationLoc);
3307196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis        Pass.TA.reportNote("intended @autoreleasepool scope begins here",
3317196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis                           (*scope.Begin)->getLocStart());
3327196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis        Pass.TA.reportNote("intended @autoreleasepool scope ends here",
3337196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis                           (*scope.End)->getLocStart());
3347196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis        return;
3357196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis      }
3367196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    }
3377196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
3387196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    // Collect all releases of the pool; they will be removed.
3397196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    {
3407196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis      ReleaseCollector releaseColl(scope.PoolVar, scope.Releases);
3417196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis      Stmt::child_iterator I = scope.Begin;
3427196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis      ++I;
3437196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis      for (; I != scope.End; ++I)
3447196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis        releaseColl.TraverseStmt(*I);
3457196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    }
3467196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
3477196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    PoolVars[scope.PoolVar].Scopes.push_back(scope);
3487196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  }
3497196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
3507196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  bool isPoolCreation(Expr *E) {
3517196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    if (!E) return false;
3527196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    E = getEssential(E);
3537196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    ObjCMessageExpr *ME = dyn_cast<ObjCMessageExpr>(E);
3547196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    if (!ME) return false;
3557196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    if (ME->getMethodFamily() == OMF_new &&
3567196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis        ME->getReceiverKind() == ObjCMessageExpr::Class &&
3577196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis        isNSAutoreleasePool(ME->getReceiverInterface()))
3587196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis      return true;
3597196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    if (ME->getReceiverKind() == ObjCMessageExpr::Instance &&
3607196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis        ME->getMethodFamily() == OMF_init) {
3617196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis      Expr *rec = getEssential(ME->getInstanceReceiver());
3627196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis      if (ObjCMessageExpr *recME = dyn_cast_or_null<ObjCMessageExpr>(rec)) {
3637196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis        if (recME->getMethodFamily() == OMF_alloc &&
3647196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis            recME->getReceiverKind() == ObjCMessageExpr::Class &&
3657196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis            isNSAutoreleasePool(recME->getReceiverInterface()))
3667196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis          return true;
3677196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis      }
3687196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    }
3697196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
3707196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    return false;
3717196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  }
3727196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
3737196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  bool isPoolDrain(VarDecl *poolVar, Stmt *S) {
3747196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    if (!S) return false;
3757196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    S = getEssential(S);
3767196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    ObjCMessageExpr *ME = dyn_cast<ObjCMessageExpr>(S);
3777196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    if (!ME) return false;
3787196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    if (ME->getReceiverKind() == ObjCMessageExpr::Instance) {
3797196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis      Expr *rec = getEssential(ME->getInstanceReceiver());
3807196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis      if (DeclRefExpr *dref = dyn_cast<DeclRefExpr>(rec))
3817196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis        if (dref->getDecl() == poolVar)
3827196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis          return ME->getMethodFamily() == OMF_release ||
3837196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis                 ME->getSelector() == DrainSel;
3847196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    }
3857196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
3867196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    return false;
3877196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  }
3887196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
3897196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  bool isNSAutoreleasePool(ObjCInterfaceDecl *IDecl) {
3907196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    return IDecl && IDecl->getIdentifier() == PoolII;
3917196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  }
3927196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
3937196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  bool isNSAutoreleasePool(QualType Ty) {
3947196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    QualType pointee = Ty->getPointeeType();
3957196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    if (pointee.isNull())
3967196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis      return false;
3977196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    if (const ObjCInterfaceType *interT = pointee->getAs<ObjCInterfaceType>())
3987196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis      return isNSAutoreleasePool(interT->getDecl());
3997196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    return false;
4007196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  }
4017196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
4027196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  static Expr *getEssential(Expr *E) {
4037196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    return cast<Expr>(getEssential((Stmt*)E));
4047196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  }
4057196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  static Stmt *getEssential(Stmt *S) {
4067196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    if (ExprWithCleanups *EWC = dyn_cast<ExprWithCleanups>(S))
4077196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis      S = EWC->getSubExpr();
4087196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    if (Expr *E = dyn_cast<Expr>(S))
4097196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis      S = E->IgnoreParenCasts();
4107196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    return S;
4117196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  }
4127196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
4137196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  Stmt *Body;
4147196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  MigrationPass &Pass;
4157196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
4167196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  IdentifierInfo *PoolII;
4177196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  Selector DrainSel;
4187196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
4197196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  struct PoolVarInfo {
4207196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    DeclStmt *Dcl;
4217196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    ExprSet Refs;
4225f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner    SmallVector<PoolScope, 2> Scopes;
4237196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
4246bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    PoolVarInfo() : Dcl(nullptr) { }
4257196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  };
4267196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
4277196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  std::map<VarDecl *, PoolVarInfo> PoolVars;
4287196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis};
4297196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
4307196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis} // anonymous namespace
4317196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
4327196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidisvoid trans::rewriteAutoreleasePool(MigrationPass &pass) {
4337196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  BodyTransform<AutoreleasePoolRewriter> trans(pass);
4347196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  trans.TraverseDecl(pass.Ctx.getTranslationUnitDecl());
4357196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis}
436