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