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