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 1044b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian#include "Transforms.h" 1130660a898545416f0fea2d717f16f75640001e38Ted Kremenek#include "clang/ARCMigrate/ARCMTActions.h" 1255fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/AST/ASTConsumer.h" 13471c8b49982d1132f30b0b0da27fef94fd6e4f67Benjamin Kramer#include "clang/AST/ASTContext.h" 1430660a898545416f0fea2d717f16f75640001e38Ted Kremenek#include "clang/AST/NSAPI.h" 15a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis#include "clang/AST/ParentMap.h" 1655fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/AST/RecursiveASTVisitor.h" 1755fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/Basic/FileManager.h" 1830660a898545416f0fea2d717f16f75640001e38Ted Kremenek#include "clang/Edit/Commit.h" 1955fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/Edit/EditedSource.h" 2030660a898545416f0fea2d717f16f75640001e38Ted Kremenek#include "clang/Edit/EditsReceiver.h" 2155fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/Edit/Rewriters.h" 2255fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/Frontend/CompilerInstance.h" 2355fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/Frontend/MultiplexConsumer.h" 2437ed12720a35b7bfa1c4de73ad6f1c6c1c88ee17Argyrios Kyrtzidis#include "clang/Lex/PPConditionalDirectiveRecord.h" 2555fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/Lex/Preprocessor.h" 2655fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/Rewrite/Core/Rewriter.h" 2730660a898545416f0fea2d717f16f75640001e38Ted Kremenek#include "llvm/ADT/SmallString.h" 2830660a898545416f0fea2d717f16f75640001e38Ted Kremenek 2930660a898545416f0fea2d717f16f75640001e38Ted Kremenekusing namespace clang; 3030660a898545416f0fea2d717f16f75640001e38Ted Kremenekusing namespace arcmt; 3130660a898545416f0fea2d717f16f75640001e38Ted Kremenek 3230660a898545416f0fea2d717f16f75640001e38Ted Kremeneknamespace { 3330660a898545416f0fea2d717f16f75640001e38Ted Kremenek 3430660a898545416f0fea2d717f16f75640001e38Ted Kremenekclass ObjCMigrateASTConsumer : public ASTConsumer { 3530660a898545416f0fea2d717f16f75640001e38Ted Kremenek void migrateDecl(Decl *D); 36baf15574ebe70871b4682cdd5a87028bad1c9f6fFariborz Jahanian void migrateObjCInterfaceDecl(ASTContext &Ctx, ObjCInterfaceDecl *D); 377556853c60f3e2a3f43864d8ebe74ba5ac11e68eFariborz Jahanian void migrateProtocolConformance(ASTContext &Ctx, 387556853c60f3e2a3f43864d8ebe74ba5ac11e68eFariborz Jahanian const ObjCImplementationDecl *ImpDecl); 39bbbb0fe4f466d3163fcbf0a64ebf0f5868833efbFariborz Jahanian void migrateNSEnumDecl(ASTContext &Ctx, const EnumDecl *EnumDcl, 40bbbb0fe4f466d3163fcbf0a64ebf0f5868833efbFariborz Jahanian const TypedefDecl *TypedefDcl); 4111638f7b922aa0182ab2028ec819001ed2fe8085Fariborz Jahanian void migrateInstanceType(ASTContext &Ctx, ObjCContainerDecl *CDecl); 4226cf046ff3a2d24ff3e2c3757599976b644a06daFariborz Jahanian void migrateMethodInstanceType(ASTContext &Ctx, ObjCContainerDecl *CDecl, 4326cf046ff3a2d24ff3e2c3757599976b644a06daFariborz Jahanian ObjCMethodDecl *OM); 44f647b69147c6e640bbccf501783fafc495bbefb2Fariborz Jahanian void migrateFactoryMethod(ASTContext &Ctx, ObjCContainerDecl *CDecl, 458d3794e06a63578093bd71c3c2520bd01e6197a3Fariborz Jahanian ObjCMethodDecl *OM, 468d3794e06a63578093bd71c3c2520bd01e6197a3Fariborz Jahanian ObjCInstanceTypeFamily OIT_Family = OIT_None); 4730660a898545416f0fea2d717f16f75640001e38Ted Kremenek 4830660a898545416f0fea2d717f16f75640001e38Ted Kremenekpublic: 4930660a898545416f0fea2d717f16f75640001e38Ted Kremenek std::string MigrateDir; 5030660a898545416f0fea2d717f16f75640001e38Ted Kremenek bool MigrateLiterals; 5130660a898545416f0fea2d717f16f75640001e38Ted Kremenek bool MigrateSubscripting; 52d412999a3da6387dbfaf00f7647132082e94310eFariborz Jahanian bool MigrateProperty; 53cfa88f893915ceb8ae4ce2f17c46c24a4d67502fDmitri Gribenko OwningPtr<NSAPI> NSAPIObj; 54cfa88f893915ceb8ae4ce2f17c46c24a4d67502fDmitri Gribenko OwningPtr<edit::EditedSource> Editor; 5530660a898545416f0fea2d717f16f75640001e38Ted Kremenek FileRemapper &Remapper; 5630660a898545416f0fea2d717f16f75640001e38Ted Kremenek FileManager &FileMgr; 5737ed12720a35b7bfa1c4de73ad6f1c6c1c88ee17Argyrios Kyrtzidis const PPConditionalDirectiveRecord *PPRec; 58baf15574ebe70871b4682cdd5a87028bad1c9f6fFariborz Jahanian Preprocessor &PP; 5930660a898545416f0fea2d717f16f75640001e38Ted Kremenek bool IsOutputFile; 607556853c60f3e2a3f43864d8ebe74ba5ac11e68eFariborz Jahanian llvm::SmallPtrSet<ObjCProtocolDecl *, 32> ObjCProtocolDecls; 617556853c60f3e2a3f43864d8ebe74ba5ac11e68eFariborz Jahanian 6230660a898545416f0fea2d717f16f75640001e38Ted Kremenek ObjCMigrateASTConsumer(StringRef migrateDir, 6330660a898545416f0fea2d717f16f75640001e38Ted Kremenek bool migrateLiterals, 6430660a898545416f0fea2d717f16f75640001e38Ted Kremenek bool migrateSubscripting, 65d412999a3da6387dbfaf00f7647132082e94310eFariborz Jahanian bool migrateProperty, 6630660a898545416f0fea2d717f16f75640001e38Ted Kremenek FileRemapper &remapper, 6730660a898545416f0fea2d717f16f75640001e38Ted Kremenek FileManager &fileMgr, 6837ed12720a35b7bfa1c4de73ad6f1c6c1c88ee17Argyrios Kyrtzidis const PPConditionalDirectiveRecord *PPRec, 69baf15574ebe70871b4682cdd5a87028bad1c9f6fFariborz Jahanian Preprocessor &PP, 7030660a898545416f0fea2d717f16f75640001e38Ted Kremenek bool isOutputFile = false) 7130660a898545416f0fea2d717f16f75640001e38Ted Kremenek : MigrateDir(migrateDir), 7230660a898545416f0fea2d717f16f75640001e38Ted Kremenek MigrateLiterals(migrateLiterals), 7330660a898545416f0fea2d717f16f75640001e38Ted Kremenek MigrateSubscripting(migrateSubscripting), 74d412999a3da6387dbfaf00f7647132082e94310eFariborz Jahanian MigrateProperty(migrateProperty), 75baf15574ebe70871b4682cdd5a87028bad1c9f6fFariborz Jahanian Remapper(remapper), FileMgr(fileMgr), PPRec(PPRec), PP(PP), 7630660a898545416f0fea2d717f16f75640001e38Ted Kremenek IsOutputFile(isOutputFile) { } 7730660a898545416f0fea2d717f16f75640001e38Ted Kremenek 7830660a898545416f0fea2d717f16f75640001e38Ted Kremenekprotected: 7930660a898545416f0fea2d717f16f75640001e38Ted Kremenek virtual void Initialize(ASTContext &Context) { 8030660a898545416f0fea2d717f16f75640001e38Ted Kremenek NSAPIObj.reset(new NSAPI(Context)); 8130660a898545416f0fea2d717f16f75640001e38Ted Kremenek Editor.reset(new edit::EditedSource(Context.getSourceManager(), 824e4d08403ca5cfd4d558fa2936215d3a4e5a528dDavid Blaikie Context.getLangOpts(), 8330660a898545416f0fea2d717f16f75640001e38Ted Kremenek PPRec)); 8430660a898545416f0fea2d717f16f75640001e38Ted Kremenek } 8530660a898545416f0fea2d717f16f75640001e38Ted Kremenek 8630660a898545416f0fea2d717f16f75640001e38Ted Kremenek virtual bool HandleTopLevelDecl(DeclGroupRef DG) { 8730660a898545416f0fea2d717f16f75640001e38Ted Kremenek for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I) 8830660a898545416f0fea2d717f16f75640001e38Ted Kremenek migrateDecl(*I); 8930660a898545416f0fea2d717f16f75640001e38Ted Kremenek return true; 9030660a898545416f0fea2d717f16f75640001e38Ted Kremenek } 9130660a898545416f0fea2d717f16f75640001e38Ted Kremenek virtual void HandleInterestingDecl(DeclGroupRef DG) { 9230660a898545416f0fea2d717f16f75640001e38Ted Kremenek // Ignore decls from the PCH. 9330660a898545416f0fea2d717f16f75640001e38Ted Kremenek } 9430660a898545416f0fea2d717f16f75640001e38Ted Kremenek virtual void HandleTopLevelDeclInObjCContainer(DeclGroupRef DG) { 9530660a898545416f0fea2d717f16f75640001e38Ted Kremenek ObjCMigrateASTConsumer::HandleTopLevelDecl(DG); 9630660a898545416f0fea2d717f16f75640001e38Ted Kremenek } 9730660a898545416f0fea2d717f16f75640001e38Ted Kremenek 9830660a898545416f0fea2d717f16f75640001e38Ted Kremenek virtual void HandleTranslationUnit(ASTContext &Ctx); 9930660a898545416f0fea2d717f16f75640001e38Ted Kremenek}; 10030660a898545416f0fea2d717f16f75640001e38Ted Kremenek 10130660a898545416f0fea2d717f16f75640001e38Ted Kremenek} 10230660a898545416f0fea2d717f16f75640001e38Ted Kremenek 10330660a898545416f0fea2d717f16f75640001e38Ted KremenekObjCMigrateAction::ObjCMigrateAction(FrontendAction *WrappedAction, 10430660a898545416f0fea2d717f16f75640001e38Ted Kremenek StringRef migrateDir, 10530660a898545416f0fea2d717f16f75640001e38Ted Kremenek bool migrateLiterals, 106d412999a3da6387dbfaf00f7647132082e94310eFariborz Jahanian bool migrateSubscripting, 107d412999a3da6387dbfaf00f7647132082e94310eFariborz Jahanian bool migrateProperty) 10830660a898545416f0fea2d717f16f75640001e38Ted Kremenek : WrapperFrontendAction(WrappedAction), MigrateDir(migrateDir), 10930660a898545416f0fea2d717f16f75640001e38Ted Kremenek MigrateLiterals(migrateLiterals), MigrateSubscripting(migrateSubscripting), 110d412999a3da6387dbfaf00f7647132082e94310eFariborz Jahanian MigrateProperty(migrateProperty), 11130660a898545416f0fea2d717f16f75640001e38Ted Kremenek CompInst(0) { 11230660a898545416f0fea2d717f16f75640001e38Ted Kremenek if (MigrateDir.empty()) 11330660a898545416f0fea2d717f16f75640001e38Ted Kremenek MigrateDir = "."; // user current directory if none is given. 11430660a898545416f0fea2d717f16f75640001e38Ted Kremenek} 11530660a898545416f0fea2d717f16f75640001e38Ted Kremenek 11630660a898545416f0fea2d717f16f75640001e38Ted KremenekASTConsumer *ObjCMigrateAction::CreateASTConsumer(CompilerInstance &CI, 11730660a898545416f0fea2d717f16f75640001e38Ted Kremenek StringRef InFile) { 11837ed12720a35b7bfa1c4de73ad6f1c6c1c88ee17Argyrios Kyrtzidis PPConditionalDirectiveRecord * 11937ed12720a35b7bfa1c4de73ad6f1c6c1c88ee17Argyrios Kyrtzidis PPRec = new PPConditionalDirectiveRecord(CompInst->getSourceManager()); 12037ed12720a35b7bfa1c4de73ad6f1c6c1c88ee17Argyrios Kyrtzidis CompInst->getPreprocessor().addPPCallbacks(PPRec); 12130660a898545416f0fea2d717f16f75640001e38Ted Kremenek ASTConsumer * 12230660a898545416f0fea2d717f16f75640001e38Ted Kremenek WrappedConsumer = WrapperFrontendAction::CreateASTConsumer(CI, InFile); 12330660a898545416f0fea2d717f16f75640001e38Ted Kremenek ASTConsumer *MTConsumer = new ObjCMigrateASTConsumer(MigrateDir, 12430660a898545416f0fea2d717f16f75640001e38Ted Kremenek MigrateLiterals, 12530660a898545416f0fea2d717f16f75640001e38Ted Kremenek MigrateSubscripting, 126d412999a3da6387dbfaf00f7647132082e94310eFariborz Jahanian MigrateProperty, 12730660a898545416f0fea2d717f16f75640001e38Ted Kremenek Remapper, 12830660a898545416f0fea2d717f16f75640001e38Ted Kremenek CompInst->getFileManager(), 129baf15574ebe70871b4682cdd5a87028bad1c9f6fFariborz Jahanian PPRec, 130baf15574ebe70871b4682cdd5a87028bad1c9f6fFariborz Jahanian CompInst->getPreprocessor()); 13130660a898545416f0fea2d717f16f75640001e38Ted Kremenek ASTConsumer *Consumers[] = { MTConsumer, WrappedConsumer }; 13230660a898545416f0fea2d717f16f75640001e38Ted Kremenek return new MultiplexConsumer(Consumers); 13330660a898545416f0fea2d717f16f75640001e38Ted Kremenek} 13430660a898545416f0fea2d717f16f75640001e38Ted Kremenek 13530660a898545416f0fea2d717f16f75640001e38Ted Kremenekbool ObjCMigrateAction::BeginInvocation(CompilerInstance &CI) { 13630660a898545416f0fea2d717f16f75640001e38Ted Kremenek Remapper.initFromDisk(MigrateDir, CI.getDiagnostics(), 13730660a898545416f0fea2d717f16f75640001e38Ted Kremenek /*ignoreIfFilesChanges=*/true); 13830660a898545416f0fea2d717f16f75640001e38Ted Kremenek CompInst = &CI; 13930660a898545416f0fea2d717f16f75640001e38Ted Kremenek CI.getDiagnostics().setIgnoreAllWarnings(true); 14030660a898545416f0fea2d717f16f75640001e38Ted Kremenek return true; 14130660a898545416f0fea2d717f16f75640001e38Ted Kremenek} 14230660a898545416f0fea2d717f16f75640001e38Ted Kremenek 14330660a898545416f0fea2d717f16f75640001e38Ted Kremeneknamespace { 14430660a898545416f0fea2d717f16f75640001e38Ted Kremenekclass ObjCMigrator : public RecursiveASTVisitor<ObjCMigrator> { 14530660a898545416f0fea2d717f16f75640001e38Ted Kremenek ObjCMigrateASTConsumer &Consumer; 146a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis ParentMap &PMap; 14730660a898545416f0fea2d717f16f75640001e38Ted Kremenek 14830660a898545416f0fea2d717f16f75640001e38Ted Kremenekpublic: 149a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis ObjCMigrator(ObjCMigrateASTConsumer &consumer, ParentMap &PMap) 150a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis : Consumer(consumer), PMap(PMap) { } 15130660a898545416f0fea2d717f16f75640001e38Ted Kremenek 15230660a898545416f0fea2d717f16f75640001e38Ted Kremenek bool shouldVisitTemplateInstantiations() const { return false; } 15330660a898545416f0fea2d717f16f75640001e38Ted Kremenek bool shouldWalkTypesOfTypeLocs() const { return false; } 15430660a898545416f0fea2d717f16f75640001e38Ted Kremenek 15530660a898545416f0fea2d717f16f75640001e38Ted Kremenek bool VisitObjCMessageExpr(ObjCMessageExpr *E) { 15630660a898545416f0fea2d717f16f75640001e38Ted Kremenek if (Consumer.MigrateLiterals) { 15730660a898545416f0fea2d717f16f75640001e38Ted Kremenek edit::Commit commit(*Consumer.Editor); 158a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis edit::rewriteToObjCLiteralSyntax(E, *Consumer.NSAPIObj, commit, &PMap); 15930660a898545416f0fea2d717f16f75640001e38Ted Kremenek Consumer.Editor->commit(commit); 16030660a898545416f0fea2d717f16f75640001e38Ted Kremenek } 16130660a898545416f0fea2d717f16f75640001e38Ted Kremenek 16230660a898545416f0fea2d717f16f75640001e38Ted Kremenek if (Consumer.MigrateSubscripting) { 16330660a898545416f0fea2d717f16f75640001e38Ted Kremenek edit::Commit commit(*Consumer.Editor); 16430660a898545416f0fea2d717f16f75640001e38Ted Kremenek edit::rewriteToObjCSubscriptSyntax(E, *Consumer.NSAPIObj, commit); 16530660a898545416f0fea2d717f16f75640001e38Ted Kremenek Consumer.Editor->commit(commit); 16630660a898545416f0fea2d717f16f75640001e38Ted Kremenek } 16730660a898545416f0fea2d717f16f75640001e38Ted Kremenek 16830660a898545416f0fea2d717f16f75640001e38Ted Kremenek return true; 16930660a898545416f0fea2d717f16f75640001e38Ted Kremenek } 17030660a898545416f0fea2d717f16f75640001e38Ted Kremenek 17130660a898545416f0fea2d717f16f75640001e38Ted Kremenek bool TraverseObjCMessageExpr(ObjCMessageExpr *E) { 17230660a898545416f0fea2d717f16f75640001e38Ted Kremenek // Do depth first; we want to rewrite the subexpressions first so that if 17330660a898545416f0fea2d717f16f75640001e38Ted Kremenek // we have to move expressions we will move them already rewritten. 17430660a898545416f0fea2d717f16f75640001e38Ted Kremenek for (Stmt::child_range range = E->children(); range; ++range) 17530660a898545416f0fea2d717f16f75640001e38Ted Kremenek if (!TraverseStmt(*range)) 17630660a898545416f0fea2d717f16f75640001e38Ted Kremenek return false; 17730660a898545416f0fea2d717f16f75640001e38Ted Kremenek 17830660a898545416f0fea2d717f16f75640001e38Ted Kremenek return WalkUpFromObjCMessageExpr(E); 17930660a898545416f0fea2d717f16f75640001e38Ted Kremenek } 18030660a898545416f0fea2d717f16f75640001e38Ted Kremenek}; 181a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis 182a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidisclass BodyMigrator : public RecursiveASTVisitor<BodyMigrator> { 183a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis ObjCMigrateASTConsumer &Consumer; 184a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis OwningPtr<ParentMap> PMap; 185a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis 186a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidispublic: 187a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis BodyMigrator(ObjCMigrateASTConsumer &consumer) : Consumer(consumer) { } 188a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis 189a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis bool shouldVisitTemplateInstantiations() const { return false; } 190a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis bool shouldWalkTypesOfTypeLocs() const { return false; } 191a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis 192a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis bool TraverseStmt(Stmt *S) { 193a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis PMap.reset(new ParentMap(S)); 194a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis ObjCMigrator(Consumer, *PMap).TraverseStmt(S); 195a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis return true; 196a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis } 197a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis}; 19830660a898545416f0fea2d717f16f75640001e38Ted Kremenek} 19930660a898545416f0fea2d717f16f75640001e38Ted Kremenek 20030660a898545416f0fea2d717f16f75640001e38Ted Kremenekvoid ObjCMigrateASTConsumer::migrateDecl(Decl *D) { 20130660a898545416f0fea2d717f16f75640001e38Ted Kremenek if (!D) 20230660a898545416f0fea2d717f16f75640001e38Ted Kremenek return; 20330660a898545416f0fea2d717f16f75640001e38Ted Kremenek if (isa<ObjCMethodDecl>(D)) 20430660a898545416f0fea2d717f16f75640001e38Ted Kremenek return; // Wait for the ObjC container declaration. 20530660a898545416f0fea2d717f16f75640001e38Ted Kremenek 206a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis BodyMigrator(*this).TraverseDecl(D); 20730660a898545416f0fea2d717f16f75640001e38Ted Kremenek} 20830660a898545416f0fea2d717f16f75640001e38Ted Kremenek 20944b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanianstatic bool rewriteToObjCProperty(const ObjCMethodDecl *Getter, 21044b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian const ObjCMethodDecl *Setter, 21144b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian const NSAPI &NS, edit::Commit &commit) { 21244b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian ASTContext &Context = NS.getASTContext(); 21344b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian std::string PropertyString = "@property"; 21444b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian 215fa45cb3bf95a10d6c3b1ab55d60dae28e8a57cf4Fariborz Jahanian std::string PropertyNameString = Getter->getNameAsString(); 216fa45cb3bf95a10d6c3b1ab55d60dae28e8a57cf4Fariborz Jahanian StringRef PropertyName(PropertyNameString); 217fa45cb3bf95a10d6c3b1ab55d60dae28e8a57cf4Fariborz Jahanian // Short circuit properties that contain the name "delegate" or "dataSource", 218fa45cb3bf95a10d6c3b1ab55d60dae28e8a57cf4Fariborz Jahanian // or have exact name "target" to have unsafe_unretained attribute. 219fa45cb3bf95a10d6c3b1ab55d60dae28e8a57cf4Fariborz Jahanian if (PropertyName.equals("target") || 220fa45cb3bf95a10d6c3b1ab55d60dae28e8a57cf4Fariborz Jahanian (PropertyName.find("delegate") != StringRef::npos) || 221fa45cb3bf95a10d6c3b1ab55d60dae28e8a57cf4Fariborz Jahanian (PropertyName.find("dataSource") != StringRef::npos)) 22244b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian PropertyString += "(unsafe_unretained)"; 223fa45cb3bf95a10d6c3b1ab55d60dae28e8a57cf4Fariborz Jahanian else { 224fa45cb3bf95a10d6c3b1ab55d60dae28e8a57cf4Fariborz Jahanian const ParmVarDecl *argDecl = *Setter->param_begin(); 225fa45cb3bf95a10d6c3b1ab55d60dae28e8a57cf4Fariborz Jahanian QualType ArgType = Context.getCanonicalType(argDecl->getType()); 226fa45cb3bf95a10d6c3b1ab55d60dae28e8a57cf4Fariborz Jahanian Qualifiers::ObjCLifetime propertyLifetime = ArgType.getObjCLifetime(); 227fa45cb3bf95a10d6c3b1ab55d60dae28e8a57cf4Fariborz Jahanian bool RetainableObject = ArgType->isObjCRetainableType(); 228fa45cb3bf95a10d6c3b1ab55d60dae28e8a57cf4Fariborz Jahanian if (RetainableObject && propertyLifetime == Qualifiers::OCL_Strong) { 229fa45cb3bf95a10d6c3b1ab55d60dae28e8a57cf4Fariborz Jahanian if (const ObjCObjectPointerType *ObjPtrTy = 230fa45cb3bf95a10d6c3b1ab55d60dae28e8a57cf4Fariborz Jahanian ArgType->getAs<ObjCObjectPointerType>()) { 231fa45cb3bf95a10d6c3b1ab55d60dae28e8a57cf4Fariborz Jahanian ObjCInterfaceDecl *IDecl = ObjPtrTy->getObjectType()->getInterface(); 232fa45cb3bf95a10d6c3b1ab55d60dae28e8a57cf4Fariborz Jahanian if (IDecl && 233fa45cb3bf95a10d6c3b1ab55d60dae28e8a57cf4Fariborz Jahanian IDecl->lookupNestedProtocol(&Context.Idents.get("NSCopying"))) 234fa45cb3bf95a10d6c3b1ab55d60dae28e8a57cf4Fariborz Jahanian PropertyString += "(copy)"; 235fa45cb3bf95a10d6c3b1ab55d60dae28e8a57cf4Fariborz Jahanian else 236fa45cb3bf95a10d6c3b1ab55d60dae28e8a57cf4Fariborz Jahanian PropertyString += "(retain)"; 237fa45cb3bf95a10d6c3b1ab55d60dae28e8a57cf4Fariborz Jahanian } 238fa45cb3bf95a10d6c3b1ab55d60dae28e8a57cf4Fariborz Jahanian } else if (propertyLifetime == Qualifiers::OCL_Weak) 239fa45cb3bf95a10d6c3b1ab55d60dae28e8a57cf4Fariborz Jahanian // TODO. More precise determination of 'weak' attribute requires 240fa45cb3bf95a10d6c3b1ab55d60dae28e8a57cf4Fariborz Jahanian // looking into setter's implementation for backing weak ivar. 241fa45cb3bf95a10d6c3b1ab55d60dae28e8a57cf4Fariborz Jahanian PropertyString += "(weak)"; 242fa45cb3bf95a10d6c3b1ab55d60dae28e8a57cf4Fariborz Jahanian else if (RetainableObject) 243fa45cb3bf95a10d6c3b1ab55d60dae28e8a57cf4Fariborz Jahanian PropertyString += "(retain)"; 244fa45cb3bf95a10d6c3b1ab55d60dae28e8a57cf4Fariborz Jahanian } 24544b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian 24644b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian // strip off any ARC lifetime qualifier. 24744b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian QualType CanResultTy = Context.getCanonicalType(Getter->getResultType()); 24844b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian if (CanResultTy.getQualifiers().hasObjCLifetime()) { 24944b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian Qualifiers Qs = CanResultTy.getQualifiers(); 25044b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian Qs.removeObjCLifetime(); 25144b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian CanResultTy = Context.getQualifiedType(CanResultTy.getUnqualifiedType(), Qs); 25244b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian } 25344b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian PropertyString += " "; 25444b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian PropertyString += CanResultTy.getAsString(Context.getPrintingPolicy()); 25544b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian PropertyString += " "; 256fa45cb3bf95a10d6c3b1ab55d60dae28e8a57cf4Fariborz Jahanian PropertyString += PropertyNameString; 25744b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian commit.replace(CharSourceRange::getCharRange(Getter->getLocStart(), 25844b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian Getter->getDeclaratorEndLoc()), 25944b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian PropertyString); 26044b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian SourceLocation EndLoc = Setter->getDeclaratorEndLoc(); 26144b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian // Get location past ';' 26244b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian EndLoc = EndLoc.getLocWithOffset(1); 26344b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian commit.remove(CharSourceRange::getCharRange(Setter->getLocStart(), EndLoc)); 26444b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian return true; 26544b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian} 26644b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian 267baf15574ebe70871b4682cdd5a87028bad1c9f6fFariborz Jahanianvoid ObjCMigrateASTConsumer::migrateObjCInterfaceDecl(ASTContext &Ctx, 268baf15574ebe70871b4682cdd5a87028bad1c9f6fFariborz Jahanian ObjCInterfaceDecl *D) { 269baf15574ebe70871b4682cdd5a87028bad1c9f6fFariborz Jahanian for (ObjCContainerDecl::method_iterator M = D->meth_begin(), MEnd = D->meth_end(); 270baf15574ebe70871b4682cdd5a87028bad1c9f6fFariborz Jahanian M != MEnd; ++M) { 271baf15574ebe70871b4682cdd5a87028bad1c9f6fFariborz Jahanian ObjCMethodDecl *Method = (*M); 272dca7289799517c3eee1765a174984f2ecffad0f1Fariborz Jahanian if (Method->isPropertyAccessor() || Method->param_size() != 0) 273baf15574ebe70871b4682cdd5a87028bad1c9f6fFariborz Jahanian continue; 274baf15574ebe70871b4682cdd5a87028bad1c9f6fFariborz Jahanian // Is this method candidate to be a getter? 275dca7289799517c3eee1765a174984f2ecffad0f1Fariborz Jahanian QualType GRT = Method->getResultType(); 276dca7289799517c3eee1765a174984f2ecffad0f1Fariborz Jahanian if (GRT->isVoidType()) 277dca7289799517c3eee1765a174984f2ecffad0f1Fariborz Jahanian continue; 2782a4ebcfe8b5920ca35924359135f3c5ddca7b171Fariborz Jahanian // FIXME. Don't know what todo with attributes, skip for now. 2792a4ebcfe8b5920ca35924359135f3c5ddca7b171Fariborz Jahanian if (Method->hasAttrs()) 2802a4ebcfe8b5920ca35924359135f3c5ddca7b171Fariborz Jahanian continue; 2812a4ebcfe8b5920ca35924359135f3c5ddca7b171Fariborz Jahanian 282dca7289799517c3eee1765a174984f2ecffad0f1Fariborz Jahanian Selector GetterSelector = Method->getSelector(); 283dca7289799517c3eee1765a174984f2ecffad0f1Fariborz Jahanian IdentifierInfo *getterName = GetterSelector.getIdentifierInfoForSlot(0); 284dca7289799517c3eee1765a174984f2ecffad0f1Fariborz Jahanian Selector SetterSelector = 285dca7289799517c3eee1765a174984f2ecffad0f1Fariborz Jahanian SelectorTable::constructSetterSelector(PP.getIdentifierTable(), 286dca7289799517c3eee1765a174984f2ecffad0f1Fariborz Jahanian PP.getSelectorTable(), 287dca7289799517c3eee1765a174984f2ecffad0f1Fariborz Jahanian getterName); 288dca7289799517c3eee1765a174984f2ecffad0f1Fariborz Jahanian if (ObjCMethodDecl *SetterMethod = D->lookupMethod(SetterSelector, true)) { 289dca7289799517c3eee1765a174984f2ecffad0f1Fariborz Jahanian // Is this a valid setter, matching the target getter? 290dca7289799517c3eee1765a174984f2ecffad0f1Fariborz Jahanian QualType SRT = SetterMethod->getResultType(); 291dca7289799517c3eee1765a174984f2ecffad0f1Fariborz Jahanian if (!SRT->isVoidType()) 292dca7289799517c3eee1765a174984f2ecffad0f1Fariborz Jahanian continue; 293dca7289799517c3eee1765a174984f2ecffad0f1Fariborz Jahanian const ParmVarDecl *argDecl = *SetterMethod->param_begin(); 29452477fb1b86f99a2a8c77e1523d4f186490c28e9Fariborz Jahanian QualType ArgType = argDecl->getType(); 2952a4ebcfe8b5920ca35924359135f3c5ddca7b171Fariborz Jahanian if (!Ctx.hasSameUnqualifiedType(ArgType, GRT) || 2962a4ebcfe8b5920ca35924359135f3c5ddca7b171Fariborz Jahanian SetterMethod->hasAttrs()) 29752477fb1b86f99a2a8c77e1523d4f186490c28e9Fariborz Jahanian continue; 298afcb16f9cff8d5ccd57a6386d65ddc055368d0bcFariborz Jahanian edit::Commit commit(*Editor); 29944b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian rewriteToObjCProperty(Method, SetterMethod, *NSAPIObj, commit); 300afcb16f9cff8d5ccd57a6386d65ddc055368d0bcFariborz Jahanian Editor->commit(commit); 301baf15574ebe70871b4682cdd5a87028bad1c9f6fFariborz Jahanian } 302baf15574ebe70871b4682cdd5a87028bad1c9f6fFariborz Jahanian } 303baf15574ebe70871b4682cdd5a87028bad1c9f6fFariborz Jahanian} 304baf15574ebe70871b4682cdd5a87028bad1c9f6fFariborz Jahanian 305e99b37c8f271814ba63046bbde9af0c68e7a26c9Fariborz Jahanianstatic bool 306bf13df238a82659c0b6363541a84f09bc997fb86Fariborz JahanianClassImplementsAllMethodsAndProperties(ASTContext &Ctx, 307e99b37c8f271814ba63046bbde9af0c68e7a26c9Fariborz Jahanian const ObjCImplementationDecl *ImpDecl, 308ad4aaf11897cc5e9d443b0a80114daacf385f6dfFariborz Jahanian const ObjCInterfaceDecl *IDecl, 309e99b37c8f271814ba63046bbde9af0c68e7a26c9Fariborz Jahanian ObjCProtocolDecl *Protocol) { 310ad4aaf11897cc5e9d443b0a80114daacf385f6dfFariborz Jahanian // In auto-synthesis, protocol properties are not synthesized. So, 311ad4aaf11897cc5e9d443b0a80114daacf385f6dfFariborz Jahanian // a conforming protocol must have its required properties declared 312ad4aaf11897cc5e9d443b0a80114daacf385f6dfFariborz Jahanian // in class interface. 31334cb2a3ed535eebed87d1118e89d006eb324e156Fariborz Jahanian bool HasAtleastOneRequiredProperty = false; 314ad4aaf11897cc5e9d443b0a80114daacf385f6dfFariborz Jahanian if (const ObjCProtocolDecl *PDecl = Protocol->getDefinition()) 315ad4aaf11897cc5e9d443b0a80114daacf385f6dfFariborz Jahanian for (ObjCProtocolDecl::prop_iterator P = PDecl->prop_begin(), 316ad4aaf11897cc5e9d443b0a80114daacf385f6dfFariborz Jahanian E = PDecl->prop_end(); P != E; ++P) { 317ad4aaf11897cc5e9d443b0a80114daacf385f6dfFariborz Jahanian ObjCPropertyDecl *Property = *P; 318ad4aaf11897cc5e9d443b0a80114daacf385f6dfFariborz Jahanian if (Property->getPropertyImplementation() == ObjCPropertyDecl::Optional) 319ad4aaf11897cc5e9d443b0a80114daacf385f6dfFariborz Jahanian continue; 32034cb2a3ed535eebed87d1118e89d006eb324e156Fariborz Jahanian HasAtleastOneRequiredProperty = true; 321ad4aaf11897cc5e9d443b0a80114daacf385f6dfFariborz Jahanian DeclContext::lookup_const_result R = IDecl->lookup(Property->getDeclName()); 3228d8bfb3e52567b86add4bfa931023f2e2a291499Fariborz Jahanian if (R.size() == 0) { 3238d8bfb3e52567b86add4bfa931023f2e2a291499Fariborz Jahanian // Relax the rule and look into class's implementation for a synthesize 3248d8bfb3e52567b86add4bfa931023f2e2a291499Fariborz Jahanian // or dynamic declaration. Class is implementing a property coming from 3258d8bfb3e52567b86add4bfa931023f2e2a291499Fariborz Jahanian // another protocol. This still makes the target protocol as conforming. 3268d8bfb3e52567b86add4bfa931023f2e2a291499Fariborz Jahanian if (!ImpDecl->FindPropertyImplDecl( 3278d8bfb3e52567b86add4bfa931023f2e2a291499Fariborz Jahanian Property->getDeclName().getAsIdentifierInfo())) 3288d8bfb3e52567b86add4bfa931023f2e2a291499Fariborz Jahanian return false; 3298d8bfb3e52567b86add4bfa931023f2e2a291499Fariborz Jahanian } 3308d8bfb3e52567b86add4bfa931023f2e2a291499Fariborz Jahanian else if (ObjCPropertyDecl *ClassProperty = dyn_cast<ObjCPropertyDecl>(R[0])) { 3318d8bfb3e52567b86add4bfa931023f2e2a291499Fariborz Jahanian if ((ClassProperty->getPropertyAttributes() 3328d8bfb3e52567b86add4bfa931023f2e2a291499Fariborz Jahanian != Property->getPropertyAttributes()) || 3338d8bfb3e52567b86add4bfa931023f2e2a291499Fariborz Jahanian !Ctx.hasSameType(ClassProperty->getType(), Property->getType())) 334ad4aaf11897cc5e9d443b0a80114daacf385f6dfFariborz Jahanian return false; 335ad4aaf11897cc5e9d443b0a80114daacf385f6dfFariborz Jahanian } 3368d8bfb3e52567b86add4bfa931023f2e2a291499Fariborz Jahanian else 3378d8bfb3e52567b86add4bfa931023f2e2a291499Fariborz Jahanian return false; 338ad4aaf11897cc5e9d443b0a80114daacf385f6dfFariborz Jahanian } 33934cb2a3ed535eebed87d1118e89d006eb324e156Fariborz Jahanian 340ad4aaf11897cc5e9d443b0a80114daacf385f6dfFariborz Jahanian // At this point, all required properties in this protocol conform to those 341ad4aaf11897cc5e9d443b0a80114daacf385f6dfFariborz Jahanian // declared in the class. 342ad4aaf11897cc5e9d443b0a80114daacf385f6dfFariborz Jahanian // Check that class implements the required methods of the protocol too. 34334cb2a3ed535eebed87d1118e89d006eb324e156Fariborz Jahanian bool HasAtleastOneRequiredMethod = false; 3448c355831ac3c9e8c12b23ca69b7587dcbd0439efFariborz Jahanian if (const ObjCProtocolDecl *PDecl = Protocol->getDefinition()) { 3458c355831ac3c9e8c12b23ca69b7587dcbd0439efFariborz Jahanian if (PDecl->meth_begin() == PDecl->meth_end()) 34634cb2a3ed535eebed87d1118e89d006eb324e156Fariborz Jahanian return HasAtleastOneRequiredProperty; 347ad4aaf11897cc5e9d443b0a80114daacf385f6dfFariborz Jahanian for (ObjCContainerDecl::method_iterator M = PDecl->meth_begin(), 348ad4aaf11897cc5e9d443b0a80114daacf385f6dfFariborz Jahanian MEnd = PDecl->meth_end(); M != MEnd; ++M) { 349ad4aaf11897cc5e9d443b0a80114daacf385f6dfFariborz Jahanian ObjCMethodDecl *MD = (*M); 3508c355831ac3c9e8c12b23ca69b7587dcbd0439efFariborz Jahanian if (MD->isImplicit()) 3518c355831ac3c9e8c12b23ca69b7587dcbd0439efFariborz Jahanian continue; 352ad4aaf11897cc5e9d443b0a80114daacf385f6dfFariborz Jahanian if (MD->getImplementationControl() == ObjCMethodDecl::Optional) 353ad4aaf11897cc5e9d443b0a80114daacf385f6dfFariborz Jahanian continue; 354ad4aaf11897cc5e9d443b0a80114daacf385f6dfFariborz Jahanian DeclContext::lookup_const_result R = ImpDecl->lookup(MD->getDeclName()); 3558c355831ac3c9e8c12b23ca69b7587dcbd0439efFariborz Jahanian if (R.size() == 0) 3568c355831ac3c9e8c12b23ca69b7587dcbd0439efFariborz Jahanian return false; 35734cb2a3ed535eebed87d1118e89d006eb324e156Fariborz Jahanian bool match = false; 35834cb2a3ed535eebed87d1118e89d006eb324e156Fariborz Jahanian HasAtleastOneRequiredMethod = true; 359ad4aaf11897cc5e9d443b0a80114daacf385f6dfFariborz Jahanian for (unsigned I = 0, N = R.size(); I != N; ++I) 360ad4aaf11897cc5e9d443b0a80114daacf385f6dfFariborz Jahanian if (ObjCMethodDecl *ImpMD = dyn_cast<ObjCMethodDecl>(R[0])) 361ad4aaf11897cc5e9d443b0a80114daacf385f6dfFariborz Jahanian if (Ctx.ObjCMethodsAreEqual(MD, ImpMD)) { 362ad4aaf11897cc5e9d443b0a80114daacf385f6dfFariborz Jahanian match = true; 363ad4aaf11897cc5e9d443b0a80114daacf385f6dfFariborz Jahanian break; 364ad4aaf11897cc5e9d443b0a80114daacf385f6dfFariborz Jahanian } 365ad4aaf11897cc5e9d443b0a80114daacf385f6dfFariborz Jahanian if (!match) 366ad4aaf11897cc5e9d443b0a80114daacf385f6dfFariborz Jahanian return false; 367ad4aaf11897cc5e9d443b0a80114daacf385f6dfFariborz Jahanian } 3688c355831ac3c9e8c12b23ca69b7587dcbd0439efFariborz Jahanian } 36934cb2a3ed535eebed87d1118e89d006eb324e156Fariborz Jahanian if (HasAtleastOneRequiredProperty || HasAtleastOneRequiredMethod) 37034cb2a3ed535eebed87d1118e89d006eb324e156Fariborz Jahanian return true; 37134cb2a3ed535eebed87d1118e89d006eb324e156Fariborz Jahanian return false; 372e99b37c8f271814ba63046bbde9af0c68e7a26c9Fariborz Jahanian} 373e99b37c8f271814ba63046bbde9af0c68e7a26c9Fariborz Jahanian 37444b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanianstatic bool rewriteToObjCInterfaceDecl(const ObjCInterfaceDecl *IDecl, 37544b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian llvm::SmallVectorImpl<ObjCProtocolDecl*> &ConformingProtocols, 37644b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian const NSAPI &NS, edit::Commit &commit) { 37744b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian const ObjCList<ObjCProtocolDecl> &Protocols = IDecl->getReferencedProtocols(); 37844b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian std::string ClassString; 37944b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian SourceLocation EndLoc = 38044b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian IDecl->getSuperClass() ? IDecl->getSuperClassLoc() : IDecl->getLocation(); 38144b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian 38244b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian if (Protocols.empty()) { 38344b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian ClassString = '<'; 38444b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian for (unsigned i = 0, e = ConformingProtocols.size(); i != e; i++) { 38544b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian ClassString += ConformingProtocols[i]->getNameAsString(); 38644b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian if (i != (e-1)) 38744b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian ClassString += ", "; 38844b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian } 38944b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian ClassString += "> "; 39044b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian } 39144b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian else { 39244b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian ClassString = ", "; 39344b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian for (unsigned i = 0, e = ConformingProtocols.size(); i != e; i++) { 39444b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian ClassString += ConformingProtocols[i]->getNameAsString(); 39544b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian if (i != (e-1)) 39644b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian ClassString += ", "; 39744b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian } 39844b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian ObjCInterfaceDecl::protocol_loc_iterator PL = IDecl->protocol_loc_end() - 1; 39944b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian EndLoc = *PL; 40044b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian } 40144b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian 40244b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian commit.insertAfterToken(EndLoc, ClassString); 40344b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian return true; 40444b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian} 40544b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian 40644b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanianstatic bool rewriteToNSEnumDecl(const EnumDecl *EnumDcl, 40744b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian const TypedefDecl *TypedefDcl, 4089f9e54390c255587b009d912007b139432ab7bdcFariborz Jahanian const NSAPI &NS, edit::Commit &commit, 4099f9e54390c255587b009d912007b139432ab7bdcFariborz Jahanian bool IsNSIntegerType) { 410faae53d1cec325140a548c8e9ff647b7edb43702Fariborz Jahanian std::string ClassString = 4119f9e54390c255587b009d912007b139432ab7bdcFariborz Jahanian IsNSIntegerType ? "typedef NS_ENUM(NSInteger, " : "typedef NS_OPTIONS(NSUInteger, "; 41244b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian ClassString += TypedefDcl->getIdentifier()->getName(); 41344b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian ClassString += ')'; 41444b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian SourceRange R(EnumDcl->getLocStart(), EnumDcl->getLocStart()); 41544b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian commit.replace(R, ClassString); 41644b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian SourceLocation EndOfTypedefLoc = TypedefDcl->getLocEnd(); 41744b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian EndOfTypedefLoc = trans::findLocationAfterSemi(EndOfTypedefLoc, NS.getASTContext()); 41844b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian if (!EndOfTypedefLoc.isInvalid()) { 41944b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian commit.remove(SourceRange(TypedefDcl->getLocStart(), EndOfTypedefLoc)); 42044b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian return true; 42144b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian } 42244b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian return false; 42344b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian} 42444b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian 425e3069e231eeeafeaef6078bc585c82dc6a1830e2Fariborz Jahanianstatic bool rewriteToNSMacroDecl(const EnumDecl *EnumDcl, 426faae53d1cec325140a548c8e9ff647b7edb43702Fariborz Jahanian const TypedefDecl *TypedefDcl, 427e3069e231eeeafeaef6078bc585c82dc6a1830e2Fariborz Jahanian const NSAPI &NS, edit::Commit &commit, 428e3069e231eeeafeaef6078bc585c82dc6a1830e2Fariborz Jahanian bool IsNSIntegerType) { 429e3069e231eeeafeaef6078bc585c82dc6a1830e2Fariborz Jahanian std::string ClassString = 430e3069e231eeeafeaef6078bc585c82dc6a1830e2Fariborz Jahanian IsNSIntegerType ? "NS_ENUM(NSInteger, " : "NS_OPTIONS(NSUInteger, "; 431faae53d1cec325140a548c8e9ff647b7edb43702Fariborz Jahanian ClassString += TypedefDcl->getIdentifier()->getName(); 432faae53d1cec325140a548c8e9ff647b7edb43702Fariborz Jahanian ClassString += ')'; 433faae53d1cec325140a548c8e9ff647b7edb43702Fariborz Jahanian SourceRange R(EnumDcl->getLocStart(), EnumDcl->getLocStart()); 434faae53d1cec325140a548c8e9ff647b7edb43702Fariborz Jahanian commit.replace(R, ClassString); 435faae53d1cec325140a548c8e9ff647b7edb43702Fariborz Jahanian SourceLocation TypedefLoc = TypedefDcl->getLocEnd(); 436faae53d1cec325140a548c8e9ff647b7edb43702Fariborz Jahanian commit.remove(SourceRange(TypedefLoc, TypedefLoc)); 437faae53d1cec325140a548c8e9ff647b7edb43702Fariborz Jahanian return true; 438faae53d1cec325140a548c8e9ff647b7edb43702Fariborz Jahanian} 439faae53d1cec325140a548c8e9ff647b7edb43702Fariborz Jahanian 440e3069e231eeeafeaef6078bc585c82dc6a1830e2Fariborz Jahanianstatic bool UseNSOptionsMacro(ASTContext &Ctx, 441e3069e231eeeafeaef6078bc585c82dc6a1830e2Fariborz Jahanian const EnumDecl *EnumDcl) { 442e3069e231eeeafeaef6078bc585c82dc6a1830e2Fariborz Jahanian bool PowerOfTwo = true; 443e3069e231eeeafeaef6078bc585c82dc6a1830e2Fariborz Jahanian for (EnumDecl::enumerator_iterator EI = EnumDcl->enumerator_begin(), 444e3069e231eeeafeaef6078bc585c82dc6a1830e2Fariborz Jahanian EE = EnumDcl->enumerator_end(); EI != EE; ++EI) { 445e3069e231eeeafeaef6078bc585c82dc6a1830e2Fariborz Jahanian EnumConstantDecl *Enumerator = (*EI); 446e3069e231eeeafeaef6078bc585c82dc6a1830e2Fariborz Jahanian const Expr *InitExpr = Enumerator->getInitExpr(); 447e3069e231eeeafeaef6078bc585c82dc6a1830e2Fariborz Jahanian if (!InitExpr) { 448e3069e231eeeafeaef6078bc585c82dc6a1830e2Fariborz Jahanian PowerOfTwo = false; 449e3069e231eeeafeaef6078bc585c82dc6a1830e2Fariborz Jahanian continue; 450e3069e231eeeafeaef6078bc585c82dc6a1830e2Fariborz Jahanian } 451e3069e231eeeafeaef6078bc585c82dc6a1830e2Fariborz Jahanian InitExpr = InitExpr->IgnoreImpCasts(); 452e3069e231eeeafeaef6078bc585c82dc6a1830e2Fariborz Jahanian if (const BinaryOperator *BO = dyn_cast<BinaryOperator>(InitExpr)) 453e3069e231eeeafeaef6078bc585c82dc6a1830e2Fariborz Jahanian if (BO->isShiftOp() || BO->isBitwiseOp()) 454e3069e231eeeafeaef6078bc585c82dc6a1830e2Fariborz Jahanian return true; 455e3069e231eeeafeaef6078bc585c82dc6a1830e2Fariborz Jahanian 456e3069e231eeeafeaef6078bc585c82dc6a1830e2Fariborz Jahanian uint64_t EnumVal = Enumerator->getInitVal().getZExtValue(); 457e3069e231eeeafeaef6078bc585c82dc6a1830e2Fariborz Jahanian if (PowerOfTwo && EnumVal && !llvm::isPowerOf2_64(EnumVal)) 458e3069e231eeeafeaef6078bc585c82dc6a1830e2Fariborz Jahanian PowerOfTwo = false; 459e3069e231eeeafeaef6078bc585c82dc6a1830e2Fariborz Jahanian } 460e3069e231eeeafeaef6078bc585c82dc6a1830e2Fariborz Jahanian return PowerOfTwo; 461e3069e231eeeafeaef6078bc585c82dc6a1830e2Fariborz Jahanian} 462e3069e231eeeafeaef6078bc585c82dc6a1830e2Fariborz Jahanian 46372685630b693c0ba6050875128ff6bb18107ba2fFariborz Jahanianvoid ObjCMigrateASTConsumer::migrateProtocolConformance(ASTContext &Ctx, 4647556853c60f3e2a3f43864d8ebe74ba5ac11e68eFariborz Jahanian const ObjCImplementationDecl *ImpDecl) { 4657556853c60f3e2a3f43864d8ebe74ba5ac11e68eFariborz Jahanian const ObjCInterfaceDecl *IDecl = ImpDecl->getClassInterface(); 4667556853c60f3e2a3f43864d8ebe74ba5ac11e68eFariborz Jahanian if (!IDecl || ObjCProtocolDecls.empty()) 4677556853c60f3e2a3f43864d8ebe74ba5ac11e68eFariborz Jahanian return; 4687556853c60f3e2a3f43864d8ebe74ba5ac11e68eFariborz Jahanian // Find all implicit conforming protocols for this class 4697556853c60f3e2a3f43864d8ebe74ba5ac11e68eFariborz Jahanian // and make them explicit. 4707556853c60f3e2a3f43864d8ebe74ba5ac11e68eFariborz Jahanian llvm::SmallPtrSet<ObjCProtocolDecl *, 8> ExplicitProtocols; 4717556853c60f3e2a3f43864d8ebe74ba5ac11e68eFariborz Jahanian Ctx.CollectInheritedProtocols(IDecl, ExplicitProtocols); 472e99b37c8f271814ba63046bbde9af0c68e7a26c9Fariborz Jahanian llvm::SmallVector<ObjCProtocolDecl *, 8> PotentialImplicitProtocols; 4737556853c60f3e2a3f43864d8ebe74ba5ac11e68eFariborz Jahanian 474e99b37c8f271814ba63046bbde9af0c68e7a26c9Fariborz Jahanian for (llvm::SmallPtrSet<ObjCProtocolDecl*, 32>::iterator I = 4757556853c60f3e2a3f43864d8ebe74ba5ac11e68eFariborz Jahanian ObjCProtocolDecls.begin(), 4767556853c60f3e2a3f43864d8ebe74ba5ac11e68eFariborz Jahanian E = ObjCProtocolDecls.end(); I != E; ++I) 4777556853c60f3e2a3f43864d8ebe74ba5ac11e68eFariborz Jahanian if (!ExplicitProtocols.count(*I)) 478e99b37c8f271814ba63046bbde9af0c68e7a26c9Fariborz Jahanian PotentialImplicitProtocols.push_back(*I); 4797556853c60f3e2a3f43864d8ebe74ba5ac11e68eFariborz Jahanian 4807556853c60f3e2a3f43864d8ebe74ba5ac11e68eFariborz Jahanian if (PotentialImplicitProtocols.empty()) 4817556853c60f3e2a3f43864d8ebe74ba5ac11e68eFariborz Jahanian return; 482e99b37c8f271814ba63046bbde9af0c68e7a26c9Fariborz Jahanian 483e99b37c8f271814ba63046bbde9af0c68e7a26c9Fariborz Jahanian // go through list of non-optional methods and properties in each protocol 484e99b37c8f271814ba63046bbde9af0c68e7a26c9Fariborz Jahanian // in the PotentialImplicitProtocols list. If class implements every one of the 485e99b37c8f271814ba63046bbde9af0c68e7a26c9Fariborz Jahanian // methods and properties, then this class conforms to this protocol. 486e99b37c8f271814ba63046bbde9af0c68e7a26c9Fariborz Jahanian llvm::SmallVector<ObjCProtocolDecl*, 8> ConformingProtocols; 487e99b37c8f271814ba63046bbde9af0c68e7a26c9Fariborz Jahanian for (unsigned i = 0, e = PotentialImplicitProtocols.size(); i != e; i++) 488ad4aaf11897cc5e9d443b0a80114daacf385f6dfFariborz Jahanian if (ClassImplementsAllMethodsAndProperties(Ctx, ImpDecl, IDecl, 489e99b37c8f271814ba63046bbde9af0c68e7a26c9Fariborz Jahanian PotentialImplicitProtocols[i])) 490e99b37c8f271814ba63046bbde9af0c68e7a26c9Fariborz Jahanian ConformingProtocols.push_back(PotentialImplicitProtocols[i]); 4918c355831ac3c9e8c12b23ca69b7587dcbd0439efFariborz Jahanian 4928c355831ac3c9e8c12b23ca69b7587dcbd0439efFariborz Jahanian if (ConformingProtocols.empty()) 4938c355831ac3c9e8c12b23ca69b7587dcbd0439efFariborz Jahanian return; 494e8280188f7245e479418a716c3959f66b48ef64aFariborz Jahanian 495e8280188f7245e479418a716c3959f66b48ef64aFariborz Jahanian // Further reduce number of conforming protocols. If protocol P1 is in the list 496e8280188f7245e479418a716c3959f66b48ef64aFariborz Jahanian // protocol P2 (P2<P1>), No need to include P1. 497e8280188f7245e479418a716c3959f66b48ef64aFariborz Jahanian llvm::SmallVector<ObjCProtocolDecl*, 8> MinimalConformingProtocols; 498e8280188f7245e479418a716c3959f66b48ef64aFariborz Jahanian for (unsigned i = 0, e = ConformingProtocols.size(); i != e; i++) { 499e8280188f7245e479418a716c3959f66b48ef64aFariborz Jahanian bool DropIt = false; 500e8280188f7245e479418a716c3959f66b48ef64aFariborz Jahanian ObjCProtocolDecl *TargetPDecl = ConformingProtocols[i]; 501e8280188f7245e479418a716c3959f66b48ef64aFariborz Jahanian for (unsigned i1 = 0, e1 = ConformingProtocols.size(); i1 != e1; i1++) { 502e8280188f7245e479418a716c3959f66b48ef64aFariborz Jahanian ObjCProtocolDecl *PDecl = ConformingProtocols[i1]; 503e8280188f7245e479418a716c3959f66b48ef64aFariborz Jahanian if (PDecl == TargetPDecl) 504e8280188f7245e479418a716c3959f66b48ef64aFariborz Jahanian continue; 505e8280188f7245e479418a716c3959f66b48ef64aFariborz Jahanian if (PDecl->lookupProtocolNamed( 506e8280188f7245e479418a716c3959f66b48ef64aFariborz Jahanian TargetPDecl->getDeclName().getAsIdentifierInfo())) { 507e8280188f7245e479418a716c3959f66b48ef64aFariborz Jahanian DropIt = true; 508e8280188f7245e479418a716c3959f66b48ef64aFariborz Jahanian break; 509e8280188f7245e479418a716c3959f66b48ef64aFariborz Jahanian } 510e8280188f7245e479418a716c3959f66b48ef64aFariborz Jahanian } 511e8280188f7245e479418a716c3959f66b48ef64aFariborz Jahanian if (!DropIt) 512e8280188f7245e479418a716c3959f66b48ef64aFariborz Jahanian MinimalConformingProtocols.push_back(TargetPDecl); 513e8280188f7245e479418a716c3959f66b48ef64aFariborz Jahanian } 5148c355831ac3c9e8c12b23ca69b7587dcbd0439efFariborz Jahanian edit::Commit commit(*Editor); 51544b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian rewriteToObjCInterfaceDecl(IDecl, MinimalConformingProtocols, 51644b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian *NSAPIObj, commit); 5178c355831ac3c9e8c12b23ca69b7587dcbd0439efFariborz Jahanian Editor->commit(commit); 5187556853c60f3e2a3f43864d8ebe74ba5ac11e68eFariborz Jahanian} 5197556853c60f3e2a3f43864d8ebe74ba5ac11e68eFariborz Jahanian 520bbbb0fe4f466d3163fcbf0a64ebf0f5868833efbFariborz Jahanianvoid ObjCMigrateASTConsumer::migrateNSEnumDecl(ASTContext &Ctx, 521bbbb0fe4f466d3163fcbf0a64ebf0f5868833efbFariborz Jahanian const EnumDecl *EnumDcl, 522bbbb0fe4f466d3163fcbf0a64ebf0f5868833efbFariborz Jahanian const TypedefDecl *TypedefDcl) { 523bbbb0fe4f466d3163fcbf0a64ebf0f5868833efbFariborz Jahanian if (!EnumDcl->isCompleteDefinition() || EnumDcl->getIdentifier() || 524bbbb0fe4f466d3163fcbf0a64ebf0f5868833efbFariborz Jahanian !TypedefDcl->getIdentifier()) 525bbbb0fe4f466d3163fcbf0a64ebf0f5868833efbFariborz Jahanian return; 526bbbb0fe4f466d3163fcbf0a64ebf0f5868833efbFariborz Jahanian 527bbbb0fe4f466d3163fcbf0a64ebf0f5868833efbFariborz Jahanian QualType qt = TypedefDcl->getTypeSourceInfo()->getType(); 5289f9e54390c255587b009d912007b139432ab7bdcFariborz Jahanian bool IsNSIntegerType = NSAPIObj->isObjCNSIntegerType(qt); 5299f9e54390c255587b009d912007b139432ab7bdcFariborz Jahanian bool IsNSUIntegerType = !IsNSIntegerType && NSAPIObj->isObjCNSUIntegerType(qt); 530e3069e231eeeafeaef6078bc585c82dc6a1830e2Fariborz Jahanian 531faae53d1cec325140a548c8e9ff647b7edb43702Fariborz Jahanian if (!IsNSIntegerType && !IsNSUIntegerType) { 532faae53d1cec325140a548c8e9ff647b7edb43702Fariborz Jahanian // Also check for typedef enum {...} TD; 533faae53d1cec325140a548c8e9ff647b7edb43702Fariborz Jahanian if (const EnumType *EnumTy = qt->getAs<EnumType>()) { 534faae53d1cec325140a548c8e9ff647b7edb43702Fariborz Jahanian if (EnumTy->getDecl() == EnumDcl) { 535e3069e231eeeafeaef6078bc585c82dc6a1830e2Fariborz Jahanian bool NSOptions = UseNSOptionsMacro(Ctx, EnumDcl); 536e3069e231eeeafeaef6078bc585c82dc6a1830e2Fariborz Jahanian if (NSOptions) { 537e3069e231eeeafeaef6078bc585c82dc6a1830e2Fariborz Jahanian if (!Ctx.Idents.get("NS_OPTIONS").hasMacroDefinition()) 538e3069e231eeeafeaef6078bc585c82dc6a1830e2Fariborz Jahanian return; 539e3069e231eeeafeaef6078bc585c82dc6a1830e2Fariborz Jahanian } 540e3069e231eeeafeaef6078bc585c82dc6a1830e2Fariborz Jahanian else if (!Ctx.Idents.get("NS_ENUM").hasMacroDefinition()) 541faae53d1cec325140a548c8e9ff647b7edb43702Fariborz Jahanian return; 542faae53d1cec325140a548c8e9ff647b7edb43702Fariborz Jahanian edit::Commit commit(*Editor); 543e3069e231eeeafeaef6078bc585c82dc6a1830e2Fariborz Jahanian rewriteToNSMacroDecl(EnumDcl, TypedefDcl, *NSAPIObj, commit, !NSOptions); 544faae53d1cec325140a548c8e9ff647b7edb43702Fariborz Jahanian Editor->commit(commit); 545faae53d1cec325140a548c8e9ff647b7edb43702Fariborz Jahanian } 546faae53d1cec325140a548c8e9ff647b7edb43702Fariborz Jahanian } 547e3069e231eeeafeaef6078bc585c82dc6a1830e2Fariborz Jahanian return; 548e3069e231eeeafeaef6078bc585c82dc6a1830e2Fariborz Jahanian } 549e3069e231eeeafeaef6078bc585c82dc6a1830e2Fariborz Jahanian if (IsNSIntegerType && UseNSOptionsMacro(Ctx, EnumDcl)) { 550e3069e231eeeafeaef6078bc585c82dc6a1830e2Fariborz Jahanian // We may still use NS_OPTIONS based on what we find in the enumertor list. 551e3069e231eeeafeaef6078bc585c82dc6a1830e2Fariborz Jahanian IsNSIntegerType = false; 552e3069e231eeeafeaef6078bc585c82dc6a1830e2Fariborz Jahanian IsNSUIntegerType = true; 553faae53d1cec325140a548c8e9ff647b7edb43702Fariborz Jahanian } 554bbbb0fe4f466d3163fcbf0a64ebf0f5868833efbFariborz Jahanian 555bbbb0fe4f466d3163fcbf0a64ebf0f5868833efbFariborz Jahanian // NS_ENUM must be available. 5569f9e54390c255587b009d912007b139432ab7bdcFariborz Jahanian if (IsNSIntegerType && !Ctx.Idents.get("NS_ENUM").hasMacroDefinition()) 5579f9e54390c255587b009d912007b139432ab7bdcFariborz Jahanian return; 5589f9e54390c255587b009d912007b139432ab7bdcFariborz Jahanian // NS_OPTIONS must be available. 5599f9e54390c255587b009d912007b139432ab7bdcFariborz Jahanian if (IsNSUIntegerType && !Ctx.Idents.get("NS_OPTIONS").hasMacroDefinition()) 560bbbb0fe4f466d3163fcbf0a64ebf0f5868833efbFariborz Jahanian return; 561bbbb0fe4f466d3163fcbf0a64ebf0f5868833efbFariborz Jahanian edit::Commit commit(*Editor); 5629f9e54390c255587b009d912007b139432ab7bdcFariborz Jahanian rewriteToNSEnumDecl(EnumDcl, TypedefDcl, *NSAPIObj, commit, IsNSIntegerType); 563bbbb0fe4f466d3163fcbf0a64ebf0f5868833efbFariborz Jahanian Editor->commit(commit); 564bbbb0fe4f466d3163fcbf0a64ebf0f5868833efbFariborz Jahanian} 565bbbb0fe4f466d3163fcbf0a64ebf0f5868833efbFariborz Jahanian 566f647b69147c6e640bbccf501783fafc495bbefb2Fariborz Jahanianstatic void ReplaceWithInstancetype(const ObjCMigrateASTConsumer &ASTC, 567f647b69147c6e640bbccf501783fafc495bbefb2Fariborz Jahanian ObjCMethodDecl *OM) { 568f647b69147c6e640bbccf501783fafc495bbefb2Fariborz Jahanian SourceRange R; 569f647b69147c6e640bbccf501783fafc495bbefb2Fariborz Jahanian std::string ClassString; 570f647b69147c6e640bbccf501783fafc495bbefb2Fariborz Jahanian if (TypeSourceInfo *TSInfo = OM->getResultTypeSourceInfo()) { 571f647b69147c6e640bbccf501783fafc495bbefb2Fariborz Jahanian TypeLoc TL = TSInfo->getTypeLoc(); 572f647b69147c6e640bbccf501783fafc495bbefb2Fariborz Jahanian R = SourceRange(TL.getBeginLoc(), TL.getEndLoc()); 573f647b69147c6e640bbccf501783fafc495bbefb2Fariborz Jahanian ClassString = "instancetype"; 574f647b69147c6e640bbccf501783fafc495bbefb2Fariborz Jahanian } 575f647b69147c6e640bbccf501783fafc495bbefb2Fariborz Jahanian else { 576f647b69147c6e640bbccf501783fafc495bbefb2Fariborz Jahanian R = SourceRange(OM->getLocStart(), OM->getLocStart()); 577f647b69147c6e640bbccf501783fafc495bbefb2Fariborz Jahanian ClassString = OM->isInstanceMethod() ? '-' : '+'; 578f647b69147c6e640bbccf501783fafc495bbefb2Fariborz Jahanian ClassString += " (instancetype)"; 579f647b69147c6e640bbccf501783fafc495bbefb2Fariborz Jahanian } 580f647b69147c6e640bbccf501783fafc495bbefb2Fariborz Jahanian edit::Commit commit(*ASTC.Editor); 581f647b69147c6e640bbccf501783fafc495bbefb2Fariborz Jahanian commit.replace(R, ClassString); 582f647b69147c6e640bbccf501783fafc495bbefb2Fariborz Jahanian ASTC.Editor->commit(commit); 583f647b69147c6e640bbccf501783fafc495bbefb2Fariborz Jahanian} 584f647b69147c6e640bbccf501783fafc495bbefb2Fariborz Jahanian 58526cf046ff3a2d24ff3e2c3757599976b644a06daFariborz Jahanianvoid ObjCMigrateASTConsumer::migrateMethodInstanceType(ASTContext &Ctx, 58626cf046ff3a2d24ff3e2c3757599976b644a06daFariborz Jahanian ObjCContainerDecl *CDecl, 58726cf046ff3a2d24ff3e2c3757599976b644a06daFariborz Jahanian ObjCMethodDecl *OM) { 58811638f7b922aa0182ab2028ec819001ed2fe8085Fariborz Jahanian ObjCInstanceTypeFamily OIT_Family = 58911638f7b922aa0182ab2028ec819001ed2fe8085Fariborz Jahanian Selector::getInstTypeMethodFamily(OM->getSelector()); 5908d3794e06a63578093bd71c3c2520bd01e6197a3Fariborz Jahanian 59165f1a4c931bc17e51c751a5e9c6a71a9e52d5b8cFariborz Jahanian std::string ClassName; 592211b4a2b2260ba5a3150f2b8d47f569e9773b1d3Fariborz Jahanian switch (OIT_Family) { 5938d3794e06a63578093bd71c3c2520bd01e6197a3Fariborz Jahanian case OIT_None: 5948d3794e06a63578093bd71c3c2520bd01e6197a3Fariborz Jahanian migrateFactoryMethod(Ctx, CDecl, OM); 5958d3794e06a63578093bd71c3c2520bd01e6197a3Fariborz Jahanian return; 596211b4a2b2260ba5a3150f2b8d47f569e9773b1d3Fariborz Jahanian case OIT_Array: 59765f1a4c931bc17e51c751a5e9c6a71a9e52d5b8cFariborz Jahanian ClassName = "NSArray"; 598211b4a2b2260ba5a3150f2b8d47f569e9773b1d3Fariborz Jahanian break; 599211b4a2b2260ba5a3150f2b8d47f569e9773b1d3Fariborz Jahanian case OIT_Dictionary: 60065f1a4c931bc17e51c751a5e9c6a71a9e52d5b8cFariborz Jahanian ClassName = "NSDictionary"; 60165f1a4c931bc17e51c751a5e9c6a71a9e52d5b8cFariborz Jahanian break; 60265f1a4c931bc17e51c751a5e9c6a71a9e52d5b8cFariborz Jahanian case OIT_MemManage: 60365f1a4c931bc17e51c751a5e9c6a71a9e52d5b8cFariborz Jahanian ClassName = "NSObject"; 604211b4a2b2260ba5a3150f2b8d47f569e9773b1d3Fariborz Jahanian break; 6058d3794e06a63578093bd71c3c2520bd01e6197a3Fariborz Jahanian case OIT_Singleton: 6068d3794e06a63578093bd71c3c2520bd01e6197a3Fariborz Jahanian migrateFactoryMethod(Ctx, CDecl, OM, OIT_Singleton); 607211b4a2b2260ba5a3150f2b8d47f569e9773b1d3Fariborz Jahanian return; 608211b4a2b2260ba5a3150f2b8d47f569e9773b1d3Fariborz Jahanian } 60911638f7b922aa0182ab2028ec819001ed2fe8085Fariborz Jahanian if (!OM->getResultType()->isObjCIdType()) 61011638f7b922aa0182ab2028ec819001ed2fe8085Fariborz Jahanian return; 61111638f7b922aa0182ab2028ec819001ed2fe8085Fariborz Jahanian 61211638f7b922aa0182ab2028ec819001ed2fe8085Fariborz Jahanian ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(CDecl); 61311638f7b922aa0182ab2028ec819001ed2fe8085Fariborz Jahanian if (!IDecl) { 61411638f7b922aa0182ab2028ec819001ed2fe8085Fariborz Jahanian if (ObjCCategoryDecl *CatDecl = dyn_cast<ObjCCategoryDecl>(CDecl)) 61511638f7b922aa0182ab2028ec819001ed2fe8085Fariborz Jahanian IDecl = CatDecl->getClassInterface(); 61611638f7b922aa0182ab2028ec819001ed2fe8085Fariborz Jahanian else if (ObjCImplDecl *ImpDecl = dyn_cast<ObjCImplDecl>(CDecl)) 61711638f7b922aa0182ab2028ec819001ed2fe8085Fariborz Jahanian IDecl = ImpDecl->getClassInterface(); 61811638f7b922aa0182ab2028ec819001ed2fe8085Fariborz Jahanian } 61965f1a4c931bc17e51c751a5e9c6a71a9e52d5b8cFariborz Jahanian if (!IDecl || 620f647b69147c6e640bbccf501783fafc495bbefb2Fariborz Jahanian !IDecl->lookupInheritedClass(&Ctx.Idents.get(ClassName))) { 621f647b69147c6e640bbccf501783fafc495bbefb2Fariborz Jahanian migrateFactoryMethod(Ctx, CDecl, OM); 62211638f7b922aa0182ab2028ec819001ed2fe8085Fariborz Jahanian return; 623cd683986e991f0e60afd6bc6f336cfc1fd844193Rafael Espindola } 624f647b69147c6e640bbccf501783fafc495bbefb2Fariborz Jahanian ReplaceWithInstancetype(*this, OM); 62511638f7b922aa0182ab2028ec819001ed2fe8085Fariborz Jahanian} 62611638f7b922aa0182ab2028ec819001ed2fe8085Fariborz Jahanian 62711638f7b922aa0182ab2028ec819001ed2fe8085Fariborz Jahanianvoid ObjCMigrateASTConsumer::migrateInstanceType(ASTContext &Ctx, 62811638f7b922aa0182ab2028ec819001ed2fe8085Fariborz Jahanian ObjCContainerDecl *CDecl) { 62911638f7b922aa0182ab2028ec819001ed2fe8085Fariborz Jahanian // migrate methods which can have instancetype as their result type. 63011638f7b922aa0182ab2028ec819001ed2fe8085Fariborz Jahanian for (ObjCContainerDecl::method_iterator M = CDecl->meth_begin(), 63111638f7b922aa0182ab2028ec819001ed2fe8085Fariborz Jahanian MEnd = CDecl->meth_end(); 63211638f7b922aa0182ab2028ec819001ed2fe8085Fariborz Jahanian M != MEnd; ++M) { 63311638f7b922aa0182ab2028ec819001ed2fe8085Fariborz Jahanian ObjCMethodDecl *Method = (*M); 63411638f7b922aa0182ab2028ec819001ed2fe8085Fariborz Jahanian migrateMethodInstanceType(Ctx, CDecl, Method); 63511638f7b922aa0182ab2028ec819001ed2fe8085Fariborz Jahanian } 63611638f7b922aa0182ab2028ec819001ed2fe8085Fariborz Jahanian} 63711638f7b922aa0182ab2028ec819001ed2fe8085Fariborz Jahanian 638f647b69147c6e640bbccf501783fafc495bbefb2Fariborz Jahanianvoid ObjCMigrateASTConsumer::migrateFactoryMethod(ASTContext &Ctx, 639f647b69147c6e640bbccf501783fafc495bbefb2Fariborz Jahanian ObjCContainerDecl *CDecl, 6408d3794e06a63578093bd71c3c2520bd01e6197a3Fariborz Jahanian ObjCMethodDecl *OM, 6418d3794e06a63578093bd71c3c2520bd01e6197a3Fariborz Jahanian ObjCInstanceTypeFamily OIT_Family) { 642c217ced5ada5c5723bfca450b37ac046193a8c2fFariborz Jahanian if (OM->isInstanceMethod() || 643c217ced5ada5c5723bfca450b37ac046193a8c2fFariborz Jahanian OM->getResultType() == Ctx.getObjCInstanceType() || 644c217ced5ada5c5723bfca450b37ac046193a8c2fFariborz Jahanian !OM->getResultType()->isObjCIdType()) 645f647b69147c6e640bbccf501783fafc495bbefb2Fariborz Jahanian return; 646f647b69147c6e640bbccf501783fafc495bbefb2Fariborz Jahanian 647f647b69147c6e640bbccf501783fafc495bbefb2Fariborz Jahanian // Candidate factory methods are + (id) NaMeXXX : ... which belong to a class 648f647b69147c6e640bbccf501783fafc495bbefb2Fariborz Jahanian // NSYYYNamE with matching names be at least 3 characters long. 649f647b69147c6e640bbccf501783fafc495bbefb2Fariborz Jahanian ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(CDecl); 650f647b69147c6e640bbccf501783fafc495bbefb2Fariborz Jahanian if (!IDecl) { 651f647b69147c6e640bbccf501783fafc495bbefb2Fariborz Jahanian if (ObjCCategoryDecl *CatDecl = dyn_cast<ObjCCategoryDecl>(CDecl)) 652f647b69147c6e640bbccf501783fafc495bbefb2Fariborz Jahanian IDecl = CatDecl->getClassInterface(); 653f647b69147c6e640bbccf501783fafc495bbefb2Fariborz Jahanian else if (ObjCImplDecl *ImpDecl = dyn_cast<ObjCImplDecl>(CDecl)) 654f647b69147c6e640bbccf501783fafc495bbefb2Fariborz Jahanian IDecl = ImpDecl->getClassInterface(); 655f647b69147c6e640bbccf501783fafc495bbefb2Fariborz Jahanian } 656f647b69147c6e640bbccf501783fafc495bbefb2Fariborz Jahanian if (!IDecl) 657f647b69147c6e640bbccf501783fafc495bbefb2Fariborz Jahanian return; 658f647b69147c6e640bbccf501783fafc495bbefb2Fariborz Jahanian 659f647b69147c6e640bbccf501783fafc495bbefb2Fariborz Jahanian std::string StringClassName = IDecl->getName(); 660f647b69147c6e640bbccf501783fafc495bbefb2Fariborz Jahanian StringRef LoweredClassName(StringClassName); 661f647b69147c6e640bbccf501783fafc495bbefb2Fariborz Jahanian std::string StringLoweredClassName = LoweredClassName.lower(); 662f647b69147c6e640bbccf501783fafc495bbefb2Fariborz Jahanian LoweredClassName = StringLoweredClassName; 663f647b69147c6e640bbccf501783fafc495bbefb2Fariborz Jahanian 664f647b69147c6e640bbccf501783fafc495bbefb2Fariborz Jahanian IdentifierInfo *MethodIdName = OM->getSelector().getIdentifierInfoForSlot(0); 665f647b69147c6e640bbccf501783fafc495bbefb2Fariborz Jahanian std::string MethodName = MethodIdName->getName(); 6668d3794e06a63578093bd71c3c2520bd01e6197a3Fariborz Jahanian if (OIT_Family == OIT_Singleton) { 6678d3794e06a63578093bd71c3c2520bd01e6197a3Fariborz Jahanian StringRef STRefMethodName(MethodName); 6688d3794e06a63578093bd71c3c2520bd01e6197a3Fariborz Jahanian size_t len = 0; 6698d3794e06a63578093bd71c3c2520bd01e6197a3Fariborz Jahanian if (STRefMethodName.startswith("standard")) 6708d3794e06a63578093bd71c3c2520bd01e6197a3Fariborz Jahanian len = strlen("standard"); 6718d3794e06a63578093bd71c3c2520bd01e6197a3Fariborz Jahanian else if (STRefMethodName.startswith("shared")) 6728d3794e06a63578093bd71c3c2520bd01e6197a3Fariborz Jahanian len = strlen("shared"); 6738d3794e06a63578093bd71c3c2520bd01e6197a3Fariborz Jahanian else if (STRefMethodName.startswith("default")) 6748d3794e06a63578093bd71c3c2520bd01e6197a3Fariborz Jahanian len = strlen("default"); 6758d3794e06a63578093bd71c3c2520bd01e6197a3Fariborz Jahanian else 6768d3794e06a63578093bd71c3c2520bd01e6197a3Fariborz Jahanian return; 6778d3794e06a63578093bd71c3c2520bd01e6197a3Fariborz Jahanian MethodName = STRefMethodName.substr(len); 6788d3794e06a63578093bd71c3c2520bd01e6197a3Fariborz Jahanian } 679f647b69147c6e640bbccf501783fafc495bbefb2Fariborz Jahanian std::string MethodNameSubStr = MethodName.substr(0, 3); 680f647b69147c6e640bbccf501783fafc495bbefb2Fariborz Jahanian StringRef MethodNamePrefix(MethodNameSubStr); 681f647b69147c6e640bbccf501783fafc495bbefb2Fariborz Jahanian std::string StringLoweredMethodNamePrefix = MethodNamePrefix.lower(); 682f647b69147c6e640bbccf501783fafc495bbefb2Fariborz Jahanian MethodNamePrefix = StringLoweredMethodNamePrefix; 683f647b69147c6e640bbccf501783fafc495bbefb2Fariborz Jahanian size_t Ix = LoweredClassName.rfind(MethodNamePrefix); 684f647b69147c6e640bbccf501783fafc495bbefb2Fariborz Jahanian if (Ix == StringRef::npos) 685f647b69147c6e640bbccf501783fafc495bbefb2Fariborz Jahanian return; 686f647b69147c6e640bbccf501783fafc495bbefb2Fariborz Jahanian std::string ClassNamePostfix = LoweredClassName.substr(Ix); 687f647b69147c6e640bbccf501783fafc495bbefb2Fariborz Jahanian StringRef LoweredMethodName(MethodName); 688f647b69147c6e640bbccf501783fafc495bbefb2Fariborz Jahanian std::string StringLoweredMethodName = LoweredMethodName.lower(); 689f647b69147c6e640bbccf501783fafc495bbefb2Fariborz Jahanian LoweredMethodName = StringLoweredMethodName; 690f647b69147c6e640bbccf501783fafc495bbefb2Fariborz Jahanian if (!LoweredMethodName.startswith(ClassNamePostfix)) 691f647b69147c6e640bbccf501783fafc495bbefb2Fariborz Jahanian return; 692f647b69147c6e640bbccf501783fafc495bbefb2Fariborz Jahanian ReplaceWithInstancetype(*this, OM); 693f647b69147c6e640bbccf501783fafc495bbefb2Fariborz Jahanian} 694f647b69147c6e640bbccf501783fafc495bbefb2Fariborz Jahanian 69530660a898545416f0fea2d717f16f75640001e38Ted Kremeneknamespace { 69630660a898545416f0fea2d717f16f75640001e38Ted Kremenek 69730660a898545416f0fea2d717f16f75640001e38Ted Kremenekclass RewritesReceiver : public edit::EditsReceiver { 69830660a898545416f0fea2d717f16f75640001e38Ted Kremenek Rewriter &Rewrite; 69930660a898545416f0fea2d717f16f75640001e38Ted Kremenek 70030660a898545416f0fea2d717f16f75640001e38Ted Kremenekpublic: 70130660a898545416f0fea2d717f16f75640001e38Ted Kremenek RewritesReceiver(Rewriter &Rewrite) : Rewrite(Rewrite) { } 70230660a898545416f0fea2d717f16f75640001e38Ted Kremenek 70330660a898545416f0fea2d717f16f75640001e38Ted Kremenek virtual void insert(SourceLocation loc, StringRef text) { 70430660a898545416f0fea2d717f16f75640001e38Ted Kremenek Rewrite.InsertText(loc, text); 70530660a898545416f0fea2d717f16f75640001e38Ted Kremenek } 70630660a898545416f0fea2d717f16f75640001e38Ted Kremenek virtual void replace(CharSourceRange range, StringRef text) { 70730660a898545416f0fea2d717f16f75640001e38Ted Kremenek Rewrite.ReplaceText(range.getBegin(), Rewrite.getRangeSize(range), text); 70830660a898545416f0fea2d717f16f75640001e38Ted Kremenek } 70930660a898545416f0fea2d717f16f75640001e38Ted Kremenek}; 71030660a898545416f0fea2d717f16f75640001e38Ted Kremenek 71130660a898545416f0fea2d717f16f75640001e38Ted Kremenek} 71230660a898545416f0fea2d717f16f75640001e38Ted Kremenek 71330660a898545416f0fea2d717f16f75640001e38Ted Kremenekvoid ObjCMigrateASTConsumer::HandleTranslationUnit(ASTContext &Ctx) { 714baf15574ebe70871b4682cdd5a87028bad1c9f6fFariborz Jahanian 715baf15574ebe70871b4682cdd5a87028bad1c9f6fFariborz Jahanian TranslationUnitDecl *TU = Ctx.getTranslationUnitDecl(); 716d412999a3da6387dbfaf00f7647132082e94310eFariborz Jahanian if (MigrateProperty) 717d412999a3da6387dbfaf00f7647132082e94310eFariborz Jahanian for (DeclContext::decl_iterator D = TU->decls_begin(), DEnd = TU->decls_end(); 718d412999a3da6387dbfaf00f7647132082e94310eFariborz Jahanian D != DEnd; ++D) { 719d412999a3da6387dbfaf00f7647132082e94310eFariborz Jahanian if (ObjCInterfaceDecl *CDecl = dyn_cast<ObjCInterfaceDecl>(*D)) 720d412999a3da6387dbfaf00f7647132082e94310eFariborz Jahanian migrateObjCInterfaceDecl(Ctx, CDecl); 7217556853c60f3e2a3f43864d8ebe74ba5ac11e68eFariborz Jahanian else if (ObjCProtocolDecl *PDecl = dyn_cast<ObjCProtocolDecl>(*D)) 7227556853c60f3e2a3f43864d8ebe74ba5ac11e68eFariborz Jahanian ObjCProtocolDecls.insert(PDecl); 7237556853c60f3e2a3f43864d8ebe74ba5ac11e68eFariborz Jahanian else if (const ObjCImplementationDecl *ImpDecl = 7247556853c60f3e2a3f43864d8ebe74ba5ac11e68eFariborz Jahanian dyn_cast<ObjCImplementationDecl>(*D)) 7257556853c60f3e2a3f43864d8ebe74ba5ac11e68eFariborz Jahanian migrateProtocolConformance(Ctx, ImpDecl); 726bbbb0fe4f466d3163fcbf0a64ebf0f5868833efbFariborz Jahanian else if (const EnumDecl *ED = dyn_cast<EnumDecl>(*D)) { 727bbbb0fe4f466d3163fcbf0a64ebf0f5868833efbFariborz Jahanian DeclContext::decl_iterator N = D; 728bbbb0fe4f466d3163fcbf0a64ebf0f5868833efbFariborz Jahanian ++N; 72972685630b693c0ba6050875128ff6bb18107ba2fFariborz Jahanian if (N != DEnd) 73072685630b693c0ba6050875128ff6bb18107ba2fFariborz Jahanian if (const TypedefDecl *TD = dyn_cast<TypedefDecl>(*N)) 73172685630b693c0ba6050875128ff6bb18107ba2fFariborz Jahanian migrateNSEnumDecl(Ctx, ED, TD); 732bbbb0fe4f466d3163fcbf0a64ebf0f5868833efbFariborz Jahanian } 73311638f7b922aa0182ab2028ec819001ed2fe8085Fariborz Jahanian // migrate methods which can have instancetype as their result type. 73411638f7b922aa0182ab2028ec819001ed2fe8085Fariborz Jahanian if (ObjCContainerDecl *CDecl = dyn_cast<ObjCContainerDecl>(*D)) 73511638f7b922aa0182ab2028ec819001ed2fe8085Fariborz Jahanian migrateInstanceType(Ctx, CDecl); 736d412999a3da6387dbfaf00f7647132082e94310eFariborz Jahanian } 737baf15574ebe70871b4682cdd5a87028bad1c9f6fFariborz Jahanian 7384e4d08403ca5cfd4d558fa2936215d3a4e5a528dDavid Blaikie Rewriter rewriter(Ctx.getSourceManager(), Ctx.getLangOpts()); 73930660a898545416f0fea2d717f16f75640001e38Ted Kremenek RewritesReceiver Rec(rewriter); 74030660a898545416f0fea2d717f16f75640001e38Ted Kremenek Editor->applyRewrites(Rec); 74130660a898545416f0fea2d717f16f75640001e38Ted Kremenek 74230660a898545416f0fea2d717f16f75640001e38Ted Kremenek for (Rewriter::buffer_iterator 74330660a898545416f0fea2d717f16f75640001e38Ted Kremenek I = rewriter.buffer_begin(), E = rewriter.buffer_end(); I != E; ++I) { 74430660a898545416f0fea2d717f16f75640001e38Ted Kremenek FileID FID = I->first; 74530660a898545416f0fea2d717f16f75640001e38Ted Kremenek RewriteBuffer &buf = I->second; 74630660a898545416f0fea2d717f16f75640001e38Ted Kremenek const FileEntry *file = Ctx.getSourceManager().getFileEntryForID(FID); 74730660a898545416f0fea2d717f16f75640001e38Ted Kremenek assert(file); 748cfa88f893915ceb8ae4ce2f17c46c24a4d67502fDmitri Gribenko SmallString<512> newText; 74930660a898545416f0fea2d717f16f75640001e38Ted Kremenek llvm::raw_svector_ostream vecOS(newText); 75030660a898545416f0fea2d717f16f75640001e38Ted Kremenek buf.write(vecOS); 75130660a898545416f0fea2d717f16f75640001e38Ted Kremenek vecOS.flush(); 75230660a898545416f0fea2d717f16f75640001e38Ted Kremenek llvm::MemoryBuffer *memBuf = llvm::MemoryBuffer::getMemBufferCopy( 75330660a898545416f0fea2d717f16f75640001e38Ted Kremenek StringRef(newText.data(), newText.size()), file->getName()); 754cfa88f893915ceb8ae4ce2f17c46c24a4d67502fDmitri Gribenko SmallString<64> filePath(file->getName()); 75530660a898545416f0fea2d717f16f75640001e38Ted Kremenek FileMgr.FixupRelativePath(filePath); 75630660a898545416f0fea2d717f16f75640001e38Ted Kremenek Remapper.remap(filePath.str(), memBuf); 75730660a898545416f0fea2d717f16f75640001e38Ted Kremenek } 75830660a898545416f0fea2d717f16f75640001e38Ted Kremenek 75930660a898545416f0fea2d717f16f75640001e38Ted Kremenek if (IsOutputFile) { 76030660a898545416f0fea2d717f16f75640001e38Ted Kremenek Remapper.flushToFile(MigrateDir, Ctx.getDiagnostics()); 76130660a898545416f0fea2d717f16f75640001e38Ted Kremenek } else { 76230660a898545416f0fea2d717f16f75640001e38Ted Kremenek Remapper.flushToDisk(MigrateDir, Ctx.getDiagnostics()); 76330660a898545416f0fea2d717f16f75640001e38Ted Kremenek } 76430660a898545416f0fea2d717f16f75640001e38Ted Kremenek} 76530660a898545416f0fea2d717f16f75640001e38Ted Kremenek 76630660a898545416f0fea2d717f16f75640001e38Ted Kremenekbool MigrateSourceAction::BeginInvocation(CompilerInstance &CI) { 767013a254a5b85cfb54066e4022649368689c9ab06Argyrios Kyrtzidis CI.getDiagnostics().setIgnoreAllWarnings(true); 76830660a898545416f0fea2d717f16f75640001e38Ted Kremenek return true; 76930660a898545416f0fea2d717f16f75640001e38Ted Kremenek} 77030660a898545416f0fea2d717f16f75640001e38Ted Kremenek 77130660a898545416f0fea2d717f16f75640001e38Ted KremenekASTConsumer *MigrateSourceAction::CreateASTConsumer(CompilerInstance &CI, 77230660a898545416f0fea2d717f16f75640001e38Ted Kremenek StringRef InFile) { 77337ed12720a35b7bfa1c4de73ad6f1c6c1c88ee17Argyrios Kyrtzidis PPConditionalDirectiveRecord * 77437ed12720a35b7bfa1c4de73ad6f1c6c1c88ee17Argyrios Kyrtzidis PPRec = new PPConditionalDirectiveRecord(CI.getSourceManager()); 77537ed12720a35b7bfa1c4de73ad6f1c6c1c88ee17Argyrios Kyrtzidis CI.getPreprocessor().addPPCallbacks(PPRec); 77630660a898545416f0fea2d717f16f75640001e38Ted Kremenek return new ObjCMigrateASTConsumer(CI.getFrontendOpts().OutputFile, 77730660a898545416f0fea2d717f16f75640001e38Ted Kremenek /*MigrateLiterals=*/true, 77830660a898545416f0fea2d717f16f75640001e38Ted Kremenek /*MigrateSubscripting=*/true, 779d412999a3da6387dbfaf00f7647132082e94310eFariborz Jahanian /*MigrateProperty*/true, 78030660a898545416f0fea2d717f16f75640001e38Ted Kremenek Remapper, 78130660a898545416f0fea2d717f16f75640001e38Ted Kremenek CI.getFileManager(), 78237ed12720a35b7bfa1c4de73ad6f1c6c1c88ee17Argyrios Kyrtzidis PPRec, 783baf15574ebe70871b4682cdd5a87028bad1c9f6fFariborz Jahanian CI.getPreprocessor(), 78430660a898545416f0fea2d717f16f75640001e38Ted Kremenek /*isOutputFile=*/true); 78530660a898545416f0fea2d717f16f75640001e38Ted Kremenek} 786