ObjCMT.cpp revision 7556853c60f3e2a3f43864d8ebe74ba5ac11e68e
130660a898545416f0fea2d717f16f75640001e38Ted Kremenek//===--- ObjCMT.cpp - ObjC Migrate Tool -----------------------------------===// 230660a898545416f0fea2d717f16f75640001e38Ted Kremenek// 330660a898545416f0fea2d717f16f75640001e38Ted Kremenek// The LLVM Compiler Infrastructure 430660a898545416f0fea2d717f16f75640001e38Ted Kremenek// 530660a898545416f0fea2d717f16f75640001e38Ted Kremenek// This file is distributed under the University of Illinois Open Source 630660a898545416f0fea2d717f16f75640001e38Ted Kremenek// License. See LICENSE.TXT for details. 730660a898545416f0fea2d717f16f75640001e38Ted Kremenek// 830660a898545416f0fea2d717f16f75640001e38Ted Kremenek//===----------------------------------------------------------------------===// 930660a898545416f0fea2d717f16f75640001e38Ted Kremenek 1030660a898545416f0fea2d717f16f75640001e38Ted Kremenek#include "clang/ARCMigrate/ARCMTActions.h" 1155fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/AST/ASTConsumer.h" 12471c8b49982d1132f30b0b0da27fef94fd6e4f67Benjamin Kramer#include "clang/AST/ASTContext.h" 1330660a898545416f0fea2d717f16f75640001e38Ted Kremenek#include "clang/AST/NSAPI.h" 14a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis#include "clang/AST/ParentMap.h" 1555fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/AST/RecursiveASTVisitor.h" 1655fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/Basic/FileManager.h" 1730660a898545416f0fea2d717f16f75640001e38Ted Kremenek#include "clang/Edit/Commit.h" 1855fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/Edit/EditedSource.h" 1930660a898545416f0fea2d717f16f75640001e38Ted Kremenek#include "clang/Edit/EditsReceiver.h" 2055fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/Edit/Rewriters.h" 2155fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/Frontend/CompilerInstance.h" 2255fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/Frontend/MultiplexConsumer.h" 2337ed12720a35b7bfa1c4de73ad6f1c6c1c88ee17Argyrios Kyrtzidis#include "clang/Lex/PPConditionalDirectiveRecord.h" 2455fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/Lex/Preprocessor.h" 2555fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/Rewrite/Core/Rewriter.h" 2630660a898545416f0fea2d717f16f75640001e38Ted Kremenek#include "llvm/ADT/SmallString.h" 2730660a898545416f0fea2d717f16f75640001e38Ted Kremenek 2830660a898545416f0fea2d717f16f75640001e38Ted Kremenekusing namespace clang; 2930660a898545416f0fea2d717f16f75640001e38Ted Kremenekusing namespace arcmt; 3030660a898545416f0fea2d717f16f75640001e38Ted Kremenek 3130660a898545416f0fea2d717f16f75640001e38Ted Kremeneknamespace { 3230660a898545416f0fea2d717f16f75640001e38Ted Kremenek 3330660a898545416f0fea2d717f16f75640001e38Ted Kremenekclass ObjCMigrateASTConsumer : public ASTConsumer { 3430660a898545416f0fea2d717f16f75640001e38Ted Kremenek void migrateDecl(Decl *D); 35baf15574ebe70871b4682cdd5a87028bad1c9f6fFariborz Jahanian void migrateObjCInterfaceDecl(ASTContext &Ctx, ObjCInterfaceDecl *D); 367556853c60f3e2a3f43864d8ebe74ba5ac11e68eFariborz Jahanian void migrateProtocolConformance(ASTContext &Ctx, 377556853c60f3e2a3f43864d8ebe74ba5ac11e68eFariborz Jahanian const ObjCImplementationDecl *ImpDecl); 3830660a898545416f0fea2d717f16f75640001e38Ted Kremenek 3930660a898545416f0fea2d717f16f75640001e38Ted Kremenekpublic: 4030660a898545416f0fea2d717f16f75640001e38Ted Kremenek std::string MigrateDir; 4130660a898545416f0fea2d717f16f75640001e38Ted Kremenek bool MigrateLiterals; 4230660a898545416f0fea2d717f16f75640001e38Ted Kremenek bool MigrateSubscripting; 43d412999a3da6387dbfaf00f7647132082e94310eFariborz Jahanian bool MigrateProperty; 44cfa88f893915ceb8ae4ce2f17c46c24a4d67502fDmitri Gribenko OwningPtr<NSAPI> NSAPIObj; 45cfa88f893915ceb8ae4ce2f17c46c24a4d67502fDmitri Gribenko OwningPtr<edit::EditedSource> Editor; 4630660a898545416f0fea2d717f16f75640001e38Ted Kremenek FileRemapper &Remapper; 4730660a898545416f0fea2d717f16f75640001e38Ted Kremenek FileManager &FileMgr; 4837ed12720a35b7bfa1c4de73ad6f1c6c1c88ee17Argyrios Kyrtzidis const PPConditionalDirectiveRecord *PPRec; 49baf15574ebe70871b4682cdd5a87028bad1c9f6fFariborz Jahanian Preprocessor &PP; 5030660a898545416f0fea2d717f16f75640001e38Ted Kremenek bool IsOutputFile; 517556853c60f3e2a3f43864d8ebe74ba5ac11e68eFariborz Jahanian llvm::SmallPtrSet<ObjCProtocolDecl *, 32> ObjCProtocolDecls; 527556853c60f3e2a3f43864d8ebe74ba5ac11e68eFariborz Jahanian 5330660a898545416f0fea2d717f16f75640001e38Ted Kremenek ObjCMigrateASTConsumer(StringRef migrateDir, 5430660a898545416f0fea2d717f16f75640001e38Ted Kremenek bool migrateLiterals, 5530660a898545416f0fea2d717f16f75640001e38Ted Kremenek bool migrateSubscripting, 56d412999a3da6387dbfaf00f7647132082e94310eFariborz Jahanian bool migrateProperty, 5730660a898545416f0fea2d717f16f75640001e38Ted Kremenek FileRemapper &remapper, 5830660a898545416f0fea2d717f16f75640001e38Ted Kremenek FileManager &fileMgr, 5937ed12720a35b7bfa1c4de73ad6f1c6c1c88ee17Argyrios Kyrtzidis const PPConditionalDirectiveRecord *PPRec, 60baf15574ebe70871b4682cdd5a87028bad1c9f6fFariborz Jahanian Preprocessor &PP, 6130660a898545416f0fea2d717f16f75640001e38Ted Kremenek bool isOutputFile = false) 6230660a898545416f0fea2d717f16f75640001e38Ted Kremenek : MigrateDir(migrateDir), 6330660a898545416f0fea2d717f16f75640001e38Ted Kremenek MigrateLiterals(migrateLiterals), 6430660a898545416f0fea2d717f16f75640001e38Ted Kremenek MigrateSubscripting(migrateSubscripting), 65d412999a3da6387dbfaf00f7647132082e94310eFariborz Jahanian MigrateProperty(migrateProperty), 66baf15574ebe70871b4682cdd5a87028bad1c9f6fFariborz Jahanian Remapper(remapper), FileMgr(fileMgr), PPRec(PPRec), PP(PP), 6730660a898545416f0fea2d717f16f75640001e38Ted Kremenek IsOutputFile(isOutputFile) { } 6830660a898545416f0fea2d717f16f75640001e38Ted Kremenek 6930660a898545416f0fea2d717f16f75640001e38Ted Kremenekprotected: 7030660a898545416f0fea2d717f16f75640001e38Ted Kremenek virtual void Initialize(ASTContext &Context) { 7130660a898545416f0fea2d717f16f75640001e38Ted Kremenek NSAPIObj.reset(new NSAPI(Context)); 7230660a898545416f0fea2d717f16f75640001e38Ted Kremenek Editor.reset(new edit::EditedSource(Context.getSourceManager(), 734e4d08403ca5cfd4d558fa2936215d3a4e5a528dDavid Blaikie Context.getLangOpts(), 7430660a898545416f0fea2d717f16f75640001e38Ted Kremenek PPRec)); 7530660a898545416f0fea2d717f16f75640001e38Ted Kremenek } 7630660a898545416f0fea2d717f16f75640001e38Ted Kremenek 7730660a898545416f0fea2d717f16f75640001e38Ted Kremenek virtual bool HandleTopLevelDecl(DeclGroupRef DG) { 7830660a898545416f0fea2d717f16f75640001e38Ted Kremenek for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I) 7930660a898545416f0fea2d717f16f75640001e38Ted Kremenek migrateDecl(*I); 8030660a898545416f0fea2d717f16f75640001e38Ted Kremenek return true; 8130660a898545416f0fea2d717f16f75640001e38Ted Kremenek } 8230660a898545416f0fea2d717f16f75640001e38Ted Kremenek virtual void HandleInterestingDecl(DeclGroupRef DG) { 8330660a898545416f0fea2d717f16f75640001e38Ted Kremenek // Ignore decls from the PCH. 8430660a898545416f0fea2d717f16f75640001e38Ted Kremenek } 8530660a898545416f0fea2d717f16f75640001e38Ted Kremenek virtual void HandleTopLevelDeclInObjCContainer(DeclGroupRef DG) { 8630660a898545416f0fea2d717f16f75640001e38Ted Kremenek ObjCMigrateASTConsumer::HandleTopLevelDecl(DG); 8730660a898545416f0fea2d717f16f75640001e38Ted Kremenek } 8830660a898545416f0fea2d717f16f75640001e38Ted Kremenek 8930660a898545416f0fea2d717f16f75640001e38Ted Kremenek virtual void HandleTranslationUnit(ASTContext &Ctx); 9030660a898545416f0fea2d717f16f75640001e38Ted Kremenek}; 9130660a898545416f0fea2d717f16f75640001e38Ted Kremenek 9230660a898545416f0fea2d717f16f75640001e38Ted Kremenek} 9330660a898545416f0fea2d717f16f75640001e38Ted Kremenek 9430660a898545416f0fea2d717f16f75640001e38Ted KremenekObjCMigrateAction::ObjCMigrateAction(FrontendAction *WrappedAction, 9530660a898545416f0fea2d717f16f75640001e38Ted Kremenek StringRef migrateDir, 9630660a898545416f0fea2d717f16f75640001e38Ted Kremenek bool migrateLiterals, 97d412999a3da6387dbfaf00f7647132082e94310eFariborz Jahanian bool migrateSubscripting, 98d412999a3da6387dbfaf00f7647132082e94310eFariborz Jahanian bool migrateProperty) 9930660a898545416f0fea2d717f16f75640001e38Ted Kremenek : WrapperFrontendAction(WrappedAction), MigrateDir(migrateDir), 10030660a898545416f0fea2d717f16f75640001e38Ted Kremenek MigrateLiterals(migrateLiterals), MigrateSubscripting(migrateSubscripting), 101d412999a3da6387dbfaf00f7647132082e94310eFariborz Jahanian MigrateProperty(migrateProperty), 10230660a898545416f0fea2d717f16f75640001e38Ted Kremenek CompInst(0) { 10330660a898545416f0fea2d717f16f75640001e38Ted Kremenek if (MigrateDir.empty()) 10430660a898545416f0fea2d717f16f75640001e38Ted Kremenek MigrateDir = "."; // user current directory if none is given. 10530660a898545416f0fea2d717f16f75640001e38Ted Kremenek} 10630660a898545416f0fea2d717f16f75640001e38Ted Kremenek 10730660a898545416f0fea2d717f16f75640001e38Ted KremenekASTConsumer *ObjCMigrateAction::CreateASTConsumer(CompilerInstance &CI, 10830660a898545416f0fea2d717f16f75640001e38Ted Kremenek StringRef InFile) { 10937ed12720a35b7bfa1c4de73ad6f1c6c1c88ee17Argyrios Kyrtzidis PPConditionalDirectiveRecord * 11037ed12720a35b7bfa1c4de73ad6f1c6c1c88ee17Argyrios Kyrtzidis PPRec = new PPConditionalDirectiveRecord(CompInst->getSourceManager()); 11137ed12720a35b7bfa1c4de73ad6f1c6c1c88ee17Argyrios Kyrtzidis CompInst->getPreprocessor().addPPCallbacks(PPRec); 11230660a898545416f0fea2d717f16f75640001e38Ted Kremenek ASTConsumer * 11330660a898545416f0fea2d717f16f75640001e38Ted Kremenek WrappedConsumer = WrapperFrontendAction::CreateASTConsumer(CI, InFile); 11430660a898545416f0fea2d717f16f75640001e38Ted Kremenek ASTConsumer *MTConsumer = new ObjCMigrateASTConsumer(MigrateDir, 11530660a898545416f0fea2d717f16f75640001e38Ted Kremenek MigrateLiterals, 11630660a898545416f0fea2d717f16f75640001e38Ted Kremenek MigrateSubscripting, 117d412999a3da6387dbfaf00f7647132082e94310eFariborz Jahanian MigrateProperty, 11830660a898545416f0fea2d717f16f75640001e38Ted Kremenek Remapper, 11930660a898545416f0fea2d717f16f75640001e38Ted Kremenek CompInst->getFileManager(), 120baf15574ebe70871b4682cdd5a87028bad1c9f6fFariborz Jahanian PPRec, 121baf15574ebe70871b4682cdd5a87028bad1c9f6fFariborz Jahanian CompInst->getPreprocessor()); 12230660a898545416f0fea2d717f16f75640001e38Ted Kremenek ASTConsumer *Consumers[] = { MTConsumer, WrappedConsumer }; 12330660a898545416f0fea2d717f16f75640001e38Ted Kremenek return new MultiplexConsumer(Consumers); 12430660a898545416f0fea2d717f16f75640001e38Ted Kremenek} 12530660a898545416f0fea2d717f16f75640001e38Ted Kremenek 12630660a898545416f0fea2d717f16f75640001e38Ted Kremenekbool ObjCMigrateAction::BeginInvocation(CompilerInstance &CI) { 12730660a898545416f0fea2d717f16f75640001e38Ted Kremenek Remapper.initFromDisk(MigrateDir, CI.getDiagnostics(), 12830660a898545416f0fea2d717f16f75640001e38Ted Kremenek /*ignoreIfFilesChanges=*/true); 12930660a898545416f0fea2d717f16f75640001e38Ted Kremenek CompInst = &CI; 13030660a898545416f0fea2d717f16f75640001e38Ted Kremenek CI.getDiagnostics().setIgnoreAllWarnings(true); 13130660a898545416f0fea2d717f16f75640001e38Ted Kremenek return true; 13230660a898545416f0fea2d717f16f75640001e38Ted Kremenek} 13330660a898545416f0fea2d717f16f75640001e38Ted Kremenek 13430660a898545416f0fea2d717f16f75640001e38Ted Kremeneknamespace { 13530660a898545416f0fea2d717f16f75640001e38Ted Kremenekclass ObjCMigrator : public RecursiveASTVisitor<ObjCMigrator> { 13630660a898545416f0fea2d717f16f75640001e38Ted Kremenek ObjCMigrateASTConsumer &Consumer; 137a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis ParentMap &PMap; 13830660a898545416f0fea2d717f16f75640001e38Ted Kremenek 13930660a898545416f0fea2d717f16f75640001e38Ted Kremenekpublic: 140a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis ObjCMigrator(ObjCMigrateASTConsumer &consumer, ParentMap &PMap) 141a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis : Consumer(consumer), PMap(PMap) { } 14230660a898545416f0fea2d717f16f75640001e38Ted Kremenek 14330660a898545416f0fea2d717f16f75640001e38Ted Kremenek bool shouldVisitTemplateInstantiations() const { return false; } 14430660a898545416f0fea2d717f16f75640001e38Ted Kremenek bool shouldWalkTypesOfTypeLocs() const { return false; } 14530660a898545416f0fea2d717f16f75640001e38Ted Kremenek 14630660a898545416f0fea2d717f16f75640001e38Ted Kremenek bool VisitObjCMessageExpr(ObjCMessageExpr *E) { 14730660a898545416f0fea2d717f16f75640001e38Ted Kremenek if (Consumer.MigrateLiterals) { 14830660a898545416f0fea2d717f16f75640001e38Ted Kremenek edit::Commit commit(*Consumer.Editor); 149a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis edit::rewriteToObjCLiteralSyntax(E, *Consumer.NSAPIObj, commit, &PMap); 15030660a898545416f0fea2d717f16f75640001e38Ted Kremenek Consumer.Editor->commit(commit); 15130660a898545416f0fea2d717f16f75640001e38Ted Kremenek } 15230660a898545416f0fea2d717f16f75640001e38Ted Kremenek 15330660a898545416f0fea2d717f16f75640001e38Ted Kremenek if (Consumer.MigrateSubscripting) { 15430660a898545416f0fea2d717f16f75640001e38Ted Kremenek edit::Commit commit(*Consumer.Editor); 15530660a898545416f0fea2d717f16f75640001e38Ted Kremenek edit::rewriteToObjCSubscriptSyntax(E, *Consumer.NSAPIObj, commit); 15630660a898545416f0fea2d717f16f75640001e38Ted Kremenek Consumer.Editor->commit(commit); 15730660a898545416f0fea2d717f16f75640001e38Ted Kremenek } 15830660a898545416f0fea2d717f16f75640001e38Ted Kremenek 15930660a898545416f0fea2d717f16f75640001e38Ted Kremenek return true; 16030660a898545416f0fea2d717f16f75640001e38Ted Kremenek } 16130660a898545416f0fea2d717f16f75640001e38Ted Kremenek 16230660a898545416f0fea2d717f16f75640001e38Ted Kremenek bool TraverseObjCMessageExpr(ObjCMessageExpr *E) { 16330660a898545416f0fea2d717f16f75640001e38Ted Kremenek // Do depth first; we want to rewrite the subexpressions first so that if 16430660a898545416f0fea2d717f16f75640001e38Ted Kremenek // we have to move expressions we will move them already rewritten. 16530660a898545416f0fea2d717f16f75640001e38Ted Kremenek for (Stmt::child_range range = E->children(); range; ++range) 16630660a898545416f0fea2d717f16f75640001e38Ted Kremenek if (!TraverseStmt(*range)) 16730660a898545416f0fea2d717f16f75640001e38Ted Kremenek return false; 16830660a898545416f0fea2d717f16f75640001e38Ted Kremenek 16930660a898545416f0fea2d717f16f75640001e38Ted Kremenek return WalkUpFromObjCMessageExpr(E); 17030660a898545416f0fea2d717f16f75640001e38Ted Kremenek } 17130660a898545416f0fea2d717f16f75640001e38Ted Kremenek}; 172a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis 173a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidisclass BodyMigrator : public RecursiveASTVisitor<BodyMigrator> { 174a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis ObjCMigrateASTConsumer &Consumer; 175a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis OwningPtr<ParentMap> PMap; 176a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis 177a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidispublic: 178a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis BodyMigrator(ObjCMigrateASTConsumer &consumer) : Consumer(consumer) { } 179a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis 180a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis bool shouldVisitTemplateInstantiations() const { return false; } 181a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis bool shouldWalkTypesOfTypeLocs() const { return false; } 182a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis 183a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis bool TraverseStmt(Stmt *S) { 184a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis PMap.reset(new ParentMap(S)); 185a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis ObjCMigrator(Consumer, *PMap).TraverseStmt(S); 186a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis return true; 187a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis } 188a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis}; 18930660a898545416f0fea2d717f16f75640001e38Ted Kremenek} 19030660a898545416f0fea2d717f16f75640001e38Ted Kremenek 19130660a898545416f0fea2d717f16f75640001e38Ted Kremenekvoid ObjCMigrateASTConsumer::migrateDecl(Decl *D) { 19230660a898545416f0fea2d717f16f75640001e38Ted Kremenek if (!D) 19330660a898545416f0fea2d717f16f75640001e38Ted Kremenek return; 19430660a898545416f0fea2d717f16f75640001e38Ted Kremenek if (isa<ObjCMethodDecl>(D)) 19530660a898545416f0fea2d717f16f75640001e38Ted Kremenek return; // Wait for the ObjC container declaration. 19630660a898545416f0fea2d717f16f75640001e38Ted Kremenek 197a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis BodyMigrator(*this).TraverseDecl(D); 19830660a898545416f0fea2d717f16f75640001e38Ted Kremenek} 19930660a898545416f0fea2d717f16f75640001e38Ted Kremenek 200baf15574ebe70871b4682cdd5a87028bad1c9f6fFariborz Jahanianvoid ObjCMigrateASTConsumer::migrateObjCInterfaceDecl(ASTContext &Ctx, 201baf15574ebe70871b4682cdd5a87028bad1c9f6fFariborz Jahanian ObjCInterfaceDecl *D) { 202baf15574ebe70871b4682cdd5a87028bad1c9f6fFariborz Jahanian for (ObjCContainerDecl::method_iterator M = D->meth_begin(), MEnd = D->meth_end(); 203baf15574ebe70871b4682cdd5a87028bad1c9f6fFariborz Jahanian M != MEnd; ++M) { 204baf15574ebe70871b4682cdd5a87028bad1c9f6fFariborz Jahanian ObjCMethodDecl *Method = (*M); 205dca7289799517c3eee1765a174984f2ecffad0f1Fariborz Jahanian if (Method->isPropertyAccessor() || Method->param_size() != 0) 206baf15574ebe70871b4682cdd5a87028bad1c9f6fFariborz Jahanian continue; 207baf15574ebe70871b4682cdd5a87028bad1c9f6fFariborz Jahanian // Is this method candidate to be a getter? 208dca7289799517c3eee1765a174984f2ecffad0f1Fariborz Jahanian QualType GRT = Method->getResultType(); 209dca7289799517c3eee1765a174984f2ecffad0f1Fariborz Jahanian if (GRT->isVoidType()) 210dca7289799517c3eee1765a174984f2ecffad0f1Fariborz Jahanian continue; 2112a4ebcfe8b5920ca35924359135f3c5ddca7b171Fariborz Jahanian // FIXME. Don't know what todo with attributes, skip for now. 2122a4ebcfe8b5920ca35924359135f3c5ddca7b171Fariborz Jahanian if (Method->hasAttrs()) 2132a4ebcfe8b5920ca35924359135f3c5ddca7b171Fariborz Jahanian continue; 2142a4ebcfe8b5920ca35924359135f3c5ddca7b171Fariborz Jahanian 215dca7289799517c3eee1765a174984f2ecffad0f1Fariborz Jahanian Selector GetterSelector = Method->getSelector(); 216dca7289799517c3eee1765a174984f2ecffad0f1Fariborz Jahanian IdentifierInfo *getterName = GetterSelector.getIdentifierInfoForSlot(0); 217dca7289799517c3eee1765a174984f2ecffad0f1Fariborz Jahanian Selector SetterSelector = 218dca7289799517c3eee1765a174984f2ecffad0f1Fariborz Jahanian SelectorTable::constructSetterSelector(PP.getIdentifierTable(), 219dca7289799517c3eee1765a174984f2ecffad0f1Fariborz Jahanian PP.getSelectorTable(), 220dca7289799517c3eee1765a174984f2ecffad0f1Fariborz Jahanian getterName); 221dca7289799517c3eee1765a174984f2ecffad0f1Fariborz Jahanian if (ObjCMethodDecl *SetterMethod = D->lookupMethod(SetterSelector, true)) { 222dca7289799517c3eee1765a174984f2ecffad0f1Fariborz Jahanian // Is this a valid setter, matching the target getter? 223dca7289799517c3eee1765a174984f2ecffad0f1Fariborz Jahanian QualType SRT = SetterMethod->getResultType(); 224dca7289799517c3eee1765a174984f2ecffad0f1Fariborz Jahanian if (!SRT->isVoidType()) 225dca7289799517c3eee1765a174984f2ecffad0f1Fariborz Jahanian continue; 226dca7289799517c3eee1765a174984f2ecffad0f1Fariborz Jahanian const ParmVarDecl *argDecl = *SetterMethod->param_begin(); 22752477fb1b86f99a2a8c77e1523d4f186490c28e9Fariborz Jahanian QualType ArgType = argDecl->getType(); 2282a4ebcfe8b5920ca35924359135f3c5ddca7b171Fariborz Jahanian if (!Ctx.hasSameUnqualifiedType(ArgType, GRT) || 2292a4ebcfe8b5920ca35924359135f3c5ddca7b171Fariborz Jahanian SetterMethod->hasAttrs()) 23052477fb1b86f99a2a8c77e1523d4f186490c28e9Fariborz Jahanian continue; 231afcb16f9cff8d5ccd57a6386d65ddc055368d0bcFariborz Jahanian edit::Commit commit(*Editor); 232afcb16f9cff8d5ccd57a6386d65ddc055368d0bcFariborz Jahanian edit::rewriteToObjCProperty(Method, SetterMethod, *NSAPIObj, commit); 233afcb16f9cff8d5ccd57a6386d65ddc055368d0bcFariborz Jahanian Editor->commit(commit); 234baf15574ebe70871b4682cdd5a87028bad1c9f6fFariborz Jahanian } 235baf15574ebe70871b4682cdd5a87028bad1c9f6fFariborz Jahanian } 236baf15574ebe70871b4682cdd5a87028bad1c9f6fFariborz Jahanian} 237baf15574ebe70871b4682cdd5a87028bad1c9f6fFariborz Jahanian 2387556853c60f3e2a3f43864d8ebe74ba5ac11e68eFariborz Jahanianvoid ObjCMigrateASTConsumer::migrateProtocolConformance(ASTContext &Ctx, 2397556853c60f3e2a3f43864d8ebe74ba5ac11e68eFariborz Jahanian const ObjCImplementationDecl *ImpDecl) { 2407556853c60f3e2a3f43864d8ebe74ba5ac11e68eFariborz Jahanian const ObjCInterfaceDecl *IDecl = ImpDecl->getClassInterface(); 2417556853c60f3e2a3f43864d8ebe74ba5ac11e68eFariborz Jahanian if (!IDecl || ObjCProtocolDecls.empty()) 2427556853c60f3e2a3f43864d8ebe74ba5ac11e68eFariborz Jahanian return; 2437556853c60f3e2a3f43864d8ebe74ba5ac11e68eFariborz Jahanian // Find all implicit conforming protocols for this class 2447556853c60f3e2a3f43864d8ebe74ba5ac11e68eFariborz Jahanian // and make them explicit. 2457556853c60f3e2a3f43864d8ebe74ba5ac11e68eFariborz Jahanian llvm::SmallPtrSet<ObjCProtocolDecl *, 8> ExplicitProtocols; 2467556853c60f3e2a3f43864d8ebe74ba5ac11e68eFariborz Jahanian Ctx.CollectInheritedProtocols(IDecl, ExplicitProtocols); 2477556853c60f3e2a3f43864d8ebe74ba5ac11e68eFariborz Jahanian llvm::SmallPtrSet<ObjCProtocolDecl *, 8> PotentialImplicitProtocols; 2487556853c60f3e2a3f43864d8ebe74ba5ac11e68eFariborz Jahanian 2497556853c60f3e2a3f43864d8ebe74ba5ac11e68eFariborz Jahanian for (llvm::SmallPtrSet<ObjCProtocolDecl*,32>::iterator I = 2507556853c60f3e2a3f43864d8ebe74ba5ac11e68eFariborz Jahanian ObjCProtocolDecls.begin(), 2517556853c60f3e2a3f43864d8ebe74ba5ac11e68eFariborz Jahanian E = ObjCProtocolDecls.end(); I != E; ++I) 2527556853c60f3e2a3f43864d8ebe74ba5ac11e68eFariborz Jahanian if (!ExplicitProtocols.count(*I)) 2537556853c60f3e2a3f43864d8ebe74ba5ac11e68eFariborz Jahanian PotentialImplicitProtocols.insert(*I); 2547556853c60f3e2a3f43864d8ebe74ba5ac11e68eFariborz Jahanian 2557556853c60f3e2a3f43864d8ebe74ba5ac11e68eFariborz Jahanian if (PotentialImplicitProtocols.empty()) 2567556853c60f3e2a3f43864d8ebe74ba5ac11e68eFariborz Jahanian return; 2577556853c60f3e2a3f43864d8ebe74ba5ac11e68eFariborz Jahanian} 2587556853c60f3e2a3f43864d8ebe74ba5ac11e68eFariborz Jahanian 25930660a898545416f0fea2d717f16f75640001e38Ted Kremeneknamespace { 26030660a898545416f0fea2d717f16f75640001e38Ted Kremenek 26130660a898545416f0fea2d717f16f75640001e38Ted Kremenekclass RewritesReceiver : public edit::EditsReceiver { 26230660a898545416f0fea2d717f16f75640001e38Ted Kremenek Rewriter &Rewrite; 26330660a898545416f0fea2d717f16f75640001e38Ted Kremenek 26430660a898545416f0fea2d717f16f75640001e38Ted Kremenekpublic: 26530660a898545416f0fea2d717f16f75640001e38Ted Kremenek RewritesReceiver(Rewriter &Rewrite) : Rewrite(Rewrite) { } 26630660a898545416f0fea2d717f16f75640001e38Ted Kremenek 26730660a898545416f0fea2d717f16f75640001e38Ted Kremenek virtual void insert(SourceLocation loc, StringRef text) { 26830660a898545416f0fea2d717f16f75640001e38Ted Kremenek Rewrite.InsertText(loc, text); 26930660a898545416f0fea2d717f16f75640001e38Ted Kremenek } 27030660a898545416f0fea2d717f16f75640001e38Ted Kremenek virtual void replace(CharSourceRange range, StringRef text) { 27130660a898545416f0fea2d717f16f75640001e38Ted Kremenek Rewrite.ReplaceText(range.getBegin(), Rewrite.getRangeSize(range), text); 27230660a898545416f0fea2d717f16f75640001e38Ted Kremenek } 27330660a898545416f0fea2d717f16f75640001e38Ted Kremenek}; 27430660a898545416f0fea2d717f16f75640001e38Ted Kremenek 27530660a898545416f0fea2d717f16f75640001e38Ted Kremenek} 27630660a898545416f0fea2d717f16f75640001e38Ted Kremenek 27730660a898545416f0fea2d717f16f75640001e38Ted Kremenekvoid ObjCMigrateASTConsumer::HandleTranslationUnit(ASTContext &Ctx) { 278baf15574ebe70871b4682cdd5a87028bad1c9f6fFariborz Jahanian 279baf15574ebe70871b4682cdd5a87028bad1c9f6fFariborz Jahanian TranslationUnitDecl *TU = Ctx.getTranslationUnitDecl(); 280d412999a3da6387dbfaf00f7647132082e94310eFariborz Jahanian if (MigrateProperty) 281d412999a3da6387dbfaf00f7647132082e94310eFariborz Jahanian for (DeclContext::decl_iterator D = TU->decls_begin(), DEnd = TU->decls_end(); 282d412999a3da6387dbfaf00f7647132082e94310eFariborz Jahanian D != DEnd; ++D) { 283d412999a3da6387dbfaf00f7647132082e94310eFariborz Jahanian if (ObjCInterfaceDecl *CDecl = dyn_cast<ObjCInterfaceDecl>(*D)) 284d412999a3da6387dbfaf00f7647132082e94310eFariborz Jahanian migrateObjCInterfaceDecl(Ctx, CDecl); 2857556853c60f3e2a3f43864d8ebe74ba5ac11e68eFariborz Jahanian else if (ObjCProtocolDecl *PDecl = dyn_cast<ObjCProtocolDecl>(*D)) 2867556853c60f3e2a3f43864d8ebe74ba5ac11e68eFariborz Jahanian ObjCProtocolDecls.insert(PDecl); 2877556853c60f3e2a3f43864d8ebe74ba5ac11e68eFariborz Jahanian else if (const ObjCImplementationDecl *ImpDecl = 2887556853c60f3e2a3f43864d8ebe74ba5ac11e68eFariborz Jahanian dyn_cast<ObjCImplementationDecl>(*D)) 2897556853c60f3e2a3f43864d8ebe74ba5ac11e68eFariborz Jahanian migrateProtocolConformance(Ctx, ImpDecl); 290d412999a3da6387dbfaf00f7647132082e94310eFariborz Jahanian } 291baf15574ebe70871b4682cdd5a87028bad1c9f6fFariborz Jahanian 2924e4d08403ca5cfd4d558fa2936215d3a4e5a528dDavid Blaikie Rewriter rewriter(Ctx.getSourceManager(), Ctx.getLangOpts()); 29330660a898545416f0fea2d717f16f75640001e38Ted Kremenek RewritesReceiver Rec(rewriter); 29430660a898545416f0fea2d717f16f75640001e38Ted Kremenek Editor->applyRewrites(Rec); 29530660a898545416f0fea2d717f16f75640001e38Ted Kremenek 29630660a898545416f0fea2d717f16f75640001e38Ted Kremenek for (Rewriter::buffer_iterator 29730660a898545416f0fea2d717f16f75640001e38Ted Kremenek I = rewriter.buffer_begin(), E = rewriter.buffer_end(); I != E; ++I) { 29830660a898545416f0fea2d717f16f75640001e38Ted Kremenek FileID FID = I->first; 29930660a898545416f0fea2d717f16f75640001e38Ted Kremenek RewriteBuffer &buf = I->second; 30030660a898545416f0fea2d717f16f75640001e38Ted Kremenek const FileEntry *file = Ctx.getSourceManager().getFileEntryForID(FID); 30130660a898545416f0fea2d717f16f75640001e38Ted Kremenek assert(file); 302cfa88f893915ceb8ae4ce2f17c46c24a4d67502fDmitri Gribenko SmallString<512> newText; 30330660a898545416f0fea2d717f16f75640001e38Ted Kremenek llvm::raw_svector_ostream vecOS(newText); 30430660a898545416f0fea2d717f16f75640001e38Ted Kremenek buf.write(vecOS); 30530660a898545416f0fea2d717f16f75640001e38Ted Kremenek vecOS.flush(); 30630660a898545416f0fea2d717f16f75640001e38Ted Kremenek llvm::MemoryBuffer *memBuf = llvm::MemoryBuffer::getMemBufferCopy( 30730660a898545416f0fea2d717f16f75640001e38Ted Kremenek StringRef(newText.data(), newText.size()), file->getName()); 308cfa88f893915ceb8ae4ce2f17c46c24a4d67502fDmitri Gribenko SmallString<64> filePath(file->getName()); 30930660a898545416f0fea2d717f16f75640001e38Ted Kremenek FileMgr.FixupRelativePath(filePath); 31030660a898545416f0fea2d717f16f75640001e38Ted Kremenek Remapper.remap(filePath.str(), memBuf); 31130660a898545416f0fea2d717f16f75640001e38Ted Kremenek } 31230660a898545416f0fea2d717f16f75640001e38Ted Kremenek 31330660a898545416f0fea2d717f16f75640001e38Ted Kremenek if (IsOutputFile) { 31430660a898545416f0fea2d717f16f75640001e38Ted Kremenek Remapper.flushToFile(MigrateDir, Ctx.getDiagnostics()); 31530660a898545416f0fea2d717f16f75640001e38Ted Kremenek } else { 31630660a898545416f0fea2d717f16f75640001e38Ted Kremenek Remapper.flushToDisk(MigrateDir, Ctx.getDiagnostics()); 31730660a898545416f0fea2d717f16f75640001e38Ted Kremenek } 31830660a898545416f0fea2d717f16f75640001e38Ted Kremenek} 31930660a898545416f0fea2d717f16f75640001e38Ted Kremenek 32030660a898545416f0fea2d717f16f75640001e38Ted Kremenekbool MigrateSourceAction::BeginInvocation(CompilerInstance &CI) { 321013a254a5b85cfb54066e4022649368689c9ab06Argyrios Kyrtzidis CI.getDiagnostics().setIgnoreAllWarnings(true); 32230660a898545416f0fea2d717f16f75640001e38Ted Kremenek return true; 32330660a898545416f0fea2d717f16f75640001e38Ted Kremenek} 32430660a898545416f0fea2d717f16f75640001e38Ted Kremenek 32530660a898545416f0fea2d717f16f75640001e38Ted KremenekASTConsumer *MigrateSourceAction::CreateASTConsumer(CompilerInstance &CI, 32630660a898545416f0fea2d717f16f75640001e38Ted Kremenek StringRef InFile) { 32737ed12720a35b7bfa1c4de73ad6f1c6c1c88ee17Argyrios Kyrtzidis PPConditionalDirectiveRecord * 32837ed12720a35b7bfa1c4de73ad6f1c6c1c88ee17Argyrios Kyrtzidis PPRec = new PPConditionalDirectiveRecord(CI.getSourceManager()); 32937ed12720a35b7bfa1c4de73ad6f1c6c1c88ee17Argyrios Kyrtzidis CI.getPreprocessor().addPPCallbacks(PPRec); 33030660a898545416f0fea2d717f16f75640001e38Ted Kremenek return new ObjCMigrateASTConsumer(CI.getFrontendOpts().OutputFile, 33130660a898545416f0fea2d717f16f75640001e38Ted Kremenek /*MigrateLiterals=*/true, 33230660a898545416f0fea2d717f16f75640001e38Ted Kremenek /*MigrateSubscripting=*/true, 333d412999a3da6387dbfaf00f7647132082e94310eFariborz Jahanian /*MigrateProperty*/true, 33430660a898545416f0fea2d717f16f75640001e38Ted Kremenek Remapper, 33530660a898545416f0fea2d717f16f75640001e38Ted Kremenek CI.getFileManager(), 33637ed12720a35b7bfa1c4de73ad6f1c6c1c88ee17Argyrios Kyrtzidis PPRec, 337baf15574ebe70871b4682cdd5a87028bad1c9f6fFariborz Jahanian CI.getPreprocessor(), 33830660a898545416f0fea2d717f16f75640001e38Ted Kremenek /*isOutputFile=*/true); 33930660a898545416f0fea2d717f16f75640001e38Ted Kremenek} 340