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