18f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall//===--- Tranforms.cpp - Tranformations to ARC mode -----------------------===// 28f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall// 38f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall// The LLVM Compiler Infrastructure 48f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall// 58f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall// This file is distributed under the University of Illinois Open Source 68f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall// License. See LICENSE.TXT for details. 78f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall// 88f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall//===----------------------------------------------------------------------===// 98f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall 107196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis#include "Transforms.h" 118f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall#include "Internals.h" 128f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall#include "clang/Sema/SemaDiagnostic.h" 138f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall#include "clang/AST/RecursiveASTVisitor.h" 148f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall#include "clang/AST/StmtVisitor.h" 158f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall#include "clang/Lex/Lexer.h" 168f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall#include "clang/Basic/SourceManager.h" 178f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall#include "llvm/ADT/StringSwitch.h" 188f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall#include "llvm/ADT/DenseSet.h" 198f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall#include <map> 208f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall 218f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCallusing namespace clang; 228f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCallusing namespace arcmt; 237196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidisusing namespace trans; 248f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall 25e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios KyrtzidisASTTraverser::~ASTTraverser() { } 26e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis 278f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall//===----------------------------------------------------------------------===// 287196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis// Helpers. 298f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall//===----------------------------------------------------------------------===// 308f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall 3112192cf50a96cb59a3039af044b7fa97f043101cArgyrios Kyrtzidisbool trans::canApplyWeak(ASTContext &Ctx, QualType type, 3212192cf50a96cb59a3039af044b7fa97f043101cArgyrios Kyrtzidis bool AllowOnUnknownClass) { 334e4d08403ca5cfd4d558fa2936215d3a4e5a528dDavid Blaikie if (!Ctx.getLangOpts().ObjCRuntimeHasWeak) 3486625b5650cdddc38c0b4cc1eb7fb460478c9d11Argyrios Kyrtzidis return false; 3586625b5650cdddc38c0b4cc1eb7fb460478c9d11Argyrios Kyrtzidis 3686625b5650cdddc38c0b4cc1eb7fb460478c9d11Argyrios Kyrtzidis QualType T = type; 37b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis if (T.isNull()) 38b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis return false; 39b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis 402af504bf157cce51bdb4a9bab0e6d3b34f898f6eArgyrios Kyrtzidis // iOS is always safe to use 'weak'. 412af504bf157cce51bdb4a9bab0e6d3b34f898f6eArgyrios Kyrtzidis if (Ctx.getTargetInfo().getTriple().getOS() == llvm::Triple::IOS) 422af504bf157cce51bdb4a9bab0e6d3b34f898f6eArgyrios Kyrtzidis AllowOnUnknownClass = true; 432af504bf157cce51bdb4a9bab0e6d3b34f898f6eArgyrios Kyrtzidis 4486625b5650cdddc38c0b4cc1eb7fb460478c9d11Argyrios Kyrtzidis while (const PointerType *ptr = T->getAs<PointerType>()) 4586625b5650cdddc38c0b4cc1eb7fb460478c9d11Argyrios Kyrtzidis T = ptr->getPointeeType(); 4686625b5650cdddc38c0b4cc1eb7fb460478c9d11Argyrios Kyrtzidis if (const ObjCObjectPointerType *ObjT = T->getAs<ObjCObjectPointerType>()) { 4786625b5650cdddc38c0b4cc1eb7fb460478c9d11Argyrios Kyrtzidis ObjCInterfaceDecl *Class = ObjT->getInterfaceDecl(); 4812192cf50a96cb59a3039af044b7fa97f043101cArgyrios Kyrtzidis if (!AllowOnUnknownClass && (!Class || Class->getName() == "NSObject")) 4986625b5650cdddc38c0b4cc1eb7fb460478c9d11Argyrios Kyrtzidis return false; // id/NSObject is not safe for weak. 507723fec9b45b7258c0eddf4cbfd0d335348f5edcDouglas Gregor if (!AllowOnUnknownClass && !Class->hasDefinition()) 515363e8df5d274cb32c0c47fd2df45aa02cf68dfeArgyrios Kyrtzidis return false; // forward classes are not verifiable, therefore not safe. 5286625b5650cdddc38c0b4cc1eb7fb460478c9d11Argyrios Kyrtzidis if (Class->isArcWeakrefUnavailable()) 5386625b5650cdddc38c0b4cc1eb7fb460478c9d11Argyrios Kyrtzidis return false; 5486625b5650cdddc38c0b4cc1eb7fb460478c9d11Argyrios Kyrtzidis } 5586625b5650cdddc38c0b4cc1eb7fb460478c9d11Argyrios Kyrtzidis 5686625b5650cdddc38c0b4cc1eb7fb460478c9d11Argyrios Kyrtzidis return true; 5786625b5650cdddc38c0b4cc1eb7fb460478c9d11Argyrios Kyrtzidis} 5886625b5650cdddc38c0b4cc1eb7fb460478c9d11Argyrios Kyrtzidis 597196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis/// \brief 'Loc' is the end of a statement range. This returns the location 607196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis/// immediately after the semicolon following the statement. 617196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis/// If no semicolon is found or the location is inside a macro, the returned 627196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis/// source location will be invalid. 637196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios KyrtzidisSourceLocation trans::findLocationAfterSemi(SourceLocation loc, 647196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis ASTContext &Ctx) { 65aec230d29835285777ecc467e268c83b33a2addeArgyrios Kyrtzidis SourceLocation SemiLoc = findSemiAfterLocation(loc, Ctx); 66aec230d29835285777ecc467e268c83b33a2addeArgyrios Kyrtzidis if (SemiLoc.isInvalid()) 67aec230d29835285777ecc467e268c83b33a2addeArgyrios Kyrtzidis return SourceLocation(); 68a64ccefdf0ea4e03ec88805d71b0af74950c7472Argyrios Kyrtzidis return SemiLoc.getLocWithOffset(1); 69aec230d29835285777ecc467e268c83b33a2addeArgyrios Kyrtzidis} 70aec230d29835285777ecc467e268c83b33a2addeArgyrios Kyrtzidis 71aec230d29835285777ecc467e268c83b33a2addeArgyrios Kyrtzidis/// \brief \arg Loc is the end of a statement range. This returns the location 72aec230d29835285777ecc467e268c83b33a2addeArgyrios Kyrtzidis/// of the semicolon following the statement. 73aec230d29835285777ecc467e268c83b33a2addeArgyrios Kyrtzidis/// If no semicolon is found or the location is inside a macro, the returned 74aec230d29835285777ecc467e268c83b33a2addeArgyrios Kyrtzidis/// source location will be invalid. 75aec230d29835285777ecc467e268c83b33a2addeArgyrios KyrtzidisSourceLocation trans::findSemiAfterLocation(SourceLocation loc, 76aec230d29835285777ecc467e268c83b33a2addeArgyrios Kyrtzidis ASTContext &Ctx) { 777196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis SourceManager &SM = Ctx.getSourceManager(); 787196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis if (loc.isMacroID()) { 794e4d08403ca5cfd4d558fa2936215d3a4e5a528dDavid Blaikie if (!Lexer::isAtEndOfMacroExpansion(loc, SM, Ctx.getLangOpts(), &loc)) 807196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis return SourceLocation(); 817196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis } 824e4d08403ca5cfd4d558fa2936215d3a4e5a528dDavid Blaikie loc = Lexer::getLocForEndOfToken(loc, /*Offset=*/0, SM, Ctx.getLangOpts()); 838f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall 847196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis // Break down the source location. 857196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis std::pair<FileID, unsigned> locInfo = SM.getDecomposedLoc(loc); 868f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall 877196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis // Try to load the file buffer. 887196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis bool invalidTemp = false; 895f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner StringRef file = SM.getBufferData(locInfo.first, &invalidTemp); 907196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis if (invalidTemp) 917196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis return SourceLocation(); 927196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 937196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis const char *tokenBegin = file.data() + locInfo.second; 947196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 957196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis // Lex from the start of the given location. 967196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis Lexer lexer(SM.getLocForStartOfFile(locInfo.first), 974e4d08403ca5cfd4d558fa2936215d3a4e5a528dDavid Blaikie Ctx.getLangOpts(), 987196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis file.begin(), tokenBegin, file.end()); 997196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis Token tok; 1007196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis lexer.LexFromRawLexer(tok); 1017196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis if (tok.isNot(tok::semi)) 1027196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis return SourceLocation(); 1038f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall 104aec230d29835285777ecc467e268c83b33a2addeArgyrios Kyrtzidis return tok.getLocation(); 1057196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis} 1068f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall 1077196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidisbool trans::hasSideEffects(Expr *E, ASTContext &Ctx) { 1088f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall if (!E || !E->HasSideEffects(Ctx)) 1098f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall return false; 1108f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall 1118f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall E = E->IgnoreParenCasts(); 1128f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall ObjCMessageExpr *ME = dyn_cast<ObjCMessageExpr>(E); 1138f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall if (!ME) 1148f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall return true; 1158f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall switch (ME->getMethodFamily()) { 1168f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall case OMF_autorelease: 1178f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall case OMF_dealloc: 1188f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall case OMF_release: 1198f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall case OMF_retain: 1208f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall switch (ME->getReceiverKind()) { 1218f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall case ObjCMessageExpr::SuperInstance: 1228f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall return false; 1238f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall case ObjCMessageExpr::Instance: 1247196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis return hasSideEffects(ME->getInstanceReceiver(), Ctx); 1258f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall default: 1268f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall break; 1278f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall } 1288f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall break; 1298f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall default: 1308f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall break; 1318f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall } 1328f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall 1338f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall return true; 1348f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall} 1358f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall 1362c18ca0575b60082f2a9f4563b4071071960d37cArgyrios Kyrtzidisbool trans::isGlobalVar(Expr *E) { 1372c18ca0575b60082f2a9f4563b4071071960d37cArgyrios Kyrtzidis E = E->IgnoreParenCasts(); 1382c18ca0575b60082f2a9f4563b4071071960d37cArgyrios Kyrtzidis if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) 13918fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis return DRE->getDecl()->getDeclContext()->isFileContext() && 14018fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis DRE->getDecl()->getLinkage() == ExternalLinkage; 1412c18ca0575b60082f2a9f4563b4071071960d37cArgyrios Kyrtzidis if (ConditionalOperator *condOp = dyn_cast<ConditionalOperator>(E)) 1422c18ca0575b60082f2a9f4563b4071071960d37cArgyrios Kyrtzidis return isGlobalVar(condOp->getTrueExpr()) && 1432c18ca0575b60082f2a9f4563b4071071960d37cArgyrios Kyrtzidis isGlobalVar(condOp->getFalseExpr()); 1442c18ca0575b60082f2a9f4563b4071071960d37cArgyrios Kyrtzidis 1452c18ca0575b60082f2a9f4563b4071071960d37cArgyrios Kyrtzidis return false; 1462c18ca0575b60082f2a9f4563b4071071960d37cArgyrios Kyrtzidis} 1472c18ca0575b60082f2a9f4563b4071071960d37cArgyrios Kyrtzidis 14818fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios KyrtzidisStringRef trans::getNilString(ASTContext &Ctx) { 14918fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis if (Ctx.Idents.get("nil").hasMacroDefinition()) 15018fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis return "nil"; 15118fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis else 15218fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis return "0"; 15318fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis} 15418fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis 1558f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCallnamespace { 1568f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall 1578f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCallclass ReferenceClear : public RecursiveASTVisitor<ReferenceClear> { 1587196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis ExprSet &Refs; 1598f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCallpublic: 1607196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis ReferenceClear(ExprSet &refs) : Refs(refs) { } 1618f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall bool VisitDeclRefExpr(DeclRefExpr *E) { Refs.erase(E); return true; } 1628f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall}; 1638f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall 1648f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCallclass ReferenceCollector : public RecursiveASTVisitor<ReferenceCollector> { 1658f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall ValueDecl *Dcl; 1667196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis ExprSet &Refs; 1678f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall 1688f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCallpublic: 1697196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis ReferenceCollector(ValueDecl *D, ExprSet &refs) 1707196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis : Dcl(D), Refs(refs) { } 1718f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall 1728f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall bool VisitDeclRefExpr(DeclRefExpr *E) { 1738f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall if (E->getDecl() == Dcl) 1748f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall Refs.insert(E); 1758f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall return true; 1768f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall } 1778f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall}; 1788f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall 1797196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidisclass RemovablesCollector : public RecursiveASTVisitor<RemovablesCollector> { 1807196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis ExprSet &Removables; 1818f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall 1828f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCallpublic: 1837196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis RemovablesCollector(ExprSet &removables) 1847196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis : Removables(removables) { } 1857196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 1867196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis bool shouldWalkTypesOfTypeLocs() const { return false; } 1877196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 1887196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis bool TraverseStmtExpr(StmtExpr *E) { 1897196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis CompoundStmt *S = E->getSubStmt(); 1907196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis for (CompoundStmt::body_iterator 1917196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis I = S->body_begin(), E = S->body_end(); I != E; ++I) { 1927196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis if (I != E - 1) 1937196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis mark(*I); 1947196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis TraverseStmt(*I); 1958f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall } 1968f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall return true; 1978f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall } 1987196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 1997196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis bool VisitCompoundStmt(CompoundStmt *S) { 2007196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis for (CompoundStmt::body_iterator 2017196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis I = S->body_begin(), E = S->body_end(); I != E; ++I) 2027196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis mark(*I); 2038f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall return true; 2048f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall } 2057196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 2067196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis bool VisitIfStmt(IfStmt *S) { 2077196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis mark(S->getThen()); 2087196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis mark(S->getElse()); 2098f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall return true; 2108f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall } 2117196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 2127196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis bool VisitWhileStmt(WhileStmt *S) { 2137196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis mark(S->getBody()); 2148f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall return true; 2158f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall } 2167196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 2177196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis bool VisitDoStmt(DoStmt *S) { 2187196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis mark(S->getBody()); 2198f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall return true; 2208f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall } 2217196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 2227196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis bool VisitForStmt(ForStmt *S) { 2237196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis mark(S->getInit()); 2247196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis mark(S->getInc()); 2257196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis mark(S->getBody()); 2268f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall return true; 2278f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall } 2287196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 2298f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCallprivate: 2307196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis void mark(Stmt *S) { 2317196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis if (!S) return; 2327196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 2337e5e5f4cc36fe50f46ad76dca7a266434c94f475John McCall while (LabelStmt *Label = dyn_cast<LabelStmt>(S)) 2347e5e5f4cc36fe50f46ad76dca7a266434c94f475John McCall S = Label->getSubStmt(); 2357e5e5f4cc36fe50f46ad76dca7a266434c94f475John McCall S = S->IgnoreImplicit(); 2367196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis if (Expr *E = dyn_cast<Expr>(S)) 2377196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis Removables.insert(E); 2388e2ce7fdf9e8033b77788662a9c3f61334eb5dafArgyrios Kyrtzidis } 2397196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis}; 2408e2ce7fdf9e8033b77788662a9c3f61334eb5dafArgyrios Kyrtzidis 2417196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis} // end anonymous namespace 2428f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall 2437196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidisvoid trans::clearRefsIn(Stmt *S, ExprSet &refs) { 2447196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis ReferenceClear(refs).TraverseStmt(S); 2457196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis} 2468f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall 2477196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidisvoid trans::collectRefs(ValueDecl *D, Stmt *S, ExprSet &refs) { 2487196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis ReferenceCollector(D, refs).TraverseStmt(S); 2498f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall} 2508f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall 2517196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidisvoid trans::collectRemovables(Stmt *S, ExprSet &exprs) { 2527196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis RemovablesCollector(exprs).TraverseStmt(S); 2538f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall} 2548f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall 2558f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall//===----------------------------------------------------------------------===// 256e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis// MigrationContext 257e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis//===----------------------------------------------------------------------===// 258e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis 259e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidisnamespace { 260e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis 261e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidisclass ASTTransform : public RecursiveASTVisitor<ASTTransform> { 262e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis MigrationContext &MigrateCtx; 263a33849b368b0973e64ee9c49af4c080a59f99eb4Argyrios Kyrtzidis typedef RecursiveASTVisitor<ASTTransform> base; 264e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis 265e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidispublic: 266e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis ASTTransform(MigrationContext &MigrateCtx) : MigrateCtx(MigrateCtx) { } 267e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis 268f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis bool shouldWalkTypesOfTypeLocs() const { return false; } 269f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis 270b0d5db1b7cac1a0680877c17fe92c6d64cf1c730Argyrios Kyrtzidis bool TraverseObjCImplementationDecl(ObjCImplementationDecl *D) { 271b0d5db1b7cac1a0680877c17fe92c6d64cf1c730Argyrios Kyrtzidis ObjCImplementationContext ImplCtx(MigrateCtx, D); 272b0d5db1b7cac1a0680877c17fe92c6d64cf1c730Argyrios Kyrtzidis for (MigrationContext::traverser_iterator 273b0d5db1b7cac1a0680877c17fe92c6d64cf1c730Argyrios Kyrtzidis I = MigrateCtx.traversers_begin(), 274b0d5db1b7cac1a0680877c17fe92c6d64cf1c730Argyrios Kyrtzidis E = MigrateCtx.traversers_end(); I != E; ++I) 275b0d5db1b7cac1a0680877c17fe92c6d64cf1c730Argyrios Kyrtzidis (*I)->traverseObjCImplementation(ImplCtx); 276b0d5db1b7cac1a0680877c17fe92c6d64cf1c730Argyrios Kyrtzidis 277a33849b368b0973e64ee9c49af4c080a59f99eb4Argyrios Kyrtzidis return base::TraverseObjCImplementationDecl(D); 278b0d5db1b7cac1a0680877c17fe92c6d64cf1c730Argyrios Kyrtzidis } 279b0d5db1b7cac1a0680877c17fe92c6d64cf1c730Argyrios Kyrtzidis 280e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis bool TraverseStmt(Stmt *rootS) { 281e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis if (!rootS) 282e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis return true; 283e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis 284e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis BodyContext BodyCtx(MigrateCtx, rootS); 285e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis for (MigrationContext::traverser_iterator 286e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis I = MigrateCtx.traversers_begin(), 287e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis E = MigrateCtx.traversers_end(); I != E; ++I) 288e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis (*I)->traverseBody(BodyCtx); 289e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis 290e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis return true; 291e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis } 292e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis}; 293e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis 294e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis} 295e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis 296e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios KyrtzidisMigrationContext::~MigrationContext() { 297e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis for (traverser_iterator 298e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis I = traversers_begin(), E = traversers_end(); I != E; ++I) 299e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis delete *I; 300e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis} 301e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis 3021fe4203ca05d0a3283efc8a2e8c01ecdf78fbf2eArgyrios Kyrtzidisbool MigrationContext::isGCOwnedNonObjC(QualType T) { 3031fe4203ca05d0a3283efc8a2e8c01ecdf78fbf2eArgyrios Kyrtzidis while (!T.isNull()) { 3041fe4203ca05d0a3283efc8a2e8c01ecdf78fbf2eArgyrios Kyrtzidis if (const AttributedType *AttrT = T->getAs<AttributedType>()) { 3051fe4203ca05d0a3283efc8a2e8c01ecdf78fbf2eArgyrios Kyrtzidis if (AttrT->getAttrKind() == AttributedType::attr_objc_ownership) 3061fe4203ca05d0a3283efc8a2e8c01ecdf78fbf2eArgyrios Kyrtzidis return !AttrT->getModifiedType()->isObjCRetainableType(); 3071fe4203ca05d0a3283efc8a2e8c01ecdf78fbf2eArgyrios Kyrtzidis } 3081fe4203ca05d0a3283efc8a2e8c01ecdf78fbf2eArgyrios Kyrtzidis 3091fe4203ca05d0a3283efc8a2e8c01ecdf78fbf2eArgyrios Kyrtzidis if (T->isArrayType()) 3101fe4203ca05d0a3283efc8a2e8c01ecdf78fbf2eArgyrios Kyrtzidis T = Pass.Ctx.getBaseElementType(T); 3111fe4203ca05d0a3283efc8a2e8c01ecdf78fbf2eArgyrios Kyrtzidis else if (const PointerType *PT = T->getAs<PointerType>()) 3121fe4203ca05d0a3283efc8a2e8c01ecdf78fbf2eArgyrios Kyrtzidis T = PT->getPointeeType(); 3131fe4203ca05d0a3283efc8a2e8c01ecdf78fbf2eArgyrios Kyrtzidis else if (const ReferenceType *RT = T->getAs<ReferenceType>()) 3141fe4203ca05d0a3283efc8a2e8c01ecdf78fbf2eArgyrios Kyrtzidis T = RT->getPointeeType(); 3151fe4203ca05d0a3283efc8a2e8c01ecdf78fbf2eArgyrios Kyrtzidis else 3161fe4203ca05d0a3283efc8a2e8c01ecdf78fbf2eArgyrios Kyrtzidis break; 3171fe4203ca05d0a3283efc8a2e8c01ecdf78fbf2eArgyrios Kyrtzidis } 3181fe4203ca05d0a3283efc8a2e8c01ecdf78fbf2eArgyrios Kyrtzidis 3191fe4203ca05d0a3283efc8a2e8c01ecdf78fbf2eArgyrios Kyrtzidis return false; 3201fe4203ca05d0a3283efc8a2e8c01ecdf78fbf2eArgyrios Kyrtzidis} 3211fe4203ca05d0a3283efc8a2e8c01ecdf78fbf2eArgyrios Kyrtzidis 322b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidisbool MigrationContext::rewritePropertyAttribute(StringRef fromAttr, 323b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis StringRef toAttr, 324b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis SourceLocation atLoc) { 325b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis if (atLoc.isMacroID()) 326b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis return false; 327b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis 328b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis SourceManager &SM = Pass.Ctx.getSourceManager(); 329b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis 330b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis // Break down the source location. 331b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis std::pair<FileID, unsigned> locInfo = SM.getDecomposedLoc(atLoc); 332b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis 333b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis // Try to load the file buffer. 334b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis bool invalidTemp = false; 335b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis StringRef file = SM.getBufferData(locInfo.first, &invalidTemp); 336b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis if (invalidTemp) 337b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis return false; 338b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis 339b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis const char *tokenBegin = file.data() + locInfo.second; 340b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis 341b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis // Lex from the start of the given location. 342b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis Lexer lexer(SM.getLocForStartOfFile(locInfo.first), 3434e4d08403ca5cfd4d558fa2936215d3a4e5a528dDavid Blaikie Pass.Ctx.getLangOpts(), 344b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis file.begin(), tokenBegin, file.end()); 345b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis Token tok; 346b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis lexer.LexFromRawLexer(tok); 347b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis if (tok.isNot(tok::at)) return false; 348b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis lexer.LexFromRawLexer(tok); 349b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis if (tok.isNot(tok::raw_identifier)) return false; 350b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis if (StringRef(tok.getRawIdentifierData(), tok.getLength()) 351b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis != "property") 352b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis return false; 353b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis lexer.LexFromRawLexer(tok); 354b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis if (tok.isNot(tok::l_paren)) return false; 355b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis 356b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis Token BeforeTok = tok; 357b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis Token AfterTok; 358b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis AfterTok.startToken(); 359b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis SourceLocation AttrLoc; 360b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis 361b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis lexer.LexFromRawLexer(tok); 362b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis if (tok.is(tok::r_paren)) 363b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis return false; 364b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis 365b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis while (1) { 366b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis if (tok.isNot(tok::raw_identifier)) return false; 367b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis StringRef ident(tok.getRawIdentifierData(), tok.getLength()); 368b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis if (ident == fromAttr) { 369b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis if (!toAttr.empty()) { 370b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis Pass.TA.replaceText(tok.getLocation(), fromAttr, toAttr); 371b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis return true; 372b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis } 373b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis // We want to remove the attribute. 374b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis AttrLoc = tok.getLocation(); 375b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis } 376b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis 377b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis do { 378b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis lexer.LexFromRawLexer(tok); 379b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis if (AttrLoc.isValid() && AfterTok.is(tok::unknown)) 380b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis AfterTok = tok; 381b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis } while (tok.isNot(tok::comma) && tok.isNot(tok::r_paren)); 382b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis if (tok.is(tok::r_paren)) 383b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis break; 384b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis if (AttrLoc.isInvalid()) 385b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis BeforeTok = tok; 386b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis lexer.LexFromRawLexer(tok); 387b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis } 388b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis 389b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis if (toAttr.empty() && AttrLoc.isValid() && AfterTok.isNot(tok::unknown)) { 390b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis // We want to remove the attribute. 391b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis if (BeforeTok.is(tok::l_paren) && AfterTok.is(tok::r_paren)) { 392b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis Pass.TA.remove(SourceRange(BeforeTok.getLocation(), 393b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis AfterTok.getLocation())); 394b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis } else if (BeforeTok.is(tok::l_paren) && AfterTok.is(tok::comma)) { 395b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis Pass.TA.remove(SourceRange(AttrLoc, AfterTok.getLocation())); 396b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis } else { 397b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis Pass.TA.remove(SourceRange(BeforeTok.getLocation(), AttrLoc)); 398b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis } 399b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis 400b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis return true; 401b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis } 402b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis 403b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis return false; 404b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis} 405b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis 4066da4274724f6bd0f24f0fbfd1af076cd14b14710Argyrios Kyrtzidisbool MigrationContext::addPropertyAttribute(StringRef attr, 4076da4274724f6bd0f24f0fbfd1af076cd14b14710Argyrios Kyrtzidis SourceLocation atLoc) { 4086da4274724f6bd0f24f0fbfd1af076cd14b14710Argyrios Kyrtzidis if (atLoc.isMacroID()) 4096da4274724f6bd0f24f0fbfd1af076cd14b14710Argyrios Kyrtzidis return false; 4106da4274724f6bd0f24f0fbfd1af076cd14b14710Argyrios Kyrtzidis 4116da4274724f6bd0f24f0fbfd1af076cd14b14710Argyrios Kyrtzidis SourceManager &SM = Pass.Ctx.getSourceManager(); 4126da4274724f6bd0f24f0fbfd1af076cd14b14710Argyrios Kyrtzidis 4136da4274724f6bd0f24f0fbfd1af076cd14b14710Argyrios Kyrtzidis // Break down the source location. 4146da4274724f6bd0f24f0fbfd1af076cd14b14710Argyrios Kyrtzidis std::pair<FileID, unsigned> locInfo = SM.getDecomposedLoc(atLoc); 4156da4274724f6bd0f24f0fbfd1af076cd14b14710Argyrios Kyrtzidis 4166da4274724f6bd0f24f0fbfd1af076cd14b14710Argyrios Kyrtzidis // Try to load the file buffer. 4176da4274724f6bd0f24f0fbfd1af076cd14b14710Argyrios Kyrtzidis bool invalidTemp = false; 4186da4274724f6bd0f24f0fbfd1af076cd14b14710Argyrios Kyrtzidis StringRef file = SM.getBufferData(locInfo.first, &invalidTemp); 4196da4274724f6bd0f24f0fbfd1af076cd14b14710Argyrios Kyrtzidis if (invalidTemp) 4206da4274724f6bd0f24f0fbfd1af076cd14b14710Argyrios Kyrtzidis return false; 4216da4274724f6bd0f24f0fbfd1af076cd14b14710Argyrios Kyrtzidis 4226da4274724f6bd0f24f0fbfd1af076cd14b14710Argyrios Kyrtzidis const char *tokenBegin = file.data() + locInfo.second; 4236da4274724f6bd0f24f0fbfd1af076cd14b14710Argyrios Kyrtzidis 4246da4274724f6bd0f24f0fbfd1af076cd14b14710Argyrios Kyrtzidis // Lex from the start of the given location. 4256da4274724f6bd0f24f0fbfd1af076cd14b14710Argyrios Kyrtzidis Lexer lexer(SM.getLocForStartOfFile(locInfo.first), 4264e4d08403ca5cfd4d558fa2936215d3a4e5a528dDavid Blaikie Pass.Ctx.getLangOpts(), 4276da4274724f6bd0f24f0fbfd1af076cd14b14710Argyrios Kyrtzidis file.begin(), tokenBegin, file.end()); 4286da4274724f6bd0f24f0fbfd1af076cd14b14710Argyrios Kyrtzidis Token tok; 4296da4274724f6bd0f24f0fbfd1af076cd14b14710Argyrios Kyrtzidis lexer.LexFromRawLexer(tok); 4306da4274724f6bd0f24f0fbfd1af076cd14b14710Argyrios Kyrtzidis if (tok.isNot(tok::at)) return false; 4316da4274724f6bd0f24f0fbfd1af076cd14b14710Argyrios Kyrtzidis lexer.LexFromRawLexer(tok); 4326da4274724f6bd0f24f0fbfd1af076cd14b14710Argyrios Kyrtzidis if (tok.isNot(tok::raw_identifier)) return false; 4336da4274724f6bd0f24f0fbfd1af076cd14b14710Argyrios Kyrtzidis if (StringRef(tok.getRawIdentifierData(), tok.getLength()) 4346da4274724f6bd0f24f0fbfd1af076cd14b14710Argyrios Kyrtzidis != "property") 4356da4274724f6bd0f24f0fbfd1af076cd14b14710Argyrios Kyrtzidis return false; 4366da4274724f6bd0f24f0fbfd1af076cd14b14710Argyrios Kyrtzidis lexer.LexFromRawLexer(tok); 4376da4274724f6bd0f24f0fbfd1af076cd14b14710Argyrios Kyrtzidis 4386da4274724f6bd0f24f0fbfd1af076cd14b14710Argyrios Kyrtzidis if (tok.isNot(tok::l_paren)) { 4396da4274724f6bd0f24f0fbfd1af076cd14b14710Argyrios Kyrtzidis Pass.TA.insert(tok.getLocation(), std::string("(") + attr.str() + ") "); 4406da4274724f6bd0f24f0fbfd1af076cd14b14710Argyrios Kyrtzidis return true; 4416da4274724f6bd0f24f0fbfd1af076cd14b14710Argyrios Kyrtzidis } 4426da4274724f6bd0f24f0fbfd1af076cd14b14710Argyrios Kyrtzidis 4436da4274724f6bd0f24f0fbfd1af076cd14b14710Argyrios Kyrtzidis lexer.LexFromRawLexer(tok); 4446da4274724f6bd0f24f0fbfd1af076cd14b14710Argyrios Kyrtzidis if (tok.is(tok::r_paren)) { 4456da4274724f6bd0f24f0fbfd1af076cd14b14710Argyrios Kyrtzidis Pass.TA.insert(tok.getLocation(), attr); 4466da4274724f6bd0f24f0fbfd1af076cd14b14710Argyrios Kyrtzidis return true; 4476da4274724f6bd0f24f0fbfd1af076cd14b14710Argyrios Kyrtzidis } 4486da4274724f6bd0f24f0fbfd1af076cd14b14710Argyrios Kyrtzidis 4496da4274724f6bd0f24f0fbfd1af076cd14b14710Argyrios Kyrtzidis if (tok.isNot(tok::raw_identifier)) return false; 4506da4274724f6bd0f24f0fbfd1af076cd14b14710Argyrios Kyrtzidis 4516da4274724f6bd0f24f0fbfd1af076cd14b14710Argyrios Kyrtzidis Pass.TA.insert(tok.getLocation(), std::string(attr) + ", "); 4526da4274724f6bd0f24f0fbfd1af076cd14b14710Argyrios Kyrtzidis return true; 4536da4274724f6bd0f24f0fbfd1af076cd14b14710Argyrios Kyrtzidis} 4546da4274724f6bd0f24f0fbfd1af076cd14b14710Argyrios Kyrtzidis 455e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidisvoid MigrationContext::traverse(TranslationUnitDecl *TU) { 456f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis for (traverser_iterator 457f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis I = traversers_begin(), E = traversers_end(); I != E; ++I) 458f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis (*I)->traverseTU(*this); 459f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis 460e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis ASTTransform(*this).TraverseDecl(TU); 461e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis} 462e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis 463bbdfad581fa300fa0d162d968ec14de3c95fc760Fariborz Jahanianstatic void GCRewriteFinalize(MigrationPass &pass) { 464bbdfad581fa300fa0d162d968ec14de3c95fc760Fariborz Jahanian ASTContext &Ctx = pass.Ctx; 465bbdfad581fa300fa0d162d968ec14de3c95fc760Fariborz Jahanian TransformActions &TA = pass.TA; 466bbdfad581fa300fa0d162d968ec14de3c95fc760Fariborz Jahanian DeclContext *DC = Ctx.getTranslationUnitDecl(); 467bbdfad581fa300fa0d162d968ec14de3c95fc760Fariborz Jahanian Selector FinalizeSel = 468bbdfad581fa300fa0d162d968ec14de3c95fc760Fariborz Jahanian Ctx.Selectors.getNullarySelector(&pass.Ctx.Idents.get("finalize")); 469bbdfad581fa300fa0d162d968ec14de3c95fc760Fariborz Jahanian 470bbdfad581fa300fa0d162d968ec14de3c95fc760Fariborz Jahanian typedef DeclContext::specific_decl_iterator<ObjCImplementationDecl> 471bbdfad581fa300fa0d162d968ec14de3c95fc760Fariborz Jahanian impl_iterator; 472bbdfad581fa300fa0d162d968ec14de3c95fc760Fariborz Jahanian for (impl_iterator I = impl_iterator(DC->decls_begin()), 473bbdfad581fa300fa0d162d968ec14de3c95fc760Fariborz Jahanian E = impl_iterator(DC->decls_end()); I != E; ++I) { 474bbdfad581fa300fa0d162d968ec14de3c95fc760Fariborz Jahanian for (ObjCImplementationDecl::instmeth_iterator 475bbdfad581fa300fa0d162d968ec14de3c95fc760Fariborz Jahanian MI = (*I)->instmeth_begin(), 476bbdfad581fa300fa0d162d968ec14de3c95fc760Fariborz Jahanian ME = (*I)->instmeth_end(); MI != ME; ++MI) { 477bbdfad581fa300fa0d162d968ec14de3c95fc760Fariborz Jahanian ObjCMethodDecl *MD = *MI; 478bbdfad581fa300fa0d162d968ec14de3c95fc760Fariborz Jahanian if (!MD->hasBody()) 479bbdfad581fa300fa0d162d968ec14de3c95fc760Fariborz Jahanian continue; 480bbdfad581fa300fa0d162d968ec14de3c95fc760Fariborz Jahanian 481bbdfad581fa300fa0d162d968ec14de3c95fc760Fariborz Jahanian if (MD->isInstanceMethod() && MD->getSelector() == FinalizeSel) { 482bbdfad581fa300fa0d162d968ec14de3c95fc760Fariborz Jahanian ObjCMethodDecl *FinalizeM = MD; 483bbdfad581fa300fa0d162d968ec14de3c95fc760Fariborz Jahanian Transaction Trans(TA); 484bbdfad581fa300fa0d162d968ec14de3c95fc760Fariborz Jahanian TA.insert(FinalizeM->getSourceRange().getBegin(), 485bbdfad581fa300fa0d162d968ec14de3c95fc760Fariborz Jahanian "#if !__has_feature(objc_arc)\n"); 486bbdfad581fa300fa0d162d968ec14de3c95fc760Fariborz Jahanian CharSourceRange::getTokenRange(FinalizeM->getSourceRange()); 487bbdfad581fa300fa0d162d968ec14de3c95fc760Fariborz Jahanian const SourceManager &SM = pass.Ctx.getSourceManager(); 4884e4d08403ca5cfd4d558fa2936215d3a4e5a528dDavid Blaikie const LangOptions &LangOpts = pass.Ctx.getLangOpts(); 489bbdfad581fa300fa0d162d968ec14de3c95fc760Fariborz Jahanian bool Invalid; 490bbdfad581fa300fa0d162d968ec14de3c95fc760Fariborz Jahanian std::string str = "\n#endif\n"; 491bbdfad581fa300fa0d162d968ec14de3c95fc760Fariborz Jahanian str += Lexer::getSourceText( 492bbdfad581fa300fa0d162d968ec14de3c95fc760Fariborz Jahanian CharSourceRange::getTokenRange(FinalizeM->getSourceRange()), 493bbdfad581fa300fa0d162d968ec14de3c95fc760Fariborz Jahanian SM, LangOpts, &Invalid); 494bbdfad581fa300fa0d162d968ec14de3c95fc760Fariborz Jahanian TA.insertAfterToken(FinalizeM->getSourceRange().getEnd(), str); 495bbdfad581fa300fa0d162d968ec14de3c95fc760Fariborz Jahanian 496bbdfad581fa300fa0d162d968ec14de3c95fc760Fariborz Jahanian break; 497bbdfad581fa300fa0d162d968ec14de3c95fc760Fariborz Jahanian } 498bbdfad581fa300fa0d162d968ec14de3c95fc760Fariborz Jahanian } 499bbdfad581fa300fa0d162d968ec14de3c95fc760Fariborz Jahanian } 500bbdfad581fa300fa0d162d968ec14de3c95fc760Fariborz Jahanian} 501bbdfad581fa300fa0d162d968ec14de3c95fc760Fariborz Jahanian 502e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis//===----------------------------------------------------------------------===// 5038f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall// getAllTransformations. 5048f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall//===----------------------------------------------------------------------===// 5058f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall 506e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidisstatic void traverseAST(MigrationPass &pass) { 507e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis MigrationContext MigrateCtx(pass); 508e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis 509e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis if (pass.isGCMigration()) { 510e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis MigrateCtx.addTraverser(new GCCollectableCallsTraverser); 511f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis MigrateCtx.addTraverser(new GCAttrsTraverser()); 512e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis } 513b0d5db1b7cac1a0680877c17fe92c6d64cf1c730Argyrios Kyrtzidis MigrateCtx.addTraverser(new PropertyRewriteTraverser()); 5142a2781805a6b55573d369e34c5dcfba307ce83e9Argyrios Kyrtzidis MigrateCtx.addTraverser(new BlockObjCVariableTraverser()); 515e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis 516e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis MigrateCtx.traverse(pass.Ctx.getTranslationUnitDecl()); 517e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis} 518e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis 5198f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCallstatic void independentTransforms(MigrationPass &pass) { 5208f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall rewriteAutoreleasePool(pass); 521e7ef8556f4ee3012a0479308c993af0fbee448dfArgyrios Kyrtzidis removeRetainReleaseDeallocFinalize(pass); 5227196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis rewriteUnusedInitDelegate(pass); 523e7ef8556f4ee3012a0479308c993af0fbee448dfArgyrios Kyrtzidis removeZeroOutPropsInDeallocFinalize(pass); 5248f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall makeAssignARCSafe(pass); 5257196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis rewriteUnbridgedCasts(pass); 526fd10398c10ffdcbdeb1e3e299c74d70e689f503cArgyrios Kyrtzidis checkAPIUses(pass); 527e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis traverseAST(pass); 5288f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall} 5298f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall 530e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidisstd::vector<TransformFn> arcmt::getAllTransformations( 531bbdfad581fa300fa0d162d968ec14de3c95fc760Fariborz Jahanian LangOptions::GCMode OrigGCMode, 532bbdfad581fa300fa0d162d968ec14de3c95fc760Fariborz Jahanian bool NoFinalizeRemoval) { 5338f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall std::vector<TransformFn> transforms; 5348f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall 535bbdfad581fa300fa0d162d968ec14de3c95fc760Fariborz Jahanian if (OrigGCMode == LangOptions::GCOnly && NoFinalizeRemoval) 536bbdfad581fa300fa0d162d968ec14de3c95fc760Fariborz Jahanian transforms.push_back(GCRewriteFinalize); 5378f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall transforms.push_back(independentTransforms); 538fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis // This depends on previous transformations removing various expressions. 539e7ef8556f4ee3012a0479308c993af0fbee448dfArgyrios Kyrtzidis transforms.push_back(removeEmptyStatementsAndDeallocFinalize); 5408f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall 5418f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall return transforms; 5428f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall} 543