1accaf19bc1129c0273ec50dba52318e60bc29103Benjamin Kramer//===--- Transforms.cpp - Transformations 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"
12471c8b49982d1132f30b0b0da27fef94fd6e4f67Benjamin Kramer#include "clang/AST/ASTContext.h"
138f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall#include "clang/AST/RecursiveASTVisitor.h"
148f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall#include "clang/AST/StmtVisitor.h"
1555fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/Analysis/DomainSpecific/CocoaConventions.h"
168f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall#include "clang/Basic/SourceManager.h"
179852f58f50b4fc20914fbce5b4454135a42343f4Benjamin Kramer#include "clang/Basic/TargetInfo.h"
18471c8b49982d1132f30b0b0da27fef94fd6e4f67Benjamin Kramer#include "clang/Lex/Lexer.h"
19471c8b49982d1132f30b0b0da27fef94fd6e4f67Benjamin Kramer#include "clang/Sema/Sema.h"
20471c8b49982d1132f30b0b0da27fef94fd6e4f67Benjamin Kramer#include "clang/Sema/SemaDiagnostic.h"
218f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall#include "llvm/ADT/DenseSet.h"
229852f58f50b4fc20914fbce5b4454135a42343f4Benjamin Kramer#include "llvm/ADT/StringSwitch.h"
238f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall#include <map>
248f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall
258f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCallusing namespace clang;
268f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCallusing namespace arcmt;
277196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidisusing namespace trans;
288f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall
29e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios KyrtzidisASTTraverser::~ASTTraverser() { }
30e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis
31684190b8dbe5258f4708ffbd816b8c5ee5b3502dArgyrios Kyrtzidisbool MigrationPass::CFBridgingFunctionsDefined() {
32684190b8dbe5258f4708ffbd816b8c5ee5b3502dArgyrios Kyrtzidis  if (!EnableCFBridgeFns.hasValue())
33684190b8dbe5258f4708ffbd816b8c5ee5b3502dArgyrios Kyrtzidis    EnableCFBridgeFns = SemaRef.isKnownName("CFBridgingRetain") &&
34684190b8dbe5258f4708ffbd816b8c5ee5b3502dArgyrios Kyrtzidis                        SemaRef.isKnownName("CFBridgingRelease");
35684190b8dbe5258f4708ffbd816b8c5ee5b3502dArgyrios Kyrtzidis  return *EnableCFBridgeFns;
36684190b8dbe5258f4708ffbd816b8c5ee5b3502dArgyrios Kyrtzidis}
37684190b8dbe5258f4708ffbd816b8c5ee5b3502dArgyrios Kyrtzidis
388f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall//===----------------------------------------------------------------------===//
397196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis// Helpers.
408f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall//===----------------------------------------------------------------------===//
418f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall
4212192cf50a96cb59a3039af044b7fa97f043101cArgyrios Kyrtzidisbool trans::canApplyWeak(ASTContext &Ctx, QualType type,
4312192cf50a96cb59a3039af044b7fa97f043101cArgyrios Kyrtzidis                         bool AllowOnUnknownClass) {
440a7dd788dbef975f35f273c7ab913f480f7edd60John McCall  if (!Ctx.getLangOpts().ObjCARCWeak)
4586625b5650cdddc38c0b4cc1eb7fb460478c9d11Argyrios Kyrtzidis    return false;
4686625b5650cdddc38c0b4cc1eb7fb460478c9d11Argyrios Kyrtzidis
4786625b5650cdddc38c0b4cc1eb7fb460478c9d11Argyrios Kyrtzidis  QualType T = type;
48b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis  if (T.isNull())
49b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis    return false;
50b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis
512af504bf157cce51bdb4a9bab0e6d3b34f898f6eArgyrios Kyrtzidis  // iOS is always safe to use 'weak'.
522af504bf157cce51bdb4a9bab0e6d3b34f898f6eArgyrios Kyrtzidis  if (Ctx.getTargetInfo().getTriple().getOS() == llvm::Triple::IOS)
532af504bf157cce51bdb4a9bab0e6d3b34f898f6eArgyrios Kyrtzidis    AllowOnUnknownClass = true;
542af504bf157cce51bdb4a9bab0e6d3b34f898f6eArgyrios Kyrtzidis
5586625b5650cdddc38c0b4cc1eb7fb460478c9d11Argyrios Kyrtzidis  while (const PointerType *ptr = T->getAs<PointerType>())
5686625b5650cdddc38c0b4cc1eb7fb460478c9d11Argyrios Kyrtzidis    T = ptr->getPointeeType();
5786625b5650cdddc38c0b4cc1eb7fb460478c9d11Argyrios Kyrtzidis  if (const ObjCObjectPointerType *ObjT = T->getAs<ObjCObjectPointerType>()) {
5886625b5650cdddc38c0b4cc1eb7fb460478c9d11Argyrios Kyrtzidis    ObjCInterfaceDecl *Class = ObjT->getInterfaceDecl();
5912192cf50a96cb59a3039af044b7fa97f043101cArgyrios Kyrtzidis    if (!AllowOnUnknownClass && (!Class || Class->getName() == "NSObject"))
6086625b5650cdddc38c0b4cc1eb7fb460478c9d11Argyrios Kyrtzidis      return false; // id/NSObject is not safe for weak.
617723fec9b45b7258c0eddf4cbfd0d335348f5edcDouglas Gregor    if (!AllowOnUnknownClass && !Class->hasDefinition())
625363e8df5d274cb32c0c47fd2df45aa02cf68dfeArgyrios Kyrtzidis      return false; // forward classes are not verifiable, therefore not safe.
63a8eaf008e92759142982f7b40720b2b2674bd663Richard Smith    if (Class && Class->isArcWeakrefUnavailable())
6486625b5650cdddc38c0b4cc1eb7fb460478c9d11Argyrios Kyrtzidis      return false;
6586625b5650cdddc38c0b4cc1eb7fb460478c9d11Argyrios Kyrtzidis  }
6686625b5650cdddc38c0b4cc1eb7fb460478c9d11Argyrios Kyrtzidis
6786625b5650cdddc38c0b4cc1eb7fb460478c9d11Argyrios Kyrtzidis  return true;
6886625b5650cdddc38c0b4cc1eb7fb460478c9d11Argyrios Kyrtzidis}
6986625b5650cdddc38c0b4cc1eb7fb460478c9d11Argyrios Kyrtzidis
701b8fbd3601e009803565e74d2ec54abecb5cbf73Argyrios Kyrtzidisbool trans::isPlusOneAssign(const BinaryOperator *E) {
711b8fbd3601e009803565e74d2ec54abecb5cbf73Argyrios Kyrtzidis  if (E->getOpcode() != BO_Assign)
721b8fbd3601e009803565e74d2ec54abecb5cbf73Argyrios Kyrtzidis    return false;
731b8fbd3601e009803565e74d2ec54abecb5cbf73Argyrios Kyrtzidis
7420bcd4ead46e3764a5d1279845f8ed351f4d3984Argyrios Kyrtzidis  return isPlusOne(E->getRHS());
7520bcd4ead46e3764a5d1279845f8ed351f4d3984Argyrios Kyrtzidis}
7620bcd4ead46e3764a5d1279845f8ed351f4d3984Argyrios Kyrtzidis
7720bcd4ead46e3764a5d1279845f8ed351f4d3984Argyrios Kyrtzidisbool trans::isPlusOne(const Expr *E) {
7820bcd4ead46e3764a5d1279845f8ed351f4d3984Argyrios Kyrtzidis  if (!E)
7920bcd4ead46e3764a5d1279845f8ed351f4d3984Argyrios Kyrtzidis    return false;
8020bcd4ead46e3764a5d1279845f8ed351f4d3984Argyrios Kyrtzidis  if (const ExprWithCleanups *EWC = dyn_cast<ExprWithCleanups>(E))
8120bcd4ead46e3764a5d1279845f8ed351f4d3984Argyrios Kyrtzidis    E = EWC->getSubExpr();
8220bcd4ead46e3764a5d1279845f8ed351f4d3984Argyrios Kyrtzidis
831b8fbd3601e009803565e74d2ec54abecb5cbf73Argyrios Kyrtzidis  if (const ObjCMessageExpr *
8420bcd4ead46e3764a5d1279845f8ed351f4d3984Argyrios Kyrtzidis        ME = dyn_cast<ObjCMessageExpr>(E->IgnoreParenCasts()))
851b8fbd3601e009803565e74d2ec54abecb5cbf73Argyrios Kyrtzidis    if (ME->getMethodFamily() == OMF_retain)
861b8fbd3601e009803565e74d2ec54abecb5cbf73Argyrios Kyrtzidis      return true;
871b8fbd3601e009803565e74d2ec54abecb5cbf73Argyrios Kyrtzidis
881b8fbd3601e009803565e74d2ec54abecb5cbf73Argyrios Kyrtzidis  if (const CallExpr *
8920bcd4ead46e3764a5d1279845f8ed351f4d3984Argyrios Kyrtzidis        callE = dyn_cast<CallExpr>(E->IgnoreParenCasts())) {
901b8fbd3601e009803565e74d2ec54abecb5cbf73Argyrios Kyrtzidis    if (const FunctionDecl *FD = callE->getDirectCallee()) {
911b8fbd3601e009803565e74d2ec54abecb5cbf73Argyrios Kyrtzidis      if (FD->getAttr<CFReturnsRetainedAttr>())
921b8fbd3601e009803565e74d2ec54abecb5cbf73Argyrios Kyrtzidis        return true;
931b8fbd3601e009803565e74d2ec54abecb5cbf73Argyrios Kyrtzidis
941b8fbd3601e009803565e74d2ec54abecb5cbf73Argyrios Kyrtzidis      if (FD->isGlobal() &&
951b8fbd3601e009803565e74d2ec54abecb5cbf73Argyrios Kyrtzidis          FD->getIdentifier() &&
961b8fbd3601e009803565e74d2ec54abecb5cbf73Argyrios Kyrtzidis          FD->getParent()->isTranslationUnit() &&
97181e3ecc0907ae0103586a9f4db52241995a8267Rafael Espindola          FD->isExternallyVisible() &&
981b8fbd3601e009803565e74d2ec54abecb5cbf73Argyrios Kyrtzidis          ento::cocoa::isRefType(callE->getType(), "CF",
991b8fbd3601e009803565e74d2ec54abecb5cbf73Argyrios Kyrtzidis                                 FD->getIdentifier()->getName())) {
1001b8fbd3601e009803565e74d2ec54abecb5cbf73Argyrios Kyrtzidis        StringRef fname = FD->getIdentifier()->getName();
1011b8fbd3601e009803565e74d2ec54abecb5cbf73Argyrios Kyrtzidis        if (fname.endswith("Retain") ||
1021b8fbd3601e009803565e74d2ec54abecb5cbf73Argyrios Kyrtzidis            fname.find("Create") != StringRef::npos ||
1031b8fbd3601e009803565e74d2ec54abecb5cbf73Argyrios Kyrtzidis            fname.find("Copy") != StringRef::npos) {
1041b8fbd3601e009803565e74d2ec54abecb5cbf73Argyrios Kyrtzidis          return true;
1051b8fbd3601e009803565e74d2ec54abecb5cbf73Argyrios Kyrtzidis        }
1061b8fbd3601e009803565e74d2ec54abecb5cbf73Argyrios Kyrtzidis      }
1071b8fbd3601e009803565e74d2ec54abecb5cbf73Argyrios Kyrtzidis    }
1081b8fbd3601e009803565e74d2ec54abecb5cbf73Argyrios Kyrtzidis  }
1091b8fbd3601e009803565e74d2ec54abecb5cbf73Argyrios Kyrtzidis
11020bcd4ead46e3764a5d1279845f8ed351f4d3984Argyrios Kyrtzidis  const ImplicitCastExpr *implCE = dyn_cast<ImplicitCastExpr>(E);
1111b8fbd3601e009803565e74d2ec54abecb5cbf73Argyrios Kyrtzidis  while (implCE && implCE->getCastKind() ==  CK_BitCast)
1121b8fbd3601e009803565e74d2ec54abecb5cbf73Argyrios Kyrtzidis    implCE = dyn_cast<ImplicitCastExpr>(implCE->getSubExpr());
1131b8fbd3601e009803565e74d2ec54abecb5cbf73Argyrios Kyrtzidis
1141b8fbd3601e009803565e74d2ec54abecb5cbf73Argyrios Kyrtzidis  if (implCE && implCE->getCastKind() == CK_ARCConsumeObject)
1151b8fbd3601e009803565e74d2ec54abecb5cbf73Argyrios Kyrtzidis    return true;
1161b8fbd3601e009803565e74d2ec54abecb5cbf73Argyrios Kyrtzidis
1171b8fbd3601e009803565e74d2ec54abecb5cbf73Argyrios Kyrtzidis  return false;
1181b8fbd3601e009803565e74d2ec54abecb5cbf73Argyrios Kyrtzidis}
1191b8fbd3601e009803565e74d2ec54abecb5cbf73Argyrios Kyrtzidis
1207196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis/// \brief 'Loc' is the end of a statement range. This returns the location
1217196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis/// immediately after the semicolon following the statement.
1227196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis/// If no semicolon is found or the location is inside a macro, the returned
1237196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis/// source location will be invalid.
1247196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios KyrtzidisSourceLocation trans::findLocationAfterSemi(SourceLocation loc,
1257196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis                                            ASTContext &Ctx) {
126aec230d29835285777ecc467e268c83b33a2addeArgyrios Kyrtzidis  SourceLocation SemiLoc = findSemiAfterLocation(loc, Ctx);
127aec230d29835285777ecc467e268c83b33a2addeArgyrios Kyrtzidis  if (SemiLoc.isInvalid())
128aec230d29835285777ecc467e268c83b33a2addeArgyrios Kyrtzidis    return SourceLocation();
129a64ccefdf0ea4e03ec88805d71b0af74950c7472Argyrios Kyrtzidis  return SemiLoc.getLocWithOffset(1);
130aec230d29835285777ecc467e268c83b33a2addeArgyrios Kyrtzidis}
131aec230d29835285777ecc467e268c83b33a2addeArgyrios Kyrtzidis
132aec230d29835285777ecc467e268c83b33a2addeArgyrios Kyrtzidis/// \brief \arg Loc is the end of a statement range. This returns the location
133aec230d29835285777ecc467e268c83b33a2addeArgyrios Kyrtzidis/// of the semicolon following the statement.
134aec230d29835285777ecc467e268c83b33a2addeArgyrios Kyrtzidis/// If no semicolon is found or the location is inside a macro, the returned
135aec230d29835285777ecc467e268c83b33a2addeArgyrios Kyrtzidis/// source location will be invalid.
136aec230d29835285777ecc467e268c83b33a2addeArgyrios KyrtzidisSourceLocation trans::findSemiAfterLocation(SourceLocation loc,
137aec230d29835285777ecc467e268c83b33a2addeArgyrios Kyrtzidis                                            ASTContext &Ctx) {
1387196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  SourceManager &SM = Ctx.getSourceManager();
1397196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  if (loc.isMacroID()) {
1404e4d08403ca5cfd4d558fa2936215d3a4e5a528dDavid Blaikie    if (!Lexer::isAtEndOfMacroExpansion(loc, SM, Ctx.getLangOpts(), &loc))
1417196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis      return SourceLocation();
1427196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  }
1434e4d08403ca5cfd4d558fa2936215d3a4e5a528dDavid Blaikie  loc = Lexer::getLocForEndOfToken(loc, /*Offset=*/0, SM, Ctx.getLangOpts());
1448f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall
1457196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  // Break down the source location.
1467196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  std::pair<FileID, unsigned> locInfo = SM.getDecomposedLoc(loc);
1478f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall
1487196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  // Try to load the file buffer.
1497196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  bool invalidTemp = false;
1505f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner  StringRef file = SM.getBufferData(locInfo.first, &invalidTemp);
1517196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  if (invalidTemp)
1527196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    return SourceLocation();
1537196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
1547196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  const char *tokenBegin = file.data() + locInfo.second;
1557196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
1567196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  // Lex from the start of the given location.
1577196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  Lexer lexer(SM.getLocForStartOfFile(locInfo.first),
1584e4d08403ca5cfd4d558fa2936215d3a4e5a528dDavid Blaikie              Ctx.getLangOpts(),
1597196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis              file.begin(), tokenBegin, file.end());
1607196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  Token tok;
1617196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  lexer.LexFromRawLexer(tok);
1627196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  if (tok.isNot(tok::semi))
1637196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    return SourceLocation();
1648f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall
165aec230d29835285777ecc467e268c83b33a2addeArgyrios Kyrtzidis  return tok.getLocation();
1667196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis}
1678f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall
1687196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidisbool trans::hasSideEffects(Expr *E, ASTContext &Ctx) {
1698f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  if (!E || !E->HasSideEffects(Ctx))
1708f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall    return false;
1718f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall
1728f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  E = E->IgnoreParenCasts();
1738f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  ObjCMessageExpr *ME = dyn_cast<ObjCMessageExpr>(E);
1748f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  if (!ME)
1758f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall    return true;
1768f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  switch (ME->getMethodFamily()) {
1778f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  case OMF_autorelease:
1788f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  case OMF_dealloc:
1798f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  case OMF_release:
1808f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  case OMF_retain:
1818f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall    switch (ME->getReceiverKind()) {
1828f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall    case ObjCMessageExpr::SuperInstance:
1838f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall      return false;
1848f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall    case ObjCMessageExpr::Instance:
1857196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis      return hasSideEffects(ME->getInstanceReceiver(), Ctx);
1868f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall    default:
1878f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall      break;
1888f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall    }
1898f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall    break;
1908f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  default:
1918f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall    break;
1928f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  }
1938f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall
1948f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  return true;
1958f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall}
1968f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall
1972c18ca0575b60082f2a9f4563b4071071960d37cArgyrios Kyrtzidisbool trans::isGlobalVar(Expr *E) {
1982c18ca0575b60082f2a9f4563b4071071960d37cArgyrios Kyrtzidis  E = E->IgnoreParenCasts();
1992c18ca0575b60082f2a9f4563b4071071960d37cArgyrios Kyrtzidis  if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E))
20018fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis    return DRE->getDecl()->getDeclContext()->isFileContext() &&
201181e3ecc0907ae0103586a9f4db52241995a8267Rafael Espindola           DRE->getDecl()->isExternallyVisible();
2022c18ca0575b60082f2a9f4563b4071071960d37cArgyrios Kyrtzidis  if (ConditionalOperator *condOp = dyn_cast<ConditionalOperator>(E))
2032c18ca0575b60082f2a9f4563b4071071960d37cArgyrios Kyrtzidis    return isGlobalVar(condOp->getTrueExpr()) &&
2042c18ca0575b60082f2a9f4563b4071071960d37cArgyrios Kyrtzidis           isGlobalVar(condOp->getFalseExpr());
2052c18ca0575b60082f2a9f4563b4071071960d37cArgyrios Kyrtzidis
2062c18ca0575b60082f2a9f4563b4071071960d37cArgyrios Kyrtzidis  return false;
2072c18ca0575b60082f2a9f4563b4071071960d37cArgyrios Kyrtzidis}
2082c18ca0575b60082f2a9f4563b4071071960d37cArgyrios Kyrtzidis
20918fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios KyrtzidisStringRef trans::getNilString(ASTContext &Ctx) {
21018fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis  if (Ctx.Idents.get("nil").hasMacroDefinition())
21118fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis    return "nil";
21218fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis  else
21318fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis    return "0";
21418fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis}
21518fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis
2168f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCallnamespace {
2178f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall
2188f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCallclass ReferenceClear : public RecursiveASTVisitor<ReferenceClear> {
2197196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  ExprSet &Refs;
2208f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCallpublic:
2217196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  ReferenceClear(ExprSet &refs) : Refs(refs) { }
2228f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  bool VisitDeclRefExpr(DeclRefExpr *E) { Refs.erase(E); return true; }
2238f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall};
2248f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall
2258f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCallclass ReferenceCollector : public RecursiveASTVisitor<ReferenceCollector> {
2268f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  ValueDecl *Dcl;
2277196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  ExprSet &Refs;
2288f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall
2298f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCallpublic:
2307196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  ReferenceCollector(ValueDecl *D, ExprSet &refs)
2317196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    : Dcl(D), Refs(refs) { }
2328f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall
2338f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  bool VisitDeclRefExpr(DeclRefExpr *E) {
2348f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall    if (E->getDecl() == Dcl)
2358f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall      Refs.insert(E);
2368f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall    return true;
2378f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  }
2388f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall};
2398f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall
2407196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidisclass RemovablesCollector : public RecursiveASTVisitor<RemovablesCollector> {
2417196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  ExprSet &Removables;
2428f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall
2438f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCallpublic:
2447196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  RemovablesCollector(ExprSet &removables)
2457196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  : Removables(removables) { }
2467196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
2477196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  bool shouldWalkTypesOfTypeLocs() const { return false; }
2487196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
2497196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  bool TraverseStmtExpr(StmtExpr *E) {
2507196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    CompoundStmt *S = E->getSubStmt();
2517196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    for (CompoundStmt::body_iterator
2527196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis        I = S->body_begin(), E = S->body_end(); I != E; ++I) {
2537196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis      if (I != E - 1)
2547196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis        mark(*I);
2557196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis      TraverseStmt(*I);
2568f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall    }
2578f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall    return true;
2588f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  }
2597196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
2607196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  bool VisitCompoundStmt(CompoundStmt *S) {
2617196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    for (CompoundStmt::body_iterator
2627196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis        I = S->body_begin(), E = S->body_end(); I != E; ++I)
2637196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis      mark(*I);
2648f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall    return true;
2658f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  }
2667196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
2677196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  bool VisitIfStmt(IfStmt *S) {
2687196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    mark(S->getThen());
2697196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    mark(S->getElse());
2708f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall    return true;
2718f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  }
2727196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
2737196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  bool VisitWhileStmt(WhileStmt *S) {
2747196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    mark(S->getBody());
2758f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall    return true;
2768f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  }
2777196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
2787196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  bool VisitDoStmt(DoStmt *S) {
2797196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    mark(S->getBody());
2808f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall    return true;
2818f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  }
2827196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
2837196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  bool VisitForStmt(ForStmt *S) {
2847196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    mark(S->getInit());
2857196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    mark(S->getInc());
2867196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    mark(S->getBody());
2878f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall    return true;
2888f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  }
2897196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
2908f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCallprivate:
2917196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  void mark(Stmt *S) {
2927196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    if (!S) return;
2937196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
2947e5e5f4cc36fe50f46ad76dca7a266434c94f475John McCall    while (LabelStmt *Label = dyn_cast<LabelStmt>(S))
2957e5e5f4cc36fe50f46ad76dca7a266434c94f475John McCall      S = Label->getSubStmt();
2967e5e5f4cc36fe50f46ad76dca7a266434c94f475John McCall    S = S->IgnoreImplicit();
2977196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    if (Expr *E = dyn_cast<Expr>(S))
2987196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis      Removables.insert(E);
2998e2ce7fdf9e8033b77788662a9c3f61334eb5dafArgyrios Kyrtzidis  }
3007196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis};
3018e2ce7fdf9e8033b77788662a9c3f61334eb5dafArgyrios Kyrtzidis
3027196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis} // end anonymous namespace
3038f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall
3047196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidisvoid trans::clearRefsIn(Stmt *S, ExprSet &refs) {
3057196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  ReferenceClear(refs).TraverseStmt(S);
3067196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis}
3078f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall
3087196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidisvoid trans::collectRefs(ValueDecl *D, Stmt *S, ExprSet &refs) {
3097196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  ReferenceCollector(D, refs).TraverseStmt(S);
3108f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall}
3118f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall
3127196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidisvoid trans::collectRemovables(Stmt *S, ExprSet &exprs) {
3137196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  RemovablesCollector(exprs).TraverseStmt(S);
3148f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall}
3158f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall
3168f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall//===----------------------------------------------------------------------===//
317e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis// MigrationContext
318e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis//===----------------------------------------------------------------------===//
319e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis
320e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidisnamespace {
321e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis
322e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidisclass ASTTransform : public RecursiveASTVisitor<ASTTransform> {
323e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis  MigrationContext &MigrateCtx;
324a33849b368b0973e64ee9c49af4c080a59f99eb4Argyrios Kyrtzidis  typedef RecursiveASTVisitor<ASTTransform> base;
325e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis
326e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidispublic:
327e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis  ASTTransform(MigrationContext &MigrateCtx) : MigrateCtx(MigrateCtx) { }
328e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis
329f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis  bool shouldWalkTypesOfTypeLocs() const { return false; }
330f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis
331b0d5db1b7cac1a0680877c17fe92c6d64cf1c730Argyrios Kyrtzidis  bool TraverseObjCImplementationDecl(ObjCImplementationDecl *D) {
332b0d5db1b7cac1a0680877c17fe92c6d64cf1c730Argyrios Kyrtzidis    ObjCImplementationContext ImplCtx(MigrateCtx, D);
333b0d5db1b7cac1a0680877c17fe92c6d64cf1c730Argyrios Kyrtzidis    for (MigrationContext::traverser_iterator
334b0d5db1b7cac1a0680877c17fe92c6d64cf1c730Argyrios Kyrtzidis           I = MigrateCtx.traversers_begin(),
335b0d5db1b7cac1a0680877c17fe92c6d64cf1c730Argyrios Kyrtzidis           E = MigrateCtx.traversers_end(); I != E; ++I)
336b0d5db1b7cac1a0680877c17fe92c6d64cf1c730Argyrios Kyrtzidis      (*I)->traverseObjCImplementation(ImplCtx);
337b0d5db1b7cac1a0680877c17fe92c6d64cf1c730Argyrios Kyrtzidis
338a33849b368b0973e64ee9c49af4c080a59f99eb4Argyrios Kyrtzidis    return base::TraverseObjCImplementationDecl(D);
339b0d5db1b7cac1a0680877c17fe92c6d64cf1c730Argyrios Kyrtzidis  }
340b0d5db1b7cac1a0680877c17fe92c6d64cf1c730Argyrios Kyrtzidis
341e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis  bool TraverseStmt(Stmt *rootS) {
342e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis    if (!rootS)
343e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis      return true;
344e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis
345e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis    BodyContext BodyCtx(MigrateCtx, rootS);
346e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis    for (MigrationContext::traverser_iterator
347e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis           I = MigrateCtx.traversers_begin(),
348e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis           E = MigrateCtx.traversers_end(); I != E; ++I)
349e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis      (*I)->traverseBody(BodyCtx);
350e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis
351e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis    return true;
352e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis  }
353e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis};
354e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis
355e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis}
356e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis
357e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios KyrtzidisMigrationContext::~MigrationContext() {
358e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis  for (traverser_iterator
359e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis         I = traversers_begin(), E = traversers_end(); I != E; ++I)
360e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis    delete *I;
361e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis}
362e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis
3631fe4203ca05d0a3283efc8a2e8c01ecdf78fbf2eArgyrios Kyrtzidisbool MigrationContext::isGCOwnedNonObjC(QualType T) {
3641fe4203ca05d0a3283efc8a2e8c01ecdf78fbf2eArgyrios Kyrtzidis  while (!T.isNull()) {
3651fe4203ca05d0a3283efc8a2e8c01ecdf78fbf2eArgyrios Kyrtzidis    if (const AttributedType *AttrT = T->getAs<AttributedType>()) {
3661fe4203ca05d0a3283efc8a2e8c01ecdf78fbf2eArgyrios Kyrtzidis      if (AttrT->getAttrKind() == AttributedType::attr_objc_ownership)
3671fe4203ca05d0a3283efc8a2e8c01ecdf78fbf2eArgyrios Kyrtzidis        return !AttrT->getModifiedType()->isObjCRetainableType();
3681fe4203ca05d0a3283efc8a2e8c01ecdf78fbf2eArgyrios Kyrtzidis    }
3691fe4203ca05d0a3283efc8a2e8c01ecdf78fbf2eArgyrios Kyrtzidis
3701fe4203ca05d0a3283efc8a2e8c01ecdf78fbf2eArgyrios Kyrtzidis    if (T->isArrayType())
3711fe4203ca05d0a3283efc8a2e8c01ecdf78fbf2eArgyrios Kyrtzidis      T = Pass.Ctx.getBaseElementType(T);
3721fe4203ca05d0a3283efc8a2e8c01ecdf78fbf2eArgyrios Kyrtzidis    else if (const PointerType *PT = T->getAs<PointerType>())
3731fe4203ca05d0a3283efc8a2e8c01ecdf78fbf2eArgyrios Kyrtzidis      T = PT->getPointeeType();
3741fe4203ca05d0a3283efc8a2e8c01ecdf78fbf2eArgyrios Kyrtzidis    else if (const ReferenceType *RT = T->getAs<ReferenceType>())
3751fe4203ca05d0a3283efc8a2e8c01ecdf78fbf2eArgyrios Kyrtzidis      T = RT->getPointeeType();
3761fe4203ca05d0a3283efc8a2e8c01ecdf78fbf2eArgyrios Kyrtzidis    else
3771fe4203ca05d0a3283efc8a2e8c01ecdf78fbf2eArgyrios Kyrtzidis      break;
3781fe4203ca05d0a3283efc8a2e8c01ecdf78fbf2eArgyrios Kyrtzidis  }
3791fe4203ca05d0a3283efc8a2e8c01ecdf78fbf2eArgyrios Kyrtzidis
3801fe4203ca05d0a3283efc8a2e8c01ecdf78fbf2eArgyrios Kyrtzidis  return false;
3811fe4203ca05d0a3283efc8a2e8c01ecdf78fbf2eArgyrios Kyrtzidis}
3821fe4203ca05d0a3283efc8a2e8c01ecdf78fbf2eArgyrios Kyrtzidis
383b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidisbool MigrationContext::rewritePropertyAttribute(StringRef fromAttr,
384b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis                                                StringRef toAttr,
385b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis                                                SourceLocation atLoc) {
386b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis  if (atLoc.isMacroID())
387b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis    return false;
388b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis
389b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis  SourceManager &SM = Pass.Ctx.getSourceManager();
390b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis
391b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis  // Break down the source location.
392b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis  std::pair<FileID, unsigned> locInfo = SM.getDecomposedLoc(atLoc);
393b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis
394b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis  // Try to load the file buffer.
395b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis  bool invalidTemp = false;
396b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis  StringRef file = SM.getBufferData(locInfo.first, &invalidTemp);
397b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis  if (invalidTemp)
398b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis    return false;
399b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis
400b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis  const char *tokenBegin = file.data() + locInfo.second;
401b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis
402b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis  // Lex from the start of the given location.
403b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis  Lexer lexer(SM.getLocForStartOfFile(locInfo.first),
4044e4d08403ca5cfd4d558fa2936215d3a4e5a528dDavid Blaikie              Pass.Ctx.getLangOpts(),
405b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis              file.begin(), tokenBegin, file.end());
406b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis  Token tok;
407b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis  lexer.LexFromRawLexer(tok);
408b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis  if (tok.isNot(tok::at)) return false;
409b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis  lexer.LexFromRawLexer(tok);
410b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis  if (tok.isNot(tok::raw_identifier)) return false;
411b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis  if (StringRef(tok.getRawIdentifierData(), tok.getLength())
412b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis        != "property")
413b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis    return false;
414b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis  lexer.LexFromRawLexer(tok);
415b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis  if (tok.isNot(tok::l_paren)) return false;
416b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis
417b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis  Token BeforeTok = tok;
418b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis  Token AfterTok;
419b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis  AfterTok.startToken();
420b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis  SourceLocation AttrLoc;
421b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis
422b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis  lexer.LexFromRawLexer(tok);
423b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis  if (tok.is(tok::r_paren))
424b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis    return false;
425b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis
426b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis  while (1) {
427b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis    if (tok.isNot(tok::raw_identifier)) return false;
428b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis    StringRef ident(tok.getRawIdentifierData(), tok.getLength());
429b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis    if (ident == fromAttr) {
430b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis      if (!toAttr.empty()) {
431b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis        Pass.TA.replaceText(tok.getLocation(), fromAttr, toAttr);
432b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis        return true;
433b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis      }
434b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis      // We want to remove the attribute.
435b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis      AttrLoc = tok.getLocation();
436b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis    }
437b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis
438b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis    do {
439b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis      lexer.LexFromRawLexer(tok);
440b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis      if (AttrLoc.isValid() && AfterTok.is(tok::unknown))
441b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis        AfterTok = tok;
442b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis    } while (tok.isNot(tok::comma) && tok.isNot(tok::r_paren));
443b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis    if (tok.is(tok::r_paren))
444b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis      break;
445b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis    if (AttrLoc.isInvalid())
446b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis      BeforeTok = tok;
447b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis    lexer.LexFromRawLexer(tok);
448b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis  }
449b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis
450b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis  if (toAttr.empty() && AttrLoc.isValid() && AfterTok.isNot(tok::unknown)) {
451b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis    // We want to remove the attribute.
452b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis    if (BeforeTok.is(tok::l_paren) && AfterTok.is(tok::r_paren)) {
453b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis      Pass.TA.remove(SourceRange(BeforeTok.getLocation(),
454b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis                                 AfterTok.getLocation()));
455b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis    } else if (BeforeTok.is(tok::l_paren) && AfterTok.is(tok::comma)) {
456b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis      Pass.TA.remove(SourceRange(AttrLoc, AfterTok.getLocation()));
457b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis    } else {
458b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis      Pass.TA.remove(SourceRange(BeforeTok.getLocation(), AttrLoc));
459b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis    }
460b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis
461b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis    return true;
462b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis  }
463b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis
464b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis  return false;
465b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis}
466b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis
4676da4274724f6bd0f24f0fbfd1af076cd14b14710Argyrios Kyrtzidisbool MigrationContext::addPropertyAttribute(StringRef attr,
4686da4274724f6bd0f24f0fbfd1af076cd14b14710Argyrios Kyrtzidis                                            SourceLocation atLoc) {
4696da4274724f6bd0f24f0fbfd1af076cd14b14710Argyrios Kyrtzidis  if (atLoc.isMacroID())
4706da4274724f6bd0f24f0fbfd1af076cd14b14710Argyrios Kyrtzidis    return false;
4716da4274724f6bd0f24f0fbfd1af076cd14b14710Argyrios Kyrtzidis
4726da4274724f6bd0f24f0fbfd1af076cd14b14710Argyrios Kyrtzidis  SourceManager &SM = Pass.Ctx.getSourceManager();
4736da4274724f6bd0f24f0fbfd1af076cd14b14710Argyrios Kyrtzidis
4746da4274724f6bd0f24f0fbfd1af076cd14b14710Argyrios Kyrtzidis  // Break down the source location.
4756da4274724f6bd0f24f0fbfd1af076cd14b14710Argyrios Kyrtzidis  std::pair<FileID, unsigned> locInfo = SM.getDecomposedLoc(atLoc);
4766da4274724f6bd0f24f0fbfd1af076cd14b14710Argyrios Kyrtzidis
4776da4274724f6bd0f24f0fbfd1af076cd14b14710Argyrios Kyrtzidis  // Try to load the file buffer.
4786da4274724f6bd0f24f0fbfd1af076cd14b14710Argyrios Kyrtzidis  bool invalidTemp = false;
4796da4274724f6bd0f24f0fbfd1af076cd14b14710Argyrios Kyrtzidis  StringRef file = SM.getBufferData(locInfo.first, &invalidTemp);
4806da4274724f6bd0f24f0fbfd1af076cd14b14710Argyrios Kyrtzidis  if (invalidTemp)
4816da4274724f6bd0f24f0fbfd1af076cd14b14710Argyrios Kyrtzidis    return false;
4826da4274724f6bd0f24f0fbfd1af076cd14b14710Argyrios Kyrtzidis
4836da4274724f6bd0f24f0fbfd1af076cd14b14710Argyrios Kyrtzidis  const char *tokenBegin = file.data() + locInfo.second;
4846da4274724f6bd0f24f0fbfd1af076cd14b14710Argyrios Kyrtzidis
4856da4274724f6bd0f24f0fbfd1af076cd14b14710Argyrios Kyrtzidis  // Lex from the start of the given location.
4866da4274724f6bd0f24f0fbfd1af076cd14b14710Argyrios Kyrtzidis  Lexer lexer(SM.getLocForStartOfFile(locInfo.first),
4874e4d08403ca5cfd4d558fa2936215d3a4e5a528dDavid Blaikie              Pass.Ctx.getLangOpts(),
4886da4274724f6bd0f24f0fbfd1af076cd14b14710Argyrios Kyrtzidis              file.begin(), tokenBegin, file.end());
4896da4274724f6bd0f24f0fbfd1af076cd14b14710Argyrios Kyrtzidis  Token tok;
4906da4274724f6bd0f24f0fbfd1af076cd14b14710Argyrios Kyrtzidis  lexer.LexFromRawLexer(tok);
4916da4274724f6bd0f24f0fbfd1af076cd14b14710Argyrios Kyrtzidis  if (tok.isNot(tok::at)) return false;
4926da4274724f6bd0f24f0fbfd1af076cd14b14710Argyrios Kyrtzidis  lexer.LexFromRawLexer(tok);
4936da4274724f6bd0f24f0fbfd1af076cd14b14710Argyrios Kyrtzidis  if (tok.isNot(tok::raw_identifier)) return false;
4946da4274724f6bd0f24f0fbfd1af076cd14b14710Argyrios Kyrtzidis  if (StringRef(tok.getRawIdentifierData(), tok.getLength())
4956da4274724f6bd0f24f0fbfd1af076cd14b14710Argyrios Kyrtzidis        != "property")
4966da4274724f6bd0f24f0fbfd1af076cd14b14710Argyrios Kyrtzidis    return false;
4976da4274724f6bd0f24f0fbfd1af076cd14b14710Argyrios Kyrtzidis  lexer.LexFromRawLexer(tok);
4986da4274724f6bd0f24f0fbfd1af076cd14b14710Argyrios Kyrtzidis
4996da4274724f6bd0f24f0fbfd1af076cd14b14710Argyrios Kyrtzidis  if (tok.isNot(tok::l_paren)) {
5006da4274724f6bd0f24f0fbfd1af076cd14b14710Argyrios Kyrtzidis    Pass.TA.insert(tok.getLocation(), std::string("(") + attr.str() + ") ");
5016da4274724f6bd0f24f0fbfd1af076cd14b14710Argyrios Kyrtzidis    return true;
5026da4274724f6bd0f24f0fbfd1af076cd14b14710Argyrios Kyrtzidis  }
5036da4274724f6bd0f24f0fbfd1af076cd14b14710Argyrios Kyrtzidis
5046da4274724f6bd0f24f0fbfd1af076cd14b14710Argyrios Kyrtzidis  lexer.LexFromRawLexer(tok);
5056da4274724f6bd0f24f0fbfd1af076cd14b14710Argyrios Kyrtzidis  if (tok.is(tok::r_paren)) {
5066da4274724f6bd0f24f0fbfd1af076cd14b14710Argyrios Kyrtzidis    Pass.TA.insert(tok.getLocation(), attr);
5076da4274724f6bd0f24f0fbfd1af076cd14b14710Argyrios Kyrtzidis    return true;
5086da4274724f6bd0f24f0fbfd1af076cd14b14710Argyrios Kyrtzidis  }
5096da4274724f6bd0f24f0fbfd1af076cd14b14710Argyrios Kyrtzidis
5106da4274724f6bd0f24f0fbfd1af076cd14b14710Argyrios Kyrtzidis  if (tok.isNot(tok::raw_identifier)) return false;
5116da4274724f6bd0f24f0fbfd1af076cd14b14710Argyrios Kyrtzidis
5126da4274724f6bd0f24f0fbfd1af076cd14b14710Argyrios Kyrtzidis  Pass.TA.insert(tok.getLocation(), std::string(attr) + ", ");
5136da4274724f6bd0f24f0fbfd1af076cd14b14710Argyrios Kyrtzidis  return true;
5146da4274724f6bd0f24f0fbfd1af076cd14b14710Argyrios Kyrtzidis}
5156da4274724f6bd0f24f0fbfd1af076cd14b14710Argyrios Kyrtzidis
516e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidisvoid MigrationContext::traverse(TranslationUnitDecl *TU) {
517f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis  for (traverser_iterator
518f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis         I = traversers_begin(), E = traversers_end(); I != E; ++I)
519f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis    (*I)->traverseTU(*this);
520f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis
521e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis  ASTTransform(*this).TraverseDecl(TU);
522e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis}
523e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis
524bbdfad581fa300fa0d162d968ec14de3c95fc760Fariborz Jahanianstatic void GCRewriteFinalize(MigrationPass &pass) {
525bbdfad581fa300fa0d162d968ec14de3c95fc760Fariborz Jahanian  ASTContext &Ctx = pass.Ctx;
526bbdfad581fa300fa0d162d968ec14de3c95fc760Fariborz Jahanian  TransformActions &TA = pass.TA;
527bbdfad581fa300fa0d162d968ec14de3c95fc760Fariborz Jahanian  DeclContext *DC = Ctx.getTranslationUnitDecl();
528bbdfad581fa300fa0d162d968ec14de3c95fc760Fariborz Jahanian  Selector FinalizeSel =
529bbdfad581fa300fa0d162d968ec14de3c95fc760Fariborz Jahanian   Ctx.Selectors.getNullarySelector(&pass.Ctx.Idents.get("finalize"));
530bbdfad581fa300fa0d162d968ec14de3c95fc760Fariborz Jahanian
531bbdfad581fa300fa0d162d968ec14de3c95fc760Fariborz Jahanian  typedef DeclContext::specific_decl_iterator<ObjCImplementationDecl>
532bbdfad581fa300fa0d162d968ec14de3c95fc760Fariborz Jahanian  impl_iterator;
533bbdfad581fa300fa0d162d968ec14de3c95fc760Fariborz Jahanian  for (impl_iterator I = impl_iterator(DC->decls_begin()),
534bbdfad581fa300fa0d162d968ec14de3c95fc760Fariborz Jahanian       E = impl_iterator(DC->decls_end()); I != E; ++I) {
535bbdfad581fa300fa0d162d968ec14de3c95fc760Fariborz Jahanian    for (ObjCImplementationDecl::instmeth_iterator
536262bc18e32500558af7cb0afa205b34bd37bafedDavid Blaikie         MI = I->instmeth_begin(),
537262bc18e32500558af7cb0afa205b34bd37bafedDavid Blaikie         ME = I->instmeth_end(); MI != ME; ++MI) {
538bbdfad581fa300fa0d162d968ec14de3c95fc760Fariborz Jahanian      ObjCMethodDecl *MD = *MI;
539bbdfad581fa300fa0d162d968ec14de3c95fc760Fariborz Jahanian      if (!MD->hasBody())
540bbdfad581fa300fa0d162d968ec14de3c95fc760Fariborz Jahanian        continue;
541bbdfad581fa300fa0d162d968ec14de3c95fc760Fariborz Jahanian
542bbdfad581fa300fa0d162d968ec14de3c95fc760Fariborz Jahanian      if (MD->isInstanceMethod() && MD->getSelector() == FinalizeSel) {
543bbdfad581fa300fa0d162d968ec14de3c95fc760Fariborz Jahanian        ObjCMethodDecl *FinalizeM = MD;
544bbdfad581fa300fa0d162d968ec14de3c95fc760Fariborz Jahanian        Transaction Trans(TA);
545bbdfad581fa300fa0d162d968ec14de3c95fc760Fariborz Jahanian        TA.insert(FinalizeM->getSourceRange().getBegin(),
546bbdfad581fa300fa0d162d968ec14de3c95fc760Fariborz Jahanian                  "#if !__has_feature(objc_arc)\n");
547bbdfad581fa300fa0d162d968ec14de3c95fc760Fariborz Jahanian        CharSourceRange::getTokenRange(FinalizeM->getSourceRange());
548bbdfad581fa300fa0d162d968ec14de3c95fc760Fariborz Jahanian        const SourceManager &SM = pass.Ctx.getSourceManager();
5494e4d08403ca5cfd4d558fa2936215d3a4e5a528dDavid Blaikie        const LangOptions &LangOpts = pass.Ctx.getLangOpts();
550bbdfad581fa300fa0d162d968ec14de3c95fc760Fariborz Jahanian        bool Invalid;
551bbdfad581fa300fa0d162d968ec14de3c95fc760Fariborz Jahanian        std::string str = "\n#endif\n";
552bbdfad581fa300fa0d162d968ec14de3c95fc760Fariborz Jahanian        str += Lexer::getSourceText(
553bbdfad581fa300fa0d162d968ec14de3c95fc760Fariborz Jahanian                  CharSourceRange::getTokenRange(FinalizeM->getSourceRange()),
554bbdfad581fa300fa0d162d968ec14de3c95fc760Fariborz Jahanian                                    SM, LangOpts, &Invalid);
555bbdfad581fa300fa0d162d968ec14de3c95fc760Fariborz Jahanian        TA.insertAfterToken(FinalizeM->getSourceRange().getEnd(), str);
556bbdfad581fa300fa0d162d968ec14de3c95fc760Fariborz Jahanian
557bbdfad581fa300fa0d162d968ec14de3c95fc760Fariborz Jahanian        break;
558bbdfad581fa300fa0d162d968ec14de3c95fc760Fariborz Jahanian      }
559bbdfad581fa300fa0d162d968ec14de3c95fc760Fariborz Jahanian    }
560bbdfad581fa300fa0d162d968ec14de3c95fc760Fariborz Jahanian  }
561bbdfad581fa300fa0d162d968ec14de3c95fc760Fariborz Jahanian}
562bbdfad581fa300fa0d162d968ec14de3c95fc760Fariborz Jahanian
563e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis//===----------------------------------------------------------------------===//
5648f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall// getAllTransformations.
5658f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall//===----------------------------------------------------------------------===//
5668f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall
567e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidisstatic void traverseAST(MigrationPass &pass) {
568e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis  MigrationContext MigrateCtx(pass);
569e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis
570e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis  if (pass.isGCMigration()) {
571e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis    MigrateCtx.addTraverser(new GCCollectableCallsTraverser);
572f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis    MigrateCtx.addTraverser(new GCAttrsTraverser());
573e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis  }
574b0d5db1b7cac1a0680877c17fe92c6d64cf1c730Argyrios Kyrtzidis  MigrateCtx.addTraverser(new PropertyRewriteTraverser());
5752a2781805a6b55573d369e34c5dcfba307ce83e9Argyrios Kyrtzidis  MigrateCtx.addTraverser(new BlockObjCVariableTraverser());
576ea2224d7078c4d31ad32adbaba4bdc2d85a3d609Argyrios Kyrtzidis  MigrateCtx.addTraverser(new ProtectedScopeTraverser());
577e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis
578e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis  MigrateCtx.traverse(pass.Ctx.getTranslationUnitDecl());
579e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis}
580e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis
5818f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCallstatic void independentTransforms(MigrationPass &pass) {
5828f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  rewriteAutoreleasePool(pass);
583e7ef8556f4ee3012a0479308c993af0fbee448dfArgyrios Kyrtzidis  removeRetainReleaseDeallocFinalize(pass);
5847196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  rewriteUnusedInitDelegate(pass);
585e7ef8556f4ee3012a0479308c993af0fbee448dfArgyrios Kyrtzidis  removeZeroOutPropsInDeallocFinalize(pass);
5868f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  makeAssignARCSafe(pass);
5877196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  rewriteUnbridgedCasts(pass);
588fd10398c10ffdcbdeb1e3e299c74d70e689f503cArgyrios Kyrtzidis  checkAPIUses(pass);
589e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis  traverseAST(pass);
5908f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall}
5918f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall
592e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidisstd::vector<TransformFn> arcmt::getAllTransformations(
593bbdfad581fa300fa0d162d968ec14de3c95fc760Fariborz Jahanian                                               LangOptions::GCMode OrigGCMode,
594bbdfad581fa300fa0d162d968ec14de3c95fc760Fariborz Jahanian                                               bool NoFinalizeRemoval) {
5958f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  std::vector<TransformFn> transforms;
5968f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall
597bbdfad581fa300fa0d162d968ec14de3c95fc760Fariborz Jahanian  if (OrigGCMode ==  LangOptions::GCOnly && NoFinalizeRemoval)
598bbdfad581fa300fa0d162d968ec14de3c95fc760Fariborz Jahanian    transforms.push_back(GCRewriteFinalize);
5998f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  transforms.push_back(independentTransforms);
600fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis  // This depends on previous transformations removing various expressions.
601e7ef8556f4ee3012a0479308c993af0fbee448dfArgyrios Kyrtzidis  transforms.push_back(removeEmptyStatementsAndDeallocFinalize);
6028f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall
6038f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  return transforms;
6048f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall}
605