Transforms.cpp revision b0e1e121b32a9a04b39f1b77b3068bce2f3be05a
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/Analysis/DomainSpecific/CocoaConventions.h"
168f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall#include "clang/Lex/Lexer.h"
178f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall#include "clang/Basic/SourceManager.h"
188f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall#include "llvm/ADT/StringSwitch.h"
198f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall#include "llvm/ADT/DenseSet.h"
208f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall#include <map>
218f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall
228f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCallusing namespace clang;
238f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCallusing namespace arcmt;
247196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidisusing namespace trans;
258f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall
26e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios KyrtzidisASTTraverser::~ASTTraverser() { }
27e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis
288f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall//===----------------------------------------------------------------------===//
297196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis// Helpers.
308f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall//===----------------------------------------------------------------------===//
318f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall
3286625b5650cdddc38c0b4cc1eb7fb460478c9d11Argyrios Kyrtzidis/// \brief True if the class is one that does not support weak.
3386625b5650cdddc38c0b4cc1eb7fb460478c9d11Argyrios Kyrtzidisstatic bool isClassInWeakBlacklist(ObjCInterfaceDecl *cls) {
3486625b5650cdddc38c0b4cc1eb7fb460478c9d11Argyrios Kyrtzidis  if (!cls)
3586625b5650cdddc38c0b4cc1eb7fb460478c9d11Argyrios Kyrtzidis    return false;
3686625b5650cdddc38c0b4cc1eb7fb460478c9d11Argyrios Kyrtzidis
3786625b5650cdddc38c0b4cc1eb7fb460478c9d11Argyrios Kyrtzidis  bool inList = llvm::StringSwitch<bool>(cls->getName())
3886625b5650cdddc38c0b4cc1eb7fb460478c9d11Argyrios Kyrtzidis                 .Case("NSColorSpace", true)
3986625b5650cdddc38c0b4cc1eb7fb460478c9d11Argyrios Kyrtzidis                 .Case("NSFont", true)
4086625b5650cdddc38c0b4cc1eb7fb460478c9d11Argyrios Kyrtzidis                 .Case("NSFontPanel", true)
4186625b5650cdddc38c0b4cc1eb7fb460478c9d11Argyrios Kyrtzidis                 .Case("NSImage", true)
4286625b5650cdddc38c0b4cc1eb7fb460478c9d11Argyrios Kyrtzidis                 .Case("NSLazyBrowserCell", true)
4386625b5650cdddc38c0b4cc1eb7fb460478c9d11Argyrios Kyrtzidis                 .Case("NSWindow", true)
4486625b5650cdddc38c0b4cc1eb7fb460478c9d11Argyrios Kyrtzidis                 .Case("NSWindowController", true)
4586625b5650cdddc38c0b4cc1eb7fb460478c9d11Argyrios Kyrtzidis                 .Case("NSMenuView", true)
4686625b5650cdddc38c0b4cc1eb7fb460478c9d11Argyrios Kyrtzidis                 .Case("NSPersistentUIWindowInfo", true)
4786625b5650cdddc38c0b4cc1eb7fb460478c9d11Argyrios Kyrtzidis                 .Case("NSTableCellView", true)
4886625b5650cdddc38c0b4cc1eb7fb460478c9d11Argyrios Kyrtzidis                 .Case("NSATSTypeSetter", true)
4986625b5650cdddc38c0b4cc1eb7fb460478c9d11Argyrios Kyrtzidis                 .Case("NSATSGlyphStorage", true)
5086625b5650cdddc38c0b4cc1eb7fb460478c9d11Argyrios Kyrtzidis                 .Case("NSLineFragmentRenderingContext", true)
5186625b5650cdddc38c0b4cc1eb7fb460478c9d11Argyrios Kyrtzidis                 .Case("NSAttributeDictionary", true)
5286625b5650cdddc38c0b4cc1eb7fb460478c9d11Argyrios Kyrtzidis                 .Case("NSParagraphStyle", true)
5386625b5650cdddc38c0b4cc1eb7fb460478c9d11Argyrios Kyrtzidis                 .Case("NSTextTab", true)
5486625b5650cdddc38c0b4cc1eb7fb460478c9d11Argyrios Kyrtzidis                 .Case("NSSimpleHorizontalTypesetter", true)
5586625b5650cdddc38c0b4cc1eb7fb460478c9d11Argyrios Kyrtzidis                 .Case("_NSCachedAttributedString", true)
5686625b5650cdddc38c0b4cc1eb7fb460478c9d11Argyrios Kyrtzidis                 .Case("NSStringDrawingTextStorage", true)
5786625b5650cdddc38c0b4cc1eb7fb460478c9d11Argyrios Kyrtzidis                 .Case("NSTextView", true)
5886625b5650cdddc38c0b4cc1eb7fb460478c9d11Argyrios Kyrtzidis                 .Case("NSSubTextStorage", true)
5986625b5650cdddc38c0b4cc1eb7fb460478c9d11Argyrios Kyrtzidis                 .Default(false);
6086625b5650cdddc38c0b4cc1eb7fb460478c9d11Argyrios Kyrtzidis
6186625b5650cdddc38c0b4cc1eb7fb460478c9d11Argyrios Kyrtzidis  if (inList)
6286625b5650cdddc38c0b4cc1eb7fb460478c9d11Argyrios Kyrtzidis    return true;
6386625b5650cdddc38c0b4cc1eb7fb460478c9d11Argyrios Kyrtzidis
6486625b5650cdddc38c0b4cc1eb7fb460478c9d11Argyrios Kyrtzidis  return isClassInWeakBlacklist(cls->getSuperClass());
6586625b5650cdddc38c0b4cc1eb7fb460478c9d11Argyrios Kyrtzidis}
6686625b5650cdddc38c0b4cc1eb7fb460478c9d11Argyrios Kyrtzidis
6712192cf50a96cb59a3039af044b7fa97f043101cArgyrios Kyrtzidisbool trans::canApplyWeak(ASTContext &Ctx, QualType type,
6812192cf50a96cb59a3039af044b7fa97f043101cArgyrios Kyrtzidis                         bool AllowOnUnknownClass) {
6986625b5650cdddc38c0b4cc1eb7fb460478c9d11Argyrios Kyrtzidis  if (!Ctx.getLangOptions().ObjCRuntimeHasWeak)
7086625b5650cdddc38c0b4cc1eb7fb460478c9d11Argyrios Kyrtzidis    return false;
7186625b5650cdddc38c0b4cc1eb7fb460478c9d11Argyrios Kyrtzidis
7286625b5650cdddc38c0b4cc1eb7fb460478c9d11Argyrios Kyrtzidis  QualType T = type;
73b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis  if (T.isNull())
74b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis    return false;
75b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis
7686625b5650cdddc38c0b4cc1eb7fb460478c9d11Argyrios Kyrtzidis  while (const PointerType *ptr = T->getAs<PointerType>())
7786625b5650cdddc38c0b4cc1eb7fb460478c9d11Argyrios Kyrtzidis    T = ptr->getPointeeType();
7886625b5650cdddc38c0b4cc1eb7fb460478c9d11Argyrios Kyrtzidis  if (const ObjCObjectPointerType *ObjT = T->getAs<ObjCObjectPointerType>()) {
7986625b5650cdddc38c0b4cc1eb7fb460478c9d11Argyrios Kyrtzidis    ObjCInterfaceDecl *Class = ObjT->getInterfaceDecl();
8012192cf50a96cb59a3039af044b7fa97f043101cArgyrios Kyrtzidis    if (!AllowOnUnknownClass && (!Class || Class->getName() == "NSObject"))
8186625b5650cdddc38c0b4cc1eb7fb460478c9d11Argyrios Kyrtzidis      return false; // id/NSObject is not safe for weak.
8212192cf50a96cb59a3039af044b7fa97f043101cArgyrios Kyrtzidis    if (!AllowOnUnknownClass && Class->isForwardDecl())
835363e8df5d274cb32c0c47fd2df45aa02cf68dfeArgyrios Kyrtzidis      return false; // forward classes are not verifiable, therefore not safe.
8486625b5650cdddc38c0b4cc1eb7fb460478c9d11Argyrios Kyrtzidis    if (Class->isArcWeakrefUnavailable())
8586625b5650cdddc38c0b4cc1eb7fb460478c9d11Argyrios Kyrtzidis      return false;
8686625b5650cdddc38c0b4cc1eb7fb460478c9d11Argyrios Kyrtzidis    if (isClassInWeakBlacklist(Class))
8786625b5650cdddc38c0b4cc1eb7fb460478c9d11Argyrios Kyrtzidis      return false;
8886625b5650cdddc38c0b4cc1eb7fb460478c9d11Argyrios Kyrtzidis  }
8986625b5650cdddc38c0b4cc1eb7fb460478c9d11Argyrios Kyrtzidis
9086625b5650cdddc38c0b4cc1eb7fb460478c9d11Argyrios Kyrtzidis  return true;
9186625b5650cdddc38c0b4cc1eb7fb460478c9d11Argyrios Kyrtzidis}
9286625b5650cdddc38c0b4cc1eb7fb460478c9d11Argyrios Kyrtzidis
937196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis/// \brief 'Loc' is the end of a statement range. This returns the location
947196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis/// immediately after the semicolon following the statement.
957196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis/// If no semicolon is found or the location is inside a macro, the returned
967196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis/// source location will be invalid.
977196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios KyrtzidisSourceLocation trans::findLocationAfterSemi(SourceLocation loc,
987196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis                                            ASTContext &Ctx) {
99aec230d29835285777ecc467e268c83b33a2addeArgyrios Kyrtzidis  SourceLocation SemiLoc = findSemiAfterLocation(loc, Ctx);
100aec230d29835285777ecc467e268c83b33a2addeArgyrios Kyrtzidis  if (SemiLoc.isInvalid())
101aec230d29835285777ecc467e268c83b33a2addeArgyrios Kyrtzidis    return SourceLocation();
102a64ccefdf0ea4e03ec88805d71b0af74950c7472Argyrios Kyrtzidis  return SemiLoc.getLocWithOffset(1);
103aec230d29835285777ecc467e268c83b33a2addeArgyrios Kyrtzidis}
104aec230d29835285777ecc467e268c83b33a2addeArgyrios Kyrtzidis
105aec230d29835285777ecc467e268c83b33a2addeArgyrios Kyrtzidis/// \brief \arg Loc is the end of a statement range. This returns the location
106aec230d29835285777ecc467e268c83b33a2addeArgyrios Kyrtzidis/// of the semicolon following the statement.
107aec230d29835285777ecc467e268c83b33a2addeArgyrios Kyrtzidis/// If no semicolon is found or the location is inside a macro, the returned
108aec230d29835285777ecc467e268c83b33a2addeArgyrios Kyrtzidis/// source location will be invalid.
109aec230d29835285777ecc467e268c83b33a2addeArgyrios KyrtzidisSourceLocation trans::findSemiAfterLocation(SourceLocation loc,
110aec230d29835285777ecc467e268c83b33a2addeArgyrios Kyrtzidis                                            ASTContext &Ctx) {
1117196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  SourceManager &SM = Ctx.getSourceManager();
1127196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  if (loc.isMacroID()) {
113433db06b614f26dc6829e86d6ff469e2cca7d4f9Chandler Carruth    if (!Lexer::isAtEndOfMacroExpansion(loc, SM, Ctx.getLangOptions()))
1147196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis      return SourceLocation();
115edc3dccece244a584f8ebdb81da6c962c08e79beChandler Carruth    loc = SM.getExpansionRange(loc).second;
1167196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  }
1177196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  loc = Lexer::getLocForEndOfToken(loc, /*Offset=*/0, SM, Ctx.getLangOptions());
1188f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall
1197196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  // Break down the source location.
1207196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  std::pair<FileID, unsigned> locInfo = SM.getDecomposedLoc(loc);
1218f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall
1227196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  // Try to load the file buffer.
1237196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  bool invalidTemp = false;
1245f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner  StringRef file = SM.getBufferData(locInfo.first, &invalidTemp);
1257196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  if (invalidTemp)
1267196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    return SourceLocation();
1277196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
1287196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  const char *tokenBegin = file.data() + locInfo.second;
1297196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
1307196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  // Lex from the start of the given location.
1317196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  Lexer lexer(SM.getLocForStartOfFile(locInfo.first),
1327196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis              Ctx.getLangOptions(),
1337196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis              file.begin(), tokenBegin, file.end());
1347196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  Token tok;
1357196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  lexer.LexFromRawLexer(tok);
1367196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  if (tok.isNot(tok::semi))
1377196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    return SourceLocation();
1388f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall
139aec230d29835285777ecc467e268c83b33a2addeArgyrios Kyrtzidis  return tok.getLocation();
1407196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis}
1418f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall
1427196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidisbool trans::hasSideEffects(Expr *E, ASTContext &Ctx) {
1438f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  if (!E || !E->HasSideEffects(Ctx))
1448f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall    return false;
1458f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall
1468f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  E = E->IgnoreParenCasts();
1478f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  ObjCMessageExpr *ME = dyn_cast<ObjCMessageExpr>(E);
1488f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  if (!ME)
1498f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall    return true;
1508f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  switch (ME->getMethodFamily()) {
1518f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  case OMF_autorelease:
1528f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  case OMF_dealloc:
1538f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  case OMF_release:
1548f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  case OMF_retain:
1558f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall    switch (ME->getReceiverKind()) {
1568f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall    case ObjCMessageExpr::SuperInstance:
1578f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall      return false;
1588f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall    case ObjCMessageExpr::Instance:
1597196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis      return hasSideEffects(ME->getInstanceReceiver(), Ctx);
1608f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall    default:
1618f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall      break;
1628f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall    }
1638f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall    break;
1648f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  default:
1658f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall    break;
1668f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  }
1678f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall
1688f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  return true;
1698f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall}
1708f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall
1712c18ca0575b60082f2a9f4563b4071071960d37cArgyrios Kyrtzidisbool trans::isGlobalVar(Expr *E) {
1722c18ca0575b60082f2a9f4563b4071071960d37cArgyrios Kyrtzidis  E = E->IgnoreParenCasts();
1732c18ca0575b60082f2a9f4563b4071071960d37cArgyrios Kyrtzidis  if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E))
17418fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis    return DRE->getDecl()->getDeclContext()->isFileContext() &&
17518fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis           DRE->getDecl()->getLinkage() == ExternalLinkage;
1762c18ca0575b60082f2a9f4563b4071071960d37cArgyrios Kyrtzidis  if (ConditionalOperator *condOp = dyn_cast<ConditionalOperator>(E))
1772c18ca0575b60082f2a9f4563b4071071960d37cArgyrios Kyrtzidis    return isGlobalVar(condOp->getTrueExpr()) &&
1782c18ca0575b60082f2a9f4563b4071071960d37cArgyrios Kyrtzidis           isGlobalVar(condOp->getFalseExpr());
1792c18ca0575b60082f2a9f4563b4071071960d37cArgyrios Kyrtzidis
1802c18ca0575b60082f2a9f4563b4071071960d37cArgyrios Kyrtzidis  return false;
1812c18ca0575b60082f2a9f4563b4071071960d37cArgyrios Kyrtzidis}
1822c18ca0575b60082f2a9f4563b4071071960d37cArgyrios Kyrtzidis
18318fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios KyrtzidisStringRef trans::getNilString(ASTContext &Ctx) {
18418fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis  if (Ctx.Idents.get("nil").hasMacroDefinition())
18518fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis    return "nil";
18618fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis  else
18718fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis    return "0";
18818fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis}
18918fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis
1908f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCallnamespace {
1918f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall
1928f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCallclass ReferenceClear : public RecursiveASTVisitor<ReferenceClear> {
1937196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  ExprSet &Refs;
1948f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCallpublic:
1957196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  ReferenceClear(ExprSet &refs) : Refs(refs) { }
1968f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  bool VisitDeclRefExpr(DeclRefExpr *E) { Refs.erase(E); return true; }
1978f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  bool VisitBlockDeclRefExpr(BlockDeclRefExpr *E) { Refs.erase(E); return true; }
1988f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall};
1998f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall
2008f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCallclass ReferenceCollector : public RecursiveASTVisitor<ReferenceCollector> {
2018f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  ValueDecl *Dcl;
2027196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  ExprSet &Refs;
2038f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall
2048f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCallpublic:
2057196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  ReferenceCollector(ValueDecl *D, ExprSet &refs)
2067196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    : Dcl(D), Refs(refs) { }
2078f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall
2088f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  bool VisitDeclRefExpr(DeclRefExpr *E) {
2098f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall    if (E->getDecl() == Dcl)
2108f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall      Refs.insert(E);
2118f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall    return true;
2128f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  }
2138f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall
2148f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  bool VisitBlockDeclRefExpr(BlockDeclRefExpr *E) {
2158f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall    if (E->getDecl() == Dcl)
2168f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall      Refs.insert(E);
2178f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall    return true;
2188f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  }
2198f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall};
2208f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall
2217196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidisclass RemovablesCollector : public RecursiveASTVisitor<RemovablesCollector> {
2227196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  ExprSet &Removables;
2238f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall
2248f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCallpublic:
2257196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  RemovablesCollector(ExprSet &removables)
2267196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  : Removables(removables) { }
2277196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
2287196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  bool shouldWalkTypesOfTypeLocs() const { return false; }
2297196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
2307196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  bool TraverseStmtExpr(StmtExpr *E) {
2317196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    CompoundStmt *S = E->getSubStmt();
2327196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    for (CompoundStmt::body_iterator
2337196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis        I = S->body_begin(), E = S->body_end(); I != E; ++I) {
2347196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis      if (I != E - 1)
2357196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis        mark(*I);
2367196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis      TraverseStmt(*I);
2378f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall    }
2388f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall    return true;
2398f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  }
2407196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
2417196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  bool VisitCompoundStmt(CompoundStmt *S) {
2427196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    for (CompoundStmt::body_iterator
2437196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis        I = S->body_begin(), E = S->body_end(); I != E; ++I)
2447196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis      mark(*I);
2458f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall    return true;
2468f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  }
2477196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
2487196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  bool VisitIfStmt(IfStmt *S) {
2497196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    mark(S->getThen());
2507196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    mark(S->getElse());
2518f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall    return true;
2528f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  }
2537196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
2547196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  bool VisitWhileStmt(WhileStmt *S) {
2557196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    mark(S->getBody());
2568f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall    return true;
2578f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  }
2587196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
2597196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  bool VisitDoStmt(DoStmt *S) {
2607196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    mark(S->getBody());
2618f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall    return true;
2628f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  }
2637196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
2647196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  bool VisitForStmt(ForStmt *S) {
2657196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    mark(S->getInit());
2667196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    mark(S->getInc());
2677196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    mark(S->getBody());
2688f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall    return true;
2698f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  }
2707196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
2718f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCallprivate:
2727196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  void mark(Stmt *S) {
2737196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    if (!S) return;
2747196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis
2757e5e5f4cc36fe50f46ad76dca7a266434c94f475John McCall    while (LabelStmt *Label = dyn_cast<LabelStmt>(S))
2767e5e5f4cc36fe50f46ad76dca7a266434c94f475John McCall      S = Label->getSubStmt();
2777e5e5f4cc36fe50f46ad76dca7a266434c94f475John McCall    S = S->IgnoreImplicit();
2787196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis    if (Expr *E = dyn_cast<Expr>(S))
2797196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis      Removables.insert(E);
2808e2ce7fdf9e8033b77788662a9c3f61334eb5dafArgyrios Kyrtzidis  }
2817196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis};
2828e2ce7fdf9e8033b77788662a9c3f61334eb5dafArgyrios Kyrtzidis
2837196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis} // end anonymous namespace
2848f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall
2857196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidisvoid trans::clearRefsIn(Stmt *S, ExprSet &refs) {
2867196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  ReferenceClear(refs).TraverseStmt(S);
2877196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis}
2888f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall
2897196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidisvoid trans::collectRefs(ValueDecl *D, Stmt *S, ExprSet &refs) {
2907196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  ReferenceCollector(D, refs).TraverseStmt(S);
2918f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall}
2928f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall
2937196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidisvoid trans::collectRemovables(Stmt *S, ExprSet &exprs) {
2947196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  RemovablesCollector(exprs).TraverseStmt(S);
2958f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall}
2968f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall
2978f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall//===----------------------------------------------------------------------===//
298e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis// MigrationContext
299e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis//===----------------------------------------------------------------------===//
300e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis
301e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidisnamespace {
302e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis
303e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidisclass ASTTransform : public RecursiveASTVisitor<ASTTransform> {
304e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis  MigrationContext &MigrateCtx;
305e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis
306e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidispublic:
307e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis  ASTTransform(MigrationContext &MigrateCtx) : MigrateCtx(MigrateCtx) { }
308e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis
309f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis  bool shouldWalkTypesOfTypeLocs() const { return false; }
310f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis
311b0d5db1b7cac1a0680877c17fe92c6d64cf1c730Argyrios Kyrtzidis  bool TraverseObjCImplementationDecl(ObjCImplementationDecl *D) {
312b0d5db1b7cac1a0680877c17fe92c6d64cf1c730Argyrios Kyrtzidis    ObjCImplementationContext ImplCtx(MigrateCtx, D);
313b0d5db1b7cac1a0680877c17fe92c6d64cf1c730Argyrios Kyrtzidis    for (MigrationContext::traverser_iterator
314b0d5db1b7cac1a0680877c17fe92c6d64cf1c730Argyrios Kyrtzidis           I = MigrateCtx.traversers_begin(),
315b0d5db1b7cac1a0680877c17fe92c6d64cf1c730Argyrios Kyrtzidis           E = MigrateCtx.traversers_end(); I != E; ++I)
316b0d5db1b7cac1a0680877c17fe92c6d64cf1c730Argyrios Kyrtzidis      (*I)->traverseObjCImplementation(ImplCtx);
317b0d5db1b7cac1a0680877c17fe92c6d64cf1c730Argyrios Kyrtzidis
318b0d5db1b7cac1a0680877c17fe92c6d64cf1c730Argyrios Kyrtzidis    return true;
319b0d5db1b7cac1a0680877c17fe92c6d64cf1c730Argyrios Kyrtzidis  }
320b0d5db1b7cac1a0680877c17fe92c6d64cf1c730Argyrios Kyrtzidis
321e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis  bool TraverseStmt(Stmt *rootS) {
322e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis    if (!rootS)
323e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis      return true;
324e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis
325e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis    BodyContext BodyCtx(MigrateCtx, rootS);
326e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis    for (MigrationContext::traverser_iterator
327e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis           I = MigrateCtx.traversers_begin(),
328e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis           E = MigrateCtx.traversers_end(); I != E; ++I)
329e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis      (*I)->traverseBody(BodyCtx);
330e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis
331e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis    return true;
332e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis  }
333e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis};
334e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis
335e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis}
336e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis
337e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios KyrtzidisMigrationContext::~MigrationContext() {
338e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis  for (traverser_iterator
339e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis         I = traversers_begin(), E = traversers_end(); I != E; ++I)
340e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis    delete *I;
341e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis}
342e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis
3431fe4203ca05d0a3283efc8a2e8c01ecdf78fbf2eArgyrios Kyrtzidisbool MigrationContext::isGCOwnedNonObjC(QualType T) {
3441fe4203ca05d0a3283efc8a2e8c01ecdf78fbf2eArgyrios Kyrtzidis  while (!T.isNull()) {
3451fe4203ca05d0a3283efc8a2e8c01ecdf78fbf2eArgyrios Kyrtzidis    if (const AttributedType *AttrT = T->getAs<AttributedType>()) {
3461fe4203ca05d0a3283efc8a2e8c01ecdf78fbf2eArgyrios Kyrtzidis      if (AttrT->getAttrKind() == AttributedType::attr_objc_ownership)
3471fe4203ca05d0a3283efc8a2e8c01ecdf78fbf2eArgyrios Kyrtzidis        return !AttrT->getModifiedType()->isObjCRetainableType();
3481fe4203ca05d0a3283efc8a2e8c01ecdf78fbf2eArgyrios Kyrtzidis    }
3491fe4203ca05d0a3283efc8a2e8c01ecdf78fbf2eArgyrios Kyrtzidis
3501fe4203ca05d0a3283efc8a2e8c01ecdf78fbf2eArgyrios Kyrtzidis    if (T->isArrayType())
3511fe4203ca05d0a3283efc8a2e8c01ecdf78fbf2eArgyrios Kyrtzidis      T = Pass.Ctx.getBaseElementType(T);
3521fe4203ca05d0a3283efc8a2e8c01ecdf78fbf2eArgyrios Kyrtzidis    else if (const PointerType *PT = T->getAs<PointerType>())
3531fe4203ca05d0a3283efc8a2e8c01ecdf78fbf2eArgyrios Kyrtzidis      T = PT->getPointeeType();
3541fe4203ca05d0a3283efc8a2e8c01ecdf78fbf2eArgyrios Kyrtzidis    else if (const ReferenceType *RT = T->getAs<ReferenceType>())
3551fe4203ca05d0a3283efc8a2e8c01ecdf78fbf2eArgyrios Kyrtzidis      T = RT->getPointeeType();
3561fe4203ca05d0a3283efc8a2e8c01ecdf78fbf2eArgyrios Kyrtzidis    else
3571fe4203ca05d0a3283efc8a2e8c01ecdf78fbf2eArgyrios Kyrtzidis      break;
3581fe4203ca05d0a3283efc8a2e8c01ecdf78fbf2eArgyrios Kyrtzidis  }
3591fe4203ca05d0a3283efc8a2e8c01ecdf78fbf2eArgyrios Kyrtzidis
3601fe4203ca05d0a3283efc8a2e8c01ecdf78fbf2eArgyrios Kyrtzidis  return false;
3611fe4203ca05d0a3283efc8a2e8c01ecdf78fbf2eArgyrios Kyrtzidis}
3621fe4203ca05d0a3283efc8a2e8c01ecdf78fbf2eArgyrios Kyrtzidis
363b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidisbool MigrationContext::rewritePropertyAttribute(StringRef fromAttr,
364b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis                                                StringRef toAttr,
365b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis                                                SourceLocation atLoc) {
366b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis  if (atLoc.isMacroID())
367b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis    return false;
368b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis
369b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis  SourceManager &SM = Pass.Ctx.getSourceManager();
370b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis
371b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis  // Break down the source location.
372b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis  std::pair<FileID, unsigned> locInfo = SM.getDecomposedLoc(atLoc);
373b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis
374b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis  // Try to load the file buffer.
375b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis  bool invalidTemp = false;
376b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis  StringRef file = SM.getBufferData(locInfo.first, &invalidTemp);
377b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis  if (invalidTemp)
378b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis    return false;
379b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis
380b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis  const char *tokenBegin = file.data() + locInfo.second;
381b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis
382b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis  // Lex from the start of the given location.
383b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis  Lexer lexer(SM.getLocForStartOfFile(locInfo.first),
384b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis              Pass.Ctx.getLangOptions(),
385b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis              file.begin(), tokenBegin, file.end());
386b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis  Token tok;
387b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis  lexer.LexFromRawLexer(tok);
388b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis  if (tok.isNot(tok::at)) return false;
389b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis  lexer.LexFromRawLexer(tok);
390b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis  if (tok.isNot(tok::raw_identifier)) return false;
391b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis  if (StringRef(tok.getRawIdentifierData(), tok.getLength())
392b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis        != "property")
393b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis    return false;
394b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis  lexer.LexFromRawLexer(tok);
395b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis  if (tok.isNot(tok::l_paren)) return false;
396b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis
397b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis  Token BeforeTok = tok;
398b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis  Token AfterTok;
399b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis  AfterTok.startToken();
400b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis  SourceLocation AttrLoc;
401b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis
402b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis  lexer.LexFromRawLexer(tok);
403b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis  if (tok.is(tok::r_paren))
404b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis    return false;
405b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis
406b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis  while (1) {
407b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis    if (tok.isNot(tok::raw_identifier)) return false;
408b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis    StringRef ident(tok.getRawIdentifierData(), tok.getLength());
409b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis    if (ident == fromAttr) {
410b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis      if (!toAttr.empty()) {
411b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis        Pass.TA.replaceText(tok.getLocation(), fromAttr, toAttr);
412b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis        return true;
413b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis      }
414b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis      // We want to remove the attribute.
415b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis      AttrLoc = tok.getLocation();
416b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis    }
417b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis
418b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis    do {
419b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis      lexer.LexFromRawLexer(tok);
420b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis      if (AttrLoc.isValid() && AfterTok.is(tok::unknown))
421b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis        AfterTok = tok;
422b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis    } while (tok.isNot(tok::comma) && tok.isNot(tok::r_paren));
423b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis    if (tok.is(tok::r_paren))
424b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis      break;
425b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis    if (AttrLoc.isInvalid())
426b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis      BeforeTok = tok;
427b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis    lexer.LexFromRawLexer(tok);
428b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis  }
429b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis
430b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis  if (toAttr.empty() && AttrLoc.isValid() && AfterTok.isNot(tok::unknown)) {
431b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis    // We want to remove the attribute.
432b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis    if (BeforeTok.is(tok::l_paren) && AfterTok.is(tok::r_paren)) {
433b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis      Pass.TA.remove(SourceRange(BeforeTok.getLocation(),
434b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis                                 AfterTok.getLocation()));
435b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis    } else if (BeforeTok.is(tok::l_paren) && AfterTok.is(tok::comma)) {
436b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis      Pass.TA.remove(SourceRange(AttrLoc, AfterTok.getLocation()));
437b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis    } else {
438b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis      Pass.TA.remove(SourceRange(BeforeTok.getLocation(), AttrLoc));
439b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis    }
440b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis
441b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis    return true;
442b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis  }
443b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis
444b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis  return false;
445b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis}
446b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis
447e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidisvoid MigrationContext::traverse(TranslationUnitDecl *TU) {
448f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis  for (traverser_iterator
449f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis         I = traversers_begin(), E = traversers_end(); I != E; ++I)
450f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis    (*I)->traverseTU(*this);
451f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis
452e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis  ASTTransform(*this).TraverseDecl(TU);
453e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis}
454e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis
455e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis//===----------------------------------------------------------------------===//
4568f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall// getAllTransformations.
4578f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall//===----------------------------------------------------------------------===//
4588f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall
459e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidisstatic void traverseAST(MigrationPass &pass) {
460e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis  MigrationContext MigrateCtx(pass);
461e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis
462e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis  if (pass.isGCMigration()) {
463e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis    MigrateCtx.addTraverser(new GCCollectableCallsTraverser);
464f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis    MigrateCtx.addTraverser(new GCAttrsTraverser());
465e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis  }
466b0d5db1b7cac1a0680877c17fe92c6d64cf1c730Argyrios Kyrtzidis  MigrateCtx.addTraverser(new PropertyRewriteTraverser());
467e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis
468e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis  MigrateCtx.traverse(pass.Ctx.getTranslationUnitDecl());
469e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis}
470e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis
4718f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCallstatic void independentTransforms(MigrationPass &pass) {
4728f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  rewriteAutoreleasePool(pass);
473e7ef8556f4ee3012a0479308c993af0fbee448dfArgyrios Kyrtzidis  removeRetainReleaseDeallocFinalize(pass);
4747196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  rewriteUnusedInitDelegate(pass);
475e7ef8556f4ee3012a0479308c993af0fbee448dfArgyrios Kyrtzidis  removeZeroOutPropsInDeallocFinalize(pass);
4768f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  makeAssignARCSafe(pass);
4777196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis  rewriteUnbridgedCasts(pass);
4788f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  rewriteBlockObjCVariable(pass);
479fd10398c10ffdcbdeb1e3e299c74d70e689f503cArgyrios Kyrtzidis  checkAPIUses(pass);
480e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis  traverseAST(pass);
4818f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall}
4828f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall
483e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidisstd::vector<TransformFn> arcmt::getAllTransformations(
484e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis                                               LangOptions::GCMode OrigGCMode) {
4858f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  std::vector<TransformFn> transforms;
4868f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall
4878f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  transforms.push_back(independentTransforms);
488fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis  // This depends on previous transformations removing various expressions.
489e7ef8556f4ee3012a0479308c993af0fbee448dfArgyrios Kyrtzidis  transforms.push_back(removeEmptyStatementsAndDeallocFinalize);
4908f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall
4918f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  return transforms;
4928f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall}
493