Transforms.cpp revision 263d66718365aadc621c3feb9badedf46d787e0e
1c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)//===--- Tranforms.cpp - Tranformations to ARC mode -----------------------===//
2c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)//
3c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)//                     The LLVM Compiler Infrastructure
4c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)//
5c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// This file is distributed under the University of Illinois Open Source
6c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// License. See LICENSE.TXT for details.
7c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)//
8c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)//===----------------------------------------------------------------------===//
9ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
10c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "Transforms.h"
1190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "Internals.h"
1290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "clang/Sema/SemaDiagnostic.h"
1390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "clang/AST/RecursiveASTVisitor.h"
147dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "clang/AST/StmtVisitor.h"
1590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "clang/Analysis/DomainSpecific/CocoaConventions.h"
1690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "clang/Lex/Lexer.h"
1790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "clang/Basic/SourceManager.h"
1890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "llvm/ADT/StringSwitch.h"
197dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "llvm/ADT/DenseSet.h"
20868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include <map>
21a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch
2290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)using namespace clang;
23c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)using namespace arcmt;
24c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)using namespace trans;
25c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
26c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)ASTTraverser::~ASTTraverser() { }
27c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
28c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)//===----------------------------------------------------------------------===//
29c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Helpers.
30c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)//===----------------------------------------------------------------------===//
317dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
327dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch/// \brief True if the class is one that does not support weak.
337dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochstatic bool isClassInWeakBlacklist(ObjCInterfaceDecl *cls) {
3490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (!cls)
3590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return false;
3690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
37c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  bool inList = llvm::StringSwitch<bool>(cls->getName())
38c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 .Case("NSColorSpace", true)
39c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 .Case("NSFont", true)
40c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 .Case("NSFontPanel", true)
41c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 .Case("NSImage", true)
42c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 .Case("NSLazyBrowserCell", true)
43c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 .Case("NSWindow", true)
44c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 .Case("NSWindowController", true)
45c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 .Case("NSViewController", true)
46c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 .Case("NSMenuView", true)
47c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 .Case("NSPersistentUIWindowInfo", true)
48c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 .Case("NSTableCellView", true)
49b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                 .Case("NSATSTypeSetter", true)
50c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 .Case("NSATSGlyphStorage", true)
51c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 .Case("NSLineFragmentRenderingContext", true)
52c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 .Case("NSAttributeDictionary", true)
53c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 .Case("NSParagraphStyle", true)
54c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 .Case("NSTextTab", true)
55c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 .Case("NSSimpleHorizontalTypesetter", true)
56c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 .Case("_NSCachedAttributedString", true)
57c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 .Case("NSStringDrawingTextStorage", true)
587dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                 .Case("NSTextView", true)
597dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                 .Case("NSSubTextStorage", true)
607dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                 .Default(false);
617dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
62c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (inList)
63c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return true;
64c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
657dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  return isClassInWeakBlacklist(cls->getSuperClass());
667dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
677dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
6890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)bool trans::canApplyWeak(ASTContext &Ctx, QualType type,
6990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                         bool AllowOnUnknownClass) {
707dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!Ctx.getLangOptions().ObjCRuntimeHasWeak)
7190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return false;
7290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
73c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  QualType T = type;
74c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (T.isNull())
75c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return false;
76c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
77c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  while (const PointerType *ptr = T->getAs<PointerType>())
78c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    T = ptr->getPointeeType();
79c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (const ObjCObjectPointerType *ObjT = T->getAs<ObjCObjectPointerType>()) {
80c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    ObjCInterfaceDecl *Class = ObjT->getInterfaceDecl();
81c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (!AllowOnUnknownClass && (!Class || Class->getName() == "NSObject"))
82c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return false; // id/NSObject is not safe for weak.
83c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (!AllowOnUnknownClass && Class->isForwardDecl())
84c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return false; // forward classes are not verifiable, therefore not safe.
85c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (Class->isArcWeakrefUnavailable())
86c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return false;
87c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (isClassInWeakBlacklist(Class))
88c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return false;
89c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
90c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
91c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return true;
92c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
93c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
94c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)/// \brief 'Loc' is the end of a statement range. This returns the location
957dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch/// immediately after the semicolon following the statement.
967dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch/// If no semicolon is found or the location is inside a macro, the returned
977dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch/// source location will be invalid.
98c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)SourceLocation trans::findLocationAfterSemi(SourceLocation loc,
99c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                            ASTContext &Ctx) {
100c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  SourceLocation SemiLoc = findSemiAfterLocation(loc, Ctx);
101c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (SemiLoc.isInvalid())
102c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return SourceLocation();
103c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return SemiLoc.getLocWithOffset(1);
104c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
105868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
106868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)/// \brief \arg Loc is the end of a statement range. This returns the location
107c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)/// of the semicolon following the statement.
108c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)/// If no semicolon is found or the location is inside a macro, the returned
109c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)/// source location will be invalid.
110c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)SourceLocation trans::findSemiAfterLocation(SourceLocation loc,
111c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                            ASTContext &Ctx) {
112c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  SourceManager &SM = Ctx.getSourceManager();
113c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (loc.isMacroID()) {
114c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (!Lexer::isAtEndOfMacroExpansion(loc, SM, Ctx.getLangOptions()))
115c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return SourceLocation();
116c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    loc = SM.getExpansionRange(loc).second;
117c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
118c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  loc = Lexer::getLocForEndOfToken(loc, /*Offset=*/0, SM, Ctx.getLangOptions());
119c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
120868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Break down the source location.
121868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  std::pair<FileID, unsigned> locInfo = SM.getDecomposedLoc(loc);
122c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
123c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Try to load the file buffer.
124c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  bool invalidTemp = false;
125c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  StringRef file = SM.getBufferData(locInfo.first, &invalidTemp);
126c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (invalidTemp)
127c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return SourceLocation();
128c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
129c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const char *tokenBegin = file.data() + locInfo.second;
130c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
131c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Lex from the start of the given location.
132c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  Lexer lexer(SM.getLocForStartOfFile(locInfo.first),
133c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)              Ctx.getLangOptions(),
134c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)              file.begin(), tokenBegin, file.end());
135c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  Token tok;
136c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  lexer.LexFromRawLexer(tok);
137c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (tok.isNot(tok::semi))
138c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return SourceLocation();
139c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
140c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return tok.getLocation();
141c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
142c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
143c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool trans::hasSideEffects(Expr *E, ASTContext &Ctx) {
144c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!E || !E->HasSideEffects(Ctx))
145c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return false;
146c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
147868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  E = E->IgnoreParenCasts();
148c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ObjCMessageExpr *ME = dyn_cast<ObjCMessageExpr>(E);
149c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!ME)
150868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return true;
151868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  switch (ME->getMethodFamily()) {
152c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  case OMF_autorelease:
153c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  case OMF_dealloc:
154c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  case OMF_release:
155868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  case OMF_retain:
156868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    switch (ME->getReceiverKind()) {
157c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case ObjCMessageExpr::SuperInstance:
158c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return false;
159c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case ObjCMessageExpr::Instance:
160c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return hasSideEffects(ME->getInstanceReceiver(), Ctx);
161868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    default:
162c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      break;
163c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
164c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    break;
165c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  default:
166c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    break;
167c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
168c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
169c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return true;
170c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
171c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
172c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool trans::isGlobalVar(Expr *E) {
173b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  E = E->IgnoreParenCasts();
174c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E))
175c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return DRE->getDecl()->getDeclContext()->isFileContext() &&
176c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)           DRE->getDecl()->getLinkage() == ExternalLinkage;
177c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (ConditionalOperator *condOp = dyn_cast<ConditionalOperator>(E))
178c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return isGlobalVar(condOp->getTrueExpr()) &&
179c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)           isGlobalVar(condOp->getFalseExpr());
180c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
181c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return false;
182c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
183c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
184c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)StringRef trans::getNilString(ASTContext &Ctx) {
185c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (Ctx.Idents.get("nil").hasMacroDefinition())
186c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return "nil";
187c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  else
188a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    return "0";
189a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch}
190a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch
191a3f7b4e666c476898878fa745f637129375cd889Ben Murdochnamespace {
192c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
193c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)class ReferenceClear : public RecursiveASTVisitor<ReferenceClear> {
194c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ExprSet &Refs;
195c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)public:
196c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ReferenceClear(ExprSet &refs) : Refs(refs) { }
197a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  bool VisitDeclRefExpr(DeclRefExpr *E) { Refs.erase(E); return true; }
198c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  bool VisitBlockDeclRefExpr(BlockDeclRefExpr *E) { Refs.erase(E); return true; }
199c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)};
200c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
201c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)class ReferenceCollector : public RecursiveASTVisitor<ReferenceCollector> {
202c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ValueDecl *Dcl;
203a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  ExprSet &Refs;
204a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch
205a3f7b4e666c476898878fa745f637129375cd889Ben Murdochpublic:
206a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  ReferenceCollector(ValueDecl *D, ExprSet &refs)
207a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    : Dcl(D), Refs(refs) { }
208a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch
209c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  bool VisitDeclRefExpr(DeclRefExpr *E) {
210c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (E->getDecl() == Dcl)
211c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      Refs.insert(E);
212a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    return true;
213c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
214c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
215b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  bool VisitBlockDeclRefExpr(BlockDeclRefExpr *E) {
216b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    if (E->getDecl() == Dcl)
217c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      Refs.insert(E);
218c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return true;
219a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  }
220a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch};
221a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch
222a3f7b4e666c476898878fa745f637129375cd889Ben Murdochclass RemovablesCollector : public RecursiveASTVisitor<RemovablesCollector> {
223a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  ExprSet &Removables;
224a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch
225a3f7b4e666c476898878fa745f637129375cd889Ben Murdochpublic:
226a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  RemovablesCollector(ExprSet &removables)
227c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  : Removables(removables) { }
228c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
229a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  bool shouldWalkTypesOfTypeLocs() const { return false; }
230c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
231c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  bool TraverseStmtExpr(StmtExpr *E) {
232c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    CompoundStmt *S = E->getSubStmt();
233c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    for (CompoundStmt::body_iterator
234c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        I = S->body_begin(), E = S->body_end(); I != E; ++I) {
235a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch      if (I != E - 1)
236c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        mark(*I);
237c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      TraverseStmt(*I);
238c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
239c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return true;
240c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
241c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
242a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  bool VisitCompoundStmt(CompoundStmt *S) {
243c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    for (CompoundStmt::body_iterator
244c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        I = S->body_begin(), E = S->body_end(); I != E; ++I)
245c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      mark(*I);
246c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return true;
247c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
248c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
249c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  bool VisitIfStmt(IfStmt *S) {
250c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    mark(S->getThen());
251c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    mark(S->getElse());
252c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return true;
253c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
254c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
255a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  bool VisitWhileStmt(WhileStmt *S) {
256c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    mark(S->getBody());
257c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return true;
258c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
259c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
260c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  bool VisitDoStmt(DoStmt *S) {
261c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    mark(S->getBody());
262c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return true;
263c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
264c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
265c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  bool VisitForStmt(ForStmt *S) {
266c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    mark(S->getInit());
267c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    mark(S->getInc());
268c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    mark(S->getBody());
269c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return true;
270a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  }
271c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
272c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)private:
273c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  void mark(Stmt *S) {
274c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (!S) return;
275c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
276c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    while (LabelStmt *Label = dyn_cast<LabelStmt>(S))
277c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      S = Label->getSubStmt();
278c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    S = S->IgnoreImplicit();
279c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (Expr *E = dyn_cast<Expr>(S))
280c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      Removables.insert(E);
281c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
282c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)};
283a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch
284c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} // end anonymous namespace
285c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
286c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void trans::clearRefsIn(Stmt *S, ExprSet &refs) {
287c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ReferenceClear(refs).TraverseStmt(S);
288c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
289c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
290c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void trans::collectRefs(ValueDecl *D, Stmt *S, ExprSet &refs) {
291c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ReferenceCollector(D, refs).TraverseStmt(S);
292c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
293c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
294c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void trans::collectRemovables(Stmt *S, ExprSet &exprs) {
295c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  RemovablesCollector(exprs).TraverseStmt(S);
296c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
297a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch
298c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)//===----------------------------------------------------------------------===//
299c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// MigrationContext
300c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)//===----------------------------------------------------------------------===//
301a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch
302c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace {
303c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
304c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)class ASTTransform : public RecursiveASTVisitor<ASTTransform> {
305c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  MigrationContext &MigrateCtx;
306c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  typedef RecursiveASTVisitor<ASTTransform> base;
307c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
308a3f7b4e666c476898878fa745f637129375cd889Ben Murdochpublic:
309a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  ASTTransform(MigrationContext &MigrateCtx) : MigrateCtx(MigrateCtx) { }
310a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch
311a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  bool shouldWalkTypesOfTypeLocs() const { return false; }
312a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch
313a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  bool TraverseObjCImplementationDecl(ObjCImplementationDecl *D) {
314a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    ObjCImplementationContext ImplCtx(MigrateCtx, D);
315a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    for (MigrationContext::traverser_iterator
316a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch           I = MigrateCtx.traversers_begin(),
317a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch           E = MigrateCtx.traversers_end(); I != E; ++I)
318a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch      (*I)->traverseObjCImplementation(ImplCtx);
319a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch
320a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    return base::TraverseObjCImplementationDecl(D);
321a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  }
322c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
323  bool TraverseStmt(Stmt *rootS) {
324    if (!rootS)
325      return true;
326
327    BodyContext BodyCtx(MigrateCtx, rootS);
328    for (MigrationContext::traverser_iterator
329           I = MigrateCtx.traversers_begin(),
330           E = MigrateCtx.traversers_end(); I != E; ++I)
331      (*I)->traverseBody(BodyCtx);
332
333    return true;
334  }
335};
336
337}
338
339MigrationContext::~MigrationContext() {
340  for (traverser_iterator
341         I = traversers_begin(), E = traversers_end(); I != E; ++I)
342    delete *I;
343}
344
345bool MigrationContext::isGCOwnedNonObjC(QualType T) {
346  while (!T.isNull()) {
347    if (const AttributedType *AttrT = T->getAs<AttributedType>()) {
348      if (AttrT->getAttrKind() == AttributedType::attr_objc_ownership)
349        return !AttrT->getModifiedType()->isObjCRetainableType();
350    }
351
352    if (T->isArrayType())
353      T = Pass.Ctx.getBaseElementType(T);
354    else if (const PointerType *PT = T->getAs<PointerType>())
355      T = PT->getPointeeType();
356    else if (const ReferenceType *RT = T->getAs<ReferenceType>())
357      T = RT->getPointeeType();
358    else
359      break;
360  }
361
362  return false;
363}
364
365bool MigrationContext::rewritePropertyAttribute(StringRef fromAttr,
366                                                StringRef toAttr,
367                                                SourceLocation atLoc) {
368  if (atLoc.isMacroID())
369    return false;
370
371  SourceManager &SM = Pass.Ctx.getSourceManager();
372
373  // Break down the source location.
374  std::pair<FileID, unsigned> locInfo = SM.getDecomposedLoc(atLoc);
375
376  // Try to load the file buffer.
377  bool invalidTemp = false;
378  StringRef file = SM.getBufferData(locInfo.first, &invalidTemp);
379  if (invalidTemp)
380    return false;
381
382  const char *tokenBegin = file.data() + locInfo.second;
383
384  // Lex from the start of the given location.
385  Lexer lexer(SM.getLocForStartOfFile(locInfo.first),
386              Pass.Ctx.getLangOptions(),
387              file.begin(), tokenBegin, file.end());
388  Token tok;
389  lexer.LexFromRawLexer(tok);
390  if (tok.isNot(tok::at)) return false;
391  lexer.LexFromRawLexer(tok);
392  if (tok.isNot(tok::raw_identifier)) return false;
393  if (StringRef(tok.getRawIdentifierData(), tok.getLength())
394        != "property")
395    return false;
396  lexer.LexFromRawLexer(tok);
397  if (tok.isNot(tok::l_paren)) return false;
398
399  Token BeforeTok = tok;
400  Token AfterTok;
401  AfterTok.startToken();
402  SourceLocation AttrLoc;
403
404  lexer.LexFromRawLexer(tok);
405  if (tok.is(tok::r_paren))
406    return false;
407
408  while (1) {
409    if (tok.isNot(tok::raw_identifier)) return false;
410    StringRef ident(tok.getRawIdentifierData(), tok.getLength());
411    if (ident == fromAttr) {
412      if (!toAttr.empty()) {
413        Pass.TA.replaceText(tok.getLocation(), fromAttr, toAttr);
414        return true;
415      }
416      // We want to remove the attribute.
417      AttrLoc = tok.getLocation();
418    }
419
420    do {
421      lexer.LexFromRawLexer(tok);
422      if (AttrLoc.isValid() && AfterTok.is(tok::unknown))
423        AfterTok = tok;
424    } while (tok.isNot(tok::comma) && tok.isNot(tok::r_paren));
425    if (tok.is(tok::r_paren))
426      break;
427    if (AttrLoc.isInvalid())
428      BeforeTok = tok;
429    lexer.LexFromRawLexer(tok);
430  }
431
432  if (toAttr.empty() && AttrLoc.isValid() && AfterTok.isNot(tok::unknown)) {
433    // We want to remove the attribute.
434    if (BeforeTok.is(tok::l_paren) && AfterTok.is(tok::r_paren)) {
435      Pass.TA.remove(SourceRange(BeforeTok.getLocation(),
436                                 AfterTok.getLocation()));
437    } else if (BeforeTok.is(tok::l_paren) && AfterTok.is(tok::comma)) {
438      Pass.TA.remove(SourceRange(AttrLoc, AfterTok.getLocation()));
439    } else {
440      Pass.TA.remove(SourceRange(BeforeTok.getLocation(), AttrLoc));
441    }
442
443    return true;
444  }
445
446  return false;
447}
448
449void MigrationContext::traverse(TranslationUnitDecl *TU) {
450  for (traverser_iterator
451         I = traversers_begin(), E = traversers_end(); I != E; ++I)
452    (*I)->traverseTU(*this);
453
454  ASTTransform(*this).TraverseDecl(TU);
455}
456
457//===----------------------------------------------------------------------===//
458// getAllTransformations.
459//===----------------------------------------------------------------------===//
460
461static void traverseAST(MigrationPass &pass) {
462  MigrationContext MigrateCtx(pass);
463
464  if (pass.isGCMigration()) {
465    MigrateCtx.addTraverser(new GCCollectableCallsTraverser);
466    MigrateCtx.addTraverser(new GCAttrsTraverser());
467  }
468  MigrateCtx.addTraverser(new PropertyRewriteTraverser());
469
470  MigrateCtx.traverse(pass.Ctx.getTranslationUnitDecl());
471}
472
473static void independentTransforms(MigrationPass &pass) {
474  rewriteAutoreleasePool(pass);
475  removeRetainReleaseDeallocFinalize(pass);
476  rewriteUnusedInitDelegate(pass);
477  removeZeroOutPropsInDeallocFinalize(pass);
478  makeAssignARCSafe(pass);
479  rewriteUnbridgedCasts(pass);
480  rewriteBlockObjCVariable(pass);
481  checkAPIUses(pass);
482  traverseAST(pass);
483}
484
485std::vector<TransformFn> arcmt::getAllTransformations(
486                                               LangOptions::GCMode OrigGCMode) {
487  std::vector<TransformFn> transforms;
488
489  transforms.push_back(independentTransforms);
490  // This depends on previous transformations removing various expressions.
491  transforms.push_back(removeEmptyStatementsAndDeallocFinalize);
492
493  return transforms;
494}
495